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,781 @@
|
|
|
1
|
+
/* Bereich E – Rahmen und Objekte veraendern. */
|
|
2
|
+
|
|
3
|
+
/* Objekt, das kein Gruppenmitglied ist; sonst invalid_state. */
|
|
4
|
+
function idcRejectGroupMember(item, frameId, what) {
|
|
5
|
+
var parentName = '';
|
|
6
|
+
try { parentName = IDC.className(item.parent); } catch (e) { parentName = ''; }
|
|
7
|
+
if (parentName === 'Group') {
|
|
8
|
+
IDC.fail('invalid_state', 'Object ' + frameId + ' is inside a group; ' + what + ' works on the group as a whole (its parent group id is ' +
|
|
9
|
+
String(item.parent.id) + ').', { frame_id: frameId, parent_group_id: Number(item.parent.id) });
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/* Textrahmen verlangen, sonst invalid_state. */
|
|
14
|
+
function idcTextFrameArg(doc, args, field) {
|
|
15
|
+
var found = idcFrameArg(doc, args, field);
|
|
16
|
+
if (!IDC.isTextFrame(found.item)) {
|
|
17
|
+
IDC.fail('invalid_state', 'Object ' + args[field] + ' is not a text frame (it is a ' + IDC.itemType(found.item) + ').',
|
|
18
|
+
{ frame_id: args[field], type: IDC.itemType(found.item) });
|
|
19
|
+
}
|
|
20
|
+
return found;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function idcRotationOf(item) {
|
|
24
|
+
try { return IDC.round(Number(item.rotationAngle), 3); } catch (e) { return null; }
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/* Seite, auf der ein Objekt liegt (Dokument- oder Musterseite), sonst null. */
|
|
28
|
+
function idcPageOfItem(doc, item) {
|
|
29
|
+
var landing = IDC.landing(item);
|
|
30
|
+
var found;
|
|
31
|
+
if (landing.on_pasteboard) { return null; }
|
|
32
|
+
found = IDC.pageById(doc, landing.page_id);
|
|
33
|
+
return found === null ? null : found.page;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/* Begrenzung unter Bogen-Nullpunkt schreiben (E-28). Nur der Rahmen – eine platzierte Grafik bleibt liegen. */
|
|
37
|
+
function idcWriteSpreadBounds(doc, item, spreadBounds) {
|
|
38
|
+
IDC.withRulerOrigin(doc, RulerOrigin.SPREAD_ORIGIN, function () {
|
|
39
|
+
item.geometricBounds = spreadBounds;
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/*
|
|
44
|
+
* Objekt um dx/dy mm verschieben – ueber move(), damit eine platzierte
|
|
45
|
+
* Grafik mitwandert. geometricBounds allein verschiebt nur den Rahmen und
|
|
46
|
+
* beschneidet das Bild neu (Live-Fund 04.09.2026, Integrationssuite).
|
|
47
|
+
*/
|
|
48
|
+
function idcMoveBy(doc, item, dx, dy) {
|
|
49
|
+
if (Math.abs(dx) < 0.0005 && Math.abs(dy) < 0.0005) { return; }
|
|
50
|
+
IDC.withRulerOrigin(doc, RulerOrigin.SPREAD_ORIGIN, function () {
|
|
51
|
+
item.move(undefined, [dx, dy]);
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/*
|
|
56
|
+
* Zielbegrenzung (Bogenkoordinaten [y1, x1, y2, x2]) setzen: erst die Lage
|
|
57
|
+
* per move() (Inhalt geht mit), dann bei geaenderter Groesse die Begrenzung.
|
|
58
|
+
*/
|
|
59
|
+
function idcPlaceSpreadBounds(doc, item, spreadBounds) {
|
|
60
|
+
var current = IDC.withRulerOrigin(doc, RulerOrigin.SPREAD_ORIGIN, function () { return item.geometricBounds; });
|
|
61
|
+
var dx = spreadBounds[1] - current[1];
|
|
62
|
+
var dy = spreadBounds[0] - current[0];
|
|
63
|
+
var resized = Math.abs((spreadBounds[3] - spreadBounds[1]) - (current[3] - current[1])) > 0.0005
|
|
64
|
+
|| Math.abs((spreadBounds[2] - spreadBounds[0]) - (current[2] - current[0])) > 0.0005;
|
|
65
|
+
idcMoveBy(doc, item, dx, dy);
|
|
66
|
+
if (resized) { idcWriteSpreadBounds(doc, item, spreadBounds); }
|
|
67
|
+
return resized;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/* --------------------------------------------------------- set_frame_bounds */
|
|
71
|
+
|
|
72
|
+
IDC.register('set_frame_bounds', { needs_document: true, read_only: false, ruler: 'page' },
|
|
73
|
+
function (ctx) {
|
|
74
|
+
var args = ctx.args;
|
|
75
|
+
var doc = ctx.doc;
|
|
76
|
+
var found = idcFrameArg(doc, args, 'frame_id');
|
|
77
|
+
var item = found.item;
|
|
78
|
+
var rect = idcBoundsArg(args.bounds_mm, 'bounds_mm');
|
|
79
|
+
var type = IDC.itemType(item);
|
|
80
|
+
var page = null, pageFound, itemSpread, pageSpread, rotation, landing, bounds;
|
|
81
|
+
|
|
82
|
+
if (type === 'group') {
|
|
83
|
+
IDC.fail('invalid_state', 'Object ' + args.frame_id + ' is a group; set_frame_bounds would move the frames without their graphics. Use move_frame_to_page (also for a position on the same page) or address the members.',
|
|
84
|
+
{ frame_id: args.frame_id, type: 'group' });
|
|
85
|
+
}
|
|
86
|
+
idcRejectGroupMember(item, args.frame_id, 'set_frame_bounds');
|
|
87
|
+
|
|
88
|
+
if (args.page_id !== undefined && args.page_id !== null) {
|
|
89
|
+
pageFound = idcAnyPageById(doc, args.page_id);
|
|
90
|
+
page = pageFound.page;
|
|
91
|
+
itemSpread = IDC.spreadOfItem(item);
|
|
92
|
+
try { pageSpread = page.parent; } catch (e0) { pageSpread = null; }
|
|
93
|
+
if (itemSpread !== null && pageSpread !== null && Number(itemSpread.id) !== Number(pageSpread.id)) {
|
|
94
|
+
IDC.fail('invalid_argument', 'page_id ' + args.page_id + ' lies on another spread (Druckbogen) than object ' + args.frame_id +
|
|
95
|
+
'. set_frame_bounds never changes the spread – use move_frame_to_page.', { frame_id: args.frame_id, page_id: args.page_id });
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
rotation = idcRotationOf(item);
|
|
100
|
+
if (rotation !== null && rotation !== 0) {
|
|
101
|
+
ctx.warn('Object ' + args.frame_id + ' is rotated by ' + rotation + ' degrees; the bounds apply in its rotated space. Set set_frame_rotation 0 first for page-aligned values.');
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/* Stand vor dem Eingriff: Seite und Uebersatz (Vermerk E-63). */
|
|
105
|
+
var pageBefore = IDC.landing(item);
|
|
106
|
+
var recBefore = idcRecomposeBefore(doc, item);
|
|
107
|
+
var resized = false;
|
|
108
|
+
try {
|
|
109
|
+
resized = idcPlaceSpreadBounds(doc, item, idcToSpreadBounds(page, idcRectToBounds(rect), page === null ? 'spread' : 'page'));
|
|
110
|
+
} catch (e) {
|
|
111
|
+
IDC.fail('script_error', 'InDesign could not set the bounds of object ' + args.frame_id + ': ' + String(e.message ? e.message : e),
|
|
112
|
+
{ frame_id: args.frame_id, bounds_mm: rect });
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
var rec = idcRecomposeAfter(ctx, doc, recBefore);
|
|
116
|
+
landing = IDC.landing(item);
|
|
117
|
+
/*
|
|
118
|
+
* Ohne page_id sind die Werte Bogenkoordinaten. Wer seitenrelativ gelesene
|
|
119
|
+
* Werte unveraendert zurueckgibt, verschiebt den Rahmen auf die Nachbarseite
|
|
120
|
+
* - deshalb eine Warnung, sobald der Rahmen dabei die Seite wechselt (E-63).
|
|
121
|
+
*/
|
|
122
|
+
if (page === null && pageBefore.on_pasteboard !== true && landing.on_pasteboard !== true
|
|
123
|
+
&& landing.page_id !== pageBefore.page_id) {
|
|
124
|
+
ctx.warn('Object ' + args.frame_id + ' moved from page ' + pageBefore.page_name + ' to page ' + landing.page_name +
|
|
125
|
+
'; without page_id bounds_mm are spread coordinates (Druckbogen). Values from get_page_state, get_frame_options, get_selection or get_image_link_info are page coordinates (coordinate_space "page") - pass page_id to use them unchanged.');
|
|
126
|
+
}
|
|
127
|
+
if (page !== null) {
|
|
128
|
+
idcCheckLanding(ctx, item, page, IDC.itemType(item) === 'text' ? 'text frame' : 'object');
|
|
129
|
+
bounds = IDC.boundsOnPage(doc, item, page);
|
|
130
|
+
} else {
|
|
131
|
+
bounds = IDC.boundsOnPage(doc, item, null);
|
|
132
|
+
}
|
|
133
|
+
if (type === 'image' && resized) {
|
|
134
|
+
ctx.warn('The frame holds a graphic and was resized; the graphic keeps its position and scale (new crop) – place it again or run scale_image_in_frame / get_image_link_info to check.');
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
ctx.changes = { modified_frame_ids: [Number(item.id)] };
|
|
138
|
+
return {
|
|
139
|
+
frame_id: Number(item.id),
|
|
140
|
+
type: type,
|
|
141
|
+
bounds_mm: bounds,
|
|
142
|
+
coordinate_space: page === null ? 'spread' : 'page',
|
|
143
|
+
page_id: page === null ? null : Number(page.id),
|
|
144
|
+
rotation_deg: rotation,
|
|
145
|
+
resized: resized,
|
|
146
|
+
landed_on_page_id: landing.page_id,
|
|
147
|
+
landed_on_page_name: landing.page_name,
|
|
148
|
+
on_parent_page: found.on_parent,
|
|
149
|
+
recomposed: rec.recomposed,
|
|
150
|
+
overset_stories_before: rec.overset_stories_before,
|
|
151
|
+
overset_stories_after: rec.overset_stories_after,
|
|
152
|
+
overset_changed: rec.overset_changed
|
|
153
|
+
};
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
/* ------------------------------------------------------- move_frame_to_page */
|
|
157
|
+
|
|
158
|
+
/*
|
|
159
|
+
* Sitzung 24 (Befund aus dem Praxiseinsatz, E-79): Ziel Montageflaeche neben dem
|
|
160
|
+
* Bogen der Zielseite – pasteboard {side, gap_mm, y_mm}. side left: links
|
|
161
|
+
* von der linken Seite des Bogens, right: rechts von der rechten; gap_mm ist
|
|
162
|
+
* der Abstand zwischen Objekt und Seitenkante.
|
|
163
|
+
*/
|
|
164
|
+
function idcPasteboardTargetArg(spec) {
|
|
165
|
+
if (!spec || typeof spec !== 'object') {
|
|
166
|
+
IDC.fail('invalid_argument', 'pasteboard must be an object { side, gap_mm, y_mm }.', null);
|
|
167
|
+
}
|
|
168
|
+
if (spec.side !== 'left' && spec.side !== 'right') {
|
|
169
|
+
IDC.fail('invalid_argument', 'pasteboard.side must be "left" or "right".', { side: spec.side });
|
|
170
|
+
}
|
|
171
|
+
if (typeof spec.gap_mm !== 'number' || !isFinite(spec.gap_mm) || spec.gap_mm < 0) {
|
|
172
|
+
IDC.fail('invalid_argument', 'pasteboard.gap_mm must be a number of 0 or more (mm).', { gap_mm: spec.gap_mm });
|
|
173
|
+
}
|
|
174
|
+
if (spec.y_mm !== undefined && spec.y_mm !== null && (typeof spec.y_mm !== 'number' || !isFinite(spec.y_mm))) {
|
|
175
|
+
IDC.fail('invalid_argument', 'pasteboard.y_mm must be a number (mm from the top of the page).', { y_mm: spec.y_mm });
|
|
176
|
+
}
|
|
177
|
+
return { side: spec.side, gap_mm: spec.gap_mm, y_mm: spec.y_mm === undefined ? null : spec.y_mm };
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/* Breite aller Seiten des Bogens einer Seite in mm. */
|
|
181
|
+
function idcSpreadWidthOfPage(page) {
|
|
182
|
+
var spread = page.parent;
|
|
183
|
+
var i, width = 0;
|
|
184
|
+
for (i = 0; i < spread.pages.length; i++) { width += IDC.pageSize(spread.pages.item(i)).width; }
|
|
185
|
+
return width;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
IDC.register('move_frame_to_page', { needs_document: true, read_only: false, ruler: 'page' },
|
|
189
|
+
function (ctx) {
|
|
190
|
+
var args = ctx.args;
|
|
191
|
+
var doc = ctx.doc;
|
|
192
|
+
var found = idcFrameArg(doc, args, 'frame_id');
|
|
193
|
+
var item = found.item;
|
|
194
|
+
var pageFound = idcAnyPageById(doc, args.page_id);
|
|
195
|
+
var page = pageFound.page;
|
|
196
|
+
var oldId = Number(item.id);
|
|
197
|
+
var idPreserved = true;
|
|
198
|
+
var position = null;
|
|
199
|
+
var pasteboard = null;
|
|
200
|
+
var before, rotation, moved, copy, landing, bounds, target;
|
|
201
|
+
|
|
202
|
+
idcRejectGroupMember(item, args.frame_id, 'move_frame_to_page');
|
|
203
|
+
if (args.position_mm !== undefined && args.position_mm !== null) { position = idcPointArg(args.position_mm, 'position_mm'); }
|
|
204
|
+
if (args.pasteboard !== undefined && args.pasteboard !== null) {
|
|
205
|
+
pasteboard = idcPasteboardTargetArg(args.pasteboard);
|
|
206
|
+
if (position !== null) {
|
|
207
|
+
IDC.fail('invalid_argument', 'Pass either position_mm or pasteboard, not both (pasteboard.y_mm sets the height).', null);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
rotation = idcRotationOf(item);
|
|
212
|
+
if (rotation !== null && rotation !== 0) {
|
|
213
|
+
ctx.warn('Object ' + args.frame_id + ' is rotated by ' + rotation + ' degrees; set set_frame_rotation 0 before moving for predictable coordinates.');
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
var recBeforeMove = idcRecomposeBefore(doc, item);
|
|
217
|
+
/* Position wie auf der alten Seite: relativ zur Seite, auf der InDesign das Objekt fuehrt (Montageflaeche: Bogen). */
|
|
218
|
+
before = IDC.boundsOnOwnPage(doc, item);
|
|
219
|
+
target = position === null ? { x: before.x, y: before.y } : position;
|
|
220
|
+
|
|
221
|
+
/* Erst die DOM-Methode move() – nur so gehen die Grafiken einer Gruppe mit. */
|
|
222
|
+
try {
|
|
223
|
+
moved = item.move(page);
|
|
224
|
+
if (IDC.isArray(moved)) { moved = moved[0]; }
|
|
225
|
+
if (moved !== undefined && moved !== null) { moved = IDC.concrete(moved); }
|
|
226
|
+
else { moved = item; }
|
|
227
|
+
} catch (e) {
|
|
228
|
+
/* Rueckfall: Duplizieren auf die Seite und Original loeschen – neue ID. */
|
|
229
|
+
try {
|
|
230
|
+
copy = item.duplicate(page);
|
|
231
|
+
if (IDC.isArray(copy)) { copy = copy[0]; }
|
|
232
|
+
copy = IDC.concrete(copy);
|
|
233
|
+
item.remove();
|
|
234
|
+
moved = copy;
|
|
235
|
+
idPreserved = false;
|
|
236
|
+
ctx.warn('InDesign could not move object ' + args.frame_id + ' directly (' + String(e.message ? e.message : e) +
|
|
237
|
+
'); it was duplicated onto page ' + String(page.name) + ' and the original removed – the object has a new id.');
|
|
238
|
+
} catch (e2) {
|
|
239
|
+
IDC.fail('script_error', 'InDesign could not move object ' + args.frame_id + ' to page ' + String(page.name) + ': ' +
|
|
240
|
+
String(e.message ? e.message : e) + ' / fallback: ' + String(e2.message ? e2.message : e2), { frame_id: args.frame_id, page_id: args.page_id });
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
item = moved;
|
|
244
|
+
try { if (Number(item.id) !== oldId) { idPreserved = false; } } catch (e3) { /* egal */ }
|
|
245
|
+
|
|
246
|
+
/* Zielposition seitenrelativ setzen: Groesse bleibt, x/y unter Bogen-Nullpunkt (E-28). */
|
|
247
|
+
try {
|
|
248
|
+
bounds = IDC.boundsOnPage(doc, item, page);
|
|
249
|
+
if (pasteboard !== null) {
|
|
250
|
+
/* Neben dem Bogen: links von dessen linker Seite oder rechts von dessen rechter (Werte relativ zu page). */
|
|
251
|
+
if (pasteboard.side === 'left') { target.x = -IDC.spreadOffsetOfPage(page) - pasteboard.gap_mm - bounds.width; }
|
|
252
|
+
else { target.x = idcSpreadWidthOfPage(page) - IDC.spreadOffsetOfPage(page) + pasteboard.gap_mm; }
|
|
253
|
+
if (pasteboard.y_mm !== null) { target.y = pasteboard.y_mm; }
|
|
254
|
+
}
|
|
255
|
+
/* Per move(): nur so wandert eine platzierte Grafik mit (Live-Fund 04.09.2026). */
|
|
256
|
+
idcMoveBy(doc, item, target.x - bounds.x, target.y - bounds.y);
|
|
257
|
+
} catch (e4) {
|
|
258
|
+
ctx.warn('The object was moved to page ' + String(page.name) + ' but could not be positioned at ' + target.x + '/' + target.y + ' mm: ' +
|
|
259
|
+
String(e4.message ? e4.message : e4));
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
var recMove = idcRecomposeAfter(ctx, doc, recBeforeMove);
|
|
263
|
+
if (pasteboard !== null) {
|
|
264
|
+
landing = IDC.landing(item);
|
|
265
|
+
if (!landing.on_pasteboard) {
|
|
266
|
+
ctx.warn('The object was meant for the pasteboard (Montageflaeche) but InDesign assigns it to page ' + landing.page_name +
|
|
267
|
+
' – its centre lies on that page. Check the size of the object and gap_mm.');
|
|
268
|
+
}
|
|
269
|
+
} else {
|
|
270
|
+
landing = idcCheckLanding(ctx, item, page, IDC.itemType(item) === 'text' ? 'text frame' : 'object');
|
|
271
|
+
if (landing.on_pasteboard || landing.page_id !== Number(page.id)) {
|
|
272
|
+
ctx.warn('InDesign assigns an object to the page holding its centre; for a half-page bleed object set the bounds in spread coordinates with set_frame_bounds without page_id.');
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
ctx.changes = idPreserved
|
|
277
|
+
? { modified_frame_ids: [Number(item.id)] }
|
|
278
|
+
: { removed_frame_ids: [oldId], created_frame_ids: [Number(item.id)], modified_frame_ids: [] };
|
|
279
|
+
return {
|
|
280
|
+
frame_id: Number(item.id),
|
|
281
|
+
previous_frame_id: oldId,
|
|
282
|
+
id_preserved: idPreserved,
|
|
283
|
+
type: IDC.itemType(item),
|
|
284
|
+
page_id: Number(page.id),
|
|
285
|
+
bounds_mm: IDC.boundsOnPage(doc, item, page),
|
|
286
|
+
landed_on_page_id: landing.page_id,
|
|
287
|
+
landed_on_page_name: landing.page_name,
|
|
288
|
+
on_pasteboard: landing.on_pasteboard,
|
|
289
|
+
pasteboard_side: pasteboard === null ? null : pasteboard.side,
|
|
290
|
+
on_parent_page: pageFound.is_parent_page,
|
|
291
|
+
coordinate_space: 'page',
|
|
292
|
+
recomposed: recMove.recomposed,
|
|
293
|
+
overset_stories_before: recMove.overset_stories_before,
|
|
294
|
+
overset_stories_after: recMove.overset_stories_after,
|
|
295
|
+
overset_changed: recMove.overset_changed
|
|
296
|
+
};
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
/* ------------------------------------------------------- set_frame_rotation */
|
|
300
|
+
|
|
301
|
+
IDC.register('set_frame_rotation', { needs_document: true, read_only: false, ruler: 'page' },
|
|
302
|
+
function (ctx) {
|
|
303
|
+
var args = ctx.args;
|
|
304
|
+
var doc = ctx.doc;
|
|
305
|
+
var found = idcFrameArg(doc, args, 'frame_id');
|
|
306
|
+
var item = found.item;
|
|
307
|
+
var wanted = args.angle_deg;
|
|
308
|
+
var current, delta, matrix, after;
|
|
309
|
+
|
|
310
|
+
if (typeof wanted !== 'number' || !isFinite(wanted) || wanted < -360 || wanted > 360) {
|
|
311
|
+
IDC.fail('invalid_argument', 'angle_deg must be a number between -360 and 360 (absolute, positive = counterclockwise).', { angle_deg: wanted });
|
|
312
|
+
}
|
|
313
|
+
current = idcRotationOf(item);
|
|
314
|
+
if (current === null) {
|
|
315
|
+
IDC.fail('invalid_state', 'Object ' + args.frame_id + ' has no rotation angle.', { frame_id: args.frame_id });
|
|
316
|
+
}
|
|
317
|
+
delta = wanted - current;
|
|
318
|
+
|
|
319
|
+
/*
|
|
320
|
+
* Um den Mittelpunkt drehen: transform() mit dem Anker CENTER_ANCHOR und
|
|
321
|
+
* einer Drehmatrix um die Differenz. rotationAngle allein dreht um den
|
|
322
|
+
* Bezugspunkt der Palette, nicht sicher um die Mitte.
|
|
323
|
+
*/
|
|
324
|
+
try {
|
|
325
|
+
if (Math.abs(delta) > 0.0005) {
|
|
326
|
+
matrix = app.transformationMatrices.add({ counterclockwiseRotationAngle: delta });
|
|
327
|
+
item.transform(CoordinateSpaces.PASTEBOARD_COORDINATES, AnchorPoint.CENTER_ANCHOR, matrix);
|
|
328
|
+
}
|
|
329
|
+
} catch (e) {
|
|
330
|
+
try {
|
|
331
|
+
item.rotationAngle = wanted;
|
|
332
|
+
ctx.warn('transform() failed (' + String(e.message ? e.message : e) + '); rotationAngle was set directly, which may rotate around the reference point instead of the centre.');
|
|
333
|
+
} catch (e2) {
|
|
334
|
+
IDC.fail('script_error', 'InDesign could not rotate object ' + args.frame_id + ': ' + String(e2.message ? e2.message : e2), { frame_id: args.frame_id });
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
after = idcRotationOf(item);
|
|
339
|
+
if (after !== null && Math.abs(((after - wanted) % 360 + 360) % 360) > 0.01 && Math.abs(((after - wanted) % 360 + 360) % 360 - 360) > 0.01) {
|
|
340
|
+
ctx.warn('The rotation reads ' + after + ' degrees after setting ' + wanted + '.');
|
|
341
|
+
}
|
|
342
|
+
var landing = IDC.landing(item);
|
|
343
|
+
ctx.changes = { modified_frame_ids: [Number(item.id)] };
|
|
344
|
+
return {
|
|
345
|
+
frame_id: Number(item.id),
|
|
346
|
+
angle_deg: after,
|
|
347
|
+
previous_angle_deg: current,
|
|
348
|
+
bounds_mm: idcItemBounds(doc, item),
|
|
349
|
+
landed_on_page_id: landing.page_id,
|
|
350
|
+
landed_on_page_name: landing.page_name
|
|
351
|
+
};
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
/* ------------------------------------------------------- set_frame_stacking */
|
|
355
|
+
|
|
356
|
+
IDC.register('set_frame_stacking', { needs_document: true, read_only: false, ruler: 'none' },
|
|
357
|
+
function (ctx) {
|
|
358
|
+
var args = ctx.args;
|
|
359
|
+
var doc = ctx.doc;
|
|
360
|
+
var found = idcFrameArg(doc, args, 'frame_id');
|
|
361
|
+
var item = found.item;
|
|
362
|
+
var action = args.action;
|
|
363
|
+
var actions = { bring_to_front: 1, send_to_back: 1, bring_forward: 1, send_backward: 1 };
|
|
364
|
+
|
|
365
|
+
if (typeof action !== 'string' || !IDC.hasOwn(actions, action)) {
|
|
366
|
+
IDC.fail('invalid_argument', 'action must be bring_to_front, send_to_back, bring_forward or send_backward.', { action: action });
|
|
367
|
+
}
|
|
368
|
+
try {
|
|
369
|
+
if (action === 'bring_to_front') { item.bringToFront(); }
|
|
370
|
+
else if (action === 'send_to_back') { item.sendToBack(); }
|
|
371
|
+
else if (action === 'bring_forward') { item.bringForward(); }
|
|
372
|
+
else { item.sendBackward(); }
|
|
373
|
+
} catch (e) {
|
|
374
|
+
IDC.fail('script_error', 'InDesign could not change the stacking of object ' + args.frame_id + ': ' + String(e.message ? e.message : e),
|
|
375
|
+
{ frame_id: args.frame_id, action: action });
|
|
376
|
+
}
|
|
377
|
+
var layerName = null;
|
|
378
|
+
try { layerName = String(item.itemLayer.name); } catch (e2) { layerName = null; }
|
|
379
|
+
/*
|
|
380
|
+
* Die Stapelfolge ist ueber die Sammlungen nicht ablesbar: pageItems
|
|
381
|
+
* liefert nach Objektart gruppiert, index zaehlt je Art. Geprueft am
|
|
382
|
+
* 04.09.2026 ueber den PDF-Export (rot vor blau nach bring_to_front).
|
|
383
|
+
*/
|
|
384
|
+
ctx.changes = { modified_frame_ids: [Number(item.id)] };
|
|
385
|
+
return { frame_id: Number(item.id), action: action, layer: layerName };
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
/* ----------------------------------------------------- set_frame_appearance */
|
|
389
|
+
|
|
390
|
+
/* "#RRGGBB" | "none" pruefen; Farbfeldnamen wie "Paper" werden abgewiesen. */
|
|
391
|
+
function idcColourArg(value, field) {
|
|
392
|
+
var text;
|
|
393
|
+
if (value === undefined || value === null) { return null; }
|
|
394
|
+
text = String(value);
|
|
395
|
+
if (text.toLowerCase() === 'none') { return 'none'; }
|
|
396
|
+
if (!/^#?[0-9a-fA-F]{6}$/.test(text)) {
|
|
397
|
+
IDC.fail('invalid_argument', field + ' must be a hex colour like "#1A2B3C" or "none"; swatch names such as "' + text + '" are not accepted.', { value: text });
|
|
398
|
+
}
|
|
399
|
+
return text;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
IDC.register('set_frame_appearance', { needs_document: true, read_only: false, ruler: 'none' },
|
|
403
|
+
function (ctx) {
|
|
404
|
+
var args = ctx.args;
|
|
405
|
+
var doc = ctx.doc;
|
|
406
|
+
var found = idcFrameArg(doc, args, 'frame_id');
|
|
407
|
+
var item = found.item;
|
|
408
|
+
var fill = idcColourArg(args.fill, 'fill');
|
|
409
|
+
var stroke = idcColourArg(args.stroke, 'stroke');
|
|
410
|
+
var weight = null;
|
|
411
|
+
var swatchIds = [];
|
|
412
|
+
var none, fillSwatch = null, strokeSwatch = null, look;
|
|
413
|
+
var fillName = args.fill_swatch_name, strokeName = args.stroke_swatch_name;
|
|
414
|
+
|
|
415
|
+
idcBothGiven(args, 'fill', 'fill_swatch_name');
|
|
416
|
+
idcBothGiven(args, 'stroke', 'stroke_swatch_name');
|
|
417
|
+
if (fillName !== undefined && fillName !== null) { fillSwatch = idcSwatchArg(doc, fillName, 'fill_swatch_name'); fill = 'swatch'; }
|
|
418
|
+
if (strokeName !== undefined && strokeName !== null) { strokeSwatch = idcSwatchArg(doc, strokeName, 'stroke_swatch_name'); stroke = 'swatch'; }
|
|
419
|
+
|
|
420
|
+
if (args.stroke_weight_pt !== undefined && args.stroke_weight_pt !== null) {
|
|
421
|
+
if (typeof args.stroke_weight_pt !== 'number' || !isFinite(args.stroke_weight_pt) || args.stroke_weight_pt < 0) {
|
|
422
|
+
IDC.fail('invalid_argument', 'stroke_weight_pt must be a number of 0 or more (points).', { stroke_weight_pt: args.stroke_weight_pt });
|
|
423
|
+
}
|
|
424
|
+
weight = args.stroke_weight_pt;
|
|
425
|
+
}
|
|
426
|
+
/* A-8.5: Farbton und Verlaufswinkel. */
|
|
427
|
+
var fillTint = idcTintArg(args.fill_tint_percent, 'fill_tint_percent');
|
|
428
|
+
var strokeTint = idcTintArg(args.stroke_tint_percent, 'stroke_tint_percent');
|
|
429
|
+
var fillAngle = idcAngleArg(args.gradient_fill_angle_deg, 'gradient_fill_angle_deg');
|
|
430
|
+
var strokeAngle = idcAngleArg(args.gradient_stroke_angle_deg, 'gradient_stroke_angle_deg');
|
|
431
|
+
if (fill === null && stroke === null && weight === null && fillTint === null && strokeTint === null && fillAngle === null && strokeAngle === null) {
|
|
432
|
+
IDC.fail('invalid_argument', 'Pass at least one of fill, fill_swatch_name, stroke, stroke_swatch_name, stroke_weight_pt, fill_tint_percent, stroke_tint_percent, gradient_fill_angle_deg or gradient_stroke_angle_deg.', null);
|
|
433
|
+
}
|
|
434
|
+
if (IDC.itemType(item) === 'group') {
|
|
435
|
+
IDC.fail('invalid_state', 'Object ' + args.frame_id + ' is a group; set fill and stroke on its members.', { frame_id: args.frame_id, type: 'group' });
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
none = idcNoneSwatch(doc);
|
|
439
|
+
if (fill !== null && fill !== 'none' && fill !== 'swatch') { fillSwatch = idcSwatchForHex(doc, fill, 'fill', swatchIds); }
|
|
440
|
+
if (stroke !== null && stroke !== 'none' && stroke !== 'swatch') { strokeSwatch = idcSwatchForHex(doc, stroke, 'stroke', swatchIds); }
|
|
441
|
+
|
|
442
|
+
/* stroke "none" setzt zusaetzlich die Staerke 0 – nur die Staerke entfernt die Kontur sicher im Export. */
|
|
443
|
+
if (stroke === 'none') {
|
|
444
|
+
if (weight !== null && weight > 0) {
|
|
445
|
+
ctx.warn('stroke "none" forces stroke_weight_pt 0; the given ' + weight + ' pt was not applied.');
|
|
446
|
+
}
|
|
447
|
+
weight = 0;
|
|
448
|
+
}
|
|
449
|
+
if (strokeSwatch !== null && weight === null) {
|
|
450
|
+
try {
|
|
451
|
+
var currentWeight = IDC.inPoints(function () { return Number(item.strokeWeight); });
|
|
452
|
+
if (!(currentWeight > 0)) {
|
|
453
|
+
weight = 1;
|
|
454
|
+
ctx.warn('The object had no stroke weight; stroke_weight_pt 1 was applied together with the stroke colour.');
|
|
455
|
+
}
|
|
456
|
+
} catch (ew) { /* Staerke bleibt */ }
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
/* Reihenfolge: Staerke, Konturfarbe, Flaeche (Live-Fund Sitzung 3). */
|
|
460
|
+
try {
|
|
461
|
+
if (weight !== null) { idcSetStrokeWeightPt(item, weight); }
|
|
462
|
+
if (stroke === 'none' && none !== null) { item.strokeColor = none; }
|
|
463
|
+
else if (strokeSwatch !== null) { item.strokeColor = strokeSwatch; }
|
|
464
|
+
if (fill === 'none' && none !== null) { item.fillColor = none; }
|
|
465
|
+
else if (fillSwatch !== null) { item.fillColor = fillSwatch; }
|
|
466
|
+
idcApplyTintsAndAngles(ctx, item, fillTint, strokeTint, fillAngle, strokeAngle);
|
|
467
|
+
} catch (e) {
|
|
468
|
+
if (e && e.isIdcError) { throw e; }
|
|
469
|
+
IDC.fail('script_error', 'InDesign could not change the appearance of object ' + args.frame_id + ': ' + String(e.message ? e.message : e),
|
|
470
|
+
{ frame_id: args.frame_id });
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
look = idcAppearanceFull(item);
|
|
474
|
+
if (weight === 0 && look.stroke_weight_pt !== null && look.stroke_weight_pt > 0) {
|
|
475
|
+
ctx.warn('The stroke weight still reads ' + look.stroke_weight_pt + ' pt; check the export.');
|
|
476
|
+
}
|
|
477
|
+
ctx.changes = { modified_frame_ids: [Number(item.id)], created_swatch_ids: swatchIds };
|
|
478
|
+
return {
|
|
479
|
+
frame_id: Number(item.id),
|
|
480
|
+
applied_fill: look.fill_color,
|
|
481
|
+
applied_stroke: look.stroke_color,
|
|
482
|
+
applied_stroke_weight_pt: look.stroke_weight_pt,
|
|
483
|
+
swatch_ids: swatchIds,
|
|
484
|
+
fill_kind: look.fill_kind,
|
|
485
|
+
stroke_kind: look.stroke_kind,
|
|
486
|
+
fill_tint_percent: look.fill_tint_percent,
|
|
487
|
+
stroke_tint_percent: look.stroke_tint_percent,
|
|
488
|
+
gradient_fill_angle_deg: look.gradient_fill_angle_deg,
|
|
489
|
+
gradient_stroke_angle_deg: look.gradient_stroke_angle_deg,
|
|
490
|
+
gradient_fill_start_mm: look.gradient_fill_start_mm,
|
|
491
|
+
gradient_fill_length_mm: look.gradient_fill_length_mm
|
|
492
|
+
};
|
|
493
|
+
});
|
|
494
|
+
|
|
495
|
+
/* -------------------------------------------------------- set_frame_columns */
|
|
496
|
+
|
|
497
|
+
IDC.register('set_frame_columns', { needs_document: true, read_only: false, ruler: 'none' },
|
|
498
|
+
function (ctx) {
|
|
499
|
+
var args = ctx.args;
|
|
500
|
+
var doc = ctx.doc;
|
|
501
|
+
var found = idcTextFrameArg(doc, args, 'frame_id');
|
|
502
|
+
var frame = found.item;
|
|
503
|
+
var count = args.count;
|
|
504
|
+
/* Ohne gutter_mm bleibt der Steg des Rahmens (G-2); InDesigns eigene Vorgabe fuer neue Rahmen ist 1 Pica. */
|
|
505
|
+
var gutter = args.gutter_mm === undefined || args.gutter_mm === null ? null : args.gutter_mm;
|
|
506
|
+
var prefs;
|
|
507
|
+
|
|
508
|
+
if (args.column_count !== undefined) {
|
|
509
|
+
IDC.fail('invalid_argument', 'The parameter is called count, not column_count.', { column_count: args.column_count });
|
|
510
|
+
}
|
|
511
|
+
if (typeof count !== 'number' || count < 1 || Math.floor(count) !== count) {
|
|
512
|
+
IDC.fail('invalid_argument', 'count must be a whole number of 1 or more.', { count: count });
|
|
513
|
+
}
|
|
514
|
+
if (gutter !== null && (typeof gutter !== 'number' || !isFinite(gutter) || gutter < 0)) {
|
|
515
|
+
IDC.fail('invalid_argument', 'gutter_mm must be a number of 0 or more.', { gutter_mm: gutter });
|
|
516
|
+
}
|
|
517
|
+
try {
|
|
518
|
+
prefs = frame.textFramePreferences;
|
|
519
|
+
/* Feste Spaltenzahl: beide Breitenschalter aus (Adobe-DOM: useFixedColumnWidth, useFlexibleColumnWidth). */
|
|
520
|
+
try { prefs.useFlexibleColumnWidth = false; } catch (e0a) { /* kennt die Laufzeit nicht */ }
|
|
521
|
+
try { prefs.useFixedColumnWidth = false; } catch (e0b) { /* kennt die Laufzeit nicht */ }
|
|
522
|
+
prefs.textColumnCount = count;
|
|
523
|
+
if (gutter !== null) { prefs.textColumnGutter = gutter; }
|
|
524
|
+
} catch (e) {
|
|
525
|
+
IDC.fail('script_error', 'InDesign could not set the columns of text frame ' + args.frame_id + ': ' + String(e.message ? e.message : e),
|
|
526
|
+
{ frame_id: args.frame_id });
|
|
527
|
+
}
|
|
528
|
+
var countBack = null, gutterBack = null;
|
|
529
|
+
try { countBack = Number(prefs.textColumnCount); } catch (e1) { countBack = null; }
|
|
530
|
+
try { gutterBack = IDC.round(Number(prefs.textColumnGutter)); } catch (e2) { gutterBack = null; }
|
|
531
|
+
ctx.changes = { modified_frame_ids: [Number(frame.id)] };
|
|
532
|
+
return { frame_id: Number(frame.id), count: countBack, gutter_mm: gutterBack };
|
|
533
|
+
});
|
|
534
|
+
|
|
535
|
+
/* ---------------------------------------------------------- set_frame_inset */
|
|
536
|
+
|
|
537
|
+
function idcEdgeObjectArg(spec, field, allowMissing) {
|
|
538
|
+
var keys = ['top', 'left', 'bottom', 'right'];
|
|
539
|
+
var out = {};
|
|
540
|
+
var i, v;
|
|
541
|
+
if (!spec || typeof spec !== 'object') {
|
|
542
|
+
IDC.fail('invalid_argument', field + ' must be an object { top, left, bottom, right }.', null);
|
|
543
|
+
}
|
|
544
|
+
for (i = 0; i < keys.length; i++) {
|
|
545
|
+
v = spec[keys[i]];
|
|
546
|
+
if (v === undefined || v === null) {
|
|
547
|
+
if (allowMissing) { out[keys[i]] = null; continue; }
|
|
548
|
+
IDC.fail('invalid_argument', field + '.' + keys[i] + ' is required.', spec);
|
|
549
|
+
}
|
|
550
|
+
if (typeof v !== 'number' || !isFinite(v) || v < 0) {
|
|
551
|
+
IDC.fail('invalid_argument', field + '.' + keys[i] + ' must be a number of 0 or more.', spec);
|
|
552
|
+
}
|
|
553
|
+
out[keys[i]] = v;
|
|
554
|
+
}
|
|
555
|
+
return out;
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
/* insetSpacing / textWrapOffset: [oben, links, unten, rechts] – ein Wert, wenn InDesign nur einen fuehrt. */
|
|
559
|
+
function idcEdgesFromArray(value) {
|
|
560
|
+
if (IDC.isArray(value)) {
|
|
561
|
+
if (value.length >= 4) {
|
|
562
|
+
return { top: IDC.round(value[0]), left: IDC.round(value[1]), bottom: IDC.round(value[2]), right: IDC.round(value[3]) };
|
|
563
|
+
}
|
|
564
|
+
if (value.length > 0) {
|
|
565
|
+
return { top: IDC.round(value[0]), left: IDC.round(value[0]), bottom: IDC.round(value[0]), right: IDC.round(value[0]) };
|
|
566
|
+
}
|
|
567
|
+
return null;
|
|
568
|
+
}
|
|
569
|
+
if (typeof value === 'number') {
|
|
570
|
+
return { top: IDC.round(value), left: IDC.round(value), bottom: IDC.round(value), right: IDC.round(value) };
|
|
571
|
+
}
|
|
572
|
+
return null;
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
IDC.register('set_frame_inset', { needs_document: true, read_only: false, ruler: 'none' },
|
|
576
|
+
function (ctx) {
|
|
577
|
+
var args = ctx.args;
|
|
578
|
+
var doc = ctx.doc;
|
|
579
|
+
var found = idcTextFrameArg(doc, args, 'frame_id');
|
|
580
|
+
var frame = found.item;
|
|
581
|
+
var hasInset = args.inset_mm !== undefined && args.inset_mm !== null;
|
|
582
|
+
var vj = args.vertical_justification;
|
|
583
|
+
var hasVj = vj !== undefined && vj !== null;
|
|
584
|
+
var inset = null, vjEnum = null, back = null, vjBack = null;
|
|
585
|
+
|
|
586
|
+
/* Sitzung 24 (E-79): vertikale Ausrichtung als optionaler Parameter; dann darf inset_mm fehlen. */
|
|
587
|
+
if (!hasInset && !hasVj) {
|
|
588
|
+
IDC.fail('invalid_argument', 'Pass inset_mm, vertical_justification or both.', null);
|
|
589
|
+
}
|
|
590
|
+
if (hasInset) { inset = idcEdgeObjectArg(args.inset_mm, 'inset_mm', false); }
|
|
591
|
+
if (hasVj) {
|
|
592
|
+
vjEnum = idcVerticalJustificationFor(vj);
|
|
593
|
+
if (vjEnum === null) {
|
|
594
|
+
IDC.fail('invalid_argument', 'vertical_justification must be top, center, bottom or justify.', { vertical_justification: vj });
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
try {
|
|
599
|
+
if (inset !== null) { frame.textFramePreferences.insetSpacing = [inset.top, inset.left, inset.bottom, inset.right]; }
|
|
600
|
+
} catch (e) {
|
|
601
|
+
IDC.fail('script_error', 'InDesign could not set the inset (Innenabstand) of text frame ' + args.frame_id + ': ' + String(e.message ? e.message : e),
|
|
602
|
+
{ frame_id: args.frame_id });
|
|
603
|
+
}
|
|
604
|
+
try {
|
|
605
|
+
if (vjEnum !== null) { frame.textFramePreferences.verticalJustification = vjEnum; }
|
|
606
|
+
} catch (e1) {
|
|
607
|
+
IDC.fail('script_error', 'InDesign could not set the vertical justification (vertikale Ausrichtung) of text frame ' + args.frame_id + ': ' + String(e1.message ? e1.message : e1),
|
|
608
|
+
{ frame_id: args.frame_id });
|
|
609
|
+
}
|
|
610
|
+
try { back = idcEdgesFromArray(frame.textFramePreferences.insetSpacing); } catch (e2) { back = null; }
|
|
611
|
+
try { vjBack = idcVerticalJustificationName(frame.textFramePreferences.verticalJustification); } catch (e3) { vjBack = null; }
|
|
612
|
+
ctx.changes = { modified_frame_ids: [Number(frame.id)] };
|
|
613
|
+
return { frame_id: Number(frame.id), inset_mm: back, vertical_justification: vjBack };
|
|
614
|
+
});
|
|
615
|
+
|
|
616
|
+
/* ------------------------------------------------------------ set_text_wrap */
|
|
617
|
+
|
|
618
|
+
function idcTextWrapModeFor(name) {
|
|
619
|
+
if (name === 'none') { return TextWrapModes.NONE; }
|
|
620
|
+
if (name === 'bounding_box') { return TextWrapModes.BOUNDING_BOX_TEXT_WRAP; }
|
|
621
|
+
if (name === 'object_shape') { return TextWrapModes.CONTOUR; }
|
|
622
|
+
if (name === 'jump_object') { return TextWrapModes.JUMP_OBJECT_TEXT_WRAP; }
|
|
623
|
+
if (name === 'next_column') { return TextWrapModes.NEXT_COLUMN_TEXT_WRAP; }
|
|
624
|
+
return null;
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
IDC.register('set_text_wrap', { needs_document: true, read_only: false, ruler: 'none' },
|
|
628
|
+
function (ctx) {
|
|
629
|
+
var args = ctx.args;
|
|
630
|
+
var doc = ctx.doc;
|
|
631
|
+
var found = idcFrameArg(doc, args, 'frame_id');
|
|
632
|
+
var item = found.item;
|
|
633
|
+
var mode = args.mode;
|
|
634
|
+
var enumValue, offset = null, unit = 'mm', prefs, modeBack, offsetBack = null;
|
|
635
|
+
|
|
636
|
+
if (typeof TextWrapModes === 'undefined') {
|
|
637
|
+
IDC.fail('invalid_state', 'This InDesign runtime has no TextWrapModes.', null);
|
|
638
|
+
}
|
|
639
|
+
enumValue = typeof mode === 'string' ? idcTextWrapModeFor(mode) : null;
|
|
640
|
+
if (enumValue === null) {
|
|
641
|
+
IDC.fail('invalid_argument', 'mode must be none, bounding_box, object_shape, jump_object or next_column.', { mode: mode });
|
|
642
|
+
}
|
|
643
|
+
if (args.offset_mm !== undefined && args.offset_mm !== null && args.offset_pt !== undefined && args.offset_pt !== null) {
|
|
644
|
+
IDC.fail('invalid_argument', 'Pass either offset_mm or offset_pt, not both.', null);
|
|
645
|
+
}
|
|
646
|
+
if (args.offset_mm !== undefined && args.offset_mm !== null) { offset = idcEdgeObjectArg(args.offset_mm, 'offset_mm', false); unit = 'mm'; }
|
|
647
|
+
else if (args.offset_pt !== undefined && args.offset_pt !== null) { offset = idcEdgeObjectArg(args.offset_pt, 'offset_pt', false); unit = 'pt'; }
|
|
648
|
+
|
|
649
|
+
try { prefs = item.textWrapPreferences; } catch (e0) { prefs = null; }
|
|
650
|
+
if (prefs === null || prefs === undefined) {
|
|
651
|
+
IDC.fail('invalid_state', 'Object ' + args.frame_id + ' has no text wrap preferences (Textumfluss).', { frame_id: args.frame_id });
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
/* Vermerk E-63: der Umbruch muss nach jeder Aenderung am Textumfluss erzwungen werden. */
|
|
655
|
+
var recBeforeWrap = idcOversetBefore(doc);
|
|
656
|
+
|
|
657
|
+
try {
|
|
658
|
+
prefs.textWrapMode = enumValue;
|
|
659
|
+
} catch (e) {
|
|
660
|
+
IDC.fail('script_error', 'InDesign could not set the text wrap mode of object ' + args.frame_id + ': ' + String(e.message ? e.message : e),
|
|
661
|
+
{ frame_id: args.frame_id, mode: mode });
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
if (offset !== null) {
|
|
665
|
+
if (mode === 'none') {
|
|
666
|
+
ctx.warn('mode "none" ignores the offset.');
|
|
667
|
+
} else {
|
|
668
|
+
/* Als ganzes Array zuweisen – die alte Fassung scheiterte an der Zuweisung einzelner Elemente. */
|
|
669
|
+
var values = [offset.top, offset.left, offset.bottom, offset.right];
|
|
670
|
+
var assign = function () {
|
|
671
|
+
if (mode === 'object_shape') {
|
|
672
|
+
/* Konturumfluss fuehrt nur einen Abstand. */
|
|
673
|
+
try { prefs.textWrapOffset = values[0]; } catch (e0) { prefs.textWrapOffset = values; }
|
|
674
|
+
return;
|
|
675
|
+
}
|
|
676
|
+
try {
|
|
677
|
+
prefs.textWrapOffset = values;
|
|
678
|
+
} catch (e1) {
|
|
679
|
+
prefs.textWrapOffset = values[0];
|
|
680
|
+
}
|
|
681
|
+
};
|
|
682
|
+
try {
|
|
683
|
+
if (unit === 'pt') { IDC.inPoints(assign); } else { assign(); }
|
|
684
|
+
} catch (e2) {
|
|
685
|
+
IDC.fail('script_error', 'The text wrap mode was set, but InDesign could not set the offset of object ' + args.frame_id + ': ' +
|
|
686
|
+
String(e2.message ? e2.message : e2), { frame_id: args.frame_id, offset: offset, unit: unit });
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
modeBack = idcTextWrapName(item);
|
|
692
|
+
if (modeBack === 'contour') { modeBack = 'object_shape'; }
|
|
693
|
+
var rawOffset = null;
|
|
694
|
+
try { rawOffset = prefs.textWrapOffset; offsetBack = idcEdgesFromArray(rawOffset); } catch (e3) { offsetBack = null; }
|
|
695
|
+
var recWrap = idcRecomposeAfter(ctx, doc, recBeforeWrap);
|
|
696
|
+
var out = { frame_id: Number(item.id), mode: modeBack, offset_mm: offsetBack,
|
|
697
|
+
recomposed: recWrap.recomposed, overset_stories_before: recWrap.overset_stories_before,
|
|
698
|
+
overset_stories_after: recWrap.overset_stories_after, overset_changed: recWrap.overset_changed };
|
|
699
|
+
if (offsetBack === null) {
|
|
700
|
+
try { out.offset_raw = String(rawOffset) + ' (' + typeof rawOffset + ')'; } catch (e5) { out.offset_raw = null; }
|
|
701
|
+
if (mode === 'object_shape' && offset !== null) {
|
|
702
|
+
/* Live-Fund 04.09.2026: bei Konturumfluss liest InDesign textWrapOffset als NOTHING zurueck. */
|
|
703
|
+
ctx.warn('InDesign does not report the offset for object_shape wrap (reads NOTHING); the value ' + offset.top + ' was assigned – check visually.');
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
ctx.changes = { modified_frame_ids: [Number(item.id)] };
|
|
707
|
+
return out;
|
|
708
|
+
});
|
|
709
|
+
|
|
710
|
+
/* ------------------------------------------------------- thread_text_frames */
|
|
711
|
+
|
|
712
|
+
function idcStoryLength(frame) {
|
|
713
|
+
try { return Number(frame.parentStory.characters.length); } catch (e) { return null; }
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
function idcStoryId(frame) {
|
|
717
|
+
try { return Number(frame.parentStory.id); } catch (e) { return null; }
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
function idcSameObject(a, b) {
|
|
721
|
+
try { return Number(a.id) === Number(b.id); } catch (e) { return false; }
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
IDC.register('thread_text_frames', { needs_document: true, read_only: false, ruler: 'none' },
|
|
725
|
+
function (ctx) {
|
|
726
|
+
var args = ctx.args;
|
|
727
|
+
var doc = ctx.doc;
|
|
728
|
+
var source = idcTextFrameArg(doc, args, 'source_frame_id').item;
|
|
729
|
+
var target = idcTextFrameArg(doc, args, 'target_frame_id').item;
|
|
730
|
+
var already = false;
|
|
731
|
+
var next = null, prev = null, targetChars = 0;
|
|
732
|
+
|
|
733
|
+
if (idcSameObject(source, target)) {
|
|
734
|
+
IDC.fail('invalid_argument', 'source_frame_id and target_frame_id must differ.', { frame_id: args.source_frame_id });
|
|
735
|
+
}
|
|
736
|
+
try { next = source.nextTextFrame; } catch (e0) { next = null; }
|
|
737
|
+
if (next !== null && next !== undefined) {
|
|
738
|
+
try { already = next.isValid === true && idcSameObject(next, target); } catch (e1) { already = false; }
|
|
739
|
+
if (!already) {
|
|
740
|
+
try {
|
|
741
|
+
if (next.isValid === true) {
|
|
742
|
+
IDC.fail('invalid_state', 'Text frame ' + args.source_frame_id + ' is already threaded to frame ' + Number(next.id) + '.',
|
|
743
|
+
{ source_frame_id: args.source_frame_id, next_frame_id: Number(next.id) });
|
|
744
|
+
}
|
|
745
|
+
} catch (e2) { if (e2 && e2.isIdcError) { throw e2; } }
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
if (!already) {
|
|
749
|
+
try { prev = target.previousTextFrame; } catch (e3) { prev = null; }
|
|
750
|
+
try {
|
|
751
|
+
if (prev !== null && prev !== undefined && prev.isValid === true) {
|
|
752
|
+
IDC.fail('invalid_state', 'Text frame ' + args.target_frame_id + ' already continues frame ' + Number(prev.id) + '.',
|
|
753
|
+
{ target_frame_id: args.target_frame_id, previous_frame_id: Number(prev.id) });
|
|
754
|
+
}
|
|
755
|
+
} catch (e4) { if (e4 && e4.isIdcError) { throw e4; } }
|
|
756
|
+
if (idcStoryId(source) !== null && idcStoryId(source) === idcStoryId(target)) {
|
|
757
|
+
IDC.fail('invalid_state', 'Both frames already belong to the same story.', { story_id: idcStoryId(source) });
|
|
758
|
+
}
|
|
759
|
+
try { targetChars = Number(target.parentStory.characters.length); } catch (e5) { targetChars = 0; }
|
|
760
|
+
try {
|
|
761
|
+
source.nextTextFrame = target;
|
|
762
|
+
} catch (e) {
|
|
763
|
+
IDC.fail('script_error', 'InDesign could not thread frame ' + args.source_frame_id + ' to frame ' + args.target_frame_id + ': ' +
|
|
764
|
+
String(e.message ? e.message : e), { source_frame_id: args.source_frame_id, target_frame_id: args.target_frame_id });
|
|
765
|
+
}
|
|
766
|
+
if (targetChars > 0) {
|
|
767
|
+
ctx.warn('The target frame held ' + targetChars + ' characters; they were merged into the story after the source text.');
|
|
768
|
+
}
|
|
769
|
+
ctx.changes = { modified_frame_ids: [Number(source.id), Number(target.id)] };
|
|
770
|
+
}
|
|
771
|
+
var overflows = false;
|
|
772
|
+
try { overflows = target.overflows === true; } catch (e6) { overflows = false; }
|
|
773
|
+
return {
|
|
774
|
+
source_frame_id: Number(source.id),
|
|
775
|
+
target_frame_id: Number(target.id),
|
|
776
|
+
story_id: idcStoryId(source),
|
|
777
|
+
story_character_count: idcStoryLength(source),
|
|
778
|
+
already_threaded: already,
|
|
779
|
+
target_overflows: overflows
|
|
780
|
+
};
|
|
781
|
+
});
|