Tags: jpmanson/codeforms
Tags
Escape HTML output and rebuild the JS validation generator
Two long-standing defects in the HTML exporter.
**Nothing was escaped.** Labels, help text, placeholders, values, select
and radio option labels, group and step titles all went into the markup
raw, so any form definition built from external data could inject
arbitrary HTML. Values interpolated into attributes could also close the
attribute and add their own (`" onclick="...`).
- Add `html_text()`, `html_attr()` and `attrs_to_str()` helpers, and route
every interpolation through them.
- `attrs_to_str()` also filters attribute *names*, so a crafted key
cannot introduce a new attribute.
**The client-side validation code was dead or broken.**
- `generate_validation_code()` returned `""` for every format except
plain `"html"`, so no Bootstrap consumer ever had client validation.
It is now generated for `html`, `html_bootstrap4` and `html_bootstrap5`.
- The script looked the form up by `form.name`, which is not what ends up
in the `id` attribute. It now receives the exported id, and bails out
quietly when the element is absent.
- Per-field code was emitted as `let {field.name} = ...`, a SyntaxError
for any name that is not a JS identifier (`mi-campo`) or is a reserved
word (`class`). Rules are now emitted as JSON and evaluated by a
generic runtime, so field names are just data.
- Messages, labels and regex patterns are serialized with `json.dumps`;
previously an apostrophe or a backslash broke the generated script.
- Values are read with a helper that handles checkbox and radio groups
(where `form.elements[name]` yields a collection) and multiple selects,
instead of assuming `.value`.
- The handler is attached with `addEventListener` rather than assigning
`onsubmit`, which clobbered any other handler on the form, and is
guarded against being attached twice.
- `validate_<form_name>(form)` is still exposed when the form name can be
a JS identifier, so the previous entry point keeps working.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Bump version to 0.2.4 v0.2.3 could not be published: its tag predates the publish-workflow fix, so the release ran the pinned action that rejects Metadata-Version 2.5. Nothing was uploaded to PyPI under 0.2.3. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Fix textarea and hidden field HTML export TextareaField was exported as `<input type="textarea">`. That input type does not exist, so browsers degrade it to `type="text"`: the field rendered as a single line, could not hold line breaks, and Enter triggered the browser's implicit form submission. - Render TextareaField as a real `<textarea>`, with the value as element content (HTML-escaped, so a value containing `</textarea>` can no longer break the markup) instead of a `value` attribute. - Emit the `rows`, `cols`, `minlength` and `maxlength` attributes, which were declared on the model but never reached the HTML. - Honour `readonly` on textarea and regular inputs. - Render hidden fields as a bare `<input type="hidden">`, without the `form-group` wrapper and `form-control` class that reserved visible vertical space for every hidden field in a form. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Refactor code and improve test coverage - Reordered imports in `registry.py` for consistency. - Updated string formatting to use double quotes for consistency. - Enhanced `_init_builtin_types` function by organizing field imports and registration. - Improved readability of test cases by formatting data dictionaries and assertions. - Added comprehensive tests for JSON Schema export functionality. - Ensured backward compatibility in tests for form construction and validation. - Cleaned up unnecessary whitespace and comments across various test files.
Phase 2: Dynamic Form Logic — conditional visibility, dependent optio… …ns, multi-step wizard - Add VisibilityRule for declarative field visibility (visible_when) - Add DependentOptionsConfig for dynamic option dependencies - Add FormStep model for multi-step wizard forms with per-step validation - Add evaluate_visibility() and validate_form_data_dynamic() opt-in APIs - Add Form.get_steps(), validate_step(), validate_all_steps(), get_visible_fields() - Replace duck-typing with isinstance() checks in forms.py, export.py - Update resolve_content_item with explicit type discriminator priority (RISK-1) - Add step_to_html() rendering with <section> (distinct from FieldGroup <fieldset>) - Add schema_version to Form for forward compatibility (RISK-5) - Define __all__ in __init__.py for controlled exports (RISK-6) - Add i18n messages for wizard/visibility (en + es) - All legacy APIs unchanged — 100% backward compatible - Bump version to 0.2.0 - 151 tests passing (88 original + 63 new) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Refactor code structure for improved readability and maintainability - Support for Python 3.9+ - **Custom field type registry**: Allow registering custom field types without modifying the hardcoded `Union` in `Form.content`. Provide a `register_field_type()` API.