atdoc-core 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +33 -0
- package/configs/atdoc-setting.json +30 -0
- package/dist/Adapters.d.ts +18 -0
- package/dist/Adapters.d.ts.map +1 -0
- package/dist/Adapters.js +484 -0
- package/dist/Adapters.js.map +1 -0
- package/dist/Lexer.d.ts +23 -0
- package/dist/Lexer.d.ts.map +1 -0
- package/dist/Lexer.js +292 -0
- package/dist/Lexer.js.map +1 -0
- package/dist/Parser.d.ts +136 -0
- package/dist/Parser.d.ts.map +1 -0
- package/dist/Parser.js +797 -0
- package/dist/Parser.js.map +1 -0
- package/dist/Serializer.d.ts +97 -0
- package/dist/Serializer.d.ts.map +1 -0
- package/dist/Serializer.js +753 -0
- package/dist/Serializer.js.map +1 -0
- package/dist/editor/monarch.d.ts +17 -0
- package/dist/editor/monarch.d.ts.map +1 -0
- package/dist/editor/monarch.js +163 -0
- package/dist/editor/monarch.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -0
- package/dist/registry.d.ts +104 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +265 -0
- package/dist/registry.js.map +1 -0
- package/dist/types.d.ts +55 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +7 -0
- package/dist/types.js.map +1 -0
- package/docs/en/Block-Syntax-Specification.md +992 -0
- package/docs/en/Inline-Syntax-Specification.md +915 -0
- package/docs/en/README.md +235 -0
- package/package.json +36 -0
|
@@ -0,0 +1,992 @@
|
|
|
1
|
+
# @Doc Block Syntax Specification v1.4
|
|
2
|
+
|
|
3
|
+
> 🌐 Other languages: [Traditional Chinese](https://github.com/WEDC-Studio-Official/AtDoc/blob/main/docs/zh-tw/Block-Syntax-Specification.md) ・ [Simplified Chinese](https://github.com/WEDC-Studio-Official/AtDoc/blob/main/docs/zh-cn/Block-Syntax-Specification.md) ・ [Japanese (AI translation; may contain errors)](https://github.com/WEDC-Studio-Official/AtDoc/blob/main/docs/ja/Block-Syntax-Specification.md) ・ [Korean (AI translation; may contain errors)](https://github.com/WEDC-Studio-Official/AtDoc/blob/main/docs/ko/Block-Syntax-Specification.md)
|
|
4
|
+
|
|
5
|
+
## 0. Table of Contents
|
|
6
|
+
|
|
7
|
+
* [1. Design Philosophy](#1-design-philosophy)
|
|
8
|
+
* [2. Document AST Structure](#2-document-ast-structure)
|
|
9
|
+
* [3. EBNF](#3-ebnf)
|
|
10
|
+
* [4. Shared Components](#4-shared-components)
|
|
11
|
+
* [5. Structural Blocks](#5-structural-blocks)
|
|
12
|
+
* [6. Container Blocks](#6-container-blocks)
|
|
13
|
+
* [7. Callout Blocks](#7-callout-blocks)
|
|
14
|
+
* [8. Widget Blocks](#8-widget-blocks)
|
|
15
|
+
* [9. Metadata](#9-metadata)
|
|
16
|
+
* [10. Core Principle](#10-core-principle)
|
|
17
|
+
* [11. Simplified Syntax Aliases](#11-simplified-syntax-aliases)
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## 1. Design Philosophy
|
|
22
|
+
|
|
23
|
+
@Doc Block Syntax adopts:
|
|
24
|
+
|
|
25
|
+
> **Semantic First, Layout Later**
|
|
26
|
+
|
|
27
|
+
Block nodes describe:
|
|
28
|
+
|
|
29
|
+
> The semantics of the document (What)
|
|
30
|
+
|
|
31
|
+
rather than:
|
|
32
|
+
|
|
33
|
+
> The presentation (How)
|
|
34
|
+
|
|
35
|
+
Therefore @Doc does not provide:
|
|
36
|
+
|
|
37
|
+
* `@div`
|
|
38
|
+
* `@span`
|
|
39
|
+
* `@flex`
|
|
40
|
+
* `@grid`
|
|
41
|
+
* `@row`
|
|
42
|
+
* `@col`
|
|
43
|
+
* `@class`
|
|
44
|
+
* `@style`
|
|
45
|
+
|
|
46
|
+
The renderer can freely decide, based on the platform:
|
|
47
|
+
|
|
48
|
+
* HTML
|
|
49
|
+
* React
|
|
50
|
+
* PDF
|
|
51
|
+
* DOCX
|
|
52
|
+
* Discord
|
|
53
|
+
* Terminal
|
|
54
|
+
* Notion
|
|
55
|
+
* AI UI
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## 2. Document AST Structure
|
|
60
|
+
|
|
61
|
+
```text
|
|
62
|
+
Document AST
|
|
63
|
+
│
|
|
64
|
+
├── Metadata
|
|
65
|
+
│ └── @meta
|
|
66
|
+
│
|
|
67
|
+
├── Block Nodes
|
|
68
|
+
│ │
|
|
69
|
+
│ ├── Structural Blocks
|
|
70
|
+
│ │ ├── @heading (alias: @h)
|
|
71
|
+
│ │ ├── @paragraph (alias: @p)
|
|
72
|
+
│ │ ├── @quote
|
|
73
|
+
│ │ ├── @list
|
|
74
|
+
│ │ ├── @code
|
|
75
|
+
│ │ ├── @img
|
|
76
|
+
│ │ ├── @table
|
|
77
|
+
│ │ ├── @hr
|
|
78
|
+
│ │ └── @svg
|
|
79
|
+
│ │
|
|
80
|
+
│ ├── Container Blocks
|
|
81
|
+
│ │ ├── @details
|
|
82
|
+
│ │ └── @card
|
|
83
|
+
│ │
|
|
84
|
+
│ ├── Callout Blocks
|
|
85
|
+
│ │ ├── @note
|
|
86
|
+
│ │ ├── @tip
|
|
87
|
+
│ │ ├── @important
|
|
88
|
+
│ │ ├── @warning
|
|
89
|
+
│ │ └── @caution
|
|
90
|
+
│ │
|
|
91
|
+
│ └── Widget Blocks
|
|
92
|
+
│ ├── @tabs
|
|
93
|
+
│ ├── @tab
|
|
94
|
+
│ └── @mermaid
|
|
95
|
+
│
|
|
96
|
+
└── Inline Nodes
|
|
97
|
+
│
|
|
98
|
+
├── Text Formatting
|
|
99
|
+
│ ├── @mark
|
|
100
|
+
│ ├── @color
|
|
101
|
+
│ ├── @bordered
|
|
102
|
+
│ ├── @bold (alias: @b)
|
|
103
|
+
│ ├── @italic (alias: @i)
|
|
104
|
+
│ ├── @underline (alias: @u)
|
|
105
|
+
│ ├── @del
|
|
106
|
+
│ └── @raw
|
|
107
|
+
│
|
|
108
|
+
├── Semantic Inline
|
|
109
|
+
│ ├── @sup
|
|
110
|
+
│ ├── @sub
|
|
111
|
+
│ ├── @kbd
|
|
112
|
+
│ └── @link
|
|
113
|
+
│
|
|
114
|
+
├── Footnotes
|
|
115
|
+
│ ├── @fn
|
|
116
|
+
│ └── @defn
|
|
117
|
+
│
|
|
118
|
+
└── Special Nodes
|
|
119
|
+
├── @n
|
|
120
|
+
└── @@
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## 3. EBNF
|
|
126
|
+
|
|
127
|
+
```ebnf
|
|
128
|
+
document =
|
|
129
|
+
[ metadata ],
|
|
130
|
+
{ block-node } ;
|
|
131
|
+
|
|
132
|
+
block-node =
|
|
133
|
+
heading
|
|
134
|
+
| paragraph
|
|
135
|
+
| quote
|
|
136
|
+
| list
|
|
137
|
+
| code
|
|
138
|
+
| image
|
|
139
|
+
| table
|
|
140
|
+
| hr
|
|
141
|
+
| svg
|
|
142
|
+
| details
|
|
143
|
+
| card
|
|
144
|
+
| note
|
|
145
|
+
| tip
|
|
146
|
+
| important
|
|
147
|
+
| warning
|
|
148
|
+
| caution
|
|
149
|
+
| tabs
|
|
150
|
+
| mermaid ;
|
|
151
|
+
|
|
152
|
+
(* Note:
|
|
153
|
+
`tab` is not part of block-node.
|
|
154
|
+
It is child-node syntax exclusive to @tabs, and can only appear within
|
|
155
|
+
tabs-content — see "Widget-Specific Grammar: @tabs" below for details.
|
|
156
|
+
*)
|
|
157
|
+
|
|
158
|
+
metadata =
|
|
159
|
+
"@meta" , meta-content ;
|
|
160
|
+
|
|
161
|
+
(* meta-content is lexed the same way as block-content — the "[" / "]" pair
|
|
162
|
+
tokenizes normally, so an unregistered "@word" still falls back to plain
|
|
163
|
+
text per §6 Unknown Command Fallback — but Parser.ts is semantically
|
|
164
|
+
stricter here than for any other block node: it rejects every registered
|
|
165
|
+
node inside @meta, not just structural ones, not even @n or @raw. The
|
|
166
|
+
parser then splits the resulting text on newlines and the first "=" on
|
|
167
|
+
each line into key/value pairs and stores them directly on the AST node
|
|
168
|
+
(MetaNode.meta), rather than leaving that structuring to a later pass.
|
|
169
|
+
See Metadata.md §3/§6 for the full behavior and worked examples. *)
|
|
170
|
+
meta-content =
|
|
171
|
+
"[" ,
|
|
172
|
+
{ text } ,
|
|
173
|
+
"]" ;
|
|
174
|
+
|
|
175
|
+
heading =
|
|
176
|
+
( "@heading" | "@h" ) ,
|
|
177
|
+
[ "(" , level , ")" ] ,
|
|
178
|
+
block-content ;
|
|
179
|
+
|
|
180
|
+
paragraph =
|
|
181
|
+
( "@paragraph" | "@p" ) , block-content ;
|
|
182
|
+
|
|
183
|
+
quote =
|
|
184
|
+
"@quote" , block-content ;
|
|
185
|
+
|
|
186
|
+
list =
|
|
187
|
+
"@list" ,
|
|
188
|
+
[ "(" , "ordered" , ")" ] ,
|
|
189
|
+
block-content ;
|
|
190
|
+
|
|
191
|
+
code =
|
|
192
|
+
"@code" ,
|
|
193
|
+
[ language ] ,
|
|
194
|
+
raw-block-content ;
|
|
195
|
+
|
|
196
|
+
image =
|
|
197
|
+
"@img" ,
|
|
198
|
+
"(" ,
|
|
199
|
+
image-option-list ,
|
|
200
|
+
")" ,
|
|
201
|
+
[ styles ] ,
|
|
202
|
+
block-content ;
|
|
203
|
+
|
|
204
|
+
hr =
|
|
205
|
+
"@hr" ;
|
|
206
|
+
|
|
207
|
+
svg =
|
|
208
|
+
"@svg" ,
|
|
209
|
+
raw-block-content ;
|
|
210
|
+
|
|
211
|
+
details =
|
|
212
|
+
"@details" ,
|
|
213
|
+
[ title ] ,
|
|
214
|
+
[ styles ] ,
|
|
215
|
+
block-content ;
|
|
216
|
+
|
|
217
|
+
card =
|
|
218
|
+
"@card" ,
|
|
219
|
+
[ title ] ,
|
|
220
|
+
[ styles ] ,
|
|
221
|
+
block-content ;
|
|
222
|
+
|
|
223
|
+
note =
|
|
224
|
+
"@note" ,
|
|
225
|
+
[ title ] ,
|
|
226
|
+
[ styles ] ,
|
|
227
|
+
block-content ;
|
|
228
|
+
|
|
229
|
+
tip =
|
|
230
|
+
"@tip" ,
|
|
231
|
+
[ title ] ,
|
|
232
|
+
[ styles ] ,
|
|
233
|
+
block-content ;
|
|
234
|
+
|
|
235
|
+
important =
|
|
236
|
+
"@important" ,
|
|
237
|
+
[ title ] ,
|
|
238
|
+
[ styles ] ,
|
|
239
|
+
block-content ;
|
|
240
|
+
|
|
241
|
+
warning =
|
|
242
|
+
"@warning" ,
|
|
243
|
+
[ title ] ,
|
|
244
|
+
[ styles ] ,
|
|
245
|
+
block-content ;
|
|
246
|
+
|
|
247
|
+
caution =
|
|
248
|
+
"@caution" ,
|
|
249
|
+
[ title ] ,
|
|
250
|
+
[ styles ] ,
|
|
251
|
+
block-content ;
|
|
252
|
+
|
|
253
|
+
mermaid =
|
|
254
|
+
"@mermaid" ,
|
|
255
|
+
raw-block-content ;
|
|
256
|
+
|
|
257
|
+
(* ==========================================================================
|
|
258
|
+
Structural-Specific Grammar: @img
|
|
259
|
+
|
|
260
|
+
The parenthesized content of @img is not a single bare text, but a
|
|
261
|
+
comma-separated key=value option list (image-option-list), which is
|
|
262
|
+
extensible. If the first option omits the key, it defaults to src.
|
|
263
|
+
|
|
264
|
+
The `image` production (above) also has an independent, optional
|
|
265
|
+
[styles] after ")" — Image Style v1, which at the grammar level is
|
|
266
|
+
completely unrelated to image-option-list (it cannot be written inside
|
|
267
|
+
the parentheses); see the "Image Style v1" subsection below for its
|
|
268
|
+
semantics.
|
|
269
|
+
========================================================================== *)
|
|
270
|
+
|
|
271
|
+
image-option-list =
|
|
272
|
+
image-option ,
|
|
273
|
+
{ "," , image-option } ;
|
|
274
|
+
|
|
275
|
+
image-option =
|
|
276
|
+
src-option
|
|
277
|
+
| width-option
|
|
278
|
+
| height-option
|
|
279
|
+
| align-option
|
|
280
|
+
| radius-option
|
|
281
|
+
| border-option ;
|
|
282
|
+
|
|
283
|
+
src-option =
|
|
284
|
+
[ "src=" ] , url ;
|
|
285
|
+
|
|
286
|
+
width-option =
|
|
287
|
+
"width=" , integer ;
|
|
288
|
+
|
|
289
|
+
height-option =
|
|
290
|
+
"height=" , integer ;
|
|
291
|
+
|
|
292
|
+
align-option =
|
|
293
|
+
"align=" , ( "left" | "center" | "right" ) ;
|
|
294
|
+
|
|
295
|
+
radius-option =
|
|
296
|
+
"radius=" , text ;
|
|
297
|
+
|
|
298
|
+
border-option =
|
|
299
|
+
"border=" , text ;
|
|
300
|
+
|
|
301
|
+
url =
|
|
302
|
+
{ text-char - "," - ")" } ;
|
|
303
|
+
|
|
304
|
+
(* ==========================================================================
|
|
305
|
+
Widget-Specific Grammar: @table
|
|
306
|
+
|
|
307
|
+
@table does not use the generic block-content; instead it has its own
|
|
308
|
+
dedicated structured syntax (Columns + Rows).
|
|
309
|
+
========================================================================== *)
|
|
310
|
+
|
|
311
|
+
table =
|
|
312
|
+
"@table" , table-content ;
|
|
313
|
+
|
|
314
|
+
table-content =
|
|
315
|
+
"[" ,
|
|
316
|
+
cols ,
|
|
317
|
+
data ,
|
|
318
|
+
"]" ;
|
|
319
|
+
|
|
320
|
+
cols =
|
|
321
|
+
"@cols" ,
|
|
322
|
+
"[" ,
|
|
323
|
+
column-list ,
|
|
324
|
+
"]" ;
|
|
325
|
+
|
|
326
|
+
column-list =
|
|
327
|
+
cell ,
|
|
328
|
+
{ "," , cell } ;
|
|
329
|
+
|
|
330
|
+
data =
|
|
331
|
+
"@data" ,
|
|
332
|
+
"[" ,
|
|
333
|
+
{ row } ,
|
|
334
|
+
"]" ;
|
|
335
|
+
|
|
336
|
+
row =
|
|
337
|
+
"[" ,
|
|
338
|
+
cell ,
|
|
339
|
+
{ "," , cell } ,
|
|
340
|
+
"]" ;
|
|
341
|
+
|
|
342
|
+
(* A cell isn't plain text only — it also allows a curated subset of
|
|
343
|
+
inline-node (cell-inline-node), the same shape @cols columns and @data
|
|
344
|
+
cells share. The authoritative allowlist lives in registry.ts's
|
|
345
|
+
isCellAllowedNode(), not this grammar — a node outside that set (e.g.
|
|
346
|
+
@card, @table, @details) MUST throw rather than being silently dropped,
|
|
347
|
+
per Strict Mode (Inline Syntax Specification §11). *)
|
|
348
|
+
cell =
|
|
349
|
+
{ cell-inline-node | any-unicode-char - "," - "]" } ;
|
|
350
|
+
|
|
351
|
+
(* ==========================================================================
|
|
352
|
+
Widget-Specific Grammar: @tabs / @tab
|
|
353
|
+
|
|
354
|
+
@tab can only appear within @tabs' tabs-content; it does not belong to
|
|
355
|
+
the generic block-node set, and therefore cannot appear on its own at
|
|
356
|
+
the top level of a document or within any other block-content.
|
|
357
|
+
========================================================================== *)
|
|
358
|
+
|
|
359
|
+
tabs =
|
|
360
|
+
"@tabs" , tabs-content ;
|
|
361
|
+
|
|
362
|
+
tabs-content =
|
|
363
|
+
"[" ,
|
|
364
|
+
{ tab } ,
|
|
365
|
+
"]" ;
|
|
366
|
+
|
|
367
|
+
tab =
|
|
368
|
+
"@tab" ,
|
|
369
|
+
"(" ,
|
|
370
|
+
text ,
|
|
371
|
+
")" ,
|
|
372
|
+
block-content ;
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
---
|
|
376
|
+
|
|
377
|
+
## 4. Shared Components
|
|
378
|
+
|
|
379
|
+
```ebnf
|
|
380
|
+
block-content =
|
|
381
|
+
"[" ,
|
|
382
|
+
{ block-element } ,
|
|
383
|
+
"]" ;
|
|
384
|
+
|
|
385
|
+
block-element =
|
|
386
|
+
block-node
|
|
387
|
+
| inline-stream
|
|
388
|
+
| text ;
|
|
389
|
+
|
|
390
|
+
raw-block-content =
|
|
391
|
+
"[" ,
|
|
392
|
+
{ any-unicode-char } ,
|
|
393
|
+
"]" ;
|
|
394
|
+
|
|
395
|
+
title =
|
|
396
|
+
"(" ,
|
|
397
|
+
text ,
|
|
398
|
+
")" ;
|
|
399
|
+
|
|
400
|
+
language =
|
|
401
|
+
"(" ,
|
|
402
|
+
text ,
|
|
403
|
+
")" ;
|
|
404
|
+
|
|
405
|
+
level =
|
|
406
|
+
"1"
|
|
407
|
+
| "2"
|
|
408
|
+
| "3"
|
|
409
|
+
| "4"
|
|
410
|
+
| "5"
|
|
411
|
+
| "6" ;
|
|
412
|
+
|
|
413
|
+
text =
|
|
414
|
+
{ any-unicode-char } ;
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
> The terminal definitions `integer`, `text-char`, etc. reuse the `integer`
|
|
418
|
+
> and `text-char` productions from Inline Spec §4 (Complete EBNF Grammar
|
|
419
|
+
> Definition); both documents share the same character-set definitions, so
|
|
420
|
+
> they are not repeated here.
|
|
421
|
+
>
|
|
422
|
+
> `styles` likewise reuses the `styles` production from Inline Spec §4
|
|
423
|
+
> (`"{" , { text-char - "}" } , "}"`); at the grammar level it is still only
|
|
424
|
+
> defined as "an arbitrary character sequence wrapped in curly braces."
|
|
425
|
+
> Container Blocks (`@details`, `@card`), Callout Blocks (`@note`, `@tip`,
|
|
426
|
+
> `@important`, `@warning`, `@caution`), and `@img` now formally include it
|
|
427
|
+
> in their respective productions (see §5–7 above), rather than it being
|
|
428
|
+
> incidental Parser-side behavior not explicitly sanctioned by the EBNF.
|
|
429
|
+
>
|
|
430
|
+
> **Token semantics are each node's own rules, not a single shared table.**
|
|
431
|
+
> `@note`/`@tip`/`@important`/`@warning`/`@caution`/`@details` reuse the
|
|
432
|
+
> existing color token rules from Inline Spec §7 `@mark Styles Semantics`
|
|
433
|
+
> (named-token lookup table + hex support); `@card` and `@img` are each
|
|
434
|
+
> their own independent, closed token set — `Card Style v1` (see the
|
|
435
|
+
> "Card Style v1" subsection in §6 below) and `Image Style v1` (see the
|
|
436
|
+
> "Image Style v1" subsection in §5 below) respectively — sharing the same
|
|
437
|
+
> `#RRGGBB` / `radius-N` token shapes, but with independent semantics
|
|
438
|
+
> (`@card`'s hex is a background color, `@img`'s hex is a border color);
|
|
439
|
+
> neither reuses the named color swatch from Inline Spec §7.
|
|
440
|
+
> Whether/how the renderer maps `styles` for Container/Callout/`@img` into
|
|
441
|
+
> visual styling is left to each renderer to decide.
|
|
442
|
+
|
|
443
|
+
---
|
|
444
|
+
|
|
445
|
+
## 5. Structural Blocks
|
|
446
|
+
|
|
447
|
+
### Heading
|
|
448
|
+
|
|
449
|
+
The canonical syntax is `@heading`; `@h` is an equivalent Simplified Alias — both parse to the same AST node, and the renderer does not distinguish which form the author actually typed.
|
|
450
|
+
|
|
451
|
+
```text
|
|
452
|
+
@heading(1)[
|
|
453
|
+
Introduction
|
|
454
|
+
]
|
|
455
|
+
|
|
456
|
+
@h(1)[
|
|
457
|
+
Introduction
|
|
458
|
+
]
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
HTML (both forms produce the same output):
|
|
462
|
+
|
|
463
|
+
```html
|
|
464
|
+
<h1>Introduction</h1>
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
---
|
|
468
|
+
|
|
469
|
+
### Paragraph
|
|
470
|
+
|
|
471
|
+
The canonical syntax is `@paragraph`; `@p` is an equivalent Simplified Alias.
|
|
472
|
+
|
|
473
|
+
```text
|
|
474
|
+
@paragraph[
|
|
475
|
+
Hello World
|
|
476
|
+
]
|
|
477
|
+
|
|
478
|
+
@p[
|
|
479
|
+
Hello World
|
|
480
|
+
]
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
HTML (both forms produce the same output):
|
|
484
|
+
|
|
485
|
+
```html
|
|
486
|
+
<p>Hello World</p>
|
|
487
|
+
```
|
|
488
|
+
|
|
489
|
+
---
|
|
490
|
+
|
|
491
|
+
### Quote
|
|
492
|
+
|
|
493
|
+
```text
|
|
494
|
+
@quote[
|
|
495
|
+
Talk is cheap.
|
|
496
|
+
Show me the code.
|
|
497
|
+
]
|
|
498
|
+
```
|
|
499
|
+
|
|
500
|
+
HTML:
|
|
501
|
+
|
|
502
|
+
```html
|
|
503
|
+
<blockquote>
|
|
504
|
+
Talk is cheap.
|
|
505
|
+
Show me the code.
|
|
506
|
+
</blockquote>
|
|
507
|
+
```
|
|
508
|
+
|
|
509
|
+
---
|
|
510
|
+
|
|
511
|
+
### List
|
|
512
|
+
|
|
513
|
+
Any non-empty line is an item; a leading `- ` is an **optional** backward-compatible form that the Parser automatically strips:
|
|
514
|
+
|
|
515
|
+
```text
|
|
516
|
+
@list[
|
|
517
|
+
Apple
|
|
518
|
+
Banana
|
|
519
|
+
Orange
|
|
520
|
+
]
|
|
521
|
+
```
|
|
522
|
+
|
|
523
|
+
This is equivalent to:
|
|
524
|
+
|
|
525
|
+
```text
|
|
526
|
+
@list[
|
|
527
|
+
- Apple
|
|
528
|
+
- Banana
|
|
529
|
+
- Orange
|
|
530
|
+
]
|
|
531
|
+
```
|
|
532
|
+
|
|
533
|
+
Each item is an independent `list-item` node in the AST (`node.items`); its content can include inline nodes (e.g. `@bold`), not just plain text:
|
|
534
|
+
|
|
535
|
+
```text
|
|
536
|
+
@list[
|
|
537
|
+
@bold[Apple] (today's special)
|
|
538
|
+
Banana
|
|
539
|
+
]
|
|
540
|
+
```
|
|
541
|
+
|
|
542
|
+
AST:
|
|
543
|
+
|
|
544
|
+
```text
|
|
545
|
+
List
|
|
546
|
+
└── items
|
|
547
|
+
├── ListItem [ Bold("Apple"), " (today's special)" ]
|
|
548
|
+
└── ListItem [ "Banana" ]
|
|
549
|
+
```
|
|
550
|
+
|
|
551
|
+
> [!TIP]
|
|
552
|
+
> **TIP**: The old semantics required "must start with `- ` to count as an item," which was inconsistent with the intuition that "a newline means a new item," and also led every renderer (Route A / Route B / ...) to reimplement its own list-splitting logic via string processing. Under the new semantics, the Parser uniformly produces the `ListItem` AST, and renderers only need to render the existing structure without splitting strings themselves.
|
|
553
|
+
|
|
554
|
+
#### Ordered List
|
|
555
|
+
|
|
556
|
+
`@list(ordered)[...]` renders as `<ol>` instead of the default `<ul>`. As with a regular `@list`, a leading `- ` is optional and not required — a plain text line still counts as an item; explicitly writing `N. `/`N)` specifies the number explicitly, and the Parser stores that number in the `ListItem`'s `marker` field. The renderer only converts `marker` into `<li value="N">` when `ordered` is true, leaving the native `<ol>` counter in the browser to handle "auto-continuing after a skipped number":
|
|
557
|
+
|
|
558
|
+
```text
|
|
559
|
+
@list(ordered)[
|
|
560
|
+
- Apple
|
|
561
|
+
- Banana
|
|
562
|
+
3. Cherry
|
|
563
|
+
- Date
|
|
564
|
+
]
|
|
565
|
+
```
|
|
566
|
+
|
|
567
|
+
The rendered result is `1. Apple`, `2. Banana`, `3. Cherry` (explicitly specified), `4. Date` (auto-continued).
|
|
568
|
+
|
|
569
|
+
#### Nested List
|
|
570
|
+
|
|
571
|
+
No new syntax is introduced — the content of `@list` is already `block-content`, so a nested `@list[...]` is already a valid child node. A nested `@list[...]` occupying its own line (with only whitespace before and after) is merged by the Parser into the content of the **preceding** item, rather than starting a new item:
|
|
572
|
+
|
|
573
|
+
```text
|
|
574
|
+
@list[
|
|
575
|
+
- Fruits
|
|
576
|
+
@list[
|
|
577
|
+
- Apple
|
|
578
|
+
- Banana
|
|
579
|
+
]
|
|
580
|
+
- Vegetables
|
|
581
|
+
]
|
|
582
|
+
```
|
|
583
|
+
|
|
584
|
+
In the AST, the inner `@list` node appears within the `content` array of the `Fruits` `ListItem`; the renderer needs no extra logic — recursively rendering `content` naturally produces the nested `<ul>`/`<ol>`.
|
|
585
|
+
> An older version of the document once mentioned a proposal to declare list type per level using a `(modifier)` array (e.g. `@list(bullet,number)[...]`); the design above — `@list(ordered)` plus nested sublists each declaring their own type — is the simpler approach that was actually adopted, instead of that proposal.
|
|
586
|
+
|
|
587
|
+
---
|
|
588
|
+
|
|
589
|
+
### Code
|
|
590
|
+
|
|
591
|
+
```text
|
|
592
|
+
@code(ts)[
|
|
593
|
+
const x = 1;
|
|
594
|
+
]
|
|
595
|
+
```
|
|
596
|
+
|
|
597
|
+
HTML:
|
|
598
|
+
|
|
599
|
+
```html
|
|
600
|
+
<pre><code class="language-ts">
|
|
601
|
+
const x = 1;
|
|
602
|
+
</code></pre>
|
|
603
|
+
```
|
|
604
|
+
|
|
605
|
+
---
|
|
606
|
+
|
|
607
|
+
### Image
|
|
608
|
+
|
|
609
|
+
The parenthesized content of `@img` is a comma-separated key=value option list (`image-option-list`), which is extensible. If the first option omits `key=`, it defaults to `src`:
|
|
610
|
+
|
|
611
|
+
```text
|
|
612
|
+
@img(
|
|
613
|
+
https://example.com/logo.png
|
|
614
|
+
)[
|
|
615
|
+
WEDC Logo
|
|
616
|
+
]
|
|
617
|
+
```
|
|
618
|
+
|
|
619
|
+
This is equivalent to:
|
|
620
|
+
|
|
621
|
+
```text
|
|
622
|
+
@img(src=https://example.com/logo.png)[
|
|
623
|
+
WEDC Logo
|
|
624
|
+
]
|
|
625
|
+
```
|
|
626
|
+
|
|
627
|
+
Used together with other options:
|
|
628
|
+
|
|
629
|
+
```text
|
|
630
|
+
@img(
|
|
631
|
+
https://example.com/logo.png,width=200,align=center
|
|
632
|
+
)[
|
|
633
|
+
WEDC Logo
|
|
634
|
+
]
|
|
635
|
+
```
|
|
636
|
+
|
|
637
|
+
Currently supported options:
|
|
638
|
+
|
|
639
|
+
| Option | Description | Example value |
|
|
640
|
+
| ------------- | ----------------------------------- | -------------------------- |
|
|
641
|
+
| `src` (optional) | Image source URL | `src=https://...` |
|
|
642
|
+
| `width` | Display width (unit decided by the renderer) | `width=200` |
|
|
643
|
+
| `height` | Display height (unit decided by the renderer) | `height=150` |
|
|
644
|
+
| `align` | Alignment | `align=left/center/right` |
|
|
645
|
+
| `radius` | Corner radius (CSS value passed directly through to the renderer) | `radius=8px` |
|
|
646
|
+
| `border` | Border (CSS value passed directly through to the renderer) | `border=1px solid #ccc` |
|
|
647
|
+
|
|
648
|
+
> [!TIP]
|
|
649
|
+
> **TIP**: This extension mechanism follows the same design philosophy as Inline Spec §7 `@mark Styles Semantics` — the grammar level only defines "a comma-separated option list inside parentheses"; the actual set of keys belongs to the semantic level, so adding new options in the future (e.g. `alt`, `loading`) does not require modifying the EBNF itself. The renderer MUST ignore unrecognized keys, and SHOULD fall back to "applying only `src`" rather than throwing an error.
|
|
650
|
+
|
|
651
|
+
#### Image Style v1
|
|
652
|
+
|
|
653
|
+
`@img(...)` can be followed by an optional `{styles}` (grammar defined in §4), which shares the same **Card Style v1** token shape (`#RRGGBB` / `radius-N`) as `@card`, but with independent semantics forming its own closed token set — it **does not reuse** the named color swatch from Inline Spec §7, and it is **not** part of `image-option-list` (it cannot be written inside the `(...)` parentheses):
|
|
654
|
+
|
|
655
|
+
| Token shape | Semantics | Example |
|
|
656
|
+
|---|---|---|
|
|
657
|
+
| `#RRGGBB` (hexadecimal) | Border color, applied as a 1px solid border | `@img(src=...){#3366ff}[...]` → `border: 1px solid #3366ff` |
|
|
658
|
+
| `radius-N` (N is a non-negative integer) | Corner radius, `N` is a pixel value | `@img(src=...){radius-12}[...]` → `border-radius: 12px` |
|
|
659
|
+
|
|
660
|
+
```text
|
|
661
|
+
@img(src=https://example.com/photo.jpg){#3366ff,radius-12}[
|
|
662
|
+
WEDC Photo
|
|
663
|
+
]
|
|
664
|
+
```
|
|
665
|
+
|
|
666
|
+
When `{styles}` is omitted, the result is a plain, bare `<img>` with no default corner radius or border — unlike `@card`, which usually has the renderer's own static defaults that can be overridden, `{styles}` for `@img` is purely an "optional" switch, not an "override the default" one.
|
|
667
|
+
|
|
668
|
+
> [!NOTE]
|
|
669
|
+
> **NOTE**: The existing `radius`/`border` `(...)` options (see the table above) remain valid, serving as an escape hatch for cases that need arbitrary CSS values (e.g. `border=2px dashed red`); `{styles}` is the cross-platform, closed-token-set shorthand. When both appear together, the renderer SHOULD let `{styles}` override the corresponding `(...)` option (`{radius-N}` overrides `radius=`, `{#RRGGBB}` overrides `border=`), rather than stacking the two or throwing an error.
|
|
670
|
+
|
|
671
|
+
---
|
|
672
|
+
|
|
673
|
+
### Table
|
|
674
|
+
|
|
675
|
+
The internal structure of `@table` is fixed as two dedicated child nodes, `@cols` + `@data`, **in a fixed order, both required**:
|
|
676
|
+
|
|
677
|
+
```text
|
|
678
|
+
@table[
|
|
679
|
+
@cols[id,name,price]
|
|
680
|
+
|
|
681
|
+
@data[
|
|
682
|
+
[1,Breakfast,60]
|
|
683
|
+
[2,Lunch,80]
|
|
684
|
+
[3,Dinner,90]
|
|
685
|
+
]
|
|
686
|
+
]
|
|
687
|
+
```
|
|
688
|
+
|
|
689
|
+
* `@cols[...]`: a comma-separated list of column headers that defines the column order and count; each column is a `cell` (see below) just like `@data`'s cells, not limited to plain-text identifiers.
|
|
690
|
+
* `@data[...]`: each row is wrapped in `[...]`; the number of `cell`s SHOULD match the number of columns defined by `@cols`. The Parser MAY throw a warning or error for a row whose count doesn't match (decided by Strict / Editor Mode, see Inline Spec §11 Parser Recovery Strategy).
|
|
691
|
+
|
|
692
|
+
> [!TIP]
|
|
693
|
+
> **TIP**: The fixed order and required presence of both `@cols` and `@data` is a deliberate design trade-off — sacrificing a bit of flexibility in exchange for a high degree of predictability, both for the Parser and for AI-generated content.
|
|
694
|
+
|
|
695
|
+
Each `cell` is not merely plain text — besides the text itself, it also allows a curated set of inline formatting nodes (`@bold`, `@italic`, `@underline`, `@del`, `@mark`, `@color`, `@sup`, `@sub`, `@link`, `@fn`, and `@n`, which is converted into a line break), because these nodes only change how the text is presented and do not affect the table's own "columns aligned with data rows" structure. This list is maintained on the renderer side (`isCellAllowedNode` in `registry.ts`); the grammar level itself does not restrict the list's contents, and it can be extended in the future. A node not on the list (e.g. block nodes that bring their own layout structure, such as `@card`, `@table`, `@details`) MUST throw a syntax error rather than being silently dropped — this is consistent with the spirit of Strict Mode (Inline Syntax Specification §11): "prefer to throw an error rather than swallow erroneous content."
|
|
696
|
+
|
|
697
|
+
> [!NOTE]
|
|
698
|
+
> **Exception**: the raw family of nodes (`@code`, `@mermaid`, `@raw`, `@kbd`) are also not on the `isCellAllowedNode` list, but they are neither "block nodes that bring their own layout structure" nor subject to the MUST-throw rule above — `Parser.ts` (`parseInlineCellList`) deliberately flattens their raw content into plain text inside the cell, rather than throwing an error or parsing them as real nodes. This is separate behavior from how structural nodes like `@card`/`@table`/`@details` are handled; see the comments above `CELL_ALLOWED_INLINE` in `registry.ts` and above `parseInlineCellList` in `Parser.ts` for details.
|
|
699
|
+
|
|
700
|
+
```text
|
|
701
|
+
@table[
|
|
702
|
+
@cols[id,name,note]
|
|
703
|
+
|
|
704
|
+
@data[
|
|
705
|
+
[1,@bold[Alice],See @link(https://example.com)[profile]@n more info]
|
|
706
|
+
]
|
|
707
|
+
]
|
|
708
|
+
```
|
|
709
|
+
|
|
710
|
+
AST:
|
|
711
|
+
|
|
712
|
+
```text
|
|
713
|
+
Table
|
|
714
|
+
├── Columns
|
|
715
|
+
│ ├── id
|
|
716
|
+
│ ├── name
|
|
717
|
+
│ └── price
|
|
718
|
+
└── Rows
|
|
719
|
+
├── Row [1, Breakfast, 60]
|
|
720
|
+
├── Row [2, Lunch, 80]
|
|
721
|
+
└── Row [3, Dinner, 90]
|
|
722
|
+
```
|
|
723
|
+
|
|
724
|
+
Or, with cells containing inline formatting:
|
|
725
|
+
|
|
726
|
+
```text
|
|
727
|
+
Table
|
|
728
|
+
├── Columns
|
|
729
|
+
│ ├── id
|
|
730
|
+
│ ├── name
|
|
731
|
+
│ └── note
|
|
732
|
+
└── Rows
|
|
733
|
+
└── Row [
|
|
734
|
+
"1",
|
|
735
|
+
[ Bold("Alice") ],
|
|
736
|
+
[ "See ", Link("https://example.com", "profile"), "\n", " more info" ]
|
|
737
|
+
]
|
|
738
|
+
```
|
|
739
|
+
|
|
740
|
+
---
|
|
741
|
+
|
|
742
|
+
### Horizontal Rule
|
|
743
|
+
|
|
744
|
+
```text
|
|
745
|
+
@hr
|
|
746
|
+
```
|
|
747
|
+
|
|
748
|
+
HTML:
|
|
749
|
+
|
|
750
|
+
```html
|
|
751
|
+
<hr>
|
|
752
|
+
```
|
|
753
|
+
|
|
754
|
+
---
|
|
755
|
+
|
|
756
|
+
### SVG
|
|
757
|
+
|
|
758
|
+
`@svg` belongs to `raw-block-content`, the same as `@code`/`@mermaid` — the content is preserved verbatim; the Parser does not parse or escape it:
|
|
759
|
+
|
|
760
|
+
```text
|
|
761
|
+
@svg[
|
|
762
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 10 10">
|
|
763
|
+
<circle cx="5" cy="5" r="4" />
|
|
764
|
+
</svg>
|
|
765
|
+
]
|
|
766
|
+
```
|
|
767
|
+
|
|
768
|
+
> [!TIP]
|
|
769
|
+
> **TIP**: The content of `@svg` is a **trust boundary** — it is output verbatim by the renderer as a vector graphic actually rendered by the browser, rather than displayed as text the way `@code` is. The renderer SHOULD filter out `<script>` tags and `on*=` event attributes before output (see `sanitizeSvg()` in `Adapters.ts`), but this is a renderer responsibility, not a grammar-level guarantee; `@svg` content from untrusted sources should still be content-reviewed at an earlier stage.
|
|
770
|
+
|
|
771
|
+
---
|
|
772
|
+
|
|
773
|
+
## 6. Container Blocks
|
|
774
|
+
|
|
775
|
+
`@details`/`@card` now also accept an **optional** `{styles}` (grammar defined in §4), placed after `(title)` and before `block-content`:
|
|
776
|
+
|
|
777
|
+
```text
|
|
778
|
+
@card(API Key){#3366ff,radius-12}[
|
|
779
|
+
Put the description content here.
|
|
780
|
+
]
|
|
781
|
+
```
|
|
782
|
+
|
|
783
|
+
When omitted, the plain-content form is retained — both are valid. The renderer MAY ignore unrecognized tokens (consistent with the spirit of Inline Spec §6 Unknown Command Fallback). The semantics of `@card`'s `{styles}` tokens are its own closed rule set (`Card Style v1`), unrelated to the named color token lookup table in Inline Spec §7 — see the "Card Style v1" subsection below.
|
|
784
|
+
|
|
785
|
+
### Details
|
|
786
|
+
|
|
787
|
+
```text
|
|
788
|
+
@details(Show more)[
|
|
789
|
+
Content
|
|
790
|
+
]
|
|
791
|
+
```
|
|
792
|
+
|
|
793
|
+
HTML:
|
|
794
|
+
|
|
795
|
+
```html
|
|
796
|
+
<details>
|
|
797
|
+
<summary>Show more</summary>
|
|
798
|
+
Content
|
|
799
|
+
</details>
|
|
800
|
+
```
|
|
801
|
+
|
|
802
|
+
---
|
|
803
|
+
|
|
804
|
+
### Card
|
|
805
|
+
|
|
806
|
+
```text
|
|
807
|
+
@card(API Key)[
|
|
808
|
+
Put the description content here.
|
|
809
|
+
]
|
|
810
|
+
```
|
|
811
|
+
|
|
812
|
+
#### Card Style v1
|
|
813
|
+
|
|
814
|
+
`@card`'s `{styles}` only allows a small number of cross-platform, high-value styles, deliberately not designed as a general-purpose CSS escape hatch — currently only the following two token shapes are recognized; they can each appear alone, be combined together (comma-separated, order not significant), or be omitted entirely:
|
|
815
|
+
|
|
816
|
+
| Token shape | Semantics | Example |
|
|
817
|
+
|---|---|---|
|
|
818
|
+
| `#RRGGBB` (hexadecimal) | Background color, using the value directly | `@card{#3366ff}[...]` → `background-color: #3366ff` |
|
|
819
|
+
| `radius-N` (N is a non-negative integer) | Corner radius, `N` is a pixel value | `@card{radius-12}[...]` → `border-radius: 12px` |
|
|
820
|
+
|
|
821
|
+
```text
|
|
822
|
+
@card{#3366ff,radius-12}[
|
|
823
|
+
Setting both background color and corner radius at the same time.
|
|
824
|
+
]
|
|
825
|
+
```
|
|
826
|
+
|
|
827
|
+
Tokens not in the table above (e.g. named color words, or the color tokens from Inline Spec §7) are always treated as unrecognized; the renderer MUST ignore them rather than throwing an error (consistent with the spirit of Inline Spec §6 Unknown Command Fallback), and fall back to its own default appearance. If `radius-N`'s `N` is not a pure number (e.g. `radius-lg`), it is likewise treated as unrecognized.
|
|
828
|
+
|
|
829
|
+
---
|
|
830
|
+
|
|
831
|
+
## 7. Callout Blocks
|
|
832
|
+
|
|
833
|
+
`@note`, `@tip`, `@important`, `@warning`, and `@caution` can all be paired with an **optional** `(title)` (defined in §4) to attach a title field independent of the body content; they can also be paired with an **optional** `{styles}` (see §4 and the same explanation in §6 Container Blocks), placed after `(title)`. When both are omitted, the plain-content form is retained — all forms are valid:
|
|
834
|
+
|
|
835
|
+
### Note
|
|
836
|
+
|
|
837
|
+
```text
|
|
838
|
+
@note[
|
|
839
|
+
This is general information.
|
|
840
|
+
]
|
|
841
|
+
```
|
|
842
|
+
|
|
843
|
+
---
|
|
844
|
+
|
|
845
|
+
### Tip
|
|
846
|
+
|
|
847
|
+
```text
|
|
848
|
+
@tip[
|
|
849
|
+
This is a best-practice recommendation.
|
|
850
|
+
]
|
|
851
|
+
```
|
|
852
|
+
|
|
853
|
+
---
|
|
854
|
+
|
|
855
|
+
### Important
|
|
856
|
+
|
|
857
|
+
```text
|
|
858
|
+
@important[
|
|
859
|
+
Please read this content first.
|
|
860
|
+
]
|
|
861
|
+
```
|
|
862
|
+
|
|
863
|
+
---
|
|
864
|
+
|
|
865
|
+
### Warning
|
|
866
|
+
|
|
867
|
+
```text
|
|
868
|
+
@warning[
|
|
869
|
+
Cannot be undone after deletion.
|
|
870
|
+
]
|
|
871
|
+
```
|
|
872
|
+
|
|
873
|
+
With a title:
|
|
874
|
+
|
|
875
|
+
```text
|
|
876
|
+
@warning(Data Retention Policy)[
|
|
877
|
+
Cannot be undone after deletion.
|
|
878
|
+
]
|
|
879
|
+
```
|
|
880
|
+
|
|
881
|
+
---
|
|
882
|
+
|
|
883
|
+
### Caution
|
|
884
|
+
|
|
885
|
+
```text
|
|
886
|
+
@caution[
|
|
887
|
+
This operation may cause data loss.
|
|
888
|
+
]
|
|
889
|
+
```
|
|
890
|
+
|
|
891
|
+
---
|
|
892
|
+
|
|
893
|
+
## 8. Widget Blocks
|
|
894
|
+
|
|
895
|
+
### Tabs
|
|
896
|
+
|
|
897
|
+
`@tabs` can **only** contain one or more `@tab` child nodes internally; it does not accept other block-nodes or bare text:
|
|
898
|
+
|
|
899
|
+
```text
|
|
900
|
+
@tabs[
|
|
901
|
+
@tab(JavaScript)[
|
|
902
|
+
...
|
|
903
|
+
]
|
|
904
|
+
|
|
905
|
+
@tab(Python)[
|
|
906
|
+
...
|
|
907
|
+
]
|
|
908
|
+
|
|
909
|
+
@tab(Rust)[
|
|
910
|
+
...
|
|
911
|
+
]
|
|
912
|
+
]
|
|
913
|
+
```
|
|
914
|
+
|
|
915
|
+
* `@tab(title)[content]`: `title` is the tab's display name, and `content` is a full `block-content` (may contain any block-node and inline-stream).
|
|
916
|
+
* If a node other than `@tab` appears inside `@tabs[...]` (e.g. bare text or another block-node), the Parser MUST treat it as a syntax error (Strict Mode), or Editor Mode automatically ignores it / prompts a fix.
|
|
917
|
+
|
|
918
|
+
> [!TIP]
|
|
919
|
+
> **TIP**: The reason `@tab` is not folded into `block-node` is to prevent it from being misused outside of `@tabs` (e.g. placed directly at the top level of a document). This is similar in spirit to the Opaque Domain design of `@raw` in the Inline Spec: specific syntax is only valid in a specific context.
|
|
920
|
+
|
|
921
|
+
---
|
|
922
|
+
|
|
923
|
+
### Mermaid
|
|
924
|
+
|
|
925
|
+
```text
|
|
926
|
+
@mermaid[
|
|
927
|
+
graph TD
|
|
928
|
+
A --> B
|
|
929
|
+
]
|
|
930
|
+
```
|
|
931
|
+
|
|
932
|
+
---
|
|
933
|
+
|
|
934
|
+
## 9. Metadata
|
|
935
|
+
|
|
936
|
+
```text
|
|
937
|
+
@meta[
|
|
938
|
+
title = @Doc
|
|
939
|
+
author = WEDC
|
|
940
|
+
description = AI Native Document Format
|
|
941
|
+
keywords = parser,ast,dsl
|
|
942
|
+
]
|
|
943
|
+
```
|
|
944
|
+
|
|
945
|
+
The renderer can map this to:
|
|
946
|
+
|
|
947
|
+
* HTML Meta Tags
|
|
948
|
+
* OpenGraph
|
|
949
|
+
* PDF Metadata
|
|
950
|
+
* DOCX Properties
|
|
951
|
+
* Search Index
|
|
952
|
+
* RAG Metadata
|
|
953
|
+
|
|
954
|
+
---
|
|
955
|
+
|
|
956
|
+
## 10. Core Principle
|
|
957
|
+
|
|
958
|
+
The goal of @Doc Block Syntax is not to invent a new HTML.
|
|
959
|
+
|
|
960
|
+
but rather to establish:
|
|
961
|
+
|
|
962
|
+
> Human Editable
|
|
963
|
+
> Machine Deterministic
|
|
964
|
+
> AI Friendly
|
|
965
|
+
> Cross Platform
|
|
966
|
+
|
|
967
|
+
for the document AST.
|
|
968
|
+
|
|
969
|
+
HTML is a renderer.
|
|
970
|
+
|
|
971
|
+
Markdown is a renderer.
|
|
972
|
+
|
|
973
|
+
React is a renderer.
|
|
974
|
+
|
|
975
|
+
And @Doc is:
|
|
976
|
+
|
|
977
|
+
> Source of Truth.
|
|
978
|
+
|
|
979
|
+
---
|
|
980
|
+
|
|
981
|
+
## 11. Simplified Syntax Aliases
|
|
982
|
+
|
|
983
|
+
Some high-frequency commands additionally provide a Simplified Alias — purely a shorthand at input time. The Parser normalizes it to the canonical name before creating the AST node (`node.type` is always the canonical name); the renderer never needs to, and never does, distinguish which form the author actually typed.
|
|
984
|
+
|
|
985
|
+
Aliases covered by Block Syntax:
|
|
986
|
+
|
|
987
|
+
| Canonical | Alias |
|
|
988
|
+
|---|---|
|
|
989
|
+
| `@heading` | `@h` |
|
|
990
|
+
| `@paragraph` | `@p` |
|
|
991
|
+
|
|
992
|
+
(The Inline Syntax aliases `@b`/`@i`/`@u` for `@bold`/`@italic`/`@underline` are defined in the Inline Syntax Specification.)
|