@Doc

Text Formatting

このドキュメントはまだこの言語に翻訳されていません。以下はEnglish版です。

@Doc Text Formatting — Semantic Reference

Companion to Inline Syntax Specification §4 (Complete EBNF Definition) — plus §7 (@mark / @color / @bordered Styles Semantics), §9 (@raw Opaque Domain), and §10 (Nested Parsing), which each cover one member of this family in dedicated detail. This document covers @bold, @italic, @underline, @del, @mark, @color, @bordered, and @raw as a group; where a node already has its own numbered section, this reference summarizes and links out rather than repeating it. Categorized as "Text Formatting" in Block Syntax Specification §2's Document AST Structure diagram.

0. Table of Contents


1. Design Philosophy

Text Formatting nodes describe how a fragment should be visually or semantically distinguished from surrounding text — emphasized, struck through, highlighted — without dictating a specific font weight, color, or tag. Five of the eight members share one shape almost exactly:

text
@bold   @italic   @underline   @del   @mark

@color and @bordered are the deliberate exceptions to "no specific color" above — they exist precisely to let an author pin an exact text/border color when the semantic-only default isn't enough. Both stay in this family because they're shaped like @mark (an inline wrapper plus one extra slot), not a Structural or Container node; @bordered further shares @color's exact {styles} color-swatch semantics (see Color, Bordered).

@raw is the deliberate outlier: it names an absence of formatting parsing, not a formatting style. It belongs to this family because it lives in the same part of the grammar (an inline-node wrapping a bracketed body), not because it shares the others' behavior.


2. Why Text Formatting Nodes Exist

Markdown expresses most of this family through repurposed punctuation — **bold**, *italic*, ~~strikethrough~~ — where the same character () means two different things depending on whether it's doubled, and where authors regularly hit ambiguity around word boundaries (foobarbazvsfoo bar* baz). Underline and highlight have no standard Markdown syntax at all; authors fall back to raw HTML (<u>, <mark>`) or platform-specific extensions.

@Doc gives each of these an explicit node name instead of overloading a small set of punctuation characters across multiple meanings:

text
Meaning
  ↓
AST Node
  ↓
Renderer Adapter
  ↓
Output Target

A parser can find every @mark (for a highlight/annotation index) or every @del (for a "what changed" scan) directly, without disambiguating * from ** from *** by counting characters.


3. Shape Comparison

NodeModifier / OptionContent typeShape notes
@bold (alias @b)—content (nestable)plain wrapper
@italic (alias @i)—content (nestable)plain wrapper
@underline (alias @u)—content (nestable)plain wrapper
@del—content (nestable)plain wrapper
​@mark{styles}, optionalcontent (nestable)recolors the background — see §7 below
​@color{styles}, optionalcontent (nestable)recolors the text — see Color
​@bordered{styles}, optionalcontent (nestable)recolors the border, shares @color's {styles} slot — see Bordered
​@raw—raw-content (opaque, not nestable)only node in this family that disables inline parsing entirely
ebnf
mark      = "@mark" , [ styles ] , content ;
color     = "@color" , [ styles ] , content ;
bordered  = "@bordered" , [ styles ] , content ;
bold      = ( "@bold" | "@b" ) , content ;
italic    = ( "@italic" | "@i" ) , content ;
underline = ( "@underline" | "@u" ) , content ;
del       = "@del" , content ;

raw       = "@raw" , raw-content ;

Four of the eight nodes — @bold, @italic, @underline, @del — are structurally identical: a keyword and nothing but content (@bold/@italic/@underline also each offer the @b/@i/@u simplified alias, see their sections below). @mark, @color, and @bordered share one further shape on top of that: the same optional {styles} slot — they differ only in what's semantically valid inside it (a comma-separated token list for @mark vs. a single color token for @color/@bordered), not in the grammar shape itself. @raw is the only member whose content production is different in kind, not just in options — see Raw.


4. Node Reference

Bold

Simplified alias: @b. Parses to the identical AST node as @bold — purely a shorthand at authoring time (see Inline Syntax Specification §14).

text
這是@bold[重要]內容。
這是@b[重要]內容。

Marks a fragment as having stronger importance than surrounding text. No modifier, no styles — the plainest node in the family.


Italic

Simplified alias: @i.

text
這是@italic[強調]內容。
這是@i[強調]內容。

Marks a fragment as stylistically or semantically distinct — emphasis, a title, a foreign-language term. Same shape as @bold.


Underline

Simplified alias: @u.

text
這是@underline[底線]內容。
這是@u[底線]內容。

Same shape again. Unlike @bold/@italic, underline has no strong precedent in Markdown at all — @Doc gives it first-class status anyway, rather than forcing authors into raw <u>.


Strikethrough — @del

text
這是@del[刪除線]內容。

Marks a fragment as removed, retracted, or no longer applicable — the semantic opposite of newly added content. Same shape as the three nodes above.


Mark

text
@mark[預設高亮]
@mark{yellow}[黃色高亮]
@mark{red}[紅色高亮]

A node with a second slot: an optional {styles} color-token list (named colors or hex colors, comma-separable). The three modifier tokens — underline, strikethrough, bordered — have been removed from {styles}: underline duplicated the @underline node's semantics, strikethrough duplicated @del's, and bordered has been promoted to its own first-class node, @bordered (see below). Full semantics — the color-token definition, renderer fallback rules for unrecognized tokens, and why styles is a lexical-only production (a brace-wrapped character run, with token splitting left to the semantic/renderer layer) — are covered in dedicated detail at Inline Syntax Specification §7; this document does not repeat that content.

Note that @mark's color tokens set a background — that's what the named palette (yellow, red, green, …) is tuned for. See Color below for actual text-color.


Color

text
@color{blue}[這段文字是深藍色的]
@color{#ff0000}[這段文字是紅色的]

Where @mark recolors the background, @color recolors the text itself — a gap the syntax had no answer for before this node existed. It shares @mark's exact {styles} slot — same brace, same optional-ness, same seven named tokens (yellow/red/green/blue/orange/purple/gray) plus literal #RRGGBB hex. The two nodes' named tokens resolve through independent palettes, though: @mark's are pale shades tuned for highlight backgrounds, and would read as low-contrast, barely-visible text if reused here, so a Renderer typically keeps a separate, darker palette for @color. An unrecognized, malformed, or omitted value (e.g. @color{not-a-color}[...], @color{#zzz}[...], @color[...]) falls back to a default rather than throwing, per Inline Syntax Specification §6's ignore-don't-throw spirit.

@color's earlier (hex-color) paren syntax has been retired, and — unlike the fallback above — using it is a hard Parser error (Strict Mode throw / Editor Mode diagnostic), not a silent fallback: @color(#ff0000)[...] looks like it should work and visibly doesn't, which is a worse trap for an author than an upfront error.


Bordered

text
@bordered{blue}[blue border]
@bordered{#3366ff}[hex border color]

Adds a border around a fragment — sharing @color's exact {styles} slot semantics (same named tokens plus hex, see Color above), just applied to the border instead of the text color; implementations typically reuse @color's swatch resolver directly. An omitted or unrecognized value falls back to the renderer's default border style, per the same ignore-don't-throw spirit. This node replaces @mark's former bordered modifier token, becoming a first-class node the same way underline (already @underline) and strikethrough (already @del) are. Full semantics at Inline Syntax Specification §7.


Raw

text
@raw[@mark[hello]]

Output: the literal text @mark[hello] — not a mark node. @raw's content is raw-content, not content: nothing inside is parsed as @Doc syntax, and even the global @@ escape rule is disabled inside it (replaced by two narrower local exceptions, @] → ] and @@] → @]). Full rules and worked examples live at Inline Syntax Specification §9 and Special Nodes §6 (which documents the interaction between @raw's local exceptions and the global escape rule in detail).

@raw is not "inline code," even though it's often reached for in that role — it names an absence of parsing, not a semantic claim about the content being code. @Doc currently has no dedicated inline-code node at all (@code per Block Syntax Specification §5 is block-level only); using @raw for a short code fragment borrows its opaque-parsing behavior without asserting "this is code" the way @kbd asserts "this is a keyboard key" (see Semantic Inline: Keyboard Key).


5. Semantic HTML Mapping (Non-Normative)

Neither the Block Syntax Specification nor the Inline Syntax Specification prescribes which HTML tag @bold or @italic should compile to. A reasonable, commonly-expected mapping — @bold → <strong>, @italic → <em> — favors semantic HTML (importance/emphasis) over purely presentational tags (<b>, <i>), consistent with @Doc's stated goal of separating meaning from appearance (README § What @Doc Is). Treat this as sensible renderer-adapter guidance, not a normative rule — the formal spec leaves tag choice to the renderer, the same way it leaves @warning's HTML output to the renderer adapter (see Callout Blocks §8).


6. AST Representation

Inline Syntax Specification §10 gives the canonical nesting example for this family:

text
@bold[
    這是粗體,
    裡面有
    @mark{yellow}[重要高亮]
    與
    @underline[底線]
]
text
Document
└── BlockNodes
    └── ParagraphNode
        └── BoldNode
            ├── TextNode
            │   └── "這是粗體,裡面有"
            ├── MarkNode
            │   ├── Styles
            │   │   └── ["yellow"]
            │   └── Content
            │       └── "重要高亮"
            ├── TextNode
            │   └── "與"
            └── UnderlineNode
                └── Content
                    └── "底線"

@raw produces a structurally different tree — a single leaf node holding an opaque string, the same shape @code and @mermaid use at the block level (see Widget Blocks §5):

text
Document
└── BlockNodes
    └── ParagraphNode
        └── RawNode
            └── RawContent
                └── "@mark[hello]"

Because Bold/Italic/Underline/Del/Mark all route through the same nestable content production, a tool can walk arbitrarily deep combinations of them; Raw's content is opaque by design, so no tool can (or should) look inside it.


7. Renderer Independence

Source:

text
這是@bold[重要]內容,這段@del[已過時]。

Web:

html
<p>這是<strong>重要</strong>內容,這段<del>已過時</del>。</p>

Terminal:

text
這是【重要】內容,這段~~已過時~~。

Documentation platform: native emphasis/strikethrough components, chosen by the adapter — not by the @Doc source. @raw's output is identical across every target by definition: whatever string was inside the brackets, unparsed.


8. AI Generation Stability

Markdown's overloaded punctuation is a well-documented source of generation drift: a model has to track whether it's inside single or double asterisks, whether underscores or asterisks are the active delimiter, and whether a * mid-word starts emphasis or is just a literal character. @bold[...], @italic[...], @underline[...], and @del[...] remove that ambiguity — each has one spelling, and [] has exactly one meaning everywhere in @Doc (README § Core Syntax).

@raw solves a different generation problem: when a model needs to produce example @Doc syntax as literal text (documentation about @Doc itself, as this file repeatedly does), wrapping it in @raw[...] guarantees the compiler won't try to parse the example as real nodes — no manual escaping of every @ and [ inside the sample required.


9. Design Principle

Text Formatting nodes follow the same rule as the rest of @Doc:

text
Semantic First, Layout Later

Bold text is not two asterisks. A highlight is not a <mark> tag some renderer happened to pick. Each node is defined by what it means for a fragment of text, not by how any single renderer happens to draw it today.