Skip to content

Prinzip des versteckten Modus: Warum die Breitenberechnung so wichtig ist

Was Sie nach diesem Kurs können

  • Verstehen Sie, wie der OpenCode-Versteckmodus funktioniert
  • Wissen Sie, warum normale Formatierungstools im versteckten Modus falsch ausrichten
  • Beherrschen Sie den Breitenberechnungsalgorithmus des Plugins (drei Schritte)
  • Verstehen Sie die Funktion von Bun.stringWidth

Ihr aktuelles Problem

Sie schreiben Code mit OpenCode, und die KI generiert eine schöne Tabelle:

markdown
| Feld | Typ | Beschreibung |
|--- | --- | ---|
| **name** | string | Benutzername |
| age | number | Alter |

In der Quellcodeansicht sieht es ordentlich aus. Aber in der Vorschau ist die Tabelle verschoben:

| Feld     | Typ   | Beschreibung   |
|--- | --- | ---|
| name | string | Benutzername |    ← Warum ist es kürzer?
| age      | number | Alter   |

Wo liegt das Problem? Versteckter Modus.

Was ist der versteckte Modus

OpenCode aktiviert standardmäßig den Versteckten Modus (Concealment Mode), der Markdown-Syntaxsymbole beim Rendern ausblendet:

QuellcodeIm versteckten Modus angezeigt
**fett**fett (4 Zeichen)
*kursiv*kursiv (4 Zeichen)
~~durchgestrichen~~durchgestrichen (6 Zeichen)
`Code`Code (4 Zeichen + Hintergrundfarbe)

Vorteil des versteckten Modus

Ermöglicht es Ihnen, sich auf den Inhalt zu konzentrieren, anstatt von einer Reihe von **- und *-Symbolen abgelenkt zu werden.

Warum normale Formatierungstools Probleme verursachen

Normale Tabellenformatierungstools berechnen die Breite, indem sie **name** als 8 Zeichen behandeln:

** n a m e ** = 8 Zeichen

Aber im versteckten Modus sieht der Benutzer name, nur 4 Zeichen.

Das Ergebnis ist: Das Formatierungstool richtet nach 8 Zeichen aus, aber der Benutzer sieht 4 Zeichen, also ist die Tabelle natürlich verschoben.

Kernidee: Berechnen der "Anzeigebreite" statt der "Zeichenlänge"

Die Kernidee dieses Plugins ist: Berechnen der Breite, die der Benutzer tatsächlich sieht, nicht der Zeichenanzahl im Quellcode.

Der Algorithmus besteht aus drei Schritten:

Schritt 1: Codeblöcke schützen (Symbole in Codeblöcken werden nicht entfernt)
Schritt 2: Markdown-Symbole entfernen (**, *, ~~ usw.)
Schritt 3: Endgültige Breite mit Bun.stringWidth berechnen

Machen Sie mit: Verstehen des dreistufigen Algorithmus

Schritt 1: Codeblöcke schützen

Warum

Markdown-Symbole in Inline-Code (mit Backticks umschlossen) sind "Literale". Der Benutzer sieht die 8 Zeichen **bold**, nicht die 4 Zeichen bold.

Daher müssen Sie den Inhalt der Codeblöcke "verstecken", bevor Sie die Markdown-Symbole entfernen.

Quellcode-Implementierung

typescript
// Schritt 1: Inline-Code extrahieren und schützen
const codeBlocks: string[] = []
let textWithPlaceholders = text.replace(/`(.+?)`/g, (match, content) => {
  codeBlocks.push(content)
  return `\x00CODE${codeBlocks.length - 1}\x00`
})

Funktionsweise

EingabeNach der VerarbeitungcodeBlocks-Array
`**bold**`\x00CODE0\x00["**bold**"]
`a` and `b`\x00CODE0\x00 and \x00CODE1\x00["a", "b"]

Ersetzen Sie Codeblöcke mit speziellen Platzhaltern wie \x00CODE0\x00, damit sie beim Entfernen von Markdown-Symbolen nicht versehentlich beschädigt werden.

Schritt 2: Markdown-Symbole entfernen

Warum

Im versteckten Modus wird **fett** als fett angezeigt, *kursiv* als kursiv. Bei der Breitenberechnung müssen diese Symbole entfernt werden.

Quellcode-Implementierung

typescript
// Schritt 2: Markdown-Symbole aus Nicht-Code-Teilen entfernen
let visualText = textWithPlaceholders
let previousText = ""

while (visualText !== previousText) {
  previousText = visualText
  visualText = visualText
    .replace(/\*\*\*(.+?)\*\*\*/g, "$1") // ***fett kursiv*** → Text
    .replace(/\*\*(.+?)\*\*/g, "$1")     // **fett** → fett
    .replace(/\*(.+?)\*/g, "$1")         // *kursiv* → kursiv
    .replace(/~~(.+?)~~/g, "$1")         // ~~durchgestrichen~~ → durchgestrichen
    .replace(/!\[([^\]]*)\]\(([^)]+)\)/g, "$1")     // ![alt](url) → alt
    .replace(/\[([^\]]+)\]\(([^)]+)\)/g, "$1 ($2)") // [text](url) → text (url)
}

Warum eine while-Schleife?

Um verschachtelte Syntax zu verarbeiten. Zum Beispiel ***fett kursiv***:

Runde 1: ***fett kursiv*** → **fett kursiv** (äußere *** entfernt)
Runde 2: **fett kursiv** → *fett kursiv* (** entfernt)
Runde 3: *fett kursiv* → fett kursiv (* entfernt)
Runde 4: fett kursiv = fett kursiv (keine Änderung, Schleife beendet)
Behandlung von Bildern und Links
  • Bilder ![alt](url): OpenCode zeigt nur den alt-Text an, also wird durch alt ersetzt
  • Links [text](url): Wird als text (url) angezeigt, URL-Informationen werden beibehalten

Schritt 3: Codeblöcke wiederherstellen + Breite berechnen

Warum

Der Inhalt der Codeblöcke muss zurückgesetzt werden, dann wird die endgültige Anzeigebreite mit Bun.stringWidth berechnet.

Quellcode-Implementierung

typescript
// Schritt 3: Codeblock-Inhalte wiederherstellen
visualText = visualText.replace(/\x00CODE(\d+)\x00/g, (match, index) => {
  return codeBlocks[parseInt(index)]
})

return Bun.stringWidth(visualText)

Warum Bun.stringWidth?

Bun.stringWidth kann korrekt berechnen:

ZeichentypBeispielZeichenanzahlAnzeigebreite
ASCIIabc33
Chinesisch你好24 (jedes belegt 2 Positionen)
Emoji😀12 (belegt 2 Positionen)
Nullbreite-Zeichena\u200Bb32 (Nullbreite-Zeichen belegt keinen Platz)

Normales text.length kann nur die Zeichenanzahl zählen und kann diese Sonderfälle nicht verarbeiten.

Vollständiges Beispiel

Angenommen, der Zelleninhalt ist: **`code`** and *text*

Schritt 1: Codeblöcke schützen

Eingabe: **`code`** and *text*
Ausgabe: **\x00CODE0\x00** and *text*
codeBlocks = ["code"]

Schritt 2: Markdown-Symbole entfernen

Runde 1: **\x00CODE0\x00** and *text* → \x00CODE0\x00 and text
Runde 2: Keine Änderung, beendet

Schritt 3: Codeblöcke wiederherstellen + Breite berechnen

Nach Wiederherstellung: code and text
Breite: Bun.stringWidth("code and text") = 13

Schließlich richtet das Plugin diese Zelle nach einer Breite von 13 Zeichen aus, nicht nach den 22 Zeichen des Quellcodes.

Kontrollpunkte

Nach Abschluss dieses Kurses sollten Sie folgende Fragen beantworten können:

  • [ ] Welche Symbole werden im versteckten Modus ausgeblendet? (Antwort: **, *, ~~ und andere Markdown-Syntaxsymbole)
  • [ ] Warum müssen Codeblöcke zuerst geschützt werden? (Antwort: Symbole in Codeblöcken sind Literale und sollten nicht entfernt werden)
  • [ ] Warum wird eine while-Schleife zum Entfernen von Symbolen verwendet? (Antwort: Um verschachtelte Syntax zu verarbeiten, z. B. ***fett kursiv***)
  • [ ] Was ist der Vorteil von Bun.stringWidth gegenüber text.length? (Antwort: Kann die Anzeigebreite von chinesischen Zeichen, Emojis und Nullbreite-Zeichen korrekt berechnen)

Warnung vor Fallstricken

Häufige Missverständnisse

Missverständnis: ** in Codeblöcken wird ebenfalls entfernt

Tatsache: Nein. Das Plugin schützt den Inhalt der Codeblöcke zuerst mit Platzhaltern, entfernt die Symbole anderer Teile und stellt sie dann wieder her.

Daher ist die Breite von `**bold**` 8 (**bold**), nicht 4 (bold).

Zusammenfassung dieser Lektion

SchrittFunktionSchlüsselcode
Codeblöcke schützenVerhindert, dass Symbole in Codeblöcken versehentlich entfernt werdentext.replace(/\(.+?)`/g, ...)`
Markdown entfernenBerechnet den tatsächlichen Anzeigeinhalt im versteckten ModusMehrere Regex-Ersetzungen
Breite berechnenVerarbeitet chinesische Zeichen, Emojis und andere SonderzeichenBun.stringWidth()

Vorschau auf die nächste Lektion

In der nächsten Lektion lernen wir Tabellenspezifikationen.

Sie werden lernen:

  • Welche Tabellen formatiert werden können
  • Die 4 Regeln der Tabellenvalidierung
  • Wie Sie "Ungültige Tabelle"-Fehler vermeiden

Anhang: Quellcode-Referenz

Klicken, um Quellcodepositionen anzuzeigen

Aktualisierungszeit: 2026-01-26

FunktionDateipfadZeilennummer
Einstiegspunkt für Anzeigebreitenberechnungindex.ts151-159
---------
---------
---------
Bun.stringWidth-Aufrufindex.ts195

Schlüsselfunktionen:

  • calculateDisplayWidth(): Einstiegspunkt für Breitenberechnung mit Cache
  • getStringWidth(): Kernalgorithmus, entfernt Markdown-Symbole und berechnet Anzeigebreite

Schlüsselkonstanten:

  • \x00CODE{n}\x00: Format für Codeblock-Platzhalter