react-native-enriched-markdown-scaffold 0.7.4-scaffold.9 → 1.0.2-scaffold.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +54 -8
- package/ReactNativeEnrichedMarkdown.podspec +82 -73
- package/android/build.gradle +186 -1
- package/android/consumer-rules.pro +1 -1
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownManagerDelegate.java +9 -0
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownManagerInterface.java +3 -0
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextInputManagerDelegate.java +24 -0
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextInputManagerInterface.java +8 -0
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextManagerDelegate.java +9 -0
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextManagerInterface.java +3 -0
- package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/EventEmitters.cpp +75 -0
- package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/EventEmitters.h +63 -0
- package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/Props.cpp +35 -0
- package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/Props.h +886 -23
- package/android/src/main/baseline-prof.txt +1 -1
- package/android/src/main/cpp/jni-adapter.cpp +74 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdown.kt +189 -13
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownInternalText.kt +17 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownManager.kt +50 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownText.kt +48 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownTextLayoutManager.kt +10 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownTextManager.kt +42 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/MeasurementStore.kt +82 -4
- package/android/src/main/java/com/swmansion/enriched/markdown/events/CopyPressEvent.kt +24 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/EnrichedMarkdownTextInputManager.kt +54 -4
- package/android/src/main/java/com/swmansion/enriched/markdown/input/EnrichedMarkdownTextInputView.kt +901 -462
- package/android/src/main/java/com/swmansion/enriched/markdown/input/MarkdownClipboard.kt +42 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/BlockEditCoordinator.kt +196 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/ClipboardCoordinator.kt +73 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/EditContext.kt +19 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/EditPipeline.kt +248 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/EditSession.kt +52 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/InputConnectionWrapper.kt +101 -7
- package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/LinkCoordinator.kt +69 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/MarkdownTextWatcher.kt +3 -3
- package/android/src/main/java/com/swmansion/enriched/markdown/input/editing/MentionCoordinator.kt +118 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnChangeStateEvent.kt +26 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnContextMenuItemPressEvent.kt +26 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnInputKeyPressEvent.kt +24 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/events/OnPasteEvent.kt +24 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/BlockStore.kt +254 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/FormattingStore.kt +80 -87
- package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/InputFormatter.kt +109 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/InputParser.kt +116 -22
- package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/MarkdownSerializer.kt +167 -38
- package/android/src/main/java/com/swmansion/enriched/markdown/input/formatting/RangeEditAdjustment.kt +149 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/layout/InputEventEmitter.kt +66 -5
- package/android/src/main/java/com/swmansion/enriched/markdown/input/layout/InputMeasurementStore.kt +4 -2
- package/android/src/main/java/com/swmansion/enriched/markdown/input/model/BlockRange.kt +27 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/model/BlockType.kt +48 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/model/FormattingRange.kt +9 -4
- package/android/src/main/java/com/swmansion/enriched/markdown/input/model/InputFormatterStyle.kt +39 -2
- package/android/src/main/java/com/swmansion/enriched/markdown/input/model/MathAtom.kt +20 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/model/MathChipStyle.kt +1 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/input/model/MutableRangeBounds.kt +11 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/spans/InputBulletSpan.kt +82 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/spans/InputHeadingSpan.kt +58 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/spans/InputListItemSpacingSpan.kt +37 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/spans/InputOrderedListMarkerSpan.kt +63 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/styles/BlockHandler.kt +54 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/styles/HeadingBlockHandler.kt +27 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/styles/OrderedListBlockHandler.kt +38 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/styles/UnorderedListBlockHandler.kt +37 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/input/toolbar/InputContextMenu.kt +8 -26
- package/android/src/main/java/com/swmansion/enriched/markdown/parser/MarkdownASTNode.kt +1 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/parser/Parser.kt +1 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/BlockStyleContext.kt +9 -2
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/BlockquoteRenderer.kt +100 -12
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/CodeBlockRenderer.kt +16 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/HeadingRenderer.kt +4 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListContextManager.kt +2 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListItemRenderer.kt +74 -18
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListRenderer.kt +43 -4
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/NodeRenderer.kt +9 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/SoftBreakRenderer.kt +16 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/renderer/SpanStyleCache.kt +30 -27
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/BaseListSpan.kt +24 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/BlockquoteSpan.kt +174 -24
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/CodeBackgroundSpan.kt +27 -3
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/CodeBlockSpan.kt +13 -16
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/CodeSpan.kt +1 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/EmphasisSpan.kt +1 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/ImageSpan.kt +182 -46
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/ListItemSpacingSpan.kt +33 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/ListMarkerAnchorSpan.kt +38 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/OrderedListSpan.kt +2 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/StrongSpan.kt +1 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/TaskListSpan.kt +3 -2
- package/android/src/main/java/com/swmansion/enriched/markdown/spans/UnorderedListSpan.kt +3 -2
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/BlockquoteStyle.kt +6 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/CodeBlockStyle.kt +26 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/ImageStyle.kt +7 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/ListStyle.kt +4 -1
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/StyleConfig.kt +13 -4
- package/android/src/main/java/com/swmansion/enriched/markdown/styles/TableStyle.kt +6 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/CodeBlockHighlighter.kt +90 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/CodeBlockNode.kt +57 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/FeatureFlags.kt +1 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/MarkdownSegment.kt +9 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/MarkdownViewManagerUtils.kt +37 -7
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/ReadableMapExtensions.kt +3 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/RenderedSegment.kt +10 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/SegmentSignature.kt +1 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/StreamingMarkdownFilter.kt +83 -5
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/common/serialization/MarkdownASTSerializer.kt +4 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/input/MarkdownStyleParser.kt +74 -44
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/input/PasteTextUtils.kt +20 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/ImageCache.kt +26 -3
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/ImageDownloader.kt +22 -9
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/LocalImageLoader.kt +161 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/extensions/TextPaintExtensions.kt +23 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/interaction/CheckboxTouchHelper.kt +7 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/interaction/TaskListTapUtils.kt +41 -21
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/span/BlockSpacing.kt +15 -8
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/LinkLongPressMovementMethod.kt +58 -27
- package/android/src/main/java/com/swmansion/enriched/markdown/utils/text/view/SelectionActionMode.kt +49 -15
- package/android/src/main/java/com/swmansion/enriched/markdown/views/BlockMenuOptions.kt +45 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/views/CodeBlockContainerView.kt +396 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/views/ContextMenuPopup.kt +9 -6
- package/android/src/main/java/com/swmansion/enriched/markdown/views/CopyGlyph.kt +101 -0
- package/android/src/main/java/com/swmansion/enriched/markdown/views/TableContainerView.kt +36 -9
- package/android/src/main/jni/CMakeLists.txt +53 -0
- package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownContainerShadowNode.cpp +10 -0
- package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownContainerShadowNode.h +11 -2
- package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextShadowNode.cpp +10 -0
- package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextShadowNode.h +12 -2
- package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextState.cpp +9 -0
- package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextState.h +24 -0
- package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/conversions.h +16 -0
- package/android/src/math/java/com/swmansion/enriched/markdown/input/math/MathChipControllerImpl.kt +21 -4
- package/android/src/math/java/com/swmansion/enriched/markdown/renderer/MathInlineRenderer.kt +7 -2
- package/android/src/math/java/com/swmansion/enriched/markdown/spans/MathChipSpan.kt +1 -1
- package/android/src/math/java/com/swmansion/enriched/markdown/views/MathContainerView.kt +6 -4
- package/cpp/highlight/CodeBlockHighlighter.cpp +284 -0
- package/cpp/highlight/CodeBlockHighlighter.hpp +66 -0
- package/cpp/highlight/CodeBlockLanguages.cpp +138 -0
- package/cpp/highlight/CodeBlockLanguages.hpp +25 -0
- package/cpp/highlight/HighlightGrammars.hpp +28 -0
- package/cpp/highlight/code_highlight_podspec.rb +211 -0
- package/cpp/highlight/gen-registry.mjs +155 -0
- package/cpp/highlight/grammar-versions.json +159 -0
- package/cpp/highlight/vendor/generated/generated_queries.h +1665 -0
- package/cpp/highlight/vendor/generated/generated_registry.cpp +59 -0
- package/cpp/parser/MD4CParser.cpp +173 -61
- package/cpp/parser/MD4CParser.hpp +1 -0
- package/cpp/parser/MarkdownASTNode.hpp +2 -1
- package/cpp/wasm/ASTSerializer.cpp +2 -0
- package/cpp/wasm/build.sh +1 -0
- package/cpp/wasm/md4c_wasm.cpp +3 -1
- package/docs/ACCESSIBILITY.md +14 -2
- package/docs/API_REFERENCE.md +234 -12
- package/docs/BREAKING_CHANGES.md +129 -0
- package/docs/CODE_HIGHLIGHT.md +133 -0
- package/docs/COPY_OPTIONS.md +47 -3
- package/docs/ELEMENTS_STRUCTURE.md +52 -4
- package/docs/IMAGE_CACHING.md +30 -0
- package/docs/INPUT.md +108 -11
- package/docs/LATEX_MATH.md +87 -45
- package/docs/MACOS.md +1 -1
- package/docs/MARKDOWN_STREAMING.md +27 -1
- package/docs/NATIVE_ASSETS.md +127 -0
- package/docs/RTL.md +1 -1
- package/docs/STYLES.md +46 -6
- package/docs/TESTING.md +112 -0
- package/docs/TEXT.md +16 -6
- package/docs/WEB.md +3 -1
- package/ios/EnrichedMarkdown.h +7 -0
- package/ios/EnrichedMarkdown.mm +284 -75
- package/ios/EnrichedMarkdownText.h +7 -0
- package/ios/EnrichedMarkdownText.mm +101 -73
- package/ios/attachments/ENRMImageAttachment.h +9 -0
- package/ios/attachments/ENRMImageAttachment.m +143 -40
- package/ios/attachments/ENRMMathInlineAttachment.h +2 -0
- package/ios/attachments/ENRMMathInlineAttachment.m +48 -81
- package/ios/attachments/ENRMMathInlineAttachmentShared.h +2 -0
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/EventEmitters.cpp +75 -0
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/EventEmitters.h +63 -0
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/Props.cpp +35 -0
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/Props.h +886 -23
- package/ios/generated/ReactCodegen/EnrichedMarkdownTextSpec/RCTComponentViewHelpers.h +131 -0
- package/ios/input/ENRMAutoLinkDetector.h +2 -1
- package/ios/input/ENRMAutoLinkDetector.mm +79 -41
- package/ios/input/ENRMBlockEditCoordinator.h +71 -0
- package/ios/input/ENRMBlockEditCoordinator.mm +195 -0
- package/ios/input/ENRMBlockRange.h +28 -0
- package/ios/input/ENRMBlockRange.mm +30 -0
- package/ios/input/ENRMBlockStore.h +56 -0
- package/ios/input/ENRMBlockStore.mm +275 -0
- package/ios/input/ENRMClipboardCoordinator.h +45 -0
- package/ios/input/ENRMClipboardCoordinator.mm +120 -0
- package/ios/input/ENRMDetectorPipeline.h +2 -1
- package/ios/input/ENRMEditPipeline.h +76 -0
- package/ios/input/ENRMEditPipeline.mm +228 -0
- package/ios/input/ENRMEditSession.h +36 -0
- package/ios/input/ENRMEditSession.mm +63 -0
- package/ios/input/ENRMFormattingStore.h +17 -0
- package/ios/input/ENRMFormattingStore.mm +95 -105
- package/ios/input/ENRMInputBlockType.h +91 -0
- package/ios/input/ENRMInputBlockType.mm +5 -0
- package/ios/input/ENRMInputDecorationDrawer.h +18 -0
- package/ios/input/ENRMInputEventEmitter.h +56 -0
- package/ios/input/ENRMInputEventEmitter.mm +308 -0
- package/ios/input/ENRMInputFormatter.h +29 -69
- package/ios/input/ENRMInputFormatter.mm +216 -124
- package/ios/input/ENRMInputFormatterStyle.h +99 -0
- package/ios/input/ENRMInputFormatterStyle.mm +188 -0
- package/ios/input/ENRMInputLayoutManager.h +9 -0
- package/ios/input/ENRMInputLayoutManager.mm +30 -0
- package/ios/input/ENRMInputListMarkerDrawer.h +32 -0
- package/ios/input/ENRMInputListMarkerDrawer.mm +426 -0
- package/ios/input/ENRMInputParser.h +5 -6
- package/ios/input/ENRMInputParser.mm +461 -178
- package/ios/input/ENRMInputRemend.mm +2 -2
- package/ios/input/ENRMInputStyleStateBuilder.h +40 -0
- package/ios/input/ENRMInputStyleStateBuilder.mm +60 -0
- package/ios/input/ENRMInputTextView.mm +103 -8
- package/ios/input/ENRMInputTypingAttributesController.h +42 -0
- package/ios/input/ENRMInputTypingAttributesController.mm +203 -0
- package/ios/input/ENRMLinkCoordinator.h +41 -0
- package/ios/input/ENRMLinkCoordinator.mm +89 -0
- package/ios/input/ENRMMarkdownSerializer.h +29 -5
- package/ios/input/ENRMMarkdownSerializer.mm +170 -48
- package/ios/input/ENRMMathAtom.h +26 -0
- package/ios/input/ENRMMathAtom.mm +12 -0
- package/ios/input/ENRMMentionCoordinator.h +45 -0
- package/ios/input/ENRMMentionCoordinator.mm +167 -0
- package/ios/input/ENRMRangeEditAdjustment.h +38 -0
- package/ios/input/ENRMRangeEditAdjustment.mm +91 -0
- package/ios/input/ENRMRangeStoreUtils.h +39 -0
- package/ios/input/EnrichedMarkdownTextInput+ContextMenu.mm +6 -6
- package/ios/input/EnrichedMarkdownTextInput+Internal.h +11 -3
- package/ios/input/EnrichedMarkdownTextInput.h +7 -1
- package/ios/input/EnrichedMarkdownTextInput.mm +1089 -1023
- package/ios/input/InputStylePropsUtils.h +109 -68
- package/ios/input/internals/EnrichedMarkdownTextInputShadowNode.mm +2 -1
- package/ios/input/styles/ENRMBlockHandler.h +46 -0
- package/ios/input/styles/ENRMHeadingBlockHandler.h +15 -0
- package/ios/input/styles/ENRMHeadingBlockHandler.mm +38 -0
- package/ios/input/styles/ENRMOrderedListBlockHandler.h +14 -0
- package/ios/input/styles/ENRMOrderedListBlockHandler.mm +48 -0
- package/ios/input/styles/ENRMUnorderedListBlockHandler.h +15 -0
- package/ios/input/styles/ENRMUnorderedListBlockHandler.mm +51 -0
- package/ios/internals/ENRMViewFreeMeasurement.h +331 -0
- package/ios/internals/EnrichedMarkdownShadowNode.h +1 -3
- package/ios/internals/EnrichedMarkdownShadowNode.mm +16 -20
- package/ios/internals/EnrichedMarkdownTextShadowNode.h +1 -3
- package/ios/internals/EnrichedMarkdownTextShadowNode.mm +15 -20
- package/ios/internals/MeasurementCache.h +33 -7
- package/ios/internals/ShadowMeasurementUtils.h +63 -58
- package/ios/math/ENRMMathChipController.h +74 -0
- package/ios/math/ENRMMathChipController.mm +476 -0
- package/ios/math/ENRMRaTeXBridge.swift +4 -1
- package/ios/parser/ENRMMarkdownParser.h +1 -8
- package/ios/parser/ENRMMarkdownParser.mm +2 -11
- package/ios/parser/MarkdownASTNode.h +2 -1
- package/ios/parser/MarkdownParserBridge.mm +4 -0
- package/ios/renderer/AttributedRenderer.m +20 -2
- package/ios/renderer/BaseRenderer.h +17 -2
- package/ios/renderer/BaseRenderer.m +30 -0
- package/ios/renderer/BlockquoteRenderer.h +1 -1
- package/ios/renderer/BlockquoteRenderer.m +144 -35
- package/ios/renderer/CodeBlockRenderer.h +1 -1
- package/ios/renderer/CodeBlockRenderer.m +27 -23
- package/ios/renderer/CodeRenderer.h +1 -1
- package/ios/renderer/CodeRenderer.m +3 -1
- package/ios/renderer/ENRMImageRenderer.h +1 -1
- package/ios/renderer/ENRMImageRenderer.m +5 -1
- package/ios/renderer/ENRMMathInlineRenderer.h +1 -1
- package/ios/renderer/ENRMMathInlineRenderer.m +5 -1
- package/ios/renderer/ENRMSpoilerRenderer.h +1 -1
- package/ios/renderer/ENRMSpoilerRenderer.m +3 -1
- package/ios/renderer/EmphasisRenderer.h +1 -1
- package/ios/renderer/EmphasisRenderer.m +3 -1
- package/ios/renderer/HeadingRenderer.h +1 -1
- package/ios/renderer/HeadingRenderer.m +13 -6
- package/ios/renderer/HighlightRenderer.h +1 -1
- package/ios/renderer/HighlightRenderer.m +3 -1
- package/ios/renderer/LinkRenderer.h +1 -1
- package/ios/renderer/LinkRenderer.m +3 -1
- package/ios/renderer/ListItemRenderer.h +13 -1
- package/ios/renderer/ListItemRenderer.m +102 -44
- package/ios/renderer/ListRenderer.h +2 -2
- package/ios/renderer/ListRenderer.m +63 -25
- package/ios/renderer/ParagraphRenderer.h +1 -1
- package/ios/renderer/ParagraphRenderer.m +16 -8
- package/ios/renderer/RenderContext.h +10 -0
- package/ios/renderer/RenderContext.m +44 -0
- package/ios/renderer/RendererFactory.m +14 -0
- package/ios/renderer/StrikethroughRenderer.h +1 -1
- package/ios/renderer/StrikethroughRenderer.m +3 -1
- package/ios/renderer/StrongRenderer.h +1 -1
- package/ios/renderer/StrongRenderer.m +3 -1
- package/ios/renderer/SubscriptRenderer.h +1 -1
- package/ios/renderer/SubscriptRenderer.m +3 -1
- package/ios/renderer/SuperscriptRenderer.h +1 -1
- package/ios/renderer/SuperscriptRenderer.m +3 -1
- package/ios/renderer/TextRenderer.h +2 -2
- package/ios/renderer/TextRenderer.m +3 -1
- package/ios/renderer/ThematicBreakRenderer.h +1 -1
- package/ios/renderer/ThematicBreakRenderer.m +3 -1
- package/ios/renderer/UnderlineRenderer.h +1 -1
- package/ios/renderer/UnderlineRenderer.m +3 -1
- package/ios/styles/StyleConfig.h +22 -0
- package/ios/styles/StyleConfig.mm +132 -0
- package/ios/utils/BlockquoteBorder.h +6 -0
- package/ios/utils/BlockquoteBorder.m +249 -52
- package/ios/utils/CodeBlockBackground.m +16 -2
- package/ios/utils/ENRMAtomicSize.h +65 -0
- package/ios/utils/ENRMBlockMenu.h +57 -0
- package/ios/utils/ENRMCodeBlockContent.h +37 -0
- package/ios/utils/ENRMCodeBlockContent.mm +79 -0
- package/ios/utils/ENRMCodeBlockHighlighter.h +37 -0
- package/ios/utils/ENRMCodeBlockHighlighter.mm +51 -0
- package/ios/utils/ENRMFeatureFlags.h +7 -0
- package/ios/utils/ENRMImageDownloader.h +11 -1
- package/ios/utils/ENRMImageDownloader.m +60 -16
- package/ios/utils/ENRMLocalImageLoader.h +31 -0
- package/ios/utils/ENRMLocalImageLoader.m +68 -0
- package/ios/utils/ENRMMathFallback.h +26 -0
- package/ios/utils/ENRMMathFallback.m +18 -0
- package/ios/utils/ENRMTextViewSetup.h +35 -17
- package/ios/utils/EditMenuUtils.h +22 -5
- package/ios/utils/EditMenuUtils.m +53 -9
- package/ios/utils/ImageRequestHeaderUtils.h +35 -0
- package/ios/utils/LastElementUtils.h +1 -0
- package/ios/utils/ListMarkerDrawer.m +29 -42
- package/ios/utils/MarkdownASTSerializer.m +4 -0
- package/ios/utils/ParagraphStyleUtils.h +5 -0
- package/ios/utils/ParagraphStyleUtils.m +77 -17
- package/ios/utils/RenderedMarkdownSegment.h +13 -1
- package/ios/utils/RenderedMarkdownSegment.m +20 -0
- package/ios/utils/SegmentRenderer.m +17 -4
- package/ios/utils/StreamingMarkdownFilter.h +11 -1
- package/ios/utils/StreamingMarkdownFilter.m +98 -2
- package/ios/utils/StylePropsUtils.h +63 -0
- package/ios/utils/TaskListTapUtils.m +24 -0
- package/ios/views/ENRMCodeBlockContainerView.h +53 -0
- package/ios/views/ENRMCodeBlockContainerView.m +559 -0
- package/ios/views/ENRMMathContainerView.h +16 -0
- package/ios/views/ENRMMathContainerView.m +74 -19
- package/ios/views/TableContainerView.h +22 -0
- package/ios/views/TableContainerView.m +261 -175
- package/jest.d.ts +1 -0
- package/jest.js +5 -0
- package/lib/module/EnrichedMarkdownNativeComponent.ts +73 -0
- package/lib/module/EnrichedMarkdownTextInput.js +84 -5
- package/lib/module/EnrichedMarkdownTextInput.js.map +1 -1
- package/lib/module/EnrichedMarkdownTextInputNativeComponent.ts +78 -5
- package/lib/module/EnrichedMarkdownTextNativeComponent.ts +74 -0
- package/lib/module/headingDefaults.js +34 -0
- package/lib/module/headingDefaults.js.map +1 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/jest/index.js +191 -0
- package/lib/module/jest/index.js.map +1 -0
- package/lib/module/native/EnrichedMarkdownText.js +37 -5
- package/lib/module/native/EnrichedMarkdownText.js.map +1 -1
- package/lib/module/normalizeMarkdownStyle.js +81 -19
- package/lib/module/normalizeMarkdownStyle.js.map +1 -1
- package/lib/module/normalizeMarkdownStyle.web.js +56 -18
- package/lib/module/normalizeMarkdownStyle.web.js.map +1 -1
- package/lib/module/normalizeMarkdownTextInputStyle.js +62 -15
- package/lib/module/normalizeMarkdownTextInputStyle.js.map +1 -1
- package/lib/module/normalizeMenuItem.js +1 -1
- package/lib/module/utils/textInputState.js +26 -0
- package/lib/module/utils/textInputState.js.map +1 -0
- package/lib/module/web/EnrichedMarkdownText.js +9 -5
- package/lib/module/web/EnrichedMarkdownText.js.map +1 -1
- package/lib/module/web/parseMarkdown.js +4 -3
- package/lib/module/web/parseMarkdown.js.map +1 -1
- package/lib/module/web/renderers/InlineRenderers.js +6 -0
- package/lib/module/web/renderers/InlineRenderers.js.map +1 -1
- package/lib/module/web/renderers/ListRenderers.js +7 -2
- package/lib/module/web/renderers/ListRenderers.js.map +1 -1
- package/lib/module/web/renderers/index.js +7 -4
- package/lib/module/web/renderers/index.js.map +1 -1
- package/lib/module/web/styles.js +83 -6
- package/lib/module/web/styles.js.map +1 -1
- package/lib/module/web/utils.js +1 -0
- package/lib/module/web/utils.js.map +1 -1
- package/lib/module/web/wasm/md4c.js +0 -0
- package/lib/module/web/wasm/md4c.js.map +1 -1
- package/lib/typescript/src/EnrichedMarkdownNativeComponent.d.ts +66 -0
- package/lib/typescript/src/EnrichedMarkdownNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/EnrichedMarkdownTextInput.d.ts +94 -9
- package/lib/typescript/src/EnrichedMarkdownTextInput.d.ts.map +1 -1
- package/lib/typescript/src/EnrichedMarkdownTextInputNativeComponent.d.ts +69 -5
- package/lib/typescript/src/EnrichedMarkdownTextInputNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/EnrichedMarkdownTextNativeComponent.d.ts +66 -0
- package/lib/typescript/src/EnrichedMarkdownTextNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/headingDefaults.d.ts +9 -0
- package/lib/typescript/src/headingDefaults.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +2 -2
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/index.web.d.ts +1 -1
- package/lib/typescript/src/index.web.d.ts.map +1 -1
- package/lib/typescript/src/jest/index.d.ts +6 -0
- package/lib/typescript/src/jest/index.d.ts.map +1 -0
- package/lib/typescript/src/native/EnrichedMarkdownText.d.ts +3 -3
- package/lib/typescript/src/native/EnrichedMarkdownText.d.ts.map +1 -1
- package/lib/typescript/src/normalizeMarkdownStyle.d.ts.map +1 -1
- package/lib/typescript/src/normalizeMarkdownStyle.web.d.ts.map +1 -1
- package/lib/typescript/src/normalizeMarkdownTextInputStyle.d.ts +19 -5
- package/lib/typescript/src/normalizeMarkdownTextInputStyle.d.ts.map +1 -1
- package/lib/typescript/src/types/MarkdownStyle.d.ts +72 -0
- package/lib/typescript/src/types/MarkdownStyle.d.ts.map +1 -1
- package/lib/typescript/src/types/MarkdownStyleInternal.d.ts +27 -0
- package/lib/typescript/src/types/MarkdownStyleInternal.d.ts.map +1 -1
- package/lib/typescript/src/types/MarkdownTextProps.d.ts +104 -9
- package/lib/typescript/src/types/MarkdownTextProps.d.ts.map +1 -1
- package/lib/typescript/src/types/MarkdownTextProps.web.d.ts +19 -0
- package/lib/typescript/src/types/MarkdownTextProps.web.d.ts.map +1 -1
- package/lib/typescript/src/types/events.d.ts +19 -0
- package/lib/typescript/src/types/events.d.ts.map +1 -1
- package/lib/typescript/src/utils/textInputState.d.ts +24 -0
- package/lib/typescript/src/utils/textInputState.d.ts.map +1 -0
- package/lib/typescript/src/web/EnrichedMarkdownText.d.ts +1 -1
- package/lib/typescript/src/web/EnrichedMarkdownText.d.ts.map +1 -1
- package/lib/typescript/src/web/parseMarkdown.d.ts +1 -1
- package/lib/typescript/src/web/parseMarkdown.d.ts.map +1 -1
- package/lib/typescript/src/web/renderers/InlineRenderers.d.ts.map +1 -1
- package/lib/typescript/src/web/renderers/ListRenderers.d.ts.map +1 -1
- package/lib/typescript/src/web/renderers/index.d.ts +2 -1
- package/lib/typescript/src/web/renderers/index.d.ts.map +1 -1
- package/lib/typescript/src/web/styles.d.ts +2 -1
- package/lib/typescript/src/web/styles.d.ts.map +1 -1
- package/lib/typescript/src/web/types.d.ts +6 -2
- package/lib/typescript/src/web/types.d.ts.map +1 -1
- package/lib/typescript/src/web/utils.d.ts.map +1 -1
- package/package.json +36 -9
- package/postinstall.mjs +131 -0
- package/ratex-version.json +21 -0
- package/src/EnrichedMarkdownNativeComponent.ts +73 -0
- package/src/EnrichedMarkdownTextInput.tsx +159 -8
- package/src/EnrichedMarkdownTextInputNativeComponent.ts +78 -5
- package/src/EnrichedMarkdownTextNativeComponent.ts +74 -0
- package/src/headingDefaults.ts +21 -0
- package/src/index.tsx +9 -0
- package/src/index.web.tsx +1 -0
- package/src/jest/index.tsx +215 -0
- package/src/native/EnrichedMarkdownText.tsx +53 -2
- package/src/normalizeMarkdownStyle.ts +102 -16
- package/src/normalizeMarkdownStyle.web.ts +63 -15
- package/src/normalizeMarkdownTextInputStyle.ts +110 -35
- package/src/normalizeMenuItem.ts +1 -1
- package/src/types/MarkdownStyle.ts +74 -0
- package/src/types/MarkdownStyleInternal.ts +39 -0
- package/src/types/MarkdownTextProps.ts +101 -9
- package/src/types/MarkdownTextProps.web.ts +19 -0
- package/src/types/events.ts +21 -0
- package/src/utils/textInputState.ts +35 -0
- package/src/web/EnrichedMarkdownText.tsx +16 -2
- package/src/web/parseMarkdown.ts +6 -2
- package/src/web/renderers/InlineRenderers.tsx +5 -0
- package/src/web/renderers/ListRenderers.tsx +14 -2
- package/src/web/renderers/index.tsx +6 -2
- package/src/web/styles.ts +89 -5
- package/src/web/types.ts +6 -1
- package/src/web/utils.ts +1 -0
- package/src/web/wasm/md4c.js +0 -0
- package/vendor-grammars.mjs +511 -0
- package/vendor-ratex.mjs +173 -0
- package/app.plugin.js +0 -2
- package/plugin/build/withAndroidMath.js +0 -19
- package/plugin/build/withIosMath.js +0 -28
- package/plugin/build/withReactNativeEnrichedMarkdown.js +0 -11
- package/plugin/src/withAndroidMath.ts +0 -24
- package/plugin/src/withIosMath.ts +0 -35
- package/plugin/src/withReactNativeEnrichedMarkdown.ts +0 -17
- package/plugin/tsconfig.build.json +0 -16
|
@@ -0,0 +1,396 @@
|
|
|
1
|
+
package com.swmansion.enriched.markdown.views
|
|
2
|
+
|
|
3
|
+
import android.content.ClipData
|
|
4
|
+
import android.content.ClipboardManager
|
|
5
|
+
import android.content.Context
|
|
6
|
+
import android.graphics.Canvas
|
|
7
|
+
import android.graphics.ColorFilter
|
|
8
|
+
import android.graphics.Paint
|
|
9
|
+
import android.graphics.PixelFormat
|
|
10
|
+
import android.graphics.Typeface
|
|
11
|
+
import android.graphics.drawable.Drawable
|
|
12
|
+
import android.graphics.drawable.GradientDrawable
|
|
13
|
+
import android.os.Build
|
|
14
|
+
import android.text.Layout
|
|
15
|
+
import android.text.SpannableString
|
|
16
|
+
import android.text.StaticLayout
|
|
17
|
+
import android.text.TextPaint
|
|
18
|
+
import android.text.TextUtils
|
|
19
|
+
import android.util.TypedValue
|
|
20
|
+
import android.view.View
|
|
21
|
+
import android.widget.FrameLayout
|
|
22
|
+
import android.widget.HorizontalScrollView
|
|
23
|
+
import android.widget.ImageView
|
|
24
|
+
import androidx.appcompat.widget.AppCompatImageButton
|
|
25
|
+
import androidx.appcompat.widget.AppCompatTextView
|
|
26
|
+
import com.swmansion.enriched.markdown.parser.MarkdownASTNode
|
|
27
|
+
import com.swmansion.enriched.markdown.spans.LineHeightSpan
|
|
28
|
+
import com.swmansion.enriched.markdown.styles.CodeBlockStyle
|
|
29
|
+
import com.swmansion.enriched.markdown.styles.StyleConfig
|
|
30
|
+
import com.swmansion.enriched.markdown.utils.common.CodeBlockHighlighter
|
|
31
|
+
import com.swmansion.enriched.markdown.utils.common.CodeBlockNode
|
|
32
|
+
import com.swmansion.enriched.markdown.utils.text.extensions.applyCodeBlockTextStyle
|
|
33
|
+
import com.swmansion.enriched.markdown.utils.text.span.SPAN_FLAGS_EXCLUSIVE_EXCLUSIVE
|
|
34
|
+
import kotlin.math.ceil
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Block segment view for fenced code blocks (see splitASTIntoSegments):
|
|
38
|
+
* a fixed header bar (language name, copy button) above a horizontally
|
|
39
|
+
* scrolling, non-wrapping code pane. Syntax coloring comes from the
|
|
40
|
+
* CodeBlockHighlighter seam and falls back to plain text. The box visuals
|
|
41
|
+
* must stay in sync with the commonmark flavor's CodeBlockSpan.
|
|
42
|
+
*
|
|
43
|
+
* measureCodeBlockNodeHeight must stay in sync with the view: it builds the
|
|
44
|
+
* same styled text, paint, and header metrics, so the height reported to
|
|
45
|
+
* Yoga matches the laid-out height. Since lines never wrap, the height is
|
|
46
|
+
* independent of the available width.
|
|
47
|
+
*/
|
|
48
|
+
class CodeBlockContainerView(
|
|
49
|
+
context: Context,
|
|
50
|
+
styleConfig: StyleConfig,
|
|
51
|
+
) : FrameLayout(context),
|
|
52
|
+
BlockSegmentView {
|
|
53
|
+
private val codeBlockStyle: CodeBlockStyle = styleConfig.codeBlockStyle
|
|
54
|
+
|
|
55
|
+
private val inset = contentInset(codeBlockStyle)
|
|
56
|
+
private val borderW = borderPx(codeBlockStyle)
|
|
57
|
+
private val headerH = headerHeight(codeBlockStyle)
|
|
58
|
+
|
|
59
|
+
override val segmentMarginTop: Int get() = codeBlockStyle.marginTop.toInt()
|
|
60
|
+
override val segmentMarginBottom: Int get() = codeBlockStyle.marginBottom.toInt()
|
|
61
|
+
|
|
62
|
+
var copyLabel: String = ""
|
|
63
|
+
set(value) {
|
|
64
|
+
field = value
|
|
65
|
+
copyButton.contentDescription = value
|
|
66
|
+
}
|
|
67
|
+
var copyAsMarkdownLabel: String = ""
|
|
68
|
+
|
|
69
|
+
// Hides the long-press copy menu only; the header copy button is a visible
|
|
70
|
+
// control, not a context menu, and stays.
|
|
71
|
+
var contextMenuHidden: Boolean = false
|
|
72
|
+
|
|
73
|
+
// Copy / Copy as Markdown visibility, Copy format and the header copy button.
|
|
74
|
+
// The header button always copies the raw code.
|
|
75
|
+
var menuOptions: BlockMenuOptions = BlockMenuOptions()
|
|
76
|
+
set(value) {
|
|
77
|
+
field = value
|
|
78
|
+
// Hiding the button leaves the header (and its height) untouched.
|
|
79
|
+
copyButton.visibility = if (value.copyButtonHidden) View.GONE else View.VISIBLE
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
var onCopyPress: ((code: String, language: String) -> Unit)? = null
|
|
83
|
+
|
|
84
|
+
private var code: String = ""
|
|
85
|
+
private var language: String? = null
|
|
86
|
+
private var fenceChar: String = "`"
|
|
87
|
+
|
|
88
|
+
// True until the closing fence arrives: highlighting is deferred and copying
|
|
89
|
+
// is disabled, while the header stays visible.
|
|
90
|
+
var pending: Boolean = false
|
|
91
|
+
set(value) {
|
|
92
|
+
if (field == value) return
|
|
93
|
+
field = value
|
|
94
|
+
copyButton.isEnabled = !value
|
|
95
|
+
// The reconciler can reuse an unchanged block without re-applying the
|
|
96
|
+
// node, so re-derive here to pick up highlighting once the block closes.
|
|
97
|
+
rebuildCodeText()
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
private val textView =
|
|
101
|
+
AppCompatTextView(context).apply {
|
|
102
|
+
includeFontPadding = false
|
|
103
|
+
setLineSpacing(0f, 1f)
|
|
104
|
+
breakStrategy = Layout.BREAK_STRATEGY_SIMPLE
|
|
105
|
+
hyphenationFrequency = Layout.HYPHENATION_FREQUENCY_NONE
|
|
106
|
+
layoutDirection = View.LAYOUT_DIRECTION_LTR
|
|
107
|
+
textDirection = View.TEXT_DIRECTION_LTR
|
|
108
|
+
setTextSize(TypedValue.COMPLEX_UNIT_PX, codeBlockStyle.fontSize)
|
|
109
|
+
typeface = createCodePaint(codeBlockStyle, context).typeface
|
|
110
|
+
setTextColor(codeBlockStyle.color)
|
|
111
|
+
val horizontalPad = (inset - borderW).coerceAtLeast(0)
|
|
112
|
+
setPadding(horizontalPad, inset, horizontalPad, inset)
|
|
113
|
+
setOnLongClickListener { view -> showContextMenu(view) }
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
private val scrollView =
|
|
117
|
+
HorizontalScrollView(context).apply {
|
|
118
|
+
isHorizontalScrollBarEnabled = true
|
|
119
|
+
overScrollMode = View.OVER_SCROLL_NEVER
|
|
120
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
|
121
|
+
horizontalScrollbarThumbDrawable =
|
|
122
|
+
GradientDrawable().apply {
|
|
123
|
+
setColor(secondaryColor(codeBlockStyle.color))
|
|
124
|
+
cornerRadius = context.resources.displayMetrics.density * 2
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
addView(textView, LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT))
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
private val languageView =
|
|
131
|
+
AppCompatTextView(context).apply {
|
|
132
|
+
includeFontPadding = false
|
|
133
|
+
maxLines = 1
|
|
134
|
+
ellipsize = TextUtils.TruncateAt.END
|
|
135
|
+
setTextSize(TypedValue.COMPLEX_UNIT_PX, codeBlockStyle.fontSize * HEADER_LABEL_SCALE)
|
|
136
|
+
typeface = headerTypeface
|
|
137
|
+
setTextColor(secondaryColor(codeBlockStyle.color))
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
private val copyButton =
|
|
141
|
+
AppCompatImageButton(context).apply {
|
|
142
|
+
background = null
|
|
143
|
+
scaleType = ImageView.ScaleType.CENTER
|
|
144
|
+
setImageDrawable(
|
|
145
|
+
CopyIconDrawable(
|
|
146
|
+
secondaryColor(codeBlockStyle.color),
|
|
147
|
+
ceil(codeBlockStyle.fontSize * HEADER_ICON_SCALE).toInt(),
|
|
148
|
+
),
|
|
149
|
+
)
|
|
150
|
+
setOnClickListener { copyCode() }
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
private val dividerPaint =
|
|
154
|
+
Paint(Paint.ANTI_ALIAS_FLAG).apply {
|
|
155
|
+
color = dividerColor(codeBlockStyle.color)
|
|
156
|
+
strokeWidth = context.resources.displayMetrics.density
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
init {
|
|
160
|
+
setWillNotDraw(false)
|
|
161
|
+
background =
|
|
162
|
+
GradientDrawable().apply {
|
|
163
|
+
setColor(codeBlockStyle.backgroundColor)
|
|
164
|
+
cornerRadius = codeBlockStyle.borderRadius
|
|
165
|
+
if (codeBlockStyle.borderWidth > 0f) {
|
|
166
|
+
setStroke(ceil(codeBlockStyle.borderWidth).toInt(), codeBlockStyle.borderColor)
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
isLongClickable = true
|
|
170
|
+
setOnLongClickListener { view -> showContextMenu(view) }
|
|
171
|
+
addView(scrollView, LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT))
|
|
172
|
+
addView(languageView, LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT))
|
|
173
|
+
addView(copyButton, LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT))
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
fun applyCodeBlockNode(node: MarkdownASTNode) {
|
|
177
|
+
code = CodeBlockNode.extractCode(node)
|
|
178
|
+
fenceChar = CodeBlockNode.fenceChar(node)
|
|
179
|
+
|
|
180
|
+
val newLanguage = CodeBlockNode.language(node)
|
|
181
|
+
if (newLanguage != language) {
|
|
182
|
+
language = newLanguage
|
|
183
|
+
languageView.text = CodeBlockNode.displayLanguageName(newLanguage)
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
rebuildCodeText()
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// Highlighting is deferred while pending, applied once the block closes.
|
|
190
|
+
private fun rebuildCodeText() {
|
|
191
|
+
val plainCode = buildCodeText(code, codeBlockStyle)
|
|
192
|
+
if (!pending) {
|
|
193
|
+
CodeBlockHighlighter.highlight(plainCode, code, language, codeBlockStyle)
|
|
194
|
+
}
|
|
195
|
+
textView.text = plainCode
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
override fun onMeasure(
|
|
199
|
+
widthSpec: Int,
|
|
200
|
+
heightSpec: Int,
|
|
201
|
+
) {
|
|
202
|
+
val measuredWidth = MeasureSpec.getSize(widthSpec)
|
|
203
|
+
scrollView.measure(
|
|
204
|
+
MeasureSpec.makeMeasureSpec((measuredWidth - borderW * 2).coerceAtLeast(0), MeasureSpec.EXACTLY),
|
|
205
|
+
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
|
|
206
|
+
)
|
|
207
|
+
copyButton.measure(
|
|
208
|
+
MeasureSpec.makeMeasureSpec(headerH, MeasureSpec.EXACTLY),
|
|
209
|
+
MeasureSpec.makeMeasureSpec(headerH, MeasureSpec.EXACTLY),
|
|
210
|
+
)
|
|
211
|
+
val labelMaxWidth = (measuredWidth - inset * 2 - headerH).coerceAtLeast(0)
|
|
212
|
+
languageView.measure(
|
|
213
|
+
MeasureSpec.makeMeasureSpec(labelMaxWidth, MeasureSpec.AT_MOST),
|
|
214
|
+
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
|
|
215
|
+
)
|
|
216
|
+
setMeasuredDimension(measuredWidth, headerH + scrollView.measuredHeight)
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
override fun onLayout(
|
|
220
|
+
changed: Boolean,
|
|
221
|
+
left: Int,
|
|
222
|
+
top: Int,
|
|
223
|
+
right: Int,
|
|
224
|
+
bottom: Int,
|
|
225
|
+
) {
|
|
226
|
+
val width = right - left
|
|
227
|
+
val labelTop = headerH - languageView.measuredHeight
|
|
228
|
+
languageView.layout(
|
|
229
|
+
inset,
|
|
230
|
+
labelTop,
|
|
231
|
+
inset + languageView.measuredWidth,
|
|
232
|
+
labelTop + languageView.measuredHeight,
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
val iconWidth = copyButton.drawable?.intrinsicWidth ?: copyButton.measuredWidth
|
|
236
|
+
val iconSlack = ((copyButton.measuredWidth - iconWidth) / 2).coerceAtLeast(0)
|
|
237
|
+
val buttonLeft = (width - inset - copyButton.measuredWidth + iconSlack).coerceAtLeast(0)
|
|
238
|
+
val buttonTop = (headerH - languageView.measuredHeight / 2 - copyButton.measuredHeight / 2).coerceAtLeast(0)
|
|
239
|
+
copyButton.layout(
|
|
240
|
+
buttonLeft,
|
|
241
|
+
buttonTop,
|
|
242
|
+
buttonLeft + copyButton.measuredWidth,
|
|
243
|
+
buttonTop + copyButton.measuredHeight,
|
|
244
|
+
)
|
|
245
|
+
|
|
246
|
+
scrollView.layout(borderW, headerH, width - borderW, bottom - top - borderW)
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// Divider between the header and the code, centered in the gap the code
|
|
250
|
+
// text's top inset creates, so it adds no height of its own.
|
|
251
|
+
override fun onDraw(canvas: Canvas) {
|
|
252
|
+
super.onDraw(canvas)
|
|
253
|
+
val borderWidth = borderW.toFloat()
|
|
254
|
+
val y = headerH + inset / 2f
|
|
255
|
+
canvas.drawLine(borderWidth, y, width - borderWidth, y, dividerPaint)
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// Returns whether a menu was shown, so the long-press listener only consumes
|
|
259
|
+
// the event when there is one (a pending block has no menu yet, and a hidden
|
|
260
|
+
// one never does).
|
|
261
|
+
private fun showContextMenu(anchor: View): Boolean {
|
|
262
|
+
if (pending || contextMenuHidden || !menuOptions.hasItems) return false
|
|
263
|
+
ContextMenuPopup.show(anchor, this) {
|
|
264
|
+
blockCopyItems(menuOptions, copyLabel, copyAsMarkdownLabel, ::copyCode, ::copyFencedMarkdown)
|
|
265
|
+
}
|
|
266
|
+
return true
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
private fun copyCode() {
|
|
270
|
+
if (pending || code.isEmpty()) return
|
|
271
|
+
copyToClipboard(code)
|
|
272
|
+
onCopyPress?.invoke(code, language ?: "")
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
private fun copyFencedMarkdown() {
|
|
276
|
+
if (code.isEmpty()) return
|
|
277
|
+
copyToClipboard(CodeBlockNode.fencedMarkdown(code, language, fenceChar))
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
private fun copyToClipboard(text: String) {
|
|
281
|
+
val clipboard = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
|
282
|
+
clipboard.setPrimaryClip(ClipData.newPlainText("Code", text))
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
private class CopyIconDrawable(
|
|
286
|
+
color: Int,
|
|
287
|
+
private val size: Int,
|
|
288
|
+
) : Drawable() {
|
|
289
|
+
private val paint =
|
|
290
|
+
Paint(Paint.ANTI_ALIAS_FLAG).apply {
|
|
291
|
+
style = Paint.Style.STROKE
|
|
292
|
+
strokeWidth = size / 20f
|
|
293
|
+
strokeJoin = Paint.Join.ROUND
|
|
294
|
+
strokeCap = Paint.Cap.ROUND
|
|
295
|
+
this.color = color
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
private val glyph = CopyGlyph()
|
|
299
|
+
|
|
300
|
+
override fun draw(canvas: Canvas) {
|
|
301
|
+
glyph.draw(canvas, bounds.width().toFloat(), paint)
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
override fun getIntrinsicWidth() = size
|
|
305
|
+
|
|
306
|
+
override fun getIntrinsicHeight() = size
|
|
307
|
+
|
|
308
|
+
override fun setAlpha(alpha: Int) {
|
|
309
|
+
paint.alpha = alpha
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
override fun setColorFilter(colorFilter: ColorFilter?) {
|
|
313
|
+
paint.colorFilter = colorFilter
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
@Deprecated("Deprecated in Java")
|
|
317
|
+
override fun getOpacity() = PixelFormat.TRANSLUCENT
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
companion object {
|
|
321
|
+
private const val HEADER_LABEL_SCALE = 0.85f
|
|
322
|
+
|
|
323
|
+
// Drawable box for the copy glyph, as a multiple of the code font size.
|
|
324
|
+
// iOS sizes the SF Symbol by point size (kENRMHeaderIconScale = 0.72) but
|
|
325
|
+
// the symbol renders roughly half again as tall as its point size; this box
|
|
326
|
+
// is scaled up to land the drawn glyph at the same on-screen size.
|
|
327
|
+
private const val HEADER_ICON_SCALE = 1.08f
|
|
328
|
+
|
|
329
|
+
private val headerTypeface: Typeface = Typeface.create("sans-serif-medium", Typeface.NORMAL)
|
|
330
|
+
|
|
331
|
+
private fun secondaryColor(color: Int): Int = (color and 0x00FFFFFF) or (0x99 shl 24)
|
|
332
|
+
|
|
333
|
+
private fun dividerColor(color: Int): Int = (color and 0x00FFFFFF) or (0x33 shl 24)
|
|
334
|
+
|
|
335
|
+
private fun contentInset(style: CodeBlockStyle): Int = ceil(style.padding + style.borderWidth).toInt()
|
|
336
|
+
|
|
337
|
+
private fun borderPx(style: CodeBlockStyle): Int = ceil(style.borderWidth).toInt()
|
|
338
|
+
|
|
339
|
+
// Header is the top content inset plus one label line; the code text
|
|
340
|
+
// view's own top inset then forms the single gap below the label.
|
|
341
|
+
private fun headerHeight(style: CodeBlockStyle): Int {
|
|
342
|
+
val paint =
|
|
343
|
+
TextPaint(Paint.ANTI_ALIAS_FLAG).apply {
|
|
344
|
+
textSize = style.fontSize * HEADER_LABEL_SCALE
|
|
345
|
+
typeface = headerTypeface
|
|
346
|
+
}
|
|
347
|
+
val metrics = paint.fontMetrics
|
|
348
|
+
return contentInset(style) + ceil(metrics.descent - metrics.ascent).toInt()
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
private fun createCodePaint(
|
|
352
|
+
style: CodeBlockStyle,
|
|
353
|
+
context: Context,
|
|
354
|
+
): TextPaint =
|
|
355
|
+
TextPaint(Paint.ANTI_ALIAS_FLAG).apply {
|
|
356
|
+
applyCodeBlockTextStyle(style, context)
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
private fun buildCodeText(
|
|
360
|
+
code: String,
|
|
361
|
+
style: CodeBlockStyle,
|
|
362
|
+
): SpannableString =
|
|
363
|
+
SpannableString(code).apply {
|
|
364
|
+
if (style.lineHeight > 0f && isNotEmpty()) {
|
|
365
|
+
setSpan(LineHeightSpan(style.lineHeight), 0, length, SPAN_FLAGS_EXCLUSIVE_EXCLUSIVE)
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
// Lines never wrap (the code pane scrolls horizontally), so the layout is
|
|
370
|
+
// built at the text's desired width and the result is independent of the
|
|
371
|
+
// available width.
|
|
372
|
+
fun measureCodeBlockNodeHeight(
|
|
373
|
+
node: MarkdownASTNode,
|
|
374
|
+
config: StyleConfig,
|
|
375
|
+
context: Context,
|
|
376
|
+
@Suppress("unused") width: Float,
|
|
377
|
+
): Float {
|
|
378
|
+
val style = config.codeBlockStyle
|
|
379
|
+
val inset = contentInset(style)
|
|
380
|
+
val headerH = headerHeight(style)
|
|
381
|
+
val text = buildCodeText(CodeBlockNode.extractCode(node), style)
|
|
382
|
+
if (text.isEmpty()) return headerH + inset * 2f
|
|
383
|
+
val paint = createCodePaint(style, context)
|
|
384
|
+
val contentWidth = ceil(Layout.getDesiredWidth(text, paint)).toInt().coerceAtLeast(1)
|
|
385
|
+
val layout =
|
|
386
|
+
StaticLayout.Builder
|
|
387
|
+
.obtain(text, 0, text.length, paint, contentWidth)
|
|
388
|
+
.setIncludePad(false)
|
|
389
|
+
.setLineSpacing(0f, 1f)
|
|
390
|
+
.setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE)
|
|
391
|
+
.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NONE)
|
|
392
|
+
.build()
|
|
393
|
+
return layout.height.toFloat() + inset * 2 + headerH
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
}
|
|
@@ -183,16 +183,19 @@ object ContextMenuPopup {
|
|
|
183
183
|
color = Color.parseColor("#333333")
|
|
184
184
|
}
|
|
185
185
|
|
|
186
|
+
private val copyGlyph = CopyGlyph()
|
|
187
|
+
|
|
188
|
+
// COPY mirrors SF Symbol doc.on.doc, DOCUMENT mirrors doc.text; the copy
|
|
189
|
+
// glyph is shared with the header button in CodeBlockContainerView.
|
|
186
190
|
override fun draw(canvas: Canvas) {
|
|
187
191
|
val u = bounds.width() / 24f
|
|
188
192
|
if (icon == Icon.COPY) {
|
|
189
|
-
|
|
190
|
-
canvas.drawRoundRect(RectF(2 * u, 8 * u, 16 * u, 22 * u), 2 * u, 2 * u, paint)
|
|
193
|
+
copyGlyph.draw(canvas, bounds.width().toFloat(), paint)
|
|
191
194
|
} else {
|
|
192
|
-
canvas.drawRoundRect(RectF(
|
|
193
|
-
canvas.drawLine(8 * u,
|
|
194
|
-
canvas.drawLine(8 * u, 12 * u,
|
|
195
|
-
canvas.drawLine(8 * u, 16 * u, 13 * u, 16 * u, paint)
|
|
195
|
+
canvas.drawRoundRect(RectF(5 * u, 3 * u, 19 * u, 21 * u), 2.5f * u, 2.5f * u, paint)
|
|
196
|
+
canvas.drawLine(8.5f * u, 9 * u, 15.5f * u, 9 * u, paint)
|
|
197
|
+
canvas.drawLine(8.5f * u, 12.5f * u, 15.5f * u, 12.5f * u, paint)
|
|
198
|
+
canvas.drawLine(8.5f * u, 16 * u, 13 * u, 16 * u, paint)
|
|
196
199
|
}
|
|
197
200
|
}
|
|
198
201
|
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
package com.swmansion.enriched.markdown.views
|
|
2
|
+
|
|
3
|
+
import android.graphics.Canvas
|
|
4
|
+
import android.graphics.Paint
|
|
5
|
+
import android.graphics.Path
|
|
6
|
+
import android.graphics.PorterDuff
|
|
7
|
+
import android.graphics.PorterDuffXfermode
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Draws the copy glyph so Android matches the SF Symbol doc.on.doc rendered on
|
|
11
|
+
* iOS: two portrait document pages with a folded (dog-eared) top-right corner,
|
|
12
|
+
* a front page in the lower-left laid over a back page in the upper-right.
|
|
13
|
+
*
|
|
14
|
+
* The back page is punched out where the front page (plus a hairline of
|
|
15
|
+
* clearance) covers it, so the front reads as sitting on top exactly as the SF
|
|
16
|
+
* Symbol does, instead of both outlines crossing. The clear is done inside an
|
|
17
|
+
* offscreen layer so the punched region reveals whatever background the drawable
|
|
18
|
+
* sits on, without the glyph needing to know that color.
|
|
19
|
+
*
|
|
20
|
+
* One instance is held per drawable rather than shared: the paths and clear
|
|
21
|
+
* paint are reused across draws to keep draw() allocation-free, and two drawables
|
|
22
|
+
* of different sizes must not share those buffers. All coordinates use a 24-unit
|
|
23
|
+
* grid scaled to the drawable width, matching the grid the iOS symbol is authored
|
|
24
|
+
* on.
|
|
25
|
+
*/
|
|
26
|
+
internal class CopyGlyph {
|
|
27
|
+
private val back = Path()
|
|
28
|
+
private val front = Path()
|
|
29
|
+
private val backFold = Path()
|
|
30
|
+
private val frontFold = Path()
|
|
31
|
+
|
|
32
|
+
// Color and colorFilter are irrelevant under PorterDuff.CLEAR; only the
|
|
33
|
+
// widened stroke (set per draw) matters, so this is configured once.
|
|
34
|
+
private val clearPaint =
|
|
35
|
+
Paint(Paint.ANTI_ALIAS_FLAG).apply {
|
|
36
|
+
style = Paint.Style.FILL_AND_STROKE
|
|
37
|
+
strokeJoin = Paint.Join.ROUND
|
|
38
|
+
strokeCap = Paint.Cap.ROUND
|
|
39
|
+
xfermode = PorterDuffXfermode(PorterDuff.Mode.CLEAR)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
fun draw(
|
|
43
|
+
canvas: Canvas,
|
|
44
|
+
width: Float,
|
|
45
|
+
stroke: Paint,
|
|
46
|
+
) {
|
|
47
|
+
val u = width / 24f
|
|
48
|
+
val fold = 4f * u
|
|
49
|
+
val corner = 2f * u
|
|
50
|
+
|
|
51
|
+
buildPage(back, 9 * u, 1 * u, 20 * u, 17 * u, fold, corner)
|
|
52
|
+
buildPage(front, 3 * u, 7 * u, 14 * u, 23 * u, fold, corner)
|
|
53
|
+
buildFold(backFold, 20 * u, 1 * u, fold)
|
|
54
|
+
buildFold(frontFold, 14 * u, 7 * u, fold)
|
|
55
|
+
clearPaint.strokeWidth = stroke.strokeWidth * 3f
|
|
56
|
+
|
|
57
|
+
val saved = canvas.saveLayer(0f, 0f, width, width, null)
|
|
58
|
+
canvas.drawPath(back, stroke)
|
|
59
|
+
canvas.drawPath(backFold, stroke)
|
|
60
|
+
canvas.drawPath(front, clearPaint)
|
|
61
|
+
canvas.drawPath(front, stroke)
|
|
62
|
+
canvas.drawPath(frontFold, stroke)
|
|
63
|
+
canvas.restoreToCount(saved)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// A page outline whose top-right corner is cut back by fold, with the other
|
|
67
|
+
// three corners rounded by corner.
|
|
68
|
+
private fun buildPage(
|
|
69
|
+
path: Path,
|
|
70
|
+
l: Float,
|
|
71
|
+
t: Float,
|
|
72
|
+
r: Float,
|
|
73
|
+
b: Float,
|
|
74
|
+
fold: Float,
|
|
75
|
+
corner: Float,
|
|
76
|
+
) {
|
|
77
|
+
path.rewind()
|
|
78
|
+
path.moveTo(l, t + corner)
|
|
79
|
+
path.quadTo(l, t, l + corner, t)
|
|
80
|
+
path.lineTo(r - fold, t)
|
|
81
|
+
path.lineTo(r, t + fold)
|
|
82
|
+
path.lineTo(r, b - corner)
|
|
83
|
+
path.quadTo(r, b, r - corner, b)
|
|
84
|
+
path.lineTo(l + corner, b)
|
|
85
|
+
path.quadTo(l, b, l, b - corner)
|
|
86
|
+
path.close()
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// The two inner edges of the folded-over corner, at the page's top-right.
|
|
90
|
+
private fun buildFold(
|
|
91
|
+
path: Path,
|
|
92
|
+
r: Float,
|
|
93
|
+
t: Float,
|
|
94
|
+
fold: Float,
|
|
95
|
+
) {
|
|
96
|
+
path.rewind()
|
|
97
|
+
path.moveTo(r - fold, t)
|
|
98
|
+
path.lineTo(r - fold, t + fold)
|
|
99
|
+
path.lineTo(r, t + fold)
|
|
100
|
+
}
|
|
101
|
+
}
|
|
@@ -43,7 +43,7 @@ class TableContainerView(
|
|
|
43
43
|
private val styleConfig: StyleConfig,
|
|
44
44
|
) : FrameLayout(context),
|
|
45
45
|
BlockSegmentView {
|
|
46
|
-
|
|
46
|
+
internal val tableStyle: TableStyle = styleConfig.tableStyle
|
|
47
47
|
|
|
48
48
|
override val segmentMarginTop: Int get() = tableStyle.marginTop.toInt()
|
|
49
49
|
override val segmentMarginBottom: Int get() = tableStyle.marginBottom.toInt()
|
|
@@ -63,6 +63,8 @@ class TableContainerView(
|
|
|
63
63
|
|
|
64
64
|
var copyLabel: String = ""
|
|
65
65
|
var copyAsMarkdownLabel: String = ""
|
|
66
|
+
var contextMenuHidden: Boolean = false
|
|
67
|
+
var menuOptions: BlockMenuOptions = BlockMenuOptions()
|
|
66
68
|
|
|
67
69
|
private val scrollView =
|
|
68
70
|
HorizontalScrollView(context).apply {
|
|
@@ -327,19 +329,45 @@ class TableContainerView(
|
|
|
327
329
|
right: Int,
|
|
328
330
|
bottom: Int,
|
|
329
331
|
) {
|
|
330
|
-
scrollView.layout(0, 0, right - left, bottom - top)
|
|
331
332
|
val viewWidth = right - left
|
|
332
|
-
|
|
333
|
+
val overhang = max(ceil(tableStyle.horizontalOverflow.toDouble()).toInt(), 0)
|
|
334
|
+
val contentWidth = viewWidth - overhang * 2
|
|
335
|
+
val tableOverflows = totalTableWidth > contentWidth
|
|
336
|
+
|
|
337
|
+
scrollView.setPadding(overhang, 0, overhang, 0)
|
|
338
|
+
scrollView.clipToPadding = !tableOverflows
|
|
339
|
+
scrollView.isHorizontalScrollBarEnabled = tableOverflows
|
|
340
|
+
|
|
341
|
+
scrollView.layout(0, 0, viewWidth, bottom - top)
|
|
342
|
+
|
|
343
|
+
gridContainer.translationX =
|
|
344
|
+
if (tableStyle.align.isNotEmpty() && !tableOverflows) {
|
|
345
|
+
val freeSpace = max(contentWidth - totalTableWidth, 0f)
|
|
346
|
+
val desiredLeft =
|
|
347
|
+
overhang +
|
|
348
|
+
when (tableStyle.align) {
|
|
349
|
+
"center" -> freeSpace / 2f
|
|
350
|
+
"right" -> freeSpace
|
|
351
|
+
else -> 0f
|
|
352
|
+
}
|
|
353
|
+
desiredLeft - gridContainer.left
|
|
354
|
+
} else {
|
|
355
|
+
0f
|
|
356
|
+
}
|
|
333
357
|
|
|
334
|
-
if (isRtl
|
|
335
|
-
|
|
358
|
+
if (isRtl) {
|
|
359
|
+
val effectiveWidth = if (tableOverflows) contentWidth.toFloat() else viewWidth.toFloat()
|
|
360
|
+
if (totalTableWidth > effectiveWidth) {
|
|
361
|
+
scrollView.scrollTo((totalTableWidth - effectiveWidth).toInt(), 0)
|
|
362
|
+
}
|
|
336
363
|
}
|
|
337
364
|
}
|
|
338
365
|
|
|
339
366
|
private fun showContextMenu(anchor: View) {
|
|
367
|
+
if (contextMenuHidden) return
|
|
340
368
|
val clipboard = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
|
341
369
|
ContextMenuPopup.show(anchor, this) {
|
|
342
|
-
|
|
370
|
+
blockCopyItems(menuOptions, copyLabel, copyAsMarkdownLabel, copyRaw = {
|
|
343
371
|
val plainText = rows.joinToString("\n") { row -> row.joinToString("\t") { it.plainText } }
|
|
344
372
|
if (plainText.isNotEmpty()) {
|
|
345
373
|
val displayMetrics = context.resources.displayMetrics
|
|
@@ -350,10 +378,9 @@ class TableContainerView(
|
|
|
350
378
|
val html = HTMLGenerator.generateTableHTML(tableRows, styleConfig, displayMetrics.scaledDensity, displayMetrics.density)
|
|
351
379
|
clipboard.setPrimaryClip(ClipData.newHtmlText("Table", plainText, html))
|
|
352
380
|
}
|
|
353
|
-
}
|
|
354
|
-
item(ContextMenuPopup.Icon.DOCUMENT, copyAsMarkdownLabel) {
|
|
381
|
+
}, copyMarkdown = {
|
|
355
382
|
if (tableMarkdown.isNotEmpty()) clipboard.setPrimaryClip(ClipData.newPlainText("Table", tableMarkdown))
|
|
356
|
-
}
|
|
383
|
+
})
|
|
357
384
|
}
|
|
358
385
|
}
|
|
359
386
|
|
|
@@ -25,8 +25,17 @@ endif()
|
|
|
25
25
|
|
|
26
26
|
set(ANDROID_CPP_DIR "${LIB_ANDROID_DIR}/src/main/cpp")
|
|
27
27
|
|
|
28
|
+
# Optional tree-sitter code highlighting. build.gradle writes this config during
|
|
29
|
+
# configuration (enable flag, selected languages, generated registry dir); absent
|
|
30
|
+
# on a bare CMake invocation, in which case highlighting stays compiled out.
|
|
31
|
+
set(HIGHLIGHT_CONFIG "${LIB_ANDROID_DIR}/build/generated/highlight/highlight-config.cmake")
|
|
32
|
+
if(EXISTS "${HIGHLIGHT_CONFIG}")
|
|
33
|
+
include("${HIGHLIGHT_CONFIG}")
|
|
34
|
+
endif()
|
|
35
|
+
|
|
28
36
|
file(GLOB MD4C_SOURCES "${CPP_ROOT}/md4c/*.c")
|
|
29
37
|
file(GLOB PARSER_SOURCES "${CPP_ROOT}/parser/*.cpp")
|
|
38
|
+
file(GLOB HIGHLIGHT_SOURCES "${CPP_ROOT}/highlight/*.cpp")
|
|
30
39
|
|
|
31
40
|
# md4c is C code, build as separate static library with C flags
|
|
32
41
|
add_library(md4c_lib STATIC ${MD4C_SOURCES})
|
|
@@ -46,6 +55,7 @@ add_library(
|
|
|
46
55
|
${LIB_CODEGEN_SRCS}
|
|
47
56
|
${LIB_CUSTOM_JNI_SRCS}
|
|
48
57
|
${PARSER_SOURCES}
|
|
58
|
+
${HIGHLIGHT_SOURCES}
|
|
49
59
|
${ANDROID_CPP_DIR}/jni-adapter.cpp
|
|
50
60
|
)
|
|
51
61
|
|
|
@@ -58,6 +68,7 @@ target_include_directories(
|
|
|
58
68
|
${LIB_ANDROID_GENERATED_COMPONENTS_DIR}
|
|
59
69
|
${CPP_ROOT}/md4c
|
|
60
70
|
${CPP_ROOT}/parser
|
|
71
|
+
${CPP_ROOT}/highlight
|
|
61
72
|
)
|
|
62
73
|
|
|
63
74
|
target_compile_definitions(${LIB_TARGET_NAME} PRIVATE MD4C_USE_UTF8=1)
|
|
@@ -82,3 +93,45 @@ target_include_directories(
|
|
|
82
93
|
)
|
|
83
94
|
|
|
84
95
|
target_compile_reactnative_options(${LIB_TARGET_NAME} PRIVATE)
|
|
96
|
+
|
|
97
|
+
# --- Code-block syntax highlighting (tree-sitter) ---
|
|
98
|
+
# CodeBlockHighlighter.cpp / CodeBlockLanguages.cpp are already in the target via
|
|
99
|
+
# HIGHLIGHT_SOURCES; without the define below CodeBlockHighlighter.cpp is the stub.
|
|
100
|
+
# When enabled we add the runtime, the generated registry, and one OBJECT lib per
|
|
101
|
+
# selected grammar (each isolated to its own dir so grammar parser.h files never
|
|
102
|
+
# collide), then define ENRICHED_MARKDOWN_CODE_HIGHLIGHT so the real seam compiles.
|
|
103
|
+
if(ENRICHED_MARKDOWN_CODE_HIGHLIGHT)
|
|
104
|
+
set(TS_VENDOR "${CPP_ROOT}/highlight/vendor")
|
|
105
|
+
|
|
106
|
+
add_library(tree_sitter_runtime STATIC "${TS_VENDOR}/tree-sitter/src/lib.c")
|
|
107
|
+
target_include_directories(tree_sitter_runtime
|
|
108
|
+
PRIVATE "${TS_VENDOR}/tree-sitter/src"
|
|
109
|
+
PUBLIC "${TS_VENDOR}/tree-sitter/include")
|
|
110
|
+
set_target_properties(tree_sitter_runtime PROPERTIES
|
|
111
|
+
C_STANDARD 11 C_STANDARD_REQUIRED ON POSITION_INDEPENDENT_CODE ON)
|
|
112
|
+
target_compile_options(tree_sitter_runtime PRIVATE -fvisibility=hidden)
|
|
113
|
+
|
|
114
|
+
set(GRAMMAR_OBJECTS "")
|
|
115
|
+
foreach(lang IN LISTS ENRICHED_MARKDOWN_HIGHLIGHT_LANGUAGES)
|
|
116
|
+
set(gdir "${TS_VENDOR}/grammars/${lang}")
|
|
117
|
+
set(gsrcs "${gdir}/parser.c")
|
|
118
|
+
if(EXISTS "${gdir}/scanner.c")
|
|
119
|
+
list(APPEND gsrcs "${gdir}/scanner.c")
|
|
120
|
+
endif()
|
|
121
|
+
add_library(ts_grammar_${lang} OBJECT ${gsrcs})
|
|
122
|
+
target_include_directories(ts_grammar_${lang} PRIVATE "${gdir}")
|
|
123
|
+
set_target_properties(ts_grammar_${lang} PROPERTIES
|
|
124
|
+
C_STANDARD 11 C_STANDARD_REQUIRED ON POSITION_INDEPENDENT_CODE ON)
|
|
125
|
+
target_compile_options(ts_grammar_${lang} PRIVATE -fvisibility=hidden)
|
|
126
|
+
list(APPEND GRAMMAR_OBJECTS $<TARGET_OBJECTS:ts_grammar_${lang}>)
|
|
127
|
+
endforeach()
|
|
128
|
+
|
|
129
|
+
target_sources(${LIB_TARGET_NAME} PRIVATE
|
|
130
|
+
"${ENRICHED_MARKDOWN_HIGHLIGHT_GENERATED_DIR}/generated_registry.cpp"
|
|
131
|
+
${GRAMMAR_OBJECTS})
|
|
132
|
+
target_include_directories(${LIB_TARGET_NAME} PRIVATE
|
|
133
|
+
"${TS_VENDOR}/tree-sitter/include"
|
|
134
|
+
"${ENRICHED_MARKDOWN_HIGHLIGHT_GENERATED_DIR}")
|
|
135
|
+
target_compile_definitions(${LIB_TARGET_NAME} PRIVATE ENRICHED_MARKDOWN_CODE_HIGHLIGHT=1)
|
|
136
|
+
target_link_libraries(${LIB_TARGET_NAME} tree_sitter_runtime)
|
|
137
|
+
endif()
|