Skip to content

Commit

Permalink
fix #497
Browse files Browse the repository at this point in the history
  • Loading branch information
Vanessa219 committed Nov 27, 2020
1 parent 246ef17 commit 38f007a
Show file tree
Hide file tree
Showing 9 changed files with 173 additions and 106 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@
* 文档修改
* 3.7.0
* `preview` 静态方法添加 `mode` 配置
* 大纲 DOM 结构和 class 变更

### v3.6.6 / 2020-11-23

Expand Down
31 changes: 6 additions & 25 deletions demo/render.html
Original file line number Diff line number Diff line change
Expand Up @@ -71,39 +71,20 @@
overflow: auto;
font-size: 12px;
border-left: 1px solid var(--border-color);
border-right: 0;
--border-color: #eee;
--color: #616161;
--hover-color: #4285f4;
--toolbar-icon-hover-color: #4285f4;
--textarea-text-color: #616161;
--hover-background-color: #f6f8fa;
}

#outline.dark {
--border-color: #d1d5da;
--color: #a6aab0;
--hover-color: #fff;
--toolbar-icon-hover-color: #fff;
--textarea-text-color: #a6aab0;
--hover-background-color: #444d56;
}

#outline ul {
list-style: none !important;
padding-left: 1em;
margin: 0;
}

#outline li > span {
display: block;
padding: 5px 10px;
cursor: pointer;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
color: var(--color);
}

#outline li > span:hover {
color: var(--hover-color);
}

.vditor-reset ul[data-style="*"] {
list-style-type: disc
}
Expand Down Expand Up @@ -179,6 +160,6 @@
<div id="previewWrap">
<div id="preview" class="preview"></div>
</div>
<div id="outline"></div>
<div id="outline" class="vditor-outline"></div>
</body>
</html>
39 changes: 0 additions & 39 deletions src/assets/scss/_content.scss
Original file line number Diff line number Diff line change
Expand Up @@ -224,43 +224,4 @@
}
}
}

&-outline {
width: 250px;
border-right: 1px solid var(--border-color);
background-color: var(--panel-background-color);
display: none;
overflow: auto;

&::-webkit-scrollbar {
display: none;
}

ul {
list-style: none !important;
padding-left: 1em;
margin: 0;
}

li > span {
display: block;
padding: 5px 10px;
cursor: pointer;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
color: var(--textarea-text-color);

&:hover {
color: var(--toolbar-icon-hover-color);
}
}

&__title {
border-bottom: 1px dashed var(--border-color);
padding: 5px 10px;
color: var(--toolbar-icon-color);
font-size: 12px;
}
}
}
64 changes: 64 additions & 0 deletions src/assets/scss/_reset.scss
Original file line number Diff line number Diff line change
Expand Up @@ -498,13 +498,77 @@
user-select: text;
color: $blurColor;

.vditor-outline__action {
display: none;
}

ul {
list-style: none !important;
padding-left: 1em;
}

& > ul {
padding-left: 0;
}

span {
cursor: pointer;
}
}

&-outline {
width: 250px;
border-right: 1px solid var(--border-color);
background-color: var(--panel-background-color);
display: none;
overflow: auto;

&::-webkit-scrollbar {
display: none;
}

ul {
list-style: none !important;
padding-left: 1em;
margin: 0;
}

&__content > ul {
padding-left: 0;
}

li > span {
display: flex;
align-items: center;
padding: 5px 10px;
cursor: pointer;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
color: var(--textarea-text-color);

&:hover {
color: var(--toolbar-icon-hover-color);
}
}

&__title {
border-bottom: 1px dashed var(--border-color);
padding: 5px 10px;
color: var(--toolbar-icon-color);
font-size: 12px;
}

&__action {
transition: $transition;
height: 10px;
width: 10px;
fill: currentColor;
margin-right: 5px;

&--close {
transform: rotate(-90deg);
}
}
}
}
88 changes: 58 additions & 30 deletions src/ts/markdown/outlineRender.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,42 +3,68 @@ import {mathRender} from "./mathRender";

export const outlineRender = (contentElement: HTMLElement, targetElement: Element, vditor?: IVditor) => {
let tocHTML = "";
const ids: string[] = []
const ids: string[] = [];
Array.from(contentElement.children).forEach((item: HTMLElement, index: number) => {
if (hasClosestByHeadings(item)) {
const lastIndex = item.id.lastIndexOf("_");
item.id = item.id.substring(0, lastIndex === -1 ? undefined : lastIndex) + "_" + index;
if (vditor) {
const lastIndex = item.id.lastIndexOf("_");
item.id = item.id.substring(0, lastIndex === -1 ? undefined : lastIndex) + "_" + index;
}
ids.push(item.id);
tocHTML += item.outerHTML.replace("<wbr>", "");
}
});
if (tocHTML !== "") {
const tempElement = document.createElement("div");
if (vditor) {
if (vditor.currentMode === "wysiwyg") {
tempElement.innerHTML = vditor.lute.SpinVditorDOM("<p>[ToC]</p>" + tocHTML);
} else if (vditor.currentMode === "ir") {
tempElement.innerHTML = vditor.lute.SpinVditorIRDOM("<p>[ToC]</p>" + tocHTML);
}
if (tocHTML === "") {
return ""
}
const tempElement = document.createElement("div");
if (vditor) {
if (vditor.currentMode === "wysiwyg" && !vditor.preview.element.contains(contentElement)) {
tempElement.innerHTML = vditor.lute.SpinVditorDOM("<p>[ToC]</p>" + tocHTML);
} else if (vditor.currentMode === "ir" && !vditor.preview.element.contains(contentElement)) {
tempElement.innerHTML = vditor.lute.SpinVditorIRDOM("<p>[ToC]</p>" + tocHTML);
} else {
const lute = Lute.New();
lute.SetToC(true);
tempElement.innerHTML = lute.HTML2VditorDOM("<p>[ToC]</p>" + tocHTML);
tempElement.innerHTML = vditor.lute.HTML2VditorDOM("<p>[ToC]</p>" + tocHTML);
}
tempElement.firstElementChild.querySelectorAll("li > span[data-target-id]").forEach((item, index) => {
item.setAttribute("data-target-id", ids[index]);
});
tocHTML = tempElement.firstElementChild.innerHTML;
targetElement.innerHTML = tocHTML;
if (vditor) {
mathRender(targetElement as HTMLElement, {
cdn: vditor.options.cdn,
math: vditor.options.preview.math,
});
} else {
const lute = Lute.New();
lute.SetToC(true);
tempElement.innerHTML = lute.HTML2VditorDOM("<p>[ToC]</p>" + tocHTML);
}
tempElement.firstElementChild.querySelectorAll("li > span[data-target-id]").forEach((item, index) => {
if (item.nextElementSibling && item.nextElementSibling.tagName === "UL") {
item.insertAdjacentHTML("afterbegin", "<svg class='vditor-outline__action'><use xlink:href='#vditor-icon-down'></use></svg>")
} else {
item.insertAdjacentHTML("afterbegin", "<svg class='vditor-outline__action'></svg>")
}
targetElement.querySelectorAll("li > span").forEach((item) => {
item.addEventListener("click", (event: Event & { target: HTMLElement }) => {
const idElement = document.getElementById(item.getAttribute("data-target-id"));
item.setAttribute("data-target-id", ids[index]);
});
tocHTML = tempElement.firstElementChild.innerHTML;
targetElement.innerHTML = tocHTML;
if (vditor) {
mathRender(targetElement as HTMLElement, {
cdn: vditor.options.cdn,
math: vditor.options.preview.math,
});
}
targetElement.firstElementChild.addEventListener("click", (event: Event) => {
let target = event.target as HTMLElement;
while (target && !target.isEqualNode(targetElement)) {
if (target.classList.contains("vditor-outline__action")) {
if (target.classList.contains("vditor-outline__action--close")) {
target.classList.remove("vditor-outline__action--close");
target.parentElement.nextElementSibling.setAttribute("style", "display:block");
} else {
target.classList.add("vditor-outline__action--close");
target.parentElement.nextElementSibling.setAttribute("style", "display:none");
}
event.preventDefault();
event.stopPropagation();
break;
} else if (target.getAttribute("data-target-id")) {
event.preventDefault();
event.stopPropagation();
const idElement = document.getElementById(target.getAttribute("data-target-id"));
if (!idElement) {
return;
}
Expand All @@ -62,8 +88,10 @@ export const outlineRender = (contentElement: HTMLElement, targetElement: Elemen
} else {
window.scrollTo(window.scrollX, idElement.offsetTop);
}
});
});
}
break;
}
target = target.parentElement;
}
});
return tocHTML;
};
11 changes: 11 additions & 0 deletions src/ts/markdown/previewRender.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {mermaidRender} from "./mermaidRender";
import {mindmapRender} from "./mindmapRender";
import {setLute} from "./setLute";
import {speechRender} from "./speechRender";
import {hasClosestByClassName, hasClosestByMatchTag} from "../util/hasClosest";

const mergeOptions = (options?: IPreviewOptions) => {
const defaultOption: IPreviewOptions = {
Expand Down Expand Up @@ -111,4 +112,14 @@ export const previewRender = async (previewElement: HTMLDivElement, markdown: st
if (mergedOptions.icon) {
addScript(`${mergedOptions.cdn}/dist/js/icons/${mergedOptions.icon}.js`, "vditorIconScript");
}
previewElement.addEventListener("click", (event: MouseEvent & { target: HTMLElement }) => {
const spanElement = hasClosestByMatchTag(event.target, "SPAN");
if (spanElement && hasClosestByClassName(spanElement, "vditor-toc")) {
const headingElement = previewElement.querySelector("#" + spanElement.getAttribute("data-target-id")) as HTMLElement;
if (headingElement) {
window.scrollTo(window.scrollX, headingElement.offsetTop);
}
return;
}
})
};
32 changes: 28 additions & 4 deletions src/ts/preview/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {mindmapRender} from "../markdown/mindmapRender";
import {getEventName} from "../util/compatibility";
import {hasClosestByTag} from "../util/hasClosestByHeadings";
import {setSelectionFocus} from "../util/selection";
import {hasClosestByClassName, hasClosestByMatchTag} from "../util/hasClosest";

export class Preview {
public element: HTMLElement;
Expand All @@ -36,6 +37,16 @@ export class Preview {
this.copyToX(vditor, tempElement);
event.preventDefault();
});
previewElement.addEventListener("click", (event: MouseEvent & { target: HTMLElement }) => {
const spanElement = hasClosestByMatchTag(event.target, "SPAN");
if (spanElement && hasClosestByClassName(spanElement, "vditor-toc")) {
const headingElement = previewElement.querySelector("#" + spanElement.getAttribute("data-target-id")) as HTMLElement;
if (headingElement) {
this.element.scrollTop = headingElement.offsetTop;
}
return;
}
})

const actions = vditor.options.preview.actions;
const actionElement = document.createElement("div");
Expand Down Expand Up @@ -189,17 +200,30 @@ export class Preview {
codeRender(vditor.preview.element.lastElementChild as HTMLElement, vditor.options.lang);
highlightRender(vditor.options.preview.hljs, vditor.preview.element.lastElementChild as HTMLElement,
vditor.options.cdn);
mathRender(vditor.preview.element.lastElementChild as HTMLElement, {
cdn: vditor.options.cdn,
math: vditor.options.preview.math,
});
mermaidRender(vditor.preview.element.lastElementChild as HTMLElement, vditor.options.cdn, vditor.options.theme);
flowchartRender(vditor.preview.element.lastElementChild as HTMLElement, vditor.options.cdn);
graphvizRender(vditor.preview.element.lastElementChild as HTMLElement, vditor.options.cdn);
chartRender(vditor.preview.element.lastElementChild as HTMLElement, vditor.options.cdn, vditor.options.theme);
mindmapRender(vditor.preview.element.lastElementChild as HTMLElement, vditor.options.cdn, vditor.options.theme);
abcRender(vditor.preview.element.lastElementChild as HTMLElement, vditor.options.cdn);
mediaRender(vditor.preview.element.lastElementChild as HTMLElement);
// toc render
const editorElement = vditor.preview.element;
let tocHTML = vditor.outline.render(vditor);
if (tocHTML === "") {
tocHTML = "[ToC]";
}
editorElement.querySelectorAll('[data-type="toc-block"]').forEach((item: HTMLElement) => {
item.innerHTML = tocHTML;
mathRender(item, {
cdn: vditor.options.cdn,
math: vditor.options.preview.math,
});
});
mathRender(vditor.preview.element.lastElementChild as HTMLElement, {
cdn: vditor.options.cdn,
math: vditor.options.preview.math,
});
}

private copyToX(vditor: IVditor, copyElement: HTMLElement, type = "mp-wechat") {
Expand Down
4 changes: 3 additions & 1 deletion src/ts/util/toc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import {getSelectPosition} from "./selection";
import {execAfterRender, insertAfterBlock, insertBeforeBlock} from "./fixBrowserBehavior";

export const renderToc = (vditor: IVditor) => {
if (vditor.currentMode === "sv") {
return;
}
const editorElement = vditor[vditor.currentMode].element;
let tocHTML = vditor.outline.render(vditor);
if (tocHTML === "") {
Expand All @@ -19,7 +22,6 @@ export const renderToc = (vditor: IVditor) => {
};

export const clickToc = (event: MouseEvent & { target: HTMLElement }, vditor: IVditor) => {
// TOC 点击
const spanElement = hasClosestByMatchTag(event.target, "SPAN");
if (spanElement && hasClosestByClassName(spanElement, "vditor-toc")) {
const headingElement = vditor[vditor.currentMode].element.querySelector("#" + spanElement.getAttribute("data-target-id")) as HTMLElement;
Expand Down
Loading

2 comments on commit 38f007a

@cweijan
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个提交导致大纲解析失败.

@Vanessa219
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

非常抱歉,3.7.0 稍后发布再试。

Please sign in to comment.