layoutbridge-light 0.0.0-stage → 1.0.1
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 +105 -0
- package/LICENSE +26 -0
- package/README.de.md +367 -0
- package/README.md +353 -2
- package/THIRD-PARTY-NOTICES.md +2878 -0
- package/dist/src/mcp/catalog.js +131 -0
- package/dist/src/mcp/config.js +211 -0
- package/dist/src/mcp/content-credentials.js +65 -0
- package/dist/src/mcp/dispatch.js +171 -0
- package/dist/src/mcp/epub-check.js +331 -0
- package/dist/src/mcp/epub-orientation.js +132 -0
- package/dist/src/mcp/license/free-tools.js +16 -0
- package/dist/src/mcp/license/gate.js +210 -0
- package/dist/src/mcp/license/index.js +107 -0
- package/dist/src/mcp/license/instance-name.js +57 -0
- package/dist/src/mcp/license/key-source.js +59 -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 +100 -0
- package/dist/src/mcp/license/polar-verifier.js +285 -0
- package/dist/src/mcp/license/product-ids.js +73 -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 +271 -0
- package/dist/src/mcp/pdf-postprocess.js +798 -0
- package/dist/src/mcp/product-info.js +54 -0
- package/dist/src/mcp/product.js +56 -0
- package/dist/src/mcp/server.js +253 -0
- package/dist/src/mcp/setup.js +680 -0
- package/dist/src/mcp/start.cjs +117 -0
- package/dist/src/mcp/target-folder.js +25 -0
- package/dist/src/mcp/tool-definition.js +2 -0
- package/dist/src/mcp/tools.js +2680 -0
- package/dist/src/mcp/typography-rules.js +70 -0
- package/dist/src/transport/com.js +436 -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 +52 -0
- package/indesign/commands/10-app.js +6 -0
- package/indesign/commands/20-documents.js +517 -0
- package/indesign/commands/22-document-setup.js +204 -0
- package/indesign/commands/23-save-package.js +258 -0
- package/indesign/commands/25-export.js +695 -0
- package/indesign/commands/26-export-image.js +202 -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 +310 -0
- package/indesign/commands/32-sections.js +203 -0
- package/indesign/commands/35-parents.js +448 -0
- package/indesign/commands/37-layout.js +837 -0
- package/indesign/commands/40-frames.js +886 -0
- package/indesign/commands/41-shapes.js +505 -0
- package/indesign/commands/42-groups.js +117 -0
- package/indesign/commands/43-layers.js +310 -0
- package/indesign/commands/44-effects.js +274 -0
- package/indesign/commands/45-frame-options.js +247 -0
- package/indesign/commands/47-anchored.js +473 -0
- package/indesign/commands/50-modify.js +803 -0
- package/indesign/commands/52-align.js +139 -0
- package/indesign/commands/55-fit.js +106 -0
- package/indesign/commands/60-images.js +1154 -0
- package/indesign/commands/62-embed.js +120 -0
- package/indesign/commands/69-placeholders.js +132 -0
- package/indesign/commands/70-text.js +710 -0
- package/indesign/commands/71-outlines.js +92 -0
- package/indesign/commands/72-place-text.js +476 -0
- package/indesign/commands/73-story-lock.js +157 -0
- package/indesign/commands/74-stories.js +121 -0
- package/indesign/commands/75-tables.js +702 -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 +511 -0
- package/indesign/commands/79-check-typography.js +480 -0
- package/indesign/commands/80-styles.js +1960 -0
- package/indesign/commands/81-composition.js +355 -0
- package/indesign/commands/82-object-styles.js +263 -0
- package/indesign/commands/83-drop-caps.js +87 -0
- package/indesign/commands/83-indents-tabs.js +264 -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 +212 -0
- package/indesign/commands/89-toc-index.js +1002 -0
- package/indesign/commands/90-print-on-demand.js +495 -0
- package/indesign/commands/91-epub.js +629 -0
- package/indesign/commands/92-accessibility.js +1131 -0
- package/indesign/interpreter.js +829 -0
- package/package.json +41 -4
- package/rules/typography-rules.json +32 -0
|
@@ -0,0 +1,1960 @@
|
|
|
1
|
+
/* Bereich H – Formate und Zeichenformatierung. */
|
|
2
|
+
|
|
3
|
+
/* ------------------------------------------------------------- Hilfen */
|
|
4
|
+
|
|
5
|
+
/*
|
|
6
|
+
* Vorhanden? DOM-Objekte (Color, Swatch) ueberladen === in ExtendScript und
|
|
7
|
+
* werfen beim Vergleich mit null ("Color.===() cannot work with instances of
|
|
8
|
+
* this class", Live-Fund 04.09.2026) – wirft der Vergleich, ist es ein Objekt.
|
|
9
|
+
*/
|
|
10
|
+
function idcPresent(value) {
|
|
11
|
+
try {
|
|
12
|
+
return !(value === null || value === undefined);
|
|
13
|
+
} catch (e) { return true; }
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/* NothingEnum.NOTHING: so liest InDesign ein nicht gesetztes Attribut (Zeichenformate). */
|
|
17
|
+
function idcIsNothing(value) {
|
|
18
|
+
if (!idcPresent(value)) { return true; }
|
|
19
|
+
try {
|
|
20
|
+
if (typeof NothingEnum !== 'undefined' && IDC.enumIs(value, NothingEnum.NOTHING)) { return true; }
|
|
21
|
+
} catch (e) { /* kein Enum */ }
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/*
|
|
26
|
+
* Schnitt oder null. A-68 Befund (15), Sitzung 81: ein Zeichenformat ohne
|
|
27
|
+
* Schnitt las sich live als "NOTHING" (Zeichenkette des Enumerators, an
|
|
28
|
+
* idcIsNothing vorbei) – auch "", "undefined" und "NOTHING" sind kein Schnitt.
|
|
29
|
+
*/
|
|
30
|
+
function idcFontStyleOrNull(value) {
|
|
31
|
+
var text;
|
|
32
|
+
if (idcIsNothing(value)) { return null; }
|
|
33
|
+
text = String(value);
|
|
34
|
+
if (text === '' || text === 'undefined' || text === 'NOTHING') { return null; }
|
|
35
|
+
return text;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/* Schrift eines Text- oder Formatobjekts; nicht gesetzte Attribute bleiben null. */
|
|
39
|
+
function idcReadFontLoose(target) {
|
|
40
|
+
var raw;
|
|
41
|
+
try { raw = target.appliedFont; } catch (e) { raw = null; }
|
|
42
|
+
if (idcIsNothing(raw)) {
|
|
43
|
+
var style = null;
|
|
44
|
+
try { style = target.fontStyle; } catch (e2) { style = null; }
|
|
45
|
+
return { family: null, style: idcFontStyleOrNull(style) };
|
|
46
|
+
}
|
|
47
|
+
var read = idcReadDefaultFont(target);
|
|
48
|
+
/* Nicht gesetzte Familie eines Zeichenformats liest sich als "" oder "undefined" (Live-Fund 04.09.2026). */
|
|
49
|
+
if (read.family === '' || read.family === 'undefined') { read.family = null; }
|
|
50
|
+
read.style = idcFontStyleOrNull(read.style);
|
|
51
|
+
return read;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/* Punktwert lesen (Schriftgrad, Abstand): unter Punkt-Masseinheit, null wenn nicht gesetzt. */
|
|
55
|
+
function idcReadPt(target, property) {
|
|
56
|
+
var value;
|
|
57
|
+
try {
|
|
58
|
+
value = IDC.inPoints(function () { return target[property]; });
|
|
59
|
+
} catch (e) { return null; }
|
|
60
|
+
if (idcIsNothing(value)) { return null; }
|
|
61
|
+
return IDC.round(Number(value), 3);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/* Zeilenabstand: { pt, auto } – pt null bei automatischem Zeilenabstand. */
|
|
65
|
+
function idcReadLeading(target) {
|
|
66
|
+
var value;
|
|
67
|
+
try {
|
|
68
|
+
value = IDC.inPoints(function () { return target.leading; });
|
|
69
|
+
} catch (e) { return { pt: null, auto: false }; }
|
|
70
|
+
if (idcIsNothing(value)) { return { pt: null, auto: false }; }
|
|
71
|
+
if (typeof Leading !== 'undefined' && IDC.enumIs(value, Leading.AUTO)) { return { pt: null, auto: true }; }
|
|
72
|
+
var n = Number(value);
|
|
73
|
+
if (isNaN(n)) { return { pt: null, auto: false }; }
|
|
74
|
+
return { pt: IDC.round(n, 3), auto: false };
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function idcReadNumberLoose(target, property, digits) {
|
|
78
|
+
var value;
|
|
79
|
+
try { value = target[property]; } catch (e) { return null; }
|
|
80
|
+
if (idcIsNothing(value)) { return null; }
|
|
81
|
+
var n = Number(value);
|
|
82
|
+
return isNaN(n) ? null : IDC.round(n, digits === undefined ? 3 : digits);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function idcReadBoolLoose(target, property) {
|
|
86
|
+
var value;
|
|
87
|
+
try { value = target[property]; } catch (e) { return null; }
|
|
88
|
+
if (idcIsNothing(value)) { return null; }
|
|
89
|
+
return value === true;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function idcReadSwatchName(target, property) {
|
|
93
|
+
var value;
|
|
94
|
+
try { value = target[property]; } catch (e) { return null; }
|
|
95
|
+
if (idcIsNothing(value)) { return null; }
|
|
96
|
+
try { return String(value.name); } catch (e2) { return null; }
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/* Gruppenpfad eines Formats ("Group/Subgroup"), leer auf oberster Ebene. */
|
|
100
|
+
function idcStyleGroupPath(style) {
|
|
101
|
+
var names = [];
|
|
102
|
+
var current, name, step;
|
|
103
|
+
try { current = style.parent; } catch (e) { return ''; }
|
|
104
|
+
for (step = 0; step < 12; step++) {
|
|
105
|
+
if (current === null || current === undefined) { break; }
|
|
106
|
+
name = IDC.className(current);
|
|
107
|
+
if (name === 'ParagraphStyleGroup' || name === 'CharacterStyleGroup') {
|
|
108
|
+
try { names.unshift(String(current.name)); } catch (e2) { break; }
|
|
109
|
+
try { current = current.parent; } catch (e3) { break; }
|
|
110
|
+
} else {
|
|
111
|
+
break;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return names.join('/');
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/* Name des Grundlagenformats; die Wurzel ([Kein Absatzformat]) kommt als Verweis ohne lesbaren Namen zurueck (Live-Fund 04.09.2026) – dann null. */
|
|
118
|
+
function idcBasedOnName(style) {
|
|
119
|
+
var base, name;
|
|
120
|
+
try { base = style.basedOn; } catch (e) { return null; }
|
|
121
|
+
if (idcIsNothing(base)) { return null; }
|
|
122
|
+
if (typeof base === 'string') { return base === '' || base === 'undefined' ? null : base; }
|
|
123
|
+
try { name = String(base.name); } catch (e2) { name = 'undefined'; }
|
|
124
|
+
if (name === 'undefined' || name === '') {
|
|
125
|
+
try { name = String(IDC.concrete(base).name); } catch (e3) { name = 'undefined'; }
|
|
126
|
+
}
|
|
127
|
+
return name === 'undefined' || name === '' ? null : name;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/* Ausrichtungsname zu einem Justification-Wert. */
|
|
131
|
+
function idcJustificationName(value) {
|
|
132
|
+
if (typeof Justification === 'undefined') { return value === undefined ? null : String(value); }
|
|
133
|
+
if (idcIsNothing(value)) { return null; }
|
|
134
|
+
var table = [
|
|
135
|
+
['left', Justification.LEFT_ALIGN],
|
|
136
|
+
['center', Justification.CENTER_ALIGN],
|
|
137
|
+
['right', Justification.RIGHT_ALIGN],
|
|
138
|
+
['justify_left', Justification.LEFT_JUSTIFIED],
|
|
139
|
+
['justify_center', Justification.CENTER_JUSTIFIED],
|
|
140
|
+
['justify_right', Justification.RIGHT_JUSTIFIED],
|
|
141
|
+
['justify_full', Justification.FULLY_JUSTIFIED],
|
|
142
|
+
['away_from_binding', Justification.AWAY_FROM_BINDING_SIDE],
|
|
143
|
+
['to_binding', Justification.TO_BINDING_SIDE]
|
|
144
|
+
];
|
|
145
|
+
var i;
|
|
146
|
+
for (i = 0; i < table.length; i++) {
|
|
147
|
+
if (IDC.enumIs(value, table[i][1])) { return table[i][0]; }
|
|
148
|
+
}
|
|
149
|
+
return String(value);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/* Justification-Wert zu einem Ausrichtungsnamen; "justify" = Blocksatz, letzte Zeile links. */
|
|
153
|
+
function idcJustificationFor(name, field) {
|
|
154
|
+
var text = String(name);
|
|
155
|
+
if (typeof Justification === 'undefined') {
|
|
156
|
+
IDC.fail('invalid_state', 'This runtime has no Justification enumeration.', null);
|
|
157
|
+
}
|
|
158
|
+
if (text === 'left') { return Justification.LEFT_ALIGN; }
|
|
159
|
+
if (text === 'center') { return Justification.CENTER_ALIGN; }
|
|
160
|
+
if (text === 'right') { return Justification.RIGHT_ALIGN; }
|
|
161
|
+
if (text === 'justify' || text === 'justify_left') { return Justification.LEFT_JUSTIFIED; }
|
|
162
|
+
if (text === 'justify_center') { return Justification.CENTER_JUSTIFIED; }
|
|
163
|
+
if (text === 'justify_right') { return Justification.RIGHT_JUSTIFIED; }
|
|
164
|
+
if (text === 'justify_full') { return Justification.FULLY_JUSTIFIED; }
|
|
165
|
+
IDC.fail('invalid_argument', field + ' must be one of left, center, right, justify, justify_left, justify_center, justify_right, justify_full.', { value: text });
|
|
166
|
+
return null;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function idcStyleNameArg(value, field) {
|
|
170
|
+
if (typeof value !== 'string' || value.length === 0) {
|
|
171
|
+
IDC.fail('invalid_argument', field + ' is required (a non-empty string).', null);
|
|
172
|
+
}
|
|
173
|
+
if (value.charAt(0) === '[') {
|
|
174
|
+
IDC.fail('invalid_argument', field + ' must not start with "[" – those names are reserved for InDesign\'s internal styles.', { value: value });
|
|
175
|
+
}
|
|
176
|
+
return value;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
function idcCollisionArg(value) {
|
|
180
|
+
if (value === undefined || value === null) { return 'error'; }
|
|
181
|
+
if (value !== 'error' && value !== 'update' && value !== 'version') {
|
|
182
|
+
IDC.fail('invalid_argument', 'on_collision must be error, update or version.', { value: value });
|
|
183
|
+
}
|
|
184
|
+
return value;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function idcNumberArg(value, field, min, max) {
|
|
188
|
+
if (typeof value !== 'number' || !isFinite(value)) {
|
|
189
|
+
IDC.fail('invalid_argument', field + ' must be a number.', { value: value });
|
|
190
|
+
}
|
|
191
|
+
if (min !== null && value < min) {
|
|
192
|
+
IDC.fail('invalid_argument', field + ' must be ' + min + ' or more.', { value: value });
|
|
193
|
+
}
|
|
194
|
+
if (max !== null && value > max) {
|
|
195
|
+
IDC.fail('invalid_argument', field + ' must be ' + max + ' or less.', { value: value });
|
|
196
|
+
}
|
|
197
|
+
return value;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
function idcGiven(value) {
|
|
201
|
+
return value !== undefined && value !== null;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/* Zeichenformat ueber den Namen, auch in Formatgruppen; eine gleichnamige Gruppe zaehlt nicht (IDC.styleFromLookup). */
|
|
205
|
+
function idcCharacterStyleByName(doc, name) {
|
|
206
|
+
var style, all, i;
|
|
207
|
+
try { all = doc.allCharacterStyles; } catch (e0) { all = null; }
|
|
208
|
+
try {
|
|
209
|
+
style = IDC.styleFromLookup(doc.characterStyles.itemByName(name), all);
|
|
210
|
+
if (style !== null) { return style; }
|
|
211
|
+
} catch (e) { /* weiter */ }
|
|
212
|
+
if (all === null) { return null; }
|
|
213
|
+
try {
|
|
214
|
+
for (i = 0; i < all.length; i++) {
|
|
215
|
+
if (String(all[i].name) === String(name)) { return all[i]; }
|
|
216
|
+
}
|
|
217
|
+
} catch (e2) { /* weiter */ }
|
|
218
|
+
return null;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/*
|
|
222
|
+
* Formatgruppe dieses Namens auf oberster Ebene, sonst null. InDesign laesst
|
|
223
|
+
* daneben kein gleichnamiges Format zu ("Es existiert bereits ein Format
|
|
224
|
+
* dieses Namens", Live-Fund 23.10.2026, A-59) – der Name ist belegt, die
|
|
225
|
+
* Gruppe selbst aber kein Format, das sich aendern liesse.
|
|
226
|
+
*/
|
|
227
|
+
function idcTopLevelStyleGroup(doc, name, kind) {
|
|
228
|
+
var groups;
|
|
229
|
+
/* Schleife statt itemByName: das liefert auch fuer einen Formatnamen einen gueltigen Gruppenverweis (Live-Fund 23.10.2026). */
|
|
230
|
+
try { groups = kind === 'character' ? doc.characterStyleGroups : doc.paragraphStyleGroups; } catch (e) { return null; }
|
|
231
|
+
return idcDirectChildByName(groups, name);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/* Name durch eine Gruppe belegt: version weicht aus (true), error und update scheitern mit details.code "style_group_name". */
|
|
235
|
+
function idcGroupNameCollision(doc, name, kind, onCollision) {
|
|
236
|
+
var group = idcTopLevelStyleGroup(doc, name, kind);
|
|
237
|
+
var what = kind === 'character' ? 'character' : 'paragraph';
|
|
238
|
+
if (group === null) { return false; }
|
|
239
|
+
if (onCollision === 'version') { return true; }
|
|
240
|
+
IDC.fail('invalid_state', '"' + name + '" is the name of a ' + what + ' style group; InDesign allows no ' + what + ' style of the same name beside it, and a group cannot be ' +
|
|
241
|
+
(onCollision === 'update' ? 'updated' : 'used') + ' as a style. Choose another name or pass on_collision "version" to add "' + name + ' 2".',
|
|
242
|
+
{ code: 'style_group_name', name: name, group_id: (function () { try { return Number(group.id); } catch (e) { return null; } })() });
|
|
243
|
+
return false;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/* Alle Absatz- bzw. Zeichenformate als Array, auch aus Gruppen. */
|
|
247
|
+
function idcAllStyles(doc, kind) {
|
|
248
|
+
var out = [];
|
|
249
|
+
var all, collection, i;
|
|
250
|
+
try {
|
|
251
|
+
all = kind === 'character' ? doc.allCharacterStyles : doc.allParagraphStyles;
|
|
252
|
+
for (i = 0; i < all.length; i++) { out.push(all[i]); }
|
|
253
|
+
return out;
|
|
254
|
+
} catch (e) { /* Rueckfall: nur die oberste Ebene */ }
|
|
255
|
+
try {
|
|
256
|
+
collection = kind === 'character' ? doc.characterStyles : doc.paragraphStyles;
|
|
257
|
+
for (i = 0; i < collection.length; i++) { out.push(collection.item(i)); }
|
|
258
|
+
} catch (e2) { /* leer */ }
|
|
259
|
+
return out;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/* Naechster freier Name "Name 2", "Name 3" ... fuer Absatz-/Zeichenformat oder Farbfeld. */
|
|
263
|
+
function idcFreeName(doc, base, kind, container) {
|
|
264
|
+
var n = 2;
|
|
265
|
+
var candidate;
|
|
266
|
+
/* Formatnamen im ganzen Dokument frei, dazu kein Gruppenname auf der Zielebene (container, Vorgabe oberste Ebene). */
|
|
267
|
+
function groupThere(name) {
|
|
268
|
+
if (idcPresent(container) && container !== doc) { return idcDirectChildByName(idcGroupsOf(container, kind), name) !== null; }
|
|
269
|
+
return idcTopLevelStyleGroup(doc, name, kind) !== null;
|
|
270
|
+
}
|
|
271
|
+
function taken(name) {
|
|
272
|
+
if (kind === 'paragraph') { return IDC.paragraphStyleByName(doc, name) !== null || groupThere(name); }
|
|
273
|
+
if (kind === 'character') { return idcCharacterStyleByName(doc, name) !== null || groupThere(name); }
|
|
274
|
+
return idcPresent(idcSwatchByName(doc, name));
|
|
275
|
+
}
|
|
276
|
+
for (n = 2; n < 1000; n++) {
|
|
277
|
+
candidate = base + ' ' + n;
|
|
278
|
+
if (!taken(candidate)) { return candidate; }
|
|
279
|
+
}
|
|
280
|
+
IDC.fail('invalid_state', 'No free name found for "' + base + '".', { name: base });
|
|
281
|
+
return null;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
function idcSwatchByName(doc, name) {
|
|
285
|
+
var swatch = null;
|
|
286
|
+
try {
|
|
287
|
+
swatch = doc.swatches.itemByName(String(name));
|
|
288
|
+
if (swatch && swatch.isValid === true) { return swatch; }
|
|
289
|
+
} catch (e) { /* weiter */ }
|
|
290
|
+
return null;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/* Zeichenformat [None]; der Skriptname ist in jeder Sprachfassung "[None]". */
|
|
294
|
+
function idcNoneCharacterStyle(doc) {
|
|
295
|
+
var style = null;
|
|
296
|
+
try {
|
|
297
|
+
style = doc.characterStyles.itemByName('[None]');
|
|
298
|
+
if (style && style.isValid === true) { return style; }
|
|
299
|
+
} catch (e) { /* weiter */ }
|
|
300
|
+
try {
|
|
301
|
+
style = doc.characterStyles.item(0);
|
|
302
|
+
if (style && style.isValid === true) { return style; }
|
|
303
|
+
} catch (e2) { /* weiter */ }
|
|
304
|
+
return null;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/* Ist ein Zeichenformat das eingebaute [None]? Sein Name ist lokalisiert ("[Ohne]" in der deutschen Fassung, Live-Fund 04.09.2026) – deshalb ueber die ID. */
|
|
308
|
+
function idcIsNoneCharacterStyle(doc, style) {
|
|
309
|
+
var none = idcNoneCharacterStyle(doc);
|
|
310
|
+
if (!idcPresent(style) || none === null) { return null; }
|
|
311
|
+
try { return Number(style.id) === Number(none.id); } catch (e) { /* weiter */ }
|
|
312
|
+
try { return String(style.name).charAt(0) === '['; } catch (e2) { return null; }
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/*
|
|
316
|
+
* A-68 (1) und (3), Sitzung 81 – Grundlage Probe InDesign 21.6 am 11.11.2026:
|
|
317
|
+
* ParagraphStyle.gridAlignment (GridAlignment NONE, ALIGN_BASELINE, ...) und
|
|
318
|
+
* capitalization an Absatz- und Zeichenformaten (Capitalization NORMAL,
|
|
319
|
+
* SMALL_CAPS, ALL_CAPS, CAP_TO_SMALL_CAP, LOWER_CASE; am neuen Zeichenformat
|
|
320
|
+
* NothingEnum.NOTHING = nicht festgelegt).
|
|
321
|
+
*/
|
|
322
|
+
var IDC_CAPITALIZATIONS = [
|
|
323
|
+
['normal', 'NORMAL'], ['small_caps', 'SMALL_CAPS'], ['all_caps', 'ALL_CAPS'],
|
|
324
|
+
['cap_to_small_caps', 'CAP_TO_SMALL_CAP'], ['lower_case', 'LOWER_CASE']
|
|
325
|
+
];
|
|
326
|
+
|
|
327
|
+
function idcCapitalizationFor(name) {
|
|
328
|
+
var i, names = [];
|
|
329
|
+
if (typeof Capitalization === 'undefined') { IDC.fail('invalid_state', 'This runtime has no Capitalization enumeration.', null); }
|
|
330
|
+
for (i = 0; i < IDC_CAPITALIZATIONS.length; i++) {
|
|
331
|
+
if (IDC_CAPITALIZATIONS[i][0] === name) { return Capitalization[IDC_CAPITALIZATIONS[i][1]]; }
|
|
332
|
+
names.push(IDC_CAPITALIZATIONS[i][0]);
|
|
333
|
+
}
|
|
334
|
+
IDC.fail('invalid_argument', 'capitalization must be one of ' + names.join(', ') + '.', { value: name });
|
|
335
|
+
return null;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
function idcReadCapitalization(style) {
|
|
339
|
+
var value, i;
|
|
340
|
+
try { value = style.capitalization; } catch (e0) { return null; }
|
|
341
|
+
if (value === undefined || value === null || idcIsNothing(value) || typeof Capitalization === 'undefined') { return null; }
|
|
342
|
+
for (i = 0; i < IDC_CAPITALIZATIONS.length; i++) {
|
|
343
|
+
try { if (IDC.enumIs(value, Capitalization[IDC_CAPITALIZATIONS[i][1]])) { return IDC_CAPITALIZATIONS[i][0]; } } catch (e1) { /* weiter */ }
|
|
344
|
+
}
|
|
345
|
+
return String(value);
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
/* true bei Ausrichtung an der Grundlinie, false bei keiner, sonst der Name (Em-Box, ICF – nur ueber InDesign gesetzt). */
|
|
349
|
+
function idcReadGridAlignment(style) {
|
|
350
|
+
var value;
|
|
351
|
+
try { value = style.gridAlignment; } catch (e0) { return null; }
|
|
352
|
+
if (value === undefined || value === null || typeof GridAlignment === 'undefined') { return null; }
|
|
353
|
+
if (IDC.enumIs(value, GridAlignment.ALIGN_BASELINE)) { return true; }
|
|
354
|
+
if (IDC.enumIs(value, GridAlignment.NONE)) { return false; }
|
|
355
|
+
return String(value);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
/* Beschreibung eines Absatzformats fuer list_paragraph_styles und debug_inspect_run. */
|
|
359
|
+
function idcDescribeParagraphStyle(style) {
|
|
360
|
+
var font = idcReadFontLoose(style);
|
|
361
|
+
var leading = idcReadLeading(style);
|
|
362
|
+
var id = null, name = null, alignment = null;
|
|
363
|
+
try { id = Number(style.id); } catch (e1) { id = null; }
|
|
364
|
+
try { name = String(style.name); } catch (e2) { name = null; }
|
|
365
|
+
try { alignment = idcJustificationName(style.justification); } catch (e3) { alignment = null; }
|
|
366
|
+
return {
|
|
367
|
+
name: name,
|
|
368
|
+
style_id: id,
|
|
369
|
+
group: idcStyleGroupPath(style),
|
|
370
|
+
based_on: idcBasedOnName(style),
|
|
371
|
+
font_family: font.family,
|
|
372
|
+
font_style: font.style,
|
|
373
|
+
point_size: idcReadPt(style, 'pointSize'),
|
|
374
|
+
leading_pt: leading.pt,
|
|
375
|
+
leading_auto: leading.auto,
|
|
376
|
+
fill_swatch: idcReadSwatchName(style, 'fillColor'),
|
|
377
|
+
alignment: alignment,
|
|
378
|
+
space_before_pt: idcReadPt(style, 'spaceBefore'),
|
|
379
|
+
space_after_pt: idcReadPt(style, 'spaceAfter'),
|
|
380
|
+
hyphenation: idcReadBoolLoose(style, 'hyphenation'),
|
|
381
|
+
tracking: idcReadNumberLoose(style, 'tracking', 1),
|
|
382
|
+
/* A-7.1 bis A-7.3 (81-composition.js) */
|
|
383
|
+
keep_options: idcReadKeepOptions(style),
|
|
384
|
+
hyphenation_options: idcReadHyphenationOptions(style),
|
|
385
|
+
justification_options: idcReadJustificationOptions(style),
|
|
386
|
+
/* Sitzung 10, Demo-Heft-Befund 3 (83-indents-tabs.js) */
|
|
387
|
+
indents: idcReadIndentTabLanguage(style),
|
|
388
|
+
/* A-67 Punkt 1, Sitzung 72 (83-drop-caps.js) */
|
|
389
|
+
drop_cap: idcReadDropCap(style),
|
|
390
|
+
/* A-68 (1) und (3), Sitzung 81 */
|
|
391
|
+
align_to_baseline_grid: idcReadGridAlignment(style),
|
|
392
|
+
capitalization: idcReadCapitalization(style),
|
|
393
|
+
/* A-79, Sitzung 82 (92-accessibility.js): "" = kein PDF-Tag */
|
|
394
|
+
pdf_tag: idcReadPdfTag(style)
|
|
395
|
+
};
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
/* Beschreibung eines Zeichenformats; nicht gesetzte Attribute sind null. */
|
|
399
|
+
function idcDescribeCharacterStyle(style) {
|
|
400
|
+
var font = idcReadFontLoose(style);
|
|
401
|
+
var id = null, name = null;
|
|
402
|
+
try { id = Number(style.id); } catch (e1) { id = null; }
|
|
403
|
+
try { name = String(style.name); } catch (e2) { name = null; }
|
|
404
|
+
return {
|
|
405
|
+
name: name,
|
|
406
|
+
style_id: id,
|
|
407
|
+
group: idcStyleGroupPath(style),
|
|
408
|
+
based_on: idcBasedOnName(style),
|
|
409
|
+
font_family: font.family,
|
|
410
|
+
font_style: font.style,
|
|
411
|
+
point_size: idcReadPt(style, 'pointSize'),
|
|
412
|
+
fill_swatch: idcReadSwatchName(style, 'fillColor'),
|
|
413
|
+
tracking: idcReadNumberLoose(style, 'tracking', 1),
|
|
414
|
+
/* A-68 (3), Sitzung 81: null, wenn das Zeichenformat die Schreibweise nicht festlegt */
|
|
415
|
+
capitalization: idcReadCapitalization(style),
|
|
416
|
+
/* A-79, Sitzung 82 (92-accessibility.js): "" = kein PDF-Tag */
|
|
417
|
+
pdf_tag: idcReadPdfTag(style)
|
|
418
|
+
};
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
/* ------------------------------------------------------------ Schriften */
|
|
422
|
+
|
|
423
|
+
function idcFontStatusName(status) {
|
|
424
|
+
if (typeof FontStatus === 'undefined' || idcIsNothing(status)) { return 'installed'; }
|
|
425
|
+
if (IDC.enumIs(status, FontStatus.INSTALLED)) { return 'installed'; }
|
|
426
|
+
if (IDC.enumIs(status, FontStatus.SUBSTITUTED)) { return 'substituted'; }
|
|
427
|
+
if (IDC.enumIs(status, FontStatus.FAUXED)) { return 'substituted'; }
|
|
428
|
+
if (IDC.enumIs(status, FontStatus.NOT_AVAILABLE)) { return 'not_available'; }
|
|
429
|
+
if (IDC.enumIs(status, FontStatus.UNKNOWN)) { return 'not_available'; }
|
|
430
|
+
return 'not_available';
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
/*
|
|
434
|
+
* Schriften gezielt aufloesen statt die ganze Schriftliste zu lesen (A-59,
|
|
435
|
+
* Sitzung 70, E-105). Bei einem Kunden mit sehr vielen aktiven Schriften hing
|
|
436
|
+
* InDesign an jedem Werkzeug, das die Liste las: app.fonts.item(i) kostet je
|
|
437
|
+
* Zugriff Zeit proportional zur Schriftzahl (live 26.10.2026, InDesign 21.6:
|
|
438
|
+
* 22 ms bei 1409, 47 ms bei 4199 Schriften), eine Schleife darueber waechst
|
|
439
|
+
* quadratisch. Darum: erst itemByName("Familie\tSchnitt"), die Namensliste
|
|
440
|
+
* nur fuer available_styles und Schreibvarianten – in einem DOM-Aufruf und nie
|
|
441
|
+
* ueber app.fonts.item(i).
|
|
442
|
+
*/
|
|
443
|
+
|
|
444
|
+
/* Schrift unter genau diesem Namen, sonst null. itemByName ist auch fuer unbekannte Namen gueltig; erst das Lesen wirft (live 26.10.2026). */
|
|
445
|
+
function idcFontByExactName(name) {
|
|
446
|
+
var fontObject, family, style, status;
|
|
447
|
+
try {
|
|
448
|
+
fontObject = app.fonts.itemByName(name);
|
|
449
|
+
if (!fontObject || fontObject.isValid !== true) { return null; }
|
|
450
|
+
family = String(fontObject.fontFamily);
|
|
451
|
+
style = String(fontObject.fontStyleName);
|
|
452
|
+
status = idcFontStatusName(fontObject.status);
|
|
453
|
+
} catch (e) { return null; }
|
|
454
|
+
return { object: fontObject, family: family, style: style, status: status };
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
/* Namen aller Schriften als [{ family, style, name }] – ein DOM-Aufruf (name ist "Familie\tSchnitt"). */
|
|
458
|
+
function idcFontNames() {
|
|
459
|
+
var out = [];
|
|
460
|
+
var names = null;
|
|
461
|
+
var all, i, text, tab;
|
|
462
|
+
try { names = app.fonts.everyItem().name; } catch (e) { names = null; }
|
|
463
|
+
if (!IDC.isArray(names)) {
|
|
464
|
+
names = [];
|
|
465
|
+
try { all = app.fonts.everyItem().getElements(); } catch (e2) { all = []; }
|
|
466
|
+
for (i = 0; i < all.length; i++) {
|
|
467
|
+
try { names.push(String(all[i].name)); } catch (e3) { /* Eintrag ohne Namen */ }
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
for (i = 0; i < names.length; i++) {
|
|
471
|
+
text = String(names[i]);
|
|
472
|
+
tab = text.indexOf('\t');
|
|
473
|
+
out.push({ family: tab < 0 ? text : text.substr(0, tab), style: tab < 0 ? '' : text.substr(tab + 1), name: text });
|
|
474
|
+
}
|
|
475
|
+
return out;
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
/*
|
|
479
|
+
* Schriftauskunft eines Aufrufs. find(family, style): { object, family, style,
|
|
480
|
+
* status } oder null, wenn InDesign die Schrift nicht fuehrt – erst gezielt,
|
|
481
|
+
* dann ueber die Namensliste (Gross-/Kleinschreibung, Formatzusatz " (OTF)").
|
|
482
|
+
* stylesOf(family): Schnitte der Familie aus der Namensliste. Die Liste wird
|
|
483
|
+
* hoechstens einmal je Aufruf gelesen und nur, wenn sie gebraucht wird.
|
|
484
|
+
*/
|
|
485
|
+
function idcFontLookup() {
|
|
486
|
+
var names = null;
|
|
487
|
+
function list() {
|
|
488
|
+
if (names === null) { names = idcFontNames(); }
|
|
489
|
+
return names;
|
|
490
|
+
}
|
|
491
|
+
function find(family, style) {
|
|
492
|
+
var exact = idcFontByExactName(String(family) + '\t' + String(style));
|
|
493
|
+
var entries, i, viaList;
|
|
494
|
+
if (exact !== null && idcSameFamily(exact.family, family) && idcSameText(exact.style, style)) { return exact; }
|
|
495
|
+
entries = list();
|
|
496
|
+
for (i = 0; i < entries.length; i++) {
|
|
497
|
+
if (idcSameFamily(entries[i].family, family) && idcSameText(entries[i].style, style)) {
|
|
498
|
+
viaList = idcFontByExactName(entries[i].name);
|
|
499
|
+
if (viaList !== null) { return viaList; }
|
|
500
|
+
return { object: null, family: entries[i].family, style: entries[i].style, status: 'not_available' };
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
return null;
|
|
504
|
+
}
|
|
505
|
+
function stylesOf(family) {
|
|
506
|
+
var out = [];
|
|
507
|
+
var entries = list();
|
|
508
|
+
var i;
|
|
509
|
+
for (i = 0; i < entries.length; i++) {
|
|
510
|
+
if (idcSameFamily(entries[i].family, family)) { out.push(entries[i].style); }
|
|
511
|
+
}
|
|
512
|
+
return out;
|
|
513
|
+
}
|
|
514
|
+
function hasFamily(family) {
|
|
515
|
+
/* itemByName mit der Familie allein liefert ihren ersten Schnitt (live 26.10.2026). */
|
|
516
|
+
var first = idcFontByExactName(String(family));
|
|
517
|
+
if (first !== null && idcSameFamily(first.family, family)) { return true; }
|
|
518
|
+
return stylesOf(family).length > 0;
|
|
519
|
+
}
|
|
520
|
+
return { find: find, stylesOf: stylesOf, hasFamily: hasFamily };
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
function idcSameText(a, b) {
|
|
524
|
+
return String(a).toLowerCase() === String(b).toLowerCase();
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
/*
|
|
528
|
+
* Familienname ohne Formatzusatz: InDesign haengt " (OTF)", " (TT)" oder
|
|
529
|
+
* " (T1)" an, wenn es eine Familie in mehreren Formaten kennt (Demo-Heft-
|
|
530
|
+
* Befund 7, 05.09.2026: "Source Sans 3 (OTF)"). Vergleiche von Familiennamen
|
|
531
|
+
* lassen den Zusatz auf beiden Seiten weg.
|
|
532
|
+
*/
|
|
533
|
+
function idcFamilyKey(name) {
|
|
534
|
+
return String(name).toLowerCase().replace(/\s*\((otf|tt|t1|ttf|opentype|truetype|type ?1)\)\s*$/, '');
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
function idcSameFamily(a, b) {
|
|
538
|
+
return idcFamilyKey(a) === idcFamilyKey(b);
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
/* Status der im Dokument benutzten Schriften: { "Familie\tSchnitt": status }. */
|
|
542
|
+
function idcDocumentFontStatuses(doc) {
|
|
543
|
+
var out = {};
|
|
544
|
+
var i, entry, name, status;
|
|
545
|
+
try {
|
|
546
|
+
for (i = 0; i < doc.fonts.length; i++) {
|
|
547
|
+
entry = doc.fonts.item(i);
|
|
548
|
+
name = String(entry.name);
|
|
549
|
+
try { status = idcFontStatusName(entry.status); } catch (e1) { status = 'installed'; }
|
|
550
|
+
out[name] = status;
|
|
551
|
+
try {
|
|
552
|
+
out[String(entry.fontFamily) + '\t' + String(entry.fontStyleName)] = status;
|
|
553
|
+
} catch (e2) { /* Name reicht */ }
|
|
554
|
+
}
|
|
555
|
+
} catch (e) { /* leer */ }
|
|
556
|
+
return out;
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
/*
|
|
560
|
+
* Schrift auf ein Format oder eine Textstelle setzen. Beides: ueber das
|
|
561
|
+
* Font-Objekt, wenn installiert, sonst als "Familie\tSchnitt" (InDesign fuehrt
|
|
562
|
+
* sie dann als fehlend). Nur Familie: InDesign behaelt eine unbekannte
|
|
563
|
+
* Familie stillschweigend – deshalb zuruecklesen.
|
|
564
|
+
*/
|
|
565
|
+
function idcApplyFont(ctx, target, family, styleName, fonts, probe) {
|
|
566
|
+
var fontObject, text, after, found;
|
|
567
|
+
var applied = [];
|
|
568
|
+
var reader = idcPresent(probe) ? probe : target;
|
|
569
|
+
if (idcGiven(family) && idcGiven(styleName)) {
|
|
570
|
+
text = String(family) + '\t' + String(styleName);
|
|
571
|
+
/* Bei installierter Familie ist der Verweis auch fuer einen fehlenden Schnitt gueltig (Live-Fund 23.10.2026, A-59) – nur ein Schnitt, den InDesign fuehrt, zaehlt. */
|
|
572
|
+
found = fonts.find(family, styleName);
|
|
573
|
+
fontObject = found !== null && found.status !== 'not_available' ? found.object : null;
|
|
574
|
+
try {
|
|
575
|
+
if (fontObject !== null) { target.appliedFont = fontObject; }
|
|
576
|
+
else { target.appliedFont = text; }
|
|
577
|
+
} catch (e1) {
|
|
578
|
+
/* InDesign 21.5: "Die gewuenschte Schriftfamilie ist nicht verfuegbar." – eine fehlende Schrift laesst sich per Skript nicht setzen (Live-Fund 04.09.2026). */
|
|
579
|
+
IDC.fail('not_found', 'Font "' + String(family) + ' ' + String(styleName) + '" is not installed; InDesign rejects it: ' + String(e1.message ? e1.message : e1),
|
|
580
|
+
{ font_family: family, font_style: styleName, available_styles: fonts.stylesOf(family) });
|
|
581
|
+
}
|
|
582
|
+
after = idcReadFontLoose(reader);
|
|
583
|
+
if (fontObject === null) {
|
|
584
|
+
if (after.family !== null && !idcSameFamily(after.family, family)) {
|
|
585
|
+
IDC.fail('not_found', 'Font "' + String(family) + ' ' + String(styleName) + '" is not installed; InDesign kept "' + after.family + ' ' + after.style + '".',
|
|
586
|
+
{ font_family: family, font_style: styleName, available_styles: fonts.stylesOf(family) });
|
|
587
|
+
}
|
|
588
|
+
ctx.warn('Font "' + String(family) + ' ' + String(styleName) + '" is not installed; InDesign lists it as missing (fehlende Schrift).');
|
|
589
|
+
}
|
|
590
|
+
applied.push('font_family');
|
|
591
|
+
applied.push('font_style');
|
|
592
|
+
return applied;
|
|
593
|
+
}
|
|
594
|
+
if (idcGiven(family)) {
|
|
595
|
+
try { target.appliedFont = String(family); } catch (e2) {
|
|
596
|
+
/* InDesign 21.5 wirft auch bei der Familie allein (Live-Fund 04.09.2026, Suite Lauf 2). */
|
|
597
|
+
IDC.fail('not_found', 'Font family "' + String(family) + '" is not installed; InDesign rejects it: ' + String(e2.message ? e2.message : e2), { font_family: family });
|
|
598
|
+
}
|
|
599
|
+
after = idcReadFontLoose(reader);
|
|
600
|
+
if (after.family === null || !idcSameFamily(after.family, family)) {
|
|
601
|
+
IDC.fail('not_found', 'Font family "' + String(family) + '" is not installed; InDesign kept "' + after.family + '". Pass font_style as well to define a missing font on purpose.',
|
|
602
|
+
{ font_family: family });
|
|
603
|
+
}
|
|
604
|
+
applied.push('font_family');
|
|
605
|
+
return applied;
|
|
606
|
+
}
|
|
607
|
+
if (idcGiven(styleName)) {
|
|
608
|
+
var before = idcReadFontLoose(reader);
|
|
609
|
+
try { target.fontStyle = String(styleName); } catch (e3) {
|
|
610
|
+
IDC.fail('invalid_argument', 'Font style "' + String(styleName) + '" is not available for "' + before.family + '" – use get_font_info_at_index for the exact style names (e.g. "75 Bold").',
|
|
611
|
+
{ font_style: styleName, font_family: before.family, available_styles: before.family === null ? [] : fonts.stylesOf(before.family) });
|
|
612
|
+
}
|
|
613
|
+
after = idcReadFontLoose(reader);
|
|
614
|
+
if (after.style === null || !idcSameText(after.style, styleName)) {
|
|
615
|
+
IDC.fail('invalid_argument', 'Font style "' + String(styleName) + '" is not available for "' + before.family + '"; InDesign kept "' + after.style + '" – use get_font_info_at_index for the exact style names.',
|
|
616
|
+
{ font_style: styleName, font_family: before.family, available_styles: before.family === null ? [] : fonts.stylesOf(before.family) });
|
|
617
|
+
}
|
|
618
|
+
applied.push('font_style');
|
|
619
|
+
return applied;
|
|
620
|
+
}
|
|
621
|
+
return applied;
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
/* Gemeinsame Attribute von define_paragraph_style und define_character_style. */
|
|
625
|
+
function idcApplyStyleAttributes(ctx, doc, style, args, created, kind) {
|
|
626
|
+
var applied = [];
|
|
627
|
+
var fontApplied, leading, swatch, hex;
|
|
628
|
+
|
|
629
|
+
if (idcGiven(args.font_family) || idcGiven(args.font_style)) {
|
|
630
|
+
fontApplied = idcApplyFont(ctx, style, args.font_family, args.font_style, idcFontLookup());
|
|
631
|
+
applied = applied.concat(fontApplied);
|
|
632
|
+
}
|
|
633
|
+
if (kind === 'paragraph' && idcGiven(args.size_pt)) {
|
|
634
|
+
idcNumberArg(args.size_pt, 'size_pt', 0.1, 1296);
|
|
635
|
+
IDC.inPoints(function () { style.pointSize = args.size_pt; });
|
|
636
|
+
applied.push('size_pt');
|
|
637
|
+
}
|
|
638
|
+
if (kind === 'character' && idcGiven(args.point_size)) {
|
|
639
|
+
idcNumberArg(args.point_size, 'point_size', 0.1, 1296);
|
|
640
|
+
IDC.inPoints(function () { style.pointSize = args.point_size; });
|
|
641
|
+
applied.push('point_size');
|
|
642
|
+
}
|
|
643
|
+
if (idcGiven(args.leading_pt)) {
|
|
644
|
+
leading = args.leading_pt;
|
|
645
|
+
if (leading === 'auto') {
|
|
646
|
+
if (typeof Leading === 'undefined') { IDC.fail('invalid_state', 'This runtime has no Leading enumeration.', null); }
|
|
647
|
+
style.leading = Leading.AUTO;
|
|
648
|
+
} else {
|
|
649
|
+
idcNumberArg(leading, 'leading_pt', 0, 5000);
|
|
650
|
+
IDC.inPoints(function () { style.leading = leading; });
|
|
651
|
+
}
|
|
652
|
+
applied.push('leading_pt');
|
|
653
|
+
}
|
|
654
|
+
if (idcGiven(args.alignment)) {
|
|
655
|
+
style.justification = idcJustificationFor(args.alignment, 'alignment');
|
|
656
|
+
applied.push('alignment');
|
|
657
|
+
}
|
|
658
|
+
hex = kind === 'paragraph' ? args.color_hex : args.fill_hex;
|
|
659
|
+
/* A-9.3: swatch_name setzt ein vorhandenes Farbfeld (CMYK, Vollton, Ton, Verlauf) statt ueber Hex ein RGB-Feld anzulegen. */
|
|
660
|
+
if (idcGiven(hex) && idcGiven(args.swatch_name)) {
|
|
661
|
+
IDC.fail('invalid_argument', 'Pass either ' + (kind === 'paragraph' ? 'color_hex' : 'fill_hex') + ' or swatch_name, not both.', null);
|
|
662
|
+
}
|
|
663
|
+
if (idcGiven(hex)) {
|
|
664
|
+
swatch = idcSwatchForHex(doc, hex, kind === 'paragraph' ? 'color_hex' : 'fill_hex', created);
|
|
665
|
+
style.fillColor = swatch;
|
|
666
|
+
applied.push(kind === 'paragraph' ? 'color_hex' : 'fill_hex');
|
|
667
|
+
}
|
|
668
|
+
if (idcGiven(args.swatch_name)) {
|
|
669
|
+
swatch = idcSwatchArg(doc, args.swatch_name, 'swatch_name');
|
|
670
|
+
style.fillColor = swatch;
|
|
671
|
+
applied.push('fill_swatch');
|
|
672
|
+
}
|
|
673
|
+
if (idcGiven(args.space_before_pt)) {
|
|
674
|
+
idcNumberArg(args.space_before_pt, 'space_before_pt', 0, 8640);
|
|
675
|
+
IDC.inPoints(function () { style.spaceBefore = args.space_before_pt; });
|
|
676
|
+
applied.push('space_before_pt');
|
|
677
|
+
}
|
|
678
|
+
if (idcGiven(args.space_after_pt)) {
|
|
679
|
+
idcNumberArg(args.space_after_pt, 'space_after_pt', 0, 8640);
|
|
680
|
+
IDC.inPoints(function () { style.spaceAfter = args.space_after_pt; });
|
|
681
|
+
applied.push('space_after_pt');
|
|
682
|
+
}
|
|
683
|
+
if (idcGiven(args.tracking)) {
|
|
684
|
+
idcNumberArg(args.tracking, 'tracking', -1000, 10000);
|
|
685
|
+
style.tracking = args.tracking;
|
|
686
|
+
applied.push('tracking');
|
|
687
|
+
}
|
|
688
|
+
if (idcGiven(args.hyphenation)) {
|
|
689
|
+
if (typeof args.hyphenation !== 'boolean') { IDC.fail('invalid_argument', 'hyphenation must be true or false.', { value: args.hyphenation }); }
|
|
690
|
+
style.hyphenation = args.hyphenation;
|
|
691
|
+
applied.push('hyphenation');
|
|
692
|
+
}
|
|
693
|
+
if (idcGiven(args.capitalization)) {
|
|
694
|
+
style.capitalization = idcCapitalizationFor(args.capitalization);
|
|
695
|
+
applied.push('capitalization');
|
|
696
|
+
}
|
|
697
|
+
if (kind === 'paragraph' && idcGiven(args.align_to_baseline_grid)) {
|
|
698
|
+
if (typeof args.align_to_baseline_grid !== 'boolean') {
|
|
699
|
+
IDC.fail('invalid_argument', 'align_to_baseline_grid must be true or false.', { value: args.align_to_baseline_grid });
|
|
700
|
+
}
|
|
701
|
+
if (typeof GridAlignment === 'undefined') { IDC.fail('invalid_state', 'This runtime has no GridAlignment enumeration.', null); }
|
|
702
|
+
style.gridAlignment = args.align_to_baseline_grid ? GridAlignment.ALIGN_BASELINE : GridAlignment.NONE;
|
|
703
|
+
applied.push('align_to_baseline_grid');
|
|
704
|
+
}
|
|
705
|
+
/* A-79, Sitzung 82 (E-117 Nachtrag 1): PDF-Tag des Formats */
|
|
706
|
+
if (idcGiven(args.pdf_tag)) {
|
|
707
|
+
idcApplyPdfTag(style, args.pdf_tag);
|
|
708
|
+
applied.push('pdf_tag');
|
|
709
|
+
}
|
|
710
|
+
if (kind === 'paragraph') {
|
|
711
|
+
applied = applied.concat(idcApplyCompositionOptions(style, args));
|
|
712
|
+
applied = applied.concat(idcApplyIndentTabLanguage(doc, style, args, ctx));
|
|
713
|
+
if (idcGiven(args.drop_cap)) { applied = applied.concat(idcApplyDropCap(style, idcDropCapArg(doc, args.drop_cap))); }
|
|
714
|
+
}
|
|
715
|
+
return applied;
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
/*
|
|
719
|
+
* Farbfelder wieder entfernen, die dieser Aufruf angelegt hat (Ruecknahme).
|
|
720
|
+
* Nur ueber die ID, damit kein gleichnamiges Farbfeld des Hefts getroffen wird.
|
|
721
|
+
*/
|
|
722
|
+
function idcRemoveSwatchesById(doc, ids) {
|
|
723
|
+
var i, j, swatch, id;
|
|
724
|
+
if (!ids || ids.length === 0) { return; }
|
|
725
|
+
for (i = 0; i < ids.length; i++) {
|
|
726
|
+
id = Number(ids[i]);
|
|
727
|
+
for (j = doc.swatches.length - 1; j >= 0; j--) {
|
|
728
|
+
swatch = doc.swatches.item(j);
|
|
729
|
+
try {
|
|
730
|
+
if (Number(swatch.id) === id) { swatch.remove(); break; }
|
|
731
|
+
} catch (e) { /* naechstes */ }
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
/* ---------------------------------------------------- list_paragraph_styles */
|
|
737
|
+
|
|
738
|
+
IDC.register('list_paragraph_styles', { needs_document: true, read_only: true, ruler: 'none' },
|
|
739
|
+
function (ctx) {
|
|
740
|
+
var doc = ctx.doc;
|
|
741
|
+
var styles = [];
|
|
742
|
+
var characterStyles = [];
|
|
743
|
+
var internal = 0;
|
|
744
|
+
var all, i, entry, name;
|
|
745
|
+
|
|
746
|
+
all = idcAllStyles(doc, 'paragraph');
|
|
747
|
+
for (i = 0; i < all.length; i++) {
|
|
748
|
+
try { name = String(all[i].name); } catch (e1) { continue; }
|
|
749
|
+
if (name.charAt(0) === '[') { internal += 1; continue; }
|
|
750
|
+
entry = idcDescribeParagraphStyle(all[i]);
|
|
751
|
+
styles.push(entry);
|
|
752
|
+
}
|
|
753
|
+
all = idcAllStyles(doc, 'character');
|
|
754
|
+
for (i = 0; i < all.length; i++) {
|
|
755
|
+
try { name = String(all[i].name); } catch (e2) { continue; }
|
|
756
|
+
if (name.charAt(0) === '[') { internal += 1; continue; }
|
|
757
|
+
characterStyles.push(idcDescribeCharacterStyle(all[i]));
|
|
758
|
+
}
|
|
759
|
+
return {
|
|
760
|
+
styles: styles,
|
|
761
|
+
count: styles.length,
|
|
762
|
+
character_styles: characterStyles,
|
|
763
|
+
character_style_count: characterStyles.length,
|
|
764
|
+
internal_styles_excluded: internal
|
|
765
|
+
};
|
|
766
|
+
});
|
|
767
|
+
|
|
768
|
+
/* ------------------------------------------- Elternformat und Formatgruppe (A-60) */
|
|
769
|
+
|
|
770
|
+
/*
|
|
771
|
+
* Direktes Kind einer Sammlung (Formate oder Gruppen einer Ebene) ueber den
|
|
772
|
+
* Namen – per Schleife, nie per itemByName: InDesign liefert dort fuer den
|
|
773
|
+
* Namen eines Formats auch einen gueltigen Gruppenverweis und umgekehrt,
|
|
774
|
+
* auf jeder Ebene (Live-Fund 23.10.2026, Sitzungen 66 und 67).
|
|
775
|
+
*/
|
|
776
|
+
function idcDirectChildByName(collection, name) {
|
|
777
|
+
var i, item;
|
|
778
|
+
try {
|
|
779
|
+
for (i = 0; i < collection.length; i++) {
|
|
780
|
+
item = collection.item(i);
|
|
781
|
+
if (String(item.name) === String(name)) { return item; }
|
|
782
|
+
}
|
|
783
|
+
} catch (e) { /* leer */ }
|
|
784
|
+
return null;
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
function idcStylesOf(container, kind) {
|
|
788
|
+
return kind === 'character' ? container.characterStyles : container.paragraphStyles;
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
function idcGroupsOf(container, kind) {
|
|
792
|
+
return kind === 'character' ? container.characterStyleGroups : container.paragraphStyleGroups;
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
/* group: "A/B" oder ["A", "B"] – Liste der Gruppennamen, [] = oberste Ebene, null = nicht angegeben. */
|
|
796
|
+
function idcGroupPathArg(value) {
|
|
797
|
+
var parts, i, out = [];
|
|
798
|
+
if (!idcGiven(value)) { return null; }
|
|
799
|
+
if (typeof value === 'string') {
|
|
800
|
+
if (value === '') { return []; }
|
|
801
|
+
parts = value.split('/');
|
|
802
|
+
} else if (IDC.isArray(value)) {
|
|
803
|
+
parts = value;
|
|
804
|
+
} else {
|
|
805
|
+
IDC.fail('invalid_argument', 'group must be a path such as "Headings/Main" or a list of group names.', { value: value });
|
|
806
|
+
}
|
|
807
|
+
for (i = 0; i < parts.length; i++) {
|
|
808
|
+
if (typeof parts[i] !== 'string' || parts[i].length === 0) {
|
|
809
|
+
IDC.fail('invalid_argument', 'group contains an empty group name – write "Headings/Main" without leading, trailing or double "/", or pass a list of names.', { value: value });
|
|
810
|
+
}
|
|
811
|
+
out.push(parts[i]);
|
|
812
|
+
}
|
|
813
|
+
return out;
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
/* Vorhandene Gruppe zum Pfad, ohne etwas anzulegen; null, wenn ein Glied fehlt. */
|
|
817
|
+
function idcFindGroup(doc, segments, kind) {
|
|
818
|
+
var container = doc;
|
|
819
|
+
var i;
|
|
820
|
+
for (i = 0; i < segments.length; i++) {
|
|
821
|
+
container = idcDirectChildByName(idcGroupsOf(container, kind), segments[i]);
|
|
822
|
+
if (container === null) { return null; }
|
|
823
|
+
}
|
|
824
|
+
return container;
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
function idcGroupNameClash(segments, index, kind) {
|
|
828
|
+
var what = kind === 'character' ? 'character' : 'paragraph';
|
|
829
|
+
IDC.fail('invalid_state', 'Cannot create the ' + what + ' style group "' + segments[index] + '": a ' + what + ' style of that name exists at the same level, and InDesign allows no group of the same name beside it. Choose another group name.',
|
|
830
|
+
{ code: 'style_group_name', group: segments.slice(0, index + 1).join('/') });
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
/* Gruppenpfad anlegen, wo er fehlt; neu angelegte Gruppen landen in created (fuer die Ruecknahme). */
|
|
834
|
+
function idcEnsureGroup(doc, segments, kind, created) {
|
|
835
|
+
var container = doc;
|
|
836
|
+
var i, next;
|
|
837
|
+
for (i = 0; i < segments.length; i++) {
|
|
838
|
+
next = idcDirectChildByName(idcGroupsOf(container, kind), segments[i]);
|
|
839
|
+
if (next === null) {
|
|
840
|
+
if (idcDirectChildByName(idcStylesOf(container, kind), segments[i]) !== null) { idcGroupNameClash(segments, i, kind); }
|
|
841
|
+
try {
|
|
842
|
+
next = idcGroupsOf(container, kind).add({ name: segments[i] });
|
|
843
|
+
} catch (e) {
|
|
844
|
+
IDC.fail('script_error', 'InDesign could not create the style group "' + segments[i] + '": ' + String(e.message ? e.message : e), { group: segments.slice(0, i + 1).join('/') });
|
|
845
|
+
}
|
|
846
|
+
created.push(next);
|
|
847
|
+
}
|
|
848
|
+
container = next;
|
|
849
|
+
}
|
|
850
|
+
return container;
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
/* Alle Formate dieser Art mit genau diesem Namen (Gruppen eingeschlossen). */
|
|
854
|
+
function idcStylesNamed(doc, name, kind) {
|
|
855
|
+
var all = idcAllStyles(doc, kind);
|
|
856
|
+
var out = [];
|
|
857
|
+
var i;
|
|
858
|
+
for (i = 0; i < all.length; i++) {
|
|
859
|
+
try { if (String(all[i].name) === String(name)) { out.push(all[i]); } } catch (e) { /* naechstes */ }
|
|
860
|
+
}
|
|
861
|
+
return out;
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
/*
|
|
865
|
+
* Elternformat zu based_on: zuerst als Pfad "Gruppe/Format", dann als Name
|
|
866
|
+
* (wie die Anwende-Werkzeuge). Die internen Wurzeln auch unter ihrem
|
|
867
|
+
* Skriptnamen, den die deutsche Fassung ueber itemByName nicht findet
|
|
868
|
+
* (Live-Fund 23.10.2026): "[No Paragraph Style]", "[Basic Paragraph]", "[None]".
|
|
869
|
+
*/
|
|
870
|
+
function idcParentStyleArg(ctx, doc, value, kind) {
|
|
871
|
+
var parts, group, found, named;
|
|
872
|
+
if (typeof value !== 'string' || value.length === 0) {
|
|
873
|
+
IDC.fail('invalid_argument', 'based_on must be the name of an existing style.', { value: value });
|
|
874
|
+
}
|
|
875
|
+
if (kind === 'paragraph' && value === '[No Paragraph Style]') { return doc.paragraphStyles.item(0); }
|
|
876
|
+
if (kind === 'paragraph' && value === '[Basic Paragraph]') { return doc.paragraphStyles.item(1); }
|
|
877
|
+
if (kind === 'character' && value === '[None]') { return idcNoneCharacterStyle(doc); }
|
|
878
|
+
if (value.indexOf('/') > 0) {
|
|
879
|
+
parts = value.split('/');
|
|
880
|
+
group = idcFindGroup(doc, parts.slice(0, parts.length - 1), kind);
|
|
881
|
+
if (group !== null) {
|
|
882
|
+
found = idcDirectChildByName(idcStylesOf(group, kind), parts[parts.length - 1]);
|
|
883
|
+
if (found !== null) { return found; }
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
found = kind === 'character' ? idcCharacterStyleByName(doc, value) : IDC.paragraphStyleByName(doc, value);
|
|
887
|
+
if (found === null) {
|
|
888
|
+
IDC.fail('not_found', (kind === 'character' ? 'Character' : 'Paragraph') + ' style "' + value + '" for based_on not found – ' +
|
|
889
|
+
(kind === 'character' ? 'list_paragraph_styles lists the character styles; "[None]" is the root.' : 'list_paragraph_styles shows the names; "[Basic Paragraph]" and "[No Paragraph Style]" are the built-in ones.') +
|
|
890
|
+
' A style in a group can be named as "Group/Style".', { code: 'based_on_not_found', based_on: value });
|
|
891
|
+
}
|
|
892
|
+
named = idcStylesNamed(doc, value, kind);
|
|
893
|
+
if (named.length > 1) {
|
|
894
|
+
ctx.warn('Several ' + kind + ' styles are named "' + value + '"; based_on took the one in "' + idcStyleGroupPath(found) + '" (top level when empty) – pass "Group/Style" to choose another.');
|
|
895
|
+
}
|
|
896
|
+
return found;
|
|
897
|
+
}
|
|
898
|
+
|
|
899
|
+
/* Zirkel: Liegt style schon in der Kette ueber parent (oder ist es selbst)? InDesign lehnt das ab (Live-Fund 23.10.2026). */
|
|
900
|
+
function idcBasedOnCycle(style, parent) {
|
|
901
|
+
var current = parent;
|
|
902
|
+
var target, step, id;
|
|
903
|
+
try { target = Number(style.id); } catch (e) { return false; }
|
|
904
|
+
for (step = 0; step < 100; step++) {
|
|
905
|
+
if (!idcPresent(current)) { return false; }
|
|
906
|
+
try { id = Number(current.id); } catch (e1) { return false; }
|
|
907
|
+
if (isNaN(id)) { return false; }
|
|
908
|
+
if (id === target) { return true; }
|
|
909
|
+
try { current = current.basedOn; } catch (e2) { return false; }
|
|
910
|
+
if (typeof current === 'string' || idcIsNothing(current)) { return false; }
|
|
911
|
+
}
|
|
912
|
+
return false;
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
/* --------------------------------------- define_paragraph_style / define_character_style */
|
|
916
|
+
|
|
917
|
+
function idcDefineStyle(ctx, kind) {
|
|
918
|
+
var args = ctx.args;
|
|
919
|
+
var doc = ctx.doc;
|
|
920
|
+
var what = kind === 'character' ? 'Character' : 'Paragraph';
|
|
921
|
+
var name = idcStyleNameArg(args.name, 'name');
|
|
922
|
+
var onCollision = idcCollisionArg(args.on_collision);
|
|
923
|
+
var segments = idcGroupPathArg(args.group);
|
|
924
|
+
var parent = null;
|
|
925
|
+
var container = doc;
|
|
926
|
+
var existing, clash, elsewhere, i;
|
|
927
|
+
var collision = 'none';
|
|
928
|
+
var chosenName = name;
|
|
929
|
+
var createdSwatches = [];
|
|
930
|
+
var createdGroups = [];
|
|
931
|
+
var style = null;
|
|
932
|
+
var isNew = false;
|
|
933
|
+
var applied = [];
|
|
934
|
+
var changes, groupIds;
|
|
935
|
+
|
|
936
|
+
if (kind === 'character' && !idcGiven(args.font_family) && !idcGiven(args.font_style) && !idcGiven(args.point_size) && !idcGiven(args.fill_hex) && !idcGiven(args.swatch_name) && !idcGiven(args.tracking) && !idcGiven(args.based_on) && !idcGiven(args.capitalization) && !idcGiven(args.pdf_tag)) {
|
|
937
|
+
IDC.fail('invalid_argument', 'At least one attribute is required: font_family, font_style, point_size, fill_hex, swatch_name, tracking, capitalization, pdf_tag or based_on.', null);
|
|
938
|
+
}
|
|
939
|
+
/* A-68 (3): Schreibweise vor jeder Aenderung pruefen. */
|
|
940
|
+
if (idcGiven(args.capitalization)) { idcCapitalizationFor(args.capitalization); }
|
|
941
|
+
if (idcGiven(args.pdf_tag)) { idcPdfTagArg(args.pdf_tag); }
|
|
942
|
+
if (idcGiven(args.based_on)) { parent = idcParentStyleArg(ctx, doc, args.based_on, kind); }
|
|
943
|
+
|
|
944
|
+
if (segments === null) {
|
|
945
|
+
/* Ohne group wie bis 1.0.2: Name im ganzen Dokument, Gruppenname auf oberster Ebene. */
|
|
946
|
+
existing = kind === 'character' ? idcCharacterStyleByName(doc, name) : IDC.paragraphStyleByName(doc, name);
|
|
947
|
+
} else {
|
|
948
|
+
/* Mit group: Formate und Gruppen dieser einen Ebene; eine noch fehlende Gruppe hat keine. */
|
|
949
|
+
container = segments.length === 0 ? doc : idcFindGroup(doc, segments, kind);
|
|
950
|
+
existing = container === null ? null : idcDirectChildByName(idcStylesOf(container, kind), name);
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
if (existing !== null) {
|
|
954
|
+
if (onCollision === 'error') {
|
|
955
|
+
IDC.fail('invalid_state', what + ' style "' + name + '" exists already. Pass on_collision "update" to change it or "version" to add "' + name + ' 2".',
|
|
956
|
+
{ name: name, style_id: (function () { try { return Number(existing.id); } catch (e) { return null; } })() });
|
|
957
|
+
}
|
|
958
|
+
if (onCollision === 'update') {
|
|
959
|
+
style = existing;
|
|
960
|
+
collision = 'updated';
|
|
961
|
+
} else {
|
|
962
|
+
chosenName = idcFreeName(doc, name, kind, container);
|
|
963
|
+
collision = 'versioned';
|
|
964
|
+
}
|
|
965
|
+
} else if (segments === null) {
|
|
966
|
+
if (idcGroupNameCollision(doc, name, kind, onCollision)) {
|
|
967
|
+
chosenName = idcFreeName(doc, name, kind, doc);
|
|
968
|
+
collision = 'versioned';
|
|
969
|
+
}
|
|
970
|
+
} else if (container !== null) {
|
|
971
|
+
clash = idcDirectChildByName(idcGroupsOf(container, kind), name);
|
|
972
|
+
if (clash !== null) {
|
|
973
|
+
if (onCollision !== 'version') {
|
|
974
|
+
IDC.fail('invalid_state', '"' + name + '" is the name of a ' + kind + ' style group in "' + segments.join('/') + '"; InDesign allows no ' + kind + ' style of the same name beside it. Choose another name or pass on_collision "version" to add "' + name + ' 2".',
|
|
975
|
+
{ code: 'style_group_name', name: name, group_id: (function () { try { return Number(clash.id); } catch (e) { return null; } })() });
|
|
976
|
+
}
|
|
977
|
+
chosenName = idcFreeName(doc, name, kind, container);
|
|
978
|
+
collision = 'versioned';
|
|
979
|
+
}
|
|
980
|
+
}
|
|
981
|
+
if (segments !== null && collision !== 'updated') {
|
|
982
|
+
elsewhere = idcStylesNamed(doc, chosenName, kind);
|
|
983
|
+
if (elsewhere.length > 0) {
|
|
984
|
+
ctx.warn('A ' + kind + ' style "' + chosenName + '" exists in "' + idcStyleGroupPath(elsewhere[0]) + '" (top level when empty) as well; tools that take a style name use the first match – keep names unique where you can.');
|
|
985
|
+
}
|
|
986
|
+
}
|
|
987
|
+
if (style !== null && parent !== null && idcBasedOnCycle(style, parent)) {
|
|
988
|
+
IDC.fail('invalid_state', what + ' style "' + name + '" cannot be based on "' + args.based_on + '": that style is "' + name + '" itself or based on it (circular based-on).',
|
|
989
|
+
{ code: 'based_on_cycle', name: name, based_on: args.based_on });
|
|
990
|
+
}
|
|
991
|
+
|
|
992
|
+
try {
|
|
993
|
+
if (style === null) {
|
|
994
|
+
if (segments !== null && container === null) { container = idcEnsureGroup(doc, segments, kind, createdGroups); }
|
|
995
|
+
try {
|
|
996
|
+
style = idcStylesOf(container, kind).add({ name: chosenName });
|
|
997
|
+
} catch (e) {
|
|
998
|
+
IDC.fail('script_error', 'InDesign could not create the ' + kind + ' style "' + chosenName + '": ' + String(e.message ? e.message : e), { name: chosenName });
|
|
999
|
+
}
|
|
1000
|
+
isNew = true;
|
|
1001
|
+
}
|
|
1002
|
+
if (parent !== null) {
|
|
1003
|
+
try {
|
|
1004
|
+
style.basedOn = parent;
|
|
1005
|
+
} catch (e3) {
|
|
1006
|
+
IDC.fail('invalid_state', 'InDesign rejects "' + args.based_on + '" as based_on for "' + chosenName + '": ' + String(e3.message ? e3.message : e3), { code: 'based_on_rejected', based_on: args.based_on });
|
|
1007
|
+
}
|
|
1008
|
+
applied.push('based_on');
|
|
1009
|
+
}
|
|
1010
|
+
if (segments !== null && isNew) { applied.push('group'); }
|
|
1011
|
+
applied = applied.concat(idcApplyStyleAttributes(ctx, doc, style, args, createdSwatches, kind));
|
|
1012
|
+
} catch (err) {
|
|
1013
|
+
/* Nichts Halbfertiges (E-46): neues Format, neue Farbfelder und neue Gruppen wieder weg; ein mit update geaendertes Format bleibt. */
|
|
1014
|
+
if (isNew && style !== null) {
|
|
1015
|
+
try { style.remove(); } catch (e4) { /* bleibt stehen */ }
|
|
1016
|
+
}
|
|
1017
|
+
try { idcRemoveSwatchesById(doc, createdSwatches); } catch (e5) { /* bleibt stehen */ }
|
|
1018
|
+
for (i = createdGroups.length - 1; i >= 0; i--) {
|
|
1019
|
+
try { createdGroups[i].remove(); } catch (e6) { /* bleibt stehen */ }
|
|
1020
|
+
}
|
|
1021
|
+
throw err;
|
|
1022
|
+
}
|
|
1023
|
+
|
|
1024
|
+
changes = collision === 'updated'
|
|
1025
|
+
? { modified_style_ids: [Number(style.id)] }
|
|
1026
|
+
: { created_style_ids: [Number(style.id)] };
|
|
1027
|
+
if (createdSwatches.length > 0) { changes.created_swatch_ids = createdSwatches; }
|
|
1028
|
+
groupIds = [];
|
|
1029
|
+
for (i = 0; i < createdGroups.length; i++) {
|
|
1030
|
+
try { groupIds.push(Number(createdGroups[i].id)); } catch (e7) { /* ohne ID */ }
|
|
1031
|
+
}
|
|
1032
|
+
if (groupIds.length > 0) { changes.created_group_ids = groupIds; }
|
|
1033
|
+
ctx.changes = changes;
|
|
1034
|
+
return {
|
|
1035
|
+
style_id: Number(style.id),
|
|
1036
|
+
name: String(style.name),
|
|
1037
|
+
collision: collision,
|
|
1038
|
+
existed: existing !== null || collision === 'versioned',
|
|
1039
|
+
applied: applied,
|
|
1040
|
+
based_on: idcBasedOnName(style),
|
|
1041
|
+
group: idcStyleGroupPath(style),
|
|
1042
|
+
created_groups: (function () {
|
|
1043
|
+
var paths = [];
|
|
1044
|
+
var k;
|
|
1045
|
+
for (k = 0; k < createdGroups.length; k++) { paths.push(segments.slice(0, segments.length - createdGroups.length + k + 1).join('/')); }
|
|
1046
|
+
return paths;
|
|
1047
|
+
})(),
|
|
1048
|
+
definition: kind === 'character' ? idcDescribeCharacterStyle(style) : idcDescribeParagraphStyle(style)
|
|
1049
|
+
};
|
|
1050
|
+
}
|
|
1051
|
+
|
|
1052
|
+
IDC.register('define_paragraph_style', { needs_document: true, read_only: false, ruler: 'none' },
|
|
1053
|
+
function (ctx) { return idcDefineStyle(ctx, 'paragraph'); });
|
|
1054
|
+
|
|
1055
|
+
IDC.register('define_character_style', { needs_document: true, read_only: false, ruler: 'none' },
|
|
1056
|
+
function (ctx) { return idcDefineStyle(ctx, 'character'); });
|
|
1057
|
+
|
|
1058
|
+
/* --------------------------------------------------------- Zeichenbereiche */
|
|
1059
|
+
|
|
1060
|
+
/*
|
|
1061
|
+
* Zeichenbereich [start_index, end_index) einer Story wie in Bereich G:
|
|
1062
|
+
* start einschliesslich, end ausschliesslich, beide aus get_frame_text.
|
|
1063
|
+
* Liefert { start, end, text } mit text = characters.itemByRange(start, end - 1).
|
|
1064
|
+
*/
|
|
1065
|
+
function idcRangeArg(story, args, allowEmpty) {
|
|
1066
|
+
var start = args.start_index;
|
|
1067
|
+
var end = args.end_index;
|
|
1068
|
+
var length = 0;
|
|
1069
|
+
var text;
|
|
1070
|
+
if (typeof start !== 'number' || Math.floor(start) !== start || start < 0) {
|
|
1071
|
+
IDC.fail('invalid_argument', 'start_index must be a whole number of 0 or more (inclusive).', { start_index: start });
|
|
1072
|
+
}
|
|
1073
|
+
if (typeof end !== 'number' || Math.floor(end) !== end || end < start) {
|
|
1074
|
+
IDC.fail('invalid_argument', 'end_index must be a whole number not smaller than start_index (exclusive).', { start_index: start, end_index: end });
|
|
1075
|
+
}
|
|
1076
|
+
try { length = Number(story.characters.length); } catch (e0) { length = 0; }
|
|
1077
|
+
if (end > length) {
|
|
1078
|
+
IDC.fail('invalid_argument', 'end_index ' + end + ' exceeds the story length ' + length + '.', { end_index: end, story_length: length });
|
|
1079
|
+
}
|
|
1080
|
+
if (end === start && allowEmpty !== true) {
|
|
1081
|
+
IDC.fail('invalid_argument', 'The range is empty (start_index equals end_index); formatting needs at least one character.', { start_index: start, end_index: end });
|
|
1082
|
+
}
|
|
1083
|
+
try {
|
|
1084
|
+
text = story.characters.itemByRange(start, end - 1);
|
|
1085
|
+
} catch (e) {
|
|
1086
|
+
IDC.fail('script_error', 'InDesign could not address characters ' + start + '–' + end + ': ' + String(e.message ? e.message : e),
|
|
1087
|
+
{ start_index: start, end_index: end });
|
|
1088
|
+
}
|
|
1089
|
+
return { start: start, end: end, text: text };
|
|
1090
|
+
}
|
|
1091
|
+
|
|
1092
|
+
/* Erstes Zeichen eines Bereichs (fuer Gegenproben). */
|
|
1093
|
+
function idcFirstCharacter(story, index) {
|
|
1094
|
+
try { return story.characters.item(index); } catch (e) { return null; }
|
|
1095
|
+
}
|
|
1096
|
+
|
|
1097
|
+
/*
|
|
1098
|
+
* Absatzformat sauber zuweisen: Format mit "Abweichungen loeschen", danach
|
|
1099
|
+
* Zeichenformat [None], alle lokalen Abweichungen weg, Format noch einmal.
|
|
1100
|
+
* So stimmt nicht nur der Formatname, sondern auch der Druck.
|
|
1101
|
+
*/
|
|
1102
|
+
function idcApplyParagraphStyleClean(doc, textObject, style, clearOverrides) {
|
|
1103
|
+
var none;
|
|
1104
|
+
try {
|
|
1105
|
+
textObject.applyParagraphStyle(style, clearOverrides === true);
|
|
1106
|
+
} catch (e) {
|
|
1107
|
+
textObject.appliedParagraphStyle = style;
|
|
1108
|
+
}
|
|
1109
|
+
if (clearOverrides !== true) { return; }
|
|
1110
|
+
none = idcNoneCharacterStyle(doc);
|
|
1111
|
+
if (none !== null) {
|
|
1112
|
+
try { textObject.applyCharacterStyle(none); } catch (e1) {
|
|
1113
|
+
try { textObject.appliedCharacterStyle = none; } catch (e1b) { /* dann bleibt es */ }
|
|
1114
|
+
}
|
|
1115
|
+
}
|
|
1116
|
+
try {
|
|
1117
|
+
if (typeof OverrideType !== 'undefined') { textObject.clearOverrides(OverrideType.ALL); }
|
|
1118
|
+
else { textObject.clearOverrides(); }
|
|
1119
|
+
} catch (e2) { /* nicht ueberall vorhanden */ }
|
|
1120
|
+
try {
|
|
1121
|
+
textObject.applyParagraphStyle(style, true);
|
|
1122
|
+
} catch (e3) {
|
|
1123
|
+
textObject.appliedParagraphStyle = style;
|
|
1124
|
+
}
|
|
1125
|
+
}
|
|
1126
|
+
|
|
1127
|
+
function idcParagraphStyleArg(doc, name, field) {
|
|
1128
|
+
var style;
|
|
1129
|
+
if (typeof name !== 'string' || name.length === 0) {
|
|
1130
|
+
IDC.fail('invalid_argument', field + ' is required.', null);
|
|
1131
|
+
}
|
|
1132
|
+
style = IDC.paragraphStyleByName(doc, name);
|
|
1133
|
+
if (style === null) {
|
|
1134
|
+
IDC.fail('not_found', 'Paragraph style "' + name + '" not found – list_paragraph_styles shows the names (groups as "Gruppe/Name" are matched by the style name alone).',
|
|
1135
|
+
{ style_name: name });
|
|
1136
|
+
}
|
|
1137
|
+
return style;
|
|
1138
|
+
}
|
|
1139
|
+
|
|
1140
|
+
/* Absaetze der Story (als Array), die den Zeichenbereich [start, end) beruehren. */
|
|
1141
|
+
function idcStoryParagraphsInRange(story, start, end) {
|
|
1142
|
+
var out = [];
|
|
1143
|
+
var i, p, position = 0, length;
|
|
1144
|
+
try {
|
|
1145
|
+
for (i = 0; i < story.paragraphs.length; i++) {
|
|
1146
|
+
p = story.paragraphs.item(i);
|
|
1147
|
+
try { length = Number(p.characters.length); } catch (e1) { length = 0; }
|
|
1148
|
+
if (position < end && position + length > start) { out.push(p); }
|
|
1149
|
+
position += length;
|
|
1150
|
+
if (position >= end) { break; }
|
|
1151
|
+
}
|
|
1152
|
+
} catch (e) { /* was da ist */ }
|
|
1153
|
+
return out;
|
|
1154
|
+
}
|
|
1155
|
+
|
|
1156
|
+
function idcParagraphStart(paragraph) {
|
|
1157
|
+
try { return Number(paragraph.characters.item(0).index); } catch (e) { return null; }
|
|
1158
|
+
}
|
|
1159
|
+
|
|
1160
|
+
function idcParagraphEnd(paragraph) {
|
|
1161
|
+
var start = idcParagraphStart(paragraph);
|
|
1162
|
+
if (start === null) { return null; }
|
|
1163
|
+
try { return start + Number(paragraph.characters.length); } catch (e) { return null; }
|
|
1164
|
+
}
|
|
1165
|
+
|
|
1166
|
+
/* ---------------------------------------------------- apply_paragraph_style */
|
|
1167
|
+
|
|
1168
|
+
IDC.register('apply_paragraph_style', { needs_document: true, read_only: false, ruler: 'none' },
|
|
1169
|
+
function (ctx) {
|
|
1170
|
+
var args = ctx.args;
|
|
1171
|
+
var doc = ctx.doc;
|
|
1172
|
+
var found = idcTextFrameArg(doc, args, 'frame_id');
|
|
1173
|
+
var frame = found.item;
|
|
1174
|
+
var style = idcParagraphStyleArg(doc, args.style_name, 'style_name');
|
|
1175
|
+
var clear = args.clear_overrides !== false;
|
|
1176
|
+
var paragraphs, count = 0, i, threaded;
|
|
1177
|
+
|
|
1178
|
+
idcRejectStoryLocked(idcContentStoryOf(frame), Number(frame.id), 'apply_paragraph_style');
|
|
1179
|
+
|
|
1180
|
+
try {
|
|
1181
|
+
paragraphs = frame.paragraphs;
|
|
1182
|
+
count = Number(paragraphs.length);
|
|
1183
|
+
} catch (e0) { count = 0; }
|
|
1184
|
+
if (count === 0) {
|
|
1185
|
+
ctx.warn('The frame holds no text; nothing was formatted.');
|
|
1186
|
+
return { frame_id: Number(frame.id), style_applied: String(style.name), affected_paragraphs: 0, overrides_cleared: clear, threaded: idcIsThreaded(frame) };
|
|
1187
|
+
}
|
|
1188
|
+
try {
|
|
1189
|
+
for (i = 0; i < count; i++) {
|
|
1190
|
+
idcApplyParagraphStyleClean(doc, paragraphs.item(i), style, clear);
|
|
1191
|
+
}
|
|
1192
|
+
} catch (e) {
|
|
1193
|
+
IDC.fail('script_error', 'InDesign could not apply the paragraph style "' + args.style_name + '" to frame ' + args.frame_id + ': ' + String(e.message ? e.message : e),
|
|
1194
|
+
{ frame_id: args.frame_id, style_name: args.style_name, paragraphs_done: i });
|
|
1195
|
+
}
|
|
1196
|
+
threaded = idcIsThreaded(frame);
|
|
1197
|
+
if (threaded) {
|
|
1198
|
+
ctx.warn('The frame is threaded (verkettet): only the ' + count + ' paragraph(s) touching this frame were formatted – use apply_paragraph_style_to_range over the whole story for the rest.');
|
|
1199
|
+
}
|
|
1200
|
+
if (!clear) {
|
|
1201
|
+
ctx.warn('clear_overrides is false: local character formatting and character styles stay in place – the style name is right, the print may not be.');
|
|
1202
|
+
}
|
|
1203
|
+
ctx.changes = { modified_frame_ids: [Number(frame.id)] };
|
|
1204
|
+
return {
|
|
1205
|
+
frame_id: Number(frame.id),
|
|
1206
|
+
style_applied: String(style.name),
|
|
1207
|
+
affected_paragraphs: count,
|
|
1208
|
+
overrides_cleared: clear,
|
|
1209
|
+
threaded: threaded
|
|
1210
|
+
};
|
|
1211
|
+
});
|
|
1212
|
+
|
|
1213
|
+
/* ------------------------------------------- apply_paragraph_style_to_range */
|
|
1214
|
+
|
|
1215
|
+
IDC.register('apply_paragraph_style_to_range', { needs_document: true, read_only: false, ruler: 'none' },
|
|
1216
|
+
function (ctx) {
|
|
1217
|
+
var args = ctx.args;
|
|
1218
|
+
var doc = ctx.doc;
|
|
1219
|
+
var found = idcTextFrameArg(doc, args, 'frame_id');
|
|
1220
|
+
var frame = found.item;
|
|
1221
|
+
var story = idcStoryOf(frame);
|
|
1222
|
+
var style = idcParagraphStyleArg(doc, args.style_name, 'style_name');
|
|
1223
|
+
var range = idcRangeArg(story, args, false);
|
|
1224
|
+
var paragraphs, count = 0, i, first, firstStart = null, lastEnd = null, startChar;
|
|
1225
|
+
|
|
1226
|
+
idcRejectStoryLocked(story, Number(frame.id), 'apply_paragraph_style_to_range');
|
|
1227
|
+
|
|
1228
|
+
startChar = idcFirstCharacter(story, range.start);
|
|
1229
|
+
try {
|
|
1230
|
+
if (startChar !== null && String(startChar.contents).charCodeAt(0) === 13) {
|
|
1231
|
+
ctx.warn('start_index ' + range.start + ' is the paragraph mark of the preceding paragraph – that paragraph is formatted too. Start one character later to leave it alone.');
|
|
1232
|
+
}
|
|
1233
|
+
} catch (e0) { /* egal */ }
|
|
1234
|
+
|
|
1235
|
+
try {
|
|
1236
|
+
paragraphs = range.text.paragraphs;
|
|
1237
|
+
count = Number(paragraphs.length);
|
|
1238
|
+
} catch (e1) {
|
|
1239
|
+
IDC.fail('script_error', 'InDesign could not read the paragraphs of the range: ' + String(e1.message ? e1.message : e1), { start_index: range.start, end_index: range.end });
|
|
1240
|
+
}
|
|
1241
|
+
try {
|
|
1242
|
+
for (i = 0; i < count; i++) {
|
|
1243
|
+
idcApplyParagraphStyleClean(doc, paragraphs.item(i), style, true);
|
|
1244
|
+
}
|
|
1245
|
+
} catch (e) {
|
|
1246
|
+
IDC.fail('script_error', 'InDesign could not apply the paragraph style "' + args.style_name + '": ' + String(e.message ? e.message : e),
|
|
1247
|
+
{ frame_id: args.frame_id, style_name: args.style_name, paragraphs_done: i });
|
|
1248
|
+
}
|
|
1249
|
+
if (count > 0) {
|
|
1250
|
+
first = paragraphs.item(0);
|
|
1251
|
+
firstStart = idcParagraphStart(first);
|
|
1252
|
+
lastEnd = idcParagraphEnd(paragraphs.item(count - 1));
|
|
1253
|
+
}
|
|
1254
|
+
ctx.changes = { modified_frame_ids: [Number(frame.id)] };
|
|
1255
|
+
return {
|
|
1256
|
+
frame_id: Number(frame.id),
|
|
1257
|
+
story_id: (function () { try { return Number(story.id); } catch (e2) { return null; } })(),
|
|
1258
|
+
style_applied: String(style.name),
|
|
1259
|
+
affected_paragraphs: count,
|
|
1260
|
+
start_index: range.start,
|
|
1261
|
+
end_index: range.end,
|
|
1262
|
+
first_paragraph_start_index: firstStart,
|
|
1263
|
+
last_paragraph_end_index: lastEnd,
|
|
1264
|
+
overrides_cleared: true
|
|
1265
|
+
};
|
|
1266
|
+
});
|
|
1267
|
+
|
|
1268
|
+
/* ------------------------------------------- apply_character_style_to_range */
|
|
1269
|
+
|
|
1270
|
+
IDC.register('apply_character_style_to_range', { needs_document: true, read_only: false, ruler: 'none' },
|
|
1271
|
+
function (ctx) {
|
|
1272
|
+
var args = ctx.args;
|
|
1273
|
+
var doc = ctx.doc;
|
|
1274
|
+
var found = idcTextFrameArg(doc, args, 'frame_id');
|
|
1275
|
+
var frame = found.item;
|
|
1276
|
+
var story = idcStoryOf(frame);
|
|
1277
|
+
var name = args.character_style_name;
|
|
1278
|
+
var style, range;
|
|
1279
|
+
|
|
1280
|
+
if (typeof name !== 'string' || name.length === 0) {
|
|
1281
|
+
IDC.fail('invalid_argument', 'character_style_name is required.', null);
|
|
1282
|
+
}
|
|
1283
|
+
style = idcCharacterStyleByName(doc, name);
|
|
1284
|
+
if (style === null) {
|
|
1285
|
+
IDC.fail('not_found', 'Character style "' + name + '" not found – define it with define_character_style first; list_paragraph_styles lists the existing ones.',
|
|
1286
|
+
{ character_style_name: name });
|
|
1287
|
+
}
|
|
1288
|
+
range = idcRangeArg(story, args, false);
|
|
1289
|
+
idcRejectStoryLocked(story, Number(frame.id), 'apply_character_style_to_range');
|
|
1290
|
+
try {
|
|
1291
|
+
range.text.applyCharacterStyle(style);
|
|
1292
|
+
} catch (e) {
|
|
1293
|
+
try { range.text.appliedCharacterStyle = style; } catch (e2) {
|
|
1294
|
+
IDC.fail('script_error', 'InDesign could not apply the character style "' + name + '": ' + String(e.message ? e.message : e), { character_style_name: name });
|
|
1295
|
+
}
|
|
1296
|
+
}
|
|
1297
|
+
/*
|
|
1298
|
+
* Demo-Heft-Befund 9 (Sitzung 10): die Laufweite des Zeichenformats ersetzt
|
|
1299
|
+
* die des Absatzformats – die wirksame Laufweite am ersten Zeichen zurueckgeben.
|
|
1300
|
+
*/
|
|
1301
|
+
var styleTracking = idcReadNumberLoose(style, 'tracking', 1);
|
|
1302
|
+
var effective = null, paragraphTracking = null, firstChar = null, paragraphStyle = null;
|
|
1303
|
+
try { firstChar = idcFirstCharacter(story, range.start); } catch (e3) { firstChar = null; }
|
|
1304
|
+
if (firstChar !== null) {
|
|
1305
|
+
effective = idcReadNumberLoose(firstChar, 'tracking', 1);
|
|
1306
|
+
try { paragraphStyle = firstChar.appliedParagraphStyle; } catch (e4) { paragraphStyle = null; }
|
|
1307
|
+
if (paragraphStyle !== null && paragraphStyle !== undefined) { paragraphTracking = idcReadNumberLoose(paragraphStyle, 'tracking', 1); }
|
|
1308
|
+
}
|
|
1309
|
+
ctx.changes = { modified_frame_ids: [Number(frame.id)] };
|
|
1310
|
+
return {
|
|
1311
|
+
frame_id: Number(frame.id),
|
|
1312
|
+
characters_affected: range.end - range.start,
|
|
1313
|
+
style_applied: String(style.name),
|
|
1314
|
+
start_index: range.start,
|
|
1315
|
+
end_index: range.end,
|
|
1316
|
+
tracking: { effective: effective, character_style: styleTracking, paragraph_style: paragraphTracking }
|
|
1317
|
+
};
|
|
1318
|
+
});
|
|
1319
|
+
|
|
1320
|
+
/* ------------------------------------------ apply_character_format_to_range */
|
|
1321
|
+
|
|
1322
|
+
IDC.register('apply_character_format_to_range', { needs_document: true, read_only: false, ruler: 'none' },
|
|
1323
|
+
function (ctx) {
|
|
1324
|
+
var args = ctx.args;
|
|
1325
|
+
var doc = ctx.doc;
|
|
1326
|
+
var found = idcTextFrameArg(doc, args, 'frame_id');
|
|
1327
|
+
var frame = found.item;
|
|
1328
|
+
var story = idcStoryOf(frame);
|
|
1329
|
+
var applied = [];
|
|
1330
|
+
var range, swatch, first, font, sizeApplied = null, fill = null, lang = null, langRead = null;
|
|
1331
|
+
|
|
1332
|
+
if (!idcGiven(args.font_family) && !idcGiven(args.font_style) && !idcGiven(args.swatch_name) && !idcGiven(args.superscript) &&
|
|
1333
|
+
!idcGiven(args.tracking) && !idcGiven(args.point_size) && !idcGiven(args.language)) {
|
|
1334
|
+
IDC.fail('invalid_argument', 'At least one attribute is required: font_style, swatch_name, superscript, tracking, point_size or language.', null);
|
|
1335
|
+
}
|
|
1336
|
+
range = idcRangeArg(story, args, false);
|
|
1337
|
+
idcRejectStoryLocked(story, Number(frame.id), 'apply_character_format_to_range');
|
|
1338
|
+
/* A-78: Sprache vor jeder Aenderung aufloesen (gleicher Loeser wie define_paragraph_style). */
|
|
1339
|
+
if (idcGiven(args.language)) { lang = idcLanguageArg(doc, args.language, 'language', ctx); }
|
|
1340
|
+
|
|
1341
|
+
if (idcGiven(args.font_family) || idcGiven(args.font_style)) {
|
|
1342
|
+
applied = applied.concat(idcApplyFont(ctx, range.text, args.font_family, args.font_style, idcFontLookup(), idcFirstCharacter(story, range.start)));
|
|
1343
|
+
}
|
|
1344
|
+
if (idcGiven(args.swatch_name)) {
|
|
1345
|
+
swatch = idcSwatchByName(doc, args.swatch_name);
|
|
1346
|
+
if (!idcPresent(swatch)) {
|
|
1347
|
+
IDC.fail('not_found', 'Swatch "' + args.swatch_name + '" not found – create it with create_swatch (names are exact; the built-in ones are "Black", "Paper", "None").',
|
|
1348
|
+
{ swatch_name: args.swatch_name });
|
|
1349
|
+
}
|
|
1350
|
+
try { range.text.fillColor = swatch; } catch (e1) {
|
|
1351
|
+
IDC.fail('script_error', 'InDesign could not set the fill colour: ' + String(e1.message ? e1.message : e1), { swatch_name: args.swatch_name });
|
|
1352
|
+
}
|
|
1353
|
+
applied.push('swatch_name');
|
|
1354
|
+
}
|
|
1355
|
+
if (idcGiven(args.superscript)) {
|
|
1356
|
+
if (typeof args.superscript !== 'boolean') { IDC.fail('invalid_argument', 'superscript must be true or false.', { value: args.superscript }); }
|
|
1357
|
+
if (typeof Position === 'undefined') { IDC.fail('invalid_state', 'This runtime has no Position enumeration.', null); }
|
|
1358
|
+
try { range.text.position = args.superscript ? Position.SUPERSCRIPT : Position.NORMAL; } catch (e2) {
|
|
1359
|
+
IDC.fail('script_error', 'InDesign could not set the superscript position: ' + String(e2.message ? e2.message : e2), null);
|
|
1360
|
+
}
|
|
1361
|
+
applied.push('superscript');
|
|
1362
|
+
}
|
|
1363
|
+
if (idcGiven(args.tracking)) {
|
|
1364
|
+
idcNumberArg(args.tracking, 'tracking', -1000, 10000);
|
|
1365
|
+
/* Toleranz nur aus der Serverkonfiguration (tracking_warn_beyond, E-54); ohne Eintrag keine Warnung. */
|
|
1366
|
+
if (typeof args.tracking_warn_beyond === 'number' && isFinite(args.tracking_warn_beyond)
|
|
1367
|
+
&& Math.abs(args.tracking) > args.tracking_warn_beyond) {
|
|
1368
|
+
ctx.warn('tracking ' + args.tracking + ' is beyond the configured tolerance of \u00b1' + args.tracking_warn_beyond + ' (tracking_warn_beyond).');
|
|
1369
|
+
}
|
|
1370
|
+
try { range.text.tracking = args.tracking; } catch (e3) {
|
|
1371
|
+
IDC.fail('script_error', 'InDesign could not set the tracking: ' + String(e3.message ? e3.message : e3), null);
|
|
1372
|
+
}
|
|
1373
|
+
applied.push('tracking');
|
|
1374
|
+
}
|
|
1375
|
+
if (idcGiven(args.point_size)) {
|
|
1376
|
+
idcNumberArg(args.point_size, 'point_size', 0.1, 1296);
|
|
1377
|
+
try { IDC.inPoints(function () { range.text.pointSize = args.point_size; }); } catch (e4) {
|
|
1378
|
+
IDC.fail('script_error', 'InDesign could not set the point size: ' + String(e4.message ? e4.message : e4), null);
|
|
1379
|
+
}
|
|
1380
|
+
applied.push('point_size');
|
|
1381
|
+
}
|
|
1382
|
+
if (lang !== null) {
|
|
1383
|
+
try { range.text.appliedLanguage = lang; } catch (e5) {
|
|
1384
|
+
IDC.fail('script_error', 'InDesign could not set the language: ' + String(e5.message ? e5.message : e5), { language: args.language });
|
|
1385
|
+
}
|
|
1386
|
+
applied.push('language');
|
|
1387
|
+
}
|
|
1388
|
+
|
|
1389
|
+
first = idcFirstCharacter(story, range.start);
|
|
1390
|
+
if (first !== null) {
|
|
1391
|
+
sizeApplied = idcReadPt(first, 'pointSize');
|
|
1392
|
+
font = idcReadFontLoose(first);
|
|
1393
|
+
fill = idcReadSwatchName(first, 'fillColor');
|
|
1394
|
+
langRead = idcReadLanguage(first);
|
|
1395
|
+
} else {
|
|
1396
|
+
font = { family: null, style: null };
|
|
1397
|
+
}
|
|
1398
|
+
ctx.changes = { modified_frame_ids: [Number(frame.id)] };
|
|
1399
|
+
return {
|
|
1400
|
+
frame_id: Number(frame.id),
|
|
1401
|
+
start_index: range.start,
|
|
1402
|
+
end_index: range.end,
|
|
1403
|
+
characters_affected: range.end - range.start,
|
|
1404
|
+
applied: applied,
|
|
1405
|
+
point_size_applied: sizeApplied,
|
|
1406
|
+
font_family: font.family,
|
|
1407
|
+
font_style: font.style,
|
|
1408
|
+
fill_color: fill,
|
|
1409
|
+
language: langRead
|
|
1410
|
+
};
|
|
1411
|
+
});
|
|
1412
|
+
|
|
1413
|
+
/* ----------------------------------------------------- set_paragraph_options */
|
|
1414
|
+
|
|
1415
|
+
IDC.register('set_paragraph_options', { needs_document: true, read_only: false, ruler: 'none' },
|
|
1416
|
+
function (ctx) {
|
|
1417
|
+
var args = ctx.args;
|
|
1418
|
+
var doc = ctx.doc;
|
|
1419
|
+
var found = idcTextFrameArg(doc, args, 'frame_id');
|
|
1420
|
+
var frame = found.item;
|
|
1421
|
+
var story = idcStoryOf(frame);
|
|
1422
|
+
var changed = [];
|
|
1423
|
+
var justification = null;
|
|
1424
|
+
var paragraphs, count = 0, i, p, range = null, first;
|
|
1425
|
+
|
|
1426
|
+
var dropCap = null;
|
|
1427
|
+
if (!idcGiven(args.alignment) && !idcGiven(args.hyphenation) && !idcGiven(args.no_break) && !idcCompositionGiven(args) && !idcIndentTabLanguageGiven(args) && !idcGiven(args.drop_cap)) {
|
|
1428
|
+
IDC.fail('invalid_argument', 'At least one of alignment, hyphenation, no_break, keep_options, hyphenation_options, justification_options, left_indent_mm, first_line_indent_mm, right_indent_mm, last_line_indent_mm, drop_cap, tab_stops or language is required.', null);
|
|
1429
|
+
}
|
|
1430
|
+
if (idcGiven(args.drop_cap)) { dropCap = idcDropCapArg(doc, args.drop_cap); }
|
|
1431
|
+
if (idcGiven(args.alignment)) {
|
|
1432
|
+
justification = idcJustificationFor(args.alignment, 'alignment');
|
|
1433
|
+
if (String(args.alignment) === 'justify') {
|
|
1434
|
+
IDC.fail('invalid_argument', 'alignment must name the last line: justify_left, justify_center, justify_right or justify_full.', { value: args.alignment });
|
|
1435
|
+
}
|
|
1436
|
+
}
|
|
1437
|
+
if (idcGiven(args.hyphenation) && typeof args.hyphenation !== 'boolean') {
|
|
1438
|
+
IDC.fail('invalid_argument', 'hyphenation must be true or false.', { value: args.hyphenation });
|
|
1439
|
+
}
|
|
1440
|
+
if (idcGiven(args.no_break) && typeof args.no_break !== 'boolean') {
|
|
1441
|
+
IDC.fail('invalid_argument', 'no_break must be true or false.', { value: args.no_break });
|
|
1442
|
+
}
|
|
1443
|
+
|
|
1444
|
+
if (idcGiven(args.start_index) || idcGiven(args.end_index)) {
|
|
1445
|
+
range = idcRangeArg(story, args, false);
|
|
1446
|
+
/*
|
|
1447
|
+
* Nicht range.text.paragraphs: an deren Absaetzen bleibt hyphenation
|
|
1448
|
+
* wirkungslos (Live-Fund 04.09.2026, justification greift). Die
|
|
1449
|
+
* Absaetze der Story, die den Bereich beruehren, verhalten sich wie
|
|
1450
|
+
* frame.paragraphs.
|
|
1451
|
+
*/
|
|
1452
|
+
paragraphs = idcStoryParagraphsInRange(story, range.start, range.end);
|
|
1453
|
+
count = paragraphs.length;
|
|
1454
|
+
} else {
|
|
1455
|
+
/*
|
|
1456
|
+
* Nicht frame.paragraphs waehrend der Schleife: Umbruchoptionen schieben
|
|
1457
|
+
* Absaetze in die naechste Spalte oder den Uebersatz, die Rahmensammlung
|
|
1458
|
+
* schrumpft und item(i) wird "Object is invalid" (Live-Fund 05.09.2026).
|
|
1459
|
+
* Deshalb die Absaetze der Story nehmen, die den Rahmenanteil beruehren –
|
|
1460
|
+
* die bleiben gueltig, wohin der Text auch laeuft.
|
|
1461
|
+
*/
|
|
1462
|
+
var frameStart = null, frameLength = 0;
|
|
1463
|
+
try { frameLength = Number(frame.characters.length); } catch (e1) { frameLength = 0; }
|
|
1464
|
+
try { if (frameLength > 0) { frameStart = Number(frame.characters.item(0).index); } } catch (e1b) { frameStart = null; }
|
|
1465
|
+
if (frameStart !== null && frameLength > 0) {
|
|
1466
|
+
paragraphs = idcStoryParagraphsInRange(story, frameStart, frameStart + frameLength);
|
|
1467
|
+
count = paragraphs.length;
|
|
1468
|
+
range = { start: frameStart, end: frameStart + frameLength, whole_frame: true };
|
|
1469
|
+
} else {
|
|
1470
|
+
count = 0;
|
|
1471
|
+
}
|
|
1472
|
+
}
|
|
1473
|
+
if (count === 0) {
|
|
1474
|
+
ctx.warn('No paragraphs in the given scope; nothing was changed.');
|
|
1475
|
+
return { frame_id: Number(frame.id), paragraphs_changed: 0, alignment: null, hyphenation: null, no_break: null, changed: [],
|
|
1476
|
+
keep_options: null, hyphenation_options: null, justification_options: null, indents: null, overset: null, drop_cap: null };
|
|
1477
|
+
}
|
|
1478
|
+
/* Die Optionsgruppen zuerst am ersten Absatz pruefen (Fehler vor jeder Aenderung). */
|
|
1479
|
+
var groups = [];
|
|
1480
|
+
var indentFields = [];
|
|
1481
|
+
var dropCapFields = [];
|
|
1482
|
+
try {
|
|
1483
|
+
for (i = 0; i < count; i++) {
|
|
1484
|
+
p = paragraphs[i];
|
|
1485
|
+
if (justification !== null) { p.justification = justification; }
|
|
1486
|
+
if (idcGiven(args.hyphenation)) { p.hyphenation = args.hyphenation; }
|
|
1487
|
+
if (idcGiven(args.no_break)) { p.noBreak = args.no_break; }
|
|
1488
|
+
groups = idcApplyCompositionOptions(p, args);
|
|
1489
|
+
indentFields = idcApplyIndentTabLanguage(doc, p, args, i === 0 ? ctx : null);
|
|
1490
|
+
dropCapFields = idcApplyDropCap(p, dropCap);
|
|
1491
|
+
}
|
|
1492
|
+
} catch (e) {
|
|
1493
|
+
if (e && e.isIdcError) { throw e; }
|
|
1494
|
+
IDC.fail('script_error', 'InDesign could not change the paragraph options: ' + String(e.message ? e.message : e), { frame_id: args.frame_id, paragraphs_done: i });
|
|
1495
|
+
}
|
|
1496
|
+
if (justification !== null) { changed.push('alignment'); }
|
|
1497
|
+
if (idcGiven(args.hyphenation)) { changed.push('hyphenation'); }
|
|
1498
|
+
if (idcGiven(args.no_break)) { changed.push('no_break'); }
|
|
1499
|
+
changed = changed.concat(groups).concat(indentFields).concat(dropCapFields);
|
|
1500
|
+
|
|
1501
|
+
first = paragraphs[0];
|
|
1502
|
+
var composition = idcReadCompositionOptions(first);
|
|
1503
|
+
var overset = null;
|
|
1504
|
+
try { overset = story.overflows === true; } catch (e3) { overset = null; }
|
|
1505
|
+
if (overset === true && groups.length > 0) {
|
|
1506
|
+
ctx.warn('The story overflows after the change – strict keep or justification options can push text out; check get_frame_lines.');
|
|
1507
|
+
}
|
|
1508
|
+
ctx.changes = { modified_frame_ids: [Number(frame.id)] };
|
|
1509
|
+
return {
|
|
1510
|
+
frame_id: Number(frame.id),
|
|
1511
|
+
paragraphs_changed: count,
|
|
1512
|
+
alignment: (function () { try { return idcJustificationName(first.justification); } catch (e2) { return null; } })(),
|
|
1513
|
+
hyphenation: idcReadBoolLoose(first, 'hyphenation'),
|
|
1514
|
+
no_break: idcReadBoolLoose(first, 'noBreak'),
|
|
1515
|
+
changed: changed,
|
|
1516
|
+
scope: range.whole_frame === true ? 'frame' : 'range',
|
|
1517
|
+
start_index: range.whole_frame === true ? null : range.start,
|
|
1518
|
+
end_index: range.whole_frame === true ? null : range.end,
|
|
1519
|
+
keep_options: composition.keep_options,
|
|
1520
|
+
hyphenation_options: composition.hyphenation_options,
|
|
1521
|
+
justification_options: composition.justification_options,
|
|
1522
|
+
indents: idcReadIndentTabLanguage(first),
|
|
1523
|
+
overset: overset,
|
|
1524
|
+
drop_cap: idcReadDropCap(first)
|
|
1525
|
+
};
|
|
1526
|
+
});
|
|
1527
|
+
|
|
1528
|
+
/* ---------------------------------------------------- get_font_info_at_index */
|
|
1529
|
+
|
|
1530
|
+
IDC.register('get_font_info_at_index', { needs_document: true, read_only: true, ruler: 'none' },
|
|
1531
|
+
function (ctx) {
|
|
1532
|
+
var args = ctx.args;
|
|
1533
|
+
var doc = ctx.doc;
|
|
1534
|
+
var found = idcTextFrameArg(doc, args, 'frame_id');
|
|
1535
|
+
var frame = found.item;
|
|
1536
|
+
var story = idcStoryOf(frame);
|
|
1537
|
+
var index = args.index;
|
|
1538
|
+
var length = 0;
|
|
1539
|
+
var character, font, fonts, found, status, text = null;
|
|
1540
|
+
|
|
1541
|
+
if (typeof index !== 'number' || Math.floor(index) !== index || index < 0) {
|
|
1542
|
+
IDC.fail('invalid_argument', 'index must be a whole number of 0 or more (a story index from get_frame_text).', { index: index });
|
|
1543
|
+
}
|
|
1544
|
+
try { length = Number(story.characters.length); } catch (e0) { length = 0; }
|
|
1545
|
+
if (index >= length) {
|
|
1546
|
+
IDC.fail('invalid_argument', 'index ' + index + ' is beyond the story length ' + length + '.', { index: index, story_length: length });
|
|
1547
|
+
}
|
|
1548
|
+
character = idcFirstCharacter(story, index);
|
|
1549
|
+
if (character === null) {
|
|
1550
|
+
IDC.fail('script_error', 'InDesign could not address character ' + index + '.', { index: index });
|
|
1551
|
+
}
|
|
1552
|
+
font = idcReadFontLoose(character);
|
|
1553
|
+
try { text = String(character.contents); } catch (e1) { text = null; }
|
|
1554
|
+
fonts = idcFontLookup();
|
|
1555
|
+
found = font.family === null ? null : fonts.find(font.family, font.style);
|
|
1556
|
+
status = found === null ? null : found.status;
|
|
1557
|
+
if (status === null && font.family !== null) {
|
|
1558
|
+
status = idcDocumentFontStatuses(doc)[font.family + '\t' + font.style] || 'not_available';
|
|
1559
|
+
}
|
|
1560
|
+
return {
|
|
1561
|
+
frame_id: Number(frame.id),
|
|
1562
|
+
index: index,
|
|
1563
|
+
character: text,
|
|
1564
|
+
font_family: font.family,
|
|
1565
|
+
font_style: font.style,
|
|
1566
|
+
font_status: status,
|
|
1567
|
+
available_styles: font.family === null ? [] : fonts.stylesOf(font.family),
|
|
1568
|
+
point_size: idcReadPt(character, 'pointSize'),
|
|
1569
|
+
paragraph_style: idcReadSwatchName(character, 'appliedParagraphStyle'),
|
|
1570
|
+
character_style: idcReadSwatchName(character, 'appliedCharacterStyle'),
|
|
1571
|
+
character_style_is_none: (function () { try { return idcIsNoneCharacterStyle(doc, character.appliedCharacterStyle); } catch (e2) { return null; } })()
|
|
1572
|
+
};
|
|
1573
|
+
});
|
|
1574
|
+
|
|
1575
|
+
/* ----------------------------------------------------------- find_font_usage */
|
|
1576
|
+
|
|
1577
|
+
/* Rahmen eines Textlaufs: IDs und Seite des ersten Rahmens. */
|
|
1578
|
+
function idcRunFrames(textObject) {
|
|
1579
|
+
var out = { frame_ids: [], page_id: null, page_name: '', is_master: false };
|
|
1580
|
+
var frames, i, frame, landing;
|
|
1581
|
+
try {
|
|
1582
|
+
frames = textObject.parentTextFrames;
|
|
1583
|
+
for (i = 0; i < frames.length; i++) {
|
|
1584
|
+
frame = IDC.concrete(frames[i]);
|
|
1585
|
+
out.frame_ids.push(Number(frame.id));
|
|
1586
|
+
if (i === 0) {
|
|
1587
|
+
landing = IDC.landing(frame);
|
|
1588
|
+
out.page_id = landing.page_id;
|
|
1589
|
+
out.page_name = landing.page_name;
|
|
1590
|
+
out.is_master = IDC.isOnParentSpread(frame);
|
|
1591
|
+
}
|
|
1592
|
+
}
|
|
1593
|
+
} catch (e) { /* Uebersatz ohne Rahmen */ }
|
|
1594
|
+
return out;
|
|
1595
|
+
}
|
|
1596
|
+
|
|
1597
|
+
/* Liegt eine Story (ueber ihren ersten Rahmen) auf einer Musterseite? */
|
|
1598
|
+
function idcStoryOnMaster(story) {
|
|
1599
|
+
var containers, first;
|
|
1600
|
+
try {
|
|
1601
|
+
containers = story.textContainers;
|
|
1602
|
+
if (containers && containers.length > 0) {
|
|
1603
|
+
first = IDC.concrete(containers[0]);
|
|
1604
|
+
return IDC.isOnParentSpread(first);
|
|
1605
|
+
}
|
|
1606
|
+
} catch (e) { /* unbekannt */ }
|
|
1607
|
+
return false;
|
|
1608
|
+
}
|
|
1609
|
+
|
|
1610
|
+
function idcSnippet(text, max) {
|
|
1611
|
+
/* Absatz-/Zeilenwechsel, Sonderzeichen und das Tabellenzeichen U+0016 (live 05.09.2026) werden Leerzeichen. */
|
|
1612
|
+
var s = String(text).replace(/[\r\n\u000e\u000f\u0010\u0011\u0012\u0016\u0007\u0008]/g, ' ');
|
|
1613
|
+
if (s.length > max) { s = s.substr(0, max) + '...'; }
|
|
1614
|
+
return s.replace(/\s+$/, '');
|
|
1615
|
+
}
|
|
1616
|
+
|
|
1617
|
+
function idcMergeIds(target, extra) {
|
|
1618
|
+
var i, j, seen;
|
|
1619
|
+
for (i = 0; i < extra.length; i++) {
|
|
1620
|
+
seen = false;
|
|
1621
|
+
for (j = 0; j < target.length; j++) { if (target[j] === extra[i]) { seen = true; break; } }
|
|
1622
|
+
if (!seen) { target.push(extra[i]); }
|
|
1623
|
+
}
|
|
1624
|
+
}
|
|
1625
|
+
|
|
1626
|
+
IDC.register('find_font_usage', { needs_document: true, read_only: true, ruler: 'none' },
|
|
1627
|
+
function (ctx) {
|
|
1628
|
+
var args = ctx.args;
|
|
1629
|
+
var doc = ctx.doc;
|
|
1630
|
+
var wantFamily = idcGiven(args.font_family) ? String(args.font_family) : null;
|
|
1631
|
+
var wantStyle = idcGiven(args.font_style) ? String(args.font_style) : null;
|
|
1632
|
+
var onlyMissing = args.only_missing === true;
|
|
1633
|
+
var includeMasters = args.include_master_pages !== false;
|
|
1634
|
+
var maxOccurrences = 500;
|
|
1635
|
+
var docStatuses = idcDocumentFontStatuses(doc);
|
|
1636
|
+
var fonts = null;
|
|
1637
|
+
var used = {};
|
|
1638
|
+
var usedOrder = [];
|
|
1639
|
+
var occurrences = [];
|
|
1640
|
+
var totalMatching = 0;
|
|
1641
|
+
var storyCount = 0, s, story, storyId, onMaster, ranges, r, run, runs, range, font, key, start, length, frames, snippet, i, entry;
|
|
1642
|
+
|
|
1643
|
+
function statusOf(family, style) {
|
|
1644
|
+
var name = family + '\t' + style;
|
|
1645
|
+
var status = docStatuses[name];
|
|
1646
|
+
var found;
|
|
1647
|
+
if (status !== undefined) { return status; }
|
|
1648
|
+
if (fonts === null) { fonts = idcFontLookup(); }
|
|
1649
|
+
found = fonts.find(family, style);
|
|
1650
|
+
return found === null ? 'not_available' : found.status;
|
|
1651
|
+
}
|
|
1652
|
+
|
|
1653
|
+
function matches(runEntry, status) {
|
|
1654
|
+
if (wantFamily !== null && !idcSameFamily(runEntry.family, wantFamily)) { return false; }
|
|
1655
|
+
if (wantStyle !== null && !idcSameText(runEntry.style, wantStyle)) { return false; }
|
|
1656
|
+
if (onlyMissing && status === 'installed') { return false; }
|
|
1657
|
+
return true;
|
|
1658
|
+
}
|
|
1659
|
+
|
|
1660
|
+
try { storyCount = Number(doc.stories.length); } catch (e0) {
|
|
1661
|
+
IDC.fail('script_error', 'InDesign could not list the stories of the document.', null);
|
|
1662
|
+
}
|
|
1663
|
+
|
|
1664
|
+
for (s = 0; s < storyCount; s++) {
|
|
1665
|
+
story = doc.stories.item(s);
|
|
1666
|
+
try { storyId = Number(story.id); } catch (e1) { storyId = null; }
|
|
1667
|
+
onMaster = idcStoryOnMaster(story);
|
|
1668
|
+
if (onMaster && !includeMasters) { continue; }
|
|
1669
|
+
runs = [];
|
|
1670
|
+
try {
|
|
1671
|
+
ranges = story.textStyleRanges;
|
|
1672
|
+
for (r = 0; r < ranges.length; r++) {
|
|
1673
|
+
range = ranges.item(r);
|
|
1674
|
+
font = idcReadFontLoose(range);
|
|
1675
|
+
if (font.family === null) { continue; }
|
|
1676
|
+
key = font.family + '\t' + (font.style === null ? '' : font.style);
|
|
1677
|
+
try { start = Number(range.index); } catch (e2) { start = null; }
|
|
1678
|
+
try { length = Number(range.characters.length); } catch (e3) { length = 0; }
|
|
1679
|
+
if (start === null) {
|
|
1680
|
+
try { start = Number(range.characters.item(0).index); } catch (e3b) { start = 0; }
|
|
1681
|
+
}
|
|
1682
|
+
frames = idcRunFrames(range);
|
|
1683
|
+
if (runs.length > 0 && runs[runs.length - 1].key === key && runs[runs.length - 1].end === start) {
|
|
1684
|
+
run = runs[runs.length - 1];
|
|
1685
|
+
run.end = start + length;
|
|
1686
|
+
idcMergeIds(run.frame_ids, frames.frame_ids);
|
|
1687
|
+
if (run.page_id === null) { run.page_id = frames.page_id; run.page_name = frames.page_name; }
|
|
1688
|
+
if (run.raw.length < 60) {
|
|
1689
|
+
try { run.raw += String(range.contents); } catch (e4b) { /* bleibt */ }
|
|
1690
|
+
}
|
|
1691
|
+
} else {
|
|
1692
|
+
try { snippet = String(range.contents); } catch (e4) { snippet = ''; }
|
|
1693
|
+
runs.push({
|
|
1694
|
+
key: key, family: font.family, style: font.style === null ? '' : font.style,
|
|
1695
|
+
start: start, end: start + length, raw: snippet,
|
|
1696
|
+
frame_ids: frames.frame_ids, page_id: frames.page_id, page_name: frames.page_name,
|
|
1697
|
+
is_master: onMaster || frames.is_master
|
|
1698
|
+
});
|
|
1699
|
+
}
|
|
1700
|
+
}
|
|
1701
|
+
} catch (e5) {
|
|
1702
|
+
ctx.warn('Story ' + storyId + ' could not be read completely: ' + String(e5.message ? e5.message : e5));
|
|
1703
|
+
}
|
|
1704
|
+
for (i = 0; i < runs.length; i++) {
|
|
1705
|
+
run = runs[i];
|
|
1706
|
+
entry = used[run.key];
|
|
1707
|
+
if (entry === undefined) {
|
|
1708
|
+
entry = { family: run.family, style: run.style, status: statusOf(run.family, run.style), occurrences: 0, characters: 0 };
|
|
1709
|
+
used[run.key] = entry;
|
|
1710
|
+
usedOrder.push(run.key);
|
|
1711
|
+
}
|
|
1712
|
+
entry.occurrences += 1;
|
|
1713
|
+
entry.characters += run.end - run.start;
|
|
1714
|
+
if (matches(run, entry.status)) {
|
|
1715
|
+
totalMatching += 1;
|
|
1716
|
+
if (occurrences.length < maxOccurrences) {
|
|
1717
|
+
occurrences.push({
|
|
1718
|
+
family: run.family, style: run.style, status: entry.status,
|
|
1719
|
+
story_id: storyId, frame_ids: run.frame_ids, page_id: run.page_id, page_name: run.page_name,
|
|
1720
|
+
is_master: run.is_master, start_index: run.start, end_index: run.end, snippet: idcSnippet(run.raw, 60)
|
|
1721
|
+
});
|
|
1722
|
+
}
|
|
1723
|
+
}
|
|
1724
|
+
}
|
|
1725
|
+
}
|
|
1726
|
+
|
|
1727
|
+
var fontsUsed = [];
|
|
1728
|
+
for (i = 0; i < usedOrder.length; i++) { fontsUsed.push(used[usedOrder[i]]); }
|
|
1729
|
+
fontsUsed.sort(function (a, b) {
|
|
1730
|
+
var ka = (a.family + '\t' + a.style).toLowerCase();
|
|
1731
|
+
var kb = (b.family + '\t' + b.style).toLowerCase();
|
|
1732
|
+
return ka < kb ? -1 : (ka > kb ? 1 : 0);
|
|
1733
|
+
});
|
|
1734
|
+
if (totalMatching > maxOccurrences) {
|
|
1735
|
+
ctx.warn('Only the first ' + maxOccurrences + ' of ' + totalMatching + ' matching occurrences are listed.');
|
|
1736
|
+
}
|
|
1737
|
+
return {
|
|
1738
|
+
fonts_used: fontsUsed,
|
|
1739
|
+
occurrences: occurrences,
|
|
1740
|
+
occurrence_count: totalMatching,
|
|
1741
|
+
stories_scanned: storyCount,
|
|
1742
|
+
filter: { font_family: wantFamily, font_style: wantStyle, only_missing: onlyMissing, include_master_pages: includeMasters }
|
|
1743
|
+
};
|
|
1744
|
+
});
|
|
1745
|
+
|
|
1746
|
+
/* ----------------------------------------------------------- debug_inspect_run */
|
|
1747
|
+
|
|
1748
|
+
function idcFrameScale(frame) {
|
|
1749
|
+
var h = null, v = null;
|
|
1750
|
+
try { h = IDC.round(Number(frame.absoluteHorizontalScale), 3); } catch (e1) { h = null; }
|
|
1751
|
+
try { v = IDC.round(Number(frame.absoluteVerticalScale), 3); } catch (e2) { v = null; }
|
|
1752
|
+
if (h === null) { try { h = IDC.round(Number(frame.horizontalScale), 3); } catch (e3) { h = null; } }
|
|
1753
|
+
if (v === null) { try { v = IDC.round(Number(frame.verticalScale), 3); } catch (e4) { v = null; } }
|
|
1754
|
+
return { horizontal: h, vertical: v };
|
|
1755
|
+
}
|
|
1756
|
+
|
|
1757
|
+
/* Absatz des Zeichens mit Umbruch-, Trennungs- und Blocksatzoptionen (A-7). */
|
|
1758
|
+
function idcInspectParagraph(character) {
|
|
1759
|
+
var paragraph = null;
|
|
1760
|
+
var out;
|
|
1761
|
+
try { paragraph = character.paragraphs.item(0); } catch (e) { paragraph = null; }
|
|
1762
|
+
if (paragraph === null || paragraph === undefined) { return null; }
|
|
1763
|
+
out = idcReadCompositionOptions(paragraph);
|
|
1764
|
+
/* Live 05.09.2026: Paragraph.index ist der Zeichenindex des Absatzanfangs, keine Ordnungszahl – deshalb beides ausdruecklich. */
|
|
1765
|
+
out.start_index = idcParagraphStart(paragraph);
|
|
1766
|
+
out.index = null;
|
|
1767
|
+
try {
|
|
1768
|
+
var story = paragraph.parentStory, ordinal, probe;
|
|
1769
|
+
for (ordinal = 0; ordinal < story.paragraphs.length; ordinal++) {
|
|
1770
|
+
probe = idcParagraphStart(story.paragraphs.item(ordinal));
|
|
1771
|
+
if (probe === out.start_index) { out.index = ordinal; break; }
|
|
1772
|
+
if (probe !== null && probe > out.start_index) { break; }
|
|
1773
|
+
}
|
|
1774
|
+
} catch (e2) { out.index = null; }
|
|
1775
|
+
try { out.alignment = idcJustificationName(paragraph.justification); } catch (e3) { out.alignment = null; }
|
|
1776
|
+
out.hyphenation = idcReadBoolLoose(paragraph, 'hyphenation');
|
|
1777
|
+
return out;
|
|
1778
|
+
}
|
|
1779
|
+
|
|
1780
|
+
IDC.register('debug_inspect_run', { needs_document: true, read_only: true, ruler: 'none' },
|
|
1781
|
+
function (ctx) {
|
|
1782
|
+
var args = ctx.args;
|
|
1783
|
+
var doc = ctx.doc;
|
|
1784
|
+
var found = idcTextFrameArg(doc, args, 'frame_id');
|
|
1785
|
+
var frame = found.item;
|
|
1786
|
+
var story = idcStoryOf(frame);
|
|
1787
|
+
var index = idcGiven(args.index) ? args.index : 0;
|
|
1788
|
+
var length = 0;
|
|
1789
|
+
var character, font, out, styleInfo = null, all, i, name, hits, kind;
|
|
1790
|
+
|
|
1791
|
+
if (typeof index !== 'number' || Math.floor(index) !== index || index < 0) {
|
|
1792
|
+
IDC.fail('invalid_argument', 'index must be a whole number of 0 or more.', { index: index });
|
|
1793
|
+
}
|
|
1794
|
+
try { length = Number(story.characters.length); } catch (e0) { length = 0; }
|
|
1795
|
+
if (length === 0) {
|
|
1796
|
+
IDC.fail('invalid_state', 'The frame holds no text; there is no character to inspect.', { frame_id: args.frame_id });
|
|
1797
|
+
}
|
|
1798
|
+
if (index >= length) {
|
|
1799
|
+
IDC.fail('invalid_argument', 'index ' + index + ' is beyond the story length ' + length + '.', { index: index, story_length: length });
|
|
1800
|
+
}
|
|
1801
|
+
character = idcFirstCharacter(story, index);
|
|
1802
|
+
font = idcReadFontLoose(character);
|
|
1803
|
+
out = {
|
|
1804
|
+
frame_id: Number(frame.id),
|
|
1805
|
+
index: index,
|
|
1806
|
+
character: (function () { try { return String(character.contents); } catch (e1) { return null; } })(),
|
|
1807
|
+
point_size: idcReadPt(character, 'pointSize'),
|
|
1808
|
+
leading_pt: idcReadLeading(character).pt,
|
|
1809
|
+
leading_auto: idcReadLeading(character).auto,
|
|
1810
|
+
applied_paragraph_style: idcReadSwatchName(character, 'appliedParagraphStyle'),
|
|
1811
|
+
applied_character_style: idcReadSwatchName(character, 'appliedCharacterStyle'),
|
|
1812
|
+
character_style_is_none: (function () { try { return idcIsNoneCharacterStyle(doc, character.appliedCharacterStyle); } catch (e1b) { return null; } })(),
|
|
1813
|
+
fill_color: idcReadSwatchName(character, 'fillColor'),
|
|
1814
|
+
applied_font: font.family,
|
|
1815
|
+
font_style: font.style,
|
|
1816
|
+
tracking: idcReadNumberLoose(character, 'tracking', 1),
|
|
1817
|
+
horizontal_scale: idcReadNumberLoose(character, 'horizontalScale', 3),
|
|
1818
|
+
vertical_scale: idcReadNumberLoose(character, 'verticalScale', 3),
|
|
1819
|
+
style_overridden: idcReadBoolLoose(character, 'styleOverridden'),
|
|
1820
|
+
frame_scale: idcFrameScale(frame),
|
|
1821
|
+
paragraph: idcInspectParagraph(character)
|
|
1822
|
+
};
|
|
1823
|
+
|
|
1824
|
+
if (idcGiven(args.style_name)) {
|
|
1825
|
+
name = String(args.style_name);
|
|
1826
|
+
hits = [];
|
|
1827
|
+
kind = null;
|
|
1828
|
+
all = idcAllStyles(doc, 'paragraph');
|
|
1829
|
+
for (i = 0; i < all.length; i++) {
|
|
1830
|
+
try { if (String(all[i].name) === name) { hits.push(all[i]); } } catch (e2) { /* weiter */ }
|
|
1831
|
+
}
|
|
1832
|
+
if (hits.length > 0) { kind = 'paragraph'; }
|
|
1833
|
+
else {
|
|
1834
|
+
all = idcAllStyles(doc, 'character');
|
|
1835
|
+
for (i = 0; i < all.length; i++) {
|
|
1836
|
+
try { if (String(all[i].name) === name) { hits.push(all[i]); } } catch (e3) { /* weiter */ }
|
|
1837
|
+
}
|
|
1838
|
+
if (hits.length > 0) { kind = 'character'; }
|
|
1839
|
+
}
|
|
1840
|
+
if (hits.length === 0) {
|
|
1841
|
+
styleInfo = { name: name, found: false, kind: null, matches: 0, duplicated: false, nested: false, definition: null, groups: [] };
|
|
1842
|
+
} else {
|
|
1843
|
+
var groups = [];
|
|
1844
|
+
for (i = 0; i < hits.length; i++) { groups.push(idcStyleGroupPath(hits[i])); }
|
|
1845
|
+
styleInfo = {
|
|
1846
|
+
name: name,
|
|
1847
|
+
found: true,
|
|
1848
|
+
kind: kind,
|
|
1849
|
+
matches: hits.length,
|
|
1850
|
+
duplicated: hits.length > 1,
|
|
1851
|
+
nested: groups[0] !== '',
|
|
1852
|
+
groups: groups,
|
|
1853
|
+
definition: kind === 'paragraph' ? idcDescribeParagraphStyle(hits[0]) : idcDescribeCharacterStyle(hits[0])
|
|
1854
|
+
};
|
|
1855
|
+
if (hits.length > 1) {
|
|
1856
|
+
ctx.warn('The style name "' + name + '" occurs ' + hits.length + ' times (in groups: ' + groups.join(', ') + ') – apply by name may pick the wrong one.');
|
|
1857
|
+
}
|
|
1858
|
+
}
|
|
1859
|
+
out.style = styleInfo;
|
|
1860
|
+
}
|
|
1861
|
+
return out;
|
|
1862
|
+
});
|
|
1863
|
+
|
|
1864
|
+
/* --------------------------------------------------------------- create_swatch */
|
|
1865
|
+
|
|
1866
|
+
function idcCmykArg(spec) {
|
|
1867
|
+
var keys = ['c', 'm', 'y', 'k'];
|
|
1868
|
+
var out = [];
|
|
1869
|
+
var i, v;
|
|
1870
|
+
if (typeof spec !== 'object' || spec === null || IDC.isArray(spec)) {
|
|
1871
|
+
IDC.fail('invalid_argument', 'cmyk must be an object { c, m, y, k } with values 0–100.', { value: spec });
|
|
1872
|
+
}
|
|
1873
|
+
for (i = 0; i < keys.length; i++) {
|
|
1874
|
+
v = spec[keys[i]];
|
|
1875
|
+
if (typeof v !== 'number' || !isFinite(v) || v < 0 || v > 100) {
|
|
1876
|
+
IDC.fail('invalid_argument', 'cmyk.' + keys[i] + ' must be a number from 0 to 100.', { value: v });
|
|
1877
|
+
}
|
|
1878
|
+
out.push(v);
|
|
1879
|
+
}
|
|
1880
|
+
return out;
|
|
1881
|
+
}
|
|
1882
|
+
|
|
1883
|
+
IDC.register('create_swatch', { needs_document: true, read_only: false, ruler: 'none' },
|
|
1884
|
+
function (ctx) {
|
|
1885
|
+
var args = ctx.args;
|
|
1886
|
+
var doc = ctx.doc;
|
|
1887
|
+
var name = args.name;
|
|
1888
|
+
var onCollision = idcCollisionArg(args.on_collision);
|
|
1889
|
+
var hasHex = idcGiven(args.hex);
|
|
1890
|
+
var hasCmyk = idcGiven(args.cmyk);
|
|
1891
|
+
var values, space, spaceName, existing, collision = 'none', chosenName, swatch = null, className;
|
|
1892
|
+
var haveSwatch = false, existed = false;
|
|
1893
|
+
|
|
1894
|
+
if (typeof name !== 'string' || name.length < 1 || name.length > 60) {
|
|
1895
|
+
IDC.fail('invalid_argument', 'name is required (1–60 characters).', { name: name });
|
|
1896
|
+
}
|
|
1897
|
+
if (name.charAt(0) === '[') {
|
|
1898
|
+
IDC.fail('invalid_argument', 'name must not start with "[" – those names are reserved for InDesign\'s built-in swatches.', { name: name });
|
|
1899
|
+
}
|
|
1900
|
+
if (hasHex === hasCmyk) {
|
|
1901
|
+
IDC.fail('invalid_argument', 'Pass exactly one of hex (RGB, e.g. "#1A2B3C") or cmyk ({ c, m, y, k } in percent).', null);
|
|
1902
|
+
}
|
|
1903
|
+
if (hasHex) {
|
|
1904
|
+
var rgb = idcParseHex(args.hex, 'hex');
|
|
1905
|
+
values = [rgb.r, rgb.g, rgb.b];
|
|
1906
|
+
space = ColorSpace.RGB;
|
|
1907
|
+
spaceName = 'rgb';
|
|
1908
|
+
} else {
|
|
1909
|
+
values = idcCmykArg(args.cmyk);
|
|
1910
|
+
space = ColorSpace.CMYK;
|
|
1911
|
+
spaceName = 'cmyk';
|
|
1912
|
+
}
|
|
1913
|
+
chosenName = name;
|
|
1914
|
+
existing = idcSwatchByName(doc, name);
|
|
1915
|
+
existed = idcPresent(existing);
|
|
1916
|
+
if (existed) {
|
|
1917
|
+
if (onCollision === 'error') {
|
|
1918
|
+
IDC.fail('invalid_state', 'Swatch "' + name + '" exists already. Pass on_collision "update" to change it or "version" to add "' + name + ' 2".',
|
|
1919
|
+
{ name: name, swatch_id: (function () { try { return Number(existing.id); } catch (e) { return null; } })() });
|
|
1920
|
+
}
|
|
1921
|
+
if (onCollision === 'update') {
|
|
1922
|
+
className = IDC.className(existing);
|
|
1923
|
+
if (className !== 'Color' && className !== 'Swatch') {
|
|
1924
|
+
IDC.fail('invalid_state', 'Swatch "' + name + '" is a ' + className + ', not a colour; it cannot be updated with values.', { name: name, type: className });
|
|
1925
|
+
}
|
|
1926
|
+
swatch = existing;
|
|
1927
|
+
haveSwatch = true;
|
|
1928
|
+
collision = 'updated';
|
|
1929
|
+
try {
|
|
1930
|
+
swatch.model = ColorModel.PROCESS;
|
|
1931
|
+
swatch.space = space;
|
|
1932
|
+
swatch.colorValue = values;
|
|
1933
|
+
} catch (e1) {
|
|
1934
|
+
IDC.fail('script_error', 'InDesign could not update the swatch "' + name + '": ' + String(e1.message ? e1.message : e1), { name: name });
|
|
1935
|
+
}
|
|
1936
|
+
} else {
|
|
1937
|
+
chosenName = idcFreeName(doc, name, 'swatch');
|
|
1938
|
+
collision = 'versioned';
|
|
1939
|
+
}
|
|
1940
|
+
}
|
|
1941
|
+
if (!haveSwatch) {
|
|
1942
|
+
try {
|
|
1943
|
+
/* Colors.add nimmt nur withProperties (Live-Fund Sitzung 3). */
|
|
1944
|
+
swatch = doc.colors.add({ name: chosenName, model: ColorModel.PROCESS, space: space, colorValue: values });
|
|
1945
|
+
} catch (e2) {
|
|
1946
|
+
IDC.fail('script_error', 'InDesign could not create the swatch "' + chosenName + '": ' + String(e2.message ? e2.message : e2), { name: chosenName });
|
|
1947
|
+
}
|
|
1948
|
+
}
|
|
1949
|
+
ctx.changes = collision === 'updated'
|
|
1950
|
+
? { modified_swatch_ids: [Number(swatch.id)] }
|
|
1951
|
+
: { created_swatch_ids: [Number(swatch.id)] };
|
|
1952
|
+
return {
|
|
1953
|
+
name: String(swatch.name),
|
|
1954
|
+
swatch_id: Number(swatch.id),
|
|
1955
|
+
collision: collision,
|
|
1956
|
+
existed: existed,
|
|
1957
|
+
space: spaceName,
|
|
1958
|
+
values: values
|
|
1959
|
+
};
|
|
1960
|
+
});
|