Skip to content

Commit

Permalink
♻️ Vanessa219#27
Browse files Browse the repository at this point in the history
  • Loading branch information
Vanessa219 authored and stevapple committed Apr 8, 2020
1 parent 190e904 commit f0873ff
Show file tree
Hide file tree
Showing 5 changed files with 140 additions and 141 deletions.
53 changes: 14 additions & 39 deletions src/ts/ir/processKeydown.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import {Constants} from "../constants";
import {isCtrl} from "../util/compatibility";
import {scrollCenter} from "../util/editorCommenEvent";
import {hasClosestByAttribute, hasClosestByClassName, hasClosestByMatchTag} from "../util/hasClosest";
import {mdKeydown} from "../util/processMD";
import {processList} from "../util/processList";
import {mdKeydown, processTab} from "../util/processMD";
import {tableHotkey} from "../util/processTable";
import {getSelectPosition, setRangeByWbr} from "../util/selection";
import {processAfterRender} from "./process";
Expand All @@ -27,10 +28,10 @@ export const processKeydown = (vditor: IVditor, event: KeyboardEvent) => {
const range = getSelection().getRangeAt(0);
const startContainer = range.startContainer;

// 斜体、粗体、内联代码块中换行
const newlineElement = hasClosestByAttribute(startContainer, "data-newline", "1");
if (!isCtrl(event) && !event.altKey && !event.shiftKey && event.key === "Enter" && newlineElement
&& range.startOffset < newlineElement.textContent.length) {
// 斜体、粗体、内联代码块中换行
const beforeMarkerElement = newlineElement.previousElementSibling;
if (beforeMarkerElement) {
range.insertNode(document.createTextNode(beforeMarkerElement.textContent));
Expand All @@ -45,7 +46,12 @@ export const processKeydown = (vditor: IVditor, event: KeyboardEvent) => {

const pElement = hasClosestByMatchTag(startContainer, "P");
if (pElement) {
if (mdKeydown(event, vditor, pElement, range, processAfterRender)) {
// md 处理
if (mdKeydown(event, vditor, pElement, range)) {
return true;
}
// li
if (processList(range, vditor, pElement, event)) {
return true;
}
}
Expand Down Expand Up @@ -147,43 +153,8 @@ export const processKeydown = (vditor: IVditor, event: KeyboardEvent) => {
}
}

const liElement = hasClosestByMatchTag(startContainer, "LI");
if (liElement) {
if (!isCtrl(event) && !event.altKey && event.key === "Enter" &&
(event.shiftKey // 软换行
// fix li 中有多个 P 时,在第一个 P 中换行会在下方生成新的 li
|| (!event.shiftKey && pElement && liElement.contains(pElement) && pElement.nextElementSibling))) {
if (liElement && !liElement.textContent.endsWith("\n")) {
// li 结尾需 \n
liElement.insertAdjacentText("beforeend", "\n");
}
range.insertNode(document.createTextNode("\n"));
range.collapse(false);
processAfterRender(vditor);
event.preventDefault();
return true;
}

if (!isCtrl(event) && !event.shiftKey && !event.altKey && event.key === "Backspace" &&
!liElement.previousElementSibling && range.toString() === "" &&
getSelectPosition(liElement, range).start === 0) {
// 光标位于点和第一个字符中间时,无法删除 li 元素
if (liElement.nextElementSibling) {
liElement.parentElement.insertAdjacentHTML("beforebegin",
`<p data-block="0"><wbr>${liElement.innerHTML}</p>`);
liElement.remove();
} else {
liElement.parentElement.outerHTML = `<p data-block="0"><wbr>${liElement.innerHTML}</p>`;
}
setRangeByWbr(vditor.ir.element, range);
processAfterRender(vditor);
event.preventDefault();
return true;
}
}

// table
if (tableHotkey(vditor, event, range, processAfterRender)) {
if (tableHotkey(vditor, event, range)) {
return true;
}

Expand Down Expand Up @@ -226,6 +197,10 @@ export const processKeydown = (vditor: IVditor, event: KeyboardEvent) => {
}
}

if (processTab(vditor, range, event)) {
return true;
}

if (event.key === "Enter") {
scrollCenter(vditor.ir.element);
}
Expand Down
70 changes: 70 additions & 0 deletions src/ts/util/processList.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import {isCtrl} from "./compatibility";
import {hasClosestByMatchTag} from "./hasClosest";
import {execAfterRender} from "./processMD";
import {getSelectPosition, setRangeByWbr} from "./selection";

export const processList = (range: Range, vditor: IVditor, pElement: HTMLElement, event: KeyboardEvent) => {
const startContainer = range.startContainer;
const liElement = hasClosestByMatchTag(startContainer, "LI");
if (liElement) {
if (!isCtrl(event) && !event.altKey && event.key === "Enter" &&
(event.shiftKey // 软换行
// fix li 中有多个 P 时,在第一个 P 中换行会在下方生成新的 li
|| (!event.shiftKey && pElement && liElement.contains(pElement) && pElement.nextElementSibling))) {
if (liElement && !liElement.textContent.endsWith("\n")) {
// li 结尾需 \n
liElement.insertAdjacentText("beforeend", "\n");
}
range.insertNode(document.createTextNode("\n"));
range.collapse(false);
execAfterRender(vditor);
event.preventDefault();
return true;
}

if (!isCtrl(event) && !event.shiftKey && !event.altKey && event.key === "Backspace" &&
!liElement.previousElementSibling && range.toString() === "" &&
getSelectPosition(liElement, range).start === 0) {
// 光标位于点和第一个字符中间时,无法删除 li 元素
if (liElement.nextElementSibling) {
liElement.parentElement.insertAdjacentHTML("beforebegin",
`<p data-block="0"><wbr>${liElement.innerHTML}</p>`);
liElement.remove();
} else {
liElement.parentElement.outerHTML = `<p data-block="0"><wbr>${liElement.innerHTML}</p>`;
}
setRangeByWbr(vditor[vditor.currentMode].element, range);
execAfterRender(vditor);
event.preventDefault();
return true;
}

if (!isCtrl(event) && !event.altKey && event.key === "Tab") {
// 光标位于第一/零字符时,tab 用于列表的缩进
let isFirst = false;
if (range.startOffset === 0
&& ((startContainer.nodeType === 3 && !startContainer.previousSibling)
|| (startContainer.nodeType !== 3 && startContainer.nodeName === "LI"))) {
// 有序/无序列表
isFirst = true;
} else if (liElement.classList.contains("vditor-task") && range.startOffset === 1
&& startContainer.previousSibling.nodeType !== 3
&& (startContainer.previousSibling as HTMLElement).tagName === "INPUT") {
// 任务列表
isFirst = true;
}

// TODO
if (isFirst) {
if (event.shiftKey) {
vditor.wysiwyg.popover.querySelector('button[data-type="outdent"]').dispatchEvent(new CustomEvent("click"));
} else {
vditor.wysiwyg.popover.querySelector('button[data-type="indent"]').dispatchEvent(new CustomEvent("click"));
}
event.preventDefault();
return true;
}
}
}
return false;
};
40 changes: 35 additions & 5 deletions src/ts/util/processMD.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import {processAfterRender} from "../ir/process";
import {afterRenderEvent} from "../wysiwyg/afterRenderEvent";
import {isCtrl} from "./compatibility";
import {scrollCenter} from "./editorCommenEvent";
import {getLastNode} from "./hasClosest";
Expand Down Expand Up @@ -68,8 +70,7 @@ export const renderToc = (editorElement: HTMLPreElement) => {
tocElement.innerHTML = tocHTML || "[ToC]";
};

export const mdKeydown = (event: KeyboardEvent, vditor: IVditor, pElement: HTMLElement, range: Range,
afterRenderEvent: (vditor: IVditor) => void) => {
export const mdKeydown = (event: KeyboardEvent, vditor: IVditor, pElement: HTMLElement, range: Range) => {
if (!isCtrl(event) && !event.altKey && event.key === "Enter") {
const pText = String.raw`${pElement.textContent}`.replace(/\\\|/g, "").trim();
const pTextList = pText.split("|");
Expand All @@ -80,7 +81,7 @@ export const mdKeydown = (event: KeyboardEvent, vditor: IVditor, pElement: HTMLE
pElement.textContent + tableHeaderMD.substring(3, tableHeaderMD.length - 3) + "\n|<wbr>";
pElement.outerHTML = vditor.lute.SpinVditorDOM(tableHeaderMD);
setRangeByWbr(vditor[vditor.currentMode].element, range);
afterRenderEvent(vditor);
execAfterRender(vditor);
scrollCenter(vditor[vditor.currentMode].element);
event.preventDefault();
return true;
Expand All @@ -100,7 +101,7 @@ export const mdKeydown = (event: KeyboardEvent, vditor: IVditor, pElement: HTMLE
`${pInnerHTML}<hr data-block="0"><p data-block="0">\n<wbr></p>`);
pElement.remove();
setRangeByWbr(vditor[vditor.currentMode].element, range);
afterRenderEvent(vditor);
execAfterRender(vditor);
scrollCenter(vditor[vditor.currentMode].element);
event.preventDefault();
return true;
Expand All @@ -110,7 +111,7 @@ export const mdKeydown = (event: KeyboardEvent, vditor: IVditor, pElement: HTMLE
// heading 渲染
pElement.outerHTML = vditor.lute.SpinVditorDOM(pElement.innerHTML + '<p data-block="0">\n<wbr></p>');
setRangeByWbr(vditor[vditor.currentMode].element, range);
afterRenderEvent(vditor);
execAfterRender(vditor);
scrollCenter(vditor[vditor.currentMode].element);
event.preventDefault();
return true;
Expand All @@ -132,3 +133,32 @@ export const mdKeydown = (event: KeyboardEvent, vditor: IVditor, pElement: HTMLE
}
return false;
};

// tab 处理: block code render, table, 列表第一个字符中的 tab 处理单独写在上面
export const processTab = (vditor: IVditor, range: Range, event: KeyboardEvent) => {
if (vditor.options.tab && event.key === "Tab") {
if (event.shiftKey) {
// TODO shift+tab
} else {
if (range.toString() === "") {
range.insertNode(document.createTextNode(vditor.options.tab));
range.collapse(false);
} else {
range.extractContents();
range.insertNode(document.createTextNode(vditor.options.tab));
range.collapse(false);
}
}
execAfterRender(vditor);
event.preventDefault();
return true;
}
};

export const execAfterRender = (vditor: IVditor) => {
if (vditor.currentMode === "wysiwyg") {
afterRenderEvent(vditor);
} else if (vditor.currentMode === "ir") {
processAfterRender(vditor);
}
};
20 changes: 10 additions & 10 deletions src/ts/util/processTable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {isCtrl} from "./compatibility";
import {scrollCenter} from "./editorCommenEvent";
import {hasClosestByMatchTag} from "./hasClosest";
import {matchHotKey} from "./hotKey";
import {execAfterRender} from "./processMD";
import {setRangeByWbr} from "./selection";

// 光标设置到前一个表格中
Expand Down Expand Up @@ -46,8 +47,7 @@ export const setTableAlign = (tableElement: HTMLTableElement, type: string) => {
}
};

export const tableHotkey = (vditor: IVditor, event: KeyboardEvent, range: Range,
afterRenderEvent: (vditor: IVditor) => void) => {
export const tableHotkey = (vditor: IVditor, event: KeyboardEvent, range: Range) => {
const startContainer = range.startContainer;
const cellElement = hasClosestByMatchTag(startContainer, "TD") ||
hasClosestByMatchTag(startContainer, "TH");
Expand All @@ -62,7 +62,7 @@ export const tableHotkey = (vditor: IVditor, event: KeyboardEvent, range: Range,
const brElement = document.createElement("br");
range.insertNode(brElement);
range.setStartAfter(brElement);
afterRenderEvent(vditor);
execAfterRender(vditor);
scrollCenter(vditor[vditor.currentMode].element);
event.preventDefault();
return true;
Expand Down Expand Up @@ -121,7 +121,7 @@ export const tableHotkey = (vditor: IVditor, event: KeyboardEvent, range: Range,

range.collapse(false);
event.preventDefault();
afterRenderEvent(vditor);
execAfterRender(vditor);
return true;
}

Expand All @@ -139,7 +139,7 @@ export const tableHotkey = (vditor: IVditor, event: KeyboardEvent, range: Range,
}

setRangeByWbr(vditor[vditor.currentMode].element, range);
afterRenderEvent(vditor);
execAfterRender(vditor);
scrollCenter(vditor[vditor.currentMode].element);
event.preventDefault();
return true;
Expand All @@ -162,7 +162,7 @@ export const tableHotkey = (vditor: IVditor, event: KeyboardEvent, range: Range,
}
}

afterRenderEvent(vditor);
execAfterRender(vditor);
event.preventDefault();
return true;
}
Expand All @@ -186,7 +186,7 @@ export const tableHotkey = (vditor: IVditor, event: KeyboardEvent, range: Range,
tableElement.rows[i].cells[index].remove();
}
}
afterRenderEvent(vditor);
execAfterRender(vditor);
event.preventDefault();
return true;
}
Expand All @@ -195,7 +195,7 @@ export const tableHotkey = (vditor: IVditor, event: KeyboardEvent, range: Range,
if (matchHotKey("⌘-⇧-L", event)) {
if (vditor.currentMode === "ir") {
setTableAlign(tableElement, "left");
afterRenderEvent(vditor);
execAfterRender(vditor);
event.preventDefault();
return true;
} else {
Expand All @@ -212,7 +212,7 @@ export const tableHotkey = (vditor: IVditor, event: KeyboardEvent, range: Range,
if (matchHotKey("⌘-⇧-C", event)) {
if (vditor.currentMode === "ir") {
setTableAlign(tableElement, "center");
afterRenderEvent(vditor);
execAfterRender(vditor);
event.preventDefault();
return true;
} else {
Expand All @@ -228,7 +228,7 @@ export const tableHotkey = (vditor: IVditor, event: KeyboardEvent, range: Range,
if (matchHotKey("⌘-⇧-R", event)) {
if (vditor.currentMode === "ir") {
setTableAlign(tableElement, "right");
afterRenderEvent(vditor);
execAfterRender(vditor);
event.preventDefault();
return true;
} else {
Expand Down
Loading

0 comments on commit f0873ff

Please sign in to comment.