jodit
Version:
Jodit is an awesome and useful wysiwyg editor with filebrowser
221 lines (220 loc) • 8.09 kB
JavaScript
/*!
* Jodit Editor (https://xdsoft.net/jodit/)
* Released under MIT see LICENSE.txt in the project root for license information.
* Copyright (c) 2013-2025 Valeriy Chupurnov. All rights reserved. https://xdsoft.net
*/
import * as constants from "../../../../core/constants.js";
import { isString, loadNext } from "../../../../core/helpers/index.js";
import { SourceEditor } from "../sourceEditor.js";
export class AceEditor extends SourceEditor {
constructor() {
super(...arguments);
this.className = 'jodit_ace_editor';
/**
* Proxy Method
*/
this.proxyOnBlur = (e) => {
this.j.e.fire('blur', e);
};
this.proxyOnFocus = (e) => {
this.j.e.fire('focus', e);
};
this.proxyOnMouseDown = (e) => {
this.j.e.fire('mousedown', e);
};
}
aceExists() {
return this.j.ow.ace !== undefined;
}
getLastColumnIndex(row) {
return this.instance.session.getLine(row).length;
}
getLastColumnIndices() {
const rows = this.instance.session.getLength();
const lastColumnIndices = [];
let lastColIndex = 0;
for (let i = 0; i < rows; i++) {
lastColIndex += this.getLastColumnIndex(i);
if (i > 0) {
lastColIndex += 1;
}
lastColumnIndices[i] = lastColIndex;
}
return lastColumnIndices;
}
getRowColumnIndices(characterIndex) {
const lastColumnIndices = this.getLastColumnIndices();
if (characterIndex <= lastColumnIndices[0]) {
return { row: 0, column: characterIndex };
}
let row = 1;
for (let i = 1; i < lastColumnIndices.length; i++) {
if (characterIndex > lastColumnIndices[i]) {
row = i + 1;
}
}
const column = characterIndex - lastColumnIndices[row - 1] - 1;
return { row, column };
}
setSelectionRangeIndices(start, end) {
const startRowColumn = this.getRowColumnIndices(start);
const endRowColumn = this.getRowColumnIndices(end);
this.instance.getSelection().setSelectionRange({
start: startRowColumn,
end: endRowColumn
});
}
getIndexByRowColumn(row, column) {
const lastColumnIndices = this.getLastColumnIndices();
return lastColumnIndices[row] - this.getLastColumnIndex(row) + column;
}
init(editor) {
const tryInitAceEditor = () => {
if (this.instance !== undefined || !this.aceExists()) {
return;
}
const fakeMirror = this.j.c.div('jodit-source__mirror-fake');
this.container.appendChild(fakeMirror);
const ace = editor.ow.ace;
this.instance = ace.edit(fakeMirror);
if (editor.o.direction === 'rtl') {
this.instance.setOption('rtlText', true);
this.instance.setOption('rtl', true);
}
this.instance.setTheme(editor.o.sourceEditorNativeOptions.theme);
this.instance.renderer.setShowGutter(editor.o.sourceEditorNativeOptions.showGutter);
this.instance
.getSession()
.setMode(editor.o.sourceEditorNativeOptions.mode);
this.instance.setHighlightActiveLine(editor.o.sourceEditorNativeOptions.highlightActiveLine);
this.instance.getSession().setUseWrapMode(true);
this.instance.setOption('indentedSoftWrap', false);
this.instance.setOption('wrap', editor.o.sourceEditorNativeOptions.wrap);
this.instance.getSession().setUseWorker(false);
this.instance.$blockScrolling = Infinity;
this.instance.on('change', this.toWYSIWYG);
this.instance.on('focus', this.proxyOnFocus);
this.instance.on('mousedown', this.proxyOnMouseDown);
this.instance.on('blur', this.proxyOnBlur);
if (editor.getRealMode() !== constants.MODE_WYSIWYG) {
this.setValue(this.getValue());
}
const onResize = this.j.async.throttle(() => {
if (editor.isInDestruct ||
editor.getMode() === constants.MODE_WYSIWYG) {
return;
}
const hasFocus = this.instance.isFocused();
if (editor.o.height !== 'auto') {
this.instance.setOption('maxLines', editor.workplace.offsetHeight /
this.instance.renderer.lineHeight);
}
else {
this.instance.setOption('maxLines', Infinity);
}
this.instance.resize();
hasFocus && this.focus();
}, this.j.defaultTimeout * 2);
editor.e
.on(editor, 'resize', onResize)
.on('afterResize afterSetMode', onResize);
onResize();
this.onReady();
};
editor.e.on('afterSetMode', () => {
if (editor.getRealMode() !== constants.MODE_SOURCE &&
editor.getMode() !== constants.MODE_SPLIT) {
return;
}
this.fromWYSIWYG();
tryInitAceEditor();
});
tryInitAceEditor();
// global add ace editor in browser
if (!this.aceExists()) {
loadNext(editor, editor.o.sourceEditorCDNUrlsJS)
.then(() => {
if (!editor.isInDestruct) {
tryInitAceEditor();
}
})
.catch(() => null);
}
}
destruct() {
var _a, _b;
this.instance.off('change', this.toWYSIWYG);
this.instance.off('focus', this.proxyOnFocus);
this.instance.off('mousedown', this.proxyOnMouseDown);
this.instance.destroy();
(_b = (_a = this.j) === null || _a === void 0 ? void 0 : _a.events) === null || _b === void 0 ? void 0 : _b.off('aceInited.source');
}
setValue(value) {
if (!this.j.o.editHTMLDocumentMode && this.j.o.beautifyHTML) {
const html = this.j.e.fire('beautifyHTML', value);
if (isString(html)) {
value = html;
}
}
this.instance.setValue(value);
this.instance.clearSelection();
}
getValue() {
return this.instance.getValue();
}
setReadOnly(isReadOnly) {
this.instance.setReadOnly(isReadOnly);
}
get isFocused() {
return this.instance.isFocused();
}
focus() {
this.instance.container.focus();
this.instance.focus();
}
blur() {
this.instance.blur();
}
getSelectionStart() {
const range = this.instance.selection.getRange();
return this.getIndexByRowColumn(range.start.row, range.start.column);
}
getSelectionEnd() {
const range = this.instance.selection.getRange();
return this.getIndexByRowColumn(range.end.row, range.end.column);
}
selectAll() {
this.instance.selection.selectAll();
}
insertRaw(html) {
const start = this.instance.selection.getCursor(), end = this.instance.session.insert(start, html);
this.instance.selection.setRange({
start,
end
}, false);
}
setSelectionRange(start, end) {
this.setSelectionRangeIndices(start, end);
}
setPlaceHolder(title) {
// ACE does not support placeholder
// title
}
replaceUndoManager() {
const { history } = this.jodit;
this.instance.commands.addCommand({
name: 'Undo',
bindKey: { win: 'Ctrl-Z', mac: 'Command-Z' },
exec: () => {
history.undo();
}
});
this.instance.commands.addCommand({
name: 'Redo',
bindKey: { win: 'Ctrl-Shift-Z', mac: 'Command-Shift-Z' },
exec: () => {
history.redo();
}
});
}
}