json formaat beschreven
This commit is contained in:
+940
@@ -0,0 +1,940 @@
|
|||||||
|
# JSON-export- en importformaat van Racket Wiki
|
||||||
|
|
||||||
|
Deze specificatie beschrijft **`racket-wiki-cmap-bundle`, formaatversie 1**,
|
||||||
|
op basis van het JSON Schema, de implementatie in deze repository en de
|
||||||
|
drie aangeleverde exports van Racket Wiki 0.2.122:
|
||||||
|
`modelgids-lts-opzet-cmap.json`, `rws-dingen-cmap.json` en
|
||||||
|
`rws-lbs-architectuur-cmap.json`.
|
||||||
|
Een bundel bevat één of meer concept maps (CMaps), gedeelde concepten,
|
||||||
|
gekoppelde wikipagina's en eventueel hun bijlagen. Het is geen volledige
|
||||||
|
databaseback-up: gebruikers, instellingen, versiegeschiedenis en aliassen
|
||||||
|
maken geen deel uit van dit formaat.
|
||||||
|
|
||||||
|
## 1. Status en conventies
|
||||||
|
|
||||||
|
Het machineleesbare contract staat in
|
||||||
|
[racket-wiki-cmap-bundle-v1.schema.json](static/schemas/racket-wiki-cmap-bundle-v1.schema.json)
|
||||||
|
en gebruikt JSON Schema Draft 2020-12. De browser voert daarnaast eigen
|
||||||
|
controles uit in [interchange.js](static/js/cmap/model/interchange.js).
|
||||||
|
|
||||||
|
**MOET**, **MAG** en **BEHOORT** betekenen respectievelijk een eis, een
|
||||||
|
toegestane mogelijkheid en een aanbeveling. De veldtabellen beschrijven het
|
||||||
|
schema; aanvullende voorwaarden staan bij de betreffende velden en in § 9.
|
||||||
|
Verschillen met de huidige uitvoering staan expliciet in § 12. Succesvolle
|
||||||
|
browservalidatie is dus niet hetzelfde als volledige schemavalidatie.
|
||||||
|
|
||||||
|
Het bestand bevat één JSON-object. Gebruik UTF-8, echte JSON-getallen en
|
||||||
|
booleans; gebruik geen commentaar of afsluitende komma's. Een optioneel veld
|
||||||
|
MAG ontbreken. `null` is uitsluitend toegestaan waar dat is vermeld.
|
||||||
|
De volgorde van objectvelden heeft geen betekenis.
|
||||||
|
|
||||||
|
### 1.1 Nadere typering
|
||||||
|
|
||||||
|
Naast het JSON-basistype gebruikt dit document benoemde typen voor betekenis
|
||||||
|
en interne structuur. `T[]` betekent een array van elementen van type `T`;
|
||||||
|
`T of null` staat expliciet `null` toe. `Record<K, V>` is een JSON-object
|
||||||
|
waarvan de veldnamen sleutels van type `K` zijn en de waarden type `V` hebben.
|
||||||
|
Een lege array in een voorbeeld bewijst niet welk elementtype is toegestaan.
|
||||||
|
|
||||||
|
De tabellen met **schema** als aanduiding beschrijven het bestaande contract.
|
||||||
|
Tabellen met **model/export** beschrijven de huidige modelrepresentatie,
|
||||||
|
waar nodig aangevuld met waarnemingen uit de drie aangeleverde exports. Een
|
||||||
|
waargenomen waarde is geen uitputtende opsomming van toegestane waarden.
|
||||||
|
Een gewenste semantische wijziging wordt afzonderlijk aangeduid en is geen
|
||||||
|
bewering dat de huidige software die wijziging al uitvoert.
|
||||||
|
|
||||||
|
### 1.2 Verbindingszin: betekenis en huidige representatie
|
||||||
|
|
||||||
|
Het beoogde domeinuitgangspunt is: **een verbindingszin drukt een relatie
|
||||||
|
tussen concepten uit en is zelf een concept**. Die betekenis is onafhankelijk
|
||||||
|
van de kaart waarop zij wordt getoond. De plaatsing, opmaak en getekende
|
||||||
|
lijnstukken zijn wel kaartgebonden.
|
||||||
|
|
||||||
|
De huidige export vertegenwoordigt dit uitgangspunt nog niet volledig.
|
||||||
|
Daarin is `omvat` een item met `kind: "phrase"`, `id: 2` en `conceptId: null`.
|
||||||
|
De tekst staat op het item, niet in de gedeelde `concepts`-tabel. Het model
|
||||||
|
`ConceptMapPhrase` bewaart dit eveneens zo. De eerdere formulering
|
||||||
|
“een verbindingszin is kaartlokaal” was daarom te algemeen: **de huidige
|
||||||
|
opslag van de verbindingszin is kaartlokaal; haar bedoelde betekenis is dat niet**.
|
||||||
|
|
||||||
|
De code kent daarnaast een `ConceptRelation` met bronconcept, doelconcept
|
||||||
|
en een tekstueel label (§ 5.3). Dat is een semantische relatie, maar maakt
|
||||||
|
het label nog niet tot een zelfstandig gedeeld concept. Geen van de drie
|
||||||
|
exports bevat `conceptRelations`, `conceptOwnerships` of een `relationId`
|
||||||
|
op de connectoren. Alle phrase-items hebben `conceptId: null`.
|
||||||
|
De editorfunctie `connectWithPhrase` maakt een phrase en connectoren aan,
|
||||||
|
zonder daarbij een `ConceptRelation` te registreren.
|
||||||
|
|
||||||
|
Om het domeinuitgangspunt volledig te ondersteunen, zouden verbindingszinnen
|
||||||
|
een gedeelde conceptidentiteit moeten hebben en zouden semantische relaties
|
||||||
|
die identiteit moeten gebruiken. Het huidige formaat bevat daarvoor geen
|
||||||
|
expliciete rolverwijzing naar het verbindingsconcept. Alleen een `conceptId`
|
||||||
|
invullen op een `phrase` volstaat niet: het huidige phrase-model bewaart
|
||||||
|
die koppeling niet. Dit is een verschil tussen het bedoelde domeinmodel en
|
||||||
|
de implementatie, geen wijziging die deze documentatie in het formaat aanbrengt.
|
||||||
|
|
||||||
|
### 1.3 Verbindingszinnen in model en database
|
||||||
|
|
||||||
|
Verbindingszinnen zijn **wel onderdeel van de persistent opgeslagen wikidata**.
|
||||||
|
De opslagcode behandelt ze als volgt:
|
||||||
|
|
||||||
|
| Laag | Huidige representatie |
|
||||||
|
| --- | --- |
|
||||||
|
| JavaScript-model | `ConceptMapPhrase`, met eigen lokale `id`, `label` en `synopsis`. |
|
||||||
|
| CMap-document | Een object in `document.items` met `kind: "phrase"`; connectoren verwijzen naar dit item via `sourceId`/`targetId`. |
|
||||||
|
| Database | Het phrase-item, inclusief tekst, blijft staan in de JSONB-kolom `concept_maps.document`. |
|
||||||
|
| Gedeeld conceptregister | `concept_definitions` bevat de gedeelde conceptinhoud. Phrases worden door `concept-placement?` expliciet uitgesloten van conceptplaatsingen. |
|
||||||
|
|
||||||
|
`concept-map-storage-document` verwijdert gedeelde inhoud uit gewone
|
||||||
|
conceptplaatsingen, maar laat phrase-items ongewijzigd. `create-concept-map!`
|
||||||
|
en `update-concept-map!` schrijven dit document naar PostgreSQL. Ook de
|
||||||
|
migraties die gedeelde conceptinhoud uit items verwijderen, behouden
|
||||||
|
expliciet de tekst van phrases.
|
||||||
|
|
||||||
|
De conclusie is daarom: **persistent in het kaartmodel, maar niet als
|
||||||
|
zelfstandig gedeeld concept gemodelleerd**. De tekst staat niet op de
|
||||||
|
connector zelf en wordt niet uitsluitend door de presentatielaag bijgehouden.
|
||||||
|
Een apart `ConceptRelation`-object in de JavaScript-code verandert dit niet
|
||||||
|
automatisch: het aanmaken van een phrase vult die semantische relatietabel
|
||||||
|
momenteel niet.
|
||||||
|
|
||||||
|
Deze vaststelling is gebaseerd op de opslagcode en migraties in deze
|
||||||
|
repository en op de drie exports; er is geen rechtstreekse inspectie van
|
||||||
|
de actieve database uitgevoerd.
|
||||||
|
|
||||||
|
## 2. Structuur van de bundel
|
||||||
|
|
||||||
|
| Veld | Type | Verplicht | Betekenis |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| `$schema` | string | Nee | Verwijzing naar het schema; de exporter schrijft `/schemas/racket-wiki-cmap-bundle-v1.schema.json`. |
|
||||||
|
| `format` | string | Ja | Exact `racket-wiki-cmap-bundle`. |
|
||||||
|
| `formatVersion` | integer | Ja | Exact `1`. Andere versies worden afgewezen. |
|
||||||
|
| `exportedAt` | string | Nee | Exporttijdstip in `date-time`-notatie, bijvoorbeeld `2026-09-18T12:00:00.000Z`. |
|
||||||
|
| `generator` | string | Nee | Naam van de producerende toepassing; standaard `Racket Wiki`. |
|
||||||
|
| `rootCmapSlug` | slug | Ja | Slug van de CMap die na import wordt geopend; MOET voorkomen in `cmaps`. |
|
||||||
|
| `cmaps` | array van CMap-objecten | Ja | Ten minste één CMap; zie § 5. |
|
||||||
|
| `concepts` | array van conceptobjecten | Ja | Gedeelde conceptinhoud; zie § 4. MAG leeg zijn. |
|
||||||
|
| `pages` | array van paginaobjecten | Ja | Meegeleverde wikipagina's; zie § 7. MAG leeg zijn. |
|
||||||
|
| `missing` | object | Nee | Niet geladen afhankelijkheden; zie § 8. |
|
||||||
|
|
||||||
|
De exporter schrijft al deze velden. Op het hoofdniveau zijn andere velden
|
||||||
|
volgens het schema niet toegestaan.
|
||||||
|
|
||||||
|
## 3. Identificatie en verwijzingen
|
||||||
|
|
||||||
|
### 3.1 Slug
|
||||||
|
|
||||||
|
Een slug begint met een Unicode-letter of -cijfer. Daarna zijn ook `.`, `_`
|
||||||
|
en `-` toegestaan. De totale lengte is 1 tot en met 120 tekens, volgens
|
||||||
|
deze JavaScript-reguliere expressie met Unicode-modus:
|
||||||
|
|
||||||
|
```text
|
||||||
|
^[\p{L}\p{N}][\p{L}\p{N}._-]{0,119}$
|
||||||
|
```
|
||||||
|
|
||||||
|
Dit geldt voor CMap-slugs en voor het sluggedeelte van paginaverwijzingen.
|
||||||
|
Een CMap-slug bevat geen dubbele punt. Identiteiten en verwijzingen moeten
|
||||||
|
exact overeenkomen; de bundelvalidator vergelijkt ze hoofdlettergevoelig.
|
||||||
|
|
||||||
|
### 3.2 Paginaverwijzing
|
||||||
|
|
||||||
|
Een paginaverwijzing heeft de vorm `slug` of `namespace:slug`. Beide delen
|
||||||
|
voldoen aan de slugregels, met maximaal 80 tekens voor de namespace.
|
||||||
|
Voorbeelden: `inleiding`, `proces:ontwerp` en `cmap:architectuur`.
|
||||||
|
Het is een wiki-adres, geen URL of bestandsnaam.
|
||||||
|
|
||||||
|
### 3.3 Concept-id
|
||||||
|
|
||||||
|
Een concept-id is een string met één van de volgende vormen:
|
||||||
|
|
||||||
|
| Vorm | Regel | Voorbeeld |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| UUID | Hexadecimale groepen van 8-4-4-4-12 tekens; hoofdletters toegestaan. | `24d27086-9f8b-4b57-a7fb-47b513277555` |
|
||||||
|
| Tijdelijke id | `new:` gevolgd door 1–120 ASCII-tekens; eerst een letter of cijfer, daarna ook `.`, `_` en `-`. | `new:proces` |
|
||||||
|
|
||||||
|
De UUID-controle toetst de tekstvorm, niet de UUID-versie. Gebruik bij voorkeur
|
||||||
|
kleine letters. Externe generators MOGEN tijdelijke id's gebruiken. De server
|
||||||
|
zet nieuwe identiteiten bij opslag om naar UUID's en kan concepten op basis
|
||||||
|
van een reeds bestaande naam aan een bestaande identiteit koppelen (§ 11).
|
||||||
|
|
||||||
|
### 3.4 Lokale item-id
|
||||||
|
|
||||||
|
Een `document.items[].id` is een integer die uniek is binnen zijn CMap.
|
||||||
|
Een andere CMap MAG dezelfde item-id gebruiken. Een item-id identificeert
|
||||||
|
een plaatsing of verbindingszin; een concept-id identificeert gedeelde inhoud.
|
||||||
|
Connectoren verwijzen naar lokale item-id's, nooit rechtstreeks naar concept-id's.
|
||||||
|
|
||||||
|
### 3.5 Benoemde waardetypen
|
||||||
|
|
||||||
|
| Type | JSON-basistype | Nadere typering |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `Slug` | string | Adres volgens § 3.1. |
|
||||||
|
| `PageReference` | string | `slug` of `namespace:slug`, volgens § 3.2. |
|
||||||
|
| `ConceptId` | string | UUID of tijdelijke id volgens § 3.3. |
|
||||||
|
| `ItemId` | integer | Verwijzing binnen één diagram; § 3.4. |
|
||||||
|
| `ConnectorId` | integer | Identiteit binnen de connectoren van één diagram. |
|
||||||
|
| `RelationId` | string | Niet-lege identiteit van een `ConceptRelation`; het model legt geen UUID-patroon op. |
|
||||||
|
| `ContextKey` | string | `root` of de `id` van een interne kaartreferentie, bijvoorbeeld `cmap-7`. |
|
||||||
|
| `CssColor` | string | CSS-kleur; waargenomen zijn hexkleuren zoals `#edf7e8`, de korte vorm `#333` en `transparent`. Geen kleurenenum in het bundelschema. |
|
||||||
|
| `FontSize` | number of string | Huidige model/exportwaarde: getal of CSS-lettergrootte, bijvoorbeeld `"11pt"`, `"9pt"`, `"0.84em"`. Het schema staat op items nu alleen `number` toe. |
|
||||||
|
| `FontFamily` | string | CSS-lettertypefamilie of lijst daarvan, bijvoorbeeld `"Arial, Helvetica, sans-serif"`. |
|
||||||
|
| `FontWeight` | string | CSS-gewicht als tekst, in de export `"400"` of `"700"`; dit zijn geen JSON-getallen. |
|
||||||
|
| `FontStyle` | string | CSS-letterstijl; de voorbeelden bevatten `"normal"` en `"italic"`. Het schema legt geen enum op. |
|
||||||
|
| `HttpUrl` | string | Volledige URL met protocol `http:` of `https:`. |
|
||||||
|
| `UploadUrl` | string | Lokale URL die begint met `/uploads/`. |
|
||||||
|
| `Base64` | string | Gecodeerde bestandsbytes volgens § 7.2. |
|
||||||
|
|
||||||
|
Voor `FontSize` verwerkt de lettergroottehelper getallen en eenheden `pt`,
|
||||||
|
`px`, `em` en `%` bij omzetting naar punten. Dat is geen volledige
|
||||||
|
CSS-validatie door de bundelvalidator. Behoud bij overdracht de oorspronkelijke
|
||||||
|
waarde en eenheid; `"0.84em"` mag niet zonder betekenisverlies `0.84` worden.
|
||||||
|
|
||||||
|
## 4. Gedeelde concepten: `concepts[]`
|
||||||
|
|
||||||
|
| Veld | Type | Verplicht | Betekenis |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| `id` | concept-id | Ja | Unieke identiteit binnen de bundel. |
|
||||||
|
| `label` | string | Ja | Naam; MOET na trimmen niet leeg zijn. |
|
||||||
|
| `synopsis` | string | Nee | Korte beschrijving. |
|
||||||
|
| `aspects` | array van strings | Nee | Aspecten van het concept. |
|
||||||
|
| `tags` | array; model: `ConceptTag[]` | Nee | Concepttags; zie § 4.1. |
|
||||||
|
| `descriptionPageSlug` | string of null; niet-leeg: `PageReference` | Nee | Paginaverwijzing naar conceptuitleg. |
|
||||||
|
| `pageSlug` | string of null; niet-leeg: `PageReference` | Nee | Gekoppelde wikipagina. |
|
||||||
|
| `cmapSlug` | string of null; niet-leeg: `Slug` | Nee | Gekoppelde CMap. |
|
||||||
|
| `externalUrl` | `HttpUrl` of null | Nee | Volledige HTTP- of HTTPS-URL. Een lege string is ongeldig. |
|
||||||
|
| `imageSource` | string of null | Nee | Afbeeldingsbron zoals opgeslagen door het conceptmodel. |
|
||||||
|
|
||||||
|
Andere conceptvelden zijn volgens het schema niet toegestaan. Niet-lege
|
||||||
|
paginaverwijzingen en CMap-verwijzingen MOETEN aan § 3 voldoen. Gebruik voor
|
||||||
|
een ontbrekende verwijzing bij voorkeur weglaten of `null`.
|
||||||
|
|
||||||
|
Conceptnamen MOETEN uniek zijn na trimmen en omzetting naar kleine letters
|
||||||
|
(`toLocaleLowerCase()` in de validator). Ieder concept MOET op ten minste
|
||||||
|
één CMap in de bundel als niet-`phrase`-item geplaatst zijn. Hetzelfde concept
|
||||||
|
MAG meerdere plaatsingen hebben en op meerdere CMaps voorkomen.
|
||||||
|
|
||||||
|
Het schema laat de inhoud van `tags` vrij. Het huidige model gebruikt
|
||||||
|
objecten met `type` en `value`, bijvoorbeeld
|
||||||
|
`{"type":"person","value":"Hans"}` of
|
||||||
|
`{"type":"label","value":"ontwerp"}`. Strings worden omgezet naar
|
||||||
|
tags van type `label`; bij objecten kan `name` als alternatief voor `value`
|
||||||
|
worden gelezen. Paginatags (§ 7) zijn uitsluitend strings.
|
||||||
|
|
||||||
|
### 4.1 Concepttag: `ConceptTag`
|
||||||
|
|
||||||
|
| Veld | Type in model/export | Betekenis |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `type` | string | Tagcategorie, bijvoorbeeld `label` of `person`. Het model bewaart ook andere niet-lege categorienamen; dit is geen gesloten enum. |
|
||||||
|
| `value` | string | Tagwaarde, bijvoorbeeld een label of persoonsnaam. |
|
||||||
|
|
||||||
|
Het model schrijft beide velden. Bij invoer wordt een ontbrekend of leeg
|
||||||
|
`type` aangevuld met `label`. `value` en de compatibiliteitsinvoer `name`
|
||||||
|
worden getrimd. De Modelgids-export bevat alleen lege concepttagarrays;
|
||||||
|
deze elementtypering is daarom ontleend aan het conceptmodel.
|
||||||
|
|
||||||
|
De aanvullende export `rws-dingen-cmap.json` bevat wel gevulde tags,
|
||||||
|
bijvoorbeeld `{"type":"person","value":"Hans"}`. Daarmee bevestigt die
|
||||||
|
export de objectstructuur. `aspects` bevat daar onder meer `"TODO"`,
|
||||||
|
`"Todo"` en `"todo"`: het is een array van vrije strings, geen enum en geen
|
||||||
|
lijst van `ConceptTag`-objecten. Het model schrijft deze strings niet naar
|
||||||
|
één vaste schrijfwijze om.
|
||||||
|
|
||||||
|
Bij opslag in het gedeelde conceptregister bewaart de huidige server via
|
||||||
|
`concept-content` uitsluitend concepttags met `type: "person"`. Andere
|
||||||
|
tagtypen kunnen dus door het JSON Schema en het JavaScript-model worden
|
||||||
|
geaccepteerd zonder na opslag behouden te blijven. Voor gewone aspecten
|
||||||
|
staat het afzonderlijke veld `aspects` ter beschikking.
|
||||||
|
|
||||||
|
## 5. CMaps: `cmaps[]`
|
||||||
|
|
||||||
|
| Veld | Type | Verplicht | Betekenis |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| `slug` | slug | Ja | Uniek CMap-adres binnen de bundel. |
|
||||||
|
| `title` | string | Ja | Titel; MOET na trimmen niet leeg zijn. |
|
||||||
|
| `document` | object | Ja | Diagramdocument volgens onderstaande tabel. |
|
||||||
|
|
||||||
|
Andere velden op dit CMap-object zijn volgens het schema niet toegestaan.
|
||||||
|
|
||||||
|
### 5.1 Diagramdocument
|
||||||
|
|
||||||
|
| Veld | Type | Verplicht | Betekenis |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| `schemaVersion` | integer | Nee | Versie van het diagrammodel; het huidige model gebruikt standaard `2`. Dit is onafhankelijk van `formatVersion`. |
|
||||||
|
| `metadata` | object | Nee | CMap-metadata; zie hieronder. |
|
||||||
|
| `derivedView` | object | Nee | Verwijzing naar een afgeleide weergave; zie § 5.2. |
|
||||||
|
| `concepts` | array van `{ "id": concept-id }` | Ja | Verwijzingen naar de gedeelde concepttabel; geen conceptinhoud. Id's MOETEN binnen deze array uniek zijn. |
|
||||||
|
| `items` | array van items | Ja | Plaatsingen en verbindingszinnen; zie § 6. |
|
||||||
|
| `connectors` | array van connectoren | Ja | Diagramverbindingen; zie § 6.2. |
|
||||||
|
| `conceptMaps` | array; model: `MapReference[]` | Nee | Interne kaartreferenties volgens § 6.4; leeg in de Modelgids-export en gevuld in de twee aanvullende exports. |
|
||||||
|
| `conceptRelations` | model: `ConceptRelation[]` | Nee | Semantische relaties tussen concepten; modeluitbreiding volgens § 5.3. |
|
||||||
|
| `conceptOwnerships` | model: `ConceptOwnership[]` | Nee | Semantische ouder-kindrelaties; modeluitbreiding volgens § 5.3. |
|
||||||
|
| `viewport` | object | Nee | Toegestaan door het schema; het huidige model bewaart dit niet bij import. |
|
||||||
|
|
||||||
|
Een lege CMap is toegestaan: de drie verplichte arrays mogen leeg zijn.
|
||||||
|
Gebruik bij voorkeur een `document.concepts`-verwijzing voor ieder geplaatst
|
||||||
|
concept. De importer verzamelt ook concept-id's rechtstreeks uit de items.
|
||||||
|
|
||||||
|
Het huidige model gebruikt de volgende metadata:
|
||||||
|
|
||||||
|
| Veld | Gebruikelijk type | Betekenis |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `namespace` | string | Namespace van de kaart. |
|
||||||
|
| `tags` | array van strings | Kaarttags. |
|
||||||
|
| `summary` | string | Samenvatting. |
|
||||||
|
| `explanationPageSlug` | string | Paginaverwijzing naar kaartuitleg, of `""` indien afwezig. |
|
||||||
|
|
||||||
|
Het schema staat extra velden toe op `document` en `metadata`. Dat garandeert
|
||||||
|
niet dat de importer onbekende velden bewaart: het diagrammodel wordt opnieuw
|
||||||
|
opgebouwd. Modeluitbreidingen zoals `conceptRelations` en `conceptOwnerships`
|
||||||
|
vallen onder deze open documentstructuur. Hun huidige modeltypen worden
|
||||||
|
hieronder beschreven; het bundelschema specificeert of valideert die
|
||||||
|
interne structuur niet.
|
||||||
|
|
||||||
|
### 5.2 Afgeleide CMap: `derivedView`
|
||||||
|
|
||||||
|
| Veld | Type | Verplicht | Betekenis |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| `sourceCmapSlug` | slug | Ja | Bron-CMap van de afgeleide weergave. |
|
||||||
|
| `rootItemId` | integer | Ja | Lokaal item in de bron-CMap dat de wortel van de weergave vormt. |
|
||||||
|
|
||||||
|
Extra velden zijn hier niet toegestaan. Voor een bruikbare afgeleide weergave
|
||||||
|
moeten bronkaart en wortelitem beschikbaar zijn. De exporter probeert de
|
||||||
|
bronkaart ook bij exportdiepte `0` mee te nemen. De browservalidator controleert
|
||||||
|
het bestaan van deze bron en dit item niet.
|
||||||
|
|
||||||
|
De export `rws-lbs-architectuur-cmap.json` bevat vijf concrete afgeleide
|
||||||
|
kaarten (§ 13.3). Hun `concepts`, `items` en `connectors` zijn lege arrays:
|
||||||
|
de bronkaart levert de diagraminhoud. Een lege lokale itemarray betekent bij
|
||||||
|
een `derivedView` dus niet dat de zichtbare kaart geen inhoud heeft.
|
||||||
|
|
||||||
|
### 5.3 Semantische relaties en eigenaarschap in het model
|
||||||
|
|
||||||
|
`ConceptRelation` is het elementtype van `document.conceptRelations`:
|
||||||
|
|
||||||
|
| Veld | Type in model/export | Betekenis |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `id` | `RelationId` | Identiteit van de relatie, onafhankelijk van een lokale connector-id. |
|
||||||
|
| `sourceConceptId` | `ConceptId` | Bronconcept. |
|
||||||
|
| `targetConceptId` | `ConceptId` | Doelconcept. |
|
||||||
|
| `label` | string | Relatietekst; standaard `""`. Er is hier nog geen verwijzing naar een concept dat de verbindingszin vertegenwoordigt. |
|
||||||
|
| `tags` | `ConceptTag[]` | Relatietags; standaard `[]`. |
|
||||||
|
|
||||||
|
Het model schrijft alle vijf velden. Voor constructie zijn een niet-lege
|
||||||
|
id, bron en doel nodig. De repository controleert dat bron en doel in de
|
||||||
|
concepten van het opgebouwde kaartmodel voorkomen. Dit is een latere
|
||||||
|
modelcontrole, niet een controle van `validateBundle`.
|
||||||
|
|
||||||
|
`ConceptOwnership` is het elementtype van `document.conceptOwnerships`:
|
||||||
|
|
||||||
|
| Veld | Type in model/export | Betekenis |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `parentConceptId` | `ConceptId` | Semantisch ouderconcept. |
|
||||||
|
| `childConceptId` | `ConceptId` | Semantisch kindconcept. |
|
||||||
|
|
||||||
|
Beide velden zijn nodig. De repository vereist bestaande, verschillende
|
||||||
|
concepten en wijst cyclisch eigenaarschap af. Zij bewaart één ouder per kind.
|
||||||
|
Dit eigenaarschap is iets anders dan de plaatsing onder `parentSubmapId`.
|
||||||
|
Een verbindingszin met het label `omvat` creëert niet automatisch een
|
||||||
|
`ConceptOwnership`. Beide arrays ontbreken in de Modelgids-export.
|
||||||
|
|
||||||
|
## 6. Diagramitems en connectoren
|
||||||
|
|
||||||
|
### 6.1 Items: `cmaps[].document.items[]`
|
||||||
|
|
||||||
|
| Veld | Type volgens schema | Nadere typering in model/export | Verplicht volgens schema |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| `id` | integer | `ItemId`, lokale identiteit van de plaatsing. | Ja |
|
||||||
|
| `x`, `y` | number | Diagramcoördinaten; negatieve waarden en decimalen toegestaan. | Ja |
|
||||||
|
| `kind` | enum van strings | `concept`, `page`, `submap` of `phrase`; standaard `concept`. | Nee |
|
||||||
|
| `conceptId` | concept-id | `ConceptId` bij conceptplaatsingen; bij `phrase` exporteert het model `null`. | Tenzij `kind = "phrase"` |
|
||||||
|
| `label` | string | Tekst van de huidige phrase-representatie; conceptplaatsingen halen de naam uit `concepts`. | Bij `kind = "phrase"` |
|
||||||
|
| `width`, `height` | number | Afmetingen in diagramcoördinaten. | Nee |
|
||||||
|
| `parentSubmapId` | integer of null | `ItemId` van de bovenliggende submap, of `null`. | Nee |
|
||||||
|
| `hidden` | boolean | Niet bewaard door het huidige model; dit gebruikt `hiddenContexts`. | Nee |
|
||||||
|
| `backgroundColor`, `borderColor`, `textColor` | string | `CssColor`. | Nee |
|
||||||
|
| `fontFamily` | string | `FontFamily`. | Nee |
|
||||||
|
| `fontWeight` | string | `FontWeight`. | Nee |
|
||||||
|
| `fontStyle` | string | `FontStyle`. | Nee |
|
||||||
|
| `fontSize`, `synopsisFontSize` | number | `FontSize`; in de Modelgids-export strings met eenheid. | Nee |
|
||||||
|
| `synopsisFontWeight` | string | `FontWeight` voor de synopsis. | Nee |
|
||||||
|
| `synopsisFontStyle` | string | `FontStyle` voor de synopsis. | Nee |
|
||||||
|
| `submapBackgroundColor`, `submapBorderColor` | string | `CssColor of null`; in de Modelgids-export steeds `null`. | Nee |
|
||||||
|
|
||||||
|
De laatste twee verschillen — lettergroottes als strings en nullable
|
||||||
|
submapkleuren — worden door de browser geaccepteerd, maar vallen buiten de
|
||||||
|
huidige veldtypen van het schema (§ 12).
|
||||||
|
|
||||||
|
Een `phrase`-item is de huidige diagramrepresentatie van een verbindingszin;
|
||||||
|
het vereist in versie 1 geen gedeeld conceptobject. Dit beschrijft de opslag,
|
||||||
|
niet de bedoelde conceptsemantiek (§ 1.2). Voor schema-conforme versie-1-invoer
|
||||||
|
BEHOORT `conceptId` op een `phrase` weggelaten te worden; de huidige exporter
|
||||||
|
schrijft daar zelf `null`.
|
||||||
|
|
||||||
|
Bij conceptplaatsingen wordt gedeelde inhoud zoals `label`, `synopsis`,
|
||||||
|
`aspects`, `tags` en links door de exporter van het item verwijderd.
|
||||||
|
Die inhoud staat uitsluitend in de gedeelde concepttabel.
|
||||||
|
|
||||||
|
Extra itemvelden zijn toegestaan door het schema. Hun modeltypen staan in
|
||||||
|
§ 6.3–6.5. Behoud deze velden bij bewerking van een bestaande export om
|
||||||
|
diagramgedrag en opmaak zo veel mogelijk te behouden.
|
||||||
|
|
||||||
|
### 6.2 Connectoren: `cmaps[].document.connectors[]`
|
||||||
|
|
||||||
|
| Veld | Type | Verplicht volgens schema | Betekenis |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| `id` | `ConnectorId` (integer) | Nee | Lokale connector-id; de huidige importer vereist deze wel. |
|
||||||
|
| `sourceId` | `ItemId` (integer) | Ja | Bestaande item-id in dezelfde CMap. |
|
||||||
|
| `targetId` | `ItemId` (integer) | Ja | Bestaande item-id in dezelfde CMap. |
|
||||||
|
| `hasArrow` | boolean | Nee | Pijlpunt; standaard `true` in het model. |
|
||||||
|
| `relationId` | model: `RelationId` (string) | Nee, open uitbreiding | Koppeling naar een semantische relatie; ontbreekt in de Modelgids-export. |
|
||||||
|
| `lineColor` | model: `CssColor` (string) | Nee, open uitbreiding | Lijnkleur; standaard `"#333"`. |
|
||||||
|
| `lineWidth` | model: number | Nee, open uitbreiding | Lijndikte; standaard `2`. |
|
||||||
|
|
||||||
|
Extra velden zijn toegestaan. Lever iedere
|
||||||
|
connector met een unieke integer-`id` binnen zijn kaart aan voor succesvolle
|
||||||
|
import. Connector-id's en item-id's hebben afzonderlijke verzamelingen.
|
||||||
|
|
||||||
|
Een connector is één getekend lijnstuk. Bij een constructie
|
||||||
|
`bronconcept → phrase → doelconcept` zijn er twee connectoren voor één
|
||||||
|
semantische uitspraak. Een phrase kan meerdere inkomende of uitgaande
|
||||||
|
connectoren hebben. `hasArrow: false` onderdrukt de pijlpunt; `sourceId` en
|
||||||
|
`targetId` blijven de geregistreerde bron en het doel van dat lijnstuk.
|
||||||
|
|
||||||
|
De exporter verwijdert connectoren waarvan een eindpunt niet meer bestaat.
|
||||||
|
De importer wijst zulke connectoren af als ze toch in het bestand staan.
|
||||||
|
|
||||||
|
### 6.3 Aanvullende itemvelden
|
||||||
|
|
||||||
|
Deze velden vallen onder `additionalProperties: true` van het itemschema.
|
||||||
|
Onderstaande typen beschrijven het huidige model en de editor; de
|
||||||
|
bundelvalidator dwingt deze nadere typering niet af.
|
||||||
|
|
||||||
|
| Veld | Type in model/export | Betekenis en waarneming in de Modelgids-export |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `synopsis` | string | Phrase-eigen toelichting in de huidige representatie; bij `omvat` is dit `""`. Voor concepten staat deze inhoud in de gedeelde tabel. |
|
||||||
|
| `parentCmapLink` | boolean | Markering van een plaatsing als terugkoppeling naar een bovenliggende kaart; hier overal `false`. |
|
||||||
|
| `groupId` | string of null | Groepsidentiteit voor plaatsingen; hier `null`. Door de editor gebruikte vorm: `group-<nummer>`. |
|
||||||
|
| `childMap` | string of null | Naam van een onderliggende kaart/submap; hier `null`. Dit is geen ingebed diagramdocument. |
|
||||||
|
| `submapDepth` | integer | Nestingsniveau in de editor, met `0` voor het hoofdniveau; hier overal `0`. Het schema specificeert dit veld niet. |
|
||||||
|
| `expanded` | boolean | Of de submap uitgeklapt is; hier `false`. |
|
||||||
|
| `submapInitialized` | boolean | Of de submapinhoud is geïnitialiseerd; hier `false`. |
|
||||||
|
| `separateMap` | boolean | Of de submap een afzonderlijke interne kaartreferentie heeft; hier `false`. |
|
||||||
|
| `mapReference` | `MapReference` of null | Interne kaartreferentie volgens § 6.4; hier `null`. |
|
||||||
|
| `hiddenContexts` | `ContextKey[]` | Contexten waarin de plaatsing verborgen is; hier `[]`. |
|
||||||
|
| `layouts` | `Record<ContextKey, Layout>` | Opgeslagen plaatsing en opmaak per context; hier steeds een object met sleutel `root`. Zie § 6.5. |
|
||||||
|
| `autoWidth`, `autoHeight` | boolean | Automatische bepaling van breedte respectievelijk hoogte. Beide blijven booleans, ook als `width` en `height` zijn ingevuld. |
|
||||||
|
| `synopsisTextColor` | `CssColor` | Tekstkleur van de synopsis. |
|
||||||
|
| `synopsisFontFamily` | `FontFamily` | Lettertypefamilie van de synopsis. |
|
||||||
|
|
||||||
|
Alleen `null` in een export toont niet welk niet-null type mogelijk is.
|
||||||
|
De typering van `groupId`, `childMap` en `mapReference` is daarom aangevuld
|
||||||
|
vanuit de editorcode. De twee aanvullende exports bevestigen `childMap` als
|
||||||
|
string en `mapReference` als object. Ze bevatten ook integerwaarden voor
|
||||||
|
`parentSubmapId`, submapdieptes groter dan nul en daadwerkelijke kleuren voor
|
||||||
|
de nullable submapkleurvelden. `groupId` blijft in alle drie voorbeelden
|
||||||
|
`null`; `hiddenContexts` blijft steeds een lege array.
|
||||||
|
|
||||||
|
### 6.4 Interne kaartreferentie: `MapReference`
|
||||||
|
|
||||||
|
Dit is het objecttype voor `item.mapReference` en de elementen van
|
||||||
|
`document.conceptMaps`. De submapcontroller maakt de volgende structuur:
|
||||||
|
|
||||||
|
| Veld | Type in model/export | Betekenis |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `id` | string | Interne referentie-id, door de editor opgebouwd als `cmap-<ItemId>`. Ook bruikbaar als `ContextKey`; geen opgeslagen CMap-slug. |
|
||||||
|
| `title` | string | Titel van de interne kaart. |
|
||||||
|
| `rootItemId` | `ItemId` | Wortelitem binnen het diagram. |
|
||||||
|
| `itemIds` | `ItemId[]` | Items die onder die wortel vallen. |
|
||||||
|
|
||||||
|
Deze structuur verschilt van `derivedView`: een afgeleide opgeslagen kaart
|
||||||
|
gebruikt een `sourceCmapSlug` om een andere opgeslagen CMap aan te wijzen.
|
||||||
|
In de Modelgids-export is `conceptMaps` leeg en is ieder `mapReference`
|
||||||
|
`null`; de structuur hierboven is ontleend aan de model- en controllercode.
|
||||||
|
De twee aanvullende exports bevatten deze structuur daadwerkelijk, onder
|
||||||
|
meer de referentie `cmap-23` naar de submap `RWS TODO` (§ 13.2).
|
||||||
|
|
||||||
|
`itemIds` is een opgeslagen lijst van lokale verwijzingen. De huidige
|
||||||
|
bundelvalidator controleert die lijst niet op volledigheid of overeenstemming
|
||||||
|
met `parentSubmapId`. Ook in de voorbeelden zijn zulke lijsten niet altijd
|
||||||
|
actueel. Gebruik ze daarom niet als de enige bron voor de submapstructuur;
|
||||||
|
het huidige model bepaalt afstammelingen via `parentSubmapId`.
|
||||||
|
|
||||||
|
### 6.5 Layout per context: `Layout`
|
||||||
|
|
||||||
|
De export bevat bijvoorbeeld `items[0].layouts.root`. `root` is hier een
|
||||||
|
objectsleutel van type `ContextKey`, geen vast veld in elk layoutobject.
|
||||||
|
Iedere waarde in `layouts` heeft de volgende structuur:
|
||||||
|
|
||||||
|
| Veld | Type in model/export | Voorbeeld uit de Modelgids-export |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `x`, `y` | number | `33`, `75`, `152.66666666666669` |
|
||||||
|
| `width`, `height` | number | `380`, `76` |
|
||||||
|
| `backgroundColor`, `borderColor`, `textColor` | `CssColor` | `"#edf7e8"`, `"#57834a"`, `"#222222"`; bij de phrase ook `"transparent"` als randkleur |
|
||||||
|
| `fontFamily` | `FontFamily` | `"Arial, Helvetica, sans-serif"` |
|
||||||
|
| `fontSize` | `FontSize` | `"11pt"` |
|
||||||
|
| `fontWeight` | `FontWeight` | `"700"` |
|
||||||
|
| `fontStyle` | `FontStyle` | `"normal"` |
|
||||||
|
| `synopsisTextColor` | `CssColor` | `"#4d4d4d"` |
|
||||||
|
| `synopsisFontFamily` | `FontFamily` | `"Arial, Helvetica, sans-serif"` |
|
||||||
|
| `synopsisFontSize` | `FontSize` | `"9pt"`; bij de phrase `"0.84em"` |
|
||||||
|
| `synopsisFontWeight` | `FontWeight` | `"400"`; bij de phrase `"700"` |
|
||||||
|
| `synopsisFontStyle` | `FontStyle` | `"normal"` |
|
||||||
|
|
||||||
|
Dit zijn de velden die de layoutcontroller vastlegt. Het bundelschema legt
|
||||||
|
geen verplichte deelvelden of typen voor `Layout` vast. De directe
|
||||||
|
itemvelden beschrijven de plaatsing; de contextlayout bevat een opgeslagen
|
||||||
|
weergave daarvan. Bij openen van een context past de editor de bijbehorende
|
||||||
|
layout toe. Wie coördinaten of opmaak in een bestaande export wijzigt,
|
||||||
|
moet dus ook de relevante contextlayout consistent aanpassen.
|
||||||
|
|
||||||
|
De aanvullende exports bevatten behalve `root` onder meer `cmap-23`,
|
||||||
|
`cmap-26` en `cmap-89` als contexten. Ook afmetingen kunnen decimalen bevatten,
|
||||||
|
bijvoorbeeld `width: 180.888916015625`. Gebruik voor alle vier geometrievelden
|
||||||
|
dus `number`, niet `integer`. Een contextkey is lokaal aan zijn diagram;
|
||||||
|
dezelfde tekst in twee verschillende CMaps maakt de contexten niet identiek.
|
||||||
|
|
||||||
|
## 7. Wikipagina's en bijlagen
|
||||||
|
|
||||||
|
### 7.1 Pagina: `pages[]`
|
||||||
|
|
||||||
|
| Veld | Type | Verplicht | Betekenis |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| `reference` | paginaverwijzing | Ja | Uniek pagina-adres binnen de bundel, inclusief eventuele namespace. |
|
||||||
|
| `title` | string | Ja | Titel; MOET na trimmen niet leeg zijn. |
|
||||||
|
| `markdown` | string | Ja | Actuele Markdown-bron; MAG leeg zijn. |
|
||||||
|
| `tags` | array van strings | Ja | Paginatags; MAG leeg zijn. |
|
||||||
|
| `attachments` | array van bijlagen | Nee | Ingebedde bestanden; ontbrekend betekent geen meegeleverde bijlagen. |
|
||||||
|
|
||||||
|
Andere paginavelden zijn volgens het schema niet toegestaan. Bundels van vóór
|
||||||
|
de toevoeging van bijlagen blijven geldig zonder wijziging van `formatVersion`.
|
||||||
|
|
||||||
|
### 7.2 Bijlage: `pages[].attachments[]`
|
||||||
|
|
||||||
|
| Veld | Type | Verplicht | Betekenis |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| `url` | `UploadUrl` (string) | Ja | Oorspronkelijke lokale URL, beginnend met `/uploads/`; uniek binnen de pagina. |
|
||||||
|
| `name` | string | Ja | Niet-lege bestandsnaam. |
|
||||||
|
| `mimeType` | string | Ja | Niet-leeg MIME-type, bijvoorbeeld `image/png`. |
|
||||||
|
| `contentBase64` | `Base64` (string) | Ja | Bestandsbytes als standaard Base64. |
|
||||||
|
|
||||||
|
Andere bijlagevelden zijn niet toegestaan. Base64 gebruikt `A–Z`, `a–z`,
|
||||||
|
`0–9`, `+`, `/` en waar nodig afsluitende `=`-padding. Witruimte, regeleinden
|
||||||
|
en een `data:`-prefix zijn niet toegestaan. Een lege string vertegenwoordigt
|
||||||
|
een leeg bestand en wordt door de bundelvalidator geaccepteerd.
|
||||||
|
|
||||||
|
Bij import worden bestanden opnieuw geüpload onder de betreffende pagina.
|
||||||
|
De oorspronkelijke `url` dient als vervangsleutel: voorkomens in de Markdown
|
||||||
|
worden vervangen door de nieuwe upload-URL. Bestandsnamen en URL's hoeven na
|
||||||
|
import dus niet identiek te zijn aan de export.
|
||||||
|
|
||||||
|
## 8. Ontbrekende afhankelijkheden: `missing`
|
||||||
|
|
||||||
|
| Veld | Type | Verplicht | Betekenis |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| `cmaps` | array van slugs | Nee | CMaps waarvoor het laden tijdens export is mislukt. |
|
||||||
|
| `pages` | array van niet-lege strings | Nee | Paginaverwijzingen waarvoor export is mislukt. |
|
||||||
|
|
||||||
|
Extra velden zijn niet toegestaan. De exporter schrijft beide arrays, ook
|
||||||
|
als ze leeg zijn. Een mislukte bijlage-export laat de hele betreffende pagina
|
||||||
|
uit `pages` weg en vermeldt haar verwijzing in `missing.pages`.
|
||||||
|
|
||||||
|
`missing` bevat geen vervangende inhoud. De importer maakt voor deze records
|
||||||
|
geen lege pagina's of kaarten aan en probeert ze niet alsnog op te halen.
|
||||||
|
Een CMap die uitsluitend wegens de gekozen dieptelimiet niet is meegenomen,
|
||||||
|
wordt niet als ontbrekend vermeld.
|
||||||
|
|
||||||
|
## 9. Aanvullende validatieregels
|
||||||
|
|
||||||
|
Naast de veldtypen gelden de volgende controles in `validateBundle`:
|
||||||
|
|
||||||
|
1. CMap-slugs, pagina-adressen en gedeelde concept-id's MOETEN binnen hun
|
||||||
|
eigen verzameling uniek zijn. Conceptnamen voldoen bovendien aan § 4.
|
||||||
|
2. `rootCmapSlug` MOET exact naar een meegeleverde CMap verwijzen.
|
||||||
|
3. Iedere `document.concepts[].id` en iedere niet-`phrase`-`conceptId` MOET
|
||||||
|
bestaan in de gedeelde concepttabel.
|
||||||
|
4. Elk gedeeld concept MOET ten minste één niet-`phrase`-plaatsing hebben.
|
||||||
|
Een vermelding in alleen `document.concepts` is onvoldoende.
|
||||||
|
5. Item-id's MOETEN per kaart uniek zijn; alle connector-eindpunten MOETEN
|
||||||
|
binnen dezelfde kaart bestaan.
|
||||||
|
6. Iedere niet-lege `pageSlug`, `descriptionPageSlug` en
|
||||||
|
`metadata.explanationPageSlug` MOET voorkomen als `pages[].reference`
|
||||||
|
of als exacte verwijzing in `missing.pages`.
|
||||||
|
7. Bijlage-URL's MOETEN per pagina uniek zijn en hun inhoud MOET aan de
|
||||||
|
Base64-regel voldoen.
|
||||||
|
|
||||||
|
Een gekoppelde `cmapSlug` hoeft niet in `cmaps` of `missing.cmaps` voor te
|
||||||
|
komen: export kan bewust op een bepaalde diepte stoppen. Ook extra pagina's
|
||||||
|
zonder verwijzing vanuit een concept of kaart zijn toegestaan.
|
||||||
|
|
||||||
|
Er is geen controle dat iedere upload-URL in Markdown een bijlage heeft,
|
||||||
|
noch dat iedere meegeleverde bijlage daadwerkelijk wordt gebruikt. Voor een
|
||||||
|
zelfstandige overdracht BEHOORT de generator alle benodigde lokale bestanden
|
||||||
|
mee te leveren.
|
||||||
|
|
||||||
|
## 10. Selectie tijdens export
|
||||||
|
|
||||||
|
De normale JSON-export slaat eerst openstaande kaartwijzigingen op en neemt
|
||||||
|
de gekozen wortelkaart mee. De ingestelde volgdiepte wordt begrensd op
|
||||||
|
`0` tot en met `10`; standaard is `0`.
|
||||||
|
|
||||||
|
- Diepte `0` exporteert de wortelkaart en haar pagina-afhankelijkheden.
|
||||||
|
- Een gevolgde `cmapSlug` van een geplaatst concept verhoogt de diepte met één.
|
||||||
|
- De bron van een `derivedView` wordt op dezelfde diepte geladen, ook als
|
||||||
|
de dieptelimiet al is bereikt.
|
||||||
|
- Iedere CMap-slug wordt hoogstens één keer bezocht, zodat cycli niet tot
|
||||||
|
eindeloze recursie leiden. De huidige implementatie volgt diepte-eerst;
|
||||||
|
de eerste bezochte route bepaalt de verdere verwerking van een kaart.
|
||||||
|
- De exporter verzamelt `pageSlug` en `descriptionPageSlug` van geplaatste
|
||||||
|
concepten, plus `metadata.explanationPageSlug` van meegenomen kaarten.
|
||||||
|
- Gewone links in de Markdown van die pagina's worden niet recursief gevolgd.
|
||||||
|
- Herkende lokale `/uploads/`-verwijzingen in Markdown en `src`/`href`-attributen
|
||||||
|
worden als bijlagen ingebed, eenmaal per URL per pagina. Externe bestanden
|
||||||
|
en `imageSource` worden niet zelfstandig als bijlage opgehaald.
|
||||||
|
|
||||||
|
Bij gelijke concept-id's verzamelt de bundelbouwer de eerst aangetroffen
|
||||||
|
conceptinhoud. In normale exports komt die inhoud uit het gedeelde conceptmodel.
|
||||||
|
De resulterende bundel wordt vóór teruggave met `validateBundle` gecontroleerd.
|
||||||
|
|
||||||
|
## 11. Importgedrag en limieten
|
||||||
|
|
||||||
|
De browser leest en valideert het geselecteerde bestand vóór de importwrites.
|
||||||
|
De maximale bestandsgrootte is **256 MiB** (`268435456` bytes), inclusief
|
||||||
|
JSON en Base64. Een afzonderlijke gedecodeerde bijlage mag maximaal
|
||||||
|
**50 MiB** (`52428800` bytes) bevatten.
|
||||||
|
|
||||||
|
De server begrenst daarnaast ieder geserialiseerd CMap-opslagdocument op
|
||||||
|
**10 MiB** (`10485760` bytes). De bestandsgroottegrens van de bundel vervangt
|
||||||
|
deze afzonderlijke opslaggrens niet.
|
||||||
|
|
||||||
|
Conflicten worden bepaald op `pages[].reference` en `cmaps[].slug` ten
|
||||||
|
opzichte van de geladen catalogi. De gebruiker kiest voor vervangen of
|
||||||
|
overslaan van bestaande records. Nieuwe records worden in beide gevallen
|
||||||
|
geïmporteerd. Overslaan van een pagina slaat ook haar bijlagen over.
|
||||||
|
|
||||||
|
De importer verwerkt eerst pagina's en daarna CMaps, telkens in arrayvolgorde.
|
||||||
|
Bij een nieuwe pagina met bijlagen wordt eerst de pagina aangemaakt, daarna
|
||||||
|
worden bestanden geüpload en wordt de Markdown met nieuwe URL's opgeslagen.
|
||||||
|
Bij een bestaande pagina worden de bestanden vóór de pagina-update geüpload.
|
||||||
|
Pagina-updates gebruiken `baseVersion`; CMap-updates laden de bestaande kaart
|
||||||
|
en slaan via de repository op.
|
||||||
|
|
||||||
|
Voor iedere CMap voegt de importer de gedeelde conceptinhoud weer samen met
|
||||||
|
de lokale plaatsingen en bouwt een `CmapModel`. De server normaliseert
|
||||||
|
conceptidentiteiten. Bij gelijke namen na trimmen en omzetting naar kleine
|
||||||
|
letters kan een bestaande conceptidentiteit worden gebruikt. Als daarbij de
|
||||||
|
id verandert naar die van een bestaand concept, kan de bestaande inhoud
|
||||||
|
worden behouden. Bij updates van gedeelde conceptinhoud kunnen ook andere
|
||||||
|
kaarten met datzelfde concept de gewijzigde inhoud tonen.
|
||||||
|
|
||||||
|
De overdracht is geen enkele database-transactie voor de gehele bundel.
|
||||||
|
Een fout tijdens upload, modelopbouw of opslag kan optreden nadat eerdere
|
||||||
|
records al zijn geïmporteerd. De grens van 50 MiB wordt pas bij het decoderen
|
||||||
|
voor upload gecontroleerd. Geldige bundelvalidatie garandeert daarom niet dat
|
||||||
|
alle vervolgstappen slagen. Na succesvolle import worden de catalogi vernieuwd
|
||||||
|
en wordt `rootCmapSlug` geopend. Versiegeschiedenis uit de bron wordt niet
|
||||||
|
hersteld; de doelwiki legt normale nieuwe versies vast.
|
||||||
|
|
||||||
|
## 12. Bekende verschillen tussen schema en uitvoering
|
||||||
|
|
||||||
|
Deze punten beschrijven het huidige gedrag, geen uitbreiding van het schema:
|
||||||
|
|
||||||
|
| Onderwerp | JSON Schema | Huidige uitvoering |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| Validatiemethode | Volledige structurele veldregels. | De importer roept `validateBundle` aan en laadt het schema niet. |
|
||||||
|
| Onbekende velden | Op meerdere objecttypen verboden. | De browservalidator wijst onbekende velden niet algemeen af. Het model kan ze vervolgens weglaten. |
|
||||||
|
| Exportmetadata | Typen voor `$schema`, `exportedAt` en `generator`; `date-time` voor het tijdstip. | Deze velden worden niet door `validateBundle` getoetst. |
|
||||||
|
| Documentarrays | `concepts`, `items` en `connectors` verplicht. | Ontbrekende of niet-array waarden worden in meerdere validatorlussen als lege arrays behandeld. |
|
||||||
|
| Getallen | JSON-getallen vereist. | De validator gebruikt bij item-id's, posities en connector-eindpunten `Number(...)`, waardoor sommige andere JSON-typen de controle kunnen passeren. |
|
||||||
|
| Verbindingszin | Indien aanwezig moet `conceptId` een geldige concept-id zijn. | Het huidige model exporteert bij `phrase` expliciet `conceptId: null`; de browser accepteert dit, het schema niet. |
|
||||||
|
| Lettergroottes | `fontSize` en `synopsisFontSize` op items zijn `number`. | De Modelgids-export bevat `"11pt"`, `"9pt"` en `"0.84em"`; model en browservalidator accepteren die strings. |
|
||||||
|
| Submapkleuren | `submapBackgroundColor` en `submapBorderColor` zijn `string`. | De Modelgids-export bevat expliciet `null`; model en browservalidator accepteren dit. |
|
||||||
|
| Connector-id | Optioneel. | `CmapModel` vereist een integer-id en wijst dubbele connector-id's af, pas bij de modelopbouw tijdens import. |
|
||||||
|
| Optionele velden | Onder meer typen voor `kind`, `label`, opmaak en conceptinhoud. | Niet al deze typen en verplichte conditionele velden worden door `validateBundle` gecontroleerd. |
|
||||||
|
| Submapstructuur | `parentSubmapId` heeft een type; `derivedView` heeft veldregels. | De bundelvalidator controleert geen submapcycli, ontbrekende ouders of het bestaan van de afgeleide bron/wortel. |
|
||||||
|
| Behoud van velden | Open uitbreiding van document, items en connectoren; onder meer `viewport` en `hidden` toegestaan. | Het huidige model serialiseert alleen ondersteunde velden; `viewport` en itemveld `hidden` worden niet bewaard. |
|
||||||
|
|
||||||
|
De Modelgids-export voldoet dus niet volledig aan het gepubliceerde
|
||||||
|
JSON Schema, hoewel de huidige bundelvalidator hem accepteert. Het schema
|
||||||
|
zou onder meer de lettergroottes, nullable submapkleuren en de bestaande
|
||||||
|
phrase-representatie moeten afstemmen op de uitvoering. Dat staat los van
|
||||||
|
de verdere domeinwijziging om verbindingszinnen als gedeelde concepten te
|
||||||
|
modelleren (§ 1.2).
|
||||||
|
|
||||||
|
Voor een nieuwe externe generator: voldoe aan het schema én § 9, lever unieke
|
||||||
|
connector-id's, laat `conceptId` bij verbindingszinnen weg en gebruik de
|
||||||
|
gedocumenteerde veldtypen. Reken niet op een byte-identieke export na import.
|
||||||
|
|
||||||
|
## 13. Voorbeelden
|
||||||
|
|
||||||
|
### 13.1 Analyse van de aangeleverde Modelgids-export
|
||||||
|
|
||||||
|
Bronbestand: [modelgids-lts-opzet-cmap.json](wiki-data/modelgids-lts-opzet-cmap.json).
|
||||||
|
De export vermeldt generator `Racket Wiki 0.2.122` en tijdstip
|
||||||
|
`2026-09-18T13:35:14.928Z`.
|
||||||
|
|
||||||
|
| Onderdeel | Aantal / waarde |
|
||||||
|
| --- | --- |
|
||||||
|
| CMaps | 1: `modelgids-lts-opzet` |
|
||||||
|
| Gedeelde concepten | 15: het hoofdconcept en 14 hoofdstukconcepten |
|
||||||
|
| Diagramitems | 16: 15 conceptplaatsingen en 1 phrase-item |
|
||||||
|
| Phrase | Item `2`, label `omvat`, `conceptId: null` |
|
||||||
|
| Connectoren | 15: één lijnstuk van item `1` naar phrase `2`, veertien van phrase `2` naar items `3` t/m `16` |
|
||||||
|
| Wikipagina's | 15: veertien conceptuitlegpagina's en de CMap-uitlegpagina |
|
||||||
|
| Bijlagen | 12, alle met MIME-type `image/png` |
|
||||||
|
| `conceptRelations`, `conceptOwnerships` | Beide afwezig |
|
||||||
|
| `conceptMaps` | Lege array |
|
||||||
|
| Ontbrekende afhankelijkheden | `missing.cmaps` en `missing.pages` beide leeg |
|
||||||
|
|
||||||
|
Onderstaand fragment selecteert de eerste drie items en de eerste twee
|
||||||
|
connectoren. Alleen de genoemde velden zijn overgenomen; dit is geen
|
||||||
|
zelfstandige importbundel:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"conceptId": "fdaf8df6-57b5-4eaf-98af-d2fcc00c1439",
|
||||||
|
"kind": "concept"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2,
|
||||||
|
"conceptId": null,
|
||||||
|
"kind": "phrase",
|
||||||
|
"label": "omvat"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 3,
|
||||||
|
"conceptId": "7aa9ca75-a272-4a74-aca2-f2b586849bfa",
|
||||||
|
"kind": "concept"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"connectors": [
|
||||||
|
{ "id": 1, "sourceId": 1, "targetId": 2, "hasArrow": false },
|
||||||
|
{ "id": 2, "sourceId": 2, "targetId": 3, "hasArrow": true }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Door de concept-id's op te zoeken in `concepts` volgt de uitspraak:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Modelgids LTS Opzet — omvat → 1. Inleiding, doel en scope
|
||||||
|
```
|
||||||
|
|
||||||
|
De dertien andere uitgaande connectoren drukken dezelfde relatie uit naar
|
||||||
|
de overige hoofdstukken. Daarmee verbeeldt één phrase-item veertien
|
||||||
|
uitspraken. De tekst `omvat` heeft in deze export geen eigen `ConceptId`.
|
||||||
|
Ook heeft geen van deze uitspraken een afzonderlijk geëxporteerd
|
||||||
|
`ConceptRelation`-record. Hun betekenis is hier af te leiden uit de
|
||||||
|
diagramstructuur, niet uit een expliciet opgeslagen semantische relatietabel.
|
||||||
|
|
||||||
|
In het bedoelde domeinmodel zou het verbindingsconcept `omvat` een eigen
|
||||||
|
gedeelde identiteit hebben, en zouden de uitspraken bronconcept,
|
||||||
|
verbindingsconcept en doelconcept verbinden. De plaatsing met item-id `2`
|
||||||
|
zou dan alleen een weergave van dat verbindingsconcept zijn. Dit is de
|
||||||
|
gewenste interpretatie; bovenstaande JSON toont de huidige representatie.
|
||||||
|
|
||||||
|
### 13.2 Aanvullend voorbeeld: RWS Dingen
|
||||||
|
|
||||||
|
Bronbestand: [rws-dingen-cmap.json](wiki-data/rws-dingen-cmap.json).
|
||||||
|
Deze bundel van `2026-09-18T13:41:32.898Z` bevat 5 CMaps, 161 gedeelde
|
||||||
|
concepten, 77 pagina's en 14 bijlagen. `missing.pages` bevat 87 verwijzingen;
|
||||||
|
`missing.cmaps` is leeg. Dat betekent dat de betreffende pagina-inhoud niet
|
||||||
|
is meegeleverd, niet dat die verwijzingen uit de concepten verdwijnen.
|
||||||
|
De export vermeldt niet waarom het ophalen per pagina is mislukt.
|
||||||
|
|
||||||
|
| CMap | Items | Phrases | Connectoren |
|
||||||
|
| --- | ---: | ---: | ---: |
|
||||||
|
| `rws-dingen` | 38 | 9 | 41 |
|
||||||
|
| `model-lts` | 45 | 10 | 42 |
|
||||||
|
| `rws-lbs-architectuur` | 69 | 21 | 71 |
|
||||||
|
| `review-zuidasdok-augustus-2026` | 59 | 8 | 63 |
|
||||||
|
| `onderhoudsgui-lts` | 6 | 3 | 6 |
|
||||||
|
|
||||||
|
Alle 51 phrases hebben `conceptId: null`. Een phrase-label hoeft
|
||||||
|
grammaticaal geen werkwoord te zijn: deze export bevat bijvoorbeeld ook
|
||||||
|
`Architectuur`, `Personen` en `Introductie`. `label` is vrije tekst.
|
||||||
|
|
||||||
|
De 166 niet-phrase-plaatsingen verwijzen naar 161 gedeelde concepten.
|
||||||
|
Het concept `RWS Model LTS` staat bijvoorbeeld tweemaal op `rws-dingen`,
|
||||||
|
met item-id's `2` en `33` maar dezelfde concept-id. `Architectuurprincipes`
|
||||||
|
komt met dezelfde concept-id voor op twee verschillende kaarten. Dat
|
||||||
|
illustreert waarom `ItemId` en `ConceptId` verschillende typen en
|
||||||
|
verschillende identiteitsbereiken hebben.
|
||||||
|
|
||||||
|
Onderstaand fragment is de daadwerkelijke `mapReference` van item `23`
|
||||||
|
(`kind: "submap"`) op `rws-dingen`; het is geen zelfstandige bundel:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"id": "cmap-23",
|
||||||
|
"itemIds": [6, 7, 8, 9, 15, 20, 21, 22, 24, 29, 31, 32, 33, 34, 35, 40, 41, 42, 43],
|
||||||
|
"rootItemId": 23,
|
||||||
|
"title": "RWS TODO"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Dit item heeft `separateMap: true`, `childMap: "RWS TODO"` en layouts
|
||||||
|
voor zowel `root` als `cmap-23`. De referentie beschrijft een interne
|
||||||
|
weergave van de kaart; er hoeft geen afzonderlijk `cmaps[]`-object met
|
||||||
|
slug `cmap-23` te bestaan.
|
||||||
|
|
||||||
|
### 13.3 Aanvullend voorbeeld: RWS LBS Architectuur
|
||||||
|
|
||||||
|
Bronbestand: [rws-lbs-architectuur-cmap.json](wiki-data/rws-lbs-architectuur-cmap.json).
|
||||||
|
Deze bundel van `2026-09-18T13:44:02.082Z` bevat 8 CMaps, 96 gedeelde
|
||||||
|
concepten, 40 pagina's en 23 bijlagen. `missing.pages` bevat 55 verwijzingen;
|
||||||
|
`missing.cmaps` is leeg. De drie kaarten met eigen diagramitems zijn
|
||||||
|
`rws-lbs-architectuur`, `model-lts` en `modelgids-lts-opzet`.
|
||||||
|
|
||||||
|
De overige vijf kaarten gebruiken `derivedView`:
|
||||||
|
|
||||||
|
| Afgeleide kaart | `sourceCmapSlug` | `rootItemId` |
|
||||||
|
| --- | --- | ---: |
|
||||||
|
| `kaderdocumenten-beoordelen` | `rws-lbs-architectuur` | 36 |
|
||||||
|
| `sd-inhoud` | `rws-lbs-architectuur` | 48 |
|
||||||
|
| `metamodel-lbs` | `rws-lbs-architectuur` | 89 |
|
||||||
|
| `refactoring-lts-model` | `model-lts` | 26 |
|
||||||
|
| `lts-aspecten-voor-modelverniewing-en-versimpeling` | `model-lts` | 37 |
|
||||||
|
|
||||||
|
Bijvoorbeeld: `kaderdocumenten-beoordelen` bevat geen eigen items of
|
||||||
|
connectoren, maar verwijst met dit daadwerkelijke `derivedView`-object
|
||||||
|
naar de bronkaart:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"rootItemId": 36,
|
||||||
|
"sourceCmapSlug": "rws-lbs-architectuur"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`rootItemId` moet hier in de bronkaart worden opgezocht. `sourceCmapSlug`
|
||||||
|
is een opgeslagen CMap-adres, terwijl `cmap-36` in een `MapReference` een
|
||||||
|
interne referentie- en contextkey is. Deze waarden zijn niet uitwisselbaar.
|
||||||
|
Dat ook `model-lts` in deze bundel staat, past bij de exportregel die de
|
||||||
|
bronkaart van een afgeleide weergave meeneemt.
|
||||||
|
|
||||||
|
De twee bronkaarten `rws-lbs-architectuur` en `model-lts` zijn inhoudelijk
|
||||||
|
gelijk aan hun records in de RWS Dingen-export. Deze voorbeelden zijn
|
||||||
|
daarmee overlappende bundels, geen afzonderlijke definities van dezelfde
|
||||||
|
concepten. Ook deze derde bundel bevat phrases zonder gedeelde concept-id
|
||||||
|
en geen afzonderlijk geëxporteerde semantische relaties.
|
||||||
|
|
||||||
|
### 13.4 Volledige kleine versie-1-bundel
|
||||||
|
|
||||||
|
Deze bundel toont twee gedeelde concepten, een verbindingszin, twee connectoren,
|
||||||
|
een pagina en een ingebed tekstbestand. `SGFsbG8K` is Base64 voor `Hallo`
|
||||||
|
gevolgd door een newline. De tijdelijke concept-id's worden bij opslag opgelost.
|
||||||
|
De verbindingszin gebruikt de huidige versie-1-representatie. Het voorbeeld
|
||||||
|
is dus geen implementatie van het gewenste verbindingsconcept uit § 1.2.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"$schema": "/schemas/racket-wiki-cmap-bundle-v1.schema.json",
|
||||||
|
"format": "racket-wiki-cmap-bundle",
|
||||||
|
"formatVersion": 1,
|
||||||
|
"exportedAt": "2026-09-18T12:00:00.000Z",
|
||||||
|
"generator": "Voorbeeldgenerator",
|
||||||
|
"rootCmapSlug": "voorbeeld",
|
||||||
|
"cmaps": [
|
||||||
|
{
|
||||||
|
"slug": "voorbeeld",
|
||||||
|
"title": "Voorbeeldkaart",
|
||||||
|
"document": {
|
||||||
|
"schemaVersion": 2,
|
||||||
|
"metadata": {
|
||||||
|
"namespace": "",
|
||||||
|
"tags": ["documentatie"],
|
||||||
|
"summary": "Een eenvoudige voorbeeldkaart",
|
||||||
|
"explanationPageSlug": ""
|
||||||
|
},
|
||||||
|
"concepts": [
|
||||||
|
{ "id": "new:proces" },
|
||||||
|
{ "id": "new:documentatie" }
|
||||||
|
],
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"conceptId": "new:proces",
|
||||||
|
"kind": "concept",
|
||||||
|
"x": 100,
|
||||||
|
"y": 80,
|
||||||
|
"width": 200,
|
||||||
|
"height": 90,
|
||||||
|
"parentSubmapId": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2,
|
||||||
|
"kind": "phrase",
|
||||||
|
"label": "heeft documentatie",
|
||||||
|
"x": 360,
|
||||||
|
"y": 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 3,
|
||||||
|
"conceptId": "new:documentatie",
|
||||||
|
"kind": "concept",
|
||||||
|
"x": 600,
|
||||||
|
"y": 80
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"connectors": [
|
||||||
|
{ "id": 1, "sourceId": 1, "targetId": 2, "hasArrow": false },
|
||||||
|
{ "id": 2, "sourceId": 2, "targetId": 3, "hasArrow": true }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"concepts": [
|
||||||
|
{
|
||||||
|
"id": "new:proces",
|
||||||
|
"label": "Proces",
|
||||||
|
"synopsis": "Een reeks samenhangende activiteiten",
|
||||||
|
"aspects": ["ontwerp"],
|
||||||
|
"tags": [{ "type": "person", "value": "Hans" }],
|
||||||
|
"pageSlug": "proces:beschrijving",
|
||||||
|
"externalUrl": "https://example.com/proces"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "new:documentatie",
|
||||||
|
"label": "Documentatie"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"pages": [
|
||||||
|
{
|
||||||
|
"reference": "proces:beschrijving",
|
||||||
|
"title": "Procesbeschrijving",
|
||||||
|
"markdown": "# Proces\n\n[Voorbeeldbestand](/uploads/proces:beschrijving/hallo.txt)",
|
||||||
|
"tags": ["voorbeeld"],
|
||||||
|
"attachments": [
|
||||||
|
{
|
||||||
|
"url": "/uploads/proces:beschrijving/hallo.txt",
|
||||||
|
"name": "hallo.txt",
|
||||||
|
"mimeType": "text/plain",
|
||||||
|
"contentBase64": "SGFsbG8K"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"missing": { "cmaps": [], "pages": [] }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 14. Bronnen in de repository
|
||||||
|
|
||||||
|
- [JSON Schema](static/schemas/racket-wiki-cmap-bundle-v1.schema.json): veldstructuur en typen.
|
||||||
|
- [Bundelopbouw en validatie](static/js/cmap/model/interchange.js): selectie, verwijzingen en integriteitsregels.
|
||||||
|
- [JSON-exporter](static/js/cmap/model/json-exporter.js): modeloverdracht en Base64-export.
|
||||||
|
- [JSON-importer](static/js/cmap/model/json-importer.js): bestandslimieten, uploads en opslagvolgorde.
|
||||||
|
- [Overdrachtscontroller](static/js/wiki/cmap/cmap-transfer-controller.js): conflictkeuze en navigatie.
|
||||||
|
- [Diagrammodel](static/js/cmap/model/concept-map.js) en [conceptmodel](static/js/cmap/model/concept-repository.js): reconstructie en normalisatie.
|
||||||
|
- [Relatiecontroller](static/js/cmap/controller/cmap-relation-controller.js): aanmaken van phrases en connectoren.
|
||||||
|
- [Layoutcontroller](static/js/cmap/controller/cmap-layout-controller.js) en [submapcontroller](static/js/cmap/controller/cmap-submap-controller.js): contextlayouts en interne kaartreferenties.
|
||||||
|
- [Opmaakmodel](static/js/cmap/model/appearance.js): interpretatie van lettergroottes en opmaakwaarden.
|
||||||
|
- [Aangeleverde Modelgids-export](wiki-data/modelgids-lts-opzet-cmap.json): concrete veldwaarden en het uitgewerkte voorbeeld in § 13.1.
|
||||||
|
- [Aangeleverde RWS Dingen-export](wiki-data/rws-dingen-cmap.json): gedeelde plaatsingen, interne submaps en tags (§ 13.2).
|
||||||
|
- [Aangeleverde RWS LBS Architectuur-export](wiki-data/rws-lbs-architectuur-cmap.json): afgeleide kaarten en bronafhankelijkheden (§ 13.3).
|
||||||
|
- [CMap-opslag](private/cmap-storage.rkt): servernormalisatie van conceptidentiteiten.
|
||||||
|
- [Databasemigraties](private/migrations.rkt): scheiding van gedeelde conceptinhoud en kaartitems, met expliciet behoud van phrase-tekst.
|
||||||
|
- [Bundeltests](test/cmap-interchange.test.js) en [import/exporttests](test/cmap-json-import-export.test.mjs): bestaande gedragscontroles.
|
||||||
@@ -11,6 +11,9 @@ and their editor remain unchanged.
|
|||||||
|
|
||||||
A small self-hosted wiki with a Racket backend and an HTML5/CSS/JavaScript frontend.
|
A small self-hosted wiki with a Racket backend and an HTML5/CSS/JavaScript frontend.
|
||||||
|
|
||||||
|
De formele Nederlandse beschrijving van het JSON-export- en importformaat staat in
|
||||||
|
[JSON-FORMAAT.md](JSON-FORMAAT.md), met velddefinities, validatieregels en een volledig voorbeeld.
|
||||||
|
|
||||||
Version 0.2.9 uses PostgreSQL as the wiki's complete content store. Users, sessions, pages, immutable page versions, attachment metadata and attachment bytes live in PostgreSQL. PostgreSQL full-text search is built into the page table and exposed by the wiki search UI.
|
Version 0.2.9 uses PostgreSQL as the wiki's complete content store. Users, sessions, pages, immutable page versions, attachment metadata and attachment bytes live in PostgreSQL. PostgreSQL full-text search is built into the page table and exposed by the wiki search UI.
|
||||||
|
|
||||||
The first-run flow is web based. An unconfigured wiki redirects immediately to `/setup`. Setup asks for the PostgreSQL connection, creates the schema, downloads the pinned frontend libraries and creates the first administrator. After setup the browser is sent to `/login`.
|
The first-run flow is web based. An unconfigured wiki redirects immediately to `/setup`. Setup asks for the PostgreSQL connection, creates the schema, downloads the pinned frontend libraries and creates the first administrator. After setup the browser is sent to `/login`.
|
||||||
|
|||||||
Reference in New Issue
Block a user