This repository has been archived by the owner on Jun 26, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathheadingengine.js
104 lines (90 loc) · 3.44 KB
/
headingengine.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
/**
* @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
* For licensing, see LICENSE.md.
*/
/**
* @module heading/headingengine
*/
import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
import buildModelConverter from '@ckeditor/ckeditor5-engine/src/conversion/buildmodelconverter';
import buildViewConverter from '@ckeditor/ckeditor5-engine/src/conversion/buildviewconverter';
import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';
import HeadingCommand from './headingcommand';
const defaultModelElement = 'paragraph';
/**
* The headings engine feature. It handles switching between block formats – headings and paragraph.
* This class represents the engine part of the heading feature. See also {@link module:heading/heading~Heading}.
*
* @extends modules:core/plugin~Plugin
*/
export default class HeadingEngine extends Plugin {
/**
* @inheritDoc
*/
constructor( editor ) {
super( editor );
// TODO: This needs proper documentation, i.e. why paragraph entry does not need
// more properties (https://github.com/ckeditor/ckeditor5/issues/403).
// TODO: Document CSS classes as well.
editor.config.define( 'heading', {
options: [
{ modelElement: 'paragraph', title: 'Paragraph', class: 'ck-heading_paragraph' },
{ modelElement: 'heading1', viewElement: 'h2', title: 'Heading 1', class: 'ck-heading_heading1' },
{ modelElement: 'heading2', viewElement: 'h3', title: 'Heading 2', class: 'ck-heading_heading2' },
{ modelElement: 'heading3', viewElement: 'h4', title: 'Heading 3', class: 'ck-heading_heading3' }
]
} );
}
/**
* @inheritDoc
*/
static get requires() {
return [ Paragraph ];
}
/**
* @inheritDoc
*/
init() {
const editor = this.editor;
const data = editor.data;
const editing = editor.editing;
const options = editor.config.get( 'heading.options' );
for ( let option of options ) {
// Skip paragraph - it is defined in required Paragraph feature.
if ( option.modelElement !== defaultModelElement ) {
// Schema.
editor.document.schema.registerItem( option.modelElement, '$block' );
// Build converter from model to view for data and editing pipelines.
buildModelConverter().for( data.modelToView, editing.modelToView )
.fromElement( option.modelElement )
.toElement( option.viewElement );
// Build converter from view to model for data pipeline.
buildViewConverter().for( data.viewToModel )
.fromElement( option.viewElement )
.toElement( option.modelElement );
// Register the heading command for this option.
editor.commands.set( option.modelElement, new HeadingCommand( editor, option ) );
}
}
}
/**
* @inheritDoc
*/
afterInit() {
// If the enter command is added to the editor, alter its behavior.
// Enter at the end of a heading element should create a paragraph.
const editor = this.editor;
const enterCommand = editor.commands.get( 'enter' );
const options = editor.config.get( 'heading.options' );
if ( enterCommand ) {
this.listenTo( enterCommand, 'afterExecute', ( evt, data ) => {
const positionParent = editor.document.selection.getFirstPosition().parent;
const batch = data.batch;
const isHeading = options.some( option => positionParent.is( option.modelElement ) );
if ( isHeading && !positionParent.is( defaultModelElement ) && positionParent.childCount === 0 ) {
batch.rename( positionParent, defaultModelElement );
}
} );
}
}
}