标记下- 反应- 内在
Discord Markdown parser 的回放原生绑定器(@discord/markdown-react-native, (中文(简体) ),
以纯 C++ TurboModule 执行。 Rust parser 被编译为本地图书馆
(单位:千美元)ffi/c)并链接到一个单一的 C++ 模块
(单位:千美元)cpp/NativeDiscordMarkdown.cpp两个平台共享;
没有每个呼叫桥的流量 也没有特定平台的解码 同一个图书馆是
也可以从 克特林和斯威夫特。 。 。 .
需要新架构(反应原住民0.77+).
使用量
import { Syntax, parse } from "@discord/markdown-react-native";
const blocks = parse("# Hello **world**");
// [{ type: "heading", value: { level: 1, content: [...] } }]
// Optionally pick the syntax to parse, as an OR of `Syntax` bits (`Syntax.ALL` by default):
const restricted = parse("**bold** _italic_", Syntax.BOLD);
const noMentions = parse("@everyone **hi**", Syntax.ALL & ~Syntax.MENTIONS);
// Optionally cap how much work a parse may do:
const bounded = parse(untrustedContent, null, 50_000);
parse 在 JS 线程上同步运行并返回相同的 AST
(单位:千美元)Block[] 从 @discord/markdown-types)作为束束,所以渲染代码
可在网络和本地共享。 雪花ID和时间戳值为 BigInts,还有
匹配原装订.
由于解析会阻碍JS线,第三个论点值得了解:
帕塞尔的燃料预算, 限制工作 一个对抗性的投入可以导致。 {\fn微軟雅黑\bord1\shad0\1cHC8C8C8\b0}
默认长度为信件长度, 空余空间, 因此大多数呼叫者应该使用 。 内容
将预算抛出 parser ran out of fuel 而不产生部分AST——预算
设置太低 拒绝合法内容, 所以在收紧它之前先测量你自己 .
对于丰富的文本, parseLossless(content, flags?, fuel?) 返回无损失树:节点
降级意味着什么 象征着每个性格 content 顺序,下至
分隔器、逃生器、标记和线尾,因此加入 text 把它还给我.
每个节点和标志都有一个 span 在UTF-16代码单位中,所以 content.slice(span.start, span.end)
是其文本。 这些类型是: LosslessNode 还有朋友 @discord/markdown-types。 。 。 .
当地使用(科特林和斯威夫特)
安装软件包也会给应用程序本身的本地代码一个直接线条到 parser, 有 没有JS的运行时间。 每个平台都有一个小包装器 覆盖同样的涡轮摩多仪 使用 :
import com.discord.markdown.DiscordMarkdown
val ast: String = DiscordMarkdown.parse("# Hello **world**")
val restricted = DiscordMarkdown.parse("**bold** _italic_", flags = DiscordMarkdown.Syntax.BOLD)
import DiscordMarkdown
let ast: String = try DiscordMarkdownParser.parse("# Hello **world**")
let restricted = try DiscordMarkdownParser.parse("**bold** _italic_", syntax: .bold)
两者将AST作为JSON弦还原,其形状与JS相同,除了64位整数.
这些是完全精确的JSON数字 {"$bigint": "…"} 对象。 雪花没有签名,可能会超过 Long.MAX_VALUE这样
解码为 UInt64 (斯维夫特的) JSONDecoder)或(或) ULong (kotlinx.serialization) (英语). 时间戳
签名:将其解码为 Int64 编号 : LongAndroid的内置 org.json 还不够,因为
它读取任何整数过去 Long.MAX_VALUE 作为 Double双方采用与联署材料相同的任择燃料预算
parse失败投出 DiscordMarkdownException (科特林语)或 DiscordMarkdownError (摇摆),
携带解析器的消息。 电话是同步的,没有状态,所以安全
任何线索.
parseLossless (科特林语)和 DiscordMarkdownParser.parseLossless (斯威克特)还原无损失
树与 JSON 相同。 它的跨度计有UTF-16代码单位,所以它们会索引一个克特林
String 或者说 Spannable 直接,在斯威夫特是一个 NSRange 输入内容为
NSString。 。 。 .
包装活在 android/src/main/java/com/discord/markdown/DiscordMarkdown.kt
(超过JNI的入境点) ffi/jni和
ios/DiscordMarkdownParser.swift (通过CABI,通过
DiscordMarkdownC x框架中的模块映射。 他们把货装在原生货包里
它们只提供给链接它的目标:例如,iOS应用程序扩展不能使用
他们没有反应原生舱.
如何运作
src/NativeDiscordMarkdown.ts是涡轮模具谱; 代码( 通过codegenConfig内package.json生成 键入 C++ 碱类NativeDiscordMarkdownCxxSpec。 。 。 .cpp/NativeDiscordMarkdown.cpp通过 调用 Rust parser 的 C ABI (dmd_parse财务报告和审定财务报表dmd_parse_lossless) (中文(简体) ).parseToAstString财务报告和审定财务报表parseLosslessToAstString是同步 JSI 方法——没有桥,没有ASync hop.- 注册是申报性的,不需要更改应用程序:
- 机器人数字 :
react-native.config.cjs点自动链接于android/CMakeLists.txt; 生成autolinking.cpp即时化模块, C++ 在应用程序的本地构建中编译, 链接 反对Rust 解析器libdiscord_markdown_jni.so(单位:千美元)ffi/jni,哪个 与JNI入境点一起再出口CABI。 Android Gradle 插件包 分享到APK的库, 在那里,克特林包装器加载相同的副本。 这个 Gradle项目在这里运行了代码并建造了克特林包装机(并运行货物,在-repo). - iOS系统数字 :
codegenConfig.ios.modulesProvider将模块映射到ios/DiscordMarkdownModuleProvider.mm。 。 。 .
- 机器人数字 :
- JS包装器解码退回的JSON. 涡轮摩托通过CABI
js_bigints因此64位整数跨越边界为{"$bigint": "…"}包装 (参见ffi/c/src/bigint.rs恢复为BigInts,因为 简单JSON.parse将使他们变成漂浮的64人。 克特林和斯威夫特的包装纸离开 旗下关闭并获得普通数字.
大楼
当地人自己建造了驱动货物
Rust 剖析器预建( R)android/prebuilt/, (中文(简体) ), ios/DiscordMarkdownC.xcframework),建造于
发布时间.
Android (Gradle 运行 货物吨克 打开 ffi/jni,用于
armeabi-v7a, (中文(简体) ), arm64-v8a, (中文(简体) ), x86,以及 x86_64,或者在 reactNativeArchitectures:
rustup target add aarch64-linux-android armv7-linux-androideabi i686-linux-android x86_64-linux-android
cargo install cargo-ndk
iOS(示例应用程序的 Podfile 运行) ios/build-rust.sh,该词也
组装出价的 xcframe; 更改解析器后重运行 :
rustup target add aarch64-apple-ios aarch64-apple-ios-sim x86_64-apple-ios
JS测试(包装和解码层;解剖器及其C ABI,包括燃料)
参数,在 cargo test -p discord-markdown-c:
pnpm test
示例应用程序
example/ 是一个反应原生操场应用程序(工作空间软件包,例如
site 用于网络:一个现场标记 ~ AST 视图在本地解析器上, 用于手动
核查和发展。 从回波根:
pnpm install
cd lib/react-native/example
pnpm android # or open example/android in Android Studio
cd ios && bundle exec pod install # then: pnpm ios, or open MarkdownExample.xcworkspace
端到端测试
这个 e2e_react_native CI 任务 构建示例应用程序
在两个平台上发布——行使代码,自动链接,以及收发后Rust构建——
然后在Android模拟器和iOS模拟器上驱动
大师 (单位:千美元)example/.maestro/parse.yaml, (中文(简体) ),
在 AST 上断言该应用程序使: 默认内容解析为标题
全精度 BigInt 提及 id,并打出内容再分录为活. 应用程序
MainActivity.kt 财务报告和审定财务报表 AppDelegate.swift 也通过 Kotlin 或 Swift 进行圆通内容
发射时包裹,流程检查结果 应用报告。 然后,他们收拾npm
柏油丸 并申明 预先建造的 Rust 文物船在里面。 同一流量在本地运行
maestro test -e APP_ID=… .maestro/parse.yaml 对抗任何运行中的模拟器或模拟器.
已知的限制
- 只有新建筑. 关于旧建筑
TurboModuleRegistry.getEnforcing导入时丢出. - 工作室运行时间 (恢复等)是独立的JSI运行时间;
parse仅可调用 从主要JS运行时间.