| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145 |
- /**
- * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
- */
- /**
- * @module code-block/codeblockediting
- */
- import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
- import ShiftEnter from '@ckeditor/ckeditor5-enter/src/shiftenter';
- import CodeBlockCommand from './codeblockcommand';
- /**
- * The editing part of the code block feature.
- *
- * Introduces the `'codeBlock'` command and the `'codeBlock'` model element.
- *
- * @extends module:core/plugin~Plugin
- */
- export default class CodeBlockEditing extends Plugin {
- /**
- * @inheritDoc
- */
- static get pluginName() {
- return 'CodeBlockEditing';
- }
- /**
- * @inheritDoc
- */
- static get requires() {
- return [ ShiftEnter ];
- }
- /**
- * @inheritDoc
- */
- init() {
- const editor = this.editor;
- const schema = editor.model.schema;
- // Command.
- editor.commands.add( 'codeBlock', new CodeBlockCommand( editor ) );
- // Schema.
- schema.register( 'codeBlock', { inheritAllFrom: '$block' } );
- // Disallow codeBlock in codeBlock.
- schema.addChildCheck( ( context, childDef ) => {
- if ( context.endsWith( 'codeBlock' ) && childDef.name === 'codeBlock' ) {
- return false;
- }
- } );
- // Disallow all attributes in `codeBlock`.
- schema.addAttributeCheck( context => {
- if ( context.endsWith( 'codeBlock' ) || context.endsWith( 'codeBlock $text' ) ) {
- return false;
- }
- } );
- // Conversion.
- editor.conversion.for( 'editingDowncast' ).elementToElement( { model: 'codeBlock', view: 'pre' } );
- editor.conversion.for( 'dataDowncast' ).elementToElement( { model: 'codeBlock', view: 'pre' } );
- editor.data.downcastDispatcher.on( 'insert:softBreak', dataModelViewSoftBreakInsertion( editor.model ), { priority: 'high' } );
- editor.data.upcastDispatcher.on( 'element:pre', dataViewModelPreInsertion( editor.data ) );
- }
- /**
- * @inheritDoc
- */
- afterInit() {
- const editor = this.editor;
- const viewDoc = editor.editing.view.document;
- this.listenTo( viewDoc, 'enter', ( evt, data ) => {
- const doc = editor.model.document;
- const positionParent = doc.selection.getLastPosition().parent;
- if ( positionParent.is( 'codeBlock' ) ) {
- editor.execute( 'shiftEnter' );
- data.preventDefault();
- evt.stop();
- }
- } );
- }
- }
- // A model-to-view converter for the new line separator.
- //
- // @param {module:engine/model/model~Model} model
- // @returns {Function} Returns a conversion callback.
- function dataModelViewSoftBreakInsertion( model ) {
- return ( evt, data, conversionApi ) => {
- if ( data.item.parent.name !== 'codeBlock' ) {
- return;
- }
- const { writer, mapper, consumable } = conversionApi;
- if ( !consumable.consume( data.item, 'insert' ) ) {
- return;
- }
- const position = mapper.toViewPosition( model.createPositionBefore( data.item ) );
- writer.insert( position, writer.createText( '\n' ) );
- };
- }
- // A view-to-model converter for `pre` tag.
- //
- // @param {module:engine/controller/datacontroller~DataController} dataController
- // @returns {Function} Returns a conversion callback.
- function dataViewModelPreInsertion( dataController ) {
- return ( evt, data, conversionApi ) => {
- const { consumable, writer } = conversionApi;
- if ( !consumable.consume( data.viewItem, { name: true } ) ) {
- return;
- }
- const modelItem = writer.createElement( 'codeBlock' );
- const stringifiedElement = dataController.processor.toData( data.viewItem );
- const textData = new RegExp( /^<pre>(.*)<\/pre>$/, 's' ).exec( stringifiedElement )[ 1 ];
- const textLines = textData.split( '\n' ).map( data => writer.createText( data ) );
- const lastLine = textLines[ textLines.length - 1 ];
- for ( const node of textLines ) {
- writer.append( node, modelItem );
- if ( node !== lastLine ) {
- writer.appendElement( 'softBreak', modelItem );
- }
- }
- writer.insert( modelItem, data.modelCursor );
- data.modelCursor = writer.createPositionAfter( modelItem );
- data.modelRange = writer.createRange( data.modelCursor );
- };
- }
|