@novastera-oss/react-native-markdown-display 8.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 (69) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +1206 -0
  3. package/dist/cjs/index.js +164 -0
  4. package/dist/cjs/lib/AstRenderer.js +129 -0
  5. package/dist/cjs/lib/data/textStyleProps.js +24 -0
  6. package/dist/cjs/lib/parser.js +22 -0
  7. package/dist/cjs/lib/renderRules.js +148 -0
  8. package/dist/cjs/lib/styles.js +183 -0
  9. package/dist/cjs/lib/util/Token.js +11 -0
  10. package/dist/cjs/lib/util/cleanupTokens.js +61 -0
  11. package/dist/cjs/lib/util/convertAdditionalStyles.js +39 -0
  12. package/dist/cjs/lib/util/flattenInlineTokens.js +17 -0
  13. package/dist/cjs/lib/util/getTokenTypeByToken.js +21 -0
  14. package/dist/cjs/lib/util/getUniqueID.js +8 -0
  15. package/dist/cjs/lib/util/groupTextTokens.js +30 -0
  16. package/dist/cjs/lib/util/hasParents.js +6 -0
  17. package/dist/cjs/lib/util/omitListItemParagraph.js +33 -0
  18. package/dist/cjs/lib/util/openUrl.js +15 -0
  19. package/dist/cjs/lib/util/removeTextStyleProps.js +15 -0
  20. package/dist/cjs/lib/util/renderInlineAsText.js +16 -0
  21. package/dist/cjs/lib/util/splitTextNonTextNodes.js +21 -0
  22. package/dist/cjs/lib/util/stringToTokens.js +13 -0
  23. package/dist/cjs/lib/util/tokensToAST.js +63 -0
  24. package/dist/cjs/types.js +2 -0
  25. package/dist/esm/index.js +112 -0
  26. package/dist/esm/lib/AstRenderer.js +123 -0
  27. package/dist/esm/lib/data/textStyleProps.js +22 -0
  28. package/dist/esm/lib/parser.js +16 -0
  29. package/dist/esm/lib/renderRules.js +143 -0
  30. package/dist/esm/lib/styles.js +180 -0
  31. package/dist/esm/lib/util/Token.js +8 -0
  32. package/dist/esm/lib/util/cleanupTokens.js +55 -0
  33. package/dist/esm/lib/util/convertAdditionalStyles.js +36 -0
  34. package/dist/esm/lib/util/flattenInlineTokens.js +14 -0
  35. package/dist/esm/lib/util/getTokenTypeByToken.js +18 -0
  36. package/dist/esm/lib/util/getUniqueID.js +5 -0
  37. package/dist/esm/lib/util/groupTextTokens.js +24 -0
  38. package/dist/esm/lib/util/hasParents.js +3 -0
  39. package/dist/esm/lib/util/omitListItemParagraph.js +30 -0
  40. package/dist/esm/lib/util/openUrl.js +12 -0
  41. package/dist/esm/lib/util/removeTextStyleProps.js +9 -0
  42. package/dist/esm/lib/util/renderInlineAsText.js +13 -0
  43. package/dist/esm/lib/util/splitTextNonTextNodes.js +18 -0
  44. package/dist/esm/lib/util/stringToTokens.js +10 -0
  45. package/dist/esm/lib/util/tokensToAST.js +57 -0
  46. package/dist/esm/types.js +1 -0
  47. package/dist/types/index.d.ts +23 -0
  48. package/dist/types/lib/AstRenderer.d.ts +16 -0
  49. package/dist/types/lib/data/textStyleProps.d.ts +2 -0
  50. package/dist/types/lib/parser.d.ts +3 -0
  51. package/dist/types/lib/renderRules.d.ts +3 -0
  52. package/dist/types/lib/styles.d.ts +141 -0
  53. package/dist/types/lib/util/Token.d.ts +8 -0
  54. package/dist/types/lib/util/cleanupTokens.d.ts +2 -0
  55. package/dist/types/lib/util/convertAdditionalStyles.d.ts +1 -0
  56. package/dist/types/lib/util/flattenInlineTokens.d.ts +2 -0
  57. package/dist/types/lib/util/getTokenTypeByToken.d.ts +2 -0
  58. package/dist/types/lib/util/getUniqueID.d.ts +1 -0
  59. package/dist/types/lib/util/groupTextTokens.d.ts +2 -0
  60. package/dist/types/lib/util/hasParents.d.ts +2 -0
  61. package/dist/types/lib/util/omitListItemParagraph.d.ts +2 -0
  62. package/dist/types/lib/util/openUrl.d.ts +1 -0
  63. package/dist/types/lib/util/removeTextStyleProps.d.ts +1 -0
  64. package/dist/types/lib/util/renderInlineAsText.d.ts +2 -0
  65. package/dist/types/lib/util/splitTextNonTextNodes.d.ts +7 -0
  66. package/dist/types/lib/util/stringToTokens.d.ts +2 -0
  67. package/dist/types/lib/util/tokensToAST.d.ts +2 -0
  68. package/dist/types/types.d.ts +59 -0
  69. package/package.json +69 -0
@@ -0,0 +1,143 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Text, TouchableWithoutFeedback, View, Platform, StyleSheet, } from 'react-native';
3
+ import { Image } from 'expo-image';
4
+ import openUrl from './util/openUrl';
5
+ import hasParents from './util/hasParents';
6
+ import textStyleProps from './data/textStyleProps';
7
+ const baseRule = (fn) => fn;
8
+ const linkRule = (fn) => fn;
9
+ const imageRule = (fn) => fn;
10
+ const renderRules = {
11
+ // when unknown elements are introduced, so it wont break
12
+ unknown: baseRule(() => null),
13
+ // The main container
14
+ body: baseRule((node, children, parent, styles) => (_jsx(View, { style: styles._VIEW_SAFE_body, children: children }, node.key))),
15
+ // Headings
16
+ heading1: baseRule((node, children, parent, styles) => (_jsx(View, { style: styles._VIEW_SAFE_heading1, children: children }, node.key))),
17
+ heading2: baseRule((node, children, parent, styles) => (_jsx(View, { style: styles._VIEW_SAFE_heading2, children: children }, node.key))),
18
+ heading3: baseRule((node, children, parent, styles) => (_jsx(View, { style: styles._VIEW_SAFE_heading3, children: children }, node.key))),
19
+ heading4: baseRule((node, children, parent, styles) => (_jsx(View, { style: styles._VIEW_SAFE_heading4, children: children }, node.key))),
20
+ heading5: baseRule((node, children, parent, styles) => (_jsx(View, { style: styles._VIEW_SAFE_heading5, children: children }, node.key))),
21
+ heading6: baseRule((node, children, parent, styles) => (_jsx(View, { style: styles._VIEW_SAFE_heading6, children: children }, node.key))),
22
+ // Horizontal Rule
23
+ hr: baseRule((node, children, parent, styles) => (_jsx(View, { style: styles._VIEW_SAFE_hr }, node.key))),
24
+ // Emphasis
25
+ strong: baseRule((node, children, parent, styles) => (_jsx(Text, { style: styles.strong, children: children }, node.key))),
26
+ em: baseRule((node, children, parent, styles) => (_jsx(Text, { style: styles.em, children: children }, node.key))),
27
+ s: baseRule((node, children, parent, styles) => (_jsx(Text, { style: styles.s, children: children }, node.key))),
28
+ // Blockquotes
29
+ blockquote: baseRule((node, children, parent, styles) => (_jsx(View, { style: styles._VIEW_SAFE_blockquote, children: children }, node.key))),
30
+ // Lists
31
+ bullet_list: baseRule((node, children, parent, styles) => (_jsx(View, { style: styles._VIEW_SAFE_bullet_list, children: children }, node.key))),
32
+ ordered_list: baseRule((node, children, parent, styles) => (_jsx(View, { style: styles._VIEW_SAFE_ordered_list, children: children }, node.key))),
33
+ // this is a unique and quite annoying render rule because it has
34
+ // child items that can be styled (the list icon and the list content)
35
+ // outside of the AST tree so there are some work arounds in the
36
+ // AST renderer specifically to get the styling right here
37
+ list_item: baseRule((node, children, parent, styles, inheritedStyles = {}) => {
38
+ // we need to grab any text specific stuff here that is applied on the list_item style
39
+ // and apply it onto bullet_list_icon. the AST renderer has some workaround code to make
40
+ // the content classes apply correctly to the child AST tree items as well
41
+ // as code that forces the creation of the inheritedStyles object for list_items
42
+ const refStyle = {
43
+ ...inheritedStyles,
44
+ ...StyleSheet.flatten(styles.list_item),
45
+ };
46
+ const arr = Object.keys(refStyle);
47
+ const modifiedInheritedStylesObj = {};
48
+ for (let b = 0; b < arr.length; b++) {
49
+ if (textStyleProps.includes(arr[b])) {
50
+ modifiedInheritedStylesObj[arr[b]] = refStyle[arr[b]];
51
+ }
52
+ }
53
+ if (hasParents(parent, 'bullet_list')) {
54
+ return (_jsxs(View, { style: styles._VIEW_SAFE_list_item, children: [_jsx(Text, { style: [modifiedInheritedStylesObj, styles.bullet_list_icon], accessible: false, children: Platform.select({
55
+ android: '\u2022',
56
+ ios: '\u00B7',
57
+ default: '\u2022',
58
+ }) }), _jsx(View, { style: styles._VIEW_SAFE_bullet_list_content, children: children })] }, node.key));
59
+ }
60
+ if (hasParents(parent, 'ordered_list')) {
61
+ const orderedListIndex = parent.findIndex((el) => el.type === 'ordered_list');
62
+ const orderedList = parent[orderedListIndex];
63
+ let listItemNumber;
64
+ if (orderedList.attributes && orderedList.attributes.start) {
65
+ listItemNumber = orderedList.attributes.start + node.index;
66
+ }
67
+ else {
68
+ listItemNumber = node.index + 1;
69
+ }
70
+ return (_jsxs(View, { style: styles._VIEW_SAFE_list_item, children: [_jsxs(Text, { style: [modifiedInheritedStylesObj, styles.ordered_list_icon], children: [listItemNumber, node.markup] }), _jsx(View, { style: styles._VIEW_SAFE_ordered_list_content, children: children })] }, node.key));
71
+ }
72
+ // we should not need this, but just in case
73
+ return (_jsx(View, { style: styles._VIEW_SAFE_list_item, children: children }, node.key));
74
+ }),
75
+ // Code
76
+ code_inline: baseRule((node, children, parent, styles, inheritedStyles = {}) => (_jsx(Text, { style: [inheritedStyles, styles.code_inline], children: node.content }, node.key))),
77
+ code_block: baseRule((node, children, parent, styles, inheritedStyles = {}) => {
78
+ // we trim new lines off the end of code blocks because the parser sends an extra one.
79
+ let { content } = node;
80
+ if (typeof node.content === 'string' &&
81
+ node.content.charAt(node.content.length - 1) === '\n') {
82
+ content = node.content.substring(0, node.content.length - 1);
83
+ }
84
+ return (_jsx(Text, { style: [inheritedStyles, styles.code_block], children: content }, node.key));
85
+ }),
86
+ fence: baseRule((node, children, parent, styles, inheritedStyles = {}) => {
87
+ // we trim new lines off the end of code blocks because the parser sends an extra one.
88
+ let { content } = node;
89
+ if (typeof node.content === 'string' &&
90
+ node.content.charAt(node.content.length - 1) === '\n') {
91
+ content = node.content.substring(0, node.content.length - 1);
92
+ }
93
+ return (_jsx(Text, { style: [inheritedStyles, styles.fence], children: content }, node.key));
94
+ }),
95
+ // Tables
96
+ table: baseRule((node, children, parent, styles) => (_jsx(View, { style: styles._VIEW_SAFE_table, children: children }, node.key))),
97
+ thead: baseRule((node, children, parent, styles) => (_jsx(View, { style: styles._VIEW_SAFE_thead, children: children }, node.key))),
98
+ tbody: baseRule((node, children, parent, styles) => (_jsx(View, { style: styles._VIEW_SAFE_tbody, children: children }, node.key))),
99
+ th: baseRule((node, children, parent, styles) => (_jsx(View, { style: styles._VIEW_SAFE_th, children: children }, node.key))),
100
+ tr: baseRule((node, children, parent, styles) => (_jsx(View, { style: styles._VIEW_SAFE_tr, children: children }, node.key))),
101
+ td: baseRule((node, children, parent, styles) => (_jsx(View, { style: styles._VIEW_SAFE_td, children: children }, node.key))),
102
+ // Links
103
+ link: linkRule((node, children, parent, styles, onLinkPress) => (_jsx(Text, { style: styles.link, onPress: () => openUrl(node.attributes.href, onLinkPress), children: children }, node.key))),
104
+ blocklink: linkRule((node, children, parent, styles, onLinkPress) => (_jsx(TouchableWithoutFeedback, { onPress: () => openUrl(node.attributes.href, onLinkPress), style: styles.blocklink, children: _jsx(View, { style: styles.image, children: children }) }, node.key))),
105
+ // Images
106
+ image: imageRule((node, children, parent, styles, allowedImageHandlers, defaultImageHandler) => {
107
+ const { src, alt } = node.attributes;
108
+ if (!src) {
109
+ return null;
110
+ }
111
+ // we check that the source starts with at least one of the elements in allowedImageHandlers
112
+ const show = allowedImageHandlers.filter((value) => {
113
+ return src.toLowerCase().startsWith(value.toLowerCase());
114
+ }).length > 0;
115
+ if (show === false && defaultImageHandler === null) {
116
+ return null;
117
+ }
118
+ const imageUri = show === true ? src : `${defaultImageHandler !== null && defaultImageHandler !== void 0 ? defaultImageHandler : ''}${src}`;
119
+ const imageProps = {
120
+ key: node.key,
121
+ style: styles._VIEW_SAFE_image,
122
+ source: {
123
+ uri: imageUri,
124
+ },
125
+ };
126
+ if (alt) {
127
+ imageProps.accessible = true;
128
+ imageProps.accessibilityLabel = alt;
129
+ }
130
+ return _jsx(Image, { ...imageProps });
131
+ }),
132
+ // Text Output
133
+ text: baseRule((node, children, parent, styles, inheritedStyles = {}) => (_jsx(Text, { style: [inheritedStyles, styles.text], children: node.content }, node.key))),
134
+ textgroup: baseRule((node, children, parent, styles) => (_jsx(Text, { style: styles.textgroup, children: children }, node.key))),
135
+ paragraph: baseRule((node, children, parent, styles) => (_jsx(View, { style: styles._VIEW_SAFE_paragraph, children: children }, node.key))),
136
+ hardbreak: baseRule((node, children, parent, styles) => (_jsx(Text, { style: styles.hardbreak, children: '\n' }, node.key))),
137
+ softbreak: baseRule((node, children, parent, styles) => (_jsx(Text, { style: styles.softbreak, children: '\n' }, node.key))),
138
+ // Believe these are never used but retained for completeness
139
+ pre: baseRule((node, children, parent, styles) => (_jsx(View, { style: styles._VIEW_SAFE_pre, children: children }, node.key))),
140
+ inline: baseRule((node, children, parent, styles) => (_jsx(Text, { style: styles.inline, children: children }, node.key))),
141
+ span: baseRule((node, children, parent, styles) => (_jsx(Text, { style: styles.span, children: children }, node.key))),
142
+ };
143
+ export default renderRules;
@@ -0,0 +1,180 @@
1
+ import { Platform } from 'react-native';
2
+ // this is converted to a stylesheet internally at run time with StyleSheet.create(
3
+ export const styles = {
4
+ // The main container
5
+ body: {},
6
+ // Headings
7
+ heading1: {
8
+ flexDirection: 'row',
9
+ fontSize: 32,
10
+ },
11
+ heading2: {
12
+ flexDirection: 'row',
13
+ fontSize: 24,
14
+ },
15
+ heading3: {
16
+ flexDirection: 'row',
17
+ fontSize: 18,
18
+ },
19
+ heading4: {
20
+ flexDirection: 'row',
21
+ fontSize: 16,
22
+ },
23
+ heading5: {
24
+ flexDirection: 'row',
25
+ fontSize: 13,
26
+ },
27
+ heading6: {
28
+ flexDirection: 'row',
29
+ fontSize: 11,
30
+ },
31
+ // Horizontal Rule
32
+ hr: {
33
+ backgroundColor: '#000000',
34
+ height: 1,
35
+ },
36
+ // Emphasis
37
+ strong: {
38
+ fontWeight: 'bold',
39
+ },
40
+ em: {
41
+ fontStyle: 'italic',
42
+ },
43
+ s: {
44
+ textDecorationLine: 'line-through',
45
+ },
46
+ // Blockquotes
47
+ blockquote: {
48
+ backgroundColor: '#F5F5F5',
49
+ borderColor: '#CCC',
50
+ borderLeftWidth: 4,
51
+ marginLeft: 5,
52
+ paddingHorizontal: 5,
53
+ },
54
+ // Lists
55
+ bullet_list: {},
56
+ ordered_list: {},
57
+ list_item: {
58
+ flexDirection: 'row',
59
+ justifyContent: 'flex-start',
60
+ },
61
+ // @pseudo class, does not have a unique render rule
62
+ bullet_list_icon: {
63
+ marginLeft: 10,
64
+ marginRight: 10,
65
+ },
66
+ // @pseudo class, does not have a unique render rule
67
+ bullet_list_content: {
68
+ flex: 1,
69
+ },
70
+ // @pseudo class, does not have a unique render rule
71
+ ordered_list_icon: {
72
+ marginLeft: 10,
73
+ marginRight: 10,
74
+ },
75
+ // @pseudo class, does not have a unique render rule
76
+ ordered_list_content: {
77
+ flex: 1,
78
+ },
79
+ // Code
80
+ code_inline: {
81
+ borderWidth: 1,
82
+ borderColor: '#CCCCCC',
83
+ backgroundColor: '#f5f5f5',
84
+ padding: 10,
85
+ borderRadius: 4,
86
+ ...Platform.select({
87
+ ['ios']: {
88
+ fontFamily: 'Courier',
89
+ },
90
+ ['android']: {
91
+ fontFamily: 'monospace',
92
+ },
93
+ }),
94
+ },
95
+ code_block: {
96
+ borderWidth: 1,
97
+ borderColor: '#CCCCCC',
98
+ backgroundColor: '#f5f5f5',
99
+ padding: 10,
100
+ borderRadius: 4,
101
+ ...Platform.select({
102
+ ['ios']: {
103
+ fontFamily: 'Courier',
104
+ },
105
+ ['android']: {
106
+ fontFamily: 'monospace',
107
+ },
108
+ }),
109
+ },
110
+ fence: {
111
+ borderWidth: 1,
112
+ borderColor: '#CCCCCC',
113
+ backgroundColor: '#f5f5f5',
114
+ padding: 10,
115
+ borderRadius: 4,
116
+ ...Platform.select({
117
+ ['ios']: {
118
+ fontFamily: 'Courier',
119
+ },
120
+ ['android']: {
121
+ fontFamily: 'monospace',
122
+ },
123
+ }),
124
+ },
125
+ // Tables
126
+ table: {
127
+ borderWidth: 1,
128
+ borderColor: '#000000',
129
+ borderRadius: 3,
130
+ },
131
+ thead: {},
132
+ tbody: {},
133
+ th: {
134
+ flex: 1,
135
+ padding: 5,
136
+ },
137
+ tr: {
138
+ borderBottomWidth: 1,
139
+ borderColor: '#000000',
140
+ flexDirection: 'row',
141
+ },
142
+ td: {
143
+ flex: 1,
144
+ padding: 5,
145
+ },
146
+ // Links
147
+ link: {
148
+ textDecorationLine: 'underline',
149
+ },
150
+ blocklink: {
151
+ flex: 1,
152
+ borderColor: '#000000',
153
+ borderBottomWidth: 1,
154
+ },
155
+ // Images
156
+ image: {
157
+ flex: 1,
158
+ },
159
+ // Text Output
160
+ text: {},
161
+ textgroup: {},
162
+ paragraph: {
163
+ marginTop: 10,
164
+ marginBottom: 10,
165
+ flexWrap: 'wrap',
166
+ flexDirection: 'row',
167
+ alignItems: 'flex-start',
168
+ justifyContent: 'flex-start',
169
+ width: '100%',
170
+ },
171
+ hardbreak: {
172
+ width: '100%',
173
+ height: 1,
174
+ },
175
+ softbreak: {},
176
+ // Believe these are never used but retained for completeness
177
+ pre: {},
178
+ inline: {},
179
+ span: {},
180
+ };
@@ -0,0 +1,8 @@
1
+ export default class Token {
2
+ constructor(type, nesting = 0, children = null, block = false) {
3
+ this.type = type;
4
+ this.nesting = nesting;
5
+ this.children = children;
6
+ this.block = block;
7
+ }
8
+ }
@@ -0,0 +1,55 @@
1
+ import getTokenTypeByToken from './getTokenTypeByToken';
2
+ import flattenInlineTokens from './flattenInlineTokens';
3
+ import renderInlineAsText from './renderInlineAsText';
4
+ export function cleanupTokens(tokens) {
5
+ tokens = flattenInlineTokens(tokens);
6
+ tokens.forEach((token) => {
7
+ var _a;
8
+ token.type = getTokenTypeByToken(token);
9
+ // set image and hardbreak to block elements
10
+ if (token.type === 'image' || token.type === 'hardbreak') {
11
+ token.block = true;
12
+ }
13
+ // Set img alt text
14
+ if (token.type === 'image' && token.attrs) {
15
+ const altIndex = typeof token.attrIndex === 'function'
16
+ ? token.attrIndex('alt')
17
+ : token.attrs.findIndex((attr) => attr[0] === 'alt');
18
+ if (altIndex >= 0) {
19
+ token.attrs[altIndex][1] = renderInlineAsText((_a = token.children) !== null && _a !== void 0 ? _a : []);
20
+ }
21
+ }
22
+ });
23
+ /**
24
+ * changing a link token to a blocklink to fix issue where link tokens with
25
+ * nested non text tokens breaks component
26
+ */
27
+ const stack = [];
28
+ tokens = tokens.reduce((acc, token) => {
29
+ if (token.type === 'link' && token.nesting === 1) {
30
+ stack.push(token);
31
+ }
32
+ else if (stack.length > 0 &&
33
+ token.type === 'link' &&
34
+ token.nesting === -1) {
35
+ if (stack.some((stackToken) => stackToken.block)) {
36
+ stack[0].type = 'blocklink';
37
+ stack[0].block = true;
38
+ token.type = 'blocklink';
39
+ token.block = true;
40
+ }
41
+ stack.push(token);
42
+ while (stack.length) {
43
+ acc.push(stack.shift());
44
+ }
45
+ }
46
+ else if (stack.length > 0) {
47
+ stack.push(token);
48
+ }
49
+ else {
50
+ acc.push(token);
51
+ }
52
+ return acc;
53
+ }, []);
54
+ return tokens;
55
+ }
@@ -0,0 +1,36 @@
1
+ function toCamelCase(input) {
2
+ return input.replace(/-([a-z])/g, (_, char) => char.toUpperCase());
3
+ }
4
+ function parseValue(value) {
5
+ const trimmed = value.trim();
6
+ const pxMatch = trimmed.match(/^(-?\d+(\.\d+)?)px$/);
7
+ if (pxMatch) {
8
+ return Number(pxMatch[1]);
9
+ }
10
+ const numMatch = trimmed.match(/^-?\d+(\.\d+)?$/);
11
+ if (numMatch) {
12
+ return Number(trimmed);
13
+ }
14
+ return trimmed;
15
+ }
16
+ export default function convertAdditionalStyles(style) {
17
+ if (!style || typeof style !== 'string') {
18
+ return {};
19
+ }
20
+ const rules = style.split(';');
21
+ const tuples = rules
22
+ .map((rule) => {
23
+ const [rawKey, rawValue] = rule.split(':');
24
+ if (rawKey && rawValue) {
25
+ const key = toCamelCase(rawKey.trim());
26
+ const value = parseValue(rawValue);
27
+ return [key, value];
28
+ }
29
+ return null;
30
+ })
31
+ .filter((x) => x !== null);
32
+ return tuples.reduce((acc, [key, value]) => {
33
+ acc[key] = value;
34
+ return acc;
35
+ }, {});
36
+ }
@@ -0,0 +1,14 @@
1
+ export default function flattenTokens(tokens) {
2
+ return tokens.reduce((acc, curr) => {
3
+ if (curr.type === 'inline' && curr.children && curr.children.length > 0) {
4
+ const children = flattenTokens(curr.children);
5
+ while (children.length) {
6
+ acc.push(children.shift());
7
+ }
8
+ }
9
+ else {
10
+ acc.push(curr);
11
+ }
12
+ return acc;
13
+ }, []);
14
+ }
@@ -0,0 +1,18 @@
1
+ const regSelectOpenClose = /_open|_close/g;
2
+ export default function getTokenTypeByToken(token) {
3
+ var _a, _b;
4
+ let cleanedType = 'unknown';
5
+ if (token.type) {
6
+ cleanedType = token.type.replace(regSelectOpenClose, '');
7
+ }
8
+ switch (cleanedType) {
9
+ case 'heading': {
10
+ cleanedType = `${cleanedType}${(_b = (_a = token.tag) === null || _a === void 0 ? void 0 : _a.substr(1)) !== null && _b !== void 0 ? _b : ''}`;
11
+ break;
12
+ }
13
+ default: {
14
+ break;
15
+ }
16
+ }
17
+ return cleanedType;
18
+ }
@@ -0,0 +1,5 @@
1
+ let uuid = new Date().getTime();
2
+ export default function getUniqueID() {
3
+ uuid++;
4
+ return `rnmr_${uuid.toString(16)}`;
5
+ }
@@ -0,0 +1,24 @@
1
+ import TokenGroup from './Token';
2
+ export default function groupTextTokens(tokens) {
3
+ const result = [];
4
+ let hasGroup = false;
5
+ tokens.forEach((token) => {
6
+ if (!token.block && !hasGroup) {
7
+ hasGroup = true;
8
+ result.push(new TokenGroup('textgroup', 1));
9
+ result.push(token);
10
+ }
11
+ else if (!token.block && hasGroup) {
12
+ result.push(token);
13
+ }
14
+ else if (token.block && hasGroup) {
15
+ hasGroup = false;
16
+ result.push(new TokenGroup('textgroup', -1));
17
+ result.push(token);
18
+ }
19
+ else {
20
+ result.push(token);
21
+ }
22
+ });
23
+ return result;
24
+ }
@@ -0,0 +1,3 @@
1
+ export default function hasParents(parents, type) {
2
+ return parents.findIndex((el) => el.type === type) > -1;
3
+ }
@@ -0,0 +1,30 @@
1
+ export default function omitListItemParagraph(tokens) {
2
+ // used to ensure that we remove the correct ending paragraph token
3
+ let depth = null;
4
+ return tokens.filter((token, index) => {
5
+ // update depth if we've already removed a starting paragraph token
6
+ if (depth !== null) {
7
+ depth = depth + token.nesting;
8
+ }
9
+ // check for a list_item token followed by paragraph token (to remove)
10
+ if (token.type === 'list_item' && token.nesting === 1 && depth === null) {
11
+ const next = index + 1 in tokens ? tokens[index + 1] : null;
12
+ if (next && next.type === 'paragraph' && next.nesting === 1) {
13
+ depth = 0;
14
+ return true;
15
+ }
16
+ }
17
+ else if (token.type === 'paragraph') {
18
+ if (token.nesting === 1 && depth === 1) {
19
+ // remove the paragraph token immediately after the list_item token
20
+ return false;
21
+ }
22
+ else if (token.nesting === -1 && depth === 0) {
23
+ // remove the ending paragraph token; reset depth
24
+ depth = null;
25
+ return false;
26
+ }
27
+ }
28
+ return true;
29
+ });
30
+ }
@@ -0,0 +1,12 @@
1
+ import { Linking } from 'react-native';
2
+ export default function openUrl(url, customCallback) {
3
+ if (customCallback) {
4
+ const result = customCallback(url);
5
+ if (url && result && typeof result === 'boolean') {
6
+ Linking.openURL(url);
7
+ }
8
+ }
9
+ else if (url) {
10
+ Linking.openURL(url);
11
+ }
12
+ }
@@ -0,0 +1,9 @@
1
+ import textStyleProps from '../data/textStyleProps';
2
+ export default function removeTextStyleProps(style) {
3
+ const intersection = textStyleProps.filter((value) => Object.keys(style).includes(value));
4
+ const obj = { ...style };
5
+ intersection.forEach((value) => {
6
+ delete obj[value];
7
+ });
8
+ return obj;
9
+ }
@@ -0,0 +1,13 @@
1
+ export default function renderInlineAsText(tokens) {
2
+ var _a;
3
+ let result = '';
4
+ for (let i = 0, len = tokens.length; i < len; i++) {
5
+ if (tokens[i].type === 'text') {
6
+ result += tokens[i].content;
7
+ }
8
+ else if (tokens[i].type === 'image') {
9
+ result += renderInlineAsText((_a = tokens[i].children) !== null && _a !== void 0 ? _a : []);
10
+ }
11
+ }
12
+ return result;
13
+ }
@@ -0,0 +1,18 @@
1
+ function isTextElement(node) {
2
+ if (typeof node.type === 'string') {
3
+ return node.type === 'Text';
4
+ }
5
+ const displayName = node.type.displayName;
6
+ return displayName === 'Text';
7
+ }
8
+ export default function splitTextNonTextNodes(children) {
9
+ return children.reduce((acc, curr) => {
10
+ if (isTextElement(curr)) {
11
+ acc.textNodes.push(curr);
12
+ }
13
+ else {
14
+ acc.nonTextNodes.push(curr);
15
+ }
16
+ return acc;
17
+ }, { textNodes: [], nonTextNodes: [] });
18
+ }
@@ -0,0 +1,10 @@
1
+ export function stringToTokens(source, markdownIt) {
2
+ let result = [];
3
+ try {
4
+ result = markdownIt.parse(source, {});
5
+ }
6
+ catch (err) {
7
+ console.warn(err);
8
+ }
9
+ return result;
10
+ }
@@ -0,0 +1,57 @@
1
+ import getUniqueID from './getUniqueID';
2
+ import getTokenTypeByToken from './getTokenTypeByToken';
3
+ function createNode(token, tokenIndex) {
4
+ var _a, _b, _c;
5
+ const type = getTokenTypeByToken(token);
6
+ const content = (_a = token.content) !== null && _a !== void 0 ? _a : '';
7
+ let attributes = {};
8
+ if (token.attrs) {
9
+ attributes = token.attrs.reduce((prev, curr) => {
10
+ const [name, value] = curr;
11
+ return { ...prev, [name]: value };
12
+ }, {});
13
+ }
14
+ return {
15
+ type,
16
+ sourceType: token.type,
17
+ sourceInfo: token.info,
18
+ sourceMeta: token.meta,
19
+ block: token.block,
20
+ markup: (_b = token.markup) !== null && _b !== void 0 ? _b : '',
21
+ key: `${getUniqueID()}_${type}`,
22
+ content,
23
+ tokenIndex,
24
+ index: 0,
25
+ attributes,
26
+ children: tokensToAST((_c = token.children) !== null && _c !== void 0 ? _c : []),
27
+ };
28
+ }
29
+ export default function tokensToAST(tokens) {
30
+ var _a;
31
+ let stack = [];
32
+ let children = [];
33
+ if (!tokens || tokens.length === 0) {
34
+ return [];
35
+ }
36
+ for (let i = 0; i < tokens.length; i++) {
37
+ const token = tokens[i];
38
+ const astNode = createNode(token, i);
39
+ if (!(astNode.type === 'text' &&
40
+ astNode.children.length === 0 &&
41
+ astNode.content === '')) {
42
+ astNode.index = children.length;
43
+ if (token.nesting === 1) {
44
+ children.push(astNode);
45
+ stack.push(children);
46
+ children = astNode.children;
47
+ }
48
+ else if (token.nesting === -1) {
49
+ children = (_a = stack.pop()) !== null && _a !== void 0 ? _a : [];
50
+ }
51
+ else if (token.nesting === 0) {
52
+ children.push(astNode);
53
+ }
54
+ }
55
+ }
56
+ return children;
57
+ }
@@ -0,0 +1 @@
1
+ export {};