主にInDesignによる新聞組版Tips中心です。Mac使いですが業務はWin多め。Win DTP Tipsを増やしたい

【InDesign】【スクリプト】0.13mm(小数点)罫線を探せない ※解決済み

日本のDTP業界では罫線として引く最細の実線、いわゆる「オモテケイ」は0.1~0.13mm辺りとされています。つまり小数点第二位ありです。

まず

alert (app.selection[0].strokeWeight);

呼び出しでは、どの線太も問題なく正しいstrokeWeight(環境設定単位:mm)を返します。

InDesign上の0.12mm罫を選択し、実行

しかし、同じ罫線でこの書き方の場合

if (app.selection[0].strokeWeight == 0.12) //選択オブジェクトの線太が0.12mmであれば
{ alert ("true"); } //0.12mmだよ
else
{ alert ("else"); } //そうじゃない

elseを返します。なんでやねん。

因みに 0.1mm=else 0.12mm=else 0.13mm=true 0.14mm=true など、挙動がまちまちです。

この疑問を、去る2021.2.20のDTPerのスクリプトもくもく会#21に持ち込んだところ、主催Uske_Sさん及びこうちゃん

JavaScript浮動小数点(float)いわゆる「mm→point→mmの丸め問題」であろうと。

そうだ、すっかり忘れていましたよ…mmにはそういう問題があったのだ。暫く遭遇しないとうっかりしてしまいます。というわけで、状況や用途に応じ解決策を3点提示して戴きました。

ExtendScript:等価演算子で小数がtrueにならない

このうち自分の業務に適していたのは、グローバルメソッドparseInt()(一旦100を掛けて整数にする)であろうと思われ、以下の様に作成しました。

//DESCRIPTION:選択中から0.1mmベタk100直線のみ削除(らーで閣下)

app.doScript (main, ScriptLanguage.JAVASCRIPT, null, UndoModes.FAST_ENTIRE_SCRIPT);

function main()
{
    var myDoc = app.activeDocument;
    var mySel = myDoc.selection;
    if(mySel == null)
    { alert("何も選択されていません"); exit(); }
    else
    {
        for(i=mySel.length-1; i>=0; i--)
        if((mySel[i].constructor.name === "GraphicLine") && (mySel[i].strokeColor.name === "Black") && (mySel[i].strokeType.name === "ベタ"))
        // fillColor.nameは取り敢えず無視
         {
            if(parseInt(mySel[i].strokeWeight*100, 10) === 10) // 0.10mmなら10
            { mySel[i].remove(); }
            else
            { continue; }
            }
        }

}

TextFrameやRectangle、Imageなど同時に選択していても、指定の罫線のみ削除します。


最後に、せっかくご指南頂いてるのに発表遅くて済みません(涙)運用はずっと前からやってます

秀丸エディタでJedit「複数一括置換」を再現 ※マクロ

秀丸はいいぞ

突然ですみません(

世の中を検索するとエディターは「VS Code! 時代はVS Code!!」「WEB屋ならAtom」「Vim VS Emacs」「漢は黙ってサクラエディタ」辺りしか出てきません。

しかしこちとら、DTP日本語メイン。初期状態では日本語の禁則処理すら覚束無いエディターなんぞに、用はない! 暴言 ※サクラエディタは別です


みんな大好きJeditが身に染みついているMac DTPerな皆様が、Windowsに移行する際障壁となるのが「複数一括置換(正規表現)」。だが、忘れていないだろうか。「お前の不満など、先人がとうに解決済みだ」。そう、ほぼそのままのマクロがちゃんとあるのです。

変換リストによる連続置換マクロ (ListReplace.mac)

秀丸マクロ随一のプロフェッショナルといっても過言ではない、おなじみ山紫水明さんです。

ただ例によって作者さん説明が初心者向けでない()ため、スクショ付きでご説明。

本当は秀丸の必須設定とかモジュールとか先に説明したいところですが、これが膨大な質量でなかなか厳しくて…


マクロのインストール

田楽(でんがく)DLLモジュール必須です!ダウンロード及びインストール・登録は後日(酷い)←後で思い出した

  1. 上記リンクからzipをダウンロード、ListReplace.macをできれば親フォルダーごとマクロフォルダーへ。
    マクロフォルダーは(メニュー)その他→動作環境→環境→パス で指定

  2. (メニュー)マクロ→ マクロ登録→ 対象(エリア)選択・空いている場所を選択しファイルを登録・任意タイトルとグループ(対象エリア)名を付けて完了。※対象1~10はマクロトップメニュー(エリア)
    マクロ登録画面

    マクロ登録数が80に限られるのが、秀丸最大の弱点だと思う


実行

例題。

Jeditでおなじみ、正規表現でのハイライトカラーUnicode番号表示も可能だ!

置換例。「木曽路は」と「すべて」を入れ替え、前後のスペースを削除

秀丸の検索置換機能

上記を、マクロから実行してみる

(メニュー)マクロ→ 対象の分類→ ListReplace(任意名)選択

  1. トップ画面→ 変換小リストの作成
    ListReplaceトップ画面

  2. ここで残念仕様、このウィンドウではこれ以上の長文を受け付けません(UIの長さに比例?)。一旦「名前を付けて保存」後、デスクトップ上でテキストデータを編集します。
    「パラーメータ」はr(正規表現のみ推奨(c=大文字小文字を区別 を入れると、何故か日本語置換できなくなりました)
    半角27字?

  3. 名前をつけて*.txt保存。エンコードとBOMは何でも良いよう。
    記憶しやすいよう、マクロと同じフォルダーが吉

  4. デスクトップ上からこのリスト.txtを開き、書き足して上書き保存。複数作るには改行で区切り、最終行の改行はあってもなくても可。
    編集前

    編集後

  5. 改めてListReplace上で、編集したリストが選択されていることを確認した上で「置換実行」
    「リストの確認・修正」から更に増やす事も可。

  6. 実行プレビューが見え、confirmメニューが表示→ OKなら「このまま確定する」
    ここで取り消しもできます


2)でリスト数を無限?に増やせますが、モニターからはみ出て触れなくなるので、4)5)の編集で増やす方が楽。※次回利用時は、デフォルト値20に戻ります

因みに置換グルーピングは、秀丸固有の\fも使えますが、7つ以内の制限付き。(丸パーレンの場合、10だったかな?)


これだけ賛美しておいて言うのも何ですが

パラメータ「大文字小文字を区別する」がアカンのって、最悪では← 私自身は、前後の一時カラーリング処理や全角半角処理なども含め自作マクロで一度にやる方が効率が良いので、これを使う事は殆どないのですが 更に何てことを←

秀丸の更に良いところは独自マクロ文法が激簡単なことですが、サクラエディタも比較的簡単な上、こちらはJavaScriptも書けるようなので、無料でもあるし、さほど多機能を求めないならそちらを選ぶのもアリでしょう(何故最後にそんな事を)

テキストを選択順に書き出し【InDesign】EDICOLOR機能を再現(5)

InDesignのテキスト書き出しは、基本ストーリー単位・1つずつしかできません。

一括書き出しはスクリプトで可能ですが、単純に抜き出すとページも順序もバラバラ(※story ID順)、出したくないマスターやレイヤー上も対象、またページを跨ぐストーリーをは分断され、何故か他のストーリーと繋がってしま(った記憶)うなどそのままでは不都合だらけなのです。


以下、確かいき親分作(ネタ元は確かBBS)

flag = confirm("ドキュメント全テキストを順不同でUTF-8書き出し\r\r※欄外の不要テキストフレームは削除しておいて下さい¥r※色々ゴミが付くので、必ずエディタで後処理を。");
if (flag == true){
    var myObj = new File ("~/Desktop/_export.txt");
    var flagA = myObj.open ("w");
    myObj.encoding="UTF-8"; //エンコードは必ず付けよう

    if (flagA == true){
        var mytext = app.documents[0].stories.everyItem().contents;
        myObj.writeln (mytext);
        myObj.close();
        }else{
            alert ("書き込むためのファイルが開けません");
                }
        alert ("書き出しました");
        }else{
        alert("処理を中止しました");
            }

InDesignサンプルスクリプトExportAllStories.jsxを使えばストーリー切断は解消できますが、非出力レイヤーの制御やストーリー順の問題は解決できず、更にエンコーディングは前回利用時に依存し、コントロールができません。

スクリプトパネル→ アプリケーション→ Samples→ JavaScript→ ExportAllStories.jsx

というわけで、以下。ページ内に沢山のストーリーがある物、例えば漫画フキダシ等の書き出しに便利です。

InDesignCS5から選択順の認識が可能になり、実現できました(つまりCS4以下は不可)。

2013年頃原型を鯵ぼんさんに作って頂き、長らく自分だけで便利に使っていました。しかし検索すると解決できてる所は意外と見つけられず、これは需要があるのか?と考え、世のため多少のブラシュアップを加え公開する事に。こういうの幾つかあるんですよね… 自分で使っているものを公開しようという発想がありませんでした←


選択フレームのContentsをforと+=で変数の後ろに加算していき、新規作成するInDesignドキュメントのテキストフレームに配置。更にInDesignで新規*.txtを作成保存し、それに先のInDesignドキュメントの内容を書き込む。基本的には最初のいき親分の進化系ですね。

それに最低限の記号類の整理(検索と置換)と、テキストフレーム以外を選択した時のエラー処理を追加しました。普段は検索置換をもっと増やして、親フォルダ名を追加したりしています。

  • Desktopに「myText」フォルダーを作り、保存。連番は「01,02....」
  • インラインオブジェクトやアンカーはゲタに置き換え、表組み非対応
  • 当然スプレッド単位
  • UTF-16/BOMなし
  • LineFeed(改行コード)は指定しない方が良さげ(組み合わせ次第では文字化けする)
  • 検索置換部分は、市川せうぞー大先生の丸パクリ


テキストを選択順に書き出し

//DESCRIPTION:テキストフレームを選択順に書き出し(らーで閣下)
//インラインやミッシンググリフ、インデント分割系の処理だけは入れた

var mySel = app.selection;
if (mySel.length < 1)
{ alert ("何も選択されていません"); exit(); }
else {
    //activeDocumentのテキストを整形 ////////////////////////////////////////////////////////
    //文字列を16進数にエスケープして、「\x{hex}」という形で返す。    
        function my_escape(str) {
            tmp_str = escape(str);
            return tmp_str.replace(/\%u([0-9A-F]+)/i, "\\x{$1}")
            }
        //正規表現検索でカタカナを16進に変換--------------------------------------
        function katakana2hex() {
            var find_str = app.findGrepPreferences.findWhat;
            while (/([ァ-ヴ])/.exec(find_str)) {
                find_str = find_str.replace(/([ァ-ヴ])/, my_escape(RegExp.$1));
                }
            app.findGrepPreferences.findWhat = find_str;//検索文字の設定
            }
        //実行:その1(Grep)--------------------------------------------------------------
        function my_RegexFindChange(my_range, my_find, my_change) {
            //検索の初期化
            app.findGrepPreferences = NothingEnum.nothing;
            app.changeGrepPreferences = NothingEnum.nothing;
            //検索オプション
            app.findChangeGrepOptions.includeLockedLayersForFind = false;//ロックされたレイヤーをふくめるかどうか
            app.findChangeGrepOptions.includeLockedStoriesForFind = true;//ロックされたストーリーを含めるかどうか
            app.findChangeGrepOptions.includeHiddenLayers = false;//非表示レイヤーを含めるかどうか
            app.findChangeGrepOptions.includeMasterPages = true;//マスターページを含めるかどうか
            app.findChangeGrepOptions.includeFootnotes = true;//脚注を含めるかどうか
            app.findChangeGrepOptions.kanaSensitive = true;//カナを区別するかどうか
            app.findChangeGrepOptions.widthSensitive = true;//全角半角を区別するかどうか

            app.findGrepPreferences.properties = my_find;//検索の設定
            app.changeGrepPreferences.properties = my_change;//置換の設定
            my_range.changeGrep(); //検索置換を実行
            }
        var my_doc = app.documents[0]; //範囲
        var my_find_obj = {findWhat:"[\uFFFC\uFFFD\u001A]"};
        //replacmentObject(インライン)・replacmentCharacter(置き換えられた文字)・substitute(ミッシンググリフ等)
        var my_change_obj = {changeTo:"〓"};
        my_RegexFindChange(my_doc, my_find_obj, my_change_obj);
    //実行:その2(Grep)--------------------------------------------------------------
    function my_RegexFindChange(my_range, my_find, my_change) {
        //検索の初期化
        app.findGrepPreferences = NothingEnum.nothing;
        app.changeGrepPreferences = NothingEnum.nothing;
        app.findGrepPreferences.properties = my_find;//検索の設定
        app.changeGrepPreferences.properties = my_change;//置換の設定
        my_range.changeGrep(); //検索置換を実行
        }
    var  my_doc = app.documents[0]; //範囲
    var my_find_obj = {findWhat:"[\u2011\u0007\u0008\u000A\u000B\u0003\u200C\u00A0\u202F\u2008\u2007\u2028\u2029\u2001\u200B\u0019\u00A7]"};
    //分散禁止ハイフン・ここまでインデント・右インデントタブ・LF・垂直タブ・先頭文字スタイルの終了(EOT)・結合なし・分散禁止スペース・分散禁止スペース固定幅・句読点等の間隔・数字の間隔・行区切り文字・段落区切り文字・フラッシュスペース・任意の改行(強制改行)・セクションマーカー・セクション記号
    var my_change_obj = {changeTo:""};
    my_RegexFindChange(my_doc, my_find_obj, my_change_obj);
    //検索置換の終了 ///////////////////////////////////////////////////////////////////////////////////////////

//main ////////////////////////////////////////////////////////////////////////////////////////////////////////////
for (i=0; i<mySel.length; i++)
if (mySel[i].constructor.name != "TextFrame")
{
    alert ("テキストフレーム以外を選択しています(グループも不可)\r\r処理を中断します");
    app.scriptPreferences.userInteractionLevel = UserInteractionLevels.NEVER_INTERACT;
    var rvt = app.documents[0].revert();
    app.scriptPreferences.userInteractionLevel = UserInteractionLevels.INTERACT_WITH_ALL; 
    exit(); }
else
{
    var myContents = "";
    for (j=0; j<mySel.length; j++)
    {
        myContents += mySel[j].parentStory.contents; //(+=)加算
        if (j<mySel.length -1)
        myContents = myContents + "\r\r"; //フレーム間を改行で区切る
    }
}
    //New Documentを作成・myContentsを書き込んで*.txt保存---------------------
    myFolder = new Folder("~/Desktop" + "/" + "myText" );
    myFolder.create();
    var newDoc = app.documents.add();
    var tf = newDoc.textFrames.add();
    tf.contents = myContents;
    var fileList = myFolder.getFiles(); //doc名に連番を振る為のList
    var myFileList = fileList.length;
    var myFile = new File(myFolder + "/" + "0" + (myFileList+1) + ".txt");
    myFile.open("w");
    myFile.encoding="UTF-16"; //UTF-8
    //myFile.lineFeed = "windows"; //macintosh
    myFile.write(myContents); //*.txtにmyContentsを書き込む
    app.documents[0].close(SaveOptions.no); //用済みnewDocを保存せず閉じる
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//処理前=最後の上書きまで復帰(確認アラートを出さない)
app.scriptPreferences.userInteractionLevel = UserInteractionLevels.NEVER_INTERACT;
var rvt = app.documents[0].revert();
app.scriptPreferences.userInteractionLevel = UserInteractionLevels.INTERACT_WITH_ALL; 
alert ("デスクトップの「myText」フォルダーに保存しました");
}

改行がバラバラなのは勘弁してね(

確実に選択したか認識するために、こちら選択数を表示パレットを併用下さい。

表組みとインラインは… まず中へ潜りContents取得、行列数やインラインの場所・位置を記録してその位置へペースト…などかなり面倒で← 表テキスト保存はセルID順にひたすらタブで繋げられ、素では行で折り返されないのです。そういうトコが、腕の見せ所だろうに

因みにサンプルスクリプトExportAllStories.jsxは、不要レイヤーの削除とドキュメントの見開き保存、からのPDF Exportなどを書き足し、顧客への納品に使ったりしています。


余談ですが、私は前処理としてグループを解除する場合に、あるふぁ(仮)さんによる「入れ子のないグループ」の下に、改めてグループ解除を付け足して運用しています。

// 入れ子グループをまとめる-------------------------------------------
app.doScript(main,ScriptLanguage.JAVASCRIPT,[],UndoModes.FAST_ENTIRE_SCRIPT);
function main(){
    var myDocu=app.activeDocument;
    var Sel=myDocu.selection;
    if (Sel.length==1 && Sel[0].constructor.name=="Group"){
    IrekoGroupKaijo(Sel[0]);
} else if (Sel.length>1) {
    SelGroup=myDocu.groups.add(Sel);
    IrekoGroupKaijo(SelGroup);
    SelGroup.select();
    }
}
function IrekoGroupKaijo(GObj){
    while(GObj.groups.length>0){
    //グループを破壊するのでダルマ落とし的に次のグループがgroups[0]に
    GObj.groups[0].ungroup();
    }
}
    //-----------------------------------------------------------------------
    var myDoc = app.activeDocument;
    var mySel = myDoc.selection;
    //myDoc.preferences.GeneralPreference. //環境設定→ 一般 → オブジェクトの編集→ロックされたオブジェクトの選択を防ぐ = false

    for (i=0; i<mySel.length; i++){
    if (mySel[i].constructor.name == "Group")
    mySel[i].ungroup();
    }

【InDesign】左右向き二等辺三角形を一発で作る

新聞向き小ネタ。

f:id:chocomarine:20220308142424j:plain
縦見出しの背面に地紋を置く

こういう表現って、新聞ではよくありました。※最近は減りました

これ、基本機能だけでは手順が
三角形作成→ (反)時計回り 2ステップあるのと、最初の一発で適正サイズに決められないのがもどかしく。回転させると縦横の概念逆転しちゃうしね。

なので、一発小ネタスクリプトにしました。というか最初に小難しい手順で考えていたのを、Uske_Sさんten_Aさんが「簡単に解釈したらいいんだよ」と教えてくれました ←アホね


f:id:chocomarine:20220308143647j:plain
作りたいサイズの矩形を新規作成
任意サイズの新規矩形を作り、選択しておいて下さい。

//DESCRIPTION:選択した矩形サイズで【左右向き】二等辺三角形を作成
// 任意サイズの新規矩形を作り、選択しておいて下さい。

var myDoc = app.activeDocument;
var mySel = myDoc.selection[0];
app.doScript (Main, ScriptLanguage.JAVASCRIPT, null, UndoModes.FAST_ENTIRE_SCRIPT);
function Main()
{
    var  myPath = mySel.paths[0];
    // 左向き
    var  pathA = (mySel.geometricBounds[2] - mySel.geometricBounds[0]) /2;
    myPath.pathPoints[1].remove();
    myPath.pathPoints[0].anchor = [myPath.pathPoints[0].anchor[0], myPath.pathPoints[1].anchor[1] - pathA];
    /* 右向き
    var  pathA = (mySel.geometricBounds[2] - mySel.geometricBounds[0]) /2; // y2-y1 /2
    myPath.pathPoints[3].remove();
    myPath.pathPoints[2].anchor = [myPath.pathPoints[2].anchor[0], myPath.pathPoints[2].anchor[1] - pathA];
    */
}

あ、エラー処理入れてないね(まあいいか)

これ、最後の

myPath.pathPoints[].anchor = ~~~

の行がなければ二等辺三角形を作れるわけですが そこはまあ、各自別個に作って下さい(面倒)←

【InDesign】フォルダー内inddを一括でversion up(もしくはダウングレード)

14ヶ月放ったらかしですね。そうですね いやメンテナンスはしていたんだよ

まあ今さら小ネタ晒しも・・・ と思ってたんですが、やる事ないならやるべきですね(意味不明)

条件テキスト一括指定辺りとやってる事は変わり映えありませんが、沈黙破りとして。


たまに「テンプレート100枚を全部ダウングレードして」やら、アップグレードやらの依頼がきます。昔はBookに収めてそのBookを上位バージョンで開けば、登録inddが全てBookを開いたバージョンに自動アップデートされちゃうという荒業が存在した記憶があるのですが、これは非常に迷惑 最近のBookは事前に警告メッセージを出した挙げ句、同期をかけた瞬間登録*.inddを全て上位に手動変換アクションが始まります。

f:id:chocomarine:20220308132031j:plain
上位バージョンで下位Bookを開いたところ

100枚分、ヤメテ止めて。付き合ってられんわ。ということで自動化です。

フォルダー内*.inddを一括でidml化(ダウングレード下準備)

//DESCRIPTION:フォルダー内inddを一括IDML書き出し(サブフォルダー含)(らーで閣下)
//2019.1.30

(function()
{
    alert("フォント検索、画像のリンク切れor更新もれがあった際は処理を終了します") ;

 try {
        var folderObj = Folder.selectDialog ("処理するInDesignファイルのあるフォルダを選択");
        if (! folderObj)
        {
            exit(); //キャンセル押されたら
            } else
        {
        app.colorSettings.mismatchAskWhenOpening = false; //ファイルを開いた時、カラー設定の不一致ダイアログを表示しない
        var count = 0;
            makeList (folderObj);
            //--------------------------- inddファイルを求める関数
            function makeList (folderObj)
            {
                var fileList = folderObj.getFiles("*.indd"); //ファイルとフォルダを取得
                for (i=0; i<fileList.length; i++)
                {
                    fileObj = new File(fileList[i].fsName);
                    app.open(File(fileObj)); 

                    var saveObj = folderObj + "/" ; //末尾に区切りのスラッシュを追加
                    var myDoc = app.activeDocument; //今開いている分
                    var myDocName = myDoc.name ; //ドキュメント名を取得
                    var fsArray = myDocName.split(".") ;
                    var inddName = fsArray[0] ; //ドキュメント名取得できた
                    var saveIDMLName2 = new File(saveObj+ inddName + ".idml") ; //保存フルパス
                    myDoc.exportFile(ExportFormat.INDESIGN_MARKUP, saveIDMLName2, false);
                    //最後のブーリアン= 保存オプションを出すか否か
                    }
                //サブフォルダへもぐっていく
                for (var j=0; j<fileList.length; j++)
                {
                    try { //不可視fileとか、変なもの居る可能性もあるので
                        var filename =
                        decodeURI (fileList[j].fsName);
                        } catch(e) {
                            var filename = fileList[j].fsName;
                            }
                        count = count + 1;
                } //try前のforの閉じ

            fileList = folderObj.getFiles();
            for (var k=0; k<fileList.length; k++)
            {
                //フォルダかどうか調べる
                if (fileList[k].getFiles)
                {
                    makeList (fileList[k]);//フォルダなら再帰呼び出し
                    }
                }

            } //MakeListのfunction閉じ
        } //最初のelseの閉じ

    } //最初のtryの閉じ
catch(e) {
    alert(e+"\n処理を中止します") ;
    if (myDoc == 0)
    myDoc.close(SaveOptions.no) ;
    } //e処理(最初のtry)の閉じ

alert ("end"); //終了時のメッセージ
app.quit(SaveOptions.no);

})();

フォルダー内*.idmlを一括でindd化(最新・旧バージョンへ)

//DESCRIPTION:IDMLを探しinddに一括保存(サブフォルダ含)(らーで閣下)
//2019.1.30

(function()
{
    alert("フォント検索は基本放置を(OKで進んで下さい)") ;

    try { //idml以外はスルー
        var folderObj = Folder.selectDialog ("処理する「IDML」ファイルのあるフォルダを選択");
        if (! folderObj)
        {
            exit(); //キャンセル押されたら
            } else
        {
            app.colorSettings.mismatchAskWhenOpening = false;
            var count = 0; //41Lで使う
            makeList (folderObj);

            //--------------------------- inddファイルを求める関数
            function makeList (folderObj)
            {
                var myFileList = folderObj.getFiles("*.idml"); //ファイルとフォルダを取得
                for (i=0; i<myFileList.length; i++)
                {
                    fileObj = new File(myFileList[i].fsName);
                    app.open(File(fileObj)); 

                    var myDoc = app.activeDocument; //今開いている分
                    var myDocName = myDoc.name ; //ドキュメント名取得
                    var fsArray = myDocName.split(".") ; //ドットで分割(拡張子をカット)
                    var inddName = fsArray[0] ; //splitの先頭だけ取得
                    var saveINDDName = new File(folderObj + "/" + inddName + ".indd") ; //保存フルパス(上書きモード)
                    myDoc.save(saveINDDName);
                    }
                //サブフォルダへもぐっていく
                for (var j=0; j<myFileList.length; j++)
                {
                    try { //不可視fileとか、変なもの居る可能性もあるので
                        var myFileName =
                        decodeURI (myFileList[j].fsName);
                        } catch(e) {
                            var myFileName = myFileList[j].fsName;
                            }
                        count = count + 1;
                } //try前のforの閉じ

            myFileList = folderObj.getFiles();
            for (var k=0; k<myFileList.length; k++)
            {
                //フォルダかどうか調べる
                if (myFileList[k].getFiles)
                {
                    makeList (myFileList[k]);//フォルダなら再帰呼び出し
                    }
                }

            } //MakeListのfunction閉じ
        } //最初のelseの閉じ

    } //最初のtryの閉じ
    catch(e) {
        alert(e+"\n処理を中止します") ;
        if (myDoc == 0)
        myDoc.close(SaveOptions.no) ;
        } //e処理(最初のtry)の閉じ

alert ("end"); //終了時のメッセージ
app.quit(SaveOptions.no);

})();

何やら懇切丁寧なComments付き…

参考にしたのは、条件テキストのページにあります「再帰処理」の方々です。フォルダーを潜りながら拡張子*.inddを探して開き、idml書き出ししているだけ。最後にアプリケーションも終了しています。

途中の

app.colorSettings.mismatchAskWhenOpening = false; //ファイルを開いた時、カラー設定の不一致ダイアログを表示しない

は、賛否両論あるかと思いますが、ノータッチ一括を重視して。本当は設定を取得→false→最後に戻す が必要ですが、プロファイルから取得か個別に取得変更か…など考え出すと面倒なので、取り敢えず無理やり変更・戻さない形で← いつもの

どうせスタイルの並びや一部設定名称が欧文化するなど、開いてチェックする必要はあるかと思うので(本末転倒と言わないで)、そのついでにカラー設定をドキュメントに付け直す前提に。


****

一番最初のBook警告メッセージ、

これ、最後までよく読んだら、自動変換設定が付けられるんやないすか(呆)

・・・・まあ、わざわざブックに入れて設定全てOFFって、するより速い。はず(

【InDesign】右クリック→(リンク)編集ツール のカスタマイズ

Windows DTP屋の皆様、お元気ですか。

Adobeアプリには、右クリック→(元データを編集)編集ツール→ からアプリを指定し直接開ける機能があります。

Mac版は、システムで見つかる関連アプリをメーカーに依らず全Version表示しますが(これはこれで鬱陶しい)、Win版はOS側の関連付けの性質が悪く、直近のAdobeインストールVersionを1~2しか表示しません。

(cc2019~cc2021までインストール済み・cc2020で作業中)

毎回「その他...」からドライブ(C:)を一から掘り起こさねばならない。 近いディレクトリをDirect Foldersに登録して使っていましたが、それでも2 touchくらいロスが出る。*.exeそのものの登録実行はできなかった

しかし、ボヤいたら神が降臨して下さいました。あるふぁ(仮)さん。本当に神です、いつも本当にありがとうございますーー!


用意するもの

検証環境:Windows 10(2004、20H2)InDesign CC2020(15.0~15.1.2辺り)Illustrator CC2020(24.2.3)

追記:20H2?のアップデート以降、既に起動中の関連アプリがアクティブウィンドウになりません。(2021.3.10)

記述
  1. ExtendScript Toolkit CCをインストール後、起動。新規ドキュメント(ソース)に以下をコピペ

    ※下記セッション名(targetengine)は、他と被らない名で任意
    ※異versionを同時に立ち上げた時も重複してしまうので注意

      //DESCRIPTION:オブジェクトを右クリック「編集ツール」にadobeアプリを追加する(Startup Scripts)
      /*
          最初のとこのアプリ名のリストは、左側がメニュー名(なんでもいい)、右側がBridgeTalkでアプリを特定する文字列。
          調べるには対象にしたいアプリでalert(BridgeTalk.appSpecifier)というスクリプトを実行する
          */
    
      #targetengine "sessionAppMenu"
      apuriNames=[
      ["Illustrator CC 2019","〓"],
      ["InDesign CC 2019","〓"],
      ];
    
      for(var i=0;i<apuriNames.length;i++)
      {
          var m = app.scriptMenuActions.add (apuriNames[i][00]);
          m.addEventListener("onInvoke", (function (t)
          {
              return function()
              {
                  var gs = [], ls = [], s = app.selection;
                  for(var i=0; i<s.length; i++)
                  {
                      if (s[i].hasOwnProperty("itemLink")) gs.push(s[i]);
                      else gs.push.apply(gs,s[i].allGraphics);
                      }
                  for(var i=0; i<gs.length; i++)
                  {
                      if(gs[i].itemLink.status == LinkStatus.NORMAL) ls.push(File(gs[i].itemLink.filePath) + "");
                      }
                  var bt = new BridgeTalk;
                  bt.target = t;
                  bt.body = "var p='"+ls.join(",")+"'.split(',');for(var i=0;i<p.length;i++)app.open(File(p[i]))";
                  bt.send();
                  }
              })
          (apuriNames[i][1]) );
    
          app.menus.item("レイアウトのコンテキストメニュー").submenus.item("編集ツール").menuItems.add(m);
          }
    

  2. Windowsの隠しファイルを表示=ON

    タスクバー「ここに入力して検索」→ 隠しファイル(入力)→隠しファイルを表示する
  3. PC→ Windows(C:)→ ユーザー→ (ユーザー名)→ AppData→ Roaming→ Adobe→ InDesign→ Version xxxx-J→ ja_JP→ Scripts→

    Startup Scripts 名のフォルダを作り、ここへ保存


対象アプリの文字列を調べる
  1. 対象アプリケーションとAdobe ExtendScript Toolkit CC(以下ESTK)を起動
  2. ESTKで対象アプリケーションを指定
    (ドキュメントの左上→ プルダウンリスト)
  3. 新規ドキュメント(ソース)に下記をコピペ、(メニュー)デバッグ→実行

     $.writeln(BridgeTalk.appSpecifier)
    

    デバッグ→ 実行)

  4. (メニュー)ウインドウ→ JavaScriptコンソール展開

  5. アプリバージョン箇所をコピー、最初の記述内 〓 に差し替え、上書き保存
    例:["InDesign CC 2020","indesign-15.064"],

    文字列が分かれば、もうこのソース.jsxは不要です。


ESTKを入れられなかった人は、メモ帳などで
$.writeln を
alert に差し替えてScript Panelフォルダへ保存。拡張子を(.jsx)にリネームしInDesignスクリプトパネルから実行、アラートで出た名称を記述内に記入して下さい。雑説明


InDesignを再起動して、運用してみましょう

(いぇあー)

編集ツール→ その他メニューに、任意のAdobeアプリケーションが追加されましたー

※リンクパネルの同機能に反映・応用はできません


基本機能と違い、編集後リンクバッジのクリックが必要になりますが、なに、そのくらいの手間は甘んじましょう。

これでまたひとつ、InDesignをアナタ色に染める事ができました!

※そう、このコメントを送ったのは私でした

Windowsから見えるMacの不可視ファイルを一括削除

※〜MacOS 10.6〜10.14且つHFS+(Mac OS拡張ジャーナリング1 限定。10.15及びAPFSは手元に環境がない為、カスを吐くのか現時点では検証できません(2020.10)

※当方紙媒体DTP戦士なため、基本的に最新OSの運用は致しません。ご了承下さい。

Automator内の説明・記述を再度修正しました orz(2020.11.3)
サポートのHARMAN移管に伴い、Adobe AIR配布Link先を修正しました(2021.3.9)


NASもしくはUSBメモリーなどで、Windowsと直接生データの遣り取りをしている方。

Macからは見えない、先頭が「._」で始まる謎のデータが発生

WindowsLinux側からはこういったデータが見えていて、知らずに相手方(もしくはサーバ管理者)に迷惑をかけているかもしれません。事前にMac側から消しておいてあげましょう。まあ目障りなだけで、然程実害ないんですが。 ただプログラムがコレも数としてカウントしてしまうので、困る事はあります

MacからのNAS(smb)接続でデータコピーや移動に失敗したり、互換USBメモリFAT32exFATボリューム)のイジェクトに失敗するのは、この見えないカスが影響している可能性もあります。試してみて下さい。

これらは俗にAppleDouble 2(のカケラ)、リソースフォークなどと呼ばれます。面倒なので説明はWiki先生に任せて← まず結論から、削除方法。


NAS or 互換USBメモリーに上げた後のフォルダに対して処理して下さい。 それ以前、リソースフォーク生成前には意味ありません。発生条件は下に記載します

MacOS(~10.14)側から削除

Automatorに登録

  1. Automatorを起動、新規「サービス」選択

  2. 検索「シェル」→ 「シェルスクリプトを実行」をつかみ、右へドラッグ

  3. 次の選択項目を受け取る:フォルダ
    検索対象:Finder
    シェル:/bin/bash
    入力の引き渡し方法:引数として

  4. 記述「do ~ done」の間に、下記コマンドを入力

     find "$f" \( -name '.DS_Store' -or -name '._*' -or -name '.Bridge*' -or -name 'Thumbs.db' \) -delete -print
    

  5. 検索窓に「リスト」→ 出てきた「リストから選択」を右下へドラッグ→ メッセージに文言を入力(削除されたファイル)
    リストから選択→ シェルスクリプトの下へドラッグ

  6. 名前をつけて保存。

    ここに保存される(ユーザ→ [ユーザー名]→ ライブラリ→ Services

    これで登録完了。


削除の実行

  1. 対象フォルダを右クリック→ サービス

    先ほど作った設定を選択

  2. find( )の条件(名称指定)で見つかった削除リストが表示される

    ※このウインドウが出る前にもうdelete済みなので、ここで実行・拒否を選びたい場合は構造と記述を少し変えないといけません(面倒臭い)← 

  3. →OKで閉じる。


ターミナルからの直接実行も可能ですが、パス指定の楽な乙女ちゃんの方が断然お勧め。

シェルスクリプト部分は、ここまで冗長でない

dot_clean --keep=dotbar "$f"

※通常ターミナルでは最後を対象フルパス or .(ピリオド=今いる場所) と書きますが、Automatorでは最初に for f in "$@"と変数宣言する様です

とするやり方もありますが、どうもデータフォーク側にも影響があるようで、新規保存し直すまで一部アプリでサムネイルが見えなくなります。やめておいた方が無難。

ドキュメントアイコンが半透明に

Bridgeウインドウ内で見えない

カスどもが確実に消えたかどうかMac OS GUI上から視認する事はできないので、ターミナルから

find [フォルダをターミナルウィンドウにドロップ] \( -name '.*' -or -name 'Thumbs.db' \) -print

→enter で確認してみましょう。 ※スクエアブラケット[]はトル

※フルパスの中にスペースがある場合、フォルダードロップではなく、
対象を右クリック→ パスをコピー→ 記述「find(半角スペース)」の後にカーソルを立て、(ターミナルメニュー)編集→「テキストをエスケープしてペースト」
で指定して下さい。

・・・USBメモリーの

.fseventsd .Spotlight-V100 .Trashes

を消していないのは分かると思いますが、これらは互換ドライブがマウントしただけでMacOSが生成する性質なためMac側から消す意味がなく、Windows上で手動削除するしかありません ←

この3つは削除してなんの問題もありませんが、Macからマウントするたびに復活します。


デキる人であれば、cronKeyboard Maestro[^3] などで自動削除スケジュールが作れると思いますが、後述の様にclientでの大量処理は負荷がキツい以上、狭い範囲の固定ディレクトリに対してのスケジュールでは、あまり意味ないのではないかと。そういう処理はサーバ側に組ませる方がいいと思います。

[^3]: Mac用キーボードユーティリティ。有償 Keyboard Maestro


ネット上でこの削除方法を探すと、'.AppleDouble' 指定のみのものをよく見ますが、複数の環境で試していずれも失敗しました。 ※10.10、10.14で検証

例え属性指定できたとしても、消さない方がいい種類のある可能性もあるので、愚直に名称でひとつひとつ指定した方がいいのではないかなと、私は思ってます。

因みにNASの場合、AFP(Apple Filing Protocol)[^4] 接続する事でAppleDoubleリソースフォーク生成(分離)は回避できます。afp対応しないnetatalk 3.x[^5] 以外のNASでは不可。NAS以外の事情は知りません

将来的にAppleが悔い改めデータフォーマットを見直す時が来れば、これらは解消するのかもしれません。 apfsはどうなってますのやろ

[^4]: AFP Wikipedia

[^5]: netatalk Wikipedia


「ネットワークボリューム・USBメモリーに最初から.DS_Storeを作らない方法(コマンド)」は広く紹介されていますが(※Macボリューム上は不可能)、AppleDouble(リソースフォーク)及び「. fseventsd .Spotlight-V100 .Trashes」を作らない方法というのは、理論上不可能。ですよね


Windowsから削除

コマンドプロントから「.AppleDouble」で削除するエントリーを見かけましたが、私が検証した限りではPowerShellコマンドプロンプトは、例え名称決め打ち指定であっても、CUI上でApple独自のリソースフォークを認識できない様です。何かしらやりようはあるんでしょうか。

GUI側ではしっかり選択・deleteできるクセに、、

Mac OSと同様に他言語からの削除はできますが、まだアプリ化する能力が私にはない為、今回は断念。  ESTKだとドキュメント・フォルダ両方削除できる再帰処理がちっと面倒だった← のもあるし、わざわざESTK起動してパスを選択しにいって、、あまり効率的ではありませんよね

なので、Windowsではカス削除くんを利用するのが一番手っ取り早いです。

カス削除くんのインストール・実行

カス削除くん

Adobe AIR(Runtime)必須。

※カス削除くん公式内のAdobe AIRはリンク切れになっています。
Adobe AIRは、2021.1よりサポート及び開発をHARMANに移管しました。2021.3.8現在

フォルダをドロップ→ カスファイルを削除する

カス削除くんMacでは、AppleDoubleカスを消す事はできませんMacからは、先に説明したAutomatorかターミナルコマンドを。

更に、ご覧になって分かるように.fseventsd .Spotlight-V100 .Trashesには対応していません←←

この3つは手動で削除して下さい、、


不可視ファイル類が発生する条件:


注意事項(共通)

  • ボリューム丸ごと突っ込まない 数が多いと処理しきれません

  • ボリューム直下・ユーザーディレクトリ直下を丸ごと突っ込まない 必須不可視データまで消してしまう危険が(あるかもしれない)


不可視ファイルの種類(削除可)

  • .DS_Store
    Winのdesktop.iniと同等。手動配置の位置、ウインドウサイズ、アイコンサイズ等、フォルダオプション情報を記録。Macデスクトップ上以外は消してOK

  • ._.DS_Store
    .DS_Store自体をMacOS側から他へコピーした事で、そのリソースフォークとして作られたもの(多分)

  • .fseventsd
    MacOSのFile System Event log。ファイルが作成、変更、または削除されるたびに通知され、実行中のMacプログラムが情報を知るために参照する

  • .Spotlight-V100
    スポットライトインデックス(database)
    MacOSが検索するためのインデックスを作成する …そういえば、これを今後作成しないターミナルコマンドが確かありましたよね

  • .Trashes
    MacOS固有の「仮ゴミ箱」システム。

  • Thumbs.db
    Windows上のアイコンプレビューを高速化するためのキャッシュ。

捨てない方がいい不可視ファイル

  • .localized
    (カラム・アイコン表示以外で)フォルダ・データ名の日本語表示に必要

  • デスクトップ上の.DS_Store
    アイコン表示での配置・アイコン等の情報が初期化されます

  • Windowsデスクトップ上のdesktop.ini
    Winのデスクトップ情報。表示オプション→ 表示→ 保護されたオペレーティングシステムファイルを表示しない→ OFF で見える(非推奨)


最後に

何か間違えてたら、ご指摘お願いします←

ちゃんとエディタでチェックしてないので、脚注3以降の表示がおかしい・・(泣

11.30 追記

次期MacOSではAFPを切り捨て、SMB接続に絞る様ですね。

カス問題も、そちらに合う様にデータ構造が改良されるのでしょう。まだまだ読めませんが。


  1. ディスクユーティリティでフォーマットできるファイル・システム・フォーマット Appleサポート

  2. AppleSingleとAppleDouble Wikipedia