* docs: add list schema implementation plan
* feat(schemas): add list schema
* fix(schemas): improve list form editing
* fix(schemas): localize list editing labels
* fix(schemas): align table control buttons
* fix(schemas): keep list designer editing during actions
* fix(tsconfig): resolve list schema subpath
* fix(schemas): keep list action clicks isolated
* fix(schemas): support empty list state
* fix(schemas): allow editing list items in designer
* fix(schemas): keep list designer editing on enter
* fix(schemas): ignore IME enter in list editor
* fix(schemas): make enter insert list item line breaks
* test(generator): add list plugin to playground snapshots
* refactor(schemas): render list items with text ui
* fix(schemas): adapt list prop panel fields by style
* fix(schemas): simplify list options and nested numbering
* Reorder import statements in generate-templates-thumbnail
* Reorder List plugin in getPlugins function
* fix(ui): reflow schemas after dynamic list resize
* chore: remove obsolete list plan
* fix(ui): reflow form list height changes
* fix(ui): keep designer height changes local
* fix(schemas): commit list item line breaks immediately
* fix(schemas): restore list focus after line break rerender
* fix(schemas): keep form list focused after enter
* test(generator): update dynamic list snapshots
* fix(schemas): store list content as json arrays
* fix(schemas): address list review cleanup
* test(ui): update designer snapshot
* chore: trim list pr noise
* fix(schemas): align list markers in ui
* fix: two unbounded-cache memory leaks in common and schemas
Two module-level Map caches that never evict and store multi-MB strings
as keys, silently leaking for the entire lifetime of any consumer.
1. packages/common/src/expression.ts — parseDataCache
parseData() was memoized via a module-level parseDataCache keyed by
JSON.stringify(data). replacePlaceholders() calls it with a merged
{ ...schemaNameDefaults, ...variables } object where values may be
arbitrary strings from the caller. Whenever inputs contain base64
(image schemas with embedded data URLs, embedded fonts, large text),
the cache key is a multi-MB JSON string that gets pinned permanently;
every unique inputs state adds its own key, never collected. Parsing
is O(fields) and cheap, so removing the cache is strictly a win.
Regression test: packages/common/__tests__/expression.test.ts
'replacePlaceholders memory safety > does not retain call inputs in
a module-level cache' — runs 30 replacePlaceholders() calls with
unique ~500 KB payloads, captures a V8 heap snapshot via
v8.writeHeapSnapshot, aggregates string nodes >= 200 KB and asserts
the total retained size is below 2 MB. Pre-fix: ~30 MB retained
(FAILS). Post-fix: 0 bytes retained (passes).
2. packages/schemas/src/graphics/image.ts — getCacheKey
getCacheKey(schema, input) returned `${schema.type}${input}`, using
the full base64 bytes of the image as part of the cache key. Every
unique image processed by the PDF render path added a permanent Map
entry whose key byte length matched the image itself.
Replaced with a short fingerprint that samples the total length plus
three 16-char regions (first, middle, last). The middle-region
sample is essential: base64 PNGs share a common header and IEND
trailer, so distinct images of the same size would collide if only
first/last regions were sampled. Middle bytes are pixel data and
differ between distinct images with overwhelming probability. Keys
stay under 80 chars regardless of input size.
Regression tests: packages/schemas/__tests__/image.test.ts
- 'does not pin the full base64 input as a cache key' — asserts
key length < 100 chars. Pre-fix: 139 chars for a minimal PNG and
proportionally more for realistic images (FAILS).
- 'distinguishes different images via the fingerprint' — guards
against future over-shortening of the fingerprint that could
reintroduce collisions between distinct images.
Both leaks were originally identified via a V8 heap-snapshot diff taken
across a UI workload (typing + field tabbing) against a consumer app
with image schemas carrying base64 content. Before the fix, the top two
growing allocations by retained size were multi-MB string entries — one
per module-level cache in this PR — together accounting for hundreds of
MB of retained JS heap in a single 3-iteration run. After the fix, both
string entries disappear from the top 25 growing allocations and
aggregate JS heap is net flat / slightly shrinking across iterations.
No public API change. No behavioral change for consumers. Both caches
were module-local implementation details.
* fix(schemas): harden image cache key with FNV-1a hash; fix stale test comments
Addresses Greptile review on #1426:
- Replace 3-region sampling fingerprint in getCacheKey with an FNV-1a
32-bit hash over the full input. The old first-16 slice was a
constant data-URI prefix for any image of the same MIME type,
contributing no entropy; hashing every byte removes that weakness
at the same O(n) cost without retaining any slice as a Map key.
Key format is now `${type}:${len}:${fnv1a-hex}` (~40 chars).
- Rewrite stale comments in image.test.ts that referred to a
padding/mutation scheme the test never performs, and update the
fingerprint-format comment to match the new hash-based key.
- Add trailing newline to expression.test.ts.
All pre-existing and new tests still pass.
* fix(dynamicTemplate): rewrite layout engine for accurate multi-page table rendering
- Implement sequential offset-based layout algorithm for correct element positioning
- Add floating point tolerance (EPSILON) to prevent precision errors in page break calculations
- Fix __bodyRange indexing to correctly map dynamicHeights to table body data
- Prevent orphaned table headers by moving header with first data row when page breaks
- Fix UI recalculation timing to use immediate input values for dynamic templates
- Update tests to match new layout behavior
* refactor(common): process dynamic template per page and remove duplicate cloneDeep
* refactor(common): process each template page independently regardless of dynamic content
* build(deps): bump zod from 3.25.67 to 4.1.11
Bumps [zod](https://github.com/colinhacks/zod) from 3.25.67 to 4.1.11.
- [Release notes](https://github.com/colinhacks/zod/releases)
- [Commits](https://github.com/colinhacks/zod/compare/v3.25.67...v4.1.11)
---
updated-dependencies:
- dependency-name: zod
dependency-version: 4.1.11
dependency-type: direct:production
update-type: version-update:semver-major
...
Signed-off-by: dependabot[bot] <support@github.com>
* Fix zod v4 API compatibility issues
- Update z.function() usage to z.any() for Plugin schema (zod v4 changed z.function() to a function factory)
- Update z.record() calls to use two arguments (key schema, value schema) as required by zod v4
- Add type assertions for Object.entries() to fix type inference issues
- Update test error message to match zod v4 format
Co-Authored-By: Kyohei Fukuda <kyoheif@wix.com>
* Update test expectations for zod v4 error message format
- Update error messages in common package tests to match zod v4 format
- 'Expected array, received string' → 'Invalid input: expected array, received string'
- 'Array must contain at least 1 element(s)' → 'Too small: expected array to have >=1 items'
- 'Required' → 'Invalid input: expected {type}, received undefined'
Co-Authored-By: Kyohei Fukuda <kyoheif@wix.com>
---------
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Kyohei Fukuda <kyoheif@wix.com>
Co-authored-by: Kyohei Fukuda <kyouhei.fukuda0729@gmail.com>
* test(expression): add XSS vulnerability prevention tests for replacePlaceholders function
* Update packages/common/src/expression.ts
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
* test: group safe Object method tests into single test case
- Refactored individual tests for Object.keys, Object.values, Object.entries, and Object.assign
- Combined them into a single test case with multiple assertions for better organization
- Addresses code review feedback about test organization
Co-authored-by: Kyohei Fukuda <hand-dot@users.noreply.github.com>
* feat(security): implement safeAssign to prevent prototype pollution and enhance XSS protection
* fix(safeAssign): use object spread for safer target assignment
---------
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
Co-authored-by: Kyohei Fukuda <hand-dot@users.noreply.github.com>
* remove old japanese template
* Add new image snapshots and update font references in tests
* Refactor code structure for improved readability and maintainability
* add pluginRepository and make plugin checking more robust
* Apply suggestions from code review
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
* f
* f
---------
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
* Fix linting errors in packages/common directory
- Replace explicit 'any' types with more specific types like 'unknown'
- Fix unsafe function calls with proper type assertions
- Remove unnecessary type assertions
- Replace non-null assertions with nullish coalescing operators
- Fix redundant type constituents in union types
Co-Authored-By: Kyohei Fukuda <kyouhei.fukuda0729@gmail.com>
* Fix type error in helper.ts getFontNamesInSchemas function
Co-Authored-By: Kyohei Fukuda <kyouhei.fukuda0729@gmail.com>
* Fix type errors in schemas package and test files
Co-Authored-By: Kyohei Fukuda <kyouhei.fukuda0729@gmail.com>
* Revert strict type changes to maintain backward compatibility
Co-Authored-By: Kyohei Fukuda <kyouhei.fukuda0729@gmail.com>
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Kyohei Fukuda <kyouhei.fukuda0729@gmail.com>
* Remove fast-xml-parser dependency and update vite-tsconfig-paths to 5.1.4
* tmp
* Refactor test files and scripts to use ES modules; remove obsolete files
* Enhance tests with new PDF utilities and update Jest configuration for ESM support
* [630]: Bug fix on basePdf as array buffer
* Minor fix
* Fix handling of customPdf in getB64BasePdf to ensure proper conversion to Uint8Array
* TMP
* Fix test
---------
Co-authored-by: hand-dot <kyouhei.fukuda0729@gmail.com>
* Fix table layout bug
* Update snapshot
* Move cloneDeep to common
* Minor fix
* revert some test pdf
* add test
* Minor fix
* Minor fix
* Minor fix
* refactoring
* Reconsider the internal data types and the template types (#389)
* Change SchemaForUI's data and readOnlyValue to content
* Fix bug
* Remove sampledata and instead always use content. & Use content regardless of readOnly or not. & Eliminate defaultValue and replace it with always using content.
* Change website template
* Fix placeholder bug
* Change generator test template
* Change content to optional
* Move getInputFromTemplate to common
* Remove columns
* Fix test
* move dynamictable.excalidraw
* remove idea dir
* New basePdf type and Support adding new pages to template (#394)
* Minor fix
* IMPL Support adding new pages to template #111
* Fix test
* Minor fix
* IMPL padding behavior
* Update snapshot
* Minor fix
* Update snapshot
* add i18n
* remove option from BlankPdf.padding
* Minor fix
* Minor fix
* format
* Add changeSchemas unit test (#403)
* Minor fix
* Add a version number to pdfme template from V4 onwards (#404)
* Impl
* Minor fix
* Padding move width (#407)
* Refactor position and size handling in helper.ts
* Fix bug
* Add DynamicTable Schema #332 (#408)
* [tmp] add some comment
* Update snapshot
* Add deploy-table script to package.json
* add new template for playground
* bug fix for form
* fix cell editing bug
* Fix Adding rows doesn't change the overall height of the table
* fix padding problem
* Fix build error
* Fix bug
* Minor fix
* Fix New lines not reflecting correctly
* minor fix
* Minor fix
* Change tableStyles def
* add i18n
* small bugfix
* FIx some TODO
* Remove japanese comment
* Minor fix
* Fix infinity loom for form
* fix save inputs bug
* fix window resize bug
* add skip for failing test and update snapshot
* Minor fix
* add presets for playground
* Minor fix
* Reconsider the internal data types and the template types (#389)
* Change SchemaForUI's data and readOnlyValue to content
* Fix bug
* Remove sampledata and instead always use content. & Use content regardless of readOnly or not. & Eliminate defaultValue and replace it with always using content.
* Change website template
* Fix placeholder bug
* Change generator test template
* Change content to optional
* Move getInputFromTemplate to common
* Remove columns
* Fix test
* move dynamictable.excalidraw
* remove idea dir
* New basePdf type and Support adding new pages to template (#394)
* Minor fix
* IMPL Support adding new pages to template #111
* Fix test
* Minor fix
* IMPL padding behavior
* Update snapshot
* Minor fix
* Update snapshot
* add i18n
* remove option from BlankPdf.padding
* Minor fix
* Minor fix
* format
* Add changeSchemas unit test (#403)
* Minor fix
* Add a version number to pdfme template from V4 onwards (#404)
* Impl
* Minor fix
* Padding move width (#407)
* Refactor position and size handling in helper.ts
* Fix bug
* Add DynamicTable Schema #332 (#408)
* [tmp] add some comment
* Update snapshot
* Add deploy-table script to package.json
* add new template for playground
* bug fix for form
* fix cell editing bug
* Fix Adding rows doesn't change the overall height of the table
* fix padding problem
* Fix build error
* Fix bug
* Minor fix
* Fix New lines not reflecting correctly
* minor fix
* Minor fix
* Change tableStyles def
* add i18n
* small bugfix
* FIx some TODO
* Remove japanese comment
* Minor fix
* Fix infinity loom for form
* fix save inputs bug
* fix window resize bug
* add skip for failing test and update snapshot
* Minor fix
* add presets for playground
* Minor fix
* Minor fix
* Update imports and fix font rendering
* Add a Left Sidebar for Placing Schemas #400 (#452)
* Remove original 'Add new field' Button
* add icon
* FIx drag position bug
* Minor fix
* Fix sidebar position
* Update snapshot
* Minor fix
* Update packages/ui/src/components/Designer/index.tsx
Co-authored-by: Peter Ward <pete@pennyblack.io>
---------
Co-authored-by: Peter Ward <pete@pennyblack.io>
* Fix test
* Improve left sidebar icon drop placement accuracy (#454)
* Fix Spanish translations for v4 (#463)
* Fix#431
* V4 (#467)
* feat: add french language
* feat: relecture
* feat: add french language
---------
Co-authored-by: regis <regis>
* Add French language option to playground
* rename table export name to tableBeta
---------
Co-authored-by: Peter Ward <pete@pennyblack.io>
Co-authored-by: Iker Diez <32014358+ikerd@users.noreply.github.com>
Co-authored-by: Régis <regis.charnace@leandco.fr>
* Move some type to common
* Add plugins interface
* TMP
* Fix build error
* Fix generator test
* Remove CommonProps export for user
* Add checkPlugins
* Minor fix
* QR Codes - ability to customise barcode colours added
* review fixes
* fix typo
* consolidate ColorInputSet for shared use between Text and BarCode
* consolidate some logic shared for bwip.js barcode lip between UI and generator
---------
Co-authored-by: Pete Ward <pete@pennyblack.io>
* added fit options for dynamic font sizing
implemented horizontal fit as default
* rebase fix
* review feedback
* tests
* add integration test
* vertical as default fit
* fix tests
* review feedback
* Dynamic font size 2.0
- grow and shrink font to fit vertical space
- improve UX for managing dynamic font sizing
* fix edge cases
add common tests
* further tests
* comment
* chore: Update font tests & calculateDynamicFontSize
- Updated the font tests and added tests for calculateDynamicFontSize.
- Also refactored code for readability and maintainability.
* [WIP] Update font test and font module to support font alignment.
- The font test was updated to use a shorter input string.
- The `calculateDynamicFontSize` function in the font module was updated to include font alignment calculations.
- The `heightOfFontAtSize` function in the font module was updated to use the provided font size parameter.
- The `getFontKitFont` function in the font module was updated to use the provided fontName from the text schema.
- The `drawInputByTextSchema` function in the generator module was updated to use the `getFontKitFont` and `getFontAlignmentValue` functions from the font module.
* Update generator snapshot pdf
* Update generator snapshot pdf