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
|
@@ -3,6 +3,11 @@
|
|
|
3
3
|
#import "LastElementUtils.h"
|
|
4
4
|
#import "StyleConfig.h"
|
|
5
5
|
|
|
6
|
+
// Draws the commonmark-flavor code block box behind the text view's glyph
|
|
7
|
+
// runs. The visual conventions (half-stroke border inset, corner radius
|
|
8
|
+
// handling) must stay in sync with the whole-rect box the github flavor
|
|
9
|
+
// draws in ENRMCodeBlockContainerView's drawRect:.
|
|
10
|
+
|
|
6
11
|
@implementation CodeBlockBackground {
|
|
7
12
|
StyleConfig *_config;
|
|
8
13
|
}
|
|
@@ -53,9 +58,18 @@
|
|
|
53
58
|
if (CGRectIsEmpty(blockRect))
|
|
54
59
|
return;
|
|
55
60
|
|
|
56
|
-
|
|
61
|
+
NSNumber *indentAttr = [layoutManager.textStorage attribute:CodeBlockIndentAttributeName
|
|
62
|
+
atIndex:range.location
|
|
63
|
+
effectiveRange:NULL];
|
|
64
|
+
CGFloat indent = [indentAttr doubleValue];
|
|
65
|
+
|
|
66
|
+
CGFloat availableWidth = textContainer.size.width - indent;
|
|
67
|
+
if (availableWidth <= 0)
|
|
68
|
+
return;
|
|
69
|
+
|
|
70
|
+
blockRect.origin.x = origin.x + indent;
|
|
57
71
|
blockRect.origin.y += origin.y;
|
|
58
|
-
blockRect.size.width =
|
|
72
|
+
blockRect.size.width = availableWidth;
|
|
59
73
|
|
|
60
74
|
// We extend the background specifically to cover the bottom padding spacer,
|
|
61
75
|
// excluding any additional marginBottom applied via measurement.
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <CoreGraphics/CGGeometry.h>
|
|
4
|
+
#include <atomic>
|
|
5
|
+
#include <cstdint>
|
|
6
|
+
#include <cstring>
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Lock-free size mailbox (issue #550).
|
|
10
|
+
*
|
|
11
|
+
* `measureContent` may run on the JS/layout thread while React Native holds
|
|
12
|
+
* the ShadowTree revision mutex (`preventShadowTreeCommitExhaustion` re-runs
|
|
13
|
+
* the entire commit — layout included — under `revisionMutexRecursive_` after
|
|
14
|
+
* three failed optimistic commits). A main-thread committer (e.g. Reanimated)
|
|
15
|
+
* can already be blocked on that same mutex, so any `dispatch_sync` to main
|
|
16
|
+
* from the measure path can deadlock: JS waits for main, main waits for the
|
|
17
|
+
* mutex JS holds. iOS kills the frozen app ~60s later (watchdog 0x8BADF00D).
|
|
18
|
+
*
|
|
19
|
+
* Reading `view.bounds` from a background thread is not safe either, so the
|
|
20
|
+
* component view *publishes* its last committed size here (from
|
|
21
|
+
* `updateLayoutMetrics:`, always on main) and the measure path *loads* it
|
|
22
|
+
* wait-free from any thread.
|
|
23
|
+
*
|
|
24
|
+
* Both dimensions are packed as IEEE-754 floats into one `uint64_t` so a
|
|
25
|
+
* single lock-free atomic covers the pair — a reader can never observe a new
|
|
26
|
+
* width with an old height (no torn reads). Relaxed memory ordering suffices:
|
|
27
|
+
* the value is self-contained and no other memory is published through it.
|
|
28
|
+
*/
|
|
29
|
+
class ENRMAtomicSize {
|
|
30
|
+
public:
|
|
31
|
+
void store(CGSize size)
|
|
32
|
+
{
|
|
33
|
+
bits_.store(pack(size), std::memory_order_relaxed);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
CGSize load() const
|
|
37
|
+
{
|
|
38
|
+
return unpack(bits_.load(std::memory_order_relaxed));
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
private:
|
|
42
|
+
static uint64_t pack(CGSize size)
|
|
43
|
+
{
|
|
44
|
+
float width = (float)size.width;
|
|
45
|
+
float height = (float)size.height;
|
|
46
|
+
uint32_t widthBits;
|
|
47
|
+
uint32_t heightBits;
|
|
48
|
+
memcpy(&widthBits, &width, sizeof(widthBits));
|
|
49
|
+
memcpy(&heightBits, &height, sizeof(heightBits));
|
|
50
|
+
return ((uint64_t)widthBits << 32) | heightBits;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
static CGSize unpack(uint64_t bits)
|
|
54
|
+
{
|
|
55
|
+
uint32_t widthBits = (uint32_t)(bits >> 32);
|
|
56
|
+
uint32_t heightBits = (uint32_t)bits;
|
|
57
|
+
float width;
|
|
58
|
+
float height;
|
|
59
|
+
memcpy(&width, &widthBits, sizeof(width));
|
|
60
|
+
memcpy(&height, &heightBits, sizeof(height));
|
|
61
|
+
return CGSizeMake(width, height);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
std::atomic<uint64_t> bits_{0};
|
|
65
|
+
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
#import "ENRMUIKit.h"
|
|
3
|
+
#include <TargetConditionals.h>
|
|
4
|
+
|
|
5
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
6
|
+
|
|
7
|
+
/// Selection-menu options that table, math and code block views need for their
|
|
8
|
+
/// own long-press menus. Every field is phrased so that the zero value keeps the
|
|
9
|
+
/// legacy behavior, so a block view that has not received options yet behaves
|
|
10
|
+
/// exactly as before.
|
|
11
|
+
typedef struct {
|
|
12
|
+
// `selectionMenuConfig.copy.enabled == false`.
|
|
13
|
+
BOOL copyHidden;
|
|
14
|
+
// `selectionMenuConfig.copy.format == 'markdown'`: the Copy item writes the
|
|
15
|
+
// block's Markdown instead of its raw content.
|
|
16
|
+
BOOL copyWritesMarkdown;
|
|
17
|
+
// `selectionMenuConfig.copyAsMarkdown.enabled == false`.
|
|
18
|
+
BOOL copyAsMarkdownHidden;
|
|
19
|
+
// `selectionMenuConfig.codeBlockCopyButton.enabled == false`.
|
|
20
|
+
BOOL copyButtonHidden;
|
|
21
|
+
} ENRMBlockMenuOptions;
|
|
22
|
+
|
|
23
|
+
#if !TARGET_OS_OSX
|
|
24
|
+
/// Builds the long-press menu shared by the table, math and code block views.
|
|
25
|
+
/// Returns nil when no item is left — nil is how UIKit suppresses a context
|
|
26
|
+
/// menu, whereas an empty menu would still lift the view.
|
|
27
|
+
static inline UIContextMenuConfiguration *_Nullable ENRMBlockContextMenuConfiguration(
|
|
28
|
+
ENRMBlockMenuOptions options, NSString *_Nullable copyLabel, NSString *_Nullable copyAsMarkdownLabel,
|
|
29
|
+
void (^copyRaw)(void), void (^copyMarkdown)(void))
|
|
30
|
+
{
|
|
31
|
+
if (options.copyHidden && options.copyAsMarkdownHidden) {
|
|
32
|
+
return nil;
|
|
33
|
+
}
|
|
34
|
+
void (^copyHandler)(void) = options.copyWritesMarkdown ? copyMarkdown : copyRaw;
|
|
35
|
+
return [UIContextMenuConfiguration
|
|
36
|
+
configurationWithIdentifier:nil
|
|
37
|
+
previewProvider:nil
|
|
38
|
+
actionProvider:^UIMenu *(NSArray<UIMenuElement *> *suggestedActions) {
|
|
39
|
+
NSMutableArray<UIMenuElement *> *children = [NSMutableArray arrayWithCapacity:2];
|
|
40
|
+
if (!options.copyHidden) {
|
|
41
|
+
[children addObject:[UIAction actionWithTitle:copyLabel ?: @""
|
|
42
|
+
image:[RCTUIImage systemImageNamed:@"doc.on.doc"]
|
|
43
|
+
identifier:nil
|
|
44
|
+
handler:^(__kindof UIAction *action) { copyHandler(); }]];
|
|
45
|
+
}
|
|
46
|
+
if (!options.copyAsMarkdownHidden) {
|
|
47
|
+
[children addObject:[UIAction actionWithTitle:copyAsMarkdownLabel ?: @""
|
|
48
|
+
image:[RCTUIImage systemImageNamed:@"doc.text"]
|
|
49
|
+
identifier:nil
|
|
50
|
+
handler:^(__kindof UIAction *action) { copyMarkdown(); }]];
|
|
51
|
+
}
|
|
52
|
+
return [UIMenu menuWithTitle:@"" children:children];
|
|
53
|
+
}];
|
|
54
|
+
}
|
|
55
|
+
#endif
|
|
56
|
+
|
|
57
|
+
NS_ASSUME_NONNULL_END
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#import <Foundation/Foundation.h>
|
|
4
|
+
|
|
5
|
+
@class MarkdownASTNode;
|
|
6
|
+
@class StyleConfig;
|
|
7
|
+
|
|
8
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
9
|
+
|
|
10
|
+
#ifdef __cplusplus
|
|
11
|
+
extern "C" {
|
|
12
|
+
#endif
|
|
13
|
+
|
|
14
|
+
/// Shared code block node semantics, used by both markdown flavors so the
|
|
15
|
+
/// meaning of a CodeBlock AST node (its text, language, fence) is defined in
|
|
16
|
+
/// one place. Language display names come from the shared C++ core
|
|
17
|
+
/// (cpp/highlight/CodeBlockLanguages.hpp) so all platforms label fences
|
|
18
|
+
/// identically.
|
|
19
|
+
|
|
20
|
+
NSString *ENRMCodeBlockExtractCode(MarkdownASTNode *node);
|
|
21
|
+
NSString *_Nullable ENRMCodeBlockLanguage(MarkdownASTNode *node);
|
|
22
|
+
NSString *ENRMCodeBlockFenceChar(MarkdownASTNode *node);
|
|
23
|
+
NSString *ENRMCodeBlockFencedMarkdown(NSString *code, NSString *_Nullable language, NSString *fenceChar);
|
|
24
|
+
NSString *ENRMCodeBlockDisplayLanguageName(NSString *_Nullable language);
|
|
25
|
+
|
|
26
|
+
/// Applies the flavor-independent code block text attributes (code font,
|
|
27
|
+
/// color, line height, forced-LTR left-aligned paragraph) to the range.
|
|
28
|
+
/// Callers layer their container-specific paragraph adjustments on top (the
|
|
29
|
+
/// commonmark span flavor adds padding indents; the github block view has
|
|
30
|
+
/// none).
|
|
31
|
+
void ENRMApplyCodeBlockTextAttributes(NSMutableAttributedString *string, NSRange range, StyleConfig *config);
|
|
32
|
+
|
|
33
|
+
#ifdef __cplusplus
|
|
34
|
+
}
|
|
35
|
+
#endif
|
|
36
|
+
|
|
37
|
+
NS_ASSUME_NONNULL_END
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
#import "ENRMCodeBlockContent.h"
|
|
2
|
+
#include "CodeBlockLanguages.hpp"
|
|
3
|
+
#import "ENRMUIKit.h"
|
|
4
|
+
#import "MarkdownASTNode.h"
|
|
5
|
+
#import "ParagraphStyleUtils.h"
|
|
6
|
+
#import "StyleConfig.h"
|
|
7
|
+
|
|
8
|
+
static void ENRMAppendNodeContent(MarkdownASTNode *node, NSMutableString *output)
|
|
9
|
+
{
|
|
10
|
+
if (node.content.length > 0) {
|
|
11
|
+
[output appendString:node.content];
|
|
12
|
+
}
|
|
13
|
+
for (MarkdownASTNode *child in node.children) {
|
|
14
|
+
ENRMAppendNodeContent(child, output);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
NSString *ENRMCodeBlockExtractCode(MarkdownASTNode *node)
|
|
19
|
+
{
|
|
20
|
+
NSMutableString *code = [NSMutableString string];
|
|
21
|
+
ENRMAppendNodeContent(node, code);
|
|
22
|
+
NSUInteger end = code.length;
|
|
23
|
+
while (end > 0 && [code characterAtIndex:end - 1] == '\n') {
|
|
24
|
+
end--;
|
|
25
|
+
}
|
|
26
|
+
return [code substringToIndex:end];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
NSString *ENRMCodeBlockLanguage(MarkdownASTNode *node)
|
|
30
|
+
{
|
|
31
|
+
NSString *language = node.attributes[@"language"];
|
|
32
|
+
return language.length > 0 ? language : nil;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
NSString *ENRMCodeBlockFenceChar(MarkdownASTNode *node)
|
|
36
|
+
{
|
|
37
|
+
NSString *fenceChar = node.attributes[@"fenceChar"];
|
|
38
|
+
return fenceChar.length > 0 ? fenceChar : @"`";
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
NSString *ENRMCodeBlockFencedMarkdown(NSString *code, NSString *language, NSString *fenceChar)
|
|
42
|
+
{
|
|
43
|
+
NSString *fence = [@"" stringByPaddingToLength:3 withString:fenceChar startingAtIndex:0];
|
|
44
|
+
return [NSString stringWithFormat:@"%@%@\n%@\n%@", fence, language ?: @"", code, fence];
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
NSString *ENRMCodeBlockDisplayLanguageName(NSString *language)
|
|
48
|
+
{
|
|
49
|
+
if (language.length == 0) {
|
|
50
|
+
return @"";
|
|
51
|
+
}
|
|
52
|
+
std::string display = Markdown::displayNameForLanguage(language.UTF8String ?: "");
|
|
53
|
+
return [NSString stringWithUTF8String:display.c_str()] ?: language;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
void ENRMApplyCodeBlockTextAttributes(NSMutableAttributedString *string, NSRange range, StyleConfig *config)
|
|
57
|
+
{
|
|
58
|
+
if (range.length == 0) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
UIFont *font = [config codeBlockFont];
|
|
63
|
+
RCTUIColor *color = [config codeBlockColor];
|
|
64
|
+
if (color) {
|
|
65
|
+
[string addAttributes:@{NSFontAttributeName : font, NSForegroundColorAttributeName : color} range:range];
|
|
66
|
+
} else {
|
|
67
|
+
[string addAttribute:NSFontAttributeName value:font range:range];
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
CGFloat lineHeight = [config codeBlockLineHeight];
|
|
71
|
+
if (lineHeight > 0) {
|
|
72
|
+
applyLineHeight(string, range, lineHeight);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
NSMutableParagraphStyle *paragraphStyle = [getOrCreateParagraphStyle(string, range.location) mutableCopy];
|
|
76
|
+
paragraphStyle.baseWritingDirection = NSWritingDirectionLeftToRight;
|
|
77
|
+
paragraphStyle.alignment = NSTextAlignmentLeft;
|
|
78
|
+
[string addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:range];
|
|
79
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#import <Foundation/Foundation.h>
|
|
4
|
+
|
|
5
|
+
@class StyleConfig;
|
|
6
|
+
|
|
7
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
8
|
+
|
|
9
|
+
#ifdef __cplusplus
|
|
10
|
+
extern "C" {
|
|
11
|
+
#endif
|
|
12
|
+
|
|
13
|
+
/// Platform adapter over the shared C++ syntax highlighting seam
|
|
14
|
+
/// (cpp/highlight/CodeBlockHighlighter.hpp).
|
|
15
|
+
///
|
|
16
|
+
/// Applies token colors as foreground-color attributes onto a mutable copy of
|
|
17
|
+
/// the plain styled code, so highlighting can never change text metrics and
|
|
18
|
+
/// the block height measured from the plain string stays valid. Token colors
|
|
19
|
+
/// come from the config's resolved per-token palette. Returns nil when
|
|
20
|
+
/// highlighting is unavailable (module compiled out, unknown language, parse
|
|
21
|
+
/// failure); callers keep the plain attributed code.
|
|
22
|
+
NSAttributedString *_Nullable ENRMHighlightedAttributedCode(NSAttributedString *plainCode, NSString *code,
|
|
23
|
+
NSString *_Nullable language, StyleConfig *config);
|
|
24
|
+
|
|
25
|
+
/// Applies token foreground colors from the config's palette onto `output`
|
|
26
|
+
/// within `range` (range.location is where the code begins in output). Used by
|
|
27
|
+
/// the commonmark flavor, which renders code inline instead of as a container.
|
|
28
|
+
/// Returns whether any color was applied. No-op when highlighting is
|
|
29
|
+
/// unavailable, so callers keep the plain rendering.
|
|
30
|
+
BOOL ENRMApplyHighlightTokens(NSMutableAttributedString *output, NSRange range, NSString *code,
|
|
31
|
+
NSString *_Nullable language, StyleConfig *config);
|
|
32
|
+
|
|
33
|
+
#ifdef __cplusplus
|
|
34
|
+
}
|
|
35
|
+
#endif
|
|
36
|
+
|
|
37
|
+
NS_ASSUME_NONNULL_END
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
#import "ENRMCodeBlockHighlighter.h"
|
|
2
|
+
#include "CodeBlockHighlighter.hpp"
|
|
3
|
+
#import "ENRMUIKit.h"
|
|
4
|
+
#import "StyleConfig.h"
|
|
5
|
+
|
|
6
|
+
BOOL ENRMApplyHighlightTokens(NSMutableAttributedString *output, NSRange range, NSString *code,
|
|
7
|
+
NSString *_Nullable language, StyleConfig *config)
|
|
8
|
+
{
|
|
9
|
+
if (code.length == 0) {
|
|
10
|
+
return NO;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
std::vector<Markdown::HighlightToken> tokens;
|
|
14
|
+
try {
|
|
15
|
+
tokens = Markdown::highlightCode(code.UTF8String ?: "", language.UTF8String ?: "");
|
|
16
|
+
} catch (...) {
|
|
17
|
+
return NO;
|
|
18
|
+
}
|
|
19
|
+
if (tokens.empty()) {
|
|
20
|
+
return NO;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
NSUInteger cap = MIN(NSMaxRange(range), output.length);
|
|
24
|
+
BOOL applied = NO;
|
|
25
|
+
for (const auto &token : tokens) {
|
|
26
|
+
RCTUIColor *color = [config codeBlockSyntaxColorForToken:(NSInteger)token.type];
|
|
27
|
+
if (!color || token.end <= token.start) {
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
NSUInteger start = range.location + token.start;
|
|
31
|
+
NSUInteger end = range.location + token.end;
|
|
32
|
+
if (end > cap) {
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
[output addAttribute:NSForegroundColorAttributeName value:color range:NSMakeRange(start, end - start)];
|
|
36
|
+
applied = YES;
|
|
37
|
+
}
|
|
38
|
+
return applied;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
NSAttributedString *ENRMHighlightedAttributedCode(NSAttributedString *plainCode, NSString *code,
|
|
42
|
+
NSString *_Nullable language, StyleConfig *config)
|
|
43
|
+
{
|
|
44
|
+
if (code.length == 0) {
|
|
45
|
+
return nil;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
NSMutableAttributedString *highlighted = [plainCode mutableCopy];
|
|
49
|
+
BOOL applied = ENRMApplyHighlightTokens(highlighted, NSMakeRange(0, highlighted.length), code, language, config);
|
|
50
|
+
return applied ? highlighted : nil;
|
|
51
|
+
}
|
|
@@ -10,3 +10,10 @@
|
|
|
10
10
|
#if !defined(ENRICHED_MARKDOWN_MATH)
|
|
11
11
|
#define ENRICHED_MARKDOWN_MATH 0
|
|
12
12
|
#endif
|
|
13
|
+
|
|
14
|
+
// Code-block syntax highlighting is defined purely by the podspec (no external
|
|
15
|
+
// framework to auto-detect, unlike RaTeX). Default off when the podspec did not
|
|
16
|
+
// enable it; the C++ seam then degrades to no tokens.
|
|
17
|
+
#if !defined(ENRICHED_MARKDOWN_CODE_HIGHLIGHT)
|
|
18
|
+
#define ENRICHED_MARKDOWN_CODE_HIGHLIGHT 0
|
|
19
|
+
#endif
|
|
@@ -5,11 +5,21 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
5
5
|
|
|
6
6
|
typedef void (^ENRMImageDownloadCompletion)(RCTUIImage *_Nullable image);
|
|
7
7
|
|
|
8
|
+
/**
|
|
9
|
+
* Cache identity for a remote image request. Returns the URL itself when no
|
|
10
|
+
* headers are set; otherwise appends a SHA-256 digest of the sorted header
|
|
11
|
+
* pairs, so the same URL fetched with different headers is cached and
|
|
12
|
+
* deduplicated separately without embedding header values in the key.
|
|
13
|
+
*/
|
|
14
|
+
NSString *ENRMImageCacheKey(NSString *url, NSDictionary<NSString *, NSString *> *_Nullable headers);
|
|
15
|
+
|
|
8
16
|
@interface ENRMImageDownloader : NSObject
|
|
9
17
|
|
|
10
18
|
+ (instancetype)shared;
|
|
11
19
|
|
|
12
|
-
- (void)downloadURL:(NSString *)url
|
|
20
|
+
- (void)downloadURL:(NSString *)url
|
|
21
|
+
headers:(nullable NSDictionary<NSString *, NSString *> *)headers
|
|
22
|
+
completion:(ENRMImageDownloadCompletion)completion;
|
|
13
23
|
|
|
14
24
|
@end
|
|
15
25
|
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
#import "ENRMImageDownloader.h"
|
|
2
2
|
#import "ENRMImageAttachment.h"
|
|
3
|
+
#import "ENRMLocalImageLoader.h"
|
|
4
|
+
#import <CommonCrypto/CommonDigest.h>
|
|
3
5
|
#include <TargetConditionals.h>
|
|
4
6
|
|
|
5
7
|
static const NSUInteger kDiskCacheMemoryCapacity = 10 * 1024 * 1024;
|
|
@@ -13,6 +15,27 @@ static inline NSUInteger ENRMImageByteCost(RCTUIImage *image)
|
|
|
13
15
|
return CGImageGetBytesPerRow(cgImage) * CGImageGetHeight(cgImage);
|
|
14
16
|
}
|
|
15
17
|
|
|
18
|
+
NSString *ENRMImageCacheKey(NSString *url, NSDictionary<NSString *, NSString *> *headers)
|
|
19
|
+
{
|
|
20
|
+
if (headers.count == 0) {
|
|
21
|
+
return url;
|
|
22
|
+
}
|
|
23
|
+
NSArray<NSString *> *names = [headers.allKeys sortedArrayUsingSelector:@selector(compare:)];
|
|
24
|
+
NSMutableArray<NSString *> *pairs = [NSMutableArray arrayWithCapacity:names.count];
|
|
25
|
+
for (NSString *name in names) {
|
|
26
|
+
[pairs addObject:[NSString stringWithFormat:@"%@:%@", name, headers[name]]];
|
|
27
|
+
}
|
|
28
|
+
NSString *joined = [pairs componentsJoinedByString:@"\n"];
|
|
29
|
+
NSData *data = [joined dataUsingEncoding:NSUTF8StringEncoding];
|
|
30
|
+
unsigned char digest[CC_SHA256_DIGEST_LENGTH];
|
|
31
|
+
CC_SHA256(data.bytes, (CC_LONG)data.length, digest);
|
|
32
|
+
NSMutableString *hash = [NSMutableString stringWithCapacity:CC_SHA256_DIGEST_LENGTH * 2];
|
|
33
|
+
for (int i = 0; i < CC_SHA256_DIGEST_LENGTH; i++) {
|
|
34
|
+
[hash appendFormat:@"%02x", digest[i]];
|
|
35
|
+
}
|
|
36
|
+
return [NSString stringWithFormat:@"%@|%@", url, hash];
|
|
37
|
+
}
|
|
38
|
+
|
|
16
39
|
@implementation ENRMImageDownloader {
|
|
17
40
|
NSURLSession *_session;
|
|
18
41
|
NSMutableDictionary<NSString *, NSMutableArray<ENRMImageDownloadCompletion> *> *_inFlightRequests;
|
|
@@ -43,56 +66,77 @@ static inline NSUInteger ENRMImageByteCost(RCTUIImage *image)
|
|
|
43
66
|
return self;
|
|
44
67
|
}
|
|
45
68
|
|
|
46
|
-
- (void)downloadURL:(NSString *)url
|
|
69
|
+
- (void)downloadURL:(NSString *)url
|
|
70
|
+
headers:(NSDictionary<NSString *, NSString *> *)headers
|
|
71
|
+
completion:(ENRMImageDownloadCompletion)completion
|
|
47
72
|
{
|
|
48
73
|
if (url.length == 0) {
|
|
49
74
|
completion(nil);
|
|
50
75
|
return;
|
|
51
76
|
}
|
|
52
77
|
|
|
53
|
-
|
|
78
|
+
BOOL isLocal = ENRMIsLocalImageURL(url);
|
|
79
|
+
NSString *cacheKey = isLocal ? url : ENRMImageCacheKey(url, headers);
|
|
80
|
+
|
|
81
|
+
RCTUIImage *cached = [[ENRMImageAttachment originalImageCache] objectForKey:cacheKey];
|
|
54
82
|
if (cached) {
|
|
55
83
|
completion(cached);
|
|
56
84
|
return;
|
|
57
85
|
}
|
|
58
86
|
|
|
87
|
+
if (isLocal) {
|
|
88
|
+
RCTUIImage *local = ENRMLoadLocalImage(url);
|
|
89
|
+
if (local) {
|
|
90
|
+
[[ENRMImageAttachment originalImageCache] setObject:local forKey:cacheKey cost:ENRMImageByteCost(local)];
|
|
91
|
+
}
|
|
92
|
+
completion(local);
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
|
|
59
96
|
@synchronized(_inFlightRequests) {
|
|
60
|
-
NSMutableArray *existing = _inFlightRequests[
|
|
97
|
+
NSMutableArray *existing = _inFlightRequests[cacheKey];
|
|
61
98
|
if (existing) {
|
|
62
99
|
[existing addObject:completion];
|
|
63
100
|
return;
|
|
64
101
|
}
|
|
65
|
-
_inFlightRequests[
|
|
102
|
+
_inFlightRequests[cacheKey] = [NSMutableArray arrayWithObject:completion];
|
|
66
103
|
}
|
|
67
104
|
|
|
68
105
|
NSURL *nsURL = [NSURL URLWithString:url];
|
|
69
106
|
if (!nsURL) {
|
|
70
|
-
[self
|
|
107
|
+
[self dispatchCallbacksForKey:cacheKey image:nil];
|
|
71
108
|
return;
|
|
72
109
|
}
|
|
73
110
|
|
|
74
|
-
[
|
|
75
|
-
|
|
111
|
+
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:nsURL];
|
|
112
|
+
[headers enumerateKeysAndObjectsUsingBlock:^(NSString *name, NSString *value, BOOL *stop) {
|
|
113
|
+
[request setValue:value forHTTPHeaderField:name];
|
|
114
|
+
}];
|
|
115
|
+
|
|
116
|
+
[[_session dataTaskWithRequest:request
|
|
117
|
+
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
|
|
76
118
|
#if !TARGET_OS_OSX
|
|
77
|
-
|
|
119
|
+
RCTUIImage *image = (data && !error) ? [RCTUIImage imageWithData:data] : nil;
|
|
78
120
|
#else
|
|
79
121
|
RCTUIImage *image = (data && !error) ? [[RCTUIImage alloc] initWithData:data] : nil;
|
|
80
122
|
#endif
|
|
81
123
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
124
|
+
if (image) {
|
|
125
|
+
[[ENRMImageAttachment originalImageCache] setObject:image
|
|
126
|
+
forKey:cacheKey
|
|
127
|
+
cost:ENRMImageByteCost(image)];
|
|
128
|
+
}
|
|
85
129
|
|
|
86
|
-
|
|
87
|
-
|
|
130
|
+
[self dispatchCallbacksForKey:cacheKey image:image];
|
|
131
|
+
}] resume];
|
|
88
132
|
}
|
|
89
133
|
|
|
90
|
-
- (void)
|
|
134
|
+
- (void)dispatchCallbacksForKey:(NSString *)cacheKey image:(RCTUIImage *_Nullable)image
|
|
91
135
|
{
|
|
92
136
|
NSArray<ENRMImageDownloadCompletion> *callbacks;
|
|
93
137
|
@synchronized(_inFlightRequests) {
|
|
94
|
-
callbacks = [_inFlightRequests[
|
|
95
|
-
[_inFlightRequests removeObjectForKey:
|
|
138
|
+
callbacks = [_inFlightRequests[cacheKey] copy];
|
|
139
|
+
[_inFlightRequests removeObjectForKey:cacheKey];
|
|
96
140
|
}
|
|
97
141
|
|
|
98
142
|
if (!callbacks)
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
#import "ENRMUIKit.h"
|
|
3
|
+
|
|
4
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Local (non-network) image loading for markdown sources (issue #377).
|
|
8
|
+
*
|
|
9
|
+
* React Native's asset system resolves `require('./img.png')` to a Metro http
|
|
10
|
+
* URL in dev, but to a `file://` URL near the app bundle in release builds
|
|
11
|
+
* (`AssetSourceResolver.scaledAssetURLNearBundle`), and libraries like
|
|
12
|
+
* expo-asset also hand out percent-encoded `file://` paths in the caches
|
|
13
|
+
* directory. These should not go through NSURLSession + NSURLCache: they gain
|
|
14
|
+
* nothing from HTTP caching or timeouts, and bundle assets lose `@2x`/`@3x`
|
|
15
|
+
* scale selection and asset-catalog resolution.
|
|
16
|
+
*
|
|
17
|
+
* Resolution mirrors RN's RCTImageFromLocalAssetURL: bundle-relative names are
|
|
18
|
+
* tried with `imageNamed:` first (scale suffixes, asset catalogs, and system
|
|
19
|
+
* caching for free), then the loader falls back to loading the file directly,
|
|
20
|
+
* appending `.png` when the path has no extension.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
/// YES when the URL refers to a non-network source: any `file://` URL, or a
|
|
24
|
+
/// scheme-less string (bare bundle-relative asset name or absolute path).
|
|
25
|
+
BOOL ENRMIsLocalImageURL(NSString *url);
|
|
26
|
+
|
|
27
|
+
/// Synchronously loads a local image; returns nil when the source cannot be
|
|
28
|
+
/// resolved. Safe to call off the main thread.
|
|
29
|
+
RCTUIImage *_Nullable ENRMLoadLocalImage(NSString *url);
|
|
30
|
+
|
|
31
|
+
NS_ASSUME_NONNULL_END
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
#import "ENRMLocalImageLoader.h"
|
|
2
|
+
|
|
3
|
+
static NSString *_Nullable ENRMBundleRelativePath(NSString *path)
|
|
4
|
+
{
|
|
5
|
+
NSString *bundlePath = [[NSBundle mainBundle] resourcePath];
|
|
6
|
+
if (bundlePath == nil || ![path hasPrefix:bundlePath]) {
|
|
7
|
+
return nil;
|
|
8
|
+
}
|
|
9
|
+
NSString *relative = [path substringFromIndex:bundlePath.length];
|
|
10
|
+
return [relative hasPrefix:@"/"] ? [relative substringFromIndex:1] : relative;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
static RCTUIImage *_Nullable ENRMImageNamed(NSString *name)
|
|
14
|
+
{
|
|
15
|
+
return [RCTUIImage imageNamed:name];
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
static RCTUIImage *_Nullable ENRMImageAtPath(NSString *path)
|
|
19
|
+
{
|
|
20
|
+
if (path.pathExtension.length == 0) {
|
|
21
|
+
path = [path stringByAppendingPathExtension:@"png"];
|
|
22
|
+
}
|
|
23
|
+
#if !TARGET_OS_OSX
|
|
24
|
+
return [RCTUIImage imageWithContentsOfFile:path];
|
|
25
|
+
#else
|
|
26
|
+
return [[RCTUIImage alloc] initWithContentsOfFile:path];
|
|
27
|
+
#endif
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
BOOL ENRMIsLocalImageURL(NSString *url)
|
|
31
|
+
{
|
|
32
|
+
if ([url hasPrefix:@"file://"]) {
|
|
33
|
+
return YES;
|
|
34
|
+
}
|
|
35
|
+
NSURL *parsed = [NSURL URLWithString:url];
|
|
36
|
+
return parsed == nil || parsed.scheme.length == 0;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
RCTUIImage *_Nullable ENRMLoadLocalImage(NSString *url)
|
|
40
|
+
{
|
|
41
|
+
NSString *filePath = nil;
|
|
42
|
+
NSString *imageName = nil;
|
|
43
|
+
|
|
44
|
+
if ([url hasPrefix:@"file://"]) {
|
|
45
|
+
NSURL *fileURL = [NSURL URLWithString:url];
|
|
46
|
+
if (fileURL.fileURL) {
|
|
47
|
+
filePath = @(fileURL.fileSystemRepresentation);
|
|
48
|
+
} else {
|
|
49
|
+
NSString *stripped = [url substringFromIndex:@"file://".length];
|
|
50
|
+
filePath = [stripped stringByRemovingPercentEncoding] ?: stripped;
|
|
51
|
+
}
|
|
52
|
+
imageName = ENRMBundleRelativePath(filePath);
|
|
53
|
+
} else {
|
|
54
|
+
NSString *decoded = [url stringByRemovingPercentEncoding] ?: url;
|
|
55
|
+
if (decoded.absolutePath) {
|
|
56
|
+
filePath = decoded;
|
|
57
|
+
} else {
|
|
58
|
+
imageName = decoded;
|
|
59
|
+
filePath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:decoded];
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
RCTUIImage *image = imageName.length > 0 ? ENRMImageNamed(imageName) : nil;
|
|
64
|
+
if (image == nil && filePath.length > 0) {
|
|
65
|
+
image = ENRMImageAtPath(filePath);
|
|
66
|
+
}
|
|
67
|
+
return image;
|
|
68
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
#import "ENRMUIKit.h"
|
|
3
|
+
#import <Foundation/Foundation.h>
|
|
4
|
+
|
|
5
|
+
static const CGFloat kENRMMathFallbackDefaultFontSize = 16.0;
|
|
6
|
+
|
|
7
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
8
|
+
|
|
9
|
+
#ifdef __cplusplus
|
|
10
|
+
extern "C" {
|
|
11
|
+
#endif
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Builds the visible-source fallback for a RaTeX parse failure: the original
|
|
15
|
+
* LaTeX source wrapped in its delimiters ($ inline, $$ block), typeset in body
|
|
16
|
+
* style. A parse failure must never render as an invisible zero-size box —
|
|
17
|
+
* the formula stays visible and copyable instead.
|
|
18
|
+
*/
|
|
19
|
+
NSAttributedString *ENRMMathFallbackString(NSString *_Nullable latex, NSString *delimiter, CGFloat fontSize,
|
|
20
|
+
RCTUIColor *_Nullable color);
|
|
21
|
+
|
|
22
|
+
#ifdef __cplusplus
|
|
23
|
+
}
|
|
24
|
+
#endif
|
|
25
|
+
|
|
26
|
+
NS_ASSUME_NONNULL_END
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
#import "ENRMMathFallback.h"
|
|
2
|
+
|
|
3
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
4
|
+
|
|
5
|
+
NSAttributedString *ENRMMathFallbackString(NSString *_Nullable latex, NSString *delimiter, CGFloat fontSize,
|
|
6
|
+
RCTUIColor *_Nullable color)
|
|
7
|
+
{
|
|
8
|
+
CGFloat size = fontSize > 0 ? fontSize : kENRMMathFallbackDefaultFontSize;
|
|
9
|
+
UIFont *font = [UIFont systemFontOfSize:size];
|
|
10
|
+
NSString *source = [NSString stringWithFormat:@"%@%@%@", delimiter, latex ?: @"", delimiter];
|
|
11
|
+
return [[NSAttributedString alloc] initWithString:source
|
|
12
|
+
attributes:@{
|
|
13
|
+
NSFontAttributeName : font,
|
|
14
|
+
NSForegroundColorAttributeName : color ?: [RCTUIColor blackColor],
|
|
15
|
+
}];
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
NS_ASSUME_NONNULL_END
|