@bitrix24/b24ui-nuxt
Version:
Bitrix24 UI-Kit for developing web applications REST API for NUXT & VUE
250 lines (241 loc) • 9.39 kB
JavaScript
import { fileURLToPath } from 'node:url';
import { join, normalize } from 'pathe';
import { createUnplugin } from 'unplugin';
import { defu } from 'defu';
import tailwind from '@tailwindcss/vite';
import { g as getTemplates, d as defaultOptions, a as getDefaultUiConfig } from './shared/b24ui-nuxt.COkgCO-x.mjs';
import { globSync } from 'tinyglobby';
import { genSafeVariableName } from 'knitwork';
import MagicString from 'magic-string';
import { resolvePathSync } from 'mlly';
import AutoImportComponents from 'unplugin-vue-components';
import AutoImport from 'unplugin-auto-import';
import 'scule';
import '@nuxt/kit';
function TemplatePlugin(options) {
const templates = getTemplates(options);
const templateKeys = new Set(templates.map((t) => `#build/${t.filename}`));
return {
name: "bitrix24:b24ui:templates",
enforce: "pre",
resolveId(id) {
if (templateKeys.has(id + ".ts")) {
return id.replace("#build/", "virtual:bitrix24-ui-templates/") + ".ts";
}
},
loadInclude: (id) => templateKeys.has(id.replace("virtual:bitrix24-ui-templates/", "#build/")),
load(id) {
id = id.replace("virtual:bitrix24-ui-templates/", "#build/");
return templates.find((t) => `#build/${t.filename}` === id).getContents({});
}
};
}
function PluginsPlugin(options) {
const plugins = globSync(["**/*", "!*.d.ts"], { cwd: join(runtimeDir, "plugins"), absolute: true });
plugins.unshift(resolvePathSync("../runtime/vue/plugins/head", { extensions: [".ts", ".mjs", ".js"], url: import.meta.url }));
if (options.colorMode) {
plugins.push(resolvePathSync("../runtime/vue/plugins/color-mode", { extensions: [".ts", ".mjs", ".js"], url: import.meta.url }));
}
return {
name: "bitrix24:b24ui:plugins",
enforce: "pre",
resolveId(id) {
if (id === "@bitrix24/b24ui-nuxt/vue-plugin") {
return "virtual:bitrix24-ui-plugins";
}
},
transform(code, id) {
if (plugins.some((p) => id.startsWith(p)) && code.includes("import.meta.client")) {
const s = new MagicString(code);
s.replaceAll("import.meta.client", "true");
if (s.hasChanged()) {
return {
code: s.toString(),
map: s.generateMap({ hires: true })
};
}
}
},
loadInclude: (id) => id === "virtual:bitrix24-ui-plugins",
load() {
return `
${plugins.map((p) => `import ${genSafeVariableName(p)} from "${p}"`).join("\n")}
export default {
install (app) {
${plugins.map((p) => ` app.use(${genSafeVariableName(p)})`).join("\n")}
}
}
`;
},
// Argument Vite specific configuration
vite: {
config() {
return {
// Opt-out Bitrix24 UI from Vite's pre-bundling,
// as we need Vite's pipeline to resolve imports like `#imports`
optimizeDeps: {
exclude: ["@bitrix24/b24ui-nuxt"]
}
};
}
}
};
}
function AppConfigPlugin(options, appConfig) {
return {
name: "bitrix24:b24ui:app-config",
enforce: "pre",
resolveId(id) {
if (id === "#build/app.config") {
return "virtual:bitrix24-ui-app-config";
}
},
loadInclude: (id) => id === "virtual:bitrix24-ui-app-config",
load() {
return `
export default ${JSON.stringify(appConfig)}
`;
},
vite: {
config() {
return {
test: {
server: {
deps: {
inline: ["@bitrix24/b24ui"]
}
}
}
};
}
}
};
}
function ComponentImportPlugin(options, meta) {
const components = globSync("**/*.vue", { cwd: join(runtimeDir, "components") });
const componentNames = new Set(components.map((c) => `B24${c.replace(/\.vue$/, "")}`));
const componentsContent = globSync("**/*.vue", { cwd: join(runtimeDir, "components/content") });
const componentContentNames = new Set(componentsContent.map((c) => `B24${c.replace(/\.vue$/, "")}`));
const inertiaOverrides = globSync("**/*.vue", { cwd: join(runtimeDir, "inertia/components") });
const inertiaOverrideNames = new Set(inertiaOverrides.map((c) => `B24${c.replace(/\.vue$/, "")}`));
const componentsProse = globSync("**/*.vue", { cwd: join(runtimeDir, "prose") });
const componentProseNames = new Set(componentsProse.map((c) => `Prose${c.replace(/\.vue$/, "")}`));
const overrides = globSync("**/*.vue", { cwd: join(runtimeDir, "vue/components") });
const overrideNames = new Set(overrides.map((c) => `B24${c.replace(/\.vue$/, "")}`));
const pluginOptions = defu(options.components, {
dts: options.dts ?? true,
exclude: [
/[\\/]node_modules[\\/](?!\.pnpm|@bitrix24\/b24ui-nuxt|@compodium\/examples)/,
/[\\/]\.git[\\/]/,
/[\\/]\.nuxt[\\/]/
],
resolvers: [
(componentName) => {
if (options.inertia && inertiaOverrideNames.has(componentName)) {
return { name: "default", from: join(runtimeDir, "inertia/components", `${componentName.slice("B24".length)}.vue`) };
}
if (overrideNames.has(componentName))
return { name: "default", from: join(runtimeDir, "vue/components", `${componentName.slice("B24".length)}.vue`) };
if (componentProseNames.has(componentName))
return { name: "default", from: join(runtimeDir, "prose", `${componentName.slice("Prose".length)}.vue`) };
if (componentContentNames.has(componentName))
return { name: "default", from: join(runtimeDir, "components/content", `${componentName.slice("B24".length)}.vue`) };
if (componentNames.has(componentName))
return { name: "default", from: join(runtimeDir, "components", `${componentName.slice("B24".length)}.vue`) };
}
]
});
return [
/**
* This plugin aims to ensure we override certain components with Vue-compatible versions:
* <B24Link> currently.
*/
{
name: "bitrix24:b24ui:components",
enforce: "pre",
resolveId(id, importer) {
if (!importer) {
return;
}
if (!normalize(importer).includes(runtimeDir) && (!options.extraRuntimeDir || !normalize(importer).includes(options.extraRuntimeDir))) {
return;
}
if (!RELATIVE_IMPORT_RE.test(id) && !id.startsWith("@bitrix24/b24ui-nuxt/components/")) {
return;
}
const filename = id.match(/([^/]+)\.vue$/)?.[1];
if (filename && options.inertia && inertiaOverrideNames.has(`B24${filename}`)) {
return join(runtimeDir, "inertia/components", `${filename}.vue`);
}
if (filename && overrideNames.has(`B24${filename}`)) {
return join(runtimeDir, "vue/components", `${filename}.vue`);
}
}
},
AutoImportComponents.raw(pluginOptions, meta)
];
}
const RELATIVE_IMPORT_RE = /^\.{1,2}\//;
function Bitrix24EnvironmentPlugin(options) {
const stubPath = resolvePathSync(options.inertia ? "../runtime/inertia/stubs" : "../runtime/vue/stubs", { extensions: [".ts", ".mjs", ".js"], url: import.meta.url });
return {
name: "bitrix24:b24ui",
enforce: "pre",
resolveId(id) {
if (id === "#imports") {
return stubPath;
}
},
transformInclude(id) {
return normalize(id).includes(runtimeDir);
},
transform(code) {
if (code.includes("import.meta.client")) {
const s = new MagicString(code);
s.replaceAll("import.meta.client", "true");
if (s.hasChanged()) {
return {
code: s.toString(),
map: s.generateMap({ hires: true })
};
}
}
}
};
}
function AutoImportPlugin(options, meta) {
const pluginOptions = defu(options.autoImport, {
dts: options.dts ?? true,
dirs: [join(runtimeDir, "composables"), join(runtimeDir, "vue/composables")]
});
return AutoImport.raw(pluginOptions, meta);
}
const runtimeDir = normalize(fileURLToPath(new URL("./runtime", import.meta.url)));
const Bitrix24UIPlugin = createUnplugin((_options = {}, meta) => {
const options = defu(_options, {}, defaultOptions);
const appConfig = defu({ b24ui: options.b24ui, colorMode: options.colorMode }, { b24ui: getDefaultUiConfig() });
return [
Bitrix24EnvironmentPlugin(options),
ComponentImportPlugin(options, meta),
AutoImportPlugin(options, meta),
tailwind(),
PluginsPlugin(options),
TemplatePlugin(options),
AppConfigPlugin(options, appConfig),
{
name: "bitrix24:b24ui:plugins-duplication-detection",
vite: {
configResolved(config) {
const plugins = config.plugins || [];
if (plugins.filter((i) => i.name === "unplugin-auto-import").length > 1) {
throw new Error("[Bitrix24 UI] Multiple instances of `unplugin-auto-import` detected. Bitrix24 UI includes `unplugin-auto-import` already, and you can configure it using `autoImport` option in Bitrix24 UI module options.");
}
if (plugins.filter((i) => i.name === "unplugin-vue-components").length > 1) {
throw new Error("[Bitrix24 UI] Multiple instances of `unplugin-vue-components` detected. Bitrix24 UI includes `unplugin-vue-components` already, and you can configure it using `components` option in Bitrix24 UI module options.");
}
}
}
}
].flat(1);
});
export { Bitrix24UIPlugin, runtimeDir };