npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

wang-markdown-render

v1.0.0

Published

Marknote Markdown 渲染与编辑核心 SDK

Readme

wang-markdown-render

Marknote Markdown 编辑器核心 SDK。

使用

最小可用示例:

import { MarkdownCore } from 'wang-markdown-render';
import 'wang-markdown-render/style.css';

const editor = new MarkdownCore(hostElement, {
  value: '# 标题',
  readOnly: false,
  imageBasePath: '',
  onChange: (source) => {},
  onThemeChange: (theme) => {},
  onContextMenu: (payload) => {},
  onImageFileAction: async (context) => null,
  onImageContextMenu: (payload) => {},
  onImageContextMenuClose: (payload) => {},
  onImageDblClick: (payload) => {},
  pickImagePath: async (context) => '',
});

editor.focus();
editor.execCommand('bold');
editor.findAndReveal('关键字', { direction: 'next', highlight: true, focus: false });

const matches = MarkdownCore.findMarkdownMatches(editor.getValue(), '关键字');
const metrics = MarkdownCore.collectDocumentMetrics(editor.getValue());

const sourceEditor = MarkdownCore.createSourceCodeEditor(sourceHostElement, {
  value: editor.getValue(),
  onChange: (source) => {},
});

只读渲染:

const viewer = new MarkdownCore(hostElement, {
  value: markdownSource,
  readOnly: true,
});

静态工具 API:

const matches = MarkdownCore.findMarkdownMatches(source, 'keyword');
const metrics = MarkdownCore.collectDocumentMetrics(source);
MarkdownCore.applyPageTheme({ cursorColor: '#1890ff' });

构造与基础

new MarkdownCore(host, options)

创建编辑器实例并挂载到 host

options:

  • value: string 初始 Markdown 内容。
  • readOnly: boolean 是否只读渲染。为 true 时保留选择、复制、查找、滚动和程序化 setValue,阻止输入、粘贴、剪切、删除、格式化、替换和撤销重做等会修改源码的操作。
  • imageBasePath: string 图片相对路径解析基准目录。
  • onChange(source) 内容变化回调。
  • onThemeChange(theme) 主题变化回调。
  • onContextMenu(payload) 文档右键菜单回调。core 只传出上下文,不渲染菜单 UI。
  • onImageFileAction(context) 图片右键菜单文件操作回调。
  • onImageContextMenu(payload) 图片右键菜单回调。core 只传出图片上下文,不渲染菜单 UI。
  • onImageContextMenuClose(payload) 图片菜单上下文被 core 清理时回调,外层可同步关闭菜单。
  • onImageDblClick(payload) 图片双击回调,传出当前图片、图片列表和当前索引。
  • onPasteImage(context) 粘贴图片保存回调,返回 { success, url, alt } 后插入 Markdown 图片。
  • onCodeFormatError(payload) 代码块格式化失败回调,传出 { language, reason, message, error }
  • pickImagePath(context) 图片路径选择回调。
  • renderBatchSize: number 分批渲染批大小。
  • asyncRenderLineThreshold: number 超过该行数后在非聚焦状态下分批渲染。
  • codeBlockLineNumbersVisible: boolean 是否显示代码块行号,默认 true

基础实例方法

| API | 说明 | | --- | --- | | getValue() | 获取当前 Markdown 源码。 | | isReadOnly() | 获取当前是否只读。 | | setReadOnly(readOnly) | 动态切换只读状态。 | | setValue(nextSource, config = {}) | 设置源码并重新渲染。config.preserveSelectiontrue 时保留选择和行 ID。 | | getCursorOffset() | 获取当前光标在源码中的偏移位置,无有效位置时返回 null。 | | getViewportAnchor() | 获取当前视口顶部对应的 Markdown 源码行锚点。 | | setViewportAnchor(anchor) | 按源码行锚点恢复渲染视图滚动位置。 | | focus() | 聚焦正文编辑器并恢复选择。 | | focusAtOffset(offset, options = {}) | 聚焦到指定源码偏移位置。 | | focusToEnd(options = {}) | 聚焦到文档末尾。 | | onNextRenderReady(callback) | 在下一次文档渲染就绪后执行一次回调。 | | blur() | 取消正文编辑器焦点。 | | destroy() | 销毁编辑器、事件监听、浮层和 DOM。 | | setTheme(theme) | 设置主题,支持 'light' / 'dark',成功返回 true。 | | getTheme() | 获取当前主题。 | | setImageBasePath(imageBasePath, config = {}) | 设置图片基准路径。config.render === false 时不立即重渲染。 | | setContextMenuHandler(handler) | 设置文档右键菜单回调。 | | emitChange() | 主动触发 options.onChange。 |

ViewportAnchor 结构:

{
  lineIndex: 0,
  lineOffsetRatio: 0,
}

MarkdownCore.createSourceCodeEditor(host, options)

创建源码模式编辑器实例。

options:

  • value: string 初始 Markdown 源码。
  • onChange(source, update) 源码变化回调。

源码编辑器实例方法:

| API | 说明 | | --- | --- | | getValue() | 获取当前 Markdown 源码。 | | setValue(nextSource) | 从外部同步源码到源码编辑器。 | | focus() | 聚焦源码编辑器。 | | getViewportAnchor() | 获取当前源码视口锚点。 | | setViewportAnchor(anchor) | 恢复源码视口滚动位置。 | | undo() | 撤销源码模式编辑。 | | redo() | 重做源码模式编辑。 | | resize() | 重新测量 CodeMirror 布局。 | | scrollToLine(lineIndex) | 滚动到指定源码行。 | | selectRange(start, end, lineIndex, options) | 选中源码范围并滚动到可见位置。 | | destroy() | 销毁源码编辑器实例。 |

命令 API

execCommand(name, options = {})

执行注册命令。返回 true 表示命令存在并已执行。

常用命令:

| 命令 | 说明 | | --- | --- | | bold | 加粗。 | | italic | 斜体。 | | strike / strikethrough | 删除线。 | | underline | 下划线,使用 <u>text</u>。 | | comment | HTML 注释,使用 <!--text-->。 | | inlineCode | 行内代码。 | | highlight | 高亮标记 ==text==。 | | subscript | 下标。 | | superscript | 上标。 | | paragraph | 转为普通段落。 | | heading | 标题,使用 options.level 指定 1-6。 | | heading1 / heading2 / heading3 | 标题快捷命令。 | | quote | 引用块。 | | orderedList | 有序列表。 | | unorderedList | 无序列表。 | | taskList | 任务列表。 | | codeBlock / insertCodeBlock | 代码块。 | | horizontalRule / insertHorizontalRule | 分割线。 | | insertLink | 插入链接,options.url 可指定地址。 | | insertImage | 插入图片,支持 options.url / options.alt。 | | insertTable | 插入表格,支持 options.rows / options.columns。 | | insertText | 插入文本,使用 options.text。 | | undo / redo | 撤销 / 重做。 | | copy / cut / paste / pasteText / delete | 复制、剪切、粘贴、粘贴纯文本、删除当前选区。 | | focus | 聚焦编辑器。 |

命令管理

| API | 说明 | | --- | --- | | registerCommand(name, handler) | 注册自定义命令。 | | getCommands() | 获取已注册命令名列表。 |

直接格式化方法

| API | 说明 | | --- | --- | | toggleInline(marker) | 按指定 Markdown 标记切换行内样式,如 ***`。 | | toggleHtmlInline(tagName) | 按 HTML 标签切换行内样式,如 u 对应 <u>text</u>。 | | toggleHtmlComment() | 切换 HTML 注释包裹。 | | toggleBlock(command) | 切换块样式,如 { type: 'heading', level: 2 }。 | | toggleTaskLine(lineIndex) | 切换任务列表勾选状态。 | | copySelection() | 复制当前选中的 Markdown 源码。 | | cutSelection() | 剪切当前选中的 Markdown 源码。 | | pasteFromClipboard() | 从系统剪贴板粘贴纯文本。 | | deleteSelection() | 删除当前选区。 | | insertTextAtSelection(text) | 替换当前选区为文本。 | | insertCodeBlock() | 插入代码块。 | | insertHorizontalRule() | 插入分割线。 | | insertLink(url = 'https://example.com') | 插入链接。 | | insertImage(urlOrOptions, options = {}) | 插入图片。 | | insertTable(options = {}) | 插入表格。 |

查找与替换 API

| API | 说明 | | --- | --- | | findMatches(query, options = {}) | 返回全部匹配项,不改变正文状态。 | | findAndReveal(query, options = {}) | 查找并锚点到下一个/上一个匹配项,默认高亮关键字。 | | findNextMatch(query, options = {}) | 查找下一个匹配项。 | | findPreviousMatch(query, options = {}) | 查找上一个匹配项。 | | selectFindMatch(match, options = {}) | 选中并滚动到指定匹配项。 | | highlightFindTarget(match, options = {}) | 只高亮匹配关键字。 | | clearFindTarget() | 清除查找关键字高亮。 | | replaceFindMatch(match, replacement = '') | 替换指定匹配项。 | | replaceAllMatches(query, replacement = '', options = {}) | 替换全部匹配项。 |

options:

  • caseSensitive: boolean 区分大小写。
  • wholeWord: boolean 全词匹配。
  • direction: 'next' | 'previous' 查找方向。
  • highlight: boolean 是否高亮查找关键字。
  • focus: boolean 是否聚焦正文编辑器。
  • block: ScrollLogicalPosition 纵向滚动位置,默认 'center'
  • inline: ScrollLogicalPosition 横向滚动位置,默认 'nearest'
  • behavior: ScrollBehavior 滚动行为,默认 'auto'
  • pulseDuration: number 高亮动效时长。

返回的匹配项结构:

{
  id,
  index,
  start,
  end,
  text,
  lineIndex,
  localStart,
  localEnd,
  endLineIndex,
  endLocalOffset,
  lineText,
}

大纲与滚动 API

| API | 说明 | | --- | --- | | getOutline() | 获取文档标题大纲。 | | getTableOfContentsData() | 等同于 getOutline()。 | | scrollToLine(lineIndex, options = {}) | 滚动到指定行。 | | clearOutlineTarget() | 清除侧边栏跳转的整行高亮。 |

scrollToLine 常用 options:

  • highlight: boolean 是否使用侧边栏跳转的整行高亮。
  • select: boolean 是否把光标移动到该行开头。
  • block: ScrollLogicalPosition 默认 'center'
  • behavior: ScrollBehavior 默认 'auto'
  • pulseDuration: number 高亮动效时长。

导出与元数据 API

| API | 说明 | | --- | --- | | getHTML(options = {}) | 获取渲染后的 HTML。options.wrappertrue 时返回外层节点。 | | exportHTML(options = {}) | 导出完整 HTML 文档字符串。 | | getMarkdownExportData(options = {}) | 获取 Markdown 导出数据。 | | getPDFExportData(options = {}) | 获取 PDF 导出数据。 | | getTitle() | 获取首个标题作为文档标题。 | | getMetadata() | 获取标题、行数、字数、创建/更新时间等元数据。 |

历史记录 API

| API | 说明 | | --- | --- | | undo() | 撤销。 | | redo() | 重做。 | | pushHistory(snapshot, options = {}) | 压入历史记录。 | | restoreHistoryState(state) | 恢复历史状态。 |

表格 API

| API | 说明 | | --- | --- | | showTableToolbar(lineIndex, columnIndex = 0) | 显示当前表格工具条。 | | hideTableToolbar() | 隐藏表格工具条。 | | updateTableToolbar() | 更新表格工具条状态。 | | setTableColumnAlignment(alignment) | 设置当前列对齐方式:left / center / right。 | | resizeCurrentTable(rows, columns) | 调整当前表格行列数。 | | deleteCurrentTable() | 删除当前表格。 | | mountTableToolbar() | 挂载表格工具条。 | | destroyTableToolbar() | 销毁表格工具条。 | | handleTablePointer(event) | 处理表格区域指针事件。 |

图片 API

| API | 说明 | | --- | --- | | insertImage(urlOrOptions, options = {}) | 插入图片。 | | setImageBasePath(imageBasePath, config = {}) | 设置图片基准路径。 | | setImagePathPicker(handler) | 设置图片路径选择器。 | | pickImagePath(context = {}) | 调用图片路径选择器。 | | queueImagePathFocus(lineIndex, sourceStart) | 等待下一次渲染后聚焦图片路径输入框。 | | focusPendingImagePathInput() | 聚焦待处理图片路径输入框。 | | commitImagePathInput(input) | 提交图片路径输入。 | | openImagePathPicker(input) | 打开图片路径选择器。 | | handleImagePathKeyDown(event) | 处理图片路径输入快捷键。 | | handleImagePathPointer(event) | 处理图片路径输入指针事件。 | | handleImageContextMenu(event) | 生成图片右键上下文并触发 onImageContextMenu。 | | handleImageDoubleClick(event) | 处理图片双击预览回调。 | | setImageContextMenuHandler(handler) | 设置图片右键菜单回调。 | | setImageContextMenuCloseHandler(handler) | 设置图片右键菜单关闭回调。 | | getImageContextFromEvent(event) | 根据事件目标读取图片上下文。 | | setImageMenuContext(context) | 缓存当前图片菜单上下文。 | | getImageMenuContext() | 获取当前图片菜单上下文。 | | clearImageMenuContext() | 清理当前图片菜单上下文。 | | hideImageContextMenu() | 清理图片菜单上下文,并触发 onImageContextMenuClose。 | | destroyImageContextMenu() | 销毁阶段清理图片菜单上下文。 | | runImageMenuAction(action, context = getImageMenuContext()) | 执行图片菜单动作。 |

onImageDblClick(payload) 回调结构:

{
  image: { src, url, filePath, alt, title, kind, lineIndex, sourceStart, sourceEnd, start, end, sourceText },
  images: [{ src, url, filePath, alt, title, kind, lineIndex, sourceStart, sourceEnd, start, end, sourceText }],
  index: 0,
}

onContextMenu(payload) 回调结构:

{
  editor,
  event,
  clientX: 0,
  clientY: 0,
  position: { x: 0, y: 0 },
  readOnly: false,
  context: {
    block: 'paragraph',
    hasSelection: false,
    headingLevel: 0,
    lineIndex: 0,
    source: '',
  },
}

onImageContextMenu(payload) 回调结构:

{
  editor,
  event,
  context: { src, url, filePath, alt, title, kind, lineIndex, sourceStart, sourceEnd, start, end, sourceText },
  image: { src, url, filePath, alt, title, kind, lineIndex, sourceStart, sourceEnd, start, end, sourceText },
  clientX: 0,
  clientY: 0,
  position: { x: 0, y: 0 },
  readOnly: false,
}

代码块语言 API

| API | 说明 | | --- | --- | | showCodeLanguageEditor(block, language = '', syncInput = true) | 显示代码块工具栏并同步语言输入。 | | hideCodeLanguageEditor() | 隐藏代码块工具栏。 | | setCodeBlockLanguage(openLineIndex, nextLanguage, selectionSnapshot = null) | 设置代码块语言。 | | updateCodeLanguageEditor() | 更新代码块工具栏位置与内容。 | | handleCodeLanguagePointer(event) | 处理代码块语言区域指针事件。 | | mountCodeLanguageEditor() | 挂载代码块工具栏。 | | destroyCodeLanguageEditor() | 销毁代码块工具栏。 | | toggleCodeBlockWrap(force) | 切换代码块自动换行。 | | setCodeBlockLineNumbersVisible(visible) | 设置是否显示代码块行号。 | | copyCurrentCodeBlock() | 复制当前代码块内容。 |

渲染与源码同步 API

这些方法通常由 core 内部调用,外部扩展时可按需使用。

| API | 说明 | | --- | --- | | renderAll(options = {}) | 全量渲染。 | | renderAfterChange(previousLines, start, end, insertedText) | 根据变更范围渲染。 | | renderLinePatch(previousLine, lineIndex) | 单行局部渲染。 | | replaceLine(lineIndex) | 替换指定行 DOM。 | | createLineElement(source, lineIndex) | 创建可见行 DOM。 | | updateActiveLine() | 更新当前活动行和行内 token 状态。 | | cancelPendingRender() | 取消待处理分批渲染。 | | commitChange(start, end, text, nextSelection, snapshot) | 提交源码变更。 | | syncFromDom(historySnapshot = null) | 从 DOM 同步源码。 | | mount() | 挂载基础 DOM。 |

输入事件 API

这些方法主要供编辑器事件绑定内部使用。

| API | 说明 | | --- | --- | | bindEvents() | 绑定编辑器事件。 | | onBeforeInput(event) | 处理 beforeinput。 | | onInput(event) | 处理输入同步。 | | createInputOperation(event) | 根据输入事件生成变更操作。 | | onKeyDown(event) | 处理键盘事件。 | | onMouseDown(event) | 处理鼠标按下。 | | onClick(event) | 处理点击。 | | onDoubleClick(event) | 处理双击。 | | onContextMenu(event) | 处理右键菜单。 | | onPaste(event) | 处理粘贴。 | | onCopy(event) | 处理复制。 | | onCut(event) | 处理剪切。 | | insertTextAtSelection(text) | 在当前选区插入文本。 | | createSmartLineBreakOperation(snapshot, selection, options = {}) | 创建智能换行操作。 | | createPrefixDeleteOperation(snapshot) | 创建块前缀删除操作。 | | createHorizontalRuleDeleteOperation(snapshot, selection, direction) | 创建分割线删除操作。 | | createTableCellNavigation(snapshot, direction) | 创建表格单元格导航操作。 |

说明:bindEvents() 会在实例上生成 handleBeforeInputhandleInputhandlePastehandleCopyhandleCuthandleMouseDownhandleClickhandleDoubleClickhandleContextMenuhandleKeyDownhandleFocusInhandleFocusOuthandleSelectionChangehandleCompositionStarthandleCompositionEndhandleWindowResize 等事件处理引用,用于解绑和生命周期管理。

静态工具 API

| API | 说明 | | --- | --- | | MarkdownCore.appendInlineMarkdown(...args) | 追加行内 Markdown。 | | MarkdownCore.appendTableMarkdown(...args) | 追加表格 Markdown。 | | MarkdownCore.buildLineContexts(...args) | 构建行上下文。 | | MarkdownCore.getBlockPrefixInfo(...args) | 获取块前缀信息。 | | MarkdownCore.getContinuationInfo(...args) | 获取续行信息。 | | MarkdownCore.isContextSensitiveLine(...args) | 判断是否为上下文敏感行。 | | MarkdownCore.isMarkdownSyntaxDisabledContext(...args) | 判断是否禁用 Markdown 语法。 | | MarkdownCore.parseMarkdownLine(...args) | 解析 Markdown 行。 | | MarkdownCore.collectDocumentMetrics(...args) | 收集文档指标。 | | MarkdownCore.findMarkdownMatches(...args) | 查找 Markdown 匹配项。 | | MarkdownCore.stripHtmlTags(...args) | 剥离 HTML 标签。 | | MarkdownCore.stripInlineMarkdown(...args) | 剥离行内 Markdown。 | | MarkdownCore.applyPageTheme(...args) | 应用页面主题。 | | MarkdownCore.getPageCursorColor(...args) | 获取页面光标颜色。 | | MarkdownCore.setPageCursorColor(...args) | 设置页面光标颜色。 | | MarkdownCore.getPageAccentColor(...args) | 获取页面强调色。 | | MarkdownCore.setPageAccentColor(...args) | 设置页面强调色。 | | MarkdownCore.createSourceCodeEditor(...args) | 创建源码编辑器。 | | MarkdownCore.createDocumentMetricsWorker(options = {}) | 创建文档指标 Worker。 | | MarkdownCore.createFindMatchesWorker(options = {}) | 创建查找匹配 Worker。 | | MarkdownCore.createLineContextsWorker(options = {}) | 创建行上下文 Worker。 |

静态属性

| 属性 | 说明 | | --- | --- | | MarkdownCore.SourceCodeEditorCore | 源码编辑器核心类。 | | MarkdownCore.MarkdownDocumentMetrics | 文档指标类。 | | MarkdownCore.MarkdownSearchMatcher | 搜索匹配类。 | | MarkdownCore.MarkdownLineContextBuilder | 行上下文构建器类。 | | MarkdownCore.DEFAULT_CURSOR_COLOR | 默认光标颜色。 | | MarkdownCore.DEFAULT_PAGE_ACCENT_COLOR | 默认页面强调色。 | | MarkdownCore.TASK_CHECK_PATTERN | 任务勾选正则。 | | MarkdownCore.patterns | Markdown 正则集合。 | | MarkdownCore.HEADING_PATTERN | 标题正则。 | | MarkdownCore.QUOTE_PATTERN | 引用正则。 | | MarkdownCore.TASK_PATTERN | 任务列表正则。 | | MarkdownCore.UNORDERED_PATTERN | 无序列表正则。 | | MarkdownCore.ORDERED_PATTERN | 有序列表正则。 | | MarkdownCore.FENCE_PATTERN | 代码块正则。 | | MarkdownCore.FENCE_OPEN_PATTERN | 代码块开始正则。 | | MarkdownCore.FENCE_CLOSE_PATTERN | 代码块结束正则。 | | MarkdownCore.HORIZONTAL_RULE_PATTERN | 分割线正则。 | | MarkdownCore.TABLE_DIVIDER_PATTERN | 表格分隔行正则。 | | MarkdownCore.TABLE_ROW_PATTERN | 表格行正则。 |

构建

在根项目中构建:

npm run sdk:build

在 SDK 目录中单独构建:

npm run build

构建产物输出到 dist/