150 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			150 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| "use strict";
 | |
| var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
 | |
|     if (k2 === undefined) k2 = k;
 | |
|     Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
 | |
| }) : (function(o, m, k, k2) {
 | |
|     if (k2 === undefined) k2 = k;
 | |
|     o[k2] = m[k];
 | |
| }));
 | |
| var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
 | |
|     Object.defineProperty(o, "default", { enumerable: true, value: v });
 | |
| }) : function(o, v) {
 | |
|     o["default"] = v;
 | |
| });
 | |
| var __importStar = (this && this.__importStar) || function (mod) {
 | |
|     if (mod && mod.__esModule) return mod;
 | |
|     var result = {};
 | |
|     if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
 | |
|     __setModuleDefault(result, mod);
 | |
|     return result;
 | |
| };
 | |
| Object.defineProperty(exports, "__esModule", { value: true });
 | |
| exports.pitch = void 0;
 | |
| const qs = __importStar(require("querystring"));
 | |
| const util_1 = require("./util");
 | |
| const selfPath = require.resolve('./index');
 | |
| // const templateLoaderPath = require.resolve('./templateLoader')
 | |
| const stylePostLoaderPath = require.resolve('./stylePostLoader');
 | |
| const styleInlineLoaderPath = require.resolve('./styleInlineLoader');
 | |
| const isESLintLoader = (l) => /(\/|\\|@)eslint-loader/.test(l.path);
 | |
| const isNullLoader = (l) => /(\/|\\|@)null-loader/.test(l.path);
 | |
| const isCSSLoader = (l) => /(\/|\\|@)css-loader/.test(l.path);
 | |
| const isCacheLoader = (l) => /(\/|\\|@)cache-loader/.test(l.path);
 | |
| const isNotPitcher = (l) => l.path !== __filename;
 | |
| const pitcher = (code) => code;
 | |
| // This pitching loader is responsible for intercepting all vue block requests
 | |
| // and transform it into appropriate requests.
 | |
| const pitch = function () {
 | |
|     var _a;
 | |
|     const context = this;
 | |
|     const rawLoaders = context.loaders.filter(isNotPitcher);
 | |
|     let loaders = rawLoaders;
 | |
|     // do not inject if user uses null-loader to void the type (#1239)
 | |
|     if (loaders.some(isNullLoader)) {
 | |
|         return;
 | |
|     }
 | |
|     const query = qs.parse(context.resourceQuery.slice(1));
 | |
|     const isInlineBlock = /\.vue$/.test(context.resourcePath);
 | |
|     // eslint-loader may get matched multiple times
 | |
|     // if this is an inline block, since the whole file itself is being linted,
 | |
|     // remove eslint-loader to avoid duplicate linting.
 | |
|     if (isInlineBlock) {
 | |
|         loaders = loaders.filter((l) => !isESLintLoader(l));
 | |
|     }
 | |
|     // Important: dedupe loaders since both the original rule
 | |
|     // and the cloned rule would match a source import request or a
 | |
|     // resourceQuery-only rule that intends to target a custom block with no lang
 | |
|     const seen = new Map();
 | |
|     loaders = loaders.filter((loader) => {
 | |
|         const identifier = typeof loader === 'string'
 | |
|             ? loader
 | |
|             : // Dedupe based on both path and query if available. This is important
 | |
|                 // in Vue CLI so that postcss-loaders with different options can co-exist
 | |
|                 loader.path + loader.query;
 | |
|         if (!seen.has(identifier)) {
 | |
|             seen.set(identifier, true);
 | |
|             return true;
 | |
|         }
 | |
|     });
 | |
|     // Inject style-post-loader before css-loader for scoped CSS and trimming
 | |
|     const isWebpack5 = (0, util_1.testWebpack5)(context._compiler);
 | |
|     const options = ((0, util_1.getOptions)(context) || {});
 | |
|     if (query.type === `style`) {
 | |
|         if (isWebpack5 && ((_a = context._compiler) === null || _a === void 0 ? void 0 : _a.options.experiments.css)) {
 | |
|             // If user enables `experiments.css`, then we are trying to emit css code directly.
 | |
|             // Although we can target requests like `xxx.vue?type=style` to match `type: "css"`,
 | |
|             // it will make the plugin a mess.
 | |
|             if (!options.experimentalInlineMatchResource) {
 | |
|                 context.emitError(new Error('`experimentalInlineMatchResource` should be enabled if `experiments.css` enabled currently'));
 | |
|                 return '';
 | |
|             }
 | |
|             if (query.inline || query.module) {
 | |
|                 context.emitError(new Error('`inline` or `module` is currently not supported with `experiments.css` enabled'));
 | |
|                 return '';
 | |
|             }
 | |
|             const loaderString = [stylePostLoaderPath, ...loaders]
 | |
|                 .map((loader) => {
 | |
|                 return typeof loader === 'string' ? loader : loader.request;
 | |
|             })
 | |
|                 .join('!');
 | |
|             const styleRequest = (0, util_1.stringifyRequest)(context, `${context.resourcePath}${query.lang ? `.${query.lang}` : ''}${context.resourceQuery}!=!-!${loaderString}!${context.resource}`);
 | |
|             return `@import ${styleRequest};`;
 | |
|         }
 | |
|         const cssLoaderIndex = loaders.findIndex(isCSSLoader);
 | |
|         if (cssLoaderIndex > -1) {
 | |
|             // if inlined, ignore any loaders after css-loader and replace w/ inline
 | |
|             // loader
 | |
|             const afterLoaders = query.inline != null
 | |
|                 ? [styleInlineLoaderPath]
 | |
|                 : loaders.slice(0, cssLoaderIndex + 1);
 | |
|             const beforeLoaders = loaders.slice(cssLoaderIndex + 1);
 | |
|             return genProxyModule([...afterLoaders, stylePostLoaderPath, ...beforeLoaders], context, !!query.module || query.inline != null, query.lang || 'css');
 | |
|         }
 | |
|     }
 | |
|     // if a custom block has no other matching loader other than vue-loader itself
 | |
|     // or cache-loader, we should ignore it
 | |
|     if (query.type === `custom` && shouldIgnoreCustomBlock(loaders)) {
 | |
|         return ``;
 | |
|     }
 | |
|     // Rewrite request. Technically this should only be done when we have deduped
 | |
|     // loaders. But somehow this is required for block source maps to work.
 | |
|     return genProxyModule(loaders, context, query.type !== 'template', query.ts ? 'ts' : query.lang);
 | |
| };
 | |
| exports.pitch = pitch;
 | |
| function genProxyModule(loaders, context, exportDefault = true, lang = 'js') {
 | |
|     const request = genRequest(loaders, lang, context);
 | |
|     // return a proxy module which simply re-exports everything from the
 | |
|     // actual request. Note for template blocks the compiled module has no
 | |
|     // default export.
 | |
|     return ((exportDefault ? `export { default } from ${request}; ` : ``) +
 | |
|         `export * from ${request}`);
 | |
| }
 | |
| function genRequest(loaders, lang, context) {
 | |
|     const isWebpack5 = (0, util_1.testWebpack5)(context._compiler);
 | |
|     const options = ((0, util_1.getOptions)(context) || {});
 | |
|     const enableInlineMatchResource = isWebpack5 && options.experimentalInlineMatchResource;
 | |
|     const loaderStrings = loaders.map((loader) => {
 | |
|         return typeof loader === 'string' ? loader : loader.request;
 | |
|     });
 | |
|     const resource = context.resourcePath + context.resourceQuery;
 | |
|     if (enableInlineMatchResource) {
 | |
|         return (0, util_1.stringifyRequest)(context, `${context.resourcePath}${lang ? `.${lang}` : ''}${context.resourceQuery}!=!-!${[...loaderStrings, resource].join('!')}`);
 | |
|     }
 | |
|     return (0, util_1.stringifyRequest)(context, '-!' + [...loaderStrings, resource].join('!'));
 | |
| }
 | |
| function shouldIgnoreCustomBlock(loaders) {
 | |
|     const actualLoaders = loaders.filter((loader) => {
 | |
|         // vue-loader
 | |
|         if (loader.path === selfPath) {
 | |
|             return false;
 | |
|         }
 | |
|         // cache-loader
 | |
|         if (isCacheLoader(loader)) {
 | |
|             return false;
 | |
|         }
 | |
|         return true;
 | |
|     });
 | |
|     return actualLoaders.length === 0;
 | |
| }
 | |
| exports.default = pitcher;
 |