=== FEATURE-INLINE-LINKS.md === # FEATURE: Inline Links and Images | Field | Value | |-------------|-------| | Version | 20260812 V1 | | Description | Defines inline links, reference links, images, destinations, titles, and reference resolution. | | Depends On | ARCHITECTURE.md, FEATURE-BLOCK-LEAF.md, FEATURE-INLINE-EMPHASIS.md | | Provides | link parser, image parser, reference resolver | | Consumes | block parser, inline parser | ## Questions - None. ## Purpose The inline parser recognizes inline, full-reference, collapsed-reference, and shortcut links and images. It resolves link reference definitions collected during block parsing, supports balanced destinations and titles, and prevents nested links while permitting nested image descriptions. ## Behavior - Inline destinations may be empty, angle-bracket delimited, escaped, or contain balanced parentheses. - Titles may use single quotes, double quotes, or parentheses. - Reference labels are normalized with Unicode case folding and whitespace normalization. - The first matching reference definition wins. - Link text is parsed as inline content. - Image descriptions produce plain-text `alt` content. - Links cannot contain links; image descriptions may contain links. ## Programmatic Acceptance === AC inline-links-suite === Intent: The inline link, reference link, and image syntax passes its complete owned conformance scope. Suite: scoped Requires: executable=python3; scope=test import subprocess import sys result = subprocess.run( [sys.executable, "spec_tests.py", "--spec", "spec.txt", "--program", "./commonmark", "--pattern", "^(Links|Images)$"], capture_output=True, text=True, ) print(result.stdout) print(result.stderr, file=sys.stderr) assert result.returncode == 0 === END AC inline-links-suite === === AC inline-links-boundaries === Intent: The implementation preserves link and image destination, title, reference, and nesting behavior. Suite: scoped Requires: executable=python3; scope=test import subprocess import sys result = subprocess.run( [sys.executable, "spec_tests.py", "--spec", "spec.txt", "--program", "./commonmark", "--pattern", "^(Links|Images)$"], capture_output=True, text=True, ) assert result.returncode == 0 === END AC inline-links-boundaries === ## User Acceptance - None. ## Guardrails - The implementation does not use a public Markdown implementation. - Reference definitions are resolved globally while preserving first-definition precedence. === END FEATURE-INLINE-LINKS.md === === FEATURE-INLINE-HTML.md === # FEATURE: Autolinks and Raw HTML | Field | Value | |-------------|-------| | Version | 20260812 V1 | | Description | Defines URI and email autolinks and preservation of raw HTML inline constructs. | | Depends On | ARCHITECTURE.md, FEATURE-INLINE-LINKS.md | | Provides | autolink parser, raw HTML parser | | Consumes | block parser, inline parser | ## Questions - None. ## Behavior - Absolute URI autolinks become links whose labels preserve the source URI. - Valid email autolinks become `mailto:` links. - HTML tags, comments, declarations, processing instructions, and CDATA are preserved as raw HTML. - Invalid autolinks and malformed HTML-like text remain escaped text. - Backslash escapes do not apply inside autolinks or raw HTML. ## Programmatic Acceptance === AC inline-html-suite === Intent: The autolink and raw HTML syntax passes its complete owned conformance scope. Suite: scoped Requires: executable=python3; scope=test import subprocess import sys result = subprocess.run( [sys.executable, "spec_tests.py", "--spec", "spec.txt", "--program", "./commonmark", "--pattern", "^(Autolinks|Raw HTML)$"], capture_output=True, text=True, ) print(result.stdout) print(result.stderr, file=sys.stderr) assert result.returncode == 0 === END AC inline-html-suite === === AC inline-html-malformed === Intent: Invalid autolinks and malformed HTML remain ordinary escaped content. Suite: scoped Requires: executable=python3; scope=test import subprocess import sys result = subprocess.run( [sys.executable, "spec_tests.py", "--spec", "spec.txt", "--program", "./commonmark", "--pattern", "^(Autolinks|Raw HTML)$"], capture_output=True, text=True, ) assert result.returncode == 0 === END AC inline-html-malformed === ## User Acceptance - None. ## Guardrails - Raw HTML is preserved only when it satisfies the CommonMark inline grammar. - The parser does not execute or fetch HTML or URI content. === END FEATURE-INLINE-HTML.md === === FEATURE-RENDER-BLOCKS.md === # FEATURE: Block HTML Rendering | Field | Value | |-------------|-------| | Version | 20260812 V1 | | Description | Defines HTML rendering for parsed block structure and block-level content. | | Depends On | ARCHITECTURE.md, FEATURE-BLOCK-LISTS.md, FEATURE-INLINE-HTML.md | | Provides | block HTML renderer | | Consumes | block parser, inline parser | ## Questions - None. ## Rendering Contract - Paragraphs render as `

` elements except for paragraphs in tight lists. - ATX and setext headings render as `

` through `

`. - Thematic breaks render as `
`. - Indented and fenced code render as escaped `
` content.
- Block quotes render as `
`. - Ordered and unordered lists preserve nesting, start values, item boundaries, and tightness. - Raw HTML blocks remain unescaped. ## Programmatic Acceptance === AC render-blocks-suite === Intent: Block-level HTML rendering passes the complete owned conformance scope. Suite: scoped Requires: executable=python3; scope=test import subprocess import sys result = subprocess.run( [sys.executable, "spec_tests.py", "--spec", "spec.txt", "--program", "./commonmark", "--pattern", "^(Thematic breaks|ATX headings|Setext headings|Indented code blocks|Fenced code blocks|HTML blocks|Paragraphs|Blank lines|Block quotes|List items|Lists)$"], capture_output=True, text=True, ) print(result.stdout) print(result.stderr, file=sys.stderr) assert result.returncode == 0 === END AC render-blocks-suite === === AC render-blocks-escaping === Intent: Block rendering preserves structural nesting and escapes literal code content. Suite: scoped Requires: executable=python3; scope=test import subprocess import sys result = subprocess.run( [sys.executable, "spec_tests.py", "--spec", "spec.txt", "--program", "./commonmark", "--pattern", "^(Indented code blocks|Fenced code blocks|Block quotes|List items|Lists)$"], capture_output=True, text=True, ) assert result.returncode == 0 === END AC render-blocks-escaping === ## User Acceptance - None. ## Guardrails - Block rendering never treats captured test output as a correctness oracle. - Literal code content is escaped while raw HTML blocks remain preserved. === END FEATURE-RENDER-BLOCKS.md === === FEATURE-RENDER-INLINE.md === # FEATURE: Inline HTML Rendering | Field | Value | |-------------|-------| | Version | 20260812 V1 | | Description | Defines HTML rendering for parsed inline nodes and inline source constructs. | | Depends On | ARCHITECTURE.md, FEATURE-RENDER-BLOCKS.md | | Provides | inline HTML renderer | | Consumes | inline parser | ## Questions - None. ## Rendering Contract - Text escapes HTML-significant characters. - Emphasis and strong emphasis render as `` and ``. - Code spans render as escaped `` content. - Links render escaped `href` and optional `title` attributes. - Images render escaped `src`, plain-text `alt`, and optional `title`. - Hard breaks render as `
`; soft breaks preserve permitted line-break semantics. - Autolinks and raw HTML preserve the required HTML representation. - Entity references render as their corresponding characters, with HTML escaping where required. ## Programmatic Acceptance === AC render-inline-suite === Intent: Inline HTML rendering passes the complete owned conformance scope. Suite: scoped Requires: executable=python3; scope=test import subprocess import sys result = subprocess.run( [sys.executable, "spec_tests.py", "--spec", "spec.txt", "--program", "./commonmark", "--pattern", "^(Characters and lines|Backslash escapes|Entity and numeric character references|Code spans|Emphasis and strong emphasis|Links|Images|Autolinks|Raw HTML|Hard line breaks|Soft line breaks|Textual content)$"], capture_output=True, text=True, ) print(result.stdout) print(result.stderr, file=sys.stderr) assert result.returncode == 0 === END AC render-inline-suite === === AC render-inline-escaping === Intent: Inline rendering escapes text and code while preserving links, images, and raw HTML. Suite: scoped Requires: executable=python3; scope=test import subprocess import sys result = subprocess.run( [sys.executable, "spec_tests.py", "--spec", "spec.txt", "--program", "./commonmark", "--pattern", "^(Code spans|Links|Images|Autolinks|Raw HTML|Hard line breaks|Soft line breaks)$"], capture_output=True, text=True, ) assert result.returncode == 0 === END AC render-inline-escaping === ## User Acceptance - None. ## Guardrails - Renderer output is derived from parsed inline nodes and never from test-result text. - User text cannot inject markup except through valid raw HTML constructs. === END FEATURE-RENDER-INLINE.md === === FEATURE-RENDER-NORMALIZATION.md === # FEATURE: Normalized HTML Output | Field | Value | |-------------|-------| | Version | 20260812 V1 | | Description | Defines URL, title, attribute, entity, and special-character output compatibility with the supplied harness. | | Depends On | ARCHITECTURE.md, FEATURE-RENDER-INLINE.md | | Provides | normalized URL output, normalized title output, normalized attribute output | | Consumes | block HTML renderer, inline HTML renderer | ## Questions - None. ## Output Rules - URLs preserve valid percent escapes and encode required spaces, Unicode characters, and backslashes. - Titles and attribute values are HTML-escaped. - Attribute output is deterministic and preserves required source semantics. - Entity and numeric references are normalized consistently with the supplied harness. - Special characters use the required HTML entities. - Normalization compatibility does not alter code-block whitespace or raw HTML semantics. ## Programmatic Acceptance === AC render-normalization-suite === Intent: URL, title, attribute, entity, and special-character rendering passes its complete conformance scope. Suite: scoped Requires: executable=python3; scope=test import subprocess import sys result = subprocess.run( [sys.executable, "spec_tests.py", "--spec", "spec.txt", "--program", "./commonmark", "--pattern", "^(Links|Images|Autolinks|Raw HTML|Entity and numeric character references)$"], capture_output=True, text=True, ) print(result.stdout) print(result.stderr, file=sys.stderr) assert result.returncode == 0 === END AC render-normalization-suite === === AC render-normalization-specials === Intent: Normalized output preserves URL escaping, title escaping, attribute semantics, and special characters. Suite: scoped Requires: executable=python3; scope=test import subprocess import sys result = subprocess.run( [sys.executable, "spec_tests.py", "--spec", "spec.txt", "--program", "./commonmark", "--pattern", "^(Links|Images|Autolinks|Raw HTML|Entity and numeric character references)$"], capture_output=True, text=True, ) assert result.returncode == 0 === END AC render-normalization-specials === ## User Acceptance - None. ## Guardrails - Output normalization is deterministic and does not use a hardcoded pass tally. - The supplied normalizer is used only as a comparison aid; its output is never the acceptance oracle. === END FEATURE-RENDER-NORMALIZATION.md ===