@@ -3,10 +3,10 @@ import { getLocator } from 'locate-character';
3
3
import { MappedCode , SourceLocation , sourcemap_add_offset , combine_sourcemaps } from '../utils/mapped_code' ;
4
4
import { decode_map } from './decode_sourcemap' ;
5
5
import { replace_in_code , Source } from './replace_in_code' ;
6
- import { Preprocessor , PreprocessorGroup , Processed } from './types' ;
6
+ import { MarkupPreprocessor , Preprocessor , PreprocessorGroup , Processed } from './types' ;
7
7
8
8
interface SourceUpdate {
9
- string : string ;
9
+ string ? : string ;
10
10
map ?: DecodedSourceMap ;
11
11
dependencies ?: string [ ] ;
12
12
}
@@ -18,7 +18,7 @@ function get_file_basename(filename: string) {
18
18
/**
19
19
* Represents intermediate states of the preprocessing.
20
20
*/
21
- class PreprocessResult {
21
+ class PreprocessResult implements Source {
22
22
// sourcemap_list is sorted in reverse order from last map (index 0) to first map (index -1)
23
23
// so we use sourcemap_list.unshift() to add new maps
24
24
// https://github.com/ampproject/remapping#multiple-transformations-of-a-file
@@ -36,8 +36,10 @@ class PreprocessResult {
36
36
}
37
37
38
38
update_source ( { string : source , map, dependencies } : SourceUpdate ) {
39
- this . source = source ;
40
- this . get_location = getLocator ( source ) ;
39
+ if ( source ) {
40
+ this . source = source ;
41
+ this . get_location = getLocator ( source ) ;
42
+ }
41
43
42
44
if ( map ) {
43
45
this . sourcemap_list . unshift ( map ) ;
@@ -69,16 +71,12 @@ class PreprocessResult {
69
71
/**
70
72
* Convert preprocessor output for the tag content into MappedCode
71
73
*/
72
- function processed_content_to_code (
73
- processed : Processed ,
74
- location : SourceLocation ,
75
- file_basename : string
76
- ) : MappedCode {
74
+ function processed_content_to_code ( processed : Processed , location : SourceLocation , file_basename : string ) : MappedCode {
77
75
// Convert the preprocessed code and its sourcemap to a MappedCode
78
76
let decoded_map : DecodedSourceMap ;
79
77
if ( processed . map ) {
80
78
decoded_map = decode_map ( processed ) ;
81
-
79
+
82
80
// offset only segments pointing at original component source
83
81
const source_index = decoded_map . sources . indexOf ( file_basename ) ;
84
82
if ( source_index !== - 1 ) {
@@ -97,7 +95,8 @@ function processed_tag_to_code(
97
95
processed : Processed ,
98
96
tag_name : 'style' | 'script' ,
99
97
attributes : string ,
100
- { source, file_basename, get_location } : Source ) : MappedCode {
98
+ { source, file_basename, get_location } : Source
99
+ ) : MappedCode {
101
100
const build_mapped_code = ( source : string , offset : number ) =>
102
101
MappedCode . from_source ( file_basename , source , get_location ( offset ) ) ;
103
102
@@ -114,16 +113,19 @@ function processed_tag_to_code(
114
113
115
114
function parse_tag_attributes ( str : string ) {
116
115
// note: won't work with attribute values containing spaces.
117
- return str . split ( / \s + / ) . filter ( Boolean ) . reduce ( ( attrs , attr ) => {
118
- const [ key , value ] = attr . split ( '=' ) ;
119
- const [ , unquoted ] = value && value . match ( / ^ [ ' " ] ( .* ) [ ' " ] $ / ) || [ ] ;
120
-
121
- return { ...attrs , [ key ] : unquoted ?? value ?? true } ;
122
- } , { } ) ;
116
+ return str
117
+ . split ( / \s + / )
118
+ . filter ( Boolean )
119
+ . reduce ( ( attrs , attr ) => {
120
+ const [ key , value ] = attr . split ( '=' ) ;
121
+ const [ , unquoted ] = ( value && value . match ( / ^ [ ' " ] ( .* ) [ ' " ] $ / ) ) || [ ] ;
122
+
123
+ return { ...attrs , [ key ] : unquoted ?? value ?? true } ;
124
+ } , { } ) ;
123
125
}
124
126
125
- /**
126
- * Calculate the updates required to process all instances of the specified tag.
127
+ /**
128
+ * Calculate the updates required to process all instances of the specified tag.
127
129
*/
128
130
async function process_tag (
129
131
tag_name : 'style' | 'script' ,
@@ -144,8 +146,7 @@ async function process_tag(
144
146
content = '' ,
145
147
tag_offset : number
146
148
) : Promise < MappedCode > {
147
- const no_change = ( ) =>
148
- MappedCode . from_source ( file_basename , tag_with_content , get_location ( tag_offset ) ) ;
149
+ const no_change = ( ) => MappedCode . from_source ( file_basename , tag_with_content , get_location ( tag_offset ) ) ;
149
150
150
151
if ( ! attributes && ! content ) return no_change ( ) ;
151
152
@@ -155,14 +156,43 @@ async function process_tag(
155
156
filename
156
157
} ) ;
157
158
158
- if ( processed && processed . dependencies ) dependencies . push ( ...processed . dependencies ) ;
159
- if ( ! processed || ! processed . map && processed . code === content ) return no_change ( ) ;
159
+ if ( ! processed ) return no_change ( ) ;
160
+ if ( processed . dependencies ) dependencies . push ( ...processed . dependencies ) ;
161
+ if ( ! processed . map && processed . code === content ) return no_change ( ) ;
160
162
161
- return processed_tag_to_code ( processed , tag_name , attributes ,
162
- { source : content , get_location : offset => source . get_location ( offset + tag_offset ) , filename, file_basename} ) ;
163
+ return processed_tag_to_code ( processed , tag_name , attributes , {
164
+ source : content ,
165
+ get_location : offset => source . get_location ( offset + tag_offset ) ,
166
+ filename,
167
+ file_basename
168
+ } ) ;
163
169
}
164
170
165
- return { ...await replace_in_code ( tag_regex , process_single_tag , source ) , dependencies} ;
171
+ const { string, map } = await replace_in_code ( tag_regex , process_single_tag , source ) ;
172
+
173
+ return { string, map, dependencies } ;
174
+ }
175
+
176
+ async function process_markup ( filename : string , process : MarkupPreprocessor , source : Source ) {
177
+ const processed = await process ( {
178
+ content : source . source ,
179
+ filename
180
+ } ) ;
181
+
182
+ if ( processed ) {
183
+ return {
184
+ string : processed . code ,
185
+ map : processed . map
186
+ ? // TODO: can we use decode_sourcemap?
187
+ typeof processed . map === 'string'
188
+ ? JSON . parse ( processed . map )
189
+ : processed . map
190
+ : undefined ,
191
+ dependencies : processed . dependencies
192
+ } ;
193
+ } else {
194
+ return { } ;
195
+ }
166
196
}
167
197
168
198
export default async function preprocess (
@@ -173,9 +203,7 @@ export default async function preprocess(
173
203
// @ts -ignore todo: doublecheck
174
204
const filename = ( options && options . filename ) || preprocessor . filename ; // legacy
175
205
176
- const preprocessors = preprocessor
177
- ? Array . isArray ( preprocessor ) ? preprocessor : [ preprocessor ]
178
- : [ ] ;
206
+ const preprocessors = preprocessor ? ( Array . isArray ( preprocessor ) ? preprocessor : [ preprocessor ] ) : [ ] ;
179
207
180
208
const markup = preprocessors . map ( p => p . markup ) . filter ( Boolean ) ;
181
209
const script = preprocessors . map ( p => p . script ) . filter ( Boolean ) ;
@@ -187,23 +215,7 @@ export default async function preprocess(
187
215
// to make debugging easier = detect low-resolution sourcemaps in fn combine_mappings
188
216
189
217
for ( const process of markup ) {
190
- const processed = await process ( {
191
- content : result . source ,
192
- filename
193
- } ) ;
194
-
195
- if ( ! processed ) continue ;
196
-
197
- result . update_source ( {
198
- string : processed . code ,
199
- map : processed . map
200
- ? // TODO: can we use decode_sourcemap?
201
- typeof processed . map === 'string'
202
- ? JSON . parse ( processed . map )
203
- : processed . map
204
- : undefined ,
205
- dependencies : processed . dependencies
206
- } ) ;
218
+ result . update_source ( await process_markup ( filename , process , result ) ) ;
207
219
}
208
220
209
221
for ( const process of script ) {
0 commit comments