texttransformation.js 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  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. testTransformation( '(tm)', '™' );
  37. } );
  38. describe( 'mathematical', () => {
  39. testTransformation( '1/2', '½' );
  40. testTransformation( '<=', '≤' );
  41. } );
  42. describe( 'typography', () => {
  43. testTransformation( '...', '…' );
  44. testTransformation( ' -- ', ' – ' );
  45. testTransformation( ' --- ', ' — ' );
  46. } );
  47. describe( 'quotations', () => {
  48. describe( 'english US', () => {
  49. describe( 'primary', () => {
  50. testTransformation( '"Foo 1992 — bar(1) baz: xyz."', '“Foo 1992 — bar(1) baz: xyz.”' );
  51. testTransformation( '\' foo "bar"', '\' foo “bar”' );
  52. } );
  53. describe( 'secondary', () => {
  54. testTransformation( '\'Foo 1992 — bar(1) baz: xyz.\'', '‘Foo 1992 — bar(1) baz: xyz.’' );
  55. testTransformation( '" foo \'bar\'', '" foo ‘bar’' );
  56. } );
  57. } );
  58. } );
  59. function testTransformation( transformFrom, transformTo ) {
  60. it( `should transform "${ transformFrom }" to "${ transformTo }"`, () => {
  61. setData( model, '<paragraph>A foo[]</paragraph>' );
  62. const letters = transformFrom.split( '' );
  63. for ( const letter of letters ) {
  64. model.enqueueChange( model.createBatch(), writer => {
  65. writer.insertText( letter, doc.selection.focus );
  66. } );
  67. }
  68. expect( getData( model, { withoutSelection: true } ) ).to.equal( `<paragraph>A foo${ transformTo }</paragraph>` );
  69. } );
  70. it( `should not transform "${ transformFrom }" to "${ transformTo }" inside text`, () => {
  71. setData( model, '<paragraph>[]</paragraph>' );
  72. // Insert text - should not be transformed.
  73. model.enqueueChange( model.createBatch(), writer => {
  74. writer.insertText( `foo ${ transformFrom } bar`, doc.selection.focus );
  75. } );
  76. // Enforce text watcher check after insertion.
  77. model.enqueueChange( model.createBatch(), writer => {
  78. writer.insertText( ' ', doc.selection.focus );
  79. } );
  80. expect( getData( model, { withoutSelection: true } ) ).to.equal( `<paragraph>foo ${ transformFrom } bar </paragraph>` );
  81. } );
  82. }
  83. } );
  84. describe( 'configuration', () => {
  85. it( 'should allow adding own rules with string pattern', () => {
  86. return createEditorInstance( {
  87. textTransformation: {
  88. transformations: [
  89. {
  90. from: 'CKS',
  91. to: 'CKSource'
  92. }
  93. ]
  94. }
  95. } ).then( () => {
  96. setData( model, '<paragraph>[]</paragraph>' );
  97. model.enqueueChange( model.createBatch(), writer => {
  98. writer.insertText( 'CKS', doc.selection.focus );
  99. } );
  100. expect( getData( model, { withoutSelection: true } ) ).to.equal( '<paragraph>CKSource</paragraph>' );
  101. } );
  102. } );
  103. it( 'should allow adding own rules with RegExp object', () => {
  104. return createEditorInstance( {
  105. textTransformation: {
  106. transformations: [
  107. {
  108. from: /([a-z]+)@(example.com)$/,
  109. to: '$1.at.$2'
  110. }
  111. ]
  112. }
  113. } ).then( () => {
  114. setData( model, '<paragraph>[]</paragraph>' );
  115. model.enqueueChange( model.createBatch(), writer => {
  116. writer.insertText( 'user@example.com', doc.selection.focus );
  117. } );
  118. expect( getData( model, { withoutSelection: true } ) ).to.equal( '<paragraph>user.at.example.com</paragraph>' );
  119. } );
  120. } );
  121. } );
  122. function createEditorInstance( additionalConfig = {} ) {
  123. return ClassicTestEditor
  124. .create( editorElement, Object.assign( {
  125. plugins: [ Paragraph, TextTransformation ]
  126. }, additionalConfig ) )
  127. .then( newEditor => {
  128. editor = newEditor;
  129. model = editor.model;
  130. doc = model.document;
  131. } );
  132. }
  133. } );