Skip to content

Commit

Permalink
Add authToken support for inline image URLs (#510)
Browse files Browse the repository at this point in the history
  • Loading branch information
Skalakid authored Oct 4, 2024
1 parent 49481a0 commit 003e026
Show file tree
Hide file tree
Showing 6 changed files with 38 additions and 12 deletions.
3 changes: 2 additions & 1 deletion src/MarkdownTextInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@ import type {MarkdownStyle} from './MarkdownTextInputDecoratorViewNativeComponen
import NativeLiveMarkdownModule from './NativeLiveMarkdownModule';
import {mergeMarkdownStyleWithDefault} from './styleUtils';
import type {PartialMarkdownStyle} from './styleUtils';
import type {InlineImagesInputProps} from './commonTypes';

if (NativeLiveMarkdownModule) {
NativeLiveMarkdownModule.install();
}

interface MarkdownTextInputProps extends TextInputProps {
interface MarkdownTextInputProps extends TextInputProps, InlineImagesInputProps {
markdownStyle?: PartialMarkdownStyle;
}

Expand Down
12 changes: 9 additions & 3 deletions src/MarkdownTextInput.web.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,13 @@ import type {MarkdownStyle} from './MarkdownTextInputDecoratorViewNativeComponen
import {getElementHeight, getPlaceholderValue, isEventComposing, normalizeValue, parseInnerHTMLToText} from './web/utils/inputUtils';
import {parseToReactDOMStyle, processMarkdownStyle} from './web/utils/webStyleUtils';
import {forceRefreshAllImages} from './web/inputElements/inlineImage';
import type {InlineImagesInputProps} from './commonTypes';

require('../parser/react-native-live-markdown-parser.js');

const useClientEffect = typeof window === 'undefined' ? useEffect : useLayoutEffect;

interface MarkdownTextInputProps extends TextInputProps {
interface MarkdownTextInputProps extends TextInputProps, InlineImagesInputProps {
markdownStyle?: MarkdownStyle;
onClick?: (e: MouseEvent<HTMLDivElement>) => void;
dir?: string;
Expand Down Expand Up @@ -101,6 +102,8 @@ const MarkdownTextInput = React.forwardRef<TextInput, MarkdownTextInputProps>(
id,
inputMode,
onTouchStart,
addAuthTokenToImageURLCallback,
imagePreviewAuthRequiredURLs,
},
ref,
) => {
Expand Down Expand Up @@ -154,7 +157,10 @@ const MarkdownTextInput = React.forwardRef<TextInput, MarkdownTextInputProps>(
if (text === null) {
return {text: divRef.current.value, cursorPosition: null};
}
const parsedText = updateInputStructure(target, text, cursorPosition, multiline, customMarkdownStyles, false, shouldForceDOMUpdate, shouldScrollIntoView);
const parsedText = updateInputStructure(target, text, cursorPosition, multiline, customMarkdownStyles, false, shouldForceDOMUpdate, shouldScrollIntoView, {
addAuthTokenToImageURLCallback,
imagePreviewAuthRequiredURLs,
});
divRef.current.value = parsedText.text;

if (history.current && shouldAddToHistory) {
Expand All @@ -163,7 +169,7 @@ const MarkdownTextInput = React.forwardRef<TextInput, MarkdownTextInputProps>(

return parsedText;
},
[multiline],
[addAuthTokenToImageURLCallback, imagePreviewAuthRequiredURLs, multiline],
);

const processedMarkdownStyle = useMemo(() => {
Expand Down
7 changes: 6 additions & 1 deletion src/commonTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,9 @@ interface MarkdownRange {
depth?: number;
}

export type {MarkdownType, MarkdownRange};
type InlineImagesInputProps = {
addAuthTokenToImageURLCallback?: (url: string) => string;
imagePreviewAuthRequiredURLs?: string[];
};

export type {MarkdownType, MarkdownRange, InlineImagesInputProps};
15 changes: 13 additions & 2 deletions src/web/inputElements/inlineImage.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type {HTMLMarkdownElement, MarkdownTextInputElement} from '../../MarkdownTextInput.web';
import type {MarkdownRange} from '../../commonTypes';
import type {InlineImagesInputProps, MarkdownRange} from '../../commonTypes';
import {parseStringWithUnitToNumber} from '../../styleUtils';
import type {PartialMarkdownStyle} from '../../styleUtils';
import type {TreeNode} from '../utils/treeUtils';
Expand Down Expand Up @@ -141,11 +141,22 @@ function updateImageTreeNode(targetNode: TreeNode, newElement: HTMLMarkdownEleme
}

/** The main function that adds inline image preview to the node */
function addInlineImagePreview(currentInput: MarkdownTextInputElement, targetNode: TreeNode, text: string, ranges: MarkdownRange[], markdownStyle: PartialMarkdownStyle) {
function addInlineImagePreview(
currentInput: MarkdownTextInputElement,
targetNode: TreeNode,
text: string,
ranges: MarkdownRange[],
markdownStyle: PartialMarkdownStyle,
inlineImagesProps: InlineImagesInputProps,
) {
const {addAuthTokenToImageURLCallback, imagePreviewAuthRequiredURLs} = inlineImagesProps;
const linkRange = ranges.find((r) => r.type === 'link');
let imageHref = '';
if (linkRange) {
imageHref = text.substring(linkRange.start, linkRange.start + linkRange.length);
if (addAuthTokenToImageURLCallback && imagePreviewAuthRequiredURLs && imagePreviewAuthRequiredURLs.find((url) => imageHref.startsWith(url))) {
imageHref = addAuthTokenToImageURLCallback(imageHref);
}
}

const imageMarginTop = parseStringWithUnitToNumber(`${markdownStyle.inlineImage?.marginTop}`);
Expand Down
5 changes: 3 additions & 2 deletions src/web/utils/blockUtils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type {MarkdownTextInputElement} from '../../MarkdownTextInput.web';
import type {MarkdownRange} from '../../commonTypes';
import type {InlineImagesInputProps, MarkdownRange} from '../../commonTypes';
import type {PartialMarkdownStyle} from '../../styleUtils';
import {addInlineImagePreview} from '../inputElements/inlineImage';
import type {NodeType, TreeNode} from './treeUtils';
Expand Down Expand Up @@ -98,10 +98,11 @@ function extendBlockStructure(
ranges: MarkdownRange[],
text: string,
markdownStyle: PartialMarkdownStyle,
inlineImagesProps: InlineImagesInputProps,
) {
switch (currentRange.type) {
case 'inline-image':
return addInlineImagePreview(currentInput, targetNode, text, ranges, markdownStyle);
return addInlineImagePreview(currentInput, targetNode, text, ranges, markdownStyle, inlineImagesProps);
default:
break;
}
Expand Down
8 changes: 5 additions & 3 deletions src/web/utils/parserUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import type {NodeType, TreeNode} from './treeUtils';
import type {PartialMarkdownStyle} from '../../styleUtils';
import {getCurrentCursorPosition, moveCursorToEnd, setCursorPosition} from './cursorUtils';
import {addStyleToBlock, extendBlockStructure, getFirstBlockMarkdownRange, isBlockMarkdownType} from './blockUtils';
import type {MarkdownRange} from '../../commonTypes';
import type {InlineImagesInputProps, MarkdownRange} from '../../commonTypes';
import {getAnimationCurrentTimes, updateAnimationsTime} from './animationUtils';

type Paragraph = {
Expand Down Expand Up @@ -151,6 +151,7 @@ function parseRangesToHTMLNodes(
markdownStyle: PartialMarkdownStyle = {},
disableInlineStyles = false,
currentInput: MarkdownTextInputElement | null = null,
inlineImagesProps: InlineImagesInputProps = {},
) {
const rootElement: HTMLMarkdownElement = document.createElement('span') as HTMLMarkdownElement;
const textLength = text.length;
Expand Down Expand Up @@ -224,7 +225,7 @@ function parseRangesToHTMLNodes(
const spanNode = appendNode(span, currentParentNode, range.type, range.length);

if (isMultiline && !disableInlineStyles && currentInput) {
currentParentNode = extendBlockStructure(currentInput, currentParentNode, range, lineMarkdownRanges, text, markdownStyle);
currentParentNode = extendBlockStructure(currentInput, currentParentNode, range, lineMarkdownRanges, text, markdownStyle, inlineImagesProps);
}

if (lineMarkdownRanges.length > 0 && nextRangeStartIndex < endOfCurrentRange && range.type !== 'syntax') {
Expand Down Expand Up @@ -279,6 +280,7 @@ function updateInputStructure(
alwaysMoveCursorToTheEnd = false,
shouldForceDOMUpdate = false,
shouldScrollIntoView = false,
inlineImagesProps: InlineImagesInputProps = {},
) {
const targetElement = target;

Expand All @@ -297,7 +299,7 @@ function updateInputStructure(

// We don't want to parse text with single '\n', because contentEditable represents it as invisible <br />
if (text) {
const {dom, tree} = parseRangesToHTMLNodes(text, markdownRanges, isMultiline, markdownStyle, false, targetElement);
const {dom, tree} = parseRangesToHTMLNodes(text, markdownRanges, isMultiline, markdownStyle, false, targetElement, inlineImagesProps);

if (shouldForceDOMUpdate || targetElement.innerHTML !== dom.innerHTML) {
const animationTimes = getAnimationCurrentTimes(targetElement);
Expand Down

0 comments on commit 003e026

Please sign in to comment.