docs: add logo, README, architecture, deploy, wiki, analysis
This commit is contained in:
1 parent
32245f76ac
commit
15eb4016de
9 files changed
+561
-1
No files matched your search
@@ -0,0 +1,98 @@
|
||||
# Analisi Completa del Progetto Bookish
|
||||
|
||||
## 1. Analisi del Codice
|
||||
|
||||
### Qualità Generale
|
||||
- **Leggibilità**: Buona. Codice Python pulito con nomi descrittivi. JS ben strutturato.
|
||||
- **Manutenibilità**: Alta. Modulare (routes/services/static). Ogni file ha una responsabilità chiara.
|
||||
- **Type Safety**: Assente (Python). JS è vanilla senza TypeScript. Accettabile per un progetto personale.
|
||||
|
||||
### Punti di Forza
|
||||
- App factory pattern Flask (creazione configurabile)
|
||||
- SSE nativo senza dipendenze esterne
|
||||
- Thread-safe SSE manager con lock
|
||||
- Pulizia automatica file temporanei
|
||||
- Secure filename e path sanitization
|
||||
- Fallback ricerche porta libera
|
||||
- Formati validati dinamicamente lato server + client
|
||||
|
||||
### Punti di Debolezza
|
||||
- **Nessun logging**: Manca logging strutturato per debug
|
||||
- **Error handling**: Le eccezioni in conversion thread vengono catturate ma non loggate
|
||||
- **Nessun rate limiting**: Upload illimitati (accettabile per uso singolo)
|
||||
- **CSS in unico file**: Diventerà grande con l'aggiunta di feature
|
||||
- **Reader JS monolitico**: `reader.js` gestisce EPUB, PDF e testo in un unico file (può essere suddiviso)
|
||||
- **Nessun test**: Il progetto non ha test automatici
|
||||
- **Markdown renderer**: Il simpleMarkdownToHtml è minimale (non gestisce code block, elenchi annidati, tabelle)
|
||||
|
||||
### Pattern e Convenzioni
|
||||
- Flask Blueprints per separazione route
|
||||
- Template Jinja2 con estensione base
|
||||
- JS in IIFE (Immediately Invoked Function Expression) per isolamento scope
|
||||
- CSS organizzato per sezioni (navbar, converter, reader)
|
||||
- Config centralizzata in config.py
|
||||
|
||||
## 2. Analisi della Sicurezza
|
||||
|
||||
| Asse | Valutazione | Note |
|
||||
|---|---|---|
|
||||
| Path traversal | ✅ Protetto | `os.path.basename()` + `secure_filename()` |
|
||||
| Upload dimensioni | ✅ Limitato | MAX_CONTENT_LENGTH = 50MB |
|
||||
| XSS (templates) | ✅ Protetto | Jinja2 auto-escape |
|
||||
| XSS (reader) | ⚠️ Parziale | HTML renderizzato direttamente nel text viewer |
|
||||
| Command injection | ✅ Safe | Pandoc chiamato via libreria, non shell |
|
||||
| Secret key | ✅ Config | Tramite env var BOOKISH_SECRET |
|
||||
| CSRF | ⚠️ Assente | Nessun token CSRF sui form (uso personale) |
|
||||
| Autenticazione | ⚠️ Assente | Volutamente, uso singolo utente |
|
||||
|
||||
## 3. Analisi Performance
|
||||
|
||||
- **Conversione**: Pandoc è veloce (ebook < 1 secondo). PDF via WeasyPrint può richiedere qualche secondo.
|
||||
- **Thread**: Ogni conversione è un thread separato. Per uso singolo non ci sono problemi.
|
||||
- **SSE**: Connessione keep-alive leggera, ~300 bytes ogni 300ms.
|
||||
- **Reader**: epub.js rende tutto lato client. File EPUB fino a 50MB senza problemi.
|
||||
- **Memoria**: L'app in idle usa ~50MB. Durante conversione PDF ~150MB (WeasyPrint).
|
||||
|
||||
## 4. Analisi Modularità
|
||||
|
||||
```
|
||||
bookish/
|
||||
├── routes/ ⬅️ Separati per dominio (convert vs reader)
|
||||
│ ├── convert.py
|
||||
│ └── reader.py
|
||||
├── services/ ⬅️ Logica di business isolata dal routing
|
||||
│ ├── converter.py
|
||||
│ ├── sse_manager.py
|
||||
│ └── formatter.py
|
||||
├── templates/ ⬅️ HTML separato per pagina
|
||||
├── static/ ⬅️ CSS, JS, immagini
|
||||
│ ├── css/
|
||||
│ ├── js/
|
||||
│ └── lib/
|
||||
```
|
||||
|
||||
La separazione è chiara. Unica nota: `converter.py` importa `formatter.py` — dipendenza circolare potenziale ma gestita con import differito.
|
||||
|
||||
## 5. Possibili Miglioramenti
|
||||
|
||||
### Breve termine
|
||||
- [ ] Aggiungere logging strutturato (Python logging + file di log)
|
||||
- [ ] Migliorare il renderer Markdown nel reader (usare marked.js via CDN)
|
||||
- [ ] Aggiungere favicon diversa per stato conversione
|
||||
- [ ] Test di base con pytest
|
||||
|
||||
### Medio termine
|
||||
- [ ] Supporto per code block syntax highlighting nel reader
|
||||
- [ ] Drag&drop anche nella pagina reader per caricamento diretto
|
||||
- [ ] Modalità notte persistente con preferenza sistema (prefers-color-scheme)
|
||||
- [ ] Aggiungere pipeline di CI/CD per test
|
||||
|
||||
### Lungo termine
|
||||
- [ ] Supporto multi-utente con autenticazione
|
||||
- [ ] Libreria personale con cronologia conversioni (SQLite)
|
||||
- [ ] Plugin system per engine di conversione custom
|
||||
- [ ] Mobile app via PWA
|
||||
|
||||
## 6. Conclusioni
|
||||
|
||||
Bookish è un'applicazione solida per il suo scopo. L'architettura è pulita, la separazione delle responsabilità è corretta, e le scelte tecnologiche sono appropriate per un progetto self-hostato a uso singolo. Le aree di miglioramento principali sono logging, testing e completezza del reader markdown.
|
||||
@@ -0,0 +1,114 @@
|
||||
# Architettura di Bookish
|
||||
|
||||
## Panoramica
|
||||
|
||||
Bookish è un'applicazione web Flask monolitica progettata per l'uso self-hostato. Si compone di due macro-funzionalità: un **convertitore di formati ebook** e un **reader web** per visualizzarli.
|
||||
|
||||
```
|
||||
┌──────────┐ ┌─────────────────────────────────────┐
|
||||
│ Browser │────▶│ Flask │
|
||||
│ │ │ ┌─────────┐ ┌──────────────────┐ │
|
||||
│ HTML/CSS │ │ │ Routes │ │ Services │ │
|
||||
│ JS/ES │ │ │ │ │ │ │
|
||||
│ │ │ │convert │─▶│converter.py │──▶│ Pandoc
|
||||
│epub.js │ │ │reader │ │sse_manager.py │ │ WeasyPrint
|
||||
│pdf.js │ │ │ │ │formatter.py │ │ python-docx
|
||||
└──────────┘ │ └─────────┘ └──────────────────┘ │
|
||||
└─────────────────────────────────────┘
|
||||
│ │
|
||||
uploads/ converted/
|
||||
(temporaneo) (temporaneo)
|
||||
```
|
||||
|
||||
## Stack Tecnologico
|
||||
|
||||
| Componente | Tecnologia | Ruolo |
|
||||
|---|---|---|
|
||||
| Backend | Flask 3.x + Jinja2 | Server web, routing, template engine |
|
||||
| Conversione | Pandoc 3.x (via pypandoc) | Motore di conversione principale |
|
||||
| PDF avanzato | WeasyPrint | PDF con layout precisi da HTML |
|
||||
| DOCX avanzato | python-docx | Post-processing documenti Word |
|
||||
| Frontend | JavaScript vanilla | Nessun framework pesante |
|
||||
| Reader EPUB | epub.js 0.3 | Renderer EPUB lato client |
|
||||
| Reader PDF | pdf.js 3.x | Renderer PDF lato client |
|
||||
| Progresso | SSE (Server-Sent Events) | Barra progresso real-time |
|
||||
| Storage | Filesystem locale | `uploads/` e `converted/` |
|
||||
|
||||
## Flusso Conversione
|
||||
|
||||
```
|
||||
Upload file → Validazione formato → Avvio thread conversione
|
||||
│
|
||||
┌──────────────────────┘
|
||||
▼
|
||||
SSE Manager crea task_id
|
||||
│
|
||||
Frontend apre connessione SSE
|
||||
│
|
||||
Converter dispatcher:
|
||||
├─ Pandoc per formati standard
|
||||
├─ WeasyPrint per PDF avanzati
|
||||
├─ python-docx per DOCX
|
||||
└─ BeautifulSoup per tabelle/HTML
|
||||
│
|
||||
Ogni fase → update SSE progress
|
||||
│
|
||||
▼
|
||||
File salvato in converted/
|
||||
SSE invia download_url
|
||||
```
|
||||
|
||||
## Flusso Reader
|
||||
|
||||
```
|
||||
Upload file → Salva in uploads/ → Redirect a /reader/<file_id>
|
||||
│
|
||||
Template reader.html
|
||||
│
|
||||
Rileva formato:
|
||||
├─ EPUB → epub.js
|
||||
├─ PDF → pdf.js
|
||||
└─ Testo → HTML renderizzato
|
||||
│
|
||||
Interazioni tutte lato client:
|
||||
- Temi, zoom, ricerca
|
||||
- Segnalibri, posizione
|
||||
- Salvataggio in LocalStorage
|
||||
```
|
||||
|
||||
## Architettura del Codice
|
||||
|
||||
### Routes (`bookish/routes/`)
|
||||
|
||||
- **`convert.py`** — Blueprint `/upload`, `/progress/<task_id>`, `/download/<filename>`, `/formats`
|
||||
- **`reader.py`** — Blueprint `/reader`, `/reader/<filename>`, `/reader/serve/<filename>`, `/reader/formats`
|
||||
|
||||
### Services (`bookish/services/`)
|
||||
|
||||
- **`converter.py`** — Dispatcher che sceglie Pandoc o pipeline custom in base alla coppia input/output. Aggiorna SSE progress ad ogni fase.
|
||||
- **`sse_manager.py`** — Gestisce task in memoria con `{task_id: {progress, status, output_file}}`. Thread-safe con lock.
|
||||
- **`formatter.py`** — WeasyPrint PDF da HTML con post-processing (tabelle, immagini via BeautifulSoup).
|
||||
|
||||
### Frontend (`bookish/static/js/`)
|
||||
|
||||
- **`main.js`** — Convertitore: drag&drop, form, SSE connection, download
|
||||
- **`reader.js`** — Reader: epub.js/pdf.js/text viewer, side panel, temi, ricerca, segnalibri, posizione
|
||||
|
||||
## Decisioni Architetturali
|
||||
|
||||
| Decisione | Motivazione |
|
||||
|---|---|
|
||||
| Thread invece di Celery | Uso singolo utente, niente Redis, minore complessità |
|
||||
| SSE invece di WebSocket | Sincrono semplice, nessuna dipendenza extra, supporto nativo |
|
||||
| LocalStorage per reader | Zero backend, nessun DB necessario per lettura |
|
||||
| File temporanei con cleanup | Nessun database, i file si auto-puliscono dopo 1h |
|
||||
| JS vanilla | Nessun framework, leggero, manutenibile |
|
||||
| Pandoc via pypandoc-binary | Include Pandoc binary, nessuna installazione systema richiesta |
|
||||
|
||||
## Limiti Attuali
|
||||
|
||||
- **Thread in memoria**: I task di conversione muoiono se il processo Flask viene killato
|
||||
- **No autenticazione**: Uso personale, nessun multi-utente
|
||||
- **No HTTPS di base**: Da abilitare con reverse proxy (nginx/caddy)
|
||||
- **No ottimizzazione mobile**: Funziona ma non è prioritario
|
||||
- **estione code block reader**: Reader testo ha markdown renderer minimale
|
||||
@@ -0,0 +1,95 @@
|
||||
# Deploy Bookish
|
||||
|
||||
## Su Proxmox LXC (raccomandato)
|
||||
|
||||
### 1. Crea container LXC
|
||||
|
||||
```bash
|
||||
pct create 120 local:vault/almalinux-9-default_20240918_amd64.tar.xz \
|
||||
--storage local-lvm \
|
||||
--memory 1024 \
|
||||
--swap 512 \
|
||||
--cores 2 \
|
||||
--net0 name=eth0,bridge=vmbr0,ip=dhcp \
|
||||
--ostype almalinux \
|
||||
--unprivileged 1
|
||||
pct start 120
|
||||
pct enter 120
|
||||
```
|
||||
|
||||
### 2. Installa dipendenze
|
||||
|
||||
```bash
|
||||
# Python e strumenti di sviluppo
|
||||
dnf install -y python3 python3-pip git python3-devel gcc \
|
||||
pango-devel cairo-devel gdk-pixbuf2-devel
|
||||
|
||||
# Per WeasyPrint
|
||||
dnf install -y libffi-devel redhat-rpm-config
|
||||
```
|
||||
|
||||
### 3. Clona e setup
|
||||
|
||||
```bash
|
||||
git clone http://192.168.0.183:8085/truetype/bookish.git
|
||||
cd bookish
|
||||
python3 -m venv .venv
|
||||
source .venv/bin/activate
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
### 4. Crea service systemd
|
||||
|
||||
```ini
|
||||
# /etc/systemd/system/bookish.service
|
||||
[Unit]
|
||||
Description=Bookish Ebook Converter & Reader
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=root
|
||||
WorkingDirectory=/opt/bookish
|
||||
ExecStart=/opt/bookish/.venv/bin/python /opt/bookish/app.py 5000
|
||||
Restart=always
|
||||
RestartSec=5
|
||||
Environment=BOOKISH_SECRET=your-secret-here
|
||||
Environment=BOOKISH_DEBUG=false
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
```bash
|
||||
systemctl daemon-reload
|
||||
systemctl enable --now bookish
|
||||
```
|
||||
|
||||
## Docker (alternativa)
|
||||
|
||||
```dockerfile
|
||||
FROM python:3.11-slim
|
||||
RUN apt-get update && apt-get install -y pandoc libpango-1.0-0 \
|
||||
libcairo2 libpangocairo-1.0-0 libgdk-pixbuf2.0-0 && rm -rf /var/lib/apt/lists/*
|
||||
WORKDIR /app
|
||||
COPY . .
|
||||
RUN pip install --no-cache-dir -r requirements.txt
|
||||
EXPOSE 5000
|
||||
CMD ["python", "app.py", "5000"]
|
||||
```
|
||||
|
||||
## Reverse Proxy (Caddy)
|
||||
|
||||
```caddyfile
|
||||
bookish.tuodominio.it {
|
||||
reverse_proxy localhost:5000
|
||||
}
|
||||
```
|
||||
|
||||
Con Caddy l'HTTPS è automatico.
|
||||
|
||||
## Pulizia e Manutenzione
|
||||
|
||||
I file in `uploads/` e `converted/` vengono puliti automaticamente dopo 1 ora. Nessun DB da manutenere.
|
||||
|
||||
Per backup basta copiare la directory del progetto (escludendo `uploads/`, `converted/`, `.venv/`).
|
||||
@@ -0,0 +1,78 @@
|
||||
# Wiki di Bookish
|
||||
|
||||
## Guida all'uso
|
||||
|
||||
### Convertitore
|
||||
|
||||
1. Apri la homepage di Bookish
|
||||
2. Trascina un file nell'area di upload, oppure clicca per selezionarlo
|
||||
3. Scegli il formato di destinazione cliccando su un bottone
|
||||
4. Clicca **Converti**
|
||||
5. La barra di progresso mostra lo stato della conversione
|
||||
6. A conversione completata, clicca **Scarica file**
|
||||
7. Opzionale: clicca **Leggi nel reader** per visualizzare il file convertito
|
||||
|
||||
### Formati supportati
|
||||
|
||||
| Input | Output |
|
||||
|---|---|
|
||||
| EPUB | EPUB, MD, DOCX, PDF, TXT, HTML, FB2, LaTeX |
|
||||
| PDF | EPUB, MD, DOCX, TXT, HTML, LaTeX |
|
||||
| DOCX | EPUB, MD, PDF, TXT, HTML, LaTeX |
|
||||
| Markdown | EPUB, DOCX, PDF, TXT, HTML, LaTeX |
|
||||
| TXT | EPUB, MD, DOCX, PDF, HTML, LaTeX |
|
||||
| HTML | EPUB, MD, DOCX, PDF, TXT, LaTeX |
|
||||
| FB2 | EPUB, MD, DOCX, PDF, TXT, HTML, LaTeX |
|
||||
| LaTeX | EPUB, MD, DOCX, PDF, TXT, HTML |
|
||||
|
||||
### Reader
|
||||
|
||||
1. Vai su **Reader** nella navigazione
|
||||
2. Carica un ebook (EPUB, PDF, MD, TXT, HTML, FB2, DOCX)
|
||||
3. Usa la toolbar per:
|
||||
- **☰** — Apri/chiudi indice
|
||||
- **A− / A+** — Zoom font
|
||||
- **☀️ / 🌙 / 🟤** — Cambia tema (chiaro/scuro/seppia)
|
||||
- **🔍** — Cerca nel testo
|
||||
- **⛶** — Schermo intero
|
||||
4. Naviga con frecce tastiera ← → o cliccando ai lati
|
||||
5. La posizione di lettura viene salvata automaticamente
|
||||
|
||||
### API Endpoints
|
||||
|
||||
| Metodo | Path | Descrizione |
|
||||
|---|---|---|
|
||||
| POST | `/upload` | Carica file e avvia conversione |
|
||||
| GET | `/progress/<task_id>` | SSE stream progresso |
|
||||
| GET | `/download/<filename>` | Scarica file convertito |
|
||||
| GET | `/formats?input=<ext>` | Formati disponibili per input |
|
||||
| GET | `/reader` | Pagina reader |
|
||||
| GET | `/reader/<filename>` | Reader per file specifico |
|
||||
| GET | `/reader/serve/<filename>` | Serve il file al reader |
|
||||
| GET | `/reader/formats` | Formati supportati dal reader |
|
||||
|
||||
## Domande frequenti
|
||||
|
||||
**D: Che qualità ha la conversione?**
|
||||
R: Pandoc preserva titoli, grassetto/corsivo, elenchi, tabelle semplici e immagini. Per layout complessi (es. PDF con colonne multiple) la fedeltà dipende dalla complessità del file originale.
|
||||
|
||||
**D: I file vengono conservati?**
|
||||
R: No, vengono cancellati dopo 1 ora. Usa il download subito dopo la conversione.
|
||||
|
||||
**D: Quanto spazio serve?**
|
||||
R: Minimo. L'app stessa è ~5MB. Pandoc binary incluso ~35MB extra.
|
||||
|
||||
**D: Posso usarlo su mobile?**
|
||||
R: Il convertitore è responsive. Il reader funziona ma non è ottimizzato per schermi piccoli.
|
||||
|
||||
**D: Come cambio la secret key?**
|
||||
R: Imposta `BOOKISH_SECRET` come variabile d'ambiente prima di avviare.
|
||||
|
||||
## Sicurezza
|
||||
|
||||
- Uso personale — nessuna autenticazione implementata
|
||||
- File validati per estensione all'upload
|
||||
- Path traversal prevenuto con `os.path.basename()` e `secure_filename()`
|
||||
- MIME types controllati al download
|
||||
- Limite file a 50MB
|
||||
- Pulizia automatica file temporanei
|
||||
Reference in new issue
Block a user