1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | exports.createTransformer = void 0;
|
4 | const path = require("path");
|
5 | const ts = require("typescript");
|
6 | const ts_is_kind_1 = require("./ts-is-kind");
|
7 | const hash_1 = require("./hash");
|
8 | const minify_1 = require("./minify");
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 | function isStyledFunction(node, identifiers) {
|
19 | if ((0, ts_is_kind_1.isPropertyAccessExpression)(node)) {
|
20 | if (isStyledObject(node.expression, identifiers)) {
|
21 | return true;
|
22 | }
|
23 | if (isStyledExtendIdentifier(node.name.text, identifiers) && isValidComponent(node.expression)) {
|
24 | return true;
|
25 | }
|
26 | return false;
|
27 | }
|
28 | if ((0, ts_is_kind_1.isCallExpression)(node) && node.arguments.length === 1) {
|
29 | if (isStyledObject(node.expression, identifiers)) {
|
30 | return true;
|
31 | }
|
32 | if (isStyledAttrs(node.expression, identifiers)) {
|
33 | return true;
|
34 | }
|
35 | }
|
36 | return false;
|
37 | }
|
38 | function isStyledObjectIdentifier(name, { styled: styledIdentifiers = ['styled'] }) {
|
39 | return styledIdentifiers.indexOf(name) >= 0;
|
40 | }
|
41 | function isStyledObject(node, identifiers) {
|
42 | return node && (0, ts_is_kind_1.isIdentifier)(node) && isStyledObjectIdentifier(node.text, identifiers);
|
43 | }
|
44 | function isValidComponent(node) {
|
45 | return node && (0, ts_is_kind_1.isIdentifier)(node) && isValidComponentName(node.text);
|
46 | }
|
47 | function isLetter(ch) {
|
48 | return ch.toLowerCase() !== ch.toUpperCase();
|
49 | }
|
50 | function isValidTagName(name) {
|
51 | return isLetter(name[0]) && name[0] === name[0].toLowerCase();
|
52 | }
|
53 | function isValidComponentName(name) {
|
54 | return isLetter(name[0]) && name[0] === name[0].toUpperCase();
|
55 | }
|
56 | function isStyledAttrsIdentifier(name, { attrs: attrsIdentifiers = ['attrs'] }) {
|
57 | return attrsIdentifiers.indexOf(name) >= 0;
|
58 | }
|
59 | function isStyledAttrs(node, identifiers) {
|
60 | return (node &&
|
61 | (0, ts_is_kind_1.isPropertyAccessExpression)(node) &&
|
62 | isStyledAttrsIdentifier(node.name.text, identifiers) &&
|
63 | isStyledFunction(node.expression, identifiers));
|
64 | }
|
65 | function isStyledKeyframesIdentifier(name, { keyframes = ['keyframes'] }) {
|
66 | return keyframes.indexOf(name) >= 0;
|
67 | }
|
68 | function isStyledCssIdentifier(name, { css = ['css'] }) {
|
69 | return css.indexOf(name) >= 0;
|
70 | }
|
71 | function isStyledCreateGlobalStyleIdentifier(name, { createGlobalStyle = ['createGlobalStyle'] }) {
|
72 | return createGlobalStyle.indexOf(name) >= 0;
|
73 | }
|
74 | function isStyledExtendIdentifier(name, { extend = [] }) {
|
75 | return extend.indexOf(name) >= 0;
|
76 | }
|
77 | function isMinifyableStyledFunction(node, identifiers) {
|
78 | return (isStyledFunction(node, identifiers) ||
|
79 | ((0, ts_is_kind_1.isIdentifier)(node) &&
|
80 | (isStyledKeyframesIdentifier(node.text, identifiers) ||
|
81 | isStyledCssIdentifier(node.text, identifiers) ||
|
82 | isStyledCreateGlobalStyleIdentifier(node.text, identifiers))));
|
83 | }
|
84 | function defaultGetDisplayName(filename, bindingName) {
|
85 | return bindingName;
|
86 | }
|
87 | function createTransformer({ getDisplayName = defaultGetDisplayName, identifiers = {}, ssr = true, displayName = true, minify = false, componentIdPrefix = '' } = {}) {
|
88 | |
89 |
|
90 |
|
91 |
|
92 |
|
93 |
|
94 |
|
95 | function getDisplayNameFromNode(node, sourceFile) {
|
96 | if ((0, ts_is_kind_1.isVariableDeclaration)(node) && (0, ts_is_kind_1.isIdentifier)(node.name)) {
|
97 | return (componentIdPrefix ? componentIdPrefix + '-' : '') + getDisplayName(sourceFile.fileName, node.name.text);
|
98 | }
|
99 | if ((0, ts_is_kind_1.isExportAssignment)(node)) {
|
100 | return getDisplayName(sourceFile.fileName, undefined);
|
101 | }
|
102 | return undefined;
|
103 | }
|
104 | function getIdFromNode(node, sourceRoot, position, sourceFile) {
|
105 | if (((0, ts_is_kind_1.isVariableDeclaration)(node) && (0, ts_is_kind_1.isIdentifier)(node.name)) || (0, ts_is_kind_1.isExportAssignment)(node)) {
|
106 | const fileName = sourceFile.fileName;
|
107 | const filePath = sourceRoot
|
108 | ? path.relative(sourceRoot, fileName).replace(path.sep, path.posix.sep)
|
109 | : fileName;
|
110 | return (componentIdPrefix || 'sc') + '-' + (0, hash_1.hash)(`${getDisplayNameFromNode(node, sourceFile)}${filePath}${position}`);
|
111 | }
|
112 | return undefined;
|
113 | }
|
114 | const transformer = (context) => {
|
115 | const { sourceRoot } = context.getCompilerOptions();
|
116 | return (sourceFile) => {
|
117 | let lastComponentPosition = 0;
|
118 | const withConfig = (node, properties) => properties.length > 0
|
119 | ? context.factory.createCallExpression(context.factory.createPropertyAccessExpression(node, 'withConfig'), undefined, [context.factory.createObjectLiteralExpression(properties)])
|
120 | : node;
|
121 | const createDisplayNameConfig = (displayNameValue) => displayNameValue
|
122 | ? [
|
123 | context.factory.createPropertyAssignment('displayName', context.factory.createStringLiteral(displayNameValue)),
|
124 | ]
|
125 | : [];
|
126 | const createIdConfig = (componentId) => componentId
|
127 | ? [
|
128 | context.factory.createPropertyAssignment('componentId', context.factory.createStringLiteral(componentId)),
|
129 | ]
|
130 | : [];
|
131 | const transformStyledFunction = (binding, node) => withConfig(node, [
|
132 | ...(displayName ? createDisplayNameConfig(getDisplayNameFromNode(binding, sourceFile)) : []),
|
133 | ...(ssr
|
134 | ? createIdConfig(getIdFromNode(binding, sourceRoot, ++lastComponentPosition, sourceFile))
|
135 | : []),
|
136 | ]);
|
137 | const transformTemplateLiteral = (templateLiteral) => minify ? (0, minify_1.minifyTemplate)(templateLiteral, context.factory) : templateLiteral;
|
138 | const transformTaggedTemplateExpression = (node) => isMinifyableStyledFunction(node.tag, identifiers)
|
139 | ? context.factory.updateTaggedTemplateExpression(node, node.tag, node.typeArguments, transformTemplateLiteral(node.template))
|
140 | : node;
|
141 | const transformBindingExpression = (binding, node) => {
|
142 | if ((0, ts_is_kind_1.isTaggedTemplateExpression)(node) && isStyledFunction(node.tag, identifiers)) {
|
143 | return context.factory.updateTaggedTemplateExpression(node, transformStyledFunction(binding, node.tag), node.typeArguments, transformTemplateLiteral(node.template));
|
144 | }
|
145 | if ((0, ts_is_kind_1.isCallExpression)(node) && isStyledFunction(node.expression, identifiers)) {
|
146 | return context.factory.updateCallExpression(node, transformStyledFunction(binding, node.expression), node.typeArguments, node.arguments);
|
147 | }
|
148 | };
|
149 | const updateNode = (node, data, updateFn) => (data ? updateFn(node, data) : undefined);
|
150 | const updateVariableDeclarationInitializer = (node, initializer) => context.factory.updateVariableDeclaration(node, node.name, node.exclamationToken, node.type, initializer);
|
151 | const updateExportAssignmentExpression = (node, expression) => context.factory.updateExportAssignment(node, node.modifiers, expression);
|
152 | const transformNode = (node) => (0, ts_is_kind_1.isVariableDeclaration)(node) && node.initializer
|
153 | ? updateNode(node, transformBindingExpression(node, node.initializer), updateVariableDeclarationInitializer)
|
154 | : (0, ts_is_kind_1.isExportAssignment)(node)
|
155 | ? updateNode(node, transformBindingExpression(node, node.expression), updateExportAssignmentExpression)
|
156 | : minify && (0, ts_is_kind_1.isTaggedTemplateExpression)(node)
|
157 | ? transformTaggedTemplateExpression(node)
|
158 | : undefined;
|
159 | const visitNode = (node) => transformNode(node) || ts.visitEachChild(node, visitNode, context);
|
160 | return ts.visitNode(sourceFile, visitNode);
|
161 | };
|
162 | };
|
163 | return transformer;
|
164 | }
|
165 | exports.createTransformer = createTransformer;
|
166 | exports.default = createTransformer;
|