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,57 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
import express from "express";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { mkdir } from "node:fs/promises";
|
|
5
|
+
import { buildBrowserBundle } from "./browser-build.js";
|
|
6
|
+
|
|
7
|
+
const PORT = Number.parseInt(process.env.PORT ?? "", 10) || 5177;
|
|
8
|
+
const PUBLIC_DIR = path.resolve("playground", "public");
|
|
9
|
+
const ENTRY = "playground/browser-entry.ts";
|
|
10
|
+
const OUTFILE = "playground/public/vendor/pagyra-playground-browser.js";
|
|
11
|
+
|
|
12
|
+
async function start() {
|
|
13
|
+
await mkdir(path.dirname(path.resolve(OUTFILE)), { recursive: true });
|
|
14
|
+
const buildResult = await buildBrowserBundle({
|
|
15
|
+
entry: ENTRY,
|
|
16
|
+
outfile: OUTFILE,
|
|
17
|
+
minify: false,
|
|
18
|
+
sourcemap: true,
|
|
19
|
+
watch: true,
|
|
20
|
+
onRebuild(error) {
|
|
21
|
+
if (error) {
|
|
22
|
+
console.error("[playground bundle] rebuild failed:", error);
|
|
23
|
+
} else {
|
|
24
|
+
console.log("[playground bundle] rebuild finished.");
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
const app = express();
|
|
30
|
+
|
|
31
|
+
app.get("/mode.js", (_req, res) => {
|
|
32
|
+
res.type("application/javascript");
|
|
33
|
+
res.send('window.__PLAYGROUND_MODE = "browser";');
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
// Expose shared assets (fonts, images) for the browser bundle.
|
|
37
|
+
app.use("/assets", express.static(path.resolve("assets")));
|
|
38
|
+
app.use(express.static(PUBLIC_DIR));
|
|
39
|
+
|
|
40
|
+
const server = app.listen(PORT, () => {
|
|
41
|
+
console.log(`[playground:browser] serving http://localhost:${PORT}`);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
const cleanup = async () => {
|
|
45
|
+
server.close(() => console.log("[playground:browser] server stopped"));
|
|
46
|
+
await buildResult.stop?.();
|
|
47
|
+
process.exit();
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
process.once("SIGINT", cleanup);
|
|
51
|
+
process.once("SIGTERM", cleanup);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
start().catch((error) => {
|
|
55
|
+
console.error("[playground:browser] failed to start:", error);
|
|
56
|
+
process.exit(1);
|
|
57
|
+
});
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { parseTtfBuffer } from "../src/pdf/font/ttf-lite.js";
|
|
3
|
+
|
|
4
|
+
const data = await readFile("assets/fonts/Roboto-Regular.ttf");
|
|
5
|
+
const metrics = parseTtfBuffer(data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength));
|
|
6
|
+
console.log("glyphId", metrics.cmap.getGlyphId(0x25AA));
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
import fs from 'fs/promises';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import { fileURLToPath } from 'url';
|
|
5
|
+
import { renderHtmlToPdf } from '../src/html-to-pdf.js';
|
|
6
|
+
import { DEFAULT_PAGE_WIDTH_PX, DEFAULT_PAGE_HEIGHT_PX } from '../src/units/page-utils.js';
|
|
7
|
+
|
|
8
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
9
|
+
const __dirname = path.dirname(__filename);
|
|
10
|
+
|
|
11
|
+
async function main() {
|
|
12
|
+
// Parse command line arguments
|
|
13
|
+
const args = process.argv.slice(2);
|
|
14
|
+
let debugLevel: string | undefined;
|
|
15
|
+
let debugCats: string[] | undefined;
|
|
16
|
+
let examplePathArg: string | undefined;
|
|
17
|
+
let pageWidth: number | undefined;
|
|
18
|
+
let pageHeight: number | undefined;
|
|
19
|
+
let margins: { top: number; right: number; bottom: number; left: number } | undefined;
|
|
20
|
+
|
|
21
|
+
for (let i = 0; i < args.length; i++) {
|
|
22
|
+
const arg = args[i];
|
|
23
|
+
if (arg === '--debug-level' && i + 1 < args.length) {
|
|
24
|
+
debugLevel = args[i + 1] as any; // will validate later
|
|
25
|
+
i++;
|
|
26
|
+
} else if (arg === '--debug-cats' && i + 1 < args.length) {
|
|
27
|
+
debugCats = args[i + 1].split(',').map(cat => cat.trim()).filter(Boolean);
|
|
28
|
+
i++;
|
|
29
|
+
} else if (arg === '--page-width' && i + 1 < args.length) {
|
|
30
|
+
pageWidth = parseFloat(args[i + 1]);
|
|
31
|
+
i++;
|
|
32
|
+
} else if (arg === '--page-height' && i + 1 < args.length) {
|
|
33
|
+
pageHeight = parseFloat(args[i + 1]);
|
|
34
|
+
i++;
|
|
35
|
+
} else if (arg === '--margins' && i + 1 < args.length) {
|
|
36
|
+
const marginValues = args[i + 1].split(',').map(m => parseFloat(m.trim()));
|
|
37
|
+
if (marginValues.length === 1) {
|
|
38
|
+
margins = { top: marginValues[0], right: marginValues[0], bottom: marginValues[0], left: marginValues[0] };
|
|
39
|
+
} else if (marginValues.length === 2) {
|
|
40
|
+
margins = { top: marginValues[0], right: marginValues[1], bottom: marginValues[0], left: marginValues[1] };
|
|
41
|
+
} else if (marginValues.length === 4) {
|
|
42
|
+
margins = { top: marginValues[0], right: marginValues[1], bottom: marginValues[2], left: marginValues[3] };
|
|
43
|
+
} else {
|
|
44
|
+
console.warn('Invalid --margins argument. Expected 1, 2, or 4 comma-separated numbers (e.g., "10", "10,20", "10,20,30,40").');
|
|
45
|
+
}
|
|
46
|
+
i++;
|
|
47
|
+
} else if (!arg.startsWith('--')) {
|
|
48
|
+
examplePathArg = arg;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const repoRoot = path.resolve(__dirname, '..');
|
|
53
|
+
const examplesDir = path.join(repoRoot, 'playground', 'public', 'examples');
|
|
54
|
+
// Allow passing an example path or filename as the first argument. If it's a filename,
|
|
55
|
+
// resolve it under playground/public/examples. Otherwise use the default demo.
|
|
56
|
+
const arg = examplePathArg;
|
|
57
|
+
let examplePath: string;
|
|
58
|
+
if (arg) {
|
|
59
|
+
// Try a few sensible resolutions for the provided argument.
|
|
60
|
+
const candidateAbsolute = path.isAbsolute(arg) ? arg : path.join(repoRoot, arg);
|
|
61
|
+
const candidateExamples = path.join(examplesDir, arg);
|
|
62
|
+
try {
|
|
63
|
+
await fs.stat(candidateAbsolute);
|
|
64
|
+
examplePath = candidateAbsolute;
|
|
65
|
+
} catch {
|
|
66
|
+
try {
|
|
67
|
+
await fs.stat(candidateExamples);
|
|
68
|
+
examplePath = candidateExamples;
|
|
69
|
+
} catch {
|
|
70
|
+
const withHtml = candidateExamples.endsWith('.html') ? '' : '.html';
|
|
71
|
+
const candidateWithExt = candidateExamples + withHtml;
|
|
72
|
+
try {
|
|
73
|
+
await fs.stat(candidateWithExt);
|
|
74
|
+
examplePath = candidateWithExt;
|
|
75
|
+
} catch {
|
|
76
|
+
// Fallback: resolve under examplesDir (may still error later when reading)
|
|
77
|
+
examplePath = candidateExamples;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
} else {
|
|
82
|
+
examplePath = path.join(examplesDir, 'svg-radial-transform-demo.html');
|
|
83
|
+
}
|
|
84
|
+
const outDir = path.join(repoRoot, 'playground', 'exports');
|
|
85
|
+
await fs.mkdir(outDir, { recursive: true });
|
|
86
|
+
|
|
87
|
+
const html = await fs.readFile(examplePath, 'utf8');
|
|
88
|
+
|
|
89
|
+
const finalPageWidth = pageWidth ?? DEFAULT_PAGE_WIDTH_PX;
|
|
90
|
+
const finalPageHeight = pageHeight ?? DEFAULT_PAGE_HEIGHT_PX;
|
|
91
|
+
|
|
92
|
+
console.log('Rendering playground example to PDF:', examplePath);
|
|
93
|
+
// Provide resource/asset roots so example-relative and absolute (/images/...) URLs resolve
|
|
94
|
+
const resourceBaseDir = path.dirname(examplePath);
|
|
95
|
+
const assetRootDir = path.join(repoRoot, 'playground', 'public');
|
|
96
|
+
|
|
97
|
+
const pdf = await renderHtmlToPdf({
|
|
98
|
+
html,
|
|
99
|
+
css: '',
|
|
100
|
+
viewportWidth: finalPageWidth,
|
|
101
|
+
viewportHeight: finalPageHeight,
|
|
102
|
+
pageWidth: finalPageWidth,
|
|
103
|
+
pageHeight: finalPageHeight,
|
|
104
|
+
margins: margins ?? { top: 0, right: 0, bottom: 0, left: 0 },
|
|
105
|
+
debug: !!(debugLevel || debugCats),
|
|
106
|
+
debugLevel: debugLevel as any,
|
|
107
|
+
debugCats,
|
|
108
|
+
resourceBaseDir,
|
|
109
|
+
assetRootDir,
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
const outName = path.basename(examplePath).replace(/\.html?$/i, '') + '.pdf';
|
|
113
|
+
const outPath = path.join(outDir, outName);
|
|
114
|
+
await fs.writeFile(outPath, pdf);
|
|
115
|
+
console.log('PDF written to:', outPath);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
main().catch(err => {
|
|
119
|
+
console.error('Error rendering playground example:', err instanceof Error ? err.stack : err);
|
|
120
|
+
process.exit(1);
|
|
121
|
+
});
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runner that imports compiled JS from dist and runs the atlas tuner.
|
|
3
|
+
* Use after building the project: `npm run build`
|
|
4
|
+
*
|
|
5
|
+
* Run with: `node scripts/run-glyph-atlas-tuner-runner.mjs`
|
|
6
|
+
*
|
|
7
|
+
* This avoids ts-node resolution issues by using the compiled output.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import fs from "fs";
|
|
11
|
+
import path from "path";
|
|
12
|
+
|
|
13
|
+
import { parseTtfFont } from "../dist/src/pdf/font/ttf-lite.js";
|
|
14
|
+
import { getGlyphMask, clearGlyphMaskCache } from "../dist/src/pdf/font/glyph-cache.js";
|
|
15
|
+
import { pickAtlasSettingsFromSamples } from "../dist/src/pdf/font/glyph-atlas-tuner.js";
|
|
16
|
+
|
|
17
|
+
async function sampleFromFont(fontPath, opts = {}) {
|
|
18
|
+
const samples = [];
|
|
19
|
+
const maxGlyphs = opts.maxGlyphs ?? 200;
|
|
20
|
+
const fontSizePx = opts.fontSizePx ?? 64;
|
|
21
|
+
|
|
22
|
+
try {
|
|
23
|
+
const metrics = parseTtfFont(fontPath);
|
|
24
|
+
const glyphCount = metrics.glyphMetrics ? metrics.glyphMetrics.size : Math.max(256, maxGlyphs);
|
|
25
|
+
const limit = Math.min(maxGlyphs, glyphCount);
|
|
26
|
+
|
|
27
|
+
if (metrics.glyphMetrics && metrics.glyphMetrics.size > 0) {
|
|
28
|
+
let i = 0;
|
|
29
|
+
for (const [gid] of metrics.glyphMetrics) {
|
|
30
|
+
if (i >= limit) break;
|
|
31
|
+
try {
|
|
32
|
+
const mask = getGlyphMask(metrics, gid, fontSizePx, 4);
|
|
33
|
+
if (mask && mask.width > 0 && mask.height > 0) {
|
|
34
|
+
samples.push({ width: mask.width, height: mask.height });
|
|
35
|
+
i++;
|
|
36
|
+
}
|
|
37
|
+
} catch (e) {
|
|
38
|
+
// ignore
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
} else {
|
|
42
|
+
for (let gid = 0; gid < limit; gid++) {
|
|
43
|
+
try {
|
|
44
|
+
const mask = getGlyphMask(metrics, gid, fontSizePx, 4);
|
|
45
|
+
if (mask && mask.width > 0 && mask.height > 0) {
|
|
46
|
+
samples.push({ width: mask.width, height: mask.height });
|
|
47
|
+
}
|
|
48
|
+
} catch (e) {}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
clearGlyphMaskCache();
|
|
53
|
+
} catch (err) {
|
|
54
|
+
console.error("Failed to parse font", fontPath, err && err.message ? err.message : err);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return samples;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function syntheticSamples() {
|
|
61
|
+
const arr = [];
|
|
62
|
+
for (let i = 0; i < 40; i++) arr.push({ width: 8, height: 10 });
|
|
63
|
+
for (let i = 0; i < 40; i++) arr.push({ width: 20 + (i % 10), height: 24 + (i % 8) });
|
|
64
|
+
for (let i = 0; i < 20; i++) arr.push({ width: 48 + (i % 16), height: 56 + (i % 10) });
|
|
65
|
+
for (let i = 0; i < 6; i++) arr.push({ width: 128, height: 140 });
|
|
66
|
+
return arr;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
async function run() {
|
|
70
|
+
const fontDir = path.resolve(process.cwd(), "assets", "fonts");
|
|
71
|
+
let fontFiles = [];
|
|
72
|
+
try {
|
|
73
|
+
const files = fs.readdirSync(fontDir);
|
|
74
|
+
fontFiles = files.filter((f) => /\.(ttf|otf|woff2?)$/i.test(f)).map((f) => path.join(fontDir, f));
|
|
75
|
+
} catch (e) {
|
|
76
|
+
console.warn("No bundled fonts found in assets/fonts — continuing with synthetic samples only");
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
console.log("Found fonts:", fontFiles.map((p) => path.basename(p)));
|
|
80
|
+
const allSamples = [];
|
|
81
|
+
|
|
82
|
+
for (const fontPath of fontFiles) {
|
|
83
|
+
console.log("Sampling font:", path.basename(fontPath));
|
|
84
|
+
const s = await sampleFromFont(fontPath, { maxGlyphs: 200, fontSizePx: 64 });
|
|
85
|
+
console.log(` -> collected ${s.length} samples from ${path.basename(fontPath)}`);
|
|
86
|
+
allSamples.push(...s);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const synth = syntheticSamples();
|
|
90
|
+
console.log("Adding", synth.length, "synthetic samples");
|
|
91
|
+
allSamples.push(...synth);
|
|
92
|
+
|
|
93
|
+
if (allSamples.length === 0) {
|
|
94
|
+
console.warn("No samples gathered — returning conservative defaults");
|
|
95
|
+
console.log("Suggested settings: pageSize=2048, padding=1");
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const settings = pickAtlasSettingsFromSamples(allSamples, { candidates: [1024, 2048, 4096], paddings: [0, 1, 2, 3] });
|
|
100
|
+
console.log("Tuner result:", settings);
|
|
101
|
+
console.log("");
|
|
102
|
+
console.log("Recommended values to apply to MaxRects packer:");
|
|
103
|
+
console.log(` pageSize: ${settings.pageSize}`);
|
|
104
|
+
console.log(` padding: ${settings.padding}`);
|
|
105
|
+
console.log(`Estimated pages: ${settings.estimatedPages}, wastedRatio: ${settings.wastedRatio.toFixed(3)}`);
|
|
106
|
+
console.log("");
|
|
107
|
+
console.log("If you want me to apply these settings to src/pdf/font/glyph-atlas-maxrects.ts I can do that now.");
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
run().catch((err) => {
|
|
111
|
+
console.error("Error running tuner runner:", err);
|
|
112
|
+
process.exit(1);
|
|
113
|
+
});
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Run glyph atlas tuner (sample fonts + synthetic) and print recommended atlas settings.
|
|
3
|
+
*
|
|
4
|
+
* Usage (from repo root):
|
|
5
|
+
* - With ts-node (recommended):
|
|
6
|
+
* npx ts-node scripts/run-glyph-atlas-tuner.ts
|
|
7
|
+
* - Or via node if you have ts-node registered:
|
|
8
|
+
* node -r ts-node/register scripts/run-glyph-atlas-tuner.ts
|
|
9
|
+
*
|
|
10
|
+
* Notes:
|
|
11
|
+
* - This script imports project modules (TS sources). When running with ts-node,
|
|
12
|
+
* TypeScript files are resolved directly (we import .ts paths here to avoid
|
|
13
|
+
* Node ESM resolving .js which caused ERR_MODULE_NOT_FOUND).
|
|
14
|
+
*
|
|
15
|
+
* What it does:
|
|
16
|
+
* - Loads fonts from ./assets/fonts
|
|
17
|
+
* - For each font samples up to N glyphs (attempts to rasterize glyph masks at fontSizePx)
|
|
18
|
+
* - Adds synthetic samples (small/medium/large)
|
|
19
|
+
* - Runs pickAtlasSettingsFromSamples(...) and prints the chosen settings
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
import fs from "fs";
|
|
23
|
+
import path from "path";
|
|
24
|
+
|
|
25
|
+
// IMPORTANT: import the .ts modules (ts-node resolves .ts imports). This avoids Node ESM looking for .js files.
|
|
26
|
+
import { parseTtfFont } from "../src/pdf/font/ttf-lite.ts";
|
|
27
|
+
import { getGlyphMask, clearGlyphMaskCache } from "../src/pdf/font/glyph-cache.ts";
|
|
28
|
+
import { pickAtlasSettingsFromSamples } from "../src/pdf/font/glyph-atlas-tuner.ts";
|
|
29
|
+
|
|
30
|
+
async function sampleFromFont(fontPath: string, opts: { maxGlyphs?: number; fontSizePx?: number } = {}) {
|
|
31
|
+
const samples: Array<{ width: number; height: number }> = [];
|
|
32
|
+
const maxGlyphs = opts.maxGlyphs ?? 200;
|
|
33
|
+
const fontSizePx = opts.fontSizePx ?? 64;
|
|
34
|
+
|
|
35
|
+
try {
|
|
36
|
+
const metrics = parseTtfFont(fontPath);
|
|
37
|
+
// Try to sample from glyphMetrics map if available
|
|
38
|
+
const glyphCount = metrics.glyphMetrics ? metrics.glyphMetrics.size : Math.max(256, maxGlyphs);
|
|
39
|
+
const limit = Math.min(maxGlyphs, glyphCount);
|
|
40
|
+
|
|
41
|
+
// Prefer to sample glyph IDs present in the metrics map
|
|
42
|
+
if (metrics.glyphMetrics && metrics.glyphMetrics.size > 0) {
|
|
43
|
+
let i = 0;
|
|
44
|
+
for (const [gid] of metrics.glyphMetrics) {
|
|
45
|
+
if (i >= limit) break;
|
|
46
|
+
try {
|
|
47
|
+
const mask = getGlyphMask(metrics as any, gid, fontSizePx, 4);
|
|
48
|
+
if (mask && mask.width > 0 && mask.height > 0) {
|
|
49
|
+
samples.push({ width: mask.width, height: mask.height });
|
|
50
|
+
i++;
|
|
51
|
+
}
|
|
52
|
+
} catch (e) {
|
|
53
|
+
// ignore glyphs that fail during rasterization
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
} else {
|
|
57
|
+
// Fallback: try glyph ids 0..limit-1
|
|
58
|
+
for (let gid = 0; gid < limit; gid++) {
|
|
59
|
+
try {
|
|
60
|
+
const mask = getGlyphMask(metrics as any, gid, fontSizePx, 4);
|
|
61
|
+
if (mask && mask.width > 0 && mask.height > 0) {
|
|
62
|
+
samples.push({ width: mask.width, height: mask.height });
|
|
63
|
+
}
|
|
64
|
+
} catch (e) {
|
|
65
|
+
// continue
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Clear any packed atlas/cache artifacts between fonts to avoid skew
|
|
71
|
+
clearGlyphMaskCache();
|
|
72
|
+
} catch (err) {
|
|
73
|
+
console.error("Failed to parse font", fontPath, err instanceof Error ? err.message : err);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return samples;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function syntheticSamples(): Array<{ width: number; height: number }> {
|
|
80
|
+
// Provide a sensible mixture of sizes: small glyphs, punctuation, medium letters, large capitals
|
|
81
|
+
const arr: Array<{ width: number; height: number }> = [];
|
|
82
|
+
// many small
|
|
83
|
+
for (let i = 0; i < 40; i++) arr.push({ width: 8, height: 10 });
|
|
84
|
+
// medium
|
|
85
|
+
for (let i = 0; i < 40; i++) arr.push({ width: 20 + (i % 10), height: 24 + (i % 8) });
|
|
86
|
+
// larger
|
|
87
|
+
for (let i = 0; i < 20; i++) arr.push({ width: 48 + (i % 16), height: 56 + (i % 10) });
|
|
88
|
+
// some very large glyphs (accents, icons)
|
|
89
|
+
for (let i = 0; i < 6; i++) arr.push({ width: 128, height: 140 });
|
|
90
|
+
return arr;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
async function run() {
|
|
94
|
+
const fontDir = path.resolve(process.cwd(), "assets", "fonts");
|
|
95
|
+
let fontFiles: string[] = [];
|
|
96
|
+
try {
|
|
97
|
+
const files = fs.readdirSync(fontDir);
|
|
98
|
+
fontFiles = files
|
|
99
|
+
.filter((f) => /\.(ttf|otf|woff2?)$/i.test(f))
|
|
100
|
+
.map((f) => path.join(fontDir, f));
|
|
101
|
+
} catch (e) {
|
|
102
|
+
console.warn("No bundled fonts found in assets/fonts — continuing with synthetic samples only");
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
console.log("Found fonts:", fontFiles.map((p) => path.basename(p)));
|
|
106
|
+
const allSamples: Array<{ width: number; height: number }> = [];
|
|
107
|
+
|
|
108
|
+
for (const fontPath of fontFiles) {
|
|
109
|
+
console.log("Sampling font:", path.basename(fontPath));
|
|
110
|
+
const s = await sampleFromFont(fontPath, { maxGlyphs: 200, fontSizePx: 64 });
|
|
111
|
+
console.log(` -> collected ${s.length} samples from ${path.basename(fontPath)}`);
|
|
112
|
+
allSamples.push(...s);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// add synthetic
|
|
116
|
+
const synth = syntheticSamples();
|
|
117
|
+
console.log("Adding", synth.length, "synthetic samples");
|
|
118
|
+
allSamples.push(...synth);
|
|
119
|
+
|
|
120
|
+
if (allSamples.length === 0) {
|
|
121
|
+
console.warn("No samples gathered — returning conservative defaults");
|
|
122
|
+
console.log("Suggested settings: pageSize=2048, padding=1");
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Run tuner
|
|
127
|
+
const settings = pickAtlasSettingsFromSamples(allSamples, { candidates: [1024, 2048, 4096], paddings: [0, 1, 2, 3] });
|
|
128
|
+
console.log("Tuner result:", settings);
|
|
129
|
+
console.log("");
|
|
130
|
+
console.log("If you want to apply these settings to the MaxRects packer in-code, the recommended values are:");
|
|
131
|
+
console.log(` pageSize: ${settings.pageSize}`);
|
|
132
|
+
console.log(` padding: ${settings.padding}`);
|
|
133
|
+
console.log(`Estimated pages: ${settings.estimatedPages}, wastedRatio: ${settings.wastedRatio.toFixed(3)}`);
|
|
134
|
+
console.log("");
|
|
135
|
+
console.log("To apply, update the MaxRects packer defaults in src/pdf/font/glyph-atlas-maxrects.ts (constructor or export) or pass these values when constructing the packer.");
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
run().catch((err) => {
|
|
139
|
+
console.error("Error running tuner script:", err);
|
|
140
|
+
process.exit(1);
|
|
141
|
+
});
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Top 10 arquivos .ts por numero de linhas (recursivo, com progresso)
|
|
2
|
+
$Path = "." # diretorio inicial
|
|
3
|
+
$Top = 10 # quantidade a exibir
|
|
4
|
+
$Pattern = "*.ts"
|
|
5
|
+
$SkipPattern = '(\\|/)(?:node_modules|dist|\.git|bin|obj|\.venv|\.tox)(\\|/)'
|
|
6
|
+
|
|
7
|
+
Write-Host "Buscando arquivos $Pattern em $Path..." -ForegroundColor Cyan
|
|
8
|
+
|
|
9
|
+
# filtra apenas .ts e ignora pastas grandes
|
|
10
|
+
$files = Get-ChildItem -LiteralPath $Path -Recurse -File -Filter $Pattern -Force |
|
|
11
|
+
Where-Object { $_.FullName -notmatch $SkipPattern }
|
|
12
|
+
|
|
13
|
+
$total = $files.Count
|
|
14
|
+
|
|
15
|
+
$i = 0
|
|
16
|
+
$results = New-Object System.Collections.Generic.List[object]
|
|
17
|
+
|
|
18
|
+
foreach ($f in $files) {
|
|
19
|
+
$i++
|
|
20
|
+
Write-Progress -Activity "Contando linhas..." -Status $f.FullName -PercentComplete (($i / $total) * 100)
|
|
21
|
+
try {
|
|
22
|
+
$lineCount = [int]([System.Linq.Enumerable]::Count([System.IO.File]::ReadLines($f.FullName)))
|
|
23
|
+
$results.Add([pscustomobject]@{
|
|
24
|
+
Lines = $lineCount
|
|
25
|
+
SizeBytes = $f.Length
|
|
26
|
+
Path = $f.FullName
|
|
27
|
+
})
|
|
28
|
+
} catch {
|
|
29
|
+
Write-Warning "Falha ao ler: $($f.FullName) -> $($_.Exception.Message)"
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
Write-Progress -Activity "Contando linhas..." -Completed
|
|
34
|
+
Write-Host "`nTop $Top arquivos $Pattern por numero de linhas:`n" -ForegroundColor Green
|
|
35
|
+
|
|
36
|
+
$results |
|
|
37
|
+
Sort-Object Lines -Descending |
|
|
38
|
+
Select-Object -First $Top |
|
|
39
|
+
Format-Table Lines, SizeBytes, Path -AutoSize
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# Top 10 arquivos .ts por número de linhas (recursivo, com progresso)
|
|
4
|
+
PATH="."
|
|
5
|
+
TOP=10
|
|
6
|
+
PATTERN="*.ts"
|
|
7
|
+
SKIP_PATTERN="(node_modules|dist|\.git|bin|obj|\.venv|\.tox)"
|
|
8
|
+
|
|
9
|
+
echo "🔍 Buscando arquivos $PATTERN em $PATH..."
|
|
10
|
+
|
|
11
|
+
# filtra apenas .ts e ignora pastas grandes
|
|
12
|
+
files=$(find "$PATH" -type f -name "$PATTERN" 2>/dev/null | grep -v -E "$SKIP_PATTERN")
|
|
13
|
+
|
|
14
|
+
total=$(echo "$files" | wc -l)
|
|
15
|
+
if [ "$total" -eq 0 ]; then
|
|
16
|
+
echo "Nenhum arquivo $PATTERN encontrado (verifique filtros)."
|
|
17
|
+
exit 1
|
|
18
|
+
fi
|
|
19
|
+
|
|
20
|
+
i=0
|
|
21
|
+
temp=$(mktemp)
|
|
22
|
+
|
|
23
|
+
echo "$files" | while read -r f; do
|
|
24
|
+
i=$((i+1))
|
|
25
|
+
echo -ne "Contando linhas... $i/$total\r"
|
|
26
|
+
lines=$(wc -l < "$f" 2>/dev/null || echo 0)
|
|
27
|
+
size=$(stat -c%s "$f" 2>/dev/null || echo 0)
|
|
28
|
+
echo "$lines|$size|$f" >> "$temp"
|
|
29
|
+
done
|
|
30
|
+
|
|
31
|
+
echo ""
|
|
32
|
+
echo "📊 Top $TOP arquivos $PATTERN por número de linhas:"
|
|
33
|
+
echo ""
|
|
34
|
+
|
|
35
|
+
sort -nr "$temp" | head -n $TOP | awk -F'|' '{printf "%-10s %-10s %s\n", $1, $2, $3}'
|
|
36
|
+
|
|
37
|
+
rm "$temp"
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
param(
|
|
2
|
+
# Caminho da fonte (TTF/OTF/WOFF/WOFF2)
|
|
3
|
+
[Parameter(Mandatory = $true)]
|
|
4
|
+
[string]$File,
|
|
5
|
+
|
|
6
|
+
# ttx (CLI da FontTools)
|
|
7
|
+
[string]$Ttx = "ttx",
|
|
8
|
+
|
|
9
|
+
# Nome base do arquivo de saída TTX (sem ou com .ttx)
|
|
10
|
+
# O script vai adicionar automaticamente o sufixo com o nome da fonte.
|
|
11
|
+
[string]$OutFile = "font_dump.ttx",
|
|
12
|
+
|
|
13
|
+
# Formato da saída do script
|
|
14
|
+
# xml = só gera TTX XML (default)
|
|
15
|
+
# json = converte o XML inteiro pra JSON
|
|
16
|
+
# fulljson = JSON completo sem compressão
|
|
17
|
+
# name = só tabela name (metadados)
|
|
18
|
+
# cmap = só cmap
|
|
19
|
+
# metrics = só head / hhea / OS/2
|
|
20
|
+
[ValidateSet("xml", "json", "fulljson", "name", "cmap", "metrics")]
|
|
21
|
+
[string]$Format = "xml",
|
|
22
|
+
|
|
23
|
+
# Forçar overwrite
|
|
24
|
+
[switch]$Force
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
### 1. Resolve paths
|
|
28
|
+
$fullPath = (Resolve-Path $File).Path
|
|
29
|
+
|
|
30
|
+
# Nome da fonte baseado no arquivo (sem extensão)
|
|
31
|
+
$fontBaseName = [System.IO.Path]::GetFileNameWithoutExtension($fullPath)
|
|
32
|
+
|
|
33
|
+
# Se o usuário passou um caminho com diretório em $OutFile, respeita.
|
|
34
|
+
# Caso contrário, usa o diretório do script.
|
|
35
|
+
$outDir = Split-Path -Path $OutFile -Parent
|
|
36
|
+
if ([string]::IsNullOrWhiteSpace($outDir)) {
|
|
37
|
+
$outDir = $PSScriptRoot
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
$outName = [System.IO.Path]::GetFileName($OutFile)
|
|
41
|
+
|
|
42
|
+
# Se não tiver extensão, assume .ttx
|
|
43
|
+
$outBase = [System.IO.Path]::GetFileNameWithoutExtension($outName)
|
|
44
|
+
$outExt = [System.IO.Path]::GetExtension($outName)
|
|
45
|
+
if ([string]::IsNullOrWhiteSpace($outExt)) {
|
|
46
|
+
$outExt = ".ttx"
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
# Monta o nome final com sufixo da fonte
|
|
50
|
+
$finalOutName = "{0}-{1}{2}" -f $outBase, $fontBaseName, $outExt
|
|
51
|
+
$ttxOut = Join-Path $outDir $finalOutName
|
|
52
|
+
|
|
53
|
+
if ((Test-Path $ttxOut) -and (-not $Force)) {
|
|
54
|
+
Write-Output "[ERROR] Output file already exists: $ttxOut"
|
|
55
|
+
Write-Output "Use -Force to overwrite."
|
|
56
|
+
exit 1
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if ($Force -and (Test-Path $ttxOut)) {
|
|
60
|
+
Remove-Item $ttxOut -Force
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
Write-Output "[INFO] Generating TTX to: $ttxOut"
|
|
64
|
+
|
|
65
|
+
### 2. Gera o TTX (XML)
|
|
66
|
+
$cmd = "$Ttx -o `"$ttxOut`" `"$fullPath`" 2>&1"
|
|
67
|
+
$output = Invoke-Expression $cmd
|
|
68
|
+
|
|
69
|
+
if (-not (Test-Path $ttxOut)) {
|
|
70
|
+
Write-Output "[ERROR] Failed to generate TTX dump."
|
|
71
|
+
Write-Output $output
|
|
72
|
+
exit 1
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
### 3. Se o usuário pediu só XML
|
|
76
|
+
if ($Format -eq "xml") {
|
|
77
|
+
Write-Output "[DUMP] $((Resolve-Path $ttxOut).Path)"
|
|
78
|
+
exit 0
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
### 4. Carrega XML como objeto
|
|
82
|
+
[xml]$xml = Get-Content $ttxOut
|
|
83
|
+
|
|
84
|
+
### 5. Funções auxiliares
|
|
85
|
+
function Convert-ToJsonCompact($obj) {
|
|
86
|
+
return ($obj | ConvertTo-Json -Depth 20 -Compress)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function Convert-ToJsonPretty($obj) {
|
|
90
|
+
return ($obj | ConvertTo-Json -Depth 20)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
### 6. Modos especializados
|
|
94
|
+
switch ($Format) {
|
|
95
|
+
|
|
96
|
+
"json" {
|
|
97
|
+
$json = Convert-ToJsonCompact $xml
|
|
98
|
+
Write-Output $json
|
|
99
|
+
exit 0
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
"fulljson" {
|
|
103
|
+
$json = Convert-ToJsonPretty $xml
|
|
104
|
+
Write-Output $json
|
|
105
|
+
exit 0
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
"name" {
|
|
109
|
+
$name = $xml.ttFont.name
|
|
110
|
+
$json = Convert-ToJsonPretty $name
|
|
111
|
+
Write-Output $json
|
|
112
|
+
exit 0
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
"cmap" {
|
|
116
|
+
$cmap = $xml.ttFont.cmap
|
|
117
|
+
$json = Convert-ToJsonPretty $cmap
|
|
118
|
+
Write-Output $json
|
|
119
|
+
exit 0
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
"metrics" {
|
|
123
|
+
$metrics = [ordered]@{
|
|
124
|
+
head = $xml.ttFont.head
|
|
125
|
+
hhea = $xml.ttFont.hhea
|
|
126
|
+
os2 = $xml.ttFont."OS_2"
|
|
127
|
+
}
|
|
128
|
+
$json = Convert-ToJsonPretty $metrics
|
|
129
|
+
Write-Output $json
|
|
130
|
+
exit 0
|
|
131
|
+
}
|
|
132
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser entrypoint: minimal surface that wires the BrowserEnvironment.
|
|
3
|
+
* Expect callers to provide HTML/CSS strings and optional fontConfig with preloaded ArrayBuffers.
|
|
4
|
+
*/
|
|
5
|
+
import { BrowserEnvironment } from "./environment/browser-environment.js";
|
|
6
|
+
import { setGlobalEnvironment } from "./environment/global.js";
|
|
7
|
+
import type { RenderHtmlOptions } from "./html-to-pdf.js";
|
|
8
|
+
import { renderHtmlToPdf } from "./html-to-pdf.js";
|
|
9
|
+
|
|
10
|
+
export async function renderHtmlToPdfBrowser(options: Omit<RenderHtmlOptions, "environment">): Promise<Uint8Array> {
|
|
11
|
+
const environment = new BrowserEnvironment();
|
|
12
|
+
setGlobalEnvironment(environment);
|
|
13
|
+
return renderHtmlToPdf({ ...options, environment });
|
|
14
|
+
}
|