Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ability to support regular expression as a value type #792

Open
lb- opened this issue Sep 26, 2024 · 0 comments
Open

Ability to support regular expression as a value type #792

lb- opened this issue Sep 26, 2024 · 0 comments

Comments

@lb-
Copy link
Contributor

lb- commented Sep 26, 2024

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))
  • The decoding would accept a pattern and flags in the format /some|pattern/gy/ (with leading & trailing slashes).
  • The decoded pattern & flags would be passed into the RegExp function, creating a new RegExp instance.
  • The default, for an empty string, aligns with the default when calling RegExp('') as a regex that matches only an empty string /(?:)/.
  • Attribute values would need to encode the slashes with the appropriate escaping.
  • When decoding, the toString method will be called on the RegExp instance, resolving to the same pattern & flags with slashes value.

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')
  • Some assumptions could be made about the appropriate flags to use for the common case (e.g. v, same as input pattern) and then any modifications to these can happen within the Stimulus controller.
  • Using source to provide the pattern string will escape slashes when output https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/source
  • When decoding, an empty string will be used as the default, to avoid unintended undefined leaking into RegExp.
  • false may not work as expected, unless we change the decoding behaviour, RegExp(false) gets coerced into a string of 'false'. e.g. we could decode as RegExp((value == "0" || value == "false") ? '' : value)

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

1 participant