@talrace/ngx-noder 19.0.41 → 19.0.42

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1378,7 +1378,7 @@ class ExternalComponent extends BaseNoderComponent {
1378
1378
  constructor() {
1379
1379
  super(...arguments);
1380
1380
  this.focusSidenav = true;
1381
- this.isText = false;
1381
+ this.isText = false; // this will substitute component block by in editor text (getText() will be used as a value)
1382
1382
  }
1383
1383
  getText() {
1384
1384
  return '';
@@ -1772,13 +1772,6 @@ class BreakHelper {
1772
1772
  }
1773
1773
  return breaks.find(x => x.insertIndex === insertIndex)?.breakType ?? null;
1774
1774
  }
1775
- static removeBreakMarker(breaks, text, fragmentStartIndex) {
1776
- const index = text.at(-1) === NEW_LINE_MARKUP ? -2 : -1;
1777
- if (text.at(index) === CUSTOM_ELEMENT_MARKER && breaks.some(x => x.insertIndex === fragmentStartIndex + text.length + index)) {
1778
- return index === -1 ? text.substring(0, text.length + index) : text.substring(0, text.length + index).concat(text.at(-1));
1779
- }
1780
- return text;
1781
- }
1782
1775
  }
1783
1776
 
1784
1777
  const COMMENT_TYPES = new InjectionToken('COMMENT_TYPES');
@@ -1922,6 +1915,12 @@ class CreateEdgesModel {
1922
1915
  }
1923
1916
  }
1924
1917
 
1918
+ const PARENT_TAG = 'APP-NOD-EDITOR';
1919
+ const TABLE_CELL_TAG = 'APP-NOD-TABLE-CELL';
1920
+ const EDGE_TAG = 'APP-NOD-EDGE';
1921
+ const IMAGE_TAG = 'APP-NOD-IMAGE';
1922
+ const CUSTOM_TAG = 'APP-NOD-CUSTOM-ELEMENT';
1923
+
1925
1924
  class CustomElementSearchResult {
1926
1925
  constructor(init) {
1927
1926
  Object.assign(this, init);
@@ -6308,36 +6307,26 @@ class PositionHelper {
6308
6307
  const paragraphLine = documentLine - index;
6309
6308
  return { paragraph, paragraphLine };
6310
6309
  }
6311
- static paragraphToParagraphLine(nextLineIndexes, indexInParagraph) {
6312
- if (!nextLineIndexes.length || nextLineIndexes[0] > indexInParagraph) {
6313
- return { paragraphLine: 0, indexInLine: indexInParagraph };
6314
- }
6315
- let index = nextLineIndexes.findLastIndex(x => x <= indexInParagraph);
6316
- const indexInLine = indexInParagraph - nextLineIndexes[index];
6317
- return { paragraphLine: index + 1, indexInLine };
6310
+ static paragraphToParagraphLine(paragraph, indexInParagraph) {
6311
+ const lines = paragraph.paragraphSettings.textLinesInfo;
6312
+ const paragraphLine = lines.findIndex(x => x.endIndex >= indexInParagraph);
6313
+ const indexInLine = indexInParagraph - lines[paragraphLine].startIndex;
6314
+ return { paragraphLine, indexInLine };
6318
6315
  }
6319
- static paragraphToDocumentLine(session, paragraph, indexInParagraph) {
6320
- const paragraphLine = session.displayData.paragraphs[paragraph].lineNumber;
6321
- const nextLineIndexes = session.displayData.paragraphs[paragraph].nextLineIndexes;
6322
- if (!nextLineIndexes.length || nextLineIndexes[0] > indexInParagraph) {
6323
- return new CursorParagraph(paragraphLine, indexInParagraph);
6324
- }
6325
- let line = 0;
6326
- while (nextLineIndexes[line] <= indexInParagraph && line < nextLineIndexes.length) {
6327
- line++;
6328
- }
6329
- return new CursorParagraph(paragraphLine + line, indexInParagraph - nextLineIndexes[line - 1]);
6316
+ static paragraphToDocumentLine(paragraph, indexInParagraph) {
6317
+ const { paragraphLine, indexInLine } = this.paragraphToParagraphLine(paragraph, indexInParagraph);
6318
+ return new CursorParagraph(paragraph.lineNumber + paragraphLine, indexInLine);
6330
6319
  }
6331
6320
  static documentLineToParagraph(session, documentLine, indexInLine) {
6332
- let paragraphIndex = session.displayData.paragraphs.findIndex(x => x.lineNumber > documentLine);
6333
- paragraphIndex = paragraphIndex === -1 ? session.displayData.paragraphs.length - 1 : paragraphIndex - 1;
6321
+ const paragraphIndex = session.displayData.paragraphs.findLastIndex(x => x.lineNumber <= documentLine);
6334
6322
  const paragraph = session.displayData.paragraphs[paragraphIndex];
6335
- let paragraphLine = documentLine - paragraph.lineNumber;
6336
- const indexInParagraph = paragraphLine === 0 ? indexInLine : indexInLine + paragraph.nextLineIndexes[paragraphLine - 1];
6323
+ const paragraphLine = documentLine - paragraph.lineNumber;
6324
+ const lines = paragraph.paragraphSettings.textLinesInfo;
6325
+ const indexInParagraph = lines[paragraphLine].startIndex + indexInLine;
6337
6326
  return new CursorParagraph(paragraphIndex, indexInParagraph);
6338
6327
  }
6339
6328
  static paragraphToPixel(session, paragraph, indexInParagraph) {
6340
- const line = this.paragraphToParagraphLine(session.displayData.paragraphs[paragraph].nextLineIndexes, indexInParagraph);
6329
+ const line = this.paragraphToParagraphLine(session.displayData.paragraphs[paragraph], indexInParagraph);
6341
6330
  return this.paragraphLineToPixel(session, paragraph, line.paragraphLine, line.indexInLine);
6342
6331
  }
6343
6332
  static documentLineToPixel(session, documentLine, indexInLine) {
@@ -6348,26 +6337,17 @@ class PositionHelper {
6348
6337
  const marginLeft = session.displayData.pagesFormat[0].pageFormatModel.marginLeft; // this value is the same for all page formats.
6349
6338
  const paragraphs = session.displayData.paragraphs;
6350
6339
  const tokens = session.displayData.getParagraphLineTokens(paragraph, paragraphLine);
6351
- let tokenIndex = indexInLine > 0 ? indexInLine - 1 : indexInLine;
6352
- let sizeMax = { ...tokens[tokenIndex] };
6353
- let lineWidthToPosition = marginLeft;
6354
- for (let i = 0; i < tokens.length; i++) {
6355
- const currentToken = tokens[i];
6356
- if (i < indexInLine) {
6357
- lineWidthToPosition += currentToken.width;
6358
- }
6359
- if (sizeMax.ascent < currentToken.ascent) {
6360
- sizeMax = currentToken;
6361
- }
6340
+ let width = marginLeft;
6341
+ for (let i = 0; i < tokens.length && !tokens[i].isParagraph && tokens[i].index - tokens[0].index < indexInLine; i++) {
6342
+ width += tokens[i].width;
6362
6343
  }
6363
6344
  const lineTopOffset = this.getLineTopOffset(paragraphs[paragraph].paragraphSettings.textLinesInfo, paragraphLine);
6364
6345
  const paragraphTop = paragraphs[paragraph].paragraphSettings.distanceFromTop || 0;
6365
6346
  const info = paragraphs[paragraph].paragraphSettings.textLinesInfo[paragraphLine];
6366
6347
  const markerOffset = NumberingHelper.getOffsetCausedByMarker(paragraphs[paragraph].paragraphSettings.numberingData, info);
6367
6348
  return {
6368
- pageX: lineWidthToPosition + info.paddingLeft + info.offsetMargin + markerOffset,
6349
+ pageX: width + info.paddingLeft + info.offsetMargin + markerOffset,
6369
6350
  pageY: paragraphTop + lineTopOffset - session.scrollTop,
6370
- width: tokens[tokenIndex].width,
6371
6351
  height: info.height,
6372
6352
  ascent: info.ascent
6373
6353
  };
@@ -6394,37 +6374,42 @@ class PositionHelper {
6394
6374
  }
6395
6375
  return { paragraph, paragraphLine };
6396
6376
  }
6397
- static pixelToParagraph(session, pageX, pageY, tokenDivider) {
6377
+ static pixelToIndexInParagraph(session, pageX, paragraph, paragraphLine, tokenDivider) {
6398
6378
  const marginLeft = session.displayData.pagesFormat[0].pageFormatModel.marginLeft; // this value is the same for all page formats.
6399
6379
  const paragraphs = session.displayData.paragraphs;
6400
- const { paragraph, paragraphLine } = this.pixelToParagraphLine(paragraphs, pageY);
6401
- const settings = paragraphs[paragraph].paragraphSettings;
6402
6380
  const tokens = session.displayData.getParagraphLineTokens(paragraph, paragraphLine);
6403
- const lineInfo = settings.textLinesInfo[paragraphLine];
6404
- const indexInLine = this.getIndexInLine(tokens, lineInfo, settings.numberingData, marginLeft, pageX, tokenDivider);
6405
- const indexInParagraph = paragraphLine === 0 ? indexInLine : indexInLine + paragraphs[paragraph].nextLineIndexes[paragraphLine - 1];
6406
- return { paragraph, indexInParagraph };
6407
- }
6408
- static pixelToIndexInLine(session, documentLine, pageX, tokenDivider) {
6409
- const marginLeft = session.displayData.pagesFormat[0].pageFormatModel.marginLeft; // this value is the same for all page formats.
6410
- const { paragraph, paragraphLine } = this.documentLineToParagraphLine(session.displayData.paragraphs, documentLine);
6411
- const settings = session.displayData.paragraphs[paragraph].paragraphSettings;
6412
- const tokens = session.displayData.getParagraphLineTokens(paragraph, paragraphLine);
6413
- const lineInfo = settings.textLinesInfo[paragraphLine];
6414
- return this.getIndexInLine(tokens, lineInfo, settings.numberingData, marginLeft, pageX, tokenDivider);
6381
+ const lines = paragraphs[paragraph].paragraphSettings.textLinesInfo;
6382
+ const numberingData = paragraphs[paragraph].paragraphSettings.numberingData;
6383
+ const indexInLine = this.getIndexInLine(tokens, lines[paragraphLine], numberingData, marginLeft, pageX, tokenDivider);
6384
+ return lines[paragraphLine].startIndex + indexInLine;
6415
6385
  }
6416
6386
  static getIndexInLine(tokens, lineInfo, numberingData, marginLeft, pageX, tokenDivider) {
6417
- if (tokens[0].isParagraph) {
6418
- return 0;
6419
- }
6420
- let indexInLine = 0;
6387
+ let index = 0;
6421
6388
  const markerOffset = NumberingHelper.getOffsetCausedByMarker(numberingData, lineInfo);
6422
6389
  let width = pageX - marginLeft - lineInfo.paddingLeft - lineInfo.offsetMargin - markerOffset;
6423
- while (indexInLine < tokens.length && width >= tokens[indexInLine].width / tokenDivider) {
6424
- width -= tokens[indexInLine].width;
6425
- indexInLine++;
6390
+ while (index < tokens.length && !tokens[index].isParagraph) {
6391
+ const merged = this.mergeCustomTokens(tokens, index);
6392
+ if (width >= merged.width / tokenDivider) {
6393
+ width -= merged.width;
6394
+ index += merged.count;
6395
+ }
6396
+ else {
6397
+ break;
6398
+ }
6399
+ }
6400
+ return index === 0 ? 0 : tokens[index - 1].index - tokens[0].index + 1;
6401
+ }
6402
+ static mergeCustomTokens(tokens, index) {
6403
+ let count = 1;
6404
+ let width = tokens[index].width;
6405
+ if (!(tokens[index].customIndex >= 0)) {
6406
+ return { width, count };
6407
+ }
6408
+ while (index + count < tokens.length && tokens[index].index === tokens[index + count].index) {
6409
+ width += tokens[index + count].width;
6410
+ count++;
6426
6411
  }
6427
- return indexInLine;
6412
+ return { width, count };
6428
6413
  }
6429
6414
  }
6430
6415
 
@@ -6498,45 +6483,44 @@ class RenderingHelper {
6498
6483
  static renderParagraph(domContent, paragraph, formats, customContentService, customComponents, scalingRatio, breaks = []) {
6499
6484
  const { offset, markerWidth } = NumberingHelper.getMarkerOffset(paragraph.paragraphSettings);
6500
6485
  const lineInfos = paragraph.paragraphSettings.textLinesInfo;
6501
- const start = paragraph.startIndex;
6502
- const end = paragraph.startIndex + paragraph.content.length;
6486
+ const lastLine = paragraph.paragraphSettings.textLinesInfo.length - 1;
6503
6487
  const fragment = DomHelper.createFragment(domContent.currentElement);
6504
6488
  let lineIndex = 0;
6505
- let renderedCount = 0;
6489
+ let renderedIndexes = 0;
6490
+ let renderedTokensInLine = 0;
6491
+ let lineEndIndex = lineInfos[0].endIndex + paragraph.startIndex;
6506
6492
  let lineEl = RenderingHelper.createLineElement(paragraph.paragraphSettings.textLinesInfo[0], offset - markerWidth, scalingRatio);
6507
6493
  for (const format of formats) {
6508
6494
  do {
6509
- const lineEnd = paragraph.nextLineIndexes[lineIndex]
6510
- ? paragraph.startIndex + paragraph.nextLineIndexes[lineIndex] - 1
6511
- : end;
6512
- let fragmentEnd = format.endIndex < lineEnd ? format.endIndex : lineEnd;
6495
+ let fragmentEndIndex = format.endIndex < lineEndIndex ? format.endIndex : lineEndIndex;
6513
6496
  let wordSpacing = lineInfos[lineIndex].wordSpacing;
6514
6497
  if (wordSpacing) {
6515
- const lineStart = lineIndex > 0 ? paragraph.nextLineIndexes[lineIndex - 1] : 0;
6516
- const lineStartIndex = start + lineStart;
6517
- const renderedInLine = renderedCount - lineStart;
6518
- const wordSpacingStart = lineInfos[lineIndex].wordSpacingStart;
6519
- const wordSpacingEnd = lineInfos[lineIndex].wordSpacingEnd;
6520
- if (renderedInLine < wordSpacingStart && lineStartIndex + wordSpacingStart < fragmentEnd) {
6521
- fragmentEnd = lineStartIndex + wordSpacingStart;
6498
+ const wordSpacingStartToken = lineInfos[lineIndex].wordSpacingStartToken;
6499
+ const wordSpacingEndToken = lineInfos[lineIndex].wordSpacingEndToken;
6500
+ const wordSpacingStartIndex = lineInfos[lineIndex].wordSpacingStartIndex + paragraph.startIndex;
6501
+ const wordSpacingEndIndex = lineInfos[lineIndex].wordSpacingEndIndex + paragraph.startIndex;
6502
+ if (renderedTokensInLine < wordSpacingStartToken && wordSpacingStartIndex < fragmentEndIndex) {
6503
+ fragmentEndIndex = wordSpacingStartIndex;
6522
6504
  }
6523
- else if (renderedInLine < wordSpacingEnd && lineStartIndex + wordSpacingEnd < fragmentEnd) {
6524
- fragmentEnd = lineStartIndex + wordSpacingEnd;
6505
+ else if (renderedTokensInLine < wordSpacingEndToken && wordSpacingEndIndex < fragmentEndIndex) {
6506
+ fragmentEndIndex = wordSpacingEndIndex;
6525
6507
  }
6526
- if (renderedInLine < wordSpacingStart || renderedInLine > wordSpacingEnd) {
6508
+ if (renderedTokensInLine < wordSpacingStartToken || renderedTokensInLine > wordSpacingEndToken) {
6527
6509
  wordSpacing = null;
6528
6510
  }
6529
6511
  }
6530
- const fragmentLength = fragmentEnd - start - renderedCount + 1;
6531
- this.renderFormatContent(fragment, format.textStyle, start + renderedCount, fragmentEnd, paragraph.content.substring(renderedCount, renderedCount + fragmentLength), customContentService, customComponents, breaks, wordSpacing);
6512
+ const rendered = this.renderFormatContent(fragment, paragraph.content.substring(renderedIndexes, fragmentEndIndex - paragraph.startIndex + 1), paragraph.startIndex + renderedIndexes, fragmentEndIndex, renderedTokensInLine, format.textStyle, lineInfos[lineIndex], customContentService, customComponents, breaks, wordSpacing, paragraph.startIndex);
6532
6513
  lineEl.appendChild(fragment);
6533
- renderedCount += fragmentLength;
6534
- if (paragraph.nextLineIndexes.length > lineIndex && start + renderedCount > lineEnd) {
6514
+ renderedIndexes += rendered.renderedIndexes;
6515
+ renderedTokensInLine += rendered.renderedTokens;
6516
+ if (lineIndex < lastLine && fragmentEndIndex === lineEndIndex) {
6535
6517
  lineIndex++;
6518
+ lineEndIndex = lineInfos[lineIndex].endIndex + paragraph.startIndex;
6536
6519
  domContent.parentNode.appendChild(lineEl);
6537
6520
  lineEl = RenderingHelper.createLineElement(lineInfos[lineIndex], offset, scalingRatio);
6521
+ renderedTokensInLine = 0;
6538
6522
  }
6539
- } while (renderedCount < paragraph.content.length && format.endIndex > start + renderedCount);
6523
+ } while (renderedIndexes < paragraph.content.length && format.endIndex >= paragraph.startIndex + renderedIndexes);
6540
6524
  domContent.parentNode.appendChild(lineEl);
6541
6525
  }
6542
6526
  }
@@ -6563,36 +6547,88 @@ class RenderingHelper {
6563
6547
  containerElement.className = className;
6564
6548
  return containerElement;
6565
6549
  }
6566
- static renderFormatContent(fragment, textStyle, start, end, textFragment, customContentService, customComponents, breaks, wordSpacing) {
6567
- if (!textFragment) {
6568
- return;
6569
- }
6570
- const textFragmentWithoutBreaks = BreakHelper.removeBreakMarker(breaks, textFragment, start);
6571
- const components = customContentService.getComponents(customComponents, start, end);
6572
- if (components.length) {
6573
- let newTextFragmentStartIndex = start;
6574
- let nextTextFragment = textFragmentWithoutBreaks;
6575
- for (const component of components) {
6576
- const textBeforeElement = nextTextFragment.substring(0, component.instance.insertIndex - newTextFragmentStartIndex);
6577
- nextTextFragment = nextTextFragment.substring(textBeforeElement.length + 1, nextTextFragment.length);
6578
- newTextFragmentStartIndex = newTextFragmentStartIndex + (textBeforeElement.length ? textBeforeElement.length + 1 : 1);
6579
- if (textBeforeElement.length) {
6580
- this.renderText(fragment, textStyle, textBeforeElement, wordSpacing);
6581
- }
6582
- customContentService.componentService.attachComponent(fragment, component);
6550
+ static renderFormatContent(fragment, fragmentText, fragmentStartIndex, // model content index
6551
+ fragmentEndIndex, // model content index
6552
+ renderedTokensInLine, textStyle, line, customContentService, customComponents, breaks, wordSpacing, paragraphStartIndex) {
6553
+ let renderedIndexes = 0;
6554
+ if (!fragmentText) {
6555
+ return { renderedIndexes, renderedTokens: 0 };
6556
+ }
6557
+ let additionalTokens = 0;
6558
+ if (fragmentText.at(-1) === CUSTOM_ELEMENT_MARKER &&
6559
+ breaks.some(x => x.insertIndex === fragmentStartIndex + fragmentText.length - 1)) {
6560
+ fragmentText = fragmentText.substring(0, fragmentText.length - 1);
6561
+ renderedIndexes = 1;
6562
+ }
6563
+ const components = customContentService.getComponents(customComponents, fragmentStartIndex, fragmentEndIndex);
6564
+ for (const component of components) {
6565
+ const textBeforeElement = fragmentText.substring(0, component.instance.insertIndex - fragmentStartIndex);
6566
+ fragmentText = fragmentText.substring(textBeforeElement.length + 1, fragmentText.length);
6567
+ this.renderText(fragment, textStyle, textBeforeElement, wordSpacing);
6568
+ renderedIndexes += textBeforeElement.length;
6569
+ if (component.instance instanceof ExternalComponent && component.instance.isText) {
6570
+ const rendered = this.renderExternalText(fragment, textStyle, wordSpacing, component.instance, line, renderedTokensInLine, paragraphStartIndex);
6571
+ renderedIndexes += rendered.renderedIndexes;
6572
+ additionalTokens += rendered.additionalTokens;
6583
6573
  }
6584
- if (nextTextFragment.length) {
6585
- this.renderText(fragment, textStyle, nextTextFragment, wordSpacing);
6574
+ else {
6575
+ customContentService.componentService.attachComponent(fragment, component);
6576
+ renderedIndexes++;
6586
6577
  }
6578
+ fragmentStartIndex = fragmentStartIndex + textBeforeElement.length + 1;
6579
+ }
6580
+ this.renderText(fragment, textStyle, fragmentText, wordSpacing);
6581
+ renderedIndexes += fragmentText.length;
6582
+ return { renderedIndexes, renderedTokens: renderedIndexes + additionalTokens };
6583
+ }
6584
+ static renderExternalText(fragment, textStyle, wordSpacing, instance, line, renderedTokensInLine, paragraphStartIndex) {
6585
+ let additionalTokens = 0;
6586
+ let renderedIndexes = 0;
6587
+ const attributes = [
6588
+ { name: 'data-session-id', value: `${instance.sessionId}` },
6589
+ { name: 'data-insert-index', value: `${instance.insertIndex}` }
6590
+ ];
6591
+ let text = instance.getText();
6592
+ text = !text.length ? ' ' : text;
6593
+ const customText = line.customTexts.find(x => x.index === instance.insertIndex - paragraphStartIndex);
6594
+ const customTextFragment = text.substring(customText.start, customText.end);
6595
+ if (!line.wordSpacing) {
6596
+ this.renderText(fragment, textStyle, customTextFragment, wordSpacing, [CUSTOM_TAG, 'noder-pointing'], attributes);
6597
+ additionalTokens += customTextFragment.length;
6587
6598
  }
6588
6599
  else {
6589
- this.renderText(fragment, textStyle, textFragmentWithoutBreaks, wordSpacing);
6600
+ const wordSpacingStart = line.wordSpacingStartToken - renderedTokensInLine - renderedIndexes - additionalTokens;
6601
+ const wordSpacingEnd = line.wordSpacingEndToken - renderedTokensInLine - renderedIndexes - additionalTokens;
6602
+ if (wordSpacingStart > 0) {
6603
+ const leftText = customTextFragment.substring(0, wordSpacingStart);
6604
+ this.renderText(fragment, textStyle, leftText, null, [CUSTOM_TAG, 'noder-pointing'], attributes);
6605
+ additionalTokens += leftText.length;
6606
+ }
6607
+ const middleText = customTextFragment.substring(wordSpacingStart, wordSpacingEnd + 1);
6608
+ this.renderText(fragment, textStyle, middleText, line.wordSpacing, [CUSTOM_TAG, 'noder-pointing'], attributes);
6609
+ additionalTokens += middleText.length;
6610
+ if (wordSpacingEnd >= 0) {
6611
+ const rightText = customTextFragment.substring(wordSpacingEnd + 1);
6612
+ this.renderText(fragment, textStyle, rightText, null, [CUSTOM_TAG, 'noder-pointing'], attributes);
6613
+ additionalTokens += rightText.length;
6614
+ }
6615
+ }
6616
+ if (text.length === customText.end) {
6617
+ renderedIndexes++;
6618
+ additionalTokens--;
6619
+ }
6620
+ return { renderedIndexes, additionalTokens };
6621
+ }
6622
+ static renderText(fragment, textStyle, content, wordSpacing, additionalClasses = [], additionalAttributes = []) {
6623
+ if (!content.length) {
6624
+ return;
6590
6625
  }
6591
- }
6592
- static renderText(fragment, textStyle, content, wordSpacing) {
6593
6626
  const span = document.createElement('span');
6594
- if (content === NEW_LINE_MARKUP) {
6595
- span.className = 'paragraph-symbol';
6627
+ for (const additionalClass of additionalClasses) {
6628
+ span.classList.add(additionalClass);
6629
+ }
6630
+ for (const attribute of additionalAttributes) {
6631
+ span.setAttribute(attribute.name, attribute.value);
6596
6632
  }
6597
6633
  if (textStyle.headingStyleId === HYPERLINK_HEADING_STYLE_ID) {
6598
6634
  span.classList.add('hyperlink');
@@ -7057,6 +7093,7 @@ class ParagraphHelper {
7057
7093
  const { splitsCount, leftHeight, tableHeight, tableInsertIndex } = ParagraphHelper.processTableSplit(tables, startInsertIndex, leftSpaceOnPage, spaceBetweenPagesContent, currentPageVerticalData.contentHeight);
7058
7094
  previousTableInsertIndex = tableInsertIndex;
7059
7095
  textLineInfo.height = tableHeight;
7096
+ textLineInfo.ascent = tableHeight;
7060
7097
  textLineInfo.page = currentPage;
7061
7098
  currentPage += splitsCount;
7062
7099
  if (splitsCount) {
@@ -7435,9 +7472,9 @@ class Range {
7435
7472
  const compare = this.compareSingleLine(position);
7436
7473
  return compare ?? this.compareMultiLine(position);
7437
7474
  }
7438
- paragraphToDocumentLine(session) {
7439
- const screenPosStart = PositionHelper.paragraphToDocumentLine(session, this.start.row, this.start.column);
7440
- const screenPosEnd = PositionHelper.paragraphToDocumentLine(session, this.end.row, this.end.column);
7475
+ paragraphToDocumentLine(paragraphs) {
7476
+ const screenPosStart = PositionHelper.paragraphToDocumentLine(paragraphs[this.start.row], this.start.column);
7477
+ const screenPosEnd = PositionHelper.paragraphToDocumentLine(paragraphs[this.end.row], this.end.column);
7441
7478
  return new Range(screenPosStart, screenPosEnd);
7442
7479
  }
7443
7480
  /**
@@ -8302,12 +8339,12 @@ class Selection {
8302
8339
  this.anchor = null;
8303
8340
  }
8304
8341
  selectRight(session) {
8305
- const position = this.getCursorRight(session);
8342
+ const position = this.getRight(session.displayData.paragraphs, this.cursor.row, this.cursor.column);
8306
8343
  this.moveSelection(position);
8307
8344
  }
8308
8345
  navigateRight(session) {
8309
8346
  if (this.isEmpty) {
8310
- const position = this.getCursorRight(session);
8347
+ const position = this.getRight(session.displayData.paragraphs, this.cursor.row, this.cursor.column);
8311
8348
  this.placeCursor(position);
8312
8349
  }
8313
8350
  else {
@@ -8316,12 +8353,12 @@ class Selection {
8316
8353
  }
8317
8354
  }
8318
8355
  selectLeft(session) {
8319
- const position = this.getCursorLeft(session);
8356
+ const position = this.getLeft(session.displayData.paragraphs, this.cursor.row, this.cursor.column);
8320
8357
  this.moveSelection(position);
8321
8358
  }
8322
8359
  navigateLeft(session) {
8323
8360
  if (this.isEmpty) {
8324
- const position = this.getCursorLeft(session);
8361
+ const position = this.getLeft(session.displayData.paragraphs, this.cursor.row, this.cursor.column);
8325
8362
  this.placeCursor(position);
8326
8363
  }
8327
8364
  else {
@@ -8347,12 +8384,12 @@ class Selection {
8347
8384
  }
8348
8385
  selectFileEnd(session) {
8349
8386
  const paragraph = session.displayData.paragraphs.length - 1;
8350
- const paragraphIndex = session.displayData.getParagraphContent(paragraph).length;
8387
+ const paragraphIndex = session.displayData.paragraphs[paragraph].content.length;
8351
8388
  this.moveSelection(new CursorParagraph(paragraph, paragraphIndex));
8352
8389
  }
8353
8390
  navigateFileEnd(session) {
8354
8391
  const paragraph = session.displayData.paragraphs.length - 1;
8355
- const paragraphIndex = session.displayData.getParagraphContent(paragraph).length;
8392
+ const paragraphIndex = session.displayData.paragraphs[paragraph].content.length;
8356
8393
  this.placeCursor(new CursorParagraph(paragraph, paragraphIndex));
8357
8394
  }
8358
8395
  selectFileStart() {
@@ -8378,73 +8415,80 @@ class Selection {
8378
8415
  this.placeCursor(position);
8379
8416
  }
8380
8417
  moveCursorUp(session, position) {
8381
- const line = PositionHelper.paragraphToDocumentLine(session, position.row, position.column);
8418
+ const paragraphs = session.displayData.paragraphs;
8419
+ const line = PositionHelper.paragraphToDocumentLine(paragraphs[position.row], position.column);
8382
8420
  if (line.row === 0) {
8383
8421
  this.selectLineStart(session);
8422
+ return;
8423
+ }
8424
+ const moved = this.moveToLine(session, line.row - 1, line);
8425
+ if (moved.paragraph !== position.row || moved.indexInParagraph !== position.column) {
8426
+ this.cursor = new CursorParagraph(moved.paragraph, moved.indexInParagraph);
8384
8427
  }
8385
8428
  else {
8386
- this.moveToLine(session, line.row - 1, line);
8429
+ this.cursor = this.getLeft(paragraphs, moved.paragraph, moved.indexInParagraph);
8387
8430
  }
8388
8431
  }
8389
8432
  moveCursorDown(session, position) {
8390
- const line = PositionHelper.paragraphToDocumentLine(session, position.row, position.column);
8391
- const lastParagraphsIndex = session.displayData.paragraphs.length - 1;
8392
- const lastParagraph = session.displayData.getParagraphSettings(lastParagraphsIndex);
8393
- const lastParagraphLine = lastParagraph.textLinesInfo[lastParagraph.textLinesInfo.length - 1].screenLine;
8394
- if (line.row === lastParagraphLine) {
8433
+ const paragraphs = session.displayData.paragraphs;
8434
+ const line = PositionHelper.paragraphToDocumentLine(paragraphs[position.row], position.column);
8435
+ const lastParagraphLines = paragraphs[paragraphs.length - 1].paragraphSettings.textLinesInfo;
8436
+ const lastDocumentLine = lastParagraphLines[lastParagraphLines.length - 1].screenLine;
8437
+ if (line.row === lastDocumentLine) {
8395
8438
  this.selectLineEnd(session);
8439
+ return;
8440
+ }
8441
+ const moved = this.moveToLine(session, line.row + 1, line);
8442
+ if (moved.paragraph !== position.row || moved.indexInParagraph !== position.column) {
8443
+ this.cursor = new CursorParagraph(moved.paragraph, moved.indexInParagraph);
8396
8444
  }
8397
8445
  else {
8398
- this.moveToLine(session, line.row + 1, line);
8446
+ this.cursor = this.getRight(paragraphs, moved.paragraph, moved.indexInParagraph);
8399
8447
  }
8400
8448
  }
8401
8449
  moveToLine(session, line, fromLine) {
8402
8450
  if (!this.keepLinePositionX) {
8403
8451
  this.keepLinePositionX = PositionHelper.documentLineToPixel(session, fromLine.row, fromLine.column).pageX;
8404
8452
  }
8405
- const indexInLine = PositionHelper.pixelToIndexInLine(session, line, this.keepLinePositionX, 2);
8406
- this.cursor = PositionHelper.documentLineToParagraph(session, line, indexInLine);
8407
- this.overlayService.close();
8453
+ const { paragraph, paragraphLine } = PositionHelper.documentLineToParagraphLine(session.displayData.paragraphs, line);
8454
+ const indexInParagraph = PositionHelper.pixelToIndexInParagraph(session, this.keepLinePositionX, paragraph, paragraphLine, 2);
8455
+ return { paragraph, indexInParagraph };
8408
8456
  }
8409
- getCursorLeft(session) {
8410
- if (this.cursor.row === 0 && this.cursor.column === 0) {
8411
- return this.cursor;
8457
+ getLeft(paragraphs, paragraph, indexInParagraph) {
8458
+ if (paragraph === 0) {
8459
+ indexInParagraph -= indexInParagraph > 0 ? 1 : 0;
8460
+ return new CursorParagraph(paragraph, indexInParagraph);
8461
+ }
8462
+ indexInParagraph--;
8463
+ if (indexInParagraph >= 0) {
8464
+ return new CursorParagraph(paragraph, indexInParagraph);
8412
8465
  }
8413
- const index = ContentHelper.paragraphPositionToDocumentIndex(session.displayData.paragraphs, this.cursor);
8414
- return ContentHelper.documentIndexToParagraphIndex(session.displayData.paragraphs, index - 1);
8466
+ return new CursorParagraph(paragraph - 1, paragraphs[paragraph].startIndex - paragraphs[paragraph - 1].startIndex - 1);
8415
8467
  }
8416
- getCursorRight(session) {
8417
- const last = session.displayData.paragraphs.length - 1;
8418
- if (this.cursor.row === last && this.cursor.column === session.displayData.getParagraphContent(last).length) {
8419
- return this.cursor;
8468
+ getRight(paragraphs, paragraph, indexInParagraph) {
8469
+ if (paragraph === paragraphs.length - 1) {
8470
+ indexInParagraph += indexInParagraph < paragraphs[paragraphs.length - 1].content.length ? 1 : 0;
8471
+ return new CursorParagraph(paragraph, indexInParagraph);
8420
8472
  }
8421
- const index = ContentHelper.paragraphPositionToDocumentIndex(session.displayData.paragraphs, this.cursor);
8422
- return ContentHelper.documentIndexToParagraphIndex(session.displayData.paragraphs, index + 1);
8473
+ indexInParagraph++;
8474
+ if (paragraphs[paragraph + 1].startIndex === paragraphs[paragraph].startIndex + indexInParagraph) {
8475
+ return new CursorParagraph(paragraph + 1, 0);
8476
+ }
8477
+ return new CursorParagraph(paragraph, indexInParagraph);
8423
8478
  }
8424
8479
  getLineStart(session, position) {
8425
- const line = PositionHelper.paragraphToDocumentLine(session, position.row, position.column);
8480
+ const line = PositionHelper.paragraphToDocumentLine(session.displayData.paragraphs[position.row], position.column);
8426
8481
  return PositionHelper.documentLineToParagraph(session, line.row, 0);
8427
8482
  }
8428
8483
  getLineEnd(session, position) {
8429
- const line = PositionHelper.paragraphToDocumentLine(session, position.row, position.column);
8430
- const paragraphLength = session.displayData.getParagraphContent(position.row).length;
8431
- const linesCount = session.displayData.getParagraphSettings(position.row).textLinesInfo.length;
8432
- if (linesCount === 1) {
8433
- return PositionHelper.documentLineToParagraph(session, line.row, paragraphLength);
8434
- }
8435
- const paragraphLine = line.row - session.displayData.paragraphs[position.row].lineNumber;
8436
- const nextLineIndexes = session.displayData.paragraphs[position.row].nextLineIndexes;
8437
- let index;
8438
- if (paragraphLine === 0) {
8439
- index = nextLineIndexes[0];
8440
- }
8441
- else if (paragraphLine === linesCount - 1) {
8442
- index = paragraphLength - nextLineIndexes[paragraphLine - 1];
8484
+ const paragraph = session.displayData.paragraphs[position.row];
8485
+ const documentLine = PositionHelper.paragraphToDocumentLine(paragraph, position.column);
8486
+ if (documentLine.row - paragraph.lineNumber === paragraph.paragraphSettings.textLinesInfo.length - 1) {
8487
+ return new CursorParagraph(position.row, paragraph.content.length);
8443
8488
  }
8444
- else {
8445
- index = nextLineIndexes[paragraphLine] - nextLineIndexes[paragraphLine - 1];
8446
- }
8447
- return PositionHelper.documentLineToParagraph(session, line.row, index);
8489
+ const paragraphLine = paragraph.paragraphSettings.textLinesInfo[documentLine.row - paragraph.lineNumber];
8490
+ const endOfLineIndex = paragraphLine.endIndex - paragraphLine.startIndex + 1;
8491
+ return PositionHelper.documentLineToParagraph(session, documentLine.row, endOfLineIndex);
8448
8492
  }
8449
8493
  getWordRight(session, position) {
8450
8494
  let row = position.row;
@@ -8640,7 +8684,7 @@ class Editor {
8640
8684
  get grammarChecker() {
8641
8685
  return this.regulatorService.grammarChecker;
8642
8686
  }
8643
- constructor(model, container, editorService, overlayService, regulatorService, commandsService, clipboard, externalElementTagNames, insertOverlays, customPageWidth) {
8687
+ constructor(model, container, editorService, overlayService, regulatorService, commandsService, clipboard, externalElementTags, insertOverlays, customPageWidth) {
8644
8688
  this.model = model;
8645
8689
  this.container = container;
8646
8690
  this.editorService = editorService;
@@ -8648,14 +8692,9 @@ class Editor {
8648
8692
  this.regulatorService = regulatorService;
8649
8693
  this.commandsService = commandsService;
8650
8694
  this.clipboard = clipboard;
8651
- this.externalElementTagNames = externalElementTagNames;
8695
+ this.externalElementTags = externalElementTags;
8652
8696
  this.insertOverlays = insertOverlays;
8653
8697
  this.customPageWidth = customPageWidth;
8654
- this.MAX_COUNT = 999;
8655
- this.parentTagName = 'APP-NOD-EDITOR';
8656
- this.tableCellTagName = 'APP-NOD-TABLE-CELL';
8657
- this.edgeElementTagName = 'APP-NOD-EDGE';
8658
- this.imageTagName = 'APP-NOD-IMAGE';
8659
8698
  this.subscriptions = [];
8660
8699
  this.commentCreateRequests = [];
8661
8700
  this.emojiRegex = /\p{Extended_Pictographic}(?:\p{Emoji_Modifier}|\u{200D}\p{Extended_Pictographic})*/gu;
@@ -8670,7 +8709,7 @@ class Editor {
8670
8709
  this.renderer.updateCursor();
8671
8710
  };
8672
8711
  this.subscriptions.push(this.receiveTextStyleSubscription());
8673
- this.customElementTagNames = [...this.externalElementTagNames, this.imageTagName, this.tableCellTagName, this.edgeElementTagName];
8712
+ this.customElementTags = [...this.externalElementTags, IMAGE_TAG, TABLE_CELL_TAG, EDGE_TAG, CUSTOM_TAG];
8674
8713
  this.history = new OperationHistory(editorService, regulatorService);
8675
8714
  this.selection = new Selection(this.overlayService);
8676
8715
  this.regulatorService.setSelection(this.selection);
@@ -9758,7 +9797,7 @@ class Editor {
9758
9797
  }
9759
9798
  onMouseClick(event) {
9760
9799
  const customElement = this.setCurrentSession(event.target);
9761
- if (customElement && customElement.tagName !== this.tableCellTagName && customElement.tagName !== this.edgeElementTagName) {
9800
+ if (customElement && customElement.tagName !== TABLE_CELL_TAG && customElement.tagName !== EDGE_TAG) {
9762
9801
  this.focusCustomComponent(customElement);
9763
9802
  }
9764
9803
  else {
@@ -9789,7 +9828,7 @@ class Editor {
9789
9828
  }
9790
9829
  onShortLeftClick(event, isSelectionClick = false) {
9791
9830
  const customElement = this.setCurrentSession(event.target);
9792
- if (customElement && customElement.tagName !== this.tableCellTagName && customElement.tagName !== this.edgeElementTagName) {
9831
+ if (customElement && customElement.tagName !== TABLE_CELL_TAG && customElement.tagName !== EDGE_TAG) {
9793
9832
  this.focusCustomComponent(customElement);
9794
9833
  return;
9795
9834
  }
@@ -9842,7 +9881,7 @@ class Editor {
9842
9881
  this.regulatorService.setMainSessionAsCurrent();
9843
9882
  }
9844
9883
  }
9845
- if (customElement && customElement.tagName !== this.tableCellTagName && customElement.tagName !== this.edgeElementTagName) {
9884
+ if (customElement && customElement.tagName !== TABLE_CELL_TAG && customElement.tagName !== EDGE_TAG) {
9846
9885
  this.focusCustomComponent(customElement);
9847
9886
  return;
9848
9887
  }
@@ -9860,7 +9899,7 @@ class Editor {
9860
9899
  }
9861
9900
  onTripleClick(event) {
9862
9901
  const customElement = this.setCurrentSession(event.target);
9863
- if (customElement && customElement.tagName !== this.tableCellTagName && customElement.tagName !== this.edgeElementTagName) {
9902
+ if (customElement && customElement.tagName !== TABLE_CELL_TAG && customElement.tagName !== EDGE_TAG) {
9864
9903
  this.focusCustomComponent(customElement);
9865
9904
  return;
9866
9905
  }
@@ -9874,7 +9913,7 @@ class Editor {
9874
9913
  }
9875
9914
  onQuadClick(event) {
9876
9915
  const customElement = this.setCurrentSession(event.target);
9877
- if (customElement && customElement.tagName !== this.tableCellTagName && customElement.tagName !== this.edgeElementTagName) {
9916
+ if (customElement && customElement.tagName !== TABLE_CELL_TAG && customElement.tagName !== EDGE_TAG) {
9878
9917
  this.focusCustomComponent(customElement);
9879
9918
  return;
9880
9919
  }
@@ -9984,17 +10023,17 @@ class Editor {
9984
10023
  const isEdgeEdit = this.mainSession.customComponents.edges.isEdit;
9985
10024
  if (!customElement || (!isEdgeEdit && isInsideEdge)) {
9986
10025
  this.regulatorService.setMainSessionAsCurrent();
9987
- return this.customElementTagNames.includes(customElement?.tagName) ? customElement : null;
10026
+ return this.customElementTags.includes(customElement?.tagName) ? customElement : null;
9988
10027
  }
9989
10028
  const elementSessionId = +customElement.attributes.getNamedItem('data-session-id').value;
9990
10029
  this.regulatorService.setCustomSessionAsCurrent(elementSessionId);
9991
- return customElement.tagName !== this.edgeElementTagName ? customElement : null;
10030
+ return customElement.tagName !== EDGE_TAG ? customElement : null;
9992
10031
  }
9993
10032
  getCustomElement(element) {
9994
- if (!element || element.tagName === this.parentTagName) {
10033
+ if (!element || element.tagName === PARENT_TAG) {
9995
10034
  return null;
9996
10035
  }
9997
- else if (this.customElementTagNames.includes(element.tagName)) {
10036
+ else if (this.customElementTags.includes(element.tagName) || element.classList.contains(CUSTOM_TAG)) {
9998
10037
  return element;
9999
10038
  }
10000
10039
  else {
@@ -10005,10 +10044,10 @@ class Editor {
10005
10044
  return !!this.getParentEdge(element);
10006
10045
  }
10007
10046
  getParentEdge(element) {
10008
- if (!element || element.tagName === this.parentTagName) {
10047
+ if (!element || element.tagName === PARENT_TAG) {
10009
10048
  return null;
10010
10049
  }
10011
- else if (element.tagName === this.edgeElementTagName) {
10050
+ else if (element.tagName === EDGE_TAG) {
10012
10051
  return element;
10013
10052
  }
10014
10053
  else {
@@ -10084,7 +10123,7 @@ class Editor {
10084
10123
  return;
10085
10124
  }
10086
10125
  const customElement = this.container.nativeElement.querySelector(`[data-session-id="${this.session.sessionId}"]`);
10087
- if (customElement.tagName === this.tableCellTagName) {
10126
+ if (customElement.tagName === TABLE_CELL_TAG) {
10088
10127
  const tableSession = this.regulatorService.getSession(this.regulatorService.currentSession.parentSessionId);
10089
10128
  const table = tableSession.customComponents.tables.find(x => x.instance.sessionId === this.regulatorService.currentSession.parentSessionId);
10090
10129
  table.instance.tableSelection.clearSelection();
@@ -10900,7 +10939,7 @@ class DisplayToken {
10900
10939
  get isWhiteSpace() {
10901
10940
  return this.isSpace || this.isParagraph;
10902
10941
  }
10903
- get breaksLine() {
10942
+ get isBreak() {
10904
10943
  return this.isPageBreak || this.isLineBreak;
10905
10944
  }
10906
10945
  get breakable() {
@@ -12173,13 +12212,66 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImpor
12173
12212
  }], ctorParameters: () => [{ type: ComponentService }, { type: i0.ElementRef }, { type: OverlayService }, { type: RegulatorService }] });
12174
12213
 
12175
12214
  class DisplayTokenHelper {
12176
- static getDisplayValue(charCode, breakType) {
12215
+ static getParagraphToken(paragraphSymbolStyle, index) {
12216
+ const size = FontMetrics.measureCharSize('0', ContentStyleHelper.getFontStylesString(paragraphSymbolStyle));
12217
+ return new DisplayToken({ ...size, displayValue: DisplayValue.paragraph, index });
12218
+ }
12219
+ static getBreakToken(symbol, fontString, breakType, index) {
12220
+ return new DisplayToken({
12221
+ ...FontMetrics.measureCharSize(symbol, fontString),
12222
+ displayValue: this.getBreakDisplayValue(breakType),
12223
+ index
12224
+ });
12225
+ }
12226
+ static getSymbolToken(symbol, fontString, index) {
12227
+ const result = new DisplayToken({
12228
+ ...FontMetrics.measureCharSize(symbol, fontString),
12229
+ displayValue: this.getSymbolDisplayValue(symbol),
12230
+ index
12231
+ });
12232
+ if (result.isSpace) {
12233
+ result.ascent = 0;
12234
+ result.descent = 0;
12235
+ result.height = 0;
12236
+ }
12237
+ return result;
12238
+ }
12239
+ static getComponentTokens(component, fontString, index) {
12240
+ if (component.instance instanceof ExternalComponent && component.instance.isText) {
12241
+ const result = [];
12242
+ let text = component.instance.getText();
12243
+ text = !text.length ? ' ' : text;
12244
+ for (let i = 0; i < text.length; i++) {
12245
+ result.push(this.getSymbolToken(text[i], fontString, index));
12246
+ result[i].customIndex = i;
12247
+ }
12248
+ return result.length ? result : [this.getSymbolToken(' ', fontString, index)];
12249
+ }
12250
+ const ascent = component.instance.ascent() ?? 0;
12251
+ const descent = component.instance.descent() ?? 0;
12252
+ return [
12253
+ new DisplayToken({
12254
+ width: component.instance.width(),
12255
+ height: ascent + descent,
12256
+ font: FontMetrics.measureCharSize('0', fontString).font,
12257
+ ascent,
12258
+ descent,
12259
+ displayValue: this.getComponentDisplayValue(component.instance),
12260
+ index
12261
+ })
12262
+ ];
12263
+ }
12264
+ static getBreakDisplayValue(breakType) {
12177
12265
  if (breakType === BreakTypes.Page) {
12178
12266
  return DisplayValue.pageBreak;
12179
12267
  }
12180
12268
  if (breakType === BreakTypes.TextWrapping) {
12181
12269
  return DisplayValue.lineBreak;
12182
12270
  }
12271
+ return DisplayValue.char;
12272
+ }
12273
+ static getSymbolDisplayValue(symbol) {
12274
+ const charCode = symbol.charCodeAt(0);
12183
12275
  if (charCode === 32) {
12184
12276
  return DisplayValue.space;
12185
12277
  }
@@ -12191,32 +12283,14 @@ class DisplayTokenHelper {
12191
12283
  }
12192
12284
  return DisplayValue.char;
12193
12285
  }
12194
- static getParagraphToken(paragraphSymbolStyle) {
12195
- const size = FontMetrics.measureCharSize('0', ContentStyleHelper.getFontStylesString(paragraphSymbolStyle));
12196
- return new DisplayToken({ ...size, displayValue: DisplayValue.paragraph });
12197
- }
12198
- static getSymbolToken(code, size, breakType) {
12199
- const result = new DisplayToken({ ...size, displayValue: DisplayTokenHelper.getDisplayValue(code, breakType) });
12200
- if (result.isSpace) {
12201
- result.ascent = 0;
12202
- result.descent = 0;
12203
- result.height = 0;
12286
+ static getComponentDisplayValue(instance) {
12287
+ if (instance instanceof NoderTabComponent) {
12288
+ return DisplayValue.tab;
12204
12289
  }
12205
- return result;
12206
- }
12207
- static getComponentToken(component, size) {
12208
- const ascent = component.instance.ascent() ?? 0;
12209
- const descent = component.instance.descent() ?? 0;
12210
- let displayValue = component.instance instanceof NoderTabComponent ? DisplayValue.tab : DisplayValue.customContent;
12211
- displayValue = component.instance instanceof NoderTableComponent ? DisplayValue.table : displayValue;
12212
- return new DisplayToken({
12213
- width: component.instance.width(),
12214
- height: ascent + descent,
12215
- font: size.font,
12216
- ascent,
12217
- descent,
12218
- displayValue
12219
- });
12290
+ if (instance instanceof NoderTableComponent) {
12291
+ return DisplayValue.table;
12292
+ }
12293
+ return DisplayValue.customContent;
12220
12294
  }
12221
12295
  }
12222
12296
 
@@ -12240,72 +12314,26 @@ class LineInfoModel {
12240
12314
  }
12241
12315
 
12242
12316
  class LineInfoHelper {
12243
- static get(tokens, isAfterPageBreak, isLastLine, style, indent, isNumbering, width, defaultHeight, defaultAscent) {
12317
+ static get(tokens, style, indent, width, paragraphStartIndex, position) {
12244
12318
  const result = new LineInfoModel({
12245
- isAfterPageBreak,
12246
- isEndedByPageBreak: tokens[tokens.length - 1].isPageBreak,
12319
+ isAfterPageBreak: position.isAfterPageBreak,
12320
+ isEndedByPageBreak: tokens[tokens.length - 1].isPageBreak || (tokens.length > 1 && tokens[tokens.length - 2].isPageBreak),
12247
12321
  backgroundColor: style.backgroundColor,
12248
12322
  align: style.alignment ?? DEFAULT_PARAGRAPH_STYLE.alignment,
12249
12323
  indent,
12250
12324
  offsetBefore: DEFAULT_PARAGRAPH_STYLE.spaceBefore,
12251
12325
  lineSpacing: style.lineSpacing ?? DEFAULT_PARAGRAPH_STYLE.lineSpacing,
12252
- isNumbering,
12326
+ startIndex: tokens[0].index - paragraphStartIndex,
12327
+ endIndex: tokens[tokens.length - 1].index - paragraphStartIndex,
12328
+ isNumbering: position.isNumbering,
12253
12329
  hasTable: false,
12254
12330
  width: 0
12255
12331
  });
12256
- let maxAscent = 0;
12257
- let maxDescent = 0;
12258
- for (const token of tokens) {
12259
- if (maxAscent < token.ascent) {
12260
- maxAscent = token.ascent;
12261
- }
12262
- if (maxDescent < token.descent) {
12263
- maxDescent = token.descent;
12264
- }
12265
- result.width += token.width;
12266
- }
12267
- result.height = maxAscent + maxDescent;
12268
- result.ascent = maxAscent;
12269
- if (result.height === 0) {
12270
- result.height = defaultHeight;
12271
- result.ascent = defaultAscent;
12272
- }
12273
- result.offsetAfter = result.height * (result.lineSpacing - 1);
12274
- if (style.alignment === Alignment$1.justify && !isLastLine) {
12275
- let right = tokens.length - 1;
12276
- let adjustableWidth = result.width;
12277
- while (right > 0 && tokens[right].isSpace) {
12278
- adjustableWidth -= tokens[right].width;
12279
- right--;
12280
- }
12281
- let left = 0;
12282
- while (left < tokens.length - 1 && tokens[left].isSpace) {
12283
- left++;
12284
- }
12285
- let spaces = 0;
12286
- for (let i = right; i > left; i--) {
12287
- if (tokens[i].isTab) {
12288
- left = i;
12289
- }
12290
- if (tokens[i].isSpace) {
12291
- spaces++;
12292
- }
12293
- }
12294
- const indentWidth = (indent.left ?? 0) + (indent.right ?? 0) + (indent.firstLine ?? 0) - (indent.hanging ?? 0);
12295
- const availableWidth = width - indentWidth - indent.markerWidth; // todo: use NumberingHelper.getOffsetCausedByMarker
12296
- const whitespaceDeficit = availableWidth - adjustableWidth;
12297
- if (spaces > 0 && whitespaceDeficit > 0) {
12298
- result.wordSpacing = whitespaceDeficit / spaces;
12299
- result.width = availableWidth;
12300
- result.wordSpacingStart = left;
12301
- result.wordSpacingEnd = right;
12302
- for (let i = right; i > left; i--) {
12303
- if (tokens[i].isSpace) {
12304
- tokens[i].width += result.wordSpacing;
12305
- }
12306
- }
12307
- }
12332
+ this.applySizeToLine(result, tokens);
12333
+ if (style.alignment === Alignment$1.justify && !position.isLastLine) {
12334
+ this.applyWordSpacingToLine(result, tokens, indent, width, paragraphStartIndex);
12308
12335
  }
12336
+ this.applyCustomTextsToLine(result, tokens, paragraphStartIndex);
12309
12337
  return result;
12310
12338
  }
12311
12339
  static getFirstLineIndent(model, paragraphIndex, generalProperties) {
@@ -12323,6 +12351,86 @@ class LineInfoHelper {
12323
12351
  ? paragraph.paragraphStyle.indentLeft
12324
12352
  : levelsModel[paragraphStyle.numberingLevel].indentLeft, paragraph.paragraphStyle.indentRight ?? DEFAULT_PARAGRAPH_STYLE.indentRight, markerWidth + markerWidth / marker.length);
12325
12353
  }
12354
+ static applySizeToLine(line, tokens) {
12355
+ const lastToken = tokens[tokens.length - 1];
12356
+ let maxAscent = 0;
12357
+ let maxDescent = 0;
12358
+ let i = 0;
12359
+ const length = lastToken.isParagraph && tokens.length > 1 ? tokens.length - 1 : tokens.length;
12360
+ do {
12361
+ if (maxAscent < tokens[i].ascent) {
12362
+ maxAscent = tokens[i].ascent;
12363
+ }
12364
+ if (maxDescent < tokens[i].descent) {
12365
+ maxDescent = tokens[i].descent;
12366
+ }
12367
+ line.width += tokens[i].width;
12368
+ i++;
12369
+ } while (i < length);
12370
+ line.height = maxAscent + maxDescent;
12371
+ line.ascent = maxAscent;
12372
+ if (line.height === 0) {
12373
+ line.height = lastToken.ascent + lastToken.descent;
12374
+ line.ascent = lastToken.ascent;
12375
+ }
12376
+ line.offsetAfter = line.height * (line.lineSpacing - 1);
12377
+ }
12378
+ static applyWordSpacingToLine(line, tokens, indent, width, paragraphStartIndex) {
12379
+ const lastToken = tokens[tokens.length - 1].isParagraph ? tokens.length - 2 : tokens.length - 1;
12380
+ let right = lastToken;
12381
+ let adjustableWidth = line.width;
12382
+ while (right > 0 && tokens[right].isSpace) {
12383
+ adjustableWidth -= tokens[right].width;
12384
+ right--;
12385
+ }
12386
+ let left = 0;
12387
+ while (left < lastToken && tokens[left].isSpace) {
12388
+ left++;
12389
+ }
12390
+ let spaces = 0;
12391
+ for (let i = right; i > left; i--) {
12392
+ if (tokens[i].isTab) {
12393
+ left = i;
12394
+ }
12395
+ if (tokens[i].isSpace) {
12396
+ spaces++;
12397
+ }
12398
+ }
12399
+ const indentWidth = (indent.left ?? 0) + (indent.right ?? 0) + (indent.firstLine ?? 0) - (indent.hanging ?? 0);
12400
+ const availableWidth = width - indentWidth - indent.markerWidth; // todo: use NumberingHelper.getOffsetCausedByMarker
12401
+ const whitespaceDeficit = availableWidth - adjustableWidth;
12402
+ if (spaces > 0 && whitespaceDeficit > 0) {
12403
+ line.wordSpacing = whitespaceDeficit / spaces;
12404
+ line.width = availableWidth;
12405
+ line.wordSpacingStartToken = left;
12406
+ line.wordSpacingEndToken = right;
12407
+ line.wordSpacingStartIndex = tokens[left].index - paragraphStartIndex;
12408
+ line.wordSpacingEndIndex = tokens[right].index - paragraphStartIndex;
12409
+ for (let i = right; i > left; i--) {
12410
+ if (tokens[i].isSpace) {
12411
+ tokens[i].width += line.wordSpacing;
12412
+ }
12413
+ }
12414
+ }
12415
+ }
12416
+ static applyCustomTextsToLine(line, tokens, paragraphStartIndex) {
12417
+ for (const token of tokens) {
12418
+ if (token.customIndex >= 0) {
12419
+ const indexInParagraph = token.index - paragraphStartIndex;
12420
+ if (line.customTexts && line.customTexts[line.customTexts.length - 1].index === indexInParagraph) {
12421
+ line.customTexts[line.customTexts.length - 1].end++;
12422
+ }
12423
+ else {
12424
+ line.customTexts ??= [];
12425
+ line.customTexts.push({
12426
+ index: indexInParagraph,
12427
+ start: token.customIndex,
12428
+ end: token.customIndex + 1
12429
+ });
12430
+ }
12431
+ }
12432
+ }
12433
+ }
12326
12434
  }
12327
12435
 
12328
12436
  class PageVerticalDataModel {
@@ -12809,13 +12917,13 @@ class DisplayData extends EventEmitting {
12809
12917
  this.removeAllListeners('pagesCountChanged');
12810
12918
  }
12811
12919
  updateParagraphLineNumber(first) {
12812
- const count = this.paragraphs.length;
12813
12920
  if (first === 0) {
12814
12921
  this.paragraphs[first].lineNumber = 0;
12815
12922
  first++;
12816
12923
  }
12817
- for (let i = first; i < count; i++) {
12818
- this.paragraphs[i].lineNumber = this.paragraphs[i - 1].lineNumber + this.paragraphs[i - 1].nextLineIndexes.length + 1;
12924
+ for (let i = first; i < this.paragraphs.length; i++) {
12925
+ this.paragraphs[i].lineNumber =
12926
+ this.paragraphs[i - 1].lineNumber + this.paragraphs[i - 1].paragraphSettings.textLinesInfo.length;
12819
12927
  }
12820
12928
  }
12821
12929
  updateParagraphStartIndex(first) {
@@ -12863,8 +12971,7 @@ class DisplayData extends EventEmitting {
12863
12971
  NumberingHelper.setNumberingNeedToRecalculate(this.generalProperties.numberingInfo, numberingId);
12864
12972
  }
12865
12973
  const numberingData = NumberingHelper.createDataModel(this.generalProperties.numberings, this.model.paragraphs, i, this.generalProperties.numberingInfo);
12866
- const { splits, rowInfos } = this.splitParagraphByLines(i);
12867
- this.paragraphs[i].nextLineIndexes = splits;
12974
+ const rowInfos = this.splitParagraphByLines(i);
12868
12975
  if (indexOfParagraphAfterPageBreak === i) {
12869
12976
  rowInfos[0].isAfterPageBreak = true;
12870
12977
  }
@@ -12912,29 +13019,29 @@ class DisplayData extends EventEmitting {
12912
13019
  }
12913
13020
  splitParagraphByLines(paragraphIndex) {
12914
13021
  const paragraph = this.paragraphs[paragraphIndex];
12915
- const { paragraphTokens, paragraphToken } = this.getParagraphTokens(paragraph);
12916
- const splits = [];
13022
+ const isLastParagraph = paragraphIndex === this.paragraphs.length - 1;
13023
+ const paragraphSymbolIndex = paragraph.startIndex + paragraph.content.length;
13024
+ const paragraphTokens = this.getTokens(paragraph.startIndex, paragraph.content, paragraphSymbolIndex);
12917
13025
  const rowInfos = [];
12918
13026
  const style = this.model.paragraphs[paragraphIndex].paragraphStyle;
12919
13027
  const pageFormat = this.getPageFormatAtPosition(paragraph.startIndex);
12920
- const defaultHeight = paragraphToken.height;
12921
- const defaultAscent = paragraphToken.ascent;
12922
13028
  let index = 0;
12923
13029
  let indent = LineInfoHelper.getFirstLineIndent(this.model, paragraphIndex, this.generalProperties);
12924
13030
  do {
12925
13031
  let tokens = paragraphTokens.slice(index);
12926
13032
  const maxWidth = pageFormat.contentWidth - indent.right - indent.markerWidth;
12927
- let startWidth = indent.left + indent.firstLine - indent.hanging || 0;
12928
- let last = this.computeWrapIndex(tokens, startWidth, maxWidth, style.tabSettings ?? []);
13033
+ const startWidth = indent.left + indent.firstLine - indent.hanging || 0;
13034
+ const last = this.computeWrapToken(tokens, startWidth, maxWidth, style.tabSettings ?? [], isLastParagraph);
12929
13035
  tokens = tokens.slice(0, last + 1);
12930
13036
  const width = pageFormat.contentWidth;
12931
13037
  const isNumbering = index === 0 && !!indent.markerWidth;
12932
- const isBreak = !rowInfos.length ? false : rowInfos[rowInfos.length - 1].isEndedByPageBreak;
12933
- const isLast = index + last + 1 === paragraphTokens.length;
12934
- const info = LineInfoHelper.get(tokens, isBreak, isLast, style, indent, isNumbering, width, defaultHeight, defaultAscent);
13038
+ const isAfterPageBreak = !rowInfos.length ? false : rowInfos[rowInfos.length - 1].isEndedByPageBreak;
13039
+ const isLastLine = index + last + 1 === paragraphTokens.length;
13040
+ const position = { isLastLine, isNumbering, isAfterPageBreak };
13041
+ const info = LineInfoHelper.get(tokens, style, indent, width, paragraph.startIndex, position);
12935
13042
  for (let i = 0; i < tokens.length; i++) {
12936
13043
  if (tokens[i].isTab) {
12937
- const tab = this.customComponents.tabs.find(x => x.instance.insertIndex === paragraph.startIndex + index + i);
13044
+ const tab = this.customComponents.tabs.find(x => x.instance.insertIndex === tokens[i].index);
12938
13045
  tab.instance.applySize(tokens[i].width);
12939
13046
  }
12940
13047
  else if (tokens[i].isTable) {
@@ -12944,61 +13051,57 @@ class DisplayData extends EventEmitting {
12944
13051
  rowInfos.push(info);
12945
13052
  index += last + 1;
12946
13053
  if (index < paragraphTokens.length) {
12947
- splits.push(index);
12948
13054
  indent = new IndentModel(null, null, indent.left, indent.right, 0);
12949
13055
  }
12950
13056
  } while (index < paragraphTokens.length);
12951
13057
  ParagraphHelper.applyParagraphIndentsToLines(rowInfos, paragraphIndex, this.model.paragraphs);
12952
- return { splits, rowInfos };
12953
- }
12954
- getParagraphTokens(paragraphInfo) {
12955
- const paragraphSymbolIndex = paragraphInfo.startIndex + paragraphInfo.content.length;
12956
- const { tokens, paragraphToken } = this.getTokens(paragraphInfo.startIndex, paragraphInfo.content, paragraphSymbolIndex);
12957
- return { paragraphTokens: tokens, paragraphToken };
13058
+ return rowInfos;
12958
13059
  }
12959
13060
  getParagraphLineTokens(paragraphIndex, paragraphLine) {
12960
13061
  const paragraph = this.paragraphs[paragraphIndex];
12961
- const lineStart = paragraphLine > 0 ? paragraph.nextLineIndexes[paragraphLine - 1] : 0;
12962
- const lineEnd = paragraph.nextLineIndexes[paragraphLine] ? paragraph.nextLineIndexes[paragraphLine] : paragraph.content.length;
12963
- const lineContent = paragraph.content.substring(lineStart, lineEnd);
13062
+ const isLastParagraph = paragraphIndex === this.paragraphs.length - 1;
13063
+ const line = paragraph.paragraphSettings.textLinesInfo[paragraphLine];
13064
+ const lineContent = paragraph.content.substring(line.startIndex, line.endIndex + 1);
12964
13065
  const paragraphSymbolIndex = paragraph.paragraphSettings.startInsertIndex + paragraph.content.length;
12965
- const { tokens } = this.getTokens(lineStart + paragraph.startIndex, lineContent, paragraphSymbolIndex);
13066
+ const tokens = this.getTokens(line.startIndex + paragraph.startIndex, lineContent, paragraphSymbolIndex);
13067
+ if (line.customTexts && line.customTexts[0].index === line.startIndex) {
13068
+ tokens.splice(0, line.customTexts[0].start); // cut additional tokens in case when line starts from the middle of the textual custom component
13069
+ }
12966
13070
  const pageFormat = this.getPageFormatAtPosition(this.paragraphs[paragraphIndex].startIndex);
12967
13071
  const paragraphStyle = this.model.paragraphs[paragraphIndex].paragraphStyle;
12968
- const lineInfo = paragraph.paragraphSettings.textLinesInfo[paragraphLine];
12969
- const maxWidth = pageFormat.contentWidth - lineInfo.indent.right - lineInfo.indent.markerWidth;
12970
- const startWidth = lineInfo.indentLeft + lineInfo.indentFirstLine - lineInfo.indent.hanging || 0;
12971
- this.computeWrapIndex(tokens, startWidth, maxWidth, paragraphStyle.tabSettings ?? []); // needed to proceed a tab width correction according to the tabs complex positioning
12972
- const isLast = paragraphLine === paragraph.nextLineIndexes.length;
12973
- LineInfoHelper.get(tokens, false, isLast, paragraphStyle, lineInfo.indent, lineInfo.isNumbering, pageFormat.contentWidth, 0, 0); // needed to proceed a space width correction according to the wordSpacing in case of justify alignment
13072
+ const maxWidth = pageFormat.contentWidth - line.indent.right - line.indent.markerWidth;
13073
+ const startWidth = line.indentLeft + line.indentFirstLine - line.indent.hanging || 0;
13074
+ const last = this.computeWrapToken(tokens, startWidth, maxWidth, paragraphStyle.tabSettings ?? [], isLastParagraph); // tab width correction for tokens according to the tabs complex positioning
13075
+ tokens.splice(last + 1); // cut additional tokens in case when line ends in the middle of the textual custom component
13076
+ const isLastLine = paragraphLine === paragraph.paragraphSettings.textLinesInfo.length - 1;
13077
+ const position = { isLastLine, isNumbering: line.isNumbering, isAfterPageBreak: false };
13078
+ LineInfoHelper.get(tokens, paragraphStyle, line.indent, pageFormat.contentWidth, 0, position); // space width correction for tokens according to the wordSpacing in case of justify alignment
12974
13079
  return tokens;
12975
13080
  }
12976
13081
  getTokens(contentIndex, content, paragraphSymbolIndex) {
12977
13082
  const tokens = [];
12978
- const prev = { char: '', style: null, size: null };
12979
13083
  let format = FormatStyleHelper.getFormatAtIndex(this.model.formats, contentIndex);
12980
13084
  let fontString = ContentStyleHelper.getFontStylesString(format.textStyle);
12981
13085
  for (let i = 0; i < content.length; i++) {
12982
- if (content[i] !== prev.char || !prev.style || !ContentStyleHelper.areSameTextStyles(format.textStyle, prev.style)) {
12983
- prev.size = FontMetrics.measureCharSize(content[i], fontString);
12984
- prev.char = content[i];
12985
- prev.style = format.textStyle;
12986
- }
12987
- const customComponent = this.getOrGenerateComponent(contentIndex, content[i]);
12988
13086
  const breakType = BreakHelper.getBreakType(this.model.breaks, content[i], contentIndex);
12989
- const token = customComponent && !breakType
12990
- ? DisplayTokenHelper.getComponentToken(customComponent, prev.size)
12991
- : DisplayTokenHelper.getSymbolToken(content.charCodeAt(i), prev.size, breakType);
13087
+ const customComponent = breakType === null ? this.getOrGenerateComponent(contentIndex, content[i]) : null;
13088
+ let newTokens = breakType !== null ? [DisplayTokenHelper.getBreakToken(content[i], fontString, breakType, contentIndex)] : null;
13089
+ newTokens ??= customComponent
13090
+ ? DisplayTokenHelper.getComponentTokens(customComponent, fontString, contentIndex)
13091
+ : [DisplayTokenHelper.getSymbolToken(content[i], fontString, contentIndex)];
12992
13092
  contentIndex++;
12993
13093
  if (contentIndex > format.endIndex) {
12994
13094
  format = FormatStyleHelper.getFormatAtIndex(this.model.formats, contentIndex);
12995
13095
  fontString = ContentStyleHelper.getFontStylesString(format.textStyle);
12996
13096
  }
12997
- tokens.push(token);
13097
+ tokens.push(...newTokens);
12998
13098
  }
12999
- const paragraphFormat = FormatStyleHelper.getFormatAtIndex(this.model.formats, paragraphSymbolIndex);
13000
- const paragraphToken = DisplayTokenHelper.getParagraphToken(paragraphFormat.textStyle);
13001
- return tokens.length ? { tokens, paragraphToken } : { tokens: [paragraphToken], paragraphToken };
13099
+ if (contentIndex === paragraphSymbolIndex) {
13100
+ const paragraphFormat = FormatStyleHelper.getFormatAtIndex(this.model.formats, contentIndex);
13101
+ const paragraphToken = DisplayTokenHelper.getParagraphToken(paragraphFormat.textStyle, contentIndex);
13102
+ tokens.push(paragraphToken);
13103
+ }
13104
+ return tokens;
13002
13105
  }
13003
13106
  getOrGenerateComponent(charIndex, char) {
13004
13107
  if (!this.customContentService.isSpecialMarker(char)) {
@@ -13006,9 +13109,6 @@ class DisplayData extends EventEmitting {
13006
13109
  }
13007
13110
  const existingComponent = this.customContentService.getComponent(this.customComponents, char, charIndex);
13008
13111
  if (existingComponent) {
13009
- if (existingComponent.instance instanceof NoderTableComponent) {
13010
- existingComponent.instance.updateCells();
13011
- }
13012
13112
  return existingComponent;
13013
13113
  }
13014
13114
  const pageFormat = this.getPageFormatAtPosition(charIndex);
@@ -13044,16 +13144,19 @@ class DisplayData extends EventEmitting {
13044
13144
  }
13045
13145
  return -1;
13046
13146
  }
13047
- // The index of a token which should be the last on the line
13048
- computeWrapIndex(displayTokens, startWidth, maxWidth, tabSettings) {
13147
+ // Compute token which should be the last on the line
13148
+ computeWrapToken(displayTokens, startWidth, maxWidth, tabSettings, isLastParagraph) {
13049
13149
  let width = startWidth;
13050
13150
  let lastBreakable = -1;
13051
13151
  const lastTab = { token: null, alignment: TabAlignment.Left, usedWidth: 0, tokenWidth: 0 };
13052
13152
  for (let i = 0; i < displayTokens.length; i++) {
13053
13153
  const token = displayTokens[i];
13054
- if (token.breaksLine) {
13154
+ if (token.isParagraph) {
13055
13155
  return i;
13056
13156
  }
13157
+ if (token.isBreak) {
13158
+ return i + 1 < displayTokens.length && displayTokens[i + 1].isParagraph && !isLastParagraph ? i + 1 : i;
13159
+ }
13057
13160
  if (token.isTable) {
13058
13161
  return i > 0 ? i - 1 : 0;
13059
13162
  }
@@ -13202,7 +13305,7 @@ class DisplayData extends EventEmitting {
13202
13305
  const right = this.paragraphs[position.row].content.slice(position.column);
13203
13306
  const originalParagraphId = this.paragraphs[position.row].id;
13204
13307
  const insertParagraphs = this.splitByParagraphs(`${left}${text}${right}`).map((x, i) => {
13205
- const newParagraph = new ParagraphInfoModel({ content: x, nextLineIndexes: [] });
13308
+ const newParagraph = new ParagraphInfoModel({ content: x });
13206
13309
  if (i === 0) {
13207
13310
  newParagraph.id = originalParagraphId;
13208
13311
  }
@@ -14826,9 +14929,9 @@ class HighlightLayer {
14826
14929
  }
14827
14930
  drawCustomElementHighlight(elementInfo, cssClass, screenParentRange) {
14828
14931
  const paragraphPos = elementInfo.parentRange.start;
14829
- const documentLine = PositionHelper.paragraphToDocumentLine(this.session, paragraphPos.row, paragraphPos.column);
14830
14932
  const paragraph = this.session.displayData.paragraphs[paragraphPos.row];
14831
- const lineInfo = paragraph.paragraphSettings.textLinesInfo.find(x => x.screenLine === documentLine.column);
14933
+ const documentLine = PositionHelper.paragraphToDocumentLine(paragraph, paragraphPos.column);
14934
+ const lineInfo = paragraph.paragraphSettings.textLinesInfo.find(x => x.screenLine === documentLine.row);
14832
14935
  const elementIndex = paragraph.startIndex + paragraphPos.column;
14833
14936
  const element = this.session.customComponents.customElements.find(x => x.instance.content.insertIndex === elementIndex);
14834
14937
  if (!element) {
@@ -14876,7 +14979,7 @@ class CommentHighlightLayer extends HighlightLayer {
14876
14979
  const startPosition = ContentHelper.documentIndexToParagraphIndex(this.session.displayData.paragraphs, comment.startIndex);
14877
14980
  const endPosition = ContentHelper.documentIndexToParagraphIndex(this.session.displayData.paragraphs, comment.endIndex + 1);
14878
14981
  const range = new Range(startPosition, endPosition);
14879
- const screenRange = range.paragraphToDocumentLine(this.session);
14982
+ const screenRange = range.paragraphToDocumentLine(this.session.displayData.paragraphs);
14880
14983
  if (config.visibleRange &&
14881
14984
  (screenRange.end.row < config.visibleRange.startScreenLine || screenRange.start.row > config.visibleRange.endScreenLine)) {
14882
14985
  this.commentService.removeCommentFromRender(this.session.sessionId, comment.commentId);
@@ -14988,14 +15091,14 @@ class CursorLayer {
14988
15091
  this.addAnimationClass();
14989
15092
  }
14990
15093
  drawCursor(maxLayerHeight) {
14991
- const isCursorInView = this.cursorPosition.pageY >= 0 && this.cursorPosition.pageY < maxLayerHeight;
15094
+ // check does not make much sense, as right condition is true all the time (maybe it should be height instead of maxHeight), also it ignores scroll in virtual renderer case
15095
+ const isCursorInView = this.cursorPosition.pageY + this.cursorPosition.height >= 0 && this.cursorPosition.pageY < maxLayerHeight;
14992
15096
  if (!isCursorInView) {
14993
15097
  DomHelper.setStyle(this.cursor.style, 'display', 'none');
14994
15098
  return;
14995
15099
  }
14996
15100
  DomHelper.setStyle(this.cursor.style, 'display', 'block');
14997
15101
  DomHelper.setStyle(this.cursor.style, 'left', `${this.cursorPosition.pageX}px`);
14998
- DomHelper.setStyle(this.cursor.style, 'width', `${this.cursorPosition.width}px`);
14999
15102
  this.addTextStylesToCursor();
15000
15103
  }
15001
15104
  removeAnimationClass() {
@@ -15026,7 +15129,7 @@ class GrammarHighlightLayer extends HighlightLayer {
15026
15129
  continue;
15027
15130
  }
15028
15131
  for (const error of grammarErrors) {
15029
- const range = new Range(new CursorParagraph(index, error.offset), new CursorParagraph(index, error.offset + error.length)).paragraphToDocumentLine(this.session);
15132
+ const range = new Range(new CursorParagraph(index, error.offset), new CursorParagraph(index, error.offset + error.length)).paragraphToDocumentLine(this.session.displayData.paragraphs);
15030
15133
  if (config.visibleRange &&
15031
15134
  (range.end.row < config.visibleRange.startScreenLine || range.start.row > config.visibleRange.endScreenLine)) {
15032
15135
  continue;
@@ -15156,7 +15259,7 @@ class SearchHighlightLayer extends HighlightLayer {
15156
15259
  this.getVisibleCustomElementResults(config);
15157
15260
  if (this.active) {
15158
15261
  if (this.active instanceof Range) {
15159
- const screenRange = this.active.paragraphToDocumentLine(this.session);
15262
+ const screenRange = this.active.paragraphToDocumentLine(this.session.displayData.paragraphs);
15160
15263
  if (!screenRange.isEmpty &&
15161
15264
  (!config.visibleRange ||
15162
15265
  (screenRange.start.row >= config.visibleRange.startScreenLine &&
@@ -15171,13 +15274,13 @@ class SearchHighlightLayer extends HighlightLayer {
15171
15274
  }
15172
15275
  else {
15173
15276
  this.updateActiveResult();
15174
- const screenParentRange = this.active.parentRange.paragraphToDocumentLine(this.session);
15277
+ const screenParentRange = this.active.parentRange.paragraphToDocumentLine(this.session.displayData.paragraphs);
15175
15278
  this.drawCustomElementHighlight(this.active, this.selectedClassName, screenParentRange);
15176
15279
  }
15177
15280
  }
15178
15281
  if (this.markers?.length) {
15179
15282
  const ranges = this.markers
15180
- .map(x => x.paragraphToDocumentLine(this.session))
15283
+ .map(x => x.paragraphToDocumentLine(this.session.displayData.paragraphs))
15181
15284
  .filter(x => !x.isEmpty &&
15182
15285
  (!config.visibleRange ||
15183
15286
  (x.start.row >= config.visibleRange.startScreenLine && x.end.row <= config.visibleRange.endScreenLine)) &&
@@ -15202,7 +15305,7 @@ class SearchHighlightLayer extends HighlightLayer {
15202
15305
  this.active.location.isEqual(element.location))) {
15203
15306
  continue;
15204
15307
  }
15205
- const screenParentRange = element.parentRange.paragraphToDocumentLine(this.session);
15308
+ const screenParentRange = element.parentRange.paragraphToDocumentLine(this.session.displayData.paragraphs);
15206
15309
  if (!config.visibleRange ||
15207
15310
  (screenParentRange.start.row >= config.visibleRange.startScreenLine &&
15208
15311
  screenParentRange.end.row <= config.visibleRange.endScreenLine)) {
@@ -15240,7 +15343,7 @@ class SearchHighlightLayer extends HighlightLayer {
15240
15343
  return;
15241
15344
  }
15242
15345
  for (const group of groupedByParentRange) {
15243
- const screenParentRange = group.range.paragraphToDocumentLine(this.session);
15346
+ const screenParentRange = group.range.paragraphToDocumentLine(this.session.displayData.paragraphs);
15244
15347
  if (config.visibleRange &&
15245
15348
  (screenParentRange.start.row < config.visibleRange.startScreenLine ||
15246
15349
  screenParentRange.end.row > config.visibleRange.endScreenLine)) {
@@ -15284,7 +15387,7 @@ class SelectionLayer extends HighlightLayer {
15284
15387
  if (this.marker) {
15285
15388
  let range = this.marker.clipRows(config.contentRange.start, config.contentRange.end);
15286
15389
  if (!range.isEmpty) {
15287
- range = range.paragraphToDocumentLine(this.session);
15390
+ range = range.paragraphToDocumentLine(this.session.displayData.paragraphs);
15288
15391
  if (range.isSingleLine) {
15289
15392
  this.drawSingleLineMarker(range, this.className);
15290
15393
  }
@@ -15515,7 +15618,8 @@ class Renderer extends EventEmitting {
15515
15618
  const { left, top } = rect ?? this.container.getBoundingClientRect();
15516
15619
  const pageX = x - left;
15517
15620
  const pageY = y + this.session.scrollTop - top;
15518
- const { paragraph, indexInParagraph } = PositionHelper.pixelToParagraph(this.session, pageX, pageY, tokenDivider);
15621
+ const { paragraph, paragraphLine } = PositionHelper.pixelToParagraphLine(this.session.displayData.paragraphs, pageY);
15622
+ const indexInParagraph = PositionHelper.pixelToIndexInParagraph(this.session, pageX, paragraph, paragraphLine, tokenDivider);
15519
15623
  return new CursorParagraph(paragraph, indexInParagraph);
15520
15624
  }
15521
15625
  showCursor() {