UNPKG

6.03 kBJavaScriptView Raw
1import * as tslib_1 from "tslib";
2// @ts-ignore
3import * as crc32 from 'crc-32';
4import { existsSync } from 'fs';
5import { dirname, join, relative, resolve } from 'path';
6import { processComment } from './magic-comments';
7export var encipherImport = function (str) {
8 return crc32.str(str).toString(32);
9};
10// Babel v7 compat
11var syntax;
12try {
13 syntax = require('babel-plugin-syntax-dynamic-import');
14}
15catch (err) {
16 try {
17 syntax = require('@babel/plugin-syntax-dynamic-import');
18 }
19 catch (e) {
20 throw new Error('react-imported-component babel plugin is requiring `babel-plugin-syntax-dynamic-import` or `@babel/plugin-syntax-dynamic-import` to work. Please add this dependency.');
21 }
22}
23syntax = syntax.default || syntax;
24var resolveImport = function (importName, file) {
25 if (file === void 0) { file = ''; }
26 if (importName.charAt(0) === '.') {
27 return relative(process.cwd(), resolve(dirname(file), importName));
28 }
29 return importName;
30};
31var templateOptions = {
32 placeholderPattern: /^([A-Z0-9]+)([A-Z0-9_]+)$/,
33};
34function getImportArg(callPath) {
35 return callPath.get('arguments.0');
36}
37function getComments(callPath) {
38 return callPath.has('leadingComments') ? callPath.get('leadingComments') : [];
39}
40// load configuration
41var configurationFile = join(process.cwd(), '.imported.js');
42var defaultConfiguration = (existsSync(configurationFile)
43 ? require(configurationFile)
44 : {});
45export var createTransformer = function (_a, excludeMacro, configuration) {
46 var t = _a.types, template = _a.template;
47 if (excludeMacro === void 0) { excludeMacro = false; }
48 if (configuration === void 0) { configuration = defaultConfiguration; }
49 var headerTemplate = template("var importedWrapper = require('react-imported-component/wrapper');", templateOptions);
50 var importRegistration = template('importedWrapper(MARK, IMPORT)', templateOptions);
51 var hasImports = new Set();
52 var visitedNodes = new Map();
53 return {
54 traverse: function (programPath, fileName) {
55 var isBootstrapFile = false;
56 programPath.traverse({
57 ImportDeclaration: function (path) {
58 if (excludeMacro) {
59 return;
60 }
61 var source = path.node.source.value;
62 if (source === 'react-imported-component/macro') {
63 var specifiers = path.node.specifiers;
64 path.remove();
65 var assignName = 'assignImportedComponents';
66 if (specifiers.length === 1 && specifiers[0].imported.name === assignName) {
67 isBootstrapFile = true;
68 programPath.node.body.unshift(t.importDeclaration([t.importSpecifier(t.identifier(assignName), t.identifier(assignName))], t.stringLiteral('react-imported-component/boot')));
69 }
70 else {
71 programPath.node.body.unshift(t.importDeclaration(specifiers.map(function (spec) {
72 return t.importSpecifier(t.identifier(spec.imported.name), t.identifier(spec.imported.name));
73 }), t.stringLiteral('react-imported-component')));
74 }
75 }
76 },
77 Import: function (_a) {
78 var parentPath = _a.parentPath;
79 if (visitedNodes.has(parentPath.node)) {
80 return;
81 }
82 var newImport = parentPath.node;
83 var rawImport = getImportArg(parentPath);
84 var importName = rawImport.node.value;
85 var rawComments = getComments(rawImport);
86 var comments = rawComments.map(function (parent) { return parent.node.value; });
87 var newComments = processComment(configuration, comments, importName, fileName, {
88 isBootstrapFile: isBootstrapFile,
89 });
90 if (newComments !== comments) {
91 rawComments.forEach(function (comment) { return comment.remove(); });
92 newComments.forEach(function (comment) {
93 rawImport.addComment('leading', " " + comment + " ");
94 });
95 }
96 if (!importName) {
97 return;
98 }
99 var requiredFileHash = encipherImport(resolveImport(importName, fileName));
100 var replace = null;
101 replace = importRegistration({
102 MARK: t.stringLiteral("imported_" + requiredFileHash + "_component"),
103 IMPORT: newImport,
104 });
105 hasImports.add(fileName);
106 visitedNodes.set(newImport, true);
107 parentPath.replaceWith(replace);
108 },
109 });
110 },
111 finish: function (node, filename) {
112 if (!hasImports.has(filename)) {
113 return;
114 }
115 node.body.unshift(headerTemplate());
116 },
117 hasImports: hasImports,
118 };
119};
120export var babelPlugin = function (babel, options) {
121 if (options === void 0) { options = {}; }
122 var transformer = createTransformer(babel, false, tslib_1.__assign({}, defaultConfiguration, options));
123 return {
124 inherits: syntax,
125 visitor: {
126 Program: {
127 enter: function (programPath, _a) {
128 var file = _a.file;
129 transformer.traverse(programPath, file.opts.filename);
130 },
131 exit: function (_a, _b) {
132 var node = _a.node;
133 var file = _b.file;
134 transformer.finish(node, file.opts.filename);
135 },
136 },
137 },
138 };
139};