From 159b858cfaaa4ae2fcfc9d72ac320af0465fa657 Mon Sep 17 00:00:00 2001 From: Vanessa Date: Thu, 20 May 2021 21:22:45 +0800 Subject: [PATCH] :sparkles: fix https://github.com/Vanessa219/vditor/issues/1011 --- CHANGELOG.md | 7 +- README.md | 156 +++++++---------------------- README_en_US.md | 164 +++++++------------------------ demo/index.js | 2 +- src/index.ts | 7 +- src/ts/export/index.ts | 7 +- src/ts/markdown/previewRender.ts | 15 ++- src/ts/preview/image.ts | 2 +- src/ts/preview/index.ts | 3 +- src/ts/util/editorCommonEvent.ts | 2 +- 10 files changed, 101 insertions(+), 264 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c07f7fed9..dcade0b94 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -98,9 +98,14 @@ ### v3.8.5 / 2021-06-xx +* [1011](https://github.com/Vanessa219/vditor/issues/1011) 支持导出 JSON `引入特性` * [1010](https://github.com/Vanessa219/vditor/issues/1010) 多语言分离 `改进功能` * [1008](https://github.com/Vanessa219/vditor/pull/1008) 自定义多语言 `引入特性` - +* 文档修改 + * codeRender 方法中移除 lang 参数 + * 为 options 添加 i18n 语言自定义参数 + * 添加 exportJSON 方法 + ### v3.8.4 / 2021-05-13 * [1000](https://github.com/Vanessa219/vditor/issues/1000) 升级 hljs 并添加更多的语言支持 `改进功能` diff --git a/README.md b/README.md index c7a7d3f79..972459e46 100644 --- a/README.md +++ b/README.md @@ -11,9 +11,9 @@


- - - + + +

@@ -200,8 +200,7 @@ Markdown 输出的 HTML 所展现的外观。内置 light,dark,wechat 3 套 | minHeight | 编辑区域最小高度 | - | | width | 编辑器总宽度,支持 % | 'auto' | | placeholder | 输入区域为空时的提示 | '' | -| lang | 多语言:en_US, ja_JP, ko_KR, ru_RU, zh_CN | 'zh_CN' | -| i18n | 自定义语言包实现国际化(当 `lang === ""`时, 生效), 类型定义参考[ITips](#options.i18n) | [i18n['zh_CN']](https://github.com/Vanessa219/vditor/blob/master/src/ts/i18n/index.ts#L318) | +| lang | 多语言:en_US, ja_JP, ko_KR, ru_RU, zh_CN, zh_TW | 'zh_CN' | | input(value: string) | 输入后触发 | - | | focus(value: string) | 聚焦后触发 | - | | blur(value: string) | 失焦后触发 | - | @@ -379,35 +378,35 @@ interface IHintExtend { * 文件上传的数据结构如下。后端返回的数据结构不一致时,可使用 `format` 进行转换。 ```js -// POST data -xhr.send(formData); // formData = FormData.append("file[]", File) -// return data -{ - "msg": "", - "code": 0, - "data": { - "errFiles": ['filename', 'filename2'], - "succMap": { - "filename3": "filepath3", - "filename3": "filepath3" - } - } +// POST data +xhr.send(formData); // formData = FormData.append("file[]", File) +// return data +{ + "msg": "", + "code": 0, + "data": { + "errFiles": ['filename', 'filename2'], + "succMap": { + "filename3": "filepath3", + "filename3": "filepath3" + } + } } ``` * 为了防止站外图片失效, `linkToImgUrl` 可将剪贴板中的站外图片地址传到服务器端进行保存处理,其数据结构如下: ```js -// POST data -xhr.send(JSON.stringify({url: src})); // src 为站外图片地址 -// return data -{ - msg: '', - code: 0, - data : { - originalURL: '', - url: '' - } +// POST data +xhr.send(JSON.stringify({url: src})); // src 为站外图片地址 +// return data +{ + msg: '', + code: 0, + data : { + originalURL: '', + url: '' + } } ``` @@ -483,90 +482,6 @@ if (xhr.status === 200) { | enable | 初始化是否展现大纲 | false | | position | 大纲位置:'left', 'right' | 'left' | -#### options.i18n - -```ts -interface ITips { - alignCenter: string - alignLeft: string - alignRight: string - alternateText: string - bold: string - both: string - check: string - close: string - code: string - "code-theme": string - column: string - comment: string - confirm: string - "content-theme": string - copied: string - copy: string - "delete-column": string - "delete-row": string - devtools: string - down: string - downloadTip: string - edit: string - "edit-mode": string - emoji: string - export: string - fileTypeError: string - footnoteRef: string - fullscreen: string - generate: string - headings: string - help: string - imageURL: string - indent: string - info: string - "inline-code": string - "insert-after": string - "insert-before": string - insertColumnLeft: string - insertColumnRight: string - insertRowAbove: string - insertRowBelow: string - instantRendering: string - italic: string - language: string - line: string - link: string - linkRef: string - list: string - more: string - nameEmpty: string - "ordered-list": string - outdent: string - outline: string - over: string - performanceTip: string - preview: string - quote: string - record: string - "record-tip": string - recording: string - redo: string - remove: string - row: string - spin: string - splitView: string - strike: string - table: string - textIsNotEmpty: string - title: string - tooltipText: string - undo: string - up: string - update: string - upload: string - uploadError: string - uploading: string - wysiwyg: string -} -``` - #### methods | | 说明 | @@ -599,7 +514,6 @@ interface ITips { | hlCommentIds(ids: string[]) | 高亮评论 | | unHlCommentIds(ids: string[]) | 取消评论高亮 | | removeCommentIds(removeIds: string[]) | 删除评论 | -| exportJSON(value: string) | 获取markdown导出为JSON格式的语法树 | #### static methods @@ -610,7 +524,7 @@ Vditor.mermaidRender(document) ``` ```js -import VditorPreview from 'vditor/dist/method.min' +import VditorPreview from 'vditor/dist/method.min' VditorPreview.mermaidRender(document) ``` @@ -622,14 +536,12 @@ markdown: string, // 需要渲染的 markdown 原文 options?: IPreviewOptions { mode: "dark" | "light"; anchor?: number; // 为标题添加锚点 0:不渲染;1:渲染于标题前;2:渲染于标题后,默认 0 - customEmoji?: { [key: string]: string }; // 自定义 emoji,默认为 {} - lang?: (keyof II18nLang); // 语言,默认为 'zh_CN' - i18n?: ITips; // 自定义国际化, 默认为 'i18n['zh_CN']' - emojiPath?: string; // 表情图片路径 - hljs?: IHljs; // 参见 options.preview.hljs + customEmoji?: { [key: string]: string }; // 自定义 emoji,默认为 {} + lang?: (keyof II18nLang); // 语言,默认为 'zh_CN' + emojiPath?: string; // 表情图片路径 + hljs?: IHljs; // 参见 options.preview.hljs speech?: { // 对选中后的内容进行阅读 enable?: boolean, - lang?: string // 语言类型, 默认等于 lang }; math?: IMath; // 数学公式渲染配置 cdn?: string; // 自建 CDN 地址 @@ -659,15 +571,13 @@ options?: IPreviewOptions { | highlightRender(hljsOption?: IHljs, element?: HTMLElement \| Document, cdn = options.cdn) | 为 element 中的代码块进行高亮渲染 | | mediaRender(element: HTMLElement) | 为[特定链接](https://ld246.com/article/1589813914768)分别渲染为视频、音频、嵌入的 iframe | | mathRender(element: HTMLElement, options?: {cdn?: string, math?: IMath}) | 对数学公式进行渲染 | -| speechRender(element: HTMLElement, speechLang?: string, lang?: (keyof II18n)) | 对选中的文字进行阅读 | +| speechRender(element: HTMLElement, lang?: (keyof II18nLang)) | 对选中的文字进行阅读 | | graphvizRender(element: HTMLElement, cdn?: string) | 对 graphviz 进行渲染 | | outlineRender(contentElement: HTMLElement, targetElement: Element) | 对大纲进行渲染 | | lazyLoadImageRender(element: (HTMLElement \| Document) = document) | 对启用懒加载的图片进行渲染 | | setCodeTheme(codeTheme: string, cdn = options.cdn) | 设置代码主题,codeTheme 参见 options.preview.hljs.style | | setContentTheme(contentTheme: string, path: string) | 设置内容主题,contentTheme 参见 options.preview.theme.list | -> Tip: `speechRender(element, speechLang, lang)` 函数当 `!!lang === true`时, `speechLang`的值不生效 - ## 🏗 开发文档 ### 原理相关 diff --git a/README_en_US.md b/README_en_US.md index 80ce6a50b..506905bf4 100644 --- a/README_en_US.md +++ b/README_en_US.md @@ -11,9 +11,9 @@ Easy-to-use Markdown editor, born to adapt to different application scenarios


- - - + + +

@@ -96,16 +96,16 @@ The traditional *Split View* mode is suitable for Markdown editing on a large sc * All GFM syntax: Tables, Task list items, Strikethrough, Autolinks, XSS filtering * Common Markdown extended syntax: Footnotes, ToC, Custom Heading ID * Chart syntax - * Flow chart, sequence diagram, Gantt chart, supported by Mermaid - * Graphviz - * Line chart, pie chart, brain chart, etc., supported by ECharts + * Flow chart, sequence diagram, Gantt chart, supported by Mermaid + * Graphviz + * Line chart, pie chart, brain chart, etc., supported by ECharts * Stave: supported by abc.js * Math formulas: Math formula blocks, row-level math formulas, supported by MathJax and KaTeX * YAML Front Matter * Chinese context optimization - * Insert space between Chinese and Western - * Terminology spelling correction - * Chinese followed by English comma period and other punctuation are replaced with Chinese corresponding punctuation + * Insert space between Chinese and Western + * Terminology spelling correction + * Chinese followed by English comma period and other punctuation are replaced with Chinese corresponding punctuation Most of the above features can be enabled or disabled through the switch configuration, developers can choose to match according to their own application scenarios. @@ -177,8 +177,7 @@ Can be filled with element `id` or element itself` HTMLElement` | minHeight | Editing area minimum height | - | | width | Total editor width, supports % | 'auto' | | placeholder | Tips when the input area is empty | '' | -| lang | i18n: en_US, ja_JP, ko_KR, ru_RU, zh_CN | 'zh_CN' | -| i18n | custom language package(Effective when `lang === ""`), The type definition [ITips](#options.i18n) | [i18n['zh_CN']](https://github.com/Vanessa219/vditor/blob/master/src/ts/i18n/index.ts#L318) | +| lang | i18n: en_US, ja_JP, ko_KR, ru_RU, zh_CN, zh_TW | 'zh_CN' | | input | Trigger after input (value: string) | - | | focus | Trigger after focusing (value: string) | - | | blur | Trigger after out of focus (value: string) | - | @@ -355,35 +354,35 @@ interface IHintExtend { * The data structure of the file upload is as follows. When the data structure returned by the backend is inconsistent, you can use `format` for conversion. ```js -// POST data -xhr.send(formData); // formData = FormData.append("file[]", File) -// return data -{ - "msg": "", - "code": 0, - "data": { - "errFiles": ['filename', 'filename2'], - "succMap": { - "filename3": "filepath3", - "filename3": "filepath3" - } - } +// POST data +xhr.send(formData); // formData = FormData.append("file[]", File) +// return data +{ + "msg": "", + "code": 0, + "data": { + "errFiles": ['filename', 'filename2'], + "succMap": { + "filename3": "filepath3", + "filename3": "filepath3" + } + } } ``` * In order to prevent the off-site pictures from being invalid, `linkToImgUrl` can transfer the off-site picture addresses in the clipboard to the server for saving and processing. The data structure is as follows: ```js -// POST data +// POST data xhr.send(JSON.stringify({url: src})); // src is the address of the image outside the station -// return data -{ - msg: '', - code: 0, - data : { - originalURL: '', - url: '' - } +// return data +{ + msg: '', + code: 0, + data : { + originalURL: '', + url: '' + } } ``` @@ -437,90 +436,6 @@ xhr.send(JSON.stringify({url: src})); // src is the address of the image outside | enable | Initialize whether to show outline | false | | position | Outline location: 'left', 'right' | 'left' | -#### options.i18n - -```ts -interface ITips { - alignCenter: string - alignLeft: string - alignRight: string - alternateText: string - bold: string - both: string - check: string - close: string - code: string - "code-theme": string - column: string - comment: string - confirm: string - "content-theme": string - copied: string - copy: string - "delete-column": string - "delete-row": string - devtools: string - down: string - downloadTip: string - edit: string - "edit-mode": string - emoji: string - export: string - fileTypeError: string - footnoteRef: string - fullscreen: string - generate: string - headings: string - help: string - imageURL: string - indent: string - info: string - "inline-code": string - "insert-after": string - "insert-before": string - insertColumnLeft: string - insertColumnRight: string - insertRowAbove: string - insertRowBelow: string - instantRendering: string - italic: string - language: string - line: string - link: string - linkRef: string - list: string - more: string - nameEmpty: string - "ordered-list": string - outdent: string - outline: string - over: string - performanceTip: string - preview: string - quote: string - record: string - "record-tip": string - recording: string - redo: string - remove: string - row: string - spin: string - splitView: string - strike: string - table: string - textIsNotEmpty: string - title: string - tooltipText: string - undo: string - up: string - update: string - upload: string - uploadError: string - uploading: string - wysiwyg: string -} -``` - #### methods | | Explanation | @@ -553,7 +468,6 @@ interface ITips { | hlCommentIds(ids: string[]) | Highlight comment by Ids | | unHlCommentIds(ids: string[]) | Cancel highlight comment by Ids | | removeCommentIds(removeIds: string[]) | Remove comment by Ids | -| exportJSON(value: string) | export markdown as Syntax Tree | #### static methods @@ -564,7 +478,7 @@ Vditor.mermaidRender(document) ``` ```js -import VditorPreview from 'vditor/dist/method.min' +import VditorPreview from 'vditor/dist/method.min' VditorPreview.mermaidRender(document) ``` @@ -577,13 +491,11 @@ options?: IPreviewOptions { mode: "dark" | "light"; anchor?: number; // 0: no render, 1: render left, 2: render right customEmoji?: { [key: string]: string }; // Custom emoji, default is {} - lang?: (keyof II18nLang); // Language, default is 'zh_CN' - i18n?: ITips; // custom language package, default is i18n['zh_CN'] - emojiPath?: string; // Emoji picture path - hljs?: IHljs; // Refer to options.preview.hljs + lang?: (keyof II18nLang); // Language, default is 'zh_CN' + emojiPath?: string; // Emoji picture path + hljs?: IHljs; // Refer to options.preview.hljs speech?: { // Read the selected content enable?: boolean, - lang?: string // speech language, default is 'zh_CN' }; math?: IMath; // Math formula rendering configuration transform?(html: string): string; // Callback method before rendering @@ -612,15 +524,13 @@ options?: IPreviewOptions { | highlightRender(hljsOption?: IHljs, element?: HTMLElement \| Document, cdn = options.cdn) | Highlight the code block in element | | mediaRender(element: HTMLElement) | Rendering as [specific link](https://ld246.com/article/1589813914768) as video, audio, embedded iframe | | mathRender(element: HTMLElement, options?: {cdn?: string, math?: IMath}) | Render math formulas | -| speechRender(element: HTMLElement, speechLang?: string, lang?: (keyof II18n)) | Read the selected text | +| speechRender(element: HTMLElement, lang?: (keyof II18nLang)) | Read the selected text | | graphvizRender(element: HTMLElement, cdn?: string) | Render graphviz | | lazyLoadImageRender(element: (HTMLElement \| Document) = document) | Render lazy load image | | setCodeTheme (codeTheme: string, cdn = options.cdn) | update code theme | | setContentTheme (contentTheme: string, path: string) | update content theme | | mindmapRender (element: (HTMLElement \| Document) = document, cdn = options.cdn, theme = options.theme) | Render mind map | -> Tip: Function `speechRender(element, speechLang, lang)`, When `!!lang === true`, `speechLang` is not effective! - ## 🏗 Developer Guide ### Principle related diff --git a/demo/index.js b/demo/index.js index e5cd16f43..284892e68 100644 --- a/demo/index.js +++ b/demo/index.js @@ -52,7 +52,7 @@ if (window.innerWidth < 768) { window.vditor = new Vditor('vditor', { // _lutePath: `http://192.168.0.107:9090/lute.min.js?${new Date().getTime()}`, _lutePath: 'src/js/lute/lute.min.js', - cdn: "", + cdn: "http://localhost:9000", toolbar, mode: 'wysiwyg', height: window.innerHeight + 100, diff --git a/src/index.ts b/src/index.ts index 4e4b60589..b34dadc59 100644 --- a/src/index.ts +++ b/src/index.ts @@ -208,7 +208,7 @@ class Vditor extends VditorMethod { return this.vditor.lute.HTML2Md(value); } - /** markdown转JSON输出 */ + /** markdown 转 JSON 输出 */ public exportJSON(value: string) { return this.vditor.lute.RenderJSON(value); } @@ -493,10 +493,7 @@ class Vditor extends VditorMethod { } if (mergedOptions.icon) { // 防止初始化 2 个编辑器时加载 2 次 - addScriptSync( - `${mergedOptions.cdn}/dist/js/icons/${mergedOptions.icon}.js`, - "vditorIconScript", - ); + addScriptSync(`${mergedOptions.cdn}/dist/js/icons/${mergedOptions.icon}.js`, "vditorIconScript"); } }); } diff --git a/src/ts/export/index.ts b/src/ts/export/index.ts index cd5a3863e..b71861b3c 100644 --- a/src/ts/export/index.ts +++ b/src/ts/export/index.ts @@ -55,12 +55,13 @@ window.addEventListener("message", (e) => { export const exportHTML = (vditor: IVditor) => { const content = getHTML(vditor); const html = ` +
${content}
`; + Vditor.speechRender(previewElement); + +`; download(vditor, html, content.substr(0, 10) + ".html"); }; diff --git a/src/ts/markdown/previewRender.ts b/src/ts/markdown/previewRender.ts index bff0dc2e5..5d94dfb8f 100644 --- a/src/ts/markdown/previewRender.ts +++ b/src/ts/markdown/previewRender.ts @@ -1,6 +1,6 @@ import {Constants} from "../constants"; import {setContentTheme} from "../ui/setContentTheme"; -import {addScript} from "../util/addScript"; +import {addScript, addScriptSync} from "../util/addScript"; import {hasClosestByClassName, hasClosestByMatchTag} from "../util/hasClosest"; import {merge} from "../util/merge"; import {abcRender} from "./abcRender"; @@ -83,6 +83,19 @@ export const previewRender = async (previewElement: HTMLDivElement, markdown: st } previewElement.innerHTML = html; previewElement.classList.add("vditor-reset"); + + if (!mergedOptions.i18n) { + if (!["en_US", "ja_JP", "ko_KR", "ru_RU", "zh_CN", "zh_TW"].includes(mergedOptions.lang)) { + throw new Error( + "options.lang error, see https://ld246.com/article/1549638745630#options", + ); + } else { + addScriptSync(`${mergedOptions.cdn}/dist/js/i18n/${mergedOptions.lang}.js`, "vditorI18nScript"); + } + } else { + window.VditorI18n = mergedOptions.i18n; + } + setContentTheme(mergedOptions.theme.current, mergedOptions.theme.path); if (mergedOptions.anchor === 1) { previewElement.classList.add("vditor-reset--anchor"); diff --git a/src/ts/preview/image.ts b/src/ts/preview/image.ts index 415b8f076..e19644ccc 100644 --- a/src/ts/preview/image.ts +++ b/src/ts/preview/image.ts @@ -1,4 +1,4 @@ -export const previewImage = (oldImgElement: HTMLImageElement, options: IOptions , lang: keyof II18n = "zh_CN", theme = "classic") => { +export const previewImage = (oldImgElement: HTMLImageElement, lang: keyof II18n = "zh_CN", theme = "classic") => { const oldImgRect = oldImgElement.getBoundingClientRect(); const height = 36; document.body.insertAdjacentHTML("beforeend", `
diff --git a/src/ts/preview/index.ts b/src/ts/preview/index.ts index a1d127f50..5a97bbde7 100644 --- a/src/ts/preview/index.ts +++ b/src/ts/preview/index.ts @@ -53,8 +53,7 @@ export class Preview { return; } if (event.target.tagName === "IMG") { - previewImage(event.target as HTMLImageElement, vditor.options, vditor.options.lang, - vditor.options.theme); + previewImage(event.target as HTMLImageElement, vditor.options.lang, vditor.options.theme); } }); diff --git a/src/ts/util/editorCommonEvent.ts b/src/ts/util/editorCommonEvent.ts index 0184765c4..1f390b531 100644 --- a/src/ts/util/editorCommonEvent.ts +++ b/src/ts/util/editorCommonEvent.ts @@ -29,7 +29,7 @@ export const focusEvent = (vditor: IVditor, editorElement: HTMLElement) => { export const dblclickEvent = (vditor: IVditor, editorElement: HTMLElement) => { editorElement.addEventListener("dblclick", (event: MouseEvent & { target: HTMLElement }) => { if (event.target.tagName === "IMG") { - previewImage(event.target as HTMLImageElement, vditor.options, vditor.options.lang, vditor.options.theme); + previewImage(event.target as HTMLImageElement, vditor.options.lang, vditor.options.theme); } }); };