UNPKG

quill-delta-to-html

Version:
488 lines (428 loc) 18.2 kB
import 'mocha'; import * as assert from 'assert'; import { DeltaInsertOp } from './../src/DeltaInsertOp'; import { QuillDeltaToHtmlConverter } from "./../src/QuillDeltaToHtmlConverter"; import { callWhenXEqualY } from './_helper'; import { delta1 } from './data/delta1'; import { GroupType, ListType } from './../src/value-types'; import { encodeHtml } from './../src/funcs-html'; describe('QuillDeltaToHtmlConverter', function () { describe('constructor()', function () { it('should instantiate return proper html', function () { var qdc = new QuillDeltaToHtmlConverter(delta1.ops, { classPrefix: 'noz' }); var html = qdc.convert(); assert.equal(html, delta1.html); }); }); describe("convert()", function () { var ops2 = [ { insert: "this is text" }, { insert: "\n" }, { insert: "this is code" }, { insert: "\n", attributes: { 'code-block': true } }, { insert: "this is code TOO!" }, { insert: "\n", attributes: { 'code-block': true } }, ]; it('should render html', function () { var qdc = new QuillDeltaToHtmlConverter(ops2); var html = qdc.convert(); assert.equal(html.indexOf('<pre>this is code') > -1, true, html); }); it('should render mention', function () { let ops = [ { insert: "mention", attributes: { mentions: true, mention: { 'end-point': 'http://abc.com', slug: 'a', class: 'abc', target: '_blank' } } } ] var qdc = new QuillDeltaToHtmlConverter(ops); var html = qdc.convert(); assert.equal(html, ['<p><a class="abc"', ' href="http://abc.com/a" target="_blank"', '>mention</a></p>' ].join("")); var qdc = new QuillDeltaToHtmlConverter([{ insert: 'mention', attributes: { mentions: true, mention: { slug: 'aa' } } }]); var html = qdc.convert(); assert.equal(html, ['<p><a', ' href="about:blank">mention</a></p>' ].join("")); }); it('should open and close list tags', function () { var ops4 = [ { insert: "mr\n" }, { insert: "hello" }, { insert: "\n", attributes: { list: 'ordered' } }, { insert: "there" }, { insert: "\n", attributes: { list: 'bullet' } }, { insert: "\n", attributes: { list: 'ordered' } }, ] var qdc = new QuillDeltaToHtmlConverter(ops4); var html = qdc.convert(); assert.equal(html.indexOf('<p>mr') > -1, true); assert.equal(html.indexOf('</ol><ul><li>there') > -1, true); }); it('should wrap positional styles in right tag', function () { var ops4 = [ { insert: "mr" }, { insert: "\n", attributes: { align: 'center' } }, { insert: "\n", attributes: { direction: 'rtl' } }, { insert: "\n", attributes: { indent: 2 } } ] var qdc = new QuillDeltaToHtmlConverter(ops4, { paragraphTag: 'div' }); var html = qdc.convert(); assert.equal(html.indexOf('<div class="ql-align') > -1, true); assert.equal(html.indexOf('<div class="ql-direction') > -1, true); assert.equal(html.indexOf('<div class="ql-indent') > -1, true); var qdc = new QuillDeltaToHtmlConverter(ops4); var html = qdc.convert(); assert.equal(html.indexOf('<p class="ql-align') > -1, true); assert.equal(html.indexOf('<p class="ql-direction') > -1, true); assert.equal(html.indexOf('<p class="ql-indent') > -1, true); }); it('should render target attr correctly', () => { let ops = [ {"attributes":{"target":"_self","link":"#"},"insert":"A"}, {"attributes":{"target":"_blank","link":"#"},"insert":"B"}, {"attributes":{"link":"#"},"insert":"C"},{"insert":"\n"} ]; let qdc = new QuillDeltaToHtmlConverter(ops, {linkTarget: ''}); let html = qdc.convert(); assert.equal(html, [ `<p><a href="unsafe:#" target="_self">A</a>`, `<a href="unsafe:#" target="_blank">B</a>`, `<a href="unsafe:#">C</a></p>` ].join('')); qdc = new QuillDeltaToHtmlConverter(ops); html = qdc.convert(); assert.equal(html, [ `<p><a href="unsafe:#" target="_self">A</a>`, `<a href="unsafe:#" target="_blank">B</a>`, `<a href="unsafe:#" target="_blank">C</a></p>` ].join('')); qdc = new QuillDeltaToHtmlConverter(ops, {linkTarget: '_top'}); html = qdc.convert(); assert.equal(html, [ `<p><a href="unsafe:#" target="_self">A</a>`, `<a href="unsafe:#" target="_blank">B</a>`, `<a href="unsafe:#" target="_top">C</a></p>` ].join('')); }); }); describe('custom types', () => { it(`should return empty string if renderer not defined for custom blot`, () => { let ops = [ { insert: { customstuff: 'my val' } } ]; let qdc = new QuillDeltaToHtmlConverter(ops); assert.equal(qdc.convert(), '<p></p>'); }); it('should render custom insert types with given renderer', () => { let ops = [ { insert: { bolditalic: 'my text' } }, { insert: { blah: 1 } } ]; let qdc = new QuillDeltaToHtmlConverter(ops); qdc.renderCustomWith((op) => { if (op.insert.type === 'bolditalic') { return '<b><i>' + op.insert.value + '</i></b>'; } return 'unknown'; }); let html = qdc.convert(); assert.equal(html, '<p><b><i>my text</i></b>unknown</p>'); }); it('should render custom insert types in code blocks with given renderer', () => { let ops = [ { insert: { colonizer: ':' }}, { insert: "\n", attributes: { 'code-block': true } }, { insert: "code1"}, { insert: "\n", attributes: { 'code-block': true } }, { insert: { colonizer: ':' }}, { insert: "\n", attributes: { 'code-block': true } } ]; let renderer = (op: DeltaInsertOp) => { if (op.insert.type === 'colonizer') { return op.insert.value; } return ''; }; let qdc = new QuillDeltaToHtmlConverter(ops.slice(0,2)); qdc.renderCustomWith(renderer); assert.equal(qdc.convert(), '<pre>:</pre>'); qdc = new QuillDeltaToHtmlConverter(ops); qdc.renderCustomWith(renderer); assert.equal(qdc.convert(), '<pre>:\ncode1\n:</pre>'); }); it('should render custom insert types in headers with given renderer', () => { let ops = [ { insert: { colonizer: ':' }}, { insert: "\n", attributes: { header: 1 } }, { insert: "hello"}, { insert: "\n", attributes: { header: 1 } }, { insert: { colonizer: ':' }}, { insert: "\n", attributes: { header: 1 } } ]; let renderer = (op: DeltaInsertOp) => { if (op.insert.type === 'colonizer') { return op.insert.value; } return ''; }; let qdc = new QuillDeltaToHtmlConverter(ops.slice(0,2)); qdc.renderCustomWith(renderer); assert.equal(qdc.convert(), '<h1>:</h1>'); qdc = new QuillDeltaToHtmlConverter(ops); qdc.renderCustomWith(renderer); assert.equal(qdc.convert(), '<h1>:<br/>hello<br/>:</h1>'); }); }); describe('_getListTag()', function () { it('should return proper list tag', function () { var op = new DeltaInsertOp("\n", { list: ListType.Ordered }); var qdc = new QuillDeltaToHtmlConverter(delta1.ops) assert.equal(qdc._getListTag(op), 'ol'); var op = new DeltaInsertOp("\n", { list: ListType.Bullet }); assert.equal(qdc._getListTag(op), 'ul'); var op = new DeltaInsertOp("d"); assert.equal(qdc._getListTag(op), ''); }); }); describe(' prepare data before inline and block renders', function () { var ops: any; beforeEach(function () { ops = [ { insert: 'Hello' }, { insert: ' my ', attributes: { italic: true } }, { insert: '\n', attributes: { italic: true } }, { insert: ' name is joey' } ].map((v: any) => new DeltaInsertOp(v.insert, v.attributes)); }); describe('renderInlines()', function () { it('should render inlines', function () { var qdc = new QuillDeltaToHtmlConverter([]); var inlines = qdc._renderInlines(ops); assert.equal(inlines, ['<p>Hello', '<em> my </em><br/> name is joey</p>'].join('')); qdc = new QuillDeltaToHtmlConverter([], { paragraphTag: 'div' }); var inlines = qdc._renderInlines(ops); assert.equal(inlines, '<div>Hello<em> my </em><br/> name is joey</div>'); qdc = new QuillDeltaToHtmlConverter([], { paragraphTag: '' }); var inlines = qdc._renderInlines(ops); assert.equal(inlines, 'Hello<em> my </em><br/> name is joey'); }); it('should render plain new line string', function () { var ops = [new DeltaInsertOp("\n")]; var qdc = new QuillDeltaToHtmlConverter([]); assert.equal(qdc._renderInlines(ops), '<p><br/></p>'); }); it('should render styled new line string', function () { var ops = [new DeltaInsertOp("\n", { font: 'arial' })]; var qdc = new QuillDeltaToHtmlConverter([]); assert.equal(qdc._renderInlines(ops), '<p><br/></p>'); var qdc = new QuillDeltaToHtmlConverter([], { paragraphTag: '' }); assert.equal(qdc._renderInlines(ops), '<br/>'); }); it('should render when first line is new line', function () { var ops = [new DeltaInsertOp("\n"), new DeltaInsertOp("aa")]; var qdc = new QuillDeltaToHtmlConverter([]); assert.equal(qdc._renderInlines(ops), '<p><br/>aa</p>'); }); it('should render when last line is new line', function () { var ops = [new DeltaInsertOp("aa"), new DeltaInsertOp("\n")]; var qdc = new QuillDeltaToHtmlConverter([]); assert.equal(qdc._renderInlines(ops), '<p>aa</p>'); }); it('should render mixed lines', function () { var ops = [new DeltaInsertOp("aa"), new DeltaInsertOp("bb")]; var nlop = new DeltaInsertOp("\n"); var stylednlop = new DeltaInsertOp("\n", { color: '#333', italic: true }); var qdc = new QuillDeltaToHtmlConverter([]); assert.equal(qdc._renderInlines(ops), '<p>aabb</p>'); var ops0 = [nlop, ops[0], nlop, ops[1]] assert.equal(qdc._renderInlines(ops0), '<p><br/>aa<br/>bb</p>'); var ops4 = [ops[0], stylednlop, stylednlop, stylednlop, ops[1]] assert.equal(qdc._renderInlines(ops4), ['<p>aa<br/><br/><br/>bb</p>'].join('')); }); }); describe('renderBlock()', function () { var op = new DeltaInsertOp('\n', { header: 3, indent: 2 }); var inlineop = new DeltaInsertOp("hi there"); it('should render container block', function () { var qdc = new QuillDeltaToHtmlConverter([]); var blockhtml = qdc._renderBlock(op, [inlineop]); assert.equal(blockhtml, ['<h3 class="ql-indent-2">', 'hi there</h3>'].join('')); var qdc = new QuillDeltaToHtmlConverter([]); var blockhtml = qdc._renderBlock(op, []); assert.equal(blockhtml, ['<h3 class="ql-indent-2">', '<br/></h3>'].join('')); }); it('should correctly render code block', function () { let ops = [ { "insert": "line 1" }, { "attributes": { "code-block": true }, "insert": "\n" }, { "insert": "line 2" }, { "attributes": { "code-block": true }, "insert": "\n" }, { "insert": "line 3" }, { "attributes": { "code-block": true }, "insert": "\n" }, { "insert": "<p>line 4</p>" }, { "attributes": { "code-block": true }, "insert": "\n" } ] console.log(encodeHtml("<p>line 4</p>")); var qdc = new QuillDeltaToHtmlConverter(ops); let html = qdc.convert(); assert.equal(html, ["<pre>line 1\nline 2\nline 3\n", encodeHtml("<p>line 4</p>"), "</pre>"].join("") ); qdc = new QuillDeltaToHtmlConverter(ops, { multiLineCodeblock: false }); html = qdc.convert(); assert.equal( '<pre>line 1</pre><pre>line 2</pre><pre>line 3</pre>'+ '<pre>'+ encodeHtml("<p>line 4</p>") + '</pre>', html); qdc = new QuillDeltaToHtmlConverter([ops[0], ops[1]]); html = qdc.convert(); assert.equal(html, '<pre>line 1</pre>'); }); }); describe('before n after renders()', function () { var ops = [ { insert: 'hello', attributes: { bold: true } }, { insert: '\n', attributes: { bold: true } }, { insert: 'how r u?' }, { insert: 'r u fine' }, { insert: '\n', attributes: { blockquote: true } }, { insert: { video: 'http://' } }, { insert: 'list item 1' }, { insert: '\n', attributes: { list: 'bullet' } }, { insert: 'list item 1 indented' }, { insert: '\n', attributes: { list: 'bullet', indent: 1 } } ] var qdc = new QuillDeltaToHtmlConverter(ops); it('should call before/after render callbacks ', function (done) { let status = {x:0, y:8}; qdc.beforeRender((groupType, data) => { if (groupType === GroupType.InlineGroup) { var op = (<any>data).ops[0]; assert.ok(op.attributes.bold); } else if (groupType === GroupType.Video) { var op = (<any>data).op; assert.ok(op.insert.type === 'video'); } else if (groupType === GroupType.Block) { var d = (<any>data); assert.ok(d.op.attributes.blockquote && d.ops.length === 2); } else { var d = (<any>data); assert.ok(d.items.length === 1); } status.x++; return ''; }); qdc.afterRender((groupType, html) => { if (groupType === GroupType.InlineGroup) { assert.ok(html.indexOf('<strong>hello') > -1); } else if (groupType === GroupType.Video) { assert.ok(html.indexOf('<iframe') > -1); } else if (groupType === GroupType.Block) { assert.ok(html.indexOf('<blockquote') > -1); } else { assert.ok(html.indexOf('list item 1<ul><li') > -1); } status.x++; return html; }); qdc.convert(); callWhenXEqualY(status, done); }); it(`should call before render with block grouptype for align indent and direction`, (done) => { let ops = [ {insert: 'align'}, {insert: '\n', attributes: {align: 'right'}}, {insert: 'rtl'}, {insert: '\n', attributes: {direction: 'rtl'}}, {insert: 'indent 1'}, {insert: '\n', attributes: {indent: 1}}, ]; let status = {x:0, y: 3}; let qdc = new QuillDeltaToHtmlConverter(ops); qdc.beforeRender((gtype: any) => { gtype === 'block' && status.x++; return ''; }); qdc.convert(); callWhenXEqualY(status, done); }); it('should use my custom html if I return from before call back', function () { var c = new QuillDeltaToHtmlConverter([ { insert: { video: "http" } }, { insert: 'aa' }]); c.beforeRender(() => { return '<my custom video html>'; }); var v = c.convert(); assert.ok(v.indexOf('<my custom') > - 1); }); it('should register and use callbacks if they are functions', function () { var c = new QuillDeltaToHtmlConverter([ { insert: { video: "http" } }, { insert: 'aa' }]); var dummy = (): any => ''; c.beforeRender(dummy()); c.afterRender(dummy()); v = c.convert(); assert.ok(v.indexOf('iframe') > -1); c.beforeRender(dummy); var v = c.convert(); assert.ok(v.indexOf('<iframe') > - 1 && v.indexOf('aa') > -1); c.afterRender(dummy); v = c.convert(); assert.ok(v === ''); }); }); }); });