ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Plate 编辑器 Date 与 Media/Embed 扩展共识计划:源契约优先的架构升级实战指南

Plate 编辑器 Date 与 Media/Embed 扩展共识计划:源契约优先的架构升级实战指南 Plate 编辑器 Date 与 Media/Embed 扩展共识计划源契约优先的架构升级实战指南【免费下载链接】plateRich-text editor with AI and shadcn/ui项目地址: https://gitcode.com/GitHub_Trending/pl/plate本文围绕 Plate基于 Slate 的富文本编辑器集成 AI 与 shadcn/ui仓库中的 Date 与 Media/Embed 扩展共识计划 展开系统讲解该计划如何将date节点与media/embed节点从散落的字符串与隐式解析升级为显式、可往返、由 Plate 自主定标的源契约source-canonical contract。读完本文你将掌握为什么toDateString()不是合格的长期数据格式、如何设计YYYY-MM-DD规范日期值与双读dual-readMarkdown 线格式、媒体嵌入的信任边界trust boundary如何显式化以及一套从契约决策、代码实现、测试覆盖到文档法law同步的完整落地路径。计划定位一份已经部分兑现的共识性架构计划先明确该文档在仓库中的位置与状态。文档自述Status为date 半程在历史意义上已经关闭historical for the date halfmedia/embed半程仍在为活跃通道active lane提供背景上下文。因此这份文件有两个用途作为窄契约narrow contract最终胜出的历史理由记录作为 Lane 4 media/embed 后续工作的活动背景材料。对照当前仓库源码计划的 date 半程核心内容已经落地例如 insertDate.ts 已通过normalizeDateValue写入规范值dateValue.ts 已实现YYYY-MM-DD规范化、toDateString()旧格式兼容与无时区漂移解析。也就是说这篇文章既是计划本身的解析也是计划如何演化为现实的源码级印证。任务定义补齐 date 与 media/embed 两个通道的剩余扩展计划的原始任务Task很明确为文档描述中剩余的date与media/embed扩展批次创建真正的实施计划并且必须扎根于当前的 law行为规范文档、research研究文档与 runtime运行时源码而不是凭空设计。两条通道必须一起完成而不是只做相对容易的 media 通道。原因在于仓库的决策纪律要求契约、代码、测试、文档四者同步更新任何一条通道若只做表面修补都会让另外一条通道的 schema 决策失去参照。仓库现状Repo Grounding四份文档与六处源码共同定义的基线计划用现状即约束的方式锚定实施范围任何新契约都必须与以下基线兼容。这体现了 Plate 文档体系里law行为规范—protocol协议矩阵—parity对齐矩阵—research研究决策—runtime运行时代码五层互锁的方法论。行为规范law层markdown-editing-spec.md 仍将date锁定为node.date上的单一纯字符串载荷Markdown 往返形态为纯datevalue/dateeditor-protocol-matrix.md 将更丰富的 date 载荷标记为deferred延后当前渲染行为仅标记为specified已规定但未全面实现markdown-parity-matrix.md 将Date与Media embed的窄契约标记为locked更丰富的扩展仍停留在 feature-gap 行。研究决策research层既有扩展说明明确指出media 的扩展基础比 date 更坚实见 2026-04-09-editor-spec-date-media-expansion.mddate 的开放问题文档承认当前仓库尚无正当理由引入更丰富的载荷见docs/research/open-questions/date-mdx-payload-contract.mdmedia 决策文档要求更丰富的 media 应从创作authoring与路径策略path-policy、信任边界出发而非仅仅追加新的 provider 字段见docs/research/decisions/media-authoring-follows-the-image-path-policy-family.md。运行时runtime层计划记录的历史现状部分已被后续实现改变但作为设计动因仍具参考价值date 曾以new Date().toDateString()存储demo 渲染器从日历回写toDateString()date-node.tsx、date-node-static.tsxMarkdown 规则曾将 date 序列化为纯子文本date元素defaultRules.tsmedia/embed 规范化曾分散在多个原始字符串助手与提交时变更中parseIframeUrl.tspackages/media/src/lib/media-embed/parseIframeUrl.ts、parseVideoUrl.ts、parseTwitterUrl.ts以及 submitFloatingMedia.tsmarkdown media 流规则在 mediaRules.ts 中为audio/file/video保留属性但 embed 特有的丰富元数据尚未一等公民化。这些基线共同回答了为什么不能继续在旧形态上叠加行为在模糊的数据之上继续增加行为只会产生更多没有 law 支撑的行为。需求摘要五条硬约束与四条硬性非目标计划对本次扩展批次的全局要求可以归纳为五条双通道并行收尾同时完成 date 与 media/embed不允许只做容易的 media 通道源真值显式且可往返source truth 必须显式化并且能通过 Markdown/MDX 无损往返外部证据薄弱处由 Plate 自主决策契约决策权归 Plate 自身不等待外部标准渲染/UI 工作收敛只做直接由源契约推导出的渲染行为不为 UI 发明新规则四件套同步代码、测试、editor-behavior law、面向用户的文档必须一起更新。同时保持四条硬性非目标non-goals任何方案都不得触碰不允许任意脚本嵌入no arbitrary script embeds不支持 PDF 嵌入no PDF embed support不做重 locale / 重 timezone 的日期 UX不开 preview-first 的产品通道。方案选型RALPLAN-DR 给出的三个选项与推荐计划使用 RALPLAN-DR 方法做决策先立原则再比较选项。五条设计原则规范载荷优先于渲染便利Canonical payload beats render convenience在共享功能包中规范化而非在应用级 demo 渲染器中Markdown 规则应往返一个刻意的 schema而非偶然的原始字符串嵌入输入的信任边界必须显式并被负向测试覆盖渲染行为可以派生自规范数据但无权重新定义 schema。选项对比选项做法优点缺点A源契约增强 窄渲染跟进date 引入机器可读规范节点值保留旧数据读兼容、派生渲染标签、与 Markdown 线格式迁移解耦media/embed 引入规范化元数据 显式 allowlist/信任边界只持久化编辑面真正需要的来源信息长期架构最优存储契约与渲染标签诚实分离为未来 AI/streaming 兼容铺路给 Markdown 规则明确的往返对象触及多个包需要谨慎的旧数据读兼容现在就要做真正的 schema 决策B保持现有节点形态仅修补渲染器/解析器date 保持单一原始字符串media 保持url 运行时推断即时 diff 小近期协调成本低锁死糟糕的toDateString()契约media 元数据/来源信息继续隐式行为变多但 law 没有变好CUI 先行扩展先做更丰富的选择器语义、更宽的嵌入 chrome、更多 provider 行为与预览行为用户可见变化炫目顺序错误违反非目标最容易产生假 law 与 schema 漂移推荐结论选择选项 A但 date 节点迁移要比完整字段重命名更窄。具体含义date获得规范机器可读值 派生渲染标签media/embed获得显式规范化元数据 信任边界处理provenance来源信息只在确实帮助编辑时才持久化渲染器只表达这些契约不得发明额外的产品 law。Date 契约决策规范日历日字符串 双读 Markdown 线格式计划为platejs/date设计了一个 Plate 自有的新契约核心要点如下。规范节点值保留现有节点字段名date收窄其语义为规范的YYYY-MM-DD日历日字符串inline void 节点其余部分保持不变。推荐的规范节点值{ date: 2026-03-23; }Markdown / MDX 线格式决策本批次采用**双读dual-read**策略读取两种形态旧式子文本形态date2026-03-23/date带属性形态date value2026-03-23 /写入形态保持显式且保守本批次 writer 仍输出规范的子文本形态带属性形态仅作读取兼容不是本批次的默认序列化输出。兼容性行为读取旧式纯子文本date.../date输入只将两类安全旧形态规范化为node.date规范的YYYY-MM-DD旧的 Plate 风格Date.prototype.toDateString()输出形如Mon Mar 23 2026若旧式子文本无法安全规范化则通过显式 Markdown 回退路径保留原文而不是物化一个更丰富的date节点停止从插入操作或日历 UI 写入新的toDateString()值。有限渲染行为从规范date派生当前相对标签Today/Yesterday/Tomorrow与长日期标签将YYYY-MM-DD解析为无时区漂移的日历日而不是依赖裸new Date(node.date)若在 Markdown 回退路径之外遇到非规范date节点按字面回退文本渲染而不是臆造一个解析日。明确排除Out重 locale / 重 timezone 的序列化语义display-vs-value 分离的序列化语义超出写入规范值的独立选择器产品 law。源码印证契约如何在platejs/date中落地计划执行后packages/date/src/lib/utils/dateValue.ts 已成为该契约的共享实现可以直接对照阅读CANONICAL_DATE_REGEX/^\d{4}-\d{2}-\d{2}$/与LEGACY_DATE_REGEX/^[A-Z][a-z]{2} [A-Z][a-z]{2} \d{2} \d{4}$/分别识别两类安全形态formatDateValue(date)将Date格式化为规范YYYY-MM-DDparseCanonicalDateValue(value)用**本地时区正午hour 12**构造Date并逐项校验年/月/日从而避免时区漂移导致的日期错位normalizeDateValue(value)统一处理Date与字符串输入规范形态直接通过toDateString()旧形态转换为规范值无法规范化的输入落入rawDate字段getDateDisplayLabel({ date, now, rawDate })负责渲染标签派生有rawDate时返回原文否则按日历日比较输出Today/Yesterday/Tomorrow其余走toLocaleDateString长格式。而 insertDate.ts 的插入默认值已改为normalizeDateValue(date ?? new Date())随后通过editor.tf.insertNodes写入带children: [{ text: }]的空子文本 inline void 节点——这正是新写入只产出规范值的实现证据。Media / Embed 契约决策结构化规范化元数据 显式信任边界计划为platejs/media设计了一个更丰富的规范化嵌入契约。字段设计必选url规范的渲染/嵌入 URL可选provider规范化的 provider slugid规范化的 provider 资源 idsourceUrl当编辑面需要保留一个与url不同的用户可见 URL 时保存规范的用户/来源侧 URL。仅规范化不序列化的元数据sourceKind可以存在于共享规范化助手与测试中除非出现第二个持久化消费者否则sourceKind不需要在本批次成为序列化的 markdown/文档字段。推荐边界allowlist 片段提取保持显式绝不把任意脚本标记存储为规范节点载荷不扩展到 PDF iframe 或任意脚本嵌入。有限渲染行为渲染器可直接使用规范化元数据无需重新解析原始输入编辑面在可用时应保留sourceUrl而不是只把 provider 的嵌入 URL 泄漏给用户。源码印证结构化契约与信任边界如何落地packages/media/src/lib/media/parseMediaUrl.ts 实现了计划所要求的单一显式结构化契约EmbedUrlData类型即契约本身{ id?, provider?, sourceKind?, sourceUrl?, url? }其中sourceKind取值为allowlisted_snippet | iframe | urlparseMediaUrl(url, { urlParsers })依次尝试各个 parser并在返回前做XSS 加固只允许http:与https:协议其余协议直接拒绝——这就是信任边界的代码表达parseIframeUrl.ts 退位为信任边界助手而非整个契约它负责从粘贴的完整 iframe 代码中提取src、识别 Twitter/X status URL本身不构成 schemaBaseMediaEmbedPlugin.ts 将parseIframeUrl注册为options.transformUrl并把media_embed声明为{ isElement: true, isVoid: true }HTML 反序列化只接受IFRAME节点的srcsubmitFloatingMedia.ts 是提交即消费契约的示范先跑isUrl校验与可选的transformUrl再用parseMediaUrl[parseTwitterUrl, parseVideoUrl]规范化最后editor.tf.setNodes一次性写入id、provider、sourceUrl、url——提交路径不再在应用代码里临时解析原始输入。可测试验收标准九条契约级的完成定义计划的验收标准直接映射到代码与测试是契约优先方法论中最可操作的部分新 date 写入与可安全规范化的旧 date 读取都存储规范机器可读的date值日期插入与 demo 日历编辑写入规范值而非toDateString()Markdown date 规则双读旧式子文本与带属性 date 元素本批次写回规范子文本规范 date 渲染使用无时区漂移的日历日解析不可规范化的旧式 markdown 日期输入走显式非日期回退路径既有非规范date节点用字面渲染回退而非被静默重解释media 嵌入把受支持的 URL / iframe / allowlist 片段输入规范化为platejs/media拥有的显式共享元数据字段任意脚本片段继续被拒绝PDF iframe 片段继续不受支持更丰富的media_embed元数据通过显式 markdown/MDX 规则与测试往返而非隐藏的回退行为date 渲染器对规范日显示行为有显式覆盖而不只是包级 transform 测试markdown-editing-spec.md、editor-protocol-matrix.md、markdown-parity-matrix.md、重新打开的扩展说明与公开文档描述同一套边界。实施步骤八步从契约到交付计划给出了八步实施顺序每步都明确到文件与交付物。这里结合当前仓库源码逐条展开。第 1 步先在代码中锁定 date 契约涉及文件insertDate.ts、packages/date/src/lib/**下的新规范化/序列化助手、packages/date导出的日期类型。工作内容添加platejs/date拥有的共享日期规范化助手将插入默认值从toDateString()改为规范date在足够长的窗口内保留旧形态读兼容避免破坏旧文档显式定义旧式子文本值无法安全规范化时的 Markdown 回退分支把 Markdown 线格式迁移与节点契约决策解耦——先改数据语义再改线格式。从当前源码看dateValue.ts正是这一步的产出规范化、旧格式识别、rawDate回退一应俱全。第 2 步让 date 渲染器跟随共享契约涉及文件date-node.tsx、date-node-static.tsx。工作内容停止把element.date当作自由格式显示字符串从规范date派生相对/长标签日历选择写入规范date规范解析与标签派生路由到共享包助手而非应用代码中的裸new Date(element.date)为规范日渲染路径与回退路径补充 UI 测试覆盖。第 3 步让 Markdown date 规则从仅子文本变为刻意设计涉及文件defaultRules.ts、packages/markdown/src/lib/dateElement.spec.ts。工作内容反序列化时同时接受带属性的 date 元素与旧式子文本 date 元素writer 选择保持显式本批次只输出规范子文本属性输出仅读兼容不进 writer补充四类显式测试规范子文本形态、带属性读兼容、旧式读兼容、不可规范化旧式 markdown 回退行为。从当前 defaultRules.ts 的date规则实现看这一步已经兑现deserialize优先读value属性否则取子文本并通过normalizeDateValue归一serialize在存在date且无rawDate时输出带value属性的形态否则回退为子文本。这恰好体现了读双形态、写保守的契约精神。第 4 步集中 media/embed 规范化与 provenance涉及文件parseMediaUrl.ts、parseIframeUrl.ts、parseVideoUrl.ts、parseTwitterUrl.ts、useMediaState.ts、submitFloatingMedia.ts、BaseMediaEmbedPlugin.ts以及作为消费者而非 schema 所有者的 media-embed-node.tsx。工作内容把嵌入规范化提升为parseMediaUrl拥有的一个显式结构化契约让parseIframeUrl只做信任边界助手而非整个契约让 submit/edit/render 路径消费丰富元数据而不是在应用代码里重新解析原始输入对非 allowlist 脚本标记与 PDF 保持显式负向行为持久化 schema 冻结为url、provider、id仅当编辑路径确实需要时才加sourceUrl除非出现真正的序列化消费者否则sourceKind保持为规范化/调试元数据。第 5 步为更丰富的media_embed元数据实现显式 Markdown 所有权涉及文件mediaRules.ts 及其旁新增的专用media_embed规则。工作内容停止依赖隐式行为处理丰富 embed 元数据新增专用media_embedmarkdown 规则所有权不再可选或藏在回退行为后面只保留属于规范契约的元数据不序列化不受支持的原始 snippet/script 载荷。第 6 步在文档法最终提升前扩展测试Date 测试packages/date/src/lib/transforms/insertDate.spec.tsxpackages/date/src/lib/BaseDatePlugin.spec.tsxpackages/markdown/src/lib/dateElement.spec.ts包级 date 助手 spec即 dateValue.spec.ts应用渲染器 specapps/www/src/registry/ui/date-node.spec.tsx、apps/www/src/registry/ui/date-node-static.spec.tsxMedia 测试packages/media/src/lib/media/parseMediaUrl.spec.tspackages/media/src/lib/media-embed/parseIframeUrl.spec.tspackages/media/src/lib/media-embed/BaseMediaEmbedPlugin.spec.tspackages/media/src/react/media/FloatingMedia/submitFloatingMedia.spec.tspackages/media/src/react/media/useMediaState.spec.ts围绕结构化 embed 元数据规范化器的测试显式media_embedmarkdown 往返 spec优先放在packages/markdown/src/lib/mediaSurface.spec.ts旁丰富元数据影响预览或编辑路径选择处的渲染器覆盖第 7 步代码形态被证明后再补 law/文档涉及文件markdown-editing-spec.md、editor-protocol-matrix.md、markdown-parity-matrix.md、2026-04-09-editor-spec-date-media-expansion.md以及公开文档content/(plugins)/(elements)/date.mdx、content/(plugins)/(elements)/media.mdx、content/(plugins)/(serializing)/markdown.mdx。工作内容把 law 从延后的更丰富契约更新为本批次选定的契约保持非目标显式记录新的规范序列化形态保持审计纪律诚实不虚构外部权威依据。第 8 步为包级工作添加 changesets可能触及的包platejs/date、platejs/media、platejs/markdown。风险与缓解五个已知坑及对策计划为每个主要风险都预设了缓解措施这是它区别于普通 todo 清单的关键风险缓解措施date 迁移损坏旧内容双读旧式与规范形态仅在规范化安全时才自动序列化规范形态补充显式旧式往返测试丰富 media 数据再次分散到解析器与 UI让一个共享规范化嵌入助手成为唯一所有者UI 的 submit/render 代码只做消费者不做临时规范化器provenance 字段过早成为永久包袱sourceUrl按需启用由编辑流可逆性证明其必要性没有第二个持久化消费者前sourceKind不进序列化契约嵌入支持悄悄回退到不安全的脚本处理保持窄 allowlist对任意脚本标记与 PDF 保留负向测试在 spec、protocol、docs 中声明信任边界渲染行为把额外产品 law 偷渡进 schema直接从规范date渲染不允许应用渲染器发明额外序列化字段或显示属性验证步骤测试、构建、类型检查、lint 与浏览器验证计划提供了可直接复制的验证命令序列。定向测试bun test packages/date/src/lib/transforms/insertDate.spec.tsx \ packages/date/src/lib/BaseDatePlugin.spec.tsx \ packages/markdown/src/lib/dateElement.spec.ts \ packages/media/src/lib/media/parseMediaUrl.spec.ts \ packages/media/src/lib/media-embed/parseIframeUrl.spec.ts \ packages/media/src/lib/media-embed/BaseMediaEmbedPlugin.spec.ts \ packages/media/src/react/media/FloatingMedia/submitFloatingMedia.spec.ts \ packages/media/src/react/media/useMediaState.spec.ts \ packages/markdown/src/lib/mediaSurface.spec.ts \ apps/www/src/registry/ui/media-video-node.spec.tsx随后运行本批次新增的测试文件包级 date 规范化/格式化助手apps/www/src/registry/ui/date-node.spec.tsx与date-node-static.spec.tsx显式media_embedmarkdown 往返覆盖。构建pnpm install pnpm brl pnpm turbo build --filter./packages/date --filter./packages/media --filter./packages/markdown --filter./apps/www类型检查pnpm turbo typecheck --filter./packages/date --filter./packages/media --filter./packages/markdown --filter./apps/www若过滤后的 typecheck 仍遇到未解析的 workspace 包导入回退方案pnpm build pnpm turbo typecheck --filter./packages/date --filter./packages/media --filter./packages/markdown --filter./apps/wwwLintpnpm lint:fix浏览器验证browser-use --connect http://127.0.0.1:9222重点验证 date demo 路径仍满足规范日渲染无时区漂移日历编辑写入规范 date 值。计划同时强调不可规范化的旧式 markdown 回退与既有非规范date节点渲染器回退必须由显式单元/spec 覆盖不能假装浏览器 demo 会自动覆盖它们——这是测试纪律的细节要求。ADR 摘要为什么这是最小的真修复计划的 ADR 部分浓缩了整个决策决策把剩余 date/media 扩展批次做成源契约升级而非 UI 先行的产品通道驱动因素date 存储弱、media/embed 规范化分散且建模不足、仓库已有足够底气做 Plate 自有决策备选方案保持现有节点形态只补行为直接跳到更丰富的 UI/产品面选择理由这是能真正修复架构的最小批次而不是在模糊数据上继续堆行为后果现在付出更多包级改动长期 DX 更干净未来 AI/streaming 更容易因为源真值显式date 节点语义可能先于 Markdown 线格式变化除非编辑面证明需要provenance 保持窄。后续事项Follow-ups本批次后重新评估是否值得加入更丰富的 date locale/timezone 语义本批次后重新评估本地 media 路径策略是否从specified推进到完全实现。执行组织ralph 与 team 两种模式计划最后给出了执行分工建议对使用多 Agent 协作执行该批次有直接指导意义。若通过ralph执行建议的通道顺序契约决策与文件所有权确认 → date 实现 → media/embed 实现 → markdown 往返更新 → docs/spec 对齐 → 验证。建议推理级别reasoning levels契约选择 / markdown schema / 信任边界xhigh代码与测试highdocs/spec 同步high最终验证评审high若通过team执行建议分工Date 负责人packages/date/**、apps/www/src/registry/ui/date-node.tsx、date-node-static.tsx及 date 测试Media 负责人packages/media/**与 media embed 测试Markdown 文档负责人packages/markdown/**、editor-behavior 文档、公开文档、changesets。启动提示示例$team Execute docs/plans/2026-04-09-date-media-expansion-consensus-plan.md omx team run docs/plans/2026-04-09-date-media-expansion-consensus-plan.md团队验证路径每个负责人在交接前运行其写入范围的定向测试Markdown/文档负责人在合并后运行跨包 markdown/date/media 测试最终验证者按仓库要求顺序执行 build → typecheck → lint最终评审者确认 spec/protocol/parity/公开文档描述一致且非目标没有越界。总结从模糊数据 分散解析到显式契约 单一所有者这份共识计划为编辑器功能扩展提供了一个可复用的方法论模板先用研究文档锁定问题边界再用 RALPLAN-DR 在原则指导下比较选项选定源契约优先的窄批次然后按代码 → 渲染器 → Markdown 规则 → 测试 → 文档法 → changesets的顺序推进最后用明确的验收标准与验证命令收尾。对照当前仓库源码date 半程的核心契约YYYY-MM-DD规范值、toDateString()兼容、无时区漂移解析、双读 Markdown 线格式已在 dateValue.ts 与 defaultRules.ts 中落地media 半程的结构化契约EmbedUrlData、协议白名单信任边界、提交路径统一规范化已在 parseMediaUrl.ts 与 submitFloatingMedia.ts 中成形。对于正在为编辑器扩展做架构决策的开发者本文的契约设计、非目标管理与验证纪律均可直接借鉴。【免费下载链接】plateRich-text editor with AI and shadcn/ui项目地址: https://gitcode.com/GitHub_Trending/pl/plate创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表