# Konvertering mellan AsciiDoc och TipTap: Typspecifikation Detta dokument beskriver i detalj hur datamodellen mappas mellan **TipTap JSON** och **AsciiDoc**. Dokumentet fungerar som en specifikation för utvecklare som ska implementera konverteringslogik, baserat på referenslogiken från `tiptap-to-asciidoc`. **Gällande versioner:** * **TipTap:** v2 * **AsciiDoc:** Asciidoctor (Asciidoctor.js / källkodsstandard) --- ## Översikt av datamodeller * **TipTap JSON:** Ett träd av _Nodes_ (blockelement som stycken, rubriker, listor) och _Marks_ (inline-formatering som fetstil, kursivt, länkar). Roten i trädet är en nod av typen `doc` som innehåller en array av block-noder i `content`. * **AsciiDoc:** Textbaserad markup som förlitar sig på radbrytningar och prefix/suffix (t.ex. `==`, `*`, `_`). Vid konvertering från TipTap till AsciiDoc traverseras JSON-trädet uppifrån och ner. Vid konvertering från AsciiDoc till TipTap behöver AsciiDoc-mjukvara generellt konvertera texten till HTML, varefter TipTaps inbyggda parser (`@tiptap/html` -> `generateJSON`) nyttjas för att omvandla HTML till TipTap JSON. --- ## Block-noder (Nodes) ### 1. Document (Rot-nod) **TipTap JSON:** ```json { "type": "doc", "content": [ ... // Andra block-noder ] } ``` **AsciiDoc:** Inget specifikt syntax, detta representerar hela dokumentfilen. Block-noderna under `content` renderas sekventiellt separerade med tomma rader (två radbrytningar `\n\n` mellan blockelement rekommenderas generellt). --- ### 2. Heading (Rubriker) Rubriknivåer definieras med attributet `level`. **TipTap JSON:** ```json { "type": "heading", "attrs": { "level": 2 }, "content": [ { "type": "text", "text": "Min Rubrik" } ] } ``` **AsciiDoc:** Antalet likhetstecken (`=`) motsvarar värdet i `level`. Exempel för `level: 2`: ```asciidoc == Min Rubrik ``` --- ### 3. Paragraph (Stycken och Tomma rader) Ett stycke översätts normalt rätt upp och ner. En tom rad i TipTap (ett tomt stycke) representeras via AsciiDocs specialattribut `{blank}` vilket skapar en tom paragraf som parsas tillbaka som ett tomt stycke. **TipTap JSON (Vanligt stycke):** ```json { "type": "paragraph", "content": [ { "type": "text", "text": "Ett vanligt stycke text." } ] } ``` **AsciiDoc (Vanligt stycke):** ```asciidoc Ett vanligt stycke text. ``` **TipTap JSON (Tomt stycke / Tom rad):** ```json { "type": "paragraph" } ``` **AsciiDoc (Tomt stycke / Tom rad):** ```asciidoc {blank} ``` --- ### 4. Code Block (Kodblock) **TipTap JSON:** ```json { "type": "codeBlock", "attrs": { "language": "javascript" }, "content": [ { "type": "text", "text": "console.log('Hej');" } ] } ``` **AsciiDoc:** ```asciidoc [source,javascript] ---- console.log('Hej'); ---- ``` --- ### 5. Blockquote (Citatblock) **TipTap JSON:** ```json { "type": "blockquote", "content": [ { "type": "paragraph", "content": [ { "type": "text", "text": "Detta är ett citat." } ] } ] } ``` **AsciiDoc:** ```asciidoc ____ Detta är ett citat. ____ ``` --- ### 6. Horizontal Rule (Avdelare) **TipTap JSON:** ```json { "type": "horizontalRule" } ``` **AsciiDoc:** ```asciidoc ''' ``` --- ### 7. Listor (Bullet List / Ordered List) **TipTap JSON (Oordnad / Bullet List):** ```json { "type": "bulletList", "content": [ { "type": "listItem", "content": [ { "type": "paragraph", "content": [{ "type": "text", "text": "Punkt 1" }] } ] } ] } ``` **AsciiDoc (Oordnad):** ```asciidoc * Punkt 1 ``` **TipTap JSON (Ordnad / Ordered List):** Samma men `type` är `"orderedList"`. **AsciiDoc (Ordnad):** ```asciidoc . Punkt 1 . Punkt 2 .. Underpunkt 2.1 ``` --- ## Inline-formatering (Marks) ### Hard Break **TipTap JSON:** ```json { "type": "hardBreak" } ``` **AsciiDoc:** ```asciidoc + ``` ### Bold **TipTap JSON:** ```json { "type": "text", "text": "viktig", "marks": [{ "type": "bold" }] } ``` **AsciiDoc:** ```asciidoc *viktig* ``` ### Italic **TipTap JSON:** ```json { "type": "text", "text": "speciell", "marks": [{ "type": "italic" }] } ``` **AsciiDoc:** ```asciidoc _speciell_ ``` ### Strike **TipTap JSON:** ```json { "type": "text", "text": "gammal", "marks": [{ "type": "strike" }] } ``` **AsciiDoc:** ```asciidoc [line-through]#gammal# ``` ### Code **TipTap JSON:** ```json { "type": "text", "text": "const x = 1;", "marks": [{ "type": "code" }] } ``` **AsciiDoc:** ```asciidoc `const x = 1;` ``` ### Link **TipTap JSON:** ```json { "type": "text", "text": "Klicka här", "marks": [{ "type": "link", "attrs": { "href": "https://example.com" } }] } ``` **AsciiDoc:** ```asciidoc https://example.com[Klicka här] ``` --- ### 8. Länkar (Links) Explicita attributslänkar i AsciiDoc. **TipTap JSON:** ```json { "type": "text", "text": "platsöversikten", "marks": [ { "type": "link", "attrs": { "href": "index" } } ] } ``` **AsciiDoc:** ```asciidoc link:index[platsöversikten] ``` *(Notera att http/https-länkar kan använda `https://exempel.com[text]`, medan interna/släktlänkar primärt använder `link:path[text]` i AsciiDoc).* --- ### 9. Admonitions (Varningar, Tips, Notiser) Informationsblock som sticker ut från mängden. För att TipTap inte ska tappa bort detta (vilket ofta sker om man låter standard HTML-tabeller importeras), representeras detta som en egen anpassad (custom) nod-typ i JSON, `admonition`. **TipTap JSON:** ```json { "type": "admonition", "attrs": { "type": "tip" }, "content": [ { "type": "paragraph", "content": [ { "type": "text", "text": "Spelarna känner till detta..." } ] } ] } ``` **AsciiDoc (Förenklad ettklyftig admonition):** ```asciidoc [TIP] ==== Spelarna känner till detta... ==== ``` *(Eller enraders som `TIP: Spelarna...` - men blockformat är mer robust och generikt).* --- ### 10. Code Block - Språk-attribut (Syntax Highlighting) För att kodblocket ska förstå och färgkoda språket korrekt (till exempel `yaml`), paraserar koden `attrs.language` i TipTap JSON med `language` till `source`-parametern i AsciiDoc. **TipTap JSON:** ```json { "type": "codeBlock", "attrs": { "language": "yaml" }, "content": [ { "type": "text", "text": "services:\n archivum:" } ] } ``` **AsciiDoc:** ```asciidoc [source,yaml] ---- services: archivum: ---- ```