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