File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -304,6 +304,12 @@ rules in templates can be disabled with eslint directives with mustache or html
304304| [ route-path-style] ( docs/rules/route-path-style.md ) | enforce usage of kebab-case (instead of snake_case or camelCase) in route paths | | | 💡 |
305305| [ routes-segments-snake-case] ( docs/rules/routes-segments-snake-case.md ) | enforce usage of snake_cased dynamic segments in routes | ✅ | | |
306306
307+ ### Security
308+
309+ | Name | Description | 💼 | 🔧 | 💡 |
310+ | :--------------------------------------------------------------------- | :-------------------------------------------------------------- | :- | :- | :- |
311+ | [ template-link-rel-noopener] ( docs/rules/template-link-rel-noopener.md ) | require rel="noopener noreferrer" on links with target="_ blank" | | 🔧 | |
312+
307313### Services
308314
309315| Name | Description | 💼 | 🔧 | 💡 |
Original file line number Diff line number Diff line change 1+ # ember/template-link-rel-noopener
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+ ## Examples
8+
9+ See ember-template-lint documentation.
10+
11+ ## References
12+
13+ - [ ember-template-lint link-rel-noopener] ( https://github.com/ember-template-lint/ember-template-lint/blob/master/docs/rule/link-rel-noopener.md )
Original file line number Diff line number Diff line change 1+ /** @type {import('eslint').Rule.RuleModule } */
2+ module . exports = {
3+ meta : {
4+ type : 'problem' ,
5+ docs : {
6+ description : 'require rel="noopener noreferrer" on links with target="_blank"' ,
7+ category : 'Security' ,
8+ strictGjs : true ,
9+ strictGts : true ,
10+ url : 'https://github.com/ember-cli/eslint-plugin-ember/tree/master/docs/rules/template-link-rel-noopener.md' ,
11+ } ,
12+ fixable : 'code' ,
13+ schema : [ ] ,
14+ messages : {
15+ missingRel : 'links with target="_blank" must have rel="noopener noreferrer"' ,
16+ } ,
17+ } ,
18+ create ( context ) {
19+ return {
20+ GlimmerElementNode ( node ) {
21+ if ( node . tag !== 'a' ) {
22+ return ;
23+ }
24+
25+ const targetAttr = node . attributes ?. find ( ( a ) => a . name === 'target' ) ;
26+ if ( ! targetAttr ?. value || targetAttr . value . type !== 'GlimmerTextNode' ) {
27+ return ;
28+ }
29+ if ( targetAttr . value . chars !== '_blank' ) {
30+ return ;
31+ }
32+
33+ const relAttr = node . attributes ?. find ( ( a ) => a . name === 'rel' ) ;
34+ const hasProperRel =
35+ relAttr ?. value ?. type === 'GlimmerTextNode' &&
36+ / n o o p e n e r / . test ( relAttr . value . chars ) &&
37+ / n o r e f e r r e r / . test ( relAttr . value . chars ) ;
38+
39+ if ( ! hasProperRel ) {
40+ context . report ( {
41+ node : targetAttr ,
42+ messageId : 'missingRel' ,
43+ fix ( fixer ) {
44+ const sourceCode = context . sourceCode ;
45+ const openTag = sourceCode . getText ( node ) . match ( / ^ < a [ ^ > ] * / ) [ 0 ] ;
46+ const insertPos = node . range [ 0 ] + openTag . length ;
47+ return fixer . insertTextBeforeRange (
48+ [ insertPos , insertPos ] ,
49+ ' rel="noopener noreferrer"'
50+ ) ;
51+ } ,
52+ } ) ;
53+ }
54+ } ,
55+ } ;
56+ } ,
57+ } ;
Original file line number Diff line number Diff line change 1+ const rule = require ( '../../../lib/rules/template-link-rel-noopener' ) ;
2+ const RuleTester = require ( 'eslint' ) . RuleTester ;
3+
4+ const ruleTester = new RuleTester ( {
5+ parser : require . resolve ( 'ember-eslint-parser' ) ,
6+ parserOptions : { ecmaVersion : 2022 , sourceType : 'module' } ,
7+ } ) ;
8+ ruleTester . run ( 'template-link-rel-noopener' , rule , {
9+ valid : [ '<template><a href="/" target="_blank" rel="noopener noreferrer">Link</a></template>' ] ,
10+ invalid : [
11+ {
12+ code : '<template><a href="/" target="_blank">Link</a></template>' ,
13+ output : '<template><a href="/" target="_blank" rel="noopener noreferrer">Link</a></template>' ,
14+ errors : [ { messageId : 'missingRel' } ] ,
15+ } ,
16+ ] ,
17+ } ) ;
You can’t perform that action at this time.
0 commit comments