Fix code quality violations and enhance ROUTE-EXISTS-01 rule
Implement JQHTML function cache ID system and fix bundle compilation Implement underscore prefix for system tables Fix JS syntax linter to support decorators and grant exception to Task system SPA: Update planning docs and wishlists with remaining features SPA: Document Navigation API abandonment and future enhancements Implement SPA browser integration with History API (Phase 1) Convert contacts view page to SPA action Convert clients pages to SPA actions and document conversion procedure SPA: Merge GET parameters and update documentation Implement SPA route URL generation in JavaScript and PHP Implement SPA bootstrap controller architecture Add SPA routing manual page (rsx:man spa) Add SPA routing documentation to CLAUDE.md Phase 4 Complete: Client-side SPA routing implementation Update get_routes() consumers for unified route structure Complete SPA Phase 3: PHP-side route type detection and is_spa flag Restore unified routes structure and Manifest_Query class Refactor route indexing and add SPA infrastructure Phase 3 Complete: SPA route registration in manifest Implement SPA Phase 2: Extract router code and test decorators Rename Jqhtml_Component to Component and complete SPA foundation setup 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
136
node_modules/@jqhtml/parser/dist/parser.js
generated
vendored
136
node_modules/@jqhtml/parser/dist/parser.js
generated
vendored
@@ -302,113 +302,6 @@ export class Parser {
|
||||
return createNode(NodeType.CODE_BLOCK, { tokens }, // Pass tokens array instead of concatenated code
|
||||
start_token.start, end_token.end, start_token.line, start_token.column, this.create_location(start_token, end_token));
|
||||
}
|
||||
// Parse if statement with colon style only
|
||||
parse_if_statement(start_token) {
|
||||
console.log('[Parser] Parsing if statement at line', start_token.line);
|
||||
this.consume(TokenType.IF, 'Expected if');
|
||||
const condition_token = this.consume(TokenType.JAVASCRIPT, 'Expected condition');
|
||||
console.log('[Parser] If condition:', condition_token.value);
|
||||
this.consume(TokenType.TAG_END, 'Expected %>');
|
||||
const consequent = [];
|
||||
let alternate = null;
|
||||
// Parse consequent branch
|
||||
while (!this.check_sequence(TokenType.CODE_START, TokenType.ELSE) &&
|
||||
!this.check_sequence(TokenType.CODE_START, TokenType.ENDIF)) {
|
||||
if (this.is_at_end()) {
|
||||
const error = unclosedError('if statement', `if (${condition_token.value})`, start_token.line, start_token.column, this.source, this.filename);
|
||||
error.message += getSuggestion(error.message);
|
||||
throw error;
|
||||
}
|
||||
const node = this.parse_content();
|
||||
if (node) {
|
||||
consequent.push(node);
|
||||
}
|
||||
}
|
||||
// Check for else branch
|
||||
if (this.check_sequence(TokenType.CODE_START, TokenType.ELSE)) {
|
||||
console.log('[Parser] Found else branch');
|
||||
this.advance(); // CODE_START
|
||||
this.advance(); // ELSE
|
||||
// Check if this is an "else if"
|
||||
if (this.check(TokenType.IF)) {
|
||||
console.log('[Parser] This is an else if statement');
|
||||
// This is an else if - put back the ELSE token and parse as new if statement
|
||||
this.current--; // Put back ELSE
|
||||
this.current--; // Put back CODE_START
|
||||
// Parse the else if as a new if statement
|
||||
alternate = [];
|
||||
const elseIfNode = this.parse_content();
|
||||
if (elseIfNode) {
|
||||
alternate.push(elseIfNode);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Regular else branch
|
||||
// Skip optional trailing code
|
||||
if (this.check(TokenType.JAVASCRIPT)) {
|
||||
this.advance();
|
||||
}
|
||||
this.consume(TokenType.TAG_END, 'Expected %>');
|
||||
alternate = [];
|
||||
// Parse else branch
|
||||
while (!this.check_sequence(TokenType.CODE_START, TokenType.ENDIF)) {
|
||||
if (this.is_at_end()) {
|
||||
const error = unclosedError('if statement (in else branch)', `if (${condition_token.value})`, start_token.line, start_token.column, this.source, this.filename);
|
||||
error.message += getSuggestion(error.message);
|
||||
throw error;
|
||||
}
|
||||
const node = this.parse_content();
|
||||
if (node) {
|
||||
alternate.push(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Consume endif
|
||||
this.consume(TokenType.CODE_START, 'Expected <%');
|
||||
this.consume(TokenType.ENDIF, 'Expected endif');
|
||||
// Skip optional semicolon
|
||||
if (this.check(TokenType.JAVASCRIPT)) {
|
||||
this.advance();
|
||||
}
|
||||
const end_token = this.consume(TokenType.TAG_END, 'Expected %>');
|
||||
return createNode(NodeType.IF_STATEMENT, {
|
||||
condition: condition_token.value,
|
||||
consequent,
|
||||
alternate
|
||||
}, start_token.start, end_token.end, start_token.line, start_token.column, this.create_location(start_token, end_token));
|
||||
}
|
||||
// Parse for loop
|
||||
parse_for_statement(start_token) {
|
||||
this.consume(TokenType.FOR, 'Expected for');
|
||||
const iterator_token = this.consume(TokenType.JAVASCRIPT, 'Expected iterator expression');
|
||||
this.consume(TokenType.TAG_END, 'Expected %>');
|
||||
const body = [];
|
||||
// Parse loop body
|
||||
while (!this.check_sequence(TokenType.CODE_START, TokenType.ENDFOR)) {
|
||||
if (this.is_at_end()) {
|
||||
const error = unclosedError('for statement', `for ${iterator_token.value}`, start_token.line, start_token.column, this.source, this.filename);
|
||||
error.message += getSuggestion(error.message);
|
||||
throw error;
|
||||
}
|
||||
const node = this.parse_content();
|
||||
if (node) {
|
||||
body.push(node);
|
||||
}
|
||||
}
|
||||
// Consume endfor
|
||||
this.consume(TokenType.CODE_START, 'Expected <%');
|
||||
this.consume(TokenType.ENDFOR, 'Expected endfor');
|
||||
// Skip optional semicolon
|
||||
if (this.check(TokenType.JAVASCRIPT)) {
|
||||
this.advance();
|
||||
}
|
||||
const end_token = this.consume(TokenType.TAG_END, 'Expected %>');
|
||||
return createNode(NodeType.FOR_STATEMENT, {
|
||||
iterator: iterator_token.value,
|
||||
body
|
||||
}, start_token.start, end_token.end, start_token.line, start_token.column, this.create_location(start_token, end_token));
|
||||
}
|
||||
// JavaScript reserved words that cannot be used as slot names
|
||||
static JAVASCRIPT_RESERVED_WORDS = new Set([
|
||||
// Keywords
|
||||
@@ -642,10 +535,12 @@ export class Parser {
|
||||
}
|
||||
// Handle special attribute prefixes
|
||||
if (name.startsWith('$')) {
|
||||
// General case: $property becomes data-property
|
||||
// This includes $id → data-id (for scoped IDs)
|
||||
// The distinction between data-id (scoped) and id (pass-through) is preserved
|
||||
name = 'data-' + name.substring(1);
|
||||
// Special case: $id becomes data-id (needed for scoped ID system)
|
||||
// All other $ attributes stay as-is (handled by instruction-processor.ts)
|
||||
if (name === '$id') {
|
||||
name = 'data-id';
|
||||
}
|
||||
// Keep $ prefix for other attributes - they get stored via .data() at runtime
|
||||
// Keep the value object intact to preserve quoted/unquoted distinction
|
||||
}
|
||||
else if (name.startsWith(':')) {
|
||||
@@ -655,9 +550,9 @@ export class Parser {
|
||||
// Keep the value object intact to preserve quoted/unquoted distinction
|
||||
}
|
||||
else if (name.startsWith('@')) {
|
||||
// Event binding: @click="handler" becomes data-on-click
|
||||
// Event binding: @click="handler" becomes data-__-on-click
|
||||
// Preserve whether value was quoted or not for proper code generation
|
||||
name = 'data-on-' + name.substring(1);
|
||||
name = 'data-__-on-' + name.substring(1);
|
||||
// Keep the value object intact to preserve quoted/unquoted distinction
|
||||
}
|
||||
attributes[name] = value;
|
||||
@@ -674,11 +569,8 @@ export class Parser {
|
||||
// Consume <%
|
||||
this.consume(TokenType.CODE_START, 'Expected <%');
|
||||
let condition;
|
||||
// Two possibilities:
|
||||
// 1. Brace style: CODE_START → JAVASCRIPT "if (condition) {" → TAG_END
|
||||
// 2. Colon style: CODE_START → IF → JAVASCRIPT "(condition)" → TAG_END
|
||||
// Only brace style supported: CODE_START → JAVASCRIPT "if (condition) {" → TAG_END
|
||||
if (this.check(TokenType.JAVASCRIPT)) {
|
||||
// Brace style
|
||||
const jsToken = this.consume(TokenType.JAVASCRIPT, 'Expected if statement');
|
||||
const jsCode = jsToken.value.trim();
|
||||
// Verify it starts with 'if' and contains both ( and {
|
||||
@@ -694,12 +586,6 @@ export class Parser {
|
||||
// Extract just the condition part (between parens, including parens)
|
||||
condition = jsCode.substring(openParen, closeBrace).trim();
|
||||
}
|
||||
else if (this.check(TokenType.IF)) {
|
||||
// Colon style
|
||||
this.advance(); // consume 'if'
|
||||
const jsToken = this.consume(TokenType.JAVASCRIPT, 'Expected condition after if');
|
||||
condition = jsToken.value.trim();
|
||||
}
|
||||
else {
|
||||
// Not an if statement
|
||||
throw syntaxError('Only if statements are allowed in attribute context. Use <% if (condition) { %>attr="value"<% } %>', this.peek().line, this.peek().column, this.source);
|
||||
@@ -783,8 +669,8 @@ export class Parser {
|
||||
// Return as an identifier expression (function call chain)
|
||||
return { identifier: true, value: value };
|
||||
}
|
||||
// Otherwise, treat as a literal string value
|
||||
return value;
|
||||
// Otherwise, treat as a JavaScript expression (includes numeric literals like 42, 3.14, etc.)
|
||||
return { expression: true, value: value };
|
||||
}
|
||||
// Any expression or multiple parts needs interpolation handling
|
||||
return { interpolated: true, parts };
|
||||
|
||||
Reference in New Issue
Block a user