8
0
Quellcode durchsuchen

Bootstrap the reconversion demo.

Maciej Gołaszewski vor 5 Jahren
Ursprung
Commit
dbca0867cf

+ 4 - 0
packages/ckeditor5-engine/docs/_snippets/framework/build-element-reconversion-source.js

@@ -7,4 +7,8 @@
 
 import ClassicEditor from '@ckeditor/ckeditor5-build-classic/src/ckeditor';
 
+import { toWidget, toWidgetEditable } from '@ckeditor/ckeditor5-widget/src/utils';
+
 window.ClassicEditor = ClassicEditor;
+window.toWidget = toWidget;
+window.toWidgetEditable = toWidgetEditable;

+ 67 - 0
packages/ckeditor5-engine/docs/_snippets/framework/element-reconversion-demo.html

@@ -0,0 +1,67 @@
+<style>
+	.ck-content .info-box {
+		background: hsl(0, 0%, 45%);
+		border: 1px solid hsl(0, 0%, 80%);
+		padding: 1em;
+		border-radius: 8px;
+	}
+
+	.ck-content .info-box-title {
+		margin-bottom: 0.5em;
+		font-size: 1.4em;
+		color: inherit;
+		border-bottom-color: inherit;
+		border-bottom-style: solid;
+		border-bottom-width: 1px;
+	}
+
+	.ck-content .info-box-warning {
+		background: hsl(48, 100%, 87%);
+		border: 1px solid hsl(47, 100%, 62%);
+	}
+
+	.ck-content .info-box-warning .info-box-title {
+		color: hsl(47, 100%, 32%)
+	}
+
+	.ck-content .info-box-info {
+		background: hsl(205, 100%, 95%);
+		border: 1px solid hsl(205, 91%, 82%);
+	}
+
+	.ck-content .info-box-info .info-box-title {
+		color: hsl(204, 79%, 41%)
+	}
+
+	.ck-content .info-box-content {
+		padding: 8px 10px;
+		background: hsl(0, 0%, 100%);
+		border-radius: 6px;
+		margin-top: 0.5em;
+	}
+
+	.ck-content .info-box-content p:only-child,
+	.ck-content .info-box-content p:last-child {
+		margin-bottom: 0;
+	}
+</style>
+
+<div id="editor-element-reconversion">
+	<p>Info:</p>
+	<div class="info-box info-box-info">
+		<div class="info-box-title">Hey! Did you know?</div>
+		<div class="info-box-content">
+			<p>Editable content of the <strong>info box</strong>.</p>
+		</div>
+		<div class="info-box-content">
+			<p>Another content box.</p>
+		</div>
+	</div>
+	<p>Warning:</p>
+	<div class="info-box info-box-warning">
+		<div class="info-box-title">Watch out for <strong>this</strong>!</div>
+		<div class="info-box-content">
+			<p>Editable content of the <strong>info box</strong>.</p>
+		</div>
+	</div>
+</div>

+ 129 - 0
packages/ckeditor5-engine/docs/_snippets/framework/element-reconversion-demo.js

@@ -0,0 +1,129 @@
+/**
+ * @license Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+/* globals ClassicEditor, console, window, document */
+
+import { CS_CONFIG } from '@ckeditor/ckeditor5-cloud-services/tests/_utils/cloud-services-config';
+
+const getTypeFromViewElement = viewElement => {
+	for ( const type of [ 'info', 'warning' ] ) {
+		if ( viewElement.hasClass( `info-box-${ type }` ) ) {
+			return type;
+		}
+	}
+
+	return 'info';
+};
+
+class ComplexInfoBox {
+	constructor( editor ) {
+		// Schema definition.
+		editor.model.schema.register( 'complexInfoBox', {
+			allowWhere: '$block',
+			allowContentOf: '$root',
+			isObject: true,
+			allowAttributes: [ 'infoBoxType', 'infoBoxURL' ]
+		} );
+
+		editor.model.schema.register( 'complexInfoBoxTitle', {
+			isLimit: true,
+			allowIn: 'complexInfoBox',
+			allowContentOf: '$block'
+		} );
+
+		editor.model.schema.register( 'complexInfoBoxContent', {
+			isLimit: true,
+			allowIn: 'complexInfoBox',
+			allowContentOf: '$root'
+		} );
+
+		// Upcast converter.
+		editor.conversion.for( 'upcast' )
+			.elementToElement( {
+				view: {
+					name: 'div',
+					classes: [ 'info-box' ]
+				},
+				model( viewElement, { writer } ) {
+					const complexInfoBox = writer.createElement( 'complexInfoBox' );
+
+					const type = getTypeFromViewElement( viewElement );
+
+					writer.setAttribute( 'infoBoxType', type, complexInfoBox );
+					writer.setAttribute( 'infoBoxURL', 'https://ckeditor.com', complexInfoBox );
+
+					return complexInfoBox;
+				}
+			} )
+			.elementToElement( {
+				view: {
+					name: 'div',
+					classes: [ 'info-box-title' ]
+				},
+				model: 'complexInfoBoxTitle'
+			} )
+			.elementToElement( {
+				view: {
+					name: 'div',
+					classes: [ 'info-box-content' ]
+				},
+				model: 'complexInfoBoxContent'
+			} );
+
+		// The downcast conversion must be split as you need a widget in the editing pipeline.
+		editor.conversion.for( 'downcast' ).elementToElement( {
+			model: 'complexInfoBox',
+			view( modelElement, { writer, consumable, mapper } ) {
+				const complexInfoBoxView = writer.createContainerElement( 'div', { class: 'info-box' } );
+
+				const type = modelElement.getAttribute( 'infoBoxType' ) || 'info';
+
+				writer.addClass( `info-box-${ type }`, complexInfoBoxView );
+
+				for ( const child of modelElement.getChildren() ) {
+					const childView = writer.createContainerElement( 'div' );
+
+					if ( child.is( 'element', 'complexInfoBoxTitle' ) ) {
+						writer.addClass( 'info-box-title', childView );
+					} else {
+						writer.addClass( 'info-box-content', childView );
+					}
+
+					consumable.consume( child, 'insert' );
+					mapper.bindElements( child, childView );
+					writer.insert( writer.createPositionAt( complexInfoBoxView, 'end' ), childView );
+				}
+
+				return complexInfoBoxView;
+			}
+		} );
+	}
+}
+
+ClassicEditor
+	.create( document.querySelector( '#editor-element-reconversion' ), {
+		cloudServices: CS_CONFIG,
+		extraPlugins: [ ComplexInfoBox ],
+		image: {
+			toolbar: [ 'imageStyle:full', 'imageStyle:side', '|', 'imageTextAlternative' ]
+		},
+		table: {
+			contentToolbar: [
+				'tableColumn',
+				'tableRow',
+				'mergeTableCells'
+			]
+		},
+		toolbar: {
+			items: [ 'paragraph', 'heading1', 'heading2', '|', '|', 'bold', 'italic', '|' ],
+			viewportTopOffset: window.getViewportTopOffsetConfig()
+		}
+	} )
+	.then( editor => {
+		window.editor = editor;
+	} )
+	.catch( err => {
+		console.error( err );
+	} );

+ 9 - 9
packages/ckeditor5-engine/docs/_snippets/framework/extending-content-custom-element-converter.html

@@ -1,44 +1,44 @@
 <style>
-	.info-box {
+	.ck-content .info-box {
 		background: hsl(0, 0%, 45%);
 		border: 1px solid hsl(0, 0%, 80%);
 		padding: 1em;
 		border-radius: 8px;
 	}
 
-	.info-box-title {
+	.ck-content .info-box-title {
 		margin-bottom: 0.5em;
 		font-size: 1.4em;
 		font-weight: bold;
 		color: inherit;
 	}
 
-	.info-box-warning {
+	.ck-content .info-box-warning {
 		background: hsl(48, 100%, 87%);
 		border: 1px solid hsl(47, 100%, 62%);
 	}
 
-	.info-box-warning .info-box-title  {
+	.ck-content .info-box-warning .info-box-title  {
 		color: hsl(47, 100%, 32%)
 	}
 
-	.info-box-info {
+	.ck-content .info-box-info {
 		background: hsl(205, 100%, 95%);
 		border: 1px solid hsl(205, 91%, 82%);
 	}
 
-	.info-box-info .info-box-title  {
+	.ck-content .info-box-info .info-box-title  {
 		color: hsl(204, 79%, 41%)
 	}
 
-	.info-box-content {
+	.ck-content .info-box-content {
 		padding: 8px 10px;
 		background: hsl(0, 0%, 100%);
 		border-radius: 6px;
 	}
 
-	.info-box-content p:only-child,
-	.info-box-content p:last-child {
+	.ck-content .info-box-content p:only-child,
+	.ck-content .info-box-content p:last-child {
 		margin-bottom: 0;
 	}
 </style>

+ 19 - 1
packages/ckeditor5-engine/docs/framework/guides/deep-dive/element-reconversion.md

@@ -13,4 +13,22 @@ order: 50
 
 This guide introduces {@link framework/guides/architecture/editing-engine#editing-pipeline "downcast"} reconversion concepts. It expands concepts used in other conversion guides such as {@link framework/guides/deep-dive/custom-element-conversion custom element conversion}.
 
-## Introduction
+## Before we begin
+
+This guide builds on top of two similar features:
+
+- custom element conversion
+- implementing a block widget
+
+## Demo
+
+Let's take a look at the below enhanced info box might behave:
+
+{@snippet framework/element-reconversion-demo}
+
+The above demo assumes that each box:
+
+- have 1 title
+- have multiple content-boxes
+- have type
+- have URL associated