viewLineRenderer.test.ts 19.1 KB
Newer Older
A
Alex Dima 已提交
1 2 3 4 5 6
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/
'use strict';

A
Alex Dima 已提交
7
import * as assert from 'assert';
A
Alex Dima 已提交
8
import { renderViewLine, RenderLineInput, CharacterMapping } from 'vs/editor/common/viewLayout/viewLineRenderer';
A
Alex Dima 已提交
9
import { ViewLineToken } from 'vs/editor/common/core/viewLineToken';
J
Johannes Rieken 已提交
10
import { CharCode } from 'vs/base/common/charCode';
A
Alex Dima 已提交
11
import { MetadataConsts } from 'vs/editor/common/modes';
A
Alex Dima 已提交
12 13 14

suite('viewLineRenderer.renderLine', () => {

A
Alex Dima 已提交
15 16
	function createPart(endIndex: number, foreground: number): ViewLineToken {
		return new ViewLineToken(endIndex, (
A
Alex Dima 已提交
17 18
			foreground << MetadataConsts.FOREGROUND_OFFSET
		) >>> 0);
A
Alex Dima 已提交
19 20
	}

21
	function assertCharacterReplacement(lineContent: string, tabSize: number, expected: string, expectedCharOffsetInPart: number[][], expectedPartLengts: number[]): void {
A
Alex Dima 已提交
22
		let _actual = renderViewLine(new RenderLineInput(
23
			false,
A
Alex Dima 已提交
24
			lineContent,
25
			false,
26
			0,
A
Alex Dima 已提交
27
			[new ViewLineToken(lineContent.length, 0)],
28
			[],
A
Alex Dima 已提交
29
			tabSize,
30
			0,
A
Alex Dima 已提交
31
			-1,
32
			'none',
33
			false
A
Alex Dima 已提交
34
		));
A
Alex Dima 已提交
35

A
Alex Dima 已提交
36
		assert.equal(_actual.html, '<span><span class="mtk0">' + expected + '</span></span>');
37
		assertCharacterMapping(_actual.characterMapping, expectedCharOffsetInPart);
38
		assertPartLengths(_actual.characterMapping, expectedPartLengts);
A
Alex Dima 已提交
39 40 41
	}

	test('replaces spaces', () => {
42 43 44
		assertCharacterReplacement(' ', 4, '&nbsp;', [[0, 1]], [1]);
		assertCharacterReplacement('  ', 4, '&nbsp;&nbsp;', [[0, 1, 2]], [2]);
		assertCharacterReplacement('a  b', 4, 'a&nbsp;&nbsp;b', [[0, 1, 2, 3, 4]], [4]);
A
Alex Dima 已提交
45 46 47
	});

	test('escapes HTML markup', () => {
48 49 50
		assertCharacterReplacement('a<b', 4, 'a&lt;b', [[0, 1, 2, 3]], [3]);
		assertCharacterReplacement('a>b', 4, 'a&gt;b', [[0, 1, 2, 3]], [3]);
		assertCharacterReplacement('a&b', 4, 'a&amp;b', [[0, 1, 2, 3]], [3]);
A
Alex Dima 已提交
51 52 53
	});

	test('replaces some bad characters', () => {
54 55 56 57
		assertCharacterReplacement('a\0b', 4, 'a&#00;b', [[0, 1, 2, 3]], [3]);
		assertCharacterReplacement('a' + String.fromCharCode(CharCode.UTF8_BOM) + 'b', 4, 'a\ufffdb', [[0, 1, 2, 3]], [3]);
		assertCharacterReplacement('a\u2028b', 4, 'a\ufffdb', [[0, 1, 2, 3]], [3]);
		assertCharacterReplacement('a\rb', 4, 'a&#8203b', [[0, 1, 2, 3]], [3]);
A
Alex Dima 已提交
58 59 60
	});

	test('handles tabs', () => {
61 62 63 64 65
		assertCharacterReplacement('\t', 4, '&nbsp;&nbsp;&nbsp;&nbsp;', [[0, 4]], [4]);
		assertCharacterReplacement('x\t', 4, 'x&nbsp;&nbsp;&nbsp;', [[0, 1, 4]], [4]);
		assertCharacterReplacement('xx\t', 4, 'xx&nbsp;&nbsp;', [[0, 1, 2, 4]], [4]);
		assertCharacterReplacement('xxx\t', 4, 'xxx&nbsp;', [[0, 1, 2, 3, 4]], [4]);
		assertCharacterReplacement('xxxx\t', 4, 'xxxx&nbsp;&nbsp;&nbsp;&nbsp;', [[0, 1, 2, 3, 4, 8]], [8]);
A
Alex Dima 已提交
66 67
	});

A
Alex Dima 已提交
68
	function assertParts(lineContent: string, tabSize: number, parts: ViewLineToken[], expected: string, expectedCharOffsetInPart: number[][], expectedPartLengts: number[]): void {
A
Alex Dima 已提交
69
		let _actual = renderViewLine(new RenderLineInput(
70
			false,
A
Alex Dima 已提交
71
			lineContent,
72
			false,
73 74
			0,
			parts,
75
			[],
A
Alex Dima 已提交
76
			tabSize,
77
			0,
A
Alex Dima 已提交
78
			-1,
79
			'none',
80
			false
A
Alex Dima 已提交
81
		));
A
Alex Dima 已提交
82

83
		assert.equal(_actual.html, '<span>' + expected + '</span>');
84
		assertCharacterMapping(_actual.characterMapping, expectedCharOffsetInPart);
85
		assertPartLengths(_actual.characterMapping, expectedPartLengts);
A
Alex Dima 已提交
86 87 88
	}

	test('empty line', () => {
89
		assertParts('', 4, [], '<span>&nbsp;</span>', [], []);
A
Alex Dima 已提交
90 91 92
	});

	test('uses part type', () => {
A
Alex Dima 已提交
93 94 95
		assertParts('x', 4, [createPart(1, 10)], '<span class="mtk10">x</span>', [[0, 1]], [1]);
		assertParts('x', 4, [createPart(1, 20)], '<span class="mtk20">x</span>', [[0, 1]], [1]);
		assertParts('x', 4, [createPart(1, 30)], '<span class="mtk30">x</span>', [[0, 1]], [1]);
A
Alex Dima 已提交
96 97 98
	});

	test('two parts', () => {
A
Alex Dima 已提交
99 100 101
		assertParts('xy', 4, [createPart(1, 1), createPart(2, 2)], '<span class="mtk1">x</span><span class="mtk2">y</span>', [[0], [0, 1]], [1, 1]);
		assertParts('xyz', 4, [createPart(1, 1), createPart(3, 2)], '<span class="mtk1">x</span><span class="mtk2">yz</span>', [[0], [0, 1, 2]], [1, 2]);
		assertParts('xyz', 4, [createPart(2, 1), createPart(3, 2)], '<span class="mtk1">xy</span><span class="mtk2">z</span>', [[0, 1], [0, 1]], [2, 1]);
A
Alex Dima 已提交
102 103 104
	});

	test('overflow', () => {
A
Alex Dima 已提交
105
		let _actual = renderViewLine(new RenderLineInput(
106
			false,
A
Alex Dima 已提交
107
			'Hello world!',
108
			false,
109 110
			0,
			[
A
Alex Dima 已提交
111 112 113 114 115 116 117 118 119 120 121 122
				createPart(1, 0),
				createPart(2, 1),
				createPart(3, 2),
				createPart(4, 3),
				createPart(5, 4),
				createPart(6, 5),
				createPart(7, 6),
				createPart(8, 7),
				createPart(9, 8),
				createPart(10, 9),
				createPart(11, 10),
				createPart(12, 11),
123
			],
124
			[],
A
Alex Dima 已提交
125
			4,
126
			10,
A
Alex Dima 已提交
127
			6,
128
			'boundary',
129
			false
A
Alex Dima 已提交
130
		));
A
Alex Dima 已提交
131 132

		let expectedOutput = [
A
Alex Dima 已提交
133 134 135 136 137 138
			'<span class="mtk0">H</span>',
			'<span class="mtk1">e</span>',
			'<span class="mtk2">l</span>',
			'<span class="mtk3">l</span>',
			'<span class="mtk4">o</span>',
			'<span class="mtk5">&nbsp;</span>',
139
			'<span class="vs-whitespace">&hellip;</span>'
A
Alex Dima 已提交
140 141
		].join('');

142
		assert.equal(_actual.html, '<span>' + expectedOutput + '</span>');
143 144 145 146 147 148
		assertCharacterMapping(_actual.characterMapping, [
			[0],
			[0],
			[0],
			[0],
			[0],
A
Alex Dima 已提交
149
			[0, 1],
A
Alex Dima 已提交
150
		]);
151
		assertPartLengths(_actual.characterMapping, [1, 1, 1, 1, 1, 1]);
A
Alex Dima 已提交
152 153 154 155 156
	});

	test('typical line', () => {
		let lineText = '\t    export class Game { // http://test.com     ';
		let lineParts = [
A
Alex Dima 已提交
157 158 159 160 161 162 163 164 165 166 167 168
			createPart(5, 1),
			createPart(11, 2),
			createPart(12, 3),
			createPart(17, 4),
			createPart(18, 5),
			createPart(22, 6),
			createPart(23, 7),
			createPart(24, 8),
			createPart(25, 9),
			createPart(28, 10),
			createPart(43, 11),
			createPart(48, 12),
A
Alex Dima 已提交
169 170
		];
		let expectedOutput = [
A
Alex Dima 已提交
171 172
			'<span class="vs-whitespace" style="width:40px">&rarr;&nbsp;&nbsp;&nbsp;</span>',
			'<span class="vs-whitespace" style="width:40px">&middot;&middot;&middot;&middot;</span>',
A
Alex Dima 已提交
173 174 175 176 177 178 179 180 181 182
			'<span class="mtk2">export</span>',
			'<span class="mtk3">&nbsp;</span>',
			'<span class="mtk4">class</span>',
			'<span class="mtk5">&nbsp;</span>',
			'<span class="mtk6">Game</span>',
			'<span class="mtk7">&nbsp;</span>',
			'<span class="mtk8">{</span>',
			'<span class="mtk9">&nbsp;</span>',
			'<span class="mtk10">//&nbsp;</span>',
			'<span class="mtk11">http://test.com</span>',
A
Alex Dima 已提交
183 184
			'<span class="vs-whitespace" style="width:20px">&middot;&middot;</span>',
			'<span class="vs-whitespace" style="width:30px">&middot;&middot;&middot;</span>'
A
Alex Dima 已提交
185 186
		].join('');
		let expectedOffsetsArr = [
187 188
			[0],
			[0, 1, 2, 3],
A
Alex Dima 已提交
189 190 191 192 193 194 195 196 197 198
			[0, 1, 2, 3, 4, 5],
			[0],
			[0, 1, 2, 3, 4],
			[0],
			[0, 1, 2, 3],
			[0],
			[0],
			[0],
			[0, 1, 2],
			[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14],
199 200
			[0, 1],
			[0, 1, 2, 3],
A
Alex Dima 已提交
201 202
		];

A
Alex Dima 已提交
203
		let _actual = renderViewLine(new RenderLineInput(
204
			false,
A
Alex Dima 已提交
205
			lineText,
206
			false,
207 208
			0,
			lineParts,
209
			[],
A
Alex Dima 已提交
210
			4,
211
			10,
A
Alex Dima 已提交
212
			-1,
213
			'boundary',
214
			false
A
Alex Dima 已提交
215
		));
A
Alex Dima 已提交
216

217
		assert.equal(_actual.html, '<span>' + expectedOutput + '</span>');
218
		assertCharacterMapping(_actual.characterMapping, expectedOffsetsArr);
219
		assertPartLengths(_actual.characterMapping, [4, 4, 6, 1, 5, 1, 4, 1, 1, 1, 3, 15, 2, 3]);
A
Alex Dima 已提交
220
	});
221 222 223 224 225

	test('issue #2255: Weird line rendering part 1', () => {
		let lineText = '\t\t\tcursorStyle:\t\t\t\t\t\t(prevOpts.cursorStyle !== newOpts.cursorStyle),';

		let lineParts = [
A
Alex Dima 已提交
226 227 228 229 230 231 232 233 234 235
			createPart(3, 1), // 3 chars
			createPart(15, 2), // 12 chars
			createPart(21, 3), // 6 chars
			createPart(22, 4), // 1 char
			createPart(43, 5), // 21 chars
			createPart(45, 6), // 2 chars
			createPart(46, 7), // 1 char
			createPart(66, 8), // 20 chars
			createPart(67, 9), // 1 char
			createPart(68, 10), // 2 chars
236 237
		];
		let expectedOutput = [
A
Alex Dima 已提交
238 239 240 241 242 243 244 245 246 247
			'<span class="mtk1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>',
			'<span class="mtk2">cursorStyle:</span>',
			'<span class="mtk3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>',
			'<span class="mtk4">(</span>',
			'<span class="mtk5">prevOpts.cursorStyle&nbsp;</span>',
			'<span class="mtk6">!=</span>',
			'<span class="mtk7">=</span>',
			'<span class="mtk8">&nbsp;newOpts.cursorStyle</span>',
			'<span class="mtk9">)</span>',
			'<span class="mtk10">,</span>',
248 249 250 251 252 253 254 255 256 257 258 259 260 261
		].join('');
		let expectedOffsetsArr = [
			[0, 4, 8], // 3 chars
			[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], // 12 chars
			[0, 4, 8, 12, 16, 20], // 6 chars
			[0], // 1 char
			[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], // 21 chars
			[0, 1], // 2 chars
			[0], // 1 char
			[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19], // 20 chars
			[0], // 1 char
			[0, 1] // 2 chars
		];

A
Alex Dima 已提交
262
		let _actual = renderViewLine(new RenderLineInput(
263
			false,
A
Alex Dima 已提交
264
			lineText,
265
			false,
266 267
			0,
			lineParts,
268
			[],
A
Alex Dima 已提交
269
			4,
270
			10,
A
Alex Dima 已提交
271
			-1,
272
			'none',
273
			false
A
Alex Dima 已提交
274
		));
275

276
		assert.equal(_actual.html, '<span>' + expectedOutput + '</span>');
277
		assertCharacterMapping(_actual.characterMapping, expectedOffsetsArr);
278
		assertPartLengths(_actual.characterMapping, [12, 12, 24, 1, 21, 2, 1, 20, 1, 1]);
279 280 281 282 283 284
	});

	test('issue #2255: Weird line rendering part 2', () => {
		let lineText = ' \t\t\tcursorStyle:\t\t\t\t\t\t(prevOpts.cursorStyle !== newOpts.cursorStyle),';

		let lineParts = [
A
Alex Dima 已提交
285 286 287 288 289 290 291 292 293 294
			createPart(4, 1), // 4 chars
			createPart(16, 2), // 12 chars
			createPart(22, 3), // 6 chars
			createPart(23, 4), // 1 char
			createPart(44, 5), // 21 chars
			createPart(46, 6), // 2 chars
			createPart(47, 7), // 1 char
			createPart(67, 8), // 20 chars
			createPart(68, 9), // 1 char
			createPart(69, 10), // 2 chars
295 296
		];
		let expectedOutput = [
A
Alex Dima 已提交
297 298 299 300 301 302 303 304 305 306
			'<span class="mtk1">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>',
			'<span class="mtk2">cursorStyle:</span>',
			'<span class="mtk3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>',
			'<span class="mtk4">(</span>',
			'<span class="mtk5">prevOpts.cursorStyle&nbsp;</span>',
			'<span class="mtk6">!=</span>',
			'<span class="mtk7">=</span>',
			'<span class="mtk8">&nbsp;newOpts.cursorStyle</span>',
			'<span class="mtk9">)</span>',
			'<span class="mtk10">,</span>',
307 308 309 310 311 312 313 314 315 316 317 318 319 320
		].join('');
		let expectedOffsetsArr = [
			[0, 1, 4, 8], // 4 chars
			[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], // 12 chars
			[0, 4, 8, 12, 16, 20], // 6 chars
			[0], // 1 char
			[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], // 21 chars
			[0, 1], // 2 chars
			[0], // 1 char
			[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19], // 20 chars
			[0], // 1 char
			[0, 1] // 2 chars
		];

A
Alex Dima 已提交
321
		let _actual = renderViewLine(new RenderLineInput(
322
			false,
A
Alex Dima 已提交
323
			lineText,
324
			false,
325 326
			0,
			lineParts,
327
			[],
A
Alex Dima 已提交
328
			4,
329
			10,
A
Alex Dima 已提交
330
			-1,
331
			'none',
332
			false
A
Alex Dima 已提交
333
		));
334

335
		assert.equal(_actual.html, '<span>' + expectedOutput + '</span>');
336
		assertCharacterMapping(_actual.characterMapping, expectedOffsetsArr);
337
		assertPartLengths(_actual.characterMapping, [12, 12, 24, 1, 21, 2, 1, 20, 1, 1]);
338 339
	});

340 341 342 343
	test('issue Microsoft/monaco-editor#280: Improved source code rendering for RTL languages', () => {
		let lineText = 'var קודמות = \"מיותר קודמות צ\'ט של, אם לשון העברית שינויים ויש, אם\";';

		let lineParts = [
A
Alex Dima 已提交
344 345 346 347
			createPart(3, 6),
			createPart(13, 1),
			createPart(66, 20),
			createPart(67, 1),
348 349 350 351 352 353 354 355 356 357
		];

		let expectedOutput = [
			'<span dir="ltr" class="mtk6">var</span>',
			'<span dir="ltr" class="mtk1">&nbsp;קודמות&nbsp;=&nbsp;</span>',
			'<span dir="ltr" class="mtk20">"מיותר&nbsp;קודמות&nbsp;צ\'ט&nbsp;של,&nbsp;אם&nbsp;לשון&nbsp;העברית&nbsp;שינויים&nbsp;ויש,&nbsp;אם"</span>',
			'<span dir="ltr" class="mtk1">;</span>'
		].join('');

		let _actual = renderViewLine(new RenderLineInput(
358
			false,
359 360 361 362 363 364 365 366 367 368 369 370
			lineText,
			true,
			0,
			lineParts,
			[],
			4,
			10,
			-1,
			'none',
			false
		));

371
		assert.equal(_actual.html, '<span>' + expectedOutput + '</span>');
372
		assert.equal(_actual.containsRTL, true);
373 374 375 376 377 378 379 380 381
	});

	test('issue #6885: Splits large tokens', () => {
		//                                                                                                                  1         1         1
		//                        1         2         3         4         5         6         7         8         9         0         1         2
		//               1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234
		let _lineText = 'This is just a long line that contains very interesting text. This is just a long line that contains very interesting text.';

		function assertSplitsTokens(message: string, lineText: string, expectedOutput: string[]): void {
A
Alex Dima 已提交
382
			let lineParts = [createPart(lineText.length, 1)];
383
			let actual = renderViewLine(new RenderLineInput(
384
				false,
385 386 387 388 389 390 391 392 393 394 395
				lineText,
				false,
				0,
				lineParts,
				[],
				4,
				10,
				-1,
				'none',
				false
			));
396
			assert.equal(actual.html, '<span>' + expectedOutput.join('') + '</span>', message);
397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470
		}

		// A token with 49 chars
		{
			assertSplitsTokens(
				'49 chars',
				_lineText.substr(0, 49),
				[
					'<span class="mtk1">This&nbsp;is&nbsp;just&nbsp;a&nbsp;long&nbsp;line&nbsp;that&nbsp;contains&nbsp;very&nbsp;inter</span>',
				]
			);
		}

		// A token with 50 chars
		{
			assertSplitsTokens(
				'50 chars',
				_lineText.substr(0, 50),
				[
					'<span class="mtk1">This&nbsp;is&nbsp;just&nbsp;a&nbsp;long&nbsp;line&nbsp;that&nbsp;contains&nbsp;very&nbsp;intere</span>',
				]
			);
		}

		// A token with 51 chars
		{
			assertSplitsTokens(
				'51 chars',
				_lineText.substr(0, 51),
				[
					'<span class="mtk1">This&nbsp;is&nbsp;just&nbsp;a&nbsp;long&nbsp;line&nbsp;that&nbsp;contains&nbsp;very&nbsp;intere</span>',
					'<span class="mtk1">s</span>',
				]
			);
		}

		// A token with 99 chars
		{
			assertSplitsTokens(
				'99 chars',
				_lineText.substr(0, 99),
				[
					'<span class="mtk1">This&nbsp;is&nbsp;just&nbsp;a&nbsp;long&nbsp;line&nbsp;that&nbsp;contains&nbsp;very&nbsp;intere</span>',
					'<span class="mtk1">sting&nbsp;text.&nbsp;This&nbsp;is&nbsp;just&nbsp;a&nbsp;long&nbsp;line&nbsp;that&nbsp;contain</span>',
				]
			);
		}

		// A token with 100 chars
		{
			assertSplitsTokens(
				'100 chars',
				_lineText.substr(0, 100),
				[
					'<span class="mtk1">This&nbsp;is&nbsp;just&nbsp;a&nbsp;long&nbsp;line&nbsp;that&nbsp;contains&nbsp;very&nbsp;intere</span>',
					'<span class="mtk1">sting&nbsp;text.&nbsp;This&nbsp;is&nbsp;just&nbsp;a&nbsp;long&nbsp;line&nbsp;that&nbsp;contains</span>',
				]
			);
		}

		// A token with 101 chars
		{
			assertSplitsTokens(
				'101 chars',
				_lineText.substr(0, 101),
				[
					'<span class="mtk1">This&nbsp;is&nbsp;just&nbsp;a&nbsp;long&nbsp;line&nbsp;that&nbsp;contains&nbsp;very&nbsp;intere</span>',
					'<span class="mtk1">sting&nbsp;text.&nbsp;This&nbsp;is&nbsp;just&nbsp;a&nbsp;long&nbsp;line&nbsp;that&nbsp;contains</span>',
					'<span class="mtk1">&nbsp;</span>',
				]
			);
		}
	});

471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497
	test('issue #20624: Unaligned surrogate pairs are corrupted at multiples of 50 columns', () => {
		let lineText = 'a𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷';

		let lineParts = [createPart(lineText.length, 1)];
		let actual = renderViewLine(new RenderLineInput(
			false,
			lineText,
			false,
			0,
			lineParts,
			[],
			4,
			10,
			-1,
			'none',
			false
		));
		let expectedOutput = [
			'<span class="mtk1">a𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷</span>',
			'<span class="mtk1">𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷</span>',
			'<span class="mtk1">𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷</span>',
			'<span class="mtk1">𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷</span>',
			'<span class="mtk1">𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷𠮷</span>',
		];
		assert.equal(actual.html, '<span>' + expectedOutput.join('') + '</span>');
	});

498 499
	test('issue #6885: Does not split large tokens in RTL text', () => {
		let lineText = 'את גרמנית בהתייחסות שמו, שנתי המשפט אל חפש, אם כתב אחרים ולחבר. של התוכן אודות בויקיפדיה כלל, של עזרה כימיה היא. על עמוד יוצרים מיתולוגיה סדר, אם שכל שתפו לעברית שינויים, אם שאלות אנגלית עזה. שמות בקלות מה סדר.';
A
Alex Dima 已提交
500
		let lineParts = [createPart(lineText.length, 1)];
501 502 503 504
		let expectedOutput = [
			'<span dir="ltr" class="mtk1">את&nbsp;גרמנית&nbsp;בהתייחסות&nbsp;שמו,&nbsp;שנתי&nbsp;המשפט&nbsp;אל&nbsp;חפש,&nbsp;אם&nbsp;כתב&nbsp;אחרים&nbsp;ולחבר.&nbsp;של&nbsp;התוכן&nbsp;אודות&nbsp;בויקיפדיה&nbsp;כלל,&nbsp;של&nbsp;עזרה&nbsp;כימיה&nbsp;היא.&nbsp;על&nbsp;עמוד&nbsp;יוצרים&nbsp;מיתולוגיה&nbsp;סדר,&nbsp;אם&nbsp;שכל&nbsp;שתפו&nbsp;לעברית&nbsp;שינויים,&nbsp;אם&nbsp;שאלות&nbsp;אנגלית&nbsp;עזה.&nbsp;שמות&nbsp;בקלות&nbsp;מה&nbsp;סדר.</span>'
		];
		let actual = renderViewLine(new RenderLineInput(
505
			false,
506 507 508 509 510 511 512 513 514 515 516
			lineText,
			true,
			0,
			lineParts,
			[],
			4,
			10,
			-1,
			'none',
			false
		));
517
		assert.equal(actual.html, '<span>' + expectedOutput.join('') + '</span>');
518
		assert.equal(actual.containsRTL, true);
519 520
	});

521 522 523 524 525 526
	function assertCharacterMapping(actual: CharacterMapping, expected: number[][]): void {
		let charOffset = 0;
		for (let partIndex = 0; partIndex < expected.length; partIndex++) {
			let part = expected[partIndex];
			for (let i = 0; i < part.length; i++) {
				let charIndex = part[i];
527
				// here
528 529 530 531 532 533 534 535 536
				let _actualPartData = actual.charOffsetToPartData(charOffset);
				let actualPartIndex = CharacterMapping.getPartIndex(_actualPartData);
				let actualCharIndex = CharacterMapping.getCharIndex(_actualPartData);

				assert.deepEqual(
					{ partIndex: actualPartIndex, charIndex: actualCharIndex },
					{ partIndex: partIndex, charIndex: charIndex },
					`character mapping for offset ${charOffset}`
				);
537

538
				// here
539 540 541 542 543 544 545 546 547 548 549 550 551 552
				let actualOffset = actual.partDataToCharOffset(partIndex, part[part.length - 1] + 1, charIndex);

				assert.equal(
					actualOffset,
					charOffset,
					`character mapping for part ${partIndex}, ${charIndex}`
				);

				charOffset++;
			}
		}

		assert.equal(actual.length, charOffset);
	}
553 554 555 556 557 558 559 560 561

	function assertPartLengths(actual: CharacterMapping, expected: number[]): void {
		let _partLengths = actual.getPartLengths();
		let actualLengths: number[] = [];
		for (let i = 0; i < _partLengths.length; i++) {
			actualLengths[i] = _partLengths[i];
		}
		assert.deepEqual(actualLengths, expected, 'part lengths OK');
	}
A
Alex Dima 已提交
562
});