1- import { parse } from 'url' ;
2-
31import { Parser } from 'htmlparser2' ;
4- import { isUrlRequest , urlToRequest } from 'loader-utils' ;
2+ import { isUrlRequest } from 'loader-utils' ;
53
64import HtmlSourceError from '../HtmlSourceError' ;
7- import { getFilter , parseSrc , parseSrcset } from '../utils' ;
8-
9- function parseSource ( source ) {
10- const URLObject = parse ( source ) ;
11- const { hash } = URLObject ;
12-
13- if ( ! hash ) {
14- return { sourceValue : source } ;
15- }
16-
17- URLObject . hash = null ;
18-
19- const sourceWithoutHash = URLObject . format ( ) ;
20-
21- return { sourceValue : sourceWithoutHash , hash } ;
22- }
5+ import {
6+ getFilter ,
7+ parseSrc ,
8+ parseSrcset ,
9+ normalizeUrl ,
10+ requestify ,
11+ } from '../utils' ;
2312
2413export default ( options ) =>
2514 function process ( html ) {
@@ -44,45 +33,6 @@ export default (options) =>
4433 } ) ;
4534 } ;
4635 const { resourcePath } = options ;
47- const imports = new Map ( ) ;
48- const getImportItem = ( value ) => {
49- const key = urlToRequest ( decodeURIComponent ( value ) , root ) ;
50-
51- let name = imports . get ( key ) ;
52-
53- if ( name ) {
54- return { key, name } ;
55- }
56-
57- name = `___HTML_LOADER_IMPORT_${ imports . size } ___` ;
58- imports . set ( key , name ) ;
59-
60- options . imports . push ( { importName : name , source : key } ) ;
61-
62- return { key, name } ;
63- } ;
64- const replacements = new Map ( ) ;
65- const getReplacementItem = ( importItem , unquoted , hash ) => {
66- const key = JSON . stringify ( { key : importItem . key , unquoted, hash } ) ;
67-
68- let name = replacements . get ( key ) ;
69-
70- if ( name ) {
71- return { key, name } ;
72- }
73-
74- name = `___HTML_LOADER_REPLACEMENT_${ replacements . size } ___` ;
75- replacements . set ( key , name ) ;
76-
77- options . replacements . push ( {
78- replacementName : name ,
79- importName : importItem . name ,
80- hash,
81- unquoted,
82- } ) ;
83-
84- return { key, name } ;
85- } ;
8636 const parser = new Parser (
8737 {
8838 attributesMeta : { } ,
@@ -135,21 +85,16 @@ export default (options) =>
13585 return ;
13686 }
13787
138- if ( ! urlFilter ( attribute , source . value , resourcePath ) ) {
139- return ;
140- }
141-
142- const { sourceValue, hash } = parseSource ( source . value ) ;
143- const importItem = getImportItem ( sourceValue ) ;
144- const replacementItem = getReplacementItem (
145- importItem ,
146- unquoted ,
147- hash
148- ) ;
14988 const startIndex = valueStartIndex + source . startIndex ;
15089 const endIndex = startIndex + source . value . length ;
15190
152- sources . push ( { replacementItem, startIndex, endIndex } ) ;
91+ sources . push ( {
92+ name : attribute ,
93+ value : source . value ,
94+ unquoted,
95+ startIndex,
96+ endIndex,
97+ } ) ;
15398
15499 break ;
155100 }
@@ -173,22 +118,16 @@ export default (options) =>
173118
174119 sourceSet . forEach ( ( sourceItem ) => {
175120 const { source } = sourceItem ;
176-
177- if ( ! urlFilter ( attribute , source . value , resourcePath ) ) {
178- return ;
179- }
180-
181- const { sourceValue, hash } = parseSource ( source . value ) ;
182- const importItem = getImportItem ( sourceValue ) ;
183- const replacementItem = getReplacementItem (
184- importItem ,
185- unquoted ,
186- hash
187- ) ;
188121 const startIndex = valueStartIndex + source . startIndex ;
189122 const endIndex = startIndex + source . value . length ;
190123
191- sources . push ( { replacementItem, startIndex, endIndex } ) ;
124+ sources . push ( {
125+ name : attribute ,
126+ value : source . value ,
127+ unquoted,
128+ startIndex,
129+ endIndex,
130+ } ) ;
192131 } ) ;
193132
194133 break ;
@@ -261,18 +200,76 @@ export default (options) =>
261200 parser . write ( html ) ;
262201 parser . end ( ) ;
263202
203+ const imports = new Map ( ) ;
204+ const replacements = new Map ( ) ;
205+
264206 let offset = 0 ;
265207
266208 for ( const source of sources ) {
267- const { startIndex, endIndex, replacementItem } = source ;
209+ const { name, value, unquoted, startIndex, endIndex } = source ;
210+
211+ let normalizedUrl = value ;
212+ let prefix = '' ;
213+
214+ const queryParts = normalizedUrl . split ( '!' ) ;
215+
216+ if ( queryParts . length > 1 ) {
217+ normalizedUrl = queryParts . pop ( ) ;
218+ prefix = queryParts . join ( '!' ) ;
219+ }
220+
221+ normalizedUrl = normalizeUrl ( normalizedUrl ) ;
222+
223+ if ( ! urlFilter ( name , value , resourcePath ) ) {
224+ // eslint-disable-next-line no-continue
225+ continue ;
226+ }
227+
228+ let hash ;
229+ const indexHash = normalizedUrl . lastIndexOf ( '#' ) ;
230+
231+ if ( indexHash >= 0 ) {
232+ hash = normalizedUrl . substr ( indexHash , indexHash ) ;
233+ normalizedUrl = normalizedUrl . substr ( 0 , indexHash ) ;
234+ }
235+
236+ const request = requestify ( normalizedUrl , root ) ;
237+ const newUrl = prefix ? `${ prefix } !${ request } ` : request ;
238+ const importKey = newUrl ;
239+ let importName = imports . get ( importKey ) ;
240+
241+ if ( ! importName ) {
242+ importName = `___HTML_LOADER_IMPORT_${ imports . size } ___` ;
243+ imports . set ( importKey , importName ) ;
244+
245+ options . imports . push ( {
246+ importName,
247+ source : options . urlHandler ( newUrl ) ,
248+ } ) ;
249+ }
250+
251+ const replacementKey = JSON . stringify ( { newUrl, unquoted, hash } ) ;
252+ let replacementName = replacements . get ( replacementKey ) ;
253+
254+ if ( ! replacementName ) {
255+ replacementName = `___HTML_LOADER_REPLACEMENT_${ replacements . size } ___` ;
256+ replacements . set ( replacementKey , replacementName ) ;
257+
258+ options . replacements . push ( {
259+ replacementName,
260+ importName,
261+ hash,
262+ unquoted,
263+ } ) ;
264+ }
268265
269266 // eslint-disable-next-line no-param-reassign
270267 html =
271268 html . slice ( 0 , startIndex + offset ) +
272- replacementItem . name +
269+ replacementName +
273270 html . slice ( endIndex + offset ) ;
274271
275- offset += startIndex + replacementItem . name . length - endIndex ;
272+ offset += startIndex + replacementName . length - endIndex ;
276273 }
277274
278275 return html ;
0 commit comments