Docs — Markdown Rendering — QA Test Cases¶
Source: every write path that turns a user's Markdown into a Google Doc. That's our converter (tools/docs/content.py _md_to_html → html_parser.py → emitter.py), Drive's native Markdown import (tools/drive/transfer.py _CONVERT_MIME[".md"]), and Drive's HTML import of upload_file(source_format='markdown').
Tracking: #1044. This file is the v0.9.4 release gate for Markdown rendering: v0.9.4 ships when every case below passes on screen through every entry point.
Fixtures: docs/qa/fixtures/md/. The nesting, containment, adjacency, inline-matrix, long-document and docstart/ fixtures, and the four matrix tables in this file, are generated by uv run python scripts/qa_gen_md_fixtures.py (--check reports drift); change those there, not by hand. Substitute {FOLDER_ID} (a throwaway child folder of TEST_FOLDER_ID, see "Running this suite") and {REPO} (absolute path of the checkout the server under test runs from).
Rules¶
- Playwright is the oracle. Every case is Playwright: required. The verdict comes from the rendered Doc on screen, with one screenshot saved per case per entry point.
get_doc_structureandget_doc_as_markdownare supporting evidence only, never the verdict: the Markdown export writes every numbered item as1., so it can't see a numbering restart, and it may be blind to more. "Confirmed via unit tests" or "known gap, visual only" is not a result. - The expected rendering is written down before a case runs (this file). It says what a reader sees: numbering, indent level, glyph, font, link target. Where the screen alone can't settle a detail, the case names the structural check that does (the Structural column or line).
- A known failure is a FAIL. "Matches documented failure mode," "known gap," "pre-existing," and "not a new regression" are never a PASS. A failing case stays FAIL, linked to an open issue, until the fix lands and the case passes on screen.
- Nondeterminism is a FAIL. The whole matrix runs twice (Run 1, Run 2). A case that renders differently across the two runs fails, even if both renderings look acceptable.
- No sampling. Every case goes through every entry point in the table below, unless the case is marked N/A for an entry point with a reason. Shared code is how a path-specific wrapper bug hides.
- Anything that looks wrong is a finding, whether or not a case below covers it. Phase 1 especially: read each document top to bottom against its source.
Entry points¶
Every case runs through every entry point. EP-1 to EP-4 use our converter. EP-5 to EP-7 use Drive's native Markdown import (they upload the .md file and Drive converts it). EP-8 converts with Python-Markdown's extra extension and then uses Drive's HTML import. A rendering difference between engines is itself a finding: the same Markdown should read the same way whichever tool turned it into a Doc.
| EP | Tool call (fixture F = absolute path of the .md file) |
Engine |
|---|---|---|
| EP-1 | create_doc(title="MD-<case>-EP1", content=<contents of F>, content_format="markdown", folder_id="{FOLDER_ID}") |
ours |
| EP-2 | write_doc_content(doc_id=<a blank Doc in {FOLDER_ID}>, content=<contents of F>, content_format="markdown") |
ours |
| EP-3 | create_doc_from_file(local_path=F, title="MD-<case>-EP3", folder_id="{FOLDER_ID}") |
ours |
| EP-4 | update_doc_from_file(doc_id=<a blank Doc in {FOLDER_ID}>, local_path=F) |
ours |
| EP-5 | upload_local_file(local_path=F, parent_folder_id=<empty child of {FOLDER_ID} for EP-5>, convert=True) |
Drive Markdown import |
| EP-6 | upload_local_folder(local_path=<a temp dir holding only F>, parent_folder_id=<empty child of {FOLDER_ID} for EP-6>, convert=True) |
Drive Markdown import |
| EP-7 | sync_folder(local_path=<a temp dir holding only F>, folder_id=<empty child of {FOLDER_ID} for EP-7>, direction="upload", convert_markdown=True) |
Drive Markdown import |
| EP-8 | upload_file(name="<case>.md", content=<contents of F>, source_format="markdown", folder_id="{FOLDER_ID}", convert_to_doc=True) |
Python-Markdown extra + Drive HTML import |
EP-5, EP-6 and EP-7 each get their own empty child folder: these tools skip a file whose converted Doc already exists in the target folder (skip_if_exists defaults to True), so a shared folder would turn a later entry point's render into a skipped.
Not an entry point: no tool inserts Markdown at an index in an existing Doc (insert_doc_text takes plain text). The "insert at an index" state in #1044 is therefore N/A; if such a tool is added, it joins this table.
Parameter variants that only some entry points take:
autolink_urls=False(EP-1 to EP-4 only; the Drive engines have no such switch): runmd-links.mda second time with it. Cases LK-05 and LK-06 then expect plain, unlinked text; every other links case is unchanged.- Images with a local path or
drive:source (IM-04 to IM-06): EP-5 to EP-8 don't resolve them, so those cells expect whatever Drive does with an unresolvable image reference. Record what's on screen; a broken-image icon or literaltext is a FAIL for that engine.
What correct looks like in a Google Doc¶
Markdown describes HTML, and Docs has no direct equivalent for some constructs. These conventions turn "renders correctly" into something checkable. They follow the converter's documented design (docs/design/markdown-support.md, docs/design/blockquote-representation.md) where one exists.
| # | Construct | Expected on screen | Structural check when the screen is ambiguous |
|---|---|---|---|
| C1 | ATX/Setext heading level N | Docs "Heading N" style (font size and weight of that named style) | get_doc_structure: namedStyleType == HEADING_N |
| C2 | Bullet list, levels 0/1/2 | Glyphs ● / ○ / ■, each level indented one step further | bullet.nestingLevel = 0/1/2; contiguous same-type items of one Markdown list share one listId (a bullet run nested in a numbered list is its own Docs list) |
| C3 | Numbered list, levels 0/1/2 | 1. 2. … / a. b. … / i. ii. …; numbering never restarts inside one Markdown list, including after a nested block |
contiguous same-type items share one listId; the screen is the verdict for the number shown, since a nested block of the other type is a separate Docs list |
| C4 | Task item | Bullet item whose text starts with ☐ (unchecked) or ☑ (checked); no literal [ ]/[x] |
— |
| C5 | Inline code | Courier New on exactly the code characters | textStyle.weightedFontFamily.fontFamily == "Courier New" on that run only |
| C6 | Code block (fenced or indented) | One Courier New block; each source line on its own visual line; leading indentation and blank lines kept; no Markdown inside it interpreted | one paragraph (lines joined by soft breaks), all runs Courier New |
| C7 | Blockquote, depth N | Indented N steps with a gray left border; content inside keeps its own formatting (lists stay lists, headings stay headings) | paragraphStyle.indentStart = 36pt × N and borderLeft set |
| C8 | Thematic break | A visible horizontal line across the page; never an empty-looking gap | — |
| C9 | Hard break (two trailing spaces, \) |
Line break inside the same paragraph: no extra blank line, no paragraph spacing between the two lines | one paragraph containing a \v (soft line break) |
| C10 | Soft break (a plain newline inside a paragraph) | The lines join into one paragraph, separated by a space | one paragraph |
| C11 | Image | The image itself is visible at its natural size (or scaled to page width); alt text is not shown as visible text | inlineObjectElement present |
| C12 | Link | Link-styled text (blue, underlined) whose target is the Markdown URL | hover or textStyle.link.url |
| C13 | Table | A Docs table, header row bold, cell text and inline formatting intact; column alignment from :--/:-:/--: applied to the cells of that column |
tableCells[].content[].paragraph.paragraphStyle.alignment |
| C14 | Block inside a list item (paragraph, code, quote, table, heading) | Shown under the item, indented to the item's text, not as a new top-level block and not as literal Markdown; the list continues after it (next item keeps the list's numbering and nesting) | the screen is the verdict: the next item shows the continued number or glyph; it shares the preceding items' listId when they're the same type |
| C15 | Empty paragraph spacing | No visible empty paragraph that the source doesn't imply. The known collapsed blank paragraph before each table (docs/known-limitations.md, "Blank paragraph before every table") must stay invisible |
— |
Decisions where CommonMark/GFM and what a user means disagree, approved by the maintainer on 2026-10-17. Each is the expected behavior for this plan; changing one changes the expected rendering of the cases that cite it.
- D1 — nesting width. A list marker indented at least 2 spaces (or one tab) further than the previous item's marker nests under that item, whatever the parent's marker width. CommonMark requires the child to reach the parent's content column, so
1. Afollowed by- a1(2 spaces) doesn't nest under CommonMark, but that is how models and people write sub-bullets, and #1044's own example expects it to nest. - D2 — a table starts its own block. A pipe table directly under a paragraph, list item or quote line (no blank line) renders as a separate table after that block, not as text joined to it.
- D3 — YAML front matter is not shown. A leading
----delimited YAML block is omitted from the Doc (docs/design/markdown-support.mdcurrently calls it "acceptable" that it renders as a rule; that is a FAIL under this plan).
Anything CommonMark/GFM permits that the converter deliberately won't support goes into docs/known-limitations.md, tied to an open issue, and its cases stay FAIL until a decision changes the expected rendering here.
Running this suite¶
- Server and slot. Use a server running the code under test with
LOCAL_FILE_ACCESS=full(EP-3 to EP-7 are local-only tools). Use an OAuth identity, or a service account with a Shared Drive{FOLDER_ID}. - Throwaway folder. Create a child folder of
TEST_FOLDER_IDnamedQA-MD-<date>-run<N>and use it as{FOLDER_ID}. Everything this suite creates goes there. Trash the folder after the results are recorded. - Placeholders.
md-images.mdcontains{QA_IMAGE_LOCAL_PATH}and{QA_IMAGE_DRIVE_ID}. Copy the fixture todocs/qa/fixtures/md/syntax/md-images.local.md(next to the original, so IM-05's relative path still resolves the same way), substitute the absolute path ofdocs/qa/fixtures/qa-fixture-pixel.pngand the Drive ID of an uploaded copy of it, and use the copy.*.local.mdunderdocs/qa/fixtures/is ignored by version control, so the substituted copy (it holds a resource ID) can't be committed by accident. - One render per fixture per entry point. Each syntax fixture holds many small cases, each under its own
### <ID> — <description>heading, so one render covers them all and a failure still points at one construct. Phase 1 documents and the document-boundary files (docstart/) are one case per file. - Screenshots. Open the Doc at
https://docs.google.com/document/d/<id>/editand take one screenshot per case, scrolled so the case's heading and its full content are in view. Name itdocs/qa/screenshots/md/<run>/<EP>/<case>.png(thescreenshots/tree is gitignored; keep the files until every issue filed from the run has them attached). Follow the Playwright mutex inrun.md§"Coordinating Playwright across parallel shards", and verify the account first per §"Verifying Playwright is signed into the right account". - Order. Phase 1 first, and file its failures before starting Phase 2 (#1044, "obvious problems first"). Then Phase 2, then the document-state cases.
- Determinism. Repeat the whole matrix as Run 2 in a fresh folder. Compare each case's Run 2 screenshot with Run 1.
- Recording. Write the per-case × per-entry-point grid to
docs/qa/results/<date>-markdown.md(rows: case IDs; columns: EP-1 to EP-8; cells ✅, ❌ with the issue number, or N/A with the reason). Under each TC below, add one summary line:**Result (<date>) ❌ FAIL — <passed>/<total> case×EP cells pass; failures: #…**. A TC is ✅ PASS only when every cell of every case in it passes in both runs. - Group.
docs/qa/operations.yamlrun_groupwithgroup: docs_markdownruns this file.
Phase 1 — Realistic documents¶
Documents of the kind AI clients produce, written the way a model writes them (2- and 3-space nesting, numbered steps with sub-bullets, bold lead-ins, tables, code). For each: render it, then read the Doc on screen top to bottom against the source, as a user would. Every construct follows the conventions above. The checklist names what's most likely to go wrong in that document; it doesn't limit what counts as a finding.
TC-MD001: Meeting notes ⚠️ destructive¶
Prompt Playwright: required
Render
docs/qa/fixtures/md/realistic/r01-meeting-notes.mdthrough EP-1 to EP-8.
Checks
- The Date/Attendees/Facilitator lines: each label bold. Under C10 the three source lines join into one paragraph (no blank lines between them in the source); that is expected, not a finding.
- Agenda: items numbered 1–4 with no restart; the 3-space sub-bullets under items 1 and 2 nest at level 1 (○), and no - shows as text.
- The two-line blockquote with the attribution line: one quote, left border, both lines inside it, italic/bold intact.
- Decisions table: 3 columns, bold header, every cell's text intact.
- Action items: ☐/☑ glyphs, no literal [ ]/[x]; the bold names stay bold.
- The closing italic line is italic.
Result (2026-10-18) ❌ FAIL — 0/8 case×EP cells pass, in both runs; failures: #1071, #1093, #1056, #1098, #1101, #1102. Grid: results/2026-10-18-markdown.md.
TC-MD002: Project plan ⚠️ destructive¶
Prompt Playwright: required
Render
docs/qa/fixtures/md/realistic/r02-project-plan.mdthrough EP-1 to EP-8.
Checks
- Goals: 1–3 numbered with no restart after the 3-space sub-bullets; each goal's bold lead-in bold.
- Phase 1 list: 1–4 with a nested numbered list (a. b. c.) under item 3, and item 4 numbered 4.
- Phase 2: bullets with a nested level under "Usability tests".
- Timeline table: four rows, en-dash date ranges intact.
- **30%** bold in the overview.
Result (2026-10-18) ❌ FAIL — 0/8 case×EP cells pass, in both runs; failures: #1071, #1093, #1101, #1102. Grid: results/2026-10-18-markdown.md.
TC-MD003: Spec / PRD ⚠️ destructive¶
Prompt Playwright: required
Render
docs/qa/fixtures/md/realistic/r03-spec-prd.mdthrough EP-1 to EP-8.
Checks
- The --- under the metadata block renders as a horizontal line (C8), not a Setext heading (there's a blank line above it).
- Section headings "1. Problem", "4.1 Functional": headings, not list items.
- Requirements table: the Priority column is centered (:--------:), ID and Requirement left-aligned.
- http code block: monospace, blank line inside it kept, JSON line intact.
- Appendix links: both link to their URLs; the titled link shows no title text.
Result (2026-10-18) ❌ FAIL — 0/8 case×EP cells pass, in both runs; failures: #1093, #1095, #1096, #1101, #1102. Grid: results/2026-10-18-markdown.md.
TC-MD004: README ⚠️ destructive¶
Prompt Playwright: required
Render
docs/qa/fixtures/md/realistic/r04-readme.mdthrough EP-1 to EP-8.
Checks
- The badge (a linked image) shows as an image and links to the CI URL.
- Each fenced block (bash, python) is one monospace block; Python indentation and the blank line between definitions kept.
- Configuration table: backticked values monospace inside cells.
- Usage notes: 1–4 numbered, with the fenced code block under item 3 (C14) and item 4 numbered 4.
- The > **Note:** blockquote spans both source lines, with "Note:" bold.
- © renders.
Result (2026-10-18) ❌ FAIL — 0/8 case×EP cells pass, in both runs; failures: #1094, #1093, #1099, #1101, #1102. EP-8 rendering changed between runs (Rule 4). Grid: results/2026-10-18-markdown.md.
TC-MD005: Status report ⚠️ destructive¶
Prompt Playwright: required
Render
docs/qa/fixtures/md/realistic/r05-status-report.mdthrough EP-1 to EP-8.
Checks - Emoji in headings (🟢 🟡) render inside the heading style. - "Mitigation:" bullet has two nested bullets at level 1 (2-space indentation). - Performance table: three right-aligned numeric columns. - Asks: numbered 1–2.
Result (2026-10-18) ❌ FAIL — 0/8 case×EP cells pass, in both runs; failures: #1071, #1095, #1093, #1101, #1102. Grid: results/2026-10-18-markdown.md.
TC-MD006: How-to with numbered steps and code ⚠️ destructive¶
Prompt Playwright: required
Render
docs/qa/fixtures/md/realistic/r06-howto.mdthrough EP-1 to EP-8.
Checks
- Steps: numbered 1–5 with no restart, although each step holds a fenced code block (loose list, code inside items, C14).
- Each code block sits under its step, indented to the step text, in monospace; no literal `` fences.
- Step 3's second paragraph ("Wait until…") and its second code block stay inside step 3.
- Step 4's sub-bullets nest under step 4.
-http://localhost:8000` is a link.
- Troubleshooting: the bold lead-in paragraphs are bold, and the OS bullet list follows.
Result (2026-10-18) ❌ FAIL — 0/8 case×EP cells pass, in both runs; failures: #1094, #1072, #1071, #1056, #1093, #1101, #1102. Grid: results/2026-10-18-markdown.md.
TC-MD007: Comparison with tables ⚠️ destructive¶
Prompt Playwright: required
Render
docs/qa/fixtures/md/realistic/r07-comparison.mdthrough EP-1 to EP-8.
Checks - "At a glance" table: empty top-left header cell; provider columns centered; ✅/❌ emoji in cells. - Scoring table: Weight/A/B/C right-aligned; the bold "Weighted total" row bold in every cell. - Each provider's Pros / Cons bold paragraphs followed by their own bullet lists (separate lists).
Result (2026-10-18) ❌ FAIL — 0/8 case×EP cells pass, in both runs; failures: #1095, #1093, #1101, #1102. Grid: results/2026-10-18-markdown.md.
TC-MD008: Research summary with quotes and links ⚠️ destructive¶
Prompt Playwright: required
Render
docs/qa/fixtures/md/realistic/r08-research-summary.mdthrough EP-1 to EP-8.
Checks - Key findings: 1–3 numbered; finding 1's text continues onto a second source line and joins into one item (C10); item 2's nested bullets at level 1; item 3 numbered 3. - Two separate one-paragraph quotes, then a nested quote (depth 2) followed by a depth-1 attribution line. - The bare URL in "Related reading" is a link. - The data table's two numeric columns right-aligned.
Result (2026-10-18) ❌ FAIL — 0/8 case×EP cells pass, in both runs; failures: #1071, #1093, #1098, #1056, #1095, #1101, #1102. Grid: results/2026-10-18-markdown.md.
TC-MD009: Changelog ⚠️ destructive¶
Prompt Playwright: required
Render
docs/qa/fixtures/md/realistic/r09-changelog.mdthrough EP-1 to EP-8.
Checks
- Version headings [2.4.0] - 2026-10-15 show as headings in which "2.4.0" links to its compare URL: the reference definitions at the bottom make [2.4.0] a shortcut reference link (CommonMark). No brackets shown, and the three definition lines at the bottom aren't shown at all.
- The fenced code block nested in the "Added" bullet stays under that bullet.
- "Breaking:" bold.
Result (2026-10-18) ❌ FAIL — 0/8 case×EP cells pass, in both runs; failures: #1094, #1093, #1101, #1102. Grid: results/2026-10-18-markdown.md.
TC-MD010: Checklist-heavy task plan ⚠️ destructive¶
Prompt Playwright: required
Render
docs/qa/fixtures/md/realistic/r10-task-plan.mdthrough EP-1 to EP-8.
Checks
- Nested task items at level 1 under "Accessibility pass" and "Performance budget met", each with its own ☐/☑.
- Release candidate: numbered task items 1–4 (C3 + C4), with nested task bullets under item 3 and item 4 numbered 4.
- The blockquote with a bold first line and a bullet list inside it: the list stays a list inside the quote (C7).
- 5% → 20% → 50% → 100% bold, arrows intact.
Result (2026-10-18) ❌ FAIL — 0/8 case×EP cells pass, in both runs; failures: #1071, #1056, #1101, #1102. Grid: results/2026-10-18-markdown.md.
TC-MD011: Incident postmortem ⚠️ destructive¶
Prompt Playwright: required
Render
docs/qa/fixtures/md/realistic/r11-incident-postmortem.mdthrough EP-1 to EP-8.
Checks
- The bold-label metadata lines join per C10.
- Timeline table and Action items table intact; pool_size × replicas monospace inside its cell.
- The yaml code block keeps its indentation and comments.
- Lessons: 1–2 numbered; three nested bullets under item 2.
Result (2026-10-18) ❌ FAIL — 0/8 case×EP cells pass, in both runs; failures: #1071, #1093, #1101, #1102. EP-8 rendering changed between runs (Rule 4). Grid: results/2026-10-18-markdown.md.
TC-MD012: Interview guide (numbered in numbered) ⚠️ destructive¶
Prompt Playwright: required
Render
docs/qa/fixtures/md/realistic/r12-interview-guide.mdthrough EP-1 to EP-8.
Checks
- Prompts: 1–3 at level 0 with a.–c. at level 1 under each (3-space indentation), no restart of the level-0 numbers.
- "What good looks like": a bullet with two nested bullets at level 1.
- Scorecard table with empty cells: all 6 rows and 5 columns present.
- "After the interview": numbered 1–3, "one hour" bold.
- résumé renders.
Result (2026-10-18) ❌ FAIL — 0/8 case×EP cells pass, in both runs; failures: #1071, #1093, #1101, #1102. Grid: results/2026-10-18-markdown.md.
TC-MD013: API reference ⚠️ destructive¶
Prompt Playwright: required
Render
docs/qa/fixtures/md/realistic/r13-api-reference.mdthrough EP-1 to EP-8.
Checks
- Paragraphs that are only inline code (`GET /orders`) render as monospace text in a normal paragraph.
- The bash block keeps its backslash line continuation; the json block its indentation.
- Body list: items with two nested bullets at level 1.
- Query-parameter table: the Required column centered.
Result (2026-10-18) ❌ FAIL — 0/8 case×EP cells pass, in both runs; failures: #1095, #1071, #1097, #1098, #1056, #1093, #1101, #1102. EP-8 rendering changed between runs (Rule 4). Grid: results/2026-10-18-markdown.md.
TC-MD014: Study notes ⚠️ destructive¶
Prompt Playwright: required
Render
docs/qa/fixtures/md/realistic/r14-study-notes.mdthrough EP-1 to EP-8.
Checks
- Raft section: numbered 1–3 with nested bullets; the bullet whose text continues on an indented second source line joins into one item.
- Italic variables (f, n) italic; ⌊5/2⌋ renders.
- The table with an empty top-left header cell.
- Questions: numbered 1–3.
Result (2026-10-18) ❌ FAIL — 0/8 case×EP cells pass, in both runs; failures: #1071, #1093, #1101, #1102. Grid: results/2026-10-18-markdown.md.
TC-MD015: Travel itinerary ⚠️ destructive¶
Prompt Playwright: required
Render
docs/qa/fixtures/md/realistic/r15-travel-itinerary.mdthrough EP-1 to EP-8.
Checks - Each day: numbered list with 3-space nested bullets, no restart (Thursday 1–4, Friday 1–2). - Saturday's bullets with a nested level under "Afternoon". - Packing task list, budget table with right-aligned amounts and a bold total row. - Accented Portuguese names render.
Result (2026-10-18) ❌ FAIL — 0/8 case×EP cells pass, in both runs; failures: #1071, #1097, #1095, #1101, #1102. Grid: results/2026-10-18-markdown.md.
TC-MD016: Planning notes (the #1044 report document) ⚠️ destructive¶
Prompt Playwright: required
Render
docs/qa/fixtures/md/realistic/r16-planning-notes.mdthrough EP-1 to EP-8.
Checks
- Agenda: items 1, 2, 3, 4 at level 0 (no restart after the sub-bullets), each with its 2-space sub-bullets nested at level 1 (D1). No literal - text anywhere.
- Prep tasks: ☐/☑ glyphs.
- The un-languaged fenced block shows 1. Q4 results etc. as literal monospace lines, not a list.
- Logistics table intact.
Result (2026-10-18) ❌ FAIL — 0/8 case×EP cells pass, in both runs; failures: #1071, #1093, #1100, #1101, #1102. Grid: results/2026-10-18-markdown.md.
Phase 2 — Syntax coverage¶
Each TC renders one fixture; the cases are the ### sections inside it. "Expected" is what a reader sees, per the conventions above.
TC-MD101: Headings ⚠️ destructive¶
Prompt Playwright: required
Render
docs/qa/fixtures/md/syntax/md-headings.mdthrough EP-1 to EP-8.
| Case | Expected |
|---|---|
| HD-01 | Six headings, Heading 1 to Heading 6, in decreasing size |
| HD-02 | A normal paragraph reading "####### Seven hashes stay a paragraph" |
| HD-03 | Heading 2 "Closed heading" and Heading 3 "Closed with extra hashes"; no trailing # shown |
| HD-04 | A paragraph "#hashtag stays a paragraph" |
| HD-05 | Heading 1 "Setext level one", Heading 2 "Setext level two"; no ===/--- shown |
| HD-06 | One Heading 2 with "bold" bold, "italic" italic, "code" Courier New, "link" linked; the rest plain heading text |
| HD-07 | A paragraph "A paragraph line." then a Heading 2 "Heading right after paragraph" |
| HD-08 | A paragraph "# Not a heading" (the backslash not shown) |
TC-MD102: Emphasis and strikethrough ⚠️ destructive¶
Prompt Playwright: required
Render
docs/qa/fixtures/md/syntax/md-emphasis.mdthrough EP-1 to EP-8.
| Case | Expected |
|---|---|
| EM-01 | Both "italic" words italic |
| EM-02 | Both "bold" words bold |
| EM-03 | All three phrases bold and italic |
| EM-04 | First line bold throughout, "italic inside" also italic; second line italic throughout, "bold inside" also bold |
| EM-05 | "bold" and "italic" styled inside their words; snake_case_name plain with underscores shown |
| EM-06 | "struck through" with a line through it; "bold struck" bold and struck |
| EM-07 | Literal stars shown, nothing italic |
| EM-08 | One paragraph, all bold, the two source lines joined by a space (C10) |
TC-MD103: Inline code ⚠️ destructive¶
Prompt Playwright: required
Render
docs/qa/fixtures/md/syntax/md-inline-code.mdthrough EP-1 to EP-8.
| Case | Expected |
|---|---|
| IC-01 | "make test" Courier New, rest of the sentence in the body font |
| IC-02 | "a b" and "ticks`" in Courier New with the backticks shown |
| IC-03 | "bold code" bold + Courier New; "italic code" italic + Courier New; "code" Courier New immediately followed by bold "bold"; bold "bold" immediately followed by Courier New "code" |
| IC-04 | All three spans literal in Courier New: no bold, no link, no HTML interpretation |
| IC-05 | "start" and "end" Courier New, the middle text plain |
| IC-06 | One paragraph with "only_code_here()" in Courier New (C5; not required to look like a code block) |
TC-MD104: Code blocks ⚠️ destructive¶
Prompt Playwright: required
Render
docs/qa/fixtures/md/syntax/md-code-blocks.mdthrough EP-1 to EP-8.
| Case | Expected |
|---|---|
| CB-01 | One Courier New block, two lines, the 4-space indent of return kept; the language tag not shown |
| CB-02 | One Courier New block, two lines |
| CB-03 | One Courier New block "tilde fenced block" |
| CB-04 | Paragraph, then a Courier New block of two lines (the 4 leading spaces not shown) |
| CB-05 | One Courier New block with one empty line between lines 1 and 3 and two empty lines before line 6 |
| CB-06 | The long line in Courier New, wrapping at the page edge; nothing cut off |
| CB-07 | Four literal lines in Courier New: no heading, list, bold, or table |
| CB-08 | YAML with 0/2/4-space indents kept |
| CB-09 | The inner ``` lines shown literally around "inner fence is literal" |
| CB-10 | Paragraph "A paragraph line.", then the code block (a fence may interrupt a paragraph) |
TC-MD105: List markers and numbering ⚠️ destructive¶
Prompt Playwright: required
Render
docs/qa/fixtures/md/syntax/md-lists-markers.mdthrough EP-1 to EP-8.
| Case | Expected | Structural |
|---|---|---|
| LM-01 | Three separate 2-item bullet lists (a blank line plus a marker change starts a new list) | three listIds |
| LM-02 | 1. 2. 3. | — |
| LM-03 | 1. 2. 3. (an ordered list; no literal 1) text) |
— |
| LM-04 | 3. 4. 5. | — |
| LM-05 | 1. 2. 3. | — |
| LM-06 | 1. to 11., two-digit numbers aligned with the rest | — |
| LM-07 | Two separate one-item bullet lists | two listIds |
| LM-08 | A one-item bullet list, then a one-item numbered list "1." | — |
TC-MD106: Nesting widths × list-type combinations ⚠️ destructive¶
Prompt Playwright: required
Render
docs/qa/fixtures/md/syntax/md-lists-nesting.mdthrough EP-1 to EP-8.
Sixteen cases, LN-01 to LN-16: every combination of indent width (2 spaces, 3 spaces, 4 spaces, tab; D1) and parent/child type (bullet in bullet, bullet in numbered, numbered in bullet, numbered in numbered), each three levels deep, then back to level 1, then back to level 0 twice.
Every case expects the same shape:
| Line | Level | Glyph if the level is bullets | Number if the level is numbered |
|---|---|---|---|
| Top one | 0 | ● | 1. |
| Child one | 1 | ○ | a. |
| Grandchild one | 2 | ■ | i. |
| Grandchild two | 2 | ■ | ii. |
| Child two | 1 | ○ | b. |
| Top two | 0 | ● | 2. |
| Top three | 0 | ● | 3. |
No literal - or 1. text anywhere. Level 0 and level 2 have the parent's type; level 1 the child's.
Structural: nestingLevel 0/1/2 as in the table. Contiguous same-type items share one listId: in the same-type cases (bullet in bullet, numbered in numbered) all seven items do; in the mixed cases the level-1 items are a separate Docs list, so listId can't show continuation there. The numbers on screen (b., 2., 3.) are the verdict for continuation in every case.
TC-MD107: Loose lists and blocks inside list items ⚠️ destructive¶
Prompt Playwright: required
Render
docs/qa/fixtures/md/syntax/md-lists-blocks.mdthrough EP-1 to EP-8.
| Case | Expected |
|---|---|
| LB-01 | Three bullets |
| LB-02 | Three bullets (still a bulleted list; extra spacing between items is fine) |
| LB-03 | Numbered 1. 2. 3. |
| LB-04 | Item 1 with its second paragraph indented under it (C14), then item 2. |
| LB-05 | Item 1, the code block under it (C6 + C14), then item 2. |
| LB-06 | Bullet, the quote under it (C7 + C14), then the next bullet in the same list |
| LB-07 | Item 1, the 3×2 table under it (C13 + C14), then item 2. |
| LB-08 | A bullet whose text is a Heading 1 "Heading inside an item", then a plain bullet, one list |
| LB-09 | Item 1 with two nested bullets (level 1), then item 2. |
TC-MD108: List boundaries ⚠️ destructive¶
Prompt Playwright: required
Render
docs/qa/fixtures/md/syntax/md-lists-boundaries.mdthrough EP-1 to EP-8.
| Case | Expected |
|---|---|
| LX-01 | Paragraph "Things to bring:" then a 2-item bullet list |
| LX-02 | Paragraph "Steps:" then a numbered list 1. 2. |
| LX-03 | Heading 4 then a 2-item bullet list |
| LX-04 | One bullet whose text is "Last item Paragraph after the list without a blank line." (lazy continuation; CommonMark) |
| LX-05 | Two separate bullet lists (two listIds); the comment not shown |
| LX-06 | List 1. 2., the paragraph, then a new list 1. 2. |
| LX-07 | A bullet list, then a separate numbered list starting at 1. |
| LX-08 | 1., the code block under it, then 2. and 3. |
| LX-09 | 1., then an unindented code block, then a new numbered list starting at 2. (the source says 2.) |
TC-MD109: Task lists ⚠️ destructive¶
Prompt Playwright: required
Render
docs/qa/fixtures/md/syntax/md-tasks.mdthrough EP-1 to EP-8.
| Case | Expected |
|---|---|
| TK-01 | ☐ Unchecked task, ☑ Checked task, ☑ Checked with uppercase X |
| TK-02 | ☐ Parent task; level 1 ☑ Child done, ☐ Child open; level 2 ☐ Grandchild open |
| TK-03 | One list: ☐ A task, plain "A plain bullet" (no glyph), ☑ Another task |
| TK-04 | Numbered 1. ☐ First…, 2. ☑ Second…, 3. Plain numbered item |
| TK-05 | ☐ then the task text with bold, code and link styling |
| TK-06 | Two plain bullets with "[link-looking]" and "[]" shown literally |
TC-MD110: Blockquotes ⚠️ destructive¶
Prompt Playwright: required
Render
docs/qa/fixtures/md/syntax/md-blockquotes.mdthrough EP-1 to EP-8.
| Case | Expected |
|---|---|
| BQ-01 | One quoted paragraph (C7, depth 1) |
| BQ-02 | Two quoted paragraphs, both depth 1 |
| BQ-03 | "Outer level." depth 1, "Inner level." depth 2, "Third level." depth 3 |
| BQ-04 | Inside the quote: paragraph, 2-item bullet list, 2-item numbered list 1. 2. |
| BQ-05 | Inside the quote: paragraph and a Courier New code block |
| BQ-06 | Inside the quote: a Heading 2, then a paragraph |
| BQ-07 | One quoted paragraph containing both lines joined by a space |
| BQ-08 | Quoted paragraph with each inline style intact |
| BQ-09 | Two separate quotes |
TC-MD111: Links ⚠️ destructive¶
Prompt Playwright: required
Render
docs/qa/fixtures/md/syntax/md-links.mdthrough EP-1 to EP-8, andmd-links.mdagain through EP-1 to EP-4 withautolink_urls=False.
| Case | Expected | autolink_urls=False |
|---|---|---|
| LK-01 | "the docs" links to /docs |
same |
| LK-02 | "the titled docs" links to /titled; no title text visible |
same |
| LK-03 | Three links, to /ref-a, /collapsed, /shortcut; definition lines not shown |
same |
| LK-04 | "https://example.com/angle" linked; no angle brackets shown | same |
| LK-05 | Both bare URLs linked; the trailing period after /end is not part of the link |
both plain text |
| LK-06 | "www.example.com/www" linked (GFM extended www. autolink) |
plain text |
| LK-07 | Both addresses link to mailto:team@example.com |
first linked, second plain |
| LK-08 | Both bold and linked | same |
| LK-09 | Both spans Courier New, not linked | same |
| LK-10 | Heading 4 with "link" linked | same |
| LK-11 | Links keep the full query string and the closing ) of (disambiguation) |
same |
| LK-12 | "the guide" links to ./guide.md as written (relative) and "an anchor" links to the LK-01 heading or is dropped as text, not left pointing nowhere (docs/design/heading-anchor-resolution.md) |
same |
TC-MD112: Images ⚠️ destructive¶
Prompt Playwright: required
Render the placeholder-substituted copy of
docs/qa/fixtures/md/syntax/md-images.md(see "Running this suite" step 3) through EP-1 to EP-8.
| Case | Expected |
|---|---|
| IM-01 | The image, on its own line (C11) |
| IM-02 | One paragraph: "Text before", the image inline, "text after" |
| IM-03 | The image |
| IM-04 | The 1×1 fixture pixel embedded; the call's images result reports success |
| IM-05 | The fixture pixel, with the path resolved relative to the .md file's own directory (EP-3/EP-4 read a file; a README's relative image is relative to the README). For EP-1/EP-2 (content string, no file) N/A |
| IM-06 | The fixture pixel embedded from Drive |
| IM-07 | The image, linked to /linked-image |
| IM-08 | The image, no visible alt text |
| IM-09 | A bullet with the image inline at the end of its text; a 2×2 table with the image inside the body cell |
TC-MD113: Tables ⚠️ destructive¶
Prompt Playwright: required
Render
docs/qa/fixtures/md/syntax/md-tables.mdthrough EP-1 to EP-8.
| Case | Expected | Structural |
|---|---|---|
| TB-01 | 3×2 table, bold header | — |
| TB-02 | Column 1 left, column 2 centered, column 3 right, in every row including the header | cell paragraph alignment START / CENTER / END |
| TB-03 | Each cell shows its style: bold, italic, struck, Courier New, linked, and the mixed cell with all three | run styles per cell |
| TB-04 | Cells "a | b" in Courier New showing the pipe; "x | y" plain showing the pipe; the table stays 2 columns | 2 columns |
| TB-05 | Empty cells empty; the table stays 3 columns | — |
| TB-06 | 3 columns throughout: the short row padded with empty cells, the long row's 4th cell dropped (GFM) | 3 columns |
| TB-07 | Heading 4, then the table | — |
| TB-08 | The paragraph, then the table (D2) | — |
| TB-09 | 8 columns, all text visible (wrapping in cells is fine) | — |
| TB-10 | 2 columns, header Name/Score, Score right-aligned | — |
| TB-11 | Two separate one-column tables | 2 tables |
| TB-12 | The long text wraps inside its cell | — |
TC-MD114: Breaks and thematic breaks ⚠️ destructive¶
Prompt Playwright: required
Render
docs/qa/fixtures/md/syntax/md-breaks-rules.mdthrough EP-1 to EP-8.
| Case | Expected | Structural |
|---|---|---|
| BR-01 | One paragraph: "This sentence is written across three source lines but is one paragraph." (C10) | 1 paragraph |
| BR-02 | "Line one with two trailing spaces" and "Line two" on consecutive lines of one paragraph, no gap (C9) | 1 paragraph with \v |
| BR-03 | Same as BR-02; no backslash shown | 1 paragraph with \v |
| BR-04 | Paragraph, a horizontal line (C8), paragraph | — |
| BR-05 | Same as BR-04 | — |
| BR-06 | Same as BR-04 | — |
| BR-07 | A Heading 2 "This line becomes a level-two heading"; no line | HEADING_2 |
| BR-08 | Same as BR-04 | — |
| BR-09 | Two paragraphs with normal paragraph spacing, no extra empty paragraphs | 2 paragraphs |
TC-MD115: Escapes and entities ⚠️ destructive¶
Prompt Playwright: required
Render
docs/qa/fixtures/md/syntax/md-escapes.mdthrough EP-1 to EP-8.
| Case | Expected |
|---|---|
| ES-01 | All 32 punctuation characters shown once each, no backslashes, nothing formatted |
| ES-02 | "$12" and "$120" with no backslashes (#213) |
| ES-03 | Literal stars and underscores, nothing italic or bold |
| ES-04 | Three plain paragraphs: "- not a bullet", "1. not a numbered item", "# not a heading" |
| ES-05 | & < > " © — (a non-breaking space) © ☃ |
| ES-06 | The sentence exactly as written, with < > & shown |
| ES-07 | Backslashes kept: C:\Users\name\file.txt and a\b |
TC-MD116: Inline HTML ⚠️ destructive¶
Prompt Playwright: required
Render
docs/qa/fixtures/md/syntax/md-inline-html.mdthrough EP-1 to EP-8.
CommonMark passes raw HTML through, and every entry point turns HTML into a Doc, so the HTML's meaning is the expected rendering. A tag the converter decides not to support becomes a known limitation tied to an open issue; its case stays FAIL.
| Case | Expected |
|---|---|
| HT-01 | bold, bold, italic, italic, underlined, struck, struck; no tags shown |
| HT-02 | "2" subscript; "2" superscript |
| HT-03 | "Line one" and "Line two" on consecutive lines of one paragraph (C9) |
| HT-04 | "HTML link" linked |
| HT-05 | A paragraph with the div's text |
| HT-06 | "Visible beforevisible after."; no comment text |
| HT-07 | "Ctrl" and "C" in a key style or plain (no tags shown); "highlighted" with a highlight |
TC-MD117: Unicode ⚠️ destructive¶
Prompt Playwright: required
Render
docs/qa/fixtures/md/syntax/md-unicode.mdthrough EP-1 to EP-8.
| Case | Expected |
|---|---|
| UN-01 | Emoji render; "🎉 here" bold; the ZWJ sequence 👩💻 shows as one glyph; three bullets |
| UN-02 | Japanese, Chinese and Korean text intact |
| UN-03 | Both lines shown right-to-left, characters intact |
| UN-04 | Both é forms look identical; the stacked accents render |
| UN-05 | The no-break, thin and ideographic spaces kept (no line break inside "100 km") |
| UN-06 | Exactly "bold after three emoji" bold, exactly "code after" Courier New, exactly "link after" linked: no style shifted by a character (UTF-16 offsets, #358) |
| UN-07 | Heading 4 with the globe; flag emoji in the table cells |
Phase 2 — Matrices¶
TC-MD201: Containment matrix ⚠️ destructive¶
Prompt Playwright: required
Render
docs/qa/fixtures/md/syntax/md-containment.mdthrough EP-1 to EP-8.
Every block construct (paragraph, heading, bullet list, numbered list, task list, code block, blockquote, table, image, rule) inside every container that can hold it: a bullet item and a numbered item at levels 0, 1 and 2, a blockquote, and a nested blockquote. Contained content is indented 4 spaces per list level, so a failure here isolates containment from the indent-width cases in TC-MD106. Blank lines appear only where CommonMark needs them (around a contained paragraph, table or image), so most cases are tight lists; TC-MD107 covers loose ones.
A list contained in a list item nests one level deeper than the item and uses that level's glyph (C2/C3); every other contained block follows C14.
Not expressible, so not in the matrix: - Any block inside a table cell: GFM table cells hold inline content only. Inline content and images in cells are covered by TC-MD113 (TB-03) and TC-MD112 (IM-09). - A list item at level 3 or deeper: covered by nesting depth in TC-MD106, not containment.
| Case | Block | Container | Expected |
|---|---|---|---|
| CT-01 | paragraph | bullet item, level 0 | "Container item", then a plain paragraph "Plain paragraph text." indented under it as part of that item, then "Sibling after" as the next bullet at level 0, in the same list |
| CT-02 | heading | bullet item, level 0 | "Container item", then a Heading 4 "Inner heading" indented under it as part of that item, then "Sibling after" as the next bullet at level 0, in the same list |
| CT-03 | bullet list | bullet item, level 0 | "Container item", then a nested bullet list (Bullet A, Bullet B) one level deeper, with that level's glyph indented under it as part of that item, then "Sibling after" as the next bullet at level 0, in the same list |
| CT-04 | numbered list | bullet item, level 0 | "Container item", then a nested numbered list (Number A, Number B) one level deeper, with that level's numbering style (C3) indented under it as part of that item, then "Sibling after" as the next bullet at level 0, in the same list |
| CT-05 | task list | bullet item, level 0 | "Container item", then a nested task list (☐ Task A, ☑ Task B) one level deeper indented under it as part of that item, then "Sibling after" as the next bullet at level 0, in the same list |
| CT-06 | code block | bullet item, level 0 | "Container item", then a monospace code block "code line" indented under it as part of that item, then "Sibling after" as the next bullet at level 0, in the same list |
| CT-07 | blockquote | bullet item, level 0 | "Container item", then a quote (indent + left border) "Quoted line" indented under it as part of that item, then "Sibling after" as the next bullet at level 0, in the same list |
| CT-08 | table | bullet item, level 0 | "Container item", then a 2x2 table (bold header K/V, row k1/v1) indented under it as part of that item, then "Sibling after" as the next bullet at level 0, in the same list |
| CT-09 | image | bullet item, level 0 | "Container item", then the image indented under it as part of that item, then "Sibling after" as the next bullet at level 0, in the same list |
| CT-10 | rule | bullet item, level 0 | "Container item", then a horizontal rule indented under it as part of that item, then "Sibling after" as the next bullet at level 0, in the same list |
| CT-11 | paragraph | bullet item, level 1 | "Container item", then a plain paragraph "Plain paragraph text." indented under it as part of that item, then "Sibling after" back at level 1 and "Top after" at level 0, continuing the outer list |
| CT-12 | heading | bullet item, level 1 | "Container item", then a Heading 4 "Inner heading" indented under it as part of that item, then "Sibling after" back at level 1 and "Top after" at level 0, continuing the outer list |
| CT-13 | bullet list | bullet item, level 1 | "Container item", then a nested bullet list (Bullet A, Bullet B) one level deeper, with that level's glyph indented under it as part of that item, then "Sibling after" back at level 1 and "Top after" at level 0, continuing the outer list |
| CT-14 | numbered list | bullet item, level 1 | "Container item", then a nested numbered list (Number A, Number B) one level deeper, with that level's numbering style (C3) indented under it as part of that item, then "Sibling after" back at level 1 and "Top after" at level 0, continuing the outer list |
| CT-15 | task list | bullet item, level 1 | "Container item", then a nested task list (☐ Task A, ☑ Task B) one level deeper indented under it as part of that item, then "Sibling after" back at level 1 and "Top after" at level 0, continuing the outer list |
| CT-16 | code block | bullet item, level 1 | "Container item", then a monospace code block "code line" indented under it as part of that item, then "Sibling after" back at level 1 and "Top after" at level 0, continuing the outer list |
| CT-17 | blockquote | bullet item, level 1 | "Container item", then a quote (indent + left border) "Quoted line" indented under it as part of that item, then "Sibling after" back at level 1 and "Top after" at level 0, continuing the outer list |
| CT-18 | table | bullet item, level 1 | "Container item", then a 2x2 table (bold header K/V, row k1/v1) indented under it as part of that item, then "Sibling after" back at level 1 and "Top after" at level 0, continuing the outer list |
| CT-19 | image | bullet item, level 1 | "Container item", then the image indented under it as part of that item, then "Sibling after" back at level 1 and "Top after" at level 0, continuing the outer list |
| CT-20 | rule | bullet item, level 1 | "Container item", then a horizontal rule indented under it as part of that item, then "Sibling after" back at level 1 and "Top after" at level 0, continuing the outer list |
| CT-21 | paragraph | bullet item, level 2 | "Container item", then a plain paragraph "Plain paragraph text." indented under it as part of that item, then "Sibling after" at level 2, "Mid after" at level 1, "Top after" at level 0, continuing the outer list |
| CT-22 | heading | bullet item, level 2 | "Container item", then a Heading 4 "Inner heading" indented under it as part of that item, then "Sibling after" at level 2, "Mid after" at level 1, "Top after" at level 0, continuing the outer list |
| CT-23 | bullet list | bullet item, level 2 | "Container item", then a nested bullet list (Bullet A, Bullet B) one level deeper, with that level's glyph indented under it as part of that item, then "Sibling after" at level 2, "Mid after" at level 1, "Top after" at level 0, continuing the outer list |
| CT-24 | numbered list | bullet item, level 2 | "Container item", then a nested numbered list (Number A, Number B) one level deeper, with that level's numbering style (C3) indented under it as part of that item, then "Sibling after" at level 2, "Mid after" at level 1, "Top after" at level 0, continuing the outer list |
| CT-25 | task list | bullet item, level 2 | "Container item", then a nested task list (☐ Task A, ☑ Task B) one level deeper indented under it as part of that item, then "Sibling after" at level 2, "Mid after" at level 1, "Top after" at level 0, continuing the outer list |
| CT-26 | code block | bullet item, level 2 | "Container item", then a monospace code block "code line" indented under it as part of that item, then "Sibling after" at level 2, "Mid after" at level 1, "Top after" at level 0, continuing the outer list |
| CT-27 | blockquote | bullet item, level 2 | "Container item", then a quote (indent + left border) "Quoted line" indented under it as part of that item, then "Sibling after" at level 2, "Mid after" at level 1, "Top after" at level 0, continuing the outer list |
| CT-28 | table | bullet item, level 2 | "Container item", then a 2x2 table (bold header K/V, row k1/v1) indented under it as part of that item, then "Sibling after" at level 2, "Mid after" at level 1, "Top after" at level 0, continuing the outer list |
| CT-29 | image | bullet item, level 2 | "Container item", then the image indented under it as part of that item, then "Sibling after" at level 2, "Mid after" at level 1, "Top after" at level 0, continuing the outer list |
| CT-30 | rule | bullet item, level 2 | "Container item", then a horizontal rule indented under it as part of that item, then "Sibling after" at level 2, "Mid after" at level 1, "Top after" at level 0, continuing the outer list |
| CT-31 | paragraph | numbered item, level 0 | "Container item", then a plain paragraph "Plain paragraph text." indented under it as part of that item, then "Sibling after" numbered 2. (numbering continues) |
| CT-32 | heading | numbered item, level 0 | "Container item", then a Heading 4 "Inner heading" indented under it as part of that item, then "Sibling after" numbered 2. (numbering continues) |
| CT-33 | bullet list | numbered item, level 0 | "Container item", then a nested bullet list (Bullet A, Bullet B) one level deeper, with that level's glyph indented under it as part of that item, then "Sibling after" numbered 2. (numbering continues) |
| CT-34 | numbered list | numbered item, level 0 | "Container item", then a nested numbered list (Number A, Number B) one level deeper, with that level's numbering style (C3) indented under it as part of that item, then "Sibling after" numbered 2. (numbering continues) |
| CT-35 | task list | numbered item, level 0 | "Container item", then a nested task list (☐ Task A, ☑ Task B) one level deeper indented under it as part of that item, then "Sibling after" numbered 2. (numbering continues) |
| CT-36 | code block | numbered item, level 0 | "Container item", then a monospace code block "code line" indented under it as part of that item, then "Sibling after" numbered 2. (numbering continues) |
| CT-37 | blockquote | numbered item, level 0 | "Container item", then a quote (indent + left border) "Quoted line" indented under it as part of that item, then "Sibling after" numbered 2. (numbering continues) |
| CT-38 | table | numbered item, level 0 | "Container item", then a 2x2 table (bold header K/V, row k1/v1) indented under it as part of that item, then "Sibling after" numbered 2. (numbering continues) |
| CT-39 | image | numbered item, level 0 | "Container item", then the image indented under it as part of that item, then "Sibling after" numbered 2. (numbering continues) |
| CT-40 | rule | numbered item, level 0 | "Container item", then a horizontal rule indented under it as part of that item, then "Sibling after" numbered 2. (numbering continues) |
| CT-41 | paragraph | numbered item, level 1 | "Container item", then a plain paragraph "Plain paragraph text." indented under it as part of that item, then "Sibling after" numbered b. at level 1 and "Top after" numbered 2. at level 0 |
| CT-42 | heading | numbered item, level 1 | "Container item", then a Heading 4 "Inner heading" indented under it as part of that item, then "Sibling after" numbered b. at level 1 and "Top after" numbered 2. at level 0 |
| CT-43 | bullet list | numbered item, level 1 | "Container item", then a nested bullet list (Bullet A, Bullet B) one level deeper, with that level's glyph indented under it as part of that item, then "Sibling after" numbered b. at level 1 and "Top after" numbered 2. at level 0 |
| CT-44 | numbered list | numbered item, level 1 | "Container item", then a nested numbered list (Number A, Number B) one level deeper, with that level's numbering style (C3) indented under it as part of that item, then "Sibling after" numbered b. at level 1 and "Top after" numbered 2. at level 0 |
| CT-45 | task list | numbered item, level 1 | "Container item", then a nested task list (☐ Task A, ☑ Task B) one level deeper indented under it as part of that item, then "Sibling after" numbered b. at level 1 and "Top after" numbered 2. at level 0 |
| CT-46 | code block | numbered item, level 1 | "Container item", then a monospace code block "code line" indented under it as part of that item, then "Sibling after" numbered b. at level 1 and "Top after" numbered 2. at level 0 |
| CT-47 | blockquote | numbered item, level 1 | "Container item", then a quote (indent + left border) "Quoted line" indented under it as part of that item, then "Sibling after" numbered b. at level 1 and "Top after" numbered 2. at level 0 |
| CT-48 | table | numbered item, level 1 | "Container item", then a 2x2 table (bold header K/V, row k1/v1) indented under it as part of that item, then "Sibling after" numbered b. at level 1 and "Top after" numbered 2. at level 0 |
| CT-49 | image | numbered item, level 1 | "Container item", then the image indented under it as part of that item, then "Sibling after" numbered b. at level 1 and "Top after" numbered 2. at level 0 |
| CT-50 | rule | numbered item, level 1 | "Container item", then a horizontal rule indented under it as part of that item, then "Sibling after" numbered b. at level 1 and "Top after" numbered 2. at level 0 |
| CT-51 | paragraph | numbered item, level 2 | "Container item", then a plain paragraph "Plain paragraph text." indented under it as part of that item, then "Sibling after" numbered ii. at level 2, "Mid after" b., "Top after" 2. |
| CT-52 | heading | numbered item, level 2 | "Container item", then a Heading 4 "Inner heading" indented under it as part of that item, then "Sibling after" numbered ii. at level 2, "Mid after" b., "Top after" 2. |
| CT-53 | bullet list | numbered item, level 2 | "Container item", then a nested bullet list (Bullet A, Bullet B) one level deeper, with that level's glyph indented under it as part of that item, then "Sibling after" numbered ii. at level 2, "Mid after" b., "Top after" 2. |
| CT-54 | numbered list | numbered item, level 2 | "Container item", then a nested numbered list (Number A, Number B) one level deeper, with that level's numbering style (C3) indented under it as part of that item, then "Sibling after" numbered ii. at level 2, "Mid after" b., "Top after" 2. |
| CT-55 | task list | numbered item, level 2 | "Container item", then a nested task list (☐ Task A, ☑ Task B) one level deeper indented under it as part of that item, then "Sibling after" numbered ii. at level 2, "Mid after" b., "Top after" 2. |
| CT-56 | code block | numbered item, level 2 | "Container item", then a monospace code block "code line" indented under it as part of that item, then "Sibling after" numbered ii. at level 2, "Mid after" b., "Top after" 2. |
| CT-57 | blockquote | numbered item, level 2 | "Container item", then a quote (indent + left border) "Quoted line" indented under it as part of that item, then "Sibling after" numbered ii. at level 2, "Mid after" b., "Top after" 2. |
| CT-58 | table | numbered item, level 2 | "Container item", then a 2x2 table (bold header K/V, row k1/v1) indented under it as part of that item, then "Sibling after" numbered ii. at level 2, "Mid after" b., "Top after" 2. |
| CT-59 | image | numbered item, level 2 | "Container item", then the image indented under it as part of that item, then "Sibling after" numbered ii. at level 2, "Mid after" b., "Top after" 2. |
| CT-60 | rule | numbered item, level 2 | "Container item", then a horizontal rule indented under it as part of that item, then "Sibling after" numbered ii. at level 2, "Mid after" b., "Top after" 2. |
| CT-61 | paragraph | blockquote | the "Container quote line", then a plain paragraph "Plain paragraph text." inside the quote, all inside the quote (depth 1: one step of indent and the left border) |
| CT-62 | heading | blockquote | the "Container quote line", then a Heading 4 "Inner heading" inside the quote, all inside the quote (depth 1: one step of indent and the left border) |
| CT-63 | bullet list | blockquote | the "Container quote line", then a 2-item bullet list at level 0 (● Bullet A, ● Bullet B) inside the quote, all inside the quote (depth 1: one step of indent and the left border) |
| CT-64 | numbered list | blockquote | the "Container quote line", then a 2-item numbered list at level 0 (1. Number A, 2. Number B) inside the quote, all inside the quote (depth 1: one step of indent and the left border) |
| CT-65 | task list | blockquote | the "Container quote line", then a 2-item task list at level 0 (☐ Task A, ☑ Task B) inside the quote, all inside the quote (depth 1: one step of indent and the left border) |
| CT-66 | code block | blockquote | the "Container quote line", then a monospace code block "code line" inside the quote, all inside the quote (depth 1: one step of indent and the left border) |
| CT-67 | blockquote | blockquote | the "Container quote line" at depth 1, then "Quoted line" as its own quote at depth 2 |
| CT-68 | table | blockquote | the "Container quote line", then a 2x2 table (bold header K/V, row k1/v1) inside the quote, all inside the quote (depth 1: one step of indent and the left border) |
| CT-69 | image | blockquote | the "Container quote line", then the image inside the quote, all inside the quote (depth 1: one step of indent and the left border) |
| CT-70 | rule | blockquote | the "Container quote line", then a horizontal rule inside the quote, all inside the quote (depth 1: one step of indent and the left border) |
| CT-71 | paragraph | nested blockquote (depth 2) | the "Container quote line", then a plain paragraph "Plain paragraph text." inside the quote, all inside the inner quote (depth 2: two steps of indent) |
| CT-72 | heading | nested blockquote (depth 2) | the "Container quote line", then a Heading 4 "Inner heading" inside the quote, all inside the inner quote (depth 2: two steps of indent) |
| CT-73 | bullet list | nested blockquote (depth 2) | the "Container quote line", then a 2-item bullet list at level 0 (● Bullet A, ● Bullet B) inside the quote, all inside the inner quote (depth 2: two steps of indent) |
| CT-74 | numbered list | nested blockquote (depth 2) | the "Container quote line", then a 2-item numbered list at level 0 (1. Number A, 2. Number B) inside the quote, all inside the inner quote (depth 2: two steps of indent) |
| CT-75 | task list | nested blockquote (depth 2) | the "Container quote line", then a 2-item task list at level 0 (☐ Task A, ☑ Task B) inside the quote, all inside the inner quote (depth 2: two steps of indent) |
| CT-76 | code block | nested blockquote (depth 2) | the "Container quote line", then a monospace code block "code line" inside the quote, all inside the inner quote (depth 2: two steps of indent) |
| CT-77 | blockquote | nested blockquote (depth 2) | "Outer quote" at depth 1, the "Container quote line" at depth 2, then "Quoted line" at depth 3 |
| CT-78 | table | nested blockquote (depth 2) | the "Container quote line", then a 2x2 table (bold header K/V, row k1/v1) inside the quote, all inside the inner quote (depth 2: two steps of indent) |
| CT-79 | image | nested blockquote (depth 2) | the "Container quote line", then the image inside the quote, all inside the inner quote (depth 2: two steps of indent) |
| CT-80 | rule | nested blockquote (depth 2) | the "Container quote line", then a horizontal rule inside the quote, all inside the inner quote (depth 2: two steps of indent) |
TC-MD202: Adjacency matrix, no blank line ⚠️ destructive¶
Prompt Playwright: required
Render
docs/qa/fixtures/md/syntax/md-adjacency-noblank.mdthrough EP-1 to EP-8.
Every block construct directly followed by every other, with no blank line between. Most bugs live at these boundaries. Several pairs merge under CommonMark/GFM (a paragraph line continues a list item, a quote, or a table); the Expected column says so where it applies.
| Case | A | B | Expected |
|---|---|---|---|
| AJ-001 | paragraph | paragraph | ONE paragraph: "Plain paragraph text." joined to what precedes it by a space |
| AJ-002 | paragraph | heading | a plain paragraph "Plain paragraph text.", then a Heading 4 "Inner heading" |
| AJ-003 | paragraph | bullet list | a plain paragraph "Plain paragraph text.", then a 2-item bullet list (Bullet A, Bullet B) |
| AJ-004 | paragraph | numbered list | a plain paragraph "Plain paragraph text.", then a 2-item numbered list (1. Number A, 2. Number B) (an ordered list starting at 1 may interrupt a paragraph) |
| AJ-005 | paragraph | task list | a plain paragraph "Plain paragraph text.", then a 2-item task list (☐ Task A, ☑ Task B) |
| AJ-006 | paragraph | code block | a plain paragraph "Plain paragraph text.", then a monospace code block "code line" |
| AJ-007 | paragraph | blockquote | a plain paragraph "Plain paragraph text.", then a quote (indent + left border) "Quoted line" |
| AJ-008 | paragraph | table | a plain paragraph "Plain paragraph text.", then a 2x2 table (bold header K/V, row k1/v1) (D2: the table starts its own block) |
| AJ-009 | paragraph | image | ONE paragraph: "Plain paragraph text.", a space, then the image inline |
| AJ-010 | paragraph | rule | a plain paragraph "Plain paragraph text.", then a horizontal rule |
| AJ-011 | heading | paragraph | a Heading 4 "Inner heading", then a plain paragraph "Plain paragraph text." |
| AJ-012 | heading | heading | a Heading 4 "Inner heading", then a Heading 4 "Inner heading" |
| AJ-013 | heading | bullet list | a Heading 4 "Inner heading", then a 2-item bullet list (Bullet A, Bullet B) |
| AJ-014 | heading | numbered list | a Heading 4 "Inner heading", then a 2-item numbered list (1. Number A, 2. Number B) |
| AJ-015 | heading | task list | a Heading 4 "Inner heading", then a 2-item task list (☐ Task A, ☑ Task B) |
| AJ-016 | heading | code block | a Heading 4 "Inner heading", then a monospace code block "code line" |
| AJ-017 | heading | blockquote | a Heading 4 "Inner heading", then a quote (indent + left border) "Quoted line" |
| AJ-018 | heading | table | a Heading 4 "Inner heading", then a 2x2 table (bold header K/V, row k1/v1) |
| AJ-019 | heading | image | a Heading 4 "Inner heading", then an inline image on its own line |
| AJ-020 | heading | rule | a Heading 4 "Inner heading", then a horizontal rule |
| AJ-021 | bullet list | paragraph | a 2-item bullet list (Bullet A, Bullet B), with the next line joined to the last item's text by a space (lazy continuation) |
| AJ-022 | bullet list | heading | a 2-item bullet list (Bullet A, Bullet B), then a Heading 4 "Inner heading" |
| AJ-023 | bullet list | bullet list | ONE list holding all four items, in order |
| AJ-024 | bullet list | numbered list | a 2-item bullet list (Bullet A, Bullet B), then a 2-item numbered list (1. Number A, 2. Number B) |
| AJ-025 | bullet list | task list | ONE list holding all four items, in order |
| AJ-026 | bullet list | code block | a 2-item bullet list (Bullet A, Bullet B), then a monospace code block "code line" |
| AJ-027 | bullet list | blockquote | a 2-item bullet list (Bullet A, Bullet B), then a quote (indent + left border) "Quoted line" |
| AJ-028 | bullet list | table | a 2-item bullet list (Bullet A, Bullet B), then a 2x2 table (bold header K/V, row k1/v1) (D2: the table starts its own block) |
| AJ-029 | bullet list | image | a 2-item bullet list (Bullet A, Bullet B), with the next line joined to the last item's text by a space (lazy continuation) |
| AJ-030 | bullet list | rule | a 2-item bullet list (Bullet A, Bullet B), then a horizontal rule |
| AJ-031 | numbered list | paragraph | a 2-item numbered list (1. Number A, 2. Number B), with the next line joined to the last item's text by a space (lazy continuation) |
| AJ-032 | numbered list | heading | a 2-item numbered list (1. Number A, 2. Number B), then a Heading 4 "Inner heading" |
| AJ-033 | numbered list | bullet list | a 2-item numbered list (1. Number A, 2. Number B), then a 2-item bullet list (Bullet A, Bullet B) |
| AJ-034 | numbered list | numbered list | ONE list holding all four items, in order (1. to 4.) |
| AJ-035 | numbered list | task list | a 2-item numbered list (1. Number A, 2. Number B), then a 2-item task list (☐ Task A, ☑ Task B) |
| AJ-036 | numbered list | code block | a 2-item numbered list (1. Number A, 2. Number B), then a monospace code block "code line" |
| AJ-037 | numbered list | blockquote | a 2-item numbered list (1. Number A, 2. Number B), then a quote (indent + left border) "Quoted line" |
| AJ-038 | numbered list | table | a 2-item numbered list (1. Number A, 2. Number B), then a 2x2 table (bold header K/V, row k1/v1) (D2: the table starts its own block) |
| AJ-039 | numbered list | image | a 2-item numbered list (1. Number A, 2. Number B), with the next line joined to the last item's text by a space (lazy continuation) |
| AJ-040 | numbered list | rule | a 2-item numbered list (1. Number A, 2. Number B), then a horizontal rule |
| AJ-041 | task list | paragraph | a 2-item task list (☐ Task A, ☑ Task B), with the next line joined to the last item's text by a space (lazy continuation) |
| AJ-042 | task list | heading | a 2-item task list (☐ Task A, ☑ Task B), then a Heading 4 "Inner heading" |
| AJ-043 | task list | bullet list | ONE list holding all four items, in order |
| AJ-044 | task list | numbered list | a 2-item task list (☐ Task A, ☑ Task B), then a 2-item numbered list (1. Number A, 2. Number B) |
| AJ-045 | task list | task list | ONE list holding all four items, in order |
| AJ-046 | task list | code block | a 2-item task list (☐ Task A, ☑ Task B), then a monospace code block "code line" |
| AJ-047 | task list | blockquote | a 2-item task list (☐ Task A, ☑ Task B), then a quote (indent + left border) "Quoted line" |
| AJ-048 | task list | table | a 2-item task list (☐ Task A, ☑ Task B), then a 2x2 table (bold header K/V, row k1/v1) (D2: the table starts its own block) |
| AJ-049 | task list | image | a 2-item task list (☐ Task A, ☑ Task B), with the next line joined to the last item's text by a space (lazy continuation) |
| AJ-050 | task list | rule | a 2-item task list (☐ Task A, ☑ Task B), then a horizontal rule |
| AJ-051 | code block | paragraph | a monospace code block "code line", then a plain paragraph "Plain paragraph text." |
| AJ-052 | code block | heading | a monospace code block "code line", then a Heading 4 "Inner heading" |
| AJ-053 | code block | bullet list | a monospace code block "code line", then a 2-item bullet list (Bullet A, Bullet B) |
| AJ-054 | code block | numbered list | a monospace code block "code line", then a 2-item numbered list (1. Number A, 2. Number B) |
| AJ-055 | code block | task list | a monospace code block "code line", then a 2-item task list (☐ Task A, ☑ Task B) |
| AJ-056 | code block | code block | a monospace code block "code line", then a monospace code block "code line" |
| AJ-057 | code block | blockquote | a monospace code block "code line", then a quote (indent + left border) "Quoted line" |
| AJ-058 | code block | table | a monospace code block "code line", then a 2x2 table (bold header K/V, row k1/v1) |
| AJ-059 | code block | image | a monospace code block "code line", then an inline image on its own line |
| AJ-060 | code block | rule | a monospace code block "code line", then a horizontal rule |
| AJ-061 | blockquote | paragraph | ONE quote holding one paragraph: the next line joins the quoted line by a space |
| AJ-062 | blockquote | heading | a quote (indent + left border) "Quoted line", then a Heading 4 "Inner heading" |
| AJ-063 | blockquote | bullet list | a quote (indent + left border) "Quoted line", then a 2-item bullet list (Bullet A, Bullet B) |
| AJ-064 | blockquote | numbered list | a quote (indent + left border) "Quoted line", then a 2-item numbered list (1. Number A, 2. Number B) |
| AJ-065 | blockquote | task list | a quote (indent + left border) "Quoted line", then a 2-item task list (☐ Task A, ☑ Task B) |
| AJ-066 | blockquote | code block | a quote (indent + left border) "Quoted line", then a monospace code block "code line" |
| AJ-067 | blockquote | blockquote | ONE quote holding one paragraph: the next line joins the quoted line by a space |
| AJ-068 | blockquote | table | a quote (indent + left border) "Quoted line", then a 2x2 table (bold header K/V, row k1/v1) (D2: the table starts its own block) |
| AJ-069 | blockquote | image | ONE quote holding one paragraph: the next line joins the quoted line by a space |
| AJ-070 | blockquote | rule | a quote (indent + left border) "Quoted line", then a horizontal rule |
| AJ-071 | table | paragraph | the table with the next line as an extra one-cell body row (GFM: a table ends only at a blank line or another block) |
| AJ-072 | table | heading | a 2x2 table (bold header K/V, row k1/v1), then a Heading 4 "Inner heading" |
| AJ-073 | table | bullet list | a 2x2 table (bold header K/V, row k1/v1), then a 2-item bullet list (Bullet A, Bullet B) |
| AJ-074 | table | numbered list | a 2x2 table (bold header K/V, row k1/v1), then a 2-item numbered list (1. Number A, 2. Number B) |
| AJ-075 | table | task list | a 2x2 table (bold header K/V, row k1/v1), then a 2-item task list (☐ Task A, ☑ Task B) |
| AJ-076 | table | code block | a 2x2 table (bold header K/V, row k1/v1), then a monospace code block "code line" |
| AJ-077 | table | blockquote | a 2x2 table (bold header K/V, row k1/v1), then a quote (indent + left border) "Quoted line" |
| AJ-078 | table | table | ONE table: the second table's three lines become body rows K/V, ---/---, k1/v1 (GFM: a table ends only at a blank line) |
| AJ-079 | table | image | the table with the next line as an extra one-cell body row (GFM: a table ends only at a blank line or another block) |
| AJ-080 | table | rule | a 2x2 table (bold header K/V, row k1/v1), then a horizontal rule |
| AJ-081 | image | paragraph | ONE paragraph: the image, a space, then "Plain paragraph text." |
| AJ-082 | image | heading | an inline image on its own line, then a Heading 4 "Inner heading" |
| AJ-083 | image | bullet list | an inline image on its own line, then a 2-item bullet list (Bullet A, Bullet B) |
| AJ-084 | image | numbered list | an inline image on its own line, then a 2-item numbered list (1. Number A, 2. Number B) (an ordered list starting at 1 may interrupt a paragraph) |
| AJ-085 | image | task list | an inline image on its own line, then a 2-item task list (☐ Task A, ☑ Task B) |
| AJ-086 | image | code block | an inline image on its own line, then a monospace code block "code line" |
| AJ-087 | image | blockquote | an inline image on its own line, then a quote (indent + left border) "Quoted line" |
| AJ-088 | image | table | an inline image on its own line, then a 2x2 table (bold header K/V, row k1/v1) (D2: the table starts its own block) |
| AJ-089 | image | image | ONE paragraph holding both images, separated by a space |
| AJ-090 | image | rule | an inline image on its own line, then a horizontal rule |
| AJ-091 | rule | paragraph | a horizontal rule, then a plain paragraph "Plain paragraph text." |
| AJ-092 | rule | heading | a horizontal rule, then a Heading 4 "Inner heading" |
| AJ-093 | rule | bullet list | a horizontal rule, then a 2-item bullet list (Bullet A, Bullet B) |
| AJ-094 | rule | numbered list | a horizontal rule, then a 2-item numbered list (1. Number A, 2. Number B) |
| AJ-095 | rule | task list | a horizontal rule, then a 2-item task list (☐ Task A, ☑ Task B) |
| AJ-096 | rule | code block | a horizontal rule, then a monospace code block "code line" |
| AJ-097 | rule | blockquote | a horizontal rule, then a quote (indent + left border) "Quoted line" |
| AJ-098 | rule | table | a horizontal rule, then a 2x2 table (bold header K/V, row k1/v1) |
| AJ-099 | rule | image | a horizontal rule, then an inline image on its own line |
| AJ-100 | rule | rule | a horizontal rule, then a horizontal rule |
TC-MD203: Adjacency matrix, blank line ⚠️ destructive¶
Prompt Playwright: required
Render
docs/qa/fixtures/md/syntax/md-adjacency-blank.mdthrough EP-1 to EP-8.
The same 100 pairs separated by one blank line.
| Case | A | B | Expected |
|---|---|---|---|
| AB-001 | paragraph | paragraph | a plain paragraph "Plain paragraph text.", then a plain paragraph "Plain paragraph text.", as separate blocks |
| AB-002 | paragraph | heading | a plain paragraph "Plain paragraph text.", then a Heading 4 "Inner heading", as separate blocks |
| AB-003 | paragraph | bullet list | a plain paragraph "Plain paragraph text.", then a 2-item bullet list (Bullet A, Bullet B), as separate blocks |
| AB-004 | paragraph | numbered list | a plain paragraph "Plain paragraph text.", then a 2-item numbered list (1. Number A, 2. Number B), as separate blocks |
| AB-005 | paragraph | task list | a plain paragraph "Plain paragraph text.", then a 2-item task list (☐ Task A, ☑ Task B), as separate blocks |
| AB-006 | paragraph | code block | a plain paragraph "Plain paragraph text.", then a monospace code block "code line", as separate blocks |
| AB-007 | paragraph | blockquote | a plain paragraph "Plain paragraph text.", then a quote (indent + left border) "Quoted line", as separate blocks |
| AB-008 | paragraph | table | a plain paragraph "Plain paragraph text.", then a 2x2 table (bold header K/V, row k1/v1), as separate blocks |
| AB-009 | paragraph | image | a plain paragraph "Plain paragraph text.", then an inline image on its own line, as separate blocks |
| AB-010 | paragraph | rule | a plain paragraph "Plain paragraph text.", then a horizontal rule, as separate blocks |
| AB-011 | heading | paragraph | a Heading 4 "Inner heading", then a plain paragraph "Plain paragraph text.", as separate blocks |
| AB-012 | heading | heading | a Heading 4 "Inner heading", then a Heading 4 "Inner heading", as separate blocks |
| AB-013 | heading | bullet list | a Heading 4 "Inner heading", then a 2-item bullet list (Bullet A, Bullet B), as separate blocks |
| AB-014 | heading | numbered list | a Heading 4 "Inner heading", then a 2-item numbered list (1. Number A, 2. Number B), as separate blocks |
| AB-015 | heading | task list | a Heading 4 "Inner heading", then a 2-item task list (☐ Task A, ☑ Task B), as separate blocks |
| AB-016 | heading | code block | a Heading 4 "Inner heading", then a monospace code block "code line", as separate blocks |
| AB-017 | heading | blockquote | a Heading 4 "Inner heading", then a quote (indent + left border) "Quoted line", as separate blocks |
| AB-018 | heading | table | a Heading 4 "Inner heading", then a 2x2 table (bold header K/V, row k1/v1), as separate blocks |
| AB-019 | heading | image | a Heading 4 "Inner heading", then an inline image on its own line, as separate blocks |
| AB-020 | heading | rule | a Heading 4 "Inner heading", then a horizontal rule, as separate blocks |
| AB-021 | bullet list | paragraph | a 2-item bullet list (Bullet A, Bullet B), then a plain paragraph "Plain paragraph text.", as separate blocks |
| AB-022 | bullet list | heading | a 2-item bullet list (Bullet A, Bullet B), then a Heading 4 "Inner heading", as separate blocks |
| AB-023 | bullet list | bullet list | ONE loose list holding all four items, in order (a blank line doesn't end a list) |
| AB-024 | bullet list | numbered list | a 2-item bullet list (Bullet A, Bullet B), then a 2-item numbered list (1. Number A, 2. Number B), as separate blocks |
| AB-025 | bullet list | task list | ONE loose list holding all four items, in order (a blank line doesn't end a list) |
| AB-026 | bullet list | code block | a 2-item bullet list (Bullet A, Bullet B), then a monospace code block "code line", as separate blocks |
| AB-027 | bullet list | blockquote | a 2-item bullet list (Bullet A, Bullet B), then a quote (indent + left border) "Quoted line", as separate blocks |
| AB-028 | bullet list | table | a 2-item bullet list (Bullet A, Bullet B), then a 2x2 table (bold header K/V, row k1/v1), as separate blocks |
| AB-029 | bullet list | image | a 2-item bullet list (Bullet A, Bullet B), then an inline image on its own line, as separate blocks |
| AB-030 | bullet list | rule | a 2-item bullet list (Bullet A, Bullet B), then a horizontal rule, as separate blocks |
| AB-031 | numbered list | paragraph | a 2-item numbered list (1. Number A, 2. Number B), then a plain paragraph "Plain paragraph text.", as separate blocks |
| AB-032 | numbered list | heading | a 2-item numbered list (1. Number A, 2. Number B), then a Heading 4 "Inner heading", as separate blocks |
| AB-033 | numbered list | bullet list | a 2-item numbered list (1. Number A, 2. Number B), then a 2-item bullet list (Bullet A, Bullet B), as separate blocks |
| AB-034 | numbered list | numbered list | ONE loose list holding all four items, in order (a blank line doesn't end a list) (1. to 4.) |
| AB-035 | numbered list | task list | a 2-item numbered list (1. Number A, 2. Number B), then a 2-item task list (☐ Task A, ☑ Task B), as separate blocks |
| AB-036 | numbered list | code block | a 2-item numbered list (1. Number A, 2. Number B), then a monospace code block "code line", as separate blocks |
| AB-037 | numbered list | blockquote | a 2-item numbered list (1. Number A, 2. Number B), then a quote (indent + left border) "Quoted line", as separate blocks |
| AB-038 | numbered list | table | a 2-item numbered list (1. Number A, 2. Number B), then a 2x2 table (bold header K/V, row k1/v1), as separate blocks |
| AB-039 | numbered list | image | a 2-item numbered list (1. Number A, 2. Number B), then an inline image on its own line, as separate blocks |
| AB-040 | numbered list | rule | a 2-item numbered list (1. Number A, 2. Number B), then a horizontal rule, as separate blocks |
| AB-041 | task list | paragraph | a 2-item task list (☐ Task A, ☑ Task B), then a plain paragraph "Plain paragraph text.", as separate blocks |
| AB-042 | task list | heading | a 2-item task list (☐ Task A, ☑ Task B), then a Heading 4 "Inner heading", as separate blocks |
| AB-043 | task list | bullet list | ONE loose list holding all four items, in order (a blank line doesn't end a list) |
| AB-044 | task list | numbered list | a 2-item task list (☐ Task A, ☑ Task B), then a 2-item numbered list (1. Number A, 2. Number B), as separate blocks |
| AB-045 | task list | task list | ONE loose list holding all four items, in order (a blank line doesn't end a list) |
| AB-046 | task list | code block | a 2-item task list (☐ Task A, ☑ Task B), then a monospace code block "code line", as separate blocks |
| AB-047 | task list | blockquote | a 2-item task list (☐ Task A, ☑ Task B), then a quote (indent + left border) "Quoted line", as separate blocks |
| AB-048 | task list | table | a 2-item task list (☐ Task A, ☑ Task B), then a 2x2 table (bold header K/V, row k1/v1), as separate blocks |
| AB-049 | task list | image | a 2-item task list (☐ Task A, ☑ Task B), then an inline image on its own line, as separate blocks |
| AB-050 | task list | rule | a 2-item task list (☐ Task A, ☑ Task B), then a horizontal rule, as separate blocks |
| AB-051 | code block | paragraph | a monospace code block "code line", then a plain paragraph "Plain paragraph text.", as separate blocks |
| AB-052 | code block | heading | a monospace code block "code line", then a Heading 4 "Inner heading", as separate blocks |
| AB-053 | code block | bullet list | a monospace code block "code line", then a 2-item bullet list (Bullet A, Bullet B), as separate blocks |
| AB-054 | code block | numbered list | a monospace code block "code line", then a 2-item numbered list (1. Number A, 2. Number B), as separate blocks |
| AB-055 | code block | task list | a monospace code block "code line", then a 2-item task list (☐ Task A, ☑ Task B), as separate blocks |
| AB-056 | code block | code block | a monospace code block "code line", then a monospace code block "code line", as separate blocks |
| AB-057 | code block | blockquote | a monospace code block "code line", then a quote (indent + left border) "Quoted line", as separate blocks |
| AB-058 | code block | table | a monospace code block "code line", then a 2x2 table (bold header K/V, row k1/v1), as separate blocks |
| AB-059 | code block | image | a monospace code block "code line", then an inline image on its own line, as separate blocks |
| AB-060 | code block | rule | a monospace code block "code line", then a horizontal rule, as separate blocks |
| AB-061 | blockquote | paragraph | a quote (indent + left border) "Quoted line", then a plain paragraph "Plain paragraph text.", as separate blocks |
| AB-062 | blockquote | heading | a quote (indent + left border) "Quoted line", then a Heading 4 "Inner heading", as separate blocks |
| AB-063 | blockquote | bullet list | a quote (indent + left border) "Quoted line", then a 2-item bullet list (Bullet A, Bullet B), as separate blocks |
| AB-064 | blockquote | numbered list | a quote (indent + left border) "Quoted line", then a 2-item numbered list (1. Number A, 2. Number B), as separate blocks |
| AB-065 | blockquote | task list | a quote (indent + left border) "Quoted line", then a 2-item task list (☐ Task A, ☑ Task B), as separate blocks |
| AB-066 | blockquote | code block | a quote (indent + left border) "Quoted line", then a monospace code block "code line", as separate blocks |
| AB-067 | blockquote | blockquote | two separate quotes |
| AB-068 | blockquote | table | a quote (indent + left border) "Quoted line", then a 2x2 table (bold header K/V, row k1/v1), as separate blocks |
| AB-069 | blockquote | image | a quote (indent + left border) "Quoted line", then an inline image on its own line, as separate blocks |
| AB-070 | blockquote | rule | a quote (indent + left border) "Quoted line", then a horizontal rule, as separate blocks |
| AB-071 | table | paragraph | a 2x2 table (bold header K/V, row k1/v1), then a plain paragraph "Plain paragraph text.", as separate blocks |
| AB-072 | table | heading | a 2x2 table (bold header K/V, row k1/v1), then a Heading 4 "Inner heading", as separate blocks |
| AB-073 | table | bullet list | a 2x2 table (bold header K/V, row k1/v1), then a 2-item bullet list (Bullet A, Bullet B), as separate blocks |
| AB-074 | table | numbered list | a 2x2 table (bold header K/V, row k1/v1), then a 2-item numbered list (1. Number A, 2. Number B), as separate blocks |
| AB-075 | table | task list | a 2x2 table (bold header K/V, row k1/v1), then a 2-item task list (☐ Task A, ☑ Task B), as separate blocks |
| AB-076 | table | code block | a 2x2 table (bold header K/V, row k1/v1), then a monospace code block "code line", as separate blocks |
| AB-077 | table | blockquote | a 2x2 table (bold header K/V, row k1/v1), then a quote (indent + left border) "Quoted line", as separate blocks |
| AB-078 | table | table | a 2x2 table (bold header K/V, row k1/v1), then a 2x2 table (bold header K/V, row k1/v1), as separate blocks |
| AB-079 | table | image | a 2x2 table (bold header K/V, row k1/v1), then an inline image on its own line, as separate blocks |
| AB-080 | table | rule | a 2x2 table (bold header K/V, row k1/v1), then a horizontal rule, as separate blocks |
| AB-081 | image | paragraph | an inline image on its own line, then a plain paragraph "Plain paragraph text.", as separate blocks |
| AB-082 | image | heading | an inline image on its own line, then a Heading 4 "Inner heading", as separate blocks |
| AB-083 | image | bullet list | an inline image on its own line, then a 2-item bullet list (Bullet A, Bullet B), as separate blocks |
| AB-084 | image | numbered list | an inline image on its own line, then a 2-item numbered list (1. Number A, 2. Number B), as separate blocks |
| AB-085 | image | task list | an inline image on its own line, then a 2-item task list (☐ Task A, ☑ Task B), as separate blocks |
| AB-086 | image | code block | an inline image on its own line, then a monospace code block "code line", as separate blocks |
| AB-087 | image | blockquote | an inline image on its own line, then a quote (indent + left border) "Quoted line", as separate blocks |
| AB-088 | image | table | an inline image on its own line, then a 2x2 table (bold header K/V, row k1/v1), as separate blocks |
| AB-089 | image | image | an inline image on its own line, then an inline image on its own line, as separate blocks |
| AB-090 | image | rule | an inline image on its own line, then a horizontal rule, as separate blocks |
| AB-091 | rule | paragraph | a horizontal rule, then a plain paragraph "Plain paragraph text.", as separate blocks |
| AB-092 | rule | heading | a horizontal rule, then a Heading 4 "Inner heading", as separate blocks |
| AB-093 | rule | bullet list | a horizontal rule, then a 2-item bullet list (Bullet A, Bullet B), as separate blocks |
| AB-094 | rule | numbered list | a horizontal rule, then a 2-item numbered list (1. Number A, 2. Number B), as separate blocks |
| AB-095 | rule | task list | a horizontal rule, then a 2-item task list (☐ Task A, ☑ Task B), as separate blocks |
| AB-096 | rule | code block | a horizontal rule, then a monospace code block "code line", as separate blocks |
| AB-097 | rule | blockquote | a horizontal rule, then a quote (indent + left border) "Quoted line", as separate blocks |
| AB-098 | rule | table | a horizontal rule, then a 2x2 table (bold header K/V, row k1/v1), as separate blocks |
| AB-099 | rule | image | a horizontal rule, then an inline image on its own line, as separate blocks |
| AB-100 | rule | rule | a horizontal rule, then a horizontal rule, as separate blocks |
TC-MD204: Inline formatting matrix ⚠️ destructive¶
Prompt Playwright: required
Render
docs/qa/fixtures/md/syntax/md-inline-matrix.mdthrough EP-1 to EP-8.
IN-01 to IN-20: each inline style (bold, italic, strikethrough, code, link) containing each other one. IN-21 to IN-32: all five styles together inside each block type, including headings, list items at depth 2, table header and body cells, and blockquotes. A link inside a link isn't valid Markdown and is left out; inside code, markers are literal by definition (IN-13 to IN-16 check exactly that).
| Case | Combination | Expected |
|---|---|---|
| IN-01 | italic inside bold | "outer inner outer" all bold; "inner" is also italic; no literal markers |
| IN-02 | strike inside bold | "outer inner outer" all bold; "inner" is also struck through; no literal markers |
| IN-03 | code inside bold | "outer inner outer" all bold; "inner" is also monospace (Courier New); no literal markers |
| IN-04 | link inside bold | "outer inner outer" all bold; "inner" is also a link to https://example.com/inline; no literal markers |
| IN-05 | bold inside italic | "outer inner outer" all italic; "inner" is also bold; no literal markers |
| IN-06 | strike inside italic | "outer inner outer" all italic; "inner" is also struck through; no literal markers |
| IN-07 | code inside italic | "outer inner outer" all italic; "inner" is also monospace (Courier New); no literal markers |
| IN-08 | link inside italic | "outer inner outer" all italic; "inner" is also a link to https://example.com/inline; no literal markers |
| IN-09 | bold inside strike | "outer inner outer" all struck through; "inner" is also bold; no literal markers |
| IN-10 | italic inside strike | "outer inner outer" all struck through; "inner" is also italic; no literal markers |
| IN-11 | code inside strike | "outer inner outer" all struck through; "inner" is also monospace (Courier New); no literal markers |
| IN-12 | link inside strike | "outer inner outer" all struck through; "inner" is also a link to https://example.com/inline; no literal markers |
| IN-13 | bold inside code | the whole span **inner** in code is monospace with the bold markers shown literally (no bold formatting inside code) |
| IN-14 | italic inside code | the whole span *inner* in code is monospace with the italic markers shown literally (no italic formatting inside code) |
| IN-15 | strike inside code | the whole span ~~inner~~ in code is monospace with the strike markers shown literally (no strike formatting inside code) |
| IN-16 | link inside code | the whole span [inner](https://example.com/inline) in code is monospace with the link markers shown literally (no link formatting inside code) |
| IN-17 | bold inside link | "outer inner outer" all a link to https://example.com/inline; "inner" is also bold; no literal markers |
| IN-18 | italic inside link | "outer inner outer" all a link to https://example.com/inline; "inner" is also italic; no literal markers |
| IN-19 | strike inside link | "outer inner outer" all a link to https://example.com/inline; "inner" is also struck through; no literal markers |
| IN-20 | code inside link | "outer inner outer" all a link to https://example.com/inline; "inner" is also monospace (Courier New); no literal markers |
| IN-21 | all five styles in a paragraph | B bold, I italic, S struck through, C monospace, L a link; each style only on its own letter; the paragraph itself renders correctly |
| IN-22 | all five styles in a heading 2 | B bold, I italic, S struck through, C monospace, L a link; each style only on its own letter; the heading 2 itself renders correctly |
| IN-23 | all five styles in a heading 6 | B bold, I italic, S struck through, C monospace, L a link; each style only on its own letter; the heading 6 itself renders correctly |
| IN-24 | all five styles in a bullet item, level 0 | B bold, I italic, S struck through, C monospace, L a link; each style only on its own letter; the bullet item, level 0 itself renders correctly |
| IN-25 | all five styles in a bullet item, level 2 | B bold, I italic, S struck through, C monospace, L a link; each style only on its own letter; the bullet item, level 2 itself renders correctly |
| IN-26 | all five styles in a numbered item, level 0 | B bold, I italic, S struck through, C monospace, L a link; each style only on its own letter; the numbered item, level 0 itself renders correctly |
| IN-27 | all five styles in a numbered item, level 2 | B bold, I italic, S struck through, C monospace, L a link; each style only on its own letter; the numbered item, level 2 itself renders correctly |
| IN-28 | all five styles in a task item | B bold, I italic, S struck through, C monospace, L a link; each style only on its own letter; the task item itself renders correctly |
| IN-29 | all five styles in a table header cell | B bold, I italic, S struck through, C monospace, L a link; every letter is bold (the header row is bold, C13), and each other style is only on its own letter; the table header cell itself renders correctly |
| IN-30 | all five styles in a table body cell | B bold, I italic, S struck through, C monospace, L a link; each style only on its own letter; the table body cell itself renders correctly |
| IN-31 | all five styles in a blockquote | B bold, I italic, S struck through, C monospace, L a link; each style only on its own letter; the blockquote itself renders correctly |
| IN-32 | all five styles in a nested blockquote | B bold, I italic, S struck through, C monospace, L a link; each style only on its own letter; the nested blockquote itself renders correctly |
Document boundaries¶
TC-MD301: Documents that start or end with a non-paragraph block, and degenerate input ⚠️ destructive¶
Prompt Playwright: required
Render each file in
docs/qa/fixtures/md/syntax/docstart/through EP-1 to EP-8. Each file is its own case.
| Case | File | Expected |
|---|---|---|
| DS-01 | ds-01-starts-bullets.md |
The bullet list is the first thing in the Doc; no empty paragraph above it |
| DS-02 | ds-02-starts-numbered.md |
Numbered list first, starting at 1. |
| DS-03 | ds-03-starts-table.md |
The table first (the collapsed blank paragraph before it stays invisible, C15), then the paragraph |
| DS-04 | ds-04-starts-code.md |
The code block first, then the paragraph |
| DS-05 | ds-05-starts-quote.md |
The quote first, then the paragraph |
| DS-06 | ds-06-starts-image.md |
The image first, then the paragraph |
| DS-07 | ds-07-starts-rule.md |
A horizontal line first, then the paragraph |
| DS-08 | ds-08-ends-table.md |
Heading, paragraph, table; no stray visible paragraph after the table beyond Docs' mandatory final one |
| DS-09 | ds-09-ends-list.md |
The list's last item is the last visible line; no empty bulleted line after it |
| DS-10 | ds-10-empty.md |
The call succeeds and leaves an empty Doc (EP-2/EP-4: the Doc's previous content is cleared) |
| DS-11 | ds-11-whitespace-only.md |
Same as DS-10 |
| DS-12 | ds-12-no-trailing-newline.md |
The paragraph, intact |
| DS-13 | ds-13-crlf-line-endings.md |
Same rendering as the LF equivalent: heading, 2-item list, paragraph; no stray characters |
| DS-14 | ds-14-front-matter.md |
D3: the front matter isn't shown; the Doc starts with the Heading 1 "Body heading" |
TC-MD302: Long document ⚠️ destructive¶
Prompt Playwright: required
Render
docs/qa/fixtures/md/syntax/md-long-document.md(~2,000 lines: Phase 1's sixteen documents twice) through EP-1 to EP-8.
Checks - The call completes without a timeout or a partial Doc; on failure, the error names what failed. - Spot-check the second copy of r06 (how-to) and r16 (planning notes) at the end of the Doc: they render exactly like their Phase 1 renders (same numbering, nesting, code blocks). An offset bug that only shows deep into a long Doc shows here. - Every thematic break between documents is a visible line.
TC-MD303: A .md file with a long name through the Drive-import entry points ⚠️ destructive¶
Setup: copy docs/qa/fixtures/md/realistic/r01-meeting-notes.md to a temp directory as a file whose name is 110 ASCII bytes (qa-md303- padded with x, ending .md), and a second copy whose name is 45 CJK characters plus .md (over 130 UTF-8 bytes). Don't commit either name.
Prompt Playwright: required
Render each copy through EP-3, EP-5, EP-6 and EP-7.
Checks
- No error and no failed entry for either file; nothing returns 403 propertyLengthLimitExceeded (#805, #806).
- list_files on the target folder shows exactly one Doc per upload: no orphan left by a failed property write.
- EP-7: a second sync_folder call with the same arguments reports the file skipped (in sync), not a new upload or a conflict.
- Each Doc renders the meeting notes per TC-MD001.
Document state¶
These use our converter's write paths (EP-2 and EP-4); the Drive-import entry points always create a new file and have no "existing Doc" to write into.
TC-MD401: Replacing a Doc that already has content ⚠️ destructive¶
Prompt Playwright: required
Create a Doc with
create_doc(content=<contents of r07-comparison.md>, content_format="markdown"), then replace its content with r06-howto.md through EP-2, and again (a second Doc set up the same way) through EP-4.
Checks - The result is identical on screen to r06's render into a blank Doc (TC-MD006, same EP). - Nothing of r07 remains: no leftover table, list formatting, or styled empty paragraph.
TC-MD402: Writing into a Doc with a theme and non-default named styles ⚠️ destructive¶
Prompt Playwright: required
Create a blank Doc, run
apply_theme(doc_id, theme=<contents of docs/qa/fixtures/md/state/theme.json>), then write r02-project-plan.md through EP-2 and (on a second themed Doc) EP-4.
Checks - Headings take the theme: Heading 1/2 in Montserrat, blue-ish, bold; Heading 3 Montserrat, gray, italic. Body text in Georgia. - Code spans and code blocks are still Courier New, not Georgia. - Lists, tables and numbering render exactly as in TC-MD002.
TC-MD403: update_doc_from_file twice in a row ⚠️ destructive¶
Prompt Playwright: required
On one blank Doc, run
update_doc_from_file(doc_id, local_path=<r10-task-plan.md>)twice in a row.
Checks
- The render after the second call is identical on screen to the render after the first.
- Structural: get_doc_structure returns the same element list both times (same count, types, styles, list nesting); no accumulated empty paragraphs or duplicate lists.
TC-MD404: Determinism across runs ⚠️ destructive¶
Prompt
Not a separate render: this TC records the Run 1 vs. Run 2 comparison from "Running this suite" step 7 for every case in this file.
Checks - Every case's Run 2 screenshot matches Run 1 per entry point. Any difference is a FAIL of the case and of this TC.
Known gaps and not-applicable¶
- Insert Markdown at an index: no tool does this (see "Entry points").
- Nested tables: Markdown can't express a table inside a table cell (
docs/known-limitations.md, "Nested tables not supported via Markdown input"); not a case here. - Comments, headers, footers: not Markdown constructs.