velund
Version:
Модульная UI-система на Vite для полиглотных бэкендов
98 lines (95 loc) • 3.34 kB
JavaScript
import path from 'path';
import { pathToFileURL } from 'url';
import * as fs from 'fs';
import fg from 'fast-glob';
const buildPlugin = (opts, generator, extensions) => {
const assetSet = /* @__PURE__ */ new Set();
let rollupInput;
let outDir;
return {
configResolved(config) {
rollupInput = path.resolve(
config?.build?.rollupOptions?.input === "index.html" ? "./src/main.ts" : config?.build?.rollupOptions?.input?.toString() || "./src/main.ts"
).toString().replace(/\\/g, "/");
outDir = path.resolve(config.build?.outDir);
path.resolve(config.build?.assetsDir);
},
// Сбор ассетов
async buildStart() {
if (this.meta?.watchMode) return;
const templatesGlob = [
"./**/*.vel.ts",
"./**/*.vel.js",
...extensions.map((ext) => `./**/*${ext}`)
];
const files = await fg(templatesGlob, { absolute: true });
const assetsToEmit = /* @__PURE__ */ new Set();
for (const file of files) {
const content = fs.readFileSync(file, "utf-8");
const regex = /@\/([^\s"'<>]+)/g;
let match;
while ((match = regex.exec(content)) !== null) {
assetsToEmit.add(match[1]);
}
}
assetsToEmit.forEach((_, relPath) => {
const absPath = path.join("./src", relPath);
if (!fs.existsSync(absPath)) {
console.warn(`[vite-plugin-twig] Asset not found: ${relPath}`);
return;
}
const ext = path.extname(relPath);
this.emitFile({
type: "chunk",
id: path.resolve(absPath),
name: path.basename(relPath, ext)
});
assetSet.add("src/" + relPath);
});
},
// Генерация PHP библиотеки
async writeBundle(options, bundle) {
const mainFile = Object.values(bundle).find(
(f) => f.type === "chunk" && f.isEntry && f.facadeModuleId == rollupInput
);
if (!mainFile) {
console.warn("Main entry not found in bundle");
return;
}
const mainPath = path.resolve(
options.dir || process.cwd(),
mainFile.fileName
);
await import(pathToFileURL(mainPath).href);
const components = globalThis.__APP__.components || [];
const finalAssetMap = {};
for (const fileName in bundle) {
const b = bundle[fileName];
if ((b.type === "asset" || b.type === "chunk") && (b.originalFileName || b.facadeModuleId)) {
const originalFileName = b.originalFileName || b.facadeModuleId.replace(
path.resolve("./").replace(/\\/g, "/") + "/",
""
);
if (assetSet.has(originalFileName)) {
finalAssetMap[originalFileName.replace("src/", "@/")] = b.fileName;
}
}
}
components.forEach((tpl) => {
let updated = tpl.template;
Object.entries(finalAssetMap).forEach(([origPath, finalPath]) => {
updated = updated.split(origPath).join(
path.join(opts.assetsUrl, finalPath.replace("assets/", "./")).replace(/\\/g, "/")
);
});
tpl.template = updated;
});
await generator.generate(
opts.renderer,
components,
path.join(outDir, "/lib")
);
}
};
};
export { buildPlugin as default };