knip
Version:
Find and fix unused dependencies, exports and files in your TypeScript and JavaScript projects
55 lines (54 loc) • 2.44 kB
JavaScript
import { Visitor } from 'oxc-parser';
import { findProperty, getImportMap, getStringValues } from '../../typescript/ast-helpers.js';
import { isFile, loadFile } from '../../util/fs.js';
import { toProductionEntry } from '../../util/input.js';
import { join } from '../../util/path.js';
import { getDependenciesFromConfig } from '../babel/index.js';
const babelPluginSources = ['@rolldown/plugin-babel', '@vitejs/plugin-react', 'vite-plugin-babel'];
const isBabelWrappingPlugin = (path) => babelPluginSources.some(source => path === source || path.startsWith(`${source}/`));
export const getBabelInputs = (program) => {
const pluginNames = new Set();
for (const [name, path] of getImportMap(program)) {
if (isBabelWrappingPlugin(path))
pluginNames.add(name);
}
if (pluginNames.size === 0)
return [];
const inputs = [];
const visitor = new Visitor({
CallExpression(node) {
if (node.callee?.type !== 'Identifier' || !pluginNames.has(node.callee.name))
return;
const options = node.arguments?.[0];
const plugins = [];
const presets = [];
for (const config of [options, findProperty(options, 'babel'), findProperty(options, 'babelConfig')]) {
plugins.push(...getStringValues(findProperty(config, 'plugins')));
presets.push(...getStringValues(findProperty(config, 'presets')));
}
inputs.push(...getDependenciesFromConfig({ plugins, presets }));
},
});
visitor.visit(program);
return inputs;
};
const moduleScriptPattern = /<script\b(?=[^>]*\btype\s*=\s*["']?module["']?)(?=[^>]*\bsrc\s*=\s*["']?([^"' >]+)["']?)[^>]*>/gi;
const normalizeModuleScriptSrc = (value) => value.trim().replace(/^\//, '');
const getModuleScriptSources = (html) => {
const matches = html.matchAll(moduleScriptPattern);
const sources = [];
for (const match of matches) {
const src = normalizeModuleScriptSrc(match[1]);
if (src)
sources.push(src);
}
return sources;
};
export const getIndexHtmlEntries = async (rootDir) => {
const indexPath = join(rootDir, 'index.html');
if (!isFile(indexPath))
return [];
const html = await loadFile(indexPath);
const entries = getModuleScriptSources(html).map(src => join(rootDir, src));
return entries.map(entry => toProductionEntry(entry));
};