hotwired / stimulus

A modest JavaScript framework for the HTML you already have
https://stimulus.hotwired.dev/
MIT License
12.73k stars 426 forks source link

Ability to support regular expression as a value type #792

Open lb- opened 2 months ago

lb- commented 2 months ago

There are often cases where a regular expression for custom validation, parsing, masking or replacing is required by a controller. Currently this would need to be handled bespoke within the controller logic.

This issue proposes a new RegExp value type that abstracts away the common logic required for controllers that want to handle a 'pattern' (or even flags) passed in via data attributes to a controller.

Proposed implementation 1 (with flags)

A new type would be added to the documentation https://stimulus.hotwired.dev/reference/values#types

Type Encoded as... Decoded as...
... ... ...
RegExp value.toString() RegExp(...Object.values(/^\/(?<a>.+)\/(?<b>[a-z]*)$/.exec(value \|\| '/(?:)/').groups))

Usage

<div data-my-controller-pattern-value=""></div>
<!-- Equivalent to /(?:)/ -->
<div data-my-controller-pattern-value="/a|b|c/g"></div>
<!-- Equivalent to /a|b|c/g -->
<div data-my-controller-pattern-value="[0-9]{3}"></div>
<!-- Would error -->
<div data-my-controller-pattern-value="/[0-9]{3}/"></div>
<!-- Equivalent to /[0-9]{3}/ -->
<div data-my-controller-pattern-value="/[0-9]{3}\/[a-z]*/"></div>
<!-- Equivalent to /[0-9]{3}\/[a-z]*/ -->

Proposed implementation 2 (without flags)

This alternative approach is a simpler (no flags) option, where the RegExp pattern is provided as is and there is no need to escape slashes.

This could mean we can align with the behaviour in input pattern attributes - https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/pattern

A new type would be added to the documentation https://stimulus.hotwired.dev/reference/values#types

Type Encoded as... Decoded as...
... ... ...
RegExp value.source RegExp(value \|\| '', 'v')

Usage

<div data-my-controller-pattern-value=""></div>
<!-- Equivalent to /(?:)/v -->
<div data-my-controller-pattern-value="[0-9]{3}"></div>
<!-- Equivalent to /[0-9]{3}/v -->
<div data-my-controller-pattern-value="[0-9]{3}/[a-z]*"></div>
<!-- Equivalent to /[0-9]{3}\/[a-z]*/v (note: no escaping needed for inner slash) -->

Prior art