=== 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 ===