diff --git a/CHANGELOG.md b/CHANGELOG.md index 6b90faa3a..d77171793 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,8 +40,10 @@ * [55](https://github.com/Vanessa219/vditor/issues/55) 链接引用不转换为内联链接 `改进功能` * [81](https://github.com/Vanessa219/vditor/issues/81) 链接和图片嵌套问题 `修复缺陷` -### v2.1.5 / 2020-01-29 +### v2.1.6 / 2020-01-29 +* [96](https://github.com/Vanessa219/vditor/issues/96) 所见即所得模式下的任务列表Bug `修复缺陷` +* [95](https://github.com/Vanessa219/vditor/issues/95) setVaule 和 初始化时,不触发 input 事件 `改进功能` * [93](https://github.com/Vanessa219/vditor/issues/93) Headers with = and - `修复缺陷` * [92](https://github.com/Vanessa219/vditor/issues/92) 空行回车可以逐层跳出引用 `改进功能` * [88](https://github.com/Vanessa219/vditor/issues/88) Bold `修复缺陷` diff --git a/src/ts/markdown/md2html.ts b/src/ts/markdown/md2html.ts index 09b95dcb8..921810420 100644 --- a/src/ts/markdown/md2html.ts +++ b/src/ts/markdown/md2html.ts @@ -11,8 +11,8 @@ export const loadLuteJs = async (vditor: IVditor | string) => { } else if (typeof vditor === "object" && vditor.options.cdn) { cdn = vditor.options.cdn; } - addScript(`${cdn}/dist/js/lute/lute.min.js`, "vditorLuteScript"); - // addScript(`http://192.168.80.35:9090/lute.min.js?${new Date().getTime()}`, "vditorLuteScript"); + // addScript(`${cdn}/dist/js/lute/lute.min.js`, "vditorLuteScript"); + addScript(`http://192.168.80.35:9090/lute.min.js?${new Date().getTime()}`, "vditorLuteScript"); if (vditor && typeof vditor === "object" && !vditor.lute) { vditor.lute = Lute.New(); diff --git a/src/ts/toolbar/MenuItem.ts b/src/ts/toolbar/MenuItem.ts index 6374a2b56..07b61cd12 100644 --- a/src/ts/toolbar/MenuItem.ts +++ b/src/ts/toolbar/MenuItem.ts @@ -6,6 +6,7 @@ import {hasClosestByMatchTag} from "../util/hasClosest"; import {updateHotkeyTip} from "../util/updateHotkeyTip"; import {afterRenderEvent} from "../wysiwyg/afterRenderEvent"; import {genAPopover, highlightToolbar} from "../wysiwyg/highlightToolbar"; +import {listToggle} from "../wysiwyg/listToggle"; import {processCodeRender} from "../wysiwyg/processCodeRender"; import {setCurrentToolbar} from "./setCurrentToolbar"; @@ -50,11 +51,8 @@ export class MenuItem { } if (commandName === "strike") { commandName = "strikeThrough"; - } else if (commandName === "list" || commandName === "check") { - commandName = "insertUnorderedList"; - } else if (commandName === "ordered-list") { - commandName = "insertOrderedList"; } + if (commandName === "quote") { const quoteElement = hasClosestByMatchTag(range.startContainer, "BLOCKQUOTE"); if (quoteElement) { @@ -76,8 +74,10 @@ export class MenuItem { range.selectNode(range.startContainer.parentElement); document.execCommand("unlink", false, ""); } + } else if (commandName === "check" || commandName === "list" || commandName === "ordered-list") { + listToggle(vditor, range, commandName); } else { - // bold, italic, check + // bold, italic document.execCommand(commandName, false, ""); } vditor.wysiwyg.element.focus(); @@ -91,26 +91,13 @@ export class MenuItem { commandName = "insertHorizontalRule"; } else if (commandName === "strike") { commandName = "strikeThrough"; - } else if (commandName === "list") { - commandName = "insertUnorderedList"; - } else if (commandName === "ordered-list") { - commandName = "insertOrderedList"; } if (commandName === "quote") { document.execCommand("formatBlock", false, "BLOCKQUOTE"); getSelection().getRangeAt(0).startContainer.parentElement.setAttribute("data-block", "0"); - } else if (commandName === "check") { - const liElement = hasClosestByMatchTag(range.startContainer, "LI"); - if (liElement) { - range.setStartAfter(liElement); - range.collapse(true); - document.execCommand("insertHTML", false, - ' '); - } else { - document.execCommand("insertHTML", false, - ''); - } + } else if (commandName === "check" || commandName === "list" || commandName === "ordered-list") { + listToggle(vditor, range, commandName, false); } else if (commandName === "inline-code") { if (range.collapsed) { const node = document.createTextNode("``"); diff --git a/src/ts/wysiwyg/highlightToolbar.ts b/src/ts/wysiwyg/highlightToolbar.ts index 0ea431cb9..76724f59f 100644 --- a/src/ts/wysiwyg/highlightToolbar.ts +++ b/src/ts/wysiwyg/highlightToolbar.ts @@ -43,8 +43,16 @@ export const highlightToolbar = (vditor: IVditor) => { } // 工具栏高亮和禁用 - if (hasClosestByMatchTag(typeElement, "OL")) { - setCurrentToolbar(vditor.toolbar.elements, ["ordered-list"]); + const liElement = hasClosestByMatchTag(typeElement, "LI"); + if (hasClosestByClassName(typeElement, "vditor-task")) { + setCurrentToolbar(vditor.toolbar.elements, ["check"]); + } else { + if (liElement && liElement.parentElement.tagName === "OL") { + setCurrentToolbar(vditor.toolbar.elements, ["ordered-list"]); + } + if (liElement && liElement.parentElement.tagName === "UL") { + setCurrentToolbar(vditor.toolbar.elements, ["list"]); + } } if (hasClosestByMatchTag(typeElement, "BLOCKQUOTE")) { @@ -66,7 +74,6 @@ export const highlightToolbar = (vditor: IVditor) => { if (hasClosestByMatchTag(typeElement, "A")) { setCurrentToolbar(vditor.toolbar.elements, ["link"]); } - const topUlElement = hasClosestByMatchTag(typeElement, "UL"); const tableElement = hasClosestByMatchTag(typeElement, "TABLE") as HTMLTableElement; if (hasClosestByMatchTag(typeElement, "CODE")) { if (hasClosestByMatchTag(typeElement, "PRE")) { @@ -81,23 +88,17 @@ export const highlightToolbar = (vditor: IVditor) => { } else if (hasClosestByTag(typeElement, "H")) { disableToolbar(vditor.toolbar.elements, ["bold"]); setCurrentToolbar(vditor.toolbar.elements, ["headings"]); - } else if (topUlElement && !topUlElement.querySelector("input")) { - setCurrentToolbar(vditor.toolbar.elements, ["list"]); - } else if (hasClosestByMatchTag(typeElement, "OL")) { - setCurrentToolbar(vditor.toolbar.elements, ["ordered-list"]); } else if (tableElement) { disableToolbar(vditor.toolbar.elements, ["table"]); } // list popover const topOlElement = hasTopClosestByTag(typeElement, "OL"); + const topUlElement = hasTopClosestByTag(typeElement, "UL"); let topListElement = topUlElement; if (topOlElement && (!topUlElement || (topUlElement && topOlElement.contains(topUlElement)))) { topListElement = topOlElement; } - if (topListElement && topListElement.querySelector("input")) { - topListElement = false; - } if (topListElement) { vditor.wysiwyg.popover.innerHTML = ""; const outdent = document.createElement("button"); @@ -117,12 +118,12 @@ export const highlightToolbar = (vditor: IVditor) => { updateHotkeyTip("<⌘-⇧-e>")); indent.className = "vditor-icon vditor-tooltipped vditor-tooltipped__n"; indent.onclick = () => { - const liElement = hasClosestByMatchTag(range.startContainer, "LI"); - // fix 空列表缩进光标会飘逸 - if (liElement && liElement.innerHTML === "") { - liElement.innerHTML = "\n"; - } - document.execCommand("indent", false); + // const liElement = hasClosestByMatchTag(range.startContainer, "LI"); + // // fix 空列表缩进光标会飘逸 + // if (liElement && liElement.innerHTML === "") { + // liElement.innerHTML = "\n"; + // } + // document.execCommand("indent", false); }; vditor.wysiwyg.popover.insertAdjacentElement("beforeend", outdent); diff --git a/src/ts/wysiwyg/listToggle.ts b/src/ts/wysiwyg/listToggle.ts new file mode 100644 index 000000000..ea0dc33a5 --- /dev/null +++ b/src/ts/wysiwyg/listToggle.ts @@ -0,0 +1,73 @@ +import {hasClosestByAttribute, hasClosestByMatchTag} from "../util/hasClosest"; +import {setRangeByWbr} from "./setRangeByWbr"; + +export const listToggle = (vditor: IVditor, range: Range, type: string, cancel = true) => { + const itemElement = hasClosestByMatchTag(range.startContainer, "LI"); + vditor.wysiwyg.element.querySelectorAll("wbr").forEach((wbr) => { + wbr.remove(); + }); + range.insertNode(document.createElement("wbr")); + + if (cancel && itemElement) { + // 取消 + list2p(itemElement.parentElement); + } else { + if (!itemElement) { + // 添加 + const blockElement = hasClosestByAttribute(range.startContainer, "data-block", "0"); + if (blockElement) { + if (type === "check") { + blockElement.insertAdjacentHTML("beforebegin", + ``); + blockElement.remove(); + } else if (type === "list") { + blockElement.insertAdjacentHTML("beforebegin", + ``); + blockElement.remove(); + } else if (type === "ordered-list") { + blockElement.insertAdjacentHTML("beforebegin", + `
  1. ${blockElement.innerHTML}
`); + blockElement.remove(); + } + } + } else { + // 切换 + if (type === "check") { + itemElement.parentElement.querySelectorAll("li").forEach((item) => { + item.insertAdjacentHTML("afterbegin", ''); + item.classList.add("vditor-task"); + }); + } else { + if (itemElement.querySelector("input")) { + itemElement.parentElement.querySelectorAll("li").forEach((item) => { + item.querySelector("input").remove(); + item.classList.remove("vditor-task"); + }); + } + let element + if (type === "list") { + element = document.createElement("ul"); + + } else { + element = document.createElement("ol"); + } + element.innerHTML = itemElement.parentElement.innerHTML; + itemElement.parentElement.parentNode.replaceChild(element, itemElement.parentElement); + } + } + } + setRangeByWbr(vditor.wysiwyg.element, range); +}; + +const list2p = (listElement: HTMLElement) => { + let pHTML = ""; + listElement.querySelectorAll("li").forEach((item) => { + const inputElement = item.querySelector("input"); + if (inputElement) { + inputElement.remove(); + } + pHTML += `

${item.innerHTML.trimLeft()}

`; + }); + listElement.insertAdjacentHTML("beforebegin", pHTML); + listElement.remove(); +};