Skip to content

fix(comark): absorb markdown under incomplete HTML openers - #390

Open
farnabaz wants to merge 9 commits into
mainfrom
fix/html-block
Open

fix(comark): absorb markdown under incomplete HTML openers#390
farnabaz wants to merge 9 commits into
mainfrom
fix/html-block

Conversation

@farnabaz

Copy link
Copy Markdown
Collaborator

What

Incomplete block HTML open tags (e.g. streaming <ai-thinking>… with no closer) now wrap following markdown as children with $: { html: 1, block: 0 }, including the single-newline case where CommonMark would otherwise swallow the body into one raw html_block.

Why

During AI/streaming output, custom tags often arrive without a closing tag yet. The previous CommonMark-faithful path left the opener empty and the body as siblings, so renderers could not keep the unfinished element around its content. Blank-line-terminated incomplete openers were fixed first; the blank-line-less case still needed the block rule to stop at the opener line so the token processor can absorb the rest.

Leave single-line incomplete open tags (e.g. `<ai-thinking>\n**bold**`) as
opener-only html_block tokens so the following markdown can be absorbed as
children, matching the blank-line incomplete case.
@vercel

vercel Bot commented Aug 28, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
comark Ready Ready Preview Sep 3, 2026 12:30pm UTC
comark-json-render Ready Ready Preview Sep 3, 2026 12:30pm UTC
comark-nextjs Ready Ready Preview Sep 3, 2026 12:30pm UTC
comark-nuxt Ready Ready Preview Sep 3, 2026 12:30pm UTC
comark-svelte Ready Ready Preview Sep 3, 2026 12:30pm UTC
comark-sveltekit Ready Ready Preview Sep 3, 2026 12:30pm UTC
comark-twoslash Ready Ready Preview Sep 3, 2026 12:30pm UTC
comark-vue Ready Ready Preview Sep 3, 2026 12:30pm UTC

@pkg-pr-new

pkg-pr-new Bot commented Aug 28, 2026

Copy link
Copy Markdown

Open in StackBlitz

comark

npm i https://pkg.pr.new/comark@390

@comark/angular

npm i https://pkg.pr.new/@comark/angular@390

@comark/ansi

npm i https://pkg.pr.new/@comark/ansi@390

@comark/html

npm i https://pkg.pr.new/@comark/html@390

@comark/nuxt

npm i https://pkg.pr.new/@comark/nuxt@390

@comark/react

npm i https://pkg.pr.new/@comark/react@390

@comark/svelte

npm i https://pkg.pr.new/@comark/svelte@390

@comark/vue

npm i https://pkg.pr.new/@comark/vue@390

commit: d36cbfc

@github-actions

github-actions Bot commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

📦 Bundle size snapshot is out of date

The published size of one or more packages changed, so the inline snapshot in
test/bundle.test.ts no longer matches.

Please review the diff below. If the change is expected, accept the new snapshot:

  • 🔄 Update the bundle snapshot — tick this box and CI will run vitest run bundle --update and commit the result to this branch.

Update bundle snapshot

Only maintainers with write access can trigger the update. You can also comment /update-bundle-snapshot, or run it locally with pnpm prepack && pnpm vitest run bundle -u.

Bundle size diff
 FAIL  test/bundle.test.ts > package bundle size > published size of each package
Error: Snapshot `package bundle size > published size of each package 1` mismatched

- Expected
+ Received

@@ -4,7 +4,7 @@
    "@comark/html": "18.9k (58 files)",
    "@comark/nuxt": "11.8k (58 files)",
    "@comark/react": "43.6k (74 files)",
    "@comark/svelte": "43.9k (82 files)",
    "@comark/vue": "60.5k (78 files)",
-   "comark": "440k (156 files)",
+   "comark": "450k (156 files)",
  }

 ❯ test/bundle.test.ts:61:20
     59|     }
     60|
     61|     expect(report).toMatchInlineSnapshot(`
       |                    ^
     62|       {
     63|         "@comark/angular": "60.6k (70 files)",

⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯

Full CI log

A `$` at end of line (or with only trailing whitespace) is not an incomplete
inline-math opener, so auto-close leaves it alone instead of appending `$`.
Incomplete HTML openers with a later matching closer now absorb
intervening
tokens (including nested same-tag blocks) as children, so cases like
details-in-details build a proper tree instead of sibling empties.
Markdown stringify no longer glues `</summary>Nested content`. HTML wrappers
with a lone markdown paragraph among HTML siblings still auto-unwrap that
paragraph; multi-block bodies keep their `<p>` structure.
@coldtea-pr-lens

coldtea-pr-lens Bot commented Sep 3, 2026

Copy link
Copy Markdown

◈ PR Lens

🟢 +0 new · 🟠 ~5 changed · 🔴 -0 removed · 2 flows · 15 files · commit d36cbfc


Architecture

Architecture diagram for comarkdown/comark at d36cbfc

5 components touched across 2 lanes.

Open full size


Inside the changed components — 2 views

Component view — HTML Tokenization & AST Construction

HTML block rule tokenization, recursive token-to-AST nesting for matched and streaming tags, and paragraph auto-unwrapping.

Architecture view of Component view — HTML Tokenization & AST Construction in comarkdown/comark

Component view — HTML AST Serialization

HTML stringifier handler logic managing multiline block tag formatting and separator spacing.

Architecture view of Component view — HTML AST Serialization in comarkdown/comark

Data flow

Data flow diagram for comarkdown/comark at d36cbfc

Parsing nested and streaming HTML blocks · Stringifying HTML AST nodes

Open full size


The other flows — 1 sequence

Stringifying HTML AST nodes

Sequence diagram of Stringifying HTML AST nodes in comarkdown/comark

Drill down
Core Engine — 4 components
🟡 CHANGED Streaming & Auto-Close

Repairs incomplete inline markdown syntax and manages incremental AST node reuse during streaming parses.

🟡 CHANGED HTML Block Tokenizer

Tokenizes HTML blocks, identifying lone opening tags so subsequent markdown lines are not swallowed into raw text blocks.

🟡 CHANGED Token-to-AST Processor

Converts token streams into Comark AST, tracking tag depth to nest body tokens between matching HTML tags or absorb tokens under streaming openers.

🟡 CHANGED Auto-Unwrap Processor

Recursively hoists lone markdown paragraph children out of container elements and HTML wrappers like details blocks.

Stringifier & Renderer — 1 component
🟡 CHANGED AST Stringifier

Serializes AST trees into formatted Markdown and HTML, supporting multi-line incomplete HTML blocks and inter-element spacing.


View

  • Architecture lens
  • Data flow lens
  • Expand every detail
  • Show unchanged neighbours

Tip

PR Lens is free for open source. A star on the repository is what keeps it going.

🪧 More tips
  • Run PR Lens on your own machine: npx skills add coldteadotai/pr-lens installs the agent skill. Then tell your coding agent: "Diagram the change you just made with PR Lens and attach it to the pull request."
  • Draw a diff before it is even a pull request: npx @coldtea/pr-lens-cli analyze --base origin/main reads the diff with your own model key, and npx @coldtea/pr-lens-cli render .pr-lens/graph.json draws the same lenses on your machine.
  • The boxes under View are live. Tick Architecture lens or Data flow lens to choose which diagrams appear, or Expand every detail to open every drill-down at once. The comment redraws in place a few seconds later.
  • Show unchanged neighbours lists the components this change did not touch alongside the ones it did, so the drill-down shows what the changed code sits next to.
  • GitHub will not let you zoom an image in a comment. The link under each diagram opens it full size on a page of its own, where you can.
  • The CLI's render picks up .github/pr-lens.yml automatically and applies your corrections (renames, exclusions, lane pins) at draw time.
  • Would you rather run it from CI on a key of your own? Add .github/workflows/pr-lens.yml with coldteadotai/pr-lens/packages/action@v0 and a model key in your repository secrets, say GEMINI_API_KEY. The Action asks Gemini by default, or OpenAI and any endpoint speaking /chat/completions through its provider input.
  • Push a new commit and the whole comment re-renders for the new head. An older run never overwrites a newer one, so a slow render cannot put a stale diagram back.
  • The diagrams follow your GitHub theme, so dark mode gets the dark render and light mode the light one, and the moving dots show this pull request's data in motion.

◈ Rendered by PR Lens · crafted with ❤️ by the Coldtea team · Something drawn wrong?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant