layoutbridge-spm 0.0.1 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +171 -0
- package/LICENSE +26 -0
- package/README.de.md +318 -0
- package/README.md +304 -4
- package/THIRD-PARTY-NOTICES.md +2878 -0
- package/dist/src/mcp/config.js +125 -0
- package/dist/src/mcp/dispatch.js +123 -0
- package/dist/src/mcp/license/free-tools.js +16 -0
- package/dist/src/mcp/license/gate.js +209 -0
- package/dist/src/mcp/license/index.js +96 -0
- package/dist/src/mcp/license/instance-name.js +56 -0
- package/dist/src/mcp/license/key-source.js +58 -0
- package/dist/src/mcp/license/lemonsqueezy-verifier.js +207 -0
- package/dist/src/mcp/license/placeholder-verifier.js +10 -0
- package/dist/src/mcp/license/polar-ids.js +63 -0
- package/dist/src/mcp/license/polar-verifier.js +265 -0
- package/dist/src/mcp/license/product-ids.js +72 -0
- package/dist/src/mcp/license/state-store.js +91 -0
- package/dist/src/mcp/license/types.js +11 -0
- package/dist/src/mcp/logging.js +270 -0
- package/dist/src/mcp/product-info.js +48 -0
- package/dist/src/mcp/server.js +250 -0
- package/dist/src/mcp/setup.js +608 -0
- package/dist/src/mcp/start.cjs +95 -0
- package/dist/src/mcp/tool-definition.js +2 -0
- package/dist/src/mcp/tools.js +2004 -0
- package/dist/src/mcp/typography-rules.js +70 -0
- package/dist/src/transport/com.js +250 -0
- package/dist/src/transport/osascript.js +171 -0
- package/dist/src/transport/queue.js +19 -0
- package/dist/src/transport/script-bundle.js +92 -0
- package/dist/src/transport/transport.js +30 -0
- package/indesign/commands/10-app.js +6 -0
- package/indesign/commands/20-documents.js +513 -0
- package/indesign/commands/22-document-setup.js +118 -0
- package/indesign/commands/23-save-package.js +255 -0
- package/indesign/commands/25-export.js +379 -0
- package/indesign/commands/26-export-image.js +197 -0
- package/indesign/commands/27-textdefaults.js +151 -0
- package/indesign/commands/28-selection.js +174 -0
- package/indesign/commands/30-pages.js +1032 -0
- package/indesign/commands/31-view.js +210 -0
- package/indesign/commands/32-sections.js +203 -0
- package/indesign/commands/35-parents.js +428 -0
- package/indesign/commands/37-layout.js +760 -0
- package/indesign/commands/40-frames.js +836 -0
- package/indesign/commands/41-shapes.js +505 -0
- package/indesign/commands/42-groups.js +117 -0
- package/indesign/commands/43-layers.js +291 -0
- package/indesign/commands/44-effects.js +274 -0
- package/indesign/commands/45-frame-options.js +247 -0
- package/indesign/commands/47-anchored.js +287 -0
- package/indesign/commands/50-modify.js +781 -0
- package/indesign/commands/52-align.js +139 -0
- package/indesign/commands/55-fit.js +106 -0
- package/indesign/commands/60-images.js +771 -0
- package/indesign/commands/62-embed.js +120 -0
- package/indesign/commands/69-placeholders.js +127 -0
- package/indesign/commands/70-text.js +567 -0
- package/indesign/commands/71-outlines.js +92 -0
- package/indesign/commands/72-place-text.js +366 -0
- package/indesign/commands/74-stories.js +116 -0
- package/indesign/commands/75-tables.js +676 -0
- package/indesign/commands/76-text-variables.js +260 -0
- package/indesign/commands/77-story-options.js +86 -0
- package/indesign/commands/78-frame-lines.js +304 -0
- package/indesign/commands/79-check-typography.js +303 -0
- package/indesign/commands/80-styles.js +1620 -0
- package/indesign/commands/81-composition.js +355 -0
- package/indesign/commands/82-object-styles.js +263 -0
- package/indesign/commands/83-indents-tabs.js +237 -0
- package/indesign/commands/84-import-styles.js +142 -0
- package/indesign/commands/85-swatches.js +112 -0
- package/indesign/commands/86-gradients.js +185 -0
- package/indesign/commands/87-replace-swatch.js +180 -0
- package/indesign/commands/88-replace-font.js +217 -0
- package/indesign/interpreter.js +758 -0
- package/package.json +55 -6
- package/rules/typography-rules.json +31 -0
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Auftrag A-9.2 (Sitzung 9) – replace_swatch: alle Verwendungen eines
|
|
3
|
+
* Farbfelds auf ein anderes umstellen und das alte entfernen (InDesign
|
|
4
|
+
* "Farbfeld loeschen ... ersetzen durch"). Adobe-DOM (geprueft 05.09.2026):
|
|
5
|
+
* Swatch.remove(replacingWith) – InDesign stellt Flaechen, Konturen, Text,
|
|
6
|
+
* Formate, Tabellen und Verlaeufe selbst um. Ohne delete_old: Text ueber
|
|
7
|
+
* die Suchen/Ersetzen-Klammer (FindTextPreference.fillColor), Objekte
|
|
8
|
+
* ueber allPageItems, Absatz- und Zeichenformate direkt; Objektformate,
|
|
9
|
+
* Tabellenformate und Verlaufsstopps bleiben dann beim alten Feld (Warnung).
|
|
10
|
+
* Verlaufsfarbfelder (A-8.4) sind als Quelle und Ziel zulaessig: InDesign
|
|
11
|
+
* ersetzt sie wie Farben; ein Verlauf als Ziel eines Textlaufs ist ein
|
|
12
|
+
* Verlaufstext.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
function idcSwatchRef(doc, args, nameKey, idKey, what) {
|
|
16
|
+
var hasName = idcGiven(args[nameKey]);
|
|
17
|
+
var hasId = idcGiven(args[idKey]);
|
|
18
|
+
var swatch = null, i, list;
|
|
19
|
+
if (hasName === hasId) {
|
|
20
|
+
IDC.fail('invalid_argument', 'Pass exactly one of ' + nameKey + ' and ' + idKey + ' for the ' + what + ' swatch.', null);
|
|
21
|
+
}
|
|
22
|
+
if (hasName) {
|
|
23
|
+
swatch = idcSwatchByName(doc, args[nameKey]);
|
|
24
|
+
if (swatch === null) {
|
|
25
|
+
IDC.fail('not_found', 'Swatch "' + args[nameKey] + '" not found – names are exact (see list_swatches).', { swatch_name: args[nameKey] });
|
|
26
|
+
}
|
|
27
|
+
return swatch;
|
|
28
|
+
}
|
|
29
|
+
try {
|
|
30
|
+
list = doc.swatches;
|
|
31
|
+
for (i = 0; i < list.length; i++) {
|
|
32
|
+
if (Number(list.item(i).id) === Number(args[idKey])) { return list.item(i); }
|
|
33
|
+
}
|
|
34
|
+
} catch (e) { /* nicht gefunden */ }
|
|
35
|
+
IDC.fail('not_found', 'No swatch with ' + idKey + ' ' + args[idKey] + ' (see list_swatches).', { swatch_id: args[idKey] });
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function idcDescribeSwatchShort(swatch) {
|
|
40
|
+
var out = { name: null, swatch_id: null, kind: null, space: null, values: [] };
|
|
41
|
+
try { out.name = String(swatch.name); } catch (e0) { /* null */ }
|
|
42
|
+
try { out.swatch_id = Number(swatch.id); } catch (e1) { /* null */ }
|
|
43
|
+
out.kind = idcSwatchKind(swatch);
|
|
44
|
+
try { out.space = idcColorSpaceName(swatch.space); } catch (e2) { out.space = null; }
|
|
45
|
+
try { out.values = idcNumberList(swatch.colorValue); } catch (e3) { out.values = []; }
|
|
46
|
+
return out;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function idcSwatchIs(value, swatch) {
|
|
50
|
+
try { return value !== null && value !== undefined && Number(value.id) === Number(swatch.id); } catch (e) { return false; }
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/* Verwendungen eines Farbfelds zaehlen; Tabellen werden nicht gezaehlt (null). */
|
|
54
|
+
function idcSwatchUsage(doc, swatch, args) {
|
|
55
|
+
var out = { text_runs: 0, fills: 0, strokes: 0, paragraph_styles: 0, character_styles: 0, object_styles: 0, tables: null, gradients: 0 };
|
|
56
|
+
var items, i, item, styles, found;
|
|
57
|
+
try { items = doc.allPageItems; } catch (e0) { items = []; }
|
|
58
|
+
for (i = 0; i < items.length; i++) {
|
|
59
|
+
item = IDC.concrete(items[i]);
|
|
60
|
+
try { if (idcSwatchIs(item.fillColor, swatch)) { out.fills += 1; } } catch (e1) { /* kein fillColor */ }
|
|
61
|
+
try { if (idcSwatchIs(item.strokeColor, swatch)) { out.strokes += 1; } } catch (e2) { /* kein strokeColor */ }
|
|
62
|
+
}
|
|
63
|
+
styles = idcAllStyles(doc, 'paragraph');
|
|
64
|
+
for (i = 0; i < styles.length; i++) { try { if (idcSwatchIs(styles[i].fillColor, swatch)) { out.paragraph_styles += 1; } } catch (e3) { /* weiter */ } }
|
|
65
|
+
styles = idcAllStyles(doc, 'character');
|
|
66
|
+
for (i = 0; i < styles.length; i++) { try { if (idcSwatchIs(styles[i].fillColor, swatch)) { out.character_styles += 1; } } catch (e4) { /* weiter */ } }
|
|
67
|
+
try {
|
|
68
|
+
for (i = 0; i < doc.allObjectStyles.length; i++) {
|
|
69
|
+
item = doc.allObjectStyles[i];
|
|
70
|
+
try { if (item.enableFill === true && idcSwatchIs(item.fillColor, swatch)) { out.object_styles += 1; } } catch (e5) { /* weiter */ }
|
|
71
|
+
try { if (item.enableStroke === true && idcSwatchIs(item.strokeColor, swatch)) { out.object_styles += 1; } } catch (e6) { /* weiter */ }
|
|
72
|
+
}
|
|
73
|
+
} catch (e7) { /* keine Objektformate */ }
|
|
74
|
+
idcEachIn(doc, 'gradients', function (gradient) {
|
|
75
|
+
var stops, k;
|
|
76
|
+
try {
|
|
77
|
+
stops = gradient.gradientStops;
|
|
78
|
+
for (k = 0; k < stops.length; k++) { if (idcSwatchIs(stops.item(k).stopColor, swatch)) { out.gradients += 1; } }
|
|
79
|
+
} catch (e8) { /* weiter */ }
|
|
80
|
+
});
|
|
81
|
+
/* Textlaeufe ueber die Suche (dry run): fillColor in findTextPreferences. */
|
|
82
|
+
try {
|
|
83
|
+
app.findTextPreferences = NothingEnum.NOTHING;
|
|
84
|
+
app.changeTextPreferences = NothingEnum.NOTHING;
|
|
85
|
+
idcSetFindOptions(app.findChangeTextOptions, { include_master_pages: true, include_hidden_layers: true, include_locked_layers: args.include_locked_layers === true });
|
|
86
|
+
app.findTextPreferences.fillColor = swatch;
|
|
87
|
+
found = doc.findText();
|
|
88
|
+
out.text_runs = found.length;
|
|
89
|
+
} catch (e9) {
|
|
90
|
+
out.text_runs = null;
|
|
91
|
+
} finally {
|
|
92
|
+
try { app.findTextPreferences = NothingEnum.NOTHING; } catch (e10) { /* egal */ }
|
|
93
|
+
try { app.changeTextPreferences = NothingEnum.NOTHING; } catch (e11) { /* egal */ }
|
|
94
|
+
}
|
|
95
|
+
return out;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/* Verwendungen ohne Loeschen umstellen (delete_old false). */
|
|
99
|
+
function idcReassignSwatch(ctx, doc, oldSwatch, newSwatch, args) {
|
|
100
|
+
var items, i, item, styles, changed = { text_runs: 0, fills: 0, strokes: 0, paragraph_styles: 0, character_styles: 0 };
|
|
101
|
+
try { items = doc.allPageItems; } catch (e0) { items = []; }
|
|
102
|
+
for (i = 0; i < items.length; i++) {
|
|
103
|
+
item = IDC.concrete(items[i]);
|
|
104
|
+
try { if (idcSwatchIs(item.fillColor, oldSwatch)) { item.fillColor = newSwatch; changed.fills += 1; } } catch (e1) { /* weiter */ }
|
|
105
|
+
try { if (idcSwatchIs(item.strokeColor, oldSwatch)) { item.strokeColor = newSwatch; changed.strokes += 1; } } catch (e2) { /* weiter */ }
|
|
106
|
+
}
|
|
107
|
+
styles = idcAllStyles(doc, 'paragraph');
|
|
108
|
+
for (i = 0; i < styles.length; i++) { try { if (idcSwatchIs(styles[i].fillColor, oldSwatch)) { styles[i].fillColor = newSwatch; changed.paragraph_styles += 1; } } catch (e3) { /* weiter */ } }
|
|
109
|
+
styles = idcAllStyles(doc, 'character');
|
|
110
|
+
for (i = 0; i < styles.length; i++) { try { if (idcSwatchIs(styles[i].fillColor, oldSwatch)) { styles[i].fillColor = newSwatch; changed.character_styles += 1; } } catch (e4) { /* weiter */ } }
|
|
111
|
+
try {
|
|
112
|
+
app.findTextPreferences = NothingEnum.NOTHING;
|
|
113
|
+
app.changeTextPreferences = NothingEnum.NOTHING;
|
|
114
|
+
idcSetFindOptions(app.findChangeTextOptions, { include_master_pages: true, include_hidden_layers: true, include_locked_layers: args.include_locked_layers === true });
|
|
115
|
+
app.findTextPreferences.fillColor = oldSwatch;
|
|
116
|
+
app.changeTextPreferences.fillColor = newSwatch;
|
|
117
|
+
changed.text_runs = doc.changeText().length;
|
|
118
|
+
} catch (e5) {
|
|
119
|
+
ctx.warn('Text runs could not be changed by search: ' + String(e5.message ? e5.message : e5));
|
|
120
|
+
} finally {
|
|
121
|
+
try { app.findTextPreferences = NothingEnum.NOTHING; } catch (e6) { /* egal */ }
|
|
122
|
+
try { app.changeTextPreferences = NothingEnum.NOTHING; } catch (e7) { /* egal */ }
|
|
123
|
+
}
|
|
124
|
+
return changed;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
IDC.register('replace_swatch', { needs_document: true, read_only: false, ruler: 'none' },
|
|
128
|
+
function (ctx) {
|
|
129
|
+
var args = ctx.args;
|
|
130
|
+
var doc = ctx.doc;
|
|
131
|
+
var deleteOld = args.delete_old !== false;
|
|
132
|
+
var dryRun = args.dry_run === true;
|
|
133
|
+
var oldSwatch = idcSwatchRef(doc, args, 'old_name', 'old_swatch_id', 'old');
|
|
134
|
+
var newSwatch = idcSwatchRef(doc, args, 'new_name', 'new_swatch_id', 'new');
|
|
135
|
+
var oldInfo = idcDescribeSwatchShort(oldSwatch);
|
|
136
|
+
var newInfo = idcDescribeSwatchShort(newSwatch);
|
|
137
|
+
var usage, deleted = false, reassigned = null, remaining = null;
|
|
138
|
+
|
|
139
|
+
if (oldInfo.name === null || oldInfo.name.charAt(0) === '[' || oldInfo.name === 'None' || oldInfo.name === 'Paper' || oldInfo.name === 'Black' || oldInfo.name === 'Registration') {
|
|
140
|
+
IDC.fail('invalid_argument', 'Built-in swatch "' + oldInfo.name + '" cannot be replaced.', { old: oldInfo });
|
|
141
|
+
}
|
|
142
|
+
if (oldInfo.swatch_id === newInfo.swatch_id) {
|
|
143
|
+
IDC.fail('invalid_argument', 'old and new name the same swatch "' + oldInfo.name + '".', { old: oldInfo });
|
|
144
|
+
}
|
|
145
|
+
if (oldInfo.space !== null && newInfo.space !== null && oldInfo.space !== newInfo.space) {
|
|
146
|
+
ctx.warn('Colour space changes from ' + oldInfo.space + ' to ' + newInfo.space + ' – this is no colour management; the printed colour may differ. Check the values with list_swatches.');
|
|
147
|
+
}
|
|
148
|
+
usage = idcSwatchUsage(doc, oldSwatch, args);
|
|
149
|
+
if (usage.text_runs === null) { ctx.warn('Text runs could not be counted by search; the other counts are complete.'); }
|
|
150
|
+
|
|
151
|
+
if (!dryRun) {
|
|
152
|
+
if (deleteOld) {
|
|
153
|
+
try {
|
|
154
|
+
oldSwatch.remove(newSwatch);
|
|
155
|
+
deleted = true;
|
|
156
|
+
} catch (e) {
|
|
157
|
+
IDC.fail('invalid_state', 'InDesign refused to remove swatch "' + oldInfo.name + '" (used as a base for a mixed ink or gradient?): ' + String(e.message ? e.message : e), { old: oldInfo });
|
|
158
|
+
}
|
|
159
|
+
} else {
|
|
160
|
+
reassigned = idcReassignSwatch(ctx, doc, oldSwatch, newSwatch, args);
|
|
161
|
+
if (usage.object_styles > 0 || usage.gradients > 0) {
|
|
162
|
+
ctx.warn('Without delete_old, ' + usage.object_styles + ' object style use(s) and ' + usage.gradients + ' gradient stop(s) keep the old swatch; table styles are not checked. Use delete_old true to let InDesign replace everything.');
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
ctx.changes = { modified_document_ids: [Number(doc.id)] };
|
|
166
|
+
if (deleted) { ctx.changes.removed_swatch_ids = [oldInfo.swatch_id]; }
|
|
167
|
+
}
|
|
168
|
+
try { remaining = Number(doc.swatches.length); } catch (e2) { remaining = null; }
|
|
169
|
+
/* "new" ist in ExtendScript auch als Eigenschaftsname verboten (Live-Fund 05.09.2026) – deshalb ueber die Klammer. */
|
|
170
|
+
var out = {
|
|
171
|
+
old: oldInfo,
|
|
172
|
+
deleted: deleted,
|
|
173
|
+
usage_before: usage,
|
|
174
|
+
reassigned: reassigned,
|
|
175
|
+
remaining_swatches: remaining,
|
|
176
|
+
dry_run: dryRun
|
|
177
|
+
};
|
|
178
|
+
out['new'] = newInfo;
|
|
179
|
+
return out;
|
|
180
|
+
});
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Auftrag A-9.1 (Sitzung 9) – replace_font: eine Schrift dokumentweit
|
|
3
|
+
* ersetzen (InDesign "Schrift suchen/ersetzen") – in Absatz- und
|
|
4
|
+
* Zeichenformaten und in lokaler Formatierung, auf Dokument- und
|
|
5
|
+
* Musterseiten. Lokale Laeufe werden ueber story.textStyleRanges gelesen
|
|
6
|
+
* und je Lauf ueber appliedFont gesetzt (dieselbe Mechanik wie
|
|
7
|
+
* find_font_usage); die Zielschrift muss installiert sein. Adobe-DOM
|
|
8
|
+
* (geprueft 05.09.2026): FindTextPreference.appliedFont/fontStyle waeren
|
|
9
|
+
* der andere Weg; der Lauf ueber die Formatlaeufe zaehlt und lokalisiert
|
|
10
|
+
* dabei gleich und braucht keine Suchklammer.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/* Zielschrift: installiert? Liefert { object, family, style } oder wirft not_found. */
|
|
14
|
+
function idcTargetFont(catalogue, family, style) {
|
|
15
|
+
var name = String(family) + '\t' + String(style);
|
|
16
|
+
var status = idcCatalogueStatus(catalogue, family, style);
|
|
17
|
+
var fontObject = null;
|
|
18
|
+
if (status === null) {
|
|
19
|
+
IDC.fail('not_found', 'Target font "' + family + ' ' + style + '" is not installed.', { to_family: family, to_style: style, available_styles: idcStylesOfFamily(catalogue, family) });
|
|
20
|
+
}
|
|
21
|
+
try {
|
|
22
|
+
fontObject = app.fonts.itemByName(name);
|
|
23
|
+
if (!fontObject || fontObject.isValid !== true) { fontObject = null; }
|
|
24
|
+
} catch (e) { fontObject = null; }
|
|
25
|
+
return { object: fontObject, family: String(family), style: String(style), name: name };
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function idcStoryLocked(doc, story) {
|
|
29
|
+
var containers, i, layer;
|
|
30
|
+
try { containers = story.textContainers; } catch (e0) { return false; }
|
|
31
|
+
for (i = 0; i < containers.length; i++) {
|
|
32
|
+
try { layer = containers[i].itemLayer; if (layer && layer.locked === true) { return true; } } catch (e1) { /* weiter */ }
|
|
33
|
+
}
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/* Bezieht ein Lauf seine Schrift aus einem Absatz- oder Zeichenformat, das ersetzt wird? */
|
|
38
|
+
function idcRunFontFromChangedStyle(range, font, stylesChanged) {
|
|
39
|
+
var i, style, styleFont, name;
|
|
40
|
+
var candidates = [];
|
|
41
|
+
try { candidates.push(range.appliedCharacterStyle); } catch (e0) { /* keins */ }
|
|
42
|
+
try { candidates.push(range.appliedParagraphStyle); } catch (e1) { /* keins */ }
|
|
43
|
+
for (i = 0; i < candidates.length; i++) {
|
|
44
|
+
style = candidates[i];
|
|
45
|
+
if (style === null || style === undefined) { continue; }
|
|
46
|
+
try { name = String(style.name); } catch (e2) { continue; }
|
|
47
|
+
styleFont = idcReadFontLoose(style);
|
|
48
|
+
if (styleFont.family === null || !idcSameFamily(styleFont.family, font.family)) { continue; }
|
|
49
|
+
if (styleFont.style !== null && font.style !== null && !idcSameText(styleFont.style, font.style)) { continue; }
|
|
50
|
+
if (idcStyleInList(stylesChanged, name)) { return true; }
|
|
51
|
+
}
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function idcStyleInList(list, name) {
|
|
56
|
+
var i;
|
|
57
|
+
for (i = 0; i < list.length; i++) { if (list[i].name === name) { return true; } }
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function idcSetFontOn(target, font) {
|
|
62
|
+
if (font.object !== null) { target.appliedFont = font.object; }
|
|
63
|
+
else { target.appliedFont = font.name; }
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
IDC.register('replace_font', { needs_document: true, read_only: false, ruler: 'none' },
|
|
67
|
+
function (ctx) {
|
|
68
|
+
var args = ctx.args;
|
|
69
|
+
var doc = ctx.doc;
|
|
70
|
+
var fromFamily = args.from_family;
|
|
71
|
+
var fromStyle = idcGiven(args.from_style) ? String(args.from_style) : null;
|
|
72
|
+
var toFamily = args.to_family;
|
|
73
|
+
var toStyle = idcGiven(args.to_style) ? String(args.to_style) : null;
|
|
74
|
+
var scope = idcGiven(args.scope) ? String(args.scope) : 'all';
|
|
75
|
+
var includeMasters = args.include_master_pages !== false;
|
|
76
|
+
var includeLocked = args.include_locked_layers === true;
|
|
77
|
+
var dryRun = args.dry_run === true;
|
|
78
|
+
var catalogue, targets = {}, missingStyles = [], stylesChanged = [], runsChanged = 0, charsChanged = 0, storiesTouched = 0;
|
|
79
|
+
var skippedLocked = [], oversetStories = [], remaining = 0, remainingWhere = [];
|
|
80
|
+
var kinds, k, styles, i, font, s, story, storyId, ranges, r, range, touched, length, target, styleName;
|
|
81
|
+
|
|
82
|
+
if (typeof fromFamily !== 'string' || fromFamily === '') { IDC.fail('invalid_argument', 'from_family is required.', null); }
|
|
83
|
+
if (typeof toFamily !== 'string' || toFamily === '') { IDC.fail('invalid_argument', 'to_family is required.', null); }
|
|
84
|
+
if (scope !== 'all' && scope !== 'styles_only' && scope !== 'local_only') {
|
|
85
|
+
IDC.fail('invalid_argument', 'scope must be all, styles_only or local_only.', { scope: scope });
|
|
86
|
+
}
|
|
87
|
+
if (fromStyle === null && toStyle !== null) {
|
|
88
|
+
IDC.fail('invalid_argument', 'to_style needs from_style; without from_style every style of the family is replaced by the same style name in the target family.', null);
|
|
89
|
+
}
|
|
90
|
+
if (fromStyle !== null && toStyle === null) { toStyle = fromStyle; }
|
|
91
|
+
if (idcSameFamily(fromFamily, toFamily) && (fromStyle === null || idcSameText(fromStyle, toStyle))) {
|
|
92
|
+
IDC.fail('invalid_argument', 'from and to name the same font.', { from_family: fromFamily, to_family: toFamily });
|
|
93
|
+
}
|
|
94
|
+
catalogue = idcFontCatalogue();
|
|
95
|
+
if (idcStylesOfFamily(catalogue, toFamily).length === 0) {
|
|
96
|
+
IDC.fail('not_found', 'Target font family "' + toFamily + '" is not installed.', { to_family: toFamily, available_styles: [] });
|
|
97
|
+
}
|
|
98
|
+
if (fromStyle !== null) { targets[fromStyle.toLowerCase()] = idcTargetFont(catalogue, toFamily, toStyle); }
|
|
99
|
+
|
|
100
|
+
/* Zielschnitt je Quellschnitt: gleicher Name in der Zielfamilie, sonst Warnung und Auslassen. */
|
|
101
|
+
function targetFor(styleOfRun) {
|
|
102
|
+
var key = styleOfRun === null ? '' : String(styleOfRun).toLowerCase();
|
|
103
|
+
if (fromStyle !== null && !idcSameText(styleOfRun, fromStyle)) { return null; }
|
|
104
|
+
if (IDC.hasOwn(targets, key)) { return targets[key]; }
|
|
105
|
+
if (idcCatalogueStatus(catalogue, toFamily, styleOfRun) === null) {
|
|
106
|
+
if (!idcInList(missingStyles, String(styleOfRun))) { missingStyles.push(String(styleOfRun)); }
|
|
107
|
+
targets[key] = null;
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
targets[key] = idcTargetFont(catalogue, toFamily, styleOfRun);
|
|
111
|
+
return targets[key];
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/* Formate. */
|
|
115
|
+
if (scope !== 'local_only') {
|
|
116
|
+
kinds = ['paragraph', 'character'];
|
|
117
|
+
for (k = 0; k < kinds.length; k++) {
|
|
118
|
+
styles = idcAllStyles(doc, kinds[k]);
|
|
119
|
+
for (i = 0; i < styles.length; i++) {
|
|
120
|
+
font = idcReadFontLoose(styles[i]);
|
|
121
|
+
if (font.family === null || !idcSameFamily(font.family, fromFamily)) { continue; }
|
|
122
|
+
target = targetFor(font.style);
|
|
123
|
+
if (target === null) { continue; }
|
|
124
|
+
try { styleName = String(styles[i].name); } catch (e0) { styleName = ''; }
|
|
125
|
+
if (!dryRun) {
|
|
126
|
+
try { idcSetFontOn(styles[i], target); } catch (e1) {
|
|
127
|
+
IDC.fail('script_error', 'InDesign could not set the font of style "' + styleName + '": ' + String(e1.message ? e1.message : e1), { style: styleName });
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
stylesChanged.push({ kind: kinds[k], name: styleName, from_style: font.style, to_style: target.style });
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/* Lokale Laeufe. */
|
|
136
|
+
if (scope !== 'styles_only') {
|
|
137
|
+
for (s = 0; s < doc.stories.length; s++) {
|
|
138
|
+
story = doc.stories.item(s);
|
|
139
|
+
try { storyId = Number(story.id); } catch (e2) { storyId = null; }
|
|
140
|
+
if (!includeMasters && idcStoryOnMaster(story)) { continue; }
|
|
141
|
+
if (!includeLocked && idcStoryLocked(doc, story)) { skippedLocked.push(storyId); continue; }
|
|
142
|
+
touched = false;
|
|
143
|
+
try { ranges = story.textStyleRanges; } catch (e3) { continue; }
|
|
144
|
+
for (r = 0; r < ranges.length; r++) {
|
|
145
|
+
try { range = ranges.item(r); } catch (e4) { continue; }
|
|
146
|
+
font = idcReadFontLoose(range);
|
|
147
|
+
if (font.family === null || !idcSameFamily(font.family, fromFamily)) { continue; }
|
|
148
|
+
target = targetFor(font.style);
|
|
149
|
+
if (target === null) { continue; }
|
|
150
|
+
/* dry_run: Laeufe, die ihre Schrift nur aus einem Format beziehen, das schon in styles_changed steht, zaehlen nicht (der echte Lauf aendert erst die Formate). */
|
|
151
|
+
if (dryRun && idcRunFontFromChangedStyle(range, font, stylesChanged)) { continue; }
|
|
152
|
+
try { length = Number(range.characters.length); } catch (e5) { length = 0; }
|
|
153
|
+
if (!dryRun) {
|
|
154
|
+
try { idcSetFontOn(range, target); } catch (e6) {
|
|
155
|
+
IDC.fail('script_error', 'InDesign could not set the font of a text run in story ' + storyId + ': ' + String(e6.message ? e6.message : e6), { story_id: storyId });
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
runsChanged += 1;
|
|
159
|
+
charsChanged += length;
|
|
160
|
+
touched = true;
|
|
161
|
+
}
|
|
162
|
+
if (touched) {
|
|
163
|
+
storiesTouched += 1;
|
|
164
|
+
if (!dryRun) { try { if (story.overflows === true) { oversetStories.push(storyId); } } catch (e7) { /* egal */ } }
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/* Nachkontrolle: was von der Ausgangsschrift noch da ist (gesperrte Ebenen, Formate bei local_only ...). */
|
|
170
|
+
if (!dryRun) {
|
|
171
|
+
for (s = 0; s < doc.stories.length; s++) {
|
|
172
|
+
story = doc.stories.item(s);
|
|
173
|
+
try { ranges = story.textStyleRanges; } catch (e8) { continue; }
|
|
174
|
+
for (r = 0; r < ranges.length; r++) {
|
|
175
|
+
try { range = ranges.item(r); font = idcReadFontLoose(range); } catch (e9) { continue; }
|
|
176
|
+
if (font.family !== null && idcSameFamily(font.family, fromFamily) && (fromStyle === null || idcSameText(font.style, fromStyle))) {
|
|
177
|
+
remaining += 1;
|
|
178
|
+
if (remainingWhere.length < 20) {
|
|
179
|
+
try { remainingWhere.push({ story_id: Number(story.id), index: Number(range.characters.item(0).index), style: font.style }); } catch (e10) { /* auslassen */ }
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
if (remaining > 0) {
|
|
185
|
+
ctx.warn(remaining + ' run(s) still use "' + fromFamily + '" (locked layers, tables, anchored objects, a style outside the scope, or a style name missing in the target family) – see remaining_where.');
|
|
186
|
+
}
|
|
187
|
+
if (oversetStories.length > 0) {
|
|
188
|
+
ctx.warn(oversetStories.length + ' story/stories overflow after the change – InDesign recomposed every paragraph; check get_frame_lines.');
|
|
189
|
+
}
|
|
190
|
+
if (stylesChanged.length + runsChanged > 0) { ctx.changes = { modified_document_ids: [Number(doc.id)] }; }
|
|
191
|
+
}
|
|
192
|
+
for (i = 0; i < missingStyles.length; i++) {
|
|
193
|
+
ctx.warn('Style "' + missingStyles[i] + '" does not exist in "' + toFamily + '"; runs and styles with it were left alone. Available: ' + idcStylesOfFamily(catalogue, toFamily).join(', ') + '.');
|
|
194
|
+
}
|
|
195
|
+
if (skippedLocked.length > 0) {
|
|
196
|
+
ctx.warn(skippedLocked.length + ' story/stories on locked layers were skipped (include_locked_layers true to change them).');
|
|
197
|
+
}
|
|
198
|
+
if (stylesChanged.length + runsChanged === 0) {
|
|
199
|
+
ctx.warn('"' + fromFamily + (fromStyle === null ? '' : ' ' + fromStyle) + '" is not used in the given scope; nothing to replace.');
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
return {
|
|
203
|
+
from: { family: String(fromFamily), style: fromStyle },
|
|
204
|
+
to: { family: String(toFamily), style: toStyle },
|
|
205
|
+
scope: scope,
|
|
206
|
+
styles_changed: stylesChanged,
|
|
207
|
+
runs_changed: runsChanged,
|
|
208
|
+
characters_changed: charsChanged,
|
|
209
|
+
stories_touched: storiesTouched,
|
|
210
|
+
remaining_occurrences: dryRun ? null : remaining,
|
|
211
|
+
remaining_where: remainingWhere,
|
|
212
|
+
skipped_locked: skippedLocked,
|
|
213
|
+
styles_missing_in_target: missingStyles,
|
|
214
|
+
overset_stories: oversetStories,
|
|
215
|
+
dry_run: dryRun
|
|
216
|
+
};
|
|
217
|
+
});
|