352 lines
6.3 KiB
Markdown
352 lines
6.3 KiB
Markdown
# 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:
|
|
----
|
|
```
|