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

Commit 6015b68

Browse files
authored
Merge pull request #1 from ckeditor/t/ckeditor5/908
Feature: Introduced the Remove Format feature. Closes ckeditor/ckeditor5#908.
2 parents 73e5ef3 + 0f153a2 commit 6015b68

19 files changed

+834
-2
lines changed

docs/_snippets/features/build-remove-format-source.html

Whitespace-only changes.
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/**
2+
* @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
3+
* For licensing, see LICENSE.md.
4+
*/
5+
6+
/* globals window */
7+
8+
import ClassicEditor from '@ckeditor/ckeditor5-build-classic/src/ckeditor';
9+
import RemoveFormat from '@ckeditor/ckeditor5-remove-format/src/removeformat';
10+
11+
import Alignment from '@ckeditor/ckeditor5-alignment/src/alignment';
12+
import Font from '@ckeditor/ckeditor5-font/src/font';
13+
import Bold from '@ckeditor/ckeditor5-basic-styles/src/bold';
14+
import Italic from '@ckeditor/ckeditor5-basic-styles/src/italic';
15+
import Underline from '@ckeditor/ckeditor5-basic-styles/src/underline';
16+
import Strikethrough from '@ckeditor/ckeditor5-basic-styles/src/strikethrough';
17+
import Subscript from '@ckeditor/ckeditor5-basic-styles/src/subscript';
18+
import Superscript from '@ckeditor/ckeditor5-basic-styles/src/superscript';
19+
import Code from '@ckeditor/ckeditor5-basic-styles/src/code';
20+
21+
ClassicEditor.builtinPlugins.push(
22+
RemoveFormat, Alignment, Font, Bold, Italic, Underline, Strikethrough, Subscript, Superscript, Code );
23+
24+
window.ClassicEditor = ClassicEditor;
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<div id="editor">
2+
<p>
3+
You can use the <strong>remove format</strong> feature to easily clean up text formatting.
4+
</p>
5+
<p>
6+
Some examples of the formatting removed by this feature:
7+
<strong>bold</strong>,
8+
<i>italics</i>,
9+
<u>underline</u>,
10+
<s>strikethrough</s>,
11+
<code>code</code>,
12+
<sub>subscript</sub>,
13+
<sup>superscript</sup>,
14+
<span class="text-tiny">font size</span> as well as
15+
<span style="font-family: 'Courier New', Courier, monospace;">font family</span>.
16+
</p>
17+
<p style="text-align: center">
18+
Remove format resets the text alignment too.
19+
</p>
20+
<p>
21+
<b>Note</b>: The feature will not erase non-formatting content — <a href="https://ckeditor.com">your links</a> are safe!
22+
</p>
23+
</div>
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/**
2+
* @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
3+
* For licensing, see LICENSE.md.
4+
*/
5+
6+
/* globals ClassicEditor, console, window, document */
7+
8+
ClassicEditor
9+
.create( document.querySelector( '#editor' ), {
10+
toolbar: {
11+
items: [
12+
'removeformat',
13+
'|',
14+
'bold',
15+
'italic',
16+
'underline',
17+
'strikethrough',
18+
'code',
19+
'subscript',
20+
'superscript',
21+
'fontSize',
22+
'fontFamily',
23+
'alignment',
24+
'link',
25+
'|',
26+
'undo',
27+
'redo'
28+
],
29+
viewportTopOffset: window.getViewportTopOffsetConfig()
30+
}
31+
} )
32+
.then( editor => {
33+
window.editor = editor;
34+
} )
35+
.catch( err => {
36+
console.error( err.stack );
37+
} );

docs/api/remove-format.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
---
2+
category: api-reference
3+
---
4+
5+
# CKEditor 5 remove format feature
6+
7+
[![npm version](https://badge.fury.io/js/%40ckeditor%2Fckeditor5-remove-format.svg)](https://www.npmjs.com/package/@ckeditor/ckeditor5-remove-format)
8+
9+
This package implements the remove format feature for CKEditor 5.
10+
11+
## Demo
12+
13+
Check out the {@link features/remove-format#demo demo in the remove format feature} guide.
14+
15+
## Documentation
16+
17+
See the {@link features/remove-format remove format feature} guide and the {@link module:remove-format/removeformat~RemoveFormat} plugin documentation.
18+
19+
## Installation
20+
21+
```bash
22+
npm install --save @ckeditor/ckeditor5-remove-format
23+
```
24+
25+
## Contribute
26+
27+
The source code of this package is available on GitHub in https://github.com/ckeditor/ckeditor5-remove-format.
28+
29+
## External links
30+
31+
* [`@ckeditor/ckeditor5-remove-format` on npm](https://www.npmjs.com/package/@ckeditor/ckeditor5-remove-format)
32+
* [`ckeditor/ckeditor5-remove-format` on GitHub](https://github.com/ckeditor/ckeditor5-remove-format)
33+
* [Issue tracker](https://github.com/ckeditor/ckeditor5-remove-format/issues)
34+
* [Changelog](https://github.com/ckeditor/ckeditor5-remove-format/blob/master/CHANGELOG.md)

docs/features/remove-format.md

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
---
2+
title: Removing Text Formatting
3+
menu-title: Remove Format
4+
category: features
5+
---
6+
7+
{@snippet features/build-remove-format-source}
8+
9+
The {@link module:remove-format/removeformat~RemoveFormat Remove Format} feature allows to quickly remove any text formatting applied using inline HTML elements and CSS styles, like {@link features/basic-styles basic text styles} (bold, italic, etc.), {@link features/font font family, size, and color} and similar. Note that block—level formatting ({@link features/headings headings}, {@link features/image images}) and semantic data ({@link features/link links}) will not be removed.
10+
11+
## Demo
12+
13+
Select the content you want to clean up and press the "Remove Format" button in the toolbar:
14+
15+
{@snippet features/remove-format}
16+
17+
## Configuring the remove format feature
18+
19+
The feature has no integration–level configuration. Once enabled, it works out–of–the–box with all {@link features/index core editor features}.
20+
21+
## Integrating with editor features
22+
23+
To make it possible for the remove formatting feature to work with your custom content, you must first mark it in the {@link framework/guides/architecture/editing-engine#schema schema}. All you need to do is set the `isFormatting` property on your custom {@link framework/guides/architecture/editing-engine#text-attributes text attribute}. {@link module:engine/model/schema~Schema#setAttributeProperties Learn more about attribute properties.}
24+
25+
## Installation
26+
27+
To add this feature to your editor install the [`@ckeditor/ckeditor5-remove-format`](https://www.npmjs.com/package/@ckeditor/ckeditor5-remove-format) package:
28+
29+
```bash
30+
npm install --save @ckeditor/ckeditor5-remove-format
31+
```
32+
33+
And add it to your plugin list and the toolbar configuration:
34+
35+
```js
36+
import RemoveFormat from '@ckeditor/ckeditor5-remove-format/src/removeformat';
37+
38+
ClassicEditor
39+
.create( document.querySelector( '#editor' ), {
40+
plugins: [ RemoveFormat, ... ],
41+
toolbar: [ 'removeFormat', ... ]
42+
} )
43+
.then( ... )
44+
.catch( ... );
45+
```
46+
47+
<info-box info>
48+
Read more about {@link builds/guides/integration/installing-plugins installing plugins}.
49+
</info-box>
50+
51+
## Common API
52+
53+
The {@link module:remove-format/removeformat~RemoveFormat} plugin registers the `'removeFormat'` UI button component the command of the same name implemented by {@link module:remove-format/removeformatcommand~RemoveFormatCommand}.
54+
55+
The command can be executed using the {@link module:core/editor/editor~Editor#execute `editor.execute()`} method:
56+
57+
```js
58+
// Removes all the formatting in the selection.
59+
editor.execute( 'removeFormat' );
60+
```
61+
62+
<info-box>
63+
We recommend using the official {@link framework/guides/development-tools#ckeditor-5-inspector CKEditor 5 inspector} for development and debugging. It will give you tons of useful information about the state of the editor such as internal data structures, selection, commands, and many more.
64+
</info-box>
65+
66+
## Contribute
67+
68+
The source code of the feature is available on GitHub in https://github.com/ckeditor/ckeditor5-remove-format.

lang/contexts.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"Remove Format": "The label of the remove format toolbar button."
3+
}

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212
"dependencies": {
1313
"@ckeditor/ckeditor5-core": "^12.0.0",
1414
"@ckeditor/ckeditor5-ui": "^12.0.0",
15-
"@ckeditor/ckeditor5-utils": "^12.0.0"
15+
"@ckeditor/ckeditor5-utils": "^12.0.0",
16+
"eslint-plugin-ckeditor5-rules": "^0.0.2"
1617
},
1718
"devDependencies": {
1819
"@ckeditor/ckeditor5-basic-styles": "^11.0.0",
@@ -24,7 +25,7 @@
2425
"@ckeditor/ckeditor5-link": "^11.0.0",
2526
"@ckeditor/ckeditor5-typing": "^12.0.0",
2627
"@ckeditor/ckeditor5-undo": "^11.0.0",
27-
"eslint": "^5.5.0",
28+
"eslint": "^5.15.3",
2829
"eslint-config-ckeditor5": "^1.0.11",
2930
"husky": "^1.3.1",
3031
"lint-staged": "^7.0.0"

src/removeformat.js

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/**
2+
* @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
3+
* For licensing, see LICENSE.md.
4+
*/
5+
6+
/**
7+
* @module remove-format/removeformat
8+
*/
9+
10+
import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
11+
12+
import RemoveFormatUI from './removeformatui';
13+
import RemoveFormatCommand from './removeformatcommand';
14+
15+
/**
16+
* The remove format plugin.
17+
*
18+
* This is a "glue" plugin which loads the {@link module:remove-format/removeformatcommand~RemoveFormatCommand command}
19+
* and the {@link module:remove-format/removeformatui~RemoveFormatUI UI}.
20+
*
21+
* For a detailed overview, check out the {@glink features/remove-format Remove Format} feature documentation.
22+
*
23+
* @extends module:core/plugin~Plugin
24+
*/
25+
export default class RemoveFormat extends Plugin {
26+
/**
27+
* @inheritDoc
28+
*/
29+
static get requires() {
30+
return [ RemoveFormatCommand, RemoveFormatUI ];
31+
}
32+
33+
init() {
34+
const editor = this.editor;
35+
36+
editor.commands.add( 'removeFormat', new RemoveFormatCommand( editor ) );
37+
}
38+
39+
/**
40+
* @inheritDoc
41+
*/
42+
static get pluginName() {
43+
return 'RemoveFormat';
44+
}
45+
}

src/removeformatcommand.js

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
/**
2+
* @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
3+
* For licensing, see LICENSE.md.
4+
*/
5+
6+
/**
7+
* @module remove-format/removeformatcommand
8+
*/
9+
10+
import Command from '@ckeditor/ckeditor5-core/src/command';
11+
import first from '@ckeditor/ckeditor5-utils/src/first';
12+
13+
/**
14+
* The remove format command.
15+
*
16+
* It is used by the {@link module:remove-format/removeformat~RemoveFormat remove format feature}
17+
* to clear the formatting in the selection.
18+
*
19+
* editor.execute( 'removeFormat' );
20+
*
21+
* @extends module:core/command~Command
22+
*/
23+
export default class RemoveFormatCommand extends Command {
24+
/**
25+
* @inheritDoc
26+
*/
27+
refresh() {
28+
const model = this.editor.model;
29+
30+
this.isEnabled = !!first( this._getFormattingItems( model.document.selection, model.schema ) );
31+
}
32+
33+
/**
34+
* @inheritDoc
35+
*/
36+
execute() {
37+
const model = this.editor.model;
38+
const schema = model.schema;
39+
40+
model.change( writer => {
41+
for ( const item of this._getFormattingItems( model.document.selection, schema ) ) {
42+
if ( item.is( 'selection' ) ) {
43+
for ( const attributeName of this._getFormattingAttributes( item, schema ) ) {
44+
writer.removeSelectionAttribute( attributeName );
45+
}
46+
} else {
47+
// Workaround for items with multiple removable attributes. See
48+
// https://github.com/ckeditor/ckeditor5-remove-format/pull/1#pullrequestreview-220515609
49+
const itemRange = writer.createRangeOn( item );
50+
51+
for ( const attributeName of this._getFormattingAttributes( item, schema ) ) {
52+
writer.removeAttribute( attributeName, itemRange );
53+
}
54+
}
55+
}
56+
} );
57+
}
58+
59+
/**
60+
* Returns an iterable of items in a selection (including selection itself) that have formatting model
61+
* attributes to be removed by the feature.
62+
*
63+
* @protected
64+
* @param {module:engine/model/documentselection~DocumentSelection} selection
65+
* @param {module:engine/model/schema~Schema} schema Schema describing the item.
66+
* @returns {Iterable.<module:engine/model/item~Item>|Iterable.<module:engine/model/documentselection~DocumentSelection>}
67+
*/
68+
* _getFormattingItems( selection, schema ) {
69+
const itemHasRemovableFormatting = item => {
70+
return !!first( this._getFormattingAttributes( item, schema ) );
71+
};
72+
73+
for ( const curRange of selection.getRanges() ) {
74+
for ( const item of curRange.getItems() ) {
75+
if ( itemHasRemovableFormatting( item ) ) {
76+
yield item;
77+
}
78+
}
79+
}
80+
81+
// Finally the selection might be formatted as well, so make sure to check it.
82+
if ( itemHasRemovableFormatting( selection ) ) {
83+
yield selection;
84+
}
85+
}
86+
87+
/**
88+
* Returns an iterable of formatting attributes of a given model item.
89+
*
90+
* **Note:** Formatting items have the `isFormatting` property set `true`.
91+
*
92+
* @protected
93+
* @param {module:engine/model/item~Item|module:engine/model/documentselection~DocumentSelection} item
94+
* @param {module:engine/model/schema~Schema} schema Schema describing the item.
95+
* @returns {Iterable.<String>} Names of formatting attributes found in a given item.
96+
*/
97+
* _getFormattingAttributes( item, schema ) {
98+
for ( const [ attributeName ] of item.getAttributes() ) {
99+
const attributeProperties = schema.getAttributeProperties( attributeName );
100+
101+
if ( attributeProperties && attributeProperties.isFormatting ) {
102+
yield attributeName;
103+
}
104+
}
105+
}
106+
}

0 commit comments

Comments
 (0)