@@ -3,6 +3,7 @@ const Preprocessor = require('./Preprocessor');
33const PluginService = require ( '../Plugin/PluginService' ) ;
44const { parseQuery } = require ( '../Common/Helpers' ) ;
55const { rootSourceDir, filterParentPaths } = require ( '../Common/FileUtils' ) ;
6+ const { findRootIssuer } = require ( '../Common/CompilationHelpers' ) ;
67const { watchPathsException, dataFileNotFoundException, dataFileException } = require ( './Messages/Exeptions' ) ;
78
89/**
@@ -21,6 +22,7 @@ class Option {
2122 static #options;
2223 static #rootContext;
2324 static #resourcePath;
25+ static #pluginOption;
2426
2527 // rule: the first value is default
2628 static preprocessorModes = new Set ( [ 'render' , 'compile' ] ) ;
@@ -33,8 +35,9 @@ class Option {
3335 const queryData = parseQuery ( resourceQuery ) ;
3436 let options = PluginService . getLoaderCache ( loaderId ) ;
3537
36- this . fileSystem = loaderContext . fs . fileSystem ;
38+ this . #pluginOption = PluginService . getOptions ( ) ;
3739 this . #watch = PluginService . isWatchMode ( ) ;
40+ this . fileSystem = loaderContext . fs . fileSystem ;
3841 this . #webpackOptions = loaderContext . _compiler . options || { } ;
3942 this . #rootContext = rootContext ;
4043 this . #resourcePath = resourcePath ;
@@ -43,6 +46,9 @@ class Option {
4346 const loaderOptions = PluginService . getLoaderOptions ( ) ;
4447 options = { ...loaderOptions , ...( loaderContext . getOptions ( ) || { } ) } ;
4548
49+ // save the initial value defined in the webpack config
50+ options . originalPreprocessorMode = options . preprocessorMode ;
51+
4652 // the assets root path is used for resolving files specified in attributes (`sources` option)
4753 // allow both 'root' and 'basedir' option name for compatibility
4854 const basedir = options . root || options . basedir || false ;
@@ -53,16 +59,57 @@ class Option {
5359
5460 PluginService . setLoaderCache ( loaderId , options ) ;
5561 }
56-
5762 this . #options = options ;
5863
59- // preprocessor mode
64+ // if the data option is a string, it must be an absolute or relative filename of an existing file that exports the data
65+ const loaderData = this . #loadData( options . data ) ;
66+ const entryData = this . #loadData( loaderContext . entryData ) ;
67+ const contextData = loaderContext . data || { } ;
68+
69+ // merge plugin and loader data, the plugin data property overrides the same loader data property
70+ loaderObject . data = { ...contextData , ...loaderData , ...entryData , ...queryData } ;
71+
72+ // beforePreprocessor
73+ if ( typeof options . beforePreprocessor !== 'function' ) {
74+ options . beforePreprocessor = null ;
75+ }
76+
77+ // preprocessor
78+ this . #initPreprocessor( loaderContext , queryData ) ;
79+
80+ // clean loaderContext of artifacts
81+ if ( loaderContext . entryData != null ) delete loaderContext . entryData ;
82+
83+ // defaults, cacheable is true, the loader option is not documented in readme, use it only for debugging
84+ if ( loaderContext . cacheable != null ) loaderContext . cacheable ( options ?. cacheable !== false ) ;
85+
86+ if ( this . #watch) this . #initWatchFiles( ) ;
87+ }
88+
89+ /**
90+ * @param {BundlerPluginLoaderContext } loaderContext The loader context of Webpack.
91+ * @param {Object } queryData The parsed parameters from the url query.
92+ */
93+ static #initPreprocessor( loaderContext , queryData ) {
94+ const pluginOption = this . #pluginOption;
95+ const options = this . #options;
6096 const issuer = loaderContext . _module . resourceResolveData ?. context ?. issuer || '' ;
6197 let [ defaultPreprocessorMode ] = this . preprocessorModes ;
98+ let isIssuerScript = false ;
6299 let preprocessorMode ;
63100
101+ if ( issuer ) {
102+ isIssuerScript = pluginOption . isScript ( issuer ) ;
103+ if ( ! isIssuerScript ) {
104+ const rootIssuer = findRootIssuer ( PluginService . compilation , issuer ) ;
105+ if ( rootIssuer ) {
106+ isIssuerScript = pluginOption . isScript ( rootIssuer ) ;
107+ }
108+ }
109+ }
110+
64111 // rule: defaults, if issuer is JS, then compile template to the template function
65- if ( issuer && PluginService . getOptions ( ) . isScript ( issuer ) ) {
112+ if ( isIssuerScript ) {
66113 preprocessorMode = defaultPreprocessorMode = 'compile' ;
67114 }
68115
@@ -75,61 +122,35 @@ class Option {
75122 }
76123 }
77124
125+ // reset the original option value, also no cached state,
126+ // because the loader works in different modes depend on the context
127+ options . preprocessorMode = options . originalPreprocessorMode ;
128+
78129 if ( preprocessorMode && this . preprocessorModes . has ( preprocessorMode ) ) {
79130 options . preprocessorMode = preprocessorMode ;
80131 } else if ( ! this . preprocessorModes . has ( options . preprocessorMode ) ) {
81132 options . preprocessorMode = defaultPreprocessorMode ;
82133 }
83134
84- // if the data option is a string, it must be an absolute or relative filename of an existing file that exports the data
85- const loaderData = this . loadData ( options . data ) ;
86- const entryData = this . loadData ( loaderContext . entryData ) ;
87- const contextData = loaderContext . data || { } ;
88-
89- //console.log('*** INIT DATA1: ', { data: loaderContext.data });
90-
91- // merge plugin and loader data, the plugin data property overrides the same loader data property
92- const data = { ...contextData , ...loaderData , ...entryData , ...queryData } ;
93- if ( Object . keys ( data ) . length > 0 ) loaderObject . data = data ;
94-
95- loaderObject . data = data ;
96-
97- //if (!loaderObject.data) loaderObject.data = {};
98-
99- //console.log('*** INIT DATA2: ', { data: loaderContext.data });
100-
101- // beforePreprocessor
102- if ( typeof options . beforePreprocessor !== 'function' ) {
103- options . beforePreprocessor = null ;
104- }
105-
106- // preprocessor
107135 if ( ! Preprocessor . isUsed ( options . preprocessor ) ) {
108136 options . preprocessor = Preprocessor . factory ( loaderContext , {
109137 preprocessor : options . preprocessor ,
110- watch : this . #watch,
111138 options : options . preprocessorOptions ,
139+ watch : this . #watch,
112140 } ) ;
113141 }
114-
115- // clean loaderContext of artifacts
116- if ( loaderContext . entryData != null ) delete loaderContext . entryData ;
117-
118- // defaults, cacheable is true, the loader option is not documented in readme, use it only for debugging
119- if ( loaderContext . cacheable != null ) loaderContext . cacheable ( options ?. cacheable !== false ) ;
120-
121- if ( this . #watch) this . #initWatchFiles( ) ;
122142 }
123143
124144 static #initWatchFiles( ) {
145+ const pluginOption = this . #pluginOption;
125146 const watchFiles = {
126147 // watch files only in the directories;
127148 // defaults is first-level subdirectory of a template, relative to root context
128149 paths : [ ] ,
129150
130151 // watch only files matched to RegExps,
131152 // if empty then watch all files, except ignored
132- files : PluginService . getOptions ( ) . getEntryTest ( ) ,
153+ files : pluginOption . getEntryTest ( ) ,
133154
134155 // ignore paths and files matched to RegExps
135156 ignore : [
@@ -142,7 +163,7 @@ class Option {
142163 } ;
143164
144165 const fs = this . fileSystem ;
145- const { paths, files, ignore } = PluginService . getOptions ( ) . getWatchFiles ( ) ;
166+ const { paths, files, ignore } = pluginOption . getWatchFiles ( ) ;
146167 const watchDirs = new Set ( [ rootSourceDir ( this . #rootContext, this . #resourcePath) ] ) ;
147168 const rootContext = this . #rootContext;
148169
@@ -195,7 +216,7 @@ class Option {
195216 * @param {Object|string|null } dataValue If string, the relative or absolute filename.
196217 * @return {Object }
197218 */
198- static loadData ( dataValue ) {
219+ static # loadData( dataValue ) {
199220 if ( typeof dataValue !== 'string' ) return dataValue || { } ;
200221
201222 let dataFile = PluginService . dataFiles . get ( dataValue ) ;
0 commit comments