@talrace/ngx-noder 19.0.41 → 19.0.43

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
+ }
6426
6399
  }
6427
- return indexInLine;
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++;
6411
+ }
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) {
@@ -7125,13 +7162,11 @@ class ParagraphHelper {
7125
7162
  visibleScreenIndex: offsetTop > 0 ? screenIndex + direction : screenIndex
7126
7163
  };
7127
7164
  }
7128
- static getParagraphPages(paragraphTextLinesInfo) {
7165
+ static getParagraphPages(lines) {
7129
7166
  const resultPages = [];
7130
- paragraphTextLinesInfo.forEach(x => {
7131
- if (!resultPages.includes(x.page)) {
7132
- resultPages.push(x.page);
7133
- }
7134
- });
7167
+ for (let i = lines[0].page; i <= lines[lines.length - 1].page; i++) {
7168
+ resultPages.push(i);
7169
+ }
7135
7170
  return resultPages;
7136
7171
  }
7137
7172
  static getParagraphHeight(paragraphTextLinesInfo) {
@@ -7435,9 +7470,9 @@ class Range {
7435
7470
  const compare = this.compareSingleLine(position);
7436
7471
  return compare ?? this.compareMultiLine(position);
7437
7472
  }
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);
7473
+ paragraphToDocumentLine(paragraphs) {
7474
+ const screenPosStart = PositionHelper.paragraphToDocumentLine(paragraphs[this.start.row], this.start.column);
7475
+ const screenPosEnd = PositionHelper.paragraphToDocumentLine(paragraphs[this.end.row], this.end.column);
7441
7476
  return new Range(screenPosStart, screenPosEnd);
7442
7477
  }
7443
7478
  /**
@@ -8302,12 +8337,12 @@ class Selection {
8302
8337
  this.anchor = null;
8303
8338
  }
8304
8339
  selectRight(session) {
8305
- const position = this.getCursorRight(session);
8340
+ const position = this.getRight(session.displayData.paragraphs, this.cursor.row, this.cursor.column);
8306
8341
  this.moveSelection(position);
8307
8342
  }
8308
8343
  navigateRight(session) {
8309
8344
  if (this.isEmpty) {
8310
- const position = this.getCursorRight(session);
8345
+ const position = this.getRight(session.displayData.paragraphs, this.cursor.row, this.cursor.column);
8311
8346
  this.placeCursor(position);
8312
8347
  }
8313
8348
  else {
@@ -8316,12 +8351,12 @@ class Selection {
8316
8351
  }
8317
8352
  }
8318
8353
  selectLeft(session) {
8319
- const position = this.getCursorLeft(session);
8354
+ const position = this.getLeft(session.displayData.paragraphs, this.cursor.row, this.cursor.column);
8320
8355
  this.moveSelection(position);
8321
8356
  }
8322
8357
  navigateLeft(session) {
8323
8358
  if (this.isEmpty) {
8324
- const position = this.getCursorLeft(session);
8359
+ const position = this.getLeft(session.displayData.paragraphs, this.cursor.row, this.cursor.column);
8325
8360
  this.placeCursor(position);
8326
8361
  }
8327
8362
  else {
@@ -8347,12 +8382,12 @@ class Selection {
8347
8382
  }
8348
8383
  selectFileEnd(session) {
8349
8384
  const paragraph = session.displayData.paragraphs.length - 1;
8350
- const paragraphIndex = session.displayData.getParagraphContent(paragraph).length;
8385
+ const paragraphIndex = session.displayData.paragraphs[paragraph].content.length;
8351
8386
  this.moveSelection(new CursorParagraph(paragraph, paragraphIndex));
8352
8387
  }
8353
8388
  navigateFileEnd(session) {
8354
8389
  const paragraph = session.displayData.paragraphs.length - 1;
8355
- const paragraphIndex = session.displayData.getParagraphContent(paragraph).length;
8390
+ const paragraphIndex = session.displayData.paragraphs[paragraph].content.length;
8356
8391
  this.placeCursor(new CursorParagraph(paragraph, paragraphIndex));
8357
8392
  }
8358
8393
  selectFileStart() {
@@ -8378,73 +8413,80 @@ class Selection {
8378
8413
  this.placeCursor(position);
8379
8414
  }
8380
8415
  moveCursorUp(session, position) {
8381
- const line = PositionHelper.paragraphToDocumentLine(session, position.row, position.column);
8416
+ const paragraphs = session.displayData.paragraphs;
8417
+ const line = PositionHelper.paragraphToDocumentLine(paragraphs[position.row], position.column);
8382
8418
  if (line.row === 0) {
8383
8419
  this.selectLineStart(session);
8420
+ return;
8421
+ }
8422
+ const moved = this.moveToLine(session, line.row - 1, line);
8423
+ if (moved.paragraph !== position.row || moved.indexInParagraph !== position.column) {
8424
+ this.cursor = new CursorParagraph(moved.paragraph, moved.indexInParagraph);
8384
8425
  }
8385
8426
  else {
8386
- this.moveToLine(session, line.row - 1, line);
8427
+ this.cursor = this.getLeft(paragraphs, moved.paragraph, moved.indexInParagraph);
8387
8428
  }
8388
8429
  }
8389
8430
  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) {
8431
+ const paragraphs = session.displayData.paragraphs;
8432
+ const line = PositionHelper.paragraphToDocumentLine(paragraphs[position.row], position.column);
8433
+ const lastParagraphLines = paragraphs[paragraphs.length - 1].paragraphSettings.textLinesInfo;
8434
+ const lastDocumentLine = lastParagraphLines[lastParagraphLines.length - 1].screenLine;
8435
+ if (line.row === lastDocumentLine) {
8395
8436
  this.selectLineEnd(session);
8437
+ return;
8438
+ }
8439
+ const moved = this.moveToLine(session, line.row + 1, line);
8440
+ if (moved.paragraph !== position.row || moved.indexInParagraph !== position.column) {
8441
+ this.cursor = new CursorParagraph(moved.paragraph, moved.indexInParagraph);
8396
8442
  }
8397
8443
  else {
8398
- this.moveToLine(session, line.row + 1, line);
8444
+ this.cursor = this.getRight(paragraphs, moved.paragraph, moved.indexInParagraph);
8399
8445
  }
8400
8446
  }
8401
8447
  moveToLine(session, line, fromLine) {
8402
8448
  if (!this.keepLinePositionX) {
8403
8449
  this.keepLinePositionX = PositionHelper.documentLineToPixel(session, fromLine.row, fromLine.column).pageX;
8404
8450
  }
8405
- const indexInLine = PositionHelper.pixelToIndexInLine(session, line, this.keepLinePositionX, 2);
8406
- this.cursor = PositionHelper.documentLineToParagraph(session, line, indexInLine);
8407
- this.overlayService.close();
8451
+ const { paragraph, paragraphLine } = PositionHelper.documentLineToParagraphLine(session.displayData.paragraphs, line);
8452
+ const indexInParagraph = PositionHelper.pixelToIndexInParagraph(session, this.keepLinePositionX, paragraph, paragraphLine, 2);
8453
+ return { paragraph, indexInParagraph };
8408
8454
  }
8409
- getCursorLeft(session) {
8410
- if (this.cursor.row === 0 && this.cursor.column === 0) {
8411
- return this.cursor;
8455
+ getLeft(paragraphs, paragraph, indexInParagraph) {
8456
+ if (paragraph === 0) {
8457
+ indexInParagraph -= indexInParagraph > 0 ? 1 : 0;
8458
+ return new CursorParagraph(paragraph, indexInParagraph);
8412
8459
  }
8413
- const index = ContentHelper.paragraphPositionToDocumentIndex(session.displayData.paragraphs, this.cursor);
8414
- return ContentHelper.documentIndexToParagraphIndex(session.displayData.paragraphs, index - 1);
8460
+ indexInParagraph--;
8461
+ if (indexInParagraph >= 0) {
8462
+ return new CursorParagraph(paragraph, indexInParagraph);
8463
+ }
8464
+ return new CursorParagraph(paragraph - 1, paragraphs[paragraph].startIndex - paragraphs[paragraph - 1].startIndex - 1);
8415
8465
  }
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;
8466
+ getRight(paragraphs, paragraph, indexInParagraph) {
8467
+ if (paragraph === paragraphs.length - 1) {
8468
+ indexInParagraph += indexInParagraph < paragraphs[paragraphs.length - 1].content.length ? 1 : 0;
8469
+ return new CursorParagraph(paragraph, indexInParagraph);
8470
+ }
8471
+ indexInParagraph++;
8472
+ if (paragraphs[paragraph + 1].startIndex === paragraphs[paragraph].startIndex + indexInParagraph) {
8473
+ return new CursorParagraph(paragraph + 1, 0);
8420
8474
  }
8421
- const index = ContentHelper.paragraphPositionToDocumentIndex(session.displayData.paragraphs, this.cursor);
8422
- return ContentHelper.documentIndexToParagraphIndex(session.displayData.paragraphs, index + 1);
8475
+ return new CursorParagraph(paragraph, indexInParagraph);
8423
8476
  }
8424
8477
  getLineStart(session, position) {
8425
- const line = PositionHelper.paragraphToDocumentLine(session, position.row, position.column);
8478
+ const line = PositionHelper.paragraphToDocumentLine(session.displayData.paragraphs[position.row], position.column);
8426
8479
  return PositionHelper.documentLineToParagraph(session, line.row, 0);
8427
8480
  }
8428
8481
  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];
8482
+ const paragraph = session.displayData.paragraphs[position.row];
8483
+ const documentLine = PositionHelper.paragraphToDocumentLine(paragraph, position.column);
8484
+ if (documentLine.row - paragraph.lineNumber === paragraph.paragraphSettings.textLinesInfo.length - 1) {
8485
+ return new CursorParagraph(position.row, paragraph.content.length);
8440
8486
  }
8441
- else if (paragraphLine === linesCount - 1) {
8442
- index = paragraphLength - nextLineIndexes[paragraphLine - 1];
8443
- }
8444
- else {
8445
- index = nextLineIndexes[paragraphLine] - nextLineIndexes[paragraphLine - 1];
8446
- }
8447
- return PositionHelper.documentLineToParagraph(session, line.row, index);
8487
+ const paragraphLine = paragraph.paragraphSettings.textLinesInfo[documentLine.row - paragraph.lineNumber];
8488
+ const endOfLineIndex = paragraphLine.endIndex - paragraphLine.startIndex + 1;
8489
+ return PositionHelper.documentLineToParagraph(session, documentLine.row, endOfLineIndex);
8448
8490
  }
8449
8491
  getWordRight(session, position) {
8450
8492
  let row = position.row;
@@ -8640,7 +8682,7 @@ class Editor {
8640
8682
  get grammarChecker() {
8641
8683
  return this.regulatorService.grammarChecker;
8642
8684
  }
8643
- constructor(model, container, editorService, overlayService, regulatorService, commandsService, clipboard, externalElementTagNames, insertOverlays, customPageWidth) {
8685
+ constructor(model, container, editorService, overlayService, regulatorService, commandsService, clipboard, externalElementTags, insertOverlays, customPageWidth) {
8644
8686
  this.model = model;
8645
8687
  this.container = container;
8646
8688
  this.editorService = editorService;
@@ -8648,14 +8690,9 @@ class Editor {
8648
8690
  this.regulatorService = regulatorService;
8649
8691
  this.commandsService = commandsService;
8650
8692
  this.clipboard = clipboard;
8651
- this.externalElementTagNames = externalElementTagNames;
8693
+ this.externalElementTags = externalElementTags;
8652
8694
  this.insertOverlays = insertOverlays;
8653
8695
  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
8696
  this.subscriptions = [];
8660
8697
  this.commentCreateRequests = [];
8661
8698
  this.emojiRegex = /\p{Extended_Pictographic}(?:\p{Emoji_Modifier}|\u{200D}\p{Extended_Pictographic})*/gu;
@@ -8670,7 +8707,7 @@ class Editor {
8670
8707
  this.renderer.updateCursor();
8671
8708
  };
8672
8709
  this.subscriptions.push(this.receiveTextStyleSubscription());
8673
- this.customElementTagNames = [...this.externalElementTagNames, this.imageTagName, this.tableCellTagName, this.edgeElementTagName];
8710
+ this.customElementTags = [...this.externalElementTags, IMAGE_TAG, TABLE_CELL_TAG, EDGE_TAG, CUSTOM_TAG];
8674
8711
  this.history = new OperationHistory(editorService, regulatorService);
8675
8712
  this.selection = new Selection(this.overlayService);
8676
8713
  this.regulatorService.setSelection(this.selection);
@@ -9758,7 +9795,7 @@ class Editor {
9758
9795
  }
9759
9796
  onMouseClick(event) {
9760
9797
  const customElement = this.setCurrentSession(event.target);
9761
- if (customElement && customElement.tagName !== this.tableCellTagName && customElement.tagName !== this.edgeElementTagName) {
9798
+ if (customElement && customElement.tagName !== TABLE_CELL_TAG && customElement.tagName !== EDGE_TAG) {
9762
9799
  this.focusCustomComponent(customElement);
9763
9800
  }
9764
9801
  else {
@@ -9789,7 +9826,7 @@ class Editor {
9789
9826
  }
9790
9827
  onShortLeftClick(event, isSelectionClick = false) {
9791
9828
  const customElement = this.setCurrentSession(event.target);
9792
- if (customElement && customElement.tagName !== this.tableCellTagName && customElement.tagName !== this.edgeElementTagName) {
9829
+ if (customElement && customElement.tagName !== TABLE_CELL_TAG && customElement.tagName !== EDGE_TAG) {
9793
9830
  this.focusCustomComponent(customElement);
9794
9831
  return;
9795
9832
  }
@@ -9842,7 +9879,7 @@ class Editor {
9842
9879
  this.regulatorService.setMainSessionAsCurrent();
9843
9880
  }
9844
9881
  }
9845
- if (customElement && customElement.tagName !== this.tableCellTagName && customElement.tagName !== this.edgeElementTagName) {
9882
+ if (customElement && customElement.tagName !== TABLE_CELL_TAG && customElement.tagName !== EDGE_TAG) {
9846
9883
  this.focusCustomComponent(customElement);
9847
9884
  return;
9848
9885
  }
@@ -9860,7 +9897,7 @@ class Editor {
9860
9897
  }
9861
9898
  onTripleClick(event) {
9862
9899
  const customElement = this.setCurrentSession(event.target);
9863
- if (customElement && customElement.tagName !== this.tableCellTagName && customElement.tagName !== this.edgeElementTagName) {
9900
+ if (customElement && customElement.tagName !== TABLE_CELL_TAG && customElement.tagName !== EDGE_TAG) {
9864
9901
  this.focusCustomComponent(customElement);
9865
9902
  return;
9866
9903
  }
@@ -9874,7 +9911,7 @@ class Editor {
9874
9911
  }
9875
9912
  onQuadClick(event) {
9876
9913
  const customElement = this.setCurrentSession(event.target);
9877
- if (customElement && customElement.tagName !== this.tableCellTagName && customElement.tagName !== this.edgeElementTagName) {
9914
+ if (customElement && customElement.tagName !== TABLE_CELL_TAG && customElement.tagName !== EDGE_TAG) {
9878
9915
  this.focusCustomComponent(customElement);
9879
9916
  return;
9880
9917
  }
@@ -9984,17 +10021,17 @@ class Editor {
9984
10021
  const isEdgeEdit = this.mainSession.customComponents.edges.isEdit;
9985
10022
  if (!customElement || (!isEdgeEdit && isInsideEdge)) {
9986
10023
  this.regulatorService.setMainSessionAsCurrent();
9987
- return this.customElementTagNames.includes(customElement?.tagName) ? customElement : null;
10024
+ return this.customElementTags.includes(customElement?.tagName) ? customElement : null;
9988
10025
  }
9989
10026
  const elementSessionId = +customElement.attributes.getNamedItem('data-session-id').value;
9990
10027
  this.regulatorService.setCustomSessionAsCurrent(elementSessionId);
9991
- return customElement.tagName !== this.edgeElementTagName ? customElement : null;
10028
+ return customElement.tagName !== EDGE_TAG ? customElement : null;
9992
10029
  }
9993
10030
  getCustomElement(element) {
9994
- if (!element || element.tagName === this.parentTagName) {
10031
+ if (!element || element.tagName === PARENT_TAG) {
9995
10032
  return null;
9996
10033
  }
9997
- else if (this.customElementTagNames.includes(element.tagName)) {
10034
+ else if (this.customElementTags.includes(element.tagName) || element.classList.contains(CUSTOM_TAG)) {
9998
10035
  return element;
9999
10036
  }
10000
10037
  else {
@@ -10005,10 +10042,10 @@ class Editor {
10005
10042
  return !!this.getParentEdge(element);
10006
10043
  }
10007
10044
  getParentEdge(element) {
10008
- if (!element || element.tagName === this.parentTagName) {
10045
+ if (!element || element.tagName === PARENT_TAG) {
10009
10046
  return null;
10010
10047
  }
10011
- else if (element.tagName === this.edgeElementTagName) {
10048
+ else if (element.tagName === EDGE_TAG) {
10012
10049
  return element;
10013
10050
  }
10014
10051
  else {
@@ -10084,7 +10121,7 @@ class Editor {
10084
10121
  return;
10085
10122
  }
10086
10123
  const customElement = this.container.nativeElement.querySelector(`[data-session-id="${this.session.sessionId}"]`);
10087
- if (customElement.tagName === this.tableCellTagName) {
10124
+ if (customElement.tagName === TABLE_CELL_TAG) {
10088
10125
  const tableSession = this.regulatorService.getSession(this.regulatorService.currentSession.parentSessionId);
10089
10126
  const table = tableSession.customComponents.tables.find(x => x.instance.sessionId === this.regulatorService.currentSession.parentSessionId);
10090
10127
  table.instance.tableSelection.clearSelection();
@@ -10900,7 +10937,7 @@ class DisplayToken {
10900
10937
  get isWhiteSpace() {
10901
10938
  return this.isSpace || this.isParagraph;
10902
10939
  }
10903
- get breaksLine() {
10940
+ get isBreak() {
10904
10941
  return this.isPageBreak || this.isLineBreak;
10905
10942
  }
10906
10943
  get breakable() {
@@ -12173,13 +12210,66 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.5", ngImpor
12173
12210
  }], ctorParameters: () => [{ type: ComponentService }, { type: i0.ElementRef }, { type: OverlayService }, { type: RegulatorService }] });
12174
12211
 
12175
12212
  class DisplayTokenHelper {
12176
- static getDisplayValue(charCode, breakType) {
12213
+ static getParagraphToken(paragraphSymbolStyle, index) {
12214
+ const size = FontMetrics.measureCharSize('0', ContentStyleHelper.getFontStylesString(paragraphSymbolStyle));
12215
+ return new DisplayToken({ ...size, displayValue: DisplayValue.paragraph, index });
12216
+ }
12217
+ static getBreakToken(symbol, fontString, breakType, index) {
12218
+ return new DisplayToken({
12219
+ ...FontMetrics.measureCharSize(symbol, fontString),
12220
+ displayValue: this.getBreakDisplayValue(breakType),
12221
+ index
12222
+ });
12223
+ }
12224
+ static getSymbolToken(symbol, fontString, index) {
12225
+ const result = new DisplayToken({
12226
+ ...FontMetrics.measureCharSize(symbol, fontString),
12227
+ displayValue: this.getSymbolDisplayValue(symbol),
12228
+ index
12229
+ });
12230
+ if (result.isSpace) {
12231
+ result.ascent = 0;
12232
+ result.descent = 0;
12233
+ result.height = 0;
12234
+ }
12235
+ return result;
12236
+ }
12237
+ static getComponentTokens(component, fontString, index) {
12238
+ if (component.instance instanceof ExternalComponent && component.instance.isText) {
12239
+ const result = [];
12240
+ let text = component.instance.getText();
12241
+ text = !text.length ? ' ' : text;
12242
+ for (let i = 0; i < text.length; i++) {
12243
+ result.push(this.getSymbolToken(text[i], fontString, index));
12244
+ result[i].customIndex = i;
12245
+ }
12246
+ return result.length ? result : [this.getSymbolToken(' ', fontString, index)];
12247
+ }
12248
+ const ascent = component.instance.ascent() ?? 0;
12249
+ const descent = component.instance.descent() ?? 0;
12250
+ return [
12251
+ new DisplayToken({
12252
+ width: component.instance.width(),
12253
+ height: ascent + descent,
12254
+ font: FontMetrics.measureCharSize('0', fontString).font,
12255
+ ascent,
12256
+ descent,
12257
+ displayValue: this.getComponentDisplayValue(component.instance),
12258
+ index
12259
+ })
12260
+ ];
12261
+ }
12262
+ static getBreakDisplayValue(breakType) {
12177
12263
  if (breakType === BreakTypes.Page) {
12178
12264
  return DisplayValue.pageBreak;
12179
12265
  }
12180
12266
  if (breakType === BreakTypes.TextWrapping) {
12181
12267
  return DisplayValue.lineBreak;
12182
12268
  }
12269
+ return DisplayValue.char;
12270
+ }
12271
+ static getSymbolDisplayValue(symbol) {
12272
+ const charCode = symbol.charCodeAt(0);
12183
12273
  if (charCode === 32) {
12184
12274
  return DisplayValue.space;
12185
12275
  }
@@ -12191,32 +12281,14 @@ class DisplayTokenHelper {
12191
12281
  }
12192
12282
  return DisplayValue.char;
12193
12283
  }
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;
12284
+ static getComponentDisplayValue(instance) {
12285
+ if (instance instanceof NoderTabComponent) {
12286
+ return DisplayValue.tab;
12204
12287
  }
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
- });
12288
+ if (instance instanceof NoderTableComponent) {
12289
+ return DisplayValue.table;
12290
+ }
12291
+ return DisplayValue.customContent;
12220
12292
  }
12221
12293
  }
12222
12294
 
@@ -12240,72 +12312,26 @@ class LineInfoModel {
12240
12312
  }
12241
12313
 
12242
12314
  class LineInfoHelper {
12243
- static get(tokens, isAfterPageBreak, isLastLine, style, indent, isNumbering, width, defaultHeight, defaultAscent) {
12315
+ static get(tokens, style, indent, width, paragraphStartIndex, position) {
12244
12316
  const result = new LineInfoModel({
12245
- isAfterPageBreak,
12246
- isEndedByPageBreak: tokens[tokens.length - 1].isPageBreak,
12317
+ isAfterPageBreak: position.isAfterPageBreak,
12318
+ isEndedByPageBreak: tokens[tokens.length - 1].isPageBreak || (tokens.length > 1 && tokens[tokens.length - 2].isPageBreak),
12247
12319
  backgroundColor: style.backgroundColor,
12248
12320
  align: style.alignment ?? DEFAULT_PARAGRAPH_STYLE.alignment,
12249
12321
  indent,
12250
12322
  offsetBefore: DEFAULT_PARAGRAPH_STYLE.spaceBefore,
12251
12323
  lineSpacing: style.lineSpacing ?? DEFAULT_PARAGRAPH_STYLE.lineSpacing,
12252
- isNumbering,
12324
+ startIndex: tokens[0].index - paragraphStartIndex,
12325
+ endIndex: tokens[tokens.length - 1].index - paragraphStartIndex,
12326
+ isNumbering: position.isNumbering,
12253
12327
  hasTable: false,
12254
12328
  width: 0
12255
12329
  });
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
- }
12330
+ this.applySizeToLine(result, tokens);
12331
+ if (style.alignment === Alignment$1.justify && !position.isLastLine) {
12332
+ this.applyWordSpacingToLine(result, tokens, indent, width, paragraphStartIndex);
12308
12333
  }
12334
+ this.applyCustomTextsToLine(result, tokens, paragraphStartIndex);
12309
12335
  return result;
12310
12336
  }
12311
12337
  static getFirstLineIndent(model, paragraphIndex, generalProperties) {
@@ -12323,6 +12349,86 @@ class LineInfoHelper {
12323
12349
  ? paragraph.paragraphStyle.indentLeft
12324
12350
  : levelsModel[paragraphStyle.numberingLevel].indentLeft, paragraph.paragraphStyle.indentRight ?? DEFAULT_PARAGRAPH_STYLE.indentRight, markerWidth + markerWidth / marker.length);
12325
12351
  }
12352
+ static applySizeToLine(line, tokens) {
12353
+ const lastToken = tokens[tokens.length - 1];
12354
+ let maxAscent = 0;
12355
+ let maxDescent = 0;
12356
+ let i = 0;
12357
+ const length = lastToken.isParagraph && tokens.length > 1 ? tokens.length - 1 : tokens.length;
12358
+ do {
12359
+ if (maxAscent < tokens[i].ascent) {
12360
+ maxAscent = tokens[i].ascent;
12361
+ }
12362
+ if (maxDescent < tokens[i].descent) {
12363
+ maxDescent = tokens[i].descent;
12364
+ }
12365
+ line.width += tokens[i].width;
12366
+ i++;
12367
+ } while (i < length);
12368
+ line.height = maxAscent + maxDescent;
12369
+ line.ascent = maxAscent;
12370
+ if (line.height === 0) {
12371
+ line.height = lastToken.ascent + lastToken.descent;
12372
+ line.ascent = lastToken.ascent;
12373
+ }
12374
+ line.offsetAfter = line.height * (line.lineSpacing - 1);
12375
+ }
12376
+ static applyWordSpacingToLine(line, tokens, indent, width, paragraphStartIndex) {
12377
+ const lastToken = tokens[tokens.length - 1].isParagraph ? tokens.length - 2 : tokens.length - 1;
12378
+ let right = lastToken;
12379
+ let adjustableWidth = line.width;
12380
+ while (right > 0 && tokens[right].isSpace) {
12381
+ adjustableWidth -= tokens[right].width;
12382
+ right--;
12383
+ }
12384
+ let left = 0;
12385
+ while (left < lastToken && tokens[left].isSpace) {
12386
+ left++;
12387
+ }
12388
+ let spaces = 0;
12389
+ for (let i = right; i > left; i--) {
12390
+ if (tokens[i].isTab) {
12391
+ left = i;
12392
+ }
12393
+ if (tokens[i].isSpace) {
12394
+ spaces++;
12395
+ }
12396
+ }
12397
+ const indentWidth = (indent.left ?? 0) + (indent.right ?? 0) + (indent.firstLine ?? 0) - (indent.hanging ?? 0);
12398
+ const availableWidth = width - indentWidth - indent.markerWidth; // todo: use NumberingHelper.getOffsetCausedByMarker
12399
+ const whitespaceDeficit = availableWidth - adjustableWidth;
12400
+ if (spaces > 0 && whitespaceDeficit > 0) {
12401
+ line.wordSpacing = whitespaceDeficit / spaces;
12402
+ line.width = availableWidth;
12403
+ line.wordSpacingStartToken = left;
12404
+ line.wordSpacingEndToken = right;
12405
+ line.wordSpacingStartIndex = tokens[left].index - paragraphStartIndex;
12406
+ line.wordSpacingEndIndex = tokens[right].index - paragraphStartIndex;
12407
+ for (let i = right; i > left; i--) {
12408
+ if (tokens[i].isSpace) {
12409
+ tokens[i].width += line.wordSpacing;
12410
+ }
12411
+ }
12412
+ }
12413
+ }
12414
+ static applyCustomTextsToLine(line, tokens, paragraphStartIndex) {
12415
+ for (const token of tokens) {
12416
+ if (token.customIndex >= 0) {
12417
+ const indexInParagraph = token.index - paragraphStartIndex;
12418
+ if (line.customTexts && line.customTexts[line.customTexts.length - 1].index === indexInParagraph) {
12419
+ line.customTexts[line.customTexts.length - 1].end++;
12420
+ }
12421
+ else {
12422
+ line.customTexts ??= [];
12423
+ line.customTexts.push({
12424
+ index: indexInParagraph,
12425
+ start: token.customIndex,
12426
+ end: token.customIndex + 1
12427
+ });
12428
+ }
12429
+ }
12430
+ }
12431
+ }
12326
12432
  }
12327
12433
 
12328
12434
  class PageVerticalDataModel {
@@ -12809,13 +12915,13 @@ class DisplayData extends EventEmitting {
12809
12915
  this.removeAllListeners('pagesCountChanged');
12810
12916
  }
12811
12917
  updateParagraphLineNumber(first) {
12812
- const count = this.paragraphs.length;
12813
12918
  if (first === 0) {
12814
12919
  this.paragraphs[first].lineNumber = 0;
12815
12920
  first++;
12816
12921
  }
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;
12922
+ for (let i = first; i < this.paragraphs.length; i++) {
12923
+ this.paragraphs[i].lineNumber =
12924
+ this.paragraphs[i - 1].lineNumber + this.paragraphs[i - 1].paragraphSettings.textLinesInfo.length;
12819
12925
  }
12820
12926
  }
12821
12927
  updateParagraphStartIndex(first) {
@@ -12863,8 +12969,7 @@ class DisplayData extends EventEmitting {
12863
12969
  NumberingHelper.setNumberingNeedToRecalculate(this.generalProperties.numberingInfo, numberingId);
12864
12970
  }
12865
12971
  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;
12972
+ const rowInfos = this.splitParagraphByLines(i);
12868
12973
  if (indexOfParagraphAfterPageBreak === i) {
12869
12974
  rowInfos[0].isAfterPageBreak = true;
12870
12975
  }
@@ -12912,29 +13017,29 @@ class DisplayData extends EventEmitting {
12912
13017
  }
12913
13018
  splitParagraphByLines(paragraphIndex) {
12914
13019
  const paragraph = this.paragraphs[paragraphIndex];
12915
- const { paragraphTokens, paragraphToken } = this.getParagraphTokens(paragraph);
12916
- const splits = [];
13020
+ const isLastParagraph = paragraphIndex === this.paragraphs.length - 1;
13021
+ const paragraphSymbolIndex = paragraph.startIndex + paragraph.content.length;
13022
+ const paragraphTokens = this.getTokens(paragraph.startIndex, paragraph.content, paragraphSymbolIndex);
12917
13023
  const rowInfos = [];
12918
13024
  const style = this.model.paragraphs[paragraphIndex].paragraphStyle;
12919
13025
  const pageFormat = this.getPageFormatAtPosition(paragraph.startIndex);
12920
- const defaultHeight = paragraphToken.height;
12921
- const defaultAscent = paragraphToken.ascent;
12922
13026
  let index = 0;
12923
13027
  let indent = LineInfoHelper.getFirstLineIndent(this.model, paragraphIndex, this.generalProperties);
12924
13028
  do {
12925
13029
  let tokens = paragraphTokens.slice(index);
12926
13030
  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 ?? []);
13031
+ const startWidth = indent.left + indent.firstLine - indent.hanging || 0;
13032
+ const last = this.computeWrapToken(tokens, startWidth, maxWidth, style.tabSettings ?? [], isLastParagraph);
12929
13033
  tokens = tokens.slice(0, last + 1);
12930
13034
  const width = pageFormat.contentWidth;
12931
13035
  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);
13036
+ const isAfterPageBreak = !rowInfos.length ? false : rowInfos[rowInfos.length - 1].isEndedByPageBreak;
13037
+ const isLastLine = index + last + 1 === paragraphTokens.length;
13038
+ const position = { isLastLine, isNumbering, isAfterPageBreak };
13039
+ const info = LineInfoHelper.get(tokens, style, indent, width, paragraph.startIndex, position);
12935
13040
  for (let i = 0; i < tokens.length; i++) {
12936
13041
  if (tokens[i].isTab) {
12937
- const tab = this.customComponents.tabs.find(x => x.instance.insertIndex === paragraph.startIndex + index + i);
13042
+ const tab = this.customComponents.tabs.find(x => x.instance.insertIndex === tokens[i].index);
12938
13043
  tab.instance.applySize(tokens[i].width);
12939
13044
  }
12940
13045
  else if (tokens[i].isTable) {
@@ -12944,61 +13049,57 @@ class DisplayData extends EventEmitting {
12944
13049
  rowInfos.push(info);
12945
13050
  index += last + 1;
12946
13051
  if (index < paragraphTokens.length) {
12947
- splits.push(index);
12948
13052
  indent = new IndentModel(null, null, indent.left, indent.right, 0);
12949
13053
  }
12950
13054
  } while (index < paragraphTokens.length);
12951
13055
  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 };
13056
+ return rowInfos;
12958
13057
  }
12959
13058
  getParagraphLineTokens(paragraphIndex, paragraphLine) {
12960
13059
  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);
13060
+ const isLastParagraph = paragraphIndex === this.paragraphs.length - 1;
13061
+ const line = paragraph.paragraphSettings.textLinesInfo[paragraphLine];
13062
+ const lineContent = paragraph.content.substring(line.startIndex, line.endIndex + 1);
12964
13063
  const paragraphSymbolIndex = paragraph.paragraphSettings.startInsertIndex + paragraph.content.length;
12965
- const { tokens } = this.getTokens(lineStart + paragraph.startIndex, lineContent, paragraphSymbolIndex);
13064
+ const tokens = this.getTokens(line.startIndex + paragraph.startIndex, lineContent, paragraphSymbolIndex);
13065
+ if (line.customTexts && line.customTexts[0].index === line.startIndex) {
13066
+ tokens.splice(0, line.customTexts[0].start); // cut additional tokens in case when line starts from the middle of the textual custom component
13067
+ }
12966
13068
  const pageFormat = this.getPageFormatAtPosition(this.paragraphs[paragraphIndex].startIndex);
12967
13069
  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
13070
+ const maxWidth = pageFormat.contentWidth - line.indent.right - line.indent.markerWidth;
13071
+ const startWidth = line.indentLeft + line.indentFirstLine - line.indent.hanging || 0;
13072
+ const last = this.computeWrapToken(tokens, startWidth, maxWidth, paragraphStyle.tabSettings ?? [], isLastParagraph); // tab width correction for tokens according to the tabs complex positioning
13073
+ tokens.splice(last + 1); // cut additional tokens in case when line ends in the middle of the textual custom component
13074
+ const isLastLine = paragraphLine === paragraph.paragraphSettings.textLinesInfo.length - 1;
13075
+ const position = { isLastLine, isNumbering: line.isNumbering, isAfterPageBreak: false };
13076
+ 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
13077
  return tokens;
12975
13078
  }
12976
13079
  getTokens(contentIndex, content, paragraphSymbolIndex) {
12977
13080
  const tokens = [];
12978
- const prev = { char: '', style: null, size: null };
12979
13081
  let format = FormatStyleHelper.getFormatAtIndex(this.model.formats, contentIndex);
12980
13082
  let fontString = ContentStyleHelper.getFontStylesString(format.textStyle);
12981
13083
  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
13084
  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);
13085
+ const customComponent = breakType === null ? this.getOrGenerateComponent(contentIndex, content[i]) : null;
13086
+ let newTokens = breakType !== null ? [DisplayTokenHelper.getBreakToken(content[i], fontString, breakType, contentIndex)] : null;
13087
+ newTokens ??= customComponent
13088
+ ? DisplayTokenHelper.getComponentTokens(customComponent, fontString, contentIndex)
13089
+ : [DisplayTokenHelper.getSymbolToken(content[i], fontString, contentIndex)];
12992
13090
  contentIndex++;
12993
13091
  if (contentIndex > format.endIndex) {
12994
13092
  format = FormatStyleHelper.getFormatAtIndex(this.model.formats, contentIndex);
12995
13093
  fontString = ContentStyleHelper.getFontStylesString(format.textStyle);
12996
13094
  }
12997
- tokens.push(token);
13095
+ tokens.push(...newTokens);
12998
13096
  }
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 };
13097
+ if (contentIndex === paragraphSymbolIndex) {
13098
+ const paragraphFormat = FormatStyleHelper.getFormatAtIndex(this.model.formats, contentIndex);
13099
+ const paragraphToken = DisplayTokenHelper.getParagraphToken(paragraphFormat.textStyle, contentIndex);
13100
+ tokens.push(paragraphToken);
13101
+ }
13102
+ return tokens;
13002
13103
  }
13003
13104
  getOrGenerateComponent(charIndex, char) {
13004
13105
  if (!this.customContentService.isSpecialMarker(char)) {
@@ -13006,9 +13107,6 @@ class DisplayData extends EventEmitting {
13006
13107
  }
13007
13108
  const existingComponent = this.customContentService.getComponent(this.customComponents, char, charIndex);
13008
13109
  if (existingComponent) {
13009
- if (existingComponent.instance instanceof NoderTableComponent) {
13010
- existingComponent.instance.updateCells();
13011
- }
13012
13110
  return existingComponent;
13013
13111
  }
13014
13112
  const pageFormat = this.getPageFormatAtPosition(charIndex);
@@ -13044,16 +13142,19 @@ class DisplayData extends EventEmitting {
13044
13142
  }
13045
13143
  return -1;
13046
13144
  }
13047
- // The index of a token which should be the last on the line
13048
- computeWrapIndex(displayTokens, startWidth, maxWidth, tabSettings) {
13145
+ // Compute token which should be the last on the line
13146
+ computeWrapToken(displayTokens, startWidth, maxWidth, tabSettings, isLastParagraph) {
13049
13147
  let width = startWidth;
13050
13148
  let lastBreakable = -1;
13051
13149
  const lastTab = { token: null, alignment: TabAlignment.Left, usedWidth: 0, tokenWidth: 0 };
13052
13150
  for (let i = 0; i < displayTokens.length; i++) {
13053
13151
  const token = displayTokens[i];
13054
- if (token.breaksLine) {
13152
+ if (token.isParagraph) {
13055
13153
  return i;
13056
13154
  }
13155
+ if (token.isBreak) {
13156
+ return i + 1 < displayTokens.length && displayTokens[i + 1].isParagraph && !isLastParagraph ? i + 1 : i;
13157
+ }
13057
13158
  if (token.isTable) {
13058
13159
  return i > 0 ? i - 1 : 0;
13059
13160
  }
@@ -13202,7 +13303,7 @@ class DisplayData extends EventEmitting {
13202
13303
  const right = this.paragraphs[position.row].content.slice(position.column);
13203
13304
  const originalParagraphId = this.paragraphs[position.row].id;
13204
13305
  const insertParagraphs = this.splitByParagraphs(`${left}${text}${right}`).map((x, i) => {
13205
- const newParagraph = new ParagraphInfoModel({ content: x, nextLineIndexes: [] });
13306
+ const newParagraph = new ParagraphInfoModel({ content: x });
13206
13307
  if (i === 0) {
13207
13308
  newParagraph.id = originalParagraphId;
13208
13309
  }
@@ -14826,9 +14927,9 @@ class HighlightLayer {
14826
14927
  }
14827
14928
  drawCustomElementHighlight(elementInfo, cssClass, screenParentRange) {
14828
14929
  const paragraphPos = elementInfo.parentRange.start;
14829
- const documentLine = PositionHelper.paragraphToDocumentLine(this.session, paragraphPos.row, paragraphPos.column);
14830
14930
  const paragraph = this.session.displayData.paragraphs[paragraphPos.row];
14831
- const lineInfo = paragraph.paragraphSettings.textLinesInfo.find(x => x.screenLine === documentLine.column);
14931
+ const documentLine = PositionHelper.paragraphToDocumentLine(paragraph, paragraphPos.column);
14932
+ const lineInfo = paragraph.paragraphSettings.textLinesInfo.find(x => x.screenLine === documentLine.row);
14832
14933
  const elementIndex = paragraph.startIndex + paragraphPos.column;
14833
14934
  const element = this.session.customComponents.customElements.find(x => x.instance.content.insertIndex === elementIndex);
14834
14935
  if (!element) {
@@ -14876,7 +14977,7 @@ class CommentHighlightLayer extends HighlightLayer {
14876
14977
  const startPosition = ContentHelper.documentIndexToParagraphIndex(this.session.displayData.paragraphs, comment.startIndex);
14877
14978
  const endPosition = ContentHelper.documentIndexToParagraphIndex(this.session.displayData.paragraphs, comment.endIndex + 1);
14878
14979
  const range = new Range(startPosition, endPosition);
14879
- const screenRange = range.paragraphToDocumentLine(this.session);
14980
+ const screenRange = range.paragraphToDocumentLine(this.session.displayData.paragraphs);
14880
14981
  if (config.visibleRange &&
14881
14982
  (screenRange.end.row < config.visibleRange.startScreenLine || screenRange.start.row > config.visibleRange.endScreenLine)) {
14882
14983
  this.commentService.removeCommentFromRender(this.session.sessionId, comment.commentId);
@@ -14988,14 +15089,14 @@ class CursorLayer {
14988
15089
  this.addAnimationClass();
14989
15090
  }
14990
15091
  drawCursor(maxLayerHeight) {
14991
- const isCursorInView = this.cursorPosition.pageY >= 0 && this.cursorPosition.pageY < maxLayerHeight;
15092
+ // 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
15093
+ const isCursorInView = this.cursorPosition.pageY + this.cursorPosition.height >= 0 && this.cursorPosition.pageY < maxLayerHeight;
14992
15094
  if (!isCursorInView) {
14993
15095
  DomHelper.setStyle(this.cursor.style, 'display', 'none');
14994
15096
  return;
14995
15097
  }
14996
15098
  DomHelper.setStyle(this.cursor.style, 'display', 'block');
14997
15099
  DomHelper.setStyle(this.cursor.style, 'left', `${this.cursorPosition.pageX}px`);
14998
- DomHelper.setStyle(this.cursor.style, 'width', `${this.cursorPosition.width}px`);
14999
15100
  this.addTextStylesToCursor();
15000
15101
  }
15001
15102
  removeAnimationClass() {
@@ -15026,7 +15127,7 @@ class GrammarHighlightLayer extends HighlightLayer {
15026
15127
  continue;
15027
15128
  }
15028
15129
  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);
15130
+ const range = new Range(new CursorParagraph(index, error.offset), new CursorParagraph(index, error.offset + error.length)).paragraphToDocumentLine(this.session.displayData.paragraphs);
15030
15131
  if (config.visibleRange &&
15031
15132
  (range.end.row < config.visibleRange.startScreenLine || range.start.row > config.visibleRange.endScreenLine)) {
15032
15133
  continue;
@@ -15156,7 +15257,7 @@ class SearchHighlightLayer extends HighlightLayer {
15156
15257
  this.getVisibleCustomElementResults(config);
15157
15258
  if (this.active) {
15158
15259
  if (this.active instanceof Range) {
15159
- const screenRange = this.active.paragraphToDocumentLine(this.session);
15260
+ const screenRange = this.active.paragraphToDocumentLine(this.session.displayData.paragraphs);
15160
15261
  if (!screenRange.isEmpty &&
15161
15262
  (!config.visibleRange ||
15162
15263
  (screenRange.start.row >= config.visibleRange.startScreenLine &&
@@ -15171,13 +15272,13 @@ class SearchHighlightLayer extends HighlightLayer {
15171
15272
  }
15172
15273
  else {
15173
15274
  this.updateActiveResult();
15174
- const screenParentRange = this.active.parentRange.paragraphToDocumentLine(this.session);
15275
+ const screenParentRange = this.active.parentRange.paragraphToDocumentLine(this.session.displayData.paragraphs);
15175
15276
  this.drawCustomElementHighlight(this.active, this.selectedClassName, screenParentRange);
15176
15277
  }
15177
15278
  }
15178
15279
  if (this.markers?.length) {
15179
15280
  const ranges = this.markers
15180
- .map(x => x.paragraphToDocumentLine(this.session))
15281
+ .map(x => x.paragraphToDocumentLine(this.session.displayData.paragraphs))
15181
15282
  .filter(x => !x.isEmpty &&
15182
15283
  (!config.visibleRange ||
15183
15284
  (x.start.row >= config.visibleRange.startScreenLine && x.end.row <= config.visibleRange.endScreenLine)) &&
@@ -15202,7 +15303,7 @@ class SearchHighlightLayer extends HighlightLayer {
15202
15303
  this.active.location.isEqual(element.location))) {
15203
15304
  continue;
15204
15305
  }
15205
- const screenParentRange = element.parentRange.paragraphToDocumentLine(this.session);
15306
+ const screenParentRange = element.parentRange.paragraphToDocumentLine(this.session.displayData.paragraphs);
15206
15307
  if (!config.visibleRange ||
15207
15308
  (screenParentRange.start.row >= config.visibleRange.startScreenLine &&
15208
15309
  screenParentRange.end.row <= config.visibleRange.endScreenLine)) {
@@ -15240,7 +15341,7 @@ class SearchHighlightLayer extends HighlightLayer {
15240
15341
  return;
15241
15342
  }
15242
15343
  for (const group of groupedByParentRange) {
15243
- const screenParentRange = group.range.paragraphToDocumentLine(this.session);
15344
+ const screenParentRange = group.range.paragraphToDocumentLine(this.session.displayData.paragraphs);
15244
15345
  if (config.visibleRange &&
15245
15346
  (screenParentRange.start.row < config.visibleRange.startScreenLine ||
15246
15347
  screenParentRange.end.row > config.visibleRange.endScreenLine)) {
@@ -15284,7 +15385,7 @@ class SelectionLayer extends HighlightLayer {
15284
15385
  if (this.marker) {
15285
15386
  let range = this.marker.clipRows(config.contentRange.start, config.contentRange.end);
15286
15387
  if (!range.isEmpty) {
15287
- range = range.paragraphToDocumentLine(this.session);
15388
+ range = range.paragraphToDocumentLine(this.session.displayData.paragraphs);
15288
15389
  if (range.isSingleLine) {
15289
15390
  this.drawSingleLineMarker(range, this.className);
15290
15391
  }
@@ -15515,7 +15616,8 @@ class Renderer extends EventEmitting {
15515
15616
  const { left, top } = rect ?? this.container.getBoundingClientRect();
15516
15617
  const pageX = x - left;
15517
15618
  const pageY = y + this.session.scrollTop - top;
15518
- const { paragraph, indexInParagraph } = PositionHelper.pixelToParagraph(this.session, pageX, pageY, tokenDivider);
15619
+ const { paragraph, paragraphLine } = PositionHelper.pixelToParagraphLine(this.session.displayData.paragraphs, pageY);
15620
+ const indexInParagraph = PositionHelper.pixelToIndexInParagraph(this.session, pageX, paragraph, paragraphLine, tokenDivider);
15519
15621
  return new CursorParagraph(paragraph, indexInParagraph);
15520
15622
  }
15521
15623
  showCursor() {