react-native-enriched-markdown-scaffold 0.7.4-scaffold.8 → 1.0.2-scaffold.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +54 -8
- package/ReactNativeEnrichedMarkdown.podspec +82 -73
- package/android/build.gradle +191 -1
- package/android/consumer-rules.pro +1 -1
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownManagerDelegate.java +9 -0
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownManagerInterface.java +3 -0
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextInputManagerDelegate.java +27 -0
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextInputManagerInterface.java +9 -0
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextManagerDelegate.java +9 -0
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextManagerInterface.java +3 -0
- package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/EventEmitters.cpp +75 -0
- package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/EventEmitters.h +63 -0
- package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/Props.cpp +40 -0
- package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/Props.h +839 -23
- package/android/src/main/baseline-prof.txt +1 -1
- package/android/src/main/cpp/jni-adapter.cpp +74 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdown.kt +175 -11
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownInternalText.kt +17 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownManager.kt +50 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownText.kt +48 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownTextLayoutManager.kt +10 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownTextManager.kt +42 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/MeasurementStore.kt +82 -4
- package/android/src/main/java/com/swmansion/enriched/markdown/events/CopyPressEvent.kt +24 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/EnrichedMarkdownTextInputManager.kt +62 -4
- package/android/src/main/java/com/swmansion/enriched/markdown/input/EnrichedMarkdownTextInputView.kt +911 -460
- package/android/src/main/java/com/swmansion/enriched/markdown/input/MarkdownClipboard.kt +42 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/BlockEditCoordinator.kt +196 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/ClipboardCoordinator.kt +73 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/EditContext.kt +19 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/EditPipeline.kt +248 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/EditSession.kt +52 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/InputConnectionWrapper.kt +101 -7
- package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/LinkCoordinator.kt +69 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/MarkdownTextWatcher.kt +3 -3
- package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/MentionCoordinator.kt +118 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnChangeStateEvent.kt +26 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnContextMenuItemPressEvent.kt +26 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnInputKeyPressEvent.kt +24 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnPasteEvent.kt +24 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/BlockStore.kt +254 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/BlockSyntaxSentinel.kt +69 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/FormattingStore.kt +80 -87
- package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/InputFormatter.kt +109 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/InputParser.kt +180 -27
- package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/MarkdownSerializer.kt +167 -38
- package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/RangeEditAdjustment.kt +149 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/layout/InputEventEmitter.kt +66 -5
- package/android/src/main/java/com/swmansion/enriched/markdown/input/layout/InputMeasurementStore.kt +7 -2
- package/android/src/main/java/com/swmansion/enriched/markdown/input/model/BlockRange.kt +27 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/model/BlockType.kt +48 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/model/FormattingRange.kt +9 -4
- package/android/src/main/java/com/swmansion/enriched/markdown/input/model/InputFormatterStyle.kt +39 -2
- package/android/src/main/java/com/swmansion/enriched/markdown/input/model/MathAtom.kt +20 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/model/MathChipStyle.kt +1 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/input/model/MutableRangeBounds.kt +11 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/spans/InputBulletSpan.kt +82 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/spans/InputHeadingSpan.kt +58 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/spans/InputListItemSpacingSpan.kt +37 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/spans/InputOrderedListMarkerSpan.kt +63 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/styles/BlockHandler.kt +54 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/styles/HeadingBlockHandler.kt +27 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/styles/OrderedListBlockHandler.kt +38 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/styles/UnorderedListBlockHandler.kt +37 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/toolbar/InputContextMenu.kt +8 -26
- package/android/src/main/java/com/swmansion/enriched/markdown/parser/MarkdownASTNode.kt +1 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/parser/Parser.kt +1 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/BlockStyleContext.kt +9 -2
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/BlockquoteRenderer.kt +100 -12
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/CodeBlockRenderer.kt +16 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/HeadingRenderer.kt +4 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListContextManager.kt +2 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListItemRenderer.kt +74 -18
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListRenderer.kt +43 -4
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/NodeRenderer.kt +9 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/SoftBreakRenderer.kt +16 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/SpanStyleCache.kt +30 -27
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/BaseListSpan.kt +24 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/BlockquoteSpan.kt +174 -24
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/CodeBackgroundSpan.kt +27 -3
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/CodeBlockSpan.kt +13 -16
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/CodeSpan.kt +1 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/EmphasisSpan.kt +1 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/ImageSpan.kt +182 -46
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/ListItemSpacingSpan.kt +33 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/ListMarkerAnchorSpan.kt +38 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/OrderedListSpan.kt +2 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/StrongSpan.kt +1 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/TaskListSpan.kt +3 -2
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/UnorderedListSpan.kt +3 -2
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/BlockquoteStyle.kt +6 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/CodeBlockStyle.kt +26 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/ImageStyle.kt +7 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/ListStyle.kt +4 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/StyleConfig.kt +13 -4
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/TableStyle.kt +6 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/CodeBlockHighlighter.kt +90 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/CodeBlockNode.kt +57 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/FeatureFlags.kt +1 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/MarkdownSegment.kt +9 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/MarkdownViewManagerUtils.kt +33 -7
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/ReadableMapExtensions.kt +3 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/RenderedSegment.kt +10 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/SegmentSignature.kt +1 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/StreamingMarkdownFilter.kt +83 -5
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/serialization/MarkdownASTSerializer.kt +4 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/input/MarkdownStyleParser.kt +74 -44
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/input/PasteTextUtils.kt +20 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/ImageCache.kt +26 -3
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/ImageDownloader.kt +22 -9
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/LocalImageLoader.kt +161 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/extensions/TextPaintExtensions.kt +23 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/interaction/CheckboxTouchHelper.kt +7 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/interaction/TaskListTapUtils.kt +41 -21
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/span/BlockSpacing.kt +15 -8
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/LinkLongPressMovementMethod.kt +58 -27
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/SelectionActionMode.kt +19 -2
- package/android/src/main/java/com/swmansion/enriched/markdown/views/CodeBlockContainerView.kt +388 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/views/ContextMenuPopup.kt +9 -6
- package/android/src/main/java/com/swmansion/enriched/markdown/views/CopyGlyph.kt +101 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/views/TableContainerView.kt +32 -5
- package/android/src/main/jni/CMakeLists.txt +53 -0
- package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownContainerShadowNode.cpp +10 -0
- package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownContainerShadowNode.h +11 -2
- package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextShadowNode.cpp +10 -0
- package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextShadowNode.h +12 -2
- package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextState.cpp +9 -0
- package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextState.h +24 -0
- package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/conversions.h +16 -0
- package/android/src/math/java/com/swmansion/enriched/markdown/input/math/MathChipControllerImpl.kt +21 -4
- package/android/src/math/java/com/swmansion/enriched/markdown/renderer/MathInlineRenderer.kt +7 -2
- package/android/src/math/java/com/swmansion/enriched/markdown/spans/MathChipSpan.kt +1 -1
- package/android/src/math/java/com/swmansion/enriched/markdown/views/MathContainerView.kt +2 -0
- package/cpp/highlight/CodeBlockHighlighter.cpp +284 -0
- package/cpp/highlight/CodeBlockHighlighter.hpp +66 -0
- package/cpp/highlight/CodeBlockLanguages.cpp +138 -0
- package/cpp/highlight/CodeBlockLanguages.hpp +25 -0
- package/cpp/highlight/HighlightGrammars.hpp +28 -0
- package/cpp/highlight/code_highlight_podspec.rb +211 -0
- package/cpp/highlight/gen-registry.mjs +155 -0
- package/cpp/highlight/grammar-versions.json +159 -0
- package/cpp/highlight/vendor/generated/generated_queries.h +1665 -0
- package/cpp/highlight/vendor/generated/generated_registry.cpp +59 -0
- package/cpp/parser/MD4CParser.cpp +173 -61
- package/cpp/parser/MD4CParser.hpp +1 -0
- package/cpp/parser/MarkdownASTNode.hpp +2 -1
- package/cpp/wasm/ASTSerializer.cpp +2 -0
- package/cpp/wasm/build.sh +1 -0
- package/cpp/wasm/md4c_wasm.cpp +3 -1
- package/docs/ACCESSIBILITY.md +14 -2
- package/docs/API_REFERENCE.md +231 -8
- package/docs/BREAKING_CHANGES.md +129 -0
- package/docs/CODE_HIGHLIGHT.md +133 -0
- package/docs/COPY_OPTIONS.md +21 -3
- package/docs/ELEMENTS_STRUCTURE.md +52 -4
- package/docs/IMAGE_CACHING.md +30 -0
- package/docs/INPUT.md +146 -5
- package/docs/LATEX_MATH.md +87 -45
- package/docs/MACOS.md +1 -1
- package/docs/MARKDOWN_STREAMING.md +27 -1
- package/docs/NATIVE_ASSETS.md +127 -0
- package/docs/RTL.md +1 -1
- package/docs/STYLES.md +46 -6
- package/docs/TESTING.md +112 -0
- package/docs/TEXT.md +16 -6
- package/docs/WEB.md +3 -1
- package/ios/EnrichedMarkdown.h +7 -0
- package/ios/EnrichedMarkdown.mm +262 -67
- package/ios/EnrichedMarkdownText.h +7 -0
- package/ios/EnrichedMarkdownText.mm +97 -68
- package/ios/attachments/ENRMImageAttachment.h +9 -0
- package/ios/attachments/ENRMImageAttachment.m +143 -40
- package/ios/attachments/ENRMMathInlineAttachment.h +2 -0
- package/ios/attachments/ENRMMathInlineAttachment.m +48 -81
- package/ios/attachments/ENRMMathInlineAttachmentShared.h +2 -0
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/EventEmitters.cpp +75 -0
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/EventEmitters.h +63 -0
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/Props.cpp +40 -0
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/Props.h +839 -23
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/RCTComponentViewHelpers.h +131 -0
- package/ios/input/ENRMAutoLinkDetector.h +2 -1
- package/ios/input/ENRMAutoLinkDetector.mm +79 -41
- package/ios/input/ENRMBlockEditCoordinator.h +71 -0
- package/ios/input/ENRMBlockEditCoordinator.mm +195 -0
- package/ios/input/ENRMBlockRange.h +28 -0
- package/ios/input/ENRMBlockRange.mm +30 -0
- package/ios/input/ENRMBlockStore.h +56 -0
- package/ios/input/ENRMBlockStore.mm +275 -0
- package/ios/input/ENRMBlockSyntaxSentinel.h +25 -0
- package/ios/input/ENRMBlockSyntaxSentinel.mm +80 -0
- package/ios/input/ENRMClipboardCoordinator.h +45 -0
- package/ios/input/ENRMClipboardCoordinator.mm +120 -0
- package/ios/input/ENRMDetectorPipeline.h +2 -1
- package/ios/input/ENRMEditPipeline.h +76 -0
- package/ios/input/ENRMEditPipeline.mm +228 -0
- package/ios/input/ENRMEditSession.h +36 -0
- package/ios/input/ENRMEditSession.mm +63 -0
- package/ios/input/ENRMFormattingStore.h +17 -0
- package/ios/input/ENRMFormattingStore.mm +95 -105
- package/ios/input/ENRMInputBlockType.h +91 -0
- package/ios/input/ENRMInputBlockType.mm +5 -0
- package/ios/input/ENRMInputDecorationDrawer.h +18 -0
- package/ios/input/ENRMInputEventEmitter.h +56 -0
- package/ios/input/ENRMInputEventEmitter.mm +308 -0
- package/ios/input/ENRMInputFormatter.h +29 -69
- package/ios/input/ENRMInputFormatter.mm +216 -124
- package/ios/input/ENRMInputFormatterStyle.h +99 -0
- package/ios/input/ENRMInputFormatterStyle.mm +188 -0
- package/ios/input/ENRMInputLayoutManager.h +9 -0
- package/ios/input/ENRMInputLayoutManager.mm +30 -0
- package/ios/input/ENRMInputListMarkerDrawer.h +32 -0
- package/ios/input/ENRMInputListMarkerDrawer.mm +426 -0
- package/ios/input/ENRMInputParser.h +10 -6
- package/ios/input/ENRMInputParser.mm +527 -171
- package/ios/input/ENRMInputRemend.mm +2 -2
- package/ios/input/ENRMInputStyleStateBuilder.h +40 -0
- package/ios/input/ENRMInputStyleStateBuilder.mm +60 -0
- package/ios/input/ENRMInputTextView.mm +103 -8
- package/ios/input/ENRMInputTypingAttributesController.h +42 -0
- package/ios/input/ENRMInputTypingAttributesController.mm +203 -0
- package/ios/input/ENRMLinkCoordinator.h +41 -0
- package/ios/input/ENRMLinkCoordinator.mm +89 -0
- package/ios/input/ENRMMarkdownSerializer.h +29 -5
- package/ios/input/ENRMMarkdownSerializer.mm +170 -48
- package/ios/input/ENRMMathAtom.h +26 -0
- package/ios/input/ENRMMathAtom.mm +12 -0
- package/ios/input/ENRMMentionCoordinator.h +45 -0
- package/ios/input/ENRMMentionCoordinator.mm +167 -0
- package/ios/input/ENRMRangeEditAdjustment.h +38 -0
- package/ios/input/ENRMRangeEditAdjustment.mm +91 -0
- package/ios/input/ENRMRangeStoreUtils.h +39 -0
- package/ios/input/EnrichedMarkdownTextInput+ContextMenu.mm +6 -6
- package/ios/input/EnrichedMarkdownTextInput+Internal.h +11 -3
- package/ios/input/EnrichedMarkdownTextInput.h +7 -1
- package/ios/input/EnrichedMarkdownTextInput.mm +1104 -1024
- package/ios/input/InputStylePropsUtils.h +109 -68
- package/ios/input/internals/EnrichedMarkdownTextInputShadowNode.mm +2 -1
- package/ios/input/styles/ENRMBlockHandler.h +46 -0
- package/ios/input/styles/ENRMHeadingBlockHandler.h +15 -0
- package/ios/input/styles/ENRMHeadingBlockHandler.mm +38 -0
- package/ios/input/styles/ENRMOrderedListBlockHandler.h +14 -0
- package/ios/input/styles/ENRMOrderedListBlockHandler.mm +48 -0
- package/ios/input/styles/ENRMUnorderedListBlockHandler.h +15 -0
- package/ios/input/styles/ENRMUnorderedListBlockHandler.mm +51 -0
- package/ios/internals/ENRMViewFreeMeasurement.h +331 -0
- package/ios/internals/EnrichedMarkdownShadowNode.h +1 -3
- package/ios/internals/EnrichedMarkdownShadowNode.mm +16 -20
- package/ios/internals/EnrichedMarkdownTextShadowNode.h +1 -3
- package/ios/internals/EnrichedMarkdownTextShadowNode.mm +15 -20
- package/ios/internals/MeasurementCache.h +33 -7
- package/ios/internals/ShadowMeasurementUtils.h +63 -58
- package/ios/math/ENRMMathChipController.h +74 -0
- package/ios/math/ENRMMathChipController.mm +476 -0
- package/ios/math/ENRMRaTeXBridge.swift +4 -1
- package/ios/parser/ENRMMarkdownParser.h +1 -8
- package/ios/parser/ENRMMarkdownParser.mm +2 -11
- package/ios/parser/MarkdownASTNode.h +2 -1
- package/ios/parser/MarkdownParserBridge.mm +4 -0
- package/ios/renderer/AttributedRenderer.m +20 -2
- package/ios/renderer/BaseRenderer.h +17 -2
- package/ios/renderer/BaseRenderer.m +30 -0
- package/ios/renderer/BlockquoteRenderer.h +1 -1
- package/ios/renderer/BlockquoteRenderer.m +144 -35
- package/ios/renderer/CodeBlockRenderer.h +1 -1
- package/ios/renderer/CodeBlockRenderer.m +27 -23
- package/ios/renderer/CodeRenderer.h +1 -1
- package/ios/renderer/CodeRenderer.m +3 -1
- package/ios/renderer/ENRMImageRenderer.h +1 -1
- package/ios/renderer/ENRMImageRenderer.m +5 -1
- package/ios/renderer/ENRMMathInlineRenderer.h +1 -1
- package/ios/renderer/ENRMMathInlineRenderer.m +5 -1
- package/ios/renderer/ENRMSpoilerRenderer.h +1 -1
- package/ios/renderer/ENRMSpoilerRenderer.m +3 -1
- package/ios/renderer/EmphasisRenderer.h +1 -1
- package/ios/renderer/EmphasisRenderer.m +3 -1
- package/ios/renderer/HeadingRenderer.h +1 -1
- package/ios/renderer/HeadingRenderer.m +13 -6
- package/ios/renderer/HighlightRenderer.h +1 -1
- package/ios/renderer/HighlightRenderer.m +3 -1
- package/ios/renderer/LinkRenderer.h +1 -1
- package/ios/renderer/LinkRenderer.m +3 -1
- package/ios/renderer/ListItemRenderer.h +13 -1
- package/ios/renderer/ListItemRenderer.m +102 -44
- package/ios/renderer/ListRenderer.h +2 -2
- package/ios/renderer/ListRenderer.m +63 -25
- package/ios/renderer/ParagraphRenderer.h +1 -1
- package/ios/renderer/ParagraphRenderer.m +16 -8
- package/ios/renderer/RenderContext.h +10 -0
- package/ios/renderer/RenderContext.m +44 -0
- package/ios/renderer/RendererFactory.m +14 -0
- package/ios/renderer/StrikethroughRenderer.h +1 -1
- package/ios/renderer/StrikethroughRenderer.m +3 -1
- package/ios/renderer/StrongRenderer.h +1 -1
- package/ios/renderer/StrongRenderer.m +3 -1
- package/ios/renderer/SubscriptRenderer.h +1 -1
- package/ios/renderer/SubscriptRenderer.m +3 -1
- package/ios/renderer/SuperscriptRenderer.h +1 -1
- package/ios/renderer/SuperscriptRenderer.m +3 -1
- package/ios/renderer/TextRenderer.h +2 -2
- package/ios/renderer/TextRenderer.m +3 -1
- package/ios/renderer/ThematicBreakRenderer.h +1 -1
- package/ios/renderer/ThematicBreakRenderer.m +3 -1
- package/ios/renderer/UnderlineRenderer.h +1 -1
- package/ios/renderer/UnderlineRenderer.m +3 -1
- package/ios/styles/StyleConfig.h +22 -0
- package/ios/styles/StyleConfig.mm +132 -0
- package/ios/utils/BlockquoteBorder.h +6 -0
- package/ios/utils/BlockquoteBorder.m +249 -52
- package/ios/utils/CodeBlockBackground.m +16 -2
- package/ios/utils/ENRMAtomicSize.h +65 -0
- package/ios/utils/ENRMCodeBlockContent.h +37 -0
- package/ios/utils/ENRMCodeBlockContent.mm +79 -0
- package/ios/utils/ENRMCodeBlockHighlighter.h +37 -0
- package/ios/utils/ENRMCodeBlockHighlighter.mm +51 -0
- package/ios/utils/ENRMFeatureFlags.h +7 -0
- package/ios/utils/ENRMImageDownloader.h +11 -1
- package/ios/utils/ENRMImageDownloader.m +60 -16
- package/ios/utils/ENRMLocalImageLoader.h +31 -0
- package/ios/utils/ENRMLocalImageLoader.m +68 -0
- package/ios/utils/ENRMMathFallback.h +26 -0
- package/ios/utils/ENRMMathFallback.m +18 -0
- package/ios/utils/ENRMTextViewSetup.h +35 -17
- package/ios/utils/EditMenuUtils.m +22 -1
- package/ios/utils/ImageRequestHeaderUtils.h +35 -0
- package/ios/utils/LastElementUtils.h +1 -0
- package/ios/utils/ListMarkerDrawer.m +29 -42
- package/ios/utils/MarkdownASTSerializer.m +4 -0
- package/ios/utils/ParagraphStyleUtils.h +5 -0
- package/ios/utils/ParagraphStyleUtils.m +77 -17
- package/ios/utils/RenderedMarkdownSegment.h +13 -1
- package/ios/utils/RenderedMarkdownSegment.m +20 -0
- package/ios/utils/SegmentRenderer.m +17 -4
- package/ios/utils/StreamingMarkdownFilter.h +11 -1
- package/ios/utils/StreamingMarkdownFilter.m +98 -2
- package/ios/utils/StylePropsUtils.h +63 -0
- package/ios/utils/TaskListTapUtils.m +24 -0
- package/ios/views/ENRMCodeBlockContainerView.h +46 -0
- package/ios/views/ENRMCodeBlockContainerView.m +566 -0
- package/ios/views/ENRMMathContainerView.h +12 -0
- package/ios/views/ENRMMathContainerView.m +71 -1
- package/ios/views/TableContainerView.h +18 -0
- package/ios/views/TableContainerView.m +259 -159
- package/jest.d.ts +1 -0
- package/jest.js +5 -0
- package/lib/module/EnrichedMarkdownNativeComponent.ts +65 -0
- package/lib/module/EnrichedMarkdownTextInput.js +86 -5
- package/lib/module/EnrichedMarkdownTextInput.js.map +1 -1
- package/lib/module/EnrichedMarkdownTextInputNativeComponent.ts +89 -5
- package/lib/module/EnrichedMarkdownTextNativeComponent.ts +66 -0
- package/lib/module/headingDefaults.js +34 -0
- package/lib/module/headingDefaults.js.map +1 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/jest/index.js +191 -0
- package/lib/module/jest/index.js.map +1 -0
- package/lib/module/native/EnrichedMarkdownText.js +30 -4
- package/lib/module/native/EnrichedMarkdownText.js.map +1 -1
- package/lib/module/normalizeMarkdownStyle.js +81 -19
- package/lib/module/normalizeMarkdownStyle.js.map +1 -1
- package/lib/module/normalizeMarkdownStyle.web.js +56 -18
- package/lib/module/normalizeMarkdownStyle.web.js.map +1 -1
- package/lib/module/normalizeMarkdownTextInputStyle.js +62 -15
- package/lib/module/normalizeMarkdownTextInputStyle.js.map +1 -1
- package/lib/module/normalizeMenuItem.js +1 -1
- package/lib/module/utils/textInputState.js +26 -0
- package/lib/module/utils/textInputState.js.map +1 -0
- package/lib/module/web/EnrichedMarkdownText.js +9 -5
- package/lib/module/web/EnrichedMarkdownText.js.map +1 -1
- package/lib/module/web/parseMarkdown.js +4 -3
- package/lib/module/web/parseMarkdown.js.map +1 -1
- package/lib/module/web/renderers/InlineRenderers.js +6 -0
- package/lib/module/web/renderers/InlineRenderers.js.map +1 -1
- package/lib/module/web/renderers/ListRenderers.js +7 -2
- package/lib/module/web/renderers/ListRenderers.js.map +1 -1
- package/lib/module/web/renderers/index.js +7 -4
- package/lib/module/web/renderers/index.js.map +1 -1
- package/lib/module/web/styles.js +83 -6
- package/lib/module/web/styles.js.map +1 -1
- package/lib/module/web/utils.js +1 -0
- package/lib/module/web/utils.js.map +1 -1
- package/lib/module/web/wasm/md4c.js +0 -0
- package/lib/module/web/wasm/md4c.js.map +1 -1
- package/lib/typescript/src/EnrichedMarkdownNativeComponent.d.ts +62 -0
- package/lib/typescript/src/EnrichedMarkdownNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/EnrichedMarkdownTextInput.d.ts +95 -9
- package/lib/typescript/src/EnrichedMarkdownTextInput.d.ts.map +1 -1
- package/lib/typescript/src/EnrichedMarkdownTextInputNativeComponent.d.ts +80 -5
- package/lib/typescript/src/EnrichedMarkdownTextInputNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/EnrichedMarkdownTextNativeComponent.d.ts +62 -0
- package/lib/typescript/src/EnrichedMarkdownTextNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/headingDefaults.d.ts +9 -0
- package/lib/typescript/src/headingDefaults.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +2 -2
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/index.web.d.ts +1 -1
- package/lib/typescript/src/index.web.d.ts.map +1 -1
- package/lib/typescript/src/jest/index.d.ts +6 -0
- package/lib/typescript/src/jest/index.d.ts.map +1 -0
- package/lib/typescript/src/native/EnrichedMarkdownText.d.ts +3 -3
- package/lib/typescript/src/native/EnrichedMarkdownText.d.ts.map +1 -1
- package/lib/typescript/src/normalizeMarkdownStyle.d.ts.map +1 -1
- package/lib/typescript/src/normalizeMarkdownStyle.web.d.ts.map +1 -1
- package/lib/typescript/src/normalizeMarkdownTextInputStyle.d.ts +19 -5
- package/lib/typescript/src/normalizeMarkdownTextInputStyle.d.ts.map +1 -1
- package/lib/typescript/src/types/MarkdownStyle.d.ts +72 -0
- package/lib/typescript/src/types/MarkdownStyle.d.ts.map +1 -1
- package/lib/typescript/src/types/MarkdownStyleInternal.d.ts +27 -0
- package/lib/typescript/src/types/MarkdownStyleInternal.d.ts.map +1 -1
- package/lib/typescript/src/types/MarkdownTextProps.d.ts +65 -1
- package/lib/typescript/src/types/MarkdownTextProps.d.ts.map +1 -1
- package/lib/typescript/src/types/MarkdownTextProps.web.d.ts +19 -0
- package/lib/typescript/src/types/MarkdownTextProps.web.d.ts.map +1 -1
- package/lib/typescript/src/types/events.d.ts +19 -0
- package/lib/typescript/src/types/events.d.ts.map +1 -1
- package/lib/typescript/src/utils/textInputState.d.ts +24 -0
- package/lib/typescript/src/utils/textInputState.d.ts.map +1 -0
- package/lib/typescript/src/web/EnrichedMarkdownText.d.ts +1 -1
- package/lib/typescript/src/web/EnrichedMarkdownText.d.ts.map +1 -1
- package/lib/typescript/src/web/parseMarkdown.d.ts +1 -1
- package/lib/typescript/src/web/parseMarkdown.d.ts.map +1 -1
- package/lib/typescript/src/web/renderers/InlineRenderers.d.ts.map +1 -1
- package/lib/typescript/src/web/renderers/ListRenderers.d.ts.map +1 -1
- package/lib/typescript/src/web/renderers/index.d.ts +2 -1
- package/lib/typescript/src/web/renderers/index.d.ts.map +1 -1
- package/lib/typescript/src/web/styles.d.ts +2 -1
- package/lib/typescript/src/web/styles.d.ts.map +1 -1
- package/lib/typescript/src/web/types.d.ts +6 -2
- package/lib/typescript/src/web/types.d.ts.map +1 -1
- package/lib/typescript/src/web/utils.d.ts.map +1 -1
- package/package.json +36 -9
- package/postinstall.mjs +131 -0
- package/ratex-version.json +21 -0
- package/src/EnrichedMarkdownNativeComponent.ts +65 -0
- package/src/EnrichedMarkdownTextInput.tsx +162 -8
- package/src/EnrichedMarkdownTextInputNativeComponent.ts +89 -5
- package/src/EnrichedMarkdownTextNativeComponent.ts +66 -0
- package/src/headingDefaults.ts +21 -0
- package/src/index.tsx +9 -0
- package/src/index.web.tsx +1 -0
- package/src/jest/index.tsx +215 -0
- package/src/native/EnrichedMarkdownText.tsx +40 -2
- package/src/normalizeMarkdownStyle.ts +102 -16
- package/src/normalizeMarkdownStyle.web.ts +63 -15
- package/src/normalizeMarkdownTextInputStyle.ts +110 -35
- package/src/normalizeMenuItem.ts +1 -1
- package/src/types/MarkdownStyle.ts +74 -0
- package/src/types/MarkdownStyleInternal.ts +39 -0
- package/src/types/MarkdownTextProps.ts +65 -0
- package/src/types/MarkdownTextProps.web.ts +19 -0
- package/src/types/events.ts +21 -0
- package/src/utils/textInputState.ts +35 -0
- package/src/web/EnrichedMarkdownText.tsx +16 -2
- package/src/web/parseMarkdown.ts +6 -2
- package/src/web/renderers/InlineRenderers.tsx +5 -0
- package/src/web/renderers/ListRenderers.tsx +14 -2
- package/src/web/renderers/index.tsx +6 -2
- package/src/web/styles.ts +89 -5
- package/src/web/types.ts +6 -1
- package/src/web/utils.ts +1 -0
- package/src/web/wasm/md4c.js +0 -0
- package/vendor-grammars.mjs +511 -0
- package/vendor-ratex.mjs +173 -0
- package/app.plugin.js +0 -2
- package/plugin/build/withAndroidMath.js +0 -19
- package/plugin/build/withIosMath.js +0 -28
- package/plugin/build/withReactNativeEnrichedMarkdown.js +0 -11
- package/plugin/src/withAndroidMath.ts +0 -24
- package/plugin/src/withIosMath.ts +0 -35
- package/plugin/src/withReactNativeEnrichedMarkdown.ts +0 -17
- package/plugin/tsconfig.build.json +0 -16
|
@@ -7,8 +7,8 @@ typedef struct {
|
|
|
7
7
|
} ENRMDelimiterPair;
|
|
8
8
|
|
|
9
9
|
static const ENRMDelimiterPair kDelimiterPairs[] = {
|
|
10
|
-
{@"
|
|
11
|
-
{@"||", @"||", YES}, {@"`", @"`", YES}, {@"[", @"]", NO},
|
|
10
|
+
{@"***", @"***", YES}, {@"**", @"**", YES}, {@"*", @"*", YES}, {@"_", @"_", YES},
|
|
11
|
+
{@"~~", @"~~", YES}, {@"||", @"||", YES}, {@"`", @"`", YES}, {@"[", @"]", NO},
|
|
12
12
|
};
|
|
13
13
|
static const NSUInteger kDelimiterPairCount = sizeof(kDelimiterPairs) / sizeof(kDelimiterPairs[0]);
|
|
14
14
|
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#import "ENRMBlockRange.h"
|
|
4
|
+
#import "ENRMInputStyledRange.h"
|
|
5
|
+
#import <Foundation/Foundation.h>
|
|
6
|
+
|
|
7
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
8
|
+
|
|
9
|
+
typedef struct {
|
|
10
|
+
BOOL bold;
|
|
11
|
+
BOOL italic;
|
|
12
|
+
BOOL underline;
|
|
13
|
+
BOOL strikethrough;
|
|
14
|
+
BOOL spoiler;
|
|
15
|
+
BOOL link;
|
|
16
|
+
NSInteger headingLevel;
|
|
17
|
+
BOOL unorderedList;
|
|
18
|
+
BOOL orderedList;
|
|
19
|
+
NSInteger listDepth;
|
|
20
|
+
} ENRMInputStyleSnapshot;
|
|
21
|
+
|
|
22
|
+
@protocol ENRMInputStyleStateDataSource <NSObject>
|
|
23
|
+
|
|
24
|
+
- (NSRange)selectedRange;
|
|
25
|
+
- (BOOL)isEffectiveStyleActive:(ENRMInputStyleType)type atPosition:(NSUInteger)position;
|
|
26
|
+
- (BOOL)isStyleActive:(ENRMInputStyleType)type inRange:(NSRange)range;
|
|
27
|
+
- (NSInteger)headingLevelForCursorParagraph;
|
|
28
|
+
- (nullable ENRMBlockRange *)listBlockForCursorParagraph;
|
|
29
|
+
|
|
30
|
+
@end
|
|
31
|
+
|
|
32
|
+
@interface ENRMInputStyleStateBuilder : NSObject
|
|
33
|
+
|
|
34
|
+
+ (ENRMInputStyleSnapshot)snapshotAtCurrentCursor:(id<ENRMInputStyleStateDataSource>)dataSource;
|
|
35
|
+
|
|
36
|
+
+ (ENRMInputStyleSnapshot)snapshotForRange:(NSRange)range dataSource:(id<ENRMInputStyleStateDataSource>)dataSource;
|
|
37
|
+
|
|
38
|
+
@end
|
|
39
|
+
|
|
40
|
+
NS_ASSUME_NONNULL_END
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
#import "ENRMInputStyleStateBuilder.h"
|
|
2
|
+
|
|
3
|
+
@implementation ENRMInputStyleStateBuilder
|
|
4
|
+
|
|
5
|
+
+ (ENRMInputStyleSnapshot)snapshotAtCurrentCursor:(id<ENRMInputStyleStateDataSource>)dataSource
|
|
6
|
+
{
|
|
7
|
+
NSUInteger cursor = [dataSource selectedRange].location;
|
|
8
|
+
ENRMInputStyleSnapshot snapshot = {};
|
|
9
|
+
if (cursor == NSNotFound) {
|
|
10
|
+
return snapshot;
|
|
11
|
+
}
|
|
12
|
+
snapshot.bold = [dataSource isEffectiveStyleActive:ENRMInputStyleTypeStrong atPosition:cursor];
|
|
13
|
+
snapshot.italic = [dataSource isEffectiveStyleActive:ENRMInputStyleTypeEmphasis atPosition:cursor];
|
|
14
|
+
snapshot.underline = [dataSource isEffectiveStyleActive:ENRMInputStyleTypeUnderline atPosition:cursor];
|
|
15
|
+
snapshot.strikethrough = [dataSource isEffectiveStyleActive:ENRMInputStyleTypeStrikethrough atPosition:cursor];
|
|
16
|
+
snapshot.spoiler = [dataSource isEffectiveStyleActive:ENRMInputStyleTypeSpoiler atPosition:cursor];
|
|
17
|
+
snapshot.link = [dataSource isEffectiveStyleActive:ENRMInputStyleTypeLink atPosition:cursor];
|
|
18
|
+
snapshot.headingLevel = [dataSource headingLevelForCursorParagraph];
|
|
19
|
+
|
|
20
|
+
ENRMBlockRange *listBlock = [dataSource listBlockForCursorParagraph];
|
|
21
|
+
snapshot.unorderedList = listBlock != nil && listBlock.type == ENRMInputBlockTypeUnorderedListItem;
|
|
22
|
+
snapshot.orderedList = listBlock != nil && listBlock.type == ENRMInputBlockTypeOrderedListItem;
|
|
23
|
+
snapshot.listDepth = listBlock != nil ? listBlock.level : 0;
|
|
24
|
+
|
|
25
|
+
return snapshot;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
+ (ENRMInputStyleSnapshot)snapshotForRange:(NSRange)range dataSource:(id<ENRMInputStyleStateDataSource>)dataSource
|
|
29
|
+
{
|
|
30
|
+
ENRMInputStyleSnapshot snapshot = {};
|
|
31
|
+
if (range.location == NSNotFound) {
|
|
32
|
+
return snapshot;
|
|
33
|
+
}
|
|
34
|
+
if (range.length > 0) {
|
|
35
|
+
snapshot.bold = [dataSource isStyleActive:ENRMInputStyleTypeStrong inRange:range];
|
|
36
|
+
snapshot.italic = [dataSource isStyleActive:ENRMInputStyleTypeEmphasis inRange:range];
|
|
37
|
+
snapshot.underline = [dataSource isStyleActive:ENRMInputStyleTypeUnderline inRange:range];
|
|
38
|
+
snapshot.strikethrough = [dataSource isStyleActive:ENRMInputStyleTypeStrikethrough inRange:range];
|
|
39
|
+
snapshot.spoiler = [dataSource isStyleActive:ENRMInputStyleTypeSpoiler inRange:range];
|
|
40
|
+
snapshot.link = [dataSource isStyleActive:ENRMInputStyleTypeLink inRange:range];
|
|
41
|
+
} else {
|
|
42
|
+
snapshot.bold = [dataSource isEffectiveStyleActive:ENRMInputStyleTypeStrong atPosition:range.location];
|
|
43
|
+
snapshot.italic = [dataSource isEffectiveStyleActive:ENRMInputStyleTypeEmphasis atPosition:range.location];
|
|
44
|
+
snapshot.underline = [dataSource isEffectiveStyleActive:ENRMInputStyleTypeUnderline atPosition:range.location];
|
|
45
|
+
snapshot.strikethrough = [dataSource isEffectiveStyleActive:ENRMInputStyleTypeStrikethrough
|
|
46
|
+
atPosition:range.location];
|
|
47
|
+
snapshot.spoiler = [dataSource isEffectiveStyleActive:ENRMInputStyleTypeSpoiler atPosition:range.location];
|
|
48
|
+
snapshot.link = [dataSource isEffectiveStyleActive:ENRMInputStyleTypeLink atPosition:range.location];
|
|
49
|
+
}
|
|
50
|
+
snapshot.headingLevel = [dataSource headingLevelForCursorParagraph];
|
|
51
|
+
|
|
52
|
+
ENRMBlockRange *listBlock = [dataSource listBlockForCursorParagraph];
|
|
53
|
+
snapshot.unorderedList = listBlock != nil && listBlock.type == ENRMInputBlockTypeUnorderedListItem;
|
|
54
|
+
snapshot.orderedList = listBlock != nil && listBlock.type == ENRMInputBlockTypeOrderedListItem;
|
|
55
|
+
snapshot.listDepth = listBlock != nil ? listBlock.level : 0;
|
|
56
|
+
|
|
57
|
+
return snapshot;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
@end
|
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
#import "ENRMInputTextView.h"
|
|
2
|
+
#import "ENRMInputLayoutManager.h"
|
|
3
|
+
#import "EnrichedMarkdownTextInput+Internal.h"
|
|
2
4
|
#import "EnrichedMarkdownTextInput.h"
|
|
3
5
|
#import "PasteboardUtils.h"
|
|
4
6
|
#if TARGET_OS_OSX
|
|
5
|
-
#import
|
|
7
|
+
#import <objc/message.h>
|
|
6
8
|
#endif
|
|
7
9
|
|
|
8
10
|
NSString *const kENRMMarkdownPasteboardType = @"com.swmansion.enriched-markdown.markdown";
|
|
9
11
|
|
|
10
12
|
#if !TARGET_OS_OSX
|
|
11
13
|
|
|
12
|
-
@implementation ENRMInputTextView
|
|
14
|
+
@implementation ENRMInputTextView {
|
|
15
|
+
CGFloat _lastLayoutWidth;
|
|
16
|
+
}
|
|
13
17
|
|
|
14
18
|
- (void)copy:(id)sender
|
|
15
19
|
{
|
|
@@ -46,13 +50,27 @@ NSString *const kENRMMarkdownPasteboardType = @"com.swmansion.enriched-markdown.
|
|
|
46
50
|
markdown = [[NSString alloc] initWithData:markdownValue encoding:NSUTF8StringEncoding];
|
|
47
51
|
}
|
|
48
52
|
|
|
53
|
+
NSString *plainText = pasteboard.string;
|
|
54
|
+
|
|
55
|
+
// Both flavors are read before anything is decided, then nothing is written:
|
|
56
|
+
// JS owns the paste from here and must call resolvePaste. Mutating the buffer
|
|
57
|
+
// first would mean a handler that dies mid-flight leaves the selection gone
|
|
58
|
+
// with no text to show for it — a no-op paste is the visible failure.
|
|
59
|
+
if (self.markdownTextInput.interceptPaste && (plainText.length > 0 || markdown.length > 0)) {
|
|
60
|
+
[self.markdownTextInput emitOnPasteWithText:(plainText ?: @"") markdown:(markdown ?: @"")];
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
|
|
49
64
|
if (markdown.length > 0 && self.markdownTextInput != nil) {
|
|
50
65
|
[self.markdownTextInput pasteMarkdown:markdown];
|
|
51
66
|
return;
|
|
52
67
|
}
|
|
53
68
|
|
|
54
|
-
|
|
55
|
-
|
|
69
|
+
// External plain text is treated as markdown so pasted syntax ("- ", "#",
|
|
70
|
+
// "**") formats instead of landing literal; syntax-free text is unchanged.
|
|
71
|
+
if (plainText.length > 0 && self.markdownTextInput != nil) {
|
|
72
|
+
[self.markdownTextInput pasteMarkdown:plainText];
|
|
73
|
+
} else if (plainText.length > 0) {
|
|
56
74
|
[self replaceRange:self.selectedTextRange withText:plainText];
|
|
57
75
|
}
|
|
58
76
|
}
|
|
@@ -71,16 +89,65 @@ NSString *const kENRMMarkdownPasteboardType = @"com.swmansion.enriched-markdown.
|
|
|
71
89
|
- (void)layoutSubviews
|
|
72
90
|
{
|
|
73
91
|
[super layoutSubviews];
|
|
74
|
-
|
|
92
|
+
CGFloat currentWidth = self.bounds.size.width;
|
|
93
|
+
if (self.markdownTextInput != nil && fabs(currentWidth - _lastLayoutWidth) > 0.5) {
|
|
94
|
+
_lastLayoutWidth = currentWidth;
|
|
75
95
|
[self.markdownTextInput scheduleRelayoutIfNeeded];
|
|
76
96
|
}
|
|
77
97
|
}
|
|
78
98
|
|
|
99
|
+
- (void)deleteBackward
|
|
100
|
+
{
|
|
101
|
+
// Backspace at the very start of the document doesn't fire the text-change
|
|
102
|
+
// delegate (nothing precedes the caret), so removing/outdenting the first
|
|
103
|
+
// line's list marker has to be handled here.
|
|
104
|
+
if (self.markdownTextInput != nil && [self.markdownTextInput handleBackspaceAtDocumentStart]) {
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
[super deleteBackward];
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/// Hardware-keyboard Tab / Shift+Tab indent and outdent the current list item.
|
|
111
|
+
/// UIKeyCommand only fires for an attached keyboard; on-screen Tab/Backspace go
|
|
112
|
+
/// through the text-change delegate (see handleListKeyForReplacementRange:).
|
|
113
|
+
- (NSArray<UIKeyCommand *> *)keyCommands
|
|
114
|
+
{
|
|
115
|
+
return @[
|
|
116
|
+
[UIKeyCommand keyCommandWithInput:@"\t" modifierFlags:0 action:@selector(enrmIndentList:)],
|
|
117
|
+
[UIKeyCommand keyCommandWithInput:@"\t" modifierFlags:UIKeyModifierShift action:@selector(enrmOutdentList:)],
|
|
118
|
+
];
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
- (void)enrmIndentList:(UIKeyCommand *)command
|
|
122
|
+
{
|
|
123
|
+
[self.markdownTextInput indentList];
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
- (void)enrmOutdentList:(UIKeyCommand *)command
|
|
127
|
+
{
|
|
128
|
+
[self.markdownTextInput outdentList];
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
- (void)drawRect:(CGRect)rect
|
|
132
|
+
{
|
|
133
|
+
[super drawRect:rect];
|
|
134
|
+
// A wholly empty editor has no glyphs, so the layout manager's
|
|
135
|
+
// drawGlyphsForGlyphRange: never runs — draw decorations here instead.
|
|
136
|
+
if (self.text.length == 0) {
|
|
137
|
+
NSLayoutManager *layoutManager = self.layoutManager;
|
|
138
|
+
if ([layoutManager isKindOfClass:[ENRMInputLayoutManager class]]) {
|
|
139
|
+
[(ENRMInputLayoutManager *)layoutManager drawEmptyEditorDecorationsWithInset:self.textContainerInset];
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
79
144
|
@end
|
|
80
145
|
|
|
81
146
|
#else // TARGET_OS_OSX
|
|
82
147
|
|
|
83
|
-
@implementation ENRMInputTextView
|
|
148
|
+
@implementation ENRMInputTextView {
|
|
149
|
+
CGFloat _lastLayoutWidth;
|
|
150
|
+
}
|
|
84
151
|
|
|
85
152
|
- (void)copy:(id)sender
|
|
86
153
|
{
|
|
@@ -115,8 +182,12 @@ NSString *const kENRMMarkdownPasteboardType = @"com.swmansion.enriched-markdown.
|
|
|
115
182
|
return;
|
|
116
183
|
}
|
|
117
184
|
|
|
185
|
+
// External plain text is treated as markdown so pasted syntax ("- ", "#",
|
|
186
|
+
// "**") formats instead of landing literal; syntax-free text is unchanged.
|
|
118
187
|
NSString *plainText = [pasteboard stringForType:NSPasteboardTypeString];
|
|
119
|
-
if (plainText.length > 0) {
|
|
188
|
+
if (plainText.length > 0 && self.markdownTextInput != nil) {
|
|
189
|
+
[self.markdownTextInput pasteMarkdown:plainText];
|
|
190
|
+
} else if (plainText.length > 0) {
|
|
120
191
|
[self insertText:plainText replacementRange:self.selectedRange];
|
|
121
192
|
}
|
|
122
193
|
}
|
|
@@ -153,14 +224,38 @@ NSString *const kENRMMarkdownPasteboardType = @"com.swmansion.enriched-markdown.
|
|
|
153
224
|
return menu;
|
|
154
225
|
}
|
|
155
226
|
|
|
227
|
+
- (void)setTypingAttributes:(NSDictionary *)typingAttributes
|
|
228
|
+
{
|
|
229
|
+
// RCTUITextView's override discards the value and always resets to
|
|
230
|
+
// defaultTextAttributes. We need the actual value (e.g. list paragraph
|
|
231
|
+
// indent) to reach NSTextView so the caret positions correctly.
|
|
232
|
+
struct objc_super superSuper = {self, [NSTextView class]};
|
|
233
|
+
((void (*)(struct objc_super *, SEL, NSDictionary *))objc_msgSendSuper)(&superSuper, _cmd, typingAttributes);
|
|
234
|
+
}
|
|
235
|
+
|
|
156
236
|
- (void)layout
|
|
157
237
|
{
|
|
158
238
|
[super layout];
|
|
159
|
-
|
|
239
|
+
CGFloat currentWidth = self.bounds.size.width;
|
|
240
|
+
if (self.markdownTextInput != nil && fabs(currentWidth - _lastLayoutWidth) > 0.5) {
|
|
241
|
+
_lastLayoutWidth = currentWidth;
|
|
160
242
|
[self.markdownTextInput scheduleRelayoutIfNeeded];
|
|
161
243
|
}
|
|
162
244
|
}
|
|
163
245
|
|
|
246
|
+
- (void)drawRect:(NSRect)rect
|
|
247
|
+
{
|
|
248
|
+
[super drawRect:rect];
|
|
249
|
+
if (self.string.length == 0) {
|
|
250
|
+
NSLayoutManager *lm = self.layoutManager;
|
|
251
|
+
if ([lm isKindOfClass:[ENRMInputLayoutManager class]]) {
|
|
252
|
+
NSEdgeInsets insets = self.textContainerInsets;
|
|
253
|
+
insets.left += self.textContainer.lineFragmentPadding;
|
|
254
|
+
[(ENRMInputLayoutManager *)lm drawEmptyEditorDecorationsWithInset:insets];
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
164
259
|
@end
|
|
165
260
|
|
|
166
261
|
#endif
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#import "ENRMBlockRange.h"
|
|
4
|
+
#import "ENRMEditSession.h"
|
|
5
|
+
#import "ENRMInputFormatterStyle.h"
|
|
6
|
+
#import "ENRMInputStyledRange.h"
|
|
7
|
+
#import "ENRMInputTextView.h"
|
|
8
|
+
#import <Foundation/Foundation.h>
|
|
9
|
+
|
|
10
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
11
|
+
|
|
12
|
+
@protocol ENRMInputTypingAttributesDataSource <NSObject>
|
|
13
|
+
|
|
14
|
+
- (NSRange)selectedRange;
|
|
15
|
+
- (NSInteger)headingLevelForCursorParagraph;
|
|
16
|
+
- (nullable ENRMBlockRange *)listBlockForCursorParagraph;
|
|
17
|
+
- (BOOL)isStyleAdjacentBefore:(ENRMInputStyleType)type position:(NSUInteger)position;
|
|
18
|
+
- (BOOL)isStyleActive:(ENRMInputStyleType)type atPosition:(NSUInteger)position;
|
|
19
|
+
|
|
20
|
+
@end
|
|
21
|
+
|
|
22
|
+
@interface ENRMInputTypingAttributesController : NSObject
|
|
23
|
+
|
|
24
|
+
- (instancetype)initWithTextView:(ENRMPlatformTextView *)textView
|
|
25
|
+
formatterStyle:(ENRMInputFormatterStyle *)style
|
|
26
|
+
dataSource:(id<ENRMInputTypingAttributesDataSource>)dataSource
|
|
27
|
+
editSession:(ENRMEditSession *)editSession;
|
|
28
|
+
|
|
29
|
+
- (BOOL)isEffectiveStyleActive:(ENRMInputStyleType)type atPosition:(NSUInteger)position;
|
|
30
|
+
- (void)togglePendingStyle:(ENRMInputStyleType)type wasActive:(BOOL)wasActive hasSelection:(BOOL)hasSelection;
|
|
31
|
+
- (void)clearPendingStyle:(ENRMInputStyleType)type;
|
|
32
|
+
- (void)syncWithCursorBlock;
|
|
33
|
+
- (void)syncWithPendingStyles;
|
|
34
|
+
- (void)resetForSelectionChange;
|
|
35
|
+
- (void)clearListParagraphStyle;
|
|
36
|
+
|
|
37
|
+
@property (nonatomic, readonly) NSSet<NSNumber *> *pendingStyles;
|
|
38
|
+
@property (nonatomic, readonly) NSSet<NSNumber *> *pendingStyleRemovals;
|
|
39
|
+
|
|
40
|
+
@end
|
|
41
|
+
|
|
42
|
+
NS_ASSUME_NONNULL_END
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
#import "ENRMInputTypingAttributesController.h"
|
|
2
|
+
#import "ENRMInputBlockType.h"
|
|
3
|
+
|
|
4
|
+
@implementation ENRMInputTypingAttributesController {
|
|
5
|
+
__weak ENRMPlatformTextView *_textView;
|
|
6
|
+
__weak id<ENRMInputTypingAttributesDataSource> _dataSource;
|
|
7
|
+
ENRMInputFormatterStyle *_formatterStyle;
|
|
8
|
+
ENRMEditSession *_editSession;
|
|
9
|
+
|
|
10
|
+
NSMutableSet<NSNumber *> *_pendingStyles;
|
|
11
|
+
NSMutableSet<NSNumber *> *_pendingStyleRemovals;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
- (instancetype)initWithTextView:(ENRMPlatformTextView *)textView
|
|
15
|
+
formatterStyle:(ENRMInputFormatterStyle *)style
|
|
16
|
+
dataSource:(id<ENRMInputTypingAttributesDataSource>)dataSource
|
|
17
|
+
editSession:(ENRMEditSession *)editSession
|
|
18
|
+
{
|
|
19
|
+
self = [super init];
|
|
20
|
+
if (self) {
|
|
21
|
+
_textView = textView;
|
|
22
|
+
_formatterStyle = style;
|
|
23
|
+
_dataSource = dataSource;
|
|
24
|
+
_editSession = editSession;
|
|
25
|
+
_pendingStyles = [NSMutableSet set];
|
|
26
|
+
_pendingStyleRemovals = [NSMutableSet set];
|
|
27
|
+
}
|
|
28
|
+
return self;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
#pragma mark - Properties
|
|
32
|
+
|
|
33
|
+
- (NSSet<NSNumber *> *)pendingStyles
|
|
34
|
+
{
|
|
35
|
+
return [_pendingStyles copy];
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
- (NSSet<NSNumber *> *)pendingStyleRemovals
|
|
39
|
+
{
|
|
40
|
+
return [_pendingStyleRemovals copy];
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
#pragma mark - Style queries
|
|
44
|
+
|
|
45
|
+
- (BOOL)isEffectiveStyleActive:(ENRMInputStyleType)type atPosition:(NSUInteger)position
|
|
46
|
+
{
|
|
47
|
+
BOOL inRange = [_dataSource isStyleActive:type atPosition:position];
|
|
48
|
+
NSNumber *key = @(type);
|
|
49
|
+
if ([_pendingStyleRemovals containsObject:key]) {
|
|
50
|
+
return NO;
|
|
51
|
+
}
|
|
52
|
+
if ([_pendingStyles containsObject:key]) {
|
|
53
|
+
return YES;
|
|
54
|
+
}
|
|
55
|
+
return inRange;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
#pragma mark - Pending style mutations
|
|
59
|
+
|
|
60
|
+
- (void)togglePendingStyle:(ENRMInputStyleType)type wasActive:(BOOL)wasActive hasSelection:(BOOL)hasSelection
|
|
61
|
+
{
|
|
62
|
+
NSNumber *key = @(type);
|
|
63
|
+
if (hasSelection) {
|
|
64
|
+
[_pendingStyles removeObject:key];
|
|
65
|
+
[_pendingStyleRemovals removeObject:key];
|
|
66
|
+
} else {
|
|
67
|
+
if ([_pendingStyleRemovals containsObject:key]) {
|
|
68
|
+
[_pendingStyleRemovals removeObject:key];
|
|
69
|
+
} else if ([_pendingStyles containsObject:key]) {
|
|
70
|
+
[_pendingStyles removeObject:key];
|
|
71
|
+
} else if (wasActive) {
|
|
72
|
+
[_pendingStyleRemovals addObject:key];
|
|
73
|
+
} else {
|
|
74
|
+
[_pendingStyles addObject:key];
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
- (void)clearPendingStyle:(ENRMInputStyleType)type
|
|
80
|
+
{
|
|
81
|
+
NSNumber *key = @(type);
|
|
82
|
+
[_pendingStyles removeObject:key];
|
|
83
|
+
[_pendingStyleRemovals removeObject:key];
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
#pragma mark - Typing attribute synchronization
|
|
87
|
+
|
|
88
|
+
- (void)syncWithCursorBlock
|
|
89
|
+
{
|
|
90
|
+
UIFontDescriptorSymbolicTraits traits = 0;
|
|
91
|
+
if ([_pendingStyles containsObject:@(ENRMInputStyleTypeStrong)]) {
|
|
92
|
+
traits |= UIFontDescriptorTraitBold;
|
|
93
|
+
}
|
|
94
|
+
if ([_pendingStyles containsObject:@(ENRMInputStyleTypeEmphasis)]) {
|
|
95
|
+
traits |= UIFontDescriptorTraitItalic;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
NSInteger headingLevel = [_dataSource headingLevelForCursorParagraph];
|
|
99
|
+
|
|
100
|
+
UIFont *font;
|
|
101
|
+
if (headingLevel >= 1 && headingLevel <= 6) {
|
|
102
|
+
UIFont *headingFont = [_formatterStyle headingFontForLevel:headingLevel];
|
|
103
|
+
UIFontDescriptorSymbolicTraits merged = headingFont.fontDescriptor.symbolicTraits | traits;
|
|
104
|
+
UIFontDescriptor *descriptor = [headingFont.fontDescriptor fontDescriptorWithSymbolicTraits:merged];
|
|
105
|
+
font = descriptor ? [UIFont fontWithDescriptor:descriptor size:0] : headingFont;
|
|
106
|
+
} else {
|
|
107
|
+
font = [_formatterStyle fontForTraits:traits];
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
NSMutableDictionary *attrs = [_textView.typingAttributes mutableCopy];
|
|
111
|
+
attrs[NSFontAttributeName] = font;
|
|
112
|
+
RCTUIColor *headingColor = headingLevel >= 1 ? [_formatterStyle headingColorForLevel:headingLevel] : nil;
|
|
113
|
+
attrs[NSForegroundColorAttributeName] = headingColor ?: _formatterStyle.baseTextColor;
|
|
114
|
+
|
|
115
|
+
ENRMBlockRange *typingListBlock = [_dataSource listBlockForCursorParagraph];
|
|
116
|
+
if (typingListBlock != nil) {
|
|
117
|
+
NSMutableParagraphStyle *paragraph = [[NSMutableParagraphStyle alloc] init];
|
|
118
|
+
CGFloat indent = (typingListBlock.level + 1) * kENRMListIndentPerDepth;
|
|
119
|
+
paragraph.firstLineHeadIndent = indent;
|
|
120
|
+
paragraph.headIndent = indent;
|
|
121
|
+
paragraph.paragraphSpacingBefore = _formatterStyle.listItemSpacing;
|
|
122
|
+
attrs[NSParagraphStyleAttributeName] = paragraph;
|
|
123
|
+
} else {
|
|
124
|
+
[attrs removeObjectForKey:NSParagraphStyleAttributeName];
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (![attrs isEqualToDictionary:_textView.typingAttributes]) {
|
|
128
|
+
_textView.typingAttributes = attrs;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
- (void)syncWithPendingStyles
|
|
133
|
+
{
|
|
134
|
+
UIFontDescriptorSymbolicTraits traits = 0;
|
|
135
|
+
if ([_pendingStyles containsObject:@(ENRMInputStyleTypeStrong)]) {
|
|
136
|
+
traits |= UIFontDescriptorTraitBold;
|
|
137
|
+
}
|
|
138
|
+
if ([_pendingStyles containsObject:@(ENRMInputStyleTypeEmphasis)]) {
|
|
139
|
+
traits |= UIFontDescriptorTraitItalic;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
NSMutableDictionary *attrs = [_textView.typingAttributes mutableCopy];
|
|
143
|
+
attrs[NSFontAttributeName] = [_formatterStyle fontForTraits:traits];
|
|
144
|
+
_textView.typingAttributes = attrs;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
- (void)resetForSelectionChange
|
|
148
|
+
{
|
|
149
|
+
if (_editSession.isPostEditGracePeriod) {
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
[_pendingStyles removeAllObjects];
|
|
153
|
+
[_pendingStyleRemovals removeAllObjects];
|
|
154
|
+
[self rebuildFromContext];
|
|
155
|
+
if ([_dataSource selectedRange].length == 0) {
|
|
156
|
+
[self syncWithCursorBlock];
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
- (void)clearListParagraphStyle
|
|
161
|
+
{
|
|
162
|
+
if (_textView.typingAttributes[NSParagraphStyleAttributeName] == nil) {
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
NSMutableDictionary *attrs = [_textView.typingAttributes mutableCopy];
|
|
166
|
+
[attrs removeObjectForKey:NSParagraphStyleAttributeName];
|
|
167
|
+
_textView.typingAttributes = attrs;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
#pragma mark - Private
|
|
171
|
+
|
|
172
|
+
- (void)rebuildFromContext
|
|
173
|
+
{
|
|
174
|
+
static const ENRMInputStyleType inlineStyles[] = {
|
|
175
|
+
ENRMInputStyleTypeStrong, ENRMInputStyleTypeEmphasis, ENRMInputStyleTypeUnderline,
|
|
176
|
+
ENRMInputStyleTypeStrikethrough, ENRMInputStyleTypeSpoiler,
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
NSRange selection = [_dataSource selectedRange];
|
|
180
|
+
|
|
181
|
+
if (selection.length > 0) {
|
|
182
|
+
for (NSUInteger i = 0; i < sizeof(inlineStyles) / sizeof(inlineStyles[0]); i++) {
|
|
183
|
+
ENRMInputStyleType type = inlineStyles[i];
|
|
184
|
+
if ([_dataSource isStyleActive:type atPosition:selection.location]) {
|
|
185
|
+
[_pendingStyles addObject:@(type)];
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
if (selection.location == 0) {
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
for (NSUInteger i = 0; i < sizeof(inlineStyles) / sizeof(inlineStyles[0]); i++) {
|
|
196
|
+
ENRMInputStyleType type = inlineStyles[i];
|
|
197
|
+
if ([_dataSource isStyleAdjacentBefore:type position:selection.location]) {
|
|
198
|
+
[_pendingStyles addObject:@(type)];
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
@end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#import "ENRMFormattingRange.h"
|
|
4
|
+
#import "ENRMFormattingStore.h"
|
|
5
|
+
#import <Foundation/Foundation.h>
|
|
6
|
+
|
|
7
|
+
@class AutoLinkDetector;
|
|
8
|
+
|
|
9
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
10
|
+
|
|
11
|
+
@protocol ENRMAutoLinkDetecting <NSObject>
|
|
12
|
+
- (void)clearAutoLinkInRange:(NSRange)range;
|
|
13
|
+
@end
|
|
14
|
+
|
|
15
|
+
@interface ENRMLinkCoordinator : NSObject
|
|
16
|
+
|
|
17
|
+
- (instancetype)initWithFormattingStore:(ENRMFormattingStore *)formattingStore
|
|
18
|
+
autoLinkDetector:(id<ENRMAutoLinkDetecting>)autoLinkDetector;
|
|
19
|
+
|
|
20
|
+
- (NSString *)sanitizeURL:(NSString *)url;
|
|
21
|
+
- (nullable ENRMFormattingRange *)linkAtPosition:(NSUInteger)position;
|
|
22
|
+
|
|
23
|
+
/// Sets a link on the selection range, or updates an existing link's URL at the cursor.
|
|
24
|
+
/// Returns YES if a mutation occurred.
|
|
25
|
+
- (BOOL)setLinkURL:(NSString *)url atCursor:(NSUInteger)cursor selection:(NSRange)selection;
|
|
26
|
+
|
|
27
|
+
/// Adds a new link range (sanitizes the URL, clears auto-links).
|
|
28
|
+
- (void)addLinkWithURL:(NSString *)url start:(NSUInteger)start end:(NSUInteger)end;
|
|
29
|
+
|
|
30
|
+
/// Adds a link range with an already-sanitized URL (no auto-link clearing).
|
|
31
|
+
- (void)addLinkDirectWithURL:(NSString *)url start:(NSUInteger)start end:(NSUInteger)end;
|
|
32
|
+
|
|
33
|
+
/// Removes the link at the given position. Returns YES if a link was found and removed.
|
|
34
|
+
- (BOOL)removeLinkAtPosition:(NSUInteger)position;
|
|
35
|
+
|
|
36
|
+
/// Returns the link range containing `position - 1`, for atomic link deletion.
|
|
37
|
+
- (nullable ENRMFormattingRange *)linkRangeForDeletionAtPosition:(NSUInteger)position;
|
|
38
|
+
|
|
39
|
+
@end
|
|
40
|
+
|
|
41
|
+
NS_ASSUME_NONNULL_END
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
#import "ENRMLinkCoordinator.h"
|
|
2
|
+
|
|
3
|
+
@implementation ENRMLinkCoordinator {
|
|
4
|
+
ENRMFormattingStore *_formattingStore;
|
|
5
|
+
id<ENRMAutoLinkDetecting> _autoLinkDetector;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
- (instancetype)initWithFormattingStore:(ENRMFormattingStore *)formattingStore
|
|
9
|
+
autoLinkDetector:(id<ENRMAutoLinkDetecting>)autoLinkDetector
|
|
10
|
+
{
|
|
11
|
+
if (self = [super init]) {
|
|
12
|
+
_formattingStore = formattingStore;
|
|
13
|
+
_autoLinkDetector = autoLinkDetector;
|
|
14
|
+
}
|
|
15
|
+
return self;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
- (NSString *)sanitizeURL:(NSString *)url
|
|
19
|
+
{
|
|
20
|
+
NSString *result = [url stringByReplacingOccurrencesOfString:@"(" withString:@"%28"];
|
|
21
|
+
return [result stringByReplacingOccurrencesOfString:@")" withString:@"%29"];
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
- (nullable ENRMFormattingRange *)linkAtPosition:(NSUInteger)position
|
|
25
|
+
{
|
|
26
|
+
return [_formattingStore rangeOfType:ENRMInputStyleTypeLink containingPosition:position];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
- (BOOL)setLinkURL:(NSString *)url atCursor:(NSUInteger)cursor selection:(NSRange)selection
|
|
30
|
+
{
|
|
31
|
+
ENRMFormattingRange *activeLink = [_formattingStore rangeOfType:ENRMInputStyleTypeLink containingPosition:cursor];
|
|
32
|
+
|
|
33
|
+
if (activeLink != nil) {
|
|
34
|
+
activeLink.url = url;
|
|
35
|
+
[_autoLinkDetector clearAutoLinkInRange:activeLink.range];
|
|
36
|
+
return YES;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (selection.length > 0) {
|
|
40
|
+
ENRMFormattingRange *linkRange = [ENRMFormattingRange rangeWithType:ENRMInputStyleTypeLink range:selection url:url];
|
|
41
|
+
[_formattingStore addRange:linkRange];
|
|
42
|
+
[_autoLinkDetector clearAutoLinkInRange:selection];
|
|
43
|
+
return YES;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return NO;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
- (void)addLinkWithURL:(NSString *)url start:(NSUInteger)start end:(NSUInteger)end
|
|
50
|
+
{
|
|
51
|
+
if (start >= end) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
NSRange range = NSMakeRange(start, end - start);
|
|
55
|
+
[_autoLinkDetector clearAutoLinkInRange:range];
|
|
56
|
+
[_formattingStore addRange:[ENRMFormattingRange rangeWithType:ENRMInputStyleTypeLink
|
|
57
|
+
range:range
|
|
58
|
+
url:[self sanitizeURL:url]]];
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
- (void)addLinkDirectWithURL:(NSString *)url start:(NSUInteger)start end:(NSUInteger)end
|
|
62
|
+
{
|
|
63
|
+
if (start >= end) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
[_formattingStore addRange:[ENRMFormattingRange rangeWithType:ENRMInputStyleTypeLink
|
|
67
|
+
range:NSMakeRange(start, end - start)
|
|
68
|
+
url:url]];
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
- (BOOL)removeLinkAtPosition:(NSUInteger)position
|
|
72
|
+
{
|
|
73
|
+
ENRMFormattingRange *activeLink = [_formattingStore rangeOfType:ENRMInputStyleTypeLink containingPosition:position];
|
|
74
|
+
if (activeLink == nil) {
|
|
75
|
+
return NO;
|
|
76
|
+
}
|
|
77
|
+
[_formattingStore removeRange:activeLink];
|
|
78
|
+
return YES;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
- (nullable ENRMFormattingRange *)linkRangeForDeletionAtPosition:(NSUInteger)position
|
|
82
|
+
{
|
|
83
|
+
if (position == 0) {
|
|
84
|
+
return nil;
|
|
85
|
+
}
|
|
86
|
+
return [_formattingStore rangeOfType:ENRMInputStyleTypeLink containingPosition:position - 1];
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
@end
|