layoutbridge-spm 0.0.1 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +171 -0
- package/LICENSE +26 -0
- package/README.de.md +318 -0
- package/README.md +304 -4
- package/THIRD-PARTY-NOTICES.md +2878 -0
- package/dist/src/mcp/config.js +125 -0
- package/dist/src/mcp/dispatch.js +123 -0
- package/dist/src/mcp/license/free-tools.js +16 -0
- package/dist/src/mcp/license/gate.js +209 -0
- package/dist/src/mcp/license/index.js +96 -0
- package/dist/src/mcp/license/instance-name.js +56 -0
- package/dist/src/mcp/license/key-source.js +58 -0
- package/dist/src/mcp/license/lemonsqueezy-verifier.js +207 -0
- package/dist/src/mcp/license/placeholder-verifier.js +10 -0
- package/dist/src/mcp/license/polar-ids.js +63 -0
- package/dist/src/mcp/license/polar-verifier.js +265 -0
- package/dist/src/mcp/license/product-ids.js +72 -0
- package/dist/src/mcp/license/state-store.js +91 -0
- package/dist/src/mcp/license/types.js +11 -0
- package/dist/src/mcp/logging.js +270 -0
- package/dist/src/mcp/product-info.js +48 -0
- package/dist/src/mcp/server.js +250 -0
- package/dist/src/mcp/setup.js +608 -0
- package/dist/src/mcp/start.cjs +95 -0
- package/dist/src/mcp/tool-definition.js +2 -0
- package/dist/src/mcp/tools.js +2004 -0
- package/dist/src/mcp/typography-rules.js +70 -0
- package/dist/src/transport/com.js +250 -0
- package/dist/src/transport/osascript.js +171 -0
- package/dist/src/transport/queue.js +19 -0
- package/dist/src/transport/script-bundle.js +92 -0
- package/dist/src/transport/transport.js +30 -0
- package/indesign/commands/10-app.js +6 -0
- package/indesign/commands/20-documents.js +513 -0
- package/indesign/commands/22-document-setup.js +118 -0
- package/indesign/commands/23-save-package.js +255 -0
- package/indesign/commands/25-export.js +379 -0
- package/indesign/commands/26-export-image.js +197 -0
- package/indesign/commands/27-textdefaults.js +151 -0
- package/indesign/commands/28-selection.js +174 -0
- package/indesign/commands/30-pages.js +1032 -0
- package/indesign/commands/31-view.js +210 -0
- package/indesign/commands/32-sections.js +203 -0
- package/indesign/commands/35-parents.js +428 -0
- package/indesign/commands/37-layout.js +760 -0
- package/indesign/commands/40-frames.js +836 -0
- package/indesign/commands/41-shapes.js +505 -0
- package/indesign/commands/42-groups.js +117 -0
- package/indesign/commands/43-layers.js +291 -0
- package/indesign/commands/44-effects.js +274 -0
- package/indesign/commands/45-frame-options.js +247 -0
- package/indesign/commands/47-anchored.js +287 -0
- package/indesign/commands/50-modify.js +781 -0
- package/indesign/commands/52-align.js +139 -0
- package/indesign/commands/55-fit.js +106 -0
- package/indesign/commands/60-images.js +771 -0
- package/indesign/commands/62-embed.js +120 -0
- package/indesign/commands/69-placeholders.js +127 -0
- package/indesign/commands/70-text.js +567 -0
- package/indesign/commands/71-outlines.js +92 -0
- package/indesign/commands/72-place-text.js +366 -0
- package/indesign/commands/74-stories.js +116 -0
- package/indesign/commands/75-tables.js +676 -0
- package/indesign/commands/76-text-variables.js +260 -0
- package/indesign/commands/77-story-options.js +86 -0
- package/indesign/commands/78-frame-lines.js +304 -0
- package/indesign/commands/79-check-typography.js +303 -0
- package/indesign/commands/80-styles.js +1620 -0
- package/indesign/commands/81-composition.js +355 -0
- package/indesign/commands/82-object-styles.js +263 -0
- package/indesign/commands/83-indents-tabs.js +237 -0
- package/indesign/commands/84-import-styles.js +142 -0
- package/indesign/commands/85-swatches.js +112 -0
- package/indesign/commands/86-gradients.js +185 -0
- package/indesign/commands/87-replace-swatch.js +180 -0
- package/indesign/commands/88-replace-font.js +217 -0
- package/indesign/interpreter.js +758 -0
- package/package.json +55 -6
- package/rules/typography-rules.json +31 -0
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Sitzung 10 (Demo-Heft-Befund 3, 05.09.2026) – Einzuege, Tabulatoren und
|
|
3
|
+
* Sprache fuer Absatzformate (define_paragraph_style) und Absaetze
|
|
4
|
+
* (set_paragraph_options).
|
|
5
|
+
*
|
|
6
|
+
* Adobe-DOM (geprueft 05.09.2026, Klasse Text): leftIndent, rightIndent,
|
|
7
|
+
* firstLineIndent, lastLineIndent (Masseinheit – hier mm, weil der
|
|
8
|
+
* Interpreter waehrend eines Befehls auf Millimeter steht); tabStops
|
|
9
|
+
* (Sammlung, add(withProperties)) mit TabStop.position, alignment
|
|
10
|
+
* (TabStopAlignment LEFT_ALIGN, CENTER_ALIGN, RIGHT_ALIGN, CHARACTER_ALIGN),
|
|
11
|
+
* leader, alignmentCharacter; appliedLanguage (Language oder
|
|
12
|
+
* LanguageWithVendors, nimmt auch String) – Language.name (lokalisiert),
|
|
13
|
+
* untranslatedName, icuLocaleName; Application.languagesWithVendors,
|
|
14
|
+
* Document.languages.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
var IDC_INDENT_MAX_MM = 3048; /* 8640 pt, InDesigns Grenze */
|
|
18
|
+
|
|
19
|
+
function idcIndentArg(value, field, min, max) {
|
|
20
|
+
if (typeof value !== 'number' || isNaN(value) || value < min || value > max) {
|
|
21
|
+
IDC.fail('invalid_argument', field + ' must be a number from ' + min + ' to ' + max + ' (mm).', { value: value });
|
|
22
|
+
}
|
|
23
|
+
return value;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/* ---------------------------------------------------------- Tabulatoren */
|
|
27
|
+
|
|
28
|
+
function idcTabAlignmentFor(name, field) {
|
|
29
|
+
var text = name === undefined || name === null ? 'left' : String(name);
|
|
30
|
+
if (typeof TabStopAlignment === 'undefined') {
|
|
31
|
+
IDC.fail('invalid_state', 'This runtime has no TabStopAlignment enumeration.', null);
|
|
32
|
+
}
|
|
33
|
+
if (text === 'left') { return TabStopAlignment.LEFT_ALIGN; }
|
|
34
|
+
if (text === 'center') { return TabStopAlignment.CENTER_ALIGN; }
|
|
35
|
+
if (text === 'right') { return TabStopAlignment.RIGHT_ALIGN; }
|
|
36
|
+
if (text === 'character') { return TabStopAlignment.CHARACTER_ALIGN; }
|
|
37
|
+
IDC.fail('invalid_argument', field + ' must be left, center, right or character.', { value: name });
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function idcTabAlignmentName(value) {
|
|
42
|
+
if (typeof TabStopAlignment === 'undefined') { return String(value); }
|
|
43
|
+
if (IDC.enumIs(value, TabStopAlignment.LEFT_ALIGN)) { return 'left'; }
|
|
44
|
+
if (IDC.enumIs(value, TabStopAlignment.CENTER_ALIGN)) { return 'center'; }
|
|
45
|
+
if (IDC.enumIs(value, TabStopAlignment.RIGHT_ALIGN)) { return 'right'; }
|
|
46
|
+
if (IDC.enumIs(value, TabStopAlignment.CHARACTER_ALIGN)) { return 'character'; }
|
|
47
|
+
return String(value);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/* tab_stops[] pruefen und in DOM-Eigenschaften uebersetzen (vor jeder Aenderung). */
|
|
51
|
+
function idcTabStopsArg(list) {
|
|
52
|
+
var out = [];
|
|
53
|
+
var i, spec, entry, leader, alignOn;
|
|
54
|
+
if (!IDC.isArray(list)) {
|
|
55
|
+
IDC.fail('invalid_argument', 'tab_stops must be an array of {position_mm, alignment, leader, align_on}; [] removes every tab stop.', null);
|
|
56
|
+
}
|
|
57
|
+
for (i = 0; i < list.length; i++) {
|
|
58
|
+
spec = list[i];
|
|
59
|
+
if (spec === null || typeof spec !== 'object' || IDC.isArray(spec)) {
|
|
60
|
+
IDC.fail('invalid_argument', 'tab_stops[' + i + '] must be an object {position_mm, alignment, leader, align_on}.', { index: i });
|
|
61
|
+
}
|
|
62
|
+
entry = { position: idcIndentArg(spec.position_mm, 'tab_stops[' + i + '].position_mm', 0, IDC_INDENT_MAX_MM) };
|
|
63
|
+
entry.alignment = idcTabAlignmentFor(spec.alignment, 'tab_stops[' + i + '].alignment');
|
|
64
|
+
leader = spec.leader === undefined || spec.leader === null ? '' : spec.leader;
|
|
65
|
+
if (typeof leader !== 'string' || leader.length > 8) {
|
|
66
|
+
IDC.fail('invalid_argument', 'tab_stops[' + i + '].leader must be a string of up to 8 characters (e.g. ".").', { index: i, value: spec.leader });
|
|
67
|
+
}
|
|
68
|
+
entry.leader = leader;
|
|
69
|
+
alignOn = spec.align_on === undefined || spec.align_on === null ? null : spec.align_on;
|
|
70
|
+
if (alignOn !== null && (typeof alignOn !== 'string' || alignOn.length !== 1)) {
|
|
71
|
+
IDC.fail('invalid_argument', 'tab_stops[' + i + '].align_on must be a single character (used with alignment character).', { index: i, value: spec.align_on });
|
|
72
|
+
}
|
|
73
|
+
entry.alignmentCharacter = alignOn;
|
|
74
|
+
out.push(entry);
|
|
75
|
+
}
|
|
76
|
+
return out;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/* Alle Tabulatoren eines Ziels entfernen und die Liste neu setzen. */
|
|
80
|
+
function idcSetTabStops(target, entries) {
|
|
81
|
+
var stops, i, stop, props;
|
|
82
|
+
stops = target.tabStops;
|
|
83
|
+
for (i = stops.length - 1; i >= 0; i--) {
|
|
84
|
+
stops.item(i).remove();
|
|
85
|
+
}
|
|
86
|
+
for (i = 0; i < entries.length; i++) {
|
|
87
|
+
props = { position: entries[i].position, alignment: entries[i].alignment, leader: entries[i].leader };
|
|
88
|
+
if (entries[i].alignmentCharacter !== null) { props.alignmentCharacter = entries[i].alignmentCharacter; }
|
|
89
|
+
/*
|
|
90
|
+
* Nur add(withProperties): ein Nachsetzen der Eigenschaften am
|
|
91
|
+
* zurueckgegebenen TabStop loeschte am lebenden InDesign 21.5 die zuvor
|
|
92
|
+
* angelegten Tabulatoren (Live-Fund 05.09.2026 – von drei blieb einer).
|
|
93
|
+
*/
|
|
94
|
+
stop = target.tabStops.add(props);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function idcReadTabStops(target) {
|
|
99
|
+
var out = [];
|
|
100
|
+
var stops, i, stop, entry;
|
|
101
|
+
try { stops = target.tabStops; } catch (e0) { return null; }
|
|
102
|
+
try {
|
|
103
|
+
for (i = 0; i < stops.length; i++) {
|
|
104
|
+
stop = stops.item(i);
|
|
105
|
+
entry = { position_mm: null, alignment: null, leader: null, align_on: null };
|
|
106
|
+
try { entry.position_mm = IDC.round(Number(stop.position)); } catch (e1) { /* bleibt null */ }
|
|
107
|
+
try { entry.alignment = idcTabAlignmentName(stop.alignment); } catch (e2) { /* bleibt null */ }
|
|
108
|
+
try { entry.leader = String(stop.leader); } catch (e3) { /* bleibt null */ }
|
|
109
|
+
if (entry.alignment === 'character') {
|
|
110
|
+
try { entry.align_on = String(stop.alignmentCharacter); } catch (e4) { /* bleibt null */ }
|
|
111
|
+
}
|
|
112
|
+
out.push(entry);
|
|
113
|
+
}
|
|
114
|
+
} catch (e5) { return null; }
|
|
115
|
+
return out;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/* -------------------------------------------------------------- Sprache */
|
|
119
|
+
|
|
120
|
+
function idcLanguageEntry(lang) {
|
|
121
|
+
var entry = { name: null, untranslated_name: null, icu_locale: null };
|
|
122
|
+
try { entry.name = String(lang.name); } catch (e0) { /* bleibt null */ }
|
|
123
|
+
try { entry.untranslated_name = String(lang.untranslatedName); } catch (e1) { /* bleibt null */ }
|
|
124
|
+
try { entry.icu_locale = String(lang.icuLocaleName); } catch (e2) { /* bleibt null */ }
|
|
125
|
+
return entry;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function idcLanguageKey(text) {
|
|
129
|
+
return String(text).toLowerCase().replace(/-/g, '_');
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/* Alle Sprachen: erst die der Anwendung (mit Anbietern), dann die des Dokuments. */
|
|
133
|
+
function idcAllLanguages(doc) {
|
|
134
|
+
var out = [];
|
|
135
|
+
var seen = {};
|
|
136
|
+
var lists = [], i, j, list, lang, key;
|
|
137
|
+
try { if (app.languagesWithVendors) { lists.push(app.languagesWithVendors); } } catch (e0) { /* keine */ }
|
|
138
|
+
try { if (doc.languages) { lists.push(doc.languages); } } catch (e1) { /* keine */ }
|
|
139
|
+
for (i = 0; i < lists.length; i++) {
|
|
140
|
+
list = lists[i];
|
|
141
|
+
try {
|
|
142
|
+
for (j = 0; j < list.length; j++) {
|
|
143
|
+
lang = list.item(j);
|
|
144
|
+
try { key = String(lang.name); } catch (e2) { continue; }
|
|
145
|
+
if (IDC.hasOwn(seen, key)) { continue; }
|
|
146
|
+
seen[key] = true;
|
|
147
|
+
out.push(lang);
|
|
148
|
+
}
|
|
149
|
+
} catch (e3) { /* naechste Liste */ }
|
|
150
|
+
}
|
|
151
|
+
return out;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/* Sprache ueber Namen (lokalisiert), englischen Namen oder ICU-Kennung (de_DE, de-DE) finden. */
|
|
155
|
+
function idcLanguageArg(doc, value, field) {
|
|
156
|
+
var wanted, all, i, lang, entry, available = [];
|
|
157
|
+
if (typeof value !== 'string' || value === '') {
|
|
158
|
+
IDC.fail('invalid_argument', field + ' must be a language name as InDesign shows it, its English name, or an ICU locale such as de_DE.', { value: value });
|
|
159
|
+
}
|
|
160
|
+
wanted = idcLanguageKey(value);
|
|
161
|
+
all = idcAllLanguages(doc);
|
|
162
|
+
for (i = 0; i < all.length; i++) {
|
|
163
|
+
lang = all[i];
|
|
164
|
+
entry = idcLanguageEntry(lang);
|
|
165
|
+
if ((entry.name !== null && idcLanguageKey(entry.name) === wanted) ||
|
|
166
|
+
(entry.untranslated_name !== null && idcLanguageKey(entry.untranslated_name) === wanted) ||
|
|
167
|
+
(entry.icu_locale !== null && entry.icu_locale !== '' && idcLanguageKey(entry.icu_locale) === wanted)) {
|
|
168
|
+
return lang;
|
|
169
|
+
}
|
|
170
|
+
if (available.length < 120) { available.push(entry); }
|
|
171
|
+
}
|
|
172
|
+
IDC.fail('not_found', 'No language "' + value + '" in this InDesign. Use a name from available (name as shown, English name or ICU locale).',
|
|
173
|
+
{ language: value, available: available });
|
|
174
|
+
return null;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function idcReadLanguage(target) {
|
|
178
|
+
var lang = null;
|
|
179
|
+
try { lang = target.appliedLanguage; } catch (e0) { return null; }
|
|
180
|
+
if (lang === null || lang === undefined) { return null; }
|
|
181
|
+
if (typeof lang === 'string') { return { name: lang, untranslated_name: null, icu_locale: null }; }
|
|
182
|
+
return idcLanguageEntry(lang);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/* ------------------------------------------------ gemeinsame Anwendung */
|
|
186
|
+
|
|
187
|
+
function idcIndentTabLanguageGiven(args) {
|
|
188
|
+
return idcGiven(args.left_indent_mm) || idcGiven(args.first_line_indent_mm) || idcGiven(args.right_indent_mm) ||
|
|
189
|
+
idcGiven(args.last_line_indent_mm) || idcGiven(args.tab_stops) || idcGiven(args.language);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/*
|
|
193
|
+
* Einzuege, Tabulatoren und Sprache an ein Format oder einen Absatz setzen.
|
|
194
|
+
* Erst pruefen (alle Argumente), dann schreiben. Liefert die Liste der
|
|
195
|
+
* gesetzten Felder.
|
|
196
|
+
*/
|
|
197
|
+
function idcApplyIndentTabLanguage(doc, target, args) {
|
|
198
|
+
var applied = [];
|
|
199
|
+
var left = null, first = null, right = null, last = null, tabs = null, lang = null;
|
|
200
|
+
var currentLeft = 0;
|
|
201
|
+
|
|
202
|
+
if (idcGiven(args.left_indent_mm)) { left = idcIndentArg(args.left_indent_mm, 'left_indent_mm', 0, IDC_INDENT_MAX_MM); }
|
|
203
|
+
if (idcGiven(args.right_indent_mm)) { right = idcIndentArg(args.right_indent_mm, 'right_indent_mm', 0, IDC_INDENT_MAX_MM); }
|
|
204
|
+
if (idcGiven(args.first_line_indent_mm)) { first = idcIndentArg(args.first_line_indent_mm, 'first_line_indent_mm', -IDC_INDENT_MAX_MM, IDC_INDENT_MAX_MM); }
|
|
205
|
+
if (idcGiven(args.last_line_indent_mm)) { last = idcIndentArg(args.last_line_indent_mm, 'last_line_indent_mm', -IDC_INDENT_MAX_MM, IDC_INDENT_MAX_MM); }
|
|
206
|
+
if (idcGiven(args.tab_stops)) { tabs = idcTabStopsArg(args.tab_stops); }
|
|
207
|
+
if (idcGiven(args.language)) { lang = idcLanguageArg(doc, args.language, 'language'); }
|
|
208
|
+
|
|
209
|
+
/* Ein haengender Einzug darf nicht weiter nach links als der linke Einzug reichen (InDesign lehnt das ab). */
|
|
210
|
+
if (first !== null) {
|
|
211
|
+
try { currentLeft = Number(target.leftIndent); } catch (e0) { currentLeft = 0; }
|
|
212
|
+
if (left !== null) { currentLeft = left; }
|
|
213
|
+
if (first < 0 && -first > currentLeft + 0.0001) {
|
|
214
|
+
IDC.fail('invalid_argument', 'first_line_indent_mm ' + first + ' reaches further left than the left indent (' + IDC.round(currentLeft) + ' mm); a hanging indent needs left_indent_mm >= -first_line_indent_mm.',
|
|
215
|
+
{ first_line_indent_mm: first, left_indent_mm: currentLeft });
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
if (left !== null) { target.leftIndent = left; applied.push('left_indent_mm'); }
|
|
220
|
+
if (right !== null) { target.rightIndent = right; applied.push('right_indent_mm'); }
|
|
221
|
+
if (first !== null) { target.firstLineIndent = first; applied.push('first_line_indent_mm'); }
|
|
222
|
+
if (last !== null) { target.lastLineIndent = last; applied.push('last_line_indent_mm'); }
|
|
223
|
+
if (tabs !== null) { idcSetTabStops(target, tabs); applied.push('tab_stops'); }
|
|
224
|
+
if (lang !== null) { target.appliedLanguage = lang; applied.push('language'); }
|
|
225
|
+
return applied;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
function idcReadIndentTabLanguage(target) {
|
|
229
|
+
return {
|
|
230
|
+
left_indent_mm: idcReadNumberLoose(target, 'leftIndent', 4),
|
|
231
|
+
first_line_indent_mm: idcReadNumberLoose(target, 'firstLineIndent', 4),
|
|
232
|
+
right_indent_mm: idcReadNumberLoose(target, 'rightIndent', 4),
|
|
233
|
+
last_line_indent_mm: idcReadNumberLoose(target, 'lastLineIndent', 4),
|
|
234
|
+
tab_stops: idcReadTabStops(target),
|
|
235
|
+
language: idcReadLanguage(target)
|
|
236
|
+
};
|
|
237
|
+
}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/* Wunschliste J2 Nr. 19 (Sitzung 8) – Formate aus einer Vorlage uebernehmen: import_styles. */
|
|
2
|
+
|
|
3
|
+
var IDC_IMPORT_KINDS = ['paragraph', 'character', 'object', 'table', 'cell', 'swatches'];
|
|
4
|
+
|
|
5
|
+
function idcImportFormatFor(kind) {
|
|
6
|
+
if (typeof ImportFormat === 'undefined') { return null; }
|
|
7
|
+
if (kind === 'paragraph') { return ImportFormat.PARAGRAPH_STYLES_FORMAT; }
|
|
8
|
+
if (kind === 'character') { return ImportFormat.CHARACTER_STYLES_FORMAT; }
|
|
9
|
+
if (kind === 'object') { return ImportFormat.OBJECT_STYLES_FORMAT; }
|
|
10
|
+
if (kind === 'table') { return ImportFormat.TABLE_STYLES_FORMAT; }
|
|
11
|
+
if (kind === 'cell') { return ImportFormat.CELL_STYLES_FORMAT; }
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function idcClashStrategyFor(name) {
|
|
16
|
+
if (typeof GlobalClashResolutionStrategy === 'undefined') { return null; }
|
|
17
|
+
if (name === 'keep_existing') { return GlobalClashResolutionStrategy.DO_NOT_LOAD_THE_STYLE; }
|
|
18
|
+
if (name === 'overwrite') { return GlobalClashResolutionStrategy.LOAD_ALL_WITH_OVERWRITE; }
|
|
19
|
+
if (name === 'rename') { return GlobalClashResolutionStrategy.LOAD_ALL_WITH_RENAME; }
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/* Namen einer Formatart im Dokument (Gruppen eingeschlossen). */
|
|
24
|
+
function idcStyleNamesOfKind(doc, kind) {
|
|
25
|
+
var list = [], i, all = null, collection = null;
|
|
26
|
+
try {
|
|
27
|
+
if (kind === 'paragraph') { all = doc.allParagraphStyles; }
|
|
28
|
+
else if (kind === 'character') { all = doc.allCharacterStyles; }
|
|
29
|
+
else if (kind === 'object') { all = doc.allObjectStyles; }
|
|
30
|
+
else if (kind === 'table') { all = doc.allTableStyles; }
|
|
31
|
+
else if (kind === 'cell') { all = doc.allCellStyles; }
|
|
32
|
+
} catch (e0) { all = null; }
|
|
33
|
+
if (all !== null && all !== undefined) {
|
|
34
|
+
for (i = 0; i < all.length; i++) { try { list.push(String(all[i].name)); } catch (e1) { /* ohne */ } }
|
|
35
|
+
return list;
|
|
36
|
+
}
|
|
37
|
+
try {
|
|
38
|
+
if (kind === 'paragraph') { collection = doc.paragraphStyles; }
|
|
39
|
+
else if (kind === 'character') { collection = doc.characterStyles; }
|
|
40
|
+
else if (kind === 'object') { collection = doc.objectStyles; }
|
|
41
|
+
else if (kind === 'table') { collection = doc.tableStyles; }
|
|
42
|
+
else if (kind === 'cell') { collection = doc.cellStyles; }
|
|
43
|
+
else if (kind === 'swatches') { collection = doc.swatches; }
|
|
44
|
+
if (collection !== null && collection !== undefined) {
|
|
45
|
+
for (i = 0; i < collection.length; i++) { try { list.push(String(collection.item(i).name)); } catch (e2) { /* ohne */ } }
|
|
46
|
+
}
|
|
47
|
+
} catch (e3) { /* leer */ }
|
|
48
|
+
return list;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function idcNamesNotIn(after, before) {
|
|
52
|
+
var out = [], i, j, seen;
|
|
53
|
+
for (i = 0; i < after.length; i++) {
|
|
54
|
+
seen = false;
|
|
55
|
+
for (j = 0; j < before.length; j++) { if (before[j] === after[i]) { seen = true; break; } }
|
|
56
|
+
if (!seen) { out.push(after[i]); }
|
|
57
|
+
}
|
|
58
|
+
return out;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
IDC.register('import_styles', { needs_document: true, read_only: false, ruler: 'none' },
|
|
62
|
+
function (ctx) {
|
|
63
|
+
var args = ctx.args;
|
|
64
|
+
var doc = ctx.doc;
|
|
65
|
+
var path = args.file_path;
|
|
66
|
+
var kinds = args.kinds;
|
|
67
|
+
var onConflict = args.on_conflict === undefined || args.on_conflict === null ? 'keep_existing' : args.on_conflict;
|
|
68
|
+
var file, strategy, i, j, kind, format, before, after, added, results = {}, totalAdded = 0, lower;
|
|
69
|
+
var ownPath = '';
|
|
70
|
+
|
|
71
|
+
if (typeof path !== 'string' || path === '') {
|
|
72
|
+
IDC.fail('invalid_argument', 'file_path is required (.indd, .indt or .idml).', null);
|
|
73
|
+
}
|
|
74
|
+
lower = path.toLowerCase();
|
|
75
|
+
if (!/\.(indd|indt|idml)$/.test(lower)) {
|
|
76
|
+
IDC.fail('invalid_argument', 'file_path must end in .indd, .indt or .idml.', { file_path: path });
|
|
77
|
+
}
|
|
78
|
+
if (kinds === undefined || kinds === null) {
|
|
79
|
+
kinds = IDC_IMPORT_KINDS.slice();
|
|
80
|
+
}
|
|
81
|
+
if (!IDC.isArray(kinds) || kinds.length === 0) {
|
|
82
|
+
IDC.fail('invalid_argument', 'kinds must be a non-empty list of ' + IDC_IMPORT_KINDS.join(', ') + '.', null);
|
|
83
|
+
}
|
|
84
|
+
for (i = 0; i < kinds.length; i++) {
|
|
85
|
+
if (typeof kinds[i] !== 'string') { IDC.fail('invalid_argument', 'kinds must contain names.', { kinds: kinds }); }
|
|
86
|
+
for (j = 0; j < IDC_IMPORT_KINDS.length; j++) { if (IDC_IMPORT_KINDS[j] === kinds[i]) { break; } }
|
|
87
|
+
if (j === IDC_IMPORT_KINDS.length) {
|
|
88
|
+
IDC.fail('invalid_argument', 'Unknown kind "' + kinds[i] + '"; allowed: ' + IDC_IMPORT_KINDS.join(', ') + '.', { kind: kinds[i] });
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
if (onConflict !== 'keep_existing' && onConflict !== 'overwrite' && onConflict !== 'rename') {
|
|
92
|
+
IDC.fail('invalid_argument', 'on_conflict must be keep_existing, overwrite or rename.', { on_conflict: onConflict });
|
|
93
|
+
}
|
|
94
|
+
file = IDC.fileFor(path);
|
|
95
|
+
if (!file.exists) {
|
|
96
|
+
IDC.fail('not_found', 'File not found: ' + path, { file_path: path });
|
|
97
|
+
}
|
|
98
|
+
try { ownPath = idcDocumentPath(doc); } catch (e0) { ownPath = ''; }
|
|
99
|
+
if (ownPath !== '' && IDC.fsPath(file) === ownPath) {
|
|
100
|
+
IDC.fail('invalid_argument', 'file_path is the document itself.', { file_path: path });
|
|
101
|
+
}
|
|
102
|
+
strategy = idcClashStrategyFor(onConflict);
|
|
103
|
+
if (strategy === null) {
|
|
104
|
+
IDC.fail('invalid_state', 'This runtime has no GlobalClashResolutionStrategy enumeration.', null);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
for (i = 0; i < kinds.length; i++) {
|
|
108
|
+
kind = kinds[i];
|
|
109
|
+
before = idcStyleNamesOfKind(doc, kind);
|
|
110
|
+
try {
|
|
111
|
+
if (kind === 'swatches') {
|
|
112
|
+
doc.loadSwatches(file);
|
|
113
|
+
} else {
|
|
114
|
+
format = idcImportFormatFor(kind);
|
|
115
|
+
if (format === null) { IDC.fail('invalid_state', 'This runtime has no ImportFormat enumeration.', null); }
|
|
116
|
+
doc.importStyles(format, file, strategy);
|
|
117
|
+
}
|
|
118
|
+
} catch (e1) {
|
|
119
|
+
if (e1 && e1.isIdcError) { throw e1; }
|
|
120
|
+
IDC.fail('io_error', 'InDesign could not import ' + kind + ' styles from ' + path + ': ' + String(e1.message ? e1.message : e1),
|
|
121
|
+
{ file_path: path, kind: kind, imported_so_far: results });
|
|
122
|
+
}
|
|
123
|
+
after = idcStyleNamesOfKind(doc, kind);
|
|
124
|
+
added = idcNamesNotIn(after, before);
|
|
125
|
+
totalAdded += added.length;
|
|
126
|
+
results[kind] = { before: before.length, after: after.length, added: added };
|
|
127
|
+
}
|
|
128
|
+
if (kinds.length > 0 && totalAdded === 0) {
|
|
129
|
+
ctx.warn('No new styles or swatches were added – the file had none of the requested kinds, or all names existed already (on_conflict ' + onConflict + ').');
|
|
130
|
+
}
|
|
131
|
+
if (onConflict === 'overwrite') {
|
|
132
|
+
ctx.warn('on_conflict overwrite: existing styles with the same names were replaced; the counts cannot show which.');
|
|
133
|
+
}
|
|
134
|
+
ctx.changes = { modified_document_ids: [Number(doc.id)] };
|
|
135
|
+
return {
|
|
136
|
+
file_path: IDC.fsPath(file) || path,
|
|
137
|
+
kinds: kinds,
|
|
138
|
+
on_conflict: onConflict,
|
|
139
|
+
results: results,
|
|
140
|
+
total_added: totalAdded
|
|
141
|
+
};
|
|
142
|
+
});
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/* Wunschliste J2 Nr. 18 (Sitzung 7) – Farbfelder auflisten: list_swatches. */
|
|
2
|
+
|
|
3
|
+
function idcColorSpaceName(value) {
|
|
4
|
+
if (value === undefined || value === null) { return null; }
|
|
5
|
+
if (typeof ColorSpace === 'undefined') { return String(value); }
|
|
6
|
+
if (IDC.enumIs(value, ColorSpace.RGB)) { return 'RGB'; }
|
|
7
|
+
if (IDC.enumIs(value, ColorSpace.CMYK)) { return 'CMYK'; }
|
|
8
|
+
try { if (ColorSpace.LAB !== undefined && IDC.enumIs(value, ColorSpace.LAB)) { return 'LAB'; } } catch (e0) { /* kein LAB */ }
|
|
9
|
+
try { if (ColorSpace.MIXEDINK !== undefined && IDC.enumIs(value, ColorSpace.MIXEDINK)) { return 'MIXED_INK'; } } catch (e1) { /* kein MIXEDINK */ }
|
|
10
|
+
return String(value);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function idcColorModelName(value) {
|
|
14
|
+
if (value === undefined || value === null) { return null; }
|
|
15
|
+
if (typeof ColorModel === 'undefined') { return String(value); }
|
|
16
|
+
if (IDC.enumIs(value, ColorModel.PROCESS)) { return 'process'; }
|
|
17
|
+
if (IDC.enumIs(value, ColorModel.SPOT)) { return 'spot'; }
|
|
18
|
+
try { if (ColorModel.REGISTRATION !== undefined && IDC.enumIs(value, ColorModel.REGISTRATION)) { return 'registration'; } } catch (e0) { /* keine */ }
|
|
19
|
+
return String(value);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function idcNumberList(values) {
|
|
23
|
+
var out = [];
|
|
24
|
+
var i;
|
|
25
|
+
if (!values) { return out; }
|
|
26
|
+
for (i = 0; i < values.length; i++) { out.push(IDC.round(Number(values[i]), 3)); }
|
|
27
|
+
return out;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/* Sammlung (colors, tints, gradients, mixedInks) durchgehen; fehlt sie, leere Liste. */
|
|
31
|
+
function idcEachIn(doc, collectionName, fn) {
|
|
32
|
+
var collection = null, i, item;
|
|
33
|
+
try { collection = doc[collectionName]; } catch (e0) { collection = null; }
|
|
34
|
+
if (collection === null || collection === undefined) { return; }
|
|
35
|
+
for (i = 0; i < collection.length; i++) {
|
|
36
|
+
try { item = collection.item(i); } catch (e1) { continue; }
|
|
37
|
+
fn(item);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function idcDescribeColor(color) {
|
|
42
|
+
var out = { swatch_id: null, name: null, kind: 'color', space: null, model: null, values: [], tint_percent: null, base_color: null, built_in: false };
|
|
43
|
+
try { out.swatch_id = Number(color.id); } catch (e0) { /* null */ }
|
|
44
|
+
try { out.name = String(color.name); } catch (e1) { /* null */ }
|
|
45
|
+
try { out.space = idcColorSpaceName(color.space); } catch (e2) { /* null */ }
|
|
46
|
+
try { out.model = idcColorModelName(color.model); } catch (e3) { /* null */ }
|
|
47
|
+
try { out.values = idcNumberList(color.colorValue); } catch (e4) { out.values = []; }
|
|
48
|
+
out.built_in = out.name !== null && (out.name === 'Black' || out.name === 'Paper' || out.name === 'Registration' || out.name === 'None' || out.name.charAt(0) === '[');
|
|
49
|
+
return out;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
IDC.register('list_swatches', { needs_document: true, read_only: true, ruler: 'none' },
|
|
53
|
+
function (ctx) {
|
|
54
|
+
var args = ctx.args;
|
|
55
|
+
var doc = ctx.doc;
|
|
56
|
+
var includeBuiltIn = args.include_built_in !== false;
|
|
57
|
+
var out = [];
|
|
58
|
+
var counts = { color: 0, tint: 0, gradient: 0, mixed_ink: 0 };
|
|
59
|
+
var unnamed = 0;
|
|
60
|
+
/* Unbenannte Farben (leerer Name, z. B. Verlaufsstufen) sind per Name nicht erreichbar – nur zaehlen (Live-Fund 05.09.2026). */
|
|
61
|
+
var skipUnnamed = function (entry) {
|
|
62
|
+
if (entry.name === null || entry.name === '') { unnamed += 1; return true; }
|
|
63
|
+
return false;
|
|
64
|
+
};
|
|
65
|
+
var noneSwatch = idcNoneSwatch(doc);
|
|
66
|
+
|
|
67
|
+
if (noneSwatch !== null && includeBuiltIn) {
|
|
68
|
+
out.push({ swatch_id: Number(noneSwatch.id), name: String(noneSwatch.name), kind: 'none', space: null, model: null, values: [], tint_percent: null, base_color: null, built_in: true });
|
|
69
|
+
}
|
|
70
|
+
idcEachIn(doc, 'colors', function (color) {
|
|
71
|
+
var entry = idcDescribeColor(color);
|
|
72
|
+
if (skipUnnamed(entry)) { return; }
|
|
73
|
+
if (entry.built_in && !includeBuiltIn) { return; }
|
|
74
|
+
counts.color += 1;
|
|
75
|
+
out.push(entry);
|
|
76
|
+
});
|
|
77
|
+
idcEachIn(doc, 'tints', function (tint) {
|
|
78
|
+
var entry = { swatch_id: null, name: null, kind: 'tint', space: null, model: null, values: [], tint_percent: null, base_color: null, built_in: false };
|
|
79
|
+
try { entry.swatch_id = Number(tint.id); } catch (e0) { /* null */ }
|
|
80
|
+
try { entry.name = String(tint.name); } catch (e1) { /* null */ }
|
|
81
|
+
try { entry.tint_percent = IDC.round(Number(tint.tintValue), 3); } catch (e2) { /* null */ }
|
|
82
|
+
try { entry.base_color = String(tint.baseColor.name); } catch (e3) { /* null */ }
|
|
83
|
+
try { entry.space = idcColorSpaceName(tint.space); } catch (e4) { /* null */ }
|
|
84
|
+
try { entry.values = idcNumberList(tint.colorValue); } catch (e5) { entry.values = []; }
|
|
85
|
+
if (skipUnnamed(entry)) { return; }
|
|
86
|
+
counts.tint += 1;
|
|
87
|
+
out.push(entry);
|
|
88
|
+
});
|
|
89
|
+
idcEachIn(doc, 'gradients', function (gradient) {
|
|
90
|
+
var entry = { swatch_id: null, name: null, kind: 'gradient', space: null, model: null, values: [], tint_percent: null, base_color: null, built_in: false, stop_count: null };
|
|
91
|
+
try { entry.swatch_id = Number(gradient.id); } catch (e0) { /* null */ }
|
|
92
|
+
try { entry.name = String(gradient.name); } catch (e1) { /* null */ }
|
|
93
|
+
try { entry.stop_count = Number(gradient.gradientStops.length); } catch (e2) { /* null */ }
|
|
94
|
+
/* A-8.4: Art und Stopps. */
|
|
95
|
+
entry.type = idcGradientTypeName((function () { try { return gradient.type; } catch (e3) { return null; } })());
|
|
96
|
+
entry.stops = idcReadGradientStops(gradient);
|
|
97
|
+
if (skipUnnamed(entry)) { return; }
|
|
98
|
+
counts.gradient += 1;
|
|
99
|
+
out.push(entry);
|
|
100
|
+
});
|
|
101
|
+
idcEachIn(doc, 'mixedInks', function (ink) {
|
|
102
|
+
var entry = { swatch_id: null, name: null, kind: 'mixed_ink', space: 'MIXED_INK', model: null, values: [], tint_percent: null, base_color: null, built_in: false };
|
|
103
|
+
try { entry.swatch_id = Number(ink.id); } catch (e0) { /* null */ }
|
|
104
|
+
try { entry.name = String(ink.name); } catch (e1) { /* null */ }
|
|
105
|
+
try { entry.values = idcNumberList(ink.inkPercentages); } catch (e2) { entry.values = []; }
|
|
106
|
+
if (skipUnnamed(entry)) { return; }
|
|
107
|
+
counts.mixed_ink += 1;
|
|
108
|
+
out.push(entry);
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
return { swatches: out, count: out.length, counts: counts, unnamed_skipped: unnamed, include_built_in: includeBuiltIn };
|
|
112
|
+
});
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Auftrag A-8.4 (Sitzung 9) – create_gradient_swatch: Verlaufsfarbfeld
|
|
3
|
+
* anlegen, das an Flaechen und Konturen per fill_swatch_name /
|
|
4
|
+
* stroke_swatch_name verwendet wird. Adobe-DOM (Auftrag, geprueft
|
|
5
|
+
* 05.09.2026): Gradients.add(withProperties) -> Gradient {name, type
|
|
6
|
+
* (GradientType.LINEAR|RADIAL), gradientStops}; GradientStops.add() ->
|
|
7
|
+
* GradientStop {stopColor (Swatch-Objekt), location 0–100, midpoint 13–87}.
|
|
8
|
+
* Ob ein neuer Verlauf schon zwei Stopps traegt: live pruefen (Journal).
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
function idcGradientTypeFor(name) {
|
|
12
|
+
if (typeof GradientType === 'undefined') {
|
|
13
|
+
IDC.fail('invalid_state', 'This runtime has no GradientType enumeration.', null);
|
|
14
|
+
}
|
|
15
|
+
if (name === 'linear') { return GradientType.LINEAR; }
|
|
16
|
+
if (name === 'radial') { return GradientType.RADIAL; }
|
|
17
|
+
IDC.fail('invalid_argument', 'type must be linear or radial.', { type: name });
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function idcGradientTypeName(value) {
|
|
22
|
+
if (value === null || value === undefined || typeof GradientType === 'undefined') { return null; }
|
|
23
|
+
if (IDC.enumIs(value, GradientType.LINEAR)) { return 'linear'; }
|
|
24
|
+
if (IDC.enumIs(value, GradientType.RADIAL)) { return 'radial'; }
|
|
25
|
+
return String(value);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/* Stopps eines Verlaufs lesen: [{index, swatch_name, location, midpoint}]. */
|
|
29
|
+
function idcReadGradientStops(gradient) {
|
|
30
|
+
var out = [], stops, i, stop, entry;
|
|
31
|
+
try { stops = gradient.gradientStops; } catch (e0) { return out; }
|
|
32
|
+
for (i = 0; i < stops.length; i++) {
|
|
33
|
+
entry = { index: i, swatch_name: null, location: null, midpoint: null };
|
|
34
|
+
try { stop = stops.item(i); } catch (e1) { continue; }
|
|
35
|
+
try { entry.swatch_name = String(stop.stopColor.name); } catch (e2) { /* null */ }
|
|
36
|
+
try { entry.location = IDC.round(Number(stop.location), 3); } catch (e3) { /* null */ }
|
|
37
|
+
try { entry.midpoint = IDC.round(Number(stop.midpoint), 3); } catch (e4) { /* null */ }
|
|
38
|
+
out.push(entry);
|
|
39
|
+
}
|
|
40
|
+
return out;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/* Stopp-Angabe pruefen und das Farbfeld dafuer beschaffen (Name, Hex oder CMYK). */
|
|
44
|
+
function idcGradientStopArg(doc, spec, index, gradientName, created) {
|
|
45
|
+
var ways = 0, swatch = null, kind, hexName;
|
|
46
|
+
if (spec === null || typeof spec !== 'object' || IDC.isArray(spec)) {
|
|
47
|
+
IDC.fail('invalid_argument', 'stops[' + index + '] must be an object {swatch_name | hex | cmyk, location, midpoint}.', { value: spec });
|
|
48
|
+
}
|
|
49
|
+
if (idcGiven(spec.swatch_name)) { ways += 1; }
|
|
50
|
+
if (idcGiven(spec.hex)) { ways += 1; }
|
|
51
|
+
if (idcGiven(spec.cmyk)) { ways += 1; }
|
|
52
|
+
if (ways !== 1) {
|
|
53
|
+
IDC.fail('invalid_argument', 'stops[' + index + '] needs exactly one of swatch_name, hex or cmyk.', { value: spec });
|
|
54
|
+
}
|
|
55
|
+
if (typeof spec.location !== 'number' || !isFinite(spec.location) || spec.location < 0 || spec.location > 100) {
|
|
56
|
+
IDC.fail('invalid_argument', 'stops[' + index + '].location must be a number between 0 and 100.', { value: spec.location });
|
|
57
|
+
}
|
|
58
|
+
if (idcGiven(spec.midpoint) && (typeof spec.midpoint !== 'number' || !isFinite(spec.midpoint) || spec.midpoint < 13 || spec.midpoint > 87)) {
|
|
59
|
+
IDC.fail('invalid_argument', 'stops[' + index + '].midpoint must be a number between 13 and 87.', { value: spec.midpoint });
|
|
60
|
+
}
|
|
61
|
+
if (idcGiven(spec.swatch_name)) {
|
|
62
|
+
swatch = idcSwatchArg(doc, spec.swatch_name, 'stops[' + index + '].swatch_name');
|
|
63
|
+
kind = idcSwatchKind(swatch);
|
|
64
|
+
if (kind !== 'color' && kind !== 'tint') {
|
|
65
|
+
IDC.fail('invalid_argument', 'stops[' + index + '].swatch_name must be a colour or tint swatch, not a ' + kind + '.', { swatch_name: spec.swatch_name, kind: kind });
|
|
66
|
+
}
|
|
67
|
+
} else if (idcGiven(spec.hex)) {
|
|
68
|
+
swatch = idcSwatchForHex(doc, spec.hex, 'stops[' + index + '].hex', created);
|
|
69
|
+
} else {
|
|
70
|
+
hexName = gradientName + ' Stopp ' + (index + 1);
|
|
71
|
+
swatch = idcSwatchByName(doc, hexName);
|
|
72
|
+
if (swatch === null) {
|
|
73
|
+
try {
|
|
74
|
+
swatch = doc.colors.add({ name: hexName, model: ColorModel.PROCESS, space: ColorSpace.CMYK, colorValue: idcCmykArg(spec.cmyk) });
|
|
75
|
+
created.push(Number(swatch.id));
|
|
76
|
+
} catch (e) {
|
|
77
|
+
IDC.fail('script_error', 'InDesign could not create the stop swatch "' + hexName + '": ' + String(e.message ? e.message : e), { name: hexName });
|
|
78
|
+
}
|
|
79
|
+
} else {
|
|
80
|
+
try { swatch.colorValue = idcCmykArg(spec.cmyk); } catch (e2) { /* Werte bleiben */ }
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return { swatch: swatch, location: spec.location, midpoint: idcGiven(spec.midpoint) ? spec.midpoint : null };
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/* Stopps in den Verlauf schreiben: vorhandene setzen, fehlende anlegen, ueberzaehlige entfernen. */
|
|
87
|
+
function idcWriteGradientStops(gradient, stops) {
|
|
88
|
+
var collection = gradient.gradientStops;
|
|
89
|
+
var i, stop, count;
|
|
90
|
+
for (i = 0; i < stops.length; i++) {
|
|
91
|
+
try { count = Number(collection.length); } catch (e0) { count = 0; }
|
|
92
|
+
if (i < count) { stop = collection.item(i); }
|
|
93
|
+
else { stop = collection.add(); }
|
|
94
|
+
stop.stopColor = stops[i].swatch;
|
|
95
|
+
stop.location = stops[i].location;
|
|
96
|
+
if (stops[i].midpoint !== null) { stop.midpoint = stops[i].midpoint; }
|
|
97
|
+
}
|
|
98
|
+
try { count = Number(collection.length); } catch (e1) { count = stops.length; }
|
|
99
|
+
while (count > stops.length) {
|
|
100
|
+
try { collection.item(count - 1).remove(); } catch (e2) { break; }
|
|
101
|
+
count -= 1;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
IDC.register('create_gradient_swatch', { needs_document: true, read_only: false, ruler: 'none' },
|
|
106
|
+
function (ctx) {
|
|
107
|
+
var args = ctx.args;
|
|
108
|
+
var doc = ctx.doc;
|
|
109
|
+
var name = args.name;
|
|
110
|
+
var typeName = idcGiven(args.type) ? String(args.type) : 'linear';
|
|
111
|
+
var onCollision = idcCollisionArg(args.on_collision);
|
|
112
|
+
var created = [];
|
|
113
|
+
var stops = [], i, existing, existed, collision = 'none', chosenName, gradient = null, className, previous = null;
|
|
114
|
+
|
|
115
|
+
if (typeof name !== 'string' || name.length < 1 || name.length > 60) {
|
|
116
|
+
IDC.fail('invalid_argument', 'name is required (1–60 characters).', { name: name });
|
|
117
|
+
}
|
|
118
|
+
if (name.charAt(0) === '[') {
|
|
119
|
+
IDC.fail('invalid_argument', 'name must not start with "[".', { name: name });
|
|
120
|
+
}
|
|
121
|
+
idcGradientTypeFor(typeName);
|
|
122
|
+
if (!IDC.isArray(args.stops) || args.stops.length < 2 || args.stops.length > 20) {
|
|
123
|
+
IDC.fail('invalid_argument', 'stops must be an array of 2 to 20 entries in order.', { count: IDC.isArray(args.stops) ? args.stops.length : null });
|
|
124
|
+
}
|
|
125
|
+
for (i = 0; i < args.stops.length; i++) {
|
|
126
|
+
stops.push(idcGradientStopArg(doc, args.stops[i], i, name, created));
|
|
127
|
+
if (i > 0 && stops[i].location < stops[i - 1].location) {
|
|
128
|
+
IDC.fail('invalid_argument', 'stops must be in ascending order of location (stop ' + i + ' is at ' + stops[i].location + ', the one before at ' + stops[i - 1].location + ').', null);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
if (stops[0].location !== 0) { ctx.warn('The first stop is at ' + stops[0].location + ' %, not 0 % – the gradient starts with a flat area.'); }
|
|
132
|
+
if (stops[stops.length - 1].location !== 100) { ctx.warn('The last stop is at ' + stops[stops.length - 1].location + ' %, not 100 % – the gradient ends with a flat area.'); }
|
|
133
|
+
|
|
134
|
+
chosenName = name;
|
|
135
|
+
existing = idcSwatchByName(doc, name);
|
|
136
|
+
existed = idcPresent(existing);
|
|
137
|
+
if (existed) {
|
|
138
|
+
className = IDC.className(existing);
|
|
139
|
+
if (onCollision === 'error') {
|
|
140
|
+
IDC.fail('invalid_state', 'Swatch "' + name + '" exists already (' + className + '). Pass on_collision "update" to change it or "version" to add "' + name + ' 2".',
|
|
141
|
+
{ name: name, swatch_id: (function () { try { return Number(existing.id); } catch (e) { return null; } })() });
|
|
142
|
+
}
|
|
143
|
+
if (onCollision === 'update') {
|
|
144
|
+
if (className !== 'Gradient') {
|
|
145
|
+
IDC.fail('invalid_state', 'Swatch "' + name + '" is a ' + className + ', not a gradient; it cannot be updated with stops.', { name: name, type: className });
|
|
146
|
+
}
|
|
147
|
+
gradient = existing;
|
|
148
|
+
collision = 'updated';
|
|
149
|
+
previous = { type: idcGradientTypeName(gradient.type), stops: idcReadGradientStops(gradient) };
|
|
150
|
+
} else {
|
|
151
|
+
chosenName = idcFreeName(doc, name, 'swatch');
|
|
152
|
+
collision = 'versioned';
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
if (gradient === null) {
|
|
156
|
+
try {
|
|
157
|
+
gradient = doc.gradients.add({ name: chosenName, type: idcGradientTypeFor(typeName) });
|
|
158
|
+
} catch (e2) {
|
|
159
|
+
IDC.fail('script_error', 'InDesign could not create the gradient "' + chosenName + '": ' + String(e2.message ? e2.message : e2), { name: chosenName });
|
|
160
|
+
}
|
|
161
|
+
} else {
|
|
162
|
+
try { gradient.type = idcGradientTypeFor(typeName); } catch (e3) { /* Art bleibt */ }
|
|
163
|
+
}
|
|
164
|
+
try {
|
|
165
|
+
idcWriteGradientStops(gradient, stops);
|
|
166
|
+
} catch (e4) {
|
|
167
|
+
IDC.fail('script_error', 'InDesign could not write the gradient stops of "' + chosenName + '": ' + String(e4.message ? e4.message : e4), { name: chosenName });
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
var changes = { created_swatch_ids: created.slice() };
|
|
171
|
+
if (collision === 'updated') { changes.modified_swatch_ids = [Number(gradient.id)]; }
|
|
172
|
+
else { changes.created_swatch_ids.push(Number(gradient.id)); }
|
|
173
|
+
ctx.changes = changes;
|
|
174
|
+
return {
|
|
175
|
+
name: String(gradient.name),
|
|
176
|
+
swatch_id: Number(gradient.id),
|
|
177
|
+
type: idcGradientTypeName(gradient.type),
|
|
178
|
+
stops: idcReadGradientStops(gradient),
|
|
179
|
+
stop_count: idcReadGradientStops(gradient).length,
|
|
180
|
+
collision: collision,
|
|
181
|
+
existed: existed,
|
|
182
|
+
previous: previous,
|
|
183
|
+
swatch_ids: created
|
|
184
|
+
};
|
|
185
|
+
});
|