feat(client): includi librerie e font in locale per il funzionamento offline

Punto 12 del documento modifiche del 28/07. L'installazione a Trafilo e'
on-premise su rete di produzione isolata: finche' Alpine.js, Plotly, PDF.js,
Fabric.js e i Google Fonts venivano scaricati da CDN a ogni apertura di pagina,
senza internet l'interfaccia non partiva affatto (Alpine governa tutta la UI).

Le librerie passano in static/vendor/ con la versione nel nome del file, e la
CSP del backend si chiude a solo-origine. Il worker di PDF.js e' ripuntato in
tutti e quattro i template che lo usano: ripuntando solo lo script principale la
libreria si carica in locale ma il worker continua a cercare internet, e sembra
funzionare finche' non si apre un disegno.

Alpine e' pinnato a 3.15.12, cioe' la versione a cui "3.x.x" risolveva oggi: il
congelamento non cambia il comportamento di quanto e' gia' in esercizio, e toglie
il fatto che l'applicazione cambiasse da sola a ogni rilascio degli autori -
rilevante per le evidenze ISO 9001 / IATF 16949.

Inter e JetBrains Mono sono font variabili: un solo woff2 per subset copre tutti
i pesi, dove Google serviva lo stesso file sotto otto URL. Tenuti i soli subset
latin e latin-ext, che coprono per intero italiano e inglese.

Provenienza, versioni e impronte SHA-256 in static/vendor/VERSIONS.md.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Adriano Dal Pastro
2026-07-28 15:41:57 +00:00
parent 2a566321f3
commit 28ee44bcf1
18 changed files with 201 additions and 22 deletions
+77
View File
@@ -0,0 +1,77 @@
# Librerie di terze parti — copie locali
Queste copie servono al **punto 12** del documento delle modifiche: l'installazione a
Tràfilo è on-premise, su rete di produzione isolata. Finché queste librerie venivano
scaricate da CDN a ogni apertura di pagina, senza internet l'interfaccia non partiva
affatto (Alpine.js governa tutta la UI).
Secondo effetto, non meno importante: le versioni sono **congelate**. Prima Alpine.js
era agganciato a `alpinejs@3.x.x`, cioè l'applicazione cambiava da sola a ogni rilascio
degli autori, senza validazione. Per un sistema che produce evidenze per audit
ISO 9001 / IATF 16949 questo è di per sé un difetto.
Scaricate il **28 luglio 2026**.
## JavaScript
| File | Versione | Origine |
|---|---|---|
| `alpinejs-3.15.12.min.js` | 3.15.12 | `https://cdn.jsdelivr.net/npm/alpinejs@3.15.12/dist/cdn.min.js` |
| `plotly-2.32.0.min.js` | 2.32.0 | `https://cdn.plot.ly/plotly-2.32.0.min.js` |
| `pdf-3.11.174.min.js` | 3.11.174 | `https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.min.js` |
| `pdf.worker-3.11.174.min.js` | 3.11.174 | `https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.worker.min.js` |
| `fabric-5.3.1.min.js` | 5.3.1 | `https://cdnjs.cloudflare.com/ajax/libs/fabric.js/5.3.1/fabric.min.js` |
La versione di Alpine è quella a cui `3.x.x` risolveva il giorno del congelamento:
il pin non cambia il comportamento rispetto a quanto già in esercizio.
`pdf.worker` è un file a sé che PDF.js carica **a runtime** via
`pdfjsLib.GlobalWorkerOptions.workerSrc`. Va ripuntato in tutti i template che usano
PDF.js, non basta lo script principale: altrimenti la libreria si carica in locale e il
worker continua a cercare internet — sembra funzionare finché non si apre un disegno.
## Font
`fonts.css` sostituisce il `<link>` a `fonts.googleapis.com` in `base.html`.
| File | Famiglia | Subset |
|---|---|---|
| `fonts/inter-latin.woff2` | Inter | latin |
| `fonts/inter-latin-ext.woff2` | Inter | latin-ext |
| `fonts/jetbrains-mono-latin.woff2` | JetBrains Mono | latin |
| `fonts/jetbrains-mono-latin-ext.woff2` | JetBrains Mono | latin-ext |
Entrambe le famiglie sono **font variabili** (asse `wght`: Inter 100900, JetBrains Mono
400800): un solo file per subset copre tutti i pesi usati dall'interfaccia. Google
serviva lo stesso woff2 sotto otto URL diversi, uno per peso dichiarato.
Tenuti i soli subset **latin** e **latin-ext**, che coprono per intero italiano e
inglese. Per gli altri alfabeti il browser ricade sul font di sistema — scelta
consapevole: cirillico, greco e vietnamita valevano 600 KB di peso morto.
## Impronte SHA-256
```
57b37d7cae9a27d965fdae4adcc844245dfdc407e655aee85dcfff3a08036a3f alpinejs-3.15.12.min.js
bb0442d69a4d4673320f689bc6e16c05a0e3f16ccfbf551f394d90a7e7cfc772 fabric-5.3.1.min.js
5b5799e6f8c680663207ac5b42ee14eed2a406fa7af48f50c154f0c0b1566946 pdf-3.11.174.min.js
feabdf309770ed24bba31a5467836cdc8cf639c705af27d52b585b041bb8527b pdf.worker-3.11.174.min.js
0a17719a72751704861215da0e5c5cdb3f9a8d50eff5cb84cb6f8b80786682b0 plotly-2.32.0.min.js
34b9c504cab7a73e37b746343a449132e56cf7b5481af2cb81dc74dcff25c956 fonts/inter-latin-ext.woff2
3100e775e8616cd2611beecfa23a4263d7037586789b43f035236a2e6fbd4c62 fonts/inter-latin.woff2
db5ff4db83e580426280e9337a58dc57d3a83784a1b03ad80914651594441d52 fonts/jetbrains-mono-latin-ext.woff2
83c005d49d8a6a50474c73a5a36ac0468076e9c4a29da7bdb14995d80560a5be fonts/jetbrains-mono-latin.woff2
```
Verifica: `sha256sum -c` da questa cartella, oppure
`sha256sum *.js fonts/*.woff2`.
## Aggiornare una libreria
1. Scaricare la nuova versione con il nome comprensivo di versione.
2. Ripuntare i `<script>`/`<link>` nei template (`grep -rn vendor/ ../../templates/`).
3. Aggiornare questa tabella e le impronte.
4. Rimuovere il file vecchio.
Il nome del file porta la versione apposta: un aggiornamento non passa inosservato in
revisione, e la modifica resta tracciata in git.
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+44
View File
@@ -0,0 +1,44 @@
/* Inter + JetBrains Mono self-hosted — subset latin + latin-ext, font variabili.
Sostituisce il <link> a fonts.googleapis.com: l'app deve partire a rete staccata
(punto 12). Un solo woff2 per subset copre tutti i pesi via asse wght.
Provenienza e hash dei file: vendor/VERSIONS.md */
/* latin */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 100 900;
font-display: swap;
src: url(fonts/inter-latin.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* latin-ext */
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 100 900;
font-display: swap;
src: url(fonts/inter-latin-ext.woff2) format('woff2');
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
font-family: 'JetBrains Mono';
font-style: normal;
font-weight: 400 800;
font-display: swap;
src: url(fonts/jetbrains-mono-latin.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* latin-ext */
@font-face {
font-family: 'JetBrains Mono';
font-style: normal;
font-weight: 400 800;
font-display: swap;
src: url(fonts/jetbrains-mono-latin-ext.woff2) format('woff2');
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long