Hatena::ブログ(Diary)

名もないテクノ手 このページをアンテナに追加 RSSフィード Twitter

EPUB版『InDesign者のための正規表現入門』

InDesignのTips一覧

2008-10-24

[][][][][]InDesign上で日本語校正支援「proofreader」

なにをするスクリプトか?

InDesign上のテキストの日本語校正支援をします。「ら抜き言葉」や「誤変換」「固有名詞」などの間違いを注釈で指摘します。エンジンには「Yahoo! 校正支援Webサービス」を利用しています。校正精度はYahoo!のエンジンに依存します。

簡単な説明は下記のムービーをご覧ください。

D

高解像度版movie(2.7MB)はこちら。


動作環境

このスクリプトが正常に動作する環境は以下の通りです。Windows環境でも動作する可能性がありますが、動作確認はしていません。テスト歓迎。

  • Mac Pro Quad 3GHz
  • Mac OS X 10.5.5
  • InDesign CS3_J(5.0.4)
  • インターネット接続環境
  • Yahoo!アプリケーションID(無料)が必要です。下記サイトから取得できます。

校正支援Webサービス


ダウンロード

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/

にコピーしてください。エイリアスを入れておくだけでもかまいません。スクリプトパレットから使用します。


使用方法

  1. 「ウインドウ」メニューから「スクリプティング」ー「スクリプト」を選択し、スクリプトパレットを出します。
  2. 校正したいテキストを選択します。
  3. スクリプトパレットから、スクリプト「proofreader.jsx」をダブルクリックします。
    • 初めて起動する場合のみ、Yahoo!アプリケーションIDを入力するダイアログが開きます。取得したIDを入力してください。IDはスクリプトと同じ階層にある「yahooID.txt」に記録され、次回の起動以降に使用されます。
  4. 設定ダイアログが出現します。校正すべき項目をチェックしてください。
  5. 処理が終わるとダイアログが出現して、何カ所校正があったかレポートします。
  6. 注釈パレットで校正内容を確認してください。

  • 【Tips】コードの18行目付近にある下記の行にYahoo!アプリケーションIDを直接書き込むと、ファイルアクセスがなくなり、若干早く処理できるようになります。
YAHOO_ID = "ここに入力するのだ";
  • 校正にまちがいを見つけたら...

Yahoo! JAPANへ校正結果の間違いを報告する


既知の不具合、またはToDo、あるいは仕様

  • 校正後の単語に対して、2重のチェックはできません。たとえば、「出鱈目」という単語は「当て字」でもあり、「鱈」が表外漢字でもあります。しかし、指摘されるのは最初の「当て字」のみです。必要ならば、訂正後にもう一度チェックをしなおしてみてください。
  • Yahoo!サーバーがエラーを返したとき、その内容を精査して見合った警告をしたいけれど、どんな時にどんなエラーを返すのか、テスト不足。<-なんだかよくわからないエラーが出た人は、とりあえずコメントを付けてください。
  • 1行が数千字とかの文章だと、おそらくエラーになります。やったことないですけれど。
  • こういうのって本来はInCopy上で動くと都合がいいのかもしれない。だけど、InCopy持っていないしなぁ。短期雇用していただけるなら、開発してもOKです。

免責事項

  • 変換品質は、「Yahoo! 校正支援Webサービス」に依存します。正確な校正品質を保証するものではありません。
  • このツールを使用する上でデータの破損などのあらゆる不具合・不利益については一切の責任を負いかねますのでご了解ください。
  • このツールはすべてのMacintoshMac 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 + "箇所の注釈をつけました");

参考・関連サイト

標準XML完全解説〈上〉

改訂版 標準XML完全解説(下)

校正支援Webサービス

Socketオブジェクトで遊ぶ。いや遊ばれる -- ディザInDesignブログ

選択したテキストフレーム内の漢字に対してルビをふる -- ディザInDesignブログ

InDesignでSocketクラスの上位クラスを作りHTTPでアクセス -- CLの日記

AJAX and scripting Web services with E4X, Part 1 -- IBM

JavaScript を強化した E4X -- IBM

Processing XML with E4X -- mozilla.org

ふりがな(ルビ)を追加 -- seuzo.jp

注釈(Note)の取り扱い - 名もないテクノ手

WebサイトのコンテンツをInDesignに取り込む - 名もないテクノ手

テキストにふりがな(ルビ)を付加する。 - 名もないテクノ手

XMLオブジェクトの取り扱い - 名もないテクノ手


Powered by Web Services by Yahoo! JAPAN

お〜まちお〜まち 2008/10/24 18:32 早速やってみました。いやー、これはすごいですね。なんか突き抜けたって感じです。もはやデスクトップパブリッシングではなくてクラウドパブリッシングの域に達してますね。
テスト環境はWindows Vista SP1 InDesign CS3 5.0.4です。
> ブログの仕様により、「\」が正しくないことがあります。エディタなどで調整してください。
私の環境(Opera 9.61)ではこの問題は発生しませんでした。

seuzoseuzo 2008/10/24 18:51 テストありがとうございます。
スクリプトを書く人にお褒めいただくのは、お恥ずかしい限りです。

> ブログの仕様により、「\」が正しくないことがあります。エディタなどで調整してください。
えーっと、はてなブログってeucなんですよね。
それで、「\」は本来バックスラッシュなんですけれど、Mac環境のsafariでは「¥」になてしまって失敗します。
コピペする場合は気をつけてくださいってことで。

なかとじなかとじ 2008/10/25 15:49 またやられた〜って感じです。
せうぞーさんならできると思ってました。
ただ、やるならルビ付けのほうを出してくると思ってました。
ん〜む、自分とはアメ車と軽自動車くらいパワーが違うなと痛感するばかりです。

seuzoseuzo 2008/10/25 17:11 >やるならルビ付けのほうを出してくる
そちらはお〜まちさんがやられていますしね。ウチのWebサービスもあるし。

これ、作りながら思ったんですけれど、
ジャストシステムさんのJust Right!3 for InDesignとばちかぶり(Only You)ぢゃないですか(w
http://www.justsystems.com/jp/justright/indesign.html
まあ、JustRightの方はローカル辞書で早いでしょうし、長年のノウハウっていうかジャストシステム品質なんでしょうけれど。
でも、個人がこんなモノを作れる時代ってすごいなあ、と思ってしまいます。<自分でいうなっ!

なかとじなかとじ 2008/10/26 12:45 >そちらはお〜まちさんが
あ、しまった。本当ですね。
失礼いたしました。

>本来はInCopy上で
そうですね。校正はInCopy(編集者)ですよね。
デザイナーやオペが勝手にやるものではありませんものね。
ちなみに道楽でWin用InCopy持ってたりします。
道楽というか、編集者に伝道しようとしていたのですが、
なかなか食いつきが悪くて……

とにもかくにも本当に世の中便利になったもんです。

seuzoseuzo 2008/10/26 13:35 >なかなか食いつきが悪くて
グループワークの環境はあっても、モデルがないというか、成功体験がないのかもしれませんね。

InDesignのプログラマの方は「InDesignとInCopyは同じだよ」とおっしゃいます。
値段は1/3ですね。

お〜まちお〜まち 2008/10/26 15:32 > そちらはお〜まちさんが
え? あの中途半端なのを完成しないといけないんですか(笑)
まあ、この機会にYahooアプリケーションIDも取得したことだし、せうぞーさんのソースをパクッて...

seuzoseuzo 2008/10/26 16:00 >せうぞーさんのソースをパクッて...
あ、こんなものでよければ、ご遠慮なくパクパクしてくださいね。

ライセンスのこととか、考えなくちゃいけない、と思っています。
パクパクしやすいように。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証