Files
Archivum/ASCIIDOC_TIPTAP_CONVERSION.md

6.3 KiB

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:

{
  "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:

{
  "type": "heading",
  "attrs": {
    "level": 2
  },
  "content": [
    { "type": "text", "text": "Min Rubrik" }
  ]
}

AsciiDoc: Antalet likhetstecken (=) motsvarar värdet i level. Exempel för level: 2:

== 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):

{
  "type": "paragraph",
  "content": [
    { "type": "text", "text": "Ett vanligt stycke text." }
  ]
}

AsciiDoc (Vanligt stycke):

Ett vanligt stycke text.

TipTap JSON (Tomt stycke / Tom rad):

{
  "type": "paragraph"
}

AsciiDoc (Tomt stycke / Tom rad):

{blank}

4. Code Block (Kodblock)

TipTap JSON:

{
  "type": "codeBlock",
  "attrs": {
    "language": "javascript"
  },
  "content": [
    { "type": "text", "text": "console.log('Hej');" }
  ]
}

AsciiDoc:

[source,javascript]
----
console.log('Hej');
----

5. Blockquote (Citatblock)

TipTap JSON:

{
  "type": "blockquote",
  "content": [
    {
      "type": "paragraph",
      "content": [
        { "type": "text", "text": "Detta är ett citat." }
      ]
    }
  ]
}

AsciiDoc:

____
Detta är ett citat.
____

6. Horizontal Rule (Avdelare)

TipTap JSON:

{
  "type": "horizontalRule"
}

AsciiDoc:

'''

7. Listor (Bullet List / Ordered List)

TipTap JSON (Oordnad / Bullet List):

{
  "type": "bulletList",
  "content": [
    {
      "type": "listItem",
      "content": [
        {
          "type": "paragraph",
          "content": [{ "type": "text", "text": "Punkt 1" }]
        }
      ]
    }
  ]
}

AsciiDoc (Oordnad):

* Punkt 1

TipTap JSON (Ordnad / Ordered List): Samma men type är "orderedList".

AsciiDoc (Ordnad):

. Punkt 1
. Punkt 2
.. Underpunkt 2.1

Inline-formatering (Marks)

Hard Break

TipTap JSON:

{ "type": "hardBreak" }

AsciiDoc:

 +

Bold

TipTap JSON:

{ "type": "text", "text": "viktig", "marks": [{ "type": "bold" }] }

AsciiDoc:

*viktig*

Italic

TipTap JSON:

{ "type": "text", "text": "speciell", "marks": [{ "type": "italic" }] }

AsciiDoc:

_speciell_

Strike

TipTap JSON:

{ "type": "text", "text": "gammal", "marks": [{ "type": "strike" }] }

AsciiDoc:

[line-through]#gammal#

Code

TipTap JSON:

{ "type": "text", "text": "const x = 1;", "marks": [{ "type": "code" }] }

AsciiDoc:

`const x = 1;`

TipTap JSON:

{ "type": "text", "text": "Klicka här", "marks": [{ "type": "link", "attrs": { "href": "https://example.com" } }] }

AsciiDoc:

https://example.com[Klicka här]

Explicita attributslänkar i AsciiDoc.

TipTap JSON:

{
  "type": "text",
  "text": "platsöversikten",
  "marks": [
    {
      "type": "link",
      "attrs": {
        "href": "index"
      }
    }
  ]
}

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:

{
  "type": "admonition",
  "attrs": {
    "type": "tip"
  },
  "content": [
    {
      "type": "paragraph",
      "content": [
        { "type": "text", "text": "Spelarna känner till detta..." }
      ]
    }
  ]
}

AsciiDoc (Förenklad ettklyftig admonition):

[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:

{
  "type": "codeBlock",
  "attrs": {
    "language": "yaml"
  },
  "content": [
    { "type": "text", "text": "services:\n  archivum:" }
  ]
}

AsciiDoc:

[source,yaml]
----
services:
  archivum:
----