Add <%br= %> jqhtml syntax docs, class override detection, npm update
Document event handler placement and model fetch clarification 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
39
node_modules/@jqhtml/parser/dist/parser.js
generated
vendored
39
node_modules/@jqhtml/parser/dist/parser.js
generated
vendored
@@ -242,9 +242,10 @@ export class Parser {
|
||||
const token = this.previous();
|
||||
return createNode(NodeType.TEXT, { content: token.value }, token.start, token.end, token.line, token.column, this.create_location(token, token));
|
||||
}
|
||||
// Expression <%= ... %> or <%!= ... %>
|
||||
// Expression <%= ... %> or <%!= ... %> or <%br= ... %>
|
||||
if (this.match(TokenType.EXPRESSION_START) ||
|
||||
this.match(TokenType.EXPRESSION_UNESCAPED)) {
|
||||
this.match(TokenType.EXPRESSION_UNESCAPED) ||
|
||||
this.match(TokenType.EXPRESSION_BR)) {
|
||||
return this.parse_expression();
|
||||
}
|
||||
// Code block <% ... %>
|
||||
@@ -270,16 +271,22 @@ export class Parser {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
// Parse <%= expression %> or <%!= expression %>
|
||||
// Parse <%= expression %> or <%!= expression %> or <%br= expression %>
|
||||
parse_expression() {
|
||||
const start_token = this.previous(); // EXPRESSION_START or EXPRESSION_UNESCAPED
|
||||
const start_token = this.previous(); // EXPRESSION_START, EXPRESSION_UNESCAPED, or EXPRESSION_BR
|
||||
const code_token = this.consume(TokenType.JAVASCRIPT, 'Expected JavaScript code');
|
||||
// Validate JavaScript code for common mistakes
|
||||
this.validate_javascript_code(code_token.value, code_token);
|
||||
const end_token = this.consume(TokenType.TAG_END, 'Expected %>');
|
||||
// EXPRESSION_START and EXPRESSION_BR are escaped, EXPRESSION_UNESCAPED is not
|
||||
const is_escaped = start_token.type === TokenType.EXPRESSION_START ||
|
||||
start_token.type === TokenType.EXPRESSION_BR;
|
||||
// Only EXPRESSION_BR converts newlines to <br />
|
||||
const is_nl2br = start_token.type === TokenType.EXPRESSION_BR;
|
||||
return createNode(NodeType.EXPRESSION, {
|
||||
code: code_token.value,
|
||||
escaped: start_token.type === TokenType.EXPRESSION_START
|
||||
escaped: is_escaped,
|
||||
nl2br: is_nl2br
|
||||
}, start_token.start, end_token.end, start_token.line, start_token.column, this.create_location(start_token, end_token));
|
||||
}
|
||||
// Parse <% code %> - collect tokens with their types for proper transformation
|
||||
@@ -529,7 +536,8 @@ export class Parser {
|
||||
// Check if this is a compound value with interpolation
|
||||
if (this.check(TokenType.ATTR_VALUE) ||
|
||||
this.check(TokenType.EXPRESSION_START) ||
|
||||
this.check(TokenType.EXPRESSION_UNESCAPED)) {
|
||||
this.check(TokenType.EXPRESSION_UNESCAPED) ||
|
||||
this.check(TokenType.EXPRESSION_BR)) {
|
||||
value = this.parse_attribute_value();
|
||||
}
|
||||
}
|
||||
@@ -618,11 +626,13 @@ export class Parser {
|
||||
const firstToken = this.peek();
|
||||
const isSimpleValue = this.check(TokenType.ATTR_VALUE) &&
|
||||
!this.check_ahead(1, TokenType.EXPRESSION_START) &&
|
||||
!this.check_ahead(1, TokenType.EXPRESSION_UNESCAPED);
|
||||
!this.check_ahead(1, TokenType.EXPRESSION_UNESCAPED) &&
|
||||
!this.check_ahead(1, TokenType.EXPRESSION_BR);
|
||||
// Collect all parts of the attribute value
|
||||
while (this.check(TokenType.ATTR_VALUE) ||
|
||||
this.check(TokenType.EXPRESSION_START) ||
|
||||
this.check(TokenType.EXPRESSION_UNESCAPED)) {
|
||||
this.check(TokenType.EXPRESSION_UNESCAPED) ||
|
||||
this.check(TokenType.EXPRESSION_BR)) {
|
||||
if (this.check(TokenType.ATTR_VALUE)) {
|
||||
const token = this.advance();
|
||||
// Preserve whitespace in interpolated attribute values - spaces between
|
||||
@@ -633,12 +643,15 @@ export class Parser {
|
||||
}
|
||||
}
|
||||
else if (this.check(TokenType.EXPRESSION_START) ||
|
||||
this.check(TokenType.EXPRESSION_UNESCAPED)) {
|
||||
const is_escaped = this.peek().type === TokenType.EXPRESSION_START;
|
||||
this.advance(); // consume <%= or <%!=
|
||||
this.check(TokenType.EXPRESSION_UNESCAPED) ||
|
||||
this.check(TokenType.EXPRESSION_BR)) {
|
||||
const token_type = this.peek().type;
|
||||
const is_escaped = token_type === TokenType.EXPRESSION_START || token_type === TokenType.EXPRESSION_BR;
|
||||
const is_nl2br = token_type === TokenType.EXPRESSION_BR;
|
||||
this.advance(); // consume <%=, <%!=, or <%br=
|
||||
const expr_token = this.consume(TokenType.JAVASCRIPT, 'Expected expression');
|
||||
this.consume(TokenType.TAG_END, 'Expected %>');
|
||||
parts.push({ type: 'expression', value: expr_token.value, escaped: is_escaped });
|
||||
parts.push({ type: 'expression', value: expr_token.value, escaped: is_escaped, nl2br: is_nl2br });
|
||||
}
|
||||
}
|
||||
// If it's a single text part, check if it's quoted
|
||||
@@ -769,7 +782,7 @@ export class Parser {
|
||||
const token = this.peek();
|
||||
// Special case: Detecting template expressions inside HTML tag attributes
|
||||
if (type === TokenType.GT &&
|
||||
(token.type === TokenType.EXPRESSION_START || token.type === TokenType.EXPRESSION_UNESCAPED)) {
|
||||
(token.type === TokenType.EXPRESSION_START || token.type === TokenType.EXPRESSION_UNESCAPED || token.type === TokenType.EXPRESSION_BR)) {
|
||||
const error = syntaxError('Template expressions (<% %>) cannot be used as attribute values inside HTML tags', token.line, token.column, this.source, this.filename);
|
||||
// Add helpful remediation examples
|
||||
error.message += '\n\n' +
|
||||
|
||||
Reference in New Issue
Block a user