Rerun TextDocument Archetype 详解:在独立文本框中记录纯文本与 Markdown 文档
【免费下载链接】rerunVisualize, query, and stream to train on multimodal robotics data.项目地址: https://gitcode.com/GitHub_Trending/re/rerun
本文基于 Rerun 仓库中 TextDocument 官方参考文档,系统讲解TextDocument这个 Archetype 的数据模型(text必填字段与media_type可选字段)、三种语言 SDK 下的完整记录示例、Markdown 渲染能力与recording://内部链接机制,并结合 re_sdk_types 源码 剖析其组件序列化、文件读取扩展与列式批量写入的实现细节。读完后你将能够正确选择TextDocument与TextLog的使用场景,并掌握从文件加载、批量写入到在 TextDocumentView / DataframeView 中呈现的完整链路。
TextDocument 的定位:拥有独立文本框的文本元素
Rerun 的参考文档将TextDocument定义为:
A text element intended to be displayed in its own text box. Supports raw text and markdown.
即:一个旨在独立文本框中显示的文本元素,同时支持原始文本(raw text)与 Markdown 两种格式。它和同属文本家族的TextLog(面向逐条滚动追加的日志流,见 text_log_view 参考)形成互补——当你需要一份"文档型"内容(如报告、说明、状态面板文本)作为某个实体的整体属性时,TextDocument是更合适的载体:更新时整体替换,而不是在日志流末尾追加一行。
TextDocument是一个典型的 Rerun Archetype(rerun.archetypes.TextDocument),由类型定义文件经代码生成器自动产出三语言 API。文档页脚标注该文件由crates/build/re_types_builder/src/codegen/docs/website.rs自动生成,Rust 侧实现同样标注"DO NOT EDIT",源自 re_types_builder 代码生成器。这意味着三语言 API 的行为是严格对齐的。
数据模型:一个必填组件 + 一个可选组件
原始文档给出的字段结构如下:
| 字段 | 类型 | 必填性 | 说明 |
|---|---|---|---|
text | Text组件 | 必填 | 文本文档的内容 |
media_type | MediaType组件 | 可选 | 文本的媒体类型,如text/plain、text/markdown;省略时默认按text/plain处理 |
从 Rust 实现 text_document.rs 可以确认这两个字段的底层形态:
#[derive(Clone, Debug, PartialEq, Default, ::re_byte_size::SizeBytes)] pub struct TextDocument { /// Contents of the text document. pub text: Option<SerializedComponentBatch>, /// The Media Type of the text. /// /// For instance: /// * `text/plain` /// * `text/markdown` /// /// If omitted, `text/plain` is assumed. pub media_type: Option<SerializedComponentBatch>, }几个值得注意的实现事实(均来自源码):
- 组件总数固定为 2:
NUM_COMPONENTS: usize = 2(1 个必填、0 个推荐、1 个可选,见 L159-L162)。 - 每个字段都携带
ComponentDescriptor:例如text字段映射到TextDocument:text,对应组件类型rerun.components.Text;media_type映射到TextDocument:media_type,对应rerun.components.MediaType(见 L112-L139)。这套描述符在 chunk 存储与数据框展示时用于把 Arrow 列反查回"哪个 Archetype 的哪个字段"。 Text组件本质是 UTF-8 字符串包装:components/text.rs 中定义为pub struct Text(pub crate::encodings::Utf8),实现了From<T: Into<Utf8>>,因此任何字符串字面量、&str、String都可以直接传入TextDocument::new(...)。clear_fields()会写入空批次而非None(L255-L269),用于显式清除实体上的既有内容,区别于"不发送该字段"。
Python SDK 中对应的自动生成为 rerun_py/rerun_sdk/rerun/archetypes/text_document.py:构造签名为TextDocument(text, *, media_type=None),字段类型分别为components.TextBatch与components.MediaTypeBatch,并同样提供columns()列式构造入口。
三种语言的完整记录示例
仓库 snippets 目录 中为TextDocument提供了三语言可运行示例(Python / Rust / C++),内容一致:记录一个纯文本实体text_document,再记录一个完整的 Markdown 文档实体markdown。
Python(text_document.py)
"""Log a `TextDocument`.""" import rerun as rr rr.init("rerun_example_text_document", spawn=True) rr.log("text_document", rr.TextDocument("Hello, TextDocument!")) rr.log( "markdown", rr.TextDocument( ''' # Hello Markdown! Click here to see the raw text. Basic formatting: | **Feature** | **Alternative** | | ----------------- | --------------- | | Plain | | | *italics* | _italics_ | | **bold** | __bold__ | | ~~strikethrough~~ | | | `inline code` | | ---------------------------------- ## Support - [x] [Commonmark](https://commonmark.org/help/) support - [x] GitHub-style strikethrough, tables, and checkboxes - Basic syntax highlighting for: - [x] C and C++ - [x] Python - [x] Rust - [ ] Other languages ## Links You can link to an entity, a specific instance of an entity, or a specific component. ## Image  '''.strip(), media_type=rr.MediaType.MARKDOWN, ), )Rust(text_document.rs)
//! Log a `TextDocument` fn main() -> Result<(), Box<dyn std::error::Error>> { let rec = rerun::RecordingStreamBuilder::new("rerun_example_text_document") .spawn()?; rec.log( "text_document", &rerun::TextDocument::new("Hello, TextDocument!"), )?; rec.log( "markdown", &rerun::TextDocument::from_markdown( r#" # Hello Markdown! Click here to see the raw text. ## Links You can link to an entity, a specific instance of an entity, or a specific component. ... "# .trim(), ) )?; Ok(()) }注意 Rust 侧使用了from_markdown()便捷构造器,等价于TextDocument::new(markdown).with_media_type(MediaType::markdown())——这一等价关系直接写在扩展实现的文档注释里(text_document_ext.rs)。
C++(text_document.cpp)
#include <rerun.hpp> int main(int argc, char* argv[]) { const auto rec = rerun::RecordingStream("rerun_example_text_document"); rec.spawn().exit_on_failure(); rec.log("text_document", rerun::TextDocument("Hello, TextDocument!")); rec.log( "markdown", rerun::TextDocument(R"#(# Hello Markdown! ... )#" .with_media_type(rerun::MediaType::markdown()) ); }三个示例中,纯文本实体不传media_type(按text/plain处理),Markdown 实体显式声明media_type(Python 用rr.MediaType.MARKDOWN,Rust 用from_markdown,C++ 用.with_media_type(rerun::MediaType::markdown()))。
media_type 的取值与自动推断
media_type是一个 MIME 风格字符串组件(底层同样是 UTF-8 文本)。文档给出的典型取值:
text/plain:普通文本,缺省值;text/markdown:启用 Markdown 渲染管线。
Rust SDK 还额外提供了两条"从文件构造"的路径(text_document_ext.rs),其媒体类型推断策略值得展开:
TextDocument::from_file_path(path):读取 UTF-8 文件,优先从文件扩展名推断媒体类型(MediaType::guess_from_path),推断失败则回退到内容嗅探(or_guess_from_data);非 UTF-8 内容会返回TextDocumentError::InvalidUtf8。该方法仅在非 wasm32 目标下可用(#[cfg(not(target_arch = "wasm32"))])。TextDocument::from_file_contents(contents, media_type):给定字节内容时,显式传入的media_type优先,未传入则从内容本身猜测。
从这条扩展 API 可以推断:仓库期望"文档型"文本常来自磁盘上的现成文件(如.md报告),并尽量让媒体类型自动到位,避免用户忘记声明text/markdown导致按纯文本渲染。
Markdown 渲染能力与 recording:// 链接
示例文档本身就是一份"能力清单",它声明了 TextDocumentView 的 Markdown 支持范围:
- Commonmark标准支持,外加 GitHub 风格的删除线、表格与复选框;
- 语法高亮:C/C++、Python、Rust(示例中明确标注"Other languages"未支持);
- 普通 https 链接:与浏览器行为一致;
- 图片:Markdown 图片语法可用。
最有 Rerun 特色的是recording://内部链接,示例展示了三种精度:
| 链接写法 | 指向 |
|---|---|
recording://markdown | 实体本身 |
recording://markdown[#0] | 该实体的特定实例(instance) |
recording://markdown:Text | 该实体上的特定组件(这里是Text组件) |
这三类目标与本文"数据模型"一节中的组件描述符一一对应:markdown是实体路径,#0是实例索引,:Text正是TextDocument:text字段映射的组件类型rerun.components.Text。这意味着文档可以在 Rerun 内部互相引用,点击即跳转到对应实体视图,把"文档"变成了数据导航入口。
从视图源码 view_class.rs 看,TextDocumentView维护了一个only_showing_markdown: bool状态,会在 L135-L138 检查当前可见条目是否全部为MediaType::markdown(),据此切换渲染路径;单条条目是否在 L205 按media_type == markdown()决定是否走 Markdown 渲染。这说明混合记录纯文本与 Markdown 条目时,视图的呈现策略由当前条目的媒体类型集合决定——保持同一实体下媒体类型一致,可以得到最可预期的展示。
显示载体:TextDocumentView 与 DataframeView
原始参考文档声明TextDocument"Can be shown in":
- TextDocumentView:把文档内容渲染进独立文本框的专用视图,支持上述 Markdown 能力;
- DataframeView:作为数据框中的一列呈现。
第二条值得注意:由于TextDocument的字段最终都以 Arrow 组件列存储(from_arrow_components见 L199-L217),它天然可进入 Rerun 的表格/数据框体系,与其他 Archetype 的行数据并列查询与展示。Python SDK 的visualizer()方法(见 text_document.py L308-L321)也证实了它实现了VisualizableArchetype接口,Rust 侧对应实现为crate::Visualizer::new("TextDocument")(text_document.rs L232-L237),用于 Blueprint 中声明该实体应使用的视图。
进阶:列式批量写入与字段更新 API
对于需要一次写入大量文本行的场景(例如把一批描述灌入数据框),生成代码提供了列式入口,Python 与 Rust 对齐:
- Python:
TextDocument.columns(text=..., media_type=...)返回ComponentColumnList,默认把批次切分为单元长度子批次,可配合rr.send_columns直接写列式数据;输入为 numpy/Arrow 数组时可从形状推断行数(text_document.py L206-L279)。 - Rust:
TextDocument::columns(lengths)把SerializedComponentBatch切分为SerializedComponentColumn,供RecordingStream::send_columns使用;columns_of_unit_batches()则按各组件批长度自动猜出行数做等长切分(text_document.rs L271-L312)。配套的with_many_text(...)/with_many_media_type(...)用于"一个批次里打包多个值",文档注释明确:只记录单行数据时应使用with_text(...)。
单行更新的构建器 API 同样齐备:TextDocument::new(text)、update_fields()(部分字段更新)、clear_fields()(显式清空)、with_text(...)、with_media_type(...)(text_document.rs L239-L358)。Python 侧对应TextDocument.from_fields(...)与cleared(),from_fields还支持clear_unset=True语义。
使用建议小结
- 需要独立文本框展示、整体替换的文档内容(含 Markdown 报告)→ 用
TextDocument,在 TextDocumentView 中查看; - 需要逐行滚动的日志流 → 改用
TextLog族 Archetype(参见 TextLog 相关视图参考); - 记录 Markdown 时务必显式声明
media_type(Rust 用from_markdown,Python 用rr.MediaType.MARKDOWN,C++ 用with_media_type),或依赖from_file_path的扩展名推断,避免被按text/plain呈现; - 想利用文档做数据导航时,用
recording://entity、recording://entity[#0]、recording://entity:Component三类链接把文本与实体、实例、组件关联起来; - 批量写入走
columns/send_columns列式路径,单行写入走with_*构建器。
所有结论均可在仓库内追溯:字段定义见 TextDocument Rust 实现 与 Python 生成代码,文件扩展见 text_document_ext.rs,Text组件见 components/text.rs,三语言示例见 docs/snippets/all/archetypes/,视图行为见 re_view_text_document。
【免费下载链接】rerunVisualize, query, and stream to train on multimodal robotics data.项目地址: https://gitcode.com/GitHub_Trending/re/rerun
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考