Last active
November 10, 2025 09:10
-
-
Save AJABON/bb120b07abbd2798acbd9d00e8a8b823 to your computer and use it in GitHub Desktop.
InDesign: 文字数単位でインデント値を制御するやつ。未選択のときは段落スタイルパネルで選択されているスタイルを制御します。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // File: mojindent.jsx | |
| // Author: (z-) ajabon.catfood.jp | |
| // Date: 2025-11-10 | |
| // Version: 1.1.2 | |
| // Desc: InDesignで段落のインデント値を「文字数」で扱うScriptUI。 | |
| // 同一設定であれば複数処理が可能。 | |
| // オブジェクト未選択状態ではドキュメントデフォルトの段落スタイル設定が変更されます。 | |
| // ※縦組みは(まだ)考慮していません | |
| // | |
| // shiftキー併用で増減値が5になります | |
| // history: 1.1.1 定規の単位 Q, 歯 で不具合があったのを取り急ぎ修正 他のマイナー単位へは将来的に対応 | |
| // 1.1.2 旧ギョギョモジャー方式を採用、すべての単位に対応 | |
| #target indesign | |
| #targetengine "mojindent" | |
| // 条件が揃っているか調べる | |
| if(!app.documents.length) exit(); | |
| var doc = app.activeDocument; | |
| var paragraphs, pointSizeUnitValue, pointSizeVal, leftIndentVal, firstLineIndentVal, rightIndentVal, lastLineIndentVal; | |
| var lastTime = 0; // キー入力イベントの発火がダブるのと、イベント伝播を正しく制御できないので代替措置。ChatGPTにきいた。 | |
| var sel; // 選択範囲 | |
| // 単位名の変換用 | |
| var getUnitName = { | |
| AGATES : "ag", | |
| AMERICAN_POINTS : "ap", | |
| CENTIMETERS : "cm", | |
| CICEROS : "c", | |
| HA : "H", | |
| INCHES : "in", | |
| INCHES_DECIMAL : "in", //暫定 | |
| MILLIMETERS : "mm", | |
| PICAS : "p", | |
| POINTS : "pt", | |
| Q : "Q", | |
| CUSTOM : "pt" //暫定 | |
| }; | |
| // ScriptUI | |
| var win = new Window("""palette{text: "文字数でインデントするから mojindent", orientation: "column", alignChildren: "center", | |
| prms: Panel{orientation: "row",spacing: 28, | |
| left: Group{orientation: "column", spacing: 4, alignChildren: "right", | |
| leftIndent: Group{orientation: "row", spacing: 2, | |
| s: StaticText{text:" 左 : "}, | |
| ctrl: Group{orientation: "column", spacing: 8, | |
| up: StaticText{text: "︿", size: [20, 12]}, | |
| dn: StaticText{text: "﹀", size: [20, 12]} | |
| }, | |
| e: EditText{characters: 6, text: "", minus: false, order: 0} | |
| }, | |
| firstLineIndent: Group{orientation: "row", spacing: 2, | |
| s: StaticText{text:"1 行目左 : "}, | |
| ctrl: Group{orientation: "column", spacing: 8, | |
| up: StaticText{text: "︿", size: [20, 12]}, | |
| dn: StaticText{text: "﹀", size: [20, 12]} | |
| }, | |
| e: EditText{characters: 6, text: "", minus: true, order: 1} | |
| } | |
| }, | |
| right: Group{orientation: "column", spacing: 4, alignChildren: "right", | |
| rightIndent: Group{orientation: "row", spacing: 2, | |
| s: StaticText{text:" 右 : "}, | |
| ctrl: Group{orientation: "column", spacing: 8, | |
| up: StaticText{text: "︿", size: [20, 12]}, | |
| dn: StaticText{text: "﹀", size: [20, 12]} | |
| }, | |
| e: EditText{characters: 6, text: "", minus: false, order: 2} | |
| }, | |
| lastLineIndent: Group{orientation: "row", spacing: 2, | |
| s: StaticText{text:"最終行の右 : "}, | |
| ctrl: Group{orientation: "column", spacing: 8, | |
| up: StaticText{text: "︿", size: [20, 12]}, | |
| dn: StaticText{text: "﹀", size: [20, 12]} | |
| }, | |
| e: EditText{characters: 6, text: "", minus: true, order: 3} | |
| } | |
| } | |
| } | |
| s: StaticText{text: "選択なしでドキュメントデフォルトの段落スタイルが対象となります"}, | |
| bottom: Group{orientation: "row", spacing: 2, | |
| s: StaticText{text: "対象文字サイズ:", characters: 20}, | |
| space: StaticText{characters: 6}, | |
| capBtn: Button{text: "とりこみ", helpTip: "選択オブジェクトの設定を反映しますよ"} | |
| } | |
| }"""); | |
| // ヘンスー | |
| var UIleftIndent = win.prms.left.leftIndent; | |
| var UIfirstLineIndent = win.prms.left.firstLineIndent; | |
| var UIrightIndent = win.prms.right.rightIndent; | |
| var UIlastLineIndent = win.prms.right.lastLineIndent; | |
| // tebキーで送る順番 | |
| var etAry = [UIleftIndent, UIfirstLineIndent, UIrightIndent, UIlastLineIndent]; | |
| /* イベントハンドラ */ | |
| // 値のダイレクト入力 単位の入力は不可 | |
| UIleftIndent.e.onEnterKey = UIleftIndent.e.onChange = function(){ | |
| getIndents(); | |
| var val = veryfyValue(this.text, false); | |
| if(val == undefined) return; | |
| app.doScript("func_left(" + val + ")", ScriptLanguage.JAVASCRIPT, [], UndoModes.FAST_ENTIRE_SCRIPT); | |
| } | |
| UIfirstLineIndent.e.onEnterKey = UIfirstLineIndent.e.onChange = function(){ | |
| getIndents(); | |
| var val = veryfyValue(this.text, true); | |
| if(val == undefined) return; | |
| app.doScript("func_first(" + val + ")", ScriptLanguage.JAVASCRIPT, [], UndoModes.FAST_ENTIRE_SCRIPT); | |
| } | |
| UIrightIndent.e.onEnterKey = UIrightIndent.e.onChange = function(){ | |
| getIndents(); | |
| var val = veryfyValue(this.text, false); | |
| if(val == undefined) return; | |
| app.doScript("func_right(" + val + ")", ScriptLanguage.JAVASCRIPT, [], UndoModes.FAST_ENTIRE_SCRIPT); | |
| } | |
| UIlastLineIndent.e.onEnterKey = UIlastLineIndent.e.onChange = function(){ | |
| getIndents(); | |
| var val = veryfyValue(this.text, true); | |
| if(val == undefined) return; | |
| app.doScript("func_last(" + val + ")", ScriptLanguage.JAVASCRIPT, [], UndoModes.FAST_ENTIRE_SCRIPT); | |
| } | |
| // StaticTextをクリックしたら同一グループのEditTextにフォーカス | |
| UIleftIndent.s.addEventListener("click", focusEditText); | |
| UIfirstLineIndent.s.addEventListener("click", focusEditText); | |
| UIrightIndent.s.addEventListener("click", focusEditText); | |
| UIlastLineIndent.s.addEventListener("click", focusEditText); | |
| // 値の上下ボタン操作 | |
| UIleftIndent.ctrl.up.addEventListener("click", upBtn); | |
| UIleftIndent.ctrl.dn.addEventListener("click", dnBtn); | |
| UIfirstLineIndent.ctrl.up.addEventListener("click", upBtn); | |
| UIfirstLineIndent.ctrl.dn.addEventListener("click", dnBtn); | |
| UIrightIndent.ctrl.up.addEventListener("click", upBtn); | |
| UIrightIndent.ctrl.dn.addEventListener("click", dnBtn); | |
| UIlastLineIndent.ctrl.up.addEventListener("click", upBtn); | |
| UIlastLineIndent.ctrl.dn.addEventListener("click", dnBtn); | |
| // 値のフィールドで矢印キー上下の操作、tebでフィールド送り、shiftキー併用で逆送り | |
| UIleftIndent.e.addEventListener ("keydown", keyDownFunc); | |
| UIfirstLineIndent.e.addEventListener ("keydown", keyDownFunc); | |
| UIrightIndent.e.addEventListener ("keydown", keyDownFunc); | |
| UIlastLineIndent.e.addEventListener ("keydown", keyDownFunc); | |
| // 選択とりこみボタン | |
| win.bottom.capBtn.onClick = function(){ | |
| // 設定値の取得とUI反映 | |
| getIndents(); | |
| inputToUI(); | |
| } | |
| // 初期動作 | |
| win.bottom.capBtn.notify("onClick"); | |
| win.show(); | |
| ////////////// カンスー /////////////////// | |
| // 左インデント | |
| function func_left(val){ | |
| for(var i = 0; i < paragraphs.length; i++){ | |
| paragraphs[i].leftIndent = pointSizeUnitValue * val; | |
| if(paragraphs[i].firstLineIndent < -paragraphs[i].leftIndent){ | |
| paragraphs[i].firstLineIndent = -paragraphs[i].leftIndent; | |
| } | |
| } | |
| win.bottom.capBtn.notify("onClick"); | |
| } | |
| // 1行目 左インデント | |
| function func_first(val){ | |
| for(var i = 0; i < paragraphs.length; i++){ | |
| while(val < 0 && toNum(paragraphs[i].leftIndent) < toNum(-pointSizeUnitValue * val)){ | |
| paragraphs[i].leftIndent += pointSizeUnitValue; | |
| } | |
| paragraphs[i].firstLineIndent = pointSizeUnitValue * val; | |
| } | |
| win.bottom.capBtn.notify("onClick"); | |
| } | |
| // 右インデント | |
| function func_right(val){ | |
| for(var i = 0; i < paragraphs.length; i++){ | |
| paragraphs[i].rightIndent = pointSizeUnitValue * val; | |
| if(paragraphs[i].lastLineIndent < -paragraphs[i].rightIndent){ | |
| paragraphs[i].lastLineIndent = -paragraphs[i].rightIndent; | |
| } | |
| } | |
| win.bottom.capBtn.notify("onClick"); | |
| } | |
| // 最終行の右インデント | |
| function func_last(val){ | |
| for(var i = 0; i < paragraphs.length; i++){ | |
| while(val < 0 && toNum(paragraphs[i].rightIndent) < toNum(-pointSizeUnitValue * val)){ | |
| paragraphs[i].rightIndent += pointSizeUnitValue; | |
| } | |
| paragraphs[i].lastLineIndent = pointSizeUnitValue * val; | |
| } | |
| win.bottom.capBtn.notify("onClick"); | |
| } | |
| // キーボード操作 | |
| function keyDownFunc(ev){ | |
| var now = new Date().getTime(); | |
| if (now - lastTime < 50) return; // 50ms | |
| lastTime = now; | |
| if(ev.keyName == "Up"){ | |
| upFunc(this); | |
| } | |
| if(ev.keyName == "Down"){ | |
| dnFunc(this); | |
| } | |
| if(ev.keyName == "Tab"){ | |
| if(ScriptUI.environment.keyboardState.shiftKey){ | |
| etAry[(this.order - 1 + 4) % 4].e.active = true; | |
| } else{ | |
| etAry[(this.order + 1) % 4].e.active = true; | |
| } | |
| ev.preventDefault(); | |
| } | |
| } | |
| // StaticTextのクリックで同グループのEditTextにフォーカス | |
| function focusEditText(ev){ | |
| ev.target.parent.e.active = true; | |
| } | |
| // ふえボタン | |
| function upBtn(ev){ | |
| upFunc(ev.target.parent.parent.e); | |
| } | |
| // へりボタン | |
| function dnBtn(ev){ | |
| dnFunc(ev.target.parent.parent.e); | |
| } | |
| // 値のボタン操作による増加 シフトキーで5ずつ | |
| function upFunc(et){ | |
| var val = et.text - 0; | |
| var bs = ScriptUI.environment.keyboardState.shiftKey ? 5 : 1; | |
| var res = val - val % bs; | |
| if(res <= val) res += bs; | |
| et.text = res; | |
| et.notify("onChange"); | |
| } | |
| // 値のボタン操作による減少 シフトキーで5ずつ minus: マイナスを許可するboolean | |
| function dnFunc(et){ | |
| var val = et.text - 0 + 1000; | |
| var bs = ScriptUI.environment.keyboardState.shiftKey ? 5 : 1; | |
| var res = val - (val % bs == 0? bs : val % bs); | |
| res -= 1000; | |
| et.text = res < 0 && et.minus == false? 0 : res; | |
| et.notify("onChange"); | |
| } | |
| // インデント値を取得 | |
| function getIndents(){ | |
| paragraphs = getParagraphs(); | |
| pointSizeVal = isOneValue(paragraphs, "pointSize"); | |
| leftIndentVal = isOneValue(paragraphs, "leftIndent"); | |
| firstLineIndentVal = isOneValue(paragraphs, "firstLineIndent"); | |
| rightIndentVal = isOneValue(paragraphs, "rightIndent"); | |
| lastLineIndentVal = isOneValue(paragraphs, "lastLineIndent"); | |
| } | |
| // 取得した値をUIに反映 | |
| function inputToUI(){ | |
| if(pointSizeVal == undefined){ | |
| valueFunc(["", "", "", ""]); | |
| return; | |
| } | |
| var defaultMU = app.scriptPreferences.measurementUnit; | |
| var defaultAnchor = app.activeWindow.transformReferencePoint; | |
| var tsm = doc.viewPreferences.textSizeMeasurementUnits; | |
| var val = sel[0].insertionPoints[0].pointSize; | |
| var unitName = getUnitName[tsm.toString()]; | |
| app.activeWindow.transformReferencePoint = [val + unitName, 0]; | |
| pointSizeUnitValue = app.activeWindow.transformReferencePoint[0]; | |
| win.bottom.s.text = win.bottom.s.text.replace(/:.*$/, ":" + val + " " + unitName); | |
| valueFunc(leftIndentVal, UIleftIndent); | |
| valueFunc(firstLineIndentVal, UIfirstLineIndent); | |
| valueFunc(rightIndentVal, UIrightIndent); | |
| valueFunc(lastLineIndentVal, UIlastLineIndent); | |
| app.activeWindow.transformReferencePoint = defaultAnchor; | |
| app.scriptPreferences.measurementUnit = defaultMU; | |
| } | |
| // EditTextの値を評価 flag:マイナス値を許容するか | |
| function veryfyValue(txt, flag){ | |
| if(pointSizeVal == undefined) return; | |
| var val = eval(txt); | |
| if(isNaN(val)){ | |
| alert("入力値が気に入らないので考え直してください"); | |
| return; | |
| } | |
| if(val < 0 && flag == false){ | |
| alert("マイナスだめです"); | |
| return; | |
| } | |
| return val; | |
| } | |
| // 段落群を取得 | |
| function getParagraphs(){ | |
| doc = app.activeDocument; | |
| sel = doc.selection; | |
| var ary = []; | |
| if(sel.length == 0){ | |
| // 未選択時はドキュメントデフォルトの段落スタイルをいじる | |
| ary.push(doc.textDefaults.appliedParagraphStyle); | |
| } | |
| for(var i = 0; i < sel.length; i++){ | |
| if(sel[i].hasOwnProperty("paragraphs")){ | |
| ary = ary.concat(sel[i].paragraphs.everyItem().getElements()); | |
| } | |
| } | |
| return ary; | |
| } | |
| // 丸め誤差対策 | |
| function toNum(num){ | |
| return Number(num.toString()); | |
| } | |
| // 選択範囲内すべて一意かをみる 一意ならその値、ばらついたらundefinedを返す | |
| function isOneValue(paragraphs, prop){ | |
| if(paragraphs.length == 0) return undefined; | |
| // var val = eval("paragraphs[0]." + prop); | |
| var val = paragraphs[0][prop]; | |
| if(paragraphs.length == 1) return val; | |
| for(var i = 1; i < paragraphs.length; i++){ | |
| // if(eval("paragraphs[i]." + prop) != val){ | |
| if(paragraphs[i][prop] != val){ | |
| return undefined; | |
| } | |
| } | |
| return val; | |
| } | |
| function valueFunc(val, obj){ | |
| obj.e.text = val == undefined? "" : val / pointSizeUnitValue; | |
| // obj.e.text = val == undefined? "" : val; | |
| } | |
| // function absFloor(val){ /*小数第5位ぐらいで四捨五入してから正数化*/ | |
| // return Math.abs(Math.round(val * 10000) / 10000); | |
| // } | |
| // チェック用 | |
| function cp(mes){ | |
| // alert(mes); | |
| // $.writeln(mes); | |
| } |
Author
Author
1.1.0 とりこみボタン操作時、段落の先頭文字ではなく選択テキストの先頭挿入点に対象を変更。
また対象文字サイズをUI下部に表示するよう追記。
Author
1.1.1 定規の単位 がポイント、インチ、cm、mm 以外のものだと動作不良する旨ご指摘をうけ修正。
とりいそぎQ, 歯に対応。ほかのマイナー単位(シセロ、アゲート、ピクセル、アメリカ式ポイント、U、bai、Mils)には将来的に対応します。
Author
1.1.2 旧ギョギョモジャー方式を採用、すべての単位に対応
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
説明は以下でしてます
https://ajabon.catfood.jp/?p=2805