All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
2.0.5 - 2026-04-15
- PHPStan: Baseline (
phpstan-baseline.neon) andphpstan.neon.distupdates (e.g.treatPhpDocTypesAsCertain). - GitHub: Issue templates, PR template,
SECURITY.md,CODEOWNERS,FUNDING.yml, Dependabot adjustments,sync-releases.ymlworkflow; additional workflowspr-lint.ymlandstale.yml; Copilot instructions for contributors. - Scrutinizer:
.scrutinizer.ymlfor external code quality integration. - Documentation: DEMO-FRANKENPHP, ENGRAM.
- QA: Expanded Python pytest coverage under
.scripts/test/; helper scripts.scripts/php-coverage-percent.shand.scripts/ts-coverage-percent.sh.
- Repository layout: Maintenance scripts moved from
scripts/to.scripts/(translation validation, PoC, Python helpers).composer validate-translationsand Make targets use the new paths. Contributors: update any automation or docs that still referencescripts/. - Tests: PHPUnit organized into
tests/Unitandtests/Integration; TypeScript/Vite/Vitest config tweaks; Vitest tests live undersrc/Resources/assets/next to the TS sources. - Demos (Symfony 7 & 8): Docker/Caddy dev flow (
Caddyfile.dev),.env.example, demo bundle config and dev Twig packages, AcroForm controller/menu updates; nginx demo configs removed in favour of Caddy. - Makefile / demo Makefiles: Additional targets (coverage helpers, pytest against
.scripts/test, PoC path). - README: Coverage and tooling notes updated.
- PHP: PHP-CS-Fixer pass and PHPStan-oriented type/docblock adjustments (controllers, forms, models, events, AcroForm).
- Composer (root): Lock file refreshed with current dev tooling.
- Symfony Flex:
extra.symfony.requireupdated from7.0.*to7.4.*socomposer updatecan resolve Symfony 7.4.x when Composer’s security audit blocks unmaintained 7.0.x ranges (see Symfony security advisories).
- README: Configuration snippet clarifies
example_pdf_url(matchesConfiguration.php: sample public PDF unless set to''). Demos section distinguishes dev (Caddyfile.dev) vs production Caddyfile; links to the full config reference. - Paths: INSTALLATION, TESTING, ACROFORM_BACKEND_EXTENSION, and
.scripts/PoC/README.mdnow refer to.scripts/instead ofscripts/.
- CHANGELOG, UPGRADING, and RELEASE checklist updated for 2.0.5.
- Removed accidentally tracked Python
__pycache__files; ignore rules extended so they are not committed again.
For upgrade steps from 2.0.4, see UPGRADING.
2.0.4 - 2026-03-02
- PHP-CS-Fixer: Refined rules to align with PSR-12 and Symfony coding standards.
- Docker: Root and demo Dockerfiles updated to PHP 8.2 Alpine; added dependencies for development and testing.
- Demos: Symfony 7 and 8 demos now serve over HTTP by default (Caddyfile updated) to simplify local development; Makefiles enhanced with commands for restarting containers, building images, and running tests; added README files with quick start instructions for each demo.
- CI: Simplified GitHub Actions workflow (ci.yml).
- CHANGELOG, UPGRADING, and RELEASE checklist updated for 2.0.4.
For upgrade steps from 2.0.3, see UPGRADING.
2.0.3 - 2026-02-16
- Packagist: Removed
repositoryfromcomposer.jsonsocomposer validate --strictpasses when publishing the package. No impact on installs; Packagist uses the repo URL from package registration.
For upgrade steps from 2.0.2, see UPGRADING.
2.0.2 - 2026-02-16
- Routes: Comment in
Resources/config/routes.yamlwith a copy-paste example for the app’sconfig/routes.yaml(resource + prefix), reducing friction on first install. - Proxy URL allowlist validation (dev):
ProxyUrlAllowlistValidationPassruns at container compile whenkernel.debugis true; validates regex patterns (entries starting with#) inproxy_url_allowlistand triggersE_USER_WARNINGif a pattern is invalid. Does not run in production. - Tests: Broader coverage:
ProxyUrlValidator(SSRF: empty host, private ranges 10.x/192.168.x/169.254.x, IPv6 link-local/loopback; allowlist: empty pattern skip, no-match returns false, invalid regex with/without logger).DependencyCheckListenercache (reuses request attribute, does not call checker again).NowoPdfSignableBundle::build()registers the compiler pass.CheckDependenciesCommandoutput with warnings when not strict.SignatureCoordinatesModel::fromArrayskips non-array box items.Configurationacroformlabel_mode,font_sizes,font_familiesdefaults and overrides. NewProxyUrlAllowlistValidationPassTestfor the compiler pass. - Test groups:
DependencyCheckerTest::testCheckWhenBundlePublicDirMissingAddsWarningandtestCheckRequiredExtensionsInFailureMessageWhenMissingmarked with@group integrationso CI can exclude them with--exclude-group integrationif needed.
- (None.)
- ProxyUrlValidator (SSRF): When
parse_url($url, PHP_URL_HOST)returnsfalse(e.g. malformed URL likehttp:///path), the validator no longer passes it tostrtolower(); invalid or missing host is now treated as blocked. IPv6 literal hosts in URLs (e.g.http://[::1]/orhttp://[fe80::1]/) are normalized (brackets stripped) and link-local (fe80:) is blocked via an early string check so SSRF blocking works in all environments.
- Documentation: Added “Estado de las mejoras (seguimiento)” table tracking implementation of review suggestions (routes, allowlist validation, integration group).
For upgrade steps from 2.0.1, see UPGRADING.
2.0.1 - 2026-02-16
- Tests: More coverage for PDF.js loader (
getWorkerUrlabsolute URL conversion, protocol-relative and empty-string handling,querySelectorfallback whencurrentScriptis null;getPdfJsLibCDN path). PHP test for defaultpdfjs_worker_urlnull inSignatureCoordinatesType. Extraurl-and-scaletests (empty proxy,getScaleForFitPagewith null container).
- PDF.js worker: Default worker asset is now
pdf.worker.min.js(waspdf.worker.min.mjs) so typical servers serve it withContent-Type: application/javascript, avoiding “Failed to fetch dynamically imported module” and “Setting up fake worker” in development. Theme and loader default tobundles/nowopdfsignable/js/pdf.worker.min.js. Vite build copies the worker fromnode_modules/pdfjs-dist/buildto the output dir;copy-workerscript andpostinstallstill output the same file for installs without a full build. - Worker URL resolution: Relative worker URLs are converted to absolute (using
window.location.origin) so the worker loads correctly in SPAs and when the script is served from a different base. Fallback: whendocument.currentScripthas nosrc(e.g. lazy-loaded script), the loader looks for a script tag withsrccontainingpdf-signable.jsoracroform-editor.jsand derives the worker path from it.
- Translations: Added missing AcroForm editor modal keys to 10 locales (ca, cs, de, fr, it, nl, pl, pt, ru, tr):
acroform_editor.modal_create_if_missing,modal_field_name,modal_field_name_placeholder,modal_hidden,modal_max_len,modal_max_len_placeholder. Ensuresmake validate-translationspasses. - Turkish (tr) YAML: Fixed invalid escape in single-quoted strings (
PDF\'deki→"PDF'deki alan adı") so the file parses correctly.
- USAGE: Default worker asset and MIME-type note for “Setting up fake worker” / “Failed to fetch dynamically imported module”.
For upgrade steps from 2.0.0, see UPGRADING.
2.0.0 - 2026-02-16
- Configuration structure: Signature config must be under the
signaturenode (global box options +configsby alias). AcroForm config must be under a singleacroformnode (replacingacroform_editorandacroform_configs). Container parameters are renamed:nowo_pdf_signable.default_box_*,.configs→nowo_pdf_signable.signature.*;nowo_pdf_signable.acroform_editor.*,nowo_pdf_signable.acroform_configs→nowo_pdf_signable.acroform.*,nowo_pdf_signable.acroform.configs. See UPGRADING for migration steps and examples.
- Signature config under
signaturenode: Global box defaults and named configs by alias (default aliasdefault). Use form optionconfig: 'alias'to apply. Container parameters:nowo_pdf_signable.signature.*andnowo_pdf_signable.signature.configs. See UPGRADING. - AcroForm config under single
acroformnode: Replacesacroform_editorandacroform_configs. Platform options, editor defaults,default_config_alias, andconfigsby alias. Container parameters:nowo_pdf_signable.acroform.*andnowo_pdf_signable.acroform.configs. See UPGRADING. - AcroForm editor translations: All UI strings in the AcroForm editor panel (demo templates) are now translatable. New translation keys under
acroform_editor.*(domainnowo_pdf_signable): page title, config header, form errors intro, close aria, panel title, draft intro (with HTML), document key label/placeholder, fields label, fields from PDF, refresh button, draft label/placeholder/title, load/save/clear buttons. Translations added for all 12 locales (EN, ES, FR, DE, CA, IT, NL, PT, CS, PL, RU, TR). Demo templatesacroform_editor.html.twig(Symfony 7 and 8) use|trans({}, 'nowo_pdf_signable')for every user-facing string. - AcroForm editor config (Type): New options under the
acroformnode to control the edit-field modal from the bundle config:label_mode('input'|'choice'): label as free text or select with predefined options plus "Other".label_choices(string[]): list of label options whenlabel_modeis'choice'(each entry: string or"value|Label").label_other_text(string): text for the "Other" option in the label select (default'Other').show_field_rect(bool, defaulttrue): whenfalse, the coordinates (rect) input is hidden in the edit-field modal.font_sizes(int[]): allowed font sizes in pt; empty = number input (1–72); non-empty = select with these values.font_families(string[]): allowed font families; empty = built-in list; non-empty = select with these options (each entry: string or"value|Label"). See CONFIGURATION and ACROFORM.
- Demo — AcroForm section: New dedicated "AcroForm" section in the demo nav and home index (Symfony 7 and 8) with six demos: AcroForm editor (default), AcroForm editor — Label as dropdown, AcroForm editor — Coordinates hidden, AcroForm editor — Custom font options, AcroForm editor — All options, AcroForm editor (min field size 24 pt).
- AcroForm apply — font family in PDF: The edit-field modal allows editing font size and font family for text/textarea fields. These values are now sent in the patch payload when applying to the PDF;
AcroFormFieldPatchincludesfontFamily; the Python apply script (apply_acroform_patches.py) sets the default appearance (/DA) with both font size and family, mapping common names (Arial, Helvetica, Times New Roman, Courier New, sans-serif, serif, monospace) to standard PDF fonts. See ACROFORM_BACKEND_EXTENSION and ACROFORM.
- (None.)
- (None.)
- Unified AcroForm docs: Single ACROFORM guide; ACROFORM_FLOWS for flow diagrams; ACROFORM_BACKEND_EXTENSION for backend. Removed redundant ACROFORM_EDITOR.md and ACROFORM_EDITOR_UX.md.
- Documentation in English: README, ACROFORM, ACROFORM_FLOWS, and EVENTS frontend section translated to English; ROADMAP updated with AcroForm section and doc links.
- Code comments in English: Spanish comments in
src/Resources/assets/acroform-editor.ts,src/Resources/assets/pdf-signable.scss, andscripts/PoC/run_poc.pytranslated to English.
For upgrade steps from 1.5.x, see UPGRADING.
1.5.4 - 2026-02-11
- Show AcroForm option (
show_acroform): Form option (defaulttrue) to draw an outline overlay over AcroForm/PDF form fields so they are visible in the viewer. Uses PDF.jsgetAnnotations(); outlines are non-interactive (clicks still add signature boxes). Setshow_acroform: falseto hide them. See USAGE and STYLES (.pdf-annotation-layer,.acroform-field-outline). - Demo: Recipe and demo named configs (
default,fixed_url) and demo base options includeshow_acroform: trueby default.
- Default configs: Recipe example and demo configs (Symfony 7 and 8) set
show_acroform: truein named configs and in the demo form base options so AcroForm fields are visible by default everywhere.
- CHANGELOG, UPGRADING, RELEASE checklist updated for 1.5.4.
For upgrade steps from 1.5.3, see UPGRADING.
1.5.3 - 2026-02-10
- Extended debug logging: When
nowo_pdf_signable.debugistrue, the viewer script now logs more detail to the browser console to help detect template/override issues: DOM resolution (widget, boxes list, prototype, key elements), overlay updates (box item count, missing page/coordinate fields, missing overlay container per page), add box (empty prototype, missing root or page/coordinate inputs), remove box (index and remaining count; warning if clicked item is not a direct box-item), signature pads init (canvas count; warnings when box item or signature-data input is missing), and PDF DOM built (pages and overlay containers). See CONFIGURATION for thedebugoption.
- Box item fallback: The script finds box rows by
[data-pdf-signable="box-item"]with fallback to.signature-box-item, so overridden themes that only use the class (e.g..signature-box-item) without the attribute still work and overlays are drawn correctly. USAGE notes the fallback.
- CHANGELOG, UPGRADING, and RELEASE checklist updated for 1.5.3.
For upgrade steps from 1.5.2, see UPGRADING.
1.5.2 - 2026-02-10
- Workflow documentation: WORKFLOW.md with Mermaid diagrams for architecture, page load and init, load PDF, add signature box, drag/resize overlay, coordinate sync, and form submit. Linked from USAGE and README.
- Data attributes for overrides: The viewer script finds elements by
data-pdf-signableattributes (e.g.data-pdf-signable="widget","page","x") instead of CSS classes, so you can change or remove classes in overridden templates for styling without breaking the JS. Form types and theme add these attributes; USAGE documents the full table and override notes. - Recipe:
.symfony/recipeconfig file is a complete example with all options commented and explained in English.
- Override form theme: USAGE now explains that if the overridden form theme is not applied (form fields still from bundle), add the theme explicitly in
config/packages/twig.yamlunderform_themesso Twig uses your overridden template.
- Widget init: Script finds the widget by
[data-pdf-signable="widget"]with fallback to.nowo-pdf-signable-widget, so overridden themes that do not add the attribute still work. - Page field on add box: When the page field is an input and the template override omits the expected class, the script now finds it by
[data-pdf-signable="page"]or by input/select whosenameends with[page], so the page number is set correctly when clicking on the PDF. - Mermaid diagrams: WORKFLOW.md sequence diagram labels simplified (no commas or special characters in arrow text) so Mermaid parsers accept them.
- CHANGELOG, UPGRADING, and RELEASE checklist updated for 1.5.2.
For upgrade steps from 1.5.1, see UPGRADING.
1.5.1 - 2026-02-11
- Named config merge order: When using a named config (e.g.
config: 'fixed_url'), the named config now overrides the form type’s resolver defaults. Previously the merge order was reversed, so options likeurl_field: false,show_load_pdf_button: false,unit_field: false, andorigin_field: falsefrom the YAML config were overwritten by the defaults and had no effect. If you use a named config with these options set tofalse, they now apply correctly (URL row, Load PDF button, and unit/origin selectors are hidden). - Form theme visibility: The Twig form theme now evaluates
url_field,show_load_pdf_button,unit_field, andorigin_fieldso that when they arefalse(or the string'false'), the corresponding UI is hidden. View options are passed as strict booleans frombuildViewfor consistent behaviour.
- Demo: The Symfony 7 and 8 demos’ Makefile forces
vendor/nowo-tech/pdf-signable-bundleto be a symlink to the mounted repo (/var/pdf-signable-bundle) aftercomposer install, so the container always uses the live bundle code. Path repository in the demos’composer.jsonhas"options": {"symlink": true}.
- Tests: New test
SignatureCoordinatesTypeTest::testNamedConfigWithHiddenFieldsOverridesDefaultsensures that a named config withurl_field,show_load_pdf_button,unit_field, andorigin_fieldset tofalseoverrides resolver defaults in both form building and view options. Presetfixed_urladded to the test form factory. TESTING updated (121 tests, coverage note for named config merge).
For upgrade steps from 1.5.0, see UPGRADING.
1.5.0 - 2026-02-10
- Guides and grid: Form options
show_grid(defaultfalse) andgrid_step(e.g.5in form unit). Whenshow_gridis true, a grid overlay is drawn on each page in the viewer (canvas above PDF, below signature overlays) to help align boxes; coordinates are unchanged. See USAGE and STYLES (.pdf-grid-overlay). - Viewer lazy load: Form option
viewer_lazy_load(defaultfalse). Whentrue, PDF.js and the signable script are not loaded at page bottom; a small inline script uses IntersectionObserver and loads them when the widget enters the viewport. Useful for long pages with multiple widgets. See USAGE. - Advanced signing (structure and extension points): Bundle now provides structures and events for PKI/PAdES, timestamp, audit trail, and batch signing without adding third-party dependencies. Your app adds keys, TSA URL, and signing service. See SIGNING_ADVANCED.
- Audit: Config
audit.fill_from_request(defaulttrue) mergessubmitted_at,ip,user_agentinto the model before dispatch.AuditMetadataclass with recommended keys (tsa_token,user_id, etc.). Config placeholderstsa_urlandsigning_service_id(bundle does not call them; use in listeners). - Events:
BATCH_SIGN_REQUESTED(when form is submitted with “Sign all”,batch_sign=1);PDF_SIGN_REQUEST(when your code requests a digital signature; listener can set response). See EVENTS. - Batch signing: Form option
batch_sign_enabledshows a “Sign all” button; your listener subscribes toBATCH_SIGN_REQUESTEDto perform the actual signing.
- Audit: Config
- Single inclusion of CSS and JS per request: When multiple
SignatureCoordinatesTypewidgets are rendered on the same page, the form theme includes the PDF viewer CSS (pdf-signable.css), PDF.js, andpdf-signable.jsonly once. A new Twig extension (NowoPdfSignableTwigExtension) exposesnowo_pdf_signable_include_assets()used by the theme. See USAGE and STYLES. - Demo: "Guides and grid" and "Viewer lazy load" demo pages (19 demos in total); sidebar and offcanvas highlight the current route; home index lists all demos including the new two.
- Larger resize and rotate handles: Corner resize handles on signature box overlays are now 12×12 px (was 8×8 px); the rotation handle is 16×16 px (was 12×12 px) for easier grabbing. See STYLES.
- Rotated signature boxes: Drag constraints now use the axis-aligned bounding box of the rotated rectangle, so boxes can be moved flush to all page edges (left, right, top, bottom) at any rotation angle (e.g. -90°, 45°). Previously, rotated boxes could not be placed against the left (and sometimes top) edge.
- Tests:
NowoPdfSignableTwigExtensionTestcoversnowo_pdf_signable_include_assets()(true once per request, then false; no request → always true).BatchSignRequestedEventTestandPdfSignRequestEventTestadded;PdfSignableEventsTestextended withBATCH_SIGN_REQUESTEDandPDF_SIGN_REQUESTconstants. - Documentation: CONTRIBUTING documents form theme assets and the Twig function for overriders. TESTING updated with current coverage summary (120 tests) and exclusion of
PdfSignableEvents.php. - Coverage:
PdfSignableEvents.phpexcluded from coverage (constants only); phpunit.xml.dist and TESTING.md updated.
For upgrade steps from 1.4.x, see UPGRADING.
1.4.1 - 2026-02-09
- Translations: Added
signing.consent_labelandsigning.consent_requiredto all locales (CA, CS, DE, FR, IT, NL, PL, PT, RU, TR). Fixed YAML escaping in Catalan, French and Italian (single quotes in single-quoted strings). - Tests:
SignatureCoordinatesTypeTest::testEnableSignatureCaptureAndDisclaimerPassedToViewno longer submits the same form twice; uses a separate form instance for the null-consent assertion to avoidAlreadySubmittedException.
1.4.0 - 2026-02-09
- Signing in boxes: Draw or upload a signature image per box. Options
enable_signature_capture(draw pad) andenable_signature_upload(file input); image stored inSignatureBoxModel::signatureDataand shown in the PDF overlay. See USAGE. - Legal disclaimer:
signing_legal_disclaimerandsigning_legal_disclaimer_urlform options to show a notice above the viewer (e.g. “simple signature, not qualified”). See USAGE. - Consent checkbox:
signing_require_consent(defaultfalse) andsigning_consent_label. Whentrue, a required checkbox is shown; value inSignatureCoordinatesModel::getSigningConsent(). Translations:signing.consent_label,signing.consent_required(EN, ES). - Timestamp per box:
SignatureBoxModel::getSignedAt()/setSignedAt()(ISO 8601). Set by the frontend when the user draws or uploads; backend can overwrite with server time for stronger evidence. Exported intoArray()/fromArray()assigned_at. - Audit metadata:
SignatureCoordinatesModel::getAuditMetadata()/setAuditMetadata()(e.g.signed_at,ip,user_agent) for evidence; included intoArray(). See USAGE. - Signing-only mode (
signing_only): Whentrue, each box row shows only the box name (read-only) and the signature capture (draw/upload); coordinate fields and unit/origin are hidden (values still submitted). Use for predefined boxes where the user only signs. See USAGE. - Signature pad improvements: Canvas resized to display size with
devicePixelRatiofor sharp rendering; smooth strokes viaquadraticCurveTo; pressure-sensitive line width (1–6 px) on touch (Touch.force) and mouse (MouseEvent.pressure) when supported. Signature capture row uses full form width. - Demo: “Signing options (AutoFirma, legal)” info page with links to AutoFirma, bundle roadmap (eIDAS/qualified), and USAGE; all demo texts in English.
- Demo layout: Burger menu replaced by a sidebar (aside) with all demo links (By configuration, Define areas, Signing, Bundle route); on small screens a “Demos” button opens an offcanvas with the same nav.
- Demo: All demo UI copy is in English. Sidebar and offcanvas list all demo pages; predefined sign-only demo uses
signing_only: true(name + signature only, no coordinate fields).
- TypeScript:
MouseEvent.pressureaccess fixed for strict DOM types (cast toMouseEvent & { pressure?: number }).
- Tests:
SignatureCoordinatesTypeTestassertssigning_onlydefault and when true; consent checkbox submit uses'1'/null.SignatureBoxModelTestandSignatureCoordinatesModelTestcoversignedAt,signingConsent,auditMetadataand toArray/fromArray.
For upgrade steps from 1.3.x, see UPGRADING.
1.3.0 - 2026-02-09
- PDF viewer zoom: Toolbar with zoom out (−), zoom in (+) and fit width (translated). PDF loads by default at fit-to-width; zoom range 0.5×–3×. Toolbar appears in the top-right of the viewer when a PDF is loaded. See USAGE.
- Debug option (
nowo_pdf_signable.debug): Whentrue, the frontend emitsconsole.log/console.warnin the browser (e.g. PDF load, add/remove box). Defaultfalse. See CONFIGURATION. - Translations: Zoom toolbar labels (
js.zoom_in,js.zoom_out,js.zoom_fit) in all supported languages (EN, ES, FR, DE, IT, PT, TR, CA, CS, NL, PL, RU).
- Viewer: Initial PDF scale is always fit-to-width (unchanged behaviour; ResizeObserver also uses fit-to-width on resize).
- (None in this release.)
- Tests:
ConfigurationTestnow coversdebugdefault and override.
For upgrade steps from 1.2.x, see UPGRADING.
1.2.0 - 2026-02-10
- Optional rotation (
enable_rotation): form option (defaultfalse). Whentrue, each box has an angle field (degrees) and the viewer shows a rotate handle above each overlay; whenfalse, the angle field is not rendered and boxes are not rotatable. See USAGE. - Default values per box name (
box_defaults_by_name): form option to pre-fill width, height, x, y, angle when the user selects a name (dropdown or input). See USAGE and ROADMAP. - Demos: added rotation, defaults-by-name, and allow-overlap demo pages (16 demo pages in total for Symfony 7 and 8).
- CI: translation validation step now runs after
composer installsovendor/autoload.phpexists (fixes failure in GitHub Actions).
For upgrade steps from 1.1.x, see UPGRADING.
1.1.0 - 2026-02-10
- Page restriction (
allowed_pages): form option to limit which pages boxes can be placed on; page field becomes a dropdown. See USAGE. - Proxy URL allowlist (
proxy_url_allowlist): bundle config to restrict which URLs the proxy can fetch (substring or regex). See CONFIGURATION and SECURITY. - Box order (
sort_boxes): form option to sort boxes by page, then Y, then X on submit. - Non-overlapping boxes (
prevent_box_overlap): default is nowtrue; validation on submit and frontend enforcement (drag/resize that would overlap is reverted and a translated message is shown). Set tofalseto allow overlapping boxes. - Translations: added CA, CS, NL, PL, RU (12 languages total: EN, ES, FR, DE, IT, PT, TR, CA, CS, NL, PL, RU).
- Translation validation:
scripts/validate-translations-yaml.phpnow checks that all translation files have the same keys as the reference (English) file;composer validate-translationsruns it. - Demos: added page restriction, sorted boxes, no-overlap, and latest features (combined) demos (13 demo pages in total for Symfony 7 and 8).
- SECURITY: Proxy no longer leaks exception messages to the client on 502/errors; SSRF mitigation blocks private/local URLs before fetch. Success flash in demos shows coordinates as an HTML list (user names escaped); see SECURITY.
prevent_box_overlapdefault changed fromfalsetotrue. If you relied on overlapping boxes being allowed by default, set'prevent_box_overlap' => falsewhen adding the form type. See UPGRADING.
- PHP 8.1+
- Symfony 6.1+, 7.x, 8.x.
1.0.0 - 2026-02-09
First stable release.
- Form types
SignatureCoordinatesType: form field that renders a PDF viewer and lets users define signature boxes by click; submitsSignatureCoordinatesModel(pdfUrl, unit, origin, signatureBoxes).SignatureBoxType: child type for a single signature box; submitsSignatureBoxModel(name, page, x, y, width, height). Name as text or dropdown (name_mode: choice); first choice pre-selected when empty.
- Models
SignatureCoordinatesModel: pdfUrl, unit (mm, cm, pt, px, in), origin (corners), signatureBoxes collection.SignatureBoxModel: name, page, x, y, width, height.
- PDF viewer
- Browser-based viewer using PDF.js with overlays for each signature box. Click on the PDF to add a box; drag to move; drag corners to resize.
- Overlay color by box name (deterministic); disambiguator label when same name on multiple boxes (e.g.
signer_1 (1),signer_1 (2)). - ResizeObserver loop fix:
scrollbar-gutter: stableandisReRenderingflag to prevent layout oscillation.
- Configuration
nowo_pdf_signable:proxy_enabledfor external PDFs (avoids CORS),example_pdf_urlfor form preload, optionalconfigs(named presets).
- Named configurations
- Define preset options in
nowo_pdf_signable.signature.configsand reference with form optionconfig: 'name'. See CONFIGURATION.md and USAGE.md.
- Define preset options in
- Optional proxy
- Route and controller to proxy external PDFs (
/pdf-signable/proxy). Events:PdfProxyRequestEvent,PdfProxyResponseEvent. See EVENTS.md.
- Route and controller to proxy external PDFs (
- Form theme
- Twig form theme for the signature coordinates widget (full widget: PDF + boxes). Reusable
SignatureBoxTypelayout.
- Twig form theme for the signature coordinates widget (full widget: PDF + boxes). Reusable
- Frontend assets
- Vite + TypeScript entry (
src/Resources/assets/signable-editor.ts). Built file atResources/public/js/pdf-signable.js. Form submits as normal POST; JS re-indexes collection before submit.
- Vite + TypeScript entry (
- Validation
- Required box name (
NotBlankonSignatureBoxType).unique_box_names:true(all unique),false(no check), or array (e.g.['signer_1', 'witness']) for per-name uniqueness. See USAGE.md.
- Required box name (
- Events
SignatureCoordinatesSubmittedEvent(after valid form submit),PdfProxyRequestEvent(before proxy fetch),PdfProxyResponseEvent(after proxy fetch). See EVENTS.md.
- Translation
- EN, ES, FR, DE, IT, PT, TR (e.g.
signature_box_type.name.required,signature_boxes.unique_names_message,js.alert_submit_error). Scriptscripts/validate-translations-yaml.phpfor CI.
- EN, ES, FR, DE, IT, PT, TR (e.g.
- Demos
- Dockerized demos for Symfony 7 and 8 (Bootstrap, Vite, TypeScript). Twelve demo pages: no config, default, fixed_url, overridden, URL as dropdown, limited boxes, same signer multiple, unique per name, page restriction, sorted boxes, no-overlap, predefined boxes. Home and burger menu list all; each page shows configuration in bullets. Flash message with coordinates (plain text).
- Documentation
- README, INSTALLATION.md, CONFIGURATION.md, USAGE.md, EVENTS.md, UPGRADING.md, ROADMAP.md, CONTRIBUTING.md, SECURITY.md (all in
docs/, English). “Same signer, multiple locations” and backend grouping example in USAGE.
- README, INSTALLATION.md, CONFIGURATION.md, USAGE.md, EVENTS.md, UPGRADING.md, ROADMAP.md, CONTRIBUTING.md, SECURITY.md (all in
- NotBlank: Uses named argument
message:(array form no longer supported in recent Symfony Validator). - Makefile:
make install,make assets,make validate-translationsrun via Docker for consistency.
- PHP 8.1+
- Symfony 6.1+, 7.x, 8.x.