postext 0.3.16 → 0.3.18
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/dist/__tests__/columnBalancing.test.d.ts +2 -0
- package/dist/__tests__/columnBalancing.test.d.ts.map +1 -0
- package/dist/__tests__/columnBalancing.test.js +194 -0
- package/dist/__tests__/columnBalancing.test.js.map +1 -0
- package/dist/__tests__/createLayout.test.js +12 -13
- package/dist/__tests__/createLayout.test.js.map +1 -1
- package/dist/__tests__/defaults/resourceTypes.test.d.ts +2 -0
- package/dist/__tests__/defaults/resourceTypes.test.d.ts.map +1 -0
- package/dist/__tests__/defaults/resourceTypes.test.js +69 -0
- package/dist/__tests__/defaults/resourceTypes.test.js.map +1 -0
- package/dist/__tests__/exports.test.js +60 -0
- package/dist/__tests__/exports.test.js.map +1 -1
- package/dist/__tests__/parse/inlineRef.test.d.ts +2 -0
- package/dist/__tests__/parse/inlineRef.test.d.ts.map +1 -0
- package/dist/__tests__/parse/inlineRef.test.js +83 -0
- package/dist/__tests__/parse/inlineRef.test.js.map +1 -0
- package/dist/__tests__/parse/resourceDirective.test.d.ts +2 -0
- package/dist/__tests__/parse/resourceDirective.test.d.ts.map +1 -0
- package/dist/__tests__/parse/resourceDirective.test.js +55 -0
- package/dist/__tests__/parse/resourceDirective.test.js.map +1 -0
- package/dist/__tests__/pipeline/floatPlacement.test.d.ts +2 -0
- package/dist/__tests__/pipeline/floatPlacement.test.d.ts.map +1 -0
- package/dist/__tests__/pipeline/floatPlacement.test.js +262 -0
- package/dist/__tests__/pipeline/floatPlacement.test.js.map +1 -0
- package/dist/__tests__/pipeline/inlineRefRender.test.d.ts +2 -0
- package/dist/__tests__/pipeline/inlineRefRender.test.d.ts.map +1 -0
- package/dist/__tests__/pipeline/inlineRefRender.test.js +107 -0
- package/dist/__tests__/pipeline/inlineRefRender.test.js.map +1 -0
- package/dist/__tests__/pipeline/resourceNumbering.test.d.ts +2 -0
- package/dist/__tests__/pipeline/resourceNumbering.test.d.ts.map +1 -0
- package/dist/__tests__/pipeline/resourceNumbering.test.js +186 -0
- package/dist/__tests__/pipeline/resourceNumbering.test.js.map +1 -0
- package/dist/__tests__/singleInk.test.d.ts +2 -0
- package/dist/__tests__/singleInk.test.d.ts.map +1 -0
- package/dist/__tests__/singleInk.test.js +42 -0
- package/dist/__tests__/singleInk.test.js.map +1 -0
- package/dist/__tests__/table/model.test.d.ts +2 -0
- package/dist/__tests__/table/model.test.d.ts.map +1 -0
- package/dist/__tests__/table/model.test.js +187 -0
- package/dist/__tests__/table/model.test.js.map +1 -0
- package/dist/canvas-backend/blockRender.d.ts.map +1 -1
- package/dist/canvas-backend/blockRender.js +103 -66
- package/dist/canvas-backend/blockRender.js.map +1 -1
- package/dist/canvas-backend/decorations.d.ts +4 -1
- package/dist/canvas-backend/decorations.d.ts.map +1 -1
- package/dist/canvas-backend/decorations.js +14 -6
- package/dist/canvas-backend/decorations.js.map +1 -1
- package/dist/canvas-backend/headerFooter.d.ts +2 -2
- package/dist/canvas-backend/headerFooter.d.ts.map +1 -1
- package/dist/canvas-backend/headerFooter.js +62 -2
- package/dist/canvas-backend/headerFooter.js.map +1 -1
- package/dist/canvas-backend/index.d.ts +2 -0
- package/dist/canvas-backend/index.d.ts.map +1 -1
- package/dist/canvas-backend/index.js +20 -10
- package/dist/canvas-backend/index.js.map +1 -1
- package/dist/canvas-backend/renderResourceBlock.d.ts +28 -0
- package/dist/canvas-backend/renderResourceBlock.d.ts.map +1 -0
- package/dist/canvas-backend/renderResourceBlock.js +146 -0
- package/dist/canvas-backend/renderResourceBlock.js.map +1 -0
- package/dist/defaults/bodyText.d.ts.map +1 -1
- package/dist/defaults/bodyText.js +30 -0
- package/dist/defaults/bodyText.js.map +1 -1
- package/dist/defaults/captionStyle.d.ts +9 -0
- package/dist/defaults/captionStyle.d.ts.map +1 -0
- package/dist/defaults/captionStyle.js +74 -0
- package/dist/defaults/captionStyle.js.map +1 -0
- package/dist/defaults/debug.d.ts.map +1 -1
- package/dist/defaults/debug.js +6 -0
- package/dist/defaults/debug.js.map +1 -1
- package/dist/defaults/diagramStyle.d.ts +5 -0
- package/dist/defaults/diagramStyle.d.ts.map +1 -0
- package/dist/defaults/diagramStyle.js +29 -0
- package/dist/defaults/diagramStyle.js.map +1 -0
- package/dist/defaults/headerFooter.d.ts +20 -18
- package/dist/defaults/headerFooter.d.ts.map +1 -1
- package/dist/defaults/headerFooter.js +269 -165
- package/dist/defaults/headerFooter.js.map +1 -1
- package/dist/defaults/headings.d.ts +4 -0
- package/dist/defaults/headings.d.ts.map +1 -1
- package/dist/defaults/headings.js +65 -9
- package/dist/defaults/headings.js.map +1 -1
- package/dist/defaults/index.d.ts +5 -1
- package/dist/defaults/index.d.ts.map +1 -1
- package/dist/defaults/index.js +29 -1
- package/dist/defaults/index.js.map +1 -1
- package/dist/defaults/resourceTypes.d.ts +8 -0
- package/dist/defaults/resourceTypes.d.ts.map +1 -0
- package/dist/defaults/resourceTypes.js +43 -0
- package/dist/defaults/resourceTypes.js.map +1 -0
- package/dist/defaults/shared.d.ts.map +1 -1
- package/dist/defaults/shared.js +40 -0
- package/dist/defaults/shared.js.map +1 -1
- package/dist/defaults/tableStyle.d.ts +11 -0
- package/dist/defaults/tableStyle.d.ts.map +1 -0
- package/dist/defaults/tableStyle.js +114 -0
- package/dist/defaults/tableStyle.js.map +1 -0
- package/dist/design/layout.d.ts +94 -0
- package/dist/design/layout.d.ts.map +1 -0
- package/dist/design/layout.js +642 -0
- package/dist/design/layout.js.map +1 -0
- package/dist/design/placeholders.d.ts +29 -0
- package/dist/design/placeholders.d.ts.map +1 -0
- package/dist/design/placeholders.js +126 -0
- package/dist/design/placeholders.js.map +1 -0
- package/dist/html-backend.d.ts +6 -0
- package/dist/html-backend.d.ts.map +1 -1
- package/dist/html-backend.js +274 -10
- package/dist/html-backend.js.map +1 -1
- package/dist/index.d.ts +14 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -2
- package/dist/index.js.map +1 -1
- package/dist/knuthPlass/breakpoints.d.ts.map +1 -1
- package/dist/knuthPlass/breakpoints.js +41 -98
- package/dist/knuthPlass/breakpoints.js.map +1 -1
- package/dist/knuthPlass/richAdapter.d.ts +1 -0
- package/dist/knuthPlass/richAdapter.d.ts.map +1 -1
- package/dist/knuthPlass/richAdapter.js +2 -1
- package/dist/knuthPlass/richAdapter.js.map +1 -1
- package/dist/measure/cache.js +1 -1
- package/dist/measure/cache.js.map +1 -1
- package/dist/measure/canvas.d.ts +3 -0
- package/dist/measure/canvas.d.ts.map +1 -1
- package/dist/measure/canvas.js +40 -2
- package/dist/measure/canvas.js.map +1 -1
- package/dist/measure/font.d.ts +3 -2
- package/dist/measure/font.d.ts.map +1 -1
- package/dist/measure/font.js +5 -2
- package/dist/measure/font.js.map +1 -1
- package/dist/measure/plain.d.ts.map +1 -1
- package/dist/measure/plain.js +14 -7
- package/dist/measure/plain.js.map +1 -1
- package/dist/measure/rich.d.ts +7 -0
- package/dist/measure/rich.d.ts.map +1 -1
- package/dist/measure/rich.js +34 -7
- package/dist/measure/rich.js.map +1 -1
- package/dist/numbering.d.ts +16 -0
- package/dist/numbering.d.ts.map +1 -1
- package/dist/numbering.js +28 -18
- package/dist/numbering.js.map +1 -1
- package/dist/parse/blockParser.d.ts.map +1 -1
- package/dist/parse/blockParser.js +37 -9
- package/dist/parse/blockParser.js.map +1 -1
- package/dist/parse/injectSpans.d.ts +9 -0
- package/dist/parse/injectSpans.d.ts.map +1 -0
- package/dist/parse/injectSpans.js +35 -0
- package/dist/parse/injectSpans.js.map +1 -0
- package/dist/parse/inlineFormatting.d.ts +38 -0
- package/dist/parse/inlineFormatting.d.ts.map +1 -1
- package/dist/parse/inlineFormatting.js +58 -0
- package/dist/parse/inlineFormatting.js.map +1 -1
- package/dist/parse/inlineMath.d.ts.map +1 -1
- package/dist/parse/inlineMath.js +26 -43
- package/dist/parse/inlineMath.js.map +1 -1
- package/dist/parse/sourceMapping.d.ts.map +1 -1
- package/dist/parse/sourceMapping.js +34 -7
- package/dist/parse/sourceMapping.js.map +1 -1
- package/dist/parse/types.d.ts +20 -1
- package/dist/parse/types.d.ts.map +1 -1
- package/dist/pipeline/build.d.ts.map +1 -1
- package/dist/pipeline/build.js +521 -28
- package/dist/pipeline/build.js.map +1 -1
- package/dist/pipeline/buildBlockKind.d.ts +14 -0
- package/dist/pipeline/buildBlockKind.d.ts.map +1 -1
- package/dist/pipeline/buildBlockKind.js +16 -1
- package/dist/pipeline/buildBlockKind.js.map +1 -1
- package/dist/pipeline/buildHelpers.d.ts.map +1 -1
- package/dist/pipeline/buildHelpers.js +7 -1
- package/dist/pipeline/buildHelpers.js.map +1 -1
- package/dist/pipeline/buildMeasurement.d.ts +17 -1
- package/dist/pipeline/buildMeasurement.d.ts.map +1 -1
- package/dist/pipeline/buildMeasurement.js +32 -0
- package/dist/pipeline/buildMeasurement.js.map +1 -1
- package/dist/pipeline/columnBalancing.d.ts +75 -0
- package/dist/pipeline/columnBalancing.d.ts.map +1 -0
- package/dist/pipeline/columnBalancing.js +125 -0
- package/dist/pipeline/columnBalancing.js.map +1 -0
- package/dist/pipeline/config.d.ts +4 -1
- package/dist/pipeline/config.d.ts.map +1 -1
- package/dist/pipeline/config.js +12 -1
- package/dist/pipeline/config.js.map +1 -1
- package/dist/pipeline/floatPlacement.d.ts +45 -0
- package/dist/pipeline/floatPlacement.d.ts.map +1 -0
- package/dist/pipeline/floatPlacement.js +68 -0
- package/dist/pipeline/floatPlacement.js.map +1 -0
- package/dist/pipeline/headerFooter.d.ts +23 -7
- package/dist/pipeline/headerFooter.d.ts.map +1 -1
- package/dist/pipeline/headerFooter.js +260 -100
- package/dist/pipeline/headerFooter.js.map +1 -1
- package/dist/pipeline/lists.d.ts +4 -9
- package/dist/pipeline/lists.d.ts.map +1 -1
- package/dist/pipeline/lists.js +24 -42
- package/dist/pipeline/lists.js.map +1 -1
- package/dist/pipeline/placeholders.d.ts +6 -0
- package/dist/pipeline/placeholders.d.ts.map +1 -1
- package/dist/pipeline/placeholders.js +18 -5
- package/dist/pipeline/placeholders.js.map +1 -1
- package/dist/pipeline/placement.d.ts +15 -2
- package/dist/pipeline/placement.d.ts.map +1 -1
- package/dist/pipeline/placement.js +38 -3
- package/dist/pipeline/placement.js.map +1 -1
- package/dist/pipeline/resourceLayout.d.ts +58 -0
- package/dist/pipeline/resourceLayout.d.ts.map +1 -0
- package/dist/pipeline/resourceLayout.js +338 -0
- package/dist/pipeline/resourceLayout.js.map +1 -0
- package/dist/pipeline/resourceNumbering.d.ts +54 -0
- package/dist/pipeline/resourceNumbering.d.ts.map +1 -0
- package/dist/pipeline/resourceNumbering.js +218 -0
- package/dist/pipeline/resourceNumbering.js.map +1 -0
- package/dist/pipeline/styles.d.ts +6 -0
- package/dist/pipeline/styles.d.ts.map +1 -1
- package/dist/pipeline/styles.js +1 -1
- package/dist/pipeline/styles.js.map +1 -1
- package/dist/svg/singleInk.d.ts +10 -0
- package/dist/svg/singleInk.d.ts.map +1 -0
- package/dist/svg/singleInk.js +86 -0
- package/dist/svg/singleInk.js.map +1 -0
- package/dist/table/model.d.ts +53 -0
- package/dist/table/model.d.ts.map +1 -0
- package/dist/table/model.js +253 -0
- package/dist/table/model.js.map +1 -0
- package/dist/types.d.ts +429 -41
- package/dist/types.d.ts.map +1 -1
- package/dist/vdt.d.ts +181 -18
- package/dist/vdt.d.ts.map +1 -1
- package/dist/vdt.js +34 -0
- package/dist/vdt.js.map +1 -1
- package/package.json +6 -6
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
import type { PostextConfig } from '../types';
|
|
1
|
+
import type { PostextConfig, ResolvedHeadingLevelConfig } from '../types';
|
|
2
2
|
import { type BoundingBox, type ResolvedConfig } from '../vdt';
|
|
3
3
|
export declare function resolveAllConfig(rawConfig?: PostextConfig): ResolvedConfig;
|
|
4
|
+
/** Index heading-level configs by level so per-block lookups in the
|
|
5
|
+
* placement loop are O(1) instead of a linear `.find()`. */
|
|
6
|
+
export declare function buildHeadingLevelMap(resolved: ResolvedConfig): Map<number, ResolvedHeadingLevelConfig>;
|
|
4
7
|
export declare function computeBaselineGrid(resolved: ResolvedConfig): number;
|
|
5
8
|
export declare function computeColumnBboxes(contentArea: BoundingBox, resolved: ResolvedConfig): BoundingBox[];
|
|
6
9
|
//# sourceMappingURL=config.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/pipeline/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/pipeline/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,0BAA0B,EAAE,MAAM,UAAU,CAAC;AAiB1E,OAAO,EAAqB,KAAK,WAAW,EAAE,KAAK,cAAc,EAAE,MAAM,QAAQ,CAAC;AAElF,wBAAgB,gBAAgB,CAAC,SAAS,CAAC,EAAE,aAAa,GAAG,cAAc,CAkB1E;AAED;6DAC6D;AAC7D,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,cAAc,GACvB,GAAG,CAAC,MAAM,EAAE,0BAA0B,CAAC,CAIzC;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,cAAc,GAAG,MAAM,CAUpE;AAED,wBAAgB,mBAAmB,CACjC,WAAW,EAAE,WAAW,EACxB,QAAQ,EAAE,cAAc,GACvB,WAAW,EAAE,CAyBf"}
|
package/dist/pipeline/config.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { resolvePageConfig, resolveLayoutConfig, resolveBodyTextConfig, resolveHeadingsConfig, resolveUnorderedListsConfig, resolveOrderedListsConfig, resolveMathConfig, resolveHeaderFooterConfig, applyPaletteToConfig, applyPaletteToResolvedConfig, } from '../defaults';
|
|
1
|
+
import { resolvePageConfig, resolveLayoutConfig, resolveBodyTextConfig, resolveHeadingsConfig, resolveTableStyleConfig, resolveCaptionStyleConfig, resolveDiagramStyleConfig, resolveUnorderedListsConfig, resolveOrderedListsConfig, resolveMathConfig, resolveHeaderFooterConfig, applyPaletteToConfig, applyPaletteToResolvedConfig, } from '../defaults';
|
|
2
2
|
import { dimensionToPx } from '../units';
|
|
3
3
|
import { createBoundingBox } from '../vdt';
|
|
4
4
|
export function resolveAllConfig(rawConfig) {
|
|
@@ -9,6 +9,9 @@ export function resolveAllConfig(rawConfig) {
|
|
|
9
9
|
layout: resolveLayoutConfig(config?.layout),
|
|
10
10
|
bodyText,
|
|
11
11
|
headings: resolveHeadingsConfig(config?.headings),
|
|
12
|
+
tableStyle: resolveTableStyleConfig(config?.tableStyle, bodyText),
|
|
13
|
+
captionStyle: resolveCaptionStyleConfig(config?.captionStyle, bodyText),
|
|
14
|
+
diagramStyle: resolveDiagramStyleConfig(config?.diagramStyle),
|
|
12
15
|
unorderedLists: resolveUnorderedListsConfig(config?.unorderedLists, bodyText),
|
|
13
16
|
orderedLists: resolveOrderedListsConfig(config?.orderedLists, bodyText),
|
|
14
17
|
math: resolveMathConfig(config?.math),
|
|
@@ -17,6 +20,14 @@ export function resolveAllConfig(rawConfig) {
|
|
|
17
20
|
};
|
|
18
21
|
return applyPaletteToResolvedConfig(resolved, rawConfig?.colorPalette);
|
|
19
22
|
}
|
|
23
|
+
/** Index heading-level configs by level so per-block lookups in the
|
|
24
|
+
* placement loop are O(1) instead of a linear `.find()`. */
|
|
25
|
+
export function buildHeadingLevelMap(resolved) {
|
|
26
|
+
const map = new Map();
|
|
27
|
+
for (const lvl of resolved.headings.levels)
|
|
28
|
+
map.set(lvl.level, lvl);
|
|
29
|
+
return map;
|
|
30
|
+
}
|
|
20
31
|
export function computeBaselineGrid(resolved) {
|
|
21
32
|
const dpi = resolved.page.dpi;
|
|
22
33
|
const bodyFontSizePx = dimensionToPx(resolved.bodyText.fontSize, dpi);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/pipeline/config.ts"],"names":[],"mappings":"AACA,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,qBAAqB,EACrB,qBAAqB,EACrB,2BAA2B,EAC3B,yBAAyB,EACzB,iBAAiB,EACjB,yBAAyB,EACzB,oBAAoB,EACpB,4BAA4B,GAC7B,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,iBAAiB,EAAyC,MAAM,QAAQ,CAAC;AAElF,MAAM,UAAU,gBAAgB,CAAC,SAAyB;IACxD,MAAM,MAAM,GAAG,oBAAoB,CAAC,SAAS,CAAC,CAAC;IAC/C,MAAM,QAAQ,GAAG,qBAAqB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACzD,MAAM,QAAQ,GAAmB;QAC/B,IAAI,EAAE,iBAAiB,CAAC,MAAM,EAAE,IAAI,CAAC;QACrC,MAAM,EAAE,mBAAmB,CAAC,MAAM,EAAE,MAAM,CAAC;QAC3C,QAAQ;QACR,QAAQ,EAAE,qBAAqB,CAAC,MAAM,EAAE,QAAQ,CAAC;QACjD,cAAc,EAAE,2BAA2B,CAAC,MAAM,EAAE,cAAc,EAAE,QAAQ,CAAC;QAC7E,YAAY,EAAE,yBAAyB,CAAC,MAAM,EAAE,YAAY,EAAE,QAAQ,CAAC;QACvE,IAAI,EAAE,iBAAiB,CAAC,MAAM,EAAE,IAAI,CAAC;QACrC,MAAM,EAAE,yBAAyB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC;QAC3D,MAAM,EAAE,yBAAyB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC;KAC5D,CAAC;IACF,OAAO,4BAA4B,CAAC,QAAQ,EAAE,SAAS,EAAE,YAAY,CAAC,CAAC;AACzE,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,QAAwB;IAC1D,MAAM,GAAG,GAAG,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC;IAC9B,MAAM,cAAc,GAAG,aAAa,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;IACtE,MAAM,aAAa,GAAG,QAAQ,CAAC,QAAQ,CAAC,UAAU,CAAC;IAEnD,0DAA0D;IAC1D,IAAI,aAAa,CAAC,IAAI,KAAK,IAAI,IAAI,aAAa,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;QAChE,OAAO,cAAc,GAAG,aAAa,CAAC,KAAK,CAAC;IAC9C,CAAC;IACD,OAAO,aAAa,CAAC,aAAa,EAAE,GAAG,EAAE,cAAc,CAAC,CAAC;AAC3D,CAAC;AAED,MAAM,UAAU,mBAAmB,CACjC,WAAwB,EACxB,QAAwB;IAExB,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,iBAAiB,EAAE,GAAG,QAAQ,CAAC,MAAM,CAAC;IACvE,MAAM,GAAG,GAAG,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC;IAE9B,IAAI,UAAU,KAAK,QAAQ,EAAE,CAAC;QAC5B,OAAO,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,EAAE,WAAW,CAAC,KAAK,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC;IAClG,CAAC;IAED,MAAM,QAAQ,GAAG,aAAa,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;IAEjD,IAAI,UAAU,KAAK,QAAQ,EAAE,CAAC;QAC5B,MAAM,QAAQ,GAAG,CAAC,WAAW,CAAC,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;QACpD,OAAO;YACL,iBAAiB,CAAC,WAAW,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,EAAE,QAAQ,EAAE,WAAW,CAAC,MAAM,CAAC;YAC7E,iBAAiB,CAAC,WAAW,CAAC,CAAC,GAAG,QAAQ,GAAG,QAAQ,EAAE,WAAW,CAAC,CAAC,EAAE,QAAQ,EAAE,WAAW,CAAC,MAAM,CAAC;SACpG,CAAC;IACJ,CAAC;IAED,aAAa;IACb,MAAM,SAAS,GAAG,WAAW,CAAC,KAAK,GAAG,CAAC,iBAAiB,GAAG,GAAG,CAAC,CAAC;IAChE,MAAM,SAAS,GAAG,WAAW,CAAC,KAAK,GAAG,SAAS,GAAG,QAAQ,CAAC;IAC3D,OAAO;QACL,iBAAiB,CAAC,WAAW,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,EAAE,SAAS,EAAE,WAAW,CAAC,MAAM,CAAC;QAC9E,iBAAiB,CAAC,WAAW,CAAC,CAAC,GAAG,SAAS,GAAG,QAAQ,EAAE,WAAW,CAAC,CAAC,EAAE,SAAS,EAAE,WAAW,CAAC,MAAM,CAAC;KACtG,CAAC;AACJ,CAAC"}
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/pipeline/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Float planning (issue #49 §7 — Placement, revised model).
|
|
3
|
+
*
|
|
4
|
+
* In the revised model a resource is *incorporated by reference*: the first
|
|
5
|
+
* time it is mentioned (an inline `:ref` or a `::resource` directive, whichever
|
|
6
|
+
* comes first in reading order) the engine floats it to a band at the top or
|
|
7
|
+
* bottom of the page near that reference. The author never places it twice and
|
|
8
|
+
* the running text flows past the reference uninterrupted.
|
|
9
|
+
*
|
|
10
|
+
* This module is the pure planning half: it resolves each resource's placement
|
|
11
|
+
* and produces the ordered list of floats with the content-block index of their
|
|
12
|
+
* first reference. The geometry (reserving page bands, positioning the float
|
|
13
|
+
* blocks, deferring overflow to the next page) lives in the build pipeline,
|
|
14
|
+
* which owns the VDT and measurement context.
|
|
15
|
+
*/
|
|
16
|
+
import type { ContentBlock } from '../parse';
|
|
17
|
+
import type { Resource, ResourceType, ResourceFloatPosition, ResourceFloatSpan } from '../types';
|
|
18
|
+
/** Resolved placement for a resource: never `undefined` fields. */
|
|
19
|
+
export interface ResolvedPlacement {
|
|
20
|
+
position: ResourceFloatPosition;
|
|
21
|
+
span: ResourceFloatSpan;
|
|
22
|
+
}
|
|
23
|
+
/** A planned float: the resource, its resolved placement, and the index of the
|
|
24
|
+
* content block where it is first referenced (its anchor). */
|
|
25
|
+
export interface PlannedFloat {
|
|
26
|
+
resourceId: string;
|
|
27
|
+
firstBlockIdx: number;
|
|
28
|
+
position: 'top' | 'bottom';
|
|
29
|
+
span: ResourceFloatSpan;
|
|
30
|
+
}
|
|
31
|
+
/** Resolve a resource's placement: own `placement` → its type's
|
|
32
|
+
* `defaultPlacement` → the built-in default (`top` / `column`). */
|
|
33
|
+
export declare function resolveResourcePlacement(resource: Resource, type: ResourceType | undefined): ResolvedPlacement;
|
|
34
|
+
/**
|
|
35
|
+
* Walk the parsed blocks in reading order and produce the floats to place, in
|
|
36
|
+
* first-reference order. A resource is floated when its resolved position is
|
|
37
|
+
* `'top'` or `'bottom'`; `'here'` resources are left for inline `::resource`
|
|
38
|
+
* placement and are not returned here. Resources with an unknown id or type are
|
|
39
|
+
* skipped (the warnings phase surfaces those).
|
|
40
|
+
*/
|
|
41
|
+
export declare function computeFloatPlan(blocks: ContentBlock[], resources: Resource[], resourceTypes: ResourceType[]): PlannedFloat[];
|
|
42
|
+
/** The set of resource ids that float (so the build loop can skip their inline
|
|
43
|
+
* `::resource` placement). Derived from a {@link computeFloatPlan} result. */
|
|
44
|
+
export declare function floatedResourceIds(plan: PlannedFloat[]): Set<string>;
|
|
45
|
+
//# sourceMappingURL=floatPlacement.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"floatPlacement.d.ts","sourceRoot":"","sources":["../../src/pipeline/floatPlacement.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,KAAK,EACV,QAAQ,EACR,YAAY,EACZ,qBAAqB,EACrB,iBAAiB,EAClB,MAAM,UAAU,CAAC;AAElB,mEAAmE;AACnE,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,qBAAqB,CAAC;IAChC,IAAI,EAAE,iBAAiB,CAAC;CACzB;AAED;+DAC+D;AAC/D,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,KAAK,GAAG,QAAQ,CAAC;IAC3B,IAAI,EAAE,iBAAiB,CAAC;CACzB;AAED;oEACoE;AACpE,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,QAAQ,EAClB,IAAI,EAAE,YAAY,GAAG,SAAS,GAC7B,iBAAiB,CAKnB;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,YAAY,EAAE,EACtB,SAAS,EAAE,QAAQ,EAAE,EACrB,aAAa,EAAE,YAAY,EAAE,GAC5B,YAAY,EAAE,CA6BhB;AAED;+EAC+E;AAC/E,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,YAAY,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC,CAEpE"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Float planning (issue #49 §7 — Placement, revised model).
|
|
3
|
+
*
|
|
4
|
+
* In the revised model a resource is *incorporated by reference*: the first
|
|
5
|
+
* time it is mentioned (an inline `:ref` or a `::resource` directive, whichever
|
|
6
|
+
* comes first in reading order) the engine floats it to a band at the top or
|
|
7
|
+
* bottom of the page near that reference. The author never places it twice and
|
|
8
|
+
* the running text flows past the reference uninterrupted.
|
|
9
|
+
*
|
|
10
|
+
* This module is the pure planning half: it resolves each resource's placement
|
|
11
|
+
* and produces the ordered list of floats with the content-block index of their
|
|
12
|
+
* first reference. The geometry (reserving page bands, positioning the float
|
|
13
|
+
* blocks, deferring overflow to the next page) lives in the build pipeline,
|
|
14
|
+
* which owns the VDT and measurement context.
|
|
15
|
+
*/
|
|
16
|
+
/** Resolve a resource's placement: own `placement` → its type's
|
|
17
|
+
* `defaultPlacement` → the built-in default (`top` / `column`). */
|
|
18
|
+
export function resolveResourcePlacement(resource, type) {
|
|
19
|
+
const position = resource.placement?.position ?? type?.defaultPlacement?.position ?? 'top';
|
|
20
|
+
const span = resource.placement?.span ?? type?.defaultPlacement?.span ?? 'column';
|
|
21
|
+
return { position, span };
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Walk the parsed blocks in reading order and produce the floats to place, in
|
|
25
|
+
* first-reference order. A resource is floated when its resolved position is
|
|
26
|
+
* `'top'` or `'bottom'`; `'here'` resources are left for inline `::resource`
|
|
27
|
+
* placement and are not returned here. Resources with an unknown id or type are
|
|
28
|
+
* skipped (the warnings phase surfaces those).
|
|
29
|
+
*/
|
|
30
|
+
export function computeFloatPlan(blocks, resources, resourceTypes) {
|
|
31
|
+
const resourceById = new Map();
|
|
32
|
+
for (const r of resources)
|
|
33
|
+
resourceById.set(r.id, r);
|
|
34
|
+
const typeById = new Map();
|
|
35
|
+
for (const t of resourceTypes)
|
|
36
|
+
typeById.set(t.id, t);
|
|
37
|
+
const plan = [];
|
|
38
|
+
const seen = new Set();
|
|
39
|
+
const record = (resourceId, blockIdx) => {
|
|
40
|
+
if (seen.has(resourceId))
|
|
41
|
+
return;
|
|
42
|
+
seen.add(resourceId);
|
|
43
|
+
const resource = resourceById.get(resourceId);
|
|
44
|
+
if (!resource)
|
|
45
|
+
return;
|
|
46
|
+
const type = typeById.get(resource.typeId);
|
|
47
|
+
const { position, span } = resolveResourcePlacement(resource, type);
|
|
48
|
+
if (position === 'here')
|
|
49
|
+
return;
|
|
50
|
+
plan.push({ resourceId, firstBlockIdx: blockIdx, position, span });
|
|
51
|
+
};
|
|
52
|
+
for (let i = 0; i < blocks.length; i++) {
|
|
53
|
+
const b = blocks[i];
|
|
54
|
+
if (b.type === 'resourceBlock' && b.resourceId)
|
|
55
|
+
record(b.resourceId, i);
|
|
56
|
+
for (const span of b.spans) {
|
|
57
|
+
if (span.ref?.resourceId)
|
|
58
|
+
record(span.ref.resourceId, i);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return plan;
|
|
62
|
+
}
|
|
63
|
+
/** The set of resource ids that float (so the build loop can skip their inline
|
|
64
|
+
* `::resource` placement). Derived from a {@link computeFloatPlan} result. */
|
|
65
|
+
export function floatedResourceIds(plan) {
|
|
66
|
+
return new Set(plan.map((f) => f.resourceId));
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=floatPlacement.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"floatPlacement.js","sourceRoot":"","sources":["../../src/pipeline/floatPlacement.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAyBH;oEACoE;AACpE,MAAM,UAAU,wBAAwB,CACtC,QAAkB,EAClB,IAA8B;IAE9B,MAAM,QAAQ,GACZ,QAAQ,CAAC,SAAS,EAAE,QAAQ,IAAI,IAAI,EAAE,gBAAgB,EAAE,QAAQ,IAAI,KAAK,CAAC;IAC5E,MAAM,IAAI,GAAG,QAAQ,CAAC,SAAS,EAAE,IAAI,IAAI,IAAI,EAAE,gBAAgB,EAAE,IAAI,IAAI,QAAQ,CAAC;IAClF,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;AAC5B,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAC9B,MAAsB,EACtB,SAAqB,EACrB,aAA6B;IAE7B,MAAM,YAAY,GAAG,IAAI,GAAG,EAAoB,CAAC;IACjD,KAAK,MAAM,CAAC,IAAI,SAAS;QAAE,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;IACrD,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAwB,CAAC;IACjD,KAAK,MAAM,CAAC,IAAI,aAAa;QAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;IAErD,MAAM,IAAI,GAAmB,EAAE,CAAC;IAChC,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAE/B,MAAM,MAAM,GAAG,CAAC,UAAkB,EAAE,QAAgB,EAAE,EAAE;QACtD,IAAI,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC;YAAE,OAAO;QACjC,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QACrB,MAAM,QAAQ,GAAG,YAAY,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QAC9C,IAAI,CAAC,QAAQ;YAAE,OAAO;QACtB,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QAC3C,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,wBAAwB,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QACpE,IAAI,QAAQ,KAAK,MAAM;YAAE,OAAO;QAChC,IAAI,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,aAAa,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;IACrE,CAAC,CAAC;IAEF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACvC,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,CAAE,CAAC;QACrB,IAAI,CAAC,CAAC,IAAI,KAAK,eAAe,IAAI,CAAC,CAAC,UAAU;YAAE,MAAM,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;QACxE,KAAK,MAAM,IAAI,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC;YAC3B,IAAI,IAAI,CAAC,GAAG,EAAE,UAAU;gBAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED;+EAC+E;AAC/E,MAAM,UAAU,kBAAkB,CAAC,IAAoB;IACrD,OAAO,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC;AAChD,CAAC"}
|
|
@@ -1,11 +1,27 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { DocumentMetadata, ResolvedDesignSlot, ResolvedHeadingLevelConfig } from '../types';
|
|
2
|
+
import { type VDTDocument, type VDTDesignSlot } from '../vdt';
|
|
3
|
+
import type { DesignPlaceholderContext } from '../design/placeholders';
|
|
4
|
+
/** Measure the natural bottom of a heading's advanced-design slot when laid
|
|
5
|
+
* out against a container of the given `width` with unbounded height.
|
|
6
|
+
* Returns 0 if the level has no advanced design or the slot is empty. Used
|
|
7
|
+
* during body layout to enlarge a heading block's reserved height so
|
|
8
|
+
* subsequent blocks sit below the actual bottom of the design content
|
|
9
|
+
* rather than below the natural text bottom. Applies to both in-column
|
|
10
|
+
* headings (overlay in block bbox) and page-spanning openers (width is the
|
|
11
|
+
* full content area; passed in by the caller). */
|
|
12
|
+
export declare function measureHeadingAdvancedDesignHeight(level: ResolvedHeadingLevelConfig, heading: {
|
|
13
|
+
titleText: string;
|
|
14
|
+
formattedNumber: string;
|
|
15
|
+
chapterNumber: string;
|
|
16
|
+
}, width: number, dpi: number, metadata: DocumentMetadata, pageIndex: number): number;
|
|
17
|
+
export declare function layoutSlotToVdt(slot: ResolvedDesignSlot, container: {
|
|
18
|
+
x: number;
|
|
19
|
+
y: number;
|
|
20
|
+
width: number;
|
|
21
|
+
height: number;
|
|
22
|
+
}, pageIndex: number, placeholders: DesignPlaceholderContext, dpi: number): VDTDesignSlot | undefined;
|
|
2
23
|
/**
|
|
3
|
-
* After body placement finishes, attach header/footer slots
|
|
4
|
-
* rendered text/rule blocks) to every page of the document.
|
|
5
|
-
*
|
|
6
|
-
* Headers and footers are rendered inside the existing page margins — they
|
|
7
|
-
* do not consume body space. Header elements stack upward from the body's
|
|
8
|
-
* top edge; footer elements stack downward from the body's bottom edge.
|
|
24
|
+
* After body placement finishes, attach header/footer slots to every page.
|
|
9
25
|
*/
|
|
10
26
|
export declare function buildHeadersAndFooters(doc: VDTDocument): void;
|
|
11
27
|
//# sourceMappingURL=headerFooter.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"headerFooter.d.ts","sourceRoot":"","sources":["../../src/pipeline/headerFooter.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"headerFooter.d.ts","sourceRoot":"","sources":["../../src/pipeline/headerFooter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,kBAAkB,EAA6B,0BAA0B,EAAE,MAAM,UAAU,CAAC;AAC5H,OAAO,EAGL,KAAK,WAAW,EAChB,KAAK,aAAa,EAMnB,MAAM,QAAQ,CAAC;AAWhB,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AA0GvE;;;;;;;mDAOmD;AACnD,wBAAgB,kCAAkC,CAChD,KAAK,EAAE,0BAA0B,EACjC,OAAO,EAAE;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,eAAe,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE,EAC9E,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,gBAAgB,EAC1B,SAAS,EAAE,MAAM,GAChB,MAAM,CAsBR;AAED,wBAAgB,eAAe,CAC7B,IAAI,EAAE,kBAAkB,EACxB,SAAS,EAAE;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,EAClE,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,wBAAwB,EACtC,GAAG,EAAE,MAAM,GACV,aAAa,GAAG,SAAS,CAQ3B;AAsED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,WAAW,GAAG,IAAI,CAmH7D"}
|
|
@@ -1,134 +1,294 @@
|
|
|
1
1
|
import { createBoundingBox, } from '../vdt';
|
|
2
|
-
import {
|
|
3
|
-
import { buildFontString, measureTextWidth } from '../measure';
|
|
4
|
-
import { computeChapterTitles, resolvePlaceholders } from './placeholders';
|
|
2
|
+
import { computeChapterTitles, computeChapterNumbers } from './placeholders';
|
|
5
3
|
import { computePageMetrics } from './buildHelpers';
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
4
|
+
import { buildHeadingLevelMap } from './config';
|
|
5
|
+
import { layoutDesignSlot, } from '../design/layout';
|
|
6
|
+
/** Slots live in the page margin area between the body edge and the page
|
|
7
|
+
* edge. Header slot container: from `top-margin` edge down to body top.
|
|
8
|
+
* Footer slot container: from body bottom down to `bottom-margin` edge.
|
|
9
|
+
*
|
|
10
|
+
* We use a larger container (the full page vertical extent of the margin
|
|
11
|
+
* area) so that anchors like `bottom-center` / `bottom-right` for headers
|
|
12
|
+
* and `top-*` for footers align with the body edge (the body-facing side
|
|
13
|
+
* of the margin area) rather than the outer page edge.
|
|
14
|
+
*
|
|
15
|
+
* This matches the legacy semantics: `marginFromBody` was "distance from
|
|
16
|
+
* body edge" — the migration translates that to an offset of the same
|
|
17
|
+
* magnitude from the body-facing edge. */
|
|
18
|
+
function headerContainerBbox(contentArea, _pageHeight) {
|
|
19
|
+
// Header: spans from top of page to body top.
|
|
20
|
+
return { x: contentArea.x, y: 0, width: contentArea.width, height: contentArea.y };
|
|
21
21
|
}
|
|
22
|
-
function
|
|
23
|
-
|
|
22
|
+
function footerContainerBbox(contentArea, pageHeight) {
|
|
23
|
+
const bodyBottom = contentArea.y + contentArea.height;
|
|
24
|
+
return {
|
|
25
|
+
x: contentArea.x,
|
|
26
|
+
y: bodyBottom,
|
|
27
|
+
width: contentArea.width,
|
|
28
|
+
height: Math.max(0, pageHeight - bodyBottom),
|
|
29
|
+
};
|
|
24
30
|
}
|
|
25
|
-
function
|
|
31
|
+
function textAlignOffsetX(align, contentWidth, lineWidth) {
|
|
26
32
|
if (align === 'left')
|
|
27
|
-
return
|
|
33
|
+
return 0;
|
|
28
34
|
if (align === 'right')
|
|
29
|
-
return
|
|
30
|
-
return
|
|
35
|
+
return Math.max(0, contentWidth - lineWidth);
|
|
36
|
+
return Math.max(0, (contentWidth - lineWidth) / 2);
|
|
37
|
+
}
|
|
38
|
+
function primitiveToBlock(prim) {
|
|
39
|
+
if (prim.kind === 'text')
|
|
40
|
+
return textPrimitiveToBlock(prim);
|
|
41
|
+
if (prim.kind === 'rule')
|
|
42
|
+
return rulePrimitiveToBlock(prim);
|
|
43
|
+
return boxPrimitiveToBlock(prim);
|
|
31
44
|
}
|
|
32
|
-
function
|
|
33
|
-
const
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
45
|
+
function textPrimitiveToBlock(prim) {
|
|
46
|
+
const totalContentHeight = prim.lines.reduce((s, l) => Math.max(s, l.topY + l.height), 0);
|
|
47
|
+
const vOffset = prim.verticalAlign === 'top' ? 0
|
|
48
|
+
: prim.verticalAlign === 'bottom' ? Math.max(0, prim.contentHeight - totalContentHeight)
|
|
49
|
+
: Math.max(0, (prim.contentHeight - totalContentHeight) / 2);
|
|
50
|
+
const lines = prim.lines.map((l) => ({
|
|
51
|
+
text: l.text,
|
|
52
|
+
xOffset: prim.contentX + textAlignOffsetX(prim.align, prim.contentWidth, l.width),
|
|
53
|
+
baselineY: prim.y + prim.contentY + vOffset + l.baselineY,
|
|
54
|
+
width: l.width,
|
|
55
|
+
}));
|
|
43
56
|
return {
|
|
44
57
|
kind: 'text',
|
|
45
|
-
bbox: createBoundingBox(x,
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
58
|
+
bbox: createBoundingBox(prim.x, prim.y, prim.width, prim.height),
|
|
59
|
+
fontString: prim.fontString,
|
|
60
|
+
color: prim.color,
|
|
61
|
+
lines,
|
|
62
|
+
box: prim.box
|
|
63
|
+
? {
|
|
64
|
+
backgroundColor: prim.box.backgroundColor,
|
|
65
|
+
borderColor: prim.box.borderColor,
|
|
66
|
+
borderWidthPx: prim.box.borderWidthPx,
|
|
67
|
+
borderRadiusPx: prim.box.borderRadiusPx,
|
|
68
|
+
}
|
|
69
|
+
: undefined,
|
|
70
|
+
clip: prim.needsClip,
|
|
51
71
|
};
|
|
52
72
|
}
|
|
53
|
-
function
|
|
54
|
-
const thicknessPx = dimensionToPx(el.thickness, dpi);
|
|
55
|
-
const widthPx = el.width === 'full' ? contentWidth : dimensionToPx(el.width, dpi);
|
|
56
|
-
// `marginFromEdge` only meaningful for non-full rules — a full-width rule
|
|
57
|
-
// already spans the content, so the inset would just crop it asymmetrically.
|
|
58
|
-
const edgeInsetPx = el.width === 'full' ? 0 : dimensionToPx(el.marginFromEdge, dpi);
|
|
59
|
-
const x = xForAlign(el.align, contentX, contentWidth, widthPx, edgeInsetPx);
|
|
73
|
+
function rulePrimitiveToBlock(prim) {
|
|
60
74
|
return {
|
|
61
75
|
kind: 'rule',
|
|
62
|
-
bbox: createBoundingBox(x,
|
|
63
|
-
color:
|
|
64
|
-
thicknessPx,
|
|
76
|
+
bbox: createBoundingBox(prim.x, prim.y, prim.width, prim.height),
|
|
77
|
+
color: prim.color,
|
|
78
|
+
thicknessPx: prim.thicknessPx,
|
|
79
|
+
direction: prim.direction,
|
|
65
80
|
};
|
|
66
81
|
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
82
|
+
function boxPrimitiveToBlock(prim) {
|
|
83
|
+
return {
|
|
84
|
+
kind: 'box',
|
|
85
|
+
bbox: createBoundingBox(prim.x, prim.y, prim.width, prim.height),
|
|
86
|
+
box: {
|
|
87
|
+
backgroundColor: prim.box.backgroundColor,
|
|
88
|
+
borderColor: prim.box.borderColor,
|
|
89
|
+
borderWidthPx: prim.box.borderWidthPx,
|
|
90
|
+
borderRadiusPx: prim.box.borderRadiusPx,
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
/** Measure the natural bottom of a heading's advanced-design slot when laid
|
|
95
|
+
* out against a container of the given `width` with unbounded height.
|
|
96
|
+
* Returns 0 if the level has no advanced design or the slot is empty. Used
|
|
97
|
+
* during body layout to enlarge a heading block's reserved height so
|
|
98
|
+
* subsequent blocks sit below the actual bottom of the design content
|
|
99
|
+
* rather than below the natural text bottom. Applies to both in-column
|
|
100
|
+
* headings (overlay in block bbox) and page-spanning openers (width is the
|
|
101
|
+
* full content area; passed in by the caller). */
|
|
102
|
+
export function measureHeadingAdvancedDesignHeight(level, heading, width, dpi, metadata, pageIndex) {
|
|
103
|
+
if (!level.advancedDesign.enabled)
|
|
104
|
+
return 0;
|
|
105
|
+
if (level.advancedDesign.slot.elements.length === 0)
|
|
106
|
+
return 0;
|
|
107
|
+
const stubPage = { index: pageIndex, pageLabel: '1' };
|
|
108
|
+
const placeholders = {
|
|
109
|
+
kind: 'heading',
|
|
110
|
+
page: stubPage,
|
|
111
|
+
allPages: [stubPage],
|
|
83
112
|
metadata,
|
|
84
|
-
chapterTitleByPageIndex,
|
|
113
|
+
chapterTitleByPageIndex: [],
|
|
114
|
+
heading,
|
|
85
115
|
};
|
|
86
|
-
const
|
|
87
|
-
let
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
const height = elementHeightPx(el, dpi);
|
|
91
|
-
const marginPx = dimensionToPx(el.marginFromBody, dpi);
|
|
92
|
-
// For a header (anchor='bottom' at body top): element's bottom edge sits
|
|
93
|
-
// `marginPx` above the body. For a footer (anchor='top' at body bottom):
|
|
94
|
-
// element's top edge sits `marginPx` below the body.
|
|
95
|
-
const elementTop = anchor === 'bottom' ? anchorY - marginPx - height : anchorY + marginPx;
|
|
96
|
-
if (el.kind === 'text') {
|
|
97
|
-
const { text } = resolvePlaceholders(el.content, ctx);
|
|
98
|
-
if (text.length > 0) {
|
|
99
|
-
blocks.push(buildTextBlock(el, text, contentX, contentWidth, elementTop, dpi));
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
else {
|
|
103
|
-
blocks.push(buildRuleBlock(el, contentX, contentWidth, elementTop, dpi));
|
|
104
|
-
}
|
|
105
|
-
minY = Math.min(minY, elementTop);
|
|
106
|
-
maxBottom = Math.max(maxBottom, elementTop + height);
|
|
116
|
+
const result = layoutDesignSlot(level.advancedDesign.slot, { container: { x: 0, y: 0, width, height: 1e6 }, dpi, placeholders }, pageIndex);
|
|
117
|
+
let bottom = 0;
|
|
118
|
+
for (const prim of result.primitives) {
|
|
119
|
+
bottom = Math.max(bottom, prim.y + prim.height);
|
|
107
120
|
}
|
|
108
|
-
|
|
121
|
+
return bottom;
|
|
122
|
+
}
|
|
123
|
+
export function layoutSlotToVdt(slot, container, pageIndex, placeholders, dpi) {
|
|
124
|
+
const result = layoutDesignSlot(slot, { container, dpi, placeholders }, pageIndex);
|
|
125
|
+
if (result.primitives.length === 0)
|
|
109
126
|
return undefined;
|
|
110
|
-
const
|
|
111
|
-
return {
|
|
127
|
+
const blocks = result.primitives.map(primitiveToBlock);
|
|
128
|
+
return {
|
|
129
|
+
bbox: createBoundingBox(container.x, container.y, container.width, container.height),
|
|
130
|
+
blocks,
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
/** Container bbox for a page-spanning heading opener band: occupies the
|
|
134
|
+
* vertical band the heading block reserved in its column, extended
|
|
135
|
+
* horizontally across the full content area (both columns) — but NOT beyond
|
|
136
|
+
* the page margins. */
|
|
137
|
+
function openerContainerBbox(block, contentArea) {
|
|
138
|
+
return { x: contentArea.x, y: block.bbox.y, width: contentArea.width, height: block.bbox.height };
|
|
139
|
+
}
|
|
140
|
+
/** Find the first heading block on `page` that belongs to a level with
|
|
141
|
+
* `span === 'page'`. Returns the block and info needed to resolve
|
|
142
|
+
* placeholders in the design slot. Triggers regardless of whether
|
|
143
|
+
* `advancedDesign.enabled` is true — when false, the pipeline synthesises
|
|
144
|
+
* a default slot from the heading level typography. */
|
|
145
|
+
function findOpenerHeading(page, headingLevelByNumber) {
|
|
146
|
+
for (const col of page.columns) {
|
|
147
|
+
for (const block of col.blocks) {
|
|
148
|
+
if (block.type !== 'heading' || !block.headingLevel)
|
|
149
|
+
continue;
|
|
150
|
+
const lvl = headingLevelByNumber.get(block.headingLevel);
|
|
151
|
+
if (!lvl)
|
|
152
|
+
continue;
|
|
153
|
+
if (lvl.span !== 'page')
|
|
154
|
+
continue;
|
|
155
|
+
const full = block.lines
|
|
156
|
+
.map((ln) => (ln.segments ?? []).map((s) => s.text).join(''))
|
|
157
|
+
.join(' ');
|
|
158
|
+
const pref = block.numberPrefix ?? '';
|
|
159
|
+
const title = pref && full.startsWith(`${pref} `) ? full.slice(pref.length + 1) : full;
|
|
160
|
+
return { block, level: block.headingLevel, titleText: title, numberPrefix: pref };
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
return undefined;
|
|
164
|
+
}
|
|
165
|
+
/** Build a synthesised default design slot for a `span: 'page'` heading when
|
|
166
|
+
* the user has not configured an `advancedDesign.slot`. Renders as a single
|
|
167
|
+
* text element, anchored to fill the full-page-width container, using the
|
|
168
|
+
* heading level's resolved typography. Emits `{formattedNumber} {titleText}`
|
|
169
|
+
* when the heading carries a numberPrefix, otherwise `{titleText}`. */
|
|
170
|
+
function synthesiseDefaultOpenerSlot(level, hasNumberPrefix) {
|
|
171
|
+
const content = hasNumberPrefix ? '{formattedNumber} {titleText}' : '{titleText}';
|
|
172
|
+
const textEl = {
|
|
173
|
+
kind: 'text',
|
|
174
|
+
id: 'defaultHeadingOpener',
|
|
175
|
+
parity: 'all',
|
|
176
|
+
placement: {
|
|
177
|
+
anchor: { to: 'container', edge: 'top-left' },
|
|
178
|
+
offset: { x: { value: 0, unit: 'pt' }, y: { value: 0, unit: 'pt' } },
|
|
179
|
+
size: { width: 'fill', height: 'fill' },
|
|
180
|
+
},
|
|
181
|
+
content,
|
|
182
|
+
fontFamily: level.fontFamily,
|
|
183
|
+
fontSize: level.fontSize,
|
|
184
|
+
fontWeight: level.fontWeight,
|
|
185
|
+
italic: level.italic,
|
|
186
|
+
color: level.color,
|
|
187
|
+
align: 'left',
|
|
188
|
+
verticalAlign: 'middle',
|
|
189
|
+
lineHeight: level.lineHeight.unit === 'em' ? level.lineHeight.value : 1.2,
|
|
190
|
+
overflow: 'wrap',
|
|
191
|
+
hyphenate: true,
|
|
192
|
+
};
|
|
193
|
+
return { elements: [textEl] };
|
|
112
194
|
}
|
|
113
195
|
/**
|
|
114
|
-
* After body placement finishes, attach header/footer slots
|
|
115
|
-
* rendered text/rule blocks) to every page of the document.
|
|
116
|
-
*
|
|
117
|
-
* Headers and footers are rendered inside the existing page margins — they
|
|
118
|
-
* do not consume body space. Header elements stack upward from the body's
|
|
119
|
-
* top edge; footer elements stack downward from the body's bottom edge.
|
|
196
|
+
* After body placement finishes, attach header/footer slots to every page.
|
|
120
197
|
*/
|
|
121
198
|
export function buildHeadersAndFooters(doc) {
|
|
122
199
|
const resolved = doc.config;
|
|
123
200
|
const dpi = resolved.page.dpi;
|
|
124
201
|
const { contentArea } = computePageMetrics(resolved);
|
|
125
202
|
const chapterTitleByPageIndex = computeChapterTitles(doc.blocks, doc.pages.length, doc.pages);
|
|
203
|
+
const chapterNumberByPageIndex = computeChapterNumbers(doc.blocks, doc.pages.length, doc.pages);
|
|
204
|
+
const headingLevelByNumber = buildHeadingLevelMap(resolved);
|
|
126
205
|
for (const page of doc.pages) {
|
|
127
206
|
if (resolved.header.elements.length > 0) {
|
|
128
|
-
|
|
207
|
+
const placeholders = {
|
|
208
|
+
kind: 'header',
|
|
209
|
+
page,
|
|
210
|
+
allPages: doc.pages,
|
|
211
|
+
metadata: doc.metadata,
|
|
212
|
+
chapterTitleByPageIndex,
|
|
213
|
+
};
|
|
214
|
+
page.header = layoutSlotToVdt(resolved.header, headerContainerBbox(contentArea, page.height), page.index, placeholders, dpi);
|
|
215
|
+
}
|
|
216
|
+
const opener = findOpenerHeading(page, headingLevelByNumber);
|
|
217
|
+
if (opener) {
|
|
218
|
+
const level = headingLevelByNumber.get(opener.level);
|
|
219
|
+
if (level) {
|
|
220
|
+
const slot = level.advancedDesign.enabled && level.advancedDesign.slot.elements.length > 0
|
|
221
|
+
? level.advancedDesign.slot
|
|
222
|
+
: synthesiseDefaultOpenerSlot(level, opener.numberPrefix.length > 0);
|
|
223
|
+
const placeholders = {
|
|
224
|
+
kind: 'heading',
|
|
225
|
+
page,
|
|
226
|
+
allPages: doc.pages,
|
|
227
|
+
metadata: doc.metadata,
|
|
228
|
+
chapterTitleByPageIndex,
|
|
229
|
+
heading: {
|
|
230
|
+
titleText: opener.titleText,
|
|
231
|
+
formattedNumber: opener.numberPrefix,
|
|
232
|
+
chapterNumber: chapterNumberByPageIndex[page.index] ?? '',
|
|
233
|
+
},
|
|
234
|
+
};
|
|
235
|
+
page.openerBand = layoutSlotToVdt(slot, openerContainerBbox(opener.block, contentArea), page.index, placeholders, dpi);
|
|
236
|
+
if (page.openerBand) {
|
|
237
|
+
opener.block.hidden = true;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
// In-column heading advanced-design overlays: any heading whose level
|
|
242
|
+
// has `advancedDesign.enabled` and a non-empty slot gets its default
|
|
243
|
+
// text rendering replaced with a design overlay laid out inside the
|
|
244
|
+
// block's bbox. `span: 'page'` headings are handled via `openerBand`
|
|
245
|
+
// above (and are already `hidden`), so they're skipped here.
|
|
246
|
+
for (const col of page.columns) {
|
|
247
|
+
for (const block of col.blocks) {
|
|
248
|
+
if (block.hidden)
|
|
249
|
+
continue;
|
|
250
|
+
if (block.type !== 'heading' || !block.headingLevel)
|
|
251
|
+
continue;
|
|
252
|
+
const lvl = headingLevelByNumber.get(block.headingLevel);
|
|
253
|
+
if (!lvl)
|
|
254
|
+
continue;
|
|
255
|
+
if (lvl.span === 'page')
|
|
256
|
+
continue;
|
|
257
|
+
if (!lvl.advancedDesign.enabled)
|
|
258
|
+
continue;
|
|
259
|
+
if (lvl.advancedDesign.slot.elements.length === 0)
|
|
260
|
+
continue;
|
|
261
|
+
const full = block.lines
|
|
262
|
+
.map((ln) => (ln.segments ?? []).map((s) => s.text).join(''))
|
|
263
|
+
.join(' ');
|
|
264
|
+
const pref = block.numberPrefix ?? '';
|
|
265
|
+
const title = pref && full.startsWith(`${pref} `) ? full.slice(pref.length + 1) : full;
|
|
266
|
+
const placeholders = {
|
|
267
|
+
kind: 'heading',
|
|
268
|
+
page,
|
|
269
|
+
allPages: doc.pages,
|
|
270
|
+
metadata: doc.metadata,
|
|
271
|
+
chapterTitleByPageIndex,
|
|
272
|
+
heading: {
|
|
273
|
+
titleText: title,
|
|
274
|
+
formattedNumber: pref,
|
|
275
|
+
chapterNumber: chapterNumberByPageIndex[page.index] ?? '',
|
|
276
|
+
},
|
|
277
|
+
};
|
|
278
|
+
const overlay = layoutSlotToVdt(lvl.advancedDesign.slot, { x: block.bbox.x, y: block.bbox.y, width: block.bbox.width, height: block.bbox.height }, page.index, placeholders, dpi);
|
|
279
|
+
if (overlay)
|
|
280
|
+
block.designOverlay = overlay;
|
|
281
|
+
}
|
|
129
282
|
}
|
|
130
283
|
if (resolved.footer.elements.length > 0) {
|
|
131
|
-
|
|
284
|
+
const placeholders = {
|
|
285
|
+
kind: 'footer',
|
|
286
|
+
page,
|
|
287
|
+
allPages: doc.pages,
|
|
288
|
+
metadata: doc.metadata,
|
|
289
|
+
chapterTitleByPageIndex,
|
|
290
|
+
};
|
|
291
|
+
page.footer = layoutSlotToVdt(resolved.footer, footerContainerBbox(contentArea, page.height), page.index, placeholders, dpi);
|
|
132
292
|
}
|
|
133
293
|
}
|
|
134
294
|
}
|