Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 24 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -527,13 +527,36 @@ result.frontmatter // Record<string, any>
result.meta // Record<string, any>
```

### autoCloseMarkdown(markdown)
### autoCloseMarkdown(markdown, options?)

Self-healing markdown for streaming. Heals incomplete CommonMark/GFM per
`packages/comark/SPEC/auto-close.md`, then completes Comark components / tables / frontmatter.

```typescript
autoCloseMarkdown('**bold text') // '**bold text**'
autoCloseMarkdown('::alert\nContent') // '::alert\nContent\n::'

// Incomplete links get a safe placeholder URL (default protocol mode)
autoCloseMarkdown('[partial')
// '[partial](comark:incomplete-link)'

// Math (inline `$` and block `$$`) is off by default on bare autoCloseMarkdown
autoCloseMarkdown('$x = 5') // '$x = 5'
autoCloseMarkdown('$x = 5', { math: true }) // '$x = 5$'
// parseMarkdown / createMarkdownParser pass math: true when math plugin provided

// Plain markdown without Comark component fences
autoCloseMarkdown('**bold', { syntax: false })

// Streaming: drop a half-typed opener after whitespace so it does not flash
autoCloseMarkdown('hello *', { dropTrailingOpeners: true }) // 'hello'
```

Key options: `linkMode: 'protocol' | 'text-only'`, `math` (default false; on in parse),
`dropTrailingOpeners` (default false; on when parsing with `streaming: true`),
`incompleteLinkPlaceholder`, `incompleteImagePlaceholder`, `frontmatter`, `syntax`, `attributes`.
Behavioral SPEC: `packages/comark/SPEC/auto-close.md` (run via `test/auto-close-spec.test.ts`).

## Markdown Document Model

```typescript
Expand Down
33 changes: 27 additions & 6 deletions docs/content/5.reference/2.auto-close.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,18 @@ links:
variant: soft
---

## `autoCloseMarkdown(source)`{lang="ts"}
## `autoCloseMarkdown(source, options?)`{lang="ts"}

Automatically closes unclosed markdown inline syntax and Comark components. Built for streaming scenarios where content arrives incrementally and may be incomplete at any point.
Automatically closes unclosed markdown inline syntax and Comark components. Built for streaming scenarios where content arrives incrementally and may be incomplete at any point. CommonMark/GFM healing follows the behavioral SPEC in `packages/comark/SPEC/auto-close.md`.

**Parameters:**

- `source` - The markdown content (potentially partial/incomplete)
- `options` (optional) - `frontmatter: true` completes an unclosed leading frontmatter block; `syntax: false` skips Comark component-fence closing (for content parsed without the components plugin)
- `options` (optional) - Feature flags and Comark settings:
- **Comark:** `frontmatter: true` completes an unclosed leading frontmatter block; `syntax: false` skips component-fence closing; `attributes` controls `{...}` attribute scopes (defaults to `syntax`)
- **Links / images:** `linkMode: 'protocol' | 'text-only'` (default `'protocol'`), `incompleteLinkPlaceholder` (default `comark:incomplete-link`), `incompleteImagePlaceholder` (default `comark:incomplete-image`)
- **Math:** inline `$…$` and block `$$…$$` off by default on bare `autoCloseMarkdown`; pass `math: true` (or use `parseMarkdown`, which enables it)
- **Streaming:** `dropTrailingOpeners: true` drops a trailing opener after whitespace (`hello *` → `hello`) so half-typed markers do not flash. Enabled automatically when parsing with `streaming: true`.

**Returns:** `string`, the source with all unclosed syntax closed

Expand All @@ -32,6 +36,19 @@ Automatically closes unclosed markdown inline syntax and Comark components. Buil
import { autoCloseMarkdown } from 'comark'

autoCloseMarkdown('**bold text')
// '**bold text**'

autoCloseMarkdown('[partial link')
// '[partial link](comark:incomplete-link)'

autoCloseMarkdown('$x = 5')
// '$x = 5'

autoCloseMarkdown('$x = 5', { math: true })
// '$x = 5$'

autoCloseMarkdown('hello *', { dropTrailingOpeners: true })
// 'hello'
```

```typescript [Output]
Expand Down Expand Up @@ -79,11 +96,15 @@ const result = await parseMarkdown(closed, { autoClose: false })
| Syntax | Example | Auto-closed |
|--------|---------|-------------|
| Bold | `**text` | `**text**` |
| Italic | `*text` | `*text*` |
| Italic | `*text` / `_text` | `*text*` / `_text_` |
| Bold-italic | `***text` | `***text***` |
| Code | `` `code `` | `` `code` `` |
| Strikethrough | `~~text` | `~~text~~` |
| Link | `[text](url` | `[text](url)` |
| Image | `![alt](url` | `![alt](url)` |
| Link (protocol) | `[text](url` | `[text](comark:incomplete-link)` |
| Link (text-only) | `[text` | `text` |
| Image | `![alt](url` | `![alt](comark:incomplete-image)` |
| Block math | `$$x` | `$$x$$` |
| Inline math | `$x` | `$x$` (`math: true`) |

#### Comark components

Expand Down
Loading
Loading