feat(dx): dev-mode warning for unbalanced template tags (#1769) - #1770
Merged
Conversation
A single dropped closing tag (e.g. a missing </div>) is silently auto-closed at EOF, re-parenting every following sibling inside the unclosed element — which then inherits its x-show/display:none and renders blank, with zero diagnostics at any layer (server 200s, hydration succeeds, no console output). Add a coarse, void- and optional-close-aware open/close COUNT per tag name, run on the RAW template of views/layouts (in processDirectives) and @include'd partials (in the include pipeline), that warns on a mismatch, e.g.: [stx] SettingsTab.stx: <div> 47 opened, 46 closed — an unclosed <div> (first opened at line 771) may swallow the content that follows it. - New template-tag-balance module: pure findUnbalancedTags() + warnUnbalancedTags(). Ignores void elements, optional-close elements (li/td/p/...), self-closing components, and tags inside scripts/styles/comments/interpolations/attributes, so it stays false-positive-free. - On by default in development; opt-in via 'debug' elsewhere; off in the prod build and under the test runner (so it never adds noise to CI or the bundle). - Deduped per file so a broken file warns once, re-arming on edit. 14 new tests; full suite green (7810 pass, 0 fail).
❌ Deploy Preview for stacks-stx failed. Why did it fail? →
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #1769.
The problem
A single dropped closing tag (a missing
</div>) is silently auto-closed by the HTML parser at EOF, re-parenting every following sibling inside the unclosed element. Those siblings inherit itsx-show/display:noneand render blank — with zero diagnostics at any layer: the server 200s, hydration succeeds, no console output. It's only visible by eye (or by walkinggetComputedStyleup the ancestor chain).The fix
A coarse, void- and optional-close-aware open/close count per tag name, run at template-parse time and warning on any mismatch:
template-tag-balance.ts— a small module: purefindUnbalancedTags()(fully unit-tested) +warnUnbalancedTags(). It's deliberately a count, not a parse — the goal is a cheap, high-signal heads-up.processDirectiveson the raw template of views/layouts, and the include pipeline on each@included partial's raw content (the issue's exact case — a tab component). Both check the RAW source before any processing auto-closes tags.debugelsewhere (options.debug || (!isProduction() && !isTest())). Off in the production build and under the test runner, so it never adds noise to CI or the shipped bundle. Deduped per file (warns once; re-arms on edit).False-positive-free by design
It ignores, and there are tests for each: void elements (
<br>,<img>, …), optional-close elements (<li>,<td>,<p>, …), self-closing components (<Icon />), and any</>inside<script>/<style>/comments/{{ }}interpolations/quoted attribute values. Component tags (<StxLink>…</StxLink>) are checked case-preserved, so an unbalanced component is caught too.Verification
test/template-tag-balance.test.ts): the pure counter across all the edge cases above,warnUnbalancedTagsmessage/dedupe, and aprocessDirectivesintegration test confirming the hook fires in dev and stays quiet otherwise.NODE_ENV=developmentwith nodebugflag; silent inNODE_ENV=production.Notes for review
debugdefaults tofalse). Easy to flip todebug-only if you'd rather it be opt-in.