react-native-enriched-markdown-scaffold 0.7.4-scaffold.9 → 1.0.2-scaffold.10
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/README.md +54 -8
- package/ReactNativeEnrichedMarkdown.podspec +82 -73
- package/android/build.gradle +188 -1
- package/android/consumer-rules.pro +1 -1
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownManagerDelegate.java +27 -0
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownManagerInterface.java +7 -0
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextInputManagerDelegate.java +24 -0
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextInputManagerInterface.java +8 -0
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextManagerDelegate.java +27 -0
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextManagerInterface.java +7 -0
- package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/EventEmitters.cpp +223 -0
- package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/EventEmitters.h +183 -0
- package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/Props.cpp +65 -0
- package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/Props.h +1086 -61
- package/android/src/main/baseline-prof.txt +1 -1
- package/android/src/main/cpp/jni-adapter.cpp +74 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdown.kt +351 -13
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownInternalText.kt +62 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownManager.kt +85 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownText.kt +160 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownTextLayoutManager.kt +10 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownTextManager.kt +76 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/MeasurementStore.kt +126 -10
- package/android/src/main/java/com/swmansion/enriched/markdown/events/CopyPressEvent.kt +24 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/events/CopyRequestEvent.kt +28 -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 +43 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/EnrichedMarkdownTextInputManager.kt +54 -4
- package/android/src/main/java/com/swmansion/enriched/markdown/input/EnrichedMarkdownTextInputView.kt +923 -462
- package/android/src/main/java/com/swmansion/enriched/markdown/input/MarkdownClipboard.kt +42 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/BlockEditCoordinator.kt +196 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/ClipboardCoordinator.kt +73 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/EditContext.kt +19 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/EditPipeline.kt +248 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/EditSession.kt +52 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/InputConnectionWrapper.kt +108 -7
- package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/LinkCoordinator.kt +69 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/MarkdownTextWatcher.kt +3 -3
- package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/MentionCoordinator.kt +118 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnChangeStateEvent.kt +26 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnContextMenuItemPressEvent.kt +26 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnInputKeyPressEvent.kt +24 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnPasteEvent.kt +24 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/BlockStore.kt +254 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/FormattingStore.kt +80 -87
- package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/InputFormatter.kt +109 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/InputParser.kt +116 -22
- package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/MarkdownSerializer.kt +167 -38
- package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/RangeEditAdjustment.kt +149 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/layout/InputEventEmitter.kt +66 -5
- package/android/src/main/java/com/swmansion/enriched/markdown/input/layout/InputMeasurementStore.kt +4 -2
- package/android/src/main/java/com/swmansion/enriched/markdown/input/model/BlockRange.kt +27 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/model/BlockType.kt +48 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/model/FormattingRange.kt +9 -4
- package/android/src/main/java/com/swmansion/enriched/markdown/input/model/InputFormatterStyle.kt +39 -2
- package/android/src/main/java/com/swmansion/enriched/markdown/input/model/MathAtom.kt +20 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/model/MathChipStyle.kt +1 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/input/model/MutableRangeBounds.kt +11 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/spans/InputBulletSpan.kt +82 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/spans/InputHeadingSpan.kt +58 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/spans/InputListItemSpacingSpan.kt +37 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/spans/InputOrderedListMarkerSpan.kt +63 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/styles/BlockHandler.kt +54 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/styles/HeadingBlockHandler.kt +27 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/styles/OrderedListBlockHandler.kt +38 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/styles/UnorderedListBlockHandler.kt +37 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/toolbar/InputContextMenu.kt +8 -26
- package/android/src/main/java/com/swmansion/enriched/markdown/parser/MarkdownASTNode.kt +1 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/parser/Parser.kt +1 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/BlockStyleContext.kt +9 -2
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/BlockquoteRenderer.kt +100 -12
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/CodeBlockRenderer.kt +16 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/HeadingRenderer.kt +4 -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/ListContextManager.kt +2 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListItemRenderer.kt +74 -18
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListRenderer.kt +43 -4
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/NodeRenderer.kt +9 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/SoftBreakRenderer.kt +16 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/SpanStyleCache.kt +35 -28
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/BaseListSpan.kt +24 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/BlockquoteSpan.kt +174 -24
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/CodeBackgroundSpan.kt +20 -82
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/CodeBlockSpan.kt +13 -16
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/CodeSpan.kt +1 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/EmphasisSpan.kt +1 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/ImageSpan.kt +182 -46
- 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/spans/ListItemSpacingSpan.kt +33 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/ListMarkerAnchorSpan.kt +38 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/OrderedListSpan.kt +2 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/StrongSpan.kt +1 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/TaskListSpan.kt +3 -2
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/UnorderedListSpan.kt +3 -2
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/BlockquoteStyle.kt +6 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/CodeBlockStyle.kt +26 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/ImageStyle.kt +7 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/InlineMathStyle.kt +16 -1
- 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/styles/ListStyle.kt +4 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/MathStyle.kt +3 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/StyleConfig.kt +13 -4
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/TableStyle.kt +6 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/CodeBlockHighlighter.kt +90 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/CodeBlockNode.kt +57 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/FeatureFlags.kt +1 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/MarkdownSegment.kt +9 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/MarkdownViewManagerUtils.kt +84 -7
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/ReadableMapExtensions.kt +3 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/RenderedSegment.kt +10 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/SegmentSignature.kt +1 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/StreamingMarkdownFilter.kt +83 -5
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/serialization/MarkdownASTSerializer.kt +4 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/input/MarkdownStyleParser.kt +74 -44
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/input/PasteTextUtils.kt +52 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/ImageCache.kt +26 -3
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/ImageDownloader.kt +22 -9
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/LocalImageLoader.kt +161 -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/extensions/TextPaintExtensions.kt +23 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/interaction/CheckboxTouchHelper.kt +7 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/interaction/TaskListTapUtils.kt +41 -21
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/span/BlockSpacing.kt +15 -8
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/HeadlessActionMode.kt +88 -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/LinkLongPressMovementMethod.kt +58 -27
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/SelectionActionMode.kt +72 -16
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/SelectionChangeReporter.kt +232 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/views/BlockMenuOptions.kt +64 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/views/CodeBlockContainerView.kt +414 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/views/ContextMenuPopup.kt +9 -6
- package/android/src/main/java/com/swmansion/enriched/markdown/views/CopyGlyph.kt +101 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/views/TableContainerView.kt +61 -11
- package/android/src/main/jni/CMakeLists.txt +53 -0
- package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownContainerShadowNode.cpp +10 -0
- package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownContainerShadowNode.h +11 -2
- package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextShadowNode.cpp +10 -0
- package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextShadowNode.h +12 -2
- package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextState.cpp +9 -0
- package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextState.h +24 -0
- package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/conversions.h +16 -0
- package/android/src/math/java/com/swmansion/enriched/markdown/input/math/MathChipControllerImpl.kt +21 -4
- package/android/src/math/java/com/swmansion/enriched/markdown/renderer/MathInlineRenderer.kt +8 -2
- package/android/src/math/java/com/swmansion/enriched/markdown/spans/MathChipSpan.kt +1 -1
- package/android/src/math/java/com/swmansion/enriched/markdown/spans/MathInlineSpan.kt +13 -6
- package/android/src/math/java/com/swmansion/enriched/markdown/spans/MathMeasureHelper.kt +2 -1
- package/android/src/math/java/com/swmansion/enriched/markdown/views/MathContainerView.kt +26 -8
- package/cpp/highlight/CodeBlockHighlighter.cpp +284 -0
- package/cpp/highlight/CodeBlockHighlighter.hpp +66 -0
- package/cpp/highlight/CodeBlockLanguages.cpp +138 -0
- package/cpp/highlight/CodeBlockLanguages.hpp +25 -0
- package/cpp/highlight/HighlightGrammars.hpp +28 -0
- package/cpp/highlight/code_highlight_podspec.rb +211 -0
- package/cpp/highlight/gen-registry.mjs +155 -0
- package/cpp/highlight/grammar-versions.json +159 -0
- package/cpp/highlight/vendor/generated/generated_queries.h +1665 -0
- package/cpp/highlight/vendor/generated/generated_registry.cpp +59 -0
- package/cpp/parser/MD4CParser.cpp +173 -61
- package/cpp/parser/MD4CParser.hpp +1 -0
- package/cpp/parser/MarkdownASTNode.hpp +2 -1
- package/cpp/wasm/ASTSerializer.cpp +2 -0
- package/cpp/wasm/build.sh +1 -0
- package/cpp/wasm/md4c_wasm.cpp +3 -1
- package/docs/ACCESSIBILITY.md +14 -2
- package/docs/API_REFERENCE.md +405 -12
- package/docs/BREAKING_CHANGES.md +129 -0
- package/docs/CODE_HIGHLIGHT.md +133 -0
- package/docs/COPY_OPTIONS.md +61 -3
- package/docs/ELEMENTS_STRUCTURE.md +52 -4
- package/docs/IMAGE_CACHING.md +30 -0
- package/docs/INPUT.md +110 -11
- package/docs/LATEX_MATH.md +87 -45
- package/docs/MACOS.md +1 -1
- package/docs/MARKDOWN_STREAMING.md +27 -1
- package/docs/MENTIONS.md +8 -1
- package/docs/NATIVE_ASSETS.md +127 -0
- package/docs/RTL.md +1 -1
- package/docs/STYLES.md +73 -6
- package/docs/TESTING.md +112 -0
- package/docs/TEXT.md +18 -6
- package/docs/WEB.md +4 -1
- package/ios/EnrichedMarkdown.h +7 -0
- package/ios/EnrichedMarkdown.mm +583 -76
- package/ios/EnrichedMarkdownText.h +7 -0
- package/ios/EnrichedMarkdownText.mm +299 -73
- package/ios/attachments/ENRMImageAttachment.h +9 -0
- package/ios/attachments/ENRMImageAttachment.m +143 -40
- package/ios/attachments/ENRMMathInlineAttachment+macOS.m +2 -1
- package/ios/attachments/ENRMMathInlineAttachment.h +5 -0
- package/ios/attachments/ENRMMathInlineAttachment.m +50 -82
- package/ios/attachments/ENRMMathInlineAttachmentShared.h +2 -0
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/EventEmitters.cpp +223 -0
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/EventEmitters.h +183 -0
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/Props.cpp +65 -0
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/Props.h +1086 -61
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/RCTComponentViewHelpers.h +181 -2
- package/ios/input/ENRMAutoLinkDetector.h +2 -1
- package/ios/input/ENRMAutoLinkDetector.mm +79 -41
- package/ios/input/ENRMBlockEditCoordinator.h +71 -0
- package/ios/input/ENRMBlockEditCoordinator.mm +195 -0
- package/ios/input/ENRMBlockRange.h +28 -0
- package/ios/input/ENRMBlockRange.mm +30 -0
- package/ios/input/ENRMBlockStore.h +56 -0
- package/ios/input/ENRMBlockStore.mm +275 -0
- package/ios/input/ENRMClipboardCoordinator.h +45 -0
- package/ios/input/ENRMClipboardCoordinator.mm +120 -0
- package/ios/input/ENRMDetectorPipeline.h +2 -1
- package/ios/input/ENRMEditPipeline.h +76 -0
- package/ios/input/ENRMEditPipeline.mm +228 -0
- package/ios/input/ENRMEditSession.h +36 -0
- package/ios/input/ENRMEditSession.mm +63 -0
- package/ios/input/ENRMFormattingStore.h +17 -0
- package/ios/input/ENRMFormattingStore.mm +95 -105
- package/ios/input/ENRMInputBlockType.h +91 -0
- package/ios/input/ENRMInputBlockType.mm +5 -0
- package/ios/input/ENRMInputDecorationDrawer.h +18 -0
- package/ios/input/ENRMInputEventEmitter.h +56 -0
- package/ios/input/ENRMInputEventEmitter.mm +308 -0
- package/ios/input/ENRMInputFormatter.h +29 -69
- package/ios/input/ENRMInputFormatter.mm +216 -124
- package/ios/input/ENRMInputFormatterStyle.h +99 -0
- package/ios/input/ENRMInputFormatterStyle.mm +188 -0
- package/ios/input/ENRMInputLayoutManager.h +9 -0
- package/ios/input/ENRMInputLayoutManager.mm +30 -0
- package/ios/input/ENRMInputListMarkerDrawer.h +32 -0
- package/ios/input/ENRMInputListMarkerDrawer.mm +426 -0
- package/ios/input/ENRMInputParser.h +5 -6
- package/ios/input/ENRMInputParser.mm +461 -178
- package/ios/input/ENRMInputRemend.mm +2 -2
- package/ios/input/ENRMInputStyleStateBuilder.h +40 -0
- package/ios/input/ENRMInputStyleStateBuilder.mm +60 -0
- package/ios/input/ENRMInputTextView.mm +103 -8
- package/ios/input/ENRMInputTypingAttributesController.h +42 -0
- package/ios/input/ENRMInputTypingAttributesController.mm +203 -0
- package/ios/input/ENRMLinkCoordinator.h +41 -0
- package/ios/input/ENRMLinkCoordinator.mm +89 -0
- package/ios/input/ENRMMarkdownSerializer.h +29 -5
- package/ios/input/ENRMMarkdownSerializer.mm +170 -48
- package/ios/input/ENRMMathAtom.h +26 -0
- package/ios/input/ENRMMathAtom.mm +12 -0
- package/ios/input/ENRMMentionCoordinator.h +45 -0
- package/ios/input/ENRMMentionCoordinator.mm +167 -0
- package/ios/input/ENRMRangeEditAdjustment.h +38 -0
- package/ios/input/ENRMRangeEditAdjustment.mm +91 -0
- package/ios/input/ENRMRangeStoreUtils.h +39 -0
- package/ios/input/EnrichedMarkdownTextInput+ContextMenu.mm +6 -6
- package/ios/input/EnrichedMarkdownTextInput+Internal.h +11 -3
- package/ios/input/EnrichedMarkdownTextInput.h +7 -1
- package/ios/input/EnrichedMarkdownTextInput.mm +1089 -1023
- package/ios/input/InputStylePropsUtils.h +109 -68
- package/ios/input/internals/EnrichedMarkdownTextInputShadowNode.mm +2 -1
- package/ios/input/styles/ENRMBlockHandler.h +46 -0
- package/ios/input/styles/ENRMHeadingBlockHandler.h +15 -0
- package/ios/input/styles/ENRMHeadingBlockHandler.mm +38 -0
- package/ios/input/styles/ENRMOrderedListBlockHandler.h +14 -0
- package/ios/input/styles/ENRMOrderedListBlockHandler.mm +48 -0
- package/ios/input/styles/ENRMUnorderedListBlockHandler.h +15 -0
- package/ios/input/styles/ENRMUnorderedListBlockHandler.mm +51 -0
- package/ios/internals/ENRMViewFreeMeasurement.h +331 -0
- package/ios/internals/EnrichedMarkdownShadowNode.h +1 -3
- package/ios/internals/EnrichedMarkdownShadowNode.mm +16 -20
- package/ios/internals/EnrichedMarkdownTextShadowNode.h +1 -3
- package/ios/internals/EnrichedMarkdownTextShadowNode.mm +15 -20
- package/ios/internals/MeasurementCache.h +41 -9
- package/ios/internals/ShadowMeasurementUtils.h +63 -58
- package/ios/math/ENRMMathChipController.h +74 -0
- package/ios/math/ENRMMathChipController.mm +476 -0
- package/ios/math/ENRMRaTeXBridge.swift +27 -6
- package/ios/parser/ENRMMarkdownParser.h +1 -8
- package/ios/parser/ENRMMarkdownParser.mm +2 -11
- package/ios/parser/MarkdownASTNode.h +2 -1
- package/ios/parser/MarkdownParserBridge.mm +4 -0
- package/ios/renderer/AttributedRenderer.m +20 -2
- package/ios/renderer/BaseRenderer.h +17 -2
- package/ios/renderer/BaseRenderer.m +30 -0
- package/ios/renderer/BlockquoteRenderer.h +1 -1
- package/ios/renderer/BlockquoteRenderer.m +144 -35
- package/ios/renderer/CodeBlockRenderer.h +1 -1
- package/ios/renderer/CodeBlockRenderer.m +27 -23
- package/ios/renderer/CodeRenderer.h +1 -1
- package/ios/renderer/CodeRenderer.m +3 -1
- package/ios/renderer/ENRMImageRenderer.h +1 -1
- package/ios/renderer/ENRMImageRenderer.m +5 -1
- package/ios/renderer/ENRMMathInlineRenderer.h +1 -1
- package/ios/renderer/ENRMMathInlineRenderer.m +6 -1
- package/ios/renderer/ENRMSpoilerRenderer.h +1 -1
- package/ios/renderer/ENRMSpoilerRenderer.m +3 -1
- package/ios/renderer/EmphasisRenderer.h +1 -1
- package/ios/renderer/EmphasisRenderer.m +3 -1
- package/ios/renderer/HeadingRenderer.h +1 -1
- package/ios/renderer/HeadingRenderer.m +13 -6
- package/ios/renderer/HighlightRenderer.h +1 -1
- package/ios/renderer/HighlightRenderer.m +3 -1
- package/ios/renderer/LinkRenderer.h +1 -1
- package/ios/renderer/LinkRenderer.m +50 -16
- package/ios/renderer/ListItemRenderer.h +13 -1
- package/ios/renderer/ListItemRenderer.m +102 -44
- package/ios/renderer/ListRenderer.h +2 -2
- package/ios/renderer/ListRenderer.m +63 -25
- package/ios/renderer/ParagraphRenderer.h +1 -1
- package/ios/renderer/ParagraphRenderer.m +16 -8
- package/ios/renderer/RenderContext.h +10 -0
- package/ios/renderer/RenderContext.m +44 -0
- package/ios/renderer/RendererFactory.m +14 -0
- package/ios/renderer/StrikethroughRenderer.h +1 -1
- package/ios/renderer/StrikethroughRenderer.m +3 -1
- package/ios/renderer/StrongRenderer.h +1 -1
- package/ios/renderer/StrongRenderer.m +3 -1
- package/ios/renderer/SubscriptRenderer.h +1 -1
- package/ios/renderer/SubscriptRenderer.m +3 -1
- package/ios/renderer/SuperscriptRenderer.h +1 -1
- package/ios/renderer/SuperscriptRenderer.m +3 -1
- package/ios/renderer/TextRenderer.h +2 -2
- package/ios/renderer/TextRenderer.m +3 -1
- package/ios/renderer/ThematicBreakRenderer.h +1 -1
- package/ios/renderer/ThematicBreakRenderer.m +3 -1
- package/ios/renderer/UnderlineRenderer.h +1 -1
- package/ios/renderer/UnderlineRenderer.m +3 -1
- package/ios/styles/StyleConfig.h +42 -0
- package/ios/styles/StyleConfig.mm +216 -0
- package/ios/utils/BlockquoteBorder.h +6 -0
- package/ios/utils/BlockquoteBorder.m +249 -52
- package/ios/utils/CodeBackground.m +3 -65
- package/ios/utils/CodeBlockBackground.m +16 -2
- package/ios/utils/ENRMAtomicSize.h +65 -0
- package/ios/utils/ENRMBlockMenu.h +66 -0
- package/ios/utils/ENRMChipDrawing.h +24 -0
- package/ios/utils/ENRMChipDrawing.m +83 -0
- package/ios/utils/ENRMCodeBlockContent.h +37 -0
- package/ios/utils/ENRMCodeBlockContent.mm +79 -0
- package/ios/utils/ENRMCodeBlockHighlighter.h +37 -0
- package/ios/utils/ENRMCodeBlockHighlighter.mm +51 -0
- package/ios/utils/ENRMFeatureFlags.h +7 -0
- package/ios/utils/ENRMImageDownloader.h +11 -1
- package/ios/utils/ENRMImageDownloader.m +60 -16
- package/ios/utils/ENRMLinkChip.h +70 -0
- package/ios/utils/ENRMLinkChip.m +213 -0
- package/ios/utils/ENRMLinkLayout.h +50 -0
- package/ios/utils/ENRMLinkLayout.m +45 -0
- package/ios/utils/ENRMLocalImageLoader.h +31 -0
- package/ios/utils/ENRMLocalImageLoader.m +68 -0
- package/ios/utils/ENRMMathFallback.h +26 -0
- package/ios/utils/ENRMMathFallback.m +18 -0
- package/ios/utils/ENRMSelectionChange.h +120 -0
- package/ios/utils/ENRMSelectionChange.m +282 -0
- package/ios/utils/ENRMTextViewSetup.h +35 -17
- package/ios/utils/EditMenuUtils+macOS.m +4 -1
- package/ios/utils/EditMenuUtils.h +35 -6
- package/ios/utils/EditMenuUtils.m +188 -11
- package/ios/utils/HTMLGenerator.m +2 -1
- package/ios/utils/ImageRequestHeaderUtils.h +35 -0
- package/ios/utils/LastElementUtils.h +1 -0
- package/ios/utils/ListMarkerDrawer.m +29 -42
- package/ios/utils/MarkdownASTSerializer.m +4 -0
- package/ios/utils/MarkdownAccessibilityElementBuilder.m +3 -1
- package/ios/utils/MarkdownExtractor.m +2 -1
- package/ios/utils/ParagraphStyleUtils.h +5 -0
- package/ios/utils/ParagraphStyleUtils.m +77 -17
- package/ios/utils/RTFExportUtils.m +2 -0
- package/ios/utils/RenderedMarkdownSegment.h +13 -1
- package/ios/utils/RenderedMarkdownSegment.m +20 -0
- package/ios/utils/SegmentRenderer.m +17 -4
- package/ios/utils/StreamingMarkdownFilter.h +11 -1
- package/ios/utils/StreamingMarkdownFilter.m +98 -2
- package/ios/utils/StylePropsUtils.h +110 -1
- package/ios/utils/TaskListTapUtils.m +24 -0
- package/ios/utils/TextViewLayoutManager.mm +3 -0
- package/ios/views/ENRMCodeBlockContainerView.h +60 -0
- package/ios/views/ENRMCodeBlockContainerView.m +569 -0
- package/ios/views/ENRMMathContainerView.h +23 -0
- package/ios/views/ENRMMathContainerView.m +87 -20
- package/ios/views/TableContainerView.h +32 -0
- package/ios/views/TableContainerView.m +291 -175
- package/jest.d.ts +1 -0
- package/jest.js +5 -0
- package/lib/module/EnrichedMarkdownNativeComponent.ts +203 -1
- package/lib/module/EnrichedMarkdownTextInput.js +84 -5
- package/lib/module/EnrichedMarkdownTextInput.js.map +1 -1
- package/lib/module/EnrichedMarkdownTextInputNativeComponent.ts +78 -5
- package/lib/module/EnrichedMarkdownTextNativeComponent.ts +204 -1
- package/lib/module/headingDefaults.js +34 -0
- package/lib/module/headingDefaults.js.map +1 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/jest/index.js +205 -0
- package/lib/module/jest/index.js.map +1 -0
- package/lib/module/native/EnrichedMarkdownText.js +199 -15
- package/lib/module/native/EnrichedMarkdownText.js.map +1 -1
- package/lib/module/normalizeMarkdownStyle.js +98 -23
- package/lib/module/normalizeMarkdownStyle.js.map +1 -1
- package/lib/module/normalizeMarkdownStyle.web.js +73 -22
- package/lib/module/normalizeMarkdownStyle.web.js.map +1 -1
- package/lib/module/normalizeMarkdownTextInputStyle.js +62 -15
- package/lib/module/normalizeMarkdownTextInputStyle.js.map +1 -1
- package/lib/module/normalizeMenuItem.js +1 -1
- package/lib/module/utils/textInputState.js +26 -0
- package/lib/module/utils/textInputState.js.map +1 -0
- package/lib/module/web/EnrichedMarkdownText.js +15 -8
- package/lib/module/web/EnrichedMarkdownText.js.map +1 -1
- package/lib/module/web/parseMarkdown.js +4 -3
- package/lib/module/web/parseMarkdown.js.map +1 -1
- package/lib/module/web/renderers/InlineRenderers.js +102 -3
- package/lib/module/web/renderers/InlineRenderers.js.map +1 -1
- package/lib/module/web/renderers/ListRenderers.js +7 -2
- package/lib/module/web/renderers/ListRenderers.js.map +1 -1
- package/lib/module/web/renderers/index.js +7 -4
- package/lib/module/web/renderers/index.js.map +1 -1
- package/lib/module/web/styles.js +101 -6
- package/lib/module/web/styles.js.map +1 -1
- package/lib/module/web/utils.js +14 -0
- package/lib/module/web/utils.js.map +1 -1
- package/lib/module/web/wasm/md4c.js +0 -0
- package/lib/module/web/wasm/md4c.js.map +1 -1
- package/lib/typescript/src/EnrichedMarkdownNativeComponent.d.ts +185 -2
- package/lib/typescript/src/EnrichedMarkdownNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/EnrichedMarkdownTextInput.d.ts +94 -9
- package/lib/typescript/src/EnrichedMarkdownTextInput.d.ts.map +1 -1
- package/lib/typescript/src/EnrichedMarkdownTextInputNativeComponent.d.ts +69 -5
- package/lib/typescript/src/EnrichedMarkdownTextInputNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/EnrichedMarkdownTextNativeComponent.d.ts +185 -2
- package/lib/typescript/src/EnrichedMarkdownTextNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/headingDefaults.d.ts +9 -0
- package/lib/typescript/src/headingDefaults.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +3 -3
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/index.web.d.ts +2 -2
- package/lib/typescript/src/index.web.d.ts.map +1 -1
- package/lib/typescript/src/jest/index.d.ts +6 -0
- package/lib/typescript/src/jest/index.d.ts.map +1 -0
- 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/normalizeMarkdownTextInputStyle.d.ts +19 -5
- package/lib/typescript/src/normalizeMarkdownTextInputStyle.d.ts.map +1 -1
- package/lib/typescript/src/types/MarkdownStyle.d.ts +122 -5
- package/lib/typescript/src/types/MarkdownStyle.d.ts.map +1 -1
- package/lib/typescript/src/types/MarkdownStyleInternal.d.ts +39 -0
- package/lib/typescript/src/types/MarkdownStyleInternal.d.ts.map +1 -1
- package/lib/typescript/src/types/MarkdownTextProps.d.ts +207 -10
- package/lib/typescript/src/types/MarkdownTextProps.d.ts.map +1 -1
- package/lib/typescript/src/types/MarkdownTextProps.web.d.ts +60 -1
- package/lib/typescript/src/types/MarkdownTextProps.web.d.ts.map +1 -1
- package/lib/typescript/src/types/events.d.ts +85 -0
- package/lib/typescript/src/types/events.d.ts.map +1 -1
- package/lib/typescript/src/utils/textInputState.d.ts +24 -0
- package/lib/typescript/src/utils/textInputState.d.ts.map +1 -0
- 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/parseMarkdown.d.ts +1 -1
- package/lib/typescript/src/web/parseMarkdown.d.ts.map +1 -1
- package/lib/typescript/src/web/renderers/InlineRenderers.d.ts.map +1 -1
- package/lib/typescript/src/web/renderers/ListRenderers.d.ts.map +1 -1
- package/lib/typescript/src/web/renderers/index.d.ts +2 -1
- package/lib/typescript/src/web/renderers/index.d.ts.map +1 -1
- package/lib/typescript/src/web/styles.d.ts +2 -1
- package/lib/typescript/src/web/styles.d.ts.map +1 -1
- package/lib/typescript/src/web/types.d.ts +10 -2
- 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 +36 -9
- package/postinstall.mjs +131 -0
- package/ratex-version.json +21 -0
- package/src/EnrichedMarkdownNativeComponent.ts +203 -1
- package/src/EnrichedMarkdownTextInput.tsx +159 -8
- package/src/EnrichedMarkdownTextInputNativeComponent.ts +78 -5
- package/src/EnrichedMarkdownTextNativeComponent.ts +204 -1
- package/src/headingDefaults.ts +21 -0
- package/src/index.tsx +15 -0
- package/src/index.web.tsx +6 -1
- package/src/jest/index.tsx +236 -0
- package/src/native/EnrichedMarkdownText.tsx +260 -11
- package/src/normalizeMarkdownStyle.ts +117 -16
- package/src/normalizeMarkdownStyle.web.ts +76 -15
- package/src/normalizeMarkdownTextInputStyle.ts +110 -35
- package/src/normalizeMenuItem.ts +1 -1
- package/src/types/MarkdownStyle.ts +125 -5
- package/src/types/MarkdownStyleInternal.ts +51 -0
- package/src/types/MarkdownTextProps.ts +215 -10
- package/src/types/MarkdownTextProps.web.ts +62 -1
- package/src/types/events.ts +90 -0
- package/src/utils/textInputState.ts +35 -0
- package/src/web/EnrichedMarkdownText.tsx +26 -5
- package/src/web/parseMarkdown.ts +6 -2
- package/src/web/renderers/InlineRenderers.tsx +116 -3
- package/src/web/renderers/ListRenderers.tsx +14 -2
- package/src/web/renderers/index.tsx +6 -2
- package/src/web/styles.ts +114 -5
- package/src/web/types.ts +10 -1
- package/src/web/utils.ts +9 -0
- package/src/web/wasm/md4c.js +0 -0
- package/vendor-grammars.mjs +511 -0
- package/vendor-ratex.mjs +173 -0
- package/app.plugin.js +0 -2
- package/plugin/build/withAndroidMath.js +0 -19
- package/plugin/build/withIosMath.js +0 -28
- package/plugin/build/withReactNativeEnrichedMarkdown.js +0 -11
- package/plugin/src/withAndroidMath.ts +0 -24
- package/plugin/src/withIosMath.ts +0 -35
- package/plugin/src/withReactNativeEnrichedMarkdown.ts +0 -17
- package/plugin/tsconfig.build.json +0 -16
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# Breaking changes
|
|
2
|
+
|
|
3
|
+
This file tracks breaking changes and how to migrate for each. Entries are newest first. Deprecations
|
|
4
|
+
(things that still work but are slated for removal) are noted alongside the change that introduces them.
|
|
5
|
+
|
|
6
|
+
## Unreleased
|
|
7
|
+
|
|
8
|
+
### `EnrichedMarkdownTextInput` math style keys renamed to match the renderer
|
|
9
|
+
|
|
10
|
+
The editor's `markdownStyle` used `math` for the **inline** chip and `mathBlock` for the **block**
|
|
11
|
+
chip — the exact opposite of `EnrichedMarkdownText`, where `math` is the block style and `inlineMath`
|
|
12
|
+
the inline one. The same key name meant two different things depending on which component you were
|
|
13
|
+
styling. The editor now follows the renderer.
|
|
14
|
+
|
|
15
|
+
**Migrate:**
|
|
16
|
+
|
|
17
|
+
| Before (input) | After (input) | Renderer equivalent |
|
|
18
|
+
|---|---|---|
|
|
19
|
+
| `markdownStyle.math` | `markdownStyle.inlineMath` | `markdownStyle.inlineMath` |
|
|
20
|
+
| `markdownStyle.mathBlock` | `markdownStyle.math` | `markdownStyle.math` |
|
|
21
|
+
| `markdownStyle.mathBlock.alignment` | `markdownStyle.math.textAlign` | `markdownStyle.math.textAlign` |
|
|
22
|
+
|
|
23
|
+
```diff
|
|
24
|
+
<EnrichedMarkdownTextInput
|
|
25
|
+
markdownStyle={{
|
|
26
|
+
- math: { color: '#0F172A', backgroundColor: '#EEF2FF' },
|
|
27
|
+
- mathBlock: { fontSize: 22, alignment: 'center' },
|
|
28
|
+
+ inlineMath: { color: '#0F172A', backgroundColor: '#EEF2FF' },
|
|
29
|
+
+ math: { fontSize: 22, textAlign: 'center' },
|
|
30
|
+
}}
|
|
31
|
+
/>
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
`markdownStyle.math` additionally accepts `padding` as a shorthand for both axes, matching the
|
|
35
|
+
renderer's `math.padding`; `paddingHorizontal` / `paddingVertical` still override it per axis.
|
|
36
|
+
|
|
37
|
+
The accompanying types are exported for the first time under names that say which surface they belong
|
|
38
|
+
to: `InputInlineMathStyle` and `InputMathStyle` (the renderer's own math style types stay internal to
|
|
39
|
+
`MarkdownStyle`).
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
## v1.0.2
|
|
43
|
+
|
|
44
|
+
### The Expo config plugin was removed
|
|
45
|
+
|
|
46
|
+
The built-in Expo config plugin (`app.plugin.js` and the `plugin/` folder) has been removed. Feature
|
|
47
|
+
configuration now lives entirely in your app's `package.json`, read directly by the native build and by
|
|
48
|
+
`postinstall` — the same approach `react-native-worklets` uses for its static feature flags.
|
|
49
|
+
|
|
50
|
+
Why: the plugin only wrote the (now deprecated) Podfile `ENV` / `gradle.properties` channels, it could
|
|
51
|
+
never influence the install-time asset download (it runs during `expo prebuild`, _after_ `npm install`),
|
|
52
|
+
and its option shape diverged from the `package.json` block. The `package.json` block supersedes it for
|
|
53
|
+
both the download and the build, and it survives `expo prebuild`.
|
|
54
|
+
|
|
55
|
+
**Migrate:** remove the plugin entry from `app.json` / `app.config.js` and move the options into the
|
|
56
|
+
`enriched-markdown` block of your `package.json`.
|
|
57
|
+
|
|
58
|
+
Before (`app.json`):
|
|
59
|
+
|
|
60
|
+
```json
|
|
61
|
+
{
|
|
62
|
+
"expo": {
|
|
63
|
+
"plugins": [
|
|
64
|
+
[
|
|
65
|
+
"react-native-enriched-markdown-scaffold",
|
|
66
|
+
{
|
|
67
|
+
"enableMath": false,
|
|
68
|
+
"codeHighlight": {
|
|
69
|
+
"enabled": true,
|
|
70
|
+
"languages": ["javascript", "tsx"]
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
]
|
|
74
|
+
]
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
After (`package.json`):
|
|
80
|
+
|
|
81
|
+
```json
|
|
82
|
+
{
|
|
83
|
+
"enriched-markdown": {
|
|
84
|
+
"enableMath": false,
|
|
85
|
+
"enableCodeHighlight": true,
|
|
86
|
+
"codeHighlightLanguages": ["javascript", "tsx"]
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Note the key renames: the plugin's `codeHighlight.enabled` / `codeHighlight.languages` become
|
|
92
|
+
`enableCodeHighlight` / `codeHighlightLanguages`. Then run `pod install` (iOS) or rebuild (Android).
|
|
93
|
+
These are compile/link-time settings, so they apply only in builds you compile yourself (a custom dev
|
|
94
|
+
client or `expo prebuild`) — they cannot be changed in Expo Go, which ships a fixed prebuilt binary.
|
|
95
|
+
|
|
96
|
+
The `@expo/config-plugins` peer dependency was dropped as part of this removal.
|
|
97
|
+
|
|
98
|
+
### Feature config moved to `package.json`; ENV vars and gradle properties are deprecated
|
|
99
|
+
|
|
100
|
+
The `enriched-markdown` block in your app's `package.json` is now the single source of truth for
|
|
101
|
+
`enableMath`, `enableCodeHighlight`, and `codeHighlightLanguages` on both platforms — the native build
|
|
102
|
+
reads it directly at `pod install` / Gradle configuration time. The previous build flags still work as a
|
|
103
|
+
fallback but are deprecated, print a warning, and are ignored when the matching `package.json` key is set:
|
|
104
|
+
|
|
105
|
+
| Deprecated flag | Replaced by (`package.json` `enriched-markdown`) |
|
|
106
|
+
| -------------------------------------------------------------------------------------------------------------- | ------------------------------------------------ |
|
|
107
|
+
| Podfile `ENV['ENRICHED_MARKDOWN_ENABLE_MATH']` / gradle `enrichedMarkdown.enableMath` | `enableMath` |
|
|
108
|
+
| Podfile `ENV['ENRICHED_MARKDOWN_ENABLE_CODE_HIGHLIGHT']` / gradle `enrichedMarkdown.enableCodeHighlight` | `enableCodeHighlight` |
|
|
109
|
+
| Podfile `ENV['ENRICHED_MARKDOWN_CODE_HIGHLIGHT_LANGUAGES']` / gradle `enrichedMarkdown.codeHighlightLanguages` | `codeHighlightLanguages` |
|
|
110
|
+
|
|
111
|
+
In a monorepo the _build_ flag is read from the app's `package.json` (the one beside `ios/`/`android/`),
|
|
112
|
+
so each app configures independently. The _download_ opt-out is read where the install runs — usually the
|
|
113
|
+
workspace root — so put it in the root `package.json` to skip a download for the whole repo. See
|
|
114
|
+
[Native assets](./NATIVE_ASSETS.md).
|
|
115
|
+
|
|
116
|
+
### Explicitly enabling a feature whose assets are missing now fails the build
|
|
117
|
+
|
|
118
|
+
Previously, a missing native asset (the RaTeX XCFramework, or the tree-sitter grammars) always silently
|
|
119
|
+
disabled the feature. Now, if you **explicitly** set `enableMath: true` or `enableCodeHighlight: true` but
|
|
120
|
+
the asset was not downloaded (for example an install with `--ignore-scripts`, or a monorepo root opt-out
|
|
121
|
+
that an app overrides), the build fails with an actionable error instead of degrading. Features left on by
|
|
122
|
+
default still degrade to a clean build. To fix, restore the assets:
|
|
123
|
+
|
|
124
|
+
```sh
|
|
125
|
+
node node_modules/react-native-enriched-markdown-scaffold/postinstall.mjs
|
|
126
|
+
# or: npm rebuild react-native-enriched-markdown-scaffold
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
then re-run `pod install` (iOS) / rebuild (Android).
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# Code-block syntax highlighting
|
|
2
|
+
|
|
3
|
+
Fenced code blocks are syntax-highlighted natively via [tree-sitter](https://tree-sitter.github.io/).
|
|
4
|
+
Highlighting is **foreground-only** (it recolors tokens and never changes text metrics), so a code
|
|
5
|
+
block's measured height always matches its drawn height. It is enabled by default on iOS and Android
|
|
6
|
+
with a curated set of languages, and can be trimmed or disabled to reduce binary size.
|
|
7
|
+
|
|
8
|
+
## Usage
|
|
9
|
+
|
|
10
|
+
Highlighting activates automatically for a fenced block whose info string names a supported language:
|
|
11
|
+
|
|
12
|
+
````tsx
|
|
13
|
+
<EnrichedMarkdownText
|
|
14
|
+
flavor="github"
|
|
15
|
+
markdown={String.raw`
|
|
16
|
+
\`\`\`python
|
|
17
|
+
def greet(name: str) -> str:
|
|
18
|
+
return f"Hello, {name}!" # a comment
|
|
19
|
+
\`\`\`
|
|
20
|
+
`}
|
|
21
|
+
markdownStyle={{
|
|
22
|
+
codeBlock: {
|
|
23
|
+
syntaxColors: {
|
|
24
|
+
keyword: '#C678DD',
|
|
25
|
+
string: '#98C379',
|
|
26
|
+
number: '#D19A66',
|
|
27
|
+
comment: '#7F848E',
|
|
28
|
+
function: '#61AFEF',
|
|
29
|
+
type: '#E5C07B',
|
|
30
|
+
// ...any of the 14 token types
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
}}
|
|
34
|
+
/>
|
|
35
|
+
````
|
|
36
|
+
|
|
37
|
+
Token colors are set through `codeBlock.syntaxColors`. The 14 token types are: `keyword`,
|
|
38
|
+
`operator`, `punctuation`, `string`, `number`, `constant`, `comment`, `function`, `type`,
|
|
39
|
+
`variable`, `property`, `tag`, `attribute`, `embedded`. Any type left unset is drawn in the normal
|
|
40
|
+
code color.
|
|
41
|
+
|
|
42
|
+
## Copy button
|
|
43
|
+
|
|
44
|
+
With `flavor="github"`, each code block's header shows a copy button (and a long-press context
|
|
45
|
+
menu with **Copy** / **Copy as Markdown**). The CommonMark flavor renders code blocks inline with
|
|
46
|
+
no header, so it has no copy button. To observe when a user copies code, pass
|
|
47
|
+
[`onCopyPress`](./API_REFERENCE.md#oncopypress) — it fires with the copied `code` and its
|
|
48
|
+
`language` for the header button, the context-menu **Copy** action, and the VoiceOver copy action.
|
|
49
|
+
The copy label shown to assistive technologies is configurable via
|
|
50
|
+
[`selectionMenuConfig`](./COPY_OPTIONS.md).
|
|
51
|
+
|
|
52
|
+
## Supported languages
|
|
53
|
+
|
|
54
|
+
Fence info strings map to a grammar (for example `js` and `jsx` both select JavaScript). The **curated default
|
|
55
|
+
set** is compiled in unless you override it. It is defined by `default:true` in
|
|
56
|
+
`vendor/grammar-versions.json` (the single source of truth the iOS podspec and Android build both
|
|
57
|
+
derive from), so the table below tracks that manifest:
|
|
58
|
+
|
|
59
|
+
| Default (on) | Opt-in (heavier) |
|
|
60
|
+
|---|---|
|
|
61
|
+
| json, html, css, markdown, yaml, go, java, javascript, python, c, rust, bash, typescript, tsx | cpp, swift, php, ruby, c-sharp |
|
|
62
|
+
|
|
63
|
+
The default set is the smaller-footprint tier (~32 MB of grammar C source across the whole set).
|
|
64
|
+
The opt-in grammars are larger (17-29 MB each) and are only compiled when you list them explicitly.
|
|
65
|
+
A block whose language is not compiled in simply renders as plain (uncolored) code.
|
|
66
|
+
|
|
67
|
+
## Choosing languages / reducing binary size
|
|
68
|
+
|
|
69
|
+
Only the grammars you compile end up in your binary, so trimming the list is the main size lever.
|
|
70
|
+
The seam degrades to plain code whenever a grammar is absent, so nothing breaks when you remove one.
|
|
71
|
+
|
|
72
|
+
Configure everything through the `enriched-markdown` block of your app's `package.json` — it is the
|
|
73
|
+
single source of truth for both platforms and both the install-time download and the build:
|
|
74
|
+
|
|
75
|
+
```json
|
|
76
|
+
{
|
|
77
|
+
"enriched-markdown": {
|
|
78
|
+
"enableCodeHighlight": true,
|
|
79
|
+
"codeHighlightLanguages": ["javascript", "tsx", "json", "bash"]
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
How the two keys interact:
|
|
85
|
+
|
|
86
|
+
- **`enableCodeHighlight`** (default `true`) is the master switch. When `false`, the grammar download is
|
|
87
|
+
skipped **and** the tree-sitter runtime is excluded from the native build. In that state
|
|
88
|
+
**`codeHighlightLanguages` is ignored — it is a no-op**, because there is no highlighter compiled in for
|
|
89
|
+
languages to feed.
|
|
90
|
+
- **`codeHighlightLanguages`** selects which grammars to compile *when highlighting is enabled*. Omit it
|
|
91
|
+
for the curated default set, or pass a subset to shrink the binary. An empty array (`[]`) compiles no
|
|
92
|
+
grammars, which disables highlighting entirely — equivalent to `enableCodeHighlight: false`.
|
|
93
|
+
|
|
94
|
+
Re-run `pod install` (iOS) / rebuild (Android) after changing these. The same block works with Expo —
|
|
95
|
+
`node_modules` survives `npx expo prebuild`, so no config plugin is needed (highlighting is compiled in,
|
|
96
|
+
so it can't be changed in **Expo Go**; use a dev client or `expo prebuild`). See
|
|
97
|
+
[Skipping the download](./NATIVE_ASSETS.md#skipping-the-download-opt-out).
|
|
98
|
+
|
|
99
|
+
> [!NOTE]
|
|
100
|
+
> **Deprecated:** the `ENV['ENRICHED_MARKDOWN_*']` Podfile variables and the `enrichedMarkdown.*` gradle
|
|
101
|
+
> properties still work as a fallback but are deprecated and print a warning; they are ignored when the
|
|
102
|
+
> corresponding `package.json` key is set. The Expo config plugin was removed — see
|
|
103
|
+
> [Breaking changes](./BREAKING_CHANGES.md). Prefer the `package.json` block above.
|
|
104
|
+
|
|
105
|
+
## How it works
|
|
106
|
+
|
|
107
|
+
Grammars are **vendored** into `packages/core/cpp/highlight/vendor/` (only each grammar's
|
|
108
|
+
`parser.c`/`scanner.c` + `highlights.scm`, never whole npm packages), so the native build itself is
|
|
109
|
+
fully offline and deterministic. The stable tree-sitter runtime is vendored the same way and compiled
|
|
110
|
+
with WebAssembly support left out. A build-time codegen emits a registry for exactly the selected
|
|
111
|
+
languages, so the binary and link step only ever reference compiled grammars.
|
|
112
|
+
|
|
113
|
+
The entire `vendor/` tree is **gitignored** to keep the repo and PRs small — nothing generated lives
|
|
114
|
+
in git. `vendor/vendor-grammars.mjs` restores all of it from the pins in `vendor/grammar-versions.json`:
|
|
115
|
+
the tree-sitter runtime (`vendor/tree-sitter/`) is fetched and sha256-verified from the pinned GitHub
|
|
116
|
+
release tarball, the ~178 MB of grammar `parser.c` tables (`vendor/grammars/`) are copied from the
|
|
117
|
+
pinned grammar devDependencies, and the default registry (`vendor/generated/`) is codegen'd from them.
|
|
118
|
+
It is wired into the package `prepare` script (so a plain `yarn install` restores everything, with
|
|
119
|
+
`.stamp` guards making repeats a no-op).
|
|
120
|
+
|
|
121
|
+
The published npm tarball ships only the small default registry, **not** the heavy grammar/runtime
|
|
122
|
+
source — that would bloat every install to ~230 MB. Instead a `postinstall` script downloads the
|
|
123
|
+
grammar sources (from the npm registry) and the tree-sitter runtime (from the pinned GitHub release)
|
|
124
|
+
into the installed package, sha256-verified and idempotent. See [Native assets](./NATIVE_ASSETS.md)
|
|
125
|
+
for the install-time behavior, network requirements, and how to recover an offline/pnpm install.
|
|
126
|
+
|
|
127
|
+
Highlighting runs synchronously when a code block is applied and is cached per block, with a size cap
|
|
128
|
+
(~50 KB / ~2000 lines) that falls back to plain rendering for pathological inputs. Maintainers re-pin
|
|
129
|
+
by editing `vendor/grammar-versions.json` (for a runtime bump, also update `runtime.sha256` — a full
|
|
130
|
+
`node vendor/vendor-grammars.mjs --force` run prints the correct digest on mismatch) and re-running
|
|
131
|
+
the script; there is nothing generated to commit. To vendor the runtime from a local tree-sitter
|
|
132
|
+
checkout instead of the network, pass `--runtime-src <path to tree-sitter/lib>` (or set
|
|
133
|
+
`TREE_SITTER_SRC`).
|
package/docs/COPY_OPTIONS.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Copy Options
|
|
2
2
|
|
|
3
|
-
When text is selected, `react-native-enriched-markdown` provides enhanced copy functionality through the context menu on both platforms.
|
|
3
|
+
When text is selected, `react-native-enriched-markdown-scaffold` provides enhanced copy functionality through the context menu on both platforms.
|
|
4
4
|
|
|
5
5
|
## Smart Copy
|
|
6
6
|
|
|
@@ -44,6 +44,59 @@ Use `selectionMenuConfig` to hide built-in selection menu actions while keeping
|
|
|
44
44
|
/>
|
|
45
45
|
```
|
|
46
46
|
|
|
47
|
+
### Copy as Markdown only, no system items
|
|
48
|
+
|
|
49
|
+
`copy` can also be hidden (`{ enabled: false }`) or switched to Markdown with
|
|
50
|
+
`format: 'markdown'`, and `systemItems: 'none'` drops everything the OS adds
|
|
51
|
+
(Select All, Look Up, Share, Translate, app text actions…):
|
|
52
|
+
|
|
53
|
+
```tsx
|
|
54
|
+
<EnrichedMarkdownText
|
|
55
|
+
markdown={content}
|
|
56
|
+
selectionMenuConfig={{
|
|
57
|
+
copy: { format: 'markdown' }, // inline math → $…$, plain text only
|
|
58
|
+
copyAsMarkdown: { enabled: false },
|
|
59
|
+
systemItems: 'none',
|
|
60
|
+
codeBlockCopyButton: { enabled: false },
|
|
61
|
+
}}
|
|
62
|
+
/>
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
The same `copy` and `copyAsMarkdown` settings drive the long-press menus on
|
|
66
|
+
table, math and code blocks: with `format: 'markdown'` their Copy item writes
|
|
67
|
+
the block's Markdown (`$$…$$`, a fenced code block, a Markdown table). On code
|
|
68
|
+
blocks, the header copy button and the VoiceOver copy action always copy the raw
|
|
69
|
+
code and fire `onCopyPress`; `codeBlockCopyButton: { enabled: false }` hides the
|
|
70
|
+
button, and `copy: { enabled: false }` also removes the VoiceOver action.
|
|
71
|
+
`copy.enabled`, `copy.format` and `systemItems` are ignored on macOS.
|
|
72
|
+
|
|
73
|
+
### Handling Copy in JS
|
|
74
|
+
|
|
75
|
+
To decide in JS what lands on the clipboard, pass `onCopy`. The Copy item
|
|
76
|
+
(text selection and block menus) then writes nothing itself and hands you the
|
|
77
|
+
content — `markdown`, `text`, `source` and `whole` — to write with your
|
|
78
|
+
clipboard library. See [`onCopy`](API_REFERENCE.md#oncopy).
|
|
79
|
+
|
|
80
|
+
```tsx
|
|
81
|
+
<EnrichedMarkdownText
|
|
82
|
+
markdown={content}
|
|
83
|
+
onCopy={({ markdown }) => Clipboard.setStringAsync(markdown)}
|
|
84
|
+
/>
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
To turn the menu off entirely rather than item by item, use `contextMenuHidden`:
|
|
88
|
+
|
|
89
|
+
```tsx
|
|
90
|
+
// No selection menu at all — text is still selectable
|
|
91
|
+
<EnrichedMarkdownText markdown={content} contextMenuHidden />
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
The two are complementary: `selectionMenuConfig` prunes individual built-in
|
|
95
|
+
items and leaves the menu in place, while `contextMenuHidden` suppresses the
|
|
96
|
+
menu as a whole — including `contextMenuItems` and the copy menus on table,
|
|
97
|
+
code and math blocks. Note that `contextMenuHidden` applies to `EnrichedMarkdownText`
|
|
98
|
+
only; it does not affect `EnrichedMarkdownTextInput`.
|
|
99
|
+
|
|
47
100
|
`EnrichedMarkdownTextInput` supports the same `{ enabled, label }` shape. In addition to `copyAsMarkdown`, the input's `selectionMenuConfig` exposes the built-in **Format** submenu, and `formatMenuConfig` controls the items inside it:
|
|
48
101
|
|
|
49
102
|
```tsx
|
|
@@ -93,8 +146,13 @@ Notes:
|
|
|
93
146
|
plural category (`zero`, `one`, `two`, `few`, `many`, `other`). Only `other` is
|
|
94
147
|
required; any category left `undefined` falls back to it. The `{count}` token
|
|
95
148
|
is replaced by the number of selected images.
|
|
96
|
-
- The labels apply to the main text selection menu as well as the table
|
|
97
|
-
block copy menus.
|
|
149
|
+
- The labels apply to the main text selection menu as well as the table, math,
|
|
150
|
+
and code block copy menus. With `flavor="github"`, the code block header's copy
|
|
151
|
+
button also reuses the copy label for assistive technologies (the CommonMark
|
|
152
|
+
flavor renders code inline with no header button): it is the button's
|
|
153
|
+
contentDescription on Android, and on iOS it names the VoiceOver custom
|
|
154
|
+
action that triggers the copy. To be notified when code is copied from a code
|
|
155
|
+
block, use the [`onCopyPress`](./API_REFERENCE.md#oncopypress) callback.
|
|
98
156
|
- OS-provided actions (Look Up, Translate…) and the system **Cut / Paste /
|
|
99
157
|
Select All** items are localized by the platform and are not affected by this
|
|
100
158
|
config.
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# Element Structure
|
|
2
2
|
|
|
3
|
-
Markdown elements in `react-native-enriched-markdown` are organized into block and inline categories, each with distinct rendering behaviors.
|
|
3
|
+
Markdown elements in `react-native-enriched-markdown-scaffold` are organized into block and inline categories, each with distinct rendering behaviors.
|
|
4
4
|
|
|
5
5
|
## Supported Markdown Elements
|
|
6
6
|
|
|
7
|
-
`react-native-enriched-markdown` supports a comprehensive set of Markdown elements:
|
|
7
|
+
`react-native-enriched-markdown-scaffold` supports a comprehensive set of Markdown elements:
|
|
8
8
|
|
|
9
9
|
### Block Elements
|
|
10
10
|
|
|
@@ -13,7 +13,7 @@ Markdown elements in `react-native-enriched-markdown` are organized into block a
|
|
|
13
13
|
| Headings | `# H1` to `###### H6` | `h1` - `h6` | Six levels of headings |
|
|
14
14
|
| Paragraphs | Plain text | `paragraph` | Default text container |
|
|
15
15
|
| Blockquotes | `> Quote` | `blockquote` | Quoted content with accent bar, unlimited nesting |
|
|
16
|
-
| Code Blocks | ` ``` code ``` ` | `codeBlock` | Multi-line code containers |
|
|
16
|
+
| Code Blocks | ` ``` code ``` ` | `codeBlock` | Multi-line code containers; with `flavor="github"` rendered as a block component with a language header and copy-code button |
|
|
17
17
|
| Unordered Lists | `- Item`, `* Item`, or `+ Item` | `list` | Bullet lists with unlimited nesting |
|
|
18
18
|
| Ordered Lists | `1. Item` | `list` | Numbered lists with unlimited nesting |
|
|
19
19
|
| Task Lists | `- [x] Done`, `- [ ] Todo` | `taskList` | Interactive checkboxes (requires `flavor="github"`) |
|
|
@@ -60,6 +60,22 @@ Markdown elements in `react-native-enriched-markdown` are organized into block a
|
|
|
60
60
|
2. Second item
|
|
61
61
|
```
|
|
62
62
|
|
|
63
|
+
### Lists with Block Content Example
|
|
64
|
+
|
|
65
|
+
List items can contain block elements — fenced code blocks, nested lists, and multiple paragraphs:
|
|
66
|
+
|
|
67
|
+
````markdown
|
|
68
|
+
1. Install via npm:
|
|
69
|
+
|
|
70
|
+
```
|
|
71
|
+
npm install
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
2. Verify the connection.
|
|
75
|
+
````
|
|
76
|
+
|
|
77
|
+
Code blocks indent to the item's content column, and the marker is drawn next to the first line even when a code block or nested list is the item's first child.
|
|
78
|
+
|
|
63
79
|
### Nested Blockquotes Example
|
|
64
80
|
|
|
65
81
|
```markdown
|
|
@@ -94,6 +110,38 @@ Block elements are structural containers that define the layout and establish th
|
|
|
94
110
|
|
|
95
111
|
Inline elements modify text within blocks and apply additional styling on top of the block's typography.
|
|
96
112
|
|
|
113
|
+
## Line Breaks
|
|
114
|
+
|
|
115
|
+
Newlines follow standard CommonMark semantics by default:
|
|
116
|
+
|
|
117
|
+
- **Blank line**: Starts a new paragraph.
|
|
118
|
+
- **Single newline (soft break)**: Renders as a space — consecutive lines flow together into one wrapped paragraph, matching how GitHub and other CommonMark renderers display Markdown.
|
|
119
|
+
- **Hard break**: Ends a line with two spaces or a backslash to force a line break within the paragraph.
|
|
120
|
+
|
|
121
|
+
```markdown
|
|
122
|
+
This line and
|
|
123
|
+
this line render as one continuous sentence.
|
|
124
|
+
|
|
125
|
+
A blank line starts a new paragraph.
|
|
126
|
+
|
|
127
|
+
Two trailing spaces
|
|
128
|
+
or a trailing backslash\
|
|
129
|
+
force a line break within the paragraph.
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Preserving single newlines
|
|
133
|
+
|
|
134
|
+
When displaying content authored in `EnrichedMarkdownTextInput`, pressing Enter produces a single newline in the serialized markdown. By default, `EnrichedMarkdownText` collapses these to spaces (per CommonMark). To preserve them as visible line breaks, enable the `hardSoftBreaks` flag:
|
|
135
|
+
|
|
136
|
+
```tsx
|
|
137
|
+
<EnrichedMarkdownText
|
|
138
|
+
markdown={markdownFromInput}
|
|
139
|
+
md4cFlags={{ hardSoftBreaks: true }}
|
|
140
|
+
/>
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
This forces the parser to treat every soft break as a hard break, so single newlines render as line breaks on all platforms.
|
|
144
|
+
|
|
97
145
|
## Images: Block vs Inline
|
|
98
146
|
|
|
99
147
|
Images are automatically detected as block or inline based on context:
|
|
@@ -101,7 +149,7 @@ Images are automatically detected as block or inline based on context:
|
|
|
101
149
|
- **Block images**: When an image is the only content in a paragraph (standalone), it's treated as a block image and uses block-level spacing
|
|
102
150
|
- **Inline images**: When an image appears alongside other text content, it's treated as inline and aligns with the text baseline
|
|
103
151
|
|
|
104
|
-
You don't need to specify which type—the renderer automatically determines this based on the image's position in the content.
|
|
152
|
+
You don't need to specify which type—the renderer automatically determines this based on the image's position in the content. Note that a single newline doesn't split a paragraph, so an image on its own source line directly below text is still inline; separate it with a blank line to make it a block image.
|
|
105
153
|
|
|
106
154
|
## Nested Elements
|
|
107
155
|
|
package/docs/IMAGE_CACHING.md
CHANGED
|
@@ -2,6 +2,30 @@
|
|
|
2
2
|
|
|
3
3
|
Images in Markdown content are loaded, cached, and reused automatically — no configuration required.
|
|
4
4
|
|
|
5
|
+
## Supported Image Sources
|
|
6
|
+
|
|
7
|
+
Markdown image URLs are strings, so bundled assets must be resolved to a URI before being interpolated into the markdown:
|
|
8
|
+
|
|
9
|
+
```tsx
|
|
10
|
+
import { Image } from 'react-native';
|
|
11
|
+
|
|
12
|
+
const logoUri = Image.resolveAssetSource(require('./assets/logo.png')).uri;
|
|
13
|
+
const markdown = ``;
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
This works in every environment: in dev the URI is a Metro dev-server URL, while in a release build it resolves to a drawable resource name on Android and a bundle `file://` URL on iOS — all of which are supported. URIs from `expo-asset` (`asset.uri` / `asset.localUri`) work the same way.
|
|
17
|
+
|
|
18
|
+
| Source | Android | iOS / macOS |
|
|
19
|
+
|---|---|---|
|
|
20
|
+
| `http://`, `https://` | Yes | Yes |
|
|
21
|
+
| `file://` (including percent-encoded paths) | Yes | Yes |
|
|
22
|
+
| Bare asset name (release builds, expo-asset `localUri`) | Yes (drawable/raw resource) | Yes (bundle resource) |
|
|
23
|
+
| `file:///android_res/…`, `file:///android_asset/…` | Yes | No |
|
|
24
|
+
| `asset://`, `res://`, `content://` | Yes | No |
|
|
25
|
+
| `data:` (base64) | Yes | Yes |
|
|
26
|
+
|
|
27
|
+
Local sources skip the HTTP layers below (disk cache, request headers, deduplication) but still use both memory cache tiers.
|
|
28
|
+
|
|
5
29
|
## Cache Layers
|
|
6
30
|
|
|
7
31
|
The library uses a three-tier caching strategy on both platforms:
|
|
@@ -16,6 +40,12 @@ The library uses a three-tier caching strategy on both platforms:
|
|
|
16
40
|
- **Processed cache** stores scaled and clipped variants keyed by URL + dimensions + border radius, so repeated layouts with the same geometry skip all image processing.
|
|
17
41
|
- **Disk cache** persists raw HTTP responses across app launches, respecting standard HTTP cache headers.
|
|
18
42
|
|
|
43
|
+
## Request Headers
|
|
44
|
+
|
|
45
|
+
When `imageRequestHeaders` is set, the headers become part of the cache identity for both memory tiers and for request deduplication: the same URL requested with different headers is fetched and cached separately, and changing the prop re-fetches the images.
|
|
46
|
+
|
|
47
|
+
One caveat: the disk cache is managed by the HTTP stack (OkHttp / `NSURLCache`) and keys responses by URL alone. A response fetched with one set of headers can be served from disk for a request with different headers, subject to standard HTTP caching semantics (`Cache-Control`, `Vary`).
|
|
48
|
+
|
|
19
49
|
## Request Deduplication
|
|
20
50
|
|
|
21
51
|
When multiple components request the same image URL simultaneously (e.g. during a re-render), only one network request is made. All pending callbacks are coalesced and dispatched together once the download completes.
|