{"_id":"@architprasar/md4ai","_rev":"4-f92c661e3cedea82cb56004e5d5a569e","name":"@architprasar/md4ai","dist-tags":{"latest":"0.1.2"},"versions":{"0.1.0":{"name":"@architprasar/md4ai","version":"0.1.0","keywords":["markdown","ai","renderer","react","rich-text"],"license":"MIT","_id":"@architprasar/md4ai@0.1.0","maintainers":[{"name":"architprasar","email":"architprasar@gmail.com"}],"homepage":"https://github.com/architprasar/md4ai#readme","bugs":{"url":"https://github.com/architprasar/md4ai/issues"},"dist":{"shasum":"d93dca3a46ece80343c7fbb2c3e45099828803ca","tarball":"https://registry.npmjs.org/@architprasar/md4ai/-/md4ai-0.1.0.tgz","fileCount":58,"integrity":"sha512-bK6p8gsRt9rDtwJwvr3GyIHYLlVxTti5si+ZMC2At+e2FGKxnwQfiSuHDkFx3cg4JvVd6pszZZMuKd097Ua+GA==","signatures":[{"sig":"MEQCICLeyzCEJ6mTYvJP20k7Y8CRxE8OgINlfrZunGWgOnt/AiBjOPQq7w4rsuoe9+yjmrq8V2ZpiIW8cE0dp5Px+gJjZw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1008879},"main":"./dist/md4ai.umd.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/md4ai.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/md4ai.js","require":"./dist/md4ai.umd.cjs"},"./core":{"types":"./dist/core.d.ts","import":"./dist/core.js"},"./react":{"types":"./dist/react.d.ts","import":"./dist/react.js"}},"gitHead":"bf5badd2d173f1c5566efb8a352e194726245ec9","scripts":{"dev":"cd examples/demo && npm run dev","test":"tsc -p tsconfig.test.json && node --test test/*.test.mjs","build":"vite build && tsc -p tsconfig.runtime.json && tsc --emitDeclarationOnly --declarationDir dist","typecheck":"tsc --noEmit","build:demo":"npm --prefix examples/demo run build"},"_npmUser":{"name":"architprasar","email":"architprasar@gmail.com"},"repository":{"url":"git+https://github.com/architprasar/md4ai.git","type":"git"},"_npmVersion":"10.8.2","description":"AI-friendly rich markdown renderer — extended markdown syntax that renders to interactive UI","directories":{},"_nodeVersion":"20.19.2","dependencies":{"unified":"^11.0.5","remark-gfm":"^4.0.1","remark-parse":"^11.0.0","remark-rehype":"^11.1.1","remark-directive":"^3.0.1","unist-util-visit":"^5.0.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^6.3.4","chart.js":"^4.4.9","typescript":"^5.8.3","@types/react":"^18.3.23","vite-plugin-dts":"^4.5.4","@types/react-dom":"^18.3.7"},"peerDependencies":{"react":">=18","chart.js":">=4","react-dom":">=18"},"peerDependenciesMeta":{"chart.js":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/md4ai_0.1.0_1777073602680_0.8735869832161804","host":"s3://npm-registry-packages-npm-production"},"deprecated":"Package no longer supported. Contact Support at https://www.npmjs.com/support for more info."},"0.1.1":{"name":"@architprasar/md4ai","version":"0.1.1","keywords":["markdown","ai","renderer","react","rich-text"],"license":"MIT","_id":"@architprasar/md4ai@0.1.1","maintainers":[{"name":"architprasar","email":"architprasar@gmail.com"}],"homepage":"https://github.com/architprasar/md4ai#readme","bugs":{"url":"https://github.com/architprasar/md4ai/issues"},"bin":{"md4ai-mcp":"mcp-server.mjs"},"dist":{"shasum":"b90c7040d09d8c045c9b9112c458e91346b910e8","tarball":"https://registry.npmjs.org/@architprasar/md4ai/-/md4ai-0.1.1.tgz","fileCount":67,"integrity":"sha512-28mm9mYG2W/zTVITDCVRWSgvAR/d87JtaKOfLYkXYebCZjhovnolpIpuONhF/BA1mnAMSv2P44FbIwG+c6EOXw==","signatures":[{"sig":"MEUCIQDWUTjNcuSGaGE/vbobtZHuppTCEgYs71FQYalNbLHCrQIgG3U+HaFptQSKbEFBx/X8JToq1mXYBASq8MdS5C+poSI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1077570},"main":"./dist/md4ai.umd.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/md4ai.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/md4ai.js","require":"./dist/md4ai.umd.cjs"},"./core":{"types":"./dist/core.d.ts","import":"./dist/core.js"},"./react":{"types":"./dist/react.d.ts","import":"./dist/react.js"}},"gitHead":"646bc921f77daebdc570b06c317d534c193b298d","scripts":{"dev":"cd examples/demo && npm run dev","test":"tsc -p tsconfig.test.json && node --test test/*.test.mjs","build":"vite build && tsc -p tsconfig.runtime.json && tsc --emitDeclarationOnly --declarationDir dist","check":"node scripts/check.mjs","typecheck":"tsc --noEmit","build:demo":"npm --prefix examples/demo run build"},"_npmUser":{"name":"architprasar","email":"architprasar@gmail.com"},"repository":{"url":"git+https://github.com/architprasar/md4ai.git","type":"git"},"_npmVersion":"10.8.2","description":"AI-friendly rich markdown renderer — extended markdown syntax that renders to interactive UI","directories":{},"_nodeVersion":"20.19.2","dependencies":{"unified":"^11.0.5","remark-gfm":"^4.0.1","remark-parse":"^11.0.0","remark-rehype":"^11.1.1","remark-directive":"^3.0.1","unist-util-visit":"^5.0.0","@modelcontextprotocol/sdk":"^1.29.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^6.3.4","chart.js":"^4.4.9","typescript":"^5.8.3","js-tiktoken":"^1.0.21","@types/react":"^18.3.23","vite-plugin-dts":"^4.5.4","@types/react-dom":"^18.3.7"},"peerDependencies":{"react":">=18","chart.js":">=4","react-dom":">=18"},"peerDependenciesMeta":{"chart.js":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/md4ai_0.1.1_1777163565772_0.6725750125246572","host":"s3://npm-registry-packages-npm-production"},"deprecated":"Package no longer supported. Contact Support at https://www.npmjs.com/support for more info."},"0.1.2":{"name":"@architprasar/md4ai","version":"0.1.2","keywords":["markdown","ai","renderer","react","rich-text"],"license":"MIT","_id":"@architprasar/md4ai@0.1.2","maintainers":[{"name":"architprasar","email":"architprasar@gmail.com"}],"homepage":"https://github.com/architprasar/md4ai#readme","bugs":{"url":"https://github.com/architprasar/md4ai/issues"},"bin":{"md4ai-mcp":"mcp-server.mjs"},"dist":{"shasum":"893949d571dd15d269b3ef77ad2d40b98455854e","tarball":"https://registry.npmjs.org/@architprasar/md4ai/-/md4ai-0.1.2.tgz","fileCount":61,"integrity":"sha512-OeP9zwntUuXP7GctjfmHfIwtCafNVEFE3k4PQ1ym+E2pYfnF8y3jX3+Q77nD5CLz11kRKSjnRgaNqRYxET2Clg==","signatures":[{"sig":"MEUCIQCQAQlEe9cNgPaABrFkBAD4LSLv96Vzzyr5bwJeDGhbzgIgXl8WCG4DaeHwK+5oyJ6+nes/tKHbjF/LecxIIPu2qF8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":752366},"main":"./dist/md4ai.umd.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/md4ai.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/md4ai.js","require":"./dist/md4ai.umd.cjs"},"./core":{"types":"./dist/core.d.ts","import":"./dist/core.js"},"./react":{"types":"./dist/react.d.ts","import":"./dist/react.js"}},"gitHead":"ca583dafb1da60d5a5a38837f45ad955b77d9918","scripts":{"dev":"cd examples/demo && npm run dev","test":"tsc -p tsconfig.test.json && node --test test/*.test.mjs","build":"vite build && tsc -p tsconfig.runtime.json && tsc --emitDeclarationOnly --declarationDir dist","check":"node scripts/check.mjs","typecheck":"tsc --noEmit","build:demo":"npm --prefix examples/demo run build"},"_npmUser":{"name":"architprasar","email":"architprasar@gmail.com"},"repository":{"url":"git+https://github.com/architprasar/md4ai.git","type":"git"},"_npmVersion":"10.8.2","description":"AI-friendly rich markdown renderer — extended markdown syntax that renders to interactive UI","directories":{},"_nodeVersion":"20.19.2","dependencies":{"@modelcontextprotocol/sdk":"^1.29.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^6.3.4","chart.js":"^4.4.9","typescript":"^5.8.3","js-tiktoken":"^1.0.21","@types/react":"^18.3.23","vite-plugin-dts":"^4.5.4","@types/react-dom":"^18.3.7"},"peerDependencies":{"react":">=18","chart.js":">=4","react-dom":">=18"},"peerDependenciesMeta":{"chart.js":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/md4ai_0.1.2_1777271189153_0.7680100485170465","host":"s3://npm-registry-packages-npm-production"},"deprecated":"Package no longer supported. Contact Support at https://www.npmjs.com/support for more info."}},"time":{"created":"2026-04-24T23:33:22.617Z","modified":"2026-04-28T11:50:37.986Z","0.1.0":"2026-04-24T23:33:22.830Z","0.1.1":"2026-04-26T00:32:45.967Z","0.1.2":"2026-04-27T06:26:29.381Z"},"bugs":{"url":"https://github.com/architprasar/md4ai/issues"},"license":"MIT","homepage":"https://github.com/architprasar/md4ai#readme","keywords":["markdown","ai","renderer","react","rich-text"],"repository":{"url":"git+https://github.com/architprasar/md4ai.git","type":"git"},"description":"AI-friendly rich markdown renderer — extended markdown syntax that renders to interactive UI","maintainers":[{"name":"architprasar","email":"architprasar@gmail.com"}],"readme":"# md4ai\n\n**Rich markdown for AI.** Drop md4ai into your AI chat UI and responses automatically render as charts, callouts, cards, KPI metrics, timelines, and more — no prompt engineering, no JSON, just markdown.\n\n```\nnpm install @architprasar/md4ai\n```\n\n> **Peer deps:** `react >=18`, `react-dom >=18`  \n> **Optional:** `chart.js >=4` — only needed if you use chart fences\n\n---\n\n## The problem\n\nAI models output markdown natively. But standard markdown renderers give you headings and bullet points. Your users get a wall of text when the AI could be showing them a bar chart, a KPI card, a status timeline.\n\nThe usual fix is prompt engineering — coerce the AI into outputting JSON, parse it, render it. It breaks constantly. The AI forgets the schema, nests things wrong, adds a sentence before the JSON block.\n\nmd4ai takes a different approach: **extend markdown itself.** The AI writes markdown. md4ai renders it as rich UI. No JSON. No custom formats. No prompt gymnastics.\n\nAnother practical advantage: this often saves tokens compared to custom JSON UI schemas. Markdown plus compact directives like `@kpi[Revenue; $167k; +18%; QoQ]` is usually smaller than nested `type/props/content` JSON, and it also reduces repair-cost tokens from malformed structured output.\n\n## Bridge System (AI-Native Components)\n\nInstead of complex JSON schemas, `md4ai` uses a **dType Schema API** to define component interfaces. \n\n- **Automatic Casting**: Converts raw strings to `number`, `boolean`, `Array`, or `Record`.\n- **Hybrid Syntax**: AI can use positional arguments, named keys, or a mix of both.\n- **Recursive Parsing**: Lists and Key-Values recursively parse their children.\n- **Smart Delimiters**: Lists automatically detect the best separator (`|` or `,`).\n\n### Example: Defining a Bridge\n\n```tsx\nimport { defineBridge, B } from '@architprasar/md4ai/core';\n\nconst kpiBridge = defineBridge({\n  marker: 'kpi',\n  fields: [\n    B.string('label').describe('The metric name'),\n    B.string('value').describe('Current value'),\n    B.number('change').optional(),\n  ],\n  render: ({ label, value, change }) => (\n    <div className=\"kpi-card\">\n      <h4>{label}</h4>\n      <strong>{value}</strong>\n      {change && <span>{change > 0 ? '+' : ''}{change}%</span>}\n    </div>\n  )\n});\n```\n\n### AI Output Examples\n\nThe model can emit any of these; the parser handles them all:\n\n- **Positional**: `@kpi[Revenue; $1.2M; +14%; QoQ]`\n- **Named**: `@kpi[label=Revenue; value=$1.2M; change=+14%; period=QoQ]`\n- **Mixed**: `@kpi[Revenue; $1.2M; change=+14%]`\n- **Inner lists**: `@sparkline[10,20,15,30,25]`\n\n## Two-Tier Prompting\n\nKeep your system prompts small by separating the universal protocol from the component manifest.\n\n```ts\nimport { getBridgeProtocolPrompt, getPrompt } from '@architprasar/md4ai/core';\n\n// 1. The universal bridge syntax rules\nconst protocol = getBridgeProtocolPrompt();\n\n// 2. The manifest of markers and fields (Catalog)\nconst catalog = getPrompt({ bridges, mode: 'minimal' });\n```\n\n---\n\n## Quickstart\n\n```tsx\nimport { parse } from '@architprasar/md4ai/core';\nimport { renderContent } from '@architprasar/md4ai/react';\n\nfunction AIMessage({ content }: { content: string }) {\n  return renderContent(parse(content));\n}\n```\n\nFor streaming responses — call on the full accumulated text every chunk:\n\n```tsx\nimport { parseStreaming } from '@architprasar/md4ai/core';\nimport { renderContent } from '@architprasar/md4ai/react';\n\nfunction StreamingMessage({ text }: { text: string }) {\n  // Safe mid-stream — unclosed fences render as placeholders, never throw\n  return renderContent(parseStreaming(text));\n}\n```\n\nIf you want a clearer package boundary, use subpath imports:\n\n```tsx\nimport { parse, parseStreaming, defineBridge } from '@architprasar/md4ai/core';\nimport { renderContent, themes } from '@architprasar/md4ai/react';\n```\n\n`md4ai` still re-exports the full API for backwards compatibility, but `@architprasar/md4ai/core` and `@architprasar/md4ai/react` make the parser/renderer split explicit.\n\n---\n\n## Documentation\nDetailed documentation and interactive playground are available at [architprasar.github.io/md4ai](https://architprasar.github.io/md4ai).\n\n## Agent Support (MCP & llms.txt)\nmd4ai is designed for AI native workflows.\n- **MCP Server**: Connect your agent with `npx @architprasar/md4ai-mcp`.\n- **llms.txt**: Agents can find a concise map at [https://architprasar.github.io/md4ai/llms.txt](https://architprasar.github.io/md4ai/llms.txt) or full context at [https://architprasar.github.io/md4ai/llms-full.txt](https://architprasar.github.io/md4ai/llms-full.txt).\n\n## Repository layout\n\n- `src/` — parser, IR, themes, bridges, and React renderer\n- `examples/demo/` — playground, docs page, and GitHub Pages demo\n- `test/` — parser and streaming regression tests\n- `docs/` — contributor-facing architecture notes\n\n---\n\n## Development\n\n```bash\nnpm ci\nnpm --prefix examples/demo ci\nnpm run typecheck\nnpm test\nnpm run dev\n```\n\n- `npm run typecheck` validates the library source with TypeScript\n- `npm test` rebuilds the package and runs the Node-based regression suite\n- `npm run dev` starts the example app for manual QA\n- `npm run build:demo` builds the Pages-ready demo bundle\n\nContributor workflow and review expectations live in [`CONTRIBUTING.md`](./CONTRIBUTING.md). A short system view of the parser and renderer pipeline lives in [`docs/architecture.md`](./docs/architecture.md). Production integration guidance for streaming, theming, bridges, and component overrides lives in [`docs/production.md`](./docs/production.md).\n\n---\n\n## Extended syntax\n\nAll standard markdown works exactly as expected. md4ai adds these on top — every extension is valid plain text if md4ai isn't present.\n\n### Callouts\n\nGitHub-style alerts — the AI already knows this syntax from its training data.\n\n```markdown\n> [!NOTE]\n> East region leads with $167k, up 18% QoQ.\n\n> [!TIP]\n> APAC shows the strongest growth trajectory. Invest now.\n\n> [!WARNING]\n> South region is down 7%. Churn is accelerating.\n\n> [!DANGER]\n> Pipeline coverage for Q2 is critically thin.\n```\n\nVariants: `NOTE` `INFO` `TIP` `WARNING` `DANGER`\n\n---\n\n### Charts\n\nFenced code block with `chart` lang. Uses Chart.js under the hood — install it separately.\n\n````markdown\n```chart\n{\n  \"type\": \"bar\",\n  \"labels\": [\"North\", \"South\", \"East\", \"West\", \"APAC\"],\n  \"datasets\": [\n    { \"label\": \"Q1 Revenue ($k)\", \"data\": [142, 98, 167, 121, 89] },\n    { \"label\": \"Q4 Revenue ($k)\", \"data\": [128, 105, 141, 110, 74] }\n  ]\n}\n```\n````\n\nSupported types: `bar` `line` `pie` `doughnut` `radar`\n\nDuring streaming, an animated skeleton placeholder renders until the JSON is complete — no raw JSON flash.\n\n---\n\n### Steps and timelines\n\nUse a fenced workflow block for AI-generated plans, checklists, and project updates. Both `steps` and `timeline` render the same first-class component.\n\n````markdown\n```steps\n- [done] Gather requirements\n  Confirm success criteria and edge cases\n- [active] Build parser support\n  Accept partial syntax during streaming\n- [planned] Add docs and demo examples\n```\n````\n\nAccepted formats are intentionally forgiving: `[done] Title`, `Title [done]`, `done: Title`, `Title: planned`, and `Title | active | extra detail` all work. Lines without a recognized status fall back to `planned`.\n\n---\n\n### KPI metrics\n\n```markdown\n@kpi[Revenue; $167k; +18%; QoQ]\n@kpi[Net Retention; 108%; +4 pts; YoY]\n@kpi[South Region; $98k; -7%; QoQ]\n```\n\n`label` and `value` are the core fields. `change` and `period` are optional.\n\n---\n\n### Cards\n\n```markdown\n@card[Immediate action]\nSchedule a call with South region AEs. Pull exit survey data first.\n```\n\n---\n\n### Multi-column layout\n\n````markdown\n```layout columns=2\n### What's Working\n- Enterprise motion in East is repeatable\n- APAC partner channel gaining traction\n\n---\n\n### What Needs Attention\n- South SMB retention — churn is accelerating\n- West pipeline coverage is thin\n```\n````\n\n---\n\n### Buttons\n\n```markdown\n@button[Export Report; #; primary]\n@button[Build Forecast; #; secondary]\n```\n\nVariants: `primary` `secondary` `default`\n\n---\n\n### Inputs\n\n```markdown\n@input[Follow-up; text; Ask a follow-up...]\n```\n\n---\n\n### Video embeds\n\n````markdown\n```video\nhttps://www.youtube.com/watch?v=dQw4w9WgXcQ\n```\n````\n\nYouTube and Vimeo URLs become responsive iframes. Any other URL renders as a native `<video>` element.\n\n---\n\n### Task lists\n\nStandard GFM syntax — rendered with visual checkboxes.\n\n```markdown\n- [x] Pull Q1 revenue data from CRM\n- [x] Identify top churned accounts\n- [ ] Schedule South region review call\n- [ ] Draft Q2 forecast model\n```\n\n---\n\n### Inline bridges\n\nmd4ai ships 16 ready-made bridge markers for AI product surfaces. Use any of them by adding the corresponding bridge definition to your `BRIDGES` array. See [`docs/bridges.md`](./docs/bridges.md) for the full field reference.\n\n**General purpose**\n\n```markdown\n@kpi[Revenue; $167k; +18%; QoQ]\n\n@sparkline[38,41,45,49,58,62,71]\n\n@release[zod v3.22; beta; Pinned at rc.2; Platform]\n\n@gauge[Checkout Processor; 61; max=100; unit=%; warn=75; crit=65]\n\n@signal[SQL injection; critical; 9.4; note=Parameterized query required.]\n\n@fileheat[47 files; src/checkout/processor.ts:98:modified,src/auth/session.ts:71:added]\n\n@payment[$79; CodeSentinel Pro; desc=Automatic merge blocking and auto-fix PRs.]\n```\n\n**AI agent surfaces**\n\n```markdown\n@agent[CodeSentinel; Security Reviewer; done; tools=AST Analysis,Semgrep; goal=Block insecure merges]\n\n@command[Ops Console; Live; owner=AI Ops; channels=PagerDuty,Slack]\n```\n\n**Trading / market data**\n\n```markdown\n@ticker[NVDA; $984.22; +3.8%; 42.1M]\n\n@position[NVDA; long; entry=$902; target=$1025; stop=$864; size=7.5%]\n\n@trade[Buy on pullback; window=next 2 sessions; confidence=78; status=active]\n\n@candles[NVDA; thesis=Support holding at $952; candles=2026-04-21:910:956:905:948:36,2026-04-22:948:972:941:966:41]\n```\n\n**Architecture / infra**\n\n```markdown\n@servicemap[Checkout graph; nodes=api,API Layer,0,80,active; edges=api>validator>validate]\n\n@pipelineflow[Q2 Pipeline; stages=Sourced,$2.8M,182,done]\n```\n\nSee [`docs/bridges.md`](./docs/bridges.md) for all fields and formats.\n\n---\n\n### Tables\n\nStandard GFM tables work out of the box. The built-in HTML renderer adds analytics-friendly defaults without changing markdown syntax: mostly numeric columns are right-aligned, dense tables tighten spacing automatically, summary rows like `Total` and `Average` are emphasized, and simple status/delta values get clearer visual treatment.\n\n```markdown\n| Region | Revenue | Change | Status |\n| --- | --- | --- | --- |\n| East | $167k | +18% | On track |\n| South | $98k | -7% | At risk |\n| APAC | $89k | +20% | Healthy |\n| Total | $354k | +11% | Stable |\n```\n\nThis keeps AI-generated report tables readable on mobile and desktop, even when the model only emits plain markdown.\n\n---\n\n## Bridge system\n\nBridges let anyone map a custom `@marker[data]` inline syntax to any React component. The AI learns it from a single example in the system prompt. Publish bridges as `md4ai-bridge-*` npm packages to share with the ecosystem.\n\n### Syntax\n\n```\nThe build is @status[passing] with @num[142] tests.\n\nTop markets this quarter: @tags[East,North,APAC]\n\n@kpi[East Revenue; $167k; +18%; QoQ]\n\n@release[Agent Inbox; beta; July 2026; Core UX]\n```\n\n`@` only fires when followed by `word[` — bare mentions like `@john` and emails like `user@company.com` are never matched.\n\n---\n\n### Define a bridge\n \n```tsx\nimport { defineBridge, B } from '@architprasar/md4ai/core';\n \n// Use B.type() to define a fluent, positional-aware schema\nconst releaseBridge = defineBridge({\n  marker: 'release',\n  fields: [\n    B.string('name').describe('Package name (e.g., zod)'),\n    B.enum('status', ['live', 'beta', 'planned']).default('planned'),\n  ],\n  render: ({ name, status }) => (\n    <ReleaseBadge name={name} status={status} />\n  ),\n});\n```\n \n`defineBridge()` now accepts an array of **dTypes**. The order in the array defines the positional arguments.\n \n### Prompt generation\n \nmd4ai uses a two-tier prompting system (**Protocol & Catalog**) to save tokens.\n- **Protocol**: One-time rules for universal bridge syntax (brackets, lists, spacing).\n- **Catalog**: A compressed manifest of available markers and their fields.\n \nUse `getBridgeProtocolPrompt()` to get the Tier 1 instructions, and the system handles the rest.\n\n### Register it\n\nPass the same `bridges` array to both `parse` and `renderContent`:\n\n```tsx\nconst bridges = [statusBridge];\n\nconst nodes = parse(markdown, { bridges });\nconst ui = renderContent(nodes, { bridges });\n```\n\n### System prompt hint\n\nUse `getPrompt()` when you want a full md4ai-aware prompt that includes built-in syntax guidance plus optional bridge hints. Use `getBridgePrompt()` when you only want the bridge-specific portion:\n\n```ts\nimport { getPrompt, getBridgePrompt } from '@architprasar/md4ai/core';\n\nstatusBridge.prompt\n// → 'Use @status[value] inline. Example: @status[success]'\n\nconst systemPrompt = getPrompt({\n  bridges,\n  prefix: 'Write markdown and use md4ai syntax when it helps:',\n});\n\nconst analyticsPrompt = getPrompt({\n  bridges,\n  includeBuiltins: ['callouts', 'charts', 'kpi', 'tables'],\n  includeBridges: ['status'],\n});\n\nconst bridgeOnlyPrompt = getBridgePrompt(bridges, {\n  include: ['payment', 'status'],\n});\n```\n\n`getPrompt()` supports three modes:\n\n- `minimal` — smallest useful prompt, with strong fallback guidance and no long examples\n- `standard` — recommended default for most production surfaces\n- `withExamples` — higher-token mode with canonical examples for better syntax reliability\n\nExample:\n\n```ts\nconst minimalPrompt = getPrompt({\n  mode: 'minimal',\n  includeBuiltins: ['kpi', 'tables', 'steps'],\n});\n\nconst standardPrompt = getPrompt({\n  mode: 'standard',\n  bridges,\n  includeBuiltins: ['callouts', 'kpi', 'tables', 'steps'],\n});\n\nconst examplePrompt = getPrompt({\n  mode: 'withExamples',\n  bridges,\n  includeBuiltins: ['steps', 'kpi', 'buttons'],\n  includeBridges: ['payment'],\n});\n```\n\n---\n\n### Built-in patterns\n\n| Pattern | Markdown | Parsed as |\n|---------|----------|-----------|\n| `scalar` | `@badge[success]` | `\"success\"` |\n| `array` | `@tags[React,Vue,Angular]` | `[\"React\", \"Vue\", \"Angular\"]` |\n| `keyvalue` | `@kpi[label=Revenue; value=$167k]` | `{ label: \"Revenue\", value: \"$167k\" }` |\n| `range` | `@range[100 → 500]` | `{ min: \"100\", max: \"500\" }` |\n\nFor custom parsing, pass a function:\n\n```ts\ndefineBridge({\n  marker: 'progress',\n  pattern: (raw) => {\n    const [done, total] = raw.split('/').map(Number);\n    return { done, total, pct: Math.round((done / total) * 100) };\n  },\n  render: ({ done, total, pct }) => (\n    <div className=\"progress-bar\">\n      <div style={{ width: `${pct}%` }} />\n      <span>{done}/{total}</span>\n    </div>\n  ),\n});\n```\n\nIf you want to reuse the built-in parsers directly in your own helpers, `parseBridgeData()` is exported:\n\n```ts\nimport { parseBridgeData } from '@architprasar/md4ai/core';\n\nconst tags = parseBridgeData('array', 'React, Vue, Angular');\n// → ['React', 'Vue', 'Angular']\n```\n\nFor stricter custom parsing with a safe fallback:\n\n```ts\nconst progressBridge = defineBridge({\n  marker: 'progress',\n  pattern: (raw) => {\n    const [done, total] = raw.split('/').map(Number);\n    if (!Number.isFinite(done) || !Number.isFinite(total) || total <= 0) {\n      throw new Error('Invalid progress payload');\n    }\n    return { done, total, pct: Math.round((done / total) * 100) };\n  },\n  onParseError: (raw) => ({ done: 0, total: 0, pct: 0, raw }),\n  render: ({ pct }) => <span>{pct}%</span>,\n});\n```\n\n---\n\n### Host data and events\n\nBridges can pull live data from your app and emit events back — the AI writes identifiers, your app resolves them.\n\n```tsx\nrenderContent(nodes, {\n  bridges,\n\n  store: {\n    stock: ({ symbol }) => myStore.getPrice(symbol),\n    inventory: ({ sku, warehouse }) => api.getStock(sku, warehouse),\n  },\n\n  onEvent: (event, data) => {\n    if (event === 'buy') api.post('/orders', data);\n  },\n});\n```\n\nInside the bridge:\n\n```tsx\ndefineBridge({\n  marker: 'stock',\n  pattern: 'scalar',\n  render: (symbol, { query, emit }) => {\n    const price = query('stock', { symbol });\n    return (\n      <StockCard\n        symbol={symbol as string}\n        price={price as number}\n        onBuy={() => emit('buy', { symbol })}\n      />\n    );\n  },\n});\n```\n\nThe markdown never contains real prices. The AI writes `@stock[AAPL]` — your store resolves it at render time.\n\nIf a bridge renderer throws at render time, md4ai falls back to showing the original `@marker[data]` token instead of breaking the message tree.\n\n---\n\n## Themes\n\nFour built-in themes, each with light and dark variants. All use the same CSS variable system as shadcn — plug straight into your existing shadcn app.\n\n```tsx\nimport { renderContent, themes } from '@architprasar/md4ai/react';\nimport type { ThemeName } from '@architprasar/md4ai/react';\n\nrenderContent(nodes, {\n  theme: themes.violet.dark,\n});\n```\n\nAvailable themes: `zinc` `violet` `rose` `blue`\n\n### Apply to the app shell too\n\nUse `tokensToCSSVars` to apply the same tokens as CSS variables on your root element — both the shell and the renderer inherit the same theme with zero duplication:\n\n```tsx\nfunction tokensToCSSVars(tokens: Record<string, string | undefined>) {\n  return {\n    '--bg':           tokens.bg,\n    '--surface':      tokens.surface,\n    '--accent':       tokens.accent,\n    '--text':         tokens.text,\n    // ...\n  } as React.CSSProperties;\n}\n\nconst theme = themes[themeName][isDark ? 'dark' : 'light'];\n\n<div style={tokensToCSSVars(theme)}>\n  {renderContent(nodes, { theme })}\n</div>\n```\n\n### Custom theme\n\nPass any subset — unset tokens fall back to the CSS variables already on the page:\n\n```tsx\nrenderContent(nodes, {\n  theme: {\n    accent: '#7c3aed',\n    accentHover: '#6d28d9',\n    codeBg: '#1e1e2e',\n  },\n});\n```\n\n---\n\n## Syntax highlighting\n\nThe library doesn't bundle a highlighter — pass any highlighter via the `highlight` option:\n\n```tsx\nimport hljs from 'highlight.js';\n\nrenderContent(nodes, {\n  highlight: (code, lang) => {\n    if (lang && hljs.getLanguage(lang)) {\n      return hljs.highlight(code, { language: lang }).value;\n    }\n    return hljs.highlightAuto(code).value;\n  },\n});\n```\n\nWorks with highlight.js, Shiki, Prism, lowlight — anything that returns an HTML string.\n\n---\n\n## Custom component overrides\n\nReplace any built-in renderer with your own component:\n\n```tsx\nimport type { ComponentOverrides } from '@architprasar/md4ai/react';\n\nrenderContent(nodes, {\n  components: {\n    // Leaf nodes receive raw props\n    chart: ({ chartType, data }) => <MyChart type={chartType} data={data} />,\n    video: ({ src }) => <MyPlayer src={src} />,\n\n    // Container nodes receive pre-rendered children\n    callout: ({ variant, children }) => (\n      <Alert variant={variant}>{children}</Alert>\n    ),\n    card: ({ title, children }) => (\n      <Card><CardHeader>{title}</CardHeader><CardBody>{children}</CardBody></Card>\n    ),\n  },\n});\n```\n\nAll overridable keys: `paragraph` `heading` `code` `blockquote` `list` `table` `thematicBreak` `callout` `chart` `video` `button` `input` `card` `layout` `steps`\n\n---\n\n## API reference\n\n### `parse(markdown, options?)`\n\n| Option | Type | Default | Description |\n|--------|------|---------|-------------|\n| `gfm` | `boolean` | `true` | GFM — tables, task lists, strikethrough |\n| `bridges` | `BridgeDefinition[]` | `[]` | Registers `@marker` tokens for the parser |\n\nReturns `IRNode[]` — plain serializable JSON, framework-agnostic.\n\n### `parseStreaming(markdown, options?)`\n\nSame signature as `parse`. Lenient about unclosed blocks at the end of the string — safe to call on every streaming chunk. Partial `steps` fences render immediately, with unfinished or unknown statuses falling back to `planned`.\n\nSee [`docs/production.md`](./docs/production.md) for integration guidance around streaming updates and fallback expectations.\n\n### `renderContent(nodes, options?)`\n\n| Option | Type | Description |\n|--------|------|-------------|\n| `theme` | `ThemeTokens` | CSS variable overrides scoped to the root wrapper |\n| `highlight` | `(code, lang) => string \\| null` | Syntax highlighter for code blocks |\n| `components` | `ComponentOverrides` | Replace built-in renderers |\n| `bridges` | `BridgeDefinition[]` | Registered bridge renderers |\n| `store` | `Record<string, (params?) => unknown>` | Data resolvers for bridge `query()` |\n| `onEvent` | `(event, data?) => void` | Handler for bridge `emit()` |\n| `className` | `string` | Extra class on the root wrapper |\n\nSee [`docs/production.md`](./docs/production.md) for production patterns using `theme`, `components`, `store`, and `onEvent` together.\n\n### `defineBridge(options)`\n\n| Option | Type | Description |\n|--------|------|-------------|\n| `marker` | `string` | The `@marker` name — lowercase, letters and hyphens only |\n| `fields` | `BridgeField[]` | Fluent array of dTypes (e.g. `[B.string('id'), B.number('val')]`) |\n| `render` | `(data: T, ctx: BridgeRenderCtx) => ReactElement \\| null` | Renders the component |\n| `prompt` | `string` | Overrides the auto-generated AI system prompt hint |\n| `onParseError` | `(raw, error) => T` | Safe fallback when a custom parser throws |\n\n### `themes`\n\n```ts\nimport { themes } from '@architprasar/md4ai/react';\n// themes.zinc.light | themes.zinc.dark\n// themes.violet.light | themes.violet.dark\n// themes.rose.light | themes.rose.dark\n// themes.blue.light | themes.blue.dark\n```\n\n---\n\n## License\n\nMIT\n","readmeFilename":"README.md"}