Releases: jpmanson/codeforms
Release list
v0.3.0 — HTML escaping and a working JS validation generator
Security
The HTML exporter escaped nothing. Labels, help text, placeholders, values, select and radio option labels, and group/step titles were interpolated into the markup raw. Any form definition built from external data could inject arbitrary HTML, and values placed into attributes could close the attribute and add their own (" onclick="…).
All interpolation now goes through new html_text() / html_attr() / attrs_to_str() helpers. attrs_to_str() also filters attribute names, so a crafted key cannot introduce a new attribute.
Fixes — client-side validation
The generated validation script was either absent or broken:
generate_validation_code()returned""for every format except plain"html", so no Bootstrap consumer ever had client-side validation. It is now generated forhtml,html_bootstrap4andhtml_bootstrap5.- The script looked the form up by
form.name, which is not what ends up in theidattribute. It now receives the exported id, and bails out quietly if the element is absent. - Per-field code was emitted as
let {field.name} = …— aSyntaxErrorfor any field 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 a single apostrophe or backslash broke the script. - Values are read by a helper that handles checkbox/radio groups (where
form.elements[name]yields a collection) and multiple selects, instead of assuming.value. - The handler attaches with
addEventListenerinstead of assigningonsubmit, which clobbered any other handler on the form, and is guarded against double attachment.
Compatibility
validate_<form_name>(form)is still exposed when the form name can be a JS identifier, so the previous entry point keeps working. Validation is also reachable aswindow.codeformsValidate[formId]().- Consumers that relied on unescaped HTML in labels, help text or option labels will now see those tags rendered as text.
- Bootstrap consumers start receiving a non-empty
javascript_validation_codefor the first time. It is inert until you inject it into the page.
42 new tests; 248 total.
v0.2.4 — Fix textarea and hidden field HTML export
Fixes
TextareaField was exported as <input type="textarea">. That input type does not exist in HTML, so browsers degrade it to type="text". The field rendered as a single-line input: it could not hold line breaks, and pressing Enter triggered the browser's implicit form submission instead of inserting a newline.
TextareaFieldnow renders a real<textarea>, with the value as element content instead of avalueattribute. The content is HTML-escaped, so a value containing</textarea>can no longer break the markup.- The
rows,cols,minlengthandmaxlengthattributes are now emitted — they were declared on the model but never reached the HTML. readonlyis now honoured on textareas and on regular inputs.- Hidden fields render as a bare
<input type="hidden">, without theform-groupwrapper andform-controlclass that reserved visible vertical space for every hidden field in a form.
Build
- The PyPI publish workflow was pinned to a 2021 revision of
pypa/gh-action-pypi-publish, whose bundled twine rejects theMetadata-Version: 2.5that current hatchling emits. Pinned to v1.14.2.
Note
v0.2.3 carries the same library fixes but was never published to PyPI: its tag predates the workflow fix above, so its release failed at the upload step. Use 0.2.4.
Upgrading
No API changes. Any consumer styling the previous <input type="textarea"> by tag, or relying on the form-group wrapper around hidden fields, should check its CSS.
v0.2.3 — Fix textarea and hidden field HTML export
Fixes
TextareaField was exported as <input type="textarea">. That input type does not exist in HTML, so browsers degrade it to type="text". The field rendered as a single-line input: it could not hold line breaks, and pressing Enter triggered the browser's implicit form submission instead of inserting a newline.
TextareaFieldnow renders a real<textarea>, with the value as element content instead of avalueattribute. The content is HTML-escaped, so a value containing</textarea>can no longer break the markup.- The
rows,cols,minlengthandmaxlengthattributes are now emitted — they were declared on the model but never reached the HTML. readonlyis now honoured on textareas and on regular inputs.- Hidden fields render as a bare
<input type="hidden">, without theform-groupwrapper andform-controlclass that reserved visible vertical space for every hidden field in a form.
Upgrading
No API changes. Any consumer styling the previous <input type="textarea"> by tag or relying on the form-group wrapper around hidden fields should check its CSS.
0.2.2
v0.2.1
Refactor code and improve test coverage
- Reordered imports in
registry.pyfor consistency. - Updated string formatting to use double quotes for consistency.
- Enhanced
_init_builtin_typesfunction 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.
v0.2.0 — Dynamic Form Logic
What's New
Conditional Field Visibility
visible_whenattribute on any field with operators: equals, not_equals, in, not_in, gt, lt, is_empty, is_not_emptyevaluate_visibility()function for runtime evaluationForm.get_visible_fields(data)helper
Dependent Field Options
DependentOptionsConfigmodel for parent-child option relationshipsdependent_optionsattribute on SelectField/RadioField
Multi-Step Wizard Forms
FormStepmodel with title, description, validation_mode, skippableForm.get_steps(),Form.validate_step(),Form.validate_all_steps()- HTML export renders steps as
<section>withdata-wizardattributes
Dynamic Validation
validate_form_data_dynamic()— opt-in validation respecting visibility rules- Legacy
validate_form_data()unchanged (backward compatible)
Other
- Duck-typing cleanup (isinstance checks)
- Resolver priority ordering for type discrimination
- i18n messages for wizard/visibility (EN + ES)
- 151 tests passing
Full Changelog: v0.1.1...v0.2.0
v0.1.1
- 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.