8
0

headingediting.js 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. /**
  2. * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved.
  3. * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
  4. */
  5. /**
  6. * @module heading/headingediting
  7. */
  8. import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
  9. import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';
  10. import HeadingCommand from './headingcommand';
  11. import priorities from '@ckeditor/ckeditor5-utils/src/priorities';
  12. const defaultModelElement = 'paragraph';
  13. /**
  14. * The headings engine feature. It handles switching between block formats – headings and paragraph.
  15. * This class represents the engine part of the heading feature. See also {@link module:heading/heading~Heading}.
  16. * It introduces `heading1`-`headingN` commands which allow to convert paragraphs into headings.
  17. *
  18. * @extends module:core/plugin~Plugin
  19. */
  20. export default class HeadingEditing extends Plugin {
  21. /**
  22. * @inheritDoc
  23. */
  24. constructor( editor ) {
  25. super( editor );
  26. editor.config.define( 'heading', {
  27. options: [
  28. { model: 'paragraph', title: 'Paragraph', class: 'ck-heading_paragraph' },
  29. { model: 'heading1', view: 'h2', title: 'Heading 1', class: 'ck-heading_heading1' },
  30. { model: 'heading2', view: 'h3', title: 'Heading 2', class: 'ck-heading_heading2' },
  31. { model: 'heading3', view: 'h4', title: 'Heading 3', class: 'ck-heading_heading3' }
  32. ]
  33. } );
  34. }
  35. /**
  36. * @inheritDoc
  37. */
  38. static get requires() {
  39. return [ Paragraph ];
  40. }
  41. /**
  42. * @inheritDoc
  43. */
  44. init() {
  45. const editor = this.editor;
  46. const options = editor.config.get( 'heading.options' );
  47. const modelElements = [];
  48. for ( const option of options ) {
  49. // Skip paragraph - it is defined in required Paragraph feature.
  50. if ( option.model !== defaultModelElement ) {
  51. // Schema.
  52. editor.model.schema.register( option.model, {
  53. inheritAllFrom: '$block'
  54. } );
  55. editor.conversion.elementToElement( option );
  56. modelElements.push( option.model );
  57. }
  58. }
  59. this._addDefaultH1Conversion( editor );
  60. // Register the heading command for this option.
  61. editor.commands.add( 'heading', new HeadingCommand( editor, modelElements ) );
  62. }
  63. /**
  64. * @inheritDoc
  65. */
  66. afterInit() {
  67. // If the enter command is added to the editor, alter its behavior.
  68. // Enter at the end of a heading element should create a paragraph.
  69. const editor = this.editor;
  70. const enterCommand = editor.commands.get( 'enter' );
  71. const options = editor.config.get( 'heading.options' );
  72. if ( enterCommand ) {
  73. this.listenTo( enterCommand, 'afterExecute', ( evt, data ) => {
  74. const positionParent = editor.model.document.selection.getFirstPosition().parent;
  75. const isHeading = options.some( option => positionParent.is( option.model ) );
  76. if ( isHeading && !positionParent.is( defaultModelElement ) && positionParent.childCount === 0 ) {
  77. data.writer.rename( positionParent, defaultModelElement );
  78. }
  79. } );
  80. }
  81. }
  82. /**
  83. * Adds default conversion for `h1` -> `heading1` with a low priority.
  84. *
  85. * @private
  86. * @param {module:core/editor/editor~Editor} editor Editor instance on which to add the `h1` conversion.
  87. */
  88. _addDefaultH1Conversion( editor ) {
  89. editor.conversion.for( 'upcast' ).elementToElement( {
  90. model: 'heading1',
  91. view: 'h1',
  92. // With a `low` priority, `paragraph` plugin autoparagraphing mechanism is executed. Make sure
  93. // this listener is called before it. If not, `h1` will be transformed into a paragraph.
  94. converterPriority: priorities.get( 'low' ) + 1
  95. } );
  96. }
  97. }