@expensify/react-native-live-markdown 0.1.162 → 0.1.164

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 (49) hide show
  1. package/lib/commonjs/MarkdownTextInput.js.map +1 -1
  2. package/lib/commonjs/MarkdownTextInput.web.js +8 -3
  3. package/lib/commonjs/MarkdownTextInput.web.js.map +1 -1
  4. package/lib/commonjs/web/inputElements/inlineImage.js +8 -1
  5. package/lib/commonjs/web/inputElements/inlineImage.js.map +1 -1
  6. package/lib/commonjs/web/utils/blockUtils.js +2 -2
  7. package/lib/commonjs/web/utils/blockUtils.js.map +1 -1
  8. package/lib/commonjs/web/utils/cursorUtils.js +4 -2
  9. package/lib/commonjs/web/utils/cursorUtils.js.map +1 -1
  10. package/lib/commonjs/web/utils/parserUtils.js +4 -4
  11. package/lib/commonjs/web/utils/parserUtils.js.map +1 -1
  12. package/lib/commonjs/web/utils/treeUtils.js +3 -0
  13. package/lib/commonjs/web/utils/treeUtils.js.map +1 -1
  14. package/lib/module/MarkdownTextInput.js.map +1 -1
  15. package/lib/module/MarkdownTextInput.web.js +8 -3
  16. package/lib/module/MarkdownTextInput.web.js.map +1 -1
  17. package/lib/module/web/inputElements/inlineImage.js +8 -1
  18. package/lib/module/web/inputElements/inlineImage.js.map +1 -1
  19. package/lib/module/web/utils/blockUtils.js +2 -2
  20. package/lib/module/web/utils/blockUtils.js.map +1 -1
  21. package/lib/module/web/utils/cursorUtils.js +4 -2
  22. package/lib/module/web/utils/cursorUtils.js.map +1 -1
  23. package/lib/module/web/utils/parserUtils.js +4 -4
  24. package/lib/module/web/utils/parserUtils.js.map +1 -1
  25. package/lib/module/web/utils/treeUtils.js +3 -0
  26. package/lib/module/web/utils/treeUtils.js.map +1 -1
  27. package/lib/typescript/src/MarkdownTextInput.d.ts +2 -1
  28. package/lib/typescript/src/MarkdownTextInput.d.ts.map +1 -1
  29. package/lib/typescript/src/MarkdownTextInput.web.d.ts +2 -1
  30. package/lib/typescript/src/MarkdownTextInput.web.d.ts.map +1 -1
  31. package/lib/typescript/src/commonTypes.d.ts +5 -1
  32. package/lib/typescript/src/commonTypes.d.ts.map +1 -1
  33. package/lib/typescript/src/web/inputElements/inlineImage.d.ts +2 -2
  34. package/lib/typescript/src/web/inputElements/inlineImage.d.ts.map +1 -1
  35. package/lib/typescript/src/web/utils/blockUtils.d.ts +2 -2
  36. package/lib/typescript/src/web/utils/blockUtils.d.ts.map +1 -1
  37. package/lib/typescript/src/web/utils/cursorUtils.d.ts.map +1 -1
  38. package/lib/typescript/src/web/utils/parserUtils.d.ts +3 -3
  39. package/lib/typescript/src/web/utils/parserUtils.d.ts.map +1 -1
  40. package/lib/typescript/src/web/utils/treeUtils.d.ts.map +1 -1
  41. package/package.json +1 -1
  42. package/src/MarkdownTextInput.tsx +2 -1
  43. package/src/MarkdownTextInput.web.tsx +9 -3
  44. package/src/commonTypes.ts +6 -1
  45. package/src/web/inputElements/inlineImage.ts +13 -2
  46. package/src/web/utils/blockUtils.ts +3 -2
  47. package/src/web/utils/cursorUtils.ts +4 -2
  48. package/src/web/utils/parserUtils.ts +5 -3
  49. package/src/web/utils/treeUtils.ts +5 -1
@@ -23,12 +23,13 @@ import type {MarkdownStyle} from './MarkdownTextInputDecoratorViewNativeComponen
23
23
  import {getElementHeight, getPlaceholderValue, isEventComposing, normalizeValue, parseInnerHTMLToText} from './web/utils/inputUtils';
24
24
  import {parseToReactDOMStyle, processMarkdownStyle} from './web/utils/webStyleUtils';
25
25
  import {forceRefreshAllImages} from './web/inputElements/inlineImage';
26
+ import type {InlineImagesInputProps} from './commonTypes';
26
27
 
27
28
  require('../parser/react-native-live-markdown-parser.js');
28
29
 
29
30
  const useClientEffect = typeof window === 'undefined' ? useEffect : useLayoutEffect;
30
31
 
31
- interface MarkdownTextInputProps extends TextInputProps {
32
+ interface MarkdownTextInputProps extends TextInputProps, InlineImagesInputProps {
32
33
  markdownStyle?: MarkdownStyle;
33
34
  onClick?: (e: MouseEvent<HTMLDivElement>) => void;
34
35
  dir?: string;
@@ -101,6 +102,8 @@ const MarkdownTextInput = React.forwardRef<TextInput, MarkdownTextInputProps>(
101
102
  id,
102
103
  inputMode,
103
104
  onTouchStart,
105
+ addAuthTokenToImageURLCallback,
106
+ imagePreviewAuthRequiredURLs,
104
107
  },
105
108
  ref,
106
109
  ) => {
@@ -154,7 +157,10 @@ const MarkdownTextInput = React.forwardRef<TextInput, MarkdownTextInputProps>(
154
157
  if (text === null) {
155
158
  return {text: divRef.current.value, cursorPosition: null};
156
159
  }
157
- const parsedText = updateInputStructure(target, text, cursorPosition, multiline, customMarkdownStyles, false, shouldForceDOMUpdate, shouldScrollIntoView);
160
+ const parsedText = updateInputStructure(target, text, cursorPosition, multiline, customMarkdownStyles, false, shouldForceDOMUpdate, shouldScrollIntoView, {
161
+ addAuthTokenToImageURLCallback,
162
+ imagePreviewAuthRequiredURLs,
163
+ });
158
164
  divRef.current.value = parsedText.text;
159
165
 
160
166
  if (history.current && shouldAddToHistory) {
@@ -163,7 +169,7 @@ const MarkdownTextInput = React.forwardRef<TextInput, MarkdownTextInputProps>(
163
169
 
164
170
  return parsedText;
165
171
  },
166
- [multiline],
172
+ [addAuthTokenToImageURLCallback, imagePreviewAuthRequiredURLs, multiline],
167
173
  );
168
174
 
169
175
  const processedMarkdownStyle = useMemo(() => {
@@ -21,4 +21,9 @@ interface MarkdownRange {
21
21
  depth?: number;
22
22
  }
23
23
 
24
- export type {MarkdownType, MarkdownRange};
24
+ type InlineImagesInputProps = {
25
+ addAuthTokenToImageURLCallback?: (url: string) => string;
26
+ imagePreviewAuthRequiredURLs?: string[];
27
+ };
28
+
29
+ export type {MarkdownType, MarkdownRange, InlineImagesInputProps};
@@ -1,5 +1,5 @@
1
1
  import type {HTMLMarkdownElement, MarkdownTextInputElement} from '../../MarkdownTextInput.web';
2
- import type {MarkdownRange} from '../../commonTypes';
2
+ import type {InlineImagesInputProps, MarkdownRange} from '../../commonTypes';
3
3
  import {parseStringWithUnitToNumber} from '../../styleUtils';
4
4
  import type {PartialMarkdownStyle} from '../../styleUtils';
5
5
  import type {TreeNode} from '../utils/treeUtils';
@@ -141,11 +141,22 @@ function updateImageTreeNode(targetNode: TreeNode, newElement: HTMLMarkdownEleme
141
141
  }
142
142
 
143
143
  /** The main function that adds inline image preview to the node */
144
- function addInlineImagePreview(currentInput: MarkdownTextInputElement, targetNode: TreeNode, text: string, ranges: MarkdownRange[], markdownStyle: PartialMarkdownStyle) {
144
+ function addInlineImagePreview(
145
+ currentInput: MarkdownTextInputElement,
146
+ targetNode: TreeNode,
147
+ text: string,
148
+ ranges: MarkdownRange[],
149
+ markdownStyle: PartialMarkdownStyle,
150
+ inlineImagesProps: InlineImagesInputProps,
151
+ ) {
152
+ const {addAuthTokenToImageURLCallback, imagePreviewAuthRequiredURLs} = inlineImagesProps;
145
153
  const linkRange = ranges.find((r) => r.type === 'link');
146
154
  let imageHref = '';
147
155
  if (linkRange) {
148
156
  imageHref = text.substring(linkRange.start, linkRange.start + linkRange.length);
157
+ if (addAuthTokenToImageURLCallback && imagePreviewAuthRequiredURLs && imagePreviewAuthRequiredURLs.find((url) => imageHref.startsWith(url))) {
158
+ imageHref = addAuthTokenToImageURLCallback(imageHref);
159
+ }
149
160
  }
150
161
 
151
162
  const imageMarginTop = parseStringWithUnitToNumber(`${markdownStyle.inlineImage?.marginTop}`);
@@ -1,5 +1,5 @@
1
1
  import type {MarkdownTextInputElement} from '../../MarkdownTextInput.web';
2
- import type {MarkdownRange} from '../../commonTypes';
2
+ import type {InlineImagesInputProps, MarkdownRange} from '../../commonTypes';
3
3
  import type {PartialMarkdownStyle} from '../../styleUtils';
4
4
  import {addInlineImagePreview} from '../inputElements/inlineImage';
5
5
  import type {NodeType, TreeNode} from './treeUtils';
@@ -98,10 +98,11 @@ function extendBlockStructure(
98
98
  ranges: MarkdownRange[],
99
99
  text: string,
100
100
  markdownStyle: PartialMarkdownStyle,
101
+ inlineImagesProps: InlineImagesInputProps,
101
102
  ) {
102
103
  switch (currentRange.type) {
103
104
  case 'inline-image':
104
- return addInlineImagePreview(currentInput, targetNode, text, ranges, markdownStyle);
105
+ return addInlineImagePreview(currentInput, targetNode, text, ranges, markdownStyle, inlineImagesProps);
105
106
  default:
106
107
  break;
107
108
  }
@@ -27,13 +27,15 @@ function setCursorPosition(target: MarkdownTextInputElement, startIndex: number,
27
27
  if (startTreeNode.type === 'br') {
28
28
  range.setStartBefore(startTreeNode.element);
29
29
  } else {
30
- range.setStart(startTreeNode.element.childNodes[0] as ChildNode, start - startTreeNode.start);
30
+ const startElement = startTreeNode.element;
31
+ range.setStart((startElement.childNodes[0] || startElement) as ChildNode, start - startTreeNode.start);
31
32
  }
32
33
 
33
34
  if (endTreeNode.type === 'br') {
34
35
  range.setEndBefore(endTreeNode.element);
35
36
  } else {
36
- range.setEnd(endTreeNode.element.childNodes[0] as ChildNode, (end || start) - endTreeNode.start);
37
+ const endElement = endTreeNode.element;
38
+ range.setEnd((endElement.childNodes[0] || endElement) as ChildNode, (end || start) - endTreeNode.start);
37
39
  }
38
40
 
39
41
  if (!end) {
@@ -4,7 +4,7 @@ import type {NodeType, TreeNode} from './treeUtils';
4
4
  import type {PartialMarkdownStyle} from '../../styleUtils';
5
5
  import {getCurrentCursorPosition, moveCursorToEnd, setCursorPosition} from './cursorUtils';
6
6
  import {addStyleToBlock, extendBlockStructure, getFirstBlockMarkdownRange, isBlockMarkdownType} from './blockUtils';
7
- import type {MarkdownRange} from '../../commonTypes';
7
+ import type {InlineImagesInputProps, MarkdownRange} from '../../commonTypes';
8
8
  import {getAnimationCurrentTimes, updateAnimationsTime} from './animationUtils';
9
9
 
10
10
  type Paragraph = {
@@ -151,6 +151,7 @@ function parseRangesToHTMLNodes(
151
151
  markdownStyle: PartialMarkdownStyle = {},
152
152
  disableInlineStyles = false,
153
153
  currentInput: MarkdownTextInputElement | null = null,
154
+ inlineImagesProps: InlineImagesInputProps = {},
154
155
  ) {
155
156
  const rootElement: HTMLMarkdownElement = document.createElement('span') as HTMLMarkdownElement;
156
157
  const textLength = text.length;
@@ -224,7 +225,7 @@ function parseRangesToHTMLNodes(
224
225
  const spanNode = appendNode(span, currentParentNode, range.type, range.length);
225
226
 
226
227
  if (isMultiline && !disableInlineStyles && currentInput) {
227
- currentParentNode = extendBlockStructure(currentInput, currentParentNode, range, lineMarkdownRanges, text, markdownStyle);
228
+ currentParentNode = extendBlockStructure(currentInput, currentParentNode, range, lineMarkdownRanges, text, markdownStyle, inlineImagesProps);
228
229
  }
229
230
 
230
231
  if (lineMarkdownRanges.length > 0 && nextRangeStartIndex < endOfCurrentRange && range.type !== 'syntax') {
@@ -279,6 +280,7 @@ function updateInputStructure(
279
280
  alwaysMoveCursorToTheEnd = false,
280
281
  shouldForceDOMUpdate = false,
281
282
  shouldScrollIntoView = false,
283
+ inlineImagesProps: InlineImagesInputProps = {},
282
284
  ) {
283
285
  const targetElement = target;
284
286
 
@@ -297,7 +299,7 @@ function updateInputStructure(
297
299
 
298
300
  // We don't want to parse text with single '\n', because contentEditable represents it as invisible <br />
299
301
  if (text) {
300
- const {dom, tree} = parseRangesToHTMLNodes(text, markdownRanges, isMultiline, markdownStyle, false, targetElement);
302
+ const {dom, tree} = parseRangesToHTMLNodes(text, markdownRanges, isMultiline, markdownStyle, false, targetElement, inlineImagesProps);
301
303
 
302
304
  if (shouldForceDOMUpdate || targetElement.innerHTML !== dom.innerHTML) {
303
305
  const animationTimes = getAnimationCurrentTimes(targetElement);
@@ -106,9 +106,13 @@ function findHTMLElementInTree(treeRoot: TreeNode, element: HTMLElement): TreeNo
106
106
 
107
107
  function getTreeNodeByIndex(treeRoot: TreeNode, index: number): TreeNode | null {
108
108
  let el: TreeNode | null = treeRoot;
109
-
110
109
  let i = 0;
111
110
  let newLineGenerated = false;
111
+
112
+ if (treeRoot.length === 0) {
113
+ return treeRoot;
114
+ }
115
+
112
116
  while (el && el.childNodes.length > 0 && i < el.childNodes.length) {
113
117
  const child = el.childNodes[i] as TreeNode;
114
118