feat(ui): render every application template except the loading screen as a Vue view

The scene chrome, cockpit, Display controls, command dock, layer panels,
Context rail, welcome card and Provider Settings move verbatim into
src/ui/views and mount into their hosts before the page is translated and
wired. Each view renders the same elements, attributes and text as its
template; Vue keeps whitespace between elements as one space, and no view
markup sits under a white-space: pre rule.

Template asset URLs stay literal, view files are left out of Prettier so
the markup is not reflowed, and the Node component loader moves to build/
and is exported as build/register-vue for host test runners. Hosts that do
not initialize Core's locale pass localePicker: false instead of editing
the markup.
This commit is contained in:
Sameh Khamis committed 2026-10-30 17:47:52 -07:00
1 parent 9d24945143
commit 6802c9c8b0
46 files changed
+258 -97

No files matched your search

+5 -4
View File
@@ -20,13 +20,14 @@ export async function renderApplicationHtml(html) {
const view = APPLICATION_VIEWS[name];
if (!view) throw new Error(`Unknown application view: ${name}`);
const markup = (await renderToString(createSSRApp(view).use(createPinia())))
// Hydration markers and empty-attribute values are SSR detail; the
// DOM is the same as the template's.
// Hydration markers, empty-attribute values and escaped apostrophes
// are SSR detail; the DOM is the same as the template's.
.replace(/<!--\[-->|<!--\]-->|<!---->/g, '')
.replace(/ ([\w:.-]+)=""/g, ' $1');
.replace(/ ([\w:.-]+)=""/g, ' $1')
.replaceAll('&#39;', "'");
output = output.replace(
host,
`<div class="gev-view" data-gev-view="${name}">${markup}</div>`,
() => `<div class="gev-view" data-gev-view="${name}">${markup}</div>`,
);
}
return output;
-4
View File
@@ -1,4 +0,0 @@
import { register } from 'node:module';
// Lets unit tests import single-file components (`node --import`).
register('./vueLoader.mjs', import.meta.url);
-48
View File
@@ -1,48 +0,0 @@
import { readFile } from 'node:fs/promises';
import { fileURLToPath } from 'node:url';
import { compileScript, compileTemplate, parse } from 'vue/compiler-sfc';
import { VUE_COMPILER_OPTIONS } from '../../build/vueOptions.js';
/**
* Compile a single-file component to an ES module for Node's test runner.
* Styles are dropped: tests read the global stylesheet separately.
*/
export function compileVueModule(source, filename) {
const { descriptor, errors } = parse(source, { filename });
if (errors.length) throw errors[0];
const id = filename;
if (descriptor.scriptSetup) {
return compileScript(descriptor, {
id,
inlineTemplate: true,
templateOptions: { compilerOptions: VUE_COMPILER_OPTIONS },
}).content;
}
const script = descriptor.script
? compileScript(descriptor, { id, genDefaultAs: '__sfc__' }).content
: 'const __sfc__ = {};';
let template = '';
if (descriptor.template) {
const compiled = compileTemplate({
source: descriptor.template.content,
filename,
id,
compilerOptions: VUE_COMPILER_OPTIONS,
});
if (compiled.errors.length) throw compiled.errors[0];
template = compiled.code;
}
return `${script}\n${template}\nif (typeof render === 'function') __sfc__.render = render;\nexport default __sfc__;\n`;
}
/** Node module hook: load `.vue` files as compiled modules. */
export async function load(url, context, nextLoad) {
if (!url.endsWith('.vue')) return nextLoad(url, context);
const filename = fileURLToPath(url);
const source = await readFile(filename, 'utf8');
return {
format: 'module',
source: compileVueModule(source, filename),
shortCircuit: true,
};
}