All files / lib plugin.js

100% Statements 27/27
100% Branches 20/20
100% Functions 4/4
100% Lines 24/24

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81    7x 7x             1x                       7x 11x   11x       32x 32x   31x 31x 31x 12x   12x 22x 1x 1x     21x         21x   21x 19x 34x     19x   19x                                   12x          
"use strict";
 
const PluginOptions = require("./internal/PluginOptions");
const DependencyTree = require("./internal/DependencyTree");
 
/**
 * @param {string} localName
 * @param {string} source
 */
function warnNamespaceImport(localName, source) {
  console.warn(
    `
babel-plugin-direct-import: Can not optimize 'import * as ${localName} from "${source}"'.
See plugin limitations https://git.io/vFDOO for more details.    
`.trim()
  );
}
 
/**
 * @param {import("@babel/core")} babel
 * @returns {import("@babel/core").PluginObj}
 */
module.exports = function plugin(babel) {
  const { types: t } = babel;
 
  return {
    name: "babel-plugin-direct-import",
    visitor: {
      ImportDeclaration(declaration, { opts }) {
        const { source, specifiers, importKind } = declaration.node;
        if (!specifiers.length || importKind === "type") return;
 
        const pluginOptions = PluginOptions.parse(opts);
        const nodeModule = pluginOptions.modules.get(source.value);
        if (!nodeModule) return;
        const tree = DependencyTree.create(nodeModule, babel);
 
        for (const specifier of specifiers) {
          if (t.isImportNamespaceSpecifier(specifier)) {
            warnNamespaceImport(specifier.local.name, source.value);
            continue;
          }
 
          const moduleName = t.isImportDefaultSpecifier(specifier)
            ? "default"
            : t.isIdentifier(specifier.imported)
            ? specifier.imported.name
            : specifier.imported.value;
          const dependency = tree.dependencies.get(moduleName);
 
          if (dependency) {
            declaration.node.specifiers = declaration.node.specifiers.filter(
              (x) => x !== specifier
            );
 
            const localName = t.identifier(specifier.local.name);
 
            declaration.insertBefore(
              t.importDeclaration(
                [
                  dependency.internalID === "*"
                    ? t.importNamespaceSpecifier(localName)
                    : dependency.internalID === "default"
                    ? t.importDefaultSpecifier(localName)
                    : t.importSpecifier(
                        localName,
                        t.identifier(dependency.internalID)
                      ),
                ],
                t.stringLiteral(dependency.source)
              )
            );
          }
        }
 
        if (!declaration.node.specifiers.length) declaration.remove();
      },
    },
  };
};