react-native-enriched-markdown-scaffold 0.7.4-scaffold.8 → 1.0.2-scaffold.1
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 +191 -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 +27 -0
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextInputManagerInterface.java +9 -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 +40 -0
- package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/Props.h +839 -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 +175 -11
- 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 +62 -4
- package/android/src/main/java/com/swmansion/enriched/markdown/input/EnrichedMarkdownTextInputView.kt +911 -460
- 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/BlockSyntaxSentinel.kt +69 -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 +180 -27
- 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 +7 -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 +33 -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 +19 -2
- package/android/src/main/java/com/swmansion/enriched/markdown/views/CodeBlockContainerView.kt +388 -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 +32 -5
- 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 +2 -0
- 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 +231 -8
- package/docs/BREAKING_CHANGES.md +129 -0
- package/docs/CODE_HIGHLIGHT.md +133 -0
- package/docs/COPY_OPTIONS.md +21 -3
- package/docs/ELEMENTS_STRUCTURE.md +52 -4
- package/docs/IMAGE_CACHING.md +30 -0
- package/docs/INPUT.md +146 -5
- 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 +262 -67
- package/ios/EnrichedMarkdownText.h +7 -0
- package/ios/EnrichedMarkdownText.mm +97 -68
- 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 +40 -0
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/Props.h +839 -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/ENRMBlockSyntaxSentinel.h +25 -0
- package/ios/input/ENRMBlockSyntaxSentinel.mm +80 -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 +10 -6
- package/ios/input/ENRMInputParser.mm +527 -171
- 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 +1104 -1024
- 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/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.m +22 -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/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 +46 -0
- package/ios/views/ENRMCodeBlockContainerView.m +566 -0
- package/ios/views/ENRMMathContainerView.h +12 -0
- package/ios/views/ENRMMathContainerView.m +71 -1
- package/ios/views/TableContainerView.h +18 -0
- package/ios/views/TableContainerView.m +259 -159
- package/jest.d.ts +1 -0
- package/jest.js +5 -0
- package/lib/module/EnrichedMarkdownNativeComponent.ts +65 -0
- package/lib/module/EnrichedMarkdownTextInput.js +86 -5
- package/lib/module/EnrichedMarkdownTextInput.js.map +1 -1
- package/lib/module/EnrichedMarkdownTextInputNativeComponent.ts +89 -5
- package/lib/module/EnrichedMarkdownTextNativeComponent.ts +66 -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 +30 -4
- 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 +62 -0
- package/lib/typescript/src/EnrichedMarkdownNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/EnrichedMarkdownTextInput.d.ts +95 -9
- package/lib/typescript/src/EnrichedMarkdownTextInput.d.ts.map +1 -1
- package/lib/typescript/src/EnrichedMarkdownTextInputNativeComponent.d.ts +80 -5
- package/lib/typescript/src/EnrichedMarkdownTextInputNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/EnrichedMarkdownTextNativeComponent.d.ts +62 -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 +65 -1
- 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 +65 -0
- package/src/EnrichedMarkdownTextInput.tsx +162 -8
- package/src/EnrichedMarkdownTextInputNativeComponent.ts +89 -5
- package/src/EnrichedMarkdownTextNativeComponent.ts +66 -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 +40 -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 +65 -0
- 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
|
@@ -7,6 +7,7 @@ import android.graphics.Color
|
|
|
7
7
|
import android.graphics.Paint
|
|
8
8
|
import android.graphics.Path
|
|
9
9
|
import android.graphics.drawable.Drawable
|
|
10
|
+
import android.net.Uri
|
|
10
11
|
import android.os.Build
|
|
11
12
|
import android.text.Spannable
|
|
12
13
|
import android.text.Spanned
|
|
@@ -17,9 +18,12 @@ import androidx.core.graphics.createBitmap
|
|
|
17
18
|
import androidx.core.graphics.drawable.toDrawable
|
|
18
19
|
import androidx.core.graphics.withClip
|
|
19
20
|
import androidx.core.graphics.withSave
|
|
21
|
+
import com.swmansion.enriched.markdown.EnrichedMarkdown
|
|
22
|
+
import com.swmansion.enriched.markdown.EnrichedMarkdownText
|
|
20
23
|
import com.swmansion.enriched.markdown.styles.StyleConfig
|
|
21
24
|
import com.swmansion.enriched.markdown.utils.text.ImageCache
|
|
22
25
|
import com.swmansion.enriched.markdown.utils.text.ImageDownloader
|
|
26
|
+
import com.swmansion.enriched.markdown.utils.text.LocalImageLoader
|
|
23
27
|
import java.lang.ref.WeakReference
|
|
24
28
|
import java.util.concurrent.Executors
|
|
25
29
|
import android.text.style.ImageSpan as AndroidImageSpan
|
|
@@ -39,36 +43,84 @@ class ImageSpan(
|
|
|
39
43
|
AndroidLineHeightSpan {
|
|
40
44
|
private var loadedDrawable: Drawable? = null
|
|
41
45
|
private val height: Int = if (isInline) styleConfig.inlineImageStyle.size.toInt() else styleConfig.imageStyle.height.toInt()
|
|
42
|
-
|
|
46
|
+
|
|
47
|
+
private val borderRadiusPx: Int = styleConfig.imageStyle.borderRadius.toInt()
|
|
48
|
+
private val maxHeightPx: Int = if (isInline) 0 else styleConfig.imageStyle.maxHeight.toInt()
|
|
49
|
+
private val aspectRatio: Float = if (isInline) 0f else styleConfig.imageStyle.aspectRatio
|
|
50
|
+
private val resizeMode: String = if (isInline) "" else styleConfig.imageStyle.resizeMode
|
|
51
|
+
|
|
52
|
+
// so legacy always implies a fixed height box.
|
|
53
|
+
private val legacySizing: Boolean = resizeMode.isEmpty()
|
|
54
|
+
|
|
55
|
+
private val dynamicBoxHeight: Boolean = !isInline && (maxHeightPx > 0 || aspectRatio > 0f)
|
|
56
|
+
|
|
57
|
+
private var boxHeight: Int =
|
|
58
|
+
when {
|
|
59
|
+
isInline -> height
|
|
60
|
+
maxHeightPx > 0 -> maxHeightPx
|
|
61
|
+
else -> height
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
private val requestHeaders: Map<String, String> = styleConfig.imageRequestHeaders
|
|
65
|
+
private val requestKey: String = ImageCache.requestKey(imageUrl, requestHeaders)
|
|
43
66
|
|
|
44
67
|
private var cachedWidth: Int = 0
|
|
45
68
|
private var viewRef: WeakReference<TextView>? = null
|
|
46
69
|
private var sourceDrawable: Drawable? = null
|
|
47
70
|
|
|
71
|
+
private fun intrinsicImageSize(): Pair<Int, Int> {
|
|
72
|
+
sourceDrawable?.let { return it.intrinsicWidth to it.intrinsicHeight }
|
|
73
|
+
val cached = ImageCache.getOriginal(imageUrl) ?: return 0 to 0
|
|
74
|
+
return cached.width to cached.height
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Sizing precedence: aspectRatio > maxHeight > height. Returns the legacy fixed
|
|
78
|
+
// height when no new knob is set.
|
|
79
|
+
private fun resolveBoxHeight(targetWidth: Int): Int {
|
|
80
|
+
if (isInline) return height
|
|
81
|
+
if (aspectRatio > 0f && targetWidth > 0) {
|
|
82
|
+
return (targetWidth / aspectRatio).toInt().coerceAtLeast(1)
|
|
83
|
+
}
|
|
84
|
+
if (maxHeightPx > 0) {
|
|
85
|
+
val (intrinsicWidth, intrinsicHeight) = intrinsicImageSize()
|
|
86
|
+
if (targetWidth > 0 && intrinsicWidth > 0 && intrinsicHeight > 0) {
|
|
87
|
+
val fitted = targetWidth.toFloat() * intrinsicHeight / intrinsicWidth
|
|
88
|
+
return minOf(maxHeightPx.toFloat(), fitted).toInt().coerceAtLeast(1)
|
|
89
|
+
}
|
|
90
|
+
return maxHeightPx
|
|
91
|
+
}
|
|
92
|
+
return height
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
fun prepareForMeasurement(
|
|
96
|
+
text: Spanned,
|
|
97
|
+
widthPx: Int,
|
|
98
|
+
) {
|
|
99
|
+
if (!dynamicBoxHeight || widthPx <= 0) return
|
|
100
|
+
val available = availableWidthIn(text, widthPx)
|
|
101
|
+
if (available > 0) boxHeight = resolveBoxHeight(available)
|
|
102
|
+
}
|
|
103
|
+
|
|
48
104
|
init {
|
|
49
105
|
loadImage()
|
|
50
106
|
}
|
|
51
107
|
|
|
52
108
|
private fun loadImage() {
|
|
53
|
-
|
|
54
|
-
|
|
109
|
+
val scheme = Uri.parse(imageUrl).scheme?.lowercase()
|
|
110
|
+
if (scheme == "http" || scheme == "https") {
|
|
111
|
+
ImageDownloader.download(context, imageUrl, requestHeaders) { bitmap ->
|
|
55
112
|
if (bitmap != null) {
|
|
56
113
|
sourceDrawable = bitmap.toDrawable(context.resources)
|
|
57
114
|
wrapAndAssignDrawable()
|
|
58
115
|
}
|
|
59
116
|
}
|
|
60
117
|
} else {
|
|
61
|
-
val
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
sourceDrawable = bitmap.toDrawable(context.resources)
|
|
68
|
-
wrapAndAssignDrawable()
|
|
69
|
-
}
|
|
70
|
-
} catch (e: Exception) {
|
|
71
|
-
Log.w(TAG, "Failed to load local image: $path", e)
|
|
118
|
+
val cached = ImageCache.getOriginal(imageUrl)
|
|
119
|
+
val bitmap = cached ?: LocalImageLoader.load(context, imageUrl)
|
|
120
|
+
if (bitmap != null) {
|
|
121
|
+
if (cached == null) ImageCache.putOriginal(imageUrl, bitmap)
|
|
122
|
+
sourceDrawable = bitmap.toDrawable(context.resources)
|
|
123
|
+
wrapAndAssignDrawable()
|
|
72
124
|
}
|
|
73
125
|
}
|
|
74
126
|
}
|
|
@@ -83,21 +135,26 @@ class ImageSpan(
|
|
|
83
135
|
available.coerceAtLeast(0)
|
|
84
136
|
}
|
|
85
137
|
|
|
86
|
-
|
|
138
|
+
boxHeight = resolveBoxHeight(targetWidth)
|
|
139
|
+
|
|
140
|
+
val cachedBitmap = ImageCache.getProcessed(requestKey, targetWidth, boxHeight, borderRadiusPx, resizeMode)
|
|
141
|
+
|
|
87
142
|
if (cachedBitmap != null) {
|
|
88
143
|
loadedDrawable =
|
|
89
144
|
cachedBitmap.toDrawable(context.resources).apply {
|
|
90
|
-
setBounds(0, 0, targetWidth,
|
|
145
|
+
setBounds(0, 0, targetWidth, boxHeight)
|
|
91
146
|
}
|
|
92
147
|
} else {
|
|
93
148
|
loadedDrawable =
|
|
94
149
|
ScaledImageDrawable(
|
|
95
150
|
imageDrawable = base,
|
|
96
151
|
targetWidth = targetWidth,
|
|
97
|
-
targetHeight =
|
|
152
|
+
targetHeight = boxHeight,
|
|
98
153
|
borderRadius = borderRadiusPx,
|
|
99
154
|
isBlockImage = !isInline,
|
|
100
|
-
|
|
155
|
+
resizeMode = resizeMode,
|
|
156
|
+
legacySizing = legacySizing,
|
|
157
|
+
cacheKey = CacheKey(requestKey, targetWidth, boxHeight, borderRadiusPx, resizeMode),
|
|
101
158
|
)
|
|
102
159
|
}
|
|
103
160
|
requestReflow()
|
|
@@ -116,6 +173,22 @@ class ImageSpan(
|
|
|
116
173
|
view.invalidate()
|
|
117
174
|
view.requestLayout()
|
|
118
175
|
}
|
|
176
|
+
notifyBoxHeightMayHaveChanged(view)
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// With maxHeight/aspectRatio the box height can change after the image loads
|
|
180
|
+
// (maxHeight fitted, aspectRatio at a late width). The React container height
|
|
181
|
+
// was measured with the pre-load value, so ask the owning component to
|
|
182
|
+
// re-measure; it only propagates when the stored height actually changed.
|
|
183
|
+
private fun notifyBoxHeightMayHaveChanged(view: TextView) {
|
|
184
|
+
if (!dynamicBoxHeight) return
|
|
185
|
+
if (view is EnrichedMarkdownText) {
|
|
186
|
+
view.layoutManager.invalidateLayout()
|
|
187
|
+
return
|
|
188
|
+
}
|
|
189
|
+
var parent = view.parent
|
|
190
|
+
while (parent != null && parent !is EnrichedMarkdown) parent = parent.parent
|
|
191
|
+
parent?.onImageLayoutChanged()
|
|
119
192
|
}
|
|
120
193
|
|
|
121
194
|
fun registerTextView(view: TextView) {
|
|
@@ -137,12 +210,27 @@ class ImageSpan(
|
|
|
137
210
|
cachedWidth = newWidth
|
|
138
211
|
if (sourceDrawable != null) {
|
|
139
212
|
wrapAndAssignDrawable()
|
|
213
|
+
return
|
|
214
|
+
}
|
|
215
|
+
if (dynamicBoxHeight) {
|
|
216
|
+
val newBoxHeight = resolveBoxHeight(newWidth)
|
|
217
|
+
if (newBoxHeight != boxHeight) {
|
|
218
|
+
boxHeight = newBoxHeight
|
|
219
|
+
requestReflow()
|
|
220
|
+
}
|
|
140
221
|
}
|
|
141
222
|
}
|
|
142
223
|
|
|
143
224
|
private fun getAvailableWidth(view: TextView): Int {
|
|
144
225
|
val baseWidth = (view.layout?.width ?: view.width).coerceAtLeast(0)
|
|
145
226
|
val text = view.text as? Spanned ?: return baseWidth
|
|
227
|
+
return availableWidthIn(text, baseWidth)
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
private fun availableWidthIn(
|
|
231
|
+
text: Spanned,
|
|
232
|
+
baseWidth: Int,
|
|
233
|
+
): Int {
|
|
146
234
|
val start = text.getSpanStart(this).takeIf { it >= 0 } ?: return baseWidth
|
|
147
235
|
val end = text.getSpanEnd(this).coerceAtLeast(start)
|
|
148
236
|
// Subtract leading margins (list bullet/indent, blockquote bar) that consume
|
|
@@ -159,7 +247,7 @@ class ImageSpan(
|
|
|
159
247
|
val drawable = loadedDrawable ?: transparentDrawable
|
|
160
248
|
if (drawable !is ScaledImageDrawable) {
|
|
161
249
|
val drawableWidth = if (isInline) height else cachedWidth.takeIf { it > 0 } ?: drawable.intrinsicWidth
|
|
162
|
-
drawable.setBounds(0, 0, drawableWidth.coerceAtLeast(0),
|
|
250
|
+
drawable.setBounds(0, 0, drawableWidth.coerceAtLeast(0), boxHeight.coerceAtLeast(0))
|
|
163
251
|
}
|
|
164
252
|
return drawable
|
|
165
253
|
}
|
|
@@ -182,8 +270,8 @@ class ImageSpan(
|
|
|
182
270
|
) {
|
|
183
271
|
if (fm == null || isInline) return
|
|
184
272
|
val currentLineHeight = fm.descent - fm.ascent
|
|
185
|
-
if (
|
|
186
|
-
val extraHeight =
|
|
273
|
+
if (boxHeight > currentLineHeight) {
|
|
274
|
+
val extraHeight = boxHeight - currentLineHeight
|
|
187
275
|
fm.descent += extraHeight
|
|
188
276
|
fm.bottom += extraHeight
|
|
189
277
|
}
|
|
@@ -217,6 +305,7 @@ class ImageSpan(
|
|
|
217
305
|
val width: Int,
|
|
218
306
|
val height: Int,
|
|
219
307
|
val borderRadius: Int,
|
|
308
|
+
val resizeMode: String,
|
|
220
309
|
)
|
|
221
310
|
|
|
222
311
|
private class ScaledImageDrawable(
|
|
@@ -225,6 +314,8 @@ class ImageSpan(
|
|
|
225
314
|
private val targetHeight: Int,
|
|
226
315
|
private val borderRadius: Int,
|
|
227
316
|
isBlockImage: Boolean,
|
|
317
|
+
private val resizeMode: String = "",
|
|
318
|
+
private val legacySizing: Boolean = true,
|
|
228
319
|
private val cacheKey: CacheKey? = null,
|
|
229
320
|
) : Drawable() {
|
|
230
321
|
private val clipPath: Path?
|
|
@@ -235,14 +326,26 @@ class ImageSpan(
|
|
|
235
326
|
val intrinsicWidth = imageDrawable.intrinsicWidth
|
|
236
327
|
val intrinsicHeight = imageDrawable.intrinsicHeight
|
|
237
328
|
|
|
329
|
+
// New sizing needs a clip to the box so cropping
|
|
330
|
+
// modes don't spill over neighbouring lines.
|
|
331
|
+
val clipToBox = isBlockImage && !legacySizing
|
|
332
|
+
|
|
238
333
|
val (scaledWidth, scaledHeight) =
|
|
239
334
|
if (intrinsicWidth > 0 && intrinsicHeight > 0) {
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
335
|
+
when {
|
|
336
|
+
!isBlockImage -> {
|
|
337
|
+
val scale = minOf(targetWidth.toFloat() / intrinsicWidth, targetHeight.toFloat() / intrinsicHeight)
|
|
338
|
+
(intrinsicWidth * scale).toInt() to (intrinsicHeight * scale).toInt()
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
legacySizing -> {
|
|
342
|
+
val scale = targetWidth.toFloat() / intrinsicWidth
|
|
343
|
+
targetWidth to (intrinsicHeight * scale).toInt()
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
else -> {
|
|
347
|
+
resizeModeSize(intrinsicWidth, intrinsicHeight)
|
|
348
|
+
}
|
|
246
349
|
}
|
|
247
350
|
} else {
|
|
248
351
|
targetWidth to targetHeight
|
|
@@ -252,26 +355,53 @@ class ImageSpan(
|
|
|
252
355
|
val top = (targetHeight - scaledHeight) / 2
|
|
253
356
|
imageDrawable.setBounds(left, top, left + scaledWidth, top + scaledHeight)
|
|
254
357
|
|
|
358
|
+
val clipLeft = maxOf(0, left).toFloat()
|
|
359
|
+
val clipTop = maxOf(0, top).toFloat()
|
|
360
|
+
val clipRight = minOf(targetWidth, left + scaledWidth).toFloat()
|
|
361
|
+
val clipBottom = minOf(targetHeight, top + scaledHeight).toFloat()
|
|
255
362
|
clipPath =
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
Path.Direction.CW,
|
|
270
|
-
)
|
|
363
|
+
when {
|
|
364
|
+
borderRadius > 0 -> {
|
|
365
|
+
Path().apply {
|
|
366
|
+
addRoundRect(
|
|
367
|
+
clipLeft,
|
|
368
|
+
clipTop,
|
|
369
|
+
clipRight,
|
|
370
|
+
clipBottom,
|
|
371
|
+
borderRadius.toFloat(),
|
|
372
|
+
borderRadius.toFloat(),
|
|
373
|
+
Path.Direction.CW,
|
|
374
|
+
)
|
|
375
|
+
}
|
|
271
376
|
}
|
|
272
|
-
|
|
273
|
-
|
|
377
|
+
|
|
378
|
+
clipToBox -> {
|
|
379
|
+
Path().apply {
|
|
380
|
+
addRect(clipLeft, clipTop, clipRight, clipBottom, Path.Direction.CW)
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
else -> {
|
|
385
|
+
null
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
private fun resizeModeSize(
|
|
391
|
+
intrinsicWidth: Int,
|
|
392
|
+
intrinsicHeight: Int,
|
|
393
|
+
): Pair<Int, Int> {
|
|
394
|
+
if (resizeMode == "stretch") return targetWidth to targetHeight
|
|
395
|
+
val widthScale = targetWidth.toFloat() / intrinsicWidth
|
|
396
|
+
val heightScale = targetHeight.toFloat() / intrinsicHeight
|
|
397
|
+
val scale =
|
|
398
|
+
when (resizeMode) {
|
|
399
|
+
"contain" -> minOf(widthScale, heightScale)
|
|
400
|
+
"center" -> minOf(1f, minOf(widthScale, heightScale))
|
|
401
|
+
"none" -> 1f
|
|
402
|
+
else -> maxOf(widthScale, heightScale) // cover (default)
|
|
274
403
|
}
|
|
404
|
+
return (intrinsicWidth * scale).toInt() to (intrinsicHeight * scale).toInt()
|
|
275
405
|
}
|
|
276
406
|
|
|
277
407
|
override fun draw(canvas: Canvas) {
|
|
@@ -303,7 +433,14 @@ class ImageSpan(
|
|
|
303
433
|
} else {
|
|
304
434
|
source.draw(offscreen)
|
|
305
435
|
}
|
|
306
|
-
ImageCache.putProcessed(
|
|
436
|
+
ImageCache.putProcessed(
|
|
437
|
+
cachedKey.url,
|
|
438
|
+
cachedKey.width,
|
|
439
|
+
cachedKey.height,
|
|
440
|
+
cachedKey.borderRadius,
|
|
441
|
+
cachedKey.resizeMode,
|
|
442
|
+
bitmap,
|
|
443
|
+
)
|
|
307
444
|
} catch (_: OutOfMemoryError) {
|
|
308
445
|
Log.e("ScaledImageDrawable", "OOM caching bitmap ${width}x$height")
|
|
309
446
|
}
|
|
@@ -328,7 +465,6 @@ class ImageSpan(
|
|
|
328
465
|
}
|
|
329
466
|
|
|
330
467
|
companion object {
|
|
331
|
-
private const val TAG = "ImageSpan"
|
|
332
468
|
private val transparentDrawable by lazy { Color.TRANSPARENT.toDrawable() }
|
|
333
469
|
private val cacheExecutor = Executors.newSingleThreadExecutor()
|
|
334
470
|
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
package com.swmansion.enriched.markdown.spans
|
|
2
|
+
|
|
3
|
+
import android.graphics.Paint
|
|
4
|
+
import android.text.Spanned
|
|
5
|
+
import android.text.style.LineHeightSpan
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Adds vertical spacing between list items using LineHeightSpan.
|
|
9
|
+
*
|
|
10
|
+
* Attached over the newline that separates two items; extends only the line
|
|
11
|
+
* ending at that newline so the gap appears below the preceding item.
|
|
12
|
+
*
|
|
13
|
+
* @param spacing The spacing in pixels to add below the line (0 = no spacing)
|
|
14
|
+
*/
|
|
15
|
+
class ListItemSpacingSpan(
|
|
16
|
+
val spacing: Float,
|
|
17
|
+
) : LineHeightSpan {
|
|
18
|
+
override fun chooseHeight(
|
|
19
|
+
text: CharSequence,
|
|
20
|
+
start: Int,
|
|
21
|
+
end: Int,
|
|
22
|
+
spanstartv: Int,
|
|
23
|
+
lineHeight: Int,
|
|
24
|
+
fm: Paint.FontMetricsInt,
|
|
25
|
+
) {
|
|
26
|
+
val spanEnd = (text as? Spanned)?.getSpanEnd(this) ?: return
|
|
27
|
+
if (end != spanEnd) return
|
|
28
|
+
|
|
29
|
+
val spacingPixels = spacing.toInt()
|
|
30
|
+
fm.descent += spacingPixels
|
|
31
|
+
fm.bottom += spacingPixels
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
package com.swmansion.enriched.markdown.spans
|
|
2
|
+
|
|
3
|
+
import android.graphics.Canvas
|
|
4
|
+
import android.graphics.Paint
|
|
5
|
+
import android.text.Layout
|
|
6
|
+
import android.text.Spanned
|
|
7
|
+
import android.text.style.LeadingMarginSpan
|
|
8
|
+
|
|
9
|
+
// Draws a list marker on a line owned by another block (code block, nested
|
|
10
|
+
// sublist) without contributing any margin of its own.
|
|
11
|
+
class ListMarkerAnchorSpan(
|
|
12
|
+
internal val marker: BaseListSpan,
|
|
13
|
+
) : LeadingMarginSpan {
|
|
14
|
+
override fun getLeadingMargin(first: Boolean): Int = 0
|
|
15
|
+
|
|
16
|
+
override fun drawLeadingMargin(
|
|
17
|
+
c: Canvas,
|
|
18
|
+
p: Paint,
|
|
19
|
+
x: Int,
|
|
20
|
+
dir: Int,
|
|
21
|
+
top: Int,
|
|
22
|
+
baseline: Int,
|
|
23
|
+
bottom: Int,
|
|
24
|
+
text: CharSequence?,
|
|
25
|
+
start: Int,
|
|
26
|
+
end: Int,
|
|
27
|
+
first: Boolean,
|
|
28
|
+
layout: Layout?,
|
|
29
|
+
) {
|
|
30
|
+
if (!first) return
|
|
31
|
+
if (text is Spanned && text.getSpanStart(this) != start) return
|
|
32
|
+
|
|
33
|
+
// Pass the paragraph origin: drawMarker reconstructs its offset from depth,
|
|
34
|
+
// matching the x its own span would receive on a plain text line.
|
|
35
|
+
val originX = if (dir > 0) 0 else layout?.width ?: 0
|
|
36
|
+
marker.drawMarkerAt(c, p, originX, dir, top, baseline, bottom, layout, start)
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -18,6 +18,7 @@ class OrderedListSpan(
|
|
|
18
18
|
depth: Int,
|
|
19
19
|
context: Context,
|
|
20
20
|
styleCache: SpanStyleCache,
|
|
21
|
+
drawsMarker: Boolean = true,
|
|
21
22
|
) : BaseListSpan(
|
|
22
23
|
depth = depth,
|
|
23
24
|
context = context,
|
|
@@ -31,6 +32,7 @@ class OrderedListSpan(
|
|
|
31
32
|
),
|
|
32
33
|
marginLeft = listStyle.marginLeft,
|
|
33
34
|
gapWidth = listStyle.gapWidth,
|
|
35
|
+
drawsMarker = drawsMarker,
|
|
34
36
|
) {
|
|
35
37
|
companion object {
|
|
36
38
|
private val sharedMarkerPaint = TextPaint().apply { isAntiAlias = true }
|
|
@@ -31,7 +31,7 @@ class StrongSpan(
|
|
|
31
31
|
tp.typeface =
|
|
32
32
|
if (styleCache.strongFontFamily.isNotEmpty()) {
|
|
33
33
|
val resolvedStyle = if (styleCache.strongFontWeight == "normal") Typeface.NORMAL else style
|
|
34
|
-
|
|
34
|
+
styleCache.getTypeface(styleCache.strongFontFamily, resolvedStyle)
|
|
35
35
|
} else {
|
|
36
36
|
Typeface.create(currentTypeface, style)
|
|
37
37
|
}
|
|
@@ -19,6 +19,7 @@ class TaskListSpan(
|
|
|
19
19
|
styleCache: SpanStyleCache,
|
|
20
20
|
val taskIndex: Int,
|
|
21
21
|
val isChecked: Boolean,
|
|
22
|
+
drawsMarker: Boolean = true,
|
|
22
23
|
) : BaseListSpan(
|
|
23
24
|
depth = depth,
|
|
24
25
|
context = context,
|
|
@@ -32,6 +33,7 @@ class TaskListSpan(
|
|
|
32
33
|
),
|
|
33
34
|
marginLeft = listStyle.marginLeft,
|
|
34
35
|
gapWidth = listStyle.gapWidth,
|
|
36
|
+
drawsMarker = drawsMarker,
|
|
35
37
|
) {
|
|
36
38
|
private val checkboxSize = taskStyle.checkboxSize
|
|
37
39
|
private val markerColumnWidth = listStyle.effectiveMarkerWidth(checkboxSize)
|
|
@@ -69,8 +71,7 @@ class TaskListSpan(
|
|
|
69
71
|
layout: Layout?,
|
|
70
72
|
start: Int,
|
|
71
73
|
) {
|
|
72
|
-
val
|
|
73
|
-
val capHeight = -fontMetrics.ascent * CAP_HEIGHT_RATIO
|
|
74
|
+
val capHeight = -markerFontMetrics.ascent * CAP_HEIGHT_RATIO
|
|
74
75
|
val centerY = baseline - capHeight / HALF_DIVISOR
|
|
75
76
|
// Right-align the checkbox inside the reserved marker column so it hugs
|
|
76
77
|
// the gap before the text. At the default (markerColumnWidth ==
|
|
@@ -13,6 +13,7 @@ class UnorderedListSpan(
|
|
|
13
13
|
depth: Int,
|
|
14
14
|
context: Context,
|
|
15
15
|
styleCache: SpanStyleCache,
|
|
16
|
+
drawsMarker: Boolean = true,
|
|
16
17
|
) : BaseListSpan(
|
|
17
18
|
depth = depth,
|
|
18
19
|
context = context,
|
|
@@ -26,6 +27,7 @@ class UnorderedListSpan(
|
|
|
26
27
|
),
|
|
27
28
|
marginLeft = listStyle.marginLeft,
|
|
28
29
|
gapWidth = listStyle.gapWidth,
|
|
30
|
+
drawsMarker = drawsMarker,
|
|
29
31
|
) {
|
|
30
32
|
companion object {
|
|
31
33
|
private val sharedBulletPaint =
|
|
@@ -64,8 +66,7 @@ class UnorderedListSpan(
|
|
|
64
66
|
// visually flush-left when the column width equals the bullet radius
|
|
65
67
|
// (the default).
|
|
66
68
|
val bulletX = x + (depth * marginLeft + markerColumnWidth) * dir
|
|
67
|
-
val
|
|
68
|
-
val bulletY = baseline + (fontMetrics.ascent + fontMetrics.descent) / 2f
|
|
69
|
+
val bulletY = baseline + (markerFontMetrics.ascent + markerFontMetrics.descent) / 2f
|
|
69
70
|
|
|
70
71
|
when (depth) {
|
|
71
72
|
0 -> {
|
|
@@ -14,6 +14,8 @@ data class BlockquoteStyle(
|
|
|
14
14
|
val borderWidth: Float,
|
|
15
15
|
val gapWidth: Float,
|
|
16
16
|
val backgroundColor: Int?,
|
|
17
|
+
val borderRadius: Float,
|
|
18
|
+
val padding: Float,
|
|
17
19
|
) : BaseBlockStyle {
|
|
18
20
|
companion object {
|
|
19
21
|
fun fromReadableMap(
|
|
@@ -32,6 +34,8 @@ data class BlockquoteStyle(
|
|
|
32
34
|
val borderWidth = parser.toPixelFromDIP(map.getDouble("borderWidth").toFloat())
|
|
33
35
|
val gapWidth = parser.toPixelFromDIP(map.getDouble("gapWidth").toFloat())
|
|
34
36
|
val backgroundColor = parser.parseOptionalColor(map, "backgroundColor")
|
|
37
|
+
val borderRadius = parser.toPixelFromDIP(map.getDouble("borderRadius").toFloat())
|
|
38
|
+
val padding = parser.toPixelFromDIP(map.getDouble("padding").toFloat())
|
|
35
39
|
|
|
36
40
|
return BlockquoteStyle(
|
|
37
41
|
fontSize,
|
|
@@ -45,6 +49,8 @@ data class BlockquoteStyle(
|
|
|
45
49
|
borderWidth,
|
|
46
50
|
gapWidth,
|
|
47
51
|
backgroundColor,
|
|
52
|
+
borderRadius,
|
|
53
|
+
padding,
|
|
48
54
|
)
|
|
49
55
|
}
|
|
50
56
|
}
|
|
@@ -15,8 +15,27 @@ data class CodeBlockStyle(
|
|
|
15
15
|
val borderRadius: Float,
|
|
16
16
|
val borderWidth: Float,
|
|
17
17
|
val padding: Float,
|
|
18
|
+
val syntaxColors: List<Int>,
|
|
18
19
|
) : BaseBlockStyle {
|
|
19
20
|
companion object {
|
|
21
|
+
private val SYNTAX_COLOR_KEYS =
|
|
22
|
+
listOf(
|
|
23
|
+
"keyword",
|
|
24
|
+
"operatorColor",
|
|
25
|
+
"punctuation",
|
|
26
|
+
"string",
|
|
27
|
+
"number",
|
|
28
|
+
"constant",
|
|
29
|
+
"comment",
|
|
30
|
+
"function",
|
|
31
|
+
"type",
|
|
32
|
+
"variable",
|
|
33
|
+
"property",
|
|
34
|
+
"tag",
|
|
35
|
+
"attribute",
|
|
36
|
+
"embedded",
|
|
37
|
+
)
|
|
38
|
+
|
|
20
39
|
fun fromReadableMap(
|
|
21
40
|
map: ReadableMap,
|
|
22
41
|
parser: StyleParser,
|
|
@@ -35,6 +54,12 @@ data class CodeBlockStyle(
|
|
|
35
54
|
val borderWidth = parser.toPixelFromDIP(map.getDouble("borderWidth").toFloat())
|
|
36
55
|
val padding = parser.toPixelFromDIP(map.getDouble("padding").toFloat())
|
|
37
56
|
|
|
57
|
+
val syntaxMap = map.getMap("syntaxColors")
|
|
58
|
+
val syntaxColors =
|
|
59
|
+
SYNTAX_COLOR_KEYS.map { key ->
|
|
60
|
+
syntaxMap?.let { parser.parseOptionalColor(it, key) } ?: color
|
|
61
|
+
}
|
|
62
|
+
|
|
38
63
|
return CodeBlockStyle(
|
|
39
64
|
fontSize,
|
|
40
65
|
fontFamily,
|
|
@@ -48,6 +73,7 @@ data class CodeBlockStyle(
|
|
|
48
73
|
borderRadius,
|
|
49
74
|
borderWidth,
|
|
50
75
|
padding,
|
|
76
|
+
syntaxColors,
|
|
51
77
|
)
|
|
52
78
|
}
|
|
53
79
|
}
|
|
@@ -4,6 +4,9 @@ import com.facebook.react.bridge.ReadableMap
|
|
|
4
4
|
|
|
5
5
|
data class ImageStyle(
|
|
6
6
|
val height: Float,
|
|
7
|
+
val maxHeight: Float,
|
|
8
|
+
val aspectRatio: Float,
|
|
9
|
+
val resizeMode: String,
|
|
7
10
|
val borderRadius: Float,
|
|
8
11
|
val marginTop: Float,
|
|
9
12
|
val marginBottom: Float,
|
|
@@ -14,10 +17,13 @@ data class ImageStyle(
|
|
|
14
17
|
parser: StyleParser,
|
|
15
18
|
): ImageStyle {
|
|
16
19
|
val height = parser.toPixelFromDIP(map.getDouble("height").toFloat())
|
|
20
|
+
val maxHeight = parser.toPixelFromDIP(map.getDouble("maxHeight").toFloat())
|
|
21
|
+
val aspectRatio = map.getDouble("aspectRatio").toFloat()
|
|
22
|
+
val resizeMode = map.getString("resizeMode") ?: ""
|
|
17
23
|
val borderRadius = parser.toPixelFromDIP(map.getDouble("borderRadius").toFloat())
|
|
18
24
|
val marginTop = parser.toPixelFromDIP(map.getDouble("marginTop").toFloat())
|
|
19
25
|
val marginBottom = parser.toPixelFromDIP(map.getDouble("marginBottom").toFloat())
|
|
20
|
-
return ImageStyle(height, borderRadius, marginTop, marginBottom)
|
|
26
|
+
return ImageStyle(height, maxHeight, aspectRatio, resizeMode, borderRadius, marginTop, marginBottom)
|
|
21
27
|
}
|
|
22
28
|
}
|
|
23
29
|
}
|
|
@@ -17,6 +17,7 @@ data class ListStyle(
|
|
|
17
17
|
val markerFontWeight: String,
|
|
18
18
|
val gapWidth: Float,
|
|
19
19
|
val marginLeft: Float,
|
|
20
|
+
val itemSpacing: Float,
|
|
20
21
|
) : BaseBlockStyle {
|
|
21
22
|
fun effectiveMarkerWidth(naturalWidth: Float): Float = naturalWidth.coerceAtLeast(markerMinWidth)
|
|
22
23
|
|
|
@@ -34,12 +35,13 @@ data class ListStyle(
|
|
|
34
35
|
val lineHeightRaw = map.getDouble("lineHeight").toFloat()
|
|
35
36
|
val lineHeight = parser.toPixelFromSP(lineHeightRaw)
|
|
36
37
|
val bulletColor = parser.parseColor(map, "bulletColor")
|
|
37
|
-
val bulletSize = parser.
|
|
38
|
+
val bulletSize = parser.toPixelFromSP(map.getDouble("bulletSize").toFloat())
|
|
38
39
|
val markerMinWidth = parser.toPixelFromDIP(map.getDouble("markerMinWidth").toFloat().coerceAtLeast(0f))
|
|
39
40
|
val markerColor = parser.parseColor(map, "markerColor")
|
|
40
41
|
val markerFontWeight = parser.parseString(map, "markerFontWeight", "normal")
|
|
41
42
|
val gapWidth = parser.toPixelFromDIP(map.getDouble("gapWidth").toFloat())
|
|
42
43
|
val marginLeft = parser.toPixelFromDIP(map.getDouble("marginLeft").toFloat())
|
|
44
|
+
val itemSpacing = parser.toPixelFromDIP(map.getDouble("itemSpacing").toFloat().coerceAtLeast(0f))
|
|
43
45
|
|
|
44
46
|
return ListStyle(
|
|
45
47
|
fontSize,
|
|
@@ -56,6 +58,7 @@ data class ListStyle(
|
|
|
56
58
|
markerFontWeight,
|
|
57
59
|
gapWidth,
|
|
58
60
|
marginLeft,
|
|
61
|
+
itemSpacing,
|
|
59
62
|
)
|
|
60
63
|
}
|
|
61
64
|
}
|