@affanhamid/markdown-renderer 2.0.0 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +135 -0
  2. package/package.json +3 -2
package/README.md ADDED
@@ -0,0 +1,135 @@
1
+ # @affanhamid/markdown-renderer
2
+
3
+ A React markdown renderer built for AI-generated content. Handles the math rendering problems that react-markdown + remark-math can't.
4
+
5
+ ## Why this exists
6
+
7
+ If you've used `react-markdown` with `remark-math` and `rehype-katex` to render LLM output, you've hit these problems:
8
+
9
+ **1. Dollar signs break everything.** `remark-math` uses `$` for LaTeX math, but `$` is also currency. Their `singleDollarTextMath: false` option disables single-dollar math entirely, forcing `$$` for everything. This package disambiguates intelligently: `$20` renders as currency (digit follows `$`), while `$x + y$` renders as math. It also handles CJK characters, Devanagari/Hindi punctuation, and fullwidth punctuation as valid math boundaries.
10
+
11
+ **2. AI models use inconsistent math delimiters.** GPT, Claude, and Gemini variously output `$...$`, `$$...$$`, `\(...\)`, and `\[...\]`. `remark-math` does not support `\(...\)` or `\[...\]` — there's an [open discussion](https://github.com/remarkjs/remark-math/issues) with no resolution. This package normalizes all four formats automatically before rendering.
12
+
13
+ **3. Too many moving parts.** The standard setup requires `react-markdown` + `remark-math` + `remark-gfm` + `rehype-katex` + KaTeX CSS + a syntax highlighter + custom components for tables, images, code blocks. This package is one import.
14
+
15
+ ## Features
16
+
17
+ - **Math rendering** — KaTeX with automatic delimiter normalization (`$`, `$$`, `\(`, `\[`)
18
+ - **Dollar sign disambiguation** — currency vs. math, with CJK/Devanagari/fullwidth support
19
+ - **Syntax highlighting** — Shiki with `github-light` theme and copy-to-clipboard
20
+ - **Tables** — GFM-style with column alignment (left, center, right)
21
+ - **Executable code blocks** — optional `onRunCode` callback for running Python, R, etc.
22
+ - **Inline images** — `![alt](url)` works inside paragraphs, not just as standalone blocks
23
+ - **Semantic color tags** — `{color:important}text{/color}` for highlighting (important, definition, example, note, formula)
24
+ - **Auto-scaling brackets** — `($x + y$)` automatically uses `\left(` and `\right)` for proper sizing
25
+ - **Prompt appendix** — exported `MATH_MARKDOWN_RULES_APPENDIX` string to append to your LLM system prompt, steering models toward consistent delimiter usage
26
+
27
+ ## Installation
28
+
29
+ ```bash
30
+ npm install @affanhamid/markdown-renderer
31
+ ```
32
+
33
+ Peer dependency: `react >= 18`
34
+
35
+ ## Usage
36
+
37
+ ### React component
38
+
39
+ ```tsx
40
+ import { MarkdownRenderer } from "@affanhamid/markdown-renderer";
41
+
42
+ function ChatMessage({ content }: { content: string }) {
43
+ return <MarkdownRenderer markdown={content} />;
44
+ }
45
+ ```
46
+
47
+ ### With executable code blocks
48
+
49
+ ```tsx
50
+ import { MarkdownRenderer } from "@affanhamid/markdown-renderer";
51
+
52
+ function Notebook({ content }: { content: string }) {
53
+ const handleRunCode = async (code: string, language: string) => {
54
+ const result = await executeOnServer(code, language);
55
+ return {
56
+ output: result.stdout,
57
+ error: result.stderr,
58
+ images: result.plots, // base64 data URIs
59
+ };
60
+ };
61
+
62
+ return (
63
+ <MarkdownRenderer
64
+ markdown={content}
65
+ onRunCode={handleRunCode}
66
+ executableLanguages={["python", "r"]}
67
+ />
68
+ );
69
+ }
70
+ ```
71
+
72
+ ### Server-side HTML (no React)
73
+
74
+ ```ts
75
+ import { renderMarkdownToHtml } from "@affanhamid/markdown-renderer";
76
+
77
+ const html = renderMarkdownToHtml(markdownString);
78
+ ```
79
+
80
+ ### Normalize delimiters only
81
+
82
+ If you want to preprocess markdown before passing it to your own renderer:
83
+
84
+ ```ts
85
+ import { normalizeMathMarkdownDelimiters } from "@affanhamid/markdown-renderer";
86
+
87
+ // Converts \(...\) -> $...$, \[...\] -> $$...$$, inline $$...$$ -> $...$
88
+ const normalized = normalizeMathMarkdownDelimiters(rawMarkdown);
89
+ ```
90
+
91
+ ### Prompt engineering helper
92
+
93
+ Append this to your LLM system prompt to reduce delimiter inconsistency at the source:
94
+
95
+ ```ts
96
+ import { MATH_MARKDOWN_RULES_APPENDIX } from "@affanhamid/markdown-renderer";
97
+
98
+ const systemPrompt = `You are a helpful assistant.\n\n${MATH_MARKDOWN_RULES_APPENDIX}`;
99
+ ```
100
+
101
+ ## API
102
+
103
+ ### `<MarkdownRenderer />` (default export)
104
+
105
+ | Prop | Type | Default | Description |
106
+ |------|------|---------|-------------|
107
+ | `markdown` | `string` | required | Markdown content to render |
108
+ | `onRunCode` | `(code: string, language: string) => Promise<CodeExecutionResult>` | `undefined` | Callback for executing code blocks |
109
+ | `executableLanguages` | `string[]` | `["python", "r"]` | Languages that get a "Run" button |
110
+
111
+ ### `CodeExecutionResult`
112
+
113
+ ```ts
114
+ interface CodeExecutionResult {
115
+ output: string;
116
+ error?: string;
117
+ images?: string[]; // data URIs or URLs
118
+ }
119
+ ```
120
+
121
+ ### `renderMarkdownToHtml(markdown: string, options?: { executableLanguages?: string[] }): string`
122
+
123
+ Renders markdown to an HTML string. Works without React (server-side, emails, PDFs).
124
+
125
+ ### `normalizeMathMarkdownDelimiters(markdown: string): string`
126
+
127
+ Normalizes `\(...\)` to `$...$` and `\[...\]` to `$$...$$`. Converts inline `$$...$$` to `$...$`. Leaves code fences untouched.
128
+
129
+ ### `MATH_MARKDOWN_RULES_APPENDIX: string`
130
+
131
+ A plain-text string with math formatting rules to append to LLM system prompts.
132
+
133
+ ## License
134
+
135
+ MIT
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@affanhamid/markdown-renderer",
3
- "version": "2.0.0",
3
+ "version": "2.0.1",
4
4
  "description": "Custom markdown renderer with KaTeX support",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
@@ -34,7 +34,8 @@
34
34
  "typescript": "^5.8.0"
35
35
  },
36
36
  "files": [
37
- "dist"
37
+ "dist",
38
+ "README.md"
38
39
  ],
39
40
  "license": "MIT"
40
41
  }