Skip to content

chat 0.0.20 — swap <chat-streaming-md> to @cacheplane/partial-markdown#193

Merged
blove merged 15 commits into
mainfrom
claude/chat-streaming-md-partial-markdown
May 4, 2026
Merged

chat 0.0.20 — swap <chat-streaming-md> to @cacheplane/partial-markdown#193
blove merged 15 commits into
mainfrom
claude/chat-streaming-md-partial-markdown

Conversation

@blove
Copy link
Copy Markdown
Contributor

@blove blove commented May 4, 2026

Summary

Replaces ``'s `marked` + `innerHTML` rendering pipeline with an Angular template walking a `@cacheplane/partial-markdown@0.1.0` AST through the existing `@ngaf/render` view registry.

What's new

  • 18 per-node-type Angular components (one per MarkdownNode type) under `libs/chat/src/lib/markdown/views/`.
  • `cacheplaneMarkdownViews` default `ViewRegistry` mapping each node type to its component. Override via `withViews(cacheplaneMarkdownViews, { heading: MyHeading })`.
  • New optional `[viewRegistry]` input on `` for per-instance overrides.
  • Internal: `` keeps a `createPartialMarkdownParser()` instance across signal changes; pushes deltas (or resets on divergence) and renders the resulting tree.
  • New `MARKDOWN_VIEW_REGISTRY` DI token + `` recursive dispatcher for registry-based child rendering.

Identity preservation

The component returns `materialize(this.parser.root)` — partial-markdown's structural-shared snapshot. Same JS reference for unchanged subtrees (Angular `track`/CD short-circuits), new reference whenever any descendant changed. The DOM-node identity assertions in the identity-preservation spec verify this works: appending a paragraph keeps the prior paragraph's `

` element identity-stable.

Documented regressions

  • Tables regress. Markdown tables render as paragraphs with literal pipe characters in 0.0.20. Restored when partial-markdown v0.3 ships table support.
  • GFM task lists regress. `- [x]` renders as a literal text bullet rather than a checkbox. Restored at the same time.

No other rendered surface changes.

Sanitization

All `href`/`src` flows through Angular's built-in URL sanitization. No `bypassSecurityTrustHtml` calls. No `innerHTML` bindings. Verified by a `javascript:` URL test in the link spec.

Testing

  • 18 per-component unit specs (one per node type)
  • `` registry-dispatch spec (4 tests)
  • `cacheplaneMarkdownViews` registry shape spec (2 tests)
  • Integration corpus for `` (8 canonical samples × 2 push patterns = 16 tests)
  • Identity preservation spec (2 tests, real DOM-node reference equality)

`@ngaf/chat` 0.0.19 → `0.0.20`. `@cacheplane/partial-markdown@0.1.0` added as a runtime dep (chat-internal; not a peer dep). `marked` retained — still used by `messageContent` shared util elsewhere; cleanup is a follow-up.

🤖 Generated with Claude Code

blove and others added 14 commits May 4, 2026 10:38
Used by <chat-streaming-md> for streaming markdown AST. Implementation
detail (not a peer dep) — chat consumers don't need to install it.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…link)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…eading/blockquote/list/list-item/code-block)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replaces the marked + innerHTML rendering pipeline with an Angular
template walking a @cacheplane/partial-markdown AST through @ngaf/render's
view registry. Stable parser identity → Angular track-by-id keeps DOM
stable across pushes. The default cacheplaneMarkdownViews registry
covers all 18 v0.1 node types; consumers override per-type via
withViews().

Tables and task lists regress (not in partial-markdown v0.1) — restored
when partial-markdown v0.3 ships them.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…-string)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The parser's root reference is stable across pushes (partial-markdown's
identity guarantee), so Angular's Object.is signal equality short-circuits
mid-stream content updates. Calling materialize() at the boundary surfaces
a structurally-shared snapshot whose root reference changes when any
descendant changes (via partial-markdown's per-node version fingerprint),
while unchanged subtrees keep their references stable. This is exactly
the property Angular signal CD needs.

The integration test's chunked path now exercises per-chunk detectChanges
(matching production usage), and the identity-preservation spec asserts
real DOM-node reference equality for unchanged subtrees.

Also adds @cacheplane/partial-markdown to allowedNonPeerDependencies in
ng-package.json (was already a runtime dependency but missing from the
ng-packagr allowlist, causing build failures).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown

vercel Bot commented May 4, 2026

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

Project Deployment Actions Updated (UTC)
cacheplane Ready Ready Preview, Comment May 4, 2026 6:21pm

Request Review

…rule

Renames all md-* Angular component selectors to chat-md-* (md-children,
md-document, md-paragraph, md-heading, md-blockquote, md-list, md-list-item,
md-code-block, md-thematic-break, md-text, md-emphasis, md-strong,
md-strikethrough, md-inline-code, md-link, md-autolink, md-image,
md-soft-break, md-hard-break) to satisfy the @angular-eslint/component-selector
rule requiring the 'chat' or 'a2ui' prefix. Updates all template usages and
spec files accordingly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@blove blove merged commit 2e42776 into main May 4, 2026
14 checks passed
@blove blove deleted the claude/chat-streaming-md-partial-markdown branch May 4, 2026 18:27
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