1
1
import type { TSESTree } from '@typescript-eslint/experimental-utils' ;
2
2
import { createESLintRule } from '../utils/create-eslint-rule' ;
3
3
import { COMPONENT_CLASS_DECORATOR } from '../utils/selectors' ;
4
- import {
5
- getDecoratorProperty ,
6
- isArrayExpression ,
7
- isLiteralWithStringValue ,
8
- } from '../utils/utils' ;
4
+ import { isArrayExpression , isLiteralWithStringValue } from '../utils/utils' ;
9
5
10
6
type Options = [ ] ;
11
7
export type MessageIds = 'relativeUrlPrefix' ;
12
8
export const RULE_NAME = 'relative-url-prefix' ;
13
9
14
10
const STYLE_GUIDE_LINK = 'https://angular.io/styleguide#style-05-04' ;
15
- const RELATIVE_URL_PREFIX_MATCHER = / ^ \. { 1 , 2 } \/ [ ^ . / ] / ;
11
+ const RELATIVE_URL_PREFIX_MATCHER = / ^ \. \. ? \/ . + / ;
16
12
17
13
export default createESLintRule < Options , MessageIds > ( {
18
14
name : RULE_NAME ,
19
15
meta : {
20
16
type : 'suggestion' ,
21
17
docs : {
22
- description : `The ./ and ../ prefix is standard syntax for relative URLs; don't depend on Angular's current ability to do without that prefix. See more at ${ STYLE_GUIDE_LINK } . ` ,
18
+ description : `The ./ and ../ prefix is standard syntax for relative URLs; don't depend on Angular's current ability to do without that prefix. See more at ${ STYLE_GUIDE_LINK } ` ,
23
19
category : 'Best Practices' ,
24
20
recommended : false ,
25
21
} ,
@@ -31,43 +27,35 @@ export default createESLintRule<Options, MessageIds>({
31
27
defaultOptions : [ ] ,
32
28
create ( context ) {
33
29
return {
34
- [ COMPONENT_CLASS_DECORATOR ] ( node : TSESTree . Decorator ) {
35
- const templateUrlProperty = getDecoratorProperty ( node , 'templateUrl' ) ;
36
- if (
37
- templateUrlProperty &&
38
- isLiteralWithStringValue ( templateUrlProperty . value )
39
- ) {
40
- if (
41
- ! RELATIVE_URL_PREFIX_MATCHER . test ( templateUrlProperty . value . value )
42
- ) {
43
- context . report ( {
44
- node : templateUrlProperty . value ,
45
- messageId : 'relativeUrlPrefix' ,
46
- } ) ;
47
- }
48
- }
30
+ [ `${ COMPONENT_CLASS_DECORATOR } Property[key.name='templateUrl']` ] ( {
31
+ value,
32
+ } : TSESTree . Property ) {
33
+ if ( ! isUrlInvalid ( value ) ) return ;
49
34
50
- const styleUrlsProperty = getDecoratorProperty ( node , 'styleUrls' ) ;
51
- if ( styleUrlsProperty ) {
52
- if (
53
- styleUrlsProperty . value &&
54
- isArrayExpression ( styleUrlsProperty . value ) &&
55
- styleUrlsProperty . value . elements . length > 0
56
- ) {
57
- styleUrlsProperty . value . elements . forEach ( ( e ) => {
58
- if (
59
- isLiteralWithStringValue ( e ) &&
60
- ! RELATIVE_URL_PREFIX_MATCHER . test ( e . value )
61
- ) {
62
- context . report ( {
63
- node : e ,
64
- messageId : 'relativeUrlPrefix' ,
65
- } ) ;
66
- }
67
- } ) ;
68
- }
69
- }
35
+ context . report ( {
36
+ node : value ,
37
+ messageId : 'relativeUrlPrefix' ,
38
+ } ) ;
39
+ } ,
40
+ [ `${ COMPONENT_CLASS_DECORATOR } Property[key.name='styleUrls']` ] ( {
41
+ value,
42
+ } : TSESTree . Property ) {
43
+ if ( ! isArrayExpression ( value ) ) return ;
44
+
45
+ value . elements . filter ( isUrlInvalid ) . forEach ( ( element ) => {
46
+ context . report ( {
47
+ node : element ,
48
+ messageId : 'relativeUrlPrefix' ,
49
+ } ) ;
50
+ } ) ;
70
51
} ,
71
52
} ;
72
53
} ,
73
54
} ) ;
55
+
56
+ function isUrlInvalid ( node : TSESTree . Property | TSESTree . Property [ 'value' ] ) {
57
+ return (
58
+ ! isLiteralWithStringValue ( node ) ||
59
+ ! RELATIVE_URL_PREFIX_MATCHER . test ( node . value )
60
+ ) ;
61
+ }
0 commit comments