diff --git a/.changeset/late-ants-explain.md b/.changeset/late-ants-explain.md
new file mode 100644
index 000000000..eb161f1af
--- /dev/null
+++ b/.changeset/late-ants-explain.md
@@ -0,0 +1,5 @@
+---
+"cherry-markdown": minor
+---
+
+refactor: 重构链接属性配置类型和工具栏选项。现有使用 `hiddenToolbar` 的代码仍然可以正常工作(向后兼容),但 IDE 会显示废弃警告,建议迁移到 `registerHeadlessToolbars`。
diff --git a/packages/cherry-markdown/src/Cherry.config.js b/packages/cherry-markdown/src/Cherry.config.js
index 3c179f09e..eba66c51f 100644
--- a/packages/cherry-markdown/src/Cherry.config.js
+++ b/packages/cherry-markdown/src/Cherry.config.js
@@ -650,7 +650,7 @@ const defaultConfig = {
* @deprecated 不再支持theme的配置,统一在`themeSettings.toolbarTheme`中配置
*/
// theme: 'dark', // light or dark
- showToolbar: true, // false:不展示顶部工具栏; true:展示工具栏; toolbars.showToolbar=false 与 toolbars.toolbar=false 等效
+ showToolbar: true, // false:不展示顶部工具栏和侧边栏; true:展示工具栏; toolbars.showToolbar=false 与 toolbars.toolbar=false 等效
toolbar: [
'bold',
'italic',
@@ -690,7 +690,8 @@ const defaultConfig = {
sidebar: false,
bubble: ['bold', 'italic', 'underline', 'strikethrough', 'sub', 'sup', 'quote', '|', 'size', 'color'], // array or false
float: ['h1', 'h2', 'h3', '|', 'checklist', 'quote', 'table', 'code'], // array or false
- hiddenToolbar: [], // 不展示在编辑器中的工具栏,只使用工具栏的api和快捷键功能
+ hiddenToolbar: [], // @deprecated 请使用 registerHeadlessToolbars 代替
+ registerHeadlessToolbars: [], // 不展示在编辑器中的工具栏,只使用工具栏的 api 和快捷键功能
toc: false, // 不展示悬浮目录
// toc: {
// updateLocationHash: false, // 要不要更新URL的hash
diff --git a/packages/cherry-markdown/src/Cherry.js b/packages/cherry-markdown/src/Cherry.js
index 803a99beb..ca591b912 100644
--- a/packages/cherry-markdown/src/Cherry.js
+++ b/packages/cherry-markdown/src/Cherry.js
@@ -704,11 +704,14 @@ export default class Cherry extends CherryStatic {
}
createHiddenToolbar() {
- if (this.options.toolbars.hiddenToolbar) {
- $expectTarget(this.options.toolbars.hiddenToolbar, Array);
+ // registerHeadlessToolbars 优先级高于 hiddenToolbar
+ const headlessToolbars =
+ this.options.toolbars.registerHeadlessToolbars || this.options.toolbars.hiddenToolbar;
+ if (headlessToolbars) {
+ $expectTarget(headlessToolbars, Array);
this.hiddenToolbar = new HiddenToolbar({
$cherry: this,
- buttonConfig: this.options.toolbars.hiddenToolbar,
+ buttonConfig: headlessToolbars,
customMenu: this.options.toolbars.customMenu,
});
this.toolbar.collectMenuInfo(this.hiddenToolbar);
diff --git a/packages/cherry-markdown/src/Event.js b/packages/cherry-markdown/src/Event.js
index 01673bf92..5884f9af7 100644
--- a/packages/cherry-markdown/src/Event.js
+++ b/packages/cherry-markdown/src/Event.js
@@ -64,6 +64,10 @@ export default class Event {
this.emitter.all.clear();
}
+ /**
+ * 根据配置项绑定事件回调
+ * @param {import('~types/cherry').CherryOptions} options 配置项
+ */
bindCallbacksByOptions(options) {
if (options.callback.afterChange) {
this.on(this.Events.afterChange, (msg) => {
diff --git a/packages/cherry-markdown/src/core/hooks/AutoLink.js b/packages/cherry-markdown/src/core/hooks/AutoLink.js
index e64e21047..be08a49c1 100644
--- a/packages/cherry-markdown/src/core/hooks/AutoLink.js
+++ b/packages/cherry-markdown/src/core/hooks/AutoLink.js
@@ -31,9 +31,31 @@ export default class AutoLink extends SyntaxBase {
super({ config });
this.enableShortLink = !!config.enableShortLink;
this.shortLinkLength = config.shortLinkLength;
- // eslint-disable-next-line no-nested-ternary
- this.target = config.target ? `target="${config.target}"` : !!config.openNewPage ? 'target="_blank"' : '';
- this.rel = config.rel ? `rel="${config.rel}"` : '';
+ const validTarget = ['_blank', '_parent', '_self', '_top'];
+ if (config.target && validTarget.includes(config.target)) {
+ this.target = `target="${config.target}"`;
+ } else {
+ this.target = config.openNewPage ? 'target="_blank"' : '';
+ }
+ // HTML标准 标签的 rel 属性有效值
+ const validRel = [
+ 'alternate',
+ 'author',
+ 'bookmark',
+ 'external',
+ 'help',
+ 'license',
+ 'next',
+ 'nofollow',
+ 'noopener',
+ 'noreferrer',
+ 'opener',
+ 'prev',
+ 'privacy-policy',
+ 'search',
+ 'tag',
+ ];
+ this.rel = validRel.includes(config.rel) ? `rel="${config.rel}"` : '';
}
/**
diff --git a/packages/cherry-markdown/src/core/hooks/Link.js b/packages/cherry-markdown/src/core/hooks/Link.js
index 6983a0048..3aafda6ed 100644
--- a/packages/cherry-markdown/src/core/hooks/Link.js
+++ b/packages/cherry-markdown/src/core/hooks/Link.js
@@ -24,9 +24,31 @@ export default class Link extends SyntaxBase {
constructor({ config, globalConfig }) {
super({ config });
- // eslint-disable-next-line no-nested-ternary
- this.target = config.target ? `target="${config.target}"` : !!config.openNewPage ? 'target="_blank"' : '';
- this.rel = config.rel ? `rel="${config.rel}"` : '';
+ const validTarget = ['_blank', '_parent', '_self', '_top'];
+ if (config.target && validTarget.includes(config.target)) {
+ this.target = `target="${config.target}"`;
+ } else {
+ this.target = config.openNewPage ? 'target="_blank"' : '';
+ }
+ // HTML标准 标签的 rel 属性有效值
+ const validRel = [
+ 'alternate',
+ 'author',
+ 'bookmark',
+ 'external',
+ 'help',
+ 'license',
+ 'next',
+ 'nofollow',
+ 'noopener',
+ 'noreferrer',
+ 'opener',
+ 'prev',
+ 'privacy-policy',
+ 'search',
+ 'tag',
+ ];
+ this.rel = validRel.includes(config.rel) ? `rel="${config.rel}"` : '';
}
/**
diff --git a/packages/cherry-markdown/types/cherry.d.ts b/packages/cherry-markdown/types/cherry.d.ts
index 1b1f121d6..fe383c808 100644
--- a/packages/cherry-markdown/types/cherry.d.ts
+++ b/packages/cherry-markdown/types/cherry.d.ts
@@ -1,13 +1,74 @@
import CodeMirror from 'codemirror';
import SyntaxBase from '../src/core/SyntaxBase';
-import { FormulaMenu } from '@/toolbars/BubbleFormula';
+
+/**
+ * 公式菜单项类型
+ * @see BubbleFormula.js 中的 FormulaMenu typedef
+ */
+export interface FormulaMenu {
+ [key: string]: {
+ [key: string]: string;
+ };
+}
+
+/**
+ * HTML 标准 `` 标签的 target 属性有效值
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#target MDN - HTML anchor target}
+ *
+ * | 值 | 描述 |
+ * |---|---|
+ * | `_blank` | 在新窗口/新标签页中打开链接 |
+ * | `_self` | 在当前窗口/标签页中打开链接(默认行为) |
+ * | `_parent` | 在父框架中打开链接(用于 iframe 嵌套场景) |
+ * | `_top` | 在最顶层窗口中打开链接,跳出所有 iframe 嵌套 |
+ */
+export type AnchorTargetValue = '_blank' | '_parent' | '_self' | '_top';
+
+/**
+ * HTML 标准 `` 标签的 rel 属性有效值
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/rel MDN - HTML rel attribute}
+ *
+ * | 值 | 描述 |
+ * |---|---|
+ * | `alternate` | 当前文档的替代版本(翻译、PDF 等) |
+ * | `author` | 指向作者信息页面 |
+ * | `bookmark` | 最近祖先文章的永久链接 |
+ * | `external` | 外部链接,不属于当前站点 |
+ * | `help` | 上下文相关的帮助页面 |
+ * | `license` | 内容的版权许可协议 |
+ * | `next` | 系列文档中的下一篇 |
+ * | `nofollow` | 告诉搜索引擎不追踪此链接 |
+ * | `noopener` | 阻止新窗口通过 window.opener 访问原窗口 |
+ * | `noreferrer` | 不发送 Referer 头,同时包含 noopener 效果 |
+ * | `opener` | 允许新窗口访问原窗口(与 noopener 相反) |
+ * | `prev` | 系列文档中的上一篇 |
+ * | `privacy-policy` | 隐私政策页面 |
+ * | `search` | 搜索页面 |
+ * | `tag` | 描述文档标签/关键词的页面 |
+ */
+export type AnchorRelValue =
+ | 'alternate'
+ | 'author'
+ | 'bookmark'
+ | 'external'
+ | 'help'
+ | 'license'
+ | 'next'
+ | 'nofollow'
+ | 'noopener'
+ | 'noreferrer'
+ | 'opener'
+ | 'prev'
+ | 'privacy-policy'
+ | 'search'
+ | 'tag';
export interface CherryExternalsOptions {
[key: string]: any;
}
/**
- * 自定义toolbar键名[key]
+ * 自定义 toolbar 键名 [key]
*/
export interface CustomMenuType {
[key: string]: any;
@@ -73,9 +134,9 @@ export interface _CherryOptions | undefined;
- // 打开draw.io编辑页的url,如果为空则drawio按钮失效
+ // 打开 draw.io 编辑页的 url,如果为空则 drawio 按钮失效
drawioIframeUrl: string;
- // drawio iframe的样式
+ // drawio iframe 的样式
drawioIframeStyle: string;
/** 文件上传回调 */
fileUpload: CherryFileUploadHandler;
@@ -97,27 +158,27 @@ export interface _CherryOptions string;
@@ -152,8 +213,8 @@ export interface _CherryOptions boolean;
};
event: {
- focus?: ({ e: MouseEvent, cherry: Cherry }) => void;
- blur?: ({ e: MouseEvent, cherry: Cherry }) => void;
+ focus?: (params: { e: Event; cherry: Cherry }) => void;
+ blur?: (params: { e: Event; cherry: Cherry }) => void;
/** 编辑器内容改变并完成渲染后触发 */
afterChange?: CherryLifecycle;
/** 编辑器完成初次渲染后触发 */
@@ -161,7 +222,12 @@ export interface _CherryOptions void;
+ selectionChange?: (params: {
+ selections: string[];
+ lastSelections: string[];
+ // CodeMirror.EditorSelectionChange
+ info: any;
+ }) => void;
/** 变更语言时触发 */
afterChangeLocale?: (locale: string) => void;
/** 变更主题时触发 */
@@ -177,11 +243,11 @@ export interface _CherryOptions string;
/**
- * 额外允许渲染的html标签
+ * 额外允许渲染的 html 标签
* 标签以英文竖线分隔,如:htmlWhiteList: 'iframe|script|style'
- * 默认为空,默认允许渲染的html见src/utils/sanitize.js whiteList 属性
+ * 默认为空,默认允许渲染的 html 见 src/utils/sanitize.js whiteList 属性
* 需要注意:
- * - 启用iframe、script等标签后,会产生xss注入,请根据实际场景判断是否需要启用
- * - 一般编辑权限可控的场景(如api文档系统)可以允许iframe、script等标签
+ * - 启用 iframe、script 等标签后,会产生 xss 注入,请根据实际场景判断是否需要启用
+ * - 一般编辑权限可控的场景(如 api 文档系统)可以允许 iframe、script 等标签
*/
htmlWhiteList?: string;
/**
- * html黑名单,优先级高于htmlWhiteList
+ * html 黑名单,优先级高于 htmlWhiteList
* 标签以英文竖线分隔,如:htmlBlackList: 'div|span'
- * 默认为空,表示不禁止渲染任何html标签
+ * 默认为空,表示不禁止渲染任何 html 标签
* 需要注意:
- * - 启用htmlBlackList后,将禁止渲染htmlBlackList里配置的标签
- * - 如果要禁用所有html标签,可配置htmlBlackList: '*'
+ * - 启用 htmlBlackList 后,将禁止渲染 htmlBlackList 里配置的标签
+ * - 如果要禁用所有 html 标签,可配置 htmlBlackList: '*'
*/
htmlBlackList?: string;
/**
- * 额外允许渲染的html标签的属性
+ * 额外允许渲染的 html 标签的属性
* 标签以英文竖线分隔,如:htmlAttrWhiteList: 'part|onmouseover|my-attr'
- * 默认为空,默认允许渲染的html标签属性见 https://github.com/cure53/DOMPurify/blob/main/src/attrs.ts
+ * 默认为空,默认允许渲染的 html 标签属性见 https://github.com/cure53/DOMPurify/blob/main/src/attrs.ts
*/
htmlAttrWhiteList?: string;
/**
@@ -255,10 +321,10 @@ export interface CherryEngineOptions {
*/
flowSessionContext?: boolean;
/**
- * 流式会话时,在最后位置增加一个类似光标的dom
- * - 'default':用cherry提供的默认样式
- * - '':不增加任何dom
- * - '': 自定义的dom
+ * 流式会话时,在最后位置增加一个类似光标的 dom
+ * - 'default':用 cherry 提供的默认样式
+ * - '':不增加任何 dom
+ * - '': 自定义的 dom
*/
flowSessionCursor?: string;
};
@@ -273,26 +339,50 @@ export interface CherryEngineOptions {
link?:
| false
| {
- /** 生成的标签追加target属性的默认值 空:在标签里不会追加target属性, _blank:在标签里追加target="_blank"属性 */
- target?: '_blank' | '';
- /** 生成的标签追加rel属性的默认值 空:在标签里不会追加rel属性, nofollow:在标签里追加rel="nofollow:在"属性*/
- rel?: '_blank' | 'nofollow' | '';
- /** 自定义标签的属性,默认为空 */
+ /**
+ * 生成的标签追加target属性的默认值
+ * - 支持标准HTML target属性值:`_blank`、`_parent`、`_self`、`_top`
+ * - 空字符串或不设置表示不追加target属性,此时会根据 `openNewPage` 配置决定是否添加 `target="_blank"`
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#target MDN - HTML anchor target}
+ */
+ target?: AnchorTargetValue | '';
+ /**
+ * 生成的标签追加rel属性的默认值
+ * - 支持标准HTML rel属性值,如:`nofollow`、`noopener`、`noreferrer` 等
+ * - 空字符串或不设置表示不追加rel属性
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/rel MDN - HTML rel attribute}
+ */
+ rel?: AnchorRelValue | '';
+ /** 是否在新窗口打开链接,当 target 未设置时生效 */
+ openNewPage?: boolean;
+ /** 自定义 标签的属性,默认为空 */
attrRender?: (text: string, href: string) => string;
selfClosing?: boolean;
};
autoLink?:
| false
| {
- /** 生成的标签追加target属性的默认值 空:在标签里不会追加target属性, _blank:在标签里追加target="_blank"属性 */
- target?: '_blank' | '';
- /** 生成的标签追加rel属性的默认值 空:在标签里不会追加rel属性, nofollow:在标签里追加rel="nofollow:在"属性*/
- rel?: '_blank' | 'nofollow' | '';
- /** 是否开启短链接 默认:true */
+ /**
+ * 生成的标签追加target属性的默认值
+ * - 支持标准HTML target属性值:`_blank`、`_parent`、`_self`、`_top`
+ * - 空字符串或不设置表示不追加target属性,此时会根据 `openNewPage` 配置决定是否添加 `target="_blank"`
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#target MDN - HTML anchor target}
+ */
+ target?: AnchorTargetValue | '';
+ /**
+ * 生成的标签追加rel属性的默认值
+ * - 支持标准HTML rel属性值,如:`nofollow`、`noopener`、`noreferrer` 等
+ * - 空字符串或不设置表示不追加rel属性
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/rel MDN - HTML rel attribute}
+ */
+ rel?: AnchorRelValue | '';
+ /** 是否在新窗口打开链接,当 target 未设置时生效 */
+ openNewPage?: boolean;
+ /** 是否开启短链接 默认:false */
enableShortLink?: boolean;
/** 短链接长度 默认:20 */
shortLinkLength?: number;
- /** 自定义标签的属性,默认为空 */
+ /** 自定义 标签的属性,默认为空 */
attrRender?: (text: string, href: string) => string;
};
image?:
@@ -305,13 +395,13 @@ export interface CherryEngineOptions {
| false
| {
listNested?: boolean; // 同级列表类型转换后变为子级
- indentSpace?: number; // 默认2个空格缩进
+ indentSpace?: number; // 默认 2 个空格缩进
};
table?:
| false
| {
enableChart?: boolean;
- selfClosing?: boolean; // 自动闭合,为true时,当输入第一行table内容时,cherry会自动按表格进行解析
+ selfClosing?: boolean; // 自动闭合,为 true 时,当输入第一行 table 内容时,cherry 会自动按表格进行解析
// chartRenderEngine: EChartsTableEngine,
// externals: ['echarts'],
};
@@ -320,45 +410,45 @@ export interface CherryEngineOptions {
| false
| {
/**
- * @deprecated 不再支持theme的配置,统一在`themeSettings.inlineCodeTheme`中配置
+ * @deprecated 不再支持 theme 的配置,统一在 `themeSettings.inlineCodeTheme` 中配置
*/
// theme: 'red',
/** 是否在行内代码为颜色值时展示颜色指示 */
showColor?: boolean;
- /** 是否自动闭合 为true时,会尝试补全最后一行的行内代码*/
+ /** 是否自动闭合 为 true 时,会尝试补全最后一行的行内代码*/
selfClosing?: boolean;
};
codeBlock?:
| false
| {
/**
- * @deprecated 不再支持theme的配置,统一在`themeSettings.codeBlockTheme`中配置
+ * @deprecated 不再支持 theme 的配置,统一在 `themeSettings.codeBlockTheme` 中配置
*/
// theme: 'dark', // 默认为深色主题
- wrap?: boolean; // 超出长度是否换行,false则显示滚动条
+ wrap?: boolean; // 超出长度是否换行,false 则显示滚动条
lineNumber?: boolean; // 默认显示行号
- copyCode?: boolean; // 是否显示“复制”按钮
- editCode?: boolean; // 是否显示“编辑”按钮
- changeLang?: boolean; // 是否显示“切换语言”按钮
- expandCode?: boolean; // 是否展开/收起代码块,当代码块行数大于10行时,会自动收起代码块
- selfClosing?: boolean; // 自动闭合,为true时,当md中有奇数个```时,会自动在md末尾追加一个```
+ copyCode?: boolean; // 是否显示"复制"按钮
+ editCode?: boolean; // 是否显示"编辑"按钮
+ changeLang?: boolean; // 是否显示"切换语言"按钮
+ expandCode?: boolean; // 是否展开/收起代码块,当代码块行数大于 10 行时,会自动收起代码块
+ selfClosing?: boolean; // 自动闭合,为 true 时,当 md 中有奇数个```时,会自动在 md 末尾追加一个```
customRenderer?: {
// 自定义语法渲染器
};
/** 自定义代码块的包裹渲染器 */
wrapperRender?: (language: string, code: string, innerHTML: string) => string;
mermaid?: {
- svg2img?: boolean; // 是否将mermaid生成的画图变成img格式
+ svg2img?: boolean; // 是否将 mermaid 生成的画图变成 img 格式
};
/**
- * indentedCodeBlock是缩进代码块是否启用的开关
+ * indentedCodeBlock 是缩进代码块是否启用的开关
*
- * 在6.X之前的版本中默认不支持该语法。
- * 因为cherry的开发团队认为该语法太丑了(容易误触)
+ * 在 6.X 之前的版本中默认不支持该语法。
+ * 因为 cherry 的开发团队认为该语法太丑了(容易误触)
* 开发团队希望用```代码块语法来彻底取代该语法
* 但在后续的沟通中,开发团队发现在某些场景下该语法有更好的显示效果
- * 因此开发团队在6.X版本中才引入了该语法
- * 已经引用6.x以下版本的业务如果想做到用户无感知升级,可以去掉该语法:
+ * 因此开发团队在 6.X 版本中才引入了该语法
+ * 已经引用 6.x 以下版本的业务如果想做到用户无感知升级,可以去掉该语法:
* indentedCodeBlock:false
*/
indentedCodeBlock?: boolean;
@@ -366,14 +456,14 @@ export interface CherryEngineOptions {
* 自定义按钮,出现在代码块右上角
**/
customBtns?: {
- html: '';
- onClick: (event: MouseEvent, code: string, language: string) => {};
+ html: string;
+ onClick: (event: MouseEvent, code: string, language: string) => void;
}[];
};
emoji?:
| false
| {
- useUnicode?: boolean; // 是否使用unicode进行渲染
+ useUnicode?: boolean; // 是否使用 unicode 进行渲染
};
fontEmphasis?:
| false
@@ -390,7 +480,7 @@ export interface CherryEngineOptions {
* __hello__ ====> hello
*/
allowWhitespace?: boolean;
- selfClosing?: boolean; // 自动闭合,为true时,当输入**XXX时,会自动在末尾追加**
+ selfClosing?: boolean; // 自动闭合,为 true 时,当输入**XXX 时,会自动在末尾追加**
};
strikethrough?:
| false
@@ -411,7 +501,7 @@ export interface CherryEngineOptions {
mathBlock?:
| false
| {
- engine?: 'katex' | 'MathJax'; // katex或MathJax
+ engine?: 'katex' | 'MathJax'; // katex 或 MathJax
src?: string;
css?: string;
plugins?: boolean; // 加载插件
@@ -420,7 +510,7 @@ export interface CherryEngineOptions {
inlineMath?:
| false
| {
- engine?: 'katex' | 'MathJax'; // katex或MathJax
+ engine?: 'katex' | 'MathJax'; // katex 或 MathJax
src?: string;
selfClosing?: boolean; // 自动闭合
};
@@ -491,7 +581,7 @@ export interface CherryEngineOptions {
refNumber?: {
appendClass?: string; // 添加到引用序号的类名
render?: (refNum: number, refTitle: string) => string; // 脚注标号的内容
- clickRefNumberCallback?: (event: MouseEvent, refNum: number, refTitle: string, content: string) => boolean; // 点击标号时回调,如果返回false,则不再执行cherry的默认动作
+ clickRefNumberCallback?: (event: MouseEvent, refNum: number, refTitle: string, content: string) => boolean; // 点击标号时回调,如果返回 false,则不再执行 cherry 的默认动作
};
/**
* 脚注列表的配置
@@ -515,8 +605,8 @@ export interface CherryEngineOptions {
};
};
/**
- * hover到脚注标号时,显示一个卡片
- * - false: 不响应hover事件
+ * hover 到脚注标号时,显示一个卡片
+ * - false: 不响应 hover 事件
*/
bubbleCard?:
| false
@@ -559,33 +649,33 @@ export type EditorMode =
| 'edit&preview';
export interface CherryEditorOptions {
- id?: string; // textarea 的id属性值
- name?: string; // textarea 的name属性值
- autoSave2Textarea?: boolean; // 是否自动将编辑区的内容回写到textarea里
+ id?: string; // textarea 的 id 属性值
+ name?: string; // textarea 的 name 属性值
+ autoSave2Textarea?: boolean; // 是否自动将编辑区的内容回写到 textarea 里
/**
- * @deprecated 不再支持theme的配置,废弃该功能,统一由`themeSettings.mainTheme`配置
+ * @deprecated 不再支持 theme 的配置,废弃该功能,统一由 `themeSettings.mainTheme` 配置
*/
theme?: string;
- /** 编辑器的高度,默认100%,如果挂载点存在内联设置的height则以内联样式为主 */
+ /** 编辑器的高度,默认 100%,如果挂载点存在内联设置的 height 则以内联样式为主 */
height?: string;
/** 编辑器初始化后的模式 */
defaultModel?: EditorMode;
- /** 粘贴时是否自动将html转成markdown */
+ /** 粘贴时是否自动将 html 转成 markdown */
convertWhenPaste?: boolean;
/** 快捷键风格,目前仅支持 sublime 和 vim */
keyMap?: 'sublime' | 'vim';
- /** 透传给codemirror的配置项 */
- codemirror?: object;
- /** 书写风格,normal 普通 | typewriter 打字机 | focus 专注,默认normal */
- writingStyle?: string;
+ /** 透传给 codemirror 的配置项 */
+ codemirror?: CodeMirror.EditorConfiguration;
+ /** 书写风格,normal 普通 | typewriter 打字机 | focus 专注,默认 normal */
+ writingStyle?: 'normal' | 'typewriter' | 'focus';
editor?: CodeMirror.Editor;
- /** 在初始化后是否保持网页的滚动,true:保持滚动;false:网页自动滚动到cherry初始化的位置 */
+ /** 在初始化后是否保持网页的滚动,true:保持滚动;false:网页自动滚动到 cherry 初始化的位置 */
keepDocumentScrollAfterInit?: boolean;
- /** 是否高亮全角符号 ·|¥|、|:|“|”|【|】|(|)|《|》 */
+ /** 是否高亮全角符号 ·|¥|、|:|"|"|【|】|(|)|《|》 */
showFullWidthMark?: boolean;
/** 是否显示联想框 */
showSuggestList?: boolean;
- /** URL的最大长度,-1表示不限制,超过该长度的URL会显示省略号 */
+ /** URL 的最大长度,-1 表示不限制,超过该长度的 URL 会显示省略号 */
maxUrlLength?: number;
/**
* 输入联想配置
@@ -613,25 +703,25 @@ export type CherryLifecycle = (text: string, html: string) => void;
export interface CherryPreviewerOptions {
dom?: HTMLDivElement | false;
- /** 预览区域的DOM className */
+ /** 预览区域的 DOM className */
className?: string;
/** 是否是移动端预览 */
- isMobilePreview?: boolean,
+ isMobilePreview?: boolean;
enablePreviewerBubble?: boolean;
floatWhenClosePreviewer?: boolean;
// 配置图片懒加载的逻辑
lazyLoadImg?: {
- // 加载图片时如果需要展示loaing图,则配置loading图的地址
+ // 加载图片时如果需要展示 loading 图,则配置 loading 图的地址
loadingImgPath?: string;
- // 同一时间最多有几个图片请求,最大同时加载6张图片
+ // 同一时间最多有几个图片请求,最大同时加载 6 张图片
maxNumPerTime?: 1 | 2 | 3 | 4 | 5 | 6;
- // 不进行懒加载处理的图片数量,如果为0,即所有图片都进行懒加载处理, 如果设置为-1,则所有图片都不进行懒加载处理
+ // 不进行懒加载处理的图片数量,如果为 0,即所有图片都进行懒加载处理, 如果设置为 -1,则所有图片都不进行懒加载处理
noLoadImgNum?: number;
// 首次自动加载几张图片(不论图片是否滚动到视野内),autoLoadImgNum = -1 表示会自动加载完所有图片
- autoLoadImgNum?: -1 | number;
- // 针对加载失败的图片 或 beforeLoadOneImgCallback 返回false 的图片,最多尝试加载几次,为了防止死循环,最多5次。以图片的src为纬度统计重试次数
+ autoLoadImgNum?: number;
+ // 针对加载失败的图片 或 beforeLoadOneImgCallback 返回 false 的图片,最多尝试加载几次,为了防止死循环,最多 5 次。以图片的 src 为纬度统计重试次数
maxTryTimesPerSrc?: 0 | 1 | 2 | 3 | 4 | 5;
- // 加载一张图片之前的回调函数,函数return false 会终止加载操作
+ // 加载一张图片之前的回调函数,函数 return false 会终止加载操作
beforeLoadOneImgCallback?: (img: HTMLImageElement) => void | boolean;
// 加载一张图片失败之后的回调函数
failLoadOneImgCallback?: (img: HTMLImageElement) => void;
@@ -761,7 +851,7 @@ export interface CherryChangeLocaleToolbarOption {
}
export interface CherryToolbarsOptions {
/**
- * @deprecated 不再支持theme的配置,统一在`themeSettings.toolbarTheme`中配置
+ * @deprecated 不再支持 theme 的配置,统一在 `themeSettings.toolbarTheme` 中配置
*/
theme?: 'light' | 'dark';
toolbar?:
@@ -777,43 +867,56 @@ export interface CherryToolbarsOptions)[] | false;
/** 是否展示悬浮目录 */
toc?:
| false
| {
- /** 要不要更新URL的hash */
+ /** 要不要更新 URL 的 hash */
updateLocationHash?: boolean;
/** pure: 精简模式/缩略模式,只有一排小点; full: 完整模式,会展示所有标题 */
defaultModel?: 'pure' | 'full';
/** 是否显示自增序号 */
showAutoNumber?: boolean;
- /** 悬浮目录的悬浮方式。当滚动条在cherry内部时,用absolute;当滚动条在cherry外部时,用fixed */
+ /** 悬浮目录的悬浮方式。当滚动条在 cherry 内部时,用 absolute;当滚动条在 cherry 外部时,用 fixed */
position?: 'absolute' | 'fixed';
/** 额外样式 */
cssText?: string;
};
- /** 不展示在编辑器中的工具栏,只使用工具栏的api和快捷键功能 */
- hiddenToolbar?: any[];
- /** 是否展示顶部工具栏 */
+ /**
+ * @deprecated 请使用 `registerHeadlessToolbars` 代替
+ * @description 不展示在编辑器中的工具栏,只使用工具栏的 api 和 快捷键功能 */
+ hiddenToolbar?: (CherryToolbarSeparator | CherryDefaultToolbar | keyof Partial)[];
+ /** 不展示在编辑器中的工具栏,只使用工具栏的 api 和 快捷键功能 */
+ registerHeadlessToolbars?: (CherryToolbarSeparator | CherryDefaultToolbar | keyof Partial)[];
+ /** 是否展示顶部工具栏和侧边栏 */
showToolbar?: boolean;
/** 侧边栏配置 */
- sidebar?: any[] | false;
+ sidebar?: (CherryToolbarSeparator | CherryDefaultToolbar | keyof Partial)[] | false;
/** 选中悬停菜单配置 */
- bubble?: any[] | false;
+ bubble?:
+ | (
+ | CherryToolbarSeparator
+ | CherryDefaultBubbleToolbar
+ | CherryDefaultToolbar
+ | keyof Partial
+ )[]
+ | false;
/** 新行悬停菜单配置 */
- float?: any[] | false;
+ float?:
+ | (CherryToolbarSeparator | CherryDefaultFloatToolbar | CherryDefaultToolbar | keyof Partial)[]
+ | false;
customMenu?: Record;
/**
* 自定义快捷键
* @deprecated 请使用`shortcutKeySettings`
*/
- shortcutKey?: Object | false;
+ shortcutKey?: object | false;
/**
* 自定义快捷键
*/
shortcutKeySettings?: {
- /** 是否替换已有的快捷键, true: 替换默认快捷键; false: 会追加到默认快捷键里,相同的shortcutKey会覆盖默认的 */
+ /** 是否替换已有的快捷键, true: 替换默认快捷键; false: 会追加到默认快捷键里,相同的 shortcutKey 会覆盖默认的 */
isReplace?: boolean;
shortcutKeyMap?: { [shortcutKey: string]: ShortcutKeyMapStruct };
};
@@ -855,37 +958,41 @@ export interface CherryFileUploadHandler {
export interface CherryFileUploadMultiHandler {
/**
* @param files 用户上传的文件对象数组
- * @param callback 回调函数,接收最终的文件url
+ * @param callback 回调函数,接收最终的文件信息数组
*/
(
files: File[],
/**
- * @param params.name 回填的alt信息
- * @param params.poster 封面图片地址(视频的场景下生效)
- * @param params.isBorder 是否有边框样式(图片场景下生效)
- * @param params.isShadow 是否有阴影样式(图片场景下生效)
- * @param params.isRadius 是否有圆角样式(图片场景下生效)
- * @param params.width 设置宽度,可以是像素、也可以是百分比(图片、视频场景下生效)
- * @param params.height 设置高度,可以是像素、也可以是百分比(图片、视频场景下生效)
+ * @param results 文件上传结果数组
+ * @param results[].url 文件url
+ * @param results[].params.name 回填的alt信息
+ * @param results[].params.poster 封面图片地址(视频的场景下生效)
+ * @param results[].params.isBorder 是否有边框样式(图片场景下生效)
+ * @param results[].params.isShadow 是否有阴影样式(图片场景下生效)
+ * @param results[].params.isRadius 是否有圆角样式(图片场景下生效)
+ * @param results[].params.width 设置宽度,可以是像素、也可以是百分比(图片、视频场景下生效)
+ * @param results[].params.height 设置高度,可以是像素、也可以是百分比(图片、视频场景下生效)
*/
callback: (
- url: string,
- params?: {
- name?: string;
- poster?: string;
- isBorder?: boolean;
- isShadow?: boolean;
- isRadius?: boolean;
- width?: string;
- height?: string;
- },
+ results: Array<{
+ url: string;
+ params?: {
+ name?: string;
+ poster?: string;
+ isBorder?: boolean;
+ isShadow?: boolean;
+ isRadius?: boolean;
+ width?: string;
+ height?: string;
+ };
+ }>,
) => void,
): void;
}
type ShortcutKeyMapStruct = {
/**
- * 原始hook
+ * 原始 hook
*/
hookName: string;
/**
@@ -895,7 +1002,7 @@ type ShortcutKeyMapStruct = {
/**
* 其他扩展字段
* 如果存在则会赋值给 data-[fieldName]=value 存储记录
- * @summary 切记不要使用驼峰,因为dataset 会全部转成全小写,除非你在取值的时候能记住,否则永远不要这么做
+ * @summary 切记不要使用驼峰,因为 dataset 会全部转成全小写,除非你在取值的时候能记住,否则永远不要这么做
*/
[x: string]: string | number;
};
diff --git a/packages/cherry-markdown/types/previewer.d.ts b/packages/cherry-markdown/types/previewer.d.ts
index 272b5f68a..ed8c048b6 100644
--- a/packages/cherry-markdown/types/previewer.d.ts
+++ b/packages/cherry-markdown/types/previewer.d.ts
@@ -31,7 +31,7 @@ export interface PreviewerOptions {
$cherry?: Cherry;
// 配置图片懒加载的逻辑
lazyLoadImg?: {
- // 加载图片时如果需要展示loaing图,则配置loading图的地址
+ // 加载图片时如果需要展示 loading 图,则配置 loading 图的地址
loadingImgPath?: string;
// 同一时间最多有几个图片请求,最大同时加载6张图片
maxNumPerTime?: 1 | 2 | 3 | 4 | 5 | 6,