66 lines
2.5 KiB
JavaScript
66 lines
2.5 KiB
JavaScript
import { createHash } from 'node:crypto';
|
|
import {
|
|
copyFileSync,
|
|
existsSync,
|
|
mkdirSync,
|
|
readFileSync,
|
|
readdirSync,
|
|
writeFileSync
|
|
} from 'node:fs';
|
|
import path from 'node:path';
|
|
import { fileURLToPath } from 'node:url';
|
|
|
|
const frontendRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
|
const outputDirectory = path.join(frontendRoot, 'dist');
|
|
|
|
mkdirSync(outputDirectory, { recursive: true });
|
|
|
|
function copyEntry(source, destination) {
|
|
const entries = readdirSync(source, { withFileTypes: true });
|
|
mkdirSync(destination, { recursive: true });
|
|
for (const entry of entries) {
|
|
const sourcePath = path.join(source, entry.name);
|
|
const destinationPath = path.join(destination, entry.name);
|
|
if (entry.isDirectory()) {
|
|
copyEntry(sourcePath, destinationPath);
|
|
} else if (entry.isFile()) {
|
|
copyFileSync(sourcePath, destinationPath);
|
|
}
|
|
}
|
|
}
|
|
|
|
for (const entry of ['libs', 'favicon.ico']) {
|
|
const source = path.join(frontendRoot, entry);
|
|
if (existsSync(source)) {
|
|
const destination = path.join(outputDirectory, entry);
|
|
if (entry.includes('.')) {
|
|
copyFileSync(source, destination);
|
|
} else {
|
|
copyEntry(source, destination);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Vite hoists linked stylesheets into <head>, ahead of legacy inline styles in
|
|
// app.html. Re-emit the workspace layer after those styles so production and
|
|
// development use the same cascade order.
|
|
const workspaceSourcePath = path.join(frontendRoot, 'workspace.css');
|
|
const workspaceContents = readFileSync(workspaceSourcePath);
|
|
const workspaceHash = createHash('sha256').update(workspaceContents).digest('hex').slice(0, 12);
|
|
const workspaceFileName = `workspace-${workspaceHash}.css`;
|
|
copyFileSync(workspaceSourcePath, path.join(outputDirectory, workspaceFileName));
|
|
|
|
const builtAppPath = path.join(outputDirectory, 'app.html');
|
|
const builtAppHtml = readFileSync(builtAppPath, 'utf8');
|
|
const runtimeStylesheet = ` <link rel="stylesheet" href="/${workspaceFileName}" data-workspace-runtime>\n`;
|
|
const nextBuiltAppHtml = builtAppHtml.includes('data-workspace-runtime')
|
|
? builtAppHtml.replace(/\s*<link[^>]+data-workspace-runtime[^>]*>\s*/u, `\n${runtimeStylesheet}`)
|
|
: builtAppHtml.replace('</body>', `${runtimeStylesheet}</body>`);
|
|
|
|
if (!nextBuiltAppHtml.includes('data-workspace-runtime')) {
|
|
throw new Error('Unable to inject the runtime workspace stylesheet into dist/app.html');
|
|
}
|
|
|
|
writeFileSync(builtAppPath, nextBuiltAppHtml, 'utf8');
|
|
console.log(`Injected runtime workspace stylesheet: ${workspaceFileName}`);
|