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

Commit ae069ba

Browse files
authored
Merge pull request #6 from ckeditor/t/2
Feature: Initial implementation. Closes #2.
2 parents f0c0298 + 59cebd3 commit ae069ba

22 files changed

+1367
-1
lines changed

lang/contexts.json

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"Align left": "Toolbar button tooltip for aligning text to the left.",
3+
"Align right": "Toolbar button tooltip for aligning text to the right.",
4+
"Align center": "Toolbar button tooltip for aligning text to center.",
5+
"Justify": "Toolbar button tooltip for making text justified."
6+
}

package.json

+10-1
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,18 @@
99
"dependencies": {
1010
"@ckeditor/ckeditor5-core": "^1.0.0-alpha.1",
1111
"@ckeditor/ckeditor5-engine": "^1.0.0-alpha.1",
12-
"@ckeditor/ckeditor5-utils": "^1.0.0-alpha.1"
12+
"@ckeditor/ckeditor5-ui": "^1.0.0-alpha.1"
1313
},
1414
"devDependencies": {
15+
"@ckeditor/ckeditor5-block-quote": "^1.0.0-alpha.1",
16+
"@ckeditor/ckeditor5-editor-classic": "^1.0.0-alpha.1",
17+
"@ckeditor/ckeditor5-enter": "^1.0.0-alpha.1",
18+
"@ckeditor/ckeditor5-heading": "^1.0.0-alpha.1",
19+
"@ckeditor/ckeditor5-image": "^1.0.0-alpha.1",
20+
"@ckeditor/ckeditor5-list": "^1.0.0-alpha.1",
21+
"@ckeditor/ckeditor5-paragraph": "^1.0.0-alpha.1",
22+
"@ckeditor/ckeditor5-typing": "^1.0.0-alpha.1",
23+
"@ckeditor/ckeditor5-utils": "^1.0.0-alpha.1",
1524
"eslint": "^4.8.0",
1625
"eslint-config-ckeditor5": "^1.0.6",
1726
"husky": "^0.14.3",

src/alignment.js

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/**
2+
* @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3+
* For licensing, see LICENSE.md.
4+
*/
5+
6+
/**
7+
* @module alignment/alignment
8+
*/
9+
10+
import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
11+
12+
import AlignmentEditing from './alignmentediting';
13+
import AlignmentUI from './alignmentui';
14+
15+
/**
16+
* The alignment plugin.
17+
*
18+
* It requires {@link module:alignment/alignmentediting~AlignmentEditing} and {@link module:alignment/alignmentui~AlignmentUI} plugins.
19+
*
20+
* @extends module:core/plugin~Plugin
21+
*/
22+
export default class Alignment extends Plugin {
23+
/**
24+
* @inheritDoc
25+
*/
26+
static get requires() {
27+
return [ AlignmentEditing, AlignmentUI ];
28+
}
29+
30+
/**
31+
* @inheritDoc
32+
*/
33+
static get pluginName() {
34+
return 'Alignment';
35+
}
36+
}

src/alignmentcommand.js

+147
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
/**
2+
* @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
3+
* For licensing, see LICENSE.md.
4+
*/
5+
6+
/**
7+
* @module alignment/alignmentcommand
8+
*/
9+
10+
import Command from '@ckeditor/ckeditor5-core/src/command';
11+
import first from '@ckeditor/ckeditor5-utils/src/first';
12+
13+
/**
14+
* The alignment command plugin.
15+
*
16+
* @extends module:core/command~Command
17+
*/
18+
export default class AlignmentCommand extends Command {
19+
/**
20+
* Creates an instance of the command.
21+
*
22+
* @param {module:core/editor/editor~Editor} editor The editor instance.
23+
* @param {'left'|'right'|'center'|'justify'} type Alignment type to be handled by this command.
24+
* @param {Boolean} isDefault Indicates if command is of default type.
25+
*/
26+
constructor( editor, type, isDefault ) {
27+
super( editor );
28+
29+
/**
30+
* The type of the list created by the command.
31+
*
32+
* @readonly
33+
* @member {'left'|'right'|'center'|'justify'}
34+
*/
35+
this.type = type;
36+
37+
/**
38+
* Whether this command has default type.
39+
*
40+
* @readonly
41+
* @private
42+
* @member {Boolean}
43+
*/
44+
this._isDefault = isDefault;
45+
46+
/**
47+
* A flag indicating whether the command is active, which means that the selection starts in a block
48+
* that has defined alignment of the same type.
49+
*
50+
* @observable
51+
* @readonly
52+
* @member {Boolean} #value
53+
*/
54+
}
55+
56+
/**
57+
* @inheritDoc
58+
*/
59+
refresh() {
60+
const firstBlock = first( this.editor.document.selection.getSelectedBlocks() );
61+
62+
// As first check whether to enable or disable command as value will be always false if command cannot be enabled.
63+
this.isEnabled = !!firstBlock && this._canBeAligned( firstBlock );
64+
this.value = this._getValue( firstBlock );
65+
}
66+
67+
/**
68+
* Executes the command.
69+
*
70+
* @protected
71+
* @param {Object} [options] Options for the executed command.
72+
* @param {module:engine/model/batch~Batch} [options.batch] A batch to collect all the change steps.
73+
* A new batch will be created if this option is not set.
74+
*/
75+
execute( options = {} ) {
76+
const editor = this.editor;
77+
const document = editor.document;
78+
79+
document.enqueueChanges( () => {
80+
const batch = options.batch || document.batch();
81+
82+
// Get only those blocks from selected that can have alignment set
83+
const blocks = Array.from( document.selection.getSelectedBlocks() ).filter( block => this._canBeAligned( block ) );
84+
85+
// Remove alignment attribute if current alignment is as selected or is default one.
86+
// Default alignment should not be stored in model as it will bloat model data.
87+
if ( this.value || this._isDefault ) {
88+
removeAlignmentFromSelection( blocks, batch );
89+
} else {
90+
setAlignmentOnSelection( blocks, batch, this.type );
91+
}
92+
} );
93+
}
94+
95+
/**
96+
* Checks whether block can have aligned set.
97+
*
98+
* @param {module:engine/model/element~Element} block A block to be checked.
99+
* @returns {Boolean}
100+
* @private
101+
*/
102+
_canBeAligned( block ) {
103+
const schema = this.editor.document.schema;
104+
105+
// Check if adding alignment attribute to selected block is allowed.
106+
return schema.check( {
107+
name: block.name,
108+
// Apparently I must pass current attributes as otherwise adding alignment on listItem will fail.
109+
attributes: [ ...block.getAttributeKeys(), 'alignment' ]
110+
} );
111+
}
112+
113+
/**
114+
* Checks the command's {@link #value}.
115+
*
116+
* @private
117+
* @param {module:engine/model/element~Element} firstBlock A first block in selection to be checked.
118+
* @returns {Boolean} The current value.
119+
*/
120+
_getValue( firstBlock ) {
121+
// The #_checkEnabled is checked as first so if command is disabled it's value is also false.
122+
if ( !this.isEnabled || !firstBlock ) {
123+
return false;
124+
}
125+
126+
const selectionAlignment = firstBlock.getAttribute( 'alignment' );
127+
128+
// Command's value will be set when commands type is matched in selection or the selection is default one.
129+
return selectionAlignment ? selectionAlignment === this.type : this._isDefault;
130+
}
131+
}
132+
133+
// Removes alignment attribute from blocks.
134+
// @private
135+
function removeAlignmentFromSelection( blocks, batch ) {
136+
for ( const block of blocks ) {
137+
batch.removeAttribute( block, 'alignment' );
138+
}
139+
}
140+
141+
// Sets alignment attribute on blocks.
142+
// @private
143+
function setAlignmentOnSelection( blocks, batch, type ) {
144+
for ( const block of blocks ) {
145+
batch.setAttribute( block, 'alignment', type );
146+
}
147+
}

0 commit comments

Comments
 (0)