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/input/styles/HeadingBlockHandler.kt
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
package com.swmansion.enriched.markdown.input.styles
|
|
2
|
+
|
|
3
|
+
import com.swmansion.enriched.markdown.input.model.BlockRange
|
|
4
|
+
import com.swmansion.enriched.markdown.input.model.BlockType
|
|
5
|
+
import com.swmansion.enriched.markdown.input.model.InputFormatterStyle
|
|
6
|
+
import com.swmansion.enriched.markdown.input.spans.InputHeadingSpan
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Block handler for ATX headings (H1-H6). A single instance serves all six levels:
|
|
10
|
+
* it reads the H-level from each [BlockRange.level], so it is registered in the
|
|
11
|
+
* [com.swmansion.enriched.markdown.input.formatting.InputFormatter] under every
|
|
12
|
+
* `HEADING_n` key. The level — not [blockType] — drives styling and serialization,
|
|
13
|
+
* so [blockType] is only a nominal interface value and never consulted by the
|
|
14
|
+
* formatter (it dispatches on `range.type`).
|
|
15
|
+
*/
|
|
16
|
+
class HeadingBlockHandler : BlockHandler {
|
|
17
|
+
override val blockType: BlockType = BlockType.HEADING_1
|
|
18
|
+
|
|
19
|
+
override fun createSpans(
|
|
20
|
+
blockRange: BlockRange,
|
|
21
|
+
style: InputFormatterStyle,
|
|
22
|
+
): List<Any> = listOf(InputHeadingSpan(blockRange.level, style))
|
|
23
|
+
|
|
24
|
+
override fun spanClasses(): List<Class<*>> = listOf(InputHeadingSpan::class.java)
|
|
25
|
+
|
|
26
|
+
override fun markdownLinePrefix(blockRange: BlockRange): String = "#".repeat(blockRange.level.coerceIn(1, 6)) + " "
|
|
27
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
package com.swmansion.enriched.markdown.input.styles
|
|
2
|
+
|
|
3
|
+
import com.swmansion.enriched.markdown.input.model.BlockRange
|
|
4
|
+
import com.swmansion.enriched.markdown.input.model.BlockType
|
|
5
|
+
import com.swmansion.enriched.markdown.input.model.InputFormatterStyle
|
|
6
|
+
import com.swmansion.enriched.markdown.input.spans.InputListItemSpacingSpan
|
|
7
|
+
import com.swmansion.enriched.markdown.input.spans.InputOrderedListMarkerSpan
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Block handler for ordered list items. One instance serves every nesting depth —
|
|
11
|
+
* the 0-based depth rides in [BlockRange.level] and the displayed number in
|
|
12
|
+
* [BlockRange.ordinal], both maintained by the block store.
|
|
13
|
+
*/
|
|
14
|
+
class OrderedListBlockHandler(
|
|
15
|
+
private val density: Float,
|
|
16
|
+
) : BlockHandler {
|
|
17
|
+
override val blockType: BlockType = BlockType.ORDERED_LIST_ITEM
|
|
18
|
+
|
|
19
|
+
override val continuesOnNewline: Boolean = true
|
|
20
|
+
|
|
21
|
+
override fun createSpans(
|
|
22
|
+
blockRange: BlockRange,
|
|
23
|
+
style: InputFormatterStyle,
|
|
24
|
+
): List<Any> {
|
|
25
|
+
val spans = mutableListOf<Any>(InputOrderedListMarkerSpan(blockRange.level, blockRange.ordinal, density))
|
|
26
|
+
val spacingPx = (style.listItemSpacing * density).toInt()
|
|
27
|
+
if (spacingPx > 0) {
|
|
28
|
+
spans.add(InputListItemSpacingSpan(spacingPx))
|
|
29
|
+
}
|
|
30
|
+
return spans
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
override fun spanClasses(): List<Class<*>> = listOf(InputOrderedListMarkerSpan::class.java, InputListItemSpacingSpan::class.java)
|
|
34
|
+
|
|
35
|
+
/** `"1. "` numbering from the range's ordinal, indented three spaces per nesting depth. */
|
|
36
|
+
override fun markdownLinePrefix(blockRange: BlockRange): String =
|
|
37
|
+
" ".repeat(blockRange.level.coerceAtLeast(0)) + "${blockRange.ordinal}. "
|
|
38
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
package com.swmansion.enriched.markdown.input.styles
|
|
2
|
+
|
|
3
|
+
import com.swmansion.enriched.markdown.input.model.BlockRange
|
|
4
|
+
import com.swmansion.enriched.markdown.input.model.BlockType
|
|
5
|
+
import com.swmansion.enriched.markdown.input.model.InputFormatterStyle
|
|
6
|
+
import com.swmansion.enriched.markdown.input.spans.InputBulletSpan
|
|
7
|
+
import com.swmansion.enriched.markdown.input.spans.InputListItemSpacingSpan
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Block handler for unordered (bullet) list items. One instance serves every
|
|
11
|
+
* nesting depth — the 0-based depth rides in [BlockRange.level] and drives the
|
|
12
|
+
* indent, marker glyph, and serialized indentation.
|
|
13
|
+
*/
|
|
14
|
+
class UnorderedListBlockHandler(
|
|
15
|
+
private val density: Float,
|
|
16
|
+
) : BlockHandler {
|
|
17
|
+
override val blockType: BlockType = BlockType.UNORDERED_LIST_ITEM
|
|
18
|
+
|
|
19
|
+
override val continuesOnNewline: Boolean = true
|
|
20
|
+
|
|
21
|
+
override fun createSpans(
|
|
22
|
+
blockRange: BlockRange,
|
|
23
|
+
style: InputFormatterStyle,
|
|
24
|
+
): List<Any> {
|
|
25
|
+
val spans = mutableListOf<Any>(InputBulletSpan(blockRange.level, density))
|
|
26
|
+
val spacingPx = (style.listItemSpacing * density).toInt()
|
|
27
|
+
if (spacingPx > 0) {
|
|
28
|
+
spans.add(InputListItemSpacingSpan(spacingPx))
|
|
29
|
+
}
|
|
30
|
+
return spans
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
override fun spanClasses(): List<Class<*>> = listOf(InputBulletSpan::class.java, InputListItemSpacingSpan::class.java)
|
|
34
|
+
|
|
35
|
+
/** `"- "` for a top-level item, indented three spaces per nesting depth (wide enough for ordered markers). */
|
|
36
|
+
override fun markdownLinePrefix(blockRange: BlockRange): String = " ".repeat(blockRange.level.coerceAtLeast(0)) + "- "
|
|
37
|
+
}
|
package/android/src/main/java/com/swmansion/enriched/markdown/input/toolbar/InputContextMenu.kt
CHANGED
|
@@ -10,8 +10,8 @@ import android.view.MenuItem
|
|
|
10
10
|
import android.widget.EditText
|
|
11
11
|
import androidx.appcompat.app.AlertDialog
|
|
12
12
|
import com.swmansion.enriched.markdown.input.EnrichedMarkdownTextInputView
|
|
13
|
+
import com.swmansion.enriched.markdown.input.MarkdownClipboard
|
|
13
14
|
import com.swmansion.enriched.markdown.input.formatting.MarkdownSerializer
|
|
14
|
-
import com.swmansion.enriched.markdown.input.model.FormattingRange
|
|
15
15
|
import com.swmansion.enriched.markdown.input.model.StyleType
|
|
16
16
|
|
|
17
17
|
data class InputSelectionMenuConfig(
|
|
@@ -112,7 +112,9 @@ class InputContextMenu(
|
|
|
112
112
|
if (customIndex in customItemTexts.indices) {
|
|
113
113
|
val start = view.selectionStart
|
|
114
114
|
val end = view.selectionEnd
|
|
115
|
-
|
|
115
|
+
// Strip the internal ZWSP anchor so it never reaches JS (a selection can
|
|
116
|
+
// span an empty anchored list line).
|
|
117
|
+
val selectedText = if (start < end) MarkdownSerializer.stripZwsp(view.text?.substring(start, end) ?: "") else ""
|
|
116
118
|
view.eventEmitter.emitContextMenuItemPress(customItemTexts[customIndex], selectedText, start, end)
|
|
117
119
|
mode.finish()
|
|
118
120
|
return true
|
|
@@ -171,32 +173,12 @@ class InputContextMenu(
|
|
|
171
173
|
.show()
|
|
172
174
|
}
|
|
173
175
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
val selEnd = view.selectionEnd
|
|
177
|
-
if (selStart >= selEnd) return null
|
|
178
|
-
|
|
179
|
-
val editable = view.text ?: return null
|
|
180
|
-
val selected = editable.subSequence(selStart, selEnd) as? android.text.Spanned ?: return null
|
|
181
|
-
|
|
182
|
-
val clippedRanges = mutableListOf<FormattingRange>()
|
|
183
|
-
for (range in view.formattingStore.allRanges) {
|
|
184
|
-
if (range.end <= selStart || range.start >= selEnd) continue
|
|
185
|
-
|
|
186
|
-
val clippedStart = maxOf(range.start, selStart)
|
|
187
|
-
val clippedEnd = minOf(range.end, selEnd)
|
|
188
|
-
clippedRanges.add(
|
|
189
|
-
FormattingRange(range.type, clippedStart - selStart, clippedEnd - selStart, range.url),
|
|
190
|
-
)
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
return MarkdownSerializer.serialize(selected, clippedRanges, view.mathChipController)
|
|
194
|
-
}
|
|
195
|
-
|
|
176
|
+
// Explicit "Copy as Markdown": the user asked for markdown syntax, so it is
|
|
177
|
+
// also the plain-text representation external targets receive.
|
|
196
178
|
fun copyAsMarkdown() {
|
|
197
|
-
val markdown = markdownForSelectedRange() ?: return
|
|
179
|
+
val markdown = view.markdownForSelectedRange() ?: return
|
|
198
180
|
val clipboard = view.context.getSystemService(Context.CLIPBOARD_SERVICE) as? ClipboardManager ?: return
|
|
199
|
-
clipboard.setPrimaryClip(
|
|
181
|
+
clipboard.setPrimaryClip(MarkdownClipboard.newMarkdownClip(markdown, markdown))
|
|
200
182
|
}
|
|
201
183
|
|
|
202
184
|
companion object {
|
|
@@ -42,6 +42,9 @@ class BlockStyleContext {
|
|
|
42
42
|
var listType: ListType? = null
|
|
43
43
|
var listItemNumber = 0
|
|
44
44
|
var taskItemCount = 0
|
|
45
|
+
var accumulatedIndent = 0
|
|
46
|
+
|
|
47
|
+
val listItemStarts = mutableListOf<Int>()
|
|
45
48
|
|
|
46
49
|
private val orderedListItemNumbers = ArrayDeque<Int>()
|
|
47
50
|
|
|
@@ -106,8 +109,10 @@ class BlockStyleContext {
|
|
|
106
109
|
listItemNumber++
|
|
107
110
|
}
|
|
108
111
|
|
|
109
|
-
fun resetListItemNumber() {
|
|
110
|
-
|
|
112
|
+
fun resetListItemNumber(startNumber: Int = 1) {
|
|
113
|
+
// ListItemRenderer pre-increments, so the counter starts one below the
|
|
114
|
+
// first rendered number.
|
|
115
|
+
listItemNumber = startNumber - 1
|
|
111
116
|
}
|
|
112
117
|
|
|
113
118
|
fun pushOrderedListItemNumber() {
|
|
@@ -147,6 +152,8 @@ class BlockStyleContext {
|
|
|
147
152
|
listType = null
|
|
148
153
|
listItemNumber = 0
|
|
149
154
|
taskItemCount = 0
|
|
155
|
+
accumulatedIndent = 0
|
|
156
|
+
listItemStarts.clear()
|
|
150
157
|
orderedListItemNumbers.clear()
|
|
151
158
|
}
|
|
152
159
|
}
|
package/android/src/main/java/com/swmansion/enriched/markdown/renderer/BlockquoteRenderer.kt
CHANGED
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
package com.swmansion.enriched.markdown.renderer
|
|
2
2
|
|
|
3
|
+
import android.graphics.Paint
|
|
3
4
|
import android.text.SpannableStringBuilder
|
|
5
|
+
import android.text.Spanned
|
|
6
|
+
import android.text.style.LineHeightSpan
|
|
4
7
|
import com.swmansion.enriched.markdown.parser.MarkdownASTNode
|
|
5
8
|
import com.swmansion.enriched.markdown.spans.BlockquoteSpan
|
|
6
9
|
import com.swmansion.enriched.markdown.utils.text.span.SPAN_FLAGS_CONTAINER_BACKGROUND
|
|
7
10
|
import com.swmansion.enriched.markdown.utils.text.span.SPAN_FLAGS_EXCLUSIVE_EXCLUSIVE
|
|
11
|
+
import com.swmansion.enriched.markdown.utils.text.span.applyLineHeightSkippingImages
|
|
8
12
|
import com.swmansion.enriched.markdown.utils.text.span.applyMarginBottom
|
|
9
13
|
import com.swmansion.enriched.markdown.utils.text.span.applyMarginTop
|
|
10
|
-
import com.swmansion.enriched.markdown.utils.text.span.createLineHeightSpan
|
|
11
14
|
|
|
12
15
|
class BlockquoteRenderer(
|
|
13
16
|
private val config: RendererConfig,
|
|
@@ -19,6 +22,10 @@ class BlockquoteRenderer(
|
|
|
19
22
|
onLinkLongPress: ((String) -> Unit)?,
|
|
20
23
|
factory: RendererFactory,
|
|
21
24
|
) {
|
|
25
|
+
if (builder.isNotEmpty() && builder.last() != '\n') {
|
|
26
|
+
builder.append("\n")
|
|
27
|
+
}
|
|
28
|
+
|
|
22
29
|
val start = builder.length
|
|
23
30
|
val style = config.style.blockquoteStyle
|
|
24
31
|
val context = factory.blockStyleContext
|
|
@@ -36,19 +43,31 @@ class BlockquoteRenderer(
|
|
|
36
43
|
}
|
|
37
44
|
|
|
38
45
|
if (builder.length == start) return
|
|
39
|
-
|
|
46
|
+
var end = builder.length
|
|
47
|
+
val padding = style.padding.toInt()
|
|
48
|
+
|
|
49
|
+
var contentStart = start
|
|
50
|
+
if (padding > 0) {
|
|
51
|
+
builder.insert(start, "\n")
|
|
52
|
+
builder.setSpan(
|
|
53
|
+
BlockquotePaddingSpacerSpan(padding),
|
|
54
|
+
start,
|
|
55
|
+
start + 1,
|
|
56
|
+
SPAN_FLAGS_EXCLUSIVE_EXCLUSIVE,
|
|
57
|
+
)
|
|
58
|
+
contentStart = start + 1
|
|
59
|
+
end += 1
|
|
60
|
+
}
|
|
40
61
|
|
|
41
62
|
// Find immediately nested quotes to exclude them from this level's line-height/margins
|
|
42
63
|
val nestedRanges =
|
|
43
64
|
builder
|
|
44
|
-
.getSpans(
|
|
65
|
+
.getSpans(contentStart, end, BlockquoteSpan::class.java)
|
|
45
66
|
.filter { it.depth == depth + 1 }
|
|
46
67
|
.map { builder.getSpanStart(it) to builder.getSpanEnd(it) }
|
|
47
68
|
.sortedBy { it.first }
|
|
48
69
|
|
|
49
|
-
// The accent bar span covers the full
|
|
50
|
-
// SPAN_FLAGS_CONTAINER_BACKGROUND keeps the blockquote fill under any
|
|
51
|
-
// inline chip/pill backgrounds on the same line.
|
|
70
|
+
// The accent bar / background span covers the full box, incl. the top spacer.
|
|
52
71
|
builder.setSpan(
|
|
53
72
|
BlockquoteSpan(style, depth, factory.context, factory.styleCache),
|
|
54
73
|
start,
|
|
@@ -56,8 +75,16 @@ class BlockquoteRenderer(
|
|
|
56
75
|
SPAN_FLAGS_CONTAINER_BACKGROUND,
|
|
57
76
|
)
|
|
58
77
|
|
|
59
|
-
|
|
60
|
-
|
|
78
|
+
applyLineHeightExcludingNested(builder, nestedRanges, contentStart, end, style.lineHeight)
|
|
79
|
+
|
|
80
|
+
if (padding > 0) {
|
|
81
|
+
builder.setSpan(
|
|
82
|
+
BlockquoteBoundaryPaddingSpan(padding),
|
|
83
|
+
contentStart,
|
|
84
|
+
end,
|
|
85
|
+
SPAN_FLAGS_EXCLUSIVE_EXCLUSIVE,
|
|
86
|
+
)
|
|
87
|
+
}
|
|
61
88
|
|
|
62
89
|
// Margins are only applied by the outermost (root) quote
|
|
63
90
|
if (depth == 0) {
|
|
@@ -66,22 +93,83 @@ class BlockquoteRenderer(
|
|
|
66
93
|
}
|
|
67
94
|
}
|
|
68
95
|
|
|
69
|
-
|
|
96
|
+
/**
|
|
97
|
+
* A blockquote's top padding, rendered as a standalone spacer line of exactly
|
|
98
|
+
* [padding] px.
|
|
99
|
+
*
|
|
100
|
+
* Top padding cannot be added by growing the first content line's ascent:
|
|
101
|
+
* StaticLayout reuses one FontMetricsInt across a paragraph's soft-wrapped lines,
|
|
102
|
+
* so the inflated first-line metrics leak into the wrapped continuation line, where
|
|
103
|
+
* the line-height clamp then skews them into overlapping baselines. A spacer sits in
|
|
104
|
+
* its own paragraph, and setting absolute metrics keeps it fixed regardless of that
|
|
105
|
+
* reuse.
|
|
106
|
+
*/
|
|
107
|
+
private class BlockquotePaddingSpacerSpan(
|
|
108
|
+
private val padding: Int,
|
|
109
|
+
) : LineHeightSpan {
|
|
110
|
+
override fun chooseHeight(
|
|
111
|
+
text: CharSequence,
|
|
112
|
+
startLine: Int,
|
|
113
|
+
endLine: Int,
|
|
114
|
+
spanstartv: Int,
|
|
115
|
+
v: Int,
|
|
116
|
+
fm: Paint.FontMetricsInt,
|
|
117
|
+
) {
|
|
118
|
+
fm.top = 0
|
|
119
|
+
fm.ascent = 0
|
|
120
|
+
fm.descent = padding
|
|
121
|
+
fm.bottom = padding
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* A blockquote's bottom padding, grown onto the last content line's descent (safe
|
|
127
|
+
* because no later line inherits its metrics; top padding uses
|
|
128
|
+
* [BlockquotePaddingSpacerSpan]).
|
|
129
|
+
*
|
|
130
|
+
* The span range can include trailing '\n'(s) that form no visible line, so the last
|
|
131
|
+
* drawn line ends before getSpanEnd; the comparison uses the visible content end.
|
|
132
|
+
*/
|
|
133
|
+
private class BlockquoteBoundaryPaddingSpan(
|
|
134
|
+
private val padding: Int,
|
|
135
|
+
) : LineHeightSpan {
|
|
136
|
+
override fun chooseHeight(
|
|
137
|
+
text: CharSequence,
|
|
138
|
+
startLine: Int,
|
|
139
|
+
endLine: Int,
|
|
140
|
+
spanstartv: Int,
|
|
141
|
+
v: Int,
|
|
142
|
+
fm: Paint.FontMetricsInt,
|
|
143
|
+
) {
|
|
144
|
+
if (text !is Spanned) return
|
|
145
|
+
|
|
146
|
+
var contentEnd = text.getSpanEnd(this)
|
|
147
|
+
while (contentEnd > 0 && text[contentEnd - 1] == '\n') {
|
|
148
|
+
contentEnd--
|
|
149
|
+
}
|
|
150
|
+
if (endLine >= contentEnd) {
|
|
151
|
+
fm.descent += padding
|
|
152
|
+
fm.bottom += padding
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
private fun applyLineHeightExcludingNested(
|
|
70
158
|
builder: SpannableStringBuilder,
|
|
71
159
|
nestedRanges: List<Pair<Int, Int>>,
|
|
72
160
|
start: Int,
|
|
73
161
|
end: Int,
|
|
74
|
-
|
|
162
|
+
lineHeight: Float,
|
|
75
163
|
) {
|
|
76
164
|
var currentPos = start
|
|
77
165
|
for ((nestedStart, nestedEnd) in nestedRanges) {
|
|
78
166
|
if (currentPos < nestedStart) {
|
|
79
|
-
builder
|
|
167
|
+
applyLineHeightSkippingImages(builder, currentPos, nestedStart, lineHeight)
|
|
80
168
|
}
|
|
81
169
|
currentPos = nestedEnd
|
|
82
170
|
}
|
|
83
171
|
if (currentPos < end) {
|
|
84
|
-
builder
|
|
172
|
+
applyLineHeightSkippingImages(builder, currentPos, end, lineHeight)
|
|
85
173
|
}
|
|
86
174
|
}
|
|
87
175
|
}
|
|
@@ -7,6 +7,8 @@ import android.text.style.LineHeightSpan
|
|
|
7
7
|
import com.swmansion.enriched.markdown.parser.MarkdownASTNode
|
|
8
8
|
import com.swmansion.enriched.markdown.spans.CodeBlockSpan
|
|
9
9
|
import com.swmansion.enriched.markdown.spans.MarginBottomSpan
|
|
10
|
+
import com.swmansion.enriched.markdown.utils.common.CodeBlockHighlighter
|
|
11
|
+
import com.swmansion.enriched.markdown.utils.common.CodeBlockNode
|
|
10
12
|
import com.swmansion.enriched.markdown.utils.text.span.SPAN_FLAGS_EXCLUSIVE_EXCLUSIVE
|
|
11
13
|
import com.swmansion.enriched.markdown.utils.text.span.applyMarginTop
|
|
12
14
|
|
|
@@ -20,6 +22,10 @@ class CodeBlockRenderer(
|
|
|
20
22
|
onLinkLongPress: ((String) -> Unit)?,
|
|
21
23
|
factory: RendererFactory,
|
|
22
24
|
) {
|
|
25
|
+
if (builder.isNotEmpty() && builder.last() != '\n') {
|
|
26
|
+
builder.append("\n")
|
|
27
|
+
}
|
|
28
|
+
|
|
23
29
|
val start = builder.length
|
|
24
30
|
val style = config.style.codeBlockStyle
|
|
25
31
|
val context = factory.blockStyleContext
|
|
@@ -40,11 +46,20 @@ class CodeBlockRenderer(
|
|
|
40
46
|
if (builder.length == contentStart) return
|
|
41
47
|
|
|
42
48
|
val end = builder.length
|
|
49
|
+
|
|
50
|
+
CodeBlockHighlighter.highlight(
|
|
51
|
+
builder,
|
|
52
|
+
CodeBlockNode.extractCode(node),
|
|
53
|
+
CodeBlockNode.language(node),
|
|
54
|
+
style,
|
|
55
|
+
contentStart,
|
|
56
|
+
)
|
|
57
|
+
|
|
43
58
|
val padding = style.padding.toInt()
|
|
44
59
|
|
|
45
60
|
// Apply background, borders, and horizontal padding to content only
|
|
46
61
|
builder.setSpan(
|
|
47
|
-
CodeBlockSpan(style, factory.context, factory.styleCache),
|
|
62
|
+
CodeBlockSpan(style, factory.context, factory.styleCache, context.accumulatedIndent),
|
|
48
63
|
contentStart,
|
|
49
64
|
end,
|
|
50
65
|
SPAN_FLAGS_EXCLUSIVE_EXCLUSIVE,
|
|
@@ -19,6 +19,10 @@ class HeadingRenderer(
|
|
|
19
19
|
onLinkLongPress: ((String) -> Unit)?,
|
|
20
20
|
factory: RendererFactory,
|
|
21
21
|
) {
|
|
22
|
+
if (builder.isNotEmpty() && builder.last() != '\n') {
|
|
23
|
+
builder.append("\n")
|
|
24
|
+
}
|
|
25
|
+
|
|
22
26
|
val level = node.getAttribute("level")?.toIntOrNull() ?: 1
|
|
23
27
|
val start = builder.length
|
|
24
28
|
|
package/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListContextManager.kt
CHANGED
|
@@ -36,6 +36,7 @@ class ListContextManager(
|
|
|
36
36
|
fun enterList(
|
|
37
37
|
listType: BlockStyleContext.ListType,
|
|
38
38
|
style: ListStyle,
|
|
39
|
+
startNumber: Int = 1,
|
|
39
40
|
): ListEntryState {
|
|
40
41
|
val previousDepth = context.listDepth
|
|
41
42
|
val isNested = previousDepth > 0
|
|
@@ -58,7 +59,7 @@ class ListContextManager(
|
|
|
58
59
|
context.setUnorderedListStyle(style)
|
|
59
60
|
}
|
|
60
61
|
}
|
|
61
|
-
context.resetListItemNumber()
|
|
62
|
+
context.resetListItemNumber(startNumber)
|
|
62
63
|
|
|
63
64
|
return ListEntryState(
|
|
64
65
|
previousDepth = previousDepth,
|
|
@@ -5,6 +5,8 @@ import android.text.style.ForegroundColorSpan
|
|
|
5
5
|
import android.text.style.StrikethroughSpan
|
|
6
6
|
import com.swmansion.enriched.markdown.parser.MarkdownASTNode
|
|
7
7
|
import com.swmansion.enriched.markdown.spans.BaseListSpan
|
|
8
|
+
import com.swmansion.enriched.markdown.spans.CodeBlockSpan
|
|
9
|
+
import com.swmansion.enriched.markdown.spans.ListMarkerAnchorSpan
|
|
8
10
|
import com.swmansion.enriched.markdown.spans.OrderedListSpan
|
|
9
11
|
import com.swmansion.enriched.markdown.spans.TaskListSpan
|
|
10
12
|
import com.swmansion.enriched.markdown.spans.UnorderedListSpan
|
|
@@ -33,19 +35,10 @@ class ListItemRenderer(
|
|
|
33
35
|
|
|
34
36
|
val taskIndex = if (isTask) styleContext.taskItemCount++ else -1
|
|
35
37
|
|
|
36
|
-
factory.renderChildren(node, builder, onLinkPress, onLinkLongPress)
|
|
37
|
-
|
|
38
|
-
if (builder.length == start || builder.substring(start).isBlank()) return
|
|
39
|
-
|
|
40
|
-
while (builder.length > start && builder.last() == '\n') {
|
|
41
|
-
builder.delete(builder.length - 1, builder.length)
|
|
42
|
-
}
|
|
43
|
-
builder.append("\n")
|
|
44
|
-
|
|
45
38
|
val depth = styleContext.listDepth - 1
|
|
46
39
|
val listStyle = config.style.listStyle
|
|
47
|
-
|
|
48
|
-
|
|
40
|
+
|
|
41
|
+
fun makeSpan(drawsMarker: Boolean): BaseListSpan =
|
|
49
42
|
if (isTask) {
|
|
50
43
|
TaskListSpan(
|
|
51
44
|
taskStyle = config.style.taskListStyle,
|
|
@@ -55,22 +48,85 @@ class ListItemRenderer(
|
|
|
55
48
|
styleCache = factory.styleCache,
|
|
56
49
|
taskIndex = taskIndex,
|
|
57
50
|
isChecked = isChecked,
|
|
51
|
+
drawsMarker = drawsMarker,
|
|
58
52
|
)
|
|
59
53
|
} else {
|
|
60
54
|
when (listType) {
|
|
61
55
|
BlockStyleContext.ListType.UNORDERED -> {
|
|
62
|
-
UnorderedListSpan(listStyle, depth, factory.context, factory.styleCache)
|
|
56
|
+
UnorderedListSpan(listStyle, depth, factory.context, factory.styleCache, drawsMarker)
|
|
63
57
|
}
|
|
64
58
|
|
|
65
59
|
BlockStyleContext.ListType.ORDERED -> {
|
|
66
|
-
OrderedListSpan(listStyle, depth, factory.context, factory.styleCache).apply {
|
|
60
|
+
OrderedListSpan(listStyle, depth, factory.context, factory.styleCache, drawsMarker).apply {
|
|
67
61
|
setItemNumber(styleContext.listItemNumber)
|
|
68
62
|
}
|
|
69
63
|
}
|
|
70
64
|
}
|
|
71
65
|
}
|
|
72
66
|
|
|
73
|
-
|
|
67
|
+
val markerSpan = makeSpan(drawsMarker = true)
|
|
68
|
+
|
|
69
|
+
val prevIndent = styleContext.accumulatedIndent
|
|
70
|
+
styleContext.accumulatedIndent = prevIndent + markerSpan.getLeadingMargin(false)
|
|
71
|
+
try {
|
|
72
|
+
factory.renderChildren(node, builder, onLinkPress, onLinkLongPress)
|
|
73
|
+
} finally {
|
|
74
|
+
styleContext.accumulatedIndent = prevIndent
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (builder.length == start || builder.substring(start).isBlank()) return
|
|
78
|
+
|
|
79
|
+
styleContext.listItemStarts.add(start)
|
|
80
|
+
|
|
81
|
+
if (builder.last() != '\n') {
|
|
82
|
+
builder.append("\n")
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
val itemEnd = builder.length
|
|
86
|
+
|
|
87
|
+
// Anchor the marker on the first content character so items that open with
|
|
88
|
+
// a code block or nested sublist still get their marker.
|
|
89
|
+
var anchor = start
|
|
90
|
+
while (anchor < itemEnd && builder[anchor].isWhitespace()) anchor++
|
|
91
|
+
if (anchor == itemEnd) anchor = start
|
|
92
|
+
|
|
93
|
+
val plainAnchor =
|
|
94
|
+
builder.getSpans(anchor, anchor + 1, CodeBlockSpan::class.java).isEmpty() &&
|
|
95
|
+
builder.getSpans(anchor, anchor + 1, BaseListSpan::class.java).none { it.depth > depth }
|
|
96
|
+
|
|
97
|
+
val codeBlockRanges =
|
|
98
|
+
builder
|
|
99
|
+
.getSpans(start, itemEnd, CodeBlockSpan::class.java)
|
|
100
|
+
.map { builder.getSpanStart(it) to builder.getSpanEnd(it) }
|
|
101
|
+
.filter { it.first < it.second }
|
|
102
|
+
.sortedBy { it.first }
|
|
103
|
+
|
|
104
|
+
var pos = start
|
|
105
|
+
var isFirstSegment = true
|
|
106
|
+
for ((cbStart, cbEnd) in codeBlockRanges) {
|
|
107
|
+
if (pos < cbStart) {
|
|
108
|
+
builder.setSpan(
|
|
109
|
+
if (isFirstSegment && plainAnchor) markerSpan else makeSpan(drawsMarker = false),
|
|
110
|
+
pos,
|
|
111
|
+
cbStart,
|
|
112
|
+
SPAN_FLAGS_EXCLUSIVE_EXCLUSIVE,
|
|
113
|
+
)
|
|
114
|
+
isFirstSegment = false
|
|
115
|
+
}
|
|
116
|
+
pos = maxOf(pos, cbEnd)
|
|
117
|
+
}
|
|
118
|
+
if (pos < itemEnd) {
|
|
119
|
+
builder.setSpan(
|
|
120
|
+
if (isFirstSegment && plainAnchor) markerSpan else makeSpan(drawsMarker = false),
|
|
121
|
+
pos,
|
|
122
|
+
itemEnd,
|
|
123
|
+
SPAN_FLAGS_EXCLUSIVE_EXCLUSIVE,
|
|
124
|
+
)
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (!plainAnchor) {
|
|
128
|
+
builder.setSpan(ListMarkerAnchorSpan(markerSpan), anchor, anchor + 1, SPAN_FLAGS_EXCLUSIVE_EXCLUSIVE)
|
|
129
|
+
}
|
|
74
130
|
|
|
75
131
|
if (isTask && isChecked) {
|
|
76
132
|
applyCheckedDecorations(builder, start, itemEnd, depth)
|
|
@@ -90,10 +146,10 @@ class ListItemRenderer(
|
|
|
90
146
|
if (checkedTextColor == 0 && !strikethrough) return
|
|
91
147
|
|
|
92
148
|
val excludedRanges =
|
|
93
|
-
|
|
94
|
-
.getSpans(itemStart, itemEnd, BaseListSpan::class.java)
|
|
95
|
-
|
|
96
|
-
|
|
149
|
+
(
|
|
150
|
+
builder.getSpans(itemStart, itemEnd, BaseListSpan::class.java).filter { it.depth > itemDepth } +
|
|
151
|
+
builder.getSpans(itemStart, itemEnd, CodeBlockSpan::class.java).toList()
|
|
152
|
+
).map { builder.getSpanStart(it) to builder.getSpanEnd(it) }
|
|
97
153
|
.sortedBy { it.first }
|
|
98
154
|
|
|
99
155
|
var currentPos = itemStart
|
|
@@ -2,7 +2,9 @@ package com.swmansion.enriched.markdown.renderer
|
|
|
2
2
|
|
|
3
3
|
import android.text.SpannableStringBuilder
|
|
4
4
|
import com.swmansion.enriched.markdown.parser.MarkdownASTNode
|
|
5
|
+
import com.swmansion.enriched.markdown.spans.ListItemSpacingSpan
|
|
5
6
|
import com.swmansion.enriched.markdown.spans.MarginBottomSpan
|
|
7
|
+
import com.swmansion.enriched.markdown.styles.ListStyle
|
|
6
8
|
import com.swmansion.enriched.markdown.utils.text.span.SPAN_FLAGS_EXCLUSIVE_EXCLUSIVE
|
|
7
9
|
import com.swmansion.enriched.markdown.utils.text.span.applyLineHeightSkippingImages
|
|
8
10
|
import com.swmansion.enriched.markdown.utils.text.span.applyMarginTop
|
|
@@ -22,8 +24,15 @@ class ListRenderer(
|
|
|
22
24
|
val listStyle = config.style.listStyle
|
|
23
25
|
val listType = if (isOrdered) BlockStyleContext.ListType.ORDERED else BlockStyleContext.ListType.UNORDERED
|
|
24
26
|
|
|
27
|
+
val startNumber =
|
|
28
|
+
if (isOrdered) {
|
|
29
|
+
node.getAttribute("start")?.toIntOrNull()?.coerceAtLeast(0) ?: 1
|
|
30
|
+
} else {
|
|
31
|
+
1
|
|
32
|
+
}
|
|
33
|
+
|
|
25
34
|
val contextManager = ListContextManager(factory.blockStyleContext)
|
|
26
|
-
val entryState = contextManager.enterList(listType, listStyle)
|
|
35
|
+
val entryState = contextManager.enterList(listType, listStyle, startNumber)
|
|
27
36
|
|
|
28
37
|
// For top-level lists, insert marginTop spacer before rendering content
|
|
29
38
|
if (entryState.previousDepth == 0) {
|
|
@@ -45,7 +54,7 @@ class ListRenderer(
|
|
|
45
54
|
}
|
|
46
55
|
|
|
47
56
|
if (builder.length > contentStart) {
|
|
48
|
-
applyListSpacing(builder, contentStart, entryState.previousDepth, listStyle)
|
|
57
|
+
applyListSpacing(builder, contentStart, entryState.previousDepth, listStyle, factory.blockStyleContext)
|
|
49
58
|
}
|
|
50
59
|
}
|
|
51
60
|
|
|
@@ -53,15 +62,18 @@ class ListRenderer(
|
|
|
53
62
|
builder: SpannableStringBuilder,
|
|
54
63
|
start: Int,
|
|
55
64
|
depth: Int,
|
|
56
|
-
style:
|
|
65
|
+
style: ListStyle,
|
|
66
|
+
styleContext: BlockStyleContext,
|
|
57
67
|
) {
|
|
58
68
|
// TODO: LineHeightSpan may also clip superscript/subscript glyphs that extend
|
|
59
69
|
// outside the normal line bounds. A similar "skip" strategy as for images may
|
|
60
70
|
// be needed here once super/subscript usage in practice is better understood.
|
|
61
71
|
applyLineHeightSkippingImages(builder, start, builder.length, style.lineHeight)
|
|
62
72
|
|
|
63
|
-
//
|
|
73
|
+
// Item spacing and external bottom margin are only handled by the root-level list
|
|
64
74
|
if (depth == 0) {
|
|
75
|
+
applyItemSpacing(builder, start, style.itemSpacing, styleContext)
|
|
76
|
+
|
|
65
77
|
builder.append("\n")
|
|
66
78
|
builder.setSpan(
|
|
67
79
|
MarginBottomSpan(style.marginBottom),
|
|
@@ -71,4 +83,31 @@ class ListRenderer(
|
|
|
71
83
|
)
|
|
72
84
|
}
|
|
73
85
|
}
|
|
86
|
+
|
|
87
|
+
// Inserts the vertical gap between consecutive items (including nested ones)
|
|
88
|
+
// by spanning the newline that precedes each item start. The first item of
|
|
89
|
+
// the root list gets no spacing above it.
|
|
90
|
+
private fun applyItemSpacing(
|
|
91
|
+
builder: SpannableStringBuilder,
|
|
92
|
+
start: Int,
|
|
93
|
+
itemSpacing: Float,
|
|
94
|
+
styleContext: BlockStyleContext,
|
|
95
|
+
) {
|
|
96
|
+
if (itemSpacing <= 0f) return
|
|
97
|
+
|
|
98
|
+
val itemStarts =
|
|
99
|
+
styleContext.listItemStarts
|
|
100
|
+
.filter { it in start until builder.length }
|
|
101
|
+
.distinct()
|
|
102
|
+
.sorted()
|
|
103
|
+
|
|
104
|
+
for (itemStart in itemStarts.drop(1)) {
|
|
105
|
+
builder.setSpan(
|
|
106
|
+
ListItemSpacingSpan(itemSpacing),
|
|
107
|
+
itemStart - 1,
|
|
108
|
+
itemStart,
|
|
109
|
+
SPAN_FLAGS_EXCLUSIVE_EXCLUSIVE,
|
|
110
|
+
)
|
|
111
|
+
}
|
|
112
|
+
}
|
|
74
113
|
}
|