react-native-nitro-markdown 0.4.3 → 0.5.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 (175) hide show
  1. package/README.md +417 -25
  2. package/android/src/main/java/com/margelo/nitro/com/nitromarkdown/HybridMarkdownSession.kt +46 -8
  3. package/android/src/main/java/com/nitromarkdown/NitroMarkdownPackage.kt +2 -1
  4. package/cpp/bindings/HybridMarkdownParser.cpp +216 -66
  5. package/cpp/bindings/HybridMarkdownParser.hpp +2 -0
  6. package/ios/HybridMarkdownSession.swift +51 -7
  7. package/lib/commonjs/MarkdownContext.js.map +1 -1
  8. package/lib/commonjs/headless.js +61 -5
  9. package/lib/commonjs/headless.js.map +1 -1
  10. package/lib/commonjs/index.js +9 -1
  11. package/lib/commonjs/index.js.map +1 -1
  12. package/lib/commonjs/markdown-stream.js +107 -13
  13. package/lib/commonjs/markdown-stream.js.map +1 -1
  14. package/lib/commonjs/markdown.js +191 -26
  15. package/lib/commonjs/markdown.js.map +1 -1
  16. package/lib/commonjs/renderers/code.js +21 -2
  17. package/lib/commonjs/renderers/code.js.map +1 -1
  18. package/lib/commonjs/renderers/table/cell-content.js +32 -0
  19. package/lib/commonjs/renderers/table/cell-content.js.map +1 -0
  20. package/lib/commonjs/renderers/table/index.js +310 -0
  21. package/lib/commonjs/renderers/table/index.js.map +1 -0
  22. package/lib/commonjs/renderers/table/table-reducer.js +29 -0
  23. package/lib/commonjs/renderers/table/table-reducer.js.map +1 -0
  24. package/lib/commonjs/renderers/table/table-utils.js +68 -0
  25. package/lib/commonjs/renderers/table/table-utils.js.map +1 -0
  26. package/lib/commonjs/renderers/table/types.js +6 -0
  27. package/lib/commonjs/renderers/table/types.js.map +1 -0
  28. package/lib/commonjs/renderers/table.js +6 -306
  29. package/lib/commonjs/renderers/table.js.map +1 -1
  30. package/lib/commonjs/theme.js +10 -1
  31. package/lib/commonjs/theme.js.map +1 -1
  32. package/lib/commonjs/use-markdown-stream.js +9 -1
  33. package/lib/commonjs/use-markdown-stream.js.map +1 -1
  34. package/lib/commonjs/utils/code-highlight.js +101 -0
  35. package/lib/commonjs/utils/code-highlight.js.map +1 -0
  36. package/lib/commonjs/utils/incremental-ast.js +153 -0
  37. package/lib/commonjs/utils/incremental-ast.js.map +1 -0
  38. package/lib/module/MarkdownContext.js.map +1 -1
  39. package/lib/module/headless.js +56 -4
  40. package/lib/module/headless.js.map +1 -1
  41. package/lib/module/index.js +1 -0
  42. package/lib/module/index.js.map +1 -1
  43. package/lib/module/markdown-stream.js +108 -14
  44. package/lib/module/markdown-stream.js.map +1 -1
  45. package/lib/module/markdown.js +193 -28
  46. package/lib/module/markdown.js.map +1 -1
  47. package/lib/module/renderers/code.js +21 -2
  48. package/lib/module/renderers/code.js.map +1 -1
  49. package/lib/module/renderers/table/cell-content.js +27 -0
  50. package/lib/module/renderers/table/cell-content.js.map +1 -0
  51. package/lib/module/renderers/table/index.js +305 -0
  52. package/lib/module/renderers/table/index.js.map +1 -0
  53. package/lib/module/renderers/table/table-reducer.js +24 -0
  54. package/lib/module/renderers/table/table-reducer.js.map +1 -0
  55. package/lib/module/renderers/table/table-utils.js +62 -0
  56. package/lib/module/renderers/table/table-utils.js.map +1 -0
  57. package/lib/module/renderers/table/types.js +4 -0
  58. package/lib/module/renderers/table/types.js.map +1 -0
  59. package/lib/module/renderers/table.js +1 -305
  60. package/lib/module/renderers/table.js.map +1 -1
  61. package/lib/module/theme.js +10 -1
  62. package/lib/module/theme.js.map +1 -1
  63. package/lib/module/use-markdown-stream.js +9 -1
  64. package/lib/module/use-markdown-stream.js.map +1 -1
  65. package/lib/module/utils/code-highlight.js +97 -0
  66. package/lib/module/utils/code-highlight.js.map +1 -0
  67. package/lib/module/utils/incremental-ast.js +147 -0
  68. package/lib/module/utils/incremental-ast.js.map +1 -0
  69. package/lib/typescript/commonjs/Markdown.nitro.d.ts +2 -0
  70. package/lib/typescript/commonjs/Markdown.nitro.d.ts.map +1 -1
  71. package/lib/typescript/commonjs/MarkdownContext.d.ts +6 -0
  72. package/lib/typescript/commonjs/MarkdownContext.d.ts.map +1 -1
  73. package/lib/typescript/commonjs/headless.d.ts +18 -0
  74. package/lib/typescript/commonjs/headless.d.ts.map +1 -1
  75. package/lib/typescript/commonjs/index.d.ts +4 -0
  76. package/lib/typescript/commonjs/index.d.ts.map +1 -1
  77. package/lib/typescript/commonjs/markdown-stream.d.ts +6 -1
  78. package/lib/typescript/commonjs/markdown-stream.d.ts.map +1 -1
  79. package/lib/typescript/commonjs/markdown.d.ts +77 -1
  80. package/lib/typescript/commonjs/markdown.d.ts.map +1 -1
  81. package/lib/typescript/commonjs/renderers/code.d.ts.map +1 -1
  82. package/lib/typescript/commonjs/renderers/table/cell-content.d.ts +15 -0
  83. package/lib/typescript/commonjs/renderers/table/cell-content.d.ts.map +1 -0
  84. package/lib/typescript/commonjs/renderers/table/index.d.ts +11 -0
  85. package/lib/typescript/commonjs/renderers/table/index.d.ts.map +1 -0
  86. package/lib/typescript/commonjs/renderers/table/table-reducer.d.ts +5 -0
  87. package/lib/typescript/commonjs/renderers/table/table-reducer.d.ts.map +1 -0
  88. package/lib/typescript/commonjs/renderers/table/table-utils.d.ts +10 -0
  89. package/lib/typescript/commonjs/renderers/table/table-utils.d.ts.map +1 -0
  90. package/lib/typescript/commonjs/renderers/table/types.d.ts +24 -0
  91. package/lib/typescript/commonjs/renderers/table/types.d.ts.map +1 -0
  92. package/lib/typescript/commonjs/renderers/table.d.ts +1 -11
  93. package/lib/typescript/commonjs/renderers/table.d.ts.map +1 -1
  94. package/lib/typescript/commonjs/specs/MarkdownSession.nitro.d.ts +14 -2
  95. package/lib/typescript/commonjs/specs/MarkdownSession.nitro.d.ts.map +1 -1
  96. package/lib/typescript/commonjs/theme.d.ts +18 -2
  97. package/lib/typescript/commonjs/theme.d.ts.map +1 -1
  98. package/lib/typescript/commonjs/use-markdown-stream.d.ts +4 -0
  99. package/lib/typescript/commonjs/use-markdown-stream.d.ts.map +1 -1
  100. package/lib/typescript/commonjs/utils/code-highlight.d.ts +8 -0
  101. package/lib/typescript/commonjs/utils/code-highlight.d.ts.map +1 -0
  102. package/lib/typescript/commonjs/utils/incremental-ast.d.ts +12 -0
  103. package/lib/typescript/commonjs/utils/incremental-ast.d.ts.map +1 -0
  104. package/lib/typescript/module/Markdown.nitro.d.ts +2 -0
  105. package/lib/typescript/module/Markdown.nitro.d.ts.map +1 -1
  106. package/lib/typescript/module/MarkdownContext.d.ts +6 -0
  107. package/lib/typescript/module/MarkdownContext.d.ts.map +1 -1
  108. package/lib/typescript/module/headless.d.ts +18 -0
  109. package/lib/typescript/module/headless.d.ts.map +1 -1
  110. package/lib/typescript/module/index.d.ts +4 -0
  111. package/lib/typescript/module/index.d.ts.map +1 -1
  112. package/lib/typescript/module/markdown-stream.d.ts +6 -1
  113. package/lib/typescript/module/markdown-stream.d.ts.map +1 -1
  114. package/lib/typescript/module/markdown.d.ts +77 -1
  115. package/lib/typescript/module/markdown.d.ts.map +1 -1
  116. package/lib/typescript/module/renderers/code.d.ts.map +1 -1
  117. package/lib/typescript/module/renderers/table/cell-content.d.ts +15 -0
  118. package/lib/typescript/module/renderers/table/cell-content.d.ts.map +1 -0
  119. package/lib/typescript/module/renderers/table/index.d.ts +11 -0
  120. package/lib/typescript/module/renderers/table/index.d.ts.map +1 -0
  121. package/lib/typescript/module/renderers/table/table-reducer.d.ts +5 -0
  122. package/lib/typescript/module/renderers/table/table-reducer.d.ts.map +1 -0
  123. package/lib/typescript/module/renderers/table/table-utils.d.ts +10 -0
  124. package/lib/typescript/module/renderers/table/table-utils.d.ts.map +1 -0
  125. package/lib/typescript/module/renderers/table/types.d.ts +24 -0
  126. package/lib/typescript/module/renderers/table/types.d.ts.map +1 -0
  127. package/lib/typescript/module/renderers/table.d.ts +1 -11
  128. package/lib/typescript/module/renderers/table.d.ts.map +1 -1
  129. package/lib/typescript/module/specs/MarkdownSession.nitro.d.ts +14 -2
  130. package/lib/typescript/module/specs/MarkdownSession.nitro.d.ts.map +1 -1
  131. package/lib/typescript/module/theme.d.ts +18 -2
  132. package/lib/typescript/module/theme.d.ts.map +1 -1
  133. package/lib/typescript/module/use-markdown-stream.d.ts +4 -0
  134. package/lib/typescript/module/use-markdown-stream.d.ts.map +1 -1
  135. package/lib/typescript/module/utils/code-highlight.d.ts +8 -0
  136. package/lib/typescript/module/utils/code-highlight.d.ts.map +1 -0
  137. package/lib/typescript/module/utils/incremental-ast.d.ts +12 -0
  138. package/lib/typescript/module/utils/incremental-ast.d.ts.map +1 -0
  139. package/nitrogen/generated/android/NitroMarkdownOnLoad.cpp +38 -26
  140. package/nitrogen/generated/android/NitroMarkdownOnLoad.hpp +13 -4
  141. package/nitrogen/generated/android/c++/JFunc_void_double_double.hpp +75 -0
  142. package/nitrogen/generated/android/c++/JHybridMarkdownSessionSpec.cpp +49 -34
  143. package/nitrogen/generated/android/c++/JHybridMarkdownSessionSpec.hpp +25 -24
  144. package/nitrogen/generated/android/kotlin/com/margelo/nitro/com/nitromarkdown/Func_void_double_double.kt +80 -0
  145. package/nitrogen/generated/android/kotlin/com/margelo/nitro/com/nitromarkdown/HybridMarkdownSessionSpec.kt +34 -21
  146. package/nitrogen/generated/ios/NitroMarkdown-Swift-Cxx-Bridge.cpp +8 -0
  147. package/nitrogen/generated/ios/NitroMarkdown-Swift-Cxx-Bridge.hpp +31 -0
  148. package/nitrogen/generated/ios/c++/HybridMarkdownSessionSpecSwift.hpp +34 -2
  149. package/nitrogen/generated/ios/swift/Func_void_double_double.swift +46 -0
  150. package/nitrogen/generated/ios/swift/HybridMarkdownSessionSpec.swift +6 -2
  151. package/nitrogen/generated/ios/swift/HybridMarkdownSessionSpec_cxx.swift +57 -9
  152. package/nitrogen/generated/shared/c++/HybridMarkdownParserSpec.cpp +2 -0
  153. package/nitrogen/generated/shared/c++/HybridMarkdownParserSpec.hpp +2 -0
  154. package/nitrogen/generated/shared/c++/HybridMarkdownSessionSpec.cpp +4 -0
  155. package/nitrogen/generated/shared/c++/HybridMarkdownSessionSpec.hpp +6 -2
  156. package/package.json +9 -5
  157. package/react-native-nitro-markdown.podspec +1 -1
  158. package/src/Markdown.nitro.ts +2 -0
  159. package/src/MarkdownContext.ts +6 -0
  160. package/src/headless.ts +54 -4
  161. package/src/index.ts +10 -0
  162. package/src/markdown-stream.tsx +163 -15
  163. package/src/markdown.tsx +381 -26
  164. package/src/renderers/code.tsx +32 -3
  165. package/src/renderers/table/cell-content.tsx +38 -0
  166. package/src/renderers/table/index.tsx +419 -0
  167. package/src/renderers/table/table-reducer.ts +36 -0
  168. package/src/renderers/table/table-utils.ts +81 -0
  169. package/src/renderers/table/types.ts +24 -0
  170. package/src/renderers/table.tsx +1 -401
  171. package/src/specs/MarkdownSession.nitro.ts +16 -2
  172. package/src/theme.ts +29 -1
  173. package/src/use-markdown-stream.ts +10 -0
  174. package/src/utils/code-highlight.ts +102 -0
  175. package/src/utils/incremental-ast.ts +224 -0
@@ -0,0 +1,224 @@
1
+ import {
2
+ parseMarkdown,
3
+ parseMarkdownWithOptions,
4
+ type MarkdownNode,
5
+ } from "../headless";
6
+ import type { ParserOptions } from "../Markdown.nitro";
7
+
8
+ const PLAIN_TEXT_APPEND_PATTERN = /[`*_~[\]#!<>()|$\n\r]/;
9
+ const FENCE_LINE_PATTERN = /^ {0,3}(```+|~~~+)/;
10
+
11
+ const parseAst = (text: string, options?: ParserOptions): MarkdownNode => {
12
+ if (options) {
13
+ return parseMarkdownWithOptions(text, options);
14
+ }
15
+ return parseMarkdown(text);
16
+ };
17
+
18
+ const isInsideFencedCodeBlock = (text: string): boolean => {
19
+ const lines = text.split(/\r?\n/);
20
+ let openFenceChar: "`" | "~" | null = null;
21
+ let openFenceLength = 0;
22
+
23
+ for (const line of lines) {
24
+ const fenceMatch = line.match(FENCE_LINE_PATTERN);
25
+ if (!fenceMatch) continue;
26
+
27
+ const marker = fenceMatch[1];
28
+ const markerChar = marker[0] as "`" | "~";
29
+ const markerLength = marker.length;
30
+
31
+ if (!openFenceChar) {
32
+ openFenceChar = markerChar;
33
+ openFenceLength = markerLength;
34
+ continue;
35
+ }
36
+
37
+ if (markerChar === openFenceChar && markerLength >= openFenceLength) {
38
+ openFenceChar = null;
39
+ openFenceLength = 0;
40
+ }
41
+ }
42
+
43
+ return openFenceChar !== null;
44
+ };
45
+
46
+ const containsFenceLine = (text: string): boolean => {
47
+ return text.split(/\r?\n/).some((line) => FENCE_LINE_PATTERN.test(line));
48
+ };
49
+
50
+ const getTrailingLine = (text: string): string => {
51
+ const lastLineBreak = Math.max(
52
+ text.lastIndexOf("\n"),
53
+ text.lastIndexOf("\r"),
54
+ );
55
+ if (lastLineBreak === -1) return text;
56
+ return text.slice(lastLineBreak + 1);
57
+ };
58
+
59
+ const getLeadingLine = (text: string): string => {
60
+ const newlineIndex = text.indexOf("\n");
61
+ const carriageReturnIndex = text.indexOf("\r");
62
+
63
+ const hasNewline = newlineIndex !== -1;
64
+ const hasCarriageReturn = carriageReturnIndex !== -1;
65
+
66
+ if (!hasNewline && !hasCarriageReturn) return text;
67
+ if (!hasNewline) return text.slice(0, carriageReturnIndex);
68
+ if (!hasCarriageReturn) return text.slice(0, newlineIndex);
69
+
70
+ return text.slice(0, Math.min(newlineIndex, carriageReturnIndex));
71
+ };
72
+
73
+ const hasSplitFenceBoundary = (
74
+ previousText: string,
75
+ appendedChunk: string,
76
+ ): boolean => {
77
+ if (appendedChunk.length === 0) return false;
78
+
79
+ const candidateLine = `${getTrailingLine(previousText)}${getLeadingLine(
80
+ appendedChunk,
81
+ )}`;
82
+ if (candidateLine.length === 0) return false;
83
+
84
+ return FENCE_LINE_PATTERN.test(candidateLine);
85
+ };
86
+
87
+ const findTrailingLeafPath = (
88
+ node: MarkdownNode,
89
+ path: number[] = [],
90
+ ): number[] => {
91
+ const children = node.children;
92
+ if (!children || children.length === 0) {
93
+ return path;
94
+ }
95
+
96
+ const lastIndex = children.length - 1;
97
+ return findTrailingLeafPath(children[lastIndex], [...path, lastIndex]);
98
+ };
99
+
100
+ const getNodeAtPath = (
101
+ node: MarkdownNode,
102
+ path: readonly number[],
103
+ ): MarkdownNode | null => {
104
+ let current: MarkdownNode = node;
105
+ for (const index of path) {
106
+ const child = current.children?.[index];
107
+ if (!child) return null;
108
+ current = child;
109
+ }
110
+ return current;
111
+ };
112
+
113
+ const appendPlainTextToAst = (
114
+ ast: MarkdownNode,
115
+ appendedChunk: string,
116
+ previousTextLength: number,
117
+ ): MarkdownNode | null => {
118
+ if (appendedChunk.length === 0) return ast;
119
+ const path = findTrailingLeafPath(ast);
120
+ const leaf = getNodeAtPath(ast, path);
121
+ if (leaf?.type !== "text") return null;
122
+ if (typeof leaf.end !== "number" || leaf.end !== previousTextLength) {
123
+ return null;
124
+ }
125
+
126
+ const delta = appendedChunk.length;
127
+ const update = (node: MarkdownNode, depth: number): MarkdownNode => {
128
+ if (depth === path.length) {
129
+ return {
130
+ ...node,
131
+ content: (node.content ?? "") + appendedChunk,
132
+ end: typeof node.end === "number" ? node.end + delta : node.end,
133
+ };
134
+ }
135
+
136
+ const childIndex = path[depth];
137
+ const children = node.children?.map((child, index) =>
138
+ index === childIndex ? update(child, depth + 1) : child,
139
+ );
140
+
141
+ return {
142
+ ...node,
143
+ end: typeof node.end === "number" ? node.end + delta : node.end,
144
+ children,
145
+ };
146
+ };
147
+
148
+ return update(ast, 0);
149
+ };
150
+
151
+ const endsAtBlockBoundary = (text: string): boolean => {
152
+ return text.endsWith("\n") || text.endsWith("\r");
153
+ };
154
+
155
+ export type IncrementalAstInput = {
156
+ allowIncremental?: boolean;
157
+ nextText: string;
158
+ options?: ParserOptions;
159
+ previousAst: MarkdownNode;
160
+ previousText: string;
161
+ };
162
+
163
+ export const getNextStreamAst = ({
164
+ allowIncremental = true,
165
+ nextText,
166
+ options,
167
+ previousAst,
168
+ previousText,
169
+ }: IncrementalAstInput): MarkdownNode => {
170
+ if (!allowIncremental || !nextText.startsWith(previousText)) {
171
+ return parseAst(nextText, options);
172
+ }
173
+
174
+ const appendedChunk = nextText.slice(previousText.length);
175
+ if (appendedChunk.length === 0) {
176
+ return previousAst;
177
+ }
178
+
179
+ const insideFencedCodeBlock = isInsideFencedCodeBlock(previousText);
180
+ const hasFenceBoundary =
181
+ containsFenceLine(appendedChunk) ||
182
+ hasSplitFenceBoundary(previousText, appendedChunk);
183
+
184
+ if (insideFencedCodeBlock && !hasFenceBoundary) {
185
+ const fencedTextAppendAst = appendPlainTextToAst(
186
+ previousAst,
187
+ appendedChunk,
188
+ previousText.length,
189
+ );
190
+ if (fencedTextAppendAst) {
191
+ return fencedTextAppendAst;
192
+ }
193
+ }
194
+
195
+ if (!PLAIN_TEXT_APPEND_PATTERN.test(appendedChunk)) {
196
+ if (endsAtBlockBoundary(previousText)) {
197
+ return parseAst(nextText, options);
198
+ }
199
+
200
+ const textAppendedAst = appendPlainTextToAst(
201
+ previousAst,
202
+ appendedChunk,
203
+ previousText.length,
204
+ );
205
+ if (textAppendedAst) {
206
+ return textAppendedAst;
207
+ }
208
+ }
209
+
210
+ if (insideFencedCodeBlock) {
211
+ return parseAst(nextText, options);
212
+ }
213
+
214
+ // Correctness-first fallback: full reparse for all non-trivial appends.
215
+ // Incremental append is only used for plain text chunks at the true trailing leaf.
216
+ return parseAst(nextText, options);
217
+ };
218
+
219
+ export const parseMarkdownAst = (
220
+ text: string,
221
+ options?: ParserOptions,
222
+ ): MarkdownNode => {
223
+ return parseAst(text, options);
224
+ };