fix(forms): preserve regex quantifiers and use inline constraint errors
This commit is contained in:
1 parent
1dd60ded0d
commit
fe40cc56df
13 files changed
+132
-26
No files matched your search
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@wrnexus/compiler",
|
||||
"version": "0.8.26",
|
||||
"version": "0.8.27",
|
||||
"type": "module",
|
||||
"main": "src/index.ts",
|
||||
"exports": {
|
||||
|
||||
@@ -912,7 +912,7 @@ function renderNestedComponentInvocation(
|
||||
|
||||
const compiledValue = wholeExpression
|
||||
? `\${__wrnProp(${ctx.resolveExpr(wholeExpression)})}`
|
||||
: compileAttrValue(attr.value, ctx);
|
||||
: compileAttrValue(attr.value, ctx, attr.name === "pattern");
|
||||
|
||||
const rendered = ` ${attr.name}="${compiledValue}"`;
|
||||
|
||||
@@ -2254,7 +2254,7 @@ function compileText(raw: string, ctx: CompCtx): string {
|
||||
}
|
||||
|
||||
/** Compile an attribute value; `{expr}` is baked server-side (loop vars stay literal). */
|
||||
function compileAttrValue(raw: string, ctx: CompCtx): string {
|
||||
function compileAttrValue(raw: string, ctx: CompCtx, regexPattern = false): string {
|
||||
if (!raw.includes("{")) return escLit(attrEscape(raw));
|
||||
let out = "";
|
||||
let last = 0;
|
||||
@@ -2263,7 +2263,9 @@ function compileAttrValue(raw: string, ctx: CompCtx): string {
|
||||
while ((m = INTERP_RE.exec(raw))) {
|
||||
out += escLit(attrEscape(raw.slice(last, m.index)));
|
||||
const expr = m[1]!.trim();
|
||||
if (ctx.loopVars && exprRefsState(expr, ctx.loopVars)) {
|
||||
if (regexPattern && /^\d+(?:,\d*)?$/.test(expr)) {
|
||||
out += escLit(attrEscape(m[0])); // Regex quantifiers are not template expressions.
|
||||
} else if (ctx.loopVars && exprRefsState(expr, ctx.loopVars)) {
|
||||
out += escLit(`{${expr}}`); // hydrated per-item by the list renderer
|
||||
} else {
|
||||
out += `\${__wrnAttr(${ctx.resolveExpr(expr)})}`;
|
||||
@@ -2628,7 +2630,7 @@ function renderComponentNode(node: ViewNode, ctx: CompCtx): string {
|
||||
const compiledValue =
|
||||
isExplicitComponentMount && wholeExpression
|
||||
? `\${__wrnProp(${elementContext.resolveExpr(wholeExpression)})}`
|
||||
: compileAttrValue(a.value, elementContext);
|
||||
: compileAttrValue(a.value, elementContext, a.name === "pattern");
|
||||
|
||||
/*
|
||||
* A constraint attribute whose value is only known at render time (a
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
import { test, expect } from "bun:test";
|
||||
import { parse, generate } from "../src/index.ts";
|
||||
|
||||
test("HTML and component pattern attributes preserve regex quantifiers", () => {
|
||||
for (const tag of ["input", "Input"]) {
|
||||
for (const pattern of ["[0-9]{6}", "[a-z]{2,8}", "[A-Z]{1,}"]) {
|
||||
const code = generate(parse(`page Example { view { <${tag} pattern="${pattern}" /> } }`));
|
||||
expect(code).toContain(pattern);
|
||||
expect(code).not.toContain("__wrnAttr(6)");
|
||||
expect(code).not.toContain("__wrnAttr(2,8)");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
test("dynamic pattern props still compile as expressions", () => {
|
||||
const code = generate(
|
||||
parse(
|
||||
'component Example { props { pattern: string = "" } view { <input pattern="{pattern}" /> } }',
|
||||
),
|
||||
);
|
||||
expect(code).toContain("__wrnAttr(pattern)");
|
||||
});
|
||||
Reference in new issue
Block a user