From 4f69aef17cac30fb6e0852a252a2085c534c385d Mon Sep 17 00:00:00 2001 From: krflol Date: Tue, 27 Oct 2026 07:24:24 -0500 Subject: [PATCH] Fix nested quotations in the browser, React and Vue starters --- .github/workflows/browser-starter.yml | 4 +- .github/workflows/react-starter.yml | 4 +- .github/workflows/vue-starter.yml | 4 +- examples/browser/README.md | 4 +- examples/browser/package-lock.json | 8 +- examples/browser/package.json | 2 +- examples/react/README.md | 4 +- examples/react/package-lock.json | 8 +- examples/react/package.json | 2 +- examples/vue/README.md | 4 +- examples/vue/package-lock.json | 8 +- examples/vue/package.json | 2 +- tools/starter-engine-2.5.38.json | 63 ++++ tools/starter_engine_fixes.py | 38 ++- verification/starters-083.json | 443 ++++++++++++++++++++++++++ 15 files changed, 569 insertions(+), 29 deletions(-) create mode 100644 tools/starter-engine-2.5.38.json create mode 100644 verification/starters-083.json diff --git a/.github/workflows/browser-starter.yml b/.github/workflows/browser-starter.yml index bab888c..533997e 100644 --- a/.github/workflows/browser-starter.yml +++ b/.github/workflows/browser-starter.yml @@ -3,9 +3,9 @@ name: Browser starter on: push: branches: [main] - paths: ['examples/browser/**', 'tools/check-browser-starter.py', 'tools/browser-requirements.txt', 'tools/starter_standard_fonts.py', 'tools/starter_engine_fixes.py', 'tools/starter-engine-2.5.22.json', 'tools/starter-engine-2.5.24.json', '.github/workflows/browser-starter.yml'] + paths: ['examples/browser/**', 'tools/check-browser-starter.py', 'tools/browser-requirements.txt', 'tools/starter_standard_fonts.py', 'tools/starter_engine_fixes.py', 'tools/starter-engine-2.5.22.json', 'tools/starter-engine-2.5.24.json', 'tools/starter-engine-2.5.38.json', '.github/workflows/browser-starter.yml'] pull_request: - paths: ['examples/browser/**', 'tools/check-browser-starter.py', 'tools/browser-requirements.txt', 'tools/starter_standard_fonts.py', 'tools/starter_engine_fixes.py', 'tools/starter-engine-2.5.22.json', 'tools/starter-engine-2.5.24.json', '.github/workflows/browser-starter.yml'] + paths: ['examples/browser/**', 'tools/check-browser-starter.py', 'tools/browser-requirements.txt', 'tools/starter_standard_fonts.py', 'tools/starter_engine_fixes.py', 'tools/starter-engine-2.5.22.json', 'tools/starter-engine-2.5.24.json', 'tools/starter-engine-2.5.38.json', '.github/workflows/browser-starter.yml'] workflow_dispatch: permissions: diff --git a/.github/workflows/react-starter.yml b/.github/workflows/react-starter.yml index cafc9f3..2fff3ee 100644 --- a/.github/workflows/react-starter.yml +++ b/.github/workflows/react-starter.yml @@ -3,9 +3,9 @@ name: React starter on: push: branches: [main] - paths: ['examples/react/**', 'tools/check-react-starter.py', 'tools/check-react-development.py', 'tools/prepare-react-check.mjs', 'tools/react_component_checks.py', 'tools/browser-requirements.txt', 'tools/starter_standard_fonts.py', 'tools/starter_engine_fixes.py', 'tools/starter-engine-2.5.22.json', 'tools/starter-engine-2.5.24.json', '.github/workflows/react-starter.yml'] + paths: ['examples/react/**', 'tools/check-react-starter.py', 'tools/check-react-development.py', 'tools/prepare-react-check.mjs', 'tools/react_component_checks.py', 'tools/browser-requirements.txt', 'tools/starter_standard_fonts.py', 'tools/starter_engine_fixes.py', 'tools/starter-engine-2.5.22.json', 'tools/starter-engine-2.5.24.json', 'tools/starter-engine-2.5.38.json', '.github/workflows/react-starter.yml'] pull_request: - paths: ['examples/react/**', 'tools/check-react-starter.py', 'tools/check-react-development.py', 'tools/prepare-react-check.mjs', 'tools/react_component_checks.py', 'tools/browser-requirements.txt', 'tools/starter_standard_fonts.py', 'tools/starter_engine_fixes.py', 'tools/starter-engine-2.5.22.json', 'tools/starter-engine-2.5.24.json', '.github/workflows/react-starter.yml'] + paths: ['examples/react/**', 'tools/check-react-starter.py', 'tools/check-react-development.py', 'tools/prepare-react-check.mjs', 'tools/react_component_checks.py', 'tools/browser-requirements.txt', 'tools/starter_standard_fonts.py', 'tools/starter_engine_fixes.py', 'tools/starter-engine-2.5.22.json', 'tools/starter-engine-2.5.24.json', 'tools/starter-engine-2.5.38.json', '.github/workflows/react-starter.yml'] workflow_dispatch: permissions: diff --git a/.github/workflows/vue-starter.yml b/.github/workflows/vue-starter.yml index 87a53c0..960276b 100644 --- a/.github/workflows/vue-starter.yml +++ b/.github/workflows/vue-starter.yml @@ -3,9 +3,9 @@ name: Vue starter on: push: branches: [main] - paths: ['examples/vue/**', 'tools/check-vue-starter.py', 'tools/prepare-vue-check.mjs', 'tools/browser-requirements.txt', 'tools/starter_standard_fonts.py', 'tools/starter_engine_fixes.py', 'tools/starter-engine-2.5.22.json', 'tools/starter-engine-2.5.24.json', '.github/workflows/vue-starter.yml'] + paths: ['examples/vue/**', 'tools/check-vue-starter.py', 'tools/prepare-vue-check.mjs', 'tools/browser-requirements.txt', 'tools/starter_standard_fonts.py', 'tools/starter_engine_fixes.py', 'tools/starter-engine-2.5.22.json', 'tools/starter-engine-2.5.24.json', 'tools/starter-engine-2.5.38.json', '.github/workflows/vue-starter.yml'] pull_request: - paths: ['examples/vue/**', 'tools/check-vue-starter.py', 'tools/prepare-vue-check.mjs', 'tools/browser-requirements.txt', 'tools/starter_standard_fonts.py', 'tools/starter_engine_fixes.py', 'tools/starter-engine-2.5.22.json', 'tools/starter-engine-2.5.24.json', '.github/workflows/vue-starter.yml'] + paths: ['examples/vue/**', 'tools/check-vue-starter.py', 'tools/prepare-vue-check.mjs', 'tools/browser-requirements.txt', 'tools/starter_standard_fonts.py', 'tools/starter_engine_fixes.py', 'tools/starter-engine-2.5.22.json', 'tools/starter-engine-2.5.24.json', 'tools/starter-engine-2.5.38.json', '.github/workflows/vue-starter.yml'] workflow_dispatch: permissions: diff --git a/examples/browser/README.md b/examples/browser/README.md index 3873d4b..98754e4 100644 --- a/examples/browser/README.md +++ b/examples/browser/README.md @@ -63,8 +63,8 @@ explains CSP, custom assets, structured errors, and browser worker lifecycle lim ## Versions and verification -The lockfile pins Fullbleed npm 0.8.2 / engine 2.5.37 and Vite 8.3.2. -The browser SDK is covered by the [versioned release evidence](https://github.com/fullbleed-engine/fullbleed-node/releases/tag/v0.8.2). +The lockfile pins Fullbleed npm 0.8.3 / engine 2.5.38 and Vite 8.3.2. +The browser SDK is covered by the [versioned release evidence](https://github.com/fullbleed-engine/fullbleed-node/releases/tag/v0.8.3). The repository's starter check builds this app, serves it below `/nested/demo/`, downloads actual PDFs, checks their text and page size, exercises editing and cancellation, and captures desktop/mobile screenshots. Playwright WebKit is not diff --git a/examples/browser/package-lock.json b/examples/browser/package-lock.json index 056f094..4227cdd 100644 --- a/examples/browser/package-lock.json +++ b/examples/browser/package-lock.json @@ -8,7 +8,7 @@ "name": "fullbleed-browser-starter", "version": "1.0.0", "dependencies": { - "fullbleed": "0.8.2" + "fullbleed": "0.8.3" }, "devDependencies": { "vite": "8.3.2" @@ -357,9 +357,9 @@ } }, "node_modules/fullbleed": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/fullbleed/-/fullbleed-0.8.2.tgz", - "integrity": "sha512-OkqQzTbLE7JLx4nwriQEwqHiowLFx3j4AWtPYeSlP+dCdTd75oaBvS/h2VJj0WBI4zP2U9lE0Z6wH7bTASfIOA==", + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/fullbleed/-/fullbleed-0.8.3.tgz", + "integrity": "sha512-Df9VSjsLEyygxvQTiFwgwndEyspzy6AIvLkbDm0IgIYSfXXuGy+C2MJWTxpy21hp6NwWVg6MHKx7mYTJUA7I6g==", "license": "MIT", "dependencies": { "@bjorn3/browser_wasi_shim": "0.4.2" diff --git a/examples/browser/package.json b/examples/browser/package.json index 0617396..55c079e 100644 --- a/examples/browser/package.json +++ b/examples/browser/package.json @@ -10,6 +10,6 @@ "build": "npm run assets && vite build", "preview": "vite preview --host 127.0.0.1" }, - "dependencies": { "fullbleed": "0.8.2" }, + "dependencies": { "fullbleed": "0.8.3" }, "devDependencies": { "vite": "8.3.2" } } diff --git a/examples/react/README.md b/examples/react/README.md index 914da4f..a74646e 100644 --- a/examples/react/README.md +++ b/examples/react/README.md @@ -54,7 +54,7 @@ See [supported print CSS](https://docs.fullbleed.dev/css-coverage/) for layout f ## Reuse the hook Copy `src/usePdfPreview.ts` and the `src/documents/` directory into your client application, install -`fullbleed@0.8.2`, and copy the runtime with +`fullbleed@0.8.3`, and copy the runtime with `npx fullbleed-browser-assets public/fullbleed`. Keep the document input stable with `useMemo` so ordinary component updates do not schedule another render: @@ -117,7 +117,7 @@ WebAssembly, and Web Crypto are required. ## Versions and verification -The lockfile pins Fullbleed 0.8.2 / engine 2.5.37, React 19.3.0, TypeScript 7.0.2, +The lockfile pins Fullbleed 0.8.3 / engine 2.5.38, React 19.3.0, TypeScript 7.0.2, and Vite 8.3.2. No Fullbleed engine or package release is needed for this example. The repository's `React starter` workflow builds the locked project and checks diff --git a/examples/react/package-lock.json b/examples/react/package-lock.json index cf93dad..7e72485 100644 --- a/examples/react/package-lock.json +++ b/examples/react/package-lock.json @@ -8,7 +8,7 @@ "name": "fullbleed-react-starter", "version": "1.0.0", "dependencies": { - "fullbleed": "0.8.2", + "fullbleed": "0.8.3", "react": "19.3.0", "react-dom": "19.3.0" }, @@ -838,9 +838,9 @@ } }, "node_modules/fullbleed": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/fullbleed/-/fullbleed-0.8.2.tgz", - "integrity": "sha512-OkqQzTbLE7JLx4nwriQEwqHiowLFx3j4AWtPYeSlP+dCdTd75oaBvS/h2VJj0WBI4zP2U9lE0Z6wH7bTASfIOA==", + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/fullbleed/-/fullbleed-0.8.3.tgz", + "integrity": "sha512-Df9VSjsLEyygxvQTiFwgwndEyspzy6AIvLkbDm0IgIYSfXXuGy+C2MJWTxpy21hp6NwWVg6MHKx7mYTJUA7I6g==", "license": "MIT", "dependencies": { "@bjorn3/browser_wasi_shim": "0.4.2" diff --git a/examples/react/package.json b/examples/react/package.json index 088a60d..3dceed8 100644 --- a/examples/react/package.json +++ b/examples/react/package.json @@ -14,7 +14,7 @@ "preview": "vite preview --host 127.0.0.1" }, "dependencies": { - "fullbleed": "0.8.2", + "fullbleed": "0.8.3", "react": "19.3.0", "react-dom": "19.3.0" }, diff --git a/examples/vue/README.md b/examples/vue/README.md index 97ede14..f98c402 100644 --- a/examples/vue/README.md +++ b/examples/vue/README.md @@ -43,7 +43,7 @@ Use [supported print CSS](https://docs.fullbleed.dev/css-coverage/). ## Reuse the composable Copy `src/usePdfPreview.ts` into your client application, install -`fullbleed@0.8.2`, and copy the runtime with +`fullbleed@0.8.3`, and copy the runtime with `npx fullbleed-browser-assets public/fullbleed`: ```vue @@ -111,7 +111,7 @@ WebAssembly, and Web Crypto are required. ## Versions and verification -The lockfile pins Fullbleed 0.8.2 / engine 2.5.37, Vue 3.5.43, TypeScript 6.0.3, +The lockfile pins Fullbleed 0.8.3 / engine 2.5.38, Vue 3.5.43, TypeScript 6.0.3, and Vite 8.3.2. TypeScript 6 is used because the pinned `vue-tsc` still needs TypeScript's JavaScript compiler entry; TypeScript 7 does not expose it. diff --git a/examples/vue/package-lock.json b/examples/vue/package-lock.json index e6a86b8..d9c9bdf 100644 --- a/examples/vue/package-lock.json +++ b/examples/vue/package-lock.json @@ -9,7 +9,7 @@ "version": "1.0.0", "license": "MIT", "dependencies": { - "fullbleed": "0.8.2", + "fullbleed": "0.8.3", "vue": "3.5.43" }, "devDependencies": { @@ -683,9 +683,9 @@ } }, "node_modules/fullbleed": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/fullbleed/-/fullbleed-0.8.2.tgz", - "integrity": "sha512-OkqQzTbLE7JLx4nwriQEwqHiowLFx3j4AWtPYeSlP+dCdTd75oaBvS/h2VJj0WBI4zP2U9lE0Z6wH7bTASfIOA==", + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/fullbleed/-/fullbleed-0.8.3.tgz", + "integrity": "sha512-Df9VSjsLEyygxvQTiFwgwndEyspzy6AIvLkbDm0IgIYSfXXuGy+C2MJWTxpy21hp6NwWVg6MHKx7mYTJUA7I6g==", "license": "MIT", "dependencies": { "@bjorn3/browser_wasi_shim": "0.4.2" diff --git a/examples/vue/package.json b/examples/vue/package.json index 9b4085c..19f7ab5 100644 --- a/examples/vue/package.json +++ b/examples/vue/package.json @@ -15,7 +15,7 @@ "preview": "vite preview --host 127.0.0.1" }, "dependencies": { - "fullbleed": "0.8.2", + "fullbleed": "0.8.3", "vue": "3.5.43" }, "devDependencies": { diff --git a/tools/starter-engine-2.5.38.json b/tools/starter-engine-2.5.38.json new file mode 100644 index 0000000..1a644ce --- /dev/null +++ b/tools/starter-engine-2.5.38.json @@ -0,0 +1,63 @@ +{ + "schema": "fullbleed.starter.engine-fixes.v1", + "upstreamRelease": "2.5.38", + "source": { + "path": "test/fixtures/generated-quotes-2.5.38.json", + "sha256": "892cf0862fe14d639cdb1f639ce755ce9a6fe5f88622217690da3da762ff4015", + "url": "https://github.com/fullbleed-engine/fullbleed-node/blob/v0.8.3/test/fixtures/generated-quotes-2.5.38.json" + }, + "cases": [ + { + "name": "quote-inline-nested", + "family": "quotation", + "html": "

Record Ada

outerinnerend", + "css": "@page { size: 600px 400px; margin: 12px }\nbody { margin: 0; font-family: Inter; font-size: 20px; quotes: \"[\" \"]\" \"{\" \"}\" }\n.q::before { content: open-quote } .q::after { content: close-quote }\n.open::before { content: no-open-quote } .after::after { content: no-open-quote }\n.close::before { content: no-close-quote } .closeafter::after { content: no-close-quote }\n.visibleclose::after { content: close-quote } .balanced::after { content: open-quote close-quote }\n.suppressed::before { display: none }\n", + "pages": 1, + "previewDpi": 96, + "previousEngineFails": false, + "expected": { + "text": "RecordAda[outer{inner}end]", + "pageSizePt": [ + 450, + 300 + ], + "minimumInkPixels": 100 + } + }, + { + "name": "quote-contents-nested", + "family": "quotation", + "html": "

Record Ada

outerinnerend", + "css": "@page { size: 600px 400px; margin: 12px }\nbody { margin: 0; font-family: Inter; font-size: 20px; quotes: \"[\" \"]\" \"{\" \"}\" }\n.q::before { content: open-quote } .q::after { content: close-quote }\n.open::before { content: no-open-quote } .after::after { content: no-open-quote }\n.close::before { content: no-close-quote } .closeafter::after { content: no-close-quote }\n.visibleclose::after { content: close-quote } .balanced::after { content: open-quote close-quote }\n.suppressed::before { display: none }\n", + "pages": 1, + "previewDpi": 96, + "previousEngineFails": true, + "expected": { + "text": "RecordAda[outer{inner}end]", + "pageSizePt": [ + 450, + 300 + ], + "minimumInkPixels": 100 + } + }, + { + "name": "quote-block-nested", + "family": "quotation", + "html": "

Record Ada

outerinnerend", + "css": "@page { size: 600px 400px; margin: 12px }\nbody { margin: 0; font-family: Inter; font-size: 20px; quotes: \"[\" \"]\" \"{\" \"}\" }\n.q::before { content: open-quote } .q::after { content: close-quote }\n.open::before { content: no-open-quote } .after::after { content: no-open-quote }\n.close::before { content: no-close-quote } .closeafter::after { content: no-close-quote }\n.visibleclose::after { content: close-quote } .balanced::after { content: open-quote close-quote }\n.suppressed::before { display: none }\n", + "pages": 1, + "previewDpi": 96, + "previousEngineFails": true, + "expected": { + "text": "RecordAda[outer{inner}end]", + "pageSizePt": [ + 450, + 300 + ], + "minimumInkPixels": 100 + } + } + ], + "scope": "Three reviewed quotation inputs through the actual starter editors and downloads. One healthy control and two earlier engine failures; no full CSS or arbitrary-template parity claim." +} diff --git a/tools/starter_engine_fixes.py b/tools/starter_engine_fixes.py index 3bbacad..acdec20 100644 --- a/tools/starter_engine_fixes.py +++ b/tools/starter_engine_fixes.py @@ -19,6 +19,7 @@ FIXTURES = Path(__file__).with_name('starter-engine-2.5.22.json') CURRENT_FIXTURES = Path(__file__).with_name('starter-engine-2.5.24.json') +QUOTATION_FIXTURES = Path(__file__).with_name('starter-engine-2.5.38.json') def decoration_widths(page, reader): @@ -64,6 +65,37 @@ def inspect_outputs(case, pdf_path, preview_path, out, check): if 'pdfSha256' in expected: check(name + ': PDF matches the released source/control fixture', hashlib.sha256(pdf_path.read_bytes()).hexdigest() == expected['pdfSha256']) + if case['family'] == 'quotation': + check(name + ': print CSS preserves the expected page geometry', + [float(reader.pages[0].mediabox.width), float(reader.pages[0].mediabox.height)] == expected['pageSizePt']) + document = pdfium.PdfDocument(pdf_path) + try: + pdf_page = document[0] + try: + text_page = pdf_page.get_textpage() + try: + independent_text = re.sub(r'\s+', '', text_page.get_text_range()) + finally: + text_page.close() + bitmap = pdf_page.render(scale=case['previewDpi'] / 72) + try: + raster = bitmap.to_pil().convert('RGB') + raster.save(out / (name + '-pdfium.png')) + finally: + bitmap.close() + finally: + pdf_page.close() + finally: + document.close() + check(name + ': a second PDF reader finds the exact quotation text', independent_text == expected['text']) + with Image.open(preview_path) as displayed: + preview = displayed.convert('RGB') + ink = {source: sum(image.convert('L').histogram()[:200]) + for source, image in [('pdfium', raster), ('preview', preview)]} + check(name + ': independent PDF render and displayed preview contain visible ink', + all(count >= expected['minimumInkPixels'] for count in ink.values())) + record.update(pdfiumText=independent_text, inkPixels=ink, + independentRasterSha256=hashlib.sha256((out / (name + '-pdfium.png')).read_bytes()).hexdigest()) if case['family'] == 'decoration': widths = decoration_widths(reader.pages[0], reader) check(name + ': decoration stroke count matches', len(widths) == expected['strokes']) @@ -108,6 +140,7 @@ def verify_engine_fixes(page, out, check, ready, *, manual=False, """Paste focused cases, inspect actual downloads, then restore the editor.""" fixtures = json.loads(FIXTURES.read_text(encoding='utf-8')) current = json.loads(CURRENT_FIXTURES.read_text(encoding='utf-8')) + quotations = json.loads(QUOTATION_FIXTURES.read_text(encoding='utf-8')) evidence = out / 'engine-fixes' evidence.mkdir(exist_ok=False) original_html = page.locator(html_selector).input_value() @@ -119,7 +152,7 @@ def edit(html, css): page.locator(html_selector).fill(html) page.locator(css_selector).fill(css) records = [] - for case in [*fixtures['cases'], *current['cases']]: + for case in [*fixtures['cases'], *current['cases'], *quotations['cases']]: name = case['name'] (evidence / (name + '.html')).write_text(case['html'], encoding='utf-8', newline='\n') (evidence / (name + '.css')).write_text(case['css'], encoding='utf-8', newline='\n') @@ -151,7 +184,8 @@ def edit(html, css): ready() result = {'ok': True, 'fixturesSha256': hashlib.sha256(FIXTURES.read_bytes()).hexdigest(), 'additionalFixturesSha256': hashlib.sha256(CURRENT_FIXTURES.read_bytes()).hexdigest(), + 'quotationFixturesSha256': hashlib.sha256(QUOTATION_FIXTURES.read_bytes()).hexdigest(), 'readers': {package: version(package) for package in ['pypdf', 'pypdfium2', 'pillow']}, - 'scope': fixtures['scope'] + ' ' + current['scope'], 'cases': records} + 'scope': fixtures['scope'] + ' ' + current['scope'] + ' ' + quotations['scope'], 'cases': records} (evidence / 'verification.json').write_text(json.dumps(result, indent=2) + '\n', encoding='utf-8', newline='\n') return result diff --git a/verification/starters-083.json b/verification/starters-083.json new file mode 100644 index 0000000..be1d753 --- /dev/null +++ b/verification/starters-083.json @@ -0,0 +1,443 @@ +{ + "ok": true, + "checkedAt": "2026-10-27T12:23:27.346667+00:00", + "package": "0.8.3", + "engine": "2.5.38", + "packageIntegrity": "sha512-Df9VSjsLEyygxvQTiFwgwndEyspzy6AIvLkbDm0IgIYSfXXuGy+C2MJWTxpy21hp6NwWVg6MHKx7mYTJUA7I6g==", + "publicTarballSha256": "9bdfd44de150e609819f9e46bf1bcd9c4bda4cdedc09aa477b593003f1e24b55", + "sourceFiles": { + "examples/browser/README.md": "4c3b962ac8e5ae81ac2d2234103755e9fb60b4b138f36ee3f00a5957a7b93a2e", + "examples/browser/package.json": "68c2577262ad8a92c81f3ec3ee68bebc3c9ca44fb0885ff339d9c663f19e6958", + "examples/browser/package-lock.json": "6f18c206a1f6fe030a94b59f987f162e217d2f5cdeaeff6680bbebfc26fe4341", + ".github/workflows/browser-starter.yml": "7c171044253314af2cc1681fdf37911b7bba36aa2f6aeccadf442043f7264d17", + "examples/react/README.md": "3143a9bab919265d69177d71f92bfc5e79cda1f3e3007add9a87084bf60a7193", + "examples/react/package.json": "7558b849e48ecbc214f636f2f97b1baff491dae3916fd2e4472ec71ea7df3651", + "examples/react/package-lock.json": "13611c811da54fbb4b0d4269b1362525607f4dd94fd6b102eef6d66ed056b964", + ".github/workflows/react-starter.yml": "38ecfb431c7180dbb84e6290ac0d370c646d4972d78e7f13443bc560c3d1cc9a", + "examples/vue/README.md": "829eb5e93811627816b8a3fcf7eaa4df1c47cb1eac3a890143c2df6973fe24dc", + "examples/vue/package.json": "92f6a541523f034864d87044d700977a6d302163e57fa77f5a5177179309d7b0", + "examples/vue/package-lock.json": "94621bff307a11a2ce43a7881f076a665ccfd7c40bcca6c6075c92a77d6db7ca", + ".github/workflows/vue-starter.yml": "d3d2438e9a527dd9b42923d371c89f82c9ff526fc0a72634abf7ce6f4bf63111", + "tools/starter_engine_fixes.py": "972cdd86569513817424758a8a5ac6a9998ed2c4988500219763b126485b2932", + "tools/starter-engine-2.5.38.json": "a3c43265bf4a1d749210bb3842a4a8ebd94ea0bf9608ac247f3268ea9867117d" + }, + "installedPackageFiles": { + "browser": { + "files": 47, + "matchesPublicTarball": true + }, + "react": { + "files": 47, + "matchesPublicTarball": true + }, + "vue": { + "files": 47, + "matchesPublicTarball": true + } + }, + "localVerification": { + "browser": { + "browser": "156.0.8078.47", + "checks": 94, + "documents": [ + { + "name": "invoice", + "filename": "invoice-NS-1042.pdf", + "pages": 1, + "sha256": "3078d155f30536f5ad721f7be3c241cd78661ae41249131fc0fd65f37f23e408" + }, + { + "name": "color-only", + "filename": "invoice-NS-1042.pdf", + "pages": 1, + "sha256": "a2b69ba41f7ad4c9bcbd38d803a46e70f0b9ccacd90ffbab5b0f7d87ffca5e4b" + }, + { + "name": "customized", + "filename": "invoice-TEST-2042.pdf", + "pages": 1, + "sha256": "31ff314b44a6f13534cc383e0cf24929f0695c1dd3d84769dedf8828c6486a93" + }, + { + "name": "edited", + "filename": "invoice-TEST-2042.pdf", + "pages": 1, + "sha256": "fecff59c1bfd6b59de2f0fb56965a5668023b3b88e64b5c6c30f95875592c4b2" + }, + { + "name": "report", + "filename": "community-report.pdf", + "pages": 3, + "sha256": "80fc4306db1898688d846cfea4fb1b4ef5bf07713fe9301662143619441205b5" + }, + { + "name": "recovered", + "filename": "invoice-TEST-2042.pdf", + "pages": 1, + "sha256": "31ff314b44a6f13534cc383e0cf24929f0695c1dd3d84769dedf8828c6486a93" + } + ], + "quotationCases": [ + { + "name": "quote-inline-nested", + "pages": 1, + "text": "Record Ada\n[outer{inner}end]", + "probes": [], + "pdfiumText": "RecordAda[outer{inner}end]", + "inkPixels": { + "pdfium": 1695, + "preview": 1627 + }, + "independentRasterSha256": "63eebe27b3c8518dfc43e9e79ebb503200f4c49d44bde60f4119fd0004791311", + "pdfSha256": "0dd4e8e1cad03da49a74a2451d97180f5212c42262addff402e087c0796e32f9", + "previewSha256": "817be578ca49e67329b503bdee74f8d4d202319c8988e966419c4f8087d50cd1", + "suggestedFilename": "invoice-TEST-2042.pdf" + }, + { + "name": "quote-contents-nested", + "pages": 1, + "text": "Record Ada\n[\nouter\n{inner}\nend\n]", + "probes": [], + "pdfiumText": "RecordAda[outer{inner}end]", + "inkPixels": { + "pdfium": 1677, + "preview": 1613 + }, + "independentRasterSha256": "8a155f599e8ad72c1f83768d9935732c5af56bcb7d9676864c1b6495304a328b", + "pdfSha256": "658681c73d9f6cb8e942ac331a64d9e4cb7c70190b5a7d7a7258bd7028163585", + "previewSha256": "bb3a35f08897bcecceec9afb57439388e448681fca8513023d2bba908bd516f8", + "suggestedFilename": "invoice-TEST-2042.pdf" + }, + { + "name": "quote-block-nested", + "pages": 1, + "text": "Record Ada\n[outer{inner}end]", + "probes": [], + "pdfiumText": "RecordAda[outer{inner}end]", + "inkPixels": { + "pdfium": 1695, + "preview": 1635 + }, + "independentRasterSha256": "63eebe27b3c8518dfc43e9e79ebb503200f4c49d44bde60f4119fd0004791311", + "pdfSha256": "b032ca751718d12ec90f10d4934044f1ac1024b9731ba2c72c1529fe9f44e6e7", + "previewSha256": "28cfba86ea6182baccff1322dcb100279bf10eef965e33266b3baaabd41ccccf", + "suggestedFilename": "invoice-TEST-2042.pdf" + } + ], + "reportSha256": "2238f332be48b5155e5ede7eb7e020d10bbb1f8216e0a301d93e977e0fcf8eec", + "engineFixesReportSha256": "2c87ed1f2a284ffcefdd754957241c217fe9b249a74d9f6343693cab3c66d800" + }, + "react": { + "browser": "156.0.8078.47", + "checks": 143, + "documents": [ + { + "name": "component-invoice", + "pages": 1, + "filename": "invoice-NS-1042.pdf", + "sha256": "f2553f220e9d30e26df785a4ed251f07ff1e615afd3972a5c29c19a0c5fd3f6c", + "whitespace_normalized_text_checks": true + }, + { + "name": "component-paid", + "pages": 1, + "filename": "invoice-NS-1042.pdf", + "sha256": "91d8c8360fac37cd413fe669ed8f06650658b9ca01777129879207aac014d4c2", + "whitespace_normalized_text_checks": true + }, + { + "name": "component-edited", + "pages": 1, + "filename": "invoice-Ref-aBc-2042.pdf", + "sha256": "a664f9fd84af1d2354537645aa6b70dd9abe3ab762b8a9631047aab742b1297e", + "whitespace_normalized_text_checks": true + }, + { + "name": "component-empty", + "pages": 1, + "filename": "invoice-NS-1042.pdf", + "sha256": "cc1982eaea9dfa05b014cffea44644ecc2f4d33e8eb22ae6f6a501ab6d7f1248", + "whitespace_normalized_text_checks": true + }, + { + "name": "component-credit", + "pages": 1, + "filename": "invoice-NS-1042.pdf", + "sha256": "cd57b56ec26e86365ab0223656d7e21b1543c9fbf404e967f0aef2e9b98024e6", + "whitespace_normalized_text_checks": true + }, + { + "name": "component-long", + "pages": 3, + "filename": "invoice-NS-1042.pdf", + "sha256": "589210d6b5bb0684fdbf5dbf62c5e32742c7166d3a8cfc5ae304c430e08357a3", + "whitespace_normalized_text_checks": true + }, + { + "name": "invoice", + "pages": 1, + "filename": "invoice-NS-1042.pdf", + "sha256": "3078d155f30536f5ad721f7be3c241cd78661ae41249131fc0fd65f37f23e408", + "whitespace_normalized_text_checks": false + }, + { + "name": "manual", + "pages": 1, + "filename": "invoice-NS-1042.pdf", + "sha256": "1df9b1852ad96e07d00520d190140044f528b14047df6e30432e91a512be8883", + "whitespace_normalized_text_checks": false + }, + { + "name": "latest-input", + "pages": 1, + "filename": "invoice-REACT-2042.pdf", + "sha256": "fccdad8d56abef7206e5efefc716af2c44c717c0e1c3619827c6d27931ed76be", + "whitespace_normalized_text_checks": false + }, + { + "name": "edited-template", + "pages": 1, + "filename": "invoice-REACT-2042.pdf", + "sha256": "c1fe667a39ac3eaae3292c3a1fab1c466999e798a5ab0a4616b73689acc79880", + "whitespace_normalized_text_checks": false + }, + { + "name": "report", + "pages": 3, + "filename": "community-report.pdf", + "sha256": "80fc4306db1898688d846cfea4fb1b4ef5bf07713fe9301662143619441205b5", + "whitespace_normalized_text_checks": false + }, + { + "name": "recovered", + "pages": 1, + "filename": "invoice-REACT-2042.pdf", + "sha256": "fccdad8d56abef7206e5efefc716af2c44c717c0e1c3619827c6d27931ed76be", + "whitespace_normalized_text_checks": false + }, + { + "name": "remounted", + "pages": 1, + "filename": "invoice-NS-1042.pdf", + "sha256": "3078d155f30536f5ad721f7be3c241cd78661ae41249131fc0fd65f37f23e408", + "whitespace_normalized_text_checks": false + } + ], + "quotationCases": [ + { + "name": "quote-inline-nested", + "pages": 1, + "text": "Record Ada\n[outer{inner}end]", + "probes": [], + "pdfiumText": "RecordAda[outer{inner}end]", + "inkPixels": { + "pdfium": 1695, + "preview": 1627 + }, + "independentRasterSha256": "63eebe27b3c8518dfc43e9e79ebb503200f4c49d44bde60f4119fd0004791311", + "pdfSha256": "0dd4e8e1cad03da49a74a2451d97180f5212c42262addff402e087c0796e32f9", + "previewSha256": "817be578ca49e67329b503bdee74f8d4d202319c8988e966419c4f8087d50cd1", + "suggestedFilename": "invoice-REACT-2042.pdf" + }, + { + "name": "quote-contents-nested", + "pages": 1, + "text": "Record Ada\n[\nouter\n{inner}\nend\n]", + "probes": [], + "pdfiumText": "RecordAda[outer{inner}end]", + "inkPixels": { + "pdfium": 1677, + "preview": 1613 + }, + "independentRasterSha256": "8a155f599e8ad72c1f83768d9935732c5af56bcb7d9676864c1b6495304a328b", + "pdfSha256": "658681c73d9f6cb8e942ac331a64d9e4cb7c70190b5a7d7a7258bd7028163585", + "previewSha256": "bb3a35f08897bcecceec9afb57439388e448681fca8513023d2bba908bd516f8", + "suggestedFilename": "invoice-REACT-2042.pdf" + }, + { + "name": "quote-block-nested", + "pages": 1, + "text": "Record Ada\n[outer{inner}end]", + "probes": [], + "pdfiumText": "RecordAda[outer{inner}end]", + "inkPixels": { + "pdfium": 1695, + "preview": 1635 + }, + "independentRasterSha256": "63eebe27b3c8518dfc43e9e79ebb503200f4c49d44bde60f4119fd0004791311", + "pdfSha256": "b032ca751718d12ec90f10d4934044f1ac1024b9731ba2c72c1529fe9f44e6e7", + "previewSha256": "28cfba86ea6182baccff1322dcb100279bf10eef965e33266b3baaabd41ccccf", + "suggestedFilename": "invoice-REACT-2042.pdf" + } + ], + "reportSha256": "3ee01492fef2b3e7a1b50985880907c4b3793edd52d2e1f43d2bab52a4a447b5", + "engineFixesReportSha256": "752f852579f14efc27ac8044fb1cf4bffc504121779c8ef267ae6b55cd312e82" + }, + "vue": { + "browser": "156.0.8078.47", + "checks": 102, + "documents": [ + { + "name": "invoice", + "pages": 1, + "filename": "invoice-NS-1042.pdf", + "sha256": "3078d155f30536f5ad721f7be3c241cd78661ae41249131fc0fd65f37f23e408" + }, + { + "name": "manual", + "pages": 1, + "filename": "invoice-NS-1042.pdf", + "sha256": "1df9b1852ad96e07d00520d190140044f528b14047df6e30432e91a512be8883" + }, + { + "name": "latest-input", + "pages": 1, + "filename": "invoice-VUE-2042.pdf", + "sha256": "f63a42a366b08f4f054cca5594dbcd22510455ddfe2e9129623facfb8371e8ee" + }, + { + "name": "edited-template", + "pages": 1, + "filename": "invoice-VUE-2042.pdf", + "sha256": "071d2bd98b7b90b52aa5b60e74ce0934ef54d3c6032c222d7237786dc12fc953" + }, + { + "name": "report", + "pages": 3, + "filename": "community-report.pdf", + "sha256": "80fc4306db1898688d846cfea4fb1b4ef5bf07713fe9301662143619441205b5" + }, + { + "name": "outage-recovery", + "pages": 1, + "filename": "invoice-VUE-2042.pdf", + "sha256": "f63a42a366b08f4f054cca5594dbcd22510455ddfe2e9129623facfb8371e8ee" + }, + { + "name": "recovered", + "pages": 1, + "filename": "invoice-VUE-2042.pdf", + "sha256": "f63a42a366b08f4f054cca5594dbcd22510455ddfe2e9129623facfb8371e8ee" + }, + { + "name": "remounted", + "pages": 1, + "filename": "invoice-NS-1042.pdf", + "sha256": "3078d155f30536f5ad721f7be3c241cd78661ae41249131fc0fd65f37f23e408" + } + ], + "quotationCases": [ + { + "name": "quote-inline-nested", + "pages": 1, + "text": "Record Ada\n[outer{inner}end]", + "probes": [], + "pdfiumText": "RecordAda[outer{inner}end]", + "inkPixels": { + "pdfium": 1695, + "preview": 1627 + }, + "independentRasterSha256": "63eebe27b3c8518dfc43e9e79ebb503200f4c49d44bde60f4119fd0004791311", + "pdfSha256": "0dd4e8e1cad03da49a74a2451d97180f5212c42262addff402e087c0796e32f9", + "previewSha256": "817be578ca49e67329b503bdee74f8d4d202319c8988e966419c4f8087d50cd1", + "suggestedFilename": "invoice-VUE-2042.pdf" + }, + { + "name": "quote-contents-nested", + "pages": 1, + "text": "Record Ada\n[\nouter\n{inner}\nend\n]", + "probes": [], + "pdfiumText": "RecordAda[outer{inner}end]", + "inkPixels": { + "pdfium": 1677, + "preview": 1613 + }, + "independentRasterSha256": "8a155f599e8ad72c1f83768d9935732c5af56bcb7d9676864c1b6495304a328b", + "pdfSha256": "658681c73d9f6cb8e942ac331a64d9e4cb7c70190b5a7d7a7258bd7028163585", + "previewSha256": "bb3a35f08897bcecceec9afb57439388e448681fca8513023d2bba908bd516f8", + "suggestedFilename": "invoice-VUE-2042.pdf" + }, + { + "name": "quote-block-nested", + "pages": 1, + "text": "Record Ada\n[outer{inner}end]", + "probes": [], + "pdfiumText": "RecordAda[outer{inner}end]", + "inkPixels": { + "pdfium": 1695, + "preview": 1635 + }, + "independentRasterSha256": "63eebe27b3c8518dfc43e9e79ebb503200f4c49d44bde60f4119fd0004791311", + "pdfSha256": "b032ca751718d12ec90f10d4934044f1ac1024b9731ba2c72c1529fe9f44e6e7", + "previewSha256": "28cfba86ea6182baccff1322dcb100279bf10eef965e33266b3baaabd41ccccf", + "suggestedFilename": "invoice-VUE-2042.pdf" + } + ], + "reportSha256": "62f972db0e525132dde58c5b4dfef9b1028cfe54ae119b0794e589370882e991", + "engineFixesReportSha256": "23892b7f580cc677c9934f1090f0ffa8fdfe3de918ba7e4402156f8a1d79b05b" + } + }, + "unchangedPdfDownloadsFrom082": { + "browser": 6, + "react": 13, + "vue": 8 + }, + "retainedPublicControls": { + "browser": [ + { + "case": "inline-nested", + "beforeText": "RecordAda[outer{inner}end]", + "afterText": "RecordAda[outer{inner}end]", + "beforePdfSha256": "0dd4e8e1cad03da49a74a2451d97180f5212c42262addff402e087c0796e32f9", + "afterPdfSha256": "0dd4e8e1cad03da49a74a2451d97180f5212c42262addff402e087c0796e32f9", + "unchangedHealthyControl": true + }, + { + "case": "block-nested", + "beforeText": "RecordAda[outer[inner]end", + "afterText": "RecordAda[outer{inner}end]", + "beforePdfSha256": "8bea79d1eaf3493291ba303acc16dbdf59cf989836408ebe7e240eccd878dfec", + "afterPdfSha256": "b032ca751718d12ec90f10d4934044f1ac1024b9731ba2c72c1529fe9f44e6e7", + "unchangedHealthyControl": false + } + ], + "react": [ + { + "case": "inline-nested", + "beforeText": "RecordAda[outer{inner}end]", + "afterText": "RecordAda[outer{inner}end]", + "beforePdfSha256": "0dd4e8e1cad03da49a74a2451d97180f5212c42262addff402e087c0796e32f9", + "afterPdfSha256": "0dd4e8e1cad03da49a74a2451d97180f5212c42262addff402e087c0796e32f9", + "unchangedHealthyControl": true + }, + { + "case": "block-nested", + "beforeText": "RecordAda[outer[inner]end", + "afterText": "RecordAda[outer{inner}end]", + "beforePdfSha256": "8bea79d1eaf3493291ba303acc16dbdf59cf989836408ebe7e240eccd878dfec", + "afterPdfSha256": "b032ca751718d12ec90f10d4934044f1ac1024b9731ba2c72c1529fe9f44e6e7", + "unchangedHealthyControl": false + } + ], + "vue": [ + { + "case": "inline-nested", + "beforeText": "RecordAda[outer{inner}end]", + "afterText": "RecordAda[outer{inner}end]", + "beforePdfSha256": "0dd4e8e1cad03da49a74a2451d97180f5212c42262addff402e087c0796e32f9", + "afterPdfSha256": "0dd4e8e1cad03da49a74a2451d97180f5212c42262addff402e087c0796e32f9", + "unchangedHealthyControl": true + }, + { + "case": "block-nested", + "beforeText": "RecordAda[outer[inner]end", + "afterText": "RecordAda[outer{inner}end]", + "beforePdfSha256": "8bea79d1eaf3493291ba303acc16dbdf59cf989836408ebe7e240eccd878dfec", + "afterPdfSha256": "b032ca751718d12ec90f10d4934044f1ac1024b9731ba2c72c1529fe9f44e6e7", + "unchangedHealthyControl": false + } + ] + }, + "publicBeforeObservationSha256": "21b125227fe1652220f8a850749e645bcbaac35caf345c80d1de1833b6ede781", + "scope": "Locked public npm installation and actual browser, React and Vue production editors in Chrome on Windows. Nine quotation downloads pass, including three unchanged healthy controls, and 27 previous document downloads remain byte-identical. The repository CI covers the other browser engines and React development checks separately." +}