mirror of
https://github.com/lobehub/lobehub.git
synced 2026-09-20 04:56:13 +08:00
1001a58a22
* ♻️ refactor(spa): extract verify/acceptance into apps/workbench Move the Workbench SPA into apps/workbench and serve /verify and /acceptance from that runtime for every web UA. The main SPA no longer registers those page routes, so they drop out of its bundle. * 🔧 chore(docker): wire the workbench workspace into image builds Copy apps/workbench/package.json before pnpm i so Docker can resolve the extracted SPA. Keep generateSpaTemplates optional for Cloud, and require the HTML only when WORKBENCH_REQUIRED=1 (build:docker). * ♻️ refactor(workbench): hard-navigate only from markdown entity links Keep Link and useWorkspaceAwareNavigate in-router. Markdown verify, acceptance, and mobile agent-doc links document-navigate. Drop the __WORKBENCH__ Vite define; Electron still skips hard-nav for portals. * ♻️ refactor(verify): slot-inject origin conversation and decouple shared components * 🐛 fix(i18n): make vite glob loaders independent of the vite root * ✨ feat(workbench): React Router framework mode SSR on Cloudflare Workers * 🐛 fix(verify): render viewer-timezone timestamps only after hydration * 💚 ci(workbench): deploy with affected detection and PR build verification * 📝 docs(skills): micro-app split and gateway routing playbook * 🐛 fix(workbench): track app/lib swallowed by the root lib/ ignore rules * ✨ feat(workbench): signed-in acceptance list sidebar on detail pages * 🐛 fix(workbench): survive shared-origin gateway quirks in client navigation * 💄 style(workbench): surface error detail on the boundary page * 💄 style(workbench): adopt the shared ErrorCapture page for the root boundary * 💄 style(verify): drop the app-home back arrow from the acceptance list panel * 🔧 chore(workbench): persist only error logs in wrangler observability * 📝 docs(skills): record Docker vs Cloud hosting for micro apps OSS Docker still builds and serves the SPA in-image. Cloud Next must not build, rewrite, or CDN-upload it — gateway routes to the Worker. * 💄 style(workbench): pin the acceptance logo while the list panel slides * 🐛 fix(workbench): only show the acceptance sidebar when signed in * 🐛 fix(verify): drop namespace prefix on bound verify translations
96 lines
3.1 KiB
HTML
96 lines
3.1 KiB
HTML
<!doctype html>
|
|
<html>
|
|
<head>
|
|
<meta charset="utf-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
<link rel="icon" href="/favicon.ico" />
|
|
<link rel="shortcut icon" href="/favicon-32x32.ico" />
|
|
<!--SEO_META-->
|
|
<style>
|
|
html body {
|
|
background: #f8f8f8;
|
|
}
|
|
html[data-theme='dark'] body {
|
|
background-color: #000;
|
|
}
|
|
</style>
|
|
<script>
|
|
(function () {
|
|
function supportsImportMaps() {
|
|
return (
|
|
typeof HTMLScriptElement !== 'undefined' &&
|
|
typeof HTMLScriptElement.supports === 'function' &&
|
|
HTMLScriptElement.supports('importmap')
|
|
);
|
|
}
|
|
|
|
function supportsCascadeLayers() {
|
|
var el = document.createElement('div');
|
|
el.className = '__layer_test__';
|
|
el.style.position = 'absolute';
|
|
el.style.left = '-99999px';
|
|
el.style.top = '-99999px';
|
|
|
|
var style = document.createElement('style');
|
|
style.textContent =
|
|
'@layer a, b;' +
|
|
'@layer a { .__layer_test__ { color: rgb(1, 2, 3); } }' +
|
|
'@layer b { .__layer_test__ { color: rgb(4, 5, 6); } }';
|
|
|
|
document.documentElement.append(style);
|
|
document.documentElement.append(el);
|
|
|
|
var color = getComputedStyle(el).color;
|
|
|
|
el.remove();
|
|
style.remove();
|
|
|
|
return color === 'rgb(4, 5, 6)';
|
|
}
|
|
|
|
if (!(supportsImportMaps() && supportsCascadeLayers())) {
|
|
window.location.href = '/not-compatible.html';
|
|
return;
|
|
}
|
|
|
|
var theme = 'system';
|
|
try {
|
|
theme = localStorage.getItem('theme') || 'system';
|
|
} catch (_) {}
|
|
var systemTheme =
|
|
window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches
|
|
? 'dark'
|
|
: 'light';
|
|
var resolvedTheme = theme === 'system' ? systemTheme : theme;
|
|
if (resolvedTheme === 'dark' || resolvedTheme === 'light') {
|
|
document.documentElement.setAttribute('data-theme', resolvedTheme);
|
|
}
|
|
|
|
var hl = new URLSearchParams(location.search).get('hl');
|
|
var m = document.cookie.match(/(?:^|;\s*)LOBE_LOCALE=([^;]*)/);
|
|
var cookie = m ? decodeURIComponent(m[1]) : '';
|
|
var locale = hl || cookie || navigator.language || 'en-US';
|
|
if (locale === 'auto') locale = navigator.language || 'en-US';
|
|
if (hl && !cookie) {
|
|
document.cookie =
|
|
'LOBE_LOCALE=' + encodeURIComponent(hl) + ';path=/;max-age=7776000;SameSite=Lax';
|
|
}
|
|
document.documentElement.lang = locale;
|
|
var rtl = ['ar', 'arc', 'dv', 'fa', 'ha', 'he', 'khw', 'ks', 'ku', 'ps', 'ur', 'yi'];
|
|
document.documentElement.dir =
|
|
rtl.indexOf(locale.split('-')[0].toLowerCase()) >= 0 ? 'rtl' : 'ltr';
|
|
})();
|
|
</script>
|
|
<script>
|
|
window.__SERVER_CONFIG__ = undefined; /* SERVER_CONFIG */
|
|
</script>
|
|
</head>
|
|
|
|
<body>
|
|
<div id="root" style="height: 100%"></div>
|
|
|
|
<!--ANALYTICS_SCRIPTS-->
|
|
<script type="module" src="/apps/workbench/src/entry.tsx"></script>
|
|
</body>
|
|
</html>
|