react-native-enriched-markdown-scaffold 0.7.4-scaffold.9 → 1.0.2-scaffold.2
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 +186 -1
- package/android/consumer-rules.pro +1 -1
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownManagerDelegate.java +9 -0
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownManagerInterface.java +3 -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 +9 -0
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextManagerInterface.java +3 -0
- package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/EventEmitters.cpp +75 -0
- package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/EventEmitters.h +63 -0
- package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/Props.cpp +35 -0
- package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/Props.h +886 -23
- 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 +189 -13
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownInternalText.kt +17 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownManager.kt +50 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownText.kt +48 -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 +42 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/MeasurementStore.kt +82 -4
- package/android/src/main/java/com/swmansion/enriched/markdown/events/CopyPressEvent.kt +24 -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 +901 -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 +101 -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/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 +30 -27
- 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 +27 -3
- 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/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/ListStyle.kt +4 -1
- 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 +37 -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 +20 -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/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/LinkLongPressMovementMethod.kt +58 -27
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/SelectionActionMode.kt +49 -15
- package/android/src/main/java/com/swmansion/enriched/markdown/views/BlockMenuOptions.kt +45 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/views/CodeBlockContainerView.kt +396 -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 +36 -9
- 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 +7 -2
- package/android/src/math/java/com/swmansion/enriched/markdown/spans/MathChipSpan.kt +1 -1
- package/android/src/math/java/com/swmansion/enriched/markdown/views/MathContainerView.kt +6 -4
- 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 +234 -12
- package/docs/BREAKING_CHANGES.md +129 -0
- package/docs/CODE_HIGHLIGHT.md +133 -0
- package/docs/COPY_OPTIONS.md +47 -3
- package/docs/ELEMENTS_STRUCTURE.md +52 -4
- package/docs/IMAGE_CACHING.md +30 -0
- package/docs/INPUT.md +108 -11
- package/docs/LATEX_MATH.md +87 -45
- package/docs/MACOS.md +1 -1
- package/docs/MARKDOWN_STREAMING.md +27 -1
- package/docs/NATIVE_ASSETS.md +127 -0
- package/docs/RTL.md +1 -1
- package/docs/STYLES.md +46 -6
- package/docs/TESTING.md +112 -0
- package/docs/TEXT.md +16 -6
- package/docs/WEB.md +3 -1
- package/ios/EnrichedMarkdown.h +7 -0
- package/ios/EnrichedMarkdown.mm +284 -75
- package/ios/EnrichedMarkdownText.h +7 -0
- package/ios/EnrichedMarkdownText.mm +101 -73
- package/ios/attachments/ENRMImageAttachment.h +9 -0
- package/ios/attachments/ENRMImageAttachment.m +143 -40
- package/ios/attachments/ENRMMathInlineAttachment.h +2 -0
- package/ios/attachments/ENRMMathInlineAttachment.m +48 -81
- package/ios/attachments/ENRMMathInlineAttachmentShared.h +2 -0
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/EventEmitters.cpp +75 -0
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/EventEmitters.h +63 -0
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/Props.cpp +35 -0
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/Props.h +886 -23
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/RCTComponentViewHelpers.h +131 -0
- 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 +33 -7
- 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 +4 -1
- 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 +5 -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 +3 -1
- 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 +22 -0
- package/ios/styles/StyleConfig.mm +132 -0
- package/ios/utils/BlockquoteBorder.h +6 -0
- package/ios/utils/BlockquoteBorder.m +249 -52
- package/ios/utils/CodeBlockBackground.m +16 -2
- package/ios/utils/ENRMAtomicSize.h +65 -0
- package/ios/utils/ENRMBlockMenu.h +57 -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/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/ENRMTextViewSetup.h +35 -17
- package/ios/utils/EditMenuUtils.h +22 -5
- package/ios/utils/EditMenuUtils.m +53 -9
- 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/ParagraphStyleUtils.h +5 -0
- package/ios/utils/ParagraphStyleUtils.m +77 -17
- 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 +63 -0
- package/ios/utils/TaskListTapUtils.m +24 -0
- package/ios/views/ENRMCodeBlockContainerView.h +53 -0
- package/ios/views/ENRMCodeBlockContainerView.m +559 -0
- package/ios/views/ENRMMathContainerView.h +16 -0
- package/ios/views/ENRMMathContainerView.m +74 -19
- package/ios/views/TableContainerView.h +22 -0
- package/ios/views/TableContainerView.m +261 -175
- package/jest.d.ts +1 -0
- package/jest.js +5 -0
- package/lib/module/EnrichedMarkdownNativeComponent.ts +73 -0
- 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 +74 -0
- 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 +191 -0
- package/lib/module/jest/index.js.map +1 -0
- package/lib/module/native/EnrichedMarkdownText.js +37 -5
- package/lib/module/native/EnrichedMarkdownText.js.map +1 -1
- package/lib/module/normalizeMarkdownStyle.js +81 -19
- package/lib/module/normalizeMarkdownStyle.js.map +1 -1
- package/lib/module/normalizeMarkdownStyle.web.js +56 -18
- 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 +9 -5
- 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 +6 -0
- 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 +83 -6
- package/lib/module/web/styles.js.map +1 -1
- package/lib/module/web/utils.js +1 -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 +66 -0
- 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 +66 -0
- 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 +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 +6 -0
- package/lib/typescript/src/jest/index.d.ts.map +1 -0
- package/lib/typescript/src/native/EnrichedMarkdownText.d.ts +3 -3
- 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 +72 -0
- package/lib/typescript/src/types/MarkdownStyle.d.ts.map +1 -1
- package/lib/typescript/src/types/MarkdownStyleInternal.d.ts +27 -0
- package/lib/typescript/src/types/MarkdownStyleInternal.d.ts.map +1 -1
- package/lib/typescript/src/types/MarkdownTextProps.d.ts +104 -9
- package/lib/typescript/src/types/MarkdownTextProps.d.ts.map +1 -1
- package/lib/typescript/src/types/MarkdownTextProps.web.d.ts +19 -0
- package/lib/typescript/src/types/MarkdownTextProps.web.d.ts.map +1 -1
- package/lib/typescript/src/types/events.d.ts +19 -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 +6 -2
- package/lib/typescript/src/web/types.d.ts.map +1 -1
- 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 +73 -0
- package/src/EnrichedMarkdownTextInput.tsx +159 -8
- package/src/EnrichedMarkdownTextInputNativeComponent.ts +78 -5
- package/src/EnrichedMarkdownTextNativeComponent.ts +74 -0
- package/src/headingDefaults.ts +21 -0
- package/src/index.tsx +9 -0
- package/src/index.web.tsx +1 -0
- package/src/jest/index.tsx +215 -0
- package/src/native/EnrichedMarkdownText.tsx +53 -2
- package/src/normalizeMarkdownStyle.ts +102 -16
- package/src/normalizeMarkdownStyle.web.ts +63 -15
- package/src/normalizeMarkdownTextInputStyle.ts +110 -35
- package/src/normalizeMenuItem.ts +1 -1
- package/src/types/MarkdownStyle.ts +74 -0
- package/src/types/MarkdownStyleInternal.ts +39 -0
- package/src/types/MarkdownTextProps.ts +101 -9
- package/src/types/MarkdownTextProps.web.ts +19 -0
- package/src/types/events.ts +21 -0
- package/src/utils/textInputState.ts +35 -0
- package/src/web/EnrichedMarkdownText.tsx +16 -2
- package/src/web/parseMarkdown.ts +6 -2
- package/src/web/renderers/InlineRenderers.tsx +5 -0
- package/src/web/renderers/ListRenderers.tsx +14 -2
- package/src/web/renderers/index.tsx +6 -2
- package/src/web/styles.ts +89 -5
- package/src/web/types.ts +6 -1
- package/src/web/utils.ts +1 -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
package/android/src/main/java/com/swmansion/enriched/markdown/utils/input/MarkdownStyleParser.kt
CHANGED
|
@@ -3,8 +3,11 @@ package com.swmansion.enriched.markdown.utils.input
|
|
|
3
3
|
import android.graphics.Color
|
|
4
4
|
import android.text.Layout
|
|
5
5
|
import com.facebook.react.bridge.ReadableMap
|
|
6
|
+
import com.facebook.react.common.ReactConstants
|
|
6
7
|
import com.facebook.react.uimanager.PixelUtil
|
|
8
|
+
import com.facebook.react.views.text.ReactTypefaceUtils
|
|
7
9
|
import com.swmansion.enriched.markdown.input.model.InputFormatterStyle
|
|
10
|
+
import com.swmansion.enriched.markdown.input.model.InputHeadingStyle
|
|
8
11
|
import com.swmansion.enriched.markdown.input.model.InputLinkVariantStyle
|
|
9
12
|
import com.swmansion.enriched.markdown.input.model.MathBlockStyle
|
|
10
13
|
import com.swmansion.enriched.markdown.input.model.MathChipStyle
|
|
@@ -15,11 +18,12 @@ object MarkdownStyleParser {
|
|
|
15
18
|
val emMap = map.getMap("em")
|
|
16
19
|
val linkMap = map.getMap("link")
|
|
17
20
|
val spoilerMap = map.getMap("spoiler")
|
|
18
|
-
val
|
|
19
|
-
val
|
|
21
|
+
val inlineMathMap = map.getMap("inlineMath")
|
|
22
|
+
val blockMathMap = map.getMap("math")
|
|
20
23
|
|
|
21
|
-
val
|
|
22
|
-
val
|
|
24
|
+
val inlineMath = parseInlineMathStyle(inlineMathMap)
|
|
25
|
+
val math = parseBlockMathStyle(blockMathMap, inlineMath)
|
|
26
|
+
val listMap = map.getMap("list")
|
|
23
27
|
|
|
24
28
|
return InputFormatterStyle(
|
|
25
29
|
boldColor = if (strongMap?.hasKey("color") == true) strongMap.getInt("color") else null,
|
|
@@ -30,11 +34,37 @@ object MarkdownStyleParser {
|
|
|
30
34
|
linkVariants = parseLinkVariants(map),
|
|
31
35
|
spoilerColor = spoilerMap!!.getInt("color"),
|
|
32
36
|
spoilerBackgroundColor = spoilerMap.getInt("backgroundColor"),
|
|
37
|
+
inlineMath = inlineMath,
|
|
33
38
|
math = math,
|
|
34
|
-
|
|
39
|
+
headings = parseHeadings(map),
|
|
40
|
+
listItemSpacing =
|
|
41
|
+
if (listMap?.hasKey("itemSpacing") == true) listMap.getDouble("itemSpacing").toFloat() else 0f,
|
|
35
42
|
)
|
|
36
43
|
}
|
|
37
44
|
|
|
45
|
+
// Mirrors the readonly renderer's h1..h6 markdownStyle. fontSize arrives in SP
|
|
46
|
+
// (matching the JS prop) and is converted to px so the input span can size text
|
|
47
|
+
// identically to the read view.
|
|
48
|
+
private fun parseHeadings(map: ReadableMap): List<InputHeadingStyle> =
|
|
49
|
+
(1..6).map { level ->
|
|
50
|
+
val headingMap = map.getMap("h$level")
|
|
51
|
+
InputHeadingStyle(
|
|
52
|
+
fontSizePx =
|
|
53
|
+
if (headingMap?.hasKey("fontSize") == true) {
|
|
54
|
+
PixelUtil.toPixelFromSP(headingMap.getDouble("fontSize"))
|
|
55
|
+
} else {
|
|
56
|
+
null
|
|
57
|
+
},
|
|
58
|
+
fontWeight =
|
|
59
|
+
if (headingMap?.hasKey("fontWeight") == true) {
|
|
60
|
+
ReactTypefaceUtils.parseFontWeight(headingMap.getString("fontWeight"))
|
|
61
|
+
} else {
|
|
62
|
+
ReactConstants.UNSET
|
|
63
|
+
},
|
|
64
|
+
color = if (headingMap?.hasKey("color") == true) headingMap.getInt("color") else null,
|
|
65
|
+
)
|
|
66
|
+
}
|
|
67
|
+
|
|
38
68
|
private fun parseLinkVariants(map: ReadableMap): List<InputLinkVariantStyle> {
|
|
39
69
|
if (!map.hasKey("linkVariants")) return emptyList()
|
|
40
70
|
val variants = map.getArray("linkVariants") ?: return emptyList()
|
|
@@ -49,35 +79,35 @@ object MarkdownStyleParser {
|
|
|
49
79
|
}
|
|
50
80
|
}
|
|
51
81
|
|
|
52
|
-
private fun
|
|
53
|
-
val color = if (
|
|
54
|
-
val fontSizeSp = if (
|
|
82
|
+
private fun parseInlineMathStyle(styleMap: ReadableMap?): MathChipStyle {
|
|
83
|
+
val color = if (styleMap?.hasKey("color") == true) styleMap.getInt("color") else Color.BLACK
|
|
84
|
+
val fontSizeSp = if (styleMap?.hasKey("fontSize") == true) styleMap.getDouble("fontSize").toFloat() else 16f
|
|
55
85
|
val fontSize = PixelUtil.toPixelFromSP(fontSizeSp)
|
|
56
86
|
val backgroundColor =
|
|
57
|
-
if (
|
|
58
|
-
val borderColor = if (
|
|
87
|
+
if (styleMap?.hasKey("backgroundColor") == true) styleMap.getInt("backgroundColor") else null
|
|
88
|
+
val borderColor = if (styleMap?.hasKey("borderColor") == true) styleMap.getInt("borderColor") else null
|
|
59
89
|
val borderWidth =
|
|
60
90
|
PixelUtil.toPixelFromDIP(
|
|
61
|
-
if (
|
|
91
|
+
if (styleMap?.hasKey("borderWidth") == true) styleMap.getDouble("borderWidth").toFloat() else 0f,
|
|
62
92
|
)
|
|
63
93
|
val borderRadius =
|
|
64
94
|
PixelUtil.toPixelFromDIP(
|
|
65
|
-
if (
|
|
95
|
+
if (styleMap?.hasKey("borderRadius") == true) styleMap.getDouble("borderRadius").toFloat() else 0f,
|
|
66
96
|
)
|
|
67
97
|
val paddingHorizontal =
|
|
68
98
|
PixelUtil.toPixelFromDIP(
|
|
69
|
-
if (
|
|
99
|
+
if (styleMap?.hasKey("paddingHorizontal") == true) styleMap.getDouble("paddingHorizontal").toFloat() else 0f,
|
|
70
100
|
)
|
|
71
101
|
val paddingVertical =
|
|
72
102
|
PixelUtil.toPixelFromDIP(
|
|
73
|
-
if (
|
|
103
|
+
if (styleMap?.hasKey("paddingVertical") == true) styleMap.getDouble("paddingVertical").toFloat() else 0f,
|
|
74
104
|
)
|
|
75
105
|
val selectedBackgroundColor =
|
|
76
|
-
if (
|
|
106
|
+
if (styleMap?.hasKey("selectedBackgroundColor") == true) styleMap.getInt("selectedBackgroundColor") else null
|
|
77
107
|
val selectedBorderColor =
|
|
78
|
-
if (
|
|
108
|
+
if (styleMap?.hasKey("selectedBorderColor") == true) styleMap.getInt("selectedBorderColor") else null
|
|
79
109
|
val fontWeight =
|
|
80
|
-
(if (
|
|
110
|
+
(if (styleMap?.hasKey("fontWeight") == true) styleMap.getString("fontWeight") else null) ?: "normal"
|
|
81
111
|
|
|
82
112
|
return MathChipStyle(
|
|
83
113
|
color = color,
|
|
@@ -94,75 +124,75 @@ object MarkdownStyleParser {
|
|
|
94
124
|
)
|
|
95
125
|
}
|
|
96
126
|
|
|
97
|
-
private fun
|
|
98
|
-
|
|
127
|
+
private fun parseBlockMathStyle(
|
|
128
|
+
styleMap: ReadableMap?,
|
|
99
129
|
inlineFallback: MathChipStyle,
|
|
100
|
-
):
|
|
101
|
-
val color = if (
|
|
130
|
+
): MathBlockStyle {
|
|
131
|
+
val color = if (styleMap?.hasKey("color") == true) styleMap.getInt("color") else inlineFallback.color
|
|
102
132
|
val fontSizeSp =
|
|
103
|
-
if (
|
|
133
|
+
if (styleMap?.hasKey("fontSize") == true) styleMap.getDouble("fontSize").toFloat() else 20f
|
|
104
134
|
val fontSize = PixelUtil.toPixelFromSP(fontSizeSp)
|
|
105
135
|
val backgroundColor =
|
|
106
|
-
if (
|
|
107
|
-
|
|
136
|
+
if (styleMap?.hasKey("backgroundColor") == true) {
|
|
137
|
+
styleMap.getInt("backgroundColor")
|
|
108
138
|
} else {
|
|
109
139
|
inlineFallback.backgroundColor
|
|
110
140
|
}
|
|
111
141
|
val borderColor =
|
|
112
|
-
if (
|
|
113
|
-
|
|
142
|
+
if (styleMap?.hasKey("borderColor") == true) {
|
|
143
|
+
styleMap.getInt("borderColor")
|
|
114
144
|
} else {
|
|
115
145
|
inlineFallback.borderColor
|
|
116
146
|
}
|
|
117
147
|
val borderWidth =
|
|
118
|
-
if (
|
|
119
|
-
PixelUtil.toPixelFromDIP(
|
|
148
|
+
if (styleMap?.hasKey("borderWidth") == true) {
|
|
149
|
+
PixelUtil.toPixelFromDIP(styleMap.getDouble("borderWidth").toFloat())
|
|
120
150
|
} else {
|
|
121
151
|
inlineFallback.borderWidth
|
|
122
152
|
}
|
|
123
153
|
val borderRadius =
|
|
124
|
-
if (
|
|
125
|
-
PixelUtil.toPixelFromDIP(
|
|
154
|
+
if (styleMap?.hasKey("borderRadius") == true) {
|
|
155
|
+
PixelUtil.toPixelFromDIP(styleMap.getDouble("borderRadius").toFloat())
|
|
126
156
|
} else {
|
|
127
157
|
inlineFallback.borderRadius
|
|
128
158
|
}
|
|
129
159
|
val paddingHorizontal =
|
|
130
160
|
PixelUtil.toPixelFromDIP(
|
|
131
|
-
if (
|
|
161
|
+
if (styleMap?.hasKey("paddingHorizontal") == true) styleMap.getDouble("paddingHorizontal").toFloat() else 12f,
|
|
132
162
|
)
|
|
133
163
|
val paddingVertical =
|
|
134
164
|
PixelUtil.toPixelFromDIP(
|
|
135
|
-
if (
|
|
165
|
+
if (styleMap?.hasKey("paddingVertical") == true) styleMap.getDouble("paddingVertical").toFloat() else 8f,
|
|
136
166
|
)
|
|
137
167
|
val selectedBackgroundColor =
|
|
138
|
-
if (
|
|
139
|
-
|
|
168
|
+
if (styleMap?.hasKey("selectedBackgroundColor") == true) {
|
|
169
|
+
styleMap.getInt("selectedBackgroundColor")
|
|
140
170
|
} else {
|
|
141
171
|
inlineFallback.selectedBackgroundColor
|
|
142
172
|
}
|
|
143
173
|
val selectedBorderColor =
|
|
144
|
-
if (
|
|
145
|
-
|
|
174
|
+
if (styleMap?.hasKey("selectedBorderColor") == true) {
|
|
175
|
+
styleMap.getInt("selectedBorderColor")
|
|
146
176
|
} else {
|
|
147
177
|
inlineFallback.selectedBorderColor
|
|
148
178
|
}
|
|
149
179
|
val fontWeight =
|
|
150
|
-
if (
|
|
151
|
-
|
|
180
|
+
if (styleMap?.hasKey("fontWeight") == true) {
|
|
181
|
+
styleMap.getString("fontWeight") ?: "normal"
|
|
152
182
|
} else {
|
|
153
183
|
inlineFallback.fontWeight
|
|
154
184
|
}
|
|
155
185
|
val marginTop =
|
|
156
186
|
PixelUtil.toPixelFromDIP(
|
|
157
|
-
if (
|
|
187
|
+
if (styleMap?.hasKey("marginTop") == true) styleMap.getDouble("marginTop").toFloat() else 8f,
|
|
158
188
|
)
|
|
159
189
|
val marginBottom =
|
|
160
190
|
PixelUtil.toPixelFromDIP(
|
|
161
|
-
if (
|
|
191
|
+
if (styleMap?.hasKey("marginBottom") == true) styleMap.getDouble("marginBottom").toFloat() else 8f,
|
|
162
192
|
)
|
|
163
|
-
val
|
|
164
|
-
val
|
|
165
|
-
when (
|
|
193
|
+
val textAlignRaw = if (styleMap?.hasKey("textAlign") == true) styleMap.getString("textAlign") else null
|
|
194
|
+
val textAlign =
|
|
195
|
+
when (textAlignRaw) {
|
|
166
196
|
"left" -> Layout.Alignment.ALIGN_NORMAL
|
|
167
197
|
"right" -> Layout.Alignment.ALIGN_OPPOSITE
|
|
168
198
|
else -> Layout.Alignment.ALIGN_CENTER
|
|
@@ -182,7 +212,7 @@ object MarkdownStyleParser {
|
|
|
182
212
|
fontWeight = fontWeight,
|
|
183
213
|
marginTop = marginTop,
|
|
184
214
|
marginBottom = marginBottom,
|
|
185
|
-
|
|
215
|
+
textAlign = textAlign,
|
|
186
216
|
)
|
|
187
217
|
}
|
|
188
218
|
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
package com.swmansion.enriched.markdown.utils.input
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The pure half of the paste interception path. A `ClipData` cannot be built on
|
|
5
|
+
* the JVM, so the joining rule lives here where a unit test can reach it; the
|
|
6
|
+
* two call sites (context menu and `onReceiveContent`) only extract the items.
|
|
7
|
+
*/
|
|
8
|
+
object PasteTextUtils {
|
|
9
|
+
/**
|
|
10
|
+
* Flattens a clip's items into one string. A clip regularly carries more than
|
|
11
|
+
* one item — reading only `getItemAt(0)` silently drops items 2..n. Items
|
|
12
|
+
* without text (a URI or intent) are skipped, and the rest join on newlines,
|
|
13
|
+
* which is what the platform's own paste does.
|
|
14
|
+
*/
|
|
15
|
+
fun joinClipTexts(texts: List<CharSequence?>): String =
|
|
16
|
+
texts
|
|
17
|
+
.mapNotNull { it?.toString() }
|
|
18
|
+
.filter { it.isNotEmpty() }
|
|
19
|
+
.joinToString("\n")
|
|
20
|
+
}
|
|
@@ -2,6 +2,7 @@ package com.swmansion.enriched.markdown.utils.text
|
|
|
2
2
|
|
|
3
3
|
import android.graphics.Bitmap
|
|
4
4
|
import android.util.LruCache
|
|
5
|
+
import java.security.MessageDigest
|
|
5
6
|
|
|
6
7
|
object ImageCache {
|
|
7
8
|
private const val ORIGINAL_CACHE_SIZE = 20 * 1024 * 1024
|
|
@@ -10,6 +11,25 @@ object ImageCache {
|
|
|
10
11
|
private val originalCache = bitmapLruCache(ORIGINAL_CACHE_SIZE)
|
|
11
12
|
private val processedCache = bitmapLruCache(PROCESSED_CACHE_SIZE)
|
|
12
13
|
|
|
14
|
+
/**
|
|
15
|
+
* Cache identity for a remote image request. Returns the URL itself when no
|
|
16
|
+
* headers are set; otherwise appends a SHA-256 digest of the sorted header
|
|
17
|
+
* pairs, so the same URL fetched with different headers is cached and
|
|
18
|
+
* deduplicated separately without embedding header values in the key.
|
|
19
|
+
*/
|
|
20
|
+
fun requestKey(
|
|
21
|
+
url: String,
|
|
22
|
+
headers: Map<String, String>,
|
|
23
|
+
): String {
|
|
24
|
+
if (headers.isEmpty()) return url
|
|
25
|
+
val joined =
|
|
26
|
+
headers.entries
|
|
27
|
+
.sortedBy { it.key }
|
|
28
|
+
.joinToString(separator = "\n") { "${it.key}:${it.value}" }
|
|
29
|
+
val digest = MessageDigest.getInstance("SHA-256").digest(joined.toByteArray())
|
|
30
|
+
return url + "|" + digest.joinToString(separator = "") { "%02x".format(it) }
|
|
31
|
+
}
|
|
32
|
+
|
|
13
33
|
fun getOriginal(url: String): Bitmap? = originalCache.get(url)
|
|
14
34
|
|
|
15
35
|
fun putOriginal(
|
|
@@ -24,16 +44,18 @@ object ImageCache {
|
|
|
24
44
|
width: Int,
|
|
25
45
|
height: Int,
|
|
26
46
|
borderRadius: Int,
|
|
27
|
-
|
|
47
|
+
resizeMode: String,
|
|
48
|
+
): Bitmap? = processedCache.get(processedKey(url, width, height, borderRadius, resizeMode))
|
|
28
49
|
|
|
29
50
|
fun putProcessed(
|
|
30
51
|
url: String,
|
|
31
52
|
width: Int,
|
|
32
53
|
height: Int,
|
|
33
54
|
borderRadius: Int,
|
|
55
|
+
resizeMode: String,
|
|
34
56
|
bitmap: Bitmap,
|
|
35
57
|
) {
|
|
36
|
-
processedCache.put(processedKey(url, width, height, borderRadius), bitmap)
|
|
58
|
+
processedCache.put(processedKey(url, width, height, borderRadius, resizeMode), bitmap)
|
|
37
59
|
}
|
|
38
60
|
|
|
39
61
|
private fun processedKey(
|
|
@@ -41,7 +63,8 @@ object ImageCache {
|
|
|
41
63
|
width: Int,
|
|
42
64
|
height: Int,
|
|
43
65
|
borderRadius: Int,
|
|
44
|
-
|
|
66
|
+
resizeMode: String,
|
|
67
|
+
): String = "${url}_w${width}_h${height}_r${borderRadius}_m$resizeMode"
|
|
45
68
|
|
|
46
69
|
private fun bitmapLruCache(maxSize: Int): LruCache<String, Bitmap> =
|
|
47
70
|
object : LruCache<String, Bitmap>(maxSize) {
|
|
@@ -50,23 +50,31 @@ object ImageDownloader {
|
|
|
50
50
|
fun download(
|
|
51
51
|
context: Context,
|
|
52
52
|
url: String,
|
|
53
|
+
headers: Map<String, String> = emptyMap(),
|
|
53
54
|
callback: (Bitmap?) -> Unit,
|
|
54
55
|
) {
|
|
55
|
-
ImageCache.
|
|
56
|
+
val requestKey = ImageCache.requestKey(url, headers)
|
|
57
|
+
|
|
58
|
+
ImageCache.getOriginal(requestKey)?.let {
|
|
56
59
|
callback(it)
|
|
57
60
|
return
|
|
58
61
|
}
|
|
59
62
|
|
|
60
63
|
synchronized(inFlight) {
|
|
61
|
-
val existing = inFlight[
|
|
64
|
+
val existing = inFlight[requestKey]
|
|
62
65
|
if (existing != null) {
|
|
63
66
|
existing.add(callback)
|
|
64
67
|
return
|
|
65
68
|
}
|
|
66
|
-
inFlight[
|
|
69
|
+
inFlight[requestKey] = mutableListOf(callback)
|
|
67
70
|
}
|
|
68
71
|
|
|
69
|
-
val request =
|
|
72
|
+
val request =
|
|
73
|
+
Request
|
|
74
|
+
.Builder()
|
|
75
|
+
.url(url)
|
|
76
|
+
.apply { headers.forEach { (name, value) -> addHeader(name, value) } }
|
|
77
|
+
.build()
|
|
70
78
|
getClient(context).newCall(request).enqueue(
|
|
71
79
|
object : Callback {
|
|
72
80
|
override fun onResponse(
|
|
@@ -87,8 +95,8 @@ object ImageDownloader {
|
|
|
87
95
|
}
|
|
88
96
|
}
|
|
89
97
|
|
|
90
|
-
bitmap?.let { ImageCache.putOriginal(
|
|
91
|
-
dispatchCallbacks(
|
|
98
|
+
bitmap?.let { ImageCache.putOriginal(requestKey, it) }
|
|
99
|
+
dispatchCallbacks(requestKey, bitmap)
|
|
92
100
|
}
|
|
93
101
|
|
|
94
102
|
override fun onFailure(
|
|
@@ -96,7 +104,7 @@ object ImageDownloader {
|
|
|
96
104
|
e: IOException,
|
|
97
105
|
) {
|
|
98
106
|
Log.e(TAG, "Failed to download image: $url", e)
|
|
99
|
-
dispatchCallbacks(
|
|
107
|
+
dispatchCallbacks(requestKey, null)
|
|
100
108
|
}
|
|
101
109
|
},
|
|
102
110
|
)
|
|
@@ -113,6 +121,11 @@ object ImageDownloader {
|
|
|
113
121
|
}
|
|
114
122
|
}
|
|
115
123
|
|
|
124
|
+
fun decodeBytesDownsampled(
|
|
125
|
+
context: Context,
|
|
126
|
+
bytes: ByteArray,
|
|
127
|
+
): Bitmap? = decodeDownsampled(bytes, context.resources.displayMetrics.widthPixels)
|
|
128
|
+
|
|
116
129
|
fun decodeFileDownsampled(
|
|
117
130
|
context: Context,
|
|
118
131
|
path: String,
|
|
@@ -145,10 +158,10 @@ object ImageDownloader {
|
|
|
145
158
|
}
|
|
146
159
|
|
|
147
160
|
private fun dispatchCallbacks(
|
|
148
|
-
|
|
161
|
+
requestKey: String,
|
|
149
162
|
bitmap: Bitmap?,
|
|
150
163
|
) {
|
|
151
|
-
val callbacks = synchronized(inFlight) { inFlight.remove(
|
|
164
|
+
val callbacks = synchronized(inFlight) { inFlight.remove(requestKey) } ?: return
|
|
152
165
|
mainHandler.post {
|
|
153
166
|
callbacks.forEach { it(bitmap) }
|
|
154
167
|
}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
package com.swmansion.enriched.markdown.utils.text
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import android.graphics.Bitmap
|
|
5
|
+
import android.net.Uri
|
|
6
|
+
import android.util.Base64
|
|
7
|
+
import android.util.Log
|
|
8
|
+
import java.io.FileNotFoundException
|
|
9
|
+
import java.io.InputStream
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Loads markdown images from non-network sources (issue #377).
|
|
13
|
+
*
|
|
14
|
+
* React Native's asset system produces different URI shapes for the same
|
|
15
|
+
* `require('./img.png')` depending on environment, and none of them are plain
|
|
16
|
+
* file paths in a bundled app:
|
|
17
|
+
* - Metro dev server: `http://host:8081/assets/...` (handled by [ImageDownloader])
|
|
18
|
+
* - Release APK: a bare drawable resource name, e.g. `src_assets_logo`
|
|
19
|
+
* (RN's `AssetSourceResolver.resourceIdentifierWithoutScale`)
|
|
20
|
+
* - Sideloaded JS bundle: `file:///.../drawable-xhdpi/src_assets_logo.png`
|
|
21
|
+
* - expo-updates embedded assets: `file:///android_res/drawable/<name>.png`
|
|
22
|
+
* - expo-asset downloads: percent-encoded `file://` paths in the cache dir
|
|
23
|
+
*
|
|
24
|
+
* Resolution mirrors RN core: `ImageSource.computeUri` treats a scheme-less
|
|
25
|
+
* source as a resource name, and `ResourceDrawableIdHelper` normalizes names
|
|
26
|
+
* by lowercasing, replacing `-` with `_`, and accepting numeric resource ids. The
|
|
27
|
+
* `android_res`/`android_asset` and drawable/raw lookups follow expo-asset's
|
|
28
|
+
* `ResourceAsset.kt`. `content://`, `asset://`, `res://` and `data:` URIs are
|
|
29
|
+
* supported for parity with RN's Fresco pipeline. All decodes are downsampled
|
|
30
|
+
* to screen width like the network path.
|
|
31
|
+
*/
|
|
32
|
+
object LocalImageLoader {
|
|
33
|
+
private const val TAG = "LocalImageLoader"
|
|
34
|
+
private const val ASSET_PATH_PREFIX = "/android_asset/"
|
|
35
|
+
private const val RES_PATH_PREFIX = "/android_res/"
|
|
36
|
+
private const val BASE64_MARKER = "base64,"
|
|
37
|
+
|
|
38
|
+
fun load(
|
|
39
|
+
context: Context,
|
|
40
|
+
source: String,
|
|
41
|
+
): Bitmap? =
|
|
42
|
+
try {
|
|
43
|
+
val uri = Uri.parse(source)
|
|
44
|
+
when (uri.scheme?.lowercase()) {
|
|
45
|
+
null -> {
|
|
46
|
+
if (source.startsWith('/')) {
|
|
47
|
+
ImageDownloader.decodeFileDownsampled(context, source)
|
|
48
|
+
} else {
|
|
49
|
+
decodeResourceByName(context, source)
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
"file" -> {
|
|
54
|
+
loadFileUri(context, uri)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
"asset" -> {
|
|
58
|
+
decodeStream(context) { context.assets.open(schemelessPath(uri)) }
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
"content" -> {
|
|
62
|
+
decodeStream(context) {
|
|
63
|
+
context.contentResolver.openInputStream(uri) ?: throw FileNotFoundException(source)
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
"res" -> {
|
|
68
|
+
decodeResourceByName(context, schemelessPath(uri))
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
"data" -> {
|
|
72
|
+
decodeDataUri(context, source)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
else -> {
|
|
76
|
+
Log.w(TAG, "Unsupported image URI scheme: $source")
|
|
77
|
+
null
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
} catch (_: OutOfMemoryError) {
|
|
81
|
+
Log.e(TAG, "OOM loading local image: $source")
|
|
82
|
+
null
|
|
83
|
+
} catch (e: Exception) {
|
|
84
|
+
Log.w(TAG, "Failed to load local image: $source", e)
|
|
85
|
+
null
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
private fun loadFileUri(
|
|
89
|
+
context: Context,
|
|
90
|
+
uri: Uri,
|
|
91
|
+
): Bitmap? {
|
|
92
|
+
val path = uri.path ?: return null
|
|
93
|
+
return when {
|
|
94
|
+
path.startsWith(ASSET_PATH_PREFIX) -> {
|
|
95
|
+
decodeStream(context) { context.assets.open(path.removePrefix(ASSET_PATH_PREFIX)) }
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
path.startsWith(RES_PATH_PREFIX) -> {
|
|
99
|
+
decodeAndroidRes(context, uri)
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
else -> {
|
|
103
|
+
ImageDownloader.decodeFileDownsampled(context, path)
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Resolves `file:///android_res/<dir>[-qualifier]/<file>[.<ext>]` by stripping
|
|
110
|
+
* density qualifiers and the file extension, then looking the resource up by name.
|
|
111
|
+
*/
|
|
112
|
+
private fun decodeAndroidRes(
|
|
113
|
+
context: Context,
|
|
114
|
+
uri: Uri,
|
|
115
|
+
): Bitmap? {
|
|
116
|
+
val segments = uri.pathSegments
|
|
117
|
+
if (segments.size < 3) return null
|
|
118
|
+
val directory = segments[1].substringBefore('-')
|
|
119
|
+
val name = segments[2].substringBeforeLast('.')
|
|
120
|
+
val resId = context.resources.getIdentifier(name, directory, context.packageName)
|
|
121
|
+
if (resId == 0) {
|
|
122
|
+
Log.w(TAG, "No $directory resource named: $name")
|
|
123
|
+
return null
|
|
124
|
+
}
|
|
125
|
+
return decodeStream(context) { context.resources.openRawResource(resId) }
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
private fun decodeResourceByName(
|
|
129
|
+
context: Context,
|
|
130
|
+
name: String,
|
|
131
|
+
): Bitmap? {
|
|
132
|
+
if (name.isEmpty()) return null
|
|
133
|
+
val normalized = name.lowercase().replace('-', '_')
|
|
134
|
+
val resId =
|
|
135
|
+
normalized.toIntOrNull()
|
|
136
|
+
?: context.resources.getIdentifier(normalized, "drawable", context.packageName).takeIf { it != 0 }
|
|
137
|
+
?: context.resources.getIdentifier(normalized, "raw", context.packageName)
|
|
138
|
+
if (resId == 0) {
|
|
139
|
+
Log.w(TAG, "No drawable or raw resource named: $normalized")
|
|
140
|
+
return null
|
|
141
|
+
}
|
|
142
|
+
return decodeStream(context) { context.resources.openRawResource(resId) }
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
private fun decodeDataUri(
|
|
146
|
+
context: Context,
|
|
147
|
+
source: String,
|
|
148
|
+
): Bitmap? {
|
|
149
|
+
val marker = source.indexOf(BASE64_MARKER)
|
|
150
|
+
if (marker == -1) return null
|
|
151
|
+
val bytes = Base64.decode(source.substring(marker + BASE64_MARKER.length), Base64.DEFAULT)
|
|
152
|
+
return ImageDownloader.decodeBytesDownsampled(context, bytes)
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
private inline fun decodeStream(
|
|
156
|
+
context: Context,
|
|
157
|
+
open: () -> InputStream,
|
|
158
|
+
): Bitmap? = open().use { ImageDownloader.decodeBytesDownsampled(context, it.readBytes()) }
|
|
159
|
+
|
|
160
|
+
private fun schemelessPath(uri: Uri): String = (uri.host.orEmpty() + uri.path.orEmpty()).trimStart('/')
|
|
161
|
+
}
|
|
@@ -7,6 +7,7 @@ import com.facebook.react.common.ReactConstants
|
|
|
7
7
|
import com.facebook.react.views.text.ReactTypefaceUtils.applyStyles
|
|
8
8
|
import com.facebook.react.views.text.ReactTypefaceUtils.parseFontWeight
|
|
9
9
|
import com.swmansion.enriched.markdown.renderer.BlockStyle
|
|
10
|
+
import com.swmansion.enriched.markdown.styles.CodeBlockStyle
|
|
10
11
|
|
|
11
12
|
fun TextPaint.applyColorPreserving(
|
|
12
13
|
color: Int,
|
|
@@ -51,3 +52,25 @@ fun TextPaint.applyBlockStyleFont(
|
|
|
51
52
|
typefaceCache[cacheKey] = newTypeface
|
|
52
53
|
this.typeface = newTypeface
|
|
53
54
|
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Code block text sizing and font, shared by both flavors (CodeBlockSpan for
|
|
58
|
+
* commonmark, CodeBlockContainerView for github) so the code always renders
|
|
59
|
+
* and measures with the same paint. Color is applied by the callers: the span
|
|
60
|
+
* needs color preserving, the view colors via the text view.
|
|
61
|
+
*/
|
|
62
|
+
fun TextPaint.applyCodeBlockTextStyle(
|
|
63
|
+
style: CodeBlockStyle,
|
|
64
|
+
context: Context,
|
|
65
|
+
) {
|
|
66
|
+
textSize = style.fontSize
|
|
67
|
+
applyBlockStyleFont(
|
|
68
|
+
BlockStyle(
|
|
69
|
+
fontSize = style.fontSize,
|
|
70
|
+
fontFamily = style.fontFamily,
|
|
71
|
+
fontWeight = style.fontWeight,
|
|
72
|
+
color = style.color,
|
|
73
|
+
),
|
|
74
|
+
context,
|
|
75
|
+
)
|
|
76
|
+
}
|
|
@@ -12,6 +12,12 @@ class CheckboxTouchHelper(
|
|
|
12
12
|
) {
|
|
13
13
|
var onCheckboxTap: ((taskIndex: Int, checked: Boolean, itemText: String) -> Unit)? = null
|
|
14
14
|
|
|
15
|
+
/**
|
|
16
|
+
* When false, checkbox taps are ignored: hit-testing is skipped and no
|
|
17
|
+
* gesture is consumed, so the tap falls through to the text view unchanged.
|
|
18
|
+
*/
|
|
19
|
+
var isEnabled: Boolean = true
|
|
20
|
+
|
|
15
21
|
private var touchDownX = 0f
|
|
16
22
|
private var touchDownY = 0f
|
|
17
23
|
private var pendingHit: TaskListHitTestResult? = null
|
|
@@ -19,6 +25,7 @@ class CheckboxTouchHelper(
|
|
|
19
25
|
|
|
20
26
|
/** Returns `true` if the event was consumed by a checkbox gesture. */
|
|
21
27
|
fun onTouchEvent(event: MotionEvent): Boolean {
|
|
28
|
+
if (!isEnabled) return false
|
|
22
29
|
when (event.actionMasked) {
|
|
23
30
|
MotionEvent.ACTION_DOWN -> {
|
|
24
31
|
val hit = TaskListTapUtils.hitTest(textView, event.x, event.y) ?: return false
|