lion/packages-node/babel-plugin-extend-docs/src/handleImports.js

96 lines
3 KiB
JavaScript

/* eslint-disable no-param-reassign */
const { joinPaths } = require('./helpers.js');
/**
* -1 because filepath is an absolute path starting with '/' and we turn it into a relative path without a '/' at the start
* @param {*} filePath
*/
function getFolderDepth(filePath) {
return [...filePath.match(new RegExp(/\/|\\/, 'g'))].length - 1;
}
function getImportAs(specifier, newImportName) {
if (specifier.local && specifier.local.name && specifier.local.name !== specifier.imported.name) {
return specifier.local.name;
}
return newImportName;
}
function renameAndStoreImports({ path, state, opts, types: t }) {
for (const specifier of path.node.specifiers) {
let managed = false;
if (t.isIdentifier(specifier.imported) && specifier.type === 'ImportSpecifier') {
for (const change of opts.changes) {
if (specifier.imported.name === change.variable.from) {
for (const { from, to } of change.variable.paths) {
if (managed === false && from === path.node.source.value) {
const relativePart = '../'.repeat(getFolderDepth(state.filePath));
const importAs = getImportAs(specifier, change.variable.to);
const newPath = joinPaths(relativePart, to);
// rename so it replaces all occurrences
path.scope.rename(specifier.local.name, importAs);
if (specifier.imported && specifier.imported.name) {
specifier.imported.name = change.variable.to;
}
state.importedStorage.push({
action: 'change',
specifier,
path: newPath,
});
managed = true;
}
}
}
}
}
if (managed === false) {
state.importedStorage.push({
action: 'keep',
specifier,
path: path.node.source.value,
});
}
}
path.remove();
}
function generateImportStatements({ state, types: t }) {
const statements = {};
for (const imp of state.importedStorage) {
if (!statements[imp.path]) {
statements[imp.path] = [];
}
statements[imp.path].push(imp.specifier);
}
const res = [];
for (const path of Object.keys(statements)) {
const importSpecifiers = statements[path];
const source = t.stringLiteral(path);
res.push(t.importDeclaration(importSpecifiers, source));
}
return res;
}
function replaceTagImports({ path, state, opts, types: t }) {
for (const change of opts.changes) {
if (change.tag && Array.isArray(change.tag.paths) && change.tag.paths.length > 0) {
for (const { from, to } of change.tag.paths) {
if (from === path.node.source.value) {
const relativePart = '../'.repeat(getFolderDepth(state.filePath));
const updatedPath = joinPaths(relativePart, to);
path.node.source = t.stringLiteral(updatedPath);
}
}
}
}
}
module.exports = {
renameAndStoreImports,
generateImportStatements,
replaceTagImports,
};