@digitak/grubber
Version:
Parse code files and patch it without having to use an AST
56 lines (55 loc) • 2.64 kB
JavaScript
import { readdirSync, statSync, readFileSync, writeFileSync } from "fs";
import addJsExtensions from "./addJsExtensions.js";
import { relative as relativePath, resolve as resolvePath, sep, posix } from "path";
import { createRequire } from "module";
import { resolveAliases } from "./resolveAliases.js";
const require = createRequire(process.cwd());
const resolve = (dependency, directory) => require
.resolve(dependency, { paths: [directory] })
.split(sep)
.join(posix.sep);
const relative = (directory, path) => relativePath(directory, path).split(sep).join(posix.sep);
const NODE_MODULES_DIR_REGEX = /(^|\/)node_modules(\/|$)/;
/**
* When Typescript compiles dependencies, it adds no '.js' extension at the end of imports.
* The problem is: browser, Node and Deno all need this '.js' extension.
* (Thanks #TypescriptTeam for not being standard, look at all the additional work you make me do!)
* (All this work for three stupid letters!...)
* (Love your work though, Typescript is an awesome language <3)
* This utility function can be used after a Typescript compilation to add the mandatory '.js'
*/
export default function patchJsImports(directories, aliases) {
for (let directory of directories) {
directory = resolvePath(directory);
for (const element of readdirSync(directory)) {
const entity = `${directory}/${element}`;
if (statSync(entity).isDirectory()) {
patchJsImports([entity], aliases);
}
else {
// only patch .js, .cjs and .mjs files
if (!element.match(/\.[mc]?js$/))
continue;
const content = readFileSync(entity, "utf8");
const patchedContent = addJsExtensions(content, imported => {
const resolvedAlias = resolveAliases(imported, aliases);
if (resolvedAlias != null)
return resolvedAlias;
let path = resolve(imported, directory);
if (path !== imported) {
const isNodeModulePath = NODE_MODULES_DIR_REGEX.test(path);
if (isNodeModulePath)
path = imported;
else {
path = relative(directory, path);
if (path[0] !== "." && path[0] !== "/")
path = `./${path}`;
}
}
return path;
});
writeFileSync(entity, patchedContent);
}
}
}
}