import Delta from 'quill-delta'; import { Range } from '../../../core/selection'; import Quill from '../../../core'; describe('Clipboard', function() { describe('events', function() { beforeEach(function() { this.quill = this.initialize(Quill, '

0123

5678

'); this.quill.setSelection(2, 5); }); describe('paste', function() { beforeAll(function() { this.clipboardEvent = { clipboardData: { getData: type => type === 'text/html' ? '|' : '|', }, preventDefault: () => {}, }; }); it('pastes html data', function(done) { this.quill.clipboard.onCapturePaste(this.clipboardEvent); setTimeout(() => { expect(this.quill.root).toEqualHTML( '

01|78

', ); expect(this.quill.getSelection()).toEqual(new Range(3)); done(); }, 2); }); it('pastes html data if present with file', function(done) { const upload = spyOn(this.quill.uploader, 'upload'); this.quill.clipboard.onCapturePaste( // eslint-disable-next-line prefer-object-spread Object.assign({}, this.clipboardEvent, { files: ['file '] }), ); setTimeout(() => { expect(upload).not.toHaveBeenCalled(); expect(this.quill.root).toEqualHTML( '

01|78

', ); expect(this.quill.getSelection()).toEqual(new Range(3)); done(); }, 2); }); it('does not fire selection-change', function(done) { const change = jasmine.createSpy('change'); this.quill.on('selection-change', change); this.quill.clipboard.onCapturePaste(this.clipboardEvent); setTimeout(function() { expect(change).not.toHaveBeenCalled(); done(); }, 2); }); }); it('dangerouslyPasteHTML(html)', function() { this.quill.clipboard.dangerouslyPasteHTML('abcd'); expect(this.quill.root).toEqualHTML( '

abcd

', ); }); it('dangerouslyPasteHTML(index, html)', function() { this.quill.clipboard.dangerouslyPasteHTML(2, 'ab'); expect(this.quill.root).toEqualHTML( '

01ab23

5678

', ); }); }); describe('convert', function() { beforeEach(function() { const quill = this.initialize(Quill, ''); this.clipboard = quill.clipboard; }); it('plain text', function() { const delta = this.clipboard.convert({ html: 'simple plain text' }); expect(delta).toEqual(new Delta().insert('simple plain text')); }); it('whitespace', function() { const html = '
0
1 2 3 4
' + '
5 6 7 8
'; const delta = this.clipboard.convert({ html }); expect(delta).toEqual(new Delta().insert('0\n1 2 3 4\n5 6 7 8')); }); it('inline whitespace', function() { const html = '

0 1 2

'; const delta = this.clipboard.convert({ html }); expect(delta).toEqual( new Delta() .insert('0 ') .insert('1', { bold: true }) .insert(' 2'), ); }); it('intentional whitespace', function() { const html = '1 2'; const delta = this.clipboard.convert({ html }); expect(delta).toEqual( new Delta() .insert('0\u00a0') .insert('1', { bold: true }) .insert('\u00a02'), ); }); it('consecutive intentional whitespace', function() { const html = '  1  '; const delta = this.clipboard.convert({ html }); expect(delta).toEqual( new Delta().insert('\u00a0\u00a01\u00a0\u00a0', { bold: true }), ); }); it('break', function() { const html = '
0
1
2
3

4

5
'; const delta = this.clipboard.convert({ html }); expect(delta).toEqual(new Delta().insert('0\n1\n2\n3\n\n4\n\n5')); }); it('empty block', function() { const html = '

Test

Body

'; const delta = this.clipboard.convert({ html }); expect(delta).toEqual( new Delta() .insert('Test\n', { header: 1 }) .insert('\n', { header: 2 }) .insert('Body'), ); }); it('mixed inline and block', function() { const delta = this.clipboard.convert({ html: '
One
Two
', }); expect(delta).toEqual(new Delta().insert('One\nTwo')); }); it('alias', function() { const delta = this.clipboard.convert({ html: 'BoldItalic', }); expect(delta).toEqual( new Delta() .insert('Bold', { bold: true }) .insert('Italic', { italic: true }), ); }); it('pre', function() { const html = '
 01 \n 23 
'; const delta = this.clipboard.convert({ html }); expect(delta).toEqual( new Delta().insert(' 01 \n 23 \n', { 'code-block': true }), ); }); it('nested list', function() { const delta = this.clipboard.convert({ html: '
  1. One
  2. Alpha
', }); expect(delta).toEqual( new Delta() .insert('One\n', { list: 'ordered' }) .insert('Alpha\n', { list: 'ordered', indent: 1 }), ); }); it('html nested list', function() { const delta = this.clipboard.convert({ html: '
  1. One
    1. Alpha
    2. Beta
      1. I
', }); expect(delta).toEqual( new Delta() .insert('One\n', { list: 'ordered' }) .insert('Alpha\nBeta\n', { list: 'ordered', indent: 1 }) .insert('I\n', { list: 'ordered', indent: 2 }), ); }); it('html nested bullet', function() { const delta = this.clipboard.convert({ html: '', }); expect(delta).toEqual( new Delta() .insert('One\n', { list: 'bullet' }) .insert('Alpha\nBeta\n', { list: 'bullet', indent: 1 }) .insert('I\n', { list: 'bullet', indent: 2 }), ); }); it('html nested checklist', function() { const delta = this.clipboard.convert({ html: '', }); expect(delta).toEqual( new Delta() .insert('One\n', { list: 'checked' }) .insert('Alpha\nBeta\n', { list: 'checked', indent: 1 }) .insert('I\n', { list: 'checked', indent: 2 }), ); }); it('html partial list', function() { const delta = this.clipboard.convert({ html: '
      1. iiii
    1. bbbb
  1. 2222
', }); expect(delta).toEqual( new Delta() .insert('iiii\n', { list: 'ordered', indent: 2 }) .insert('bbbb\n', { list: 'ordered', indent: 1 }) .insert('2222\n', { list: 'ordered' }), ); }); it('html table', function() { const delta = this.clipboard.convert({ html: '' + '' + '' + '
A1A2A3
B1B3
', }); expect(delta).toEqual( new Delta() .insert('A1\nA2\nA3\n', { table: 1 }) .insert('B1\n\nB3\n', { table: 2 }), ); }); it('embeds', function() { const delta = this.clipboard.convert({ html: '
0134
', }); const expected = new Delta() .insert('01') .insert( { image: '/assets/favicon.png' }, { height: '200', width: '300' }, ) .insert('34'); expect(delta).toEqual(expected); }); it('block embed', function() { const delta = this.clipboard.convert({ html: '

01

34

', }); expect(delta).toEqual( new Delta() .insert('01\n') .insert({ video: '#' }) .insert('34'), ); }); it('block embeds within blocks', function() { const delta = this.clipboard.convert({ html: '

0134

67

', }); expect(delta).toEqual( new Delta() .insert('01\n', { header: 1 }) .insert({ video: '#' }, { header: 1 }) .insert('34\n', { header: 1 }) .insert('67'), ); }); it('wrapped block embed', function() { const delta = this.clipboard.convert({ html: '

0134

67

', }); expect(delta).toEqual( new Delta() .insert('01\n', { header: 1 }) .insert({ video: '#' }, { link: '/', header: 1 }) .insert('34\n', { header: 1 }) .insert('67'), ); }); it('wrapped block embed with siblings', function() { const delta = this.clipboard.convert({ html: '

01ab34

67

', }); expect(delta).toEqual( new Delta() .insert('01', { header: 1 }) .insert('a\n', { link: '/', header: 1 }) .insert({ video: '#' }, { link: '/', header: 1 }) .insert('b', { link: '/', header: 1 }) .insert('34\n', { header: 1 }) .insert('67'), ); }); it('attributor and style match', function() { const delta = this.clipboard.convert({ html: '

Test

', }); expect(delta).toEqual(new Delta().insert('Test\n', { direction: 'rtl' })); }); it('nested styles', function() { const delta = this.clipboard.convert({ html: 'Test', }); expect(delta).toEqual(new Delta().insert('Test', { color: 'blue' })); }); it('custom matcher', function() { this.clipboard.addMatcher(Node.TEXT_NODE, function(node, delta) { let index = 0; const regex = /https?:\/\/[^\s]+/g; let match = null; const composer = new Delta(); // eslint-disable-next-line no-cond-assign while ((match = regex.exec(node.data))) { composer.retain(match.index - index); index = regex.lastIndex; composer.retain(match[0].length, { link: match[0] }); } return delta.compose(composer); }); const delta = this.clipboard.convert({ html: 'http://github.com https://quilljs.com', }); const expected = new Delta() .insert('http://github.com', { link: 'http://github.com' }) .insert(' ') .insert('https://quilljs.com', { link: 'https://quilljs.com' }); expect(delta).toEqual(expected); }); it('does not execute javascript', function() { window.unsafeFunction = jasmine.createSpy('unsafeFunction'); const html = ""; this.clipboard.convert({ html }); expect(window.unsafeFunction).not.toHaveBeenCalled(); delete window.unsafeFunction; }); it('xss', function() { const delta = this.clipboard.convert({ html: '', }); expect(delta).toEqual(new Delta().insert('')); }); }); });