feat(ui): render application templates as Vue views mounted before wiring

Templates listed in build/applicationViews.js expand to mount hosts, and
mountApplicationViews() renders them before translation and wiring. Markup
tests read the page through a server-side render helper, the i18n scanner
reads view templates, and Vue preserves whitespace so views keep the exact
DOM. No template is converted yet.
This commit is contained in:
Sameh Khamis committed 2026-10-30 17:23:45 -07:00
1 parent b7e7058a5c
commit 9d24945143
32 files changed
+243 -63

No files matched your search

+12
View File
@@ -1,4 +1,5 @@
import { readFileSync } from 'node:fs';
import { APPLICATION_VIEW_NAMES } from './applicationViews.js';
export const APPLICATION_TEMPLATES = Object.freeze([
'scene-chrome',
@@ -12,6 +13,16 @@ export const APPLICATION_TEMPLATES = Object.freeze([
'hud-loading',
]);
const allowed = new Set(APPLICATION_TEMPLATES);
const views = new Set(APPLICATION_VIEW_NAMES);
/**
* The element a Vue view renders into. `display: contents` keeps the view's
* own elements laid out as children of the page.
* @param {string} name Application template name.
*/
export function applicationViewHost(name) {
return `<div class="gev-view" data-gev-view="${name}"></div>\n`;
}
/** Expand only known component templates; markers cannot name filesystem paths. */
export function expandApplicationHtml(html) {
@@ -20,6 +31,7 @@ export function expandApplicationHtml(html) {
(_, name) => {
if (!allowed.has(name))
throw new Error(`Unknown application template: ${name}`);
if (views.has(name)) return applicationViewHost(name);
return readFileSync(
new URL(`../src/ui/templates/${name}.html`, import.meta.url),
'utf8',
+7
View File
@@ -0,0 +1,7 @@
/**
* Application templates that are now Vue views (src/ui/views). Their markers
* expand to a mount host instead of static markup, and
* `mountApplicationViews()` renders them before the page is wired. The
* loading screen stays static so it paints before any script runs.
*/
export const APPLICATION_VIEW_NAMES = Object.freeze([]);
+2 -1
View File
@@ -2,6 +2,7 @@ import { fileURLToPath } from 'node:url';
import { applicationHtmlPlugin } from './application-html.js';
import cesium from 'vite-plugin-cesium';
import vue from '@vitejs/plugin-vue';
import { VUE_PLUGIN_OPTIONS } from './vueOptions.js';
import { DEFAULT_ALLOWED_HOSTS, hostCheckPlugin } from './allowedHosts.js';
import { embedFramingPlugin } from './embed-framing.js';
import { panelBuildPlugin } from './panel.js';
@@ -158,7 +159,7 @@ export function createBrowserViteConfig({
cesium(),
applicationHtmlPlugin(),
// Application views are Vue single-file components.
vue(),
vue(VUE_PLUGIN_OPTIONS),
...plugins,
embedFramingPlugin(),
panelBuildPlugin(),
+11
View File
@@ -0,0 +1,11 @@
/**
* Template compiler options shared by the browser build, the boundary check
* and the unit-test loader. Whitespace is preserved so a view renders exactly
* the DOM its static markup did: inline layouts depend on text between nodes.
*/
export const VUE_COMPILER_OPTIONS = Object.freeze({ whitespace: 'preserve' });
/** `@vitejs/plugin-vue` options for application builds. */
export const VUE_PLUGIN_OPTIONS = Object.freeze({
template: { compilerOptions: VUE_COMPILER_OPTIONS },
});