UNPKG

typescript-react-loadable-plugin

Version:

A react-loadable plugin to add modules & webpack for typescript

159 lines 6.84 kB
/*! * Copyright 2019 acrazing <joking.young@gmail.com>. All rights reserved. * @since 2019-10-31 19:19:08 */ import { __read, __values } from "tslib"; import ts from 'typescript'; import vm from 'vm'; import { State } from './State'; var webpackCommentRegExp = new RegExp(/(^|\W)webpack[A-Z]+[A-Za-z]+:/); function createResolveWeak(id) { return ts.createCall(ts.createPropertyAccess(ts.createIdentifier('require'), 'resolveWeak'), void 0, [ts.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 (ts.isCallExpression(node) && node.expression.kind === ts.SyntaxKind.ImportKeyword) { var arg0 = node.arguments[0]; if (ts.isStringLiteral(arg0)) { webpackIds.add(arg0.text); var chunkName = ''; if (state.webpackChunkName) { var commentRanges = ts.getLeadingCommentRanges(state.sourceFile.text, arg0.pos) || []; try { for (var commentRanges_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 === ts.SyntaxKind.SingleLineCommentTrivia) { comment = comment.substr(2); } else { comment = comment.substr(2, comment.length - 4); } if (webpackCommentRegExp.test(comment)) { try { var commentValue = vm.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); ts.addSyntheticLeadingComment(arg0, ts.SyntaxKind.MultiLineCommentTrivia, " webpackChunkName: " + JSON.stringify(chunkName) + " ", false); } } if (state.moduleKind === 'webpackChunkName') { moduleIds.add(chunkName); } else { moduleIds.add(arg0.text); } } } return ts.visitEachChild(node, visitor, state.transformContext); }; return [ts.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 = ts.isIdentifier(node.name) ? node.name.escapedText : ts.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 = __read(parseLoader(state, loader), 3), moduleIds = _a[1], webpackIds = _a[2]; if (!modules && state.modules) { properties.push(ts.createPropertyAssignment('modules', ts.createArrayLiteral(state.moduleKind === 'webpackModuleId' ? Array.from(moduleIds, createResolveWeak) : Array.from(moduleIds, function (id) { return ts.createStringLiteral(id); })))); } if (!webpack && state.webpack) { properties.push(ts.createPropertyAssignment('webpack', ts.createArrowFunction(void 0, void 0, [], void 0, void 0, ts.createArrayLiteral(Array.from(webpackIds, createResolveWeak))))); } return ts.createObjectLiteral(properties, true); } export function getRealExpression(node) { return ts.isParenthesizedExpression(node) ? getRealExpression(node.expression) : ts.isAsExpression(node) ? getRealExpression(node.expression) : node; } function visitReactLoadable(state, node) { if (!ts.isCallExpression(node) || node.arguments.length !== 1) { return node; } var config = getRealExpression(node.arguments[0]); if (!ts.isObjectLiteralExpression(config)) { return node; } var identifier = getRealExpression(node.expression); if (ts.isPropertyAccessExpression(identifier) && identifier.name.escapedText === 'Map') { identifier = getRealExpression(identifier.expression); } if (!ts.isIdentifier(identifier) || !state.identifiers.has(identifier.escapedText)) { return node; } return ts.createCall(node.expression, node.typeArguments, [ transformReactLoadable(state, config), ]); } export function createReactLoadableTransformer(program, options) { var state = new State(options); return function (context) { state.transformContext = context; return function (source) { state.setSourceFile(source); var visitor = function (node) { node = visitReactLoadable(state, node); return ts.visitEachChild(node, visitor, context); }; return ts.visitNode(source, visitor); }; }; } //# sourceMappingURL=createReactLoadableTransformer.js.map