react-native-enriched-markdown-scaffold 0.7.4-scaffold.8 → 1.0.2-scaffold.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +54 -8
- package/ReactNativeEnrichedMarkdown.podspec +82 -73
- package/android/build.gradle +191 -1
- package/android/consumer-rules.pro +1 -1
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownManagerDelegate.java +9 -0
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownManagerInterface.java +3 -0
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextInputManagerDelegate.java +27 -0
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextInputManagerInterface.java +9 -0
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextManagerDelegate.java +9 -0
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextManagerInterface.java +3 -0
- package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/EventEmitters.cpp +75 -0
- package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/EventEmitters.h +63 -0
- package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/Props.cpp +40 -0
- package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/Props.h +839 -23
- package/android/src/main/baseline-prof.txt +1 -1
- package/android/src/main/cpp/jni-adapter.cpp +74 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdown.kt +175 -11
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownInternalText.kt +17 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownManager.kt +50 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownText.kt +48 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownTextLayoutManager.kt +10 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownTextManager.kt +42 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/MeasurementStore.kt +82 -4
- package/android/src/main/java/com/swmansion/enriched/markdown/events/CopyPressEvent.kt +24 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/EnrichedMarkdownTextInputManager.kt +62 -4
- package/android/src/main/java/com/swmansion/enriched/markdown/input/EnrichedMarkdownTextInputView.kt +911 -460
- package/android/src/main/java/com/swmansion/enriched/markdown/input/MarkdownClipboard.kt +42 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/BlockEditCoordinator.kt +196 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/ClipboardCoordinator.kt +73 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/EditContext.kt +19 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/EditPipeline.kt +248 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/EditSession.kt +52 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/InputConnectionWrapper.kt +101 -7
- package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/LinkCoordinator.kt +69 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/MarkdownTextWatcher.kt +3 -3
- package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/MentionCoordinator.kt +118 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnChangeStateEvent.kt +26 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnContextMenuItemPressEvent.kt +26 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnInputKeyPressEvent.kt +24 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnPasteEvent.kt +24 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/BlockStore.kt +254 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/BlockSyntaxSentinel.kt +69 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/FormattingStore.kt +80 -87
- package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/InputFormatter.kt +109 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/InputParser.kt +180 -27
- package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/MarkdownSerializer.kt +167 -38
- package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/RangeEditAdjustment.kt +149 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/layout/InputEventEmitter.kt +66 -5
- package/android/src/main/java/com/swmansion/enriched/markdown/input/layout/InputMeasurementStore.kt +7 -2
- package/android/src/main/java/com/swmansion/enriched/markdown/input/model/BlockRange.kt +27 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/model/BlockType.kt +48 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/model/FormattingRange.kt +9 -4
- package/android/src/main/java/com/swmansion/enriched/markdown/input/model/InputFormatterStyle.kt +39 -2
- package/android/src/main/java/com/swmansion/enriched/markdown/input/model/MathAtom.kt +20 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/model/MathChipStyle.kt +1 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/input/model/MutableRangeBounds.kt +11 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/spans/InputBulletSpan.kt +82 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/spans/InputHeadingSpan.kt +58 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/spans/InputListItemSpacingSpan.kt +37 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/spans/InputOrderedListMarkerSpan.kt +63 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/styles/BlockHandler.kt +54 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/styles/HeadingBlockHandler.kt +27 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/styles/OrderedListBlockHandler.kt +38 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/styles/UnorderedListBlockHandler.kt +37 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/toolbar/InputContextMenu.kt +8 -26
- package/android/src/main/java/com/swmansion/enriched/markdown/parser/MarkdownASTNode.kt +1 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/parser/Parser.kt +1 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/BlockStyleContext.kt +9 -2
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/BlockquoteRenderer.kt +100 -12
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/CodeBlockRenderer.kt +16 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/HeadingRenderer.kt +4 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListContextManager.kt +2 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListItemRenderer.kt +74 -18
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListRenderer.kt +43 -4
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/NodeRenderer.kt +9 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/SoftBreakRenderer.kt +16 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/SpanStyleCache.kt +30 -27
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/BaseListSpan.kt +24 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/BlockquoteSpan.kt +174 -24
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/CodeBackgroundSpan.kt +27 -3
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/CodeBlockSpan.kt +13 -16
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/CodeSpan.kt +1 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/EmphasisSpan.kt +1 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/ImageSpan.kt +182 -46
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/ListItemSpacingSpan.kt +33 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/ListMarkerAnchorSpan.kt +38 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/OrderedListSpan.kt +2 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/StrongSpan.kt +1 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/TaskListSpan.kt +3 -2
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/UnorderedListSpan.kt +3 -2
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/BlockquoteStyle.kt +6 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/CodeBlockStyle.kt +26 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/ImageStyle.kt +7 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/ListStyle.kt +4 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/StyleConfig.kt +13 -4
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/TableStyle.kt +6 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/CodeBlockHighlighter.kt +90 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/CodeBlockNode.kt +57 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/FeatureFlags.kt +1 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/MarkdownSegment.kt +9 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/MarkdownViewManagerUtils.kt +33 -7
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/ReadableMapExtensions.kt +3 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/RenderedSegment.kt +10 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/SegmentSignature.kt +1 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/StreamingMarkdownFilter.kt +83 -5
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/serialization/MarkdownASTSerializer.kt +4 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/input/MarkdownStyleParser.kt +74 -44
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/input/PasteTextUtils.kt +20 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/ImageCache.kt +26 -3
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/ImageDownloader.kt +22 -9
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/LocalImageLoader.kt +161 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/extensions/TextPaintExtensions.kt +23 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/interaction/CheckboxTouchHelper.kt +7 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/interaction/TaskListTapUtils.kt +41 -21
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/span/BlockSpacing.kt +15 -8
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/LinkLongPressMovementMethod.kt +58 -27
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/SelectionActionMode.kt +19 -2
- package/android/src/main/java/com/swmansion/enriched/markdown/views/CodeBlockContainerView.kt +388 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/views/ContextMenuPopup.kt +9 -6
- package/android/src/main/java/com/swmansion/enriched/markdown/views/CopyGlyph.kt +101 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/views/TableContainerView.kt +32 -5
- package/android/src/main/jni/CMakeLists.txt +53 -0
- package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownContainerShadowNode.cpp +10 -0
- package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownContainerShadowNode.h +11 -2
- package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextShadowNode.cpp +10 -0
- package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextShadowNode.h +12 -2
- package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextState.cpp +9 -0
- package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextState.h +24 -0
- package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/conversions.h +16 -0
- package/android/src/math/java/com/swmansion/enriched/markdown/input/math/MathChipControllerImpl.kt +21 -4
- package/android/src/math/java/com/swmansion/enriched/markdown/renderer/MathInlineRenderer.kt +7 -2
- package/android/src/math/java/com/swmansion/enriched/markdown/spans/MathChipSpan.kt +1 -1
- package/android/src/math/java/com/swmansion/enriched/markdown/views/MathContainerView.kt +2 -0
- package/cpp/highlight/CodeBlockHighlighter.cpp +284 -0
- package/cpp/highlight/CodeBlockHighlighter.hpp +66 -0
- package/cpp/highlight/CodeBlockLanguages.cpp +138 -0
- package/cpp/highlight/CodeBlockLanguages.hpp +25 -0
- package/cpp/highlight/HighlightGrammars.hpp +28 -0
- package/cpp/highlight/code_highlight_podspec.rb +211 -0
- package/cpp/highlight/gen-registry.mjs +155 -0
- package/cpp/highlight/grammar-versions.json +159 -0
- package/cpp/highlight/vendor/generated/generated_queries.h +1665 -0
- package/cpp/highlight/vendor/generated/generated_registry.cpp +59 -0
- package/cpp/parser/MD4CParser.cpp +173 -61
- package/cpp/parser/MD4CParser.hpp +1 -0
- package/cpp/parser/MarkdownASTNode.hpp +2 -1
- package/cpp/wasm/ASTSerializer.cpp +2 -0
- package/cpp/wasm/build.sh +1 -0
- package/cpp/wasm/md4c_wasm.cpp +3 -1
- package/docs/ACCESSIBILITY.md +14 -2
- package/docs/API_REFERENCE.md +231 -8
- package/docs/BREAKING_CHANGES.md +129 -0
- package/docs/CODE_HIGHLIGHT.md +133 -0
- package/docs/COPY_OPTIONS.md +21 -3
- package/docs/ELEMENTS_STRUCTURE.md +52 -4
- package/docs/IMAGE_CACHING.md +30 -0
- package/docs/INPUT.md +146 -5
- package/docs/LATEX_MATH.md +87 -45
- package/docs/MACOS.md +1 -1
- package/docs/MARKDOWN_STREAMING.md +27 -1
- package/docs/NATIVE_ASSETS.md +127 -0
- package/docs/RTL.md +1 -1
- package/docs/STYLES.md +46 -6
- package/docs/TESTING.md +112 -0
- package/docs/TEXT.md +16 -6
- package/docs/WEB.md +3 -1
- package/ios/EnrichedMarkdown.h +7 -0
- package/ios/EnrichedMarkdown.mm +262 -67
- package/ios/EnrichedMarkdownText.h +7 -0
- package/ios/EnrichedMarkdownText.mm +97 -68
- package/ios/attachments/ENRMImageAttachment.h +9 -0
- package/ios/attachments/ENRMImageAttachment.m +143 -40
- package/ios/attachments/ENRMMathInlineAttachment.h +2 -0
- package/ios/attachments/ENRMMathInlineAttachment.m +48 -81
- package/ios/attachments/ENRMMathInlineAttachmentShared.h +2 -0
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/EventEmitters.cpp +75 -0
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/EventEmitters.h +63 -0
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/Props.cpp +40 -0
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/Props.h +839 -23
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/RCTComponentViewHelpers.h +131 -0
- package/ios/input/ENRMAutoLinkDetector.h +2 -1
- package/ios/input/ENRMAutoLinkDetector.mm +79 -41
- package/ios/input/ENRMBlockEditCoordinator.h +71 -0
- package/ios/input/ENRMBlockEditCoordinator.mm +195 -0
- package/ios/input/ENRMBlockRange.h +28 -0
- package/ios/input/ENRMBlockRange.mm +30 -0
- package/ios/input/ENRMBlockStore.h +56 -0
- package/ios/input/ENRMBlockStore.mm +275 -0
- package/ios/input/ENRMBlockSyntaxSentinel.h +25 -0
- package/ios/input/ENRMBlockSyntaxSentinel.mm +80 -0
- package/ios/input/ENRMClipboardCoordinator.h +45 -0
- package/ios/input/ENRMClipboardCoordinator.mm +120 -0
- package/ios/input/ENRMDetectorPipeline.h +2 -1
- package/ios/input/ENRMEditPipeline.h +76 -0
- package/ios/input/ENRMEditPipeline.mm +228 -0
- package/ios/input/ENRMEditSession.h +36 -0
- package/ios/input/ENRMEditSession.mm +63 -0
- package/ios/input/ENRMFormattingStore.h +17 -0
- package/ios/input/ENRMFormattingStore.mm +95 -105
- package/ios/input/ENRMInputBlockType.h +91 -0
- package/ios/input/ENRMInputBlockType.mm +5 -0
- package/ios/input/ENRMInputDecorationDrawer.h +18 -0
- package/ios/input/ENRMInputEventEmitter.h +56 -0
- package/ios/input/ENRMInputEventEmitter.mm +308 -0
- package/ios/input/ENRMInputFormatter.h +29 -69
- package/ios/input/ENRMInputFormatter.mm +216 -124
- package/ios/input/ENRMInputFormatterStyle.h +99 -0
- package/ios/input/ENRMInputFormatterStyle.mm +188 -0
- package/ios/input/ENRMInputLayoutManager.h +9 -0
- package/ios/input/ENRMInputLayoutManager.mm +30 -0
- package/ios/input/ENRMInputListMarkerDrawer.h +32 -0
- package/ios/input/ENRMInputListMarkerDrawer.mm +426 -0
- package/ios/input/ENRMInputParser.h +10 -6
- package/ios/input/ENRMInputParser.mm +527 -171
- package/ios/input/ENRMInputRemend.mm +2 -2
- package/ios/input/ENRMInputStyleStateBuilder.h +40 -0
- package/ios/input/ENRMInputStyleStateBuilder.mm +60 -0
- package/ios/input/ENRMInputTextView.mm +103 -8
- package/ios/input/ENRMInputTypingAttributesController.h +42 -0
- package/ios/input/ENRMInputTypingAttributesController.mm +203 -0
- package/ios/input/ENRMLinkCoordinator.h +41 -0
- package/ios/input/ENRMLinkCoordinator.mm +89 -0
- package/ios/input/ENRMMarkdownSerializer.h +29 -5
- package/ios/input/ENRMMarkdownSerializer.mm +170 -48
- package/ios/input/ENRMMathAtom.h +26 -0
- package/ios/input/ENRMMathAtom.mm +12 -0
- package/ios/input/ENRMMentionCoordinator.h +45 -0
- package/ios/input/ENRMMentionCoordinator.mm +167 -0
- package/ios/input/ENRMRangeEditAdjustment.h +38 -0
- package/ios/input/ENRMRangeEditAdjustment.mm +91 -0
- package/ios/input/ENRMRangeStoreUtils.h +39 -0
- package/ios/input/EnrichedMarkdownTextInput+ContextMenu.mm +6 -6
- package/ios/input/EnrichedMarkdownTextInput+Internal.h +11 -3
- package/ios/input/EnrichedMarkdownTextInput.h +7 -1
- package/ios/input/EnrichedMarkdownTextInput.mm +1104 -1024
- package/ios/input/InputStylePropsUtils.h +109 -68
- package/ios/input/internals/EnrichedMarkdownTextInputShadowNode.mm +2 -1
- package/ios/input/styles/ENRMBlockHandler.h +46 -0
- package/ios/input/styles/ENRMHeadingBlockHandler.h +15 -0
- package/ios/input/styles/ENRMHeadingBlockHandler.mm +38 -0
- package/ios/input/styles/ENRMOrderedListBlockHandler.h +14 -0
- package/ios/input/styles/ENRMOrderedListBlockHandler.mm +48 -0
- package/ios/input/styles/ENRMUnorderedListBlockHandler.h +15 -0
- package/ios/input/styles/ENRMUnorderedListBlockHandler.mm +51 -0
- package/ios/internals/ENRMViewFreeMeasurement.h +331 -0
- package/ios/internals/EnrichedMarkdownShadowNode.h +1 -3
- package/ios/internals/EnrichedMarkdownShadowNode.mm +16 -20
- package/ios/internals/EnrichedMarkdownTextShadowNode.h +1 -3
- package/ios/internals/EnrichedMarkdownTextShadowNode.mm +15 -20
- package/ios/internals/MeasurementCache.h +33 -7
- package/ios/internals/ShadowMeasurementUtils.h +63 -58
- package/ios/math/ENRMMathChipController.h +74 -0
- package/ios/math/ENRMMathChipController.mm +476 -0
- package/ios/math/ENRMRaTeXBridge.swift +4 -1
- package/ios/parser/ENRMMarkdownParser.h +1 -8
- package/ios/parser/ENRMMarkdownParser.mm +2 -11
- package/ios/parser/MarkdownASTNode.h +2 -1
- package/ios/parser/MarkdownParserBridge.mm +4 -0
- package/ios/renderer/AttributedRenderer.m +20 -2
- package/ios/renderer/BaseRenderer.h +17 -2
- package/ios/renderer/BaseRenderer.m +30 -0
- package/ios/renderer/BlockquoteRenderer.h +1 -1
- package/ios/renderer/BlockquoteRenderer.m +144 -35
- package/ios/renderer/CodeBlockRenderer.h +1 -1
- package/ios/renderer/CodeBlockRenderer.m +27 -23
- package/ios/renderer/CodeRenderer.h +1 -1
- package/ios/renderer/CodeRenderer.m +3 -1
- package/ios/renderer/ENRMImageRenderer.h +1 -1
- package/ios/renderer/ENRMImageRenderer.m +5 -1
- package/ios/renderer/ENRMMathInlineRenderer.h +1 -1
- package/ios/renderer/ENRMMathInlineRenderer.m +5 -1
- package/ios/renderer/ENRMSpoilerRenderer.h +1 -1
- package/ios/renderer/ENRMSpoilerRenderer.m +3 -1
- package/ios/renderer/EmphasisRenderer.h +1 -1
- package/ios/renderer/EmphasisRenderer.m +3 -1
- package/ios/renderer/HeadingRenderer.h +1 -1
- package/ios/renderer/HeadingRenderer.m +13 -6
- package/ios/renderer/HighlightRenderer.h +1 -1
- package/ios/renderer/HighlightRenderer.m +3 -1
- package/ios/renderer/LinkRenderer.h +1 -1
- package/ios/renderer/LinkRenderer.m +3 -1
- package/ios/renderer/ListItemRenderer.h +13 -1
- package/ios/renderer/ListItemRenderer.m +102 -44
- package/ios/renderer/ListRenderer.h +2 -2
- package/ios/renderer/ListRenderer.m +63 -25
- package/ios/renderer/ParagraphRenderer.h +1 -1
- package/ios/renderer/ParagraphRenderer.m +16 -8
- package/ios/renderer/RenderContext.h +10 -0
- package/ios/renderer/RenderContext.m +44 -0
- package/ios/renderer/RendererFactory.m +14 -0
- package/ios/renderer/StrikethroughRenderer.h +1 -1
- package/ios/renderer/StrikethroughRenderer.m +3 -1
- package/ios/renderer/StrongRenderer.h +1 -1
- package/ios/renderer/StrongRenderer.m +3 -1
- package/ios/renderer/SubscriptRenderer.h +1 -1
- package/ios/renderer/SubscriptRenderer.m +3 -1
- package/ios/renderer/SuperscriptRenderer.h +1 -1
- package/ios/renderer/SuperscriptRenderer.m +3 -1
- package/ios/renderer/TextRenderer.h +2 -2
- package/ios/renderer/TextRenderer.m +3 -1
- package/ios/renderer/ThematicBreakRenderer.h +1 -1
- package/ios/renderer/ThematicBreakRenderer.m +3 -1
- package/ios/renderer/UnderlineRenderer.h +1 -1
- package/ios/renderer/UnderlineRenderer.m +3 -1
- package/ios/styles/StyleConfig.h +22 -0
- package/ios/styles/StyleConfig.mm +132 -0
- package/ios/utils/BlockquoteBorder.h +6 -0
- package/ios/utils/BlockquoteBorder.m +249 -52
- package/ios/utils/CodeBlockBackground.m +16 -2
- package/ios/utils/ENRMAtomicSize.h +65 -0
- package/ios/utils/ENRMCodeBlockContent.h +37 -0
- package/ios/utils/ENRMCodeBlockContent.mm +79 -0
- package/ios/utils/ENRMCodeBlockHighlighter.h +37 -0
- package/ios/utils/ENRMCodeBlockHighlighter.mm +51 -0
- package/ios/utils/ENRMFeatureFlags.h +7 -0
- package/ios/utils/ENRMImageDownloader.h +11 -1
- package/ios/utils/ENRMImageDownloader.m +60 -16
- package/ios/utils/ENRMLocalImageLoader.h +31 -0
- package/ios/utils/ENRMLocalImageLoader.m +68 -0
- package/ios/utils/ENRMMathFallback.h +26 -0
- package/ios/utils/ENRMMathFallback.m +18 -0
- package/ios/utils/ENRMTextViewSetup.h +35 -17
- package/ios/utils/EditMenuUtils.m +22 -1
- package/ios/utils/ImageRequestHeaderUtils.h +35 -0
- package/ios/utils/LastElementUtils.h +1 -0
- package/ios/utils/ListMarkerDrawer.m +29 -42
- package/ios/utils/MarkdownASTSerializer.m +4 -0
- package/ios/utils/ParagraphStyleUtils.h +5 -0
- package/ios/utils/ParagraphStyleUtils.m +77 -17
- package/ios/utils/RenderedMarkdownSegment.h +13 -1
- package/ios/utils/RenderedMarkdownSegment.m +20 -0
- package/ios/utils/SegmentRenderer.m +17 -4
- package/ios/utils/StreamingMarkdownFilter.h +11 -1
- package/ios/utils/StreamingMarkdownFilter.m +98 -2
- package/ios/utils/StylePropsUtils.h +63 -0
- package/ios/utils/TaskListTapUtils.m +24 -0
- package/ios/views/ENRMCodeBlockContainerView.h +46 -0
- package/ios/views/ENRMCodeBlockContainerView.m +566 -0
- package/ios/views/ENRMMathContainerView.h +12 -0
- package/ios/views/ENRMMathContainerView.m +71 -1
- package/ios/views/TableContainerView.h +18 -0
- package/ios/views/TableContainerView.m +259 -159
- package/jest.d.ts +1 -0
- package/jest.js +5 -0
- package/lib/module/EnrichedMarkdownNativeComponent.ts +65 -0
- package/lib/module/EnrichedMarkdownTextInput.js +86 -5
- package/lib/module/EnrichedMarkdownTextInput.js.map +1 -1
- package/lib/module/EnrichedMarkdownTextInputNativeComponent.ts +89 -5
- package/lib/module/EnrichedMarkdownTextNativeComponent.ts +66 -0
- package/lib/module/headingDefaults.js +34 -0
- package/lib/module/headingDefaults.js.map +1 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/jest/index.js +191 -0
- package/lib/module/jest/index.js.map +1 -0
- package/lib/module/native/EnrichedMarkdownText.js +30 -4
- package/lib/module/native/EnrichedMarkdownText.js.map +1 -1
- package/lib/module/normalizeMarkdownStyle.js +81 -19
- package/lib/module/normalizeMarkdownStyle.js.map +1 -1
- package/lib/module/normalizeMarkdownStyle.web.js +56 -18
- package/lib/module/normalizeMarkdownStyle.web.js.map +1 -1
- package/lib/module/normalizeMarkdownTextInputStyle.js +62 -15
- package/lib/module/normalizeMarkdownTextInputStyle.js.map +1 -1
- package/lib/module/normalizeMenuItem.js +1 -1
- package/lib/module/utils/textInputState.js +26 -0
- package/lib/module/utils/textInputState.js.map +1 -0
- package/lib/module/web/EnrichedMarkdownText.js +9 -5
- package/lib/module/web/EnrichedMarkdownText.js.map +1 -1
- package/lib/module/web/parseMarkdown.js +4 -3
- package/lib/module/web/parseMarkdown.js.map +1 -1
- package/lib/module/web/renderers/InlineRenderers.js +6 -0
- package/lib/module/web/renderers/InlineRenderers.js.map +1 -1
- package/lib/module/web/renderers/ListRenderers.js +7 -2
- package/lib/module/web/renderers/ListRenderers.js.map +1 -1
- package/lib/module/web/renderers/index.js +7 -4
- package/lib/module/web/renderers/index.js.map +1 -1
- package/lib/module/web/styles.js +83 -6
- package/lib/module/web/styles.js.map +1 -1
- package/lib/module/web/utils.js +1 -0
- package/lib/module/web/utils.js.map +1 -1
- package/lib/module/web/wasm/md4c.js +0 -0
- package/lib/module/web/wasm/md4c.js.map +1 -1
- package/lib/typescript/src/EnrichedMarkdownNativeComponent.d.ts +62 -0
- package/lib/typescript/src/EnrichedMarkdownNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/EnrichedMarkdownTextInput.d.ts +95 -9
- package/lib/typescript/src/EnrichedMarkdownTextInput.d.ts.map +1 -1
- package/lib/typescript/src/EnrichedMarkdownTextInputNativeComponent.d.ts +80 -5
- package/lib/typescript/src/EnrichedMarkdownTextInputNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/EnrichedMarkdownTextNativeComponent.d.ts +62 -0
- package/lib/typescript/src/EnrichedMarkdownTextNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/headingDefaults.d.ts +9 -0
- package/lib/typescript/src/headingDefaults.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +2 -2
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/index.web.d.ts +1 -1
- package/lib/typescript/src/index.web.d.ts.map +1 -1
- package/lib/typescript/src/jest/index.d.ts +6 -0
- package/lib/typescript/src/jest/index.d.ts.map +1 -0
- package/lib/typescript/src/native/EnrichedMarkdownText.d.ts +3 -3
- package/lib/typescript/src/native/EnrichedMarkdownText.d.ts.map +1 -1
- package/lib/typescript/src/normalizeMarkdownStyle.d.ts.map +1 -1
- package/lib/typescript/src/normalizeMarkdownStyle.web.d.ts.map +1 -1
- package/lib/typescript/src/normalizeMarkdownTextInputStyle.d.ts +19 -5
- package/lib/typescript/src/normalizeMarkdownTextInputStyle.d.ts.map +1 -1
- package/lib/typescript/src/types/MarkdownStyle.d.ts +72 -0
- package/lib/typescript/src/types/MarkdownStyle.d.ts.map +1 -1
- package/lib/typescript/src/types/MarkdownStyleInternal.d.ts +27 -0
- package/lib/typescript/src/types/MarkdownStyleInternal.d.ts.map +1 -1
- package/lib/typescript/src/types/MarkdownTextProps.d.ts +65 -1
- package/lib/typescript/src/types/MarkdownTextProps.d.ts.map +1 -1
- package/lib/typescript/src/types/MarkdownTextProps.web.d.ts +19 -0
- package/lib/typescript/src/types/MarkdownTextProps.web.d.ts.map +1 -1
- package/lib/typescript/src/types/events.d.ts +19 -0
- package/lib/typescript/src/types/events.d.ts.map +1 -1
- package/lib/typescript/src/utils/textInputState.d.ts +24 -0
- package/lib/typescript/src/utils/textInputState.d.ts.map +1 -0
- package/lib/typescript/src/web/EnrichedMarkdownText.d.ts +1 -1
- package/lib/typescript/src/web/EnrichedMarkdownText.d.ts.map +1 -1
- package/lib/typescript/src/web/parseMarkdown.d.ts +1 -1
- package/lib/typescript/src/web/parseMarkdown.d.ts.map +1 -1
- package/lib/typescript/src/web/renderers/InlineRenderers.d.ts.map +1 -1
- package/lib/typescript/src/web/renderers/ListRenderers.d.ts.map +1 -1
- package/lib/typescript/src/web/renderers/index.d.ts +2 -1
- package/lib/typescript/src/web/renderers/index.d.ts.map +1 -1
- package/lib/typescript/src/web/styles.d.ts +2 -1
- package/lib/typescript/src/web/styles.d.ts.map +1 -1
- package/lib/typescript/src/web/types.d.ts +6 -2
- package/lib/typescript/src/web/types.d.ts.map +1 -1
- package/lib/typescript/src/web/utils.d.ts.map +1 -1
- package/package.json +36 -9
- package/postinstall.mjs +131 -0
- package/ratex-version.json +21 -0
- package/src/EnrichedMarkdownNativeComponent.ts +65 -0
- package/src/EnrichedMarkdownTextInput.tsx +162 -8
- package/src/EnrichedMarkdownTextInputNativeComponent.ts +89 -5
- package/src/EnrichedMarkdownTextNativeComponent.ts +66 -0
- package/src/headingDefaults.ts +21 -0
- package/src/index.tsx +9 -0
- package/src/index.web.tsx +1 -0
- package/src/jest/index.tsx +215 -0
- package/src/native/EnrichedMarkdownText.tsx +40 -2
- package/src/normalizeMarkdownStyle.ts +102 -16
- package/src/normalizeMarkdownStyle.web.ts +63 -15
- package/src/normalizeMarkdownTextInputStyle.ts +110 -35
- package/src/normalizeMenuItem.ts +1 -1
- package/src/types/MarkdownStyle.ts +74 -0
- package/src/types/MarkdownStyleInternal.ts +39 -0
- package/src/types/MarkdownTextProps.ts +65 -0
- package/src/types/MarkdownTextProps.web.ts +19 -0
- package/src/types/events.ts +21 -0
- package/src/utils/textInputState.ts +35 -0
- package/src/web/EnrichedMarkdownText.tsx +16 -2
- package/src/web/parseMarkdown.ts +6 -2
- package/src/web/renderers/InlineRenderers.tsx +5 -0
- package/src/web/renderers/ListRenderers.tsx +14 -2
- package/src/web/renderers/index.tsx +6 -2
- package/src/web/styles.ts +89 -5
- package/src/web/types.ts +6 -1
- package/src/web/utils.ts +1 -0
- package/src/web/wasm/md4c.js +0 -0
- package/vendor-grammars.mjs +511 -0
- package/vendor-ratex.mjs +173 -0
- package/app.plugin.js +0 -2
- package/plugin/build/withAndroidMath.js +0 -19
- package/plugin/build/withIosMath.js +0 -28
- package/plugin/build/withReactNativeEnrichedMarkdown.js +0 -11
- package/plugin/src/withAndroidMath.ts +0 -24
- package/plugin/src/withIosMath.ts +0 -35
- package/plugin/src/withReactNativeEnrichedMarkdown.ts +0 -17
- package/plugin/tsconfig.build.json +0 -16
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#import "ENRMBlockRange.h"
|
|
4
|
+
|
|
5
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
6
|
+
|
|
7
|
+
/// Stores the block-level (paragraph-scoped) ranges for the editor, mirroring
|
|
8
|
+
/// ENRMFormattingStore. Unlike inline ranges, block ranges never overlap: at
|
|
9
|
+
/// most one block covers any given paragraph, and ranges are kept normalized to
|
|
10
|
+
/// whole-line boundaries.
|
|
11
|
+
@interface ENRMBlockStore : NSObject
|
|
12
|
+
|
|
13
|
+
@property (nonatomic, readonly) NSArray<ENRMBlockRange *> *allRanges;
|
|
14
|
+
|
|
15
|
+
/// Returns the block whose paragraph starts exactly at `location`, or nil.
|
|
16
|
+
/// Ranges are kept sorted by start, so this is an O(log n) binary search — the
|
|
17
|
+
/// single lookup callers use instead of linearly scanning `allRanges`. Relies on
|
|
18
|
+
/// the one-block-per-paragraph invariant (paragraph starts are unique).
|
|
19
|
+
- (nullable ENRMBlockRange *)blockStartingAtLocation:(NSUInteger)location;
|
|
20
|
+
|
|
21
|
+
- (void)setRanges:(NSArray<ENRMBlockRange *> *)ranges;
|
|
22
|
+
- (void)clearAll;
|
|
23
|
+
|
|
24
|
+
/// Sets/replaces the block on every paragraph the given range touches, expanding
|
|
25
|
+
/// to whole-line boundaries within `text`. Removes any block previously covering
|
|
26
|
+
/// those paragraphs.
|
|
27
|
+
- (void)setBlockType:(ENRMInputBlockType)type
|
|
28
|
+
level:(NSInteger)level
|
|
29
|
+
forParagraphRange:(NSRange)range
|
|
30
|
+
inText:(NSString *)text;
|
|
31
|
+
|
|
32
|
+
/// Clears any block on the paragraphs the given range touches (reverting them to
|
|
33
|
+
/// the implicit paragraph default).
|
|
34
|
+
- (void)removeBlockInParagraphRange:(NSRange)range inText:(NSString *)text;
|
|
35
|
+
|
|
36
|
+
/// Shifts/clips block ranges to follow a text edit (shared
|
|
37
|
+
/// ENRMRangeEditAdjustment classification), with heading persistence: a heading
|
|
38
|
+
/// deleted exactly to its end collapses to a zero-length anchor at the edit
|
|
39
|
+
/// location (its line survives), and existing anchors shift/keep/drop with
|
|
40
|
+
/// their line.
|
|
41
|
+
- (void)adjustForEditAtLocation:(NSUInteger)location
|
|
42
|
+
deletedLength:(NSUInteger)deletedLength
|
|
43
|
+
insertedLength:(NSUInteger)insertedLength;
|
|
44
|
+
|
|
45
|
+
/// Snaps every stored range to the line bounds of its start position.
|
|
46
|
+
/// Absorbs edge-typed chars, clips split ranges to first line, drops
|
|
47
|
+
/// duplicates. On an empty line a heading persists as a zero-length anchor;
|
|
48
|
+
/// any other collapsed range is dropped. List depths are clamped so an item
|
|
49
|
+
/// nests at most one level under the previous adjacent item (CommonMark cannot
|
|
50
|
+
/// represent orphan nesting). Call after adjustForEditAtLocation: once text is
|
|
51
|
+
/// final. Idempotent.
|
|
52
|
+
- (void)normalizeToLineBoundsInText:(NSString *)text;
|
|
53
|
+
|
|
54
|
+
@end
|
|
55
|
+
|
|
56
|
+
NS_ASSUME_NONNULL_END
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
#import "ENRMBlockStore.h"
|
|
2
|
+
#import "ENRMRangeEditAdjustment.h"
|
|
3
|
+
#import "ENRMRangeStoreUtils.h"
|
|
4
|
+
|
|
5
|
+
/// Expands a selection to cover whole paragraphs (line-scoped block boundaries).
|
|
6
|
+
/// Clamps unconditionally so out-of-bounds input can't reach
|
|
7
|
+
/// paragraphRangeForRange: (which raises on an invalid range).
|
|
8
|
+
static NSRange paragraphBoundsForRange(NSRange range, NSString *text)
|
|
9
|
+
{
|
|
10
|
+
if (text.length == 0) {
|
|
11
|
+
return NSMakeRange(0, 0);
|
|
12
|
+
}
|
|
13
|
+
NSUInteger location = MIN(range.location, text.length);
|
|
14
|
+
NSUInteger length = MIN(range.length, text.length - location);
|
|
15
|
+
return [text paragraphRangeForRange:NSMakeRange(location, length)];
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
@implementation ENRMBlockStore {
|
|
19
|
+
NSMutableArray<ENRMBlockRange *> *_ranges;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
- (instancetype)init
|
|
23
|
+
{
|
|
24
|
+
if (self = [super init]) {
|
|
25
|
+
_ranges = [NSMutableArray array];
|
|
26
|
+
}
|
|
27
|
+
return self;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
- (NSArray<ENRMBlockRange *> *)allRanges
|
|
31
|
+
{
|
|
32
|
+
return [_ranges copy];
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
- (nullable ENRMBlockRange *)blockStartingAtLocation:(NSUInteger)location
|
|
36
|
+
{
|
|
37
|
+
NSInteger lo = 0;
|
|
38
|
+
NSInteger hi = (NSInteger)_ranges.count - 1;
|
|
39
|
+
while (lo <= hi) {
|
|
40
|
+
NSInteger mid = (lo + hi) / 2;
|
|
41
|
+
NSUInteger start = _ranges[(NSUInteger)mid].range.location;
|
|
42
|
+
if (start < location) {
|
|
43
|
+
lo = mid + 1;
|
|
44
|
+
} else if (start > location) {
|
|
45
|
+
hi = mid - 1;
|
|
46
|
+
} else {
|
|
47
|
+
return _ranges[(NSUInteger)mid];
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return nil;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Incoming ranges are trusted to be non-overlapping and line-scoped — the
|
|
54
|
+
// parser owns that invariant (md4c block structure never overlaps at the same
|
|
55
|
+
// nesting level, and nested containers are not yet mapped). Revisit enforcement
|
|
56
|
+
// here if a container block type (list, blockquote) is added.
|
|
57
|
+
- (void)setRanges:(NSArray<ENRMBlockRange *> *)ranges
|
|
58
|
+
{
|
|
59
|
+
_ranges = [[ranges sortedArrayUsingComparator:^NSComparisonResult(ENRMBlockRange *first, ENRMBlockRange *second) {
|
|
60
|
+
if (first.range.location < second.range.location)
|
|
61
|
+
return NSOrderedAscending;
|
|
62
|
+
if (first.range.location > second.range.location)
|
|
63
|
+
return NSOrderedDescending;
|
|
64
|
+
return NSOrderedSame;
|
|
65
|
+
}] mutableCopy];
|
|
66
|
+
[self recomputeListMetadata];
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
- (void)clearAll
|
|
70
|
+
{
|
|
71
|
+
[_ranges removeAllObjects];
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/// Drops any stored block overlapping `paragraphRange` so a replacement can be
|
|
75
|
+
/// inserted cleanly. Blocks are line-scoped and never partially overlap, so a
|
|
76
|
+
/// touched block is removed wholesale.
|
|
77
|
+
- (void)removeBlocksOverlappingRange:(NSRange)paragraphRange
|
|
78
|
+
{
|
|
79
|
+
NSUInteger removeStart = paragraphRange.location;
|
|
80
|
+
NSUInteger removeEnd = NSMaxRange(paragraphRange);
|
|
81
|
+
NSMutableIndexSet *indexesToRemove = [NSMutableIndexSet indexSet];
|
|
82
|
+
|
|
83
|
+
for (NSUInteger idx = 0; idx < _ranges.count; idx++) {
|
|
84
|
+
ENRMBlockRange *existing = _ranges[idx];
|
|
85
|
+
NSUInteger existingStart = existing.range.location;
|
|
86
|
+
NSUInteger existingEnd = NSMaxRange(existing.range);
|
|
87
|
+
|
|
88
|
+
// A zero-length anchor occupies a point, so the half-open overlap test
|
|
89
|
+
// never matches it; drop one whose anchor lies within the removal bounds.
|
|
90
|
+
if (existing.range.length == 0) {
|
|
91
|
+
if (existingStart >= removeStart && existingStart <= removeEnd) {
|
|
92
|
+
[indexesToRemove addIndex:idx];
|
|
93
|
+
}
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (existingEnd <= removeStart || existingStart >= removeEnd) {
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
[indexesToRemove addIndex:idx];
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
ENRMRemoveIndexesInReverse(_ranges, indexesToRemove);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
- (void)setBlockType:(ENRMInputBlockType)type
|
|
107
|
+
level:(NSInteger)level
|
|
108
|
+
forParagraphRange:(NSRange)range
|
|
109
|
+
inText:(NSString *)text
|
|
110
|
+
{
|
|
111
|
+
NSRange paragraphRange = paragraphBoundsForRange(range, text);
|
|
112
|
+
[self removeBlocksOverlappingRange:paragraphRange];
|
|
113
|
+
|
|
114
|
+
paragraphRange = ENRMTrimLineTerminators(paragraphRange, text);
|
|
115
|
+
|
|
116
|
+
if (paragraphRange.length == 0 && !ENRMBlockTypePersistsWhenEmpty(type)) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
ENRMBlockRange *blockRange = [ENRMBlockRange rangeWithType:type range:paragraphRange level:level];
|
|
121
|
+
NSUInteger insertAt = ENRMSortedInsertionIndex(
|
|
122
|
+
_ranges, blockRange.range.location, ^NSUInteger(id range) { return ((ENRMBlockRange *)range).range.location; });
|
|
123
|
+
[_ranges insertObject:blockRange atIndex:insertAt];
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
- (void)removeBlockInParagraphRange:(NSRange)range inText:(NSString *)text
|
|
127
|
+
{
|
|
128
|
+
NSRange paragraphRange = paragraphBoundsForRange(range, text);
|
|
129
|
+
[self removeBlocksOverlappingRange:paragraphRange];
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
- (void)adjustForEditAtLocation:(NSUInteger)editLocation
|
|
133
|
+
deletedLength:(NSUInteger)deletedLength
|
|
134
|
+
insertedLength:(NSUInteger)insertedLength
|
|
135
|
+
{
|
|
136
|
+
if (deletedLength == 0 && insertedLength == 0)
|
|
137
|
+
return;
|
|
138
|
+
|
|
139
|
+
NSUInteger deleteEnd = editLocation + deletedLength;
|
|
140
|
+
NSMutableIndexSet *indexesToRemove = [NSMutableIndexSet indexSet];
|
|
141
|
+
|
|
142
|
+
for (NSUInteger idx = 0; idx < _ranges.count; idx++) {
|
|
143
|
+
ENRMBlockRange *blockRange = _ranges[idx];
|
|
144
|
+
BOOL persists = ENRMBlockTypePersistsWhenEmpty(blockRange.type);
|
|
145
|
+
|
|
146
|
+
// Zero-length anchors don't follow the shared adjustment: one at the edit
|
|
147
|
+
// location stays put (normalize grows it over the typed text), one past
|
|
148
|
+
// the edit shifts with it, one inside the deletion is dropped.
|
|
149
|
+
if (blockRange.range.length == 0) {
|
|
150
|
+
if (!persists) {
|
|
151
|
+
[indexesToRemove addIndex:idx];
|
|
152
|
+
} else if (blockRange.range.location >= deleteEnd && blockRange.range.location > editLocation) {
|
|
153
|
+
blockRange.range = NSMakeRange(blockRange.range.location - deletedLength + insertedLength, 0);
|
|
154
|
+
} else if (blockRange.range.location > editLocation) {
|
|
155
|
+
[indexesToRemove addIndex:idx]; // anchor sat inside the deleted region
|
|
156
|
+
}
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
ENRMAdjustedRange adjusted = ENRMAdjustRangeForEdit(blockRange.range, editLocation, deletedLength, insertedLength,
|
|
161
|
+
/* inheritsReplacementAtStart */ YES,
|
|
162
|
+
/* growsAtStartOnInsert */ YES);
|
|
163
|
+
if (adjusted.shouldRemove) {
|
|
164
|
+
// A persisting block deleted exactly to its end collapses to a zero-length
|
|
165
|
+
// anchor (the line's newline survived, so the line stays the block); a
|
|
166
|
+
// deletion running past its end removed the line, so drop the block with it.
|
|
167
|
+
if (persists && NSMaxRange(blockRange.range) == deleteEnd && blockRange.range.location >= editLocation) {
|
|
168
|
+
blockRange.range = NSMakeRange(editLocation, 0);
|
|
169
|
+
} else {
|
|
170
|
+
[indexesToRemove addIndex:idx];
|
|
171
|
+
}
|
|
172
|
+
continue;
|
|
173
|
+
}
|
|
174
|
+
blockRange.range = adjusted.range;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
ENRMRemoveIndexesInReverse(_ranges, indexesToRemove);
|
|
178
|
+
|
|
179
|
+
// Prune zero-length ranges, but keep zero-length persisting blocks: they anchor
|
|
180
|
+
// an emptied-but-still-present heading/bullet line (see the collapse rule above).
|
|
181
|
+
NSMutableIndexSet *emptyIndexes = [NSMutableIndexSet indexSet];
|
|
182
|
+
for (NSUInteger idx = 0; idx < _ranges.count; idx++) {
|
|
183
|
+
ENRMBlockRange *range = _ranges[idx];
|
|
184
|
+
if (range.range.length == 0 && !ENRMBlockTypePersistsWhenEmpty(range.type)) {
|
|
185
|
+
[emptyIndexes addIndex:idx];
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
if (emptyIndexes.count > 0) {
|
|
189
|
+
ENRMRemoveIndexesInReverse(_ranges, emptyIndexes);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
- (void)normalizeToLineBoundsInText:(NSString *)text
|
|
194
|
+
{
|
|
195
|
+
if (_ranges.count == 0) {
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
NSMutableIndexSet *indexesToRemove = [NSMutableIndexSet indexSet];
|
|
200
|
+
NSInteger previousEnd = -1;
|
|
201
|
+
|
|
202
|
+
for (NSUInteger idx = 0; idx < _ranges.count; idx++) {
|
|
203
|
+
ENRMBlockRange *blockRange = _ranges[idx];
|
|
204
|
+
NSRange lineRange = paragraphBoundsForRange(NSMakeRange(blockRange.range.location, 0), text);
|
|
205
|
+
|
|
206
|
+
lineRange = ENRMTrimLineTerminators(lineRange, text);
|
|
207
|
+
|
|
208
|
+
BOOL emptyLine = lineRange.length == 0;
|
|
209
|
+
if ((emptyLine && !ENRMBlockTypePersistsWhenEmpty(blockRange.type)) ||
|
|
210
|
+
(NSInteger)lineRange.location <= previousEnd) {
|
|
211
|
+
// Dedup: drop a range that resolves to an already-claimed paragraph. This is a
|
|
212
|
+
// legitimate self-heal path (a heading anchor and the block it merges into can
|
|
213
|
+
// briefly share a start after a line-join), so it is deliberately silent — it
|
|
214
|
+
// cannot distinguish that benign case from genuine corruption, so it does not
|
|
215
|
+
// assert here.
|
|
216
|
+
[indexesToRemove addIndex:idx];
|
|
217
|
+
continue;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
blockRange.range = lineRange;
|
|
221
|
+
previousEnd = (NSInteger)NSMaxRange(lineRange);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
ENRMRemoveIndexesInReverse(_ranges, indexesToRemove);
|
|
225
|
+
[self recomputeListMetadata];
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/// Clamps list depths to valid ancestry (an item nests at most one level under
|
|
229
|
+
/// the previous adjacent list item — CommonMark cannot represent orphan nesting)
|
|
230
|
+
/// and renumbers ordered items among their adjacent same-depth, same-type run.
|
|
231
|
+
- (void)recomputeListMetadata
|
|
232
|
+
{
|
|
233
|
+
NSInteger prevEnd = -2;
|
|
234
|
+
NSInteger prevDepth = -1;
|
|
235
|
+
NSInteger counters[kENRMMaxListDepth + 2];
|
|
236
|
+
ENRMInputBlockType counterTypes[kENRMMaxListDepth + 2];
|
|
237
|
+
memset(counters, 0, sizeof(counters));
|
|
238
|
+
memset(counterTypes, 0, sizeof(counterTypes));
|
|
239
|
+
|
|
240
|
+
for (ENRMBlockRange *blockRange in _ranges) {
|
|
241
|
+
if (!ENRMBlockTypeIsListItem(blockRange.type)) {
|
|
242
|
+
prevDepth = -1;
|
|
243
|
+
continue;
|
|
244
|
+
}
|
|
245
|
+
BOOL adjacent = prevDepth >= 0 && (NSInteger)blockRange.range.location == prevEnd + 1;
|
|
246
|
+
if (!adjacent) {
|
|
247
|
+
memset(counters, 0, sizeof(counters));
|
|
248
|
+
memset(counterTypes, 0, sizeof(counterTypes));
|
|
249
|
+
}
|
|
250
|
+
// Coerce into [0, kENRMMaxListDepth] before ancestry-clamping: parser and
|
|
251
|
+
// indent commands cap their depths, but this pass indexes the counter
|
|
252
|
+
// arrays by depth, so an out-of-bounds level must never survive it.
|
|
253
|
+
NSInteger maxDepth = MIN(adjacent ? prevDepth + 1 : 0, kENRMMaxListDepth);
|
|
254
|
+
if (blockRange.level > maxDepth) {
|
|
255
|
+
blockRange.level = maxDepth;
|
|
256
|
+
} else if (blockRange.level < 0) {
|
|
257
|
+
blockRange.level = 0;
|
|
258
|
+
}
|
|
259
|
+
NSInteger depth = blockRange.level;
|
|
260
|
+
for (NSInteger i = depth + 1; i <= kENRMMaxListDepth + 1; i++) {
|
|
261
|
+
counters[i] = 0;
|
|
262
|
+
counterTypes[i] = (ENRMInputBlockType)0;
|
|
263
|
+
}
|
|
264
|
+
if (counterTypes[depth] != blockRange.type) {
|
|
265
|
+
counters[depth] = 0;
|
|
266
|
+
counterTypes[depth] = blockRange.type;
|
|
267
|
+
}
|
|
268
|
+
counters[depth]++;
|
|
269
|
+
blockRange.ordinal = counters[depth];
|
|
270
|
+
prevEnd = (NSInteger)NSMaxRange(blockRange.range);
|
|
271
|
+
prevDepth = blockRange.level;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
@end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#import <Foundation/Foundation.h>
|
|
4
|
+
|
|
5
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
6
|
+
|
|
7
|
+
/// Vertical tab. md4c treats it as ordinary whitespace, never as a line break.
|
|
8
|
+
extern const unichar ENRMBlockSyntaxSentinelChar;
|
|
9
|
+
|
|
10
|
+
/// Collapses `\r\n` / `\r` to `\n` and drops any `0x0B` already in the input.
|
|
11
|
+
/// Dropping is deliberate: a pre-existing `0x0B` would come back out of
|
|
12
|
+
/// `ENRMBlockSyntaxDecode` as a newline and silently corrupt the text.
|
|
13
|
+
NSString *ENRMBlockSyntaxCanonicalize(NSString *markdown);
|
|
14
|
+
|
|
15
|
+
/// Prepends one sentinel and replaces every `\n` with one. Grows the string by
|
|
16
|
+
/// exactly one character and one UTF-8 byte, which is what keeps the parser's
|
|
17
|
+
/// byte-to-UTF16 map valid and the offset correction a flat -1.
|
|
18
|
+
NSString *ENRMBlockSyntaxEncode(NSString *canonical);
|
|
19
|
+
|
|
20
|
+
/// Reverses `ENRMBlockSyntaxEncode`. Returns nil when the leading sentinel is
|
|
21
|
+
/// missing, so the caller can fall back instead of shifting offsets that no
|
|
22
|
+
/// longer hold.
|
|
23
|
+
NSString *_Nullable ENRMBlockSyntaxDecode(NSString *plainText);
|
|
24
|
+
|
|
25
|
+
NS_ASSUME_NONNULL_END
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
#import "ENRMBlockSyntaxSentinel.h"
|
|
2
|
+
|
|
3
|
+
#import <vector>
|
|
4
|
+
|
|
5
|
+
const unichar ENRMBlockSyntaxSentinelChar = 0x000B;
|
|
6
|
+
|
|
7
|
+
NSString *ENRMBlockSyntaxCanonicalize(NSString *markdown)
|
|
8
|
+
{
|
|
9
|
+
NSUInteger length = markdown.length;
|
|
10
|
+
if (length == 0) {
|
|
11
|
+
return @"";
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
std::vector<unichar> source(length);
|
|
15
|
+
[markdown getCharacters:source.data() range:NSMakeRange(0, length)];
|
|
16
|
+
|
|
17
|
+
std::vector<unichar> out;
|
|
18
|
+
out.reserve(length);
|
|
19
|
+
|
|
20
|
+
for (NSUInteger i = 0; i < length; i++) {
|
|
21
|
+
unichar c = source[i];
|
|
22
|
+
if (c == '\r') {
|
|
23
|
+
out.push_back('\n');
|
|
24
|
+
if (i + 1 < length && source[i + 1] == '\n') {
|
|
25
|
+
i++;
|
|
26
|
+
}
|
|
27
|
+
} else if (c != ENRMBlockSyntaxSentinelChar) {
|
|
28
|
+
out.push_back(c);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// `out.data()` on an empty vector may be null, which -stringWithCharacters: rejects.
|
|
33
|
+
if (out.empty()) {
|
|
34
|
+
return @"";
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return [NSString stringWithCharacters:out.data() length:out.size()];
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
NSString *ENRMBlockSyntaxEncode(NSString *canonical)
|
|
41
|
+
{
|
|
42
|
+
NSUInteger length = canonical.length;
|
|
43
|
+
|
|
44
|
+
std::vector<unichar> out;
|
|
45
|
+
out.reserve(length + 1);
|
|
46
|
+
out.push_back(ENRMBlockSyntaxSentinelChar);
|
|
47
|
+
|
|
48
|
+
if (length > 0) {
|
|
49
|
+
std::vector<unichar> source(length);
|
|
50
|
+
[canonical getCharacters:source.data() range:NSMakeRange(0, length)];
|
|
51
|
+
for (NSUInteger i = 0; i < length; i++) {
|
|
52
|
+
out.push_back(source[i] == '\n' ? ENRMBlockSyntaxSentinelChar : source[i]);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return [NSString stringWithCharacters:out.data() length:out.size()];
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
NSString *ENRMBlockSyntaxDecode(NSString *plainText)
|
|
60
|
+
{
|
|
61
|
+
NSUInteger length = plainText.length;
|
|
62
|
+
if (length == 0 || [plainText characterAtIndex:0] != ENRMBlockSyntaxSentinelChar) {
|
|
63
|
+
return nil;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
std::vector<unichar> source(length);
|
|
67
|
+
[plainText getCharacters:source.data() range:NSMakeRange(0, length)];
|
|
68
|
+
|
|
69
|
+
std::vector<unichar> out;
|
|
70
|
+
out.reserve(length - 1);
|
|
71
|
+
for (NSUInteger i = 1; i < length; i++) {
|
|
72
|
+
out.push_back(source[i] == ENRMBlockSyntaxSentinelChar ? '\n' : source[i]);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (out.empty()) {
|
|
76
|
+
return @"";
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return [NSString stringWithCharacters:out.data() length:out.size()];
|
|
80
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#import "ENRMBlockRange.h"
|
|
4
|
+
#import "ENRMFormattingRange.h"
|
|
5
|
+
#import "ENRMMathAtom.h"
|
|
6
|
+
#import <Foundation/Foundation.h>
|
|
7
|
+
|
|
8
|
+
@class ENRMFormattingStore;
|
|
9
|
+
@class ENRMBlockStore;
|
|
10
|
+
@class ENRMInputFormatter;
|
|
11
|
+
@protocol ENRMDetectorPipelineTransientRanges;
|
|
12
|
+
|
|
13
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
14
|
+
|
|
15
|
+
@protocol ENRMTransientRangeProvider <NSObject>
|
|
16
|
+
- (NSArray<ENRMFormattingRange *> *)allTransientFormattingRanges;
|
|
17
|
+
@end
|
|
18
|
+
|
|
19
|
+
@interface ENRMClipboardCoordinator : NSObject
|
|
20
|
+
|
|
21
|
+
- (instancetype)initWithFormattingStore:(ENRMFormattingStore *)formattingStore
|
|
22
|
+
blockStore:(ENRMBlockStore *)blockStore
|
|
23
|
+
transientRangeProvider:(id<ENRMTransientRangeProvider>)transientRangeProvider
|
|
24
|
+
formatter:(ENRMInputFormatter *)formatter;
|
|
25
|
+
|
|
26
|
+
- (NSArray<ENRMFormattingRange *> *)allRangesIncludingTransient;
|
|
27
|
+
|
|
28
|
+
/// `mathAtoms` positions are offsets into `text`. Pass `@[]` only for text that
|
|
29
|
+
/// genuinely holds no chip — every path that serializes the live buffer must
|
|
30
|
+
/// carry its chips, or each formula leaves the editor as a bare placeholder
|
|
31
|
+
/// character instead of `$latex$`.
|
|
32
|
+
- (NSString *)serializeText:(NSString *)text
|
|
33
|
+
mathAtoms:(NSArray<ENRMMathAtom *> *)mathAtoms
|
|
34
|
+
ranges:(NSArray<ENRMFormattingRange *> *)ranges
|
|
35
|
+
blockRanges:(NSArray<ENRMBlockRange *> *)blockRanges;
|
|
36
|
+
|
|
37
|
+
- (NSString *)serializeFullDocument:(NSString *)plainText mathAtoms:(NSArray<ENRMMathAtom *> *)mathAtoms;
|
|
38
|
+
|
|
39
|
+
- (nullable NSString *)serializeSelectedRange:(NSRange)selection
|
|
40
|
+
inText:(NSString *)fullText
|
|
41
|
+
mathAtoms:(NSArray<ENRMMathAtom *> *)mathAtoms;
|
|
42
|
+
|
|
43
|
+
@end
|
|
44
|
+
|
|
45
|
+
NS_ASSUME_NONNULL_END
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
#import "ENRMClipboardCoordinator.h"
|
|
2
|
+
#import "ENRMBlockStore.h"
|
|
3
|
+
#import "ENRMFormattingStore.h"
|
|
4
|
+
#import "ENRMInputFormatter.h"
|
|
5
|
+
#import "ENRMMarkdownSerializer.h"
|
|
6
|
+
#import "styles/ENRMBlockHandler.h"
|
|
7
|
+
|
|
8
|
+
@implementation ENRMClipboardCoordinator {
|
|
9
|
+
ENRMFormattingStore *_formattingStore;
|
|
10
|
+
ENRMBlockStore *_blockStore;
|
|
11
|
+
id<ENRMTransientRangeProvider> _transientRangeProvider;
|
|
12
|
+
ENRMInputFormatter *_formatter;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
- (instancetype)initWithFormattingStore:(ENRMFormattingStore *)formattingStore
|
|
16
|
+
blockStore:(ENRMBlockStore *)blockStore
|
|
17
|
+
transientRangeProvider:(id<ENRMTransientRangeProvider>)transientRangeProvider
|
|
18
|
+
formatter:(ENRMInputFormatter *)formatter
|
|
19
|
+
{
|
|
20
|
+
if (self = [super init]) {
|
|
21
|
+
_formattingStore = formattingStore;
|
|
22
|
+
_blockStore = blockStore;
|
|
23
|
+
_transientRangeProvider = transientRangeProvider;
|
|
24
|
+
_formatter = formatter;
|
|
25
|
+
}
|
|
26
|
+
return self;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
- (NSArray<ENRMFormattingRange *> *)allRangesIncludingTransient
|
|
30
|
+
{
|
|
31
|
+
NSArray<ENRMFormattingRange *> *transient = [_transientRangeProvider allTransientFormattingRanges];
|
|
32
|
+
if (transient.count == 0) {
|
|
33
|
+
return _formattingStore.allRanges;
|
|
34
|
+
}
|
|
35
|
+
NSMutableArray<ENRMFormattingRange *> *merged = [_formattingStore.allRanges mutableCopy];
|
|
36
|
+
[merged addObjectsFromArray:transient];
|
|
37
|
+
return merged;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
- (NSString *)serializeText:(NSString *)text
|
|
41
|
+
mathAtoms:(NSArray<ENRMMathAtom *> *)mathAtoms
|
|
42
|
+
ranges:(NSArray<ENRMFormattingRange *> *)ranges
|
|
43
|
+
blockRanges:(NSArray<ENRMBlockRange *> *)blockRanges
|
|
44
|
+
{
|
|
45
|
+
ENRMInputFormatter *formatter = _formatter;
|
|
46
|
+
return [ENRMMarkdownSerializer serializePlainText:text
|
|
47
|
+
mathAtoms:mathAtoms
|
|
48
|
+
ranges:ranges
|
|
49
|
+
blockRanges:blockRanges
|
|
50
|
+
blockPrefixProvider:^NSString *(ENRMBlockRange *blockRange) {
|
|
51
|
+
id<ENRMBlockHandler> handler = [formatter handlerForBlockType:blockRange.type];
|
|
52
|
+
return [handler markdownLinePrefixForBlockRange:blockRange];
|
|
53
|
+
}];
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
- (NSString *)serializeFullDocument:(NSString *)plainText mathAtoms:(NSArray<ENRMMathAtom *> *)mathAtoms
|
|
57
|
+
{
|
|
58
|
+
return [self serializeText:plainText
|
|
59
|
+
mathAtoms:mathAtoms
|
|
60
|
+
ranges:[self allRangesIncludingTransient]
|
|
61
|
+
blockRanges:_blockStore.allRanges];
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
- (nullable NSString *)serializeSelectedRange:(NSRange)selection
|
|
65
|
+
inText:(NSString *)fullText
|
|
66
|
+
mathAtoms:(NSArray<ENRMMathAtom *> *)mathAtoms
|
|
67
|
+
{
|
|
68
|
+
if (selection.length == 0) {
|
|
69
|
+
return nil;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
NSString *selectedText = [fullText substringWithRange:selection];
|
|
73
|
+
NSUInteger selEnd = NSMaxRange(selection);
|
|
74
|
+
|
|
75
|
+
NSMutableArray<ENRMFormattingRange *> *clippedRanges = [NSMutableArray array];
|
|
76
|
+
for (ENRMFormattingRange *range in [self allRangesIncludingTransient]) {
|
|
77
|
+
NSUInteger rangeStart = range.range.location;
|
|
78
|
+
NSUInteger rangeEnd = NSMaxRange(range.range);
|
|
79
|
+
if (rangeEnd <= selection.location || rangeStart >= selEnd) {
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
NSUInteger clippedStart = MAX(rangeStart, selection.location);
|
|
83
|
+
NSUInteger clippedEnd = MIN(rangeEnd, selEnd);
|
|
84
|
+
NSRange shifted = NSMakeRange(clippedStart - selection.location, clippedEnd - clippedStart);
|
|
85
|
+
[clippedRanges addObject:[ENRMFormattingRange rangeWithType:range.type range:shifted url:range.url]];
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
NSMutableArray<ENRMBlockRange *> *clippedBlockRanges = [NSMutableArray array];
|
|
89
|
+
for (ENRMBlockRange *blockRange in _blockStore.allRanges) {
|
|
90
|
+
NSUInteger rangeStart = blockRange.range.location;
|
|
91
|
+
NSUInteger rangeEnd = NSMaxRange(blockRange.range);
|
|
92
|
+
if (rangeEnd <= selection.location || rangeStart >= selEnd) {
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
NSUInteger clippedStart = MAX(rangeStart, selection.location);
|
|
96
|
+
NSUInteger clippedEnd = MIN(rangeEnd, selEnd);
|
|
97
|
+
NSRange shifted = NSMakeRange(clippedStart - selection.location, clippedEnd - clippedStart);
|
|
98
|
+
[clippedBlockRanges addObject:[ENRMBlockRange rangeWithType:blockRange.type range:shifted level:blockRange.level]];
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// A chip is a single character, so it is cleanly inside or outside the
|
|
102
|
+
// selection; rebase the survivors onto the substring like the ranges above.
|
|
103
|
+
// Copying part of a document must serialize its formulas, not the bare
|
|
104
|
+
// placeholder character.
|
|
105
|
+
NSMutableArray<ENRMMathAtom *> *clippedAtoms = [NSMutableArray array];
|
|
106
|
+
for (ENRMMathAtom *atom in mathAtoms) {
|
|
107
|
+
if (atom.position < selection.location || atom.position >= selEnd) {
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
ENRMMathAtom *clipped = [[ENRMMathAtom alloc] init];
|
|
111
|
+
clipped.position = atom.position - selection.location;
|
|
112
|
+
clipped.latex = atom.latex;
|
|
113
|
+
clipped.displayMode = atom.displayMode;
|
|
114
|
+
[clippedAtoms addObject:clipped];
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return [self serializeText:selectedText mathAtoms:clippedAtoms ranges:clippedRanges blockRanges:clippedBlockRanges];
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
@end
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#pragma once
|
|
2
2
|
|
|
3
|
+
#import "ENRMClipboardCoordinator.h"
|
|
3
4
|
#import "ENRMFormattingRange.h"
|
|
4
5
|
#import "ENRMTextDetector.h"
|
|
5
6
|
#import <Foundation/Foundation.h>
|
|
@@ -8,7 +9,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
8
9
|
|
|
9
10
|
/// Coordinates a set of ENRMTextDetector instances. The input view calls
|
|
10
11
|
/// this pipeline instead of individual detectors.
|
|
11
|
-
@interface ENRMDetectorPipeline : NSObject
|
|
12
|
+
@interface ENRMDetectorPipeline : NSObject <ENRMTransientRangeProvider>
|
|
12
13
|
|
|
13
14
|
- (void)addDetector:(id<ENRMTextDetector>)detector;
|
|
14
15
|
|