| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175 |
- /**
- * @license Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
- /* global window */
- import Babel from 'babel-standalone';
- // Imports necessary to run a React application.
- import React from 'react';
- import ReactDOM from 'react-dom';
- // The official <CKEditor> component for React.
- import CKEditor from '@ckeditor/ckeditor5-react';
- // The base editor class and features required to run the editor.
- import ClassicEditor from '@ckeditor/ckeditor5-editor-classic/src/classiceditor';
- import Essentials from '@ckeditor/ckeditor5-essentials/src/essentials';
- import Heading from '@ckeditor/ckeditor5-heading/src/heading';
- import Bold from '@ckeditor/ckeditor5-basic-styles/src/bold';
- import Italic from '@ckeditor/ckeditor5-basic-styles/src/italic';
- import Underline from '@ckeditor/ckeditor5-basic-styles/src/underline';
- import Link from '@ckeditor/ckeditor5-link/src/link';
- import Table from '@ckeditor/ckeditor5-table/src/table';
- import TableToolbar from '@ckeditor/ckeditor5-table/src/tabletoolbar';
- import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';
- import Command from '@ckeditor/ckeditor5-core/src/command';
- import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
- import { toWidget } from '@ckeditor/ckeditor5-widget/src/utils';
- import Widget from '@ckeditor/ckeditor5-widget/src/widget';
- // ckeditor/productpreviewediting.js
- class ProductPreviewEditing extends Plugin {
- static get requires() {
- return [ Widget ];
- }
- init() {
- this._defineSchema();
- this._defineConverters();
- this.editor.commands.add( 'insertProduct', new InsertProductPreviewCommand( this.editor ) );
- }
- _defineSchema() {
- const schema = this.editor.model.schema;
- schema.register( 'productPreview', {
- // Behaves like a self-contained object (e.g. an image).
- isObject: true,
- // Allow in places where other blocks are allowed (e.g. directly in the root).
- allowWhere: '$block',
- // Each product preview has an ID. A unique ID tells the application which
- // product it represents and makes it possible to render it inside a widget.
- allowAttributes: [ 'id' ]
- } );
- }
- _defineConverters() {
- const editor = this.editor;
- const conversion = editor.conversion;
- const renderProduct = editor.config.get( 'products' ).productRenderer;
- // <productPreview> converters ((data) view → model)
- conversion.for( 'upcast' ).elementToElement( {
- view: {
- name: 'section',
- classes: 'product'
- },
- model: ( viewElement, modelWriter ) => {
- // Read the "data-id" attribute from the view and set it as the "id" in the model.
- return modelWriter.createElement( 'productPreview', {
- id: parseInt( viewElement.getAttribute( 'data-id' ) )
- } );
- }
- } );
- // <productPreview> converters (model → data view)
- conversion.for( 'dataDowncast' ).elementToElement( {
- model: 'productPreview',
- view: ( modelElement, viewWriter ) => {
- // In the data view, the model <productPreview> corresponds to:
- //
- // <section class="product" data-id="..."></section>
- return viewWriter.createEmptyElement( 'section', {
- class: 'product',
- 'data-id': modelElement.getAttribute( 'id' )
- } );
- }
- } );
- // <productPreview> converters (model → editing view)
- conversion.for( 'editingDowncast' ).elementToElement( {
- model: 'productPreview',
- view: ( modelElement, viewWriter ) => {
- // In the editing view, the model <productPreview> corresponds to:
- //
- // <section class="product" data-id="...">
- // <div class="product__react-wrapper">
- // <ProductPreview /> (React component)
- // </div>
- // </section>
- const id = modelElement.getAttribute( 'id' );
- // The outermost <section class="product" data-id="..."></section> element.
- const section = viewWriter.createContainerElement( 'section', {
- class: 'product',
- 'data-id': id
- } );
- // The inner <div class="product__react-wrapper"></div> element.
- // This element will host a React <ProductPreview /> component.
- const reactWrapper = viewWriter.createUIElement( 'div', {
- class: 'product__react-wrapper'
- }, function( domDocument ) {
- const domElement = this.toDomElement( domDocument );
- // This the place where React renders the actual product preview hosted
- // by a UIElement in the view. you are using a function (renderer) passed as
- // editor.config.products#productRenderer.
- renderProduct( id, domElement );
- return domElement;
- } );
- viewWriter.insert( viewWriter.createPositionAt( section, 0 ), reactWrapper );
- return toWidget( section, viewWriter, { label: 'product preview widget' } );
- }
- } );
- }
- }
- // ckeditor/insertproductpreviewcommand.js
- class InsertProductPreviewCommand extends Command {
- execute( id ) {
- this.editor.model.change( writer => {
- // Insert <productPreview id="...">*</productPreview> at the current selection position
- // in a way which will result in creating a valid model structure.
- this.editor.model.insertContent( writer.createElement( 'productPreview', { id } ) );
- } );
- }
- refresh() {
- const model = this.editor.model;
- const selection = model.document.selection;
- const allowedIn = model.schema.findAllowedParent( selection.getFirstPosition(), 'productPreview' );
- this.isEnabled = allowedIn !== null;
- }
- }
- Object.assign( window, {
- Babel,
- React,
- ReactDOM,
- CKEditor,
- ClassicEditor,
- Essentials,
- Heading,
- Bold,
- Italic,
- Underline,
- Link,
- Table,
- TableToolbar,
- Paragraph,
- ProductPreviewEditing,
- InsertProductPreviewCommand
- } );
|