@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.
- package/fesm2022/talrace-ngx-noder.mjs +440 -338
- package/fesm2022/talrace-ngx-noder.mjs.map +1 -1
- package/lib/editor/content/display-data/display-data.d.ts +2 -6
- package/lib/editor/content/display-data/display-token.model.d.ts +3 -1
- package/lib/editor/content/display-data/line-info.model.d.ts +8 -2
- package/lib/editor/content/display-data/models/custom-text.model.d.ts +8 -0
- package/lib/editor/content/display-data/models/paragraph-info.model.d.ts +0 -1
- package/lib/editor/content/helpers/display-token.helper.d.ts +7 -5
- package/lib/editor/content/helpers/line-info.helper.d.ts +8 -1
- package/lib/editor/display/rendering.helper.d.ts +1 -0
- package/lib/editor/execution/constants/editor-tags.const.d.ts +5 -0
- package/lib/editor/execution/editor.d.ts +3 -8
- package/lib/editor/execution/helpers/paragraph.helper.d.ts +1 -1
- package/lib/editor/gadgets/page-break/break.helper.d.ts +0 -1
- package/lib/editor/positioning/cursor-position.interface.d.ts +0 -1
- package/lib/editor/positioning/position.helper.d.ts +4 -7
- package/lib/editor/positioning/range.d.ts +2 -2
- package/lib/editor/positioning/selection.d.ts +2 -2
- package/package.json +1 -1
- package/src/scss/base-editor.scss +8 -8
|
@@ -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(
|
|
6312
|
-
|
|
6313
|
-
|
|
6314
|
-
|
|
6315
|
-
|
|
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(
|
|
6320
|
-
const paragraphLine =
|
|
6321
|
-
|
|
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
|
-
|
|
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
|
-
|
|
6336
|
-
const
|
|
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]
|
|
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
|
|
6352
|
-
let
|
|
6353
|
-
|
|
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:
|
|
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
|
|
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
|
|
6404
|
-
const
|
|
6405
|
-
const
|
|
6406
|
-
return
|
|
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
|
-
|
|
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 (
|
|
6424
|
-
|
|
6425
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
6516
|
-
const
|
|
6517
|
-
const
|
|
6518
|
-
const
|
|
6519
|
-
|
|
6520
|
-
|
|
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 (
|
|
6524
|
-
|
|
6505
|
+
else if (renderedTokensInLine < wordSpacingEndToken && wordSpacingEndIndex < fragmentEndIndex) {
|
|
6506
|
+
fragmentEndIndex = wordSpacingEndIndex;
|
|
6525
6507
|
}
|
|
6526
|
-
if (
|
|
6508
|
+
if (renderedTokensInLine < wordSpacingStartToken || renderedTokensInLine > wordSpacingEndToken) {
|
|
6527
6509
|
wordSpacing = null;
|
|
6528
6510
|
}
|
|
6529
6511
|
}
|
|
6530
|
-
const
|
|
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
|
-
|
|
6534
|
-
|
|
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 (
|
|
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,
|
|
6567
|
-
|
|
6568
|
-
|
|
6569
|
-
|
|
6570
|
-
|
|
6571
|
-
|
|
6572
|
-
|
|
6573
|
-
|
|
6574
|
-
|
|
6575
|
-
|
|
6576
|
-
|
|
6577
|
-
|
|
6578
|
-
|
|
6579
|
-
|
|
6580
|
-
|
|
6581
|
-
|
|
6582
|
-
|
|
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
|
-
|
|
6585
|
-
|
|
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
|
-
|
|
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
|
-
|
|
6595
|
-
span.
|
|
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(
|
|
7165
|
+
static getParagraphPages(lines) {
|
|
7129
7166
|
const resultPages = [];
|
|
7130
|
-
|
|
7131
|
-
|
|
7132
|
-
|
|
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(
|
|
7439
|
-
const screenPosStart = PositionHelper.paragraphToDocumentLine(
|
|
7440
|
-
const screenPosEnd = PositionHelper.paragraphToDocumentLine(
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
|
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.
|
|
8427
|
+
this.cursor = this.getLeft(paragraphs, moved.paragraph, moved.indexInParagraph);
|
|
8387
8428
|
}
|
|
8388
8429
|
}
|
|
8389
8430
|
moveCursorDown(session, position) {
|
|
8390
|
-
const
|
|
8391
|
-
const
|
|
8392
|
-
const
|
|
8393
|
-
const
|
|
8394
|
-
if (line.row ===
|
|
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.
|
|
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
|
|
8406
|
-
|
|
8407
|
-
|
|
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
|
-
|
|
8410
|
-
if (
|
|
8411
|
-
|
|
8455
|
+
getLeft(paragraphs, paragraph, indexInParagraph) {
|
|
8456
|
+
if (paragraph === 0) {
|
|
8457
|
+
indexInParagraph -= indexInParagraph > 0 ? 1 : 0;
|
|
8458
|
+
return new CursorParagraph(paragraph, indexInParagraph);
|
|
8412
8459
|
}
|
|
8413
|
-
|
|
8414
|
-
|
|
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
|
-
|
|
8417
|
-
|
|
8418
|
-
|
|
8419
|
-
return
|
|
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
|
-
|
|
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
|
|
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
|
|
8430
|
-
const
|
|
8431
|
-
|
|
8432
|
-
|
|
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
|
-
|
|
8442
|
-
|
|
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,
|
|
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.
|
|
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.
|
|
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 !==
|
|
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 !==
|
|
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 !==
|
|
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 !==
|
|
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 !==
|
|
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.
|
|
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 !==
|
|
10028
|
+
return customElement.tagName !== EDGE_TAG ? customElement : null;
|
|
9992
10029
|
}
|
|
9993
10030
|
getCustomElement(element) {
|
|
9994
|
-
if (!element || element.tagName ===
|
|
10031
|
+
if (!element || element.tagName === PARENT_TAG) {
|
|
9995
10032
|
return null;
|
|
9996
10033
|
}
|
|
9997
|
-
else if (this.
|
|
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 ===
|
|
10045
|
+
if (!element || element.tagName === PARENT_TAG) {
|
|
10009
10046
|
return null;
|
|
10010
10047
|
}
|
|
10011
|
-
else if (element.tagName ===
|
|
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 ===
|
|
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
|
|
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
|
|
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
|
|
12195
|
-
|
|
12196
|
-
|
|
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
|
-
|
|
12206
|
-
|
|
12207
|
-
|
|
12208
|
-
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
12257
|
-
|
|
12258
|
-
|
|
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 <
|
|
12818
|
-
this.paragraphs[i].lineNumber =
|
|
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
|
|
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
|
|
12916
|
-
const
|
|
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
|
-
|
|
12928
|
-
|
|
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
|
|
12933
|
-
const
|
|
12934
|
-
const
|
|
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 ===
|
|
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
|
|
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
|
|
12962
|
-
const
|
|
12963
|
-
const lineContent = paragraph.content.substring(
|
|
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
|
|
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
|
|
12969
|
-
const
|
|
12970
|
-
const
|
|
12971
|
-
|
|
12972
|
-
const
|
|
12973
|
-
|
|
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
|
|
12990
|
-
|
|
12991
|
-
|
|
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(
|
|
13095
|
+
tokens.push(...newTokens);
|
|
12998
13096
|
}
|
|
12999
|
-
|
|
13000
|
-
|
|
13001
|
-
|
|
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
|
-
//
|
|
13048
|
-
|
|
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.
|
|
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
|
|
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
|
|
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
|
-
|
|
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,
|
|
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() {
|