pagyra-js 0.0.19 → 0.0.21
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/README.md +55 -0
- package/dist/assets/fonts/licenses/selawik/SIL Open Font License.txt +43 -0
- package/dist/assets/fonts/ttf/arimo/Arimo-Bold.ttf +0 -0
- package/dist/assets/fonts/ttf/arimo/Arimo-BoldItalic.ttf +0 -0
- package/dist/assets/fonts/ttf/arimo/Arimo-Italic.ttf +0 -0
- package/dist/assets/fonts/ttf/arimo/Arimo-Regular.ttf +0 -0
- package/dist/assets/fonts/ttf/cinzeldecorative/CinzelDecorative-Black.ttf +0 -0
- package/dist/assets/fonts/ttf/cinzeldecorative/CinzelDecorative-Bold.ttf +0 -0
- package/dist/assets/fonts/ttf/cinzeldecorative/CinzelDecorative-Regular.ttf +0 -0
- package/dist/assets/fonts/ttf/dejavu/DejaVuSans.ttf +0 -0
- package/dist/assets/fonts/ttf/firecode/FiraCode-Bold.ttf +0 -0
- package/dist/assets/fonts/ttf/firecode/FiraCode-Light.ttf +0 -0
- package/dist/assets/fonts/ttf/firecode/FiraCode-Medium.ttf +0 -0
- package/dist/assets/fonts/ttf/firecode/FiraCode-Regular.ttf +0 -0
- package/dist/assets/fonts/ttf/firecode/FiraCode-SemiBold.ttf +0 -0
- package/dist/assets/fonts/ttf/notoemoji/NotoEmoji-Bold.ttf +0 -0
- package/dist/assets/fonts/ttf/notoemoji/NotoEmoji-Light.ttf +0 -0
- package/dist/assets/fonts/ttf/notoemoji/NotoEmoji-Medium.ttf +0 -0
- package/dist/assets/fonts/ttf/notoemoji/NotoEmoji-Regular.ttf +0 -0
- package/dist/assets/fonts/ttf/notoemoji/NotoEmoji-SemiBold.ttf +0 -0
- package/dist/assets/fonts/ttf/notosans/NotoSans-Regular.ttf +0 -0
- package/dist/assets/fonts/ttf/roboto/Roboto-Bold.ttf +0 -0
- package/dist/assets/fonts/ttf/roboto/Roboto-BoldItalic.ttf +0 -0
- package/dist/assets/fonts/ttf/roboto/Roboto-Italic.ttf +0 -0
- package/dist/assets/fonts/ttf/roboto/Roboto-Regular.ttf +0 -0
- package/dist/assets/fonts/ttf/selawik/selawk.ttf +0 -0
- package/dist/assets/fonts/ttf/selawik/selawkb.ttf +0 -0
- package/dist/assets/fonts/ttf/selawik/selawkl.ttf +0 -0
- package/dist/assets/fonts/ttf/selawik/selawksb.ttf +0 -0
- package/dist/assets/fonts/ttf/selawik/selawksl.ttf +0 -0
- package/dist/assets/fonts/ttf/stixtwomath/STIXTwoMath-Regular.ttf +0 -0
- package/dist/assets/fonts/ttf/tinos/Tinos-Bold.ttf +0 -0
- package/dist/assets/fonts/ttf/tinos/Tinos-BoldItalic.ttf +0 -0
- package/dist/assets/fonts/ttf/tinos/Tinos-Italic.ttf +0 -0
- package/dist/assets/fonts/ttf/tinos/Tinos-Regular.ttf +0 -0
- package/dist/assets/fonts/woff/lato/lato-latin-400-italic.woff +0 -0
- package/dist/assets/fonts/woff/lato/lato-latin-400-normal.woff +0 -0
- package/dist/assets/fonts/woff/lato/lato-latin-700-italic.woff +0 -0
- package/dist/assets/fonts/woff/lato/lato-latin-700-normal.woff +0 -0
- package/dist/assets/fonts/woff2/caveat/Caveat-Bold.woff2 +0 -0
- package/dist/assets/fonts/woff2/caveat/Caveat-Regular.woff2 +0 -0
- package/dist/assets/fonts/woff2/lato/lato-latin-400-italic.woff2 +0 -0
- package/dist/assets/fonts/woff2/lato/lato-latin-400-normal.woff2 +0 -0
- package/dist/assets/fonts/woff2/lato/lato-latin-700-italic.woff2 +0 -0
- package/dist/assets/fonts/woff2/lato/lato-latin-700-normal.woff2 +0 -0
- package/dist/browser/pagyra.min.js +34 -34
- package/dist/browser/pagyra.min.js.map +4 -4
- package/dist/playground/server.js +2 -0
- package/dist/src/css/compute-style/base-options.d.ts +7 -0
- package/dist/src/css/compute-style/base-options.js +24 -0
- package/dist/src/css/compute-style/declarations.d.ts +10 -0
- package/dist/src/css/compute-style/declarations.js +77 -0
- package/dist/src/css/compute-style/decoration.d.ts +8 -0
- package/dist/src/css/compute-style/decoration.js +55 -0
- package/dist/src/css/compute-style/defaults.d.ts +3 -0
- package/dist/src/css/compute-style/defaults.js +34 -0
- package/dist/src/css/compute-style/display.d.ts +3 -0
- package/dist/src/css/compute-style/display.js +85 -0
- package/dist/src/css/compute-style/float.d.ts +2 -0
- package/dist/src/css/compute-style/float.js +13 -0
- package/dist/src/css/compute-style/font.d.ts +12 -0
- package/dist/src/css/compute-style/font.js +57 -0
- package/dist/src/css/compute-style/overrides.d.ts +3 -0
- package/dist/src/css/compute-style/overrides.js +241 -0
- package/dist/src/css/compute-style.d.ts +2 -0
- package/dist/src/css/compute-style.js +34 -487
- package/dist/src/css/enums.d.ts +4 -0
- package/dist/src/css/enums.js +5 -0
- package/dist/src/css/layout-property-resolver.js +30 -18
- package/dist/src/css/length.d.ts +26 -2
- package/dist/src/css/length.js +48 -0
- package/dist/src/css/parsers/background-parser.js +1 -1
- package/dist/src/css/parsers/calc-parser.d.ts +2 -0
- package/dist/src/css/parsers/calc-parser.js +310 -0
- package/dist/src/css/parsers/content-parser.d.ts +2 -1
- package/dist/src/css/parsers/content-parser.js +7 -2
- package/dist/src/css/parsers/dimension-parser.js +37 -18
- package/dist/src/css/parsers/display-flex-parser.d.ts +4 -0
- package/dist/src/css/parsers/display-flex-parser.js +97 -0
- package/dist/src/css/parsers/filter-parser.d.ts +14 -0
- package/dist/src/css/parsers/filter-parser.js +255 -0
- package/dist/src/css/parsers/grid-parser-extended.d.ts +1 -0
- package/dist/src/css/parsers/grid-parser-extended.js +40 -1
- package/dist/src/css/parsers/grid-parser.d.ts +5 -2
- package/dist/src/css/parsers/grid-parser.js +71 -7
- package/dist/src/css/parsers/length-parser.d.ts +8 -3
- package/dist/src/css/parsers/length-parser.js +45 -2
- package/dist/src/css/parsers/margin-block-parser.js +3 -3
- package/dist/src/css/parsers/margin-parser.js +3 -3
- package/dist/src/css/parsers/padding-block-parser.js +3 -3
- package/dist/src/css/parsers/padding-inline-parser.js +3 -3
- package/dist/src/css/parsers/padding-parser.js +6 -6
- package/dist/src/css/parsers/position-parser.js +2 -22
- package/dist/src/css/parsers/register-parsers.js +29 -2
- package/dist/src/css/parsers/word-break-parser.d.ts +2 -0
- package/dist/src/css/parsers/word-break-parser.js +23 -0
- package/dist/src/css/properties/grid.d.ts +16 -2
- package/dist/src/css/properties/layout.d.ts +3 -1
- package/dist/src/css/properties/layout.js +1 -1
- package/dist/src/css/properties/misc.d.ts +5 -0
- package/dist/src/css/properties/typography.d.ts +3 -0
- package/dist/src/css/properties/visual.d.ts +36 -0
- package/dist/src/css/shorthands/box-shorthand.d.ts +2 -2
- package/dist/src/css/style-inheritance.d.ts +2 -1
- package/dist/src/css/style-inheritance.js +1 -0
- package/dist/src/css/style.d.ts +30 -10
- package/dist/src/css/style.js +8 -1
- package/dist/src/css/ua-defaults/base-defaults.d.ts +1 -0
- package/dist/src/css/ua-defaults/base-defaults.js +10 -1
- package/dist/src/css/ua-defaults/element-defaults.js +0 -2
- package/dist/src/html/css/parse-css.d.ts +2 -0
- package/dist/src/html/css/parse-css.js +32 -3
- package/dist/src/html/dom-converter/background-images.d.ts +3 -0
- package/dist/src/html/dom-converter/background-images.js +88 -0
- package/dist/src/html/dom-converter/convert-dom-node.d.ts +5 -0
- package/dist/src/html/dom-converter/convert-dom-node.js +81 -0
- package/dist/src/html/dom-converter/handlers/br-handler.d.ts +2 -0
- package/dist/src/html/dom-converter/handlers/br-handler.js +20 -0
- package/dist/src/html/dom-converter/handlers/form-control-handler.d.ts +2 -0
- package/dist/src/html/dom-converter/handlers/form-control-handler.js +28 -0
- package/dist/src/html/dom-converter/handlers/img-handler.d.ts +2 -0
- package/dist/src/html/dom-converter/handlers/img-handler.js +4 -0
- package/dist/src/html/dom-converter/handlers/index.d.ts +4 -0
- package/dist/src/html/dom-converter/handlers/index.js +19 -0
- package/dist/src/html/dom-converter/handlers/svg-handler.d.ts +2 -0
- package/dist/src/html/dom-converter/handlers/svg-handler.js +32 -0
- package/dist/src/html/dom-converter/handlers/types.d.ts +12 -0
- package/dist/src/html/dom-converter/handlers/types.js +2 -0
- package/dist/src/html/dom-converter/helpers.d.ts +7 -0
- package/dist/src/html/dom-converter/helpers.js +35 -0
- package/dist/src/html/dom-converter/index.d.ts +1 -0
- package/dist/src/html/dom-converter/index.js +1 -0
- package/dist/src/html/dom-converter/pseudo-elements.d.ts +6 -0
- package/dist/src/html/dom-converter/pseudo-elements.js +48 -0
- package/dist/src/html/dom-converter/text.d.ts +15 -0
- package/dist/src/html/dom-converter/text.js +170 -0
- package/dist/src/html/dom-converter.d.ts +1 -5
- package/dist/src/html/dom-converter.js +1 -412
- package/dist/src/html/image-converter.d.ts +5 -0
- package/dist/src/html/image-converter.js +8 -3
- package/dist/src/html-to-pdf/document-css.d.ts +14 -0
- package/dist/src/html-to-pdf/document-css.js +45 -0
- package/dist/src/html-to-pdf/fonts.d.ts +16 -0
- package/dist/src/html-to-pdf/fonts.js +74 -0
- package/dist/src/html-to-pdf/header-footer.d.ts +14 -0
- package/dist/src/html-to-pdf/header-footer.js +101 -0
- package/dist/src/html-to-pdf/html-parser.d.ts +6 -0
- package/dist/src/html-to-pdf/html-parser.js +81 -0
- package/dist/src/html-to-pdf/index.d.ts +3 -0
- package/dist/src/html-to-pdf/index.js +2 -0
- package/dist/src/html-to-pdf/layout-build.d.ts +37 -0
- package/dist/src/html-to-pdf/layout-build.js +73 -0
- package/dist/src/html-to-pdf/prepare-html-render.d.ts +2 -0
- package/dist/src/html-to-pdf/prepare-html-render.js +121 -0
- package/dist/src/html-to-pdf/render-finalize.d.ts +15 -0
- package/dist/src/html-to-pdf/render-finalize.js +27 -0
- package/dist/src/html-to-pdf/render-html-to-pdf.d.ts +3 -0
- package/dist/src/html-to-pdf/render-html-to-pdf.js +25 -0
- package/dist/src/html-to-pdf/resource-loader.d.ts +6 -0
- package/dist/src/html-to-pdf/resource-loader.js +120 -0
- package/dist/src/html-to-pdf/types.d.ts +38 -0
- package/dist/src/html-to-pdf/types.js +2 -0
- package/dist/src/html-to-pdf.d.ts +1 -37
- package/dist/src/html-to-pdf.js +1 -537
- package/dist/src/image/js-png-backend.d.ts +7 -0
- package/dist/src/image/js-png-backend.js +9 -0
- package/dist/src/image/png-backend.d.ts +5 -0
- package/dist/src/image/png-backend.js +1 -0
- package/dist/src/image/png-wasm-loader.d.ts +5 -0
- package/dist/src/image/png-wasm-loader.js +59 -0
- package/dist/src/image/wasm/png_decoder_wasm.d.ts +8 -0
- package/dist/src/image/wasm/png_decoder_wasm.js +24 -0
- package/dist/src/image/wasm/png_decoder_wasm_bg.js +16 -0
- package/dist/src/image/wasm-png-backend.d.ts +6 -0
- package/dist/src/image/wasm-png-backend.js +17 -0
- package/dist/src/layout/counter.d.ts +1 -2
- package/dist/src/layout/counter.js +18 -18
- package/dist/src/layout/inline/inline-utils.d.ts +1 -1
- package/dist/src/layout/inline/inline-utils.js +8 -7
- package/dist/src/layout/inline/layout.js +16 -3
- package/dist/src/layout/inline/run-placer.d.ts +1 -0
- package/dist/src/layout/inline/run-placer.js +2 -10
- package/dist/src/layout/pipeline/out-of-flow-manager.js +25 -1
- package/dist/src/layout/strategies/block.js +35 -24
- package/dist/src/layout/strategies/flex.js +305 -61
- package/dist/src/layout/strategies/form.d.ts +2 -0
- package/dist/src/layout/strategies/form.js +38 -13
- package/dist/src/layout/strategies/grid.js +166 -29
- package/dist/src/layout/strategies/image.js +53 -27
- package/dist/src/layout/strategies/inline.js +26 -21
- package/dist/src/layout/strategies/table.js +26 -18
- package/dist/src/layout/utils/content-measurer.d.ts +1 -1
- package/dist/src/layout/utils/content-measurer.js +8 -7
- package/dist/src/layout/utils/floats.d.ts +1 -0
- package/dist/src/layout/utils/floats.js +14 -12
- package/dist/src/layout/utils/margin.d.ts +4 -4
- package/dist/src/layout/utils/margin.js +20 -16
- package/dist/src/layout/utils/node-math.d.ts +12 -6
- package/dist/src/layout/utils/node-math.js +71 -41
- package/dist/src/layout/utils/sizing.js +2 -1
- package/dist/src/pdf/font-subset/font-registry.d.ts +6 -0
- package/dist/src/pdf/font-subset/font-registry.js +30 -2
- package/dist/src/pdf/header-footer-painter.d.ts +2 -0
- package/dist/src/pdf/header-footer-painter.js +52 -4
- package/dist/src/pdf/header-footer-renderer.js +12 -1
- package/dist/src/pdf/layout-tree-builder.js +5 -1
- package/dist/src/pdf/page-painter.js +13 -0
- package/dist/src/pdf/pagination.js +2 -2
- package/dist/src/pdf/renderer/box-painter.js +28 -3
- package/dist/src/pdf/renderer/page-paint.js +12 -3
- package/dist/src/pdf/renderers/radius-utils.js +31 -38
- package/dist/src/pdf/renderers/shape-renderer.js +1 -1
- package/dist/src/pdf/renderers/shape-utils.js +1 -1
- package/dist/src/pdf/renderers/text-renderer.d.ts +9 -1
- package/dist/src/pdf/renderers/text-renderer.js +36 -2
- package/dist/src/pdf/stacking/build-stacking-contexts.js +1 -2
- package/dist/src/pdf/stacking/resolve-paint-order.d.ts +5 -6
- package/dist/src/pdf/stacking/resolve-paint-order.js +29 -9
- package/dist/src/pdf/stacking/types.d.ts +14 -0
- package/dist/src/pdf/svg/shape-renderer.js +47 -20
- package/dist/src/pdf/types.d.ts +7 -1
- package/dist/src/pdf/utils/border-radius-utils.js +31 -38
- package/dist/src/pdf/utils/color-utils.js +17 -2
- package/dist/src/pdf/utils/filter-utils.d.ts +29 -0
- package/dist/src/pdf/utils/filter-utils.js +85 -0
- package/dist/src/pdf/utils/node-text-run-factory.js +1 -1
- package/dist/src/pdf/utils/text-layout-adjuster.d.ts +0 -8
- package/dist/src/pdf/utils/text-layout-adjuster.js +12 -9
- package/dist/src/shim/css-browser.d.ts +14 -9
- package/dist/src/shim/css-browser.js +50 -39
- package/dist/src/units/units.d.ts +1 -1
- package/dist/tests/css/box-sizing.spec.d.ts +1 -0
- package/dist/tests/css/box-sizing.spec.js +46 -0
- package/dist/tests/css/calc-parser.spec.d.ts +1 -0
- package/dist/tests/css/calc-parser.spec.js +68 -0
- package/dist/tests/css/container-query-units.spec.d.ts +1 -0
- package/dist/tests/css/container-query-units.spec.js +64 -0
- package/dist/tests/css/content-parser.spec.js +13 -0
- package/dist/tests/css/filter-parser.spec.d.ts +1 -0
- package/dist/tests/css/filter-parser.spec.js +116 -0
- package/dist/tests/css/flex-shorthand.spec.d.ts +1 -0
- package/dist/tests/css/flex-shorthand.spec.js +45 -0
- package/dist/tests/css/grid-clamp.spec.d.ts +1 -0
- package/dist/tests/css/grid-clamp.spec.js +82 -0
- package/dist/tests/css/parse-css-pseudo.spec.d.ts +1 -0
- package/dist/tests/css/parse-css-pseudo.spec.js +26 -0
- package/dist/tests/helpers/render-utils.d.ts +18 -2
- package/dist/tests/helpers/render-utils.js +25 -12
- package/dist/tests/html/dom-converter-pseudo-elements.spec.d.ts +1 -0
- package/dist/tests/html/dom-converter-pseudo-elements.spec.js +33 -0
- package/dist/tests/html/dom-converter-text.spec.d.ts +1 -0
- package/dist/tests/html/dom-converter-text.spec.js +67 -0
- package/dist/tests/image/png-backend.spec.d.ts +1 -0
- package/dist/tests/image/png-backend.spec.js +34 -0
- package/dist/tests/layout/box-sizing.spec.d.ts +1 -0
- package/dist/tests/layout/box-sizing.spec.js +75 -0
- package/dist/tests/layout/calc-padding.spec.d.ts +1 -0
- package/dist/tests/layout/calc-padding.spec.js +19 -0
- package/dist/tests/layout/container-query-units.spec.d.ts +1 -0
- package/dist/tests/layout/container-query-units.spec.js +24 -0
- package/dist/tests/layout/flex-auto-height.spec.d.ts +1 -0
- package/dist/tests/layout/flex-auto-height.spec.js +35 -0
- package/dist/tests/layout/flex-wrap-cards.spec.d.ts +1 -0
- package/dist/tests/layout/flex-wrap-cards.spec.js +16 -0
- package/dist/tests/layout/flex-wrap-grow-align-content.spec.d.ts +1 -0
- package/dist/tests/layout/flex-wrap-grow-align-content.spec.js +20 -0
- package/dist/tests/layout/grid-clamp-gap.spec.d.ts +1 -0
- package/dist/tests/layout/grid-clamp-gap.spec.js +22 -0
- package/dist/tests/layout/inline-fragments.spec.js +38 -0
- package/dist/tests/layout/paged-body-margin.spec.d.ts +1 -0
- package/dist/tests/layout/paged-body-margin.spec.js +92 -0
- package/dist/tests/layout/pseudo-counters-generated-content.spec.d.ts +1 -0
- package/dist/tests/layout/pseudo-counters-generated-content.spec.js +51 -0
- package/dist/tests/layout/responsive-clamp-grid-parity.spec.d.ts +1 -0
- package/dist/tests/layout/responsive-clamp-grid-parity.spec.js +75 -0
- package/dist/tests/layout/run-placer-baseline.spec.js +13 -11
- package/dist/tests/pdf/backdrop-filter-noop.spec.d.ts +1 -0
- package/dist/tests/pdf/backdrop-filter-noop.spec.js +140 -0
- package/dist/tests/pdf/filter-drop-shadow.spec.d.ts +1 -0
- package/dist/tests/pdf/filter-drop-shadow.spec.js +74 -0
- package/dist/tests/pdf/filter-opacity.spec.d.ts +1 -0
- package/dist/tests/pdf/filter-opacity.spec.js +30 -0
- package/dist/tests/pdf/font-subset-registry-key.spec.d.ts +1 -0
- package/dist/tests/pdf/font-subset-registry-key.spec.js +66 -0
- package/dist/tests/pdf/header-footer-clip-overflow.spec.d.ts +1 -0
- package/dist/tests/pdf/header-footer-clip-overflow.spec.js +45 -0
- package/dist/tests/pdf/selawik-opt-in.spec.d.ts +1 -0
- package/dist/tests/pdf/selawik-opt-in.spec.js +106 -0
- package/dist/tests/pdf/system-ui-fallback-subset-regression.spec.d.ts +1 -0
- package/dist/tests/pdf/system-ui-fallback-subset-regression.spec.js +39 -0
- package/dist/tests/pdf/text-renderer-fallback.spec.js +55 -0
- package/dist/tests/pdf/text-transform-matrix.spec.js +8 -7
- package/package.json +2 -2
|
@@ -28,7 +28,8 @@ export class ContentMeasurer {
|
|
|
28
28
|
* @param contentStartX - The X coordinate where content area begins
|
|
29
29
|
* @returns Object containing the measured width and any left offset
|
|
30
30
|
*/
|
|
31
|
-
measureInFlowWidth(node, referenceWidth, contentStartX) {
|
|
31
|
+
measureInFlowWidth(node, referenceWidth, contentStartX, containerHeight = referenceWidth) {
|
|
32
|
+
const containerRefs = { containerWidth: referenceWidth, containerHeight };
|
|
32
33
|
let minStart = Number.POSITIVE_INFINITY;
|
|
33
34
|
let maxEnd = Number.NEGATIVE_INFINITY;
|
|
34
35
|
let hasContent = false;
|
|
@@ -41,14 +42,14 @@ export class ContentMeasurer {
|
|
|
41
42
|
}
|
|
42
43
|
const marginLeft = child.box.usedMarginLeft !== undefined
|
|
43
44
|
? child.box.usedMarginLeft
|
|
44
|
-
: resolveLength(child.style.marginLeft, referenceWidth, { auto: "zero" });
|
|
45
|
+
: resolveLength(child.style.marginLeft, referenceWidth, { auto: "zero", ...containerRefs });
|
|
45
46
|
const marginRight = child.box.usedMarginRight !== undefined
|
|
46
47
|
? child.box.usedMarginRight
|
|
47
|
-
: resolveLength(child.style.marginRight, referenceWidth, { auto: "zero" });
|
|
48
|
-
const borderLeft = resolveLength(child.style.borderLeft, referenceWidth, { auto: "zero" });
|
|
49
|
-
const borderRight = resolveLength(child.style.borderRight, referenceWidth, { auto: "zero" });
|
|
50
|
-
const paddingLeft = resolveLength(child.style.paddingLeft, referenceWidth, { auto: "zero" });
|
|
51
|
-
const paddingRight = resolveLength(child.style.paddingRight, referenceWidth, { auto: "zero" });
|
|
48
|
+
: resolveLength(child.style.marginRight, referenceWidth, { auto: "zero", ...containerRefs });
|
|
49
|
+
const borderLeft = resolveLength(child.style.borderLeft, referenceWidth, { auto: "zero", ...containerRefs });
|
|
50
|
+
const borderRight = resolveLength(child.style.borderRight, referenceWidth, { auto: "zero", ...containerRefs });
|
|
51
|
+
const paddingLeft = resolveLength(child.style.paddingLeft, referenceWidth, { auto: "zero", ...containerRefs });
|
|
52
|
+
const paddingRight = resolveLength(child.style.paddingRight, referenceWidth, { auto: "zero", ...containerRefs });
|
|
52
53
|
const borderBoxWidth = child.box.borderBoxWidth || Math.max(0, child.box.contentWidth + paddingLeft + paddingRight + borderLeft + borderRight);
|
|
53
54
|
const marginBoxWidth = borderBoxWidth + marginLeft + marginRight;
|
|
54
55
|
const marginStart = child.box.x - paddingLeft - borderLeft - marginLeft;
|
|
@@ -7,6 +7,7 @@ interface FloatPlacementOptions {
|
|
|
7
7
|
context: LayoutContext;
|
|
8
8
|
contentX: number;
|
|
9
9
|
contentWidth: number;
|
|
10
|
+
contentHeight?: number;
|
|
10
11
|
startY: number;
|
|
11
12
|
}
|
|
12
13
|
export declare function clearForBlock(node: LayoutNode, floatContext: FloatContext, yCursor: number): number;
|
|
@@ -15,19 +15,21 @@ export function clearForBlock(node, floatContext, yCursor) {
|
|
|
15
15
|
}
|
|
16
16
|
export function placeFloat(options) {
|
|
17
17
|
const { node, floatContext, context, contentX, contentWidth } = options;
|
|
18
|
+
const contentHeight = options.contentHeight ?? contentWidth;
|
|
19
|
+
const containerRefs = { containerWidth: contentWidth, containerHeight: contentHeight };
|
|
18
20
|
context.layoutChild(node);
|
|
19
|
-
const marginLeft = resolveLength(node.style.marginLeft, contentWidth, { auto: "zero" });
|
|
20
|
-
const marginRight = resolveLength(node.style.marginRight, contentWidth, { auto: "zero" });
|
|
21
|
-
const marginTop = resolveLength(node.style.marginTop,
|
|
22
|
-
const marginBottom = resolveLength(node.style.marginBottom,
|
|
23
|
-
const borderLeft = resolveLength(node.style.borderLeft, contentWidth, { auto: "zero" });
|
|
24
|
-
const borderRight = resolveLength(node.style.borderRight, contentWidth, { auto: "zero" });
|
|
25
|
-
const borderTop = resolveLength(node.style.borderTop,
|
|
26
|
-
const borderBottom = resolveLength(node.style.borderBottom,
|
|
27
|
-
const paddingLeft = resolveLength(node.style.paddingLeft, contentWidth, { auto: "zero" });
|
|
28
|
-
const paddingRight = resolveLength(node.style.paddingRight, contentWidth, { auto: "zero" });
|
|
29
|
-
const paddingTop = resolveLength(node.style.paddingTop,
|
|
30
|
-
const paddingBottom = resolveLength(node.style.paddingBottom,
|
|
21
|
+
const marginLeft = resolveLength(node.style.marginLeft, contentWidth, { auto: "zero", ...containerRefs });
|
|
22
|
+
const marginRight = resolveLength(node.style.marginRight, contentWidth, { auto: "zero", ...containerRefs });
|
|
23
|
+
const marginTop = resolveLength(node.style.marginTop, contentHeight, { auto: "zero", ...containerRefs });
|
|
24
|
+
const marginBottom = resolveLength(node.style.marginBottom, contentHeight, { auto: "zero", ...containerRefs });
|
|
25
|
+
const borderLeft = resolveLength(node.style.borderLeft, contentWidth, { auto: "zero", ...containerRefs });
|
|
26
|
+
const borderRight = resolveLength(node.style.borderRight, contentWidth, { auto: "zero", ...containerRefs });
|
|
27
|
+
const borderTop = resolveLength(node.style.borderTop, contentHeight, { auto: "zero", ...containerRefs });
|
|
28
|
+
const borderBottom = resolveLength(node.style.borderBottom, contentHeight, { auto: "zero", ...containerRefs });
|
|
29
|
+
const paddingLeft = resolveLength(node.style.paddingLeft, contentWidth, { auto: "zero", ...containerRefs });
|
|
30
|
+
const paddingRight = resolveLength(node.style.paddingRight, contentWidth, { auto: "zero", ...containerRefs });
|
|
31
|
+
const paddingTop = resolveLength(node.style.paddingTop, contentHeight, { auto: "zero", ...containerRefs });
|
|
32
|
+
const paddingBottom = resolveLength(node.style.paddingBottom, contentHeight, { auto: "zero", ...containerRefs });
|
|
31
33
|
const borderBoxWidth = node.box.contentWidth + paddingLeft + paddingRight + borderLeft + borderRight;
|
|
32
34
|
const borderBoxHeight = node.box.contentHeight + paddingTop + paddingBottom + borderTop + borderBottom;
|
|
33
35
|
node.box.borderBoxWidth = borderBoxWidth;
|
|
@@ -3,7 +3,7 @@ export declare function collapseMarginSet(margins: readonly number[]): number;
|
|
|
3
3
|
export declare function collapsedGapBetween(prevBottomMargin: number, nextTopMargin: number, parentEstablishesBfc: boolean): number;
|
|
4
4
|
export declare function findFirstMarginCollapsibleChild(node: LayoutNode): LayoutNode | undefined;
|
|
5
5
|
export declare function findLastMarginCollapsibleChild(node: LayoutNode): LayoutNode | undefined;
|
|
6
|
-
export declare function canCollapseMarginStart(node: LayoutNode, containingBlockWidth: number): boolean;
|
|
7
|
-
export declare function canCollapseMarginEnd(node: LayoutNode, containingBlockWidth: number): boolean;
|
|
8
|
-
export declare function effectiveMarginTop(node: LayoutNode, containingBlockWidth: number): number;
|
|
9
|
-
export declare function effectiveMarginBottom(node: LayoutNode, containingBlockWidth: number): number;
|
|
6
|
+
export declare function canCollapseMarginStart(node: LayoutNode, containingBlockWidth: number, containingBlockHeight?: number): boolean;
|
|
7
|
+
export declare function canCollapseMarginEnd(node: LayoutNode, containingBlockWidth: number, containingBlockHeight?: number): boolean;
|
|
8
|
+
export declare function effectiveMarginTop(node: LayoutNode, containingBlockWidth: number, containingBlockHeight?: number): number;
|
|
9
|
+
export declare function effectiveMarginBottom(node: LayoutNode, containingBlockWidth: number, containingBlockHeight?: number): number;
|
|
@@ -68,57 +68,61 @@ export function findLastMarginCollapsibleChild(node) {
|
|
|
68
68
|
}
|
|
69
69
|
return undefined;
|
|
70
70
|
}
|
|
71
|
-
export function canCollapseMarginStart(node, containingBlockWidth) {
|
|
71
|
+
export function canCollapseMarginStart(node, containingBlockWidth, containingBlockHeight = containingBlockWidth) {
|
|
72
72
|
if (!isBlockLevel(node) || establishesBFC(node)) {
|
|
73
73
|
return false;
|
|
74
74
|
}
|
|
75
|
-
const
|
|
76
|
-
const
|
|
75
|
+
const containerRefs = { containerWidth: containingBlockWidth, containerHeight: containingBlockHeight };
|
|
76
|
+
const paddingTop = resolveLength(node.style.paddingTop, containingBlockHeight, { auto: "zero", ...containerRefs });
|
|
77
|
+
const borderTop = resolveLength(node.style.borderTop, containingBlockHeight, { auto: "zero", ...containerRefs });
|
|
77
78
|
if (!isApproximatelyZero(paddingTop) || !isApproximatelyZero(borderTop)) {
|
|
78
79
|
return false;
|
|
79
80
|
}
|
|
80
81
|
return findFirstMarginCollapsibleChild(node) !== undefined;
|
|
81
82
|
}
|
|
82
|
-
export function canCollapseMarginEnd(node, containingBlockWidth) {
|
|
83
|
+
export function canCollapseMarginEnd(node, containingBlockWidth, containingBlockHeight = containingBlockWidth) {
|
|
83
84
|
if (!isBlockLevel(node) || establishesBFC(node)) {
|
|
84
85
|
return false;
|
|
85
86
|
}
|
|
86
|
-
const
|
|
87
|
-
const
|
|
87
|
+
const containerRefs = { containerWidth: containingBlockWidth, containerHeight: containingBlockHeight };
|
|
88
|
+
const paddingBottom = resolveLength(node.style.paddingBottom, containingBlockHeight, { auto: "zero", ...containerRefs });
|
|
89
|
+
const borderBottom = resolveLength(node.style.borderBottom, containingBlockHeight, { auto: "zero", ...containerRefs });
|
|
88
90
|
if (!isApproximatelyZero(paddingBottom) || !isApproximatelyZero(borderBottom)) {
|
|
89
91
|
return false;
|
|
90
92
|
}
|
|
91
93
|
return findLastMarginCollapsibleChild(node) !== undefined;
|
|
92
94
|
}
|
|
93
|
-
export function effectiveMarginTop(node, containingBlockWidth) {
|
|
94
|
-
const
|
|
95
|
+
export function effectiveMarginTop(node, containingBlockWidth, containingBlockHeight = containingBlockWidth) {
|
|
96
|
+
const containerRefs = { containerWidth: containingBlockWidth, containerHeight: containingBlockHeight };
|
|
97
|
+
const ownMargin = resolveLength(node.style.marginTop, containingBlockHeight, { auto: "zero", ...containerRefs });
|
|
95
98
|
if (!isBlockLevel(node)) {
|
|
96
99
|
return ownMargin;
|
|
97
100
|
}
|
|
98
|
-
if (!canCollapseMarginStart(node, containingBlockWidth)) {
|
|
101
|
+
if (!canCollapseMarginStart(node, containingBlockWidth, containingBlockHeight)) {
|
|
99
102
|
return ownMargin;
|
|
100
103
|
}
|
|
101
104
|
const firstChild = findFirstMarginCollapsibleChild(node);
|
|
102
105
|
if (!firstChild) {
|
|
103
106
|
return ownMargin;
|
|
104
107
|
}
|
|
105
|
-
const childContainingWidth = resolveWidthBlock(node, containingBlockWidth);
|
|
106
|
-
const childMargin = effectiveMarginTop(firstChild, childContainingWidth);
|
|
108
|
+
const childContainingWidth = resolveWidthBlock(node, containingBlockWidth, containingBlockHeight);
|
|
109
|
+
const childMargin = effectiveMarginTop(firstChild, childContainingWidth, containingBlockHeight);
|
|
107
110
|
return collapseMarginSet([ownMargin, childMargin]);
|
|
108
111
|
}
|
|
109
|
-
export function effectiveMarginBottom(node, containingBlockWidth) {
|
|
110
|
-
const
|
|
112
|
+
export function effectiveMarginBottom(node, containingBlockWidth, containingBlockHeight = containingBlockWidth) {
|
|
113
|
+
const containerRefs = { containerWidth: containingBlockWidth, containerHeight: containingBlockHeight };
|
|
114
|
+
const ownMargin = resolveLength(node.style.marginBottom, containingBlockHeight, { auto: "zero", ...containerRefs });
|
|
111
115
|
if (!isBlockLevel(node)) {
|
|
112
116
|
return ownMargin;
|
|
113
117
|
}
|
|
114
|
-
if (!canCollapseMarginEnd(node, containingBlockWidth)) {
|
|
118
|
+
if (!canCollapseMarginEnd(node, containingBlockWidth, containingBlockHeight)) {
|
|
115
119
|
return ownMargin;
|
|
116
120
|
}
|
|
117
121
|
const lastChild = findLastMarginCollapsibleChild(node);
|
|
118
122
|
if (!lastChild) {
|
|
119
123
|
return ownMargin;
|
|
120
124
|
}
|
|
121
|
-
const childContainingWidth = resolveWidthBlock(node, containingBlockWidth);
|
|
122
|
-
const childMargin = effectiveMarginBottom(lastChild, childContainingWidth);
|
|
125
|
+
const childContainingWidth = resolveWidthBlock(node, containingBlockWidth, containingBlockHeight);
|
|
126
|
+
const childMargin = effectiveMarginBottom(lastChild, childContainingWidth, containingBlockHeight);
|
|
123
127
|
return collapseMarginSet([ownMargin, childMargin]);
|
|
124
128
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { LayoutNode } from "../../dom/node.js";
|
|
2
|
+
import { BoxSizing } from "../../css/enums.js";
|
|
2
3
|
import { type LengthLike } from "../../css/length.js";
|
|
3
4
|
import type { ContainingBlock, Viewport } from "../../geometry/box.js";
|
|
4
5
|
export interface BoxMetrics {
|
|
@@ -14,16 +15,21 @@ export interface BoxMetrics {
|
|
|
14
15
|
contentBoxY: number;
|
|
15
16
|
}
|
|
16
17
|
export declare function resolveBoxMetrics(node: LayoutNode, widthRef: number, heightRef: number): BoxMetrics;
|
|
17
|
-
export declare function
|
|
18
|
-
export declare function
|
|
19
|
-
export declare function
|
|
20
|
-
export declare function
|
|
18
|
+
export declare function adjustForBoxSizing(specifiedSize: number, boxSizing: BoxSizing, nonContentExtras: number): number;
|
|
19
|
+
export declare function horizontalNonContent(node: LayoutNode, reference: number, containerHeight?: number): number;
|
|
20
|
+
export declare function verticalNonContent(node: LayoutNode, reference: number, containerWidth?: number): number;
|
|
21
|
+
export declare function horizontalMargin(node: LayoutNode, reference: number, containerHeight?: number): number;
|
|
22
|
+
export declare function verticalMargin(node: LayoutNode, reference: number, containerWidth?: number): number;
|
|
21
23
|
export declare function inFlow(node: LayoutNode): boolean;
|
|
22
24
|
export declare function establishesBFC(node: LayoutNode): boolean;
|
|
23
25
|
export declare function nearestPositionedAncestor(node: LayoutNode): LayoutNode | null;
|
|
24
26
|
export declare function containingBlock(node: LayoutNode, viewport: Viewport): ContainingBlock;
|
|
25
|
-
export declare function resolveWidthBlock(node: LayoutNode, containingBlockWidth: number): number;
|
|
26
|
-
export declare function resolveBlockAutoMargins(containingBlockWidth: number, borderBoxWidth: number, marginLeft: LengthLike, marginRight: LengthLike): {
|
|
27
|
+
export declare function resolveWidthBlock(node: LayoutNode, containingBlockWidth: number, containingBlockHeight?: number): number;
|
|
28
|
+
export declare function resolveBlockAutoMargins(containingBlockWidth: number, borderBoxWidth: number, marginLeft: LengthLike, marginRight: LengthLike, containingBlockHeight?: number): {
|
|
27
29
|
marginLeft: number;
|
|
28
30
|
marginRight: number;
|
|
29
31
|
};
|
|
32
|
+
export declare function applyMinHeight(contentHeight: number, node: LayoutNode, heightRef: number, verticalExtras: number, containerRefs: {
|
|
33
|
+
containerWidth: number;
|
|
34
|
+
containerHeight: number;
|
|
35
|
+
}): number;
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
import { LayoutNode } from "../../dom/node.js";
|
|
2
|
-
import { Display, FloatMode, OverflowMode, Position } from "../../css/enums.js";
|
|
2
|
+
import { BoxSizing, Display, FloatMode, OverflowMode, Position } from "../../css/enums.js";
|
|
3
3
|
import { clampMinMax, resolveLength, isAutoLength } from "../../css/length.js";
|
|
4
4
|
export function resolveBoxMetrics(node, widthRef, heightRef) {
|
|
5
5
|
const { style } = node;
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
const
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
const
|
|
12
|
-
const
|
|
13
|
-
const
|
|
6
|
+
const containerRefs = { containerWidth: widthRef, containerHeight: heightRef };
|
|
7
|
+
const paddingLeft = resolveLength(style.paddingLeft, widthRef, { auto: "zero", ...containerRefs });
|
|
8
|
+
const paddingRight = resolveLength(style.paddingRight, widthRef, { auto: "zero", ...containerRefs });
|
|
9
|
+
const paddingTop = resolveLength(style.paddingTop, heightRef, { auto: "zero", ...containerRefs });
|
|
10
|
+
const paddingBottom = resolveLength(style.paddingBottom, heightRef, { auto: "zero", ...containerRefs });
|
|
11
|
+
const borderLeft = resolveLength(style.borderLeft, widthRef, { auto: "zero", ...containerRefs });
|
|
12
|
+
const borderRight = resolveLength(style.borderRight, widthRef, { auto: "zero", ...containerRefs });
|
|
13
|
+
const borderTop = resolveLength(style.borderTop, heightRef, { auto: "zero", ...containerRefs });
|
|
14
|
+
const borderBottom = resolveLength(style.borderBottom, heightRef, { auto: "zero", ...containerRefs });
|
|
14
15
|
return {
|
|
15
16
|
paddingLeft,
|
|
16
17
|
paddingRight,
|
|
@@ -24,27 +25,39 @@ export function resolveBoxMetrics(node, widthRef, heightRef) {
|
|
|
24
25
|
contentBoxY: node.box.y + borderTop + paddingTop,
|
|
25
26
|
};
|
|
26
27
|
}
|
|
27
|
-
export function
|
|
28
|
+
export function adjustForBoxSizing(specifiedSize, boxSizing, nonContentExtras) {
|
|
29
|
+
if (boxSizing === BoxSizing.BorderBox) {
|
|
30
|
+
return Math.max(0, specifiedSize - nonContentExtras);
|
|
31
|
+
}
|
|
32
|
+
return specifiedSize;
|
|
33
|
+
}
|
|
34
|
+
export function horizontalNonContent(node, reference, containerHeight = reference) {
|
|
28
35
|
const { style } = node;
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
resolveLength(style.
|
|
32
|
-
resolveLength(style.
|
|
36
|
+
const containerRefs = { containerWidth: reference, containerHeight };
|
|
37
|
+
return (resolveLength(style.paddingLeft, reference, { auto: "zero", ...containerRefs }) +
|
|
38
|
+
resolveLength(style.paddingRight, reference, { auto: "zero", ...containerRefs }) +
|
|
39
|
+
resolveLength(style.borderLeft, reference, { auto: "zero", ...containerRefs }) +
|
|
40
|
+
resolveLength(style.borderRight, reference, { auto: "zero", ...containerRefs }));
|
|
33
41
|
}
|
|
34
|
-
export function verticalNonContent(node, reference) {
|
|
42
|
+
export function verticalNonContent(node, reference, containerWidth = reference) {
|
|
35
43
|
const { style } = node;
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
resolveLength(style.
|
|
39
|
-
resolveLength(style.
|
|
44
|
+
const containerRefs = { containerWidth, containerHeight: reference };
|
|
45
|
+
return (resolveLength(style.paddingTop, reference, { auto: "zero", ...containerRefs }) +
|
|
46
|
+
resolveLength(style.paddingBottom, reference, { auto: "zero", ...containerRefs }) +
|
|
47
|
+
resolveLength(style.borderTop, reference, { auto: "zero", ...containerRefs }) +
|
|
48
|
+
resolveLength(style.borderBottom, reference, { auto: "zero", ...containerRefs }));
|
|
40
49
|
}
|
|
41
|
-
export function horizontalMargin(node, reference) {
|
|
50
|
+
export function horizontalMargin(node, reference, containerHeight = reference) {
|
|
42
51
|
const { style } = node;
|
|
43
|
-
|
|
52
|
+
const containerRefs = { containerWidth: reference, containerHeight };
|
|
53
|
+
return (resolveLength(style.marginLeft, reference, { auto: "zero", ...containerRefs }) +
|
|
54
|
+
resolveLength(style.marginRight, reference, { auto: "zero", ...containerRefs }));
|
|
44
55
|
}
|
|
45
|
-
export function verticalMargin(node, reference) {
|
|
56
|
+
export function verticalMargin(node, reference, containerWidth = reference) {
|
|
46
57
|
const { style } = node;
|
|
47
|
-
|
|
58
|
+
const containerRefs = { containerWidth, containerHeight: reference };
|
|
59
|
+
return (resolveLength(style.marginTop, reference, { auto: "zero", ...containerRefs }) +
|
|
60
|
+
resolveLength(style.marginBottom, reference, { auto: "zero", ...containerRefs }));
|
|
48
61
|
}
|
|
49
62
|
export function inFlow(node) {
|
|
50
63
|
const { position, float: floatMode } = node.style;
|
|
@@ -109,17 +122,22 @@ export function containingBlock(node, viewport) {
|
|
|
109
122
|
// This allows percentage heights like `height: 100%` on flex children
|
|
110
123
|
// to resolve against a definite containing block height instead of 0.
|
|
111
124
|
if (heightRef === 0 && parent.style.height !== "auto") {
|
|
112
|
-
const explicitHeight = resolveLength(parent.style.height, viewport.height, {
|
|
125
|
+
const explicitHeight = resolveLength(parent.style.height, viewport.height, {
|
|
126
|
+
auto: "reference",
|
|
127
|
+
containerWidth: viewport.width,
|
|
128
|
+
containerHeight: viewport.height,
|
|
129
|
+
});
|
|
113
130
|
if (Number.isFinite(explicitHeight) && explicitHeight > 0) {
|
|
114
131
|
heightRef = explicitHeight;
|
|
115
132
|
}
|
|
116
133
|
}
|
|
134
|
+
const containerRefs = { containerWidth: widthRef, containerHeight: heightRef };
|
|
117
135
|
const xOffset = parent.box.x +
|
|
118
|
-
resolveLength(parent.style.paddingLeft, widthRef, { auto: "zero" }) +
|
|
119
|
-
resolveLength(parent.style.borderLeft, widthRef, { auto: "zero" });
|
|
136
|
+
resolveLength(parent.style.paddingLeft, widthRef, { auto: "zero", ...containerRefs }) +
|
|
137
|
+
resolveLength(parent.style.borderLeft, widthRef, { auto: "zero", ...containerRefs });
|
|
120
138
|
const yOffset = parent.box.y +
|
|
121
|
-
resolveLength(parent.style.paddingTop, heightRef, { auto: "zero" }) +
|
|
122
|
-
resolveLength(parent.style.borderTop, heightRef, { auto: "zero" });
|
|
139
|
+
resolveLength(parent.style.paddingTop, heightRef, { auto: "zero", ...containerRefs }) +
|
|
140
|
+
resolveLength(parent.style.borderTop, heightRef, { auto: "zero", ...containerRefs });
|
|
123
141
|
return {
|
|
124
142
|
x: xOffset,
|
|
125
143
|
y: yOffset,
|
|
@@ -127,29 +145,34 @@ export function containingBlock(node, viewport) {
|
|
|
127
145
|
height: heightRef,
|
|
128
146
|
};
|
|
129
147
|
}
|
|
130
|
-
export function resolveWidthBlock(node, containingBlockWidth) {
|
|
148
|
+
export function resolveWidthBlock(node, containingBlockWidth, containingBlockHeight = containingBlockWidth) {
|
|
131
149
|
const style = node.style;
|
|
150
|
+
const containerRefs = { containerWidth: containingBlockWidth, containerHeight: containingBlockHeight };
|
|
151
|
+
const hNonContent = horizontalNonContent(node, containingBlockWidth, containingBlockHeight);
|
|
132
152
|
const marginLeft = isAutoLength(style.marginLeft)
|
|
133
153
|
? 0
|
|
134
|
-
: resolveLength(style.marginLeft, containingBlockWidth, { auto: "zero" });
|
|
154
|
+
: resolveLength(style.marginLeft, containingBlockWidth, { auto: "zero", ...containerRefs });
|
|
135
155
|
const marginRight = isAutoLength(style.marginRight)
|
|
136
156
|
? 0
|
|
137
|
-
: resolveLength(style.marginRight, containingBlockWidth, { auto: "zero" });
|
|
138
|
-
const available = Math.max(0, containingBlockWidth -
|
|
139
|
-
const width = style.width ===
|
|
157
|
+
: resolveLength(style.marginRight, containingBlockWidth, { auto: "zero", ...containerRefs });
|
|
158
|
+
const available = Math.max(0, containingBlockWidth - hNonContent - marginLeft - marginRight);
|
|
159
|
+
const width = style.width === undefined || isAutoLength(style.width)
|
|
140
160
|
? available
|
|
141
|
-
: resolveLength(style.width, containingBlockWidth, {
|
|
142
|
-
|
|
143
|
-
})
|
|
144
|
-
|
|
145
|
-
const maxWidth = style.maxWidth
|
|
161
|
+
: adjustForBoxSizing(resolveLength(style.width, containingBlockWidth, { auto: "reference", ...containerRefs }), style.boxSizing, hNonContent);
|
|
162
|
+
const minWidth = style.minWidth
|
|
163
|
+
? adjustForBoxSizing(resolveLength(style.minWidth, containingBlockWidth, { auto: "zero", ...containerRefs }), style.boxSizing, hNonContent)
|
|
164
|
+
: Number.NEGATIVE_INFINITY;
|
|
165
|
+
const maxWidth = style.maxWidth
|
|
166
|
+
? adjustForBoxSizing(resolveLength(style.maxWidth, containingBlockWidth, { auto: "reference", ...containerRefs }), style.boxSizing, hNonContent)
|
|
167
|
+
: Number.POSITIVE_INFINITY;
|
|
146
168
|
return clampMinMax(width, minWidth, maxWidth);
|
|
147
169
|
}
|
|
148
|
-
export function resolveBlockAutoMargins(containingBlockWidth, borderBoxWidth, marginLeft, marginRight) {
|
|
170
|
+
export function resolveBlockAutoMargins(containingBlockWidth, borderBoxWidth, marginLeft, marginRight, containingBlockHeight = containingBlockWidth) {
|
|
171
|
+
const containerRefs = { containerWidth: containingBlockWidth, containerHeight: containingBlockHeight };
|
|
149
172
|
const marginLeftAuto = isAutoLength(marginLeft);
|
|
150
173
|
const marginRightAuto = isAutoLength(marginRight);
|
|
151
|
-
const resolvedMarginLeft = marginLeftAuto ? 0 : resolveLength(marginLeft, containingBlockWidth, { auto: "zero" });
|
|
152
|
-
const resolvedMarginRight = marginRightAuto ? 0 : resolveLength(marginRight, containingBlockWidth, { auto: "zero" });
|
|
174
|
+
const resolvedMarginLeft = marginLeftAuto ? 0 : resolveLength(marginLeft, containingBlockWidth, { auto: "zero", ...containerRefs });
|
|
175
|
+
const resolvedMarginRight = marginRightAuto ? 0 : resolveLength(marginRight, containingBlockWidth, { auto: "zero", ...containerRefs });
|
|
153
176
|
let usedMarginLeft = resolvedMarginLeft;
|
|
154
177
|
let usedMarginRight = resolvedMarginRight;
|
|
155
178
|
const remainingSpace = containingBlockWidth - (borderBoxWidth + resolvedMarginLeft + resolvedMarginRight);
|
|
@@ -188,3 +211,10 @@ export function resolveBlockAutoMargins(containingBlockWidth, borderBoxWidth, ma
|
|
|
188
211
|
}
|
|
189
212
|
return { marginLeft: usedMarginLeft, marginRight: usedMarginRight };
|
|
190
213
|
}
|
|
214
|
+
export function applyMinHeight(contentHeight, node, heightRef, verticalExtras, containerRefs) {
|
|
215
|
+
if (node.style.minHeight === undefined || isAutoLength(node.style.minHeight)) {
|
|
216
|
+
return contentHeight;
|
|
217
|
+
}
|
|
218
|
+
const minH = adjustForBoxSizing(resolveLength(node.style.minHeight, heightRef, { auto: "zero", ...containerRefs }), node.style.boxSizing, verticalExtras);
|
|
219
|
+
return Number.isFinite(minH) ? Math.max(contentHeight, minH) : contentHeight;
|
|
220
|
+
}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { LayoutNode } from "../../dom/node.js";
|
|
2
2
|
import { resolveLength } from "../../css/length.js";
|
|
3
3
|
export function shrinkToFitWidth(node, availableWidth) {
|
|
4
|
+
const containerRefs = { containerWidth: availableWidth, containerHeight: availableWidth };
|
|
4
5
|
if (typeof node.style.width === "number") {
|
|
5
6
|
return Math.min(node.style.width, availableWidth);
|
|
6
7
|
}
|
|
7
8
|
if (node.style.width !== "auto") {
|
|
8
|
-
return Math.min(resolveLength(node.style.width, availableWidth), availableWidth);
|
|
9
|
+
return Math.min(resolveLength(node.style.width, availableWidth, { ...containerRefs }), availableWidth);
|
|
9
10
|
}
|
|
10
11
|
return availableWidth;
|
|
11
12
|
}
|
|
@@ -17,12 +17,18 @@ export declare class PdfFontRegistry {
|
|
|
17
17
|
private readonly glyphUsage;
|
|
18
18
|
private readonly fonts;
|
|
19
19
|
private fontCounter;
|
|
20
|
+
private identityCounter;
|
|
21
|
+
private readonly programIdentity;
|
|
22
|
+
private readonly cmapIdentity;
|
|
20
23
|
constructor(encoding?: "identity" | "sequential");
|
|
21
24
|
/**
|
|
22
25
|
* Generates a stable key for a UnifiedFont.
|
|
23
26
|
* Uses CSS metadata if available, otherwise falls back to a generic key.
|
|
24
27
|
*/
|
|
25
28
|
private fontKey;
|
|
29
|
+
private resolveProgramToken;
|
|
30
|
+
private resolveCmapToken;
|
|
31
|
+
private identityFor;
|
|
26
32
|
/**
|
|
27
33
|
* Registers a GlyphRun, collecting its glyph IDs for later subsetting.
|
|
28
34
|
*/
|
|
@@ -12,19 +12,47 @@ export class PdfFontRegistry {
|
|
|
12
12
|
this.fonts = new Map();
|
|
13
13
|
// Counter for generating unique font resource names
|
|
14
14
|
this.fontCounter = 0;
|
|
15
|
+
this.identityCounter = 0;
|
|
16
|
+
this.programIdentity = new WeakMap();
|
|
17
|
+
this.cmapIdentity = new WeakMap();
|
|
15
18
|
}
|
|
16
19
|
/**
|
|
17
20
|
* Generates a stable key for a UnifiedFont.
|
|
18
21
|
* Uses CSS metadata if available, otherwise falls back to a generic key.
|
|
19
22
|
*/
|
|
20
23
|
fontKey(font) {
|
|
24
|
+
const programToken = this.resolveProgramToken(font);
|
|
25
|
+
const cmapToken = this.resolveCmapToken(font);
|
|
21
26
|
if (font.css) {
|
|
22
27
|
const { family, weight, style } = font.css;
|
|
23
|
-
return `${family}|${weight}|${style}`;
|
|
28
|
+
return `${family}|${weight}|${style}|p:${programToken}|c:${cmapToken}`;
|
|
24
29
|
}
|
|
25
30
|
// Fallback: use unitsPerEm and ascender as a fingerprint
|
|
26
31
|
const { unitsPerEm, ascender } = font.metrics.metrics;
|
|
27
|
-
return `_fallback_${unitsPerEm}_${ascender}`;
|
|
32
|
+
return `_fallback_${unitsPerEm}_${ascender}|p:${programToken}|c:${cmapToken}`;
|
|
33
|
+
}
|
|
34
|
+
resolveProgramToken(font) {
|
|
35
|
+
const rawAccessor = font.program.getRawTableData;
|
|
36
|
+
if (rawAccessor) {
|
|
37
|
+
return `raw-${this.identityFor(this.programIdentity, rawAccessor)}`;
|
|
38
|
+
}
|
|
39
|
+
return `shape-${font.program.sourceFormat}-${font.program.unitsPerEm}-${font.program.glyphCount}`;
|
|
40
|
+
}
|
|
41
|
+
resolveCmapToken(font) {
|
|
42
|
+
const cmap = font.metrics.cmap;
|
|
43
|
+
if (cmap) {
|
|
44
|
+
return `map-${this.identityFor(this.cmapIdentity, cmap)}`;
|
|
45
|
+
}
|
|
46
|
+
return `none-${font.program.unitsPerEm}-${font.program.glyphCount}`;
|
|
47
|
+
}
|
|
48
|
+
identityFor(store, key) {
|
|
49
|
+
const existing = store.get(key);
|
|
50
|
+
if (existing !== undefined) {
|
|
51
|
+
return existing;
|
|
52
|
+
}
|
|
53
|
+
const next = ++this.identityCounter;
|
|
54
|
+
store.set(key, next);
|
|
55
|
+
return next;
|
|
28
56
|
}
|
|
29
57
|
/**
|
|
30
58
|
* Registers a GlyphRun, collecting its glyph IDs for later subsetting.
|
|
@@ -19,6 +19,8 @@ export interface HeaderFooterPaintContext {
|
|
|
19
19
|
fontRegistry: FontRegistry;
|
|
20
20
|
/** Page offset Y for coordinate transformation */
|
|
21
21
|
pageOffsetY: number;
|
|
22
|
+
/** Whether header/footer paint should be clipped to max height area */
|
|
23
|
+
clipOverflow?: boolean;
|
|
22
24
|
/** Optional CSS for header/footer styling */
|
|
23
25
|
css?: string;
|
|
24
26
|
/** Platform environment (Node/browser) */
|
|
@@ -28,7 +28,7 @@ export async function paintHeaderFooter(painter, header, footer, tokens, pageInd
|
|
|
28
28
|
* Renders headers and footers as full HTML through the layout pipeline.
|
|
29
29
|
*/
|
|
30
30
|
async function paintHeaderFooterWithContext(painter, header, footer, tokens, pageIndex, totalPages, context) {
|
|
31
|
-
const { margins, pageWidthPx, pageHeightPx, fontRegistry, pageOffsetY, css, resourceBaseDir, assetRootDir } = context;
|
|
31
|
+
const { margins, pageWidthPx, pageHeightPx, fontRegistry, pageOffsetY, clipOverflow = false, css, resourceBaseDir, assetRootDir } = context;
|
|
32
32
|
// Calculate content width (page width minus left and right margins)
|
|
33
33
|
const contentWidthPx = pageWidthPx - margins.left - margins.right;
|
|
34
34
|
log("layout", "debug", "paintHeaderFooterWithContext", {
|
|
@@ -58,8 +58,26 @@ async function paintHeaderFooterWithContext(painter, header, footer, tokens, pag
|
|
|
58
58
|
});
|
|
59
59
|
if (rendered) {
|
|
60
60
|
log("layout", "debug", "Header rendered successfully", { heightPx: rendered.heightPx });
|
|
61
|
-
|
|
62
|
-
|
|
61
|
+
const headerY = margins.top;
|
|
62
|
+
const shouldClip = clipOverflow && header.maxHeightPx > 0 && contentWidthPx > 0;
|
|
63
|
+
if (shouldClip) {
|
|
64
|
+
const clipPath = buildRectClipPath({
|
|
65
|
+
x: margins.left,
|
|
66
|
+
y: headerY + pageOffsetY,
|
|
67
|
+
width: contentWidthPx,
|
|
68
|
+
height: header.maxHeightPx,
|
|
69
|
+
});
|
|
70
|
+
painter.beginClipPath(clipPath);
|
|
71
|
+
}
|
|
72
|
+
try {
|
|
73
|
+
// Header is positioned at the top margin area
|
|
74
|
+
await paintRenderedHeaderFooter(painter, rendered, margins.left, headerY, fontRegistry, pageOffsetY);
|
|
75
|
+
}
|
|
76
|
+
finally {
|
|
77
|
+
if (shouldClip) {
|
|
78
|
+
painter.endClipPath();
|
|
79
|
+
}
|
|
80
|
+
}
|
|
63
81
|
}
|
|
64
82
|
}
|
|
65
83
|
catch (err) {
|
|
@@ -87,7 +105,24 @@ async function paintHeaderFooterWithContext(painter, header, footer, tokens, pag
|
|
|
87
105
|
if (rendered) {
|
|
88
106
|
// Footer is positioned at the bottom of the page
|
|
89
107
|
const footerY = pageHeightPx - margins.bottom - footer.maxHeightPx;
|
|
90
|
-
|
|
108
|
+
const shouldClip = clipOverflow && footer.maxHeightPx > 0 && contentWidthPx > 0;
|
|
109
|
+
if (shouldClip) {
|
|
110
|
+
const clipPath = buildRectClipPath({
|
|
111
|
+
x: margins.left,
|
|
112
|
+
y: footerY + pageOffsetY,
|
|
113
|
+
width: contentWidthPx,
|
|
114
|
+
height: footer.maxHeightPx,
|
|
115
|
+
});
|
|
116
|
+
painter.beginClipPath(clipPath);
|
|
117
|
+
}
|
|
118
|
+
try {
|
|
119
|
+
await paintRenderedHeaderFooter(painter, rendered, margins.left, footerY, fontRegistry, pageOffsetY);
|
|
120
|
+
}
|
|
121
|
+
finally {
|
|
122
|
+
if (shouldClip) {
|
|
123
|
+
painter.endClipPath();
|
|
124
|
+
}
|
|
125
|
+
}
|
|
91
126
|
}
|
|
92
127
|
}
|
|
93
128
|
catch (err) {
|
|
@@ -125,3 +160,16 @@ function stringify(content) {
|
|
|
125
160
|
}
|
|
126
161
|
return JSON.stringify(content);
|
|
127
162
|
}
|
|
163
|
+
function buildRectClipPath(rect) {
|
|
164
|
+
const x = rect.x;
|
|
165
|
+
const y = rect.y;
|
|
166
|
+
const right = rect.x + rect.width;
|
|
167
|
+
const bottom = rect.y + rect.height;
|
|
168
|
+
return [
|
|
169
|
+
{ type: "moveTo", x, y },
|
|
170
|
+
{ type: "lineTo", x: right, y },
|
|
171
|
+
{ type: "lineTo", x: right, y: bottom },
|
|
172
|
+
{ type: "lineTo", x, y: bottom },
|
|
173
|
+
{ type: "closePath" },
|
|
174
|
+
];
|
|
175
|
+
}
|
|
@@ -27,6 +27,7 @@ import { FontRegistryResolver } from "../fonts/font-registry-resolver.js";
|
|
|
27
27
|
import { computeGlyphRun, applyWordSpacingToGlyphRun } from "./utils/node-text-run-factory.js";
|
|
28
28
|
import { paintBoxAtomic } from "./renderer/box-painter.js";
|
|
29
29
|
import { applyPlaceholders } from "./header-footer-tokens.js";
|
|
30
|
+
import { createCounterContext } from "../layout/counter.js";
|
|
30
31
|
/**
|
|
31
32
|
* Renders header or footer HTML into a layout tree.
|
|
32
33
|
* This uses the same pipeline as the main content for full HTML/CSS support.
|
|
@@ -59,7 +60,17 @@ export async function renderHeaderFooterHtml(options) {
|
|
|
59
60
|
rootStyle.display = Display.Block;
|
|
60
61
|
}
|
|
61
62
|
const rootLayout = new LayoutNode(rootStyle, [], { tagName: rootElement?.tagName?.toLowerCase() });
|
|
62
|
-
const
|
|
63
|
+
const counterContext = createCounterContext();
|
|
64
|
+
const rootCounterScopeId = counterContext.registerScope(null);
|
|
65
|
+
const conversionContext = {
|
|
66
|
+
resourceBaseDir: resolvedResourceBase,
|
|
67
|
+
assetRootDir: resolvedAssetRoot,
|
|
68
|
+
units,
|
|
69
|
+
rootFontSize,
|
|
70
|
+
environment,
|
|
71
|
+
counterContext,
|
|
72
|
+
rootCounterScopeId,
|
|
73
|
+
};
|
|
63
74
|
if (rootElement) {
|
|
64
75
|
for (const child of Array.from(rootElement.childNodes)) {
|
|
65
76
|
if (child.nodeType === child.ELEMENT_NODE) {
|
|
@@ -137,7 +137,9 @@ function convertNode(node, state, inheritedTextGradient) {
|
|
|
137
137
|
const background = resolveBackgroundLayers(node, { borderBox, paddingBox, contentBox });
|
|
138
138
|
const clipPath = resolveClipPath(node, { borderBox, paddingBox, contentBox });
|
|
139
139
|
const zIndex = typeof node.style.zIndex === "number" ? node.style.zIndex : 0;
|
|
140
|
-
const establishesStackingContext = typeof node.style.zIndex === "number" && node.style.position !== Position.Static
|
|
140
|
+
const establishesStackingContext = typeof node.style.zIndex === "number" && node.style.position !== Position.Static ||
|
|
141
|
+
(node.style.filter !== undefined && node.style.filter.length > 0) ||
|
|
142
|
+
(node.style.backdropFilter !== undefined && node.style.backdropFilter.length > 0);
|
|
141
143
|
const borderStyle = {
|
|
142
144
|
top: normalizeBorderStyle(node.style.borderStyleTop),
|
|
143
145
|
right: normalizeBorderStyle(node.style.borderStyleRight),
|
|
@@ -202,6 +204,8 @@ function convertNode(node, state, inheritedTextGradient) {
|
|
|
202
204
|
customData,
|
|
203
205
|
textAlign,
|
|
204
206
|
transform,
|
|
207
|
+
filter: node.style.filter ? [...node.style.filter] : undefined,
|
|
208
|
+
backdropFilter: node.style.backdropFilter ? [...node.style.backdropFilter] : undefined,
|
|
205
209
|
};
|
|
206
210
|
}
|
|
207
211
|
function normalizeBorderStyle(value) {
|
|
@@ -76,9 +76,20 @@ export class PagePainter {
|
|
|
76
76
|
}
|
|
77
77
|
async drawText(text, xPx, yPx, options = { fontSizePt: 10 }) {
|
|
78
78
|
await this.textRenderer.drawText(text, xPx, yPx, options);
|
|
79
|
+
const cmds = this.textRenderer.flushCommands();
|
|
80
|
+
if (cmds.length > 0) {
|
|
81
|
+
this.shapeRenderer.pushRawCommands(cmds);
|
|
82
|
+
}
|
|
79
83
|
}
|
|
80
84
|
async drawTextRun(run) {
|
|
81
85
|
await this.textRenderer.drawTextRun(run);
|
|
86
|
+
// Immediately move text commands into the shape stream so that
|
|
87
|
+
// text and background operations are interleaved in paint order,
|
|
88
|
+
// preserving correct z-index stacking.
|
|
89
|
+
const cmds = this.textRenderer.flushCommands();
|
|
90
|
+
if (cmds.length > 0) {
|
|
91
|
+
this.shapeRenderer.pushRawCommands(cmds);
|
|
92
|
+
}
|
|
82
93
|
}
|
|
83
94
|
fillRoundedRect(rect, radii, paint) {
|
|
84
95
|
this.shapeRenderer.fillRoundedRect(rect, radii, paint);
|
|
@@ -153,9 +164,11 @@ export class PagePainter {
|
|
|
153
164
|
}
|
|
154
165
|
beginTransformScope(transform, rect) {
|
|
155
166
|
this.transformScopeManager.beginTransformScope(transform, rect);
|
|
167
|
+
this.textRenderer.setTransformContext(rect);
|
|
156
168
|
}
|
|
157
169
|
endTransformScope() {
|
|
158
170
|
this.transformScopeManager.endTransformScope();
|
|
171
|
+
this.textRenderer.clearTransformContext();
|
|
159
172
|
}
|
|
160
173
|
result() {
|
|
161
174
|
// Ensure any atlas pages created by the glyph packer are registered as image resources
|