react-native-marked 8.1.1 → 8.2.0

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 (70) hide show
  1. package/LICENSE +20 -20
  2. package/README.md +354 -354
  3. package/dist/commonjs/components/MDImage.js +3 -3
  4. package/dist/commonjs/components/MDImage.js.map +1 -1
  5. package/dist/commonjs/components/MDList.js.map +1 -1
  6. package/dist/commonjs/components/MDSvg.js.map +1 -1
  7. package/dist/commonjs/components/MDTable.js.map +1 -1
  8. package/dist/commonjs/hooks/useMarkdown.js.map +1 -1
  9. package/dist/commonjs/hooks/useMarkdownWithComponents.js.map +1 -1
  10. package/dist/commonjs/index.js.map +1 -1
  11. package/dist/commonjs/lib/Markdown.js.map +1 -1
  12. package/dist/commonjs/lib/Parser.js +4 -4
  13. package/dist/commonjs/lib/Parser.js.map +1 -1
  14. package/dist/commonjs/lib/ReactComponentRegistry.js.map +1 -1
  15. package/dist/commonjs/lib/ReactComponentTokenizer.js.map +1 -1
  16. package/dist/commonjs/lib/Renderer.js.map +1 -1
  17. package/dist/commonjs/lib/types.js.map +1 -1
  18. package/dist/commonjs/theme/colors.js.map +1 -1
  19. package/dist/commonjs/theme/spacing.js.map +1 -1
  20. package/dist/commonjs/theme/styles.js.map +1 -1
  21. package/dist/commonjs/theme/types.js.map +1 -1
  22. package/dist/commonjs/utils/handlers.js.map +1 -1
  23. package/dist/commonjs/utils/svg.js.map +1 -1
  24. package/dist/commonjs/utils/table.js.map +1 -1
  25. package/dist/commonjs/utils/url.js.map +1 -1
  26. package/dist/module/components/MDImage.js +3 -3
  27. package/dist/module/components/MDImage.js.map +1 -1
  28. package/dist/module/components/MDList.js.map +1 -1
  29. package/dist/module/components/MDSvg.js.map +1 -1
  30. package/dist/module/components/MDTable.js.map +1 -1
  31. package/dist/module/hooks/useMarkdown.js.map +1 -1
  32. package/dist/module/hooks/useMarkdownWithComponents.js.map +1 -1
  33. package/dist/module/index.js.map +1 -1
  34. package/dist/module/lib/Markdown.js.map +1 -1
  35. package/dist/module/lib/Parser.js +4 -4
  36. package/dist/module/lib/Parser.js.map +1 -1
  37. package/dist/module/lib/ReactComponentRegistry.js.map +1 -1
  38. package/dist/module/lib/ReactComponentTokenizer.js.map +1 -1
  39. package/dist/module/lib/Renderer.js.map +1 -1
  40. package/dist/module/lib/types.js.map +1 -1
  41. package/dist/module/theme/colors.js.map +1 -1
  42. package/dist/module/theme/spacing.js.map +1 -1
  43. package/dist/module/theme/styles.js.map +1 -1
  44. package/dist/module/theme/types.js.map +1 -1
  45. package/dist/module/utils/handlers.js.map +1 -1
  46. package/dist/module/utils/svg.js.map +1 -1
  47. package/dist/module/utils/table.js.map +1 -1
  48. package/dist/module/utils/url.js.map +1 -1
  49. package/package.json +175 -175
  50. package/src/components/MDImage.tsx +90 -90
  51. package/src/components/MDList.tsx +46 -46
  52. package/src/components/MDSvg.tsx +108 -108
  53. package/src/components/MDTable.tsx +60 -60
  54. package/src/hooks/useMarkdown.ts +51 -51
  55. package/src/hooks/useMarkdownWithComponents.tsx +89 -89
  56. package/src/index.ts +43 -43
  57. package/src/lib/Markdown.tsx +53 -53
  58. package/src/lib/Parser.tsx +316 -316
  59. package/src/lib/ReactComponentRegistry.tsx +52 -52
  60. package/src/lib/ReactComponentTokenizer.ts +149 -149
  61. package/src/lib/Renderer.tsx +238 -238
  62. package/src/lib/types.ts +87 -87
  63. package/src/theme/colors.ts +31 -31
  64. package/src/theme/spacing.ts +10 -10
  65. package/src/theme/styles.ts +198 -198
  66. package/src/theme/types.ts +33 -33
  67. package/src/utils/handlers.ts +9 -9
  68. package/src/utils/svg.ts +14 -14
  69. package/src/utils/table.ts +29 -29
  70. package/src/utils/url.ts +22 -22
@@ -1,316 +1,316 @@
1
- import { decode } from "html-entities";
2
- import type { Token, Tokens } from "marked";
3
- import type { ReactNode } from "react";
4
- import type { ImageStyle, TextStyle, ViewStyle } from "react-native";
5
- import type { MarkedStyles } from "../theme/types";
6
- import { getTableColAlignmentStyle } from "./../utils/table";
7
- import { getValidURL } from "./../utils/url";
8
- import type { ParserOptions, RendererInterface } from "./types";
9
-
10
- class Parser {
11
- private renderer: RendererInterface;
12
- private styles: MarkedStyles;
13
- private headingStylesMap: Record<number, TextStyle | undefined>;
14
- private baseUrl: string;
15
-
16
- constructor(options: ParserOptions) {
17
- this.styles = { ...options.styles };
18
- this.baseUrl = options.baseUrl ?? "";
19
- this.renderer = options.renderer;
20
- this.headingStylesMap = {
21
- 1: this.styles.h1,
22
- 2: this.styles.h2,
23
- 3: this.styles.h3,
24
- 4: this.styles.h4,
25
- 5: this.styles.h5,
26
- 6: this.styles.h6,
27
- };
28
- }
29
-
30
- parse(tokens?: Token[]) {
31
- return this._parse(tokens);
32
- }
33
-
34
- private _parse(
35
- tokens?: Token[],
36
- styles?: ViewStyle | TextStyle | ImageStyle,
37
- ): ReactNode[] {
38
- if (!tokens) return [];
39
-
40
- const elements: ReactNode[] = tokens.map((token) => {
41
- return this._parseToken(token, styles);
42
- });
43
- return elements.filter((element) => element !== null);
44
- }
45
-
46
- private _parseToken(
47
- token: Token,
48
- styles?: ViewStyle | TextStyle | ImageStyle,
49
- ): ReactNode {
50
- switch (token.type) {
51
- case "paragraph": {
52
- const children = this.getNormalizedSiblingNodesForBlockAndInlineTokens(
53
- token.tokens ?? [],
54
- this.styles.text,
55
- );
56
-
57
- return this.renderer.paragraph(children, this.styles.paragraph);
58
- }
59
- case "blockquote": {
60
- const children = this.parse(token.tokens);
61
- return this.renderer.blockquote(children, this.styles.blockquote);
62
- }
63
- case "heading": {
64
- const styles = this.headingStylesMap[token.depth];
65
-
66
- if (this.hasDuplicateTextChildToken(token)) {
67
- return this.renderer.heading(token.text, styles, token.depth);
68
- }
69
-
70
- const children = this._parse(token.tokens, styles);
71
- return this.renderer.heading(children, styles, token.depth);
72
- }
73
- case "code": {
74
- return this.renderer.code(
75
- token.text,
76
- token.lang,
77
- this.styles.code,
78
- this.styles.em,
79
- );
80
- }
81
- case "hr": {
82
- return this.renderer.hr(this.styles.hr);
83
- }
84
- case "list": {
85
- let startIndex = Number.parseInt(token.start.toString(), 10);
86
- if (Number.isNaN(startIndex)) {
87
- startIndex = 1;
88
- }
89
- const li = (token as Tokens.List).items.map((item) => {
90
- const children = item.tokens.flatMap((cItem) => {
91
- if (cItem.type === "text") {
92
- /* getViewNode since tokens could contain a block like elements (i.e. img) */
93
- const childTokens = (cItem as Tokens.Text).tokens || [];
94
- const listChildren =
95
- this.getNormalizedSiblingNodesForBlockAndInlineTokens(
96
- childTokens,
97
- this.styles.li,
98
- );
99
- // return this.renderer.listItem(listChildren, this.styles.li);
100
- return listChildren;
101
- }
102
-
103
- /* Parse the nested token */
104
- return this._parseToken(cItem);
105
- });
106
-
107
- return this.renderer.listItem(children, this.styles.li);
108
- });
109
-
110
- return this.renderer.list(
111
- token.ordered,
112
- li,
113
- this.styles.list,
114
- this.styles.li,
115
- startIndex,
116
- );
117
- }
118
- case "escape": {
119
- return this.renderer.escape(token.text, {
120
- ...this.styles.text,
121
- ...styles,
122
- });
123
- }
124
- case "link": {
125
- // Don't render anchors without text and children
126
- if (token.text.trim().length < 1 || !token.tokens) {
127
- return null;
128
- }
129
-
130
- // Note: Linking Images (https://www.markdownguide.org/basic-syntax/#linking-images) are wrapped
131
- // in paragraph token, so will be handled via `getNormalizedSiblingNodesForBlockAndInlineTokens`
132
- const linkStyle = {
133
- ...this.styles.link,
134
- ...styles,
135
- // To override color and fontStyle properties
136
- color: this.styles.link?.color,
137
- fontStyle: this.styles.link?.fontStyle,
138
- };
139
- const href = getValidURL(this.baseUrl, token.href);
140
-
141
- if (this.hasDuplicateTextChildToken(token)) {
142
- return this.renderer.link(token.text, href, linkStyle, token.title);
143
- }
144
-
145
- const children = this._parse(token.tokens, linkStyle);
146
- return this.renderer.link(children, href, linkStyle, token.title);
147
- }
148
- case "image": {
149
- return this.renderer.image(
150
- token.href,
151
- token.text,
152
- this.styles.image,
153
- token.title,
154
- );
155
- }
156
- case "strong": {
157
- const boldStyle = {
158
- ...this.styles.strong,
159
- ...styles,
160
- };
161
- if (this.hasDuplicateTextChildToken(token)) {
162
- return this.renderer.strong(token.text, boldStyle);
163
- }
164
-
165
- const children = this._parse(token.tokens, boldStyle);
166
- return this.renderer.strong(children, boldStyle);
167
- }
168
- case "em": {
169
- const italicStyle = {
170
- ...this.styles.em,
171
- ...styles,
172
- };
173
- if (this.hasDuplicateTextChildToken(token)) {
174
- return this.renderer.em(token.text, italicStyle);
175
- }
176
-
177
- const children = this._parse(token.tokens, italicStyle);
178
- return this.renderer.em(children, italicStyle);
179
- }
180
- case "codespan": {
181
- return this.renderer.codespan(decode(token.text), {
182
- ...this.styles.codespan,
183
- ...styles,
184
- });
185
- }
186
- case "br": {
187
- return this.renderer.br();
188
- }
189
- case "del": {
190
- const strikethroughStyle = {
191
- ...this.styles.strikethrough,
192
- ...styles,
193
- };
194
- if (this.hasDuplicateTextChildToken(token)) {
195
- return this.renderer.del(token.text, strikethroughStyle);
196
- }
197
-
198
- const children = this._parse(token.tokens, strikethroughStyle);
199
- return this.renderer.del(children, strikethroughStyle);
200
- }
201
- case "text":
202
- return this.renderer.text(token.raw, {
203
- ...this.styles.text,
204
- ...styles,
205
- });
206
- case "html": {
207
- return this.renderer.html(token.raw, {
208
- ...this.styles.text,
209
- ...styles,
210
- });
211
- }
212
- case "table": {
213
- const header = (token as Tokens.Table).header.map((row, i) =>
214
- this._parse(row.tokens, {
215
- ...getTableColAlignmentStyle(token.align[i]),
216
- }),
217
- );
218
-
219
- const rows = (token as Tokens.Table).rows.map((cols) =>
220
- cols.map((col, i) =>
221
- this._parse(col.tokens, {
222
- ...getTableColAlignmentStyle(token.align[i]),
223
- }),
224
- ),
225
- );
226
-
227
- return this.renderer.table(
228
- header,
229
- rows,
230
- this.styles.table,
231
- this.styles.tableRow,
232
- this.styles.tableCell,
233
- );
234
- }
235
- default: {
236
- return null;
237
- }
238
- }
239
- }
240
-
241
- private getNormalizedSiblingNodesForBlockAndInlineTokens(
242
- tokens: Token[],
243
- textStyle?: TextStyle,
244
- ): ReactNode[] {
245
- let tokenRenderQueue: Token[] = [];
246
- const siblingNodes: ReactNode[] = [];
247
- for (const t of tokens) {
248
- /**
249
- * To avoid inlining images
250
- * Currently supports images, link images
251
- * Note: to be extend for other token types
252
- */
253
- if (
254
- t.type === "image" ||
255
- (t.type === "link" &&
256
- t.tokens &&
257
- t.tokens[0] &&
258
- t.tokens[0].type === "image")
259
- ) {
260
- // Render existing inline tokens in the queue
261
- const parsed = this._parse(tokenRenderQueue);
262
- if (parsed.length > 0) {
263
- siblingNodes.push(this.renderer.text(parsed, textStyle));
264
- }
265
-
266
- // Render the current block token
267
- if (t.type === "image") {
268
- siblingNodes.push(this._parseToken(t));
269
- } else if (t.type === "link" && t.tokens && t.tokens[0]) {
270
- const imageToken = t.tokens[0] as Tokens.Image;
271
- const href = getValidURL(this.baseUrl, t.href);
272
- siblingNodes.push(
273
- this.renderer.linkImage(
274
- href,
275
- imageToken.href,
276
- imageToken.text ?? imageToken.title ?? "",
277
- this.styles.image,
278
- imageToken.title,
279
- ),
280
- );
281
- }
282
-
283
- tokenRenderQueue = [];
284
- continue;
285
- }
286
- tokenRenderQueue = [...tokenRenderQueue, t];
287
- }
288
-
289
- /* Remaining temp tokens if any */
290
- if (tokenRenderQueue.length > 0) {
291
- siblingNodes.push(this.renderer.text(this.parse(tokenRenderQueue), {}));
292
- }
293
-
294
- return siblingNodes;
295
- }
296
-
297
- // To avoid duplicate text node nesting when there are no child tokens with text emphasis (i.e., italic)
298
- // ref: https://github.com/gmsgowtham/react-native-marked/issues/522
299
- private hasDuplicateTextChildToken(token: Token): boolean {
300
- if (!("tokens" in token)) {
301
- return false;
302
- }
303
-
304
- if (
305
- token.tokens &&
306
- token.tokens.length === 1 &&
307
- token.tokens[0]?.type === "text"
308
- ) {
309
- return true;
310
- }
311
-
312
- return false;
313
- }
314
- }
315
-
316
- export default Parser;
1
+ import { decode } from "html-entities";
2
+ import type { Token, Tokens } from "marked";
3
+ import type { ReactNode } from "react";
4
+ import type { ImageStyle, TextStyle, ViewStyle } from "react-native";
5
+ import type { MarkedStyles } from "../theme/types";
6
+ import { getTableColAlignmentStyle } from "./../utils/table";
7
+ import { getValidURL } from "./../utils/url";
8
+ import type { ParserOptions, RendererInterface } from "./types";
9
+
10
+ class Parser {
11
+ private renderer: RendererInterface;
12
+ private styles: MarkedStyles;
13
+ private headingStylesMap: Record<number, TextStyle | undefined>;
14
+ private baseUrl: string;
15
+
16
+ constructor(options: ParserOptions) {
17
+ this.styles = { ...options.styles };
18
+ this.baseUrl = options.baseUrl ?? "";
19
+ this.renderer = options.renderer;
20
+ this.headingStylesMap = {
21
+ 1: this.styles.h1,
22
+ 2: this.styles.h2,
23
+ 3: this.styles.h3,
24
+ 4: this.styles.h4,
25
+ 5: this.styles.h5,
26
+ 6: this.styles.h6,
27
+ };
28
+ }
29
+
30
+ parse(tokens?: Token[]) {
31
+ return this._parse(tokens);
32
+ }
33
+
34
+ private _parse(
35
+ tokens?: Token[],
36
+ styles?: ViewStyle | TextStyle | ImageStyle,
37
+ ): ReactNode[] {
38
+ if (!tokens) return [];
39
+
40
+ const elements: ReactNode[] = tokens.map((token) => {
41
+ return this._parseToken(token, styles);
42
+ });
43
+ return elements.filter((element) => element !== null);
44
+ }
45
+
46
+ private _parseToken(
47
+ token: Token,
48
+ styles?: ViewStyle | TextStyle | ImageStyle,
49
+ ): ReactNode {
50
+ switch (token.type) {
51
+ case "paragraph": {
52
+ const children = this.getNormalizedSiblingNodesForBlockAndInlineTokens(
53
+ token.tokens ?? [],
54
+ this.styles.text,
55
+ );
56
+
57
+ return this.renderer.paragraph(children, this.styles.paragraph);
58
+ }
59
+ case "blockquote": {
60
+ const children = this.parse(token.tokens);
61
+ return this.renderer.blockquote(children, this.styles.blockquote);
62
+ }
63
+ case "heading": {
64
+ const styles = this.headingStylesMap[token.depth];
65
+
66
+ if (this.hasDuplicateTextChildToken(token)) {
67
+ return this.renderer.heading(token.text, styles, token.depth);
68
+ }
69
+
70
+ const children = this._parse(token.tokens, styles);
71
+ return this.renderer.heading(children, styles, token.depth);
72
+ }
73
+ case "code": {
74
+ return this.renderer.code(
75
+ token.text,
76
+ token.lang,
77
+ this.styles.code,
78
+ this.styles.em,
79
+ );
80
+ }
81
+ case "hr": {
82
+ return this.renderer.hr(this.styles.hr);
83
+ }
84
+ case "list": {
85
+ let startIndex = Number.parseInt(token.start.toString(), 10);
86
+ if (Number.isNaN(startIndex)) {
87
+ startIndex = 1;
88
+ }
89
+ const li = (token as Tokens.List).items.map((item) => {
90
+ const children = item.tokens.flatMap((cItem) => {
91
+ if (cItem.type === "text") {
92
+ /* getViewNode since tokens could contain a block like elements (i.e. img) */
93
+ const childTokens = (cItem as Tokens.Text).tokens || [];
94
+ const listChildren =
95
+ this.getNormalizedSiblingNodesForBlockAndInlineTokens(
96
+ childTokens,
97
+ this.styles.li,
98
+ );
99
+ // return this.renderer.listItem(listChildren, this.styles.li);
100
+ return listChildren;
101
+ }
102
+
103
+ /* Parse the nested token */
104
+ return this._parseToken(cItem);
105
+ });
106
+
107
+ return this.renderer.listItem(children, this.styles.li);
108
+ });
109
+
110
+ return this.renderer.list(
111
+ token.ordered,
112
+ li,
113
+ this.styles.list,
114
+ this.styles.li,
115
+ startIndex,
116
+ );
117
+ }
118
+ case "escape": {
119
+ return this.renderer.escape(token.text, {
120
+ ...this.styles.text,
121
+ ...styles,
122
+ });
123
+ }
124
+ case "link": {
125
+ // Don't render anchors without text and children
126
+ if (token.text.trim().length < 1 || !token.tokens) {
127
+ return null;
128
+ }
129
+
130
+ // Note: Linking Images (https://www.markdownguide.org/basic-syntax/#linking-images) are wrapped
131
+ // in paragraph token, so will be handled via `getNormalizedSiblingNodesForBlockAndInlineTokens`
132
+ const linkStyle = {
133
+ ...this.styles.link,
134
+ ...styles,
135
+ // To override color and fontStyle properties
136
+ color: this.styles.link?.color,
137
+ fontStyle: this.styles.link?.fontStyle,
138
+ };
139
+ const href = getValidURL(this.baseUrl, token.href);
140
+
141
+ if (this.hasDuplicateTextChildToken(token)) {
142
+ return this.renderer.link(token.text, href, linkStyle, token.title);
143
+ }
144
+
145
+ const children = this._parse(token.tokens, linkStyle);
146
+ return this.renderer.link(children, href, linkStyle, token.title);
147
+ }
148
+ case "image": {
149
+ return this.renderer.image(
150
+ token.href,
151
+ token.text,
152
+ this.styles.image,
153
+ token.title,
154
+ );
155
+ }
156
+ case "strong": {
157
+ const boldStyle = {
158
+ ...this.styles.strong,
159
+ ...styles,
160
+ };
161
+ if (this.hasDuplicateTextChildToken(token)) {
162
+ return this.renderer.strong(token.text, boldStyle);
163
+ }
164
+
165
+ const children = this._parse(token.tokens, boldStyle);
166
+ return this.renderer.strong(children, boldStyle);
167
+ }
168
+ case "em": {
169
+ const italicStyle = {
170
+ ...this.styles.em,
171
+ ...styles,
172
+ };
173
+ if (this.hasDuplicateTextChildToken(token)) {
174
+ return this.renderer.em(token.text, italicStyle);
175
+ }
176
+
177
+ const children = this._parse(token.tokens, italicStyle);
178
+ return this.renderer.em(children, italicStyle);
179
+ }
180
+ case "codespan": {
181
+ return this.renderer.codespan(decode(token.text), {
182
+ ...this.styles.codespan,
183
+ ...styles,
184
+ });
185
+ }
186
+ case "br": {
187
+ return this.renderer.br();
188
+ }
189
+ case "del": {
190
+ const strikethroughStyle = {
191
+ ...this.styles.strikethrough,
192
+ ...styles,
193
+ };
194
+ if (this.hasDuplicateTextChildToken(token)) {
195
+ return this.renderer.del(token.text, strikethroughStyle);
196
+ }
197
+
198
+ const children = this._parse(token.tokens, strikethroughStyle);
199
+ return this.renderer.del(children, strikethroughStyle);
200
+ }
201
+ case "text":
202
+ return this.renderer.text(token.raw, {
203
+ ...this.styles.text,
204
+ ...styles,
205
+ });
206
+ case "html": {
207
+ return this.renderer.html(token.raw, {
208
+ ...this.styles.text,
209
+ ...styles,
210
+ });
211
+ }
212
+ case "table": {
213
+ const header = (token as Tokens.Table).header.map((row, i) =>
214
+ this._parse(row.tokens, {
215
+ ...getTableColAlignmentStyle(token.align[i]),
216
+ }),
217
+ );
218
+
219
+ const rows = (token as Tokens.Table).rows.map((cols) =>
220
+ cols.map((col, i) =>
221
+ this._parse(col.tokens, {
222
+ ...getTableColAlignmentStyle(token.align[i]),
223
+ }),
224
+ ),
225
+ );
226
+
227
+ return this.renderer.table(
228
+ header,
229
+ rows,
230
+ this.styles.table,
231
+ this.styles.tableRow,
232
+ this.styles.tableCell,
233
+ );
234
+ }
235
+ default: {
236
+ return null;
237
+ }
238
+ }
239
+ }
240
+
241
+ private getNormalizedSiblingNodesForBlockAndInlineTokens(
242
+ tokens: Token[],
243
+ textStyle?: TextStyle,
244
+ ): ReactNode[] {
245
+ let tokenRenderQueue: Token[] = [];
246
+ const siblingNodes: ReactNode[] = [];
247
+ for (const t of tokens) {
248
+ /**
249
+ * To avoid inlining images
250
+ * Currently supports images, link images
251
+ * Note: to be extend for other token types
252
+ */
253
+ if (
254
+ t.type === "image" ||
255
+ (t.type === "link" &&
256
+ t.tokens &&
257
+ t.tokens[0] &&
258
+ t.tokens[0].type === "image")
259
+ ) {
260
+ // Render existing inline tokens in the queue
261
+ const parsed = this._parse(tokenRenderQueue);
262
+ if (parsed.length > 0) {
263
+ siblingNodes.push(this.renderer.text(parsed, textStyle));
264
+ }
265
+
266
+ // Render the current block token
267
+ if (t.type === "image") {
268
+ siblingNodes.push(this._parseToken(t));
269
+ } else if (t.type === "link" && t.tokens && t.tokens[0]) {
270
+ const imageToken = t.tokens[0] as Tokens.Image;
271
+ const href = getValidURL(this.baseUrl, t.href);
272
+ siblingNodes.push(
273
+ this.renderer.linkImage(
274
+ href,
275
+ imageToken.href,
276
+ imageToken.text ?? imageToken.title ?? "",
277
+ this.styles.image,
278
+ imageToken.title,
279
+ ),
280
+ );
281
+ }
282
+
283
+ tokenRenderQueue = [];
284
+ continue;
285
+ }
286
+ tokenRenderQueue = [...tokenRenderQueue, t];
287
+ }
288
+
289
+ /* Remaining temp tokens if any */
290
+ if (tokenRenderQueue.length > 0) {
291
+ siblingNodes.push(this.renderer.text(this.parse(tokenRenderQueue), {}));
292
+ }
293
+
294
+ return siblingNodes;
295
+ }
296
+
297
+ // To avoid duplicate text node nesting when there are no child tokens with text emphasis (i.e., italic)
298
+ // ref: https://github.com/gmsgowtham/react-native-marked/issues/522
299
+ private hasDuplicateTextChildToken(token: Token): boolean {
300
+ if (!("tokens" in token)) {
301
+ return false;
302
+ }
303
+
304
+ if (
305
+ token.tokens &&
306
+ token.tokens.length === 1 &&
307
+ token.tokens[0]?.type === "text"
308
+ ) {
309
+ return true;
310
+ }
311
+
312
+ return false;
313
+ }
314
+ }
315
+
316
+ export default Parser;