@valkyrianlabs/payload-markdown 1.4.0 → 1.4.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/README.md +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +3 -2
- package/skills/payload-markdown/claude/SKILL.md +56 -0
- package/skills/payload-markdown/claude/examples/docs-page.md +97 -0
- package/skills/payload-markdown/claude/examples/reference-page.md +75 -0
- package/skills/payload-markdown/claude/examples/release-notes.md +69 -0
- package/skills/payload-markdown/claude/reference/automated-docs-workflow.md +64 -0
- package/skills/payload-markdown/claude/reference/formatting.md +81 -0
- package/skills/payload-markdown/claude/reference/payload-markdown-directives.md +246 -0
- package/skills/payload-markdown/claude/reference/quality.md +48 -0
- package/skills/payload-markdown/claude/scripts/check_payload_markdown_doc.py +155 -0
- package/skills/payload-markdown/codex/SKILL.md +56 -0
- package/skills/payload-markdown/codex/agents/openai.yaml +4 -0
- package/skills/payload-markdown/codex/examples/docs-page.md +97 -0
- package/skills/payload-markdown/codex/examples/reference-page.md +75 -0
- package/skills/payload-markdown/codex/examples/release-notes.md +69 -0
- package/skills/payload-markdown/codex/reference/automated-docs-workflow.md +64 -0
- package/skills/payload-markdown/codex/reference/formatting.md +81 -0
- package/skills/payload-markdown/codex/reference/payload-markdown-directives.md +246 -0
- package/skills/payload-markdown/codex/reference/quality.md +48 -0
- package/skills/payload-markdown/codex/scripts/check_payload_markdown_doc.py +155 -0
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
# Payload Markdown Directives
|
|
2
|
+
|
|
3
|
+
Payload Markdown directives are Markdown-native structure. Use labels for visible titles and attributes for behavior.
|
|
4
|
+
|
|
5
|
+
## Syntax Rules
|
|
6
|
+
|
|
7
|
+
- Prefer `[Label]` for visible names.
|
|
8
|
+
- Use multiline attributes when a directive has more than one or two attributes.
|
|
9
|
+
- Boolean attributes may be bare only where the directive supports them.
|
|
10
|
+
- Close container directives with `:::` unless a specific structural closer is clearer.
|
|
11
|
+
|
|
12
|
+
Example:
|
|
13
|
+
|
|
14
|
+
```md
|
|
15
|
+
:::card[Fast Setup]{
|
|
16
|
+
href="/getting-started/installation"
|
|
17
|
+
linkScope="title"
|
|
18
|
+
icon="@fa-duotone/bolt"
|
|
19
|
+
}
|
|
20
|
+
Install, configure, ship.
|
|
21
|
+
:::
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Directive Inventory
|
|
25
|
+
|
|
26
|
+
- `:::callout`
|
|
27
|
+
- `:::details`
|
|
28
|
+
- `:::toc`
|
|
29
|
+
- `:::steps`
|
|
30
|
+
- `:::cards`
|
|
31
|
+
- `:::card`
|
|
32
|
+
- `::button`
|
|
33
|
+
- `:::buttons`
|
|
34
|
+
- `:::tabs`
|
|
35
|
+
- `:::tab`
|
|
36
|
+
- `:::section`
|
|
37
|
+
- `:::2col`
|
|
38
|
+
- `:::3col`
|
|
39
|
+
- `:::cell`
|
|
40
|
+
|
|
41
|
+
## Callouts
|
|
42
|
+
|
|
43
|
+
Use callouts for information that changes how the reader should interpret or execute a task.
|
|
44
|
+
|
|
45
|
+
Attributes:
|
|
46
|
+
|
|
47
|
+
- `variant`: `note`, `info`, `tip`, `warning`, `danger`, or `success`
|
|
48
|
+
- `theme`: `soft`, `solid`, `glass`, or a configured theme
|
|
49
|
+
- `icon`: local icon reference
|
|
50
|
+
- `[Label]` or legacy `title`
|
|
51
|
+
|
|
52
|
+
```md
|
|
53
|
+
:::callout[Production migration]{variant="danger"}
|
|
54
|
+
Back up production data before reconciling schema changes.
|
|
55
|
+
:::
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Details
|
|
59
|
+
|
|
60
|
+
Use details for optional information, caveats, error shapes, compatibility notes, or advanced paths.
|
|
61
|
+
|
|
62
|
+
Attributes:
|
|
63
|
+
|
|
64
|
+
- `[Label]` or legacy `title`
|
|
65
|
+
- `open`: `open="true"` for initially open
|
|
66
|
+
- `theme`: `default`, `muted`, `glass`, or a configured theme
|
|
67
|
+
|
|
68
|
+
```md
|
|
69
|
+
:::details[Advanced notes]{theme="glass"}
|
|
70
|
+
These notes are useful after the basic setup is working.
|
|
71
|
+
:::
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Table Of Contents
|
|
75
|
+
|
|
76
|
+
Use a TOC on long pages with several H2 or H3 sections.
|
|
77
|
+
|
|
78
|
+
Attributes:
|
|
79
|
+
|
|
80
|
+
- `[Label]` or legacy `title`
|
|
81
|
+
- `depth`: `1` through `6`
|
|
82
|
+
- `theme`: `default`, `compact`, `sidebar`, or a configured theme
|
|
83
|
+
|
|
84
|
+
```md
|
|
85
|
+
:::toc[On this page]{depth="3" theme="compact"}
|
|
86
|
+
:::
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Steps
|
|
90
|
+
|
|
91
|
+
Use steps for ordered procedures. Start each step with a heading.
|
|
92
|
+
|
|
93
|
+
Attributes:
|
|
94
|
+
|
|
95
|
+
- `variant`: `default` or `cards`
|
|
96
|
+
- `layout`: `stack` or `grid` for card steps
|
|
97
|
+
- `columns`: `1`, `2`, `3`, `4`, or `auto` for card-step grid layout
|
|
98
|
+
- `numbered`: generated visible numbers for card steps
|
|
99
|
+
- `theme`: steps wrapper theme
|
|
100
|
+
- `stepTheme`: card theme for individual step cards
|
|
101
|
+
|
|
102
|
+
```md
|
|
103
|
+
:::steps{
|
|
104
|
+
variant="cards"
|
|
105
|
+
layout="stack"
|
|
106
|
+
numbered
|
|
107
|
+
stepTheme="cyan"
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
### Install
|
|
111
|
+
|
|
112
|
+
Install the package.
|
|
113
|
+
|
|
114
|
+
### Configure
|
|
115
|
+
|
|
116
|
+
Register the plugin.
|
|
117
|
+
|
|
118
|
+
:::
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Cards
|
|
122
|
+
|
|
123
|
+
Use cards for page maps, capability groups, related links, and compact summaries.
|
|
124
|
+
|
|
125
|
+
`:::cards` attributes:
|
|
126
|
+
|
|
127
|
+
- `columns`: `1`, `2`, `3`, `4`, or `auto`
|
|
128
|
+
- `href`: inherited or section-level link
|
|
129
|
+
- `linkScope`: `section`, `card`, or `title`
|
|
130
|
+
- `newTab`: open links in a new tab
|
|
131
|
+
- `theme`: cards container theme
|
|
132
|
+
- `cardTheme`: default child card theme
|
|
133
|
+
|
|
134
|
+
`:::card` attributes:
|
|
135
|
+
|
|
136
|
+
- `[Label]` or legacy `title`
|
|
137
|
+
- `eyebrow`
|
|
138
|
+
- `icon`
|
|
139
|
+
- `href`
|
|
140
|
+
- `linkScope`: `full` or `title`
|
|
141
|
+
- `newTab`
|
|
142
|
+
- `theme`
|
|
143
|
+
|
|
144
|
+
Use `linkScope="title"` when the card body contains buttons or links.
|
|
145
|
+
|
|
146
|
+
```md
|
|
147
|
+
:::cards{
|
|
148
|
+
columns="3"
|
|
149
|
+
cardTheme="muted"
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
:::card[Configuration]{
|
|
153
|
+
href="/configuration"
|
|
154
|
+
linkScope="title"
|
|
155
|
+
}
|
|
156
|
+
Code, themes, icons, and renderer defaults.
|
|
157
|
+
:::
|
|
158
|
+
|
|
159
|
+
:::
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
## Buttons
|
|
163
|
+
|
|
164
|
+
Use button links for clear actions. Do not use snippet-only names such as `::button_icon` in source.
|
|
165
|
+
|
|
166
|
+
`::button` attributes:
|
|
167
|
+
|
|
168
|
+
- `href`: required
|
|
169
|
+
- `variant`: `primary`, `secondary`, `outline`, `ghost`, or `link`
|
|
170
|
+
- `size`: `sm`, `md`, or `lg`
|
|
171
|
+
- `icon`: local icon reference
|
|
172
|
+
- `iconPosition`: `left` or `right`
|
|
173
|
+
- `newTab`
|
|
174
|
+
- `ariaLabel` for icon-only buttons
|
|
175
|
+
|
|
176
|
+
`:::buttons` attributes:
|
|
177
|
+
|
|
178
|
+
- `align`: `left`, `center`, or `right`
|
|
179
|
+
- `stack`: `mobile`, `always`, or `never`
|
|
180
|
+
- `gap`: `sm`, `md`, or `lg`
|
|
181
|
+
|
|
182
|
+
```md
|
|
183
|
+
:::buttons{align="center" stack="mobile" gap="md"}
|
|
184
|
+
::button[Read Docs]{href="/getting-started" variant="primary"}
|
|
185
|
+
::button[GitHub]{href="https://github.com/valkyrianlabs" variant="secondary" newTab=true}
|
|
186
|
+
:::
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
## Tabs
|
|
190
|
+
|
|
191
|
+
Use tabs for equivalent alternatives. Avoid tabs when the content is sequential.
|
|
192
|
+
|
|
193
|
+
`:::tabs` attributes:
|
|
194
|
+
|
|
195
|
+
- `default`: selected tab value on first render
|
|
196
|
+
- `theme`: tabs container theme
|
|
197
|
+
- `tabTheme`: default panel theme
|
|
198
|
+
|
|
199
|
+
`:::tab` attributes:
|
|
200
|
+
|
|
201
|
+
- `[Label]` or legacy `label`
|
|
202
|
+
- `value`
|
|
203
|
+
- `theme`
|
|
204
|
+
- `disabled`
|
|
205
|
+
|
|
206
|
+
````md
|
|
207
|
+
:::tabs{default="pnpm" theme="glass" tabTheme="muted"}
|
|
208
|
+
|
|
209
|
+
:::tab[pnpm]{value="pnpm"}
|
|
210
|
+
```bash
|
|
211
|
+
pnpm add package-name
|
|
212
|
+
```
|
|
213
|
+
:::
|
|
214
|
+
|
|
215
|
+
:::tab[npm]{value="npm"}
|
|
216
|
+
```bash
|
|
217
|
+
npm install package-name
|
|
218
|
+
```
|
|
219
|
+
:::
|
|
220
|
+
|
|
221
|
+
:::
|
|
222
|
+
````
|
|
223
|
+
|
|
224
|
+
## Layout
|
|
225
|
+
|
|
226
|
+
Use layout directives sparingly for dense overview pages.
|
|
227
|
+
|
|
228
|
+
- `:::section` supports `theme`.
|
|
229
|
+
- `:::2col` and `:::3col` support `theme` and `cellTheme`.
|
|
230
|
+
- `:::cell` supports `theme`.
|
|
231
|
+
- `:::endcol` explicitly closes an active grid.
|
|
232
|
+
- `:::endsection` explicitly closes an active section.
|
|
233
|
+
|
|
234
|
+
```md
|
|
235
|
+
:::2col{cellTheme="panel"}
|
|
236
|
+
|
|
237
|
+
### Field Mode
|
|
238
|
+
|
|
239
|
+
Use for long-form docs, posts, and articles.
|
|
240
|
+
|
|
241
|
+
### Block Mode
|
|
242
|
+
|
|
243
|
+
Use when Markdown is one block in a layout builder.
|
|
244
|
+
|
|
245
|
+
:::
|
|
246
|
+
```
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Quality Checklist
|
|
2
|
+
|
|
3
|
+
Use this checklist before returning generated docs.
|
|
4
|
+
|
|
5
|
+
## Accuracy
|
|
6
|
+
|
|
7
|
+
- Public names match source exactly.
|
|
8
|
+
- Defaults are stated only when verified.
|
|
9
|
+
- Deprecated features are labeled as supported legacy paths, not removed behavior.
|
|
10
|
+
- Examples use real import paths, config keys, and commands.
|
|
11
|
+
- Warnings and limitations are visible near the relevant instructions.
|
|
12
|
+
|
|
13
|
+
## Structure
|
|
14
|
+
|
|
15
|
+
- One H1 per page.
|
|
16
|
+
- H2 sections follow the user's workflow.
|
|
17
|
+
- TOC appears on long pages.
|
|
18
|
+
- Cards summarize choices or related links.
|
|
19
|
+
- Steps are reserved for sequential work.
|
|
20
|
+
- Details contain optional content, not required setup.
|
|
21
|
+
|
|
22
|
+
## Directive Hygiene
|
|
23
|
+
|
|
24
|
+
- Only supported directives are used.
|
|
25
|
+
- Visible titles use `[Label]`.
|
|
26
|
+
- Multiline attributes are used for dense directives.
|
|
27
|
+
- `linkScope="title"` is used for cards containing buttons or links.
|
|
28
|
+
- Button directives include `href`.
|
|
29
|
+
- Icon-only buttons include `ariaLabel`.
|
|
30
|
+
- Tabs have stable `value` attributes.
|
|
31
|
+
|
|
32
|
+
## Markdown Hygiene
|
|
33
|
+
|
|
34
|
+
- Internal docs links are root-relative.
|
|
35
|
+
- Fenced code blocks use language tags.
|
|
36
|
+
- Markdown-in-Markdown examples use outer fences longer than inner fences.
|
|
37
|
+
- No MDX imports, JSX widgets, or arbitrary HTML layout.
|
|
38
|
+
- No runtime Tailwind classes in authored Markdown unless the target project explicitly allows it.
|
|
39
|
+
|
|
40
|
+
## Automated Checks
|
|
41
|
+
|
|
42
|
+
Run:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
python3 skills/payload-markdown/codex/scripts/check_payload_markdown_doc.py path/to/docs.md
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
If working inside a downstream docs package, run its docs validation command as well.
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Lightweight checks for docs authored with Payload Markdown directives."""
|
|
3
|
+
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
6
|
+
import re
|
|
7
|
+
import sys
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
|
|
10
|
+
CONTAINER_DIRECTIVES = {
|
|
11
|
+
"callout",
|
|
12
|
+
"details",
|
|
13
|
+
"toc",
|
|
14
|
+
"steps",
|
|
15
|
+
"cards",
|
|
16
|
+
"card",
|
|
17
|
+
"buttons",
|
|
18
|
+
"tabs",
|
|
19
|
+
"tab",
|
|
20
|
+
"section",
|
|
21
|
+
"2col",
|
|
22
|
+
"3col",
|
|
23
|
+
"cell",
|
|
24
|
+
}
|
|
25
|
+
LEAF_DIRECTIVES = {"button"}
|
|
26
|
+
ALL_DIRECTIVES = CONTAINER_DIRECTIVES | LEAF_DIRECTIVES
|
|
27
|
+
|
|
28
|
+
LINK_RE = re.compile(r"\[[^\]]+\]\(([^)]+)\)")
|
|
29
|
+
DIRECTIVE_RE = re.compile(r"^\s*::(?P<colons>:?)(?P<name>[A-Za-z0-9_-]+)\b(?P<rest>.*)$")
|
|
30
|
+
ATTR_RE = re.compile(r"([A-Za-z][A-Za-z0-9_-]*)=(?:\"([^\"]*)\"|'([^']*)'|([^\s}]+))")
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def strip_frontmatter(text: str) -> str:
|
|
34
|
+
if not text.startswith("---\n"):
|
|
35
|
+
return text
|
|
36
|
+
end = text.find("\n---\n", 4)
|
|
37
|
+
if end < 0:
|
|
38
|
+
return text
|
|
39
|
+
return text[end + 5 :]
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def iter_content_lines(text: str):
|
|
43
|
+
in_fence = False
|
|
44
|
+
fence_marker = ""
|
|
45
|
+
for index, line in enumerate(text.splitlines(), start=1):
|
|
46
|
+
stripped = line.strip()
|
|
47
|
+
fence = re.match(r"^(```+|~~~+)", stripped)
|
|
48
|
+
if fence:
|
|
49
|
+
marker = fence.group(1)
|
|
50
|
+
if not in_fence:
|
|
51
|
+
in_fence = True
|
|
52
|
+
fence_marker = marker[:3]
|
|
53
|
+
elif marker.startswith(fence_marker):
|
|
54
|
+
in_fence = False
|
|
55
|
+
fence_marker = ""
|
|
56
|
+
yield index, line, True
|
|
57
|
+
continue
|
|
58
|
+
yield index, line, in_fence
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def parse_attrs(rest: str) -> dict[str, str]:
|
|
62
|
+
attrs: dict[str, str] = {}
|
|
63
|
+
for match in ATTR_RE.finditer(rest):
|
|
64
|
+
attrs[match.group(1)] = next(value for value in match.groups()[1:] if value is not None)
|
|
65
|
+
return attrs
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def check_file(path: Path) -> list[str]:
|
|
69
|
+
text = path.read_text(encoding="utf-8")
|
|
70
|
+
body = strip_frontmatter(text)
|
|
71
|
+
warnings: list[str] = []
|
|
72
|
+
h1_count = 0
|
|
73
|
+
stack: list[tuple[str, int]] = []
|
|
74
|
+
|
|
75
|
+
for line_no, line, in_fence in iter_content_lines(body):
|
|
76
|
+
if in_fence:
|
|
77
|
+
continue
|
|
78
|
+
|
|
79
|
+
if re.match(r"^# ", line):
|
|
80
|
+
h1_count += 1
|
|
81
|
+
|
|
82
|
+
for target in LINK_RE.findall(line):
|
|
83
|
+
if target.startswith(("http://", "https://", "mailto:", "#")):
|
|
84
|
+
continue
|
|
85
|
+
if target.endswith(".md") or ".md#" in target:
|
|
86
|
+
warnings.append(f"{path}:{line_no}: internal docs link should not target .md source: {target}")
|
|
87
|
+
elif not target.startswith("/"):
|
|
88
|
+
warnings.append(f"{path}:{line_no}: internal docs link should be root-relative: {target}")
|
|
89
|
+
|
|
90
|
+
match = DIRECTIVE_RE.match(line)
|
|
91
|
+
if not match:
|
|
92
|
+
continue
|
|
93
|
+
|
|
94
|
+
name = match.group("name")
|
|
95
|
+
is_container = bool(match.group("colons"))
|
|
96
|
+
rest = match.group("rest")
|
|
97
|
+
|
|
98
|
+
if name in {"end", "endcol", "endsection"}:
|
|
99
|
+
if name == "endcol":
|
|
100
|
+
while stack and stack[-1][0] not in {"2col", "3col"}:
|
|
101
|
+
stack.pop()
|
|
102
|
+
if stack:
|
|
103
|
+
stack.pop()
|
|
104
|
+
elif name in {"end", "endsection"}:
|
|
105
|
+
while stack and stack[-1][0] != "section":
|
|
106
|
+
stack.pop()
|
|
107
|
+
if stack:
|
|
108
|
+
stack.pop()
|
|
109
|
+
continue
|
|
110
|
+
|
|
111
|
+
if name not in ALL_DIRECTIVES:
|
|
112
|
+
warnings.append(f"{path}:{line_no}: unsupported Payload Markdown directive: {name}")
|
|
113
|
+
continue
|
|
114
|
+
|
|
115
|
+
if name in LEAF_DIRECTIVES and is_container:
|
|
116
|
+
warnings.append(f"{path}:{line_no}: leaf directive should use two colons: {name}")
|
|
117
|
+
if name in CONTAINER_DIRECTIVES and not is_container:
|
|
118
|
+
warnings.append(f"{path}:{line_no}: container directive should use three colons: {name}")
|
|
119
|
+
|
|
120
|
+
attrs = parse_attrs(rest)
|
|
121
|
+
if name == "button" and "href" not in attrs:
|
|
122
|
+
warnings.append(f"{path}:{line_no}: button directive should include href")
|
|
123
|
+
if name == "tab" and "value" not in attrs:
|
|
124
|
+
warnings.append(f"{path}:{line_no}: tab directive should include a stable value")
|
|
125
|
+
if name == "card" and attrs.get("linkScope") == "full":
|
|
126
|
+
warnings.append(f"{path}:{line_no}: use card linkScope=\"title\" when the body may contain links")
|
|
127
|
+
|
|
128
|
+
if name in CONTAINER_DIRECTIVES:
|
|
129
|
+
stack.append((name, line_no))
|
|
130
|
+
|
|
131
|
+
if h1_count != 1:
|
|
132
|
+
warnings.append(f"{path}: expected exactly one H1, found {h1_count}")
|
|
133
|
+
|
|
134
|
+
return warnings
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def main(argv: list[str]) -> int:
|
|
138
|
+
paths = [Path(arg) for arg in argv]
|
|
139
|
+
if not paths:
|
|
140
|
+
print("Usage: check_payload_markdown_doc.py <markdown-file> [...]", file=sys.stderr)
|
|
141
|
+
return 2
|
|
142
|
+
|
|
143
|
+
warnings: list[str] = []
|
|
144
|
+
for path in paths:
|
|
145
|
+
if path.is_file() and path.suffix == ".md":
|
|
146
|
+
warnings.extend(check_file(path))
|
|
147
|
+
|
|
148
|
+
for warning in warnings:
|
|
149
|
+
print(warning)
|
|
150
|
+
|
|
151
|
+
return 1 if warnings else 0
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
if __name__ == "__main__":
|
|
155
|
+
raise SystemExit(main(sys.argv[1:]))
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: payload-markdown
|
|
3
|
+
description: Write elegant automated documentation with @valkyrianlabs/payload-markdown. Use when Codex needs to author, rewrite, audit, or structure docs using Payload Markdown directives, theme names, cards, callouts, steps, tabs, TOCs, buttons, and layout primitives.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Payload Markdown
|
|
7
|
+
|
|
8
|
+
Use this skill to write documentation that renders well with `@valkyrianlabs/payload-markdown`, especially docs generated or maintained by agents for downstream `@valkyrianlabs/payload-markdown-docs` projects.
|
|
9
|
+
|
|
10
|
+
This skill is about authoring clean Markdown content with Payload Markdown directives. It is not a Payload CMS implementation guide.
|
|
11
|
+
|
|
12
|
+
This package stores the Codex variant at `skills/payload-markdown/codex`. When installing into an environment that requires the skill directory name to match `name`, install or copy this subtree as `payload-markdown`.
|
|
13
|
+
|
|
14
|
+
## Workflow
|
|
15
|
+
|
|
16
|
+
1. Inspect the source of truth before writing docs: code, README, existing docs, examples, tests, public API, and current package metadata.
|
|
17
|
+
2. Choose a page shape: overview, installation, reference, migration, troubleshooting, release notes, or API guide.
|
|
18
|
+
3. Use normal Markdown for prose and use directives only where they improve scanning, sequencing, comparison, or calls to action.
|
|
19
|
+
4. Prefer readable directive labels such as `[Install]` over legacy `title=""`.
|
|
20
|
+
5. Keep examples copyable. Use long fences when documenting Markdown that contains code fences.
|
|
21
|
+
6. Run `scripts/check_payload_markdown_doc.py` on changed docs before finishing.
|
|
22
|
+
|
|
23
|
+
## Reference Map
|
|
24
|
+
|
|
25
|
+
- Read `reference/automated-docs-workflow.md` for source-driven docs generation and audit flow.
|
|
26
|
+
- Read `reference/formatting.md` for frontmatter, headings, links, prose, and fenced examples.
|
|
27
|
+
- Read `reference/payload-markdown-directives.md` for supported directive syntax and recipes.
|
|
28
|
+
- Read `reference/quality.md` before final review or docs drift audits.
|
|
29
|
+
|
|
30
|
+
## Authoring Defaults
|
|
31
|
+
|
|
32
|
+
- Use exactly one H1 per page.
|
|
33
|
+
- Put `:::toc[On this page]{depth="3" theme="compact"}` after the intro on long pages.
|
|
34
|
+
- Use `:::callout` for important notes, warnings, tips, and migration hazards.
|
|
35
|
+
- Use `:::steps` for setup, tutorials, and workflows.
|
|
36
|
+
- Use `:::cards` and `:::card` for page maps, feature groups, related links, and summary grids.
|
|
37
|
+
- Use `:::tabs` only for truly parallel alternatives such as package managers or framework variants.
|
|
38
|
+
- Use `:::details` for optional caveats, migration notes, or advanced branches.
|
|
39
|
+
- Use `:::section`, `:::2col`, `:::3col`, and `:::cell` sparingly for dense landing-style docs sections.
|
|
40
|
+
- Avoid unsupported directives, MDX components, arbitrary HTML widgets, and runtime Tailwind classes in authored Markdown.
|
|
41
|
+
|
|
42
|
+
## Examples
|
|
43
|
+
|
|
44
|
+
- `examples/docs-page.md`: polished docs page with TOC, cards, steps, callouts, tabs, and details.
|
|
45
|
+
- `examples/reference-page.md`: API/reference style page with structured sections and warnings.
|
|
46
|
+
- `examples/release-notes.md`: release note page using cards, details, and migration callouts.
|
|
47
|
+
|
|
48
|
+
## Validation
|
|
49
|
+
|
|
50
|
+
Run the helper on changed Markdown files:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
python3 skills/payload-markdown/codex/scripts/check_payload_markdown_doc.py docs/**/*.md
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
If the downstream project uses `@valkyrianlabs/payload-markdown-docs`, also run its docs validation command when available.
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Installation
|
|
3
|
+
navTitle: Install
|
|
4
|
+
description: Install the package, register the plugin, and render Markdown content.
|
|
5
|
+
order: 20
|
|
6
|
+
status: published
|
|
7
|
+
tags:
|
|
8
|
+
- getting-started
|
|
9
|
+
- installation
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# Installation
|
|
13
|
+
|
|
14
|
+
Install the package, enable it for your Payload collections, and render Markdown with the server component.
|
|
15
|
+
|
|
16
|
+
:::toc[On this page]{depth="3" theme="compact"}
|
|
17
|
+
:::
|
|
18
|
+
|
|
19
|
+
:::callout[Before you start]{variant="info"}
|
|
20
|
+
This guide assumes a Payload 3 project with a working Next.js app.
|
|
21
|
+
:::
|
|
22
|
+
|
|
23
|
+
:::steps{
|
|
24
|
+
variant="cards"
|
|
25
|
+
layout="stack"
|
|
26
|
+
numbered
|
|
27
|
+
stepTheme="cyan"
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
### Install The Package
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
pnpm add @valkyrianlabs/payload-markdown
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### Register The Plugin
|
|
37
|
+
|
|
38
|
+
Add `payloadMarkdown()` to the Payload config and enable the collections that should receive Markdown fields or blocks.
|
|
39
|
+
|
|
40
|
+
### Render Content
|
|
41
|
+
|
|
42
|
+
Use `MarkdownRenderer` for standalone fields and `MarkdownBlockComponent` for `vlMdBlock` entries.
|
|
43
|
+
|
|
44
|
+
:::
|
|
45
|
+
|
|
46
|
+
## Configuration Map
|
|
47
|
+
|
|
48
|
+
:::cards{
|
|
49
|
+
columns="3"
|
|
50
|
+
cardTheme="muted"
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
:::card[Fields And Blocks]{href="/getting-started/fields-and-blocks"}
|
|
54
|
+
Automatic install behavior and manual schema control.
|
|
55
|
+
:::
|
|
56
|
+
|
|
57
|
+
:::card[Rendering]{href="/getting-started/rendering"}
|
|
58
|
+
Server-first Markdown output, scoped config, and fallback behavior.
|
|
59
|
+
:::
|
|
60
|
+
|
|
61
|
+
:::card[Code Blocks]{href="/configuration/code-blocks"}
|
|
62
|
+
Shiki languages, themes, line numbers, and full-bleed code.
|
|
63
|
+
:::
|
|
64
|
+
|
|
65
|
+
:::
|
|
66
|
+
|
|
67
|
+
## Package Manager Alternatives
|
|
68
|
+
|
|
69
|
+
:::tabs{
|
|
70
|
+
default="pnpm"
|
|
71
|
+
theme="glass"
|
|
72
|
+
tabTheme="muted"
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
:::tab[pnpm]{value="pnpm"}
|
|
76
|
+
```bash
|
|
77
|
+
pnpm add @valkyrianlabs/payload-markdown
|
|
78
|
+
```
|
|
79
|
+
:::
|
|
80
|
+
|
|
81
|
+
:::tab[npm]{value="npm"}
|
|
82
|
+
```bash
|
|
83
|
+
npm install @valkyrianlabs/payload-markdown
|
|
84
|
+
```
|
|
85
|
+
:::
|
|
86
|
+
|
|
87
|
+
:::tab[yarn]{value="yarn"}
|
|
88
|
+
```bash
|
|
89
|
+
yarn add @valkyrianlabs/payload-markdown
|
|
90
|
+
```
|
|
91
|
+
:::
|
|
92
|
+
|
|
93
|
+
:::
|
|
94
|
+
|
|
95
|
+
:::details[When to configure icons]
|
|
96
|
+
Configure local SVG icon packs only when authored content uses `icon="@pack/name"` on buttons, cards, or callouts.
|
|
97
|
+
:::
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Renderer API
|
|
3
|
+
navTitle: Renderer
|
|
4
|
+
description: Render Markdown fields and blocks with server-first components.
|
|
5
|
+
order: 80
|
|
6
|
+
status: published
|
|
7
|
+
tags:
|
|
8
|
+
- reference
|
|
9
|
+
- rendering
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# Renderer API
|
|
13
|
+
|
|
14
|
+
Use the server renderer for Markdown fields and the block component for `vlMdBlock` layout entries.
|
|
15
|
+
|
|
16
|
+
:::toc[On this page]{depth="3" theme="compact"}
|
|
17
|
+
:::
|
|
18
|
+
|
|
19
|
+
## Exports
|
|
20
|
+
|
|
21
|
+
:::cards{
|
|
22
|
+
columns="2"
|
|
23
|
+
cardTheme="glass"
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
:::card[MarkdownRenderer]
|
|
27
|
+
Server component for Markdown strings stored in fields or loaded from another source.
|
|
28
|
+
:::
|
|
29
|
+
|
|
30
|
+
:::card[MarkdownBlockComponent]
|
|
31
|
+
Server component for Payload block data with `blockType: "vlMdBlock"`.
|
|
32
|
+
:::
|
|
33
|
+
|
|
34
|
+
:::
|
|
35
|
+
|
|
36
|
+
## Field Rendering
|
|
37
|
+
|
|
38
|
+
```tsx
|
|
39
|
+
import { MarkdownRenderer } from '@valkyrianlabs/payload-markdown/server'
|
|
40
|
+
|
|
41
|
+
export function PostBody({ content }: { content?: null | string }) {
|
|
42
|
+
return (
|
|
43
|
+
<MarkdownRenderer
|
|
44
|
+
collectionSlug="posts"
|
|
45
|
+
markdown={content}
|
|
46
|
+
scope="field"
|
|
47
|
+
variant="docs"
|
|
48
|
+
/>
|
|
49
|
+
)
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
:::callout[Collection scope]{variant="tip"}
|
|
54
|
+
Pass `collectionSlug` when collection-level `code`, `themes`, or `config` should apply.
|
|
55
|
+
:::
|
|
56
|
+
|
|
57
|
+
## Block Rendering
|
|
58
|
+
|
|
59
|
+
```tsx
|
|
60
|
+
import { MarkdownBlockComponent } from '@valkyrianlabs/payload-markdown/server'
|
|
61
|
+
|
|
62
|
+
export function RenderMarkdownBlock({ block }: { block: { blockType: 'vlMdBlock'; content: string } }) {
|
|
63
|
+
return <MarkdownBlockComponent {...block} collectionSlug="pages" />
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
:::callout[Direct props]{variant="warning"}
|
|
68
|
+
Pass block fields directly with `{...block}`. Do not wrap the data in a `block` prop.
|
|
69
|
+
:::
|
|
70
|
+
|
|
71
|
+
## Fallbacks
|
|
72
|
+
|
|
73
|
+
:::details[Empty and warning fallback behavior]
|
|
74
|
+
`emptyFallback` renders when Markdown is empty or whitespace-only. `errorFallback` renders when compilation produces warnings and you prefer not to show the compiled HTML.
|
|
75
|
+
:::
|