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 #61 from ckeditor/i/6165
Browse files Browse the repository at this point in the history
Feature: Introduced an option for both `FontSize` and `FontFamily` plugins that allow preserving any `font-family` and `font-size` values when pasting or loading content. Closes ckeditor/ckeditor5#6165. Closes ckeditor/ckeditor5#2278.
  • Loading branch information
Reinmar authored Mar 25, 2020
2 parents 4414b1e + 14ec7fc commit b22efec
Show file tree
Hide file tree
Showing 19 changed files with 833 additions and 135 deletions.
55 changes: 47 additions & 8 deletions docs/features/font.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ The {@link module:font/font~Font} plugin enables the following features in the r

## Configuring the font family feature

It is possible to configure which font family options are supported by the WYSIWYG editor. Use the {@link module:font/fontfamily~FontFamilyConfig#options `fontFamily.options`} configuration option to do so.
It is possible to configure which font family options are supported by the WYSIWYG editor. Use the {@link module:font/fontfamily~FontFamilyConfig#options `config.fontFamily.options`} configuration option to do so.

Use the special `'default'` keyword to use the default font family defined in the web page styles. It removes any custom font family.

Expand All @@ -47,9 +47,28 @@ ClassicEditor

{@snippet features/custom-font-family-options}

### Accept all font names

By default, all `font-family` values that are not specified in the `config.fontFamily.options` are stripped. You can enable support for all font names by using the {@link module:font/fontfamily~FontFamilyConfig#supportAllValues `config.fontFamily.supportAllValues`} option.

```js
ClassicEditor
.create( document.querySelector( '#editor' ), {
fontFamily: {
options: [
// ...
],
supportAllValues: true
},
// ...
} )
.then( ... )
.catch( ... );
```

## Configuring the font size feature

It is possible to configure which font size options are supported by the WYSIWYG editor. Use the {@link module:font/fontsize~FontSizeConfig#options `fontSize.options`} configuration option to do so.
It is possible to configure which font size options are supported by the WYSIWYG editor. Use the {@link module:font/fontsize~FontSizeConfig#options `config.fontSize.options`} configuration option to do so.

Use the special `'default'` keyword to use the default font size defined in the web page styles. It removes any custom font size.

Expand Down Expand Up @@ -150,6 +169,26 @@ ClassicEditor

{@snippet features/custom-font-size-numeric-options}

### Prevent removing non-specified values

By default, all `font-size` values that are not specified in the `config.fontSize.options` are stripped. You can enable support for all font sizes by using the {@link module:font/fontfamily~FontSizeConfig#supportAllValues `config.fontSize.supportAllValues`} option.


```js
ClassicEditor
.create( document.querySelector( '#editor' ), {
fontSize: {
options: [
// ...
],
supportAllValues: true
},
// ...
} )
.then( ... )
.catch( ... );
```

## Configuring the font color and font background color features

Both font color and font background color features are configurable and share the same configuration format.
Expand All @@ -164,7 +203,7 @@ Check out the WYSIWYG editor below with both features customized using the edito

### Specifying available colors

It is possible to configure which colors are available in the color dropdown. Use the {@link module:font/fontcolor~FontColorConfig#colors `fontColor.colors`} and {@link module:font/fontbackgroundcolor~FontBackgroundColorConfig#colors `fontBackgroundColor.colors`} configuration options to do so.
It is possible to configure which colors are available in the color dropdown. Use the {@link module:font/fontcolor~FontColorConfig#colors `config.fontColor.colors`} and {@link module:font/fontbackgroundcolor~FontBackgroundColorConfig#colors `config.fontBackgroundColor.colors`} configuration options to do so.

```js
ClassicEditor
Expand Down Expand Up @@ -232,7 +271,7 @@ ClassicEditor

### Changing the geometry of the color grid

You can configure the number of columns in the color dropdown by setting the {@link module:font/fontcolor~FontColorConfig#columns `fontColor.columns`} and {@link module:font/fontbackgroundcolor~FontBackgroundColorConfig#columns `fontBackgroundColor.columns`} configuration options.
You can configure the number of columns in the color dropdown by setting the {@link module:font/fontcolor~FontColorConfig#columns `config.fontColor.columns`} and {@link module:font/fontbackgroundcolor~FontBackgroundColorConfig#columns `config.fontBackgroundColor.columns`} configuration options.

Usually, you will want to use this option when changing the number of [available colors](#specifying-available-colors).

Expand Down Expand Up @@ -265,7 +304,7 @@ ClassicEditor

The font and font background color dropdowns contain the "Document colors" section. It lists the colors already used in the document for the users to be able to easily reuse them (for consistency purposes).

By default, the number of displayed document colors is limited to one row, but you can adjust it (or remove the whole section) by using the {@link module:font/fontcolor~FontColorConfig#documentColors `fontColor.documentColors`} or {@link module:font/fontbackgroundcolor~FontBackgroundColorConfig#documentColors `fontBackgroundColor.documentColors`} options.
By default, the number of displayed document colors is limited to one row, but you can adjust it (or remove the whole section) by using the {@link module:font/fontcolor~FontColorConfig#documentColors `config.fontColor.documentColors`} or {@link module:font/fontbackgroundcolor~FontBackgroundColorConfig#documentColors `config.fontBackgroundColor.documentColors`} options.

```js
ClassicEditor
Expand Down Expand Up @@ -340,7 +379,7 @@ The {@link module:font/fontfamily~FontFamily} plugin registers the following com
* The `'fontFamily'` dropdown.
* The {@link module:font/fontfamily/fontfamilycommand~FontFamilyCommand `'fontFamily'`} command.

The number of options and their names correspond to the {@link module:font/fontfamily~FontFamilyConfig#options `fontFamily.options`} configuration option.
The number of options and their names correspond to the {@link module:font/fontfamily~FontFamilyConfig#options `config.fontFamily.options`} configuration option.

You can change the font family of the current selection by executing the command with a desired value:

Expand Down Expand Up @@ -386,7 +425,7 @@ The {@link module:font/fontsize~FontSize} plugin registers the following compone
* The `'fontSize'` dropdown.
* The {@link module:font/fontsize/fontsizecommand~FontSizeCommand `'fontSize'`} command.

The number of options and their names correspond to the {@link module:font/fontsize~FontSizeConfig#options `fontSize.options`} configuration option.
The number of options and their names correspond to the {@link module:font/fontsize~FontSizeConfig#options `config.fontSize.options`} configuration option.

You can change the font size of the current selection by executing the command with a desired value:

Expand All @@ -398,7 +437,7 @@ The {@link module:font/fontsize~FontSize} plugin registers the following compone
editor.execute( 'fontSize', { value: 'small' } );
```

Passing an empty value will remove any `fontSize` set:
Passing an empty value will remove any `config.fontSize` set:

```js
editor.execute( 'fontSize' );
Expand Down
16 changes: 16 additions & 0 deletions src/fontfamily.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,3 +112,19 @@ export default class FontFamily extends Plugin {
*
* @member {Array.<String|module:font/fontfamily~FontFamilyOption>} module:font/fontfamily~FontFamilyConfig#options
*/

/**
* By default the plugin removes any `font-family` value that does not match to the plugin's configuration. It means if you paste a content
* with font families that the editor does not understand, the font-family attribute will be removed and the content will be displayed
* with the font.
*
* You can preserve pasted font family values by switching the option:
*
* const fontSizeConfig = {
* supportAllValues: true
* };
*
* Now, the font families, not specified in the editor's configuration, won't be removed when pasting the content.
*
* @member {Boolean} module:font/fontfamily~FontFamilyConfig#supportAllValues
*/
39 changes: 37 additions & 2 deletions src/fontfamily/fontfamilyediting.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ export default class FontFamilyEditing extends Plugin {
'Times New Roman, Times, serif',
'Trebuchet MS, Helvetica, sans-serif',
'Verdana, Geneva, sans-serif'
]
],
supportAllValues: false
} );
}

Expand All @@ -71,8 +72,42 @@ export default class FontFamilyEditing extends Plugin {
const definition = buildDefinition( FONT_FAMILY, options );

// Set-up the two-way conversion.
editor.conversion.attributeToElement( definition );
if ( editor.config.get( 'fontFamily.supportAllValues' ) ) {
this._prepareAnyValueConverters();
} else {
editor.conversion.attributeToElement( definition );
}

editor.commands.add( FONT_FAMILY, new FontFamilyCommand( editor ) );
}

/**
* Those converters enable keeping any value found as `style="font-family: *"` as a value of an attribute on a text even
* if it isn't defined in the plugin configuration.
*
* @private
*/
_prepareAnyValueConverters() {
const editor = this.editor;

editor.conversion.for( 'downcast' ).attributeToElement( {
model: FONT_FAMILY,
view: ( attributeValue, writer ) => {
return writer.createAttributeElement( 'span', { style: 'font-family:' + attributeValue }, { priority: 7 } );
}
} );

editor.conversion.for( 'upcast' ).attributeToAttribute( {
model: {
key: FONT_FAMILY,
value: viewElement => viewElement.getStyle( 'font-family' )
},
view: {
name: 'span',
styles: {
'font-family': /.*/
}
}
} );
}
}
13 changes: 12 additions & 1 deletion src/fontfamily/fontfamilyui.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,18 @@ function _prepareListOptions( options, command ) {
} )
};

def.model.bind( 'isOn' ).to( command, 'value', value => value === option.model );
def.model.bind( 'isOn' ).to( command, 'value', value => {
// "Default" or check in strict font-family converters mode.
if ( value === option.model ) {
return true;
}

if ( !value || !option.model ) {
return false;
}

return value.split( ',' )[ 0 ].replace( /'/g, '' ).toLowerCase() === option.model.toLowerCase();
} );

// Try to set a dropdown list item style.
if ( option.view && option.view.styles ) {
Expand Down
32 changes: 32 additions & 0 deletions src/fontsize.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,22 @@ export default class FontSize extends Plugin {
* options: [ 9, 10, 11, 12, 13, 14, 15 ]
* };
*
* Also, you can define a label in the dropdown for numerical values:
*
* const fontSizeConfig = {
* options: [
* {
* title: 'Small',
* model: '8px
* },
* 'default',
* {
* title: 'Big',
* model: '14px
* }
* ]
* };
*
* Font size can be applied using the command API. To do that, use the `'fontSize'` command and pass the desired font size as a `value`.
* For example, the following code will apply the `fontSize` attribute with the **tiny** value to the current selection:
*
Expand All @@ -114,3 +130,19 @@ export default class FontSize extends Plugin {
*
* @member {Array.<String|Number|module:font/fontsize~FontSizeOption>} module:font/fontsize~FontSizeConfig#options
*/

/**
* By default the plugin removes any `font-size` value that does not match to the plugin's configuration. It means if you paste a content
* with font sizes that the editor does not understand, the font-size attribute will be removed and the content will be displayed
* with the default size.
*
* You can preserve pasted font size values by switching the option:
*
* const fontSizeConfig = {
* supportAllValues: true
* };
*
* Now, the font sizes, not specified in the editor's configuration, won't be removed when pasting the content.
*
* @member {Boolean} module:font/fontsize~FontSizeConfig#supportAllValues
*/
59 changes: 49 additions & 10 deletions src/fontsize/fontsizeediting.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,31 +48,70 @@ export default class FontSizeEditing extends Plugin {
'default',
'big',
'huge'
]
],
supportAllValues: false
} );
}

/**
* @inheritDoc
*/
init() {
const editor = this.editor;

// Allow fontSize attribute on text nodes.
editor.model.schema.extend( '$text', { allowAttributes: FONT_SIZE } );
editor.model.schema.setAttributeProperties( FONT_SIZE, {
isFormatting: true,
copyOnEnter: true
} );

const supportAllValues = editor.config.get( 'fontSize.supportAllValues' );

// Define view to model conversion.
const options = normalizeOptions( this.editor.config.get( 'fontSize.options' ) ).filter( item => item.model );
const options = normalizeOptions( this.editor.config.get( 'fontSize.options' ), { supportAllValues } )
.filter( item => item.model );
const definition = buildDefinition( FONT_SIZE, options );

// Set-up the two-way conversion.
editor.conversion.attributeToElement( definition );
if ( supportAllValues ) {
this._prepareAnyValueConverters();
} else {
editor.conversion.attributeToElement( definition );
}

// Add FontSize command.
editor.commands.add( FONT_SIZE, new FontSizeCommand( editor ) );
}

/**
* @inheritDoc
* Those converters enable keeping any value found as `style="font-size: *"` as a value of an attribute on a text even
* if it isn't defined in the plugin configuration.
*
* @private
*/
init() {
_prepareAnyValueConverters() {
const editor = this.editor;

// Allow fontSize attribute on text nodes.
editor.model.schema.extend( '$text', { allowAttributes: FONT_SIZE } );
editor.model.schema.setAttributeProperties( FONT_SIZE, {
isFormatting: true,
copyOnEnter: true
editor.conversion.for( 'downcast' ).attributeToElement( {
model: FONT_SIZE,
view: ( attributeValue, writer ) => {
if ( !attributeValue ) {
return;
}

return writer.createAttributeElement( 'span', { style: 'font-size:' + attributeValue }, { priority: 7 } );
}
} );

editor.conversion.for( 'upcast' ).attributeToAttribute( {
model: {
key: FONT_SIZE,
value: viewElement => viewElement.getStyle( 'font-size' )
},
view: {
name: 'span'
}
} );
}
}
Loading

0 comments on commit b22efec

Please sign in to comment.