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
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
package com.swmansion.enriched.markdown.input
|
|
2
|
+
|
|
3
|
+
import android.content.ClipData
|
|
4
|
+
import android.content.ClipDescription
|
|
5
|
+
import android.content.ClipboardManager
|
|
6
|
+
import android.content.Context
|
|
7
|
+
import android.os.PersistableBundle
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Clipboard round-trip for markdown content, mirroring iOS's dual pasteboard
|
|
11
|
+
* representation: the clip's item text stays clean plain text for external
|
|
12
|
+
* paste targets, while the markdown source travels in the description extras
|
|
13
|
+
* under a vendor MIME type so our paste can restore formatting and block
|
|
14
|
+
* ranges. External clips (no vendor MIME) keep pasting as plain text.
|
|
15
|
+
*/
|
|
16
|
+
object MarkdownClipboard {
|
|
17
|
+
const val MIME_TYPE = "text/vnd.com.swmansion.enriched-markdown"
|
|
18
|
+
private const val EXTRA_MARKDOWN = "com.swmansion.enriched-markdown.markdown"
|
|
19
|
+
|
|
20
|
+
fun newMarkdownClip(
|
|
21
|
+
markdown: String,
|
|
22
|
+
plainText: String,
|
|
23
|
+
): ClipData {
|
|
24
|
+
val clip =
|
|
25
|
+
ClipData(
|
|
26
|
+
ClipDescription("Markdown", arrayOf(MIME_TYPE, ClipDescription.MIMETYPE_TEXT_PLAIN)),
|
|
27
|
+
ClipData.Item(plainText),
|
|
28
|
+
)
|
|
29
|
+
clip.description.extras = PersistableBundle().apply { putString(EXTRA_MARKDOWN, markdown) }
|
|
30
|
+
return clip
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** Returns the clipboard's markdown, or null if the clip wasn't created by [newMarkdownClip]. */
|
|
34
|
+
fun markdownFromClipboard(context: Context): String? {
|
|
35
|
+
val clipboard = context.getSystemService(Context.CLIPBOARD_SERVICE) as? ClipboardManager ?: return null
|
|
36
|
+
val clip = clipboard.primaryClip ?: return null
|
|
37
|
+
if (!clip.description.hasMimeType(MIME_TYPE)) return null
|
|
38
|
+
return clip.description.extras
|
|
39
|
+
?.getString(EXTRA_MARKDOWN)
|
|
40
|
+
?.takeIf { it.isNotEmpty() }
|
|
41
|
+
}
|
|
42
|
+
}
|
package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/BlockEditCoordinator.kt
ADDED
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
package com.swmansion.enriched.markdown.input.editing
|
|
2
|
+
|
|
3
|
+
import android.text.Editable
|
|
4
|
+
import com.swmansion.enriched.markdown.input.formatting.BlockStore
|
|
5
|
+
import com.swmansion.enriched.markdown.input.model.BlockRange
|
|
6
|
+
import com.swmansion.enriched.markdown.input.model.BlockType
|
|
7
|
+
import com.swmansion.enriched.markdown.input.model.MAX_LIST_DEPTH
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Encapsulates block-editing operations: toggling block types, adjusting
|
|
11
|
+
* list depth, and querying the block at a given position. The view delegates
|
|
12
|
+
* here and applies UI-level consequences (formatting, anchor sync, cursor
|
|
13
|
+
* size, typing attributes) based on the returned result.
|
|
14
|
+
*
|
|
15
|
+
* All mutating methods normalize stores to line bounds before returning, so
|
|
16
|
+
* the caller can re-stamp block spans immediately.
|
|
17
|
+
*/
|
|
18
|
+
class BlockEditCoordinator(
|
|
19
|
+
private val blockStore: BlockStore,
|
|
20
|
+
) {
|
|
21
|
+
// ── Queries ──────────────────────────────────────────────────────────
|
|
22
|
+
|
|
23
|
+
fun blockAtPosition(
|
|
24
|
+
text: CharSequence,
|
|
25
|
+
pos: Int,
|
|
26
|
+
): BlockRange? {
|
|
27
|
+
val lineStart = lineStartOf(text, pos)
|
|
28
|
+
return blockStore.blockStartingAt(lineStart)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
fun listBlockAtPosition(
|
|
32
|
+
text: CharSequence,
|
|
33
|
+
pos: Int,
|
|
34
|
+
): BlockRange? = blockAtPosition(text, pos)?.takeIf { it.type in BlockType.LIST_ITEMS }
|
|
35
|
+
|
|
36
|
+
fun listBlockAtLineStart(lineStart: Int): BlockRange? = blockStore.blockStartingAt(lineStart)?.takeIf { it.type in BlockType.LIST_ITEMS }
|
|
37
|
+
|
|
38
|
+
fun headingLevelAtPosition(
|
|
39
|
+
text: CharSequence,
|
|
40
|
+
pos: Int,
|
|
41
|
+
): Int {
|
|
42
|
+
val block = blockAtPosition(text, pos) ?: return 0
|
|
43
|
+
return if (block.type in BlockType.HEADINGS) block.level else 0
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
fun listStateAtPosition(
|
|
47
|
+
text: CharSequence,
|
|
48
|
+
pos: Int,
|
|
49
|
+
type: BlockType,
|
|
50
|
+
): Pair<Boolean, Int> {
|
|
51
|
+
val block = listBlockAtPosition(text, pos) ?: return false to 0
|
|
52
|
+
return if (block.type == type) true to block.level else false to 0
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// ── Mutations ────────────────────────────────────────────────────────
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Toggles [type] at [level] on the paragraphs the selection touches.
|
|
59
|
+
* Returns true when the block was already active (i.e. it was turned off).
|
|
60
|
+
*/
|
|
61
|
+
fun toggleBlock(
|
|
62
|
+
text: Editable,
|
|
63
|
+
type: BlockType,
|
|
64
|
+
level: Int,
|
|
65
|
+
selStart: Int,
|
|
66
|
+
selEnd: Int,
|
|
67
|
+
): Boolean {
|
|
68
|
+
val existing = blockAtPosition(text, selStart)
|
|
69
|
+
val wasActive = existing != null && existing.type == type && existing.level == level
|
|
70
|
+
|
|
71
|
+
if (wasActive) {
|
|
72
|
+
blockStore.removeBlock(selStart, selEnd, text)
|
|
73
|
+
} else {
|
|
74
|
+
forEachLine(text, selStart, selEnd) { ls, le ->
|
|
75
|
+
blockStore.setBlock(type, level, ls, le, text)
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
blockStore.normalizeToLineBounds(text)
|
|
79
|
+
return wasActive
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Toggles a list of [type] on the selection: turns lines into depth-0
|
|
84
|
+
* items (switching list type keeps each line's depth) or clears them back
|
|
85
|
+
* to plain paragraphs when the cursor line already carries [type].
|
|
86
|
+
* Returns true when the list was turned off.
|
|
87
|
+
*/
|
|
88
|
+
fun toggleList(
|
|
89
|
+
text: Editable,
|
|
90
|
+
type: BlockType,
|
|
91
|
+
cursorPos: Int,
|
|
92
|
+
selStart: Int,
|
|
93
|
+
selEnd: Int,
|
|
94
|
+
): Boolean {
|
|
95
|
+
val turningOff = listBlockAtPosition(text, cursorPos)?.type == type
|
|
96
|
+
if (turningOff) {
|
|
97
|
+
forEachLine(text, selStart, selEnd) { ls, le ->
|
|
98
|
+
blockStore.removeBlock(ls, le, text)
|
|
99
|
+
}
|
|
100
|
+
} else {
|
|
101
|
+
forEachLine(text, selStart, selEnd) { ls, le ->
|
|
102
|
+
val existing = listBlockAtLineStart(ls)
|
|
103
|
+
blockStore.setBlock(type, existing?.level ?: 0, ls, le, text)
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
blockStore.normalizeToLineBounds(text)
|
|
107
|
+
return turningOff
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
enum class DepthChangeResult {
|
|
111
|
+
/** Depth was adjusted on the existing list item(s). */
|
|
112
|
+
CHANGED,
|
|
113
|
+
|
|
114
|
+
/** No list existed; a new unordered list was started (delta > 0 only). */
|
|
115
|
+
STARTED_LIST,
|
|
116
|
+
|
|
117
|
+
/** Outdented at depth 0 — the list marker was removed. */
|
|
118
|
+
EXITED_LIST,
|
|
119
|
+
|
|
120
|
+
/** Nothing happened (e.g. outdent on a heading or plain paragraph). */
|
|
121
|
+
NO_OP,
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Adjusts list depth by [delta] on the selected lines. When the cursor
|
|
126
|
+
* is on a plain paragraph and delta > 0, starts a new unordered list.
|
|
127
|
+
* When outdenting at depth 0, removes the list marker.
|
|
128
|
+
*
|
|
129
|
+
* Returns the action taken so the view can apply the appropriate UI effects.
|
|
130
|
+
*/
|
|
131
|
+
fun changeDepth(
|
|
132
|
+
text: Editable,
|
|
133
|
+
cursorPos: Int,
|
|
134
|
+
selStart: Int,
|
|
135
|
+
selEnd: Int,
|
|
136
|
+
delta: Int,
|
|
137
|
+
): DepthChangeResult {
|
|
138
|
+
val cursorBlock = listBlockAtPosition(text, cursorPos)
|
|
139
|
+
if (cursorBlock == null) {
|
|
140
|
+
if (delta > 0 && blockAtPosition(text, cursorPos) == null) {
|
|
141
|
+
toggleList(text, BlockType.UNORDERED_LIST_ITEM, cursorPos, selStart, selEnd)
|
|
142
|
+
return DepthChangeResult.STARTED_LIST
|
|
143
|
+
}
|
|
144
|
+
return DepthChangeResult.NO_OP
|
|
145
|
+
}
|
|
146
|
+
if (delta < 0 && cursorBlock.level == 0) {
|
|
147
|
+
toggleList(text, cursorBlock.type, cursorPos, selStart, selEnd)
|
|
148
|
+
return DepthChangeResult.EXITED_LIST
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
forEachLine(text, selStart, selEnd) { ls, _ ->
|
|
152
|
+
val block = listBlockAtLineStart(ls)
|
|
153
|
+
if (block != null) {
|
|
154
|
+
val newDepth = (block.level + delta).coerceIn(0, MAX_LIST_DEPTH)
|
|
155
|
+
blockStore.setBlock(block.type, newDepth, ls, ls, text)
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
blockStore.normalizeToLineBounds(text)
|
|
159
|
+
return DepthChangeResult.CHANGED
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// ── Line utilities ───────────────────────────────────────────────────
|
|
163
|
+
|
|
164
|
+
fun lineStartOf(
|
|
165
|
+
text: CharSequence,
|
|
166
|
+
pos: Int,
|
|
167
|
+
): Int {
|
|
168
|
+
var s = pos.coerceIn(0, text.length)
|
|
169
|
+
while (s > 0 && !text[s - 1].isLineBreak()) s--
|
|
170
|
+
return s
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
fun lineEndOf(
|
|
174
|
+
text: CharSequence,
|
|
175
|
+
pos: Int,
|
|
176
|
+
): Int {
|
|
177
|
+
var e = pos.coerceIn(0, text.length)
|
|
178
|
+
while (e < text.length && !text[e].isLineBreak()) e++
|
|
179
|
+
return e
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
private inline fun forEachLine(
|
|
183
|
+
text: CharSequence,
|
|
184
|
+
selStart: Int,
|
|
185
|
+
selEnd: Int,
|
|
186
|
+
action: (lineStart: Int, lineEnd: Int) -> Unit,
|
|
187
|
+
) {
|
|
188
|
+
var cursor = lineStartOf(text, selStart)
|
|
189
|
+
while (cursor <= text.length) {
|
|
190
|
+
val le = lineEndOf(text, cursor)
|
|
191
|
+
action(cursor, le)
|
|
192
|
+
if (le >= selEnd) break
|
|
193
|
+
cursor = le + 1
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/ClipboardCoordinator.kt
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
package com.swmansion.enriched.markdown.input.editing
|
|
2
|
+
|
|
3
|
+
import android.text.Editable
|
|
4
|
+
import com.swmansion.enriched.markdown.input.detection.DetectorPipeline
|
|
5
|
+
import com.swmansion.enriched.markdown.input.formatting.BlockStore
|
|
6
|
+
import com.swmansion.enriched.markdown.input.formatting.FormattingStore
|
|
7
|
+
import com.swmansion.enriched.markdown.input.formatting.InputFormatter
|
|
8
|
+
import com.swmansion.enriched.markdown.input.formatting.MarkdownSerializer
|
|
9
|
+
import com.swmansion.enriched.markdown.input.math.MathChipController
|
|
10
|
+
import com.swmansion.enriched.markdown.input.model.BlockRange
|
|
11
|
+
import com.swmansion.enriched.markdown.input.model.FormattingRange
|
|
12
|
+
|
|
13
|
+
class ClipboardCoordinator(
|
|
14
|
+
private val formattingStore: FormattingStore,
|
|
15
|
+
private val blockStore: BlockStore,
|
|
16
|
+
private val detectorPipeline: DetectorPipeline,
|
|
17
|
+
private val formatter: InputFormatter,
|
|
18
|
+
) {
|
|
19
|
+
fun allRangesForSerialization(editable: Editable?): List<FormattingRange> {
|
|
20
|
+
if (editable == null) return formattingStore.allRanges
|
|
21
|
+
val transient = detectorPipeline.allTransientFormattingRanges(editable)
|
|
22
|
+
if (transient.isEmpty()) return formattingStore.allRanges
|
|
23
|
+
return formattingStore.allRanges + transient
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
fun serializeFullDocument(
|
|
27
|
+
text: String,
|
|
28
|
+
editable: Editable?,
|
|
29
|
+
chips: List<MathChipController.ChipInfo> = emptyList(),
|
|
30
|
+
): String =
|
|
31
|
+
MarkdownSerializer.serialize(text, chips, allRangesForSerialization(editable), blockStore.allRanges) { block ->
|
|
32
|
+
formatter.handlerForBlock(block.type)?.markdownLinePrefix(block) ?: ""
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
fun serializeSelectedRange(
|
|
36
|
+
fullText: String,
|
|
37
|
+
selStart: Int,
|
|
38
|
+
selEnd: Int,
|
|
39
|
+
editable: Editable?,
|
|
40
|
+
chips: List<MathChipController.ChipInfo> = emptyList(),
|
|
41
|
+
): String? {
|
|
42
|
+
if (selStart >= selEnd) return null
|
|
43
|
+
val selectedText = fullText.substring(selStart, selEnd)
|
|
44
|
+
|
|
45
|
+
val clippedRanges = mutableListOf<FormattingRange>()
|
|
46
|
+
for (range in allRangesForSerialization(editable)) {
|
|
47
|
+
if (range.end <= selStart || range.start >= selEnd) continue
|
|
48
|
+
val clippedStart = maxOf(range.start, selStart)
|
|
49
|
+
val clippedEnd = minOf(range.end, selEnd)
|
|
50
|
+
clippedRanges.add(FormattingRange(range.type, clippedStart - selStart, clippedEnd - selStart, range.url))
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
val clippedBlockRanges = mutableListOf<BlockRange>()
|
|
54
|
+
for (block in blockStore.allRanges) {
|
|
55
|
+
if (block.end <= selStart || block.start >= selEnd) continue
|
|
56
|
+
val clippedStart = maxOf(block.start, selStart)
|
|
57
|
+
val clippedEnd = minOf(block.end, selEnd)
|
|
58
|
+
clippedBlockRanges.add(BlockRange(block.type, clippedStart - selStart, clippedEnd - selStart, block.level))
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// A chip is a single character, so it is cleanly inside or outside the selection;
|
|
62
|
+
// rebase the survivors onto the substring like the ranges above. Copying part of
|
|
63
|
+
// a document must serialize its formulas, not the bare placeholder char.
|
|
64
|
+
val clippedChips =
|
|
65
|
+
chips
|
|
66
|
+
.filter { it.position in selStart until selEnd }
|
|
67
|
+
.map { it.copy(position = it.position - selStart) }
|
|
68
|
+
|
|
69
|
+
return MarkdownSerializer.serialize(selectedText, clippedChips, clippedRanges, clippedBlockRanges) { block ->
|
|
70
|
+
formatter.handlerForBlock(block.type)?.markdownLinePrefix(block) ?: ""
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
package com.swmansion.enriched.markdown.input.editing
|
|
2
|
+
|
|
3
|
+
import com.swmansion.enriched.markdown.input.model.StyleType
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Immutable snapshot of everything the [EditPipeline] needs to process a single
|
|
7
|
+
* text change. Built by the view from its pre-/post-edit state, then handed to
|
|
8
|
+
* [EditPipeline.processTextChange].
|
|
9
|
+
*/
|
|
10
|
+
data class EditContext(
|
|
11
|
+
val editStart: Int,
|
|
12
|
+
val deletedLength: Int,
|
|
13
|
+
val insertedLength: Int,
|
|
14
|
+
val preEditText: String,
|
|
15
|
+
val preEditSelectionStart: Int,
|
|
16
|
+
val preEditSelectionEnd: Int,
|
|
17
|
+
val pendingStyles: Set<StyleType>,
|
|
18
|
+
val pendingStyleRemovals: Set<StyleType>,
|
|
19
|
+
)
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
package com.swmansion.enriched.markdown.input.editing
|
|
2
|
+
|
|
3
|
+
import android.text.Editable
|
|
4
|
+
import com.swmansion.enriched.markdown.input.detection.DetectorPipeline
|
|
5
|
+
import com.swmansion.enriched.markdown.input.formatting.BlockStore
|
|
6
|
+
import com.swmansion.enriched.markdown.input.formatting.FormattingStore
|
|
7
|
+
import com.swmansion.enriched.markdown.input.formatting.InputFormatter
|
|
8
|
+
import com.swmansion.enriched.markdown.input.layout.InputEventEmitter
|
|
9
|
+
import com.swmansion.enriched.markdown.input.model.BlockType
|
|
10
|
+
import com.swmansion.enriched.markdown.input.model.FormattingRange
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Zero-width space: anchors an empty bullet line so the marker draws and the
|
|
14
|
+
* caret indents (Android won't apply a LeadingMarginSpan's indent to an empty
|
|
15
|
+
* paragraph). Stripped during serialization, so it never reaches the Markdown output.
|
|
16
|
+
*/
|
|
17
|
+
internal const val ZWSP = '\u200B'
|
|
18
|
+
|
|
19
|
+
internal fun Char.isLineBreak(): Boolean = this == '\n' || this == '\r' || this == '\u0085' || this == '\u2028' || this == '\u2029'
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* View-specific operations the [EditPipeline] delegates back to its host.
|
|
23
|
+
* Implemented by [EnrichedMarkdownTextInputView][com.swmansion.enriched.markdown.input.EnrichedMarkdownTextInputView].
|
|
24
|
+
*/
|
|
25
|
+
interface EditPipelineHost {
|
|
26
|
+
val editable: Editable?
|
|
27
|
+
val emitMarkdown: Boolean
|
|
28
|
+
|
|
29
|
+
fun syncEmptyListAnchor(restamp: Boolean): Boolean
|
|
30
|
+
|
|
31
|
+
fun forceScrollToSelection()
|
|
32
|
+
|
|
33
|
+
fun syncCursorSizeWithBlock()
|
|
34
|
+
|
|
35
|
+
fun updateActiveMention()
|
|
36
|
+
|
|
37
|
+
fun runAsATransaction(block: () -> Unit)
|
|
38
|
+
|
|
39
|
+
fun setViewSelection(position: Int)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Orchestrates the per-keystroke edit pipeline: store adjustment, block
|
|
44
|
+
* continuation, formatting, detection, and event emission.
|
|
45
|
+
*
|
|
46
|
+
* Phases run in a fixed order — each phase's postcondition is the next phase's
|
|
47
|
+
* precondition. New block types add behavior to [continueBlocks] (via their
|
|
48
|
+
* handler's [continuesOnNewline][com.swmansion.enriched.markdown.input.styles.BlockHandler.continuesOnNewline])
|
|
49
|
+
* without touching this pipeline.
|
|
50
|
+
*/
|
|
51
|
+
class EditPipeline(
|
|
52
|
+
private val formattingStore: FormattingStore,
|
|
53
|
+
private val blockStore: BlockStore,
|
|
54
|
+
private val formatter: InputFormatter,
|
|
55
|
+
private val detectorPipeline: DetectorPipeline,
|
|
56
|
+
private val eventEmitter: InputEventEmitter,
|
|
57
|
+
private val host: EditPipelineHost,
|
|
58
|
+
) {
|
|
59
|
+
/**
|
|
60
|
+
* Main entry point — called once per user-driven text change. The [context]
|
|
61
|
+
* captures the edit parameters and pre-edit state as an immutable snapshot.
|
|
62
|
+
*/
|
|
63
|
+
fun processTextChange(context: EditContext) {
|
|
64
|
+
adjustStores(context)
|
|
65
|
+
pruneOrphanedAnchors()
|
|
66
|
+
continueBlocks(context)
|
|
67
|
+
host.editable?.let { blockStore.normalizeToLineBounds(it) }
|
|
68
|
+
applyPendingStyles(context)
|
|
69
|
+
|
|
70
|
+
// Settle the ZWSP anchor BEFORE stamping spans, so block formatting runs
|
|
71
|
+
// exactly once over the final text/ranges — otherwise a pre-ZWSP and
|
|
72
|
+
// post-ZWSP span would both land on the empty line ("double bullet" bug).
|
|
73
|
+
val anchorChanged = host.syncEmptyListAnchor(restamp = false)
|
|
74
|
+
val touchedNewline = anchorChanged || editTouchedNewline(context)
|
|
75
|
+
|
|
76
|
+
applyInlineFormatting()
|
|
77
|
+
applyBlockFormatting(touchedNewline, context.editStart, context.insertedLength)
|
|
78
|
+
detectLinks(context)
|
|
79
|
+
|
|
80
|
+
host.forceScrollToSelection()
|
|
81
|
+
host.syncCursorSizeWithBlock()
|
|
82
|
+
|
|
83
|
+
eventEmitter.emitChangeText()
|
|
84
|
+
if (host.emitMarkdown) eventEmitter.emitChangeMarkdown()
|
|
85
|
+
host.updateActiveMention()
|
|
86
|
+
eventEmitter.emitCaretRectChangeIfNeeded()
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
private fun adjustStores(context: EditContext) {
|
|
90
|
+
formattingStore.adjustForEdit(context.editStart, context.deletedLength, context.insertedLength)
|
|
91
|
+
blockStore.adjustForEdit(context.editStart, context.deletedLength, context.insertedLength)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Drops anchored blocks (headings, list items) no longer anchored at a line
|
|
96
|
+
* start (e.g. Backspace merged their line into the previous one). Must run
|
|
97
|
+
* BEFORE [BlockStore.normalizeToLineBounds] so a merged range is judged on
|
|
98
|
+
* its unsnapped anchor.
|
|
99
|
+
*
|
|
100
|
+
* Internal so the view's [adjustStoresForEdit][com.swmansion.enriched.markdown.input.EnrichedMarkdownTextInputView]
|
|
101
|
+
* helper (used by programmatic text-mutation paths) can call it too.
|
|
102
|
+
*/
|
|
103
|
+
internal fun pruneOrphanedAnchors() {
|
|
104
|
+
val editable = host.editable ?: return
|
|
105
|
+
val orphans =
|
|
106
|
+
blockStore.allRanges.filter { range ->
|
|
107
|
+
range.type in BlockType.ANCHORED && !isAtLineStart(editable, range.start)
|
|
108
|
+
}
|
|
109
|
+
for (orphan in orphans) {
|
|
110
|
+
blockStore.removeBlock(orphan.start, orphan.start, editable)
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* After a newline insertion, continues a block whose handler reports
|
|
116
|
+
* [continuesOnNewline][com.swmansion.enriched.markdown.input.styles.BlockHandler.continuesOnNewline]
|
|
117
|
+
* onto the new line as a sibling at the same depth, or exits the block when
|
|
118
|
+
* the emptied item gets a second Enter.
|
|
119
|
+
*/
|
|
120
|
+
private fun continueBlocks(context: EditContext) {
|
|
121
|
+
val editable = host.editable ?: return
|
|
122
|
+
if (context.deletedLength != 0 || context.insertedLength <= 0) return
|
|
123
|
+
val insertedEnd = (context.editStart + context.insertedLength).coerceAtMost(editable.length)
|
|
124
|
+
val insertedNewline = (context.editStart until insertedEnd).any { editable[it] == '\n' }
|
|
125
|
+
if (!insertedNewline) return
|
|
126
|
+
|
|
127
|
+
val prevLineEnd = context.editStart
|
|
128
|
+
var prevLineStart = prevLineEnd
|
|
129
|
+
while (prevLineStart > 0 && editable[prevLineStart - 1] != '\n') prevLineStart--
|
|
130
|
+
|
|
131
|
+
val prevBlock = blockStore.blockStartingAt(prevLineStart) ?: return
|
|
132
|
+
val handler = formatter.handlerForBlock(prevBlock.type) ?: return
|
|
133
|
+
if (!handler.continuesOnNewline) return
|
|
134
|
+
|
|
135
|
+
val prevContentLength = (prevLineStart until prevLineEnd).count { editable[it] != ZWSP }
|
|
136
|
+
if (prevContentLength == 0) {
|
|
137
|
+
// Exit: clear the block AND delete the just-inserted newline so the empty
|
|
138
|
+
// item collapses in place instead of leaving an extra indented blank line.
|
|
139
|
+
blockStore.removeBlock(prevLineStart, prevLineEnd, editable)
|
|
140
|
+
val newlineEnd = (context.editStart + context.insertedLength).coerceAtMost(editable.length)
|
|
141
|
+
host.runAsATransaction { editable.delete(context.editStart, newlineEnd) }
|
|
142
|
+
blockStore.adjustForEdit(context.editStart, context.insertedLength, 0)
|
|
143
|
+
host.setViewSelection(prevLineStart.coerceAtMost(editable.length))
|
|
144
|
+
return
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
val newLineStart = (context.editStart + context.insertedLength).coerceAtMost(editable.length)
|
|
148
|
+
blockStore.setBlock(prevBlock.type, prevBlock.level, newLineStart, newLineStart, editable)
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
private fun applyPendingStyles(context: EditContext) {
|
|
152
|
+
if (context.insertedLength == 0) return
|
|
153
|
+
if (context.pendingStyles.isEmpty() && context.pendingStyleRemovals.isEmpty()) return
|
|
154
|
+
|
|
155
|
+
val rangeStart =
|
|
156
|
+
if (context.preEditSelectionStart != context.preEditSelectionEnd) {
|
|
157
|
+
context.preEditSelectionStart
|
|
158
|
+
} else {
|
|
159
|
+
context.editStart
|
|
160
|
+
}
|
|
161
|
+
val rangeEnd = rangeStart + context.insertedLength
|
|
162
|
+
|
|
163
|
+
// Skip applying pending styles when the insertion is only line breaks —
|
|
164
|
+
// a phantom range over a bare newline corrupts isStyleActive() at the boundary.
|
|
165
|
+
val currentText = host.editable
|
|
166
|
+
val insertedHasGlyphContent =
|
|
167
|
+
currentText != null &&
|
|
168
|
+
rangeEnd <= currentText.length &&
|
|
169
|
+
(rangeStart until rangeEnd).any { !currentText[it].isLineBreak() }
|
|
170
|
+
|
|
171
|
+
if (insertedHasGlyphContent) {
|
|
172
|
+
for (style in context.pendingStyles) {
|
|
173
|
+
formattingStore.addRange(FormattingRange(style, rangeStart, rangeEnd))
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
for (style in context.pendingStyleRemovals) {
|
|
178
|
+
formattingStore.removeType(style, rangeStart, rangeEnd)
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
private fun applyInlineFormatting() {
|
|
183
|
+
val editable = host.editable ?: return
|
|
184
|
+
formatter.applyFormatting(editable, formattingStore.allRanges)
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
private fun applyBlockFormatting(
|
|
188
|
+
touchedNewline: Boolean,
|
|
189
|
+
editStart: Int,
|
|
190
|
+
insertedLength: Int,
|
|
191
|
+
) {
|
|
192
|
+
val editable = host.editable ?: return
|
|
193
|
+
if (touchedNewline) {
|
|
194
|
+
formatter.applyBlockFormatting(editable, blockStore.allRanges)
|
|
195
|
+
} else {
|
|
196
|
+
applyBlockFormattingScopedToEdit(editable, editStart, insertedLength)
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
private fun applyBlockFormattingScopedToEdit(
|
|
201
|
+
editable: Editable,
|
|
202
|
+
editStart: Int,
|
|
203
|
+
insertedLength: Int,
|
|
204
|
+
) {
|
|
205
|
+
val length = editable.length
|
|
206
|
+
val rawStart = editStart.coerceIn(0, length)
|
|
207
|
+
val rawEnd = (editStart + insertedLength).coerceIn(rawStart, length)
|
|
208
|
+
|
|
209
|
+
var lineStart = rawStart
|
|
210
|
+
while (lineStart > 0 && editable[lineStart - 1] != '\n') lineStart--
|
|
211
|
+
var lineEnd = rawEnd
|
|
212
|
+
while (lineEnd < length && editable[lineEnd] != '\n') lineEnd++
|
|
213
|
+
|
|
214
|
+
formatter.applyBlockFormatting(editable, blockStore.allRanges, lineStart, lineEnd)
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
private fun detectLinks(context: EditContext) {
|
|
218
|
+
val editable = host.editable ?: return
|
|
219
|
+
val currentText = editable.toString()
|
|
220
|
+
detectorPipeline.processTextChange(editable, currentText, context.editStart, context.insertedLength)
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* True when the edit inserted or deleted a line break (so block spans may
|
|
225
|
+
* need to move across lines). Checks the inserted run in the current text
|
|
226
|
+
* and the deleted run in the pre-edit text.
|
|
227
|
+
*/
|
|
228
|
+
private fun editTouchedNewline(context: EditContext): Boolean {
|
|
229
|
+
val editable = host.editable
|
|
230
|
+
if (editable != null && context.insertedLength > 0) {
|
|
231
|
+
val end = (context.editStart + context.insertedLength).coerceAtMost(editable.length)
|
|
232
|
+
if ((context.editStart until end).any { editable[it].isLineBreak() }) return true
|
|
233
|
+
}
|
|
234
|
+
if (context.deletedLength > 0) {
|
|
235
|
+
val end = (context.editStart + context.deletedLength).coerceAtMost(context.preEditText.length)
|
|
236
|
+
if ((context.editStart until end).any { context.preEditText[it].isLineBreak() }) return true
|
|
237
|
+
}
|
|
238
|
+
return false
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
private fun isAtLineStart(
|
|
242
|
+
editable: CharSequence,
|
|
243
|
+
pos: Int,
|
|
244
|
+
): Boolean {
|
|
245
|
+
if (pos < 0 || pos > editable.length) return false
|
|
246
|
+
return pos == 0 || editable[pos - 1].isLineBreak()
|
|
247
|
+
}
|
|
248
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
package com.swmansion.enriched.markdown.input.editing
|
|
2
|
+
|
|
3
|
+
enum class EditPhase {
|
|
4
|
+
Idle,
|
|
5
|
+
Processing,
|
|
6
|
+
Importing,
|
|
7
|
+
ManagingAnchors,
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Tracks the current editing phase and exposes computed suppression queries.
|
|
12
|
+
* Replaces the scattered boolean flags (`isProcessingTextChange`,
|
|
13
|
+
* `isDuringTransaction`, `blockEmitting`, `isManagingAnchor`) that previously
|
|
14
|
+
* guarded re-entrant code paths in the view.
|
|
15
|
+
*/
|
|
16
|
+
class EditSession {
|
|
17
|
+
var phase: EditPhase = EditPhase.Idle
|
|
18
|
+
private set
|
|
19
|
+
|
|
20
|
+
var isTextChanging: Boolean = false
|
|
21
|
+
var didTextChangeRecently: Boolean = false
|
|
22
|
+
|
|
23
|
+
val shouldSuppressTextWatcher: Boolean
|
|
24
|
+
get() = phase != EditPhase.Idle
|
|
25
|
+
|
|
26
|
+
val shouldSuppressEvents: Boolean
|
|
27
|
+
get() = phase == EditPhase.Importing
|
|
28
|
+
|
|
29
|
+
val shouldSuppressAnchorSync: Boolean
|
|
30
|
+
get() = phase == EditPhase.ManagingAnchors
|
|
31
|
+
|
|
32
|
+
fun enter(newPhase: EditPhase) {
|
|
33
|
+
phase = newPhase
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
fun exit() {
|
|
37
|
+
phase = EditPhase.Idle
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
fun <T> scoped(
|
|
41
|
+
newPhase: EditPhase,
|
|
42
|
+
block: () -> T,
|
|
43
|
+
): T {
|
|
44
|
+
val previous = phase
|
|
45
|
+
phase = newPhase
|
|
46
|
+
try {
|
|
47
|
+
return block()
|
|
48
|
+
} finally {
|
|
49
|
+
phase = previous
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|