Skip to content

Commit

Permalink
🎨 Vanessa219#27 processmd
Browse files Browse the repository at this point in the history
  • Loading branch information
Vanessa219 authored and stevapple committed Apr 8, 2020
1 parent 2c4fc8a commit 2cc4429
Show file tree
Hide file tree
Showing 10 changed files with 158 additions and 136 deletions.
3 changes: 2 additions & 1 deletion src/ts/ir/input.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {getTopList, hasClosestBlock, hasClosestByClassName, hasClosestByTag} from "../util/hasClosest";
import {log} from "../util/log";
import {isHeadingMD, isHrMD} from "../util/processMD";
import {getSelectPosition, setRangeByWbr} from "../util/selection";
import {processAfterRender, processCodeRender} from "./process";

Expand Down Expand Up @@ -40,7 +41,7 @@ export const input = (vditor: IVditor, range: Range) => {
}
}

if ((startSpace || endSpace)
if ((startSpace || endSpace || isHrMD(blockElement.innerHTML) || isHeadingMD(blockElement.innerHTML))
// insert table
&& !blockElement.querySelector("wbr")) {
blockElement.classList.add("vditor-ir__node--expand");
Expand Down
8 changes: 7 additions & 1 deletion src/ts/ir/processKeydown.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ 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 {tableHotkey} from "../util/processTable";
import {getSelectPosition, setRangeByWbr} from "../util/selection";
import {processAfterRender} from "./process";
Expand All @@ -27,7 +28,6 @@ export const processKeydown = (vditor: IVditor, event: KeyboardEvent) => {
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) {
// 斜体、粗体、内联代码块中换行
Expand All @@ -44,6 +44,12 @@ export const processKeydown = (vditor: IVditor, event: KeyboardEvent) => {
}

const pElement = hasClosestByMatchTag(startContainer, "P");
if (pElement) {
if (mdKeydown(event, vditor, pElement, range, processAfterRender)) {
return true;
}
}

// 代码块
const preRenderElement = hasClosestByClassName(startContainer, "vditor-ir__marker--pre");
if (preRenderElement && preRenderElement.tagName === "PRE") {
Expand Down
7 changes: 7 additions & 0 deletions src/ts/util/hasClosest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,3 +159,10 @@ export const getTopList = (element: Node) => {
}
return topListElement;
};

export const getLastNode = (node: Node) => {
while (node && node.lastChild) {
node = node.lastChild;
}
return node;
};
134 changes: 134 additions & 0 deletions src/ts/util/processMD.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
import {isCtrl} from "./compatibility";
import {scrollCenter} from "./editorCommenEvent";
import {getLastNode} from "./hasClosest";
import {getSelectPosition, setRangeByWbr} from "./selection";

export const isHrMD = (text: string) => {
// - _ *
const marker = text.trimRight().split("\n").pop();
if (marker === "") {
return false;
}
if (marker.replace(/ |-/g, "") === ""
|| marker.replace(/ |_/g, "") === ""
|| marker.replace(/ |\*/g, "") === "") {
if (marker.replace(/ /g, "").length > 2) {
if (marker.indexOf("-") > -1 && marker.trimLeft().indexOf(" ") === -1
&& text.trimRight().split("\n").length > 1) {
// 满足 heading
return false;
}
if (marker.indexOf(" ") === 0 || marker.indexOf("\t") === 0) {
// 代码块
return false;
}
return true;
}
return false;
}
return false;
};

export const isHeadingMD = (text: string) => {
// - =
const textArray = text.trimRight().split("\n");
text = textArray.pop();

if (text.indexOf(" ") === 0 || text.indexOf("\t") === 0) {
return false;
}

text = text.trimLeft();
if (text === "" || textArray.length === 0) {
return false;
}
if (text.replace(/-/g, "") === ""
|| text.replace(/=/g, "") === "") {
return true;
}
return false;
};

export const isToC = (text: string) => {
return text.trim().toLowerCase() === "[toc]";
};

export const renderToc = (editorElement: HTMLPreElement) => {
const tocElement = editorElement.querySelector('[data-type="toc-block"]');
if (!tocElement) {
return;
}
let tocHTML = "";
Array.from(editorElement.children).forEach((item: HTMLElement) => {
if (item.tagName.indexOf("H") === 0 && item.tagName.length === 2 && item.textContent.trim() !== "") {
const space = new Array((parseInt(item.tagName.substring(1), 10) - 1) * 2).fill("&emsp;").join("");
tocHTML += `${space}<span data-type="toc-h">${item.textContent.trim()}</span><br>`;
}
});
tocElement.innerHTML = tocHTML || "[ToC]";
};

export const mdKeydown = (event: KeyboardEvent, vditor: IVditor, pElement: HTMLElement, range: Range,
afterRenderEvent: (vditor: IVditor) => void) => {
if (!isCtrl(event) && !event.altKey && event.key === "Enter") {
const pText = String.raw`${pElement.textContent}`.replace(/\\\|/g, "").trim();
const pTextList = pText.split("|");
if (pText.startsWith("|") && pText.endsWith("|") && pTextList.length > 3) {
// table 自动完成
let tableHeaderMD = pTextList.map(() => "---").join("|");
tableHeaderMD =
pElement.textContent + tableHeaderMD.substring(3, tableHeaderMD.length - 3) + "\n|<wbr>";
pElement.outerHTML = vditor.lute.SpinVditorDOM(tableHeaderMD);
setRangeByWbr(vditor[vditor.currentMode].element, range);
afterRenderEvent(vditor);
scrollCenter(vditor[vditor.currentMode].element);
event.preventDefault();
return true;
}

// hr 渲染
if (isHrMD(pElement.innerHTML)) {
// 软换行后 hr 前有内容
let pInnerHTML = "";
const innerHTMLList = pElement.innerHTML.trimRight().split("\n");
if (innerHTMLList.length > 1) {
innerHTMLList.pop();
pInnerHTML = `<p data-block="0">${innerHTMLList.join("\n")}</p>`;
}

pElement.insertAdjacentHTML("afterend",
`${pInnerHTML}<hr data-block="0"><p data-block="0">\n<wbr></p>`);
pElement.remove();
setRangeByWbr(vditor[vditor.currentMode].element, range);
afterRenderEvent(vditor);
scrollCenter(vditor[vditor.currentMode].element);
event.preventDefault();
return true;
}

if (isHeadingMD(pElement.innerHTML)) {
// heading 渲染
pElement.outerHTML = vditor.lute.SpinVditorDOM(pElement.innerHTML + '<p data-block="0">\n<wbr></p>');
setRangeByWbr(vditor[vditor.currentMode].element, range);
afterRenderEvent(vditor);
scrollCenter(vditor[vditor.currentMode].element);
event.preventDefault();
return true;
}
}

// 软换行会被切割 https://github.com/Vanessa219/vditor/issues/220
if (pElement.previousElementSibling && event.key === "Backspace" && !isCtrl(event) && !event.altKey &&
!event.shiftKey && pElement.textContent.trimRight().split("\n").length > 1 &&
getSelectPosition(pElement, range).start === 0) {
const lastElement = getLastNode(pElement.previousElementSibling) as HTMLElement;
if (!lastElement.textContent.endsWith("\n")) {
lastElement.textContent = lastElement.textContent + "\n";
}
lastElement.parentElement.insertAdjacentHTML("beforeend", `<wbr>${pElement.innerHTML}`);
pElement.remove();
setRangeByWbr(vditor[vditor.currentMode].element, range);
return false;
}
return false;
};
2 changes: 1 addition & 1 deletion src/ts/wysiwyg/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ import {
hasClosestBlock, hasClosestByAttribute,
hasClosestByClassName, hasClosestByMatchTag,
} from "../util/hasClosest";
import {isHeadingMD, isHrMD, renderToc} from "../util/processMD";
import {processPasteCode} from "../util/processPasteCode";
import {getSelectPosition, insertHTML, setRangeByWbr, setSelectionByPosition, setSelectionFocus} from "../util/selection";
import {afterRenderEvent} from "./afterRenderEvent";
import {highlightToolbar} from "./highlightToolbar";
import {getRenderElementNextNode, modifyPre} from "./inlineTag";
import {input} from "./input";
import {processCodeRender, showCode} from "./processCodeRender";
import {isHeadingMD, isHrMD, renderToc} from "./processMD";

class WYSIWYG {
public element: HTMLPreElement;
Expand Down
7 changes: 0 additions & 7 deletions src/ts/wysiwyg/inlineTag.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,13 +79,6 @@ export const getRenderElementNextNode = (blockCodeElement: HTMLElement) => {
return nextNode.nextSibling;
};

export const getLastNode = (node: Node) => {
while (node && node.lastChild) {
node = node.lastChild;
}
return node;
};

export const splitElement = (range: Range) => {
const previousHTML = getPreviousHTML(range.startContainer);
const nextHTML = getNextHTML(range.startContainer);
Expand Down
2 changes: 1 addition & 1 deletion src/ts/wysiwyg/input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ import {
hasClosestByTag,
} from "../util/hasClosest";
import {log} from "../util/log";
import {isToC, renderToc} from "../util/processMD";
import {setRangeByWbr} from "../util/selection";
import {afterRenderEvent} from "./afterRenderEvent";
import {previoueIsEmptyA} from "./inlineTag";
import {processCodeRender} from "./processCodeRender";
import {isToC, renderToc} from "./processMD";

export const input = (vditor: IVditor, range: Range, event?: InputEvent) => {
let blockElement = hasClosestBlock(range.startContainer);
Expand Down
65 changes: 5 additions & 60 deletions src/ts/wysiwyg/processKeydown.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,20 @@ import {Constants} from "../constants";
import {isCtrl} from "../util/compatibility";
import {scrollCenter} from "../util/editorCommenEvent";
import {
getLastNode,
getTopList, hasClosestBlock, hasClosestByAttribute,
hasClosestByClassName,
hasClosestByMatchTag, hasClosestByTag,
hasTopClosestByTag,
} from "../util/hasClosest";
import {matchHotKey} from "../util/hotKey";
import {mdKeydown} from "../util/processMD";
import {tableHotkey} from "../util/processTable";
import {getSelectPosition, setRangeByWbr, setSelectionFocus} from "../util/selection";
import {afterRenderEvent} from "./afterRenderEvent";
import {listOutdent} from "./highlightToolbar";
import {getLastNode, nextIsCode} from "./inlineTag";
import {nextIsCode} from "./inlineTag";
import {processCodeRender, showCode} from "./processCodeRender";
import {isHeadingMD, isHrMD} from "./processMD";
import {removeHeading, setHeading} from "./setHeading";

export const processKeydown = (vditor: IVditor, event: KeyboardEvent) => {
Expand Down Expand Up @@ -43,64 +44,8 @@ export const processKeydown = (vditor: IVditor, event: KeyboardEvent) => {
// md 处理
const pElement = hasClosestByMatchTag(startContainer, "P");
if (pElement) {
if (!isCtrl(event) && !event.altKey && event.key === "Enter") {
const pText = String.raw`${pElement.textContent}`.replace(/\\\|/g, "").trim();
const pTextList = pText.split("|");
if (pText.startsWith("|") && pText.endsWith("|") && pTextList.length > 3) {
// table 自动完成
let tableHeaderMD = pTextList.map(() => "---").join("|");
tableHeaderMD =
pElement.textContent + tableHeaderMD.substring(3, tableHeaderMD.length - 3) + "\n|<wbr>";
pElement.outerHTML = vditor.lute.SpinVditorDOM(tableHeaderMD);
setRangeByWbr(vditor.wysiwyg.element, range);
afterRenderEvent(vditor);
scrollCenter(vditor.wysiwyg.element);
event.preventDefault();
return true;
}

// hr 渲染
if (isHrMD(pElement.innerHTML)) {
// 软换行后 hr 前有内容
let pInnerHTML = "";
const innerHTMLList = pElement.innerHTML.trimRight().split("\n");
if (innerHTMLList.length > 1) {
innerHTMLList.pop();
pInnerHTML = `<p data-block="0">${innerHTMLList.join("\n")}</p>`;
}

pElement.insertAdjacentHTML("afterend",
`${pInnerHTML}<hr data-block="0"><p data-block="0">\n<wbr></p>`);
pElement.remove();
setRangeByWbr(vditor.wysiwyg.element, range);
afterRenderEvent(vditor);
scrollCenter(vditor.wysiwyg.element);
event.preventDefault();
return true;
}

if (isHeadingMD(pElement.innerHTML)) {
// heading 渲染
pElement.outerHTML = vditor.lute.SpinVditorDOM(pElement.innerHTML + '<p data-block="0">\n<wbr></p>');
setRangeByWbr(vditor.wysiwyg.element, range);
afterRenderEvent(vditor);
scrollCenter(vditor.wysiwyg.element);
event.preventDefault();
return true;
}
}

// 软换行会被切割 https://github.com/Vanessa219/vditor/issues/220
if (pElement.previousElementSibling && event.key === "Backspace" && !isCtrl(event) && !event.altKey &&
!event.shiftKey && pElement.textContent.trimRight().split("\n").length > 1 &&
getSelectPosition(pElement, range).start === 0) {
const lastElement = getLastNode(pElement.previousElementSibling) as HTMLElement;
if (!lastElement.textContent.endsWith("\n")) {
lastElement.textContent = lastElement.textContent + "\n";
}
lastElement.parentElement.insertAdjacentHTML("beforeend", `<wbr>${pElement.innerHTML}`);
pElement.remove();
setRangeByWbr(vditor.wysiwyg.element, range);
if (mdKeydown(event, vditor, pElement, range, afterRenderEvent)) {
return true;
}
}

Expand Down
64 changes: 0 additions & 64 deletions src/ts/wysiwyg/processMD.ts

This file was deleted.

2 changes: 1 addition & 1 deletion src/ts/wysiwyg/setHeading.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {hasClosestBlock} from "../util/hasClosest";
import {renderToc} from "../util/processMD";
import {getEditorRange, setRangeByWbr} from "../util/selection";
import {renderToc} from "./processMD";

export const setHeading = (vditor: IVditor, tagName: string) => {
const range = getEditorRange(vditor.wysiwyg.element);
Expand Down

0 comments on commit 2cc4429

Please sign in to comment.