@wyw-in-js/transform 0.3.0 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/esm/index.js +1 -2
  2. package/esm/index.js.map +1 -1
  3. package/esm/plugins/collector.js +5 -11
  4. package/esm/plugins/collector.js.map +1 -1
  5. package/esm/plugins/preeval.js +11 -17
  6. package/esm/plugins/preeval.js.map +1 -1
  7. package/esm/transform/Entrypoint.js +2 -1
  8. package/esm/transform/Entrypoint.js.map +1 -1
  9. package/esm/transform/generators/createStylisPreprocessor.js +171 -51
  10. package/esm/transform/generators/createStylisPreprocessor.js.map +1 -1
  11. package/esm/utils/getTagProcessor.js +113 -51
  12. package/esm/utils/getTagProcessor.js.map +1 -1
  13. package/lib/index.js +7 -15
  14. package/lib/index.js.map +1 -1
  15. package/lib/plugins/collector.js +6 -12
  16. package/lib/plugins/collector.js.map +1 -1
  17. package/lib/plugins/preeval.js +12 -17
  18. package/lib/plugins/preeval.js.map +1 -1
  19. package/lib/transform/Entrypoint.js +2 -1
  20. package/lib/transform/Entrypoint.js.map +1 -1
  21. package/lib/transform/generators/createStylisPreprocessor.js +176 -51
  22. package/lib/transform/generators/createStylisPreprocessor.js.map +1 -1
  23. package/lib/utils/getTagProcessor.js +122 -53
  24. package/lib/utils/getTagProcessor.js.map +1 -1
  25. package/package.json +7 -7
  26. package/types/index.d.ts +1 -2
  27. package/types/index.js +2 -4
  28. package/types/plugins/collector.d.ts +5 -1
  29. package/types/plugins/collector.js +5 -10
  30. package/types/plugins/preeval.d.ts +3 -3
  31. package/types/plugins/preeval.js +11 -14
  32. package/types/transform/Entrypoint.js +4 -1
  33. package/types/transform/generators/createStylisPreprocessor.d.ts +4 -1
  34. package/types/transform/generators/createStylisPreprocessor.js +187 -59
  35. package/types/utils/getTagProcessor.d.ts +10 -3
  36. package/types/utils/getTagProcessor.js +108 -53
  37. package/esm/utils/processTemplateExpression.js +0 -11
  38. package/esm/utils/processTemplateExpression.js.map +0 -1
  39. package/lib/utils/processTemplateExpression.js +0 -18
  40. package/lib/utils/processTemplateExpression.js.map +0 -1
  41. package/types/utils/processTemplateExpression.d.ts +0 -5
  42. package/types/utils/processTemplateExpression.js +0 -17
@@ -23,7 +23,8 @@ var __importStar = (this && this.__importStar) || function (mod) {
23
23
  return result;
24
24
  };
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
- exports.createStylisPreprocessor = exports.createStylisUrlReplacePlugin = exports.stylisGlobalPlugin = exports.transformUrl = void 0;
26
+ exports.createStylisPreprocessor = exports.createKeyframeSuffixerPlugin = exports.createStylisUrlReplacePlugin = exports.stylisGlobalPlugin = exports.transformUrl = void 0;
27
+ /* eslint-disable no-continue */
27
28
  const path = __importStar(require("path"));
28
29
  const stylis_1 = require("stylis");
29
30
  const POSIX_SEP = path.posix.sep;
@@ -38,11 +39,51 @@ function transformUrl(url, outputFilename, sourceFilename, platformPath = path)
38
39
  return relative.split(platformPath.sep).join(POSIX_SEP);
39
40
  }
40
41
  exports.transformUrl = transformUrl;
42
+ const DEFINED_KEYFRAMES = Symbol('definedKeyframes');
43
+ const ORIGINAL_VALUE_KEY = Symbol('originalValue');
44
+ const IS_GLOBAL_KEYFRAMES = Symbol('isGlobalKeyframes');
45
+ const getOriginalElementValue = (element) => {
46
+ return element ? element[ORIGINAL_VALUE_KEY] ?? element.value : '';
47
+ };
48
+ function throwIfNotProd(key, value, type) {
49
+ if (process.env.NODE_ENV !== 'production') {
50
+ throw new Error(`"element.${key}" has type "${type}" (${JSON.stringify(value, null, 2)}), it's not expected. Please report a bug if it happens.`);
51
+ }
52
+ return false;
53
+ }
54
+ function childrenIsString(children) {
55
+ return (typeof children === 'string' ||
56
+ throwIfNotProd('children', children, 'Element[]'));
57
+ }
58
+ function propsAreStrings(props) {
59
+ return Array.isArray(props) || throwIfNotProd('props', props, 'string');
60
+ }
61
+ function propsIsString(props) {
62
+ return (typeof props === 'string' || throwIfNotProd('props', props, 'string[]'));
63
+ }
64
+ const isDeclaration = (element) => {
65
+ return (element.type === stylis_1.DECLARATION &&
66
+ propsIsString(element.props) &&
67
+ childrenIsString(element.children));
68
+ };
69
+ const isKeyframes = (element) => {
70
+ return element.type === stylis_1.KEYFRAMES && propsAreStrings(element.props);
71
+ };
72
+ const isRuleset = (element) => {
73
+ return element.type === stylis_1.RULESET && propsAreStrings(element.props);
74
+ };
41
75
  /**
42
76
  * Stylis plugin that mimics :global() selector behavior from Stylis v3.
43
77
  */
44
78
  const stylisGlobalPlugin = (element) => {
45
- function getGlobalSelectorModifiers(value) {
79
+ function getGlobalSelectorModifiers(el) {
80
+ const { parent } = el;
81
+ const value = getOriginalElementValue(el);
82
+ const parentValue = getOriginalElementValue(parent);
83
+ if ((parent?.children.length === 0 && parentValue.includes(':global(')) ||
84
+ (parent && !value.includes(':global('))) {
85
+ return getGlobalSelectorModifiers(parent);
86
+ }
46
87
  const match = value.match(/(&\f( )?)?:global\(/);
47
88
  if (match === null) {
48
89
  throw new Error(`Failed to match :global() selector in "${value}". Please report a bug if it happens.`);
@@ -53,62 +94,53 @@ const stylisGlobalPlugin = (element) => {
53
94
  includeSpaceDelimiter: !!spaceDelimiter,
54
95
  };
55
96
  }
56
- switch (element.type) {
57
- case stylis_1.RULESET:
58
- if (typeof element.props === 'string') {
59
- if (process.env.NODE_ENV !== 'production') {
60
- throw new Error(`"element.props" has type "string" (${JSON.stringify(element.props, null, 2)}), it's not expected. Please report a bug if it happens.`);
61
- }
62
- return;
97
+ if (!isRuleset(element)) {
98
+ return;
99
+ }
100
+ Object.assign(element, {
101
+ props: element.props.map((cssSelector) => {
102
+ // The value can be changed by other middlewares, but we need an original one with `&`
103
+ Object.assign(element, { [ORIGINAL_VALUE_KEY]: element.value });
104
+ // Avoids calling tokenize() on every string
105
+ if (!cssSelector.includes(':global(')) {
106
+ return cssSelector;
63
107
  }
64
- Object.assign(element, {
65
- props: element.props.map((cssSelector) => {
66
- // Avoids calling tokenize() on every string
67
- if (!cssSelector.includes(':global(')) {
68
- return cssSelector;
69
- }
70
- if (element.children.length === 0) {
71
- Object.assign(element, {
72
- global: getGlobalSelectorModifiers(element.value),
73
- });
74
- return cssSelector;
75
- }
76
- const { includeBaseSelector, includeSpaceDelimiter } = element.parent?.global || getGlobalSelectorModifiers(element.value);
77
- const tokens = (0, stylis_1.tokenize)(cssSelector);
78
- let selector = '';
79
- for (let i = 0, len = tokens.length; i < len; i++) {
80
- const token = tokens[i];
81
- //
82
- // Match for ":global("
83
- if (token === ':' && tokens[i + 1] === 'global') {
84
- //
85
- // Match for ":global()"
86
- if (tokens[i + 2] === '()') {
87
- selector = [
88
- ...tokens.slice(i + 4),
89
- includeSpaceDelimiter ? ' ' : '',
90
- ...(includeBaseSelector ? tokens.slice(0, i - 1) : []),
91
- includeSpaceDelimiter ? '' : ' ',
92
- ].join('');
93
- break;
94
- }
95
- //
96
- // Match for ":global(selector)"
97
- selector = [
98
- tokens[i + 2].slice(1, -1),
99
- includeSpaceDelimiter ? ' ' : '',
100
- ...(includeBaseSelector ? tokens.slice(0, i - 1) : []),
101
- includeSpaceDelimiter ? '' : ' ',
102
- ].join('');
103
- break;
104
- }
108
+ if (element.children.length === 0) {
109
+ return cssSelector;
110
+ }
111
+ const { includeBaseSelector, includeSpaceDelimiter } = getGlobalSelectorModifiers(element);
112
+ const tokens = (0, stylis_1.tokenize)(cssSelector);
113
+ let selector = '';
114
+ for (let i = 0, len = tokens.length; i < len; i++) {
115
+ const token = tokens[i];
116
+ //
117
+ // Match for ":global("
118
+ if (token === ':' && tokens[i + 1] === 'global') {
119
+ //
120
+ // Match for ":global()"
121
+ if (tokens[i + 2] === '()') {
122
+ selector = [
123
+ ...tokens.slice(i + 4),
124
+ includeSpaceDelimiter ? ' ' : '',
125
+ ...(includeBaseSelector ? tokens.slice(0, i - 1) : []),
126
+ includeSpaceDelimiter ? '' : ' ',
127
+ ].join('');
128
+ break;
105
129
  }
106
- return selector;
107
- }),
108
- });
109
- break;
110
- default:
111
- }
130
+ //
131
+ // Match for ":global(selector)"
132
+ selector = [
133
+ tokens[i + 2].slice(1, -1),
134
+ includeSpaceDelimiter ? ' ' : '',
135
+ ...(includeBaseSelector ? tokens.slice(0, i - 1) : []),
136
+ includeSpaceDelimiter ? '' : ' ',
137
+ ].join('');
138
+ break;
139
+ }
140
+ }
141
+ return selector;
142
+ }),
143
+ });
112
144
  };
113
145
  exports.stylisGlobalPlugin = stylisGlobalPlugin;
114
146
  function createStylisUrlReplacePlugin(filename, outputFilename) {
@@ -117,20 +149,116 @@ function createStylisUrlReplacePlugin(filename, outputFilename) {
117
149
  // When writing to a file, we need to adjust the relative paths inside url(..) expressions.
118
150
  // It'll allow css-loader to resolve an imported asset properly.
119
151
  // eslint-disable-next-line no-param-reassign
120
- element.return = element.value.replace(/\b(url\((["']?))(\.[^)]+?)(\2\))/g, (match, p1, p2, p3, p4) => p1 + transformUrl(p3, outputFilename, filename) + p4);
152
+ element.return = element.value.replace(/\b(url\((["']?))(\.[^)]+?)(\2\))/g, (_match, p1, _p2, p3, p4) => p1 + transformUrl(p3, outputFilename, filename) + p4);
121
153
  }
122
154
  };
123
155
  }
124
156
  exports.createStylisUrlReplacePlugin = createStylisUrlReplacePlugin;
157
+ function createKeyframeSuffixerPlugin() {
158
+ const prefixes = ['webkit', 'moz', 'ms', 'o', ''].map((i) => i ? `-${i}-` : '');
159
+ const getPrefixedProp = (prop) => prefixes.map((prefix) => `${prefix}${prop}`);
160
+ const buildPropsRegexp = (prop, isAtRule) => {
161
+ const [at, colon] = isAtRule ? ['@', ''] : ['', ':'];
162
+ return new RegExp(`^(${at}(?:${getPrefixedProp(prop).join('|')})${colon})\\s*`);
163
+ };
164
+ const animationNameRegexp = /:global\(([\w_-]+)\)|([\w_-]+)/;
165
+ const getReplacer = (startsWith, searchValue, replacer) => {
166
+ return (input) => {
167
+ const [fullMatch] = input.match(startsWith) ?? [];
168
+ if (fullMatch === undefined) {
169
+ return input;
170
+ }
171
+ const rest = input.slice(fullMatch.length);
172
+ return fullMatch + rest.replace(searchValue, replacer);
173
+ };
174
+ };
175
+ const elementToKeyframeSuffix = (el) => {
176
+ if (el.parent) {
177
+ return elementToKeyframeSuffix(el.parent);
178
+ }
179
+ return el.value.replaceAll(/[^a-zA-Z0-9_-]/g, '');
180
+ };
181
+ const animationPropsSet = new Set([
182
+ ...getPrefixedProp('animation'),
183
+ ...getPrefixedProp('animation-name'),
184
+ ]);
185
+ const getDefinedKeyframes = (element) => {
186
+ if (element[DEFINED_KEYFRAMES]) {
187
+ return element[DEFINED_KEYFRAMES];
188
+ }
189
+ if (element.parent) {
190
+ return getDefinedKeyframes(element.parent);
191
+ }
192
+ const keyframes = new Set();
193
+ for (const sibling of element.siblings ?? []) {
194
+ if (!isKeyframes(sibling) || sibling[IS_GLOBAL_KEYFRAMES] === true) {
195
+ continue;
196
+ }
197
+ keyframes.add(sibling.props[0]);
198
+ }
199
+ Object.assign(element, { [DEFINED_KEYFRAMES]: keyframes });
200
+ return keyframes;
201
+ };
202
+ return (element) => {
203
+ if (isKeyframes(element) && element.parent) {
204
+ const suffix = elementToKeyframeSuffix(element);
205
+ const replaceFn = (_match, globalMatch, scopedMatch) => globalMatch || `${scopedMatch}-${suffix}`;
206
+ Object.assign(element, {
207
+ [IS_GLOBAL_KEYFRAMES]: element.props[0]?.startsWith(':global(') ?? false,
208
+ props: element.props.map(getReplacer(/^\s*/, animationNameRegexp, replaceFn)),
209
+ value: getReplacer(buildPropsRegexp('keyframes', true), animationNameRegexp, replaceFn)(element.value),
210
+ });
211
+ return;
212
+ }
213
+ if (isDeclaration(element)) {
214
+ const suffix = elementToKeyframeSuffix(element);
215
+ const keys = [
216
+ 'children',
217
+ 'return',
218
+ 'value',
219
+ ];
220
+ if (animationPropsSet.has(element.props)) {
221
+ const scopedKeyframes = getDefinedKeyframes(element);
222
+ const patch = Object.fromEntries(keys.map((key) => {
223
+ const tokens = (0, stylis_1.tokenize)(element[key]);
224
+ let result = '';
225
+ for (let i = 0; i < tokens.length; i += 1) {
226
+ if (tokens[i] === ':' &&
227
+ tokens[i + 1] === 'global' &&
228
+ tokens[i + 2].startsWith('(')) {
229
+ const globalName = tokens[i + 2].substring(1, tokens[i + 2].length - 1);
230
+ i += 2;
231
+ result += globalName;
232
+ if (tokens[i + 1] !== ';') {
233
+ result += ' ';
234
+ }
235
+ continue;
236
+ }
237
+ if (scopedKeyframes.has(tokens[i])) {
238
+ result += `${tokens[i]}-${suffix}`;
239
+ continue;
240
+ }
241
+ result += tokens[i];
242
+ }
243
+ return [key, result];
244
+ }));
245
+ Object.assign(element, patch);
246
+ }
247
+ }
248
+ };
249
+ }
250
+ exports.createKeyframeSuffixerPlugin = createKeyframeSuffixerPlugin;
251
+ const isMiddleware = (obj) => obj !== null;
125
252
  function createStylisPreprocessor(options) {
126
253
  function stylisPreprocess(selector, text) {
127
254
  const compiled = (0, stylis_1.compile)(`${selector} {${text}}\n`);
128
255
  return (0, stylis_1.serialize)(compiled, (0, stylis_1.middleware)([
129
256
  createStylisUrlReplacePlugin(options.filename, options.outputFilename),
130
257
  exports.stylisGlobalPlugin,
131
- stylis_1.prefixer,
258
+ options.prefixer === false ? null : stylis_1.prefixer,
259
+ createKeyframeSuffixerPlugin(),
132
260
  stylis_1.stringify,
133
- ]));
261
+ ].filter(isMiddleware)));
134
262
  }
135
263
  return stylisPreprocess;
136
264
  }
@@ -1,6 +1,13 @@
1
1
  import type { NodePath } from '@babel/traverse';
2
- import type { Identifier } from '@babel/types';
2
+ import type { Program } from '@babel/types';
3
3
  import { BaseProcessor } from '@wyw-in-js/processor-utils';
4
- import type { IFileContext } from '@wyw-in-js/processor-utils';
4
+ import type { IFileContext, TagSource } from '@wyw-in-js/processor-utils';
5
5
  import type { StrictOptions } from '@wyw-in-js/shared';
6
- export declare function getTagProcessor(path: NodePath<Identifier>, fileContext: IFileContext, options: Pick<StrictOptions, 'classNameSlug' | 'displayName' | 'evaluate' | 'tagResolver'>): BaseProcessor | null;
6
+ import type { IImport } from './collectExportsAndImports';
7
+ type DefinedProcessor = [ProcessorClass, TagSource];
8
+ type DefinedProcessors = Map<string, DefinedProcessor>;
9
+ export type ProcessorClass = new (...args: ConstructorParameters<typeof BaseProcessor>) => BaseProcessor;
10
+ export declare function getProcessorForImport({ imported, source }: IImport, filename: string | null | undefined, options: Pick<StrictOptions, 'tagResolver'>): [ProcessorClass | null, TagSource];
11
+ export declare function getDefinedProcessors(imports: IImport[], path: NodePath<Program>, filename: string | null | undefined, options: Pick<StrictOptions, 'tagResolver'>): DefinedProcessors;
12
+ export declare function applyProcessors(path: NodePath<Program>, fileContext: IFileContext, options: Pick<StrictOptions, 'classNameSlug' | 'displayName' | 'evaluate' | 'tagResolver'>, callback: (processor: BaseProcessor) => void): void;
13
+ export {};
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getTagProcessor = void 0;
3
+ exports.applyProcessors = exports.getDefinedProcessors = exports.getProcessorForImport = void 0;
4
4
  const fs_1 = require("fs");
5
5
  const path_1 = require("path");
6
6
  const core_1 = require("@babel/core");
@@ -76,52 +76,21 @@ function getProcessorFromFile(processorPath) {
76
76
  }
77
77
  return Processor;
78
78
  }
79
- function getProcessorForIdentifier(path, imports, filename, options) {
80
- const pathBinding = path.scope.getBinding(path.node.name);
81
- if (!pathBinding) {
82
- // It's not a binding, so it's not a tag
83
- return [null, null, null];
84
- }
79
+ function getProcessorForImport({ imported, source }, filename, options) {
85
80
  const tagResolver = options.tagResolver ?? (() => null);
86
- // FIXME: can be simplified
87
- const relatedImports = imports
88
- .map((i) => {
89
- const { local } = i;
90
- if (local === path) {
91
- return [i, null];
92
- }
93
- if (!local.isIdentifier()) {
94
- if (path.isDescendant(local)) {
95
- return [i, local];
96
- }
97
- return null;
98
- }
99
- const binding = local.scope.getBinding(local.node.name);
100
- if (pathBinding === binding) {
101
- return [i, path];
102
- }
103
- return null;
104
- })
105
- .filter(isNotNull_1.isNotNull)
106
- .filter((i) => i[1] === null || i[1].isExpression());
107
- if (relatedImports.length === 0) {
108
- return [null, null, null];
109
- }
110
- const [Processor = null, tagSource = null, tagPath = null] = relatedImports
111
- .map(([{ imported, source }, p]) => {
112
- const customFile = tagResolver(source, imported);
113
- const processor = customFile
114
- ? getProcessorFromFile(customFile)
115
- : getProcessorFromPackage(source, imported, filename);
116
- return [processor, { imported, source }, p];
117
- })
118
- .find(([proc]) => proc) ?? [];
119
- return Processor === null || tagSource === null || tagPath === null
120
- ? [null, null, null]
121
- : [Processor, tagSource, tagPath];
81
+ const customFile = tagResolver(source, imported);
82
+ const processor = customFile
83
+ ? getProcessorFromFile(customFile)
84
+ : getProcessorFromPackage(source, imported, filename);
85
+ return [processor, { imported, source }];
122
86
  }
123
- function getBuilderForIdentifier(path, imports, filename, options) {
124
- const [Processor, tagSource, tagPath] = getProcessorForIdentifier(path, imports, filename, options);
87
+ exports.getProcessorForImport = getProcessorForImport;
88
+ function getBuilderForIdentifier(definedProcessor, path, imports, options) {
89
+ const [Processor, tagSource] = definedProcessor;
90
+ let tagPath = path;
91
+ if (tagPath.parentPath?.isMemberExpression({ property: tagPath.node })) {
92
+ tagPath = tagPath.parentPath;
93
+ }
125
94
  if (!Processor || !tagSource || !tagPath) {
126
95
  return null;
127
96
  }
@@ -193,11 +162,18 @@ function getBuilderForIdentifier(path, imports, filename, options) {
193
162
  }
194
163
  });
195
164
  };
196
- const astService = {
197
- ...core_1.types,
165
+ const importHelpers = {
198
166
  addDefaultImport: (importedSource, nameHint) => (0, helper_module_imports_1.addDefault)(path, importedSource, { nameHint }),
199
167
  addNamedImport: (name, importedSource, nameHint = name) => (0, helper_module_imports_1.addNamed)(path, name, importedSource, { nameHint }),
200
168
  };
169
+ const astService = new Proxy(core_1.types, {
170
+ get(target, prop, receiver) {
171
+ if (prop in importHelpers) {
172
+ return importHelpers[prop];
173
+ }
174
+ return Reflect.get(target, prop, receiver);
175
+ },
176
+ });
201
177
  return (...args) => new Processor(params, tagSource, astService, tagPath.node.loc ?? null, replacer, ...args);
202
178
  }
203
179
  function getDisplayName(path, idx, filename) {
@@ -279,13 +255,42 @@ const getNextIndex = (state) => {
279
255
  counters.set(state, counter + 1);
280
256
  return counter;
281
257
  };
282
- function getTagProcessor(path, fileContext, options) {
283
- const cache = (0, traversalCache_1.getTraversalCache)(path, 'getTagProcessor');
258
+ function getDefinedProcessors(imports, path, filename, options) {
259
+ const cache = (0, traversalCache_1.getTraversalCache)(path, 'getDefinedProcessors');
260
+ if (!cache.has(path)) {
261
+ const defined = new Map();
262
+ imports.forEach((i) => {
263
+ const [processor, tagSource] = getProcessorForImport(i, filename, options);
264
+ const { local } = i;
265
+ if (!processor) {
266
+ return;
267
+ }
268
+ let name = null;
269
+ if (local.isIdentifier()) {
270
+ name = local.node.name;
271
+ }
272
+ if (name === null && local.isMemberExpression()) {
273
+ const property = local.get('property');
274
+ const object = local.get('object');
275
+ if (property.isIdentifier() && object.isIdentifier()) {
276
+ name = `${object.node.name}.${property.node.name}`;
277
+ }
278
+ }
279
+ if (name === null) {
280
+ return;
281
+ }
282
+ defined.set(name, [processor, tagSource]);
283
+ });
284
+ cache.set(path, defined);
285
+ }
286
+ return cache.get(path);
287
+ }
288
+ exports.getDefinedProcessors = getDefinedProcessors;
289
+ function createProcessorInstance(definedProcessor, imports, path, fileContext, options) {
290
+ const cache = (0, traversalCache_1.getTraversalCache)(path, 'createProcessorInstance');
284
291
  if (!cache.has(path.node)) {
285
- const root = path.scope.getProgramParent().path;
286
- const { imports } = (0, collectExportsAndImports_1.collectExportsAndImports)(root);
287
292
  try {
288
- const builder = getBuilderForIdentifier(path, imports.filter(collectExportsAndImports_1.explicitImport), fileContext.filename, options);
293
+ const builder = getBuilderForIdentifier(definedProcessor, path, imports, options);
289
294
  if (builder) {
290
295
  // Increment the index of the style we're processing
291
296
  // This is used for slug generation to prevent collision
@@ -312,4 +317,54 @@ function getTagProcessor(path, fileContext, options) {
312
317
  }
313
318
  return cache.get(path.node) ?? null;
314
319
  }
315
- exports.getTagProcessor = getTagProcessor;
320
+ function applyProcessors(path, fileContext, options, callback) {
321
+ const imports = (0, collectExportsAndImports_1.collectExportsAndImports)(path).imports.filter(collectExportsAndImports_1.explicitImport);
322
+ const definedProcessors = getDefinedProcessors(imports, path, fileContext.filename, options);
323
+ const usages = [];
324
+ definedProcessors.forEach((processor, idName) => {
325
+ if (idName.includes('.')) {
326
+ // It's a member expression
327
+ const [object, property] = idName.split('.');
328
+ const objBinding = path.scope.getBinding(object);
329
+ if (!objBinding) {
330
+ return;
331
+ }
332
+ objBinding.referencePaths.forEach((p) => {
333
+ const parent = p.parentPath;
334
+ if (!parent?.isMemberExpression()) {
335
+ return;
336
+ }
337
+ const identifier = parent.get('property');
338
+ if (identifier.isIdentifier({ name: property })) {
339
+ usages.push({
340
+ identifier,
341
+ processor,
342
+ });
343
+ }
344
+ });
345
+ return;
346
+ }
347
+ path.scope.getBinding(idName)?.referencePaths.forEach((identifier) => {
348
+ if (identifier.isIdentifier()) {
349
+ usages.push({
350
+ identifier,
351
+ processor,
352
+ });
353
+ }
354
+ });
355
+ });
356
+ // The same order, the same slugs
357
+ usages.sort((a, b) => (a.identifier.node.start ?? 0) - (b.identifier.node.start ?? 0));
358
+ usages.forEach((usage) => {
359
+ const definedProcessor = usage.processor;
360
+ if (!definedProcessor) {
361
+ return;
362
+ }
363
+ const instance = createProcessorInstance(definedProcessor, imports, usage.identifier, fileContext, options);
364
+ if (instance === null) {
365
+ return;
366
+ }
367
+ callback(instance);
368
+ });
369
+ }
370
+ exports.applyProcessors = applyProcessors;
@@ -1,11 +0,0 @@
1
- import { getTagProcessor } from './getTagProcessor';
2
- const processed = new WeakSet();
3
- export const processTemplateExpression = (p, fileContext, options, emit) => {
4
- if (p.parentPath.isExportSpecifier()) return;
5
- if (processed.has(p.node)) return;
6
- const tagProcessor = getTagProcessor(p, fileContext, options);
7
- processed.add(p.node);
8
- if (tagProcessor === null) return;
9
- emit(tagProcessor);
10
- };
11
- //# sourceMappingURL=processTemplateExpression.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"processTemplateExpression.js","names":["getTagProcessor","processed","WeakSet","processTemplateExpression","p","fileContext","options","emit","parentPath","isExportSpecifier","has","node","tagProcessor","add"],"sources":["../../src/utils/processTemplateExpression.ts"],"sourcesContent":["import type { NodePath } from '@babel/traverse';\nimport type { Identifier } from '@babel/types';\n\nimport type { BaseProcessor, IFileContext } from '@wyw-in-js/processor-utils';\nimport type { StrictOptions } from '@wyw-in-js/shared';\n\nimport { getTagProcessor } from './getTagProcessor';\n\nconst processed = new WeakSet<Identifier>();\n\nexport const processTemplateExpression = (\n p: NodePath<Identifier>,\n fileContext: IFileContext,\n options: Pick<\n StrictOptions,\n 'classNameSlug' | 'displayName' | 'evaluate' | 'tagResolver'\n >,\n emit: (processor: BaseProcessor) => void\n) => {\n if (p.parentPath.isExportSpecifier()) return;\n if (processed.has(p.node)) return;\n\n const tagProcessor = getTagProcessor(p, fileContext, options);\n\n processed.add(p.node);\n\n if (tagProcessor === null) return;\n\n emit(tagProcessor);\n};\n"],"mappings":"AAMA,SAASA,eAAe,QAAQ,mBAAmB;AAEnD,MAAMC,SAAS,GAAG,IAAIC,OAAO,CAAa,CAAC;AAE3C,OAAO,MAAMC,yBAAyB,GAAGA,CACvCC,CAAuB,EACvBC,WAAyB,EACzBC,OAGC,EACDC,IAAwC,KACrC;EACH,IAAIH,CAAC,CAACI,UAAU,CAACC,iBAAiB,CAAC,CAAC,EAAE;EACtC,IAAIR,SAAS,CAACS,GAAG,CAACN,CAAC,CAACO,IAAI,CAAC,EAAE;EAE3B,MAAMC,YAAY,GAAGZ,eAAe,CAACI,CAAC,EAAEC,WAAW,EAAEC,OAAO,CAAC;EAE7DL,SAAS,CAACY,GAAG,CAACT,CAAC,CAACO,IAAI,CAAC;EAErB,IAAIC,YAAY,KAAK,IAAI,EAAE;EAE3BL,IAAI,CAACK,YAAY,CAAC;AACpB,CAAC"}
@@ -1,18 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.processTemplateExpression = void 0;
7
- var _getTagProcessor = require("./getTagProcessor");
8
- const processed = new WeakSet();
9
- const processTemplateExpression = (p, fileContext, options, emit) => {
10
- if (p.parentPath.isExportSpecifier()) return;
11
- if (processed.has(p.node)) return;
12
- const tagProcessor = (0, _getTagProcessor.getTagProcessor)(p, fileContext, options);
13
- processed.add(p.node);
14
- if (tagProcessor === null) return;
15
- emit(tagProcessor);
16
- };
17
- exports.processTemplateExpression = processTemplateExpression;
18
- //# sourceMappingURL=processTemplateExpression.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"processTemplateExpression.js","names":["_getTagProcessor","require","processed","WeakSet","processTemplateExpression","p","fileContext","options","emit","parentPath","isExportSpecifier","has","node","tagProcessor","getTagProcessor","add","exports"],"sources":["../../src/utils/processTemplateExpression.ts"],"sourcesContent":["import type { NodePath } from '@babel/traverse';\nimport type { Identifier } from '@babel/types';\n\nimport type { BaseProcessor, IFileContext } from '@wyw-in-js/processor-utils';\nimport type { StrictOptions } from '@wyw-in-js/shared';\n\nimport { getTagProcessor } from './getTagProcessor';\n\nconst processed = new WeakSet<Identifier>();\n\nexport const processTemplateExpression = (\n p: NodePath<Identifier>,\n fileContext: IFileContext,\n options: Pick<\n StrictOptions,\n 'classNameSlug' | 'displayName' | 'evaluate' | 'tagResolver'\n >,\n emit: (processor: BaseProcessor) => void\n) => {\n if (p.parentPath.isExportSpecifier()) return;\n if (processed.has(p.node)) return;\n\n const tagProcessor = getTagProcessor(p, fileContext, options);\n\n processed.add(p.node);\n\n if (tagProcessor === null) return;\n\n emit(tagProcessor);\n};\n"],"mappings":";;;;;;AAMA,IAAAA,gBAAA,GAAAC,OAAA;AAEA,MAAMC,SAAS,GAAG,IAAIC,OAAO,CAAa,CAAC;AAEpC,MAAMC,yBAAyB,GAAGA,CACvCC,CAAuB,EACvBC,WAAyB,EACzBC,OAGC,EACDC,IAAwC,KACrC;EACH,IAAIH,CAAC,CAACI,UAAU,CAACC,iBAAiB,CAAC,CAAC,EAAE;EACtC,IAAIR,SAAS,CAACS,GAAG,CAACN,CAAC,CAACO,IAAI,CAAC,EAAE;EAE3B,MAAMC,YAAY,GAAG,IAAAC,gCAAe,EAACT,CAAC,EAAEC,WAAW,EAAEC,OAAO,CAAC;EAE7DL,SAAS,CAACa,GAAG,CAACV,CAAC,CAACO,IAAI,CAAC;EAErB,IAAIC,YAAY,KAAK,IAAI,EAAE;EAE3BL,IAAI,CAACK,YAAY,CAAC;AACpB,CAAC;AAACG,OAAA,CAAAZ,yBAAA,GAAAA,yBAAA"}
@@ -1,5 +0,0 @@
1
- import type { NodePath } from '@babel/traverse';
2
- import type { Identifier } from '@babel/types';
3
- import type { BaseProcessor, IFileContext } from '@wyw-in-js/processor-utils';
4
- import type { StrictOptions } from '@wyw-in-js/shared';
5
- export declare const processTemplateExpression: (p: NodePath<Identifier>, fileContext: IFileContext, options: Pick<StrictOptions, 'classNameSlug' | 'displayName' | 'evaluate' | 'tagResolver'>, emit: (processor: BaseProcessor) => void) => void;
@@ -1,17 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.processTemplateExpression = void 0;
4
- const getTagProcessor_1 = require("./getTagProcessor");
5
- const processed = new WeakSet();
6
- const processTemplateExpression = (p, fileContext, options, emit) => {
7
- if (p.parentPath.isExportSpecifier())
8
- return;
9
- if (processed.has(p.node))
10
- return;
11
- const tagProcessor = (0, getTagProcessor_1.getTagProcessor)(p, fileContext, options);
12
- processed.add(p.node);
13
- if (tagProcessor === null)
14
- return;
15
- emit(tagProcessor);
16
- };
17
- exports.processTemplateExpression = processTemplateExpression;