react-native-enriched-markdown-scaffold 0.7.4-scaffold.9 → 1.0.2-scaffold.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +54 -8
- package/ReactNativeEnrichedMarkdown.podspec +82 -73
- package/android/build.gradle +186 -1
- package/android/consumer-rules.pro +1 -1
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownManagerDelegate.java +9 -0
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownManagerInterface.java +3 -0
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextInputManagerDelegate.java +24 -0
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextInputManagerInterface.java +8 -0
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextManagerDelegate.java +9 -0
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextManagerInterface.java +3 -0
- package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/EventEmitters.cpp +75 -0
- package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/EventEmitters.h +63 -0
- package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/Props.cpp +35 -0
- package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/Props.h +886 -23
- package/android/src/main/baseline-prof.txt +1 -1
- package/android/src/main/cpp/jni-adapter.cpp +74 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdown.kt +189 -13
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownInternalText.kt +17 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownManager.kt +50 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownText.kt +48 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownTextLayoutManager.kt +10 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownTextManager.kt +42 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/MeasurementStore.kt +82 -4
- package/android/src/main/java/com/swmansion/enriched/markdown/events/CopyPressEvent.kt +24 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/EnrichedMarkdownTextInputManager.kt +54 -4
- package/android/src/main/java/com/swmansion/enriched/markdown/input/EnrichedMarkdownTextInputView.kt +901 -462
- package/android/src/main/java/com/swmansion/enriched/markdown/input/MarkdownClipboard.kt +42 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/BlockEditCoordinator.kt +196 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/ClipboardCoordinator.kt +73 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/EditContext.kt +19 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/EditPipeline.kt +248 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/EditSession.kt +52 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/InputConnectionWrapper.kt +101 -7
- package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/LinkCoordinator.kt +69 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/MarkdownTextWatcher.kt +3 -3
- package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/MentionCoordinator.kt +118 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnChangeStateEvent.kt +26 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnContextMenuItemPressEvent.kt +26 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnInputKeyPressEvent.kt +24 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnPasteEvent.kt +24 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/BlockStore.kt +254 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/FormattingStore.kt +80 -87
- package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/InputFormatter.kt +109 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/InputParser.kt +116 -22
- package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/MarkdownSerializer.kt +167 -38
- package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/RangeEditAdjustment.kt +149 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/layout/InputEventEmitter.kt +66 -5
- package/android/src/main/java/com/swmansion/enriched/markdown/input/layout/InputMeasurementStore.kt +4 -2
- package/android/src/main/java/com/swmansion/enriched/markdown/input/model/BlockRange.kt +27 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/model/BlockType.kt +48 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/model/FormattingRange.kt +9 -4
- package/android/src/main/java/com/swmansion/enriched/markdown/input/model/InputFormatterStyle.kt +39 -2
- package/android/src/main/java/com/swmansion/enriched/markdown/input/model/MathAtom.kt +20 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/model/MathChipStyle.kt +1 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/input/model/MutableRangeBounds.kt +11 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/spans/InputBulletSpan.kt +82 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/spans/InputHeadingSpan.kt +58 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/spans/InputListItemSpacingSpan.kt +37 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/spans/InputOrderedListMarkerSpan.kt +63 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/styles/BlockHandler.kt +54 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/styles/HeadingBlockHandler.kt +27 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/styles/OrderedListBlockHandler.kt +38 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/styles/UnorderedListBlockHandler.kt +37 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/toolbar/InputContextMenu.kt +8 -26
- package/android/src/main/java/com/swmansion/enriched/markdown/parser/MarkdownASTNode.kt +1 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/parser/Parser.kt +1 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/BlockStyleContext.kt +9 -2
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/BlockquoteRenderer.kt +100 -12
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/CodeBlockRenderer.kt +16 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/HeadingRenderer.kt +4 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListContextManager.kt +2 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListItemRenderer.kt +74 -18
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListRenderer.kt +43 -4
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/NodeRenderer.kt +9 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/SoftBreakRenderer.kt +16 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/SpanStyleCache.kt +30 -27
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/BaseListSpan.kt +24 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/BlockquoteSpan.kt +174 -24
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/CodeBackgroundSpan.kt +27 -3
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/CodeBlockSpan.kt +13 -16
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/CodeSpan.kt +1 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/EmphasisSpan.kt +1 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/ImageSpan.kt +182 -46
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/ListItemSpacingSpan.kt +33 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/ListMarkerAnchorSpan.kt +38 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/OrderedListSpan.kt +2 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/StrongSpan.kt +1 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/TaskListSpan.kt +3 -2
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/UnorderedListSpan.kt +3 -2
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/BlockquoteStyle.kt +6 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/CodeBlockStyle.kt +26 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/ImageStyle.kt +7 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/ListStyle.kt +4 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/StyleConfig.kt +13 -4
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/TableStyle.kt +6 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/CodeBlockHighlighter.kt +90 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/CodeBlockNode.kt +57 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/FeatureFlags.kt +1 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/MarkdownSegment.kt +9 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/MarkdownViewManagerUtils.kt +37 -7
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/ReadableMapExtensions.kt +3 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/RenderedSegment.kt +10 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/SegmentSignature.kt +1 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/StreamingMarkdownFilter.kt +83 -5
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/serialization/MarkdownASTSerializer.kt +4 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/input/MarkdownStyleParser.kt +74 -44
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/input/PasteTextUtils.kt +20 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/ImageCache.kt +26 -3
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/ImageDownloader.kt +22 -9
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/LocalImageLoader.kt +161 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/extensions/TextPaintExtensions.kt +23 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/interaction/CheckboxTouchHelper.kt +7 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/interaction/TaskListTapUtils.kt +41 -21
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/span/BlockSpacing.kt +15 -8
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/LinkLongPressMovementMethod.kt +58 -27
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/SelectionActionMode.kt +49 -15
- package/android/src/main/java/com/swmansion/enriched/markdown/views/BlockMenuOptions.kt +45 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/views/CodeBlockContainerView.kt +396 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/views/ContextMenuPopup.kt +9 -6
- package/android/src/main/java/com/swmansion/enriched/markdown/views/CopyGlyph.kt +101 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/views/TableContainerView.kt +36 -9
- package/android/src/main/jni/CMakeLists.txt +53 -0
- package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownContainerShadowNode.cpp +10 -0
- package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownContainerShadowNode.h +11 -2
- package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextShadowNode.cpp +10 -0
- package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextShadowNode.h +12 -2
- package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextState.cpp +9 -0
- package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextState.h +24 -0
- package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/conversions.h +16 -0
- package/android/src/math/java/com/swmansion/enriched/markdown/input/math/MathChipControllerImpl.kt +21 -4
- package/android/src/math/java/com/swmansion/enriched/markdown/renderer/MathInlineRenderer.kt +7 -2
- package/android/src/math/java/com/swmansion/enriched/markdown/spans/MathChipSpan.kt +1 -1
- package/android/src/math/java/com/swmansion/enriched/markdown/views/MathContainerView.kt +6 -4
- package/cpp/highlight/CodeBlockHighlighter.cpp +284 -0
- package/cpp/highlight/CodeBlockHighlighter.hpp +66 -0
- package/cpp/highlight/CodeBlockLanguages.cpp +138 -0
- package/cpp/highlight/CodeBlockLanguages.hpp +25 -0
- package/cpp/highlight/HighlightGrammars.hpp +28 -0
- package/cpp/highlight/code_highlight_podspec.rb +211 -0
- package/cpp/highlight/gen-registry.mjs +155 -0
- package/cpp/highlight/grammar-versions.json +159 -0
- package/cpp/highlight/vendor/generated/generated_queries.h +1665 -0
- package/cpp/highlight/vendor/generated/generated_registry.cpp +59 -0
- package/cpp/parser/MD4CParser.cpp +173 -61
- package/cpp/parser/MD4CParser.hpp +1 -0
- package/cpp/parser/MarkdownASTNode.hpp +2 -1
- package/cpp/wasm/ASTSerializer.cpp +2 -0
- package/cpp/wasm/build.sh +1 -0
- package/cpp/wasm/md4c_wasm.cpp +3 -1
- package/docs/ACCESSIBILITY.md +14 -2
- package/docs/API_REFERENCE.md +234 -12
- package/docs/BREAKING_CHANGES.md +129 -0
- package/docs/CODE_HIGHLIGHT.md +133 -0
- package/docs/COPY_OPTIONS.md +47 -3
- package/docs/ELEMENTS_STRUCTURE.md +52 -4
- package/docs/IMAGE_CACHING.md +30 -0
- package/docs/INPUT.md +108 -11
- package/docs/LATEX_MATH.md +87 -45
- package/docs/MACOS.md +1 -1
- package/docs/MARKDOWN_STREAMING.md +27 -1
- package/docs/NATIVE_ASSETS.md +127 -0
- package/docs/RTL.md +1 -1
- package/docs/STYLES.md +46 -6
- package/docs/TESTING.md +112 -0
- package/docs/TEXT.md +16 -6
- package/docs/WEB.md +3 -1
- package/ios/EnrichedMarkdown.h +7 -0
- package/ios/EnrichedMarkdown.mm +284 -75
- package/ios/EnrichedMarkdownText.h +7 -0
- package/ios/EnrichedMarkdownText.mm +101 -73
- package/ios/attachments/ENRMImageAttachment.h +9 -0
- package/ios/attachments/ENRMImageAttachment.m +143 -40
- package/ios/attachments/ENRMMathInlineAttachment.h +2 -0
- package/ios/attachments/ENRMMathInlineAttachment.m +48 -81
- package/ios/attachments/ENRMMathInlineAttachmentShared.h +2 -0
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/EventEmitters.cpp +75 -0
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/EventEmitters.h +63 -0
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/Props.cpp +35 -0
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/Props.h +886 -23
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/RCTComponentViewHelpers.h +131 -0
- package/ios/input/ENRMAutoLinkDetector.h +2 -1
- package/ios/input/ENRMAutoLinkDetector.mm +79 -41
- package/ios/input/ENRMBlockEditCoordinator.h +71 -0
- package/ios/input/ENRMBlockEditCoordinator.mm +195 -0
- package/ios/input/ENRMBlockRange.h +28 -0
- package/ios/input/ENRMBlockRange.mm +30 -0
- package/ios/input/ENRMBlockStore.h +56 -0
- package/ios/input/ENRMBlockStore.mm +275 -0
- package/ios/input/ENRMClipboardCoordinator.h +45 -0
- package/ios/input/ENRMClipboardCoordinator.mm +120 -0
- package/ios/input/ENRMDetectorPipeline.h +2 -1
- package/ios/input/ENRMEditPipeline.h +76 -0
- package/ios/input/ENRMEditPipeline.mm +228 -0
- package/ios/input/ENRMEditSession.h +36 -0
- package/ios/input/ENRMEditSession.mm +63 -0
- package/ios/input/ENRMFormattingStore.h +17 -0
- package/ios/input/ENRMFormattingStore.mm +95 -105
- package/ios/input/ENRMInputBlockType.h +91 -0
- package/ios/input/ENRMInputBlockType.mm +5 -0
- package/ios/input/ENRMInputDecorationDrawer.h +18 -0
- package/ios/input/ENRMInputEventEmitter.h +56 -0
- package/ios/input/ENRMInputEventEmitter.mm +308 -0
- package/ios/input/ENRMInputFormatter.h +29 -69
- package/ios/input/ENRMInputFormatter.mm +216 -124
- package/ios/input/ENRMInputFormatterStyle.h +99 -0
- package/ios/input/ENRMInputFormatterStyle.mm +188 -0
- package/ios/input/ENRMInputLayoutManager.h +9 -0
- package/ios/input/ENRMInputLayoutManager.mm +30 -0
- package/ios/input/ENRMInputListMarkerDrawer.h +32 -0
- package/ios/input/ENRMInputListMarkerDrawer.mm +426 -0
- package/ios/input/ENRMInputParser.h +5 -6
- package/ios/input/ENRMInputParser.mm +461 -178
- package/ios/input/ENRMInputRemend.mm +2 -2
- package/ios/input/ENRMInputStyleStateBuilder.h +40 -0
- package/ios/input/ENRMInputStyleStateBuilder.mm +60 -0
- package/ios/input/ENRMInputTextView.mm +103 -8
- package/ios/input/ENRMInputTypingAttributesController.h +42 -0
- package/ios/input/ENRMInputTypingAttributesController.mm +203 -0
- package/ios/input/ENRMLinkCoordinator.h +41 -0
- package/ios/input/ENRMLinkCoordinator.mm +89 -0
- package/ios/input/ENRMMarkdownSerializer.h +29 -5
- package/ios/input/ENRMMarkdownSerializer.mm +170 -48
- package/ios/input/ENRMMathAtom.h +26 -0
- package/ios/input/ENRMMathAtom.mm +12 -0
- package/ios/input/ENRMMentionCoordinator.h +45 -0
- package/ios/input/ENRMMentionCoordinator.mm +167 -0
- package/ios/input/ENRMRangeEditAdjustment.h +38 -0
- package/ios/input/ENRMRangeEditAdjustment.mm +91 -0
- package/ios/input/ENRMRangeStoreUtils.h +39 -0
- package/ios/input/EnrichedMarkdownTextInput+ContextMenu.mm +6 -6
- package/ios/input/EnrichedMarkdownTextInput+Internal.h +11 -3
- package/ios/input/EnrichedMarkdownTextInput.h +7 -1
- package/ios/input/EnrichedMarkdownTextInput.mm +1089 -1023
- package/ios/input/InputStylePropsUtils.h +109 -68
- package/ios/input/internals/EnrichedMarkdownTextInputShadowNode.mm +2 -1
- package/ios/input/styles/ENRMBlockHandler.h +46 -0
- package/ios/input/styles/ENRMHeadingBlockHandler.h +15 -0
- package/ios/input/styles/ENRMHeadingBlockHandler.mm +38 -0
- package/ios/input/styles/ENRMOrderedListBlockHandler.h +14 -0
- package/ios/input/styles/ENRMOrderedListBlockHandler.mm +48 -0
- package/ios/input/styles/ENRMUnorderedListBlockHandler.h +15 -0
- package/ios/input/styles/ENRMUnorderedListBlockHandler.mm +51 -0
- package/ios/internals/ENRMViewFreeMeasurement.h +331 -0
- package/ios/internals/EnrichedMarkdownShadowNode.h +1 -3
- package/ios/internals/EnrichedMarkdownShadowNode.mm +16 -20
- package/ios/internals/EnrichedMarkdownTextShadowNode.h +1 -3
- package/ios/internals/EnrichedMarkdownTextShadowNode.mm +15 -20
- package/ios/internals/MeasurementCache.h +33 -7
- package/ios/internals/ShadowMeasurementUtils.h +63 -58
- package/ios/math/ENRMMathChipController.h +74 -0
- package/ios/math/ENRMMathChipController.mm +476 -0
- package/ios/math/ENRMRaTeXBridge.swift +4 -1
- package/ios/parser/ENRMMarkdownParser.h +1 -8
- package/ios/parser/ENRMMarkdownParser.mm +2 -11
- package/ios/parser/MarkdownASTNode.h +2 -1
- package/ios/parser/MarkdownParserBridge.mm +4 -0
- package/ios/renderer/AttributedRenderer.m +20 -2
- package/ios/renderer/BaseRenderer.h +17 -2
- package/ios/renderer/BaseRenderer.m +30 -0
- package/ios/renderer/BlockquoteRenderer.h +1 -1
- package/ios/renderer/BlockquoteRenderer.m +144 -35
- package/ios/renderer/CodeBlockRenderer.h +1 -1
- package/ios/renderer/CodeBlockRenderer.m +27 -23
- package/ios/renderer/CodeRenderer.h +1 -1
- package/ios/renderer/CodeRenderer.m +3 -1
- package/ios/renderer/ENRMImageRenderer.h +1 -1
- package/ios/renderer/ENRMImageRenderer.m +5 -1
- package/ios/renderer/ENRMMathInlineRenderer.h +1 -1
- package/ios/renderer/ENRMMathInlineRenderer.m +5 -1
- package/ios/renderer/ENRMSpoilerRenderer.h +1 -1
- package/ios/renderer/ENRMSpoilerRenderer.m +3 -1
- package/ios/renderer/EmphasisRenderer.h +1 -1
- package/ios/renderer/EmphasisRenderer.m +3 -1
- package/ios/renderer/HeadingRenderer.h +1 -1
- package/ios/renderer/HeadingRenderer.m +13 -6
- package/ios/renderer/HighlightRenderer.h +1 -1
- package/ios/renderer/HighlightRenderer.m +3 -1
- package/ios/renderer/LinkRenderer.h +1 -1
- package/ios/renderer/LinkRenderer.m +3 -1
- package/ios/renderer/ListItemRenderer.h +13 -1
- package/ios/renderer/ListItemRenderer.m +102 -44
- package/ios/renderer/ListRenderer.h +2 -2
- package/ios/renderer/ListRenderer.m +63 -25
- package/ios/renderer/ParagraphRenderer.h +1 -1
- package/ios/renderer/ParagraphRenderer.m +16 -8
- package/ios/renderer/RenderContext.h +10 -0
- package/ios/renderer/RenderContext.m +44 -0
- package/ios/renderer/RendererFactory.m +14 -0
- package/ios/renderer/StrikethroughRenderer.h +1 -1
- package/ios/renderer/StrikethroughRenderer.m +3 -1
- package/ios/renderer/StrongRenderer.h +1 -1
- package/ios/renderer/StrongRenderer.m +3 -1
- package/ios/renderer/SubscriptRenderer.h +1 -1
- package/ios/renderer/SubscriptRenderer.m +3 -1
- package/ios/renderer/SuperscriptRenderer.h +1 -1
- package/ios/renderer/SuperscriptRenderer.m +3 -1
- package/ios/renderer/TextRenderer.h +2 -2
- package/ios/renderer/TextRenderer.m +3 -1
- package/ios/renderer/ThematicBreakRenderer.h +1 -1
- package/ios/renderer/ThematicBreakRenderer.m +3 -1
- package/ios/renderer/UnderlineRenderer.h +1 -1
- package/ios/renderer/UnderlineRenderer.m +3 -1
- package/ios/styles/StyleConfig.h +22 -0
- package/ios/styles/StyleConfig.mm +132 -0
- package/ios/utils/BlockquoteBorder.h +6 -0
- package/ios/utils/BlockquoteBorder.m +249 -52
- package/ios/utils/CodeBlockBackground.m +16 -2
- package/ios/utils/ENRMAtomicSize.h +65 -0
- package/ios/utils/ENRMBlockMenu.h +57 -0
- package/ios/utils/ENRMCodeBlockContent.h +37 -0
- package/ios/utils/ENRMCodeBlockContent.mm +79 -0
- package/ios/utils/ENRMCodeBlockHighlighter.h +37 -0
- package/ios/utils/ENRMCodeBlockHighlighter.mm +51 -0
- package/ios/utils/ENRMFeatureFlags.h +7 -0
- package/ios/utils/ENRMImageDownloader.h +11 -1
- package/ios/utils/ENRMImageDownloader.m +60 -16
- package/ios/utils/ENRMLocalImageLoader.h +31 -0
- package/ios/utils/ENRMLocalImageLoader.m +68 -0
- package/ios/utils/ENRMMathFallback.h +26 -0
- package/ios/utils/ENRMMathFallback.m +18 -0
- package/ios/utils/ENRMTextViewSetup.h +35 -17
- package/ios/utils/EditMenuUtils.h +22 -5
- package/ios/utils/EditMenuUtils.m +53 -9
- package/ios/utils/ImageRequestHeaderUtils.h +35 -0
- package/ios/utils/LastElementUtils.h +1 -0
- package/ios/utils/ListMarkerDrawer.m +29 -42
- package/ios/utils/MarkdownASTSerializer.m +4 -0
- package/ios/utils/ParagraphStyleUtils.h +5 -0
- package/ios/utils/ParagraphStyleUtils.m +77 -17
- package/ios/utils/RenderedMarkdownSegment.h +13 -1
- package/ios/utils/RenderedMarkdownSegment.m +20 -0
- package/ios/utils/SegmentRenderer.m +17 -4
- package/ios/utils/StreamingMarkdownFilter.h +11 -1
- package/ios/utils/StreamingMarkdownFilter.m +98 -2
- package/ios/utils/StylePropsUtils.h +63 -0
- package/ios/utils/TaskListTapUtils.m +24 -0
- package/ios/views/ENRMCodeBlockContainerView.h +53 -0
- package/ios/views/ENRMCodeBlockContainerView.m +559 -0
- package/ios/views/ENRMMathContainerView.h +16 -0
- package/ios/views/ENRMMathContainerView.m +74 -19
- package/ios/views/TableContainerView.h +22 -0
- package/ios/views/TableContainerView.m +261 -175
- package/jest.d.ts +1 -0
- package/jest.js +5 -0
- package/lib/module/EnrichedMarkdownNativeComponent.ts +73 -0
- package/lib/module/EnrichedMarkdownTextInput.js +84 -5
- package/lib/module/EnrichedMarkdownTextInput.js.map +1 -1
- package/lib/module/EnrichedMarkdownTextInputNativeComponent.ts +78 -5
- package/lib/module/EnrichedMarkdownTextNativeComponent.ts +74 -0
- package/lib/module/headingDefaults.js +34 -0
- package/lib/module/headingDefaults.js.map +1 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/jest/index.js +191 -0
- package/lib/module/jest/index.js.map +1 -0
- package/lib/module/native/EnrichedMarkdownText.js +37 -5
- package/lib/module/native/EnrichedMarkdownText.js.map +1 -1
- package/lib/module/normalizeMarkdownStyle.js +81 -19
- package/lib/module/normalizeMarkdownStyle.js.map +1 -1
- package/lib/module/normalizeMarkdownStyle.web.js +56 -18
- package/lib/module/normalizeMarkdownStyle.web.js.map +1 -1
- package/lib/module/normalizeMarkdownTextInputStyle.js +62 -15
- package/lib/module/normalizeMarkdownTextInputStyle.js.map +1 -1
- package/lib/module/normalizeMenuItem.js +1 -1
- package/lib/module/utils/textInputState.js +26 -0
- package/lib/module/utils/textInputState.js.map +1 -0
- package/lib/module/web/EnrichedMarkdownText.js +9 -5
- package/lib/module/web/EnrichedMarkdownText.js.map +1 -1
- package/lib/module/web/parseMarkdown.js +4 -3
- package/lib/module/web/parseMarkdown.js.map +1 -1
- package/lib/module/web/renderers/InlineRenderers.js +6 -0
- package/lib/module/web/renderers/InlineRenderers.js.map +1 -1
- package/lib/module/web/renderers/ListRenderers.js +7 -2
- package/lib/module/web/renderers/ListRenderers.js.map +1 -1
- package/lib/module/web/renderers/index.js +7 -4
- package/lib/module/web/renderers/index.js.map +1 -1
- package/lib/module/web/styles.js +83 -6
- package/lib/module/web/styles.js.map +1 -1
- package/lib/module/web/utils.js +1 -0
- package/lib/module/web/utils.js.map +1 -1
- package/lib/module/web/wasm/md4c.js +0 -0
- package/lib/module/web/wasm/md4c.js.map +1 -1
- package/lib/typescript/src/EnrichedMarkdownNativeComponent.d.ts +66 -0
- package/lib/typescript/src/EnrichedMarkdownNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/EnrichedMarkdownTextInput.d.ts +94 -9
- package/lib/typescript/src/EnrichedMarkdownTextInput.d.ts.map +1 -1
- package/lib/typescript/src/EnrichedMarkdownTextInputNativeComponent.d.ts +69 -5
- package/lib/typescript/src/EnrichedMarkdownTextInputNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/EnrichedMarkdownTextNativeComponent.d.ts +66 -0
- package/lib/typescript/src/EnrichedMarkdownTextNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/headingDefaults.d.ts +9 -0
- package/lib/typescript/src/headingDefaults.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +2 -2
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/index.web.d.ts +1 -1
- package/lib/typescript/src/index.web.d.ts.map +1 -1
- package/lib/typescript/src/jest/index.d.ts +6 -0
- package/lib/typescript/src/jest/index.d.ts.map +1 -0
- package/lib/typescript/src/native/EnrichedMarkdownText.d.ts +3 -3
- package/lib/typescript/src/native/EnrichedMarkdownText.d.ts.map +1 -1
- package/lib/typescript/src/normalizeMarkdownStyle.d.ts.map +1 -1
- package/lib/typescript/src/normalizeMarkdownStyle.web.d.ts.map +1 -1
- package/lib/typescript/src/normalizeMarkdownTextInputStyle.d.ts +19 -5
- package/lib/typescript/src/normalizeMarkdownTextInputStyle.d.ts.map +1 -1
- package/lib/typescript/src/types/MarkdownStyle.d.ts +72 -0
- package/lib/typescript/src/types/MarkdownStyle.d.ts.map +1 -1
- package/lib/typescript/src/types/MarkdownStyleInternal.d.ts +27 -0
- package/lib/typescript/src/types/MarkdownStyleInternal.d.ts.map +1 -1
- package/lib/typescript/src/types/MarkdownTextProps.d.ts +104 -9
- package/lib/typescript/src/types/MarkdownTextProps.d.ts.map +1 -1
- package/lib/typescript/src/types/MarkdownTextProps.web.d.ts +19 -0
- package/lib/typescript/src/types/MarkdownTextProps.web.d.ts.map +1 -1
- package/lib/typescript/src/types/events.d.ts +19 -0
- package/lib/typescript/src/types/events.d.ts.map +1 -1
- package/lib/typescript/src/utils/textInputState.d.ts +24 -0
- package/lib/typescript/src/utils/textInputState.d.ts.map +1 -0
- package/lib/typescript/src/web/EnrichedMarkdownText.d.ts +1 -1
- package/lib/typescript/src/web/EnrichedMarkdownText.d.ts.map +1 -1
- package/lib/typescript/src/web/parseMarkdown.d.ts +1 -1
- package/lib/typescript/src/web/parseMarkdown.d.ts.map +1 -1
- package/lib/typescript/src/web/renderers/InlineRenderers.d.ts.map +1 -1
- package/lib/typescript/src/web/renderers/ListRenderers.d.ts.map +1 -1
- package/lib/typescript/src/web/renderers/index.d.ts +2 -1
- package/lib/typescript/src/web/renderers/index.d.ts.map +1 -1
- package/lib/typescript/src/web/styles.d.ts +2 -1
- package/lib/typescript/src/web/styles.d.ts.map +1 -1
- package/lib/typescript/src/web/types.d.ts +6 -2
- package/lib/typescript/src/web/types.d.ts.map +1 -1
- package/lib/typescript/src/web/utils.d.ts.map +1 -1
- package/package.json +36 -9
- package/postinstall.mjs +131 -0
- package/ratex-version.json +21 -0
- package/src/EnrichedMarkdownNativeComponent.ts +73 -0
- package/src/EnrichedMarkdownTextInput.tsx +159 -8
- package/src/EnrichedMarkdownTextInputNativeComponent.ts +78 -5
- package/src/EnrichedMarkdownTextNativeComponent.ts +74 -0
- package/src/headingDefaults.ts +21 -0
- package/src/index.tsx +9 -0
- package/src/index.web.tsx +1 -0
- package/src/jest/index.tsx +215 -0
- package/src/native/EnrichedMarkdownText.tsx +53 -2
- package/src/normalizeMarkdownStyle.ts +102 -16
- package/src/normalizeMarkdownStyle.web.ts +63 -15
- package/src/normalizeMarkdownTextInputStyle.ts +110 -35
- package/src/normalizeMenuItem.ts +1 -1
- package/src/types/MarkdownStyle.ts +74 -0
- package/src/types/MarkdownStyleInternal.ts +39 -0
- package/src/types/MarkdownTextProps.ts +101 -9
- package/src/types/MarkdownTextProps.web.ts +19 -0
- package/src/types/events.ts +21 -0
- package/src/utils/textInputState.ts +35 -0
- package/src/web/EnrichedMarkdownText.tsx +16 -2
- package/src/web/parseMarkdown.ts +6 -2
- package/src/web/renderers/InlineRenderers.tsx +5 -0
- package/src/web/renderers/ListRenderers.tsx +14 -2
- package/src/web/renderers/index.tsx +6 -2
- package/src/web/styles.ts +89 -5
- package/src/web/types.ts +6 -1
- package/src/web/utils.ts +1 -0
- package/src/web/wasm/md4c.js +0 -0
- package/vendor-grammars.mjs +511 -0
- package/vendor-ratex.mjs +173 -0
- package/app.plugin.js +0 -2
- package/plugin/build/withAndroidMath.js +0 -19
- package/plugin/build/withIosMath.js +0 -28
- package/plugin/build/withReactNativeEnrichedMarkdown.js +0 -11
- package/plugin/src/withAndroidMath.ts +0 -24
- package/plugin/src/withIosMath.ts +0 -35
- package/plugin/src/withReactNativeEnrichedMarkdown.ts +0 -17
- package/plugin/tsconfig.build.json +0 -16
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
#import "ENRMEditPipeline.h"
|
|
2
|
+
#import "ENRMBlockHandler.h"
|
|
3
|
+
#import "ENRMBlockStore.h"
|
|
4
|
+
#import "ENRMDetectorPipeline.h"
|
|
5
|
+
#import "ENRMFormattingRange.h"
|
|
6
|
+
#import "ENRMFormattingStore.h"
|
|
7
|
+
#import "ENRMInputFormatter.h"
|
|
8
|
+
#import "ENRMUIKit.h"
|
|
9
|
+
|
|
10
|
+
@implementation ENRMEditContext
|
|
11
|
+
|
|
12
|
+
- (instancetype)initWithEditLocation:(NSUInteger)editLocation
|
|
13
|
+
deletedLength:(NSUInteger)deletedLength
|
|
14
|
+
insertedLength:(NSUInteger)insertedLength
|
|
15
|
+
preEditReplacedNewline:(BOOL)preEditReplacedNewline
|
|
16
|
+
preEditBlockType:(ENRMInputBlockType)preEditBlockType
|
|
17
|
+
preEditBlockLevel:(NSInteger)preEditBlockLevel
|
|
18
|
+
preEditParagraphWasEmpty:(BOOL)preEditParagraphWasEmpty
|
|
19
|
+
pendingStyles:(NSSet<NSNumber *> *)pendingStyles
|
|
20
|
+
pendingStyleRemovals:(NSSet<NSNumber *> *)pendingStyleRemovals
|
|
21
|
+
{
|
|
22
|
+
if (self = [super init]) {
|
|
23
|
+
_editLocation = editLocation;
|
|
24
|
+
_deletedLength = deletedLength;
|
|
25
|
+
_insertedLength = insertedLength;
|
|
26
|
+
_preEditReplacedNewline = preEditReplacedNewline;
|
|
27
|
+
_preEditBlockType = preEditBlockType;
|
|
28
|
+
_preEditBlockLevel = preEditBlockLevel;
|
|
29
|
+
_preEditParagraphWasEmpty = preEditParagraphWasEmpty;
|
|
30
|
+
_pendingStyles = [pendingStyles copy];
|
|
31
|
+
_pendingStyleRemovals = [pendingStyleRemovals copy];
|
|
32
|
+
}
|
|
33
|
+
return self;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
@end
|
|
37
|
+
|
|
38
|
+
@implementation ENRMEditPipeline {
|
|
39
|
+
ENRMFormattingStore *_formattingStore;
|
|
40
|
+
ENRMBlockStore *_blockStore;
|
|
41
|
+
ENRMInputFormatter *_formatter;
|
|
42
|
+
ENRMDetectorPipeline *_detectorPipeline;
|
|
43
|
+
__weak id<ENRMEditPipelineHost> _host;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
- (instancetype)initWithFormattingStore:(ENRMFormattingStore *)formattingStore
|
|
47
|
+
blockStore:(ENRMBlockStore *)blockStore
|
|
48
|
+
formatter:(ENRMInputFormatter *)formatter
|
|
49
|
+
detectorPipeline:(ENRMDetectorPipeline *)detectorPipeline
|
|
50
|
+
host:(id<ENRMEditPipelineHost>)host
|
|
51
|
+
{
|
|
52
|
+
if (self = [super init]) {
|
|
53
|
+
_formattingStore = formattingStore;
|
|
54
|
+
_blockStore = blockStore;
|
|
55
|
+
_formatter = formatter;
|
|
56
|
+
_detectorPipeline = detectorPipeline;
|
|
57
|
+
_host = host;
|
|
58
|
+
}
|
|
59
|
+
return self;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
#pragma mark - Public API
|
|
63
|
+
|
|
64
|
+
- (BOOL)processTextChangeWithContext:(ENRMEditContext *)context
|
|
65
|
+
{
|
|
66
|
+
NSUInteger editLocation = context.editLocation;
|
|
67
|
+
NSUInteger insertedLength = context.insertedLength;
|
|
68
|
+
|
|
69
|
+
[self adjustStoresForEditAtLocation:editLocation deletedLength:context.deletedLength insertedLength:insertedLength];
|
|
70
|
+
|
|
71
|
+
NSString *plainText = [_host plainText];
|
|
72
|
+
|
|
73
|
+
if (insertedLength > 0) {
|
|
74
|
+
BOOL insertedHasGlyphContent = [self insertedHasGlyphContentAtLocation:editLocation
|
|
75
|
+
length:insertedLength
|
|
76
|
+
text:plainText];
|
|
77
|
+
[self applyPendingStylesWithContext:context plainText:plainText hasGlyphContent:insertedHasGlyphContent];
|
|
78
|
+
|
|
79
|
+
if (!insertedHasGlyphContent && insertedLength == 1) {
|
|
80
|
+
[self reconcileBlockContinuationAfterNewlineAt:editLocation
|
|
81
|
+
previousItemWasEmpty:context.preEditParagraphWasEmpty
|
|
82
|
+
preEditBlockType:context.preEditBlockType
|
|
83
|
+
preEditBlockLevel:context.preEditBlockLevel];
|
|
84
|
+
// Continuation re-seeds fresh block ranges whose ordinal defaults to 1;
|
|
85
|
+
// normalize again so the list-metadata pass renumbers the adjacent run.
|
|
86
|
+
[_blockStore normalizeToLineBoundsInText:[_host plainText]];
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Determine whether the edit touched a newline (for full-vs-scoped formatting).
|
|
91
|
+
BOOL touchedNewline = context.preEditReplacedNewline;
|
|
92
|
+
if (!touchedNewline && insertedLength > 0) {
|
|
93
|
+
NSString *postEditText = [_host plainText];
|
|
94
|
+
NSUInteger insertedEnd = MIN(editLocation + insertedLength, postEditText.length);
|
|
95
|
+
if (editLocation < insertedEnd) {
|
|
96
|
+
NSRange insertedRun = NSMakeRange(editLocation, insertedEnd - editLocation);
|
|
97
|
+
touchedNewline = [postEditText rangeOfCharacterFromSet:[NSCharacterSet newlineCharacterSet]
|
|
98
|
+
options:0
|
|
99
|
+
range:insertedRun]
|
|
100
|
+
.location != NSNotFound;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return touchedNewline;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
- (NSString *)adjustStoresForEditAtLocation:(NSUInteger)editLocation
|
|
108
|
+
deletedLength:(NSUInteger)deletedLength
|
|
109
|
+
insertedLength:(NSUInteger)insertedLength
|
|
110
|
+
{
|
|
111
|
+
[_formattingStore adjustForEditAtLocation:editLocation deletedLength:deletedLength insertedLength:insertedLength];
|
|
112
|
+
[_blockStore adjustForEditAtLocation:editLocation deletedLength:deletedLength insertedLength:insertedLength];
|
|
113
|
+
[self pruneOrphanedBlockAnchors];
|
|
114
|
+
NSString *plainText = [_host plainText];
|
|
115
|
+
[_blockStore normalizeToLineBoundsInText:plainText];
|
|
116
|
+
return plainText;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
- (void)pruneOrphanedBlockAnchors
|
|
120
|
+
{
|
|
121
|
+
NSString *text = [_host textStorage].string;
|
|
122
|
+
for (ENRMBlockRange *block in _blockStore.allRanges) {
|
|
123
|
+
if (!ENRMBlockTypePersistsWhenEmpty(block.type)) {
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
NSUInteger anchor = MIN(block.range.location, text.length);
|
|
127
|
+
BOOL atLineStart = [text paragraphRangeForRange:NSMakeRange(anchor, 0)].location == anchor;
|
|
128
|
+
if (!atLineStart) {
|
|
129
|
+
[_blockStore removeBlockInParagraphRange:NSMakeRange(anchor, 0) inText:text];
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
- (void)detectLinksAtLocation:(NSUInteger)editLocation insertedLength:(NSUInteger)insertedLength
|
|
135
|
+
{
|
|
136
|
+
NSString *currentText = [_host plainText];
|
|
137
|
+
NSUInteger clampedEditLocation = MIN(editLocation, currentText.length);
|
|
138
|
+
NSUInteger clampedInsertedLength = MIN(insertedLength, currentText.length - clampedEditLocation);
|
|
139
|
+
[_detectorPipeline processTextChange:currentText
|
|
140
|
+
modificationRange:NSMakeRange(clampedEditLocation, clampedInsertedLength)];
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
#pragma mark - Pending styles (private)
|
|
144
|
+
|
|
145
|
+
- (void)applyPendingStylesWithContext:(ENRMEditContext *)context
|
|
146
|
+
plainText:(NSString *)plainText
|
|
147
|
+
hasGlyphContent:(BOOL)insertedHasGlyphContent
|
|
148
|
+
{
|
|
149
|
+
NSRange insertedRange = NSMakeRange(context.editLocation, context.insertedLength);
|
|
150
|
+
|
|
151
|
+
if (insertedHasGlyphContent) {
|
|
152
|
+
for (NSNumber *styleNum in context.pendingStyles) {
|
|
153
|
+
ENRMFormattingRange *newRange = [ENRMFormattingRange rangeWithType:(ENRMInputStyleType)styleNum.integerValue
|
|
154
|
+
range:insertedRange];
|
|
155
|
+
[_formattingStore addRange:newRange];
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// adjustForEditAtLocation may have expanded an existing range to cover
|
|
160
|
+
// the insertion — carve out the inserted portion for removed styles.
|
|
161
|
+
for (NSNumber *styleNum in context.pendingStyleRemovals) {
|
|
162
|
+
[_formattingStore removeType:(ENRMInputStyleType)styleNum.integerValue inRange:insertedRange];
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
- (BOOL)insertedHasGlyphContentAtLocation:(NSUInteger)location length:(NSUInteger)length text:(NSString *)text
|
|
167
|
+
{
|
|
168
|
+
NSUInteger insertedEnd = location + length;
|
|
169
|
+
if (insertedEnd > text.length)
|
|
170
|
+
return NO;
|
|
171
|
+
NSCharacterSet *newlines = [NSCharacterSet newlineCharacterSet];
|
|
172
|
+
for (NSUInteger i = location; i < insertedEnd; i++) {
|
|
173
|
+
if (![newlines characterIsMember:[text characterAtIndex:i]]) {
|
|
174
|
+
return YES;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
return NO;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
#pragma mark - Block continuation (private)
|
|
181
|
+
|
|
182
|
+
/// Reconciles blocks after Return: a non-empty item continues as a new item at
|
|
183
|
+
/// the same depth, an empty item exits the list (both lines revert to plain
|
|
184
|
+
/// paragraphs). Whether a type continues is the handler's continuesOnNewline.
|
|
185
|
+
- (void)reconcileBlockContinuationAfterNewlineAt:(NSUInteger)newlineLocation
|
|
186
|
+
previousItemWasEmpty:(BOOL)previousWasEmpty
|
|
187
|
+
preEditBlockType:(ENRMInputBlockType)blockType
|
|
188
|
+
preEditBlockLevel:(NSInteger)blockLevel
|
|
189
|
+
{
|
|
190
|
+
id<ENRMBlockHandler> handler = [_formatter handlerForBlockType:blockType];
|
|
191
|
+
if (!handler || ![handler respondsToSelector:@selector(continuesOnNewline)] || !handler.continuesOnNewline) {
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
NSString *text = [_host plainText];
|
|
196
|
+
NSUInteger newLineLocation = newlineLocation + 1;
|
|
197
|
+
if (newLineLocation > text.length) {
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
NSRange originalParagraph = [text paragraphRangeForRange:NSMakeRange(newlineLocation, 0)];
|
|
201
|
+
NSRange newParagraph = [text paragraphRangeForRange:NSMakeRange(newLineLocation, 0)];
|
|
202
|
+
|
|
203
|
+
if (previousWasEmpty) {
|
|
204
|
+
// Exit: drop the block from both lines and strip their list paragraph style.
|
|
205
|
+
// Empty lines carry no stamped block-marker attribute for applyFormatting to
|
|
206
|
+
// key off, so the manual strip is the only thing that clears the leftover indent.
|
|
207
|
+
[_blockStore removeBlockInParagraphRange:originalParagraph inText:text];
|
|
208
|
+
[_blockStore removeBlockInParagraphRange:newParagraph inText:text];
|
|
209
|
+
|
|
210
|
+
NSTextStorage *storage = [_host textStorage];
|
|
211
|
+
[storage beginEditing];
|
|
212
|
+
NSRange clamped = NSIntersectionRange(originalParagraph, NSMakeRange(0, storage.length));
|
|
213
|
+
if (clamped.length > 0) {
|
|
214
|
+
[storage removeAttribute:NSParagraphStyleAttributeName range:clamped];
|
|
215
|
+
}
|
|
216
|
+
clamped = NSIntersectionRange(newParagraph, NSMakeRange(0, storage.length));
|
|
217
|
+
if (clamped.length > 0) {
|
|
218
|
+
[storage removeAttribute:NSParagraphStyleAttributeName range:clamped];
|
|
219
|
+
}
|
|
220
|
+
[storage endEditing];
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
[_blockStore setBlockType:blockType level:blockLevel forParagraphRange:originalParagraph inText:text];
|
|
225
|
+
[_blockStore setBlockType:blockType level:blockLevel forParagraphRange:newParagraph inText:text];
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
@end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
#import "ENRMUIKit.h"
|
|
2
|
+
#import <Foundation/Foundation.h>
|
|
3
|
+
|
|
4
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
5
|
+
|
|
6
|
+
typedef NS_ENUM(NSInteger, ENRMEditPhase) {
|
|
7
|
+
ENRMEditPhaseIdle,
|
|
8
|
+
ENRMEditPhaseProcessing,
|
|
9
|
+
ENRMEditPhaseFormatting,
|
|
10
|
+
ENRMEditPhaseImporting,
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
/// Tracks the current editing phase and exposes computed suppression queries.
|
|
14
|
+
/// Replaces the scattered boolean flags (`_isApplyingFormatting`, `_isTextChanging`,
|
|
15
|
+
/// `blockEmitting`, `_lastTextChangeTime`) that previously guarded re-entrant
|
|
16
|
+
/// code paths in the view.
|
|
17
|
+
@interface ENRMEditSession : NSObject
|
|
18
|
+
|
|
19
|
+
@property (nonatomic, readonly) ENRMEditPhase phase;
|
|
20
|
+
|
|
21
|
+
- (instancetype)initWithTextView:(ENRMPlatformTextView *)textView;
|
|
22
|
+
|
|
23
|
+
- (void)enterPhase:(ENRMEditPhase)newPhase;
|
|
24
|
+
- (void)exitPhase;
|
|
25
|
+
|
|
26
|
+
- (void)recordTextChange;
|
|
27
|
+
|
|
28
|
+
@property (nonatomic, readonly) BOOL isComposing;
|
|
29
|
+
@property (nonatomic, readonly) BOOL isPostEditGracePeriod;
|
|
30
|
+
@property (nonatomic, readonly) BOOL shouldSuppressFormatting;
|
|
31
|
+
@property (nonatomic, readonly) BOOL shouldSuppressEvents;
|
|
32
|
+
@property (nonatomic, readonly) BOOL shouldSuppressSelectionSideEffects;
|
|
33
|
+
|
|
34
|
+
@end
|
|
35
|
+
|
|
36
|
+
NS_ASSUME_NONNULL_END
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
#import "ENRMEditSession.h"
|
|
2
|
+
|
|
3
|
+
static const CFTimeInterval kPostEditGracePeriod = 0.1;
|
|
4
|
+
|
|
5
|
+
@implementation ENRMEditSession {
|
|
6
|
+
__weak ENRMPlatformTextView *_textView;
|
|
7
|
+
CFTimeInterval _lastTextChangeTime;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
- (instancetype)initWithTextView:(ENRMPlatformTextView *)textView
|
|
11
|
+
{
|
|
12
|
+
if (self = [super init]) {
|
|
13
|
+
_textView = textView;
|
|
14
|
+
_phase = ENRMEditPhaseIdle;
|
|
15
|
+
_lastTextChangeTime = 0;
|
|
16
|
+
}
|
|
17
|
+
return self;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
- (void)enterPhase:(ENRMEditPhase)newPhase
|
|
21
|
+
{
|
|
22
|
+
_phase = newPhase;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
- (void)exitPhase
|
|
26
|
+
{
|
|
27
|
+
_phase = ENRMEditPhaseIdle;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
- (void)recordTextChange
|
|
31
|
+
{
|
|
32
|
+
_lastTextChangeTime = CACurrentMediaTime();
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
- (BOOL)isComposing
|
|
36
|
+
{
|
|
37
|
+
ENRMPlatformTextView *tv = _textView;
|
|
38
|
+
if (!tv)
|
|
39
|
+
return NO;
|
|
40
|
+
return ENRMHasMarkedText(tv);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
- (BOOL)isPostEditGracePeriod
|
|
44
|
+
{
|
|
45
|
+
return _lastTextChangeTime > 0 && (CACurrentMediaTime() - _lastTextChangeTime) < kPostEditGracePeriod;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
- (BOOL)shouldSuppressFormatting
|
|
49
|
+
{
|
|
50
|
+
return _phase == ENRMEditPhaseFormatting || _phase == ENRMEditPhaseImporting;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
- (BOOL)shouldSuppressEvents
|
|
54
|
+
{
|
|
55
|
+
return _phase == ENRMEditPhaseImporting;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
- (BOOL)shouldSuppressSelectionSideEffects
|
|
59
|
+
{
|
|
60
|
+
return _phase != ENRMEditPhaseIdle;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
@end
|
|
@@ -21,6 +21,23 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
21
21
|
/// the whole link, a caret inside a link moves to its end (unchanged when no adjustment is needed).
|
|
22
22
|
- (NSRange)selectionAdjustedForAtomicLinks:(NSRange)selection;
|
|
23
23
|
|
|
24
|
+
/// YES when the entire `range` is covered by adjacent/overlapping ranges of `type`.
|
|
25
|
+
- (BOOL)isStyleFullyActive:(ENRMInputStyleType)type inRange:(NSRange)range;
|
|
26
|
+
|
|
27
|
+
/// Toggles `type` on `range`. For a selection (length > 0), removes the style
|
|
28
|
+
/// when fully active, otherwise strips `conflictingStyles` and adds it.
|
|
29
|
+
/// For a caret (length == 0), reports the current state without mutating.
|
|
30
|
+
/// Returns YES when the style was active (removed / pending removal).
|
|
31
|
+
- (BOOL)toggleStyle:(ENRMInputStyleType)type
|
|
32
|
+
inRange:(NSRange)range
|
|
33
|
+
conflictingStyles:(NSSet<NSNumber *> *)conflictingStyles;
|
|
34
|
+
|
|
35
|
+
/// YES when toggling `type` ON at `position` should be refused because one of
|
|
36
|
+
/// the `blockingStyles` is active there. Toggling OFF is never blocked.
|
|
37
|
+
- (BOOL)isToggleBlocked:(ENRMInputStyleType)type
|
|
38
|
+
atPosition:(NSUInteger)position
|
|
39
|
+
blockingStyles:(NSSet<NSNumber *> *)blockingStyles;
|
|
40
|
+
|
|
24
41
|
- (void)addRange:(ENRMFormattingRange *)range;
|
|
25
42
|
- (void)removeType:(ENRMInputStyleType)type inRange:(NSRange)range;
|
|
26
43
|
- (void)removeRange:(ENRMFormattingRange *)range;
|
|
@@ -1,46 +1,6 @@
|
|
|
1
1
|
#import "ENRMFormattingStore.h"
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
{
|
|
5
|
-
NSUInteger index = 0;
|
|
6
|
-
for (ENRMFormattingRange *existing in ranges) {
|
|
7
|
-
if (existing.range.location > location)
|
|
8
|
-
break;
|
|
9
|
-
index++;
|
|
10
|
-
}
|
|
11
|
-
return index;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
static void removeIndexesInReverse(NSMutableArray *array, NSMutableIndexSet *indexes)
|
|
15
|
-
{
|
|
16
|
-
[indexes enumerateIndexesWithOptions:NSEnumerationReverse
|
|
17
|
-
usingBlock:^(NSUInteger idx, BOOL *stop) { [array removeObjectAtIndex:idx]; }];
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
typedef NS_ENUM(NSInteger, EditOverlap) {
|
|
21
|
-
EditOverlapBeforeEdit,
|
|
22
|
-
EditOverlapAfterEdit,
|
|
23
|
-
EditOverlapFullyDeleted,
|
|
24
|
-
EditOverlapDeletedInside,
|
|
25
|
-
EditOverlapClippedEnd,
|
|
26
|
-
EditOverlapClippedStart,
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
static EditOverlap classifyOverlap(NSUInteger rangeStart, NSUInteger rangeEnd, NSUInteger editLocation,
|
|
30
|
-
NSUInteger deleteEnd)
|
|
31
|
-
{
|
|
32
|
-
if (rangeEnd <= editLocation)
|
|
33
|
-
return EditOverlapBeforeEdit;
|
|
34
|
-
if (rangeStart >= deleteEnd)
|
|
35
|
-
return EditOverlapAfterEdit;
|
|
36
|
-
if (rangeStart >= editLocation && rangeEnd <= deleteEnd)
|
|
37
|
-
return EditOverlapFullyDeleted;
|
|
38
|
-
if (rangeStart < editLocation && rangeEnd > deleteEnd)
|
|
39
|
-
return EditOverlapDeletedInside;
|
|
40
|
-
if (rangeStart < editLocation && rangeEnd <= deleteEnd)
|
|
41
|
-
return EditOverlapClippedEnd;
|
|
42
|
-
return EditOverlapClippedStart;
|
|
43
|
-
}
|
|
2
|
+
#import "ENRMRangeEditAdjustment.h"
|
|
3
|
+
#import "ENRMRangeStoreUtils.h"
|
|
44
4
|
|
|
45
5
|
@implementation ENRMFormattingStore {
|
|
46
6
|
NSMutableArray<ENRMFormattingRange *> *_ranges;
|
|
@@ -148,6 +108,59 @@ static EditOverlap classifyOverlap(NSUInteger rangeStart, NSUInteger rangeEnd, N
|
|
|
148
108
|
containingPosition:position - 1] != nil;
|
|
149
109
|
}
|
|
150
110
|
|
|
111
|
+
- (BOOL)isStyleFullyActive:(ENRMInputStyleType)type inRange:(NSRange)range
|
|
112
|
+
{
|
|
113
|
+
NSUInteger pos = range.location;
|
|
114
|
+
NSUInteger end = NSMaxRange(range);
|
|
115
|
+
while (pos < end) {
|
|
116
|
+
ENRMFormattingRange *match = [self rangeOfType:type containingPosition:pos];
|
|
117
|
+
if (match == nil) {
|
|
118
|
+
return NO;
|
|
119
|
+
}
|
|
120
|
+
pos = NSMaxRange(match.range);
|
|
121
|
+
}
|
|
122
|
+
return YES;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
- (BOOL)toggleStyle:(ENRMInputStyleType)type
|
|
126
|
+
inRange:(NSRange)range
|
|
127
|
+
conflictingStyles:(NSSet<NSNumber *> *)conflictingStyles
|
|
128
|
+
{
|
|
129
|
+
BOOL wasActive;
|
|
130
|
+
if (range.length > 0) {
|
|
131
|
+
wasActive = [self isStyleFullyActive:type inRange:range];
|
|
132
|
+
if (wasActive) {
|
|
133
|
+
[self removeType:type inRange:range];
|
|
134
|
+
} else {
|
|
135
|
+
for (NSNumber *conflict in conflictingStyles) {
|
|
136
|
+
[self removeType:(ENRMInputStyleType)conflict.integerValue inRange:range];
|
|
137
|
+
}
|
|
138
|
+
[self addRange:[ENRMFormattingRange rangeWithType:type range:range]];
|
|
139
|
+
}
|
|
140
|
+
} else {
|
|
141
|
+
wasActive = [self isStyleActive:type atPosition:range.location];
|
|
142
|
+
}
|
|
143
|
+
return wasActive;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
- (BOOL)isToggleBlocked:(ENRMInputStyleType)type
|
|
147
|
+
atPosition:(NSUInteger)position
|
|
148
|
+
blockingStyles:(NSSet<NSNumber *> *)blockingStyles
|
|
149
|
+
{
|
|
150
|
+
if (blockingStyles.count == 0) {
|
|
151
|
+
return NO;
|
|
152
|
+
}
|
|
153
|
+
if ([self isStyleActive:type atPosition:position]) {
|
|
154
|
+
return NO;
|
|
155
|
+
}
|
|
156
|
+
for (NSNumber *blocker in blockingStyles) {
|
|
157
|
+
if ([self isStyleActive:(ENRMInputStyleType)blocker.integerValue atPosition:position]) {
|
|
158
|
+
return YES;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
return NO;
|
|
162
|
+
}
|
|
163
|
+
|
|
151
164
|
- (void)addRange:(ENRMFormattingRange *)newRange
|
|
152
165
|
{
|
|
153
166
|
NSMutableIndexSet *mergeIndexes = [NSMutableIndexSet indexSet];
|
|
@@ -167,13 +180,14 @@ static EditOverlap classifyOverlap(NSUInteger rangeStart, NSUInteger rangeEnd, N
|
|
|
167
180
|
}
|
|
168
181
|
}
|
|
169
182
|
|
|
170
|
-
|
|
183
|
+
ENRMRemoveIndexesInReverse(_ranges, mergeIndexes);
|
|
171
184
|
|
|
172
185
|
ENRMFormattingRange *merged = [ENRMFormattingRange rangeWithType:newRange.type
|
|
173
186
|
range:NSMakeRange(mergedStart, mergedEnd - mergedStart)
|
|
174
187
|
url:newRange.url];
|
|
175
188
|
|
|
176
|
-
NSUInteger insertAt =
|
|
189
|
+
NSUInteger insertAt = ENRMSortedInsertionIndex(
|
|
190
|
+
_ranges, merged.range.location, ^NSUInteger(id range) { return ((ENRMFormattingRange *)range).range.location; });
|
|
177
191
|
[_ranges insertObject:merged atIndex:insertAt];
|
|
178
192
|
}
|
|
179
193
|
|
|
@@ -211,11 +225,13 @@ static EditOverlap classifyOverlap(NSUInteger rangeStart, NSUInteger rangeEnd, N
|
|
|
211
225
|
}
|
|
212
226
|
}
|
|
213
227
|
|
|
214
|
-
|
|
228
|
+
ENRMRemoveIndexesInReverse(_ranges, indexesToRemove);
|
|
215
229
|
|
|
216
230
|
// Remainders are fragments of a just-removed range and cannot overlap others.
|
|
217
231
|
for (ENRMFormattingRange *remainder in remainders) {
|
|
218
|
-
NSUInteger insertAt =
|
|
232
|
+
NSUInteger insertAt = ENRMSortedInsertionIndex(_ranges, remainder.range.location, ^NSUInteger(id range) {
|
|
233
|
+
return ((ENRMFormattingRange *)range).range.location;
|
|
234
|
+
});
|
|
219
235
|
[_ranges insertObject:remainder atIndex:insertAt];
|
|
220
236
|
}
|
|
221
237
|
}
|
|
@@ -232,71 +248,20 @@ static EditOverlap classifyOverlap(NSUInteger rangeStart, NSUInteger rangeEnd, N
|
|
|
232
248
|
if (deletedLength == 0 && insertedLength == 0)
|
|
233
249
|
return;
|
|
234
250
|
|
|
235
|
-
NSUInteger deleteEnd = editLocation + deletedLength;
|
|
236
251
|
NSMutableIndexSet *indexesToRemove = [NSMutableIndexSet indexSet];
|
|
237
252
|
|
|
238
253
|
for (NSUInteger idx = 0; idx < _ranges.count; idx++) {
|
|
239
254
|
ENRMFormattingRange *formattingRange = _ranges[idx];
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
switch (overlap) {
|
|
247
|
-
case EditOverlapBeforeEdit:
|
|
248
|
-
break;
|
|
249
|
-
|
|
250
|
-
case EditOverlapAfterEdit:
|
|
251
|
-
formattingRange.range =
|
|
252
|
-
NSMakeRange(rangeStart - deletedLength + insertedLength, formattingRange.range.length);
|
|
253
|
-
break;
|
|
254
|
-
|
|
255
|
-
case EditOverlapFullyDeleted:
|
|
256
|
-
[indexesToRemove addIndex:idx];
|
|
257
|
-
break;
|
|
258
|
-
|
|
259
|
-
case EditOverlapDeletedInside: {
|
|
260
|
-
NSUInteger newLength = formattingRange.range.length - deletedLength + insertedLength;
|
|
261
|
-
formattingRange.range = NSMakeRange(rangeStart, newLength);
|
|
262
|
-
break;
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
case EditOverlapClippedEnd: {
|
|
266
|
-
NSUInteger newEnd = editLocation + insertedLength;
|
|
267
|
-
NSUInteger newLength = newEnd > rangeStart ? newEnd - rangeStart : 0;
|
|
268
|
-
formattingRange.range = NSMakeRange(rangeStart, newLength);
|
|
269
|
-
if (newLength == 0) {
|
|
270
|
-
[indexesToRemove addIndex:idx];
|
|
271
|
-
}
|
|
272
|
-
break;
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
case EditOverlapClippedStart: {
|
|
276
|
-
NSUInteger charsClipped = deleteEnd - rangeStart;
|
|
277
|
-
NSUInteger newStart = editLocation + insertedLength;
|
|
278
|
-
NSUInteger newLength = formattingRange.range.length - charsClipped;
|
|
279
|
-
formattingRange.range = NSMakeRange(newStart, newLength);
|
|
280
|
-
if (newLength == 0) {
|
|
281
|
-
[indexesToRemove addIndex:idx];
|
|
282
|
-
}
|
|
283
|
-
break;
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
} else {
|
|
287
|
-
if (rangeStart >= editLocation) {
|
|
288
|
-
// Insertion at or before the range start: shift right.
|
|
289
|
-
// _pendingStyles handles whether the inserted text inherits the style.
|
|
290
|
-
formattingRange.range = NSMakeRange(rangeStart + insertedLength, formattingRange.range.length);
|
|
291
|
-
} else if (editLocation < rangeEnd) {
|
|
292
|
-
formattingRange.range = NSMakeRange(rangeStart, formattingRange.range.length + insertedLength);
|
|
293
|
-
}
|
|
294
|
-
// Typing at rangeEnd does not expand — pending styles control
|
|
295
|
-
// whether new text at the boundary inherits the style.
|
|
255
|
+
BOOL inheritsReplacement = formattingRange.type != ENRMInputStyleTypeLink;
|
|
256
|
+
ENRMAdjustedRange adjusted = ENRMAdjustRangeForEdit(formattingRange.range, editLocation, deletedLength,
|
|
257
|
+
insertedLength, inheritsReplacement, NO);
|
|
258
|
+
formattingRange.range = adjusted.range;
|
|
259
|
+
if (adjusted.shouldRemove) {
|
|
260
|
+
[indexesToRemove addIndex:idx];
|
|
296
261
|
}
|
|
297
262
|
}
|
|
298
263
|
|
|
299
|
-
|
|
264
|
+
ENRMRemoveIndexesInReverse(_ranges, indexesToRemove);
|
|
300
265
|
|
|
301
266
|
NSMutableIndexSet *emptyIndexes = [NSMutableIndexSet indexSet];
|
|
302
267
|
for (NSUInteger idx = 0; idx < _ranges.count; idx++) {
|
|
@@ -305,7 +270,32 @@ static EditOverlap classifyOverlap(NSUInteger rangeStart, NSUInteger rangeEnd, N
|
|
|
305
270
|
}
|
|
306
271
|
}
|
|
307
272
|
if (emptyIndexes.count > 0) {
|
|
308
|
-
|
|
273
|
+
ENRMRemoveIndexesInReverse(_ranges, emptyIndexes);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
[self coalesceAdjacentSameTypeRanges];
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/// Merge same-type (and same-url) ranges left adjacent or overlapping by an
|
|
280
|
+
/// edit — e.g. deleting the space in "**foo** **bar**" leaves two touching
|
|
281
|
+
/// bold ranges that would serialize as "**foo****bar**". `addRange:` keeps
|
|
282
|
+
/// this invariant on insert; the edit path must too.
|
|
283
|
+
- (void)coalesceAdjacentSameTypeRanges
|
|
284
|
+
{
|
|
285
|
+
for (NSUInteger idx = 0; idx < _ranges.count; idx++) {
|
|
286
|
+
ENRMFormattingRange *current = _ranges[idx];
|
|
287
|
+
NSUInteger next = idx + 1;
|
|
288
|
+
while (next < _ranges.count && _ranges[next].range.location <= NSMaxRange(current.range)) {
|
|
289
|
+
ENRMFormattingRange *candidate = _ranges[next];
|
|
290
|
+
BOOL sameUrl = (current.url == candidate.url) || [current.url isEqualToString:candidate.url];
|
|
291
|
+
if (candidate.type == current.type && sameUrl) {
|
|
292
|
+
NSUInteger mergedEnd = MAX(NSMaxRange(current.range), NSMaxRange(candidate.range));
|
|
293
|
+
current.range = NSMakeRange(current.range.location, mergedEnd - current.range.location);
|
|
294
|
+
[_ranges removeObjectAtIndex:next];
|
|
295
|
+
} else {
|
|
296
|
+
next++;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
309
299
|
}
|
|
310
300
|
}
|
|
311
301
|
|