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,511 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Restores the tree-sitter runtime, each supported grammar's minimal source set,
|
|
3
|
+
// and the default-language registry into packages/core/cpp/highlight/vendor/.
|
|
4
|
+
// The whole vendor/ tree (runtime, grammars, generated registry) is GITIGNORED
|
|
5
|
+
// and reproduced on demand from the pins in grammar-versions.json, so nothing
|
|
6
|
+
// generated lives in git. This one command is wired into the package `prepare`
|
|
7
|
+
// hook (run `yarn prepare` to self-heal the working tree; note this repo is Yarn 4
|
|
8
|
+
// (Berry), where a plain `yarn install` does NOT run the workspace `prepare`
|
|
9
|
+
// script) and into `prepack` (so the published npm tarball still ships the full
|
|
10
|
+
// set).
|
|
11
|
+
//
|
|
12
|
+
// node vendor/vendor-grammars.mjs
|
|
13
|
+
// Ensures the runtime (fetched from the pinned GitHub release tarball), every
|
|
14
|
+
// grammar (copied from the grammar devDependencies), and the default registry
|
|
15
|
+
// are present and up to date. Idempotent: .stamp fingerprints on the runtime
|
|
16
|
+
// ref+sha and on the pinned grammar versions make repeated runs a no-op, so
|
|
17
|
+
// re-running `prepare` never re-fetches or rewrites an up-to-date tree.
|
|
18
|
+
//
|
|
19
|
+
// Flags:
|
|
20
|
+
// --only json,css Restore just these grammars (dev/testing). Skips the
|
|
21
|
+
// default-registry refresh and the stamp, so it never
|
|
22
|
+
// clobbers the full vendored set.
|
|
23
|
+
// --force Re-fetch the runtime and rewrite every grammar regardless
|
|
24
|
+
// of the stamps.
|
|
25
|
+
// --runtime-src <lib dir> Use a local tree-sitter lib/ checkout instead of
|
|
26
|
+
// fetching the tarball (offline / maintainer override).
|
|
27
|
+
// --from-npm Download grammar sources from the npm registry instead of
|
|
28
|
+
// copying from devDependency node_modules. Used by the
|
|
29
|
+
// postinstall script in published packages where the grammar
|
|
30
|
+
// devDependencies are not installed.
|
|
31
|
+
// --vendor-dir <dir> Override the default vendor output directory.
|
|
32
|
+
// --manifest <path> Override the default grammar-versions.json path.
|
|
33
|
+
//
|
|
34
|
+
// Only parser.c, scanner.c (when present), tree_sitter/*.h, highlights.scm and
|
|
35
|
+
// LICENSE are copied per grammar; nothing else from the grammar packages ships.
|
|
36
|
+
// WASM is left out of the runtime by never defining TREE_SITTER_FEATURE_WASM at
|
|
37
|
+
// build time, so the full lib/src tree (including wasm_store.c and its no-op
|
|
38
|
+
// stubs) is vendored verbatim and only lib.c is compiled.
|
|
39
|
+
|
|
40
|
+
import fs from 'node:fs';
|
|
41
|
+
import os from 'node:os';
|
|
42
|
+
import path from 'node:path';
|
|
43
|
+
import crypto from 'node:crypto';
|
|
44
|
+
import { fileURLToPath } from 'node:url';
|
|
45
|
+
import { spawnSync, } from 'node:child_process';
|
|
46
|
+
import { createRequire } from 'node:module';
|
|
47
|
+
|
|
48
|
+
const here = path.dirname(fileURLToPath(import.meta.url));
|
|
49
|
+
const repoRoot = path.resolve(here, '..');
|
|
50
|
+
let vendorOut = path.join(repoRoot, 'packages/core/cpp/highlight/vendor');
|
|
51
|
+
let manifestPath = path.join(here, 'grammar-versions.json');
|
|
52
|
+
|
|
53
|
+
const LOG_PREFIX = '[react-native-enriched-markdown-scaffold]';
|
|
54
|
+
const log = (message) => console.log(`${LOG_PREFIX} ${message}`);
|
|
55
|
+
const warn = (message) => console.warn(`${LOG_PREFIX} ${message}`);
|
|
56
|
+
|
|
57
|
+
// Grammar packages are devDependencies of react-native-enriched-markdown, so
|
|
58
|
+
// resolve them from that workspace regardless of hoisting.
|
|
59
|
+
const pkgRequire = createRequire(
|
|
60
|
+
path.join(repoRoot, 'packages/react-native-enriched-markdown/package.json')
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
function parseArgs(argv) {
|
|
64
|
+
const args = { only: null, runtimeSrc: null, force: false, fromNpm: false, vendorDir: null, manifest: null };
|
|
65
|
+
for (let i = 0; i < argv.length; i++) {
|
|
66
|
+
if (argv[i] === '--only') args.only = argv[++i].split(',').map((s) => s.trim());
|
|
67
|
+
else if (argv[i] === '--runtime-src') args.runtimeSrc = argv[++i];
|
|
68
|
+
else if (argv[i] === '--force') args.force = true;
|
|
69
|
+
else if (argv[i] === '--from-npm') args.fromNpm = true;
|
|
70
|
+
else if (argv[i] === '--vendor-dir') args.vendorDir = argv[++i];
|
|
71
|
+
else if (argv[i] === '--manifest') args.manifest = argv[++i];
|
|
72
|
+
// --grammars-only is accepted for backward compatibility; the single restore
|
|
73
|
+
// flow already covers grammars, so it is a no-op.
|
|
74
|
+
else if (argv[i] === '--grammars-only') continue;
|
|
75
|
+
}
|
|
76
|
+
return args;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function fail(message) {
|
|
80
|
+
console.error(`${LOG_PREFIX} ${message}`);
|
|
81
|
+
process.exit(1);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function copyFile(src, dest) {
|
|
85
|
+
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
|
86
|
+
fs.copyFileSync(src, dest);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function copyDir(src, dest) {
|
|
90
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
91
|
+
for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
|
|
92
|
+
const from = path.join(src, entry.name);
|
|
93
|
+
const to = path.join(dest, entry.name);
|
|
94
|
+
if (entry.isDirectory()) copyDir(from, to);
|
|
95
|
+
else copyFile(from, to);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function firstExisting(candidates) {
|
|
100
|
+
return candidates.find((p) => p && fs.existsSync(p)) ?? null;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Copies lib/src + lib/include/tree_sitter/api.h from a tree-sitter `lib`
|
|
104
|
+
// checkout into the vendor tree. Shared by the tarball and --runtime-src paths.
|
|
105
|
+
function copyRuntimeFromLib(libDir) {
|
|
106
|
+
const srcDir = path.join(libDir, 'src');
|
|
107
|
+
const apiHeader = path.join(libDir, 'include/tree_sitter/api.h');
|
|
108
|
+
if (!fs.existsSync(path.join(srcDir, 'lib.c')) || !fs.existsSync(apiHeader)) {
|
|
109
|
+
fail(`runtime source at ${libDir} is missing src/lib.c or include/tree_sitter/api.h`);
|
|
110
|
+
}
|
|
111
|
+
const outSrc = path.join(vendorOut, 'tree-sitter/src');
|
|
112
|
+
fs.rmSync(outSrc, { recursive: true, force: true });
|
|
113
|
+
copyDir(srcDir, outSrc);
|
|
114
|
+
copyFile(apiHeader, path.join(vendorOut, 'tree-sitter/include/tree_sitter/api.h'));
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function runtimeTarballUrl(runtime) {
|
|
118
|
+
return runtime.tarball ?? `https://github.com/tree-sitter/tree-sitter/archive/refs/tags/${runtime.ref}.tar.gz`;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Downloads the pinned runtime tarball, verifies its sha256 against the manifest,
|
|
122
|
+
// extracts it to a temp dir with the system `tar`, and returns the `lib/` path.
|
|
123
|
+
// A sha mismatch is fatal and prints the computed digest to paste back into the
|
|
124
|
+
// manifest on a deliberate re-pin.
|
|
125
|
+
async function fetchRuntimeLib(runtime) {
|
|
126
|
+
const url = runtimeTarballUrl(runtime);
|
|
127
|
+
if (!runtime.sha256) {
|
|
128
|
+
fail(`runtime.sha256 missing in grammar-versions.json; cannot verify ${url}`);
|
|
129
|
+
}
|
|
130
|
+
log(`fetching runtime ${runtime.ref} from ${url}`);
|
|
131
|
+
let buf;
|
|
132
|
+
try {
|
|
133
|
+
const res = await fetch(url);
|
|
134
|
+
if (!res.ok) fail(`runtime download failed: ${res.status} ${res.statusText} for ${url}`);
|
|
135
|
+
buf = Buffer.from(await res.arrayBuffer());
|
|
136
|
+
} catch (err) {
|
|
137
|
+
fail(`runtime download failed for ${url}: ${err.message}. Pass --runtime-src to vendor from a local checkout offline.`);
|
|
138
|
+
}
|
|
139
|
+
const digest = crypto.createHash('sha256').update(buf).digest('hex');
|
|
140
|
+
if (digest !== runtime.sha256) {
|
|
141
|
+
fail(
|
|
142
|
+
`runtime tarball sha256 mismatch for ${url}\n expected ${runtime.sha256}\n got ${digest}\n` +
|
|
143
|
+
'If this is a deliberate re-pin, update runtime.sha256 in grammar-versions.json to the "got" value.'
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'ts-runtime-'));
|
|
147
|
+
const tgz = path.join(tmp, 'runtime.tar.gz');
|
|
148
|
+
fs.writeFileSync(tgz, buf);
|
|
149
|
+
const untar = spawnSync('tar', ['-xzf', tgz, '-C', tmp], { stdio: 'inherit' });
|
|
150
|
+
if (untar.status !== 0) fail(`tar failed to extract ${tgz} (status ${untar.status})`);
|
|
151
|
+
const top = fs
|
|
152
|
+
.readdirSync(tmp, { withFileTypes: true })
|
|
153
|
+
.find((e) => e.isDirectory() && e.name.startsWith('tree-sitter-'));
|
|
154
|
+
if (!top) fail(`extracted runtime tarball has no tree-sitter-* directory in ${tmp}`);
|
|
155
|
+
return { libDir: path.join(tmp, top.name, 'lib'), tmp };
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Fingerprint of the pinned runtime: ref + sha (+ 'local' when sourced from a
|
|
159
|
+
// checkout). A re-pin invalidates it; matching stamp + present lib.c is a no-op.
|
|
160
|
+
function runtimeStampKey(runtime, fromLocal) {
|
|
161
|
+
return `${runtime.ref}|${runtime.sha256 ?? 'nosha'}|${fromLocal ? 'local' : 'tarball'}`;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
async function ensureRuntime(manifest, args) {
|
|
165
|
+
const runtime = manifest.runtime ?? {};
|
|
166
|
+
const localLib = firstExisting([args.runtimeSrc, process.env.TREE_SITTER_SRC].filter(Boolean));
|
|
167
|
+
const stampFile = path.join(vendorOut, 'tree-sitter/.stamp');
|
|
168
|
+
const stampKey = runtimeStampKey(runtime, !!localLib);
|
|
169
|
+
const present = fs.existsSync(path.join(vendorOut, 'tree-sitter/src/lib.c'));
|
|
170
|
+
|
|
171
|
+
if (!args.force && present && readStamp(stampFile) === stampKey) {
|
|
172
|
+
log('runtime already up to date; skipping.');
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
if (localLib) {
|
|
177
|
+
copyRuntimeFromLib(localLib);
|
|
178
|
+
} else {
|
|
179
|
+
const { libDir, tmp } = await fetchRuntimeLib(runtime);
|
|
180
|
+
try {
|
|
181
|
+
copyRuntimeFromLib(libDir);
|
|
182
|
+
} finally {
|
|
183
|
+
fs.rmSync(tmp, { recursive: true, force: true });
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
fs.writeFileSync(stampFile, stampKey + '\n');
|
|
187
|
+
log(`runtime -> ${path.relative(repoRoot, path.join(vendorOut, 'tree-sitter/src'))}`);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
function packageRoot(pkgName) {
|
|
191
|
+
try {
|
|
192
|
+
return path.dirname(pkgRequire.resolve(`${pkgName}/package.json`));
|
|
193
|
+
} catch {
|
|
194
|
+
fail(`grammar package ${pkgName} not installed. Add it as a devDependency and run yarn install.`);
|
|
195
|
+
return '';
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// Resolves a grammar's highlights.scm from its package (null if it ships none).
|
|
200
|
+
// A grammar with no highlights query cannot be compiled into the registry, so
|
|
201
|
+
// callers skip it. Kept separate so main() can pre-filter without side effects.
|
|
202
|
+
function grammarHighlights(spec, pkgRootOverride) {
|
|
203
|
+
const pkgRoot = pkgRootOverride ?? packageRoot(spec.package);
|
|
204
|
+
const base = spec.subPath ? path.join(pkgRoot, spec.subPath) : pkgRoot;
|
|
205
|
+
return firstExisting([
|
|
206
|
+
path.join(base, 'queries/highlights.scm'),
|
|
207
|
+
path.join(pkgRoot, 'queries/highlights.scm'),
|
|
208
|
+
]);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// tree-sitter grammars that build on another grammar's queries usually say so
|
|
212
|
+
// with a leading `; inherits:` comment, which gen-registry.mjs reads to inline
|
|
213
|
+
// the parent's captures. Some packages (notably tree-sitter-typescript) instead
|
|
214
|
+
// list the base query in their package's `queries` array and ship a
|
|
215
|
+
// highlights.scm with no such comment, so a verbatim copy drops every inherited
|
|
216
|
+
// capture -- for TypeScript that means strings, comments, and all base
|
|
217
|
+
// JavaScript keywords/functions, leaving only the TS-only supplement colored.
|
|
218
|
+
// Materialize the manifest's `inherits` as that comment here so the existing
|
|
219
|
+
// gen-registry inlining restores full highlighting. Idempotent: parents already
|
|
220
|
+
// named by an upstream `; inherits:` line are merged, not duplicated.
|
|
221
|
+
const INHERITS_RE = /^[ \t]*;+[ \t]*inherits[ \t]*:[ \t]*([^\n]+)$/m;
|
|
222
|
+
|
|
223
|
+
function writeHighlights(srcFile, destFile, spec) {
|
|
224
|
+
const raw = fs.readFileSync(srcFile, 'utf8');
|
|
225
|
+
const existing = raw.match(INHERITS_RE);
|
|
226
|
+
const parents = existing
|
|
227
|
+
? existing[1].split(',').map((s) => s.trim()).filter(Boolean)
|
|
228
|
+
: [];
|
|
229
|
+
for (const parent of spec.inherits ?? []) {
|
|
230
|
+
if (!parents.includes(parent)) parents.push(parent);
|
|
231
|
+
}
|
|
232
|
+
if (parents.length === 0) {
|
|
233
|
+
copyFile(srcFile, destFile);
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
const body = raw.replace(INHERITS_RE, '').replace(/^\n+/, '');
|
|
237
|
+
fs.mkdirSync(path.dirname(destFile), { recursive: true });
|
|
238
|
+
fs.writeFileSync(destFile, `; inherits: ${parents.join(',')}\n${body}`);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
function vendorGrammar(id, spec, pkgRootOverride) {
|
|
242
|
+
const pkgRoot = pkgRootOverride ?? packageRoot(spec.package);
|
|
243
|
+
const base = spec.subPath ? path.join(pkgRoot, spec.subPath) : pkgRoot;
|
|
244
|
+
const srcDir = path.join(base, 'src');
|
|
245
|
+
const outDir = path.join(vendorOut, 'grammars', id);
|
|
246
|
+
|
|
247
|
+
const parser = path.join(srcDir, 'parser.c');
|
|
248
|
+
if (!fs.existsSync(parser)) fail(`${id}: parser.c not found at ${parser}`);
|
|
249
|
+
|
|
250
|
+
if (spec.scanner && !fs.existsSync(path.join(srcDir, 'scanner.c'))) {
|
|
251
|
+
fail(`${id}: scanner:true but scanner.c missing at ${srcDir}`);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// Resolve highlights before writing anything so a highlights-less grammar
|
|
255
|
+
// never leaves a partial output dir (main() filters these out up front).
|
|
256
|
+
const highlights = grammarHighlights(spec, pkgRootOverride);
|
|
257
|
+
if (!highlights) fail(`${id}: queries/highlights.scm not found under ${base} or ${pkgRoot}`);
|
|
258
|
+
|
|
259
|
+
fs.rmSync(outDir, { recursive: true, force: true });
|
|
260
|
+
|
|
261
|
+
// Copy every loose .c/.h in src/ (parser.c, scanner.c, plus siblings a scanner
|
|
262
|
+
// text-includes such as html's tag.h or yaml's schema.*.c). Only parser.c and
|
|
263
|
+
// scanner.c are compiled; the rest are include-only. node-types.json,
|
|
264
|
+
// grammar.json and other non-source files are left behind.
|
|
265
|
+
for (const entry of fs.readdirSync(srcDir, { withFileTypes: true })) {
|
|
266
|
+
if (entry.isFile() && /\.(c|h)$/.test(entry.name)) {
|
|
267
|
+
copyFile(path.join(srcDir, entry.name), path.join(outDir, entry.name));
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
const headerDir = path.join(srcDir, 'tree_sitter');
|
|
272
|
+
if (fs.existsSync(headerDir)) copyDir(headerDir, path.join(outDir, 'tree_sitter'));
|
|
273
|
+
|
|
274
|
+
writeHighlights(highlights, path.join(outDir, 'highlights.scm'), spec);
|
|
275
|
+
|
|
276
|
+
const license = firstExisting([
|
|
277
|
+
path.join(pkgRoot, 'LICENSE'),
|
|
278
|
+
path.join(pkgRoot, 'LICENSE.md'),
|
|
279
|
+
path.join(pkgRoot, 'LICENSE.txt'),
|
|
280
|
+
]);
|
|
281
|
+
if (license) copyFile(license, path.join(outDir, 'LICENSE'));
|
|
282
|
+
|
|
283
|
+
// Localize any header a source file includes from outside its own src/ dir.
|
|
284
|
+
// tree-sitter-typescript's typescript and tsx grammars both text-include
|
|
285
|
+
// "../../common/scanner.h", a header shared at the package root that the
|
|
286
|
+
// per-grammar copy above (which only walks src/) leaves behind. Copy each into
|
|
287
|
+
// the grammar dir under its basename and rewrite the escaping include to that
|
|
288
|
+
// basename, so it resolves through the grammar's own quoted includes -- its
|
|
289
|
+
// tree_sitter/parser.h is vendored alongside -- with no shared search path.
|
|
290
|
+
for (const rel of spec.sharedSrc ?? []) {
|
|
291
|
+
const from = path.join(srcDir, rel);
|
|
292
|
+
if (!fs.existsSync(from)) fail(`${id}: sharedSrc '${rel}' not found at ${from}`);
|
|
293
|
+
const base = path.basename(rel);
|
|
294
|
+
copyFile(from, path.join(outDir, base));
|
|
295
|
+
for (const entry of fs.readdirSync(outDir, { withFileTypes: true })) {
|
|
296
|
+
if (!entry.isFile() || !/\.(c|h)$/.test(entry.name)) continue;
|
|
297
|
+
const filePath = path.join(outDir, entry.name);
|
|
298
|
+
const text = fs.readFileSync(filePath, 'utf8');
|
|
299
|
+
const rewritten = text.split(`"${rel}"`).join(`"${base}"`);
|
|
300
|
+
if (rewritten !== text) fs.writeFileSync(filePath, rewritten);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
log(`${id} -> ${path.relative(repoRoot, outDir)}`);
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
function regenerateDefaultRegistry(manifest) {
|
|
308
|
+
const defaults = Object.entries(manifest.grammars)
|
|
309
|
+
.filter(([, spec]) => spec.default)
|
|
310
|
+
.map(([id]) => id);
|
|
311
|
+
const outDir = path.join(vendorOut, 'generated');
|
|
312
|
+
const result = spawnSync(
|
|
313
|
+
process.execPath,
|
|
314
|
+
[
|
|
315
|
+
path.join(here, 'gen-registry.mjs'),
|
|
316
|
+
'--vendor-dir',
|
|
317
|
+
vendorOut,
|
|
318
|
+
'--languages',
|
|
319
|
+
defaults.join(','),
|
|
320
|
+
'--out',
|
|
321
|
+
outDir,
|
|
322
|
+
],
|
|
323
|
+
{ stdio: 'inherit' }
|
|
324
|
+
);
|
|
325
|
+
if (result.status !== 0) fail('gen-registry.mjs failed while refreshing the committed default set');
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
function requireSpec(manifest, id) {
|
|
329
|
+
const spec = manifest.grammars[id];
|
|
330
|
+
if (!spec) fail(`unknown grammar '${id}' (not in grammar-versions.json)`);
|
|
331
|
+
return spec;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
// Fingerprint of the pinned grammar set: manifest spec plus each grammar
|
|
335
|
+
// package's installed version, so a re-pin OR a node_modules change invalidates.
|
|
336
|
+
function grammarStampKey(manifest, ids) {
|
|
337
|
+
const parts = ids.map((id) => {
|
|
338
|
+
const spec = requireSpec(manifest, id);
|
|
339
|
+
let version = 'missing';
|
|
340
|
+
try {
|
|
341
|
+
version = pkgRequire(`${spec.package}/package.json`).version;
|
|
342
|
+
} catch {
|
|
343
|
+
/* resolved lazily during copy; a miss just forces a rebuild */
|
|
344
|
+
}
|
|
345
|
+
return `${id}|${spec.package}@${version}|scanner:${!!spec.scanner}|sub:${spec.subPath ?? ''}|shared:${(spec.sharedSrc ?? []).join('+')}`;
|
|
346
|
+
});
|
|
347
|
+
return crypto.createHash('sha256').update(JSON.stringify(parts)).digest('hex');
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
function everyGrammarPresent(ids) {
|
|
351
|
+
return ids.every((id) => fs.existsSync(path.join(vendorOut, 'grammars', id, 'parser.c')));
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
function readStamp(stampFile) {
|
|
355
|
+
return fs.existsSync(stampFile) ? fs.readFileSync(stampFile, 'utf8').trim() : null;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
// Drops grammars whose package ships no highlights.scm (they cannot be compiled
|
|
359
|
+
// into any registry). A default-set grammar missing one is a hard error; others
|
|
360
|
+
// are skipped with a warning and any stale output removed.
|
|
361
|
+
function vendorableIds(manifest, ids) {
|
|
362
|
+
const out = [];
|
|
363
|
+
for (const id of ids) {
|
|
364
|
+
const spec = requireSpec(manifest, id);
|
|
365
|
+
if (grammarHighlights(spec)) {
|
|
366
|
+
out.push(id);
|
|
367
|
+
} else if (spec.default) {
|
|
368
|
+
fail(`${id} is in the default set but its package ships no queries/highlights.scm`);
|
|
369
|
+
} else {
|
|
370
|
+
fs.rmSync(path.join(vendorOut, 'grammars', id), { recursive: true, force: true });
|
|
371
|
+
warn(`${id}: package ships no highlights.scm; skipping (non-default, not compilable).`);
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
return out;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
function registryPresent() {
|
|
378
|
+
return fs.existsSync(path.join(vendorOut, 'generated/generated_registry.cpp'));
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
// ---------------------------------------------------------------------------
|
|
382
|
+
// --from-npm: download grammar packages from the npm registry instead of
|
|
383
|
+
// copying from devDependency node_modules. Used by the postinstall script
|
|
384
|
+
// in published packages where the grammar devDependencies are not installed.
|
|
385
|
+
// ---------------------------------------------------------------------------
|
|
386
|
+
|
|
387
|
+
function npmTarballUrl(pkg, version) {
|
|
388
|
+
if (pkg.startsWith('@')) {
|
|
389
|
+
const bare = pkg.split('/')[1];
|
|
390
|
+
return `https://registry.npmjs.org/${pkg}/-/${bare}-${version}.tgz`;
|
|
391
|
+
}
|
|
392
|
+
return `https://registry.npmjs.org/${pkg}/-/${pkg}-${version}.tgz`;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
async function downloadNpmTarballs(grammars, ids) {
|
|
396
|
+
const byPkg = new Map();
|
|
397
|
+
for (const id of ids) {
|
|
398
|
+
const spec = grammars[id];
|
|
399
|
+
const key = `${spec.package}@${spec.version}`;
|
|
400
|
+
if (!byPkg.has(key)) byPkg.set(key, { spec, ids: [] });
|
|
401
|
+
byPkg.get(key).ids.push(id);
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
const extracted = new Map();
|
|
405
|
+
await Promise.all(
|
|
406
|
+
[...byPkg.entries()].map(async ([key, { spec }]) => {
|
|
407
|
+
const url = npmTarballUrl(spec.package, spec.version);
|
|
408
|
+
log(`downloading ${key} ...`);
|
|
409
|
+
let buf;
|
|
410
|
+
try {
|
|
411
|
+
const res = await fetch(url);
|
|
412
|
+
if (!res.ok) fail(`${key}: HTTP ${res.status} for ${url}`);
|
|
413
|
+
buf = Buffer.from(await res.arrayBuffer());
|
|
414
|
+
} catch (err) {
|
|
415
|
+
fail(`${key}: download failed: ${err.message}`);
|
|
416
|
+
}
|
|
417
|
+
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'ts-npm-'));
|
|
418
|
+
const tgz = path.join(tmp, 'pkg.tar.gz');
|
|
419
|
+
fs.writeFileSync(tgz, buf);
|
|
420
|
+
const untar = spawnSync('tar', ['-xzf', tgz, '-C', tmp], { stdio: 'pipe' });
|
|
421
|
+
if (untar.status !== 0) fail(`tar extract failed for ${key}`);
|
|
422
|
+
let root = path.join(tmp, 'package');
|
|
423
|
+
if (!fs.existsSync(root)) {
|
|
424
|
+
const fallback = fs.readdirSync(tmp, { withFileTypes: true })
|
|
425
|
+
.find((e) => e.isDirectory());
|
|
426
|
+
if (fallback) root = path.join(tmp, fallback.name);
|
|
427
|
+
else fail(`extracted npm tarball for ${key} has no package/ directory`);
|
|
428
|
+
}
|
|
429
|
+
extracted.set(key, { root, tmp });
|
|
430
|
+
})
|
|
431
|
+
);
|
|
432
|
+
return extracted;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
function npmGrammarStampKey(manifest, ids) {
|
|
436
|
+
const parts = ids.map((id) => {
|
|
437
|
+
const spec = manifest.grammars[id];
|
|
438
|
+
return `${id}|${spec.package}@${spec.version}|scanner:${!!spec.scanner}|sub:${spec.subPath ?? ''}|shared:${(spec.sharedSrc ?? []).join('+')}`;
|
|
439
|
+
});
|
|
440
|
+
return crypto.createHash('sha256').update(JSON.stringify(parts)).digest('hex');
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
async function main() {
|
|
444
|
+
const args = parseArgs(process.argv.slice(2));
|
|
445
|
+
if (args.vendorDir) vendorOut = path.resolve(args.vendorDir);
|
|
446
|
+
if (args.manifest) manifestPath = path.resolve(args.manifest);
|
|
447
|
+
|
|
448
|
+
const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
|
|
449
|
+
const requested = args.only ?? Object.keys(manifest.grammars);
|
|
450
|
+
|
|
451
|
+
// Runtime: fetched from the pinned tarball (gitignored, idempotent via stamp).
|
|
452
|
+
await ensureRuntime(manifest, args);
|
|
453
|
+
|
|
454
|
+
if (args.fromNpm) {
|
|
455
|
+
// Consumer mode: download grammar sources from the npm registry.
|
|
456
|
+
// The pre-built registry is already shipped in the tarball, so no
|
|
457
|
+
// registry regeneration is needed.
|
|
458
|
+
const ids = requested;
|
|
459
|
+
const stampFile = path.join(vendorOut, 'grammars', '.stamp');
|
|
460
|
+
const stampKey = args.only ? null : npmGrammarStampKey(manifest, ids);
|
|
461
|
+
|
|
462
|
+
if (!args.force && stampKey && everyGrammarPresent(ids) && readStamp(stampFile) === stampKey) {
|
|
463
|
+
log('grammar sources already up to date; skipping.');
|
|
464
|
+
} else {
|
|
465
|
+
const tarballs = await downloadNpmTarballs(manifest.grammars, ids);
|
|
466
|
+
try {
|
|
467
|
+
for (const id of ids) {
|
|
468
|
+
const spec = requireSpec(manifest, id);
|
|
469
|
+
const key = `${spec.package}@${spec.version}`;
|
|
470
|
+
const { root } = tarballs.get(key);
|
|
471
|
+
vendorGrammar(id, spec, root);
|
|
472
|
+
}
|
|
473
|
+
} finally {
|
|
474
|
+
for (const { tmp } of tarballs.values()) {
|
|
475
|
+
fs.rmSync(tmp, { recursive: true, force: true });
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
if (stampKey) {
|
|
479
|
+
fs.mkdirSync(path.dirname(stampFile), { recursive: true });
|
|
480
|
+
fs.writeFileSync(stampFile, stampKey + '\n');
|
|
481
|
+
}
|
|
482
|
+
log('grammar sources ready.');
|
|
483
|
+
}
|
|
484
|
+
} else {
|
|
485
|
+
// Monorepo mode: copy grammar sources from devDependency node_modules.
|
|
486
|
+
const ids = vendorableIds(manifest, requested);
|
|
487
|
+
const stampFile = path.join(vendorOut, 'grammars', '.stamp');
|
|
488
|
+
const stampKey = args.only ? null : grammarStampKey(manifest, ids);
|
|
489
|
+
|
|
490
|
+
let grammarsRebuilt = false;
|
|
491
|
+
if (!args.force && stampKey && everyGrammarPresent(ids) && readStamp(stampFile) === stampKey) {
|
|
492
|
+
log('grammar sources already up to date; skipping.');
|
|
493
|
+
} else {
|
|
494
|
+
for (const id of ids) vendorGrammar(id, requireSpec(manifest, id));
|
|
495
|
+
if (stampKey) fs.writeFileSync(stampFile, stampKey + '\n');
|
|
496
|
+
grammarsRebuilt = true;
|
|
497
|
+
log('grammar sources ready.');
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
// Default registry: regenerated from the vendored grammars. A partial --only
|
|
501
|
+
// run must not touch it (the default set may not all be vendored). Otherwise
|
|
502
|
+
// refresh it whenever the grammars changed or it is missing.
|
|
503
|
+
if (!args.only && (args.force || grammarsRebuilt || !registryPresent())) {
|
|
504
|
+
regenerateDefaultRegistry(manifest);
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
log('done.');
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
main().catch((err) => fail(err && err.stack ? err.stack : String(err)));
|
package/vendor-ratex.mjs
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Restores RaTeX's prebuilt static XCFramework, its four core Swift sources, and
|
|
3
|
+
// the KaTeX fonts into packages/react-native-enriched-markdown/ios/vendor/.
|
|
4
|
+
//
|
|
5
|
+
// This replaces React Native's `spm_dependency` wiring for iOS math. spm_dependency
|
|
6
|
+
// checks out RaTeX from SPM and builds/signs its Swift wrapper at app-build time,
|
|
7
|
+
// which produced arch-specific swiftmodules (#527) and duplicate signed-XCFramework
|
|
8
|
+
// signatures that collide during archive assembly (#491). Vendoring the already-built,
|
|
9
|
+
// already-signed XCFramework once removes that whole class of SPM/CocoaPods interop
|
|
10
|
+
// bugs and drops the requirement to `use_frameworks! :linkage => :dynamic`.
|
|
11
|
+
//
|
|
12
|
+
// The vendor tree is GITIGNORED and reproduced on demand from the pins in
|
|
13
|
+
// ratex-version.json, mirroring the tree-sitter runtime restore in vendor-grammars.mjs.
|
|
14
|
+
// Wired into the package `prepare` hook (self-heal the working tree) and `prepack`
|
|
15
|
+
// (bake the full set into the published npm tarball). Idempotent: a `.stamp`
|
|
16
|
+
// fingerprint on the pinned tag + both asset sha256s makes repeat runs a no-op.
|
|
17
|
+
//
|
|
18
|
+
// node vendor/vendor-ratex.mjs Ensure the vendored set is present/current.
|
|
19
|
+
// node vendor/vendor-ratex.mjs --force Re-fetch and rewrite regardless of the stamp.
|
|
20
|
+
//
|
|
21
|
+
// Offline: point a manifest url at a local file path (absolute) and it is read from
|
|
22
|
+
// disk instead of fetched; the sha256 is still verified.
|
|
23
|
+
|
|
24
|
+
import fs from 'node:fs';
|
|
25
|
+
import os from 'node:os';
|
|
26
|
+
import path from 'node:path';
|
|
27
|
+
import crypto from 'node:crypto';
|
|
28
|
+
import { fileURLToPath } from 'node:url';
|
|
29
|
+
import { spawnSync } from 'node:child_process';
|
|
30
|
+
|
|
31
|
+
const here = path.dirname(fileURLToPath(import.meta.url));
|
|
32
|
+
const repoRoot = path.resolve(here, '..');
|
|
33
|
+
let manifestPath = path.join(here, 'ratex-version.json');
|
|
34
|
+
let outDir = path.join(repoRoot, 'packages/react-native-enriched-markdown/ios/vendor');
|
|
35
|
+
|
|
36
|
+
const LOG_PREFIX = '[react-native-enriched-markdown-scaffold]';
|
|
37
|
+
const log = (m) => console.log(`${LOG_PREFIX} ${m}`);
|
|
38
|
+
const fail = (m) => { console.error(`${LOG_PREFIX} ${m}`); process.exit(1); };
|
|
39
|
+
|
|
40
|
+
function parseArgs(argv) {
|
|
41
|
+
const args = { force: false, manifest: null, output: null };
|
|
42
|
+
for (let i = 0; i < argv.length; i++) {
|
|
43
|
+
if (argv[i] === '--force') args.force = true;
|
|
44
|
+
else if (argv[i] === '--manifest') args.manifest = argv[++i];
|
|
45
|
+
else if (argv[i] === '--output') args.output = argv[++i];
|
|
46
|
+
}
|
|
47
|
+
return args;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function copyFile(src, dest) {
|
|
51
|
+
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
|
52
|
+
fs.copyFileSync(src, dest);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Reads a manifest asset from a local path when the url points at an existing file
|
|
56
|
+
// (offline), otherwise fetches it. The sha256 is verified either way; a mismatch is
|
|
57
|
+
// fatal and prints the computed digest to paste back into ratex-version.json on a re-pin.
|
|
58
|
+
async function fetchAndVerify(url, sha256, label) {
|
|
59
|
+
if (!sha256) fail(`${label}.sha256 missing in ratex-version.json; cannot verify ${url}`);
|
|
60
|
+
let buf;
|
|
61
|
+
if (path.isAbsolute(url) && fs.existsSync(url)) {
|
|
62
|
+
log(`reading ${label} from local ${url}`);
|
|
63
|
+
buf = fs.readFileSync(url);
|
|
64
|
+
} else {
|
|
65
|
+
log(`fetching ${label} from ${url}`);
|
|
66
|
+
try {
|
|
67
|
+
const res = await fetch(url);
|
|
68
|
+
if (!res.ok) fail(`${label} download failed: ${res.status} ${res.statusText} for ${url}`);
|
|
69
|
+
buf = Buffer.from(await res.arrayBuffer());
|
|
70
|
+
} catch (err) {
|
|
71
|
+
fail(`${label} download failed for ${url}: ${err.message}`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
const digest = crypto.createHash('sha256').update(buf).digest('hex');
|
|
75
|
+
if (digest !== sha256) {
|
|
76
|
+
fail(
|
|
77
|
+
`${label} sha256 mismatch for ${url}\n expected ${sha256}\n got ${digest}\n` +
|
|
78
|
+
'If this is a deliberate re-pin, update the sha256 in vendor/ratex-version.json to the "got" value.'
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
return buf;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function extractTo(buf, ext, args, tmp) {
|
|
85
|
+
const archive = path.join(tmp, `ratex${ext}`);
|
|
86
|
+
fs.writeFileSync(archive, buf);
|
|
87
|
+
const tool = ext === '.zip' ? 'unzip' : 'tar';
|
|
88
|
+
const argv = ext === '.zip' ? ['-q', '-o', archive, ...args] : ['-xzf', archive, ...args];
|
|
89
|
+
const res = spawnSync(tool, argv, { stdio: 'inherit' });
|
|
90
|
+
if (res.status !== 0) fail(`${tool} failed to extract ${archive} (status ${res.status})`);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function stampKey(m) {
|
|
94
|
+
return `${m.tag}|${m.xcframework.sha256}|${m.source.sha256}`;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function present(m, dir) {
|
|
98
|
+
if (!fs.existsSync(path.join(dir, 'RaTeX.xcframework/Info.plist'))) return false;
|
|
99
|
+
for (const rel of m.source.swiftSources) {
|
|
100
|
+
if (!fs.existsSync(path.join(dir, path.basename(rel)))) return false;
|
|
101
|
+
}
|
|
102
|
+
return fs.existsSync(path.join(dir, 'Fonts'));
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
async function main() {
|
|
106
|
+
const args = parseArgs(process.argv.slice(2));
|
|
107
|
+
if (args.manifest) manifestPath = path.resolve(args.manifest);
|
|
108
|
+
if (args.output) outDir = path.resolve(args.output);
|
|
109
|
+
|
|
110
|
+
const xcframeworkDir = path.join(outDir, 'RaTeX.xcframework');
|
|
111
|
+
const fontsOut = path.join(outDir, 'Fonts');
|
|
112
|
+
const stampFile = path.join(outDir, '.stamp');
|
|
113
|
+
|
|
114
|
+
const m = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
|
|
115
|
+
const key = stampKey(m);
|
|
116
|
+
|
|
117
|
+
if (!args.force && present(m, outDir) &&
|
|
118
|
+
(fs.existsSync(stampFile) ? fs.readFileSync(stampFile, 'utf8').trim() : null) === key) {
|
|
119
|
+
log('RaTeX vendor tree already up to date; skipping.');
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
fs.rmSync(outDir, { recursive: true, force: true });
|
|
124
|
+
fs.mkdirSync(outDir, { recursive: true });
|
|
125
|
+
|
|
126
|
+
// 1. Prebuilt static XCFramework (device + simulator[arm64,x86_64] + macOS slices).
|
|
127
|
+
const xcBuf = await fetchAndVerify(m.xcframework.url, m.xcframework.sha256, 'xcframework');
|
|
128
|
+
{
|
|
129
|
+
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'ratex-xcf-'));
|
|
130
|
+
try {
|
|
131
|
+
extractTo(xcBuf, '.zip', ['-d', outDir], tmp);
|
|
132
|
+
} finally {
|
|
133
|
+
fs.rmSync(tmp, { recursive: true, force: true });
|
|
134
|
+
}
|
|
135
|
+
if (!fs.existsSync(xcframeworkDir)) fail(`extracted zip has no RaTeX.xcframework in ${outDir}`);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// 2. Core Swift sources + KaTeX fonts + LICENSE from the pinned source tag.
|
|
139
|
+
const srcBuf = await fetchAndVerify(m.source.url, m.source.sha256, 'source');
|
|
140
|
+
{
|
|
141
|
+
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'ratex-src-'));
|
|
142
|
+
try {
|
|
143
|
+
extractTo(srcBuf, '.tgz', ['-C', tmp], tmp);
|
|
144
|
+
const root = path.join(tmp, m.source.prefix);
|
|
145
|
+
if (!fs.existsSync(root)) fail(`source tarball has no ${m.source.prefix}/ directory`);
|
|
146
|
+
|
|
147
|
+
for (const rel of m.source.swiftSources) {
|
|
148
|
+
const from = path.join(root, rel);
|
|
149
|
+
if (!fs.existsSync(from)) fail(`source tarball missing ${rel}`);
|
|
150
|
+
copyFile(from, path.join(outDir, path.basename(rel)));
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const fontsSrc = path.join(root, m.source.fontsDir);
|
|
154
|
+
if (!fs.existsSync(fontsSrc)) fail(`source tarball missing ${m.source.fontsDir}`);
|
|
155
|
+
let n = 0;
|
|
156
|
+
for (const f of fs.readdirSync(fontsSrc)) {
|
|
157
|
+
if (f.endsWith('.ttf')) { copyFile(path.join(fontsSrc, f), path.join(fontsOut, f)); n++; }
|
|
158
|
+
}
|
|
159
|
+
if (n === 0) fail(`no .ttf fonts found under ${m.source.fontsDir}`);
|
|
160
|
+
|
|
161
|
+
const licenseFrom = path.join(root, m.source.license);
|
|
162
|
+
if (fs.existsSync(licenseFrom)) copyFile(licenseFrom, path.join(outDir, 'LICENSE'));
|
|
163
|
+
} finally {
|
|
164
|
+
fs.rmSync(tmp, { recursive: true, force: true });
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
fs.writeFileSync(stampFile, key + '\n');
|
|
169
|
+
log(`RaTeX ${m.tag} -> ${outDir}`);
|
|
170
|
+
log('done.');
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
main().catch((err) => fail(err && err.stack ? err.stack : String(err)));
|
package/app.plugin.js
DELETED