suneditor 3.0.0-alpha.13 → 3.0.0-alpha.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.
- package/dist/suneditor.min.css +1 -1
- package/dist/suneditor.min.js +1 -1
- package/package.json +2 -1
- package/src/assets/icons/_default.js +9 -2
- package/src/assets/suneditor-contents.css +9 -22
- package/src/assets/suneditor.css +317 -183
- package/src/assets/variables.css +137 -0
- package/src/core/base/eventHandlers/handler_toolbar.js +1 -0
- package/src/core/base/eventHandlers/handler_ww_dragDrop.js +9 -2
- package/src/core/base/eventHandlers/handler_ww_key_input.js +1 -1
- package/src/core/base/eventManager.js +5 -0
- package/src/core/class/component.js +12 -8
- package/src/core/class/html.js +5 -5
- package/src/core/class/offset.js +11 -3
- package/src/core/class/selection.js +5 -4
- package/src/core/class/toolbar.js +1 -5
- package/src/core/class/viewer.js +29 -7
- package/src/core/editor.js +61 -1
- package/src/core/section/actives.js +5 -0
- package/src/core/section/constructor.js +35 -19
- package/src/core/section/documentType.js +143 -19
- package/src/helper/domUtils.js +5 -4
- package/src/langs/en.js +5 -0
- package/src/modules/Modal.js +108 -1
- package/src/plugins/command/exportPdf.js +1 -1
- package/src/plugins/command/list_bulleted.js +1 -1
- package/src/plugins/command/list_numbered.js +1 -1
- package/src/plugins/index.js +6 -0
- package/src/plugins/input/fontSize.js +3 -3
- package/src/plugins/input/pageNavigator.js +47 -0
- package/src/plugins/modal/drawing.js +426 -0
- package/src/plugins/modal/image.js +3 -2
- package/src/plugins/modal/math.js +72 -34
- package/src/themes/dark-variables.css +85 -0
- package/src/themes/test.css +0 -61
|
@@ -109,18 +109,18 @@ const FontSize = function (editor, pluginOptions) {
|
|
|
109
109
|
|
|
110
110
|
// increase, decrease buttons
|
|
111
111
|
if (showIncDec) {
|
|
112
|
-
this.
|
|
112
|
+
this.beforeItem = domUtils.createElement(
|
|
113
113
|
'button',
|
|
114
114
|
{ class: 'se-btn se-tooltip se-sub-btn', 'data-command': FontSize.key, 'data-type': 'command', 'data-value': 'dec' },
|
|
115
115
|
`${this.icons.minus}<span class="se-tooltip-inner"><span class="se-tooltip-text">${this.lang.decrease}</span></span>`
|
|
116
116
|
);
|
|
117
|
-
this.
|
|
117
|
+
this.afterItem = domUtils.createElement(
|
|
118
118
|
'button',
|
|
119
119
|
{ class: 'se-btn se-tooltip se-sub-btn', 'data-command': FontSize.key, 'data-type': 'command', 'data-value': 'inc' },
|
|
120
120
|
`${this.icons.plus}<span class="se-tooltip-inner"><span class="se-tooltip-text">${this.lang.increase}</span></span>`
|
|
121
121
|
);
|
|
122
122
|
} else if (!disableInput) {
|
|
123
|
-
this.
|
|
123
|
+
this.afterItem = domUtils.createElement(
|
|
124
124
|
'button',
|
|
125
125
|
{ class: 'se-btn se-tooltip se-sub-arrow-btn', 'data-command': FontSize.key, 'data-type': 'dropdown' },
|
|
126
126
|
`${this.icons.arrow_down}<span class="se-tooltip-inner"><span class="se-tooltip-text">${this.lang.fontSize}</span></span>`
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import EditorInjector from '../../editorInjector';
|
|
2
|
+
import { domUtils } from '../../helper';
|
|
3
|
+
|
|
4
|
+
const PageNavigator = function (editor) {
|
|
5
|
+
EditorInjector.call(this, editor);
|
|
6
|
+
|
|
7
|
+
// create HTML
|
|
8
|
+
this.title = this.lang.pageNumber;
|
|
9
|
+
this.inner = CreateInner();
|
|
10
|
+
this.afterItem = domUtils.createElement('span', { class: 'se-btn se-sub-btn' }, ``);
|
|
11
|
+
|
|
12
|
+
// members
|
|
13
|
+
this.pageNum = 1;
|
|
14
|
+
this.totalPages = 1;
|
|
15
|
+
|
|
16
|
+
// init
|
|
17
|
+
this.eventManager.addEvent(this.inner, 'change', OnChangeInner.bind(this));
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
PageNavigator.key = 'pageNavigator';
|
|
21
|
+
PageNavigator.type = 'input';
|
|
22
|
+
PageNavigator.className = 'se-btn-input se-btn-tool-pageNavigator';
|
|
23
|
+
PageNavigator.prototype = {
|
|
24
|
+
/**
|
|
25
|
+
* @override core
|
|
26
|
+
*/
|
|
27
|
+
display(pageNum, totalPages) {
|
|
28
|
+
this.inner.value = this.pageNum = pageNum;
|
|
29
|
+
this.afterItem.textContent = this.totalPages = totalPages;
|
|
30
|
+
this.inner.max = totalPages;
|
|
31
|
+
},
|
|
32
|
+
|
|
33
|
+
constructor: PageNavigator
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
function OnChangeInner({ target }) {
|
|
37
|
+
if (!this.editor.frameContext.has('documentType-use-page')) return;
|
|
38
|
+
|
|
39
|
+
const value = target.value || 1;
|
|
40
|
+
this.editor.frameContext.get('documentType').pageGo(value);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function CreateInner() {
|
|
44
|
+
return domUtils.createElement('input', { type: 'number', class: 'se-not-arrow-text', placeholder: '1', value: '1', min: '1' }, null);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export default PageNavigator;
|
|
@@ -0,0 +1,426 @@
|
|
|
1
|
+
import EditorInjector from '../../editorInjector';
|
|
2
|
+
import { Modal } from '../../modules';
|
|
3
|
+
import { domUtils, env } from '../../helper';
|
|
4
|
+
import { CreateTooltipInner } from '../../core/section/constructor';
|
|
5
|
+
|
|
6
|
+
const { _w, isMobile } = env;
|
|
7
|
+
|
|
8
|
+
const Drawing = function (editor, pluginOptions) {
|
|
9
|
+
// plugin basic properties
|
|
10
|
+
EditorInjector.call(this, editor);
|
|
11
|
+
this.title = this.lang.drawing;
|
|
12
|
+
this.icon = 'drawing';
|
|
13
|
+
this.pluginOptions = {
|
|
14
|
+
outputFormat: pluginOptions.outputFormat || 'dataurl', // dataurl, svg
|
|
15
|
+
useFormatType: pluginOptions.useFormatType ?? false,
|
|
16
|
+
defaultFormatType: ['block', 'inline'].includes(pluginOptions.defaultFormatType) ? pluginOptions.defaultFormatType : 'block',
|
|
17
|
+
keepFormatType: pluginOptions.keepFormatType ?? false,
|
|
18
|
+
lineWidth: pluginOptions.lineWidth || 5,
|
|
19
|
+
lineReconnect: !!pluginOptions.lineReconnect,
|
|
20
|
+
lineCap: ['butt', 'round', 'square'].includes(pluginOptions.lineCap) ? pluginOptions.lineCap : 'round',
|
|
21
|
+
lineColor: pluginOptions.lineColor || '',
|
|
22
|
+
formSize: {
|
|
23
|
+
width: '750px',
|
|
24
|
+
height: '50vh',
|
|
25
|
+
maxWidth: '',
|
|
26
|
+
maxHeight: '',
|
|
27
|
+
minWidth: '150px',
|
|
28
|
+
minHeight: '100px',
|
|
29
|
+
...pluginOptions.formSize
|
|
30
|
+
},
|
|
31
|
+
canResize: pluginOptions.canResize ?? true,
|
|
32
|
+
maintainRatio: pluginOptions.maintainRatio ?? true
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
// exception
|
|
36
|
+
if (!this.plugins.image) {
|
|
37
|
+
console.warn('[SUNEDITOR.plugins.drawing.warn] The drawing plugin must need either "image" plugin. Please add the "image" plugin.');
|
|
38
|
+
} else if (this.pluginOptions.outputFormat === 'svg' && !this.plugins.image.pluginOptions.uploadUrl) {
|
|
39
|
+
console.warn('[SUNEDITOR.plugins.drawing.warn] The drawing plugin must need the "image" plugin with the "uploadUrl" option. Please add the "image" plugin with the "uploadUrl" option.');
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// create HTML
|
|
43
|
+
const modalEl = CreateHTML_modal(this);
|
|
44
|
+
|
|
45
|
+
// modules
|
|
46
|
+
this.modal = new Modal(this, modalEl);
|
|
47
|
+
|
|
48
|
+
// members
|
|
49
|
+
this.as = this.pluginOptions.defaultFormatType;
|
|
50
|
+
if (this.pluginOptions.useFormatType) {
|
|
51
|
+
this.asBlock = modalEl.querySelector('[data-command="asBlock"]');
|
|
52
|
+
this.asInline = modalEl.querySelector('[data-command="asInline"]');
|
|
53
|
+
this.eventManager.addEvent([this.asBlock, this.asInline], 'click', OnClickAsButton.bind(this));
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
this.canvas = null;
|
|
57
|
+
this.ctx = null;
|
|
58
|
+
this.isDrawing = false;
|
|
59
|
+
this.points = [];
|
|
60
|
+
this.paths = [];
|
|
61
|
+
this.resizeObserver = null;
|
|
62
|
+
this.__events = {
|
|
63
|
+
mousedown: isMobile ? OnCanvasTouchStart.bind(this) : OnCanvasMouseDown.bind(this),
|
|
64
|
+
mousemove: isMobile ? OnCanvasTouchMove.bind(this) : OnCanvasMouseMove.bind(this),
|
|
65
|
+
mouseup: OnCanvasMouseUp.bind(this),
|
|
66
|
+
mouseleave: OnCanvasMouseLeave.bind(this),
|
|
67
|
+
mouseenter: OnCanvasMouseEnter.bind(this)
|
|
68
|
+
};
|
|
69
|
+
this.__eventsRegister = {
|
|
70
|
+
mousedown: null,
|
|
71
|
+
mousemove: null,
|
|
72
|
+
mouseup: null,
|
|
73
|
+
mouseleave: null,
|
|
74
|
+
mouseenter: null
|
|
75
|
+
};
|
|
76
|
+
this.__eventNameMap = {
|
|
77
|
+
mousedown: isMobile ? 'touchstart' : 'mousedown',
|
|
78
|
+
mousemove: isMobile ? 'touchmove' : 'mousemove',
|
|
79
|
+
mouseup: isMobile ? 'touchend' : 'mouseup',
|
|
80
|
+
mouseleave: 'mouseleave',
|
|
81
|
+
mouseenter: 'mouseenter'
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
// init
|
|
85
|
+
this.eventManager.addEvent(modalEl.querySelector('[data-command="remove"]'), 'click', OnRemove.bind(this));
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
Drawing.key = 'drawing';
|
|
89
|
+
Drawing.type = 'modal';
|
|
90
|
+
Drawing.className = '';
|
|
91
|
+
Drawing.prototype = {
|
|
92
|
+
/**
|
|
93
|
+
* @override type = "modal"
|
|
94
|
+
*/
|
|
95
|
+
open() {
|
|
96
|
+
if (this.pluginOptions.useFormatType) {
|
|
97
|
+
this._activeAsInline((this.pluginOptions.keepFormatType ? this.as : this.pluginOptions.defaultFormatType) === 'inline');
|
|
98
|
+
}
|
|
99
|
+
this.modal.open();
|
|
100
|
+
this._initDrawing();
|
|
101
|
+
},
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* @override modal
|
|
105
|
+
*/
|
|
106
|
+
off() {
|
|
107
|
+
this._destroyDrawing();
|
|
108
|
+
},
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* @override modal
|
|
112
|
+
* @returns {string}
|
|
113
|
+
*/
|
|
114
|
+
modalAction() {
|
|
115
|
+
if (this.pluginOptions.outputFormat === 'svg') {
|
|
116
|
+
const files = this._getSVGFileList();
|
|
117
|
+
this.plugins.image.init();
|
|
118
|
+
this.plugins.image.submitFile(files);
|
|
119
|
+
} else {
|
|
120
|
+
// dataurl | svg
|
|
121
|
+
const data = this.canvas.toDataURL();
|
|
122
|
+
const file = { name: 'drawing', size: 0 };
|
|
123
|
+
this.plugins.image.init();
|
|
124
|
+
if (this.as !== 'inline') {
|
|
125
|
+
this.plugins.image.create(data, null, 'auto', '', 'none', file, '');
|
|
126
|
+
} else {
|
|
127
|
+
this.plugins.image.createInline(data, null, 'auto', '', 'none', file, '');
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return true;
|
|
132
|
+
},
|
|
133
|
+
|
|
134
|
+
_initDrawing() {
|
|
135
|
+
const canvas = (this.canvas = this.modal.form.querySelector('.se-drawing-canvas'));
|
|
136
|
+
this.ctx = canvas.getContext('2d');
|
|
137
|
+
canvas.width = canvas.offsetWidth;
|
|
138
|
+
canvas.height = canvas.offsetHeight;
|
|
139
|
+
|
|
140
|
+
this.points = [];
|
|
141
|
+
this.paths = [];
|
|
142
|
+
|
|
143
|
+
this._setCtx();
|
|
144
|
+
|
|
145
|
+
this.__eventsRegister.mousedown = this.eventManager.addEvent(canvas, this.__eventNameMap.mousedown, this.__events.mousedown, { passive: false, useCapture: true });
|
|
146
|
+
this.__eventsRegister.mousemove = this.eventManager.addEvent(canvas, this.__eventNameMap.mousemove, this.__events.mousemove, true);
|
|
147
|
+
this.__eventsRegister.mouseup = this.eventManager.addEvent(canvas, this.__eventNameMap.mouseup, this.__events.mouseup, true);
|
|
148
|
+
this.__eventsRegister.mouseleave = this.eventManager.addEvent(canvas, this.__eventNameMap.mouseleave, this.__events.mouseleave);
|
|
149
|
+
this.__eventsRegister.mouseenter = this.eventManager.addEvent(canvas, this.__eventNameMap.mouseenter, this.__events.mouseenter);
|
|
150
|
+
|
|
151
|
+
if (this.resizeObserver) {
|
|
152
|
+
this.resizeObserver.disconnect();
|
|
153
|
+
this.resizeObserver = null;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
this.resizeObserver = new ResizeObserver(() => {
|
|
157
|
+
const prevWidth = canvas.width;
|
|
158
|
+
const prevHeight = canvas.height;
|
|
159
|
+
const newWidth = canvas.offsetWidth;
|
|
160
|
+
const newHeight = canvas.offsetHeight;
|
|
161
|
+
canvas.width = newWidth;
|
|
162
|
+
canvas.height = newHeight;
|
|
163
|
+
if (prevWidth !== canvas.width || prevHeight !== canvas.height) {
|
|
164
|
+
if (this.pluginOptions.maintainRatio) this._adjustPathsToNewDimensions(prevWidth, prevHeight, newWidth, newHeight);
|
|
165
|
+
this._drawAll();
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
this.resizeObserver.observe(canvas);
|
|
170
|
+
},
|
|
171
|
+
|
|
172
|
+
_destroyDrawing() {
|
|
173
|
+
if (this.resizeObserver) {
|
|
174
|
+
this.resizeObserver.disconnect();
|
|
175
|
+
this.resizeObserver = null;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
if (this.canvas) {
|
|
179
|
+
this.eventManager.removeEvent(this.__eventsRegister.mousedown);
|
|
180
|
+
this.eventManager.removeEvent(this.__eventsRegister.mousemove);
|
|
181
|
+
this.eventManager.removeEvent(this.__eventsRegister.mouseup);
|
|
182
|
+
this.eventManager.removeEvent(this.__eventsRegister.mouseleave);
|
|
183
|
+
this.eventManager.removeEvent(this.__eventsRegister.mouseenter);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
this.canvas = null;
|
|
187
|
+
this.ctx = null;
|
|
188
|
+
this.points = [];
|
|
189
|
+
this.paths = [];
|
|
190
|
+
this.isDrawing = false;
|
|
191
|
+
},
|
|
192
|
+
|
|
193
|
+
_setCtx() {
|
|
194
|
+
this.ctx.lineWidth = this.pluginOptions.lineWidth;
|
|
195
|
+
this.ctx.lineCap = this.pluginOptions.lineCap;
|
|
196
|
+
this.ctx.lineColor = this.pluginOptions.lineColor || _w.getComputedStyle(this.carrierWrapper).color;
|
|
197
|
+
},
|
|
198
|
+
|
|
199
|
+
_draw() {
|
|
200
|
+
this._setCtx();
|
|
201
|
+
this.ctx.beginPath();
|
|
202
|
+
this.points.forEach(([x, y], i) => {
|
|
203
|
+
if (i === 0) {
|
|
204
|
+
this.ctx.moveTo(x, y);
|
|
205
|
+
} else {
|
|
206
|
+
this.ctx.lineTo(x, y);
|
|
207
|
+
}
|
|
208
|
+
});
|
|
209
|
+
this.ctx.stroke();
|
|
210
|
+
},
|
|
211
|
+
|
|
212
|
+
_drawAll() {
|
|
213
|
+
this._setCtx();
|
|
214
|
+
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
|
|
215
|
+
this.paths.forEach((path) => {
|
|
216
|
+
this.points = path;
|
|
217
|
+
this._draw();
|
|
218
|
+
});
|
|
219
|
+
this.points = [];
|
|
220
|
+
},
|
|
221
|
+
|
|
222
|
+
_adjustPathsToNewDimensions(prevWidth, prevHeight, newWidth, newHeight) {
|
|
223
|
+
const xRatio = newWidth / prevWidth;
|
|
224
|
+
const yRatio = newHeight / prevHeight;
|
|
225
|
+
|
|
226
|
+
this.paths = this.paths.map((path) => path.map(([x, y]) => [x * xRatio, y * yRatio]));
|
|
227
|
+
},
|
|
228
|
+
|
|
229
|
+
_clearCanvas() {
|
|
230
|
+
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
|
|
231
|
+
this.points = [];
|
|
232
|
+
this.paths = [];
|
|
233
|
+
},
|
|
234
|
+
|
|
235
|
+
_getSVG() {
|
|
236
|
+
const svgNS = 'http://www.w3.org/2000/svg';
|
|
237
|
+
const svg = document.createElementNS(svgNS, 'svg');
|
|
238
|
+
svg.setAttribute('width', this.canvas.width);
|
|
239
|
+
svg.setAttribute('height', this.canvas.height);
|
|
240
|
+
svg.setAttribute('viewBox', `0 0 ${this.canvas.width} ${this.canvas.height}`);
|
|
241
|
+
svg.setAttribute('xmlns', svgNS);
|
|
242
|
+
|
|
243
|
+
this.paths.forEach((path) => {
|
|
244
|
+
const pathData = path.reduce((acc, [x, y], i) => {
|
|
245
|
+
return acc + (i === 0 ? `M ${x} ${y}` : ` L ${x} ${y}`);
|
|
246
|
+
}, '');
|
|
247
|
+
const svgPath = document.createElementNS(svgNS, 'path');
|
|
248
|
+
svgPath.setAttribute('d', pathData);
|
|
249
|
+
svgPath.setAttribute('fill', 'none');
|
|
250
|
+
svgPath.setAttribute('stroke', this.ctx.strokeStyle);
|
|
251
|
+
svgPath.setAttribute('stroke-width', this.ctx.lineWidth);
|
|
252
|
+
svg.appendChild(svgPath);
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
return svg;
|
|
256
|
+
},
|
|
257
|
+
|
|
258
|
+
_getSVGFileList() {
|
|
259
|
+
const svgElement = this._getSVG();
|
|
260
|
+
const serializer = new XMLSerializer();
|
|
261
|
+
const svgString = serializer.serializeToString(svgElement);
|
|
262
|
+
const blob = new Blob([svgString], { type: 'image/svg+xml' });
|
|
263
|
+
const file = new File([blob], 'drawing.svg', { type: 'image/svg+xml' });
|
|
264
|
+
|
|
265
|
+
// Creating a FileList
|
|
266
|
+
const dataTransfer = new DataTransfer();
|
|
267
|
+
dataTransfer.items.add(file);
|
|
268
|
+
|
|
269
|
+
return dataTransfer.files;
|
|
270
|
+
},
|
|
271
|
+
|
|
272
|
+
_getCanvasTouchPointer(e) {
|
|
273
|
+
const { touches } = e;
|
|
274
|
+
const rect = this.canvas.getBoundingClientRect();
|
|
275
|
+
const x = touches[0].clientX - rect.left;
|
|
276
|
+
const y = touches[0].clientY - rect.top;
|
|
277
|
+
return { x, y };
|
|
278
|
+
},
|
|
279
|
+
|
|
280
|
+
_activeAsInline(isInline) {
|
|
281
|
+
if (isInline) {
|
|
282
|
+
domUtils.addClass(this.asInline, 'on');
|
|
283
|
+
domUtils.removeClass(this.asBlock, 'on');
|
|
284
|
+
this.as = 'inline';
|
|
285
|
+
} else {
|
|
286
|
+
domUtils.addClass(this.asBlock, 'on');
|
|
287
|
+
domUtils.removeClass(this.asInline, 'on');
|
|
288
|
+
this.as = 'block';
|
|
289
|
+
}
|
|
290
|
+
},
|
|
291
|
+
|
|
292
|
+
constructor: Drawing
|
|
293
|
+
};
|
|
294
|
+
|
|
295
|
+
function CreateHTML_modal({ lang, icons, pluginOptions }) {
|
|
296
|
+
const { width, height, maxWidth, maxHeight, minWidth, minHeight } = pluginOptions.formSize;
|
|
297
|
+
const html = /*html*/ `
|
|
298
|
+
<form>
|
|
299
|
+
<div class="se-modal-header">
|
|
300
|
+
<button type="button" data-command="close" class="se-btn se-close-btn" title="${lang.close}" aria-label="${lang.close}">
|
|
301
|
+
${icons.cancel}
|
|
302
|
+
</button>
|
|
303
|
+
<span class="se-modal-title">${lang.drawing_modal_title}</span>
|
|
304
|
+
</div>
|
|
305
|
+
<div class="se-modal-body" style="width: ${width}; height: ${height}; min-width: ${minWidth}; min-height: ${minHeight};">
|
|
306
|
+
<canvas class="se-drawing-canvas" style="width: 100%; height: 100%;"></canvas>
|
|
307
|
+
${pluginOptions.canResize ? '<div class="se-modal-resize-handle-w"></div><div class="se-modal-resize-handle-h"></div><div class="se-modal-resize-handle-c"></div>' : ''}
|
|
308
|
+
</div>
|
|
309
|
+
<div class="se-modal-body-bottom">
|
|
310
|
+
<div class="se-modal-form">
|
|
311
|
+
<div class="se-modal-flex-form">
|
|
312
|
+
${
|
|
313
|
+
pluginOptions.useFormatType
|
|
314
|
+
? /*html*/ `
|
|
315
|
+
<div class="se-modal-flex-group">
|
|
316
|
+
<button type="button" class="se-btn se-tooltip" data-command="asBlock" aria-label="${lang.blockStyle}">
|
|
317
|
+
${icons.as_block}
|
|
318
|
+
${CreateTooltipInner(lang.blockStyle)}
|
|
319
|
+
</button>
|
|
320
|
+
<button type="button" class="se-btn se-tooltip" data-command="asInline" aria-label="${lang.inlineStyle}">
|
|
321
|
+
${icons.as_inline}
|
|
322
|
+
${CreateTooltipInner(lang.inlineStyle)}
|
|
323
|
+
</button>
|
|
324
|
+
</div>`
|
|
325
|
+
: ''
|
|
326
|
+
}
|
|
327
|
+
<div class="se-modal-flex-group">
|
|
328
|
+
<button type="button" class="se-btn se-tooltip" data-command="remove" aria-label="${lang.remove}">
|
|
329
|
+
${icons.eraser}
|
|
330
|
+
${CreateTooltipInner(lang.remove)}
|
|
331
|
+
</button>
|
|
332
|
+
</div>
|
|
333
|
+
</div>
|
|
334
|
+
</div>
|
|
335
|
+
</div>
|
|
336
|
+
<div class="se-modal-footer">
|
|
337
|
+
<button type="submit" class="se-btn-primary" title="${lang.submitButton}" aria-label="${lang.submitButton}">
|
|
338
|
+
<span>${lang.submitButton}</span>
|
|
339
|
+
</button>
|
|
340
|
+
</div>
|
|
341
|
+
</form>`;
|
|
342
|
+
|
|
343
|
+
return domUtils.createElement(
|
|
344
|
+
'DIV',
|
|
345
|
+
{
|
|
346
|
+
class: 'se-modal-content se-modal-responsive',
|
|
347
|
+
style: `max-width: ${maxWidth}; max-height: ${maxHeight};`
|
|
348
|
+
},
|
|
349
|
+
html
|
|
350
|
+
);
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
// canvas events
|
|
354
|
+
function OnCanvasMouseDown(e) {
|
|
355
|
+
e.preventDefault();
|
|
356
|
+
this.isDrawing = true;
|
|
357
|
+
this.points.push([e.offsetX, e.offsetY]);
|
|
358
|
+
this._draw();
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
function OnCanvasMouseMove(e) {
|
|
362
|
+
e.preventDefault();
|
|
363
|
+
if (!this.isDrawing) return;
|
|
364
|
+
this.points.push([e.offsetX, e.offsetY]);
|
|
365
|
+
this._draw();
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
function OnCanvasTouchStart(e) {
|
|
369
|
+
e.preventDefault();
|
|
370
|
+
const { x, y } = this._getCanvasTouchPointer(e);
|
|
371
|
+
this.isDrawing = true;
|
|
372
|
+
this.points.push([x, y]);
|
|
373
|
+
this._draw();
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
function OnCanvasTouchMove(e) {
|
|
377
|
+
e.preventDefault();
|
|
378
|
+
const { x, y } = this._getCanvasTouchPointer(e);
|
|
379
|
+
if (!this.isDrawing) return;
|
|
380
|
+
this.points.push([x, y]);
|
|
381
|
+
this._draw();
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
function OnCanvasMouseUp() {
|
|
385
|
+
this.isDrawing = false;
|
|
386
|
+
if (this.points.length > 0) {
|
|
387
|
+
this.paths.push([...this.points]);
|
|
388
|
+
this.points = [];
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
function OnCanvasMouseLeave() {
|
|
393
|
+
if (this.isDrawing) {
|
|
394
|
+
this.paths.push([...this.points]);
|
|
395
|
+
if (!this.pluginOptions.lineReconnect) {
|
|
396
|
+
this.points = [];
|
|
397
|
+
this.isDrawing = false;
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
function OnCanvasMouseEnter(e) {
|
|
403
|
+
if (e.buttons === 1) {
|
|
404
|
+
this.isDrawing = true;
|
|
405
|
+
if (!this.pluginOptions.lineReconnect) {
|
|
406
|
+
this.points.push([e.offsetX, e.offsetY]);
|
|
407
|
+
} else {
|
|
408
|
+
const lastPath = this.paths[this.paths.length - 1];
|
|
409
|
+
const lastPoint = lastPath[lastPath.length - 1];
|
|
410
|
+
this.points.push([lastPoint[0], lastPoint[1]]);
|
|
411
|
+
this.points.push([e.offsetX, e.offsetY]);
|
|
412
|
+
}
|
|
413
|
+
this._draw();
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
// button events
|
|
418
|
+
function OnRemove() {
|
|
419
|
+
this._clearCanvas();
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
function OnClickAsButton({ target }) {
|
|
423
|
+
this._activeAsInline(target.getAttribute('data-command') === 'asInline');
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
export default Drawing;
|
|
@@ -26,7 +26,8 @@ const Image_ = function (editor, pluginOptions) {
|
|
|
26
26
|
allowMultiple: !!pluginOptions.allowMultiple,
|
|
27
27
|
acceptedFormats: typeof pluginOptions.acceptedFormats !== 'string' || pluginOptions.acceptedFormats.trim() === '*' ? 'image/*' : pluginOptions.acceptedFormats.trim() || 'image/*',
|
|
28
28
|
useFormatType: pluginOptions.useFormatType ?? true,
|
|
29
|
-
defaultFormatType: ['block', 'inline'].includes(pluginOptions.defaultFormatType) ? pluginOptions.defaultFormatType : 'block'
|
|
29
|
+
defaultFormatType: ['block', 'inline'].includes(pluginOptions.defaultFormatType) ? pluginOptions.defaultFormatType : 'block',
|
|
30
|
+
keepFormatType: pluginOptions.keepFormatType ?? false
|
|
30
31
|
};
|
|
31
32
|
|
|
32
33
|
// create HTML
|
|
@@ -249,7 +250,7 @@ Image_.prototype = {
|
|
|
249
250
|
}
|
|
250
251
|
|
|
251
252
|
if (this.pluginOptions.useFormatType) {
|
|
252
|
-
this._activeAsInline(this.pluginOptions.defaultFormatType === 'inline');
|
|
253
|
+
this._activeAsInline((this.pluginOptions.keepFormatType ? this.as : this.pluginOptions.defaultFormatType) === 'inline');
|
|
253
254
|
}
|
|
254
255
|
|
|
255
256
|
this.anchor.init();
|
|
@@ -2,13 +2,15 @@ import EditorInjector from '../../editorInjector';
|
|
|
2
2
|
import { Modal, Controller } from '../../modules';
|
|
3
3
|
import { domUtils, env, converter } from '../../helper';
|
|
4
4
|
|
|
5
|
+
const { _w } = env;
|
|
6
|
+
|
|
5
7
|
const Math_ = function (editor, pluginOptions) {
|
|
6
8
|
// external library
|
|
7
9
|
this.katex = null;
|
|
8
10
|
this.mathjax = null;
|
|
9
11
|
|
|
10
12
|
// exception
|
|
11
|
-
if (!(this.katex = CheckKatex(editor.options.get('externalLibs').katex)) && !(this.mathjax = CheckMathJax(editor.options.get('externalLibs').mathjax))) {
|
|
13
|
+
if (!(this.katex = CheckKatex(editor.options.get('externalLibs').katex)) && !(this.mathjax = CheckMathJax(editor.options.get('externalLibs').mathjax, editor))) {
|
|
12
14
|
console.warn('[SUNEDITOR.plugins.math.warn] The math plugin must need either "KaTeX" or "MathJax" library. Please add the katex or mathjax option.');
|
|
13
15
|
}
|
|
14
16
|
|
|
@@ -17,8 +19,43 @@ const Math_ = function (editor, pluginOptions) {
|
|
|
17
19
|
this.title = this.lang.math;
|
|
18
20
|
this.icon = 'math';
|
|
19
21
|
|
|
22
|
+
this.pluginOptions = {
|
|
23
|
+
formSize: {
|
|
24
|
+
width: '460px',
|
|
25
|
+
height: '14em',
|
|
26
|
+
maxWidth: '',
|
|
27
|
+
maxHeight: '',
|
|
28
|
+
minWidth: '400px',
|
|
29
|
+
minHeight: '40px',
|
|
30
|
+
...pluginOptions.formSize
|
|
31
|
+
},
|
|
32
|
+
canResize: pluginOptions.canResize ?? true,
|
|
33
|
+
autoHeight: !!pluginOptions.autoHeight,
|
|
34
|
+
fontSizeList: pluginOptions.fontSizeList || [
|
|
35
|
+
{
|
|
36
|
+
text: '1',
|
|
37
|
+
value: '1em'
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
text: '1.5',
|
|
41
|
+
value: '1.5em'
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
text: '2',
|
|
45
|
+
value: '2em'
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
text: '2.5',
|
|
49
|
+
value: '2.5em'
|
|
50
|
+
}
|
|
51
|
+
]
|
|
52
|
+
};
|
|
53
|
+
if (this.pluginOptions.autoHeight) {
|
|
54
|
+
this.pluginOptions.formSize.height = this.pluginOptions.formSize.minHeight;
|
|
55
|
+
}
|
|
56
|
+
|
|
20
57
|
// create HTML
|
|
21
|
-
const modalEl = CreateHTML_modal(
|
|
58
|
+
const modalEl = CreateHTML_modal(this);
|
|
22
59
|
const controllerEl = CreateHTML_controller(editor);
|
|
23
60
|
|
|
24
61
|
// modules
|
|
@@ -94,7 +131,10 @@ Math_.prototype = {
|
|
|
94
131
|
domUtils.removeClass(element, 'katex');
|
|
95
132
|
}
|
|
96
133
|
|
|
97
|
-
if (this.mathjax)
|
|
134
|
+
if (this.mathjax) {
|
|
135
|
+
renderMathJax(this.mathjax);
|
|
136
|
+
this._applyMathJaxStyleOnIframe();
|
|
137
|
+
}
|
|
98
138
|
}
|
|
99
139
|
};
|
|
100
140
|
},
|
|
@@ -169,7 +209,10 @@ Math_.prototype = {
|
|
|
169
209
|
return true;
|
|
170
210
|
}
|
|
171
211
|
|
|
172
|
-
if (this.mathjax)
|
|
212
|
+
if (this.mathjax) {
|
|
213
|
+
renderMathJax(this.mathjax);
|
|
214
|
+
this._applyMathJaxStyleOnIframe();
|
|
215
|
+
}
|
|
173
216
|
|
|
174
217
|
const r = this.selection.getNearRange(mathEl);
|
|
175
218
|
if (r) {
|
|
@@ -254,7 +297,7 @@ async function copyTextToClipboard(element) {
|
|
|
254
297
|
await navigator.clipboard.writeText(text);
|
|
255
298
|
domUtils.addClass(element, 'se-copy');
|
|
256
299
|
// copy effect
|
|
257
|
-
|
|
300
|
+
_w.setTimeout(() => {
|
|
258
301
|
domUtils.removeClass(element, 'se-copy');
|
|
259
302
|
}, 120);
|
|
260
303
|
} catch (err) {
|
|
@@ -262,8 +305,13 @@ async function copyTextToClipboard(element) {
|
|
|
262
305
|
}
|
|
263
306
|
}
|
|
264
307
|
|
|
265
|
-
function RenderMathExp(
|
|
266
|
-
|
|
308
|
+
function RenderMathExp({ target }) {
|
|
309
|
+
if (this.pluginOptions.autoHeight) {
|
|
310
|
+
target.style.height = '5px';
|
|
311
|
+
target.style.height = target.scrollHeight + 5 + 'px';
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
this.previewElement.innerHTML = this._renderer(target.value);
|
|
267
315
|
if (this.mathjax) renderMathJax(this.mathjax);
|
|
268
316
|
}
|
|
269
317
|
|
|
@@ -295,8 +343,11 @@ function CheckKatex(katex) {
|
|
|
295
343
|
return katex;
|
|
296
344
|
}
|
|
297
345
|
|
|
298
|
-
function CheckMathJax(mathjax) {
|
|
346
|
+
function CheckMathJax(mathjax, editor) {
|
|
299
347
|
if (!mathjax) return null;
|
|
348
|
+
if (editor.frameOptions.get('iframe')) {
|
|
349
|
+
console.warn('[SUNEDITOR.math.mathjax.fail] The MathJax option is not supported in the iframe.');
|
|
350
|
+
}
|
|
300
351
|
|
|
301
352
|
try {
|
|
302
353
|
const adaptor = mathjax.browserAdaptor();
|
|
@@ -315,26 +366,13 @@ function CheckMathJax(mathjax) {
|
|
|
315
366
|
}
|
|
316
367
|
}
|
|
317
368
|
|
|
318
|
-
function CreateHTML_modal(
|
|
319
|
-
const
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
text: '1.5',
|
|
326
|
-
value: '1.5em'
|
|
327
|
-
},
|
|
328
|
-
{
|
|
329
|
-
text: '2',
|
|
330
|
-
value: '2em'
|
|
331
|
-
},
|
|
332
|
-
{
|
|
333
|
-
text: '2.5',
|
|
334
|
-
value: '2.5em'
|
|
335
|
-
}
|
|
336
|
-
];
|
|
337
|
-
let defaultFontSize = fontSize[0].value;
|
|
369
|
+
function CreateHTML_modal(inst) {
|
|
370
|
+
const { lang, icons, pluginOptions, katex } = inst;
|
|
371
|
+
const { formSize, fontSizeList, canResize, autoHeight } = pluginOptions;
|
|
372
|
+
const { width, height, maxWidth, maxHeight, minWidth, minHeight } = formSize;
|
|
373
|
+
const resizeType = !canResize ? 'none' : autoHeight ? 'horizontal' : 'auto';
|
|
374
|
+
|
|
375
|
+
let defaultFontSize = fontSizeList[0].value;
|
|
338
376
|
let html = /*html*/ `
|
|
339
377
|
<form>
|
|
340
378
|
<div class="se-modal-header">
|
|
@@ -345,15 +383,15 @@ function CreateHTML_modal({ lang, icons }, math, fontSizeList, isKatex) {
|
|
|
345
383
|
</div>
|
|
346
384
|
<div class="se-modal-body">
|
|
347
385
|
<div class="se-modal-form">
|
|
348
|
-
<label>${lang.math_modal_inputLabel} ${
|
|
349
|
-
<textarea class="se-input-form se-math-exp" type="text" data-focus></textarea>
|
|
386
|
+
<label>${lang.math_modal_inputLabel} ${katex ? `(<a href="${env.KATEX_WEBSITE}" target="_blank">KaTeX</a>)` : `(<a href="${env.MATHJAX_WEBSITE}" target="_blank">MathJax</a>)`}</label>
|
|
387
|
+
<textarea class="se-input-form se-math-exp se-modal-resize-form" type="text" data-focus style="width: ${width}; height: ${height}; min-width: ${minWidth}; min-height: ${minHeight}; resize: ${resizeType};"></textarea>
|
|
350
388
|
</div>
|
|
351
389
|
<div class="se-modal-form">
|
|
352
390
|
<label>${lang.math_modal_fontSizeLabel}</label>
|
|
353
391
|
<select class="se-input-select se-math-size">`;
|
|
354
392
|
|
|
355
|
-
for (let i = 0, len =
|
|
356
|
-
f =
|
|
393
|
+
for (let i = 0, len = fontSizeList.length, f; i < len; i++) {
|
|
394
|
+
f = fontSizeList[i];
|
|
357
395
|
if (f.default) defaultFontSize = f.value;
|
|
358
396
|
html += /*html*/ `<option value="${f.value}"${f.default ? ' selected' : ''}>${f.text}</option>`;
|
|
359
397
|
}
|
|
@@ -372,8 +410,8 @@ function CreateHTML_modal({ lang, icons }, math, fontSizeList, isKatex) {
|
|
|
372
410
|
</div>
|
|
373
411
|
</form>`;
|
|
374
412
|
|
|
375
|
-
|
|
376
|
-
return domUtils.createElement('DIV', { class: 'se-modal-content' }, html);
|
|
413
|
+
inst.defaultFontSize = defaultFontSize;
|
|
414
|
+
return domUtils.createElement('DIV', { class: 'se-modal-content se-modal-responsive', style: `max-width: ${maxWidth}; max-height: ${maxHeight};` }, html);
|
|
377
415
|
}
|
|
378
416
|
|
|
379
417
|
function CreateHTML_controller({ lang, icons }) {
|