UNPKG

3.86 kBJavaScriptView Raw
1"use strict";
2
3var _path = require("path");
4
5var _util = _interopRequireDefault(require("util"));
6
7var _VirtualModulePlugin = _interopRequireDefault(require("./VirtualModulePlugin"));
8
9var _loaders = require("./utils/loaders");
10
11var _replaceComposes = _interopRequireDefault(require("./utils/replaceComposes"));
12
13function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
14
15/* eslint-disable max-classes-per-file */
16const debug = _util.default.debuglog('astroturf:loader');
17
18const LOADER_PLUGIN = Symbol('loader added VM plugin');
19const SEEN = Symbol('astroturf seen modules');
20
21module.exports = async function loader(content, _map, meta) {
22 const {
23 resourcePath,
24 _compilation: compilation
25 } = this;
26 const cb = this.async();
27 if (!compilation[SEEN]) compilation[SEEN] = new Map();
28
29 const loadModule = _util.default.promisify((request, done) => this.loadModule(request, (err, _, _1, module) => done(err, module)));
30
31 const resolve = _util.default.promisify(this.resolve);
32
33 const dependencies = [];
34
35 const buildDependency = async request => {
36 const resource = await resolve((0, _path.dirname)(resourcePath), request);
37 return loadModule(resource);
38 };
39
40 function resolveDependency(interpolation, localStyle, node) {
41 const {
42 identifier,
43 request
44 } = interpolation;
45 if (!interpolation.identifier) return null;
46 const {
47 loc
48 } = node;
49 const memberProperty = 'property' in node && node.property.name;
50 const imported = `###ASTROTURF_IMPORTED_${dependencies.length}###`;
51 const source = `###ASTROTURF_SOURCE_${dependencies.length}###`;
52 debug(`resolving dependency: ${request}`);
53 dependencies.push(buildDependency(request).then(({
54 styles,
55 resource
56 }) => {
57 const style = styles.find(s => s.identifier === identifier);
58
59 if (!style) {
60 throw (0, _loaders.buildDependencyError)(content, interpolation, styles, resource, loc);
61 }
62
63 debug(`resolved request to: ${style.absoluteFilePath}`); // replace composes first bc we need need to use a different identifier
64
65 localStyle.value = (0, _replaceComposes.default)(localStyle.value, match => match.replace(source, `~${style.absoluteFilePath}`).replace(imported, style.type === 'stylesheet' ? memberProperty : 'cls2')); // replace selector interpolations
66
67 localStyle.value = localStyle.value.replace(source, `~${style.absoluteFilePath}`).replace(imported, style.type === 'stylesheet' ? memberProperty : 'cls1');
68 }));
69 return {
70 source,
71 imported
72 };
73 }
74
75 try {
76 const options = await (0, _loaders.resolveOptions)(this);
77 const {
78 styles = [],
79 changeset
80 } = (0, _loaders.collectStyles)(content, resourcePath, resolveDependency, options);
81
82 if (meta) {
83 meta.styles = styles;
84 }
85
86 if (!styles.length) {
87 return cb(null, content);
88 }
89
90 compilation[SEEN].set(resourcePath, styles);
91 this._module.styles = styles; // @ts-ignore
92
93 let {
94 emitVirtualFile
95 } = this; // The plugin isn't loaded
96
97 if (!emitVirtualFile) {
98 const {
99 compiler
100 } = compilation;
101 let plugin = compiler[LOADER_PLUGIN];
102
103 if (!plugin) {
104 debug('adding plugin to compiiler');
105 plugin = _VirtualModulePlugin.default.bootstrap(compilation);
106 compiler[LOADER_PLUGIN] = plugin;
107 }
108
109 emitVirtualFile = plugin.addFile;
110 }
111
112 return Promise.all(dependencies).then(() => {
113 styles.forEach(style => {
114 emitVirtualFile(style.absoluteFilePath, style.value); // compilation.fileTimestamps.set(style.absoluteFilePath, +mtime);
115 });
116 const result = (0, _loaders.replaceStyleTemplates)(this, resourcePath, content, changeset);
117 cb(null, result.code, result.map);
118 }).catch(cb);
119 } catch (err) {
120 return cb(err);
121 }
122};
\No newline at end of file