@pyreon/compiler 0.13.0 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -4
- package/lib/analysis/index.js.html +1 -1
- package/lib/index.js +1113 -406
- package/lib/index.js.map +1 -1
- package/lib/types/index.d.ts +140 -14
- package/lib/types/index.d.ts.map +1 -1
- package/package.json +4 -1
- package/src/index.ts +10 -1
- package/src/jsx.ts +839 -782
- package/src/pyreon-intercept.ts +504 -0
- package/src/test-audit.ts +435 -0
- package/src/tests/depth-stress.test.ts +16 -0
- package/src/tests/detector-tag-consistency.test.ts +83 -0
- package/src/tests/jsx.test.ts +934 -0
- package/src/tests/native-equivalence.test.ts +654 -0
- package/src/tests/project-scanner.test.ts +30 -0
- package/src/tests/pyreon-intercept.test.ts +331 -0
- package/src/tests/react-intercept.test.ts +354 -0
- package/src/tests/test-audit.test.ts +549 -0
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/jsx.ts","../src/project-scanner.ts","../src/react-intercept.ts"],"sourcesContent":["/**\n * JSX transform — wraps dynamic JSX expressions in `() =>` so the Pyreon runtime\n * receives reactive getters instead of eagerly-evaluated snapshot values.\n *\n * Rules:\n * - `<div>{expr}</div>` → `<div>{() => expr}</div>` (child)\n * - `<div class={expr}>` → `<div class={() => expr}>` (prop)\n * - `<button onClick={fn}>` → unchanged (event handler)\n * - `<div>{() => expr}</div>` → unchanged (already wrapped)\n * - `<div>{\"literal\"}</div>` → unchanged (static)\n *\n * Static VNode hoisting:\n * - Fully static JSX in expression containers is hoisted to module scope:\n * `{<span>Hello</span>}` → `const _$h0 = <span>Hello</span>` + `{_$h0}`\n * - Hoisted nodes are created ONCE at module initialisation, not per-instance.\n * - A JSX node is static if: all props are string literals / booleans / static\n * values, and all children are text nodes or other static JSX nodes.\n *\n * Template emission:\n * - JSX element trees with ≥ 2 DOM elements (no components, no spread attrs)\n * are compiled to `_tpl(html, bindFn)` calls instead of nested `h()` calls.\n * - The HTML string is parsed once via <template>.innerHTML, then cloneNode(true)\n * for each instance (~5-10x faster than sequential createElement calls).\n * - Static attributes are baked into the HTML string; dynamic attributes and\n * text content use renderEffect in the bind function.\n *\n * Implementation: TypeScript parser for positions + magic-string replacements.\n * No extra runtime dependencies — `typescript` is already in devDependencies.\n *\n * Known limitation (v0): expressions inside *nested* JSX within a child\n * expression container are not individually wrapped. They are still reactive\n * because the outer wrapper re-evaluates the whole subtree, just at a coarser\n * granularity. Fine-grained nested wrapping is planned for a future pass.\n */\n\nimport ts from 'typescript'\n\nexport interface CompilerWarning {\n /** Warning message */\n message: string\n /** Source file line number (1-based) */\n line: number\n /** Source file column number (0-based) */\n column: number\n /** Warning code for filtering */\n code:\n | 'signal-call-in-jsx'\n | 'missing-key-on-for'\n | 'signal-in-static-prop'\n | 'circular-prop-derived'\n}\n\nexport interface TransformResult {\n /** Transformed source code (JSX preserved, only expression containers modified) */\n code: string\n /** Whether the output uses _tpl/_re template helpers (needs auto-import) */\n usesTemplates?: boolean\n /** Compiler warnings for common mistakes */\n warnings: CompilerWarning[]\n}\n\n// Props that should never be wrapped in a reactive getter\nconst SKIP_PROPS = new Set(['key', 'ref'])\n// Event handler pattern: onClick, onInput, onMouseEnter, …\nconst EVENT_RE = /^on[A-Z]/\n// Events delegated to the container — must match runtime DELEGATED_EVENTS set\nconst DELEGATED_EVENTS = new Set([\n 'click',\n 'dblclick',\n 'contextmenu',\n 'focusin',\n 'focusout',\n 'input',\n 'change',\n 'keydown',\n 'keyup',\n 'mousedown',\n 'mouseup',\n 'mousemove',\n 'mouseover',\n 'mouseout',\n 'pointerdown',\n 'pointerup',\n 'pointermove',\n 'pointerover',\n 'pointerout',\n 'touchstart',\n 'touchend',\n 'touchmove',\n 'submit',\n])\n\nexport interface TransformOptions {\n /**\n * Compile for server-side rendering. When true, the compiler skips the\n * `_tpl()` template optimization (which mutates a real DOM via\n * `document.createElement` etc.) and falls back to plain `h()` calls so\n * `@pyreon/runtime-server` can walk the VNode tree. Client builds keep\n * the `_tpl()` fast path. Default: false.\n */\n ssr?: boolean\n}\n\nexport function transformJSX(\n code: string,\n filename = 'input.tsx',\n options: TransformOptions = {},\n): TransformResult {\n const ssr = options.ssr === true\n const scriptKind =\n filename.endsWith('.tsx') || filename.endsWith('.jsx') ? ts.ScriptKind.TSX : ts.ScriptKind.TSX // default to TSX so JSX is always parsed\n\n const sf = ts.createSourceFile(\n filename,\n code,\n ts.ScriptTarget.ESNext,\n /* setParentNodes */ true,\n scriptKind,\n )\n\n type Replacement = { start: number; end: number; text: string }\n const replacements: Replacement[] = []\n const warnings: CompilerWarning[] = []\n\n function warn(node: ts.Node, message: string, warnCode: CompilerWarning['code']): void {\n const { line, character } = sf.getLineAndCharacterOfPosition(node.getStart(sf))\n warnings.push({ message, line: line + 1, column: character, code: warnCode })\n }\n\n // ── Static hoisting state ─────────────────────────────────────────────────\n type Hoist = { name: string; text: string }\n const hoists: Hoist[] = []\n let hoistIdx = 0\n let needsTplImport = false\n let needsRpImport = false\n let needsBindTextImportGlobal = false\n let needsBindDirectImportGlobal = false\n let needsBindImportGlobal = false\n let needsApplyPropsImportGlobal = false\n let needsMountSlotImportGlobal = false\n\n /**\n * If `node` is a fully-static JSX element/fragment, register a module-scope\n * hoist for it and return the generated variable name. Otherwise return null.\n */\n function maybeHoist(node: ts.Node): string | null {\n if (\n (ts.isJsxElement(node) || ts.isJsxSelfClosingElement(node) || ts.isJsxFragment(node)) &&\n isStaticJSXNode(node as ts.JsxElement | ts.JsxSelfClosingElement | ts.JsxFragment)\n ) {\n const name = `_$h${hoistIdx++}`\n const text = code.slice(node.getStart(sf), node.getEnd())\n hoists.push({ name, text })\n return name\n }\n return null\n }\n\n function wrap(expr: ts.Expression): void {\n const start = expr.getStart(sf)\n const end = expr.getEnd()\n // Object literals need parens: `() => { ... }` is a function body with\n // labeled statements, not an object expression. Use `() => ({ ... })`.\n const sliced = sliceExpr(expr)\n const text = ts.isObjectLiteralExpression(expr)\n ? `() => (${sliced})`\n : `() => ${sliced}`\n replacements.push({ start, end, text })\n }\n\n /** Try to hoist or wrap an expression, pushing a replacement if needed. */\n function hoistOrWrap(expr: ts.Expression): void {\n const hoistName = maybeHoist(expr)\n if (hoistName) {\n replacements.push({ start: expr.getStart(sf), end: expr.getEnd(), text: hoistName })\n } else if (shouldWrap(expr)) {\n wrap(expr)\n }\n }\n\n // ── walk sub-handlers ───────────────────────────────────────────────────────\n\n /** Try to emit a template for a JsxElement. Returns true if handled. */\n function tryTemplateEmit(node: ts.JsxElement): boolean {\n // SSR builds skip the `_tpl()` fast path entirely. `_tpl` clones a real\n // DOM element via `document.createElement('template')` and the emitted\n // bind callback calls `appendChild`, `createTextNode`, etc. — none of\n // that exists in Node. Falling back to standard JSX→`h()` lets\n // `@pyreon/runtime-server` walk the VNode tree to a string. Client\n // builds keep the template optimization.\n if (ssr) return false\n const elemCount = templateElementCount(node, /* isRoot */ true)\n if (elemCount < 1) return false\n const tplCall = buildTemplateCall(node)\n if (!tplCall) return false\n const start = node.getStart(sf)\n const end = node.getEnd()\n const parent = node.parent\n const needsBraces = parent && (ts.isJsxElement(parent) || ts.isJsxFragment(parent))\n replacements.push({ start, end, text: needsBraces ? `{${tplCall}}` : tplCall })\n needsTplImport = true\n return true\n }\n\n /** Emit warnings for common JSX mistakes (e.g. <For> without by). */\n function checkForWarnings(node: ts.JsxElement | ts.JsxSelfClosingElement): void {\n const opening = ts.isJsxElement(node) ? node.openingElement : node\n const tagName = ts.isIdentifier(opening.tagName) ? opening.tagName.text : ''\n if (tagName !== 'For') return\n const hasBy = opening.attributes.properties.some(\n (p) => ts.isJsxAttribute(p) && ts.isIdentifier(p.name) && p.name.text === 'by',\n )\n if (!hasBy) {\n warn(\n opening.tagName,\n `<For> without a \"by\" prop will use index-based diffing, which is slower and may cause bugs with stateful children. Add by={(item) => item.id} for efficient keyed reconciliation.`,\n 'missing-key-on-for',\n )\n }\n }\n\n /** Handle a JSX attribute node — wrap or hoist its value if needed.\n *\n * Both DOM and component props are processed:\n * - DOM props: () => expr — applyProp creates renderEffect\n * - Component props: _rp(() => expr) — makeReactiveProps converts to getters\n *\n * The _rp() brand distinguishes compiler wrappers from user-written accessor\n * props (like Show's when, For's each) so makeReactiveProps only converts\n * compiler-emitted wrappers.\n */\n function handleJsxAttribute(node: ts.JsxAttribute): void {\n const name = ts.isIdentifier(node.name) ? node.name.text : ''\n if (SKIP_PROPS.has(name) || EVENT_RE.test(name)) return\n if (!node.initializer || !ts.isJsxExpression(node.initializer)) return\n const expr = node.initializer.expression\n if (!expr) return\n\n const openingEl = node.parent.parent as ts.JsxOpeningElement | ts.JsxSelfClosingElement\n const tagName = ts.isIdentifier(openingEl.tagName) ? openingEl.tagName.text : ''\n const isComponent = tagName.length > 0 && tagName.charAt(0) !== tagName.charAt(0).toLowerCase()\n\n if (isComponent) {\n // Component prop: wrap with _rp() brand so makeReactiveProps recognizes it.\n //\n // EXCEPTION: If the expression is a single JSX element (not a conditional),\n // do NOT wrap the outer expression. The JSX element is created once (stable VNode).\n // Its own inner props will be wrapped individually via recursive walk().\n // This prevents remounting: <Icon name={x()} /> stays one Icon instance,\n // only its name prop updates reactively.\n const isSingleJsx = ts.isJsxElement(expr) || ts.isJsxSelfClosingElement(expr)\n if (isSingleJsx) {\n // Don't wrap — recurse into the JSX element's attributes instead\n ts.forEachChild(expr, walk)\n return\n }\n\n const hoistName = maybeHoist(expr)\n if (hoistName) {\n replacements.push({ start: expr.getStart(sf), end: expr.getEnd(), text: hoistName })\n } else if (shouldWrap(expr)) {\n const start = expr.getStart(sf)\n const end = expr.getEnd()\n // Object literals need parens to disambiguate from arrow function body\n const sliced = sliceExpr(expr)\n const inner = ts.isObjectLiteralExpression(expr) ? `(${sliced})` : sliced\n replacements.push({ start, end, text: `_rp(() => ${inner})` })\n needsRpImport = true\n }\n } else {\n // DOM prop: standard () => expr wrapping\n hoistOrWrap(expr)\n }\n }\n\n /** Handle a JSX expression in child position — wrap, hoist, or recurse. */\n function handleJsxExpression(node: ts.JsxExpression): void {\n const expr = node.expression\n if (!expr) return\n const hoistName = maybeHoist(expr)\n if (hoistName) {\n replacements.push({ start: expr.getStart(sf), end: expr.getEnd(), text: hoistName })\n return\n }\n if (shouldWrap(expr)) {\n wrap(expr)\n return\n }\n // Not hoisted, not wrapped (e.g., arrow function in For callback).\n // Recurse into the expression body to find nested JSX elements\n // that should be compiled to _tpl() calls.\n ts.forEachChild(expr, walk)\n }\n\n // ── Prop-derived variable tracking ─────────────────────────────────────────\n // Pre-pass: find variables derived from props/splitProps results inside\n // component functions. These are inlined at JSX use sites so the compiler's\n // existing wrapping makes them reactive.\n //\n // Example:\n // const align = props.alignX ?? 'left'\n // return <div class={align}> ← inlined to: class={props.alignX ?? 'left'}\n // ← compiler wraps: class={() => props.alignX ?? 'left'}\n\n /** Names that refer to the props object or splitProps results. */\n const propsNames = new Set<string>()\n\n /** Map of variable name → AST node of the original expression.\n * Using AST nodes instead of text avoids all string manipulation edge cases. */\n const propDerivedVars = new Map<string, ts.Expression>()\n\n /** Check if an expression reads from a tracked props-like object. */\n function readsFromProps(node: ts.Node): boolean {\n if (ts.isPropertyAccessExpression(node) && ts.isIdentifier(node.expression)) {\n return propsNames.has(node.expression.text)\n }\n if (ts.isElementAccessExpression(node) && ts.isIdentifier(node.expression)) {\n return propsNames.has(node.expression.text)\n }\n // Check children recursively — e.g. props.x ?? 'default'\n let found = false\n ts.forEachChild(node, (child) => {\n if (found) return\n if (readsFromProps(child)) found = true\n })\n return found\n }\n\n /** Pre-pass: scan a function body for prop-derived variable declarations.\n * callbackDepth tracks nesting inside callback arguments (map, filter, etc.)\n * to avoid tracking variables declared inside callbacks as prop-derived. */\n let _callbackDepth = 0\n function scanForPropDerivedVars(node: ts.Node): void {\n // Track callback nesting — don't track vars inside callbacks\n if ((ts.isArrowFunction(node) || ts.isFunctionExpression(node))) {\n const parent = node.parent\n if (parent && ts.isCallExpression(parent) && parent.arguments.includes(node as any)) {\n _callbackDepth++\n ts.forEachChild(node, scanForPropDerivedVars)\n _callbackDepth--\n return\n }\n }\n // Track the function's first parameter as a props name.\n // Only for COMPONENT functions — not callbacks like .map(item => <div>...)\n // Heuristic: component functions are named declarations, const assignments,\n // or export defaults — NOT inline arguments to calls like .map(), .filter().\n if ((ts.isFunctionDeclaration(node) || ts.isArrowFunction(node) || ts.isFunctionExpression(node))\n && node.parameters.length > 0) {\n\n // Skip functions that are arguments to a call (map/filter callbacks)\n const parent = node.parent\n if (parent && ts.isCallExpression(parent) && parent.arguments.includes(node as any)) {\n ts.forEachChild(node, scanForPropDerivedVars)\n return\n }\n\n const firstParam = node.parameters[0]!\n if (ts.isIdentifier(firstParam.name)) {\n // Check if this function returns JSX (is a component)\n let hasJSX = false\n ts.forEachChild(node, function checkJSX(n) {\n if (hasJSX) return\n if (ts.isJsxElement(n) || ts.isJsxSelfClosingElement(n) || ts.isJsxFragment(n)) {\n hasJSX = true\n return\n }\n ts.forEachChild(n, checkJSX)\n })\n if (hasJSX) propsNames.add(firstParam.name.text)\n }\n }\n\n // Track splitProps results: const [own, rest] = splitProps(props, [...])\n if (ts.isVariableStatement(node)) {\n for (const decl of node.declarationList.declarations) {\n if (ts.isArrayBindingPattern(decl.name) && decl.initializer\n && ts.isCallExpression(decl.initializer)) {\n const callee = decl.initializer.expression\n if (ts.isIdentifier(callee) && callee.text === 'splitProps') {\n for (const el of decl.name.elements) {\n if (ts.isBindingElement(el) && ts.isIdentifier(el.name)) {\n propsNames.add(el.name.text)\n }\n }\n }\n }\n\n // Track: const x = props.y ?? z OR const x = own.y\n // Skip let/var — mutable variables can be reassigned, unsafe to inline\n // Skip declarations inside callbacks (map, filter, etc.)\n // Skip stateful calls (signal, computed, effect) — inlining creates new instances\n if (!(node.declarationList.flags & ts.NodeFlags.Const)) continue\n if (_callbackDepth > 0) continue\n if (ts.isIdentifier(decl.name) && decl.initializer) {\n if (isStatefulCall(decl.initializer)) continue\n if (readsFromProps(decl.initializer)) {\n propDerivedVars.set(decl.name.text, decl.initializer)\n }\n }\n }\n }\n\n ts.forEachChild(node, scanForPropDerivedVars)\n }\n\n // Run pre-pass\n scanForPropDerivedVars(sf)\n\n // Transitive resolution: if const b = a + 1 where a is prop-derived,\n // then b is also prop-derived. Store its AST node.\n // Fixed-point iteration until no new variables are added.\n let changed = true\n while (changed) {\n changed = false\n sf.forEachChild(function scanTransitive(node) {\n if (!ts.isVariableStatement(node)) { ts.forEachChild(node, scanTransitive); return }\n for (const decl of node.declarationList.declarations) {\n if (!ts.isIdentifier(decl.name) || !decl.initializer) continue\n const varName = decl.name.text\n if (propDerivedVars.has(varName)) continue\n if (node.declarationList.flags & ts.NodeFlags.Let) continue\n let usesPropVar = false\n ts.forEachChild(decl.initializer, function check(n) {\n if (usesPropVar) return\n if (ts.isIdentifier(n) && propDerivedVars.has(n.text)) {\n const parent = n.parent\n if (parent && ts.isPropertyAccessExpression(parent) && parent.name === n) return\n usesPropVar = true\n }\n ts.forEachChild(n, check)\n })\n if (usesPropVar) {\n propDerivedVars.set(varName, decl.initializer)\n changed = true\n }\n }\n })\n }\n\n // Resolve transitive AST: for each prop-derived var, recursively replace\n // references to other prop-derived vars in its AST with their resolved nodes.\n // Uses ts.visitNode for correct AST transformation — no string manipulation.\n //\n // The `visited` set prevents infinite recursion on circular references:\n // const a = b + props.x; const b = a + 1;\n // Without it, resolving `a` reaches `b`, which reaches `a` again, and\n // the compiler stack-overflows. The fix: when a variable is already in\n // the visited set, leave the identifier as-is (it falls back to the\n // captured const value, which is the correct runtime behavior for a\n // circular dependency — the variable reads its value at definition time).\n // Track which cycles have been warned about so we don't emit\n // duplicate warnings for the same cycle seen from different vars.\n const warnedCycles = new Set<string>()\n\n function resolveExprTransitive(\n node: ts.Expression,\n visited: Set<string> = new Set(),\n /** The source node used for warning locations. */\n sourceNode?: ts.Node,\n ): ts.Expression {\n return ts.visitNode(node, function visit(n: ts.Node): ts.Node {\n if (ts.isIdentifier(n) && propDerivedVars.has(n.text)) {\n // FIRST: skip non-reference positions. An identifier is NOT a\n // variable read when it's a property name, binding name, or\n // shorthand property key. Those positions can happen to match\n // a tracked variable name (e.g. `own.beforeContentDirection`\n // when `beforeContentDirection` is also a tracked const) and\n // would otherwise trigger false-positive cycle warnings.\n //\n // This check MUST run before the cycle check — otherwise a\n // property access like `own.X` where X matches a tracked var\n // that's already in `visited` would falsely fire the warning.\n const parent = n.parent\n if (parent) {\n // Declaration positions — identifier defines a name, not reads one.\n // Also catches PropertyAccessExpression.name (property access),\n // VariableDeclaration.name (binding), PropertyAssignment.name\n // (object literal key), etc.\n if ('name' in parent && (parent as any).name === n) return n\n // Shorthand property: { x } — the identifier is both key and value\n if (ts.isShorthandPropertyAssignment(parent)) return n\n }\n\n // Cycle detection: if this variable is already in the visited\n // set, we've found a circular reference. Leave the identifier\n // as-is (falls back to captured const value) and emit a\n // compiler warning so the developer knows reactivity is\n // incomplete on this chain.\n if (visited.has(n.text)) {\n const cycleKey = [...visited, n.text].sort().join(',')\n if (!warnedCycles.has(cycleKey)) {\n warnedCycles.add(cycleKey)\n const chain = [...visited, n.text].join(' → ')\n warn(\n sourceNode ?? n,\n `[Pyreon] Circular prop-derived const reference: ${chain}. ` +\n `The cyclic identifier \\`${n.text}\\` will use its captured value ` +\n `instead of being reactively inlined. Break the cycle by reading ` +\n `from \\`props.*\\` directly or restructuring the derivation chain.`,\n 'circular-prop-derived',\n )\n }\n return n\n }\n\n const resolved = propDerivedVars.get(n.text)!\n // Mark this variable as visited BEFORE recursing so cycles are\n // detected on the next encounter rather than re-entering.\n const nextVisited = new Set(visited)\n nextVisited.add(n.text)\n return ts.factory.createParenthesizedExpression(\n resolveExprTransitive(resolved, nextVisited, sourceNode),\n )\n }\n return ts.visitEachChild(n, visit, undefined as any)\n }) as ts.Expression\n }\n\n /** Print an AST expression back to source text. */\n const printer = ts.createPrinter({ removeComments: false })\n\n /**\n * Enhanced dynamic check — combines containsCall with props awareness.\n * Returns true if an expression is reactive (contains signal calls,\n * accesses props members, or references prop-derived variables).\n */\n function isDynamic(node: ts.Node): boolean {\n if (containsCall(node)) return true\n return accessesProps(node)\n }\n\n /** Check if an expression accesses a tracked props object or a prop-derived variable. */\n function accessesProps(node: ts.Node): boolean {\n if (ts.isPropertyAccessExpression(node) && ts.isIdentifier(node.expression)) {\n if (propsNames.has(node.expression.text)) return true\n }\n if (ts.isIdentifier(node) && propDerivedVars.has(node.text)) {\n const parent = node.parent\n if (parent && ts.isPropertyAccessExpression(parent) && parent.name === node) return false\n return true\n }\n let found = false\n ts.forEachChild(node, (child) => {\n if (found) return\n if (ts.isArrowFunction(child) || ts.isFunctionExpression(child)) return\n if (accessesProps(child)) found = true\n })\n return found\n }\n\n function shouldWrap(node: ts.Expression): boolean {\n if (ts.isArrowFunction(node) || ts.isFunctionExpression(node)) return false\n if (isStatic(node)) return false\n if (ts.isCallExpression(node) && isPureStaticCall(node)) return false\n return isDynamic(node)\n }\n\n function walk(node: ts.Node): void {\n if (ts.isJsxElement(node) && tryTemplateEmit(node)) return\n if (ts.isJsxSelfClosingElement(node) || ts.isJsxElement(node)) checkForWarnings(node)\n if (ts.isJsxAttribute(node)) {\n handleJsxAttribute(node)\n return\n }\n if (ts.isJsxExpression(node)) {\n handleJsxExpression(node)\n return\n }\n ts.forEachChild(node, walk)\n }\n\n walk(sf)\n\n if (replacements.length === 0 && hoists.length === 0) return { code, warnings }\n\n // Apply replacements left-to-right via string builder — O(n) single join\n replacements.sort((a, b) => a.start - b.start)\n\n const parts: string[] = []\n let lastPos = 0\n for (const r of replacements) {\n parts.push(code.slice(lastPos, r.start))\n parts.push(r.text)\n lastPos = r.end\n }\n parts.push(code.slice(lastPos))\n let result = parts.join('')\n\n // Prepend module-scope hoisted static VNode declarations\n if (hoists.length > 0) {\n const preamble = hoists.map((h) => `const ${h.name} = /*@__PURE__*/ ${h.text}\\n`).join('')\n result = preamble + result\n }\n\n // Prepend template imports if _tpl() was emitted\n if (needsTplImport) {\n const runtimeDomImports = ['_tpl']\n if (needsBindDirectImportGlobal) runtimeDomImports.push('_bindDirect')\n if (needsBindTextImportGlobal) runtimeDomImports.push('_bindText')\n if (needsApplyPropsImportGlobal) runtimeDomImports.push('_applyProps')\n if (needsMountSlotImportGlobal) runtimeDomImports.push('_mountSlot')\n const reactivityImports = needsBindImportGlobal\n ? `\\nimport { _bind } from \"@pyreon/reactivity\";`\n : ''\n result =\n `import { ${runtimeDomImports.join(', ')} } from \"@pyreon/runtime-dom\";${reactivityImports}\\n` +\n result\n }\n\n // Prepend _rp import if reactive component props were emitted\n if (needsRpImport) {\n result = `import { _rp } from \"@pyreon/core\";\\n` + result\n }\n\n return { code: result, usesTemplates: needsTplImport, warnings }\n\n // ── Template emission helpers (closures over sf, code) ──────────────────────\n\n /**\n * Check if attributes prevent template emission.\n * - `key` always bails (VNode reconciliation prop)\n * - Spread on inner elements bails (too complex to merge in _bind)\n * - Spread on root element is allowed — applied via applyProps in _bind\n */\n function hasBailAttr(node: ts.JsxElement | ts.JsxSelfClosingElement, isRoot = false): boolean {\n for (const attr of jsxAttrs(node)) {\n if (ts.isJsxSpreadAttribute(attr)) {\n // Allow spread on root element — handled in buildTemplateCall\n if (isRoot) continue\n return true\n }\n if (ts.isJsxAttribute(attr) && ts.isIdentifier(attr.name) && attr.name.text === 'key')\n return true\n }\n return false\n }\n\n /**\n * Count template-eligible elements for a single JSX child.\n * Returns 0 for skippable children, -1 for bail, positive for element count.\n */\n function countChildForTemplate(child: ts.JsxChild): number {\n if (ts.isJsxText(child)) return 0\n if (ts.isJsxElement(child) || ts.isJsxSelfClosingElement(child))\n return templateElementCount(child)\n if (ts.isJsxExpression(child)) {\n if (!child.expression) return 0\n return containsJSXInExpr(child.expression) ? -1 : 0\n }\n if (ts.isJsxFragment(child)) return templateFragmentCount(child)\n return -1\n }\n\n /**\n * Count DOM elements in a JSX subtree. Returns -1 if the tree is not\n * eligible for template emission.\n */\n function templateElementCount(\n node: ts.JsxElement | ts.JsxSelfClosingElement,\n isRoot = false,\n ): number {\n const tag = jsxTagName(node)\n if (!tag || !isLowerCase(tag)) return -1\n if (hasBailAttr(node, isRoot)) return -1\n if (!ts.isJsxElement(node)) return 1\n\n let count = 1\n for (const child of node.children) {\n const c = countChildForTemplate(child)\n if (c === -1) return -1\n count += c\n }\n return count\n }\n\n /** Count template-eligible elements inside a fragment. */\n function templateFragmentCount(frag: ts.JsxFragment): number {\n let count = 0\n for (const child of frag.children) {\n const c = countChildForTemplate(child)\n if (c === -1) return -1\n count += c\n }\n return count\n }\n\n /**\n * Build the complete `_tpl(\"html\", (__root) => { ... })` call string\n * for a template-eligible JSX element tree. Returns null if codegen fails.\n */\n function buildTemplateCall(node: ts.JsxElement | ts.JsxSelfClosingElement): string | null {\n const bindLines: string[] = []\n const disposerNames: string[] = []\n let varIdx = 0\n let dispIdx = 0\n // Reactive expressions that will be combined into a single _bind call\n const reactiveBindExprs: string[] = []\n let needsBindTextImport = false\n let needsBindDirectImport = false\n let needsApplyPropsImport = false\n let needsMountSlotImport = false\n\n function nextVar(): string {\n return `__e${varIdx++}`\n }\n function nextDisp(): string {\n const name = `__d${dispIdx++}`\n disposerNames.push(name)\n return name\n }\n function nextTextVar(): string {\n return `__t${varIdx++}`\n }\n\n /** Resolve the variable name for an element given its accessor path. */\n function resolveElementVar(accessor: string, hasDynamic: boolean): string {\n if (accessor === '__root') return '__root'\n if (hasDynamic) {\n const v = nextVar()\n bindLines.push(`const ${v} = ${accessor}`)\n return v\n }\n return accessor\n }\n\n /** Emit bind line for a ref attribute. */\n function emitRef(attr: ts.JsxAttribute, varName: string): void {\n if (!attr.initializer || !ts.isJsxExpression(attr.initializer)) return\n const expr = attr.initializer.expression\n if (!expr) return\n // Function ref: ref={(el) => { ... }} or ref={fn} → call with element\n // Object ref: ref={myRef} → assign element to .current\n if (ts.isArrowFunction(expr) || ts.isFunctionExpression(expr)) {\n bindLines.push(`(${sliceExpr(expr)})(${varName})`)\n } else {\n bindLines.push(\n `{ const __r = ${sliceExpr(expr)}; if (typeof __r === \"function\") __r(${varName}); else if (__r) __r.current = ${varName} }`,\n )\n }\n }\n\n /** Emit event handler bind line — delegated (expando) or addEventListener. */\n function emitEventListener(attr: ts.JsxAttribute, attrName: string, varName: string): void {\n const eventName = (attrName[2] ?? '').toLowerCase() + attrName.slice(3)\n if (!attr.initializer || !ts.isJsxExpression(attr.initializer)) return\n if (!attr.initializer.expression) return\n const handler = sliceExpr(attr.initializer.expression)\n if (DELEGATED_EVENTS.has(eventName)) {\n // Delegated: store handler as expando property — container listener picks it up\n bindLines.push(`${varName}.__ev_${eventName} = ${handler}`)\n } else {\n bindLines.push(`${varName}.addEventListener(\"${eventName}\", ${handler})`)\n }\n }\n\n /** Return HTML string for a static attribute expression, or null if not static. */\n function staticAttrToHtml(exprNode: ts.Expression, htmlAttrName: string): string | null {\n if (!isStatic(exprNode)) return null\n if (ts.isStringLiteral(exprNode)) return ` ${htmlAttrName}=\"${escapeHtmlAttr(exprNode.text)}\"`\n if (ts.isNumericLiteral(exprNode)) return ` ${htmlAttrName}=\"${exprNode.text}\"`\n if (exprNode.kind === ts.SyntaxKind.TrueKeyword) return ` ${htmlAttrName}`\n return '' // false/null/undefined → omit\n }\n\n /**\n * Try to extract a direct signal reference from an expression.\n * Returns the callee text (e.g. \"count\" or \"row.label\") if the expression\n * is a single call with no arguments, otherwise null.\n */\n function tryDirectSignalRef(exprNode: ts.Expression): string | null {\n let inner = exprNode\n // Unwrap concise arrow: () => expr\n if (ts.isArrowFunction(inner) && !ts.isBlock(inner.body)) {\n inner = inner.body as ts.Expression\n }\n if (!ts.isCallExpression(inner)) return null\n if (inner.arguments.length > 0) return null\n const callee = inner.expression\n // Only match simple identifiers: count() → _bindText(count, node)\n // Property access like obj.method() is NOT safe — detaching the method\n // loses `this` context (e.g. value.toLocaleString becomes unbound).\n if (ts.isIdentifier(callee)) {\n return sliceExpr(callee)\n }\n return null\n }\n\n /** Unwrap a reactive accessor expression for use inside _bind(). */\n function unwrapAccessor(exprNode: ts.Expression): { expr: string; isReactive: boolean } {\n // Concise arrow: () => value() → unwrap to \"value()\"\n if (ts.isArrowFunction(exprNode) && !ts.isBlock(exprNode.body)) {\n return { expr: sliceExpr(exprNode.body as ts.Expression), isReactive: true }\n }\n // Block-body arrow/function: invoke it\n if (ts.isArrowFunction(exprNode) || ts.isFunctionExpression(exprNode)) {\n return { expr: `(${sliceExpr(exprNode)})()`, isReactive: true }\n }\n return { expr: sliceExpr(exprNode), isReactive: isDynamic(exprNode) }\n }\n\n /** Build a setter expression for an attribute. */\n function attrSetter(htmlAttrName: string, varName: string, expr: string): string {\n if (htmlAttrName === 'class') return `${varName}.className = ${expr}`\n if (htmlAttrName === 'style') return `${varName}.style.cssText = ${expr}`\n return `${varName}.setAttribute(\"${htmlAttrName}\", ${expr})`\n }\n\n /** Emit bind line for a dynamic (non-static) attribute. */\n function emitDynamicAttr(\n _expr: string,\n exprNode: ts.Expression,\n htmlAttrName: string,\n varName: string,\n ): void {\n const { expr, isReactive } = unwrapAccessor(exprNode)\n\n if (!isReactive) {\n bindLines.push(attrSetter(htmlAttrName, varName, expr))\n return\n }\n\n // Direct signal binding for bare signal calls (e.g. class={() => active()})\n const directRef = tryDirectSignalRef(exprNode)\n if (directRef) {\n needsBindDirectImport = true\n const d = nextDisp()\n const updater =\n htmlAttrName === 'class'\n ? `(v) => { ${varName}.className = v == null ? \"\" : String(v) }`\n : htmlAttrName === 'style'\n ? `(v) => { if (typeof v === \"string\") ${varName}.style.cssText = v; else if (v) Object.assign(${varName}.style, v) }`\n : `(v) => { ${varName}.setAttribute(\"${htmlAttrName}\", v == null ? \"\" : String(v)) }`\n bindLines.push(`const ${d} = _bindDirect(${directRef}, ${updater})`)\n return\n }\n\n reactiveBindExprs.push(attrSetter(htmlAttrName, varName, expr))\n }\n\n /** Emit bind line or HTML for an expression attribute value. */\n function emitAttrExpression(\n exprNode: ts.Expression,\n htmlAttrName: string,\n varName: string,\n ): string {\n const staticHtml = staticAttrToHtml(exprNode, htmlAttrName)\n if (staticHtml !== null) return staticHtml\n\n // style={{...}} → Object.assign(el.style, {...}) for object expressions\n if (htmlAttrName === 'style' && ts.isObjectLiteralExpression(exprNode)) {\n bindLines.push(`Object.assign(${varName}.style, ${sliceExpr(exprNode)})`)\n return ''\n }\n\n emitDynamicAttr(sliceExpr(exprNode), exprNode, htmlAttrName, varName)\n return ''\n }\n\n /** Emit side-effects for special attrs (ref, event). Returns true if handled. */\n function tryEmitSpecialAttr(attr: ts.JsxAttribute, attrName: string, varName: string): boolean {\n if (attrName === 'ref') {\n emitRef(attr, varName)\n return true\n }\n if (EVENT_RE.test(attrName)) {\n emitEventListener(attr, attrName, varName)\n return true\n }\n return false\n }\n\n /** Convert an attribute initializer to HTML. Returns empty string for side-effect-only attrs. */\n function attrInitializerToHtml(\n attr: ts.JsxAttribute,\n htmlAttrName: string,\n varName: string,\n ): string {\n if (!attr.initializer) return ` ${htmlAttrName}`\n if (ts.isStringLiteral(attr.initializer))\n return ` ${htmlAttrName}=\"${escapeHtmlAttr(attr.initializer.text)}\"`\n if (ts.isJsxExpression(attr.initializer) && attr.initializer.expression)\n return emitAttrExpression(attr.initializer.expression, htmlAttrName, varName)\n return ''\n }\n\n /** Process a single attribute, returning HTML to append. */\n function processOneAttr(attr: ts.JsxAttributeLike, varName: string): string {\n // Spread attribute: apply all props at runtime\n if (ts.isJsxSpreadAttribute(attr)) {\n const expr = sliceExpr(attr.expression)\n // Use runtime-dom's applyProps which handles class, style, events, etc.\n needsApplyPropsImport = true\n if (isDynamic(attr.expression)) {\n reactiveBindExprs.push(`_applyProps(${varName}, ${expr})`)\n } else {\n bindLines.push(`_applyProps(${varName}, ${expr})`)\n }\n return ''\n }\n if (!ts.isJsxAttribute(attr)) return ''\n const attrName = ts.isIdentifier(attr.name) ? attr.name.text : ''\n if (attrName === 'key') return ''\n if (tryEmitSpecialAttr(attr, attrName, varName)) return ''\n return attrInitializerToHtml(attr, JSX_TO_HTML_ATTR[attrName] ?? attrName, varName)\n }\n\n /** Process all attributes on an element, returning the HTML attribute string. */\n function processAttrs(el: ts.JsxElement | ts.JsxSelfClosingElement, varName: string): string {\n let htmlAttrs = ''\n for (const attr of jsxAttrs(el)) htmlAttrs += processOneAttr(attr, varName)\n return htmlAttrs\n }\n\n /** Emit bind lines for a reactive text expression child. */\n function emitReactiveTextChild(\n expr: string,\n exprNode: ts.Expression,\n varName: string,\n parentRef: string,\n childNodeIdx: number,\n needsPlaceholder: boolean,\n ): string {\n const tVar = nextTextVar()\n bindLines.push(`const ${tVar} = document.createTextNode(\"\")`)\n if (needsPlaceholder) {\n bindLines.push(\n `${parentRef}.replaceChild(${tVar}, ${parentRef}.childNodes[${childNodeIdx}])`,\n )\n } else {\n bindLines.push(`${varName}.appendChild(${tVar})`)\n }\n // Direct signal binding: bypass effect system entirely\n const directRef = tryDirectSignalRef(exprNode)\n if (directRef) {\n needsBindTextImport = true\n const d = nextDisp()\n bindLines.push(`const ${d} = _bindText(${directRef}, ${tVar})`)\n } else {\n // Each reactive text child gets its own _bind — independent tracking.\n // When r.name() changes, r.email()'s _bind doesn't re-run.\n needsBindImportGlobal = true\n const d = nextDisp()\n bindLines.push(`const ${d} = _bind(() => { ${tVar}.data = ${expr} })`)\n }\n return needsPlaceholder ? '<!>' : ''\n }\n\n /** Emit bind lines for a static text expression child. */\n function emitStaticTextChild(\n expr: string,\n varName: string,\n parentRef: string,\n childNodeIdx: number,\n needsPlaceholder: boolean,\n ): string {\n if (needsPlaceholder) {\n const tVar = nextTextVar()\n bindLines.push(`const ${tVar} = document.createTextNode(${expr})`)\n bindLines.push(\n `${parentRef}.replaceChild(${tVar}, ${parentRef}.childNodes[${childNodeIdx}])`,\n )\n return '<!>'\n }\n bindLines.push(`${varName}.textContent = ${expr}`)\n return ''\n }\n\n /** Process a single flat child, returning the HTML contribution or null on failure. */\n function processOneChild(\n child: FlatChild,\n varName: string,\n parentRef: string,\n useMixed: boolean,\n useMultiExpr: boolean,\n childNodeIdx: number,\n ): string | null {\n if (child.kind === 'text') return escapeHtmlText(child.text)\n if (child.kind === 'element') {\n const childAccessor = useMixed\n ? `${parentRef}.childNodes[${childNodeIdx}]`\n : `${parentRef}.children[${child.elemIdx}]`\n return processElement(child.node, childAccessor)\n }\n // expression\n const needsPlaceholder = useMixed || useMultiExpr\n const { expr, isReactive } = unwrapAccessor(child.expression)\n\n // Children slot: expression accesses .children (e.g. props.children, own.children)\n // These can contain VNodes — use _mountSlot instead of text node binding.\n if (isChildrenExpression(child.expression, expr)) {\n needsMountSlotImport = true\n const placeholder = `${parentRef}.childNodes[${childNodeIdx}]`\n const d = nextDisp()\n bindLines.push(`const ${d} = _mountSlot(${expr}, ${parentRef}, ${placeholder})`)\n return '<!>'\n }\n\n if (isReactive) {\n return emitReactiveTextChild(\n expr,\n child.expression,\n varName,\n parentRef,\n childNodeIdx,\n needsPlaceholder,\n )\n }\n return emitStaticTextChild(expr, varName, parentRef, childNodeIdx, needsPlaceholder)\n }\n\n /** Process children of a JsxElement, returning the children HTML. */\n function processChildren(el: ts.JsxElement, varName: string, accessor: string): string | null {\n const flatChildren = flattenChildren(el.children)\n const { useMixed, useMultiExpr } = analyzeChildren(flatChildren)\n const parentRef = accessor === '__root' ? '__root' : varName\n\n let html = ''\n let childNodeIdx = 0\n\n for (const child of flatChildren) {\n const childHtml = processOneChild(\n child,\n varName,\n parentRef,\n useMixed,\n useMultiExpr,\n childNodeIdx,\n )\n if (childHtml === null) return null\n html += childHtml\n childNodeIdx++\n }\n\n return html\n }\n\n /** Process a single DOM element for template emission. Returns the HTML string or null. */\n function processElement(\n el: ts.JsxElement | ts.JsxSelfClosingElement,\n accessor: string,\n ): string | null {\n const tag = jsxTagName(el)\n if (!tag) return null\n\n const varName = resolveElementVar(accessor, elementHasDynamic(el))\n const htmlAttrs = processAttrs(el, varName)\n let html = `<${tag}${htmlAttrs}>`\n\n if (ts.isJsxElement(el)) {\n const childHtml = processChildren(el, varName, accessor)\n if (childHtml === null) return null\n html += childHtml\n }\n\n if (!VOID_ELEMENTS.has(tag)) html += `</${tag}>`\n return html\n }\n\n const html = processElement(node, '__root')\n if (html === null) return null\n\n if (needsBindTextImport) needsBindTextImportGlobal = true\n if (needsBindDirectImport) needsBindDirectImportGlobal = true\n if (needsApplyPropsImport) needsApplyPropsImportGlobal = true\n if (needsMountSlotImport) needsMountSlotImportGlobal = true\n\n // Build bind function body\n const escaped = html.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"')\n\n // Emit combined _bind for reactive attribute/text expressions that\n // weren't handled by _bindText. This merges N separate _bind calls into\n // one — saving N-1 closures + deps arrays per template instance.\n // Emit a single combined _bind for all reactive attribute/text expressions\n // that weren't handled by _bindText. Merges N separate _bind calls into one —\n // saving N-1 closures + deps arrays per template instance.\n if (reactiveBindExprs.length > 0) {\n needsBindImportGlobal = true\n const combinedName = nextDisp()\n const combinedBody = reactiveBindExprs.join('; ')\n bindLines.push(`const ${combinedName} = _bind(() => { ${combinedBody} })`)\n }\n\n if (bindLines.length === 0 && disposerNames.length === 0) {\n return `_tpl(\"${escaped}\", () => null)`\n }\n\n let body = bindLines.map((l) => ` ${l}`).join('\\n')\n if (disposerNames.length > 0) {\n body += `\\n return () => { ${disposerNames.map((d) => `${d}()`).join('; ')} }`\n } else {\n body += '\\n return null'\n }\n\n return `_tpl(\"${escaped}\", (__root) => {\\n${body}\\n})`\n }\n\n /** Flat child descriptor for template children processing */\n type FlatChild =\n | { kind: 'text'; text: string }\n | { kind: 'element'; node: ts.JsxElement | ts.JsxSelfClosingElement; elemIdx: number }\n | { kind: 'expression'; expression: ts.Expression }\n\n /** Classify a single JSX child into a FlatChild descriptor. */\n function classifyJsxChild(\n child: ts.JsxChild,\n out: FlatChild[],\n elemIdxRef: { value: number },\n recurse: (kids: ts.NodeArray<ts.JsxChild>) => void,\n ): void {\n if (ts.isJsxText(child)) {\n const trimmed = child.text.replace(/\\n\\s*/g, '').trim()\n if (trimmed) out.push({ kind: 'text', text: trimmed })\n return\n }\n if (ts.isJsxElement(child) || ts.isJsxSelfClosingElement(child)) {\n out.push({ kind: 'element', node: child, elemIdx: elemIdxRef.value++ })\n return\n }\n if (ts.isJsxExpression(child)) {\n if (child.expression) out.push({ kind: 'expression', expression: child.expression })\n return\n }\n if (ts.isJsxFragment(child)) recurse(child.children)\n }\n\n /**\n * Flatten JSX children, inlining fragment children and stripping whitespace-only text.\n * Returns a flat array of child descriptors with element indices pre-computed.\n */\n function flattenChildren(children: ts.NodeArray<ts.JsxChild>): FlatChild[] {\n const flatList: FlatChild[] = []\n const elemIdxRef = { value: 0 }\n\n function addChildren(kids: ts.NodeArray<ts.JsxChild>): void {\n for (const child of kids) classifyJsxChild(child, flatList, elemIdxRef, addChildren)\n }\n\n addChildren(children)\n return flatList\n }\n\n /** Analyze flat children to determine indexing strategy. */\n function analyzeChildren(flatChildren: FlatChild[]): {\n useMixed: boolean\n useMultiExpr: boolean\n } {\n const hasElem = flatChildren.some((c) => c.kind === 'element')\n const hasNonElem = flatChildren.some((c) => c.kind !== 'element')\n const exprCount = flatChildren.filter((c) => c.kind === 'expression').length\n return { useMixed: hasElem && hasNonElem, useMultiExpr: exprCount > 1 }\n }\n\n /** Check if a single attribute is dynamic (has ref, event, or non-static expression). */\n function attrIsDynamic(attr: ts.JsxAttributeLike): boolean {\n if (!ts.isJsxAttribute(attr)) return false\n const name = ts.isIdentifier(attr.name) ? attr.name.text : ''\n if (name === 'ref') return true\n if (EVENT_RE.test(name)) return true\n if (!attr.initializer || !ts.isJsxExpression(attr.initializer)) return false\n const expr = attr.initializer.expression\n return expr ? !isStatic(expr) : false\n }\n\n /** Check if an element has any dynamic attributes, events, ref, or expression children */\n function elementHasDynamic(node: ts.JsxElement | ts.JsxSelfClosingElement): boolean {\n if (jsxAttrs(node).some(attrIsDynamic)) return true\n if (ts.isJsxElement(node)) {\n return node.children.some((c) => ts.isJsxExpression(c) && c.expression !== undefined)\n }\n return false\n }\n\n /** Slice expression source from the original code.\n * Resolves any prop-derived identifiers found anywhere in the expression\n * via AST transformation — handles template literals, ternaries, etc. */\n function sliceExpr(expr: ts.Expression): string {\n // Quick check: does this expression contain any prop-derived references?\n if (propDerivedVars.size > 0 && accessesProps(expr)) {\n const resolved = resolveExprTransitive(expr, new Set(), expr)\n return printer.printNode(ts.EmitHint.Expression, resolved, sf)\n }\n return code.slice(expr.getStart(sf), expr.getEnd())\n }\n\n /** Get tag name string */\n function jsxTagName(node: ts.JsxElement | ts.JsxSelfClosingElement): string {\n const tag = ts.isJsxElement(node) ? node.openingElement.tagName : node.tagName\n return ts.isIdentifier(tag) ? tag.text : ''\n }\n\n /** Get attribute list */\n function jsxAttrs(\n node: ts.JsxElement | ts.JsxSelfClosingElement,\n ): ts.NodeArray<ts.JsxAttributeLike> {\n return ts.isJsxElement(node)\n ? node.openingElement.attributes.properties\n : node.attributes.properties\n }\n}\n\n// ─── Template constants ──────────────────────────────────────────────────────\n\nconst VOID_ELEMENTS = new Set([\n 'area',\n 'base',\n 'br',\n 'col',\n 'embed',\n 'hr',\n 'img',\n 'input',\n 'link',\n 'meta',\n 'param',\n 'source',\n 'track',\n 'wbr',\n])\n\nconst JSX_TO_HTML_ATTR: Record<string, string> = {\n className: 'class',\n htmlFor: 'for',\n}\n\n/**\n * Detect if an expression is a stateful call that must NOT be inlined.\n * signal(), computed(), effect() etc. create state — inlining them would\n * create new instances at each use site instead of referencing the original.\n */\nconst STATEFUL_CALLS = new Set([\n 'signal', 'computed', 'effect', 'batch',\n 'createContext', 'createReactiveContext',\n 'useContext', 'useRef', 'createRef',\n 'useForm', 'useQuery', 'useMutation',\n 'defineStore', 'useStore',\n])\n\nfunction isStatefulCall(node: ts.Node): boolean {\n if (!ts.isCallExpression(node)) return false\n const callee = node.expression\n if (ts.isIdentifier(callee)) return STATEFUL_CALLS.has(callee.text)\n return false\n}\n\n/**\n * Detect if an expression accesses `.children` — these can contain VNodes\n * and must use _mountSlot instead of text node binding in templates.\n * Matches: props.children, own.children, x.children, or bare `children` identifier.\n */\nfunction isChildrenExpression(node: ts.Expression, expr: string): boolean {\n // Direct property access: props.children, own.children\n if (ts.isPropertyAccessExpression(node) && node.name.text === 'children') return true\n // Bare identifier named 'children'\n if (ts.isIdentifier(node) && node.text === 'children') return true\n // String fallback for inlined expressions\n if (expr.endsWith('.children') || expr === 'children') return true\n return false\n}\n\nfunction isLowerCase(s: string): boolean {\n return s.length > 0 && s[0] === s[0]?.toLowerCase()\n}\n\n/** Check if an expression subtree contains JSX nodes */\nfunction containsJSXInExpr(node: ts.Node): boolean {\n if (ts.isJsxElement(node) || ts.isJsxSelfClosingElement(node) || ts.isJsxFragment(node))\n return true\n return ts.forEachChild(node, containsJSXInExpr) ?? false\n}\n\nfunction escapeHtmlAttr(s: string): string {\n return s.replace(/&/g, '&').replace(/\"/g, '"')\n}\n\nfunction escapeHtmlText(s: string): string {\n // TypeScript's JsxText preserves HTML entities as-is (e.g. \"<\" stays \"<\",\n // not decoded to \"<\"). Since the template is parsed via innerHTML, entities are\n // already valid HTML — pass them through. Only escape raw `<` and raw `&` that\n // are NOT part of existing entities.\n return s.replace(/&(?!(?:#\\d+|#x[\\da-fA-F]+|[a-zA-Z]\\w*);)/g, '&').replace(/</g, '<')\n}\n\n// ─── Static JSX analysis ──────────────────────────────────────────────────────\n\ntype StaticJSXNode = ts.JsxElement | ts.JsxSelfClosingElement | ts.JsxFragment\n\nfunction isStaticJSXNode(node: StaticJSXNode): boolean {\n if (ts.isJsxSelfClosingElement(node)) {\n return isStaticAttrs(node.attributes)\n }\n if (ts.isJsxFragment(node)) {\n return node.children.every(isStaticChild)\n }\n // JsxElement\n return isStaticAttrs(node.openingElement.attributes) && node.children.every(isStaticChild)\n}\n\nfunction isStaticAttrs(attrs: ts.JsxAttributes): boolean {\n return attrs.properties.every((prop) => {\n // Spread attribute — always dynamic\n if (!ts.isJsxAttribute(prop)) return false\n // Boolean shorthand: <input disabled />\n if (!prop.initializer) return true\n // String literal: class=\"foo\"\n if (ts.isStringLiteral(prop.initializer)) return true\n // Must be JsxExpression — the only remaining JsxAttributeValue type\n const expr = (prop.initializer as ts.JsxExpression).expression\n return expr ? isStatic(expr) : true\n })\n}\n\nfunction isStaticChild(child: ts.JsxChild): boolean {\n // Plain text content\n if (ts.isJsxText(child)) return true\n // Nested JSX elements\n if (ts.isJsxSelfClosingElement(child)) return isStaticJSXNode(child)\n if (ts.isJsxElement(child)) return isStaticJSXNode(child)\n if (ts.isJsxFragment(child)) return isStaticJSXNode(child)\n // Must be JsxExpression — the only remaining JsxChild type\n const expr = (child as ts.JsxExpression).expression\n return expr ? isStatic(expr) : true\n}\n\n// ─── General helpers ──────────────────────────────────────────────────────────\n\nfunction isStatic(node: ts.Expression): boolean {\n return (\n ts.isStringLiteral(node) ||\n ts.isNumericLiteral(node) ||\n ts.isNoSubstitutionTemplateLiteral(node) ||\n node.kind === ts.SyntaxKind.TrueKeyword ||\n node.kind === ts.SyntaxKind.FalseKeyword ||\n node.kind === ts.SyntaxKind.NullKeyword ||\n node.kind === ts.SyntaxKind.UndefinedKeyword\n )\n // Note: object/array literals are NOT static — they need runtime application\n // (e.g., style={{ color: \"red\" }} requires Object.assign at runtime).\n}\n\n/** Known pure global functions that don't read signals. */\nconst PURE_CALLS = new Set([\n 'Math.max', 'Math.min', 'Math.abs', 'Math.floor', 'Math.ceil', 'Math.round',\n 'Math.pow', 'Math.sqrt', 'Math.random', 'Math.trunc', 'Math.sign',\n 'Number.parseInt', 'Number.parseFloat', 'Number.isNaN', 'Number.isFinite',\n 'parseInt', 'parseFloat', 'isNaN', 'isFinite',\n 'String.fromCharCode', 'String.fromCodePoint',\n 'Object.keys', 'Object.values', 'Object.entries', 'Object.assign',\n 'Object.freeze', 'Object.create',\n 'Array.from', 'Array.isArray', 'Array.of',\n 'JSON.stringify', 'JSON.parse',\n 'encodeURIComponent', 'decodeURIComponent', 'encodeURI', 'decodeURI',\n 'Date.now',\n])\n\n/** Check if a call expression calls a known pure function with static args. */\nfunction isPureStaticCall(node: ts.CallExpression): boolean {\n const callee = node.expression\n let name = ''\n\n if (ts.isIdentifier(callee)) {\n name = callee.text\n } else if (ts.isPropertyAccessExpression(callee) && ts.isIdentifier(callee.expression)) {\n name = `${callee.expression.text}.${callee.name.text}`\n }\n\n if (!PURE_CALLS.has(name)) return false\n // Pure call with all static arguments → result is static\n return node.arguments.every((arg) => !ts.isSpreadElement(arg) && isStatic(arg))\n}\n\nfunction containsCall(node: ts.Node): boolean {\n if (ts.isCallExpression(node)) {\n // Skip pure calls with static args\n if (isPureStaticCall(node as ts.CallExpression)) return false\n return true\n }\n if (ts.isTaggedTemplateExpression(node)) return true\n // Don't recurse into nested functions — they're self-contained\n if (ts.isArrowFunction(node) || ts.isFunctionExpression(node)) return false\n return ts.forEachChild(node, containsCall) ?? false\n}\n","/**\n * Project scanner — extracts route, component, and island information from source files.\n */\n\nimport * as fs from 'node:fs'\nimport * as path from 'node:path'\n\nexport interface RouteInfo {\n path: string\n name?: string | undefined\n component?: string | undefined\n hasLoader: boolean\n hasGuard: boolean\n params: string[]\n}\n\nexport interface ComponentInfo {\n name: string\n file: string\n hasSignals: boolean\n signalNames: string[]\n props: string[]\n}\n\nexport interface IslandInfo {\n name: string\n file: string\n hydrate: string\n}\n\nexport interface ProjectContext {\n framework: 'pyreon'\n version: string\n generatedAt: string\n routes: RouteInfo[]\n components: ComponentInfo[]\n islands: IslandInfo[]\n}\n\nexport function generateContext(cwd: string): ProjectContext {\n const files = collectSourceFiles(cwd)\n const version = readVersion(cwd)\n\n return {\n framework: 'pyreon',\n version,\n generatedAt: new Date().toISOString(),\n routes: extractRoutes(files, cwd),\n components: extractComponents(files, cwd),\n islands: extractIslands(files, cwd),\n }\n}\n\nfunction collectSourceFiles(cwd: string): string[] {\n const results: string[] = []\n const extensions = new Set(['.tsx', '.jsx', '.ts', '.js'])\n const ignoreDirs = new Set(['node_modules', 'dist', 'lib', '.pyreon', '.git', 'build'])\n\n function walk(dir: string): void {\n let entries: fs.Dirent[]\n try {\n entries = fs.readdirSync(dir, { withFileTypes: true })\n } catch {\n return\n }\n for (const entry of entries) {\n if (entry.name.startsWith('.') && entry.isDirectory()) continue\n if (ignoreDirs.has(entry.name) && entry.isDirectory()) continue\n const fullPath = path.join(dir, entry.name)\n if (entry.isDirectory()) {\n walk(fullPath)\n } else if (entry.isFile() && extensions.has(path.extname(entry.name))) {\n results.push(fullPath)\n }\n }\n }\n\n walk(cwd)\n return results\n}\n\nfunction extractRoutes(files: string[], _cwd: string): RouteInfo[] {\n const routes: RouteInfo[] = []\n\n for (const file of files) {\n let code: string\n try {\n code = fs.readFileSync(file, 'utf-8')\n } catch {\n continue\n }\n\n const routeArrayRe =\n /(?:createRouter\\s*\\(\\s*\\[|(?:const|let)\\s+routes\\s*(?::\\s*RouteRecord\\[\\])?\\s*=\\s*\\[)([\\s\\S]*?)\\]/g\n let match: RegExpExecArray | null\n for (match = routeArrayRe.exec(code); match; match = routeArrayRe.exec(code)) {\n const block = match[1] ?? ''\n const routeObjRe = /path\\s*:\\s*[\"']([^\"']+)[\"']/g\n let routeMatch: RegExpExecArray | null\n for (routeMatch = routeObjRe.exec(block); routeMatch; routeMatch = routeObjRe.exec(block)) {\n const routePath = routeMatch[1] ?? ''\n const surroundingStart = Math.max(0, routeMatch.index - 50)\n const surroundingEnd = Math.min(block.length, routeMatch.index + 200)\n const surrounding = block.slice(surroundingStart, surroundingEnd)\n\n routes.push({\n path: routePath,\n name: surrounding.match(/name\\s*:\\s*[\"']([^\"']+)[\"']/)?.[1],\n hasLoader: /loader\\s*:/.test(surrounding),\n hasGuard: /beforeEnter\\s*:|beforeLeave\\s*:/.test(surrounding),\n params: extractParams(routePath),\n })\n }\n }\n }\n\n return routes\n}\n\nfunction extractComponents(files: string[], cwd: string): ComponentInfo[] {\n const components: ComponentInfo[] = []\n\n for (const file of files) {\n let code: string\n try {\n code = fs.readFileSync(file, 'utf-8')\n } catch {\n continue\n }\n\n const componentRe =\n /(?:export\\s+)?(?:const|function)\\s+([A-Z]\\w*)\\s*(?::\\s*ComponentFn<[^>]+>\\s*)?=?\\s*\\(?(?:\\s*\\{?\\s*([^)]*?)\\s*\\}?\\s*)?\\)?\\s*(?:=>|{)/g\n let match: RegExpExecArray | null\n\n for (match = componentRe.exec(code); match; match = componentRe.exec(code)) {\n const name = match[1] ?? 'Unknown'\n const propsStr = match[2] ?? ''\n const props = propsStr\n .split(/[,;]/)\n .map((p) => p.trim().replace(/[{}]/g, '').trim().split(':')[0]?.split('=')[0]?.trim() ?? '')\n .filter((p) => p && p !== 'props')\n\n const bodyStart = match.index + match[0].length\n const body = code.slice(bodyStart, Math.min(code.length, bodyStart + 2000))\n const signalNames: string[] = []\n const signalRe = /(?:const|let)\\s+(\\w+)\\s*=\\s*signal\\s*[<(]/g\n let sigMatch: RegExpExecArray | null\n for (sigMatch = signalRe.exec(body); sigMatch; sigMatch = signalRe.exec(body)) {\n if (sigMatch[1]) signalNames.push(sigMatch[1])\n }\n\n components.push({\n name,\n file: path.relative(cwd, file),\n hasSignals: signalNames.length > 0,\n signalNames,\n props,\n })\n }\n }\n\n return components\n}\n\nfunction extractIslands(files: string[], cwd: string): IslandInfo[] {\n const islands: IslandInfo[] = []\n\n for (const file of files) {\n let code: string\n try {\n code = fs.readFileSync(file, 'utf-8')\n } catch {\n continue\n }\n\n const islandRe =\n /island\\s*\\(\\s*\\(\\)\\s*=>\\s*import\\(.+?\\)\\s*,\\s*\\{[^}]*name\\s*:\\s*[\"']([^\"']+)[\"'][^}]*?(?:hydrate\\s*:\\s*[\"']([^\"']+)[\"'])?[^}]*\\}/g\n let match: RegExpExecArray | null\n for (match = islandRe.exec(code); match; match = islandRe.exec(code)) {\n if (match[1]) {\n islands.push({\n name: match[1],\n file: path.relative(cwd, file),\n hydrate: match[2] ?? 'load',\n })\n }\n }\n }\n\n return islands\n}\n\nfunction extractParams(routePath: string): string[] {\n const params: string[] = []\n const paramRe = /:(\\w+)\\??/g\n let match: RegExpExecArray | null\n for (match = paramRe.exec(routePath); match; match = paramRe.exec(routePath)) {\n if (match[1]) params.push(match[1])\n }\n return params\n}\n\nfunction readVersion(cwd: string): string {\n try {\n const pkg = JSON.parse(fs.readFileSync(path.join(cwd, 'package.json'), 'utf-8'))\n const deps: Record<string, unknown> = { ...pkg.dependencies, ...pkg.devDependencies }\n for (const [name, ver] of Object.entries(deps)) {\n if (name.startsWith('@pyreon/') && typeof ver === 'string') return ver.replace(/^[\\^~]/, '')\n }\n return (pkg.version as string) || 'unknown'\n } catch {\n return 'unknown'\n }\n}\n","/**\n * React Pattern Interceptor — detects React/Vue patterns in code and provides\n * structured diagnostics with exact fix suggestions for AI-assisted migration.\n *\n * Two modes:\n * - `detectReactPatterns(code)` — returns diagnostics only (non-destructive)\n * - `migrateReactCode(code)` — applies auto-fixes and returns transformed code\n *\n * Designed for three consumers:\n * 1. Compiler pre-pass (warnings during build)\n * 2. CLI `pyreon doctor` (project-wide scanning)\n * 3. MCP server `migrate_react` / `validate` tools (AI agent integration)\n */\n\nimport ts from 'typescript'\n\n// ═══════════════════════════════════════════════════════════════════════════════\n// Types\n// ═══════════════════════════════════════════════════════════════════════════════\n\nexport type ReactDiagnosticCode =\n | 'react-import'\n | 'react-dom-import'\n | 'react-router-import'\n | 'use-state'\n | 'use-effect-mount'\n | 'use-effect-deps'\n | 'use-effect-no-deps'\n | 'use-memo'\n | 'use-callback'\n | 'use-ref-dom'\n | 'use-ref-box'\n | 'use-reducer'\n | 'use-layout-effect'\n | 'memo-wrapper'\n | 'forward-ref'\n | 'class-name-prop'\n | 'html-for-prop'\n | 'on-change-input'\n | 'dangerously-set-inner-html'\n | 'dot-value-signal'\n | 'array-map-jsx'\n | 'key-on-for-child'\n | 'create-context-import'\n | 'use-context-import'\n\nexport interface ReactDiagnostic {\n /** Machine-readable code for filtering and programmatic handling */\n code: ReactDiagnosticCode\n /** Human-readable message explaining the issue */\n message: string\n /** 1-based line number */\n line: number\n /** 0-based column */\n column: number\n /** The code as written */\n current: string\n /** The suggested Pyreon equivalent */\n suggested: string\n /** Whether migrateReactCode can auto-fix this */\n fixable: boolean\n}\n\nexport interface MigrationChange {\n type: 'replace' | 'remove' | 'add'\n line: number\n description: string\n}\n\nexport interface MigrationResult {\n /** Transformed source code */\n code: string\n /** All detected patterns (including unfixable ones) */\n diagnostics: ReactDiagnostic[]\n /** Description of changes applied */\n changes: MigrationChange[]\n}\n\n// ═══════════════════════════════════════════════════════════════════════════════\n// React Hook → Pyreon mapping\n// ═══════════════════════════════════════════════════════════════════════════════\n\ninterface HookMapping {\n pyreonFn: string\n pyreonImport: string\n description: string\n example: string\n}\n\nconst _REACT_HOOK_MAP: Record<string, HookMapping> = {\n useState: {\n pyreonFn: 'signal',\n pyreonImport: '@pyreon/reactivity',\n description: 'Signals are callable functions — read: count(), write: count.set(5)',\n example:\n 'const count = signal(0)\\n// Read: count() Write: count.set(5) Update: count.update(n => n + 1)',\n },\n useEffect: {\n pyreonFn: 'effect',\n pyreonImport: '@pyreon/reactivity',\n description: 'Effects auto-track signal dependencies — no dependency array needed',\n example: 'effect(() => {\\n console.log(count()) // auto-subscribes to count\\n})',\n },\n useLayoutEffect: {\n pyreonFn: 'effect',\n pyreonImport: '@pyreon/reactivity',\n description: 'Pyreon effects run synchronously after signal updates',\n example: 'effect(() => {\\n // runs sync after signal changes\\n})',\n },\n useMemo: {\n pyreonFn: 'computed',\n pyreonImport: '@pyreon/reactivity',\n description: 'Computed values auto-track dependencies and memoize',\n example: 'const doubled = computed(() => count() * 2)',\n },\n useCallback: {\n pyreonFn: '(plain function)',\n pyreonImport: '',\n description:\n 'Not needed — Pyreon components run once, so closures never go stale. Use a plain function',\n example: 'const handleClick = () => doSomething(count())',\n },\n useReducer: {\n pyreonFn: 'signal',\n pyreonImport: '@pyreon/reactivity',\n description: 'Use signal with update() for reducer-like patterns',\n example:\n 'const state = signal(initialState)\\nconst dispatch = (action) => state.update(s => reducer(s, action))',\n },\n}\n\n/** React import sources → Pyreon equivalents */\nconst IMPORT_REWRITES: Record<string, string | null> = {\n react: '@pyreon/core',\n 'react-dom': '@pyreon/runtime-dom',\n 'react-dom/client': '@pyreon/runtime-dom',\n 'react-dom/server': '@pyreon/runtime-server',\n 'react-router': '@pyreon/router',\n 'react-router-dom': '@pyreon/router',\n}\n\n/** React specifiers that map to specific Pyreon imports */\nconst SPECIFIER_REWRITES: Record<string, { name: string; from: string }> = {\n useState: { name: 'signal', from: '@pyreon/reactivity' },\n useEffect: { name: 'effect', from: '@pyreon/reactivity' },\n useLayoutEffect: { name: 'effect', from: '@pyreon/reactivity' },\n useMemo: { name: 'computed', from: '@pyreon/reactivity' },\n useReducer: { name: 'signal', from: '@pyreon/reactivity' },\n useRef: { name: 'signal', from: '@pyreon/reactivity' },\n createContext: { name: 'createContext', from: '@pyreon/core' },\n useContext: { name: 'useContext', from: '@pyreon/core' },\n Fragment: { name: 'Fragment', from: '@pyreon/core' },\n Suspense: { name: 'Suspense', from: '@pyreon/core' },\n lazy: { name: 'lazy', from: '@pyreon/core' },\n memo: { name: '', from: '' }, // removed, not needed\n forwardRef: { name: '', from: '' }, // removed, not needed\n createRoot: { name: 'mount', from: '@pyreon/runtime-dom' },\n hydrateRoot: { name: 'hydrateRoot', from: '@pyreon/runtime-dom' },\n // React Router\n useNavigate: { name: 'useRouter', from: '@pyreon/router' },\n useParams: { name: 'useRoute', from: '@pyreon/router' },\n useLocation: { name: 'useRoute', from: '@pyreon/router' },\n Link: { name: 'RouterLink', from: '@pyreon/router' },\n NavLink: { name: 'RouterLink', from: '@pyreon/router' },\n Outlet: { name: 'RouterView', from: '@pyreon/router' },\n useSearchParams: { name: 'useSearchParams', from: '@pyreon/router' },\n}\n\n/** JSX attribute rewrites (React → standard HTML) */\nconst JSX_ATTR_REWRITES: Record<string, string> = {\n className: 'class',\n htmlFor: 'for',\n}\n\n// ═══════════════════════════════════════════════════════════════════════════════\n// Detection (diagnostic-only, no modifications)\n// ═══════════════════════════════════════════════════════════════════════════════\n\ninterface DetectContext {\n sf: ts.SourceFile\n code: string\n diagnostics: ReactDiagnostic[]\n reactImportedHooks: Set<string>\n}\n\nfunction detectGetNodeText(ctx: DetectContext, node: ts.Node): string {\n return ctx.code.slice(node.getStart(ctx.sf), node.getEnd())\n}\n\nfunction detectDiag(\n ctx: DetectContext,\n node: ts.Node,\n diagCode: ReactDiagnosticCode,\n message: string,\n current: string,\n suggested: string,\n fixable: boolean,\n): void {\n const { line, character } = ctx.sf.getLineAndCharacterOfPosition(node.getStart(ctx.sf))\n ctx.diagnostics.push({\n code: diagCode,\n message,\n line: line + 1,\n column: character,\n current: current.trim(),\n suggested: suggested.trim(),\n fixable,\n })\n}\n\nfunction detectImportDeclaration(ctx: DetectContext, node: ts.ImportDeclaration): void {\n if (!node.moduleSpecifier) return\n const source = (node.moduleSpecifier as ts.StringLiteral).text\n const pyreonSource = IMPORT_REWRITES[source]\n\n if (pyreonSource !== undefined) {\n if (node.importClause?.namedBindings && ts.isNamedImports(node.importClause.namedBindings)) {\n for (const spec of node.importClause.namedBindings.elements) {\n ctx.reactImportedHooks.add(spec.name.text)\n }\n }\n\n const diagCode = source.startsWith('react-router')\n ? 'react-router-import'\n : source.startsWith('react-dom')\n ? 'react-dom-import'\n : 'react-import'\n\n detectDiag(\n ctx,\n node,\n diagCode,\n `Import from '${source}' is a React package. Use Pyreon equivalent.`,\n detectGetNodeText(ctx, node),\n pyreonSource\n ? `import { ... } from \"${pyreonSource}\"`\n : 'Remove this import — not needed in Pyreon',\n true,\n )\n }\n}\n\nfunction detectUseState(ctx: DetectContext, node: ts.CallExpression): void {\n const parent = node.parent\n if (\n ts.isVariableDeclaration(parent) &&\n parent.name &&\n ts.isArrayBindingPattern(parent.name) &&\n parent.name.elements.length >= 1\n ) {\n const firstEl = parent.name.elements[0]\n const valueName =\n firstEl && ts.isBindingElement(firstEl) ? (firstEl.name as ts.Identifier).text : 'value'\n const initArg = node.arguments[0] ? detectGetNodeText(ctx, node.arguments[0]) : 'undefined'\n\n detectDiag(\n ctx,\n node,\n 'use-state',\n `useState is a React API. In Pyreon, use signal(). Read: ${valueName}(), Write: ${valueName}.set(x)`,\n detectGetNodeText(ctx, parent),\n `${valueName} = signal(${initArg})`,\n true,\n )\n } else {\n detectDiag(\n ctx,\n node,\n 'use-state',\n 'useState is a React API. In Pyreon, use signal().',\n detectGetNodeText(ctx, node),\n 'signal(initialValue)',\n true,\n )\n }\n}\n\nfunction callbackHasCleanup(callbackArg: ts.Expression): boolean {\n if (!ts.isArrowFunction(callbackArg) && !ts.isFunctionExpression(callbackArg)) return false\n const body = callbackArg.body\n if (!ts.isBlock(body)) return false\n for (const stmt of body.statements) {\n if (ts.isReturnStatement(stmt) && stmt.expression) return true\n }\n return false\n}\n\nfunction detectUseEffect(ctx: DetectContext, node: ts.CallExpression): void {\n const hookName = (node.expression as ts.Identifier).text\n const depsArg = node.arguments[1]\n const callbackArg = node.arguments[0]\n\n if (depsArg && ts.isArrayLiteralExpression(depsArg) && depsArg.elements.length === 0) {\n const hasCleanup = callbackArg ? callbackHasCleanup(callbackArg) : false\n\n detectDiag(\n ctx,\n node,\n 'use-effect-mount',\n `${hookName} with empty deps [] means \"run once on mount\". Use onMount() in Pyreon.`,\n detectGetNodeText(ctx, node),\n hasCleanup\n ? 'onMount(() => {\\n // setup...\\n return () => { /* cleanup */ }\\n})'\n : 'onMount(() => {\\n // setup...\\n})',\n true,\n )\n } else if (depsArg && ts.isArrayLiteralExpression(depsArg)) {\n detectDiag(\n ctx,\n node,\n 'use-effect-deps',\n `${hookName} with dependency array. In Pyreon, effect() auto-tracks dependencies — no array needed.`,\n detectGetNodeText(ctx, node),\n 'effect(() => {\\n // reads are auto-tracked\\n})',\n true,\n )\n } else if (!depsArg) {\n detectDiag(\n ctx,\n node,\n 'use-effect-no-deps',\n `${hookName} with no dependency array. In Pyreon, use effect() — it auto-tracks signal reads.`,\n detectGetNodeText(ctx, node),\n 'effect(() => {\\n // runs when accessed signals change\\n})',\n true,\n )\n }\n}\n\nfunction detectUseMemo(ctx: DetectContext, node: ts.CallExpression): void {\n const computeFn = node.arguments[0]\n const computeText = computeFn ? detectGetNodeText(ctx, computeFn) : '() => value'\n\n detectDiag(\n ctx,\n node,\n 'use-memo',\n 'useMemo is a React API. In Pyreon, use computed() — dependencies auto-tracked.',\n detectGetNodeText(ctx, node),\n `computed(${computeText})`,\n true,\n )\n}\n\nfunction detectUseCallback(ctx: DetectContext, node: ts.CallExpression): void {\n const callbackFn = node.arguments[0]\n const callbackText = callbackFn ? detectGetNodeText(ctx, callbackFn) : '() => {}'\n\n detectDiag(\n ctx,\n node,\n 'use-callback',\n 'useCallback is not needed in Pyreon. Components run once, so closures never go stale. Use a plain function.',\n detectGetNodeText(ctx, node),\n callbackText,\n true,\n )\n}\n\nfunction detectUseRef(ctx: DetectContext, node: ts.CallExpression): void {\n const arg = node.arguments[0]\n const isNullInit =\n arg &&\n (arg.kind === ts.SyntaxKind.NullKeyword || (ts.isIdentifier(arg) && arg.text === 'undefined'))\n\n if (isNullInit) {\n detectDiag(\n ctx,\n node,\n 'use-ref-dom',\n 'useRef(null) for DOM refs. In Pyreon, use createRef() from @pyreon/core.',\n detectGetNodeText(ctx, node),\n 'createRef()',\n true,\n )\n } else {\n const initText = arg ? detectGetNodeText(ctx, arg) : 'undefined'\n detectDiag(\n ctx,\n node,\n 'use-ref-box',\n 'useRef for mutable values. In Pyreon, use signal() — it works the same way but is reactive.',\n detectGetNodeText(ctx, node),\n `signal(${initText})`,\n true,\n )\n }\n}\n\nfunction detectUseReducer(ctx: DetectContext, node: ts.CallExpression): void {\n detectDiag(\n ctx,\n node,\n 'use-reducer',\n 'useReducer is a React API. In Pyreon, use signal() with update() for reducer patterns.',\n detectGetNodeText(ctx, node),\n 'const state = signal(initialState)\\nconst dispatch = (action) => state.update(s => reducer(s, action))',\n false,\n )\n}\n\nfunction isCallToReactDot(callee: ts.Expression, methodName: string): boolean {\n return (\n ts.isPropertyAccessExpression(callee) &&\n ts.isIdentifier(callee.expression) &&\n callee.expression.text === 'React' &&\n callee.name.text === methodName\n )\n}\n\nfunction detectMemoWrapper(ctx: DetectContext, node: ts.CallExpression): void {\n const callee = node.expression\n const isMemo =\n (ts.isIdentifier(callee) && callee.text === 'memo') || isCallToReactDot(callee, 'memo')\n\n if (isMemo) {\n const inner = node.arguments[0]\n const innerText = inner ? detectGetNodeText(ctx, inner) : 'Component'\n\n detectDiag(\n ctx,\n node,\n 'memo-wrapper',\n 'memo() is not needed in Pyreon. Components run once — only signals trigger updates, not re-renders.',\n detectGetNodeText(ctx, node),\n innerText,\n true,\n )\n }\n}\n\nfunction detectForwardRef(ctx: DetectContext, node: ts.CallExpression): void {\n const callee = node.expression\n const isForwardRef =\n (ts.isIdentifier(callee) && callee.text === 'forwardRef') ||\n isCallToReactDot(callee, 'forwardRef')\n\n if (isForwardRef) {\n detectDiag(\n ctx,\n node,\n 'forward-ref',\n 'forwardRef is not needed in Pyreon. Pass ref as a regular prop.',\n detectGetNodeText(ctx, node),\n '// Just pass ref as a prop:\\nconst MyInput = (props) => <input ref={props.ref} />',\n true,\n )\n }\n}\n\nfunction detectJsxAttributes(ctx: DetectContext, node: ts.JsxAttribute): void {\n const attrName = (node.name as ts.Identifier).text\n\n if (attrName in JSX_ATTR_REWRITES) {\n const htmlAttr = JSX_ATTR_REWRITES[attrName] as string\n detectDiag(\n ctx,\n node,\n attrName === 'className' ? 'class-name-prop' : 'html-for-prop',\n `'${attrName}' is a React JSX attribute. Use '${htmlAttr}' in Pyreon (standard HTML).`,\n detectGetNodeText(ctx, node),\n detectGetNodeText(ctx, node).replace(attrName, htmlAttr),\n true,\n )\n }\n\n if (attrName === 'onChange') {\n const jsxElement = findParentJsxElement(node)\n if (jsxElement) {\n const tagName = getJsxTagName(jsxElement)\n if (tagName === 'input' || tagName === 'textarea' || tagName === 'select') {\n detectDiag(\n ctx,\n node,\n 'on-change-input',\n `onChange on <${tagName}> fires on blur in Pyreon (native DOM behavior). For keypress-by-keypress updates, use onInput.`,\n detectGetNodeText(ctx, node),\n detectGetNodeText(ctx, node).replace('onChange', 'onInput'),\n true,\n )\n }\n }\n }\n\n if (attrName === 'dangerouslySetInnerHTML') {\n detectDiag(\n ctx,\n node,\n 'dangerously-set-inner-html',\n 'dangerouslySetInnerHTML is React-specific. Use innerHTML prop in Pyreon.',\n detectGetNodeText(ctx, node),\n 'innerHTML={htmlString}',\n true,\n )\n }\n}\n\nfunction detectDotValueSignal(ctx: DetectContext, node: ts.PropertyAccessExpression): void {\n const varName = (node.expression as ts.Identifier).text\n const parent = node.parent\n if (ts.isBinaryExpression(parent) && parent.left === node) {\n detectDiag(\n ctx,\n node,\n 'dot-value-signal',\n `'${varName}.value' looks like a Vue ref pattern. Pyreon signals are callable functions. Use ${varName}.set(x) to write.`,\n detectGetNodeText(ctx, parent),\n `${varName}.set(${detectGetNodeText(ctx, parent.right)})`,\n false,\n )\n }\n}\n\nfunction detectArrayMapJsx(ctx: DetectContext, node: ts.CallExpression): void {\n const parent = node.parent\n if (ts.isJsxExpression(parent)) {\n const arrayExpr = detectGetNodeText(\n ctx,\n (node.expression as ts.PropertyAccessExpression).expression,\n )\n const mapCallback = node.arguments[0]\n const mapCallbackText = mapCallback\n ? detectGetNodeText(ctx, mapCallback)\n : 'item => <li>{item}</li>'\n\n detectDiag(\n ctx,\n node,\n 'array-map-jsx',\n 'Array.map() in JSX is not reactive in Pyreon. Use <For> for efficient keyed list rendering.',\n detectGetNodeText(ctx, node),\n `<For each={${arrayExpr}} by={item => item.id}>\\n {${mapCallbackText}}\\n</For>`,\n false,\n )\n }\n}\n\nfunction isCallToHook(node: ts.Node, hookName: string): node is ts.CallExpression {\n return (\n ts.isCallExpression(node) &&\n ts.isIdentifier(node.expression) &&\n node.expression.text === hookName\n )\n}\n\nfunction isCallToEffectHook(node: ts.Node): node is ts.CallExpression {\n return (\n ts.isCallExpression(node) &&\n ts.isIdentifier(node.expression) &&\n (node.expression.text === 'useEffect' || node.expression.text === 'useLayoutEffect')\n )\n}\n\nfunction isMapCallExpression(node: ts.Node): node is ts.CallExpression {\n return (\n ts.isCallExpression(node) &&\n ts.isPropertyAccessExpression(node.expression) &&\n ts.isIdentifier(node.expression.name) &&\n node.expression.name.text === 'map'\n )\n}\n\nfunction isDotValueAccess(node: ts.Node): node is ts.PropertyAccessExpression {\n return (\n ts.isPropertyAccessExpression(node) &&\n ts.isIdentifier(node.name) &&\n node.name.text === 'value' &&\n ts.isIdentifier(node.expression)\n )\n}\n\nfunction detectVisitNode(ctx: DetectContext, node: ts.Node): void {\n if (ts.isImportDeclaration(node)) detectImportDeclaration(ctx, node)\n if (isCallToHook(node, 'useState')) detectUseState(ctx, node)\n if (isCallToEffectHook(node)) detectUseEffect(ctx, node)\n if (isCallToHook(node, 'useMemo')) detectUseMemo(ctx, node)\n if (isCallToHook(node, 'useCallback')) detectUseCallback(ctx, node)\n if (isCallToHook(node, 'useRef')) detectUseRef(ctx, node)\n if (isCallToHook(node, 'useReducer')) detectUseReducer(ctx, node)\n if (ts.isCallExpression(node)) detectMemoWrapper(ctx, node)\n if (ts.isCallExpression(node)) detectForwardRef(ctx, node)\n if (ts.isJsxAttribute(node) && ts.isIdentifier(node.name)) detectJsxAttributes(ctx, node)\n if (isDotValueAccess(node)) detectDotValueSignal(ctx, node)\n if (isMapCallExpression(node)) detectArrayMapJsx(ctx, node)\n}\n\nfunction detectVisit(ctx: DetectContext, node: ts.Node): void {\n ts.forEachChild(node, (child) => {\n detectVisitNode(ctx, child)\n detectVisit(ctx, child)\n })\n}\n\nexport function detectReactPatterns(code: string, filename = 'input.tsx'): ReactDiagnostic[] {\n const sf = ts.createSourceFile(filename, code, ts.ScriptTarget.ESNext, true, ts.ScriptKind.TSX)\n const ctx: DetectContext = {\n sf,\n code,\n diagnostics: [],\n reactImportedHooks: new Set<string>(),\n }\n\n detectVisit(ctx, sf)\n return ctx.diagnostics\n}\n\n// ═══════════════════════════════════════════════════════════════════════════════\n// Migration (detection + auto-fix)\n// ═══════════════════════════════════════════════════════════════════════════════\n\ntype Replacement = { start: number; end: number; text: string }\n\ninterface MigrateContext {\n sf: ts.SourceFile\n code: string\n replacements: Replacement[]\n changes: MigrationChange[]\n pyreonImports: Map<string, Set<string>>\n importsToRemove: Set<ts.ImportDeclaration>\n specifierRewrites: Map<ts.ImportSpecifier, { name: string; from: string }>\n}\n\nfunction migrateAddImport(ctx: MigrateContext, source: string, specifier: string): void {\n if (!source || !specifier) return\n let specs = ctx.pyreonImports.get(source)\n if (!specs) {\n specs = new Set()\n ctx.pyreonImports.set(source, specs)\n }\n specs.add(specifier)\n}\n\nfunction migrateReplace(ctx: MigrateContext, node: ts.Node, text: string): void {\n ctx.replacements.push({ start: node.getStart(ctx.sf), end: node.getEnd(), text })\n}\n\nfunction migrateGetNodeText(ctx: MigrateContext, node: ts.Node): string {\n return ctx.code.slice(node.getStart(ctx.sf), node.getEnd())\n}\n\nfunction migrateGetLine(ctx: MigrateContext, node: ts.Node): number {\n return ctx.sf.getLineAndCharacterOfPosition(node.getStart(ctx.sf)).line + 1\n}\n\nfunction migrateImportDeclaration(ctx: MigrateContext, node: ts.ImportDeclaration): void {\n if (!node.moduleSpecifier) return\n const source = (node.moduleSpecifier as ts.StringLiteral).text\n if (!(source in IMPORT_REWRITES)) return\n\n if (node.importClause?.namedBindings && ts.isNamedImports(node.importClause.namedBindings)) {\n for (const spec of node.importClause.namedBindings.elements) {\n const name = spec.name.text\n const rewrite = SPECIFIER_REWRITES[name]\n if (rewrite) {\n if (rewrite.name) {\n migrateAddImport(ctx, rewrite.from, rewrite.name)\n }\n ctx.specifierRewrites.set(spec, rewrite)\n }\n }\n }\n ctx.importsToRemove.add(node)\n}\n\nfunction migrateUseState(ctx: MigrateContext, node: ts.CallExpression): void {\n const parent = node.parent\n if (\n ts.isVariableDeclaration(parent) &&\n parent.name &&\n ts.isArrayBindingPattern(parent.name) &&\n parent.name.elements.length >= 1\n ) {\n const firstEl = parent.name.elements[0]\n const valueName =\n firstEl && ts.isBindingElement(firstEl) ? (firstEl.name as ts.Identifier).text : 'value'\n const initArg = node.arguments[0] ? migrateGetNodeText(ctx, node.arguments[0]) : 'undefined'\n\n const declStart = parent.getStart(ctx.sf)\n const declEnd = parent.getEnd()\n ctx.replacements.push({\n start: declStart,\n end: declEnd,\n text: `${valueName} = signal(${initArg})`,\n })\n migrateAddImport(ctx, '@pyreon/reactivity', 'signal')\n ctx.changes.push({\n type: 'replace',\n line: migrateGetLine(ctx, node),\n description: `useState → signal: ${valueName}`,\n })\n }\n}\n\nfunction migrateUseEffect(ctx: MigrateContext, node: ts.CallExpression): void {\n const depsArg = node.arguments[1]\n const callbackArg = node.arguments[0]\n const hookName = (node.expression as ts.Identifier).text\n\n if (\n depsArg &&\n ts.isArrayLiteralExpression(depsArg) &&\n depsArg.elements.length === 0 &&\n callbackArg\n ) {\n const callbackText = migrateGetNodeText(ctx, callbackArg)\n migrateReplace(ctx, node, `onMount(${callbackText})`)\n migrateAddImport(ctx, '@pyreon/core', 'onMount')\n ctx.changes.push({\n type: 'replace',\n line: migrateGetLine(ctx, node),\n description: `${hookName}(fn, []) → onMount(fn)`,\n })\n } else if (callbackArg) {\n const callbackText = migrateGetNodeText(ctx, callbackArg)\n migrateReplace(ctx, node, `effect(${callbackText})`)\n migrateAddImport(ctx, '@pyreon/reactivity', 'effect')\n ctx.changes.push({\n type: 'replace',\n line: migrateGetLine(ctx, node),\n description: `${hookName} → effect (auto-tracks deps)`,\n })\n }\n}\n\nfunction migrateUseMemo(ctx: MigrateContext, node: ts.CallExpression): void {\n const computeFn = node.arguments[0]\n if (computeFn) {\n migrateReplace(ctx, node, `computed(${migrateGetNodeText(ctx, computeFn)})`)\n migrateAddImport(ctx, '@pyreon/reactivity', 'computed')\n ctx.changes.push({\n type: 'replace',\n line: migrateGetLine(ctx, node),\n description: 'useMemo → computed (auto-tracks deps)',\n })\n }\n}\n\nfunction migrateUseCallback(ctx: MigrateContext, node: ts.CallExpression): void {\n const callbackFn = node.arguments[0]\n if (callbackFn) {\n migrateReplace(ctx, node, migrateGetNodeText(ctx, callbackFn))\n ctx.changes.push({\n type: 'replace',\n line: migrateGetLine(ctx, node),\n description: 'useCallback → plain function (not needed in Pyreon)',\n })\n }\n}\n\nfunction migrateUseRef(ctx: MigrateContext, node: ts.CallExpression): void {\n const arg = node.arguments[0]\n const isNullInit =\n arg &&\n (arg.kind === ts.SyntaxKind.NullKeyword || (ts.isIdentifier(arg) && arg.text === 'undefined'))\n\n if (isNullInit || !arg) {\n migrateReplace(ctx, node, 'createRef()')\n migrateAddImport(ctx, '@pyreon/core', 'createRef')\n ctx.changes.push({\n type: 'replace',\n line: migrateGetLine(ctx, node),\n description: 'useRef(null) → createRef()',\n })\n } else {\n migrateReplace(ctx, node, `signal(${migrateGetNodeText(ctx, arg)})`)\n migrateAddImport(ctx, '@pyreon/reactivity', 'signal')\n ctx.changes.push({\n type: 'replace',\n line: migrateGetLine(ctx, node),\n description: 'useRef(value) → signal(value)',\n })\n }\n}\n\nfunction migrateMemoWrapper(ctx: MigrateContext, node: ts.CallExpression): void {\n const callee = node.expression\n const isMemo =\n (ts.isIdentifier(callee) && callee.text === 'memo') || isCallToReactDot(callee, 'memo')\n\n if (isMemo && node.arguments[0]) {\n migrateReplace(ctx, node, migrateGetNodeText(ctx, node.arguments[0]))\n ctx.changes.push({\n type: 'remove',\n line: migrateGetLine(ctx, node),\n description: 'Removed memo() wrapper (not needed in Pyreon)',\n })\n }\n}\n\nfunction migrateForwardRef(ctx: MigrateContext, node: ts.CallExpression): void {\n const callee = node.expression\n const isForwardRef =\n (ts.isIdentifier(callee) && callee.text === 'forwardRef') ||\n isCallToReactDot(callee, 'forwardRef')\n\n if (isForwardRef && node.arguments[0]) {\n migrateReplace(ctx, node, migrateGetNodeText(ctx, node.arguments[0]))\n ctx.changes.push({\n type: 'remove',\n line: migrateGetLine(ctx, node),\n description: 'Removed forwardRef wrapper (pass ref as normal prop in Pyreon)',\n })\n }\n}\n\nfunction migrateJsxAttributes(ctx: MigrateContext, node: ts.JsxAttribute): void {\n const attrName = (node.name as ts.Identifier).text\n\n if (attrName in JSX_ATTR_REWRITES) {\n const htmlAttr = JSX_ATTR_REWRITES[attrName] as string\n ctx.replacements.push({\n start: node.name.getStart(ctx.sf),\n end: node.name.getEnd(),\n text: htmlAttr,\n })\n ctx.changes.push({\n type: 'replace',\n line: migrateGetLine(ctx, node),\n description: `${attrName} → ${htmlAttr}`,\n })\n }\n\n if (attrName === 'onChange') {\n const jsxElement = findParentJsxElement(node)\n if (jsxElement) {\n const tagName = getJsxTagName(jsxElement)\n if (tagName === 'input' || tagName === 'textarea' || tagName === 'select') {\n ctx.replacements.push({\n start: node.name.getStart(ctx.sf),\n end: node.name.getEnd(),\n text: 'onInput',\n })\n ctx.changes.push({\n type: 'replace',\n line: migrateGetLine(ctx, node),\n description: `onChange on <${tagName}> → onInput (native DOM events)`,\n })\n }\n }\n }\n\n if (attrName === 'dangerouslySetInnerHTML') {\n migrateDangerouslySetInnerHTML(ctx, node)\n }\n}\n\nfunction migrateDangerouslySetInnerHTML(ctx: MigrateContext, node: ts.JsxAttribute): void {\n if (!node.initializer || !ts.isJsxExpression(node.initializer) || !node.initializer.expression) {\n return\n }\n const expr = node.initializer.expression\n if (!ts.isObjectLiteralExpression(expr)) return\n\n const htmlProp = expr.properties.find(\n (p) => ts.isPropertyAssignment(p) && ts.isIdentifier(p.name) && p.name.text === '__html',\n ) as ts.PropertyAssignment | undefined\n\n if (htmlProp) {\n const valueText = migrateGetNodeText(ctx, htmlProp.initializer)\n migrateReplace(ctx, node, `innerHTML={${valueText}}`)\n ctx.changes.push({\n type: 'replace',\n line: migrateGetLine(ctx, node),\n description: 'dangerouslySetInnerHTML → innerHTML',\n })\n }\n}\n\nfunction applyReplacements(code: string, ctx: MigrateContext): string {\n // Remove React import declarations\n for (const imp of ctx.importsToRemove) {\n ctx.replacements.push({ start: imp.getStart(ctx.sf), end: imp.getEnd(), text: '' })\n ctx.changes.push({\n type: 'remove',\n line: ctx.sf.getLineAndCharacterOfPosition(imp.getStart(ctx.sf)).line + 1,\n description: 'Removed React import',\n })\n }\n\n // Sort descending for dedup (outermost replacements win over inner overlapping ones)\n ctx.replacements.sort((a, b) => b.start - a.start)\n\n // Deduplicate overlapping replacements (keep the outermost / first added)\n const applied = new Set<string>()\n const deduped: Replacement[] = []\n for (const r of ctx.replacements) {\n const key = `${r.start}:${r.end}`\n let overlaps = false\n for (const d of deduped) {\n if (r.start < d.end && r.end > d.start) {\n overlaps = true\n break\n }\n }\n if (!overlaps && !applied.has(key)) {\n applied.add(key)\n deduped.push(r)\n }\n }\n\n // Re-sort ascending for string builder — O(n) single join\n deduped.sort((a, b) => a.start - b.start)\n const parts: string[] = []\n let lastPos = 0\n for (const r of deduped) {\n parts.push(code.slice(lastPos, r.start))\n parts.push(r.text)\n lastPos = r.end\n }\n parts.push(code.slice(lastPos))\n return parts.join('')\n}\n\nfunction insertPyreonImports(code: string, pyreonImports: Map<string, Set<string>>): string {\n if (pyreonImports.size === 0) return code\n\n const importLines: string[] = []\n const sorted = [...pyreonImports.entries()].sort(([a], [b]) => a.localeCompare(b))\n for (const [source, specs] of sorted) {\n const specList = [...specs].sort().join(', ')\n importLines.push(`import { ${specList} } from \"${source}\"`)\n }\n const importBlock = importLines.join('\\n')\n\n const lastImportEnd = findLastImportEnd(code)\n if (lastImportEnd > 0) {\n return `${code.slice(0, lastImportEnd)}\\n${importBlock}${code.slice(lastImportEnd)}`\n }\n return `${importBlock}\\n\\n${code}`\n}\n\nfunction migrateVisitNode(ctx: MigrateContext, node: ts.Node): void {\n if (ts.isImportDeclaration(node)) migrateImportDeclaration(ctx, node)\n if (isCallToHook(node, 'useState')) migrateUseState(ctx, node)\n if (isCallToEffectHook(node)) migrateUseEffect(ctx, node)\n if (isCallToHook(node, 'useMemo')) migrateUseMemo(ctx, node)\n if (isCallToHook(node, 'useCallback')) migrateUseCallback(ctx, node)\n if (isCallToHook(node, 'useRef')) migrateUseRef(ctx, node)\n if (ts.isCallExpression(node)) migrateMemoWrapper(ctx, node)\n if (ts.isCallExpression(node)) migrateForwardRef(ctx, node)\n if (ts.isJsxAttribute(node) && ts.isIdentifier(node.name)) migrateJsxAttributes(ctx, node)\n}\n\nfunction migrateVisit(ctx: MigrateContext, node: ts.Node): void {\n ts.forEachChild(node, (child) => {\n migrateVisitNode(ctx, child)\n migrateVisit(ctx, child)\n })\n}\n\nexport function migrateReactCode(code: string, filename = 'input.tsx'): MigrationResult {\n const sf = ts.createSourceFile(filename, code, ts.ScriptTarget.ESNext, true, ts.ScriptKind.TSX)\n const diagnostics = detectReactPatterns(code, filename)\n\n const ctx: MigrateContext = {\n sf,\n code,\n replacements: [],\n changes: [],\n pyreonImports: new Map(),\n importsToRemove: new Set(),\n specifierRewrites: new Map(),\n }\n\n migrateVisit(ctx, sf)\n\n let result = applyReplacements(code, ctx)\n result = insertPyreonImports(result, ctx.pyreonImports)\n\n // Clean up empty lines from removed imports\n result = result.replace(/\\n{3,}/g, '\\n\\n')\n\n return { code: result, diagnostics, changes: ctx.changes }\n}\n\n// ═══════════════════════════════════════════════════════════════════════════════\n// Helpers\n// ═══════════════════════════════════════════════════════════════════════════════\n\nfunction findParentJsxElement(\n node: ts.Node,\n): ts.JsxOpeningElement | ts.JsxSelfClosingElement | null {\n let current = node.parent\n while (current) {\n if (ts.isJsxOpeningElement(current) || ts.isJsxSelfClosingElement(current)) {\n return current\n }\n // Don't cross component boundaries\n if (ts.isJsxElement(current)) {\n return current.openingElement\n }\n if (ts.isArrowFunction(current) || ts.isFunctionExpression(current)) {\n return null\n }\n current = current.parent\n }\n return null\n}\n\nfunction getJsxTagName(node: ts.JsxOpeningElement | ts.JsxSelfClosingElement): string {\n const tagName = node.tagName\n if (ts.isIdentifier(tagName)) {\n return tagName.text\n }\n return ''\n}\n\nfunction findLastImportEnd(code: string): number {\n const importRe = /^import\\s.+$/gm\n let lastEnd = 0\n let match: RegExpExecArray | null\n while (true) {\n match = importRe.exec(code)\n if (!match) break\n lastEnd = match.index + match[0].length\n }\n return lastEnd\n}\n\n// ═══════════════════════════════════════════════════════════════════════════════\n// Quick scan (regex-based, for fast pre-filtering)\n// ═══════════════════════════════════════════════════════════════════════════════\n\n/** Fast regex check — returns true if code likely contains React patterns worth analyzing */\nexport function hasReactPatterns(code: string): boolean {\n return (\n /\\bfrom\\s+['\"]react/.test(code) ||\n /\\bfrom\\s+['\"]react-dom/.test(code) ||\n /\\bfrom\\s+['\"]react-router/.test(code) ||\n /\\buseState\\s*[<(]/.test(code) ||\n /\\buseEffect\\s*\\(/.test(code) ||\n /\\buseMemo\\s*\\(/.test(code) ||\n /\\buseCallback\\s*\\(/.test(code) ||\n /\\buseRef\\s*[<(]/.test(code) ||\n /\\buseReducer\\s*[<(]/.test(code) ||\n /\\bReact\\.memo\\b/.test(code) ||\n /\\bforwardRef\\s*[<(]/.test(code) ||\n /\\bclassName[=\\s]/.test(code) ||\n /\\bhtmlFor[=\\s]/.test(code) ||\n /\\.value\\s*=/.test(code)\n )\n}\n\n// ═══════════════════════════════════════════════════════════════════════════════\n// Error pattern database (for MCP diagnose tool)\n// ═══════════════════════════════════════════════════════════════════════════════\n\nexport interface ErrorDiagnosis {\n cause: string\n fix: string\n fixCode?: string | undefined\n related?: string | undefined\n}\n\ninterface ErrorPattern {\n pattern: RegExp\n diagnose: (match: RegExpMatchArray) => ErrorDiagnosis\n}\n\nconst ERROR_PATTERNS: ErrorPattern[] = [\n {\n pattern: /Cannot read properties of undefined \\(reading '(set|update|peek|subscribe)'\\)/,\n diagnose: (m) => ({\n cause: `Calling .${m[1]}() on undefined. The signal variable is likely out of scope, misspelled, or not yet initialized.`,\n fix: 'Check that the signal is defined and in scope. Signals must be created with signal() before use.',\n fixCode: `const mySignal = signal(initialValue)\\nmySignal.${m[1]}(newValue)`,\n }),\n },\n {\n pattern: /(\\w+) is not a function/,\n diagnose: (m) => ({\n cause: `'${m[1]}' is not callable. If this is a signal, you need to call it: ${m[1]}()`,\n fix: 'Pyreon signals are callable functions. Read: signal(), Write: signal.set(value)',\n fixCode: `// Read value:\\nconst value = ${m[1]}()\\n// Set value:\\n${m[1]}.set(newValue)`,\n }),\n },\n {\n pattern: /Cannot find module '(@pyreon\\/\\w[\\w-]*)'/,\n diagnose: (m) => ({\n cause: `Package ${m[1]} is not installed.`,\n fix: `Run: bun add ${m[1]}`,\n fixCode: `bun add ${m[1]}`,\n }),\n },\n {\n pattern: /Cannot find module 'react'/,\n diagnose: () => ({\n cause: \"Importing from 'react' in a Pyreon project.\",\n fix: 'Replace React imports with Pyreon equivalents.',\n fixCode:\n '// Instead of:\\nimport { useState } from \"react\"\\n// Use:\\nimport { signal } from \"@pyreon/reactivity\"',\n }),\n },\n {\n pattern: /Property '(\\w+)' does not exist on type 'Signal<\\w+>'/,\n diagnose: (m) => ({\n cause: `Accessing .${m[1]} on a signal. Pyreon signals don't have a .${m[1]} property.`,\n fix:\n m[1] === 'value'\n ? 'Pyreon signals are callable functions, not .value getters. Call signal() to read, signal.set() to write.'\n : `Signals have these methods: .set(), .update(), .peek(), .subscribe(). '${m[1]}' is not one of them.`,\n fixCode:\n m[1] === 'value' ? '// Read: mySignal()\\n// Write: mySignal.set(newValue)' : undefined,\n }),\n },\n {\n pattern: /Type '(\\w+)' is not assignable to type 'VNode'/,\n diagnose: (m) => ({\n cause: `Component returned ${m[1]} instead of VNode. Components must return JSX, null, or a string.`,\n fix: 'Make sure your component returns a JSX element, null, or a string.',\n fixCode: 'const MyComponent = (props) => {\\n return <div>{props.children}</div>\\n}',\n }),\n },\n {\n pattern: /onMount callback must return/,\n diagnose: () => ({\n cause: 'onMount expects a callback that optionally returns a CleanupFn.',\n fix: 'Return a cleanup function, or return nothing.',\n fixCode: 'onMount(() => {\\n // setup code\\n})',\n }),\n },\n {\n pattern: /Expected 'by' prop on <For>/,\n diagnose: () => ({\n cause: \"<For> requires a 'by' prop for efficient keyed reconciliation.\",\n fix: 'Add a by prop that returns a unique key for each item.',\n fixCode:\n '<For each={items()} by={item => item.id}>\\n {item => <li>{item.name}</li>}\\n</For>',\n }),\n },\n {\n pattern: /useHook.*outside.*component/i,\n diagnose: () => ({\n cause:\n 'Hook called outside a component function. Pyreon hooks must be called during component setup.',\n fix: 'Move the hook call inside a component function body.',\n }),\n },\n {\n pattern: /Hydration mismatch/,\n diagnose: () => ({\n cause: \"Server-rendered HTML doesn't match client-rendered output.\",\n fix: 'Ensure SSR and client render the same initial content. Check for browser-only APIs (window, document) in SSR code.',\n related: \"Use typeof window !== 'undefined' checks or onMount() for client-only code.\",\n }),\n },\n]\n\n/** Diagnose an error message and return structured fix information */\nexport function diagnoseError(error: string): ErrorDiagnosis | null {\n for (const { pattern, diagnose } of ERROR_PATTERNS) {\n const match = error.match(pattern)\n if (match) {\n return diagnose(match)\n }\n }\n return null\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8DA,MAAM,aAAa,IAAI,IAAI,CAAC,OAAO,MAAM,CAAC;AAE1C,MAAM,WAAW;AAEjB,MAAM,mBAAmB,IAAI,IAAI;CAC/B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;AAaF,SAAgB,aACd,MACA,WAAW,aACX,UAA4B,EAAE,EACb;CACjB,MAAM,MAAM,QAAQ,QAAQ;CAC5B,MAAM,aACJ,SAAS,SAAS,OAAO,IAAI,SAAS,SAAS,OAAO,GAAG,GAAG,WAAW,MAAM,GAAG,WAAW;CAE7F,MAAM,KAAK,GAAG,iBACZ,UACA,MACA,GAAG,aAAa,QACK,MACrB,WACD;CAGD,MAAM,eAA8B,EAAE;CACtC,MAAM,WAA8B,EAAE;CAEtC,SAAS,KAAK,MAAe,SAAiB,UAAyC;EACrF,MAAM,EAAE,MAAM,cAAc,GAAG,8BAA8B,KAAK,SAAS,GAAG,CAAC;AAC/E,WAAS,KAAK;GAAE;GAAS,MAAM,OAAO;GAAG,QAAQ;GAAW,MAAM;GAAU,CAAC;;CAK/E,MAAM,SAAkB,EAAE;CAC1B,IAAI,WAAW;CACf,IAAI,iBAAiB;CACrB,IAAI,gBAAgB;CACpB,IAAI,4BAA4B;CAChC,IAAI,8BAA8B;CAClC,IAAI,wBAAwB;CAC5B,IAAI,8BAA8B;CAClC,IAAI,6BAA6B;;;;;CAMjC,SAAS,WAAW,MAA8B;AAChD,OACG,GAAG,aAAa,KAAK,IAAI,GAAG,wBAAwB,KAAK,IAAI,GAAG,cAAc,KAAK,KACpF,gBAAgB,KAAkE,EAClF;GACA,MAAM,OAAO,MAAM;GACnB,MAAM,OAAO,KAAK,MAAM,KAAK,SAAS,GAAG,EAAE,KAAK,QAAQ,CAAC;AACzD,UAAO,KAAK;IAAE;IAAM;IAAM,CAAC;AAC3B,UAAO;;AAET,SAAO;;CAGT,SAAS,KAAK,MAA2B;EACvC,MAAM,QAAQ,KAAK,SAAS,GAAG;EAC/B,MAAM,MAAM,KAAK,QAAQ;EAGzB,MAAM,SAAS,UAAU,KAAK;EAC9B,MAAM,OAAO,GAAG,0BAA0B,KAAK,GAC3C,UAAU,OAAO,KACjB,SAAS;AACb,eAAa,KAAK;GAAE;GAAO;GAAK;GAAM,CAAC;;;CAIzC,SAAS,YAAY,MAA2B;EAC9C,MAAM,YAAY,WAAW,KAAK;AAClC,MAAI,UACF,cAAa,KAAK;GAAE,OAAO,KAAK,SAAS,GAAG;GAAE,KAAK,KAAK,QAAQ;GAAE,MAAM;GAAW,CAAC;WAC3E,WAAW,KAAK,CACzB,MAAK,KAAK;;;CAOd,SAAS,gBAAgB,MAA8B;AAOrD,MAAI,IAAK,QAAO;AAEhB,MADkB,qBAAqB,MAAmB,KAAK,GAC/C,EAAG,QAAO;EAC1B,MAAM,UAAU,kBAAkB,KAAK;AACvC,MAAI,CAAC,QAAS,QAAO;EACrB,MAAM,QAAQ,KAAK,SAAS,GAAG;EAC/B,MAAM,MAAM,KAAK,QAAQ;EACzB,MAAM,SAAS,KAAK;EACpB,MAAM,cAAc,WAAW,GAAG,aAAa,OAAO,IAAI,GAAG,cAAc,OAAO;AAClF,eAAa,KAAK;GAAE;GAAO;GAAK,MAAM,cAAc,IAAI,QAAQ,KAAK;GAAS,CAAC;AAC/E,mBAAiB;AACjB,SAAO;;;CAIT,SAAS,iBAAiB,MAAsD;EAC9E,MAAM,UAAU,GAAG,aAAa,KAAK,GAAG,KAAK,iBAAiB;AAE9D,OADgB,GAAG,aAAa,QAAQ,QAAQ,GAAG,QAAQ,QAAQ,OAAO,QAC1D,MAAO;AAIvB,MAAI,CAHU,QAAQ,WAAW,WAAW,MACzC,MAAM,GAAG,eAAe,EAAE,IAAI,GAAG,aAAa,EAAE,KAAK,IAAI,EAAE,KAAK,SAAS,KAC3E,CAEC,MACE,QAAQ,SACR,qLACA,qBACD;;;;;;;;;;;;CAcL,SAAS,mBAAmB,MAA6B;EACvD,MAAM,OAAO,GAAG,aAAa,KAAK,KAAK,GAAG,KAAK,KAAK,OAAO;AAC3D,MAAI,WAAW,IAAI,KAAK,IAAI,SAAS,KAAK,KAAK,CAAE;AACjD,MAAI,CAAC,KAAK,eAAe,CAAC,GAAG,gBAAgB,KAAK,YAAY,CAAE;EAChE,MAAM,OAAO,KAAK,YAAY;AAC9B,MAAI,CAAC,KAAM;EAEX,MAAM,YAAY,KAAK,OAAO;EAC9B,MAAM,UAAU,GAAG,aAAa,UAAU,QAAQ,GAAG,UAAU,QAAQ,OAAO;AAG9E,MAFoB,QAAQ,SAAS,KAAK,QAAQ,OAAO,EAAE,KAAK,QAAQ,OAAO,EAAE,CAAC,aAAa,EAE9E;AASf,OADoB,GAAG,aAAa,KAAK,IAAI,GAAG,wBAAwB,KAAK,EAC5D;AAEf,OAAG,aAAa,MAAM,KAAK;AAC3B;;GAGF,MAAM,YAAY,WAAW,KAAK;AAClC,OAAI,UACF,cAAa,KAAK;IAAE,OAAO,KAAK,SAAS,GAAG;IAAE,KAAK,KAAK,QAAQ;IAAE,MAAM;IAAW,CAAC;YAC3E,WAAW,KAAK,EAAE;IAC3B,MAAM,QAAQ,KAAK,SAAS,GAAG;IAC/B,MAAM,MAAM,KAAK,QAAQ;IAEzB,MAAM,SAAS,UAAU,KAAK;IAC9B,MAAM,QAAQ,GAAG,0BAA0B,KAAK,GAAG,IAAI,OAAO,KAAK;AACnE,iBAAa,KAAK;KAAE;KAAO;KAAK,MAAM,aAAa,MAAM;KAAI,CAAC;AAC9D,oBAAgB;;QAIlB,aAAY,KAAK;;;CAKrB,SAAS,oBAAoB,MAA8B;EACzD,MAAM,OAAO,KAAK;AAClB,MAAI,CAAC,KAAM;EACX,MAAM,YAAY,WAAW,KAAK;AAClC,MAAI,WAAW;AACb,gBAAa,KAAK;IAAE,OAAO,KAAK,SAAS,GAAG;IAAE,KAAK,KAAK,QAAQ;IAAE,MAAM;IAAW,CAAC;AACpF;;AAEF,MAAI,WAAW,KAAK,EAAE;AACpB,QAAK,KAAK;AACV;;AAKF,KAAG,aAAa,MAAM,KAAK;;;CAc7B,MAAM,6BAAa,IAAI,KAAa;;;CAIpC,MAAM,kCAAkB,IAAI,KAA4B;;CAGxD,SAAS,eAAe,MAAwB;AAC9C,MAAI,GAAG,2BAA2B,KAAK,IAAI,GAAG,aAAa,KAAK,WAAW,CACzE,QAAO,WAAW,IAAI,KAAK,WAAW,KAAK;AAE7C,MAAI,GAAG,0BAA0B,KAAK,IAAI,GAAG,aAAa,KAAK,WAAW,CACxE,QAAO,WAAW,IAAI,KAAK,WAAW,KAAK;EAG7C,IAAI,QAAQ;AACZ,KAAG,aAAa,OAAO,UAAU;AAC/B,OAAI,MAAO;AACX,OAAI,eAAe,MAAM,CAAE,SAAQ;IACnC;AACF,SAAO;;;;;CAMT,IAAI,iBAAiB;CACrB,SAAS,uBAAuB,MAAqB;AAEnD,MAAK,GAAG,gBAAgB,KAAK,IAAI,GAAG,qBAAqB,KAAK,EAAG;GAC/D,MAAM,SAAS,KAAK;AACpB,OAAI,UAAU,GAAG,iBAAiB,OAAO,IAAI,OAAO,UAAU,SAAS,KAAY,EAAE;AACnF;AACA,OAAG,aAAa,MAAM,uBAAuB;AAC7C;AACA;;;AAOJ,OAAK,GAAG,sBAAsB,KAAK,IAAI,GAAG,gBAAgB,KAAK,IAAI,GAAG,qBAAqB,KAAK,KAC3F,KAAK,WAAW,SAAS,GAAG;GAG/B,MAAM,SAAS,KAAK;AACpB,OAAI,UAAU,GAAG,iBAAiB,OAAO,IAAI,OAAO,UAAU,SAAS,KAAY,EAAE;AACnF,OAAG,aAAa,MAAM,uBAAuB;AAC7C;;GAGF,MAAM,aAAa,KAAK,WAAW;AACnC,OAAI,GAAG,aAAa,WAAW,KAAK,EAAE;IAEpC,IAAI,SAAS;AACb,OAAG,aAAa,MAAM,SAAS,SAAS,GAAG;AACzC,SAAI,OAAQ;AACZ,SAAI,GAAG,aAAa,EAAE,IAAI,GAAG,wBAAwB,EAAE,IAAI,GAAG,cAAc,EAAE,EAAE;AAC9E,eAAS;AACT;;AAEF,QAAG,aAAa,GAAG,SAAS;MAC5B;AACF,QAAI,OAAQ,YAAW,IAAI,WAAW,KAAK,KAAK;;;AAKpD,MAAI,GAAG,oBAAoB,KAAK,CAC9B,MAAK,MAAM,QAAQ,KAAK,gBAAgB,cAAc;AACpD,OAAI,GAAG,sBAAsB,KAAK,KAAK,IAAI,KAAK,eAC3C,GAAG,iBAAiB,KAAK,YAAY,EAAE;IAC1C,MAAM,SAAS,KAAK,YAAY;AAChC,QAAI,GAAG,aAAa,OAAO,IAAI,OAAO,SAAS,cAC7C;UAAK,MAAM,MAAM,KAAK,KAAK,SACzB,KAAI,GAAG,iBAAiB,GAAG,IAAI,GAAG,aAAa,GAAG,KAAK,CACrD,YAAW,IAAI,GAAG,KAAK,KAAK;;;AAUpC,OAAI,EAAE,KAAK,gBAAgB,QAAQ,GAAG,UAAU,OAAQ;AACxD,OAAI,iBAAiB,EAAG;AACxB,OAAI,GAAG,aAAa,KAAK,KAAK,IAAI,KAAK,aAAa;AAClD,QAAI,eAAe,KAAK,YAAY,CAAE;AACtC,QAAI,eAAe,KAAK,YAAY,CAClC,iBAAgB,IAAI,KAAK,KAAK,MAAM,KAAK,YAAY;;;AAM7D,KAAG,aAAa,MAAM,uBAAuB;;AAI/C,wBAAuB,GAAG;CAK1B,IAAI,UAAU;AACd,QAAO,SAAS;AACd,YAAU;AACV,KAAG,aAAa,SAAS,eAAe,MAAM;AAC5C,OAAI,CAAC,GAAG,oBAAoB,KAAK,EAAE;AAAE,OAAG,aAAa,MAAM,eAAe;AAAE;;AAC5E,QAAK,MAAM,QAAQ,KAAK,gBAAgB,cAAc;AACpD,QAAI,CAAC,GAAG,aAAa,KAAK,KAAK,IAAI,CAAC,KAAK,YAAa;IACtD,MAAM,UAAU,KAAK,KAAK;AAC1B,QAAI,gBAAgB,IAAI,QAAQ,CAAE;AAClC,QAAI,KAAK,gBAAgB,QAAQ,GAAG,UAAU,IAAK;IACnD,IAAI,cAAc;AAClB,OAAG,aAAa,KAAK,aAAa,SAAS,MAAM,GAAG;AAClD,SAAI,YAAa;AACjB,SAAI,GAAG,aAAa,EAAE,IAAI,gBAAgB,IAAI,EAAE,KAAK,EAAE;MACrD,MAAM,SAAS,EAAE;AACjB,UAAI,UAAU,GAAG,2BAA2B,OAAO,IAAI,OAAO,SAAS,EAAG;AAC1E,oBAAc;;AAEhB,QAAG,aAAa,GAAG,MAAM;MACzB;AACF,QAAI,aAAa;AACf,qBAAgB,IAAI,SAAS,KAAK,YAAY;AAC9C,eAAU;;;IAGd;;CAgBJ,MAAM,+BAAe,IAAI,KAAa;CAEtC,SAAS,sBACP,MACA,0BAAuB,IAAI,KAAK,EAEhC,YACe;AACf,SAAO,GAAG,UAAU,MAAM,SAAS,MAAM,GAAqB;AAC5D,OAAI,GAAG,aAAa,EAAE,IAAI,gBAAgB,IAAI,EAAE,KAAK,EAAE;IAWrD,MAAM,SAAS,EAAE;AACjB,QAAI,QAAQ;AAKV,SAAI,UAAU,UAAW,OAAe,SAAS,EAAG,QAAO;AAE3D,SAAI,GAAG,8BAA8B,OAAO,CAAE,QAAO;;AAQvD,QAAI,QAAQ,IAAI,EAAE,KAAK,EAAE;KACvB,MAAM,WAAW,CAAC,GAAG,SAAS,EAAE,KAAK,CAAC,MAAM,CAAC,KAAK,IAAI;AACtD,SAAI,CAAC,aAAa,IAAI,SAAS,EAAE;AAC/B,mBAAa,IAAI,SAAS;MAC1B,MAAM,QAAQ,CAAC,GAAG,SAAS,EAAE,KAAK,CAAC,KAAK,MAAM;AAC9C,WACE,cAAc,GACd,mDAAmD,MAAM,4BAC5B,EAAE,KAAK,kKAGpC,wBACD;;AAEH,YAAO;;IAGT,MAAM,WAAW,gBAAgB,IAAI,EAAE,KAAK;IAG5C,MAAM,cAAc,IAAI,IAAI,QAAQ;AACpC,gBAAY,IAAI,EAAE,KAAK;AACvB,WAAO,GAAG,QAAQ,8BAChB,sBAAsB,UAAU,aAAa,WAAW,CACzD;;AAEH,UAAO,GAAG,eAAe,GAAG,OAAO,OAAiB;IACpD;;;CAIJ,MAAM,UAAU,GAAG,cAAc,EAAE,gBAAgB,OAAO,CAAC;;;;;;CAO3D,SAAS,UAAU,MAAwB;AACzC,MAAI,aAAa,KAAK,CAAE,QAAO;AAC/B,SAAO,cAAc,KAAK;;;CAI5B,SAAS,cAAc,MAAwB;AAC7C,MAAI,GAAG,2BAA2B,KAAK,IAAI,GAAG,aAAa,KAAK,WAAW,EACzE;OAAI,WAAW,IAAI,KAAK,WAAW,KAAK,CAAE,QAAO;;AAEnD,MAAI,GAAG,aAAa,KAAK,IAAI,gBAAgB,IAAI,KAAK,KAAK,EAAE;GAC3D,MAAM,SAAS,KAAK;AACpB,OAAI,UAAU,GAAG,2BAA2B,OAAO,IAAI,OAAO,SAAS,KAAM,QAAO;AACpF,UAAO;;EAET,IAAI,QAAQ;AACZ,KAAG,aAAa,OAAO,UAAU;AAC/B,OAAI,MAAO;AACX,OAAI,GAAG,gBAAgB,MAAM,IAAI,GAAG,qBAAqB,MAAM,CAAE;AACjE,OAAI,cAAc,MAAM,CAAE,SAAQ;IAClC;AACF,SAAO;;CAGT,SAAS,WAAW,MAA8B;AAChD,MAAI,GAAG,gBAAgB,KAAK,IAAI,GAAG,qBAAqB,KAAK,CAAE,QAAO;AACtE,MAAI,SAAS,KAAK,CAAE,QAAO;AAC3B,MAAI,GAAG,iBAAiB,KAAK,IAAI,iBAAiB,KAAK,CAAE,QAAO;AAChE,SAAO,UAAU,KAAK;;CAGxB,SAAS,KAAK,MAAqB;AACjC,MAAI,GAAG,aAAa,KAAK,IAAI,gBAAgB,KAAK,CAAE;AACpD,MAAI,GAAG,wBAAwB,KAAK,IAAI,GAAG,aAAa,KAAK,CAAE,kBAAiB,KAAK;AACrF,MAAI,GAAG,eAAe,KAAK,EAAE;AAC3B,sBAAmB,KAAK;AACxB;;AAEF,MAAI,GAAG,gBAAgB,KAAK,EAAE;AAC5B,uBAAoB,KAAK;AACzB;;AAEF,KAAG,aAAa,MAAM,KAAK;;AAG7B,MAAK,GAAG;AAER,KAAI,aAAa,WAAW,KAAK,OAAO,WAAW,EAAG,QAAO;EAAE;EAAM;EAAU;AAG/E,cAAa,MAAM,GAAG,MAAM,EAAE,QAAQ,EAAE,MAAM;CAE9C,MAAM,QAAkB,EAAE;CAC1B,IAAI,UAAU;AACd,MAAK,MAAM,KAAK,cAAc;AAC5B,QAAM,KAAK,KAAK,MAAM,SAAS,EAAE,MAAM,CAAC;AACxC,QAAM,KAAK,EAAE,KAAK;AAClB,YAAU,EAAE;;AAEd,OAAM,KAAK,KAAK,MAAM,QAAQ,CAAC;CAC/B,IAAI,SAAS,MAAM,KAAK,GAAG;AAG3B,KAAI,OAAO,SAAS,EAElB,UADiB,OAAO,KAAK,MAAM,SAAS,EAAE,KAAK,mBAAmB,EAAE,KAAK,IAAI,CAAC,KAAK,GAAG,GACtE;AAItB,KAAI,gBAAgB;EAClB,MAAM,oBAAoB,CAAC,OAAO;AAClC,MAAI,4BAA6B,mBAAkB,KAAK,cAAc;AACtE,MAAI,0BAA2B,mBAAkB,KAAK,YAAY;AAClE,MAAI,4BAA6B,mBAAkB,KAAK,cAAc;AACtE,MAAI,2BAA4B,mBAAkB,KAAK,aAAa;EACpE,MAAM,oBAAoB,wBACtB,kDACA;AACJ,WACE,YAAY,kBAAkB,KAAK,KAAK,CAAC,gCAAgC,kBAAkB,MAC3F;;AAIJ,KAAI,cACF,UAAS,0CAA0C;AAGrD,QAAO;EAAE,MAAM;EAAQ,eAAe;EAAgB;EAAU;;;;;;;CAUhE,SAAS,YAAY,MAAgD,SAAS,OAAgB;AAC5F,OAAK,MAAM,QAAQ,SAAS,KAAK,EAAE;AACjC,OAAI,GAAG,qBAAqB,KAAK,EAAE;AAEjC,QAAI,OAAQ;AACZ,WAAO;;AAET,OAAI,GAAG,eAAe,KAAK,IAAI,GAAG,aAAa,KAAK,KAAK,IAAI,KAAK,KAAK,SAAS,MAC9E,QAAO;;AAEX,SAAO;;;;;;CAOT,SAAS,sBAAsB,OAA4B;AACzD,MAAI,GAAG,UAAU,MAAM,CAAE,QAAO;AAChC,MAAI,GAAG,aAAa,MAAM,IAAI,GAAG,wBAAwB,MAAM,CAC7D,QAAO,qBAAqB,MAAM;AACpC,MAAI,GAAG,gBAAgB,MAAM,EAAE;AAC7B,OAAI,CAAC,MAAM,WAAY,QAAO;AAC9B,UAAO,kBAAkB,MAAM,WAAW,GAAG,KAAK;;AAEpD,MAAI,GAAG,cAAc,MAAM,CAAE,QAAO,sBAAsB,MAAM;AAChE,SAAO;;;;;;CAOT,SAAS,qBACP,MACA,SAAS,OACD;EACR,MAAM,MAAM,WAAW,KAAK;AAC5B,MAAI,CAAC,OAAO,CAAC,YAAY,IAAI,CAAE,QAAO;AACtC,MAAI,YAAY,MAAM,OAAO,CAAE,QAAO;AACtC,MAAI,CAAC,GAAG,aAAa,KAAK,CAAE,QAAO;EAEnC,IAAI,QAAQ;AACZ,OAAK,MAAM,SAAS,KAAK,UAAU;GACjC,MAAM,IAAI,sBAAsB,MAAM;AACtC,OAAI,MAAM,GAAI,QAAO;AACrB,YAAS;;AAEX,SAAO;;;CAIT,SAAS,sBAAsB,MAA8B;EAC3D,IAAI,QAAQ;AACZ,OAAK,MAAM,SAAS,KAAK,UAAU;GACjC,MAAM,IAAI,sBAAsB,MAAM;AACtC,OAAI,MAAM,GAAI,QAAO;AACrB,YAAS;;AAEX,SAAO;;;;;;CAOT,SAAS,kBAAkB,MAA+D;EACxF,MAAM,YAAsB,EAAE;EAC9B,MAAM,gBAA0B,EAAE;EAClC,IAAI,SAAS;EACb,IAAI,UAAU;EAEd,MAAM,oBAA8B,EAAE;EACtC,IAAI,sBAAsB;EAC1B,IAAI,wBAAwB;EAC5B,IAAI,wBAAwB;EAC5B,IAAI,uBAAuB;EAE3B,SAAS,UAAkB;AACzB,UAAO,MAAM;;EAEf,SAAS,WAAmB;GAC1B,MAAM,OAAO,MAAM;AACnB,iBAAc,KAAK,KAAK;AACxB,UAAO;;EAET,SAAS,cAAsB;AAC7B,UAAO,MAAM;;;EAIf,SAAS,kBAAkB,UAAkB,YAA6B;AACxE,OAAI,aAAa,SAAU,QAAO;AAClC,OAAI,YAAY;IACd,MAAM,IAAI,SAAS;AACnB,cAAU,KAAK,SAAS,EAAE,KAAK,WAAW;AAC1C,WAAO;;AAET,UAAO;;;EAIT,SAAS,QAAQ,MAAuB,SAAuB;AAC7D,OAAI,CAAC,KAAK,eAAe,CAAC,GAAG,gBAAgB,KAAK,YAAY,CAAE;GAChE,MAAM,OAAO,KAAK,YAAY;AAC9B,OAAI,CAAC,KAAM;AAGX,OAAI,GAAG,gBAAgB,KAAK,IAAI,GAAG,qBAAqB,KAAK,CAC3D,WAAU,KAAK,IAAI,UAAU,KAAK,CAAC,IAAI,QAAQ,GAAG;OAElD,WAAU,KACR,iBAAiB,UAAU,KAAK,CAAC,uCAAuC,QAAQ,iCAAiC,QAAQ,IAC1H;;;EAKL,SAAS,kBAAkB,MAAuB,UAAkB,SAAuB;GACzF,MAAM,aAAa,SAAS,MAAM,IAAI,aAAa,GAAG,SAAS,MAAM,EAAE;AACvE,OAAI,CAAC,KAAK,eAAe,CAAC,GAAG,gBAAgB,KAAK,YAAY,CAAE;AAChE,OAAI,CAAC,KAAK,YAAY,WAAY;GAClC,MAAM,UAAU,UAAU,KAAK,YAAY,WAAW;AACtD,OAAI,iBAAiB,IAAI,UAAU,CAEjC,WAAU,KAAK,GAAG,QAAQ,QAAQ,UAAU,KAAK,UAAU;OAE3D,WAAU,KAAK,GAAG,QAAQ,qBAAqB,UAAU,KAAK,QAAQ,GAAG;;;EAK7E,SAAS,iBAAiB,UAAyB,cAAqC;AACtF,OAAI,CAAC,SAAS,SAAS,CAAE,QAAO;AAChC,OAAI,GAAG,gBAAgB,SAAS,CAAE,QAAO,IAAI,aAAa,IAAI,eAAe,SAAS,KAAK,CAAC;AAC5F,OAAI,GAAG,iBAAiB,SAAS,CAAE,QAAO,IAAI,aAAa,IAAI,SAAS,KAAK;AAC7E,OAAI,SAAS,SAAS,GAAG,WAAW,YAAa,QAAO,IAAI;AAC5D,UAAO;;;;;;;EAQT,SAAS,mBAAmB,UAAwC;GAClE,IAAI,QAAQ;AAEZ,OAAI,GAAG,gBAAgB,MAAM,IAAI,CAAC,GAAG,QAAQ,MAAM,KAAK,CACtD,SAAQ,MAAM;AAEhB,OAAI,CAAC,GAAG,iBAAiB,MAAM,CAAE,QAAO;AACxC,OAAI,MAAM,UAAU,SAAS,EAAG,QAAO;GACvC,MAAM,SAAS,MAAM;AAIrB,OAAI,GAAG,aAAa,OAAO,CACzB,QAAO,UAAU,OAAO;AAE1B,UAAO;;;EAIT,SAAS,eAAe,UAAgE;AAEtF,OAAI,GAAG,gBAAgB,SAAS,IAAI,CAAC,GAAG,QAAQ,SAAS,KAAK,CAC5D,QAAO;IAAE,MAAM,UAAU,SAAS,KAAsB;IAAE,YAAY;IAAM;AAG9E,OAAI,GAAG,gBAAgB,SAAS,IAAI,GAAG,qBAAqB,SAAS,CACnE,QAAO;IAAE,MAAM,IAAI,UAAU,SAAS,CAAC;IAAM,YAAY;IAAM;AAEjE,UAAO;IAAE,MAAM,UAAU,SAAS;IAAE,YAAY,UAAU,SAAS;IAAE;;;EAIvE,SAAS,WAAW,cAAsB,SAAiB,MAAsB;AAC/E,OAAI,iBAAiB,QAAS,QAAO,GAAG,QAAQ,eAAe;AAC/D,OAAI,iBAAiB,QAAS,QAAO,GAAG,QAAQ,mBAAmB;AACnE,UAAO,GAAG,QAAQ,iBAAiB,aAAa,KAAK,KAAK;;;EAI5D,SAAS,gBACP,OACA,UACA,cACA,SACM;GACN,MAAM,EAAE,MAAM,eAAe,eAAe,SAAS;AAErD,OAAI,CAAC,YAAY;AACf,cAAU,KAAK,WAAW,cAAc,SAAS,KAAK,CAAC;AACvD;;GAIF,MAAM,YAAY,mBAAmB,SAAS;AAC9C,OAAI,WAAW;AACb,4BAAwB;IACxB,MAAM,IAAI,UAAU;IACpB,MAAM,UACJ,iBAAiB,UACb,YAAY,QAAQ,6CACpB,iBAAiB,UACf,uCAAuC,QAAQ,gDAAgD,QAAQ,gBACvG,YAAY,QAAQ,iBAAiB,aAAa;AAC1D,cAAU,KAAK,SAAS,EAAE,iBAAiB,UAAU,IAAI,QAAQ,GAAG;AACpE;;AAGF,qBAAkB,KAAK,WAAW,cAAc,SAAS,KAAK,CAAC;;;EAIjE,SAAS,mBACP,UACA,cACA,SACQ;GACR,MAAM,aAAa,iBAAiB,UAAU,aAAa;AAC3D,OAAI,eAAe,KAAM,QAAO;AAGhC,OAAI,iBAAiB,WAAW,GAAG,0BAA0B,SAAS,EAAE;AACtE,cAAU,KAAK,iBAAiB,QAAQ,UAAU,UAAU,SAAS,CAAC,GAAG;AACzE,WAAO;;AAGT,mBAAgB,UAAU,SAAS,EAAE,UAAU,cAAc,QAAQ;AACrE,UAAO;;;EAIT,SAAS,mBAAmB,MAAuB,UAAkB,SAA0B;AAC7F,OAAI,aAAa,OAAO;AACtB,YAAQ,MAAM,QAAQ;AACtB,WAAO;;AAET,OAAI,SAAS,KAAK,SAAS,EAAE;AAC3B,sBAAkB,MAAM,UAAU,QAAQ;AAC1C,WAAO;;AAET,UAAO;;;EAIT,SAAS,sBACP,MACA,cACA,SACQ;AACR,OAAI,CAAC,KAAK,YAAa,QAAO,IAAI;AAClC,OAAI,GAAG,gBAAgB,KAAK,YAAY,CACtC,QAAO,IAAI,aAAa,IAAI,eAAe,KAAK,YAAY,KAAK,CAAC;AACpE,OAAI,GAAG,gBAAgB,KAAK,YAAY,IAAI,KAAK,YAAY,WAC3D,QAAO,mBAAmB,KAAK,YAAY,YAAY,cAAc,QAAQ;AAC/E,UAAO;;;EAIT,SAAS,eAAe,MAA2B,SAAyB;AAE1E,OAAI,GAAG,qBAAqB,KAAK,EAAE;IACjC,MAAM,OAAO,UAAU,KAAK,WAAW;AAEvC,4BAAwB;AACxB,QAAI,UAAU,KAAK,WAAW,CAC5B,mBAAkB,KAAK,eAAe,QAAQ,IAAI,KAAK,GAAG;QAE1D,WAAU,KAAK,eAAe,QAAQ,IAAI,KAAK,GAAG;AAEpD,WAAO;;AAET,OAAI,CAAC,GAAG,eAAe,KAAK,CAAE,QAAO;GACrC,MAAM,WAAW,GAAG,aAAa,KAAK,KAAK,GAAG,KAAK,KAAK,OAAO;AAC/D,OAAI,aAAa,MAAO,QAAO;AAC/B,OAAI,mBAAmB,MAAM,UAAU,QAAQ,CAAE,QAAO;AACxD,UAAO,sBAAsB,MAAM,iBAAiB,aAAa,UAAU,QAAQ;;;EAIrF,SAAS,aAAa,IAA8C,SAAyB;GAC3F,IAAI,YAAY;AAChB,QAAK,MAAM,QAAQ,SAAS,GAAG,CAAE,cAAa,eAAe,MAAM,QAAQ;AAC3E,UAAO;;;EAIT,SAAS,sBACP,MACA,UACA,SACA,WACA,cACA,kBACQ;GACR,MAAM,OAAO,aAAa;AAC1B,aAAU,KAAK,SAAS,KAAK,gCAAgC;AAC7D,OAAI,iBACF,WAAU,KACR,GAAG,UAAU,gBAAgB,KAAK,IAAI,UAAU,cAAc,aAAa,IAC5E;OAED,WAAU,KAAK,GAAG,QAAQ,eAAe,KAAK,GAAG;GAGnD,MAAM,YAAY,mBAAmB,SAAS;AAC9C,OAAI,WAAW;AACb,0BAAsB;IACtB,MAAM,IAAI,UAAU;AACpB,cAAU,KAAK,SAAS,EAAE,eAAe,UAAU,IAAI,KAAK,GAAG;UAC1D;AAGL,4BAAwB;IACxB,MAAM,IAAI,UAAU;AACpB,cAAU,KAAK,SAAS,EAAE,mBAAmB,KAAK,UAAU,KAAK,KAAK;;AAExE,UAAO,mBAAmB,QAAQ;;;EAIpC,SAAS,oBACP,MACA,SACA,WACA,cACA,kBACQ;AACR,OAAI,kBAAkB;IACpB,MAAM,OAAO,aAAa;AAC1B,cAAU,KAAK,SAAS,KAAK,6BAA6B,KAAK,GAAG;AAClE,cAAU,KACR,GAAG,UAAU,gBAAgB,KAAK,IAAI,UAAU,cAAc,aAAa,IAC5E;AACD,WAAO;;AAET,aAAU,KAAK,GAAG,QAAQ,iBAAiB,OAAO;AAClD,UAAO;;;EAIT,SAAS,gBACP,OACA,SACA,WACA,UACA,cACA,cACe;AACf,OAAI,MAAM,SAAS,OAAQ,QAAO,eAAe,MAAM,KAAK;AAC5D,OAAI,MAAM,SAAS,WAAW;IAC5B,MAAM,gBAAgB,WAClB,GAAG,UAAU,cAAc,aAAa,KACxC,GAAG,UAAU,YAAY,MAAM,QAAQ;AAC3C,WAAO,eAAe,MAAM,MAAM,cAAc;;GAGlD,MAAM,mBAAmB,YAAY;GACrC,MAAM,EAAE,MAAM,eAAe,eAAe,MAAM,WAAW;AAI7D,OAAI,qBAAqB,MAAM,YAAY,KAAK,EAAE;AAChD,2BAAuB;IACvB,MAAM,cAAc,GAAG,UAAU,cAAc,aAAa;IAC5D,MAAM,IAAI,UAAU;AACpB,cAAU,KAAK,SAAS,EAAE,gBAAgB,KAAK,IAAI,UAAU,IAAI,YAAY,GAAG;AAChF,WAAO;;AAGT,OAAI,WACF,QAAO,sBACL,MACA,MAAM,YACN,SACA,WACA,cACA,iBACD;AAEH,UAAO,oBAAoB,MAAM,SAAS,WAAW,cAAc,iBAAiB;;;EAItF,SAAS,gBAAgB,IAAmB,SAAiB,UAAiC;GAC5F,MAAM,eAAe,gBAAgB,GAAG,SAAS;GACjD,MAAM,EAAE,UAAU,iBAAiB,gBAAgB,aAAa;GAChE,MAAM,YAAY,aAAa,WAAW,WAAW;GAErD,IAAI,OAAO;GACX,IAAI,eAAe;AAEnB,QAAK,MAAM,SAAS,cAAc;IAChC,MAAM,YAAY,gBAChB,OACA,SACA,WACA,UACA,cACA,aACD;AACD,QAAI,cAAc,KAAM,QAAO;AAC/B,YAAQ;AACR;;AAGF,UAAO;;;EAIT,SAAS,eACP,IACA,UACe;GACf,MAAM,MAAM,WAAW,GAAG;AAC1B,OAAI,CAAC,IAAK,QAAO;GAEjB,MAAM,UAAU,kBAAkB,UAAU,kBAAkB,GAAG,CAAC;GAElE,IAAI,OAAO,IAAI,MADG,aAAa,IAAI,QAAQ,CACZ;AAE/B,OAAI,GAAG,aAAa,GAAG,EAAE;IACvB,MAAM,YAAY,gBAAgB,IAAI,SAAS,SAAS;AACxD,QAAI,cAAc,KAAM,QAAO;AAC/B,YAAQ;;AAGV,OAAI,CAAC,cAAc,IAAI,IAAI,CAAE,SAAQ,KAAK,IAAI;AAC9C,UAAO;;EAGT,MAAM,OAAO,eAAe,MAAM,SAAS;AAC3C,MAAI,SAAS,KAAM,QAAO;AAE1B,MAAI,oBAAqB,6BAA4B;AACrD,MAAI,sBAAuB,+BAA8B;AACzD,MAAI,sBAAuB,+BAA8B;AACzD,MAAI,qBAAsB,8BAA6B;EAGvD,MAAM,UAAU,KAAK,QAAQ,OAAO,OAAO,CAAC,QAAQ,MAAM,OAAM;AAQhE,MAAI,kBAAkB,SAAS,GAAG;AAChC,2BAAwB;GACxB,MAAM,eAAe,UAAU;GAC/B,MAAM,eAAe,kBAAkB,KAAK,KAAK;AACjD,aAAU,KAAK,SAAS,aAAa,mBAAmB,aAAa,KAAK;;AAG5E,MAAI,UAAU,WAAW,KAAK,cAAc,WAAW,EACrD,QAAO,SAAS,QAAQ;EAG1B,IAAI,OAAO,UAAU,KAAK,MAAM,KAAK,IAAI,CAAC,KAAK,KAAK;AACpD,MAAI,cAAc,SAAS,EACzB,SAAQ,sBAAsB,cAAc,KAAK,MAAM,GAAG,EAAE,IAAI,CAAC,KAAK,KAAK,CAAC;MAE5E,SAAQ;AAGV,SAAO,SAAS,QAAQ,oBAAoB,KAAK;;;CAUnD,SAAS,iBACP,OACA,KACA,YACA,SACM;AACN,MAAI,GAAG,UAAU,MAAM,EAAE;GACvB,MAAM,UAAU,MAAM,KAAK,QAAQ,UAAU,GAAG,CAAC,MAAM;AACvD,OAAI,QAAS,KAAI,KAAK;IAAE,MAAM;IAAQ,MAAM;IAAS,CAAC;AACtD;;AAEF,MAAI,GAAG,aAAa,MAAM,IAAI,GAAG,wBAAwB,MAAM,EAAE;AAC/D,OAAI,KAAK;IAAE,MAAM;IAAW,MAAM;IAAO,SAAS,WAAW;IAAS,CAAC;AACvE;;AAEF,MAAI,GAAG,gBAAgB,MAAM,EAAE;AAC7B,OAAI,MAAM,WAAY,KAAI,KAAK;IAAE,MAAM;IAAc,YAAY,MAAM;IAAY,CAAC;AACpF;;AAEF,MAAI,GAAG,cAAc,MAAM,CAAE,SAAQ,MAAM,SAAS;;;;;;CAOtD,SAAS,gBAAgB,UAAkD;EACzE,MAAM,WAAwB,EAAE;EAChC,MAAM,aAAa,EAAE,OAAO,GAAG;EAE/B,SAAS,YAAY,MAAuC;AAC1D,QAAK,MAAM,SAAS,KAAM,kBAAiB,OAAO,UAAU,YAAY,YAAY;;AAGtF,cAAY,SAAS;AACrB,SAAO;;;CAIT,SAAS,gBAAgB,cAGvB;EACA,MAAM,UAAU,aAAa,MAAM,MAAM,EAAE,SAAS,UAAU;EAC9D,MAAM,aAAa,aAAa,MAAM,MAAM,EAAE,SAAS,UAAU;EACjE,MAAM,YAAY,aAAa,QAAQ,MAAM,EAAE,SAAS,aAAa,CAAC;AACtE,SAAO;GAAE,UAAU,WAAW;GAAY,cAAc,YAAY;GAAG;;;CAIzE,SAAS,cAAc,MAAoC;AACzD,MAAI,CAAC,GAAG,eAAe,KAAK,CAAE,QAAO;EACrC,MAAM,OAAO,GAAG,aAAa,KAAK,KAAK,GAAG,KAAK,KAAK,OAAO;AAC3D,MAAI,SAAS,MAAO,QAAO;AAC3B,MAAI,SAAS,KAAK,KAAK,CAAE,QAAO;AAChC,MAAI,CAAC,KAAK,eAAe,CAAC,GAAG,gBAAgB,KAAK,YAAY,CAAE,QAAO;EACvE,MAAM,OAAO,KAAK,YAAY;AAC9B,SAAO,OAAO,CAAC,SAAS,KAAK,GAAG;;;CAIlC,SAAS,kBAAkB,MAAyD;AAClF,MAAI,SAAS,KAAK,CAAC,KAAK,cAAc,CAAE,QAAO;AAC/C,MAAI,GAAG,aAAa,KAAK,CACvB,QAAO,KAAK,SAAS,MAAM,MAAM,GAAG,gBAAgB,EAAE,IAAI,EAAE,eAAe,OAAU;AAEvF,SAAO;;;;;CAMT,SAAS,UAAU,MAA6B;AAE9C,MAAI,gBAAgB,OAAO,KAAK,cAAc,KAAK,EAAE;GACnD,MAAM,WAAW,sBAAsB,sBAAM,IAAI,KAAK,EAAE,KAAK;AAC7D,UAAO,QAAQ,UAAU,GAAG,SAAS,YAAY,UAAU,GAAG;;AAEhE,SAAO,KAAK,MAAM,KAAK,SAAS,GAAG,EAAE,KAAK,QAAQ,CAAC;;;CAIrD,SAAS,WAAW,MAAwD;EAC1E,MAAM,MAAM,GAAG,aAAa,KAAK,GAAG,KAAK,eAAe,UAAU,KAAK;AACvE,SAAO,GAAG,aAAa,IAAI,GAAG,IAAI,OAAO;;;CAI3C,SAAS,SACP,MACmC;AACnC,SAAO,GAAG,aAAa,KAAK,GACxB,KAAK,eAAe,WAAW,aAC/B,KAAK,WAAW;;;AAMxB,MAAM,gBAAgB,IAAI,IAAI;CAC5B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;AAEF,MAAM,mBAA2C;CAC/C,WAAW;CACX,SAAS;CACV;;;;;;AAOD,MAAM,iBAAiB,IAAI,IAAI;CAC7B;CAAU;CAAY;CAAU;CAChC;CAAiB;CACjB;CAAc;CAAU;CACxB;CAAW;CAAY;CACvB;CAAe;CAChB,CAAC;AAEF,SAAS,eAAe,MAAwB;AAC9C,KAAI,CAAC,GAAG,iBAAiB,KAAK,CAAE,QAAO;CACvC,MAAM,SAAS,KAAK;AACpB,KAAI,GAAG,aAAa,OAAO,CAAE,QAAO,eAAe,IAAI,OAAO,KAAK;AACnE,QAAO;;;;;;;AAQT,SAAS,qBAAqB,MAAqB,MAAuB;AAExE,KAAI,GAAG,2BAA2B,KAAK,IAAI,KAAK,KAAK,SAAS,WAAY,QAAO;AAEjF,KAAI,GAAG,aAAa,KAAK,IAAI,KAAK,SAAS,WAAY,QAAO;AAE9D,KAAI,KAAK,SAAS,YAAY,IAAI,SAAS,WAAY,QAAO;AAC9D,QAAO;;AAGT,SAAS,YAAY,GAAoB;AACvC,QAAO,EAAE,SAAS,KAAK,EAAE,OAAO,EAAE,IAAI,aAAa;;;AAIrD,SAAS,kBAAkB,MAAwB;AACjD,KAAI,GAAG,aAAa,KAAK,IAAI,GAAG,wBAAwB,KAAK,IAAI,GAAG,cAAc,KAAK,CACrF,QAAO;AACT,QAAO,GAAG,aAAa,MAAM,kBAAkB,IAAI;;AAGrD,SAAS,eAAe,GAAmB;AACzC,QAAO,EAAE,QAAQ,MAAM,QAAQ,CAAC,QAAQ,MAAM,SAAS;;AAGzD,SAAS,eAAe,GAAmB;AAKzC,QAAO,EAAE,QAAQ,6CAA6C,QAAQ,CAAC,QAAQ,MAAM,OAAO;;AAO9F,SAAS,gBAAgB,MAA8B;AACrD,KAAI,GAAG,wBAAwB,KAAK,CAClC,QAAO,cAAc,KAAK,WAAW;AAEvC,KAAI,GAAG,cAAc,KAAK,CACxB,QAAO,KAAK,SAAS,MAAM,cAAc;AAG3C,QAAO,cAAc,KAAK,eAAe,WAAW,IAAI,KAAK,SAAS,MAAM,cAAc;;AAG5F,SAAS,cAAc,OAAkC;AACvD,QAAO,MAAM,WAAW,OAAO,SAAS;AAEtC,MAAI,CAAC,GAAG,eAAe,KAAK,CAAE,QAAO;AAErC,MAAI,CAAC,KAAK,YAAa,QAAO;AAE9B,MAAI,GAAG,gBAAgB,KAAK,YAAY,CAAE,QAAO;EAEjD,MAAM,OAAQ,KAAK,YAAiC;AACpD,SAAO,OAAO,SAAS,KAAK,GAAG;GAC/B;;AAGJ,SAAS,cAAc,OAA6B;AAElD,KAAI,GAAG,UAAU,MAAM,CAAE,QAAO;AAEhC,KAAI,GAAG,wBAAwB,MAAM,CAAE,QAAO,gBAAgB,MAAM;AACpE,KAAI,GAAG,aAAa,MAAM,CAAE,QAAO,gBAAgB,MAAM;AACzD,KAAI,GAAG,cAAc,MAAM,CAAE,QAAO,gBAAgB,MAAM;CAE1D,MAAM,OAAQ,MAA2B;AACzC,QAAO,OAAO,SAAS,KAAK,GAAG;;AAKjC,SAAS,SAAS,MAA8B;AAC9C,QACE,GAAG,gBAAgB,KAAK,IACxB,GAAG,iBAAiB,KAAK,IACzB,GAAG,gCAAgC,KAAK,IACxC,KAAK,SAAS,GAAG,WAAW,eAC5B,KAAK,SAAS,GAAG,WAAW,gBAC5B,KAAK,SAAS,GAAG,WAAW,eAC5B,KAAK,SAAS,GAAG,WAAW;;;AAOhC,MAAM,aAAa,IAAI,IAAI;CACzB;CAAY;CAAY;CAAY;CAAc;CAAa;CAC/D;CAAY;CAAa;CAAe;CAAc;CACtD;CAAmB;CAAqB;CAAgB;CACxD;CAAY;CAAc;CAAS;CACnC;CAAuB;CACvB;CAAe;CAAiB;CAAkB;CAClD;CAAiB;CACjB;CAAc;CAAiB;CAC/B;CAAkB;CAClB;CAAsB;CAAsB;CAAa;CACzD;CACD,CAAC;;AAGF,SAAS,iBAAiB,MAAkC;CAC1D,MAAM,SAAS,KAAK;CACpB,IAAI,OAAO;AAEX,KAAI,GAAG,aAAa,OAAO,CACzB,QAAO,OAAO;UACL,GAAG,2BAA2B,OAAO,IAAI,GAAG,aAAa,OAAO,WAAW,CACpF,QAAO,GAAG,OAAO,WAAW,KAAK,GAAG,OAAO,KAAK;AAGlD,KAAI,CAAC,WAAW,IAAI,KAAK,CAAE,QAAO;AAElC,QAAO,KAAK,UAAU,OAAO,QAAQ,CAAC,GAAG,gBAAgB,IAAI,IAAI,SAAS,IAAI,CAAC;;AAGjF,SAAS,aAAa,MAAwB;AAC5C,KAAI,GAAG,iBAAiB,KAAK,EAAE;AAE7B,MAAI,iBAAiB,KAA0B,CAAE,QAAO;AACxD,SAAO;;AAET,KAAI,GAAG,2BAA2B,KAAK,CAAE,QAAO;AAEhD,KAAI,GAAG,gBAAgB,KAAK,IAAI,GAAG,qBAAqB,KAAK,CAAE,QAAO;AACtE,QAAO,GAAG,aAAa,MAAM,aAAa,IAAI;;;;;;;;AC7zChD,SAAgB,gBAAgB,KAA6B;CAC3D,MAAM,QAAQ,mBAAmB,IAAI;AAGrC,QAAO;EACL,WAAW;EACX,SAJc,YAAY,IAAI;EAK9B,8BAAa,IAAI,MAAM,EAAC,aAAa;EACrC,QAAQ,cAAc,OAAO,IAAI;EACjC,YAAY,kBAAkB,OAAO,IAAI;EACzC,SAAS,eAAe,OAAO,IAAI;EACpC;;AAGH,SAAS,mBAAmB,KAAuB;CACjD,MAAM,UAAoB,EAAE;CAC5B,MAAM,aAAa,IAAI,IAAI;EAAC;EAAQ;EAAQ;EAAO;EAAM,CAAC;CAC1D,MAAM,aAAa,IAAI,IAAI;EAAC;EAAgB;EAAQ;EAAO;EAAW;EAAQ;EAAQ,CAAC;CAEvF,SAAS,KAAK,KAAmB;EAC/B,IAAI;AACJ,MAAI;AACF,aAAU,GAAG,YAAY,KAAK,EAAE,eAAe,MAAM,CAAC;UAChD;AACN;;AAEF,OAAK,MAAM,SAAS,SAAS;AAC3B,OAAI,MAAM,KAAK,WAAW,IAAI,IAAI,MAAM,aAAa,CAAE;AACvD,OAAI,WAAW,IAAI,MAAM,KAAK,IAAI,MAAM,aAAa,CAAE;GACvD,MAAM,WAAW,KAAK,KAAK,KAAK,MAAM,KAAK;AAC3C,OAAI,MAAM,aAAa,CACrB,MAAK,SAAS;YACL,MAAM,QAAQ,IAAI,WAAW,IAAI,KAAK,QAAQ,MAAM,KAAK,CAAC,CACnE,SAAQ,KAAK,SAAS;;;AAK5B,MAAK,IAAI;AACT,QAAO;;AAGT,SAAS,cAAc,OAAiB,MAA2B;CACjE,MAAM,SAAsB,EAAE;AAE9B,MAAK,MAAM,QAAQ,OAAO;EACxB,IAAI;AACJ,MAAI;AACF,UAAO,GAAG,aAAa,MAAM,QAAQ;UAC/B;AACN;;EAGF,MAAM,eACJ;EACF,IAAI;AACJ,OAAK,QAAQ,aAAa,KAAK,KAAK,EAAE,OAAO,QAAQ,aAAa,KAAK,KAAK,EAAE;GAC5E,MAAM,QAAQ,MAAM,MAAM;GAC1B,MAAM,aAAa;GACnB,IAAI;AACJ,QAAK,aAAa,WAAW,KAAK,MAAM,EAAE,YAAY,aAAa,WAAW,KAAK,MAAM,EAAE;IACzF,MAAM,YAAY,WAAW,MAAM;IACnC,MAAM,mBAAmB,KAAK,IAAI,GAAG,WAAW,QAAQ,GAAG;IAC3D,MAAM,iBAAiB,KAAK,IAAI,MAAM,QAAQ,WAAW,QAAQ,IAAI;IACrE,MAAM,cAAc,MAAM,MAAM,kBAAkB,eAAe;AAEjE,WAAO,KAAK;KACV,MAAM;KACN,MAAM,YAAY,MAAM,8BAA8B,GAAG;KACzD,WAAW,aAAa,KAAK,YAAY;KACzC,UAAU,kCAAkC,KAAK,YAAY;KAC7D,QAAQ,cAAc,UAAU;KACjC,CAAC;;;;AAKR,QAAO;;AAGT,SAAS,kBAAkB,OAAiB,KAA8B;CACxE,MAAM,aAA8B,EAAE;AAEtC,MAAK,MAAM,QAAQ,OAAO;EACxB,IAAI;AACJ,MAAI;AACF,UAAO,GAAG,aAAa,MAAM,QAAQ;UAC/B;AACN;;EAGF,MAAM,cACJ;EACF,IAAI;AAEJ,OAAK,QAAQ,YAAY,KAAK,KAAK,EAAE,OAAO,QAAQ,YAAY,KAAK,KAAK,EAAE;GAC1E,MAAM,OAAO,MAAM,MAAM;GAEzB,MAAM,SADW,MAAM,MAAM,IAE1B,MAAM,OAAO,CACb,KAAK,MAAM,EAAE,MAAM,CAAC,QAAQ,SAAS,GAAG,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,IAAI,MAAM,IAAI,CAAC,IAAI,MAAM,IAAI,GAAG,CAC3F,QAAQ,MAAM,KAAK,MAAM,QAAQ;GAEpC,MAAM,YAAY,MAAM,QAAQ,MAAM,GAAG;GACzC,MAAM,OAAO,KAAK,MAAM,WAAW,KAAK,IAAI,KAAK,QAAQ,YAAY,IAAK,CAAC;GAC3E,MAAM,cAAwB,EAAE;GAChC,MAAM,WAAW;GACjB,IAAI;AACJ,QAAK,WAAW,SAAS,KAAK,KAAK,EAAE,UAAU,WAAW,SAAS,KAAK,KAAK,CAC3E,KAAI,SAAS,GAAI,aAAY,KAAK,SAAS,GAAG;AAGhD,cAAW,KAAK;IACd;IACA,MAAM,KAAK,SAAS,KAAK,KAAK;IAC9B,YAAY,YAAY,SAAS;IACjC;IACA;IACD,CAAC;;;AAIN,QAAO;;AAGT,SAAS,eAAe,OAAiB,KAA2B;CAClE,MAAM,UAAwB,EAAE;AAEhC,MAAK,MAAM,QAAQ,OAAO;EACxB,IAAI;AACJ,MAAI;AACF,UAAO,GAAG,aAAa,MAAM,QAAQ;UAC/B;AACN;;EAGF,MAAM,WACJ;EACF,IAAI;AACJ,OAAK,QAAQ,SAAS,KAAK,KAAK,EAAE,OAAO,QAAQ,SAAS,KAAK,KAAK,CAClE,KAAI,MAAM,GACR,SAAQ,KAAK;GACX,MAAM,MAAM;GACZ,MAAM,KAAK,SAAS,KAAK,KAAK;GAC9B,SAAS,MAAM,MAAM;GACtB,CAAC;;AAKR,QAAO;;AAGT,SAAS,cAAc,WAA6B;CAClD,MAAM,SAAmB,EAAE;CAC3B,MAAM,UAAU;CAChB,IAAI;AACJ,MAAK,QAAQ,QAAQ,KAAK,UAAU,EAAE,OAAO,QAAQ,QAAQ,KAAK,UAAU,CAC1E,KAAI,MAAM,GAAI,QAAO,KAAK,MAAM,GAAG;AAErC,QAAO;;AAGT,SAAS,YAAY,KAAqB;AACxC,KAAI;EACF,MAAM,MAAM,KAAK,MAAM,GAAG,aAAa,KAAK,KAAK,KAAK,eAAe,EAAE,QAAQ,CAAC;EAChF,MAAM,OAAgC;GAAE,GAAG,IAAI;GAAc,GAAG,IAAI;GAAiB;AACrF,OAAK,MAAM,CAAC,MAAM,QAAQ,OAAO,QAAQ,KAAK,CAC5C,KAAI,KAAK,WAAW,WAAW,IAAI,OAAO,QAAQ,SAAU,QAAO,IAAI,QAAQ,UAAU,GAAG;AAE9F,SAAQ,IAAI,WAAsB;SAC5B;AACN,SAAO;;;;;;;;;;;;;;;;;;;;AC/EX,MAAM,kBAAiD;CACrD,OAAO;CACP,aAAa;CACb,oBAAoB;CACpB,oBAAoB;CACpB,gBAAgB;CAChB,oBAAoB;CACrB;;AAGD,MAAM,qBAAqE;CACzE,UAAU;EAAE,MAAM;EAAU,MAAM;EAAsB;CACxD,WAAW;EAAE,MAAM;EAAU,MAAM;EAAsB;CACzD,iBAAiB;EAAE,MAAM;EAAU,MAAM;EAAsB;CAC/D,SAAS;EAAE,MAAM;EAAY,MAAM;EAAsB;CACzD,YAAY;EAAE,MAAM;EAAU,MAAM;EAAsB;CAC1D,QAAQ;EAAE,MAAM;EAAU,MAAM;EAAsB;CACtD,eAAe;EAAE,MAAM;EAAiB,MAAM;EAAgB;CAC9D,YAAY;EAAE,MAAM;EAAc,MAAM;EAAgB;CACxD,UAAU;EAAE,MAAM;EAAY,MAAM;EAAgB;CACpD,UAAU;EAAE,MAAM;EAAY,MAAM;EAAgB;CACpD,MAAM;EAAE,MAAM;EAAQ,MAAM;EAAgB;CAC5C,MAAM;EAAE,MAAM;EAAI,MAAM;EAAI;CAC5B,YAAY;EAAE,MAAM;EAAI,MAAM;EAAI;CAClC,YAAY;EAAE,MAAM;EAAS,MAAM;EAAuB;CAC1D,aAAa;EAAE,MAAM;EAAe,MAAM;EAAuB;CAEjE,aAAa;EAAE,MAAM;EAAa,MAAM;EAAkB;CAC1D,WAAW;EAAE,MAAM;EAAY,MAAM;EAAkB;CACvD,aAAa;EAAE,MAAM;EAAY,MAAM;EAAkB;CACzD,MAAM;EAAE,MAAM;EAAc,MAAM;EAAkB;CACpD,SAAS;EAAE,MAAM;EAAc,MAAM;EAAkB;CACvD,QAAQ;EAAE,MAAM;EAAc,MAAM;EAAkB;CACtD,iBAAiB;EAAE,MAAM;EAAmB,MAAM;EAAkB;CACrE;;AAGD,MAAM,oBAA4C;CAChD,WAAW;CACX,SAAS;CACV;AAaD,SAAS,kBAAkB,KAAoB,MAAuB;AACpE,QAAO,IAAI,KAAK,MAAM,KAAK,SAAS,IAAI,GAAG,EAAE,KAAK,QAAQ,CAAC;;AAG7D,SAAS,WACP,KACA,MACA,UACA,SACA,SACA,WACA,SACM;CACN,MAAM,EAAE,MAAM,cAAc,IAAI,GAAG,8BAA8B,KAAK,SAAS,IAAI,GAAG,CAAC;AACvF,KAAI,YAAY,KAAK;EACnB,MAAM;EACN;EACA,MAAM,OAAO;EACb,QAAQ;EACR,SAAS,QAAQ,MAAM;EACvB,WAAW,UAAU,MAAM;EAC3B;EACD,CAAC;;AAGJ,SAAS,wBAAwB,KAAoB,MAAkC;AACrF,KAAI,CAAC,KAAK,gBAAiB;CAC3B,MAAM,SAAU,KAAK,gBAAqC;CAC1D,MAAM,eAAe,gBAAgB;AAErC,KAAI,iBAAiB,QAAW;AAC9B,MAAI,KAAK,cAAc,iBAAiB,GAAG,eAAe,KAAK,aAAa,cAAc,CACxF,MAAK,MAAM,QAAQ,KAAK,aAAa,cAAc,SACjD,KAAI,mBAAmB,IAAI,KAAK,KAAK,KAAK;AAU9C,aACE,KACA,MARe,OAAO,WAAW,eAAe,GAC9C,wBACA,OAAO,WAAW,YAAY,GAC5B,qBACA,gBAMJ,gBAAgB,OAAO,+CACvB,kBAAkB,KAAK,KAAK,EAC5B,eACI,wBAAwB,aAAa,KACrC,6CACJ,KACD;;;AAIL,SAAS,eAAe,KAAoB,MAA+B;CACzE,MAAM,SAAS,KAAK;AACpB,KACE,GAAG,sBAAsB,OAAO,IAChC,OAAO,QACP,GAAG,sBAAsB,OAAO,KAAK,IACrC,OAAO,KAAK,SAAS,UAAU,GAC/B;EACA,MAAM,UAAU,OAAO,KAAK,SAAS;EACrC,MAAM,YACJ,WAAW,GAAG,iBAAiB,QAAQ,GAAI,QAAQ,KAAuB,OAAO;EACnF,MAAM,UAAU,KAAK,UAAU,KAAK,kBAAkB,KAAK,KAAK,UAAU,GAAG,GAAG;AAEhF,aACE,KACA,MACA,aACA,2DAA2D,UAAU,aAAa,UAAU,UAC5F,kBAAkB,KAAK,OAAO,EAC9B,GAAG,UAAU,YAAY,QAAQ,IACjC,KACD;OAED,YACE,KACA,MACA,aACA,qDACA,kBAAkB,KAAK,KAAK,EAC5B,wBACA,KACD;;AAIL,SAAS,mBAAmB,aAAqC;AAC/D,KAAI,CAAC,GAAG,gBAAgB,YAAY,IAAI,CAAC,GAAG,qBAAqB,YAAY,CAAE,QAAO;CACtF,MAAM,OAAO,YAAY;AACzB,KAAI,CAAC,GAAG,QAAQ,KAAK,CAAE,QAAO;AAC9B,MAAK,MAAM,QAAQ,KAAK,WACtB,KAAI,GAAG,kBAAkB,KAAK,IAAI,KAAK,WAAY,QAAO;AAE5D,QAAO;;AAGT,SAAS,gBAAgB,KAAoB,MAA+B;CAC1E,MAAM,WAAY,KAAK,WAA6B;CACpD,MAAM,UAAU,KAAK,UAAU;CAC/B,MAAM,cAAc,KAAK,UAAU;AAEnC,KAAI,WAAW,GAAG,yBAAyB,QAAQ,IAAI,QAAQ,SAAS,WAAW,GAAG;EACpF,MAAM,aAAa,cAAc,mBAAmB,YAAY,GAAG;AAEnE,aACE,KACA,MACA,oBACA,GAAG,SAAS,0EACZ,kBAAkB,KAAK,KAAK,EAC5B,aACI,yEACA,sCACJ,KACD;YACQ,WAAW,GAAG,yBAAyB,QAAQ,CACxD,YACE,KACA,MACA,mBACA,GAAG,SAAS,0FACZ,kBAAkB,KAAK,KAAK,EAC5B,mDACA,KACD;UACQ,CAAC,QACV,YACE,KACA,MACA,sBACA,GAAG,SAAS,oFACZ,kBAAkB,KAAK,KAAK,EAC5B,8DACA,KACD;;AAIL,SAAS,cAAc,KAAoB,MAA+B;CACxE,MAAM,YAAY,KAAK,UAAU;CACjC,MAAM,cAAc,YAAY,kBAAkB,KAAK,UAAU,GAAG;AAEpE,YACE,KACA,MACA,YACA,kFACA,kBAAkB,KAAK,KAAK,EAC5B,YAAY,YAAY,IACxB,KACD;;AAGH,SAAS,kBAAkB,KAAoB,MAA+B;CAC5E,MAAM,aAAa,KAAK,UAAU;CAClC,MAAM,eAAe,aAAa,kBAAkB,KAAK,WAAW,GAAG;AAEvE,YACE,KACA,MACA,gBACA,+GACA,kBAAkB,KAAK,KAAK,EAC5B,cACA,KACD;;AAGH,SAAS,aAAa,KAAoB,MAA+B;CACvE,MAAM,MAAM,KAAK,UAAU;AAK3B,KAHE,QACC,IAAI,SAAS,GAAG,WAAW,eAAgB,GAAG,aAAa,IAAI,IAAI,IAAI,SAAS,aAGjF,YACE,KACA,MACA,eACA,4EACA,kBAAkB,KAAK,KAAK,EAC5B,eACA,KACD;MACI;EACL,MAAM,WAAW,MAAM,kBAAkB,KAAK,IAAI,GAAG;AACrD,aACE,KACA,MACA,eACA,+FACA,kBAAkB,KAAK,KAAK,EAC5B,UAAU,SAAS,IACnB,KACD;;;AAIL,SAAS,iBAAiB,KAAoB,MAA+B;AAC3E,YACE,KACA,MACA,eACA,0FACA,kBAAkB,KAAK,KAAK,EAC5B,0GACA,MACD;;AAGH,SAAS,iBAAiB,QAAuB,YAA6B;AAC5E,QACE,GAAG,2BAA2B,OAAO,IACrC,GAAG,aAAa,OAAO,WAAW,IAClC,OAAO,WAAW,SAAS,WAC3B,OAAO,KAAK,SAAS;;AAIzB,SAAS,kBAAkB,KAAoB,MAA+B;CAC5E,MAAM,SAAS,KAAK;AAIpB,KAFG,GAAG,aAAa,OAAO,IAAI,OAAO,SAAS,UAAW,iBAAiB,QAAQ,OAAO,EAE7E;EACV,MAAM,QAAQ,KAAK,UAAU;EAC7B,MAAM,YAAY,QAAQ,kBAAkB,KAAK,MAAM,GAAG;AAE1D,aACE,KACA,MACA,gBACA,uGACA,kBAAkB,KAAK,KAAK,EAC5B,WACA,KACD;;;AAIL,SAAS,iBAAiB,KAAoB,MAA+B;CAC3E,MAAM,SAAS,KAAK;AAKpB,KAHG,GAAG,aAAa,OAAO,IAAI,OAAO,SAAS,gBAC5C,iBAAiB,QAAQ,aAAa,CAGtC,YACE,KACA,MACA,eACA,mEACA,kBAAkB,KAAK,KAAK,EAC5B,qFACA,KACD;;AAIL,SAAS,oBAAoB,KAAoB,MAA6B;CAC5E,MAAM,WAAY,KAAK,KAAuB;AAE9C,KAAI,YAAY,mBAAmB;EACjC,MAAM,WAAW,kBAAkB;AACnC,aACE,KACA,MACA,aAAa,cAAc,oBAAoB,iBAC/C,IAAI,SAAS,mCAAmC,SAAS,+BACzD,kBAAkB,KAAK,KAAK,EAC5B,kBAAkB,KAAK,KAAK,CAAC,QAAQ,UAAU,SAAS,EACxD,KACD;;AAGH,KAAI,aAAa,YAAY;EAC3B,MAAM,aAAa,qBAAqB,KAAK;AAC7C,MAAI,YAAY;GACd,MAAM,UAAU,cAAc,WAAW;AACzC,OAAI,YAAY,WAAW,YAAY,cAAc,YAAY,SAC/D,YACE,KACA,MACA,mBACA,gBAAgB,QAAQ,kGACxB,kBAAkB,KAAK,KAAK,EAC5B,kBAAkB,KAAK,KAAK,CAAC,QAAQ,YAAY,UAAU,EAC3D,KACD;;;AAKP,KAAI,aAAa,0BACf,YACE,KACA,MACA,8BACA,4EACA,kBAAkB,KAAK,KAAK,EAC5B,0BACA,KACD;;AAIL,SAAS,qBAAqB,KAAoB,MAAyC;CACzF,MAAM,UAAW,KAAK,WAA6B;CACnD,MAAM,SAAS,KAAK;AACpB,KAAI,GAAG,mBAAmB,OAAO,IAAI,OAAO,SAAS,KACnD,YACE,KACA,MACA,oBACA,IAAI,QAAQ,mFAAmF,QAAQ,oBACvG,kBAAkB,KAAK,OAAO,EAC9B,GAAG,QAAQ,OAAO,kBAAkB,KAAK,OAAO,MAAM,CAAC,IACvD,MACD;;AAIL,SAAS,kBAAkB,KAAoB,MAA+B;CAC5E,MAAM,SAAS,KAAK;AACpB,KAAI,GAAG,gBAAgB,OAAO,EAAE;EAC9B,MAAM,YAAY,kBAChB,KACC,KAAK,WAA2C,WAClD;EACD,MAAM,cAAc,KAAK,UAAU;EACnC,MAAM,kBAAkB,cACpB,kBAAkB,KAAK,YAAY,GACnC;AAEJ,aACE,KACA,MACA,iBACA,+FACA,kBAAkB,KAAK,KAAK,EAC5B,cAAc,UAAU,8BAA8B,gBAAgB,YACtE,MACD;;;AAIL,SAAS,aAAa,MAAe,UAA6C;AAChF,QACE,GAAG,iBAAiB,KAAK,IACzB,GAAG,aAAa,KAAK,WAAW,IAChC,KAAK,WAAW,SAAS;;AAI7B,SAAS,mBAAmB,MAA0C;AACpE,QACE,GAAG,iBAAiB,KAAK,IACzB,GAAG,aAAa,KAAK,WAAW,KAC/B,KAAK,WAAW,SAAS,eAAe,KAAK,WAAW,SAAS;;AAItE,SAAS,oBAAoB,MAA0C;AACrE,QACE,GAAG,iBAAiB,KAAK,IACzB,GAAG,2BAA2B,KAAK,WAAW,IAC9C,GAAG,aAAa,KAAK,WAAW,KAAK,IACrC,KAAK,WAAW,KAAK,SAAS;;AAIlC,SAAS,iBAAiB,MAAoD;AAC5E,QACE,GAAG,2BAA2B,KAAK,IACnC,GAAG,aAAa,KAAK,KAAK,IAC1B,KAAK,KAAK,SAAS,WACnB,GAAG,aAAa,KAAK,WAAW;;AAIpC,SAAS,gBAAgB,KAAoB,MAAqB;AAChE,KAAI,GAAG,oBAAoB,KAAK,CAAE,yBAAwB,KAAK,KAAK;AACpE,KAAI,aAAa,MAAM,WAAW,CAAE,gBAAe,KAAK,KAAK;AAC7D,KAAI,mBAAmB,KAAK,CAAE,iBAAgB,KAAK,KAAK;AACxD,KAAI,aAAa,MAAM,UAAU,CAAE,eAAc,KAAK,KAAK;AAC3D,KAAI,aAAa,MAAM,cAAc,CAAE,mBAAkB,KAAK,KAAK;AACnE,KAAI,aAAa,MAAM,SAAS,CAAE,cAAa,KAAK,KAAK;AACzD,KAAI,aAAa,MAAM,aAAa,CAAE,kBAAiB,KAAK,KAAK;AACjE,KAAI,GAAG,iBAAiB,KAAK,CAAE,mBAAkB,KAAK,KAAK;AAC3D,KAAI,GAAG,iBAAiB,KAAK,CAAE,kBAAiB,KAAK,KAAK;AAC1D,KAAI,GAAG,eAAe,KAAK,IAAI,GAAG,aAAa,KAAK,KAAK,CAAE,qBAAoB,KAAK,KAAK;AACzF,KAAI,iBAAiB,KAAK,CAAE,sBAAqB,KAAK,KAAK;AAC3D,KAAI,oBAAoB,KAAK,CAAE,mBAAkB,KAAK,KAAK;;AAG7D,SAAS,YAAY,KAAoB,MAAqB;AAC5D,IAAG,aAAa,OAAO,UAAU;AAC/B,kBAAgB,KAAK,MAAM;AAC3B,cAAY,KAAK,MAAM;GACvB;;AAGJ,SAAgB,oBAAoB,MAAc,WAAW,aAAgC;CAC3F,MAAM,KAAK,GAAG,iBAAiB,UAAU,MAAM,GAAG,aAAa,QAAQ,MAAM,GAAG,WAAW,IAAI;CAC/F,MAAM,MAAqB;EACzB;EACA;EACA,aAAa,EAAE;EACf,oCAAoB,IAAI,KAAa;EACtC;AAED,aAAY,KAAK,GAAG;AACpB,QAAO,IAAI;;AAmBb,SAAS,iBAAiB,KAAqB,QAAgB,WAAyB;AACtF,KAAI,CAAC,UAAU,CAAC,UAAW;CAC3B,IAAI,QAAQ,IAAI,cAAc,IAAI,OAAO;AACzC,KAAI,CAAC,OAAO;AACV,0BAAQ,IAAI,KAAK;AACjB,MAAI,cAAc,IAAI,QAAQ,MAAM;;AAEtC,OAAM,IAAI,UAAU;;AAGtB,SAAS,eAAe,KAAqB,MAAe,MAAoB;AAC9E,KAAI,aAAa,KAAK;EAAE,OAAO,KAAK,SAAS,IAAI,GAAG;EAAE,KAAK,KAAK,QAAQ;EAAE;EAAM,CAAC;;AAGnF,SAAS,mBAAmB,KAAqB,MAAuB;AACtE,QAAO,IAAI,KAAK,MAAM,KAAK,SAAS,IAAI,GAAG,EAAE,KAAK,QAAQ,CAAC;;AAG7D,SAAS,eAAe,KAAqB,MAAuB;AAClE,QAAO,IAAI,GAAG,8BAA8B,KAAK,SAAS,IAAI,GAAG,CAAC,CAAC,OAAO;;AAG5E,SAAS,yBAAyB,KAAqB,MAAkC;AACvF,KAAI,CAAC,KAAK,gBAAiB;AAE3B,KAAI,EADY,KAAK,gBAAqC,QAC1C,iBAAkB;AAElC,KAAI,KAAK,cAAc,iBAAiB,GAAG,eAAe,KAAK,aAAa,cAAc,CACxF,MAAK,MAAM,QAAQ,KAAK,aAAa,cAAc,UAAU;EAE3D,MAAM,UAAU,mBADH,KAAK,KAAK;AAEvB,MAAI,SAAS;AACX,OAAI,QAAQ,KACV,kBAAiB,KAAK,QAAQ,MAAM,QAAQ,KAAK;AAEnD,OAAI,kBAAkB,IAAI,MAAM,QAAQ;;;AAI9C,KAAI,gBAAgB,IAAI,KAAK;;AAG/B,SAAS,gBAAgB,KAAqB,MAA+B;CAC3E,MAAM,SAAS,KAAK;AACpB,KACE,GAAG,sBAAsB,OAAO,IAChC,OAAO,QACP,GAAG,sBAAsB,OAAO,KAAK,IACrC,OAAO,KAAK,SAAS,UAAU,GAC/B;EACA,MAAM,UAAU,OAAO,KAAK,SAAS;EACrC,MAAM,YACJ,WAAW,GAAG,iBAAiB,QAAQ,GAAI,QAAQ,KAAuB,OAAO;EACnF,MAAM,UAAU,KAAK,UAAU,KAAK,mBAAmB,KAAK,KAAK,UAAU,GAAG,GAAG;EAEjF,MAAM,YAAY,OAAO,SAAS,IAAI,GAAG;EACzC,MAAM,UAAU,OAAO,QAAQ;AAC/B,MAAI,aAAa,KAAK;GACpB,OAAO;GACP,KAAK;GACL,MAAM,GAAG,UAAU,YAAY,QAAQ;GACxC,CAAC;AACF,mBAAiB,KAAK,sBAAsB,SAAS;AACrD,MAAI,QAAQ,KAAK;GACf,MAAM;GACN,MAAM,eAAe,KAAK,KAAK;GAC/B,aAAa,sBAAsB;GACpC,CAAC;;;AAIN,SAAS,iBAAiB,KAAqB,MAA+B;CAC5E,MAAM,UAAU,KAAK,UAAU;CAC/B,MAAM,cAAc,KAAK,UAAU;CACnC,MAAM,WAAY,KAAK,WAA6B;AAEpD,KACE,WACA,GAAG,yBAAyB,QAAQ,IACpC,QAAQ,SAAS,WAAW,KAC5B,aACA;AAEA,iBAAe,KAAK,MAAM,WADL,mBAAmB,KAAK,YAAY,CACP,GAAG;AACrD,mBAAiB,KAAK,gBAAgB,UAAU;AAChD,MAAI,QAAQ,KAAK;GACf,MAAM;GACN,MAAM,eAAe,KAAK,KAAK;GAC/B,aAAa,GAAG,SAAS;GAC1B,CAAC;YACO,aAAa;AAEtB,iBAAe,KAAK,MAAM,UADL,mBAAmB,KAAK,YAAY,CACR,GAAG;AACpD,mBAAiB,KAAK,sBAAsB,SAAS;AACrD,MAAI,QAAQ,KAAK;GACf,MAAM;GACN,MAAM,eAAe,KAAK,KAAK;GAC/B,aAAa,GAAG,SAAS;GAC1B,CAAC;;;AAIN,SAAS,eAAe,KAAqB,MAA+B;CAC1E,MAAM,YAAY,KAAK,UAAU;AACjC,KAAI,WAAW;AACb,iBAAe,KAAK,MAAM,YAAY,mBAAmB,KAAK,UAAU,CAAC,GAAG;AAC5E,mBAAiB,KAAK,sBAAsB,WAAW;AACvD,MAAI,QAAQ,KAAK;GACf,MAAM;GACN,MAAM,eAAe,KAAK,KAAK;GAC/B,aAAa;GACd,CAAC;;;AAIN,SAAS,mBAAmB,KAAqB,MAA+B;CAC9E,MAAM,aAAa,KAAK,UAAU;AAClC,KAAI,YAAY;AACd,iBAAe,KAAK,MAAM,mBAAmB,KAAK,WAAW,CAAC;AAC9D,MAAI,QAAQ,KAAK;GACf,MAAM;GACN,MAAM,eAAe,KAAK,KAAK;GAC/B,aAAa;GACd,CAAC;;;AAIN,SAAS,cAAc,KAAqB,MAA+B;CACzE,MAAM,MAAM,KAAK,UAAU;AAK3B,KAHE,QACC,IAAI,SAAS,GAAG,WAAW,eAAgB,GAAG,aAAa,IAAI,IAAI,IAAI,SAAS,gBAEjE,CAAC,KAAK;AACtB,iBAAe,KAAK,MAAM,cAAc;AACxC,mBAAiB,KAAK,gBAAgB,YAAY;AAClD,MAAI,QAAQ,KAAK;GACf,MAAM;GACN,MAAM,eAAe,KAAK,KAAK;GAC/B,aAAa;GACd,CAAC;QACG;AACL,iBAAe,KAAK,MAAM,UAAU,mBAAmB,KAAK,IAAI,CAAC,GAAG;AACpE,mBAAiB,KAAK,sBAAsB,SAAS;AACrD,MAAI,QAAQ,KAAK;GACf,MAAM;GACN,MAAM,eAAe,KAAK,KAAK;GAC/B,aAAa;GACd,CAAC;;;AAIN,SAAS,mBAAmB,KAAqB,MAA+B;CAC9E,MAAM,SAAS,KAAK;AAIpB,MAFG,GAAG,aAAa,OAAO,IAAI,OAAO,SAAS,UAAW,iBAAiB,QAAQ,OAAO,KAE3E,KAAK,UAAU,IAAI;AAC/B,iBAAe,KAAK,MAAM,mBAAmB,KAAK,KAAK,UAAU,GAAG,CAAC;AACrE,MAAI,QAAQ,KAAK;GACf,MAAM;GACN,MAAM,eAAe,KAAK,KAAK;GAC/B,aAAa;GACd,CAAC;;;AAIN,SAAS,kBAAkB,KAAqB,MAA+B;CAC7E,MAAM,SAAS,KAAK;AAKpB,MAHG,GAAG,aAAa,OAAO,IAAI,OAAO,SAAS,gBAC5C,iBAAiB,QAAQ,aAAa,KAEpB,KAAK,UAAU,IAAI;AACrC,iBAAe,KAAK,MAAM,mBAAmB,KAAK,KAAK,UAAU,GAAG,CAAC;AACrE,MAAI,QAAQ,KAAK;GACf,MAAM;GACN,MAAM,eAAe,KAAK,KAAK;GAC/B,aAAa;GACd,CAAC;;;AAIN,SAAS,qBAAqB,KAAqB,MAA6B;CAC9E,MAAM,WAAY,KAAK,KAAuB;AAE9C,KAAI,YAAY,mBAAmB;EACjC,MAAM,WAAW,kBAAkB;AACnC,MAAI,aAAa,KAAK;GACpB,OAAO,KAAK,KAAK,SAAS,IAAI,GAAG;GACjC,KAAK,KAAK,KAAK,QAAQ;GACvB,MAAM;GACP,CAAC;AACF,MAAI,QAAQ,KAAK;GACf,MAAM;GACN,MAAM,eAAe,KAAK,KAAK;GAC/B,aAAa,GAAG,SAAS,KAAK;GAC/B,CAAC;;AAGJ,KAAI,aAAa,YAAY;EAC3B,MAAM,aAAa,qBAAqB,KAAK;AAC7C,MAAI,YAAY;GACd,MAAM,UAAU,cAAc,WAAW;AACzC,OAAI,YAAY,WAAW,YAAY,cAAc,YAAY,UAAU;AACzE,QAAI,aAAa,KAAK;KACpB,OAAO,KAAK,KAAK,SAAS,IAAI,GAAG;KACjC,KAAK,KAAK,KAAK,QAAQ;KACvB,MAAM;KACP,CAAC;AACF,QAAI,QAAQ,KAAK;KACf,MAAM;KACN,MAAM,eAAe,KAAK,KAAK;KAC/B,aAAa,gBAAgB,QAAQ;KACtC,CAAC;;;;AAKR,KAAI,aAAa,0BACf,gCAA+B,KAAK,KAAK;;AAI7C,SAAS,+BAA+B,KAAqB,MAA6B;AACxF,KAAI,CAAC,KAAK,eAAe,CAAC,GAAG,gBAAgB,KAAK,YAAY,IAAI,CAAC,KAAK,YAAY,WAClF;CAEF,MAAM,OAAO,KAAK,YAAY;AAC9B,KAAI,CAAC,GAAG,0BAA0B,KAAK,CAAE;CAEzC,MAAM,WAAW,KAAK,WAAW,MAC9B,MAAM,GAAG,qBAAqB,EAAE,IAAI,GAAG,aAAa,EAAE,KAAK,IAAI,EAAE,KAAK,SAAS,SACjF;AAED,KAAI,UAAU;AAEZ,iBAAe,KAAK,MAAM,cADR,mBAAmB,KAAK,SAAS,YAAY,CACb,GAAG;AACrD,MAAI,QAAQ,KAAK;GACf,MAAM;GACN,MAAM,eAAe,KAAK,KAAK;GAC/B,aAAa;GACd,CAAC;;;AAIN,SAAS,kBAAkB,MAAc,KAA6B;AAEpE,MAAK,MAAM,OAAO,IAAI,iBAAiB;AACrC,MAAI,aAAa,KAAK;GAAE,OAAO,IAAI,SAAS,IAAI,GAAG;GAAE,KAAK,IAAI,QAAQ;GAAE,MAAM;GAAI,CAAC;AACnF,MAAI,QAAQ,KAAK;GACf,MAAM;GACN,MAAM,IAAI,GAAG,8BAA8B,IAAI,SAAS,IAAI,GAAG,CAAC,CAAC,OAAO;GACxE,aAAa;GACd,CAAC;;AAIJ,KAAI,aAAa,MAAM,GAAG,MAAM,EAAE,QAAQ,EAAE,MAAM;CAGlD,MAAM,0BAAU,IAAI,KAAa;CACjC,MAAM,UAAyB,EAAE;AACjC,MAAK,MAAM,KAAK,IAAI,cAAc;EAChC,MAAM,MAAM,GAAG,EAAE,MAAM,GAAG,EAAE;EAC5B,IAAI,WAAW;AACf,OAAK,MAAM,KAAK,QACd,KAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO;AACtC,cAAW;AACX;;AAGJ,MAAI,CAAC,YAAY,CAAC,QAAQ,IAAI,IAAI,EAAE;AAClC,WAAQ,IAAI,IAAI;AAChB,WAAQ,KAAK,EAAE;;;AAKnB,SAAQ,MAAM,GAAG,MAAM,EAAE,QAAQ,EAAE,MAAM;CACzC,MAAM,QAAkB,EAAE;CAC1B,IAAI,UAAU;AACd,MAAK,MAAM,KAAK,SAAS;AACvB,QAAM,KAAK,KAAK,MAAM,SAAS,EAAE,MAAM,CAAC;AACxC,QAAM,KAAK,EAAE,KAAK;AAClB,YAAU,EAAE;;AAEd,OAAM,KAAK,KAAK,MAAM,QAAQ,CAAC;AAC/B,QAAO,MAAM,KAAK,GAAG;;AAGvB,SAAS,oBAAoB,MAAc,eAAiD;AAC1F,KAAI,cAAc,SAAS,EAAG,QAAO;CAErC,MAAM,cAAwB,EAAE;CAChC,MAAM,SAAS,CAAC,GAAG,cAAc,SAAS,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,cAAc,EAAE,CAAC;AAClF,MAAK,MAAM,CAAC,QAAQ,UAAU,QAAQ;EACpC,MAAM,WAAW,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,KAAK;AAC7C,cAAY,KAAK,YAAY,SAAS,WAAW,OAAO,GAAG;;CAE7D,MAAM,cAAc,YAAY,KAAK,KAAK;CAE1C,MAAM,gBAAgB,kBAAkB,KAAK;AAC7C,KAAI,gBAAgB,EAClB,QAAO,GAAG,KAAK,MAAM,GAAG,cAAc,CAAC,IAAI,cAAc,KAAK,MAAM,cAAc;AAEpF,QAAO,GAAG,YAAY,MAAM;;AAG9B,SAAS,iBAAiB,KAAqB,MAAqB;AAClE,KAAI,GAAG,oBAAoB,KAAK,CAAE,0BAAyB,KAAK,KAAK;AACrE,KAAI,aAAa,MAAM,WAAW,CAAE,iBAAgB,KAAK,KAAK;AAC9D,KAAI,mBAAmB,KAAK,CAAE,kBAAiB,KAAK,KAAK;AACzD,KAAI,aAAa,MAAM,UAAU,CAAE,gBAAe,KAAK,KAAK;AAC5D,KAAI,aAAa,MAAM,cAAc,CAAE,oBAAmB,KAAK,KAAK;AACpE,KAAI,aAAa,MAAM,SAAS,CAAE,eAAc,KAAK,KAAK;AAC1D,KAAI,GAAG,iBAAiB,KAAK,CAAE,oBAAmB,KAAK,KAAK;AAC5D,KAAI,GAAG,iBAAiB,KAAK,CAAE,mBAAkB,KAAK,KAAK;AAC3D,KAAI,GAAG,eAAe,KAAK,IAAI,GAAG,aAAa,KAAK,KAAK,CAAE,sBAAqB,KAAK,KAAK;;AAG5F,SAAS,aAAa,KAAqB,MAAqB;AAC9D,IAAG,aAAa,OAAO,UAAU;AAC/B,mBAAiB,KAAK,MAAM;AAC5B,eAAa,KAAK,MAAM;GACxB;;AAGJ,SAAgB,iBAAiB,MAAc,WAAW,aAA8B;CACtF,MAAM,KAAK,GAAG,iBAAiB,UAAU,MAAM,GAAG,aAAa,QAAQ,MAAM,GAAG,WAAW,IAAI;CAC/F,MAAM,cAAc,oBAAoB,MAAM,SAAS;CAEvD,MAAM,MAAsB;EAC1B;EACA;EACA,cAAc,EAAE;EAChB,SAAS,EAAE;EACX,+BAAe,IAAI,KAAK;EACxB,iCAAiB,IAAI,KAAK;EAC1B,mCAAmB,IAAI,KAAK;EAC7B;AAED,cAAa,KAAK,GAAG;CAErB,IAAI,SAAS,kBAAkB,MAAM,IAAI;AACzC,UAAS,oBAAoB,QAAQ,IAAI,cAAc;AAGvD,UAAS,OAAO,QAAQ,WAAW,OAAO;AAE1C,QAAO;EAAE,MAAM;EAAQ;EAAa,SAAS,IAAI;EAAS;;AAO5D,SAAS,qBACP,MACwD;CACxD,IAAI,UAAU,KAAK;AACnB,QAAO,SAAS;AACd,MAAI,GAAG,oBAAoB,QAAQ,IAAI,GAAG,wBAAwB,QAAQ,CACxE,QAAO;AAGT,MAAI,GAAG,aAAa,QAAQ,CAC1B,QAAO,QAAQ;AAEjB,MAAI,GAAG,gBAAgB,QAAQ,IAAI,GAAG,qBAAqB,QAAQ,CACjE,QAAO;AAET,YAAU,QAAQ;;AAEpB,QAAO;;AAGT,SAAS,cAAc,MAA+D;CACpF,MAAM,UAAU,KAAK;AACrB,KAAI,GAAG,aAAa,QAAQ,CAC1B,QAAO,QAAQ;AAEjB,QAAO;;AAGT,SAAS,kBAAkB,MAAsB;CAC/C,MAAM,WAAW;CACjB,IAAI,UAAU;CACd,IAAI;AACJ,QAAO,MAAM;AACX,UAAQ,SAAS,KAAK,KAAK;AAC3B,MAAI,CAAC,MAAO;AACZ,YAAU,MAAM,QAAQ,MAAM,GAAG;;AAEnC,QAAO;;;AAQT,SAAgB,iBAAiB,MAAuB;AACtD,QACE,qBAAqB,KAAK,KAAK,IAC/B,yBAAyB,KAAK,KAAK,IACnC,4BAA4B,KAAK,KAAK,IACtC,oBAAoB,KAAK,KAAK,IAC9B,mBAAmB,KAAK,KAAK,IAC7B,iBAAiB,KAAK,KAAK,IAC3B,qBAAqB,KAAK,KAAK,IAC/B,kBAAkB,KAAK,KAAK,IAC5B,sBAAsB,KAAK,KAAK,IAChC,kBAAkB,KAAK,KAAK,IAC5B,sBAAsB,KAAK,KAAK,IAChC,mBAAmB,KAAK,KAAK,IAC7B,iBAAiB,KAAK,KAAK,IAC3B,cAAc,KAAK,KAAK;;AAoB5B,MAAM,iBAAiC;CACrC;EACE,SAAS;EACT,WAAW,OAAO;GAChB,OAAO,YAAY,EAAE,GAAG;GACxB,KAAK;GACL,SAAS,mDAAmD,EAAE,GAAG;GAClE;EACF;CACD;EACE,SAAS;EACT,WAAW,OAAO;GAChB,OAAO,IAAI,EAAE,GAAG,+DAA+D,EAAE,GAAG;GACpF,KAAK;GACL,SAAS,iCAAiC,EAAE,GAAG,qBAAqB,EAAE,GAAG;GAC1E;EACF;CACD;EACE,SAAS;EACT,WAAW,OAAO;GAChB,OAAO,WAAW,EAAE,GAAG;GACvB,KAAK,gBAAgB,EAAE;GACvB,SAAS,WAAW,EAAE;GACvB;EACF;CACD;EACE,SAAS;EACT,iBAAiB;GACf,OAAO;GACP,KAAK;GACL,SACE;GACH;EACF;CACD;EACE,SAAS;EACT,WAAW,OAAO;GAChB,OAAO,cAAc,EAAE,GAAG,6CAA6C,EAAE,GAAG;GAC5E,KACE,EAAE,OAAO,UACL,6GACA,0EAA0E,EAAE,GAAG;GACrF,SACE,EAAE,OAAO,UAAU,0DAA0D;GAChF;EACF;CACD;EACE,SAAS;EACT,WAAW,OAAO;GAChB,OAAO,sBAAsB,EAAE,GAAG;GAClC,KAAK;GACL,SAAS;GACV;EACF;CACD;EACE,SAAS;EACT,iBAAiB;GACf,OAAO;GACP,KAAK;GACL,SAAS;GACV;EACF;CACD;EACE,SAAS;EACT,iBAAiB;GACf,OAAO;GACP,KAAK;GACL,SACE;GACH;EACF;CACD;EACE,SAAS;EACT,iBAAiB;GACf,OACE;GACF,KAAK;GACN;EACF;CACD;EACE,SAAS;EACT,iBAAiB;GACf,OAAO;GACP,KAAK;GACL,SAAS;GACV;EACF;CACF;;AAGD,SAAgB,cAAc,OAAsC;AAClE,MAAK,MAAM,EAAE,SAAS,cAAc,gBAAgB;EAClD,MAAM,QAAQ,MAAM,MAAM,QAAQ;AAClC,MAAI,MACF,QAAO,SAAS,MAAM;;AAG1B,QAAO"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["getJsxTagName"],"sources":["../src/jsx.ts","../src/project-scanner.ts","../src/react-intercept.ts","../src/pyreon-intercept.ts","../src/test-audit.ts"],"sourcesContent":["/**\n * JSX transform — wraps dynamic JSX expressions in `() =>` so the Pyreon runtime\n * receives reactive getters instead of eagerly-evaluated snapshot values.\n *\n * Rules:\n * - `<div>{expr}</div>` → `<div>{() => expr}</div>` (child)\n * - `<div class={expr}>` → `<div class={() => expr}>` (prop)\n * - `<button onClick={fn}>` → unchanged (event handler)\n * - `<div>{() => expr}</div>` → unchanged (already wrapped)\n * - `<div>{\"literal\"}</div>` → unchanged (static)\n *\n * Static VNode hoisting:\n * - Fully static JSX in expression containers is hoisted to module scope:\n * `{<span>Hello</span>}` → `const _$h0 = <span>Hello</span>` + `{_$h0}`\n * - Hoisted nodes are created ONCE at module initialisation, not per-instance.\n * - A JSX node is static if: all props are string literals / booleans / static\n * values, and all children are text nodes or other static JSX nodes.\n *\n * Template emission:\n * - JSX element trees with ≥ 1 DOM elements (no components, no spread attrs on\n * inner elements) are compiled to `_tpl(html, bindFn)` calls instead of nested\n * `h()` calls.\n * - The HTML string is parsed once via <template>.innerHTML, then cloneNode(true)\n * for each instance (~5-10x faster than sequential createElement calls).\n * - Static attributes are baked into the HTML string; dynamic attributes and\n * text content use renderEffect in the bind function.\n *\n * Implementation: Rust native binary (napi-rs) when available, JS fallback via oxc-parser.\n */\n\nimport { parseSync } from 'oxc-parser'\nimport { createRequire } from 'node:module'\nimport { fileURLToPath } from 'node:url'\nimport { dirname, join } from 'node:path'\n\n// ─── Native binary auto-detection ────────────────────────────────────────────\n// Try to load the Rust napi-rs binary for 3.7-8.2x faster transforms.\n// Falls back to the JS implementation below if the binary isn't available\n// (wrong platform, CI environment, WASM runtime like StackBlitz, etc.)\n//\n// Uses createRequire for ESM compatibility — __dirname and require() don't\n// exist in ESM modules.\ntype NativeTransformFn = (code: string, filename: string, ssr: boolean, knownSignals: string[] | null) => TransformResult\nlet nativeTransformJsx: NativeTransformFn | null = null\n\ntry {\n const __filename = fileURLToPath(import.meta.url)\n const __dirname = dirname(__filename)\n const nativeRequire = createRequire(import.meta.url)\n const nativePath = join(__dirname, '..', 'native', 'pyreon-compiler.node')\n const native = nativeRequire(nativePath) as { transformJsx: NativeTransformFn }\n nativeTransformJsx = native.transformJsx\n} catch {\n // Native binary not available — JS fallback will be used\n}\n\nexport interface CompilerWarning {\n /** Warning message */\n message: string\n /** Source file line number (1-based) */\n line: number\n /** Source file column number (0-based) */\n column: number\n /** Warning code for filtering */\n code:\n | 'signal-call-in-jsx'\n | 'missing-key-on-for'\n | 'signal-in-static-prop'\n | 'circular-prop-derived'\n}\n\nexport interface TransformResult {\n /** Transformed source code (JSX preserved, only expression containers modified) */\n code: string\n /** Whether the output uses _tpl/_re template helpers (needs auto-import) */\n usesTemplates?: boolean\n /** Compiler warnings for common mistakes */\n warnings: CompilerWarning[]\n}\n\n// Props that should never be wrapped in a reactive getter\nconst SKIP_PROPS = new Set(['key', 'ref'])\n// Event handler pattern: onClick, onInput, onMouseEnter, …\nconst EVENT_RE = /^on[A-Z]/\n// Events delegated to the container — must match runtime DELEGATED_EVENTS set\nconst DELEGATED_EVENTS = new Set([\n 'click', 'dblclick', 'contextmenu', 'focusin', 'focusout', 'input',\n 'change', 'keydown', 'keyup', 'mousedown', 'mouseup', 'mousemove',\n 'mouseover', 'mouseout', 'pointerdown', 'pointerup', 'pointermove',\n 'pointerover', 'pointerout', 'touchstart', 'touchend', 'touchmove',\n 'submit',\n])\n\nexport interface TransformOptions {\n /**\n * Compile for server-side rendering. When true, the compiler skips the\n * `_tpl()` template optimization and falls back to plain `h()` calls so\n * `@pyreon/runtime-server` can walk the VNode tree. Default: false.\n */\n ssr?: boolean\n\n /**\n * Known signal variable names from resolved imports.\n * The Vite plugin maintains a cross-module signal export registry and\n * passes imported signal names here so the compiler can auto-call them\n * in JSX even though the `signal()` declaration is in another file.\n *\n * @example\n * // store.ts: export const count = signal(0)\n * // component.tsx: import { count } from './store'\n * transformJSX(code, 'component.tsx', { knownSignals: ['count'] })\n * // {count} in JSX → {() => count()}\n */\n knownSignals?: string[]\n}\n\n// ─── oxc ESTree helpers ───────────────────────────────────────────────────────\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype N = any // ESTree node — untyped for speed, matches the lint package approach\n\nfunction getLang(filename: string): 'tsx' | 'jsx' {\n if (filename.endsWith('.jsx')) return 'jsx'\n // Default to tsx so JSX is always parsed — matches the original TypeScript\n // parser behavior which forced ScriptKind.TSX for all files.\n return 'tsx'\n}\n\n/** Binary search for line/column from byte offset. */\nfunction makeLineIndex(code: string): (offset: number) => { line: number; column: number } {\n const lineStarts = [0]\n for (let i = 0; i < code.length; i++) {\n if (code[i] === '\\n') lineStarts.push(i + 1)\n }\n return (offset: number) => {\n let lo = 0\n let hi = lineStarts.length - 1\n while (lo <= hi) {\n const mid = (lo + hi) >>> 1\n if (lineStarts[mid]! <= offset) lo = mid + 1\n else hi = mid - 1\n }\n return { line: lo, column: offset - lineStarts[lo - 1]! }\n }\n}\n\n/** Iterate all direct children of an ESTree node via known property keys. */\nfunction forEachChild(node: N, cb: (child: N) => void): void {\n if (!node || typeof node !== 'object') return\n const keys = Object.keys(node)\n for (let i = 0; i < keys.length; i++) {\n const key = keys[i]!\n // Skip metadata fields for speed\n if (key === 'type' || key === 'start' || key === 'end' || key === 'loc' || key === 'range') continue\n const val = node[key]\n if (Array.isArray(val)) {\n for (let j = 0; j < val.length; j++) {\n const item = val[j]\n if (item && typeof item === 'object' && item.type) cb(item)\n }\n } else if (val && typeof val === 'object' && val.type) {\n cb(val)\n }\n }\n}\n\n// ─── JSX element helpers ────────────────────────────────────────────────────\n\nfunction jsxTagName(node: N): string {\n const opening = node.openingElement\n if (!opening) return ''\n const name = opening.name\n return name?.type === 'JSXIdentifier' ? name.name : ''\n}\n\nfunction isSelfClosing(node: N): boolean {\n return node.type === 'JSXElement' && node.openingElement?.selfClosing === true\n}\n\nfunction jsxAttrs(node: N): N[] {\n return node.openingElement?.attributes ?? []\n}\n\nfunction jsxChildren(node: N): N[] {\n return node.children ?? []\n}\n\n// ─── Main transform ─────────────────────────────────────────────────────────\n\nexport function transformJSX(\n code: string,\n filename = 'input.tsx',\n options: TransformOptions = {},\n): TransformResult {\n // Try Rust native binary first (3.7-8.2x faster).\n // Per-call try/catch: if the native binary panics on an edge case\n // (bad UTF-8, unexpected AST shape), fall back gracefully instead\n // of crashing the Vite dev server.\n if (nativeTransformJsx) {\n try {\n return nativeTransformJsx(code, filename, options.ssr === true, options.knownSignals ?? null)\n } catch {\n // Native transform failed — fall through to JS implementation\n }\n }\n return transformJSX_JS(code, filename, options)\n}\n\n/** JS fallback implementation — used when the native binary isn't available. */\nexport function transformJSX_JS(\n code: string,\n filename = 'input.tsx',\n options: TransformOptions = {},\n): TransformResult {\n const ssr = options.ssr === true\n\n let program: N\n try {\n const result = parseSync(filename, code, {\n sourceType: 'module',\n lang: getLang(filename),\n })\n program = result.program\n } catch {\n return { code, warnings: [] }\n }\n\n const locate = makeLineIndex(code)\n\n type Replacement = { start: number; end: number; text: string }\n const replacements: Replacement[] = []\n const warnings: CompilerWarning[] = []\n\n function warn(node: N, message: string, warnCode: CompilerWarning['code']): void {\n const { line, column } = locate(node.start as number)\n warnings.push({ message, line, column, code: warnCode })\n }\n\n // ── Parent + children maps (built once, eliminates repeated Object.keys) ──\n const parentMap = new WeakMap<object, N>()\n const childrenMap = new WeakMap<object, N[]>()\n\n /** Build parent pointers + cached children arrays for the entire AST. */\n function buildMaps(node: N): void {\n const kids: N[] = []\n const keys = Object.keys(node)\n for (let i = 0; i < keys.length; i++) {\n const key = keys[i]!\n if (key === 'type' || key === 'start' || key === 'end' || key === 'loc' || key === 'range') continue\n const val = node[key]\n if (Array.isArray(val)) {\n for (let j = 0; j < val.length; j++) {\n const item = val[j]\n if (item && typeof item === 'object' && item.type) kids.push(item)\n }\n } else if (val && typeof val === 'object' && val.type) {\n kids.push(val)\n }\n }\n childrenMap.set(node, kids)\n for (let i = 0; i < kids.length; i++) {\n parentMap.set(kids[i]!, node)\n buildMaps(kids[i]!)\n }\n }\n buildMaps(program)\n\n function findParent(node: N): N | undefined {\n return parentMap.get(node)\n }\n\n /** Fast child iteration using pre-computed children array. */\n function forEachChildFast(node: N, cb: (child: N) => void): void {\n const kids = childrenMap.get(node)\n if (!kids) return\n for (let i = 0; i < kids.length; i++) cb(kids[i]!)\n }\n\n // ── Static hoisting state ─────────────────────────────────────────────────\n type Hoist = { name: string; text: string }\n const hoists: Hoist[] = []\n let hoistIdx = 0\n let needsTplImport = false\n let needsRpImport = false\n let needsBindTextImportGlobal = false\n let needsBindDirectImportGlobal = false\n let needsBindImportGlobal = false\n let needsApplyPropsImportGlobal = false\n let needsMountSlotImportGlobal = false\n\n function maybeHoist(node: N): string | null {\n if (\n (node.type === 'JSXElement' || node.type === 'JSXFragment') &&\n isStaticJSXNode(node)\n ) {\n const name = `_$h${hoistIdx++}`\n const text = code.slice(node.start as number, node.end as number)\n hoists.push({ name, text })\n return name\n }\n return null\n }\n\n function wrap(expr: N): void {\n const start = expr.start as number\n const end = expr.end as number\n const sliced = sliceExpr(expr)\n const text = expr.type === 'ObjectExpression'\n ? `() => (${sliced})`\n : `() => ${sliced}`\n replacements.push({ start, end, text })\n }\n\n function hoistOrWrap(expr: N): void {\n const hoistName = maybeHoist(expr)\n if (hoistName) {\n replacements.push({ start: expr.start as number, end: expr.end as number, text: hoistName })\n } else if (shouldWrap(expr)) {\n wrap(expr)\n }\n }\n\n // ── Template emit ─────────────────────────────────────────────────────────\n\n function tryTemplateEmit(node: N): boolean {\n if (ssr) return false\n if (isSelfClosing(node)) return false\n const elemCount = templateElementCount(node, true)\n if (elemCount < 1) return false\n const tplCall = buildTemplateCall(node)\n if (!tplCall) return false\n const start = node.start as number\n const end = node.end as number\n const parent = findParent(node)\n const needsBraces = parent && (parent.type === 'JSXElement' || parent.type === 'JSXFragment')\n replacements.push({ start, end, text: needsBraces ? `{${tplCall}}` : tplCall })\n needsTplImport = true\n return true\n }\n\n function checkForWarnings(node: N): void {\n const tagName = jsxTagName(node)\n if (tagName !== 'For') return\n const hasBy = jsxAttrs(node).some(\n (p: N) => p.type === 'JSXAttribute' && p.name?.type === 'JSXIdentifier' && p.name.name === 'by',\n )\n if (!hasBy) {\n warn(\n node.openingElement?.name ?? node,\n `<For> without a \"by\" prop will use index-based diffing, which is slower and may cause bugs with stateful children. Add by={(item) => item.id} for efficient keyed reconciliation.`,\n 'missing-key-on-for',\n )\n }\n }\n\n function handleJsxAttribute(node: N, parentElement: N): void {\n const name = node.name?.type === 'JSXIdentifier' ? node.name.name : ''\n if (SKIP_PROPS.has(name) || EVENT_RE.test(name)) return\n if (!node.value || node.value.type !== 'JSXExpressionContainer') return\n const expr = node.value.expression\n if (!expr || expr.type === 'JSXEmptyExpression') return\n\n const tagName = jsxTagName(parentElement)\n const isComponent = tagName.length > 0 && tagName.charAt(0) !== tagName.charAt(0).toLowerCase()\n\n if (isComponent) {\n const isSingleJsx = expr.type === 'JSXElement' || expr.type === 'JSXFragment'\n if (isSingleJsx) {\n walkNode(expr)\n return\n }\n const hoistName = maybeHoist(expr)\n if (hoistName) {\n replacements.push({ start: expr.start as number, end: expr.end as number, text: hoistName })\n } else if (shouldWrap(expr)) {\n const start = expr.start as number\n const end = expr.end as number\n const sliced = sliceExpr(expr)\n const inner = expr.type === 'ObjectExpression' ? `(${sliced})` : sliced\n replacements.push({ start, end, text: `_rp(() => ${inner})` })\n needsRpImport = true\n }\n } else {\n hoistOrWrap(expr)\n }\n }\n\n function handleJsxExpression(node: N): void {\n const expr = node.expression\n if (!expr || expr.type === 'JSXEmptyExpression') return\n const hoistName = maybeHoist(expr)\n if (hoistName) {\n replacements.push({ start: expr.start as number, end: expr.end as number, text: hoistName })\n return\n }\n if (shouldWrap(expr)) {\n wrap(expr)\n return\n }\n walkNode(expr)\n }\n\n // ── Prop-derived variable tracking (collected during the single walk) ─────\n const propsNames = new Set<string>()\n const propDerivedVars = new Map<string, { start: number; end: number }>()\n\n // ── Signal variable tracking (for auto-call in JSX) ──────────────────────\n // Tracks `const x = signal(...)` declarations. In JSX expressions, bare\n // references to these identifiers are auto-called: `{x}` → `{x()}`.\n // This makes signals look like plain JS variables in templates while\n // maintaining fine-grained reactivity.\n const signalVars = new Set<string>(options.knownSignals)\n\n // ── Scope-aware signal shadowing ──────────────────────────────────────────\n // When a function/block declares a variable with the same name as a signal\n // (e.g. `const show = 'text'` shadowing module-scope `const show = signal(false)`),\n // that name is NOT a signal within that scope. The shadowedSignals set tracks\n // names that are currently shadowed by a closer non-signal declaration.\n const shadowedSignals = new Set<string>()\n\n /** Check if an identifier name is an active (non-shadowed) signal variable. */\n function isActiveSignal(name: string): boolean {\n return signalVars.has(name) && !shadowedSignals.has(name)\n }\n\n /** Find variable declarations and parameters in a function that shadow signal names. */\n function findShadowingNames(node: N): string[] {\n const shadows: string[] = []\n // Check function parameters\n for (const param of node.params ?? []) {\n if (param.type === 'Identifier' && signalVars.has(param.name)) {\n shadows.push(param.name)\n }\n // Handle destructured parameters: ({ name }) => ...\n if (param.type === 'ObjectPattern') {\n for (const prop of param.properties ?? []) {\n const val = prop.value ?? prop.key\n if (val?.type === 'Identifier' && signalVars.has(val.name)) {\n shadows.push(val.name)\n }\n }\n }\n // Handle array destructured parameters: ([a, b]) => ...\n if (param.type === 'ArrayPattern') {\n for (const el of param.elements ?? []) {\n if (el?.type === 'Identifier' && signalVars.has(el.name)) {\n shadows.push(el.name)\n }\n }\n }\n }\n // Check top-level variable declarations in the function body\n const body = node.body\n const stmts = body?.body ?? body?.statements\n if (!Array.isArray(stmts)) return shadows\n for (const stmt of stmts) {\n if (stmt.type === 'VariableDeclaration') {\n for (const decl of stmt.declarations ?? []) {\n if (decl.id?.type === 'Identifier' && signalVars.has(decl.id.name)) {\n // Only shadow if it's NOT a signal() call\n if (!decl.init || !isSignalCall(decl.init)) {\n shadows.push(decl.id.name)\n }\n }\n }\n }\n }\n return shadows\n }\n\n function readsFromProps(node: N): boolean {\n if (node.type === 'MemberExpression' && node.object?.type === 'Identifier') {\n if (propsNames.has(node.object.name)) return true\n }\n let found = false\n forEachChildFast(node, (child) => {\n if (found) return\n if (readsFromProps(child)) found = true\n })\n return found\n }\n\n /** Check if an expression references any prop-derived variable. */\n function referencesPropDerived(node: N): boolean {\n if (node.type === 'Identifier' && propDerivedVars.has(node.name)) {\n const p = findParent(node)\n if (p && p.type === 'MemberExpression' && p.property === node && !p.computed) return false\n return true\n }\n let found = false\n forEachChildFast(node, (child) => {\n if (found) return\n if (referencesPropDerived(child)) found = true\n })\n return found\n }\n\n /** Collect prop-derived variable info from a VariableDeclaration node.\n * Called inline during the single-pass walk when we encounter a declaration. */\n function collectPropDerivedFromDecl(node: N, callbackDepth: number): void {\n if (node.type !== 'VariableDeclaration') return\n for (const decl of node.declarations ?? []) {\n // splitProps: const [own, rest] = splitProps(props, [...])\n if (decl.id?.type === 'ArrayPattern' && decl.init?.type === 'CallExpression') {\n const callee = decl.init.callee\n if (callee?.type === 'Identifier' && callee.name === 'splitProps') {\n for (const el of decl.id.elements ?? []) {\n if (el?.type === 'Identifier') propsNames.add(el.name)\n }\n }\n }\n if (node.kind !== 'const') continue\n if (callbackDepth > 0) continue\n if (decl.id?.type === 'Identifier' && decl.init) {\n if (isStatefulCall(decl.init)) {\n // Track signal() declarations for auto-call in JSX\n if (isSignalCall(decl.init)) signalVars.add(decl.id.name)\n continue\n }\n // Direct prop read OR transitive (references another prop-derived var)\n if (readsFromProps(decl.init) || referencesPropDerived(decl.init)) {\n propDerivedVars.set(decl.id.name, { start: decl.init.start as number, end: decl.init.end as number })\n }\n }\n }\n }\n\n /** Detect component functions and register their first param as a props name.\n * Called inline during the walk when entering a function. */\n function maybeRegisterComponentProps(node: N): void {\n if (\n (node.type === 'FunctionDeclaration' || node.type === 'ArrowFunctionExpression' || node.type === 'FunctionExpression') &&\n (node.params?.length ?? 0) > 0\n ) {\n const parent = findParent(node)\n // Skip callback functions (arguments to calls like .map, .filter)\n if (parent && parent.type === 'CallExpression' && (parent.arguments ?? []).includes(node)) return\n const firstParam = node.params[0]\n if (firstParam?.type === 'Identifier') {\n let hasJSX = false\n function checkJSX(n: N): void {\n if (hasJSX) return\n if (n.type === 'JSXElement' || n.type === 'JSXFragment') { hasJSX = true; return }\n forEachChildFast(n, checkJSX)\n }\n forEachChildFast(node, checkJSX)\n if (hasJSX) propsNames.add(firstParam.name)\n }\n }\n }\n\n // ── String-based transitive resolution ─────────────────────────────────────\n const resolvedCache = new Map<string, string>()\n const resolving = new Set<string>()\n const warnedCycles = new Set<string>()\n\n function resolveVarToString(varName: string, sourceNode?: N): string {\n if (resolvedCache.has(varName)) return resolvedCache.get(varName)!\n if (resolving.has(varName)) {\n const cycleKey = [...resolving, varName].sort().join(',')\n if (!warnedCycles.has(cycleKey)) {\n warnedCycles.add(cycleKey)\n const chain = [...resolving, varName].join(' → ')\n warn(\n sourceNode ?? program,\n `[Pyreon] Circular prop-derived const reference: ${chain}. ` +\n `The cyclic identifier \\`${varName}\\` will use its captured value ` +\n `instead of being reactively inlined. Break the cycle by reading ` +\n `from \\`props.*\\` directly or restructuring the derivation chain.`,\n 'circular-prop-derived',\n )\n }\n return varName\n }\n resolving.add(varName)\n const span = propDerivedVars.get(varName)!\n const rawText = code.slice(span.start, span.end)\n const resolved = resolveIdentifiersInText(rawText, span.start, sourceNode)\n resolving.delete(varName)\n resolvedCache.set(varName, resolved)\n return resolved\n }\n\n function resolveIdentifiersInText(text: string, baseOffset: number, sourceNode?: N): string {\n const endOffset = baseOffset + text.length\n const idents: { start: number; end: number; name: string }[] = []\n\n // Walk the AST to find identifiers in the span, passing parent context\n // to skip non-reference positions (property names, declarations, etc.)\n function findIdents(node: N, parent: N | null): void {\n const nodeStart = node.start as number\n const nodeEnd = node.end as number\n if (nodeStart >= endOffset || nodeEnd <= baseOffset) return\n if (node.type === 'Identifier' && propDerivedVars.has(node.name)) {\n if (parent) {\n if (parent.type === 'MemberExpression' && parent.property === node && !parent.computed) { /* skip */ }\n else if (parent.type === 'VariableDeclarator' && parent.id === node) { /* skip */ }\n else if (parent.type === 'Property' && parent.key === node && !parent.computed) { /* skip */ }\n else if (parent.type === 'Property' && parent.shorthand) { /* skip */ }\n else if (nodeStart >= baseOffset && nodeEnd <= endOffset) {\n idents.push({ start: nodeStart, end: nodeEnd, name: node.name })\n }\n } else if (nodeStart >= baseOffset && nodeEnd <= endOffset) {\n idents.push({ start: nodeStart, end: nodeEnd, name: node.name })\n }\n }\n forEachChildFast(node, (child) => findIdents(child, node))\n }\n findIdents(program, null)\n\n if (idents.length === 0) return text\n\n idents.sort((a, b) => a.start - b.start)\n const parts: string[] = []\n let lastPos = baseOffset\n for (const id of idents) {\n parts.push(code.slice(lastPos, id.start))\n parts.push(`(${resolveVarToString(id.name, sourceNode)})`)\n lastPos = id.end\n }\n parts.push(code.slice(lastPos, endOffset))\n return parts.join('')\n }\n\n // ── Analysis helpers with memoization (Phase 3) ────────────────────────────\n // Cache results keyed by node.start (unique per node in a file).\n // Eliminates redundant subtree traversals for containsCall + accessesProps.\n const _isDynamicCache = new Map<number, boolean>()\n\n /** Fused isDynamic: checks both containsCall and accessesProps in one traversal. */\n function isDynamic(node: N): boolean {\n const key = node.start as number\n const cached = _isDynamicCache.get(key)\n if (cached !== undefined) return cached\n const result = _isDynamicImpl(node)\n _isDynamicCache.set(key, result)\n return result\n }\n\n function _isDynamicImpl(node: N): boolean {\n // Call expression (non-pure)\n if (node.type === 'CallExpression') {\n if (!isPureStaticCall(node)) return true\n }\n if (node.type === 'TaggedTemplateExpression') return true\n // Props access\n if (node.type === 'MemberExpression' && !node.computed && node.object?.type === 'Identifier') {\n if (propsNames.has(node.object.name)) return true\n }\n // Prop-derived variable reference\n if (node.type === 'Identifier' && propDerivedVars.has(node.name)) {\n const parent = findParent(node)\n if (parent && parent.type === 'MemberExpression' && parent.property === node && !parent.computed) {\n // This is a property name position, not a reference — fall through\n } else {\n return true\n }\n }\n // Signal variable reference — treated as dynamic (will be auto-called)\n if (node.type === 'Identifier' && isActiveSignal(node.name)) {\n const parent = findParent(node)\n if (parent && parent.type === 'MemberExpression' && parent.property === node && !parent.computed) {\n // Property name position — not a reference\n } else if (parent && parent.type === 'CallExpression' && parent.callee === node) {\n // Already being called: signal() — don't double-flag\n } else {\n return true\n }\n }\n // Don't recurse into nested functions\n if (node.type === 'ArrowFunctionExpression' || node.type === 'FunctionExpression') return false\n // Recurse into children\n let found = false\n forEachChildFast(node, (child) => {\n if (found) return\n if (isDynamic(child)) found = true\n })\n return found\n }\n\n /** accessesProps — kept for sliceExpr's quick check (does this need resolution?) */\n function accessesProps(node: N): boolean {\n if (node.type === 'MemberExpression' && !node.computed && node.object?.type === 'Identifier') {\n if (propsNames.has(node.object.name)) return true\n }\n if (node.type === 'Identifier' && propDerivedVars.has(node.name)) {\n const parent = findParent(node)\n if (parent && parent.type === 'MemberExpression' && parent.property === node && !parent.computed) return false\n return true\n }\n let found = false\n forEachChildFast(node, (child) => {\n if (found) return\n if (child.type === 'ArrowFunctionExpression' || child.type === 'FunctionExpression') return\n if (accessesProps(child)) found = true\n })\n return found\n }\n\n function shouldWrap(node: N): boolean {\n if (node.type === 'ArrowFunctionExpression' || node.type === 'FunctionExpression') return false\n if (isStatic(node)) return false\n if (node.type === 'CallExpression' && isPureStaticCall(node)) return false\n return isDynamic(node)\n }\n\n // ── Single unified walk (Phase 2) ─────────────────────────────────────────\n // Merges the old 3-pass architecture (scanForPropDerivedVars + transitive\n // resolution + JSX walk) into one top-down traversal. Works because `const`\n // declarations have a temporal dead zone — they're always before their use.\n let _callbackDepth = 0\n\n function walkNode(node: N): void {\n // ── Component function detection (was pass 1) ──\n const isFunction = node.type === 'FunctionDeclaration' || node.type === 'ArrowFunctionExpression' || node.type === 'FunctionExpression'\n let scopeShadows: string[] | null = null\n if (isFunction) {\n // Track callback nesting for prop-derived var exclusion\n const parent = findParent(node)\n const isCallbackArg = parent && parent.type === 'CallExpression' && (parent.arguments ?? []).includes(node)\n if (isCallbackArg) _callbackDepth++\n // Register component props (only for non-callback functions with JSX)\n maybeRegisterComponentProps(node)\n // Track signal name shadowing for scope awareness\n if (signalVars.size > 0) {\n scopeShadows = findShadowingNames(node)\n for (const name of scopeShadows) shadowedSignals.add(name)\n }\n }\n\n // ── Variable declaration collection (was pass 1 + 2) ──\n if (node.type === 'VariableDeclaration') {\n collectPropDerivedFromDecl(node, _callbackDepth)\n }\n\n // ── JSX processing (was pass 3) ──\n if (node.type === 'JSXElement') {\n if (!isSelfClosing(node) && tryTemplateEmit(node)) {\n // Template emitted — don't recurse into this subtree (JSXElement is never a function)\n return\n }\n checkForWarnings(node)\n for (const attr of jsxAttrs(node)) {\n if (attr.type === 'JSXAttribute') handleJsxAttribute(attr, node)\n }\n for (const child of jsxChildren(node)) {\n if (child.type === 'JSXExpressionContainer') handleJsxExpression(child)\n else walkNode(child)\n }\n // Note: JSXElement is never a function, so no callback depth or scope cleanup needed here\n return\n }\n if (node.type === 'JSXExpressionContainer') {\n handleJsxExpression(node)\n // Note: JSXExpressionContainer is never a function, no scope cleanup needed\n return\n }\n\n // Generic descent\n forEachChildFast(node, walkNode)\n\n // Restore callback depth after leaving function\n if (isFunction) {\n const parent = findParent(node)\n if (parent && parent.type === 'CallExpression' && (parent.arguments ?? []).includes(node)) _callbackDepth--\n }\n // Restore signal shadowing\n if (scopeShadows) for (const name of scopeShadows) shadowedSignals.delete(name)\n }\n\n walkNode(program)\n\n if (replacements.length === 0 && hoists.length === 0) return { code, warnings }\n\n replacements.sort((a, b) => a.start - b.start)\n const parts: string[] = []\n let lastPos = 0\n for (const r of replacements) {\n parts.push(code.slice(lastPos, r.start))\n parts.push(r.text)\n lastPos = r.end\n }\n parts.push(code.slice(lastPos))\n let result = parts.join('')\n\n if (hoists.length > 0) {\n const preamble = hoists.map((h) => `const ${h.name} = /*@__PURE__*/ ${h.text}\\n`).join('')\n result = preamble + result\n }\n\n if (needsTplImport) {\n const runtimeDomImports = ['_tpl']\n if (needsBindDirectImportGlobal) runtimeDomImports.push('_bindDirect')\n if (needsBindTextImportGlobal) runtimeDomImports.push('_bindText')\n if (needsApplyPropsImportGlobal) runtimeDomImports.push('_applyProps')\n if (needsMountSlotImportGlobal) runtimeDomImports.push('_mountSlot')\n const reactivityImports = needsBindImportGlobal\n ? `\\nimport { _bind } from \"@pyreon/reactivity\";`\n : ''\n result =\n `import { ${runtimeDomImports.join(', ')} } from \"@pyreon/runtime-dom\";${reactivityImports}\\n` +\n result\n }\n\n if (needsRpImport) {\n result = `import { _rp } from \"@pyreon/core\";\\n` + result\n }\n\n return { code: result, usesTemplates: needsTplImport, warnings }\n\n // ── Template emission helpers ─────────────────────────────────────────────\n\n function hasBailAttr(node: N, isRoot = false): boolean {\n for (const attr of jsxAttrs(node)) {\n if (attr.type === 'JSXSpreadAttribute') {\n if (isRoot) continue\n return true\n }\n if (attr.type === 'JSXAttribute' && attr.name?.type === 'JSXIdentifier' && attr.name.name === 'key')\n return true\n }\n return false\n }\n\n function countChildForTemplate(child: N): number {\n if (child.type === 'JSXText') return 0\n if (child.type === 'JSXElement') return templateElementCount(child)\n if (child.type === 'JSXExpressionContainer') {\n const expr = child.expression\n if (!expr || expr.type === 'JSXEmptyExpression') return 0\n return containsJSXInExpr(expr) ? -1 : 0\n }\n if (child.type === 'JSXFragment') return templateFragmentCount(child)\n return -1\n }\n\n function templateElementCount(node: N, isRoot = false): number {\n const tag = jsxTagName(node)\n if (!tag || !isLowerCase(tag)) return -1\n if (hasBailAttr(node, isRoot)) return -1\n if (isSelfClosing(node)) return 1\n let count = 1\n for (const child of jsxChildren(node)) {\n const c = countChildForTemplate(child)\n if (c === -1) return -1\n count += c\n }\n return count\n }\n\n function templateFragmentCount(frag: N): number {\n let count = 0\n for (const child of jsxChildren(frag)) {\n const c = countChildForTemplate(child)\n if (c === -1) return -1\n count += c\n }\n return count\n }\n\n function buildTemplateCall(node: N): string | null {\n const bindLines: string[] = []\n const disposerNames: string[] = []\n let varIdx = 0\n let dispIdx = 0\n const reactiveBindExprs: string[] = []\n let needsBindTextImport = false\n let needsBindDirectImport = false\n let needsApplyPropsImport = false\n let needsMountSlotImport = false\n\n function nextVar(): string { return `__e${varIdx++}` }\n function nextDisp(): string {\n const name = `__d${dispIdx++}`\n disposerNames.push(name)\n return name\n }\n function nextTextVar(): string { return `__t${varIdx++}` }\n\n function resolveElementVar(accessor: string, hasDynamic: boolean): string {\n if (accessor === '__root') return '__root'\n if (hasDynamic) {\n const v = nextVar()\n bindLines.push(`const ${v} = ${accessor}`)\n return v\n }\n return accessor\n }\n\n function emitRef(attr: N, varName: string): void {\n if (!attr.value || attr.value.type !== 'JSXExpressionContainer') return\n const expr = attr.value.expression\n if (!expr || expr.type === 'JSXEmptyExpression') return\n if (expr.type === 'ArrowFunctionExpression' || expr.type === 'FunctionExpression') {\n bindLines.push(`(${sliceExpr(expr)})(${varName})`)\n } else {\n bindLines.push(\n `{ const __r = ${sliceExpr(expr)}; if (typeof __r === \"function\") __r(${varName}); else if (__r) __r.current = ${varName} }`,\n )\n }\n }\n\n function emitEventListener(attr: N, attrName: string, varName: string): void {\n const eventName = (attrName[2] ?? '').toLowerCase() + attrName.slice(3)\n if (!attr.value || attr.value.type !== 'JSXExpressionContainer') return\n const expr = attr.value.expression\n if (!expr || expr.type === 'JSXEmptyExpression') return\n const handler = sliceExpr(expr)\n if (DELEGATED_EVENTS.has(eventName)) {\n bindLines.push(`${varName}.__ev_${eventName} = ${handler}`)\n } else {\n bindLines.push(`${varName}.addEventListener(\"${eventName}\", ${handler})`)\n }\n }\n\n function staticAttrToHtml(exprNode: N, htmlAttrName: string): string | null {\n if (!isStatic(exprNode)) return null\n // String literal\n if ((exprNode.type === 'Literal' || exprNode.type === 'StringLiteral') && typeof exprNode.value === 'string')\n return ` ${htmlAttrName}=\"${escapeHtmlAttr(exprNode.value)}\"`\n // Numeric literal\n if ((exprNode.type === 'Literal' || exprNode.type === 'NumericLiteral') && typeof exprNode.value === 'number')\n return ` ${htmlAttrName}=\"${exprNode.value}\"`\n // Boolean true\n if ((exprNode.type === 'Literal' || exprNode.type === 'BooleanLiteral') && exprNode.value === true)\n return ` ${htmlAttrName}`\n return '' // false/null/undefined → omit\n }\n\n function tryDirectSignalRef(exprNode: N): string | null {\n let inner = exprNode\n if (inner.type === 'ArrowFunctionExpression' && inner.body?.type !== 'BlockStatement') {\n inner = inner.body\n }\n if (inner.type !== 'CallExpression') return null\n if ((inner.arguments?.length ?? 0) > 0) return null\n const callee = inner.callee\n if (callee?.type === 'Identifier') return sliceExpr(callee)\n return null\n }\n\n function unwrapAccessor(exprNode: N): { expr: string; isReactive: boolean } {\n if (exprNode.type === 'ArrowFunctionExpression' && exprNode.body?.type !== 'BlockStatement') {\n return { expr: sliceExpr(exprNode.body), isReactive: true }\n }\n if (exprNode.type === 'ArrowFunctionExpression' || exprNode.type === 'FunctionExpression') {\n return { expr: `(${sliceExpr(exprNode)})()`, isReactive: true }\n }\n return { expr: sliceExpr(exprNode), isReactive: isDynamic(exprNode) }\n }\n\n function attrSetter(htmlAttrName: string, varName: string, expr: string): string {\n if (htmlAttrName === 'class') return `${varName}.className = ${expr}`\n if (htmlAttrName === 'style') return `${varName}.style.cssText = ${expr}`\n return `${varName}.setAttribute(\"${htmlAttrName}\", ${expr})`\n }\n\n function emitDynamicAttr(_expr: string, exprNode: N, htmlAttrName: string, varName: string): void {\n const { expr, isReactive } = unwrapAccessor(exprNode)\n if (!isReactive) {\n bindLines.push(attrSetter(htmlAttrName, varName, expr))\n return\n }\n const directRef = tryDirectSignalRef(exprNode)\n if (directRef) {\n needsBindDirectImport = true\n const d = nextDisp()\n const updater =\n htmlAttrName === 'class'\n ? `(v) => { ${varName}.className = v == null ? \"\" : String(v) }`\n : htmlAttrName === 'style'\n ? `(v) => { if (typeof v === \"string\") ${varName}.style.cssText = v; else if (v) Object.assign(${varName}.style, v) }`\n : `(v) => { ${varName}.setAttribute(\"${htmlAttrName}\", v == null ? \"\" : String(v)) }`\n bindLines.push(`const ${d} = _bindDirect(${directRef}, ${updater})`)\n return\n }\n reactiveBindExprs.push(attrSetter(htmlAttrName, varName, expr))\n }\n\n function emitAttrExpression(exprNode: N, htmlAttrName: string, varName: string): string {\n const staticHtml = staticAttrToHtml(exprNode, htmlAttrName)\n if (staticHtml !== null) return staticHtml\n if (htmlAttrName === 'style' && exprNode.type === 'ObjectExpression') {\n bindLines.push(`Object.assign(${varName}.style, ${sliceExpr(exprNode)})`)\n return ''\n }\n emitDynamicAttr(sliceExpr(exprNode), exprNode, htmlAttrName, varName)\n return ''\n }\n\n function tryEmitSpecialAttr(attr: N, attrName: string, varName: string): boolean {\n if (attrName === 'ref') { emitRef(attr, varName); return true }\n if (EVENT_RE.test(attrName)) { emitEventListener(attr, attrName, varName); return true }\n return false\n }\n\n function attrInitializerToHtml(attr: N, htmlAttrName: string, varName: string): string {\n if (!attr.value) return ` ${htmlAttrName}`\n // JSX string attribute: class=\"foo\"\n if (attr.value.type === 'StringLiteral' || (attr.value.type === 'Literal' && typeof attr.value.value === 'string'))\n return ` ${htmlAttrName}=\"${escapeHtmlAttr(attr.value.value)}\"`\n if (attr.value.type === 'JSXExpressionContainer') {\n const expr = attr.value.expression\n if (expr && expr.type !== 'JSXEmptyExpression') return emitAttrExpression(expr, htmlAttrName, varName)\n }\n return ''\n }\n\n function processOneAttr(attr: N, varName: string): string {\n if (attr.type === 'JSXSpreadAttribute') {\n const expr = sliceExpr(attr.argument)\n needsApplyPropsImport = true\n if (isDynamic(attr.argument)) {\n reactiveBindExprs.push(`_applyProps(${varName}, ${expr})`)\n } else {\n bindLines.push(`_applyProps(${varName}, ${expr})`)\n }\n return ''\n }\n if (attr.type !== 'JSXAttribute') return ''\n const attrName = attr.name?.type === 'JSXIdentifier' ? attr.name.name : ''\n if (attrName === 'key') return ''\n if (tryEmitSpecialAttr(attr, attrName, varName)) return ''\n return attrInitializerToHtml(attr, JSX_TO_HTML_ATTR[attrName] ?? attrName, varName)\n }\n\n function processAttrs(el: N, varName: string): string {\n let htmlAttrs = ''\n for (const attr of jsxAttrs(el)) htmlAttrs += processOneAttr(attr, varName)\n return htmlAttrs\n }\n\n function emitReactiveTextChild(\n expr: string, exprNode: N, varName: string,\n parentRef: string, childNodeIdx: number, needsPlaceholder: boolean,\n ): string {\n const tVar = nextTextVar()\n bindLines.push(`const ${tVar} = document.createTextNode(\"\")`)\n if (needsPlaceholder) {\n bindLines.push(`${parentRef}.replaceChild(${tVar}, ${parentRef}.childNodes[${childNodeIdx}])`)\n } else {\n bindLines.push(`${varName}.appendChild(${tVar})`)\n }\n const directRef = tryDirectSignalRef(exprNode)\n if (directRef) {\n needsBindTextImport = true\n const d = nextDisp()\n bindLines.push(`const ${d} = _bindText(${directRef}, ${tVar})`)\n } else {\n needsBindImportGlobal = true\n const d = nextDisp()\n bindLines.push(`const ${d} = _bind(() => { ${tVar}.data = ${expr} })`)\n }\n return needsPlaceholder ? '<!>' : ''\n }\n\n function emitStaticTextChild(\n expr: string, varName: string,\n parentRef: string, childNodeIdx: number, needsPlaceholder: boolean,\n ): string {\n if (needsPlaceholder) {\n const tVar = nextTextVar()\n bindLines.push(`const ${tVar} = document.createTextNode(${expr})`)\n bindLines.push(`${parentRef}.replaceChild(${tVar}, ${parentRef}.childNodes[${childNodeIdx}])`)\n return '<!>'\n }\n bindLines.push(`${varName}.textContent = ${expr}`)\n return ''\n }\n\n type FlatChild =\n | { kind: 'text'; text: string }\n | { kind: 'element'; node: N; elemIdx: number }\n | { kind: 'expression'; expression: N }\n\n function classifyJsxChild(\n child: N, out: FlatChild[],\n elemIdxRef: { value: number },\n recurse: (kids: N[]) => void,\n ): void {\n if (child.type === 'JSXText') {\n const raw = child.value ?? child.raw ?? ''\n const trimmed = raw.replace(/\\n\\s*/g, '').trim()\n if (trimmed) out.push({ kind: 'text', text: trimmed })\n return\n }\n if (child.type === 'JSXElement') {\n out.push({ kind: 'element', node: child, elemIdx: elemIdxRef.value++ })\n return\n }\n if (child.type === 'JSXExpressionContainer') {\n const expr = child.expression\n if (expr && expr.type !== 'JSXEmptyExpression') out.push({ kind: 'expression', expression: expr })\n return\n }\n if (child.type === 'JSXFragment') recurse(jsxChildren(child))\n }\n\n function flattenChildren(children: N[]): FlatChild[] {\n const flatList: FlatChild[] = []\n const elemIdxRef = { value: 0 }\n function addChildren(kids: N[]): void {\n for (const child of kids) classifyJsxChild(child, flatList, elemIdxRef, addChildren)\n }\n addChildren(children)\n return flatList\n }\n\n function analyzeChildren(flatChildren: FlatChild[]): { useMixed: boolean; useMultiExpr: boolean } {\n const hasElem = flatChildren.some((c) => c.kind === 'element')\n const hasNonElem = flatChildren.some((c) => c.kind !== 'element')\n const exprCount = flatChildren.filter((c) => c.kind === 'expression').length\n return { useMixed: hasElem && hasNonElem, useMultiExpr: exprCount > 1 }\n }\n\n function attrIsDynamic(attr: N): boolean {\n if (attr.type !== 'JSXAttribute') return false\n const name = attr.name?.type === 'JSXIdentifier' ? attr.name.name : ''\n if (name === 'ref') return true\n if (EVENT_RE.test(name)) return true\n if (!attr.value || attr.value.type !== 'JSXExpressionContainer') return false\n const expr = attr.value.expression\n return expr && expr.type !== 'JSXEmptyExpression' ? !isStatic(expr) : false\n }\n\n function elementHasDynamic(node: N): boolean {\n if (jsxAttrs(node).some(attrIsDynamic)) return true\n if (!isSelfClosing(node)) {\n return jsxChildren(node).some((c: N) =>\n c.type === 'JSXExpressionContainer' && c.expression && c.expression.type !== 'JSXEmptyExpression',\n )\n }\n return false\n }\n\n function processOneChild(\n child: FlatChild, varName: string, parentRef: string,\n useMixed: boolean, useMultiExpr: boolean, childNodeIdx: number,\n ): string | null {\n if (child.kind === 'text') return escapeHtmlText(child.text)\n if (child.kind === 'element') {\n const childAccessor = useMixed\n ? `${parentRef}.childNodes[${childNodeIdx}]`\n : `${parentRef}.children[${child.elemIdx}]`\n return processElement(child.node, childAccessor)\n }\n const needsPlaceholder = useMixed || useMultiExpr\n const { expr, isReactive } = unwrapAccessor(child.expression)\n if (isChildrenExpression(child.expression, expr)) {\n needsMountSlotImport = true\n const placeholder = `${parentRef}.childNodes[${childNodeIdx}]`\n const d = nextDisp()\n bindLines.push(`const ${d} = _mountSlot(${expr}, ${parentRef}, ${placeholder})`)\n return '<!>'\n }\n if (isReactive) {\n return emitReactiveTextChild(expr, child.expression, varName, parentRef, childNodeIdx, needsPlaceholder)\n }\n return emitStaticTextChild(expr, varName, parentRef, childNodeIdx, needsPlaceholder)\n }\n\n function processChildren(el: N, varName: string, accessor: string): string | null {\n const flatChildren = flattenChildren(jsxChildren(el))\n const { useMixed, useMultiExpr } = analyzeChildren(flatChildren)\n const parentRef = accessor === '__root' ? '__root' : varName\n let html = ''\n let childNodeIdx = 0\n for (const child of flatChildren) {\n const childHtml = processOneChild(child, varName, parentRef, useMixed, useMultiExpr, childNodeIdx)\n if (childHtml === null) return null\n html += childHtml\n childNodeIdx++\n }\n return html\n }\n\n function processElement(el: N, accessor: string): string | null {\n const tag = jsxTagName(el)\n if (!tag) return null\n const varName = resolveElementVar(accessor, elementHasDynamic(el))\n const htmlAttrs = processAttrs(el, varName)\n let html = `<${tag}${htmlAttrs}>`\n if (!isSelfClosing(el)) {\n const childHtml = processChildren(el, varName, accessor)\n if (childHtml === null) return null\n html += childHtml\n }\n if (!VOID_ELEMENTS.has(tag)) html += `</${tag}>`\n return html\n }\n\n const html = processElement(node, '__root')\n if (html === null) return null\n\n if (needsBindTextImport) needsBindTextImportGlobal = true\n if (needsBindDirectImport) needsBindDirectImportGlobal = true\n if (needsApplyPropsImport) needsApplyPropsImportGlobal = true\n if (needsMountSlotImport) needsMountSlotImportGlobal = true\n\n const escaped = html.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"')\n\n if (reactiveBindExprs.length > 0) {\n needsBindImportGlobal = true\n const combinedName = nextDisp()\n const combinedBody = reactiveBindExprs.join('; ')\n bindLines.push(`const ${combinedName} = _bind(() => { ${combinedBody} })`)\n }\n\n if (bindLines.length === 0 && disposerNames.length === 0) {\n return `_tpl(\"${escaped}\", () => null)`\n }\n\n let body = bindLines.map((l) => ` ${l}`).join('\\n')\n if (disposerNames.length > 0) {\n body += `\\n return () => { ${disposerNames.map((d) => `${d}()`).join('; ')} }`\n } else {\n body += '\\n return null'\n }\n\n return `_tpl(\"${escaped}\", (__root) => {\\n${body}\\n})`\n }\n\n function sliceExpr(expr: N): string {\n let result: string\n if (propDerivedVars.size > 0 && accessesProps(expr)) {\n const start = expr.start as number\n const end = expr.end as number\n result = resolveIdentifiersInText(code.slice(start, end), start, expr)\n } else {\n result = code.slice(expr.start as number, expr.end as number)\n }\n\n // Auto-call signal variables: replace bare `x` with `x()` in the expression.\n // Only applies to identifiers that are NOT already being called (not `x()`).\n if (signalVars.size > 0 && signalVars.size > shadowedSignals.size && referencesSignalVar(expr)) {\n result = autoCallSignals(result, expr)\n }\n\n return result\n }\n\n /** Check if an expression references any tracked signal variable. */\n function referencesSignalVar(node: N): boolean {\n if (node.type === 'Identifier' && isActiveSignal(node.name)) {\n const parent = findParent(node)\n if (parent && parent.type === 'MemberExpression' && parent.property === node && !parent.computed) return false\n if (parent && parent.type === 'CallExpression' && parent.callee === node) return false // already called\n return true\n }\n let found = false\n forEachChildFast(node, (child) => {\n if (found) return\n if (child.type === 'ArrowFunctionExpression' || child.type === 'FunctionExpression') return\n if (referencesSignalVar(child)) found = true\n })\n return found\n }\n\n /** Auto-insert () after signal variable references in the expression source.\n * Uses the AST to find exact Identifier positions — never scans raw text. */\n function autoCallSignals(text: string, expr: N): string {\n const start = expr.start as number\n // Collect signal identifier positions that need auto-calling\n const idents: { start: number; end: number }[] = []\n\n function findSignalIdents(node: N): void {\n if ((node.start as number) >= start + text.length || (node.end as number) <= start) return\n if (node.type === 'Identifier' && isActiveSignal(node.name)) {\n const parent = findParent(node)\n // Skip property name positions (obj.name)\n if (parent && parent.type === 'MemberExpression' && parent.property === node && !parent.computed) return\n // Skip if already being called: signal()\n if (parent && parent.type === 'CallExpression' && parent.callee === node) return\n // Skip declaration positions\n if (parent && parent.type === 'VariableDeclarator' && parent.id === node) return\n // Skip object property keys and shorthand properties ({ name } or { name: val })\n // Inserting () after a shorthand key produces name() which is a method shorthand — invalid\n if (parent && (parent.type === 'Property' || parent.type === 'ObjectProperty')) {\n if (parent.shorthand) return // { name } — can't auto-call without breaking syntax\n if (parent.key === node && !parent.computed) return // { name: val } — key position\n }\n idents.push({ start: node.start as number, end: node.end as number })\n }\n forEachChildFast(node, findSignalIdents)\n }\n findSignalIdents(expr)\n\n if (idents.length === 0) return text\n\n // Sort by position and insert () after each identifier\n idents.sort((a, b) => a.start - b.start)\n const parts: string[] = []\n let lastPos = start\n for (const id of idents) {\n parts.push(code.slice(lastPos, id.end))\n parts.push('()') // auto-call\n lastPos = id.end\n }\n parts.push(code.slice(lastPos, start + text.length))\n return parts.join('')\n }\n}\n\n// ─── Module-scope constants and helpers ─────────────────────────────────────\n\nconst VOID_ELEMENTS = new Set([\n 'area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input',\n 'link', 'meta', 'param', 'source', 'track', 'wbr',\n])\n\nconst JSX_TO_HTML_ATTR: Record<string, string> = {\n className: 'class',\n htmlFor: 'for',\n}\n\nconst STATEFUL_CALLS = new Set([\n 'signal', 'computed', 'effect', 'batch',\n 'createContext', 'createReactiveContext',\n 'useContext', 'useRef', 'createRef',\n 'useForm', 'useQuery', 'useMutation',\n 'defineStore', 'useStore',\n])\n\nfunction isStatefulCall(node: N): boolean {\n if (node.type !== 'CallExpression') return false\n const callee = node.callee\n if (callee?.type === 'Identifier') return STATEFUL_CALLS.has(callee.name)\n return false\n}\n\n/** Check if a call expression creates a callable reactive value (`signal(...)` or `computed(...)`). */\nfunction isSignalCall(node: N): boolean {\n if (node.type !== 'CallExpression') return false\n const callee = node.callee\n return callee?.type === 'Identifier' && (callee.name === 'signal' || callee.name === 'computed')\n}\n\nfunction isChildrenExpression(node: N, expr: string): boolean {\n if (node.type === 'MemberExpression' && !node.computed && node.property?.type === 'Identifier' && node.property.name === 'children') return true\n if (node.type === 'Identifier' && node.name === 'children') return true\n if (expr.endsWith('.children') || expr === 'children') return true\n return false\n}\n\nfunction isLowerCase(s: string): boolean {\n return s.length > 0 && s[0] === s[0]?.toLowerCase()\n}\n\nfunction containsJSXInExpr(node: N): boolean {\n if (node.type === 'JSXElement' || node.type === 'JSXFragment') return true\n let found = false\n forEachChild(node, (child) => {\n if (found) return\n if (containsJSXInExpr(child)) found = true\n })\n return found\n}\n\nfunction escapeHtmlAttr(s: string): string {\n return s.replace(/&/g, '&').replace(/\"/g, '"')\n}\n\nfunction escapeHtmlText(s: string): string {\n return s.replace(/&(?!(?:#\\d+|#x[\\da-fA-F]+|[a-zA-Z]\\w*);)/g, '&').replace(/</g, '<')\n}\n\nfunction isStaticJSXNode(node: N): boolean {\n if (node.type === 'JSXElement' && node.openingElement?.selfClosing) {\n return isStaticAttrs(node.openingElement.attributes ?? [])\n }\n if (node.type === 'JSXFragment') {\n return (node.children ?? []).every(isStaticChild)\n }\n if (node.type === 'JSXElement') {\n return isStaticAttrs(node.openingElement?.attributes ?? []) && (node.children ?? []).every(isStaticChild)\n }\n return false\n}\n\nfunction isStaticAttrs(attrs: N[]): boolean {\n return attrs.every((prop: N) => {\n if (prop.type !== 'JSXAttribute') return false\n if (!prop.value) return true\n if (prop.value.type === 'StringLiteral' || (prop.value.type === 'Literal' && typeof prop.value.value === 'string')) return true\n if (prop.value.type === 'JSXExpressionContainer') {\n const expr = prop.value.expression\n if (!expr || expr.type === 'JSXEmptyExpression') return true\n return isStatic(expr)\n }\n return false\n })\n}\n\nfunction isStaticChild(child: N): boolean {\n if (child.type === 'JSXText') return true\n if (child.type === 'JSXElement') return isStaticJSXNode(child)\n if (child.type === 'JSXFragment') return isStaticJSXNode(child)\n if (child.type === 'JSXExpressionContainer') {\n const expr = child.expression\n if (!expr || expr.type === 'JSXEmptyExpression') return true\n return isStatic(expr)\n }\n return false\n}\n\nfunction isStatic(node: N): boolean {\n if (node.type === 'Literal') return true\n if (node.type === 'StringLiteral' || node.type === 'NumericLiteral' || node.type === 'BooleanLiteral' || node.type === 'NullLiteral') return true\n if (node.type === 'TemplateLiteral' && (node.expressions?.length ?? 0) === 0) return true\n // Note: `undefined` is an Identifier in ESTree, not a keyword literal.\n // It is NOT treated as static — it goes through the dynamic attr path.\n return false\n}\n\nconst PURE_CALLS = new Set([\n 'Math.max', 'Math.min', 'Math.abs', 'Math.floor', 'Math.ceil', 'Math.round',\n 'Math.pow', 'Math.sqrt', 'Math.random', 'Math.trunc', 'Math.sign',\n 'Number.parseInt', 'Number.parseFloat', 'Number.isNaN', 'Number.isFinite',\n 'parseInt', 'parseFloat', 'isNaN', 'isFinite',\n 'String.fromCharCode', 'String.fromCodePoint',\n 'Object.keys', 'Object.values', 'Object.entries', 'Object.assign',\n 'Object.freeze', 'Object.create',\n 'Array.from', 'Array.isArray', 'Array.of',\n 'JSON.stringify', 'JSON.parse',\n 'encodeURIComponent', 'decodeURIComponent', 'encodeURI', 'decodeURI',\n 'Date.now',\n])\n\nfunction isPureStaticCall(node: N): boolean {\n const callee = node.callee\n let name = ''\n if (callee?.type === 'Identifier') {\n name = callee.name\n } else if (callee?.type === 'MemberExpression' && !callee.computed && callee.object?.type === 'Identifier' && callee.property?.type === 'Identifier') {\n name = `${callee.object.name}.${callee.property.name}`\n }\n if (!PURE_CALLS.has(name)) return false\n return (node.arguments ?? []).every((arg: N) => arg.type !== 'SpreadElement' && isStatic(arg))\n}","/**\n * Project scanner — extracts route, component, and island information from source files.\n */\n\nimport * as fs from 'node:fs'\nimport * as path from 'node:path'\n\nexport interface RouteInfo {\n path: string\n name?: string | undefined\n component?: string | undefined\n hasLoader: boolean\n hasGuard: boolean\n params: string[]\n}\n\nexport interface ComponentInfo {\n name: string\n file: string\n hasSignals: boolean\n signalNames: string[]\n props: string[]\n}\n\nexport interface IslandInfo {\n name: string\n file: string\n hydrate: string\n}\n\nexport interface ProjectContext {\n framework: 'pyreon'\n version: string\n generatedAt: string\n routes: RouteInfo[]\n components: ComponentInfo[]\n islands: IslandInfo[]\n}\n\nexport function generateContext(cwd: string): ProjectContext {\n const files = collectSourceFiles(cwd)\n const version = readVersion(cwd)\n\n return {\n framework: 'pyreon',\n version,\n generatedAt: new Date().toISOString(),\n routes: extractRoutes(files, cwd),\n components: extractComponents(files, cwd),\n islands: extractIslands(files, cwd),\n }\n}\n\nfunction collectSourceFiles(cwd: string): string[] {\n const results: string[] = []\n const extensions = new Set(['.tsx', '.jsx', '.ts', '.js'])\n const ignoreDirs = new Set(['node_modules', 'dist', 'lib', '.pyreon', '.git', 'build'])\n\n function walk(dir: string): void {\n let entries: fs.Dirent[]\n try {\n entries = fs.readdirSync(dir, { withFileTypes: true })\n } catch {\n return\n }\n for (const entry of entries) {\n if (entry.name.startsWith('.') && entry.isDirectory()) continue\n if (ignoreDirs.has(entry.name) && entry.isDirectory()) continue\n const fullPath = path.join(dir, entry.name)\n if (entry.isDirectory()) {\n walk(fullPath)\n } else if (entry.isFile() && extensions.has(path.extname(entry.name))) {\n results.push(fullPath)\n }\n }\n }\n\n walk(cwd)\n return results\n}\n\nfunction extractRoutes(files: string[], _cwd: string): RouteInfo[] {\n const routes: RouteInfo[] = []\n\n for (const file of files) {\n let code: string\n try {\n code = fs.readFileSync(file, 'utf-8')\n } catch {\n continue\n }\n\n const routeArrayRe =\n /(?:createRouter\\s*\\(\\s*\\[|(?:const|let)\\s+routes\\s*(?::\\s*RouteRecord\\[\\])?\\s*=\\s*\\[)([\\s\\S]*?)\\]/g\n let match: RegExpExecArray | null\n for (match = routeArrayRe.exec(code); match; match = routeArrayRe.exec(code)) {\n const block = match[1] ?? ''\n const routeObjRe = /path\\s*:\\s*[\"']([^\"']+)[\"']/g\n let routeMatch: RegExpExecArray | null\n for (routeMatch = routeObjRe.exec(block); routeMatch; routeMatch = routeObjRe.exec(block)) {\n const routePath = routeMatch[1] ?? ''\n const surroundingStart = Math.max(0, routeMatch.index - 50)\n const surroundingEnd = Math.min(block.length, routeMatch.index + 200)\n const surrounding = block.slice(surroundingStart, surroundingEnd)\n\n routes.push({\n path: routePath,\n name: surrounding.match(/name\\s*:\\s*[\"']([^\"']+)[\"']/)?.[1],\n hasLoader: /loader\\s*:/.test(surrounding),\n hasGuard: /beforeEnter\\s*:|beforeLeave\\s*:/.test(surrounding),\n params: extractParams(routePath),\n })\n }\n }\n }\n\n return routes\n}\n\nfunction extractComponents(files: string[], cwd: string): ComponentInfo[] {\n const components: ComponentInfo[] = []\n\n for (const file of files) {\n let code: string\n try {\n code = fs.readFileSync(file, 'utf-8')\n } catch {\n continue\n }\n\n const componentRe =\n /(?:export\\s+)?(?:const|function)\\s+([A-Z]\\w*)\\s*(?::\\s*ComponentFn<[^>]+>\\s*)?=?\\s*\\(?(?:\\s*\\{?\\s*([^)]*?)\\s*\\}?\\s*)?\\)?\\s*(?:=>|{)/g\n let match: RegExpExecArray | null\n\n for (match = componentRe.exec(code); match; match = componentRe.exec(code)) {\n const name = match[1] ?? 'Unknown'\n const propsStr = match[2] ?? ''\n const props = propsStr\n .split(/[,;]/)\n .map((p) => p.trim().replace(/[{}]/g, '').trim().split(':')[0]?.split('=')[0]?.trim() ?? '')\n .filter((p) => p && p !== 'props')\n\n const bodyStart = match.index + match[0].length\n const body = code.slice(bodyStart, Math.min(code.length, bodyStart + 2000))\n const signalNames: string[] = []\n const signalRe = /(?:const|let)\\s+(\\w+)\\s*=\\s*signal\\s*[<(]/g\n let sigMatch: RegExpExecArray | null\n for (sigMatch = signalRe.exec(body); sigMatch; sigMatch = signalRe.exec(body)) {\n if (sigMatch[1]) signalNames.push(sigMatch[1])\n }\n\n components.push({\n name,\n file: path.relative(cwd, file),\n hasSignals: signalNames.length > 0,\n signalNames,\n props,\n })\n }\n }\n\n return components\n}\n\nfunction extractIslands(files: string[], cwd: string): IslandInfo[] {\n const islands: IslandInfo[] = []\n\n for (const file of files) {\n let code: string\n try {\n code = fs.readFileSync(file, 'utf-8')\n } catch {\n continue\n }\n\n const islandRe =\n /island\\s*\\(\\s*\\(\\)\\s*=>\\s*import\\(.+?\\)\\s*,\\s*\\{[^}]*name\\s*:\\s*[\"']([^\"']+)[\"'][^}]*?(?:hydrate\\s*:\\s*[\"']([^\"']+)[\"'])?[^}]*\\}/g\n let match: RegExpExecArray | null\n for (match = islandRe.exec(code); match; match = islandRe.exec(code)) {\n if (match[1]) {\n islands.push({\n name: match[1],\n file: path.relative(cwd, file),\n hydrate: match[2] ?? 'load',\n })\n }\n }\n }\n\n return islands\n}\n\nfunction extractParams(routePath: string): string[] {\n const params: string[] = []\n const paramRe = /:(\\w+)\\??/g\n let match: RegExpExecArray | null\n for (match = paramRe.exec(routePath); match; match = paramRe.exec(routePath)) {\n if (match[1]) params.push(match[1])\n }\n return params\n}\n\nfunction readVersion(cwd: string): string {\n try {\n const pkg = JSON.parse(fs.readFileSync(path.join(cwd, 'package.json'), 'utf-8'))\n const deps: Record<string, unknown> = { ...pkg.dependencies, ...pkg.devDependencies }\n for (const [name, ver] of Object.entries(deps)) {\n if (name.startsWith('@pyreon/') && typeof ver === 'string') return ver.replace(/^[\\^~]/, '')\n }\n return (pkg.version as string) || 'unknown'\n } catch {\n return 'unknown'\n }\n}\n","/**\n * React Pattern Interceptor — detects React/Vue patterns in code and provides\n * structured diagnostics with exact fix suggestions for AI-assisted migration.\n *\n * Two modes:\n * - `detectReactPatterns(code)` — returns diagnostics only (non-destructive)\n * - `migrateReactCode(code)` — applies auto-fixes and returns transformed code\n *\n * Designed for three consumers:\n * 1. Compiler pre-pass (warnings during build)\n * 2. CLI `pyreon doctor` (project-wide scanning)\n * 3. MCP server `migrate_react` / `validate` tools (AI agent integration)\n */\n\nimport ts from 'typescript'\n\n// ═══════════════════════════════════════════════════════════════════════════════\n// Types\n// ═══════════════════════════════════════════════════════════════════════════════\n\nexport type ReactDiagnosticCode =\n | 'react-import'\n | 'react-dom-import'\n | 'react-router-import'\n | 'use-state'\n | 'use-effect-mount'\n | 'use-effect-deps'\n | 'use-effect-no-deps'\n | 'use-memo'\n | 'use-callback'\n | 'use-ref-dom'\n | 'use-ref-box'\n | 'use-reducer'\n | 'use-layout-effect'\n | 'memo-wrapper'\n | 'forward-ref'\n | 'class-name-prop'\n | 'html-for-prop'\n | 'on-change-input'\n | 'dangerously-set-inner-html'\n | 'dot-value-signal'\n | 'array-map-jsx'\n | 'key-on-for-child'\n | 'create-context-import'\n | 'use-context-import'\n\nexport interface ReactDiagnostic {\n /** Machine-readable code for filtering and programmatic handling */\n code: ReactDiagnosticCode\n /** Human-readable message explaining the issue */\n message: string\n /** 1-based line number */\n line: number\n /** 0-based column */\n column: number\n /** The code as written */\n current: string\n /** The suggested Pyreon equivalent */\n suggested: string\n /** Whether migrateReactCode can auto-fix this */\n fixable: boolean\n}\n\nexport interface MigrationChange {\n type: 'replace' | 'remove' | 'add'\n line: number\n description: string\n}\n\nexport interface MigrationResult {\n /** Transformed source code */\n code: string\n /** All detected patterns (including unfixable ones) */\n diagnostics: ReactDiagnostic[]\n /** Description of changes applied */\n changes: MigrationChange[]\n}\n\n// ═══════════════════════════════════════════════════════════════════════════════\n// React Hook → Pyreon mapping\n// ═══════════════════════════════════════════════════════════════════════════════\n\ninterface HookMapping {\n pyreonFn: string\n pyreonImport: string\n description: string\n example: string\n}\n\nconst _REACT_HOOK_MAP: Record<string, HookMapping> = {\n useState: {\n pyreonFn: 'signal',\n pyreonImport: '@pyreon/reactivity',\n description: 'Signals are callable functions — read: count(), write: count.set(5)',\n example:\n 'const count = signal(0)\\n// Read: count() Write: count.set(5) Update: count.update(n => n + 1)',\n },\n useEffect: {\n pyreonFn: 'effect',\n pyreonImport: '@pyreon/reactivity',\n description: 'Effects auto-track signal dependencies — no dependency array needed',\n example: 'effect(() => {\\n console.log(count()) // auto-subscribes to count\\n})',\n },\n useLayoutEffect: {\n pyreonFn: 'effect',\n pyreonImport: '@pyreon/reactivity',\n description: 'Pyreon effects run synchronously after signal updates',\n example: 'effect(() => {\\n // runs sync after signal changes\\n})',\n },\n useMemo: {\n pyreonFn: 'computed',\n pyreonImport: '@pyreon/reactivity',\n description: 'Computed values auto-track dependencies and memoize',\n example: 'const doubled = computed(() => count() * 2)',\n },\n useCallback: {\n pyreonFn: '(plain function)',\n pyreonImport: '',\n description:\n 'Not needed — Pyreon components run once, so closures never go stale. Use a plain function',\n example: 'const handleClick = () => doSomething(count())',\n },\n useReducer: {\n pyreonFn: 'signal',\n pyreonImport: '@pyreon/reactivity',\n description: 'Use signal with update() for reducer-like patterns',\n example:\n 'const state = signal(initialState)\\nconst dispatch = (action) => state.update(s => reducer(s, action))',\n },\n}\n\n/** React import sources → Pyreon equivalents */\nconst IMPORT_REWRITES: Record<string, string | null> = {\n react: '@pyreon/core',\n 'react-dom': '@pyreon/runtime-dom',\n 'react-dom/client': '@pyreon/runtime-dom',\n 'react-dom/server': '@pyreon/runtime-server',\n 'react-router': '@pyreon/router',\n 'react-router-dom': '@pyreon/router',\n}\n\n/** React specifiers that map to specific Pyreon imports */\nconst SPECIFIER_REWRITES: Record<string, { name: string; from: string }> = {\n useState: { name: 'signal', from: '@pyreon/reactivity' },\n useEffect: { name: 'effect', from: '@pyreon/reactivity' },\n useLayoutEffect: { name: 'effect', from: '@pyreon/reactivity' },\n useMemo: { name: 'computed', from: '@pyreon/reactivity' },\n useReducer: { name: 'signal', from: '@pyreon/reactivity' },\n useRef: { name: 'signal', from: '@pyreon/reactivity' },\n createContext: { name: 'createContext', from: '@pyreon/core' },\n useContext: { name: 'useContext', from: '@pyreon/core' },\n Fragment: { name: 'Fragment', from: '@pyreon/core' },\n Suspense: { name: 'Suspense', from: '@pyreon/core' },\n lazy: { name: 'lazy', from: '@pyreon/core' },\n memo: { name: '', from: '' }, // removed, not needed\n forwardRef: { name: '', from: '' }, // removed, not needed\n createRoot: { name: 'mount', from: '@pyreon/runtime-dom' },\n hydrateRoot: { name: 'hydrateRoot', from: '@pyreon/runtime-dom' },\n // React Router\n useNavigate: { name: 'useRouter', from: '@pyreon/router' },\n useParams: { name: 'useRoute', from: '@pyreon/router' },\n useLocation: { name: 'useRoute', from: '@pyreon/router' },\n Link: { name: 'RouterLink', from: '@pyreon/router' },\n NavLink: { name: 'RouterLink', from: '@pyreon/router' },\n Outlet: { name: 'RouterView', from: '@pyreon/router' },\n useSearchParams: { name: 'useSearchParams', from: '@pyreon/router' },\n}\n\n/** JSX attribute rewrites (React → standard HTML) */\nconst JSX_ATTR_REWRITES: Record<string, string> = {\n className: 'class',\n htmlFor: 'for',\n}\n\n// ═══════════════════════════════════════════════════════════════════════════════\n// Detection (diagnostic-only, no modifications)\n// ═══════════════════════════════════════════════════════════════════════════════\n\ninterface DetectContext {\n sf: ts.SourceFile\n code: string\n diagnostics: ReactDiagnostic[]\n reactImportedHooks: Set<string>\n}\n\nfunction detectGetNodeText(ctx: DetectContext, node: ts.Node): string {\n return ctx.code.slice(node.getStart(ctx.sf), node.getEnd())\n}\n\nfunction detectDiag(\n ctx: DetectContext,\n node: ts.Node,\n diagCode: ReactDiagnosticCode,\n message: string,\n current: string,\n suggested: string,\n fixable: boolean,\n): void {\n const { line, character } = ctx.sf.getLineAndCharacterOfPosition(node.getStart(ctx.sf))\n ctx.diagnostics.push({\n code: diagCode,\n message,\n line: line + 1,\n column: character,\n current: current.trim(),\n suggested: suggested.trim(),\n fixable,\n })\n}\n\nfunction detectImportDeclaration(ctx: DetectContext, node: ts.ImportDeclaration): void {\n if (!node.moduleSpecifier) return\n const source = (node.moduleSpecifier as ts.StringLiteral).text\n const pyreonSource = IMPORT_REWRITES[source]\n\n if (pyreonSource !== undefined) {\n if (node.importClause?.namedBindings && ts.isNamedImports(node.importClause.namedBindings)) {\n for (const spec of node.importClause.namedBindings.elements) {\n ctx.reactImportedHooks.add(spec.name.text)\n }\n }\n\n const diagCode = source.startsWith('react-router')\n ? 'react-router-import'\n : source.startsWith('react-dom')\n ? 'react-dom-import'\n : 'react-import'\n\n detectDiag(\n ctx,\n node,\n diagCode,\n `Import from '${source}' is a React package. Use Pyreon equivalent.`,\n detectGetNodeText(ctx, node),\n pyreonSource\n ? `import { ... } from \"${pyreonSource}\"`\n : 'Remove this import — not needed in Pyreon',\n true,\n )\n }\n}\n\nfunction detectUseState(ctx: DetectContext, node: ts.CallExpression): void {\n const parent = node.parent\n if (\n ts.isVariableDeclaration(parent) &&\n parent.name &&\n ts.isArrayBindingPattern(parent.name) &&\n parent.name.elements.length >= 1\n ) {\n const firstEl = parent.name.elements[0]\n const valueName =\n firstEl && ts.isBindingElement(firstEl) ? (firstEl.name as ts.Identifier).text : 'value'\n const initArg = node.arguments[0] ? detectGetNodeText(ctx, node.arguments[0]) : 'undefined'\n\n detectDiag(\n ctx,\n node,\n 'use-state',\n `useState is a React API. In Pyreon, use signal(). Read: ${valueName}(), Write: ${valueName}.set(x)`,\n detectGetNodeText(ctx, parent),\n `${valueName} = signal(${initArg})`,\n true,\n )\n } else {\n detectDiag(\n ctx,\n node,\n 'use-state',\n 'useState is a React API. In Pyreon, use signal().',\n detectGetNodeText(ctx, node),\n 'signal(initialValue)',\n true,\n )\n }\n}\n\nfunction callbackHasCleanup(callbackArg: ts.Expression): boolean {\n if (!ts.isArrowFunction(callbackArg) && !ts.isFunctionExpression(callbackArg)) return false\n const body = callbackArg.body\n if (!ts.isBlock(body)) return false\n for (const stmt of body.statements) {\n if (ts.isReturnStatement(stmt) && stmt.expression) return true\n }\n return false\n}\n\nfunction detectUseEffect(ctx: DetectContext, node: ts.CallExpression): void {\n const hookName = (node.expression as ts.Identifier).text\n const depsArg = node.arguments[1]\n const callbackArg = node.arguments[0]\n\n if (depsArg && ts.isArrayLiteralExpression(depsArg) && depsArg.elements.length === 0) {\n const hasCleanup = callbackArg ? callbackHasCleanup(callbackArg) : false\n\n detectDiag(\n ctx,\n node,\n 'use-effect-mount',\n `${hookName} with empty deps [] means \"run once on mount\". Use onMount() in Pyreon.`,\n detectGetNodeText(ctx, node),\n hasCleanup\n ? 'onMount(() => {\\n // setup...\\n return () => { /* cleanup */ }\\n})'\n : 'onMount(() => {\\n // setup...\\n})',\n true,\n )\n } else if (depsArg && ts.isArrayLiteralExpression(depsArg)) {\n detectDiag(\n ctx,\n node,\n 'use-effect-deps',\n `${hookName} with dependency array. In Pyreon, effect() auto-tracks dependencies — no array needed.`,\n detectGetNodeText(ctx, node),\n 'effect(() => {\\n // reads are auto-tracked\\n})',\n true,\n )\n } else if (!depsArg) {\n detectDiag(\n ctx,\n node,\n 'use-effect-no-deps',\n `${hookName} with no dependency array. In Pyreon, use effect() — it auto-tracks signal reads.`,\n detectGetNodeText(ctx, node),\n 'effect(() => {\\n // runs when accessed signals change\\n})',\n true,\n )\n }\n}\n\nfunction detectUseMemo(ctx: DetectContext, node: ts.CallExpression): void {\n const computeFn = node.arguments[0]\n const computeText = computeFn ? detectGetNodeText(ctx, computeFn) : '() => value'\n\n detectDiag(\n ctx,\n node,\n 'use-memo',\n 'useMemo is a React API. In Pyreon, use computed() — dependencies auto-tracked.',\n detectGetNodeText(ctx, node),\n `computed(${computeText})`,\n true,\n )\n}\n\nfunction detectUseCallback(ctx: DetectContext, node: ts.CallExpression): void {\n const callbackFn = node.arguments[0]\n const callbackText = callbackFn ? detectGetNodeText(ctx, callbackFn) : '() => {}'\n\n detectDiag(\n ctx,\n node,\n 'use-callback',\n 'useCallback is not needed in Pyreon. Components run once, so closures never go stale. Use a plain function.',\n detectGetNodeText(ctx, node),\n callbackText,\n true,\n )\n}\n\nfunction detectUseRef(ctx: DetectContext, node: ts.CallExpression): void {\n const arg = node.arguments[0]\n const isNullInit =\n arg &&\n (arg.kind === ts.SyntaxKind.NullKeyword || (ts.isIdentifier(arg) && arg.text === 'undefined'))\n\n if (isNullInit) {\n detectDiag(\n ctx,\n node,\n 'use-ref-dom',\n 'useRef(null) for DOM refs. In Pyreon, use createRef() from @pyreon/core.',\n detectGetNodeText(ctx, node),\n 'createRef()',\n true,\n )\n } else {\n const initText = arg ? detectGetNodeText(ctx, arg) : 'undefined'\n detectDiag(\n ctx,\n node,\n 'use-ref-box',\n 'useRef for mutable values. In Pyreon, use signal() — it works the same way but is reactive.',\n detectGetNodeText(ctx, node),\n `signal(${initText})`,\n true,\n )\n }\n}\n\nfunction detectUseReducer(ctx: DetectContext, node: ts.CallExpression): void {\n detectDiag(\n ctx,\n node,\n 'use-reducer',\n 'useReducer is a React API. In Pyreon, use signal() with update() for reducer patterns.',\n detectGetNodeText(ctx, node),\n 'const state = signal(initialState)\\nconst dispatch = (action) => state.update(s => reducer(s, action))',\n false,\n )\n}\n\nfunction isCallToReactDot(callee: ts.Expression, methodName: string): boolean {\n return (\n ts.isPropertyAccessExpression(callee) &&\n ts.isIdentifier(callee.expression) &&\n callee.expression.text === 'React' &&\n callee.name.text === methodName\n )\n}\n\nfunction detectMemoWrapper(ctx: DetectContext, node: ts.CallExpression): void {\n const callee = node.expression\n const isMemo =\n (ts.isIdentifier(callee) && callee.text === 'memo') || isCallToReactDot(callee, 'memo')\n\n if (isMemo) {\n const inner = node.arguments[0]\n const innerText = inner ? detectGetNodeText(ctx, inner) : 'Component'\n\n detectDiag(\n ctx,\n node,\n 'memo-wrapper',\n 'memo() is not needed in Pyreon. Components run once — only signals trigger updates, not re-renders.',\n detectGetNodeText(ctx, node),\n innerText,\n true,\n )\n }\n}\n\nfunction detectForwardRef(ctx: DetectContext, node: ts.CallExpression): void {\n const callee = node.expression\n const isForwardRef =\n (ts.isIdentifier(callee) && callee.text === 'forwardRef') ||\n isCallToReactDot(callee, 'forwardRef')\n\n if (isForwardRef) {\n detectDiag(\n ctx,\n node,\n 'forward-ref',\n 'forwardRef is not needed in Pyreon. Pass ref as a regular prop.',\n detectGetNodeText(ctx, node),\n '// Just pass ref as a prop:\\nconst MyInput = (props) => <input ref={props.ref} />',\n true,\n )\n }\n}\n\nfunction detectJsxAttributes(ctx: DetectContext, node: ts.JsxAttribute): void {\n const attrName = (node.name as ts.Identifier).text\n\n if (attrName in JSX_ATTR_REWRITES) {\n const htmlAttr = JSX_ATTR_REWRITES[attrName] as string\n detectDiag(\n ctx,\n node,\n attrName === 'className' ? 'class-name-prop' : 'html-for-prop',\n `'${attrName}' is a React JSX attribute. Use '${htmlAttr}' in Pyreon (standard HTML).`,\n detectGetNodeText(ctx, node),\n detectGetNodeText(ctx, node).replace(attrName, htmlAttr),\n true,\n )\n }\n\n if (attrName === 'onChange') {\n const jsxElement = findParentJsxElement(node)\n if (jsxElement) {\n const tagName = getJsxTagName(jsxElement)\n if (tagName === 'input' || tagName === 'textarea' || tagName === 'select') {\n detectDiag(\n ctx,\n node,\n 'on-change-input',\n `onChange on <${tagName}> fires on blur in Pyreon (native DOM behavior). For keypress-by-keypress updates, use onInput.`,\n detectGetNodeText(ctx, node),\n detectGetNodeText(ctx, node).replace('onChange', 'onInput'),\n true,\n )\n }\n }\n }\n\n if (attrName === 'dangerouslySetInnerHTML') {\n detectDiag(\n ctx,\n node,\n 'dangerously-set-inner-html',\n 'dangerouslySetInnerHTML is React-specific. Use innerHTML prop in Pyreon.',\n detectGetNodeText(ctx, node),\n 'innerHTML={htmlString}',\n true,\n )\n }\n}\n\nfunction detectDotValueSignal(ctx: DetectContext, node: ts.PropertyAccessExpression): void {\n const varName = (node.expression as ts.Identifier).text\n const parent = node.parent\n if (ts.isBinaryExpression(parent) && parent.left === node) {\n detectDiag(\n ctx,\n node,\n 'dot-value-signal',\n `'${varName}.value' looks like a Vue ref pattern. Pyreon signals are callable functions. Use ${varName}.set(x) to write.`,\n detectGetNodeText(ctx, parent),\n `${varName}.set(${detectGetNodeText(ctx, parent.right)})`,\n false,\n )\n }\n}\n\nfunction detectArrayMapJsx(ctx: DetectContext, node: ts.CallExpression): void {\n const parent = node.parent\n if (ts.isJsxExpression(parent)) {\n const arrayExpr = detectGetNodeText(\n ctx,\n (node.expression as ts.PropertyAccessExpression).expression,\n )\n const mapCallback = node.arguments[0]\n const mapCallbackText = mapCallback\n ? detectGetNodeText(ctx, mapCallback)\n : 'item => <li>{item}</li>'\n\n detectDiag(\n ctx,\n node,\n 'array-map-jsx',\n 'Array.map() in JSX is not reactive in Pyreon. Use <For> for efficient keyed list rendering.',\n detectGetNodeText(ctx, node),\n `<For each={${arrayExpr}} by={item => item.id}>\\n {${mapCallbackText}}\\n</For>`,\n false,\n )\n }\n}\n\nfunction isCallToHook(node: ts.Node, hookName: string): node is ts.CallExpression {\n return (\n ts.isCallExpression(node) &&\n ts.isIdentifier(node.expression) &&\n node.expression.text === hookName\n )\n}\n\nfunction isCallToEffectHook(node: ts.Node): node is ts.CallExpression {\n return (\n ts.isCallExpression(node) &&\n ts.isIdentifier(node.expression) &&\n (node.expression.text === 'useEffect' || node.expression.text === 'useLayoutEffect')\n )\n}\n\nfunction isMapCallExpression(node: ts.Node): node is ts.CallExpression {\n return (\n ts.isCallExpression(node) &&\n ts.isPropertyAccessExpression(node.expression) &&\n ts.isIdentifier(node.expression.name) &&\n node.expression.name.text === 'map'\n )\n}\n\nfunction isDotValueAccess(node: ts.Node): node is ts.PropertyAccessExpression {\n return (\n ts.isPropertyAccessExpression(node) &&\n ts.isIdentifier(node.name) &&\n node.name.text === 'value' &&\n ts.isIdentifier(node.expression)\n )\n}\n\nfunction detectVisitNode(ctx: DetectContext, node: ts.Node): void {\n if (ts.isImportDeclaration(node)) detectImportDeclaration(ctx, node)\n if (isCallToHook(node, 'useState')) detectUseState(ctx, node)\n if (isCallToEffectHook(node)) detectUseEffect(ctx, node)\n if (isCallToHook(node, 'useMemo')) detectUseMemo(ctx, node)\n if (isCallToHook(node, 'useCallback')) detectUseCallback(ctx, node)\n if (isCallToHook(node, 'useRef')) detectUseRef(ctx, node)\n if (isCallToHook(node, 'useReducer')) detectUseReducer(ctx, node)\n if (ts.isCallExpression(node)) detectMemoWrapper(ctx, node)\n if (ts.isCallExpression(node)) detectForwardRef(ctx, node)\n if (ts.isJsxAttribute(node) && ts.isIdentifier(node.name)) detectJsxAttributes(ctx, node)\n if (isDotValueAccess(node)) detectDotValueSignal(ctx, node)\n if (isMapCallExpression(node)) detectArrayMapJsx(ctx, node)\n}\n\nfunction detectVisit(ctx: DetectContext, node: ts.Node): void {\n ts.forEachChild(node, (child) => {\n detectVisitNode(ctx, child)\n detectVisit(ctx, child)\n })\n}\n\nexport function detectReactPatterns(code: string, filename = 'input.tsx'): ReactDiagnostic[] {\n const sf = ts.createSourceFile(filename, code, ts.ScriptTarget.ESNext, true, ts.ScriptKind.TSX)\n const ctx: DetectContext = {\n sf,\n code,\n diagnostics: [],\n reactImportedHooks: new Set<string>(),\n }\n\n detectVisit(ctx, sf)\n return ctx.diagnostics\n}\n\n// ═══════════════════════════════════════════════════════════════════════════════\n// Migration (detection + auto-fix)\n// ═══════════════════════════════════════════════════════════════════════════════\n\ntype Replacement = { start: number; end: number; text: string }\n\ninterface MigrateContext {\n sf: ts.SourceFile\n code: string\n replacements: Replacement[]\n changes: MigrationChange[]\n pyreonImports: Map<string, Set<string>>\n importsToRemove: Set<ts.ImportDeclaration>\n specifierRewrites: Map<ts.ImportSpecifier, { name: string; from: string }>\n}\n\nfunction migrateAddImport(ctx: MigrateContext, source: string, specifier: string): void {\n if (!source || !specifier) return\n let specs = ctx.pyreonImports.get(source)\n if (!specs) {\n specs = new Set()\n ctx.pyreonImports.set(source, specs)\n }\n specs.add(specifier)\n}\n\nfunction migrateReplace(ctx: MigrateContext, node: ts.Node, text: string): void {\n ctx.replacements.push({ start: node.getStart(ctx.sf), end: node.getEnd(), text })\n}\n\nfunction migrateGetNodeText(ctx: MigrateContext, node: ts.Node): string {\n return ctx.code.slice(node.getStart(ctx.sf), node.getEnd())\n}\n\nfunction migrateGetLine(ctx: MigrateContext, node: ts.Node): number {\n return ctx.sf.getLineAndCharacterOfPosition(node.getStart(ctx.sf)).line + 1\n}\n\nfunction migrateImportDeclaration(ctx: MigrateContext, node: ts.ImportDeclaration): void {\n if (!node.moduleSpecifier) return\n const source = (node.moduleSpecifier as ts.StringLiteral).text\n if (!(source in IMPORT_REWRITES)) return\n\n if (node.importClause?.namedBindings && ts.isNamedImports(node.importClause.namedBindings)) {\n for (const spec of node.importClause.namedBindings.elements) {\n const name = spec.name.text\n const rewrite = SPECIFIER_REWRITES[name]\n if (rewrite) {\n if (rewrite.name) {\n migrateAddImport(ctx, rewrite.from, rewrite.name)\n }\n ctx.specifierRewrites.set(spec, rewrite)\n }\n }\n }\n ctx.importsToRemove.add(node)\n}\n\nfunction migrateUseState(ctx: MigrateContext, node: ts.CallExpression): void {\n const parent = node.parent\n if (\n ts.isVariableDeclaration(parent) &&\n parent.name &&\n ts.isArrayBindingPattern(parent.name) &&\n parent.name.elements.length >= 1\n ) {\n const firstEl = parent.name.elements[0]\n const valueName =\n firstEl && ts.isBindingElement(firstEl) ? (firstEl.name as ts.Identifier).text : 'value'\n const initArg = node.arguments[0] ? migrateGetNodeText(ctx, node.arguments[0]) : 'undefined'\n\n const declStart = parent.getStart(ctx.sf)\n const declEnd = parent.getEnd()\n ctx.replacements.push({\n start: declStart,\n end: declEnd,\n text: `${valueName} = signal(${initArg})`,\n })\n migrateAddImport(ctx, '@pyreon/reactivity', 'signal')\n ctx.changes.push({\n type: 'replace',\n line: migrateGetLine(ctx, node),\n description: `useState → signal: ${valueName}`,\n })\n }\n}\n\nfunction migrateUseEffect(ctx: MigrateContext, node: ts.CallExpression): void {\n const depsArg = node.arguments[1]\n const callbackArg = node.arguments[0]\n const hookName = (node.expression as ts.Identifier).text\n\n if (\n depsArg &&\n ts.isArrayLiteralExpression(depsArg) &&\n depsArg.elements.length === 0 &&\n callbackArg\n ) {\n const callbackText = migrateGetNodeText(ctx, callbackArg)\n migrateReplace(ctx, node, `onMount(${callbackText})`)\n migrateAddImport(ctx, '@pyreon/core', 'onMount')\n ctx.changes.push({\n type: 'replace',\n line: migrateGetLine(ctx, node),\n description: `${hookName}(fn, []) → onMount(fn)`,\n })\n } else if (callbackArg) {\n const callbackText = migrateGetNodeText(ctx, callbackArg)\n migrateReplace(ctx, node, `effect(${callbackText})`)\n migrateAddImport(ctx, '@pyreon/reactivity', 'effect')\n ctx.changes.push({\n type: 'replace',\n line: migrateGetLine(ctx, node),\n description: `${hookName} → effect (auto-tracks deps)`,\n })\n }\n}\n\nfunction migrateUseMemo(ctx: MigrateContext, node: ts.CallExpression): void {\n const computeFn = node.arguments[0]\n if (computeFn) {\n migrateReplace(ctx, node, `computed(${migrateGetNodeText(ctx, computeFn)})`)\n migrateAddImport(ctx, '@pyreon/reactivity', 'computed')\n ctx.changes.push({\n type: 'replace',\n line: migrateGetLine(ctx, node),\n description: 'useMemo → computed (auto-tracks deps)',\n })\n }\n}\n\nfunction migrateUseCallback(ctx: MigrateContext, node: ts.CallExpression): void {\n const callbackFn = node.arguments[0]\n if (callbackFn) {\n migrateReplace(ctx, node, migrateGetNodeText(ctx, callbackFn))\n ctx.changes.push({\n type: 'replace',\n line: migrateGetLine(ctx, node),\n description: 'useCallback → plain function (not needed in Pyreon)',\n })\n }\n}\n\nfunction migrateUseRef(ctx: MigrateContext, node: ts.CallExpression): void {\n const arg = node.arguments[0]\n const isNullInit =\n arg &&\n (arg.kind === ts.SyntaxKind.NullKeyword || (ts.isIdentifier(arg) && arg.text === 'undefined'))\n\n if (isNullInit || !arg) {\n migrateReplace(ctx, node, 'createRef()')\n migrateAddImport(ctx, '@pyreon/core', 'createRef')\n ctx.changes.push({\n type: 'replace',\n line: migrateGetLine(ctx, node),\n description: 'useRef(null) → createRef()',\n })\n } else {\n migrateReplace(ctx, node, `signal(${migrateGetNodeText(ctx, arg)})`)\n migrateAddImport(ctx, '@pyreon/reactivity', 'signal')\n ctx.changes.push({\n type: 'replace',\n line: migrateGetLine(ctx, node),\n description: 'useRef(value) → signal(value)',\n })\n }\n}\n\nfunction migrateMemoWrapper(ctx: MigrateContext, node: ts.CallExpression): void {\n const callee = node.expression\n const isMemo =\n (ts.isIdentifier(callee) && callee.text === 'memo') || isCallToReactDot(callee, 'memo')\n\n if (isMemo && node.arguments[0]) {\n migrateReplace(ctx, node, migrateGetNodeText(ctx, node.arguments[0]))\n ctx.changes.push({\n type: 'remove',\n line: migrateGetLine(ctx, node),\n description: 'Removed memo() wrapper (not needed in Pyreon)',\n })\n }\n}\n\nfunction migrateForwardRef(ctx: MigrateContext, node: ts.CallExpression): void {\n const callee = node.expression\n const isForwardRef =\n (ts.isIdentifier(callee) && callee.text === 'forwardRef') ||\n isCallToReactDot(callee, 'forwardRef')\n\n if (isForwardRef && node.arguments[0]) {\n migrateReplace(ctx, node, migrateGetNodeText(ctx, node.arguments[0]))\n ctx.changes.push({\n type: 'remove',\n line: migrateGetLine(ctx, node),\n description: 'Removed forwardRef wrapper (pass ref as normal prop in Pyreon)',\n })\n }\n}\n\nfunction migrateJsxAttributes(ctx: MigrateContext, node: ts.JsxAttribute): void {\n const attrName = (node.name as ts.Identifier).text\n\n if (attrName in JSX_ATTR_REWRITES) {\n const htmlAttr = JSX_ATTR_REWRITES[attrName] as string\n ctx.replacements.push({\n start: node.name.getStart(ctx.sf),\n end: node.name.getEnd(),\n text: htmlAttr,\n })\n ctx.changes.push({\n type: 'replace',\n line: migrateGetLine(ctx, node),\n description: `${attrName} → ${htmlAttr}`,\n })\n }\n\n if (attrName === 'onChange') {\n const jsxElement = findParentJsxElement(node)\n if (jsxElement) {\n const tagName = getJsxTagName(jsxElement)\n if (tagName === 'input' || tagName === 'textarea' || tagName === 'select') {\n ctx.replacements.push({\n start: node.name.getStart(ctx.sf),\n end: node.name.getEnd(),\n text: 'onInput',\n })\n ctx.changes.push({\n type: 'replace',\n line: migrateGetLine(ctx, node),\n description: `onChange on <${tagName}> → onInput (native DOM events)`,\n })\n }\n }\n }\n\n if (attrName === 'dangerouslySetInnerHTML') {\n migrateDangerouslySetInnerHTML(ctx, node)\n }\n}\n\nfunction migrateDangerouslySetInnerHTML(ctx: MigrateContext, node: ts.JsxAttribute): void {\n if (!node.initializer || !ts.isJsxExpression(node.initializer) || !node.initializer.expression) {\n return\n }\n const expr = node.initializer.expression\n if (!ts.isObjectLiteralExpression(expr)) return\n\n const htmlProp = expr.properties.find(\n (p) => ts.isPropertyAssignment(p) && ts.isIdentifier(p.name) && p.name.text === '__html',\n ) as ts.PropertyAssignment | undefined\n\n if (htmlProp) {\n const valueText = migrateGetNodeText(ctx, htmlProp.initializer)\n migrateReplace(ctx, node, `innerHTML={${valueText}}`)\n ctx.changes.push({\n type: 'replace',\n line: migrateGetLine(ctx, node),\n description: 'dangerouslySetInnerHTML → innerHTML',\n })\n }\n}\n\nfunction applyReplacements(code: string, ctx: MigrateContext): string {\n // Remove React import declarations\n for (const imp of ctx.importsToRemove) {\n ctx.replacements.push({ start: imp.getStart(ctx.sf), end: imp.getEnd(), text: '' })\n ctx.changes.push({\n type: 'remove',\n line: ctx.sf.getLineAndCharacterOfPosition(imp.getStart(ctx.sf)).line + 1,\n description: 'Removed React import',\n })\n }\n\n // Sort descending for dedup (outermost replacements win over inner overlapping ones)\n ctx.replacements.sort((a, b) => b.start - a.start)\n\n // Deduplicate overlapping replacements (keep the outermost / first added)\n const applied = new Set<string>()\n const deduped: Replacement[] = []\n for (const r of ctx.replacements) {\n const key = `${r.start}:${r.end}`\n let overlaps = false\n for (const d of deduped) {\n if (r.start < d.end && r.end > d.start) {\n overlaps = true\n break\n }\n }\n if (!overlaps && !applied.has(key)) {\n applied.add(key)\n deduped.push(r)\n }\n }\n\n // Re-sort ascending for string builder — O(n) single join\n deduped.sort((a, b) => a.start - b.start)\n const parts: string[] = []\n let lastPos = 0\n for (const r of deduped) {\n parts.push(code.slice(lastPos, r.start))\n parts.push(r.text)\n lastPos = r.end\n }\n parts.push(code.slice(lastPos))\n return parts.join('')\n}\n\nfunction insertPyreonImports(code: string, pyreonImports: Map<string, Set<string>>): string {\n if (pyreonImports.size === 0) return code\n\n const importLines: string[] = []\n const sorted = [...pyreonImports.entries()].sort(([a], [b]) => a.localeCompare(b))\n for (const [source, specs] of sorted) {\n const specList = [...specs].sort().join(', ')\n importLines.push(`import { ${specList} } from \"${source}\"`)\n }\n const importBlock = importLines.join('\\n')\n\n const lastImportEnd = findLastImportEnd(code)\n if (lastImportEnd > 0) {\n return `${code.slice(0, lastImportEnd)}\\n${importBlock}${code.slice(lastImportEnd)}`\n }\n return `${importBlock}\\n\\n${code}`\n}\n\nfunction migrateVisitNode(ctx: MigrateContext, node: ts.Node): void {\n if (ts.isImportDeclaration(node)) migrateImportDeclaration(ctx, node)\n if (isCallToHook(node, 'useState')) migrateUseState(ctx, node)\n if (isCallToEffectHook(node)) migrateUseEffect(ctx, node)\n if (isCallToHook(node, 'useMemo')) migrateUseMemo(ctx, node)\n if (isCallToHook(node, 'useCallback')) migrateUseCallback(ctx, node)\n if (isCallToHook(node, 'useRef')) migrateUseRef(ctx, node)\n if (ts.isCallExpression(node)) migrateMemoWrapper(ctx, node)\n if (ts.isCallExpression(node)) migrateForwardRef(ctx, node)\n if (ts.isJsxAttribute(node) && ts.isIdentifier(node.name)) migrateJsxAttributes(ctx, node)\n}\n\nfunction migrateVisit(ctx: MigrateContext, node: ts.Node): void {\n ts.forEachChild(node, (child) => {\n migrateVisitNode(ctx, child)\n migrateVisit(ctx, child)\n })\n}\n\nexport function migrateReactCode(code: string, filename = 'input.tsx'): MigrationResult {\n const sf = ts.createSourceFile(filename, code, ts.ScriptTarget.ESNext, true, ts.ScriptKind.TSX)\n const diagnostics = detectReactPatterns(code, filename)\n\n const ctx: MigrateContext = {\n sf,\n code,\n replacements: [],\n changes: [],\n pyreonImports: new Map(),\n importsToRemove: new Set(),\n specifierRewrites: new Map(),\n }\n\n migrateVisit(ctx, sf)\n\n let result = applyReplacements(code, ctx)\n result = insertPyreonImports(result, ctx.pyreonImports)\n\n // Clean up empty lines from removed imports\n result = result.replace(/\\n{3,}/g, '\\n\\n')\n\n return { code: result, diagnostics, changes: ctx.changes }\n}\n\n// ═══════════════════════════════════════════════════════════════════════════════\n// Helpers\n// ═══════════════════════════════════════════════════════════════════════════════\n\nfunction findParentJsxElement(\n node: ts.Node,\n): ts.JsxOpeningElement | ts.JsxSelfClosingElement | null {\n let current = node.parent\n while (current) {\n if (ts.isJsxOpeningElement(current) || ts.isJsxSelfClosingElement(current)) {\n return current\n }\n // Don't cross component boundaries\n if (ts.isJsxElement(current)) {\n return current.openingElement\n }\n if (ts.isArrowFunction(current) || ts.isFunctionExpression(current)) {\n return null\n }\n current = current.parent\n }\n return null\n}\n\nfunction getJsxTagName(node: ts.JsxOpeningElement | ts.JsxSelfClosingElement): string {\n const tagName = node.tagName\n if (ts.isIdentifier(tagName)) {\n return tagName.text\n }\n return ''\n}\n\nfunction findLastImportEnd(code: string): number {\n const importRe = /^import\\s.+$/gm\n let lastEnd = 0\n let match: RegExpExecArray | null\n while (true) {\n match = importRe.exec(code)\n if (!match) break\n lastEnd = match.index + match[0].length\n }\n return lastEnd\n}\n\n// ═══════════════════════════════════════════════════════════════════════════════\n// Quick scan (regex-based, for fast pre-filtering)\n// ═══════════════════════════════════════════════════════════════════════════════\n\n/** Fast regex check — returns true if code likely contains React patterns worth analyzing */\nexport function hasReactPatterns(code: string): boolean {\n return (\n /\\bfrom\\s+['\"]react/.test(code) ||\n /\\bfrom\\s+['\"]react-dom/.test(code) ||\n /\\bfrom\\s+['\"]react-router/.test(code) ||\n /\\buseState\\s*[<(]/.test(code) ||\n /\\buseEffect\\s*\\(/.test(code) ||\n /\\buseMemo\\s*\\(/.test(code) ||\n /\\buseCallback\\s*\\(/.test(code) ||\n /\\buseRef\\s*[<(]/.test(code) ||\n /\\buseReducer\\s*[<(]/.test(code) ||\n /\\bReact\\.memo\\b/.test(code) ||\n /\\bforwardRef\\s*[<(]/.test(code) ||\n /\\bclassName[=\\s]/.test(code) ||\n /\\bhtmlFor[=\\s]/.test(code) ||\n /\\.value\\s*=/.test(code)\n )\n}\n\n// ═══════════════════════════════════════════════════════════════════════════════\n// Error pattern database (for MCP diagnose tool)\n// ═══════════════════════════════════════════════════════════════════════════════\n\nexport interface ErrorDiagnosis {\n cause: string\n fix: string\n fixCode?: string | undefined\n related?: string | undefined\n}\n\ninterface ErrorPattern {\n pattern: RegExp\n diagnose: (match: RegExpMatchArray) => ErrorDiagnosis\n}\n\nconst ERROR_PATTERNS: ErrorPattern[] = [\n {\n pattern: /Cannot read properties of undefined \\(reading '(set|update|peek|subscribe)'\\)/,\n diagnose: (m) => ({\n cause: `Calling .${m[1]}() on undefined. The signal variable is likely out of scope, misspelled, or not yet initialized.`,\n fix: 'Check that the signal is defined and in scope. Signals must be created with signal() before use.',\n fixCode: `const mySignal = signal(initialValue)\\nmySignal.${m[1]}(newValue)`,\n }),\n },\n {\n pattern: /(\\w+) is not a function/,\n diagnose: (m) => ({\n cause: `'${m[1]}' is not callable. If this is a signal, you need to call it: ${m[1]}()`,\n fix: 'Pyreon signals are callable functions. Read: signal(), Write: signal.set(value)',\n fixCode: `// Read value:\\nconst value = ${m[1]}()\\n// Set value:\\n${m[1]}.set(newValue)`,\n }),\n },\n {\n pattern: /Cannot find module '(@pyreon\\/\\w[\\w-]*)'/,\n diagnose: (m) => ({\n cause: `Package ${m[1]} is not installed.`,\n fix: `Run: bun add ${m[1]}`,\n fixCode: `bun add ${m[1]}`,\n }),\n },\n {\n pattern: /Cannot find module 'react'/,\n diagnose: () => ({\n cause: \"Importing from 'react' in a Pyreon project.\",\n fix: 'Replace React imports with Pyreon equivalents.',\n fixCode:\n '// Instead of:\\nimport { useState } from \"react\"\\n// Use:\\nimport { signal } from \"@pyreon/reactivity\"',\n }),\n },\n {\n pattern: /Property '(\\w+)' does not exist on type 'Signal<\\w+>'/,\n diagnose: (m) => ({\n cause: `Accessing .${m[1]} on a signal. Pyreon signals don't have a .${m[1]} property.`,\n fix:\n m[1] === 'value'\n ? 'Pyreon signals are callable functions, not .value getters. Call signal() to read, signal.set() to write.'\n : `Signals have these methods: .set(), .update(), .peek(), .subscribe(). '${m[1]}' is not one of them.`,\n fixCode:\n m[1] === 'value' ? '// Read: mySignal()\\n// Write: mySignal.set(newValue)' : undefined,\n }),\n },\n {\n pattern: /Type '(\\w+)' is not assignable to type 'VNode'/,\n diagnose: (m) => ({\n cause: `Component returned ${m[1]} instead of VNode. Components must return JSX, null, or a string.`,\n fix: 'Make sure your component returns a JSX element, null, or a string.',\n fixCode: 'const MyComponent = (props) => {\\n return <div>{props.children}</div>\\n}',\n }),\n },\n {\n pattern: /onMount callback must return/,\n diagnose: () => ({\n cause: 'onMount expects a callback that optionally returns a CleanupFn.',\n fix: 'Return a cleanup function, or return nothing.',\n fixCode: 'onMount(() => {\\n // setup code\\n})',\n }),\n },\n {\n pattern: /Expected 'by' prop on <For>/,\n diagnose: () => ({\n cause: \"<For> requires a 'by' prop for efficient keyed reconciliation.\",\n fix: 'Add a by prop that returns a unique key for each item.',\n fixCode:\n '<For each={items()} by={item => item.id}>\\n {item => <li>{item.name}</li>}\\n</For>',\n }),\n },\n {\n pattern: /useHook.*outside.*component/i,\n diagnose: () => ({\n cause:\n 'Hook called outside a component function. Pyreon hooks must be called during component setup.',\n fix: 'Move the hook call inside a component function body.',\n }),\n },\n {\n pattern: /Hydration mismatch/,\n diagnose: () => ({\n cause: \"Server-rendered HTML doesn't match client-rendered output.\",\n fix: 'Ensure SSR and client render the same initial content. Check for browser-only APIs (window, document) in SSR code.',\n related: \"Use typeof window !== 'undefined' checks or onMount() for client-only code.\",\n }),\n },\n]\n\n/** Diagnose an error message and return structured fix information */\nexport function diagnoseError(error: string): ErrorDiagnosis | null {\n for (const { pattern, diagnose } of ERROR_PATTERNS) {\n const match = error.match(pattern)\n if (match) {\n return diagnose(match)\n }\n }\n return null\n}\n","/**\n * Pyreon Pattern Interceptor — detects Pyreon-specific anti-patterns in\n * code that has ALREADY committed to the framework (imports are Pyreon,\n * not React). Complements `react-intercept.ts` — the React detector\n * catches \"coming from React\" mistakes; this one catches \"using Pyreon\n * wrong\" mistakes.\n *\n * Catalog of detected patterns (grounded in `.claude/rules/anti-patterns.md`):\n *\n * - `for-missing-by` — `<For each={...}>` without a `by` prop\n * - `for-with-key` — `<For key={...}>` (JSX reserves `key`; the keying\n * prop is `by` in Pyreon)\n * - `props-destructured` — `({ foo }: Props) => <JSX />` destructures at\n * the component signature; reading is captured once\n * and loses reactivity. Access `props.foo` instead\n * or use `splitProps(props, [...])`.\n * - `process-dev-gate` — `typeof process !== 'undefined' &&\n * process.env.NODE_ENV !== 'production'` is dead\n * code in real Vite browser bundles. Use\n * `import.meta.env?.DEV` instead.\n * - `empty-theme` — `.theme({})` chain is a no-op; remove it.\n * - `raw-add-event-listener` — raw `addEventListener(...)` in a component\n * or hook body. Use `useEventListener(...)` from\n * `@pyreon/hooks` for auto-cleanup.\n * - `raw-remove-event-listener` — same, for removeEventListener.\n * - `date-math-random-id` — `Date.now() + Math.random()` / template-concat\n * variants. Under rapid operations (paste, clone)\n * collision probability is non-trivial. Use a\n * monotonic counter.\n * - `on-click-undefined` — `onClick={undefined}` explicitly; the runtime\n * used to crash on this pattern. Omit the prop.\n *\n * Two-mode surface mirrors `react-intercept.ts`:\n * - `detectPyreonPatterns(code)` — diagnostics only\n * - `hasPyreonPatterns(code)` — fast regex pre-filter\n *\n * ## fixable: false (invariant)\n *\n * Every Pyreon diagnostic reports `fixable: false` — no exceptions.\n * The `migrate_react` MCP tool only knows React mappings, so claiming\n * a Pyreon code is auto-fixable would mislead a consumer who wires\n * their UX off the flag and finds nothing applies the fix. Flip to\n * `true` ONLY when a companion `migrate_pyreon` tool ships in a\n * subsequent PR. The invariant is locked in\n * `tests/pyreon-intercept.test.ts` under \"fixable contract\".\n *\n * Designed for three consumers:\n * 1. Compiler pre-pass warnings during build\n * 2. CLI `pyreon doctor`\n * 3. MCP server `validate` tool\n */\n\nimport ts from 'typescript'\n\n// ═══════════════════════════════════════════════════════════════════════════════\n// Types\n// ═══════════════════════════════════════════════════════════════════════════════\n\nexport type PyreonDiagnosticCode =\n | 'for-missing-by'\n | 'for-with-key'\n | 'props-destructured'\n | 'process-dev-gate'\n | 'empty-theme'\n | 'raw-add-event-listener'\n | 'raw-remove-event-listener'\n | 'date-math-random-id'\n | 'on-click-undefined'\n\nexport interface PyreonDiagnostic {\n /** Machine-readable code for filtering + programmatic handling */\n code: PyreonDiagnosticCode\n /** Human-readable message explaining the issue */\n message: string\n /** 1-based line number */\n line: number\n /** 0-based column */\n column: number\n /** The code as written */\n current: string\n /** The suggested Pyreon fix */\n suggested: string\n /** Whether a mechanical auto-fix is safe */\n fixable: boolean\n}\n\n// ═══════════════════════════════════════════════════════════════════════════════\n// Detection context\n// ═══════════════════════════════════════════════════════════════════════════════\n\ninterface DetectContext {\n sf: ts.SourceFile\n code: string\n diagnostics: PyreonDiagnostic[]\n}\n\nfunction getNodeText(ctx: DetectContext, node: ts.Node): string {\n return ctx.code.slice(node.getStart(ctx.sf), node.getEnd())\n}\n\nfunction pushDiag(\n ctx: DetectContext,\n node: ts.Node,\n code: PyreonDiagnosticCode,\n message: string,\n current: string,\n suggested: string,\n fixable: boolean,\n): void {\n const { line, character } = ctx.sf.getLineAndCharacterOfPosition(node.getStart(ctx.sf))\n ctx.diagnostics.push({\n code,\n message,\n line: line + 1,\n column: character,\n current: current.trim(),\n suggested: suggested.trim(),\n fixable,\n })\n}\n\n// ═══════════════════════════════════════════════════════════════════════════════\n// JSX helpers\n// ═══════════════════════════════════════════════════════════════════════════════\n\nfunction getJsxTagName(node: ts.JsxOpeningLikeElement): string {\n const t = node.tagName\n if (ts.isIdentifier(t)) return t.text\n return ''\n}\n\nfunction findJsxAttribute(\n node: ts.JsxOpeningLikeElement,\n name: string,\n): ts.JsxAttribute | undefined {\n for (const attr of node.attributes.properties) {\n if (ts.isJsxAttribute(attr) && ts.isIdentifier(attr.name) && attr.name.text === name) {\n return attr\n }\n }\n return undefined\n}\n\n// ═══════════════════════════════════════════════════════════════════════════════\n// Pattern: <For> without `by` / with `key`\n// ═══════════════════════════════════════════════════════════════════════════════\n\nfunction detectForKeying(ctx: DetectContext, node: ts.JsxOpeningLikeElement): void {\n if (getJsxTagName(node) !== 'For') return\n\n const keyAttr = findJsxAttribute(node, 'key')\n if (keyAttr) {\n pushDiag(\n ctx,\n keyAttr,\n 'for-with-key',\n '`key` on <For> is reserved by JSX for VNode reconciliation and is extracted before the prop reaches the runtime. In Pyreon, use `by` for list identity.',\n getNodeText(ctx, keyAttr),\n getNodeText(ctx, keyAttr).replace(/^key\\b/, 'by'),\n // fixable remains `false` until a `migrate_pyreon` tool exists —\n // today the MCP only ships `migrate_react`, so claiming auto-fix\n // here would mislead consumers building on the flag.\n false,\n )\n }\n\n const eachAttr = findJsxAttribute(node, 'each')\n const byAttr = findJsxAttribute(node, 'by')\n if (eachAttr && !byAttr && !keyAttr) {\n pushDiag(\n ctx,\n node,\n 'for-missing-by',\n '<For each={...}> requires a `by` prop so the keyed reconciler can preserve item identity across reorders. Without `by`, every update remounts the full list.',\n getNodeText(ctx, node),\n '<For each={items} by={(item) => item.id}>',\n false,\n )\n }\n}\n\n// ═══════════════════════════════════════════════════════════════════════════════\n// Pattern: destructured props in component signature\n// ═══════════════════════════════════════════════════════════════════════════════\n\nfunction containsJsx(node: ts.Node): boolean {\n let found = false\n function walk(n: ts.Node): void {\n if (found) return\n if (\n ts.isJsxElement(n) ||\n ts.isJsxSelfClosingElement(n) ||\n ts.isJsxFragment(n) ||\n ts.isJsxOpeningElement(n)\n ) {\n found = true\n return\n }\n ts.forEachChild(n, walk)\n }\n ts.forEachChild(node, walk)\n // Also allow expression-body arrow fns\n if (!found) {\n if (\n ts.isArrowFunction(node) &&\n !ts.isBlock(node.body) &&\n (ts.isJsxElement(node.body) ||\n ts.isJsxSelfClosingElement(node.body) ||\n ts.isJsxFragment(node.body))\n ) {\n found = true\n }\n }\n return found\n}\n\nfunction detectPropsDestructured(\n ctx: DetectContext,\n node: ts.ArrowFunction | ts.FunctionDeclaration | ts.FunctionExpression,\n): void {\n if (!node.parameters.length) return\n const first = node.parameters[0]\n if (!first || !ts.isObjectBindingPattern(first.name)) return\n if (first.name.elements.length === 0) return\n\n // Heuristic: only flag functions that actually render JSX (component\n // functions), not arbitrary callbacks that happen to destructure an\n // options bag.\n if (!containsJsx(node)) return\n\n pushDiag(\n ctx,\n first,\n 'props-destructured',\n 'Destructuring props at the component signature captures the values ONCE during setup — subsequent signal writes in the parent do not update the destructured locals. Access `props.x` directly, or use `splitProps(props, [...])` to carve out a group while preserving reactivity.',\n getNodeText(ctx, first),\n '(props: Props) => /* read props.x directly */',\n false,\n )\n}\n\n// ═══════════════════════════════════════════════════════════════════════════════\n// Pattern: typeof process !== 'undefined' && process.env.NODE_ENV !== 'production'\n// ═══════════════════════════════════════════════════════════════════════════════\n\nfunction isTypeofProcess(node: ts.Expression): boolean {\n if (!ts.isBinaryExpression(node)) return false\n if (node.operatorToken.kind !== ts.SyntaxKind.ExclamationEqualsEqualsToken) return false\n if (!ts.isTypeOfExpression(node.left)) return false\n if (!ts.isIdentifier(node.left.expression) || node.left.expression.text !== 'process') return false\n return ts.isStringLiteral(node.right) && node.right.text === 'undefined'\n}\n\nfunction isProcessNodeEnvProdGuard(node: ts.Expression): boolean {\n if (!ts.isBinaryExpression(node)) return false\n if (node.operatorToken.kind !== ts.SyntaxKind.ExclamationEqualsEqualsToken) return false\n // process.env.NODE_ENV\n const left = node.left\n if (!ts.isPropertyAccessExpression(left)) return false\n if (!ts.isIdentifier(left.name) || left.name.text !== 'NODE_ENV') return false\n if (!ts.isPropertyAccessExpression(left.expression)) return false\n if (\n !ts.isIdentifier(left.expression.name) ||\n left.expression.name.text !== 'env'\n ) {\n return false\n }\n if (!ts.isIdentifier(left.expression.expression)) return false\n if (left.expression.expression.text !== 'process') return false\n return ts.isStringLiteral(node.right) && node.right.text === 'production'\n}\n\nfunction detectProcessDevGate(ctx: DetectContext, node: ts.BinaryExpression): void {\n if (node.operatorToken.kind !== ts.SyntaxKind.AmpersandAmpersandToken) return\n // left: typeof process !== 'undefined', right: process.env.NODE_ENV !== 'production'\n // (or either side in either order)\n const match =\n (isTypeofProcess(node.left) && isProcessNodeEnvProdGuard(node.right)) ||\n (isTypeofProcess(node.right) && isProcessNodeEnvProdGuard(node.left))\n if (!match) return\n\n pushDiag(\n ctx,\n node,\n 'process-dev-gate',\n 'The `typeof process !== \"undefined\" && process.env.NODE_ENV !== \"production\"` gate is DEAD CODE in real Vite browser bundles — Vite does not polyfill `process`. Unit tests pass (vitest has `process`) but the warning never fires in production. Use `import.meta.env?.DEV` instead, which Vite literal-replaces at build time.',\n getNodeText(ctx, node),\n 'import.meta.env?.DEV === true',\n // No `migrate_pyreon` tool yet — claiming fixable would mislead.\n false,\n )\n}\n\n// ═══════════════════════════════════════════════════════════════════════════════\n// Pattern: .theme({}) empty chain\n// ═══════════════════════════════════════════════════════════════════════════════\n\nfunction detectEmptyTheme(ctx: DetectContext, node: ts.CallExpression): void {\n const callee = node.expression\n if (!ts.isPropertyAccessExpression(callee)) return\n if (!ts.isIdentifier(callee.name) || callee.name.text !== 'theme') return\n if (node.arguments.length !== 1) return\n const arg = node.arguments[0]\n if (!arg || !ts.isObjectLiteralExpression(arg)) return\n if (arg.properties.length !== 0) return\n\n pushDiag(\n ctx,\n node,\n 'empty-theme',\n '`.theme({})` is a no-op chain. If the component needs no base theme, skip `.theme()` entirely rather than calling it with an empty object.',\n getNodeText(ctx, node),\n getNodeText(ctx, callee.expression),\n // No `migrate_pyreon` tool yet — claiming fixable would mislead.\n false,\n )\n}\n\n// ═══════════════════════════════════════════════════════════════════════════════\n// Pattern: raw addEventListener / removeEventListener\n// ═══════════════════════════════════════════════════════════════════════════════\n\nfunction detectRawEventListener(ctx: DetectContext, node: ts.CallExpression): void {\n const callee = node.expression\n if (!ts.isPropertyAccessExpression(callee)) return\n if (!ts.isIdentifier(callee.name)) return\n const method = callee.name.text\n if (method !== 'addEventListener' && method !== 'removeEventListener') return\n\n // Only flag when the target is `window` / `document` / an identifier\n // that looks like a DOM element. Property-access chains (e.g.\n // `editor.dom.addEventListener`) are generally CodeMirror / framework\n // hosts — leave those alone.\n const target = callee.expression\n const targetName = ts.isIdentifier(target)\n ? target.text\n : ts.isPropertyAccessExpression(target) && ts.isIdentifier(target.name)\n ? target.name.text\n : ''\n\n const flagTargets = new Set(['window', 'document', 'body', 'el', 'element', 'node', 'target'])\n if (!flagTargets.has(targetName)) return\n\n if (method === 'addEventListener') {\n pushDiag(\n ctx,\n node,\n 'raw-add-event-listener',\n 'Raw `addEventListener` in a component / hook body bypasses Pyreon\\'s lifecycle cleanup — listeners leak on unmount. Use `useEventListener` from `@pyreon/hooks` for auto-cleanup.',\n getNodeText(ctx, node),\n 'useEventListener(target, event, handler)',\n false,\n )\n } else {\n pushDiag(\n ctx,\n node,\n 'raw-remove-event-listener',\n 'Raw `removeEventListener` is the symptom of manual listener management. Replace the paired `addEventListener` with `useEventListener` from `@pyreon/hooks` — it registers the cleanup automatically.',\n getNodeText(ctx, node),\n 'useEventListener(target, event, handler) // cleanup is automatic',\n false,\n )\n }\n}\n\n// ═══════════════════════════════════════════════════════════════════════════════\n// Pattern: Date.now() + Math.random() for IDs\n// ═══════════════════════════════════════════════════════════════════════════════\n\nfunction isCallTo(node: ts.Node, object: string, method: string): boolean {\n return (\n ts.isCallExpression(node) &&\n ts.isPropertyAccessExpression(node.expression) &&\n ts.isIdentifier(node.expression.expression) &&\n node.expression.expression.text === object &&\n ts.isIdentifier(node.expression.name) &&\n node.expression.name.text === method\n )\n}\n\nfunction subtreeHas(node: ts.Node, predicate: (n: ts.Node) => boolean): boolean {\n let found = false\n function walk(n: ts.Node): void {\n if (found) return\n if (predicate(n)) {\n found = true\n return\n }\n ts.forEachChild(n, walk)\n }\n walk(node)\n return found\n}\n\nfunction detectDateMathRandomId(ctx: DetectContext, node: ts.Expression): void {\n const hasDate = subtreeHas(node, (n) => isCallTo(n, 'Date', 'now'))\n if (!hasDate) return\n const hasRandom = subtreeHas(node, (n) => isCallTo(n, 'Math', 'random'))\n if (!hasRandom) return\n\n pushDiag(\n ctx,\n node,\n 'date-math-random-id',\n 'Combining `Date.now()` + `Math.random()` for unique IDs is collision-prone under rapid operations (paste, clone) — `Date.now()` returns the same value within a millisecond and `Math.random().toString(36).slice(2, 6)` has only ~1.67M combinations. Use a monotonic counter instead.',\n getNodeText(ctx, node),\n 'let _counter = 0; const nextId = () => String(++_counter)',\n false,\n )\n}\n\n// ═══════════════════════════════════════════════════════════════════════════════\n// Pattern: onClick={undefined}\n// ═══════════════════════════════════════════════════════════════════════════════\n\nfunction detectOnClickUndefined(ctx: DetectContext, node: ts.JsxAttribute): void {\n if (!ts.isIdentifier(node.name)) return\n const attrName = node.name.text\n if (!attrName.startsWith('on') || attrName.length < 3) return\n if (!node.initializer || !ts.isJsxExpression(node.initializer)) return\n const expr = node.initializer.expression\n if (!expr) return\n const isExplicitUndefined =\n (ts.isIdentifier(expr) && expr.text === 'undefined') ||\n expr.kind === ts.SyntaxKind.VoidExpression\n\n if (!isExplicitUndefined) return\n\n pushDiag(\n ctx,\n node,\n 'on-click-undefined',\n `\\`${attrName}={undefined}\\` explicitly passes undefined as a listener. Pyreon's runtime guards against this, but the cleanest pattern is to omit the attribute entirely or use a conditional: \\`${attrName}={condition ? handler : undefined}\\`.`,\n getNodeText(ctx, node),\n `/* omit ${attrName} when the handler is not defined */`,\n // No `migrate_pyreon` tool yet — claiming fixable would mislead.\n false,\n )\n}\n\n// ═══════════════════════════════════════════════════════════════════════════════\n// Visitor\n// ═══════════════════════════════════════════════════════════════════════════════\n\nfunction visitNode(ctx: DetectContext, node: ts.Node): void {\n if (ts.isJsxOpeningElement(node) || ts.isJsxSelfClosingElement(node)) {\n detectForKeying(ctx, node)\n }\n if (\n ts.isArrowFunction(node) ||\n ts.isFunctionDeclaration(node) ||\n ts.isFunctionExpression(node)\n ) {\n detectPropsDestructured(ctx, node)\n }\n if (ts.isBinaryExpression(node)) {\n detectProcessDevGate(ctx, node)\n detectDateMathRandomId(ctx, node)\n }\n if (ts.isTemplateExpression(node)) {\n detectDateMathRandomId(ctx, node)\n }\n if (ts.isCallExpression(node)) {\n detectEmptyTheme(ctx, node)\n detectRawEventListener(ctx, node)\n }\n if (ts.isJsxAttribute(node)) {\n detectOnClickUndefined(ctx, node)\n }\n}\n\nfunction visit(ctx: DetectContext, node: ts.Node): void {\n ts.forEachChild(node, (child) => {\n visitNode(ctx, child)\n visit(ctx, child)\n })\n}\n\n// ═══════════════════════════════════════════════════════════════════════════════\n// Public API\n// ═══════════════════════════════════════════════════════════════════════════════\n\nexport function detectPyreonPatterns(code: string, filename = 'input.tsx'): PyreonDiagnostic[] {\n const sf = ts.createSourceFile(filename, code, ts.ScriptTarget.ESNext, true, ts.ScriptKind.TSX)\n const ctx: DetectContext = { sf, code, diagnostics: [] }\n visit(ctx, sf)\n // Sort by (line, column) for stable ordering when multiple patterns fire.\n ctx.diagnostics.sort((a, b) => a.line - b.line || a.column - b.column)\n return ctx.diagnostics\n}\n\n/** Fast regex pre-filter — returns true if the code is worth a full AST walk. */\nexport function hasPyreonPatterns(code: string): boolean {\n return (\n /\\bFor\\b[^=]*\\beach\\s*=/.test(code) ||\n /\\btypeof\\s+process\\b/.test(code) ||\n /\\.theme\\s*\\(\\s*\\{\\s*\\}\\s*\\)/.test(code) ||\n /\\b(?:add|remove)EventListener\\s*\\(/.test(code) ||\n (/\\bDate\\.now\\s*\\(/.test(code) && /\\bMath\\.random\\s*\\(/.test(code)) ||\n /on[A-Z]\\w*\\s*=\\s*\\{\\s*undefined\\s*\\}/.test(code) ||\n /=\\s*\\(\\s*\\{[^}]+\\}\\s*[:)]/.test(code)\n )\n}\n","/**\n * Test-environment audit for the `audit_test_environment` MCP tool (T2.5.7).\n *\n * Scans `*.test.ts` / `*.test.tsx` files under the `packages` tree\n * for **mock-vnode patterns** — tests that construct `{ type, props,\n * children }` object literals (or a custom `vnode(...)` helper) in\n * place of going through the real `h()` from `@pyreon/core`. This\n * class of pattern silently drops rocketstyle / compiler / attrs\n * work from the pipeline, letting bugs through that production\n * would hit immediately (see PR #197 silent metadata drop).\n *\n * The scanner does NOT run the tests or parse TypeScript — a fast\n * regex pass is intentional. Accuracy trades for speed: the false-\n * positive rate is low because the `{ type: ..., props: ...,\n * children: ... }` shape is unusual outside of vnode construction.\n *\n * Output classification:\n * HIGH — mock patterns present, no real `h()` calls and no `h`\n * import from `@pyreon/core`. Most at risk: the file has\n * no pathway to exercise the real pipeline.\n * MEDIUM — mock patterns present, some real `h()` usage — but the\n * mock count is still notable, so a parallel real-`h()`\n * test may be missing for specific scenarios.\n * LOW — either no mocks, or mock count is dwarfed by real usage.\n *\n * Companion to the `validate` and `get_anti_patterns` tools: those\n * tell an agent what to write; this one tells an agent which existing\n * tests need strengthening.\n */\nimport { readdirSync, readFileSync, statSync } from 'node:fs'\nimport { dirname, join, relative, resolve } from 'node:path'\n\nexport type AuditRisk = 'high' | 'medium' | 'low'\n\nexport interface TestAuditEntry {\n /** Absolute path to the test file */\n path: string\n /** Path relative to the repo root for readable reporting */\n relPath: string\n /** Count of object-literal `{ type: ..., props: ..., children: ... }` patterns */\n mockVNodeLiteralCount: number\n /** Count of `vnode` / `mockVNode` / `createVNode` helper DEFINITIONS */\n mockHelperCount: number\n /**\n * Count of CALLS to a known mock-helper name. Captures pervasiveness:\n * a file with one helper definition and 50 call-sites has the same\n * `mockHelperCount` (1) as one with zero calls, but very different\n * exposure. This metric surfaces that.\n */\n mockHelperCallCount: number\n /** Count of lines that look like real `h(...)` calls (`h(Tag, props)` / `h(Component, ...)` shape) */\n realHCallCount: number\n /** True if the file imports `h` from `@pyreon/core` */\n importsH: boolean\n /** Risk classification */\n risk: AuditRisk\n}\n\nexport interface TestAuditResult {\n /** Repo root discovered by walking up for `packages/` */\n root: string | null\n /** Every test file scanned, sorted by risk (high → low) then path */\n entries: TestAuditEntry[]\n /** Total files scanned */\n totalScanned: number\n}\n\n// ═══════════════════════════════════════════════════════════════════════════════\n// Discovery\n// ═══════════════════════════════════════════════════════════════════════════════\n\nfunction findMonorepoRoot(startDir: string): string | null {\n let dir = resolve(startDir)\n for (let i = 0; i < 30; i++) {\n try {\n if (statSync(join(dir, 'packages')).isDirectory()) return dir\n } catch {\n // fall through to parent walk\n }\n const parent = dirname(dir)\n if (parent === dir) return null\n dir = parent\n }\n return null\n}\n\nfunction walkTestFiles(dir: string, out: string[], depth = 0): void {\n if (depth > 10) return\n let entries: string[]\n try {\n entries = readdirSync(dir)\n } catch {\n return\n }\n for (const name of entries) {\n if (name.startsWith('.')) continue\n if (name === 'node_modules' || name === 'lib' || name === 'dist') continue\n const full = join(dir, name)\n let isDir = false\n try {\n isDir = statSync(full).isDirectory()\n } catch {\n continue\n }\n if (isDir) {\n walkTestFiles(full, out, depth + 1)\n continue\n }\n if (/\\.test\\.(ts|tsx)$/.test(name)) {\n out.push(full)\n }\n }\n}\n\n// ═══════════════════════════════════════════════════════════════════════════════\n// Pattern detection\n// ═══════════════════════════════════════════════════════════════════════════════\n\n/**\n * Matches an object literal carrying `type`, `props`, AND `children`\n * keys — the canonical mock-vnode shape. The `s` flag spans newlines\n * because vnode literals often wrap across multiple lines.\n */\nconst MOCK_VNODE_LITERAL_PATTERN =\n /\\{\\s*type\\s*:[^{}]*?(?:(?:\\{[^{}]*\\})[^{}]*?)*?props\\s*:[^{}]*?(?:(?:\\{[^{}]*\\})[^{}]*?)*?children\\s*:[^{}]*?(?:(?:\\{[^{}]*\\})[^{}]*?)*?\\}/gs\n\n/**\n * Matches a helper definition that produces a mock vnode. Recognises:\n * const vnode = (...) => ({ type, props, children })\n * const mockVNode = ({ type, props, children })\n * function createVNode(type, props, children)\n *\n * Does NOT match bindings that merely STORE a real VNode with a\n * `vnode`-like name, which are common in component tests:\n * const vnode = defaultRender(...) // real render result\n * const vnode = <span>cell content</span> // real JSX expression\n * const vnode = h('div', null, 'x') // real h() call\n *\n * Distinguisher: a mock helper definition either\n * (a) starts an arrow function / function — RHS begins with `(` or the\n * keyword `function`, OR\n * (b) is itself an inline object literal — RHS begins with `{`.\n * `const vnode = <anything else>` is a binding, not a definition.\n */\nconst MOCK_HELPER_PATTERN =\n /(?:(?:const|let)\\s+(?:mockV[Nn]ode|vnode|createV[Nn]ode|V[Nn]odeMock|makeV[Nn]ode)\\s*=\\s*(?:\\(|\\{|function\\b|async\\s))|(?:function\\s+(?:mockV[Nn]ode|vnode|createV[Nn]ode|V[Nn]odeMock|makeV[Nn]ode)\\s*\\()/g\n\n/**\n * Matches CALLS to a known mock-helper name:\n * vnode('div', props, children)\n * mockVNode(Component, props)\n * createVNode(...)\n *\n * Non-word boundary before the name avoids hits inside other\n * identifiers (`hasVNode`, `myVnodeImpl`). The helper-def pattern\n * above ALSO matches definitions' own `<name>(` arg list, so the\n * caller should subtract definition count from call count to get\n * usage-only density — but for risk classification, the combined\n * signal (any mock-helper activity) is what we want.\n */\nconst MOCK_HELPER_CALL_PATTERN =\n /(?:^|[^a-zA-Z0-9_])(?:mockV[Nn]ode|vnode|createV[Nn]ode|V[Nn]odeMock|makeV[Nn]ode)\\s*\\(/g\n\n/**\n * Matches calls to `h(…)` where the first arg is an uppercase\n * identifier (component) or a lowercase string tag — the two real\n * shapes. Avoids matching:\n * hasSomething(...) — h followed by [a-z]\n * ch() — single h as substring of another name\n * hash() — same\n * The `(?:^|\\W)` boundary plus `[A-Z'\"\\s]` arg requirement handles both.\n */\nconst REAL_H_CALL_PATTERN = /(?:^|\\W)h\\s*\\(\\s*[\"'A-Z]/g\n\nconst IMPORT_H_PATTERN = /import\\s*(?:type\\s*)?\\{[^}]*\\bh\\b[^}]*\\}\\s*from\\s*['\"]@pyreon\\/core['\"]/\n\n/**\n * Predicate: does the `{type, props, children}` literal at this\n * position appear as an argument to a type-guard-like call\n * (`isDocNode(...)`, `hasVNode(...)`, `assertVNode(...)`, etc.)?\n *\n * Type guards take any object shape and return boolean — passing a\n * `{type, props, children}` literal there is testing the guard's\n * duck-typing, not building a mock vnode for a rendering pipeline.\n * False-positive coverage for `utils-coverage.test.ts` and similar.\n */\nfunction isLiteralInsideTypeGuardCall(source: string, literalStart: number): boolean {\n // Scan back ~60 chars from the literal for `(\\b(?:is|has|assert|validate|check)[A-Z]\\w*\\s*\\()`.\n // We're looking for a function-call opening paren that directly\n // contains this literal (no closer `)` in between).\n const window = source.slice(Math.max(0, literalStart - 60), literalStart)\n // The nearest `(` before the literal — count unmatched parens.\n let unmatched = 0\n let openAt = -1\n for (let i = window.length - 1; i >= 0; i--) {\n const ch = window[i]\n if (ch === ')') unmatched++\n else if (ch === '(') {\n if (unmatched === 0) {\n openAt = i\n break\n }\n unmatched--\n }\n }\n if (openAt < 0) return false\n // Is the token immediately before `openAt` an is*/has*/assert*/check*/validate* identifier?\n const head = window.slice(0, openAt)\n return /\\b(?:is|has|assert|validate|check)[A-Z]\\w*\\s*$/.test(head)\n}\n\n/**\n * Mask the inside of every backtick-delimited template-literal with\n * spaces. Preserves length so positions/lines/columns stay aligned.\n * Used to keep the literal scanner from counting `{type,props,children}`\n * patterns that live inside test FIXTURE strings (the `cli/doctor.test.ts`\n * case — those are fixtures for the audit tool itself, not actual code).\n *\n * Limitations: doesn't parse `${...}` interpolations precisely. If a\n * fixture contains a balanced `${ ... }` with code we'd want scanned,\n * the surrounding template string still masks it. In practice, mock-\n * vnode literals are never interpolation expressions, so this is fine.\n */\nfunction maskTemplateStrings(source: string): string {\n return source.replace(/`(?:\\\\.|[^`\\\\])*`/g, (m) => `\\`${' '.repeat(m.length - 2)}\\``)\n}\n\nfunction countMatches(source: string, pattern: RegExp): number {\n let count = 0\n pattern.lastIndex = 0\n while (pattern.exec(source) !== null) count++\n pattern.lastIndex = 0\n return count\n}\n\n/**\n * Counts `{type, props, children}` literals, skipping those that\n * appear inside a type-guard-looking call OR inside a template-literal\n * (which is fixture text, not code). Dedicated because the existing\n * `countMatches` helper has no context-aware skip.\n */\nfunction countMockVNodeLiterals(source: string): number {\n // First mask template-literal contents — fixtures inside backticks\n // (e.g. `\\`const v = { type, props, children }\\`` written via\n // writeFile in audit's own test) shouldn't count. The mask\n // preserves positions, so the type-guard skip logic still works.\n const masked = maskTemplateStrings(source)\n const pattern = MOCK_VNODE_LITERAL_PATTERN\n let count = 0\n pattern.lastIndex = 0\n let m: RegExpExecArray | null\n while (true) {\n m = pattern.exec(masked)\n if (m === null) break\n if (!isLiteralInsideTypeGuardCall(masked, m.index)) count++\n }\n pattern.lastIndex = 0\n return count\n}\n\nfunction classifyRisk(entry: Omit<TestAuditEntry, 'risk'>): AuditRisk {\n const mocks =\n entry.mockVNodeLiteralCount + entry.mockHelperCount + entry.mockHelperCallCount\n if (mocks === 0) return 'low'\n if (!entry.importsH && entry.realHCallCount === 0) return 'high'\n if (entry.realHCallCount >= mocks) return 'low'\n return 'medium'\n}\n\n// ═══════════════════════════════════════════════════════════════════════════════\n// Public API\n// ═══════════════════════════════════════════════════════════════════════════════\n\nexport function auditTestEnvironment(startDir: string): TestAuditResult {\n // Caller-supplied `startDir` (no default) — `runtime-dom` transitively\n // pulls this file via the `@pyreon/compiler` JSX runtime entry, and its\n // tsconfig narrows `process` to `{ env: ... }` only. Calling\n // `process.cwd()` here breaks that typecheck. MCP / CLI both have full\n // node types; let them resolve cwd at the call site.\n const root = findMonorepoRoot(startDir)\n if (!root) return { root: null, entries: [], totalScanned: 0 }\n\n const files: string[] = []\n walkTestFiles(join(root, 'packages'), files)\n\n const entries: TestAuditEntry[] = []\n for (const path of files) {\n let source: string\n try {\n source = readFileSync(path, 'utf8')\n } catch {\n continue\n }\n // Skip the scanner's own test fixtures so `audit_test_environment`\n // doesn't report itself.\n if (path.includes('test-audit.test.ts') || path.includes('test-audit-fixture')) {\n continue\n }\n\n // Mask template-literal contents once, then run every counter\n // against the masked source. Patterns inside backticks are\n // FIXTURE strings (the audit tool's own test fixtures, doctest\n // examples, etc.) — they shouldn't count toward any metric.\n // `countMockVNodeLiterals` already does its own masking and runs\n // on `source` so it can do its own work; we pass `source` to\n // keep that contract intact.\n const masked = maskTemplateStrings(source)\n const mockVNodeLiteralCount = countMockVNodeLiterals(source)\n const mockHelperCount = countMatches(masked, MOCK_HELPER_PATTERN)\n const mockHelperCallCount = countMatches(masked, MOCK_HELPER_CALL_PATTERN)\n const realHCallCount = countMatches(masked, REAL_H_CALL_PATTERN)\n const importsH = IMPORT_H_PATTERN.test(masked)\n\n const base = {\n path,\n relPath: relative(root, path),\n mockVNodeLiteralCount,\n mockHelperCount,\n mockHelperCallCount,\n realHCallCount,\n importsH,\n }\n entries.push({ ...base, risk: classifyRisk(base) })\n }\n\n const riskRank = { high: 0, medium: 1, low: 2 }\n entries.sort((a, b) => {\n const cmp = riskRank[a.risk] - riskRank[b.risk]\n if (cmp !== 0) return cmp\n return a.relPath.localeCompare(b.relPath)\n })\n\n return { root, entries, totalScanned: files.length }\n}\n\n// ═══════════════════════════════════════════════════════════════════════════════\n// Formatter\n// ═══════════════════════════════════════════════════════════════════════════════\n\nexport interface AuditFormatOptions {\n /** Only include entries at or above this risk level. Default 'medium'. */\n minRisk?: AuditRisk | undefined\n /** Maximum entries to show per risk group. Default 20. */\n limit?: number | undefined\n}\n\nfunction riskAtOrAbove(risk: AuditRisk, min: AuditRisk): boolean {\n const rank = { high: 0, medium: 1, low: 2 }\n return rank[risk] <= rank[min]\n}\n\nexport function formatTestAudit(\n result: TestAuditResult,\n { minRisk = 'medium', limit = 20 }: AuditFormatOptions = {},\n): string {\n if (!result.root) {\n return (\n 'No monorepo root found. This tool scans `packages/**/*.test.{ts,tsx}` ' +\n 'for mock-vnode patterns. Run the MCP from the Pyreon repo root to ' +\n 'get useful output.'\n )\n }\n\n const relevant = result.entries.filter((e) => riskAtOrAbove(e.risk, minRisk))\n const counts = {\n high: result.entries.filter((e) => e.risk === 'high').length,\n medium: result.entries.filter((e) => e.risk === 'medium').length,\n low: result.entries.filter((e) => e.risk === 'low').length,\n }\n const withMocks = result.entries.filter(\n (e) => e.mockVNodeLiteralCount + e.mockHelperCount > 0,\n ).length\n\n const parts: string[] = []\n parts.push(`# Test environment audit — ${result.totalScanned} test files scanned`)\n parts.push('')\n parts.push(\n `**Mock-vnode exposure**: ${withMocks} / ${result.totalScanned} files construct \\`{ type, props, children }\\` literals or a custom \\`vnode()\\` helper instead of going through the real \\`h()\\` from \\`@pyreon/core\\`. This is the bug class that caused PR #197's silent metadata drop — mock-only tests pass while the real pipeline (rocketstyle attrs, compiler transforms, props forwarding) stays unexercised.`,\n )\n parts.push('')\n parts.push(`**Risk counts**: ${counts.high} high · ${counts.medium} medium · ${counts.low} low`)\n parts.push('')\n\n if (relevant.length === 0) {\n parts.push(`No files at risk level \"${minRisk}\" or above. Every test file either avoids mocks entirely or pairs them with real-\\`h()\\` coverage.`)\n return parts.join('\\n')\n }\n\n const byRisk = new Map<AuditRisk, TestAuditEntry[]>()\n for (const entry of relevant) {\n if (!byRisk.has(entry.risk)) byRisk.set(entry.risk, [])\n byRisk.get(entry.risk)!.push(entry)\n }\n\n for (const [risk, group] of byRisk) {\n const shown = group.slice(0, limit)\n parts.push(`## ${risk.toUpperCase()} — ${group.length} file${group.length === 1 ? '' : 's'}${shown.length < group.length ? ` (showing ${shown.length})` : ''}`)\n parts.push('')\n parts.push(describeRisk(risk))\n parts.push('')\n for (const entry of shown) {\n const mocks =\n entry.mockVNodeLiteralCount + entry.mockHelperCount + entry.mockHelperCallCount\n const breakdown: string[] = []\n if (entry.mockVNodeLiteralCount > 0) breakdown.push(`${entry.mockVNodeLiteralCount} literal${entry.mockVNodeLiteralCount === 1 ? '' : 's'}`)\n if (entry.mockHelperCount > 0) breakdown.push(`${entry.mockHelperCount} helper${entry.mockHelperCount === 1 ? '' : 's'}`)\n if (entry.mockHelperCallCount > 0) breakdown.push(`${entry.mockHelperCallCount} helper call${entry.mockHelperCallCount === 1 ? '' : 's'}`)\n const hSide =\n entry.realHCallCount > 0\n ? `${entry.realHCallCount} real h() call${entry.realHCallCount === 1 ? '' : 's'}`\n : entry.importsH\n ? `imports h but 0 calls found`\n : `no h import`\n parts.push(`- ${entry.relPath} — ${mocks} mock signal${mocks === 1 ? '' : 's'} (${breakdown.join(' + ')}), ${hSide}`)\n }\n parts.push('')\n }\n\n parts.push('---')\n parts.push('')\n parts.push(\n 'Fix: for each HIGH file, add at least one test that imports `h` from `@pyreon/core` and renders the actual component through `h(RealComponent, props)`. The mock version can stay for speed — it is the LACK of a real-`h()` parallel that blocks bug surfacing.',\n )\n return parts.join('\\n')\n}\n\nfunction describeRisk(risk: AuditRisk): string {\n if (risk === 'high') {\n return 'Mock patterns present, no real `h()` calls, and no `h` import from `@pyreon/core`. The file has no pathway to exercise the real pipeline — bugs like PR #197 would slip through.'\n }\n if (risk === 'medium') {\n return 'Mock patterns present AND some real `h()` usage — but mocks outnumber real calls, so specific scenarios may be mock-only. Spot-check that each contract the tests assert on goes through at least one real-`h()` path.'\n }\n return 'Mocks dwarfed by real usage OR no mocks at all — low risk.'\n}\n"],"mappings":"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"}
|