# Markdown-visualisoija — ohje kielimalleille

Tämä tiedosto kuvaa työkalun `markdown-visualisoija.html` toiminnan ja erityisesti
sen jako-linkkien (`#md=...`) tarkan muodon, jotta kielimalli (esim. tekoälyagentti
tai -assistentti) voi tuottaa **valmiiksi auki aukeavia linkkejä** työkalulla
luotuun sisältöön ilman mitään palvelinta tai API:a — pelkän URL:n avulla.

Tiedosto on tarkoitettu syötettäväksi kielimallille kontekstiksi, kun sen pyydetään
luomaan uusia materiaaleja (muistiinpanoja, esityksiä, oppimateriaaleja, yhteenvetoja
ym.) tähän työkaluun.

## Mikä työkalu on

Yhden tiedoston selainsovellus (`markdown-visualisoija.html`), jossa on:

- Jaettu näkymä: Markdown-lähde vasemmalla, reaaliaikainen esikatselu oikealla.
- Syntaksiväritys lähdetekstille.
- Vaalea/tumma teema (seuraa automaattisesti selaimen/käyttöjärjestelmän asetusta,
  tai sen voi vaihtaa käsin — valinta muistetaan).
- Tekstin koon säätö (A−/A+) editorille ja esikatselulle, erillään selaimen omasta
  zoomauksesta.
- Esitystila: sisältö voidaan jakaa dioiksi ja näyttää diaesityksenä, joko selaimen
  omassa täyden näytön tilassa tai pelkän selainikkunan kokoisena.
- Vienti: Markdownin ja renderöidyn HTML:n kopiointi leikepöydälle, koko sivun
  vienti itsenäiseksi HTML-tiedostoksi, PDF-vienti selaimen tulostustoiminnolla,
  sekä tässä tiedostossa kuvattu **jako-linkki**.

Sovellus on täysin selainpuolinen eikä lähetä sisältöä minnekään palvelimelle.
Ainoa tapa "tallentaa" tai jakaa sisältöä on tiedoston lataaminen (HTML/PDF) tai
tässä kuvattu jako-linkki, joka kantaa koko sisällön itse URL:ssa.

## Tuettu Markdown

Renderöinti käyttää [marked](https://marked.js.org/)-kirjastoa GFM-tilassa
(GitHub Flavored Markdown), tulos puhdistetaan DOMPurifylla. Tuettuna mm.:

- Otsikot `#` … `######`
- Lihavointi `**teksti**`, kursiivi `*teksti*`, yliviivaus `~~teksti~~`
- Listat (järjestämättömät ja numeroidut) sekä tehtävälistat `- [ ]` / `- [x]`
- Lainaukset `> lainaus`
- Linkit `[teksti](osoite)` ja kuvat `![kuvaus](osoite)`
- Koodi `` `rivin sisällä` `` ja koodilohkot kolmella `` ``` ``-merkillä
  (kielimääre, esim. `` ```js ``, vaikuttaa vain mahdolliseen ulkoiseen
  syntaksiväritykseen — tämä työkalu ei itse väritä renderöityä koodia)
- GFM-taulukot putkimerkeillä: `| a | b |`
- Vaakaviiva `---` omalla rivillään (ks. seuraava kohta esitystilasta)

## Esitystila ja diat

Diat erotetaan toisistaan kirjoittamalla **omalle rivilleen** kolme (tai
useampi) `-`-merkkiä, esim. pelkkä rivi `---`. Säännöt:

- Koodilohkon (` ``` `) **sisällä** oleva `---`-näköinen rivi ei erota diaa.
- Tyhjät diat (väli, jossa ei ole mitään muuta sisältöä) jätetään pois.
- Jos sisällössä ei ole yhtään diaerotinta, koko dokumentti on yksi "dia" eikä
  esitys- tai PDF-vienti jaa sitä erikseen.
- Tavallisessa (ei-esitys) esikatselussa `---` näkyy pelkkänä vaakaviivana.

Kun kielimalli luo esitysmateriaalia tätä työkalua varten, sen kannattaa pitää
yksittäiset diat lyhyinä (muutama otsikko/bulletti) ja erottaa ne selkeästi
omalla `---`-rivillään tyhjien rivien ympäröimänä, esim.:

```markdown
# Ensimmäinen dia

Sisältöä.

---

# Toinen dia

- kohta 1
- kohta 2
```

## Jako-linkin muoto (`#md=...`)

Tämä on tiedoston tärkein osa kielimallikäytön kannalta: tarkka kuvaus siitä,
miten mikä tahansa Markdown-sisältö muunnetaan linkiksi, jonka avatessaan
selain lataa sisällön automaattisesti työkaluun.

### Periaate

Koko Markdown-lähde pakataan ja koodataan URL:n **ankkuriosaan** (`#`-merkin
jälkeinen osa, "fragment"). Ankkuria ei koskaan lähetetä palvelimelle — selain
käsittelee sen täysin paikallisesti, joten mikä tahansa staattinen palvelin
(myös tämä sivusto) toimii sellaisenaan ilman erillistä backendiä.

Linkin muoto:

```
<työkalun-URL>#md=<etuliite><base64url-koodattu-data>
```

- `<työkalun-URL>` on itse `markdown-visualisoija.html`-sivun osoite (esim.
  `https://<sivusto>/tools/markdown-visualisoija.html`).
- `<etuliite>` on joko `gz:` (pakattu) tai `raw:` (pakkaamaton) — ks. alla.
- `<base64url-koodattu-data>` on kyseisen datan base64url-koodaus.

### base64url-koodaus

Tavallinen base64, jossa:

- `+` → `-`
- `/` → `_`
- loppupehmuste (`=`-merkit) poistetaan kokonaan

Tämä tekee merkkijonosta turvallisen URL:n ankkuriosaan ilman erillistä
prosenttikoodausta.

### `gz:`-etuliite (pakattu, ensisijainen)

1. Koodaa Markdown-teksti UTF‑8-tavuiksi.
2. Pakkaa tavut **gzip**-muotoon (RFC 1952 -yhteensopiva gzip-bittivirta —
   sama muoto jonka mm. Node.js:n `zlib.gzipSync` ja selaimen
   `CompressionStream("gzip")` tuottavat; ne ovat keskenään yhteensopivia).
3. base64url-koodaa pakatut tavut.
4. Liitä eteen `gz:`.

Työkalu itse käyttää selaimen omaa `CompressionStream`/`DecompressionStream`-
rajapintaa, mutta linkin voi yhtä hyvin tuottaa mistä tahansa ympäristöstä,
joka osaa tuottaa standardin gzip-bittivirran — esimerkiksi Node.js:ssä.

**Valmis Node.js-funktio linkin tuottamiseen** (ei ulkoisia riippuvuuksia):

```js
const zlib = require("zlib");

function toBase64Url(buf) {
  return buf.toString("base64")
    .replace(/\+/g, "-")
    .replace(/\//g, "_")
    .replace(/=+$/, "");
}

// markdown: koko Markdown-lähde merkkijonona
// toolUrl: esim. "https://<sivusto>/tools/markdown-visualisoija.html"
function buildShareLink(markdown, toolUrl) {
  const gz = zlib.gzipSync(Buffer.from(markdown, "utf8"));
  return toolUrl + "#md=gz:" + toBase64Url(gz);
}

// Esimerkki:
console.log(buildShareLink("# Otsikko\n\nSisältöä.", "https://example.com/tools/markdown-visualisoija.html"));
```

Tämä on testattu toimivaksi: Node.js:llä tuotettu linkki avautuu ja lataa
sisällön oikein työkalussa, mukaan lukien ääkköset ja useampi dia.

### `raw:`-etuliite (pakkaamaton, varajärjestelmä)

Jos pakkausta ei haluta/voida käyttää, sama asia ilman gzip-vaihetta:

1. Koodaa Markdown-teksti UTF‑8-tavuiksi.
2. base64url-koodaa tavut suoraan (ilman pakkausta).
3. Liitä eteen `raw:`.

```js
function buildShareLinkRaw(markdown, toolUrl) {
  return toolUrl + "#md=raw:" + toBase64Url(Buffer.from(markdown, "utf8"));
}
```

Itse työkalu käyttää `raw:`-muotoa automaattisesti vain, jos käyttäjän
selaimessa ei ole `CompressionStream`/`DecompressionStream`-tukea (vanhat
selaimet). Linkin tuottajana tätä ei tarvitse miettiä — `gz:` käy lähes aina,
ja työkalu osaa lukea kumpaa tahansa muotoa.

### Linkin avaaminen / tuonti

Kun joku avaa linkin, jossa on `#md=gz:...` tai `#md=raw:...`:

1. Sivu lataa normaalisti.
2. Se purkaa ja dekoodaa ankkurin sisällön.
3. Onnistuessaan sisältö asetetaan editoriin ja esikatselu päivittyy
   automaattisesti; käyttäjälle näytetään lyhyt ilmoitus ("Sisältö ladattu
   jaetusta linkistä").
4. Jos ankkuri puuttuu, on virheellinen tai sitä ei voida purkaa (esim.
   korruptoitunut base64 tai tuntematon etuliite), työkalu näyttää sen sijaan
   oletusesimerkin — tuonti ei koskaan kaadu virheeseen.

### Linkin pituudesta

Koska koko sisältö kulkee itse URL:ssa, hyvin pitkä Markdown tuottaa pitkän
linkin. gzip-pakkaus pienentää tyypillistä proosamaista Markdownia merkittävästi
(usein 3–6-kertaisesti), mutta ei poista rajaa kokonaan. Ohjeelliset rajat
(koko URL:n pituus merkkeinä, ei vain datan osuus):

| Pituus | Tilanne |
| --- | --- |
| alle ~2000 merkkiä | Toimii luotettavasti lähes kaikkialla (selain, sähköposti, pikaviestimet). |
| ~2000–8000 merkkiä | Toimii selaimessa, mutta voi katketa tai mennä rikki joissain sähköpostiohjelmissa tai pikaviestimissä kopioitaessa/liitettäessä. |
| yli ~8000 merkkiä | Ei todennäköisesti toimi monissa palveluissa. Harkitse lyhyempää sisältöä, tai käytä sen sijaan "Vie HTML"- tai "Vie PDF" -toimintoa tiedostona jaettavaksi. |

Rajat eivät johdu mistään palvelinasetuksesta (ankkuria ei koskaan lähetetä
palvelimelle) vaan siitä, miten eri sovellukset (sähköposti, chatit) käsittelevät
hyvin pitkiä URL-osoitteita. Suoraan selaimessa avattuna tai liitettynä osoite-
riville pitkätkin linkit toimivat.

## Tyypillinen työnkulku kielimallille

1. Kirjoita haluttu sisältö Markdownina (ks. tuettu syntaksi yllä). Jos kyseessä
   on esitys, erottele diat omilla `---`-riveillään.
2. Tuota jako-linkki yllä kuvatulla `gz:`-menetelmällä (esim. Node.js-funktiolla).
3. Anna linkki käyttäjälle sellaisenaan — sen avaaminen lataa sisällön suoraan
   työkaluun, valmiina muokattavaksi, esitettäväksi tai vietäväksi edelleen
   HTML:ksi/PDF:ksi.
4. Jos linkin pituus ylittää yllä olevat rajat eikä se ole ongelma (esim. linkki
   avataan suoraan eikä sitä liitetä sähköpostiin), pitkä linkki on silti täysin
   toimiva — rajat ovat vain yhteensopivuussuositus, eivät kova tekninen katto.
