@@ -28,7 +28,20 @@ class DartScriptUpdater extends RecursiveAstVisitor<void>
28
28
final String existingScriptPath;
29
29
final String newScriptPath;
30
30
31
- DartScriptUpdater (this .existingScriptPath, this .newScriptPath);
31
+ /// Whether or not to update attributes on script/link tags (like type/crossorigin)
32
+ /// while also updating the script path.
33
+ final bool updateAttributes;
34
+ final bool removeTag;
35
+
36
+ DartScriptUpdater (this .existingScriptPath, this .newScriptPath,
37
+ {this .updateAttributes = true })
38
+ : removeTag = false ;
39
+
40
+ /// Use this constructor to remove the whole tag instead of updating it.
41
+ DartScriptUpdater .remove (this .existingScriptPath)
42
+ : removeTag = true ,
43
+ updateAttributes = false ,
44
+ newScriptPath = 'will be ignored' ;
32
45
33
46
@override
34
47
void visitSimpleStringLiteral (SimpleStringLiteral node) {
@@ -39,74 +52,107 @@ class DartScriptUpdater extends RecursiveAstVisitor<void>
39
52
...Script (pathSubpattern: existingScriptPath)
40
53
.pattern
41
54
.allMatches (stringValue),
42
- ...Script (pathSubpattern: newScriptPath).pattern.allMatches (stringValue)
55
+ ...? (! removeTag
56
+ ? Script (pathSubpattern: newScriptPath)
57
+ .pattern
58
+ .allMatches (stringValue)
59
+ : null )
43
60
];
44
61
final relevantLinkTags = [
45
62
...Link (pathSubpattern: existingScriptPath)
46
63
.pattern
47
64
.allMatches (stringValue),
48
- ...Link (pathSubpattern: newScriptPath).pattern.allMatches (stringValue)
65
+ ...? (! removeTag
66
+ ? Link (pathSubpattern: newScriptPath).pattern.allMatches (stringValue)
67
+ : null )
49
68
];
50
69
51
70
// Do not update if neither the existingScriptPath nor newScriptPath are in the file.
52
71
if (relevantScriptTags.isEmpty && relevantLinkTags.isEmpty) return ;
53
72
54
- // Add type="module" attribute to script tag.
55
- for (final scriptTagMatch in relevantScriptTags) {
56
- final scriptTag = scriptTagMatch.group (0 );
57
- if (scriptTag == null ) continue ;
58
- final typeAttributes = getAttributePattern ('type' ).allMatches (scriptTag);
59
- if (typeAttributes.isNotEmpty) {
60
- final attribute = typeAttributes.first;
61
- final value = attribute.group (1 );
62
- if (value == 'module' ) {
63
- continue ;
73
+ if (removeTag) {
74
+ for (final tag in [...relevantScriptTags, ...relevantLinkTags]) {
75
+ final tagEnd = node.offset + tag.end;
76
+ final tagStart = node.offset + tag.start;
77
+ final possibleCommaEnd = node.literal.next.toString () == ',' ? 1 : 0 ;
78
+ final isTagSameAsNode =
79
+ // Check if the only difference between [tag] and [node] is the quotes around [node].
80
+ tagStart - node.offset <= 1 && node.end - tagEnd <= 1 ;
81
+
82
+ yieldPatch (
83
+ '' ,
84
+ // If [tag] spans the whole string literal in [node], then also include
85
+ // the quotes and comma in the removal.
86
+ isTagSameAsNode
87
+ // Remove from the end of the previous token to take any preceding newline with it,
88
+ // so that we don't leave behind an empty line.
89
+ ? node.beginToken.previous? .end ?? node.offset
90
+ : tagStart,
91
+ isTagSameAsNode ? (node.end + possibleCommaEnd) : tagEnd,
92
+ );
93
+ }
94
+ return ;
95
+ }
96
+
97
+ if (updateAttributes) {
98
+ // Add type="module" attribute to script tag.
99
+ for (final scriptTagMatch in relevantScriptTags) {
100
+ final scriptTag = scriptTagMatch.group (0 );
101
+ if (scriptTag == null ) continue ;
102
+ final typeAttributes =
103
+ getAttributePattern ('type' ).allMatches (scriptTag);
104
+ if (typeAttributes.isNotEmpty) {
105
+ final attribute = typeAttributes.first;
106
+ final value = attribute.group (1 );
107
+ if (value == 'module' ) {
108
+ continue ;
109
+ } else {
110
+ // If the value of the type attribute is not "module", overwrite it.
111
+ yieldPatch (
112
+ typeModuleAttribute,
113
+ node.offset + scriptTagMatch.start + attribute.start,
114
+ node.offset + scriptTagMatch.start + attribute.end,
115
+ );
116
+ }
64
117
} else {
65
- // If the value of the type attribute is not "module", overwrite it.
118
+ // If the type attribute does not exist, add it.
119
+ final srcAttribute = getAttributePattern ('src' ).allMatches (scriptTag);
66
120
yieldPatch (
67
- typeModuleAttribute,
68
- node.offset + scriptTagMatch.start + attribute.start ,
69
- node.offset + scriptTagMatch.start + attribute .end,
121
+ ' ${ typeModuleAttribute }' ,
122
+ node.offset + scriptTagMatch.start + srcAttribute.first.end ,
123
+ node.offset + scriptTagMatch.start + srcAttribute.first .end,
70
124
);
71
125
}
72
- } else {
73
- // If the type attribute does not exist, add it.
74
- final srcAttribute = getAttributePattern ('src' ).allMatches (scriptTag);
75
- yieldPatch (
76
- ' ${typeModuleAttribute }' ,
77
- node.offset + scriptTagMatch.start + srcAttribute.first.end,
78
- node.offset + scriptTagMatch.start + srcAttribute.first.end,
79
- );
80
126
}
81
- }
82
127
83
- // Add crossorigin="" attribute to link tag.
84
- for (final linkTagMatch in relevantLinkTags) {
85
- final linkTag = linkTagMatch.group (0 );
86
- if (linkTag == null ) continue ;
87
- final crossOriginAttributes =
88
- getAttributePattern ('crossorigin' ).allMatches (linkTag);
89
- if (crossOriginAttributes.isNotEmpty) {
90
- final attribute = crossOriginAttributes.first;
91
- final value = attribute.group (1 );
92
- if (value == '' ) {
93
- continue ;
128
+ // Add crossorigin="" attribute to link tag.
129
+ for (final linkTagMatch in relevantLinkTags) {
130
+ final linkTag = linkTagMatch.group (0 );
131
+ if (linkTag == null ) continue ;
132
+ final crossOriginAttributes =
133
+ getAttributePattern ('crossorigin' ).allMatches (linkTag);
134
+ if (crossOriginAttributes.isNotEmpty) {
135
+ final attribute = crossOriginAttributes.first;
136
+ final value = attribute.group (1 );
137
+ if (value == '' ) {
138
+ continue ;
139
+ } else {
140
+ // If the value of the crossorigin attribute is not "", overwrite it.
141
+ yieldPatch (
142
+ crossOriginAttribute,
143
+ node.offset + linkTagMatch.start + attribute.start,
144
+ node.offset + linkTagMatch.start + attribute.end,
145
+ );
146
+ }
94
147
} else {
95
- // If the value of the crossorigin attribute is not "", overwrite it.
148
+ // If the crossorigin attribute does not exist, add it.
149
+ final hrefAttribute = getAttributePattern ('href' ).allMatches (linkTag);
96
150
yieldPatch (
97
- crossOriginAttribute,
98
- node.offset + linkTagMatch.start + attribute.start ,
99
- node.offset + linkTagMatch.start + attribute .end,
151
+ ' ${ crossOriginAttribute }' ,
152
+ node.offset + linkTagMatch.start + hrefAttribute.first.end ,
153
+ node.offset + linkTagMatch.start + hrefAttribute.first .end,
100
154
);
101
155
}
102
- } else {
103
- // If the crossorigin attribute does not exist, add it.
104
- final hrefAttribute = getAttributePattern ('href' ).allMatches (linkTag);
105
- yieldPatch (
106
- ' ${crossOriginAttribute }' ,
107
- node.offset + linkTagMatch.start + hrefAttribute.first.end,
108
- node.offset + linkTagMatch.start + hrefAttribute.first.end,
109
- );
110
156
}
111
157
}
112
158
0 commit comments