mdui.editor
Version:
Material Design 样式的富文本编辑器
114 lines (113 loc) • 4.52 kB
JavaScript
import $ from 'mdui.jq/es/$';
import 'mdui.jq/es/methods/add';
import 'mdui.jq/es/methods/children';
import 'mdui.jq/es/methods/each';
import 'mdui.jq/es/methods/is';
import 'mdui.jq/es/methods/last';
import 'mdui.jq/es/methods/on';
import 'mdui.jq/es/methods/remove';
import 'mdui.jq/es/methods/text';
import MenuAbstract from '../abstracts/menuAbstract';
import { replaceHtmlSymbol } from '../utils/str';
/**
* 代码块
*/
class Code extends MenuAbstract {
constructor(editor, $button) {
super(editor, $button);
this.active = false;
this.init();
}
init() {
this.$container.on('keydown', (event) => {
if (event.keyCode === 13) {
// 按回车时,添加 \n
if (this.active) {
event.preventDefault();
const startOffset = this.selection.getRange().startOffset;
this.command.do('insertHTML', '\n');
this.selection.saveRange();
if (this.selection.getRange().startOffset === startOffset) {
// 没起作用,再来一次
this.command.do('insertHTML', '\n');
}
// 换行后滚动条回到最左侧
this.selection.getContainerElem()[0].scrollLeft = 0;
}
}
if (event.keyCode === 9) {
// 按 tab 时,添加四个空格
if (this.active) {
event.preventDefault();
this.command.do('insertHTML', ' ');
}
}
});
}
onclick() {
const $rootElem = this.selection.getRootElem();
if (this.active) {
// 若当前是代码块,则每一行都转换为 p 标签
const textArray = $rootElem.text().split('\n');
let html = '';
textArray.forEach((line) => {
line = replaceHtmlSymbol(line);
html = line ? `<p>${line}</p>${html}` : `<p><br></p>${html}`;
});
this.command.do('replaceRoot', html);
return;
}
if (!$rootElem.length) {
const range = this.selection.getRange();
if (range.collapsed) {
// 没有选中任何选区,在最后添加一行
this.command.do('appendHTML', '<pre><code><br></code></pre>');
}
else {
// 选中了多行,把多行包裹在同一个 pre 中
let text = '';
let isInRange = false;
let $linesRemove = $();
this.$container.children().each((_, line) => {
const $line = $(line);
if (!isInRange) {
if ($line.is(range.startContainer) ||
$line[0].contains(range.startContainer) ||
this.$container.is(range.startContainer)) {
isInRange = true;
}
}
if (isInRange) {
text += `${replaceHtmlSymbol($line.text())}\n`;
$linesRemove = $linesRemove.add($line);
if ($line.is(range.endContainer) ||
$line[0].contains(range.endContainer)) {
return false;
}
}
return true;
});
$linesRemove.each((i, line) => {
const $line = $(line);
if (i < $linesRemove.length - 1) {
$line.remove();
}
});
this.selection.createRangeByElem($linesRemove.last(), false, true);
this.command.do('replaceRoot', `<pre><code>${text}</code></pre>`);
}
return;
}
// 选中单行,需要移除选区内容所有子元素的标签,然后转换为 pre
const text = replaceHtmlSymbol($rootElem.text());
this.command.do('replaceRoot', text ? `<pre><code>${text}</code></pre>` : '<pre><code><br></code></pre>');
}
isActive() {
this.active = this.selection.getRootElem().is('pre');
return this.active;
}
}
Code.icon = 'code';
Code.title = '代码块';
Code.disable = ['bold', 'italic', 'head', 'ol', 'ul', 'link', 'image'];
export default Code;