markform 0.1.1 → 0.1.3

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.
Files changed (36) hide show
  1. package/DOCS.md +546 -0
  2. package/README.md +340 -71
  3. package/SPEC.md +2779 -0
  4. package/dist/ai-sdk.d.mts +2 -2
  5. package/dist/ai-sdk.mjs +5 -3
  6. package/dist/{apply-BQdd-fdx.mjs → apply-00UmzDKL.mjs} +849 -730
  7. package/dist/bin.mjs +6 -3
  8. package/dist/{cli-pjOiHgCW.mjs → cli-D--Lel-e.mjs} +1374 -428
  9. package/dist/cli.mjs +6 -3
  10. package/dist/{coreTypes--6etkcwb.d.mts → coreTypes-BXhhz9Iq.d.mts} +1946 -794
  11. package/dist/coreTypes-Dful87E0.mjs +537 -0
  12. package/dist/index.d.mts +116 -19
  13. package/dist/index.mjs +5 -3
  14. package/dist/session-Bqnwi9wp.mjs +110 -0
  15. package/dist/session-DdAtY2Ni.mjs +4 -0
  16. package/dist/shared-D7gf27Tr.mjs +3 -0
  17. package/dist/shared-N_s1M-_K.mjs +176 -0
  18. package/dist/src-Dm8jZ5dl.mjs +7587 -0
  19. package/examples/celebrity-deep-research/celebrity-deep-research.form.md +912 -0
  20. package/examples/earnings-analysis/earnings-analysis.form.md +6 -1
  21. package/examples/earnings-analysis/earnings-analysis.valid.ts +119 -59
  22. package/examples/movie-research/movie-research-basic.form.md +164 -0
  23. package/examples/movie-research/movie-research-deep.form.md +486 -0
  24. package/examples/movie-research/movie-research-minimal.form.md +54 -0
  25. package/examples/simple/simple-mock-filled.form.md +17 -13
  26. package/examples/simple/simple-skipped-filled.form.md +32 -9
  27. package/examples/simple/simple-with-skips.session.yaml +102 -143
  28. package/examples/simple/simple.form.md +13 -13
  29. package/examples/simple/simple.session.yaml +80 -69
  30. package/examples/startup-deep-research/startup-deep-research.form.md +60 -8
  31. package/examples/startup-research/startup-research-mock-filled.form.md +1 -1
  32. package/examples/startup-research/startup-research.form.md +1 -1
  33. package/package.json +10 -14
  34. package/dist/src-Cs4_9lWP.mjs +0 -2151
  35. package/examples/political-research/political-research.form.md +0 -233
  36. package/examples/political-research/political-research.mock.lincoln.form.md +0 -355
package/README.md CHANGED
@@ -1,40 +1,180 @@
1
1
  # Markform
2
2
 
3
- Agent-friendly, human-readable forms stored as `.form.md` files.
3
+ ***Structured Markdown documents for humans, agents, and APIs***
4
4
 
5
- Markform enables AI agents to fill out structured forms using patches, while keeping the
6
- form source in human-readable Markdown with [Markdoc](https://markdoc.dev/) tags.
5
+ **Markform** is a **file format**, **data model**, and **editing API** for
6
+ **token-friendly, human-readable text forms**. Markform syntax is a superset of Markdown
7
+ based on [Markdoc](https://github.com/markdoc/markdoc), stored as `.form.md` files.
8
+
9
+ Markform is like if Markdown docs had a customizable API. The idea is to combine the
10
+ simple utility of a Markdown document with structured tags that define typed fields and
11
+ validation rules.
12
+ Fields, validation rules, and instructions are encoded as Markdoc tags.
13
+
14
+ Markform lets you build powerful agent workflows by structuring and validating *what*
15
+ you want (the form structure and validations) instead of *how* to get it (coding up
16
+ agent workflows). For deep research and other tasks where you want a high level of
17
+ control on intermediate states and final output from an AI pipeline, this approach is a
18
+ compelling alternative to programmatic or UI-based agent workflows.
19
+ Because it’s just Markdown with tags, agents are also very good at writing Markform,
20
+ which makes creating new workflows much easier.
7
21
 
8
22
  ## Installation
9
23
 
10
24
  ```bash
25
+ # As a global CLI
26
+ npm install -g markform
27
+
28
+ # Or as a project dependency
11
29
  npm install markform
12
- # or
13
- pnpm add markform
14
30
  ```
15
31
 
16
- Requires Node.js 24+.
32
+ Requires Node.js 20+ (v24 recommended).
17
33
 
18
34
  ## Quick Start
19
35
 
20
- The fastest way to try Markform is the interactive `examples` command:
21
-
22
36
  ```bash
23
- # Try it without installing (uses npx)
37
+ # Try it without installing
24
38
  npx markform examples
39
+ ```
25
40
 
26
- # Or after installing globally
27
- npm install -g markform
28
- markform examples
41
+ This walks you through an example form interactively, with optional AI agent filling.
42
+ You’ll need at least one [API key](#supported-providers) to have LLMs fill in forms.
43
+
44
+ ### A Minimal Form
45
+
46
+ A `.form.md` file is simply a Markdoc file.
47
+ It combines YAML frontmatter with Markdoc-tagged content:
48
+
49
+ ```markdown
50
+ ---
51
+ markform:
52
+ spec: MF/0.1
53
+ title: Movie Research (Minimal)
54
+ description: Quick movie lookup with just the essentials (title, year, ratings, summary).
55
+ roles:
56
+ - user
57
+ - agent
58
+ role_instructions:
59
+ user: "Enter the movie title."
60
+ agent: |
61
+ Quickly identify the movie and fill in basic info from IMDB.
62
+ This is a minimal lookup - just get the core facts.
63
+ ---
64
+ {% form id="movie_research_minimal" title="Movie Research (Minimal)" %}
65
+
66
+ <!-- The first field group is filled in by the user (role="user"): -->
67
+
68
+ {% field-group id="movie_input" title="Movie Identification" %}
69
+
70
+ {% string-field id="movie" label="Movie" role="user" required=true minLength=1 maxLength=300 %}{% /string-field %}
71
+ {% instructions ref="movie" %}Enter the movie title (add year or details for disambiguation).{% /instructions %}
72
+
73
+ {% /field-group %}
74
+
75
+ <!-- Everything else is filled in by the agent (role="agent"): -->
76
+
77
+ {% field-group id="about_the_movie" title="About the Movie" %}
78
+
79
+ {% string-field id="full_title" label="Full Title" role="agent" required=true %}{% /string-field %}
80
+ {% instructions ref="full_title" %}Official title including subtitle if any.{% /instructions %}
81
+
82
+ {% number-field id="year" label="Release Year" role="agent" required=true min=1888 max=2030 %}{% /number-field %}
83
+
84
+ {% url-field id="imdb_url" label="IMDB URL" role="agent" required=true %}{% /url-field %}
85
+
86
+ {% single-select id="mpaa_rating" label="MPAA Rating" role="agent" %}
87
+ - [ ] G {% #g %}
88
+ - [ ] PG {% #pg %}
89
+ - [ ] PG-13 {% #pg_13 %}
90
+ - [ ] R {% #r %}
91
+ - [ ] NC-17 {% #nc_17 %}
92
+ - [ ] NR/Unrated {% #nr %}
93
+ {% /single-select %}
94
+
95
+ {% number-field id="imdb_rating" label="IMDB Rating" role="agent" min=1.0 max=10.0 %}{% /number-field %}
96
+ {% instructions ref="imdb_rating" %}IMDB user rating (1.0-10.0 scale).{% /instructions %}
97
+
98
+ {% string-field id="logline" label="One-Line Summary" role="agent" maxLength=300 %}{% /string-field %}
99
+ {% instructions ref="logline" %}Brief plot summary in 1-2 sentences, no spoilers.{% /instructions %}
100
+
101
+ {% /field-group %}
102
+
103
+ {% /form %}
29
104
  ```
30
105
 
31
- This walks you through:
106
+ This is the minimal movie research form.
107
+ See the
108
+ [examples/](https://github.com/jlevy/markform/tree/main/packages/markform/examples)
109
+ directory for forms with more fields, including multiple rating sources (IMDB, Rotten
110
+ Tomatoes, Metacritic) and comprehensive analysis.
111
+
112
+ **Key concepts:**
113
+
114
+ - **Roles**: Define who fills what (`user` for humans, `agent` for AI)
115
+
116
+ - **Field types**: `string-field`, `number-field`, `url-field`, `string-list`,
117
+ `single-select`, `multi-select`, `checkboxes`
118
+
119
+ - **Validation**: `required`, `min/max`, `minLength/maxLength`, `pattern`
120
+
121
+ - **Structure**: Fields organized in `field-group` containers
122
+
123
+ - **Instructions**: Per-field guidance for users or agents
124
+
125
+ ### More Example Forms
126
+
127
+ The package includes example forms in
128
+ [`examples/`](https://github.com/jlevy/markform/tree/main/packages/markform/examples):
32
129
 
33
- 1. Selecting an example form (simple, political research, earnings analysis)
130
+ - [`movie-research/movie-research-minimal.form.md`](https://github.com/jlevy/markform/blob/main/packages/markform/examples/movie-research/movie-research-minimal.form.md)
131
+ \- Quick movie lookup (title, year, rating)
132
+
133
+ - [`movie-research/movie-research-basic.form.md`](https://github.com/jlevy/markform/blob/main/packages/markform/examples/movie-research/movie-research-basic.form.md)
134
+ \- Standard research with IMDB, Rotten Tomatoes, Metacritic
135
+
136
+ - [`movie-research/movie-research-deep.form.md`](https://github.com/jlevy/markform/blob/main/packages/markform/examples/movie-research/movie-research-deep.form.md)
137
+ \- Comprehensive analysis with streaming, box office
138
+
139
+ - [`simple/simple.form.md`](https://github.com/jlevy/markform/blob/main/packages/markform/examples/simple/simple.form.md)
140
+ \- Basic form demonstrating all field types
141
+
142
+ - [`earnings-analysis/earnings-analysis.form.md`](https://github.com/jlevy/markform/blob/main/packages/markform/examples/earnings-analysis/earnings-analysis.form.md)
143
+ \- Financial analysis form
144
+
145
+ View them with `markform examples --list` or try them interactively.
146
+
147
+ ## Supported Providers
148
+
149
+ Standard LLMs can be used to fill in forms or create research reports from form
150
+ templates. The package currently has support for these models built in, and enables web
151
+ search tools for them if possible.
152
+
153
+ | Provider | Env Variable | Example Models |
154
+ | --- | --- | --- |
155
+ | openai | `OPENAI_API_KEY` | gpt-5-mini, gpt-5.1, gpt-5.2 |
156
+ | anthropic | `ANTHROPIC_API_KEY` | claude-sonnet-4-5, claude-opus-4-5 |
157
+ | google | `GOOGLE_API_KEY` | gemini-2.5-pro, gemini-2.5-flash |
158
+ | xai | `XAI_API_KEY` | grok-4, grok-4-fast |
159
+ | deepseek | `DEEPSEEK_API_KEY` | deepseek-chat, deepseek-reasoner |
34
160
 
35
- 2. Filling in user fields interactively
161
+ Set the appropriate environment variable for your provider before running `markform
162
+ fill`. See
163
+ [`src/settings.ts`](https://github.com/jlevy/markform/blob/main/packages/markform/src/settings.ts)
164
+ for the full list of models.
36
165
 
37
- 3. Optionally running an AI agent to complete remaining fields
166
+ ## Why?
167
+
168
+ Many agent workflow frameworks emphasize the *flow* of information (the *how*) over its
169
+ *structure* (the *what*). But the *how* is constantly changing.
170
+
171
+ What we often really want is to express *desired structure and validation rules* for
172
+ content directly in a way that provides clear context to agents and humans at all times.
173
+
174
+ Humans have for centuries used paper forms to systematize and manage processes.
175
+ The key insight of Markform is that the most natural way to express the state and
176
+ context for a workflow is often *forms*. Just as Markdown is a transparent format for
177
+ documents, Markform is a transparent text format for structured information.
38
178
 
39
179
  ## CLI Commands
40
180
 
@@ -104,35 +244,88 @@ markform apply my-form.form.md --patch '[{"op":"set","fieldId":"name","value":"A
104
244
  markform serve my-form.form.md
105
245
  ```
106
246
 
107
- ### List Models
247
+ ### Documentation Commands
108
248
 
109
249
  ```bash
250
+ # Quick reference for writing forms (agent-friendly)
251
+ markform docs
252
+
253
+ # Full specification (SPEC.md)
254
+ markform spec
255
+
256
+ # This README
257
+ markform readme
258
+
110
259
  # See supported AI providers and example models
111
260
  markform models
261
+
262
+ # See all commands
263
+ markform --help
112
264
  ```
113
265
 
114
- ### View Documentation
266
+ ## Architecture
115
267
 
116
- ```bash
117
- # Display this README with terminal formatting
118
- markform instructions
268
+ ```mermaid
269
+ flowchart LR
270
+ subgraph SPEC["<b>MARKFORM SPEC</b>"]
271
+ direction TB
119
272
 
120
- # Output raw markdown (for piping)
121
- markform instructions --raw
122
- ```
273
+ subgraph L1["<b>LAYER 1: SYNTAX</b><br/>Markdoc tag syntax and frontmatter (form, field-group, string-field, checkboxes, etc.)"]
274
+ end
123
275
 
124
- ## Supported AI Providers
276
+ subgraph L2["<b>LAYER 2: FORM DATA MODEL</b><br/>Schema definitions for forms, fields, values (in Zod but mappable to JSON Schema or Pydantic)"]
277
+ end
125
278
 
126
- | Provider | Env Variable | Example Models |
127
- | --- | --- | --- |
128
- | openai | `OPENAI_API_KEY` | gpt-5-mini, gpt-5.1, gpt-5.2 |
129
- | anthropic | `ANTHROPIC_API_KEY` | claude-sonnet-4-5, claude-opus-4-5 |
130
- | google | `GOOGLE_API_KEY` | gemini-2.5-pro, gemini-2.5-flash |
131
- | xai | `XAI_API_KEY` | grok-4, grok-4-fast |
132
- | deepseek | `DEEPSEEK_API_KEY` | deepseek-chat, deepseek-reasoner |
279
+ subgraph L3["<b>LAYER 3: VALIDATION & FORM FILLING</b><br/>Rules for filling forms via patches, field ids, required field semantics, validation hooks"]
280
+ end
133
281
 
134
- Set the appropriate environment variable for your provider before running `markform fill`.
135
- See [`src/settings.ts`](src/settings.ts) for the full list of models.
282
+ subgraph L4["<b>LAYER 4: TOOL API & INTERFACES</b><br/>Abstract API for agents and humans (TypeScript and AI SDK integration)"]
283
+ end
284
+
285
+ L4 -->
286
+
287
+ L3 --> L2 --> L1
288
+ end
289
+
290
+ subgraph IMPL["<b>THIS IMPLEMENTATION</b>"]
291
+ direction TB
292
+
293
+ subgraph ENGINE["<b>ENGINE IMPLEMENTATION</b><br/>Markdoc parser, serializer, patch application, validation (uses jiti for TypeScript rules)"]
294
+ end
295
+
296
+ subgraph UI["<b>USER INTERFACES</b><br/>CLI commands, web UI (serve), render to HTML"]
297
+ end
298
+
299
+ subgraph AGENT["<b>AGENT INTERFACES</b><br/>Tool API library, MCP server, AI SDK tools"]
300
+ end
301
+
302
+ subgraph HARNESS["<b>EXECUTION HARNESS</b><br/>Step-by-step form-filling agentic loop"]
303
+ end
304
+
305
+ subgraph TEST["<b>TESTING FRAMEWORK</b><br/>Golden session testing with .session.yaml transcripts"]
306
+ end
307
+
308
+ UI --> ENGINE
309
+ AGENT --> HARNESS
310
+ AGENT --> ENGINE
311
+ HARNESS --> ENGINE
312
+ ENGINE --> TEST
313
+ end
314
+
315
+ SPEC ~~~ IMPL
316
+
317
+ style SPEC fill:#e8f4f8,stroke:#0077b6
318
+ style L1 fill:#caf0f8,stroke:#0077b6
319
+ style L2 fill:#caf0f8,stroke:#0077b6
320
+ style L3 fill:#caf0f8,stroke:#0077b6
321
+ style L4 fill:#caf0f8,stroke:#0077b6
322
+ style IMPL fill:#fff3e6,stroke:#fb8500
323
+ style ENGINE fill:#ffe8cc,stroke:#fb8500
324
+ style UI fill:#ffe8cc,stroke:#fb8500
325
+ style AGENT fill:#ffe8cc,stroke:#fb8500
326
+ style HARNESS fill:#ffe8cc,stroke:#fb8500
327
+ style TEST fill:#ffe8cc,stroke:#fb8500
328
+ ```
136
329
 
137
330
  ## Programmatic Usage
138
331
 
@@ -186,64 +379,140 @@ const result = await generateText({
186
379
  | `markform_export` | Export schema and values as JSON |
187
380
  | `markform_get_markdown` | Get canonical Markdown representation |
188
381
 
189
- ## Form Structure
382
+ ## FAQ
190
383
 
191
- A `.form.md` file combines YAML frontmatter with Markdoc-tagged content:
384
+ ### Is this mature?
192
385
 
193
- ```markdown
194
- ---
195
- markform:
196
- markform_version: "0.1.0"
197
- roles:
198
- - user
199
- - agent
200
- role_instructions:
201
- user: "Fill in your details."
202
- agent: "Complete the analysis fields."
203
- ---
386
+ No! I just wrote it.
387
+ The spec is a draft.
388
+ But it’s been useful for me already.
204
389
 
205
- {% form id="my_form" title="My Form" %}
390
+ ### Was it Vibe Coded?
206
391
 
207
- {% field-group id="basics" title="Basic Info" %}
392
+ It’s all written by LLMs but using a strongly spec-driven process, using rules from
393
+ [Speculate](https://github.com/jlevy/speculate).
394
+ See [the spec](SPEC.md) and the architecture docs and specs in [docs/](docs/).
208
395
 
209
- {% string-field id="name" label="Name" role="user" required=true %}{% /string-field %}
396
+ ### What are the goals of Markform?
210
397
 
211
- {% number-field id="score" label="Score" role="agent" min=0 max=100 %}{% /number-field %}
398
+ - **Markform should express complex structure and validation rules for outputs:** Fields
399
+ can be arbitrary types like checkboxes, strings, dates, numbers, URLs, and lists.
400
+ Validation rules can be simple (min and max value, regexes), arbitrary code, or LLM
401
+ calls.
212
402
 
213
- {% /field-group %}
403
+ - **Markform is programmatically editable:** Field state should be updated via APIs, by
404
+ apps, or by agent tools.
214
405
 
215
- {% /form %}
216
- ```
406
+ - **Markform is readable by humans and agents:** Both templates and field values of a
407
+ form should have a clear text format (not a binary or obscure XML format only readable
408
+ by certain applications).
217
409
 
218
- **Key concepts:**
410
+ ### How do agents fill in forms?
219
411
 
220
- - **Roles**: Define who fills what (`user` for humans, `agent` for AI)
412
+ The data model and editing API let agents fill in forms.
413
+ This enables powerful AI workflows that assemble information in a defined structure:
221
414
 
222
- - **Field types**: `string-field`, `number-field`, `string-list`, `single-select`,
223
- `multi-select`, `checkboxes`
415
+ - **Form content, structure, and field values are in a single text file** for better
416
+ context engineering.
417
+ This is a major advantage for LLM agents and for humans reviewing their work.
224
418
 
225
- - **Validation**: `required`, `min/max`, `minLength/maxLength`, `pattern`
419
+ - **Incremental filling** means an agent or a human can take many iterations, filling
420
+ and correcting a form until it is complete and satisfies the validation rules.
226
421
 
227
- - **Structure**: Fields organized in `field-group` containers
422
+ - **Multiple interfaces for humans or agents** can work with the same forms.
423
+ You can interact with a form via a CLI, a programmatic API, from Vercel AI SDK or in
424
+ an MCP server used by an agent, or in web form UIs for humans.
425
+
426
+ - **Flexible validation** at multiple scopes (field/group/form), including declarative
427
+ constraints and external hooks to arbitrary code (currently TypeScript) or LLM-based
428
+ validation instructions.
429
+
430
+ - An **agent execution harness** for step-by-step form filling, enabling deep research
431
+ agents that assemble validated output in a structured format.
432
+
433
+ ### Does anything like this already exist?
434
+
435
+ Not really. The closest alternatives are:
228
436
 
229
- ## Example Forms
437
+ - Plain Markdown docs can be used as templates and filled in by agents.
438
+ These are more expressive, but it is hard to edit them programmatically or use LLMs to
439
+ update them reliably.
230
440
 
231
- The package includes example forms in the `examples/` directory:
441
+ - Agent to-do lists are part of many chat or coding interfaces and are programmatically
442
+ edited by agents. But these are limited to simple checklists, not forms with other
443
+ fields.
232
444
 
233
- - `simple/simple.form.md` - Basic form demonstrating all field types
445
+ - Numerous tools like Typeform, Google Forms, PDF forms, and Docusign offer
446
+ human-friendly UI. But these do not have a human-friendly text format for use by
447
+ agents as well as humans.
234
448
 
235
- - `political-research/political-research.form.md` - Biographical research form
449
+ | Approach | Human-readable | Agent-editable | Custom validations |
450
+ | --- | :---: | :---: | :---: |
451
+ | Plain Markdown | ✅ | ⚠️ fragile | ❌ |
452
+ | JSON Schema | ❌ | ✅ | ✅ |
453
+ | PDF Forms, SaaS tools | ⚠️ | ❌ | ⚠️ |
454
+ | **Markform** | ✅ | ✅ | ✅ |
236
455
 
237
- - `earnings-analysis/earnings-analysis.form.md` - Financial analysis form
456
+ ### What are example use cases?
238
457
 
239
- View them with `markform examples --list` or try them interactively with `markform
240
- examples`.
458
+ - Deep research tools where agents need to follow codified processes to assemble
459
+ information
241
460
 
242
- ## Contributing
461
+ - Practical task execution plans with checklists and assembled answers and notes
243
462
 
244
- For development and contributing, see the
245
- [GitHub repository](https://github.com/jlevy/markform).
463
+ - Analysis processes, like assembling insights from unstructured sources in structured
464
+ form
465
+
466
+ - Multi-agent and agent-human workflows, where humans and/or agents fill in different
467
+ parts of a form, or where humans or agents review each other’s work in structured ways
468
+
469
+ - A clean and readable text format for web UIs that involve filling in forms, supporting
470
+ strings, lists, numbers, checkboxes, URLs, and other fields
471
+
472
+ ### Why use Markdoc as a base format?
473
+
474
+ Markdoc extends Markdown with structured tags, allowing AST parsing and programmatic
475
+ manipulation while preserving human and LLM readability.
476
+ See Stripe’s [Markdoc overview][markdoc-overview] and [blog post][stripe-markdoc] for
477
+ more on the philosophy behind “docs-as-data” that Markform extends to “forms-as-data.”
478
+ We could use XML tags, but Markdoc has some niceties like tagging Markdown AST nodes
479
+ (`{% #some-id %}`) so I decided to go with this.
480
+
481
+ ### Is there a VSCode plugin for Markform or Markdoc?
482
+
483
+ For quick syntax highlighting of `{% tag %}` syntax, install
484
+ [Better Jinja](https://marketplace.visualstudio.com/items?itemName=samuelcolvin.jinjahtml)
485
+ and associate `.form.md` files with the `jinja-md` language mode in your VS Code
486
+ settings:
487
+
488
+ ```json
489
+ "files.associations": {
490
+ "*.form.md": "jinja-md"
491
+ }
492
+ ```
493
+
494
+ Or see [markdoc/language-server](https://github.com/markdoc/language-server).
495
+
496
+ ## Documentation
497
+
498
+ - **[Quick
499
+ Reference](https://github.com/jlevy/markform/blob/main/packages/markform/DOCS.md)**
500
+ (or run `markform docs`) - Concise syntax reference (agent-friendly)
501
+
502
+ - **[Markform Spec](https://github.com/jlevy/markform/blob/main/SPEC.md)** (or run
503
+ `markform spec`) - Complete syntax and semantics
504
+
505
+ - **[Design
506
+ Doc](https://github.com/jlevy/markform/blob/main/docs/project/architecture/current/arch-markform-design.md)**
507
+ \- Technical design and roadmap
508
+
509
+ - **[Development](https://github.com/jlevy/markform/blob/main/docs/development.md)** -
510
+ Build, test, and contribute
246
511
 
247
512
  ## License
248
513
 
249
- AGPL-3.0-or-later
514
+ AGPL-3.0-or-later. [Contact me](https://github.com/jlevy) for additional licensing
515
+ options.
516
+
517
+ [markdoc-overview]: https://markdoc.dev/docs/overview
518
+ [stripe-markdoc]: https://stripe.com/blog/markdoc