vite-plugin-layoutaid
Version:
Vite plugin that adds visual layout aid for integrating web pages
101 lines (96 loc) • 2.95 kB
JavaScript
import { readFile } from 'node:fs/promises';
import defu from 'defu';
import { resolve } from 'node:path';
import { fileURLToPath } from 'node:url';
function createPlugin(pluginName, clientPath, defaultConfig) {
return function(pluginConfig = {}) {
const {
prod = false,
inject = true
} = pluginConfig;
const hotVirtualModuleId = `virtual:${pluginName}`;
const hotResolvedVirtualModuleId = `\0${hotVirtualModuleId}`;
let isDev = false;
function shouldInject() {
return inject && (isDev || prod);
}
let config;
let mainEntry;
function findMainEntry(html) {
const scriptMatch = html.match(/<script[^>]*type="module"[^>]*src="([^"]*)"[^>]*>/g);
if (scriptMatch) {
const mainScript = scriptMatch.find((script) => !script.includes("@vite/client"));
mainEntry = mainScript?.match(/src="([^"]*)"/)?.[1];
}
}
return {
name: `vite-plugin-${pluginName}`,
config(config2) {
const configObject = defu(pluginConfig, defaultConfig);
config2.define = {
...config2.define,
__LAYOUTAID_CONFIG__: JSON.stringify(configObject)
};
return config2;
},
configResolved(resolvedConfig) {
config = resolvedConfig;
isDev = config.command === "serve";
if (inject && config.build?.rollupOptions?.input) {
mainEntry = typeof config.build.rollupOptions.input === "string" ? config.build.rollupOptions.input : Array.isArray(config.build.rollupOptions.input) ? config.build.rollupOptions.input[0] : Object.values(config.build.rollupOptions.input)[0];
}
},
resolveId(id) {
if (id === hotVirtualModuleId) {
return hotResolvedVirtualModuleId;
}
},
async load(id, context) {
if (context?.ssr) {
return null;
}
if (id === hotResolvedVirtualModuleId) {
return await readFile(clientPath, "utf-8");
}
},
transformIndexHtml(html) {
if (inject && !mainEntry) {
findMainEntry(html);
}
return html;
},
async transform(code, id) {
if (!shouldInject()) {
return null;
}
const normalizedId = id.split("?")[0];
if (normalizedId.endsWith(".html")) {
findMainEntry(code);
}
const isEntry = mainEntry && normalizedId.endsWith(mainEntry);
if (!isEntry) {
return null;
}
return {
code: `import '${hotVirtualModuleId}';
${code}`,
map: null
};
}
};
};
}
function getPluginClientPath(indexFile) {
return resolve(fileURLToPath(new URL(".", indexFile)), "client.mjs");
}
const index = createPlugin(
"layoutaid",
getPluginClientPath(import.meta.url),
{
columns: {},
// use module defaults
outline: {}
// use module defaults
}
);
export { index as default };