Skip to content

Commit 2ca3d6c

Browse files
committed
Extract rule: template-no-html-comments
1 parent 3f6a7c8 commit 2ca3d6c

4 files changed

Lines changed: 182 additions & 0 deletions

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ rules in templates can be disabled with eslint directives with mustache or html
203203
| [template-no-chained-this](docs/rules/template-no-chained-this.md) | disallow redundant `this.this` in templates | | 🔧 | |
204204
| [template-no-debugger](docs/rules/template-no-debugger.md) | disallow {{debugger}} in templates | | | |
205205
| [template-no-element-event-actions](docs/rules/template-no-element-event-actions.md) | disallow element event actions (use {{on}} modifier instead) | | | |
206+
| [template-no-html-comments](docs/rules/template-no-html-comments.md) | disallow HTML comments in templates | | 🔧 | |
206207
| [template-no-inline-event-handlers](docs/rules/template-no-inline-event-handlers.md) | disallow DOM event handler attributes | | | |
207208
| [template-no-inline-styles](docs/rules/template-no-inline-styles.md) | disallow inline styles | | | |
208209
| [template-no-input-placeholder](docs/rules/template-no-input-placeholder.md) | disallow placeholder attribute on input elements | | | |
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# ember/template-no-html-comments
2+
3+
🔧 This rule is automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/latest/user-guide/command-line-interface#--fix).
4+
5+
<!-- end auto-generated rule header -->
6+
7+
Disallow HTML comments in templates. HTML comments will be visible in the rendered output, which may expose sensitive information or clutter the DOM.
8+
9+
## Rule Details
10+
11+
This rule disallows HTML comments (`<!-- -->`) in templates and suggests using Glimmer comments (`{{! }}` or `{{!-- --}}`) instead.
12+
13+
## Examples
14+
15+
Examples of **incorrect** code for this rule:
16+
17+
```gjs
18+
<template>
19+
<!-- This is an HTML comment -->
20+
<div>Content</div>
21+
</template>
22+
```
23+
24+
Examples of **correct** code for this rule:
25+
26+
```gjs
27+
<template>
28+
{{! This is a Glimmer comment }}
29+
<div>Content</div>
30+
</template>
31+
32+
<template>
33+
{{!-- This is a block Glimmer comment --}}
34+
<div>Content</div>
35+
</template>
36+
```
37+
38+
## References
39+
40+
- [Ember guides/template features](https://guides.emberjs.com/release/components/#toc_supported-features)
41+
- [Handlebars docs/comments](https://handlebarsjs.com/guide/#template-comments)
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/** @type {import('eslint').Rule.RuleModule} */
2+
module.exports = {
3+
meta: {
4+
type: 'suggestion',
5+
docs: {
6+
description: 'disallow HTML comments in templates',
7+
category: 'Best Practices',
8+
url: 'https://github.com/ember-cli/eslint-plugin-ember/tree/master/docs/rules/template-no-html-comments.md',
9+
templateMode: 'both',
10+
},
11+
fixable: 'code',
12+
schema: [],
13+
messages: {
14+
noHtmlComments:
15+
'HTML comments should not be used in templates. Use Handlebars comments instead.',
16+
},
17+
originallyFrom: {
18+
name: 'ember-template-lint',
19+
rule: 'lib/rules/no-html-comments.js',
20+
docs: 'docs/rule/no-html-comments.md',
21+
tests: 'test/unit/rules/no-html-comments-test.js',
22+
},
23+
},
24+
25+
create(context) {
26+
return {
27+
'Program:exit'(node) {
28+
// Check for HTML comments in the source text
29+
const sourceCode = context.sourceCode || context.getSourceCode();
30+
const text = sourceCode.getText(node);
31+
32+
// Find all HTML comments in template blocks
33+
const htmlCommentRegex = /<!--([\S\s]*?)-->/g;
34+
let match;
35+
36+
const hasTemplateTag = text.includes('<template>');
37+
38+
while ((match = htmlCommentRegex.exec(text)) !== null) {
39+
let isInTemplate = false;
40+
41+
if (hasTemplateTag) {
42+
const beforeComment = text.slice(0, match.index);
43+
const templateStart = beforeComment.lastIndexOf('<template>');
44+
const templateEnd = text.indexOf('</template>', match.index);
45+
isInTemplate = templateStart !== -1 && templateEnd !== -1;
46+
} else {
47+
// Standalone .hbs file — entire file is template content
48+
isInTemplate = true;
49+
}
50+
51+
if (isInTemplate) {
52+
const commentContent = match[1];
53+
const startIndex = match.index;
54+
const endIndex = match.index + match[0].length;
55+
56+
context.report({
57+
loc: {
58+
start: sourceCode.getLocFromIndex(startIndex),
59+
end: sourceCode.getLocFromIndex(endIndex),
60+
},
61+
messageId: 'noHtmlComments',
62+
fix(fixer) {
63+
return fixer.replaceTextRange([startIndex, endIndex], `{{!${commentContent}}}`);
64+
},
65+
});
66+
}
67+
}
68+
},
69+
};
70+
},
71+
};
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
//------------------------------------------------------------------------------
2+
// Requirements
3+
//------------------------------------------------------------------------------
4+
5+
const rule = require('../../../lib/rules/template-no-html-comments');
6+
const RuleTester = require('eslint').RuleTester;
7+
8+
const ruleTester = new RuleTester({
9+
parser: require.resolve('ember-eslint-parser'),
10+
parserOptions: { ecmaVersion: 2022, sourceType: 'module' },
11+
});
12+
13+
ruleTester.run('template-no-html-comments', rule, {
14+
valid: [
15+
'<template>{{! This is a comment }}</template>',
16+
'<template>{{!-- This is a comment --}}</template>',
17+
'<template><div>Content</div></template>',
18+
19+
'<template>{{!-- comment here --}}</template>',
20+
'<template>{{!--comment here--}}</template>',
21+
],
22+
invalid: [
23+
{
24+
code: '<template><!-- HTML comment --></template>',
25+
output: '<template>{{! HTML comment }}</template>',
26+
errors: [{ messageId: 'noHtmlComments' }],
27+
},
28+
29+
{
30+
code: '<template><!-- comment here --></template>',
31+
output: '<template>{{! comment here }}</template>',
32+
errors: [{ messageId: 'noHtmlComments' }],
33+
},
34+
{
35+
code: '<template><!--comment here--></template>',
36+
output: '<template>{{!comment here}}</template>',
37+
errors: [{ messageId: 'noHtmlComments' }],
38+
},
39+
],
40+
});
41+
42+
const hbsRuleTester = new RuleTester({
43+
parser: require.resolve('ember-eslint-parser/hbs'),
44+
parserOptions: {
45+
ecmaVersion: 2022,
46+
sourceType: 'module',
47+
},
48+
});
49+
50+
hbsRuleTester.run('template-no-html-comments', rule, {
51+
valid: [
52+
'{{!-- comment here --}}',
53+
'{{!--comment here--}}',
54+
'{{! template-lint-disable no-bare-strings }}',
55+
'{{! template-lint-disable }}',
56+
],
57+
invalid: [
58+
{
59+
code: '<!-- comment here -->',
60+
output: '{{! comment here }}',
61+
errors: [{ messageId: 'noHtmlComments' }],
62+
},
63+
{
64+
code: '<!--comment here-->',
65+
output: '{{!comment here}}',
66+
errors: [{ messageId: 'noHtmlComments' }],
67+
},
68+
],
69+
});

0 commit comments

Comments
 (0)