Skip to content

Commit

Permalink
🐛 fix #130
Browse files Browse the repository at this point in the history
  • Loading branch information
Vanessa219 committed Feb 13, 2020
1 parent 516e294 commit 4387c1d
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 73 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
* [133](https://github.com/Vanessa219/vditor/issues/133) MathJax 渲染无法修改 `修复缺陷`
* [132](https://github.com/Vanessa219/vditor/issues/132) 添加 md 配置项 `引入特性`
* [131](https://github.com/Vanessa219/vditor/issues/131) 代码块下输入中文 bug `修复缺陷`
* [130](https://github.com/Vanessa219/vditor/issues/130) 任务列表跳出 `修复缺陷`
* [127](https://github.com/Vanessa219/vditor/issues/127) more keyboard shortcut after ctrl+h `改进功能`

### v2.1.15 / 2020-02-09
Expand Down
70 changes: 37 additions & 33 deletions src/ts/wysiwyg/highlightToolbar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,39 +113,7 @@ export const highlightToolbar = (vditor: IVditor) => {
if (!liElement) {
return;
}
const liParentLiElement = hasClosestByMatchTag(liElement.parentElement, "LI");
if (liParentLiElement) {
vditor.wysiwyg.element.querySelectorAll("wbr").forEach((wbr) => {
wbr.remove();
});
range.insertNode(document.createElement("wbr"));

const liParentElement = liElement.parentElement;
const liParentAfterElement = liParentElement.cloneNode() as HTMLElement;

let isMatch = false;
let afterHTML = "";
liParentElement.querySelectorAll("li").forEach((item) => {
if (isMatch) {
afterHTML += item.outerHTML;
item.remove();
}
if (item.isEqualNode(liElement)) {
isMatch = true;
}
});
liParentAfterElement.innerHTML = afterHTML;

liParentLiElement.insertAdjacentElement("afterend", liElement);
liElement.insertAdjacentElement("beforeend", liParentAfterElement);

addP2Li(topListElement);
topListElement.outerHTML = vditor.lute.SpinVditorDOM(topListElement.outerHTML);

afterRenderEvent(vditor);
setRangeByWbr(vditor.wysiwyg.element, range);
highlightToolbar(vditor);
}
listOutdent(vditor, liElement, range, topListElement);
};

const indent = document.createElement("button");
Expand Down Expand Up @@ -664,3 +632,39 @@ export const genAPopover = (vditor: IVditor, aElement: HTMLElement) => {
vditor.wysiwyg.popover.insertAdjacentElement("beforeend", input2Wrap);
setPopoverPosition(vditor, aElement);
};

export const listOutdent = (vditor: IVditor, liElement: HTMLElement, range: Range, topListElement: HTMLElement) => {
const liParentLiElement = hasClosestByMatchTag(liElement.parentElement, "LI");
if (liParentLiElement) {
vditor.wysiwyg.element.querySelectorAll("wbr").forEach((wbr) => {
wbr.remove();
});
range.insertNode(document.createElement("wbr"));

const liParentElement = liElement.parentElement;
const liParentAfterElement = liParentElement.cloneNode() as HTMLElement;

let isMatch = false;
let afterHTML = "";
liParentElement.querySelectorAll("li").forEach((item) => {
if (isMatch) {
afterHTML += item.outerHTML;
item.remove();
}
if (item.isEqualNode(liElement)) {
isMatch = true;
}
});
liParentAfterElement.innerHTML = afterHTML;

liParentLiElement.insertAdjacentElement("afterend", liElement);
liElement.insertAdjacentElement("beforeend", liParentAfterElement);

addP2Li(topListElement);
topListElement.outerHTML = vditor.lute.SpinVditorDOM(topListElement.outerHTML);

afterRenderEvent(vditor);
setRangeByWbr(vditor.wysiwyg.element, range);
highlightToolbar(vditor);
}
};
7 changes: 7 additions & 0 deletions src/ts/wysiwyg/inlineTag.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,10 @@ export const getRenderElementNextNode = (blockCodeElement: HTMLElement) => {

return nextNode.nextSibling;
};

export const getLastNode = (node: Node) => {
while (node && node.lastChild) {
node = node.lastChild;
}
return node;
};
108 changes: 68 additions & 40 deletions src/ts/wysiwyg/processKeydown.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,16 @@ import {setSelectionFocus} from "../editor/setSelection";
import {isCtrl} from "../util/compatibility";
import {scrollCenter} from "../util/editorCommenEvent";
import {
getTopList,
hasClosestByAttribute,
hasClosestByClassName,
hasClosestByMatchTag, hasClosestByTag,
hasTopClosestByTag,
} from "../util/hasClosest";
import {processKeymap} from "../util/processKeymap";
import {afterRenderEvent} from "./afterRenderEvent";
import {nextIsCode} from "./inlineTag";
import {listOutdent} from "./highlightToolbar";
import {getLastNode, nextIsCode} from "./inlineTag";
import {processCodeRender, showCode} from "./processCodeRender";
import {isHeadingMD, isHrMD} from "./processMD";
import {setHeading} from "./setHeading";
Expand Down Expand Up @@ -435,32 +437,46 @@ export const processKeydown = (vditor: IVditor, event: KeyboardEvent) => {
return true;
}

if (!isCtrl(event) && !event.altKey && event.key === "Tab" && range.startOffset === 0
&& ((startContainer.nodeType === 3 && !startContainer.previousSibling)
|| (startContainer.nodeType !== 3 && startContainer.nodeName === "LI"))) {
// 光标位于第一零字符时,tab 用于列表的缩进
if (event.shiftKey) {
(vditor.wysiwyg.popover.querySelector('button[data-type="outdent"]') as HTMLElement).click();
} else {
(vditor.wysiwyg.popover.querySelector('button[data-type="indent"]') as HTMLElement).click();
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;
}

if (isFirst) {
if (event.shiftKey) {
(vditor.wysiwyg.popover.querySelector('button[data-type="outdent"]') as HTMLElement).click();
} else {
(vditor.wysiwyg.popover.querySelector('button[data-type="indent"]') as HTMLElement).click();
}
event.preventDefault();
return true;
}
event.preventDefault();
return true;
}
}

// task list
const taskItemElement = hasClosestByClassName(startContainer, "vditor-task");
if (taskItemElement) {
// Backspace: 在选择框前进行删除
if (event.key === "Backspace" && !isCtrl(event) && !event.shiftKey && !event.altKey
&& range.toString() === "" && ((startContainer.nodeType === 3 && range.startOffset === 1 &&
(startContainer.previousSibling as HTMLElement).tagName === "INPUT") ||
startContainer.nodeType !== 3)) {
if (event.key === "Backspace" && !isCtrl(event) && !event.shiftKey && !event.altKey && range.toString() === ""
&& range.startOffset === 1
&& ((startContainer.nodeType === 3 && (startContainer.previousSibling as HTMLElement).tagName === "INPUT")
|| startContainer.nodeType !== 3)) {
const previousElement = taskItemElement.previousElementSibling;
taskItemElement.querySelector("input").remove();
if (previousElement) {
previousElement.innerHTML += "<wbr>" + taskItemElement.innerHTML.trim();
const lastNode = getLastNode(previousElement);
lastNode.parentElement.insertAdjacentHTML("beforeend", "<wbr>" + taskItemElement.innerHTML.trim());
taskItemElement.remove();
} else {
taskItemElement.parentElement.insertAdjacentHTML("beforebegin",
Expand All @@ -479,37 +495,49 @@ export const processKeydown = (vditor: IVditor, event: KeyboardEvent) => {

if (event.key === "Enter" && !isCtrl(event) && !event.shiftKey && !event.altKey) {
if (taskItemElement.textContent.trim() === "") {
if (taskItemElement.nextElementSibling) {
// 用段落隔断
let afterHTML = "";
let beforeHTML = "";
let isAfter = false;
taskItemElement.parentElement.querySelectorAll("li").forEach((taskItem) => {
if (taskItemElement.isEqualNode(taskItem)) {
isAfter = true;
} else {
if (isAfter) {
afterHTML += taskItem.outerHTML;
// 当前任务列表无文字
if (hasClosestByClassName(taskItemElement.parentElement, "vditor-task")) {
// 为子元素时,需进行反向缩进
const topListElement = getTopList(startContainer);
if (topListElement) {
listOutdent(vditor, taskItemElement, range, topListElement);
}
} else {
// 仅有一级任务列表
if (taskItemElement.nextElementSibling) {
// 任务列表下方还有元素,需要使用用段落隔断
let afterHTML = "";
let beforeHTML = "";
let isAfter = false;
Array.from(taskItemElement.parentElement.children).forEach((taskItem) => {
if (taskItemElement.isEqualNode(taskItem)) {
isAfter = true;
} else {
beforeHTML += taskItem.outerHTML;
if (isAfter) {
afterHTML += taskItem.outerHTML;
} else {
beforeHTML += taskItem.outerHTML;
}
}
});
if (beforeHTML) {
beforeHTML = `<ul data-tight="true" data-marker="*" data-block="0">${beforeHTML}</ul>`;
}
});
if (beforeHTML) {
beforeHTML = `<ul data-tight="true" data-marker="*" data-block="0">${beforeHTML}</ul>`;
}
taskItemElement.parentElement.outerHTML = `${beforeHTML}<p data-block="0">\n<wbr></p><ul data-tight="true" data-marker="*" data-block="0">${afterHTML}</ul>`;
} else {
// 变成段落
taskItemElement.parentElement.insertAdjacentHTML("afterend", `<p data-block="0">\n<wbr></p>`);
if (taskItemElement.parentElement.querySelectorAll("li").length === 1) {
taskItemElement.parentElement.remove();
taskItemElement.parentElement.outerHTML = `${beforeHTML}<p data-block="0">\n<wbr></p><ul data-tight="true" data-marker="*" data-block="0">${afterHTML}</ul>`;
} else {
taskItemElement.remove();
// 任务列表下方无任务列表元素
taskItemElement.parentElement.insertAdjacentHTML("afterend", `<p data-block="0">\n<wbr></p>`);
if (taskItemElement.parentElement.querySelectorAll("li").length === 1) {
// 任务列表仅有一项时,使用 p 元素替换
taskItemElement.parentElement.remove();
} else {
// 任务列表有多项时,当前任务列表位于最后一项,移除该任务列表
taskItemElement.remove();
}
}
}
} else {
// 光标后文字添加到新列表中
// 当前任务列表有文字,光标后的文字需添加到新任务列表中
range.setEndAfter(taskItemElement.lastChild);
taskItemElement.insertAdjacentHTML("afterend", `<li class="vditor-task"><input type="checkbox"> <wbr></li>`);
document.querySelector("wbr").after(range.extractContents());
Expand Down

0 comments on commit 4387c1d

Please sign in to comment.