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
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
#pragma once
|
|
2
2
|
|
|
3
|
+
#import "ENRMBlockRange.h"
|
|
3
4
|
#import "ENRMFormattingRange.h"
|
|
5
|
+
#import "ENRMMathAtom.h"
|
|
4
6
|
|
|
5
7
|
NS_ASSUME_NONNULL_BEGIN
|
|
6
8
|
|
|
@@ -8,11 +10,33 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
8
10
|
|
|
9
11
|
+ (NSString *)serializePlainText:(NSString *)text ranges:(NSArray<ENRMFormattingRange *> *)ranges;
|
|
10
12
|
|
|
11
|
-
///
|
|
12
|
-
///
|
|
13
|
-
///
|
|
14
|
-
///
|
|
15
|
-
|
|
13
|
+
/// Block-aware serialization: serializes inline styles exactly as the inline-only
|
|
14
|
+
/// overload, then prepends each line's block prefix. `prefixProvider` is asked,
|
|
15
|
+
/// per block range, for the markdown line marker (e.g. @"# ", @"- "); returning
|
|
16
|
+
/// @"" or nil leaves the line unprefixed. With empty `blockRanges` the output is
|
|
17
|
+
/// identical to the inline-only overload.
|
|
18
|
+
+ (NSString *)serializePlainText:(NSString *)text
|
|
19
|
+
ranges:(NSArray<ENRMFormattingRange *> *)ranges
|
|
20
|
+
blockRanges:(NSArray<ENRMBlockRange *> *)blockRanges
|
|
21
|
+
blockPrefixProvider:(NSString *_Nullable (^_Nullable)(ENRMBlockRange *blockRange))prefixProvider;
|
|
22
|
+
|
|
23
|
+
/// Math-aware serialization — the single output path for a buffer that may hold
|
|
24
|
+
/// math chips. Each chip's `kENRMObjectReplacement` placeholder expands back to
|
|
25
|
+
/// `$latex$` / `$$latex$$`, and **both** the inline ranges and the block ranges
|
|
26
|
+
/// are translated through the same position map before the block-aware overload
|
|
27
|
+
/// above runs. Translating only one of the two is the silent failure this
|
|
28
|
+
/// exists to prevent: one placeholder character becomes n characters, so every
|
|
29
|
+
/// block boundary after a chip would land a line off and `# `/`- `/`1. ` would
|
|
30
|
+
/// prefix the wrong line.
|
|
31
|
+
///
|
|
32
|
+
/// Chips arrive as plain data (not an `NSAttributedString`), so this stays a pure
|
|
33
|
+
/// function over `NSString` — which is what makes the round trip testable without
|
|
34
|
+
/// a live editor. `ENRMMathAtom.position` is an offset into `text`.
|
|
35
|
+
+ (NSString *)serializePlainText:(NSString *)text
|
|
36
|
+
mathAtoms:(NSArray<ENRMMathAtom *> *)mathAtoms
|
|
37
|
+
ranges:(NSArray<ENRMFormattingRange *> *)ranges
|
|
38
|
+
blockRanges:(NSArray<ENRMBlockRange *> *)blockRanges
|
|
39
|
+
blockPrefixProvider:(NSString *_Nullable (^_Nullable)(ENRMBlockRange *blockRange))prefixProvider;
|
|
16
40
|
|
|
17
41
|
@end
|
|
18
42
|
|
|
@@ -1,9 +1,20 @@
|
|
|
1
1
|
#import "ENRMMarkdownSerializer.h"
|
|
2
2
|
|
|
3
|
-
#
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
#include <vector>
|
|
4
|
+
|
|
5
|
+
/// Translates a range over the pre-expansion text into the expanded text. Both
|
|
6
|
+
/// endpoints go through the same map, which is what keeps inline and block
|
|
7
|
+
/// ranges consistent with each other after a chip expands.
|
|
8
|
+
static NSRange mapRangeThroughPositionMap(NSRange range, const std::vector<NSUInteger> &positionMap,
|
|
9
|
+
NSUInteger textLength)
|
|
10
|
+
{
|
|
11
|
+
NSUInteger start = MIN(range.location, textLength);
|
|
12
|
+
NSUInteger end = MIN(NSMaxRange(range), textLength);
|
|
13
|
+
if (end < start) {
|
|
14
|
+
end = start;
|
|
15
|
+
}
|
|
16
|
+
return NSMakeRange(positionMap[start], positionMap[end] - positionMap[start]);
|
|
17
|
+
}
|
|
7
18
|
|
|
8
19
|
static NSString *openingDelimiterForType(ENRMInputStyleType type)
|
|
9
20
|
{
|
|
@@ -224,60 +235,171 @@ static NSArray<ENRMFormattingRange *> *splitRangesAtParagraphBreaks(NSArray<ENRM
|
|
|
224
235
|
return markdown;
|
|
225
236
|
}
|
|
226
237
|
|
|
227
|
-
+ (NSString *)
|
|
238
|
+
+ (NSString *)serializePlainText:(NSString *)text
|
|
239
|
+
ranges:(NSArray<ENRMFormattingRange *> *)ranges
|
|
240
|
+
blockRanges:(NSArray<ENRMBlockRange *> *)blockRanges
|
|
241
|
+
blockPrefixProvider:(NSString *_Nullable (^_Nullable)(ENRMBlockRange *blockRange))prefixProvider
|
|
228
242
|
{
|
|
229
|
-
|
|
230
|
-
|
|
243
|
+
NSString *inlineMarkdown = [self serializePlainText:text ranges:ranges];
|
|
244
|
+
|
|
245
|
+
if (blockRanges.count == 0 || prefixProvider == nil) {
|
|
246
|
+
return inlineMarkdown;
|
|
231
247
|
}
|
|
232
248
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
//
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
249
|
+
// Block prefixes attach per line. Inline serialization only inserts inline
|
|
250
|
+
// delimiters (never newlines), so the serialized output has the same line
|
|
251
|
+
// count as the plain text — we map a block's plain-text range to line indices
|
|
252
|
+
// and prefix the corresponding serialized lines.
|
|
253
|
+
NSArray<NSString *> *plainLines = [text componentsSeparatedByString:@"\n"];
|
|
254
|
+
NSMutableArray<NSString *> *markdownLines = [[inlineMarkdown componentsSeparatedByString:@"\n"] mutableCopy];
|
|
255
|
+
|
|
256
|
+
// Inline delimiters never cross a newline, so the line partition is preserved.
|
|
257
|
+
// If this ever breaks, prefixes would land on the wrong lines. Contract on
|
|
258
|
+
// both platforms: assert in debug, log and fall back to inline-only output in
|
|
259
|
+
// release — a library must not crash the host app over lost block prefixes.
|
|
260
|
+
NSCAssert(plainLines.count == markdownLines.count,
|
|
261
|
+
@"Block serialization line-count invariant violated: plain=%lu markdown=%lu",
|
|
262
|
+
(unsigned long)plainLines.count, (unsigned long)markdownLines.count);
|
|
263
|
+
if (plainLines.count != markdownLines.count) {
|
|
264
|
+
NSLog(@"[EnrichedMarkdown] Block serialization line-count invariant violated: plain=%lu markdown=%lu",
|
|
265
|
+
(unsigned long)plainLines.count, (unsigned long)markdownLines.count);
|
|
266
|
+
return inlineMarkdown;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
NSMutableArray<NSNumber *> *lineStartOffsets = [NSMutableArray arrayWithCapacity:plainLines.count];
|
|
270
|
+
NSUInteger runningOffset = 0;
|
|
271
|
+
for (NSString *line in plainLines) {
|
|
272
|
+
[lineStartOffsets addObject:@(runningOffset)];
|
|
273
|
+
runningOffset += line.length + 1; // +1 for the '\n' separator
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
for (ENRMBlockRange *blockRange in blockRanges) {
|
|
277
|
+
NSString *prefix = prefixProvider(blockRange);
|
|
278
|
+
if (prefix.length == 0) {
|
|
279
|
+
continue;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
NSUInteger blockStart = blockRange.range.location;
|
|
283
|
+
NSUInteger blockEnd = NSMaxRange(blockRange.range);
|
|
284
|
+
BOOL isZeroLength = blockRange.range.length == 0;
|
|
285
|
+
BOOL isListItem = ENRMBlockTypeIsListItem(blockRange.type);
|
|
286
|
+
|
|
287
|
+
for (NSUInteger lineIndex = 0; lineIndex < plainLines.count; lineIndex++) {
|
|
288
|
+
NSUInteger lineStart = lineStartOffsets[lineIndex].unsignedIntegerValue;
|
|
289
|
+
NSUInteger lineEnd = lineStart + plainLines[lineIndex].length;
|
|
290
|
+
BOOL overlaps = isZeroLength ? (lineStart == blockStart) : (lineEnd >= blockStart && lineStart < blockEnd);
|
|
291
|
+
if (overlaps) {
|
|
292
|
+
// A marker-only list line ("- " with no content) re-parses as a setext
|
|
293
|
+
// underline for the previous line; emit an empty list line bare. An
|
|
294
|
+
// empty "# " heading is valid ATX and keeps its prefix.
|
|
295
|
+
if (isListItem && plainLines[lineIndex].length == 0) {
|
|
296
|
+
continue;
|
|
254
297
|
}
|
|
255
|
-
[
|
|
256
|
-
|
|
257
|
-
|
|
298
|
+
markdownLines[lineIndex] = [prefix stringByAppendingString:markdownLines[lineIndex]];
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
return [markdownLines componentsJoinedByString:@"\n"];
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/// The chip's markdown form, delimiters included. Line breaks inside the LaTeX
|
|
307
|
+
/// are collapsed to spaces: a chip is one line box in the editor, and emitting a
|
|
308
|
+
/// real newline would change the serialized line count, which trips the
|
|
309
|
+
/// line-count invariant above and silently drops every block prefix in the
|
|
310
|
+
/// document. LaTeX is whitespace-insensitive here, so the formula is unaffected.
|
|
311
|
+
/// A blank formula expands to nothing rather than to a bare `$$` that would
|
|
312
|
+
/// re-parse as literal text.
|
|
313
|
+
static NSString *mathDelimitedMarkdown(ENRMMathAtom *atom)
|
|
314
|
+
{
|
|
315
|
+
NSMutableString *latex = [NSMutableString stringWithCapacity:atom.latex.length];
|
|
316
|
+
BOOL previousWasBreak = NO;
|
|
317
|
+
for (NSUInteger index = 0; index < atom.latex.length; index++) {
|
|
318
|
+
unichar character = [atom.latex characterAtIndex:index];
|
|
319
|
+
if (character == '\n' || character == '\r' || character == 0x2028 || character == 0x2029) {
|
|
320
|
+
if (!previousWasBreak) {
|
|
321
|
+
[latex appendString:@" "];
|
|
258
322
|
}
|
|
259
|
-
|
|
260
|
-
// Unknown attachment — skip the placeholder char so it doesn't leak.
|
|
323
|
+
previousWasBreak = YES;
|
|
261
324
|
continue;
|
|
262
325
|
}
|
|
263
|
-
[
|
|
264
|
-
|
|
326
|
+
[latex appendFormat:@"%C", character];
|
|
327
|
+
previousWasBreak = NO;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
NSString *trimmed = [latex stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
|
|
331
|
+
if (trimmed.length == 0) {
|
|
332
|
+
return @"";
|
|
265
333
|
}
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
[
|
|
334
|
+
NSString *delimiter = atom.displayMode ? @"$$" : @"$";
|
|
335
|
+
return [NSString stringWithFormat:@"%@%@%@", delimiter, trimmed, delimiter];
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
+ (NSString *)serializePlainText:(NSString *)text
|
|
339
|
+
mathAtoms:(NSArray<ENRMMathAtom *> *)mathAtoms
|
|
340
|
+
ranges:(NSArray<ENRMFormattingRange *> *)ranges
|
|
341
|
+
blockRanges:(NSArray<ENRMBlockRange *> *)blockRanges
|
|
342
|
+
blockPrefixProvider:(NSString *_Nullable (^_Nullable)(ENRMBlockRange *blockRange))prefixProvider
|
|
343
|
+
{
|
|
344
|
+
if (mathAtoms.count == 0) {
|
|
345
|
+
return [self serializePlainText:text ranges:ranges blockRanges:blockRanges blockPrefixProvider:prefixProvider];
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
NSUInteger textLength = text.length;
|
|
349
|
+
|
|
350
|
+
// A chip whose recorded position no longer holds a placeholder is stale (the
|
|
351
|
+
// buffer moved under it); expanding it there would corrupt unrelated text.
|
|
352
|
+
NSMutableDictionary<NSNumber *, NSString *> *latexByPosition =
|
|
353
|
+
[NSMutableDictionary dictionaryWithCapacity:mathAtoms.count];
|
|
354
|
+
for (ENRMMathAtom *atom in mathAtoms) {
|
|
355
|
+
if (atom.position >= textLength) {
|
|
356
|
+
continue;
|
|
357
|
+
}
|
|
358
|
+
if ([text characterAtIndex:atom.position] != kENRMObjectReplacement) {
|
|
359
|
+
continue;
|
|
360
|
+
}
|
|
361
|
+
latexByPosition[@(atom.position)] = mathDelimitedMarkdown(atom);
|
|
362
|
+
}
|
|
363
|
+
if (latexByPosition.count == 0) {
|
|
364
|
+
return [self serializePlainText:text ranges:ranges blockRanges:blockRanges blockPrefixProvider:prefixProvider];
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
// positionMap[i] = offset in `expanded` of the character that was at text[i].
|
|
368
|
+
// Length + 1 so an exclusive end offset at textLength maps too.
|
|
369
|
+
NSMutableString *expanded = [NSMutableString stringWithCapacity:textLength];
|
|
370
|
+
std::vector<NSUInteger> positionMap(textLength + 1, 0);
|
|
371
|
+
for (NSUInteger index = 0; index < textLength; index++) {
|
|
372
|
+
positionMap[index] = expanded.length;
|
|
373
|
+
NSString *replacement = latexByPosition[@(index)];
|
|
374
|
+
if (replacement != nil) {
|
|
375
|
+
[expanded appendString:replacement];
|
|
376
|
+
} else {
|
|
377
|
+
[expanded appendFormat:@"%C", [text characterAtIndex:index]];
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
positionMap[textLength] = expanded.length;
|
|
381
|
+
|
|
382
|
+
NSMutableArray<ENRMFormattingRange *> *shiftedRanges = [NSMutableArray arrayWithCapacity:ranges.count];
|
|
383
|
+
for (ENRMFormattingRange *range in ranges) {
|
|
384
|
+
ENRMFormattingRange *shifted = [range copy];
|
|
385
|
+
shifted.range = mapRangeThroughPositionMap(range.range, positionMap, textLength);
|
|
386
|
+
[shiftedRanges addObject:shifted];
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
NSMutableArray<ENRMBlockRange *> *shiftedBlockRanges = [NSMutableArray arrayWithCapacity:blockRanges.count];
|
|
390
|
+
for (ENRMBlockRange *blockRange in blockRanges) {
|
|
391
|
+
// Copy rather than rebuild: `ordinal` carries an ordered item's number and is
|
|
392
|
+
// not part of any initializer, so a rebuilt range renumbers every "1." in the
|
|
393
|
+
// document — a silent failure the copy sidesteps entirely.
|
|
394
|
+
ENRMBlockRange *shifted = [blockRange copy];
|
|
395
|
+
shifted.range = mapRangeThroughPositionMap(blockRange.range, positionMap, textLength);
|
|
396
|
+
[shiftedBlockRanges addObject:shifted];
|
|
278
397
|
}
|
|
279
398
|
|
|
280
|
-
return [self serializePlainText:expanded
|
|
399
|
+
return [self serializePlainText:expanded
|
|
400
|
+
ranges:shiftedRanges
|
|
401
|
+
blockRanges:shiftedBlockRanges
|
|
402
|
+
blockPrefixProvider:prefixProvider];
|
|
281
403
|
}
|
|
282
404
|
|
|
283
405
|
@end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#import <Foundation/Foundation.h>
|
|
4
|
+
|
|
5
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
6
|
+
|
|
7
|
+
/// U+FFFC OBJECT REPLACEMENT CHARACTER — the single character a math chip
|
|
8
|
+
/// occupies in the editor buffer. Declared once and shared by every stage of the
|
|
9
|
+
/// round trip (parser writes it, serializer expands it, the view inserts it): a
|
|
10
|
+
/// second copy of this literal is a round-trip bug waiting to happen.
|
|
11
|
+
static const unichar kENRMObjectReplacement = 0xFFFC;
|
|
12
|
+
|
|
13
|
+
/// `kENRMObjectReplacement` as a string, for insertion into text buffers.
|
|
14
|
+
NSString *ENRMObjectReplacementString(void);
|
|
15
|
+
|
|
16
|
+
/// One `$...$` / `$$...$$` formula found in the markdown. The parser has already
|
|
17
|
+
/// put a single `kENRMObjectReplacement` at `position` in the plain text; the
|
|
18
|
+
/// caller turns it into a chip. Pure data — no RaTeX dependency, so it exists in
|
|
19
|
+
/// math-disabled builds too (md4c simply never emits any).
|
|
20
|
+
@interface ENRMMathAtom : NSObject
|
|
21
|
+
@property (nonatomic, assign) NSUInteger position;
|
|
22
|
+
@property (nonatomic, copy) NSString *latex;
|
|
23
|
+
@property (nonatomic, assign) BOOL displayMode;
|
|
24
|
+
@end
|
|
25
|
+
|
|
26
|
+
NS_ASSUME_NONNULL_END
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#import "ENRMMathAtom.h"
|
|
2
|
+
|
|
3
|
+
NSString *ENRMObjectReplacementString(void)
|
|
4
|
+
{
|
|
5
|
+
static NSString *placeholder;
|
|
6
|
+
static dispatch_once_t onceToken;
|
|
7
|
+
dispatch_once(&onceToken, ^{ placeholder = [NSString stringWithCharacters:&kENRMObjectReplacement length:1]; });
|
|
8
|
+
return placeholder;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
@implementation ENRMMathAtom
|
|
12
|
+
@end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#import "ENRMFormattingStore.h"
|
|
4
|
+
#import "ENRMInputMentionCandidate.h"
|
|
5
|
+
#import <Foundation/Foundation.h>
|
|
6
|
+
|
|
7
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
8
|
+
|
|
9
|
+
typedef NS_ENUM(NSInteger, ENRMMentionEventType) {
|
|
10
|
+
ENRMMentionEventStart,
|
|
11
|
+
ENRMMentionEventChange,
|
|
12
|
+
ENRMMentionEventEnd,
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
@interface ENRMMentionEvent : NSObject
|
|
16
|
+
@property (nonatomic, assign) ENRMMentionEventType type;
|
|
17
|
+
@property (nonatomic, copy) NSString *indicator;
|
|
18
|
+
@property (nonatomic, copy, nullable) NSString *text;
|
|
19
|
+
+ (instancetype)startWithIndicator:(NSString *)indicator;
|
|
20
|
+
+ (instancetype)changeWithIndicator:(NSString *)indicator text:(NSString *)text;
|
|
21
|
+
+ (instancetype)endWithIndicator:(NSString *)indicator;
|
|
22
|
+
@end
|
|
23
|
+
|
|
24
|
+
@interface ENRMMentionCoordinator : NSObject
|
|
25
|
+
|
|
26
|
+
@property (nonatomic, readonly, nullable) NSString *activeIndicator;
|
|
27
|
+
@property (nonatomic, readonly) NSRange activeRange;
|
|
28
|
+
@property (nonatomic, readonly, copy) NSString *activeText;
|
|
29
|
+
@property (nonatomic, readonly) BOOL isActive;
|
|
30
|
+
|
|
31
|
+
- (instancetype)initWithFormattingStore:(ENRMFormattingStore *)formattingStore;
|
|
32
|
+
|
|
33
|
+
- (BOOL)containsIndicator:(NSString *)indicator;
|
|
34
|
+
- (NSArray<ENRMMentionEvent *> *)setIndicators:(NSArray<NSString *> *)indicators;
|
|
35
|
+
|
|
36
|
+
/// Re-evaluates the active mention. Returns events for the view to dispatch.
|
|
37
|
+
- (NSArray<ENRMMentionEvent *> *)updateWithText:(nullable NSString *)plainText selectedRange:(NSRange)selectedRange;
|
|
38
|
+
|
|
39
|
+
- (NSArray<ENRMMentionEvent *> *)clearWithIndicatorOverride:(nullable NSString *)indicatorOverride;
|
|
40
|
+
|
|
41
|
+
- (nullable ENRMInputMentionCandidate *)detectCandidateInText:(NSString *)plainText atCursor:(NSUInteger)cursor;
|
|
42
|
+
|
|
43
|
+
@end
|
|
44
|
+
|
|
45
|
+
NS_ASSUME_NONNULL_END
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
#import "ENRMMentionCoordinator.h"
|
|
2
|
+
#import "ENRMWordsUtils.h"
|
|
3
|
+
|
|
4
|
+
@implementation ENRMMentionEvent
|
|
5
|
+
|
|
6
|
+
+ (instancetype)startWithIndicator:(NSString *)indicator
|
|
7
|
+
{
|
|
8
|
+
ENRMMentionEvent *e = [[ENRMMentionEvent alloc] init];
|
|
9
|
+
e.type = ENRMMentionEventStart;
|
|
10
|
+
e.indicator = indicator;
|
|
11
|
+
return e;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
+ (instancetype)changeWithIndicator:(NSString *)indicator text:(NSString *)text
|
|
15
|
+
{
|
|
16
|
+
ENRMMentionEvent *e = [[ENRMMentionEvent alloc] init];
|
|
17
|
+
e.type = ENRMMentionEventChange;
|
|
18
|
+
e.indicator = indicator;
|
|
19
|
+
e.text = text;
|
|
20
|
+
return e;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
+ (instancetype)endWithIndicator:(NSString *)indicator
|
|
24
|
+
{
|
|
25
|
+
ENRMMentionEvent *e = [[ENRMMentionEvent alloc] init];
|
|
26
|
+
e.type = ENRMMentionEventEnd;
|
|
27
|
+
e.indicator = indicator;
|
|
28
|
+
return e;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
@end
|
|
32
|
+
|
|
33
|
+
@implementation ENRMMentionCoordinator {
|
|
34
|
+
ENRMFormattingStore *_formattingStore;
|
|
35
|
+
NSArray<NSString *> *_indicators;
|
|
36
|
+
NSString *_activeIndicator;
|
|
37
|
+
NSRange _activeRange;
|
|
38
|
+
NSString *_activeText;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
- (instancetype)initWithFormattingStore:(ENRMFormattingStore *)formattingStore
|
|
42
|
+
{
|
|
43
|
+
if (self = [super init]) {
|
|
44
|
+
_formattingStore = formattingStore;
|
|
45
|
+
_indicators = @[];
|
|
46
|
+
_activeRange = NSMakeRange(NSNotFound, 0);
|
|
47
|
+
_activeText = @"";
|
|
48
|
+
}
|
|
49
|
+
return self;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
- (NSString *)activeIndicator
|
|
53
|
+
{
|
|
54
|
+
return _activeIndicator;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
- (NSRange)activeRange
|
|
58
|
+
{
|
|
59
|
+
return _activeRange;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
- (NSString *)activeText
|
|
63
|
+
{
|
|
64
|
+
return _activeText;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
- (BOOL)isActive
|
|
68
|
+
{
|
|
69
|
+
return _activeIndicator != nil;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
- (BOOL)containsIndicator:(NSString *)indicator
|
|
73
|
+
{
|
|
74
|
+
return [_indicators containsObject:indicator];
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
- (NSArray<ENRMMentionEvent *> *)setIndicators:(NSArray<NSString *> *)indicators
|
|
78
|
+
{
|
|
79
|
+
if ([indicators isEqualToArray:_indicators]) {
|
|
80
|
+
return @[];
|
|
81
|
+
}
|
|
82
|
+
_indicators = [indicators copy];
|
|
83
|
+
NSMutableArray<ENRMMentionEvent *> *events = [NSMutableArray array];
|
|
84
|
+
if (_activeIndicator != nil && ![_indicators containsObject:_activeIndicator]) {
|
|
85
|
+
[events addObjectsFromArray:[self clearWithIndicatorOverride:_activeIndicator]];
|
|
86
|
+
}
|
|
87
|
+
return events;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
- (NSArray<ENRMMentionEvent *> *)updateWithText:(nullable NSString *)plainText selectedRange:(NSRange)selectedRange
|
|
91
|
+
{
|
|
92
|
+
if (plainText == nil || selectedRange.length != 0) {
|
|
93
|
+
return [self clearWithIndicatorOverride:nil];
|
|
94
|
+
}
|
|
95
|
+
NSUInteger cursor = selectedRange.location;
|
|
96
|
+
if (cursor > plainText.length) {
|
|
97
|
+
return [self clearWithIndicatorOverride:nil];
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
ENRMInputMentionCandidate *candidate = [self detectCandidateInText:plainText atCursor:cursor];
|
|
101
|
+
if (candidate == nil) {
|
|
102
|
+
return [self clearWithIndicatorOverride:nil];
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
NSMutableArray<ENRMMentionEvent *> *events = [NSMutableArray array];
|
|
106
|
+
|
|
107
|
+
if (_activeIndicator == nil || ![_activeIndicator isEqualToString:candidate.indicator] ||
|
|
108
|
+
_activeRange.location != candidate.start) {
|
|
109
|
+
if (_activeIndicator != nil) {
|
|
110
|
+
[events addObject:[ENRMMentionEvent endWithIndicator:_activeIndicator]];
|
|
111
|
+
}
|
|
112
|
+
_activeIndicator = candidate.indicator;
|
|
113
|
+
[events addObject:[ENRMMentionEvent startWithIndicator:candidate.indicator]];
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
_activeRange = NSMakeRange(candidate.start, candidate.end - candidate.start);
|
|
117
|
+
|
|
118
|
+
if (![_activeText isEqualToString:candidate.text]) {
|
|
119
|
+
_activeText = candidate.text;
|
|
120
|
+
[events addObject:[ENRMMentionEvent changeWithIndicator:candidate.indicator text:candidate.text]];
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return events;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
- (NSArray<ENRMMentionEvent *> *)clearWithIndicatorOverride:(nullable NSString *)indicatorOverride
|
|
127
|
+
{
|
|
128
|
+
NSString *indicator = indicatorOverride ?: _activeIndicator;
|
|
129
|
+
_activeIndicator = nil;
|
|
130
|
+
_activeRange = NSMakeRange(NSNotFound, 0);
|
|
131
|
+
_activeText = @"";
|
|
132
|
+
if (indicator.length > 0) {
|
|
133
|
+
return @[ [ENRMMentionEvent endWithIndicator:indicator] ];
|
|
134
|
+
}
|
|
135
|
+
return @[];
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
- (nullable ENRMInputMentionCandidate *)detectCandidateInText:(NSString *)plainText atCursor:(NSUInteger)cursor
|
|
139
|
+
{
|
|
140
|
+
if (_indicators.count == 0) {
|
|
141
|
+
return nil;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
NSUInteger start = [ENRMWordsUtils tokenStartInText:plainText beforePosition:cursor];
|
|
145
|
+
NSString *token = [plainText substringWithRange:NSMakeRange(start, cursor - start)];
|
|
146
|
+
NSString *matchedIndicator = nil;
|
|
147
|
+
for (NSString *indicator in _indicators) {
|
|
148
|
+
if ([token hasPrefix:indicator]) {
|
|
149
|
+
matchedIndicator = indicator;
|
|
150
|
+
break;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
if (matchedIndicator == nil) {
|
|
154
|
+
return nil;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if ([_formattingStore rangeOfType:ENRMInputStyleTypeLink containingPosition:start] != nil) {
|
|
158
|
+
return nil;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
return [ENRMInputMentionCandidate candidateWithIndicator:matchedIndicator
|
|
162
|
+
start:start
|
|
163
|
+
end:cursor
|
|
164
|
+
text:[token substringFromIndex:matchedIndicator.length]];
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
@end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#import <Foundation/Foundation.h>
|
|
4
|
+
|
|
5
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
6
|
+
|
|
7
|
+
typedef struct {
|
|
8
|
+
NSRange range;
|
|
9
|
+
BOOL shouldRemove;
|
|
10
|
+
} ENRMAdjustedRange;
|
|
11
|
+
|
|
12
|
+
/// Shared shift/clip logic applied to a stored range after a text edit that
|
|
13
|
+
/// replaced `deletedLength` characters at `editLocation` with `insertedLength`
|
|
14
|
+
/// characters. Both ENRMFormattingStore and ENRMBlockStore delegate here so the
|
|
15
|
+
/// overlap classification lives in exactly one place. `shouldRemove` is set
|
|
16
|
+
/// when the range was deleted outright or clipped to zero length.
|
|
17
|
+
///
|
|
18
|
+
/// Insert-only edits at exactly the range end do NOT grow the range — the typed
|
|
19
|
+
/// characters stay outside it. An insert at exactly the range start grows the
|
|
20
|
+
/// range only when `growsAtStartOnInsert` is YES; otherwise the range shifts and
|
|
21
|
+
/// the typed characters stay outside it. Whether boundary text joins the range is
|
|
22
|
+
/// otherwise decided elsewhere: pending styles for inline ranges, line
|
|
23
|
+
/// re-normalization for block ranges.
|
|
24
|
+
///
|
|
25
|
+
/// `inheritsReplacementAtStart`: when YES, a replacement whose deletion starts
|
|
26
|
+
/// at the range start lets the inserted text join the range (UIKit attribute
|
|
27
|
+
/// inheritance); when NO, the old clip/remove behavior applies.
|
|
28
|
+
///
|
|
29
|
+
/// `growsAtStartOnInsert`: when YES, a pure insert at the range start grows the
|
|
30
|
+
/// range to cover the inserted text instead of shifting the range past it. Block
|
|
31
|
+
/// ranges own their whole line, so a character typed at the line start must keep
|
|
32
|
+
/// the line's block; inline styles must NOT set this (a character typed before a
|
|
33
|
+
/// bold run must not become bold).
|
|
34
|
+
ENRMAdjustedRange ENRMAdjustRangeForEdit(NSRange range, NSUInteger editLocation, NSUInteger deletedLength,
|
|
35
|
+
NSUInteger insertedLength, BOOL inheritsReplacementAtStart,
|
|
36
|
+
BOOL growsAtStartOnInsert);
|
|
37
|
+
|
|
38
|
+
NS_ASSUME_NONNULL_END
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
#import "ENRMRangeEditAdjustment.h"
|
|
2
|
+
|
|
3
|
+
typedef NS_ENUM(NSInteger, EditOverlap) {
|
|
4
|
+
EditOverlapBeforeEdit,
|
|
5
|
+
EditOverlapAfterEdit,
|
|
6
|
+
EditOverlapFullyDeleted,
|
|
7
|
+
EditOverlapDeletedInside,
|
|
8
|
+
EditOverlapClippedEnd,
|
|
9
|
+
EditOverlapClippedStart,
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
static EditOverlap classifyOverlap(NSUInteger rangeStart, NSUInteger rangeEnd, NSUInteger editLocation,
|
|
13
|
+
NSUInteger deleteEnd)
|
|
14
|
+
{
|
|
15
|
+
if (rangeEnd <= editLocation)
|
|
16
|
+
return EditOverlapBeforeEdit;
|
|
17
|
+
if (rangeStart >= deleteEnd)
|
|
18
|
+
return EditOverlapAfterEdit;
|
|
19
|
+
if (rangeStart >= editLocation && rangeEnd <= deleteEnd)
|
|
20
|
+
return EditOverlapFullyDeleted;
|
|
21
|
+
if (rangeStart < editLocation && rangeEnd > deleteEnd)
|
|
22
|
+
return EditOverlapDeletedInside;
|
|
23
|
+
if (rangeStart < editLocation && rangeEnd <= deleteEnd)
|
|
24
|
+
return EditOverlapClippedEnd;
|
|
25
|
+
return EditOverlapClippedStart;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
ENRMAdjustedRange ENRMAdjustRangeForEdit(NSRange range, NSUInteger editLocation, NSUInteger deletedLength,
|
|
29
|
+
NSUInteger insertedLength, BOOL inheritsReplacementAtStart,
|
|
30
|
+
BOOL growsAtStartOnInsert)
|
|
31
|
+
{
|
|
32
|
+
ENRMAdjustedRange result = {range, NO};
|
|
33
|
+
NSUInteger rangeStart = range.location;
|
|
34
|
+
NSUInteger rangeEnd = NSMaxRange(range);
|
|
35
|
+
|
|
36
|
+
if (deletedLength > 0) {
|
|
37
|
+
NSUInteger deleteEnd = editLocation + deletedLength;
|
|
38
|
+
BOOL inheritsReplacement = inheritsReplacementAtStart && insertedLength > 0 && rangeStart == editLocation;
|
|
39
|
+
|
|
40
|
+
switch (classifyOverlap(rangeStart, rangeEnd, editLocation, deleteEnd)) {
|
|
41
|
+
case EditOverlapBeforeEdit:
|
|
42
|
+
break;
|
|
43
|
+
|
|
44
|
+
case EditOverlapAfterEdit:
|
|
45
|
+
result.range = NSMakeRange(rangeStart - deletedLength + insertedLength, range.length);
|
|
46
|
+
break;
|
|
47
|
+
|
|
48
|
+
case EditOverlapFullyDeleted:
|
|
49
|
+
if (inheritsReplacement) {
|
|
50
|
+
result.range = NSMakeRange(editLocation, insertedLength);
|
|
51
|
+
} else {
|
|
52
|
+
result.shouldRemove = YES;
|
|
53
|
+
}
|
|
54
|
+
break;
|
|
55
|
+
|
|
56
|
+
case EditOverlapDeletedInside:
|
|
57
|
+
result.range = NSMakeRange(rangeStart, range.length - deletedLength + insertedLength);
|
|
58
|
+
break;
|
|
59
|
+
|
|
60
|
+
case EditOverlapClippedEnd: {
|
|
61
|
+
NSUInteger newEnd = editLocation + insertedLength;
|
|
62
|
+
NSUInteger newLength = newEnd > rangeStart ? newEnd - rangeStart : 0;
|
|
63
|
+
result.range = NSMakeRange(rangeStart, newLength);
|
|
64
|
+
result.shouldRemove = (newLength == 0);
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
case EditOverlapClippedStart: {
|
|
69
|
+
NSUInteger charsClipped = deleteEnd - rangeStart;
|
|
70
|
+
NSUInteger survivingLength = range.length - charsClipped;
|
|
71
|
+
if (inheritsReplacement) {
|
|
72
|
+
result.range = NSMakeRange(editLocation, insertedLength + survivingLength);
|
|
73
|
+
} else {
|
|
74
|
+
result.range = NSMakeRange(editLocation + insertedLength, survivingLength);
|
|
75
|
+
result.shouldRemove = (survivingLength == 0);
|
|
76
|
+
}
|
|
77
|
+
break;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
} else if (insertedLength > 0) {
|
|
81
|
+
if (rangeStart == editLocation && growsAtStartOnInsert) {
|
|
82
|
+
result.range = NSMakeRange(rangeStart, range.length + insertedLength);
|
|
83
|
+
} else if (rangeStart >= editLocation) {
|
|
84
|
+
result.range = NSMakeRange(rangeStart + insertedLength, range.length);
|
|
85
|
+
} else if (editLocation < rangeEnd) {
|
|
86
|
+
result.range = NSMakeRange(rangeStart, range.length + insertedLength);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return result;
|
|
91
|
+
}
|