Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge v3.4.0 #8

Merged
merged 18 commits into from Jul 30, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Expand Up @@ -80,6 +80,14 @@
### v3.4.0 / 2020-07-xx

* [636](https://github.com/Vanessa219/vditor/issues/636) SV 模式 Setext 标题问题 `修复缺陷`
* [647](https://github.com/Vanessa219/vditor/pull/647) 即时渲染模式输入 ``` 后会弹出 hint,此时执行 undo 后, hint 不消失 `改进功能`
* [643](https://github.com/Vanessa219/vditor/issues/643) 支持 YAML Front Matter `引入特性`
* [648](https://github.com/Vanessa219/vditor/pull/648) added ja_JP lang `改进功能`
* [644](https://github.com/Vanessa219/vditor/pull/644) 粘贴多行代码时,避免代码段与当前行内容混淆在一起 `改进功能`
* [639](https://github.com/Vanessa219/vditor/issues/639) 列表嵌套代码块后输入中文的问题 `修复缺陷`
* [641](https://github.com/Vanessa219/vditor/issues/641) 清空 undo 栈后,第一次编辑操作无法进行记录 `修复缺陷`
* [640](https://github.com/Vanessa219/vditor/issues/640) options.icon 无法进行切换 `改进功能`
* [638](https://github.com/Vanessa219/vditor/pull/638) ir模式下图片编辑时很难触发md图片代码显示 `改进功能`

### v3.3.12 / 2020-07-28

Expand Down
3 changes: 2 additions & 1 deletion README.md
Expand Up @@ -103,6 +103,7 @@ Vditor 在这些方面做了努力,希望能为现代化的通用 Markdown 编
* 折线图、饼图、脑图等,通过 ECharts 支持
* 五线谱:通过 abc.js 支持
* 数学公式:数学公式块、行级数学公式,通过 MathJax 和 KaTeX 支持
* YAML Front Matter
* 中文语境优化
* 中西文之间插入空格
* 术语拼写修正
Expand Down Expand Up @@ -199,7 +200,7 @@ Markdown 输出的 HTML 所展现的外观。内置 light,dark,wechat 3 套
| minHeight | 编辑区域最小高度 | - |
| width | 编辑器总宽度,支持 % | 'auto' |
| placeholder | 输入区域为空时的提示 | '' |
| lang | 多语言:en_US, ko_KR, zh_CN | 'zh_CN' |
| lang | 多语言:en_US, ja_JP, ko_KR, zh_CN | 'zh_CN' |
| input(value: string, previewElement?: HTMLElement): void | 输入后触发 | - |
| focus(value: string): void | 聚焦后触发 | - |
| blur(value: string): void | 失焦后触发 | - |
Expand Down
3 changes: 2 additions & 1 deletion README_en_US.md
Expand Up @@ -101,6 +101,7 @@ The traditional *Split View* mode is suitable for Markdown editing on a large sc
* 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
Expand Down Expand Up @@ -176,7 +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, ko_KR, zh_CN | 'zh_CN' |
| lang | i18n: en_US, ja_JP, ko_KR, zh_CN | 'zh_CN' |
| input | Trigger after input (value: string, previewElement?: HTMLElement): void | - |
| focus | Trigger after focusing (value: string): void | - |
| blur | Trigger after out of focus (value: string): void | - |
Expand Down
2 changes: 1 addition & 1 deletion demo/index.js
Expand Up @@ -53,7 +53,7 @@ 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',
toolbar,
mode: 'sv',
mode: 'wysiwyg',
height: window.innerHeight + 100,
outline: true,
debugger: true,
Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
@@ -1,6 +1,6 @@
{
"name": "vditor",
"version": "3.3.12",
"version": "3.4.0",
"description": "♏ 易于使用的 Markdown 编辑器,为适配不同的应用场景而生",
"author": "Vanessa <v@b3log.org> (http://vanessa.b3log.org)",
"homepage": "https://vditor.b3log.org",
Expand Down
9 changes: 9 additions & 0 deletions src/assets/scss/_ir.scss
Expand Up @@ -8,6 +8,8 @@
&__node {
&[data-type="code-block"]:before,
&[data-type="code-block"]:after,
&[data-type="yaml-front-matter"]:before,
&[data-type="yaml-front-matter"]:after,
&[data-type="math-block"]:before,
&[data-type="math-block"]:after {
content: ' ';
Expand Down Expand Up @@ -104,6 +106,11 @@
content: '```';
}

&[data-type="yaml-front-matter"]:before,
&[data-type="yaml-front-matter"]:after {
content: '---';
}

&[data-type="math-block"]:before,
&[data-type="math-block"]:after {
content: '$$';
Expand All @@ -112,6 +119,8 @@

span[data-type="code-block-open-marker"],
span[data-type="code-block-close-marker"],
span[data-type="yaml-front-matter-open-marker"],
span[data-type="yaml-front-matter-close-marker"],
span[data-type="math-block-open-marker"],
span[data-type="math-block-close-marker"] {
display: none;
Expand Down
8 changes: 8 additions & 0 deletions src/assets/scss/_wysiwyg.scss
Expand Up @@ -127,6 +127,14 @@
content: "</>";
}

div.vditor-wysiwyg__block[data-type="yaml-front-matter"]:before {
content: "F";
}

div.vditor-wysiwyg__block[data-type="math-block"]:before {
content: "$$";
}

.vditor-toc:before {
content: "ToC";
}
Expand Down
15 changes: 8 additions & 7 deletions src/index.ts
Expand Up @@ -66,7 +66,7 @@ class Vditor extends VditorMethod {
const getOptions = new Options(options);
const mergedOptions = getOptions.merge();

if (!["en_US", "ko_KR", "zh_CN"].includes(mergedOptions.lang)) {
if (!["en_US", "ja_JP", "ko_KR", "zh_CN"].includes(mergedOptions.lang)) {
throw new Error("options.lang error, see https://hacpai.com/article/1549638745630#options");
}

Expand Down Expand Up @@ -296,19 +296,16 @@ class Vditor extends VditorMethod {

/** 设置编辑器内容 */
public setValue(markdown: string, clearStack = false) {
if (clearStack) {
this.clearStack();
}
if (this.vditor.currentMode === "sv") {
this.vditor.sv.element.innerHTML = this.vditor.lute.SpinVditorSVDOM(markdown);
processSVAfterRender(this.vditor, {
enableAddUndoStack: true,
enableAddUndoStack: clearStack,
enableHint: false,
enableInput: false,
});
} else if (this.vditor.currentMode === "wysiwyg") {
renderDomByMd(this.vditor, markdown, {
enableAddUndoStack: true,
enableAddUndoStack: clearStack,
enableHint: false,
enableInput: false,
});
Expand All @@ -319,7 +316,7 @@ class Vditor extends VditorMethod {
processCodeRender(item, this.vditor);
});
processAfterRender(this.vditor, {
enableAddUndoStack: true,
enableAddUndoStack: clearStack,
enableHint: false,
enableInput: false,
});
Expand All @@ -334,11 +331,15 @@ class Vditor extends VditorMethod {
}
this.clearCache();
}
if (clearStack) {
this.clearStack();
}
}

/** 清空 undo & redo 栈 */
public clearStack() {
this.vditor.undo.clearStack(this.vditor);
this.vditor.undo.addToUndoStack(this.vditor);
}

/** 销毁编辑器 */
Expand Down
12 changes: 6 additions & 6 deletions src/js/lute/lute.min.js

Large diffs are not rendered by default.

73 changes: 73 additions & 0 deletions src/ts/i18n/index.ts
Expand Up @@ -72,6 +72,79 @@ export const i18n: II18n = {
"uploading": "uploading...",
"wysiwyg": "WYSIWYG",
},
ja_JP: {
"alignCenter": "中央",
"alignLeft": "左側",
"alignRight": "右側",
"alternateText": "イメージタグ",
"bold": "太く",
"both": "エディター & プレビュー",
"check": "チェックリスト",
"code": "コードブロック挿入",
"code-theme": "コードブロックテーマ",
"column": "行列",
"confirm": "確認",
"content-theme": "コンテンツテーマ",
"copied": "コピー完了",
"copy": "コピー",
"delete-column": "列 消去",
"delete-row": "行 消去",
"devtools": "開発ツール",
"down": "ダウンロード",
"downloadTip": "ブラウザがダウンロード機能をサポートしていません。",
"edit": "修正",
"edit-mode": "編集モード",
"emoji": "絵文字",
"export": "書き出し",
"fileTypeError": "サポートしていません。",
"footnoteRef": "脚注参照",
"fullscreen": "全体画面",
"generate": "作成する",
"headings": "タイトル大きさ",
"help": "ヘルプ",
"imageURL": "イメージ URL",
"indent": "字下げ",
"info": "情報",
"inline-code": "インラインコード",
"insert-after": "ブロックの後ろに入力",
"insert-before": "ブロックの前に入力",
"insert-column": "列 挿入",
"insert-row": "行 挿入",
"instantRendering": "インスタントレンダリング",
"italic": "斜体",
"language": "言語",
"line": "段落分割",
"link": "リンク",
"linkRef": "リンク参照",
"list": "リスト",
"more": "詳しく見る",
"nameEmpty": "名前が入力されていません。",
"ordered-list": "順序のあるリスト",
"outdent": "ぶら下げインデント",
"outline": "概要",
"over": "オーバー",
"performanceTip": "リアルタイムプレビューには、${x}msが必要でエディター/プレビューボタンをクリックして閉じる事が出来ます。",
"preview": "プレビュー",
"quote": "引用段落",
"record": "録音開始/録音終了",
"record-tip": "録音がサポートされていません。",
"recording": "録音中...",
"redo": "戻る",
"remove": "消去",
"row": "列",
"splitView": "マークダウン",
"strike": "取り消し線",
"table": "表 挿入",
"textIsNotEmpty": "テキスト(no empty)",
"tooltipText": "ツールチップ",
"undo": "取り消す",
"up": "戻る",
"update": "アップデート",
"upload": "イメージをダウンロードする",
"uploadError": "アップロード失敗",
"uploading": "アップロード中",
"wysiwyg": "ウィジウィグ",
},
ko_KR: {
"alignCenter": "가운데",
"alignLeft": "왼쪽",
Expand Down
10 changes: 10 additions & 0 deletions src/ts/ir/index.ts
Expand Up @@ -130,6 +130,16 @@ class IR {
scrollCenter(vditor);
}

// 点击图片光标选中图片地址
if (event.target.tagName === "IMG") {
const linkElement =
event.target.parentElement.querySelector<HTMLSpanElement>(".vditor-ir__marker--link");
if (linkElement) {
range.selectNode(linkElement);
setSelectionFocus(range);
}
}

expandMarker(range, vditor);
highlightToolbarIR(vditor);
});
Expand Down
18 changes: 9 additions & 9 deletions src/ts/ir/input.ts
Expand Up @@ -14,7 +14,7 @@ export const input = (vditor: IVditor, range: Range, ignoreSpace = false) => {
let blockElement = hasClosestBlock(range.startContainer);
// 前后可以输入空格
if (blockElement && !ignoreSpace) {
if (isHrMD(blockElement.innerHTML) ||
if ((isHrMD(blockElement.innerHTML) && blockElement.previousElementSibling) ||
isHeadingMD(blockElement.innerHTML)) {
return;
}
Expand Down Expand Up @@ -78,7 +78,7 @@ export const input = (vditor: IVditor, range: Range, ignoreSpace = false) => {

if (!blockElement.querySelector("wbr")) {
const previewRenderElement = hasClosestByClassName(range.startContainer, "vditor-ir__preview");
if (previewRenderElement) {
if (previewRenderElement && previewRenderElement.previousElementSibling) {
// 光标如果落在预览区域中,则重置到代码区域
if (previewRenderElement.previousElementSibling.firstElementChild) {
range.selectNodeContents(previewRenderElement.previousElementSibling.firstElementChild);
Expand All @@ -104,16 +104,16 @@ export const input = (vditor: IVditor, range: Range, ignoreSpace = false) => {
const footnoteElement = hasClosestByAttribute(blockElement, "data-type", "footnotes-block");
let html = "";
if (!isIRElement) {
const blockquoteElement = hasClosestByTag(range.startContainer, "BLOCKQUOTE");
// 列表需要到最顶层
const topListElement = getTopList(range.startContainer);
if (topListElement) {
const blockquoteElement = hasClosestByTag(range.startContainer, "BLOCKQUOTE");
if (blockquoteElement) {
// li 中有 blockquote 就只渲染 blockquote
blockElement = hasClosestBlock(range.startContainer) || blockElement;
} else {
blockElement = topListElement;
}
blockElement = topListElement;
}

// 应到引用层,否则 > --- 会解析为 front-matter;列表中有 blockquote 则解析 blockquote;blockquote 中有列表则解析列表
if (blockquoteElement && (!topListElement || (topListElement && !blockquoteElement.contains(topListElement)))) {
blockElement = blockquoteElement;
}

// 修改脚注
Expand Down
10 changes: 9 additions & 1 deletion src/ts/sv/inputEvent.ts
Expand Up @@ -32,8 +32,9 @@ export const inputEvent = (vditor: IVditor, event?: InputEvent) => {
processAfterRender(vditor);
return;
}
// https://github.com/Vanessa219/vditor/issues/584

if (event.inputType === "deleteContentBackward") {
// https://github.com/Vanessa219/vditor/issues/584 代码块 marker 删除
const codeBlockMarkerElement =
hasClosestByAttribute(startContainer, "data-type", "code-block-open-marker") ||
hasClosestByAttribute(startContainer, "data-type", "code-block-close-marker");
Expand Down Expand Up @@ -65,6 +66,13 @@ export const inputEvent = (vditor: IVditor, event?: InputEvent) => {
item.remove();
}
});

// 标题删除
const headingElement = hasClosestByAttribute(startContainer, "data-type", "heading-marker");
if (headingElement && headingElement.textContent.indexOf("#") === -1) {
processAfterRender(vditor);
return;
}
}
// 删除或空格不解析,否则会 format 回去
if ((event.data === " " || event.inputType === "deleteContentBackward") &&
Expand Down
5 changes: 4 additions & 1 deletion src/ts/sv/process.ts
Expand Up @@ -59,7 +59,10 @@ export const processSpinVditorSVDOM = (html: string, vditor: IVditor) => {
export const processPreviousMarkers = (spanElement: HTMLElement) => {
const spanType = spanElement.getAttribute("data-type");
let previousElement = spanElement.previousElementSibling;
let markerText = (spanType && spanType !== "text") ? spanElement.textContent : ""; // 有内容的子列表,在其 marker 后换行
// 有内容的子列表/标题,在其 marker 后换行
let markerText = (spanType && spanType !== "text" && spanType !== "heading-marker" &&
spanType !== "yaml-front-matter-open-marker" && spanType !== "yaml-front-matter-close-marker") ?
spanElement.textContent : "";
let hasNL = false;
while (previousElement && !hasNL) {
const previousType = previousElement.getAttribute("data-type");
Expand Down
2 changes: 2 additions & 0 deletions src/ts/undo/index.ts
Expand Up @@ -64,6 +64,8 @@ class Undo {
this[vditor.currentMode].redoStack.push(state);
this.renderDiff(state, vditor);
this[vditor.currentMode].hasUndo = true;
// undo 操作后,需要关闭 hint
vditor.hint.element.style.display = "none";
}

public redo(vditor: IVditor) {
Expand Down
9 changes: 5 additions & 4 deletions src/ts/util/fixBrowserBehavior.ts
Expand Up @@ -41,14 +41,15 @@ export const fixGSKeyBackspace = (event: KeyboardEvent, vditor: IVditor, startCo
return true;
};

// https://github.com/Vanessa219/vditor/issues/361
// https://github.com/Vanessa219/vditor/issues/361 代码块后输入中文
export const fixCJKPosition = (range: Range, vditor: IVditor, event: KeyboardEvent) => {
if (event.key === "Enter" || event.key === "Tab" || event.key === "Backspace" || event.key.indexOf("Arrow") > -1
|| isCtrl(event) || event.key === "Escape" || event.shiftKey || event.altKey) {
return;
}
const pElement = hasClosestByMatchTag(range.startContainer, "P");
if (pElement && getSelectPosition(pElement, vditor[vditor.currentMode].element, range).start === 0) {
const pLiElement = hasClosestByMatchTag(range.startContainer, "P") ||
hasClosestByMatchTag(range.startContainer, "LI");
if (pLiElement && getSelectPosition(pLiElement, vditor[vditor.currentMode].element, range).start === 0) {
const zwspNode = document.createTextNode(Constants.ZWSP);
range.insertNode(zwspNode);
range.setStartAfter(zwspNode);
Expand Down Expand Up @@ -542,7 +543,7 @@ export const fixMarkdown = (event: KeyboardEvent, vditor: IVditor, pElement: HTM
}

// hr 渲染
if (isHrMD(pElement.innerHTML)) {
if (isHrMD(pElement.innerHTML) && pElement.previousElementSibling) {
// 软换行后 hr 前有内容
let pInnerHTML = "";
const innerHTMLList = pElement.innerHTML.trimRight().split("\n");
Expand Down
2 changes: 1 addition & 1 deletion src/ts/util/processCode.ts
Expand Up @@ -40,7 +40,7 @@ export const processPasteCode = (html: string, text: string, type = "sv") => {
return `<div class="vditor-wysiwyg__block" data-block="0" data-type="code-block"><pre><code>${
code.replace(/&/g, "&amp;").replace(/</g, "&lt;")}<wbr></code></pre></div>`;
}
return "```\n" + code.replace(/&/g, "&amp;").replace(/</g, "&lt;") + "\n```";
return "\n```\n" + code.replace(/&/g, "&amp;").replace(/</g, "&lt;") + "\n```";
} else {
if (type === "wysiwyg") {
return `<code>${code.replace(/&/g, "&amp;").replace(/</g, "&lt;")}</code><wbr>`;
Expand Down