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.
Files changed (148) hide show
  1. package/README.md +237 -103
  2. package/cpp/bindings/HybridMarkdownParser.cpp +2 -0
  3. package/cpp/core/MD4CParser.cpp +73 -39
  4. package/cpp/core/MarkdownTypes.hpp +6 -1
  5. package/cpp/md4c/md4c.c +79 -56
  6. package/cpp/md4c/md4c.h +7 -4
  7. package/lib/commonjs/MarkdownContext.js +3 -7
  8. package/lib/commonjs/MarkdownContext.js.map +1 -1
  9. package/lib/commonjs/default-markdown-renderer.js +4 -7
  10. package/lib/commonjs/default-markdown-renderer.js.map +1 -1
  11. package/lib/commonjs/headless.js +49 -1
  12. package/lib/commonjs/headless.js.map +1 -1
  13. package/lib/commonjs/index.js +35 -0
  14. package/lib/commonjs/index.js.map +1 -1
  15. package/lib/commonjs/markdown.js +100 -41
  16. package/lib/commonjs/markdown.js.map +1 -1
  17. package/lib/commonjs/renderers/blockquote.js +1 -1
  18. package/lib/commonjs/renderers/blockquote.js.map +1 -1
  19. package/lib/commonjs/renderers/code.js +15 -8
  20. package/lib/commonjs/renderers/code.js.map +1 -1
  21. package/lib/commonjs/renderers/heading.js +2 -1
  22. package/lib/commonjs/renderers/heading.js.map +1 -1
  23. package/lib/commonjs/renderers/horizontal-rule.js +4 -2
  24. package/lib/commonjs/renderers/horizontal-rule.js.map +1 -1
  25. package/lib/commonjs/renderers/image.js +39 -14
  26. package/lib/commonjs/renderers/image.js.map +1 -1
  27. package/lib/commonjs/renderers/link.js +1 -3
  28. package/lib/commonjs/renderers/link.js.map +1 -1
  29. package/lib/commonjs/renderers/list.js +12 -10
  30. package/lib/commonjs/renderers/list.js.map +1 -1
  31. package/lib/commonjs/renderers/math.js +33 -47
  32. package/lib/commonjs/renderers/math.js.map +1 -1
  33. package/lib/commonjs/renderers/paragraph.js +0 -6
  34. package/lib/commonjs/renderers/paragraph.js.map +1 -1
  35. package/lib/commonjs/renderers/table.js +127 -120
  36. package/lib/commonjs/renderers/table.js.map +1 -1
  37. package/lib/commonjs/theme.js +146 -13
  38. package/lib/commonjs/theme.js.map +1 -1
  39. package/lib/module/MarkdownContext.js +3 -8
  40. package/lib/module/MarkdownContext.js.map +1 -1
  41. package/lib/module/default-markdown-renderer.js +1 -4
  42. package/lib/module/default-markdown-renderer.js.map +1 -1
  43. package/lib/module/headless.js +46 -0
  44. package/lib/module/headless.js.map +1 -1
  45. package/lib/module/index.js +2 -20
  46. package/lib/module/index.js.map +1 -1
  47. package/lib/module/markdown.js +101 -42
  48. package/lib/module/markdown.js.map +1 -1
  49. package/lib/module/renderers/blockquote.js +1 -1
  50. package/lib/module/renderers/blockquote.js.map +1 -1
  51. package/lib/module/renderers/code.js +15 -8
  52. package/lib/module/renderers/code.js.map +1 -1
  53. package/lib/module/renderers/heading.js +2 -1
  54. package/lib/module/renderers/heading.js.map +1 -1
  55. package/lib/module/renderers/horizontal-rule.js +4 -2
  56. package/lib/module/renderers/horizontal-rule.js.map +1 -1
  57. package/lib/module/renderers/image.js +40 -15
  58. package/lib/module/renderers/image.js.map +1 -1
  59. package/lib/module/renderers/link.js +1 -3
  60. package/lib/module/renderers/link.js.map +1 -1
  61. package/lib/module/renderers/list.js +12 -10
  62. package/lib/module/renderers/list.js.map +1 -1
  63. package/lib/module/renderers/math.js +34 -48
  64. package/lib/module/renderers/math.js.map +1 -1
  65. package/lib/module/renderers/paragraph.js +0 -6
  66. package/lib/module/renderers/paragraph.js.map +1 -1
  67. package/lib/module/renderers/table.js +128 -121
  68. package/lib/module/renderers/table.js.map +1 -1
  69. package/lib/module/theme.js +144 -12
  70. package/lib/module/theme.js.map +1 -1
  71. package/lib/typescript/commonjs/MarkdownContext.d.ts +45 -6
  72. package/lib/typescript/commonjs/MarkdownContext.d.ts.map +1 -1
  73. package/lib/typescript/commonjs/default-markdown-renderer.d.ts +1 -1
  74. package/lib/typescript/commonjs/default-markdown-renderer.d.ts.map +1 -1
  75. package/lib/typescript/commonjs/headless.d.ts +12 -1
  76. package/lib/typescript/commonjs/headless.d.ts.map +1 -1
  77. package/lib/typescript/commonjs/index.d.ts +4 -16
  78. package/lib/typescript/commonjs/index.d.ts.map +1 -1
  79. package/lib/typescript/commonjs/markdown.d.ts +33 -2
  80. package/lib/typescript/commonjs/markdown.d.ts.map +1 -1
  81. package/lib/typescript/commonjs/renderers/code.d.ts +6 -2
  82. package/lib/typescript/commonjs/renderers/code.d.ts.map +1 -1
  83. package/lib/typescript/commonjs/renderers/heading.d.ts.map +1 -1
  84. package/lib/typescript/commonjs/renderers/horizontal-rule.d.ts +6 -1
  85. package/lib/typescript/commonjs/renderers/horizontal-rule.d.ts.map +1 -1
  86. package/lib/typescript/commonjs/renderers/image.d.ts +2 -0
  87. package/lib/typescript/commonjs/renderers/image.d.ts.map +1 -1
  88. package/lib/typescript/commonjs/renderers/link.d.ts.map +1 -1
  89. package/lib/typescript/commonjs/renderers/list.d.ts +4 -0
  90. package/lib/typescript/commonjs/renderers/list.d.ts.map +1 -1
  91. package/lib/typescript/commonjs/renderers/math.d.ts +3 -4
  92. package/lib/typescript/commonjs/renderers/math.d.ts.map +1 -1
  93. package/lib/typescript/commonjs/renderers/paragraph.d.ts +0 -5
  94. package/lib/typescript/commonjs/renderers/paragraph.d.ts.map +1 -1
  95. package/lib/typescript/commonjs/renderers/table.d.ts +2 -0
  96. package/lib/typescript/commonjs/renderers/table.d.ts.map +1 -1
  97. package/lib/typescript/commonjs/specs/MarkdownSession.nitro.d.ts.map +1 -1
  98. package/lib/typescript/commonjs/theme.d.ts +41 -28
  99. package/lib/typescript/commonjs/theme.d.ts.map +1 -1
  100. package/lib/typescript/module/MarkdownContext.d.ts +45 -6
  101. package/lib/typescript/module/MarkdownContext.d.ts.map +1 -1
  102. package/lib/typescript/module/default-markdown-renderer.d.ts +1 -1
  103. package/lib/typescript/module/default-markdown-renderer.d.ts.map +1 -1
  104. package/lib/typescript/module/headless.d.ts +12 -1
  105. package/lib/typescript/module/headless.d.ts.map +1 -1
  106. package/lib/typescript/module/index.d.ts +4 -16
  107. package/lib/typescript/module/index.d.ts.map +1 -1
  108. package/lib/typescript/module/markdown.d.ts +33 -2
  109. package/lib/typescript/module/markdown.d.ts.map +1 -1
  110. package/lib/typescript/module/renderers/code.d.ts +6 -2
  111. package/lib/typescript/module/renderers/code.d.ts.map +1 -1
  112. package/lib/typescript/module/renderers/heading.d.ts.map +1 -1
  113. package/lib/typescript/module/renderers/horizontal-rule.d.ts +6 -1
  114. package/lib/typescript/module/renderers/horizontal-rule.d.ts.map +1 -1
  115. package/lib/typescript/module/renderers/image.d.ts +2 -0
  116. package/lib/typescript/module/renderers/image.d.ts.map +1 -1
  117. package/lib/typescript/module/renderers/link.d.ts.map +1 -1
  118. package/lib/typescript/module/renderers/list.d.ts +4 -0
  119. package/lib/typescript/module/renderers/list.d.ts.map +1 -1
  120. package/lib/typescript/module/renderers/math.d.ts +3 -4
  121. package/lib/typescript/module/renderers/math.d.ts.map +1 -1
  122. package/lib/typescript/module/renderers/paragraph.d.ts +0 -5
  123. package/lib/typescript/module/renderers/paragraph.d.ts.map +1 -1
  124. package/lib/typescript/module/renderers/table.d.ts +2 -0
  125. package/lib/typescript/module/renderers/table.d.ts.map +1 -1
  126. package/lib/typescript/module/specs/MarkdownSession.nitro.d.ts.map +1 -1
  127. package/lib/typescript/module/theme.d.ts +41 -28
  128. package/lib/typescript/module/theme.d.ts.map +1 -1
  129. package/nitrogen/generated/ios/NitroMarkdownAutolinking.swift +8 -7
  130. package/nitrogen/generated/ios/swift/HybridMarkdownSessionSpec.swift +2 -2
  131. package/package.json +1 -1
  132. package/src/MarkdownContext.ts +66 -9
  133. package/src/default-markdown-renderer.tsx +1 -6
  134. package/src/headless.ts +67 -2
  135. package/src/index.ts +24 -19
  136. package/src/markdown.tsx +158 -52
  137. package/src/renderers/blockquote.tsx +1 -2
  138. package/src/renderers/code.tsx +36 -12
  139. package/src/renderers/heading.tsx +1 -1
  140. package/src/renderers/horizontal-rule.tsx +7 -4
  141. package/src/renderers/image.tsx +59 -15
  142. package/src/renderers/link.tsx +1 -6
  143. package/src/renderers/list.tsx +15 -15
  144. package/src/renderers/math.tsx +28 -45
  145. package/src/renderers/paragraph.tsx +1 -8
  146. package/src/renderers/table.tsx +185 -160
  147. package/src/specs/MarkdownSession.nitro.ts +4 -6
  148. 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
- npx expo install react-native-nitro-markdown react-native-nitro-modules
80
- npx expo prebuild
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: Custom Renderers
103
+ ### Option 2: Light Theme / Theme Presets
104
104
 
105
- Override specific node types while keeping defaults for everything else:
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 renderers={renderers} options={{ gfm: true, math: true }}>
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
- You can easily customize the look and feel of the default components by passing a `theme` object. This allows you to match your app's brand without writing custom renderers for everything.
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
- spacing: {
148
- m: 16,
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 Branded Markdown"}</Markdown>;
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
- > **Tip:** The default theme is optimized for Dark Mode. For Light Mode, pass a custom theme object or check out the [theme source](packages/react-native-nitro-markdown/src/theme.ts) to see all available tokens.
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 4: Headless (Minimal Bundle)
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
- * Only imports the parser.
164
- * Zero UI overhead, purely synchronous AST generation.
165
- */
166
- import { parseMarkdown } from "react-native-nitro-markdown/headless";
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 5: High-Performance Streaming (LLMs)
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
- **Nitro Markdown** enables **Native Streaming** via JSI. The text buffer is maintained in C++ and updates are pushed directly to the native view, bypassing React completely.
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
- The parsing is synchronous and instant. It returns a fully typed JSON AST. We recommend using the `/headless` entry point if you only need the parser.
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 | Default | Description |
233
- | :--- | :--- | :--- | :--- |
234
- | `gfm` | `boolean` | `false` | Enable GitHub Flavored Markdown (Tables, Strikethrough, Autolinks, TaskLists). |
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. The Types are fully exported for TypeScript support.
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
- // Metadata
264
- level?: number; // Headings (1-6)
265
- href?: string; // Links
266
- checked?: boolean; // Task Lists
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, you should use a library like `react-native-math-view`, `react-native-mathjax-svg`, or `react-native-katex` inside your renderer:
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()) << "\"";