Milkdown Link Tooltip 组件完全指南:链接的预览、编辑与编程式 API

Milkdown Link Tooltip 组件完全指南:链接的预览、编辑与编程式 API Milkdown Link Tooltip 组件完全指南链接的预览、编辑与编程式 API【免费下载链接】milkdown Plugin driven WYSIWYG markdown editor framework.项目地址: https://gitcode.com/GitHub_Trending/mi/milkdown本指南以 component-link-tooltip.md 为核心系统讲解 Milkdown 插件驱动 WYSIWYG 编辑器框架中linkTooltip组件的完整用法如何通过configureLinkTooltip接入组件、如何用linkTooltipConfig定制图标与回调以及如何通过linkTooltipAPIaddLink/editLink/removeLink以编程方式操控链接。读完本文你将能够在自己的 Milkdown 编辑器中实现悬停预览链接 → 点击复制 → 编辑 → 删除的完整交互闭环并深入理解其基于milkdown/plugin-tooltip与 Vue 的底层实现原理。组件概述linkTooltip是 milkdown/components 包提供的一个链接工具提示组件。当鼠标悬停在编辑器中的链接由 commonmark 预设的linkSchema定义的 mark上时它会弹出一个工具提示提供以下能力✅ 编辑链接Edit link✅ 预览链接Preview link✅ 复制链接Copy link✅ 编程式链接 APIProgrammatic link API✅addLink✅editLink✅removeLink该组件是一个纯交互逻辑组件不提供任何样式。文档原话明确指出The component itself doesnt provide any styling. You need to write your own CSS to style it. 也就是说你需要为自己的项目编写 CSS 来美化工具提示的外观可以通过查看组件的 DOM 类名如milkdown-link-preview、milkdown-link-edit、link-preview、link-edit来定位样式目标。内部结构预览从源码看组件由两套工具提示组合而成见 tooltips.tslinkPreviewTooltip通过tooltipFactory(LINK_PREVIEW)创建负责预览linkEditTooltip通过tooltipFactory(LINK_EDIT)创建负责编辑。而 configure.ts 中的configureLinkTooltip会依次调用configureLinkPreviewTooltip与configureLinkEditTooltip完成两个子组件的装配。基本使用使用组件分为三步引入配置、引入插件、注册到编辑器。以下是最小可用示例与官方文档一致import { configureLinkTooltip, linkTooltipPlugin, linkTooltipConfig, } from milkdown/components/link-tooltip import { defaultValueCtx, Editor } from milkdown/kit/core import { commonmark, linkSchema } from milkdown/kit/preset/commonmark const editor await Editor.make() .config(configureLinkTooltip) .use(commonmark) .use(linkTooltipPlugin) .create()关键点说明commonmark预设是必需的。链接 mark 的 schemalinkSchema由 commonmark 预设提供linkTooltip组件本身不定义链接 schema只负责在已有linkSchema.mark上做交互。.config(configureLinkTooltip)负责装配插件视图与 API。它把linkTooltipAPI的三个方法绑定到实际的LinkEditTooltip视图实例上并注册两个工具提示的view见 edit-configure.ts 与 preview-configure.ts。.use(linkTooltipPlugin)注册插件。从 index.ts 可以看到linkTooltipPlugin是一个MilkdownPlugin[]依次包含linkTooltipState、linkTooltipAPI、linkTooltipConfig三个 ctx slice以及linkPreviewTooltip、linkEditTooltip两个工具提示插件和toggleLinkCommand命令。此外若你的项目通过 milkdown/kit 聚合包使用组件可直接从milkdown/kit/component引入见 kit/src/component/link-tooltip.ts其内容为export * from milkdown/components/link-tooltip。配置组件的所有可配置项都收敛在一个名为linkTooltipConfig的 ctx slice 中你可以在editor.config阶段通过ctx.update修改它。配置选项总览OptionTypeDefaultDescriptionlinkIconstring链接预览中的图标点击可复制链接editButtonstring✎编辑按钮的图标/文字removeButtonstring⌫删除按钮的图标/文字confirmButtonstringConfirm ⏎链接编辑器中的确认按钮图标/文字onCopyLink(link: string) void() {}链接被复制时触发的回调inputPlaceholderstringPaste link...链接编辑器输入框的占位文本以上默认值可在 slices.ts 的defaultConfig中直接核对LinkTooltipConfig接口也定义于此export interface LinkTooltipConfig { linkIcon: string editButton: string confirmButton: string removeButton: string onCopyLink: (link: string) void inputPlaceholder: string }自定义图标与占位文本linkIcon、editButton、removeButton、confirmButton、inputPlaceholder全部是字符串类型可以使用任意文字或 emoji。注意所有图标在内部都是通过Icon组件渲染的见 edit/component.tsx 与 preview/component.tsx你传入的字符串会直接作为图标内容展示。import { linkTooltipConfig } from milkdown/components/link-tooltip ctx.update(linkTooltipConfig.key, (defaultConfig) ({ ...defaultConfig, linkIcon: , editButton: ✎, removeButton: ❌, confirmButton: ✔️, inputPlaceholder: Paste link here, }))务必注意更新时必须展开defaultConfig...defaultConfig否则会丢失未覆盖的其余配置项。复制链接回调onCopyLink当用户点击预览工具提示中的链接图标时组件会通过navigator.clipboard.writeText将链接写入剪贴板成功后调用onCopyLink(link)见 preview/component.tsx 的onClickPreview实现。你可以用它来做 toast 提示等反馈import { linkTooltipConfig } from milkdown/components/link-tooltip ctx.update(linkTooltipConfig.key, (defaultConfig) ({ ...defaultConfig, onCopyLink: (link: string) { console.log(Link copied:, link) toast(Link copied) }, }))编程式 API组件通过linkTooltipAPI这个 ctx slice 暴露编程式接口。其类型定义见 slices.ts为export interface LinkTooltipAPI { addLink: (from: number, to: number) void editLink: (mark: Mark, from: number, to: number) void removeLink: (from: number, to: number) void }三个方法在 edit-configure.ts 中被绑定到LinkEditTooltip视图实例的对应方法上。官方文档同时提供了一个linkTooltipStateslice用于判断当前工具提示所处的模式preview | edit配合 API 可以实现防重复操作。insertLink通过addLink实现在给定 range 内插入链接。官方示例封装了一个addLink(ctx)函数先检查是否已处于编辑模式、该 range 是否已存在链接 mark均满足后才调用 API。示例中的insertLink即对应 API 的addLink(from, to)import { linkTooltipAPI, linkTooltipState, } from milkdown/components/link-tooltip import { editorViewCtx } from milkdown/kit/core function addLink(ctx: Ctx) { const view ctx.get(editorViewCtx) const { selection, doc } view.state // already in edit mode if (ctx.get(linkTooltipState.key).mode edit) return const has doc.rangeHasMark( selection.from, selection.to, linkSchema.type(ctx) ) // range already has link if (has) return ctx.get(linkTooltipAPI.key).addLink(selection.from, selection.to) }官方文档注明以下示例只是简单实现你可以按需自定义。editLink编辑给定 range 和 mark 上的链接。示例先通过nodeAt取得选区所在节点再从节点的marks中找出linkSchema.mark类型的 mark最后调用 APIimport { linkTooltipAPI, linkTooltipState, } from milkdown/components/link-tooltip import { editorViewCtx } from milkdown/kit/core function editLink(ctx: Ctx) { const view ctx.get(editorViewCtx) const { selection, doc } view.state const node view.state.doc.nodeAt(selection.from) if (!node) return const mark node.marks.find( (mark) mark.type linkSchema.mark.type(ctx) ) if (!mark) return ctx.get(linkTooltipAPI.key).editLink(mark, selection.from, selection.to) }removeLink移除给定 range 内的链接仅移除 mark不会删除文本内容import { linkTooltipAPI, linkTooltipState, } from milkdown/components/link-tooltip import { editorViewCtx } from milkdown/kit/core function removeLink(ctx: Ctx) { const view ctx.get(editorViewCtx) const { selection, doc } view.state ctx.get(linkTooltipAPI.key).removeLink(selection.from, selection.to) }内置切换命令toggleLinkCommand除了手写上述封装组件还内置了一个toggleLinkCommand见 command.ts通过$command(ToggleLink)注册。其逻辑与文档示例高度一致若选区范围内已有链接 mark则调用removeLink否则调用addLink。你可以把它绑定到工具栏按钮或快捷键上实现一键加链接 / 去链接的切换。源码级原理剖析预览工具提示的工作机制configureLinkPreviewTooltip见 preview-configure.ts做了三件事通过handleDOMEvents监听编辑器的mousemove与mouseleavemousemove使用lodash-es的debounce延迟 50ms触发shouldShowPreviewWhenHover检测并且仅在view.hasFocus()且当前linkTooltipState.mode ! edit时执行检测命中后调用findMarkPosition计算出链接 mark 覆盖的完整文本范围from/to再用posToDOMRect得到链接在视口中的矩形位置最终调用LinkPreviewTooltip.show(mark, from, to, rect)显示工具提示。shouldShowPreviewWhenHover见 utils.ts通过view.posAtCoords把鼠标坐标换算成文档位置再取该位置的 node检查其 marks 中是否存在linkSchema.markfindMarkPosition则利用doc.nodesBetween在目标范围内找到 mark 对应的起始与结束位置。编辑工具提示的工作机制LinkEditTooltip见 edit-view.ts负责编辑态addLink(from, to)记录mark: null并进入编辑模式输入框初始为空editLink(mark, from, to)记录 mark 并把mark.attrs.href预填进输入框确认时调用sanitizeLinkHref对链接做安全过滤阻断javascript:等危险协议该函数来自 milkdown/preset-commonmark随后构造 ProseMirror transaction若 mark 存在先removeMark若from to光标位置无选区则插入链接文本并添加 mark否则对选区直接addMark编辑模式下会注册全局pointerdown监听点击工具提示外部即取消编辑onHide时通过requestAnimationFrame将焦点归还给编辑器视图。预览组件的安全细节preview/component.tsx 中有一个值得注意的细节预览a标签的href使用sanitizeLinkHref处理后的安全值预览锚点位于 contenteditable 区域之外直接使用原始javascript:href 会在点击时被执行而展示文本仍然使用原始链接值同时点击复制走navigator.clipboard.writeText成功后触发onCopyLink。状态与插件装配linkTooltipState以preview为默认模式见 slices.ts。预览视图订阅该 slice当模式切换到edit时自动隐藏预览工具提示见 preview-view.ts 的#onStateChange。此外预览视图还维护了#hovering状态鼠标停留在工具提示上时不隐藏移出后才允许隐藏避免交互过程中工具提示闪烁消失。常见问题与注意事项样式需要自备组件不输出任何 CSS你需要针对milkdown-link-preview/milkdown-link-edit容器及link-preview/link-edit内部类名自行编写样式。必须加载 commonmark 预设链接 schema 来自 commonmark否则组件无法识别链接 mark预览与编辑均不会触发。configureLinkTooltip与linkTooltipPlugin缺一不可前者把 API 绑定到实际视图并注册 tooltip 的view后者把三个 slice、两个 tooltip 插件和切换命令注册进编辑器。安全过滤内置无论是编辑确认还是预览展示链接 href 都会经过sanitizeLinkHref过滤可有效防止javascript:等协议注入。编程式 API 是空实现兜底未经过configureLinkTooltip配置时linkTooltipAPI的三个方法为() {}空函数因此务必保证配置与插件均已正确加载。【免费下载链接】milkdown Plugin driven WYSIWYG markdown editor framework.项目地址: https://gitcode.com/GitHub_Trending/mi/milkdown创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考