UNPKG

mdui.editor

Version:

Material Design 样式的富文本编辑器

114 lines (113 loc) 4.52 kB
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;