@yltrcc/vditor 0.1.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.css +45 -6
- package/dist/index.js +385 -74
- package/dist/index.min.js +1 -1
- package/dist/method.js +56 -56
- package/dist/method.min.js +1 -1
- package/dist/ts/util/imageResize.d.ts +1 -0
- package/dist/ts/wysiwyg/renderDomByMd.d.ts +11 -0
- package/package.json +5 -2
- package/src/assets/less/_wysiwyg.less +314 -270
- package/src/index.ts +3 -0
- package/src/ts/markdown/getMarkdown.ts +107 -60
- package/src/ts/markdown/setLute.ts +26 -26
- package/src/ts/util/fixBrowserBehavior.ts +1570 -1569
- package/src/ts/util/imageResize.ts +166 -0
- package/src/ts/wysiwyg/highlightToolbarWYSIWYG.ts +1163 -1156
- package/src/ts/wysiwyg/index.ts +33 -2
- package/src/ts/wysiwyg/input.ts +13 -9
- package/src/ts/wysiwyg/renderDomByMd.ts +109 -1
- package/src/ts/wysiwyg/showCode.ts +9 -0
|
@@ -1,60 +1,107 @@
|
|
|
1
|
-
import {code160to32} from "../util/code160to32";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* 将 doclink DOM 元素转换回 Markdown 语法
|
|
5
|
-
* 处理 <span class="vditor-doclink-wrapper" data-doc-markdown="((id 'text'))">text</span>
|
|
6
|
-
*/
|
|
7
|
-
const processDocLinksInHTML = (html: string): string => {
|
|
8
|
-
// 创建临时 DOM 元素来解析 HTML
|
|
9
|
-
const tempDiv = document.createElement("div");
|
|
10
|
-
tempDiv.innerHTML = html;
|
|
11
|
-
|
|
12
|
-
// 查找所有 doclink wrapper 元素
|
|
13
|
-
const docLinkWrappers = tempDiv.querySelectorAll(".vditor-doclink-wrapper");
|
|
14
|
-
docLinkWrappers.forEach((wrapper) => {
|
|
15
|
-
const markdown = wrapper.getAttribute("data-doc-markdown");
|
|
16
|
-
if (markdown) {
|
|
17
|
-
// 用文本节点替换整个 wrapper,内容为 Markdown 语法
|
|
18
|
-
wrapper.replaceWith(document.createTextNode(markdown));
|
|
19
|
-
} else {
|
|
20
|
-
// 如果没有 data-doc-markdown,尝试从 data-doc-id 和 data-doc-text 重建
|
|
21
|
-
const id = wrapper.getAttribute("data-doc-id");
|
|
22
|
-
const text = wrapper.getAttribute("data-doc-text");
|
|
23
|
-
if (id && text) {
|
|
24
|
-
wrapper.replaceWith(document.createTextNode(`((${id} '${text}'))`));
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
// 也处理旧的 .vditor-doclink 元素(没有 wrapper 的情况)
|
|
30
|
-
const docLinks = tempDiv.querySelectorAll(".vditor-doclink");
|
|
31
|
-
docLinks.forEach((link) => {
|
|
32
|
-
const markdown = link.getAttribute("data-doc-markdown");
|
|
33
|
-
if (markdown) {
|
|
34
|
-
link.replaceWith(document.createTextNode(markdown));
|
|
35
|
-
} else {
|
|
36
|
-
const id = link.getAttribute("data-doc-id");
|
|
37
|
-
const text = link.getAttribute("data-doc-text");
|
|
38
|
-
if (id && text) {
|
|
39
|
-
link.replaceWith(document.createTextNode(`((${id} '${text}'))`));
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
return tempDiv.innerHTML;
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
1
|
+
import {code160to32} from "../util/code160to32";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 将 doclink DOM 元素转换回 Markdown 语法
|
|
5
|
+
* 处理 <span class="vditor-doclink-wrapper" data-doc-markdown="((id 'text'))">text</span>
|
|
6
|
+
*/
|
|
7
|
+
const processDocLinksInHTML = (html: string): string => {
|
|
8
|
+
// 创建临时 DOM 元素来解析 HTML
|
|
9
|
+
const tempDiv = document.createElement("div");
|
|
10
|
+
tempDiv.innerHTML = html;
|
|
11
|
+
|
|
12
|
+
// 查找所有 doclink wrapper 元素
|
|
13
|
+
const docLinkWrappers = tempDiv.querySelectorAll(".vditor-doclink-wrapper");
|
|
14
|
+
docLinkWrappers.forEach((wrapper) => {
|
|
15
|
+
const markdown = wrapper.getAttribute("data-doc-markdown");
|
|
16
|
+
if (markdown) {
|
|
17
|
+
// 用文本节点替换整个 wrapper,内容为 Markdown 语法
|
|
18
|
+
wrapper.replaceWith(document.createTextNode(markdown));
|
|
19
|
+
} else {
|
|
20
|
+
// 如果没有 data-doc-markdown,尝试从 data-doc-id 和 data-doc-text 重建
|
|
21
|
+
const id = wrapper.getAttribute("data-doc-id");
|
|
22
|
+
const text = wrapper.getAttribute("data-doc-text");
|
|
23
|
+
if (id && text) {
|
|
24
|
+
wrapper.replaceWith(document.createTextNode(`((${id} '${text}'))`));
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
// 也处理旧的 .vditor-doclink 元素(没有 wrapper 的情况)
|
|
30
|
+
const docLinks = tempDiv.querySelectorAll(".vditor-doclink");
|
|
31
|
+
docLinks.forEach((link) => {
|
|
32
|
+
const markdown = link.getAttribute("data-doc-markdown");
|
|
33
|
+
if (markdown) {
|
|
34
|
+
link.replaceWith(document.createTextNode(markdown));
|
|
35
|
+
} else {
|
|
36
|
+
const id = link.getAttribute("data-doc-id");
|
|
37
|
+
const text = link.getAttribute("data-doc-text");
|
|
38
|
+
if (id && text) {
|
|
39
|
+
link.replaceWith(document.createTextNode(`((${id} '${text}'))`));
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
return tempDiv.innerHTML;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* 处理图片尺寸,将带 width/height 属性的图片转换为 Markdown 语法
|
|
49
|
+
* 支持: 
|
|
50
|
+
*/
|
|
51
|
+
const processImageSizeInHTML = (html: string): string => {
|
|
52
|
+
const tempDiv = document.createElement("div");
|
|
53
|
+
tempDiv.innerHTML = html;
|
|
54
|
+
|
|
55
|
+
// 查找所有带有 data-resizable="true" 标记的图片元素
|
|
56
|
+
const images = tempDiv.querySelectorAll('img[data-resizable="true"]');
|
|
57
|
+
images.forEach((imgElement) => {
|
|
58
|
+
const img = imgElement as HTMLImageElement;
|
|
59
|
+
const src = img.getAttribute("src") || "";
|
|
60
|
+
const alt = img.getAttribute("alt") || "";
|
|
61
|
+
|
|
62
|
+
// 获取尺寸 - 优先从 attribute 获取
|
|
63
|
+
let width = img.getAttribute("width") || "";
|
|
64
|
+
let height = img.getAttribute("height") || "";
|
|
65
|
+
|
|
66
|
+
// 如果 attribute 没有或为空,尝试从 style 获取
|
|
67
|
+
if (!width && img.style.width) {
|
|
68
|
+
width = img.style.width.replace("px", "").replace("%", "");
|
|
69
|
+
}
|
|
70
|
+
if (!height && img.style.height) {
|
|
71
|
+
height = img.style.height.replace("px", "").replace("%", "");
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// 构建带尺寸的 Markdown 语法: 
|
|
75
|
+
if (width && height) {
|
|
76
|
+
const md = ``;
|
|
77
|
+
// 用 Markdown 文本替换图片元素
|
|
78
|
+
img.replaceWith(document.createTextNode(md));
|
|
79
|
+
} else if (width) {
|
|
80
|
+
const md = ``;
|
|
81
|
+
img.replaceWith(document.createTextNode(md));
|
|
82
|
+
} else if (height) {
|
|
83
|
+
const md = ``;
|
|
84
|
+
img.replaceWith(document.createTextNode(md));
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
return tempDiv.innerHTML;
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
export const getMarkdown = (vditor: IVditor) => {
|
|
92
|
+
if (vditor.currentMode === "sv") {
|
|
93
|
+
return code160to32(`${vditor.sv.element.textContent}\n`.replace(/\n\n$/, "\n"));
|
|
94
|
+
} else if (vditor.currentMode === "wysiwyg") {
|
|
95
|
+
// 先处理图片尺寸 - 必须在处理 doclink 之前
|
|
96
|
+
let processedHTML = processImageSizeInHTML(vditor.wysiwyg.element.innerHTML);
|
|
97
|
+
// 再处理 doclink 元素
|
|
98
|
+
processedHTML = processDocLinksInHTML(processedHTML);
|
|
99
|
+
return vditor.lute.VditorDOM2Md(processedHTML);
|
|
100
|
+
} else if (vditor.currentMode === "ir") {
|
|
101
|
+
// 同样处理 IR 模式
|
|
102
|
+
let processedHTML = processImageSizeInHTML(vditor.ir.element.innerHTML);
|
|
103
|
+
processedHTML = processDocLinksInHTML(processedHTML);
|
|
104
|
+
return vditor.lute.VditorIRDOM2Md(processedHTML);
|
|
105
|
+
}
|
|
106
|
+
return "";
|
|
107
|
+
};
|
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
export const setLute = (options: ILuteOptions) => {
|
|
2
|
-
const lute: Lute = Lute.New();
|
|
3
|
-
lute.PutEmojis(options.emojis);
|
|
4
|
-
lute.SetEmojiSite(options.emojiSite);
|
|
5
|
-
lute.SetHeadingAnchor(options.headingAnchor);
|
|
6
|
-
lute.SetInlineMathAllowDigitAfterOpenMarker(options.inlineMathDigit);
|
|
7
|
-
lute.SetAutoSpace(options.autoSpace);
|
|
8
|
-
lute.SetToC(options.toc);
|
|
9
|
-
lute.SetFootnotes(options.footnotes);
|
|
10
|
-
lute.SetFixTermTypo(options.fixTermTypo);
|
|
11
|
-
lute.SetVditorCodeBlockPreview(options.codeBlockPreview);
|
|
12
|
-
lute.SetVditorMathBlockPreview(options.mathBlockPreview);
|
|
13
|
-
lute.SetSanitize(options.sanitize);
|
|
14
|
-
lute.SetChineseParagraphBeginningSpace(options.paragraphBeginningSpace);
|
|
15
|
-
lute.SetRenderListStyle(options.listStyle);
|
|
16
|
-
lute.SetLinkBase(options.linkBase);
|
|
17
|
-
lute.SetLinkPrefix(options.linkPrefix);
|
|
18
|
-
lute.SetMark(options.mark);
|
|
19
|
-
lute.SetGFMAutoLink(options.gfmAutoLink);
|
|
20
|
-
if (options.lazyLoadImage) {
|
|
21
|
-
lute.SetImageLazyLoading(options.lazyLoadImage);
|
|
22
|
-
}
|
|
23
|
-
lute.SetSup(options.sup);
|
|
24
|
-
lute.SetSub(options.sub);
|
|
25
|
-
return lute;
|
|
26
|
-
};
|
|
1
|
+
export const setLute = (options: ILuteOptions) => {
|
|
2
|
+
const lute: Lute = Lute.New();
|
|
3
|
+
lute.PutEmojis(options.emojis);
|
|
4
|
+
lute.SetEmojiSite(options.emojiSite);
|
|
5
|
+
lute.SetHeadingAnchor(options.headingAnchor);
|
|
6
|
+
lute.SetInlineMathAllowDigitAfterOpenMarker(options.inlineMathDigit);
|
|
7
|
+
lute.SetAutoSpace(options.autoSpace);
|
|
8
|
+
lute.SetToC(options.toc);
|
|
9
|
+
lute.SetFootnotes(options.footnotes);
|
|
10
|
+
lute.SetFixTermTypo(options.fixTermTypo);
|
|
11
|
+
lute.SetVditorCodeBlockPreview(options.codeBlockPreview);
|
|
12
|
+
lute.SetVditorMathBlockPreview(options.mathBlockPreview);
|
|
13
|
+
lute.SetSanitize(options.sanitize);
|
|
14
|
+
lute.SetChineseParagraphBeginningSpace(options.paragraphBeginningSpace);
|
|
15
|
+
lute.SetRenderListStyle(options.listStyle);
|
|
16
|
+
lute.SetLinkBase(options.linkBase);
|
|
17
|
+
lute.SetLinkPrefix(options.linkPrefix);
|
|
18
|
+
lute.SetMark(options.mark);
|
|
19
|
+
lute.SetGFMAutoLink(options.gfmAutoLink);
|
|
20
|
+
if (options.lazyLoadImage) {
|
|
21
|
+
lute.SetImageLazyLoading(options.lazyLoadImage);
|
|
22
|
+
}
|
|
23
|
+
lute.SetSup(options.sup);
|
|
24
|
+
lute.SetSub(options.sub);
|
|
25
|
+
return lute;
|
|
26
|
+
};
|