react-native-nitro-markdown 0.1.0
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 +276 -0
- package/android/CMakeLists.txt +40 -0
- package/android/build.gradle +92 -0
- package/android/gradle.properties +5 -0
- package/android/src/main/AndroidManifest.xml +4 -0
- package/android/src/main/cpp/cpp-adapter.cpp +7 -0
- package/android/src/main/java/com/nitromarkdown/NitroMarkdownPackage.kt +23 -0
- package/cpp/CMakeLists.txt +46 -0
- package/cpp/bindings/HybridMarkdownParser.cpp +112 -0
- package/cpp/bindings/HybridMarkdownParser.hpp +28 -0
- package/cpp/core/MD4CParser.cpp +442 -0
- package/cpp/core/MD4CParser.hpp +21 -0
- package/cpp/core/MarkdownTypes.hpp +119 -0
- package/cpp/md4c/md4c.c +6492 -0
- package/cpp/md4c/md4c.h +407 -0
- package/ios/NitroMarkdown-Bridging-Header.h +14 -0
- package/lib/commonjs/Markdown.nitro.js +6 -0
- package/lib/commonjs/Markdown.nitro.js.map +1 -0
- package/lib/commonjs/MarkdownJS.nitro.js +114 -0
- package/lib/commonjs/MarkdownJS.nitro.js.map +1 -0
- package/lib/commonjs/index.js +19 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/module/Markdown.nitro.js +4 -0
- package/lib/module/Markdown.nitro.js.map +1 -0
- package/lib/module/MarkdownJS.nitro.js +107 -0
- package/lib/module/MarkdownJS.nitro.js.map +1 -0
- package/lib/module/index.js +13 -0
- package/lib/module/index.js.map +1 -0
- package/lib/typescript/Markdown.nitro.d.ts +13 -0
- package/lib/typescript/Markdown.nitro.d.ts.map +1 -0
- package/lib/typescript/MarkdownJS.nitro.d.ts +33 -0
- package/lib/typescript/MarkdownJS.nitro.d.ts.map +1 -0
- package/lib/typescript/index.d.ts +22 -0
- package/lib/typescript/index.d.ts.map +1 -0
- package/nitro.json +16 -0
- package/nitrogen/generated/.gitattributes +1 -0
- package/nitrogen/generated/android/NitroMarkdown+autolinking.cmake +81 -0
- package/nitrogen/generated/android/NitroMarkdown+autolinking.gradle +27 -0
- package/nitrogen/generated/android/NitroMarkdownOnLoad.cpp +44 -0
- package/nitrogen/generated/android/NitroMarkdownOnLoad.hpp +25 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/com/nitromarkdown/NitroMarkdownOnLoad.kt +35 -0
- package/nitrogen/generated/ios/NitroMarkdown+autolinking.rb +60 -0
- package/nitrogen/generated/ios/NitroMarkdown-Swift-Cxx-Bridge.cpp +17 -0
- package/nitrogen/generated/ios/NitroMarkdown-Swift-Cxx-Bridge.hpp +27 -0
- package/nitrogen/generated/ios/NitroMarkdown-Swift-Cxx-Umbrella.hpp +38 -0
- package/nitrogen/generated/ios/NitroMarkdownAutolinking.mm +35 -0
- package/nitrogen/generated/ios/NitroMarkdownAutolinking.swift +12 -0
- package/nitrogen/generated/shared/c++/HybridMarkdownParserSpec.cpp +22 -0
- package/nitrogen/generated/shared/c++/HybridMarkdownParserSpec.hpp +65 -0
- package/nitrogen/generated/shared/c++/ParserOptions.hpp +79 -0
- package/package.json +101 -0
- package/react-native-nitro-markdown.podspec +42 -0
- package/src/Markdown.nitro.ts +12 -0
- package/src/MarkdownJS.nitro.ts +113 -0
- package/src/index.ts +65 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
///
|
|
2
|
+
/// HybridMarkdownParserSpec.cpp
|
|
3
|
+
/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
|
|
4
|
+
/// https://github.com/mrousavy/nitro
|
|
5
|
+
/// Copyright © 2025 Marc Rousavy @ Margelo
|
|
6
|
+
///
|
|
7
|
+
|
|
8
|
+
#include "HybridMarkdownParserSpec.hpp"
|
|
9
|
+
|
|
10
|
+
namespace margelo::nitro::NitroMarkdown {
|
|
11
|
+
|
|
12
|
+
void HybridMarkdownParserSpec::loadHybridMethods() {
|
|
13
|
+
// load base methods/properties
|
|
14
|
+
HybridObject::loadHybridMethods();
|
|
15
|
+
// load custom methods/properties
|
|
16
|
+
registerHybrids(this, [](Prototype& prototype) {
|
|
17
|
+
prototype.registerHybridMethod("parse", &HybridMarkdownParserSpec::parse);
|
|
18
|
+
prototype.registerHybridMethod("parseWithOptions", &HybridMarkdownParserSpec::parseWithOptions);
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
} // namespace margelo::nitro::NitroMarkdown
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
///
|
|
2
|
+
/// HybridMarkdownParserSpec.hpp
|
|
3
|
+
/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
|
|
4
|
+
/// https://github.com/mrousavy/nitro
|
|
5
|
+
/// Copyright © 2025 Marc Rousavy @ Margelo
|
|
6
|
+
///
|
|
7
|
+
|
|
8
|
+
#pragma once
|
|
9
|
+
|
|
10
|
+
#if __has_include(<NitroModules/HybridObject.hpp>)
|
|
11
|
+
#include <NitroModules/HybridObject.hpp>
|
|
12
|
+
#else
|
|
13
|
+
#error NitroModules cannot be found! Are you sure you installed NitroModules properly?
|
|
14
|
+
#endif
|
|
15
|
+
|
|
16
|
+
// Forward declaration of `ParserOptions` to properly resolve imports.
|
|
17
|
+
namespace margelo::nitro::NitroMarkdown { struct ParserOptions; }
|
|
18
|
+
|
|
19
|
+
#include <string>
|
|
20
|
+
#include "ParserOptions.hpp"
|
|
21
|
+
|
|
22
|
+
namespace margelo::nitro::NitroMarkdown {
|
|
23
|
+
|
|
24
|
+
using namespace margelo::nitro;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* An abstract base class for `MarkdownParser`
|
|
28
|
+
* Inherit this class to create instances of `HybridMarkdownParserSpec` in C++.
|
|
29
|
+
* You must explicitly call `HybridObject`'s constructor yourself, because it is virtual.
|
|
30
|
+
* @example
|
|
31
|
+
* ```cpp
|
|
32
|
+
* class HybridMarkdownParser: public HybridMarkdownParserSpec {
|
|
33
|
+
* public:
|
|
34
|
+
* HybridMarkdownParser(...): HybridObject(TAG) { ... }
|
|
35
|
+
* // ...
|
|
36
|
+
* };
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
class HybridMarkdownParserSpec: public virtual HybridObject {
|
|
40
|
+
public:
|
|
41
|
+
// Constructor
|
|
42
|
+
explicit HybridMarkdownParserSpec(): HybridObject(TAG) { }
|
|
43
|
+
|
|
44
|
+
// Destructor
|
|
45
|
+
~HybridMarkdownParserSpec() override = default;
|
|
46
|
+
|
|
47
|
+
public:
|
|
48
|
+
// Properties
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
public:
|
|
52
|
+
// Methods
|
|
53
|
+
virtual std::string parse(const std::string& text) = 0;
|
|
54
|
+
virtual std::string parseWithOptions(const std::string& text, const ParserOptions& options) = 0;
|
|
55
|
+
|
|
56
|
+
protected:
|
|
57
|
+
// Hybrid Setup
|
|
58
|
+
void loadHybridMethods() override;
|
|
59
|
+
|
|
60
|
+
protected:
|
|
61
|
+
// Tag for logging
|
|
62
|
+
static constexpr auto TAG = "MarkdownParser";
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
} // namespace margelo::nitro::NitroMarkdown
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
///
|
|
2
|
+
/// ParserOptions.hpp
|
|
3
|
+
/// This file was generated by nitrogen. DO NOT MODIFY THIS FILE.
|
|
4
|
+
/// https://github.com/mrousavy/nitro
|
|
5
|
+
/// Copyright © 2025 Marc Rousavy @ Margelo
|
|
6
|
+
///
|
|
7
|
+
|
|
8
|
+
#pragma once
|
|
9
|
+
|
|
10
|
+
#if __has_include(<NitroModules/JSIConverter.hpp>)
|
|
11
|
+
#include <NitroModules/JSIConverter.hpp>
|
|
12
|
+
#else
|
|
13
|
+
#error NitroModules cannot be found! Are you sure you installed NitroModules properly?
|
|
14
|
+
#endif
|
|
15
|
+
#if __has_include(<NitroModules/NitroDefines.hpp>)
|
|
16
|
+
#include <NitroModules/NitroDefines.hpp>
|
|
17
|
+
#else
|
|
18
|
+
#error NitroModules cannot be found! Are you sure you installed NitroModules properly?
|
|
19
|
+
#endif
|
|
20
|
+
#if __has_include(<NitroModules/JSIHelpers.hpp>)
|
|
21
|
+
#include <NitroModules/JSIHelpers.hpp>
|
|
22
|
+
#else
|
|
23
|
+
#error NitroModules cannot be found! Are you sure you installed NitroModules properly?
|
|
24
|
+
#endif
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
#include <optional>
|
|
29
|
+
|
|
30
|
+
namespace margelo::nitro::NitroMarkdown {
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* A struct which can be represented as a JavaScript object (ParserOptions).
|
|
34
|
+
*/
|
|
35
|
+
struct ParserOptions {
|
|
36
|
+
public:
|
|
37
|
+
std::optional<bool> gfm SWIFT_PRIVATE;
|
|
38
|
+
std::optional<bool> math SWIFT_PRIVATE;
|
|
39
|
+
|
|
40
|
+
public:
|
|
41
|
+
ParserOptions() = default;
|
|
42
|
+
explicit ParserOptions(std::optional<bool> gfm, std::optional<bool> math): gfm(gfm), math(math) {}
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
} // namespace margelo::nitro::NitroMarkdown
|
|
46
|
+
|
|
47
|
+
namespace margelo::nitro {
|
|
48
|
+
|
|
49
|
+
// C++ ParserOptions <> JS ParserOptions (object)
|
|
50
|
+
template <>
|
|
51
|
+
struct JSIConverter<margelo::nitro::NitroMarkdown::ParserOptions> final {
|
|
52
|
+
static inline margelo::nitro::NitroMarkdown::ParserOptions fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) {
|
|
53
|
+
jsi::Object obj = arg.asObject(runtime);
|
|
54
|
+
return margelo::nitro::NitroMarkdown::ParserOptions(
|
|
55
|
+
JSIConverter<std::optional<bool>>::fromJSI(runtime, obj.getProperty(runtime, "gfm")),
|
|
56
|
+
JSIConverter<std::optional<bool>>::fromJSI(runtime, obj.getProperty(runtime, "math"))
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::NitroMarkdown::ParserOptions& arg) {
|
|
60
|
+
jsi::Object obj(runtime);
|
|
61
|
+
obj.setProperty(runtime, "gfm", JSIConverter<std::optional<bool>>::toJSI(runtime, arg.gfm));
|
|
62
|
+
obj.setProperty(runtime, "math", JSIConverter<std::optional<bool>>::toJSI(runtime, arg.math));
|
|
63
|
+
return obj;
|
|
64
|
+
}
|
|
65
|
+
static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) {
|
|
66
|
+
if (!value.isObject()) {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
jsi::Object obj = value.getObject(runtime);
|
|
70
|
+
if (!nitro::isPlainObject(runtime, obj)) {
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
if (!JSIConverter<std::optional<bool>>::canConvert(runtime, obj.getProperty(runtime, "gfm"))) return false;
|
|
74
|
+
if (!JSIConverter<std::optional<bool>>::canConvert(runtime, obj.getProperty(runtime, "math"))) return false;
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
} // namespace margelo::nitro
|
package/package.json
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "react-native-nitro-markdown",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "High-performance Markdown parser for React Native using Nitro Modules and md4c",
|
|
5
|
+
"main": "lib/commonjs/index.js",
|
|
6
|
+
"module": "lib/module/index.js",
|
|
7
|
+
"types": "lib/typescript/index.d.ts",
|
|
8
|
+
"react-native": "src/index.ts",
|
|
9
|
+
"source": "src/index.ts",
|
|
10
|
+
"files": [
|
|
11
|
+
"src",
|
|
12
|
+
"lib",
|
|
13
|
+
"cpp",
|
|
14
|
+
"android",
|
|
15
|
+
"ios",
|
|
16
|
+
"nitrogen",
|
|
17
|
+
"nitro.json",
|
|
18
|
+
"*.podspec",
|
|
19
|
+
"!**/__tests__",
|
|
20
|
+
"!**/__fixtures__",
|
|
21
|
+
"!**/__mocks__",
|
|
22
|
+
"!cpp/core/*Test.cpp",
|
|
23
|
+
"!cpp/build",
|
|
24
|
+
"!scripts"
|
|
25
|
+
],
|
|
26
|
+
"scripts": {
|
|
27
|
+
"build": "bob build",
|
|
28
|
+
"clean": "rimraf lib nitrogen/generated",
|
|
29
|
+
"codegen": "nitrogen --logLevel=\"debug\"",
|
|
30
|
+
"typecheck": "tsc --noEmit",
|
|
31
|
+
"test": "jest",
|
|
32
|
+
"test:coverage": "jest --coverage",
|
|
33
|
+
"benchmark": "node ../../scripts/benchmark-comparison.js",
|
|
34
|
+
"prepack": "node -e \"require('fs').copyFileSync('../../README.md','./README.md')\"",
|
|
35
|
+
"postpack": "node -e \"const fs=require('fs');if(fs.existsSync('./README.md'))fs.unlinkSync('./README.md')\"",
|
|
36
|
+
"test:cpp": "node scripts/test-cpp.js"
|
|
37
|
+
},
|
|
38
|
+
"keywords": [
|
|
39
|
+
"react-native",
|
|
40
|
+
"markdown",
|
|
41
|
+
"md4c",
|
|
42
|
+
"nitro",
|
|
43
|
+
"jsi",
|
|
44
|
+
"native-module",
|
|
45
|
+
"gfm",
|
|
46
|
+
"parser"
|
|
47
|
+
],
|
|
48
|
+
"repository": {
|
|
49
|
+
"type": "git",
|
|
50
|
+
"url": "git+https://github.com/JoaoPauloCMarra/react-native-nitro-markdown.git"
|
|
51
|
+
},
|
|
52
|
+
"author": "",
|
|
53
|
+
"license": "MIT",
|
|
54
|
+
"bugs": {
|
|
55
|
+
"url": "https://github.com/JoaoPauloCMarra/react-native-nitro-markdown/issues"
|
|
56
|
+
},
|
|
57
|
+
"homepage": "https://github.com/JoaoPauloCMarra/react-native-nitro-markdown#readme",
|
|
58
|
+
"publishConfig": {
|
|
59
|
+
"registry": "https://registry.npmjs.org/"
|
|
60
|
+
},
|
|
61
|
+
"devDependencies": {
|
|
62
|
+
"@types/jest": "^29.5.14",
|
|
63
|
+
"rimraf": "^6.0.1",
|
|
64
|
+
"@types/node": "^20.0.0",
|
|
65
|
+
"jest": "^29.7.0",
|
|
66
|
+
"nitrogen": "^0.31.10",
|
|
67
|
+
"react-native-builder-bob": "^0.31.0",
|
|
68
|
+
"react-native-nitro-modules": "^0.31.10",
|
|
69
|
+
"ts-jest": "^29.2.5",
|
|
70
|
+
"typescript": "^5.6.3"
|
|
71
|
+
},
|
|
72
|
+
"peerDependencies": {
|
|
73
|
+
"react": "*",
|
|
74
|
+
"react-native": ">=0.75.0",
|
|
75
|
+
"react-native-nitro-modules": ">=0.31.0"
|
|
76
|
+
},
|
|
77
|
+
"codegenConfig": {
|
|
78
|
+
"name": "NitroMarkdownSpec",
|
|
79
|
+
"type": "all",
|
|
80
|
+
"jsSrcsDir": "src"
|
|
81
|
+
},
|
|
82
|
+
"react-native-builder-bob": {
|
|
83
|
+
"source": "src",
|
|
84
|
+
"output": "lib",
|
|
85
|
+
"targets": [
|
|
86
|
+
[
|
|
87
|
+
"commonjs",
|
|
88
|
+
{
|
|
89
|
+
"esm": true
|
|
90
|
+
}
|
|
91
|
+
],
|
|
92
|
+
[
|
|
93
|
+
"module",
|
|
94
|
+
{
|
|
95
|
+
"esm": true
|
|
96
|
+
}
|
|
97
|
+
],
|
|
98
|
+
"typescript"
|
|
99
|
+
]
|
|
100
|
+
}
|
|
101
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
require "json"
|
|
2
|
+
|
|
3
|
+
package = JSON.parse(File.read(File.join(__dir__, "package.json")))
|
|
4
|
+
|
|
5
|
+
Pod::Spec.new do |s|
|
|
6
|
+
s.name = "react-native-nitro-markdown"
|
|
7
|
+
s.version = package["version"]
|
|
8
|
+
s.summary = package["description"]
|
|
9
|
+
s.homepage = package["homepage"]
|
|
10
|
+
s.license = package["license"]
|
|
11
|
+
s.authors = package["author"]
|
|
12
|
+
|
|
13
|
+
s.platforms = { :ios => "13.0" }
|
|
14
|
+
s.source = { :git => "https://github.com/JoaoPauloCMarra/react-native-nitro-markdown.git", :tag => "#{s.version}" }
|
|
15
|
+
|
|
16
|
+
# All source files including md4c and our C++ implementation
|
|
17
|
+
s.source_files = [
|
|
18
|
+
"ios/**/*.{h,m,mm,swift}",
|
|
19
|
+
"cpp/**/*.{h,hpp,c,cpp}"
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
# Ensure md4c.c is compiled as C, not C++
|
|
23
|
+
s.pod_target_xcconfig = {
|
|
24
|
+
"CLANG_CXX_LANGUAGE_STANDARD" => "c++20",
|
|
25
|
+
"CLANG_CXX_LIBRARY" => "libc++",
|
|
26
|
+
"GCC_PREPROCESSOR_DEFINITIONS" => "$(inherited) MD4C_USE_UTF8=1",
|
|
27
|
+
"HEADER_SEARCH_PATHS" => [
|
|
28
|
+
"\"$(PODS_TARGET_SRCROOT)/cpp/md4c\"",
|
|
29
|
+
"\"$(PODS_TARGET_SRCROOT)/cpp/core\"",
|
|
30
|
+
"\"$(PODS_TARGET_SRCROOT)/cpp/bindings\"",
|
|
31
|
+
"\"$(PODS_TARGET_SRCROOT)/nitrogen/generated/shared/c++\"",
|
|
32
|
+
"\"$(PODS_TARGET_SRCROOT)/nitrogen/generated/ios\""
|
|
33
|
+
].join(" ")
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
# React Native dependency
|
|
37
|
+
s.dependency "React-Core"
|
|
38
|
+
|
|
39
|
+
# Add Nitro autolinking
|
|
40
|
+
load 'nitrogen/generated/ios/NitroMarkdown+autolinking.rb'
|
|
41
|
+
add_nitrogen_files(s)
|
|
42
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { HybridObject } from 'react-native-nitro-modules';
|
|
2
|
+
|
|
3
|
+
export interface ParserOptions {
|
|
4
|
+
gfm?: boolean;
|
|
5
|
+
math?: boolean;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export interface MarkdownParser
|
|
9
|
+
extends HybridObject<{ ios: 'c++'; android: 'c++' }> {
|
|
10
|
+
parse(text: string): string;
|
|
11
|
+
parseWithOptions(text: string, options: ParserOptions): string;
|
|
12
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { NitroModules } from 'react-native-nitro-modules';
|
|
2
|
+
|
|
3
|
+
export interface MarkdownNode {
|
|
4
|
+
type: string;
|
|
5
|
+
content?: string;
|
|
6
|
+
level?: number;
|
|
7
|
+
href?: string;
|
|
8
|
+
title?: string;
|
|
9
|
+
alt?: string;
|
|
10
|
+
language?: string;
|
|
11
|
+
ordered?: boolean;
|
|
12
|
+
start?: number;
|
|
13
|
+
checked?: boolean;
|
|
14
|
+
isHeader?: boolean;
|
|
15
|
+
align?: string;
|
|
16
|
+
children?: MarkdownNode[];
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface ParserOptions {
|
|
20
|
+
gfm?: boolean;
|
|
21
|
+
math?: boolean;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Pure JavaScript implementation using JSI
|
|
25
|
+
export class JSMarkdownParser {
|
|
26
|
+
private parseImpl(text: string, options: ParserOptions): MarkdownNode {
|
|
27
|
+
// Simple regex-based parser for comparison
|
|
28
|
+
// This is much slower than the C++ version but demonstrates JSI usage
|
|
29
|
+
const root: MarkdownNode = { type: 'document', children: [] };
|
|
30
|
+
const lines = text.split('\n');
|
|
31
|
+
let i = 0;
|
|
32
|
+
|
|
33
|
+
while (i < lines.length) {
|
|
34
|
+
const line = lines[i].trim();
|
|
35
|
+
if (!line) {
|
|
36
|
+
i++;
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Headers
|
|
41
|
+
const headerMatch = line.match(/^(#{1,6})\s+(.+)$/);
|
|
42
|
+
if (headerMatch) {
|
|
43
|
+
root.children!.push({
|
|
44
|
+
type: 'heading',
|
|
45
|
+
level: headerMatch[1].length,
|
|
46
|
+
children: [{ type: 'text', content: headerMatch[2] }]
|
|
47
|
+
});
|
|
48
|
+
i++;
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Bold
|
|
53
|
+
const boldMatch = line.match(/\*\*(.+?)\*\*/);
|
|
54
|
+
if (boldMatch) {
|
|
55
|
+
root.children!.push({
|
|
56
|
+
type: 'paragraph',
|
|
57
|
+
children: [{
|
|
58
|
+
type: 'bold',
|
|
59
|
+
children: [{ type: 'text', content: boldMatch[1] }]
|
|
60
|
+
}]
|
|
61
|
+
});
|
|
62
|
+
i++;
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Default paragraph
|
|
67
|
+
root.children!.push({
|
|
68
|
+
type: 'paragraph',
|
|
69
|
+
children: [{ type: 'text', content: line }]
|
|
70
|
+
});
|
|
71
|
+
i++;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return root;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
parse(text: string, options: ParserOptions = { gfm: true, math: true }): MarkdownNode {
|
|
78
|
+
return this.parseImpl(text, options);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// JSI-enabled version using Nitro but with JS implementation
|
|
83
|
+
export class JSINitroMarkdownParser {
|
|
84
|
+
parse(text: string, options: ParserOptions = { gfm: true, math: true }): MarkdownNode {
|
|
85
|
+
// This would use JSI to call into JavaScriptCore
|
|
86
|
+
// For now, we'll simulate it
|
|
87
|
+
const parser = new JSMarkdownParser();
|
|
88
|
+
return parser.parse(text, options);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Hybrid approach: C++ for complex parsing, JS for simple cases
|
|
93
|
+
export class HybridMarkdownParser {
|
|
94
|
+
private cppParser: any;
|
|
95
|
+
private jsParser: JSMarkdownParser;
|
|
96
|
+
|
|
97
|
+
constructor() {
|
|
98
|
+
// In real implementation, this would be the Nitro C++ parser
|
|
99
|
+
this.cppParser = null;
|
|
100
|
+
this.jsParser = new JSMarkdownParser();
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
parse(text: string, options: ParserOptions = { gfm: true, math: true }): MarkdownNode {
|
|
104
|
+
// Use C++ parser for complex cases, JS for simple
|
|
105
|
+
if (text.length > 1000 || options.gfm || options.math) {
|
|
106
|
+
// Would call C++ parser via Nitro
|
|
107
|
+
return this.jsParser.parse(text, options);
|
|
108
|
+
} else {
|
|
109
|
+
// Use JS parser for simple cases
|
|
110
|
+
return this.jsParser.parse(text, options);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { NitroModules } from 'react-native-nitro-modules';
|
|
2
|
+
import type { MarkdownParser, ParserOptions } from './Markdown.nitro';
|
|
3
|
+
|
|
4
|
+
export type { ParserOptions } from './Markdown.nitro';
|
|
5
|
+
|
|
6
|
+
export interface MarkdownNode {
|
|
7
|
+
type:
|
|
8
|
+
| 'document'
|
|
9
|
+
| 'heading'
|
|
10
|
+
| 'paragraph'
|
|
11
|
+
| 'text'
|
|
12
|
+
| 'bold'
|
|
13
|
+
| 'italic'
|
|
14
|
+
| 'strikethrough'
|
|
15
|
+
| 'link'
|
|
16
|
+
| 'image'
|
|
17
|
+
| 'code_inline'
|
|
18
|
+
| 'code_block'
|
|
19
|
+
| 'blockquote'
|
|
20
|
+
| 'horizontal_rule'
|
|
21
|
+
| 'line_break'
|
|
22
|
+
| 'soft_break'
|
|
23
|
+
| 'table'
|
|
24
|
+
| 'table_head'
|
|
25
|
+
| 'table_body'
|
|
26
|
+
| 'table_row'
|
|
27
|
+
| 'table_cell'
|
|
28
|
+
| 'list'
|
|
29
|
+
| 'list_item'
|
|
30
|
+
| 'task_list_item'
|
|
31
|
+
| 'math_inline'
|
|
32
|
+
| 'math_block'
|
|
33
|
+
| 'html_block'
|
|
34
|
+
| 'html_inline';
|
|
35
|
+
content?: string;
|
|
36
|
+
level?: number;
|
|
37
|
+
href?: string;
|
|
38
|
+
title?: string;
|
|
39
|
+
alt?: string;
|
|
40
|
+
language?: string;
|
|
41
|
+
ordered?: boolean;
|
|
42
|
+
start?: number;
|
|
43
|
+
checked?: boolean;
|
|
44
|
+
isHeader?: boolean;
|
|
45
|
+
align?: string;
|
|
46
|
+
children?: MarkdownNode[];
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export const MarkdownParserModule =
|
|
50
|
+
NitroModules.createHybridObject<MarkdownParser>('MarkdownParser');
|
|
51
|
+
|
|
52
|
+
export function parseMarkdown(text: string): MarkdownNode {
|
|
53
|
+
const jsonStr = MarkdownParserModule.parse(text);
|
|
54
|
+
return JSON.parse(jsonStr) as MarkdownNode;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function parseMarkdownWithOptions(
|
|
58
|
+
text: string,
|
|
59
|
+
options: ParserOptions
|
|
60
|
+
): MarkdownNode {
|
|
61
|
+
const jsonStr = MarkdownParserModule.parseWithOptions(text, options);
|
|
62
|
+
return JSON.parse(jsonStr) as MarkdownNode;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export { MarkdownParser };
|