前言:CKEditor是一个经典的富文本编辑器了,08年小编初入行时就已用过了,对它还存在一些敬畏之心。奈何一代新人胜旧人,互联网的快速发展,出现了很多的富文本编辑器,比如百度的UEditor,后来者居上,很快成为了主流的编辑器,但其不思进取,很多年没有更新了。后来又试了几个不错的编辑器,如Quill、Froala、Simditor、Summernote、TinyMCE等,都是很不错的编辑器,各有优缺。无意间,又发现了CKEditor5,它是完全重新设计的编辑器,和4及以下版本已经是不同的技术路线了,做得也很美观,就试了下,很是喜欢。
CKEditor编辑器是西方国家开发,照顾的是拉丁文本,对中文的排版还未完全支持,比如中文排版中常用的首行缩进功能。本文是小编使用过程中开发的一个首行缩进插件,仅供大家参考。
一、首行缩进说明(中文排版为何要首行缩进)
二、插件原码
1、textindent.js
/**
* @module text-indent/textindent
*/
import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
import TextIndentEditing from './textindentediting';
import TextIndentUI from './textindentui';
export default class TextIndent extends Plugin {
/**
* @inheritDoc
*/
static get requires() {
return [TextIndentEditing, TextIndentUI];
}
/**
* @inheritDoc
*/
static get pluginName() {
return 'TextIndent';
}
}
2、textindentcommand.js
/**
* @module text-indent/textindentcommand
*/
import Command from '@ckeditor/ckeditor5-core/src/command';
import first from '@ckeditor/ckeditor5-utils/src/first';
const TEXTINDENT = 'textindent';
/**
* The textindent command plugin.
*
* @extends module:core/command~Command
*/
export default class TextIndentCommand extends Command {
/**
* @inheritDoc
*/
refresh() {
const firstBlock = first(this.editor.model.document.selection.getSelectedBlocks());
this.isEnabled = !!firstBlock && this._canBeAligned(firstBlock);
// 设置按钮状态
if (this.isEnabled && firstBlock.hasAttribute(TEXTINDENT)) {
this.value = firstBlock.getAttribute(TEXTINDENT);
} else {
this.value = null;
}
}
/**
* @inheritDoc
*/
execute() {
//execute(options = {}) {
const editor = this.editor;
const model = editor.model;
const doc = model.document;
model.change(writer => {
const blocks = Array.from(doc.selection.getSelectedBlocks()).filter(block => this._canBeAligned(block));
const currentTextIndent = blocks[0].getAttribute(TEXTINDENT);
const removeTextIndent = currentTextIndent === TEXTINDENT || !TEXTINDENT;
if (removeTextIndent) {
removeTextIndentFromSelection(blocks, writer);
} else {
setTextIndentOnSelection(blocks, writer, TEXTINDENT);
}
});
}
_canBeAligned(block) {
return this.editor.model.schema.checkAttribute(block, TEXTINDENT);
}
}
// Removes the textindent attribute from blocks.
// @private
function removeTextIndentFromSelection(blocks, writer) {
for (const block of blocks) {
writer.removeAttribute(TEXTINDENT, block);
}
}
// Sets the textindent attribute on blocks.
// @private
function setTextIndentOnSelection(blocks, writer, textindent) {
for (const block of blocks) {
writer.setAttribute(TEXTINDENT, textindent, block);
}
}
3、textindentediting.js
/**
* @module text-indent/textindentediting
*/
import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
import TextIndentCommand from './textindentcommand';
export default class TextIndentEditing extends Plugin {
/**
* @inheritDoc
*/
static get pluginName() {
return 'TextIndentEditing';
}
/**
* @inheritDoc
*/
constructor(editor) {
super(editor);
editor.config.define('textIndentValue', '2em');
}
/**
* @inheritDoc
*/
init() {
const editor = this.editor;
const schema = editor.model.schema;
const indentValue = editor.config.get('textIndentValue');
// Allow textindent attribute on all blocks.
schema.extend('$block', { allowAttributes: 'textindent' });
editor.model.schema.setAttributeProperties('textindent', { isFormatting: true });
const definition = {
model: {
key: 'textindent',
values: ['textindent']
},
view: {
textindent: {
key: 'style',
value: {
'text-indent': indentValue
// , width: '50%'
// , margin: '5px'
}
}
}
};
editor.conversion.attributeToAttribute(definition);
editor.commands.add('textindent', new TextIndentCommand(editor));
}
}
4、textindentui.js
/**
* @module text-indent/textindentui
*/
import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
import ButtonView from '@ckeditor/ckeditor5-ui/src/button/buttonview';
import alignRightIcon from './icons/textindent.svg';
export default class TextIndentUI extends Plugin {
/**
* @inheritDoc
*/
static get pluginName() {
return 'TextIndentUI';
}
/**
* @inheritDoc
*/
init() {
const editor = this.editor;
editor.ui.componentFactory.add(`textindent`, locale => {
const command = editor.commands.get('textindent');
const buttonView = new ButtonView(locale);
buttonView.set({
label: '首行缩进',
icon: alignRightIcon,
tooltip: true
, isToggleable: true
});
buttonView.bind('isOn', 'isEnabled').to(command, 'value', 'isEnabled');
// Execute command.
this.listenTo(buttonView, 'execute', () => {
editor.execute('textindent');
editor.editing.view.focus();
});
return buttonView;
});
}
}
三、用法及效果
默认配置是首行缩进2em,也可在外部配置
ClassicEditor.create(document.querySelector('.editor'),
{
textIndentValue: '40px'
});
选中需要缩行的段落