1 | "use strict";
|
2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
3 | if (k2 === undefined) k2 = k;
|
4 | Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
5 | }) : (function(o, m, k, k2) {
|
6 | if (k2 === undefined) k2 = k;
|
7 | o[k2] = m[k];
|
8 | }));
|
9 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
10 | Object.defineProperty(o, "default", { enumerable: true, value: v });
|
11 | }) : function(o, v) {
|
12 | o["default"] = v;
|
13 | });
|
14 | var __importStar = (this && this.__importStar) || function (mod) {
|
15 | if (mod && mod.__esModule) return mod;
|
16 | var result = {};
|
17 | if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
18 | __setModuleDefault(result, mod);
|
19 | return result;
|
20 | };
|
21 | Object.defineProperty(exports, "__esModule", { value: true });
|
22 | exports.appendMixin = exports.appendMixins = exports.mixinWarnings = void 0;
|
23 | const path_1 = require("path");
|
24 | const postcss = __importStar(require("postcss"));
|
25 | const functions_1 = require("./functions");
|
26 | const parser_1 = require("./parser");
|
27 | const stylable_assets_1 = require("./stylable-assets");
|
28 | const stylable_utils_1 = require("./stylable-utils");
|
29 | const stylable_value_parsers_1 = require("./stylable-value-parsers");
|
30 | exports.mixinWarnings = {
|
31 | FAILED_TO_APPLY_MIXIN(error) {
|
32 | return `could not apply mixin: ${error}`;
|
33 | },
|
34 | JS_MIXIN_NOT_A_FUNC() {
|
35 | return `js mixin must be a function`;
|
36 | },
|
37 | CIRCULAR_MIXIN(circularPaths) {
|
38 | return `circular mixin found: ${circularPaths.join(' --> ')}`;
|
39 | },
|
40 | UNKNOWN_MIXIN_SYMBOL(name) {
|
41 | return `cannot mixin unknown symbol "${name}"`;
|
42 | },
|
43 | };
|
44 | function appendMixins(transformer, rule, meta, variableOverride, cssVarsMapping, path = []) {
|
45 | if (!rule.mixins || rule.mixins.length === 0) {
|
46 | return;
|
47 | }
|
48 | rule.mixins.forEach((mix) => {
|
49 | appendMixin(mix, transformer, rule, meta, variableOverride, cssVarsMapping, path);
|
50 | });
|
51 | rule.mixins.length = 0;
|
52 | rule.walkDecls(stylable_value_parsers_1.mixinDeclRegExp, (node) => node.remove());
|
53 | }
|
54 | exports.appendMixins = appendMixins;
|
55 | function appendMixin(mix, transformer, rule, meta, variableOverride, cssVarsMapping, path = []) {
|
56 | if (checkRecursive(transformer, meta, mix, rule, path)) {
|
57 | return;
|
58 | }
|
59 | const local = meta.mappedSymbols[mix.mixin.type];
|
60 | if (local && (local._kind === 'class' || local._kind === 'element')) {
|
61 | handleLocalClassMixin(mix, transformer, meta, variableOverride, cssVarsMapping, path, rule);
|
62 | }
|
63 | else {
|
64 | const resolvedMixin = transformer.resolver.resolve(mix.ref);
|
65 | if (resolvedMixin) {
|
66 | if (resolvedMixin._kind === 'js') {
|
67 | if (typeof resolvedMixin.symbol === 'function') {
|
68 | try {
|
69 | handleJSMixin(transformer, mix, resolvedMixin.symbol, meta, rule, variableOverride);
|
70 | }
|
71 | catch (e) {
|
72 | transformer.diagnostics.error(rule, exports.mixinWarnings.FAILED_TO_APPLY_MIXIN(e), { word: mix.mixin.type });
|
73 | return;
|
74 | }
|
75 | }
|
76 | else {
|
77 | transformer.diagnostics.error(rule, exports.mixinWarnings.JS_MIXIN_NOT_A_FUNC(), {
|
78 | word: mix.mixin.type,
|
79 | });
|
80 | }
|
81 | }
|
82 | else {
|
83 | handleImportedCSSMixin(transformer, mix, rule, meta, path, variableOverride, cssVarsMapping);
|
84 | }
|
85 | }
|
86 | else {
|
87 |
|
88 | }
|
89 | }
|
90 | }
|
91 | exports.appendMixin = appendMixin;
|
92 | function checkRecursive(transformer, meta, mix, rule, path) {
|
93 | const symbolName = mix.ref.name === meta.root
|
94 | ? mix.ref._kind === 'class'
|
95 | ? meta.root
|
96 | : 'default'
|
97 | : mix.mixin.type;
|
98 | const isRecursive = path.includes(symbolName + ' from ' + meta.source);
|
99 | if (isRecursive) {
|
100 |
|
101 | transformer.diagnostics.warn(rule, exports.mixinWarnings.CIRCULAR_MIXIN(path), {
|
102 | word: symbolName,
|
103 | });
|
104 | return true;
|
105 | }
|
106 | return false;
|
107 | }
|
108 | function handleJSMixin(transformer, mix, mixinFunction, meta, rule, variableOverride) {
|
109 | const res = mixinFunction(mix.mixin.options.map((v) => v.value));
|
110 | const mixinRoot = parser_1.cssObjectToAst(res).root;
|
111 | mixinRoot.walkDecls((decl) => {
|
112 | if (!stylable_utils_1.isValidDeclaration(decl)) {
|
113 | decl.value = String(decl);
|
114 | }
|
115 | });
|
116 | transformer.transformAst(mixinRoot, meta, undefined, variableOverride, [], true);
|
117 | const mixinPath = mix.ref.import.from;
|
118 | stylable_assets_1.fixRelativeUrls(mixinRoot, transformer.fileProcessor.resolvePath(mixinPath, path_1.dirname(meta.source)), meta.source);
|
119 | stylable_utils_1.mergeRules(mixinRoot, rule);
|
120 | }
|
121 | function createMixinRootFromCSSResolve(transformer, mix, meta, resolvedClass, path, decl, variableOverride, cssVarsMapping) {
|
122 | const isRootMixin = resolvedClass.symbol.name === resolvedClass.meta.root;
|
123 | const mixinRoot = stylable_utils_1.createSubsetAst(resolvedClass.meta.ast, (resolvedClass.symbol._kind === 'class' ? '.' : '') + resolvedClass.symbol.name, undefined, isRootMixin);
|
124 | const namedArgs = mix.mixin.options;
|
125 | if (mix.mixin.partial) {
|
126 | filterPartialMixinDecl(meta, mixinRoot, Object.keys(namedArgs));
|
127 | }
|
128 | const resolvedArgs = functions_1.resolveArgumentsValue(namedArgs, transformer, meta, transformer.diagnostics, decl, variableOverride, path, cssVarsMapping);
|
129 | const mixinMeta = isRootMixin
|
130 | ? resolvedClass.meta
|
131 | : createInheritedMeta(resolvedClass);
|
132 | const symbolName = isRootMixin ? 'default' : mix.mixin.type;
|
133 | transformer.transformAst(mixinRoot, mixinMeta, undefined, resolvedArgs, path.concat(symbolName + ' from ' + meta.source), true);
|
134 | stylable_assets_1.fixRelativeUrls(mixinRoot, mixinMeta.source, meta.source);
|
135 | return mixinRoot;
|
136 | }
|
137 | function handleImportedCSSMixin(transformer, mix, rule, meta, path, variableOverride, cssVarsMapping) {
|
138 | const isPartial = mix.mixin.partial;
|
139 | const namedArgs = mix.mixin.options;
|
140 | const overrideKeys = Object.keys(namedArgs);
|
141 | if (isPartial && overrideKeys.length === 0) {
|
142 | return;
|
143 | }
|
144 | let resolvedClass = transformer.resolver.resolve(mix.ref);
|
145 | const roots = [];
|
146 | while (resolvedClass && resolvedClass.symbol && resolvedClass._kind === 'css') {
|
147 | const mixinDecl = getMixinDeclaration(rule) || postcss.decl();
|
148 | roots.push(createMixinRootFromCSSResolve(transformer, mix, meta, resolvedClass, path, mixinDecl, variableOverride, cssVarsMapping));
|
149 | if ((resolvedClass.symbol._kind === 'class' || resolvedClass.symbol._kind === 'element') &&
|
150 | !resolvedClass.symbol[stylable_value_parsers_1.valueMapping.extends]) {
|
151 | resolvedClass = transformer.resolver.resolve(resolvedClass.symbol);
|
152 | }
|
153 | else {
|
154 | break;
|
155 | }
|
156 | }
|
157 | if (roots.length === 1) {
|
158 | stylable_utils_1.mergeRules(roots[0], rule);
|
159 | }
|
160 | else if (roots.length > 1) {
|
161 | const mixinRoot = postcss.root();
|
162 | roots.forEach((root) => mixinRoot.prepend(...root.nodes));
|
163 | stylable_utils_1.mergeRules(mixinRoot, rule);
|
164 | }
|
165 | else {
|
166 | const mixinDecl = getMixinDeclaration(rule);
|
167 | if (mixinDecl) {
|
168 | transformer.diagnostics.error(mixinDecl, exports.mixinWarnings.UNKNOWN_MIXIN_SYMBOL(mixinDecl.value), { word: mixinDecl.value });
|
169 | }
|
170 | }
|
171 | }
|
172 | function handleLocalClassMixin(mix, transformer, meta, variableOverride, cssVarsMapping, path, rule) {
|
173 | const isPartial = mix.mixin.partial;
|
174 | const namedArgs = mix.mixin.options;
|
175 | const overrideKeys = Object.keys(namedArgs);
|
176 | if (isPartial && overrideKeys.length === 0) {
|
177 | return;
|
178 | }
|
179 | const isRootMixin = mix.ref.name === meta.root;
|
180 | const mixinDecl = getMixinDeclaration(rule) || postcss.decl();
|
181 | const resolvedArgs = functions_1.resolveArgumentsValue(namedArgs, transformer, meta, transformer.diagnostics, mixinDecl, variableOverride, path, cssVarsMapping);
|
182 | const mixinRoot = stylable_utils_1.createSubsetAst(meta.ast, '.' + mix.ref.name, undefined, isRootMixin);
|
183 | if (isPartial) {
|
184 | filterPartialMixinDecl(meta, mixinRoot, overrideKeys);
|
185 | }
|
186 | transformer.transformAst(mixinRoot, isRootMixin ? meta : createInheritedMeta({ meta, symbol: mix.ref, _kind: 'css' }), undefined, resolvedArgs, path.concat(mix.mixin.type + ' from ' + meta.source), true);
|
187 | stylable_utils_1.mergeRules(mixinRoot, rule);
|
188 | }
|
189 | function createInheritedMeta(resolvedClass) {
|
190 | const mixinMeta = Object.create(resolvedClass.meta);
|
191 | mixinMeta.parent = resolvedClass.meta;
|
192 | mixinMeta.mappedSymbols = Object.create(resolvedClass.meta.mappedSymbols);
|
193 | mixinMeta.mappedSymbols[resolvedClass.meta.root] =
|
194 | resolvedClass.meta.mappedSymbols[resolvedClass.symbol.name];
|
195 | return mixinMeta;
|
196 | }
|
197 | function getMixinDeclaration(rule) {
|
198 | return (rule.nodes &&
|
199 | rule.nodes.find((node) => {
|
200 | return (node.type === 'decl' &&
|
201 | (node.prop === stylable_value_parsers_1.valueMapping.mixin || node.prop === stylable_value_parsers_1.valueMapping.partialMixin));
|
202 | }));
|
203 | }
|
204 | const partialsOnly = ({ mixin: { partial } }) => {
|
205 | return !!partial;
|
206 | };
|
207 | const nonPartials = ({ mixin: { partial } }) => {
|
208 | return !partial;
|
209 | };
|
210 |
|
211 | function filterPartialMixinDecl(meta, mixinRoot, overrideKeys) {
|
212 | let regexp;
|
213 | const overrideSet = new Set(overrideKeys);
|
214 | let size;
|
215 | do {
|
216 | size = overrideSet.size;
|
217 | regexp = new RegExp(`value\\((\\s*${Array.from(overrideSet).join('\\s*)|(\\s*')}\\s*)\\)`);
|
218 | for (const { text, name } of meta.vars) {
|
219 | if (!overrideSet.has(name) && text.match(regexp)) {
|
220 | overrideSet.add(name);
|
221 | }
|
222 | }
|
223 | } while (overrideSet.size !== size);
|
224 | mixinRoot.walkDecls((decl) => {
|
225 | var _a;
|
226 | if (!decl.value.match(regexp)) {
|
227 | const parent = decl.parent;
|
228 | decl.remove();
|
229 | if (((_a = parent === null || parent === void 0 ? void 0 : parent.nodes) === null || _a === void 0 ? void 0 : _a.length) === 0) {
|
230 | parent.remove();
|
231 | }
|
232 | else if (parent) {
|
233 | if (decl.prop === stylable_value_parsers_1.valueMapping.mixin) {
|
234 | parent.mixins = parent.mixins.filter(partialsOnly);
|
235 | }
|
236 | else if (decl.prop === stylable_value_parsers_1.valueMapping.partialMixin) {
|
237 | parent.mixins = parent.mixins.filter(nonPartials);
|
238 | }
|
239 | }
|
240 | }
|
241 | });
|
242 | }
|
243 |
|
\ | No newline at end of file |