Skip to content

Commit 328fe90

Browse files
author
Peter Stenger
committed
chore: release 1.3.4
1 parent 4f57ff1 commit 328fe90

6 files changed

Lines changed: 42 additions & 10 deletions

File tree

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,7 @@ Create a `.htmlmustache.jsonc` file in your project root to configure formatting
306306
```
307307

308308
The schema URL above tracks `main`. For release-pinned validation, replace
309-
`main` with a tag such as `v1.3.3`.
309+
`main` with a tag such as `v1.3.4`.
310310

311311
### Lint Rules
312312

@@ -538,7 +538,7 @@ export const validators = defineTagValidators('pl-order-blocks', {
538538
});
539539
```
540540

541-
`element.children` contains one level of direct child HTML elements. Mustache sections are transparent, so children inside `{{#section}}...{{/section}}` are included. Child facades expose their tag and attributes, but their own `children` arrays are empty. `element.innerHtml` is present only when the validator opts into `options.includeInnerHtml`.
541+
`element.children` contains direct child HTML elements. Mustache sections are transparent, so children inside `{{#section}}...{{/section}}` are included. Child facades are populated recursively, so validators can inspect nested direct children from each child facade. `element.innerHtml` is present only when the validator opts into `options.includeInnerHtml`.
542542

543543
`defineTagValidators(tagOrTags, rules)` is optional sugar for plugin authors. It lowercases the target tag or tags and expands each rule-map entry into an independent validator; rule-map keys are the exact rule ids used by `rules` config and inline disable comments. A rule can be a bare validation function or an object with `validate`, `severity`, and `options`.
544544

js/linter/linter.test.ts

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -946,7 +946,7 @@ describe('createLinter validators hook', () => {
946946
expect(disabled.some((x) => x.ruleName === 'no-pl-card')).toBe(false);
947947
});
948948

949-
it('exposes one-level child facades with mustache-section flattening', async () => {
949+
it('exposes direct child facades with mustache-section flattening', async () => {
950950
const handle = await createLinter({
951951
locateWasm: GRAMMAR_WASM_PATH,
952952
validators: [
@@ -958,10 +958,13 @@ describe('createLinter validators hook', () => {
958958
if (tags !== 'pl-item,pl-extra') {
959959
context.report({ element, message: `children:${tags}` });
960960
}
961-
if (element.children[0]?.children.length !== 0) {
961+
if (
962+
element.children[0]?.childrenWithTag('span').length !== 1 ||
963+
element.children[0]?.childrenWithTag('pl-extra').length !== 0
964+
) {
962965
context.report({
963966
element,
964-
message: 'children should be one-level',
967+
message: 'child facade children mismatch',
965968
});
966969
}
967970
},
@@ -981,6 +984,35 @@ describe('createLinter validators hook', () => {
981984
expect(d.filter((x) => x.ruleName === 'child-tags')).toEqual([]);
982985
});
983986

987+
it('populates nested custom-tag child facades recursively', async () => {
988+
const handle = await createLinter({
989+
locateWasm: GRAMMAR_WASM_PATH,
990+
validators: defineTagValidators('pl-order-blocks', {
991+
'requires-group-answer'(element, context) {
992+
for (const group of element.childrenWithTag('pl-block-group')) {
993+
const answers = group.childrenWithTag('pl-answer');
994+
if (answers.length === 0) {
995+
context.reportElement(group, 'Group has no answers');
996+
}
997+
}
998+
},
999+
}),
1000+
});
1001+
const d = handle.lint(
1002+
'<pl-order-blocks><pl-block-group><pl-answer>One</pl-answer></pl-block-group></pl-order-blocks>',
1003+
{
1004+
customTags: [
1005+
{ name: 'pl-order-blocks' },
1006+
{ name: 'pl-block-group' },
1007+
{ name: 'pl-answer' },
1008+
],
1009+
},
1010+
);
1011+
expect(d.filter((x) => x.ruleName === 'requires-group-answer')).toEqual(
1012+
[],
1013+
);
1014+
});
1015+
9841016
it('exposes innerHtml only when includeInnerHtml is set', async () => {
9851017
const handle = await createLinter({
9861018
locateWasm: GRAMMAR_WASM_PATH,

js/linter/tagValidatorRunner.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ function buildFacade(
116116
for (const [name, info] of attributesByName) attributes[name] = info.value;
117117
const children = includeChildren
118118
? collectDirectHtmlChildren(node)
119-
.map((child) => buildFacade(child, includeInnerHtml, false))
119+
.map((child) => buildFacade(child, includeInnerHtml, true))
120120
.filter((child): child is Facade => child !== null)
121121
: [];
122122
return {

lsp/package.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)