react-native-nitro-markdown 0.2.1 → 0.3.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.
- package/README.md +237 -103
- package/cpp/bindings/HybridMarkdownParser.cpp +2 -0
- package/cpp/core/MD4CParser.cpp +73 -39
- package/cpp/core/MarkdownTypes.hpp +6 -1
- package/cpp/md4c/md4c.c +79 -56
- package/cpp/md4c/md4c.h +7 -4
- package/lib/commonjs/MarkdownContext.js +3 -7
- package/lib/commonjs/MarkdownContext.js.map +1 -1
- package/lib/commonjs/default-markdown-renderer.js +4 -7
- package/lib/commonjs/default-markdown-renderer.js.map +1 -1
- package/lib/commonjs/headless.js +49 -1
- package/lib/commonjs/headless.js.map +1 -1
- package/lib/commonjs/index.js +35 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/markdown.js +100 -41
- package/lib/commonjs/markdown.js.map +1 -1
- package/lib/commonjs/renderers/blockquote.js +1 -1
- package/lib/commonjs/renderers/blockquote.js.map +1 -1
- package/lib/commonjs/renderers/code.js +15 -8
- package/lib/commonjs/renderers/code.js.map +1 -1
- package/lib/commonjs/renderers/heading.js +2 -1
- package/lib/commonjs/renderers/heading.js.map +1 -1
- package/lib/commonjs/renderers/horizontal-rule.js +4 -2
- package/lib/commonjs/renderers/horizontal-rule.js.map +1 -1
- package/lib/commonjs/renderers/image.js +39 -14
- package/lib/commonjs/renderers/image.js.map +1 -1
- package/lib/commonjs/renderers/link.js +1 -3
- package/lib/commonjs/renderers/link.js.map +1 -1
- package/lib/commonjs/renderers/list.js +12 -10
- package/lib/commonjs/renderers/list.js.map +1 -1
- package/lib/commonjs/renderers/math.js +33 -47
- package/lib/commonjs/renderers/math.js.map +1 -1
- package/lib/commonjs/renderers/paragraph.js +0 -6
- package/lib/commonjs/renderers/paragraph.js.map +1 -1
- package/lib/commonjs/renderers/table.js +127 -120
- package/lib/commonjs/renderers/table.js.map +1 -1
- package/lib/commonjs/theme.js +146 -13
- package/lib/commonjs/theme.js.map +1 -1
- package/lib/module/MarkdownContext.js +3 -8
- package/lib/module/MarkdownContext.js.map +1 -1
- package/lib/module/default-markdown-renderer.js +1 -4
- package/lib/module/default-markdown-renderer.js.map +1 -1
- package/lib/module/headless.js +46 -0
- package/lib/module/headless.js.map +1 -1
- package/lib/module/index.js +2 -20
- package/lib/module/index.js.map +1 -1
- package/lib/module/markdown.js +101 -42
- package/lib/module/markdown.js.map +1 -1
- package/lib/module/renderers/blockquote.js +1 -1
- package/lib/module/renderers/blockquote.js.map +1 -1
- package/lib/module/renderers/code.js +15 -8
- package/lib/module/renderers/code.js.map +1 -1
- package/lib/module/renderers/heading.js +2 -1
- package/lib/module/renderers/heading.js.map +1 -1
- package/lib/module/renderers/horizontal-rule.js +4 -2
- package/lib/module/renderers/horizontal-rule.js.map +1 -1
- package/lib/module/renderers/image.js +40 -15
- package/lib/module/renderers/image.js.map +1 -1
- package/lib/module/renderers/link.js +1 -3
- package/lib/module/renderers/link.js.map +1 -1
- package/lib/module/renderers/list.js +12 -10
- package/lib/module/renderers/list.js.map +1 -1
- package/lib/module/renderers/math.js +34 -48
- package/lib/module/renderers/math.js.map +1 -1
- package/lib/module/renderers/paragraph.js +0 -6
- package/lib/module/renderers/paragraph.js.map +1 -1
- package/lib/module/renderers/table.js +128 -121
- package/lib/module/renderers/table.js.map +1 -1
- package/lib/module/theme.js +144 -12
- package/lib/module/theme.js.map +1 -1
- package/lib/typescript/commonjs/MarkdownContext.d.ts +45 -6
- package/lib/typescript/commonjs/MarkdownContext.d.ts.map +1 -1
- package/lib/typescript/commonjs/default-markdown-renderer.d.ts +1 -1
- package/lib/typescript/commonjs/default-markdown-renderer.d.ts.map +1 -1
- package/lib/typescript/commonjs/headless.d.ts +12 -1
- package/lib/typescript/commonjs/headless.d.ts.map +1 -1
- package/lib/typescript/commonjs/index.d.ts +4 -16
- package/lib/typescript/commonjs/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/markdown.d.ts +33 -2
- package/lib/typescript/commonjs/markdown.d.ts.map +1 -1
- package/lib/typescript/commonjs/renderers/code.d.ts +6 -2
- package/lib/typescript/commonjs/renderers/code.d.ts.map +1 -1
- package/lib/typescript/commonjs/renderers/heading.d.ts.map +1 -1
- package/lib/typescript/commonjs/renderers/horizontal-rule.d.ts +6 -1
- package/lib/typescript/commonjs/renderers/horizontal-rule.d.ts.map +1 -1
- package/lib/typescript/commonjs/renderers/image.d.ts +2 -0
- package/lib/typescript/commonjs/renderers/image.d.ts.map +1 -1
- package/lib/typescript/commonjs/renderers/link.d.ts.map +1 -1
- package/lib/typescript/commonjs/renderers/list.d.ts +4 -0
- package/lib/typescript/commonjs/renderers/list.d.ts.map +1 -1
- package/lib/typescript/commonjs/renderers/math.d.ts +3 -4
- package/lib/typescript/commonjs/renderers/math.d.ts.map +1 -1
- package/lib/typescript/commonjs/renderers/paragraph.d.ts +0 -5
- package/lib/typescript/commonjs/renderers/paragraph.d.ts.map +1 -1
- package/lib/typescript/commonjs/renderers/table.d.ts +2 -0
- package/lib/typescript/commonjs/renderers/table.d.ts.map +1 -1
- package/lib/typescript/commonjs/specs/MarkdownSession.nitro.d.ts.map +1 -1
- package/lib/typescript/commonjs/theme.d.ts +41 -28
- package/lib/typescript/commonjs/theme.d.ts.map +1 -1
- package/lib/typescript/module/MarkdownContext.d.ts +45 -6
- package/lib/typescript/module/MarkdownContext.d.ts.map +1 -1
- package/lib/typescript/module/default-markdown-renderer.d.ts +1 -1
- package/lib/typescript/module/default-markdown-renderer.d.ts.map +1 -1
- package/lib/typescript/module/headless.d.ts +12 -1
- package/lib/typescript/module/headless.d.ts.map +1 -1
- package/lib/typescript/module/index.d.ts +4 -16
- package/lib/typescript/module/index.d.ts.map +1 -1
- package/lib/typescript/module/markdown.d.ts +33 -2
- package/lib/typescript/module/markdown.d.ts.map +1 -1
- package/lib/typescript/module/renderers/code.d.ts +6 -2
- package/lib/typescript/module/renderers/code.d.ts.map +1 -1
- package/lib/typescript/module/renderers/heading.d.ts.map +1 -1
- package/lib/typescript/module/renderers/horizontal-rule.d.ts +6 -1
- package/lib/typescript/module/renderers/horizontal-rule.d.ts.map +1 -1
- package/lib/typescript/module/renderers/image.d.ts +2 -0
- package/lib/typescript/module/renderers/image.d.ts.map +1 -1
- package/lib/typescript/module/renderers/link.d.ts.map +1 -1
- package/lib/typescript/module/renderers/list.d.ts +4 -0
- package/lib/typescript/module/renderers/list.d.ts.map +1 -1
- package/lib/typescript/module/renderers/math.d.ts +3 -4
- package/lib/typescript/module/renderers/math.d.ts.map +1 -1
- package/lib/typescript/module/renderers/paragraph.d.ts +0 -5
- package/lib/typescript/module/renderers/paragraph.d.ts.map +1 -1
- package/lib/typescript/module/renderers/table.d.ts +2 -0
- package/lib/typescript/module/renderers/table.d.ts.map +1 -1
- package/lib/typescript/module/specs/MarkdownSession.nitro.d.ts.map +1 -1
- package/lib/typescript/module/theme.d.ts +41 -28
- package/lib/typescript/module/theme.d.ts.map +1 -1
- package/nitrogen/generated/ios/NitroMarkdownAutolinking.swift +8 -7
- package/nitrogen/generated/ios/swift/HybridMarkdownSessionSpec.swift +2 -2
- package/package.json +1 -1
- package/src/MarkdownContext.ts +66 -9
- package/src/default-markdown-renderer.tsx +1 -6
- package/src/headless.ts +67 -2
- package/src/index.ts +24 -19
- package/src/markdown.tsx +158 -52
- package/src/renderers/blockquote.tsx +1 -2
- package/src/renderers/code.tsx +36 -12
- package/src/renderers/heading.tsx +1 -1
- package/src/renderers/horizontal-rule.tsx +7 -4
- package/src/renderers/image.tsx +59 -15
- package/src/renderers/link.tsx +1 -6
- package/src/renderers/list.tsx +15 -15
- package/src/renderers/math.tsx +28 -45
- package/src/renderers/paragraph.tsx +1 -8
- package/src/renderers/table.tsx +185 -160
- package/src/specs/MarkdownSession.nitro.ts +4 -6
- package/src/theme.ts +203 -12
package/README.md
CHANGED
|
@@ -76,8 +76,8 @@ cd ios && pod install
|
|
|
76
76
|
If you are using Expo, you must run a **Prebuild** (Development Build) because this package contains native C++ code.
|
|
77
77
|
|
|
78
78
|
```bash
|
|
79
|
-
|
|
80
|
-
|
|
79
|
+
bunx expo install react-native-nitro-markdown react-native-nitro-modules
|
|
80
|
+
bunx expo prebuild
|
|
81
81
|
```
|
|
82
82
|
|
|
83
83
|
---
|
|
@@ -100,38 +100,25 @@ export function MyComponent() {
|
|
|
100
100
|
}
|
|
101
101
|
```
|
|
102
102
|
|
|
103
|
-
### Option 2:
|
|
103
|
+
### Option 2: Light Theme / Theme Presets
|
|
104
104
|
|
|
105
|
-
|
|
105
|
+
The default theme is optimized for dark mode. For light backgrounds, use the provided `lightMarkdownTheme`:
|
|
106
106
|
|
|
107
107
|
```tsx
|
|
108
|
-
import {
|
|
109
|
-
Markdown,
|
|
110
|
-
Heading,
|
|
111
|
-
type CustomRenderers,
|
|
112
|
-
} from "react-native-nitro-markdown";
|
|
113
|
-
import MathJax from "react-native-mathjax-svg";
|
|
114
|
-
|
|
115
|
-
const renderers: CustomRenderers = {
|
|
116
|
-
// Custom styled heading
|
|
117
|
-
heading: ({ node, children }) => (
|
|
118
|
-
<Heading level={node.level ?? 1}>
|
|
119
|
-
<Text style={{ color: "pink" }}>{children}</Text>
|
|
120
|
-
</Heading>
|
|
121
|
-
),
|
|
122
|
-
// Custom math renderer
|
|
123
|
-
math_inline: ({ node }) => <MathJax fontSize={16}>{node.content}</MathJax>,
|
|
124
|
-
math_block: ({ node }) => <MathJax fontSize={20}>{node.content}</MathJax>,
|
|
125
|
-
};
|
|
108
|
+
import { Markdown, lightMarkdownTheme } from "react-native-nitro-markdown";
|
|
126
109
|
|
|
127
|
-
<Markdown
|
|
128
|
-
{markdown}
|
|
129
|
-
</Markdown>;
|
|
110
|
+
<Markdown theme={lightMarkdownTheme}>{"# Light Mode Markdown"}</Markdown>;
|
|
130
111
|
```
|
|
131
112
|
|
|
113
|
+
Available presets:
|
|
114
|
+
|
|
115
|
+
- `defaultMarkdownTheme` / `darkMarkdownTheme` - Modern dark theme
|
|
116
|
+
- `lightMarkdownTheme` - Clean light theme
|
|
117
|
+
- `minimalMarkdownTheme` - Bare minimum styling for a clean slate
|
|
118
|
+
|
|
132
119
|
### Option 3: Custom Theming
|
|
133
120
|
|
|
134
|
-
|
|
121
|
+
Customize the look and feel by passing a partial `theme` object:
|
|
135
122
|
|
|
136
123
|
```tsx
|
|
137
124
|
import { Markdown } from "react-native-nitro-markdown";
|
|
@@ -141,38 +128,154 @@ const myTheme = {
|
|
|
141
128
|
text: "#2D3748",
|
|
142
129
|
heading: "#1A202C",
|
|
143
130
|
link: "#3182CE",
|
|
144
|
-
tableBorder: "#E2E8F0",
|
|
145
|
-
tableHeader: "#F7FAFC",
|
|
146
131
|
},
|
|
147
|
-
|
|
148
|
-
|
|
132
|
+
fontFamilies: {
|
|
133
|
+
regular: "Inter",
|
|
134
|
+
heading: "Inter-Bold",
|
|
135
|
+
mono: "JetBrainsMono",
|
|
149
136
|
},
|
|
137
|
+
borderRadius: {
|
|
138
|
+
s: 4,
|
|
139
|
+
m: 8,
|
|
140
|
+
l: 16,
|
|
141
|
+
},
|
|
142
|
+
showCodeLanguage: true, // Toggle code language labels
|
|
150
143
|
};
|
|
151
144
|
|
|
152
|
-
<Markdown theme={myTheme}>{"# Custom
|
|
145
|
+
<Markdown theme={myTheme}>{"# Custom Themed Markdown"}</Markdown>;
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
**Theme Properties:**
|
|
149
|
+
|
|
150
|
+
- `colors` - All color tokens (text, heading, link, code, codeBackground, codeLanguage, etc.)
|
|
151
|
+
- `spacing` - Spacing tokens (xs, s, m, l, xl)
|
|
152
|
+
- `fontSizes` - Font sizes (xs, s, m, l, xl, h1-h6)
|
|
153
|
+
- `fontFamilies` - Font families for regular, heading, and mono text
|
|
154
|
+
- `borderRadius` - Border radius tokens (s, m, l)
|
|
155
|
+
- `showCodeLanguage` - Show/hide code block language labels
|
|
156
|
+
|
|
157
|
+
### Option 4: Style Overrides per Node Type
|
|
158
|
+
|
|
159
|
+
Apply quick style overrides to specific node types without writing custom renderers:
|
|
160
|
+
|
|
161
|
+
```tsx
|
|
162
|
+
<Markdown
|
|
163
|
+
styles={{
|
|
164
|
+
heading: { color: "red", fontWeight: "900" },
|
|
165
|
+
code_block: { backgroundColor: "#1a1a2e", borderRadius: 16 },
|
|
166
|
+
blockquote: { borderLeftColor: "#ff6b6b" },
|
|
167
|
+
}}
|
|
168
|
+
>
|
|
169
|
+
{markdown}
|
|
170
|
+
</Markdown>
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### Option 5: Minimal Styling Strategy
|
|
174
|
+
|
|
175
|
+
Start with a clean slate using the `stylingStrategy` prop:
|
|
176
|
+
|
|
177
|
+
```tsx
|
|
178
|
+
<Markdown stylingStrategy="minimal" theme={myLightTheme}>
|
|
179
|
+
{content}
|
|
180
|
+
</Markdown>
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
This zeros out all spacing and removes opinionated colors, letting you build up from scratch.
|
|
184
|
+
|
|
185
|
+
### Option 6: Custom Renderers
|
|
186
|
+
|
|
187
|
+
Override specific node types with full control. Custom renderers now receive **pre-mapped props** for common values:
|
|
188
|
+
|
|
189
|
+
```tsx
|
|
190
|
+
import {
|
|
191
|
+
Markdown,
|
|
192
|
+
CodeBlock,
|
|
193
|
+
type HeadingRendererProps,
|
|
194
|
+
type CodeBlockRendererProps,
|
|
195
|
+
} from "react-native-nitro-markdown";
|
|
196
|
+
|
|
197
|
+
const renderers = {
|
|
198
|
+
// Pre-mapped `level` prop - no need for node.level!
|
|
199
|
+
heading: ({ level, children }: HeadingRendererProps) => (
|
|
200
|
+
<MyHeading level={level}>{children}</MyHeading>
|
|
201
|
+
),
|
|
202
|
+
|
|
203
|
+
// Pre-mapped `content` and `language` - no getTextContent() needed!
|
|
204
|
+
code_block: ({ content, language }: CodeBlockRendererProps) => (
|
|
205
|
+
<CodeBlock
|
|
206
|
+
content={content}
|
|
207
|
+
language={language}
|
|
208
|
+
style={{ borderWidth: 2 }}
|
|
209
|
+
/>
|
|
210
|
+
),
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
<Markdown renderers={renderers} options={{ gfm: true }}>
|
|
214
|
+
{markdown}
|
|
215
|
+
</Markdown>;
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
**Pre-mapped Props by Node Type:**
|
|
219
|
+
|
|
220
|
+
- `heading` → `level` (1-6)
|
|
221
|
+
- `link` → `href`, `title`
|
|
222
|
+
- `image` → `url`, `alt`, `title`
|
|
223
|
+
- `code_block` → `content`, `language`
|
|
224
|
+
- `code_inline` → `content`
|
|
225
|
+
- `list` → `ordered`, `start`
|
|
226
|
+
- `task_list_item` → `checked`
|
|
227
|
+
|
|
228
|
+
### Option 7: Style Props on Individual Renderers
|
|
229
|
+
|
|
230
|
+
All built-in renderers accept a `style` prop for fine-grained overrides:
|
|
231
|
+
|
|
232
|
+
```tsx
|
|
233
|
+
import { Heading, CodeBlock, InlineCode } from "react-native-nitro-markdown";
|
|
234
|
+
|
|
235
|
+
// Works in custom renderers
|
|
236
|
+
<Heading level={1} style={{ color: "hotpink" }}>Title</Heading>
|
|
237
|
+
<CodeBlock content={code} style={{ borderRadius: 0 }} />
|
|
238
|
+
<InlineCode style={{ backgroundColor: "#ff0" }}>code</InlineCode>
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### Option 8: Auto Content Extraction for Code
|
|
153
242
|
|
|
154
|
-
|
|
243
|
+
The `CodeBlock` and `InlineCode` components now accept a `node` prop for automatic content extraction:
|
|
244
|
+
|
|
245
|
+
```tsx
|
|
246
|
+
// Before: Manual extraction required
|
|
247
|
+
code_block: ({ node }) => (
|
|
248
|
+
<CodeBlock content={getTextContent(node)} language={node.language} />
|
|
249
|
+
);
|
|
250
|
+
|
|
251
|
+
// After: Just pass the node
|
|
252
|
+
code_block: ({ node }) => <CodeBlock node={node} />;
|
|
253
|
+
|
|
254
|
+
// Or use the pre-mapped content prop (recommended)
|
|
255
|
+
code_block: ({ content, language }) => (
|
|
256
|
+
<CodeBlock content={content} language={language} />
|
|
257
|
+
);
|
|
155
258
|
```
|
|
156
259
|
|
|
157
|
-
### Option
|
|
260
|
+
### Option 9: Headless (Minimal Bundle)
|
|
158
261
|
|
|
159
262
|
For maximum control, data processing, or minimal JS overhead:
|
|
160
263
|
|
|
161
264
|
```tsx
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
265
|
+
import {
|
|
266
|
+
parseMarkdown,
|
|
267
|
+
getTextContent,
|
|
268
|
+
getFlattenedText,
|
|
269
|
+
} from "react-native-nitro-markdown/headless";
|
|
167
270
|
|
|
168
271
|
const ast = parseMarkdown("# Hello World");
|
|
272
|
+
const text = getTextContent(ast); // "Hello World"
|
|
273
|
+
const fullText = getFlattenedText(ast); // "Hello World\n\n" (Normalized with line breaks)
|
|
169
274
|
```
|
|
170
275
|
|
|
171
|
-
### Option
|
|
172
|
-
|
|
173
|
-
When streaming text token-by-token (e.g., from ChatGPT or Gemini), re-parsing the entire document in JavaScript for every token is too slow.
|
|
276
|
+
### Option 10: High-Performance Streaming (LLMs)
|
|
174
277
|
|
|
175
|
-
|
|
278
|
+
When streaming text token-by-token (e.g., from ChatGPT or Gemini):
|
|
176
279
|
|
|
177
280
|
```tsx
|
|
178
281
|
import {
|
|
@@ -181,25 +284,97 @@ import {
|
|
|
181
284
|
} from "react-native-nitro-markdown";
|
|
182
285
|
|
|
183
286
|
export function AIResponseStream() {
|
|
184
|
-
// 1. Create a native session
|
|
185
287
|
const session = useMarkdownSession();
|
|
186
288
|
|
|
187
289
|
useEffect(() => {
|
|
188
|
-
// 2. Append chunks directly to C++ (Zero-Latency)
|
|
189
|
-
// Example: Socket.on('data', (chunk) => session.getSession().append(chunk));
|
|
190
|
-
|
|
191
290
|
session.getSession().append("Hello **Nitro**!");
|
|
192
|
-
|
|
193
291
|
return () => session.clear();
|
|
194
292
|
}, [session]);
|
|
195
293
|
|
|
196
|
-
// 3. Render the localized stream component
|
|
197
294
|
return (
|
|
198
295
|
<MarkdownStream session={session.getSession()} options={{ gfm: true }} />
|
|
199
296
|
);
|
|
200
297
|
}
|
|
201
298
|
```
|
|
202
299
|
|
|
300
|
+
### Option 11: Extracting Plain Text
|
|
301
|
+
|
|
302
|
+
You can extract the plain text representation (with proper line breaks) using the `onParseComplete` callback. This is useful for "Copy All" buttons or TTS.
|
|
303
|
+
|
|
304
|
+
```tsx
|
|
305
|
+
<Markdown
|
|
306
|
+
onParseComplete={(result) => {
|
|
307
|
+
console.log(result.text); // "Hello World\n\nThis is bold text."
|
|
308
|
+
console.log(result.ast); // Full AST
|
|
309
|
+
}}
|
|
310
|
+
>
|
|
311
|
+
{markdown}
|
|
312
|
+
</Markdown>
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
---
|
|
316
|
+
|
|
317
|
+
## 🎨 Using Context in Custom Renderers
|
|
318
|
+
|
|
319
|
+
Access theme and context in custom renderers:
|
|
320
|
+
|
|
321
|
+
```tsx
|
|
322
|
+
import {
|
|
323
|
+
useMarkdownContext,
|
|
324
|
+
MarkdownContext,
|
|
325
|
+
} from "react-native-nitro-markdown";
|
|
326
|
+
|
|
327
|
+
const MyCustomRenderer = ({ children }) => {
|
|
328
|
+
const { theme, stylingStrategy } = useMarkdownContext();
|
|
329
|
+
|
|
330
|
+
return <View style={{ padding: theme.spacing.m }}>{children}</View>;
|
|
331
|
+
};
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
---
|
|
335
|
+
|
|
336
|
+
## 🛠️ Exported Utilities
|
|
337
|
+
|
|
338
|
+
```tsx
|
|
339
|
+
// Parser and utilities
|
|
340
|
+
export {
|
|
341
|
+
parseMarkdown,
|
|
342
|
+
parseMarkdownWithOptions,
|
|
343
|
+
getTextContent,
|
|
344
|
+
getFlattenedText,
|
|
345
|
+
} from "./headless";
|
|
346
|
+
|
|
347
|
+
// Theme presets
|
|
348
|
+
export {
|
|
349
|
+
defaultMarkdownTheme,
|
|
350
|
+
lightMarkdownTheme,
|
|
351
|
+
darkMarkdownTheme,
|
|
352
|
+
minimalMarkdownTheme,
|
|
353
|
+
mergeThemes,
|
|
354
|
+
};
|
|
355
|
+
|
|
356
|
+
// Context
|
|
357
|
+
export { useMarkdownContext, MarkdownContext };
|
|
358
|
+
|
|
359
|
+
// Individual renderers
|
|
360
|
+
export {
|
|
361
|
+
Heading,
|
|
362
|
+
Paragraph,
|
|
363
|
+
Link,
|
|
364
|
+
Blockquote,
|
|
365
|
+
HorizontalRule,
|
|
366
|
+
CodeBlock,
|
|
367
|
+
InlineCode,
|
|
368
|
+
List,
|
|
369
|
+
ListItem,
|
|
370
|
+
TaskListItem,
|
|
371
|
+
TableRenderer,
|
|
372
|
+
Image,
|
|
373
|
+
MathInline,
|
|
374
|
+
MathBlock,
|
|
375
|
+
};
|
|
376
|
+
```
|
|
377
|
+
|
|
203
378
|
---
|
|
204
379
|
|
|
205
380
|
## 🛠️ Headless vs. Non-Headless
|
|
@@ -214,7 +389,8 @@ export function AIResponseStream() {
|
|
|
214
389
|
---
|
|
215
390
|
|
|
216
391
|
### Basic Parsing API
|
|
217
|
-
|
|
392
|
+
|
|
393
|
+
The parsing is synchronous and instant. It returns a fully typed JSON AST:
|
|
218
394
|
|
|
219
395
|
```typescript
|
|
220
396
|
import { parseMarkdown } from "react-native-nitro-markdown/headless";
|
|
@@ -223,74 +399,33 @@ const ast = parseMarkdown(`
|
|
|
223
399
|
# Hello World
|
|
224
400
|
This is **bold** text and a [link](https://github.com).
|
|
225
401
|
`);
|
|
226
|
-
console.log(ast);
|
|
227
|
-
// Output: { type: "document", children: [...] }
|
|
228
402
|
```
|
|
229
403
|
|
|
230
404
|
### Options
|
|
231
405
|
|
|
232
|
-
| Option | Type
|
|
233
|
-
|
|
|
234
|
-
| `gfm`
|
|
235
|
-
| `math` | `boolean` | `false` | Enable LaTeX Math support (`$` and `$$`).
|
|
236
|
-
|
|
237
|
-
### Parser Options (GFM & Math)
|
|
238
|
-
|
|
239
|
-
Enable GitHub Flavored Markdown (Tables, TaskLists) or LaTeX Math support.
|
|
240
|
-
|
|
241
|
-
```typescript
|
|
242
|
-
import { parseMarkdownWithOptions } from "react-native-nitro-markdown/headless";
|
|
243
|
-
|
|
244
|
-
const ast = parseMarkdownWithOptions(markdown, {
|
|
245
|
-
gfm: true, // Tables (supports complex nested content!), Strikethrough, Autolinks, TaskLists
|
|
246
|
-
math: true, // $E=mc^2$ and $$block$$
|
|
247
|
-
});
|
|
248
|
-
```
|
|
406
|
+
| Option | Type | Default | Description |
|
|
407
|
+
| :----- | :-------- | :------ | :----------------------------------------------------------------------------- |
|
|
408
|
+
| `gfm` | `boolean` | `false` | Enable GitHub Flavored Markdown (Tables, Strikethrough, Autolinks, TaskLists). |
|
|
409
|
+
| `math` | `boolean` | `false` | Enable LaTeX Math support (`$` and `$$`). |
|
|
249
410
|
|
|
250
411
|
---
|
|
251
412
|
|
|
252
413
|
## 📐 AST Structure
|
|
253
414
|
|
|
254
|
-
The parser returns a `MarkdownNode` tree
|
|
415
|
+
The parser returns a `MarkdownNode` tree:
|
|
255
416
|
|
|
256
417
|
```typescript
|
|
257
418
|
export interface MarkdownNode {
|
|
258
419
|
type: NodeType;
|
|
259
|
-
// Content for Text/Code/Math
|
|
260
420
|
content?: string;
|
|
261
|
-
// Hierarchy
|
|
262
421
|
children?: MarkdownNode[];
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
language?: string; // Code Blocks
|
|
268
|
-
// Table Props
|
|
422
|
+
level?: number;
|
|
423
|
+
href?: string;
|
|
424
|
+
checked?: boolean;
|
|
425
|
+
language?: string;
|
|
269
426
|
align?: "left" | "center" | "right";
|
|
270
427
|
isHeader?: boolean;
|
|
271
428
|
}
|
|
272
|
-
|
|
273
|
-
export type NodeType =
|
|
274
|
-
| "document"
|
|
275
|
-
| "paragraph"
|
|
276
|
-
| "text"
|
|
277
|
-
| "heading"
|
|
278
|
-
| "bold"
|
|
279
|
-
| "italic"
|
|
280
|
-
| "strikethrough"
|
|
281
|
-
| "link"
|
|
282
|
-
| "image"
|
|
283
|
-
| "code_inline"
|
|
284
|
-
| "code_block"
|
|
285
|
-
| "blockquote"
|
|
286
|
-
| "list"
|
|
287
|
-
| "list_item"
|
|
288
|
-
| "task_list_item"
|
|
289
|
-
| "table"
|
|
290
|
-
| "table_row"
|
|
291
|
-
| "table_cell"
|
|
292
|
-
| "math_inline"
|
|
293
|
-
| "math_block";
|
|
294
429
|
```
|
|
295
430
|
|
|
296
431
|
---
|
|
@@ -299,16 +434,17 @@ export type NodeType =
|
|
|
299
434
|
|
|
300
435
|
We parse math delimiters (`$` and `$$`) natively using the `MD_FLAG_LATEXMATHSPANS` flag in `md4c`.
|
|
301
436
|
|
|
302
|
-
To render the math,
|
|
437
|
+
To render the math, use a library like `react-native-mathjax-svg`:
|
|
303
438
|
|
|
304
439
|
```tsx
|
|
305
|
-
// Inside your switch(node.type)
|
|
306
440
|
case 'math_inline':
|
|
307
441
|
return <MathView math={node.content} style={styles.math} />;
|
|
308
442
|
case 'math_block':
|
|
309
443
|
return <MathView math={node.content} style={styles.mathBlock} />;
|
|
310
444
|
```
|
|
311
445
|
|
|
446
|
+
---
|
|
447
|
+
|
|
312
448
|
## 📊 Package Size
|
|
313
449
|
|
|
314
450
|
| Metric | Size |
|
|
@@ -317,8 +453,6 @@ case 'math_block':
|
|
|
317
453
|
| **Unpacked** | ~325 kB |
|
|
318
454
|
| **Total files** | 55 |
|
|
319
455
|
|
|
320
|
-
> The package includes the [md4c](https://github.com/mity/md4c) C source code (~244 kB) which is compiled natively on iOS and Android. This is a one-time cost that enables the high-performance parsing.
|
|
321
|
-
|
|
322
456
|
---
|
|
323
457
|
|
|
324
458
|
## 🤝 Contributing
|
|
@@ -48,6 +48,8 @@ std::string HybridMarkdownParser::nodeToJson(const std::shared_ptr<InternalMarkd
|
|
|
48
48
|
std::ostringstream json;
|
|
49
49
|
json << "{";
|
|
50
50
|
json << "\"type\":\"" << ::NitroMarkdown::nodeTypeToString(node->type) << "\"";
|
|
51
|
+
json << ",\"beg\":" << node->beg;
|
|
52
|
+
json << ",\"end\":" << node->end;
|
|
51
53
|
|
|
52
54
|
if (node->content.has_value()) {
|
|
53
55
|
json << ",\"content\":\"" << escapeJson(node->content.value()) << "\"";
|