Skip to main content

production-pipelines

Audit and ship a production Markdown pipeline with explicit trust boundaries, external syntax highlighting, parse-ahead caching, compatibility checks, deterministic output, and bundle budgets. Load before deploying blogs, docs, or untrusted-content rendering.

소스 정보

저장소
TanStack/markdown
최근 소스 활동
2026년 10월 1일 02:00
감지된 SKILL.md 언어
영어
스타
432
포크
10

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
production-pipelines
description
Audit and ship a production Markdown pipeline with explicit trust boundaries, external syntax highlighting, parse-ahead caching, compatibility checks, deterministic output, and bundle budgets. Load before deploying blogs, docs, or untrusted-content rendering.
metadata
{"type":"lifecycle","library":"@tanstack/markdown","library_version":"1.0.0"}
requires
["render-markdown"]
sources
["TanStack/markdown:docs/core-concepts/security.md","TanStack/markdown:docs/core-concepts/document-model.md","TanStack/markdown:docs/core-concepts/syntax-profile.md","TanStack/markdown:docs/guides/react.md","TanStack/markdown:docs/guides/syntax-highlighting.md","TanStack/markdown:docs/guides/performance.md","TanStack/markdown:docs/guides/testing.md","TanStack/markdown:docs/comparison.md","TanStack/markdown:src/utils.ts","TanStack/markdown:tests/security.test.tsx","TanStack/markdown:tests/bundle-size.test.ts"]
This skill builds on `render-markdown`. Read it first for the supported syntax, AST, parser options, and renderer contracts. # TanStack Markdown — Production Pipeline Checklist Run every section before deploying a blog, documentation site, or user-content renderer. ## Trust Boundary Checks ### Check: Classify every Markdown source Expected: ```ts import { renderHtml } from '@tanstack/markdown/html' export function renderUntrustedMarkdown( source: string, sanitize: (html: string) => string, ): string { const rendered = renderHtml(source) return sanitize(rendered) } ``` Fail condition: Untrusted input reaches `allowHtml`, an unaudited extension `renderHtml` hook, or an unaudited highlighter. Fix: Separate trusted and untrusted entry points, keep trusted callbacks disabled for untrusted content, and enforce application link, image, and final-HTML policy. ## Highlighting Checks ### Check: Return trusted code contents only Expected: ```ts import { renderHtml } from '@tanstack/markdown/html' import { createHighlighter } from '@tanstack/highlight/core' import { plaintext } from '@tanstack/highlight/languages/plaintext' import { ts } from '@tanstack/highlight/languages/ts' import { createTanStackMarkdownHighlighter } from '@tanstack/highlight/markdown' const highlighter = createHighlighter({ languages: [plaintext, ts] }) export const html = renderHtml('```ts {1}\nconst answer = 42\n```', { highlighter: createTanStackMarkdownHighlighter(highlighter), }) ``` Fail condition: The callback returns a complete `<pre><code>` tree, does not escape source code, or comes from an unreviewed transform. Fix: Return only escaped markup for the renderer-owned `<code>` contents, and run highlighting during ingestion, build, or server rendering. ## Compatibility Checks ### Check: Validate the actual content corpus Expected: ```bash MARKDOWN_CORPUS_DIRS=../site/src/blog:../site/docs pnpm run test:corpus pnpm run corpus:audit:tanstack pnpm run corpus:audit:external ``` Fail condition: Adoption relies only on CommonMark examples or a comparison table instead of the site's Markdown. Fix: Add downstream content directories, preserve practical regressions with focused fixtures, and require renderer and bundle accounting for new syntax. ### Check: Verify deterministic output Expected: ```ts import { renderHtml } from '@tanstack/markdown/html' import { parseMarkdown } from '@tanstack/markdown/parser' const source = '# Deterministic\n\n- one\n- two' const firstDocument = JSON.stringify(parseMarkdown(source)) const secondDocument = JSON.stringify(parseMarkdown(source)) const firstHtml = renderHtml(source) const secondHtml = renderHtml(source) if (firstDocument !== secondDocument || firstHtml !== secondHtml) { throw new Error('Markdown output is nondeterministic') } ``` Fail condition: Identical source and options produce different serialized AST or HTML. Fix: Remove time, randomness, environment state, and unstable ordering from extensions and render callbacks. ## Performance and Cache Checks ### Check: Parse once with final options Expected: ```ts import type { MarkdownDocument } from '@tanstack/markdown' import { renderHtml } from '@tanstack/markdown/html' import { parseMarkdown } from '@tanstack/markdown/parser' const cache = new Map<string, MarkdownDocument>() export function renderCachedArticle(key: string, source: string): string { const cacheKey = `markdown-1.0.0:${key}` let document = cache.get(cacheKey) if (!document) { document = parseMarkdown(source, { frontmatter: true, headingIds: true, }) cache.set(cacheKey, document) } return renderHtml(document) } ``` Fail condition: Stable content is reparsed per request, or parser options/extensions change after the AST is cached. Fix: Build the AST with final parse options, version persisted cache keys, invalidate stored ASTs when node contracts change, and use only narrow entry points. ### Check: Enforce bundle budgets Expected: ```bash pnpm run size pnpm test -- tests/bundle-size.test.ts ``` Fail condition: Any measured entry exceeds its checked gzip budget or starts bundling a highlighter. Fix: Inspect the bundle diff and justify any syntax or dependency cost before adjusting a budget. ## Release Checks ### Check: Run the complete package gate Expected: ```bash pnpm run verify ``` Fail condition: Tests, typechecking, build, docs validation, conformance accounting, sizes, benchmarks, or the npm dry run fail. Fix: Resolve every gate before publishing, including HTML/React/Octane parity; audit raw HTML, highlighter output, HTML hooks, and component replacements separately. ## Common Production Mistakes ### CRITICAL Enabling HTML for untrusted Markdown Wrong: ```ts import { renderHtml } from '@tanstack/markdown/html' export function renderComment(source: string): string { return renderHtml(source, { allowHtml: true }) } ``` Correct: ```ts import { renderHtml } from '@tanstack/markdown/html' export function renderComment(source: string): string { return renderHtml(source) } ``` `allowHtml` emits raw nodes and is not a sanitization step. Source: `docs/core-concepts/security.md` ### HIGH Returning highlighter containers Wrong: ```ts import { renderHtml } from '@tanstack/markdown/html' function escapeCode(code: string): string { return code.replace(/[&<>]/g, (character) => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', })[character] ?? character) } console.log(renderHtml('```ts\nconst x = 1\n```', { highlighter: (code) => `<pre><code>${escapeCode(code)}</code></pre>`, })) ``` Correct: ```ts import { renderHtml } from '@tanstack/markdown/html' function escapeCode(code: string): string { return code.replace(/[&<>]/g, (character) => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', })[character] ?? character) } console.log(renderHtml('```ts\nconst x = 1\n```', { highlighter: (code) => `<span class="token">${escapeCode(code)}</span>`, })) ``` The renderer owns `<pre><code>`; the callback supplies only the code element's trusted contents. Source: `docs/guides/syntax-highlighting.md` ### CRITICAL Trusting arbitrary highlighter output Wrong: ```ts import { renderHtml } from '@tanstack/markdown/html' const source = '```html\n<img src=x onerror=alert(1)>\n```' console.log(renderHtml(source, { highlighter: (code) => code })) ``` Correct: ```ts import { renderHtml } from '@tanstack/markdown/html' function escapeCode(code: string): string { return code.replace(/[&<>]/g, (character) => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', })[character] ?? character) } const source = '```html\n<img src=x onerror=alert(1)>\n```' console.log(renderHtml(source, { highlighter: escapeCode })) ``` Highlighter output is inserted without further escaping in every renderer. Source: `docs/core-concepts/security.md` ### MEDIUM Bundling highlighting into static clients Wrong: ```tsx import { Markdown } from '@tanstack/markdown/react' import { tokenize } from '@tanstack/highlight' export function Article({ source }: { source: string }) { return <Markdown highlighter={(code) => String(tokenize(code))}>{source}</Markdown> } ``` Correct: ```ts import { renderHtml } from '@tanstack/markdown/html' import type { CodeHighlighter } from '@tanstack/markdown' export function renderStaticArticle( source: string, highlighter: CodeHighlighter, ): string { return renderHtml(source, { highlighter }) } ``` Tokenizer runtimes, grammars, and themes can outweigh Markdown parsing and should remain build-time or server-side for static content. Source: `docs/guides/performance.md` ### CRITICAL Treating defaults as a sanitizer Wrong: ```ts import { renderHtml } from '@tanstack/markdown/html' export function renderForEveryPolicy(source: string): string { return renderHtml(source) } ``` Correct: ```ts import { renderHtml } from '@tanstack/markdown/html' export function renderWithPolicy( source: string, sanitize: (html: string) => string, ): string { return sanitize(renderHtml(source)) } ``` Core escaping and protocol filtering do not enforce application-specific outbound-link, image, or final-HTML policy. For parsed Markdown destinations, `urlTransform(url, kind, defaultUrl)` can return the screened default, a trusted replacement, or `null` to remove the link or image while retaining its label content. Only allow data images after application validation of their content, MIME type, and size. Keep the default policy for other destinations. Callback results are not screened again, and the callback does not apply to raw HTML, extension-created URLs, or ASTs supplied directly to renderers. Do not enable raw HTML to allow images. Include URL-policy changes in persisted AST cache invalidation. Source: `docs/core-concepts/security.md` ### HIGH Assuming complete CommonMark behavior Wrong: ```ts import { renderHtml } from '@tanstack/markdown/html' export function renderArbitraryMarkdown(source: string): string { return renderHtml(source) } ``` Correct: ```ts import { renderHtml } from '@tanstack/markdown/html' export function renderControlledDocs(source: string): string { return renderHtml(source) } ``` The package implements a documented docs/blog profile, not complete CommonMark, GFM, MDX, or arbitrary plugin behavior. Source: `docs/core-concepts/syntax-profile.md` ### MEDIUM Reparsing unchanged content Wrong: ```ts import { renderHtml } from '@tanstack/markdown/html' export function renderRequest(source: string): string { return renderHtml(source) } ``` Correct: ```ts import type { MarkdownDocument } from '@tanstack/markdown' import { renderHtml } from '@tanstack/markdown/html' import { parseMarkdown } from '@tanstack/markdown/parser' export function compile(source: string): MarkdownDocument { return parseMarkdown(source) } export function renderRequest(document: MarkdownDocument): string { return renderHtml(document) } ``` String render inputs parse the complete document, while a cached `MarkdownDocument` skips that work. Source: `docs/core-concepts/document-model.md` ### HIGH Injecting HTML into React Wrong: ```tsx import { renderHtml } from '@tanstack/markdown/html' export function Article({ source }: { source: string }) { const html = renderHtml(source) return <article dangerouslySetInnerHTML={{ __html: html }} /> } ``` Correct: ```tsx import { Markdown } from '@tanstack/markdown/react' export function Article({ source }: { source: string }) { return <article><Markdown>{source}</Markdown></article> } ``` The HTML string adds a trusted insertion boundary and bypasses React component replacement. Source: `docs/guides/react.md` ### MEDIUM Expecting fence metadata to highlight Wrong: ```ts import { renderHtml } from '@tanstack/markdown/html' const source = '```ts {1}\nconst answer = 42\n```' console.log(renderHtml(source)) ``` Correct: ```ts import { renderHtml } from '@tanstack/markdown/html' function escapeCode(code: string): string { return code.replace(/[&<>]/g, (character) => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', })[character] ?? character) } const source = '```ts {1}\nconst answer = 42\n```' console.log(renderHtml(source, { highlighter: escapeCode })) ``` Fence metadata enters the AST, but token markup requires an external highlighter. Source: `docs/core-concepts/syntax-profile.md` ## Tensions ### Compatibility breadth versus bundle budget Do not maximize conformance by default. Require target-corpus evidence, renderer coverage, and measured bundle cost before adding syntax. ### Rich trusted output versus untrusted-content safety Do not enable raw HTML, extension HTML, or highlighter markup globally to solve presentation needs. Scope each trusted callback to controlled content. ### Parse-ahead performance versus option timing Build cached ASTs with final parser options and document transforms. Keep required HTML render hooks active when rendering those cached documents. ## Pre-Deploy Summary - [ ] Every content source is classified as trusted or untrusted. - [ ] Raw HTML, extension HTML, and highlighter output have explicit owners. - [ ] Application link, image, and final-sanitization policies are enforced. - [ ] The downstream corpus passes deterministic AST and renderer checks. - [ ] Unsupported syntax is documented rather than silently assumed. - [ ] Stable content is parsed once with final options and versioned cache keys. - [ ] Highlighting runs at build time or on the server where possible. - [ ] Narrow entry points and individual extensions are used. - [ ] Bundle budgets and HTML/React/Octane parity tests pass. - [ ] `pnpm run verify` passes before release. ## Related Skills - `render-markdown` for the supported profile, AST, parser options, and core HTML rendering. - `docs-features` for docs metadata and code-fence behavior. - `custom-extensions` for parser hooks and trusted HTML extension boundaries.
GitHub에서 보기
이 SKILL.md는 매우 커서 SkillsMP가 여기에는 첫 섹션만 미리 보여줍니다. GitHub에서 보기