2008-10-24
■[InDesign][JavaScript][XML][webservice][yahoo]InDesign上で日本語校正支援「proofreader」
なにをするスクリプトか?
InDesign上のテキストの日本語校正支援をします。「ら抜き言葉」や「誤変換」「固有名詞」などの間違いを注釈で指摘します。エンジンには「Yahoo! 校正支援Webサービス」を利用しています。校正精度はYahoo!のエンジンに依存します。
簡単な説明は下記のムービーをご覧ください。
動作環境
このスクリプトが正常に動作する環境は以下の通りです。Windows環境でも動作する可能性がありますが、動作確認はしていません。テスト歓迎。
- Mac Pro Quad 3GHz
- Mac OS X 10.5.5
- InDesign CS3_J(5.0.4)
- インターネット接続環境
- Yahoo!アプリケーションID(無料)が必要です。下記サイトから取得できます。
ダウンロード
http://www.seuzo.jp/st/scripts_InDesignCS3/index.html#proofreader
こちらからのパッケージ版では、Yahoo!アプリケーションIDは必要ありません。
インストール
スクリプト本体(proofreader.jsx)を
/Applications/Adobe InDesign CS3/Scripts/Scripts Panel/
または
~/Library/Preferences/Adobe InDesign/Version 5.0-J/Scripts/Scripts Panel/
にコピーしてください。エイリアスを入れておくだけでもかまいません。スクリプトパレットから使用します。
使用方法
- 「ウインドウ」メニューから「スクリプティング」ー「スクリプト」を選択し、スクリプトパレットを出します。
- 校正したいテキストを選択します。
- スクリプトパレットから、スクリプト「proofreader.jsx」をダブルクリックします。
- 初めて起動する場合のみ、Yahoo!アプリケーションIDを入力するダイアログが開きます。取得したIDを入力してください。IDはスクリプトと同じ階層にある「yahooID.txt」に記録され、次回の起動以降に使用されます。
- 設定ダイアログが出現します。校正すべき項目をチェックしてください。
- 処理が終わるとダイアログが出現して、何カ所校正があったかレポートします。
- 注釈パレットで校正内容を確認してください。
- 【Tips】コードの18行目付近にある下記の行にYahoo!アプリケーションIDを直接書き込むと、ファイルアクセスがなくなり、若干早く処理できるようになります。
YAHOO_ID = "ここに入力するのだ";
- 校正にまちがいを見つけたら...
既知の不具合、またはToDo、あるいは仕様
- 校正後の単語に対して、2重のチェックはできません。たとえば、「出鱈目」という単語は「当て字」でもあり、「鱈」が表外漢字でもあります。しかし、指摘されるのは最初の「当て字」のみです。必要ならば、訂正後にもう一度チェックをしなおしてみてください。
- Yahoo!サーバーがエラーを返したとき、その内容を精査して見合った警告をしたいけれど、どんな時にどんなエラーを返すのか、テスト不足。<-なんだかよくわからないエラーが出た人は、とりあえずコメントを付けてください。
- 1行が数千字とかの文章だと、おそらくエラーになります。やったことないですけれど。
- こういうのって本来はInCopy上で動くと都合がいいのかもしれない。だけど、InCopy持っていないしなぁ。短期雇用していただけるなら、開発してもOKです。
免責事項
- 変換品質は、「Yahoo! 校正支援Webサービス」に依存します。正確な校正品質を保証するものではありません。
- このツールを使用する上でデータの破損などのあらゆる不具合・不利益については一切の責任を負いかねますのでご了解ください。
- このツールはすべてのMacintoshとMac OS上で動作をするという確認をとっていませんし、事実上出来ません。したがって、動作を保証するものではありません。
ライセンス
GNU GPLv3
http://sourceforge.jp/projects/opensource/wiki/licenses%252FGNU_General_Public_License_version_3.0
履歴
- 2008-10-24 ver.0.1 とりあえず版
- 2008-10-25 ver.0.2 ネットワークに繋がっていなかったとき、エラーで終了するようにした。最初に設定ダイアログを出して、指摘範囲を指定できるようにした。
ソースコード
ブログの仕様やブラウザ環境などにより、「\」が正しくないことがあります。エディタなどで調整してください。
/* proofreader.jsx (c)2008 www.seuzo.jp InDesign内で文字校正をします。 Yahoo!デベロッパーネットワークのアプリケーションIDが必要です。 http://developer.yahoo.co.jp/jlp/KouseiService/V1/kousei.html 2008-10-24 ver.0.1 とりあえず 2008-10-25 ver.0.2 ネットワークに繋がっていなかったとき、エラーで終了するようにした。最初に設定ダイアログを出して、指摘範囲を指定できるようにした。 */ #target "InDesign-5.0" ////////////////////////////////////////////設定 const YAHOO_DOMAIN = "jlp.yahooapis.jp"; const YAHOO_PATH = "/KouseiService/V1/kousei?"; //Yahoo!アプリケーションIDの取得 YAHOO_ID = "";//ここにアプリケーションIDを直接入力すれば、ファイルを探さない。 const DISPLAY_DIALOG = true;//設定ダイアログを表示するかどうか ////////////////////////////////////////////エラー処理 function myerror(mess) { if (arguments.length > 0) { alert(mess); } exit(); } ////////////////////////////////////////////ファイルを読み込んで文字列を返す function read_file(my_file) { var tmp_str = ""; if (my_file.reflect.name == "String") {my_file = new File(my_file)};//ファイルパス文字列だった if (fh = my_file.open("r")) {//ファイルを読み込みモードで開く tmp_str = my_file.read(); my_file.close(); } return tmp_str; } ////////////////////////////////////////////データをファイルに書き込む function write_file(my_write_file_path, my_data) { var my_write_file_path; var my_file_obj = new File(my_write_file_path); //if (!(my_file_obj.exists)) {myerror("ファイルがありません\n" + my_write_file_path)}; if(my_file_obj.open("w")) { my_file_obj.write(my_data); my_file_obj.close(); } else { myerror("ファイルが開けません\n" + my_write_file_path); } } ////////////////////////////////////////////yahooID設定の読み書き function get_yahoo_ID() { var yahooID_file = app.activeScript.parent + "/yahooID.txt"; var yahoo_ID = read_file(yahooID_file); if ((yahoo_ID == null) || (yahoo_ID == "")) { yahoo_ID = prompt("Yahoo!アプリケーションIDを入力してください。\n持っていない場合は下記URLから取得してください(無料)\nhttp://developer.yahoo.co.jp/jlp/KouseiService/V1/kousei.html", ""); if ((yahoo_ID == null) || (yahoo_ID == "")) {myerror("キャンセルしました")} write_file(yahooID_file, yahoo_ID); } return yahoo_ID } ////////////////ダイアログ function show_dialog(){ var my_dialog = app.dialogs.add({name:"日本語校正支援:proofreader", canCancel:true}); with(my_dialog) { with(dialogColumns.add()) { // プロンプト staticTexts.add({staticLabel:"選択行の校正を実行して、注釈を添付します。"}); with (borderPanels.add()) { with(dialogRows.add()){staticTexts.add({staticLabel:"▼レベル1 - 基本:表記の間違いや不適切な表現に関する指摘"});} with(dialogRows.add()){var check_01 = checkboxControls.add({staticLabel:"誤字・誤変換 例)人事異同→人事異動", checkedState:true});} with(dialogRows.add()){var check_02 = checkboxControls.add({staticLabel:"言葉の誤用 例)煙に巻く→けむに巻く", checkedState:true});} with(dialogRows.add()){var check_03 = checkboxControls.add({staticLabel:"使用注意 例)外人墓地→外国人墓地", checkedState:true});} with(dialogRows.add()){var check_04 = checkboxControls.add({staticLabel:"不快語 例)がんをつける→にらむ", checkedState:true});} with(dialogRows.add()){var check_05 = checkboxControls.add({staticLabel:"機種依存・拡張文字 例)○付き数字、一部の旧字体など", checkedState:true});} with(dialogRows.add()){var check_06 = checkboxControls.add({staticLabel:"外国地名表記の間違い 例)モルジブ→モルディブ", checkedState:true});} with(dialogRows.add()){var check_07 = checkboxControls.add({staticLabel:"固有名詞表記の間違い 例)ヤフーブログ→Yahoo!ブログ", checkedState:true});} with(dialogRows.add()){var check_08 = checkboxControls.add({staticLabel:"人名表記の間違い 例)ベートーヴェン→ベートーベン", checkedState:true});} with(dialogRows.add()){var check_09 = checkboxControls.add({staticLabel:"ら抜き言葉 例)食べれる→食べられる", checkedState:true});} } with (borderPanels.add()) { with(dialogRows.add()){staticTexts.add({staticLabel:"▼レベル2 - 難読:わかりやすい表記にするための指摘"});} with(dialogRows.add()){var check_10 = checkboxControls.add({staticLabel:"当て字 例)出鱈目、振り仮名", checkedState:true});} with(dialogRows.add()){var check_11 = checkboxControls.add({staticLabel:"表外漢字あり 例)灯籠→灯●", checkedState:true});} with(dialogRows.add()){var check_12 = checkboxControls.add({staticLabel:"用字 例)曖昧→あいまい", checkedState:true});} with(dialogRows.add()){var check_13 = checkboxControls.add({staticLabel:"商標など用語言い換え 例)セロテープ→セロハンテープ", checkedState:true});} } with (borderPanels.add()) { with(dialogRows.add()){staticTexts.add({staticLabel:"▼レベル3 - 品質:文章をよりよくするための指摘"});} with(dialogRows.add()){var check_14 = checkboxControls.add({staticLabel:"二重否定 例)聞かなくはない", checkedState:true});} with(dialogRows.add()){var check_15 = checkboxControls.add({staticLabel:"助詞不足の可能性あり 例)学校行く", checkedState:true});} with(dialogRows.add()){var check_16 = checkboxControls.add({staticLabel:"冗長表現 例)ことができます", checkedState:true});} with(dialogRows.add()){var check_17 = checkboxControls.add({staticLabel:"略語 例)ADSL→非対称デジタル加入者線(ADSL)", checkedState:true});} } with (borderPanels.add()) { with(dialogRows.add()){staticTexts.add({staticLabel:" (c)2008 市川せうぞー http://www.seuzo.jp/"});} } } } if (my_dialog.show() == true) { check_01 = check_01.checkedState; check_02 = check_02.checkedState; check_03 = check_03.checkedState; check_04 = check_04.checkedState; check_05 = check_05.checkedState; check_06 = check_06.checkedState; check_07 = check_07.checkedState; check_08 = check_08.checkedState; check_09 = check_09.checkedState; check_10 = check_10.checkedState; check_11 = check_11.checkedState; check_12 = check_12.checkedState; check_13 = check_13.checkedState; check_14 = check_14.checkedState; check_15 = check_15.checkedState; check_16 = check_16.checkedState; check_17 = check_17.checkedState; //正常にダイアログを片付ける my_dialog.destroy(); return [false, check_01, check_02, check_03, check_04, check_05, check_06, check_07, check_08, check_09, check_10, check_11, check_12, check_13, check_14, check_15, check_16, check_17]; } else { // ユーザが「キャンセル」をクリックしたので、メモリからダイアログボックスを削除 my_dialog.destroy(); myerror(); } } ////////////////////////////////////////////yahooへのリクエストと返事 function get_yahoo_respons(post_str) { var post_str; var reply = "";//サーバーからの返事 var conn = new Socket; if (conn.open ( YAHOO_DOMAIN + ':80', 'UTF-8' ) ) { conn.write ('GET ' + YAHOO_PATH +'appid=' + YAHOO_ID + NO_FILTER + '&sentence=' + post_str + " HTTP/1.0\n" + 'Host: ' + YAHOO_DOMAIN + "\n" + 'User-Agent: ' + 'InDesign/5.0.3 ' +'(Macintosh; U; Intel Mac OS X 10_5_5; ja-jp)' + "\n" + "\n"); reply = conn.read(999999); conn.close(); } else { myerror("インターネットに接続されていません。"); } return reply; } ////////////////////////////////////////////実行 //InDesignで選択しているもののチェック if (app.documents.length == 0) {myerror("ドキュメントが開かれていません")} var my_doc = app.activeDocument; if (my_doc.selection.length == 0) {myerror("テキストを選択してください")} var my_selection = my_doc.selection[0]; var my_class =my_selection.constructor.name; my_class = "Text, TextColumn, Story, Paragraph, Line, Word, Character, TextStyleRange".match(my_class); if (my_class == null) {myerror("テキストを選択してください")} var my_paragraphs = my_selection.paragraphs;//選択している段落 if (YAHOO_ID == "") {YAHOO_ID = get_yahoo_ID()}//Yahoo!アプリケーションIDの読み込み //ダイアログ処理 NO_FILTER = "";//指摘除外フィルタ(指摘番号をコンマで区切って指定。詳細は、http://developer.yahoo.co.jp/jlp/KouseiService/V1/kousei.html) if (DISPLAY_DIALOG) { var ans_dialog = show_dialog(); var no_filter_count = 1;//除外数のカウント for (var i = 1; i < ans_dialog.length; i++) {//0番地はダミー if (ans_dialog[i] == false) { NO_FILTER += "," + i;//フィルタ番号を加算 no_filter_count++; } } if (ans_dialog.length == no_filter_count) {myerror("ダイアログのすべてのチェックが外れています")} if (NO_FILTER != "") {NO_FILTER = NO_FILTER.replace (/^,/, '&no_filter=')} } //各段落の処理 var my_regex = new RegExp(/^[ \s\r\n]*$/);//空行をみつけるための正規表現 var my_counter = 0;//かうんたっく for(var i = (my_paragraphs.length -1); i >= 0; i--) {//段落を後ろから処理 var my_contents = my_paragraphs[i].contents; if (my_regex.test(my_contents)){continue;}//空行なら次の段落へ var post_str = encodeURI(my_contents);//エンコード var my_reply = get_yahoo_respons(post_str);//Yahooへの問い合わせ my_reply = my_reply.split("\n\n", 2)[1];//レスポンスヘッダの削除 var my_xml = new XML(my_reply);//XMLオブジェクトの生成 var my_ns_uri = my_xml.namespace(); var my_ns = new Namespace(my_ns_uri); setDefaultXMLNamespace(my_ns);//デフォルトネームスペースを設定する if (my_xml.localName().toString() == "Error"){//エラー要素があったら中止 myerror("サーバーがエラーを返しました:" + my_xml.xpath("/Error/Message")[0].toString()); } for( var ii = (my_xml.Result.length() - 1); ii >= 0; ii--) {//my_xmlのエレメントを後ろから処理 var my_StartPos = parseInt(my_xml.Result[ii].StartPos[0].toString());//スタートポイント、文字位置 var my_Surface = "【誤】" + my_xml.Result[ii].Surface[0].toString() + "\n"; var my_ShitekiWord = "【正】" + my_xml.Result[ii].ShitekiWord[0].toString() + "\n"; var my_ShitekiInfo = "<" + my_xml.Result[ii].ShitekiInfo[0].toString() + ">\n"; var my_note = my_paragraphs[i].insertionPoints[my_StartPos].notes.add();//注釈の作成 my_note.texts[0].contents = my_ShitekiInfo + my_Surface + my_ShitekiWord;//注釈の中身を書き換え my_counter++; } } myerror("校正の結果:\n" + my_counter + "箇所の注釈をつけました");
参考・関連サイト
Socketオブジェクトで遊ぶ。いや遊ばれる -- ディザInDesignブログ
選択したテキストフレーム内の漢字に対してルビをふる -- ディザInDesignブログ
InDesignでSocketクラスの上位クラスを作りHTTPでアクセス -- CLの日記
AJAX and scripting Web services with E4X, Part 1 -- IBM
Processing XML with E4X -- mozilla.org
WebサイトのコンテンツをInDesignに取り込む - 名もないテクノ手
テキストにふりがな(ルビ)を付加する。 - 名もないテクノ手
- 656 http://www.seuzo.jp/st/scripts_InDesignCS3/index.html
- 80 http://www.seuzo.jp/st/index.html
- 22 http://d.hatena.ne.jp/C_L/20081012/indesign_socket_http
- 15 http://dtpwiki.jp/planet/
- 15 http://www.google.co.jp/search?hl=ja&client=firefox-a&rls=org.mozilla:ja:official&q=webサーバー xml+indesign&btnG=検索&lr=lang_ja
- 11 http://www.google.co.jp/search?sourceid=navclient&hl=ja&ie=UTF-8&&q=名もないテクノ手
- 7 http://awasete.com/show.phtml?u=http://kstation2.blog10.fc2.com/
- 7 http://search.yahoo.co.jp/search?p=InDesign+文字校正&search.x=1&fr=top_ga1_sa&tid=top_ga1_sa&ei=UTF-8&aq=&oq=
- 7 http://search.yahoo.co.jp/search?p=ProofReader&search.x=1&fr=top_ga1_sa&tid=top_ga1_sa&ei=UTF-8&aq=&oq=
- 7 http://www.google.co.jp/reader/view/



