pagyra-js 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.json +30 -0
- package/CHANGELOG.md +13 -0
- package/README.md +275 -0
- package/UA_Styles_Chromium.md +93 -0
- package/_ext/woff2_conversion/brotli-decode.d.ts +139 -0
- package/_ext/woff2_conversion/brotli-encode.d.ts +129 -0
- package/_ext/woff2_conversion/brotli-port.d.ts +12 -0
- package/_ext/woff2_conversion/brotli-shared-dictionary.d.ts +25 -0
- package/_ext/woff2_conversion/brotli-types.d.ts +15 -0
- package/_ext/woff2_conversion/woff2-common.d.ts +37 -0
- package/_ext/woff2_conversion/woff2-decode.d.ts +32 -0
- package/_ext/woff2_conversion/woff2-encode.d.ts +31 -0
- package/_ext/woff2_conversion/woff2-output.d.ts +39 -0
- package/_ext/woff2_original_cpp/brotli/brotli.c +1559 -0
- package/_ext/woff2_original_cpp/brotli/brotli.md +116 -0
- package/_ext/woff2_original_cpp/brotli/decode.h +409 -0
- package/_ext/woff2_original_cpp/brotli/encode.h +505 -0
- package/_ext/woff2_original_cpp/brotli/port.h +302 -0
- package/_ext/woff2_original_cpp/brotli/shared_dictionary.h +100 -0
- package/_ext/woff2_original_cpp/brotli/types.h +83 -0
- package/_ext/woff2_original_cpp/cmake/FindBrotliDec.cmake +35 -0
- package/_ext/woff2_original_cpp/cmake/FindBrotliEnc.cmake +35 -0
- package/_ext/woff2_original_cpp/include/woff2/decode.h +36 -0
- package/_ext/woff2_original_cpp/include/woff2/encode.h +43 -0
- package/_ext/woff2_original_cpp/include/woff2/output.h +86 -0
- package/_ext/woff2_original_cpp/src/buffer.h +164 -0
- package/_ext/woff2_original_cpp/src/convert_woff2ttf_fuzzer.cc +13 -0
- package/_ext/woff2_original_cpp/src/convert_woff2ttf_fuzzer_new_entry.cc +12 -0
- package/_ext/woff2_original_cpp/src/file.h +30 -0
- package/_ext/woff2_original_cpp/src/font.cc +400 -0
- package/_ext/woff2_original_cpp/src/font.h +105 -0
- package/_ext/woff2_original_cpp/src/glyph.cc +383 -0
- package/_ext/woff2_original_cpp/src/glyph.h +71 -0
- package/_ext/woff2_original_cpp/src/normalize.cc +314 -0
- package/_ext/woff2_original_cpp/src/normalize.h +39 -0
- package/_ext/woff2_original_cpp/src/port.h +66 -0
- package/_ext/woff2_original_cpp/src/round.h +27 -0
- package/_ext/woff2_original_cpp/src/store_bytes.h +55 -0
- package/_ext/woff2_original_cpp/src/table_tags.cc +82 -0
- package/_ext/woff2_original_cpp/src/table_tags.h +30 -0
- package/_ext/woff2_original_cpp/src/transform.cc +430 -0
- package/_ext/woff2_original_cpp/src/transform.h +26 -0
- package/_ext/woff2_original_cpp/src/variable_length.cc +129 -0
- package/_ext/woff2_original_cpp/src/variable_length.h +30 -0
- package/_ext/woff2_original_cpp/src/woff2_common.cc +50 -0
- package/_ext/woff2_original_cpp/src/woff2_common.h +64 -0
- package/_ext/woff2_original_cpp/src/woff2_compress.cc +43 -0
- package/_ext/woff2_original_cpp/src/woff2_dec.cc +1398 -0
- package/_ext/woff2_original_cpp/src/woff2_decompress.cc +41 -0
- package/_ext/woff2_original_cpp/src/woff2_enc.cc +458 -0
- package/_ext/woff2_original_cpp/src/woff2_info.cc +142 -0
- package/_ext/woff2_original_cpp/src/woff2_out.cc +63 -0
- package/assets/fonts/ttf/arimo/Arimo-Bold.ttf +0 -0
- package/assets/fonts/ttf/arimo/Arimo-BoldItalic.ttf +0 -0
- package/assets/fonts/ttf/arimo/Arimo-Italic.ttf +0 -0
- package/assets/fonts/ttf/arimo/Arimo-Regular.ttf +0 -0
- package/assets/fonts/ttf/cinzeldecorative/CinzelDecorative-Black.ttf +0 -0
- package/assets/fonts/ttf/cinzeldecorative/CinzelDecorative-Bold.ttf +0 -0
- package/assets/fonts/ttf/cinzeldecorative/CinzelDecorative-Regular.ttf +0 -0
- package/assets/fonts/ttf/dejavu/DejaVuSans.ttf +0 -0
- package/assets/fonts/ttf/firecode/FiraCode-Bold.ttf +0 -0
- package/assets/fonts/ttf/firecode/FiraCode-Light.ttf +0 -0
- package/assets/fonts/ttf/firecode/FiraCode-Medium.ttf +0 -0
- package/assets/fonts/ttf/firecode/FiraCode-Regular.ttf +0 -0
- package/assets/fonts/ttf/firecode/FiraCode-SemiBold.ttf +0 -0
- package/assets/fonts/ttf/notoemoji/NotoEmoji-Bold.ttf +0 -0
- package/assets/fonts/ttf/notoemoji/NotoEmoji-Light.ttf +0 -0
- package/assets/fonts/ttf/notoemoji/NotoEmoji-Medium.ttf +0 -0
- package/assets/fonts/ttf/notoemoji/NotoEmoji-Regular.ttf +0 -0
- package/assets/fonts/ttf/notoemoji/NotoEmoji-SemiBold.ttf +0 -0
- package/assets/fonts/ttf/notosans/NotoSans-Regular.ttf +0 -0
- package/assets/fonts/ttf/roboto/Roboto-Bold.ttf +0 -0
- package/assets/fonts/ttf/roboto/Roboto-BoldItalic.ttf +0 -0
- package/assets/fonts/ttf/roboto/Roboto-Italic.ttf +0 -0
- package/assets/fonts/ttf/roboto/Roboto-Regular.ttf +0 -0
- package/assets/fonts/ttf/stixtwomath/STIXTwoMath-Regular.ttf +0 -0
- package/assets/fonts/ttf/tinos/Tinos-Bold.ttf +0 -0
- package/assets/fonts/ttf/tinos/Tinos-BoldItalic.ttf +0 -0
- package/assets/fonts/ttf/tinos/Tinos-Italic.ttf +0 -0
- package/assets/fonts/ttf/tinos/Tinos-Regular.ttf +0 -0
- package/assets/fonts/woff/lato/lato-latin-400-italic.woff +0 -0
- package/assets/fonts/woff/lato/lato-latin-400-normal.woff +0 -0
- package/assets/fonts/woff/lato/lato-latin-700-italic.woff +0 -0
- package/assets/fonts/woff/lato/lato-latin-700-normal.woff +0 -0
- package/assets/fonts/woff2/caveat/Caveat-Bold.woff2 +0 -0
- package/assets/fonts/woff2/caveat/Caveat-Regular.woff2 +0 -0
- package/assets/fonts/woff2/lato/lato-latin-400-italic.woff2 +0 -0
- package/assets/fonts/woff2/lato/lato-latin-400-normal.woff2 +0 -0
- package/assets/fonts/woff2/lato/lato-latin-700-italic.woff2 +0 -0
- package/assets/fonts/woff2/lato/lato-latin-700-normal.woff2 +0 -0
- package/docs/AGENTS.md +288 -0
- package/docs/BACKGROUND-REPEAT-IMPLEMENTATION.md +127 -0
- package/docs/BACKGROUND-REPEAT-REFERENCE.md +127 -0
- package/docs/BACKGROUND-REPEAT-SPACE-ROUND.md +164 -0
- package/docs/css-properties-support.md +256 -0
- package/docs/src_modules_table.md +172 -0
- package/docs/text-overlap-fix.md +85 -0
- package/docs/text-overlap-investigation.md +27 -0
- package/eslint.config.js +36 -0
- package/glyph_measure.htm +1458 -0
- package/package.json +50 -0
- package/playground/browser-entry.ts +2 -0
- package/playground/exports/background-text-debug.pdf +0 -0
- package/playground/public/app.js +875 -0
- package/playground/public/assets/1.webp +0 -0
- package/playground/public/examples/accents-test.html +24 -0
- package/playground/public/examples/advanced-selectors-demo.html +118 -0
- package/playground/public/examples/background-advanced-showcase.html +82 -0
- package/playground/public/examples/background-clip-text.html +36 -0
- package/playground/public/examples/background-origin-showcase.html +137 -0
- package/playground/public/examples/background-position-showcase.html +83 -0
- package/playground/public/examples/background-repeat-showcase.html +83 -0
- package/playground/public/examples/background-repeat-space-round.html +348 -0
- package/playground/public/examples/background-size-showcase.html +82 -0
- package/playground/public/examples/background-text-debug.html +18 -0
- package/playground/public/examples/baseline-test.html +24 -0
- package/playground/public/examples/bold-showcase.html +150 -0
- package/playground/public/examples/bold-strike-example.html +12 -0
- package/playground/public/examples/border-collapse-test.html +23 -0
- package/playground/public/examples/centered-shadow-div.html +72 -0
- package/playground/public/examples/css-variables.html +50 -0
- package/playground/public/examples/debug-accents.html +11 -0
- package/playground/public/examples/debug-text-overlap.html +46 -0
- package/playground/public/examples/flex-gap-column.html +130 -0
- package/playground/public/examples/flex-gap-row.html +137 -0
- package/playground/public/examples/flex-padding-test.html +29 -0
- package/playground/public/examples/flexbox-text-test.html +193 -0
- package/playground/public/examples/fonts-demo.html +126 -0
- package/playground/public/examples/footer-example.html +4 -0
- package/playground/public/examples/gradient-text.html +54 -0
- package/playground/public/examples/grid-gap-demo.html +156 -0
- package/playground/public/examples/header-example.html +4 -0
- package/playground/public/examples/header-footer-example.html +27 -0
- package/playground/public/examples/image-showcase.html +33 -0
- package/playground/public/examples/justify-text.html +22 -0
- package/playground/public/examples/linear-gradient-example.html +38 -0
- package/playground/public/examples/lorem-span.html +14 -0
- package/playground/public/examples/margin-block-showcase.html +21 -0
- package/playground/public/examples/margin-inline-showcase.html +21 -0
- package/playground/public/examples/monthly-summary.html +95 -0
- package/playground/public/examples/multi-page-lorem.html +190 -0
- package/playground/public/examples/opacity-debug.html +39 -0
- package/playground/public/examples/opacity-example.html +70 -0
- package/playground/public/examples/png-image-example.html +13 -0
- package/playground/public/examples/red-rectangle.html +18 -0
- package/playground/public/examples/repro.html +24 -0
- package/playground/public/examples/rounded-borders-test.html +24 -0
- package/playground/public/examples/simple-list.html +89 -0
- package/playground/public/examples/simple-svg.html +37 -0
- package/playground/public/examples/simple-table.html +52 -0
- package/playground/public/examples/skew-div.html +138 -0
- package/playground/public/examples/skew-text.html +21 -0
- package/playground/public/examples/starter-report.css +51 -0
- package/playground/public/examples/starter-report.html +23 -0
- package/playground/public/examples/svg-aspect-ratio-showcase.html +116 -0
- package/playground/public/examples/svg-gradients-linear.html +28 -0
- package/playground/public/examples/svg-gradients-radial.html +29 -0
- package/playground/public/examples/svg-gradients-showcase.html +66 -0
- package/playground/public/examples/svg-image-path-test.html +43 -0
- package/playground/public/examples/svg-images-clipping.html +27 -0
- package/playground/public/examples/svg-path-gallery.html +118 -0
- package/playground/public/examples/svg-radial-transform-demo.html +78 -0
- package/playground/public/examples/svg-transform-stack.html +103 -0
- package/playground/public/examples/svg-transforms-demo.html +127 -0
- package/playground/public/examples/table-merge-test.html +34 -0
- package/playground/public/examples/text-decoration-showcase.html +138 -0
- package/playground/public/examples/text-indent-showcase.html +137 -0
- package/playground/public/examples/text-shadow-example.html +29 -0
- package/playground/public/examples/very-complex-css.html +293 -0
- package/playground/public/examples/webp-example.html +13 -0
- package/playground/public/examples/z-index-demo.html +93 -0
- package/playground/public/examples.json +240 -0
- package/playground/public/images/dice.png +0 -0
- package/playground/public/images/duck.jpg +0 -0
- package/playground/public/index.html +149 -0
- package/playground/public/mode.js +1 -0
- package/playground/public/styles.css +382 -0
- package/playground/public/tmp-h2-debug.html +33 -0
- package/playground/public/tmp-italic-debug.html +32 -0
- package/playground/public/vendor/codemirror/codemirror.min.css +1 -0
- package/playground/public/vendor/codemirror/codemirror.min.js +1 -0
- package/playground/public/vendor/codemirror/css.min.js +1 -0
- package/playground/public/vendor/codemirror/darcula.min.css +1 -0
- package/playground/public/vendor/codemirror/htmlmixed.min.js +1 -0
- package/playground/public/vendor/codemirror/javascript.min.js +1 -0
- package/playground/public/vendor/codemirror/xml.min.js +1 -0
- package/playground/public/vendor/pagyra-playground-browser.js +165966 -0
- package/playground/public/vendor/pagyra-playground-browser.js.map +7 -0
- package/playground/server.d.ts +1 -0
- package/playground/server.js +68 -0
- package/playground/server.ts +128 -0
- package/scripts/browser-build.ts +101 -0
- package/scripts/build-browser-bundle.ts +52 -0
- package/scripts/glyph-comparison/simulate.ts +744 -0
- package/scripts/playground-browser-server.ts +57 -0
- package/scripts/probe-roboto.ts +6 -0
- package/scripts/render-playground-example.ts +121 -0
- package/scripts/run-glyph-atlas-tuner-runner.mjs +113 -0
- package/scripts/run-glyph-atlas-tuner.ts +141 -0
- package/scripts/top-ts-files.ps1 +39 -0
- package/scripts/top-ts-files.sh +37 -0
- package/scripts/woff2_info.ps1 +132 -0
- package/src/browser-entry.ts +14 -0
- package/src/compression/adler32.ts +45 -0
- package/src/compression/brotli/brotli.ts +463 -0
- package/src/compression/brotli/index.ts +15 -0
- package/src/compression/brotli/transform.ts +184 -0
- package/src/compression/brotli/types.ts +58 -0
- package/src/compression/brotli/utils.ts +157 -0
- package/src/compression/brotli/vendor/bit_reader.js +124 -0
- package/src/compression/brotli/vendor/context.js +250 -0
- package/src/compression/brotli/vendor/decode.d.ts +2 -0
- package/src/compression/brotli/vendor/decode.js +938 -0
- package/src/compression/brotli/vendor/dictionary-data.js +9469 -0
- package/src/compression/brotli/vendor/dictionary.js +36 -0
- package/src/compression/brotli/vendor/huffman.js +123 -0
- package/src/compression/brotli/vendor/package.json +3 -0
- package/src/compression/brotli/vendor/prefix.js +60 -0
- package/src/compression/brotli/vendor/streams.js +31 -0
- package/src/compression/brotli/vendor/transform.js +247 -0
- package/src/compression/brotli/vendor-decode.d.ts +4 -0
- package/src/compression/brotli/woff2-glyf-transform.ts +623 -0
- package/src/compression/decompress.ts +16 -0
- package/src/compression/deflate.ts +295 -0
- package/src/compression/index.ts +4 -0
- package/src/compression/types.ts +26 -0
- package/src/compression/utils.ts +107 -0
- package/src/core.ts +18 -0
- package/src/css/apply-declarations.ts +86 -0
- package/src/css/background-types.ts +65 -0
- package/src/css/browser-defaults.ts +16 -0
- package/src/css/clip-path-types.ts +13 -0
- package/src/css/compute-style.ts +494 -0
- package/src/css/css-unit-resolver.ts +65 -0
- package/src/css/custom-properties.ts +215 -0
- package/src/css/enums.ts +127 -0
- package/src/css/font-face-parser.ts +233 -0
- package/src/css/font-weight.ts +65 -0
- package/src/css/inline-style-parser.ts +27 -0
- package/src/css/layout-property-resolver.ts +75 -0
- package/src/css/length.ts +141 -0
- package/src/css/line-height.ts +96 -0
- package/src/css/named-colors.ts +150 -0
- package/src/css/parsers/background-parser-extended.ts +111 -0
- package/src/css/parsers/background-parser.ts +456 -0
- package/src/css/parsers/border-block-parser.ts +26 -0
- package/src/css/parsers/border-inline-parser.ts +26 -0
- package/src/css/parsers/border-parser-extended.ts +256 -0
- package/src/css/parsers/border-parser.ts +175 -0
- package/src/css/parsers/box-shadow-parser.ts +106 -0
- package/src/css/parsers/clip-path-parser.ts +92 -0
- package/src/css/parsers/color-parser.ts +14 -0
- package/src/css/parsers/dimension-parser.ts +117 -0
- package/src/css/parsers/display-flex-parser.ts +59 -0
- package/src/css/parsers/flex-parser.ts +144 -0
- package/src/css/parsers/font-parser.ts +40 -0
- package/src/css/parsers/gradient-parser.ts +366 -0
- package/src/css/parsers/grid-parser-extended.ts +55 -0
- package/src/css/parsers/grid-parser.ts +218 -0
- package/src/css/parsers/length-parser.ts +95 -0
- package/src/css/parsers/list-style-parser.ts +39 -0
- package/src/css/parsers/margin-block-parser.ts +12 -0
- package/src/css/parsers/margin-inline-parser.ts +12 -0
- package/src/css/parsers/margin-parser.ts +30 -0
- package/src/css/parsers/opacity-parser.ts +32 -0
- package/src/css/parsers/overflow-wrap-parser.ts +38 -0
- package/src/css/parsers/padding-block-parser.ts +12 -0
- package/src/css/parsers/padding-inline-parser.ts +12 -0
- package/src/css/parsers/padding-parser.ts +30 -0
- package/src/css/parsers/position-parser.ts +75 -0
- package/src/css/parsers/register-parsers.ts +302 -0
- package/src/css/parsers/registry.ts +18 -0
- package/src/css/parsers/text-parser-extended.ts +144 -0
- package/src/css/parsers/text-parser.ts +25 -0
- package/src/css/parsers/text-shadow-parser.ts +94 -0
- package/src/css/properties/box-model.ts +82 -0
- package/src/css/properties/flexbox.ts +44 -0
- package/src/css/properties/gap.ts +14 -0
- package/src/css/properties/grid.ts +94 -0
- package/src/css/properties/layout.ts +59 -0
- package/src/css/properties/misc.ts +44 -0
- package/src/css/properties/typography.ts +71 -0
- package/src/css/properties/visual.ts +68 -0
- package/src/css/selectors/matcher.ts +219 -0
- package/src/css/selectors/parser.ts +163 -0
- package/src/css/selectors/simple-key.ts +31 -0
- package/src/css/selectors/specificity.ts +41 -0
- package/src/css/selectors/types.ts +31 -0
- package/src/css/shorthands/border-shorthand.ts +68 -0
- package/src/css/shorthands/box-shorthand.ts +33 -0
- package/src/css/style-inheritance.ts +50 -0
- package/src/css/style.ts +402 -0
- package/src/css/ua-defaults/base-defaults.ts +266 -0
- package/src/css/ua-defaults/browser-defaults.ts +134 -0
- package/src/css/ua-defaults/element-defaults.ts +374 -0
- package/src/css/ua-defaults/types.ts +43 -0
- package/src/css/unit-conversion.ts +24 -0
- package/src/css/utils.ts +108 -0
- package/src/css/viewport.ts +17 -0
- package/src/debug/audit.ts +20 -0
- package/src/debug/ids.ts +13 -0
- package/src/debug/log.js +28 -0
- package/src/debug/log.ts +52 -0
- package/src/debug/tree.ts +57 -0
- package/src/dom/node.ts +133 -0
- package/src/environment/browser-environment.ts +78 -0
- package/src/environment/environment.ts +35 -0
- package/src/environment/global.ts +13 -0
- package/src/environment/node-environment.browser.ts +28 -0
- package/src/environment/node-environment.ts +64 -0
- package/src/fonts/detector.ts +28 -0
- package/src/fonts/engines/ttf-engine.ts +28 -0
- package/src/fonts/engines/woff-engine.ts +38 -0
- package/src/fonts/engines/woff2-engine.ts +41 -0
- package/src/fonts/extractors/metrics-extractor.ts +362 -0
- package/src/fonts/font-registry-resolver.ts +132 -0
- package/src/fonts/index.ts +3 -0
- package/src/fonts/orchestrator.ts +92 -0
- package/src/fonts/parsers/base-parser.ts +23 -0
- package/src/fonts/types.ts +85 -0
- package/src/fonts/utils/ttf-reconstructor.ts +120 -0
- package/src/fonts/woff/decoder.ts +105 -0
- package/src/fonts/woff2/buffer.ts +106 -0
- package/src/fonts/woff2/decoder.ts +981 -0
- package/src/geometry/box.ts +48 -0
- package/src/geometry/matrix.ts +59 -0
- package/src/html/css/parse-css.ts +85 -0
- package/src/html/dom-converter.ts +433 -0
- package/src/html/image-converter.ts +200 -0
- package/src/html-to-pdf.ts +410 -0
- package/src/image/base-decoder.ts +149 -0
- package/src/image/image-service.ts +188 -0
- package/src/image/jpeg-decoder.ts +73 -0
- package/src/image/png-decoder.ts +550 -0
- package/src/image/types.ts +20 -0
- package/src/image/webp-decoder.ts +242 -0
- package/src/image/webp-huffman.ts +218 -0
- package/src/image/webp-riff-parser.ts +54 -0
- package/src/image/webp-vp8l-decoder.ts +199 -0
- package/src/index.ts +35 -0
- package/src/layout/context/float-context.ts +62 -0
- package/src/layout/context/layout-environment.ts +29 -0
- package/src/layout/debug.ts +18 -0
- package/src/layout/inline/bounding-box-calculator.ts +132 -0
- package/src/layout/inline/font-baseline-calculator.ts +76 -0
- package/src/layout/inline/inline-utils.ts +94 -0
- package/src/layout/inline/layout.ts +285 -0
- package/src/layout/inline/line_breaker.ts +109 -0
- package/src/layout/inline/measurement.ts +144 -0
- package/src/layout/inline/run-placer.ts +139 -0
- package/src/layout/inline/text-alignment.ts +70 -0
- package/src/layout/inline/tokenizer.ts +195 -0
- package/src/layout/inline/types.ts +76 -0
- package/src/layout/pipeline/context-factory.ts +16 -0
- package/src/layout/pipeline/default-engine.ts +24 -0
- package/src/layout/pipeline/engine.ts +59 -0
- package/src/layout/pipeline/layout-tree.ts +13 -0
- package/src/layout/pipeline/out-of-flow-manager.ts +73 -0
- package/src/layout/pipeline/strategy.ts +12 -0
- package/src/layout/pipeline/text-metrics-initializer.ts +13 -0
- package/src/layout/strategies/block.ts +236 -0
- package/src/layout/strategies/display-none.ts +14 -0
- package/src/layout/strategies/fallback.ts +15 -0
- package/src/layout/strategies/flex.ts +477 -0
- package/src/layout/strategies/fragmentation.ts +17 -0
- package/src/layout/strategies/grid.ts +247 -0
- package/src/layout/strategies/image.ts +342 -0
- package/src/layout/strategies/inline.ts +128 -0
- package/src/layout/strategies/table.ts +595 -0
- package/src/layout/table/cell_layout.ts +31 -0
- package/src/layout/table/diagnostics.ts +19 -0
- package/src/layout/text-run.ts +42 -0
- package/src/layout/utils/content-measurer.ts +117 -0
- package/src/layout/utils/display-utils.ts +24 -0
- package/src/layout/utils/floats.ts +98 -0
- package/src/layout/utils/gap-calculator.ts +167 -0
- package/src/layout/utils/inline-formatter.ts +31 -0
- package/src/layout/utils/inline-formatting.ts +9 -0
- package/src/layout/utils/margin.ts +140 -0
- package/src/layout/utils/node-math.ts +237 -0
- package/src/layout/utils/overflow.ts +14 -0
- package/src/layout/utils/sizing.ts +12 -0
- package/src/layout/utils/text-metrics.ts +361 -0
- package/src/logging/debug.ts +58 -0
- package/src/pdf/font/base14/widths-courier-bold.ts +159 -0
- package/src/pdf/font/base14/widths-courier.ts +159 -0
- package/src/pdf/font/base14/widths-helvetica-bold.ts +158 -0
- package/src/pdf/font/base14/widths-helvetica.ts +158 -0
- package/src/pdf/font/base14/widths-times-bold.ts +158 -0
- package/src/pdf/font/base14/widths-times-roman.ts +158 -0
- package/src/pdf/font/base14/widths-types.ts +25 -0
- package/src/pdf/font/base14-widths.ts +32 -0
- package/src/pdf/font/blur.ts +81 -0
- package/src/pdf/font/builtin-fonts.browser.ts +262 -0
- package/src/pdf/font/builtin-fonts.ts +126 -0
- package/src/pdf/font/composite-glyph-parser.ts +242 -0
- package/src/pdf/font/embedder.ts +395 -0
- package/src/pdf/font/font-config.ts +190 -0
- package/src/pdf/font/font-registry.ts +263 -0
- package/src/pdf/font/font-subset.ts +258 -0
- package/src/pdf/font/glyph-atlas-maxrects.ts +305 -0
- package/src/pdf/font/glyph-atlas-tuner.ts +98 -0
- package/src/pdf/font/glyph-atlas.ts +226 -0
- package/src/pdf/font/glyph-cache.ts +127 -0
- package/src/pdf/font/loca-reader.ts +109 -0
- package/src/pdf/font/managers/font-resource-manager.ts +73 -0
- package/src/pdf/font/managers/subset-resource-manager.ts +164 -0
- package/src/pdf/font/rasterizer.ts +270 -0
- package/src/pdf/font/resolvers/base-font-mapper.ts +77 -0
- package/src/pdf/font/resolvers/family-resolver.ts +33 -0
- package/src/pdf/font/resolvers/weight-style-applicator.ts +63 -0
- package/src/pdf/font/simple-glyph-parser.ts +289 -0
- package/src/pdf/font/to-unicode.ts +109 -0
- package/src/pdf/font/transformation-matrix.ts +136 -0
- package/src/pdf/font/ttf-cmap.ts +180 -0
- package/src/pdf/font/ttf-global-metrics.ts +58 -0
- package/src/pdf/font/ttf-glyf.ts +125 -0
- package/src/pdf/font/ttf-glyph-metrics.ts +43 -0
- package/src/pdf/font/ttf-lite.ts +269 -0
- package/src/pdf/font/ttf-table-parser.ts +132 -0
- package/src/pdf/font/ttf-table-provider.ts +61 -0
- package/src/pdf/font/widths.ts +79 -0
- package/src/pdf/font-subset/font-registry.ts +127 -0
- package/src/pdf/header-footer-layout.ts +153 -0
- package/src/pdf/header-footer-painter.ts +209 -0
- package/src/pdf/header-footer-renderer.ts +357 -0
- package/src/pdf/header-footer-tokens.ts +55 -0
- package/src/pdf/header-footer.ts +25 -0
- package/src/pdf/layout-tree-builder.ts +261 -0
- package/src/pdf/page-painter.ts +241 -0
- package/src/pdf/pagination.ts +155 -0
- package/src/pdf/primitives/pdf-builder.ts +378 -0
- package/src/pdf/primitives/pdf-bytes.ts +40 -0
- package/src/pdf/primitives/pdf-document.ts +108 -0
- package/src/pdf/primitives/pdf-reference-manager.ts +47 -0
- package/src/pdf/primitives/pdf-resource-registries.ts +255 -0
- package/src/pdf/primitives/pdf-serializers.ts +194 -0
- package/src/pdf/primitives/pdf-types.ts +73 -0
- package/src/pdf/render.ts +210 -0
- package/src/pdf/renderer/box-painter.ts +236 -0
- package/src/pdf/renderer/page-paint.ts +102 -0
- package/src/pdf/renderer/paint-box-shadows.ts +218 -0
- package/src/pdf/renderer/radius.ts +58 -0
- package/src/pdf/renderers/graphics-state-manager.ts +40 -0
- package/src/pdf/renderers/image-renderer.ts +127 -0
- package/src/pdf/renderers/radius-utils.ts +80 -0
- package/src/pdf/renderers/rectangle-renderer.ts +129 -0
- package/src/pdf/renderers/rounded-rect-path.ts +120 -0
- package/src/pdf/renderers/shape-renderer.ts +563 -0
- package/src/pdf/renderers/shape-utils.ts +194 -0
- package/src/pdf/renderers/text-decoration-renderer.ts +313 -0
- package/src/pdf/renderers/text-encoder.ts +41 -0
- package/src/pdf/renderers/text-font-resolver.ts +75 -0
- package/src/pdf/renderers/text-renderer-utils.ts +28 -0
- package/src/pdf/renderers/text-renderer.ts +391 -0
- package/src/pdf/renderers/text-shadow-renderer.ts +300 -0
- package/src/pdf/shading/gradient-service.ts +525 -0
- package/src/pdf/shading/index.ts +1 -0
- package/src/pdf/stacking/build-stacking-contexts.ts +93 -0
- package/src/pdf/stacking/resolve-paint-order.ts +157 -0
- package/src/pdf/stacking/types.ts +40 -0
- package/src/pdf/svg/aspect-ratio.ts +81 -0
- package/src/pdf/svg/coordinate-mapper.ts +81 -0
- package/src/pdf/svg/geometry-builder.ts +45 -0
- package/src/pdf/svg/render-svg.ts +296 -0
- package/src/pdf/svg/shape-renderer.ts +463 -0
- package/src/pdf/svg/style-computer.ts +246 -0
- package/src/pdf/transform-adapter.ts +26 -0
- package/src/pdf/types.ts +377 -0
- package/src/pdf/utils/background-layer-resolver.ts +439 -0
- package/src/pdf/utils/background-tiles.ts +192 -0
- package/src/pdf/utils/border-dashes.ts +109 -0
- package/src/pdf/utils/border-radius-utils.ts +86 -0
- package/src/pdf/utils/box-dimensions-utils.ts +47 -0
- package/src/pdf/utils/clip-path-resolver.ts +50 -0
- package/src/pdf/utils/clipping-path-builder.ts +190 -0
- package/src/pdf/utils/color-utils.ts +102 -0
- package/src/pdf/utils/coordinate-transformer.ts +30 -0
- package/src/pdf/utils/drop-shadow-raster.ts +233 -0
- package/src/pdf/utils/encoding.ts +98 -0
- package/src/pdf/utils/glyph-atlas-registrar.ts +13 -0
- package/src/pdf/utils/glyph-run-renderer.ts +129 -0
- package/src/pdf/utils/image-command-partitioner.ts +28 -0
- package/src/pdf/utils/image-matrix-builder.ts +31 -0
- package/src/pdf/utils/image-utils.ts +26 -0
- package/src/pdf/utils/list-utils.ts +194 -0
- package/src/pdf/utils/node-text-run-factory.ts +202 -0
- package/src/pdf/utils/page-resource-registrar.ts +46 -0
- package/src/pdf/utils/result-combiner.ts +102 -0
- package/src/pdf/utils/shadow-utils.ts +127 -0
- package/src/pdf/utils/text-alignment-resolver.ts +76 -0
- package/src/pdf/utils/text-decoration-utils.ts +64 -0
- package/src/pdf/utils/text-layout-adjuster.ts +185 -0
- package/src/pdf/utils/text-utils.ts +193 -0
- package/src/pdf/utils/transform-scope-manager.ts +69 -0
- package/src/render/offset.ts +170 -0
- package/src/shim/empty.ts +2 -0
- package/src/shim/fs-empty.ts +5 -0
- package/src/shim/url-empty.ts +7 -0
- package/src/shim/zlib-empty.ts +9 -0
- package/src/style/shorthands/index.ts +19 -0
- package/src/style/ua/defaults.ts +69 -0
- package/src/svg/index.ts +4 -0
- package/src/svg/parser-registry.ts +71 -0
- package/src/svg/parser.ts +486 -0
- package/src/svg/path-data.ts +515 -0
- package/src/svg/types.ts +194 -0
- package/src/text/line-breaker.ts +321 -0
- package/src/text/text-transform.ts +43 -0
- package/src/text/text.ts +33 -0
- package/src/transform/css-parser.ts +95 -0
- package/src/types/fonts.ts +62 -0
- package/src/types/public.ts +19 -0
- package/src/units/page-utils.ts +58 -0
- package/src/units/units.ts +50 -0
- package/src/utils/base64.ts +24 -0
- package/test-output.txt +79 -0
- package/tests/css/background-parser.spec.ts +14 -0
- package/tests/css/clip-path-parser.spec.ts +66 -0
- package/tests/environment/path-resolution.spec.ts +104 -0
- package/tests/helpers/ai-layout-diagnostics.ts +141 -0
- package/tests/helpers/render-utils.ts +52 -0
- package/tests/helpers/text-geometry.ts +56 -0
- package/tests/layout/custom-properties.test.ts +38 -0
- package/tests/layout/gap-calculator.spec.ts +196 -0
- package/tests/layout/inline-background-alignment.spec.ts +93 -0
- package/tests/layout/inline-fragments.spec.ts +26 -0
- package/tests/layout/run-placer-baseline.spec.ts +108 -0
- package/tests/pdf/alignments.spec.ts +26 -0
- package/tests/pdf/background-clip.spec.ts +57 -0
- package/tests/pdf/background-repeat-space-round.spec.ts +35 -0
- package/tests/pdf/background-repeat.spec.ts +137 -0
- package/tests/pdf/border-radius.spec.ts +151 -0
- package/tests/pdf/clip-path.spec.ts +92 -0
- package/tests/pdf/radial-gradient.spec.ts +50 -0
- package/tests/pdf/svg-stroke-dash.spec.ts +81 -0
- package/tests/pdf/text-transform-matrix.spec.ts +43 -0
- package/tsconfig.json +17 -0
- package/types/fonts.js +10 -0
- package/vitest.config.ts +9 -0
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
// src/css/custom-properties.ts
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* CSS Custom Properties (CSS Variables) support
|
|
5
|
+
* Implements variable definition and resolution per CSS Custom Properties spec
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Storage for custom properties (CSS variables)
|
|
10
|
+
* Maps variable names (e.g., "--primary-color") to their raw string values
|
|
11
|
+
*/
|
|
12
|
+
export class CustomPropertiesMap {
|
|
13
|
+
private properties: Map<string, string> = new Map();
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Set a custom property value
|
|
17
|
+
*/
|
|
18
|
+
set(name: string, value: string): void {
|
|
19
|
+
// Ensure the property name starts with --
|
|
20
|
+
if (!name.startsWith('--')) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
this.properties.set(name, value.trim());
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Get a custom property value
|
|
28
|
+
*/
|
|
29
|
+
get(name: string): string | undefined {
|
|
30
|
+
return this.properties.get(name);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Check if a custom property exists
|
|
35
|
+
*/
|
|
36
|
+
has(name: string): boolean {
|
|
37
|
+
return this.properties.has(name);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Clone the custom properties map
|
|
42
|
+
*/
|
|
43
|
+
clone(): CustomPropertiesMap {
|
|
44
|
+
const cloned = new CustomPropertiesMap();
|
|
45
|
+
this.properties.forEach((value, key) => {
|
|
46
|
+
cloned.set(key, value);
|
|
47
|
+
});
|
|
48
|
+
return cloned;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Inherit properties from a parent map
|
|
53
|
+
* Child properties override parent properties
|
|
54
|
+
*/
|
|
55
|
+
inherit(parent: CustomPropertiesMap | undefined): CustomPropertiesMap {
|
|
56
|
+
if (!parent) {
|
|
57
|
+
return this.clone();
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const inherited = parent.clone();
|
|
61
|
+
this.properties.forEach((value, key) => {
|
|
62
|
+
inherited.set(key, value);
|
|
63
|
+
});
|
|
64
|
+
return inherited;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Get all property names
|
|
69
|
+
*/
|
|
70
|
+
keys(): string[] {
|
|
71
|
+
return Array.from(this.properties.keys());
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Get the number of properties
|
|
76
|
+
*/
|
|
77
|
+
get size(): number {
|
|
78
|
+
return this.properties.size;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Regular expression to match var() function calls
|
|
84
|
+
* Matches: var(--name) or var(--name, fallback)
|
|
85
|
+
*/
|
|
86
|
+
const VAR_FUNCTION_REGEX = /var\s*\(\s*(--[a-zA-Z0-9_-]+)\s*(?:,\s*([^)]+))?\s*\)/g;
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Check if a CSS value contains var() references
|
|
90
|
+
*/
|
|
91
|
+
export function containsVariableReference(value: string): boolean {
|
|
92
|
+
return value.includes('var(');
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Extract variable name from var() function
|
|
97
|
+
* Example: "var(--primary-color)" -> "--primary-color"
|
|
98
|
+
*/
|
|
99
|
+
export function extractVariableName(varFunctionCall: string): string | null {
|
|
100
|
+
const match = varFunctionCall.match(/var\s*\(\s*(--[a-zA-Z0-9_-]+)/);
|
|
101
|
+
return match ? match[1] : null;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Parse var() function to extract variable name and fallback
|
|
106
|
+
* Returns: { name: string, fallback?: string }
|
|
107
|
+
*/
|
|
108
|
+
export function parseVarFunction(varFunctionCall: string): { name: string; fallback?: string } | null {
|
|
109
|
+
const trimmed = varFunctionCall.trim();
|
|
110
|
+
|
|
111
|
+
// Match var(--name) or var(--name, fallback)
|
|
112
|
+
const match = trimmed.match(/^var\s*\(\s*(--[a-zA-Z0-9_-]+)\s*(?:,\s*(.+))?\s*\)$/);
|
|
113
|
+
|
|
114
|
+
if (!match) {
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return {
|
|
119
|
+
name: match[1],
|
|
120
|
+
fallback: match[2]?.trim(),
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Resolve CSS value by replacing var() references with actual values
|
|
126
|
+
* Supports nested var() calls and fallback values
|
|
127
|
+
*/
|
|
128
|
+
export function resolveVariableReferences(
|
|
129
|
+
value: string,
|
|
130
|
+
customProperties: CustomPropertiesMap,
|
|
131
|
+
maxDepth = 10
|
|
132
|
+
): string {
|
|
133
|
+
if (!containsVariableReference(value)) {
|
|
134
|
+
return value;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (maxDepth <= 0) {
|
|
138
|
+
// Prevent infinite recursion
|
|
139
|
+
console.warn('CSS variable resolution depth limit reached');
|
|
140
|
+
return value;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
let resolved = value;
|
|
144
|
+
const matches = value.matchAll(VAR_FUNCTION_REGEX);
|
|
145
|
+
|
|
146
|
+
for (const match of matches) {
|
|
147
|
+
const fullMatch = match[0];
|
|
148
|
+
const varName = match[1];
|
|
149
|
+
const fallback = match[2]?.trim();
|
|
150
|
+
|
|
151
|
+
// Try to get the variable value
|
|
152
|
+
let replacement = customProperties.get(varName);
|
|
153
|
+
|
|
154
|
+
// If variable not found, use fallback
|
|
155
|
+
if (replacement === undefined) {
|
|
156
|
+
if (fallback !== undefined) {
|
|
157
|
+
replacement = fallback;
|
|
158
|
+
} else {
|
|
159
|
+
// If no fallback, leave the var() call as-is (invalid)
|
|
160
|
+
console.warn(`CSS variable ${varName} not found and no fallback provided`);
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Replace this var() call
|
|
166
|
+
resolved = resolved.replace(fullMatch, replacement);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// Recursively resolve any nested var() calls
|
|
170
|
+
if (containsVariableReference(resolved)) {
|
|
171
|
+
resolved = resolveVariableReferences(resolved, customProperties, maxDepth - 1);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
return resolved.trim();
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Apply custom properties from declarations to the custom properties map
|
|
179
|
+
* Extracts all properties that start with "--"
|
|
180
|
+
*/
|
|
181
|
+
export function extractCustomProperties(
|
|
182
|
+
declarations: Record<string, string>
|
|
183
|
+
): CustomPropertiesMap {
|
|
184
|
+
const customProps = new CustomPropertiesMap();
|
|
185
|
+
|
|
186
|
+
for (const [property, value] of Object.entries(declarations)) {
|
|
187
|
+
if (property.startsWith('--')) {
|
|
188
|
+
customProps.set(property, value);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
return customProps;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Resolve all property values in declarations by replacing var() references
|
|
197
|
+
*/
|
|
198
|
+
export function resolveDeclarationsWithVariables(
|
|
199
|
+
declarations: Record<string, string>,
|
|
200
|
+
customProperties: CustomPropertiesMap
|
|
201
|
+
): Record<string, string> {
|
|
202
|
+
const resolved: Record<string, string> = {};
|
|
203
|
+
|
|
204
|
+
for (const [property, value] of Object.entries(declarations)) {
|
|
205
|
+
// Don't resolve custom properties themselves (they can contain var())
|
|
206
|
+
if (property.startsWith('--')) {
|
|
207
|
+
resolved[property] = value;
|
|
208
|
+
} else {
|
|
209
|
+
// Resolve var() references in regular properties
|
|
210
|
+
resolved[property] = resolveVariableReferences(value, customProperties);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
return resolved;
|
|
215
|
+
}
|
package/src/css/enums.ts
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
export enum Display {
|
|
2
|
+
Block = "block",
|
|
3
|
+
Inline = "inline",
|
|
4
|
+
InlineBlock = "inline-block",
|
|
5
|
+
Flex = "flex",
|
|
6
|
+
InlineFlex = "inline-flex",
|
|
7
|
+
Grid = "grid",
|
|
8
|
+
InlineGrid = "inline-grid",
|
|
9
|
+
Table = "table",
|
|
10
|
+
InlineTable = "inline-table",
|
|
11
|
+
TableRowGroup = "table-row-group",
|
|
12
|
+
TableHeaderGroup = "table-header-group",
|
|
13
|
+
TableFooterGroup = "table-footer-group",
|
|
14
|
+
TableRow = "table-row",
|
|
15
|
+
TableCell = "table-cell",
|
|
16
|
+
TableCaption = "table-caption",
|
|
17
|
+
ListItem = "list-item",
|
|
18
|
+
None = "none",
|
|
19
|
+
FlowRoot = "flow-root",
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export enum Position {
|
|
23
|
+
Static = "static",
|
|
24
|
+
Relative = "relative",
|
|
25
|
+
Absolute = "absolute",
|
|
26
|
+
Fixed = "fixed",
|
|
27
|
+
Sticky = "sticky",
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export enum FloatMode {
|
|
31
|
+
None = "none",
|
|
32
|
+
Left = "left",
|
|
33
|
+
Right = "right",
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export enum ClearMode {
|
|
37
|
+
None = "none",
|
|
38
|
+
Left = "left",
|
|
39
|
+
Right = "right",
|
|
40
|
+
Both = "both",
|
|
41
|
+
InlineStart = "inline-start",
|
|
42
|
+
InlineEnd = "inline-end",
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export enum OverflowMode {
|
|
46
|
+
Visible = "visible",
|
|
47
|
+
Hidden = "hidden",
|
|
48
|
+
Scroll = "scroll",
|
|
49
|
+
Auto = "auto",
|
|
50
|
+
Clip = "clip",
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export enum WhiteSpace {
|
|
54
|
+
Normal = "normal",
|
|
55
|
+
NoWrap = "nowrap",
|
|
56
|
+
Pre = "pre",
|
|
57
|
+
PreWrap = "pre-wrap",
|
|
58
|
+
PreLine = "pre-line",
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export enum TextWrap {
|
|
62
|
+
Wrap = "wrap",
|
|
63
|
+
NoWrap = "nowrap",
|
|
64
|
+
Balance = "balance",
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export enum AlignItems {
|
|
68
|
+
Stretch = "stretch",
|
|
69
|
+
FlexStart = "flex-start",
|
|
70
|
+
FlexEnd = "flex-end",
|
|
71
|
+
Center = "center",
|
|
72
|
+
Baseline = "baseline",
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export enum JustifyContent {
|
|
76
|
+
FlexStart = "flex-start",
|
|
77
|
+
FlexEnd = "flex-end",
|
|
78
|
+
Center = "center",
|
|
79
|
+
SpaceBetween = "space-between",
|
|
80
|
+
SpaceAround = "space-around",
|
|
81
|
+
SpaceEvenly = "space-evenly",
|
|
82
|
+
Start = "start",
|
|
83
|
+
End = "end",
|
|
84
|
+
Left = "left",
|
|
85
|
+
Right = "right",
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export enum AlignContent {
|
|
89
|
+
Stretch = "stretch",
|
|
90
|
+
FlexStart = "flex-start",
|
|
91
|
+
FlexEnd = "flex-end",
|
|
92
|
+
Center = "center",
|
|
93
|
+
SpaceBetween = "space-between",
|
|
94
|
+
SpaceAround = "space-around",
|
|
95
|
+
SpaceEvenly = "space-evenly",
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export enum VerticalAlign {
|
|
99
|
+
Baseline = "baseline",
|
|
100
|
+
Top = "top",
|
|
101
|
+
Middle = "middle",
|
|
102
|
+
Bottom = "bottom",
|
|
103
|
+
TextTop = "text-top",
|
|
104
|
+
TextBottom = "text-bottom",
|
|
105
|
+
Sub = "sub",
|
|
106
|
+
Super = "super",
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export enum WritingMode {
|
|
110
|
+
HorizontalTb = "horizontal-tb",
|
|
111
|
+
VerticalRl = "vertical-rl",
|
|
112
|
+
VerticalLr = "vertical-lr",
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export enum TableLayoutMode {
|
|
116
|
+
Auto = "auto",
|
|
117
|
+
Fixed = "fixed",
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export enum BorderModel {
|
|
121
|
+
Separate = "separate",
|
|
122
|
+
Collapse = "collapse",
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export type FlexDirection = "row" | "row-reverse" | "column" | "column-reverse";
|
|
126
|
+
|
|
127
|
+
export type AlignSelfValue = "auto" | AlignItems;
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CSS @font-face parsing utilities.
|
|
3
|
+
*
|
|
4
|
+
* This module handles parsing of CSS @font-face rules from stylesheets,
|
|
5
|
+
* including font family list parsing, weight matching, and source extraction.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { CSSFontFace, StyleSheets } from "../pdf/types.js";
|
|
9
|
+
import { normalizeFontWeight, parseFontWeightValue } from "./font-weight.js";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Result of parsing font faces from stylesheets.
|
|
13
|
+
*/
|
|
14
|
+
export interface ParsedFontFaceMap {
|
|
15
|
+
/**
|
|
16
|
+
* Map of normalized font family names to their @font-face definitions.
|
|
17
|
+
*/
|
|
18
|
+
facesByFamily: Map<string, CSSFontFace[]>;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Parse all @font-face definitions from stylesheets into a family-keyed map.
|
|
23
|
+
*
|
|
24
|
+
* @param stylesheets - StyleSheets containing font face definitions
|
|
25
|
+
* @returns Map of font families to their face definitions
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```typescript
|
|
29
|
+
* const { facesByFamily } = parseFontFaces(stylesheets);
|
|
30
|
+
* const tinosFaces = facesByFamily.get("tinos");
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
export function parseFontFaces(stylesheets: StyleSheets): ParsedFontFaceMap {
|
|
34
|
+
const facesByFamily = new Map<string, CSSFontFace[]>();
|
|
35
|
+
|
|
36
|
+
for (const face of stylesheets.fontFaces ?? []) {
|
|
37
|
+
const family = normalizeToken(face.family);
|
|
38
|
+
if (!family) {
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
const list = facesByFamily.get(family) ?? [];
|
|
42
|
+
list.push(face);
|
|
43
|
+
facesByFamily.set(family, list);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return { facesByFamily };
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Select the best @font-face from a list based on requested weight.
|
|
51
|
+
*
|
|
52
|
+
* Chooses the face with the smallest weight difference from the requested weight.
|
|
53
|
+
* Falls back to the first face if no weight information is available.
|
|
54
|
+
*
|
|
55
|
+
* @param faces - Array of font faces to select from
|
|
56
|
+
* @param requestedWeight - Desired font weight (100-900)
|
|
57
|
+
* @returns Best matching font face, or undefined if faces array is empty
|
|
58
|
+
*/
|
|
59
|
+
export function selectFaceForWeight(faces: CSSFontFace[], requestedWeight: number): CSSFontFace | undefined {
|
|
60
|
+
let bestFace: CSSFontFace | undefined;
|
|
61
|
+
let smallestDiff = Number.POSITIVE_INFINITY;
|
|
62
|
+
|
|
63
|
+
for (const face of faces) {
|
|
64
|
+
const faceWeight = parseFaceWeight(face.weight, requestedWeight);
|
|
65
|
+
if (faceWeight === null) {
|
|
66
|
+
if (!bestFace) {
|
|
67
|
+
bestFace = face;
|
|
68
|
+
}
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
const diff = Math.abs(faceWeight - requestedWeight);
|
|
72
|
+
if (diff < smallestDiff) {
|
|
73
|
+
smallestDiff = diff;
|
|
74
|
+
bestFace = face;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return bestFace ?? faces[0];
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Parse a font family list (comma-separated) into individual family names.
|
|
83
|
+
*
|
|
84
|
+
* Handles quoted family names and filters out empty tokens.
|
|
85
|
+
*
|
|
86
|
+
* @param value - Comma-separated font family string
|
|
87
|
+
* @returns Array of normalized family names
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* ```typescript
|
|
91
|
+
* parseFamilyList("'Times New Roman', Times, serif")
|
|
92
|
+
* // => ["Times New Roman", "Times", "serif"]
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
export function parseFamilyList(value: string | undefined): string[] {
|
|
96
|
+
if (!value) {
|
|
97
|
+
return [];
|
|
98
|
+
}
|
|
99
|
+
return value
|
|
100
|
+
.split(",")
|
|
101
|
+
.map((token) => stripQuotes(token.trim()))
|
|
102
|
+
.filter((token) => token.length > 0);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Check if a font style is italic or oblique.
|
|
107
|
+
*
|
|
108
|
+
* @param style - Font style value
|
|
109
|
+
* @returns True if style is "italic" or "oblique" (case-insensitive)
|
|
110
|
+
*/
|
|
111
|
+
export function isItalicStyle(style: string | undefined): boolean {
|
|
112
|
+
if (!style) {
|
|
113
|
+
return false;
|
|
114
|
+
}
|
|
115
|
+
const normalized = style.toLowerCase();
|
|
116
|
+
return normalized === "italic" || normalized === "oblique";
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Normalize a font family or token to lowercase and remove quotes.
|
|
121
|
+
*
|
|
122
|
+
* @param value - Token to normalize
|
|
123
|
+
* @returns Normalized lowercase string, or empty string if value is undefined
|
|
124
|
+
*/
|
|
125
|
+
export function normalizeToken(value: string | undefined): string {
|
|
126
|
+
if (!value) {
|
|
127
|
+
return "";
|
|
128
|
+
}
|
|
129
|
+
return stripQuotes(value).trim().toLowerCase();
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Remove surrounding quotes from a string.
|
|
134
|
+
*
|
|
135
|
+
* Handles both single and double quotes.
|
|
136
|
+
*
|
|
137
|
+
* @param value - String potentially wrapped in quotes
|
|
138
|
+
* @returns String with quotes removed, or original value if not quoted
|
|
139
|
+
*/
|
|
140
|
+
export function stripQuotes(value: string): string {
|
|
141
|
+
if ((value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'"))) {
|
|
142
|
+
return value.slice(1, -1);
|
|
143
|
+
}
|
|
144
|
+
return value;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Extract base font name from a @font-face definition using aliases.
|
|
149
|
+
*
|
|
150
|
+
* Checks both local() sources and the family name against the provided alias map.
|
|
151
|
+
*
|
|
152
|
+
* @param face - @font-face definition
|
|
153
|
+
* @param aliases - Map of font names to their aliases
|
|
154
|
+
* @returns Base font name if found, null otherwise
|
|
155
|
+
*/
|
|
156
|
+
export function baseFontFromFace(face: CSSFontFace, aliases: ReadonlyMap<string, string>): string | null {
|
|
157
|
+
const localName = extractLocalSource(face.src);
|
|
158
|
+
if (localName) {
|
|
159
|
+
const normalized = normalizeToken(localName);
|
|
160
|
+
const alias = aliases.get(normalized);
|
|
161
|
+
if (alias) {
|
|
162
|
+
return alias;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
const familyAlias = aliases.get(normalizeToken(face.family));
|
|
166
|
+
if (familyAlias) {
|
|
167
|
+
return familyAlias;
|
|
168
|
+
}
|
|
169
|
+
return null;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Extract the first local() font source from a src list.
|
|
174
|
+
*
|
|
175
|
+
* @param srcList - Array of font source strings (e.g., ["local('Arial')", "url(...))"])
|
|
176
|
+
* @returns Local font name if found, null otherwise
|
|
177
|
+
*
|
|
178
|
+
* @example
|
|
179
|
+
* ```typescript
|
|
180
|
+
* extractLocalSource(["local('Arial')", "url(arial.woff2)"])
|
|
181
|
+
* // => "Arial"
|
|
182
|
+
* ```
|
|
183
|
+
*/
|
|
184
|
+
export function extractLocalSource(srcList: string[]): string | null {
|
|
185
|
+
for (const src of srcList) {
|
|
186
|
+
const match = src.match(/local\(([^)]+)\)/i);
|
|
187
|
+
if (match) {
|
|
188
|
+
return stripQuotes(match[1].trim());
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
return null;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Parse a @font-face weight value into a numeric weight.
|
|
196
|
+
*
|
|
197
|
+
* Handles:
|
|
198
|
+
* - Numeric weights (already normalized)
|
|
199
|
+
* - String values ("normal", "bold", "400", etc.)
|
|
200
|
+
* - Multiple weights (chooses closest to fallback)
|
|
201
|
+
*
|
|
202
|
+
* @param value - Weight value from @font-face
|
|
203
|
+
* @param fallback - Fallback weight to use for choosing from multiple values
|
|
204
|
+
* @returns Normalized numeric weight (100-900), or null if unparseable
|
|
205
|
+
*/
|
|
206
|
+
function parseFaceWeight(value: string | number | undefined, fallback: number): number | null {
|
|
207
|
+
if (typeof value === "number") {
|
|
208
|
+
return normalizeFontWeight(value);
|
|
209
|
+
}
|
|
210
|
+
if (typeof value !== "string") {
|
|
211
|
+
return null;
|
|
212
|
+
}
|
|
213
|
+
const parts = value.split(/\s+/).filter(Boolean);
|
|
214
|
+
if (parts.length > 1) {
|
|
215
|
+
const parsedWeights = parts
|
|
216
|
+
.map((part) => parseFontWeightValue(part, fallback))
|
|
217
|
+
.filter((weight): weight is number => weight !== undefined)
|
|
218
|
+
.map((weight) => normalizeFontWeight(weight));
|
|
219
|
+
if (parsedWeights.length === 0) {
|
|
220
|
+
return null;
|
|
221
|
+
}
|
|
222
|
+
return parsedWeights.reduce((closest, candidate) => {
|
|
223
|
+
const candidateDiff = Math.abs(candidate - fallback);
|
|
224
|
+
const closestDiff = Math.abs(closest - fallback);
|
|
225
|
+
return candidateDiff < closestDiff ? candidate : closest;
|
|
226
|
+
}, parsedWeights[0]);
|
|
227
|
+
}
|
|
228
|
+
const parsed = parseFontWeightValue(value, fallback);
|
|
229
|
+
if (parsed === undefined) {
|
|
230
|
+
return null;
|
|
231
|
+
}
|
|
232
|
+
return normalizeFontWeight(parsed);
|
|
233
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
const FONT_WEIGHT_STEPS = [100, 200, 300, 400, 500, 600, 700, 800, 900] as const;
|
|
2
|
+
|
|
3
|
+
type FontWeightDirection = "bolder" | "lighter";
|
|
4
|
+
|
|
5
|
+
export function normalizeFontWeight(weight: number | undefined): number {
|
|
6
|
+
if (!Number.isFinite(weight ?? NaN)) {
|
|
7
|
+
return 400;
|
|
8
|
+
}
|
|
9
|
+
const clamped = Math.min(900, Math.max(100, weight as number));
|
|
10
|
+
let nearest = 400;
|
|
11
|
+
let smallestDiff = Math.abs(nearest - clamped);
|
|
12
|
+
for (const step of FONT_WEIGHT_STEPS) {
|
|
13
|
+
const diff = Math.abs(step - clamped);
|
|
14
|
+
if (diff < smallestDiff) {
|
|
15
|
+
smallestDiff = diff;
|
|
16
|
+
nearest = step;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return nearest;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function stepFontWeight(weight: number | undefined, direction: FontWeightDirection): number {
|
|
23
|
+
const normalized = normalizeFontWeight(weight);
|
|
24
|
+
const index = FONT_WEIGHT_STEPS.indexOf(normalized as (typeof FONT_WEIGHT_STEPS)[number]);
|
|
25
|
+
if (index === -1) {
|
|
26
|
+
return normalized;
|
|
27
|
+
}
|
|
28
|
+
if (direction === "bolder") {
|
|
29
|
+
return FONT_WEIGHT_STEPS[Math.min(FONT_WEIGHT_STEPS.length - 1, index + 1)];
|
|
30
|
+
}
|
|
31
|
+
return FONT_WEIGHT_STEPS[Math.max(0, index - 1)];
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function parseFontWeightValue(value: string, inherited?: number): number | undefined {
|
|
35
|
+
const token = value.trim().toLowerCase();
|
|
36
|
+
switch (token) {
|
|
37
|
+
case "normal":
|
|
38
|
+
return 400;
|
|
39
|
+
case "bold":
|
|
40
|
+
return 700;
|
|
41
|
+
case "bolder":
|
|
42
|
+
return stepFontWeight(inherited, "bolder");
|
|
43
|
+
case "lighter":
|
|
44
|
+
return stepFontWeight(inherited, "lighter");
|
|
45
|
+
case "inherit":
|
|
46
|
+
return inherited !== undefined ? normalizeFontWeight(inherited) : undefined;
|
|
47
|
+
case "initial":
|
|
48
|
+
return 400;
|
|
49
|
+
default: {
|
|
50
|
+
const numeric = Number.parseFloat(token);
|
|
51
|
+
if (Number.isFinite(numeric)) {
|
|
52
|
+
return normalizeFontWeight(numeric);
|
|
53
|
+
}
|
|
54
|
+
return undefined;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function fontWeightCacheKey(weight: number | undefined): string {
|
|
60
|
+
return normalizeFontWeight(weight).toString();
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function isBoldFontWeight(weight: number | undefined): boolean {
|
|
64
|
+
return normalizeFontWeight(weight) >= 600;
|
|
65
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse inline style attribute
|
|
3
|
+
* Responsibility: Convert style string to property map
|
|
4
|
+
*/
|
|
5
|
+
export function parseInlineStyle(style: string): Record<string, string> {
|
|
6
|
+
const properties: Record<string, string> = {};
|
|
7
|
+
|
|
8
|
+
if (!style || typeof style !== 'string') {
|
|
9
|
+
return properties;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const declarations = style.split(';');
|
|
13
|
+
|
|
14
|
+
for (const decl of declarations) {
|
|
15
|
+
const colonIndex = decl.indexOf(':');
|
|
16
|
+
if (colonIndex === -1) continue;
|
|
17
|
+
|
|
18
|
+
const property = decl.substring(0, colonIndex).trim();
|
|
19
|
+
const value = decl.substring(colonIndex + 1).trim();
|
|
20
|
+
|
|
21
|
+
if (property && value) {
|
|
22
|
+
properties[property] = value;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return properties;
|
|
27
|
+
}
|