vditor 3.8.12 → 3.8.15

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.
Files changed (35) hide show
  1. package/README.md +2 -2
  2. package/dist/index.css +1807 -2
  3. package/dist/index.d.ts +1 -1
  4. package/dist/index.min.js +1 -1
  5. package/dist/js/highlight.js/solidity.min.js +73 -0
  6. package/dist/js/highlight.js/yul.min.js +30 -0
  7. package/dist/js/lute/lute.min.js +47 -47
  8. package/dist/method.min.js +1 -1
  9. package/dist/types/index.d.ts +2 -0
  10. package/package.json +14 -7
  11. package/src/assets/{scss/_content.scss → less/_content.less} +8 -9
  12. package/src/assets/{scss/_hint.scss → less/_hint.less} +0 -0
  13. package/src/assets/{scss/_ir.scss → less/_ir.less} +4 -4
  14. package/src/assets/{scss/_panel.scss → less/_panel.less} +4 -4
  15. package/src/assets/{scss/_reset.scss → less/_reset.less} +13 -13
  16. package/src/assets/{scss/_sv.scss → less/_sv.less} +1 -2
  17. package/src/assets/{scss/_toolbar.scss → less/_toolbar.less} +3 -3
  18. package/src/assets/{scss/_tooltipped.scss → less/_tooltipped.less} +15 -15
  19. package/src/assets/{scss/_wysiwyg.scss → less/_wysiwyg.less} +3 -3
  20. package/src/assets/{scss/index.scss → less/index.less} +27 -22
  21. package/src/index.ts +6 -3
  22. package/src/ts/constants.ts +59 -56
  23. package/src/ts/ir/index.ts +5 -0
  24. package/src/ts/markdown/highlightRender.ts +65 -61
  25. package/src/ts/sv/index.ts +6 -0
  26. package/src/ts/tip/index.ts +13 -5
  27. package/src/ts/toolbar/Info.ts +1 -1
  28. package/src/ts/ui/initUI.ts +159 -151
  29. package/src/ts/ui/setContentTheme.ts +1 -1
  30. package/src/ts/upload/index.ts +3 -0
  31. package/src/ts/util/Options.ts +5 -0
  32. package/src/ts/util/editorCommonEvent.ts +2 -2
  33. package/src/ts/util/fixBrowserBehavior.ts +30 -2
  34. package/src/ts/wysiwyg/highlightToolbarWYSIWYG.ts +4 -0
  35. package/src/ts/wysiwyg/index.ts +2 -0
@@ -6,173 +6,181 @@ import {setContentTheme} from "./setContentTheme";
6
6
  import {setTheme} from "./setTheme";
7
7
 
8
8
  declare global {
9
- interface Window {
10
- visualViewport: HTMLElement;
11
- }
9
+ interface Window {
10
+ visualViewport: HTMLElement;
11
+ }
12
12
  }
13
13
 
14
14
  export const initUI = (vditor: IVditor) => {
15
- vditor.element.innerHTML = "";
16
- vditor.element.classList.add("vditor");
17
- setTheme(vditor);
18
- setContentTheme(vditor.options.preview.theme.current, vditor.options.preview.theme.path);
19
- if (typeof vditor.options.height === "number") {
20
- vditor.element.style.height = vditor.options.height + "px";
21
- }
22
- if (typeof vditor.options.minHeight === "number") {
23
- vditor.element.style.minHeight = vditor.options.minHeight + "px";
24
- }
25
- if (typeof vditor.options.width === "number") {
26
- vditor.element.style.width = vditor.options.width + "px";
27
- } else {
28
- vditor.element.style.width = vditor.options.width;
29
- }
30
-
31
- vditor.element.appendChild(vditor.toolbar.element);
32
-
33
- const contentElement = document.createElement("div");
34
- contentElement.className = "vditor-content";
35
-
36
- if (vditor.options.outline.position === "left") {
37
- contentElement.appendChild(vditor.outline.element);
38
- }
39
-
40
- contentElement.appendChild(vditor.wysiwyg.element.parentElement);
41
-
42
- contentElement.appendChild(vditor.sv.element);
43
-
44
- contentElement.appendChild(vditor.ir.element.parentElement);
45
-
46
- contentElement.appendChild(vditor.preview.element);
47
-
48
- if (vditor.toolbar.elements.devtools) {
49
- contentElement.appendChild(vditor.devtools.element);
50
- }
51
-
52
- if (vditor.options.outline.position === "right") {
53
- vditor.outline.element.classList.add("vditor-outline--right");
54
- contentElement.appendChild(vditor.outline.element);
55
- }
56
-
57
- if (vditor.upload) {
58
- contentElement.appendChild(vditor.upload.element);
59
- }
60
-
61
- if (vditor.options.resize.enable) {
62
- contentElement.appendChild(vditor.resize.element);
63
- }
64
-
65
- contentElement.appendChild(vditor.hint.element);
66
-
67
- contentElement.appendChild(vditor.tip.element);
68
-
69
- vditor.element.appendChild(contentElement);
70
-
71
- contentElement.addEventListener("click", () => {
72
- hidePanel(vditor, ["subToolbar"]);
73
- });
74
-
75
- if (vditor.toolbar.elements.export) {
76
- // for export pdf
77
- vditor.element.insertAdjacentHTML("beforeend",
78
- '<iframe style="width: 100%;height: 0;border: 0"></iframe>');
79
- }
80
-
81
- setEditMode(vditor, vditor.options.mode, afterRender(vditor));
82
-
83
- document.execCommand("DefaultParagraphSeparator", false, "p");
84
-
85
- if (navigator.userAgent.indexOf("iPhone") > -1 && typeof window.visualViewport !== "undefined") {
86
- // https://github.com/Vanessa219/vditor/issues/379
87
- let pendingUpdate = false;
88
- const viewportHandler = (event: Event) => {
89
- if (pendingUpdate) {
90
- return;
91
- }
92
- pendingUpdate = true;
93
-
94
- requestAnimationFrame(() => {
95
- pendingUpdate = false;
96
- const layoutViewport = vditor.toolbar.element;
97
- layoutViewport.style.transform = "none";
98
- if (layoutViewport.getBoundingClientRect().top < 0) {
99
- layoutViewport.style.transform = `translate(0, ${-layoutViewport.getBoundingClientRect().top}px)`;
100
- }
101
- });
102
- };
103
- window.visualViewport.addEventListener("scroll", viewportHandler);
104
- window.visualViewport.addEventListener("resize", viewportHandler);
105
- }
15
+ vditor.element.innerHTML = "";
16
+ vditor.element.classList.add("vditor");
17
+ // 支持 RTL
18
+ if (vditor.options.rtl) {
19
+ vditor.element.setAttribute("dir", "rtl")
20
+ }
21
+ setTheme(vditor);
22
+ setContentTheme(vditor.options.preview.theme.current, vditor.options.preview.theme.path);
23
+ if (typeof vditor.options.height === "number") {
24
+ vditor.element.style.height = vditor.options.height + "px";
25
+ } else {
26
+ vditor.element.style.height = vditor.options.height;
27
+ }
28
+ if (typeof vditor.options.minHeight === "number") {
29
+ vditor.element.style.minHeight = vditor.options.minHeight + "px";
30
+ }
31
+ if (typeof vditor.options.width === "number") {
32
+ vditor.element.style.width = vditor.options.width + "px";
33
+ } else {
34
+ vditor.element.style.width = vditor.options.width;
35
+ }
36
+
37
+ vditor.element.appendChild(vditor.toolbar.element);
38
+
39
+ const contentElement = document.createElement("div");
40
+ contentElement.className = "vditor-content";
41
+
42
+ if (vditor.options.outline.position === "left") {
43
+ contentElement.appendChild(vditor.outline.element);
44
+ }
45
+
46
+ contentElement.appendChild(vditor.wysiwyg.element.parentElement);
47
+
48
+ contentElement.appendChild(vditor.sv.element);
49
+
50
+ contentElement.appendChild(vditor.ir.element.parentElement);
51
+
52
+ contentElement.appendChild(vditor.preview.element);
53
+
54
+ if (vditor.toolbar.elements.devtools) {
55
+ contentElement.appendChild(vditor.devtools.element);
56
+ }
57
+
58
+ if (vditor.options.outline.position === "right") {
59
+ vditor.outline.element.classList.add("vditor-outline--right");
60
+ contentElement.appendChild(vditor.outline.element);
61
+ }
62
+
63
+ if (vditor.upload) {
64
+ contentElement.appendChild(vditor.upload.element);
65
+ }
66
+
67
+ if (vditor.options.resize.enable) {
68
+ contentElement.appendChild(vditor.resize.element);
69
+ }
70
+
71
+ contentElement.appendChild(vditor.hint.element);
72
+
73
+ contentElement.appendChild(vditor.tip.element);
74
+
75
+ vditor.element.appendChild(contentElement);
76
+
77
+ contentElement.addEventListener("click", () => {
78
+ hidePanel(vditor, ["subToolbar"]);
79
+ });
80
+
81
+ if (vditor.toolbar.elements.export) {
82
+ // for export pdf
83
+ vditor.element.insertAdjacentHTML("beforeend",
84
+ '<iframe style="width: 100%;height: 0;border: 0"></iframe>');
85
+ }
86
+
87
+ setEditMode(vditor, vditor.options.mode, afterRender(vditor));
88
+
89
+ document.execCommand("DefaultParagraphSeparator", false, "p");
90
+
91
+ if (navigator.userAgent.indexOf("iPhone") > -1 && typeof window.visualViewport !== "undefined") {
92
+ // https://github.com/Vanessa219/vditor/issues/379
93
+ let pendingUpdate = false;
94
+ const viewportHandler = (event: Event) => {
95
+ if (pendingUpdate) {
96
+ return;
97
+ }
98
+ pendingUpdate = true;
99
+
100
+ requestAnimationFrame(() => {
101
+ pendingUpdate = false;
102
+ const layoutViewport = vditor.toolbar.element;
103
+ layoutViewport.style.transform = "none";
104
+ if (layoutViewport.getBoundingClientRect().top < 0) {
105
+ layoutViewport.style.transform = `translate(0, ${-layoutViewport.getBoundingClientRect().top}px)`;
106
+ }
107
+ });
108
+ };
109
+ window.visualViewport.addEventListener("scroll", viewportHandler);
110
+ window.visualViewport.addEventListener("resize", viewportHandler);
111
+ }
106
112
  };
107
113
 
108
114
  export const setPadding = (vditor: IVditor) => {
109
- const minPadding = window.innerWidth <= Constants.MOBILE_WIDTH ? 10 : 35;
110
- if (vditor.wysiwyg.element.parentElement.style.display !== "none") {
111
- const padding = (vditor.wysiwyg.element.parentElement.clientWidth
112
- - vditor.options.preview.maxWidth) / 2;
113
- vditor.wysiwyg.element.style.padding = `10px ${Math.max(minPadding, padding)}px`;
114
- }
115
-
116
- if (vditor.ir.element.parentElement.style.display !== "none") {
117
- const padding = (vditor.ir.element.parentElement.clientWidth
118
- - vditor.options.preview.maxWidth) / 2;
119
- vditor.ir.element.style.padding = `10px ${Math.max(minPadding, padding)}px`;
120
- }
121
-
122
- if (vditor.preview.element.style.display !== "block") {
123
- vditor.toolbar.element.style.paddingLeft = Math.max(5,
124
- parseInt(vditor[vditor.currentMode].element.style.paddingLeft || "0", 10) +
125
- (vditor.options.outline.position === "left" ? vditor.outline.element.offsetWidth : 0)) + "px";
126
- } else {
127
- vditor.toolbar.element.style.paddingLeft = (5 +
128
- (vditor.options.outline.position === "left" ? vditor.outline.element.offsetWidth : 0)) + "px";
129
- }
115
+ const minPadding = window.innerWidth <= Constants.MOBILE_WIDTH ? 10 : 35;
116
+ if (vditor.wysiwyg.element.parentElement.style.display !== "none") {
117
+ const padding = (vditor.wysiwyg.element.parentElement.clientWidth
118
+ - vditor.options.preview.maxWidth) / 2;
119
+ vditor.wysiwyg.element.style.padding = `10px ${Math.max(minPadding, padding)}px`;
120
+ }
121
+
122
+ if (vditor.ir.element.parentElement.style.display !== "none") {
123
+ const padding = (vditor.ir.element.parentElement.clientWidth
124
+ - vditor.options.preview.maxWidth) / 2;
125
+ vditor.ir.element.style.padding = `10px ${Math.max(minPadding, padding)}px`;
126
+ }
127
+
128
+ if (vditor.preview.element.style.display !== "block") {
129
+ vditor.toolbar.element.style.paddingLeft = Math.max(5,
130
+ parseInt(vditor[vditor.currentMode].element.style.paddingLeft || "0", 10) +
131
+ (vditor.options.outline.position === "left" ? vditor.outline.element.offsetWidth : 0)) + "px";
132
+ } else {
133
+ vditor.toolbar.element.style.paddingLeft = (5 +
134
+ (vditor.options.outline.position === "left" ? vditor.outline.element.offsetWidth : 0)) + "px";
135
+ }
130
136
  };
131
137
 
132
138
  export const setTypewriterPosition = (vditor: IVditor) => {
133
- if (!vditor.options.typewriterMode) {
134
- return;
135
- }
136
- let height: number = window.innerHeight;
137
- if (typeof vditor.options.height === "number") {
138
- height = vditor.options.height;
139
- if (typeof vditor.options.minHeight === "number") {
140
- height = Math.max(height, vditor.options.minHeight);
141
- }
142
- height = Math.min(window.innerHeight, height);
143
- }
144
- if (vditor.element.classList.contains("vditor--fullscreen")) {
145
- height = window.innerHeight;
146
- }
147
- // 由于 Firefox padding-bottom bug,只能使用 :after
148
- vditor[vditor.currentMode].element.style.setProperty("--editor-bottom",
149
- ((height - vditor.toolbar.element.offsetHeight) / 2) + "px");
139
+ if (!vditor.options.typewriterMode) {
140
+ return;
141
+ }
142
+ let height: number = window.innerHeight;
143
+ if (typeof vditor.options.height === "number") {
144
+ height = vditor.options.height;
145
+ if (typeof vditor.options.minHeight === "number") {
146
+ height = Math.max(height, vditor.options.minHeight);
147
+ }
148
+ height = Math.min(window.innerHeight, height);
149
+ } else {
150
+ height = vditor.element.clientHeight;
151
+ }
152
+ if (vditor.element.classList.contains("vditor--fullscreen")) {
153
+ height = window.innerHeight;
154
+ }
155
+ // 由于 Firefox padding-bottom bug,只能使用 :after
156
+ vditor[vditor.currentMode].element.style.setProperty("--editor-bottom",
157
+ ((height - vditor.toolbar.element.offsetHeight) / 2) + "px");
150
158
  };
151
159
 
152
160
  let resizeCb: () => void;
153
161
 
154
162
  export function UIUnbindListener() {
155
- window.removeEventListener("resize", resizeCb);
163
+ window.removeEventListener("resize", resizeCb);
156
164
  }
157
165
 
158
166
  const afterRender = (vditor: IVditor) => {
167
+ setTypewriterPosition(vditor);
168
+ UIUnbindListener();
169
+ window.addEventListener("resize", resizeCb = () => {
170
+ setPadding(vditor);
159
171
  setTypewriterPosition(vditor);
160
- UIUnbindListener();
161
- window.addEventListener("resize", resizeCb = () => {
162
- setPadding(vditor);
163
- setTypewriterPosition(vditor);
164
- });
165
-
166
- // set default value
167
- let initValue = accessLocalStorage() && localStorage.getItem(vditor.options.cache.id);
168
- if (!vditor.options.cache.enable || !initValue) {
169
- if (vditor.options.value) {
170
- initValue = vditor.options.value;
171
- } else if (vditor.originalInnerHTML) {
172
- initValue = vditor.lute.HTML2Md(vditor.originalInnerHTML);
173
- } else if (!vditor.options.cache.enable) {
174
- initValue = "";
175
- }
176
- }
177
- return initValue || "";
172
+ });
173
+
174
+ // set default value
175
+ let initValue = accessLocalStorage() && localStorage.getItem(vditor.options.cache.id);
176
+ if (!vditor.options.cache.enable || !initValue) {
177
+ if (vditor.options.value) {
178
+ initValue = vditor.options.value;
179
+ } else if (vditor.originalInnerHTML) {
180
+ initValue = vditor.lute.HTML2Md(vditor.originalInnerHTML);
181
+ } else if (!vditor.options.cache.enable) {
182
+ initValue = "";
183
+ }
184
+ }
185
+ return initValue || "";
178
186
  };
@@ -8,7 +8,7 @@ export const setContentTheme = (contentTheme: string, path: string) => {
8
8
  const cssPath = `${path}/${contentTheme}.css`;
9
9
  if (!vditorContentTheme) {
10
10
  addStyle(cssPath, "vditorContentTheme");
11
- } else if (vditorContentTheme.href !== cssPath) {
11
+ } else if (vditorContentTheme.getAttribute("href") !== cssPath) {
12
12
  vditorContentTheme.remove();
13
13
  addStyle(cssPath, "vditorContentTheme");
14
14
  }
@@ -155,6 +155,9 @@ const uploadFiles =
155
155
 
156
156
  if (vditor.options.upload.handler) {
157
157
  const isValidate = await vditor.options.upload.handler(fileList);
158
+ if (element) {
159
+ element.value = "";
160
+ }
158
161
  if (typeof isValidate === "string") {
159
162
  vditor.tip.show(isValidate);
160
163
  return;
@@ -4,6 +4,7 @@ import { merge } from "./merge";
4
4
  export class Options {
5
5
  public options: IOptions;
6
6
  private defaultOptions: IOptions = {
7
+ rtl: false,
7
8
  after: undefined,
8
9
  cache: {
9
10
  enable: true,
@@ -148,6 +149,10 @@ export class Options {
148
149
  if (this.options.comment) {
149
150
  this.defaultOptions.comment = this.options.comment;
150
151
  }
152
+ // 支持不够完善,我先注释了,后期再打开
153
+ // if (this.options.rtl) {
154
+ // this.defaultOptions.rtl = this.options.rtl;
155
+ // }
151
156
  }
152
157
 
153
158
  const mergedOptions = merge(this.defaultOptions, this.options);
@@ -99,11 +99,11 @@ export const scrollCenter = (vditor: IVditor) => {
99
99
  }
100
100
  const editorElement = vditor[vditor.currentMode].element;
101
101
  const cursorTop = getCursorPosition(editorElement).top;
102
- if (typeof vditor.options.height === "string" && !vditor.element.classList.contains("vditor--fullscreen")) {
102
+ if (vditor.options.height === "auto" && !vditor.element.classList.contains("vditor--fullscreen")) {
103
103
  window.scrollTo(window.scrollX,
104
104
  cursorTop + vditor.element.offsetTop + vditor.toolbar.element.offsetHeight - window.innerHeight / 2 + 10);
105
105
  }
106
- if (typeof vditor.options.height === "number" || vditor.element.classList.contains("vditor--fullscreen")) {
106
+ if (vditor.options.height !== "auto" || vditor.element.classList.contains("vditor--fullscreen")) {
107
107
  editorElement.scrollTop = cursorTop + editorElement.scrollTop - editorElement.clientHeight / 2 + 10;
108
108
  }
109
109
  };
@@ -1252,11 +1252,15 @@ export const fixFirefoxArrowUpTable = (event: KeyboardEvent, blockElement: false
1252
1252
  export const paste = async (vditor: IVditor, event: (ClipboardEvent | DragEvent) & { target: HTMLElement }, callback: {
1253
1253
  pasteCode(code: string): void,
1254
1254
  }) => {
1255
+ if (vditor[vditor.currentMode].element.getAttribute("contenteditable") !== "true") {
1256
+ return;
1257
+ }
1255
1258
  event.stopPropagation();
1256
1259
  event.preventDefault();
1257
1260
  let textHTML;
1258
1261
  let textPlain;
1259
1262
  let files;
1263
+
1260
1264
  if ("clipboardData" in event) {
1261
1265
  textHTML = event.clipboardData.getData("text/html");
1262
1266
  textPlain = event.clipboardData.getData("text/plain");
@@ -1410,8 +1414,32 @@ export const paste = async (vditor: IVditor, event: (ClipboardEvent | DragEvent)
1410
1414
  processPaste(vditor, vditor.lute.HTML2Md(tempElement.innerHTML).trimRight());
1411
1415
  }
1412
1416
  vditor.outline.render(vditor);
1413
- } else if (files.length > 0 && (vditor.options.upload.url || vditor.options.upload.handler)) {
1414
- await uploadFiles(vditor, files);
1417
+ } else if (files.length > 0) {
1418
+ if (vditor.options.upload.url || vditor.options.upload.handler) {
1419
+ await uploadFiles(vditor, files);
1420
+ } else {
1421
+ const fileReader = new FileReader();
1422
+ let file: File;
1423
+ if ("clipboardData" in event) {
1424
+ files = event.clipboardData.files;
1425
+ file = files[0];
1426
+ } else if (event.dataTransfer.types.includes("Files")) {
1427
+ files = event.dataTransfer.items;
1428
+ file = files[0].getAsFile();
1429
+ }
1430
+ if (file && file.type.startsWith("image")) {
1431
+ fileReader.readAsDataURL(file);
1432
+ fileReader.onload = () => {
1433
+ let imgHTML = ''
1434
+ if (vditor.currentMode === "wysiwyg") {
1435
+ imgHTML += `<img alt="${file.name}" src="${fileReader.result.toString()}">\n`;
1436
+ } else {
1437
+ imgHTML += `![${file.name}](${fileReader.result.toString()})\n`;
1438
+ }
1439
+ document.execCommand("insertHTML", false, imgHTML);
1440
+ }
1441
+ }
1442
+ }
1415
1443
  } else if (textPlain.trim() !== "" && files.length === 0) {
1416
1444
  if (vditor.currentMode === "ir") {
1417
1445
  renderers.Md2VditorIRDOM = {renderLinkDest};
@@ -31,6 +31,7 @@ import {
31
31
  } from "../util/selection";
32
32
  import {afterRenderEvent} from "./afterRenderEvent";
33
33
  import {removeBlockElement} from "./processKeydown";
34
+ import {renderToc} from "../util/toc";
34
35
 
35
36
  export const highlightToolbarWYSIWYG = (vditor: IVditor) => {
36
37
  clearTimeout(vditor.wysiwyg.hlToolbarTimeoutId);
@@ -931,6 +932,9 @@ const genClose = (element: HTMLElement, vditor: IVditor) => {
931
932
  element.remove();
932
933
  afterRenderEvent(vditor);
933
934
  highlightToolbarWYSIWYG(vditor);
935
+ if (["H1", "H2", "H3", "H4", "H5" ,"H6"].includes(element.tagName)) {
936
+ renderToc(vditor);
937
+ }
934
938
  };
935
939
  vditor.wysiwyg.popover.insertAdjacentElement("beforeend", close);
936
940
  };
@@ -335,9 +335,11 @@ class WYSIWYG {
335
335
  }
336
336
  if (this.preventInput) {
337
337
  this.preventInput = false;
338
+ afterRenderEvent(vditor);
338
339
  return;
339
340
  }
340
341
  if (this.composingLock || event.data === "‘" || event.data === "“" || event.data === "《") {
342
+ afterRenderEvent(vditor);
341
343
  return;
342
344
  }
343
345
  const range = getSelection().getRangeAt(0);