=== FEATURE-BLOCK-QUOTES.md ===
# FEATURE: Block Quotes
| Field | Value |
|-------------|-------|
| Version | 20260812 V1 |
| Description | Defines nested CommonMark block quotes and lazy continuation behavior. |
| Depends On | FEATURE-BLOCK-LEAF.md |
| Provides | block quote parser |
| Consumes | leaf block parser |
## Questions
- None.
## Purpose
Block quotes contain recursively parsed CommonMark blocks. A marker consists of up to three leading spaces, `>`, and an optional following space or tab.
## Behavior
The parser supports:
- Empty block quotes and block quotes with blank boundary lines.
- Nested block quotes.
- Block quotes containing headings, paragraphs, lists, code blocks, HTML blocks, and thematic breaks.
- Lazy continuation of paragraph lines when the `>` marker is omitted.
- Termination when a non-lazy line cannot continue the quoted block.
- Separate block quotes when a blank line separates them.
Block structure is resolved before inline parsing. Quoted content uses the same block parser as document content.
## Programmatic Acceptance
=== AC block-quotes ===
Intent: The parser passes the complete block quote conformance section.
Suite: scoped
Requires: executable=python3; scope=test
import subprocess
result = subprocess.run(
[
"python3",
"spec_tests.py",
"--spec",
"spec.txt",
"--program",
"./cmark",
"--pattern",
r"^Block quotes$",
],
capture_output=True,
text=True,
)
print(result.stdout)
print(result.stderr)
assert result.returncode == 0
=== END AC block-quotes ===
=== AC block-quotes-nested ===
Intent: Nested and lazy block quote examples execute successfully.
Suite: scoped
Requires: executable=python3; scope=test
import subprocess
result = subprocess.run(
[
"python3",
"spec_tests.py",
"--spec",
"spec.txt",
"--program",
"./cmark",
"--pattern",
r"^Block quotes$",
],
capture_output=True,
text=True,
)
print(result.stdout)
print(result.stderr)
assert result.returncode == 0
=== END AC block-quotes-nested ===
## User Acceptance
- None.
## Guardrails
- Block structure is parsed before inline structure.
- Lazy continuation does not continue a quote across a new block construct.
- The parser does not use a public Markdown implementation.
=== END FEATURE-BLOCK-QUOTES.md ===
=== FEATURE-BLOCK-LISTS.md ===
# FEATURE: List Items and Lists
| Field | Value |
|-------------|-------|
| Version | 20260812 V1 |
| Description | Defines CommonMark bullet lists, ordered lists, nesting, and list tightness. |
| Depends On | FEATURE-BLOCK-LEAF.md, FEATURE-BLOCK-QUOTES.md |
| Provides | list parser |
| Consumes | leaf block parser, block quote parser |
## Questions
- None.
## Purpose
Lists contain bullet or ordered list items whose contents are recursively parsed as CommonMark blocks.
## Behavior
The parser supports:
- Bullet markers `-`, `+`, and `*`.
- Ordered markers with one to nine digits followed by `.` or `)`.
- Empty list items.
- Nested lists determined by marker width and indentation.
- Lists interrupted by paragraphs where CommonMark permits interruption.
- Lazy continuation lines.
- Block quotes, headings, code blocks, paragraphs, and other blocks inside list items.
- Separate lists when bullet characters or ordered delimiters change.
- Ordered-list start numbers, including leading zeroes.
- Tight and loose list classification based on blank-line separation.
- Correct paragraph wrapping for tight and loose lists.
The list parser preserves item structure and tightness metadata for the renderer.
## Programmatic Acceptance
=== AC lists-items ===
Intent: The parser passes the complete list item conformance section.
Suite: scoped
Requires: executable=python3; scope=test
import subprocess
result = subprocess.run(
[
"python3",
"spec_tests.py",
"--spec",
"spec.txt",
"--program",
"./cmark",
"--pattern",
r"^(List items|Lists)$",
],
capture_output=True,
text=True,
)
print(result.stdout)
print(result.stderr)
assert result.returncode == 0
=== END AC lists-items ===
=== AC lists-nesting-tightness ===
Intent: Nested, empty, delimiter-changing, and tightness examples execute successfully.
Suite: scoped
Requires: executable=python3; scope=test
import subprocess
result = subprocess.run(
[
"python3",
"spec_tests.py",
"--spec",
"spec.txt",
"--program",
"./cmark",
"--pattern",
r"^(List items|Lists)$",
],
capture_output=True,
text=True,
)
print(result.stdout)
print(result.stderr)
assert result.returncode == 0
=== END AC lists-nesting-tightness ===
## User Acceptance
- None.
## Guardrails
- List markers are recognized only where CommonMark permits them.
- Thematic breaks take precedence over competing list-item interpretations.
- Tightness is derived from list structure and blank-line separation, not from output text.
- The parser does not use a public Markdown implementation.
=== END FEATURE-BLOCK-LISTS.md ===
=== FEATURE-INLINE-ESCAPES.md ===
# FEATURE: Escapes and Character References
| Field | Value |
|-------------|-------|
| Version | 20260812 V1 |
| Description | Defines CommonMark backslash escapes and character reference handling. |
| Depends On | FEATURE-BLOCK-LISTS.md |
| Provides | escape parser, character reference parser |
| Consumes | block parser |
## Questions
- None.
## Purpose
Inline parsing interprets escaped punctuation and valid HTML named or numeric character references while preserving literal syntax in restricted contexts.
## Behavior
The parser supports:
- Backslash escapes for every ASCII punctuation character.
- Literal backslashes before non-punctuation characters.
- Named HTML entities with semicolons.
- Decimal and hexadecimal numeric references.
- Replacement of invalid Unicode code points and U+0000 with U+FFFD.
- Character references in ordinary inline content, URLs, titles, and fenced-code info strings.
- Literal treatment of escapes and references in code spans, indented code, fenced code content, autolinks, and raw HTML.
- Structural characters remaining structural when represented by character references is not permitted.
## Programmatic Acceptance
=== AC escapes ===
Intent: The parser passes the complete backslash escape conformance section.
Suite: scoped
Requires: executable=python3; scope=test
import subprocess
result = subprocess.run(
[
"python3",
"spec_tests.py",
"--spec",
"spec.txt",
"--program",
"./cmark",
"--pattern",
r"^Backslash escapes$",
],
capture_output=True,
text=True,
)
print(result.stdout)
print(result.stderr)
assert result.returncode == 0
=== END AC escapes ===
=== AC character-references ===
Intent: The parser passes entity, numeric reference, and insecure-character conformance sections.
Suite: scoped
Requires: executable=python3; scope=test
result = subprocess.run(
[
"python3",
"spec_tests.py",
"--spec",
"spec.txt",
"--program",
"./cmark",
"--pattern",
r"^(Insecure characters|Entity and numeric character references)$",
],
capture_output=True,
text=True,
)
print(result.stdout)
print(result.stderr)
assert result.returncode == 0
=== END AC character-references ===
## User Acceptance
- None.
## Guardrails
- U+0000 is never emitted as a literal null character.
- Escapes and references do not alter block-level syntax.
- The parser does not use a public Markdown implementation.
=== END FEATURE-INLINE-ESCAPES.md ===
=== FEATURE-INLINE-CODE-BREAKS.md ===
# FEATURE: Code Spans and Line Breaks
| Field | Value |
|-------------|-------|
| Version | 20260812 V1 |
| Description | Defines CommonMark code spans, hard breaks, and soft breaks. |
| Depends On | FEATURE-BLOCK-LISTS.md |
| Provides | code span parser, hard break parser, soft break parser |
| Consumes | block parser |
## Questions
- None.
## Purpose
Inline parsing recognizes backtick-delimited code spans and distinguishes hard line breaks from ordinary soft line breaks.
## Behavior
The parser supports:
- Code spans delimited by equal-length backtick runs.
- Unclosed and mismatched backtick runs as literal text.
- Conversion of line endings inside code spans to spaces.
- Removal of one matching leading and trailing space around non-space code content.
- Preservation of interior spaces and literal escapes inside code spans.
- Hard breaks caused by two or more trailing spaces or a trailing backslash.
- Suppression of hard-break interpretation at block ends and inside code spans or HTML tags.
- Soft breaks for ordinary paragraph line endings.
- Removal of indentation after a hard or soft line break according to CommonMark rules.
## Programmatic Acceptance
=== AC code-spans ===
Intent: The parser passes the complete code span conformance section.
Suite: scoped
Requires: executable=python3; scope=test
import subprocess
result = subprocess.run(
[
"python3",
"spec_tests.py",
"--spec",
"spec.txt",
"--program",
"./cmark",
"--pattern",
r"^Code spans$",
],
capture_output=True,
text=True,
)
print(result.stdout)
print(result.stderr)
assert result.returncode == 0
=== END AC code-spans ===
=== AC-line-breaks ===
Intent: The parser passes hard and soft line break conformance sections.
Suite: scoped
Requires: executable=python3; scope=test
result = subprocess.run(
[
"python3",
"spec_tests.py",
"--spec",
"spec.txt",
"--program",
"./cmark",
"--pattern",
r"^(Hard line breaks|Soft line breaks)$",
],
capture_output=True,
text=True,
)
print(result.stdout)
print(result.stderr)
assert result.returncode == 0
=== END AC-line-breaks ===
## User Acceptance
- None.
## Guardrails
- Code spans do not interpret Markdown escapes or character references.
- Hard breaks are not created at the end of a block.
- The parser does not use a public Markdown implementation.
=== END FEATURE-INLINE-CODE-BREAKS.md ===
=== FEATURE-INLINE-EMPHASIS.md ===
# FEATURE: Emphasis and Strong Emphasis
| Field | Value |
|-------------|-------|
| Version | 20260812 V1 |
| Description | Defines CommonMark emphasis and strong-emphasis delimiter processing. |
| Depends On | FEATURE-INLINE-CODE-BREAKS.md |
| Provides | emphasis parser, strong emphasis parser |
| Consumes | block parser, code span parser |
## Questions
- None.
## Purpose
Inline parsing resolves asterisk and underscore delimiter runs using CommonMark flanking, nesting, precedence, and modulo-three rules.
## Behavior
The parser supports:
- Left- and right-flanking delimiter runs.
- Single and double delimiters for emphasis and strong emphasis.
- Intraword asterisk emphasis.
- Intraword underscore restrictions.
- Nested emphasis and strong emphasis.
- Mixed emphasis and strong-emphasis nesting.
- Literal unmatched delimiter characters.
- The modulo-three rule for ambiguous delimiter runs.
- Precedence of code spans, links, images, autolinks, and HTML tags over emphasis.
- Unicode whitespace and punctuation classification for delimiter decisions.
Delimiter processing occurs after block parsing and respects inline constructs that bind more tightly.
## Programmatic Acceptance
=== AC emphasis ===
Intent: The parser passes the complete emphasis and strong emphasis conformance section.
Suite: scoped
Requires: executable=python3; scope=test
import subprocess
result = subprocess.run(
[
"python3",
"spec_tests.py",
"--spec",
"spec.txt",
"--program",
"./cmark",
"--pattern",
r"^Emphasis and strong emphasis$",
],
capture_output=True,
text=True,
)
print(result.stdout)
print(result.stderr)
assert result.returncode == 0
=== END AC emphasis ===
=== AC emphasis-precedence ===
Intent: Emphasis nesting, intraword restrictions, and precedence examples execute successfully.
Suite: scoped
Requires: executable=python3; scope=test
result = subprocess.run(
[
"python3",
"spec_tests.py",
"--spec",
"spec.txt",
"--program",
"./cmark",
"--pattern",
r"^Emphasis and strong emphasis$",
],
capture_output=True,
text=True,
)
print(result.stdout)
print(result.stderr)
assert result.returncode == 0
=== END AC emphasis-precedence ===
## User Acceptance
- None.
## Guardrails
- Delimiter runs are resolved according to CommonMark 0.31.2 rules.
- Unmatched delimiters remain literal text.
- Code spans, links, images, autolinks, and raw HTML bind more tightly than emphasis.
- The parser does not use a public Markdown implementation.
=== END FEATURE-INLINE-EMPHASIS.md ===Run artifact