8
0
Quellcode durchsuchen

Merge pull request #9 from ckeditor/i/5924

Fix: It should be possible to use multiple classes in the language configuration. Closes ckeditor/ckeditor5#5924.
Aleksander Nowodzinski vor 5 Jahren
Ursprung
Commit
50413c5261

+ 3 - 2
packages/ckeditor5-code-block/docs/features/code-blocks.md

@@ -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
@@ -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' }

+ 6 - 4
packages/ckeditor5-code-block/src/codeblock.js

@@ -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( ... );
@@ -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' }

+ 12 - 1
packages/ckeditor5-code-block/src/utils.js

@@ -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;
 }
 
 /**

+ 74 - 0
packages/ckeditor5-code-block/tests/codeblockediting.js

@@ -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 ', () => {
@@ -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();
+				} );
+			} );
 		} );
 	} );