pagyra-js 0.0.20 → 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 -417
- package/dist/src/html/image-converter.d.ts +5 -0
- 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-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 +11 -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/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/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
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { Display } from "../../css/enums.js";
|
|
2
|
-
import { resolveLength } from "../../css/length.js";
|
|
3
|
-
import { containingBlock, horizontalMargin, horizontalNonContent, resolveWidthBlock, verticalNonContent, } from "../utils/node-math.js";
|
|
1
|
+
import { AlignItems, BoxSizing, Display } from "../../css/enums.js";
|
|
2
|
+
import { isAutoLength, resolveLength } from "../../css/length.js";
|
|
3
|
+
import { adjustForBoxSizing, applyMinHeight, containingBlock, horizontalMargin, horizontalNonContent, resolveWidthBlock, verticalNonContent, } from "../utils/node-math.js";
|
|
4
4
|
import { calculateTrackOffsets, calculateTotalGap } from "../utils/gap-calculator.js";
|
|
5
5
|
function isRepeatTrack(def) {
|
|
6
6
|
return typeof def === "object" && def !== null && "kind" in def && def.kind === "repeat";
|
|
@@ -12,6 +12,8 @@ function trackMinSize(track) {
|
|
|
12
12
|
switch (track.kind) {
|
|
13
13
|
case "fixed":
|
|
14
14
|
return Math.max(0, track.size);
|
|
15
|
+
case "clamp":
|
|
16
|
+
return Math.max(0, track.min);
|
|
15
17
|
case "flex":
|
|
16
18
|
return Math.max(0, track.min ?? 0);
|
|
17
19
|
case "auto":
|
|
@@ -27,6 +29,14 @@ function cloneTrackSize(track) {
|
|
|
27
29
|
if (track.kind === "fixed") {
|
|
28
30
|
return { kind: "fixed", size: track.size };
|
|
29
31
|
}
|
|
32
|
+
if (track.kind === "clamp") {
|
|
33
|
+
return {
|
|
34
|
+
kind: "clamp",
|
|
35
|
+
min: track.min,
|
|
36
|
+
preferred: track.preferred,
|
|
37
|
+
max: track.max,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
30
40
|
if (track.kind === "flex") {
|
|
31
41
|
return {
|
|
32
42
|
kind: "flex",
|
|
@@ -90,6 +100,12 @@ function resolveColumnWidths(tracks, contentWidth, columnGap) {
|
|
|
90
100
|
switch (track.kind) {
|
|
91
101
|
case "fixed":
|
|
92
102
|
return Math.max(0, track.size);
|
|
103
|
+
case "clamp": {
|
|
104
|
+
const min = Math.max(0, track.min);
|
|
105
|
+
const max = Math.max(min, track.max);
|
|
106
|
+
const preferred = track.preferred;
|
|
107
|
+
return Math.max(min, Math.min(preferred, max));
|
|
108
|
+
}
|
|
93
109
|
case "flex": {
|
|
94
110
|
let size = minSizes[index];
|
|
95
111
|
if (totalFlex > 0 && flexFactors[index] > 0) {
|
|
@@ -121,15 +137,16 @@ export class GridLayoutStrategy {
|
|
|
121
137
|
}
|
|
122
138
|
layout(node, context) {
|
|
123
139
|
const cb = containingBlock(node, context.env.viewport);
|
|
124
|
-
const
|
|
140
|
+
const containerRefs = { containerWidth: cb.width, containerHeight: cb.height };
|
|
141
|
+
const baseContentWidth = resolveWidthBlock(node, cb.width, cb.height);
|
|
125
142
|
node.box.contentWidth = baseContentWidth;
|
|
126
|
-
const horizontalExtras = horizontalNonContent(node, baseContentWidth);
|
|
143
|
+
const horizontalExtras = horizontalNonContent(node, baseContentWidth, cb.height);
|
|
127
144
|
node.box.borderBoxWidth = baseContentWidth + horizontalExtras;
|
|
128
|
-
node.box.marginBoxWidth = node.box.borderBoxWidth + horizontalMargin(node, baseContentWidth);
|
|
129
|
-
const paddingLeft = resolveLength(node.style.paddingLeft, baseContentWidth, { auto: "zero" });
|
|
130
|
-
const paddingTop = resolveLength(node.style.paddingTop,
|
|
131
|
-
const borderLeft = resolveLength(node.style.borderLeft, baseContentWidth, { auto: "zero" });
|
|
132
|
-
const borderTop = resolveLength(node.style.borderTop,
|
|
145
|
+
node.box.marginBoxWidth = node.box.borderBoxWidth + horizontalMargin(node, baseContentWidth, cb.height);
|
|
146
|
+
const paddingLeft = resolveLength(node.style.paddingLeft, baseContentWidth, { auto: "zero", ...containerRefs });
|
|
147
|
+
const paddingTop = resolveLength(node.style.paddingTop, cb.height, { auto: "zero", ...containerRefs });
|
|
148
|
+
const borderLeft = resolveLength(node.style.borderLeft, baseContentWidth, { auto: "zero", ...containerRefs });
|
|
149
|
+
const borderTop = resolveLength(node.style.borderTop, cb.height, { auto: "zero", ...containerRefs });
|
|
133
150
|
const contentOriginX = node.box.x + borderLeft + paddingLeft;
|
|
134
151
|
const contentOriginY = node.box.y + borderTop + paddingTop;
|
|
135
152
|
const columnGap = node.style.columnGap ?? 0;
|
|
@@ -141,55 +158,175 @@ export class GridLayoutStrategy {
|
|
|
141
158
|
const resolvedContentWidth = columnWidths.length > 0 ? Math.max(baseContentWidth, totalColumnWidth) : baseContentWidth;
|
|
142
159
|
node.box.contentWidth = resolvedContentWidth;
|
|
143
160
|
node.box.borderBoxWidth = resolvedContentWidth + horizontalExtras;
|
|
144
|
-
node.box.marginBoxWidth = node.box.borderBoxWidth + horizontalMargin(node, resolvedContentWidth);
|
|
161
|
+
node.box.marginBoxWidth = node.box.borderBoxWidth + horizontalMargin(node, resolvedContentWidth, cb.height);
|
|
145
162
|
const columnOffsets = calculateTrackOffsets(columnWidths, columnGap);
|
|
146
|
-
|
|
163
|
+
const rows = [];
|
|
147
164
|
let currentRowTop = contentOriginY;
|
|
148
165
|
let currentRowHeight = 0;
|
|
149
166
|
let columnIndex = 0;
|
|
150
|
-
let
|
|
167
|
+
let currentRowItems = [];
|
|
151
168
|
for (const child of node.children) {
|
|
152
169
|
if (child.style.display === Display.None) {
|
|
153
170
|
continue;
|
|
154
171
|
}
|
|
155
|
-
const
|
|
172
|
+
const span = Math.min(child.style.gridColumnSpan ?? 1, columnWidths.length);
|
|
173
|
+
// Wrap to next row if the span doesn't fit
|
|
174
|
+
if (columnIndex + span > columnWidths.length) {
|
|
175
|
+
if (currentRowItems.length > 0) {
|
|
176
|
+
rows.push({ items: currentRowItems, height: currentRowHeight });
|
|
177
|
+
currentRowTop += currentRowHeight + rowGap;
|
|
178
|
+
currentRowHeight = 0;
|
|
179
|
+
currentRowItems = [];
|
|
180
|
+
}
|
|
181
|
+
columnIndex = 0;
|
|
182
|
+
}
|
|
183
|
+
// Calculate the total width of spanned columns
|
|
184
|
+
let columnWidth = 0;
|
|
185
|
+
for (let s = 0; s < span; s++) {
|
|
186
|
+
columnWidth += columnWidths[columnIndex + s] ?? 0;
|
|
187
|
+
}
|
|
188
|
+
// Add gap between spanned columns
|
|
189
|
+
if (span > 1) {
|
|
190
|
+
columnWidth += columnGap * (span - 1);
|
|
191
|
+
}
|
|
156
192
|
const columnX = contentOriginX + (columnOffsets[columnIndex] ?? 0);
|
|
157
|
-
child.box.x = columnX;
|
|
158
|
-
child.box.y = currentRowTop;
|
|
159
193
|
const originalContentWidth = node.box.contentWidth;
|
|
160
194
|
node.box.contentWidth = columnWidth;
|
|
161
195
|
context.layoutChild(child);
|
|
162
196
|
node.box.contentWidth = originalContentWidth;
|
|
163
|
-
child.box.x = columnX;
|
|
164
|
-
child.box.y = currentRowTop;
|
|
165
197
|
currentRowHeight = Math.max(currentRowHeight, child.box.borderBoxHeight);
|
|
166
|
-
|
|
198
|
+
currentRowItems.push({
|
|
199
|
+
child,
|
|
200
|
+
columnWidth,
|
|
201
|
+
columnX,
|
|
202
|
+
});
|
|
203
|
+
columnIndex += span;
|
|
167
204
|
if (columnIndex >= columnWidths.length) {
|
|
168
|
-
|
|
169
|
-
contentHeight += currentRowHeight;
|
|
205
|
+
rows.push({ items: currentRowItems, height: currentRowHeight });
|
|
170
206
|
currentRowTop += currentRowHeight + rowGap;
|
|
171
207
|
currentRowHeight = 0;
|
|
172
208
|
columnIndex = 0;
|
|
209
|
+
currentRowItems = [];
|
|
173
210
|
}
|
|
174
211
|
}
|
|
175
|
-
if (
|
|
176
|
-
|
|
177
|
-
contentHeight += currentRowHeight;
|
|
212
|
+
if (currentRowItems.length > 0) {
|
|
213
|
+
rows.push({ items: currentRowItems, height: currentRowHeight });
|
|
178
214
|
}
|
|
215
|
+
const rowCount = rows.length;
|
|
216
|
+
const contentHeight = rows.reduce((sum, row) => sum + row.height, 0);
|
|
179
217
|
const totalRowGap = calculateTotalGap(rowGap, rowCount);
|
|
180
|
-
const verticalExtras = verticalNonContent(node,
|
|
181
|
-
|
|
218
|
+
const verticalExtras = verticalNonContent(node, cb.height, cb.width);
|
|
219
|
+
let resolvedContentHeight = Math.max(0, contentHeight + totalRowGap);
|
|
220
|
+
if (node.style.height !== "auto" && node.style.height !== undefined) {
|
|
221
|
+
resolvedContentHeight = adjustForBoxSizing(resolveLength(node.style.height, cb.height, { auto: "zero", ...containerRefs }), node.style.boxSizing, verticalExtras);
|
|
222
|
+
}
|
|
223
|
+
resolvedContentHeight = applyMinHeight(resolvedContentHeight, node, cb.height, verticalExtras, containerRefs);
|
|
224
|
+
node.box.contentHeight = Math.max(0, resolvedContentHeight);
|
|
182
225
|
node.box.borderBoxHeight = node.box.contentHeight + verticalExtras;
|
|
183
226
|
node.box.marginBoxHeight =
|
|
184
227
|
node.box.borderBoxHeight +
|
|
185
|
-
resolveLength(node.style.marginTop,
|
|
186
|
-
resolveLength(node.style.marginBottom,
|
|
228
|
+
resolveLength(node.style.marginTop, cb.height, { auto: "zero", ...containerRefs }) +
|
|
229
|
+
resolveLength(node.style.marginBottom, cb.height, { auto: "zero", ...containerRefs });
|
|
230
|
+
const stretchedRowHeights = resolveGridAlignContentRows(rows, rowGap, node.box.contentHeight, node.style.alignContent);
|
|
231
|
+
const containerAlignItems = node.style.alignItems ?? AlignItems.Stretch;
|
|
232
|
+
let finalRowTop = contentOriginY;
|
|
233
|
+
for (let rowIndex = 0; rowIndex < rows.length; rowIndex++) {
|
|
234
|
+
const row = rows[rowIndex];
|
|
235
|
+
const rowHeight = stretchedRowHeights[rowIndex] ?? row.height;
|
|
236
|
+
for (const rowItem of row.items) {
|
|
237
|
+
const child = rowItem.child;
|
|
238
|
+
const finalX = rowItem.columnX;
|
|
239
|
+
const finalY = finalRowTop;
|
|
240
|
+
const prePlaceDx = finalX - child.box.x;
|
|
241
|
+
const prePlaceDy = finalY - child.box.y;
|
|
242
|
+
child.box.x = finalX;
|
|
243
|
+
child.box.y = finalY;
|
|
244
|
+
offsetLayoutSubtree(child, prePlaceDx, prePlaceDy);
|
|
245
|
+
const alignSelf = resolveGridItemAlignment(child, containerAlignItems);
|
|
246
|
+
const autoHeight = child.style.height === undefined || child.style.height === "auto" || isAutoLength(child.style.height);
|
|
247
|
+
if (alignSelf === AlignItems.Stretch && autoHeight) {
|
|
248
|
+
const childContainerRefs = { containerWidth: rowItem.columnWidth, containerHeight: rowHeight };
|
|
249
|
+
const marginTop = resolveLength(child.style.marginTop, rowHeight, { auto: "zero", ...childContainerRefs });
|
|
250
|
+
const marginBottom = resolveLength(child.style.marginBottom, rowHeight, { auto: "zero", ...childContainerRefs });
|
|
251
|
+
const targetBorderBoxHeight = Math.max(0, rowHeight - marginTop - marginBottom);
|
|
252
|
+
const childVerticalExtras = verticalNonContent(child, rowHeight, rowItem.columnWidth);
|
|
253
|
+
const stretchedSpecifiedHeight = child.style.boxSizing === BoxSizing.BorderBox
|
|
254
|
+
? targetBorderBoxHeight
|
|
255
|
+
: Math.max(0, targetBorderBoxHeight - childVerticalExtras);
|
|
256
|
+
const currentBorderHeight = child.box.borderBoxHeight;
|
|
257
|
+
if (Math.abs(currentBorderHeight - targetBorderBoxHeight) > 0.01) {
|
|
258
|
+
const originalHeight = child.style.height;
|
|
259
|
+
const originalContentWidth = node.box.contentWidth;
|
|
260
|
+
try {
|
|
261
|
+
child.style.height = stretchedSpecifiedHeight;
|
|
262
|
+
child.box.x = finalX;
|
|
263
|
+
child.box.y = finalY;
|
|
264
|
+
node.box.contentWidth = rowItem.columnWidth;
|
|
265
|
+
context.layoutChild(child);
|
|
266
|
+
}
|
|
267
|
+
finally {
|
|
268
|
+
node.box.contentWidth = originalContentWidth;
|
|
269
|
+
child.style.height = originalHeight;
|
|
270
|
+
}
|
|
271
|
+
const relayoutDx = finalX - child.box.x;
|
|
272
|
+
const relayoutDy = finalY - child.box.y;
|
|
273
|
+
child.box.x = finalX;
|
|
274
|
+
child.box.y = finalY;
|
|
275
|
+
offsetLayoutSubtree(child, relayoutDx, relayoutDy);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
finalRowTop += rowHeight;
|
|
280
|
+
if (rowIndex < rows.length - 1) {
|
|
281
|
+
finalRowTop += rowGap;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
187
284
|
node.box.scrollWidth = Math.max(node.box.contentWidth, totalColumnWidth);
|
|
188
285
|
node.box.scrollHeight = node.box.contentHeight;
|
|
189
286
|
if (columnWidths.length === 0) {
|
|
190
287
|
node.box.contentWidth = baseContentWidth;
|
|
191
288
|
node.box.borderBoxWidth = node.box.contentWidth + horizontalExtras;
|
|
192
|
-
node.box.marginBoxWidth = node.box.borderBoxWidth + horizontalMargin(node, node.box.contentWidth);
|
|
289
|
+
node.box.marginBoxWidth = node.box.borderBoxWidth + horizontalMargin(node, node.box.contentWidth, cb.height);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
function offsetLayoutSubtree(node, deltaX, deltaY) {
|
|
294
|
+
if (deltaX === 0 && deltaY === 0) {
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
node.walk((desc) => {
|
|
298
|
+
if (desc !== node) {
|
|
299
|
+
desc.box.x += deltaX;
|
|
300
|
+
desc.box.y += deltaY;
|
|
301
|
+
}
|
|
302
|
+
desc.box.baseline += deltaY;
|
|
303
|
+
if (desc.inlineRuns && desc.inlineRuns.length > 0) {
|
|
304
|
+
for (const run of desc.inlineRuns) {
|
|
305
|
+
run.startX += deltaX;
|
|
306
|
+
run.baseline += deltaY;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
function resolveGridItemAlignment(child, containerAlign) {
|
|
312
|
+
const alignSelf = child.style.alignSelf;
|
|
313
|
+
if (alignSelf && alignSelf !== "auto") {
|
|
314
|
+
return alignSelf;
|
|
315
|
+
}
|
|
316
|
+
return containerAlign;
|
|
317
|
+
}
|
|
318
|
+
function resolveGridAlignContentRows(rows, rowGap, containerContentHeight, alignContent) {
|
|
319
|
+
const rowHeights = rows.map((row) => row.height);
|
|
320
|
+
if (alignContent !== "stretch") {
|
|
321
|
+
return rowHeights;
|
|
322
|
+
}
|
|
323
|
+
const naturalHeight = rowHeights.reduce((sum, height) => sum + height, 0) + calculateTotalGap(rowGap, rowHeights.length);
|
|
324
|
+
const freeSpace = Math.max(0, containerContentHeight - naturalHeight);
|
|
325
|
+
if (freeSpace > 0 && rowHeights.length > 0) {
|
|
326
|
+
const extraPerRow = freeSpace / rowHeights.length;
|
|
327
|
+
for (let i = 0; i < rowHeights.length; i++) {
|
|
328
|
+
rowHeights[i] += extraPerRow;
|
|
193
329
|
}
|
|
194
330
|
}
|
|
331
|
+
return rowHeights;
|
|
195
332
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { LayoutNode } from "../../dom/node.js";
|
|
2
2
|
import { Display } from "../../css/enums.js";
|
|
3
3
|
import { resolveLength, isAutoLength } from "../../css/length.js";
|
|
4
|
-
import { containingBlock, horizontalNonContent, horizontalMargin } from "../utils/node-math.js";
|
|
4
|
+
import { adjustForBoxSizing, containingBlock, horizontalNonContent, horizontalMargin } from "../utils/node-math.js";
|
|
5
5
|
/**
|
|
6
6
|
* Image strategy following SOLID principles:
|
|
7
7
|
* - Single Responsibility: Handles image layout and sizing
|
|
@@ -27,21 +27,34 @@ export class ImageStrategy {
|
|
|
27
27
|
* Sets up image sizing based on CSS properties
|
|
28
28
|
*/
|
|
29
29
|
static setupImageSizing(node, _imageInfo) {
|
|
30
|
+
const intrinsicContainerRefs = {
|
|
31
|
+
containerWidth: node.intrinsicInlineSize ?? 0,
|
|
32
|
+
containerHeight: node.intrinsicBlockSize ?? 0,
|
|
33
|
+
};
|
|
30
34
|
// If width is explicitly set, calculate proportional height
|
|
31
35
|
if (node.style.width !== undefined && typeof node.style.width === 'number' && node.style.width > 0) {
|
|
32
|
-
const specifiedWidth = resolveLength(node.style.width, node.intrinsicInlineSize, {
|
|
36
|
+
const specifiedWidth = resolveLength(node.style.width, node.intrinsicInlineSize, {
|
|
37
|
+
auto: "zero",
|
|
38
|
+
...intrinsicContainerRefs,
|
|
39
|
+
});
|
|
33
40
|
const scale = specifiedWidth / node.intrinsicInlineSize;
|
|
34
41
|
node.intrinsicBlockSize = Math.round(node.intrinsicBlockSize * scale);
|
|
35
42
|
}
|
|
36
43
|
// If height is explicitly set, calculate proportional width
|
|
37
44
|
else if (node.style.height !== undefined && typeof node.style.height === 'number' && node.style.height > 0) {
|
|
38
|
-
const specifiedHeight = resolveLength(node.style.height, node.intrinsicBlockSize, {
|
|
45
|
+
const specifiedHeight = resolveLength(node.style.height, node.intrinsicBlockSize, {
|
|
46
|
+
auto: "zero",
|
|
47
|
+
...intrinsicContainerRefs,
|
|
48
|
+
});
|
|
39
49
|
const scale = specifiedHeight / node.intrinsicBlockSize;
|
|
40
50
|
node.intrinsicInlineSize = Math.round(node.intrinsicInlineSize * scale);
|
|
41
51
|
}
|
|
42
52
|
// Handle max-width constraints
|
|
43
53
|
else if (node.style.maxWidth !== undefined && typeof node.style.maxWidth === 'number') {
|
|
44
|
-
const maxWidth = resolveLength(node.style.maxWidth, node.intrinsicInlineSize, {
|
|
54
|
+
const maxWidth = resolveLength(node.style.maxWidth, node.intrinsicInlineSize, {
|
|
55
|
+
auto: "zero",
|
|
56
|
+
...intrinsicContainerRefs,
|
|
57
|
+
});
|
|
45
58
|
if (maxWidth < node.intrinsicInlineSize) {
|
|
46
59
|
const scale = maxWidth / node.intrinsicInlineSize;
|
|
47
60
|
node.intrinsicInlineSize = maxWidth;
|
|
@@ -117,8 +130,20 @@ export function calculateImagePosition(node, containerWidth, containerHeight, im
|
|
|
117
130
|
}
|
|
118
131
|
case 'fill':
|
|
119
132
|
// Use the specified dimensions if available
|
|
120
|
-
width = node.style.width
|
|
121
|
-
|
|
133
|
+
width = node.style.width
|
|
134
|
+
? resolveLength(node.style.width, containerWidth, {
|
|
135
|
+
auto: "zero",
|
|
136
|
+
containerWidth,
|
|
137
|
+
containerHeight,
|
|
138
|
+
})
|
|
139
|
+
: containerWidth;
|
|
140
|
+
height = node.style.height
|
|
141
|
+
? resolveLength(node.style.height, containerHeight, {
|
|
142
|
+
auto: "zero",
|
|
143
|
+
containerWidth,
|
|
144
|
+
containerHeight,
|
|
145
|
+
})
|
|
146
|
+
: containerHeight;
|
|
122
147
|
break;
|
|
123
148
|
case 'none':
|
|
124
149
|
// Use original image size
|
|
@@ -153,38 +178,39 @@ export class ImageLayoutStrategy {
|
|
|
153
178
|
const cb = containingBlock(node, context.env.viewport);
|
|
154
179
|
const widthRef = Math.max(cb.width, 0);
|
|
155
180
|
const heightRef = Math.max(cb.height, 0);
|
|
181
|
+
const containerRefs = { containerWidth: widthRef, containerHeight: heightRef };
|
|
156
182
|
const intrinsicWidth = Math.max(0, node.intrinsicInlineSize ?? 0);
|
|
157
183
|
const intrinsicHeight = Math.max(0, node.intrinsicBlockSize ?? 0);
|
|
158
184
|
const hasIntrinsic = intrinsicWidth > 0 && intrinsicHeight > 0;
|
|
159
|
-
const paddingLeft = resolveLength(node.style.paddingLeft, widthRef, { auto: "zero" });
|
|
160
|
-
const paddingRight = resolveLength(node.style.paddingRight, widthRef, { auto: "zero" });
|
|
161
|
-
const paddingTop = resolveLength(node.style.paddingTop, heightRef, { auto: "zero" });
|
|
162
|
-
const paddingBottom = resolveLength(node.style.paddingBottom, heightRef, { auto: "zero" });
|
|
163
|
-
const borderLeft = resolveLength(node.style.borderLeft, widthRef, { auto: "zero" });
|
|
164
|
-
const borderRight = resolveLength(node.style.borderRight, widthRef, { auto: "zero" });
|
|
165
|
-
const borderTop = resolveLength(node.style.borderTop, heightRef, { auto: "zero" });
|
|
166
|
-
const borderBottom = resolveLength(node.style.borderBottom, heightRef, { auto: "zero" });
|
|
167
|
-
const marginLeft = resolveLength(node.style.marginLeft, widthRef, { auto: "zero" });
|
|
168
|
-
const marginRight = resolveLength(node.style.marginRight, widthRef, { auto: "zero" });
|
|
169
|
-
const marginTop = resolveLength(node.style.marginTop, heightRef, { auto: "zero" });
|
|
170
|
-
const marginBottom = resolveLength(node.style.marginBottom, heightRef, { auto: "zero" });
|
|
185
|
+
const paddingLeft = resolveLength(node.style.paddingLeft, widthRef, { auto: "zero", ...containerRefs });
|
|
186
|
+
const paddingRight = resolveLength(node.style.paddingRight, widthRef, { auto: "zero", ...containerRefs });
|
|
187
|
+
const paddingTop = resolveLength(node.style.paddingTop, heightRef, { auto: "zero", ...containerRefs });
|
|
188
|
+
const paddingBottom = resolveLength(node.style.paddingBottom, heightRef, { auto: "zero", ...containerRefs });
|
|
189
|
+
const borderLeft = resolveLength(node.style.borderLeft, widthRef, { auto: "zero", ...containerRefs });
|
|
190
|
+
const borderRight = resolveLength(node.style.borderRight, widthRef, { auto: "zero", ...containerRefs });
|
|
191
|
+
const borderTop = resolveLength(node.style.borderTop, heightRef, { auto: "zero", ...containerRefs });
|
|
192
|
+
const borderBottom = resolveLength(node.style.borderBottom, heightRef, { auto: "zero", ...containerRefs });
|
|
193
|
+
const marginLeft = resolveLength(node.style.marginLeft, widthRef, { auto: "zero", ...containerRefs });
|
|
194
|
+
const marginRight = resolveLength(node.style.marginRight, widthRef, { auto: "zero", ...containerRefs });
|
|
195
|
+
const marginTop = resolveLength(node.style.marginTop, heightRef, { auto: "zero", ...containerRefs });
|
|
196
|
+
const marginBottom = resolveLength(node.style.marginBottom, heightRef, { auto: "zero", ...containerRefs });
|
|
171
197
|
const horizontalExtras = paddingLeft + paddingRight + borderLeft + borderRight;
|
|
172
198
|
const verticalExtras = paddingTop + paddingBottom + borderTop + borderBottom;
|
|
173
|
-
const availableContentWidth = Math.max(0, widthRef - horizontalNonContent(node, widthRef) - horizontalMargin(node, widthRef));
|
|
199
|
+
const availableContentWidth = Math.max(0, widthRef - horizontalNonContent(node, widthRef, heightRef) - horizontalMargin(node, widthRef, heightRef));
|
|
174
200
|
const hasExplicitWidth = node.style.width !== "auto" && node.style.width !== undefined;
|
|
175
201
|
const hasExplicitHeight = node.style.height !== "auto" && node.style.height !== undefined;
|
|
176
202
|
let contentWidth = hasIntrinsic ? intrinsicWidth : availableContentWidth;
|
|
177
203
|
let contentHeight = hasIntrinsic ? intrinsicHeight : 0;
|
|
178
204
|
if (hasExplicitWidth) {
|
|
179
|
-
const resolved = resolveLength(node.style.width, widthRef, { auto: "reference" });
|
|
205
|
+
const resolved = resolveLength(node.style.width, widthRef, { auto: "reference", ...containerRefs });
|
|
180
206
|
if (Number.isFinite(resolved) && resolved > 0) {
|
|
181
|
-
contentWidth = resolved;
|
|
207
|
+
contentWidth = adjustForBoxSizing(resolved, node.style.boxSizing, horizontalExtras);
|
|
182
208
|
}
|
|
183
209
|
}
|
|
184
210
|
if (hasExplicitHeight) {
|
|
185
|
-
const resolved = resolveLength(node.style.height, heightRef, { auto: "reference" });
|
|
211
|
+
const resolved = resolveLength(node.style.height, heightRef, { auto: "reference", ...containerRefs });
|
|
186
212
|
if (Number.isFinite(resolved) && resolved > 0) {
|
|
187
|
-
contentHeight = resolved;
|
|
213
|
+
contentHeight = adjustForBoxSizing(resolved, node.style.boxSizing, verticalExtras);
|
|
188
214
|
}
|
|
189
215
|
}
|
|
190
216
|
if (hasIntrinsic) {
|
|
@@ -215,7 +241,7 @@ export class ImageLayoutStrategy {
|
|
|
215
241
|
const lockAspectToWidth = hasIntrinsic && !hasExplicitHeight;
|
|
216
242
|
const lockAspectToHeight = hasIntrinsic && !hasExplicitWidth;
|
|
217
243
|
if (node.style.maxWidth !== undefined && !isAutoLength(node.style.maxWidth)) {
|
|
218
|
-
const maxWidth = resolveLength(node.style.maxWidth, widthRef, { auto: "reference" });
|
|
244
|
+
const maxWidth = adjustForBoxSizing(resolveLength(node.style.maxWidth, widthRef, { auto: "reference", ...containerRefs }), node.style.boxSizing, horizontalExtras);
|
|
219
245
|
if (Number.isFinite(maxWidth) && maxWidth > 0 && contentWidth > maxWidth) {
|
|
220
246
|
if (lockAspectToWidth && contentWidth > 0) {
|
|
221
247
|
const scale = maxWidth / contentWidth;
|
|
@@ -225,7 +251,7 @@ export class ImageLayoutStrategy {
|
|
|
225
251
|
}
|
|
226
252
|
}
|
|
227
253
|
if (node.style.minWidth !== undefined && !isAutoLength(node.style.minWidth)) {
|
|
228
|
-
const minWidth = resolveLength(node.style.minWidth, widthRef, { auto: "zero" });
|
|
254
|
+
const minWidth = adjustForBoxSizing(resolveLength(node.style.minWidth, widthRef, { auto: "zero", ...containerRefs }), node.style.boxSizing, horizontalExtras);
|
|
229
255
|
if (Number.isFinite(minWidth) && minWidth > 0 && contentWidth < minWidth) {
|
|
230
256
|
if (lockAspectToWidth && contentWidth > 0) {
|
|
231
257
|
const scale = minWidth / contentWidth;
|
|
@@ -235,7 +261,7 @@ export class ImageLayoutStrategy {
|
|
|
235
261
|
}
|
|
236
262
|
}
|
|
237
263
|
if (node.style.maxHeight !== undefined && !isAutoLength(node.style.maxHeight)) {
|
|
238
|
-
const maxHeight = resolveLength(node.style.maxHeight, heightRef, { auto: "reference" });
|
|
264
|
+
const maxHeight = adjustForBoxSizing(resolveLength(node.style.maxHeight, heightRef, { auto: "reference", ...containerRefs }), node.style.boxSizing, verticalExtras);
|
|
239
265
|
if (Number.isFinite(maxHeight) && maxHeight > 0 && contentHeight > maxHeight) {
|
|
240
266
|
if (lockAspectToHeight && contentHeight > 0) {
|
|
241
267
|
const scale = maxHeight / contentHeight;
|
|
@@ -245,7 +271,7 @@ export class ImageLayoutStrategy {
|
|
|
245
271
|
}
|
|
246
272
|
}
|
|
247
273
|
if (node.style.minHeight !== undefined && !isAutoLength(node.style.minHeight)) {
|
|
248
|
-
const minHeight = resolveLength(node.style.minHeight, heightRef, { auto: "zero" });
|
|
274
|
+
const minHeight = adjustForBoxSizing(resolveLength(node.style.minHeight, heightRef, { auto: "zero", ...containerRefs }), node.style.boxSizing, verticalExtras);
|
|
249
275
|
if (Number.isFinite(minHeight) && minHeight > 0 && contentHeight < minHeight) {
|
|
250
276
|
if (lockAspectToHeight && contentHeight > 0) {
|
|
251
277
|
const scale = minHeight / contentHeight;
|
|
@@ -4,24 +4,28 @@ import { resolveLength } from "../../css/length.js";
|
|
|
4
4
|
import { resolvedLineHeight } from "../../css/style.js";
|
|
5
5
|
import { FloatContext } from "../context/float-context.js";
|
|
6
6
|
import { defaultInlineFormatter } from "../utils/inline-formatter.js";
|
|
7
|
+
import { containingBlock } from "../utils/node-math.js";
|
|
7
8
|
export class InlineLayoutStrategy {
|
|
8
9
|
canLayout(node) {
|
|
9
10
|
return node.style.display === Display.Inline;
|
|
10
11
|
}
|
|
11
12
|
layout(node, context) {
|
|
12
|
-
const
|
|
13
|
-
const
|
|
14
|
-
const
|
|
15
|
-
const
|
|
16
|
-
const
|
|
17
|
-
const
|
|
18
|
-
const
|
|
19
|
-
const
|
|
20
|
-
const
|
|
21
|
-
const
|
|
22
|
-
const
|
|
23
|
-
const
|
|
24
|
-
const
|
|
13
|
+
const cb = containingBlock(node, context.env.viewport);
|
|
14
|
+
const refWidth = Math.max(cb.width || context.env.viewport.width, 0);
|
|
15
|
+
const refHeight = Math.max(cb.height || context.env.viewport.height, 0);
|
|
16
|
+
const containerRefs = { containerWidth: refWidth, containerHeight: refHeight };
|
|
17
|
+
const paddingLeft = resolveLength(node.style.paddingLeft, refWidth, { auto: "zero", ...containerRefs });
|
|
18
|
+
const paddingRight = resolveLength(node.style.paddingRight, refWidth, { auto: "zero", ...containerRefs });
|
|
19
|
+
const paddingTop = resolveLength(node.style.paddingTop, refHeight, { auto: "zero", ...containerRefs });
|
|
20
|
+
const paddingBottom = resolveLength(node.style.paddingBottom, refHeight, { auto: "zero", ...containerRefs });
|
|
21
|
+
const borderLeft = resolveLength(node.style.borderLeft, refWidth, { auto: "zero", ...containerRefs });
|
|
22
|
+
const borderRight = resolveLength(node.style.borderRight, refWidth, { auto: "zero", ...containerRefs });
|
|
23
|
+
const borderTop = resolveLength(node.style.borderTop, refHeight, { auto: "zero", ...containerRefs });
|
|
24
|
+
const borderBottom = resolveLength(node.style.borderBottom, refHeight, { auto: "zero", ...containerRefs });
|
|
25
|
+
const marginLeft = resolveLength(node.style.marginLeft, refWidth, { auto: "zero", ...containerRefs });
|
|
26
|
+
const marginRight = resolveLength(node.style.marginRight, refWidth, { auto: "zero", ...containerRefs });
|
|
27
|
+
const marginTop = resolveLength(node.style.marginTop, refHeight, { auto: "zero", ...containerRefs });
|
|
28
|
+
const marginBottom = resolveLength(node.style.marginBottom, refHeight, { auto: "zero", ...containerRefs });
|
|
25
29
|
const horizontalExtras = paddingLeft + paddingRight + borderLeft + borderRight;
|
|
26
30
|
const verticalExtras = paddingTop + paddingBottom + borderTop + borderBottom;
|
|
27
31
|
const inlineNodes = collectInlineParticipants(node);
|
|
@@ -37,7 +41,7 @@ export class InlineLayoutStrategy {
|
|
|
37
41
|
contentWidth: availableWidth,
|
|
38
42
|
startY,
|
|
39
43
|
});
|
|
40
|
-
const extent = measureInlineExtent(inlineNodes, refWidth, node.box.x + borderLeft + paddingLeft);
|
|
44
|
+
const extent = measureInlineExtent(inlineNodes, refWidth, refHeight, node.box.x + borderLeft + paddingLeft);
|
|
41
45
|
const floatBottom = Math.max(floatContext.bottom("left"), floatContext.bottom("right"));
|
|
42
46
|
const measuredHeight = Math.max(result.newCursorY, floatBottom) - startY;
|
|
43
47
|
node.box.contentWidth = Math.max(0, extent);
|
|
@@ -81,19 +85,20 @@ function isInlineDisplay(display) {
|
|
|
81
85
|
return false;
|
|
82
86
|
}
|
|
83
87
|
}
|
|
84
|
-
function measureInlineExtent(inlineNodes, referenceWidth, contentStartX) {
|
|
88
|
+
function measureInlineExtent(inlineNodes, referenceWidth, containerHeight, contentStartX) {
|
|
85
89
|
if (inlineNodes.length === 0) {
|
|
86
90
|
return 0;
|
|
87
91
|
}
|
|
92
|
+
const containerRefs = { containerWidth: referenceWidth, containerHeight };
|
|
88
93
|
let minStart = Number.POSITIVE_INFINITY;
|
|
89
94
|
let maxEnd = Number.NEGATIVE_INFINITY;
|
|
90
95
|
for (const node of inlineNodes) {
|
|
91
|
-
const marginLeft = resolveLength(node.style.marginLeft, referenceWidth, { auto: "zero" });
|
|
92
|
-
const marginRight = resolveLength(node.style.marginRight, referenceWidth, { auto: "zero" });
|
|
93
|
-
const paddingLeft = resolveLength(node.style.paddingLeft, referenceWidth, { auto: "zero" });
|
|
94
|
-
const paddingRight = resolveLength(node.style.paddingRight, referenceWidth, { auto: "zero" });
|
|
95
|
-
const borderLeft = resolveLength(node.style.borderLeft, referenceWidth, { auto: "zero" });
|
|
96
|
-
const borderRight = resolveLength(node.style.borderRight, referenceWidth, { auto: "zero" });
|
|
96
|
+
const marginLeft = resolveLength(node.style.marginLeft, referenceWidth, { auto: "zero", ...containerRefs });
|
|
97
|
+
const marginRight = resolveLength(node.style.marginRight, referenceWidth, { auto: "zero", ...containerRefs });
|
|
98
|
+
const paddingLeft = resolveLength(node.style.paddingLeft, referenceWidth, { auto: "zero", ...containerRefs });
|
|
99
|
+
const paddingRight = resolveLength(node.style.paddingRight, referenceWidth, { auto: "zero", ...containerRefs });
|
|
100
|
+
const borderLeft = resolveLength(node.style.borderLeft, referenceWidth, { auto: "zero", ...containerRefs });
|
|
101
|
+
const borderRight = resolveLength(node.style.borderRight, referenceWidth, { auto: "zero", ...containerRefs });
|
|
97
102
|
const marginStart = node.box.x - paddingLeft - borderLeft - marginLeft;
|
|
98
103
|
const width = node.box.contentWidth +
|
|
99
104
|
paddingLeft +
|
|
@@ -2,7 +2,7 @@ import { BorderModel, Display } from "../../css/enums.js";
|
|
|
2
2
|
import { LayoutNode } from "../../dom/node.js";
|
|
3
3
|
import { log } from "../../logging/debug.js";
|
|
4
4
|
import { resolveLength } from "../../css/length.js";
|
|
5
|
-
import { containingBlock, horizontalNonContent, resolveWidthBlock, verticalNonContent } from "../utils/node-math.js";
|
|
5
|
+
import { adjustForBoxSizing, containingBlock, horizontalNonContent, resolveWidthBlock, verticalNonContent } from "../utils/node-math.js";
|
|
6
6
|
import { layoutTableCell } from "../table/cell_layout.js";
|
|
7
7
|
import { auditTableCell, debugTableCell } from "../table/diagnostics.js";
|
|
8
8
|
export class TableLayoutStrategy {
|
|
@@ -19,7 +19,8 @@ export class TableLayoutStrategy {
|
|
|
19
19
|
children: node.children.length
|
|
20
20
|
});
|
|
21
21
|
const cb = containingBlock(node, context.env.viewport);
|
|
22
|
-
|
|
22
|
+
const containerRefs = { containerWidth: cb.width, containerHeight: cb.height };
|
|
23
|
+
node.box.contentWidth = resolveWidthBlock(node, cb.width, cb.height);
|
|
23
24
|
log("layout", "debug", "Table layout start", {
|
|
24
25
|
table: node.tagName,
|
|
25
26
|
availableWidth: cb.width,
|
|
@@ -109,7 +110,7 @@ export class TableLayoutStrategy {
|
|
|
109
110
|
}
|
|
110
111
|
}
|
|
111
112
|
if (collapsedBorders) {
|
|
112
|
-
const numericBorder = (value) => resolveLength(value, node.box.contentWidth, { auto: "zero" });
|
|
113
|
+
const numericBorder = (value) => resolveLength(value, node.box.contentWidth, { auto: "zero", ...containerRefs });
|
|
113
114
|
// For collapsed borders, we need to:
|
|
114
115
|
// 1. Collapse borders between adjacent cells (winner takes the shared border)
|
|
115
116
|
// 2. Collapse outer cell borders with table border
|
|
@@ -236,7 +237,7 @@ export class TableLayoutStrategy {
|
|
|
236
237
|
const colSpan = Math.min(this.cellColSpan(cell), numCols - c);
|
|
237
238
|
const rowSpan = Math.min(this.cellRowSpan(cell), numRows - r);
|
|
238
239
|
const spannedWidth = this.sumColumns(colWidths, c, colSpan);
|
|
239
|
-
const boxMetrics = this.resolveCellBoxMetrics(cell, spannedWidth);
|
|
240
|
+
const boxMetrics = this.resolveCellBoxMetrics(cell, spannedWidth, cb.height);
|
|
240
241
|
const cellAvailableWidth = spannedWidth - boxMetrics.borderLeft - boxMetrics.borderRight - boxMetrics.paddingLeft - boxMetrics.paddingRight;
|
|
241
242
|
cell.box.x = 0;
|
|
242
243
|
cell.box.y = 0;
|
|
@@ -294,7 +295,7 @@ export class TableLayoutStrategy {
|
|
|
294
295
|
const rowSpan = Math.min(this.cellRowSpan(cell), numRows - r);
|
|
295
296
|
const spanWidth = colOffsets[c + colSpan] - colOffsets[c];
|
|
296
297
|
const spanHeight = rowOffsets[r + rowSpan] - rowOffsets[r];
|
|
297
|
-
const boxMetrics = this.resolveCellBoxMetrics(cell, spanWidth);
|
|
298
|
+
const boxMetrics = this.resolveCellBoxMetrics(cell, spanWidth, cb.height);
|
|
298
299
|
const availableContentHeight = spanHeight - boxMetrics.borderTop - boxMetrics.borderBottom - boxMetrics.paddingTop - boxMetrics.paddingBottom;
|
|
299
300
|
const alignOffsetY = this.computeVerticalAlignOffset(cell.style.verticalAlign, availableContentHeight, cell.box.contentHeight);
|
|
300
301
|
// Position the cell's border box at the column/row offset
|
|
@@ -347,9 +348,14 @@ export class TableLayoutStrategy {
|
|
|
347
348
|
rowNode.box.borderBoxHeight = rowHeights[r];
|
|
348
349
|
}
|
|
349
350
|
}
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
node.
|
|
351
|
+
let resolvedContentHeight = rowOffsets[numRows];
|
|
352
|
+
const verticalExtras = verticalNonContent(node, cb.height, cb.width);
|
|
353
|
+
if (node.style.height !== "auto" && node.style.height !== undefined) {
|
|
354
|
+
resolvedContentHeight = adjustForBoxSizing(resolveLength(node.style.height, cb.height, { auto: "zero", ...containerRefs }), node.style.boxSizing, verticalExtras);
|
|
355
|
+
}
|
|
356
|
+
node.box.contentHeight = Math.max(0, resolvedContentHeight);
|
|
357
|
+
node.box.borderBoxWidth = node.box.contentWidth + horizontalNonContent(node, cb.width, cb.height);
|
|
358
|
+
node.box.borderBoxHeight = node.box.contentHeight + verticalExtras;
|
|
353
359
|
node.box.scrollWidth = node.box.contentWidth;
|
|
354
360
|
node.box.scrollHeight = node.box.contentHeight;
|
|
355
361
|
}
|
|
@@ -514,17 +520,19 @@ export class TableLayoutStrategy {
|
|
|
514
520
|
}
|
|
515
521
|
return offsets;
|
|
516
522
|
}
|
|
517
|
-
resolveCellBoxMetrics(cell, referenceWidth) {
|
|
518
|
-
const
|
|
523
|
+
resolveCellBoxMetrics(cell, referenceWidth, referenceHeight = referenceWidth) {
|
|
524
|
+
const containerRefs = { containerWidth: referenceWidth, containerHeight: referenceHeight };
|
|
525
|
+
const resolveHorizontal = (value) => resolveLength(value, referenceWidth, { auto: "zero", ...containerRefs });
|
|
526
|
+
const resolveVertical = (value) => resolveLength(value, referenceHeight, { auto: "zero", ...containerRefs });
|
|
519
527
|
return {
|
|
520
|
-
borderLeft:
|
|
521
|
-
borderRight:
|
|
522
|
-
borderTop:
|
|
523
|
-
borderBottom:
|
|
524
|
-
paddingLeft:
|
|
525
|
-
paddingRight:
|
|
526
|
-
paddingTop:
|
|
527
|
-
paddingBottom:
|
|
528
|
+
borderLeft: resolveHorizontal(cell.style.borderLeft),
|
|
529
|
+
borderRight: resolveHorizontal(cell.style.borderRight),
|
|
530
|
+
borderTop: resolveVertical(cell.style.borderTop),
|
|
531
|
+
borderBottom: resolveVertical(cell.style.borderBottom),
|
|
532
|
+
paddingLeft: resolveHorizontal(cell.style.paddingLeft),
|
|
533
|
+
paddingRight: resolveHorizontal(cell.style.paddingRight),
|
|
534
|
+
paddingTop: resolveVertical(cell.style.paddingTop),
|
|
535
|
+
paddingBottom: resolveVertical(cell.style.paddingBottom),
|
|
528
536
|
};
|
|
529
537
|
}
|
|
530
538
|
computeVerticalAlignOffset(verticalAlign, available, content) {
|
|
@@ -25,7 +25,7 @@ export declare class ContentMeasurer {
|
|
|
25
25
|
* @param contentStartX - The X coordinate where content area begins
|
|
26
26
|
* @returns Object containing the measured width and any left offset
|
|
27
27
|
*/
|
|
28
|
-
measureInFlowWidth(node: LayoutNode, referenceWidth: number, contentStartX: number): {
|
|
28
|
+
measureInFlowWidth(node: LayoutNode, referenceWidth: number, contentStartX: number, containerHeight?: number): {
|
|
29
29
|
width: number;
|
|
30
30
|
leftOffset: number;
|
|
31
31
|
};
|