feat: markdown rendering /m/<id>
This commit is contained in:
268
.llm/analysis.md
Normal file
268
.llm/analysis.md
Normal file
@@ -0,0 +1,268 @@
|
||||
# Analiza repozytorium: bin (Pastebin)
|
||||
|
||||
> Data analizy: 2026-04-21
|
||||
|
||||
---
|
||||
|
||||
## 1. Cel projektu
|
||||
|
||||
**Bin** to minimalistyczny, samodzielny serwis pastebin akceptujący zarówno tekst, jak i pliki binarne (obrazy, PDF-y itp.). Filozofia projektu opiera się na prostocie, łatwości wdrożenia i minimalizmie. W odróżnieniu od tradycyjnych pastebinów **nie wymaga bazy danych** — wszystkie pasty przechowywane są w płaskim systemie plików. Projekt zawiera klienty: interfejs webowy, CLI i integrację z Vimem.
|
||||
|
||||
**Live demo:** https://basedbin.fly.dev
|
||||
**Docker:** `wantguns/bin` (multi-arch: amd64 + arm64)
|
||||
|
||||
---
|
||||
|
||||
## 2. Stack technologiczny
|
||||
|
||||
| Warstwa | Technologia |
|
||||
|---------|-------------|
|
||||
| Język | Rust (Edition 2021) |
|
||||
| Framework web | Rocket 0.5.0-rc.1 (async) |
|
||||
| Szablony HTML | Tera (via rocket_dyn_templates) |
|
||||
| Kolorowanie składni | Syntect 4.6.0 + motyw Ayu Dark |
|
||||
| Frontend | Vanilla JavaScript, HTML, CSS (brak frameworków) |
|
||||
| Detekcja MIME | tree_magic 0.2.3 |
|
||||
| CLI args | clap 3.0.9 |
|
||||
| Kryptografia | sha256 (ETag) |
|
||||
| Obsadzanie zasobów | rust-embed 6.3.0 |
|
||||
| Konteneryzacja | Docker (obraz scratch) |
|
||||
| Deployment | Fly.io |
|
||||
|
||||
---
|
||||
|
||||
## 3. Struktura katalogów
|
||||
|
||||
```
|
||||
bin/
|
||||
├── src/ # Kod źródłowy Rust
|
||||
│ ├── main.rs # Punkt wejścia, setup serwera, parsowanie CLI
|
||||
│ ├── routes/ # Handlery endpointów HTTP
|
||||
│ │ ├── mod.rs
|
||||
│ │ ├── index.rs # GET / – strona główna
|
||||
│ │ ├── upload.rs # POST / – upload pliku binarnego
|
||||
│ │ ├── submit.rs # POST /submit – formularz tekstowy
|
||||
│ │ ├── retrieve.rs # GET /<id> – surowe pobranie pasty
|
||||
│ │ ├── pretty_retrieve.rs # GET /p/<id> – wyświetlanie z podświetlaniem
|
||||
│ │ └── static_files.rs # GET /static/<file> – zasoby statyczne
|
||||
│ └── models/
|
||||
│ ├── mod.rs
|
||||
│ ├── paste_id.rs # Generowanie i walidacja ID pasty
|
||||
│ ├── pretty_syntax.rs # Parsowanie rozszerzenia z URL
|
||||
│ ├── pretty.rs # Logika podświetlania składni
|
||||
│ └── response_wrapper.rs # Abstrakcja odpowiedzi HTTP
|
||||
│
|
||||
├── templates/ # Szablony Tera
|
||||
│ ├── base.html.tera
|
||||
│ ├── index.html.tera
|
||||
│ └── pretty.html.tera
|
||||
│
|
||||
├── static/ # Zasoby osadzone w binarce
|
||||
│ ├── css/
|
||||
│ ├── js/
|
||||
│ ├── fonts/ # Iosevka (ttf + woff2)
|
||||
│ └── media/ # Favicony
|
||||
│
|
||||
├── resources/ # Zasoby binarne (syntaksy, motyw)
|
||||
├── contrib/cli/client # Skrypt bash CLI
|
||||
├── Cargo.toml # Manifest projektu
|
||||
├── build.rs # Wstrzykiwanie git hash do binarki
|
||||
├── Dockerfile # Wielostopniowy build
|
||||
├── docker-compose.yml
|
||||
└── fly.toml # Konfiguracja Fly.io
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. Endpointy API
|
||||
|
||||
| Metoda | Ścieżka | Opis |
|
||||
|--------|---------|------|
|
||||
| GET | `/` | Strona główna z formularzem |
|
||||
| GET | `/static/<file>` | Zasoby statyczne (CSS, JS, czcionki) |
|
||||
| POST | `/` | Upload pliku binarnego → zwraca ID |
|
||||
| POST | `/submit` | Formularz tekstowy → redirect do `/p/<id>.<ext>` |
|
||||
| GET | `/<id>` | Surowa treść pasty |
|
||||
| GET | `/<id>.<ext>` | Surowa treść z rozszerzeniem (rank=1) |
|
||||
| GET | `/p/<id>` | Pasta z podświetlaniem składni (HTML) |
|
||||
| GET | `/p/<id>.<ext>` | Pasta z wymuszonym językiem (rank=1) |
|
||||
|
||||
**Priorytet routingu:** trasy z rozszerzeniem (`rank=1`) są dopasowywane przed trasami generycznymi (`rank=2`).
|
||||
|
||||
---
|
||||
|
||||
## 5. Modele danych
|
||||
|
||||
### PasteId
|
||||
```rust
|
||||
pub struct PasteId<'a>(Cow<'a, str>)
|
||||
```
|
||||
- Generuje losowe 6-znakowe ID alfanumeryczne (36^6 ≈ 2,1 mld kombinacji)
|
||||
- Implementuje `FromParam` dla automatycznej walidacji URL w Rocket
|
||||
|
||||
### PasteIdSyntax
|
||||
```rust
|
||||
pub struct PasteIdSyntax<'a> { syn_id: Cow<'a, str> }
|
||||
```
|
||||
- Parsuje URL typu `/p/abc123.cpp` na nazwę pliku i rozszerzenie
|
||||
- `get_fname()` → `"abc123"`, `get_ext()` → `"cpp"`
|
||||
|
||||
### ResponseWrapper<R>
|
||||
```rust
|
||||
enum ResponseWrapper<R> {
|
||||
MetaInterfaceResponse(R),
|
||||
PrettyPasteContentResponse(R, SystemTime),
|
||||
RawPasteContentResponse(R, SystemTime),
|
||||
Redirect(Box<Redirect>),
|
||||
NotFound(String),
|
||||
ServerError(String),
|
||||
}
|
||||
```
|
||||
Centralnie zarządza nagłówkami HTTP:
|
||||
- `Server: bin v.<VERSION> (<GIT_HASH>)`
|
||||
- `ETag`, `Last-Modified`, `Cache-Control`
|
||||
|
||||
---
|
||||
|
||||
## 6. Zależności (Cargo.toml)
|
||||
|
||||
| Crate | Wersja | Zastosowanie |
|
||||
|-------|--------|--------------|
|
||||
| `rand` | 0.8.4 | Generowanie ID |
|
||||
| `rocket` | 0.5.0-rc.1 | Framework web |
|
||||
| `tree_magic` | 0.2.3 | Detekcja MIME |
|
||||
| `syntect` | 4.6.0 | Podświetlanie składni |
|
||||
| `rust-embed` | 6.3.0 | Osadzanie zasobów |
|
||||
| `clap` | 3.0.9 | Parsowanie CLI |
|
||||
| `once_cell` | 1 | Lazy static |
|
||||
| `sha256` | 1 | ETag |
|
||||
| `time` | 0.3 | Formatowanie czasu |
|
||||
| `rocket_dyn_templates` | 0.1.0-rc.1 | Szablony Tera |
|
||||
|
||||
---
|
||||
|
||||
## 7. System budowania
|
||||
|
||||
### build.rs
|
||||
Przechwytuje hash commita git i wstrzykuje go jako stałą czasu kompilacji (`GIT_HASH`).
|
||||
|
||||
### .cargo/config.toml
|
||||
- Kompilacja statyczna: `-C target-feature=+crt-static`
|
||||
- Domyślny target: `x86_64-unknown-linux-gnu`
|
||||
- Cross-kompilacja ARM64: `aarch64-linux-gnu-gcc`
|
||||
|
||||
### Docker (wielostopniowy)
|
||||
1. **Builder:** obraz Rust → `cargo build --release`
|
||||
2. **Runner:** obraz `scratch` (pusty) + tylko binarka
|
||||
3. Rezultat: minimalistyczny obraz (~20-30 MB)
|
||||
|
||||
---
|
||||
|
||||
## 8. Konfiguracja serwera
|
||||
|
||||
### Argumenty CLI
|
||||
|
||||
| Flag | Domyślnie | Opis |
|
||||
|------|-----------|------|
|
||||
| `-a` | `127.0.0.1` | Adres nasłuchu |
|
||||
| `-p` | `6162` | Port |
|
||||
| `-u` | `./upload` | Katalog przechowywania plików |
|
||||
| `-b` | `100 MiB` | Limit rozmiaru uploadu binarnego |
|
||||
| `-c` | off | Pokaż opis klienta CLI na stronie głównej |
|
||||
|
||||
### Zmienne środowiskowe (prefiks `BIN_`)
|
||||
```bash
|
||||
BIN_PORT=6163
|
||||
BIN_ADDRESS=0.0.0.0
|
||||
BIN_LIMITS={form="16 MiB"}
|
||||
BIN_WORKERS=8
|
||||
BIN_IDENT=false
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 9. Architektura i wzorce projektowe
|
||||
|
||||
1. **Embedded Resources** — wszystkie zasoby (CSS, JS, czcionki, definicje syntaksy) skompilowane w binarce (`rust-embed`). Zero zależności zewnętrznych.
|
||||
|
||||
2. **Response Wrapper** — generyczny wrapper abstrakcji odpowiedzi z centralizowaną logiką nagłówków HTTP.
|
||||
|
||||
3. **Type-Safe URL Params** — `PasteId` i `PasteIdSyntax` implementują trait `FromParam` — Rocket automatycznie waliduje parametry URL.
|
||||
|
||||
4. **Lazy Static** — `BINARY_ETAG` obliczany raz przy starcie (SHA256 wersji) via `once_cell::sync::Lazy`.
|
||||
|
||||
5. **Build-Time Version Injection** — hash git osadzony w czasie kompilacji, widoczny w nagłówku `Server`.
|
||||
|
||||
6. **Flat Filesystem Storage** — brak bazy danych; pasty jako pliki w katalogu `./upload`.
|
||||
|
||||
---
|
||||
|
||||
## 10. Frontend (JavaScript)
|
||||
|
||||
### index.js (~150 linii)
|
||||
- Drag-and-drop upload plików
|
||||
- Wklejanie obrazów ze schowka (`paste` event)
|
||||
- Tab jako 4 spacje (nie nawigacja formularza)
|
||||
- Ctrl+Enter → submit
|
||||
- Dynamiczne pokazywanie/ukrywanie UI
|
||||
- Fork przez localStorage
|
||||
|
||||
### pretty.js
|
||||
- Przełącznik zawijania: 3 stany (brak → auto → 80 znaków)
|
||||
- Fork: kopiuje treść do localStorage, przekierowuje na główną
|
||||
- Raw: przełącza `/p/<id>` → `/<id>`
|
||||
- New: przejście do strony głównej
|
||||
|
||||
---
|
||||
|
||||
## 11. Strategia cachowania
|
||||
|
||||
| Typ odpowiedzi | Cache-Control |
|
||||
|----------------|---------------|
|
||||
| Pasta pretty | `max-age=604800, stale-while-revalidate=86400` |
|
||||
| Pasta raw | `max-age=604800, immutable` |
|
||||
| Meta/Statyczne | ETag (SHA256 wersji) → `304 Not Modified` |
|
||||
|
||||
---
|
||||
|
||||
## 12. Statystyki kodu
|
||||
|
||||
| Metryka | Wartość |
|
||||
|---------|---------|
|
||||
| Pliki źródłowe Rust | 13 |
|
||||
| Linie kodu Rust | ~600 |
|
||||
| Szablony HTML | 3 |
|
||||
| Pliki JavaScript | 2 |
|
||||
| Arkusze CSS | 2 |
|
||||
| Obsługiwane języki (syntaksy) | 100+ |
|
||||
| Endpointy API | 7 |
|
||||
| Typy odpowiedzi HTTP | 6 |
|
||||
|
||||
---
|
||||
|
||||
## 13. Algorytmy kluczowe
|
||||
|
||||
### Generowanie ID
|
||||
```
|
||||
1. rand::thread_rng() → thread-safe RNG
|
||||
2. Alphanumeric distribution (a-z, A-Z, 0-9)
|
||||
3. Pobierz 6 próbek → String
|
||||
4. Opakuj w Cow::Owned
|
||||
```
|
||||
|
||||
### Detekcja MIME (upload binarny)
|
||||
```
|
||||
1. Wczytaj bajty pliku
|
||||
2. tree_magic::from_filepath() → MIME
|
||||
3. MIME zawiera "text" → /p/<id> (kolorowanie)
|
||||
4. Inaczej → /<id> (surowe pobranie)
|
||||
```
|
||||
|
||||
### Renderowanie składni
|
||||
```
|
||||
1. Parsuj URL /p/abc123.cpp
|
||||
2. Wyodrębnij rozszerzenie ("cpp")
|
||||
3. Znajdź definicję syntaxu w syntect
|
||||
4. Fallback → plain_text
|
||||
5. Renderuj HTML z motywem Ayu Dark
|
||||
```
|
||||
Reference in New Issue
Block a user