react-native-enriched-markdown-scaffold 0.6.0-scaffold.4
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/LICENSE +20 -0
- package/README.md +53 -0
- package/ReactNativeEnrichedMarkdown.podspec +67 -0
- package/android/build.gradle +94 -0
- package/android/consumer-rules.pro +19 -0
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownManagerDelegate.java +87 -0
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownManagerInterface.java +37 -0
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextInputManagerDelegate.java +159 -0
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextInputManagerInterface.java +59 -0
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextManagerDelegate.java +87 -0
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextManagerInterface.java +37 -0
- package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/ComponentDescriptors.cpp +22 -0
- package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/ComponentDescriptors.h +24 -0
- package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/EventEmitters.cpp +318 -0
- package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/EventEmitters.h +259 -0
- package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/Props.cpp +375 -0
- package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/Props.h +5174 -0
- package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/ShadowNodes.cpp +17 -0
- package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/ShadowNodes.h +23 -0
- package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/States.cpp +16 -0
- package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/States.h +20 -0
- package/android/gradle.properties +5 -0
- package/android/src/main/AndroidManifest.xml +2 -0
- package/android/src/main/baseline-prof.txt +254 -0
- package/android/src/main/cpp/jni-adapter.cpp +264 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdown.kt +554 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownInternalText.kt +122 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownManager.kt +255 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownText.kt +363 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownTextLayoutManager.kt +15 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownTextManager.kt +253 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownTextPackage.kt +20 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/MeasurementStore.kt +653 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/accessibility/AccessibleMarkdownTextView.kt +33 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/accessibility/MarkdownAccessibilityHelper.kt +482 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/events/ContextMenuItemPressEvent.kt +28 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/events/LinkLongPressEvent.kt +23 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/events/LinkPressEvent.kt +23 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/events/TaskListItemPressEvent.kt +26 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/EnrichedMarkdownTextInputManager.kt +465 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/EnrichedMarkdownTextInputView.kt +1066 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/autolink/AutoDetectedLinkSpan.kt +29 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/autolink/AutoLinkDetector.kt +188 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/autolink/LinkRegexConfig.kt +9 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/detection/DetectorPipeline.kt +40 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/detection/TextDetector.kt +27 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/detection/WordResult.kt +7 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/detection/WordsUtils.kt +65 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/InputConnectionWrapper.kt +69 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/MarkdownEditableFactory.kt +15 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/MarkdownTextWatcher.kt +41 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnCaretRectChangeEvent.kt +20 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnChangeMarkdownEvent.kt +22 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnChangeMentionEvent.kt +24 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnChangeSelectionEvent.kt +24 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnChangeStateEvent.kt +50 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnChangeTextEvent.kt +22 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnContextMenuItemPressEvent.kt +48 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnEndMentionEvent.kt +22 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnInputBlurEvent.kt +18 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnInputFocusEvent.kt +18 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnLinkDetectedEvent.kt +28 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnMathPressEvent.kt +36 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnRequestCaretRectResultEvent.kt +25 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnRequestMarkdownResultEvent.kt +24 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnStartMentionEvent.kt +22 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/FormattingStore.kt +192 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/InputFormatter.kt +117 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/InputParser.kt +117 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/InputRemend.kt +120 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/MarkdownSerializer.kt +176 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/layout/InputEventEmitter.kt +216 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/layout/InputLayoutManager.kt +28 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/layout/InputMeasurementStore.kt +137 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/math/MathChipController.kt +113 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/model/CaretRect.kt +17 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/model/FormattingRange.kt +10 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/model/InputFormatterStyle.kt +28 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/model/MathAtom.kt +7 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/model/MathChipStyle.kt +47 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/model/StyleType.kt +10 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/styles/BoldStyleHandler.kt +35 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/styles/ItalicStyleHandler.kt +35 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/styles/LinkStyleHandler.kt +75 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/styles/SpoilerStyleHandler.kt +36 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/styles/StrikethroughStyleHandler.kt +24 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/styles/StyleHandler.kt +18 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/styles/StyleMergingConfig.kt +10 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/styles/UnderlineStyleHandler.kt +24 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/toolbar/InputContextMenu.kt +181 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/parser/MarkdownASTNode.kt +43 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/parser/Parser.kt +68 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/BaselineShiftRenderer.kt +44 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/BlockStyleContext.kt +152 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/BlockquoteRenderer.kt +87 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/CodeBlockRenderer.kt +104 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/CodeRenderer.kt +36 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/DocumentRenderer.kt +16 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/EmphasisRenderer.kt +27 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/HeadingRenderer.kt +71 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/HighlightRenderer.kt +25 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/ImageRenderer.kt +61 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/LineBreakRenderer.kt +16 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/LinkRenderer.kt +29 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListContextManager.kt +89 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListItemRenderer.kt +127 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListRenderer.kt +74 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/NodeRenderer.kt +161 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/ParagraphRenderer.kt +75 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/Renderer.kt +113 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/SpanStyleCache.kt +134 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/SpoilerRenderer.kt +25 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/StrikethroughRenderer.kt +27 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/StrongRenderer.kt +27 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/SubscriptRenderer.kt +11 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/SuperscriptRenderer.kt +11 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/TextRenderer.kt +30 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/ThematicBreakRenderer.kt +45 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/UnderlineRenderer.kt +27 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/BaseListSpan.kt +127 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/BaselineShiftSpan.kt +27 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/BlockquoteSpan.kt +152 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/CodeBackgroundSpan.kt +180 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/CodeBlockSpan.kt +196 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/CodeSpan.kt +32 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/EmphasisSpan.kt +42 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/FadeInSpan.kt +25 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/HeadingSpan.kt +38 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/HighlightSpan.kt +26 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/ImageSpan.kt +335 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/LineHeightSpan.kt +27 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/LinkSpan.kt +66 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/MarginBottomSpan.kt +76 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/MathModels.kt +18 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/OrderedListSpan.kt +85 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/SpoilerSpan.kt +33 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/StrikethroughSpan.kt +12 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/StrongSpan.kt +39 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/TaskListSpan.kt +134 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/TextSpan.kt +26 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/ThematicBreakSpan.kt +69 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/UnorderedListSpan.kt +92 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spoiler/ParticleStrategy.kt +68 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spoiler/SegmentKey.kt +13 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spoiler/SolidStrategy.kt +95 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spoiler/SpoilerAnimator.kt +89 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spoiler/SpoilerCapable.kt +5 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spoiler/SpoilerConstants.kt +3 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spoiler/SpoilerDrawContext.kt +33 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spoiler/SpoilerDrawUtils.kt +40 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spoiler/SpoilerOverlay.kt +17 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spoiler/SpoilerOverlayDrawer.kt +152 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spoiler/SpoilerParticleDrawable.kt +237 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spoiler/SpoilerStrategy.kt +53 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/BaseBlockStyle.kt +11 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/BlockquoteStyle.kt +51 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/CodeBlockStyle.kt +54 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/CodeStyle.kt +26 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/EmphasisStyle.kt +21 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/HeadingStyle.kt +33 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/HighlightStyle.kt +19 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/ImageStyle.kt +23 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/InlineImageStyle.kt +17 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/InlineMathStyle.kt +17 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/LinkStyle.kt +23 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/LinkVariantEntry.kt +29 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/ListStyle.kt +62 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/MathStyle.kt +29 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/ParagraphStyle.kt +33 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/SpoilerStyle.kt +27 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/StrikethroughStyle.kt +17 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/StrongStyle.kt +21 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/StyleConfig.kt +364 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/StyleParser.kt +92 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/SubscriptStyle.kt +16 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/SuperscriptStyle.kt +16 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/TableStyle.kt +69 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/TaskListStyle.kt +29 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/TextAlignment.kt +32 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/ThematicBreakStyle.kt +23 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/UnderlineStyle.kt +17 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/BreakStrategyUtils.kt +32 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/FeatureFlags.kt +7 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/MarkdownSegment.kt +56 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/MarkdownViewManagerUtils.kt +100 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/MotionPreferences.kt +18 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/ReadableMapExtensions.kt +20 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/RenderedSegment.kt +78 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/SegmentReconciler.kt +118 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/SegmentSignature.kt +78 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/StreamingMarkdownFilter.kt +142 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/layout/RTLUtils.kt +6 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/serialization/MarkdownASTSerializer.kt +115 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/input/AutoCapitalizeUtils.kt +27 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/input/BorderPropsApplicator.kt +77 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/input/MarkdownStyleParser.kt +184 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/ImageCache.kt +53 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/ImageDownloader.kt +156 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/TailFadeInAnimator.kt +84 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/conversion/HTMLGenerator.kt +1067 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/conversion/MarkdownExtractor.kt +419 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/extensions/ParagraphUtils.kt +9 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/extensions/SpannableExtensions.kt +65 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/extensions/TextPaintExtensions.kt +53 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/interaction/CheckboxTouchHelper.kt +54 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/interaction/TaskListTapUtils.kt +249 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/span/BlockSpacing.kt +89 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/span/SpanFlags.kt +17 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/LinkEvents.kt +43 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/LinkLongPressMovementMethod.kt +187 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/SelectionActionMode.kt +205 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/TextSelectionColors.kt +48 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/TextViewSetup.kt +40 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/views/BlockSegmentView.kt +10 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/views/ContextMenuPopup.kt +214 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/views/TableContainerView.kt +501 -0
- package/android/src/main/jni/CMakeLists.txt +70 -0
- package/android/src/main/jni/EnrichedMarkdownTextSpec.cpp +21 -0
- package/android/src/main/jni/EnrichedMarkdownTextSpec.h +15 -0
- package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/ComponentDescriptors.h +67 -0
- package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownContainerComponentDescriptor.h +26 -0
- package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownContainerMeasurementManager.cpp +45 -0
- package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownContainerMeasurementManager.h +21 -0
- package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownContainerShadowNode.cpp +20 -0
- package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownContainerShadowNode.h +34 -0
- package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextComponentDescriptor.h +29 -0
- package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextInputMeasurementManager.cpp +44 -0
- package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextInputMeasurementManager.h +21 -0
- package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextInputShadowNode.cpp +30 -0
- package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextInputShadowNode.h +43 -0
- package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextInputState.cpp +9 -0
- package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextInputState.h +24 -0
- package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextMeasurementManager.cpp +45 -0
- package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextMeasurementManager.h +21 -0
- package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextShadowNode.cpp +20 -0
- package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextShadowNode.h +37 -0
- package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/conversions.h +45 -0
- package/android/src/math/java/com/swmansion/enriched/markdown/input/math/MathChipControllerImpl.kt +217 -0
- package/android/src/math/java/com/swmansion/enriched/markdown/renderer/MathInlineRenderer.kt +47 -0
- package/android/src/math/java/com/swmansion/enriched/markdown/spans/MathChipSpan.kt +208 -0
- package/android/src/math/java/com/swmansion/enriched/markdown/spans/MathInlinePlaceholderSpan.kt +41 -0
- package/android/src/math/java/com/swmansion/enriched/markdown/spans/MathInlineSpan.kt +92 -0
- package/android/src/math/java/com/swmansion/enriched/markdown/spans/MathMeasureHelper.kt +57 -0
- package/android/src/math/java/com/swmansion/enriched/markdown/views/MathContainerView.kt +148 -0
- package/app.plugin.js +1 -0
- package/cpp/md4c/md4c.c +7235 -0
- package/cpp/md4c/md4c.h +475 -0
- package/cpp/parser/MD4CParser.cpp +539 -0
- package/cpp/parser/MD4CParser.hpp +32 -0
- package/cpp/parser/MarkdownASTNode.hpp +63 -0
- package/cpp/wasm/ASTSerializer.cpp +158 -0
- package/cpp/wasm/ASTSerializer.hpp +17 -0
- package/cpp/wasm/build.sh +58 -0
- package/cpp/wasm/md4c_wasm.cpp +43 -0
- package/ios/EnrichedMarkdown.h +20 -0
- package/ios/EnrichedMarkdown.mm +1121 -0
- package/ios/EnrichedMarkdownText.h +20 -0
- package/ios/EnrichedMarkdownText.mm +802 -0
- package/ios/attachments/ENRMImageAttachment.h +27 -0
- package/ios/attachments/ENRMImageAttachment.m +305 -0
- package/ios/attachments/ENRMMathInlineAttachment+macOS.m +60 -0
- package/ios/attachments/ENRMMathInlineAttachment.h +47 -0
- package/ios/attachments/ENRMMathInlineAttachment.m +142 -0
- package/ios/attachments/ENRMMathInlineAttachmentShared.h +17 -0
- package/ios/attachments/ThematicBreakAttachment.h +15 -0
- package/ios/attachments/ThematicBreakAttachment.m +33 -0
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/ComponentDescriptors.cpp +22 -0
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/ComponentDescriptors.h +24 -0
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/EventEmitters.cpp +318 -0
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/EventEmitters.h +259 -0
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/Props.cpp +375 -0
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/Props.h +5174 -0
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/RCTComponentViewHelpers.h +436 -0
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/ShadowNodes.cpp +17 -0
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/ShadowNodes.h +23 -0
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/States.cpp +16 -0
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/States.h +20 -0
- package/ios/input/ENRMAutoLinkDetector.h +32 -0
- package/ios/input/ENRMAutoLinkDetector.mm +211 -0
- package/ios/input/ENRMDetectorPipeline.h +28 -0
- package/ios/input/ENRMDetectorPipeline.mm +53 -0
- package/ios/input/ENRMFormattingRange.h +19 -0
- package/ios/input/ENRMFormattingRange.mm +28 -0
- package/ios/input/ENRMFormattingStore.h +29 -0
- package/ios/input/ENRMFormattingStore.mm +278 -0
- package/ios/input/ENRMInputFormatter.h +84 -0
- package/ios/input/ENRMInputFormatter.mm +222 -0
- package/ios/input/ENRMInputLayoutManager.h +11 -0
- package/ios/input/ENRMInputLayoutManager.mm +5 -0
- package/ios/input/ENRMInputLinkPrompt.h +9 -0
- package/ios/input/ENRMInputLinkPrompt.mm +71 -0
- package/ios/input/ENRMInputMentionCandidate.h +21 -0
- package/ios/input/ENRMInputMentionCandidate.mm +18 -0
- package/ios/input/ENRMInputParser.h +27 -0
- package/ios/input/ENRMInputParser.mm +556 -0
- package/ios/input/ENRMInputRemend.h +9 -0
- package/ios/input/ENRMInputRemend.mm +136 -0
- package/ios/input/ENRMInputStyledRange.h +29 -0
- package/ios/input/ENRMInputStyledRange.mm +4 -0
- package/ios/input/ENRMInputTextView.h +13 -0
- package/ios/input/ENRMInputTextView.mm +175 -0
- package/ios/input/ENRMLinkRegexConfig.h +26 -0
- package/ios/input/ENRMLinkRegexConfig.mm +60 -0
- package/ios/input/ENRMMarkdownSerializer.h +19 -0
- package/ios/input/ENRMMarkdownSerializer.mm +283 -0
- package/ios/input/ENRMTextDetector.h +30 -0
- package/ios/input/ENRMWordsUtils.h +28 -0
- package/ios/input/ENRMWordsUtils.mm +88 -0
- package/ios/input/EnrichedMarkdownTextInput+ContextMenu.mm +157 -0
- package/ios/input/EnrichedMarkdownTextInput+Internal.h +30 -0
- package/ios/input/EnrichedMarkdownTextInput.h +20 -0
- package/ios/input/EnrichedMarkdownTextInput.mm +2008 -0
- package/ios/input/InputStylePropsUtils.h +261 -0
- package/ios/input/internals/EnrichedMarkdownTextInputComponentDescriptor.h +19 -0
- package/ios/input/internals/EnrichedMarkdownTextInputShadowNode.h +40 -0
- package/ios/input/internals/EnrichedMarkdownTextInputShadowNode.mm +83 -0
- package/ios/input/internals/EnrichedMarkdownTextInputState.h +23 -0
- package/ios/input/styles/ENRMBoldStyleHandler.h +10 -0
- package/ios/input/styles/ENRMBoldStyleHandler.mm +29 -0
- package/ios/input/styles/ENRMItalicStyleHandler.h +10 -0
- package/ios/input/styles/ENRMItalicStyleHandler.mm +29 -0
- package/ios/input/styles/ENRMLinkStyleHandler.h +10 -0
- package/ios/input/styles/ENRMLinkStyleHandler.mm +52 -0
- package/ios/input/styles/ENRMSpoilerStyleHandler.h +10 -0
- package/ios/input/styles/ENRMSpoilerStyleHandler.mm +33 -0
- package/ios/input/styles/ENRMStrikethroughStyleHandler.h +10 -0
- package/ios/input/styles/ENRMStrikethroughStyleHandler.mm +28 -0
- package/ios/input/styles/ENRMStyleHandler.h +26 -0
- package/ios/input/styles/ENRMStyleMergingConfig.h +26 -0
- package/ios/input/styles/ENRMStyleMergingConfig.mm +21 -0
- package/ios/input/styles/ENRMUnderlineStyleHandler.h +10 -0
- package/ios/input/styles/ENRMUnderlineStyleHandler.mm +28 -0
- package/ios/internals/EnrichedMarkdownComponentDescriptor.h +18 -0
- package/ios/internals/EnrichedMarkdownShadowNode.h +43 -0
- package/ios/internals/EnrichedMarkdownShadowNode.mm +73 -0
- package/ios/internals/EnrichedMarkdownState.h +23 -0
- package/ios/internals/EnrichedMarkdownTextComponentDescriptor.h +19 -0
- package/ios/internals/EnrichedMarkdownTextShadowNode.h +45 -0
- package/ios/internals/EnrichedMarkdownTextShadowNode.mm +74 -0
- package/ios/internals/EnrichedMarkdownTextState.h +24 -0
- package/ios/internals/MeasurementCache.h +223 -0
- package/ios/internals/ShadowMeasurementUtils.h +135 -0
- package/ios/math/ENRMRaTeXBridge.swift +58 -0
- package/ios/parser/ENRMMarkdownParser.h +21 -0
- package/ios/parser/ENRMMarkdownParser.mm +50 -0
- package/ios/parser/MarkdownASTNode.h +47 -0
- package/ios/parser/MarkdownASTNode.m +32 -0
- package/ios/parser/MarkdownParserBridge.mm +161 -0
- package/ios/renderer/AttributedRenderer.h +11 -0
- package/ios/renderer/AttributedRenderer.m +153 -0
- package/ios/renderer/BaseRenderer.h +18 -0
- package/ios/renderer/BaseRenderer.m +16 -0
- package/ios/renderer/BaselineShiftTextAttributes.h +6 -0
- package/ios/renderer/BaselineShiftTextAttributes.m +22 -0
- package/ios/renderer/BlockquoteRenderer.h +6 -0
- package/ios/renderer/BlockquoteRenderer.m +148 -0
- package/ios/renderer/CodeBlockRenderer.h +9 -0
- package/ios/renderer/CodeBlockRenderer.m +90 -0
- package/ios/renderer/CodeRenderer.h +9 -0
- package/ios/renderer/CodeRenderer.m +64 -0
- package/ios/renderer/ENRMImageRenderer.h +9 -0
- package/ios/renderer/ENRMImageRenderer.m +65 -0
- package/ios/renderer/ENRMMathInlineRenderer.h +9 -0
- package/ios/renderer/ENRMMathInlineRenderer.m +56 -0
- package/ios/renderer/ENRMSpoilerRenderer.h +5 -0
- package/ios/renderer/ENRMSpoilerRenderer.m +32 -0
- package/ios/renderer/EmphasisRenderer.h +5 -0
- package/ios/renderer/EmphasisRenderer.m +98 -0
- package/ios/renderer/HeadingRenderer.h +6 -0
- package/ios/renderer/HeadingRenderer.m +94 -0
- package/ios/renderer/HighlightRenderer.h +7 -0
- package/ios/renderer/HighlightRenderer.m +31 -0
- package/ios/renderer/LinkRenderer.h +6 -0
- package/ios/renderer/LinkRenderer.m +82 -0
- package/ios/renderer/ListItemRenderer.h +12 -0
- package/ios/renderer/ListItemRenderer.m +175 -0
- package/ios/renderer/ListRenderer.h +13 -0
- package/ios/renderer/ListRenderer.m +70 -0
- package/ios/renderer/NodeRenderer.h +8 -0
- package/ios/renderer/ParagraphRenderer.h +6 -0
- package/ios/renderer/ParagraphRenderer.m +70 -0
- package/ios/renderer/RenderContext.h +118 -0
- package/ios/renderer/RenderContext.m +337 -0
- package/ios/renderer/RendererFactory.h +12 -0
- package/ios/renderer/RendererFactory.m +147 -0
- package/ios/renderer/StrikethroughRenderer.h +5 -0
- package/ios/renderer/StrikethroughRenderer.m +28 -0
- package/ios/renderer/StrongRenderer.h +5 -0
- package/ios/renderer/StrongRenderer.m +86 -0
- package/ios/renderer/SubscriptRenderer.h +5 -0
- package/ios/renderer/SubscriptRenderer.m +22 -0
- package/ios/renderer/SuperscriptRenderer.h +5 -0
- package/ios/renderer/SuperscriptRenderer.m +22 -0
- package/ios/renderer/TextRenderer.h +6 -0
- package/ios/renderer/TextRenderer.m +16 -0
- package/ios/renderer/ThematicBreakRenderer.h +4 -0
- package/ios/renderer/ThematicBreakRenderer.m +40 -0
- package/ios/renderer/UnderlineRenderer.h +4 -0
- package/ios/renderer/UnderlineRenderer.m +27 -0
- package/ios/styles/ENRMFontSlot.h +12 -0
- package/ios/styles/ENRMFontSlot.m +24 -0
- package/ios/styles/StyleConfig.h +407 -0
- package/ios/styles/StyleConfig.mm +2515 -0
- package/ios/utils/AccessibilityInfo.h +35 -0
- package/ios/utils/AccessibilityInfo.m +24 -0
- package/ios/utils/BlockquoteBorder.h +20 -0
- package/ios/utils/BlockquoteBorder.m +97 -0
- package/ios/utils/CodeBackground.h +19 -0
- package/ios/utils/CodeBackground.m +197 -0
- package/ios/utils/CodeBlockBackground.h +17 -0
- package/ios/utils/CodeBlockBackground.m +89 -0
- package/ios/utils/ContextMenuUtils.h +76 -0
- package/ios/utils/ContextMenuUtils.mm +73 -0
- package/ios/utils/ENRMAsyncRenderCoordinator.h +24 -0
- package/ios/utils/ENRMAsyncRenderCoordinator.m +37 -0
- package/ios/utils/ENRMFeatureFlags.h +12 -0
- package/ios/utils/ENRMImageDownloader.h +16 -0
- package/ios/utils/ENRMImageDownloader.m +108 -0
- package/ios/utils/ENRMMenuAction.h +27 -0
- package/ios/utils/ENRMMenuAction.m +33 -0
- package/ios/utils/ENRMParticleOverlayView.h +12 -0
- package/ios/utils/ENRMParticleOverlayView.m +159 -0
- package/ios/utils/ENRMSolidOverlayView.h +12 -0
- package/ios/utils/ENRMSolidOverlayView.m +25 -0
- package/ios/utils/ENRMSpoilerCapable.h +15 -0
- package/ios/utils/ENRMSpoilerOverlayManager.h +21 -0
- package/ios/utils/ENRMSpoilerOverlayManager.m +181 -0
- package/ios/utils/ENRMSpoilerOverlayView.h +49 -0
- package/ios/utils/ENRMSpoilerOverlayView.m +144 -0
- package/ios/utils/ENRMSpoilerTapUtils.h +25 -0
- package/ios/utils/ENRMSpoilerTapUtils.m +68 -0
- package/ios/utils/ENRMTailFadeInAnimator.h +16 -0
- package/ios/utils/ENRMTailFadeInAnimator.m +161 -0
- package/ios/utils/ENRMTextHitTest.h +23 -0
- package/ios/utils/ENRMTextHitTest.m +20 -0
- package/ios/utils/ENRMTextInteractionUtils.h +20 -0
- package/ios/utils/ENRMTextInteractionUtils.m +15 -0
- package/ios/utils/ENRMTextRenderer.h +30 -0
- package/ios/utils/ENRMTextRenderer.m +38 -0
- package/ios/utils/ENRMTextViewSetup.h +78 -0
- package/ios/utils/ENRMUIKit.h +418 -0
- package/ios/utils/EditMenuUtils+macOS.m +60 -0
- package/ios/utils/EditMenuUtils.h +35 -0
- package/ios/utils/EditMenuUtils.m +119 -0
- package/ios/utils/FontScaleObserver.h +10 -0
- package/ios/utils/FontScaleObserver.m +55 -0
- package/ios/utils/FontUtils.h +30 -0
- package/ios/utils/FontUtils.m +47 -0
- package/ios/utils/HTMLGenerator.h +25 -0
- package/ios/utils/HTMLGenerator.m +1019 -0
- package/ios/utils/HeightUpdateUtils.h +25 -0
- package/ios/utils/LastElementUtils.h +53 -0
- package/ios/utils/LinkTapUtils.h +24 -0
- package/ios/utils/LinkTapUtils.m +32 -0
- package/ios/utils/ListMarkerDrawer.h +15 -0
- package/ios/utils/ListMarkerDrawer.m +212 -0
- package/ios/utils/MarkdownASTSerializer.h +24 -0
- package/ios/utils/MarkdownASTSerializer.m +114 -0
- package/ios/utils/MarkdownAccessibilityElementBuilder.h +41 -0
- package/ios/utils/MarkdownAccessibilityElementBuilder.m +450 -0
- package/ios/utils/MarkdownExtractor.h +17 -0
- package/ios/utils/MarkdownExtractor.m +355 -0
- package/ios/utils/ParagraphStyleUtils.h +53 -0
- package/ios/utils/ParagraphStyleUtils.m +349 -0
- package/ios/utils/PasteboardUtils.h +48 -0
- package/ios/utils/PasteboardUtils.m +162 -0
- package/ios/utils/RTFExportUtils.h +24 -0
- package/ios/utils/RTFExportUtils.m +297 -0
- package/ios/utils/RenderedMarkdownSegment.h +49 -0
- package/ios/utils/RenderedMarkdownSegment.m +130 -0
- package/ios/utils/RuntimeKeys.h +38 -0
- package/ios/utils/RuntimeKeys.m +11 -0
- package/ios/utils/SegmentReconciler.h +32 -0
- package/ios/utils/SegmentReconciler.m +118 -0
- package/ios/utils/SegmentRenderer.h +24 -0
- package/ios/utils/SegmentRenderer.m +88 -0
- package/ios/utils/SegmentViewRegistry.h +36 -0
- package/ios/utils/SegmentViewRegistry.m +67 -0
- package/ios/utils/SelectionColorUtils.h +14 -0
- package/ios/utils/StreamingMarkdownFilter.h +22 -0
- package/ios/utils/StreamingMarkdownFilter.m +165 -0
- package/ios/utils/StylePropsUtils.h +1146 -0
- package/ios/utils/TaskListTapUtils.h +43 -0
- package/ios/utils/TaskListTapUtils.m +227 -0
- package/ios/utils/TextViewLayoutManager.h +14 -0
- package/ios/utils/TextViewLayoutManager.mm +113 -0
- package/ios/views/ENRMContextMenuTextView+macOS.h +17 -0
- package/ios/views/ENRMContextMenuTextView+macOS.m +97 -0
- package/ios/views/ENRMMathContainerView.h +20 -0
- package/ios/views/ENRMMathContainerView.m +227 -0
- package/ios/views/ENRMTableGridView.h +36 -0
- package/ios/views/ENRMTableGridView.m +98 -0
- package/ios/views/EnrichedMarkdownInternalText.h +42 -0
- package/ios/views/EnrichedMarkdownInternalText.m +161 -0
- package/ios/views/TableContainerView.h +39 -0
- package/ios/views/TableContainerView.m +686 -0
- package/lib/module/EnrichedMarkdownNativeComponent.ts +429 -0
- package/lib/module/EnrichedMarkdownTextInput.js +310 -0
- package/lib/module/EnrichedMarkdownTextInput.js.map +1 -0
- package/lib/module/EnrichedMarkdownTextInputNativeComponent.ts +364 -0
- package/lib/module/EnrichedMarkdownTextNativeComponent.ts +428 -0
- package/lib/module/index.js +5 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/index.web.js +4 -0
- package/lib/module/index.web.js.map +1 -0
- package/lib/module/linkVariantUtils.js +28 -0
- package/lib/module/linkVariantUtils.js.map +1 -0
- package/lib/module/native/EnrichedMarkdownText.js +158 -0
- package/lib/module/native/EnrichedMarkdownText.js.map +1 -0
- package/lib/module/normalizeMarkdownStyle.js +337 -0
- package/lib/module/normalizeMarkdownStyle.js.map +1 -0
- package/lib/module/normalizeMarkdownStyle.web.js +264 -0
- package/lib/module/normalizeMarkdownStyle.web.js.map +1 -0
- package/lib/module/normalizeMarkdownTextInputStyle.js +146 -0
- package/lib/module/normalizeMarkdownTextInputStyle.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/plugin/withAndroidMath.js +20 -0
- package/lib/module/plugin/withAndroidMath.js.map +1 -0
- package/lib/module/plugin/withIosMath.js +23 -0
- package/lib/module/plugin/withIosMath.js.map +1 -0
- package/lib/module/plugin/withReactNativeEnrichedMarkdown.js +16 -0
- package/lib/module/plugin/withReactNativeEnrichedMarkdown.js.map +1 -0
- package/lib/module/styleUtils.js +64 -0
- package/lib/module/styleUtils.js.map +1 -0
- package/lib/module/types/MarkdownStyle.js +2 -0
- package/lib/module/types/MarkdownStyle.js.map +1 -0
- package/lib/module/types/MarkdownStyleInternal.js +2 -0
- package/lib/module/types/MarkdownStyleInternal.js.map +1 -0
- package/lib/module/types/MarkdownTextProps.js +4 -0
- package/lib/module/types/MarkdownTextProps.js.map +1 -0
- package/lib/module/types/MarkdownTextProps.web.js +4 -0
- package/lib/module/types/MarkdownTextProps.web.js.map +1 -0
- package/lib/module/types/events.js +2 -0
- package/lib/module/types/events.js.map +1 -0
- package/lib/module/utils/regexParser.js +43 -0
- package/lib/module/utils/regexParser.js.map +1 -0
- package/lib/module/web/EnrichedMarkdownText.js +120 -0
- package/lib/module/web/EnrichedMarkdownText.js.map +1 -0
- package/lib/module/web/globalStyles.js +10 -0
- package/lib/module/web/globalStyles.js.map +1 -0
- package/lib/module/web/injectStyle.js +20 -0
- package/lib/module/web/injectStyle.js.map +1 -0
- package/lib/module/web/katex.js +22 -0
- package/lib/module/web/katex.js.map +1 -0
- package/lib/module/web/parseMarkdown.js +35 -0
- package/lib/module/web/parseMarkdown.js.map +1 -0
- package/lib/module/web/renderers/BlockRenderers.js +115 -0
- package/lib/module/web/renderers/BlockRenderers.js.map +1 -0
- package/lib/module/web/renderers/InlineRenderers.js +160 -0
- package/lib/module/web/renderers/InlineRenderers.js.map +1 -0
- package/lib/module/web/renderers/KaTeXRenderer.js +43 -0
- package/lib/module/web/renderers/KaTeXRenderer.js.map +1 -0
- package/lib/module/web/renderers/ListRenderers.js +92 -0
- package/lib/module/web/renderers/ListRenderers.js.map +1 -0
- package/lib/module/web/renderers/TableRenderers.js +77 -0
- package/lib/module/web/renderers/TableRenderers.js.map +1 -0
- package/lib/module/web/renderers/index.js +49 -0
- package/lib/module/web/renderers/index.js.map +1 -0
- package/lib/module/web/styles.js +454 -0
- package/lib/module/web/styles.js.map +1 -0
- package/lib/module/web/types.js +4 -0
- package/lib/module/web/types.js.map +1 -0
- package/lib/module/web/utils.js +56 -0
- package/lib/module/web/utils.js.map +1 -0
- package/lib/module/web/wasm/md4c.d.js +4 -0
- package/lib/module/web/wasm/md4c.d.js.map +1 -0
- package/lib/module/web/wasm/md4c.js +0 -0
- package/lib/module/web/wasm/md4c.js.map +1 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/EnrichedMarkdownNativeComponent.d.ts +384 -0
- package/lib/typescript/src/EnrichedMarkdownNativeComponent.d.ts.map +1 -0
- package/lib/typescript/src/EnrichedMarkdownTextInput.d.ts +173 -0
- package/lib/typescript/src/EnrichedMarkdownTextInput.d.ts.map +1 -0
- package/lib/typescript/src/EnrichedMarkdownTextInputNativeComponent.d.ts +285 -0
- package/lib/typescript/src/EnrichedMarkdownTextInputNativeComponent.d.ts.map +1 -0
- package/lib/typescript/src/EnrichedMarkdownTextNativeComponent.d.ts +384 -0
- package/lib/typescript/src/EnrichedMarkdownTextNativeComponent.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +6 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/lib/typescript/src/index.web.d.ts +5 -0
- package/lib/typescript/src/index.web.d.ts.map +1 -0
- package/lib/typescript/src/linkVariantUtils.d.ts +5 -0
- package/lib/typescript/src/linkVariantUtils.d.ts.map +1 -0
- package/lib/typescript/src/native/EnrichedMarkdownText.d.ts +9 -0
- package/lib/typescript/src/native/EnrichedMarkdownText.d.ts.map +1 -0
- package/lib/typescript/src/normalizeMarkdownStyle.d.ts +4 -0
- package/lib/typescript/src/normalizeMarkdownStyle.d.ts.map +1 -0
- package/lib/typescript/src/normalizeMarkdownStyle.web.d.ts +4 -0
- package/lib/typescript/src/normalizeMarkdownStyle.web.d.ts.map +1 -0
- package/lib/typescript/src/normalizeMarkdownTextInputStyle.d.ts +48 -0
- package/lib/typescript/src/normalizeMarkdownTextInputStyle.d.ts.map +1 -0
- package/lib/typescript/src/plugin/withAndroidMath.d.ts +5 -0
- package/lib/typescript/src/plugin/withAndroidMath.d.ts.map +1 -0
- package/lib/typescript/src/plugin/withIosMath.d.ts +5 -0
- package/lib/typescript/src/plugin/withIosMath.d.ts.map +1 -0
- package/lib/typescript/src/plugin/withReactNativeEnrichedMarkdown.d.ts +6 -0
- package/lib/typescript/src/plugin/withReactNativeEnrichedMarkdown.d.ts.map +1 -0
- package/lib/typescript/src/styleUtils.d.ts +6 -0
- package/lib/typescript/src/styleUtils.d.ts.map +1 -0
- package/lib/typescript/src/types/MarkdownStyle.d.ts +300 -0
- package/lib/typescript/src/types/MarkdownStyle.d.ts.map +1 -0
- package/lib/typescript/src/types/MarkdownStyleInternal.d.ts +178 -0
- package/lib/typescript/src/types/MarkdownStyleInternal.d.ts.map +1 -0
- package/lib/typescript/src/types/MarkdownTextProps.d.ts +249 -0
- package/lib/typescript/src/types/MarkdownTextProps.d.ts.map +1 -0
- package/lib/typescript/src/types/MarkdownTextProps.web.d.ts +83 -0
- package/lib/typescript/src/types/MarkdownTextProps.web.d.ts.map +1 -0
- package/lib/typescript/src/types/events.d.ts +29 -0
- package/lib/typescript/src/types/events.d.ts.map +1 -0
- package/lib/typescript/src/utils/regexParser.d.ts +3 -0
- package/lib/typescript/src/utils/regexParser.d.ts.map +1 -0
- package/lib/typescript/src/web/EnrichedMarkdownText.d.ts +4 -0
- package/lib/typescript/src/web/EnrichedMarkdownText.d.ts.map +1 -0
- package/lib/typescript/src/web/globalStyles.d.ts +3 -0
- package/lib/typescript/src/web/globalStyles.d.ts.map +1 -0
- package/lib/typescript/src/web/injectStyle.d.ts +9 -0
- package/lib/typescript/src/web/injectStyle.d.ts.map +1 -0
- package/lib/typescript/src/web/katex.d.ts +11 -0
- package/lib/typescript/src/web/katex.d.ts.map +1 -0
- package/lib/typescript/src/web/parseMarkdown.d.ts +4 -0
- package/lib/typescript/src/web/parseMarkdown.d.ts.map +1 -0
- package/lib/typescript/src/web/renderers/BlockRenderers.d.ts +3 -0
- package/lib/typescript/src/web/renderers/BlockRenderers.d.ts.map +1 -0
- package/lib/typescript/src/web/renderers/InlineRenderers.d.ts +3 -0
- package/lib/typescript/src/web/renderers/InlineRenderers.d.ts.map +1 -0
- package/lib/typescript/src/web/renderers/KaTeXRenderer.d.ts +11 -0
- package/lib/typescript/src/web/renderers/KaTeXRenderer.d.ts.map +1 -0
- package/lib/typescript/src/web/renderers/ListRenderers.d.ts +3 -0
- package/lib/typescript/src/web/renderers/ListRenderers.d.ts.map +1 -0
- package/lib/typescript/src/web/renderers/TableRenderers.d.ts +3 -0
- package/lib/typescript/src/web/renderers/TableRenderers.d.ts.map +1 -0
- package/lib/typescript/src/web/renderers/index.d.ts +14 -0
- package/lib/typescript/src/web/renderers/index.d.ts.map +1 -0
- package/lib/typescript/src/web/styles.d.ts +49 -0
- package/lib/typescript/src/web/styles.d.ts.map +1 -0
- package/lib/typescript/src/web/types.d.ts +51 -0
- package/lib/typescript/src/web/types.d.ts.map +1 -0
- package/lib/typescript/src/web/utils.d.ts +21 -0
- package/lib/typescript/src/web/utils.d.ts.map +1 -0
- package/package.json +125 -0
- package/react-native.config.js +17 -0
- package/src/EnrichedMarkdownNativeComponent.ts +429 -0
- package/src/EnrichedMarkdownTextInput.tsx +547 -0
- package/src/EnrichedMarkdownTextInputNativeComponent.ts +364 -0
- package/src/EnrichedMarkdownTextNativeComponent.ts +428 -0
- package/src/index.tsx +28 -0
- package/src/index.web.tsx +8 -0
- package/src/linkVariantUtils.ts +42 -0
- package/src/native/EnrichedMarkdownText.tsx +187 -0
- package/src/normalizeMarkdownStyle.ts +310 -0
- package/src/normalizeMarkdownStyle.web.ts +281 -0
- package/src/normalizeMarkdownTextInputStyle.ts +242 -0
- package/src/plugin/withAndroidMath.ts +24 -0
- package/src/plugin/withIosMath.ts +35 -0
- package/src/plugin/withReactNativeEnrichedMarkdown.ts +17 -0
- package/src/styleUtils.ts +98 -0
- package/src/types/MarkdownStyle.ts +326 -0
- package/src/types/MarkdownStyleInternal.ts +208 -0
- package/src/types/MarkdownTextProps.ts +253 -0
- package/src/types/MarkdownTextProps.web.ts +90 -0
- package/src/types/events.ts +32 -0
- package/src/utils/regexParser.ts +54 -0
- package/src/web/EnrichedMarkdownText.tsx +154 -0
- package/src/web/globalStyles.ts +15 -0
- package/src/web/injectStyle.ts +17 -0
- package/src/web/katex.ts +31 -0
- package/src/web/parseMarkdown.ts +78 -0
- package/src/web/renderers/BlockRenderers.tsx +90 -0
- package/src/web/renderers/InlineRenderers.tsx +121 -0
- package/src/web/renderers/KaTeXRenderer.tsx +49 -0
- package/src/web/renderers/ListRenderers.tsx +110 -0
- package/src/web/renderers/TableRenderers.tsx +61 -0
- package/src/web/renderers/index.tsx +75 -0
- package/src/web/styles.ts +549 -0
- package/src/web/types.ts +92 -0
- package/src/web/utils.ts +52 -0
- package/src/web/wasm/md4c.d.ts +21 -0
- package/src/web/wasm/md4c.js +0 -0
|
@@ -0,0 +1,2008 @@
|
|
|
1
|
+
#import "EnrichedMarkdownTextInput.h"
|
|
2
|
+
#import "ContextMenuUtils.h"
|
|
3
|
+
#import "ENRMAutoLinkDetector.h"
|
|
4
|
+
#import "ENRMDetectorPipeline.h"
|
|
5
|
+
#import "ENRMFeatureFlags.h"
|
|
6
|
+
#import "ENRMFormattingRange.h"
|
|
7
|
+
#import "ENRMFormattingStore.h"
|
|
8
|
+
#import "ENRMInputFormatter.h"
|
|
9
|
+
#import "ENRMInputLayoutManager.h"
|
|
10
|
+
#import "ENRMInputLinkPrompt.h"
|
|
11
|
+
#import "ENRMInputMentionCandidate.h"
|
|
12
|
+
#import "ENRMInputParser.h"
|
|
13
|
+
#import "ENRMInputTextView.h"
|
|
14
|
+
#import "ENRMLinkRegexConfig.h"
|
|
15
|
+
#import "ENRMMarkdownSerializer.h"
|
|
16
|
+
#if ENRICHED_MARKDOWN_MATH
|
|
17
|
+
#import "ENRMMathInlineAttachment.h"
|
|
18
|
+
#endif
|
|
19
|
+
#import "ENRMStyleHandler.h"
|
|
20
|
+
#import "ENRMStyleMergingConfig.h"
|
|
21
|
+
#import "ENRMUIKit.h"
|
|
22
|
+
#import "ENRMWordsUtils.h"
|
|
23
|
+
#import "InputStylePropsUtils.h"
|
|
24
|
+
#import "ParagraphStyleUtils.h"
|
|
25
|
+
#import "SelectionColorUtils.h"
|
|
26
|
+
#import <React/RCTI18nUtil.h>
|
|
27
|
+
#if TARGET_OS_OSX
|
|
28
|
+
#import <React/RCTBackedTextInputDelegate.h>
|
|
29
|
+
#endif
|
|
30
|
+
|
|
31
|
+
#import <ReactNativeEnrichedMarkdown/EnrichedMarkdownTextInputComponentDescriptor.h>
|
|
32
|
+
#import <ReactNativeEnrichedMarkdown/EventEmitters.h>
|
|
33
|
+
#import <ReactNativeEnrichedMarkdown/Props.h>
|
|
34
|
+
#import <ReactNativeEnrichedMarkdown/RCTComponentViewHelpers.h>
|
|
35
|
+
|
|
36
|
+
#import "EnrichedMarkdownTextInputShadowNode.h"
|
|
37
|
+
#import "HeightUpdateUtils.h"
|
|
38
|
+
#import "RCTFabricComponentsPlugins.h"
|
|
39
|
+
#import <React/RCTConversions.h>
|
|
40
|
+
|
|
41
|
+
using namespace facebook::react;
|
|
42
|
+
|
|
43
|
+
#if !TARGET_OS_OSX
|
|
44
|
+
@interface EnrichedMarkdownTextInput () <RCTEnrichedMarkdownTextInputViewProtocol, UITextViewDelegate>
|
|
45
|
+
#else
|
|
46
|
+
@interface EnrichedMarkdownTextInput () <RCTEnrichedMarkdownTextInputViewProtocol, RCTBackedTextInputDelegate>
|
|
47
|
+
#endif
|
|
48
|
+
- (void)setupTextView;
|
|
49
|
+
- (void)applyFormatting;
|
|
50
|
+
- (void)toggleInlineStyle:(ENRMInputStyleType)styleType;
|
|
51
|
+
- (void)resetBaseTypingAttributes;
|
|
52
|
+
@end
|
|
53
|
+
|
|
54
|
+
@implementation EnrichedMarkdownTextInput {
|
|
55
|
+
ENRMPlatformTextView *_textView;
|
|
56
|
+
ENRMInputLayoutManager *_layoutManager;
|
|
57
|
+
EnrichedMarkdownTextInputShadowNode::ConcreteState::Shared _state;
|
|
58
|
+
int _heightUpdateCounter;
|
|
59
|
+
ENRMInputFormatter *_formatter;
|
|
60
|
+
ENRMInputFormatterStyle *_formatterStyle;
|
|
61
|
+
ENRMFormattingStore *_formattingStore;
|
|
62
|
+
NSMutableSet<NSNumber *> *_pendingStyles;
|
|
63
|
+
NSMutableSet<NSNumber *> *_pendingStyleRemovals;
|
|
64
|
+
BOOL _isApplyingFormatting;
|
|
65
|
+
BOOL _isTextChanging;
|
|
66
|
+
BOOL _emitMarkdown;
|
|
67
|
+
|
|
68
|
+
ENRMPlaceholderLabel *_placeholderLabel;
|
|
69
|
+
|
|
70
|
+
NSUInteger _lastTextLength;
|
|
71
|
+
NSRange _lastSelectedRange;
|
|
72
|
+
NSRange _preEditSelectedRange;
|
|
73
|
+
|
|
74
|
+
struct {
|
|
75
|
+
BOOL bold, italic, underline, strikethrough, spoiler, link, initialized;
|
|
76
|
+
} _prevState;
|
|
77
|
+
|
|
78
|
+
std::optional<CGRect> _prevCaretRect;
|
|
79
|
+
|
|
80
|
+
#if TARGET_OS_OSX
|
|
81
|
+
NSScrollView *_scrollView;
|
|
82
|
+
#endif
|
|
83
|
+
|
|
84
|
+
NSArray<NSString *> *_contextMenuItemTexts;
|
|
85
|
+
NSArray<NSString *> *_contextMenuItemIcons;
|
|
86
|
+
NSArray<NSString *> *_mentionIndicators;
|
|
87
|
+
NSString *_activeMentionIndicator;
|
|
88
|
+
NSRange _activeMentionRange;
|
|
89
|
+
NSString *_activeMentionText;
|
|
90
|
+
|
|
91
|
+
ENRMAutoLinkDetector *_autoLinkDetector;
|
|
92
|
+
ENRMDetectorPipeline *_detectorPipeline;
|
|
93
|
+
|
|
94
|
+
ENRMWritingDirectionMode _writingDirectionMode;
|
|
95
|
+
NSWritingDirection _resolvedLayoutDirection;
|
|
96
|
+
|
|
97
|
+
/// One-shot guard: when YES, the next textViewDidChangeSelection skips
|
|
98
|
+
/// clearing math chip selections. Set by handleTapForMathChip right before
|
|
99
|
+
/// it moves the caret to the chip, so the caret update doesn't immediately
|
|
100
|
+
/// wipe the chip we just selected.
|
|
101
|
+
BOOL _suppressMathChipClearOnce;
|
|
102
|
+
/// Character index of the currently selected math chip, or NSNotFound.
|
|
103
|
+
NSUInteger _activeMathChipIndex;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
#pragma mark - Fabric lifecycle
|
|
107
|
+
|
|
108
|
+
+ (ComponentDescriptorProvider)componentDescriptorProvider
|
|
109
|
+
{
|
|
110
|
+
return concreteComponentDescriptorProvider<EnrichedMarkdownTextInputComponentDescriptor>();
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
+ (BOOL)shouldBeRecycled
|
|
114
|
+
{
|
|
115
|
+
return NO;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
- (instancetype)initWithFrame:(CGRect)frame
|
|
119
|
+
{
|
|
120
|
+
if (self = [super initWithFrame:frame]) {
|
|
121
|
+
static const auto defaultProps = std::make_shared<const EnrichedMarkdownTextInputProps>();
|
|
122
|
+
_props = defaultProps;
|
|
123
|
+
|
|
124
|
+
self.backgroundColor = [RCTUIColor clearColor];
|
|
125
|
+
_blockEmitting = NO;
|
|
126
|
+
_heightUpdateCounter = 0;
|
|
127
|
+
_formatter = [[ENRMInputFormatter alloc] init];
|
|
128
|
+
_formatterStyle = [[ENRMInputFormatterStyle alloc] init];
|
|
129
|
+
_formattingStore = [[ENRMFormattingStore alloc] init];
|
|
130
|
+
_pendingStyles = [NSMutableSet set];
|
|
131
|
+
_pendingStyleRemovals = [NSMutableSet set];
|
|
132
|
+
_lastTextLength = 0;
|
|
133
|
+
_lastSelectedRange = NSMakeRange(0, 0);
|
|
134
|
+
_mentionIndicators = @[];
|
|
135
|
+
_activeMentionRange = NSMakeRange(NSNotFound, 0);
|
|
136
|
+
_activeMentionText = @"";
|
|
137
|
+
|
|
138
|
+
_writingDirectionMode = ENRMWritingDirectionModeFirstStrong;
|
|
139
|
+
_resolvedLayoutDirection =
|
|
140
|
+
[[RCTI18nUtil sharedInstance] isRTL] ? NSWritingDirectionRightToLeft : NSWritingDirectionLeftToRight;
|
|
141
|
+
|
|
142
|
+
_suppressMathChipClearOnce = NO;
|
|
143
|
+
_activeMathChipIndex = NSNotFound;
|
|
144
|
+
|
|
145
|
+
[self setupTextView];
|
|
146
|
+
|
|
147
|
+
[self setupDetectorPipeline];
|
|
148
|
+
}
|
|
149
|
+
return self;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
- (void)setupDetectorPipeline
|
|
153
|
+
{
|
|
154
|
+
_autoLinkDetector = [[ENRMAutoLinkDetector alloc] initWithTextStorage:_textView.textStorage
|
|
155
|
+
formattingStore:_formattingStore
|
|
156
|
+
style:_formatterStyle];
|
|
157
|
+
|
|
158
|
+
__weak EnrichedMarkdownTextInput *weakSelf = self;
|
|
159
|
+
_autoLinkDetector.onLinkDetected = ^(NSString *text, NSString *url, NSRange range) {
|
|
160
|
+
[weakSelf emitOnLinkDetectedWithText:text url:url range:range];
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
_detectorPipeline = [[ENRMDetectorPipeline alloc] init];
|
|
164
|
+
[_detectorPipeline addDetector:_autoLinkDetector];
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
- (void)setupTextView
|
|
168
|
+
{
|
|
169
|
+
#if !TARGET_OS_OSX
|
|
170
|
+
_layoutManager = [[ENRMInputLayoutManager alloc] init];
|
|
171
|
+
NSTextContainer *textContainer = [[NSTextContainer alloc] initWithSize:CGSizeMake(0, CGFLOAT_MAX)];
|
|
172
|
+
textContainer.widthTracksTextView = YES;
|
|
173
|
+
[_layoutManager addTextContainer:textContainer];
|
|
174
|
+
|
|
175
|
+
NSTextStorage *textStorage = [[NSTextStorage alloc] init];
|
|
176
|
+
[textStorage addLayoutManager:_layoutManager];
|
|
177
|
+
|
|
178
|
+
ENRMInputTextView *inputTextView = [[ENRMInputTextView alloc] initWithFrame:CGRectZero textContainer:textContainer];
|
|
179
|
+
#else
|
|
180
|
+
ENRMInputTextView *inputTextView = [[ENRMInputTextView alloc] initWithFrame:CGRectZero];
|
|
181
|
+
#endif
|
|
182
|
+
inputTextView.markdownTextInput = self;
|
|
183
|
+
_textView = inputTextView;
|
|
184
|
+
ENRMConfigureMarkdownTextInputTextView(_textView);
|
|
185
|
+
#if !TARGET_OS_OSX
|
|
186
|
+
_textView.adjustsFontForContentSizeCategory = YES;
|
|
187
|
+
_textView.delegate = self;
|
|
188
|
+
#else
|
|
189
|
+
_textView.textInputDelegate = self;
|
|
190
|
+
#endif
|
|
191
|
+
|
|
192
|
+
#if !TARGET_OS_OSX
|
|
193
|
+
self.contentView = _textView;
|
|
194
|
+
#else
|
|
195
|
+
_textView.selectable = YES;
|
|
196
|
+
|
|
197
|
+
_scrollView = [[NSScrollView alloc] initWithFrame:CGRectZero];
|
|
198
|
+
_scrollView.backgroundColor = [RCTUIColor clearColor];
|
|
199
|
+
_scrollView.drawsBackground = NO;
|
|
200
|
+
_scrollView.borderType = NSNoBorder;
|
|
201
|
+
_scrollView.hasHorizontalRuler = NO;
|
|
202
|
+
_scrollView.hasVerticalRuler = NO;
|
|
203
|
+
_scrollView.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
|
|
204
|
+
|
|
205
|
+
_textView.verticallyResizable = YES;
|
|
206
|
+
_textView.horizontallyResizable = YES;
|
|
207
|
+
_textView.textContainer.containerSize = NSMakeSize(CGFLOAT_MAX, CGFLOAT_MAX);
|
|
208
|
+
_textView.textContainer.widthTracksTextView = YES;
|
|
209
|
+
|
|
210
|
+
_scrollView.documentView = _textView;
|
|
211
|
+
self.contentView = _scrollView;
|
|
212
|
+
#endif
|
|
213
|
+
|
|
214
|
+
_placeholderLabel = ENRMCreatePlaceholderLabel(_textView, _formatterStyle.baseFont);
|
|
215
|
+
#if !TARGET_OS_OSX
|
|
216
|
+
_placeholderLabel.adjustsFontForContentSizeCategory = YES;
|
|
217
|
+
#endif
|
|
218
|
+
|
|
219
|
+
[self resetBaseTypingAttributes];
|
|
220
|
+
|
|
221
|
+
#if ENRICHED_MARKDOWN_MATH && !TARGET_OS_OSX
|
|
222
|
+
UITapGestureRecognizer *mathTap = [[UITapGestureRecognizer alloc] initWithTarget:self
|
|
223
|
+
action:@selector(handleTapForMathChip:)];
|
|
224
|
+
mathTap.cancelsTouchesInView = NO;
|
|
225
|
+
[_textView addGestureRecognizer:mathTap];
|
|
226
|
+
#endif
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
#if ENRICHED_MARKDOWN_MATH && !TARGET_OS_OSX
|
|
230
|
+
|
|
231
|
+
- (void)handleTapForMathChip:(UITapGestureRecognizer *)gesture
|
|
232
|
+
{
|
|
233
|
+
if (gesture.state != UIGestureRecognizerStateRecognized)
|
|
234
|
+
return;
|
|
235
|
+
CGPoint loc = [gesture locationInView:_textView];
|
|
236
|
+
UITextPosition *pos = [_textView closestPositionToPoint:loc];
|
|
237
|
+
if (!pos)
|
|
238
|
+
return;
|
|
239
|
+
NSInteger idx = [_textView offsetFromPosition:_textView.beginningOfDocument toPosition:pos];
|
|
240
|
+
if (idx < 0)
|
|
241
|
+
return;
|
|
242
|
+
NSTextStorage *storage = _textView.textStorage;
|
|
243
|
+
// The closest position can land just past the chip; probe both `idx` and `idx-1`.
|
|
244
|
+
ENRMMathInlineAttachment *att = nil;
|
|
245
|
+
NSUInteger chipIdx = NSNotFound;
|
|
246
|
+
if ((NSUInteger)idx < storage.length) {
|
|
247
|
+
id v = [storage attribute:NSAttachmentAttributeName atIndex:(NSUInteger)idx effectiveRange:NULL];
|
|
248
|
+
if ([v isKindOfClass:[ENRMMathInlineAttachment class]]) {
|
|
249
|
+
att = v;
|
|
250
|
+
chipIdx = (NSUInteger)idx;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
if (!att && idx > 0) {
|
|
254
|
+
NSUInteger probe = (NSUInteger)idx - 1;
|
|
255
|
+
id v = [storage attribute:NSAttachmentAttributeName atIndex:probe effectiveRange:NULL];
|
|
256
|
+
if ([v isKindOfClass:[ENRMMathInlineAttachment class]]) {
|
|
257
|
+
att = v;
|
|
258
|
+
chipIdx = probe;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
if (!att)
|
|
262
|
+
return;
|
|
263
|
+
|
|
264
|
+
NSRange chipRange = NSMakeRange(chipIdx, 1);
|
|
265
|
+
[self clearMathChipSelectionsExcept:chipRange];
|
|
266
|
+
att.isSelected = YES;
|
|
267
|
+
[att invalidateRender];
|
|
268
|
+
NSLayoutManager *lm = storage.layoutManagers.firstObject;
|
|
269
|
+
if (lm) {
|
|
270
|
+
[lm invalidateLayoutForCharacterRange:chipRange actualCharacterRange:NULL];
|
|
271
|
+
[lm ensureLayoutForCharacterRange:chipRange];
|
|
272
|
+
}
|
|
273
|
+
ENRMSetNeedsDisplay(_textView);
|
|
274
|
+
// Place caret right after the chip (length 0) instead of selecting the chip
|
|
275
|
+
// — a length-1 selection would make UITextView draw its blue range handles
|
|
276
|
+
// on top of our custom selected-chip background.
|
|
277
|
+
NSUInteger caretIndex = chipIdx + 1;
|
|
278
|
+
if (caretIndex > storage.length)
|
|
279
|
+
caretIndex = storage.length;
|
|
280
|
+
_activeMathChipIndex = chipIdx;
|
|
281
|
+
_suppressMathChipClearOnce = YES;
|
|
282
|
+
_textView.selectedRange = NSMakeRange(caretIndex, 0);
|
|
283
|
+
|
|
284
|
+
NSRange glyphRange = [lm glyphRangeForCharacterRange:chipRange actualCharacterRange:NULL];
|
|
285
|
+
CGRect glyphRect = [lm boundingRectForGlyphRange:glyphRange inTextContainer:_textView.textContainer];
|
|
286
|
+
glyphRect.origin.x += _textView.textContainerInset.left;
|
|
287
|
+
glyphRect.origin.y += _textView.textContainerInset.top;
|
|
288
|
+
CGRect rectInSelf = [self.contentView convertRect:glyphRect fromView:_textView];
|
|
289
|
+
|
|
290
|
+
[self emitOnMathPressWithLatex:att.latex start:chipIdx end:chipIdx + 1 displayMode:att.displayMode rect:rectInSelf];
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
- (void)emitOnMathPressWithLatex:(NSString *)latex
|
|
294
|
+
start:(NSUInteger)start
|
|
295
|
+
end:(NSUInteger)end
|
|
296
|
+
displayMode:(BOOL)displayMode
|
|
297
|
+
rect:(CGRect)rect
|
|
298
|
+
{
|
|
299
|
+
auto emitter = [self getEventEmitter];
|
|
300
|
+
if (emitter == nullptr)
|
|
301
|
+
return;
|
|
302
|
+
emitter->onMathPress({
|
|
303
|
+
.latex = std::string([latex UTF8String] ?: ""),
|
|
304
|
+
.start = static_cast<int>(start),
|
|
305
|
+
.end = static_cast<int>(end),
|
|
306
|
+
.displayMode = displayMode ? true : false,
|
|
307
|
+
.x = rect.origin.x,
|
|
308
|
+
.y = rect.origin.y,
|
|
309
|
+
.width = rect.size.width,
|
|
310
|
+
.height = rect.size.height,
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
#endif
|
|
315
|
+
|
|
316
|
+
#pragma mark - State
|
|
317
|
+
|
|
318
|
+
- (void)updateState:(const facebook::react::State::Shared &)state
|
|
319
|
+
oldState:(const facebook::react::State::Shared &)oldState
|
|
320
|
+
{
|
|
321
|
+
_state = std::static_pointer_cast<const EnrichedMarkdownTextInputShadowNode::ConcreteState>(state);
|
|
322
|
+
|
|
323
|
+
if (oldState == nullptr) {
|
|
324
|
+
[self requestHeightUpdate];
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
- (void)requestHeightUpdate
|
|
329
|
+
{
|
|
330
|
+
ENRMRequestHeightUpdate<EnrichedMarkdownTextInputState>(_state, _heightUpdateCounter, self);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/// Yoga-resolved direction inherited from any ancestor `direction` style.
|
|
334
|
+
/// In FirstStrong mode this feeds the neutral-paragraph fallback, so a change
|
|
335
|
+
/// requires re-resolving per-paragraph directions over the current text.
|
|
336
|
+
- (void)updateLayoutMetrics:(const LayoutMetrics &)layoutMetrics
|
|
337
|
+
oldLayoutMetrics:(const LayoutMetrics &)oldLayoutMetrics
|
|
338
|
+
{
|
|
339
|
+
[super updateLayoutMetrics:layoutMetrics oldLayoutMetrics:oldLayoutMetrics];
|
|
340
|
+
|
|
341
|
+
NSWritingDirection resolved = _resolvedLayoutDirection;
|
|
342
|
+
if (layoutMetrics.layoutDirection == LayoutDirection::RightToLeft) {
|
|
343
|
+
resolved = NSWritingDirectionRightToLeft;
|
|
344
|
+
} else if (layoutMetrics.layoutDirection == LayoutDirection::LeftToRight) {
|
|
345
|
+
resolved = NSWritingDirectionLeftToRight;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
if (resolved != _resolvedLayoutDirection) {
|
|
349
|
+
_resolvedLayoutDirection = resolved;
|
|
350
|
+
if (_writingDirectionMode == ENRMWritingDirectionModeFirstStrong && _textView.textStorage.length > 0) {
|
|
351
|
+
[self applyFormatting];
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
#pragma mark - Measurement
|
|
357
|
+
|
|
358
|
+
- (CGSize)measureSize:(CGFloat)maxWidth
|
|
359
|
+
{
|
|
360
|
+
NSMutableAttributedString *measuredText =
|
|
361
|
+
[[NSMutableAttributedString alloc] initWithAttributedString:ENRMGetAttributedText(_textView)];
|
|
362
|
+
|
|
363
|
+
// Empty input should still be the height of a single line.
|
|
364
|
+
// Use typingAttributes so the measurement matches the actual configured font.
|
|
365
|
+
if (measuredText.length == 0) {
|
|
366
|
+
[measuredText appendAttributedString:[[NSAttributedString alloc] initWithString:@"I"
|
|
367
|
+
attributes:_textView.typingAttributes]];
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
// Trailing newlines are not counted by boundingRectWithSize — append
|
|
371
|
+
// a mock character so the extra line is included in the height.
|
|
372
|
+
if (measuredText.length > 0) {
|
|
373
|
+
unichar lastChar = [measuredText.string characterAtIndex:measuredText.length - 1];
|
|
374
|
+
if ([[NSCharacterSet newlineCharacterSet] characterIsMember:lastChar]) {
|
|
375
|
+
[measuredText appendAttributedString:[[NSAttributedString alloc] initWithString:@"I"
|
|
376
|
+
attributes:_textView.typingAttributes]];
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
CGRect boundingBox =
|
|
381
|
+
[measuredText boundingRectWithSize:CGSizeMake(maxWidth, CGFLOAT_MAX)
|
|
382
|
+
options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading
|
|
383
|
+
context:nil];
|
|
384
|
+
|
|
385
|
+
return CGSizeMake(maxWidth, ceil(boundingBox.size.height));
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
#pragma mark - Props
|
|
389
|
+
|
|
390
|
+
- (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &)oldProps
|
|
391
|
+
{
|
|
392
|
+
const auto &oldViewProps = *std::static_pointer_cast<EnrichedMarkdownTextInputProps const>(_props);
|
|
393
|
+
const auto &newViewProps = *std::static_pointer_cast<EnrichedMarkdownTextInputProps const>(props);
|
|
394
|
+
|
|
395
|
+
if (newViewProps.editable != oldViewProps.editable) {
|
|
396
|
+
_textView.editable = newViewProps.editable;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
#if !TARGET_OS_OSX
|
|
400
|
+
if (newViewProps.scrollEnabled != oldViewProps.scrollEnabled) {
|
|
401
|
+
_textView.scrollEnabled = newViewProps.scrollEnabled;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
if (newViewProps.autoCapitalize != oldViewProps.autoCapitalize) {
|
|
405
|
+
NSString *value = [NSString stringWithUTF8String:newViewProps.autoCapitalize.c_str()];
|
|
406
|
+
_textView.autocapitalizationType = ENRMAutocapitalizationTypeFromString(value);
|
|
407
|
+
if ([_textView isFirstResponder]) {
|
|
408
|
+
[_textView resignFirstResponder];
|
|
409
|
+
[_textView becomeFirstResponder];
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
if (newViewProps.multiline != oldViewProps.multiline) {
|
|
414
|
+
_textView.textContainer.maximumNumberOfLines = newViewProps.multiline ? 0 : 1;
|
|
415
|
+
_textView.textContainer.lineBreakMode =
|
|
416
|
+
newViewProps.multiline ? NSLineBreakByWordWrapping : NSLineBreakByTruncatingTail;
|
|
417
|
+
}
|
|
418
|
+
#endif
|
|
419
|
+
|
|
420
|
+
if (newViewProps.placeholder != oldViewProps.placeholder) {
|
|
421
|
+
ENRMSetPlaceholderText(_placeholderLabel, [NSString stringWithUTF8String:newViewProps.placeholder.c_str()]);
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
if (newViewProps.placeholderTextColor != oldViewProps.placeholderTextColor) {
|
|
425
|
+
if (isColorMeaningful(newViewProps.placeholderTextColor)) {
|
|
426
|
+
_placeholderLabel.textColor = RCTUIColorFromSharedColor(newViewProps.placeholderTextColor);
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
if (newViewProps.cursorColor != oldViewProps.cursorColor) {
|
|
431
|
+
if (isColorMeaningful(newViewProps.cursorColor)) {
|
|
432
|
+
ENRMSetCursorColor(_textView, RCTUIColorFromSharedColor(newViewProps.cursorColor));
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
if (newViewProps.selectionColor != oldViewProps.selectionColor) {
|
|
437
|
+
ENRMApplySelectionColor(_textView, newViewProps.selectionColor);
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
_emitMarkdown = newViewProps.isOnChangeMarkdownSet;
|
|
441
|
+
|
|
442
|
+
{
|
|
443
|
+
auto configFromProp = [](const auto &prop) {
|
|
444
|
+
return [[ENRMLinkRegexConfig alloc] initWithPattern:[NSString stringWithUTF8String:prop.pattern.c_str()]
|
|
445
|
+
caseInsensitive:prop.caseInsensitive
|
|
446
|
+
dotAll:prop.dotAll
|
|
447
|
+
isDisabled:prop.isDisabled
|
|
448
|
+
isDefault:prop.isDefault];
|
|
449
|
+
};
|
|
450
|
+
ENRMLinkRegexConfig *oldRegexConfig = configFromProp(oldViewProps.linkRegex);
|
|
451
|
+
ENRMLinkRegexConfig *newRegexConfig = configFromProp(newViewProps.linkRegex);
|
|
452
|
+
if (![newRegexConfig isEqualToConfig:oldRegexConfig]) {
|
|
453
|
+
[_autoLinkDetector setRegexConfig:newRegexConfig];
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
if (ENRMContextMenuItemsChanged(oldViewProps.contextMenuItems, newViewProps.contextMenuItems)) {
|
|
458
|
+
_contextMenuItemTexts = ENRMContextMenuTextsFromItems(newViewProps.contextMenuItems);
|
|
459
|
+
_contextMenuItemIcons = ENRMContextMenuIconsFromItems(newViewProps.contextMenuItems);
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
if (newViewProps.mentionIndicators != oldViewProps.mentionIndicators) {
|
|
463
|
+
NSMutableArray<NSString *> *indicators = [NSMutableArray array];
|
|
464
|
+
for (const auto &indicator : newViewProps.mentionIndicators) {
|
|
465
|
+
NSString *value = [NSString stringWithUTF8String:indicator.c_str()];
|
|
466
|
+
if (value.length > 0) {
|
|
467
|
+
[indicators addObject:value];
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
_mentionIndicators = [indicators copy];
|
|
471
|
+
if (_activeMentionIndicator != nil && ![_mentionIndicators containsObject:_activeMentionIndicator]) {
|
|
472
|
+
[self clearActiveMention:_activeMentionIndicator];
|
|
473
|
+
}
|
|
474
|
+
[self updateActiveMention];
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
BOOL styleChanged = applyInputStyleProps(_formatterStyle, newViewProps, oldViewProps);
|
|
478
|
+
|
|
479
|
+
BOOL writingDirectionChanged = NO;
|
|
480
|
+
if (newViewProps.writingDirection != oldViewProps.writingDirection) {
|
|
481
|
+
NSString *value = [[NSString alloc] initWithUTF8String:newViewProps.writingDirection.c_str()];
|
|
482
|
+
_writingDirectionMode = ENRMResolveWritingDirectionMode(value);
|
|
483
|
+
writingDirectionChanged = YES;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
if (newViewProps.defaultValue != oldViewProps.defaultValue) {
|
|
487
|
+
if (!newViewProps.defaultValue.empty() && oldViewProps.defaultValue.empty()) {
|
|
488
|
+
NSString *markdown = [NSString stringWithUTF8String:newViewProps.defaultValue.c_str()];
|
|
489
|
+
[self importMarkdown:markdown];
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
if (styleChanged) {
|
|
494
|
+
_placeholderLabel.font = _formatterStyle.baseFont;
|
|
495
|
+
|
|
496
|
+
[self resetBaseTypingAttributes];
|
|
497
|
+
|
|
498
|
+
if (_formattingStore.allRanges.count > 0) {
|
|
499
|
+
[self applyFormatting];
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
#if ENRICHED_MARKDOWN_MATH && !TARGET_OS_OSX
|
|
503
|
+
[self refreshAllMathChips];
|
|
504
|
+
#endif
|
|
505
|
+
|
|
506
|
+
[self requestHeightUpdate];
|
|
507
|
+
} else if (writingDirectionChanged && _textView.textStorage.length > 0) {
|
|
508
|
+
[self applyFormatting];
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
[super updateProps:props oldProps:oldProps];
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
#pragma mark - Relayout
|
|
515
|
+
|
|
516
|
+
- (void)scheduleRelayoutIfNeeded
|
|
517
|
+
{
|
|
518
|
+
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(_performRelayout) object:nil];
|
|
519
|
+
[self performSelector:@selector(_performRelayout) withObject:nil afterDelay:0];
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
- (void)_performRelayout
|
|
523
|
+
{
|
|
524
|
+
if (!_textView) {
|
|
525
|
+
return;
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
529
|
+
NSUInteger textLength = self->_textView.textStorage.length;
|
|
530
|
+
if (textLength == 0) {
|
|
531
|
+
return;
|
|
532
|
+
}
|
|
533
|
+
NSRange wholeRange = NSMakeRange(0, textLength);
|
|
534
|
+
NSRange actualRange = NSMakeRange(0, 0);
|
|
535
|
+
[self->_textView.layoutManager invalidateLayoutForCharacterRange:wholeRange actualCharacterRange:&actualRange];
|
|
536
|
+
[self->_textView.layoutManager ensureLayoutForCharacterRange:actualRange];
|
|
537
|
+
[self->_textView.layoutManager invalidateDisplayForCharacterRange:wholeRange];
|
|
538
|
+
|
|
539
|
+
CGSize measuredSize = [self measureSize:self->_textView.frame.size.width];
|
|
540
|
+
ENRMSetContentSize(self->_textView, measuredSize);
|
|
541
|
+
});
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
#pragma mark - Window attachment
|
|
545
|
+
|
|
546
|
+
- (void)didMoveToWindow
|
|
547
|
+
{
|
|
548
|
+
[super didMoveToWindow];
|
|
549
|
+
|
|
550
|
+
if (self.window) {
|
|
551
|
+
// Don't override the contentView frame set by RCTViewComponentView.
|
|
552
|
+
ENRMRefreshTextViewLayout(_textView);
|
|
553
|
+
|
|
554
|
+
[self applyFormatting];
|
|
555
|
+
[self updatePlaceholderVisibility];
|
|
556
|
+
[self requestHeightUpdate];
|
|
557
|
+
|
|
558
|
+
const auto &viewProps = *std::static_pointer_cast<EnrichedMarkdownTextInputProps const>(_props);
|
|
559
|
+
if (viewProps.autoFocus) {
|
|
560
|
+
ENRMFocusTextView(_textView);
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
#if TARGET_OS_OSX
|
|
566
|
+
|
|
567
|
+
#pragma mark - macOS responder chain
|
|
568
|
+
|
|
569
|
+
- (BOOL)acceptsFirstResponder
|
|
570
|
+
{
|
|
571
|
+
return _textView.acceptsFirstResponder;
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
- (BOOL)becomeFirstResponder
|
|
575
|
+
{
|
|
576
|
+
return [self.window makeFirstResponder:_textView];
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
- (BOOL)needsPanelToBecomeKey
|
|
580
|
+
{
|
|
581
|
+
return YES;
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
- (BOOL)mouseDownCanMoveWindow
|
|
585
|
+
{
|
|
586
|
+
return NO;
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
- (void)mouseDown:(NSEvent *)event
|
|
590
|
+
{
|
|
591
|
+
[self.window makeFirstResponder:_textView];
|
|
592
|
+
[_textView mouseDown:event];
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
#endif
|
|
596
|
+
|
|
597
|
+
#if !TARGET_OS_OSX
|
|
598
|
+
- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection
|
|
599
|
+
{
|
|
600
|
+
[super traitCollectionDidChange:previousTraitCollection];
|
|
601
|
+
|
|
602
|
+
if (previousTraitCollection.preferredContentSizeCategory != self.traitCollection.preferredContentSizeCategory) {
|
|
603
|
+
[_formatterStyle invalidateFontCache];
|
|
604
|
+
|
|
605
|
+
[self resetBaseTypingAttributes];
|
|
606
|
+
|
|
607
|
+
_placeholderLabel.font = _formatterStyle.baseFont;
|
|
608
|
+
|
|
609
|
+
[self applyFormatting];
|
|
610
|
+
[self requestHeightUpdate];
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
#endif
|
|
614
|
+
|
|
615
|
+
#pragma mark - Placeholder
|
|
616
|
+
|
|
617
|
+
- (void)updatePlaceholderVisibility
|
|
618
|
+
{
|
|
619
|
+
_placeholderLabel.hidden = (ENRMGetPlainText(_textView).length > 0);
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
#pragma mark - Markdown import
|
|
623
|
+
|
|
624
|
+
- (void)importMarkdown:(NSString *)markdown
|
|
625
|
+
{
|
|
626
|
+
ENRMInputParser *parser = [[ENRMInputParser alloc] init];
|
|
627
|
+
ENRMParseResult *parsed = [parser parseToPlainTextAndRanges:markdown];
|
|
628
|
+
|
|
629
|
+
_blockEmitting = YES;
|
|
630
|
+
|
|
631
|
+
_isApplyingFormatting = YES;
|
|
632
|
+
ENRMSetPlainText(_textView, parsed.plainText);
|
|
633
|
+
|
|
634
|
+
#if ENRICHED_MARKDOWN_MATH && !TARGET_OS_OSX
|
|
635
|
+
if (parsed.mathAtoms.count > 0) {
|
|
636
|
+
NSTextStorage *storage = _textView.textStorage;
|
|
637
|
+
[storage beginEditing];
|
|
638
|
+
for (ENRMMathAtom *atom in parsed.mathAtoms) {
|
|
639
|
+
if (atom.position >= storage.length)
|
|
640
|
+
continue;
|
|
641
|
+
unichar c = [storage.string characterAtIndex:atom.position];
|
|
642
|
+
if (c != (unichar)0xFFFC)
|
|
643
|
+
continue;
|
|
644
|
+
ENRMMathInlineAttachment *att = [self createMathAttachmentWithLatex:atom.latex displayMode:atom.displayMode];
|
|
645
|
+
NSAttributedString *replacement = [NSAttributedString attributedStringWithAttachment:att];
|
|
646
|
+
[storage replaceCharactersInRange:NSMakeRange(atom.position, 1) withAttributedString:replacement];
|
|
647
|
+
if (atom.displayMode && _formatterStyle.mathBlockAlignment != NSTextAlignmentNatural) {
|
|
648
|
+
NSMutableParagraphStyle *ps = [[NSMutableParagraphStyle alloc] init];
|
|
649
|
+
ps.alignment = _formatterStyle.mathBlockAlignment;
|
|
650
|
+
[storage addAttribute:NSParagraphStyleAttributeName value:ps range:NSMakeRange(atom.position, 1)];
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
[storage endEditing];
|
|
654
|
+
}
|
|
655
|
+
#endif
|
|
656
|
+
|
|
657
|
+
_isApplyingFormatting = NO;
|
|
658
|
+
|
|
659
|
+
[_formattingStore setRanges:parsed.formattingRanges];
|
|
660
|
+
_lastTextLength = parsed.plainText.length;
|
|
661
|
+
_lastSelectedRange = _textView.selectedRange;
|
|
662
|
+
[self applyFormatting];
|
|
663
|
+
[self updatePlaceholderVisibility];
|
|
664
|
+
|
|
665
|
+
_blockEmitting = NO;
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
#if ENRICHED_MARKDOWN_MATH && !TARGET_OS_OSX
|
|
669
|
+
|
|
670
|
+
- (void)applyMathStyleToAttachment:(ENRMMathInlineAttachment *)att
|
|
671
|
+
{
|
|
672
|
+
if (att.displayMode) {
|
|
673
|
+
att.fontSize = _formatterStyle.mathBlockFontSize > 0 ? _formatterStyle.mathBlockFontSize : 20.0;
|
|
674
|
+
att.mathTextColor = _formatterStyle.mathBlockColor ?: _formatterStyle.baseTextColor;
|
|
675
|
+
att.containerBackgroundColor = _formatterStyle.mathBlockBackgroundColor;
|
|
676
|
+
att.containerBorderColor = _formatterStyle.mathBlockBorderColor;
|
|
677
|
+
att.containerBorderWidth = _formatterStyle.mathBlockBorderWidth;
|
|
678
|
+
att.containerBorderRadius = _formatterStyle.mathBlockBorderRadius;
|
|
679
|
+
att.containerPaddingHorizontal = _formatterStyle.mathBlockPaddingHorizontal;
|
|
680
|
+
att.containerPaddingVertical = _formatterStyle.mathBlockPaddingVertical;
|
|
681
|
+
att.blockMarginTop = _formatterStyle.mathBlockMarginTop;
|
|
682
|
+
att.blockMarginBottom = _formatterStyle.mathBlockMarginBottom;
|
|
683
|
+
att.blockAlignment = _formatterStyle.mathBlockAlignment;
|
|
684
|
+
att.selectedBackgroundColor = _formatterStyle.mathBlockSelectedBackgroundColor;
|
|
685
|
+
att.selectedBorderColor = _formatterStyle.mathBlockSelectedBorderColor;
|
|
686
|
+
} else {
|
|
687
|
+
att.fontSize = _formatterStyle.mathFontSize > 0 ? _formatterStyle.mathFontSize : 16.0;
|
|
688
|
+
att.mathTextColor = _formatterStyle.mathColor ?: _formatterStyle.baseTextColor;
|
|
689
|
+
att.containerBackgroundColor = _formatterStyle.mathBackgroundColor;
|
|
690
|
+
att.containerBorderColor = _formatterStyle.mathBorderColor;
|
|
691
|
+
att.containerBorderWidth = _formatterStyle.mathBorderWidth;
|
|
692
|
+
att.containerBorderRadius = _formatterStyle.mathBorderRadius;
|
|
693
|
+
att.containerPaddingHorizontal = _formatterStyle.mathPaddingHorizontal;
|
|
694
|
+
att.containerPaddingVertical = _formatterStyle.mathPaddingVertical;
|
|
695
|
+
att.blockMarginTop = 0;
|
|
696
|
+
att.blockMarginBottom = 0;
|
|
697
|
+
att.blockAlignment = NSTextAlignmentNatural;
|
|
698
|
+
att.selectedBackgroundColor = _formatterStyle.mathSelectedBackgroundColor;
|
|
699
|
+
att.selectedBorderColor = _formatterStyle.mathSelectedBorderColor;
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
- (ENRMMathInlineAttachment *)createMathAttachmentWithLatex:(NSString *)latex displayMode:(BOOL)displayMode
|
|
704
|
+
{
|
|
705
|
+
ENRMMathInlineAttachment *att = [[ENRMMathInlineAttachment alloc] init];
|
|
706
|
+
att.latex = latex ?: @"";
|
|
707
|
+
att.displayMode = displayMode;
|
|
708
|
+
[self applyMathStyleToAttachment:att];
|
|
709
|
+
return att;
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
- (void)refreshAllMathChips
|
|
713
|
+
{
|
|
714
|
+
NSTextStorage *storage = _textView.textStorage;
|
|
715
|
+
if (storage.length == 0)
|
|
716
|
+
return;
|
|
717
|
+
__weak EnrichedMarkdownTextInput *weakSelf = self;
|
|
718
|
+
[storage beginEditing];
|
|
719
|
+
[storage enumerateAttribute:NSAttachmentAttributeName
|
|
720
|
+
inRange:NSMakeRange(0, storage.length)
|
|
721
|
+
options:0
|
|
722
|
+
usingBlock:^(id value, NSRange range, BOOL *stop) {
|
|
723
|
+
EnrichedMarkdownTextInput *strongSelf = weakSelf;
|
|
724
|
+
if (!strongSelf)
|
|
725
|
+
return;
|
|
726
|
+
if ([value isKindOfClass:[ENRMMathInlineAttachment class]]) {
|
|
727
|
+
ENRMMathInlineAttachment *att = value;
|
|
728
|
+
[strongSelf applyMathStyleToAttachment:att];
|
|
729
|
+
[att invalidateRender];
|
|
730
|
+
}
|
|
731
|
+
}];
|
|
732
|
+
[storage endEditing];
|
|
733
|
+
|
|
734
|
+
NSLayoutManager *lm = storage.layoutManagers.firstObject;
|
|
735
|
+
if (lm) {
|
|
736
|
+
NSRange fullRange = NSMakeRange(0, storage.length);
|
|
737
|
+
[lm invalidateLayoutForCharacterRange:fullRange actualCharacterRange:NULL];
|
|
738
|
+
[lm ensureLayoutForCharacterRange:fullRange];
|
|
739
|
+
}
|
|
740
|
+
ENRMSetNeedsDisplay(_textView);
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
#endif
|
|
744
|
+
|
|
745
|
+
- (void)replaceTextInRange:(NSRange)selection
|
|
746
|
+
withText:(NSString *)text
|
|
747
|
+
formattingRanges:(NSArray<ENRMFormattingRange *> *)ranges
|
|
748
|
+
{
|
|
749
|
+
NSUInteger editLocation = selection.location;
|
|
750
|
+
|
|
751
|
+
_isApplyingFormatting = YES;
|
|
752
|
+
ENRMReplaceTextInRange(_textView, text, selection);
|
|
753
|
+
_isApplyingFormatting = NO;
|
|
754
|
+
|
|
755
|
+
[_formattingStore adjustForEditAtLocation:editLocation deletedLength:selection.length insertedLength:text.length];
|
|
756
|
+
|
|
757
|
+
for (ENRMFormattingRange *range in ranges) {
|
|
758
|
+
NSRange shifted = NSMakeRange(range.range.location + editLocation, range.range.length);
|
|
759
|
+
[_formattingStore addRange:[ENRMFormattingRange rangeWithType:range.type range:shifted url:range.url]];
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
_lastTextLength = ENRMGetPlainText(_textView).length;
|
|
763
|
+
_lastSelectedRange = _textView.selectedRange;
|
|
764
|
+
|
|
765
|
+
[self applyFormatting];
|
|
766
|
+
|
|
767
|
+
[_detectorPipeline processTextChange:ENRMGetPlainText(_textView)
|
|
768
|
+
modificationRange:NSMakeRange(editLocation, text.length)];
|
|
769
|
+
|
|
770
|
+
[self updatePlaceholderVisibility];
|
|
771
|
+
[self emitOnChangeText];
|
|
772
|
+
[self emitOnChangeSelection];
|
|
773
|
+
[self emitFormattingChanged];
|
|
774
|
+
[self requestHeightUpdate];
|
|
775
|
+
[self scheduleRelayoutIfNeeded];
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
- (void)replaceSelectedTextWith:(NSString *)text formattingRanges:(NSArray<ENRMFormattingRange *> *)ranges
|
|
779
|
+
{
|
|
780
|
+
[self replaceTextInRange:_textView.selectedRange withText:text formattingRanges:ranges];
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
- (void)pasteMarkdown:(NSString *)markdown
|
|
784
|
+
{
|
|
785
|
+
ENRMInputParser *parser = [[ENRMInputParser alloc] init];
|
|
786
|
+
ENRMParseResult *parsed = [parser parseToPlainTextAndRanges:markdown];
|
|
787
|
+
[self replaceSelectedTextWith:parsed.plainText formattingRanges:parsed.formattingRanges];
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
#pragma mark - Formatting
|
|
791
|
+
|
|
792
|
+
- (void)resetBaseTypingAttributes
|
|
793
|
+
{
|
|
794
|
+
ENRMSetDefaultTypingAttributes(_textView, @{
|
|
795
|
+
NSFontAttributeName : _formatterStyle.baseFont,
|
|
796
|
+
NSForegroundColorAttributeName : _formatterStyle.baseTextColor,
|
|
797
|
+
});
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
- (void)applyFormatting
|
|
801
|
+
{
|
|
802
|
+
if (_isApplyingFormatting) {
|
|
803
|
+
return;
|
|
804
|
+
}
|
|
805
|
+
if (ENRMHasMarkedText(_textView)) {
|
|
806
|
+
return;
|
|
807
|
+
}
|
|
808
|
+
_isApplyingFormatting = YES;
|
|
809
|
+
|
|
810
|
+
NSRange savedSelection = _textView.selectedRange;
|
|
811
|
+
|
|
812
|
+
[_formatter applyFormattingRanges:_formattingStore.allRanges toTextView:_textView style:_formatterStyle];
|
|
813
|
+
[_detectorPipeline refreshAllStyling];
|
|
814
|
+
[self applyWritingDirection];
|
|
815
|
+
|
|
816
|
+
NSUInteger textLen = ENRMGetPlainText(_textView).length;
|
|
817
|
+
if (savedSelection.location + savedSelection.length <= textLen) {
|
|
818
|
+
_textView.selectedRange = savedSelection;
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
_isApplyingFormatting = NO;
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
- (void)applyWritingDirection
|
|
825
|
+
{
|
|
826
|
+
NSTextStorage *textStorage = _textView.textStorage;
|
|
827
|
+
if (textStorage.length == 0) {
|
|
828
|
+
return;
|
|
829
|
+
}
|
|
830
|
+
[textStorage beginEditing];
|
|
831
|
+
ENRMApplyWritingDirectionMode(textStorage, _writingDirectionMode, _resolvedLayoutDirection);
|
|
832
|
+
[textStorage endEditing];
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
#pragma mark - Commands
|
|
836
|
+
|
|
837
|
+
- (void)focus
|
|
838
|
+
{
|
|
839
|
+
ENRMFocusTextView(_textView);
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
- (void)blur
|
|
843
|
+
{
|
|
844
|
+
ENRMBlurTextView(_textView);
|
|
845
|
+
}
|
|
846
|
+
|
|
847
|
+
- (void)setValue:(NSString *)markdown
|
|
848
|
+
{
|
|
849
|
+
[self importMarkdown:markdown];
|
|
850
|
+
_lastSelectedRange = _textView.selectedRange;
|
|
851
|
+
[self emitOnChangeText];
|
|
852
|
+
[self emitOnChangeSelection];
|
|
853
|
+
[self emitOnChangeState];
|
|
854
|
+
[self requestHeightUpdate];
|
|
855
|
+
}
|
|
856
|
+
|
|
857
|
+
- (void)setSelection:(NSInteger)start end:(NSInteger)end
|
|
858
|
+
{
|
|
859
|
+
NSInteger textLen = (NSInteger)ENRMGetPlainText(_textView).length;
|
|
860
|
+
NSInteger clampedStart = MIN(MAX(start, 0), textLen);
|
|
861
|
+
NSInteger clampedEnd = MIN(MAX(end, clampedStart), textLen);
|
|
862
|
+
_textView.selectedRange = NSMakeRange((NSUInteger)clampedStart, (NSUInteger)(clampedEnd - clampedStart));
|
|
863
|
+
[self emitOnChangeSelection];
|
|
864
|
+
[self emitOnChangeState];
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
- (void)toggleBold
|
|
868
|
+
{
|
|
869
|
+
[self toggleInlineStyle:ENRMInputStyleTypeStrong];
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
- (void)toggleItalic
|
|
873
|
+
{
|
|
874
|
+
[self toggleInlineStyle:ENRMInputStyleTypeEmphasis];
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
- (void)toggleUnderline
|
|
878
|
+
{
|
|
879
|
+
[self toggleInlineStyle:ENRMInputStyleTypeUnderline];
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
- (void)toggleStrikethrough
|
|
883
|
+
{
|
|
884
|
+
[self toggleInlineStyle:ENRMInputStyleTypeStrikethrough];
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
- (void)toggleSpoiler
|
|
888
|
+
{
|
|
889
|
+
[self toggleInlineStyle:ENRMInputStyleTypeSpoiler];
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
- (void)toggleInlineStyle:(ENRMInputStyleType)styleType
|
|
893
|
+
{
|
|
894
|
+
id<ENRMStyleHandler> handler = [_formatter handlerForStyleType:styleType];
|
|
895
|
+
if (!handler) {
|
|
896
|
+
return;
|
|
897
|
+
}
|
|
898
|
+
ENRMStyleMergingConfig *mergingConfig = handler.mergingConfig;
|
|
899
|
+
|
|
900
|
+
NSRange selection = _textView.selectedRange;
|
|
901
|
+
NSUInteger cursor = selection.location;
|
|
902
|
+
NSNumber *key = @(styleType);
|
|
903
|
+
|
|
904
|
+
// Check blocking rules: if any blocking style is active, refuse to toggle on.
|
|
905
|
+
if (mergingConfig.blockingStyles.count > 0) {
|
|
906
|
+
BOOL isCurrentlyActive = [_formattingStore isStyleActive:styleType atPosition:cursor];
|
|
907
|
+
if (!isCurrentlyActive) {
|
|
908
|
+
for (NSNumber *blockerNum in mergingConfig.blockingStyles) {
|
|
909
|
+
if ([_formattingStore isStyleActive:(ENRMInputStyleType)blockerNum.integerValue atPosition:cursor]) {
|
|
910
|
+
return;
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
}
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
if (selection.length > 0) {
|
|
917
|
+
BOOL fullyStyled = YES;
|
|
918
|
+
NSUInteger pos = selection.location;
|
|
919
|
+
NSUInteger selEnd = NSMaxRange(selection);
|
|
920
|
+
while (pos < selEnd) {
|
|
921
|
+
ENRMFormattingRange *match = [_formattingStore rangeOfType:styleType containingPosition:pos];
|
|
922
|
+
if (match == nil) {
|
|
923
|
+
fullyStyled = NO;
|
|
924
|
+
break;
|
|
925
|
+
}
|
|
926
|
+
pos = NSMaxRange(match.range);
|
|
927
|
+
}
|
|
928
|
+
if (fullyStyled) {
|
|
929
|
+
[_formattingStore removeType:styleType inRange:selection];
|
|
930
|
+
} else {
|
|
931
|
+
// Remove conflicting styles from the range before applying.
|
|
932
|
+
for (NSNumber *conflictNum in mergingConfig.conflictingStyles) {
|
|
933
|
+
[_formattingStore removeType:(ENRMInputStyleType)conflictNum.integerValue inRange:selection];
|
|
934
|
+
}
|
|
935
|
+
ENRMFormattingRange *newRange = [ENRMFormattingRange rangeWithType:styleType range:selection];
|
|
936
|
+
[_formattingStore addRange:newRange];
|
|
937
|
+
}
|
|
938
|
+
[_pendingStyles removeObject:key];
|
|
939
|
+
[_pendingStyleRemovals removeObject:key];
|
|
940
|
+
} else {
|
|
941
|
+
BOOL isInsideRange = [_formattingStore isStyleActive:styleType atPosition:cursor];
|
|
942
|
+
|
|
943
|
+
if ([_pendingStyleRemovals containsObject:key]) {
|
|
944
|
+
[_pendingStyleRemovals removeObject:key];
|
|
945
|
+
} else if ([_pendingStyles containsObject:key]) {
|
|
946
|
+
[_pendingStyles removeObject:key];
|
|
947
|
+
} else if (isInsideRange) {
|
|
948
|
+
[_pendingStyleRemovals addObject:key];
|
|
949
|
+
} else {
|
|
950
|
+
[_pendingStyles addObject:key];
|
|
951
|
+
}
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
[self applyFormatting];
|
|
955
|
+
[self emitFormattingChanged];
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
- (void)setLink:(NSString *)url
|
|
959
|
+
{
|
|
960
|
+
NSRange selection = _textView.selectedRange;
|
|
961
|
+
NSUInteger cursor = selection.location;
|
|
962
|
+
|
|
963
|
+
ENRMFormattingRange *activeLink = [_formattingStore rangeOfType:ENRMInputStyleTypeLink containingPosition:cursor];
|
|
964
|
+
|
|
965
|
+
if (activeLink != nil) {
|
|
966
|
+
activeLink.url = url;
|
|
967
|
+
[_autoLinkDetector clearAutoLinkInRange:activeLink.range];
|
|
968
|
+
} else if (selection.length > 0) {
|
|
969
|
+
ENRMFormattingRange *linkRange = [ENRMFormattingRange rangeWithType:ENRMInputStyleTypeLink range:selection url:url];
|
|
970
|
+
[_formattingStore addRange:linkRange];
|
|
971
|
+
[_autoLinkDetector clearAutoLinkInRange:selection];
|
|
972
|
+
} else {
|
|
973
|
+
return;
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
[self applyFormatting];
|
|
977
|
+
[self emitFormattingChanged];
|
|
978
|
+
}
|
|
979
|
+
|
|
980
|
+
- (void)insertLink:(NSString *)text url:(NSString *)url
|
|
981
|
+
{
|
|
982
|
+
NSString *displayText = text.length > 0 ? text : url;
|
|
983
|
+
NSRange linkRange = NSMakeRange(0, displayText.length);
|
|
984
|
+
ENRMFormattingRange *range = [ENRMFormattingRange rangeWithType:ENRMInputStyleTypeLink
|
|
985
|
+
range:linkRange
|
|
986
|
+
url:[self sanitizeLinkURL:url]];
|
|
987
|
+
[self replaceSelectedTextWith:displayText formattingRanges:@[ range ]];
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
- (NSString *)sanitizeLinkURL:(NSString *)url
|
|
991
|
+
{
|
|
992
|
+
NSString *result = [url stringByReplacingOccurrencesOfString:@"(" withString:@"%28"];
|
|
993
|
+
return [result stringByReplacingOccurrencesOfString:@")" withString:@"%29"];
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
- (void)startMention:(NSString *)indicator
|
|
997
|
+
{
|
|
998
|
+
if (indicator.length == 0 || ![_mentionIndicators containsObject:indicator]) {
|
|
999
|
+
return;
|
|
1000
|
+
}
|
|
1001
|
+
|
|
1002
|
+
[self replaceSelectedTextWith:indicator formattingRanges:@[]];
|
|
1003
|
+
[self updateActiveMention];
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
- (void)insertMention:(NSString *)displayText url:(NSString *)url
|
|
1007
|
+
{
|
|
1008
|
+
if (displayText.length == 0 || _activeMentionIndicator == nil || _activeMentionRange.location == NSNotFound) {
|
|
1009
|
+
return;
|
|
1010
|
+
}
|
|
1011
|
+
|
|
1012
|
+
NSString *plainText = ENRMGetPlainText(_textView);
|
|
1013
|
+
NSUInteger rangeEnd = NSMaxRange(_activeMentionRange);
|
|
1014
|
+
if (rangeEnd > plainText.length) {
|
|
1015
|
+
return;
|
|
1016
|
+
}
|
|
1017
|
+
BOOL nextCharIsWhitespace = rangeEnd < plainText.length && [[NSCharacterSet whitespaceAndNewlineCharacterSet]
|
|
1018
|
+
characterIsMember:[plainText
|
|
1019
|
+
characterAtIndex:rangeEnd]];
|
|
1020
|
+
NSString *replacement = nextCharIsWhitespace ? displayText : [displayText stringByAppendingString:@" "];
|
|
1021
|
+
ENRMFormattingRange *linkRange = [ENRMFormattingRange rangeWithType:ENRMInputStyleTypeLink
|
|
1022
|
+
range:NSMakeRange(0, displayText.length)
|
|
1023
|
+
url:[self sanitizeLinkURL:url]];
|
|
1024
|
+
NSString *indicator = _activeMentionIndicator;
|
|
1025
|
+
NSRange mentionRange = _activeMentionRange;
|
|
1026
|
+
|
|
1027
|
+
[self clearActiveMention:indicator];
|
|
1028
|
+
[self replaceTextInRange:mentionRange withText:replacement formattingRanges:@[ linkRange ]];
|
|
1029
|
+
_textView.selectedRange = NSMakeRange(mentionRange.location + replacement.length, 0);
|
|
1030
|
+
[self emitOnChangeSelection];
|
|
1031
|
+
}
|
|
1032
|
+
|
|
1033
|
+
- (void)removeLink
|
|
1034
|
+
{
|
|
1035
|
+
NSUInteger cursor = _textView.selectedRange.location;
|
|
1036
|
+
ENRMFormattingRange *activeLink = [_formattingStore rangeOfType:ENRMInputStyleTypeLink containingPosition:cursor];
|
|
1037
|
+
if (activeLink == nil) {
|
|
1038
|
+
return;
|
|
1039
|
+
}
|
|
1040
|
+
|
|
1041
|
+
[_formattingStore removeRange:activeLink];
|
|
1042
|
+
[self applyFormatting];
|
|
1043
|
+
[self emitFormattingChanged];
|
|
1044
|
+
}
|
|
1045
|
+
|
|
1046
|
+
#pragma mark - Math chip commands
|
|
1047
|
+
|
|
1048
|
+
- (void)insertMath:(NSString *)latex displayMode:(BOOL)displayMode
|
|
1049
|
+
{
|
|
1050
|
+
#if ENRICHED_MARKDOWN_MATH && !TARGET_OS_OSX
|
|
1051
|
+
if (latex.length == 0)
|
|
1052
|
+
return;
|
|
1053
|
+
NSTextStorage *storage = _textView.textStorage;
|
|
1054
|
+
NSRange selection = _textView.selectedRange;
|
|
1055
|
+
NSString *plainText = ENRMGetPlainText(_textView);
|
|
1056
|
+
|
|
1057
|
+
NSMutableString *prefix = [NSMutableString string];
|
|
1058
|
+
NSMutableString *suffix = [NSMutableString string];
|
|
1059
|
+
if (displayMode) {
|
|
1060
|
+
BOOL atLineStart = (selection.location == 0) || [plainText characterAtIndex:selection.location - 1] == '\n';
|
|
1061
|
+
NSUInteger afterSel = selection.location + selection.length;
|
|
1062
|
+
BOOL atLineEnd = (afterSel >= plainText.length) || [plainText characterAtIndex:afterSel] == '\n';
|
|
1063
|
+
if (!atLineStart)
|
|
1064
|
+
[prefix appendString:@"\n"];
|
|
1065
|
+
if (!atLineEnd)
|
|
1066
|
+
[suffix appendString:@"\n"];
|
|
1067
|
+
}
|
|
1068
|
+
|
|
1069
|
+
ENRMMathInlineAttachment *att = [self createMathAttachmentWithLatex:latex displayMode:displayMode];
|
|
1070
|
+
NSMutableAttributedString *replacement = [[NSMutableAttributedString alloc] init];
|
|
1071
|
+
if (prefix.length) {
|
|
1072
|
+
[replacement appendAttributedString:[[NSAttributedString alloc] initWithString:prefix]];
|
|
1073
|
+
}
|
|
1074
|
+
[replacement appendAttributedString:[NSAttributedString attributedStringWithAttachment:att]];
|
|
1075
|
+
if (suffix.length) {
|
|
1076
|
+
[replacement appendAttributedString:[[NSAttributedString alloc] initWithString:suffix]];
|
|
1077
|
+
}
|
|
1078
|
+
|
|
1079
|
+
if (displayMode && att.blockAlignment != NSTextAlignmentNatural) {
|
|
1080
|
+
NSMutableParagraphStyle *ps = [[NSMutableParagraphStyle alloc] init];
|
|
1081
|
+
ps.alignment = att.blockAlignment;
|
|
1082
|
+
NSRange chipRange = NSMakeRange(prefix.length, 1);
|
|
1083
|
+
[replacement addAttribute:NSParagraphStyleAttributeName value:ps range:chipRange];
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
_isApplyingFormatting = YES;
|
|
1087
|
+
[storage replaceCharactersInRange:selection withAttributedString:replacement];
|
|
1088
|
+
_isApplyingFormatting = NO;
|
|
1089
|
+
|
|
1090
|
+
NSUInteger insertedLength = replacement.length;
|
|
1091
|
+
[_formattingStore adjustForEditAtLocation:selection.location
|
|
1092
|
+
deletedLength:selection.length
|
|
1093
|
+
insertedLength:insertedLength];
|
|
1094
|
+
|
|
1095
|
+
NSUInteger newCursor = selection.location + insertedLength;
|
|
1096
|
+
_textView.selectedRange = NSMakeRange(newCursor, 0);
|
|
1097
|
+
_lastTextLength = ENRMGetPlainText(_textView).length;
|
|
1098
|
+
_lastSelectedRange = _textView.selectedRange;
|
|
1099
|
+
|
|
1100
|
+
[self applyFormatting];
|
|
1101
|
+
[self updatePlaceholderVisibility];
|
|
1102
|
+
[self emitOnChangeText];
|
|
1103
|
+
[self emitOnChangeSelection];
|
|
1104
|
+
[self emitFormattingChanged];
|
|
1105
|
+
[self requestHeightUpdate];
|
|
1106
|
+
[self scheduleRelayoutIfNeeded];
|
|
1107
|
+
#endif
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1110
|
+
- (void)updateMath:(NSInteger)start latex:(NSString *)latex displayMode:(BOOL)displayMode
|
|
1111
|
+
{
|
|
1112
|
+
#if ENRICHED_MARKDOWN_MATH && !TARGET_OS_OSX
|
|
1113
|
+
NSTextStorage *storage = _textView.textStorage;
|
|
1114
|
+
if (start < 0 || (NSUInteger)start >= storage.length)
|
|
1115
|
+
return;
|
|
1116
|
+
id value = [storage attribute:NSAttachmentAttributeName atIndex:(NSUInteger)start effectiveRange:NULL];
|
|
1117
|
+
if (![value isKindOfClass:[ENRMMathInlineAttachment class]])
|
|
1118
|
+
return;
|
|
1119
|
+
|
|
1120
|
+
ENRMMathInlineAttachment *att = value;
|
|
1121
|
+
BOOL modeChanged = (att.displayMode != displayMode);
|
|
1122
|
+
att.latex = latex ?: @"";
|
|
1123
|
+
att.displayMode = displayMode;
|
|
1124
|
+
[self applyMathStyleToAttachment:att];
|
|
1125
|
+
[att invalidateRender];
|
|
1126
|
+
|
|
1127
|
+
NSRange chipRange = NSMakeRange((NSUInteger)start, 1);
|
|
1128
|
+
if (modeChanged) {
|
|
1129
|
+
[storage beginEditing];
|
|
1130
|
+
if (displayMode && att.blockAlignment != NSTextAlignmentNatural) {
|
|
1131
|
+
NSMutableParagraphStyle *ps = [[NSMutableParagraphStyle alloc] init];
|
|
1132
|
+
ps.alignment = att.blockAlignment;
|
|
1133
|
+
[storage addAttribute:NSParagraphStyleAttributeName value:ps range:chipRange];
|
|
1134
|
+
} else {
|
|
1135
|
+
[storage removeAttribute:NSParagraphStyleAttributeName range:chipRange];
|
|
1136
|
+
}
|
|
1137
|
+
[storage endEditing];
|
|
1138
|
+
}
|
|
1139
|
+
|
|
1140
|
+
NSLayoutManager *lm = storage.layoutManagers.firstObject;
|
|
1141
|
+
if (lm) {
|
|
1142
|
+
[lm invalidateLayoutForCharacterRange:chipRange actualCharacterRange:NULL];
|
|
1143
|
+
[lm ensureLayoutForCharacterRange:chipRange];
|
|
1144
|
+
}
|
|
1145
|
+
ENRMSetNeedsDisplay(_textView);
|
|
1146
|
+
|
|
1147
|
+
if (_emitMarkdown) {
|
|
1148
|
+
[self emitOnChangeMarkdown];
|
|
1149
|
+
}
|
|
1150
|
+
[self requestHeightUpdate];
|
|
1151
|
+
[self scheduleRelayoutIfNeeded];
|
|
1152
|
+
#endif
|
|
1153
|
+
}
|
|
1154
|
+
|
|
1155
|
+
- (void)removeMath:(NSInteger)start
|
|
1156
|
+
{
|
|
1157
|
+
#if ENRICHED_MARKDOWN_MATH && !TARGET_OS_OSX
|
|
1158
|
+
NSTextStorage *storage = _textView.textStorage;
|
|
1159
|
+
if (start < 0 || (NSUInteger)start >= storage.length)
|
|
1160
|
+
return;
|
|
1161
|
+
id value = [storage attribute:NSAttachmentAttributeName atIndex:(NSUInteger)start effectiveRange:NULL];
|
|
1162
|
+
if (![value isKindOfClass:[ENRMMathInlineAttachment class]])
|
|
1163
|
+
return;
|
|
1164
|
+
|
|
1165
|
+
[self replaceTextInRange:NSMakeRange((NSUInteger)start, 1) withText:@"" formattingRanges:@[]];
|
|
1166
|
+
#endif
|
|
1167
|
+
}
|
|
1168
|
+
|
|
1169
|
+
- (void)showLinkPrompt
|
|
1170
|
+
{
|
|
1171
|
+
NSUInteger cursor = _textView.selectedRange.location;
|
|
1172
|
+
ENRMFormattingRange *activeLink = [_formattingStore rangeOfType:ENRMInputStyleTypeLink containingPosition:cursor];
|
|
1173
|
+
NSString *existingURL = activeLink != nil ? activeLink.url : nil;
|
|
1174
|
+
|
|
1175
|
+
__weak EnrichedMarkdownTextInput *weakSelf = self;
|
|
1176
|
+
ENRMShowLinkPrompt(self, existingURL, ^(NSString *url) { [weakSelf setLink:url]; });
|
|
1177
|
+
}
|
|
1178
|
+
|
|
1179
|
+
- (nullable NSString *)markdownForSelectedRange
|
|
1180
|
+
{
|
|
1181
|
+
NSRange selection = _textView.selectedRange;
|
|
1182
|
+
if (selection.length == 0) {
|
|
1183
|
+
return nil;
|
|
1184
|
+
}
|
|
1185
|
+
|
|
1186
|
+
NSAttributedString *full = _textView.textStorage;
|
|
1187
|
+
if (NSMaxRange(selection) > full.length) {
|
|
1188
|
+
return nil;
|
|
1189
|
+
}
|
|
1190
|
+
NSAttributedString *selectedAttr = [full attributedSubstringFromRange:selection];
|
|
1191
|
+
NSUInteger selEnd = NSMaxRange(selection);
|
|
1192
|
+
|
|
1193
|
+
NSMutableArray<ENRMFormattingRange *> *clippedRanges = [NSMutableArray array];
|
|
1194
|
+
for (ENRMFormattingRange *range in [self allRangesIncludingTransient]) {
|
|
1195
|
+
NSUInteger rangeStart = range.range.location;
|
|
1196
|
+
NSUInteger rangeEnd = NSMaxRange(range.range);
|
|
1197
|
+
|
|
1198
|
+
if (rangeEnd <= selection.location || rangeStart >= selEnd) {
|
|
1199
|
+
continue;
|
|
1200
|
+
}
|
|
1201
|
+
|
|
1202
|
+
NSUInteger clippedStart = MAX(rangeStart, selection.location);
|
|
1203
|
+
NSUInteger clippedEnd = MIN(rangeEnd, selEnd);
|
|
1204
|
+
NSRange shifted = NSMakeRange(clippedStart - selection.location, clippedEnd - clippedStart);
|
|
1205
|
+
|
|
1206
|
+
[clippedRanges addObject:[ENRMFormattingRange rangeWithType:range.type range:shifted url:range.url]];
|
|
1207
|
+
}
|
|
1208
|
+
|
|
1209
|
+
return [ENRMMarkdownSerializer serializeAttributedString:selectedAttr ranges:clippedRanges];
|
|
1210
|
+
}
|
|
1211
|
+
|
|
1212
|
+
- (void)requestMarkdown:(NSInteger)requestId
|
|
1213
|
+
{
|
|
1214
|
+
auto emitter = [self getEventEmitter];
|
|
1215
|
+
if (emitter == nullptr) {
|
|
1216
|
+
return;
|
|
1217
|
+
}
|
|
1218
|
+
NSString *markdown = [ENRMMarkdownSerializer serializeAttributedString:_textView.textStorage
|
|
1219
|
+
ranges:[self allRangesIncludingTransient]];
|
|
1220
|
+
emitter->onRequestMarkdownResult({
|
|
1221
|
+
.requestId = static_cast<int>(requestId),
|
|
1222
|
+
.markdown = std::string([markdown UTF8String] ?: ""),
|
|
1223
|
+
});
|
|
1224
|
+
}
|
|
1225
|
+
|
|
1226
|
+
- (CGRect)computeCaretRect
|
|
1227
|
+
{
|
|
1228
|
+
CGRect caretRect = CGRectZero;
|
|
1229
|
+
#if !TARGET_OS_OSX
|
|
1230
|
+
UITextRange *selectedRange = _textView.selectedTextRange;
|
|
1231
|
+
if (selectedRange != nil) {
|
|
1232
|
+
caretRect = [_textView caretRectForPosition:selectedRange.start];
|
|
1233
|
+
}
|
|
1234
|
+
#else
|
|
1235
|
+
NSRange selection = _textView.selectedRange;
|
|
1236
|
+
if (selection.location != NSNotFound) {
|
|
1237
|
+
NSRange glyphRange = [_textView.layoutManager glyphRangeForCharacterRange:NSMakeRange(selection.location, 0)
|
|
1238
|
+
actualCharacterRange:NULL];
|
|
1239
|
+
caretRect = [_textView.layoutManager boundingRectForGlyphRange:glyphRange inTextContainer:_textView.textContainer];
|
|
1240
|
+
caretRect.origin.x += _textView.textContainerInset.left;
|
|
1241
|
+
caretRect.origin.y += _textView.textContainerInset.top;
|
|
1242
|
+
}
|
|
1243
|
+
#endif
|
|
1244
|
+
return caretRect;
|
|
1245
|
+
}
|
|
1246
|
+
|
|
1247
|
+
- (void)requestCaretRect:(NSInteger)requestId
|
|
1248
|
+
{
|
|
1249
|
+
auto emitter = [self getEventEmitter];
|
|
1250
|
+
if (emitter == nullptr) {
|
|
1251
|
+
return;
|
|
1252
|
+
}
|
|
1253
|
+
|
|
1254
|
+
CGRect caretRect = [self computeCaretRect];
|
|
1255
|
+
emitter->onRequestCaretRectResult({
|
|
1256
|
+
.requestId = static_cast<int>(requestId),
|
|
1257
|
+
.x = caretRect.origin.x,
|
|
1258
|
+
.y = caretRect.origin.y,
|
|
1259
|
+
.width = caretRect.size.width,
|
|
1260
|
+
.height = caretRect.size.height,
|
|
1261
|
+
});
|
|
1262
|
+
}
|
|
1263
|
+
|
|
1264
|
+
- (void)handleCommand:(const NSString *)commandName args:(const NSArray *)args
|
|
1265
|
+
{
|
|
1266
|
+
RCTEnrichedMarkdownTextInputHandleCommand(self, commandName, args);
|
|
1267
|
+
}
|
|
1268
|
+
|
|
1269
|
+
#pragma mark - Style state query
|
|
1270
|
+
|
|
1271
|
+
- (BOOL)isEffectiveStyleActive:(ENRMInputStyleType)type atPosition:(NSUInteger)position
|
|
1272
|
+
{
|
|
1273
|
+
BOOL inRange = [_formattingStore isStyleActive:type atPosition:position];
|
|
1274
|
+
NSNumber *key = @(type);
|
|
1275
|
+
if ([_pendingStyleRemovals containsObject:key]) {
|
|
1276
|
+
return NO;
|
|
1277
|
+
}
|
|
1278
|
+
if ([_pendingStyles containsObject:key]) {
|
|
1279
|
+
return YES;
|
|
1280
|
+
}
|
|
1281
|
+
return inRange;
|
|
1282
|
+
}
|
|
1283
|
+
|
|
1284
|
+
#pragma mark - Event emitters
|
|
1285
|
+
|
|
1286
|
+
- (void)emitFormattingChanged
|
|
1287
|
+
{
|
|
1288
|
+
[self emitOnChangeState];
|
|
1289
|
+
if (_emitMarkdown) {
|
|
1290
|
+
[self emitOnChangeMarkdown];
|
|
1291
|
+
}
|
|
1292
|
+
}
|
|
1293
|
+
|
|
1294
|
+
- (std::shared_ptr<EnrichedMarkdownTextInputEventEmitter const>)getEventEmitter
|
|
1295
|
+
{
|
|
1296
|
+
if (_eventEmitter == nullptr || _blockEmitting) {
|
|
1297
|
+
return nullptr;
|
|
1298
|
+
}
|
|
1299
|
+
return std::static_pointer_cast<EnrichedMarkdownTextInputEventEmitter const>(_eventEmitter);
|
|
1300
|
+
}
|
|
1301
|
+
|
|
1302
|
+
- (NSArray<ENRMFormattingRange *> *)allRangesIncludingTransient
|
|
1303
|
+
{
|
|
1304
|
+
NSArray<ENRMFormattingRange *> *transient = [_detectorPipeline allTransientFormattingRanges];
|
|
1305
|
+
if (transient.count == 0) {
|
|
1306
|
+
return _formattingStore.allRanges;
|
|
1307
|
+
}
|
|
1308
|
+
NSMutableArray<ENRMFormattingRange *> *merged = [_formattingStore.allRanges mutableCopy];
|
|
1309
|
+
[merged addObjectsFromArray:transient];
|
|
1310
|
+
return merged;
|
|
1311
|
+
}
|
|
1312
|
+
|
|
1313
|
+
- (void)clearActiveMention:(nullable NSString *)indicatorOverride
|
|
1314
|
+
{
|
|
1315
|
+
NSString *indicator = indicatorOverride ?: _activeMentionIndicator;
|
|
1316
|
+
_activeMentionIndicator = nil;
|
|
1317
|
+
_activeMentionRange = NSMakeRange(NSNotFound, 0);
|
|
1318
|
+
_activeMentionText = @"";
|
|
1319
|
+
|
|
1320
|
+
if (indicator.length > 0) {
|
|
1321
|
+
[self emitOnEndMention:indicator];
|
|
1322
|
+
}
|
|
1323
|
+
}
|
|
1324
|
+
|
|
1325
|
+
- (nullable ENRMInputMentionCandidate *)mentionCandidateAtCursor
|
|
1326
|
+
{
|
|
1327
|
+
NSRange selectedRange = _textView.selectedRange;
|
|
1328
|
+
if (_mentionIndicators.count == 0 || selectedRange.length != 0) {
|
|
1329
|
+
return nil;
|
|
1330
|
+
}
|
|
1331
|
+
|
|
1332
|
+
NSString *plainText = ENRMGetPlainText(_textView);
|
|
1333
|
+
NSUInteger cursor = selectedRange.location;
|
|
1334
|
+
if (cursor > plainText.length) {
|
|
1335
|
+
return nil;
|
|
1336
|
+
}
|
|
1337
|
+
|
|
1338
|
+
NSUInteger start = [ENRMWordsUtils tokenStartInText:plainText beforePosition:cursor];
|
|
1339
|
+
NSString *token = [plainText substringWithRange:NSMakeRange(start, cursor - start)];
|
|
1340
|
+
NSString *matchedIndicator = nil;
|
|
1341
|
+
for (NSString *indicator in _mentionIndicators) {
|
|
1342
|
+
if ([token hasPrefix:indicator]) {
|
|
1343
|
+
matchedIndicator = indicator;
|
|
1344
|
+
break;
|
|
1345
|
+
}
|
|
1346
|
+
}
|
|
1347
|
+
if (matchedIndicator == nil) {
|
|
1348
|
+
return nil;
|
|
1349
|
+
}
|
|
1350
|
+
|
|
1351
|
+
if ([_formattingStore rangeOfType:ENRMInputStyleTypeLink containingPosition:start] != nil) {
|
|
1352
|
+
return nil;
|
|
1353
|
+
}
|
|
1354
|
+
|
|
1355
|
+
return [ENRMInputMentionCandidate candidateWithIndicator:matchedIndicator
|
|
1356
|
+
start:start
|
|
1357
|
+
end:cursor
|
|
1358
|
+
text:[token substringFromIndex:matchedIndicator.length]];
|
|
1359
|
+
}
|
|
1360
|
+
|
|
1361
|
+
- (void)updateActiveMention
|
|
1362
|
+
{
|
|
1363
|
+
ENRMInputMentionCandidate *candidate = [self mentionCandidateAtCursor];
|
|
1364
|
+
if (candidate == nil) {
|
|
1365
|
+
[self clearActiveMention:nil];
|
|
1366
|
+
return;
|
|
1367
|
+
}
|
|
1368
|
+
|
|
1369
|
+
NSString *indicator = candidate.indicator;
|
|
1370
|
+
NSUInteger start = candidate.start;
|
|
1371
|
+
NSUInteger end = candidate.end;
|
|
1372
|
+
NSString *query = candidate.text;
|
|
1373
|
+
|
|
1374
|
+
if (_activeMentionIndicator == nil || ![_activeMentionIndicator isEqualToString:indicator] ||
|
|
1375
|
+
_activeMentionRange.location != start) {
|
|
1376
|
+
if (_activeMentionIndicator != nil) {
|
|
1377
|
+
[self emitOnEndMention:_activeMentionIndicator];
|
|
1378
|
+
}
|
|
1379
|
+
_activeMentionIndicator = indicator;
|
|
1380
|
+
[self emitOnStartMention:indicator];
|
|
1381
|
+
}
|
|
1382
|
+
_activeMentionRange = NSMakeRange(start, end - start);
|
|
1383
|
+
|
|
1384
|
+
if (![_activeMentionText isEqualToString:query]) {
|
|
1385
|
+
_activeMentionText = query;
|
|
1386
|
+
[self emitOnChangeMentionWithIndicator:indicator text:query];
|
|
1387
|
+
}
|
|
1388
|
+
}
|
|
1389
|
+
|
|
1390
|
+
- (BOOL)deleteLinkForReplacementRange:(NSRange)range replacementText:(NSString *)text
|
|
1391
|
+
{
|
|
1392
|
+
if (text.length > 0) {
|
|
1393
|
+
return NO;
|
|
1394
|
+
}
|
|
1395
|
+
|
|
1396
|
+
NSUInteger lookupPosition;
|
|
1397
|
+
if (range.length > 0) {
|
|
1398
|
+
lookupPosition = range.location;
|
|
1399
|
+
} else if (range.location > 0) {
|
|
1400
|
+
lookupPosition = range.location - 1;
|
|
1401
|
+
} else {
|
|
1402
|
+
return NO;
|
|
1403
|
+
}
|
|
1404
|
+
|
|
1405
|
+
ENRMFormattingRange *linkRange = [_formattingStore rangeOfType:ENRMInputStyleTypeLink
|
|
1406
|
+
containingPosition:lookupPosition];
|
|
1407
|
+
if (linkRange == nil) {
|
|
1408
|
+
return NO;
|
|
1409
|
+
}
|
|
1410
|
+
|
|
1411
|
+
[self replaceTextInRange:linkRange.range withText:@"" formattingRanges:@[]];
|
|
1412
|
+
[self clearActiveMention:nil];
|
|
1413
|
+
return YES;
|
|
1414
|
+
}
|
|
1415
|
+
|
|
1416
|
+
- (void)emitOnChangeText
|
|
1417
|
+
{
|
|
1418
|
+
auto emitter = [self getEventEmitter];
|
|
1419
|
+
if (emitter == nullptr) {
|
|
1420
|
+
return;
|
|
1421
|
+
}
|
|
1422
|
+
NSString *plainText = ENRMGetPlainText(_textView);
|
|
1423
|
+
emitter->onChangeText({.value = std::string([plainText UTF8String] ?: "")});
|
|
1424
|
+
}
|
|
1425
|
+
|
|
1426
|
+
- (void)emitOnChangeMarkdown
|
|
1427
|
+
{
|
|
1428
|
+
auto emitter = [self getEventEmitter];
|
|
1429
|
+
if (emitter == nullptr) {
|
|
1430
|
+
return;
|
|
1431
|
+
}
|
|
1432
|
+
NSString *markdown = [ENRMMarkdownSerializer serializeAttributedString:_textView.textStorage
|
|
1433
|
+
ranges:[self allRangesIncludingTransient]];
|
|
1434
|
+
emitter->onChangeMarkdown({.value = std::string([markdown UTF8String] ?: "")});
|
|
1435
|
+
}
|
|
1436
|
+
|
|
1437
|
+
- (void)emitOnChangeSelection
|
|
1438
|
+
{
|
|
1439
|
+
auto emitter = [self getEventEmitter];
|
|
1440
|
+
if (emitter == nullptr) {
|
|
1441
|
+
return;
|
|
1442
|
+
}
|
|
1443
|
+
NSRange selection = _textView.selectedRange;
|
|
1444
|
+
emitter->onChangeSelection({
|
|
1445
|
+
.start = static_cast<int>(selection.location),
|
|
1446
|
+
.end = static_cast<int>(NSMaxRange(selection)),
|
|
1447
|
+
});
|
|
1448
|
+
}
|
|
1449
|
+
|
|
1450
|
+
- (void)emitOnChangeState
|
|
1451
|
+
{
|
|
1452
|
+
auto emitter = [self getEventEmitter];
|
|
1453
|
+
if (emitter == nullptr) {
|
|
1454
|
+
return;
|
|
1455
|
+
}
|
|
1456
|
+
|
|
1457
|
+
NSUInteger cursor = _textView.selectedRange.location;
|
|
1458
|
+
BOOL boldActive = [self isEffectiveStyleActive:ENRMInputStyleTypeStrong atPosition:cursor];
|
|
1459
|
+
BOOL italicActive = [self isEffectiveStyleActive:ENRMInputStyleTypeEmphasis atPosition:cursor];
|
|
1460
|
+
BOOL underlineActive = [self isEffectiveStyleActive:ENRMInputStyleTypeUnderline atPosition:cursor];
|
|
1461
|
+
BOOL strikethroughActive = [self isEffectiveStyleActive:ENRMInputStyleTypeStrikethrough atPosition:cursor];
|
|
1462
|
+
BOOL spoilerActive = [self isEffectiveStyleActive:ENRMInputStyleTypeSpoiler atPosition:cursor];
|
|
1463
|
+
BOOL linkActive = [self isEffectiveStyleActive:ENRMInputStyleTypeLink atPosition:cursor];
|
|
1464
|
+
|
|
1465
|
+
if (_prevState.initialized && _prevState.bold == boldActive && _prevState.italic == italicActive &&
|
|
1466
|
+
_prevState.underline == underlineActive && _prevState.strikethrough == strikethroughActive &&
|
|
1467
|
+
_prevState.spoiler == spoilerActive && _prevState.link == linkActive) {
|
|
1468
|
+
return;
|
|
1469
|
+
}
|
|
1470
|
+
|
|
1471
|
+
_prevState.bold = boldActive;
|
|
1472
|
+
_prevState.italic = italicActive;
|
|
1473
|
+
_prevState.underline = underlineActive;
|
|
1474
|
+
_prevState.strikethrough = strikethroughActive;
|
|
1475
|
+
_prevState.spoiler = spoilerActive;
|
|
1476
|
+
_prevState.link = linkActive;
|
|
1477
|
+
_prevState.initialized = YES;
|
|
1478
|
+
|
|
1479
|
+
emitter->onChangeState({
|
|
1480
|
+
.bold = {.isActive = boldActive},
|
|
1481
|
+
.italic = {.isActive = italicActive},
|
|
1482
|
+
.underline = {.isActive = underlineActive},
|
|
1483
|
+
.strikethrough = {.isActive = strikethroughActive},
|
|
1484
|
+
.spoiler = {.isActive = spoilerActive},
|
|
1485
|
+
.link = {.isActive = linkActive},
|
|
1486
|
+
});
|
|
1487
|
+
}
|
|
1488
|
+
|
|
1489
|
+
- (void)emitCaretRectChangeIfNeeded
|
|
1490
|
+
{
|
|
1491
|
+
auto emitter = [self getEventEmitter];
|
|
1492
|
+
if (emitter == nullptr) {
|
|
1493
|
+
return;
|
|
1494
|
+
}
|
|
1495
|
+
|
|
1496
|
+
CGRect caretRect = [self computeCaretRect];
|
|
1497
|
+
|
|
1498
|
+
if (_prevCaretRect.has_value() && CGRectEqualToRect(_prevCaretRect.value(), caretRect)) {
|
|
1499
|
+
return;
|
|
1500
|
+
}
|
|
1501
|
+
|
|
1502
|
+
_prevCaretRect = caretRect;
|
|
1503
|
+
|
|
1504
|
+
emitter->onCaretRectChange({
|
|
1505
|
+
.x = caretRect.origin.x,
|
|
1506
|
+
.y = caretRect.origin.y,
|
|
1507
|
+
.width = caretRect.size.width,
|
|
1508
|
+
.height = caretRect.size.height,
|
|
1509
|
+
});
|
|
1510
|
+
}
|
|
1511
|
+
|
|
1512
|
+
- (NSArray<NSString *> *)contextMenuItemTexts
|
|
1513
|
+
{
|
|
1514
|
+
return _contextMenuItemTexts ?: @[];
|
|
1515
|
+
}
|
|
1516
|
+
|
|
1517
|
+
- (NSArray<NSString *> *)contextMenuItemIcons
|
|
1518
|
+
{
|
|
1519
|
+
return _contextMenuItemIcons ?: @[];
|
|
1520
|
+
}
|
|
1521
|
+
|
|
1522
|
+
- (void)emitContextMenuItemPress:(NSString *)itemText
|
|
1523
|
+
{
|
|
1524
|
+
auto eventEmitter = [self getEventEmitter];
|
|
1525
|
+
if (eventEmitter == nullptr) {
|
|
1526
|
+
return;
|
|
1527
|
+
}
|
|
1528
|
+
|
|
1529
|
+
NSRange selectedRange = _textView.selectedRange;
|
|
1530
|
+
NSString *selectedText =
|
|
1531
|
+
selectedRange.length > 0 ? [_textView.textStorage.string substringWithRange:selectedRange] : @"";
|
|
1532
|
+
|
|
1533
|
+
auto isActive = [&](ENRMInputStyleType type) -> BOOL {
|
|
1534
|
+
if (selectedRange.length > 0) {
|
|
1535
|
+
return [_formattingStore isStyleActive:type inRange:selectedRange];
|
|
1536
|
+
}
|
|
1537
|
+
return [self isEffectiveStyleActive:type atPosition:selectedRange.location];
|
|
1538
|
+
};
|
|
1539
|
+
|
|
1540
|
+
BOOL boldActive = isActive(ENRMInputStyleTypeStrong);
|
|
1541
|
+
BOOL italicActive = isActive(ENRMInputStyleTypeEmphasis);
|
|
1542
|
+
BOOL underlineActive = isActive(ENRMInputStyleTypeUnderline);
|
|
1543
|
+
BOOL strikethroughActive = isActive(ENRMInputStyleTypeStrikethrough);
|
|
1544
|
+
BOOL spoilerActive = isActive(ENRMInputStyleTypeSpoiler);
|
|
1545
|
+
BOOL linkActive = isActive(ENRMInputStyleTypeLink);
|
|
1546
|
+
|
|
1547
|
+
eventEmitter->onContextMenuItemPress({
|
|
1548
|
+
.itemText = std::string(itemText.UTF8String),
|
|
1549
|
+
.selectedText = std::string(selectedText.UTF8String),
|
|
1550
|
+
.selectionStart = static_cast<int>(selectedRange.location),
|
|
1551
|
+
.selectionEnd = static_cast<int>(NSMaxRange(selectedRange)),
|
|
1552
|
+
.styleState =
|
|
1553
|
+
{
|
|
1554
|
+
.bold = {.isActive = boldActive},
|
|
1555
|
+
.italic = {.isActive = italicActive},
|
|
1556
|
+
.underline = {.isActive = underlineActive},
|
|
1557
|
+
.strikethrough = {.isActive = strikethroughActive},
|
|
1558
|
+
.spoiler = {.isActive = spoilerActive},
|
|
1559
|
+
.link = {.isActive = linkActive},
|
|
1560
|
+
},
|
|
1561
|
+
});
|
|
1562
|
+
}
|
|
1563
|
+
|
|
1564
|
+
- (void)emitOnFocus
|
|
1565
|
+
{
|
|
1566
|
+
auto emitter = [self getEventEmitter];
|
|
1567
|
+
if (emitter == nullptr) {
|
|
1568
|
+
return;
|
|
1569
|
+
}
|
|
1570
|
+
emitter->onInputFocus({});
|
|
1571
|
+
}
|
|
1572
|
+
|
|
1573
|
+
- (void)emitOnBlur
|
|
1574
|
+
{
|
|
1575
|
+
auto emitter = [self getEventEmitter];
|
|
1576
|
+
if (emitter == nullptr) {
|
|
1577
|
+
return;
|
|
1578
|
+
}
|
|
1579
|
+
emitter->onInputBlur({});
|
|
1580
|
+
}
|
|
1581
|
+
|
|
1582
|
+
- (void)emitOnLinkDetectedWithText:(NSString *)text url:(NSString *)url range:(NSRange)range
|
|
1583
|
+
{
|
|
1584
|
+
auto emitter = [self getEventEmitter];
|
|
1585
|
+
if (emitter == nullptr) {
|
|
1586
|
+
return;
|
|
1587
|
+
}
|
|
1588
|
+
emitter->onLinkDetected({
|
|
1589
|
+
.text = std::string([text UTF8String] ?: ""),
|
|
1590
|
+
.url = std::string([url UTF8String] ?: ""),
|
|
1591
|
+
.start = static_cast<int>(range.location),
|
|
1592
|
+
.end = static_cast<int>(range.location + range.length),
|
|
1593
|
+
});
|
|
1594
|
+
}
|
|
1595
|
+
|
|
1596
|
+
- (void)emitOnStartMention:(NSString *)indicator
|
|
1597
|
+
{
|
|
1598
|
+
auto emitter = [self getEventEmitter];
|
|
1599
|
+
if (emitter == nullptr) {
|
|
1600
|
+
return;
|
|
1601
|
+
}
|
|
1602
|
+
emitter->onStartMention({.indicator = std::string([indicator UTF8String] ?: "")});
|
|
1603
|
+
}
|
|
1604
|
+
|
|
1605
|
+
- (void)emitOnChangeMentionWithIndicator:(NSString *)indicator text:(NSString *)text
|
|
1606
|
+
{
|
|
1607
|
+
auto emitter = [self getEventEmitter];
|
|
1608
|
+
if (emitter == nullptr) {
|
|
1609
|
+
return;
|
|
1610
|
+
}
|
|
1611
|
+
emitter->onChangeMention({
|
|
1612
|
+
.indicator = std::string([indicator UTF8String] ?: ""),
|
|
1613
|
+
.text = std::string([text UTF8String] ?: ""),
|
|
1614
|
+
});
|
|
1615
|
+
}
|
|
1616
|
+
|
|
1617
|
+
- (void)emitOnEndMention:(NSString *)indicator
|
|
1618
|
+
{
|
|
1619
|
+
auto emitter = [self getEventEmitter];
|
|
1620
|
+
if (emitter == nullptr) {
|
|
1621
|
+
return;
|
|
1622
|
+
}
|
|
1623
|
+
emitter->onEndMention({.indicator = std::string([indicator UTF8String] ?: "")});
|
|
1624
|
+
}
|
|
1625
|
+
|
|
1626
|
+
#pragma mark - Text edit tracking
|
|
1627
|
+
|
|
1628
|
+
- (void)handleTextChanged
|
|
1629
|
+
{
|
|
1630
|
+
if (ENRMHasMarkedText(_textView)) {
|
|
1631
|
+
return;
|
|
1632
|
+
}
|
|
1633
|
+
|
|
1634
|
+
NSUInteger newLength = ENRMGetPlainText(_textView).length;
|
|
1635
|
+
NSRange selection = _textView.selectedRange;
|
|
1636
|
+
|
|
1637
|
+
NSRange preEditSelection = _preEditSelectedRange;
|
|
1638
|
+
NSUInteger editLocation = preEditSelection.location;
|
|
1639
|
+
NSUInteger deletedLength = 0;
|
|
1640
|
+
NSUInteger insertedLength = 0;
|
|
1641
|
+
|
|
1642
|
+
if (newLength >= _lastTextLength) {
|
|
1643
|
+
NSUInteger netInserted = newLength - _lastTextLength;
|
|
1644
|
+
deletedLength = preEditSelection.length;
|
|
1645
|
+
insertedLength = deletedLength + netInserted;
|
|
1646
|
+
} else {
|
|
1647
|
+
NSUInteger netDeleted = _lastTextLength - newLength;
|
|
1648
|
+
if (preEditSelection.length > 0) {
|
|
1649
|
+
deletedLength = preEditSelection.length;
|
|
1650
|
+
insertedLength = deletedLength > netDeleted ? deletedLength - netDeleted : 0;
|
|
1651
|
+
} else {
|
|
1652
|
+
deletedLength = netDeleted;
|
|
1653
|
+
insertedLength = 0;
|
|
1654
|
+
if (selection.location < editLocation) {
|
|
1655
|
+
editLocation = selection.location;
|
|
1656
|
+
}
|
|
1657
|
+
}
|
|
1658
|
+
}
|
|
1659
|
+
|
|
1660
|
+
[_formattingStore adjustForEditAtLocation:editLocation deletedLength:deletedLength insertedLength:insertedLength];
|
|
1661
|
+
|
|
1662
|
+
if (insertedLength > 0) {
|
|
1663
|
+
NSRange insertedRange = NSMakeRange(editLocation, insertedLength);
|
|
1664
|
+
|
|
1665
|
+
for (NSNumber *styleNum in _pendingStyles) {
|
|
1666
|
+
ENRMFormattingRange *newRange = [ENRMFormattingRange rangeWithType:(ENRMInputStyleType)styleNum.integerValue
|
|
1667
|
+
range:insertedRange];
|
|
1668
|
+
[_formattingStore addRange:newRange];
|
|
1669
|
+
}
|
|
1670
|
+
|
|
1671
|
+
// adjustForEditAtLocation may have expanded an existing range to cover
|
|
1672
|
+
// the insertion — carve out the inserted portion for removed styles.
|
|
1673
|
+
for (NSNumber *styleNum in _pendingStyleRemovals) {
|
|
1674
|
+
[_formattingStore removeType:(ENRMInputStyleType)styleNum.integerValue inRange:insertedRange];
|
|
1675
|
+
}
|
|
1676
|
+
}
|
|
1677
|
+
|
|
1678
|
+
_lastTextLength = newLength;
|
|
1679
|
+
|
|
1680
|
+
#if !TARGET_OS_OSX
|
|
1681
|
+
if (newLength == 0) {
|
|
1682
|
+
[self resetBaseTypingAttributes];
|
|
1683
|
+
}
|
|
1684
|
+
#endif
|
|
1685
|
+
|
|
1686
|
+
[self applyFormatting];
|
|
1687
|
+
|
|
1688
|
+
NSUInteger clampedEditLocation = MIN(editLocation, newLength);
|
|
1689
|
+
NSUInteger clampedInsertedLength = MIN(insertedLength, newLength - clampedEditLocation);
|
|
1690
|
+
[_detectorPipeline processTextChange:ENRMGetPlainText(_textView)
|
|
1691
|
+
modificationRange:NSMakeRange(clampedEditLocation, clampedInsertedLength)];
|
|
1692
|
+
|
|
1693
|
+
[self updatePlaceholderVisibility];
|
|
1694
|
+
[self emitOnChangeText];
|
|
1695
|
+
[self emitOnChangeSelection];
|
|
1696
|
+
[self emitFormattingChanged];
|
|
1697
|
+
[self updateActiveMention];
|
|
1698
|
+
[self emitCaretRectChangeIfNeeded];
|
|
1699
|
+
[self requestHeightUpdate];
|
|
1700
|
+
[self scheduleRelayoutIfNeeded];
|
|
1701
|
+
}
|
|
1702
|
+
|
|
1703
|
+
#pragma mark - Text view delegate
|
|
1704
|
+
|
|
1705
|
+
#if !TARGET_OS_OSX
|
|
1706
|
+
|
|
1707
|
+
- (void)stripLinkTypingAttributes
|
|
1708
|
+
{
|
|
1709
|
+
NSMutableDictionary *attrs = [_textView.typingAttributes mutableCopy];
|
|
1710
|
+
BOOL changed = NO;
|
|
1711
|
+
|
|
1712
|
+
UIColor *linkColor = _formatterStyle.linkColor;
|
|
1713
|
+
UIColor *currentColor = attrs[NSForegroundColorAttributeName];
|
|
1714
|
+
if (currentColor != nil && linkColor != nil && [currentColor isEqual:linkColor]) {
|
|
1715
|
+
attrs[NSForegroundColorAttributeName] = _formatterStyle.baseTextColor;
|
|
1716
|
+
changed = YES;
|
|
1717
|
+
}
|
|
1718
|
+
|
|
1719
|
+
if (attrs[NSUnderlineStyleAttributeName] != nil) {
|
|
1720
|
+
[attrs removeObjectForKey:NSUnderlineStyleAttributeName];
|
|
1721
|
+
changed = YES;
|
|
1722
|
+
}
|
|
1723
|
+
|
|
1724
|
+
if (attrs[NSLinkAttributeName] != nil) {
|
|
1725
|
+
[attrs removeObjectForKey:NSLinkAttributeName];
|
|
1726
|
+
changed = YES;
|
|
1727
|
+
}
|
|
1728
|
+
|
|
1729
|
+
if (changed) {
|
|
1730
|
+
_textView.typingAttributes = attrs;
|
|
1731
|
+
}
|
|
1732
|
+
}
|
|
1733
|
+
|
|
1734
|
+
- (void)manageSelectionBasedChanges
|
|
1735
|
+
{
|
|
1736
|
+
[self stripLinkTypingAttributes];
|
|
1737
|
+
|
|
1738
|
+
if (_textView.selectedRange.length == 0 && !_isTextChanging) {
|
|
1739
|
+
NSString *text = ENRMGetPlainText(_textView);
|
|
1740
|
+
if (text.length > 0) {
|
|
1741
|
+
NSRange paragraphRange = [text paragraphRangeForRange:_textView.selectedRange];
|
|
1742
|
+
NSString *paragraphText = [text substringWithRange:paragraphRange];
|
|
1743
|
+
BOOL isEmpty = paragraphText.length == 0 || [paragraphText isEqualToString:@"\n"];
|
|
1744
|
+
if (isEmpty) {
|
|
1745
|
+
NSMutableDictionary *attrs = [NSMutableDictionary dictionary];
|
|
1746
|
+
attrs[NSFontAttributeName] = _formatterStyle.baseFont;
|
|
1747
|
+
attrs[NSForegroundColorAttributeName] = _formatterStyle.baseTextColor;
|
|
1748
|
+
_textView.typingAttributes = attrs;
|
|
1749
|
+
}
|
|
1750
|
+
}
|
|
1751
|
+
}
|
|
1752
|
+
}
|
|
1753
|
+
|
|
1754
|
+
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
|
|
1755
|
+
{
|
|
1756
|
+
if ([self deleteLinkForReplacementRange:range replacementText:text]) {
|
|
1757
|
+
return NO;
|
|
1758
|
+
}
|
|
1759
|
+
_preEditSelectedRange = _lastSelectedRange;
|
|
1760
|
+
_isTextChanging = YES;
|
|
1761
|
+
[self stripLinkTypingAttributes];
|
|
1762
|
+
return YES;
|
|
1763
|
+
}
|
|
1764
|
+
|
|
1765
|
+
- (void)textViewDidChange:(UITextView *)textView
|
|
1766
|
+
{
|
|
1767
|
+
if (_isApplyingFormatting) {
|
|
1768
|
+
return;
|
|
1769
|
+
}
|
|
1770
|
+
[self handleTextChanged];
|
|
1771
|
+
_isTextChanging = NO;
|
|
1772
|
+
_lastSelectedRange = textView.selectedRange;
|
|
1773
|
+
}
|
|
1774
|
+
|
|
1775
|
+
- (void)textViewDidBeginEditing:(UITextView *)textView
|
|
1776
|
+
{
|
|
1777
|
+
[self emitOnFocus];
|
|
1778
|
+
}
|
|
1779
|
+
|
|
1780
|
+
- (void)textViewDidEndEditing:(UITextView *)textView
|
|
1781
|
+
{
|
|
1782
|
+
[self clearActiveMention:nil];
|
|
1783
|
+
[self emitOnBlur];
|
|
1784
|
+
}
|
|
1785
|
+
|
|
1786
|
+
- (void)textViewDidChangeSelection:(UITextView *)textView
|
|
1787
|
+
{
|
|
1788
|
+
NSRange newSelection = textView.selectedRange;
|
|
1789
|
+
NSRange previousSelection = _lastSelectedRange;
|
|
1790
|
+
_lastSelectedRange = newSelection;
|
|
1791
|
+
|
|
1792
|
+
if (_isApplyingFormatting || _isTextChanging) {
|
|
1793
|
+
return;
|
|
1794
|
+
}
|
|
1795
|
+
|
|
1796
|
+
#if ENRICHED_MARKDOWN_MATH
|
|
1797
|
+
if (_suppressMathChipClearOnce) {
|
|
1798
|
+
// Caret update was triggered by handleTapForMathChip — keep that chip
|
|
1799
|
+
// selected; consume the suppression flag.
|
|
1800
|
+
_suppressMathChipClearOnce = NO;
|
|
1801
|
+
} else {
|
|
1802
|
+
[self clearMathChipSelectionsExcept:NSMakeRange(NSNotFound, 0)];
|
|
1803
|
+
_activeMathChipIndex = NSNotFound;
|
|
1804
|
+
}
|
|
1805
|
+
#endif
|
|
1806
|
+
|
|
1807
|
+
BOOL selectionMoved =
|
|
1808
|
+
newSelection.location != previousSelection.location || newSelection.length != previousSelection.length;
|
|
1809
|
+
|
|
1810
|
+
if (selectionMoved) {
|
|
1811
|
+
[_pendingStyles removeAllObjects];
|
|
1812
|
+
[_pendingStyleRemovals removeAllObjects];
|
|
1813
|
+
}
|
|
1814
|
+
|
|
1815
|
+
[self manageSelectionBasedChanges];
|
|
1816
|
+
|
|
1817
|
+
[self emitOnChangeSelection];
|
|
1818
|
+
[self updateActiveMention];
|
|
1819
|
+
[self emitOnChangeState];
|
|
1820
|
+
[self emitCaretRectChangeIfNeeded];
|
|
1821
|
+
}
|
|
1822
|
+
|
|
1823
|
+
#if ENRICHED_MARKDOWN_MATH && !TARGET_OS_OSX
|
|
1824
|
+
- (void)clearMathChipSelectionsExcept:(NSRange)keepRange
|
|
1825
|
+
{
|
|
1826
|
+
NSTextStorage *storage = _textView.textStorage;
|
|
1827
|
+
if (storage.length == 0)
|
|
1828
|
+
return;
|
|
1829
|
+
__block BOOL anyChanged = NO;
|
|
1830
|
+
__block NSMutableArray<NSValue *> *invalidationRanges = [NSMutableArray array];
|
|
1831
|
+
[storage enumerateAttribute:NSAttachmentAttributeName
|
|
1832
|
+
inRange:NSMakeRange(0, storage.length)
|
|
1833
|
+
options:0
|
|
1834
|
+
usingBlock:^(id value, NSRange range, BOOL *stop) {
|
|
1835
|
+
if (![value isKindOfClass:[ENRMMathInlineAttachment class]])
|
|
1836
|
+
return;
|
|
1837
|
+
ENRMMathInlineAttachment *att = value;
|
|
1838
|
+
BOOL keep = NSEqualRanges(range, keepRange);
|
|
1839
|
+
if (att.isSelected && !keep) {
|
|
1840
|
+
att.isSelected = NO;
|
|
1841
|
+
[att invalidateRender];
|
|
1842
|
+
[invalidationRanges addObject:[NSValue valueWithRange:range]];
|
|
1843
|
+
anyChanged = YES;
|
|
1844
|
+
}
|
|
1845
|
+
}];
|
|
1846
|
+
if (anyChanged) {
|
|
1847
|
+
NSLayoutManager *lm = storage.layoutManagers.firstObject;
|
|
1848
|
+
for (NSValue *v in invalidationRanges) {
|
|
1849
|
+
NSRange r = v.rangeValue;
|
|
1850
|
+
[lm invalidateLayoutForCharacterRange:r actualCharacterRange:NULL];
|
|
1851
|
+
}
|
|
1852
|
+
ENRMSetNeedsDisplay(_textView);
|
|
1853
|
+
}
|
|
1854
|
+
}
|
|
1855
|
+
#else
|
|
1856
|
+
- (void)clearMathChipSelectionsExcept:(NSRange)keepRange
|
|
1857
|
+
{
|
|
1858
|
+
(void)keepRange;
|
|
1859
|
+
}
|
|
1860
|
+
#endif
|
|
1861
|
+
|
|
1862
|
+
#else
|
|
1863
|
+
|
|
1864
|
+
#pragma mark - RCTBackedTextInputDelegate (macOS)
|
|
1865
|
+
|
|
1866
|
+
- (BOOL)textInputShouldBeginEditing
|
|
1867
|
+
{
|
|
1868
|
+
return YES;
|
|
1869
|
+
}
|
|
1870
|
+
|
|
1871
|
+
- (void)textInputDidBeginEditing
|
|
1872
|
+
{
|
|
1873
|
+
[self emitOnFocus];
|
|
1874
|
+
}
|
|
1875
|
+
|
|
1876
|
+
- (BOOL)textInputShouldEndEditing
|
|
1877
|
+
{
|
|
1878
|
+
return YES;
|
|
1879
|
+
}
|
|
1880
|
+
|
|
1881
|
+
- (void)textInputDidEndEditing
|
|
1882
|
+
{
|
|
1883
|
+
[self clearActiveMention:nil];
|
|
1884
|
+
[self emitOnBlur];
|
|
1885
|
+
}
|
|
1886
|
+
|
|
1887
|
+
- (BOOL)textInputShouldReturn
|
|
1888
|
+
{
|
|
1889
|
+
return NO;
|
|
1890
|
+
}
|
|
1891
|
+
|
|
1892
|
+
- (void)textInputDidReturn
|
|
1893
|
+
{
|
|
1894
|
+
}
|
|
1895
|
+
|
|
1896
|
+
- (BOOL)textInputShouldSubmitOnReturn
|
|
1897
|
+
{
|
|
1898
|
+
return NO;
|
|
1899
|
+
}
|
|
1900
|
+
|
|
1901
|
+
- (nullable NSString *)textInputShouldChangeText:(NSString *)text inRange:(NSRange)range
|
|
1902
|
+
{
|
|
1903
|
+
if ([self deleteLinkForReplacementRange:range replacementText:text]) {
|
|
1904
|
+
return nil;
|
|
1905
|
+
}
|
|
1906
|
+
_preEditSelectedRange = _lastSelectedRange;
|
|
1907
|
+
_isTextChanging = YES;
|
|
1908
|
+
return text;
|
|
1909
|
+
}
|
|
1910
|
+
|
|
1911
|
+
- (void)textInputDidChange
|
|
1912
|
+
{
|
|
1913
|
+
if (_isApplyingFormatting) {
|
|
1914
|
+
_isTextChanging = NO;
|
|
1915
|
+
return;
|
|
1916
|
+
}
|
|
1917
|
+
[self handleTextChanged];
|
|
1918
|
+
_isTextChanging = NO;
|
|
1919
|
+
_lastSelectedRange = _textView.selectedRange;
|
|
1920
|
+
}
|
|
1921
|
+
|
|
1922
|
+
- (void)textInputDidChangeSelection
|
|
1923
|
+
{
|
|
1924
|
+
_lastSelectedRange = _textView.selectedRange;
|
|
1925
|
+
|
|
1926
|
+
if (_isApplyingFormatting || _isTextChanging) {
|
|
1927
|
+
return;
|
|
1928
|
+
}
|
|
1929
|
+
|
|
1930
|
+
[_pendingStyles removeAllObjects];
|
|
1931
|
+
[_pendingStyleRemovals removeAllObjects];
|
|
1932
|
+
|
|
1933
|
+
[self emitOnChangeSelection];
|
|
1934
|
+
[self updateActiveMention];
|
|
1935
|
+
[self emitOnChangeState];
|
|
1936
|
+
[self emitCaretRectChangeIfNeeded];
|
|
1937
|
+
}
|
|
1938
|
+
|
|
1939
|
+
// @required stubs for RCTBackedTextInputDelegate — RCTUITextView's internal adapter
|
|
1940
|
+
// calls these via textInputDelegate; omitting any causes silent failures or crashes.
|
|
1941
|
+
|
|
1942
|
+
- (BOOL)textInputShouldHandleDeleteBackward:(id<RCTBackedTextInputViewProtocol>)sender
|
|
1943
|
+
{
|
|
1944
|
+
return YES;
|
|
1945
|
+
}
|
|
1946
|
+
|
|
1947
|
+
- (BOOL)textInputShouldHandleDeleteForward:(id<RCTBackedTextInputViewProtocol>)sender
|
|
1948
|
+
{
|
|
1949
|
+
return YES;
|
|
1950
|
+
}
|
|
1951
|
+
|
|
1952
|
+
- (BOOL)textInputShouldHandleKeyEvent:(NSEvent *)event
|
|
1953
|
+
{
|
|
1954
|
+
return YES;
|
|
1955
|
+
}
|
|
1956
|
+
|
|
1957
|
+
- (BOOL)hasKeyDownEventOrKeyUpEvent:(NSString *)key
|
|
1958
|
+
{
|
|
1959
|
+
return NO;
|
|
1960
|
+
}
|
|
1961
|
+
|
|
1962
|
+
- (NSDragOperation)textInputDraggingEntered:(id<NSDraggingInfo>)draggingInfo
|
|
1963
|
+
{
|
|
1964
|
+
return NSDragOperationNone;
|
|
1965
|
+
}
|
|
1966
|
+
|
|
1967
|
+
- (void)textInputDraggingExited:(id<NSDraggingInfo>)draggingInfo
|
|
1968
|
+
{
|
|
1969
|
+
}
|
|
1970
|
+
|
|
1971
|
+
- (BOOL)textInputShouldHandleDragOperation:(id<NSDraggingInfo>)draggingInfo
|
|
1972
|
+
{
|
|
1973
|
+
return YES;
|
|
1974
|
+
}
|
|
1975
|
+
|
|
1976
|
+
- (void)textInputDidCancel
|
|
1977
|
+
{
|
|
1978
|
+
}
|
|
1979
|
+
|
|
1980
|
+
- (BOOL)textInputShouldHandlePaste:(id<RCTBackedTextInputViewProtocol>)sender
|
|
1981
|
+
{
|
|
1982
|
+
return YES;
|
|
1983
|
+
}
|
|
1984
|
+
|
|
1985
|
+
- (void)automaticSpellingCorrectionDidChange:(BOOL)enabled
|
|
1986
|
+
{
|
|
1987
|
+
}
|
|
1988
|
+
|
|
1989
|
+
- (void)continuousSpellCheckingDidChange:(BOOL)enabled
|
|
1990
|
+
{
|
|
1991
|
+
}
|
|
1992
|
+
|
|
1993
|
+
- (void)grammarCheckingDidChange:(BOOL)enabled
|
|
1994
|
+
{
|
|
1995
|
+
}
|
|
1996
|
+
|
|
1997
|
+
- (void)submitOnKeyDownIfNeeded:(NSEvent *)event
|
|
1998
|
+
{
|
|
1999
|
+
}
|
|
2000
|
+
|
|
2001
|
+
#endif
|
|
2002
|
+
|
|
2003
|
+
@end
|
|
2004
|
+
|
|
2005
|
+
Class<RCTComponentViewProtocol> EnrichedMarkdownTextInputCls(void)
|
|
2006
|
+
{
|
|
2007
|
+
return EnrichedMarkdownTextInput.class;
|
|
2008
|
+
}
|