@suid/vite-plugin
Version:
SUID integration plugin for Vite.
133 lines (132 loc) • 3.7 kB
JavaScript
import $generate from "@babel/generator";
import { parse } from "@babel/parser";
import $traverse from "@babel/traverse";
import * as types from "@babel/types";
const traverse = $traverse.default;
const generate = $generate.default;
const defaultOptions = {
disableOptimizeDeps: [
"@suid/base",
"@suid/codemod",
"@suid/css",
"@suid/icons-material",
"@suid/material",
"@suid/styled-engine",
"@suid/system",
"@suid/types",
"@suid/utils"
],
optimizeImports: {
enabled: true,
paths: ["@suid/icons-material", "@suid/material"]
},
parserOptions: {
sourceType: "module",
plugins: ["jsx", "typescript"]
},
sourceMaps: false
};
function suidPlugin(inOptions = {}) {
const options = {
...defaultOptions,
...inOptions,
parserOptions: {
...defaultOptions.parserOptions,
...inOptions.parserOptions
},
optimizeImports: {
...defaultOptions.optimizeImports,
...inOptions.optimizeImports
}
};
return {
name: "suid",
config: (config) => {
const solidDeps = options.disableOptimizeDeps || [];
return {
optimizeDeps: {
exclude: [...config.optimizeDeps?.exclude || [], ...solidDeps]
},
ssr: {
...config.ssr,
noExternal: [
...Array.isArray(config.ssr?.noExternal) ? config.ssr.noExternal : [],
...solidDeps
]
}
};
},
transform(code, id) {
const transformIconImportsOptions = options.optimizeImports || {};
if (transformIconImportsOptions.enabled && transformIconImportsOptions.paths?.some((p) => code.includes(p))) {
return transform(code, options, id);
}
}
};
}
function isCapitalized(value) {
return value[0].toUpperCase() === value[0];
}
function isMaterialStylesImport(value) {
return !["useMediaQuery"].includes(value) && (["StyledEngineProvider", "Breakpoint", "ThemeProvider", "Theme"].includes(
value
) || !isCapitalized(value));
}
function getOptimizedImportPath(source, name, alias) {
if (source === "@suid/material") {
if (isMaterialStylesImport(name)) {
return {
specifier: {
[name]: alias
},
path: `${source}/styles`
};
}
}
return {
specifier: alias,
path: `${source}/${name}`
};
}
function transform(code, options, id) {
const ast = parse(code, options.parserOptions);
traverse(ast, {
enter(path) {
const { node } = path;
const optimize = types.isImportDeclaration(node) && options.optimizeImports.paths.some((v) => v === node.source.value);
if (!optimize) return;
const imports = node.specifiers.map((spec) => {
if (types.isImportSpecifier(spec) && types.isIdentifier(spec.imported) && types.isIdentifier(spec.local)) {
return getOptimizedImportPath(
node.source.value,
spec.imported.name,
spec.local.name
);
}
}).filter((v) => !!v);
path.replaceWithMultiple(
imports.map(
(item) => types.importDeclaration(
typeof item.specifier === "string" ? [types.importDefaultSpecifier(types.identifier(item.specifier))] : [
...Object.entries(item.specifier).map(
([alias, specifier]) => types.importSpecifier(
types.identifier(specifier),
types.identifier(alias)
)
)
],
types.stringLiteral(item.path)
)
)
);
}
});
return generate(ast, {
sourceMaps: options.sourceMaps,
sourceFileName: id
});
}
export {
suidPlugin as default,
transform
};