Quantcast
Channel: chalcedony_htnの日記
Viewing all 46 articles
Browse latest View live

[InDesign][JavaScript]InDesignでスクリプトから挿入した索引マーカーの位置がずれる問題

$
0
0

ご無沙汰しております。

長々と前置きはしないことにして

淡々とInDesignの(たぶん)バグ報告します。

InDesignの索引作成時は見出し語の位置にマーカーを入れていくのですが、これをスクリプトからやろうとすると、ある条件下で挿入位置がずれるというバグがあります。JavaScriptとVBScriptで確認。

  • 見出し語と同じストーリー上に表が入っている
  • その表が見出し語より前にある
  • その表が複数行ある(列の数は関係ない模様)

CSまでは起きなかった問題です。CS4では起きるのを確認しました。CS2あたりからおかしくなってきたらしいと聞いたことがありますが、情報元のページが消えててわかんなくなったorz

というわけで実験してみました。InDesign CS5.5、言語はJavaScript、もちろんWindows版です。

f:id:chalcedony_htn:20120627175403p:image

見事にずれてます。実験に使ったスクリプトは以下のもの。

var doc = app.activeDocument;
var idx = (doc.indexes.length>0) ? doc.indexes[0] : doc.indexes.add();
idx.topics.add("見出し語","よみがな").pageReferences.add(app.selection[0]);

文書内の「→←」の間にカーソルを立てては実行、を繰り返すこと7回でさっきの画像の状態になりました。順不同にやっても変わらず。

索引を実際に追加してるのは3行目です。topics.add()で項目を追加し、pageReferences.add()で現在選択してる箇所(挿入点、またはテキスト)を参照先として指定しています。

ちなみに、リファレンス見るかぎりCS2〜CS5.5で動くはずです。CS6はまだ触ったことないです。

これのせいで

外部テキストに用意したリストを読み込んで一発で索引登録できるスクリプト!*1とか、テキスト選択して実行すると読みがなを自動解析して索引に登録するスクリプト!とか、そういうのが作りづらくなってるんで何とかして欲しいです。

しかし、索引って使ってる人少ないのかなあ……。

*1:これはディザInDesignのお〜まちさんが作ってらっしゃいますね。表さえ入ってなければCS5.5でもばっちり便利に使えてます。


[SBM]livedoor ClipがなくなったのでPinboardはじめました

$
0
0

はいこんばんは。

ちょっと前からですが、メインのソーシャルブックマークサービスをPinboardに乗り換えましたはてなのほうは継続利用中です。

これだけで完了するような話ですが、せっかくだからいろいろ書いておきます。

さようならlivedoor Clip

愛用していたソーシャルブックマークサービス「livedoor Clip」がお亡くなりになってしまったので、泣く泣く新しいサービスへ移行しなければならなくなりました。かなしい……

どうやらクリップでなじみの面々の多くははてなブックマークに移行したようなのですが……今までのブックマークを移行して長ったらしいコメントが途中でちょん切れるのは絶対に避けたかったため、他のサービスを探すことに。

ソーシャルな部分はいまとなってはTwitterで十分なところがあるので、機能面を重視して選びました。

具体的に言うとコメント文字数と速度、それからある程度メジャーで今後のサービス継続が期待できるもの。

ブックマーク支援ツール(Firefoxアドオンの「Tombloo」を使用)が対応しているかどうかも大事なところです。あ、あと日本語対応か。

こんにちはPinboard

いろいろ比較した結果、何人かがおすすめしてくれたPinboardに決定。なんとコメント文字数無制限*1なのです。桃源郷はここにあったんやー!

他の機能についてはツアーを参照。

面白いと思ったのは「to read」設定ですね。いわゆる「あとで読む」。このフラグが付けられたブックマークは「未読一覧」みたいな形で一覧表示できて、読み終えたしるしに「mark as read」リンクをクリックするまで非公開になるというものです。

たしかに、読んでみるまではブクマしたことを知られたくないってのはありますし。通常の非公開設定と分けてあるところが、使うシーンをきっちり考えてるなーって思います。まあ個人的には非公開とかまず使わないんですけど。

Pinboardは有料のサービスなのですが、月額とかではなくて1回支払えばOKということでさくっと登録。金額が登録の時期によって(つまりユーザー数が増えて維持費が上がるに従って)だんだん高くなっていくらしくて、それもちょっと面白いと思いました*2

ちなみに

LDC時代のブックマークはエクスポートしてPinboardのほうにぶちこんであります。エクスポートしたXMLをPinboard用に変換するのにえらい苦労したのですが、そのときのメモはうっかり意図的に消したので省略。

なお、ミスって日付情報がすべて吹っ飛んだため、移行した分のエントリはいつのものかさっぱりわからない状態です。細けぇ事はいいんだよ!

*1:システム上の上限はあるでしょうけどね

*2:金額据え置きで無理した結果破綻するよりよっぽどいいと思う

[レポ][InDesign]INDD 2013 Tokyo(spring)に行ってきた(第3セッション感想)

$
0
0

はいこんばんは。

先週の土曜日はInDesignの祭典、INDD 2013 Tokyo (spring)に行ってきました。セミナーのレポートとか最近サボり気味なんですが、今回は自分の業務にダイレクトにつながる内容だったので、せっかくだから俺は赤い扉を選感想など書いてみようと思います。他の2セッションについても書こうと思ったのですが力尽きましたごめんなさい……

感想なので、内容のまとめではありません。内容については当日のTwitterの様子がまとめられたTogetterがあるのでそちらを。

http://togetter.com/li/464817

うわっ……私のpost、多すぎ……?(例の顔で

第3セッション:多ページ作成でのInDesignテクニック

テクニカルドキュメント、いわゆる「トリセツ」を日々制作されている西村さんが、あかねさんを相棒に多ページのドキュメントを大量に処理する場合のテクニックを解説してくれるセッション。

立場や仕事量などもろもろ違いますが、私も主な業務は同じくテクニカルドキュメントの制作です。この種の作業の特徴としては、スライドで挙げられていた

  • ページ数が多い
  • ファイル数も多い
  • レイアウトはシンプル
  • テキストがメイン

に加え、

  • ほかのページへ誘導する記述が大量にある(X章のXを参照、XXページを参照、など)
  • ページ増減が頻繁にある(途中のページに記述がどっさり追加され、以降の改ページ位置などがすべて変わる)
  • 改訂が多く、データが長年引き継がれ続ける
  • 改訂サイクルが早い(ことがある)

などが挙げられると思います。

下版した次の日から改訂作業開始とかざらにあったり。逆に5年も前のデータを掘り起こしたり。最近は時代の流れか紙のトリセツも減りまして、最終的な出力がPDFでWeb掲載だったりすると、数百ページあるのに作業期間は1〜2日とかね。ありますね。

数百ページのドキュメントにちりばめられた「詳しくはXXページを参照してください」って記述を手作業で検索して参照元と引き合わせて違ってたら手で数値打ち直して……とか、ページ増減で内容とずれてしまった柱テキストを目視確認してちまちま修正して……とか、「テキスト修正だからそんなに時間かからないでしょ? PDFだし、できたらすぐちょうだい」、と、か……考えただけでSAN値*1ががりがり削れていきます。

そんな作業をInDesignで(正気を保ちつつ)効率的に行うためには、どんな機能をどう使ったらいいのか? というのが今回のセッション。

その内容ですが……いやー、濃かったですね! ものっすごいボリューム。

  • テキスト変数
  • 箇条書き
  • 相互参照
  • アンカー付きオブジェクト
  • ブック
  • 目次
  • 索引
  • (条件テキスト)

まさに普段業務で使っている機能ばかりで嬉しくなってしまいました。

逆に、初めて「この機能ってこういう時に使うのか」と知った人もいるんじゃないでしょうか? Adobeのヘルプではそれぞれ別の箇所に記述されていて、こんなふうに逆引き的に関連付けてまとまってはいないんですよね。機能の存在と概要を知らないと調べようがない。そもそも自動番号が箇条書きってどういうことなの……とかね。

セッションでは、取り上げたそれぞれの機能について、何がどう効率化できるのか、どう設定したら使えるのか、使うときの注意点は何か、を丁寧に説明していました。

この「注意点」のところが実はセッションの目玉だったんじゃないかと。ものすごく実践的で、「あるある!!」と何度も何度もうなずきながら聞いてたり、もちろん初めて知るものもたくさんあったり。単なる機能紹介や公式のヘルプでは絶対出てこないですよね、箇条書きの自動番号で51番目以降は丸数字が使えないとかw

設定方法についても、普段使ってる部分以外はあいまいにしか理解していなかったのできっちり復習できました。索引の参照形式とか、アンカー付きオブジェクトの位置オプションとか。後者はスライドで視覚的にまとめられていてわかりやすかったです。今まで回りくどいやり方をしていなかったか、チェックしてみるいい機会になりました。


実を言えば、これらの機能は日々使っているものの、他の環境ではどんなふうに使われているんだろう……といつも思っていたんですよね。よそで制作したデータを見ることが一切ないので。Webで検索してみても、実践的な内容はなかなか出てこないですし。

もっと効率的なやり方があるのではないか? むしろ根本的に機能を勘違いしていたりしないか? と不安を抱いていたのですが、今回ピンポイントでテクニカルドキュメントの例を見ることができ、おおむね方向性は間違っていないとわかって心底ほっとしました。そのテンションの結果があのpost数だよ*2


改めて今回紹介されていた機能を俯瞰してみると、何をおいてもまずは「ドキュメントを(データ上で)構造化すること」がはじめの一歩になるんだなあと思います。変数、相互参照、箇条書き、目次などなど、「テキストに適切なスタイルが設定されている」からこそ使えるんですよね。

逆にこれらの機能をフルに使いたいなら、それを前提にしたスタイルの設計をする、というのも必要になってくると思います。「見出しだから文字を大きくする段落スタイルを付けよう」ではなくて、「見出しとして使いたい段落だから見出しという段落スタイルを付けて、見た目でも見出しとわかるように文字を大きくしよう」という感じ。

データを構造化しておくと、さらに進んだ自動処理(たとえばスクリプトを使うとか)をしやすくなったり、Eなんとか形式にするときにもたぶん比較的スムーズだったりと、メリットは多いと思います。


あとひとつ、大事だと思ったのは、最後のまとめにあった「自動だからと安心しないでチェックは必ずしよう」です。

各機能の注意点を見返してみるとわかりますが、自動更新されたりされなかったり、テキスト量によってオブジェクトが重なってしまったり、自動挿入されるテキストが手動で修正できてしまったりと、落とし穴も結構あります。相互参照まわりとかちょいちょい怪しいし*3

自分の仕事では、修正作業に時間がかからない分、チェックは念入りに……というつもりでやっています。

終了まぎわに西村さんがぽそっと言ってた、「あくまで入力支援ですからね」という言葉を肝に銘じておきたいですね。

というわけで

InDesignかわいいよInDesign

横見出し機能搭載はよ

貴重な話を聞かせていただいてありがとうございました! 姐さん、よければ次は条件テキストも教えてください!

*1:正気度

*2:参照元と参照先を間違えてるところがあって赤面

*3:相互参照、便利でかわいいやつだけどダメなところもたくさん知ってます。こちらのBlogに詳しいです→ InDesignerの悪あがき ブログ内検索で「相互参照」を検索するといろいろ出てきます。

[Windows]なんとなく、使っているツール(フリーウェア)を晒してみる

$
0
0

はいこんばんは。

4GBパッチというものの存在を知ってちょっと調べていたのですが、その過程でこの記事を見かけまして。

4GBパッチは効果がある!  & 個人的使用ツール

せっかくなので自分の愛用しているソフトウェアをいくつか晒してみたいと思います。

当然すべてWindows用です。

テキストエディタ

サクラエディタUnicode版

メモ書きから置換処理、Grep検索、ちょっとしたスクリプト書きまでこれ一つで済んでしまいます。マクロもあるよ。

設定項目が膨大にあるけど、その分かゆいところをゴリゴリカスタマイズできて好きです。デフォルトでも十分使えますけどね。

昔は内部がShift-JISだったのですが、いまはUnicode版もあります。

ファイルリネームツール

お〜瑠璃ね〜む

http://beefway.sakura.ne.jp/dl-allrename.html

仕事しはじめて最初に使ったのがこれで、そのまま使い続けてます。正直ほかのやつ使ったことないので、どこがいいとかアピール難しい……

一通りの機能が揃っていながら、あんまり悩まずに直感的に使える素直さが魅力ですかね。リネーム前のプレビューが見やすいので、致命的なミスも回避できます。

開発はちゃんと継続されていて、たまにバージョンアップされてます。


CopyExt(拡張コピー)

http://www.htosh.com/software/freesoft/copyext.html

エクスプローラ拡張。ファイルやフォルダの右クリックメニュー(コンテキストメニュー)から、

  • リネームしつつコピー
  • 特定のフォルダにコピー
  • タイムスタンプを比較してコピー
  • まとめて選択して、フィルタを通ったものだけをコピー

などなど、いろんな方法でファイルコピーを行えます。設定をプロファイルで保存しておけば、複雑なコピーも一発で実行できたり。

たとえば私は、「1つ以上のファイルを選択した状態で、マウス右ボタンを押しながらドラッグ→表示されるコンテキストメニューで[ここに拡張コピー]をクリックすると“backupXX_(元ファイル名)”という名前でそれぞれ複製される」という設定で使っています。XXは連番で、すでに同じ名前のファイルがある場合だけ番号が増えていきます。所要時間1.5秒。

これでぽいぽいバックアップ取っていけば万が一の時も安心。エクスプローラ拡張なので、ファイルの保存ダイアログ上でも有効。別名保存時に新しい日付のファイル名をつけるのでなく、古いファイルのバックアップを取ってから上書き、という感じで使ってます。

ファイルが壊れる恐怖と日々戦うDTPerにとっては強い味方であります。けどMacのAutomatorのほうが便利じゃね?

圧縮・解凍ツール

Cube ICE

いろんなの使ってきましたが、今はこれを使用中。MacのFinderデフォルトで圧縮されたzipファイルも文字化けせず解凍できます。

使用感はごく普通。標準的なアーカイブ形式にはだいたい対応してると思います。

圧縮時・解凍時に不要ファイルを任意でフィルタリングできるのが精神衛生上よいです。Thumbs.db爆発しろ。

インストール時に謎ツールバーをインストールするかどうか聞かれますので注意。


7-zip

普段使うことはありませんが、後述する比較ツールWinMergeでアーカイブ比較機能を使うために入れています。


Explzh for Windows

ライセンスの関係で仕事用PCには入れてないですが、こちらもMacのデフォルトで圧縮したzipファイルを解凍できます。個人用PCではこちらを主に使っていますね。

ランチャー

CLaunch

パネル型のランチャー。有名どころだと思います。

タブ分けできるのである程度整理ができます。しかしだんだん登録アイテム数が増えてきてパネル自体が巨大に……

デスクトップのダブルクリックで呼び出すようにしているので、普段Adobeのアプリケーションとか使う時はあえて最大化せず、端っこ数ピクセルのスキマを作って(ダブルクリックできるようにして)います。

ファイラー(エクスプローラ拡張)

QTTabBar

Windowsエクスプローラをタブ型にするツール。たぶん似たようなのは山ほどありますが、最近は新しいのを開拓してないです。

いわゆるタブ型アプリケーションに求める機能はだいたい入っていると思います。動作のカスタマイズも細かくできます。

タブの横幅が可変で長いフォルダ名でも省略せず表示してくれること、タブをたくさん開いても多段表示できるので一覧性が損なわれないこと、あたりが個人的に好みですね。

データ比較ツール

WinMerge

定番中の定番。ファイルやフォルダを比較、テキストデータならその場でマージや編集もできます。

プラグインを入れればWordやExcel、PDFも比較可能。圧縮ファイルも解凍なしでそのまま中身を比較できます(要7-zipプラグイン)。

TortoiseSVNと連携させてリビジョン間の差分確認にも使っています。

InDesignのデータは直接比較できないけど、IDML書き出して拡張子をzipに変えたらWinMergeで修正箇所の割り出しができると最近気づきました。たまに便利。

ファイルバックアップ

BunBackup

定番。自動バックアップ、ミラーリング、フィルタ指定、上書き条件指定、世代管理などとりあえず欲しい機能が揃っています。これもカスタマイズ次第でかなり自分好みの設定を作れる。

作業データのバックアップ方法は今後変わりそうだけど、ちょっとしたデータのバックアップには使い続けるつもり。

Subversionクライアント

TortoiseSVN

最近使い始めたばかりのニューフェイス。作業データのバージョン管理を画策していまして、絶賛修行中なのです。

Windows用のGUIクライアントとしては定番どころか鉄板っぽい。エクスプローラを拡張するのはわかりやすいし便利なんだけど、ちょっと動作が重くなる気がしないでもない……

「とーたすえすぶいえぬ」、かるせど覚えた。

その他

WinCDEmu

CD/DVDのイメージファイル(isoとか)を開くと、空いているドライブレターが割り当てられ、通常のCD/DVDドライブと同じ感覚で扱うことができるようになる仮想ドライブツール。ドライブレターに空きがある限りいくつでも開けます。

なにも考えずイメージファイルをダブルクリックするだけで使えて、ドライブの解放も同じくダブルクリックでできます。仮想ドライブを右クリックして[取り出し]でもOK。このシンプルさが普段使いに便利。

例によって最初に出会ったのがこれだっただけで、他にもたくさんあるはず。


M電卓

http://www.vector.co.jp/magazine/softnews/080311/n0803113.html

電卓です。個人的には起動の速さと邪魔にならない小さいウィンドウが魅力かなあ。高機能らしいんだけど、関数電卓とか使わないし……

あと便利なのが16進数での演算。10進数で計算した結果がリアルタイムで16進数表示できたり、その逆もできたり。途中で切り替えもできます。16進数と10進数を混ぜて計算したいとき、たとえば文字コード連番でここから20文字分、とかによく使います。

ちなみに単位換算機能もあるのですが、ポイントがアメリカンポイントなので使ってないというオチ付き。


pinz

http://www.vector.co.jp/soft/win95/util/se343088.html

任意のウィンドウを最前面固定にしてくれるシンプルなツール。常駐型ですが邪魔にはならないです。

タスクバーから固定用アイコンをドラッグ→目的のウィンドウにドロップするだけで使えます。解除も同じく解除用アイコンをドロップだけでOK。

テキストエディタなりファイラーなり、それぞれに最前面固定機能は備えていると思いますが、私くらいになるといちいち個別に設定するのも(設定方法を覚えるのも)めんどくさいですからね。愛用してます。


などなど

思いつくままにいろいろ書いてみました。ほぼ毎日使うものだけに絞った*1のであんまり数なかったですね。

似た機能を持つフリーソフトがたくさんあって選択肢が多いのがWindows界のいいとこなので、「そういう使い方ならこっちのが便利だよ」というのがあったらぜひ教えてくださいー。

*1:諸事情で書かなかったやつもある

[InDesign][JavaScript]選択した文字列を索引項目に登録するJavaScript(読み仮名自動入力、CS3〜)

$
0
0

はいこんばんは。

InDesignで索引項目を追加するときはソートのために読み仮名を入力しなくてはならないのですが、手打ちするのがあまりにもめんどくさいので自動的に取得するスクリプトを作りました。

読み仮名の取得にはみんな大好きYahoo!のテキスト解析WebAPIを利用しています。

これを

f:id:chalcedony_htn:20130703213940p:image

こうします

f:id:chalcedony_htn:20130703213941p:image


あくまで自分用に作ったものなので、

  • 参照形式はデフォルトの「現在のページ」のみ
  • 項目のレベルは設定できない(すべてレベル1になる)

という仕様になっています。

あと、APIのアプリケーションIDは消してありますので、もし使用する場合は自分のアプリケーションID(ランダムな英数字になってます)を取得して、「◆◆◆ココにアプリケーションIDを書く◆◆◆」のところに入れてください(1箇所だけです)。YahooのIDを作れば誰でも取得できます。

ちょっと試してみたいという人にはだいぶ不親切ですがご了承ください><


このスクリプトを書くにあたって、2つの記事を大いに参考にさせていただいています。


動作確認は、WinXP + CS4、WinXP + CS5.5、Win7 + CS5.5、MacOSX 10.7.5 + CS3、MacOSX 10.5.8 + CS3、MacOSX 10.5.8 + CS4で行いました。Macでの動作確認にご協力いただいたお二方、ありがとうございました! 遅れてすいません!


■使用前の確認事項

  • なにが起きても泣かないようにデータのバックアップを取りながら使用してください(最重要)。
  • インターネットへアクセスできる環境が必要です。
  • Yahoo!の「日本語形態素解析API」を使用しています。サービスが終了した場合、スクリプトも使用できなくなります。
  • 選択中の文字列をインターネット経由でYahoo!のサービスへ送信します。機密情報などが漏洩した場合でも責任は持ちません。
  • アクセスログなどを見れば、どんな文字列を送信したか誰でもわかります。
  • 記号類は読み仮名から削除されます。

■使用中の注意事項

  • APIが期待通りの読み仮名を返してくるとは限らないので、必ず1件ずつ確認しながら登録してください。
  • 登録直後は索引項目のページ数が表示されません。索引パネルのメニューから[プレビューを更新]を実行すると直ります。
  • 索引登録時、ドキュメントの最初のページ付近にダミーのテキストフレームが作られます。通常は自動的に削除されますが、スクリプトが途中で止まった場合などに残る可能性があります。ひととおり登録したら、フレームが残っていないか確認してください。あったら消してね。
  • なにが起きても泣かないようにデータのバックアップを取りながら使用してください(念押し)。

// 索引登録支援ツール(InDesign CS3〜)
// Yahoo!のテキスト解析APIを利用して索引の読み仮名入力を自動化します。
// http://developer.yahoo.co.jp/webapi/jlp/
//
// 以下の記事をパク^H^H大いに参考にさせていただいています。
// kmutoさん
// via http://d.kmuto.jp/20120912.html
// CLさん
// via http://d.hatena.ne.jp/C_L/20081012/indesign_socket_http
//
// v0.9 2013/04/03
// v1.0 2013/06/03  デフォルトスタイルの初期化処理追加、自分で使用開始
// v1.1 2013/06/17  初期化処理をやめてダミー文字のサイズだけ指定する形に変更
// 
// NYSL http://www.kmonos.net/nysl/
// ==============================================================================


main();


// メインの処理
function main(){

  //Yahoo!APIのアプリケーションID
  var myAppID = "◆◆◆ココにアプリケーションIDを書く◆◆◆";

  // 選択状態チェック(テキストオブジェクトを選択してる状態のみ動作)
  if(app.selection.length == 0 || !app.selection[0].constructor.name.match(/^(Text|Word|Character|Paragraph|Line|TextColumn|TextStyleRange)$/)){
    alert("索引登録可能なテキストを選択してください。");
    return false;
  }

  var actDoc = app.activeDocument;
  var idx = (actDoc.indexes.length > 0) ? actDoc.indexes[0] : actDoc.indexes.add();

  var targ = app.selection[0]; // 選択中のテキスト
  var title = targ.contents;   // 索引項目になる文言

  // APIリクエスト
  var yapiObj = new YAPIReading();
  yapiObj.appid = myAppID;
  var reading = yapiObj.getReading(title); // 読みがなになる文言

  // 表示ダイアログ準備
  // ダイアログで読みがなを修正可能
  var dlg = createDialog();
  dlg.tf.text = title;   // 索引項目欄に入力
  dlg.rf.text = reading; // 読みがな欄に入力
  // 読みがなが空文字(APIがエラー返してきてる)だったらメッセージを上書きする
  if(reading == ""){ dlg.info.text = "読みがなの自動取得に失敗しました。直接入力してください。"; }

  // ダイアログ表示から登録実行
  // 登録ボタンを押すと、その時点の読みがな欄のテキストを読みがなとして登録
  if(dlg.show() == 1){
    title = dlg.tf.text;
    reading = dlg.rf.text;

    try{
      embedIndex(idx, targ, title, reading); // 登録実行
    } catch(e) {
      alert("登録に失敗しました。\n索引項目または読みがなに使えない文字がないか確認してください。");
      arguments.callee();
    }

    return true;
  }

  return false; // 登録しなかったらfalse返すことにしておく(なんとなく)
}





// ***************************************************************************
//
// 以下、関数・オブジェクト定義など
//
// ***************************************************************************


// 索引を追加する関数 ********************************************************
// kmutoさんのアイディア(マーカーのコピペ)を拝借
// via http://d.kmuto.jp/20120912.html
// ***************************************************************************
function embedIndex(index, target, title, reading) {

  // ダミーのテキストフレームを作って★マークとか入れておく
  var dummyFrame = index.parent.pages[0].textFrames.add();
  dummyFrame.geometricBounds = [0, 0, 50, 50]; // サイズは適当
  dummyFrame.insertionPoints[0].pointSize = 1; // 文字あふれ対策にサイズを小さくしておく
  dummyFrame.contents = "★";

  // 項目追加
  // ダミーの★マークのところに索引マーカーを入れる
  index.topics.add(title, reading).pageReferences.add(dummyFrame.characters[0]);

  // マーカー文字をカット&ペーストして正しい位置に移動
  dummyFrame.characters[0].select();
  app.cut();
  target.insertionPoints[0].select();
  app.pasteWithoutFormatting(); // フォーマットなしでペースト

  // ダミーのフレームを始末
  dummyFrame.remove();
}



// ダイアログオブジェクトを作って返す関数 ************************************
// あとで部品にアクセスしやすいようにショートカット作ってある
// dlg.tf   : 項目入力欄
// dlg.rf   : 読みがな入力欄
// dlg.info : 情報欄
// ***************************************************************************
function createDialog(){
  var dlg = new Window("dialog", "索引登録");
  dlg.orientation = "row";
  dlg.alignChildren = "top";

  var inputG = dlg.add("group");
  inputG.orientation = "column";
  inputG.alignChildren = "left";
  var infoLabel = inputG.add("statictext", undefined, "読みがなを修正してください。キャンセルすると登録を中止します。");

  var inputTitle = inputG.add("group");
  inputTitle.orientation = "row";
  var titleLabel = inputTitle.add("statictext", undefined, "索引項目:");
  var titleField = inputTitle.add ("statictext", undefined, undefined);
  titleLabel.characters = 9;
  titleField.characters = 35;

  var inputReading = inputG.add("group");
  inputReading.orientation = "row";
  var readingLabel = inputReading.add("statictext", undefined, "読みがな:");
  var readingField = inputReading.add ("edittext", undefined, undefined);
  readingLabel.characters = 9;
  readingField.characters = 35;

  var buttonG = dlg.add("group");
  buttonG.orientation = "column";
  buttonG.add("button", undefined, "登録", {name: "ok"});
  buttonG.add("button", undefined, "キャンセル", {name: "cancel"});

  // ショートカット定義
  dlg.tf = titleField;
  dlg.rf = readingField;
  dlg.info = infoLabel;

  return dlg;
}



// 読みがな取得用クラス定義 **************************************************
// アプリケーションIDはインスタンス側で設定する
//
// var hoge = new YAPIReading();      // インスタンス作成
// hoge.appid = "★★アプリケーションID★★"; // 自分のアプリケーションIDを指定する
// var title = "僕の妹は漢字が読める";     // 読みたい文言
// var reading = hoge.getReading(title);     // 解析結果を取得
//
// ってする
// 記号類はfilterで除去。これも変更可能
// 読みがな部分の抽出はテキストそのまま正規表現でぶっこぬき。XML解析なにそれおいしいの
// ***************************************************************************
function YAPIReading(){
  this.appid    = "";
  this.filter   = "1|2|3|4|5|6|7|8|9|10|11|12";
  this.response = "reading";
  this.results  = "ma";

  this.rex = /<reading>(.*?)<\/reading>/g; // <reading>要素を見つける正規表現(gオプション付き)

  this.getReading = function(sentence){
    var reading = "";

    var requestURI = 'http://jlp.yahooapis.jp/MAService/V1/parse?'
                   + 'appid=' + this.appid
                   + '&ma_filter=' + this.filter
                   + '&response='  + this.response
                   + '&results='   + this.results
                   + '&sentence='  + encodeURI(sentence);

    var lwp = new Lwp();
    var result = lwp.get(requestURI);

    // gオプション付きRegExpオブジェクトのexecループ
    // <reading>要素を見つけるたびに中身のテキストを足していく
    var m;
    while (m = this.rex.exec(result)) {
      reading += m[1];
    }
    return reading; // リクエストに失敗した場合はreadingタグがないので空文字になってるはず
  }
  return this;
}


// HTTPアクセス(GET)用クラス定義 *******************************************
// CLさんのモジュールを微改造
// via http://d.hatena.ne.jp/C_L/20081012/indesign_socket_http
// prototypeをやめてUser-Agentをそれっぽくしただけ
// ***************************************************************************
function Lwp() {
  this.userAgent = "InDesign/" + app.version + " (InDesign " + app.version + "; " + $.os + "; ja)";
  this.uri = function(uri) {
    var rex = new RegExp('http://([^:/]+)(?::(\d+))?(.+)');
    // via http://pc11.2ch.net/test/read.cgi/php/1015692614/57
    var urlObj =[];
    if ( uri.match(rex) ) {
      urlObj.host = RegExp.$1;
      urlObj.port = RegExp.$2 ?RegExp.$2 :80;
      urlObj.path = RegExp.$3;
    }
    return urlObj;
  }
  this.get = function (uri) {
    var conn = new Socket;
    var urlObj = this.uri(uri);
    if ( conn.open(urlObj.host + ':' + urlObj.port, 'UTF-8') ) {
      conn.write ("GET " + urlObj.path + " HTTP/1.0\n" + "Host: " + urlObj.host + "\n" + "User-Agent: " + this.userAgent + "\n\n");
        var reply = conn.read(999999);
        conn.close();
      return reply.substring(reply.indexOf("\n\n") + 2);
    }
  }
  return this;
};

[JavaScript]JavaScriptの条件演算子(三項演算子)

$
0
0

PCの中身を整理したので、お蔵出しシリーズと称して、昔自分のために書いた文章を供養していこうと思います。たぶんあんまり続かない。

今回は2008年2月に書いたらしいものに加筆修正しました。

基本(条件演算子の記法)

if(条件式) {
  条件式が真(true)の場合の処理
}
else {
  条件式が偽(false)の場合の処理
}

っていう文と同じ処理をする式を、

(条件式) ? 条件式が真の場合に評価する式 : 条件式が偽の場合に評価する式

と書くことができる。


?:を条件演算子という。JavaScriptでは唯一、項(被演算子)が三つの演算子なので、三項演算子とも呼ばれる。


条件式のカッコ()は可読性のために入れただけで、必須ではない。同じくスペースも必須ではない。

  • それぞれの項はすべて式である
  • 全体が一つの式になっている
  • 式なので全体をカッコ()でくくってもよい

という点に注目。といってもこれは演算子が作る式ならすべてに当てはまるのだけど。

条件式 ?
条件式が真の場合に評価する式 :
条件式が偽の場合に評価する式

とかなんとか、途中で改行してもOK。

式の評価結果

全体で一つの式になっているので、全体で一つの値を返す。

返す値は最後に評価された式の値になる。


たとえば、変数aに(xの値に応じて)bまたはcを代入したい場合、if文を使うとこんな風になる。

x = 10;
if(x == 10) {
  a = b;
}
else {
  a = c;
}
// 結果:aにbが代入される

これを省略して

x = 10;
(x == 10) ? a = b : a = c;
// 結果:aにbが代入される

と書けて、さらに省略して

x = 10;
a = (x == 10) ? b : c;
// 結果:aにbが代入される

と書ける。

演算子の優先順位にもとづき、代入演算子=より条件演算子?:のほうが先に評価されるので、「(x == 10) ? b : c」という式の値がaに代入される。


最後の書き方は個人的によく使ってる。変数に代入するという目的が目に見えやすい気がするので。


あとは、たとえば「引数が条件に合うかどうかを真偽値で返す関数」が

function hoge(huga) { return (huga == piyo) ? true : false; }

とか書けたりする。

if文が増えないからすっきり。でもこっちはやり過ぎるとたぶんあとで読めない。

応用1:入れ子にもできる

全体が式なので、入れ子にもできる。たとえば

if(x < 10) {
  y = a;
}
else if(x < 20) {
  y = b;
}
else if(x < 30) {
  y = c;
}
else {
  y = d;
}

は、

y = (x < 10) ? a : (x < 20) ? b : (x < 30) ? c : d;

と書ける。改行もできるので

y = (x < 10) ? a :
    (x < 20) ? b :
    (x < 30) ? c :
    d;

とか書いてもいい。

素直にifかswitchで書いたほうが、条件分岐ってことがわかりやすくていいと思う。人の書いたコードで見つけたときに面食らわない程度におぼえておく。

応用2:配列/ハッシュの添え字にもできる

くどいようだが式なので、配列やハッシュの添え字にもできる。

var arr = new Array("あ","い","う","え");
var x = 10;

alert(arr[(x==10)?1:3]); // 結果:「い」

使う必要ないと思う。役に立つのはブックマークレットを作るときくらいかな。

[JavaScript]JavaScriptのループ文まとめ

$
0
0

お蔵出しシリーズ2。2008年2月に書いたらしいものに加筆したら原型がなくなりました。

ループ文とは

通常は上から下に処理が進んでいくプログラムを、一定条件に当てはまるあいだだけ繰り返し処理する制御文。

for文

初期値、条件、増減式を設定して、条件が真であるあいだ、一定の処理を繰り返す命令。

正確に言うと条件が偽になったら処理をしないでループを抜ける、ってことになる。


ループ用の変数に初期値(数値)を代入して、それを増減してループ回数を制御する。なので、主にループ回数が開始前に設定できる場合に使う。

for( 式1 ; 式2 ; 式3 ) {
  繰り返したい処理
}
式1
初期値を設定する式。ループ開始前に一度だけ評価される。
式2
条件式。毎回のループの最初に評価され、もしも偽(false)だったら{}内の処理を行わずにループを抜ける。
式3
ループ用の変数の値を増減する式。後処理。毎回のループの最後に評価される。式2が偽になった場合はその時点でループを抜けてしまうので、この式は実行されない。

ちなみに、式1と式3には複数の式を書くことができる。その場合は式をカンマ , で区切ること。*1

例えば「配列arrの要素を順番にすべて書き出す」みたいな処理をしたい場合、

var arr = [10, 20, 30, 40];
for( var i = 0 ; i < arr.length ; i++ ) {
  alert( arr[i] );
}
// 結果:「10」「20」「30」「40」

って書いてもいいんだけど、これだと式2にあたる「 i < arr.length 」の評価時にいちいち配列の要素数を調べることになる。

var arr = [10, 20, 30, 40];
for( var i = 0 , arr_len = arr.length ; i < arr_len ; i++ ) {
  alert( arr[i] );
}
// 結果:「10」「20」「30」「40」

こうすれば、要素数を調べる処理はループ開始前の一回だけで済む。ループ回数が最初に固定できる場合は、採用すると処理が早くなるかも。

while 文

条件を設定し、それが真である間、一定の処理を繰り返す命令。

while( 条件式 ) {
  繰り返したい処理
}

初期値の設定や後処理がないので、ループ内で条件を変更するか、break(後述)とかでループを抜ける必要がある。でないと無限ループになる。

while(true) {
  breakがなければ無限ループされる処理
}

forのところで書いた「配列arrの要素を順番にすべて書き出す」処理をwhile文でやる場合、

var arr = [10, 20, 30, 40];
var i = 0, arr_len = arr.length;
while( i < arr_len ) {
  alert( arr[i] );
  i++;
}
// 結果:「10」「20」「30」「40」

って書くと、for文とまったく同じことができる。


もうちょっと抽象化すると、

for( 式1 ; 式2 ; 式3 ) {
  繰り返したい処理
}

式1;
while( 式2 ) {
  繰り返したい処理
  式3;
}

が同じということ。

でもwhileでこれをやるくらいなら素直にfor使えばいいと思う。


whileの場合、たとえばarrを破壊してしまってもいいなら以下のようなことができる。

var arr = [10, 20, 30, 40];
while( arr.length ) {
  alert( arr.shift() );
}
// 結果:「10」「20」「30」「40」

Array.shift()は配列から最初の要素を取り除き、その要素を返す。

ループのたびに配列arrから要素がひとつずつ減っていって、要素がなくなったら次のループ開始時には条件式「 arr.length 」が0(真偽値に変換するとfalse)になるので、ループを抜ける。

複数行にわたる文字列を取得して、一行ずつ最後まで処理したい場合なんかに使える。

do-while 文

while文と似てるけど、これは一度は必ず一定の処理を行い、その後、条件が真のあいだだけ同じ処理を繰り返す場合に使う命令。

do {
  一度は必ず行うけど、もしかしたら繰り返したいかもしれない処理
} while( 条件式 )

for文やwhile文の場合、条件式が最初からfalseだったらその時点でループを抜けてしまうので、{}内の処理は一度も行われない。

do-while文では、条件式は{}内の処理が行われた後に評価される。なので条件式の結果がどうであっても、とりあえず一度は必ず処理が行われる。

つっても、今までこれ使う機会は一度もなかったんだが……

break文、continue文

ループの途中で処理の流れを中断したい場合に使う命令文。

breakの場合は処理を中断し、直ちにループを抜け、次の処理に移る。

for( var i = 0 ; i < 10 ; i++ ) {
  if( i==5 ) {
    break; // forループを脱出
    alert( "ここは処理されない" );
  }
  alert( "i = " + i );
}
alert( "ループ外 i = " + i );
// 結果:「i = 0」「i = 1」「i = 2」「i = 3」「i = 4」「ループ外 i = 5」

breakでループを抜けた場合、ループ終了時の処理(「i++」の部分)は行われていない。

continueの場合は、直ちにその回のループ終了処理を行う

for( var i=0 ; i<10 ; i++ ) {
 if( i==5 ) {
    continue; // ループ1回分をここで終了する
    alert( "ここは処理されない" );
  }
  alert ( "i = " + i );
}
alert( "ループ外 i = " + i );
// 結果:「i = 0」「i = 1」「i = 2」「i = 3」「i = 4」「i = 6」「i = 7」「i = 8」「i = 9」「ループ外 i = 10」

while文の場合は、条件の変更前にcontinueを置いてしまうと無限ループになるので注意。

for-in文

for-in文はfor文から派生した構文。

配列の各要素……というか、オブジェクトの各プロパティにアクセスして、同じ処理を繰り返す場合に使う。

var arr = [10, 20, 30, 40];
for( var i in arr ) {
  alert( arr[i] );
}
// 結果:「10」「20」「30」「40」すべての要素を列挙

ちなみに i にはオブジェクトのプロパティ名(文字列)が入る。

var arr = [10, 20, 30, 40];
for( var i in arr ) {
  alert( i + " : " + typeof i );
}
// 結果:「0 : string」「1 : string」「2 : string」「3 : string」

数値に見えるけど文字列。


例は配列で書いたけど、実はfor-inは配列に使わないほうがいい。

以下は理由。わからなければ「使っちゃいけないのねフーン」でいいと思う(よくないけど)。


for-in構文は「オブジェクトのプロパティ」にアクセスするので、例えば他のところでArrayオブジェクトが拡張された場合、そのプロパティまで列挙してしまう。

Array.prototype.hoge = function(){ alert("ほげー"); }; // Arrayオブジェクトを拡張
var arr = [10, 20, 30, 40];

for( var i in arr ) {
  alert( arr[i] );
}
// 結果:「10」「20」「30」「40」「function(){ alert("ほげー"); }」最後のはhogeの中身が見えてる

オブジェクト(インスタンス)自身が持っているプロパティだけを列挙したいときは、都度hasOwnProperty()で判定すればOK。

Array.prototype.hoge = function(){ alert("ほげー"); }; // Arrayオブジェクトを拡張
var arr = [10, 20, 30, 40];

for( var i in arr ) {
  if(arr.hasOwnProperty(i)){
    alert( arr[i] );
  }
}
// 結果:「10」「20」「30」「40」hogeはarrが持っているプロパティじゃないのではじかれる
var arr = [10, 20, 30, 40];
arr.hoge = function(){ alert("ほげー"); }; // arrに対してhogeメソッドを追加

for( var i in arr ) {
  if(arr.hasOwnProperty(i)){
    alert( arr[i] );
  }
}
// 結果:「10」「20」「30」「40」「function(){ alert("ほげー"); }」hogeも列挙される


for-inのループはプロパティを定義した順番で行われる(正確には、プロパティに値を代入した順番)。

また、プロパティの値が定義されていないものは無視される。

var obj = new Object;
obj.age;               // 宣言だけはしたけど未定義(undefined)
obj.name = "権兵衛";
obj.age  = "20";       // ここで値を代入
obj.addr = "ちば";
obj.hobby;             // 宣言だけはしたけど未定義(undefined)
for( var i in obj ) {
  alert( i + " : " + obj[i]);
}
// 結果:「name : 権兵衛」「age : 20」「addr : ちば」hobbyは出てこない

疲れたのでこの辺で切り上げ。

*1:正確に言うと、式1〜式3のそれぞれが式であればいいので、複数の式をカンマ演算子でつないで一つの式にしているというだけ。式2も同じことができるけど、評価後の値によって分岐するので順番が大事になる。ループ毎に処理したいものは素直に式3に書いたほうがいい。

[JavaScript]JavaScriptのArray.sort覚え書き

$
0
0

お蔵出しシリーズ3。いつだか忘れたけど昔書いて、2013年5月にリライトしたらしいものをほぼそのまま。どうでもいいけどこのシリーズ、タイトルを統一しようとする気持ちがまったく見受けられませんね。

基本


array.sort(比較関数);

配列arrayの要素を、比較関数(省略可)に基づいて並べ替える。並べ替えは破壊的に行われる、つまり配列array自体が並べ替えられて、元の順番は保存されない。

比較関数を省略した場合

配列arrayの各要素を文字列として比較し、辞書順に並べ替える。

たとえば以下のように処理される。

var array = [10,9,5,15,60];
array.sort();

alert(array); // [10,15,5,60,9] ←数値順ではない
alert(typeof array[0]); // number ←要素としてはnumberのまま

数値順に並べ替えたい場合、あるいはもっと複雑な比較を行って並べ替えたい場合は、比較関数の指定が必要。

比較関数

比較関数には2つの要素が引数として渡され、戻り値に応じてその要素の順序が入れ替えられる。仮に比較関数の第一引数をa、第二引数をbとしたとき、

戻り値 < 0aが前に来るように並べ替えられる
戻り値 == 0保証なし(順序を入れ替えないことになっている)
戻り値 > 0bが前に来るように並べ替えられる

という処理が行われる。

function compare(a, b){
  if(aがbより小) {
    return -1; // 負の数であればなんでもいい
  }
  if(aがbより大) {
    return 1;  // 正の数であればなんでもいい
  }
  return 0;
}

array.sort(compare);

compareを別に定義せず、sortメソッド実行時に指定してもよい。無名関数でもOK。

array.sort(function(a, b){
  if(aがbより小) { return -1; } // 負
  if(aがbより大) { return 1;  } // 正
  return 0;
});

要するに、「こういう基準で要素を並べ替えてね」というのをsortメソッドに教えるためのもの。


例:数値の配列を数値として小さい順に並べ替えたいとき
var array = [10,9,5,15,60];

array.sort(function(a, b){ return a - b; });

alert(array); // [5,9,10,15,60] ←数値順

aとbどちらも数値であれば減算できる。aがbより小さければ式「a - b」の結果は負の数になるので、そのまま戻り値にしている。


例:オブジェクトの配列を、各オブジェクトのプロパティ「value」の値が大きい順に並べ替えたいとき
array.sort(function(a, b){
  if(a.value > b.value) { return -1; } // a.valueが大きければ負
  if(a.value < b.value) { return 1;  } // a.valueが小さければ正
  return 0;
});

これだけ覚えろ


aをbよりに置きたいときは戻り値をにする


[JavaScript]parseIntとparseFloatの覚え書き

$
0
0

前フリが思いつかない件について。

この記事の主旨は一言で言うと「parseIntには第2引数で基数を指定しよう」です。

基本

parseIntとparseFloatは、どちらも引数として渡された文字列をパースして数値に変換するグローバル関数。

parseIntは整数、parseFloatは小数と整数の両方(浮動小数点数)を扱える。

parseInt("100")    // 100
parseInt("3.14")   // 3

parseFloat("100")  // 100
parseFloat("3.14") // 3.14

パース方法とNaN

parseIntとparseFloatは、どちらも引数の文字列を先頭から1文字ずつ確認し、数値と解釈できない文字が見つかった時点で、その直前までの部分を数値として返す。

一文字も数値にできなかった場合はNaN(数値ではないことを表す数値型の値)を返す。

わかりにくいので例を。

parseInt("100pt")     // 100
parseInt("-3.14pt")   // -3
parseInt("314e-2")    // 314
parseInt("hoge123")   // NaN

parseFloat("100pt")   // 100
parseFloat("-3.14pt") // -3.14
parseFloat("314e-2")  // 3.14
parseFloat("hoge123") // NaN

parseFloatが数値と解釈できるのは、正負符号(+/-)、0〜9の数字、小数点、指数(e)。

parseIntはそこから小数点を除いたもの……ではなくて、実はもうちょっと複雑。

parseIntの第2引数(基数)

parseIntの引数として、パースしたい文字列のほかに、「何進数として解釈するか」という基数を渡すことができる。

基数は文字列でなくて数値で渡すことに注意。

parseInt("15", 10) // 15
parseInt("15", 8)  // 13
parseInt("15", 16) // 21

同じ"15"という文字列を、10進数、8進数、16進数でパースした値が返ってくる。

基数の指定によって、数として解釈できる文字は変わってくる。ちょっと複雑と言ったのはこのこと。

parseInt("19e", 10) // 19("e"はパース不可)
parseInt("19e", 8)  // 1 ("9e"はパース不可)
parseInt("19e", 16) // 414

基数を省略した場合、通常は10進数でパースされる。のだけど、省略するとけっこう危険だったりする。

基数を省略した場合

もしくは、基数に0を指定した場合、自動的に以下のように解釈されることが多い。

  • "0x"または"0X"で始まる文字列が渡された場合、基数は16(16進数)と解釈される。
  • "0"で始まる文字列が渡された場合、基数は8(8進数)と解釈される。
  • その他の文字で始まる文字列が渡された場合、基数は10(10進数)と解釈される。
parseInt("0x15") // 21(16進数として解釈)
parseInt("015")  // 13(8進数として解釈)※実装による
parseInt("15")   // 15(10進数として解釈)

16進数はともかく、この8進数がなかなか厄介で……

parseInt("015")  // 13(8進数)※実装による
parseInt("019")  // 1 (8進数、"9"はパース不可)※実装による
parseInt("08")   // 8 (8進数だとNaNになるので10進数で解釈)※実装による

あるでしょう、ノンブルとかで先頭をゼロで埋めてるやつ。

それをうっかりparseInt(textframe.contents)なんてやってしまうと、ページによって変な数値が返ってくる可能性があるということ。

余談

先頭の文字列が"0x"なら16進数、というのは、JavaScript(というか、ECMAScript)の仕様として規定されている。しかし実は先頭が"0"の場合は、「8進数にしてもいいよ(どっちかいうと10進数でやってね)」ということになっていた。

実装では8進数を採用したものが多いけど、確実ではないらしい。つまり実行する環境によって結果がまちまちということ。さっきから※実装によるって書いてるのはそういうことです。

いちおう現在の最新の仕様では、"0x"と"0X"を16進数とするのを除けばデフォルトは10進数、と定められている。けど実装のほうは今のところほとんど追いついてないらしい。AdobeのESTKでも8進数になるしね。

というわけで、この記事の主旨


parseIntには第2引数で基数を指定しよう


大事なことなので2回いいました。ちなみにparseFloatは常に10進数で、基数指定はできません。

[JavaScript][Photoshop]PhotoshopドキュメントをJavaScriptで別名保存する

$
0
0

たまにはアプリケーションに特化したことを書こうのコーナーです(今考えた)。

いわゆる「別名保存」はDocment.saveAs()メソッドを使うんだけど、オプション類をいちいち調べるのが嫌になったのでまとめます。

なお、以下はPhotoshop CS6 Javascript Scripting Reference(リンク先PDF)を信用して書いたものです。ESTK付属のオブジェクトモデルビューアよりずっと使いやすいのでおすすめ。

Document.saveAs() 書式


Document.saveAs(saveIn[, options][, asCopy][, extensionType]);

引数説明
saveIn File 必須。保存先になるFileオブジェクト。ここで拡張子つけても無視してpsd形式にされる。他の形式にしたい場合はオプションで指定する必要がある。
options varies
(いろいろ)
保存オプション。ファイル形式、および保存時のオプションを指定する。ファイル形式ごとにオブジェクト(クラス)が異なる。詳しくはあとで。
asCopy boolean 複製として保存するかどうか。オプション。
extensionTypeExtension 拡張子の書式。オプション。

Extension.LOWERCASE 小文字
Extension.NONE 拡張子なし
Extension.UPPERCASE 大文字

保存先Fileオブジェクト


var fileobj = new File("ファイルパス");

とかして作ればいいんじゃないですかね(投げやり)。

保存オプション

オプションは保存形式ごとに別々のクラスが用意されている。ふつうにGUIで保存するときもそうだけど、形式によってオプションがまるで違うからだと思う。

例えばjpg形式なら、

var saveOptions = new JPEGSaveOptions;
saveOptions.embedColorProfile = true;
saveOptions.formatOptions = FormatOptions.STANDARDBASELINE;
saveOptions.quality = 12;
// 他、各プロパティを設定

app.activeDocument.saveAs(fileobj, saveOptions, false, Extension.LOWERCASE)

って感じでオブジェクトを作ってから、saveAs()実行時に引数として渡す。

とりあえず順番にいきましょう。これ使うの?ってのもあるけど。


BMP

BMPSaveOptions

プロパティ説明
alphaChannels boolean アルファチャンネルを保持するかどうか。たぶん32bitのときだけ。
depth BMPDepthType ビット数。

BMPDepthType.ONE 1bit
BMPDepthType.FOUR 4bit
BMPDepthType.EIGHT 8bit
BMPDepthType.SIXTEEN 16bit
BMPDepthType.TWENTYFOUR 24bit
BMPDepthType.THIRTYTWO 32bit

詳細モードだともっとあるけど略
flipRowOrder boolean 行の順序の反転。osTypeがWindowsのときだけ動作。
osType OperatingSystemファイル形式。

OperatingSystem.OS2 OS/2
OperatingSystem.WINDOWS Windows
rleCompressionboolean RLE圧縮するかどうか。osTypeがWindowsでdepthが4bitか8bitのときだけ動作。
typename string オブジェクトのクラス名。readonly。"BMPSaveOptions"

DCS 1.0

DCS1_SaveOptions

プロパティ説明
dCS DCSType プレビュー用ファイルの形式。

DCSType.COLORCOMPOSITE カラープレビュー
DCSType.GRAYSCALECOMPOSITE グレースケールプレビュー
DCSType.NOCOMPOSITE プレビューなし
embedColorProfileboolean カラープロファイルを埋め込むかどうか。
encoding SaveEncodingエンコーディング形式。

SaveEncoding.ASCII ASCII
SaveEncoding.BINARY バイナリ
SaveEncoding.JPEGLOW JPEG(低画質)
SaveEncoding.JPEGMEDIUM JPEG(標準画質)
SaveEncoding.JPEGHIGH JPEG(高画質)
SaveEncoding.JPEGMAXIMUM JPEG(最高画質)
halftoneScreen boolean ハーフトーンスクリーンを保持するかどうか。
interpolation boolean プレビューに画像補間方式(バイキュービック)を適用するかどうか。
preview Preview EPSプレビュー形式。

Preview.EIGHTBITTIFF 8bitTIFF
Preview.MACOSEIGHTBIT Mac 8bitTIFF
Preview.MACOSJPEG Mac JPEG
Preview.MACOSMONOCHROME Mac 1bitTIFF(モノクロ)
Preview.MONOCHROMETIFF 1bitTIFF(モノクロ)
Preview.NONE なし
transferFunction boolean トランスファー関数を保持するかどうか。
typename string オブジェクトのクラス名。readonly。"DCS1_SaveOptions"
vectorData boolean ベクターデータを保持するかどうか。

DCS 2.0

DCS 1.0のプロパティに加えて、以下のプロパティがある。typenameは当然"DCS2_SaveOptions"になる。

DCS2_SaveOptions

プロパティ説明
multiFileDCSbooleanカラーチャンネルを複数ファイルとして出力するかどうか。falseで単一ファイルになる。
spotColors boolean特色チャンネルを保持するかどうか。

EPS

ほとんどDCSとかぶってるけど改めて全部書いておく。

EPSSaveOptions

プロパティ説明
embedColorProfileboolean カラープロファイルを埋め込むかどうか。
encoding SaveEncodingエンコーディング形式。

SaveEncoding.ASCII ASCII
SaveEncoding.BINARY バイナリ
SaveEncoding.JPEGLOW JPEG(低画質)
SaveEncoding.JPEGMEDIUM JPEG(標準画質)
SaveEncoding.JPEGHIGH JPEG(高画質)
SaveEncoding.JPEGMAXIMUM JPEG(最高画質)
halftoneScreen boolean ハーフトーンスクリーンを保持するかどうか。
interpolation boolean プレビューに画像補間方式(バイキュービック)を適用するかどうか。
preview Preview EPSプレビュー形式。

Preview.EIGHTBITTIFF 8bitTIFF
Preview.MACOSEIGHTBIT Mac 8bitTIFF
Preview.MACOSJPEG Mac JPEG
Preview.MACOSMONOCHROME Mac 1bitTIFF(モノクロ)
Preview.MONOCHROMETIFF 1bitTIFF(モノクロ)
Preview.NONE なし
psColorManagementboolean PostScriptカラーマネジメントを有効にするかどうか。
transferFunction boolean トランスファー関数を保持するかどうか。
transparentWhitesboolean 白色部分を透明として扱うかどうか。モノクロ二階調時(document.modeがDocumentMode.BITMAPのとき)のみ有効。
typename string オブジェクトのクラス名。readonly。"EPSSaveOptions"
vectorData boolean ベクターデータを保持するかどうか。

GIF

GIFSaveOptions

プロパティ説明
colors number 表示色数。
dither Dither ディザ方式。

Dither.DIFFUSION 誤差拡散法
Dither.NOISE ノイズ
Dither.NONE なし
Dither.PATTERN パターン
ditherAmount number ディザの適用量(1〜100)。誤差拡散法の適用時のみ有効。
forced ForcedColors使用しているかどうかに関わらず強制的にパレットに含む色。
ForcedColors.BLACKWHITE 白黒
ForcedColors.NONE なし
ForcedColors.PRIMARIES レッド、グリーン、ブルー、シアン、マゼンタ、イエロー、黒、白
ForcedColors.WEB Webセーフカラー
interlaced boolean インターレースを有効にするかどうか。
matte MatteType マット。透明部分(不透明度が100%でない箇所)の背景色を塗りつぶす色の設定。transparencyプロパティがtrueの場合は完全な透明部分(不透明度0%の箇所)には適用されない。

MatteType.BACKGROUND 背景色
MatteType.BLACK 黒
MatteType.FOREGROUND 描画色
MatteType.NETSCAPE ネットスケープグレー
MatteType.NONE なし
MatteType.SEMIGRAY 50%グレー
MatteType.WHITE 白
palette PaletteType パレットの設定。

PaletteType.EXACT 使用中の色をすべて割り付ける
PaletteType.LOCALADAPTIVE ローカル(割り付け)
PaletteType.LOCALPERCEPTUAL ローカル(知覚)
PaletteType.LOCALSELECTIVE ローカル(特定)
PaletteType.MACOSPALETTE Mac
PaletteType.MASTERADAPTIVE マスター(割り付け)
PaletteType.MASTERPERCEPTUAL マスター(知覚)
PaletteType.MASTERSELECTIVE マスター(特定)
PaletteType.PREVIOUSPALETTE 前回と同じ
PaletteType.UNIFORM ?
PaletteType.WEBPALETTE Web
PaletteType.WINDOWSPALETTE Windows
preserveExactColorsboolean 同一色の保持。ディザの設定が誤差拡散法の場合、カラーテーブルに含まれる色を保護するかどうか。
transparency boolean 透明箇所を維持するかどうか。
typename string オブジェクトのクラス名。readonly。"GIFSaveOptions"

JPEG

JPEGSaveOptions

プロパティ説明
embedColorProfileboolean カラープロファイルを埋め込むかどうか。
formatOptions FormatOptionsJPEGフォーマット。

FormatOptions.OPTIMIZEDBASELINE ベースライン(最適化)
FormatOptions.PROGRESSIVE プログレッシブ
FormatOptions.STANDARDBASELINE ベースライン(標準)
matte MatteType マット。透明部分(不透明度が100%でない箇所)の背景色を塗りつぶす色の設定。

MatteType.BACKGROUND 背景色
MatteType.BLACK 黒
MatteType.FOREGROUND 描画色
MatteType.NETSCAPE ネットスケープグレー
MatteType.NONE なし
MatteType.SEMIGRAY 50%グレー
MatteType.WHITE 白
quality number 画質。1〜12の数値。
scans number プログレッシブ形式のスキャン数(完全に表示されるまでの段階の数)。3〜5の数値。
typename string オブジェクトのクラス名。readonly。"JPEGSaveOptions"

PDF

PDFSaveOptions

多すぎ。プリセット作って適用するのがいいと思う。

プロパティ説明
alphaChannels boolean アルファチャンネルを保持するかどうか。
annotations boolean 注釈を保持するかどうか。
colorConversion boolean カラー変換するかどうか。
convertToEightBit boolean 16bit画像を8bit画像に変換するかどうか。
description string 保存オプションの説明文。
destinationProfile string 出力先カラープロファイル。文字列で指定。
downgradeColorProfile boolean (非推奨)
downSample PDFResample ダウンサンプル方式。

PDFResample.NONE なし
PDFResample.PDFAVERAGE ダウンサンプル(バイリニア法)
PDFResample.PDFBICUBIC ダウンサンプル(バイキュービック法)
PDFResample.PDFSUBSAMPLE サブサンプル(ニアレストネイバー法)
downSampleSize number 画像ダウンサンプル後の解像度。ppiで指定。
downSampleSizeLimit number 画像ダウンサンプルを行う対象になる解像度(この値を超えたら適用)。ppiで指定。
embedColorProfile boolean カラープロファイルを埋め込むかどうか。
embedFonts boolean (非推奨)
embedThumbnail boolean サムネイルを埋め込むかどうか。
encoding PDFEncoding 画像の圧縮形式。

PDFEncoding.JPEG JPEG(画質を数値で指定可能)
PDFEncoding.JPEG2000HIGH JPEG2000最高
PDFEncoding.JPEG2000LOSSLESS JPEG2000 ロスレス?
PDFEncoding.JPEG2000LOW JPEG2000最低
PDFEncoding.JPEG2000MED JPEG2000中
PDFEncoding.JPEG2000MEDHIGH JPEG2000高
PDFEncoding.JPEG2000MEDLOW JPEG2000低
PDFEncoding.JPEGHIGH JPEG最高
PDFEncoding.JPEGLOW JPEG最低
PDFEncoding.JPEGMED JPEG中
PDFEncoding.JPEGMEDHIGH JPEG高
PDFEncoding.JPEGMEDLOW JPEG低
PDFEncoding.NONE なし
PDFEncoding.PDFZIP ZIP8bit
PDFEncoding.PDFZIP4BIT ZIP4bit
interpolation boolean (非推奨)
jpegQuality number 画質。1〜12の数値。encodingプロパティがPDFEncoding.JPEGの時のみ有効。
layers boolean レイヤーを保持するかどうか。
optimizeForWeb boolean Web表示用に最適化するかどうか。
outputCondition string PDF/Xの出力条件。
outputConditionID string PDF/Xの出力条件ID。
PDFCompatibility PDFCompatibilityPDFの互換バージョン。

PDFCompatibility.PDF13 1.3
PDFCompatibility.PDF14 1.4
PDFCompatibility.PDF15 1.5
PDFCompatibility.PDF16 1.6
PDFCompatibility.PDF17 1.7
PDFStandard PDFStandard PDF/X規格。

PDFStandard.NONE なし
PDFStandard.PDFX1A2001 PDF/X-1a:2001
PDFStandard.PDFX1A2003 PDF/X-1a:2003
PDFStandard.PDFX32002 PDF/X-3:2002
PDFStandard.PDFX32003 PDF/X-3:2003
PDFStandard.PDFX42008 PDF/X-4:2008
preserveEditing boolean 編集機能を保持するかどうか。
presetFile string PDF書き出しプリセット(名前)。指定すると他のプロパティよりプリセットの設定が優先される。
profileInclusionPolicyboolean プロファイルを埋め込むかどうか。
registryName string PDF/Xのレジストリ名。
spotColors boolean 特色を保持するかどうか。
tileSize nunber 画像の圧縮形式がJPEG2000の場合のタイル数。encodingプロパティがPDFEncoding.JPEG2000の時のみ有効。
transparency boolean (非推奨)
typename string オブジェクトのクラス名。readonly。"PDFSaveOptions"
useOutlines boolean (非推奨)
vectorData boolean (非推奨)
view boolean 保存後にPDFを表示するかどうか。

PSD

PhotoshopSaveOptions

プロパティ説明
alphaChannels booleanアルファチャンネルを保持するかどうか。
annotations boolean注釈を保持するかどうか。
embedColorProfilebooleanカラープロファイルを埋め込むかどうか。
layers booleanレイヤーを保持するかどうか。
spotColors boolean特色を保持するかどうか。
typename string オブジェクトのクラス名。readonly。"PhotoshopSaveOptions"

PICTファイル

PICTFileSaveOptions

プロパティ説明
alphaChannels boolean アルファチャンネルを保持するかどうか。
compression PICTCompression 圧縮形式。

PICTCompression.JPEGHIGHPICT
PICTCompression.JPEGLOWPICT
PICTCompression.JPEGMAXIMUMPICT
PICTCompression.JPEGMEDIUMPICT
PICTCompression.NONE なし
embedColorProfileboolean カラープロファイルを埋め込むかどうか。
resolution PICTBitsPerPixelsbit数。

PICTBitsPerPixels.EIGHT
PICTBitsPerPixels.FOUR
PICTBitsPerPixels.SIXTEEN
PICTBitsPerPixels.THIRTYTWO
PICTBitsPerPixels.TWO
typename string オブジェクトのクラス名。readonly。"PICTFileSaveOptions"

PICTリソース

Photoshopでは読み込み専用(書き出せない)。

PICTResourceSaveOptions

プロパティ説明
alphaChannels boolean アルファチャンネルを保持するかどうか。
compression PICTCompression 圧縮形式。

PICTCompression.JPEGHIGHPICT
PICTCompression.JPEGLOWPICT
PICTCompression.JPEGMAXIMUMPICT
PICTCompression.JPEGMEDIUMPICT
PICTCompression.NONE なし
embedColorProfileboolean カラープロファイルを埋め込むかどうか。
name string PICTリソースの名前。
resolution PICTBitsPerPixelsbit数。

PICTBitsPerPixels.EIGHT
PICTBitsPerPixels.FOUR
PICTBitsPerPixels.SIXTEEN
PICTBitsPerPixels.THIRTYTWO
PICTBitsPerPixels.TWO
resourceID number PICTリソースのID。
typename string オブジェクトのクラス名。readonly。"PICTResourceSaveOptions"

PXR

PixarSaveOptions

プロパティ説明
alphaChannelsbooleanアルファチャンネルを保持するかどうか。
typename string オブジェクトのクラス名。readonly。"PixarSaveOptions"

PNG

PNGSaveOptions

プロパティ説明
compressionnumber 圧縮設定。0〜9の数値? デフォルトは0
interlaced booleanインターレースを有効にするかどうか。
typename string オブジェクトのクラス名。readonly。"PNGSaveOptions"

RAW

RawSaveOptions

プロパティ説明
alphaChannelsbooleanアルファチャンネルを保持するかどうか。
spotColors boolean特色を保持するかどうか。
typename string オブジェクトのクラス名。readonly。"RawSaveOptions"

SGIRGB

標準ではインストールされない形式らしい(知らない)。

SGIRGBSaveOptions

プロパティ説明
alphaChannelsbooleanアルファチャンネルを保持するかどうか。
spotColors boolean特色を保持するかどうか。
typename string オブジェクトのクラス名。readonly。"SGIRGBSaveOptions"

TGA(Targa)

TargaSaveOptions

プロパティ説明
alphaChannels boolean アルファチャンネルを保持するかどうか。
resolution TargaBitsPerPixels色数。

TargaBitsPerPixels.SIXTEEN 16bit
TargaBitsPerPixels.TWENTYFOUR 24bit
TargaBitsPerPixels.THIRTYTWO 32bit
rleCompressionboolean RLE圧縮するかどうか。
typename string オブジェクトのクラス名。readonly。"TargaSaveOptions"

TIFF

TiffSaveOptions

プロパティ説明
alphaChannels boolean アルファチャンネルを保持するかどうか。
annotations boolean 注釈を保持するかどうか。
byteOrder ByteOrder バイト順序。

ByteOrder.IBM IBM PC
ByteOrder.MACOS Macintosh
embedColorProfile boolean カラープロファイルを埋め込むかどうか。
imageCompression TIFFEncoding 圧縮形式。

TIFFEncoding.JPEG JPEG
TIFFEncoding.NONE なし
TIFFEncoding.TIFFLZW LZW
TIFFEncoding.TIFFZIP ZIP
interleaveChannelsboolean ピクセルの順序。trueでインターリーブになる。
jpegQuality number 画質。1〜12の数値。encodingプロパティがPDFEncoding.JPEGの時のみ有効。
layerCompression LayerCompressionレイヤーの圧縮形式。layersプロパティがtrueの時のみ有効。

LayerCompression.RLE RLE圧縮
LayerCompression.ZIP ZIP圧縮
layers boolean レイヤーを保持するかどうか。
saveImagePyramid boolean 画像ピラミッドを保存するかどうか。
spotColors boolean 特色を保持するかどうか。
transparency boolean 透明部分を保持するかどうか。
typename string オブジェクトのクラス名。readonly。"TiffSaveOptions"


以上!! つかれたー!!!!

[JavaScript][InDesign]InDesignの段落相互参照をJavaScriptで作る

$
0
0

はいこんばんは。

相互参照の作り方がけっこうめんどくさかったので自分用にメモ。ついでに実験。

10.9 + CS6でしか動かしてません。あと、テキストアンカーへの参照は別の作り方するはずです。調べてない。


必要なものは

  • 参照先ドキュメント (A)
    • 参照先マーカー挿入箇所(InsertionPoint) (A-1)
    • 段落参照先オブジェクト(ParagraphDestination) (A-2)
  • 参照元(ソース)ドキュメント (B)
    • 相互参照形式(CrossReferenceFormat) (B-1)
    • 相互参照挿入箇所(Text系オブジェクト) (B-2)
    • 相互参照ソースオブジェクト(CrossReferenceSource) (B-3)

var destinationDoc = app.documents.item("destination.indd"); // A
var sourceDoc = app.documents.item("source.indd");           // B

var destinationPoint = destinationDoc.(DOMツリー).insertionPoints[0];         // A-1
var destination = destinationDoc.paragraphDestinations.add(destinationPoint); // A-2
var format = sourceDoc.crossReferenceFormats.item("formatName");              // B-1
var sourseText = sourceDoc.(DOMツリー).texts[0];                              // B-2
var source = sourceDoc.crossReferenceSources.add(sourseText, format);         // B-3

// 相互参照挿入
sourceDoc.hyperlinks.add(source, destination);

で、たとえばこんなのを作れるねっていう思いつき。変数名は上のと一緒にしてます。

// 選択中のテキストと同じ文言をドキュメント内から検索し、まとめて段落相互参照を設定します。
// 辞書系ドキュメントの見出し語を選択して実行→本文中の同じ文言が全部相互参照になるとか。
// 単なるテキスト検索なので精度を上げるには工夫が必要。あくまで例です。

var destinationDoc = app.activeDocument;
var sourceDoc = app.documents.item("source.indd"); // 相互参照を挿入したいほうのドキュメント

var destinationPoint = app.selection[0].insertionPoints[0];
var destination = destinationDoc.paragraphDestinations.add(destinationPoint);
var format = sourceDoc.crossReferenceFormats.item("見出し参照"); // 相互参照形式は事前に作っておく

// テキスト検索
app.findTextPreferences = NothingEnum.nothing;
app.changeTextPreferences = NothingEnum.nothing;
app.findTextPreferences.findWhat = app.selection[0].contents;
app.findTextPreferences.appliedParagraphStyle = "本文"; // 念のため段落スタイル指定

var foundTexts = sourceDoc.findText(); // 検索実行
for (var i = 0, len = foundTexts.length; i < len; i++) {
  var sourseText = foundTexts[i];
  var source = sourceDoc.crossReferenceSources.add(sourseText, format);

  sourceDoc.hyperlinks.add(source, destination); // destinationは使い回せる
}

使いどころは限定されると思う。


実際のところ、私が使ったのは逆パターン(選択したテキストから参照先の見出しを探す)のほうだったりします。

そもそも相互参照じたい使ってる人少なそうだけどねー。

[JavaScript]Adobe ExtendScriptのプリプロセッサディレクティブ

$
0
0

ExtendScriptって名前、検索しづらいにもほどがあると思います。どうもこんばんは。

スクリプトをいくつかのファイルに分割したり、単機能のライブラリとして読み込んだりしたいとき、#includeディレクティブ(指示文)を記述するとインクルードすることができます。

他にも#targetとか#targetengineだとかあって、使うたびに調べてて面倒になったのでまとめておこうと思いました。

元ネタは「JavaScriptToolsGuideCC.pdf」。Mac 10.9 + ExtendScript Toolkit CCでの実験結果を含みます。


書き方


#include "file1.jsxinc;folder/file2.jsxinc"

Cとかに似てるそうですね、知らんけど。

ポイントは以下の通り。

  • 先頭に#、続けてディレクティブ名、スペース、引数。
  • 末尾にセミコロンはつけない。
  • 引数に複数の値を指定するときはセミコロンで区切る。
  • 引数の引用符は必須ではないけど、英数字以外を含む場合や、複数指定する場合は必要。'でも"でもOK。

各ディレクティブ説明

指定できるディレクティブは以下の6つ。

  • #include
  • #includepath
  • #script
  • #strict
  • #target
  • #targetengine

順番にいきましょう。


#include

#include "../folder/file1.jsxinc"

他のスクリプトファイルをインクルード(読み込んで実行)します。相対パス、絶対パスどちらも使えるっぽいです。

ちなみに.jsxincというのは普通の.jsxファイルの拡張子を変えただけのファイルです。インクルード専用のファイルだということを明示するために付ける拡張子。InDesignのスクリプトパネルなどから直接実行できなくなります。

ディレクティブは複数書いても大丈夫みたいですね。その場合は上から順に読み込まれます。


#includepath

#includepath "folder1;../folder2"

インクルードするファイル(#includeで記述)のパスを指定します。相対パス、絶対パスどちらも使えます。引数は複数指定可能。

これがなかなかややこしいというか、下手に使うと失敗しそうです。例を挙げると、

#includepath "../lib/folder1;../lib/folder2"
#includepath "../lib"
#include "multi.jsxinc"

こんなふうに記述した場合、インクルードされるファイルは以下の4つ。(数字)は読み込み順です。

  • ../lib/folder1/multi.jsxinc (3)
  • ../lib/folder2/multi.jsxinc (2)
  • ../lib/multi.jsxinc (1)
  • ./multi.jsxinc (4)

最後のは、実行中のスクリプトと同じ階層にあるファイルです。

確かに#include自体相対パスとみなせるので理解はできるんだけど……ちょっと怖いのは私だけですか。主に順番とか。

面倒なので実験はしてないけど、これで#includeが複数あるともっとややこしくなりそうです。

ファイル名をユニークにすること、グローバル変数を最低限にすることが大事っぽい。


#script

#script "Script Name"

スクリプトの名前を指定します。

「The name value is displayed in the Toolkit Editor tab.」って書いてあるんだけど、どこで使われるんだかよくわからない。知ってる人いたら教えてください。


#strict

#strict on

エラーチェックをstrict(厳密)モードにします。

オブジェクトのプロパティがreadonly(読み込み専用)に設定されているとき、通常はスクリプトで上書きしようとしても無視されてそのまま進むだけなんだけど、strictモードがonだとエラーで止まるようになるみたいです。


#target
#target "indesign"

スクリプトが動作するアプリケーションを指定します。

ここで指定しておくと、.jsxファイルをダブルクリックしたとき、アプリケーションを起動して実行するかどうかのダイアログが出ます。指定しない場合はESTKで開くだけで、実行はされません。


#targetengine

#targetengine "session"

スクリプトが動作するJavaScriptエンジンを指定します。

通常、スクリプトで使用したグローバル変数は実行後に破棄されるんだけど、ここでmain以外を指定しておくと、スクリプトが動作したアプリケーションが起動している間はずっと変数が保持され、同じエンジンを指定したスクリプトから参照できるようになります。

ScriptUIを使ってウィンドウやらパレットやらを作りたいときには指定必須です。


おしまい

正直#includepathのとこが書きたかっただけです。

[InDesign][JavaScript]InDesignのDOMをprototypeで拡張するメモ

$
0
0

自分で書かないと忘れるのでメモしておきます。

たとえばParagraphに「指定した数値だけポイントサイズを下げる」ってメソッドを生やすとか。

(function(){

  // Paragraph拡張
  // 引数に指定した数値ずつサイズを下げる。単位は無視して数値しか見ない
  // 成功するとtrueを返す
  Paragraph.prototype.downSize = function(num){
    var origin = this.pointSize;
    var size;
    if( num.constructor.name != "Number" ){ throw "downSize Error: 引数が数値ではありません"; }

    size = origin - num;
    if( size <= 0 ) { throw "downSize Error: これ以上サイズを下げられません"; }

    this.pointSize = size;
    return true;
  }

  // 例:段落が一行におさまるまで0.5ずつ文字を小さくする
 // エラー投げられたら止まるようにしておく
  var p = app.selection[0].paragraphs[0];
  while(p.lines.length > 1){
    try {
      p.downSize(0.5);
    }
    catch(e) {
      alert(e);
      break;
    }
  }

}());

エラー処理はてきとーです。

Paragraph(インスタンス)のpointSizeの値しか見てないので、段落内で文字サイズが違う場合対応できない。実験だとpointSizeは最初の文字のサイズが返ってきてるみたい。

[InDesign][JavaScript]InDesignのDOMをprototypeで拡張するメモ2

$
0
0

昨日かいたやつがeveryItem()やitemByRange()で取得したオブジェクトに対応できてなかったことに気付きまして。

twitterで騒いだところ、判別しないで対応すればいいじゃないと教えていただきました。

https://twitter.com/peprintenpa/status/570915349459136512

というわけで、書き直し。

(function(){

  // Paragraph拡張
  // 引数に指定した数値ずつサイズを下げる。単位は無視して数値しか見ない
  // 成功するとtrueを返す
  Paragraph.prototype.downSize = function(num){
    var arr = this.getElements();
    
    for( var i=0, len = arr.length; i<len; i++ ){
      var tmp = arr[i];
      var origin = tmp.pointSize;
      var size;
      if( num.constructor.name != "Number" ){ throw "downSize Error: 引数が数値ではありません"; }

      size = origin - num;
      if( size <= 0 ) { throw "downSize Error: これ以上サイズを下げられません"; }

      tmp.pointSize = size;
    } // ループ終わり
 
    return true;
  }


  // 例:全ページの「target」って名前のテキストフレーム内の全段落のサイズを1下げる
  try {
      app.activeDocument.pages.everyItem().textFrames.item("target").paragraphs.everyItem().downSize(1);
  }
  catch(e) { }


}());

最近everyItem()の便利さにちょっと目覚めました。

[InDesign][JavaScript]InDesignのパネルメニューをJavaScriptから実行するときはパネルがvisibleな必要がある

$
0
0

タイトルで用は済んでるのですが、忘れないようにもう少しメモしておきます。

以下、OSX10.9 + CS6を前提に書いたものです。



直接DOMをいじるよりInDesignのメニューコマンドを叩いてしまうほうが処理が楽なことって結構ありますが、パネルメニューの場合はそのパネルが表示状態になってないと動きません。

表示状態というのはパネルのメニューボタンが押せる状態のことで、他のパネルとくっつけてタブ表示された状態であっても、それが背面になっていたら動かないってことです。

なので、MenuActionオブジェクトをたどるだけじゃなくて、パネルの表示状態も変更する必要があります。

// サンプル
// 各スタイルで未使用の項目をすべて削除する
// 空のドキュメントだと[基本○○]とかを消そうとしてエラーになるので注意

(function(){

    // パネル名を処理したい順に並べておく
    var arr = ["オブジェクトスタイル", "表スタイル", "セルスタイル", "段落スタイル", "文字スタイル"];

    for(var i = 0, len = arr.length; i < len; i++){

      app.panels.itemByName(arr[i]).visible = true; // ★ここで表示状態にしてる

      var menu = app.menus.itemByName(arr[i] + "パネルメニュー");

      menu.menuItems.itemByName("未使用をすべて選択").associatedMenuAction.invoke();
      // 未使用のものがなかったらエラーになるのではじいておく
      try{
        menu.menuItems.itemByName("スタイルを削除...").associatedMenuAction.invoke();
      } catch(e){}

    }

}());

リハビリ的エントリでした。


InDesignの索引をCSVに書き出す(CS2〜CS4)

$
0
0

駆け込み寺の掲示板でこんなスレがあって……
InDesign の索引作成について - DTP駆け込み寺 新掲示板(リニューアル後のページにリンクしてます)
索引の生成時に、入力した読みがなを一緒に書き出せないかという要望でした。
ちょうど索引あたりをいじりまわす勉強中だったので、ごにょっとスクリプト書いて貼り付けてみるなどしたのですが、グループ化したオブジェクトや入れ子になってるテキストフレームに索引マーカーがある可能性を完全に忘れ去っていました(;´д`)ゴメンネ スレ主

というわけでリベンジなのです

(function(){var sepChar = ","// CSV用セル区切り文字(任意)var pageNumSepChar = " "; // ページ番号の区切り文字(任意、2文字以上でもOK)var tmpIndex = app.activeDocument.indexes[0];
  tmpIndex.update(); // 一度索引を更新してページ数などをソートvar str = ""; // 書き出すテキスト// 索引項目すべてについて処理for (var i = 0, t_len = tmpIndex.topics.length; i < t_len; i++) {var tmpTopic = tmpIndex.topics[i];
    str += tmpTopic.name + sepChar;
    str += tmpTopic.sortOrder + sepChar;

    // 参照先すべてのページ番号を取得していくfor (var j = 0, ref_len = tmpTopic.pageReferences.length; j < ref_len; j++) {// とりあえずマーカーのあるテキストフレームの親を取得してみるvar tmpObj = tmpTopic.pageReferences[j].sourceText.parentTextFrames[0].parent;

      // PageオブジェクトじゃなかったらPageオブジェクトが得られるまでさかのぼる// グループ化したオブジェクトや入れ子のテキストフレームに対応するためwhile (tmpObj.constructor.name != "Page") {if (tmpObj.parent.constructor.name != "Story") {
          tmpObj = tmpObj.parent;
        }else{
          tmpObj = tmpObj.parentTextFrames[0].parent;
        }}

      str += tmpObj.name;

      // 参照先がまだ残っていたらページ番号区切り文字を入れる
      str += (j != ref_len-1) ? pageNumSepChar : "";
    }

    str += "\n"; // 改行}// 項目ループここまで// テキスト書き出し(ファイル名を指定して保存)var file = File.saveDialog("ファイル書き出し","CSVファイル:*.csv");
  if (file) {
    file.open("w");
    file.write(str);
    file.close();
  }return;

})();

Windows XP SP2、InDesign CS4でのみ確認。CS2〜CS4までは動くと思います。たぶん。CSは索引関係かなり違うので無理です。
グループ化とか、入れ子とか、表とかもこれで大丈夫なはず。たぶん。whileがちょっと怖いので、万が一使うときはESTK上で動かしたほうがいいかも(無限ループになっても止められるから)。
しかし、なんていうか……変数名ってみんなどうやって決めてるのかなー?

ページ数が倒せない

「あるオブジェクトが配置されているページ」を得るのが結構たいへんなのですね。なんでだろう。
テキストフレームのparentプロパティがPageオブジェクトになるということがわかったので、索引マーカーのあるinsertionPointを含むテキストフレームを探して一つずつループしています。
参考にしたのはこちら(CS用っぽい)。試行錯誤したあとで発見したのだけど、よく見たらまんまだわ……。
(DTPtechNote:1253) [AS Indesign CS] print-current-page.as

そーいえば

Fileオブジェクトまわりはまた今度まとめよう、とか言ったきりなのを思い出した(;´д`)
ていうか私の環境がCS4に移りつつあってやる気が、その、そのうち……。

InDesign単体でも白オーバープリント

$
0
0

もしかして常識だったらどうしよう。まあ、自分メモとして書いておくことにしよう。
Windows版しかわからないのだけど、Macだとどうなんだろう?

InDesign単体なら大丈夫のはず

InDesignは白や紙色のオブジェクトにオーバープリント属性を設定できません。プリント属性パネルのチェックが触れなくなるし、もともと別の色でオーバープリントが設定されているのを白に変えると自動でチェックが外れます。CS2までは線と塗りの入れ替えによってオーバープリント属性が残ってしまう問題(参考:DTP-Sブログ-ひねもすデジタルビヘイビア: InDesignでも発生する白のオーバープリント)があったのですが、CS3からはその点も修正されています。

と思ったら、段落境界線に罠が

以下、Windows XP SP2、InDesign CS4(6.0.3)でやってます(CS1でも同様になります)。
私はこんな感じの囲み線を使った見出しをよく作ります。段落前境界線に色を設定し、段落後境界線を白にしてうまいこと重ねるとできます。(参考:2005-08-19 - 遠近法ノート

上に重ねる白い線の設定はこんな感じ。ちゃんとオーバープリントのチェックは触れなくなっています(なんか中に■があるけど、まあ、いいか)。

ここからが問題。たとえば配色に悩んでいて、いろいろいじっている間になぜかオーバープリントに設定してしまったりして……

やっぱ白でしょ、と色の設定を白に戻します。

オーバープリントのチェックは触れなくなり、最初の設定と同じ状態に見えます。
でも、ここでオーバープリントプレビューに切り換えてみると……

あばばばばば。真っ青です。

他にも

下線や取り消し線の色、あとは段落スタイル・文字スタイルの文字カラーなどでも同じようなことが起きています。文字カラーのほうはもっと恐ろしくて、チェックが完全に外れているように見えるのにオーバープリントになっています。
設定のON/OFFに関わらずパネルで同じように見えるっていうのは明らかにおかしいと思うんですけど、なんにしろオーバープリントまわりはやっぱり怖い((( ゚Д゚)))
CS4だとライブプリフライト機能で簡単に発見できるのが救いです……*1
やっぱり、よっぽどの理由がない限りオーバープリントは触っちゃだめってことですね。

*1:ただしデフォルトだとそこまで警告してくれない

Illustrator 10で、正規表現にマッチする文字が連続してるときだけトラッキングをかけるJavaScript

$
0
0

タイトル長い。

★追記:激重だったので修正版作りました!

どうにも入りきらないテキストをむりくりスペースに収めたいとき、かなの間だけ詰めたりすることがよくあります。それを自動でやろうっていうスクリプトです。俺得です。
Illustrator 10はダイアログを出したりできない(ぽい)ので、文字やトラッキング量の指定はスクリプトを書き換えて行います。10じゃなければ、「イラストレーターで正規表現とテキストの変形 - なにする?DTP+WEB」でもっとずっと高性能なものが配布されています。いいなあこれ使いたいなあ……。

// 正規表現にマッチする文字が並んでるときだけ指定量トラッキング// 選択したテキストオブジェクト(TextArtItem)について処理します。複数選択対応。// 下の例だと、「正規表現にマッチする」を処理した場合は// 「マ」「ッ」に-20のトラッキングがかかります。// すでにトラッキングが設定されている場合は現状から増減します。

(function(){// ----------------------------var amount = -20
  var charClass = "[ァ-ン]"; // エスケープとかは自分でやってね// ----------------------------// 以下本体 =================================================if ( selection.length == 0 ) {alert("何か選択してください"); return; }var sel = selection;
  var rex = newRegExp(charClass,"g");
  var rex2 = newRegExp(charClass);

  for ( var i = 0, len = sel.length; i < len; i++ ) {var tmp = sel[i];

    if ( tmp.typename != "TextArtItem" ) {alert("テキストじゃないので飛ばします");
      continue;
    }

    tmp = tmp.textRange(); // textRangeオブジェクトに変更var contents = tmp.contents;
    var characters = tmp.characters;

    var m = [];
    while ( m = rex.exec(contents) ) {var index = m.index;

      if ( index == characters.length - 1 ) {break; }// 最後の文字ならループ抜けるvar tc = tmp.characters[index];
      var nc = tmp.characters[index + 1];

      if ( !nc.contents.match(rex2) ) {continue; }// 次が違う文字クラスだったらパス

      tc.tracking += amount; // ★}// whileループここまで

    rex.lastIndex = 0; // 検索開始位置リセット}// 選択オブジェクトループここまでalert("おしまい!");

})();

例によってエラーとかまじめに気にしてないです。

★のついてる行を書き換えれば、文字単位の属性にはいろいろ使いまわせる(んじゃないかな)と思います。
ちなみにトラッキングでなくカーニングを使いたい場合(あるんかな)には注意が必要で、

tc.kerning += (amount / 1000); // ★

と書き換えないととんでもない量になります。文字パレットと単位が違うんですね……。
この単位の違い、リファレンスを見る限りCS2から解消されています。

(修正版)Illustrator 10で、正規表現にマッチする文字が連続してるときだけトラッキングをかけるJavaScript

$
0
0

まさかの2日連続投稿ですが、ただの続きです。

昨日のスクリプトですが、せっかく正規表現を使っているのになぜか一文字ずつ検索していました。あほか。
一応動くとはいえ文字が多くなると激重だったので、勉強もかねて書き直したものが下です。パフォーマンスの改善に加えて、せっかくなので相対値だけじゃなくて絶対値指定? もできるようにしました。

// 正規表現にマッチする文字が並んでるときだけ指定量トラッキング// 下の例だと、「正規表現にマッチする」を処理した場合は// 「マ」「ッ」に-20のトラッキングがかかります。// 09.08.06修正// ・一文字ずつ現在値から増減するか、全文字を指定した値に変更するか、選べるようにしました// ・動作が劇的に速くなりました

(function(){// ----------------------------var amount = -20
  var charClass = "[ァ-ン]"; // エスケープとかは自分でやってねvar relative = true; // true: それぞれ現在値から増減 false:すべて指定した値に変更// ----------------------------// 以下本体 =================================================if ( selection.length == 0 ) {alert("何か選択して!"); return; }var sel = selection;

  charClass += "+"; // 量指定子追加var rex = newRegExp(charClass,"g");

  for ( var i = 0, len = sel.length; i < len; i++ ) {var tmp = sel[i];

    if ( tmp.typename != "TextArtItem" ) {alert("テキストじゃないので飛ばします");
      continue;
    }

    tmp = tmp.textRange(); // textRangeオブジェクトに変更var contents = tmp.contents;

    var m = [];
    while ( m = rex.exec(contents) ) {var index = m.index;

      if ( index == contents.length - 1 ) {break; }// 最後の文字ならループ抜けるvar range = tmp.textRange(index, rex.lastIndex -2); // 見つかった文字列の、最後から2番目の文字まで// 相対指定かどうかで処理を分ける。// relativeがtrueのときは現在の値を増減するので一文字ずつ処理するif ( relative ) {var chars = range.characters;
        for ( var j = 0, c_len = chars.length; j < c_len; j++ ) {
          chars[j].tracking += amount;
        }}else{
        range.tracking = amount; // 絶対量ならいっぺんにいける}}// whileループここまで

    rex.lastIndex = 0; // 検索開始位置リセット}// 選択オブジェクトループここまでalert("おしまい!");

})();

要するに、量指定子を使ってトラッキングをかける範囲をダイレクトに取得するようにしたってことです。おかげで次の文字がどうとか判定する必要もなくなり、RegExpオブジェクトを一つにしぼれました。うーん、昨日の自分が何を考えていたのかわからない。
相対値でなく全部同じ値にする場合はtextRangeオブジェクトのtrackingプロパティを使えば一文字ずつ処理する必要がなくなるので、より速くなります(よほど大量にヒットしなければ大差ないですが)。
ただ、一つの状況に最適化すると応用が利かなくなるというわけで、characterオブジェクトにあってtextRangeオブジェクトにないプロパティを操作したい場合にはいろいろ書き換えが必要になってしまいますね。たいしたことないけど。

正規表現の先読みと後読みはどっちがどっちだかわかりにくいんだよ!(追記あり)

$
0
0

といつも思うので、自分用にメモすることで覚えようという魂胆です。
以下はInDesign CS4の正規表現について記述します(たしかCS3から使えたような気がする)。

結論から

名前英語で位置演算子
後読みlookbehindマッチパターンよりの部分(?&lt=) 肯定
(?&lt!) 否定
先読みlookaheadマッチパターンよりの部分(?=) 肯定
(?!) 否定

肯定の場合はパターンの前が「=」、否定の場合は「!」。
英語を見ると「後読み」「先読み」の訳語も納得できそうな気はするのですが、やっぱりわかりにくいです。背後と前方……とか言うとまた混ざるし!
「つぎの電車」と「こんどの電車」はどっちが早く発車するかみたいな感じに似ていますな。
別に演算子さえ覚えてしまえば名前は意識しなくてもよさそうなのですが、せっかくInDesignには正規表現の記述支援機能がついてるので、どうにか慣れておきたいところです。

先読みと後読みは便利

テキストデータがあって、あるパターンをもった文字列を探したいけど、その中でも「後ろに/前に決まったパターンの文字列がある場合だけ」マッチさせたい、みたいなときに活躍します。
例えば「2009年9月7日19時00分〜9月17日8時30分」とかいうテキストがあって、「○時」の数字だけ取り出したい場合は「直前に『日』があって、直後に『時』がある1桁以上の数字」を検索できればOK。
これを正規表現で書くと

(?<=日)\d+(?=時)

こうなります。

(?<=日)後読み部分
\d+マッチ部分
(?=時)先読み部分

ですね。

先読みと後読みは便利その2

先の例、検索で場所を探したいだけなら、実は後読みだの先読みだの考える必要もなかったりします。

日\d+時

だけでも検索には引っかかる。
ただし、そのときのマッチ文字列は「日19時」と「日8時」。一方先読み/後読みを使った場合、マッチ文字列は「19」「8」になります。先読み/後読みの部分は除外されてます。
この差は大きいです。例えば見つけた数字の修正をしたい場合でも、前者だと数字のところまでカーソルを動かさなければなりませんが、後者ならそのまま数字を打ち込めばいいわけです。
もしくは、数字の部分だけに文字スタイルを適用したい場合も、後者ならば置換文字列に「$0」(「見つかったテキスト」)を入力して、置換形式のところで文字スタイルを指定して置換すればいいだけ。いちいち数字部分を選択しなおしてスタイル適用、が必要ありません。

あと、例のアレ

CS4の「正規表現スタイル」。これを使うときはスタイルを設定したい文字列だけを厳密に取り出す必要があるので、先読み/後読みの使いこなしが前提になりますね。
正規表現スタイルは非常に気に入っている機能*1なので熱く語りたいところですが、まあ、いつかそのうち。

これだけ書けば

いい加減私のスカスカな脳ミソでも覚えただろう(`・ω・´)

『後読みが前、先読みが後ろ!』 ……やっぱりわかりにくい!! ><

追記(2009/09/08)

id:seuzoさんからコメントをいただいて、もうちょっとだけわかった気がしたので追記しておきます。

「後読み」のことを「戻り読み」ともいいます。

(?=re)先読み指定があると、
まだ読んでいない部分を先読みしてマッチしたら全体のマッチを成功させます。
(?<=re)後読み指定があると、
マッチ部分の後ろまで戻って、マッチしたら全体のマッチを成功させます。

       |
   \  __  /
   _ (m) _ピコーン
      |ミ|
    /  `´  \
     ('A`)
     ノヽノヽ
       くく

こうかな?

マッチ部分を基準にして、データ処理の流れの「先を読む」か「後ろに戻る」か。
やっぱり英語のほうがわかりやすい気がするけど*2、これでなんとか覚えられそうです。日本語ムズカシネー

*1:実を言えばCS4導入の一番の動機がコレ

*2:日本語の場合「先手」「後手」という言葉もあるし、って自分で混乱させているな

Viewing all 46 articles
Browse latest View live