diff --git a/.changeset/faster-streaming-fences.md b/.changeset/faster-streaming-fences.md deleted file mode 100644 index a970ebb..0000000 --- a/.changeset/faster-streaming-fences.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@tanstack/markdown': patch ---- - -Speed up plain fenced-code rendering with the React streaming extension by retaining completed code text nodes across updates. Reduce parser overhead and shrink every affected public bundle without adding runtime dependencies. - -Add unfinished-fence benchmarks at 4, 16, and 64 KiB, browser comparisons with Streamdown and streaming-markdown, and regression coverage for streamed text, custom code components, and hydration. diff --git a/.changeset/portable-markdown-integrations.md b/.changeset/portable-markdown-integrations.md deleted file mode 100644 index 56fbd3c..0000000 --- a/.changeset/portable-markdown-integrations.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -'@tanstack/markdown': patch ---- - -Forward raw code-fence metadata to `pre[data-meta]` and highlighter options in HTML, React, and Octane. - -Add portable `InlineComponentNode` output for custom inline extensions, using the existing component maps without requiring raw HTML or a bundled math engine. - -Add `urlTransform(url, kind, defaultUrl)` for application-controlled link and image policies. Default URL screening is unchanged; returning `null` removes a link or image while keeping its label content. - -Use single-pass attribute escaping, expand renderer and security regression coverage, and update documentation and shipped skills. The combined renderer increase is 74-78 gzip bytes, with no new runtime dependencies. - -Code fences with metadata now include an additional escaped HTML attribute. Consumers with exhaustive `InlineNode` switches should handle the new `inlineComponent` variant. diff --git a/CHANGELOG.md b/CHANGELOG.md index 1adc7a6..1a93ff9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,22 @@ # @tanstack/markdown +## 0.0.15 + +### Patch Changes + +- f37686a: Speed up plain fenced-code rendering with the React streaming extension by retaining completed code text nodes across updates. Reduce parser overhead and shrink every affected public bundle without adding runtime dependencies. + + Add unfinished-fence benchmarks at 4, 16, and 64 KiB, browser comparisons with Streamdown and streaming-markdown, and regression coverage for streamed text, custom code components, and hydration. +- eb6ef72: Forward raw code-fence metadata to `pre[data-meta]` and highlighter options in HTML, React, and Octane. + + Add portable `InlineComponentNode` output for custom inline extensions, using the existing component maps without requiring raw HTML or a bundled math engine. + + Add `urlTransform(url, kind, defaultUrl)` for application-controlled link and image policies. Default URL screening is unchanged; returning `null` removes a link or image while keeping its label content. + + Use single-pass attribute escaping, expand renderer and security regression coverage, and update documentation and shipped skills. The combined renderer increase is 74-78 gzip bytes, with no new runtime dependencies. + + Code fences with metadata now include an additional escaped HTML attribute. Consumers with exhaustive `InlineNode` switches should handle the new `inlineComponent` variant. + ## 0.0.14 ### Patch Changes diff --git a/package.json b/package.json index 9f45478..ba1f1ea 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/markdown", - "version": "0.0.14", + "version": "0.0.15", "type": "module", "description": "A tiny, fast, deterministic Markdown renderer for blogs and documentation.", "license": "MIT", diff --git a/skills/_artifacts/domain_map.yaml b/skills/_artifacts/domain_map.yaml index 2537f7c..d283924 100644 --- a/skills/_artifacts/domain_map.yaml +++ b/skills/_artifacts/domain_map.yaml @@ -1,13 +1,13 @@ # Generated by skill-domain-discovery # Library: @tanstack/markdown -# Version: 0.0.14 +# Version: 0.0.15 # Date: 2026-07-22 # Status: reviewed status: reviewed library: name: '@tanstack/markdown' - version: '0.0.14' + version: '0.0.15' repository: 'https://github.com/TanStack/markdown' description: 'A synchronous Markdown parser and renderer for controlled blog and documentation content.' primary_framework: 'framework-agnostic' @@ -54,7 +54,7 @@ skills: source: 'docs/core-concepts/syntax-profile.md' priority: 'HIGH' status: 'active' - version_context: 'Intentional product boundary in 0.0.14.' + version_context: 'Intentional product boundary in 0.0.15.' skills: ['render-markdown', 'production-pipelines'] - mistake: 'Reparsing unchanged content on every render' mechanism: 'String inputs are parsed by complete-document renderers, while a cached MarkdownDocument skips repeated parsing.' @@ -68,7 +68,7 @@ skills: source: 'docs/core-concepts/document-model.md' priority: 'MEDIUM' status: 'active' - version_context: 'Current API behavior in 0.0.14.' + version_context: 'Current API behavior in 0.0.15.' skills: ['render-markdown', 'production-pipelines'] - mistake: 'Applying parser options after parsing' mechanism: 'Parse-only options do not retroactively change a pre-parsed AST.' @@ -81,7 +81,7 @@ skills: source: 'docs/reference/html.md' priority: 'HIGH' status: 'active' - version_context: 'Current AST/render split in 0.0.14.' + version_context: 'Current AST/render split in 0.0.15.' - mistake: 'Using parseInline for document definitions' mechanism: 'Standalone inline parsing does not extract document-level reference links or footnote definitions unless parser state is supplied.' wrong_pattern: | @@ -91,7 +91,7 @@ skills: source: 'docs/reference/default-entry.md' priority: 'MEDIUM' status: 'active' - version_context: 'Current parsing contract in 0.0.14.' + version_context: 'Current parsing contract in 0.0.15.' - name: 'Render with React' slug: 'react-rendering' @@ -118,7 +118,7 @@ skills: source: 'docs/guides/react.md' priority: 'HIGH' status: 'active' - version_context: 'React adapter contract in 0.0.14.' + version_context: 'React adapter contract in 0.0.15.' skills: ['react-rendering', 'production-pipelines'] - mistake: 'Mapping AST node names instead of emitted tags' mechanism: 'The components option is keyed by emitted HTML/custom-element tag names such as a or md-tab-panel.' @@ -129,7 +129,7 @@ skills: source: 'docs/guides/react.md' priority: 'HIGH' status: 'active' - version_context: 'Current component map in 0.0.14.' + version_context: 'Current component map in 0.0.15.' - mistake: 'Expecting HTML extension hooks in React output' mechanism: 'MarkdownExtension.renderHtml is HTML-specific; cross-renderer custom output must use ComponentNode and component mappings.' wrong_pattern: | @@ -141,7 +141,7 @@ skills: source: 'docs/guides/extensions.md' priority: 'HIGH' status: 'active' - version_context: 'Renderer-specific extension boundary in 0.0.14.' + version_context: 'Renderer-specific extension boundary in 0.0.15.' skills: ['react-rendering', 'custom-extensions'] - name: 'Render with Octane' @@ -168,7 +168,7 @@ skills: source: 'docs/reference/octane.md' priority: 'HIGH' status: 'active' - version_context: 'Octane adapter contract in 0.0.14.' + version_context: 'Octane adapter contract in 0.0.15.' - mistake: 'Using a React component in the Octane component map' mechanism: 'Octane replacements must be host tag strings or Octane ComponentBody values.' wrong_pattern: | @@ -179,7 +179,7 @@ skills: source: 'docs/guides/octane.md' priority: 'HIGH' status: 'active' - version_context: 'Octane component map in 0.0.14.' + version_context: 'Octane component map in 0.0.15.' - mistake: 'Ignoring Octane static-render return structure' mechanism: 'octane/server static rendering returns an object containing html and css rather than only an HTML string.' wrong_pattern: | @@ -230,7 +230,7 @@ skills: source: 'docs/guides/docs-preset.md' priority: 'HIGH' status: 'active' - version_context: 'Docs preset contract in 0.0.14.' + version_context: 'Docs preset contract in 0.0.15.' - mistake: 'Using unmatched comment component boundaries' mechanism: 'An unmatched block start is consumed as an empty component while its body remains ordinary Markdown.' wrong_pattern: | @@ -245,7 +245,7 @@ skills: source: 'src/extensions/comment-components.ts' priority: 'HIGH' status: 'active' - version_context: 'Current block parser behavior in 0.0.14.' + version_context: 'Current block parser behavior in 0.0.15.' - mistake: 'Feeding a tab transform the wrong content shape' mechanism: 'Each tab variant returns the original node when its expected headings, code files, package lines, or supported bundlers are absent.' wrong_pattern: | @@ -261,7 +261,7 @@ skills: source: 'docs/guides/docs-preset.md' priority: 'MEDIUM' status: 'active' - version_context: 'Current docs transforms in 0.0.14.' + version_context: 'Current docs transforms in 0.0.15.' - mistake: 'Assuming code metadata highlights code by itself' mechanism: 'Fence metadata is parsed into the AST, but tokenization and themes require an external highlighter.' wrong_pattern: | @@ -272,7 +272,7 @@ skills: source: 'docs/core-concepts/syntax-profile.md' priority: 'MEDIUM' status: 'active' - version_context: 'Intentional core/optional boundary in 0.0.14.' + version_context: 'Intentional core/optional boundary in 0.0.15.' skills: ['docs-features', 'production-pipelines'] - name: 'Write Custom Extensions' @@ -304,7 +304,7 @@ skills: source: 'docs/guides/extensions.md' priority: 'HIGH' status: 'active' - version_context: 'Block extension contract in 0.0.14.' + version_context: 'Block extension contract in 0.0.15.' - mistake: 'Ordering a general parser before a specific parser' mechanism: 'Extensions run in array order, so an earlier broad parser can prevent a later parser from seeing its syntax.' wrong_pattern: | @@ -314,7 +314,7 @@ skills: source: 'docs/guides/extensions.md' priority: 'HIGH' status: 'active' - version_context: 'Current ordered extension lifecycle in 0.0.14.' + version_context: 'Current ordered extension lifecycle in 0.0.15.' - mistake: 'Using HTML hooks for cross-framework custom nodes' mechanism: 'renderHtml hooks do not run in React or Octane; ComponentNode plus adapter component maps is the portable path.' wrong_pattern: | @@ -332,7 +332,7 @@ skills: source: 'docs/guides/extensions.md' priority: 'HIGH' status: 'active' - version_context: 'Renderer extension boundary in 0.0.14.' + version_context: 'Renderer extension boundary in 0.0.15.' skills: ['custom-extensions', 'react-rendering', 'octane-rendering'] - mistake: 'Changing the extension set between parse and render' mechanism: 'Document transforms are embedded in the AST, while HTML render hooks still require the active extension at render time.' @@ -345,7 +345,7 @@ skills: source: 'docs/guides/extensions.md' priority: 'MEDIUM' status: 'active' - version_context: 'Current parse/render extension split in 0.0.14.' + version_context: 'Current parse/render extension split in 0.0.15.' - name: 'Ship a Production Content Pipeline' slug: 'production-pipelines' @@ -373,7 +373,7 @@ skills: source: 'docs/core-concepts/security.md' priority: 'CRITICAL' status: 'active' - version_context: 'Security boundary in 0.0.14.' + version_context: 'Security boundary in 0.0.15.' skills: ['production-pipelines', 'react-rendering', 'octane-rendering'] - mistake: 'Returning a complete pre/code tree from a highlighter' mechanism: 'The callback output becomes the trusted contents of the renderer-owned code element.' @@ -386,7 +386,7 @@ skills: source: 'docs/guides/syntax-highlighting.md' priority: 'HIGH' status: 'active' - version_context: 'CodeHighlighter contract in 0.0.14.' + version_context: 'CodeHighlighter contract in 0.0.15.' - mistake: 'Trusting arbitrary highlighter output' mechanism: 'Highlighter output is inserted without escaping in HTML, React, and Octane renderers.' wrong_pattern: | @@ -396,7 +396,7 @@ skills: source: 'docs/core-concepts/security.md' priority: 'CRITICAL' status: 'active' - version_context: 'Trusted callback boundary in 0.0.14.' + version_context: 'Trusted callback boundary in 0.0.15.' - mistake: 'Bundling optional highlighting into the client path' mechanism: 'Language grammars and themes can outweigh Markdown parsing; highlighting should stay build-time or server-side when possible.' wrong_pattern: | @@ -408,7 +408,7 @@ skills: source: 'docs/guides/performance.md' priority: 'MEDIUM' status: 'active' - version_context: 'Intentional dependency boundary in 0.0.14.' + version_context: 'Intentional dependency boundary in 0.0.15.' - mistake: 'Treating safe defaults as a complete sanitizer' mechanism: 'Dangerous protocols and raw HTML are constrained, but application-specific outbound links, images, and final HTML policies remain external.' wrong_pattern: | @@ -419,7 +419,7 @@ skills: source: 'docs/core-concepts/security.md' priority: 'CRITICAL' status: 'active' - version_context: 'Documented security limit in 0.0.14.' + version_context: 'Documented security limit in 0.0.15.' tensions: - name: 'Compatibility breadth versus bundle budget' diff --git a/skills/_artifacts/skill_tree.yaml b/skills/_artifacts/skill_tree.yaml index c0f7d68..b1e34d3 100644 --- a/skills/_artifacts/skill_tree.yaml +++ b/skills/_artifacts/skill_tree.yaml @@ -1,11 +1,11 @@ # Generated by skill-tree-generator # Library: @tanstack/markdown -# Version: 0.0.14 +# Version: 0.0.15 # Date: 2026-07-22 library: name: '@tanstack/markdown' - version: '0.0.14' + version: '0.0.15' repository: 'https://github.com/TanStack/markdown' description: 'A synchronous Markdown parser and renderer for controlled blog and documentation content.' generated_from: diff --git a/skills/custom-extensions/SKILL.md b/skills/custom-extensions/SKILL.md index 4786b4e..55bf89d 100644 --- a/skills/custom-extensions/SKILL.md +++ b/skills/custom-extensions/SKILL.md @@ -7,7 +7,7 @@ description: > metadata: type: core library: '@tanstack/markdown' - library_version: '0.0.14' + library_version: '0.0.15' requires: - 'render-markdown' sources: diff --git a/skills/docs-features/SKILL.md b/skills/docs-features/SKILL.md index 6d8867e..9294743 100644 --- a/skills/docs-features/SKILL.md +++ b/skills/docs-features/SKILL.md @@ -9,7 +9,7 @@ description: > metadata: type: core library: '@tanstack/markdown' - library_version: '0.0.14' + library_version: '0.0.15' requires: - 'render-markdown' sources: diff --git a/skills/octane-rendering/SKILL.md b/skills/octane-rendering/SKILL.md index b374f21..29853cc 100644 --- a/skills/octane-rendering/SKILL.md +++ b/skills/octane-rendering/SKILL.md @@ -9,7 +9,7 @@ metadata: type: framework library: '@tanstack/markdown' framework: 'octane' - library_version: '0.0.14' + library_version: '0.0.15' requires: - 'render-markdown' sources: diff --git a/skills/production-pipelines/SKILL.md b/skills/production-pipelines/SKILL.md index 40f073f..f2a5b5d 100644 --- a/skills/production-pipelines/SKILL.md +++ b/skills/production-pipelines/SKILL.md @@ -8,7 +8,7 @@ description: > metadata: type: lifecycle library: '@tanstack/markdown' - library_version: '0.0.14' + library_version: '0.0.15' requires: - 'render-markdown' sources: @@ -127,7 +127,7 @@ import { parseMarkdown } from '@tanstack/markdown/parser' const cache = new Map() export function renderCachedArticle(key: string, source: string): string { - const cacheKey = `markdown-0.0.14:${key}` + const cacheKey = `markdown-0.0.15:${key}` let document = cache.get(cacheKey) if (!document) { document = parseMarkdown(source, { diff --git a/skills/react-rendering/SKILL.md b/skills/react-rendering/SKILL.md index 265d662..f7a7a31 100644 --- a/skills/react-rendering/SKILL.md +++ b/skills/react-rendering/SKILL.md @@ -9,7 +9,7 @@ metadata: type: framework library: '@tanstack/markdown' framework: 'react' - library_version: '0.0.14' + library_version: '0.0.15' requires: - 'render-markdown' sources: diff --git a/skills/render-markdown/SKILL.md b/skills/render-markdown/SKILL.md index 906c24c..7ba1a27 100644 --- a/skills/render-markdown/SKILL.md +++ b/skills/render-markdown/SKILL.md @@ -9,7 +9,7 @@ description: > metadata: type: core library: '@tanstack/markdown' - library_version: '0.0.14' + library_version: '0.0.15' sources: - 'TanStack/markdown:docs/quick-start.md' - 'TanStack/markdown:docs/core-concepts/document-model.md' diff --git a/skills/render-markdown/references/ast-and-options.md b/skills/render-markdown/references/ast-and-options.md index afdc8ff..60513f7 100644 --- a/skills/render-markdown/references/ast-and-options.md +++ b/skills/render-markdown/references/ast-and-options.md @@ -1,6 +1,6 @@ # AST and Options Reference -This reference targets `@tanstack/markdown@0.0.14`. Shared public types are +This reference targets `@tanstack/markdown@0.0.15`. Shared public types are exported from `@tanstack/markdown`. ## Entry Points