typescript-react-loadable-plugin
Version:
A react-loadable plugin to add modules & webpack for typescript
163 lines • 7.67 kB
JavaScript
/*!
* Copyright 2019 acrazing <joking.young@gmail.com>. All rights reserved.
* @since 2019-10-31 19:19:08
*/
Object.defineProperty(exports, "__esModule", { value: true });
var tslib_1 = require("tslib");
var typescript_1 = tslib_1.__importDefault(require("typescript"));
var vm_1 = tslib_1.__importDefault(require("vm"));
var State_1 = require("./State");
var webpackCommentRegExp = new RegExp(/(^|\W)webpack[A-Z]+[A-Za-z]+:/);
function createResolveWeak(id) {
return typescript_1.default.createCall(typescript_1.default.createPropertyAccess(typescript_1.default.createIdentifier('require'), 'resolveWeak'), void 0, [typescript_1.default.createStringLiteral(id)]);
}
// TODO: parse require.ensure
function parseLoader(state, loader) {
var moduleIds = new Set();
var webpackIds = new Set();
var visitor = function (node) {
var e_1, _a;
if (typescript_1.default.isCallExpression(node) &&
node.expression.kind === typescript_1.default.SyntaxKind.ImportKeyword) {
var arg0 = node.arguments[0];
if (typescript_1.default.isStringLiteral(arg0)) {
webpackIds.add(arg0.text);
var chunkName = '';
if (state.webpackChunkName) {
var commentRanges = typescript_1.default.getLeadingCommentRanges(state.sourceFile.text, arg0.pos) || [];
try {
for (var commentRanges_1 = tslib_1.__values(commentRanges), commentRanges_1_1 = commentRanges_1.next(); !commentRanges_1_1.done; commentRanges_1_1 = commentRanges_1.next()) {
var range = commentRanges_1_1.value;
var comment = state.sourceFile.text.substring(range.pos, range.end);
if (range.kind === typescript_1.default.SyntaxKind.SingleLineCommentTrivia) {
comment = comment.substr(2);
}
else {
comment = comment.substr(2, comment.length - 4);
}
if (webpackCommentRegExp.test(comment)) {
try {
var commentValue = vm_1.default.runInNewContext("({ " + comment + " })");
if (typeof commentValue.webpackChunkName === 'string') {
chunkName = commentValue.webpackChunkName;
break;
}
}
catch (e) {
throw new Error(e + " while parse webpack comment chunk: " + comment);
}
}
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (commentRanges_1_1 && !commentRanges_1_1.done && (_a = commentRanges_1.return)) _a.call(commentRanges_1);
}
finally { if (e_1) throw e_1.error; }
}
if (!chunkName) {
chunkName = state.getWebpackChunkName(arg0.text, state.sourceContext);
typescript_1.default.addSyntheticLeadingComment(arg0, typescript_1.default.SyntaxKind.MultiLineCommentTrivia, " webpackChunkName: " + JSON.stringify(chunkName) + " ", false);
}
}
if (state.moduleKind === 'webpackChunkName') {
moduleIds.add(chunkName);
}
else {
moduleIds.add(arg0.text);
}
}
}
return typescript_1.default.visitEachChild(node, visitor, state.transformContext);
};
return [typescript_1.default.visitNode(loader, visitor), moduleIds, webpackIds];
}
function transformReactLoadable(state, config) {
var loader = void 0;
var modules = void 0;
var webpack = void 0;
var properties = config.properties.slice();
properties.forEach(function (node) {
if (node.name) {
var name_1 = typescript_1.default.isIdentifier(node.name)
? node.name.escapedText
: typescript_1.default.isStringLiteral(node.name)
? node.name.text
: void 0;
switch (name_1) {
case 'loader':
loader = node;
break;
case 'modules':
modules = node;
break;
case 'webpack':
webpack = node;
break;
}
}
});
if (!loader) {
return config;
}
if ((modules || !state.modules) && (webpack || !state.webpack)) {
return config;
}
var _a = tslib_1.__read(parseLoader(state, loader), 3), moduleIds = _a[1], webpackIds = _a[2];
if (!modules && state.modules) {
properties.push(typescript_1.default.createPropertyAssignment('modules', typescript_1.default.createArrayLiteral(state.moduleKind === 'webpackModuleId'
? Array.from(moduleIds, createResolveWeak)
: Array.from(moduleIds, function (id) { return typescript_1.default.createStringLiteral(id); }))));
}
if (!webpack && state.webpack) {
properties.push(typescript_1.default.createPropertyAssignment('webpack', typescript_1.default.createArrowFunction(void 0, void 0, [], void 0, void 0, typescript_1.default.createArrayLiteral(Array.from(webpackIds, createResolveWeak)))));
}
return typescript_1.default.createObjectLiteral(properties, true);
}
function getRealExpression(node) {
return typescript_1.default.isParenthesizedExpression(node)
? getRealExpression(node.expression)
: typescript_1.default.isAsExpression(node)
? getRealExpression(node.expression)
: node;
}
exports.getRealExpression = getRealExpression;
function visitReactLoadable(state, node) {
if (!typescript_1.default.isCallExpression(node) || node.arguments.length !== 1) {
return node;
}
var config = getRealExpression(node.arguments[0]);
if (!typescript_1.default.isObjectLiteralExpression(config)) {
return node;
}
var identifier = getRealExpression(node.expression);
if (typescript_1.default.isPropertyAccessExpression(identifier) &&
identifier.name.escapedText === 'Map') {
identifier = getRealExpression(identifier.expression);
}
if (!typescript_1.default.isIdentifier(identifier) ||
!state.identifiers.has(identifier.escapedText)) {
return node;
}
return typescript_1.default.createCall(node.expression, node.typeArguments, [
transformReactLoadable(state, config),
]);
}
function createReactLoadableTransformer(program, options) {
var state = new State_1.State(options);
return function (context) {
state.transformContext = context;
return function (source) {
state.setSourceFile(source);
var visitor = function (node) {
node = visitReactLoadable(state, node);
return typescript_1.default.visitEachChild(node, visitor, context);
};
return typescript_1.default.visitNode(source, visitor);
};
};
}
exports.createReactLoadableTransformer = createReactLoadableTransformer;
//# sourceMappingURL=createReactLoadableTransformer.js.map
;