postext 1.33.11 → 1.34.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (140) hide show
  1. package/README.md +2 -2
  2. package/dist/__tests__/bundle/designOverflowPin.test.js +1 -1
  3. package/dist/__tests__/bundle/gridBreakRulesPin.test.js +2 -2
  4. package/dist/__tests__/bundle/shapingLanguagePin.test.js +3 -3
  5. package/dist/__tests__/bundle/taskBoxPin.test.js +1 -1
  6. package/dist/__tests__/bundle.test.js +1 -1
  7. package/dist/__tests__/codeBlocks.test.js +1 -1
  8. package/dist/__tests__/composed/corpus.test.d.ts +2 -0
  9. package/dist/__tests__/composed/corpus.test.d.ts.map +1 -0
  10. package/dist/__tests__/composed/corpus.test.js +33 -0
  11. package/dist/__tests__/composed/corpus.test.js.map +1 -0
  12. package/dist/__tests__/composed/slotChecks.test.d.ts +2 -0
  13. package/dist/__tests__/composed/slotChecks.test.d.ts.map +1 -0
  14. package/dist/__tests__/composed/slotChecks.test.js +148 -0
  15. package/dist/__tests__/composed/slotChecks.test.js.map +1 -0
  16. package/dist/__tests__/composedTemplates.test.d.ts +2 -0
  17. package/dist/__tests__/composedTemplates.test.d.ts.map +1 -0
  18. package/dist/__tests__/composedTemplates.test.js +349 -0
  19. package/dist/__tests__/composedTemplates.test.js.map +1 -0
  20. package/dist/__tests__/contentInConfig.test.d.ts +2 -0
  21. package/dist/__tests__/contentInConfig.test.d.ts.map +1 -0
  22. package/dist/__tests__/contentInConfig.test.js +201 -0
  23. package/dist/__tests__/contentInConfig.test.js.map +1 -0
  24. package/dist/__tests__/defaults/stripRoundTrip.test.js +3 -1
  25. package/dist/__tests__/defaults/stripRoundTrip.test.js.map +1 -1
  26. package/dist/__tests__/exports.test.js +22 -0
  27. package/dist/__tests__/exports.test.js.map +1 -1
  28. package/dist/__tests__/hardBreaks.test.js +1 -1
  29. package/dist/__tests__/headingInlineMarks.test.js +1 -1
  30. package/dist/__tests__/mathSizeMigration.test.js +2 -2
  31. package/dist/__tests__/parse/composedPages.test.d.ts +2 -0
  32. package/dist/__tests__/parse/composedPages.test.d.ts.map +1 -0
  33. package/dist/__tests__/parse/composedPages.test.js +323 -0
  34. package/dist/__tests__/parse/composedPages.test.js.map +1 -0
  35. package/dist/__tests__/parse/containers.test.js +2 -2
  36. package/dist/__tests__/parse/containers.test.js.map +1 -1
  37. package/dist/__tests__/pipeline/calloutInlineResourceGap.test.js +1 -1
  38. package/dist/__tests__/pipeline/calloutSplitMinLinesChild.test.js +1 -1
  39. package/dist/__tests__/pipeline/colonListRoom.test.js +1 -1
  40. package/dist/__tests__/pipeline/compoundBreaks.test.js +1 -1
  41. package/dist/__tests__/pipeline/dashBreaks.test.js +1 -1
  42. package/dist/__tests__/pipeline/headingSplitOrphans.test.js +1 -1
  43. package/dist/__tests__/pipeline/inlineFigureSpace.test.js +1 -1
  44. package/dist/__tests__/pipeline/paragraphContainerTail.test.js +1 -1
  45. package/dist/__tests__/pipeline/raggedOptimal.test.js +1 -1
  46. package/dist/__tests__/tocGroups.test.d.ts +2 -0
  47. package/dist/__tests__/tocGroups.test.d.ts.map +1 -0
  48. package/dist/__tests__/tocGroups.test.js +213 -0
  49. package/dist/__tests__/tocGroups.test.js.map +1 -0
  50. package/dist/__tests__/verseLines.test.js +1 -1
  51. package/dist/bundle/configVersion.d.ts +16 -5
  52. package/dist/bundle/configVersion.d.ts.map +1 -1
  53. package/dist/bundle/configVersion.js +17 -4
  54. package/dist/bundle/configVersion.js.map +1 -1
  55. package/dist/bundle/types.d.ts +4 -3
  56. package/dist/bundle/types.d.ts.map +1 -1
  57. package/dist/composed/document.d.ts +43 -0
  58. package/dist/composed/document.d.ts.map +1 -0
  59. package/dist/composed/document.js +88 -0
  60. package/dist/composed/document.js.map +1 -0
  61. package/dist/composed/slotChecks.d.ts +29 -0
  62. package/dist/composed/slotChecks.d.ts.map +1 -0
  63. package/dist/composed/slotChecks.js +109 -0
  64. package/dist/composed/slotChecks.js.map +1 -0
  65. package/dist/composed/templates.d.ts +133 -0
  66. package/dist/composed/templates.d.ts.map +1 -0
  67. package/dist/composed/templates.js +702 -0
  68. package/dist/composed/templates.js.map +1 -0
  69. package/dist/composed/types.d.ts +404 -0
  70. package/dist/composed/types.d.ts.map +1 -0
  71. package/dist/composed/types.js +2 -0
  72. package/dist/composed/types.js.map +1 -0
  73. package/dist/composed/validate.d.ts +26 -0
  74. package/dist/composed/validate.d.ts.map +1 -0
  75. package/dist/composed/validate.js +276 -0
  76. package/dist/composed/validate.js.map +1 -0
  77. package/dist/configWarnings.d.ts +19 -3
  78. package/dist/configWarnings.d.ts.map +1 -1
  79. package/dist/configWarnings.js +170 -40
  80. package/dist/configWarnings.js.map +1 -1
  81. package/dist/defaults/checks.d.ts +7 -0
  82. package/dist/defaults/checks.d.ts.map +1 -0
  83. package/dist/defaults/checks.js +49 -0
  84. package/dist/defaults/checks.js.map +1 -0
  85. package/dist/defaults/index.d.ts +1 -0
  86. package/dist/defaults/index.d.ts.map +1 -1
  87. package/dist/defaults/index.js +26 -0
  88. package/dist/defaults/index.js.map +1 -1
  89. package/dist/defaults/toc.d.ts +17 -2
  90. package/dist/defaults/toc.d.ts.map +1 -1
  91. package/dist/defaults/toc.js +53 -1
  92. package/dist/defaults/toc.js.map +1 -1
  93. package/dist/design/slots.d.ts +29 -0
  94. package/dist/design/slots.d.ts.map +1 -0
  95. package/dist/design/slots.js +48 -0
  96. package/dist/design/slots.js.map +1 -0
  97. package/dist/index.d.ts +17 -3
  98. package/dist/index.d.ts.map +1 -1
  99. package/dist/index.js +10 -1
  100. package/dist/index.js.map +1 -1
  101. package/dist/parse/blockParser.d.ts.map +1 -1
  102. package/dist/parse/blockParser.js +295 -36
  103. package/dist/parse/blockParser.js.map +1 -1
  104. package/dist/parse/index.d.ts +1 -1
  105. package/dist/parse/index.d.ts.map +1 -1
  106. package/dist/parse/index.js.map +1 -1
  107. package/dist/parse/indexMarks.d.ts.map +1 -1
  108. package/dist/parse/indexMarks.js +24 -0
  109. package/dist/parse/indexMarks.js.map +1 -1
  110. package/dist/parse/types.d.ts +95 -2
  111. package/dist/parse/types.d.ts.map +1 -1
  112. package/dist/pipeline/build.d.ts.map +1 -1
  113. package/dist/pipeline/build.js +178 -3
  114. package/dist/pipeline/build.js.map +1 -1
  115. package/dist/pipeline/config.d.ts.map +1 -1
  116. package/dist/pipeline/config.js +17 -2
  117. package/dist/pipeline/config.js.map +1 -1
  118. package/dist/pipeline/contentWarnings.d.ts.map +1 -1
  119. package/dist/pipeline/contentWarnings.js +73 -0
  120. package/dist/pipeline/contentWarnings.js.map +1 -1
  121. package/dist/pipeline/placeholders.d.ts +7 -0
  122. package/dist/pipeline/placeholders.d.ts.map +1 -1
  123. package/dist/pipeline/placeholders.js +41 -0
  124. package/dist/pipeline/placeholders.js.map +1 -1
  125. package/dist/pipeline/textWrap.js +1 -1
  126. package/dist/pipeline/textWrap.js.map +1 -1
  127. package/dist/pipeline/toc.d.ts +11 -1
  128. package/dist/pipeline/toc.d.ts.map +1 -1
  129. package/dist/pipeline/toc.js +147 -8
  130. package/dist/pipeline/toc.js.map +1 -1
  131. package/dist/types.d.ts +99 -0
  132. package/dist/types.d.ts.map +1 -1
  133. package/dist/util/closestKey.d.ts +4 -0
  134. package/dist/util/closestKey.d.ts.map +1 -0
  135. package/dist/util/closestKey.js +40 -0
  136. package/dist/util/closestKey.js.map +1 -0
  137. package/dist/vdt.d.ts +125 -7
  138. package/dist/vdt.d.ts.map +1 -1
  139. package/dist/vdt.js.map +1 -1
  140. package/package.json +1 -1
@@ -0,0 +1,276 @@
1
+ // Validation of page templates and label styles (composed pages, #853).
2
+ // The engine ignores unknown keys elsewhere; a template is checked and every
3
+ // problem reported as a config warning whose `path` is a JSON pointer
4
+ // (`/pageTemplates/3/frames/2/style`). Pure.
5
+ import { closestKey } from '../util/closestKey';
6
+ import { dimensionToPx } from '../units';
7
+ import { FRAME_DIRECTIONS, FRAME_EXCLUDES, FRAME_GROUP_ALIGNS, FRAME_GROUP_KINDS, FRAME_TAKES, FRAME_VERTICAL_ALIGNS, FRAME_WRITING_MODES, LABEL_FONT_STYLES, LABEL_TEXT_TRANSFORMS, TEMPLATE_AREAS, DEFAULT_FRAME, DEFAULT_FRAME_GROUP, DEFAULT_LABEL_STYLE, DEFAULT_PAGE_TEMPLATE, resolveTemplateAt, templateChain, } from './templates';
8
+ // The keys of each object, checked against its type: a key added to a type
9
+ // fails to compile until it is listed here.
10
+ const TEMPLATE_KEYS = {
11
+ id: true, name: true, extends: true, spread: true, gutter: true, variants: true, role: true,
12
+ area: true, grid: true, frames: true, groups: true, decoration: true, header: true, footer: true,
13
+ overflowTemplate: true, bodyStyle: true, palette: true,
14
+ };
15
+ const PATCH_KEYS = {
16
+ area: true, grid: true, frames: true, groups: true, decoration: true, header: true, footer: true,
17
+ overflowTemplate: true, bodyStyle: true, palette: true,
18
+ };
19
+ const VARIANTS_KEYS = { recto: true, verso: true };
20
+ const GRID_KEYS = { columns: true, rows: true, columnGap: true, rowGap: true };
21
+ const CELL_KEYS = { col: true, row: true, cols: true, rows: true };
22
+ const FRAME_KEYS = {
23
+ name: true, placement: true, grid: true, width: true, height: true, minWidth: true, maxWidth: true, minHeight: true,
24
+ maxHeight: true, style: true, layer: true, rotate: true, verticalAlign: true, columns: true, columnGap: true, padding: true,
25
+ exclude: true, flow: true, next: true, takes: true, pin: true, grow: true, shrink: true, priority: true, fit: true,
26
+ overflow: true, optional: true, crossGutter: true, writingMode: true, direction: true, remove: true,
27
+ };
28
+ const FIT_KEYS = { shrinkText: true, minScale: true, scaleImages: true, imageMinScale: true };
29
+ const OVERFLOW_KEYS = { continueIn: true, mark: true };
30
+ const PADDING_KEYS = { top: true, right: true, bottom: true, left: true };
31
+ const GROUP_KEYS = {
32
+ name: true, kind: true, frames: true, gap: true, placement: true, grid: true, align: true, remove: true,
33
+ };
34
+ const LABEL_STYLE_KEYS = {
35
+ id: true, name: true, paragraphStyle: true, fontFamily: true, fontSize: true, fontWeight: true, fontStyle: true,
36
+ color: true, textTransform: true, letterSpacing: true, halo: true, background: true, padding: true, minScale: true,
37
+ };
38
+ const isRecord = (v) => typeof v === 'object' && v !== null && !Array.isArray(v);
39
+ /**
40
+ * Every problem of `config.pageTemplates` and `config.labelStyles` (and of
41
+ * the same keys under `htmlViewer.overrides`), as config warnings with a
42
+ * JSON-pointer `path`: the kinds listed on {@link ConfigWarning}, plus
43
+ * `unknownConfigKey` for a key no template, frame, group, grid, fit,
44
+ * overflow, variant or label style has, and `unknownConfigValue` for a word
45
+ * outside a setting's choices (`area`, `verticalAlign`, `exclude`, `takes`,
46
+ * `kind`, `align`, `writingMode`, `direction`, `fontStyle`,
47
+ * `textTransform`) or a template with no id or a frame or group with no
48
+ * name (ignored). `resolvePageTemplate` makes the same fixes the warnings
49
+ * describe. Pure.
50
+ */
51
+ export function validatePageTemplates(config, options = {}) {
52
+ if (!config)
53
+ return [];
54
+ const out = [];
55
+ const seen = new Set();
56
+ const push = (w) => {
57
+ const key = `${w.kind}|${w.path}|${w.value}`;
58
+ if (seen.has(key))
59
+ return;
60
+ seen.add(key);
61
+ out.push(w);
62
+ };
63
+ const calloutIds = (styles) => new Set((Array.isArray(styles) ? styles : [{ id: 'note' }]).filter(isRecord).map((s) => s.id).filter((id) => typeof id === 'string'));
64
+ checkTemplates(config.pageTemplates, '/pageTemplates', calloutIds(config.calloutStyles), options, push);
65
+ checkLabelStyles(config.labelStyles, '/labelStyles', push);
66
+ const overrides = config.htmlViewer?.overrides;
67
+ if (isRecord(overrides)) {
68
+ checkTemplates(overrides.pageTemplates, '/htmlViewer/overrides/pageTemplates', calloutIds(overrides.calloutStyles ?? config.calloutStyles), options, push);
69
+ checkLabelStyles(overrides.labelStyles, '/htmlViewer/overrides/labelStyles', push);
70
+ }
71
+ checkAnchorStyles(config.labelStyles, options.resources, push);
72
+ return out;
73
+ }
74
+ function unknownKeys(node, known, path, push) {
75
+ if (!isRecord(node))
76
+ return;
77
+ const names = Object.keys(known);
78
+ for (const [key, value] of Object.entries(node)) {
79
+ if (value === undefined || Object.prototype.hasOwnProperty.call(known, key))
80
+ continue;
81
+ const suggestion = closestKey(key, names);
82
+ push({ kind: 'unknownConfigKey', path: `${path}/${escapePointer(key)}`, value: key, used: '', ...(suggestion ? { suggestion } : {}) });
83
+ }
84
+ }
85
+ function choice(node, key, list, used, path, push) {
86
+ const value = node[key];
87
+ if (value === undefined || (typeof value === 'string' && list.includes(value)))
88
+ return;
89
+ const suggestion = typeof value === 'string' ? closestKey(value, list) : undefined;
90
+ push({ kind: 'unknownConfigValue', path: `${path}/${key}`, value: String(value), used, ...(suggestion ? { suggestion } : {}) });
91
+ }
92
+ /** A JSON-pointer token (RFC 6901). */
93
+ function escapePointer(token) {
94
+ return token.replace(/~/g, '~0').replace(/\//g, '~1');
95
+ }
96
+ function checkGrid(grid, path, push) {
97
+ unknownKeys(grid, GRID_KEYS, path, push);
98
+ }
99
+ function checkFrameEntry(frame, path, push) {
100
+ if (!isRecord(frame))
101
+ return;
102
+ if (typeof frame.name !== 'string' || frame.name === '') {
103
+ push({ kind: 'unknownConfigValue', path: `${path}/name`, value: String(frame.name ?? ''), used: '' });
104
+ return;
105
+ }
106
+ unknownKeys(frame, FRAME_KEYS, path, push);
107
+ unknownKeys(frame.grid, CELL_KEYS, `${path}/grid`, push);
108
+ unknownKeys(frame.fit, FIT_KEYS, `${path}/fit`, push);
109
+ unknownKeys(frame.overflow, OVERFLOW_KEYS, `${path}/overflow`, push);
110
+ unknownKeys(frame.padding, PADDING_KEYS, `${path}/padding`, push);
111
+ choice(frame, 'verticalAlign', FRAME_VERTICAL_ALIGNS, DEFAULT_FRAME.verticalAlign, path, push);
112
+ choice(frame, 'exclude', FRAME_EXCLUDES, DEFAULT_FRAME.exclude, path, push);
113
+ choice(frame, 'takes', FRAME_TAKES, '', path, push);
114
+ choice(frame, 'writingMode', FRAME_WRITING_MODES, '', path, push);
115
+ choice(frame, 'direction', FRAME_DIRECTIONS, '', path, push);
116
+ }
117
+ function checkGroupEntry(group, path, push) {
118
+ if (!isRecord(group))
119
+ return;
120
+ if (typeof group.name !== 'string' || group.name === '') {
121
+ push({ kind: 'unknownConfigValue', path: `${path}/name`, value: String(group.name ?? ''), used: '' });
122
+ return;
123
+ }
124
+ unknownKeys(group, GROUP_KEYS, path, push);
125
+ unknownKeys(group.grid, CELL_KEYS, `${path}/grid`, push);
126
+ choice(group, 'kind', FRAME_GROUP_KINDS, DEFAULT_FRAME_GROUP.kind, path, push);
127
+ choice(group, 'align', FRAME_GROUP_ALIGNS, DEFAULT_FRAME_GROUP.align, path, push);
128
+ }
129
+ function checkPatch(patch, path, push, keys) {
130
+ if (!isRecord(patch))
131
+ return;
132
+ unknownKeys(patch, keys, path, push);
133
+ choice(patch, 'area', TEMPLATE_AREAS, DEFAULT_PAGE_TEMPLATE.area, path, push);
134
+ checkGrid(patch.grid, `${path}/grid`, push);
135
+ if (Array.isArray(patch.frames))
136
+ patch.frames.forEach((f, j) => checkFrameEntry(f, `${path}/frames/${j}`, push));
137
+ if (Array.isArray(patch.groups))
138
+ patch.groups.forEach((g, j) => checkGroupEntry(g, `${path}/groups/${j}`, push));
139
+ }
140
+ function checkTemplates(raw, prefix, calloutStyleIds, options, push) {
141
+ if (!Array.isArray(raw))
142
+ return;
143
+ const templates = raw;
144
+ const firstOf = new Map();
145
+ const ids = [];
146
+ templates.forEach((t, i) => {
147
+ const path = `${prefix}/${i}`;
148
+ if (!isRecord(t))
149
+ return;
150
+ if (typeof t.id !== 'string' || t.id === '') {
151
+ push({ kind: 'unknownConfigValue', path: `${path}/id`, value: String(t.id ?? ''), used: '' });
152
+ return;
153
+ }
154
+ if (firstOf.has(t.id)) {
155
+ push({ kind: 'templateDuplicate', path, value: t.id, used: '' });
156
+ }
157
+ else {
158
+ firstOf.set(t.id, i);
159
+ ids.push(t.id);
160
+ }
161
+ checkPatch(t, path, push, TEMPLATE_KEYS);
162
+ unknownKeys(t.variants, VARIANTS_KEYS, `${path}/variants`, push);
163
+ if (isRecord(t.variants)) {
164
+ for (const side of ['recto', 'verso'])
165
+ checkPatch(t.variants[side], `${path}/variants/${side}`, push, PATCH_KEYS);
166
+ }
167
+ });
168
+ const toPx = pxConverter(options);
169
+ for (const [id, index] of firstOf) {
170
+ const t = templates[index];
171
+ const path = `${prefix}/${index}`;
172
+ if (t.extends !== undefined) {
173
+ if (typeof t.extends !== 'string' || !firstOf.has(t.extends)) {
174
+ const suggestion = typeof t.extends === 'string' ? closestKey(t.extends, ids.filter((x) => x !== id)) : undefined;
175
+ push({ kind: 'templateExtendsUnknown', path: `${path}/extends`, value: String(t.extends), used: '', ...(suggestion ? { suggestion } : {}) });
176
+ }
177
+ }
178
+ if (!templateChain(templates, index)) {
179
+ push({ kind: 'templateExtendsCycle', path: `${path}/extends`, value: loopText(templates, index, firstOf), used: '' });
180
+ continue;
181
+ }
182
+ // The template on its own, then on each side when a variant applies.
183
+ const chain = templateChain(templates, index);
184
+ const sides = chain.some((i) => isRecord(templates[i].variants)) ? [undefined, 'recto', 'verso'] : [undefined];
185
+ for (const parity of sides) {
186
+ const resolved = resolveTemplateAt(templates, index, { parity, calloutStyleIds, prefix });
187
+ if (!resolved)
188
+ continue;
189
+ for (const issue of resolved.issues)
190
+ push(issueWarning(issue));
191
+ for (const frame of resolved.template.frames)
192
+ checkMinMax(frame, toPx, push);
193
+ }
194
+ }
195
+ }
196
+ /** `a → b → a`: the chain of `extends` from `index` until it repeats. */
197
+ function loopText(templates, index, firstOf) {
198
+ const names = [];
199
+ const seen = new Set();
200
+ let at = index;
201
+ while (at !== undefined && !seen.has(at)) {
202
+ seen.add(at);
203
+ names.push(templates[at].id);
204
+ const parent = templates[at].extends;
205
+ at = typeof parent === 'string' ? firstOf.get(parent) : undefined;
206
+ }
207
+ if (at !== undefined)
208
+ names.push(templates[at].id);
209
+ return names.join(' → ');
210
+ }
211
+ function issueWarning(issue) {
212
+ const suggestion = issue.known ? closestKey(issue.value, issue.known) : undefined;
213
+ return { kind: issue.kind, path: issue.path, value: issue.value, used: issue.used, ...(suggestion ? { suggestion } : {}) };
214
+ }
215
+ function pxConverter(options) {
216
+ const dpi = options.dpi ?? 96;
217
+ const base = options.baseFontSizePx ?? 16;
218
+ return (d) => dimensionToPx(d, dpi, base);
219
+ }
220
+ const text = (d) => `${d.value}${d.unit}`;
221
+ /** A minimum above its maximum, and a fixed size outside them. */
222
+ function checkMinMax(frame, toPx, push) {
223
+ const fieldPath = (key) => frame.fieldPaths[key] ?? `${frame.configPath}/${key}`;
224
+ for (const axis of ['Width', 'Height']) {
225
+ const min = frame[`min${axis}`];
226
+ const max = frame[`max${axis}`];
227
+ if (min && max && toPx(min) > toPx(max) + 1e-6) {
228
+ push({ kind: 'frameMinMax', path: fieldPath(`min${axis}`), value: `min${axis} ${text(min)} > max${axis} ${text(max)}`, used: text(min) });
229
+ }
230
+ const size = axis === 'Width' ? frame.width : frame.height;
231
+ if (typeof size !== 'object' || 'percent' in size)
232
+ continue;
233
+ const key = axis.toLowerCase();
234
+ const sizePath = frame.fieldPaths[key] ?? (frame.fieldPaths.placement ? `${frame.fieldPaths.placement}/size/${key}` : `${frame.configPath}/${key}`);
235
+ // The minimum wins over the maximum.
236
+ const hi = max && !(min && toPx(min) > toPx(max)) ? max : min;
237
+ if (min && toPx(size) < toPx(min) - 1e-6) {
238
+ push({ kind: 'frameMinMax', path: sizePath, value: `${key} ${text(size)} < min${axis} ${text(min)}`, used: text(min) });
239
+ }
240
+ else if (hi && max && toPx(size) > toPx(hi) + 1e-6) {
241
+ push({ kind: 'frameMinMax', path: sizePath, value: `${key} ${text(size)} > max${axis} ${text(max)}`, used: text(hi) });
242
+ }
243
+ }
244
+ }
245
+ function checkLabelStyles(raw, prefix, push) {
246
+ if (!Array.isArray(raw))
247
+ return;
248
+ raw.forEach((s, i) => {
249
+ const path = `${prefix}/${i}`;
250
+ if (!isRecord(s))
251
+ return;
252
+ if (typeof s.id !== 'string' || s.id === '') {
253
+ push({ kind: 'unknownConfigValue', path: `${path}/id`, value: String(s.id ?? ''), used: '' });
254
+ return;
255
+ }
256
+ unknownKeys(s, LABEL_STYLE_KEYS, path, push);
257
+ choice(s, 'fontStyle', LABEL_FONT_STYLES, DEFAULT_LABEL_STYLE.fontStyle, path, push);
258
+ choice(s, 'textTransform', LABEL_TEXT_TRANSFORMS, DEFAULT_LABEL_STYLE.textTransform, path, push);
259
+ });
260
+ }
261
+ /** A resource anchor whose `style` no label style has. */
262
+ function checkAnchorStyles(labelStyles, resources, push) {
263
+ if (!resources)
264
+ return;
265
+ const ids = (Array.isArray(labelStyles) ? labelStyles : []).filter(isRecord).map((s) => s.id).filter((id) => typeof id === 'string');
266
+ const known = new Set(ids);
267
+ resources.forEach((r, i) => {
268
+ r.anchors?.forEach((a, j) => {
269
+ if (typeof a.style !== 'string' || known.has(a.style))
270
+ return;
271
+ const suggestion = closestKey(a.style, ids);
272
+ push({ kind: 'labelStyleUnknown', path: `/resources/${i}/anchors/${j}/style`, value: a.style, used: '', resourceId: r.id, ...(suggestion ? { suggestion } : {}) });
273
+ });
274
+ });
275
+ }
276
+ //# sourceMappingURL=validate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/composed/validate.ts"],"names":[],"mappings":"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"}
@@ -7,7 +7,7 @@
7
7
  * `VDTDocument.configWarnings`, and to any host that asks with
8
8
  * {@link collectConfigWarnings}.
9
9
  */
10
- import type { PostextConfig } from './types';
10
+ import type { PostextConfig, Resource, DocumentMetadata } from './types';
11
11
  import type { ConfigWarning } from './vdt';
12
12
  /**
13
13
  * Walk a config for values the engine replaces: an unknown numbering
@@ -22,7 +22,23 @@ import type { ConfigWarning } from './vdt';
22
22
  * `headings`, its `balancing` and `levels`, `headingStyles`,
23
23
  * `paragraphStyles`). And a setting with a value outside its choices
24
24
  * (`unknownConfigValue`: `direction`, the comics settings' words), and a `numerals` value that names
25
- * no digit system (`unknownNumerals`). Pure.
25
+ * no digit system (`unknownNumerals`). And the design texts that hold
26
+ * the book's content instead of placeholders (`contentInConfig`, #849,
27
+ * tuned by `checks.contentInConfig`). Pure.
26
28
  */
27
- export declare function collectConfigWarnings(config: PostextConfig | undefined): ConfigWarning[];
29
+ export declare function collectConfigWarnings(config: PostextConfig | undefined, options?: ConfigWarningOptions): ConfigWarning[];
30
+ /** What else the config checks may read. */
31
+ export interface ConfigWarningOptions {
32
+ /** The book's resources: an anchor's label `style` is checked against
33
+ * `labelStyles` (`labelStyleUnknown`). */
34
+ resources?: readonly Resource[];
35
+ /** The document's metadata (its front matter): its `title`, `subtitle`,
36
+ * `author` and `publisher` are allowed in a design text as if listed in
37
+ * `checks.contentInConfig.allow`, since a running head often repeats
38
+ * them. */
39
+ metadata?: DocumentMetadata;
40
+ }
41
+ /** The literal text a design text prints whatever the document: its
42
+ * content with every placeholder removed, on one line (#849). */
43
+ export declare function designTextLiteral(content: string): string;
28
44
  //# sourceMappingURL=configWarnings.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"configWarnings.d.ts","sourceRoot":"","sources":["../src/configWarnings.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAMV,aAAa,EAgBd,MAAM,SAAS,CAAC;AACjB,OAAO,KAAK,EAAE,aAAa,EAAkB,MAAM,OAAO,CAAC;AAsC3D;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,aAAa,GAAG,SAAS,GAAG,aAAa,EAAE,CAMxF"}
1
+ {"version":3,"file":"configWarnings.d.ts","sourceRoot":"","sources":["../src/configWarnings.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAMV,aAAa,EAgBb,QAAQ,EAGR,gBAAgB,EACjB,MAAM,SAAS,CAAC;AACjB,OAAO,KAAK,EAAE,aAAa,EAAkB,MAAM,OAAO,CAAC;AA6C3D;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,aAAa,GAAG,SAAS,EAAE,OAAO,GAAE,oBAAyB,GAAG,aAAa,EAAE,CAQ5H;AAED,4CAA4C;AAC5C,MAAM,WAAW,oBAAoB;IACnC;+CAC2C;IAC3C,SAAS,CAAC,EAAE,SAAS,QAAQ,EAAE,CAAC;IAChC;;;gBAGY;IACZ,QAAQ,CAAC,EAAE,gBAAgB,CAAC;CAC7B;AA6oBD;kEACkE;AAClE,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEzD"}
@@ -8,6 +8,7 @@
8
8
  * {@link collectConfigWarnings}.
9
9
  */
10
10
  import { parseNumberFormat } from './numbering';
11
+ import { parseTocGroupHead } from './defaults/toc';
11
12
  import { isFontStack, primaryFontFamily } from './measure/font';
12
13
  import { dimensionToPx } from './units';
13
14
  import { resolveAllConfig, resolveDirection, resolvedLocale, sideColumnPercentUsed, columnCountUsed } from './pipeline/config';
@@ -21,9 +22,15 @@ import { COMIC_CHOICES, isComicChoice, resolveComicsConfig } from './defaults/co
21
22
  import { resolvePrintConfig } from './defaults/print';
22
23
  import { CONTRAST_LEVELS, CONTRAST_MODES, DEFAULT_CONTRAST_CONFIG } from './defaults/contrast';
23
24
  import { isTabStopAlign, parseTabStopPosition } from './defaults/tabStops';
25
+ import { resolveContentInConfigCheck } from './defaults/checks';
26
+ import { stripPlaceholders } from './pipeline/placeholders';
27
+ import { configDesignSlots } from './design/slots';
28
+ import { metadataText } from './frontmatter';
24
29
  import { DROP_CAP_PUNCTUATION, DROP_CAP_SHORT_PARAGRAPH, isDropCap, readDropCap } from './defaults/dropCap';
25
30
  import { outputProfileInfo } from './color/catalogue';
26
31
  import { CODE_OVERFLOWS, CODE_TOKEN_KINDS } from './defaults/codeStyle';
32
+ import { closestKey } from './util/closestKey';
33
+ import { validatePageTemplates } from './composed/validate';
27
34
  import { LINE_NUMBERS_ALIGNS, LINE_NUMBERS_COUNTS, LINE_NUMBERS_MULTI_COLUMN, LINE_NUMBERS_POSITIONS, LINE_NUMBERS_RESTARTS } from './defaults/lineNumbers';
28
35
  /** The format fields and the decimal spelling each falls back to. A
29
36
  * `format` is a format field only under `pageNumbering`. */
@@ -56,16 +63,35 @@ function percentText(n) {
56
63
  * `headings`, its `balancing` and `levels`, `headingStyles`,
57
64
  * `paragraphStyles`). And a setting with a value outside its choices
58
65
  * (`unknownConfigValue`: `direction`, the comics settings' words), and a `numerals` value that names
59
- * no digit system (`unknownNumerals`). Pure.
66
+ * no digit system (`unknownNumerals`). And the design texts that hold
67
+ * the book's content instead of placeholders (`contentInConfig`, #849,
68
+ * tuned by `checks.contentInConfig`). Pure.
60
69
  */
61
- export function collectConfigWarnings(config) {
70
+ export function collectConfigWarnings(config, options = {}) {
62
71
  if (!config)
63
72
  return [];
64
73
  return [
65
74
  ...collectValueWarnings(config), ...collectSideColumnWarnings(config), ...collectColumnCountWarnings(config), ...collectUnknownKeyWarnings(config),
66
75
  ...collectCjkGridWarnings(config), ...collectChoiceWarnings(config), ...collectNumeralsWarnings(config),
76
+ ...collectPageTemplateWarnings(config, options),
77
+ ...collectContentInConfigWarnings(config, options),
67
78
  ];
68
79
  }
80
+ /** Page templates and label styles (#853): see `validatePageTemplates`.
81
+ * Lengths in different units are compared at the page's dpi, an em at
82
+ * the body text's size. */
83
+ function collectPageTemplateWarnings(config, options) {
84
+ const overrides = config.htmlViewer?.overrides;
85
+ const any = config.pageTemplates !== undefined || config.labelStyles !== undefined
86
+ || overrides?.pageTemplates !== undefined || overrides?.labelStyles !== undefined
87
+ || (options.resources ?? []).some((r) => r.anchors?.some((a) => a.style !== undefined));
88
+ if (!any)
89
+ return [];
90
+ const resolved = resolveAllConfig(config);
91
+ const dpi = resolved.page.dpi;
92
+ const baseFontSizePx = dimensionToPx(resolved.bodyText.fontSize, dpi, 16);
93
+ return validatePageTemplates(config, { resources: options.resources, dpi, baseFontSizePx });
94
+ }
69
95
  /** Settings whose value is one of a few words: one written otherwise is
70
96
  * read as the default, and `used` names what that default came to. */
71
97
  function collectChoiceWarnings(config) {
@@ -101,6 +127,11 @@ function collectChoiceWarnings(config) {
101
127
  };
102
128
  rule('bodyText.shortListSplit', config.bodyText?.shortListSplit);
103
129
  rule('layout.openerFloats', config.layout?.openerFloats);
130
+ // What heads a block of the contents (#850): read as `'part'`.
131
+ const tocHead = config.toc?.groups?.head;
132
+ if (tocHead !== undefined && parseTocGroupHead(tocHead) === undefined) {
133
+ out.push({ kind: 'unknownConfigValue', path: 'toc.groups.head', value: String(tocHead), used: 'part' });
134
+ }
104
135
  // Where a heading's number stands (#401).
105
136
  const position = (path, value) => {
106
137
  if (value !== undefined && value !== 'before' && value !== 'replace') {
@@ -117,6 +148,7 @@ function collectChoiceWarnings(config) {
117
148
  out.push(...collectComicChoiceWarnings(config));
118
149
  out.push(...collectPrintChoiceWarnings(config));
119
150
  out.push(...collectContrastChoiceWarnings(config));
151
+ out.push(...collectChecksValueWarnings(config));
120
152
  out.push(...collectLineNumbersWarnings(config));
121
153
  out.push(...collectWrapWarnings(config));
122
154
  out.push(...collectCodeStyleWarnings(config));
@@ -430,6 +462,9 @@ const DROP_CAP_LEAD_IN_KEYS = { words: true, smallCaps: true, uppercase: true };
430
462
  const TAB_STOP_KEYS = {
431
463
  position: true, align: true, leader: true, leaderGap: true, decimalChar: true,
432
464
  };
465
+ // The checks of the configuration (#849).
466
+ const CHECKS_KEYS = { contentInConfig: true };
467
+ const CONTENT_IN_CONFIG_KEYS = { enabled: true, allow: true, maxWords: true, maxChars: true };
433
468
  // Line numbers (#621).
434
469
  const LINE_NUMBERS_KEYS = {
435
470
  enabled: true, count: true, interval: true, numberFirst: true, restart: true, startAt: true, position: true,
@@ -477,44 +512,6 @@ const BALLOON_STYLE_KEYS = {
477
512
  const CAST_KEYS = {
478
513
  id: true, name: true, balloonStyle: true, color: true, fill: true, fontFamily: true,
479
514
  };
480
- /** Edit distance with transpositions (optimal string alignment), capped:
481
- * anything above `max` returns `max + 1`. */
482
- function editDistance(a, b, max) {
483
- if (Math.abs(a.length - b.length) > max)
484
- return max + 1;
485
- const d = Array.from({ length: a.length + 1 }, (_, i) => [i, ...new Array(b.length).fill(0)]);
486
- for (let j = 1; j <= b.length; j++)
487
- d[0][j] = j;
488
- for (let i = 1; i <= a.length; i++) {
489
- for (let j = 1; j <= b.length; j++) {
490
- const cost = a[i - 1] === b[j - 1] ? 0 : 1;
491
- let v = Math.min(d[i - 1][j] + 1, d[i][j - 1] + 1, d[i - 1][j - 1] + cost);
492
- if (i > 1 && j > 1 && a[i - 1] === b[j - 2] && a[i - 2] === b[j - 1])
493
- v = Math.min(v, d[i - 2][j - 2] + 1);
494
- d[i][j] = v;
495
- }
496
- }
497
- return d[a.length][b.length];
498
- }
499
- /** The known key (or word) `key` is a slip of: the same letters in another
500
- * case, or one or two letters apart (a longer key allows two). */
501
- function closestKey(key, known) {
502
- const lower = key.toLowerCase();
503
- const sameCase = known.find((k) => k.toLowerCase() === lower);
504
- if (sameCase)
505
- return sameCase;
506
- const max = key.length >= 8 ? 2 : 1;
507
- let best;
508
- let bestD = max + 1;
509
- for (const k of known) {
510
- const dist = editDistance(lower, k.toLowerCase(), max);
511
- if (dist < bestD) {
512
- best = k;
513
- bestD = dist;
514
- }
515
- }
516
- return best;
517
- }
518
515
  /**
519
516
  * Keys the heading settings do not have (EF-83), or a paragraph style
520
517
  * (EF-173): the engine reads the settings it knows and drops the rest, so
@@ -563,6 +560,9 @@ function collectUnknownKeyWarnings(config) {
563
560
  check(cap.leadIn, DROP_CAP_LEAD_IN_KEYS, `${path}.leadIn`);
564
561
  }
565
562
  check(config.lineNumbers, LINE_NUMBERS_KEYS, 'lineNumbers');
563
+ // The checks of the configuration (#849).
564
+ check(config.checks, CHECKS_KEYS, 'checks');
565
+ check(config.checks?.contentInConfig, CONTENT_IN_CONFIG_KEYS, 'checks.contentInConfig');
566
566
  // Code listings (#624): the section, its token kinds and inline code.
567
567
  const codeStyle = config.codeStyle;
568
568
  if (codeStyle && typeof codeStyle === 'object' && !Array.isArray(codeStyle)) {
@@ -695,4 +695,134 @@ function collectCjkGridWarnings(config) {
695
695
  out.push({ kind: 'cjkGridClamped', path: 'cjk.grid.linesPerPage', value: String(g.clamped.linesPerPage), used: String(g.linesPerPage) });
696
696
  return out;
697
697
  }
698
+ /** A limit of the content check that is no whole number from 0 (#849):
699
+ * the default is used. */
700
+ function collectChecksValueWarnings(config) {
701
+ const c = config.checks?.contentInConfig;
702
+ if (!c || typeof c !== 'object')
703
+ return [];
704
+ const out = [];
705
+ const used = resolveContentInConfigCheck(c);
706
+ for (const key of ['maxWords', 'maxChars']) {
707
+ const v = c[key];
708
+ if (v !== undefined && !(typeof v === 'number' && Number.isInteger(v) && v >= 0)) {
709
+ out.push({ kind: 'unknownConfigValue', path: `checks.contentInConfig.${key}`, value: String(v), used: String(used[key]) });
710
+ }
711
+ }
712
+ return out;
713
+ }
714
+ /** Most element paths a `contentInConfig` warning lists. */
715
+ const CONTENT_IN_CONFIG_MAX_PATHS = 20;
716
+ /** Longest sample of the first literal a `contentInConfig` warning quotes. */
717
+ const CONTENT_IN_CONFIG_SAMPLE = 40;
718
+ /** What a character of a script written without spaces (Chinese,
719
+ * Japanese, Korean, Thai) counts toward `maxChars`: such a text has no
720
+ * words to count, and one of its characters says about as much as a short
721
+ * Latin word, so the default limit of 24 lets eight of them through
722
+ * (`第{number}章`, `こころ`, `夏目漱石`). */
723
+ const UNSPACED_CHAR_WEIGHT = 3;
724
+ const LETTER_OR_DIGIT = /[\p{L}\p{N}]/u;
725
+ const LETTERS_OR_DIGITS = /[\p{L}\p{N}]/gu;
726
+ const UNSPACED_SCRIPT = /[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}\p{Script=Thai}]/u;
727
+ const UNSPACED_LETTERS = /[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}\p{Script=Thai}]/gu;
728
+ /** A literal as the allow list compares it: no case, the words it holds
729
+ * between spaces with the punctuation around them dropped (`·`, a comma,
730
+ * quotes), one space between them. Punctuation inside a word stays, so an
731
+ * address (`postext.dev`) or a version (`4.0`) is one word. */
732
+ function comparableLiteral(text) {
733
+ return text.normalize('NFKC').toLowerCase().split(/\s+/)
734
+ .map((w) => w.replace(/^[^\p{L}\p{N}]+|[^\p{L}\p{N}\p{M}]+$/gu, ''))
735
+ .filter(Boolean).join(' ');
736
+ }
737
+ /** `text` with every occurrence of the allowed phrase `phrase` taken out
738
+ * (both comparable): between spaces, or anywhere in text written without
739
+ * them. */
740
+ function withoutPhrase(text, phrase) {
741
+ if (!phrase || !text)
742
+ return text;
743
+ if (UNSPACED_SCRIPT.test(phrase))
744
+ return text.split(phrase).join(' ').replace(/\s+/g, ' ').trim();
745
+ return ` ${text} `.split(` ${phrase} `).join(' ').replace(/\s+/g, ' ').trim();
746
+ }
747
+ /** The literal text a design text prints whatever the document: its
748
+ * content with every placeholder removed, on one line (#849). */
749
+ export function designTextLiteral(content) {
750
+ return stripPlaceholders(content).replace(/\s+/g, ' ').trim();
751
+ }
752
+ /** What {@link collectConfigWarnings} may read besides the config. */
753
+ /** The phrases of the metadata a design may repeat. */
754
+ function metadataPhrases(metadata) {
755
+ if (!metadata)
756
+ return [];
757
+ const out = [];
758
+ for (const key of ['title', 'subtitle', 'author', 'publisher']) {
759
+ const v = metadata[key];
760
+ const values = Array.isArray(v) ? v : [v];
761
+ for (const one of values) {
762
+ const text = metadataText(one);
763
+ if (text)
764
+ out.push(text);
765
+ }
766
+ }
767
+ return out;
768
+ }
769
+ /** Content held in the configuration (#849): design text elements whose
770
+ * literal text — their content with every placeholder removed, and the
771
+ * phrases of `checks.contentInConfig.allow` (and of the metadata) taken
772
+ * out — is longer than `maxWords` words or `maxChars` letters and digits.
773
+ * One warning per owner (a heading style, a heading level, the page
774
+ * header, a part design…): `path` is the owner, `count` the texts at
775
+ * fault, `chars` their letters and digits, `elements` the path of each
776
+ * (the first 20), `value` the start of the first one's literal. */
777
+ function collectContentInConfigWarnings(config, options) {
778
+ const check = resolveContentInConfigCheck(config.checks?.contentInConfig);
779
+ if (!check.enabled)
780
+ return [];
781
+ const allow = [...new Set([...check.allow, ...metadataPhrases(options.metadata)].map(comparableLiteral).filter(Boolean))]
782
+ .sort((a, b) => b.length - a.length);
783
+ const groups = new Map();
784
+ for (const slot of configDesignSlots(config)) {
785
+ slot.slot.elements.forEach((el, i) => {
786
+ const e = el;
787
+ if (!e || typeof e !== 'object' || e.kind !== 'text' || typeof e.content !== 'string')
788
+ return;
789
+ const literal = designTextLiteral(e.content);
790
+ if (!LETTER_OR_DIGIT.test(literal))
791
+ return;
792
+ let rest = comparableLiteral(literal);
793
+ for (const phrase of allow)
794
+ rest = withoutPhrase(rest, phrase);
795
+ const chars = rest.match(LETTERS_OR_DIGITS)?.length ?? 0;
796
+ if (chars === 0)
797
+ return;
798
+ const unspaced = rest.match(UNSPACED_LETTERS)?.length ?? 0;
799
+ const weight = chars + unspaced * (UNSPACED_CHAR_WEIGHT - 1);
800
+ // A run of unspaced script is no word count: its characters are weighed.
801
+ const words = rest.split(' ').filter((w) => LETTER_OR_DIGIT.test(w) && !UNSPACED_SCRIPT.test(w)).length;
802
+ if (words <= check.maxWords && weight <= check.maxChars)
803
+ return;
804
+ let g = groups.get(slot.owner);
805
+ if (!g) {
806
+ const points = Array.from(literal);
807
+ const sample = points.length > CONTENT_IN_CONFIG_SAMPLE ? `${points.slice(0, CONTENT_IN_CONFIG_SAMPLE - 1).join('').trimEnd()}…` : literal;
808
+ g = { ...(slot.ownerId !== undefined ? { ownerId: slot.ownerId } : {}), elements: [], count: 0, chars: 0, sample };
809
+ groups.set(slot.owner, g);
810
+ }
811
+ g.count++;
812
+ g.chars += chars;
813
+ if (g.elements.length < CONTENT_IN_CONFIG_MAX_PATHS)
814
+ g.elements.push(`${slot.path}.elements[${i}]`);
815
+ });
816
+ }
817
+ return [...groups].map(([owner, g]) => ({
818
+ kind: 'contentInConfig',
819
+ path: owner,
820
+ value: g.sample,
821
+ used: '',
822
+ count: g.count,
823
+ chars: g.chars,
824
+ elements: g.elements,
825
+ ...(g.ownerId !== undefined ? { ownerId: g.ownerId } : {}),
826
+ }));
827
+ }
698
828
  //# sourceMappingURL=configWarnings.js.map