我已经创建了CKEditor5的自定义版本,并创建了插件BorderColor
。插件运行不正常。问题在于模型正在更改,但视图未更改。
border-color.js
import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
import BorderColorEditing from './border-color-editing';
import BorderColorUi from './border-color-ui';
export default class BorderColor extends Plugin {
/**
* @inheritDoc
*/
static get requires() {
return [ BorderColorEditing, BorderColorUi ];
}
/**
* @inheritDoc
*/
static get pluginName() {
return 'BorderColor';
}
}
border-color-ui.js
import ColorUI from '@ckeditor/ckeditor5-font/src/ui/colorui';
export default class BorderColorUi extends ColorUI {
/**
* @inheritDoc
*/
constructor( editor ) {
const t = editor.locale.t;
super( editor, {
commandName: 'borderColor',
componentName: 'borderColor',
dropdownLabel: t( 'Rahmenfarbe' )
} );
}
/**
* @inheritDoc
*/
static get pluginName() {
return 'BorderColorUI';
}
}
border-color-editing.js
import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
import BorderColorCommand from './border-color-command';
import { isDefault, isSupported, supportedOptions } from './utils';
export default class BorderColorEditing extends Plugin {
/**
* @inheritDoc
*/
constructor( editor ) {
super( editor );
editor.config.define( 'borderColor', supportedOptions );
}
/**
* @inheritDoc
*/
init() {
const editor = this.editor;
const schema = editor.model.schema;
// Filter out unsupported options.
const enabledOptions = editor.config.get( 'borderColor.colors' );
// Allow alignment attribute on all blocks.
schema.extend( '$block', { allowAttributes: 'borderColor' } );
editor.model.schema.setAttributeProperties( 'borderColor', { isFormatting: true } );
editor.model.schema.addAttributeCheck( ( context, attributeName ) => {
if ( context.endsWith( 'table' ) || context.endsWith( 'tableRow' ) || context.endsWith( 'tableCell' )) {
return true;
}
} );
const definition = _buildDefinition( enabledOptions.filter( option => !isDefault( option ) ) );
editor.conversion.attributeToAttribute( definition );
editor.commands.add( 'borderColor', new BorderColorCommand( editor ) );
}
}
// Utility function responsible for building converter definition.
// @private
function _buildDefinition( options ) {
const definition = {
model: {
key: 'borderColor',
values: options.slice()
},
view: {}
};
for ( const option of options ) {
const _def = { key: 'style', value: {} };
_def.value[ 'border-color' ] = option.color;
definition.view[ option ] = _def;
}
return definition;
}
border-color-command.js
import Command from '@ckeditor/ckeditor5-core/src/command';
import first from '@ckeditor/ckeditor5-utils/src/first';
import { isDefault } from './utils';
const BORDER_COLOR = 'borderColor';
export default class BorderColorCommand extends Command {
/**
* @inheritDoc
*/
refresh() {
let childBlocks;
if ( this.editor.model.document.selection.getSelectedElement() != null )
childBlocks = this.getSelectedBlocks( this.editor.model.document, 'all-tablerow' );
const firstBlock = this.editor.model.document.selection.getSelectedElement() != null
? this.editor.model.document.selection.getSelectedElement()
: first( this.editor.model.document.selection.getSelectedBlocks() );
// As first check whether to enable or disable the command as the value will always be false if the command cannot be enabled.
this.isEnabled = !!firstBlock && this._canBeAligned( firstBlock );
/**
* A value of the current block's alignment.
*
* @observable
* @readonly
* @member {String} #value
*/
if ( this.isEnabled && firstBlock.hasAttribute( BORDER_COLOR ) )
this.value = firstBlock.getAttribute( BORDER_COLOR );
else if ( this.isEnabled && childBlocks && childBlocks[ 0 ].hasAttribute( BORDER_COLOR ) )
this.value = childBlocks[ 0 ].getAttribute( BORDER_COLOR );
else
this.value = '';
}
/**
* Executes the command. Applies the alignment `value` to the selected blocks.
* If no `value` is passed, the `value` is the default one or it is equal to the currently selected block's alignment attribute,
* the command will remove the attribute from the selected blocks.
*
* @param {Object} [options] Options for the executed command.
* @param {String} [options.value] The value to apply.
* @fires execute
*/
execute( options = {} ) {
const editor = this.editor;
const model = editor.model;
const doc = model.document;
const value = options.value;
model.change( writer => {
let childBlocks;
if ( this.editor.model.document.selection.getSelectedElement() != null )
childBlocks = this.getSelectedBlocks( this.editor.model.document, 'all-tablerow' );
const firstBlock = this.editor.model.document.selection.getSelectedElement() != null
? this.editor.model.document.selection.getSelectedElement()
: first( this.editor.model.document.selection.getSelectedBlocks() );
let currentAlignment;
if ( firstBlock.hasAttribute( BORDER_COLOR ) )
currentAlignment = firstBlock.getAttribute( BORDER_COLOR );
else if ( childBlocks && childBlocks[ 0 ].hasAttribute( BORDER_COLOR ) )
currentAlignment = childBlocks[ 0 ].getAttribute( BORDER_COLOR );
// Remove alignment attribute if current alignment is:
// - default (should not be stored in model as it will bloat model data)
// - equal to currently set
// - or no value is passed - denotes default alignment.
const removeAlignment = isDefault( value ) || currentAlignment === value || !value;
console.log( 'childBlocks / firstBlock', childBlocks, firstBlock, currentAlignment);
const blocks = childBlocks ? Array.from( childBlocks ) : [];
blocks.push( firstBlock );
if ( removeAlignment ) {
removeAlignmentFromSelection( blocks, writer );
} else {
setAlignmentOnSelection( blocks, writer, value );
}
} );
}
getSelectedBlocks( doc, value ) {
let blocks;
if ( doc.selection.getSelectedElement() == null )
blocks = Array.from( doc.selection.getSelectedBlocks() ).filter( block => this._canBeAligned( block ) )
else {
blocks = [ doc.selection.getSelectedElement() ];
if ( value.indexOf( 'tablerow' ) > -1 ) {
var children = doc.selection.getSelectedElement().getChildren();
console.log( 'Selected Element Children', children );
var out = [];
let _next = children.next();
while ( !_next.done ) {
console.log( _next );
if ( _next.value.getChildren ) {
const children2 = _next.value.getChildren();
let _next2 = children2.next();
while ( !_next2.done ) {
console.log( _next2 );
out[ out.length ] = _next2.value;
_next2 = children2.next();
}
}
else {
out[ out.length ] = _next.value;
}
_next = children.next();
}
blocks = out;
}
}
return blocks;
}
/**
* Checks whether a block can have alignment set.
*
* @private
* @param {module:engine/model/element~Element} block The block to be checked.
* @returns {Boolean}
*/
_canBeAligned( block ) {
return this.editor.model.schema.checkAttribute( block, BORDER_COLOR );
}
}
// Removes the alignment attribute from blocks.
// @private
function removeAlignmentFromSelection( blocks, writer ) {
for ( const block of blocks ) {
writer.removeAttribute( BORDER_COLOR, block );
}
}
// Sets the alignment attribute on blocks.
// @private
function setAlignmentOnSelection( blocks, writer, border ) {
for ( const block of blocks ) {
writer.setAttribute( BORDER_COLOR, border, block );
}
}
该代码也可以在Github上找到:CKEditor Custom Build Github。
答案 0 :(得分:0)
我找到了解决方案。
我编辑了border-color-editing.js: 我替换了以下代码:
editor.conversion.attributeToAttribute( definition );
具有:
editor.conversion.for( 'downcast' ).attributeToAttribute( {
model: 'borderColor',
view: function( option ) {
const allSelectedBlocks = getAllSelectedBlocks( this.editor );
const borderAttribute = allSelectedBlocks[ 0 ].getAttribute( BORDER );
if ( !borderAttribute || !option )
return { key: 'style', value: '' };
const _value = {};
const styleOption = borderAttribute.replace( '-tablerow', '' );
_value[ 'border' + ( styleOption == 'all' ? '' : '-' + styleOption ) + '-color' ] = option ? option : 'black';
return { key: 'style', value: _value };
}.bind( this )
} );