1 | "use strict";
|
2 |
|
3 | Object.defineProperty(exports, "__esModule", {
|
4 | value: true
|
5 | });
|
6 | exports.default = void 0;
|
7 |
|
8 | var _path = require("path");
|
9 |
|
10 | var _pluginSyntaxJsx = _interopRequireDefault(require("@babel/plugin-syntax-jsx"));
|
11 |
|
12 | var _types = _interopRequireDefault(require("@babel/types"));
|
13 |
|
14 | var _ajvKeywords = _interopRequireDefault(require("ajv-keywords"));
|
15 |
|
16 | var _ajv = _interopRequireDefault(require("ajv"));
|
17 |
|
18 | var _optionsSchema = _interopRequireDefault(require("./schemas/optionsSchema.json"));
|
19 |
|
20 | var _optionsDefaults = _interopRequireDefault(require("./schemas/optionsDefaults"));
|
21 |
|
22 | var _createObjectExpression = _interopRequireDefault(require("./createObjectExpression"));
|
23 |
|
24 | var _requireCssModule = _interopRequireDefault(require("./requireCssModule"));
|
25 |
|
26 | var _resolveStringLiteral = _interopRequireDefault(require("./resolveStringLiteral"));
|
27 |
|
28 | var _replaceJsxExpressionContainer = _interopRequireDefault(require("./replaceJsxExpressionContainer"));
|
29 |
|
30 | var _attributeNameExists = _interopRequireDefault(require("./attributeNameExists"));
|
31 |
|
32 | var _createSpreadMapper = _interopRequireDefault(require("./createSpreadMapper"));
|
33 |
|
34 | var _handleSpreadClassName = _interopRequireDefault(require("./handleSpreadClassName"));
|
35 |
|
36 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
37 |
|
38 | const ajv = new _ajv.default({
|
39 |
|
40 | $data: true
|
41 | });
|
42 | (0, _ajvKeywords.default)(ajv);
|
43 | const validate = ajv.compile(_optionsSchema.default);
|
44 |
|
45 | var _default = ({
|
46 | types: t
|
47 | }) => {
|
48 | const filenameMap = {};
|
49 | let skip = false;
|
50 |
|
51 | const setupFileForRuntimeResolution = (path, filename) => {
|
52 | const programPath = path.findParent(parentPath => {
|
53 | return parentPath.isProgram();
|
54 | });
|
55 | filenameMap[filename].importedHelperIndentifier = programPath.scope.generateUidIdentifier('getClassName');
|
56 | filenameMap[filename].styleModuleImportMapIdentifier = programPath.scope.generateUidIdentifier('styleModuleImportMap');
|
57 | programPath.unshiftContainer('body', t.importDeclaration([t.importDefaultSpecifier(filenameMap[filename].importedHelperIndentifier)], t.stringLiteral('babel-plugin-react-css-modules/dist/browser/getClassName')));
|
58 | const firstNonImportDeclarationNode = programPath.get('body').find(node => {
|
59 | return !t.isImportDeclaration(node);
|
60 | });
|
61 | firstNonImportDeclarationNode.insertBefore(t.variableDeclaration('const', [t.variableDeclarator(filenameMap[filename].styleModuleImportMapIdentifier, (0, _createObjectExpression.default)(t, filenameMap[filename].styleModuleImportMap))]));
|
62 |
|
63 | };
|
64 |
|
65 | const addWebpackHotModuleAccept = path => {
|
66 | const test = t.memberExpression(t.identifier('module'), t.identifier('hot'));
|
67 | const consequent = t.blockStatement([t.expressionStatement(t.callExpression(t.memberExpression(t.memberExpression(t.identifier('module'), t.identifier('hot')), t.identifier('accept')), [t.stringLiteral(path.node.source.value), t.functionExpression(null, [], t.blockStatement([t.expressionStatement(t.callExpression(t.identifier('require'), [t.stringLiteral(path.node.source.value)]))]))]))]);
|
68 | const programPath = path.findParent(parentPath => {
|
69 | return parentPath.isProgram();
|
70 | });
|
71 | const firstNonImportDeclarationNode = programPath.get('body').find(node => {
|
72 | return !t.isImportDeclaration(node);
|
73 | });
|
74 | const hotAcceptStatement = t.ifStatement(test, consequent);
|
75 |
|
76 | if (firstNonImportDeclarationNode) {
|
77 | firstNonImportDeclarationNode.insertBefore(hotAcceptStatement);
|
78 | } else {
|
79 | programPath.pushContainer('body', hotAcceptStatement);
|
80 | }
|
81 | };
|
82 |
|
83 | const getTargetResourcePath = (path, stats) => {
|
84 | const targetFileDirectoryPath = (0, _path.dirname)(stats.file.opts.filename);
|
85 |
|
86 | if (path.node.source.value.startsWith('.')) {
|
87 | return (0, _path.resolve)(targetFileDirectoryPath, path.node.source.value);
|
88 | }
|
89 |
|
90 | return require.resolve(path.node.source.value);
|
91 | };
|
92 |
|
93 | const isFilenameExcluded = (filename, exclude) => {
|
94 | return filename.match(new RegExp(exclude));
|
95 | };
|
96 |
|
97 | const notForPlugin = (path, stats) => {
|
98 | stats.opts.filetypes = stats.opts.filetypes || {};
|
99 | const extension = path.node.source.value.lastIndexOf('.') > -1 ? path.node.source.value.substr(path.node.source.value.lastIndexOf('.')) : null;
|
100 |
|
101 | if (extension !== '.css' && Object.keys(stats.opts.filetypes).indexOf(extension) < 0) {
|
102 | return true;
|
103 | }
|
104 |
|
105 | const filename = getTargetResourcePath(path, stats);
|
106 |
|
107 | if (stats.opts.exclude && isFilenameExcluded(filename, stats.opts.exclude)) {
|
108 | return true;
|
109 | }
|
110 |
|
111 | return false;
|
112 | };
|
113 |
|
114 | return {
|
115 | inherits: _pluginSyntaxJsx.default,
|
116 | visitor: {
|
117 | ImportDeclaration(path, stats) {
|
118 | if (skip || notForPlugin(path, stats)) {
|
119 | return;
|
120 | }
|
121 |
|
122 | const filename = stats.file.opts.filename;
|
123 | const targetResourcePath = getTargetResourcePath(path, stats);
|
124 | let styleImportName;
|
125 |
|
126 | if (path.node.specifiers.length === 0) {
|
127 |
|
128 | styleImportName = path.node.source.value;
|
129 | } else if (path.node.specifiers.length === 1) {
|
130 | styleImportName = path.node.specifiers[0].local.name;
|
131 | } else {
|
132 |
|
133 | console.warn('Please report your use case. https://github.com/gajus/babel-plugin-react-css-modules/issues/new?title=Unexpected+use+case.');
|
134 | throw new Error('Unexpected use case.');
|
135 | }
|
136 |
|
137 | filenameMap[filename].styleModuleImportMap[styleImportName] = (0, _requireCssModule.default)(targetResourcePath, {
|
138 | context: stats.opts.context,
|
139 | filetypes: stats.opts.filetypes || {},
|
140 | generateScopedName: stats.opts.generateScopedName
|
141 | });
|
142 |
|
143 | if (stats.opts.webpackHotModuleReloading) {
|
144 | addWebpackHotModuleAccept(path);
|
145 | }
|
146 |
|
147 | if (stats.opts.removeImport) {
|
148 | path.remove();
|
149 | }
|
150 | },
|
151 |
|
152 | JSXElement(path, stats) {
|
153 | if (skip) {
|
154 | return;
|
155 | }
|
156 |
|
157 | const filename = stats.file.opts.filename;
|
158 |
|
159 | if (stats.opts.exclude && isFilenameExcluded(filename, stats.opts.exclude)) {
|
160 | return;
|
161 | }
|
162 |
|
163 | let attributeNames = _optionsDefaults.default.attributeNames;
|
164 |
|
165 | if (stats.opts && stats.opts.attributeNames) {
|
166 | attributeNames = Object.assign({}, attributeNames, stats.opts.attributeNames);
|
167 | }
|
168 |
|
169 | const attributes = path.node.openingElement.attributes.filter(attribute => {
|
170 | return typeof attribute.name !== 'undefined' && typeof attributeNames[attribute.name.name] === 'string';
|
171 | });
|
172 |
|
173 | if (attributes.length === 0) {
|
174 | return;
|
175 | }
|
176 |
|
177 | const {
|
178 | handleMissingStyleName = _optionsDefaults.default.handleMissingStyleName,
|
179 | autoResolveMultipleImports = _optionsDefaults.default.autoResolveMultipleImports
|
180 | } = stats.opts || {};
|
181 | const spreadMap = (0, _createSpreadMapper.default)(path, stats);
|
182 |
|
183 | for (const attribute of attributes) {
|
184 | const destinationName = attributeNames[attribute.name.name];
|
185 | const options = {
|
186 | autoResolveMultipleImports,
|
187 | handleMissingStyleName
|
188 | };
|
189 |
|
190 | if (t.isStringLiteral(attribute.value)) {
|
191 | (0, _resolveStringLiteral.default)(path, filenameMap[filename].styleModuleImportMap, attribute, destinationName, options);
|
192 | } else if (t.isJSXExpressionContainer(attribute.value)) {
|
193 | if (!filenameMap[filename].importedHelperIndentifier) {
|
194 | setupFileForRuntimeResolution(path, filename);
|
195 | }
|
196 |
|
197 | (0, _replaceJsxExpressionContainer.default)(t, path, attribute, destinationName, filenameMap[filename].importedHelperIndentifier, filenameMap[filename].styleModuleImportMapIdentifier, options);
|
198 | }
|
199 |
|
200 | if (spreadMap[destinationName]) {
|
201 | (0, _handleSpreadClassName.default)(path, destinationName, spreadMap[destinationName]);
|
202 | }
|
203 | }
|
204 | },
|
205 |
|
206 | Program(path, stats) {
|
207 | if (!validate(stats.opts)) {
|
208 |
|
209 | console.error(validate.errors);
|
210 | throw new Error('Invalid configuration');
|
211 | }
|
212 |
|
213 | const filename = stats.file.opts.filename;
|
214 | filenameMap[filename] = {
|
215 | styleModuleImportMap: {}
|
216 | };
|
217 |
|
218 | if (stats.opts.skip && !(0, _attributeNameExists.default)(path, stats)) {
|
219 | skip = true;
|
220 | }
|
221 | }
|
222 |
|
223 | }
|
224 | };
|
225 | };
|
226 |
|
227 | exports.default = _default;
|
228 |
|
\ | No newline at end of file |