默认实现与 UI 基础

这一页覆盖两块:default_implementation(开箱即用的组件和工厂函数,教程里用的都来自这里) 和 implbase / uibase(写自定义渲染器时会用到的基础设施)。 这里按导出项组织,供查阅签名;想系统了解这一层的用法和设计, 读默认实现那一部分。

两个顶层组件

DefaultEditorComponent

完整的默认编辑器界面。它接受 EditorComponentProps 的全部 props(见 editor 那页),另外追加:

{
    config?: PartialEditorConfig            // 样式配置(字体、边距、宽度),部分覆盖式
    texts?: PartialEditorTexts              // 界面文字(按钮提示、面板标题、提示语),部分覆盖式
    onSave?: () => void                     // 用户触发保存动作时回调
    sidebar_extras?: (() => React.ReactNode)[]  // 向侧边栏追加自定义按钮
    end_element?: React.ReactNode           // 附加在文档末尾的元素
}

它包含纸张、侧边栏、参数与概念的浮动编辑区、抽象节点的编辑弹层、键盘导航, 消息提示也内置了(内部自带 notistack 的 SnackbarProvider)。 通过 ref 调用 get_editor() 可以拿到内部真正的 EditorComponent, 进而使用 get_root() 等方法。

DefaultPrinterComponent

{
    printer: Printer
    root: AbstractNode
    config?: PartialPrinterConfig
    onUpdateCache?: (cache: PrinterCache) => void
    onDidMount?: (printer_comp: PrinterComponent, me: DefaultPrinterComponent) => void
}

完整的默认印刷界面。onUpdateCache 在每次预处理后把缓存交给你(交叉引用会用到,见教程第 6 章); onDidMount 提供内部 PrinterComponent 的引用,需要调用 scroll_to_idx 之类的方法时从这里拿。

编辑渲染器工厂

这组函数为各类节点生成带完整交互的编辑外观。公共的定制点有: get_label(标签,会被当作组件调用,内部可以用 hooks)、 surrounder(内容的包裹方式)、buttons_extra(追加按钮)、 rightbar_extra(右侧栏的扩展位)。

工厂函数适用节点特点
get_deafult_group_editor_with_appbargroup顶部带标题栏的卡片样式。注意函数名里 deafult 是历史拼写。
get_default_group_editor_with_rightbargroup右侧竖栏样式,按钮折叠在菜单里,视觉上更紧凑
get_default_inline_editorinline行内样式,surrounder 决定编辑时文字的包裹
get_default_struct_editor_with_rightbarstructure多列布局;get_numchildrenget_widths 决定列数和各列宽度,子组会按列数自动增删
get_default_spliter_editorsupport分隔线样式,get_title 决定线上的文字
get_default_display_editorsupport展示型(如图片):render_element 渲染实际内容,is_empty 判断是否为空并显示占位图标
get_default_abstract_editorabstract抽象节点(根节点、批注)的容器
get_default_editors()全部返回七种节点类型各自的默认渲染器,交给 EditorCoredefault_renderers

与抽象编辑相关的还有一个函数导出:open_abstract_editor(node, abs_idx), 以编程方式打开抽象编辑器,编辑 nodeidxabs_idx 的抽象 (注意第二个参数是抽象节点的编号,不是它在列表中的下标)。 默认界面上的抽象管理按钮用的就是这个入口;在自定义渲染器里为子节点自绘抽象管理界面时,直接调用它即可。

印刷渲染器工厂

印刷一侧的工厂。公共定制点:contexters(contexter 生成函数的数组, 工厂会把它们自动接入预处理,见教程第 6 章)。块级的工厂还支持 pre_elementaft_element(在正文前后插入内容), 以及更换整个内层或外层包装的 innerouter

工厂函数适用节点特点
get_default_group_renderergroup块级渲染的主力;small_margin_enter 可以压缩块前间距
get_default_structure_rendererstructure多列网格布局;subinner 定制每一列的包装
get_default_paragraph_rendererparagraph段落;支持在段首注入元素或文字
get_default_inline_rendererinlineouter 决定行内内容的包裹
get_default_abstract_rendererabstract渲染成一个带角标的链接,点击弹出对话框显示完整子文档
auto_renderer任意最通用的一个:给一个渲染函数(和可选的 contexters),直接构造出 PrinterRenderer
useless_renderer_block / useless_renderer_inline / useless_renderer_text用作默认渲染器不加任何样式的直通渲染器,教程第 3 章用它们拼过 default_renderers

contexter 系列

预处理阶段的工具类,机制和用法见教程第 6 章。

构造参数用途
ContexterBase<NT, CtxT, EnvT>(key, default_val)基类。提供 enter/exit 钩子和 get_env / set_env / get_context / set_context 存取方法,自定义 contexter 从它继承
OrderContexter(order_key, separate_groups?)自动编号。同名计数器共享编号;separate_groups 为 true 时遇到「分离」的组重新计数
ReferenceContexter(get_reference)为节点生成引用名并写入缓存,交叉引用的基础
InjectContexter(infokey, {preinfo?, aftinfo?})在节点进入或离开时向环境写入一条信息
ConsumerContexter(infokey)后续节点从环境读出该信息,存进自己的上下文

配套类型:PreprocessInformation<NT> 是传给 contexter 生成函数的信息包 ({node, parameters, context, env}),PreprocessFunction<NT, R> 是这类函数的类型。

implbase:渲染器内部的 hooks 与部件

写自定义的编辑渲染器(或它的 get_labelbuttons_extra)时,这些是最常用的工具:

导出说明
useNode(is_equal?)取当前正在渲染的概念节点。可传一个比较函数来控制何时触发重渲染
useParameters()取当前节点处理后的参数,get_label 里用得最多
useEditor()取当前的 EditorComponent,进而调用树操作方法
useResetSelection()返回一对函数:保存光标位置、恢复光标位置。弹出面板交互结束后用来还原编辑位置
UniversalExtra通用的行内小输入框组件,常嵌在节点右侧栏里快速编辑某个参数(示例应用用它编辑链接目标和图片地址,支持直接粘贴图片)
DefaultParameterContainer参数编辑面板本体,默认的参数抽屉内部就是它
AutoIconButton / ButtonGroup / FoldedButtonGroup / MouselessButton支持键盘导航的按钮组件,自定义按钮建议基于它们搭
MouselessHint / ShowHintControlButton快捷键提示气泡、提示常驻开关
EditorTexts / make_editortexts / useTexts界面文字表的类型、合并函数和读取 hook;自定义按钮想跟随语言就用它
EditorConfig / make_editorconfig / useEditorConfig编辑器样式配置的类型、合并函数和读取 hook

uibase:通用 UI 工具

uibase 是一组和编辑器本身无关的通用 UI 工具,默认实现内部大量使用它们; 你在搭自定义界面(侧边栏按钮、参数编辑扩展)时也可以直接拿来用,省去自己造轮子:

导出说明
AutoStack / AutoStackButtons / AutoTooltip / AutoStackedPopper一族随布局方向自动调整的组件:外层是横向时内层自动变纵向,提示框位置也随之调整
mod_scrollbar(el) / ScrollBarBox给容器应用 OverlayScrollbars 滚动条样式
usePersistedState(key, default)和 localStorage 同步的 React state
TextIcon圆形边框的文字图标
with_partial_props(Comp, defaults)预先填好一部分 props,得到一个新组件
light_grey(color)把颜色转成浅灰(配合 color 库使用)

印刷排版部件

印刷一侧另有一组排版部件,写印刷渲染器时用它们能保持和默认样式一致的间距与字号: PrinterPartBox(内容块)、PrinterParagraphBox(段落框)、 PrinterStructureBoxText(结构性文字,教程第 5 章用它做定理标题)、 PrinterNewLevelBoxPrinterOldLevelBox(进入、退出一层缩进)、 PrinterDisplayText(展示型文字)、PrinterWeakenText(弱化文字), 以及读取印刷样式配置的 PrinterConfigContext。 完整清单见 TypeDoc 参考