layoutbridge-light 0.0.0-stage → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +105 -0
- package/LICENSE +26 -0
- package/README.de.md +367 -0
- package/README.md +353 -2
- package/THIRD-PARTY-NOTICES.md +2878 -0
- package/dist/src/mcp/catalog.js +131 -0
- package/dist/src/mcp/config.js +211 -0
- package/dist/src/mcp/content-credentials.js +65 -0
- package/dist/src/mcp/dispatch.js +171 -0
- package/dist/src/mcp/epub-check.js +331 -0
- package/dist/src/mcp/epub-orientation.js +132 -0
- package/dist/src/mcp/license/free-tools.js +16 -0
- package/dist/src/mcp/license/gate.js +210 -0
- package/dist/src/mcp/license/index.js +107 -0
- package/dist/src/mcp/license/instance-name.js +57 -0
- package/dist/src/mcp/license/key-source.js +59 -0
- package/dist/src/mcp/license/lemonsqueezy-verifier.js +207 -0
- package/dist/src/mcp/license/placeholder-verifier.js +10 -0
- package/dist/src/mcp/license/polar-ids.js +100 -0
- package/dist/src/mcp/license/polar-verifier.js +285 -0
- package/dist/src/mcp/license/product-ids.js +73 -0
- package/dist/src/mcp/license/state-store.js +91 -0
- package/dist/src/mcp/license/types.js +11 -0
- package/dist/src/mcp/logging.js +271 -0
- package/dist/src/mcp/pdf-postprocess.js +798 -0
- package/dist/src/mcp/product-info.js +54 -0
- package/dist/src/mcp/product.js +56 -0
- package/dist/src/mcp/server.js +253 -0
- package/dist/src/mcp/setup.js +680 -0
- package/dist/src/mcp/start.cjs +117 -0
- package/dist/src/mcp/target-folder.js +25 -0
- package/dist/src/mcp/tool-definition.js +2 -0
- package/dist/src/mcp/tools.js +2680 -0
- package/dist/src/mcp/typography-rules.js +70 -0
- package/dist/src/transport/com.js +436 -0
- package/dist/src/transport/osascript.js +171 -0
- package/dist/src/transport/queue.js +19 -0
- package/dist/src/transport/script-bundle.js +92 -0
- package/dist/src/transport/transport.js +52 -0
- package/indesign/commands/10-app.js +6 -0
- package/indesign/commands/20-documents.js +517 -0
- package/indesign/commands/22-document-setup.js +204 -0
- package/indesign/commands/23-save-package.js +258 -0
- package/indesign/commands/25-export.js +695 -0
- package/indesign/commands/26-export-image.js +202 -0
- package/indesign/commands/27-textdefaults.js +151 -0
- package/indesign/commands/28-selection.js +174 -0
- package/indesign/commands/30-pages.js +1032 -0
- package/indesign/commands/31-view.js +310 -0
- package/indesign/commands/32-sections.js +203 -0
- package/indesign/commands/35-parents.js +448 -0
- package/indesign/commands/37-layout.js +837 -0
- package/indesign/commands/40-frames.js +886 -0
- package/indesign/commands/41-shapes.js +505 -0
- package/indesign/commands/42-groups.js +117 -0
- package/indesign/commands/43-layers.js +310 -0
- package/indesign/commands/44-effects.js +274 -0
- package/indesign/commands/45-frame-options.js +247 -0
- package/indesign/commands/47-anchored.js +473 -0
- package/indesign/commands/50-modify.js +803 -0
- package/indesign/commands/52-align.js +139 -0
- package/indesign/commands/55-fit.js +106 -0
- package/indesign/commands/60-images.js +1154 -0
- package/indesign/commands/62-embed.js +120 -0
- package/indesign/commands/69-placeholders.js +132 -0
- package/indesign/commands/70-text.js +710 -0
- package/indesign/commands/71-outlines.js +92 -0
- package/indesign/commands/72-place-text.js +476 -0
- package/indesign/commands/73-story-lock.js +157 -0
- package/indesign/commands/74-stories.js +121 -0
- package/indesign/commands/75-tables.js +702 -0
- package/indesign/commands/76-text-variables.js +260 -0
- package/indesign/commands/77-story-options.js +86 -0
- package/indesign/commands/78-frame-lines.js +511 -0
- package/indesign/commands/79-check-typography.js +480 -0
- package/indesign/commands/80-styles.js +1960 -0
- package/indesign/commands/81-composition.js +355 -0
- package/indesign/commands/82-object-styles.js +263 -0
- package/indesign/commands/83-drop-caps.js +87 -0
- package/indesign/commands/83-indents-tabs.js +264 -0
- package/indesign/commands/84-import-styles.js +142 -0
- package/indesign/commands/85-swatches.js +112 -0
- package/indesign/commands/86-gradients.js +185 -0
- package/indesign/commands/87-replace-swatch.js +180 -0
- package/indesign/commands/88-replace-font.js +212 -0
- package/indesign/commands/89-toc-index.js +1002 -0
- package/indesign/commands/90-print-on-demand.js +495 -0
- package/indesign/commands/91-epub.js +629 -0
- package/indesign/commands/92-accessibility.js +1131 -0
- package/indesign/interpreter.js +829 -0
- package/package.json +41 -4
- package/rules/typography-rules.json +32 -0
|
@@ -0,0 +1,629 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* A-45 Punkt 1 (Sitzung 60) – E-Book: export_epub und check_epub
|
|
3
|
+
* (Dokumentteil; die Pruefung der fertigen Datei laeuft ohne InDesign im
|
|
4
|
+
* Server, src/mcp/epub-check.ts). Grundlage: ExtendScript-Probe an
|
|
5
|
+
* InDesign 21.6 am 23.10.2026 (docs/EPUB-ANFORDERUNGEN.md, Teil b): die
|
|
6
|
+
* Exporteinstellungen haengen am Dokument (doc.epubExportPreferences,
|
|
7
|
+
* doc.epubFixedLayoutExportPreferences), es gibt keine auf Anwendungsebene.
|
|
8
|
+
* Jede gesetzte Einstellung markiert das Dokument als geaendert, auch wenn
|
|
9
|
+
* sie danach zurueckgestellt wird (E-101). Unbekannte Namen fuer
|
|
10
|
+
* Inhaltsverzeichnis-Formate und fehlende Coverdateien nimmt InDesign
|
|
11
|
+
* stillschweigend an – beides wird hier vorher geprueft.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/* ------------------------------------------------------------ Hilfen */
|
|
15
|
+
|
|
16
|
+
function idcEpubAvailable() {
|
|
17
|
+
if (typeof EpubVersion === 'undefined' || typeof EpubCover === 'undefined' || typeof ExportFormat === 'undefined'
|
|
18
|
+
|| typeof EpubFixedLayoutSpreadControl === 'undefined' || typeof EpubNavigationStyle === 'undefined'
|
|
19
|
+
|| ExportFormat.EPUB === undefined || ExportFormat.FIXED_LAYOUT_EPUB === undefined) {
|
|
20
|
+
IDC.fail('invalid_state', 'This InDesign version offers no EPUB export through scripting.', { code: 'epub_not_available' });
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/* Zuordnungen Parameterwert -> Aufzaehlungswert (Namen laut Probe InDesign 21.6). */
|
|
25
|
+
function idcEpubTables() {
|
|
26
|
+
return {
|
|
27
|
+
version: { '2': EpubVersion.EPUB2, '3': EpubVersion.EPUB3 },
|
|
28
|
+
cover: { none: EpubCover.NONE, first_page: EpubCover.FIRST_PAGE, image: EpubCover.EXTERNAL_IMAGE },
|
|
29
|
+
order: { layout: ExportOrder.LAYOUT_ORDER, articles: ExportOrder.ARTICLE_PANEL_ORDER, xml: ExportOrder.XML_STRUCTURE_ORDER },
|
|
30
|
+
resolution: { '72': ImageResolution.PPI_72, '96': ImageResolution.PPI_96, '150': ImageResolution.PPI_150, '300': ImageResolution.PPI_300 },
|
|
31
|
+
format: { automatic: ImageConversion.AUTOMATIC, jpeg: ImageConversion.JPEG, png: ImageConversion.PNG, gif: ImageConversion.GIF },
|
|
32
|
+
/* A-68 (8), Sitzung 81: Ausrichtung und Groesse der Objekte (Probe 11.11.2026). */
|
|
33
|
+
alignment: typeof ImageAlignmentType === 'undefined' ? {} : { left: ImageAlignmentType.ALIGN_LEFT, center: ImageAlignmentType.ALIGN_CENTER, right: ImageAlignmentType.ALIGN_RIGHT },
|
|
34
|
+
size: typeof ImageSizeOption === 'undefined' ? {} : { none: ImageSizeOption.SIZE_NONE, fixed: ImageSizeOption.SIZE_FIXED, relative: ImageSizeOption.SIZE_RELATIVE_TO_TEXT_FLOW },
|
|
35
|
+
quality: { low: JPEGOptionsQuality.LOW, medium: JPEGOptionsQuality.MEDIUM, high: JPEGOptionsQuality.HIGH, maximum: JPEGOptionsQuality.MAXIMUM },
|
|
36
|
+
spread: { document: EpubFixedLayoutSpreadControl.SPREADS_BASED_ON_DOC, physical: EpubFixedLayoutSpreadControl.PHYSICAL_SPREADS,
|
|
37
|
+
synthetic: EpubFixedLayoutSpreadControl.SYNTHETIC_SPREADS, none: EpubFixedLayoutSpreadControl.NO_SPREADS },
|
|
38
|
+
navigation: { none: EpubNavigationStyle.NO_NAVIGATION, file_names: EpubNavigationStyle.FILENAME_NAVIGATION,
|
|
39
|
+
toc_style: EpubNavigationStyle.TOC_STYLE_NAVIGATION, bookmarks: EpubNavigationStyle.BOOKMARKS_NAVIGATION }
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/* Parameterwert zu einem gelesenen Aufzaehlungswert; unbekannt = Zeichenkette des Werts. */
|
|
44
|
+
function idcEpubNameOf(value, table) {
|
|
45
|
+
var k;
|
|
46
|
+
for (k in table) { if (table.hasOwnProperty(k) && Number(table[k]) === Number(value)) { return k; } }
|
|
47
|
+
try { return String(value); } catch (e) { return null; }
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/* Waehlt aus einer Zuordnung {wert: Aufzaehlungswert}; unbekannt = invalid_argument. */
|
|
51
|
+
function idcEpubPick(key, value, table) {
|
|
52
|
+
var k;
|
|
53
|
+
var names = [];
|
|
54
|
+
for (k in table) { if (table.hasOwnProperty(k)) { names.push(k); } }
|
|
55
|
+
if (!table.hasOwnProperty(String(value))) {
|
|
56
|
+
IDC.fail('invalid_argument', key + ' must be one of ' + names.join(', ') + '.', { value: value });
|
|
57
|
+
}
|
|
58
|
+
return table[String(value)];
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/*
|
|
62
|
+
* Setzt eine Einstellung nur, wenn sie sich unterscheidet, und merkt den
|
|
63
|
+
* alten Wert zum Zurueckstellen. Vergleich ueber Number() fuer
|
|
64
|
+
* Aufzaehlungen und Zahlen, sonst als Zeichenkette.
|
|
65
|
+
*/
|
|
66
|
+
function idcEpubSet(prefs, key, value, changes) {
|
|
67
|
+
var old = prefs[key];
|
|
68
|
+
var same;
|
|
69
|
+
if (typeof value === 'string') { same = String(old) === value; }
|
|
70
|
+
else if (typeof value === 'boolean') { same = old === value; }
|
|
71
|
+
else { same = Number(old) === Number(value); }
|
|
72
|
+
if (same) { return; }
|
|
73
|
+
changes.push({ prefs: prefs, key: key, old: old });
|
|
74
|
+
prefs[key] = value;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function idcEpubRestore(changes, problems) {
|
|
78
|
+
var i, c;
|
|
79
|
+
for (i = changes.length - 1; i >= 0; i--) {
|
|
80
|
+
c = changes[i];
|
|
81
|
+
try { c.prefs[c.key] = c.old; } catch (e) { problems.push(c.key + ': ' + String(e.message ? e.message : e)); }
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function idcEpubTocStyleNames(doc) {
|
|
86
|
+
var names = [];
|
|
87
|
+
var i;
|
|
88
|
+
try { for (i = 0; i < doc.tocStyles.length; i++) { names.push(String(doc.tocStyles.item(i).name)); } } catch (e) { /* keine */ }
|
|
89
|
+
return names;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function idcEpubHasName(list, name) {
|
|
93
|
+
var i;
|
|
94
|
+
for (i = 0; i < list.length; i++) { if (list[i] === name) { return true; } }
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function idcEpubLanguage(doc) {
|
|
99
|
+
try { return String(doc.textDefaults.appliedLanguage.name); } catch (e) { return null; }
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/* "[Keine Sprache]" / "[No Language]": eckige Klammer = keine Sprache (InDesign-Namensregel fuer Grundeintraege). */
|
|
103
|
+
function idcEpubLanguageMissing(name) {
|
|
104
|
+
return name === null || name === '' || name.charAt(0) === '[';
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/* Seitenobjekte oberster Ebene einer Seite (verankerte Objekte stecken im Text, nicht hier). */
|
|
108
|
+
function idcEpubTopItems(page) {
|
|
109
|
+
var out = [];
|
|
110
|
+
var i, items;
|
|
111
|
+
try { items = page.pageItems; } catch (e) { return out; }
|
|
112
|
+
/* A-68 Befund, Sitzung 81: pageItems liefert allgemeine PageItem-Objekte; ein
|
|
113
|
+
Textrahmen mit verankerter Vignette galt so als nicht verankertes Objekt
|
|
114
|
+
(Klasse PageItem, Inhalt ueber allGraphics). Deshalb die konkrete Klasse. */
|
|
115
|
+
for (i = 0; i < items.length; i++) { out.push(IDC.concrete(items.item(i))); }
|
|
116
|
+
return out;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function idcEpubItemHasContent(item) {
|
|
120
|
+
var cls = IDC.className(item);
|
|
121
|
+
if (cls === 'TextFrame') {
|
|
122
|
+
try { return String(item.parentStory.contents).length > 0; } catch (e) { return true; }
|
|
123
|
+
}
|
|
124
|
+
try { if (item.allGraphics && item.allGraphics.length > 0) { return true; } } catch (e2) { /* weiter */ }
|
|
125
|
+
return cls === 'Group';
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/* A-77: split_by_paragraph_style als Name oder Liste -> Liste ohne Doppelte. */
|
|
129
|
+
function idcEpubSplitNames(value) {
|
|
130
|
+
var list = [], out = [], i, j, seen;
|
|
131
|
+
if (IDC.isArray(value)) { list = value; } else { list = [value]; }
|
|
132
|
+
if (list.length === 0) { IDC.fail('invalid_argument', 'split_by_paragraph_style must name at least one paragraph style.', null); }
|
|
133
|
+
for (i = 0; i < list.length; i++) {
|
|
134
|
+
if (typeof list[i] !== 'string' || list[i].length === 0) {
|
|
135
|
+
IDC.fail('invalid_argument', 'split_by_paragraph_style must be a paragraph style name or a list of names.', { value: list[i] });
|
|
136
|
+
}
|
|
137
|
+
seen = false;
|
|
138
|
+
for (j = 0; j < out.length; j++) { if (out[j] === list[i]) { seen = true; } }
|
|
139
|
+
if (!seen) { out.push(list[i]); }
|
|
140
|
+
}
|
|
141
|
+
return out;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/* Alle Absatzformate und welche davon teilen sollen; fehlende Namen = not_found (alle auf einmal). */
|
|
145
|
+
function idcEpubSplitStyles(doc, names) {
|
|
146
|
+
var all = [], chosen = [], missing = [], found, i, k, coll;
|
|
147
|
+
try { coll = doc.allParagraphStyles; } catch (e) { coll = []; }
|
|
148
|
+
for (i = 0; i < coll.length; i++) { all.push(coll[i]); chosen.push(false); }
|
|
149
|
+
for (k = 0; k < names.length; k++) {
|
|
150
|
+
found = false;
|
|
151
|
+
for (i = 0; i < all.length; i++) {
|
|
152
|
+
if (String(all[i].name) === names[k]) { chosen[i] = true; found = true; }
|
|
153
|
+
}
|
|
154
|
+
if (!found) { missing.push(names[k]); }
|
|
155
|
+
}
|
|
156
|
+
if (missing.length > 0) {
|
|
157
|
+
IDC.fail('not_found', 'Paragraph style(s) not in this document: ' + missing.join(', ') + '.',
|
|
158
|
+
{ code: 'paragraph_style_not_found', paragraph_style: missing[0], missing: missing });
|
|
159
|
+
}
|
|
160
|
+
return { all: all, chosen: chosen };
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/* Womit geteilt wird: null ohne Teilung, sonst die Formatnamen (ein Name oder die Exporttags). */
|
|
164
|
+
function idcEpubSplitUsed(doc, prefs) {
|
|
165
|
+
var out = [], coll, i;
|
|
166
|
+
if (prefs.breakDocument !== true) { return null; }
|
|
167
|
+
if (String(prefs.paragraphStyleName) !== '') { return [String(prefs.paragraphStyleName)]; }
|
|
168
|
+
try { coll = doc.allParagraphStyles; } catch (e) { coll = []; }
|
|
169
|
+
for (i = 0; i < coll.length; i++) {
|
|
170
|
+
try { if (coll[i].splitDocument === true) { out.push(String(coll[i].name)); } } catch (e2) { /* weiter */ }
|
|
171
|
+
}
|
|
172
|
+
return out;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/* ------------------------------------------------------------ export_epub */
|
|
176
|
+
|
|
177
|
+
IDC.register('export_epub', { needs_document: true, read_only: false, ruler: 'none' },
|
|
178
|
+
function (ctx) {
|
|
179
|
+
var args = ctx.args;
|
|
180
|
+
var doc = ctx.doc;
|
|
181
|
+
var fixed, prefs, file, existed, overwrite, changes = [], problems = [], used = {}, meta, key, value;
|
|
182
|
+
var tocNames, coverMode, coverFile, bytes, modifiedBefore, language, i, j, items, item, landing, unanchored = 0, fonts, f, font, status;
|
|
183
|
+
var splitNames = null, splitStyles = null;
|
|
184
|
+
|
|
185
|
+
idcEpubAvailable();
|
|
186
|
+
var t = idcEpubTables();
|
|
187
|
+
if (typeof args.path !== 'string' || args.path.length === 0) {
|
|
188
|
+
IDC.fail('invalid_argument', 'path is required (the target .epub file).', null);
|
|
189
|
+
}
|
|
190
|
+
if (!/\.epub$/i.test(args.path)) {
|
|
191
|
+
IDC.fail('invalid_argument', 'path must end in .epub.', { path: args.path });
|
|
192
|
+
}
|
|
193
|
+
if (args.layout !== 'reflowable' && args.layout !== 'fixed_layout') {
|
|
194
|
+
IDC.fail('invalid_argument', 'layout must be reflowable or fixed_layout.', { value: args.layout });
|
|
195
|
+
}
|
|
196
|
+
fixed = args.layout === 'fixed_layout';
|
|
197
|
+
file = IDC.fileFor(args.path);
|
|
198
|
+
if (!IDC.fileParentExists(file)) {
|
|
199
|
+
IDC.fail('io_error', 'The folder for the target path does not exist: ' + args.path, { path: args.path });
|
|
200
|
+
}
|
|
201
|
+
overwrite = args.overwrite === true;
|
|
202
|
+
existed = file.exists === true;
|
|
203
|
+
if (existed && !overwrite) {
|
|
204
|
+
IDC.fail('io_error', 'A file exists at path already; pass overwrite true to replace it.', { code: 'file_exists', path: args.path });
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
prefs = fixed ? doc.epubFixedLayoutExportPreferences : doc.epubExportPreferences;
|
|
208
|
+
modifiedBefore = doc.modified === true;
|
|
209
|
+
|
|
210
|
+
/* Argumente pruefen, bevor irgendetwas gesetzt wird. */
|
|
211
|
+
if (args.epub_version !== undefined && fixed) {
|
|
212
|
+
ctx.warn('epub_version applies to reflowable EPUB only; a fixed-layout EPUB is always EPUB 3.');
|
|
213
|
+
}
|
|
214
|
+
if (args.export_order !== undefined && fixed) { ctx.warn('export_order applies to reflowable EPUB only and was ignored.'); }
|
|
215
|
+
if (args.split_by_paragraph_style !== undefined && fixed) { ctx.warn('split_by_paragraph_style applies to reflowable EPUB only and was ignored.'); }
|
|
216
|
+
if (args.embed_fonts !== undefined && fixed) { ctx.warn('embed_fonts applies to reflowable EPUB only; a fixed-layout EPUB embeds the fonts.'); }
|
|
217
|
+
if ((args.image_alignment !== undefined || args.image_size !== undefined) && fixed) {
|
|
218
|
+
ctx.warn('image_alignment and image_size apply to reflowable EPUB only and were ignored.');
|
|
219
|
+
}
|
|
220
|
+
if ((args.page_range !== undefined || args.spread_control !== undefined) && !fixed) {
|
|
221
|
+
ctx.warn('page_range and spread_control apply to fixed-layout EPUB only and were ignored.');
|
|
222
|
+
}
|
|
223
|
+
if (args.orientation !== undefined && !fixed) {
|
|
224
|
+
ctx.warn('orientation applies to fixed-layout EPUB only and was ignored.');
|
|
225
|
+
}
|
|
226
|
+
if (args.orientation !== undefined && args.orientation !== 'portrait' && args.orientation !== 'landscape' && args.orientation !== 'auto') {
|
|
227
|
+
IDC.fail('invalid_argument', 'orientation must be portrait, landscape or auto.', { value: args.orientation });
|
|
228
|
+
}
|
|
229
|
+
tocNames = idcEpubTocStyleNames(doc);
|
|
230
|
+
if (args.toc_style !== undefined && !idcEpubHasName(tocNames, String(args.toc_style))) {
|
|
231
|
+
IDC.fail('not_found', 'TOC style "' + args.toc_style + '" does not exist in this document (list_toc_styles).',
|
|
232
|
+
{ code: 'toc_style_not_found', toc_style: args.toc_style, available: tocNames });
|
|
233
|
+
}
|
|
234
|
+
if (args.split_by_paragraph_style !== undefined && !fixed) {
|
|
235
|
+
splitNames = idcEpubSplitNames(args.split_by_paragraph_style);
|
|
236
|
+
if (splitNames.length === 1) {
|
|
237
|
+
var splitStyle = null;
|
|
238
|
+
try { splitStyle = doc.paragraphStyles.itemByName(splitNames[0]); } catch (eS) { splitStyle = null; }
|
|
239
|
+
if (splitStyle === null || splitStyle.isValid !== true) { splitStyle = IDC.paragraphStyleByName(doc, splitNames[0]); }
|
|
240
|
+
if (splitStyle === null || splitStyle.isValid !== true) {
|
|
241
|
+
IDC.fail('not_found', 'Paragraph style "' + splitNames[0] + '" does not exist in this document.',
|
|
242
|
+
{ code: 'paragraph_style_not_found', paragraph_style: splitNames[0] });
|
|
243
|
+
}
|
|
244
|
+
} else {
|
|
245
|
+
splitStyles = idcEpubSplitStyles(doc, splitNames);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
coverMode = args.cover === undefined ? null : String(args.cover);
|
|
249
|
+
if (coverMode !== null && coverMode !== 'none' && coverMode !== 'first_page' && coverMode !== 'image') {
|
|
250
|
+
IDC.fail('invalid_argument', 'cover must be none, first_page or image.', { value: args.cover });
|
|
251
|
+
}
|
|
252
|
+
if (coverMode === 'image') {
|
|
253
|
+
if (typeof args.cover_image_path !== 'string' || args.cover_image_path.length === 0) {
|
|
254
|
+
IDC.fail('invalid_argument', 'cover image requires cover_image_path.', null);
|
|
255
|
+
}
|
|
256
|
+
coverFile = IDC.fileFor(args.cover_image_path);
|
|
257
|
+
if (coverFile.exists !== true) {
|
|
258
|
+
IDC.fail('not_found', 'The cover image does not exist: ' + args.cover_image_path, { code: 'cover_image_not_found', path: args.cover_image_path });
|
|
259
|
+
}
|
|
260
|
+
if (!/\.(jpe?g|png|gif)$/i.test(args.cover_image_path)) {
|
|
261
|
+
ctx.warn('The cover image is not JPEG, PNG or GIF; reading systems may not show it.');
|
|
262
|
+
}
|
|
263
|
+
} else if (args.cover_image_path !== undefined) {
|
|
264
|
+
ctx.warn('cover_image_path is used only with cover image and was ignored.');
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
try {
|
|
268
|
+
/* Version, Cover, Inhaltsverzeichnis */
|
|
269
|
+
if (args.epub_version !== undefined && !fixed) {
|
|
270
|
+
idcEpubSet(prefs, 'version', idcEpubPick('epub_version', args.epub_version, t.version), changes);
|
|
271
|
+
}
|
|
272
|
+
if (coverMode !== null) {
|
|
273
|
+
if (coverMode === 'image') { idcEpubSet(prefs, 'coverImageFile', IDC.fsPath(coverFile), changes); }
|
|
274
|
+
idcEpubSet(prefs, 'epubCover', idcEpubPick('cover', coverMode, t.cover), changes);
|
|
275
|
+
}
|
|
276
|
+
if (args.toc_style !== undefined) {
|
|
277
|
+
idcEpubSet(prefs, 'tocStyleName', String(args.toc_style), changes);
|
|
278
|
+
if (fixed) { idcEpubSet(prefs, 'epubNavigationStyles', t.navigation.toc_style, changes); }
|
|
279
|
+
}
|
|
280
|
+
/* Nur reflowable */
|
|
281
|
+
if (!fixed) {
|
|
282
|
+
if (args.export_order !== undefined) {
|
|
283
|
+
idcEpubSet(prefs, 'exportOrder', idcEpubPick('export_order', args.export_order, t.order), changes);
|
|
284
|
+
}
|
|
285
|
+
if (args.split_by_paragraph_style !== undefined && splitStyles === null) {
|
|
286
|
+
idcEpubSet(prefs, 'breakDocument', true, changes);
|
|
287
|
+
idcEpubSet(prefs, 'paragraphStyleName', splitNames[0], changes);
|
|
288
|
+
} else if (splitStyles !== null) {
|
|
289
|
+
/* A-77: mehrere Formate ueber die Exporttags (splitDocument) der
|
|
290
|
+
Absatzformate; InDesign teilt danach nur bei leerem
|
|
291
|
+
paragraphStyleName (Probe 11.11.2026). Genau die genannten
|
|
292
|
+
Formate teilen, alle anderen voruebergehend nicht. */
|
|
293
|
+
for (i = 0; i < splitStyles.all.length; i++) {
|
|
294
|
+
idcEpubSet(splitStyles.all[i], 'splitDocument', splitStyles.chosen[i] === true, changes);
|
|
295
|
+
}
|
|
296
|
+
idcEpubSet(prefs, 'breakDocument', true, changes);
|
|
297
|
+
idcEpubSet(prefs, 'paragraphStyleName', '', changes);
|
|
298
|
+
}
|
|
299
|
+
if (args.embed_fonts !== undefined) { idcEpubSet(prefs, 'embedFont', args.embed_fonts === true, changes); }
|
|
300
|
+
if (args.image_alignment !== undefined) {
|
|
301
|
+
idcEpubSet(prefs, 'imageAlignment', idcEpubPick('image_alignment', args.image_alignment, t.alignment), changes);
|
|
302
|
+
}
|
|
303
|
+
if (args.image_size !== undefined) {
|
|
304
|
+
idcEpubSet(prefs, 'customImageSizeOption', idcEpubPick('image_size', args.image_size, t.size), changes);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
/* Nur fixed layout */
|
|
308
|
+
if (fixed) {
|
|
309
|
+
if (args.page_range !== undefined) {
|
|
310
|
+
idcEpubSet(prefs, 'epubPageRange', String(args.page_range), changes);
|
|
311
|
+
idcEpubSet(prefs, 'epubPageRangeFormat', PageRangeFormat.EXPORT_PAGE_RANGE, changes);
|
|
312
|
+
}
|
|
313
|
+
if (args.spread_control !== undefined) {
|
|
314
|
+
idcEpubSet(prefs, 'epubSpreadControlOptions', idcEpubPick('spread_control', args.spread_control, t.spread), changes);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
/* Bilder (beide) */
|
|
318
|
+
if (args.image_resolution !== undefined) {
|
|
319
|
+
idcEpubSet(prefs, 'imageExportResolution', idcEpubPick('image_resolution', args.image_resolution, t.resolution), changes);
|
|
320
|
+
}
|
|
321
|
+
if (args.image_format !== undefined) {
|
|
322
|
+
idcEpubSet(prefs, 'imageConversion', idcEpubPick('image_format', args.image_format, t.format), changes);
|
|
323
|
+
}
|
|
324
|
+
if (args.jpeg_quality !== undefined) {
|
|
325
|
+
idcEpubSet(prefs, 'jpegOptionsQuality', idcEpubPick('jpeg_quality', args.jpeg_quality, t.quality), changes);
|
|
326
|
+
}
|
|
327
|
+
/* Metadaten */
|
|
328
|
+
meta = args.metadata;
|
|
329
|
+
if (meta !== undefined && meta !== null) {
|
|
330
|
+
var metaMap = { title: 'epubTitle', creator: 'epubCreator', publisher: 'epubPublisher', description: 'epubDescription',
|
|
331
|
+
subject: 'epubSubject', rights: 'epubRights', date: 'epubDate', identifier: 'id' };
|
|
332
|
+
for (key in meta) {
|
|
333
|
+
if (!meta.hasOwnProperty(key)) { continue; }
|
|
334
|
+
if (!metaMap.hasOwnProperty(key)) {
|
|
335
|
+
IDC.fail('invalid_argument', 'metadata.' + key + ' is not supported (title, creator, publisher, description, subject, rights, date, identifier).', { key: key });
|
|
336
|
+
}
|
|
337
|
+
value = meta[key];
|
|
338
|
+
if (typeof value !== 'string') { IDC.fail('invalid_argument', 'metadata.' + key + ' must be a string.', { key: key }); }
|
|
339
|
+
idcEpubSet(prefs, metaMap[key], value, changes);
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/* Werte nach dem Setzen lesen – das ist, womit exportiert wird. */
|
|
344
|
+
used.layout = fixed ? 'fixed_layout' : 'reflowable';
|
|
345
|
+
used.epub_version = '3';
|
|
346
|
+
if (!fixed && Number(prefs.version) === Number(EpubVersion.EPUB2)) { used.epub_version = '2'; }
|
|
347
|
+
used.cover = idcEpubNameOf(prefs.epubCover, t.cover);
|
|
348
|
+
used.cover_image_path = used.cover === 'image' ? String(prefs.coverImageFile) : null;
|
|
349
|
+
used.toc_style = String(prefs.tocStyleName) === '' ? null : String(prefs.tocStyleName);
|
|
350
|
+
used.image_resolution = idcEpubNameOf(prefs.imageExportResolution, t.resolution);
|
|
351
|
+
used.image_format = idcEpubNameOf(prefs.imageConversion, t.format);
|
|
352
|
+
used.jpeg_quality = idcEpubNameOf(prefs.jpegOptionsQuality, t.quality);
|
|
353
|
+
if (!fixed) {
|
|
354
|
+
used.export_order = idcEpubNameOf(prefs.exportOrder, t.order);
|
|
355
|
+
used.split_by_paragraph_styles = idcEpubSplitUsed(doc, prefs);
|
|
356
|
+
used.split_by_paragraph_style = used.split_by_paragraph_styles === null ? null
|
|
357
|
+
: (String(prefs.paragraphStyleName) !== '' ? String(prefs.paragraphStyleName) : (used.split_by_paragraph_styles.length > 0 ? used.split_by_paragraph_styles[0] : null));
|
|
358
|
+
used.embed_fonts = prefs.embedFont === true;
|
|
359
|
+
try { used.image_alignment = idcEpubNameOf(prefs.imageAlignment, t.alignment); } catch (eIa) { used.image_alignment = null; }
|
|
360
|
+
try { used.image_size = idcEpubNameOf(prefs.customImageSizeOption, t.size); } catch (eIs) { used.image_size = null; }
|
|
361
|
+
} else {
|
|
362
|
+
used.page_range = Number(prefs.epubPageRangeFormat) === Number(PageRangeFormat.EXPORT_PAGE_RANGE) ? String(prefs.epubPageRange) : null;
|
|
363
|
+
used.spread_control = idcEpubNameOf(prefs.epubSpreadControlOptions, t.spread);
|
|
364
|
+
used.navigation = idcEpubNameOf(prefs.epubNavigationStyles, t.navigation);
|
|
365
|
+
}
|
|
366
|
+
used.metadata = {
|
|
367
|
+
title: String(prefs.epubTitle), creator: String(prefs.epubCreator), publisher: String(prefs.epubPublisher),
|
|
368
|
+
description: String(prefs.epubDescription), subject: String(prefs.epubSubject), rights: String(prefs.epubRights),
|
|
369
|
+
date: String(prefs.epubDate), identifier: String(prefs.id)
|
|
370
|
+
};
|
|
371
|
+
|
|
372
|
+
try {
|
|
373
|
+
doc.exportFile(fixed ? ExportFormat.FIXED_LAYOUT_EPUB : ExportFormat.EPUB, file, false);
|
|
374
|
+
} catch (eX) {
|
|
375
|
+
IDC.fail('io_error', 'EPUB export failed: ' + String(eX.message ? eX.message : eX), { path: args.path, layout: used.layout });
|
|
376
|
+
}
|
|
377
|
+
} finally {
|
|
378
|
+
idcEpubRestore(changes, problems);
|
|
379
|
+
}
|
|
380
|
+
if (problems.length > 0) { ctx.warn('Some export settings could not be restored: ' + problems.join('; ')); }
|
|
381
|
+
|
|
382
|
+
bytes = IDC.fileSize(IDC.fileFor(IDC.fsPath(file)));
|
|
383
|
+
|
|
384
|
+
/* Hinweise zum Ergebnis */
|
|
385
|
+
language = idcEpubLanguage(doc);
|
|
386
|
+
if (idcEpubLanguageMissing(language)) {
|
|
387
|
+
ctx.warn('The document has no default language (text defaults); the EPUB language (dc:language) is taken from it.');
|
|
388
|
+
}
|
|
389
|
+
if (used.metadata.title === '') { ctx.warn('No title in metadata; InDesign uses the file name as dc:title.'); }
|
|
390
|
+
if (used.metadata.creator === '') { ctx.warn('No creator (author) in metadata.'); }
|
|
391
|
+
if (used.toc_style === null) {
|
|
392
|
+
ctx.warn('No TOC style chosen; the EPUB navigation lists only the exported file names (toc_style, list_toc_styles).');
|
|
393
|
+
}
|
|
394
|
+
if (used.cover === 'none') { ctx.warn('Exported without a cover image inside the EPUB.'); }
|
|
395
|
+
if (!fixed) {
|
|
396
|
+
for (i = 0; i < doc.pages.length; i++) {
|
|
397
|
+
items = idcEpubTopItems(doc.pages.item(i));
|
|
398
|
+
for (j = 0; j < items.length; j++) {
|
|
399
|
+
item = items[j];
|
|
400
|
+
if (IDC.className(item) !== 'TextFrame' && idcEpubItemHasContent(item)) { unanchored += 1; }
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
if (unanchored > 0) {
|
|
404
|
+
ctx.warn(unanchored + ' object(s) are not anchored in the text flow; in a reflowable EPUB their place follows the export order, not the page (check_epub lists them).');
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
if (fixed || used.embed_fonts === true) {
|
|
408
|
+
try { fonts = doc.fonts; } catch (eF) { fonts = null; }
|
|
409
|
+
if (fonts !== null) {
|
|
410
|
+
for (f = 0; f < fonts.length; f++) {
|
|
411
|
+
font = fonts.item(f);
|
|
412
|
+
try { status = idcFontStatusName(font.status); } catch (eFs) { status = 'unknown'; }
|
|
413
|
+
if (status !== 'installed') { ctx.warn('Font not installed, cannot be embedded: ' + String(font.name).replace('\t', ' ') + '.'); }
|
|
414
|
+
else {
|
|
415
|
+
try { if (font.allowEditableEmbedding === false || font.allowPDFEmbedding === false) { ctx.warn('Font licence may not allow embedding: ' + String(font.name).replace('\t', ' ') + '.'); } } catch (eFa) { /* unbekannt */ }
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
if (changes.length > 0 && !modifiedBefore) {
|
|
421
|
+
ctx.warn('InDesign marks the document as modified when export settings are set, although they were restored; close without saving if nothing else changed.');
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
/* A-62: Seitenformat fuer die Ausrichtung im fixed layout (der Server setzt rendition:orientation nach dem Export). */
|
|
425
|
+
var pageOrientation = null;
|
|
426
|
+
try {
|
|
427
|
+
var pw = Number(doc.documentPreferences.pageWidth), ph = Number(doc.documentPreferences.pageHeight);
|
|
428
|
+
pageOrientation = 'square';
|
|
429
|
+
if (ph > pw) { pageOrientation = 'portrait'; }
|
|
430
|
+
if (pw > ph) { pageOrientation = 'landscape'; }
|
|
431
|
+
} catch (eO) { pageOrientation = null; }
|
|
432
|
+
|
|
433
|
+
return {
|
|
434
|
+
path: IDC.fsPath(file),
|
|
435
|
+
bytes: bytes,
|
|
436
|
+
overwritten: existed,
|
|
437
|
+
page_orientation: pageOrientation,
|
|
438
|
+
layout: used.layout,
|
|
439
|
+
settings_used: used,
|
|
440
|
+
document_language: language,
|
|
441
|
+
settings_changed_for_export: changes.length,
|
|
442
|
+
document_marked_modified: changes.length > 0 && !modifiedBefore
|
|
443
|
+
};
|
|
444
|
+
});
|
|
445
|
+
|
|
446
|
+
/* ------------------------------------------------------- check_epub (Dokument) */
|
|
447
|
+
|
|
448
|
+
function idcEpubPush(state, finding) {
|
|
449
|
+
state.total += 1;
|
|
450
|
+
if (finding.severity === 'error') { state.errors += 1; }
|
|
451
|
+
if (state.total <= state.max) { state.findings.push(finding); } else { state.truncated = true; }
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
IDC.register('check_epub', { needs_document: true, read_only: true, ruler: 'none' },
|
|
455
|
+
function (ctx) {
|
|
456
|
+
var args = ctx.args;
|
|
457
|
+
var doc = ctx.doc;
|
|
458
|
+
var fixed, minPpi, maxFindings, state, checks = [], skipped = [], i, j, k, items, item, page, landing, cls, tocNames, language;
|
|
459
|
+
var masters, mpage, stories, story, paras, count, name, graphics, graphic, ppi, link, pdfLike, fonts, font, status, title, creator, prefs;
|
|
460
|
+
|
|
461
|
+
idcEpubAvailable();
|
|
462
|
+
if (args.layout !== undefined && args.layout !== 'reflowable' && args.layout !== 'fixed_layout') {
|
|
463
|
+
IDC.fail('invalid_argument', 'layout must be reflowable or fixed_layout.', { value: args.layout });
|
|
464
|
+
}
|
|
465
|
+
fixed = args.layout === 'fixed_layout';
|
|
466
|
+
minPpi = null;
|
|
467
|
+
if (args.min_ppi !== undefined && args.min_ppi !== null) {
|
|
468
|
+
if (typeof args.min_ppi !== 'number' || args.min_ppi < 1) { IDC.fail('invalid_argument', 'min_ppi must be a number of at least 1.', { value: args.min_ppi }); }
|
|
469
|
+
minPpi = args.min_ppi;
|
|
470
|
+
}
|
|
471
|
+
maxFindings = 200;
|
|
472
|
+
if (args.max_findings !== undefined) {
|
|
473
|
+
if (typeof args.max_findings !== 'number' || args.max_findings < 1 || args.max_findings > 1000) { IDC.fail('invalid_argument', 'max_findings must be from 1 to 1000.', { value: args.max_findings }); }
|
|
474
|
+
maxFindings = args.max_findings;
|
|
475
|
+
}
|
|
476
|
+
state = { total: 0, errors: 0, max: maxFindings, truncated: false, findings: [] };
|
|
477
|
+
prefs = fixed ? doc.epubFixedLayoutExportPreferences : doc.epubExportPreferences;
|
|
478
|
+
|
|
479
|
+
/* 1. Sprache */
|
|
480
|
+
checks.push('document_language');
|
|
481
|
+
language = idcEpubLanguage(doc);
|
|
482
|
+
if (idcEpubLanguageMissing(language)) {
|
|
483
|
+
idcEpubPush(state, { check: 'document_language', severity: 'error', page_id: null, page_name: null, object_id: null,
|
|
484
|
+
hint: 'Set a default language in the text defaults (Textvorgaben); the EPUB language (dc:language) is taken from it.', actual: language });
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
/* 2. Inhaltsverzeichnis-Format */
|
|
488
|
+
checks.push('toc_style');
|
|
489
|
+
tocNames = idcEpubTocStyleNames(doc);
|
|
490
|
+
if (args.toc_style !== undefined) {
|
|
491
|
+
if (!idcEpubHasName(tocNames, String(args.toc_style))) {
|
|
492
|
+
idcEpubPush(state, { check: 'toc_style', severity: 'error', page_id: null, page_name: null, object_id: null,
|
|
493
|
+
hint: 'TOC style "' + args.toc_style + '" does not exist; available: ' + tocNames.join(', ') + '.', actual: null });
|
|
494
|
+
}
|
|
495
|
+
} else if (String(prefs.tocStyleName) === '') {
|
|
496
|
+
idcEpubPush(state, { check: 'toc_style', severity: 'warning', page_id: null, page_name: null, object_id: null,
|
|
497
|
+
hint: 'No TOC style chosen for the EPUB; the navigation would list only file names. Pass toc_style to export_epub (define_toc_style, list_toc_styles).', actual: tocNames });
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
/* 3. Metadaten */
|
|
501
|
+
checks.push('metadata');
|
|
502
|
+
title = String(prefs.epubTitle);
|
|
503
|
+
creator = String(prefs.epubCreator);
|
|
504
|
+
if (title === '') {
|
|
505
|
+
idcEpubPush(state, { check: 'metadata', severity: 'warning', page_id: null, page_name: null, object_id: null,
|
|
506
|
+
hint: 'No title in the EPUB export settings; InDesign then uses the file name as dc:title. Pass metadata.title to export_epub.', actual: null });
|
|
507
|
+
}
|
|
508
|
+
if (creator === '') {
|
|
509
|
+
idcEpubPush(state, { check: 'metadata', severity: 'warning', page_id: null, page_name: null, object_id: null,
|
|
510
|
+
hint: 'No creator (author) in the EPUB export settings; pass metadata.creator to export_epub.', actual: null });
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
/* 4. Nicht verankerte Objekte (nur reflowable) */
|
|
514
|
+
if (!fixed) {
|
|
515
|
+
checks.push('unanchored_objects');
|
|
516
|
+
for (i = 0; i < doc.pages.length; i++) {
|
|
517
|
+
page = doc.pages.item(i);
|
|
518
|
+
items = idcEpubTopItems(page);
|
|
519
|
+
for (j = 0; j < items.length; j++) {
|
|
520
|
+
item = items[j];
|
|
521
|
+
cls = IDC.className(item);
|
|
522
|
+
if (cls === 'TextFrame' || !idcEpubItemHasContent(item)) { continue; }
|
|
523
|
+
idcEpubPush(state, { check: 'unanchored_objects', severity: 'warning', page_id: Number(page.id), page_name: String(page.name),
|
|
524
|
+
object_id: Number(item.id), kind: cls,
|
|
525
|
+
hint: 'Not anchored in the text flow; in a reflowable EPUB it lands where the export order puts it. Anchor it at the text position (anchor_frame_in_text).' });
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
/* 5. Objekte auf Musterseiten (nur reflowable: dort nicht exportiert) */
|
|
530
|
+
checks.push('parent_page_objects');
|
|
531
|
+
try { masters = doc.masterSpreads; } catch (eM) { masters = null; }
|
|
532
|
+
if (masters !== null) {
|
|
533
|
+
for (i = 0; i < masters.length; i++) {
|
|
534
|
+
for (j = 0; j < masters.item(i).pages.length; j++) {
|
|
535
|
+
mpage = masters.item(i).pages.item(j);
|
|
536
|
+
items = idcEpubTopItems(mpage);
|
|
537
|
+
for (k = 0; k < items.length; k++) {
|
|
538
|
+
item = items[k];
|
|
539
|
+
if (!idcEpubItemHasContent(item)) { continue; }
|
|
540
|
+
idcEpubPush(state, { check: 'parent_page_objects', severity: 'warning', page_id: Number(mpage.id), page_name: String(mpage.name),
|
|
541
|
+
object_id: Number(item.id), kind: IDC.className(item),
|
|
542
|
+
hint: 'On a parent page; a reflowable EPUB leaves it out (fine for running heads and page numbers).' });
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
/* 6. Texte ohne eigenes Absatzformat */
|
|
549
|
+
checks.push('paragraph_styles');
|
|
550
|
+
try { stories = doc.stories; } catch (eSt) { stories = null; }
|
|
551
|
+
if (stories !== null) {
|
|
552
|
+
for (i = 0; i < stories.length; i++) {
|
|
553
|
+
story = stories.item(i);
|
|
554
|
+
count = 0;
|
|
555
|
+
/* Texte auf Musterseiten kommen in einen reflowable EPUB nicht hinein (Befund S60 am Musterbuch). */
|
|
556
|
+
try { if (story.textContainers.length > 0 && IDC.isOnParentSpread(story.textContainers[0])) { continue; } } catch (eTc) { /* weiter */ }
|
|
557
|
+
try { paras = story.paragraphs; } catch (eP) { paras = null; }
|
|
558
|
+
if (paras === null) { continue; }
|
|
559
|
+
for (j = 0; j < paras.length; j++) {
|
|
560
|
+
try { name = String(paras.item(j).appliedParagraphStyle.name); } catch (eN) { name = ''; }
|
|
561
|
+
if (name === '' || name.charAt(0) === '[') { count += 1; }
|
|
562
|
+
}
|
|
563
|
+
if (count > 0) {
|
|
564
|
+
landing = { page_id: null, page_name: null };
|
|
565
|
+
try { landing = IDC.landing(story.textContainers[0]); } catch (eL) { /* unbekannt */ }
|
|
566
|
+
idcEpubPush(state, { check: 'paragraph_styles', severity: 'warning', page_id: landing.page_id, page_name: landing.page_name,
|
|
567
|
+
object_id: Number(story.id), kind: 'Story', paragraphs: count,
|
|
568
|
+
hint: count + ' paragraph(s) use a basic paragraph style; EPUB headings, navigation and CSS classes come from named paragraph styles.' });
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
} else {
|
|
573
|
+
skipped.push('unanchored_objects', 'parent_page_objects', 'paragraph_styles');
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
/* 7. Bildaufloesung */
|
|
577
|
+
if (minPpi === null) {
|
|
578
|
+
skipped.push('image_resolution');
|
|
579
|
+
} else {
|
|
580
|
+
checks.push('image_resolution');
|
|
581
|
+
try { graphics = doc.allGraphics; } catch (eG) { graphics = []; }
|
|
582
|
+
for (i = 0; i < graphics.length; i++) {
|
|
583
|
+
graphic = graphics[i];
|
|
584
|
+
pdfLike = false;
|
|
585
|
+
try { pdfLike = /pdf|eps|postscript/i.test(String(graphic.imageTypeName)) || IDC.className(graphic) === 'PDF' || IDC.className(graphic) === 'EPS'; } catch (eP2) { pdfLike = false; }
|
|
586
|
+
if (pdfLike) { continue; }
|
|
587
|
+
try { ppi = idcPpi(graphic.effectivePpi); } catch (eE) { ppi = null; }
|
|
588
|
+
if (ppi === null || ppi.min >= minPpi) { continue; }
|
|
589
|
+
landing = IDC.landing(graphic);
|
|
590
|
+
link = null;
|
|
591
|
+
try { link = String(graphic.itemLink.name); } catch (eLk) { link = null; }
|
|
592
|
+
idcEpubPush(state, { check: 'image_resolution', severity: 'warning', page_id: landing.page_id, page_name: landing.page_name,
|
|
593
|
+
object_id: Number(graphic.id), kind: 'Graphic', file_name: link, effective_ppi: ppi.min,
|
|
594
|
+
hint: 'Effective resolution ' + ppi.min + ' ppi is below ' + minPpi + ' ppi.' });
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
/* 8. Schriften */
|
|
599
|
+
checks.push('fonts');
|
|
600
|
+
try { fonts = doc.fonts; } catch (eF) { fonts = null; }
|
|
601
|
+
if (fonts !== null) {
|
|
602
|
+
for (i = 0; i < fonts.length; i++) {
|
|
603
|
+
font = fonts.item(i);
|
|
604
|
+
try { status = idcFontStatusName(font.status); } catch (eFs) { status = 'unknown'; }
|
|
605
|
+
if (status !== 'installed') {
|
|
606
|
+
idcEpubPush(state, { check: 'fonts', severity: fixed ? 'error' : 'warning', page_id: null, page_name: null, object_id: null,
|
|
607
|
+
font: String(font.name).replace('\t', ' '), status: status,
|
|
608
|
+
hint: 'Font not installed; it cannot be embedded' + (fixed ? ' (a fixed-layout EPUB needs embedded fonts).' : '.') });
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
if (state.truncated) { ctx.warn(state.total + ' findings, only the first ' + state.max + ' returned (max_findings).'); }
|
|
614
|
+
if (minPpi === null) { ctx.warn('image_resolution not checked: pass min_ppi or set epub.min_ppi in the server configuration.'); }
|
|
615
|
+
|
|
616
|
+
return {
|
|
617
|
+
passed: state.errors === 0,
|
|
618
|
+
layout: fixed ? 'fixed_layout' : 'reflowable',
|
|
619
|
+
checked: 'document',
|
|
620
|
+
checks_run: checks,
|
|
621
|
+
skipped_checks: skipped,
|
|
622
|
+
document_language: language,
|
|
623
|
+
toc_styles: tocNames,
|
|
624
|
+
errors: state.errors,
|
|
625
|
+
findings: state.findings,
|
|
626
|
+
findings_total: state.total,
|
|
627
|
+
findings_truncated: state.truncated
|
|
628
|
+
};
|
|
629
|
+
});
|