@reteps/tree-sitter-htmlmustache 0.7.0 → 0.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +65 -14
- package/cli/out/main.js +3 -2
- package/package.json +1 -1
- package/src/parser.c +2 -2
- package/src/scanner.c +11 -0
- package/tree-sitter-htmlmustache.wasm +0 -0
package/README.md
CHANGED
|
@@ -228,36 +228,87 @@ Additionally, the following rules are configurable. Set their severities (`"erro
|
|
|
228
228
|
{
|
|
229
229
|
"rules": {
|
|
230
230
|
"consecutiveDuplicateSections": "off",
|
|
231
|
-
"preferMustacheComments": "warning"
|
|
232
|
-
}
|
|
231
|
+
"preferMustacheComments": "warning",
|
|
232
|
+
},
|
|
233
233
|
}
|
|
234
234
|
```
|
|
235
235
|
|
|
236
236
|
<!-- RULES_TABLE_START -->
|
|
237
237
|
|
|
238
|
-
| Rule
|
|
239
|
-
|
|
|
240
|
-
| `nestedDuplicateSections`
|
|
241
|
-
| `unquotedMustacheAttributes`
|
|
242
|
-
| `consecutiveDuplicateSections` | `warning` | Warns when adjacent same-name sections can be merged
|
|
243
|
-
| `selfClosingNonVoidTags`
|
|
244
|
-
| `duplicateAttributes`
|
|
245
|
-
| `unescapedEntities`
|
|
246
|
-
| `preferMustacheComments`
|
|
247
|
-
| `unrecognizedHtmlTags`
|
|
238
|
+
| Rule | Default | Description |
|
|
239
|
+
| ------------------------------ | --------- | ---------------------------------------------------------------------------- |
|
|
240
|
+
| `nestedDuplicateSections` | `error` | Flags `{{#name}}` nested inside another `{{#name}}` with the same name |
|
|
241
|
+
| `unquotedMustacheAttributes` | `error` | Requires quotes around mustache expressions used as attribute values |
|
|
242
|
+
| `consecutiveDuplicateSections` | `warning` | Warns when adjacent same-name sections can be merged |
|
|
243
|
+
| `selfClosingNonVoidTags` | `error` | Disallows self-closing syntax on non-void HTML elements (e.g. `<div/>`) |
|
|
244
|
+
| `duplicateAttributes` | `error` | Detects duplicate HTML attributes on the same element |
|
|
245
|
+
| `unescapedEntities` | `warning` | Flags unescaped `&` and `>` characters in text content |
|
|
246
|
+
| `preferMustacheComments` | `off` | Suggests replacing HTML comments with mustache comments |
|
|
247
|
+
| `unrecognizedHtmlTags` | `error` | Flags HTML tags that are not standard HTML elements or valid custom elements |
|
|
248
248
|
|
|
249
249
|
<!-- RULES_TABLE_END -->
|
|
250
250
|
|
|
251
|
+
### Custom Rules
|
|
252
|
+
|
|
253
|
+
Define project-specific lint rules using CSS-like selectors to match HTML elements and Mustache sections:
|
|
254
|
+
|
|
255
|
+
```jsonc
|
|
256
|
+
{
|
|
257
|
+
"customRules": [
|
|
258
|
+
{
|
|
259
|
+
"id": "no-font",
|
|
260
|
+
"selector": "font",
|
|
261
|
+
"message": "The <font> tag is deprecated. Use CSS instead.",
|
|
262
|
+
},
|
|
263
|
+
{
|
|
264
|
+
"id": "no-inline-styles",
|
|
265
|
+
"selector": "[style]",
|
|
266
|
+
"message": "Avoid inline styles",
|
|
267
|
+
"severity": "warning",
|
|
268
|
+
},
|
|
269
|
+
{
|
|
270
|
+
"id": "images-need-alt",
|
|
271
|
+
"selector": "img:not([alt])",
|
|
272
|
+
"message": "Images must have alt text for accessibility",
|
|
273
|
+
},
|
|
274
|
+
{
|
|
275
|
+
"id": "no-hidden-inputs-in-list",
|
|
276
|
+
"selector": "#items > input[type=hidden]",
|
|
277
|
+
"message": "Hidden inputs inside {{#items}} sections are usually a mistake",
|
|
278
|
+
},
|
|
279
|
+
],
|
|
280
|
+
}
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
Each custom rule requires an `id`, `selector`, and `message`. The `severity` defaults to `"error"` but can be set to `"warning"` or `"off"`.
|
|
284
|
+
|
|
285
|
+
**Selector syntax:**
|
|
286
|
+
|
|
287
|
+
| Selector | Matches |
|
|
288
|
+
| -------------------- | ---------------------------------------- |
|
|
289
|
+
| `div` | HTML elements by tag name |
|
|
290
|
+
| `#items` | Mustache sections by name (`{{#items}}`) |
|
|
291
|
+
| `*` | Any HTML element |
|
|
292
|
+
| `#` | Any Mustache section |
|
|
293
|
+
| `div span` | Descendant (span anywhere inside div) |
|
|
294
|
+
| `div > span` | Direct child (span directly inside div) |
|
|
295
|
+
| `[style]` | Attribute presence |
|
|
296
|
+
| `input[type=hidden]` | Attribute value |
|
|
297
|
+
| `img:not([alt])` | Negated attribute |
|
|
298
|
+
| `div, span` | Comma-separated alternatives |
|
|
299
|
+
|
|
300
|
+
The `>` (child) combinator is kind-transparent: `div > span` matches even if a Mustache section sits between them (e.g. `<div>{{#show}}<span>{{/show}}</div>`), and `#a > #b` matches across intervening HTML elements.
|
|
301
|
+
|
|
251
302
|
### Disabling Lint Rules
|
|
252
303
|
|
|
253
|
-
Disable a
|
|
304
|
+
Disable a lint rule for an entire file with an inline comment:
|
|
254
305
|
|
|
255
306
|
```html
|
|
256
307
|
<!-- htmlmustache-disable preferMustacheComments -->
|
|
257
308
|
{{! htmlmustache-disable selfClosingNonVoidTags }}
|
|
258
309
|
```
|
|
259
310
|
|
|
260
|
-
The comment can appear anywhere in the file.
|
|
311
|
+
The comment can appear anywhere in the file. Both built-in and custom rules can be disabled by name/id. Use multiple comments to disable multiple rules.
|
|
261
312
|
|
|
262
313
|
### EditorConfig
|
|
263
314
|
|
package/cli/out/main.js
CHANGED
|
@@ -1980,7 +1980,8 @@ function collectErrors(tree, rules, customTagNames, customRules) {
|
|
|
1980
1980
|
message: error.message,
|
|
1981
1981
|
severity,
|
|
1982
1982
|
fix: error.fix,
|
|
1983
|
-
fixDescription: error.fixDescription
|
|
1983
|
+
fixDescription: error.fixDescription,
|
|
1984
|
+
ruleName: rule
|
|
1984
1985
|
});
|
|
1985
1986
|
}
|
|
1986
1987
|
}
|
|
@@ -1993,7 +1994,7 @@ function collectErrors(tree, rules, customTagNames, customRules) {
|
|
|
1993
1994
|
if (!parsed) continue;
|
|
1994
1995
|
const matches = matchSelector(tree.rootNode, parsed);
|
|
1995
1996
|
for (const node of matches) {
|
|
1996
|
-
errors.push({ node, message: rule.message, severity });
|
|
1997
|
+
errors.push({ node, message: rule.message, severity, ruleName: rule.id });
|
|
1997
1998
|
}
|
|
1998
1999
|
}
|
|
1999
2000
|
}
|
package/package.json
CHANGED
package/src/parser.c
CHANGED
|
@@ -10874,8 +10874,8 @@ TS_PUBLIC const TSLanguage *tree_sitter_htmlmustache(void) {
|
|
|
10874
10874
|
.max_reserved_word_set_size = 0,
|
|
10875
10875
|
.metadata = {
|
|
10876
10876
|
.major_version = 0,
|
|
10877
|
-
.minor_version =
|
|
10878
|
-
.patch_version =
|
|
10877
|
+
.minor_version = 4,
|
|
10878
|
+
.patch_version = 1,
|
|
10879
10879
|
},
|
|
10880
10880
|
};
|
|
10881
10881
|
return &language;
|
package/src/scanner.c
CHANGED
|
@@ -386,6 +386,17 @@ static bool scan_end_tag_name(Scanner *scanner, TSLexer *lexer) {
|
|
|
386
386
|
|
|
387
387
|
Tag tag = tag_for_name(tag_name);
|
|
388
388
|
if (scanner->tags.size > 0 && tag_eq(array_back(&scanner->tags), &tag)) {
|
|
389
|
+
// Don't close HTML tags that were opened before the current mustache section.
|
|
390
|
+
// This prevents e.g. </div> inside {{#section}}...{{/section}} from closing
|
|
391
|
+
// an outer <div> that was opened before the section started.
|
|
392
|
+
if (scanner->mustache_tags.size > 0) {
|
|
393
|
+
MustacheTag *current_mustache_tag = array_back(&scanner->mustache_tags);
|
|
394
|
+
if (scanner->tags.size <= current_mustache_tag->html_tag_stack_size) {
|
|
395
|
+
lexer->result_symbol = HTML_ERRONEOUS_END_TAG_NAME;
|
|
396
|
+
tag_free(&tag);
|
|
397
|
+
return true;
|
|
398
|
+
}
|
|
399
|
+
}
|
|
389
400
|
pop_html_tag(scanner);
|
|
390
401
|
lexer->result_symbol = HTML_END_TAG_NAME;
|
|
391
402
|
} else {
|
|
Binary file
|