react-native-enriched-markdown-scaffold 1.0.2-scaffold.3 → 1.0.2-scaffold.5
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.
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownManagerDelegate.java +15 -0
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownManagerInterface.java +3 -0
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextManagerDelegate.java +15 -0
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextManagerInterface.java +3 -0
- package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/EventEmitters.cpp +122 -0
- package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/EventEmitters.h +100 -0
- package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/Props.cpp +20 -0
- package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/Props.h +124 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdown.kt +145 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownInternalText.kt +19 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownManager.kt +22 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownText.kt +85 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownTextManager.kt +22 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/events/LinkLayoutEvent.kt +36 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/events/SelectionChangeEvent.kt +42 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/LinkRenderer.kt +37 -7
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/SpanStyleCache.kt +5 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/CodeBackgroundSpan.kt +13 -99
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/InlineChipPainter.kt +140 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/LinkChipSpans.kt +177 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/LinkSpan.kt +1 -6
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/LinkStyle.kt +36 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/LinkVariantEntry.kt +7 -3
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/MarkdownViewManagerUtils.kt +28 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/conversion/HTMLGenerator.kt +2 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/conversion/MarkdownExtractor.kt +6 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/LinkLayoutCollector.kt +100 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/SelectionActionMode.kt +4 -2
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/SelectionChangeReporter.kt +230 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/views/CodeBlockContainerView.kt +11 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/views/TableContainerView.kt +22 -1
- package/android/src/math/java/com/swmansion/enriched/markdown/views/MathContainerView.kt +8 -1
- package/docs/API_REFERENCE.md +111 -0
- package/docs/MENTIONS.md +8 -1
- package/docs/STYLES.md +27 -0
- package/docs/TEXT.md +2 -0
- package/ios/EnrichedMarkdown.mm +221 -1
- package/ios/EnrichedMarkdownText.mm +142 -1
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/EventEmitters.cpp +122 -0
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/EventEmitters.h +100 -0
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/Props.cpp +20 -0
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/Props.h +124 -0
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/RCTComponentViewHelpers.h +50 -2
- package/ios/internals/MeasurementCache.h +5 -0
- package/ios/renderer/LinkRenderer.m +47 -15
- package/ios/styles/StyleConfig.h +16 -0
- package/ios/styles/StyleConfig.mm +60 -0
- package/ios/utils/CodeBackground.m +3 -65
- package/ios/utils/ENRMChipDrawing.h +24 -0
- package/ios/utils/ENRMChipDrawing.m +83 -0
- package/ios/utils/ENRMLinkChip.h +70 -0
- package/ios/utils/ENRMLinkChip.m +194 -0
- package/ios/utils/ENRMLinkLayout.h +50 -0
- package/ios/utils/ENRMLinkLayout.m +45 -0
- package/ios/utils/ENRMSelectionChange.h +96 -0
- package/ios/utils/ENRMSelectionChange.m +204 -0
- package/ios/utils/EditMenuUtils+macOS.m +4 -1
- package/ios/utils/EditMenuUtils.m +4 -1
- package/ios/utils/HTMLGenerator.m +2 -1
- package/ios/utils/MarkdownAccessibilityElementBuilder.m +3 -1
- package/ios/utils/MarkdownExtractor.m +2 -1
- package/ios/utils/RTFExportUtils.m +2 -0
- package/ios/utils/StylePropsUtils.h +37 -1
- package/ios/utils/TextViewLayoutManager.mm +3 -0
- package/ios/views/ENRMCodeBlockContainerView.h +3 -0
- package/ios/views/ENRMCodeBlockContainerView.m +3 -0
- package/ios/views/ENRMMathContainerView.h +3 -0
- package/ios/views/ENRMMathContainerView.m +3 -0
- package/ios/views/TableContainerView.h +6 -0
- package/ios/views/TableContainerView.m +24 -0
- package/lib/module/EnrichedMarkdownNativeComponent.ts +101 -1
- package/lib/module/EnrichedMarkdownTextNativeComponent.ts +101 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/jest/index.js +13 -0
- package/lib/module/jest/index.js.map +1 -1
- package/lib/module/native/EnrichedMarkdownText.js +138 -9
- package/lib/module/native/EnrichedMarkdownText.js.map +1 -1
- package/lib/module/normalizeMarkdownStyle.js +13 -2
- package/lib/module/normalizeMarkdownStyle.js.map +1 -1
- package/lib/module/normalizeMarkdownStyle.web.js +13 -2
- package/lib/module/normalizeMarkdownStyle.web.js.map +1 -1
- package/lib/module/web/EnrichedMarkdownText.js +6 -3
- package/lib/module/web/EnrichedMarkdownText.js.map +1 -1
- package/lib/module/web/renderers/InlineRenderers.js +96 -3
- package/lib/module/web/renderers/InlineRenderers.js.map +1 -1
- package/lib/module/web/styles.js +18 -0
- package/lib/module/web/styles.js.map +1 -1
- package/lib/module/web/utils.js +13 -0
- package/lib/module/web/utils.js.map +1 -1
- package/lib/typescript/src/EnrichedMarkdownNativeComponent.d.ts +93 -2
- package/lib/typescript/src/EnrichedMarkdownNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/EnrichedMarkdownTextNativeComponent.d.ts +93 -2
- package/lib/typescript/src/EnrichedMarkdownTextNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +2 -2
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/index.web.d.ts +1 -1
- package/lib/typescript/src/index.web.d.ts.map +1 -1
- package/lib/typescript/src/jest/index.d.ts +1 -1
- package/lib/typescript/src/jest/index.d.ts.map +1 -1
- package/lib/typescript/src/native/EnrichedMarkdownText.d.ts +5 -5
- package/lib/typescript/src/native/EnrichedMarkdownText.d.ts.map +1 -1
- package/lib/typescript/src/normalizeMarkdownStyle.d.ts.map +1 -1
- package/lib/typescript/src/normalizeMarkdownStyle.web.d.ts.map +1 -1
- package/lib/typescript/src/types/MarkdownStyle.d.ts +28 -5
- package/lib/typescript/src/types/MarkdownStyle.d.ts.map +1 -1
- package/lib/typescript/src/types/MarkdownStyleInternal.d.ts +10 -0
- package/lib/typescript/src/types/MarkdownStyleInternal.d.ts.map +1 -1
- package/lib/typescript/src/types/MarkdownTextProps.d.ts +76 -2
- package/lib/typescript/src/types/MarkdownTextProps.d.ts.map +1 -1
- package/lib/typescript/src/types/MarkdownTextProps.web.d.ts +41 -1
- package/lib/typescript/src/types/MarkdownTextProps.web.d.ts.map +1 -1
- package/lib/typescript/src/types/events.d.ts +36 -0
- package/lib/typescript/src/types/events.d.ts.map +1 -1
- package/lib/typescript/src/web/EnrichedMarkdownText.d.ts +1 -1
- package/lib/typescript/src/web/EnrichedMarkdownText.d.ts.map +1 -1
- package/lib/typescript/src/web/renderers/InlineRenderers.d.ts.map +1 -1
- package/lib/typescript/src/web/styles.d.ts.map +1 -1
- package/lib/typescript/src/web/types.d.ts +4 -0
- package/lib/typescript/src/web/types.d.ts.map +1 -1
- package/lib/typescript/src/web/utils.d.ts +4 -0
- package/lib/typescript/src/web/utils.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/EnrichedMarkdownNativeComponent.ts +101 -1
- package/src/EnrichedMarkdownTextNativeComponent.ts +101 -1
- package/src/index.tsx +5 -0
- package/src/index.web.tsx +5 -1
- package/src/jest/index.tsx +21 -1
- package/src/native/EnrichedMarkdownText.tsx +181 -8
- package/src/normalizeMarkdownStyle.ts +13 -0
- package/src/normalizeMarkdownStyle.web.ts +11 -0
- package/src/types/MarkdownStyle.ts +29 -5
- package/src/types/MarkdownStyleInternal.ts +10 -0
- package/src/types/MarkdownTextProps.ts +85 -1
- package/src/types/MarkdownTextProps.web.ts +43 -1
- package/src/types/events.ts +38 -0
- package/src/web/EnrichedMarkdownText.tsx +10 -3
- package/src/web/renderers/InlineRenderers.tsx +111 -3
- package/src/web/styles.ts +25 -0
- package/src/web/types.ts +4 -0
- package/src/web/utils.ts +8 -0
package/src/types/events.ts
CHANGED
|
@@ -40,6 +40,44 @@ export interface CopyEvent {
|
|
|
40
40
|
whole: boolean;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
+
/**
|
|
44
|
+
* A rect in dp, relative to the component's native view: add the origin from
|
|
45
|
+
* the component ref's `measureInWindow` to get window coordinates.
|
|
46
|
+
*/
|
|
47
|
+
export interface SelectionRect {
|
|
48
|
+
x: number;
|
|
49
|
+
y: number;
|
|
50
|
+
width: number;
|
|
51
|
+
height: number;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Payload of `onSelectionChange`: the current text selection, or a table /
|
|
56
|
+
* math / code block long-pressed while `contextMenuHidden` is on. Content
|
|
57
|
+
* fields carry what `onCopy` would receive for the same selection.
|
|
58
|
+
*/
|
|
59
|
+
export interface SelectionChangeEvent {
|
|
60
|
+
/** `false` once the selection is gone; every other field is then empty / zero. */
|
|
61
|
+
active: boolean;
|
|
62
|
+
/** `'selection'` for text; the block kind for a long-pressed block. */
|
|
63
|
+
source: CopyEvent['source'];
|
|
64
|
+
/** Rendered text of the selection, or the block's raw content. */
|
|
65
|
+
text: string;
|
|
66
|
+
/** Same as `CopyEvent.markdown` for this selection. */
|
|
67
|
+
markdown: string;
|
|
68
|
+
/** Same as `CopyEvent.whole`. Always `true` for blocks. */
|
|
69
|
+
whole: boolean;
|
|
70
|
+
/**
|
|
71
|
+
* Bounding box of the selection (full content width when it spans several
|
|
72
|
+
* lines); the block's frame for blocks.
|
|
73
|
+
*/
|
|
74
|
+
rect: SelectionRect;
|
|
75
|
+
/** Selected part of the first line (block: same as `rect`). */
|
|
76
|
+
startRect: SelectionRect;
|
|
77
|
+
/** Selected part of the last line (block: same as `rect`). */
|
|
78
|
+
endRect: SelectionRect;
|
|
79
|
+
}
|
|
80
|
+
|
|
43
81
|
/**
|
|
44
82
|
* Native-level context menu item config sent to the native component.
|
|
45
83
|
* Does not include the `onPress` callback — callbacks are managed on the JS side.
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
import { parseMarkdown } from './parseMarkdown';
|
|
10
10
|
import { RenderNode } from './renderers';
|
|
11
11
|
import type { ASTNode, RendererCallbacks, RenderCapabilities } from './types';
|
|
12
|
-
import { indexTaskItems, markInlineImages } from './utils';
|
|
12
|
+
import { indexLinks, indexTaskItems, markInlineImages } from './utils';
|
|
13
13
|
import { loadKaTeX } from './katex';
|
|
14
14
|
import type { KaTeXInstance } from './katex';
|
|
15
15
|
import { ENRM_TEXT_CLASS, ENRM_SELECTION_BG_VAR } from './globalStyles';
|
|
@@ -27,6 +27,7 @@ export const EnrichedMarkdownText = ({
|
|
|
27
27
|
selectable = true,
|
|
28
28
|
dir,
|
|
29
29
|
selectionColor,
|
|
30
|
+
renderLinkDecoration,
|
|
30
31
|
...rest
|
|
31
32
|
}: EnrichedMarkdownTextProps) => {
|
|
32
33
|
const normalizedStyle = useMemo(
|
|
@@ -66,6 +67,7 @@ export const EnrichedMarkdownText = ({
|
|
|
66
67
|
.then(([result, katexInstance]) => {
|
|
67
68
|
if (!cancelled) {
|
|
68
69
|
indexTaskItems(result);
|
|
70
|
+
indexLinks(result);
|
|
69
71
|
markInlineImages(result);
|
|
70
72
|
|
|
71
73
|
setParseError(false);
|
|
@@ -99,8 +101,13 @@ export const EnrichedMarkdownText = ({
|
|
|
99
101
|
]);
|
|
100
102
|
|
|
101
103
|
const callbacks = useMemo<RendererCallbacks>(
|
|
102
|
-
() => ({
|
|
103
|
-
|
|
104
|
+
() => ({
|
|
105
|
+
onLinkPress,
|
|
106
|
+
onLinkLongPress,
|
|
107
|
+
onTaskListItemPress,
|
|
108
|
+
renderLinkDecoration,
|
|
109
|
+
}),
|
|
110
|
+
[onLinkPress, onLinkLongPress, onTaskListItemPress, renderLinkDecoration]
|
|
104
111
|
);
|
|
105
112
|
|
|
106
113
|
const capabilities = useMemo<RenderCapabilities>(
|
|
@@ -1,8 +1,16 @@
|
|
|
1
|
-
import
|
|
1
|
+
import {
|
|
2
|
+
useLayoutEffect,
|
|
3
|
+
useRef,
|
|
4
|
+
useState,
|
|
5
|
+
type MouseEvent,
|
|
6
|
+
type ReactNode,
|
|
7
|
+
} from 'react';
|
|
8
|
+
import type { LinkRect } from '../../types/MarkdownTextProps.web';
|
|
2
9
|
import type { RendererProps, RendererMap } from '../types';
|
|
3
10
|
import { extractNodeText } from '../utils';
|
|
4
11
|
import { KaTeXRenderer } from './KaTeXRenderer';
|
|
5
12
|
import { linkStyleForUrl } from '../styles';
|
|
13
|
+
import type { CSSProperties } from 'react';
|
|
6
14
|
|
|
7
15
|
function TextRenderer({ node }: RendererProps) {
|
|
8
16
|
return <>{node.content ?? ''}</>;
|
|
@@ -78,16 +86,116 @@ function LinkRenderer({
|
|
|
78
86
|
}
|
|
79
87
|
};
|
|
80
88
|
|
|
89
|
+
const linkStyle = linkStyleForUrl(style, url);
|
|
90
|
+
const children = renderChildren(node);
|
|
91
|
+
|
|
92
|
+
if (callbacks.renderLinkDecoration) {
|
|
93
|
+
return (
|
|
94
|
+
<DecoratedLink
|
|
95
|
+
url={url}
|
|
96
|
+
index={node.attributes?.linkIndex ?? 0}
|
|
97
|
+
text={extractNodeText(node)}
|
|
98
|
+
linkStyle={linkStyle}
|
|
99
|
+
renderLinkDecoration={callbacks.renderLinkDecoration}
|
|
100
|
+
onClick={handleClick}
|
|
101
|
+
onContextMenu={handleContextMenu}
|
|
102
|
+
>
|
|
103
|
+
{children}
|
|
104
|
+
</DecoratedLink>
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
|
|
81
108
|
return (
|
|
82
109
|
<a
|
|
83
110
|
href={url}
|
|
84
|
-
style={
|
|
111
|
+
style={linkStyle}
|
|
85
112
|
target="_blank"
|
|
86
113
|
rel="noopener noreferrer"
|
|
87
114
|
onClick={handleClick}
|
|
88
115
|
onContextMenu={handleContextMenu}
|
|
89
116
|
>
|
|
90
|
-
{
|
|
117
|
+
{children}
|
|
118
|
+
</a>
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const EMPTY_RECT: LinkRect = { x: 0, y: 0, width: 0, height: 0 };
|
|
123
|
+
|
|
124
|
+
const decorationLayerStyle: CSSProperties = {
|
|
125
|
+
position: 'absolute',
|
|
126
|
+
inset: 0,
|
|
127
|
+
pointerEvents: 'none',
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
const decorationContentStyle: CSSProperties = { pointerEvents: 'auto' };
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* A link with a `renderLinkDecoration` overlay. Unlike native, the overlay
|
|
134
|
+
* anchors to the link's whole inline box (not the last line fragment of a
|
|
135
|
+
* wrapping link), and `rect` is that box relative to itself.
|
|
136
|
+
*/
|
|
137
|
+
function DecoratedLink({
|
|
138
|
+
url,
|
|
139
|
+
index,
|
|
140
|
+
text,
|
|
141
|
+
linkStyle,
|
|
142
|
+
renderLinkDecoration,
|
|
143
|
+
onClick,
|
|
144
|
+
onContextMenu,
|
|
145
|
+
children,
|
|
146
|
+
}: {
|
|
147
|
+
url: string;
|
|
148
|
+
index: number;
|
|
149
|
+
text: string;
|
|
150
|
+
linkStyle: ReturnType<typeof linkStyleForUrl>;
|
|
151
|
+
renderLinkDecoration: NonNullable<
|
|
152
|
+
RendererProps['callbacks']['renderLinkDecoration']
|
|
153
|
+
>;
|
|
154
|
+
onClick: (event: MouseEvent) => void;
|
|
155
|
+
onContextMenu: (event: MouseEvent) => void;
|
|
156
|
+
children: ReactNode;
|
|
157
|
+
}) {
|
|
158
|
+
const anchorRef = useRef<HTMLAnchorElement>(null);
|
|
159
|
+
const [rect, setRect] = useState<LinkRect>(EMPTY_RECT);
|
|
160
|
+
|
|
161
|
+
// The overlay itself is sized by CSS (inset: 0); `rect` is informational, so
|
|
162
|
+
// re-measuring when the content or chip style changes is enough.
|
|
163
|
+
useLayoutEffect(() => {
|
|
164
|
+
const anchor = anchorRef.current;
|
|
165
|
+
if (!anchor) return;
|
|
166
|
+
const { width, height } = anchor.getBoundingClientRect();
|
|
167
|
+
setRect((prev) =>
|
|
168
|
+
prev.width === width && prev.height === height
|
|
169
|
+
? prev
|
|
170
|
+
: { x: 0, y: 0, width, height }
|
|
171
|
+
);
|
|
172
|
+
}, [text, linkStyle]);
|
|
173
|
+
|
|
174
|
+
const decoration = renderLinkDecoration({
|
|
175
|
+
index,
|
|
176
|
+
url,
|
|
177
|
+
text,
|
|
178
|
+
rect,
|
|
179
|
+
rects: [rect],
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
return (
|
|
183
|
+
<a
|
|
184
|
+
ref={anchorRef}
|
|
185
|
+
href={url}
|
|
186
|
+
style={{ ...linkStyle, position: 'relative' }} // eslint-disable-line react-native/no-inline-styles
|
|
187
|
+
target="_blank"
|
|
188
|
+
rel="noopener noreferrer"
|
|
189
|
+
onClick={onClick}
|
|
190
|
+
onContextMenu={onContextMenu}
|
|
191
|
+
>
|
|
192
|
+
{children}
|
|
193
|
+
{decoration != null && (
|
|
194
|
+
<span aria-hidden style={decorationLayerStyle}>
|
|
195
|
+
{/* Mirrors native pointerEvents="box-none": only the decoration itself is hit-testable. */}
|
|
196
|
+
<span style={decorationContentStyle}>{decoration}</span>
|
|
197
|
+
</span>
|
|
198
|
+
)}
|
|
91
199
|
</a>
|
|
92
200
|
);
|
|
93
201
|
}
|
package/src/web/styles.ts
CHANGED
|
@@ -323,6 +323,12 @@ export function linkStyleForUrl(
|
|
|
323
323
|
variantIndex !== -1 ? style.linkVariants[variantIndex]! : base;
|
|
324
324
|
|
|
325
325
|
const backgroundColor = resolved.backgroundColor;
|
|
326
|
+
const hasBorder =
|
|
327
|
+
resolved.borderWidth > 0 &&
|
|
328
|
+
!!resolved.borderColor &&
|
|
329
|
+
resolved.borderColor !== 'transparent';
|
|
330
|
+
const hasPadding =
|
|
331
|
+
resolved.paddingHorizontal > 0 || resolved.paddingVertical > 0;
|
|
326
332
|
return {
|
|
327
333
|
color: resolved.color,
|
|
328
334
|
fontFamily: normalizeFontFamily(base.fontFamily),
|
|
@@ -330,6 +336,25 @@ export function linkStyleForUrl(
|
|
|
330
336
|
...(backgroundColor && backgroundColor !== 'transparent'
|
|
331
337
|
? { backgroundColor }
|
|
332
338
|
: undefined),
|
|
339
|
+
// Chip: inline padding reserves horizontal space like native; vertical
|
|
340
|
+
// padding only paints (inline boxes don't grow the line box). `clone`
|
|
341
|
+
// rounds and pads each fragment of a wrapping link.
|
|
342
|
+
...(hasPadding
|
|
343
|
+
? {
|
|
344
|
+
padding: `${resolved.paddingVertical}px ${resolved.paddingHorizontal}px`,
|
|
345
|
+
}
|
|
346
|
+
: undefined),
|
|
347
|
+
...(resolved.borderRadius > 0
|
|
348
|
+
? { borderRadius: resolved.borderRadius }
|
|
349
|
+
: undefined),
|
|
350
|
+
...(hasBorder
|
|
351
|
+
? {
|
|
352
|
+
border: `${resolved.borderWidth}px solid ${resolved.borderColor}`,
|
|
353
|
+
}
|
|
354
|
+
: undefined),
|
|
355
|
+
...(hasPadding || hasBorder || resolved.borderRadius > 0
|
|
356
|
+
? { boxDecorationBreak: 'clone', WebkitBoxDecorationBreak: 'clone' }
|
|
357
|
+
: undefined),
|
|
333
358
|
};
|
|
334
359
|
}
|
|
335
360
|
|
package/src/web/types.ts
CHANGED
|
@@ -6,6 +6,7 @@ import type {
|
|
|
6
6
|
LinkLongPressEvent,
|
|
7
7
|
TaskListItemPressEvent,
|
|
8
8
|
} from '../types/events';
|
|
9
|
+
import type { LinkDecorationInfo } from '../types/MarkdownTextProps.web';
|
|
9
10
|
import type { KaTeXInstance } from './katex';
|
|
10
11
|
|
|
11
12
|
export type NodeType =
|
|
@@ -52,6 +53,8 @@ export interface NodeAttributes {
|
|
|
52
53
|
taskIndex?: number;
|
|
53
54
|
/** Stamped by markInlineImages() — not present in the raw WASM output. */
|
|
54
55
|
isInline?: boolean;
|
|
56
|
+
/** Stamped by indexLinks() — document-order link index, not in the raw WASM output. */
|
|
57
|
+
linkIndex?: number;
|
|
55
58
|
colCount?: string;
|
|
56
59
|
headRowCount?: string;
|
|
57
60
|
bodyRowCount?: string;
|
|
@@ -72,6 +75,7 @@ export interface RendererCallbacks {
|
|
|
72
75
|
onLinkPress?: (event: LinkPressEvent) => void;
|
|
73
76
|
onLinkLongPress?: (event: LinkLongPressEvent) => void;
|
|
74
77
|
onTaskListItemPress?: (event: TaskListItemPressEvent) => void;
|
|
78
|
+
renderLinkDecoration?: (info: LinkDecorationInfo) => ReactNode | null;
|
|
75
79
|
}
|
|
76
80
|
|
|
77
81
|
export interface RenderCapabilities {
|
package/src/web/utils.ts
CHANGED
|
@@ -30,6 +30,14 @@ export function indexTaskItems(node: ASTNode, counter = { value: 0 }): void {
|
|
|
30
30
|
node.children?.forEach((child) => indexTaskItems(child, counter));
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
+
/** Stamps Link nodes with their document-order index (the `renderLinkDecoration` key). */
|
|
34
|
+
export function indexLinks(node: ASTNode, counter = { value: 0 }): void {
|
|
35
|
+
if (node.type === 'Link') {
|
|
36
|
+
node.attributes = { ...node.attributes, linkIndex: counter.value++ };
|
|
37
|
+
}
|
|
38
|
+
node.children?.forEach((child) => indexLinks(child, counter));
|
|
39
|
+
}
|
|
40
|
+
|
|
33
41
|
/**
|
|
34
42
|
* Stamps Image nodes with `isInline` when they appear inside a paragraph
|
|
35
43
|
* that also contains other content (text, links, etc.).
|