Skip to content
This repository has been archived by the owner on Jun 26, 2020. It is now read-only.

Commit

Permalink
Merge pull request #6 from ckeditor/t/2
Browse files Browse the repository at this point in the history
Feature: Initial implementation. Closes #2.
  • Loading branch information
szymonkups authored Nov 7, 2017
2 parents f0c0298 + 59cebd3 commit ae069ba
Show file tree
Hide file tree
Showing 22 changed files with 1,367 additions and 1 deletion.
6 changes: 6 additions & 0 deletions lang/contexts.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"Align left": "Toolbar button tooltip for aligning text to the left.",
"Align right": "Toolbar button tooltip for aligning text to the right.",
"Align center": "Toolbar button tooltip for aligning text to center.",
"Justify": "Toolbar button tooltip for making text justified."
}
11 changes: 10 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,18 @@
"dependencies": {
"@ckeditor/ckeditor5-core": "^1.0.0-alpha.1",
"@ckeditor/ckeditor5-engine": "^1.0.0-alpha.1",
"@ckeditor/ckeditor5-utils": "^1.0.0-alpha.1"
"@ckeditor/ckeditor5-ui": "^1.0.0-alpha.1"
},
"devDependencies": {
"@ckeditor/ckeditor5-block-quote": "^1.0.0-alpha.1",
"@ckeditor/ckeditor5-editor-classic": "^1.0.0-alpha.1",
"@ckeditor/ckeditor5-enter": "^1.0.0-alpha.1",
"@ckeditor/ckeditor5-heading": "^1.0.0-alpha.1",
"@ckeditor/ckeditor5-image": "^1.0.0-alpha.1",
"@ckeditor/ckeditor5-list": "^1.0.0-alpha.1",
"@ckeditor/ckeditor5-paragraph": "^1.0.0-alpha.1",
"@ckeditor/ckeditor5-typing": "^1.0.0-alpha.1",
"@ckeditor/ckeditor5-utils": "^1.0.0-alpha.1",
"eslint": "^4.8.0",
"eslint-config-ckeditor5": "^1.0.6",
"husky": "^0.14.3",
Expand Down
36 changes: 36 additions & 0 deletions src/alignment.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/**
* @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
* For licensing, see LICENSE.md.
*/

/**
* @module alignment/alignment
*/

import Plugin from '@ckeditor/ckeditor5-core/src/plugin';

import AlignmentEditing from './alignmentediting';
import AlignmentUI from './alignmentui';

/**
* The alignment plugin.
*
* It requires {@link module:alignment/alignmentediting~AlignmentEditing} and {@link module:alignment/alignmentui~AlignmentUI} plugins.
*
* @extends module:core/plugin~Plugin
*/
export default class Alignment extends Plugin {
/**
* @inheritDoc
*/
static get requires() {
return [ AlignmentEditing, AlignmentUI ];
}

/**
* @inheritDoc
*/
static get pluginName() {
return 'Alignment';
}
}
147 changes: 147 additions & 0 deletions src/alignmentcommand.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
/**
* @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
* For licensing, see LICENSE.md.
*/

/**
* @module alignment/alignmentcommand
*/

import Command from '@ckeditor/ckeditor5-core/src/command';
import first from '@ckeditor/ckeditor5-utils/src/first';

/**
* The alignment command plugin.
*
* @extends module:core/command~Command
*/
export default class AlignmentCommand extends Command {
/**
* Creates an instance of the command.
*
* @param {module:core/editor/editor~Editor} editor The editor instance.
* @param {'left'|'right'|'center'|'justify'} type Alignment type to be handled by this command.
* @param {Boolean} isDefault Indicates if command is of default type.
*/
constructor( editor, type, isDefault ) {
super( editor );

/**
* The type of the list created by the command.
*
* @readonly
* @member {'left'|'right'|'center'|'justify'}
*/
this.type = type;

/**
* Whether this command has default type.
*
* @readonly
* @private
* @member {Boolean}
*/
this._isDefault = isDefault;

/**
* A flag indicating whether the command is active, which means that the selection starts in a block
* that has defined alignment of the same type.
*
* @observable
* @readonly
* @member {Boolean} #value
*/
}

/**
* @inheritDoc
*/
refresh() {
const firstBlock = first( this.editor.document.selection.getSelectedBlocks() );

// As first check whether to enable or disable command as value will be always false if command cannot be enabled.
this.isEnabled = !!firstBlock && this._canBeAligned( firstBlock );
this.value = this._getValue( firstBlock );
}

/**
* Executes the command.
*
* @protected
* @param {Object} [options] Options for the executed command.
* @param {module:engine/model/batch~Batch} [options.batch] A batch to collect all the change steps.
* A new batch will be created if this option is not set.
*/
execute( options = {} ) {
const editor = this.editor;
const document = editor.document;

document.enqueueChanges( () => {
const batch = options.batch || document.batch();

// Get only those blocks from selected that can have alignment set
const blocks = Array.from( document.selection.getSelectedBlocks() ).filter( block => this._canBeAligned( block ) );

// Remove alignment attribute if current alignment is as selected or is default one.
// Default alignment should not be stored in model as it will bloat model data.
if ( this.value || this._isDefault ) {
removeAlignmentFromSelection( blocks, batch );
} else {
setAlignmentOnSelection( blocks, batch, this.type );
}
} );
}

/**
* Checks whether block can have aligned set.
*
* @param {module:engine/model/element~Element} block A block to be checked.
* @returns {Boolean}
* @private
*/
_canBeAligned( block ) {
const schema = this.editor.document.schema;

// Check if adding alignment attribute to selected block is allowed.
return schema.check( {
name: block.name,
// Apparently I must pass current attributes as otherwise adding alignment on listItem will fail.
attributes: [ ...block.getAttributeKeys(), 'alignment' ]
} );
}

/**
* Checks the command's {@link #value}.
*
* @private
* @param {module:engine/model/element~Element} firstBlock A first block in selection to be checked.
* @returns {Boolean} The current value.
*/
_getValue( firstBlock ) {
// The #_checkEnabled is checked as first so if command is disabled it's value is also false.
if ( !this.isEnabled || !firstBlock ) {
return false;
}

const selectionAlignment = firstBlock.getAttribute( 'alignment' );

// Command's value will be set when commands type is matched in selection or the selection is default one.
return selectionAlignment ? selectionAlignment === this.type : this._isDefault;
}
}

// Removes alignment attribute from blocks.
// @private
function removeAlignmentFromSelection( blocks, batch ) {
for ( const block of blocks ) {
batch.removeAttribute( block, 'alignment' );
}
}

// Sets alignment attribute on blocks.
// @private
function setAlignmentOnSelection( blocks, batch, type ) {
for ( const block of blocks ) {
batch.setAttribute( block, 'alignment', type );
}
}
Loading

0 comments on commit ae069ba

Please sign in to comment.