texttransformation.js 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  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. import ClassicTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/classictesteditor';
  6. import global from '@ckeditor/ckeditor5-utils/src/dom/global';
  7. import TextTransformation from '../src/texttransformation';
  8. import { getData, setData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model';
  9. import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';
  10. describe( 'Text transformation feature', () => {
  11. let editorElement, editor, model, doc;
  12. beforeEach( () => {
  13. editorElement = global.document.createElement( 'div' );
  14. global.document.body.appendChild( editorElement );
  15. } );
  16. afterEach( () => {
  17. editorElement.remove();
  18. if ( editor ) {
  19. return editor.destroy();
  20. }
  21. } );
  22. it( 'should be loaded', () => {
  23. return createEditorInstance().then( () => {
  24. expect( editor.plugins.get( TextTransformation ) ).to.instanceOf( TextTransformation );
  25. } );
  26. } );
  27. it( 'has proper name', () => {
  28. return createEditorInstance().then( () => {
  29. expect( TextTransformation.pluginName ).to.equal( 'TextTransformation' );
  30. } );
  31. } );
  32. describe( 'transformations', () => {
  33. beforeEach( createEditorInstance );
  34. describe( 'symbols', () => {
  35. testTransformation( '(c)', '©' );
  36. // TODO: skip because of CI: testTransformation( '(tm)', '™' );
  37. } );
  38. describe( 'mathematical', () => {
  39. testTransformation( '1/2', '½' );
  40. testTransformation( '<=', '≤' );
  41. } );
  42. describe( 'dashes', () => {
  43. testTransformation( ' -- ', ' – ' );
  44. testTransformation( ' --- ', ' — ' );
  45. } );
  46. describe( 'quotations', () => {
  47. describe( 'english US', () => {
  48. describe( 'primary', () => {
  49. testTransformation( '"Foo 1992 — bar(1) baz: xyz."', '“Foo 1992 — bar(1) baz: xyz.”' );
  50. testTransformation( '\' foo "bar"', '\' foo “bar”' );
  51. } );
  52. describe( 'secondary', () => {
  53. testTransformation( '\'Foo 1992 — bar(1) baz: xyz.\'', '‘Foo 1992 — bar(1) baz: xyz.’' );
  54. testTransformation( '" foo \'bar\'', '" foo ‘bar’' );
  55. } );
  56. } );
  57. } );
  58. function testTransformation( transformFrom, transformTo ) {
  59. it( `should transform "${ transformFrom }" to "${ transformTo }"`, () => {
  60. setData( model, '<paragraph>[]</paragraph>' );
  61. const letters = transformFrom.split( '' );
  62. for ( const letter of letters ) {
  63. model.enqueueChange( model.createBatch(), writer => {
  64. writer.insertText( letter, doc.selection.focus );
  65. } );
  66. }
  67. expect( getData( model, { withoutSelection: true } ) ).to.equal( `<paragraph>${ transformTo }</paragraph>` );
  68. } );
  69. it( `should not transform "${ transformFrom }" to "${ transformTo }" inside text`, () => {
  70. setData( model, '<paragraph>[]</paragraph>' );
  71. // Insert text - should not be transformed.
  72. model.enqueueChange( model.createBatch(), writer => {
  73. writer.insertText( `foo ${ transformFrom } bar`, doc.selection.focus );
  74. } );
  75. // Enforce text watcher check after insertion.
  76. model.enqueueChange( model.createBatch(), writer => {
  77. writer.insertText( ' ', doc.selection.focus );
  78. } );
  79. expect( getData( model, { withoutSelection: true } ) ).to.equal( `<paragraph>foo ${ transformFrom } bar </paragraph>` );
  80. } );
  81. }
  82. } );
  83. describe( 'configuration', () => {
  84. it( 'should allow adding own rules with string pattern', () => {
  85. return createEditorInstance( {
  86. textTransformation: {
  87. transformations: [
  88. {
  89. from: '([a-z]+)@(example.com)$',
  90. to: '$1.at.$2'
  91. }
  92. ]
  93. }
  94. } ).then( () => {
  95. setData( model, '<paragraph>[]</paragraph>' );
  96. model.enqueueChange( model.createBatch(), writer => {
  97. writer.insertText( 'user@example.com', doc.selection.focus );
  98. } );
  99. expect( getData( model, { withoutSelection: true } ) ).to.equal( '<paragraph>user.at.example.com</paragraph>' );
  100. } );
  101. } );
  102. it( 'should allow adding own rules with RegExp object', () => {
  103. return createEditorInstance( {
  104. textTransformation: {
  105. transformations: [
  106. {
  107. from: /([a-z]+)@(example.com)$/,
  108. to: '$1.at.$2'
  109. }
  110. ]
  111. }
  112. } ).then( () => {
  113. setData( model, '<paragraph>[]</paragraph>' );
  114. model.enqueueChange( model.createBatch(), writer => {
  115. writer.insertText( 'user@example.com', doc.selection.focus );
  116. } );
  117. expect( getData( model, { withoutSelection: true } ) ).to.equal( '<paragraph>user.at.example.com</paragraph>' );
  118. } );
  119. } );
  120. } );
  121. function createEditorInstance( additionalConfig = {} ) {
  122. return ClassicTestEditor
  123. .create( editorElement, Object.assign( {
  124. plugins: [ Paragraph, TextTransformation ]
  125. }, additionalConfig ) )
  126. .then( newEditor => {
  127. editor = newEditor;
  128. model = editor.model;
  129. doc = model.document;
  130. } );
  131. }
  132. } );