VersionDiff
Versiovertailu
Kahden version ero avain–arvo-riveinä, muutos päällekkäin −/+ ja muutosloki aikajanana.
Käyttöpaikat
Suoraan: palvelu tuo osan itse. Välillisesti: osa tulee mukaan toisen paketin osan kautta, ja sen muutos näkyy palvelussa silti. Laskettu julkaisun yhteydessä 23.10.2026.
Käyttö
Paketin README:n luku sellaisenaan.
VersionDiff — kahden version ero
const rivit = diffEntries(
vanha.map((a) => ({ key: a.name, value: a.value, meta: a.source })),
uusi.map((a) => ({ key: a.name, value: a.value, meta: a.source })),
);<VersionDiff entries={rivit} beforeLabel="v3" afterLabel="v4" />Vertailu on `lib/diff.ts`:ssä, komponentti on pelkkä esitys. Sama jako kuin lajittelussa ja sivutuksessa.
diffEntries(before, after, opts) | rivit tiloineen: added · removed · changed · unchanged |
diffSummary(entries) | montako kussakin tilassa |
hasChanges(entries) | onko mitään eroa |
Vertailun kolme sääntöä, kaikki tarpeen ulkopuolelta tulevalle datalle:
null,undefinedja""ovat sama asia — puuttuva kenttä voi olla mikä tahansa niistä5ja"5"ovat sama arvo, mutta `"5 kg"` ei ole `5`0jafalseeivät ole tyhjiä
> `compareMeta` on oletuksena `true`. Arvon alkuperän muutos on muutos, > vaikka arvo pysyisi samana: *ehdotus on väite lähteestä, tallennettu arvo > on päätös.* Perustelu on AIMO:lta, ja se korjasi oletukseni. false jos > alkuperää ei ole tai se on kohinaa.
Muuttumattomat rivit ovat suljetussa <details>-lohkossa — natiivi disclosure eikä React-tila, joten komponentti pysyy palvelinpuolella ja toimii ilman JavaScriptiä.
ChangeRow ja ChangePair — muutos kahtena rivinä
Vanha arvo punaisella «−», uusi vihreällä «+», päällekkäin kuten koodidiffissä. Tämä on muutoshistorian ainoa esitystapa (omistajan päätös): vierekkäiset sarakkeet pakottavat silmän hyppäämään, ja «35 → 35.0» ei kerro kumpi on vanha ennen kuin konvention on oppinut.
<ChangePair label="Ostohinta alv 0 %" before="19,31 €" after="20,33 €" source="lähde toimittaja" /> <ChangePair label="Tullikoodi" after="39241000" /> // uusi tieto: vain +
Ruudunlukijalle sama sanoin (Poistettu: / Lisätty:); etumerkki on aria-hidden. Teksti pysyy text-foregroundilla ja väriä kantaa reuna ja etumerkki — sama jako kuin Badgein pehmeillä varianteilla. VersionDiff on edelleen oikea työkalu kahden kokonaisen version vertailuun avaimittain; tämä on yhden arvon muutos siellä missä se näytetään.
Changelog — versiohistoriasivu
Jokaisella TP-palvelulla on /versiohistoria-sivu joka näyttää oman CHANGELOG.md:nsä. Changelog renderöi sen aikajanana.
// app/(app)/versiohistoria/page.tsx
import { readFile } from "node:fs/promises";
import { join } from "node:path";
import { Changelog, PageHeader } from "@karkkainen/ui";
export default async function VersiohistoriaPage() {
const md = await readFile(join(process.cwd(), "CHANGELOG.md"), "utf8");
return (
<>
<PageHeader
title="Versiohistoria"
subtitle="Kaikki merkittävät muutokset. Näkymä peilaa repon CHANGELOG.md:tä."
/>
<Changelog markdown={md} />
</>
);
}Komponentti ei lue tiedostoa itse. Polku on palvelukohtainen, ja node:fs rikkoisi komponentin asiakaspuolella — anna markdown merkkijonona.
| Propsi | Oletus | Merkitys |
|---|---|---|
markdown | — | CHANGELOG.md:n sisältö |
initialCount | 10 | Montako uusinta julkaisua näytetään avattuna; loput <details>-elementin taakse. 0 = kaikki auki |
summary | true | Yhteenvetokortit: nykyinen versio ja julkaisemattomien määrä |
Tuettu markdown: versio-otsikot sekä ajatus- (–) että tavuviivalla (-), versiottomat osiot (## Julkaisematon), vapaamuotoiset ###-otsikot, koodilohkot, taulukot, sisäkkäiset listat ja inline-muotoilut.
Jos haluat renderöidä itse, parseChangelog on viety erikseen:
import { parseChangelog, type ChangelogRelease } from "@karkkainen/ui";
const { intro, releases } = parseChangelog(md);Konventiot:
- Näkymä peilaa CHANGELOG.md:tä. Älä ylläpidä erillistä listaa sivulla — jos ne erkanevat, sivu on väärässä eikä kukaan huomaa.
- Otsikkotyypit (
Lisätty,Muutettu,Korjattu,Poistettu,Turvallisuus,Vanhentunut) saavat automaattisesti oman Badge-varianttinsa. Ne tunnistetaan myös muodosta### Lisätty: kuvaus. - Tyhjää `## Julkaisematon` -osiota ei kannata jättää — se renderöityy sisällöttömänä julkaisuna.
Tuonti ja lähde
import { VersionDiff, ChangeRow, ChangePair, ChangelogText, Changelog } from "@karkkainen/ui";src/components/version-diff.tsxsrc/components/change-row.tsxsrc/components/changelog.tsx