UNPKG

11 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.StylableResolver = exports.isInPath = exports.resolverWarnings = void 0;
4const stylable_value_parsers_1 = require("./stylable-value-parsers");
5exports.resolverWarnings = {
6 UNKNOWN_IMPORTED_FILE(path) {
7 return `cannot resolve imported file: "${path}"`;
8 },
9 UNKNOWN_IMPORTED_SYMBOL(name, path) {
10 return `cannot resolve imported symbol "${name}" from stylesheet "${path}"`;
11 },
12};
13function isInPath(extendPath, { symbol: { name: name1 }, meta: { source: source1 } }) {
14 return extendPath.find(({ symbol: { name }, meta: { source } }) => {
15 return name1 === name && source === source1;
16 });
17}
18exports.isInPath = isInPath;
19class StylableResolver {
20 constructor(fileProcessor, requireModule) {
21 this.fileProcessor = fileProcessor;
22 this.requireModule = requireModule;
23 }
24 resolveImported(imported, name) {
25 const { context, from } = imported;
26 let symbol;
27 if (from.match(/\.css$/)) {
28 let meta;
29 try {
30 meta = this.fileProcessor.process(from, false, context);
31 symbol = !name
32 ? meta.mappedSymbols[meta.root]
33 : meta.mappedSymbols[name] || meta.mappedKeyframes[name];
34 }
35 catch (e) {
36 return null;
37 }
38 return { _kind: 'css', symbol, meta };
39 }
40 else {
41 let _module;
42 try {
43 _module = this.requireModule(this.fileProcessor.resolvePath(from));
44 }
45 catch {
46 return null;
47 }
48 symbol = !name ? _module.default || _module : _module[name];
49 return { _kind: 'js', symbol, meta: null };
50 }
51 }
52 resolveImport(importSymbol) {
53 const name = importSymbol.type === 'named' ? importSymbol.name : '';
54 return this.resolveImported(importSymbol.import, name);
55 }
56 resolve(maybeImport) {
57 if (!maybeImport || maybeImport._kind !== 'import') {
58 if (maybeImport &&
59 maybeImport._kind !== 'var' &&
60 maybeImport._kind !== 'cssVar' &&
61 maybeImport._kind !== 'keyframes') {
62 if (maybeImport.alias && !maybeImport[stylable_value_parsers_1.valueMapping.extends]) {
63 maybeImport = maybeImport.alias;
64 }
65 else if (maybeImport[stylable_value_parsers_1.valueMapping.extends]) {
66 maybeImport = maybeImport[stylable_value_parsers_1.valueMapping.extends];
67 }
68 else {
69 return null;
70 }
71 }
72 else {
73 return null;
74 }
75 }
76 if (!maybeImport || maybeImport._kind !== 'import') {
77 return null;
78 }
79 return this.resolveImport(maybeImport);
80 }
81 resolveKeyframes(meta, name) {
82 var _a, _b;
83 const initSymbol = meta.mappedKeyframes[name];
84 let current = {
85 meta,
86 symbol: initSymbol,
87 };
88 while ((_a = current.symbol) === null || _a === void 0 ? void 0 : _a.import) {
89 const res = this.resolveImported(current.symbol.import, current.symbol.name);
90 if ((res === null || res === void 0 ? void 0 : res._kind) === 'css' && ((_b = res.symbol) === null || _b === void 0 ? void 0 : _b._kind) === 'keyframes') {
91 const { meta, symbol } = res;
92 current = {
93 meta,
94 symbol,
95 };
96 }
97 else {
98 return undefined;
99 }
100 }
101 if (current.symbol) {
102 return current;
103 }
104 return undefined;
105 }
106 deepResolve(maybeImport, path = []) {
107 let resolved = this.resolve(maybeImport);
108 while (resolved &&
109 resolved._kind === 'css' &&
110 resolved.symbol &&
111 resolved.symbol._kind === 'import') {
112 resolved = this.resolve(resolved.symbol);
113 }
114 if (resolved &&
115 resolved.symbol &&
116 resolved.meta &&
117 (resolved.symbol._kind === 'class' || resolved.symbol._kind === 'element') &&
118 resolved.symbol.alias &&
119 !resolved.symbol[stylable_value_parsers_1.valueMapping.extends]) {
120 if (path.includes(resolved.symbol)) {
121 return { _kind: 'css', symbol: resolved.symbol, meta: resolved.meta };
122 }
123 path.push(resolved.symbol);
124 return this.deepResolve(resolved.symbol.alias, path);
125 }
126 return resolved;
127 }
128 resolveSymbolOrigin(symbol, meta, path = []) {
129 if (!symbol || !meta) {
130 return null;
131 }
132 if (symbol._kind === 'element' || symbol._kind === 'class') {
133 if (path.includes(symbol)) {
134 return { meta, symbol, _kind: 'css' };
135 }
136 path.push(symbol);
137 const isAliasOnly = symbol.alias && !symbol[stylable_value_parsers_1.valueMapping.extends];
138 return isAliasOnly
139 ? this.resolveSymbolOrigin(symbol.alias, meta, path)
140 : { meta, symbol, _kind: 'css' };
141 }
142 else if (symbol._kind === 'cssVar') {
143 if (path.includes(symbol)) {
144 return { meta, symbol, _kind: 'css' };
145 }
146 }
147 else if (symbol._kind === 'import') {
148 const resolved = this.resolveImport(symbol);
149 if (resolved && resolved.symbol && resolved._kind === 'css') {
150 return this.resolveSymbolOrigin(resolved.symbol, resolved.meta, path);
151 }
152 else {
153 return null;
154 }
155 }
156 return null;
157 }
158 resolveClass(meta, symbol) {
159 return this.resolveName(meta, symbol, false);
160 }
161 resolveName(meta, symbol, isElement) {
162 const type = isElement ? 'element' : 'class';
163 let finalSymbol;
164 let finalMeta;
165 if (symbol._kind === type) {
166 finalSymbol = symbol;
167 finalMeta = meta;
168 }
169 else if (symbol._kind === 'import') {
170 const resolved = this.deepResolve(symbol);
171 if (resolved && resolved._kind === 'css' && resolved.symbol) {
172 if (resolved.symbol._kind === 'class' || resolved.symbol._kind === 'element') {
173 finalSymbol = resolved.symbol;
174 finalMeta = resolved.meta;
175 }
176 else {
177 // TODO: warn
178 }
179 }
180 else {
181 // TODO: warn
182 }
183 }
184 else {
185 // TODO: warn
186 }
187 if (finalMeta && finalSymbol) {
188 return {
189 _kind: 'css',
190 symbol: finalSymbol,
191 meta: finalMeta,
192 };
193 }
194 else {
195 return null;
196 }
197 }
198 resolveElement(meta, symbol) {
199 return this.resolveName(meta, symbol, true);
200 }
201 resolveExtends(meta, className, isElement = false, transformer, reportError) {
202 const bucket = isElement ? meta.elements : meta.classes;
203 const customSelector = isElement ? null : meta.customSelectors[':--' + className];
204 if (!bucket[className] && !customSelector) {
205 return [];
206 }
207 if (customSelector && transformer) {
208 const parsed = transformer.resolveSelectorElements(meta, customSelector);
209 if (parsed.length === 1) {
210 return parsed[0][parsed[0].length - 1].resolved;
211 }
212 else {
213 return [];
214 }
215 }
216 let current = {
217 _kind: 'css',
218 symbol: bucket[className],
219 meta,
220 };
221 const extendPath = [];
222 while (current === null || current === void 0 ? void 0 : current.symbol) {
223 if (isInPath(extendPath, current)) {
224 break;
225 }
226 extendPath.push(current);
227 const parent = current.symbol[stylable_value_parsers_1.valueMapping.extends] || current.symbol.alias;
228 if (parent) {
229 if (parent._kind === 'import') {
230 const res = this.resolve(parent);
231 if (res &&
232 res._kind === 'css' &&
233 res.symbol &&
234 (res.symbol._kind === 'element' || res.symbol._kind === 'class')) {
235 const { _kind, meta, symbol } = res;
236 current = {
237 _kind,
238 meta,
239 symbol,
240 };
241 }
242 else {
243 if (reportError) {
244 reportError(res, parent, extendPath, meta, className, isElement);
245 }
246 break;
247 }
248 }
249 else {
250 current = { _kind: 'css', symbol: parent, meta };
251 }
252 }
253 else {
254 break;
255 }
256 }
257 return extendPath;
258 }
259 validateImports(meta, diagnostics) {
260 for (const importObj of meta.imports) {
261 const resolvedImport = this.resolveImported(importObj, '');
262 if (!resolvedImport) {
263 // warn about unknown imported files
264 const fromDecl = importObj.rule.nodes &&
265 importObj.rule.nodes.find((decl) => decl.type === 'decl' && decl.prop === stylable_value_parsers_1.valueMapping.from);
266 if (fromDecl) {
267 diagnostics.warn(fromDecl, exports.resolverWarnings.UNKNOWN_IMPORTED_FILE(importObj.fromRelative), { word: importObj.fromRelative });
268 }
269 }
270 else if (resolvedImport._kind === 'css') {
271 // warn about unknown named imported symbols
272 for (const name in importObj.named) {
273 const origName = importObj.named[name];
274 const resolvedSymbol = this.resolveImported(importObj, origName);
275 const namedDecl = importObj.rule.nodes &&
276 importObj.rule.nodes.find((decl) => decl.type === 'decl' && decl.prop === stylable_value_parsers_1.valueMapping.named);
277 if (!resolvedSymbol.symbol && namedDecl) {
278 diagnostics.warn(namedDecl, exports.resolverWarnings.UNKNOWN_IMPORTED_SYMBOL(origName, importObj.fromRelative), { word: origName });
279 }
280 }
281 }
282 }
283 }
284 resolvePath(path, context) {
285 return this.fileProcessor.resolvePath(path, context);
286 }
287}
288exports.StylableResolver = StylableResolver;
289//# sourceMappingURL=stylable-resolver.js.map
\No newline at end of file