1 | "use strict";
|
2 |
|
3 | var _crypto = _interopRequireDefault(require("crypto"));
|
4 |
|
5 | var _fs = require("fs");
|
6 |
|
7 | var _path = require("path");
|
8 |
|
9 | var _util = _interopRequireDefault(require("util"));
|
10 |
|
11 | var _v = require("v8");
|
12 |
|
13 | var _findCacheDir = _interopRequireDefault(require("find-cache-dir"));
|
14 |
|
15 | var _loaders = require("./utils/loaders");
|
16 |
|
17 | var _replaceComposes = _interopRequireDefault(require("./utils/replaceComposes"));
|
18 |
|
19 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
20 |
|
21 | const cacheDir = (0, _findCacheDir.default)({
|
22 | name: 'astroturf-loader'
|
23 | });
|
24 | (0, _fs.mkdirSync)(cacheDir, {
|
25 | recursive: true
|
26 | });
|
27 | const inMemoryStyleCache = new Map();
|
28 |
|
29 | const hash = name => `${_crypto.default.createHash('md4').update(name).digest('hex')}.cache`;
|
30 |
|
31 | const cache = {
|
32 | async set(source, newStyles) {
|
33 | const styles = (await this.get(source)) || new Map();
|
34 | inMemoryStyleCache.set(source, styles);
|
35 | newStyles.forEach(style => {
|
36 | styles.set(style.identifier, style);
|
37 | });
|
38 | await _fs.promises.writeFile(`${cacheDir}/${hash(source)}`, (0, _v.serialize)(styles));
|
39 | },
|
40 |
|
41 | async get(source) {
|
42 | let styles = inMemoryStyleCache.get(source);
|
43 |
|
44 | if (!styles) {
|
45 | try {
|
46 | styles = (0, _v.deserialize)(await _fs.promises.readFile(`${cacheDir}/${hash(source)}`));
|
47 | inMemoryStyleCache.set(source, styles);
|
48 | } catch (err) {
|
49 |
|
50 | }
|
51 | }
|
52 |
|
53 | return styles;
|
54 | }
|
55 |
|
56 | };
|
57 |
|
58 | const debug = _util.default.debuglog('astroturf:loader');
|
59 |
|
60 | module.exports = async function loader(content, _map, meta) {
|
61 | const {
|
62 | resourcePath
|
63 | } = this;
|
64 | const loaderOpts = this.getOptions() || {};
|
65 | const cb = this.async();
|
66 |
|
67 | const loadModule = _util.default.promisify((request, done) => this.loadModule(request, (err, _, _1, module) => done(err, module)));
|
68 |
|
69 | if (loaderOpts.style) {
|
70 | const styleId = this.resourceQuery.slice(1);
|
71 | const styles = await cache.get(resourcePath);
|
72 | let style = styles == null ? void 0 : styles.get(styleId);
|
73 |
|
74 | if (!style) {
|
75 | var _inMemoryStyleCache$g;
|
76 |
|
77 | await loadModule(resourcePath);
|
78 | style = (_inMemoryStyleCache$g = inMemoryStyleCache.get(resourcePath)) == null ? void 0 : _inMemoryStyleCache$g.get(styleId);
|
79 | }
|
80 |
|
81 | if (!style) {
|
82 | return cb(new Error(`Could not resolve style ${styleId} in file ${resourcePath}`));
|
83 | }
|
84 |
|
85 | if (!this._module.matchResource) this._module.matchResource = style.absoluteFilePath;
|
86 | return cb(null, style.value);
|
87 | }
|
88 |
|
89 | function getLoaderRequest(from, to, id) {
|
90 | const cssBase = (0, _path.basename)(to);
|
91 | const file = `${cssBase}!=!astroturf/inline-loader?style=1!${from}?${id}`;
|
92 | return file;
|
93 | }
|
94 |
|
95 | const resolve = _util.default.promisify(this.resolve);
|
96 |
|
97 | const dependencies = [];
|
98 |
|
99 | const buildDependency = async request => {
|
100 | const resource = await resolve((0, _path.dirname)(resourcePath), request);
|
101 | return loadModule(resource);
|
102 | };
|
103 |
|
104 | function resolveDependency(interpolation, localStyle, node) {
|
105 | const {
|
106 | identifier,
|
107 | request
|
108 | } = interpolation;
|
109 | if (!interpolation.identifier) return null;
|
110 | const {
|
111 | loc
|
112 | } = node;
|
113 | const memberProperty = 'property' in node && node.property.name;
|
114 | const imported = `###ASTROTURF_IMPORTED_${dependencies.length}###`;
|
115 | const source = `###ASTROTURF_SOURCE_${dependencies.length}###`;
|
116 | debug(`resolving dependency: ${request}`);
|
117 | dependencies.push(buildDependency(request).then(module => {
|
118 | const styles = inMemoryStyleCache.get(module.resource);
|
119 | const style = styles == null ? void 0 : styles.get(identifier);
|
120 |
|
121 | if (!style) {
|
122 | throw (0, _loaders.buildDependencyError)(content, interpolation, Array.from((styles == null ? void 0 : styles.values()) || []), module.resource, loc);
|
123 | }
|
124 |
|
125 | debug(`resolved request to: ${style.absoluteFilePath}`);
|
126 | const styleReq = getLoaderRequest(module.resource, style.absoluteFilePath, style.identifier);
|
127 |
|
128 | localStyle.value = (0, _replaceComposes.default)(localStyle.value, match => match.replace(source, styleReq).replace(imported, style.type === 'stylesheet' ? memberProperty : 'cls2'));
|
129 |
|
130 | localStyle.value = localStyle.value.replace(source, styleReq).replace(imported, style.type === 'stylesheet' ? memberProperty : 'cls1');
|
131 | }));
|
132 | return {
|
133 | source,
|
134 | imported
|
135 | };
|
136 | }
|
137 |
|
138 | try {
|
139 | const options = await (0, _loaders.resolveOptions)(this);
|
140 | options.getRequirePath = getLoaderRequest;
|
141 | const {
|
142 | styles = [],
|
143 | changeset
|
144 | } = (0, _loaders.collectStyles)(content, resourcePath, resolveDependency, options);
|
145 |
|
146 | if (meta) {
|
147 | meta.styles = styles;
|
148 | }
|
149 |
|
150 | if (!styles.length) {
|
151 | return cb(null, content);
|
152 | }
|
153 |
|
154 | return Promise.all(dependencies).then(async () => {
|
155 | await cache.set(resourcePath, styles);
|
156 | const result = (0, _loaders.replaceStyleTemplates)(this, resourcePath, content, changeset);
|
157 | cb(null, result.code, result.map);
|
158 | }).catch(cb);
|
159 | } catch (err) {
|
160 | return cb(err);
|
161 | }
|
162 | }; |
\ | No newline at end of file |