UNPKG

ts-transform-css-modules

Version:
104 lines (103 loc) 3.86 kB
"use strict"; var __rest = (this && this.__rest) || function (s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) if (e.indexOf(p[i]) < 0) t[p[i]] = s[p[i]]; return t; }; Object.defineProperty(exports, "__esModule", { value: true }); const ts = require("typescript"); const path_1 = require("path"); const fs_1 = require("fs"); const CSS_EXTENSION_REGEX = /\.css['"]$/; function resolveCssPath(cssPath, sf, tsImportResolver) { // Bc cssPath includes ' or " cssPath = cssPath.substring(1, cssPath.length - 1); let resolvedPath; if (typeof tsImportResolver === "function") { resolvedPath = tsImportResolver(cssPath); } if (typeof resolvedPath !== "string") { if (cssPath.startsWith(".")) { const sourcePath = sf.fileName; return path_1.resolve(path_1.dirname(sourcePath), cssPath); } return cssPath; } return resolvedPath; } function generateClassNameObj(resolvedCssPath) { const css = require(resolvedCssPath); return ts.createObjectLiteral(ts.createNodeArray(Object.keys(css).map(k => ts.createPropertyAssignment(ts.createLiteral(k), ts.createLiteral(css[k]))))); } function importVisitor(resolvedCssPath, node) { let classNameObj; try { classNameObj = generateClassNameObj(resolvedCssPath); } catch (e) { console.error(e); return; } // No import clause, skip if (!node.importClause) { return; } // This is the "foo" from "import * as foo from 'foo.css'" const { namedBindings } = node.importClause; // Dealing with "import * as css from 'foo.css'" only since namedImports variables get mangled if (!ts.isNamespaceImport(namedBindings)) { return; } const importVar = namedBindings.name.getText(); // Create 'var css = {}' return ts.createVariableStatement(undefined, ts.createVariableDeclarationList([ ts.createVariableDeclaration(importVar, undefined, classNameObj) ])); } function visitor(ctx, sf, tsImportResolver) { const visitor = (node) => { let newNode; let cssPath; if (ts.isImportDeclaration(node)) { if (CSS_EXTENSION_REGEX.test(node.moduleSpecifier.getText())) { cssPath = resolveCssPath(node.moduleSpecifier.getText(), sf, tsImportResolver); newNode = importVisitor(cssPath, node); } } else if (ts.isCallExpression(node)) { if (node.expression.getText() === "require" && CSS_EXTENSION_REGEX.test(node.arguments[0].getText())) { cssPath = resolveCssPath(node.arguments[0].getText(), sf, tsImportResolver); try { newNode = generateClassNameObj(cssPath); } catch (e) { console.error(e); } } } if (newNode) { const externalCssSource = ts.createSourceMapSource(cssPath, fs_1.readFileSync(cssPath, "utf-8")); ts.setSourceMapRange(newNode, { source: externalCssSource, pos: node.pos, end: node.end }); return newNode; } return ts.visitEachChild(node, visitor, ctx); }; return visitor; } function default_1(opts = {}) { const { tsImportResolver } = opts, hookOpts = __rest(opts, ["tsImportResolver"]); require("css-modules-require-hook")(hookOpts); return (ctx) => { return (sf) => ts.visitNode(sf, visitor(ctx, sf, tsImportResolver)); }; } exports.default = default_1;