r-markdown-cli 0.1.0 → 0.1.1
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/dist/cli.js +5 -4
- package/package.json +2 -1
- package/skills/claude/SKILL.md +132 -0
- package/skills/claude/examples/decision-report.rmd +64 -0
- package/skills/claude/examples/tunable-config.rmd +53 -0
- package/skills/claude/references/artifacts.md +118 -0
- package/skills/claude/references/blocks.md +334 -0
- package/skills/codex/SKILL.md +92 -0
- package/skills/codex/agents/openai.yaml +8 -0
- package/skills/codex/references/artifacts.md +107 -0
- package/skills/codex/references/blocks.md +321 -0
package/dist/cli.js
CHANGED
|
@@ -11975,7 +11975,7 @@ async function createPreviewServer(file, options = {}) {
|
|
|
11975
11975
|
|
|
11976
11976
|
// packages/cli/src/index.js
|
|
11977
11977
|
var USAGE = `
|
|
11978
|
-
Rich Markdown (rmd) CLI v0.
|
|
11978
|
+
Rich Markdown (rmd) CLI v0.1.1
|
|
11979
11979
|
|
|
11980
11980
|
Usage:
|
|
11981
11981
|
rmd <command> [options]
|
|
@@ -12045,7 +12045,7 @@ async function main(argv = process.argv.slice(2), io = defaultIo()) {
|
|
|
12045
12045
|
return 0;
|
|
12046
12046
|
}
|
|
12047
12047
|
if (command === "--version" || command === "-v") {
|
|
12048
|
-
io.stdout(`rmd v0.
|
|
12048
|
+
io.stdout(`rmd v0.1.1
|
|
12049
12049
|
`);
|
|
12050
12050
|
return 0;
|
|
12051
12051
|
}
|
|
@@ -12131,8 +12131,9 @@ function parseInitArgs(args) {
|
|
|
12131
12131
|
function resolveSkillSource(platform) {
|
|
12132
12132
|
const __dirname2 = dirname2(fileURLToPath2(import.meta.url));
|
|
12133
12133
|
const candidates = [
|
|
12134
|
-
resolve2(__dirname2, "../
|
|
12135
|
-
resolve2(__dirname2, "../../../skills", platform)
|
|
12134
|
+
resolve2(__dirname2, "../skills", platform),
|
|
12135
|
+
resolve2(__dirname2, "../../../skills", platform),
|
|
12136
|
+
resolve2(__dirname2, "../assets/skills", platform)
|
|
12136
12137
|
];
|
|
12137
12138
|
return candidates.find((candidate) => existsSync(candidate));
|
|
12138
12139
|
}
|
package/package.json
CHANGED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: rich-markdown
|
|
3
|
+
description: Generate Rich Markdown (.rmd) source and self-contained interactive HTML artifacts. Use when the user asks for rmd, Rich Markdown, rich interactive Markdown, token-efficient rich docs, shareable AI documents, charts, sliders, copy/export blocks, flow diagrams, timelines, kanban boards, collapsible details, carousels, embeds, math blocks, comparison reports, PR explainers, tunable prototypes, project status reports, or any rich document that should remain readable as Markdown but render as a polished interactive HTML page.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Rich Markdown
|
|
7
|
+
|
|
8
|
+
Use this skill when the user wants a rich, readable, interactive document
|
|
9
|
+
instead of plain Markdown or hand-written HTML. The local renderer
|
|
10
|
+
(`packages/cli`) turns `.rmd` source into a self-contained HTML artifact that
|
|
11
|
+
renders in Claude's chat / desktop sandbox, in any browser, or as an offline file.
|
|
12
|
+
|
|
13
|
+
## Why .rmd over plain Markdown or HTML
|
|
14
|
+
|
|
15
|
+
- Source stays close to Markdown — diff-friendly, AI-friendly, low-token.
|
|
16
|
+
- The renderer adds charts, layouts, sliders, exports, flows, timelines, etc.
|
|
17
|
+
without forcing you to write SVG/CSS/JS.
|
|
18
|
+
- One source file, one self-contained HTML. No external assets needed for
|
|
19
|
+
Claude-rendered artifacts.
|
|
20
|
+
|
|
21
|
+
## Output Choice (decide before writing)
|
|
22
|
+
|
|
23
|
+
| User intent | What to produce |
|
|
24
|
+
|---|---|
|
|
25
|
+
| Wants source only | `.rmd` file, no HTML build |
|
|
26
|
+
| Wants something to view / share / archive | `.rmd` + `--mode self-contained` HTML |
|
|
27
|
+
| Wants smallest artifact + has network | `.rmd` + `--mode cdn` HTML |
|
|
28
|
+
| Wants inspectable assets they can host themselves | `.rmd` + `--mode split` directory |
|
|
29
|
+
| Wants to demo locally during the session | `rmd open` preview server |
|
|
30
|
+
|
|
31
|
+
When unsure, default to source `.rmd` plus a `self-contained` HTML build.
|
|
32
|
+
|
|
33
|
+
## Workflow
|
|
34
|
+
|
|
35
|
+
1. Decide the smallest useful block set from `references/blocks.md`. Use
|
|
36
|
+
plain Markdown for narrative; use `:::` blocks only when they add density,
|
|
37
|
+
structure, or interaction.
|
|
38
|
+
|
|
39
|
+
2. Write the `.rmd` file. Always include a YAML frontmatter with at least
|
|
40
|
+
`title`. Suggested location: `examples/<short-name>.rmd`.
|
|
41
|
+
|
|
42
|
+
3. Validate the source with the Bash tool:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
npm run rmd -- validate path/to/doc.rmd
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
If validation fails, fix the source. Do not return a file that fails
|
|
49
|
+
validation.
|
|
50
|
+
|
|
51
|
+
4. Build the artifact:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
# Default: single self-contained HTML
|
|
55
|
+
npm run rmd -- build path/to/doc.rmd --mode self-contained --out path/to/doc.html
|
|
56
|
+
|
|
57
|
+
# CDN-loaded variant (small artifact, requires network at view time)
|
|
58
|
+
npm run rmd -- build path/to/doc.rmd --mode cdn --version 0.1.0 --out path/to/doc.html
|
|
59
|
+
|
|
60
|
+
# Split directory (HTML + JS + CSS as separate files)
|
|
61
|
+
npm run rmd -- build path/to/doc.rmd --mode split --out path/to/dist/index.html
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
5. (Optional) Local preview during the session:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
npm run rmd -- open path/to/doc.rmd --port 0 --host 127.0.0.1 --no-open true
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
The CLI prints the bound URL. Use `--no-open true` so the agent does not
|
|
71
|
+
try to launch a desktop browser.
|
|
72
|
+
|
|
73
|
+
6. Return the generated HTML file path to the user. If self-contained, the
|
|
74
|
+
file alone is the deliverable.
|
|
75
|
+
|
|
76
|
+
## Rules (these are hard constraints)
|
|
77
|
+
|
|
78
|
+
- **No styling in source.** Never write colors, pixel sizes, fonts, or layout
|
|
79
|
+
CSS into `.rmd`. Use semantic attributes like `emphasis=primary` and let
|
|
80
|
+
the theme decide visuals. (Themes can change; source must not.)
|
|
81
|
+
|
|
82
|
+
- **Diff-clean edits.** One semantic change should touch only nearby lines.
|
|
83
|
+
Don't reorder unrelated attributes or rewrite a whole file for a small fix.
|
|
84
|
+
|
|
85
|
+
- **Validate before shipping.** Validation failures are not warnings. Fix
|
|
86
|
+
the source before returning the artifact.
|
|
87
|
+
|
|
88
|
+
- **Plain Markdown for fragile content.** Use plain Markdown — code blocks,
|
|
89
|
+
tables, blockquotes — for anything you're unsure how to express in `.rmd`.
|
|
90
|
+
Don't invent block names.
|
|
91
|
+
|
|
92
|
+
- **Self-contained for sandboxes.** If the user will view the artifact inside
|
|
93
|
+
Claude's sandbox, in email, or anywhere external assets can't be fetched,
|
|
94
|
+
use `--mode self-contained`. `split` mode will not load in those contexts.
|
|
95
|
+
|
|
96
|
+
## Block Selection Cheatsheet
|
|
97
|
+
|
|
98
|
+
Map the user's intent to the smallest block set that delivers value:
|
|
99
|
+
|
|
100
|
+
| Intent | Blocks |
|
|
101
|
+
|---|---|
|
|
102
|
+
| Compare options / approaches | `grid` + `chart` + `callout` |
|
|
103
|
+
| PR / code review explainer | `diff` + `tabs` + `callout` |
|
|
104
|
+
| Tunable prototype (params + copy back to chat) | `slider` + `export` |
|
|
105
|
+
| Release / workflow | `flow` + `callout` + `timeline` |
|
|
106
|
+
| Project status report | `chart` + `timeline` + `kanban` |
|
|
107
|
+
| Research brief | `chart` + `grid` + `details` |
|
|
108
|
+
| Showcase / gallery | `carousel` + `grid layout=masonry` |
|
|
109
|
+
| Long doc with collapsible appendix | `details` + `tabs` |
|
|
110
|
+
| Math / formal explanation | `math` + `callout` |
|
|
111
|
+
|
|
112
|
+
The 14 supported blocks (v0.2): `chart`, `grid`, `callout`, `slider`,
|
|
113
|
+
`export`, `flow`, `diff`, `tabs`, `timeline`, `kanban`, `details`, `carousel`,
|
|
114
|
+
`embed`, `math`. Full reference: `references/blocks.md`.
|
|
115
|
+
|
|
116
|
+
## Default Recipe
|
|
117
|
+
|
|
118
|
+
For Claude-visible rich output:
|
|
119
|
+
|
|
120
|
+
1. Write `examples/<short-name>.rmd` with appropriate blocks.
|
|
121
|
+
2. `npm run rmd -- validate examples/<short-name>.rmd`
|
|
122
|
+
3. `npm run rmd -- build examples/<short-name>.rmd --mode self-contained --out examples/<short-name>.html`
|
|
123
|
+
4. Return `examples/<short-name>.html` as the deliverable.
|
|
124
|
+
|
|
125
|
+
See `examples/` in this skill for two ready-to-study patterns:
|
|
126
|
+
- `examples/decision-report.rmd` — comparison + chart + callout
|
|
127
|
+
- `examples/tunable-config.rmd` — slider + export + flow
|
|
128
|
+
|
|
129
|
+
## References
|
|
130
|
+
|
|
131
|
+
- `references/blocks.md` — all 14 block types with attributes and examples
|
|
132
|
+
- `references/artifacts.md` — build modes, validation, frontmatter tips
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Storage Tier Decision Report"
|
|
3
|
+
theme: default
|
|
4
|
+
share: team
|
|
5
|
+
description: "Comparison of hot/warm/cold storage strategies for the analytics pipeline."
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Storage Tier Decision Report
|
|
9
|
+
|
|
10
|
+
We need to pick a storage strategy for the analytics pipeline that handles
|
|
11
|
+
~3 TB/day. Three candidates evaluated against latency, cost, and operational
|
|
12
|
+
complexity.
|
|
13
|
+
|
|
14
|
+
## Candidates
|
|
15
|
+
|
|
16
|
+
:::grid 3
|
|
17
|
+
### Hot only
|
|
18
|
+
All data on NVMe SSD.
|
|
19
|
+
**Pros**: lowest read latency (≈2 ms).
|
|
20
|
+
**Cons**: $$$ per TB; capacity ceiling reached in ~6 months.
|
|
21
|
+
---
|
|
22
|
+
### Tiered (hot + cold)
|
|
23
|
+
Recent 7 days on SSD, older on object storage.
|
|
24
|
+
**Pros**: 70% cost reduction, latency unchanged for typical queries.
|
|
25
|
+
**Cons**: needs lifecycle automation; cold-restore latency 30-60 s.
|
|
26
|
+
---
|
|
27
|
+
### Cold only
|
|
28
|
+
Everything on object storage with index cache.
|
|
29
|
+
**Pros**: cheapest; effectively unlimited.
|
|
30
|
+
**Cons**: P95 read latency 1.5 s, breaks the SLA for live dashboards.
|
|
31
|
+
:::
|
|
32
|
+
|
|
33
|
+
## Cost vs Latency
|
|
34
|
+
|
|
35
|
+
:::chart bar title="Monthly cost (k$) vs P95 read latency (ms)" y="cost(k$)" y2="P95(ms)" legend=top
|
|
36
|
+
HotOnly 48 2
|
|
37
|
+
Tiered 14 2
|
|
38
|
+
ColdOnly 3 1500
|
|
39
|
+
:::
|
|
40
|
+
|
|
41
|
+
## Recommendation
|
|
42
|
+
|
|
43
|
+
:::callout tip title="Pick Tiered"
|
|
44
|
+
Tiered storage hits the SLA, costs roughly a third of hot-only, and the
|
|
45
|
+
lifecycle automation is a one-time investment we already use for backups.
|
|
46
|
+
:::
|
|
47
|
+
|
|
48
|
+
## Rollout Plan
|
|
49
|
+
|
|
50
|
+
:::flow direction=lr
|
|
51
|
+
Spec -> Review -> Migrate cold path -> Enable lifecycle -> Monitor
|
|
52
|
+
Migrate cold path -> Issue -> Pause and audit
|
|
53
|
+
:::
|
|
54
|
+
|
|
55
|
+
## Risk Register
|
|
56
|
+
|
|
57
|
+
:::details title="Operational risks and mitigations"
|
|
58
|
+
1. **Cold restore stalls during peak query**: cap concurrent restore jobs;
|
|
59
|
+
surface a "restoring" badge in the UI so users don't retry.
|
|
60
|
+
2. **Lifecycle policy misfires and deletes hot data**: dry-run mode for first
|
|
61
|
+
7 days; alert on >1% delta vs expected size.
|
|
62
|
+
3. **Object storage region outage**: keep last 24h of cold data mirrored to a
|
|
63
|
+
second region; documented failover runbook.
|
|
64
|
+
:::
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Rate Limiter Config — Tune & Copy"
|
|
3
|
+
theme: default
|
|
4
|
+
share: private
|
|
5
|
+
description: "Adjust the token-bucket parameters and copy the resulting YAML."
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Rate Limiter Config — Tune & Copy
|
|
9
|
+
|
|
10
|
+
Drag the sliders to tune the token-bucket rate limiter. The export button
|
|
11
|
+
below copies the matching YAML config straight to your clipboard.
|
|
12
|
+
|
|
13
|
+
## Parameters
|
|
14
|
+
|
|
15
|
+
:::slider name=capacity label="Bucket capacity" min=10 max=2000 step=10 default=200 unit=req
|
|
16
|
+
:::
|
|
17
|
+
|
|
18
|
+
:::slider name=refill_rate label="Refill rate" min=1 max=500 step=1 default=50 unit=req/s
|
|
19
|
+
:::
|
|
20
|
+
|
|
21
|
+
:::slider name=burst_window label="Burst window" min=1 max=120 step=1 default=10 unit=s
|
|
22
|
+
:::
|
|
23
|
+
|
|
24
|
+
## Generated YAML
|
|
25
|
+
|
|
26
|
+
:::export label="Copy YAML config" format=text
|
|
27
|
+
rate_limiter:
|
|
28
|
+
type: token_bucket
|
|
29
|
+
capacity: {{capacity | int}}
|
|
30
|
+
refill_rate: {{refill_rate | int}}
|
|
31
|
+
burst_window_seconds: {{burst_window | int}}
|
|
32
|
+
:::
|
|
33
|
+
|
|
34
|
+
## How requests flow
|
|
35
|
+
|
|
36
|
+
:::flow direction=lr
|
|
37
|
+
Request -> Bucket has token? -> Allow
|
|
38
|
+
Bucket has token? -> Refill check -> Allow
|
|
39
|
+
Bucket has token? -> Refill check -> Reject 429
|
|
40
|
+
:::
|
|
41
|
+
|
|
42
|
+
## Tradeoffs
|
|
43
|
+
|
|
44
|
+
:::callout warning title="Watch the burst window"
|
|
45
|
+
A wide burst window smooths short spikes but lets sustained overload through
|
|
46
|
+
longer. If your downstream is fragile, prefer narrow windows even at the cost
|
|
47
|
+
of more 429s.
|
|
48
|
+
:::
|
|
49
|
+
|
|
50
|
+
:::callout tip title="Sane starting point"
|
|
51
|
+
For most APIs, capacity ≈ 4× refill rate, burst window ≈ 10 s. Adjust from
|
|
52
|
+
there based on observed P99 incident shape.
|
|
53
|
+
:::
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# Rich Markdown Artifacts
|
|
2
|
+
|
|
3
|
+
## Source First
|
|
4
|
+
|
|
5
|
+
Always write `.rmd` source first. It is the canonical artifact and must remain
|
|
6
|
+
readable in plain Markdown tools. The HTML build is a derived view that can
|
|
7
|
+
be regenerated any time.
|
|
8
|
+
|
|
9
|
+
## Three Build Modes
|
|
10
|
+
|
|
11
|
+
The CLI supports three output modes via `--mode`. Pick based on where the
|
|
12
|
+
artifact will be viewed.
|
|
13
|
+
|
|
14
|
+
### self-contained (default)
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm run rmd -- build path/to/doc.rmd --mode self-contained --out path/to/doc.html
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Single HTML file with the renderer, theme CSS, runtime, and `.rmd` source all
|
|
21
|
+
inlined. Zero external dependencies. Best for:
|
|
22
|
+
|
|
23
|
+
- Claude desktop / chat sandbox (the artifact has to be self-contained)
|
|
24
|
+
- Email attachments
|
|
25
|
+
- Offline / archival
|
|
26
|
+
- S3 / static-host one-click sharing
|
|
27
|
+
- Any place where the consumer cannot install or fetch the renderer
|
|
28
|
+
|
|
29
|
+
Tradeoff: file size is larger (~50–150 KB) because the renderer is inlined.
|
|
30
|
+
|
|
31
|
+
### cdn
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
npm run rmd -- build path/to/doc.rmd --mode cdn --version 0.1.0 --out path/to/doc.html
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Small HTML shell containing only the `.rmd` source plus a script tag pointing
|
|
38
|
+
at a pinned CDN version of the renderer. Best for:
|
|
39
|
+
|
|
40
|
+
- Blog posts, Notion, web pages where the renderer can be fetched from CDN
|
|
41
|
+
- When the artifact itself must be small (token economy)
|
|
42
|
+
|
|
43
|
+
Requires `--version` to be a complete semver (e.g. `0.1.0`); `latest` is rejected
|
|
44
|
+
because sandboxed viewers must not depend on a moving CDN target.
|
|
45
|
+
|
|
46
|
+
### split
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
npm run rmd -- build path/to/doc.rmd --mode split --out path/to/dist/index.html
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Writes the HTML alongside `rmd.min.js` and `themes/<theme>.css` as separate
|
|
53
|
+
files in the same directory. Best for:
|
|
54
|
+
|
|
55
|
+
- Local development / hot reload
|
|
56
|
+
- Custom hosting where you want to serve the renderer from your own origin
|
|
57
|
+
- Inspecting the generated assets
|
|
58
|
+
|
|
59
|
+
Cannot be opened in sandboxed environments (Claude artifact, email) because
|
|
60
|
+
the relative asset paths will 404.
|
|
61
|
+
|
|
62
|
+
## Validation
|
|
63
|
+
|
|
64
|
+
Always validate before building or returning to the user:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
npm run rmd -- validate path/to/doc.rmd
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Validation prints `ok` on success or a list of `path: message` lines on failure.
|
|
71
|
+
If validation fails, fix the source and re-run. Do not ship a file that fails
|
|
72
|
+
validation — the renderer may degrade silently to plain code blocks.
|
|
73
|
+
|
|
74
|
+
## Recommended Default
|
|
75
|
+
|
|
76
|
+
For most Claude-driven requests:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
npm run rmd -- validate examples/my-doc.rmd
|
|
80
|
+
npm run rmd -- build examples/my-doc.rmd --mode self-contained --out examples/my-doc.html
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Return the path `examples/my-doc.html`.
|
|
84
|
+
|
|
85
|
+
## Local Preview During the Session
|
|
86
|
+
|
|
87
|
+
When the user wants to interact with the artifact while you iterate:
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
npm run rmd -- open path/to/doc.rmd --port 0 --host 127.0.0.1 --no-open true
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
The CLI prints the bound URL. Use `--no-open true` so the agent does not try
|
|
94
|
+
to launch a desktop browser.
|
|
95
|
+
|
|
96
|
+
## Frontmatter Tips
|
|
97
|
+
|
|
98
|
+
Every `.rmd` should start with a frontmatter block. Useful fields:
|
|
99
|
+
|
|
100
|
+
```yaml
|
|
101
|
+
---
|
|
102
|
+
title: Quarterly Roadmap # Required for sharing & metadata
|
|
103
|
+
theme: default # Theme id; only `default` ships today
|
|
104
|
+
share: private # private / team / public
|
|
105
|
+
description: Short summary... # Used by share cards / OG
|
|
106
|
+
lang: zh-CN # BCP 47 — affects type/font defaults
|
|
107
|
+
---
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Unknown fields are kept but ignored. Custom fields should use the `x-` prefix
|
|
111
|
+
to mark them as non-core (e.g. `x-team: backend`).
|
|
112
|
+
|
|
113
|
+
## Iteration Loop
|
|
114
|
+
|
|
115
|
+
When the user asks for revisions, re-run validate and build only — do not
|
|
116
|
+
rewrite unrelated parts of the source. The skill optimizes for clean diffs;
|
|
117
|
+
preserve the user's existing block structure unless they explicitly ask
|
|
118
|
+
otherwise.
|
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
# Rich Markdown Blocks (v0.2)
|
|
2
|
+
|
|
3
|
+
Complete reference for the 14 blocks supported by the current renderer
|
|
4
|
+
(`packages/blocks-core`). Use the smallest set that conveys meaning. Prefer
|
|
5
|
+
plain Markdown for narrative.
|
|
6
|
+
|
|
7
|
+
Identifiers are case-sensitive. Attribute order does not matter; positional
|
|
8
|
+
arguments come immediately after the block name.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## chart
|
|
13
|
+
|
|
14
|
+
Compact data visualization. Each line is `{label} {value} [{value2} ...]`,
|
|
15
|
+
space-separated. Multi-value rows become multi-series.
|
|
16
|
+
|
|
17
|
+
```rmd
|
|
18
|
+
:::chart bar title="P99 latency (ms)" emphasis=primary
|
|
19
|
+
TokenBucket 23
|
|
20
|
+
LeakyBucket 19
|
|
21
|
+
SlidingWindow 41
|
|
22
|
+
:::
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Types (positional, required): `bar`, `line`, `pie`, `scatter`, `radar`, `area`,
|
|
26
|
+
`donut`, `heatmap`. `pie` requires single value per row.
|
|
27
|
+
|
|
28
|
+
| attribute | values | default | notes |
|
|
29
|
+
|---|---|---|---|
|
|
30
|
+
| `title` | string | empty | chart title |
|
|
31
|
+
| `x` / `y` / `y2` | string | null | axis labels (use `y2` for dual axis) |
|
|
32
|
+
| `legend` | `top` / `bottom` / `left` / `right` / `none` | `bottom` | legend position |
|
|
33
|
+
| `tooltip` | `true` / `false` | `true` | hover tooltip |
|
|
34
|
+
| `emphasis` | `primary` / `secondary` / `none` | `none` | theme-controlled accent |
|
|
35
|
+
|
|
36
|
+
Multi-series + dual axis:
|
|
37
|
+
|
|
38
|
+
```rmd
|
|
39
|
+
:::chart area title="Revenue vs MAU" y="Revenue($M)" y2="MAU(K)" legend=top
|
|
40
|
+
Q1_2025 120 40
|
|
41
|
+
Q2_2025 150 45
|
|
42
|
+
Q3_2025 180 60
|
|
43
|
+
Q4_2025 240 85
|
|
44
|
+
:::
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## grid
|
|
50
|
+
|
|
51
|
+
Multi-column layout. Cells separated by `---` on their own line.
|
|
52
|
+
|
|
53
|
+
```rmd
|
|
54
|
+
:::grid 3
|
|
55
|
+
### Option A
|
|
56
|
+
Fast, simple.
|
|
57
|
+
---
|
|
58
|
+
### Option B
|
|
59
|
+
Flexible, heavier.
|
|
60
|
+
---
|
|
61
|
+
### Option C
|
|
62
|
+
Safe, slower.
|
|
63
|
+
:::
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Positional: column count (1–12) or comma-separated responsive breakpoints
|
|
67
|
+
(e.g. `1,2,4` for mobile/tablet/desktop).
|
|
68
|
+
|
|
69
|
+
| attribute | values | default | notes |
|
|
70
|
+
|---|---|---|---|
|
|
71
|
+
| `gap` | `sm` / `md` / `lg` | `md` | column spacing |
|
|
72
|
+
| `layout` | `default` / `masonry` | `default` | masonry uses CSS columns (no JS) |
|
|
73
|
+
|
|
74
|
+
`grid` cannot nest inside another `grid`. Maximum 12 cells.
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## callout
|
|
79
|
+
|
|
80
|
+
Emphasized note, decision, or warning.
|
|
81
|
+
|
|
82
|
+
```rmd
|
|
83
|
+
:::callout tip title="Recommendation"
|
|
84
|
+
Pick token bucket for burst-friendly traffic.
|
|
85
|
+
:::
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Positional kind: `info` / `tip` / `warning` / `danger` / `success`.
|
|
89
|
+
Optional `title`.
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## slider
|
|
94
|
+
|
|
95
|
+
Reader-adjustable number. Pair with `export` to copy the tuned value back.
|
|
96
|
+
|
|
97
|
+
```rmd
|
|
98
|
+
:::slider name=capacity min=10 max=1000 step=10 default=200 unit=req
|
|
99
|
+
:::
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Range slider (two values):
|
|
103
|
+
|
|
104
|
+
```rmd
|
|
105
|
+
:::slider name=qps_range label="QPS window" min=10 max=1000 step=10 default=100,500 scale=log marks=10,100,500,1000
|
|
106
|
+
:::
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Required: `name` (matches `^[a-zA-Z_][a-zA-Z0-9_]*$`), `min`, `max` (`max > min`).
|
|
110
|
+
|
|
111
|
+
| attribute | type | default | notes |
|
|
112
|
+
|---|---|---|---|
|
|
113
|
+
| `step` | number > 0 | `1` | |
|
|
114
|
+
| `default` | number or `n,m` | `min` | range slider when comma value |
|
|
115
|
+
| `unit` | string | empty | suffix shown after value |
|
|
116
|
+
| `label` | string | name | display label |
|
|
117
|
+
| `scale` | `linear` / `log` / `pow` | `linear` | |
|
|
118
|
+
| `marks` | comma-separated numbers | empty | discrete snap points |
|
|
119
|
+
|
|
120
|
+
Slider names must be unique per document. Block body must be empty.
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## export
|
|
125
|
+
|
|
126
|
+
Copy/export template. References slider values with `{{name}}` and supports
|
|
127
|
+
`{{name | int}}` formatting.
|
|
128
|
+
|
|
129
|
+
```rmd
|
|
130
|
+
:::export label="Copy config" format=text
|
|
131
|
+
rate_limiter:
|
|
132
|
+
capacity: {{capacity | int}}
|
|
133
|
+
refill_rate: {{refill_rate | int}}
|
|
134
|
+
:::
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
| attribute | values | default | notes |
|
|
138
|
+
|---|---|---|---|
|
|
139
|
+
| `label` | string | `复制` | button text |
|
|
140
|
+
| `format` | `text` / `markdown` / `json` | `text` | clipboard MIME |
|
|
141
|
+
|
|
142
|
+
Unknown variables render as `[未定义:name]` and warn in the console.
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## flow
|
|
147
|
+
|
|
148
|
+
Directed flow with linear and branching paths.
|
|
149
|
+
|
|
150
|
+
```rmd
|
|
151
|
+
:::flow direction=lr
|
|
152
|
+
Design -> Review -> Canary -> Full rollout
|
|
153
|
+
Canary -> Incident -> Rollback
|
|
154
|
+
:::
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Each line: `Node -> Node -> ...`. Same-name nodes merge.
|
|
158
|
+
`direction`: `lr` (default) or `tb`.
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## diff
|
|
163
|
+
|
|
164
|
+
Unified-diff style. `+` add, `-` remove, leading space context.
|
|
165
|
+
`@注: ...` adds an inline note (placed at end of `+`/`-` line).
|
|
166
|
+
|
|
167
|
+
```rmd
|
|
168
|
+
:::diff lang=python title="Limiter change"
|
|
169
|
+
- @rate_limit(window=60, max=100)
|
|
170
|
+
+ @token_bucket(capacity=200, refill=50) @注: adds burst protection
|
|
171
|
+
:::
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
## tabs
|
|
177
|
+
|
|
178
|
+
Multiple views in one area. `@label` on its own line starts a panel.
|
|
179
|
+
|
|
180
|
+
```rmd
|
|
181
|
+
:::tabs default=Summary
|
|
182
|
+
@Summary
|
|
183
|
+
Plain-language explanation.
|
|
184
|
+
@Details
|
|
185
|
+
Implementation details.
|
|
186
|
+
:::
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
Cannot nest inside another `tabs`.
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
## timeline
|
|
194
|
+
|
|
195
|
+
Vertical or horizontal sequence of dated events.
|
|
196
|
+
|
|
197
|
+
```rmd
|
|
198
|
+
:::timeline
|
|
199
|
+
@ 2026-01-01 [title="Kickoff"] [status="success"]
|
|
200
|
+
Initial planning done, team formed.
|
|
201
|
+
|
|
202
|
+
@ 2026-03-15 [title="v0.1"] [status="success"]
|
|
203
|
+
Core parser shipped.
|
|
204
|
+
|
|
205
|
+
@ 2026-05-10 [title="v0.2"] [status="pending"]
|
|
206
|
+
Advanced blocks + masonry grid.
|
|
207
|
+
:::
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
Each item begins with `@ {time} [title="..."] [status="..."]` on its own line.
|
|
211
|
+
Body is normal Markdown until the next `@`.
|
|
212
|
+
|
|
213
|
+
`status`: `success` / `warning` / `danger` / `pending` / `default`.
|
|
214
|
+
`direction`: `vertical` (default) or `horizontal`.
|
|
215
|
+
|
|
216
|
+
---
|
|
217
|
+
|
|
218
|
+
## kanban
|
|
219
|
+
|
|
220
|
+
Columns of cards. `@ {column title}` on its own line starts a column.
|
|
221
|
+
|
|
222
|
+
```rmd
|
|
223
|
+
:::kanban
|
|
224
|
+
@ Todo
|
|
225
|
+
- [ ] Write the report
|
|
226
|
+
- [ ] Run perf tests
|
|
227
|
+
|
|
228
|
+
@ In progress
|
|
229
|
+
- [x] Update parser
|
|
230
|
+
- [x] Refactor theme
|
|
231
|
+
|
|
232
|
+
@ Done
|
|
233
|
+
* All conformance tests pass
|
|
234
|
+
* Carousel uses pure CSS
|
|
235
|
+
:::
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
Use lists (Markdown task lists or bullets) for cards.
|
|
239
|
+
|
|
240
|
+
---
|
|
241
|
+
|
|
242
|
+
## details
|
|
243
|
+
|
|
244
|
+
Collapsible block. Wraps a native `<details>`.
|
|
245
|
+
|
|
246
|
+
```rmd
|
|
247
|
+
:::details title="Architecture changelog" open=true
|
|
248
|
+
1. Parser: custom rule dispatch on top of markdown-it.
|
|
249
|
+
2. Validator: 20+ new rules for new tree shapes.
|
|
250
|
+
3. Renderer: pure HTML output, no React/Vue dependency.
|
|
251
|
+
:::
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
| attribute | values | default |
|
|
255
|
+
|---|---|---|
|
|
256
|
+
| `title` | string | empty |
|
|
257
|
+
| `open` | `true` / `false` | `false` |
|
|
258
|
+
|
|
259
|
+
---
|
|
260
|
+
|
|
261
|
+
## carousel
|
|
262
|
+
|
|
263
|
+
Touch / scroll-snap carousel. Cells separated by `---`.
|
|
264
|
+
|
|
265
|
+
```rmd
|
|
266
|
+
:::carousel autoplay=true interval=4000
|
|
267
|
+
### Slide 1
|
|
268
|
+
First content
|
|
269
|
+
---
|
|
270
|
+
### Slide 2
|
|
271
|
+
Second content
|
|
272
|
+
:::
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
| attribute | values | default |
|
|
276
|
+
|---|---|---|
|
|
277
|
+
| `autoplay` | `true` / `false` | `false` |
|
|
278
|
+
| `interval` | number (ms) | `3000` |
|
|
279
|
+
|
|
280
|
+
---
|
|
281
|
+
|
|
282
|
+
## embed
|
|
283
|
+
|
|
284
|
+
Embed external media (video, map, app). Aspect ratio is theme-controlled.
|
|
285
|
+
|
|
286
|
+
```rmd
|
|
287
|
+
:::embed type=video id="https://www.youtube.com/embed/XXXX" aspect-ratio="16/9"
|
|
288
|
+
:::
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
| attribute | values | default |
|
|
292
|
+
|---|---|---|
|
|
293
|
+
| `type` | `video` / `map` / `iframe` | `unknown` |
|
|
294
|
+
| `id` | URL or external id | empty |
|
|
295
|
+
| `aspect-ratio` | `16/9` / `4/3` / etc. | null |
|
|
296
|
+
|
|
297
|
+
Block body is ignored.
|
|
298
|
+
|
|
299
|
+
---
|
|
300
|
+
|
|
301
|
+
## math
|
|
302
|
+
|
|
303
|
+
LaTeX math block. Renderer outputs as math container; the active theme
|
|
304
|
+
decides whether to typeset (KaTeX/MathJax) or fall back to monospace.
|
|
305
|
+
|
|
306
|
+
```rmd
|
|
307
|
+
:::math
|
|
308
|
+
\mathcal{L} = \sum_{i=1}^{N} \left( y_i \log(\hat{y}_i) + (1-y_i) \log(1-\hat{y}_i) \right)
|
|
309
|
+
:::
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
---
|
|
313
|
+
|
|
314
|
+
## Choosing Blocks
|
|
315
|
+
|
|
316
|
+
| Goal | Suggested blocks |
|
|
317
|
+
|---|---|
|
|
318
|
+
| Compare options | `grid` + `chart` + `callout` |
|
|
319
|
+
| Explain a PR | `diff` + `tabs` + `callout` |
|
|
320
|
+
| Tunable prototype | `slider` + `export` |
|
|
321
|
+
| Release / workflow | `flow` + `callout` + `timeline` |
|
|
322
|
+
| Status report | `chart` + `timeline` + `kanban` |
|
|
323
|
+
| Research brief | `chart` + `grid` + `callout` + `details` |
|
|
324
|
+
| Long doc with appendix | `details` + `tabs` |
|
|
325
|
+
| Visual gallery | `carousel` + `grid layout=masonry` |
|
|
326
|
+
| Math / formal | `math` + `callout` |
|
|
327
|
+
|
|
328
|
+
## Don't
|
|
329
|
+
|
|
330
|
+
- Don't add CSS, color, pixel, or font attributes — they belong to the theme.
|
|
331
|
+
- Don't nest `grid` in `grid`, or `tabs` in `tabs`.
|
|
332
|
+
- Don't put body content inside `:::slider` or `:::embed`.
|
|
333
|
+
- Don't invent positional arguments beyond what's listed here.
|
|
334
|
+
- Don't use experimental block names that aren't in this file.
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: rich-markdown
|
|
3
|
+
description: Generate Rich Markdown (.rmd) documents and self-contained Rich Markdown HTML artifacts for AI-authored reports, plans, comparisons, PR explanations, prototypes, research briefs, timelines, kanbans, and tunable interactive demos. Use when the user asks for rmd, Rich Markdown, rich interactive Markdown, token-efficient rich docs, shareable AI documents, charts, sliders, export/copy blocks, flow diagrams, timelines, kanban boards, collapsible details, carousels, embeds, math blocks, or wants a Codex response rendered with the local Rich Markdown renderer.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Rich Markdown
|
|
7
|
+
|
|
8
|
+
Use this skill when the user wants a rich, readable, interactive document
|
|
9
|
+
instead of plain Markdown or hand-written HTML. The local renderer
|
|
10
|
+
(`packages/cli`) turns `.rmd` source into a self-contained HTML artifact.
|
|
11
|
+
|
|
12
|
+
## Output Choice
|
|
13
|
+
|
|
14
|
+
- User wants a file or artifact: write a `.rmd` file first, then build HTML.
|
|
15
|
+
- User wants something viewable inside Codex or shareable as one file:
|
|
16
|
+
build a self-contained HTML artifact from the `.rmd`.
|
|
17
|
+
- User wants source only: output `.rmd` source, do not build HTML.
|
|
18
|
+
- User wants a multi-file site (assets they can inspect or host): use `--mode split`.
|
|
19
|
+
|
|
20
|
+
## Workflow
|
|
21
|
+
|
|
22
|
+
1. Choose the smallest useful block set from `references/blocks.md`.
|
|
23
|
+
Plain Markdown for narrative, `:::` blocks only when they add density,
|
|
24
|
+
structure, or interaction.
|
|
25
|
+
2. Write the `.rmd` to a sensible path under `examples/` (or wherever the
|
|
26
|
+
user asks). Always include a YAML frontmatter with at least `title`.
|
|
27
|
+
3. Validate the source. Fail fast if the parser reports issues:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
npm run rmd -- validate path/to/doc.rmd
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
4. Build for the chosen consumption mode:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
# Single self-contained HTML — best default for Codex Desktop / sharing
|
|
37
|
+
npm run rmd -- build path/to/doc.rmd --mode self-contained --out path/to/doc.html
|
|
38
|
+
|
|
39
|
+
# CDN-loaded variant — small artifact, requires network at view time
|
|
40
|
+
npm run rmd -- build path/to/doc.rmd --mode cdn --version 0.1.0 --out path/to/doc.html
|
|
41
|
+
|
|
42
|
+
# Split mode — index.html + rmd.min.js + themes/<name>.css for inspection / hosting
|
|
43
|
+
npm run rmd -- build path/to/doc.rmd --mode split --out path/to/dist/index.html
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
5. For local interactive preview (will start a local HTTP server):
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
npm run rmd -- open path/to/doc.rmd --port 0 --no-open true
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
6. Report the generated HTML path back to the user.
|
|
53
|
+
|
|
54
|
+
## Rules
|
|
55
|
+
|
|
56
|
+
- Never put colors, pixels, fonts, or layout styling into `.rmd`. Use
|
|
57
|
+
`emphasis=primary|secondary|none` and let the theme decide visuals.
|
|
58
|
+
- Keep source diff clean: one semantic edit should touch only nearby lines.
|
|
59
|
+
Do not reorder unrelated attributes or rewrite whole files for tiny changes.
|
|
60
|
+
- Unknown or fragile content (rare formats, edge cases) must fall back to
|
|
61
|
+
plain Markdown rather than invented block names.
|
|
62
|
+
- Use `:::slider` + `:::export` whenever the reader should tune values and
|
|
63
|
+
copy the result back to Codex or to code.
|
|
64
|
+
- Validation failures are not warnings: fix the source, do not ship the file.
|
|
65
|
+
|
|
66
|
+
## Block Selection Cheatsheet
|
|
67
|
+
|
|
68
|
+
Map the user's intent to the smallest block set that delivers value:
|
|
69
|
+
|
|
70
|
+
| Intent | Blocks |
|
|
71
|
+
|---|---|
|
|
72
|
+
| Compare options / approaches | `grid` + `chart` + `callout` |
|
|
73
|
+
| PR / code review explainer | `diff` + `tabs` + `callout` |
|
|
74
|
+
| Tunable prototype | `slider` + `export` |
|
|
75
|
+
| Release / workflow | `flow` + `callout` + `timeline` |
|
|
76
|
+
| Project status report | `chart` + `timeline` + `kanban` |
|
|
77
|
+
| Research brief | `chart` + `grid` + `details` |
|
|
78
|
+
| Showcase / gallery | `carousel` + `grid layout=masonry` |
|
|
79
|
+
| Long doc with appendix | `details` + `tabs` |
|
|
80
|
+
| Math / formal explanation | `math` + `callout` |
|
|
81
|
+
|
|
82
|
+
Full block reference: `references/blocks.md`.
|
|
83
|
+
Build mode reference: `references/artifacts.md`.
|
|
84
|
+
|
|
85
|
+
## Default Recipe
|
|
86
|
+
|
|
87
|
+
For Codex-visible rich output:
|
|
88
|
+
|
|
89
|
+
1. Write `examples/<short-name>.rmd` with appropriate blocks.
|
|
90
|
+
2. `npm run rmd -- validate examples/<short-name>.rmd`
|
|
91
|
+
3. `npm run rmd -- build examples/<short-name>.rmd --mode self-contained --out examples/<short-name>.html`
|
|
92
|
+
4. Return `examples/<short-name>.html` as the deliverable.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
interface:
|
|
2
|
+
display_name: "Rich Markdown"
|
|
3
|
+
short_description: "Generate interactive .rmd documents"
|
|
4
|
+
brand_color: "#2563EB"
|
|
5
|
+
default_prompt: "Use $rich-markdown to create a self-contained interactive .rmd HTML report."
|
|
6
|
+
|
|
7
|
+
policy:
|
|
8
|
+
allow_implicit_invocation: true
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# Rich Markdown Artifacts
|
|
2
|
+
|
|
3
|
+
## Source First
|
|
4
|
+
|
|
5
|
+
Always write `.rmd` source first. It is the canonical artifact and must remain
|
|
6
|
+
readable in plain Markdown tools. The HTML build is a derived view.
|
|
7
|
+
|
|
8
|
+
## Three Build Modes
|
|
9
|
+
|
|
10
|
+
The CLI supports three output modes via `--mode`. Pick based on where the
|
|
11
|
+
artifact will be viewed.
|
|
12
|
+
|
|
13
|
+
### self-contained (default)
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm run rmd -- build path/to/doc.rmd --mode self-contained --out path/to/doc.html
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Produces a single HTML file with the renderer, theme CSS, runtime, and `.rmd`
|
|
20
|
+
source all inlined. Zero external dependencies. Best for:
|
|
21
|
+
|
|
22
|
+
- Codex Desktop (loads inside the app sandbox)
|
|
23
|
+
- Email attachments
|
|
24
|
+
- Offline / archival
|
|
25
|
+
- S3 / static-host one-click sharing
|
|
26
|
+
- Any place where the consumer cannot install or fetch the renderer
|
|
27
|
+
|
|
28
|
+
Tradeoff: file size is larger (~50–150 KB) because the renderer ships in-line.
|
|
29
|
+
|
|
30
|
+
### cdn
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
npm run rmd -- build path/to/doc.rmd --mode cdn --version 0.1.0 --out path/to/doc.html
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Produces a small HTML shell containing only the `.rmd` source and a script tag
|
|
37
|
+
pointing at a pinned CDN version. Best for:
|
|
38
|
+
|
|
39
|
+
- Blog posts / Notion / web pages where the renderer can be fetched from CDN
|
|
40
|
+
- Cases where token economy of the artifact itself matters most
|
|
41
|
+
|
|
42
|
+
Requires `--version` to be a complete semver (e.g. `0.1.0`); `latest` is rejected
|
|
43
|
+
because sandboxed viewers must not depend on a moving CDN target.
|
|
44
|
+
|
|
45
|
+
### split
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
npm run rmd -- build path/to/doc.rmd --mode split --out path/to/dist/index.html
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Writes the HTML alongside `rmd.min.js` and `themes/<theme>.css` as separate
|
|
52
|
+
files. Best for:
|
|
53
|
+
|
|
54
|
+
- Local development / hot reload
|
|
55
|
+
- Custom hosting where you want to serve the renderer from your own origin
|
|
56
|
+
- Inspecting the generated assets
|
|
57
|
+
|
|
58
|
+
Cannot be opened in sandboxed environments (Codex Desktop artifact, email)
|
|
59
|
+
because relative asset paths will 404.
|
|
60
|
+
|
|
61
|
+
## Validation
|
|
62
|
+
|
|
63
|
+
Always validate before building or returning to the user:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
npm run rmd -- validate path/to/doc.rmd
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
If validation fails, fix the source. Do not ship a file that fails validation.
|
|
70
|
+
|
|
71
|
+
## Recommended Default for Codex
|
|
72
|
+
|
|
73
|
+
For most Codex-driven requests:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
npm run rmd -- validate examples/my-doc.rmd
|
|
77
|
+
npm run rmd -- build examples/my-doc.rmd --mode self-contained --out examples/my-doc.html
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Return the path `examples/my-doc.html`.
|
|
81
|
+
|
|
82
|
+
## Local Preview
|
|
83
|
+
|
|
84
|
+
When the user wants to interact with the artifact during the session:
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
npm run rmd -- open path/to/doc.rmd --port 0 --host 127.0.0.1 --no-open true
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
The CLI prints the bound URL. Use `--no-open true` so the agent does not try
|
|
91
|
+
to launch a desktop browser.
|
|
92
|
+
|
|
93
|
+
## Frontmatter Tips
|
|
94
|
+
|
|
95
|
+
Every `.rmd` should start with a frontmatter block. Useful fields:
|
|
96
|
+
|
|
97
|
+
```yaml
|
|
98
|
+
---
|
|
99
|
+
title: Quarterly Roadmap # Required for sharing & metadata
|
|
100
|
+
theme: default # Theme id; only `default` ships today
|
|
101
|
+
share: private # private / team / public
|
|
102
|
+
description: Short summary... # Used by share cards / OG
|
|
103
|
+
lang: zh-CN # BCP 47 — affects type/font defaults
|
|
104
|
+
---
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Unknown fields are kept but ignored; custom fields should use `x-` prefix.
|
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
# Rich Markdown Blocks (v0.2)
|
|
2
|
+
|
|
3
|
+
These are the blocks supported by the current renderer (`packages/blocks-core`).
|
|
4
|
+
Use the smallest set that conveys meaning. Prefer plain Markdown for narrative.
|
|
5
|
+
|
|
6
|
+
Identifiers (block names, slider variable names) are case-sensitive.
|
|
7
|
+
Attribute order does not matter; positional arguments come immediately after the
|
|
8
|
+
block name.
|
|
9
|
+
|
|
10
|
+
## chart
|
|
11
|
+
|
|
12
|
+
Compact data visualization. Each line is `{label} {value} [{value2} ...]`.
|
|
13
|
+
Values are space-separated. Multi-value rows become multi-series.
|
|
14
|
+
|
|
15
|
+
```rmd
|
|
16
|
+
:::chart bar title="P99 latency (ms)" emphasis=primary
|
|
17
|
+
TokenBucket 23
|
|
18
|
+
LeakyBucket 19
|
|
19
|
+
SlidingWindow 41
|
|
20
|
+
:::
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Types (positional, required): `bar`, `line`, `pie`, `scatter`, `radar`, `area`,
|
|
24
|
+
`donut`, `heatmap`. `pie` requires single value per row.
|
|
25
|
+
|
|
26
|
+
Attributes:
|
|
27
|
+
|
|
28
|
+
| name | values | default | notes |
|
|
29
|
+
|---|---|---|---|
|
|
30
|
+
| `title` | string | empty | chart title |
|
|
31
|
+
| `x` / `y` / `y2` | string | null | axis labels (use `y2` for dual axis) |
|
|
32
|
+
| `legend` | `top` / `bottom` / `left` / `right` / `none` | `bottom` | legend position |
|
|
33
|
+
| `tooltip` | `true` / `false` | `true` | hover tooltip |
|
|
34
|
+
| `emphasis` | `primary` / `secondary` / `none` | `none` | theme-controlled accent |
|
|
35
|
+
|
|
36
|
+
Multi-series example:
|
|
37
|
+
|
|
38
|
+
```rmd
|
|
39
|
+
:::chart area title="Revenue vs MAU" y="Revenue($M)" y2="MAU(K)" legend=top
|
|
40
|
+
Q1_2025 120 40
|
|
41
|
+
Q2_2025 150 45
|
|
42
|
+
Q3_2025 180 60
|
|
43
|
+
Q4_2025 240 85
|
|
44
|
+
:::
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## grid
|
|
48
|
+
|
|
49
|
+
Multi-column layout. Cells separated by `---` on their own line.
|
|
50
|
+
|
|
51
|
+
```rmd
|
|
52
|
+
:::grid 3
|
|
53
|
+
### Option A
|
|
54
|
+
Fast, simple.
|
|
55
|
+
---
|
|
56
|
+
### Option B
|
|
57
|
+
Flexible, heavier.
|
|
58
|
+
---
|
|
59
|
+
### Option C
|
|
60
|
+
Safe, slower.
|
|
61
|
+
:::
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Positional: column count (1–12) or comma-separated responsive breakpoints
|
|
65
|
+
(e.g. `1,2,4` for mobile/tablet/desktop).
|
|
66
|
+
|
|
67
|
+
Attributes:
|
|
68
|
+
|
|
69
|
+
| name | values | default | notes |
|
|
70
|
+
|---|---|---|---|
|
|
71
|
+
| `gap` | `sm` / `md` / `lg` | `md` | column spacing |
|
|
72
|
+
| `layout` | `default` / `masonry` | `default` | masonry uses CSS columns (no JS) |
|
|
73
|
+
|
|
74
|
+
`grid` cannot nest inside another `grid`. Maximum 12 cells.
|
|
75
|
+
|
|
76
|
+
## callout
|
|
77
|
+
|
|
78
|
+
Emphasized note, decision, or warning.
|
|
79
|
+
|
|
80
|
+
```rmd
|
|
81
|
+
:::callout tip title="Recommendation"
|
|
82
|
+
Pick token bucket for burst-friendly traffic.
|
|
83
|
+
:::
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Positional kind: `info` / `tip` / `warning` / `danger` / `success`.
|
|
87
|
+
Optional `title` attribute.
|
|
88
|
+
|
|
89
|
+
## slider
|
|
90
|
+
|
|
91
|
+
Reader-adjustable number with optional range/log/marks. Pair with `export`.
|
|
92
|
+
|
|
93
|
+
```rmd
|
|
94
|
+
:::slider name=capacity min=10 max=1000 step=10 default=200 unit=req
|
|
95
|
+
:::
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Range slider (two values):
|
|
99
|
+
|
|
100
|
+
```rmd
|
|
101
|
+
:::slider name=qps_range label="QPS window" min=10 max=1000 step=10 default=100,500 scale=log marks=10,100,500,1000
|
|
102
|
+
:::
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Required: `name` (matches `^[a-zA-Z_][a-zA-Z0-9_]*$`), `min`, `max` (`max > min`).
|
|
106
|
+
|
|
107
|
+
Attributes:
|
|
108
|
+
|
|
109
|
+
| name | type | default | notes |
|
|
110
|
+
|---|---|---|---|
|
|
111
|
+
| `step` | number > 0 | `1` | |
|
|
112
|
+
| `default` | number or `n,m` | `min` | range slider when comma value |
|
|
113
|
+
| `unit` | string | empty | suffix shown after value |
|
|
114
|
+
| `label` | string | name | display label |
|
|
115
|
+
| `scale` | `linear` / `log` / `pow` | `linear` | |
|
|
116
|
+
| `marks` | comma-separated numbers | empty | discrete snap points |
|
|
117
|
+
|
|
118
|
+
Slider names must be unique per document. Block body must be empty.
|
|
119
|
+
|
|
120
|
+
## export
|
|
121
|
+
|
|
122
|
+
Copy/export template. References slider values with `{{name}}` and supports
|
|
123
|
+
`{{name | int}}` formatting.
|
|
124
|
+
|
|
125
|
+
```rmd
|
|
126
|
+
:::export label="Copy config" format=text
|
|
127
|
+
rate_limiter:
|
|
128
|
+
capacity: {{capacity | int}}
|
|
129
|
+
refill_rate: {{refill_rate | int}}
|
|
130
|
+
:::
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Attributes:
|
|
134
|
+
|
|
135
|
+
| name | values | default | notes |
|
|
136
|
+
|---|---|---|---|
|
|
137
|
+
| `label` | string | `复制` | button text |
|
|
138
|
+
| `format` | `text` / `markdown` / `json` | `text` | clipboard MIME |
|
|
139
|
+
|
|
140
|
+
Unknown variables render as `[未定义:name]` and warn in the console.
|
|
141
|
+
|
|
142
|
+
## flow
|
|
143
|
+
|
|
144
|
+
Directed flow with linear and branching paths.
|
|
145
|
+
|
|
146
|
+
```rmd
|
|
147
|
+
:::flow direction=lr
|
|
148
|
+
Design -> Review -> Canary -> Full rollout
|
|
149
|
+
Canary -> Incident -> Rollback
|
|
150
|
+
:::
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Each line: `Node -> Node -> ...`. Same-name nodes merge.
|
|
154
|
+
`direction`: `lr` (default) or `tb`.
|
|
155
|
+
|
|
156
|
+
## diff
|
|
157
|
+
|
|
158
|
+
Unified-diff style. `+` add, `-` remove, leading space context.
|
|
159
|
+
`@注: ...` adds an inline note (placed at end of `+`/`-` line).
|
|
160
|
+
|
|
161
|
+
```rmd
|
|
162
|
+
:::diff lang=python title="Limiter change"
|
|
163
|
+
- @rate_limit(window=60, max=100)
|
|
164
|
+
+ @token_bucket(capacity=200, refill=50) @注: adds burst protection
|
|
165
|
+
:::
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
## tabs
|
|
169
|
+
|
|
170
|
+
Multiple views in one area. `@label` on its own line starts a panel.
|
|
171
|
+
|
|
172
|
+
```rmd
|
|
173
|
+
:::tabs default=Summary
|
|
174
|
+
@Summary
|
|
175
|
+
Plain-language explanation.
|
|
176
|
+
@Details
|
|
177
|
+
Implementation details.
|
|
178
|
+
:::
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
Cannot nest inside another `tabs`.
|
|
182
|
+
|
|
183
|
+
## timeline
|
|
184
|
+
|
|
185
|
+
Vertical or horizontal sequence of dated events.
|
|
186
|
+
|
|
187
|
+
```rmd
|
|
188
|
+
:::timeline
|
|
189
|
+
@ 2026-01-01 [title="Kickoff"] [status="success"]
|
|
190
|
+
Initial planning done, team formed.
|
|
191
|
+
|
|
192
|
+
@ 2026-03-15 [title="v0.1"] [status="success"]
|
|
193
|
+
Core parser shipped.
|
|
194
|
+
|
|
195
|
+
@ 2026-05-10 [title="v0.2"] [status="pending"]
|
|
196
|
+
Advanced blocks + masonry grid.
|
|
197
|
+
:::
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
Each item begins with `@ {time} [title="..."] [status="..."]` on its own line.
|
|
201
|
+
Body is normal Markdown until the next `@`.
|
|
202
|
+
|
|
203
|
+
`status`: `success` / `warning` / `danger` / `pending` / `default`.
|
|
204
|
+
`direction`: `vertical` (default) or `horizontal`.
|
|
205
|
+
|
|
206
|
+
## kanban
|
|
207
|
+
|
|
208
|
+
Columns of cards. `@ {column title}` on its own line starts a column.
|
|
209
|
+
|
|
210
|
+
```rmd
|
|
211
|
+
:::kanban
|
|
212
|
+
@ Todo
|
|
213
|
+
- [ ] Write the report
|
|
214
|
+
- [ ] Run perf tests
|
|
215
|
+
|
|
216
|
+
@ In progress
|
|
217
|
+
- [x] Update parser
|
|
218
|
+
- [x] Refactor theme
|
|
219
|
+
|
|
220
|
+
@ Done
|
|
221
|
+
* All conformance tests pass
|
|
222
|
+
* Carousel uses pure CSS
|
|
223
|
+
:::
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
Use lists (Markdown task lists or bullets) for cards.
|
|
227
|
+
|
|
228
|
+
## details
|
|
229
|
+
|
|
230
|
+
Collapsible block. Wraps a native `<details>`.
|
|
231
|
+
|
|
232
|
+
```rmd
|
|
233
|
+
:::details title="Architecture changelog" open=true
|
|
234
|
+
1. Parser: custom rule dispatch on top of markdown-it.
|
|
235
|
+
2. Validator: 20+ new rules for new tree shapes.
|
|
236
|
+
3. Renderer: pure HTML output, no React/Vue dependency.
|
|
237
|
+
:::
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
Attributes:
|
|
241
|
+
|
|
242
|
+
| name | values | default |
|
|
243
|
+
|---|---|---|
|
|
244
|
+
| `title` | string | empty |
|
|
245
|
+
| `open` | `true` / `false` | `false` |
|
|
246
|
+
|
|
247
|
+
## carousel
|
|
248
|
+
|
|
249
|
+
Touch / scroll-snap carousel. Cells separated by `---`.
|
|
250
|
+
|
|
251
|
+
```rmd
|
|
252
|
+
:::carousel autoplay=true interval=4000
|
|
253
|
+
### Slide 1
|
|
254
|
+
First content
|
|
255
|
+
---
|
|
256
|
+
### Slide 2
|
|
257
|
+
Second content
|
|
258
|
+
---
|
|
259
|
+
### Slide 3
|
|
260
|
+
Third content
|
|
261
|
+
:::
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
Attributes:
|
|
265
|
+
|
|
266
|
+
| name | values | default |
|
|
267
|
+
|---|---|---|
|
|
268
|
+
| `autoplay` | `true` / `false` | `false` |
|
|
269
|
+
| `interval` | number (ms) | `3000` |
|
|
270
|
+
|
|
271
|
+
## embed
|
|
272
|
+
|
|
273
|
+
Embed external media (video, map, app). Theme-controlled aspect ratio.
|
|
274
|
+
|
|
275
|
+
```rmd
|
|
276
|
+
:::embed type=video id="https://www.youtube.com/embed/XXXX" aspect-ratio="16/9"
|
|
277
|
+
:::
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
Attributes:
|
|
281
|
+
|
|
282
|
+
| name | values | default |
|
|
283
|
+
|---|---|---|
|
|
284
|
+
| `type` | `video` / `map` / `iframe` | `unknown` |
|
|
285
|
+
| `id` | URL or external id | empty |
|
|
286
|
+
| `aspect-ratio` | `16/9` / `4/3` / etc. | null |
|
|
287
|
+
|
|
288
|
+
Block body is ignored.
|
|
289
|
+
|
|
290
|
+
## math
|
|
291
|
+
|
|
292
|
+
LaTeX math block. Renderer outputs as math container; the active theme decides
|
|
293
|
+
whether to typeset (KaTeX/MathJax) or fall back to monospace.
|
|
294
|
+
|
|
295
|
+
```rmd
|
|
296
|
+
:::math
|
|
297
|
+
\mathcal{L} = \sum_{i=1}^{N} \left( y_i \log(\hat{y}_i) + (1-y_i) \log(1-\hat{y}_i) \right)
|
|
298
|
+
:::
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
## Choosing Blocks
|
|
302
|
+
|
|
303
|
+
| Goal | Suggested blocks |
|
|
304
|
+
|---|---|
|
|
305
|
+
| Compare options | `grid` + `chart` + `callout` |
|
|
306
|
+
| Explain a PR | `diff` + `tabs` + `callout` |
|
|
307
|
+
| Tunable prototype | `slider` + `export` |
|
|
308
|
+
| Release / workflow | `flow` + `callout` + `timeline` |
|
|
309
|
+
| Status report | `chart` + `timeline` + `kanban` |
|
|
310
|
+
| Research brief | `chart` + `grid` + `callout` + `details` |
|
|
311
|
+
| Long doc with collapsible appendix | `details` + `tabs` |
|
|
312
|
+
| Visual gallery / showcase | `carousel` + `grid masonry` |
|
|
313
|
+
| Math / formal explanation | `math` + `callout` |
|
|
314
|
+
|
|
315
|
+
## Don't
|
|
316
|
+
|
|
317
|
+
- Don't add CSS, color, pixel, or font attributes — they belong to the theme.
|
|
318
|
+
- Don't nest `grid` in `grid`, or `tabs` in `tabs`.
|
|
319
|
+
- Don't put body content inside `:::slider` or `:::embed`.
|
|
320
|
+
- Don't invent new positional arguments beyond what's listed here.
|
|
321
|
+
- Don't use experimental block names that aren't in this file.
|