Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -172,3 +172,6 @@ docs/assets/styling-notebook-alpha10/*.pdf binary
examples/styling-notebook-alpha11/** text eol=lf
docs/assets/styling-notebook-alpha11/** -text
docs/assets/styling-notebook-alpha11/*.pdf binary

# React starter baselines are verified by exact PDF bytes.
docs/assets/react-starter/baseline/*.pdf binary
Binary file modified docs/assets/react-starter/baseline/component-credit-1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/assets/react-starter/baseline/component-credit.pdf
Binary file not shown.
Binary file modified docs/assets/react-starter/baseline/component-edited-1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/assets/react-starter/baseline/component-edited.pdf
Binary file not shown.
Binary file modified docs/assets/react-starter/baseline/component-empty-1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/assets/react-starter/baseline/component-empty.pdf
Binary file not shown.
Binary file modified docs/assets/react-starter/baseline/component-invoice-1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/assets/react-starter/baseline/component-invoice.pdf
Binary file not shown.
Binary file modified docs/assets/react-starter/baseline/component-long-1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/assets/react-starter/baseline/component-long.pdf
Binary file not shown.
Binary file modified docs/assets/react-starter/baseline/component-paid-1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/assets/react-starter/baseline/component-paid.pdf
Binary file not shown.
24 changes: 12 additions & 12 deletions docs/assets/react-starter/baseline/verification.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,54 +24,54 @@
{
"design": "component-invoice",
"pages": 1,
"pdfSha256": "7ab921d0f55604f84fd519514586f8d162e2912e925ea4071a59dfbd93993f56",
"pdfSha256": "f2553f220e9d30e26df785a4ed251f07ff1e615afd3972a5c29c19a0c5fd3f6c",
"previews": [
"0fa59b3ea2938c413d8c58a02e4b08bec8349aaf93500c16b17652ba92679199"
"54a931df6a4741745ae651800ff74311cb59f1c74b58a0a67936a497e288648c"
],
"repeatedPdfPreviewsEqual": true
},
{
"design": "component-paid",
"pages": 1,
"pdfSha256": "f4efce68a8f64f3f2219b9056cf2d3d345e9622fc9b3dbc355325ddbf62f02f3",
"pdfSha256": "91d8c8360fac37cd413fe669ed8f06650658b9ca01777129879207aac014d4c2",
"previews": [
"d040a9e8e435f7baa1498db9b9571508bd174b745d44eca7fc0ff5416eb46721"
"8028cdd4d9b967e61084f54711072a1cc93a208b557749187dc186eec251d531"
],
"repeatedPdfPreviewsEqual": true
},
{
"design": "component-edited",
"pages": 1,
"pdfSha256": "709f3438a1d4b363a86bf71025a8e883670354116c0d703b46b3ff16ae668709",
"pdfSha256": "a664f9fd84af1d2354537645aa6b70dd9abe3ab762b8a9631047aab742b1297e",
"previews": [
"aba217ddb0b2b068a6c649bff1510e6627fbd82ba1febfd745a1f9b722955e52"
"2ebbfde2c38975be8abf5312947a07d6375039f422fef3ad81aaad7d67cfe115"
],
"repeatedPdfPreviewsEqual": true
},
{
"design": "component-empty",
"pages": 1,
"pdfSha256": "d4f19a2559476236fe19acf76124f28ea5faa351731c7ee5585dd59f16f07122",
"pdfSha256": "cc1982eaea9dfa05b014cffea44644ecc2f4d33e8eb22ae6f6a501ab6d7f1248",
"previews": [
"7d386f278ce859efde193a30ab3981ddc26e481370fb56bd49f9f703c5f21c65"
"2c7539839be57f85421a98fad5a1abc403d914b87d0539f9128c91691c24f783"
],
"repeatedPdfPreviewsEqual": true
},
{
"design": "component-credit",
"pages": 1,
"pdfSha256": "b6b5f473e297c0c5d05f5bd1711c5ce3149dfbcbdb7234d0aeb54d2372622abf",
"pdfSha256": "cd57b56ec26e86365ab0223656d7e21b1543c9fbf404e967f0aef2e9b98024e6",
"previews": [
"6dd0b56df6bf3bdca9c19d01fc0227dd838657c93b4c095de064cf844ce506b8"
"8937d9ac9b42cf13c1dd28fcdb150dabd3f404e8bf7816050824c7905d6898e3"
],
"repeatedPdfPreviewsEqual": true
},
{
"design": "component-long",
"pages": 3,
"pdfSha256": "8ea549b4429c7f9b7e7b5d5b7491bbaf7b908b3cdaee63e385e2e979cdedb0d4",
"pdfSha256": "589210d6b5bb0684fdbf5dbf62c5e32742c7166d3a8cfc5ae304c430e08357a3",
"previews": [
"692d7e7ef7d2cafb225b1823fb4646e055fe6fee374f1f00c5c95e8d467ba7d4",
"a22c18101f3303398a17c655b88f005fffde67dddb3f0b28521a78041125f4fe",
"61e388cdd7c7d133c647b07886bd818d91382b072323c79281c80c698983b24b",
"7648f8591967cf8be2ad40f7743cc95464606687f8bcd14ac48098d9f48560c5"
],
Expand Down
Binary file modified docs/assets/react-starter/project.zip
Binary file not shown.
14 changes: 7 additions & 7 deletions docs/assets/react-starter/source.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
{
"source_repository": "https://github.com/fullbleed-engine/fullbleed-node",
"source_commit": "294ad01a9492d2e8c27feb4f5ed620b10ee47720",
"source_commit": "0de0e692d22a9058610a262a06a1797b7d892ae3",
"source_directory": "examples/react",
"package_version": "0.6.0",
"engine_version": "2.5.24",
"react_version": "19.3.0",
"package_integrity": "sha512-8tptrfaBbP4cjHohzPDPD1Lh3NuBFbRyVebn4kQhFsSX2VsMJwR6GURImfr9tbO3+iPjsZBFwZFxRYz238xc8g==",
"zip_bytes": 36270,
"zip_sha256": "a6b74368af73b2c217f9a1f2a0a6f07b0701a62185d3528f8fd6b0d9898561d1",
"zip_bytes": 36304,
"zip_sha256": "ce228650f3a34a7702a8bde10c29143864df11f4c652e10c23b60834e9ceeb8d",
"files": {
"fullbleed-react-starter/.gitignore": "0c8c1daabb918a54d7e75061883a887e9e0039d533487324a895ebe46afe15d8",
"fullbleed-react-starter/LICENSE": "36a2115938f6e68cf0d87eccff7a6a3e57c17017e909cbd640d51aff1fa0c5a9",
Expand All @@ -17,9 +17,9 @@
"fullbleed-react-starter/package.json": "d9c56c1953348c135f190e9b57cf84e54c2f960120c1c47f7959d7e1673244f1",
"fullbleed-react-starter/public/favicon.svg": "3eed6dcf1013e48bc64886fed4cf815c609ed06b404742bdacdc44c1df8d3118",
"fullbleed-react-starter/src/App.tsx": "be531b4b19f86fe2b56ebb652efca23c3ce5e5c0cc656951e4e6ac13aa738d7e",
"fullbleed-react-starter/src/documents/Invoice.tsx": "df2a087615a31c95094ac8797f17e352b3bac8c0c477476989904429349cff3a",
"fullbleed-react-starter/src/documents/Invoice.tsx": "6737ef4e107935cf0e66291f1ef1576d6aef37e647555e81ce875bf37a5cb589",
"fullbleed-react-starter/src/documents/data.ts": "c05c98fb07deaef2140f53df4f83670f138d6cad4a453fe09f423f7adb076f70",
"fullbleed-react-starter/src/documents/invoiceStyles.ts": "1cd818aec8cf2e9def15b51ce043bfdfcfc06626fd9df63372f34f9a43160a59",
"fullbleed-react-starter/src/documents/invoiceStyles.ts": "d9d63ef41fccae67d1a36de315b348c56ab5a680a18b0b2c43ffd63c46f18895",
"fullbleed-react-starter/src/invoice.css": "0b310ce0f2964fd6b9b68e4afafa9307b4ff8c6b2f1fc753367dc755620ce427",
"fullbleed-react-starter/src/invoice.html": "1f065ad6694021649e61b3f666cba6dc01aacdcbd8e80e97425b383e60d7d2fe",
"fullbleed-react-starter/src/main.tsx": "f8f523ef5fc0b1e4095830466e0caa648c01f7b42036694b800c25d43d5e2c84",
Expand All @@ -31,6 +31,6 @@
"fullbleed-react-starter/vite.config.js": "2a300aafa93df7e0269d06d104960ee5ac4d64989d37d61ca482c4b88db3629c"
},
"verification_workflow": "https://github.com/fullbleed-engine/fullbleed-node/actions/workflows/react-starter.yml",
"source_verification_run": "https://github.com/fullbleed-engine/fullbleed-node/actions/runs/38803591833",
"local_ui_evidence": "https://github.com/fullbleed-engine/fullbleed-node/blob/294ad01a9492d2e8c27feb4f5ed620b10ee47720/verification/react-components060.json"
"source_verification_run": "https://github.com/fullbleed-engine/fullbleed-node/actions/runs/39462826180",
"local_ui_evidence": "https://github.com/fullbleed-engine/fullbleed-node/blob/0de0e692d22a9058610a262a06a1797b7d892ae3/verification/react-invoice-references.json"
}
9 changes: 8 additions & 1 deletion docs/guides/react-pdf.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,11 @@ sheet, composes the chosen ink color overrides, and attaches it through
`<Document styles={...}>`. `src/style.css`
styles the React interface; print rules belong to the document's stylesheet.

The invoice reference has its own `className="invoice-reference"` rule with
`letterSpacing: "0pt"` and `textTransform: "none"`. Keep those overrides when
styling the surrounding label so references remain searchable and retain their
original case in the PDF.

Use **See the document component** to inspect the source while trying the form.
Keep your layout and data changes in these project files:

Expand Down Expand Up @@ -189,7 +194,9 @@ React development build with StrictMode enabled. It downloads real PDFs,
independently checks their text and page sizes, and compares six component
cases with the installed Node package: default, paid, edited, empty, credit,
and a twenty-row invoice across three pages. Every component preview matches
the Node output too. The existing HTML invoice and report keep their byte checks. It also checks automatic and
the Node output too. Default and mixed-case references must also survive exact
text extraction and case-sensitive PDF search without whitespace normalization.
The existing HTML invoice and report keep their byte checks. It also checks automatic and
on-demand modes, fast edits, cancellation, recovery, unmount/remount, URL cleanup,
and 1440/390/320px layouts. The docs build installs and checks the exact ZIP.
A real Vite development-server check edits TSX and stylesheet source, verifies
Expand Down
27 changes: 24 additions & 3 deletions tools/react_component_checks.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,25 @@

from playwright.sync_api import expect
from pypdf import PdfReader
import pypdfium2 as pdfium


def check_reference(path, reference, check):
# Identifiers must survive reader extraction and search without removing
# whitespace or changing case, even when the surrounding label is tracked.
text = PdfReader(path).pages[0].extract_text()
check(path.stem + ': reference extracts with exact spacing and case', reference in text)
with pdfium.PdfDocument(str(path)) as document:
page = document[0]
textpage = page.get_textpage()
search = textpage.search(reference, match_case=True)
try:
found = search.get_next() is not None
finally:
search.close()
textpage.close()
page.close()
check(path.stem + ': reference is searchable in PDFium', found)


def check_components(page, out, baseline, check, ready, download, hold_engine, resume_engine, requested):
Expand All @@ -25,7 +44,8 @@ def compare(name, text):

ready()
check('components are the initial design', page.locator('#kind').input_value() == 'components')
compare('component-invoice', ['Maple & Finch', 'NS-1042', '8,100.00'])
initial = compare('component-invoice', ['Maple & Finch', 'NS-1042', '8,100.00'])
check_reference(initial, 'NS-1042', check)
check('component design needs no HTML editor', page.locator('#html-source').count() == 0)
page.locator('#component-source summary').click()
source = page.locator('#component-source code').last.inner_text()
Expand Down Expand Up @@ -57,10 +77,11 @@ def compare(name, text):
page.locator('#customer').fill('Obsolete component input')
assert requested.wait(8), 'Expected a held component renderer.'
page.locator('#customer').fill('Birch & <Briar>')
page.locator('#reference').fill('TSX-2042')
page.locator('#reference').fill('Ref-aBc-2042')
page.locator('#accent').fill('#233b79')
resume_engine()
edited = compare('component-edited', ['Birch & <Briar>', 'TSX-2042'])
edited = compare('component-edited', ['Birch & <Briar>', 'Ref-aBc-2042'])
check_reference(edited, 'Ref-aBc-2042', check)
check('superseded component results cannot replace newer input', 'Obsolete component input' not in PdfReader(edited).pages[0].extract_text())
page.screenshot(path=str(out / 'component-edited.png'), full_page=True)
page.locator('#auto-preview').uncheck()
Expand Down
Loading