import { TestBed, inject } from '@angular/core/testing'; import { LinenumberingService } from './linenumbering.service'; describe('LinenumberingService', () => { const brMarkup = (no: number): string => { return ( '
' + ' ' ); }, noMarkup = (no: number): string => { return ( ' ' ); }, longstr = (length: number): string => { let outstr = ''; for (let i = 0; i < length; i++) { outstr += String.fromCharCode(65 + (i % 26)); } return outstr; }; beforeEach(() => { TestBed.configureTestingModule({ providers: [LinenumberingService] }); }); it('should be created', inject([LinenumberingService], (service: LinenumberingService) => { expect(service).toBeTruthy(); })); describe('paragraph splitting', () => { it('breaks simple DIVs', inject([LinenumberingService], (service: LinenumberingService) => { const htmlIn = '
Test 1
' + '\n' + '

Test 2 3

'; const out = service.splitToParagraphs(htmlIn); expect(out.length).toBe(2); expect(out[0]).toBe('
Test 1
'); expect(out[1]).toBe('

Test 2 3

'); })); it('ignores root-level text-nodes', inject([LinenumberingService], (service: LinenumberingService) => { const htmlIn = '
Test 3
' + '\n New line'; const out = service.splitToParagraphs(htmlIn); expect(out.length).toBe(1); expect(out[0]).toBe('
Test 3
'); })); it('splits UL-Lists', inject([LinenumberingService], (service: LinenumberingService) => { const htmlIn = ""; const out = service.splitToParagraphs(htmlIn); expect(out.length).toBe(3); expect(out[0]).toBe(''); expect(out[1]).toBe(''); expect(out[2]).toBe(''); })); it('splits OL-Lists', inject([LinenumberingService], (service: LinenumberingService) => { const htmlIn = "
    \n
  1. Node 1
  2. \n
  3. Node 2
  4. Node 3

"; const out = service.splitToParagraphs(htmlIn); expect(out.length).toBe(3); expect(out[0]).toBe('
  1. Node 1
'); expect(out[1]).toBe('
  1. Node 2
'); expect(out[2]).toBe('
  1. Node 3

'); })); }); describe('getting line number range', () => { it('extracts the line number range, example 1', inject( [LinenumberingService], (service: LinenumberingService) => { const html = '

' + noMarkup(2) + 'et accusam et justo duo dolores et ea rebum Inserted Text. Stet clita kasd ' + brMarkup(3) + 'gubergren,

'; const range = service.getLineNumberRange(html); expect(range).toEqual({ from: 2, to: 4 }); } )); }); describe('line numbering: test nodes', () => { it('breaks very short lines', inject([LinenumberingService], (service: LinenumberingService) => { const textNode = document.createTextNode('0123'); service.setInlineOffsetLineNumberForTests(0, 1); const out = service.textNodeToLines(textNode, 5); const outHtml = service.nodesToHtml(out); expect(outHtml).toBe('0123'); expect(service.getInlineOffsetForTests()).toBe(4); })); it('breaks simple lines', inject([LinenumberingService], (service: LinenumberingService) => { const textNode = document.createTextNode('012345678901234567'); service.setInlineOffsetLineNumberForTests(0, 1); const out = service.textNodeToLines(textNode, 5); const outHtml = service.nodesToHtml(out); expect(outHtml).toBe('01234' + brMarkup(1) + '56789' + brMarkup(2) + '01234' + brMarkup(3) + '567'); expect(service.getInlineOffsetForTests()).toBe(3); })); it('breaks simple lines with offset', inject([LinenumberingService], (service: LinenumberingService) => { const textNode = document.createTextNode('012345678901234567'); service.setInlineOffsetLineNumberForTests(2, 1); const out = service.textNodeToLines(textNode, 5); const outHtml = service.nodesToHtml(out); expect(outHtml).toBe('012' + brMarkup(1) + '34567' + brMarkup(2) + '89012' + brMarkup(3) + '34567'); expect(service.getInlineOffsetForTests()).toBe(5); })); it('breaks simple lines with offset equaling to length', inject( [LinenumberingService], (service: LinenumberingService) => { const textNode = document.createTextNode('012345678901234567'); service.setInlineOffsetLineNumberForTests(5, 1); const out = service.textNodeToLines(textNode, 5); const outHtml = service.nodesToHtml(out); expect(outHtml).toBe( brMarkup(1) + '01234' + brMarkup(2) + '56789' + brMarkup(3) + '01234' + brMarkup(4) + '567' ); expect(service.getInlineOffsetForTests()).toBe(3); } )); it('breaks simple lines with spaces (1)', inject([LinenumberingService], (service: LinenumberingService) => { const textNode = document.createTextNode('0123 45 67 89012 34 567'); service.setInlineOffsetLineNumberForTests(0, 1); const out = service.textNodeToLines(textNode, 5); const outHtml = service.nodesToHtml(out); expect(outHtml).toBe( '0123 ' + brMarkup(1) + '45 67 ' + brMarkup(2) + '89012 ' + brMarkup(3) + '34 ' + brMarkup(4) + '567' ); expect(service.getInlineOffsetForTests()).toBe(3); })); it('breaks simple lines with spaces (2)', inject([LinenumberingService], (service: LinenumberingService) => { const textNode = document.createTextNode('0123 45 67 89012tes 344 '); service.setInlineOffsetLineNumberForTests(0, 1); const out = service.textNodeToLines(textNode, 5); const outHtml = service.nodesToHtml(out); expect(outHtml).toBe( '0123 ' + brMarkup(1) + '45 67 ' + brMarkup(2) + '89012' + brMarkup(3) + 'tes ' + brMarkup(4) + '344 ' ); expect(service.getInlineOffsetForTests()).toBe(4); })); it('breaks simple lines with spaces (3)', inject([LinenumberingService], (service: LinenumberingService) => { const textNode = document.createTextNode("I'm a Demo-Text"); service.setInlineOffsetLineNumberForTests(0, 1); const out = service.textNodeToLines(textNode, 5); const outHtml = service.nodesToHtml(out); expect(outHtml).toBe("I'm a " + brMarkup(1) + 'Demo-' + brMarkup(2) + 'Text'); expect(service.getInlineOffsetForTests()).toBe(4); })); it('breaks simple lines with spaces (4)', inject([LinenumberingService], (service: LinenumberingService) => { const textNode = document.createTextNode("I'm a LongDemo-Text"); service.setInlineOffsetLineNumberForTests(0, 1); const out = service.textNodeToLines(textNode, 5); const outHtml = service.nodesToHtml(out); expect(outHtml).toBe("I'm a " + brMarkup(1) + 'LongD' + brMarkup(2) + 'emo-' + brMarkup(3) + 'Text'); expect(service.getInlineOffsetForTests()).toBe(4); })); }); describe('line numbering: inline nodes', () => { it('leaves a simple SPAN untouched', inject([LinenumberingService], (service: LinenumberingService) => { const inHtml = 'Test'; const outHtml = service.insertLineNumbers(inHtml, 5); expect(outHtml).toBe(noMarkup(1) + 'Test'); expect(service.stripLineNumbers(outHtml)).toBe(inHtml); expect(service.insertLineBreaksWithoutNumbers(outHtml, 80)).toBe(outHtml); })); it('breaks lines in a simple SPAN', inject([LinenumberingService], (service: LinenumberingService) => { const inHtml = 'Lorem ipsum dolorsit amet'; const outHtml = service.insertLineNumbers(inHtml, 5); expect(outHtml).toBe( noMarkup(1) + 'Lorem ' + brMarkup(2) + 'ipsum ' + brMarkup(3) + 'dolor' + brMarkup(4) + 'sit ' + brMarkup(5) + 'amet' ); expect(service.stripLineNumbers(outHtml)).toBe(inHtml); expect(service.insertLineBreaksWithoutNumbers(outHtml, 80)).toBe(outHtml); })); it('breaks lines in nested inline elements', inject([LinenumberingService], (service: LinenumberingService) => { const inHtml = 'Lorem ipsum dolorsit amet'; const outHtml = service.insertLineNumbers(inHtml, 5); expect(outHtml).toBe( noMarkup(1) + 'Lorem ' + brMarkup(2) + 'ipsum ' + brMarkup(3) + 'dolor' + brMarkup(4) + 'sit ' + brMarkup(5) + 'amet' ); expect(service.stripLineNumbers(outHtml)).toBe(inHtml); expect(service.insertLineBreaksWithoutNumbers(outHtml, 80)).toBe(outHtml); })); it('counts within DEL nodes', inject([LinenumberingService], (service: LinenumberingService) => { const inHtml = '1234 1234 1234 1234'; const outHtml = service.insertLineNumbers(inHtml, 10); expect(outHtml).toBe(noMarkup(1) + '1234 1234 ' + brMarkup(2) + '1234 1234'); expect(service.stripLineNumbers(outHtml)).toBe(inHtml); expect(service.insertLineBreaksWithoutNumbers(outHtml, 80)).toBe(outHtml); })); it('counts after DEL/INS-nodes', inject([LinenumberingService], (service: LinenumberingService) => { const inHtml = '

leo Testelefantgeweih Buchstabenwut als Achzehnzahlunginer. Hierbei darfsetzen bist der Deifi das Dor Reh Wachtel da Subjunktivier als Derftige Aalsan Orthopädische, der Arbeitsnachweisdiskus Bass der Tastatur Weiter schreiben wie Tasse Wasser als dienen.

'; const outHtml = service.insertLineNumbers(inHtml, 95); expect(outHtml).toBe( '

' + noMarkup(1) + 'leo Testelefantgeweih Buchstabenwut als Achzehnzahlunginer. Hierbei darfsetzen bist der Deifi das ' + brMarkup(2) + 'Dor Reh Wachtel da Subjunktivier als Derftige Aalsan Orthopädische, der Arbeitsnachweisdiskus Bass der Tastatur ' + brMarkup(3) + 'Weiter schreiben wie Tasse Wasser als dienen.

' ); })); it('handles STRIKE-tags', inject([LinenumberingService], (service: LinenumberingService) => { const inHtml = '

et accusam et justo duo dolores et ea rebum Inserted Text. Stet clita kasd gubergren,

'; const outHtml = service.insertLineNumbers(inHtml, 80); expect(outHtml).toBe( '

' + noMarkup(1) + 'et accusam et justo duo dolores et ea rebum Inserted Text. Stet clita kasd ' + brMarkup(2) + 'gubergren,

' ); expect(service.stripLineNumbers(outHtml)).toBe(inHtml); expect(service.insertLineBreaksWithoutNumbers(outHtml, 80)).toBe(outHtml); })); it('treats ascii newline characters like spaces', inject( [LinenumberingService], (service: LinenumberingService) => { const inHtml = '

Test 123\nTest1

'; const outHtml = service.insertLineNumbers(inHtml, 5); expect(outHtml).toBe('

' + noMarkup(1) + 'Test ' + brMarkup(2) + '123\n' + brMarkup(3) + 'Test1

'); } )); }); describe('line numbering: block nodes', () => { it('leaves a simple DIV untouched', inject([LinenumberingService], (service: LinenumberingService) => { const inHtml = '
Test
'; const outHtml = service.insertLineNumbers(inHtml, 5); expect(outHtml).toBe('
' + noMarkup(1) + 'Test
'); expect(service.stripLineNumbers(outHtml)).toBe(inHtml); expect(service.insertLineBreaksWithoutNumbers(outHtml, 80)).toBe(outHtml); })); it('breaks a DIV containing only inline elements', inject( [LinenumberingService], (service: LinenumberingService) => { const inHtml = '
Test Test12345678 Test
'; const outHtml = service.insertLineNumbers(inHtml, 5); expect(outHtml).toBe( '
' + noMarkup(1) + 'Test ' + brMarkup(2) + 'Test1' + brMarkup(3) + '23456' + brMarkup(4) + '78 ' + brMarkup(5) + 'Test
' ); expect(service.stripLineNumbers(outHtml)).toBe(inHtml); expect(service.insertLineBreaksWithoutNumbers(outHtml, 80)).toBe(outHtml); } )); it('handles a DIV within a DIV correctly', inject([LinenumberingService], (service: LinenumberingService) => { const inHtml = '
Te
Te Test
Test
'; const outHtml = service.insertLineNumbers(inHtml, 5); expect(outHtml).toBe( '
' + noMarkup(1) + 'Te
' + noMarkup(2) + 'Te ' + brMarkup(3) + 'Test
' + noMarkup(4) + 'Test
' ); expect(service.stripLineNumbers(outHtml)).toBe(inHtml); expect(service.insertLineBreaksWithoutNumbers(outHtml, 80)).toBe(outHtml); })); it('ignores white spaces between block element tags', inject( [LinenumberingService], (service: LinenumberingService) => { const inHtml = ''; const outHtml = service.insertLineNumbers(inHtml, 80); expect(outHtml).toBe(''); expect(service.stripLineNumbers(outHtml)).toBe(inHtml); expect(service.insertLineBreaksWithoutNumbers(outHtml, 80)).toBe(outHtml); } )); }); describe('indentation for block elements', () => { it('indents LI-elements', inject([LinenumberingService], (service: LinenumberingService) => { const inHtml = '
' + longstr(100) + '' + longstr(100) + '
'; const expected = '
' + noMarkup(1) + 'ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZAB' + brMarkup(2) + 'CDEFGHIJKLMNOPQRSTUV' + '' + noMarkup(5) + 'ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZAB' + brMarkup(6) + 'CDEFGHIJKLMNOPQRSTUV
'; const outHtml = service.insertLineNumbers(inHtml, 80); expect(outHtml).toBe(expected); expect(service.stripLineNumbers(outHtml)).toBe(inHtml); expect(service.insertLineBreaksWithoutNumbers(outHtml, 80)).toBe(outHtml); })); it('indents BLOCKQUOTE-elements', inject([LinenumberingService], (service: LinenumberingService) => { const inHtml = '
' + longstr(100) + '
' + longstr(100) + '
' + longstr(100) + '
'; const expected = '
' + noMarkup(1) + 'ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZAB' + brMarkup(2) + 'CDEFGHIJKLMNOPQRSTUV' + '
' + noMarkup(3) + 'ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGH' + brMarkup(4) + 'IJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUV' + '
' + noMarkup(5) + 'ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZAB' + brMarkup(6) + 'CDEFGHIJKLMNOPQRSTUV
'; const outHtml = service.insertLineNumbers(inHtml, 80); expect(outHtml).toBe(expected); expect(service.stripLineNumbers(outHtml)).toBe(inHtml); expect(service.insertLineBreaksWithoutNumbers(outHtml, 80)).toBe(outHtml); })); it('shortens the line for H1-elements by 2/3', inject( [LinenumberingService], (service: LinenumberingService) => { const inHtml = '

' + longstr(80) + '

'; const expected = '

' + noMarkup(1) + 'ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZA' + brMarkup(2) + 'BCDEFGHIJKLMNOPQRSTUVWXYZAB

'; const outHtml = service.insertLineNumbers(inHtml, 80); expect(outHtml).toBe(expected); expect(service.stripLineNumbers(outHtml)).toBe(inHtml); expect(service.insertLineBreaksWithoutNumbers(outHtml, 80)).toBe(outHtml); } )); it('shortens the line for H2-elements by 0.75', inject( [LinenumberingService], (service: LinenumberingService) => { const inHtml = '

' + longstr(80) + '

'; const expected = '

' + noMarkup(1) + 'ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGH' + brMarkup(2) + 'IJKLMNOPQRSTUVWXYZAB

'; const outHtml = service.insertLineNumbers(inHtml, 80); expect(outHtml).toBe(expected); expect(service.stripLineNumbers(outHtml)).toBe(inHtml); expect(service.insertLineBreaksWithoutNumbers(outHtml, 80)).toBe(outHtml); } )); it('indents Ps with 30px-padding by 6 characters', inject( [LinenumberingService], (service: LinenumberingService) => { const inHtml = '
' + longstr(80) + '
'; const expected = '
' + noMarkup(1) + 'ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUV' + brMarkup(2) + 'WXYZAB
'; const outHtml = service.insertLineNumbers(inHtml, 80); expect(outHtml).toBe(expected); expect(service.stripLineNumbers(outHtml)).toBe(inHtml); expect(service.insertLineBreaksWithoutNumbers(outHtml, 80)).toBe(outHtml); } )); it('breaks before an inline element, if the first word of the new inline element is longer than the remaining line (1)', inject( [LinenumberingService], (service: LinenumberingService) => { const inHtml = '

Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio.

'; const outHtml = service.insertLineNumbers(inHtml, 80); expect(outHtml).toBe( '

' + noMarkup(1) + 'Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie ' + brMarkup(2) + 'consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan ' + brMarkup(3) + 'et iusto odio.

' ); expect(service.stripLineNumbers(outHtml)).toBe(inHtml); expect(service.insertLineBreaksWithoutNumbers(outHtml, 80)).toBe(outHtml); } )); it('breaks before an inline element, if the first word of the new inline element is longer than the remaining line (2)', inject( [LinenumberingService], (service: LinenumberingService) => { const inHtml = '

Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio.

'; const outHtml = service.insertLineNumbers(inHtml, 80); expect(outHtml).toBe( '

' + noMarkup(1) + 'Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie ' + brMarkup(2) + 'consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan ' + brMarkup(3) + 'et iusto odio.

' ); expect(service.stripLineNumbers(outHtml)).toBe(inHtml); expect(service.insertLineBreaksWithoutNumbers(outHtml, 80)).toBe(outHtml); } )); it('does not fail in a weird case', inject([LinenumberingService], (service: LinenumberingService) => { const inHtml = 'seid Noch

Test 123

'; const outHtml = service.insertLineNumbers(inHtml, 80); expect(outHtml).toBe( noMarkup(1) + 'seid Noch

' + noMarkup(2) + 'Test 123

' ); expect(service.stripLineNumbers(outHtml)).toBe(inHtml); expect(service.insertLineBreaksWithoutNumbers(outHtml, 80)).toBe(outHtml); })); }); describe('line numbering in regard to the inline diff', () => { it('does not count within INS nodes', inject([LinenumberingService], (service: LinenumberingService) => { const inHtml = '1234 1234 1234 1234'; const outHtml = service.insertLineNumbers(inHtml, 10); expect(outHtml).toBe(noMarkup(1) + '1234 1234 1234 ' + brMarkup(2) + '1234'); expect(service.stripLineNumbers(outHtml)).toBe(inHtml); expect(service.insertLineBreaksWithoutNumbers(outHtml, 80)).toBe(outHtml); })); it('does not count within .insert nodes', inject([LinenumberingService], (service: LinenumberingService) => { const inHtml = '

1234

1234 1234

'; const outHtml = service.insertLineNumbers(inHtml, 10); expect(outHtml).toBe( '

' + noMarkup(1) + '1234

' + noMarkup(2) + '1234 1234

' ); expect(service.stripLineNumbers(outHtml)).toBe(inHtml); expect(service.insertLineBreaksWithoutNumbers(outHtml, 80)).toBe(outHtml); })); it('does not create a new line for a trailing INS', inject( [LinenumberingService], (service: LinenumberingService) => { const inHtml = '

et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, conseteturdsfsdf23

'; const outHtml = service.insertLineNumbers(inHtml, 80); expect(outHtml).toBe( '

' + noMarkup(1) + 'et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata ' + brMarkup(2) + 'sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, conseteturdsfsdf23

' ); expect(service.stripLineNumbers(outHtml)).toBe(inHtml); expect(service.insertLineBreaksWithoutNumbers(outHtml, 80)).toBe(outHtml); } )); it('inserts the line number before the INS, if INS is the first element of the paragraph', inject( [LinenumberingService], (service: LinenumberingService) => { const inHtml = "

lauthals 'liebe Kinder, ich will hinaus in den Wald, seid auf der Hut vor dem Wolf!' Und noch etwas mehr Text bis zur nächsten Zeile

"; const outHtml = service.insertLineNumbers(inHtml, 80); expect(outHtml).toBe( '

' + noMarkup(1) + "lauthals 'liebe Kinder, ich will hinaus in den Wald, seid auf der Hut vor dem Wolf!' Und " + brMarkup(2) + 'noch etwas mehr Text bis zur nächsten Zeile

' ); expect(service.stripLineNumbers(outHtml)).toBe(inHtml); expect(service.insertLineBreaksWithoutNumbers(outHtml, 80)).toBe(outHtml); } )); it('cancels newlines after br-elements', inject([LinenumberingService], (service: LinenumberingService) => { const inHtml = '

Test 123
\nTest 456

'; const outHtml = service.insertLineNumbers(inHtml, 80); expect(outHtml).toBe('

' + noMarkup(1) + 'Test 123
' + noMarkup(2) + 'Test 456

'); })); it('does not force-break words right after an INS', inject( [LinenumberingService], (service: LinenumberingService) => { const inHtml = '

' + noMarkup(1) + '012345 78 01 345678901234567890123456789

'; const outHtml = service.insertLineBreaksWithoutNumbers(inHtml, 20, true); expect(outHtml).toBe( '

' + noMarkup(1) + '012345 78 01
34567
890123456789012
3456789

' ); } )); }); describe('line breaking without adding line numbers', () => { const plainBr = '
'; it('breaks a DIV containing only inline elements', inject( [LinenumberingService], (service: LinenumberingService) => { const inHtml = '
Test Test12345678 Test
'; const outHtml = service.insertLineBreaksWithoutNumbers(inHtml, 5); expect(outHtml).toBe( '
Test ' + plainBr + 'Test1' + plainBr + '23456' + plainBr + '78 ' + plainBr + 'Test
' ); expect(service.stripLineNumbers(outHtml)).toBe(inHtml); expect(service.insertLineBreaksWithoutNumbers(outHtml, 80)).toBe(outHtml); } )); it('indents BLOCKQUOTE-elements', inject([LinenumberingService], (service: LinenumberingService) => { const inHtml = '
' + longstr(100) + '
' + longstr(100) + '
' + longstr(100) + '
'; const expected = '
' + 'ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZAB' + plainBr + 'CDEFGHIJKLMNOPQRSTUV' + '
' + 'ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGH' + plainBr + 'IJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUV' + '
' + 'ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZAB' + plainBr + 'CDEFGHIJKLMNOPQRSTUV
'; const outHtml = service.insertLineBreaksWithoutNumbers(inHtml, 80); expect(outHtml).toBe(expected); expect(service.insertLineBreaksWithoutNumbers(outHtml, 80)).toBe(outHtml); })); it('DOES count within INS nodes', inject([LinenumberingService], (service: LinenumberingService) => { const inHtml = '1234 1234 1234 1234'; const outHtml = service.insertLineBreaksWithoutNumbers(inHtml, 10, true); expect(outHtml).toBe('1234 1234 ' + plainBr + '1234 1234'); expect(service.insertLineBreaksWithoutNumbers(outHtml, 80)).toBe(outHtml); })); it('does not create a new line for a trailing INS', inject( [LinenumberingService], (service: LinenumberingService) => { const inHtml = '

et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, conseteturdsfsdf23

'; const outHtml = service.insertLineBreaksWithoutNumbers(inHtml, 80, true); expect(outHtml).toBe( '

et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata ' + plainBr + 'sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur' + plainBr + 'dsfsdf23

' ); expect(service.insertLineBreaksWithoutNumbers(outHtml, 80)).toBe(outHtml); } )); it('ignores witespaces by previously added line numbers', inject( [LinenumberingService], (service: LinenumberingService) => { const inHtml = '

' + noMarkup(1) + longstr(10) + '

'; const outHtml = service.insertLineBreaksWithoutNumbers(inHtml, 10, true); expect(outHtml).toBe('

' + noMarkup(1) + longstr(10) + '

'); expect(service.insertLineBreaksWithoutNumbers(outHtml, 80)).toBe(outHtml); } )); }); describe('behavior regarding ckeditor', () => { it('does not count empty lines, case 1', inject([LinenumberingService], (service: LinenumberingService) => { const inHtml = '

Line 1

\n\n

Line 2

'; const outHtml = service.insertLineNumbers(inHtml, 80); expect(outHtml).toBe('

' + noMarkup(1) + 'Line 1

' + '\n\n' + '

' + noMarkup(2) + 'Line 2

'); })); it('does not count empty lines, case 2', inject([LinenumberingService], (service: LinenumberingService) => { const inHtml = ''; const outHtml = service.insertLineNumbers(inHtml, 80); expect(outHtml).toBe(''); })); }); describe('line highlighting', () => { it('highlights a simple line', inject([LinenumberingService], (service: LinenumberingService) => { const inHtml = service.insertLineNumbers('Lorem ipsum dolorsit amet', 5); const highlighted = service.highlightLine(inHtml, 2); expect(highlighted).toBe( noMarkup(1) + 'Lorem ' + brMarkup(2) + 'ipsum ' + brMarkup(3) + 'dolor' + brMarkup(4) + 'sit ' + brMarkup(5) + 'amet' ); })); it('highlights a simple line with formattings', inject( [LinenumberingService], (service: LinenumberingService) => { const inHtml = service.insertLineNumbers( 'Lorem ipsum dolorsit amet Lorem ipsum dolorsit amet Lorem ipsum dolorsit amet', 20 ); expect(inHtml).toBe( noMarkup(1) + 'Lorem ipsum dolorsit ' + brMarkup(2) + 'amet Lorem ipsum ' + brMarkup(3) + 'dolorsit amet Lorem ' + brMarkup(4) + 'ipsum dolorsit amet' ); const highlighted = service.highlightLine(inHtml, 2); expect(highlighted).toBe( noMarkup(1) + 'Lorem ipsum dolorsit ' + brMarkup(2) + 'amet Lorem ipsum ' + brMarkup(3) + 'dolorsit amet Lorem ' + brMarkup(4) + 'ipsum dolorsit amet' ); } )); it('highlights the last line', inject([LinenumberingService], (service: LinenumberingService) => { const inHtml = service.insertLineNumbers('Lorem ipsum dolorsit amet', 5); const highlighted = service.highlightLine(inHtml, 5); expect(highlighted).toBe( noMarkup(1) + 'Lorem ' + brMarkup(2) + 'ipsum ' + brMarkup(3) + 'dolor' + brMarkup(4) + 'sit ' + brMarkup(5) + 'amet' ); })); it('highlights the first line', inject([LinenumberingService], (service: LinenumberingService) => { const inHtml = service.insertLineNumbers('Lorem ipsum dolorsit amet', 5); const highlighted = service.highlightLine(inHtml, 1); expect(highlighted).toBe( noMarkup(1) + 'Lorem ' + brMarkup(2) + 'ipsum ' + brMarkup(3) + 'dolor' + brMarkup(4) + 'sit ' + brMarkup(5) + 'amet' ); })); it('does not change the string if the line number is not found', inject( [LinenumberingService], (service: LinenumberingService) => { const inHtml = service.insertLineNumbers('Lorem ipsum dolorsit amet', 5); const highlighted = service.highlightLine(inHtml, 8); expect(highlighted).toBe( noMarkup(1) + 'Lorem ' + brMarkup(2) + 'ipsum ' + brMarkup(3) + 'dolor' + brMarkup(4) + 'sit ' + brMarkup(5) + 'amet' ); } )); }); describe('document structure parsing', () => { it('detects the line numbers of headings', inject([LinenumberingService], (service: LinenumberingService) => { let inHtml = '

Line 1

' + '

Heading 1

Line 2

Heading 1.1

Line 3

Heading 1.2

Line 4

' + '

Heading 2

Heading 2.1

Line 5

'; inHtml = service.insertLineNumbers(inHtml, 80); const structure = service.getHeadingsWithLineNumbers(inHtml); expect(structure).toEqual([ { lineNumber: 2, level: 1, text: 'Heading 1' }, { lineNumber: 4, level: 2, text: 'Heading 1.1' }, { lineNumber: 6, level: 2, text: 'Heading 1.2' }, { lineNumber: 8, level: 1, text: 'Heading 2' }, { lineNumber: 9, level: 2, text: 'Heading 2.1' } ]); })); }); describe('caching', () => { it('caches based on line length', inject([LinenumberingService], (service: LinenumberingService) => { const inHtml = '

' + longstr(100) + '

'; const outHtml80 = service.insertLineNumbers(inHtml, 80); const outHtml70 = service.insertLineNumbers(inHtml, 70); expect(outHtml70).not.toBe(outHtml80); })); }); });