mirror of
https://github.com/R0m1k3/Loki.git
synced 2026-10-11 17:26:57 +02:00
UI: assemblage via tools/assemble-ui (Go, multiplateforme) branche sur go generate - remplace ui/assemble.ps1
This commit is contained in:
1 parent
b4b30cd47a
commit
d5e0606dcc
6 files changed
+84
-33
No files matched your search
@@ -302,7 +302,7 @@ GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -o jean-linux-amd64 ./cmd/jean
|
||||
|
||||
- `cmd/jean/` — point d'entrée (`main()`) + ressources Windows (.syso, icône, versioninfo).
|
||||
- `internal/jean/` — tout le code, fichiers préfixés par domaine (`web_*`, `chat_*`, `llm_*`, `backend_*`, `relay_*`, `sys_*` — carte dans `doc.go`).
|
||||
- `internal/jean/ui/` — UI web embarquée. `index.html` est **généré** : les sources vivent dans `ui/src/` (`styles.css`, `js/NN-*.js` concaténés dans l'ordre alphabétique, `index.tmpl.html`). Pour modifier l'UI : éditer `ui/src/` puis lancer `ui/assemble.ps1` (le fichier assemblé reste committé car `go:embed` et `ajean-app/build-server-ui.ps1` le lisent tel quel).
|
||||
- `internal/jean/ui/` — UI web embarquée. `index.html` est **généré** : les sources vivent dans `ui/src/` (`styles.css`, `js/NN-*.js` concaténés dans l'ordre alphabétique, `index.tmpl.html`). Pour modifier l'UI : éditer `ui/src/` puis lancer `go generate ./internal/jean` (outil `tools/assemble-ui`, multiplateforme ; le fichier assemblé reste committé car `go:embed` et `ajean-app/build-server-ui.ps1` le lisent tel quel).
|
||||
|
||||
## Licence
|
||||
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
# assemble.ps1 — reconstruit ui/index.html à partir des sources ui/src/.
|
||||
#
|
||||
# ui/index.html est un fichier GÉNÉRÉ (mais committé : go:embed et
|
||||
# ajean-app/build-server-ui.ps1 le lisent tel quel). Pour modifier l'UI :
|
||||
# éditer ui/src/ (styles.css, js/NN-*.js, index.tmpl.html) puis relancer ce
|
||||
# script. Les js/ sont concaténés dans l'ordre alphabétique (préfixes NN-),
|
||||
# tout reste en scope global comme avant le découpage.
|
||||
#
|
||||
# Tout est manipulé en octets bruts (fins de ligne/encodage préservés).
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$here = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||
$src = Join-Path $here 'src'
|
||||
$dst = Join-Path $here 'index.html'
|
||||
|
||||
$tmpl = [IO.File]::ReadAllText((Join-Path $src 'index.tmpl.html'))
|
||||
$css = [IO.File]::ReadAllText((Join-Path $src 'styles.css'))
|
||||
$js = (Get-ChildItem (Join-Path $src 'js') -Filter '*.js' | Sort-Object Name |
|
||||
ForEach-Object { [IO.File]::ReadAllText($_.FullName) }) -join ''
|
||||
|
||||
# le marqueur et SA fin de ligne sont remplacés (LF ou CRLF selon le checkout) ;
|
||||
# chaque source apporte ses propres fins de ligne → sortie byte-stable.
|
||||
foreach ($m in '@@CSS@@', '@@JS@@') {
|
||||
if ($tmpl -notmatch "$m`r?`n") { throw "marqueur $m introuvable dans index.tmpl.html" }
|
||||
}
|
||||
$html = [regex]::Replace($tmpl, "@@CSS@@`r?`n", { $css })
|
||||
$html = [regex]::Replace($html, "@@JS@@`r?`n", { $js })
|
||||
|
||||
[IO.File]::WriteAllText($dst, $html, [Text.UTF8Encoding]::new($false))
|
||||
Write-Host "OK -> $dst ($([IO.File]::ReadAllBytes($dst).Length) octets)"
|
||||
@@ -1,5 +1,5 @@
|
||||
<!doctype html>
|
||||
<!-- GÉNÉRÉ par ui/assemble.ps1 depuis ui/src/ — NE PAS ÉDITER index.html DIRECTEMENT -->
|
||||
<!-- GÉNÉRÉ depuis ui/src/ par tools/assemble-ui (go generate ./internal/jean) — NE PAS ÉDITER index.html DIRECTEMENT -->
|
||||
<html lang="fr"><head>
|
||||
<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover">
|
||||
<!-- PWA standalone : "Ajouter à l'écran d'accueil" sur iPhone → app plein écran
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!doctype html>
|
||||
<!-- GÉNÉRÉ par ui/assemble.ps1 depuis ui/src/ — NE PAS ÉDITER index.html DIRECTEMENT -->
|
||||
<!-- GÉNÉRÉ depuis ui/src/ par tools/assemble-ui (go generate ./internal/jean) — NE PAS ÉDITER index.html DIRECTEMENT -->
|
||||
<html lang="fr"><head>
|
||||
<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover">
|
||||
<!-- PWA standalone : "Ajouter à l'écran d'accueil" sur iPhone → app plein écran
|
||||
|
||||
@@ -16,6 +16,7 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
//go:generate go run ../../tools/assemble-ui ui
|
||||
//go:embed ui/index.html ui/marked.min.js
|
||||
var uiFS embed.FS
|
||||
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
// assemble-ui reconstruit internal/jean/ui/index.html à partir des sources
|
||||
// internal/jean/ui/src/ (remplace l'ancien ui/assemble.ps1 — multiplateforme).
|
||||
//
|
||||
// index.html est un fichier GÉNÉRÉ mais committé : go:embed (web_server.go) et
|
||||
// ajean-app/build-server-ui.ps1 le lisent tel quel. Pour modifier l'UI : éditer
|
||||
// ui/src/ (index.tmpl.html, styles.css, js/NN-*.js concaténés dans l'ordre
|
||||
// alphabétique, tout en scope global) puis relancer :
|
||||
//
|
||||
// go generate ./internal/jean (ou : go run ./tools/assemble-ui)
|
||||
//
|
||||
// Les marqueurs @@CSS@@ / @@JS@@ du template sont remplacés avec LEUR fin de
|
||||
// ligne (LF ou CRLF) ; chaque source apporte ses propres fins de ligne.
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func main() {
|
||||
uiDir := "internal/jean/ui"
|
||||
if len(os.Args) > 1 {
|
||||
uiDir = os.Args[1]
|
||||
}
|
||||
if err := run(uiDir); err != nil {
|
||||
fmt.Fprintln(os.Stderr, "assemble-ui:", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func run(uiDir string) error {
|
||||
srcDir := filepath.Join(uiDir, "src")
|
||||
tmpl, err := os.ReadFile(filepath.Join(srcDir, "index.tmpl.html"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
css, err := os.ReadFile(filepath.Join(srcDir, "styles.css"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
entries, err := os.ReadDir(filepath.Join(srcDir, "js"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var names []string
|
||||
for _, e := range entries {
|
||||
if strings.HasSuffix(e.Name(), ".js") {
|
||||
names = append(names, e.Name())
|
||||
}
|
||||
}
|
||||
sort.Strings(names)
|
||||
var js []byte
|
||||
for _, n := range names {
|
||||
b, err := os.ReadFile(filepath.Join(srcDir, "js", n))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
js = append(js, b...)
|
||||
}
|
||||
|
||||
html := string(tmpl)
|
||||
for marker, content := range map[string]string{"@@CSS@@": string(css), "@@JS@@": string(js)} {
|
||||
re := regexp.MustCompile(regexp.QuoteMeta(marker) + "\r?\n")
|
||||
if !re.MatchString(html) {
|
||||
return fmt.Errorf("marqueur %s introuvable dans index.tmpl.html", marker)
|
||||
}
|
||||
html = re.ReplaceAllStringFunc(html, func(string) string { return content })
|
||||
}
|
||||
|
||||
dst := filepath.Join(uiDir, "index.html")
|
||||
if err := os.WriteFile(dst, []byte(html), 0o644); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Printf("OK -> %s (%d octets)\n", dst, len(html))
|
||||
return nil
|
||||
}
|
||||
Reference in new issue
Block a user