Skip to main content
dtpShibaInu
Participating Frequently
September 3, 2024
Answered

JavaScriptで孫以下までパッケージ

  • September 3, 2024
  • 4 replies
  • 2985 views

作業環境:Mac OS X 12.7.1_InDesign CC2023

 

【概要】

InDesignCCから搭載されているパッケージ機能では孫画像(AIやPSD等のリンクにリンクされているデータ)が収集出来ないという問題があります。これを回避する為にJavaScriptでデータを集められないか試しているところです。

 

【問題点】

データを移動させる時に更新日時が「移動した日」になってしまう。

 

【改善したい点】

・更新日時を変更せずに移動させたい

・コピーが出来たら完璧

 

【現状】

添付してあるテキストが「.jsx」の全文となりますが、問題となっている部分を此処に記述していきます。(実際のスクリプトではスプレッドを細切れに分けたりなどの作業が入りますのであくまでパッケージのみの範囲をピックアップしています)

// フォントのコピー関数
function copyFonts(sourceFontsFolder, saveFolder) {
    var fontsFiles = sourceFontsFolder.getFiles();
    if (fontsFiles.length === 0) return;
    var fontsFolder = new Folder(saveFolder + "/Document fonts");
    if (!fontsFolder.exists) fontsFolder.create();
    for (var i = 0; i < fontsFiles.length; i++) {
        var fontFile = fontsFiles[i];
        if (fontFile instanceof File) {
            try {
                fontFile.copy(new File(fontsFolder + "/" + fontFile.name));
            } catch (e) {
                errorLog.writeln("フォントのコピー中にエラーが発生しました: " + fontFile.name + " - エラー: " + e.message);
            }
        }
    }
}

// リンクの収集関数
function collectLinks(docFile, saveFolder) {
var doc;
    try {
        doc = app.open(docFile);
    } catch (e) {
        errorLog.writeln("リンク収集ドキュメントのオープン中にエラーが発生しました: " + docFile.name + " - エラー: " + e.message);
        return;
    }
    var links = doc.links;
    if (links.length === 0) {
        doc.close(SaveOptions.NO);
        return;
    }
    var linksFolder = new Folder(saveFolder + "/Links");
    if (!linksFolder.exists) linksFolder.create();
    var collectedLinks = {};
    for (var i = 0; i < links.length; i++) {
        var link = links[i];
        var sourceFile = new File(link.filePath);
        if (sourceFile.exists) {
            processLink(sourceFile, link.name, linksFolder, collectedLinks);
        } else {
            errorLog.writeln("リンクが見つかりません: " + link.filePath);
        }
    }
doc.close(SaveOptions.NO);
}
function processLink(fileObj, linkName, linksFolder, collectedLinks) {
    if (collectedLinks[linkName]) return;
    collectedLinks[linkName] = true;
    var originalDate = fileObj.modified;
    var destFile = new File(linksFolder + "/" + linkName);
    try {
        fileObj.copy(destFile);
        collectedLinks[linkName] = true;
        var subLinks = getLinks(destFile.fsName);
        for (var j = 0; j < subLinks.length; j++) {
            var subLinkName = subLinks[j];
            if (!collectedLinks[subLinkName]) {
                var subLinkFile = new File(fileObj.path + "/" + subLinkName);
                if (subLinkFile.exists) {
                    processLink(subLinkFile, subLinkName, linksFolder, collectedLinks);
                }
            }
        }
        updateLinkPath(fileObj, destFile.fsName);
        destFile.modified = originalDate;
    } catch (e) {
        $.writeln("リンクの処理エラー: " + e.message);
    }
}
// 無駄な抵抗_リンクの更新
function updateLinkPath(fileObj, newPath) {
    try {
        var doc = app.activeDocument;
        var links = doc.links;
        for (var i = 0; i < links.length; i++) {
            if (links[i].filePath === fileObj.fsName) {
                links[i].relink(new File(newPath));
                links[i].update();
            }
        }
    } catch (e) {
        $.writeln("リンクパスの更新エラー: " + e.message);
    }
}

function getLinks(fls) {
    var prop = "Manifest";
    var ns = "http://ns.adobe.com/xap/1.0/mm/";
    if (typeof xmpLib === 'undefined') {
        var xmpLib = new ExternalObject('lib:AdobeXMPScript');
    }
    var xmpFile = new XMPFile(fls, XMPConst.UNKNOWN, XMPConst.OPEN_FOR_READ);
    var xmpPackets = xmpFile.getXMP();
    var xmp = new XMPMeta(xmpPackets.serialize());
    var str = "";
    var result = [];
    for (var i = 1; i <= xmp.countArrayItems(ns, prop); i++) {
        str = xmp.getProperty(ns, prop + "[" + i + "]/stMfs:reference/stRef:filePath").toString();
        result.push(str.slice(str.lastIndexOf("/") + 1));
    }
    return result;
}

 

【現実的な解決案の候補】

1:JavaScriptのpackageforprint にてまるごとパッケージ、データのxmpを参照して孫以降のデータのみを移動(更新日時が最新になってしまう事には目をつむる)

2:AppleScriptにてBridgeTalk を経由して移動させる(corecaraさん  のdtp helper 参考)

3:xmpより更新日時情報を得て、移動先で更新日時の情報を変更させる

4:孫以下の一覧を出して手動で移動

 

現状BridgeTalkでしか更新日時を変更せずに移動できなさそう(そもそも移動やコピーという行為自体が変更日時に引っ掛かるのでどうにもならなさそう)ではないかと思っております。

もし、どなたかBridgeTalkなしに移動させる方法などを知っている方がいたら教えていただきたいと思い書かせていただきました。kekaなどの解凍アプリだと更新日時をそのままに移動(?)出来るのでその応用が出来たら一番なのですが…ここの更新日時周りの記述に悩みます。

 

最有力候補はBridgeTalkなのですが…勉強出来る場所や情報などが載っているサイトなどをご存じの方がいらっしゃれば教えていただけると幸いです。

Correct answer kawamoto_α

更新日時が変わるのはFileオブジェクトのcopyメソッドの残念な仕様で、ExtendScript内ではどうしようもないと思っていたのですが、Ten Aさんがそれを覆す、すごい方法を教えてくれていますね。たとえばこんなコードでファイルのコピーができます。

copyFile("~/desktop/a.jpg","~/desktop/a_.jpg")
function copyFile(moto,saki){
    var d1=app.documents.add();
    var p=d1.spreads[0].place(File(moto));
    p[0].itemLink.copyLink(File(saki));
    d1.close(SaveOptions.NO);
}


とはいえ処理が重くなりそうなので、できることならAppleScriptやVBScriptと連携するのがいちばんだと思います。InDesignでExtendScriptからAppleScriptを呼び出すのはBridgeTalkではなくapp.doScriptです

4 replies

dtpShibaInu
Participating Frequently
September 13, 2024

簡易ですが完成形をあげておきます

デスクトップにLinksフォルダを作成します

https://github.com/dtpShibainu/dtpShiba.git

Participating Frequently
January 9, 2025

初めまして、突然振られた仕事のインデザインで作成しているデータの管理が酷く、インデザインに配置したイラストレータの画像(孫データ)が回収できず悩んでいたところこちらにたどり着きました。

Githubののところでは「本番での運用にはフォントの収集含めてこれを改訂」とありますが本番のスクリプトの公開をされるご予定はありませんでしょうか。

ご検討のほどよろしくお願いいたしまます。

dtpShibaInu
Participating Frequently
February 5, 2025

気づくのが遅くなりもうしわけありません!
私の作成したものは更に改良を加えていて余計な動きが加わっているので、一般公開をするには向いていない形となっております…。
代わりにとなりますが、DTP Script noteさんの以下のScriptなどいかがでしょうか?
孫画像の名前が被ったいた場合の事も考慮されているので使いやすく、動作も簡潔で有料ではある分、いざという時にも作者と連絡が付きやすいのでお勧めです。
https://note.com/yosi2631/n/ne136ea05d54b

Ten A
Community Expert
Community Expert
September 4, 2024

inDesignからだとcopyLinkメソッドを利用すれば任意のパスにFinder上で操作した状態でコピーできるんですけど、元来そういった利用方法を行う為のメソッドではないので色々と調整は必要になります。
ちなみにBridgeTalkはExtendScriptを指定したアプリケーションで実行させる仕組みなのでターゲットアプリケーションを指定してスクリプトを渡すといった流れで処理します。一連の流れは定型なのでGithubとかで検索すれば参考になるものはたくさん見つかるでしょう。
あと、10年以上前に書いたXMP操作関数がそのまま利用され続けているのは感慨深いですね(^-^;

dtpShibaInu
Participating Frequently
September 4, 2024

Tenさんご本人でしたか…!xmp関連は「孫まで収集します。」を参考にさせていただきました。ところどころ記号の類など少し手を加えている部分はあるのですが、シンプルかつわかりやすくて後々からでも応用が利くというところで組み込ませていただいています!

 

実のところGithubは使いこなせておらず、使い方がわかりにくい(情報量の多さ)という大きな壁とぶつかっているところですが、Githubで公開されている「BridgeTalkを使っているスクリプト」を見てみるとAppleScriptに似た何かを感じさせますね。targetからスタートするのは馴染みがあるようでないような…CS時代に時々見かけたような…。

 

見ていて思ったのはBridgeTalkはあくまでアプリケーション同士の橋渡しであってデータの移動は結局の所BridgeTalkでの作業外なのでは…という結論に至っています。BridgeTalkでAppleScriptに渡して移動…?

kawamoto_α
kawamoto_αCorrect answer
Participating Frequently
September 11, 2024

更新日時が変わるのはFileオブジェクトのcopyメソッドの残念な仕様で、ExtendScript内ではどうしようもないと思っていたのですが、Ten Aさんがそれを覆す、すごい方法を教えてくれていますね。たとえばこんなコードでファイルのコピーができます。

copyFile("~/desktop/a.jpg","~/desktop/a_.jpg")
function copyFile(moto,saki){
    var d1=app.documents.add();
    var p=d1.spreads[0].place(File(moto));
    p[0].itemLink.copyLink(File(saki));
    d1.close(SaveOptions.NO);
}


とはいえ処理が重くなりそうなので、できることならAppleScriptやVBScriptと連携するのがいちばんだと思います。InDesignでExtendScriptからAppleScriptを呼び出すのはBridgeTalkではなくapp.doScriptです

ajabon grinsmith
Community Expert
Community Expert
September 3, 2024

どうもどうも。

いちど、一連の流れを日本語で書いてもらったほうが、と思うのですが(たぶんそれが必要なのは自分だけなのでいいです)

 

対象indd上のリンクでループ

 リンクの情報を取得する関数 *

 リンクの形式が .aiならIllustratorで開く(BridgeTalk)

   関数 * に再帰

  InDesignに返す

 }

}

みたいな感じですかね?

「移動」「コピー」が散見されますが、標準機能のパッケージはIdもAiもすべてリンクファイルを「複製」(コピー)で集めます。

今回はそこをあえて「移動」でやりたい感じでしょうか?(難しそう)

dtpShibaInu
Participating Frequently
September 3, 2024

Link周りがごちゃっとしていて読みづらいですよねー…わかります。

 

JSのみだと…
 格納フォルダ作成
 格納フォルダにLinks、Document fontsフォルダを作成
 font移動(複製)
 indd移動(複製)
リンクをLinksへ移動(複製)させる関数●1
xmpを参照してLinksへ移動(複製)させる関数●2
 (inddを開いてリンク上でループ){
  if{リンクが.aiか.psdの時 ●2
  }そうでない時 ●1
}

 

BridgeTalk入りだと…
とりあえずパッケージ(packageforprint)
 リンクの情報を取得する関数○1
 (inddを開いてリンク上でループ){
  if{リンクが.aiか.psdの時 ○1(BridgeTalkでLinksへ複製)
}

言語化できているかは不安ですがやりたいことは上記のような形です。

 

現状、作成しているのは「JSのみだと…」の方ですが、BridgeTalkの方を使って楽したい…というのが目的の一つでもあります。

 

移動またはコピーと言っているのは「複製」が頭から抜け落ちていた為ですね…!!
データをパッケージする為の関数は移動もまとめて「packageforprint」という定義だけで具体的にどうやって複製しているのか謎でした…。

改めて複製って定義(型)であるのですか…?

ajabon grinsmith
Community Expert
Community Expert
September 4, 2024

パッケージ処理は一般に

・リンク(とフォント)の複製による収集

・収集済みファイルへの再リンク

が行われるので(しなくもできますが、やる前提で)、

InDesignのpackageForPrint および Illustratorの「パッケージ」で末端までやるとなると

子孫→親 の順でやっていかないといけないんですかねえ。

dtpShibaInu
Participating Frequently
September 3, 2024

一応ですがテスト用のファイルも置いておきます。

フォントはライセンスに引っ掛かるのを回避するためにあえて付けておりません

Linksフォルダに各.aiを置いてお使いください(親>子>孫の順番にリンクさせています)

「ブリの見分けがつかない.zip(2024.9.3時点〜100日間保管)」

https://27.gigafile.nu/1212-b774c5914f8f44083e57b3f3e2bd07fc4