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/layout/InputEventEmitter.kt
CHANGED
|
@@ -14,12 +14,15 @@ import com.swmansion.enriched.markdown.input.events.OnContextMenuItemPressEvent
|
|
|
14
14
|
import com.swmansion.enriched.markdown.input.events.OnEndMentionEvent
|
|
15
15
|
import com.swmansion.enriched.markdown.input.events.OnInputBlurEvent
|
|
16
16
|
import com.swmansion.enriched.markdown.input.events.OnInputFocusEvent
|
|
17
|
+
import com.swmansion.enriched.markdown.input.events.OnInputKeyPressEvent
|
|
17
18
|
import com.swmansion.enriched.markdown.input.events.OnLinkDetectedEvent
|
|
18
19
|
import com.swmansion.enriched.markdown.input.events.OnMathPressEvent
|
|
20
|
+
import com.swmansion.enriched.markdown.input.events.OnPasteEvent
|
|
19
21
|
import com.swmansion.enriched.markdown.input.events.OnRequestCaretRectResultEvent
|
|
20
22
|
import com.swmansion.enriched.markdown.input.events.OnRequestMarkdownResultEvent
|
|
21
23
|
import com.swmansion.enriched.markdown.input.events.OnStartMentionEvent
|
|
22
24
|
import com.swmansion.enriched.markdown.input.formatting.MarkdownSerializer
|
|
25
|
+
import com.swmansion.enriched.markdown.input.model.BlockType
|
|
23
26
|
import com.swmansion.enriched.markdown.input.model.CaretRect
|
|
24
27
|
import com.swmansion.enriched.markdown.input.model.StyleType
|
|
25
28
|
|
|
@@ -27,10 +30,25 @@ class InputEventEmitter(
|
|
|
27
30
|
private val view: EnrichedMarkdownTextInputView,
|
|
28
31
|
) {
|
|
29
32
|
private var prevState: Map<StyleType, Boolean> = emptyMap()
|
|
33
|
+
private var prevHeadingLevel: Int = 0
|
|
34
|
+
private var prevUnorderedList: Pair<Boolean, Int> = false to 0
|
|
35
|
+
private var prevOrderedList: Pair<Boolean, Int> = false to 0
|
|
30
36
|
private var prevCaretRect: CaretRect? = null
|
|
31
37
|
|
|
32
38
|
fun emitChangeText() {
|
|
33
|
-
|
|
39
|
+
// The empty-list-line ZWSP anchor is an internal editing detail — never leak
|
|
40
|
+
// it to JS. Both output paths (plain text here, markdown) funnel through the
|
|
41
|
+
// same MarkdownSerializer.stripZwsp choke point.
|
|
42
|
+
//
|
|
43
|
+
// A math chip's U+FFFC placeholder is deliberately NOT stripped, and expanding it
|
|
44
|
+
// to `$latex$` here would be worse. This string has to stay index-compatible with
|
|
45
|
+
// the buffer: onChangeSelection, onChangeCaretRect and insertMath/updateMath/
|
|
46
|
+
// removeMath all speak buffer offsets, where a chip is exactly one character.
|
|
47
|
+
// Strip or expand it and every offset JS holds points at the wrong place. iOS
|
|
48
|
+
// lands in the same spot for free (an NSTextAttachment *is* U+FFFC in the string),
|
|
49
|
+
// so keeping it is also what makes the two platforms agree. Documented in
|
|
50
|
+
// docs/API_REFERENCE.md under onChangeText.
|
|
51
|
+
val plainText = MarkdownSerializer.stripZwsp(view.text?.toString() ?: "")
|
|
34
52
|
dispatch(OnChangeTextEvent(surfaceId(), view.id, plainText))
|
|
35
53
|
}
|
|
36
54
|
|
|
@@ -51,9 +69,19 @@ class InputEventEmitter(
|
|
|
51
69
|
StyleType.entries.associateWith { style ->
|
|
52
70
|
isStyleEffectivelyActive(style, pos)
|
|
53
71
|
}
|
|
72
|
+
val headingLevel = view.headingLevelAtCursor()
|
|
73
|
+
val unorderedList = view.listStateAtCursor(BlockType.UNORDERED_LIST_ITEM)
|
|
74
|
+
val orderedList = view.listStateAtCursor(BlockType.ORDERED_LIST_ITEM)
|
|
54
75
|
|
|
55
|
-
if (current == prevState
|
|
76
|
+
if (current == prevState && headingLevel == prevHeadingLevel && unorderedList == prevUnorderedList &&
|
|
77
|
+
orderedList == prevOrderedList
|
|
78
|
+
) {
|
|
79
|
+
return
|
|
80
|
+
}
|
|
56
81
|
prevState = current
|
|
82
|
+
prevHeadingLevel = headingLevel
|
|
83
|
+
prevUnorderedList = unorderedList
|
|
84
|
+
prevOrderedList = orderedList
|
|
57
85
|
|
|
58
86
|
dispatch(
|
|
59
87
|
OnChangeStateEvent(
|
|
@@ -65,10 +93,19 @@ class InputEventEmitter(
|
|
|
65
93
|
current[StyleType.STRIKETHROUGH] ?: false,
|
|
66
94
|
current[StyleType.SPOILER] ?: false,
|
|
67
95
|
current[StyleType.LINK] ?: false,
|
|
96
|
+
headingLevel,
|
|
97
|
+
unorderedList.first,
|
|
98
|
+
unorderedList.second,
|
|
99
|
+
orderedList.first,
|
|
100
|
+
orderedList.second,
|
|
68
101
|
),
|
|
69
102
|
)
|
|
70
103
|
}
|
|
71
104
|
|
|
105
|
+
fun emitKeyPress(key: String) {
|
|
106
|
+
dispatch(OnInputKeyPressEvent(surfaceId(), view.id, key))
|
|
107
|
+
}
|
|
108
|
+
|
|
72
109
|
fun emitFocus() {
|
|
73
110
|
dispatch(OnInputFocusEvent(surfaceId(), view.id))
|
|
74
111
|
}
|
|
@@ -99,6 +136,13 @@ class InputEventEmitter(
|
|
|
99
136
|
dispatch(OnMathPressEvent(surfaceId(), view.id, latex, start, end, displayMode, x, y, width, height))
|
|
100
137
|
}
|
|
101
138
|
|
|
139
|
+
fun emitPaste(
|
|
140
|
+
text: String,
|
|
141
|
+
markdown: String,
|
|
142
|
+
) {
|
|
143
|
+
dispatch(OnPasteEvent(surfaceId(), view.id, text, markdown))
|
|
144
|
+
}
|
|
145
|
+
|
|
102
146
|
fun emitStartMention(indicator: String) {
|
|
103
147
|
dispatch(OnStartMentionEvent(surfaceId(), view.id, indicator))
|
|
104
148
|
}
|
|
@@ -169,6 +213,8 @@ class InputEventEmitter(
|
|
|
169
213
|
isStyleEffectivelyActive(type, selectionStart)
|
|
170
214
|
}
|
|
171
215
|
|
|
216
|
+
val contextMenuListState = view.listStateAtCursor(BlockType.UNORDERED_LIST_ITEM)
|
|
217
|
+
val contextMenuOrderedState = view.listStateAtCursor(BlockType.ORDERED_LIST_ITEM)
|
|
172
218
|
dispatch(
|
|
173
219
|
OnContextMenuItemPressEvent(
|
|
174
220
|
surfaceId(),
|
|
@@ -183,6 +229,11 @@ class InputEventEmitter(
|
|
|
183
229
|
isStrikethrough = isActive(StyleType.STRIKETHROUGH),
|
|
184
230
|
isSpoiler = isActive(StyleType.SPOILER),
|
|
185
231
|
isLink = isActive(StyleType.LINK),
|
|
232
|
+
headingLevel = view.headingLevelAtCursor(),
|
|
233
|
+
isUnorderedList = contextMenuListState.first,
|
|
234
|
+
unorderedListDepth = contextMenuListState.second,
|
|
235
|
+
isOrderedList = contextMenuOrderedState.first,
|
|
236
|
+
orderedListDepth = contextMenuOrderedState.second,
|
|
186
237
|
),
|
|
187
238
|
)
|
|
188
239
|
}
|
|
@@ -198,8 +249,18 @@ class InputEventEmitter(
|
|
|
198
249
|
)
|
|
199
250
|
|
|
200
251
|
private fun serializeToMarkdown(): String {
|
|
201
|
-
val
|
|
202
|
-
|
|
252
|
+
val plainText = view.text?.toString() ?: ""
|
|
253
|
+
// Each block resolves its markdown line prefix through its registered handler.
|
|
254
|
+
// With no block handlers registered the provider returns "" for every block
|
|
255
|
+
// and output equals the inline-only serialization.
|
|
256
|
+
return MarkdownSerializer.serialize(
|
|
257
|
+
plainText,
|
|
258
|
+
view.mathChipsForSerialization(),
|
|
259
|
+
view.allFormattingRangesForSerialization(),
|
|
260
|
+
view.blockStore.allRanges,
|
|
261
|
+
) { blockRange ->
|
|
262
|
+
view.formatter.handlerForBlock(blockRange.type)?.markdownLinePrefix(blockRange) ?: ""
|
|
263
|
+
}
|
|
203
264
|
}
|
|
204
265
|
|
|
205
266
|
private fun surfaceId(): Int {
|
|
@@ -208,7 +269,7 @@ class InputEventEmitter(
|
|
|
208
269
|
}
|
|
209
270
|
|
|
210
271
|
private fun dispatch(event: Event<*>) {
|
|
211
|
-
if (view.
|
|
272
|
+
if (view.editSession.shouldSuppressEvents) return
|
|
212
273
|
val reactContext = view.context as? ReactContext ?: return
|
|
213
274
|
val dispatcher = UIManagerHelper.getEventDispatcherForReactTag(reactContext, view.id)
|
|
214
275
|
dispatcher?.dispatchEvent(event)
|
package/android/src/main/java/com/swmansion/enriched/markdown/input/layout/InputMeasurementStore.kt
CHANGED
|
@@ -10,6 +10,8 @@ import com.facebook.react.uimanager.PixelUtil
|
|
|
10
10
|
import com.facebook.yoga.YogaMeasureMode
|
|
11
11
|
import com.facebook.yoga.YogaMeasureOutput
|
|
12
12
|
import com.swmansion.enriched.markdown.input.formatting.InputParser
|
|
13
|
+
import com.swmansion.enriched.markdown.utils.common.getBooleanOrDefault
|
|
14
|
+
import com.swmansion.enriched.markdown.utils.common.getFloatOrDefault
|
|
13
15
|
import java.util.concurrent.ConcurrentHashMap
|
|
14
16
|
|
|
15
17
|
object InputMeasurementStore {
|
|
@@ -101,9 +103,9 @@ object InputMeasurementStore {
|
|
|
101
103
|
val markdown = props?.getString("defaultValue") ?: props?.getString("placeholder") ?: "I"
|
|
102
104
|
// Must read the same flag the view parses with, or the measured height and the
|
|
103
105
|
// rendered height disagree: `blockSyntax = false` keeps list markers and `#` as text.
|
|
104
|
-
val blockSyntax =
|
|
106
|
+
val blockSyntax = props.getBooleanOrDefault("blockSyntax", true)
|
|
105
107
|
val text = InputParser.parseToPlainTextAndRanges(markdown, blockSyntax).plainText
|
|
106
|
-
val fontSize = props
|
|
108
|
+
val fontSize = props.getFloatOrDefault("fontSize", 16f)
|
|
107
109
|
val spSize = kotlin.math.ceil(PixelUtil.toPixelFromSP(fontSize).toDouble()).toFloat()
|
|
108
110
|
|
|
109
111
|
val defaultView = AppCompatEditText(context)
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
package com.swmansion.enriched.markdown.input.model
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* A block-level element occupying a paragraph/line range. Mirrors [FormattingRange]
|
|
5
|
+
* but for block scope: the range always covers whole lines.
|
|
6
|
+
*
|
|
7
|
+
* Deliberately NOT a data class: [start]/[end] mutate as edits shift ranges, so
|
|
8
|
+
* value-based equals/hashCode would silently break set/map lookups. Identity
|
|
9
|
+
* semantics are the safe default for a mutable model.
|
|
10
|
+
*
|
|
11
|
+
* @property type the block kind (PARAGRAPH is the implicit default).
|
|
12
|
+
* @property start inclusive start offset, in plain-text characters.
|
|
13
|
+
* @property end exclusive end offset, in plain-text characters.
|
|
14
|
+
* @property level generic integer payload, 0 by default. Headings use it for the
|
|
15
|
+
* H-level (1-6); list items use it for nesting depth.
|
|
16
|
+
* @property ordinal 1-based position of an ordered list item among its adjacent
|
|
17
|
+
* siblings at the same depth; recomputed by the store's list-metadata pass.
|
|
18
|
+
*/
|
|
19
|
+
class BlockRange(
|
|
20
|
+
val type: BlockType,
|
|
21
|
+
override var start: Int,
|
|
22
|
+
override var end: Int,
|
|
23
|
+
var level: Int = 0,
|
|
24
|
+
var ordinal: Int = 1,
|
|
25
|
+
) : MutableRangeBounds {
|
|
26
|
+
val length: Int get() = end - start
|
|
27
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
package com.swmansion.enriched.markdown.input.model
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Block-level (paragraph-scoped) element types. A block covers whole lines,
|
|
5
|
+
* unlike inline styles ([StyleType]) which cover character ranges.
|
|
6
|
+
*
|
|
7
|
+
* PARAGRAPH is the default: every line is a paragraph until a block handler
|
|
8
|
+
* claims it. Concrete block types (headings, list items, etc.) are appended
|
|
9
|
+
* here as their handlers are added — each new case must have a matching
|
|
10
|
+
* [com.swmansion.enriched.markdown.input.styles.BlockHandler] registered in
|
|
11
|
+
* [com.swmansion.enriched.markdown.input.formatting.InputFormatter].
|
|
12
|
+
*/
|
|
13
|
+
enum class BlockType {
|
|
14
|
+
PARAGRAPH,
|
|
15
|
+
HEADING_1,
|
|
16
|
+
HEADING_2,
|
|
17
|
+
HEADING_3,
|
|
18
|
+
HEADING_4,
|
|
19
|
+
HEADING_5,
|
|
20
|
+
HEADING_6,
|
|
21
|
+
UNORDERED_LIST_ITEM,
|
|
22
|
+
ORDERED_LIST_ITEM,
|
|
23
|
+
;
|
|
24
|
+
|
|
25
|
+
companion object {
|
|
26
|
+
/** The six heading block types, indexable by level via [forHeadingLevel]. */
|
|
27
|
+
val HEADINGS: List<BlockType> =
|
|
28
|
+
listOf(HEADING_1, HEADING_2, HEADING_3, HEADING_4, HEADING_5, HEADING_6)
|
|
29
|
+
|
|
30
|
+
/** List-item block types; nesting depth rides in the range's level payload. */
|
|
31
|
+
val LIST_ITEMS: Set<BlockType> = setOf(UNORDERED_LIST_ITEM, ORDERED_LIST_ITEM)
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Block types whose emptied line persists as a zero-length anchor (an emptied
|
|
35
|
+
* heading stays a heading, an emptied list item keeps its marker) until toggled off.
|
|
36
|
+
*/
|
|
37
|
+
val ANCHORED: Set<BlockType> = HEADINGS.toSet() + LIST_ITEMS
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Maps an H-level (1-6) to its [BlockType], or null when out of range. Used by
|
|
41
|
+
* the parser to turn an AST heading node's `level` attribute into a block type.
|
|
42
|
+
*/
|
|
43
|
+
fun forHeadingLevel(level: Int): BlockType? = HEADINGS.getOrNull(level - 1)
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** Maximum bullet-list nesting depth (0-based), so indent can't run away unbounded. */
|
|
48
|
+
const val MAX_LIST_DEPTH = 5
|
package/android/src/main/java/com/swmansion/enriched/markdown/input/model/FormattingRange.kt
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
package com.swmansion.enriched.markdown.input.model
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Deliberately NOT a data class: [start]/[end] mutate as edits shift ranges, so
|
|
5
|
+
* value-based equals/hashCode would silently break set/map lookups. Identity
|
|
6
|
+
* semantics are the safe default for a mutable model.
|
|
7
|
+
*/
|
|
8
|
+
class FormattingRange(
|
|
4
9
|
val type: StyleType,
|
|
5
|
-
var start: Int,
|
|
6
|
-
var end: Int,
|
|
10
|
+
override var start: Int,
|
|
11
|
+
override var end: Int,
|
|
7
12
|
var url: String? = null,
|
|
8
|
-
) {
|
|
13
|
+
) : MutableRangeBounds {
|
|
9
14
|
val length: Int get() = end - start
|
|
10
15
|
}
|
package/android/src/main/java/com/swmansion/enriched/markdown/input/model/InputFormatterStyle.kt
CHANGED
|
@@ -9,8 +9,45 @@ data class InputFormatterStyle(
|
|
|
9
9
|
val linkVariants: List<InputLinkVariantStyle>,
|
|
10
10
|
val spoilerColor: Int,
|
|
11
11
|
val spoilerBackgroundColor: Int,
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
/**
|
|
13
|
+
* Inline chip style (`markdownStyle.inlineMath`). NOTE for anyone porting
|
|
14
|
+
* pre-rename fork code: this used to be called `math`. The field now named
|
|
15
|
+
* `math` is the **block** style — the two swapped meaning, and both are
|
|
16
|
+
* chip styles, so a stale read compiles clean and styles the wrong chip.
|
|
17
|
+
*/
|
|
18
|
+
val inlineMath: MathChipStyle,
|
|
19
|
+
/** Block chip style (`markdownStyle.math`). Narrowed to [MathBlockStyle] so
|
|
20
|
+
* passing the inline style where block fields are needed is a compile error. */
|
|
21
|
+
val math: MathBlockStyle,
|
|
22
|
+
/** Per-level heading styling, indexed 0..5 for H1..H6. Always length 6. */
|
|
23
|
+
val headings: List<InputHeadingStyle>,
|
|
24
|
+
/**
|
|
25
|
+
* Extra vertical spacing (dp) above each list item, from `markdownStyle.list.itemSpacing`.
|
|
26
|
+
* Kept in dp (not px) so this stays a pure style value; the list block handlers convert
|
|
27
|
+
* to px with the display density they hold.
|
|
28
|
+
*/
|
|
29
|
+
val listItemSpacing: Float = 0f,
|
|
30
|
+
) {
|
|
31
|
+
/**
|
|
32
|
+
* Resolves the heading style for an H-level (1-6), clamping out-of-range levels
|
|
33
|
+
* to the nearest valid level so a malformed parse can never crash the formatter.
|
|
34
|
+
*/
|
|
35
|
+
fun headingStyle(level: Int): InputHeadingStyle = headings[(level - 1).coerceIn(0, headings.size - 1)]
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Resolved per-level heading style for the input editor.
|
|
40
|
+
*
|
|
41
|
+
* @property fontSizePx font size in pixels (already converted from the SP prop),
|
|
42
|
+
* or null to leave the base text size unchanged.
|
|
43
|
+
* @property fontWeight parsed font weight (e.g. [android.graphics.Typeface.BOLD]),
|
|
44
|
+
* or [com.facebook.react.common.ReactConstants.UNSET] when unspecified.
|
|
45
|
+
* @property color text color, or null to keep the editor's default color.
|
|
46
|
+
*/
|
|
47
|
+
data class InputHeadingStyle(
|
|
48
|
+
val fontSizePx: Float?,
|
|
49
|
+
val fontWeight: Int,
|
|
50
|
+
val color: Int?,
|
|
14
51
|
)
|
|
15
52
|
|
|
16
53
|
data class InputLinkVariantStyle(
|
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
package com.swmansion.enriched.markdown.input.model
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* U+FFFC OBJECT REPLACEMENT CHARACTER — the one character a math chip occupies in
|
|
5
|
+
* the editor's plain text. Everything about a formula (its LaTeX, its display mode)
|
|
6
|
+
* lives on the span, never in the buffer, so the chip stays atomic for the caret,
|
|
7
|
+
* the IME and every range in the stores.
|
|
8
|
+
*
|
|
9
|
+
* Single source of truth on purpose: the parser writes it, the serializer expands
|
|
10
|
+
* it back to `$…$`, and the view inserts it. A second copy of this literal is a
|
|
11
|
+
* silent round-trip break waiting to happen.
|
|
12
|
+
*/
|
|
13
|
+
const val OBJECT_REPLACEMENT: Char = ''
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* A math formula parsed out of markdown, ready to be turned into a chip span.
|
|
17
|
+
*
|
|
18
|
+
* @property position offset of the [OBJECT_REPLACEMENT] placeholder in the parsed
|
|
19
|
+
* plain text.
|
|
20
|
+
* @property latex the formula source, without its `$`/`$$` delimiters.
|
|
21
|
+
* @property displayMode true for `$$…$$` (block chip), false for `$…$` (inline chip).
|
|
22
|
+
*/
|
|
3
23
|
data class MathAtom(
|
|
4
24
|
val position: Int,
|
|
5
25
|
val latex: String,
|
package/android/src/main/java/com/swmansion/enriched/markdown/input/model/MutableRangeBounds.kt
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
package com.swmansion.enriched.markdown.input.model
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Mutable `[start, end)` character bounds shared by the stored range models so
|
|
5
|
+
* [com.swmansion.enriched.markdown.input.formatting.RangeEditAdjustment] can
|
|
6
|
+
* shift/clip any range kind after a text edit.
|
|
7
|
+
*/
|
|
8
|
+
interface MutableRangeBounds {
|
|
9
|
+
var start: Int
|
|
10
|
+
var end: Int
|
|
11
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
package com.swmansion.enriched.markdown.input.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
|
+
import com.swmansion.enriched.markdown.input.formatting.MarkdownSpan
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Bullet list item span: reserves a per-depth leading margin and draws the marker
|
|
12
|
+
* glyph (dot / ring / square, capped at square for depth 2+) on the item's first line.
|
|
13
|
+
* Mirrors the readonly renderer's bullet. Tagged [MarkdownSpan] for formatter
|
|
14
|
+
* cleanup.
|
|
15
|
+
*/
|
|
16
|
+
class InputBulletSpan(
|
|
17
|
+
val depth: Int,
|
|
18
|
+
density: Float,
|
|
19
|
+
) : LeadingMarginSpan,
|
|
20
|
+
MarkdownSpan {
|
|
21
|
+
private val indentPerDepth = INDENT_PER_DEPTH_DP * density
|
|
22
|
+
private val markerWidth = MARKER_WIDTH_DP * density
|
|
23
|
+
|
|
24
|
+
override fun getLeadingMargin(first: Boolean): Int = (depth * indentPerDepth + markerWidth).toInt()
|
|
25
|
+
|
|
26
|
+
override fun drawLeadingMargin(
|
|
27
|
+
canvas: Canvas,
|
|
28
|
+
paint: Paint,
|
|
29
|
+
x: Int,
|
|
30
|
+
dir: Int,
|
|
31
|
+
top: Int,
|
|
32
|
+
baseline: Int,
|
|
33
|
+
bottom: Int,
|
|
34
|
+
text: CharSequence?,
|
|
35
|
+
start: Int,
|
|
36
|
+
end: Int,
|
|
37
|
+
first: Boolean,
|
|
38
|
+
layout: Layout?,
|
|
39
|
+
) {
|
|
40
|
+
if (!first) return
|
|
41
|
+
// Wrapped continuation lines also report first=true; draw only on the visual
|
|
42
|
+
// line where this span actually begins.
|
|
43
|
+
if (text is Spanned && text.getSpanStart(this) != start) return
|
|
44
|
+
|
|
45
|
+
// Bullet size tracks the text size (~30%), with a small floor so it stays visible.
|
|
46
|
+
val size = (paint.textSize * BULLET_SIZE_RATIO).coerceAtLeast(MIN_BULLET_PX)
|
|
47
|
+
val radius = size / 2f
|
|
48
|
+
val centerX = x + (depth * indentPerDepth + markerWidth * 0.5f) * dir
|
|
49
|
+
val fm = paint.fontMetrics
|
|
50
|
+
val centerY = baseline + (fm.ascent + fm.descent) / 2f
|
|
51
|
+
|
|
52
|
+
val originalStyle = paint.style
|
|
53
|
+
val originalStrokeWidth = paint.strokeWidth
|
|
54
|
+
when (if (depth >= 2) 2 else depth) {
|
|
55
|
+
0 -> {
|
|
56
|
+
paint.style = Paint.Style.FILL
|
|
57
|
+
canvas.drawCircle(centerX, centerY, radius, paint)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
1 -> {
|
|
61
|
+
paint.style = Paint.Style.STROKE
|
|
62
|
+
paint.strokeWidth = (size * RING_STROKE_RATIO).coerceAtLeast(1f)
|
|
63
|
+
canvas.drawCircle(centerX, centerY, radius - paint.strokeWidth / 2f, paint)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
else -> {
|
|
67
|
+
paint.style = Paint.Style.FILL
|
|
68
|
+
canvas.drawRect(centerX - radius, centerY - radius, centerX + radius, centerY + radius, paint)
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
paint.style = originalStyle
|
|
72
|
+
paint.strokeWidth = originalStrokeWidth
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
companion object {
|
|
76
|
+
private const val INDENT_PER_DEPTH_DP = 18f
|
|
77
|
+
private const val MARKER_WIDTH_DP = 18f
|
|
78
|
+
private const val BULLET_SIZE_RATIO = 0.3f
|
|
79
|
+
private const val MIN_BULLET_PX = 4f
|
|
80
|
+
private const val RING_STROKE_RATIO = 0.15f
|
|
81
|
+
}
|
|
82
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
package com.swmansion.enriched.markdown.input.spans
|
|
2
|
+
|
|
3
|
+
import android.annotation.SuppressLint
|
|
4
|
+
import android.graphics.Typeface
|
|
5
|
+
import android.text.TextPaint
|
|
6
|
+
import android.text.style.MetricAffectingSpan
|
|
7
|
+
import com.facebook.react.common.ReactConstants
|
|
8
|
+
import com.swmansion.enriched.markdown.input.formatting.MarkdownSpan
|
|
9
|
+
import com.swmansion.enriched.markdown.input.model.InputFormatterStyle
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Sizes and optionally weights/colors a heading line per [InputFormatterStyle.headingStyle].
|
|
13
|
+
* Preserves inline bold/italic via [BOLD_ITALIC_MASK] so emphasis composes with heading weight.
|
|
14
|
+
* Tagged [MarkdownSpan] for formatter cleanup.
|
|
15
|
+
*/
|
|
16
|
+
class InputHeadingSpan(
|
|
17
|
+
val level: Int,
|
|
18
|
+
style: InputFormatterStyle,
|
|
19
|
+
) : MetricAffectingSpan(),
|
|
20
|
+
MarkdownSpan {
|
|
21
|
+
private val resolved = style.headingStyle(level)
|
|
22
|
+
|
|
23
|
+
override fun updateDrawState(tp: TextPaint) {
|
|
24
|
+
applyHeadingStyle(tp)
|
|
25
|
+
resolved.color?.let { tp.color = it }
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
override fun updateMeasureState(tp: TextPaint) {
|
|
29
|
+
applyHeadingStyle(tp)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
@SuppressLint("WrongConstant") // Result of mask is always valid: 0, 1, 2, or 3
|
|
33
|
+
private fun applyHeadingStyle(tp: TextPaint) {
|
|
34
|
+
resolved.fontSizePx?.let { tp.textSize = it }
|
|
35
|
+
|
|
36
|
+
if (resolved.fontWeight != ReactConstants.UNSET) {
|
|
37
|
+
// Fold the configured heading weight into whatever bold/italic an inline span
|
|
38
|
+
// already applied, so heading weight and inline emphasis compose instead of
|
|
39
|
+
// one clobbering the other.
|
|
40
|
+
val inlineStyle = (tp.typeface?.style ?: 0) and BOLD_ITALIC_MASK
|
|
41
|
+
val headingBold = if (resolved.fontWeight >= BOLD_WEIGHT_THRESHOLD) Typeface.BOLD else 0
|
|
42
|
+
val combined = inlineStyle or headingBold
|
|
43
|
+
tp.typeface =
|
|
44
|
+
if (combined != 0) {
|
|
45
|
+
Typeface.create(tp.typeface, combined)
|
|
46
|
+
} else {
|
|
47
|
+
tp.typeface
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
companion object {
|
|
53
|
+
private const val BOLD_ITALIC_MASK = Typeface.BOLD or Typeface.ITALIC
|
|
54
|
+
|
|
55
|
+
// React Native treats weights >= 700 as bold.
|
|
56
|
+
private const val BOLD_WEIGHT_THRESHOLD = 700
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
package com.swmansion.enriched.markdown.input.spans
|
|
2
|
+
|
|
3
|
+
import android.graphics.Paint
|
|
4
|
+
import android.text.Spanned
|
|
5
|
+
import android.text.style.LineHeightSpan
|
|
6
|
+
import com.swmansion.enriched.markdown.input.formatting.MarkdownSpan
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Adds [spacingPx] of vertical space above a bullet item (counterpart to iOS
|
|
10
|
+
* `paragraphSpacingBefore`). Tagged [MarkdownSpan] for formatter cleanup.
|
|
11
|
+
*
|
|
12
|
+
* StaticLayout treats a LineHeightSpan as paragraph-scoped: [chooseHeight] runs
|
|
13
|
+
* for every wrapped line of the item regardless of the span's character range,
|
|
14
|
+
* and the FontMetricsInt is reused across those calls, so an unguarded relative
|
|
15
|
+
* adjustment compounds line after line (progressively growing gaps). Guard to
|
|
16
|
+
* the single line that contains the span start so only the item's first visual
|
|
17
|
+
* line is spaced, exactly once.
|
|
18
|
+
*/
|
|
19
|
+
class InputListItemSpacingSpan(
|
|
20
|
+
val spacingPx: Int,
|
|
21
|
+
) : LineHeightSpan,
|
|
22
|
+
MarkdownSpan {
|
|
23
|
+
override fun chooseHeight(
|
|
24
|
+
text: CharSequence?,
|
|
25
|
+
start: Int,
|
|
26
|
+
end: Int,
|
|
27
|
+
spanstartv: Int,
|
|
28
|
+
lineHeight: Int,
|
|
29
|
+
fm: Paint.FontMetricsInt?,
|
|
30
|
+
) {
|
|
31
|
+
if (fm == null || spacingPx <= 0 || text !is Spanned) return
|
|
32
|
+
val spanStart = text.getSpanStart(this)
|
|
33
|
+
if (spanStart < start || spanStart >= end) return
|
|
34
|
+
fm.ascent -= spacingPx
|
|
35
|
+
fm.top -= spacingPx
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
package com.swmansion.enriched.markdown.input.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
|
+
import com.swmansion.enriched.markdown.input.formatting.MarkdownSpan
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Ordered list item span: reserves the same per-depth leading margin as
|
|
12
|
+
* [InputBulletSpan] and draws the item's number ("3.") right-aligned before the
|
|
13
|
+
* text column. The ordinal comes from the block store's list-metadata pass.
|
|
14
|
+
* Tagged [MarkdownSpan] for formatter cleanup.
|
|
15
|
+
*/
|
|
16
|
+
class InputOrderedListMarkerSpan(
|
|
17
|
+
val depth: Int,
|
|
18
|
+
private val ordinal: Int,
|
|
19
|
+
density: Float,
|
|
20
|
+
) : LeadingMarginSpan,
|
|
21
|
+
MarkdownSpan {
|
|
22
|
+
private val indentPerDepth = INDENT_PER_DEPTH_DP * density
|
|
23
|
+
private val markerWidth = MARKER_WIDTH_DP * density
|
|
24
|
+
private val markerGap = MARKER_GAP_DP * density
|
|
25
|
+
|
|
26
|
+
override fun getLeadingMargin(first: Boolean): Int = (depth * indentPerDepth + markerWidth).toInt()
|
|
27
|
+
|
|
28
|
+
override fun drawLeadingMargin(
|
|
29
|
+
canvas: Canvas,
|
|
30
|
+
paint: Paint,
|
|
31
|
+
x: Int,
|
|
32
|
+
dir: Int,
|
|
33
|
+
top: Int,
|
|
34
|
+
baseline: Int,
|
|
35
|
+
bottom: Int,
|
|
36
|
+
text: CharSequence?,
|
|
37
|
+
start: Int,
|
|
38
|
+
end: Int,
|
|
39
|
+
first: Boolean,
|
|
40
|
+
layout: Layout?,
|
|
41
|
+
) {
|
|
42
|
+
if (!first) return
|
|
43
|
+
// Wrapped continuation lines also report first=true; draw only on the visual
|
|
44
|
+
// line where this span actually begins.
|
|
45
|
+
if (text is Spanned && text.getSpanStart(this) != start) return
|
|
46
|
+
|
|
47
|
+
// RTL (dir < 0) mirrors the marker to the trailing side and flips the label
|
|
48
|
+
// to ".3", matching the readonly renderer's OrderedListSpan.
|
|
49
|
+
val label = if (dir < 0) ".$ordinal" else "$ordinal."
|
|
50
|
+
val originalAlign = paint.textAlign
|
|
51
|
+
paint.textAlign = if (dir < 0) Paint.Align.LEFT else Paint.Align.RIGHT
|
|
52
|
+
val markerEdge = x + (depth * indentPerDepth + markerWidth - markerGap) * dir
|
|
53
|
+
canvas.drawText(label, markerEdge, baseline.toFloat(), paint)
|
|
54
|
+
paint.textAlign = originalAlign
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
companion object {
|
|
58
|
+
// Geometry mirrors InputBulletSpan so ordered and bullet items align.
|
|
59
|
+
private const val INDENT_PER_DEPTH_DP = 18f
|
|
60
|
+
private const val MARKER_WIDTH_DP = 18f
|
|
61
|
+
private const val MARKER_GAP_DP = 4f
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
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
|
+
|
|
7
|
+
/**
|
|
8
|
+
* A block handler owns how its [BlockType] styles its paragraph and how it
|
|
9
|
+
* serializes to a markdown line prefix. Mirrors [StyleHandler] for the inline
|
|
10
|
+
* pipeline. Parser recognition is NOT handler-driven: it lives in
|
|
11
|
+
* [com.swmansion.enriched.markdown.input.formatting.InputParser]'s central
|
|
12
|
+
* `nodeTypeToBlockType` map, exactly as `nodeTypeToStyleType` does for inline
|
|
13
|
+
* styles — a new block type adds one entry there plus one handler here.
|
|
14
|
+
*
|
|
15
|
+
* Block spans are paragraph-scoped and applied over the block's whole line range
|
|
16
|
+
* by [com.swmansion.enriched.markdown.input.formatting.InputFormatter]. Unlike
|
|
17
|
+
* inline [StyleHandler.createSpans] (which returns `CharacterStyle`), a block
|
|
18
|
+
* handler returns `List<Any>` so it can mix character spans (a heading's
|
|
19
|
+
* metric/size span) with paragraph spans (a list item's `LeadingMarginSpan` and
|
|
20
|
+
* line-spacing span).
|
|
21
|
+
*
|
|
22
|
+
* These signatures are designed to cover headings AND list items.
|
|
23
|
+
*/
|
|
24
|
+
interface BlockHandler {
|
|
25
|
+
val blockType: BlockType
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Whether Enter continues the block onto the next line (a list item) rather
|
|
29
|
+
* than ending it (a heading). Keeps Enter behavior handler-driven.
|
|
30
|
+
*/
|
|
31
|
+
val continuesOnNewline: Boolean
|
|
32
|
+
get() = false
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Spans to apply over the block's line range. Returned spans are tagged with
|
|
36
|
+
* [com.swmansion.enriched.markdown.input.formatting.MarkdownSpan] so the
|
|
37
|
+
* formatter can clean up only spans it created. A heading raises the font
|
|
38
|
+
* size; a list item sets a leading margin and a marker. May be empty.
|
|
39
|
+
*/
|
|
40
|
+
fun createSpans(
|
|
41
|
+
blockRange: BlockRange,
|
|
42
|
+
style: InputFormatterStyle,
|
|
43
|
+
): List<Any>
|
|
44
|
+
|
|
45
|
+
/** Span classes this handler produces, for cleanup/identity (mirrors [StyleHandler.spanClasses]). */
|
|
46
|
+
fun spanClasses(): List<Class<*>>
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Markdown prefix prepended to each line of the block during serialization,
|
|
50
|
+
* e.g. `"# "` for an H1 or `"- "` for a bullet. Returns `""` when the block
|
|
51
|
+
* needs no prefix. Owning the marker here replaces a central serializer switch.
|
|
52
|
+
*/
|
|
53
|
+
fun markdownLinePrefix(blockRange: BlockRange): String
|
|
54
|
+
}
|