autoformat.js 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. /**
  2. * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
  3. * For licensing, see LICENSE.md.
  4. */
  5. /**
  6. * @module autoformat/autoformat
  7. */
  8. import BlockAutoformatEngine from './blockautoformatengine';
  9. import InlineAutoformatEngine from './inlineautoformatengine';
  10. import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
  11. /**
  12. * Includes a set of predefined autoformatting actions.
  13. *
  14. * ## Bulleted list
  15. *
  16. * You can create a bulleted list by staring a line with:
  17. *
  18. * * `* `
  19. * * `- `
  20. *
  21. * ## Numbered list
  22. *
  23. * You can create a numbered list by staring a line with:
  24. *
  25. * * `1. `
  26. * * `1) `
  27. *
  28. * ## Headings
  29. *
  30. * You can create a heading by starting a line with:
  31. *
  32. * `# ` – will create Heading 1,
  33. * `## ` – will create Heading 2,
  34. * `### ` – will create Heading 3.
  35. *
  36. * ## Bold and italic
  37. *
  38. * You can apply bold or italic to a text by typing Markdown formatting:
  39. *
  40. * * `**foo bar**` or `__foo bar__` – will bold the text,
  41. * * `*foo bar*` or `_foo bar_` – will italicize the text,
  42. *
  43. * NOTE: Remember to add proper features to the editor configuration. Autoformatting will be enabled only for those
  44. * commands that are included in the actual configuration. For example: `bold` autoformatting will not work if there is no
  45. * `bold` command registered in the editor.
  46. *
  47. * @extends module:core/plugin~Plugin
  48. */
  49. export default class Autoformat extends Plugin {
  50. /**
  51. * @inheritDoc
  52. */
  53. static get pluginName() {
  54. return 'autoformat/autoformat';
  55. }
  56. /**
  57. * @inheritDoc
  58. */
  59. afterInit() {
  60. this._addListAutoformats();
  61. this._addBasicStylesAutoformats();
  62. this._addHeadingAutoformats();
  63. this._addBlockQuoteAutoformats();
  64. }
  65. /**
  66. * Adds autoformatting related to the {@link module:list/list~List}.
  67. *
  68. * When typed:
  69. * - `* ` or `- ` - a paragraph will be changed to a bulleted list,
  70. * - `1. ` or `1) ` - a paragraph will be changed to a numbered list ("1" can be any digit or list of digits).
  71. *
  72. * @private
  73. */
  74. _addListAutoformats() {
  75. const commands = this.editor.commands;
  76. if ( commands.has( 'bulletedList' ) ) {
  77. // eslint-disable-next-line no-new
  78. new BlockAutoformatEngine( this.editor, /^[*-]\s$/, 'bulletedList' );
  79. }
  80. if ( commands.has( 'numberedList' ) ) {
  81. // eslint-disable-next-line no-new
  82. new BlockAutoformatEngine( this.editor, /^\d+[.|)]?\s$/, 'numberedList' );
  83. }
  84. }
  85. /**
  86. * Adds autoformatting related to the {@link module:basic-styles/bold~Bold} and
  87. * {@link module:basic-styles/italic~Italic}.
  88. *
  89. * When typed:
  90. * - `**foobar**`: `**` characters are removed, and `foobar` is set to bold,
  91. * - `__foobar__`: `__` characters are removed, and `foobar` is set to bold,
  92. * - `*foobar*`: `*` characters are removed, and `foobar` is set to italic,
  93. * - `_foobar_`: `_` characters are removed, and `foobar` is set to italic.
  94. *
  95. * @private
  96. */
  97. _addBasicStylesAutoformats() {
  98. const commands = this.editor.commands;
  99. if ( commands.has( 'bold' ) ) {
  100. /* eslint-disable no-new */
  101. new InlineAutoformatEngine( this.editor, /(\*\*)([^*]+)(\*\*)$/g, 'bold' );
  102. new InlineAutoformatEngine( this.editor, /(__)([^_]+)(__)$/g, 'bold' );
  103. /* eslint-enable no-new */
  104. }
  105. if ( commands.has( 'italic' ) ) {
  106. // The italic autoformatter cannot be triggered by the bold markers, so we need to check the
  107. // text before the pattern (e.g. `(?:^|[^\*])`).
  108. /* eslint-disable no-new */
  109. new InlineAutoformatEngine( this.editor, /(?:^|[^*])(\*)([^*_]+)(\*)$/g, 'italic' );
  110. new InlineAutoformatEngine( this.editor, /(?:^|[^_])(_)([^_]+)(_)$/g, 'italic' );
  111. /* eslint-enable no-new */
  112. }
  113. }
  114. /**
  115. * Adds autoformatting related to {@link module:heading/heading~Heading}.
  116. *
  117. * It is using a number at the end of the command name to associate it with the proper trigger:
  118. * * `heading1` will be executed when typing `#`,
  119. * * `heading2` will be executed when typing `##`,
  120. * * `heading3` will be executed when typing `###`.
  121. *
  122. * @private
  123. */
  124. _addHeadingAutoformats() {
  125. const commands = this.editor.commands;
  126. const options = this.editor.config.get( 'heading.options' );
  127. if ( options ) {
  128. for ( const option of options ) {
  129. const commandName = option.modelElement;
  130. let match;
  131. if ( commands.has( commandName ) && ( match = commandName.match( /\d+$/ ) ) ) {
  132. const level = match[ 0 ];
  133. const regExp = new RegExp( `^(#{${ level }})\\s$` );
  134. // eslint-disable-next-line no-new
  135. new BlockAutoformatEngine( this.editor, regExp, context => {
  136. const { batch } = context;
  137. this.editor.execute( commandName, { batch } );
  138. } );
  139. }
  140. }
  141. }
  142. }
  143. _addBlockQuoteAutoformats() {
  144. if ( this.editor.commands.has( 'blockQuote' ) ) {
  145. // eslint-disable-next-line no-new
  146. new BlockAutoformatEngine( this.editor, /^>\s$/, 'blockQuote' );
  147. }
  148. }
  149. }