layoutbridge-light 1.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +83 -0
- package/README.de.md +31 -2
- package/README.md +31 -3
- package/THIRD-PARTY-NOTICES.md +2 -2
- package/dist/src/mcp/catalog.js +9 -4
- package/dist/src/mcp/content-credentials.js +65 -0
- package/dist/src/mcp/dispatch.js +8 -1
- package/dist/src/mcp/license/polar-ids.js +1 -1
- package/dist/src/mcp/pdf-postprocess.js +798 -0
- package/dist/src/mcp/server.js +1 -1
- package/dist/src/mcp/target-folder.js +25 -0
- package/dist/src/mcp/tools.js +275 -20
- package/dist/src/mcp/typography-rules.js +1 -1
- package/dist/src/transport/com.js +224 -38
- package/dist/src/transport/transport.js +22 -0
- package/indesign/commands/25-export.js +258 -11
- package/indesign/commands/26-export-image.js +1 -1
- package/indesign/commands/31-view.js +100 -0
- package/indesign/commands/35-parents.js +44 -24
- package/indesign/commands/40-frames.js +35 -0
- package/indesign/commands/47-anchored.js +142 -0
- package/indesign/commands/50-modify.js +25 -3
- package/indesign/commands/60-images.js +28 -2
- package/indesign/commands/69-placeholders.js +7 -2
- package/indesign/commands/70-text.js +39 -4
- package/indesign/commands/75-tables.js +27 -1
- package/indesign/commands/78-frame-lines.js +59 -0
- package/indesign/commands/79-check-typography.js +143 -4
- package/indesign/commands/80-styles.js +105 -10
- package/indesign/commands/89-toc-index.js +61 -4
- package/indesign/commands/91-epub.js +92 -9
- package/indesign/commands/92-accessibility.js +1131 -0
- package/indesign/interpreter.js +51 -1
- package/package.json +1 -1
- package/rules/typography-rules.json +3 -2
package/dist/src/mcp/tools.js
CHANGED
|
@@ -10,6 +10,9 @@ import { z } from 'zod';
|
|
|
10
10
|
import { selectTypographyRules, TYPOGRAPHY_LOCALES } from './typography-rules.js';
|
|
11
11
|
import { checkEpubFile } from './epub-check.js';
|
|
12
12
|
import { setEpubOrientation } from './epub-orientation.js';
|
|
13
|
+
import { remoteManifestOfFile, remoteManifestWarning } from './content-credentials.js';
|
|
14
|
+
import { createTargetFolder } from './target-folder.js';
|
|
15
|
+
import { postprocessPdf, PdfPostprocessError } from './pdf-postprocess.js';
|
|
13
16
|
/**
|
|
14
17
|
* Jedes Werkzeug nimmt optional document_id (Spezifikation, allgemeine
|
|
15
18
|
* Anforderung 1). Ohne Angabe gilt das vorderste Dokument.
|
|
@@ -132,8 +135,67 @@ const AUTOFLOW_MAX_PAGES = 2000;
|
|
|
132
135
|
/* Demo-Heft-Befund 7 (Sitzung 10): Familienname mit Formatzusatz. */
|
|
133
136
|
const FONT_FAMILY_NOTE = ' InDesign names a family with a format suffix such as "Source Sans 3 (OTF)" or "(TT)" when it knows the family in more than one format; pass the family with or without that suffix – the connector matches both and reads back the name InDesign uses.';
|
|
134
137
|
/* A-8.8 (Sitzung 9): benannte Sonderzeichen im Text. */
|
|
135
|
-
const PLACEHOLDER_TEXT = ' Placeholders in the text become InDesign special characters (placeholders true, default): {{line_break}} (forced line break within the paragraph), {{nbsp}} (no-break space U+00A0), {{nbsp_fixed}} (fixed-width no-break space U+202F), {{thin_space}}, {{hair_space}}, {{soft_hyphen}} (discretionary hyphen), {{nb_hyphen}} (no-break hyphen), {{en_dash}}, {{em_dash}}, {{tab}}, {{column_break}}, {{frame_break}}, {{page_break}}. Unknown {{…}} stay as written with a warning; each placeholder is exactly one character in the story. Returns placeholders_replaced {name: count} and placeholders_unknown[].';
|
|
138
|
+
const PLACEHOLDER_TEXT = ' Placeholders in the text become InDesign special characters (placeholders true, default): {{line_break}} (forced line break within the paragraph), {{nbsp}} (no-break space U+00A0), {{nbsp_fixed}} (fixed-width no-break space U+202F), {{thin_space}}, {{hair_space}}, {{soft_hyphen}} (discretionary hyphen), {{nb_hyphen}} (no-break hyphen), {{en_dash}}, {{em_dash}}, {{tab}}, {{column_break}}, {{frame_break}}, {{page_break}}, {{odd_page_break}}, {{even_page_break}} (break to the next odd or even page). Unknown {{…}} stay as written with a warning; each placeholder is exactly one character in the story. Returns placeholders_replaced {name: count} and placeholders_unknown[].';
|
|
136
139
|
const placeholdersParam = z.boolean().optional().describe('Expand {{…}} placeholders into special characters. Default true; false writes them literally.');
|
|
140
|
+
/*
|
|
141
|
+
* A-80 (Sitzung 82, E-117, E-120, E-121): barrierefreies PDF. Gleiche
|
|
142
|
+
* Parameter an export_pdf und export_interactive_pdf; ohne sie bleibt jeder
|
|
143
|
+
* Aufruf wie bisher.
|
|
144
|
+
*/
|
|
145
|
+
const taggedParam = z.boolean().optional().describe('Create a tagged PDF (Tagged PDF / Struktur einschließen) for this call. Default: as the preset or export settings say.');
|
|
146
|
+
const accessiblePdfParams = {
|
|
147
|
+
display_title: z.enum(['document_title', 'file_name']).optional().describe('What the PDF viewer shows in the title bar: document_title (needed for accessibility) or file_name. Default: as set.'),
|
|
148
|
+
pdf_language: z.string().min(1).optional().describe('Language of the PDF (/Lang), a code such as de-DE, en-GB or fr, or a language name as InDesign shows it; checked against the languages InDesign knows – unknown values are invalid_argument with details.code unknown_pdf_language. Default: as set.'),
|
|
149
|
+
title: z.string().min(1).optional().describe('Document title (File Info, written into the document and kept) – the title an accessible PDF shows.'),
|
|
150
|
+
pdfua_identifier: z.boolean().optional().describe('true: write the PDF/UA identifier (pdfuaid:part 1) into the exported file – only when check_accessibility reports no error for this document and these settings, otherwise invalid_state with details.code accessibility_check_failed and nothing is exported. Implies tagged true and display_title document_title. Default false.'),
|
|
151
|
+
artifact_untagged_paths: z.boolean().optional().describe('Mark vector paths that InDesign leaves untagged (strokes and fills of text frames, table cell strokes) as artifacts in the finished file. Default: true with tagged true (also through pdfua_identifier), otherwise false; false switches it off.'),
|
|
152
|
+
};
|
|
153
|
+
const ACCESSIBLE_PDF_TEXT = ' Accessible PDF (Barrierefreiheit), all optional and for this call only: tagged (Struktur), bookmarks, display_title document_title | file_name, pdf_language (checked, e.g. de-DE), title (written into the document), artifact_untagged_paths (InDesign writes strokes and fills of text frames and table cell strokes as untagged paths; with tagged true the server marks them as artifacts in the finished file, false switches that off) and pdfua_identifier (writes the PDF/UA identifier into the file, but only when check_accessibility reports no error – otherwise invalid_state with details.code accessibility_check_failed and the findings; the identifier claims a conformance the connector cannot fully check: links between figures and captions, complex tables, contrast). With any of them the answer adds tagged, display_title, pdf_language_used, pdf_language_source, title_set, pdfua_check, and after a tagged export untagged_paths {found, marked} and pdfua_identifier_set.';
|
|
154
|
+
/** Nacharbeit am fertigen PDF (E-120, E-121): ungetaggte Pfade, PDF/UA-Kennung. */
|
|
155
|
+
function accessiblePdfAfter(args, result) {
|
|
156
|
+
const pdfua = args['pdfua_identifier'] === true;
|
|
157
|
+
/* Rueckfrage 1 b (Anbieter 11.11.2026): mit tagged true automatisch, false schaltet ab. */
|
|
158
|
+
const explicit = args['artifact_untagged_paths'];
|
|
159
|
+
const artifactPaths = explicit === true || (explicit !== false && (args['tagged'] === true || pdfua));
|
|
160
|
+
if (!(pdfua || artifactPaths || result['tagged'] === true) || typeof result['path'] !== 'string')
|
|
161
|
+
return result;
|
|
162
|
+
const warnings = Array.isArray(result.warnings) ? [...result.warnings] : [];
|
|
163
|
+
try {
|
|
164
|
+
const done = postprocessPdf(result['path'], { pdfua, artifactPaths });
|
|
165
|
+
const out = {
|
|
166
|
+
...result,
|
|
167
|
+
warnings,
|
|
168
|
+
bytes: done.bytes,
|
|
169
|
+
untagged_paths: { found: done.untagged_paths_found, marked: done.untagged_paths_marked },
|
|
170
|
+
pdfua_identifier_set: done.pdfua_identifier_set,
|
|
171
|
+
};
|
|
172
|
+
if (!done.tagged)
|
|
173
|
+
warnings.push('The exported PDF has no structure (tags); check the preset.');
|
|
174
|
+
if (done.untagged_paths_found > 0 && !artifactPaths) {
|
|
175
|
+
warnings.push(done.untagged_paths_found + ' vector path(s) are untagged (strokes or fills of text frames, table cell strokes); PDF/UA checkers report them. ' + (explicit === false ? 'artifact_untagged_paths false left them so.' : 'Export with tagged true (or artifact_untagged_paths true) to mark them as artifacts.'));
|
|
176
|
+
}
|
|
177
|
+
if (done.pdfua_identifier_set) {
|
|
178
|
+
warnings.push('The PDF/UA identifier claims conformance with PDF/UA-1. The connector checked what InDesign exposes; it cannot check links between figures and captions, complex tables, contrast or the spoken reading order – verify the file with a PDF/UA checker and a screen reader.');
|
|
179
|
+
}
|
|
180
|
+
return out;
|
|
181
|
+
}
|
|
182
|
+
catch (error) {
|
|
183
|
+
const code = error instanceof PdfPostprocessError ? error.code : 'pdf_postprocess_failed';
|
|
184
|
+
if (pdfua || artifactPaths) {
|
|
185
|
+
return {
|
|
186
|
+
ok: false,
|
|
187
|
+
warnings,
|
|
188
|
+
error: {
|
|
189
|
+
kind: 'io_error',
|
|
190
|
+
message: 'The PDF was exported to ' + result['path'] + ', but the post-processing failed: ' + String(error instanceof Error ? error.message : error) + (pdfua ? ' The file has no PDF/UA identifier.' : ''),
|
|
191
|
+
details: { code: 'pdf_postprocess_failed', reason: code, path: result['path'] },
|
|
192
|
+
},
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
warnings.push('The exported PDF could not be inspected for untagged paths: ' + String(error instanceof Error ? error.message : error));
|
|
196
|
+
return { ...result, warnings };
|
|
197
|
+
}
|
|
198
|
+
}
|
|
137
199
|
export const TOOLS = [
|
|
138
200
|
{
|
|
139
201
|
name: 'get_app_version',
|
|
@@ -265,10 +327,11 @@ const TOOLS_A2 = [
|
|
|
265
327
|
{
|
|
266
328
|
name: 'export_pdf',
|
|
267
329
|
title: 'Export as PDF',
|
|
268
|
-
description: 'Export the document (or a page_range) as PDF to path (the target file path – not output_path). Preset chain: preset (without it the localized built-in "High Quality Print" preset); when the result exceeds fallback_over_bytes it is exported again with fallback_preset (without both there is no second pass); a preset that does not exist falls back to the localized "High Quality Print" preset, then to the current export preferences, each with a warning. A spread preset turns single pages into spreads – check exported_page_count. The server configuration can hold default values for the three preset parameters; a parameter in the call always wins. page_range uses the printed page names as shown in InDesign ("6-8", "1, 3-5"; "+3" is the third page regardless of its name). Returns path, exported_page_count and document_page_count (page_count equals exported_page_count), bytes, preset_used and page_range_used. Pass fallback_over_bytes 0 or fallback_preset "" to disable the second pass. use_document_bleed true exports with the document bleed (Anschnitt, see set_document_bleed) for this call only, without changing the preset – needed for print-on-demand and any bleeding image, because built-in presets such as [PDF/X-1a:2001] export without bleed; false exports without bleed; omitted = as the preset says. Also returned: document_bleed_used (true/false, null if unknown) and document_bleed_mm {top, bottom, inside_or_left, outside_or_right}. InDesign writes anywhere on the machine, also outside shared folders. Can take minutes on a full issue. For an e-book use export_epub.',
|
|
330
|
+
description: 'Export the document (or a page_range) as PDF to path (the target file path – not output_path). Preset chain: preset (without it the localized built-in "High Quality Print" preset); when the result exceeds fallback_over_bytes it is exported again with fallback_preset (without both there is no second pass); a preset that does not exist falls back to the localized "High Quality Print" preset, then to the current export preferences, each with a warning. A spread preset turns single pages into spreads – check exported_page_count. The server configuration can hold default values for the three preset parameters; a parameter in the call always wins. page_range uses the printed page names as shown in InDesign ("6-8", "1, 3-5"; "+3" is the third page regardless of its name). Returns path, exported_page_count and document_page_count (page_count equals exported_page_count), bytes, preset_used and page_range_used. Pass fallback_over_bytes 0 or fallback_preset "" to disable the second pass. use_document_bleed true exports with the document bleed (Anschnitt, see set_document_bleed) for this call only, without changing the preset – needed for print-on-demand and any bleeding image, because built-in presets such as [PDF/X-1a:2001] export without bleed; false exports without bleed; omitted = as the preset says. Also returned: document_bleed_used (true/false, null if unknown) and document_bleed_mm {top, bottom, inside_or_left, outside_or_right}. InDesign writes anywhere on the machine, also outside shared folders. Can take minutes on a full issue. For an e-book use export_epub.' + ACCESSIBLE_PDF_TEXT + ' For an interactive PDF use export_interactive_pdf.',
|
|
269
331
|
command: 'export_pdf',
|
|
270
332
|
readOnly: false,
|
|
271
333
|
timeoutMs: 900_000,
|
|
334
|
+
after: accessiblePdfAfter,
|
|
272
335
|
inputShape: {
|
|
273
336
|
...documentId,
|
|
274
337
|
path: z.string().min(1).describe('Required. Target .pdf path on the machine running InDesign.'),
|
|
@@ -277,6 +340,9 @@ const TOOLS_A2 = [
|
|
|
277
340
|
fallback_preset: z.string().optional().describe('Preset for the second pass when the file exceeds fallback_over_bytes. Default: the configured preset, otherwise none. "" disables the second pass.'),
|
|
278
341
|
fallback_over_bytes: z.number().int().min(0).optional().describe('Size threshold in bytes for the second pass. Default: the configured value, otherwise 0 = no second pass.'),
|
|
279
342
|
use_document_bleed: z.boolean().optional().describe('true: export with the document bleed (Anschnitt) for this call only, the preset stays unchanged; false: without bleed. Default: as the preset says.'),
|
|
343
|
+
tagged: taggedParam,
|
|
344
|
+
bookmarks: z.boolean().optional().describe('Include bookmarks (Lesezeichen) for this call. Default: as the preset says.'),
|
|
345
|
+
...accessiblePdfParams,
|
|
280
346
|
},
|
|
281
347
|
configArgs: (config) => ({
|
|
282
348
|
preset: config.export_pdf?.preset,
|
|
@@ -430,12 +496,13 @@ const TOOLS_B2 = [
|
|
|
430
496
|
{
|
|
431
497
|
name: 'apply_parent_to_page',
|
|
432
498
|
title: 'Apply a master page',
|
|
433
|
-
description: 'Apply the master spread parent_name (full name with prefix, e.g. "A-Footer") to page_id. "[None]", "none" or "Ohne" detaches the page from its master – an ad page loses header, footer line and page number in one step. Returns page_id and parent_applied as InDesign reports it afterwards.',
|
|
499
|
+
description: 'Apply the master spread parent_name (full name with prefix, e.g. "A-Footer") to page_id, or to several pages at once with page_ids (both may be given; every page is checked before anything changes). "[None]", "none" or "Ohne" detaches the page from its master – an ad page loses header, footer line and page number in one step. Returns page_id and parent_applied (of the first page) as InDesign reports it afterwards, and pages[] {page_id, parent_applied} for every page.',
|
|
434
500
|
command: 'apply_parent_to_page',
|
|
435
501
|
readOnly: false,
|
|
436
502
|
inputShape: {
|
|
437
503
|
...documentId,
|
|
438
|
-
page_id: z.number().int().describe('Page from list_pages (or a master page from list_parent_pages).'),
|
|
504
|
+
page_id: z.number().int().optional().describe('Page from list_pages (or a master page from list_parent_pages). Required unless page_ids is given.'),
|
|
505
|
+
page_ids: z.array(z.number().int()).min(1).max(5000).optional().describe('Several pages at once (from list_pages), e.g. all pages of a chapter.'),
|
|
439
506
|
parent_name: z.string().describe('Full master name with prefix, or "[None]" to detach.'),
|
|
440
507
|
},
|
|
441
508
|
},
|
|
@@ -806,7 +873,7 @@ const TOOLS_E = [
|
|
|
806
873
|
{
|
|
807
874
|
name: 'set_frame_inset',
|
|
808
875
|
title: 'Inset of a text frame',
|
|
809
|
-
description: 'Set the inset spacing (Innenabstand) of a text frame: inset_mm {top, left, bottom, right}, all four required, 0 or more; and/or the vertical justification (vertikale Ausrichtung, Textrahmenoptionen): vertical_justification top, center, bottom or justify. At least one
|
|
876
|
+
description: 'Set the inset spacing (Innenabstand) of a text frame: inset_mm {top, left, bottom, right}, all four required, 0 or more; and/or the vertical justification (vertikale Ausrichtung, Textrahmenoptionen): vertical_justification top, center, bottom or justify; and/or the first baseline (Grundlinienoptionen) as in create_text_frame: first_baseline_offset (ascent, cap_height, leading, x_height, fixed, embox_top) and min_first_baseline_pt. At least one; what is omitted stays. Returns frame_id, inset_mm, vertical_justification, first_baseline_offset and min_first_baseline_pt read back (get_frame_options reads them under text).',
|
|
810
877
|
command: 'set_frame_inset',
|
|
811
878
|
readOnly: false,
|
|
812
879
|
inputShape: {
|
|
@@ -817,6 +884,11 @@ const TOOLS_E = [
|
|
|
817
884
|
.enum(['top', 'center', 'bottom', 'justify'])
|
|
818
885
|
.optional()
|
|
819
886
|
.describe('Vertical justification of the text in the frame (vertikale Ausrichtung). Without it the frame keeps its setting.'),
|
|
887
|
+
first_baseline_offset: z
|
|
888
|
+
.enum(['ascent', 'cap_height', 'leading', 'x_height', 'fixed', 'embox_top'])
|
|
889
|
+
.optional()
|
|
890
|
+
.describe('First baseline offset (Erste Grundlinie, Versatz) as in create_text_frame. Without it the frame keeps its setting.'),
|
|
891
|
+
min_first_baseline_pt: z.number().min(0).optional().describe('Minimum first baseline offset in points (Min.). Without it the frame keeps its setting.'),
|
|
820
892
|
},
|
|
821
893
|
},
|
|
822
894
|
{
|
|
@@ -851,7 +923,7 @@ const TOOLS_F = [
|
|
|
851
923
|
{
|
|
852
924
|
name: 'place_image',
|
|
853
925
|
title: 'Place an image or PDF',
|
|
854
|
-
description: 'Place an image or PDF file (real path on the InDesign machine) into a graphic frame, replacing whatever it held (crop and scale are reset – to merely swap the file use relink_links). fit: fill_proportionally, fit_proportionally, fit_content_to_frame or center_content; without it the frame fitting options of the frame apply. pdf_crop chooses the PDF page box: media (InDesign default – the whole sheet including printer marks, the usual reason for misplaced ads), crop, trim, bleed (for bleed ads), art or content; pdf_page picks the page (default 1). When the PDF has no such box (a QR code PDF without TrimBox, say), InDesign refuses – the tool then falls back to the next larger box (bleed → trim → crop → media) with a warning and reports pdf_crop_used; without pdf_crop the box preset in InDesign applies (the last choice of the place dialog, not always media) and the same fallback starts from that box; pdf_crop_fallback false turns that off and returns the io_error instead. The place preferences are set for this call only and restored. Returns frame_id, link_status, frame_bounds_mm, graphic_bounds_mm, pdf_crop_used and fits_frame (true when the graphic covers the frame within 0.2 mm; otherwise a warning); a warning when the effective resolution is below min_ppi. A changed CropBox of a PDF is ignored by InDesign; for asymmetric bleed derive a placement copy of the PDF. A timed-out call may still have placed – check get_image_link_info before repeating.',
|
|
926
|
+
description: 'Place an image or PDF file (real path on the InDesign machine) into a graphic frame, replacing whatever it held (crop and scale are reset – to merely swap the file use relink_links). fit: fill_proportionally, fit_proportionally, fit_content_to_frame or center_content; without it the frame fitting options of the frame apply. pdf_crop chooses the PDF page box: media (InDesign default – the whole sheet including printer marks, the usual reason for misplaced ads), crop, trim, bleed (for bleed ads), art or content; pdf_page picks the page (default 1). When the PDF has no such box (a QR code PDF without TrimBox, say), InDesign refuses – the tool then falls back to the next larger box (bleed → trim → crop → media) with a warning and reports pdf_crop_used; without pdf_crop the box preset in InDesign applies (the last choice of the place dialog, not always media) and the same fallback starts from that box; pdf_crop_fallback false turns that off and returns the io_error instead. The place preferences are set for this call only and restored. Returns frame_id, link_status, frame_bounds_mm, graphic_bounds_mm, pdf_crop_used and fits_frame (true when the graphic covers the frame within 0.2 mm; otherwise a warning); a warning when the effective resolution is below min_ppi, and a warning when the XMP metadata of the file points to a remote Content Credentials manifest (exports can stall on it; the file is not changed). A changed CropBox of a PDF is ignored by InDesign; for asymmetric bleed derive a placement copy of the PDF. A timed-out call may still have placed – check get_image_link_info before repeating.',
|
|
855
927
|
command: 'place_image',
|
|
856
928
|
readOnly: false,
|
|
857
929
|
inputShape: {
|
|
@@ -865,6 +937,16 @@ const TOOLS_F = [
|
|
|
865
937
|
min_ppi: minPpi,
|
|
866
938
|
},
|
|
867
939
|
configArgs: minPpiConfig,
|
|
940
|
+
/* A-76 (Sitzung 80): Verweis auf ein entferntes C2PA-Manifest im XMP – nur Warnung, Datei bleibt unberuehrt. */
|
|
941
|
+
after: (args, result) => {
|
|
942
|
+
if (typeof args['image_path'] !== 'string')
|
|
943
|
+
return result;
|
|
944
|
+
const url = remoteManifestOfFile(args['image_path']);
|
|
945
|
+
if (url === null)
|
|
946
|
+
return result;
|
|
947
|
+
const warnings = Array.isArray(result.warnings) ? result.warnings : [];
|
|
948
|
+
return { ...result, warnings: [...warnings, remoteManifestWarning(url)] };
|
|
949
|
+
},
|
|
868
950
|
},
|
|
869
951
|
{
|
|
870
952
|
name: 'scale_image_in_frame',
|
|
@@ -905,7 +987,7 @@ const TOOLS_F = [
|
|
|
905
987
|
{
|
|
906
988
|
name: 'list_links',
|
|
907
989
|
title: 'List links',
|
|
908
|
-
description: 'List the links (Verknuepfungen) of the document, optionally filtered by path_contains (substring of path or file name, case-insensitive). Per link: link_id, file_name, file_path, status (NORMAL, LINK_MISSING, LINK_OUT_OF_DATE, EMBEDDED), page_id, page_name and frame_id (for a linked story file such as an InCopy story: its first text frame and the page of that frame). Also count. Where the holding object lies: container_id (the frame or object that holds the graphic, also when it lies on no page; for a linked story file its first text frame), container_type, graphic_type (InDesign class of the linked object, e.g. Image, PDF, EPS, Story), location (page, parent_page, pasteboard, anchored – in a story, then with story_id and in_overset true when the anchor sits in overset text –, or unknown), spread_id (the spread or parent spread of the object; for anchored objects the spread of the text frame, null in overset). For an object anchored in overset text InDesign still reports a page_id (the page it would follow) – in_overset true is the reliable sign. A link with page_id null and location pasteboard or anchored with in_overset true is a leftover that does not print – delete_link removes it, list_pasteboard_items lists all pasteboard objects. Use it to match pictures to articles by page number or to spot motifs of old issues by file name. Read-only.',
|
|
990
|
+
description: 'List the links (Verknuepfungen) of the document, optionally filtered by path_contains (substring of path or file name, case-insensitive). Per link: link_id, file_name, file_path, status (NORMAL, LINK_MISSING, LINK_OUT_OF_DATE, EMBEDDED), page_id, page_name and frame_id (for a linked story file such as an InCopy story: its first text frame and the page of that frame). Also count. Where the holding object lies: container_id (the frame or object that holds the graphic, also when it lies on no page; for a linked story file its first text frame), container_type, graphic_type (InDesign class of the linked object, e.g. Image, PDF, EPS, Story), location (page, parent_page, pasteboard, anchored – in a story, then with story_id and in_overset true when the anchor sits in overset text –, or unknown), spread_id (the spread or parent spread of the object; for anchored objects the spread of the text frame, null in overset). For an object anchored in overset text InDesign still reports a page_id (the page it would follow) – in_overset true is the reliable sign. A link with page_id null and location pasteboard or anchored with in_overset true is a leftover that does not print – delete_link removes it, list_pasteboard_items lists all pasteboard objects. without_object true marks a link InDesign keeps without any object (location unknown; often a Firefly/GenAI image whose frame was deleted) – it does not print, delete_link cannot reach it, and a warning names the remedy (export as IDML and reopen). Use it to match pictures to articles by page number or to spot motifs of old issues by file name. Read-only.',
|
|
909
991
|
command: 'list_links',
|
|
910
992
|
readOnly: true,
|
|
911
993
|
inputShape: {
|
|
@@ -1018,7 +1100,7 @@ const TOOLS_G = [
|
|
|
1018
1100
|
{
|
|
1019
1101
|
name: 'find_replace',
|
|
1020
1102
|
title: 'Find and replace text',
|
|
1021
|
-
description: 'Find and replace text in the document or in one frame: find, replace, mode literal or grep (default literal), scope document
|
|
1103
|
+
description: 'Find and replace text in the document or in one frame: find, replace, mode literal or grep (default literal), scope document, frame (only the text inside that frame – not its overset or other frames of the story; a warning says when the story goes on) or story (the whole story of frame_id, overset included); frame and story need frame_id. Removing paragraph marks merges paragraphs, which keep the style of the first one (warning). include_master_pages, include_hidden_layers, include_locked_layers (all default false), case_sensitive and whole_word (default false). dry_run true only counts and lists up to 200 matches with frame_id, page_name and index – use it before any name replacement. GREP metacharacters: ~M column break, ~R frame break, ~P page break, ~S non-breaking space (a literal U+00A0 is not found in literal mode); a straight " in GREP matches every quote, including typographic ones. Returns replacements, matches_found, scope, mode and master_pages_included. Locked managed stories (editorial workflow, lock_state as in get_frame_text) are never changed: their matches are left out of replacements and matches_found (also in dry_run) and listed in skipped_locked[] {story_id, frame_id, lock_state, managed_file, matches}, with a warning; without include_locked_layers InDesign does not search them, and a warning says how many there are. changes.modified_frame_ids lists the frames with replacements. No undo.',
|
|
1022
1104
|
command: 'find_replace',
|
|
1023
1105
|
readOnly: false,
|
|
1024
1106
|
destructive: true,
|
|
@@ -1027,8 +1109,8 @@ const TOOLS_G = [
|
|
|
1027
1109
|
find: z.string().min(1).describe('Text or GREP pattern to find.'),
|
|
1028
1110
|
replace: z.string().optional().describe('Replacement text; required unless dry_run is true. "" deletes the matches.'),
|
|
1029
1111
|
mode: z.enum(['literal', 'grep']).optional().describe('literal (default) or grep.'),
|
|
1030
|
-
scope: z.enum(['document', 'frame']).optional().describe('document (default)
|
|
1031
|
-
frame_id: z.number().int().optional().describe('Frame for scope "frame".'),
|
|
1112
|
+
scope: z.enum(['document', 'frame', 'story']).optional().describe('document (default), frame (only this frame) or story (the whole story of frame_id, overset included); frame and story need frame_id.'),
|
|
1113
|
+
frame_id: z.number().int().optional().describe('Frame for scope "frame" or "story".'),
|
|
1032
1114
|
include_master_pages: z.boolean().optional().describe('Also search master pages. Default false.'),
|
|
1033
1115
|
include_hidden_layers: z.boolean().optional().describe('Also search hidden layers. Default false.'),
|
|
1034
1116
|
include_locked_layers: z.boolean().optional().describe('Also search locked layers and stories. Default false. Matches in locked managed stories are reported in skipped_locked, never replaced.'),
|
|
@@ -1063,12 +1145,18 @@ const styleGroup = z
|
|
|
1063
1145
|
])
|
|
1064
1146
|
.optional()
|
|
1065
1147
|
.describe('Style group (Formatgruppe) for a new style; missing groups along the path are created. With group, an existing style counts only in that group (another style of the same name elsewhere is no collision, a warning names it), and update never moves a style between groups. A group and a style of the same name cannot share a level in InDesign: invalid_state with details.code "style_group_name".');
|
|
1148
|
+
/* A-79 (Sitzung 82, E-117 Nachtrag 1): Export-Tag fuer getaggte PDFs. */
|
|
1149
|
+
const pdfTag = z
|
|
1150
|
+
.enum(['P', 'H', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'Artifact', ''])
|
|
1151
|
+
.optional()
|
|
1152
|
+
.describe('PDF export tag of the style (Exporttag) for a tagged PDF: P, H, H1 to H6, Artifact (not read, e.g. page numbers) or "" to remove it. InDesign accepts no other tag here, and styles based on this one do not inherit it.');
|
|
1153
|
+
const PDF_TAG_TEXT = ' pdf_tag (P, H, H1–H6, Artifact, "" removes) sets the export tag for a tagged PDF – not inherited through based_on; the definition reads it back as pdf_tag ("" = none).';
|
|
1066
1154
|
const BASED_ON_GROUP_TEXT = ' based_on sets the parent style (Basierend auf), also from a group ("Group/Style" for an ambiguous name); group puts a new style into a style group (Formatgruppe), path "A/B" or ["A", "B"], creating missing groups. The answer adds based_on and group as read back, created_groups[] (paths of groups created by this call) and changes.created_group_ids.';
|
|
1067
1155
|
const TOOLS_H = [
|
|
1068
1156
|
{
|
|
1069
1157
|
name: 'list_paragraph_styles',
|
|
1070
1158
|
title: 'List paragraph and character styles',
|
|
1071
|
-
description: 'List the paragraph styles (Absatzformate) of the document, including those in style groups: styles[] {name, style_id, group ("" at top level, "Group/Subgroup" nested), based_on, font_family, font_style, point_size, leading_pt (null when automatic), leading_auto, fill_swatch, alignment, space_before_pt, space_after_pt, hyphenation, tracking, keep_options, hyphenation_options, justification_options, drop_cap {lines, characters, character_style}} and the character styles (Zeichenformate) as character_styles[] {name, style_id, group, based_on, font_family, font_style, point_size, fill_swatch, tracking – null for attributes the style does not set}. Internal styles whose name starts with "[" are excluded (internal_styles_excluded counts them). Read-only.',
|
|
1159
|
+
description: 'List the paragraph styles (Absatzformate) of the document, including those in style groups: styles[] {name, style_id, group ("" at top level, "Group/Subgroup" nested), based_on, font_family, font_style, point_size, leading_pt (null when automatic), leading_auto, fill_swatch, alignment, space_before_pt, space_after_pt, hyphenation, tracking, keep_options, hyphenation_options, justification_options, drop_cap {lines, characters, character_style}, pdf_tag (PDF export tag, "" = none)} and the character styles (Zeichenformate) as character_styles[] {name, style_id, group, based_on, font_family, font_style, point_size, fill_swatch, tracking – null for attributes the style does not set, pdf_tag}. Internal styles whose name starts with "[" are excluded (internal_styles_excluded counts them). Read-only.',
|
|
1072
1160
|
command: 'list_paragraph_styles',
|
|
1073
1161
|
readOnly: true,
|
|
1074
1162
|
inputShape: { ...documentId },
|
|
@@ -1076,7 +1164,7 @@ const TOOLS_H = [
|
|
|
1076
1164
|
{
|
|
1077
1165
|
name: 'define_paragraph_style',
|
|
1078
1166
|
title: 'Define a paragraph style',
|
|
1079
|
-
description: 'Create a paragraph style (Absatzformat) with name and any of font_family, font_style (exact InDesign style name, e.g. "75 Bold"), size_pt, leading_pt (points or "auto"), alignment (left, center, right, justify = Blocksatz with the last line left), color_hex (creates an RGB swatch named after the hex value) or swatch_name (an existing swatch by exact name – the way to a CMYK or spot colour; not together with color_hex), space_before_pt, space_after_pt, tracking (Laufweite in 1/1000 em), hyphenation, and the option groups keep_options (Umbruchoptionen: keep_with_next, keep_first_lines, keep_last_lines, keep_lines_together, keep_all_lines_together, keep_with_previous, start_paragraph), hyphenation_options (Silbentrennungseinstellungen) and justification_options (Blocksatz-Abstände, composer).' + INDENT_TAB_LANGUAGE_TEXT + DROP_CAP_TEXT + BASED_ON_GROUP_TEXT + FONT_FAMILY_NOTE + ' Strict keep options can produce overset or empty column ends – check overset and get_frame_lines afterwards. on_collision decides what happens when the name exists: error (default), update or version ("Name 2"). The font must be installed: InDesign rejects a font it does not have, even as family plus style (not_found with available_styles) – define such styles on the machine that has the font. Returns style_id, name (differs from the request with version), collision (none, updated, versioned), existed, applied[] and the definition read back (with keep_options, hyphenation_options and justification_options as InDesign holds them).',
|
|
1167
|
+
description: 'Create a paragraph style (Absatzformat) with name and any of font_family, font_style (exact InDesign style name, e.g. "75 Bold"), size_pt, leading_pt (points or "auto"), alignment (left, center, right, justify = Blocksatz with the last line left), color_hex (creates an RGB swatch named after the hex value) or swatch_name (an existing swatch by exact name – the way to a CMYK or spot colour; not together with color_hex), space_before_pt, space_after_pt, tracking (Laufweite in 1/1000 em), hyphenation, capitalization (normal, small_caps = Kapitälchen, all_caps = Versalien, cap_to_small_caps, lower_case), align_to_baseline_grid (Am Grundlinienraster ausrichten), and the option groups keep_options (Umbruchoptionen: keep_with_next, keep_first_lines, keep_last_lines, keep_lines_together, keep_all_lines_together, keep_with_previous, start_paragraph), hyphenation_options (Silbentrennungseinstellungen) and justification_options (Blocksatz-Abstände, composer).' + INDENT_TAB_LANGUAGE_TEXT + DROP_CAP_TEXT + BASED_ON_GROUP_TEXT + PDF_TAG_TEXT + FONT_FAMILY_NOTE + ' Strict keep options can produce overset or empty column ends – check overset and get_frame_lines afterwards. on_collision decides what happens when the name exists: error (default), update or version ("Name 2"). The font must be installed: InDesign rejects a font it does not have, even as family plus style (not_found with available_styles) – define such styles on the machine that has the font. Returns style_id, name (differs from the request with version), collision (none, updated, versioned), existed, applied[] and the definition read back (with keep_options, hyphenation_options and justification_options as InDesign holds them).',
|
|
1080
1168
|
command: 'define_paragraph_style',
|
|
1081
1169
|
readOnly: false,
|
|
1082
1170
|
inputShape: {
|
|
@@ -1101,15 +1189,18 @@ const TOOLS_H = [
|
|
|
1101
1189
|
justification_options: justificationOptions,
|
|
1102
1190
|
...indentTabLanguageParams,
|
|
1103
1191
|
drop_cap: dropCap,
|
|
1192
|
+
capitalization: z.enum(['normal', 'small_caps', 'all_caps', 'cap_to_small_caps', 'lower_case']).optional().describe('Case (Groß-/Kleinschreibung): normal, small_caps (Kapitälchen), all_caps (Versalien), cap_to_small_caps (OpenType all small caps), lower_case.'),
|
|
1193
|
+
align_to_baseline_grid: z.boolean().optional().describe('Align to baseline grid (Am Grundlinienraster ausrichten): true aligns the lines to the baseline grid of the document or frame, false turns it off.'),
|
|
1104
1194
|
based_on: basedOn('"[Basic Paragraph]" and "[No Paragraph Style]" name the built-in ones in every language.'),
|
|
1105
1195
|
group: styleGroup,
|
|
1106
1196
|
on_collision: onCollision,
|
|
1197
|
+
pdf_tag: pdfTag,
|
|
1107
1198
|
},
|
|
1108
1199
|
},
|
|
1109
1200
|
{
|
|
1110
1201
|
name: 'define_character_style',
|
|
1111
1202
|
title: 'Define a character style',
|
|
1112
|
-
description: 'Create a character style (Zeichenformat) with name and at least one of font_family, font_style (exact InDesign style name), point_size, fill_hex (creates an RGB swatch) or swatch_name (an existing swatch by exact name; not together with fill_hex), and tracking (Laufweite in 1/1000 em, -1000 to 10000; where the style is applied it replaces the tracking of the paragraph style – see apply_character_style_to_range). on_collision: error (default), update or version. Returns style_id, name, collision (none, updated, versioned), existed, applied[] and the definition read back (null for attributes the style leaves untouched); based_on alone is enough for a new style.' + BASED_ON_GROUP_TEXT + FONT_FAMILY_NOTE,
|
|
1203
|
+
description: 'Create a character style (Zeichenformat) with name and at least one of font_family, font_style (exact InDesign style name), point_size, fill_hex (creates an RGB swatch) or swatch_name (an existing swatch by exact name; not together with fill_hex), and tracking (Laufweite in 1/1000 em, -1000 to 10000; where the style is applied it replaces the tracking of the paragraph style – see apply_character_style_to_range), capitalization (normal, small_caps = Kapitälchen, all_caps = Versalien, cap_to_small_caps, lower_case). on_collision: error (default), update or version. Returns style_id, name, collision (none, updated, versioned), existed, applied[] and the definition read back (null for attributes the style leaves untouched); based_on alone is enough for a new style.' + BASED_ON_GROUP_TEXT + PDF_TAG_TEXT + FONT_FAMILY_NOTE,
|
|
1113
1204
|
command: 'define_character_style',
|
|
1114
1205
|
readOnly: false,
|
|
1115
1206
|
inputShape: {
|
|
@@ -1121,9 +1212,11 @@ const TOOLS_H = [
|
|
|
1121
1212
|
fill_hex: hexColour.optional().describe('Text colour as hex; an RGB swatch is created if needed. Not together with swatch_name.'),
|
|
1122
1213
|
swatch_name: z.string().min(1).optional().describe('Text colour as an existing swatch by exact name (CMYK, spot, tint or gradient; see list_swatches). Not together with fill_hex.'),
|
|
1123
1214
|
tracking: z.number().min(-1000).max(10000).optional().describe('Tracking (Laufweite) in 1/1000 em.'),
|
|
1215
|
+
capitalization: z.enum(['normal', 'small_caps', 'all_caps', 'cap_to_small_caps', 'lower_case']).optional().describe('Case (Groß-/Kleinschreibung): normal, small_caps (Kapitälchen), all_caps (Versalien), cap_to_small_caps (OpenType all small caps), lower_case.'),
|
|
1124
1216
|
based_on: basedOn('"[None]" names the built-in root in every language.'),
|
|
1125
1217
|
group: styleGroup,
|
|
1126
1218
|
on_collision: onCollision,
|
|
1219
|
+
pdf_tag: pdfTag,
|
|
1127
1220
|
},
|
|
1128
1221
|
},
|
|
1129
1222
|
{
|
|
@@ -1168,7 +1261,7 @@ const TOOLS_H = [
|
|
|
1168
1261
|
{
|
|
1169
1262
|
name: 'apply_character_format_to_range',
|
|
1170
1263
|
title: 'Format a range locally',
|
|
1171
|
-
description: 'Local character formatting without a style for the characters start_index (inclusive) to end_index (exclusive) of the story of a text frame: font_style (exact InDesign style name – fetch it with get_font_info_at_index first, "75 Bold" rather than "Bold"; optional font_family to switch the family), swatch_name (an existing swatch, exact name; built-ins are "Black", "Paper", "None"), superscript (true/false), tracking (Laufweite in 1/1000 em, -1000 to 10000; the server configuration can set a tolerance beyond which a warning is given), point_size (0–1296, the only way to a size without a paragraph style). At least one attribute. Never changes text. Returns applied[], point_size_applied, font_family, font_style and
|
|
1264
|
+
description: 'Local character formatting without a style for the characters start_index (inclusive) to end_index (exclusive) of the story of a text frame: font_style (exact InDesign style name – fetch it with get_font_info_at_index first, "75 Bold" rather than "Bold"; optional font_family to switch the family), swatch_name (an existing swatch, exact name; built-ins are "Black", "Paper", "None"), superscript (true/false), tracking (Laufweite in 1/1000 em, -1000 to 10000; the server configuration can set a tolerance beyond which a warning is given), point_size (0–1296, the only way to a size without a paragraph style), language (dictionary for hyphenation and spelling of the range, e.g. a foreign-language quotation – same names as in define_paragraph_style; check_typography rule foreign_language_in_text finds ranges whose language differs from their paragraph style). At least one attribute. Never changes text. Returns applied[], point_size_applied, font_family, font_style, fill_color and language {name, untranslated_name, icu_locale} read back at the first character for a cross-check, plus characters_affected. Stories managed by an editorial workflow (InCopy) that are not checked out here (lock_state checked_in_story, locked_story, missing_lock_state or mixed_lock_state) are refused before anything is written: invalid_state with details.code "story_locked" (details: frame_id, story_id, lock_state, managed_file) – check the story out in the editorial system or in InCopy first.',
|
|
1172
1265
|
command: 'apply_character_format_to_range',
|
|
1173
1266
|
readOnly: false,
|
|
1174
1267
|
configArgs: (config) => ({ tracking_warn_beyond: config.tracking_warn_beyond }),
|
|
@@ -1182,6 +1275,7 @@ const TOOLS_H = [
|
|
|
1182
1275
|
superscript: z.boolean().optional().describe('true sets superscript, false resets to normal position.'),
|
|
1183
1276
|
tracking: z.number().min(-1000).max(10000).optional().describe('Tracking in 1/1000 em.'),
|
|
1184
1277
|
point_size: z.number().positive().max(1296).optional().describe('Point size.'),
|
|
1278
|
+
language: indentTabLanguageParams.language,
|
|
1185
1279
|
},
|
|
1186
1280
|
},
|
|
1187
1281
|
{
|
|
@@ -1303,10 +1397,17 @@ const TOOLS_J = [
|
|
|
1303
1397
|
{
|
|
1304
1398
|
name: 'export_page_image',
|
|
1305
1399
|
title: 'Export pages as images',
|
|
1306
|
-
description: 'Export document pages as PNG or JPEG images, one file per page (for proofs, correction mails, the website or a measuring run without PDF). Select pages with page_ids (from list_pages) or page_range like export_pdf ("6-8", "1, 3-5", "+2"; printed page names). path is the target file; with several pages the page name is inserted before the extension (Seite.png → Seite_8.png). format png (default) or jpeg, dpi 36–600 (default 150), quality low/medium/high (default)/maximum, color_space rgb (default), gray or cmyk (jpeg only), transparent_background (png), use_bleed (include the bleed), anti_alias (default true). Master pages cannot be exported. The export preferences are set for this call only and restored. Returns format, dpi, count
|
|
1400
|
+
description: 'Export document pages as PNG or JPEG images, one file per page (for proofs, correction mails, the website or a measuring run without PDF). Select pages with page_ids (from list_pages) or page_range like export_pdf ("6-8", "1, 3-5", "+2"; printed page names). path is the target file; with several pages the page name is inserted before the extension (Seite.png → Seite_8.png). format png (default) or jpeg, dpi 36–600 (default 150), quality low/medium/high (default)/maximum, color_space rgb (default), gray or cmyk (jpeg only), transparent_background (png), use_bleed (include the bleed), anti_alias (default true). Master pages cannot be exported. The export preferences are set for this call only and restored. create_folder true creates a missing target folder first (folder_created says whether it did). Returns format, dpi, count, files[] {page_id, page_name, path, bytes} and folder_created. Read the files with an image tool of the client to check a layout visually. A timed-out call may still have written files – check the folder before repeating. For an e-book use export_epub.',
|
|
1307
1401
|
command: 'export_page_image',
|
|
1308
1402
|
readOnly: false,
|
|
1309
1403
|
timeoutMs: 600_000,
|
|
1404
|
+
/* A-68 (9), Sitzung 81: fehlenden Zielordner auf Wunsch im Server anlegen (gleicher Rechner wie InDesign). */
|
|
1405
|
+
buildArgs: (input) => {
|
|
1406
|
+
if (input['create_folder'] !== true || typeof input['path'] !== 'string')
|
|
1407
|
+
return input;
|
|
1408
|
+
return { ...input, folder_created: createTargetFolder(input['path']) };
|
|
1409
|
+
},
|
|
1410
|
+
after: (args, result) => ({ ...result, folder_created: args['folder_created'] === true }),
|
|
1310
1411
|
inputShape: {
|
|
1311
1412
|
...documentId,
|
|
1312
1413
|
path: z.string().min(1).describe('Target file on the InDesign machine, e.g. /Users/.../Seite.png; the page name is inserted before the extension when several pages are exported.'),
|
|
@@ -1319,6 +1420,7 @@ const TOOLS_J = [
|
|
|
1319
1420
|
transparent_background: z.boolean().optional().describe('PNG only: transparent instead of white background. Default false.'),
|
|
1320
1421
|
use_bleed: z.boolean().optional().describe('Include the document bleed (Anschnitt). Default false.'),
|
|
1321
1422
|
anti_alias: z.boolean().optional().describe('Smooth edges. Default true.'),
|
|
1423
|
+
create_folder: z.boolean().optional().describe('Create the target folder (and missing parent folders) when it does not exist. Default false: a missing folder is io_error.'),
|
|
1322
1424
|
},
|
|
1323
1425
|
},
|
|
1324
1426
|
{
|
|
@@ -1486,7 +1588,7 @@ const TOOLS_J8_TABLES = [
|
|
|
1486
1588
|
{
|
|
1487
1589
|
name: 'set_table_style',
|
|
1488
1590
|
title: 'Table style, cell style, widths',
|
|
1489
|
-
description: 'Change how a table looks: table_style (Tabellenformat), cell_style with cell_style_scope all|header|body|footer, column_widths_mm (one per column) or width_mm (proportional), header_rows and footer_rows (converted from existing rows; at least one body row must remain). At least one parameter. Unknown style names are not_found with the available names in the details. Returns the table summary (widths, heights, counts, table_style), cells_styled, changed, overset.',
|
|
1591
|
+
description: 'Change how a table looks: table_style (Tabellenformat), cell_style with cell_style_scope all|header|body|footer, column_widths_mm (one per column) or width_mm (proportional), header_rows and footer_rows (converted from existing rows; at least one body row must remain), header_columns (Kopfspalten, InDesign 2026 and later; every table answer carries header_columns, null before 2026). At least one parameter. Unknown style names are not_found with the available names in the details. Returns the table summary (widths, heights, counts, table_style), cells_styled, changed, overset.',
|
|
1490
1592
|
command: 'set_table_style',
|
|
1491
1593
|
readOnly: false,
|
|
1492
1594
|
inputShape: {
|
|
@@ -1500,6 +1602,7 @@ const TOOLS_J8_TABLES = [
|
|
|
1500
1602
|
width_mm: z.number().positive().optional().describe('Total table width in mm, columns scaled proportionally.'),
|
|
1501
1603
|
header_rows: z.number().int().min(0).max(20).optional().describe('Number of header rows (taken from the top rows).'),
|
|
1502
1604
|
footer_rows: z.number().int().min(0).max(20).optional().describe('Number of footer rows (taken from the bottom rows).'),
|
|
1605
|
+
header_columns: z.number().int().min(0).max(20).optional().describe('Number of header columns (Kopfspalten, taken from the left columns; exported as TH with row scope). InDesign 2026 and later only – older versions answer invalid_state with details.code needs_indesign_2026.'),
|
|
1503
1606
|
},
|
|
1504
1607
|
},
|
|
1505
1608
|
{
|
|
@@ -1818,6 +1921,28 @@ const TOOLS_J8_ANCHOR = [
|
|
|
1818
1921
|
space_after_mm: z.number().min(-1000).max(1000).optional().describe('above_line only: space after the object (Abstand danach) in mm.'),
|
|
1819
1922
|
},
|
|
1820
1923
|
},
|
|
1924
|
+
{
|
|
1925
|
+
name: 'set_anchored_object_options',
|
|
1926
|
+
title: 'Change anchored object options',
|
|
1927
|
+
description: 'Change the anchored object options (Optionen für verankertes Objekt) of an object that is already anchored in text – without releasing and re-anchoring it: position inline, above_line or custom (without it the current position stays), and the options of that position as in anchor_frame_in_text – custom: offset_mm {x, y} (only the given coordinate changes), anchor_point, horizontal_reference, vertical_reference, horizontal_alignment, vertical_alignment, keep_within_frame, lock_position; above_line: horizontal_alignment (e.g. center for a chapter vignette), space_before_mm, space_after_mm. Options that do not apply to the position are ignored with a warning; what is omitted stays. invalid_state with details.code "not_anchored" for an object that is not anchored. Returns frame_id, story_id, index, applied[], settings read back, previous_position, bounds_mm, page_id/page_name and story_overset.',
|
|
1928
|
+
command: 'set_anchored_object_options',
|
|
1929
|
+
readOnly: false,
|
|
1930
|
+
inputShape: {
|
|
1931
|
+
...documentId,
|
|
1932
|
+
frame_id: frameId,
|
|
1933
|
+
position: z.enum(['inline', 'above_line', 'custom']).optional().describe('New position; without it the current one stays.'),
|
|
1934
|
+
offset_mm: z.object({ x: z.number().optional(), y: z.number().optional() }).optional().describe('custom only: offset in mm (x right, y down); only the given coordinate changes.'),
|
|
1935
|
+
anchor_point: z.enum(['top_left', 'top_center', 'top_right', 'left_center', 'center', 'right_center', 'bottom_left', 'bottom_center', 'bottom_right']).optional().describe('custom only: reference point on the object.'),
|
|
1936
|
+
horizontal_reference: z.enum(['anchor_location', 'column_edge', 'text_frame', 'page_margins', 'page_edge']).optional().describe('custom only.'),
|
|
1937
|
+
vertical_reference: z.enum(['line_baseline', 'line_xheight', 'line_ascent', 'cap_height', 'top_of_leading', 'embox_top', 'embox_middle', 'embox_bottom', 'column_edge', 'text_frame', 'page_margins', 'page_edge']).optional().describe('custom only.'),
|
|
1938
|
+
horizontal_alignment: z.enum(['left', 'center', 'right', 'text']).optional().describe('custom and above_line (above_line: alignment in the text column).'),
|
|
1939
|
+
vertical_alignment: z.enum(['top', 'center', 'bottom']).optional().describe('custom only.'),
|
|
1940
|
+
keep_within_frame: z.boolean().optional().describe('custom only: keep the object within the top and bottom of the text frame.'),
|
|
1941
|
+
lock_position: z.boolean().optional().describe('custom only: prevent manual dragging.'),
|
|
1942
|
+
space_before_mm: z.number().min(-1000).max(1000).optional().describe('above_line only: space before the object (Abstand davor) in mm.'),
|
|
1943
|
+
space_after_mm: z.number().min(-1000).max(1000).optional().describe('above_line only: space after the object (Abstand danach) in mm.'),
|
|
1944
|
+
},
|
|
1945
|
+
},
|
|
1821
1946
|
{
|
|
1822
1947
|
name: 'unanchor_frame',
|
|
1823
1948
|
title: 'Release anchored object',
|
|
@@ -1861,7 +1986,7 @@ const TOOLS_A7 = [
|
|
|
1861
1986
|
{
|
|
1862
1987
|
name: 'check_typography',
|
|
1863
1988
|
title: 'Check typography rules (read-only)',
|
|
1864
|
-
description: 'Find violations of general typesetting rules and report them – never change anything. The rule catalogue is a data table in the package (rules/typography-rules.json): character rules run as InDesign GREP searches (double_space, space_before_punct, straight_quotes, apostrophe, hyphen_as_dash, dash_spacing, three_dots, number_unit_space, number_unit_missing_space, abbreviation_space, thousands_grouping, empty_paragraph, double_paragraph_break, tab_as_indent, trailing_space); line rules run on the composed lines of every text frame like get_frame_lines (widow – Hurenkind, error; orphan – Schusterjunge, warning; heading_at_column_end; single_word_last_line; hyphen_ladder with max_consecutive_hyphens, default 3; empty_line_at_column_start; column_first_baselines_differ, more than 0.1 mm). locale de (default), de-CH (guillemets) or en (curly quotes, closed em dash, no space before %). scope document (default), frame or story (both need frame_id). page_range limits the check to pages by printed page name like export_pdf ("6-8", "1, 3-5", "+3"): line rules read only frames on those pages, character findings elsewhere are left out (returned as page_range_used, "all" without it). Line rules read every line and take far longer than the character rules – on a long book check part of it per call with page_range; above 100 text frames in scope document without page_range a warning says so. rules[] limits to those ids, exclude_rules[] drops some; unknown ids are invalid_argument. Returns findings[] {rule_id, severity, category, message, story_id, frame_id, page_id, page_name, start_index, end_index (story indices for the *_to_range tools), snippet, suggestion (often a find_replace GREP pattern)}, counts per rule_id, rules_checked[], rules_failed[] (a GREP pattern InDesign rejected – warning, the rest runs), frames_checked, findings_dropped and truncated (max_findings caps only findings[]; every rule still runs and counts stays complete). Sources: Forssman/de Jong (Detailtypografie), Duden (Satz und Korrektur), DIN 5008, Bier (typokurz), Bringhurst (locale en). Not checked: spelling, grammar, content, text inside placed graphics; table cells are skipped in this version (warning tables_skipped). Read-only.',
|
|
1989
|
+
description: 'Find violations of general typesetting rules and report them – never change anything. The rule catalogue is a data table in the package (rules/typography-rules.json): character rules run as InDesign GREP searches (double_space, space_before_punct, straight_quotes, apostrophe, hyphen_as_dash, dash_spacing, three_dots, number_unit_space, number_unit_missing_space, abbreviation_space, thousands_grouping, empty_paragraph, double_paragraph_break, tab_as_indent, trailing_space); line rules run on the composed lines of every text frame like get_frame_lines (widow – Hurenkind, error; orphan – Schusterjunge, warning; heading_at_column_end; single_word_last_line; hyphen_ladder with max_consecutive_hyphens, default 3; empty_line_at_column_start; column_first_baselines_differ, more than 0.1 mm); the language rule foreign_language_in_text reports text ranges whose language (dictionary for hyphenation and spelling) differs from that of their paragraph style – e.g. English from a Word file inside German text; findings add language and paragraph_style_language, fix with apply_character_format_to_range language. locale de (default), de-CH (guillemets) or en (curly quotes, closed em dash, no space before %). scope document (default), frame or story (both need frame_id). page_range limits the check to pages by printed page name like export_pdf ("6-8", "1, 3-5", "+3"): line rules read only frames on those pages, character findings elsewhere are left out (returned as page_range_used, "all" without it). Line rules read every line and take far longer than the character rules – on a long book check part of it per call with page_range; above 100 text frames in scope document without page_range a warning says so. rules[] limits to those ids, exclude_rules[] drops some; unknown ids are invalid_argument. Returns findings[] {rule_id, severity, category, message, story_id, frame_id, page_id, page_name, start_index, end_index (story indices for the *_to_range tools), snippet, suggestion (often a find_replace GREP pattern)}, counts per rule_id, rules_checked[], rules_failed[] (a GREP pattern InDesign rejected – warning, the rest runs), frames_checked, findings_dropped and truncated (max_findings caps only findings[]; every rule still runs and counts stays complete). Sources: Forssman/de Jong (Detailtypografie), Duden (Satz und Korrektur), DIN 5008, Bier (typokurz), Bringhurst (locale en). Not checked: spelling, grammar, content, text inside placed graphics; table cells are skipped in this version (warning tables_skipped). Read-only.',
|
|
1865
1990
|
command: 'check_typography',
|
|
1866
1991
|
readOnly: true,
|
|
1867
1992
|
timeoutMs: 300_000,
|
|
@@ -2082,6 +2207,23 @@ const TOOLS_S10_VIEW = [
|
|
|
2082
2207
|
activate: z.boolean().optional().describe('Bring the window to the front. Default false.'),
|
|
2083
2208
|
},
|
|
2084
2209
|
},
|
|
2210
|
+
{
|
|
2211
|
+
name: 'set_view_options',
|
|
2212
|
+
title: 'Set view options',
|
|
2213
|
+
description: 'Switch what the layout window shows – for screen recordings and for checking a page by eye: guides_shown (Hilfslinien), frame_edges_shown (Rahmenkanten), text_threads_shown (Textverkettungen), baseline_grid_shown (Grundlinienraster), document_grid_shown (Dokumentraster), hidden_characters_shown (verborgene Zeichen), screen_mode normal, preview (Vorschau), bleed (Anschnitt), slug (Infobereich) or presentation. At least one; what is omitted stays. Changes only the view, never the content; InDesign stores the view settings with the document. screen_mode needs a layout window (invalid_state, details.code "no_layout_window", for a document opened with show_window false). Returns has_window, view_options with every value read back and previous (the values before, to restore them later).',
|
|
2214
|
+
command: 'set_view_options',
|
|
2215
|
+
readOnly: false,
|
|
2216
|
+
inputShape: {
|
|
2217
|
+
...documentId,
|
|
2218
|
+
guides_shown: z.boolean().optional().describe('Show guides (Hilfslinien).'),
|
|
2219
|
+
frame_edges_shown: z.boolean().optional().describe('Show frame edges (Rahmenkanten).'),
|
|
2220
|
+
text_threads_shown: z.boolean().optional().describe('Show text threads (Textverkettungen).'),
|
|
2221
|
+
baseline_grid_shown: z.boolean().optional().describe('Show the baseline grid (Grundlinienraster).'),
|
|
2222
|
+
document_grid_shown: z.boolean().optional().describe('Show the document grid.'),
|
|
2223
|
+
hidden_characters_shown: z.boolean().optional().describe('Show hidden characters (verborgene Zeichen).'),
|
|
2224
|
+
screen_mode: z.enum(['normal', 'preview', 'bleed', 'slug', 'presentation']).optional().describe('Screen mode (Bildschirmmodus): normal, preview, bleed, slug or presentation.'),
|
|
2225
|
+
},
|
|
2226
|
+
},
|
|
2085
2227
|
];
|
|
2086
2228
|
/* Sitzung 42 (A-41, E-97): Inhaltsverzeichnis und Register. */
|
|
2087
2229
|
const paragraphStyleName = z.string().min(1);
|
|
@@ -2337,7 +2479,7 @@ const TOOLS_S60_EPUB = [
|
|
|
2337
2479
|
{
|
|
2338
2480
|
name: 'export_epub',
|
|
2339
2481
|
title: 'Export as EPUB',
|
|
2340
|
-
description: 'Export the document as an e-book (EPUB) to path (a .epub file; an existing file only with overwrite true, otherwise io_error with details.code file_exists). layout is required: reflowable (text reflows to the reader\'s screen and font size; for text-led books) or fixed_layout (every page keeps its layout; for picture books, comics, heavily designed pages). Options apply to this call only and are restored afterwards: epub_version 2 or 3 (reflowable; fixed layout is always EPUB 3), cover none | first_page | image (with cover_image_path, a JPEG, PNG or GIF that must exist), toc_style (an existing TOC style, see list_toc_styles and define_toc_style – it builds the EPUB navigation; without it the navigation lists only file names), image_resolution 72 | 96 | 150 | 300 ppi, image_format automatic | jpeg | png | gif, jpeg_quality low | medium | high | maximum; reflowable only: export_order layout | articles | xml, split_by_paragraph_style (start a new file at each paragraph of this style, e.g. chapter headings), embed_fonts; fixed layout only: page_range (printed page names like export_pdf), spread_control document | physical | synthetic | none, orientation portrait | landscape | auto (InDesign itself writes landscape even for upright pages, which locks reading apps to landscape; the server therefore sets the orientation in the finished file – by default from the page format – and returns orientation_set {value, previous, changed}). metadata {title, creator, publisher, description, subject, rights, date, identifier} goes into the package (an identifier such as urn:isbn:… is added next to InDesign\'s own unique id); the EPUB language comes from the document\'s default language (text defaults), not from a parameter. ' +
|
|
2482
|
+
description: 'Export the document as an e-book (EPUB) to path (a .epub file; an existing file only with overwrite true, otherwise io_error with details.code file_exists). layout is required: reflowable (text reflows to the reader\'s screen and font size; for text-led books) or fixed_layout (every page keeps its layout; for picture books, comics, heavily designed pages). Options apply to this call only and are restored afterwards: epub_version 2 or 3 (reflowable; fixed layout is always EPUB 3), cover none | first_page | image (with cover_image_path, a JPEG, PNG or GIF that must exist), toc_style (an existing TOC style, see list_toc_styles and define_toc_style – it builds the EPUB navigation; without it the navigation lists only file names), image_resolution 72 | 96 | 150 | 300 ppi, image_format automatic | jpeg | png | gif, jpeg_quality low | medium | high | maximum; reflowable only: export_order layout | articles | xml, split_by_paragraph_style (start a new file at each paragraph of this style, e.g. chapter headings – or a list of styles, e.g. part, chapter and appendix headings; settings_used.split_by_paragraph_styles lists them), embed_fonts, image_alignment left | center | right and image_size none | fixed | relative (how images and anchored objects sit in the text flow; objects with their own object export options keep those); fixed layout only: page_range (printed page names like export_pdf), spread_control document | physical | synthetic | none, orientation portrait | landscape | auto (InDesign itself writes landscape even for upright pages, which locks reading apps to landscape; the server therefore sets the orientation in the finished file – by default from the page format – and returns orientation_set {value, previous, changed}). metadata {title, creator, publisher, description, subject, rights, date, identifier} goes into the package (an identifier such as urn:isbn:… is added next to InDesign\'s own unique id); the EPUB language comes from the document\'s default language (text defaults), not from a parameter. ' +
|
|
2341
2483
|
'Returns path, bytes, overwritten, layout, settings_used (the values InDesign exported with), document_language, settings_changed_for_export and document_marked_modified – InDesign marks the document as modified whenever an export setting is set, although the settings are restored; close without saving if nothing else changed. warnings[] name missing title or creator, a missing default language, no TOC style, no cover, objects not anchored in the text flow (reflowable) and fonts that cannot be embedded. Check the document before with check_epub and the file after with check_epub path; for print use export_pdf, for page images export_page_image. Can take minutes on a long book.',
|
|
2342
2484
|
command: 'export_epub',
|
|
2343
2485
|
readOnly: false,
|
|
@@ -2366,8 +2508,16 @@ const TOOLS_S60_EPUB = [
|
|
|
2366
2508
|
cover_image_path: z.string().min(1).optional().describe('Cover image file (JPEG, PNG or GIF) for cover image.'),
|
|
2367
2509
|
toc_style: z.string().min(1).optional().describe('Existing TOC style that builds the EPUB navigation.'),
|
|
2368
2510
|
export_order: z.enum(['layout', 'articles', 'xml']).optional().describe('Reflowable: content order – layout, Articles panel or XML structure.'),
|
|
2369
|
-
split_by_paragraph_style: z
|
|
2511
|
+
split_by_paragraph_style: z
|
|
2512
|
+
.union([
|
|
2513
|
+
z.string().min(1).describe('One paragraph style name.'),
|
|
2514
|
+
z.array(z.string().min(1)).min(1).max(100).describe('Several paragraph style names; each starts a new file (styles based on them do not, list them too).'),
|
|
2515
|
+
])
|
|
2516
|
+
.optional()
|
|
2517
|
+
.describe('Reflowable: start a new content file at every paragraph of this paragraph style, or of any style in a list (e.g. chapter, part and appendix headings).'),
|
|
2370
2518
|
embed_fonts: z.boolean().optional().describe('Reflowable: embed the fonts.'),
|
|
2519
|
+
image_alignment: z.enum(['left', 'center', 'right']).optional().describe('Reflowable: alignment of images and anchored objects in the text flow (Objekt – CSS-Ausrichtung), e.g. center for chapter vignettes. Default: as set in the document.'),
|
|
2520
|
+
image_size: z.enum(['none', 'fixed', 'relative']).optional().describe('Reflowable: CSS size of images – fixed (their size in the layout), relative (relative to the text flow, scales with the reading width) or none. Default: as set in the document.'),
|
|
2371
2521
|
page_range: z.string().min(1).optional().describe('Fixed layout: pages to export by printed page name, e.g. "1-12".'),
|
|
2372
2522
|
spread_control: z.enum(['document', 'physical', 'synthetic', 'none']).optional().describe('Fixed layout: spreads as in the document, physical, synthetic or none.'),
|
|
2373
2523
|
orientation: z.enum(['portrait', 'landscape', 'auto']).optional().describe('Fixed layout: reading orientation written into the EPUB (rendition:orientation). Default: from the page format – portrait for upright pages, landscape for wide pages, auto for square pages.'),
|
|
@@ -2418,7 +2568,112 @@ const TOOLS_S60_EPUB = [
|
|
|
2418
2568
|
},
|
|
2419
2569
|
},
|
|
2420
2570
|
];
|
|
2421
|
-
|
|
2571
|
+
/* A-79 bis A-81 (Sitzung 82, E-117 bis E-121): barrierefreie PDFs – Alternativtext, Lesereihenfolge, Pruefung, interaktiver Export. */
|
|
2572
|
+
const ALT_SOURCES = ['custom', 'xmp_title', 'xmp_description', 'xmp_headline', 'xmp_alt_text', 'xmp_extended_description', 'xmp_other', 'structure', 'decorative'];
|
|
2573
|
+
const TOOLS_S82_ACCESSIBILITY = [
|
|
2574
|
+
{
|
|
2575
|
+
name: 'list_alt_texts',
|
|
2576
|
+
title: 'List alternative texts',
|
|
2577
|
+
description: 'List the image frames (Bildrahmen) of the document with their alternative text (Alternativtext) for an accessible PDF – also anchored and grouped ones – and groups that carry their own alternative text. Each entry: frame_id, kind (image | group), page, on_parent, anchored, in_group, file_name, alt_source (custom, xmp_title, xmp_description, xmp_headline, xmp_alt_text, xmp_extended_description, xmp_other, structure, decorative), alt_text (resolved; "" = none, null = not readable here), xmp_property, actual_text_source, actual_text, tag (from_structure, artifact, based_on_object), covered_by_group_id and problem: missing, decorative_not_artifact (exported as a figure without text), hidden_by_group (a group with its own alternative text swallows the image), unverified (XMP field not readable), hides_children (group) or null. Parent page images only with include_parent_pages true. Returns items[], count, total, truncated, summary {images, missing, artifacts, hidden_by_group, decorative_not_artifact, unverified, groups_with_alt_text}. Read-only; change them with set_alt_text.',
|
|
2578
|
+
command: 'list_alt_texts',
|
|
2579
|
+
readOnly: true,
|
|
2580
|
+
inputShape: {
|
|
2581
|
+
...documentId,
|
|
2582
|
+
page_range: z.string().min(1).optional().describe('Only these pages, by printed page name, e.g. "1-4" or "2, 5". Default all.'),
|
|
2583
|
+
include_parent_pages: z.boolean().optional().describe('Also list images on parent pages (Musterseiten). Default false.'),
|
|
2584
|
+
max_items: z.number().int().min(1).max(5000).optional().describe('Cap for items[]. Default 500.'),
|
|
2585
|
+
},
|
|
2586
|
+
},
|
|
2587
|
+
{
|
|
2588
|
+
name: 'set_alt_text',
|
|
2589
|
+
title: 'Set alternative text and PDF tag type',
|
|
2590
|
+
description: 'Set the object export options for an accessible PDF on one object (frame_id) or many (frame_ids, up to 500, e.g. every image of an issue): source of the alternative text (Alternativtext) – custom with text, an XMP field of the image file (xmp_title, xmp_description, xmp_headline, xmp_alt_text, xmp_extended_description, xmp_other with xmp_property {namespace, path}), structure or decorative –, actual_text ("" removes it) and tag: from_structure, artifact (not read: decorative lines, ornaments, background images) or based_on_object. text alone means source custom. source decorative also sets tag artifact (a decorative image that is no artifact is exported as a figure without text). Works on every page object (image frame, line, rectangle, group, anchored frame). Warnings: alternative text on a group turns the whole group into one figure (texts of its members are lost), artifact on a group has no effect, actual_text on a text frame has no effect, artifact on a text frame hides its text – and its stroke and fill stay untagged anyway (a tagged export marks them as artifacts). All ids are checked before anything changes. Returns items[] as in list_alt_texts and count.',
|
|
2591
|
+
command: 'set_alt_text',
|
|
2592
|
+
readOnly: false,
|
|
2593
|
+
inputShape: {
|
|
2594
|
+
...documentId,
|
|
2595
|
+
frame_id: z.number().int().optional().describe('Object id (frame, line, group).'),
|
|
2596
|
+
frame_ids: z.array(z.number().int()).min(1).max(500).optional().describe('Several object ids; the same settings for all.'),
|
|
2597
|
+
source: z.enum(ALT_SOURCES).optional().describe('Source of the alternative text. Default: custom when text is given, otherwise unchanged.'),
|
|
2598
|
+
text: z.string().min(1).optional().describe('The alternative text (source custom).'),
|
|
2599
|
+
xmp_property: z.object({ namespace: z.string().min(1), path: z.string().min(1) }).strict().optional().describe('XMP field for source xmp_other, e.g. {namespace: "http://purl.org/dc/elements/1.1/", path: "rights[1]"}.'),
|
|
2600
|
+
actual_text: z.string().optional().describe('Actual text (Tatsächlicher Text) read instead of the content, e.g. for a logo; "" removes it.'),
|
|
2601
|
+
tag: z.enum(['from_structure', 'artifact', 'based_on_object']).optional().describe('How the object is tagged in the PDF. artifact = not read. Default: unchanged (artifact with source decorative).'),
|
|
2602
|
+
},
|
|
2603
|
+
},
|
|
2604
|
+
{
|
|
2605
|
+
name: 'list_articles',
|
|
2606
|
+
title: 'List articles (reading order)',
|
|
2607
|
+
description: 'List the articles (Artikel) of the document in their order – they define the reading order of a tagged PDF when use_for_tagged_pdf is true: articles[] {name, index, export, members[] {frame_id, kind, class_name, page, on_parent, story_id}, member_count}, count and use_for_tagged_pdf (Für Lesereihenfolge im getaggten PDF verwenden). A text frame brings its whole story, anchored objects follow their text. include_uncovered true adds uncovered[] {frame_id, kind, page}: text frames, image frames and groups on document pages that are in no article and no artifact (capped at 500, uncovered_total). Read-only.',
|
|
2608
|
+
command: 'list_articles',
|
|
2609
|
+
readOnly: true,
|
|
2610
|
+
inputShape: {
|
|
2611
|
+
...documentId,
|
|
2612
|
+
include_uncovered: z.boolean().optional().describe('Also list content outside every article. Default false.'),
|
|
2613
|
+
},
|
|
2614
|
+
},
|
|
2615
|
+
{
|
|
2616
|
+
name: 'define_article',
|
|
2617
|
+
title: 'Define an article (reading order)',
|
|
2618
|
+
description: 'Create an article (Artikel) or replace its members: name and frame_ids in reading order (a new article needs them; for an existing one they replace all members). One text frame brings its whole story. Anchored objects are rejected (invalid_argument, details.code anchored_object – they follow their text anyway), an id named twice too (details.code duplicate_frame_id); objects on parent pages, objects already in another article and frames of a story listed twice give a warning. position start | end | before | after (with relative_to, another article) orders the articles; export (default true for a new article) includes it in the export. use_for_tagged_pdf (default true) switches the document setting „Für Lesereihenfolge im getaggten PDF verwenden“ on – without it articles do not change the PDF; false switches it off for the whole document. Returns article {name, index, export, members[]}, created, use_for_tagged_pdf, use_for_tagged_pdf_changed and article_names[].',
|
|
2619
|
+
command: 'define_article',
|
|
2620
|
+
readOnly: false,
|
|
2621
|
+
inputShape: {
|
|
2622
|
+
...documentId,
|
|
2623
|
+
name: z.string().min(1).describe('Article name; an existing article of this name is changed.'),
|
|
2624
|
+
frame_ids: z.array(z.number().int()).min(1).max(1000).optional().describe('Object ids in reading order (text frames, image frames, groups). Required for a new article.'),
|
|
2625
|
+
position: z.enum(['start', 'end', 'before', 'after']).optional().describe('Where the article goes among the articles. Default: new ones at the end, existing ones stay.'),
|
|
2626
|
+
relative_to: z.string().min(1).optional().describe('The other article for position before or after.'),
|
|
2627
|
+
export: z.boolean().optional().describe('Include the article in the export. Default true for a new article, otherwise unchanged.'),
|
|
2628
|
+
use_for_tagged_pdf: z.boolean().optional().describe('Use the articles for the reading order of a tagged PDF (document setting). Default true.'),
|
|
2629
|
+
},
|
|
2630
|
+
},
|
|
2631
|
+
{
|
|
2632
|
+
name: 'delete_article',
|
|
2633
|
+
title: 'Delete an article',
|
|
2634
|
+
description: 'Delete an article (Artikel) by name; its objects stay in the layout. Unknown names are not_found with the available names. A warning comes when no article is left while the tagged PDF is still set to use articles. Returns deleted, article_names[], count and use_for_tagged_pdf.',
|
|
2635
|
+
command: 'delete_article',
|
|
2636
|
+
readOnly: false,
|
|
2637
|
+
inputShape: {
|
|
2638
|
+
...documentId,
|
|
2639
|
+
name: z.string().min(1).describe('Name of the article to delete.'),
|
|
2640
|
+
},
|
|
2641
|
+
},
|
|
2642
|
+
{
|
|
2643
|
+
name: 'check_accessibility',
|
|
2644
|
+
title: 'Check accessibility for PDF',
|
|
2645
|
+
description: 'Check the document for an accessible (tagged) PDF before export. Read-only. Findings {check, severity error | warning, page, object_id, style, hint}: alt_text_missing (error), decorative_not_artifact (error), alt_text_hidden_by_group, alt_text_unverified, group_artifact_no_effect, parent_page_image (warnings); path_not_tagged (error: text frames with stroke or fill and tables with cell strokes, which InDesign writes as untagged paths – reported only with artifact_untagged_paths false – a tagged export marks them as artifacts by default); table_without_header_row (warning), table_header_scope (warning before InDesign 2026); style_without_pdf_tag (error for used paragraph styles that look like headings, by name or because their parent style has a heading tag – tags are not inherited); document_title_missing, text_language_missing, pdf_language_missing, pdf_language_invalid (errors; the PDF language is checked as given in pdf_language, otherwise from the preset or the export settings that export_pdf or – with interactive true – export_interactive_pdf would use); no_articles, item_outside_articles (warnings) and articles_not_used_for_pdf (error). Returns passed (no error), errors, warnings, findings[], findings_total, findings_truncated (max_findings, default 200), summary {images, images_ok, tables, objects_with_untagged_paths, paragraph_styles_used, styles_without_pdf_tag[], document_title, text_language, pdf_language, pdf_language_source, articles, use_for_tagged_pdf} and manual_steps[] – what only a person or Acrobat can do (captions bound to figures, complex tables, contrast, a check with a PDF/UA checker and a screen reader). export_pdf and export_interactive_pdf with pdfua_identifier true run this same check and add the PDF/UA identifier only when it reports no error.',
|
|
2646
|
+
command: 'check_accessibility',
|
|
2647
|
+
readOnly: true,
|
|
2648
|
+
timeoutMs: 300_000,
|
|
2649
|
+
inputShape: {
|
|
2650
|
+
...documentId,
|
|
2651
|
+
pdf_language: z.string().min(1).optional().describe('The PDF language planned for the export (checked like in export_pdf).'),
|
|
2652
|
+
preset: z.string().optional().describe('The PDF preset planned for export_pdf (for its language). Default: the localized "High Quality Print".'),
|
|
2653
|
+
interactive: z.boolean().optional().describe('Planned export is export_interactive_pdf (language from its export settings). Default false.'),
|
|
2654
|
+
artifact_untagged_paths: z.boolean().optional().describe('As planned for the export: true (default, as a tagged export does) – untagged paths will be marked as artifacts and path_not_tagged is not reported; false – they stay untagged and are reported as errors.'),
|
|
2655
|
+
max_findings: z.number().int().min(1).max(1000).optional().describe('Cap for findings. Default 200.'),
|
|
2656
|
+
},
|
|
2657
|
+
},
|
|
2658
|
+
{
|
|
2659
|
+
name: 'export_interactive_pdf',
|
|
2660
|
+
title: 'Export as interactive PDF',
|
|
2661
|
+
description: 'Export the document (or a page_range, printed page names like export_pdf) as an interactive PDF (PDF (Interaktiv): links, bookmarks and buttons work; RGB; no presets) to path. Options for this call only, the export settings are restored afterwards: tagged (Struktur), tab_order_from_structure (Tab-Reihenfolge aus der Struktur; default true with tagged true), display_title, pdf_language (checked), title (written into the document), artifact_untagged_paths (default true with tagged true) and pdfua_identifier as in export_pdf (the identifier only after a check_accessibility without error, otherwise invalid_state with details.code accessibility_check_failed). Returns path, exported_page_count, document_page_count, bytes, page_range_used, settings_used {tagged, tab_order_from_structure, display_title, pdf_language}, tagged, display_title, pdf_language_used, pdf_language_source, title_set, pdfua_check, pdfua_identifier_requested, artifact_untagged_paths_requested, and after a tagged export untagged_paths {found, marked} and pdfua_identifier_set. For print use export_pdf.',
|
|
2662
|
+
command: 'export_interactive_pdf',
|
|
2663
|
+
readOnly: false,
|
|
2664
|
+
timeoutMs: 900_000,
|
|
2665
|
+
after: accessiblePdfAfter,
|
|
2666
|
+
inputShape: {
|
|
2667
|
+
...documentId,
|
|
2668
|
+
path: z.string().min(1).describe('Required. Target .pdf path on the machine running InDesign.'),
|
|
2669
|
+
page_range: z.string().optional().describe('Pages to export, by printed page name, e.g. "6-8". Default all.'),
|
|
2670
|
+
tagged: taggedParam,
|
|
2671
|
+
tab_order_from_structure: z.boolean().optional().describe('Tab order of links and form fields follows the structure (/Tabs /S). Default true with tagged true, otherwise as set.'),
|
|
2672
|
+
...accessiblePdfParams,
|
|
2673
|
+
},
|
|
2674
|
+
},
|
|
2675
|
+
];
|
|
2676
|
+
TOOLS.push(...TOOLS_S10_VIEW, ...TOOLS_A7, ...TOOLS_A8, ...TOOLS_A8_GRADIENTS, ...TOOLS_A8_EFFECTS, ...TOOLS_A8_OUTLINES, ...TOOLS_A9, ...TOOLS_A2, ...TOOLS_B2, ...TOOLS_C, ...TOOLS_D, ...TOOLS_E, ...TOOLS_F, ...TOOLS_G, ...TOOLS_H, ...TOOLS_J, ...TOOLS_J8, ...TOOLS_J8_TABLES, ...TOOLS_J8_OBJECT_STYLES, ...TOOLS_J8_ANCHOR, ...TOOLS_J8_IMPORT, ...TOOLS_J8_SECTIONS, ...TOOLS_J8_SETUP, ...TOOLS_J8_VARIABLES, ...TOOLS_J8_SAVE, ...TOOLS_J8_ALIGN, ...TOOLS_J8_SELECTION, ...TOOLS_J8_EMBED, ...TOOLS_S42_TOC_INDEX, ...TOOLS_A43_PRINT_ON_DEMAND, ...TOOLS_S60_EPUB, ...TOOLS_S82_ACCESSIBILITY);
|
|
2422
2677
|
export function toolByName(name) {
|
|
2423
2678
|
return TOOLS.find((tool) => tool.name === name);
|
|
2424
2679
|
}
|
|
@@ -21,7 +21,7 @@ function isRule(value) {
|
|
|
21
21
|
Array.isArray(r['locales']) &&
|
|
22
22
|
typeof r['category'] === 'string' &&
|
|
23
23
|
typeof r['severity'] === 'string' &&
|
|
24
|
-
(r['kind'] === 'grep' || r['kind'] === 'lines') &&
|
|
24
|
+
(r['kind'] === 'grep' || r['kind'] === 'lines' || r['kind'] === 'language') &&
|
|
25
25
|
(r['kind'] === 'grep' ? typeof r['pattern'] === 'string' : typeof r['check'] === 'string') &&
|
|
26
26
|
typeof r['message'] === 'string' &&
|
|
27
27
|
typeof r['suggestion'] === 'string' &&
|