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 #9 from ckeditor/i/5924
Browse files Browse the repository at this point in the history
Fix: It should be possible to use multiple classes in the language configuration. Closes ckeditor/ckeditor5#5924.
  • Loading branch information
oleq authored Jan 28, 2020
2 parents c9e5c2c + 8a5d211 commit dca0fe4
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 7 deletions.
5 changes: 3 additions & 2 deletions docs/features/code-blocks.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ ClassicEditor

{@snippet features/code-block-custom-languages}

By default, the CSS class of the `<code>` element in the data and editing is generated using the `language` property (prefixed with "language-"). You can customize it by specifying an optional `class` property:
By default, the CSS class of the `<code>` element in the data and editing is generated using the `language` property (prefixed with "language-"). You can customize it by specifying an optional `class` property. You can set **multiple classes** but **only the first one** will be used as defining language class:

```js
ClassicEditor
Expand All @@ -56,7 +56,8 @@ ClassicEditor
{ language: 'php', label: 'PHP', class: 'php-code' },

// Use the "js" class for JavaScript code blocks.
{ language: 'javascript', label: 'JavaScript', class: 'js' },
// Note that only the first ("js") class will determine the language of the block when loading data.
{ language: 'javascript', label: 'JavaScript', class: 'js javascript js-code' },

// Python code blocks will have the default "language-python" CSS class.
{ language: 'python', label: 'Python' }
Expand Down
10 changes: 6 additions & 4 deletions src/codeblock.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export default class CodeBlock extends Plugin {
*
* ClassicEditor
* .create( editorElement, {
* codeBlock: ... // The code block feature configuration.
* codeBlock: ... // The code block feature configuration.
* } )
* .then( ... )
* .catch( ... );
Expand Down Expand Up @@ -103,20 +103,22 @@ export default class CodeBlock extends Plugin {
*
* <pre><code class="language-javascript">window.alert( 'Hello world!' )</code></pre>
*
* You can customize the CSS class by specifying an optional `class` property in the language definition:
* You can customize the CSS class by specifying an optional `class` property in the language definition.
* You can set **multiple classes** but **only the first one** will be used as defining language class:
*
* ClassicEditor
* .create( document.querySelector( '#editor' ), {
* codeBlock: {
* languages: [
* // Do not render the CSS class for the plain text code blocks.
* { language: 'plaintext', label: 'Plain text', class: '' },
* { language: 'plaintext', label: 'Plain text', class: '' },
*
* // Use the "php-code" class for PHP code blocks.
* { language: 'php', label: 'PHP', class: 'php-code' },
*
* // Use the "js" class for JavaScript code blocks.
* { language: 'javascript', label: 'JavaScript', class: 'js' },
* // Note that only the first ("js") class will determine the language of the block when loading data.
* { language: 'javascript', label: 'JavaScript', class: 'js javascript js-code' },
*
* // Python code blocks will have the default "language-python" CSS class.
* { language: 'python', label: 'Python' }
Expand Down
13 changes: 12 additions & 1 deletion src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,18 @@ export function getNormalizedAndLocalizedLanguageDefinitions( editor ) {
* @param {Object.<String,String>}
*/
export function getPropertyAssociation( languageDefs, key, value ) {
return Object.assign( {}, ...languageDefs.map( def => ( { [ def[ key ] ]: def[ value ] } ) ) );
const association = {};

for ( const def of languageDefs ) {
if ( key === 'class' ) {
// Only the first class is considered.
association[ def[ key ].split( ' ' ).shift() ] = def[ value ];
} else {
association[ def[ key ] ] = def[ value ];
}
}

return association;
}

/**
Expand Down
74 changes: 74 additions & 0 deletions tests/codeblockediting.js
Original file line number Diff line number Diff line change
Expand Up @@ -781,6 +781,38 @@ describe( 'CodeBlockEditing', () => {
return editor.destroy();
} );
} );

it( 'should set multiple classes on the <code> if it was configured so', () => {
const element = document.createElement( 'div' );
document.body.appendChild( element );

return ClassicTestEditor
.create( element, {
plugins: [ CodeBlockEditing, AlignmentEditing, BoldEditing, Enter, Paragraph ],
codeBlock: {
languages: [
{ language: 'javascript', label: 'JavaScript', class: 'language-js' },
{ language: 'swift', label: 'Swift', class: 'swift ios-code' },
]
}
} )
.then( editor => {
const model = editor.model;

setModelData( model,
'<codeBlock language="swift">foo</codeBlock>' +
'<codeBlock language="javascript">foo</codeBlock>'
);
expect( editor.getData() ).to.equal(
'<pre><code class="swift ios-code">foo</code></pre>' +
'<pre><code class="language-js">foo</code></pre>'
);

element.remove();

return editor.destroy();
} );
} );
} );

describe( 'data pipeline v -> m conversion ', () => {
Expand Down Expand Up @@ -1008,6 +1040,48 @@ describe( 'CodeBlockEditing', () => {
return editor.destroy();
} );
} );

// https://github.com/ckeditor/ckeditor5/issues/5924
it( 'should upcast using only the first class from config as a defining language class', () => {
// "baz" is the first class configured for the "baz" language.
return ClassicTestEditor.create( '<pre><code class="baz">foo</code></pre>', {
plugins: [ CodeBlockEditing ],
codeBlock: {
languages: [
{ language: 'foo', label: 'Foo', class: 'foo' },
{ language: 'baz', label: 'Baz', class: 'baz bar' },
{ language: 'qux', label: 'Qux', class: 'qux' },
]
}
} ).then( editor => {
model = editor.model;

expect( getModelData( model ) ).to.equal( '<codeBlock language="baz">[]foo</codeBlock>' );

return editor.destroy();
} );
} );

// https://github.com/ckeditor/ckeditor5/issues/5924
it( 'should not upcast if the class is not the first (defining) language class', () => {
// "bar" is the second class configured for the "baz" language.
return ClassicTestEditor.create( '<pre><code class="bar">foo</code></pre>', {
plugins: [ CodeBlockEditing ],
codeBlock: {
languages: [
{ language: 'foo', label: 'Foo', class: 'foo' },
{ language: 'baz', label: 'Baz', class: 'baz bar' },
{ language: 'qux', label: 'Qux', class: 'qux' },
]
}
} ).then( editor => {
model = editor.model;

expect( getModelData( model ) ).to.equal( '<codeBlock language="foo">[]foo</codeBlock>' );

return editor.destroy();
} );
} );
} );
} );

Expand Down

0 comments on commit dca0fe4

Please sign in to comment.