Icônes : - Sidebar navItems : couleur distincte par section (iconStyle via data-binding) - Sidebar footer user : couleur primary - Navbar : logout → danger, soleil → amber, lune → blue - Panel widgets : œil visible → success, caché → muted Boutons : - `.neu-btn--sm:has(> i:only-child)` → carré 2rem×2rem automatiquement (theme, logout, mode édition) sans modifier le HTML Sidebar : - --sidebar-width-collapsed : 64px → 52px - Sidebar réduite : icônes centrées (justify-content center) Langue : - Setter vide sur `lang` dans navbar() pour corriger x-model avec getter (le @change gère la vraie mise à jour du store) Service Worker : - Enregistrement depuis /ws.sw.js (scope /) au lieu de /js/ws.sw.js (scope /js/) - build.mjs : copie ws.sw.js vers dist/ root en plus de dist/js/ LXC arrêté : - checkTarget() : skip si target.status !== 'running' → évite les 502 SSH Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
96 lines
2.7 KiB
JavaScript
96 lines
2.7 KiB
JavaScript
/**
|
|
* Build script for ProxmoxPanel Alpine frontend.
|
|
* - Bundles Swup into an IIFE (browser-loadable)
|
|
* - Bundles xterm.js + addon-fit into IIFEs
|
|
* - Copies all static assets to dist/
|
|
*/
|
|
|
|
import * as esbuild from 'esbuild'
|
|
import * as fs from 'fs'
|
|
import * as path from 'path'
|
|
|
|
const dist = 'dist'
|
|
|
|
// Clean dist
|
|
fs.rmSync(dist, { recursive: true, force: true })
|
|
fs.mkdirSync(`${dist}/js/vendors`, { recursive: true })
|
|
fs.mkdirSync(`${dist}/js`, { recursive: true })
|
|
fs.mkdirSync(`${dist}/css`, { recursive: true })
|
|
fs.mkdirSync(`${dist}/locales`, { recursive: true })
|
|
|
|
// 1. Bundle Swup into IIFE
|
|
console.log('Bundling Swup...')
|
|
await esbuild.build({
|
|
entryPoints: ['swup-bundle.entry.mjs'],
|
|
bundle: true,
|
|
format: 'iife',
|
|
globalName: '_swupExports',
|
|
outfile: `${dist}/js/vendors/swup.iife.js`,
|
|
minify: true,
|
|
})
|
|
// Expose Swup on window
|
|
const swupOut = fs.readFileSync(`${dist}/js/vendors/swup.iife.js`, 'utf8')
|
|
fs.writeFileSync(`${dist}/js/vendors/swup.iife.js`,
|
|
swupOut + '\nwindow.Swup=_swupExports.Swup;')
|
|
|
|
// 2. Bundle xterm.js
|
|
console.log('Bundling xterm...')
|
|
await esbuild.build({
|
|
entryPoints: ['xterm-bundle.entry.mjs'],
|
|
bundle: true,
|
|
format: 'iife',
|
|
globalName: '_xtermExports',
|
|
outfile: `${dist}/js/vendors/xterm.iife.js`,
|
|
minify: true,
|
|
})
|
|
const xtermOut = fs.readFileSync(`${dist}/js/vendors/xterm.iife.js`, 'utf8')
|
|
fs.writeFileSync(`${dist}/js/vendors/xterm.iife.js`,
|
|
xtermOut + '\nwindow.Terminal=_xtermExports.Terminal;window.FitAddon=_xtermExports.FitAddon;')
|
|
|
|
// xterm CSS
|
|
const xtermCss = 'node_modules/@xterm/xterm/css/xterm.css'
|
|
if (fs.existsSync(xtermCss)) {
|
|
fs.copyFileSync(xtermCss, `${dist}/css/xterm.css`)
|
|
}
|
|
|
|
// 3. Copy pre-downloaded vendors (Alpine, HTMX)
|
|
for (const f of ['alpine.min.js', 'htmx.min.js']) {
|
|
const src = `vendors/${f}`
|
|
if (fs.existsSync(src)) {
|
|
fs.copyFileSync(src, `${dist}/js/vendors/${f}`)
|
|
console.log(`Copied ${f}`)
|
|
} else {
|
|
console.warn(`WARN: ${src} not found`)
|
|
}
|
|
}
|
|
|
|
// 4. Copy app JS files
|
|
for (const f of fs.readdirSync('js')) {
|
|
if (f.endsWith('.js')) {
|
|
fs.mkdirSync(`${dist}/js`, { recursive: true })
|
|
fs.copyFileSync(`js/${f}`, `${dist}/js/${f}`)
|
|
}
|
|
}
|
|
// Service Worker doit être servi depuis la racine pour avoir le bon scope
|
|
if (fs.existsSync('js/ws.sw.js')) {
|
|
fs.copyFileSync('js/ws.sw.js', `${dist}/ws.sw.js`)
|
|
}
|
|
|
|
// 5. Copy CSS
|
|
for (const f of fs.readdirSync('css')) {
|
|
fs.copyFileSync(`css/${f}`, `${dist}/css/${f}`)
|
|
}
|
|
|
|
// 6. Copy locales
|
|
for (const f of fs.readdirSync('locales')) {
|
|
fs.copyFileSync(`locales/${f}`, `${dist}/locales/${f}`)
|
|
}
|
|
|
|
// 7. Copy HTML pages
|
|
for (const f of fs.readdirSync('.')) {
|
|
if (f.endsWith('.html')) {
|
|
fs.copyFileSync(f, `${dist}/${f}`)
|
|
}
|
|
}
|
|
|
|
console.log('✓ Build complete → dist/')
|