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.
Files changed (79) hide show
  1. package/CHANGELOG.md +171 -0
  2. package/LICENSE +26 -0
  3. package/README.de.md +318 -0
  4. package/README.md +304 -4
  5. package/THIRD-PARTY-NOTICES.md +2878 -0
  6. package/dist/src/mcp/config.js +125 -0
  7. package/dist/src/mcp/dispatch.js +123 -0
  8. package/dist/src/mcp/license/free-tools.js +16 -0
  9. package/dist/src/mcp/license/gate.js +209 -0
  10. package/dist/src/mcp/license/index.js +96 -0
  11. package/dist/src/mcp/license/instance-name.js +56 -0
  12. package/dist/src/mcp/license/key-source.js +58 -0
  13. package/dist/src/mcp/license/lemonsqueezy-verifier.js +207 -0
  14. package/dist/src/mcp/license/placeholder-verifier.js +10 -0
  15. package/dist/src/mcp/license/polar-ids.js +63 -0
  16. package/dist/src/mcp/license/polar-verifier.js +265 -0
  17. package/dist/src/mcp/license/product-ids.js +72 -0
  18. package/dist/src/mcp/license/state-store.js +91 -0
  19. package/dist/src/mcp/license/types.js +11 -0
  20. package/dist/src/mcp/logging.js +270 -0
  21. package/dist/src/mcp/product-info.js +48 -0
  22. package/dist/src/mcp/server.js +250 -0
  23. package/dist/src/mcp/setup.js +608 -0
  24. package/dist/src/mcp/start.cjs +95 -0
  25. package/dist/src/mcp/tool-definition.js +2 -0
  26. package/dist/src/mcp/tools.js +2004 -0
  27. package/dist/src/mcp/typography-rules.js +70 -0
  28. package/dist/src/transport/com.js +250 -0
  29. package/dist/src/transport/osascript.js +171 -0
  30. package/dist/src/transport/queue.js +19 -0
  31. package/dist/src/transport/script-bundle.js +92 -0
  32. package/dist/src/transport/transport.js +30 -0
  33. package/indesign/commands/10-app.js +6 -0
  34. package/indesign/commands/20-documents.js +513 -0
  35. package/indesign/commands/22-document-setup.js +118 -0
  36. package/indesign/commands/23-save-package.js +255 -0
  37. package/indesign/commands/25-export.js +379 -0
  38. package/indesign/commands/26-export-image.js +197 -0
  39. package/indesign/commands/27-textdefaults.js +151 -0
  40. package/indesign/commands/28-selection.js +174 -0
  41. package/indesign/commands/30-pages.js +1032 -0
  42. package/indesign/commands/31-view.js +210 -0
  43. package/indesign/commands/32-sections.js +203 -0
  44. package/indesign/commands/35-parents.js +428 -0
  45. package/indesign/commands/37-layout.js +760 -0
  46. package/indesign/commands/40-frames.js +836 -0
  47. package/indesign/commands/41-shapes.js +505 -0
  48. package/indesign/commands/42-groups.js +117 -0
  49. package/indesign/commands/43-layers.js +291 -0
  50. package/indesign/commands/44-effects.js +274 -0
  51. package/indesign/commands/45-frame-options.js +247 -0
  52. package/indesign/commands/47-anchored.js +287 -0
  53. package/indesign/commands/50-modify.js +781 -0
  54. package/indesign/commands/52-align.js +139 -0
  55. package/indesign/commands/55-fit.js +106 -0
  56. package/indesign/commands/60-images.js +771 -0
  57. package/indesign/commands/62-embed.js +120 -0
  58. package/indesign/commands/69-placeholders.js +127 -0
  59. package/indesign/commands/70-text.js +567 -0
  60. package/indesign/commands/71-outlines.js +92 -0
  61. package/indesign/commands/72-place-text.js +366 -0
  62. package/indesign/commands/74-stories.js +116 -0
  63. package/indesign/commands/75-tables.js +676 -0
  64. package/indesign/commands/76-text-variables.js +260 -0
  65. package/indesign/commands/77-story-options.js +86 -0
  66. package/indesign/commands/78-frame-lines.js +304 -0
  67. package/indesign/commands/79-check-typography.js +303 -0
  68. package/indesign/commands/80-styles.js +1620 -0
  69. package/indesign/commands/81-composition.js +355 -0
  70. package/indesign/commands/82-object-styles.js +263 -0
  71. package/indesign/commands/83-indents-tabs.js +237 -0
  72. package/indesign/commands/84-import-styles.js +142 -0
  73. package/indesign/commands/85-swatches.js +112 -0
  74. package/indesign/commands/86-gradients.js +185 -0
  75. package/indesign/commands/87-replace-swatch.js +180 -0
  76. package/indesign/commands/88-replace-font.js +217 -0
  77. package/indesign/interpreter.js +758 -0
  78. package/package.json +55 -6
  79. package/rules/typography-rules.json +31 -0
@@ -0,0 +1,676 @@
1
+ /* Wunschliste J Nr. 1 (Sitzung 8) – Tabellen: create_table, set_table_cells, set_table_style, get_table. */
2
+
3
+ var IDC_TABLE_CHAR = '';
4
+
5
+ function idcTableStyleByName(doc, name) {
6
+ var style = null, all, i;
7
+ try {
8
+ style = doc.tableStyles.itemByName(name);
9
+ if (style && style.isValid === true) { return style; }
10
+ } catch (e0) { /* weiter */ }
11
+ try {
12
+ all = doc.allTableStyles;
13
+ for (i = 0; i < all.length; i++) { if (String(all[i].name) === String(name)) { return all[i]; } }
14
+ } catch (e1) { /* weiter */ }
15
+ return null;
16
+ }
17
+
18
+ function idcCellStyleByName(doc, name) {
19
+ var style = null, all, i;
20
+ try {
21
+ style = doc.cellStyles.itemByName(name);
22
+ if (style && style.isValid === true) { return style; }
23
+ } catch (e0) { /* weiter */ }
24
+ try {
25
+ all = doc.allCellStyles;
26
+ for (i = 0; i < all.length; i++) { if (String(all[i].name) === String(name)) { return all[i]; } }
27
+ } catch (e1) { /* weiter */ }
28
+ return null;
29
+ }
30
+
31
+ function idcStyleNames(list) {
32
+ var out = [], i;
33
+ try {
34
+ for (i = 0; i < list.length; i++) { out.push(String(list[i].name)); }
35
+ } catch (e) { /* leer */ }
36
+ return out;
37
+ }
38
+
39
+ function idcTableStyleArg(doc, name, field) {
40
+ var style;
41
+ if (typeof name !== 'string' || name === '') {
42
+ IDC.fail('invalid_argument', field + ' must be a non-empty string.', { field: field, value: name });
43
+ }
44
+ style = idcTableStyleByName(doc, name);
45
+ if (style === null) {
46
+ IDC.fail('not_found', 'No table style named "' + name + '" in this document.',
47
+ { field: field, table_style: name, available: idcStyleNames(doc.allTableStyles) });
48
+ }
49
+ return style;
50
+ }
51
+
52
+ function idcCellStyleArg(doc, name, field) {
53
+ var style;
54
+ if (typeof name !== 'string' || name === '') {
55
+ IDC.fail('invalid_argument', field + ' must be a non-empty string.', { field: field, value: name });
56
+ }
57
+ style = idcCellStyleByName(doc, name);
58
+ if (style === null) {
59
+ IDC.fail('not_found', 'No cell style named "' + name + '" in this document.',
60
+ { field: field, cell_style: name, available: idcStyleNames(doc.allCellStyles) });
61
+ }
62
+ return style;
63
+ }
64
+
65
+ function idcCountArg(value, field, min, max, fallback) {
66
+ if (value === undefined || value === null) { return fallback; }
67
+ if (typeof value !== 'number' || Math.floor(value) !== value || value < min || value > max) {
68
+ IDC.fail('invalid_argument', field + ' must be a whole number from ' + min + ' to ' + max + '.', { field: field, value: value });
69
+ }
70
+ return value;
71
+ }
72
+
73
+ /* Zellmatrix pruefen: Liste von Zeilen, jede Zeile eine Liste von Texten (Zahlen erlaubt; null = Zelle nicht anfassen). */
74
+ function idcCellsArg(value, field) {
75
+ var rows = [], r, c, row, out, cell;
76
+ if (!IDC.isArray(value) || value.length === 0) {
77
+ IDC.fail('invalid_argument', field + ' must be a non-empty list of rows (each row a list of cell texts).', { field: field });
78
+ }
79
+ if (value.length > 1000) {
80
+ IDC.fail('invalid_argument', field + ' may hold at most 1000 rows.', { field: field, rows: value.length });
81
+ }
82
+ for (r = 0; r < value.length; r++) {
83
+ row = value[r];
84
+ if (!IDC.isArray(row)) {
85
+ IDC.fail('invalid_argument', field + ' row ' + r + ' is not a list.', { field: field, row: r });
86
+ }
87
+ if (row.length > 100) {
88
+ IDC.fail('invalid_argument', field + ' row ' + r + ' has more than 100 cells.', { field: field, row: r });
89
+ }
90
+ out = [];
91
+ for (c = 0; c < row.length; c++) {
92
+ cell = row[c];
93
+ if (cell === null || cell === undefined) { out.push(null); continue; }
94
+ if (typeof cell !== 'string' && typeof cell !== 'number') {
95
+ IDC.fail('invalid_argument', field + ' cell ' + r + '/' + c + ' must be text or a number.', { field: field, row: r, column: c });
96
+ }
97
+ out.push(idcNormaliseText(String(cell)));
98
+ }
99
+ rows.push(out);
100
+ }
101
+ return rows;
102
+ }
103
+
104
+ function idcMaxRowLength(rows) {
105
+ var max = 0, r;
106
+ for (r = 0; r < rows.length; r++) { if (rows[r].length > max) { max = rows[r].length; } }
107
+ return max;
108
+ }
109
+
110
+ /* Zelle an Zeile/Spalte (Zaehlung ueber alle Zeilen: Kopf, Koerper, Fuss). Zusammengefuegte: die fuehrende Zelle, sonst null. */
111
+ function idcCellAt(table, row, column) {
112
+ var cell = null, cells, i, name, parts;
113
+ try {
114
+ cell = table.cells.itemByName(column + ':' + row);
115
+ if (cell && cell.isValid === true) { return cell; }
116
+ } catch (e0) { cell = null; }
117
+ try {
118
+ cells = table.rows.item(row).cells;
119
+ for (i = 0; i < cells.length; i++) {
120
+ cell = cells.item(i);
121
+ name = String(cell.name);
122
+ parts = name.split(':');
123
+ if (Number(parts[0]) === column) { return cell; }
124
+ }
125
+ } catch (e1) { /* null */ }
126
+ return null;
127
+ }
128
+
129
+ function idcRowType(table, rowIndex) {
130
+ var header = 0, body = 0;
131
+ try { header = Number(table.headerRowCount); } catch (e0) { header = 0; }
132
+ try { body = Number(table.bodyRowCount); } catch (e1) { body = 0; }
133
+ if (rowIndex < header) { return 'header'; }
134
+ if (rowIndex < header + body) { return 'body'; }
135
+ return 'footer';
136
+ }
137
+
138
+ function idcTableCounts(table) {
139
+ var out = { rows: null, body_rows: null, header_rows: null, footer_rows: null, columns: null };
140
+ try { out.body_rows = Number(table.bodyRowCount); } catch (e0) { /* null */ }
141
+ try { out.header_rows = Number(table.headerRowCount); } catch (e1) { /* null */ }
142
+ try { out.footer_rows = Number(table.footerRowCount); } catch (e2) { /* null */ }
143
+ try { out.columns = Number(table.columnCount); } catch (e3) { /* null */ }
144
+ try { out.rows = Number(table.rows.length); } catch (e4) { out.rows = null; }
145
+ if (out.rows === null && out.body_rows !== null) { out.rows = out.body_rows + (out.header_rows || 0) + (out.footer_rows || 0); }
146
+ return out;
147
+ }
148
+
149
+ function idcColumnWidths(table) {
150
+ var out = [], i;
151
+ try {
152
+ for (i = 0; i < table.columns.length; i++) { out.push(IDC.round(Number(table.columns.item(i).width), 3)); }
153
+ } catch (e) { /* leer */ }
154
+ return out;
155
+ }
156
+
157
+ function idcRowHeights(table) {
158
+ var out = [], i;
159
+ try {
160
+ for (i = 0; i < table.rows.length; i++) { out.push(IDC.round(Number(table.rows.item(i).height), 3)); }
161
+ } catch (e) { /* leer */ }
162
+ return out;
163
+ }
164
+
165
+ function idcTableStyleName(table) {
166
+ try { return String(table.appliedTableStyle.name); } catch (e) { return null; }
167
+ }
168
+
169
+ function idcTableStoryOffset(table) {
170
+ try { return Number(table.storyOffset.index); } catch (e) { return null; }
171
+ }
172
+
173
+ function idcTableFrameId(table) {
174
+ var frames;
175
+ try {
176
+ frames = table.storyOffset.parentTextFrames;
177
+ if (frames && frames.length > 0) { return Number(frames[0].id); }
178
+ } catch (e) { /* null */ }
179
+ return null;
180
+ }
181
+
182
+ function idcDescribeTable(table, story, index, count) {
183
+ var counts = idcTableCounts(table);
184
+ var out = {
185
+ table_id: null,
186
+ table_index: index,
187
+ table_count: count,
188
+ story_id: null,
189
+ story_offset_index: idcTableStoryOffset(table),
190
+ frame_id: idcTableFrameId(table),
191
+ rows: counts.rows,
192
+ body_rows: counts.body_rows,
193
+ header_rows: counts.header_rows,
194
+ footer_rows: counts.footer_rows,
195
+ columns: counts.columns,
196
+ table_style: idcTableStyleName(table),
197
+ width_mm: null,
198
+ height_mm: null,
199
+ column_widths_mm: idcColumnWidths(table)
200
+ };
201
+ try { out.table_id = Number(table.id); } catch (e0) { /* null */ }
202
+ try { out.story_id = Number(story.id); } catch (e1) { /* null */ }
203
+ try { out.width_mm = IDC.round(Number(table.width), 3); } catch (e2) { /* null */ }
204
+ try { out.height_mm = IDC.round(Number(table.height), 3); } catch (e3) { /* null */ }
205
+ return out;
206
+ }
207
+
208
+ /* Tabelle ueber frame_id (ein Rahmen der Story) und table_index (Vorgabe 0). */
209
+ function idcTableArg(doc, args) {
210
+ var found = idcTextFrameArg(doc, args, 'frame_id');
211
+ var story = idcStoryOf(found.item);
212
+ var index = idcCountArg(args.table_index, 'table_index', 0, 10000, 0);
213
+ var count = 0, table = null;
214
+ try { count = Number(story.tables.length); } catch (e0) { count = 0; }
215
+ if (count === 0) {
216
+ IDC.fail('not_found', 'The story of frame ' + args.frame_id + ' has no table; create one with create_table.',
217
+ { frame_id: args.frame_id, table_count: 0 });
218
+ }
219
+ if (index >= count) {
220
+ IDC.fail('not_found', 'The story of frame ' + args.frame_id + ' has ' + count + ' table(s); table_index ' + index + ' does not exist.',
221
+ { frame_id: args.frame_id, table_index: index, table_count: count });
222
+ }
223
+ try { table = story.tables.item(index); } catch (e1) { table = null; }
224
+ if (table === null || table === undefined) {
225
+ IDC.fail('not_found', 'Table ' + index + ' could not be read.', { frame_id: args.frame_id, table_index: index });
226
+ }
227
+ return { frame: found.item, story: story, table: table, index: index, count: count };
228
+ }
229
+
230
+ /* Zellen aus einer Matrix schreiben; liefert Zaehler und Zellen mit Uebersatz. */
231
+ function idcWriteCells(ctx, doc, table, rows, startRow, startColumn, paragraphStyle, cellStyle, grow) {
232
+ var counts = idcTableCounts(table);
233
+ var needRows = startRow + rows.length;
234
+ var needColumns = startColumn + idcMaxRowLength(rows);
235
+ var rowsAdded = 0, columnsAdded = 0, written = 0, skipped = 0;
236
+ var overflowing = [];
237
+ var r, c, cell, text;
238
+
239
+ if (needRows > counts.rows || needColumns > counts.columns) {
240
+ if (!grow) {
241
+ IDC.fail('invalid_argument', 'The cells do not fit: they need ' + needRows + ' row(s) and ' + needColumns + ' column(s), the table has ' +
242
+ counts.rows + ' x ' + counts.columns + '. Pass grow true to add rows and columns.',
243
+ { rows_needed: needRows, columns_needed: needColumns, rows: counts.rows, columns: counts.columns });
244
+ }
245
+ try {
246
+ while (counts.rows + rowsAdded < needRows) { table.rows.add(LocationOptions.AT_END); rowsAdded += 1; }
247
+ while (counts.columns + columnsAdded < needColumns) { table.columns.add(LocationOptions.AT_END); columnsAdded += 1; }
248
+ } catch (e0) {
249
+ IDC.fail('script_error', 'InDesign could not add rows or columns: ' + String(e0.message ? e0.message : e0), null);
250
+ }
251
+ counts = idcTableCounts(table);
252
+ }
253
+
254
+ for (r = 0; r < rows.length; r++) {
255
+ for (c = 0; c < rows[r].length; c++) {
256
+ cell = idcCellAt(table, startRow + r, startColumn + c);
257
+ if (cell === null) { skipped += 1; continue; }
258
+ text = rows[r][c];
259
+ /* A-8.8: Platzhalter in Zellen sind in dieser Fassung nicht vorgesehen – nur Warnung. */
260
+ if (typeof text === 'string' && text.indexOf('{{') >= 0 && !ctx.placeholderWarned) {
261
+ ctx.placeholderWarned = true;
262
+ ctx.warn('Cell text contains "{{" – placeholders such as {{nbsp}} are not expanded in table cells in this version; they are written as they are.');
263
+ }
264
+ try {
265
+ if (text !== null) { cell.contents = text; }
266
+ } catch (e1) {
267
+ IDC.fail('script_error', 'InDesign could not write cell ' + (startRow + r) + '/' + (startColumn + c) + ': ' + String(e1.message ? e1.message : e1),
268
+ { row: startRow + r, column: startColumn + c });
269
+ }
270
+ if (paragraphStyle !== null) {
271
+ try { cell.texts.item(0).appliedParagraphStyle = paragraphStyle; } catch (e2) { ctx.warn('Paragraph style not applied in cell ' + (startRow + r) + '/' + (startColumn + c) + '.'); }
272
+ }
273
+ if (cellStyle !== null) {
274
+ try { cell.appliedCellStyle = cellStyle; } catch (e3) { ctx.warn('Cell style not applied in cell ' + (startRow + r) + '/' + (startColumn + c) + '.'); }
275
+ }
276
+ if (text !== null) { written += 1; }
277
+ overflowing.push({ row: startRow + r, column: startColumn + c });
278
+ }
279
+ }
280
+ if (skipped > 0) {
281
+ ctx.warn(skipped + ' cell(s) were skipped because they are part of a merged cell.');
282
+ }
283
+ /* Live 05.09.2026: direkt nach dem Schreiben meldet InDesign jede Zelle als uebergelaufen, bis neu umbrochen ist. */
284
+ try { table.recompose(); } catch (e5) { /* kennt die Laufzeit nicht */ }
285
+ overflowing = idcOverflowingCells(table, overflowing);
286
+ if (overflowing.length > 0) {
287
+ ctx.warn(overflowing.length + ' cell(s) overflow (Zelle mit Übersatz); widen the column or shorten the text.');
288
+ }
289
+ return { cells_written: written, cells_skipped: skipped, rows_added: rowsAdded, columns_added: columnsAdded, overflowing_cells: overflowing };
290
+ }
291
+
292
+ /* Aus einer Liste von Zellpositionen die, deren Zelle nach dem Umbruch ueberlaeuft. */
293
+ function idcOverflowingCells(table, positions) {
294
+ var out = [], i, cell;
295
+ for (i = 0; i < positions.length; i++) {
296
+ cell = idcCellAt(table, positions[i].row, positions[i].column);
297
+ if (cell === null) { continue; }
298
+ try { if (cell.overflows === true) { out.push(positions[i]); } } catch (e) { /* unbekannt */ }
299
+ }
300
+ return out;
301
+ }
302
+
303
+ /*
304
+ * Gesamtbreite proportional auf die Spalten verteilen. table.width = x setzt
305
+ * in InDesign alle Spalten gleich breit (live 05.09.2026), deshalb selbst rechnen.
306
+ */
307
+ function idcApplyTableWidth(table, width) {
308
+ var widths = idcColumnWidths(table), sum = 0, i, factor;
309
+ for (i = 0; i < widths.length; i++) { sum += widths[i]; }
310
+ if (widths.length === 0 || !(sum > 0)) {
311
+ try { table.width = width; } catch (e0) { IDC.fail('script_error', 'InDesign could not set the table width.', null); }
312
+ return;
313
+ }
314
+ factor = width / sum;
315
+ try {
316
+ for (i = 0; i < widths.length; i++) { table.columns.item(i).width = widths[i] * factor; }
317
+ } catch (e1) {
318
+ IDC.fail('script_error', 'InDesign could not set the column widths: ' + String(e1.message ? e1.message : e1), null);
319
+ }
320
+ }
321
+
322
+ /*
323
+ * Kopf-/Fusszeilen ueber rowType je Zeile umwidmen. headerRowCount/
324
+ * footerRowCount per Skript legen neue leere Zeilen an oder loeschen
325
+ * vorhandene samt Inhalt (live 05.09.2026) – deshalb nicht benutzen.
326
+ */
327
+ function idcSetRowTypes(table, headerRows, footerRows) {
328
+ var counts = idcTableCounts(table), r, row, wanted, current, i;
329
+ var order = [];
330
+ if (typeof RowTypes === 'undefined') {
331
+ IDC.fail('invalid_state', 'This runtime has no RowTypes; header_rows/footer_rows cannot be changed.', null);
332
+ }
333
+ /* Erst alles, was Koerper werden soll, dann Kopf und Fuss – so bleiben die Bereiche zusammenhaengend. */
334
+ for (r = 0; r < counts.rows; r++) {
335
+ if (r < headerRows) { wanted = RowTypes.HEADER_ROW; }
336
+ else if (r >= counts.rows - footerRows) { wanted = RowTypes.FOOTER_ROW; }
337
+ else { wanted = RowTypes.BODY_ROW; }
338
+ order.push({ index: r, wanted: wanted, body: IDC.enumIs(wanted, RowTypes.BODY_ROW) });
339
+ }
340
+ for (i = 0; i < 2; i++) {
341
+ for (r = 0; r < order.length; r++) {
342
+ if ((i === 0) !== order[r].body) { continue; }
343
+ row = table.rows.item(order[r].index);
344
+ try { current = row.rowType; } catch (e0) { current = null; }
345
+ if (current !== null && IDC.enumIs(current, order[r].wanted)) { continue; }
346
+ try { row.rowType = order[r].wanted; } catch (e1) {
347
+ IDC.fail('script_error', 'InDesign could not change the type of row ' + order[r].index + ': ' + String(e1.message ? e1.message : e1),
348
+ { row: order[r].index });
349
+ }
350
+ }
351
+ }
352
+ }
353
+
354
+ function idcApplyColumnWidths(table, widths, field) {
355
+ var i, counts = idcTableCounts(table);
356
+ if (!IDC.isArray(widths) || widths.length === 0) {
357
+ IDC.fail('invalid_argument', field + ' must be a list of widths in mm, one per column.', { field: field });
358
+ }
359
+ if (widths.length !== counts.columns) {
360
+ IDC.fail('invalid_argument', field + ' lists ' + widths.length + ' width(s), the table has ' + counts.columns + ' column(s).',
361
+ { field: field, given: widths.length, columns: counts.columns });
362
+ }
363
+ for (i = 0; i < widths.length; i++) {
364
+ if (typeof widths[i] !== 'number' || !(widths[i] > 0) || widths[i] > 2000) {
365
+ IDC.fail('invalid_argument', field + '[' + i + '] must be a number above 0 (mm).', { field: field, index: i, value: widths[i] });
366
+ }
367
+ }
368
+ try {
369
+ for (i = 0; i < widths.length; i++) { table.columns.item(i).width = widths[i]; }
370
+ } catch (e) {
371
+ IDC.fail('script_error', 'InDesign could not set the column widths: ' + String(e.message ? e.message : e), null);
372
+ }
373
+ }
374
+
375
+ IDC.register('create_table', { needs_document: true, read_only: false, ruler: 'none' },
376
+ function (ctx) {
377
+ var args = ctx.args;
378
+ var doc = ctx.doc;
379
+ var found = idcTextFrameArg(doc, args, 'frame_id');
380
+ var frame = found.item;
381
+ var story = idcStoryOf(frame);
382
+ var bodyRows = idcCountArg(args.rows, 'rows', 1, 1000, null);
383
+ var columns = idcCountArg(args.columns, 'columns', 1, 100, null);
384
+ var headerRows = idcCountArg(args.header_rows, 'header_rows', 0, 20, 0);
385
+ var footerRows = idcCountArg(args.footer_rows, 'footer_rows', 0, 20, 0);
386
+ var position = args.position === undefined || args.position === null ? 'end' : args.position;
387
+ var cells = null, tableStyle = null, paragraphStyle = null, cellStyle = null;
388
+ var insertAt, length, lastChar = '', addedReturn = false, table = null, description, writeResult = null;
389
+ var countBefore = 0, index = null, i;
390
+
391
+ if (bodyRows === null) { IDC.fail('invalid_argument', 'rows is required (body rows, 1 to 1000).', null); }
392
+ if (columns === null) { IDC.fail('invalid_argument', 'columns is required (1 to 100).', null); }
393
+ if (position !== 'end' && position !== 'start' && position !== 'replace') {
394
+ IDC.fail('invalid_argument', 'position must be end, start or replace.', { position: position });
395
+ }
396
+ if (args.cells !== undefined && args.cells !== null) {
397
+ cells = idcCellsArg(args.cells, 'cells');
398
+ if (cells.length > headerRows + bodyRows + footerRows || idcMaxRowLength(cells) > columns) {
399
+ IDC.fail('invalid_argument', 'cells has more rows or columns than the table (' + (headerRows + bodyRows + footerRows) + ' x ' + columns + ').',
400
+ { cell_rows: cells.length, cell_columns: idcMaxRowLength(cells), rows: headerRows + bodyRows + footerRows, columns: columns });
401
+ }
402
+ }
403
+ if (args.table_style !== undefined && args.table_style !== null) { tableStyle = idcTableStyleArg(doc, args.table_style, 'table_style'); }
404
+ if (args.cell_style !== undefined && args.cell_style !== null) { cellStyle = idcCellStyleArg(doc, args.cell_style, 'cell_style'); }
405
+ if (args.paragraph_style !== undefined && args.paragraph_style !== null) { paragraphStyle = idcParagraphStyleArg(doc, args.paragraph_style, 'paragraph_style'); }
406
+ if (args.column_widths_mm !== undefined && args.column_widths_mm !== null) {
407
+ if (!IDC.isArray(args.column_widths_mm) || args.column_widths_mm.length !== columns) {
408
+ IDC.fail('invalid_argument', 'column_widths_mm must list exactly ' + columns + ' width(s).', { columns: columns });
409
+ }
410
+ for (i = 0; i < columns; i++) {
411
+ if (typeof args.column_widths_mm[i] !== 'number' || !(args.column_widths_mm[i] > 0)) {
412
+ IDC.fail('invalid_argument', 'column_widths_mm[' + i + '] must be a number above 0 (mm).', { index: i, value: args.column_widths_mm[i] });
413
+ }
414
+ }
415
+ }
416
+ if (args.width_mm !== undefined && args.width_mm !== null) {
417
+ if (typeof args.width_mm !== 'number' || !(args.width_mm > 0) || args.width_mm > 2000) {
418
+ IDC.fail('invalid_argument', 'width_mm must be a number above 0 (mm).', { width_mm: args.width_mm });
419
+ }
420
+ }
421
+
422
+ try { countBefore = Number(story.tables.length); } catch (e0) { countBefore = 0; }
423
+ try { length = Number(story.characters.length); } catch (e1) { length = 0; }
424
+
425
+ if (position === 'replace') {
426
+ try { story.contents = ''; } catch (e2) {
427
+ IDC.fail('script_error', 'InDesign could not clear the story: ' + String(e2.message ? e2.message : e2), null);
428
+ }
429
+ length = 0;
430
+ countBefore = 0;
431
+ insertAt = 0;
432
+ } else if (position === 'start') {
433
+ insertAt = 0;
434
+ } else {
435
+ if (length > 0) {
436
+ try { lastChar = String(story.characters.item(length - 1).contents); } catch (e3) { lastChar = ''; }
437
+ if (lastChar !== '\r') {
438
+ try { story.insertionPoints.item(length).contents = '\r'; } catch (e4) {
439
+ IDC.fail('script_error', 'InDesign could not add a paragraph return before the table: ' + String(e4.message ? e4.message : e4), null);
440
+ }
441
+ length += 1;
442
+ addedReturn = true;
443
+ }
444
+ }
445
+ insertAt = length;
446
+ }
447
+
448
+ try {
449
+ table = story.insertionPoints.item(insertAt).tables.add(LocationOptions.AT_END, undefined, {
450
+ bodyRowCount: bodyRows,
451
+ columnCount: columns,
452
+ headerRowCount: headerRows,
453
+ footerRowCount: footerRows
454
+ });
455
+ } catch (e5) {
456
+ IDC.fail('script_error', 'InDesign could not create the table: ' + String(e5.message ? e5.message : e5),
457
+ { frame_id: args.frame_id, rows: bodyRows, columns: columns });
458
+ }
459
+ table = IDC.concrete(table);
460
+
461
+ if (tableStyle !== null) {
462
+ try { table.appliedTableStyle = tableStyle; } catch (e6) { ctx.warn('Table style "' + args.table_style + '" could not be applied.'); }
463
+ }
464
+ if (args.column_widths_mm !== undefined && args.column_widths_mm !== null) {
465
+ idcApplyColumnWidths(table, args.column_widths_mm, 'column_widths_mm');
466
+ } else if (args.width_mm !== undefined && args.width_mm !== null) {
467
+ idcApplyTableWidth(table, args.width_mm);
468
+ }
469
+ if (cells === null && (paragraphStyle !== null || cellStyle !== null)) {
470
+ /* Formate ohne Inhalte: alle Zellen einmal anfassen, Inhalt bleibt leer. */
471
+ cells = idcEmptyMatrix(headerRows + bodyRows + footerRows, columns);
472
+ }
473
+ if (cells !== null) {
474
+ writeResult = idcWriteCells(ctx, doc, table, cells, 0, 0, paragraphStyle, cellStyle, false);
475
+ }
476
+
477
+ /* Index der neuen Tabelle in der Story. */
478
+ try {
479
+ for (i = 0; i < story.tables.length; i++) {
480
+ if (Number(story.tables.item(i).id) === Number(table.id)) { index = i; break; }
481
+ }
482
+ } catch (e8) { index = null; }
483
+
484
+ description = idcDescribeTable(table, story, index, countBefore + 1);
485
+ description.position = position;
486
+ description.paragraph_return_added = addedReturn;
487
+ description.cells_written = writeResult === null ? 0 : writeResult.cells_written;
488
+ description.overflowing_cells = writeResult === null ? [] : writeResult.overflowing_cells;
489
+ description.overset = idcOverflows(frame);
490
+ if (description.overset === true) {
491
+ ctx.warn('The story overflows after adding the table (Übersatz); enlarge the frame or thread another one.');
492
+ }
493
+ if (addedReturn) {
494
+ ctx.warn('A paragraph return was added before the table so it starts its own paragraph.');
495
+ }
496
+ ctx.changes = { created_table_ids: [description.table_id], modified_frame_ids: [Number(frame.id)] };
497
+ return description;
498
+ });
499
+
500
+ function idcEmptyMatrix(rows, columns) {
501
+ var out = [], r, c, row;
502
+ for (r = 0; r < rows; r++) {
503
+ row = [];
504
+ for (c = 0; c < columns; c++) { row.push(null); }
505
+ out.push(row);
506
+ }
507
+ return out;
508
+ }
509
+
510
+ IDC.register('set_table_cells', { needs_document: true, read_only: false, ruler: 'none' },
511
+ function (ctx) {
512
+ var args = ctx.args;
513
+ var doc = ctx.doc;
514
+ var target = idcTableArg(doc, args);
515
+ var rows = idcCellsArg(args.cells, 'cells');
516
+ var startRow = idcCountArg(args.start_row, 'start_row', 0, 100000, 0);
517
+ var startColumn = idcCountArg(args.start_column, 'start_column', 0, 1000, 0);
518
+ var grow = args.grow === true;
519
+ var paragraphStyle = null, cellStyle = null, result, description;
520
+
521
+ if (args.paragraph_style !== undefined && args.paragraph_style !== null) { paragraphStyle = idcParagraphStyleArg(doc, args.paragraph_style, 'paragraph_style'); }
522
+ if (args.cell_style !== undefined && args.cell_style !== null) { cellStyle = idcCellStyleArg(doc, args.cell_style, 'cell_style'); }
523
+
524
+ result = idcWriteCells(ctx, doc, target.table, rows, startRow, startColumn, paragraphStyle, cellStyle, grow);
525
+ description = idcDescribeTable(target.table, target.story, target.index, target.count);
526
+ description.start_row = startRow;
527
+ description.start_column = startColumn;
528
+ description.cells_written = result.cells_written;
529
+ description.cells_skipped = result.cells_skipped;
530
+ description.rows_added = result.rows_added;
531
+ description.columns_added = result.columns_added;
532
+ description.overflowing_cells = result.overflowing_cells;
533
+ description.overset = idcOverflows(target.frame);
534
+ if (description.overset === true) {
535
+ ctx.warn('The story overflows (Übersatz) after writing the cells.');
536
+ }
537
+ ctx.changes = { modified_table_ids: [description.table_id], modified_frame_ids: [Number(target.frame.id)] };
538
+ return description;
539
+ });
540
+
541
+ IDC.register('set_table_style', { needs_document: true, read_only: false, ruler: 'none' },
542
+ function (ctx) {
543
+ var args = ctx.args;
544
+ var doc = ctx.doc;
545
+ var target = idcTableArg(doc, args);
546
+ var table = target.table;
547
+ var given = 0, changed = false;
548
+ var tableStyle = null, cellStyle = null, scope, counts, description;
549
+ var cellsStyled = 0, r, c, cell, type, i;
550
+
551
+ if (args.table_style !== undefined && args.table_style !== null) { tableStyle = idcTableStyleArg(doc, args.table_style, 'table_style'); given += 1; }
552
+ if (args.cell_style !== undefined && args.cell_style !== null) { cellStyle = idcCellStyleArg(doc, args.cell_style, 'cell_style'); given += 1; }
553
+ scope = args.cell_style_scope === undefined || args.cell_style_scope === null ? 'all' : args.cell_style_scope;
554
+ if (scope !== 'all' && scope !== 'header' && scope !== 'body' && scope !== 'footer') {
555
+ IDC.fail('invalid_argument', 'cell_style_scope must be all, header, body or footer.', { cell_style_scope: scope });
556
+ }
557
+ if (args.column_widths_mm !== undefined && args.column_widths_mm !== null) { given += 1; }
558
+ if (args.width_mm !== undefined && args.width_mm !== null) {
559
+ if (typeof args.width_mm !== 'number' || !(args.width_mm > 0) || args.width_mm > 2000) {
560
+ IDC.fail('invalid_argument', 'width_mm must be a number above 0 (mm).', { width_mm: args.width_mm });
561
+ }
562
+ given += 1;
563
+ }
564
+ if (args.header_rows !== undefined && args.header_rows !== null) { idcCountArg(args.header_rows, 'header_rows', 0, 20, 0); given += 1; }
565
+ if (args.footer_rows !== undefined && args.footer_rows !== null) { idcCountArg(args.footer_rows, 'footer_rows', 0, 20, 0); given += 1; }
566
+ if (given === 0) {
567
+ IDC.fail('invalid_argument', 'Pass at least one of table_style, cell_style, column_widths_mm, width_mm, header_rows, footer_rows.', null);
568
+ }
569
+
570
+ if (tableStyle !== null) {
571
+ try { table.appliedTableStyle = tableStyle; changed = true; } catch (e0) {
572
+ IDC.fail('script_error', 'InDesign could not apply table style "' + args.table_style + '": ' + String(e0.message ? e0.message : e0), null);
573
+ }
574
+ }
575
+ counts = idcTableCounts(table);
576
+ if ((args.header_rows !== undefined && args.header_rows !== null) || (args.footer_rows !== undefined && args.footer_rows !== null)) {
577
+ var headerWanted = args.header_rows === undefined || args.header_rows === null ? counts.header_rows : args.header_rows;
578
+ var footerWanted = args.footer_rows === undefined || args.footer_rows === null ? counts.footer_rows : args.footer_rows;
579
+ if (headerWanted + footerWanted >= counts.rows) {
580
+ IDC.fail('invalid_argument', 'header_rows and footer_rows together must leave at least one body row (table has ' + counts.rows + ' rows).',
581
+ { header_rows: headerWanted, footer_rows: footerWanted, rows: counts.rows });
582
+ }
583
+ if (headerWanted !== counts.header_rows || footerWanted !== counts.footer_rows) {
584
+ idcSetRowTypes(table, headerWanted, footerWanted);
585
+ changed = true;
586
+ }
587
+ }
588
+ if (args.column_widths_mm !== undefined && args.column_widths_mm !== null) {
589
+ idcApplyColumnWidths(table, args.column_widths_mm, 'column_widths_mm');
590
+ changed = true;
591
+ } else if (args.width_mm !== undefined && args.width_mm !== null) {
592
+ idcApplyTableWidth(table, args.width_mm);
593
+ changed = true;
594
+ }
595
+ if (cellStyle !== null) {
596
+ counts = idcTableCounts(table);
597
+ for (r = 0; r < counts.rows; r++) {
598
+ type = idcRowType(table, r);
599
+ if (scope !== 'all' && scope !== type) { continue; }
600
+ for (c = 0; c < counts.columns; c++) {
601
+ cell = idcCellAt(table, r, c);
602
+ if (cell === null) { continue; }
603
+ try { cell.appliedCellStyle = cellStyle; cellsStyled += 1; } catch (e4) { /* naechste */ }
604
+ }
605
+ }
606
+ changed = changed || cellsStyled > 0;
607
+ }
608
+
609
+ description = idcDescribeTable(table, target.story, target.index, target.count);
610
+ description.cell_style = cellStyle === null ? null : String(cellStyle.name);
611
+ description.cell_style_scope = cellStyle === null ? null : scope;
612
+ description.cells_styled = cellsStyled;
613
+ description.row_heights_mm = idcRowHeights(table);
614
+ description.overset = idcOverflows(target.frame);
615
+ description.changed = changed;
616
+ if (description.overset === true) {
617
+ ctx.warn('The story overflows (Übersatz) after the change; frame_id is null while the table sits in overset.');
618
+ }
619
+ if (changed) { ctx.changes = { modified_table_ids: [description.table_id], modified_frame_ids: [Number(target.frame.id)] }; }
620
+ return description;
621
+ });
622
+
623
+ IDC.register('get_table', { needs_document: true, read_only: true, ruler: 'none' },
624
+ function (ctx) {
625
+ var args = ctx.args;
626
+ var doc = ctx.doc;
627
+ var target = idcTableArg(doc, args);
628
+ var table = target.table;
629
+ var maxChars = idcCountArg(args.max_chars_per_cell, 'max_chars_per_cell', 1, 100000, 200);
630
+ var counts = idcTableCounts(table);
631
+ var rowsText = [], merged = [], overflowing = [], cellStyles = {}, styleNames = [];
632
+ var truncated = false, r, c, cell, text, row, span, name, description, key;
633
+
634
+ for (r = 0; r < counts.rows; r++) {
635
+ row = [];
636
+ for (c = 0; c < counts.columns; c++) {
637
+ cell = idcCellAt(table, r, c);
638
+ if (cell === null) { row.push(null); continue; }
639
+ try { text = String(cell.contents); } catch (e0) { text = ''; }
640
+ if (text.length > maxChars) { text = text.substring(0, maxChars); truncated = true; }
641
+ row.push(text);
642
+ try {
643
+ span = { row: r, column: c, row_span: Number(cell.rowSpan), column_span: Number(cell.columnSpan) };
644
+ if (span.row_span > 1 || span.column_span > 1) { merged.push(span); }
645
+ } catch (e1) { /* keine Angabe */ }
646
+ try { if (cell.overflows === true) { overflowing.push({ row: r, column: c }); } } catch (e2) { /* unbekannt */ }
647
+ try {
648
+ name = String(cell.appliedCellStyle.name);
649
+ if (!IDC.hasOwn(cellStyles, name)) { cellStyles[name] = 0; }
650
+ cellStyles[name] += 1;
651
+ } catch (e3) { /* ohne */ }
652
+ }
653
+ rowsText.push(row);
654
+ }
655
+ for (key in cellStyles) {
656
+ if (IDC.hasOwn(cellStyles, key)) { styleNames.push({ name: key, cells: cellStyles[key] }); }
657
+ }
658
+
659
+ description = idcDescribeTable(table, target.story, target.index, target.count);
660
+ description.row_heights_mm = idcRowHeights(table);
661
+ description.row_types = [];
662
+ for (r = 0; r < counts.rows; r++) { description.row_types.push(idcRowType(table, r)); }
663
+ description.rows_text = rowsText;
664
+ description.merged_cells = merged;
665
+ description.overflowing_cells = overflowing;
666
+ description.cell_styles = styleNames;
667
+ description.truncated = truncated;
668
+ description.max_chars_per_cell = maxChars;
669
+ description.overset = idcOverflows(target.frame);
670
+ description.available_table_styles = idcStyleNames(doc.allTableStyles);
671
+ description.available_cell_styles = idcStyleNames(doc.allCellStyles);
672
+ if (overflowing.length > 0) {
673
+ ctx.warn(overflowing.length + ' cell(s) overflow (Zelle mit Übersatz).');
674
+ }
675
+ return description;
676
+ });