Skip to content

Extract rule: template-table-groups#2623

Merged
NullVoxPopuli merged 1 commit intoember-cli:masterfrom
NullVoxPopuli:nvp/template-lint-extract-rule-template-table-groups
Mar 19, 2026
Merged

Extract rule: template-table-groups#2623
NullVoxPopuli merged 1 commit intoember-cli:masterfrom
NullVoxPopuli:nvp/template-lint-extract-rule-template-table-groups

Conversation

@NullVoxPopuli
Copy link
Copy Markdown
Contributor

Split from #2371.

Copy link
Copy Markdown

@NullVoxPopuli-ai-agent NullVoxPopuli-ai-agent left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review: template-table-groups

Compared against ember-template-lint table-groups.js.

General Correctness

  1. Faithful port: This is a complex rule and the port does a thorough job. The core logic -- checking that <table> elements only contain allowed table grouping children (caption, colgroup, thead, tbody, tfoot) in the correct order, with control flow transparency -- is well implemented.

  2. Empty table handling: The port adds special handling for truly empty tables (lines 279-288) by parsing the source text to detect self-closing-like patterns. The original ETL rule does NOT have this explicit check -- it would just iterate over an empty children array and not report. This means the ESLint port is stricter than the original for empty <table></table>. In the original, <table></table> would not trigger an error because the children array is empty and the loop simply doesn't execute. Verify whether this added strictness is intentional.

  3. dasherize function: The port implements its own dasherize() using regex. The original imports dasherizeComponentName from a helper. The port's implementation converts :: to / and camelCase to kebab-case, which matches the expected behavior for Ember component name conversion. Looks correct.

  4. isControlFlowHelper list: The port includes ['if', 'unless', 'each', 'each-in', 'let', 'with'], which matches the original's AstNodeInfo.isControlFlowHelper(). Good.

  5. Control flow scoping for if/unless branches: The original uses scopedIndices as a stack and, on CONTROL_FLOW_START_MARK, creates a new set by reducing all scoped indices. The ESLint port instead creates a copy of just the current set: new Set(currentAllowedMinimumIndices). This is a behavioral difference from the original. The original merges ALL parent scopes into the new scope, while the port only copies the current scope. For nested control flow with if/else branches, this could produce different results. Consider aligning with the original's reduce approach.

  6. Tests: Excellent coverage -- 893 lines of tests covering valid/invalid cases, control flow, ordering, custom component mappings via options, and both gjs and hbs modes. The test suite is comprehensive and well-structured.

  7. Schema alignment: The schema correctly uses the same allowed-*-components keys as the original's configuration. Good.

Scope Analysis (gjs/gts)

This rule checks structural properties: HTML tag names (table, thead, etc.), attribute names (@tagName), and control flow helper names (if, unless, each, etc.). It also checks node.path?.original === 'yield' for the {{yield}} keyword. All of these are Ember built-in keywords or HTML structural elements. No scope analysis needed -- shadowing yield, if, unless, etc. in JS would be extremely unusual and not a realistic concern.


🤖 Automated review comparing with ember-template-lint source

@NullVoxPopuli NullVoxPopuli merged commit c9d988f into ember-cli:master Mar 19, 2026
9 checks passed
@NullVoxPopuli NullVoxPopuli deleted the nvp/template-lint-extract-rule-template-table-groups branch March 19, 2026 17:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants