roosterjs-content-model-dom 9.12.0 → 9.13.0
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/lib/modelApi/common/normalizeParagraph.js +36 -0
- package/lib/modelApi/common/normalizeParagraph.js.map +1 -1
- package/lib/modelToDom/contentModelToDom.js +6 -3
- package/lib/modelToDom/contentModelToDom.js.map +1 -1
- package/lib/modelToDom/handlers/handleParagraph.js +1 -1
- package/lib/modelToDom/handlers/handleParagraph.js.map +1 -1
- package/lib/modelToDom/optimizers/optimize.d.ts +2 -1
- package/lib/modelToDom/optimizers/optimize.js +41 -2
- package/lib/modelToDom/optimizers/optimize.js.map +1 -1
- package/lib-amd/modelApi/common/normalizeParagraph.js +36 -1
- package/lib-amd/modelApi/common/normalizeParagraph.js.map +1 -1
- package/lib-amd/modelToDom/contentModelToDom.js +6 -3
- package/lib-amd/modelToDom/contentModelToDom.js.map +1 -1
- package/lib-amd/modelToDom/handlers/handleParagraph.js +1 -1
- package/lib-amd/modelToDom/handlers/handleParagraph.js.map +1 -1
- package/lib-amd/modelToDom/optimizers/optimize.d.ts +2 -1
- package/lib-amd/modelToDom/optimizers/optimize.js +41 -3
- package/lib-amd/modelToDom/optimizers/optimize.js.map +1 -1
- package/lib-mjs/modelApi/common/normalizeParagraph.js +37 -1
- package/lib-mjs/modelApi/common/normalizeParagraph.js.map +1 -1
- package/lib-mjs/modelToDom/contentModelToDom.js +6 -3
- package/lib-mjs/modelToDom/contentModelToDom.js.map +1 -1
- package/lib-mjs/modelToDom/handlers/handleParagraph.js +1 -1
- package/lib-mjs/modelToDom/handlers/handleParagraph.js.map +1 -1
- package/lib-mjs/modelToDom/optimizers/optimize.d.ts +2 -1
- package/lib-mjs/modelToDom/optimizers/optimize.js +41 -2
- package/lib-mjs/modelToDom/optimizers/optimize.js.map +1 -1
- package/package.json +2 -2
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.normalizeParagraph = void 0;
|
|
4
|
+
var tslib_1 = require("tslib");
|
|
4
5
|
var areSameFormats_1 = require("../../domToModel/utils/areSameFormats");
|
|
5
6
|
var createBr_1 = require("../creators/createBr");
|
|
6
7
|
var isEmpty_1 = require("./isEmpty");
|
|
@@ -36,6 +37,7 @@ function normalizeParagraph(paragraph) {
|
|
|
36
37
|
}
|
|
37
38
|
removeEmptyLinks(paragraph);
|
|
38
39
|
removeEmptySegments(paragraph);
|
|
40
|
+
mergeTextSegments(paragraph);
|
|
39
41
|
moveUpSegmentFormat(paragraph);
|
|
40
42
|
}
|
|
41
43
|
exports.normalizeParagraph = normalizeParagraph;
|
|
@@ -53,6 +55,40 @@ function removeEmptySegments(block) {
|
|
|
53
55
|
}
|
|
54
56
|
}
|
|
55
57
|
}
|
|
58
|
+
function mergeTextSegments(block) {
|
|
59
|
+
var lastText = null;
|
|
60
|
+
for (var i = 0; i < block.segments.length; i++) {
|
|
61
|
+
var segment = block.segments[i];
|
|
62
|
+
if (segment.segmentType != 'Text') {
|
|
63
|
+
lastText = null;
|
|
64
|
+
}
|
|
65
|
+
else if (!lastText || !segmentsWithSameFormat(lastText, segment)) {
|
|
66
|
+
lastText = segment;
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
var _a = (0, tslib_1.__read)((0, mutate_1.mutateSegments)(block, [lastText, segment]), 2), mutableBlock = _a[0], _b = (0, tslib_1.__read)(_a[1], 1), mutableLastText = _b[0];
|
|
70
|
+
mutableLastText.text += segment.text;
|
|
71
|
+
mutableBlock.segments.splice(i, 1);
|
|
72
|
+
i--;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
function segmentsWithSameFormat(seg1, seg2) {
|
|
77
|
+
return (!!seg1.isSelected == !!seg2.isSelected &&
|
|
78
|
+
(0, areSameFormats_1.areSameFormats)(seg1.format, seg2.format) &&
|
|
79
|
+
areSameLinks(seg1.link, seg2.link) &&
|
|
80
|
+
areSameCodes(seg1.code, seg2.code));
|
|
81
|
+
}
|
|
82
|
+
function areSameLinks(link1, link2) {
|
|
83
|
+
return ((!link1 && !link2) ||
|
|
84
|
+
(link1 &&
|
|
85
|
+
link2 &&
|
|
86
|
+
(0, areSameFormats_1.areSameFormats)(link1.format, link2.format) &&
|
|
87
|
+
(0, areSameFormats_1.areSameFormats)(link1.dataset, link2.dataset)));
|
|
88
|
+
}
|
|
89
|
+
function areSameCodes(code1, code2) {
|
|
90
|
+
return (!code1 && !code2) || (code1 && code2 && (0, areSameFormats_1.areSameFormats)(code1.format, code2.format));
|
|
91
|
+
}
|
|
56
92
|
function removeEmptyLinks(paragraph) {
|
|
57
93
|
var marker = paragraph.segments.find(function (x) { return x.segmentType == 'SelectionMarker'; });
|
|
58
94
|
if (marker) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"normalizeParagraph.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-dom/lib/modelApi/common/normalizeParagraph.ts"],"names":[],"mappings":"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","sourcesContent":["import { areSameFormats } from '../../domToModel/utils/areSameFormats';\nimport { createBr } from '../creators/createBr';\nimport { isSegmentEmpty } from './isEmpty';\nimport { isWhiteSpacePreserved } from '../../domUtils/isWhiteSpacePreserved';\nimport { mutateBlock, mutateSegment } from './mutate';\nimport { normalizeAllSegments } from './normalizeSegment';\nimport type {\n ContentModelSegmentFormat,\n ReadonlyContentModelParagraph,\n ReadonlyContentModelSegment,\n} from 'roosterjs-content-model-types';\n\n/**\n * @param paragraph The paragraph to normalize\n * Normalize a paragraph. If it is empty, add a BR segment to make sure it can insert content\n */\nexport function normalizeParagraph(paragraph: ReadonlyContentModelParagraph) {\n const segments = paragraph.segments;\n\n if (!paragraph.isImplicit && segments.length > 0) {\n const last = segments[segments.length - 1];\n const secondLast = segments[segments.length - 2];\n\n if (\n last.segmentType == 'SelectionMarker' &&\n (!secondLast || secondLast.segmentType == 'Br')\n ) {\n mutateBlock(paragraph).segments.push(createBr(last.format));\n } else if (segments.length > 1 && segments[segments.length - 1].segmentType == 'Br') {\n const noMarkerSegments = segments.filter(x => x.segmentType != 'SelectionMarker');\n\n // When there is content with a <BR> tag at the end, we can remove the BR.\n // But if there are more than one <BR> at the end, do not remove them.\n if (\n noMarkerSegments.length > 1 &&\n noMarkerSegments[noMarkerSegments.length - 2].segmentType != 'Br'\n ) {\n mutateBlock(paragraph).segments.pop();\n }\n }\n\n normalizeParagraphStyle(paragraph);\n }\n\n if (!isWhiteSpacePreserved(paragraph.format.whiteSpace)) {\n normalizeAllSegments(paragraph);\n }\n\n removeEmptyLinks(paragraph);\n\n removeEmptySegments(paragraph);\n\n moveUpSegmentFormat(paragraph);\n}\n\nfunction normalizeParagraphStyle(paragraph: ReadonlyContentModelParagraph) {\n // New paragraph should not have white-space style\n if (\n paragraph.format.whiteSpace &&\n paragraph.segments.every(\n seg => seg.segmentType == 'Br' || seg.segmentType == 'SelectionMarker'\n )\n ) {\n delete mutateBlock(paragraph).format.whiteSpace;\n }\n}\n\nfunction removeEmptySegments(block: ReadonlyContentModelParagraph) {\n for (let j = block.segments.length - 1; j >= 0; j--) {\n if (isSegmentEmpty(block.segments[j])) {\n mutateBlock(block).segments.splice(j, 1);\n }\n }\n}\n\nfunction removeEmptyLinks(paragraph: ReadonlyContentModelParagraph) {\n const marker = paragraph.segments.find(x => x.segmentType == 'SelectionMarker');\n if (marker) {\n const markerIndex = paragraph.segments.indexOf(marker);\n const prev = paragraph.segments[markerIndex - 1];\n const next = paragraph.segments[markerIndex + 1];\n\n if (\n (prev &&\n !prev.link &&\n areSameFormats(prev.format, marker.format) &&\n (!next || (!next.link && areSameFormats(next.format, marker.format))) &&\n marker.link) ||\n (!prev &&\n marker.link &&\n next &&\n !next.link &&\n areSameFormats(next.format, marker.format))\n ) {\n mutateSegment(paragraph, marker, mutableMarker => {\n delete mutableMarker.link;\n });\n }\n }\n}\n\ntype FormatsToMoveUp = 'fontFamily' | 'fontSize' | 'textColor';\nconst formatsToMoveUp: FormatsToMoveUp[] = ['fontFamily', 'fontSize', 'textColor'];\n\n// When all segments are sharing the same segment format (font name, size and color), we can move its format to paragraph\nfunction moveUpSegmentFormat(paragraph: ReadonlyContentModelParagraph) {\n if (!paragraph.decorator) {\n const segments = paragraph.segments.filter(x => x.segmentType != 'SelectionMarker');\n const target = paragraph.segmentFormat || {};\n let changed = false;\n\n formatsToMoveUp.forEach(key => {\n changed = internalMoveUpSegmentFormat(segments, target, key) || changed;\n });\n\n if (changed) {\n mutateBlock(paragraph).segmentFormat = target;\n }\n }\n}\n\nfunction internalMoveUpSegmentFormat(\n segments: ReadonlyContentModelSegment[],\n target: ContentModelSegmentFormat,\n formatKey: FormatsToMoveUp\n): boolean {\n const firstFormat = segments[0]?.format;\n\n if (\n firstFormat?.[formatKey] &&\n segments.every(segment => segment.format[formatKey] == firstFormat[formatKey]) &&\n target[formatKey] != firstFormat[formatKey]\n ) {\n target[formatKey] = firstFormat[formatKey];\n return true;\n } else {\n return false;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"normalizeParagraph.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-dom/lib/modelApi/common/normalizeParagraph.ts"],"names":[],"mappings":"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","sourcesContent":["import { areSameFormats } from '../../domToModel/utils/areSameFormats';\nimport { createBr } from '../creators/createBr';\nimport { isSegmentEmpty } from './isEmpty';\nimport { isWhiteSpacePreserved } from '../../domUtils/isWhiteSpacePreserved';\nimport { mutateBlock, mutateSegment, mutateSegments } from './mutate';\nimport { normalizeAllSegments } from './normalizeSegment';\nimport type {\n ContentModelSegmentFormat,\n ContentModelText,\n ReadonlyContentModelCode,\n ReadonlyContentModelLink,\n ReadonlyContentModelParagraph,\n ReadonlyContentModelSegment,\n ReadonlyContentModelText,\n} from 'roosterjs-content-model-types';\n\n/**\n * @param paragraph The paragraph to normalize\n * Normalize a paragraph. If it is empty, add a BR segment to make sure it can insert content\n */\nexport function normalizeParagraph(paragraph: ReadonlyContentModelParagraph) {\n const segments = paragraph.segments;\n\n if (!paragraph.isImplicit && segments.length > 0) {\n const last = segments[segments.length - 1];\n const secondLast = segments[segments.length - 2];\n\n if (\n last.segmentType == 'SelectionMarker' &&\n (!secondLast || secondLast.segmentType == 'Br')\n ) {\n mutateBlock(paragraph).segments.push(createBr(last.format));\n } else if (segments.length > 1 && segments[segments.length - 1].segmentType == 'Br') {\n const noMarkerSegments = segments.filter(x => x.segmentType != 'SelectionMarker');\n\n // When there is content with a <BR> tag at the end, we can remove the BR.\n // But if there are more than one <BR> at the end, do not remove them.\n if (\n noMarkerSegments.length > 1 &&\n noMarkerSegments[noMarkerSegments.length - 2].segmentType != 'Br'\n ) {\n mutateBlock(paragraph).segments.pop();\n }\n }\n\n normalizeParagraphStyle(paragraph);\n }\n\n if (!isWhiteSpacePreserved(paragraph.format.whiteSpace)) {\n normalizeAllSegments(paragraph);\n }\n\n removeEmptyLinks(paragraph);\n removeEmptySegments(paragraph);\n mergeTextSegments(paragraph);\n moveUpSegmentFormat(paragraph);\n}\n\nfunction normalizeParagraphStyle(paragraph: ReadonlyContentModelParagraph) {\n // New paragraph should not have white-space style\n if (\n paragraph.format.whiteSpace &&\n paragraph.segments.every(\n seg => seg.segmentType == 'Br' || seg.segmentType == 'SelectionMarker'\n )\n ) {\n delete mutateBlock(paragraph).format.whiteSpace;\n }\n}\n\nfunction removeEmptySegments(block: ReadonlyContentModelParagraph) {\n for (let j = block.segments.length - 1; j >= 0; j--) {\n if (isSegmentEmpty(block.segments[j])) {\n mutateBlock(block).segments.splice(j, 1);\n }\n }\n}\n\nfunction mergeTextSegments(block: ReadonlyContentModelParagraph) {\n let lastText: ReadonlyContentModelText | null = null;\n\n for (let i = 0; i < block.segments.length; i++) {\n const segment = block.segments[i];\n\n if (segment.segmentType != 'Text') {\n lastText = null;\n } else if (!lastText || !segmentsWithSameFormat(lastText, segment)) {\n lastText = segment;\n } else {\n const [mutableBlock, [mutableLastText]] = mutateSegments(block, [lastText, segment]);\n\n (mutableLastText as ContentModelText).text += segment.text;\n mutableBlock.segments.splice(i, 1);\n i--;\n }\n }\n}\n\nfunction segmentsWithSameFormat(\n seg1: ReadonlyContentModelSegment,\n seg2: ReadonlyContentModelSegment\n) {\n return (\n !!seg1.isSelected == !!seg2.isSelected &&\n areSameFormats(seg1.format, seg2.format) &&\n areSameLinks(seg1.link, seg2.link) &&\n areSameCodes(seg1.code, seg2.code)\n );\n}\n\nfunction areSameLinks(\n link1: ReadonlyContentModelLink | undefined,\n link2: ReadonlyContentModelLink | undefined\n) {\n return (\n (!link1 && !link2) ||\n (link1 &&\n link2 &&\n areSameFormats(link1.format, link2.format) &&\n areSameFormats(link1.dataset, link2.dataset))\n );\n}\n\nfunction areSameCodes(\n code1: ReadonlyContentModelCode | undefined,\n code2: ReadonlyContentModelCode | undefined\n) {\n return (!code1 && !code2) || (code1 && code2 && areSameFormats(code1.format, code2.format));\n}\n\nfunction removeEmptyLinks(paragraph: ReadonlyContentModelParagraph) {\n const marker = paragraph.segments.find(x => x.segmentType == 'SelectionMarker');\n if (marker) {\n const markerIndex = paragraph.segments.indexOf(marker);\n const prev = paragraph.segments[markerIndex - 1];\n const next = paragraph.segments[markerIndex + 1];\n\n if (\n (prev &&\n !prev.link &&\n areSameFormats(prev.format, marker.format) &&\n (!next || (!next.link && areSameFormats(next.format, marker.format))) &&\n marker.link) ||\n (!prev &&\n marker.link &&\n next &&\n !next.link &&\n areSameFormats(next.format, marker.format))\n ) {\n mutateSegment(paragraph, marker, mutableMarker => {\n delete mutableMarker.link;\n });\n }\n }\n}\n\ntype FormatsToMoveUp = 'fontFamily' | 'fontSize' | 'textColor';\nconst formatsToMoveUp: FormatsToMoveUp[] = ['fontFamily', 'fontSize', 'textColor'];\n\n// When all segments are sharing the same segment format (font name, size and color), we can move its format to paragraph\nfunction moveUpSegmentFormat(paragraph: ReadonlyContentModelParagraph) {\n if (!paragraph.decorator) {\n const segments = paragraph.segments.filter(x => x.segmentType != 'SelectionMarker');\n const target = paragraph.segmentFormat || {};\n let changed = false;\n\n formatsToMoveUp.forEach(key => {\n changed = internalMoveUpSegmentFormat(segments, target, key) || changed;\n });\n\n if (changed) {\n mutateBlock(paragraph).segmentFormat = target;\n }\n }\n}\n\nfunction internalMoveUpSegmentFormat(\n segments: ReadonlyContentModelSegment[],\n target: ContentModelSegmentFormat,\n formatKey: FormatsToMoveUp\n): boolean {\n const firstFormat = segments[0]?.format;\n\n if (\n firstFormat?.[formatKey] &&\n segments.every(segment => segment.format[formatKey] == firstFormat[formatKey]) &&\n target[formatKey] != firstFormat[formatKey]\n ) {\n target[formatKey] = firstFormat[formatKey];\n return true;\n } else {\n return false;\n }\n}\n"]}
|
|
@@ -52,14 +52,17 @@ function extractSelectionRange(doc, context) {
|
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
54
|
function calcPosition(pos) {
|
|
55
|
-
var _a, _b, _c;
|
|
55
|
+
var _a, _b, _c, _d, _e;
|
|
56
56
|
var result;
|
|
57
57
|
if (pos.block) {
|
|
58
58
|
if (!pos.segment) {
|
|
59
59
|
result = { container: pos.block, offset: 0 };
|
|
60
60
|
}
|
|
61
61
|
else if ((0, isNodeOfType_1.isNodeOfType)(pos.segment, 'TEXT_NODE')) {
|
|
62
|
-
result = {
|
|
62
|
+
result = {
|
|
63
|
+
container: pos.segment,
|
|
64
|
+
offset: (_c = (_a = pos.offset) !== null && _a !== void 0 ? _a : (_b = pos.segment.nodeValue) === null || _b === void 0 ? void 0 : _b.length) !== null && _c !== void 0 ? _c : 0,
|
|
65
|
+
};
|
|
63
66
|
}
|
|
64
67
|
else if (pos.segment.parentNode) {
|
|
65
68
|
result = {
|
|
@@ -78,7 +81,7 @@ function calcPosition(pos) {
|
|
|
78
81
|
result = {
|
|
79
82
|
container: container,
|
|
80
83
|
offset: (0, isNodeOfType_1.isNodeOfType)(container, 'TEXT_NODE')
|
|
81
|
-
? (
|
|
84
|
+
? (_e = (_d = container.nodeValue) === null || _d === void 0 ? void 0 : _d.length) !== null && _e !== void 0 ? _e : 0
|
|
82
85
|
: container.childNodes.length,
|
|
83
86
|
};
|
|
84
87
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contentModelToDom.js","sourceRoot":"","sources":["../../../../packages/roosterjs-content-model-dom/lib/modelToDom/contentModelToDom.ts"],"names":[],"mappings":";;;AAAA,yDAAwD;AACxD,+CAA8C;AAS9C;;;;;;;;;GASG;AACH,SAAgB,iBAAiB,CAC7B,GAAa,EACb,IAAU,EACV,KAA2B,EAC3B,OAA0B;IAE1B,OAAO,CAAC,aAAa,CAAC,kBAAkB,CAAC,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;IAEpE,IAAM,KAAK,GAAG,qBAAqB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAElD,IAAI,KAAK,CAAC,yBAAyB,IAAI,CAAA,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,IAAI,KAAI,OAAO,EAAE;QAC3D,KAAK,CAAC,UAAU,GAAG,IAAI,CAAC;KAC3B;IAED,IAAI,OAAO,CAAC,UAAU,IAAI,OAAO,CAAC,iBAAiB,EAAE;QAChD,KAAgD,CAAC,YAAY,GAAG,IAAI,CAAC;KACzE;IAED,IAAI,CAAC,SAAS,EAAE,CAAC;IAEjB,OAAO,KAAK,CAAC;AACjB,CAAC;AArBD,8CAqBC;AAED,SAAS,qBAAqB,CAAC,GAAa,EAAE,OAA0B;IAEhE,IAAA,KAGA,OAAO,iBAHyB,EAAZ,KAAK,WAAA,EAAE,GAAG,SAAA,EAC9B,cAAc,GAEd,OAAO,eAFO,EACd,cAAc,GACd,OAAO,eADO,CACN;IAEZ,IAAI,aAA8D,CAAC;IACnE,IAAI,WAA4D,CAAC;IAEjE,IAAI,cAAc,EAAE;QAChB,OAAO,cAAc,CAAC;KACzB;SAAM,IACH,CAAC,aAAa,GAAG,KAAK,IAAI,YAAY,CAAC,KAAK,CAAC,CAAC;QAC9C,CAAC,WAAW,GAAG,GAAG,IAAI,YAAY,CAAC,GAAG,CAAC,CAAC,EAC1C;QACE,IAAM,KAAK,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC;QAEhC,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,SAAS,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;QAC9D,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC,SAAS,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;QAExD,OAAO;YACH,IAAI,EAAE,OAAO;YACb,KAAK,OAAA;YACL,UAAU,EAAE,KAAK;SACpB,CAAC;KACL;SAAM,IAAI,cAAc,EAAE;QACvB,OAAO,cAAc,CAAC;KACzB;SAAM;QACH,OAAO,IAAI,CAAC;KACf;AACL,CAAC;AAED,SAAS,YAAY,CACjB,GAAkC;;IAElC,IAAI,MAAuD,CAAC;IAE5D,IAAI,GAAG,CAAC,KAAK,EAAE;QACX,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE;YACd,MAAM,GAAG,EAAE,SAAS,EAAE,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;SAChD;aAAM,IAAI,IAAA,2BAAY,EAAC,GAAG,CAAC,OAAO,EAAE,WAAW,CAAC,EAAE;YAC/C,MAAM,GAAG,
|
|
1
|
+
{"version":3,"file":"contentModelToDom.js","sourceRoot":"","sources":["../../../../packages/roosterjs-content-model-dom/lib/modelToDom/contentModelToDom.ts"],"names":[],"mappings":"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","sourcesContent":["import { isNodeOfType } from '../domUtils/isNodeOfType';\nimport { toArray } from '../domUtils/toArray';\nimport type { ContentModelDocumentWithPersistedCache } from '../modelApi/selection/iterateSelections';\nimport type {\n ContentModelDocument,\n DOMSelection,\n ModelToDomBlockAndSegmentNode,\n ModelToDomContext,\n} from 'roosterjs-content-model-types';\n\n/**\n * Create DOM tree fragment from Content Model document\n * @param doc Document object of the target DOM tree\n * @param root Target node that will become the container of new DOM tree.\n * When a DOM node with existing node is passed, it will be merged with content model so that unchanged blocks\n * won't be touched.\n * @param model The content model document to generate DOM tree from\n * @param context The context object for Content Model to DOM conversion\n * @returns The selection range created in DOM tree from this model, or null when there is no selection\n */\nexport function contentModelToDom(\n doc: Document,\n root: Node,\n model: ContentModelDocument,\n context: ModelToDomContext\n): DOMSelection | null {\n context.modelHandlers.blockGroupChildren(doc, root, model, context);\n\n const range = extractSelectionRange(doc, context);\n\n if (model.hasRevertedRangeSelection && range?.type == 'range') {\n range.isReverted = true;\n }\n\n if (context.domIndexer && context.allowCacheElement) {\n (model as ContentModelDocumentWithPersistedCache).persistCache = true;\n }\n\n root.normalize();\n\n return range;\n}\n\nfunction extractSelectionRange(doc: Document, context: ModelToDomContext): DOMSelection | null {\n const {\n regularSelection: { start, end },\n tableSelection,\n imageSelection,\n } = context;\n\n let startPosition: { container: Node; offset: number } | undefined;\n let endPosition: { container: Node; offset: number } | undefined;\n\n if (imageSelection) {\n return imageSelection;\n } else if (\n (startPosition = start && calcPosition(start)) &&\n (endPosition = end && calcPosition(end))\n ) {\n const range = doc.createRange();\n\n range.setStart(startPosition.container, startPosition.offset);\n range.setEnd(endPosition.container, endPosition.offset);\n\n return {\n type: 'range',\n range,\n isReverted: false,\n };\n } else if (tableSelection) {\n return tableSelection;\n } else {\n return null;\n }\n}\n\nfunction calcPosition(\n pos: ModelToDomBlockAndSegmentNode\n): { container: Node; offset: number } | undefined {\n let result: { container: Node; offset: number } | undefined;\n\n if (pos.block) {\n if (!pos.segment) {\n result = { container: pos.block, offset: 0 };\n } else if (isNodeOfType(pos.segment, 'TEXT_NODE')) {\n result = {\n container: pos.segment,\n offset: pos.offset ?? pos.segment.nodeValue?.length ?? 0,\n };\n } else if (pos.segment.parentNode) {\n result = {\n container: pos.segment.parentNode,\n offset:\n toArray(pos.segment.parentNode.childNodes as NodeListOf<Node>).indexOf(\n pos.segment\n ) + 1,\n };\n }\n }\n\n if (result && isNodeOfType(result.container, 'DOCUMENT_FRAGMENT_NODE')) {\n const childNodes = result.container.childNodes;\n\n if (childNodes.length > result.offset) {\n result = { container: childNodes[result.offset], offset: 0 };\n } else if (result.container.lastChild) {\n const container = result.container.lastChild;\n result = {\n container,\n offset: isNodeOfType(container, 'TEXT_NODE')\n ? container.nodeValue?.length ?? 0\n : container.childNodes.length,\n };\n } else {\n result = undefined;\n }\n }\n\n return result;\n}\n"]}
|
|
@@ -62,7 +62,7 @@ var handleParagraph = function (doc, parent, paragraph, context, refNode) {
|
|
|
62
62
|
else {
|
|
63
63
|
handleSegments();
|
|
64
64
|
}
|
|
65
|
-
(0, optimize_1.optimize)(container);
|
|
65
|
+
(0, optimize_1.optimize)(container, context);
|
|
66
66
|
// It is possible the next sibling node is changed during processing child segments
|
|
67
67
|
// e.g. When this paragraph is an implicit paragraph and it contains an inline entity segment
|
|
68
68
|
// The segment will be appended to container as child then the container will be removed
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handleParagraph.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-dom/lib/modelToDom/handlers/handleParagraph.ts"],"names":[],"mappings":";;;;AAAA,oDAAmD;AACnD,8DAA6D;AAC7D,mDAAkD;AAClD,wEAAuE;AACvE,oDAAmD;AACnD,gDAA+C;AAO/C,IAAM,mBAAmB,GAAG,KAAK,CAAC;AAElC;;GAEG;AACI,IAAM,eAAe,GAAoD,UAC5E,GAAa,EACb,MAAY,EACZ,SAAgC,EAChC,OAA0B,EAC1B,OAAoB;;IAEpB,IAAI,SAAS,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS,CAAC;IAEhF,IAAI,SAAS,IAAI,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,UAAA,CAAC,IAAI,OAAA,CAAC,CAAC,WAAW,IAAI,SAAS,IAAI,CAAC,CAAC,CAAC,UAAU,EAA3C,CAA2C,CAAC,EAAE;QACzF,OAAO,GAAG,IAAA,uCAAkB,EAAC,MAAM,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;KAC5D;SAAM;QACH,IAAA,yBAAW,EAAC,OAAO,EAAE,CAAA,MAAA,SAAS,CAAC,SAAS,0CAAE,OAAO,KAAI,IAAI,EAAE;;YACvD,IAAM,oBAAoB,GACtB,CAAC,SAAS,CAAC,UAAU;gBACrB,CAAC,CAAC,SAAS,CAAC,SAAS;gBACrB,CAAC,IAAA,6BAAa,EAAC,SAAS,CAAC,MAAM,CAAC,CAAC,MAAM,GAAG,CAAC;oBACvC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,UAAA,OAAO,IAAI,OAAA,OAAO,CAAC,WAAW,IAAI,iBAAiB,EAAxC,CAAwC,CAAC,CAAC,CAAC;YACtF,IAAM,eAAe,GAAG,oBAAoB;gBACxC,CAAC,iDACQ,CAAC,CAAA,MAAA,SAAS,CAAC,SAAS,0CAAE,MAAM,KAAI,EAAE,CAAC,GACnC,SAAS,CAAC,aAAa,EAEhC,CAAC,CAAC,EAAE,CAAC;YAET,SAAS,GAAG,GAAG,CAAC,aAAa,CAAC,CAAA,MAAA,SAAS,CAAC,SAAS,0CAAE,OAAO,KAAI,mBAAmB,CAAC,CAAC;YAEnF,MAAM,CAAC,YAAY,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;YAExC,OAAO,CAAC,gBAAgB,CAAC,OAAO,GAAG;gBAC/B,KAAK,EAAE,oBAAoB,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,UAAU;gBAC9D,OAAO,EAAE,IAAI;aAChB,CAAC;YAEF,IAAM,cAAc,GAAG;gBACnB,IAAM,MAAM,GAAG,SAAS,CAAC;gBAEzB,IAAI,MAAM,EAAE;oBACR,IAAM,YAAY,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;oBAE3C,IAAI,CAAA,YAAY,aAAZ,YAAY,uBAAZ,YAAY,CAAE,WAAW,KAAI,iBAAiB,EAAE;wBAChD,gEAAgE;wBAChE,8FAA8F;wBAC9F,sGAAsG;wBACtG,OAAO,CAAC,aAAa,CAAC,IAAI,CACtB,GAAG,EACH,MAAM,kDAEC,YAAY,KACf,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,EAAE,KAEZ,OAAO,EACP,EAAE,CACL,CAAC;qBACL;oBAED,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC,UAAA,OAAO;wBAC9B,IAAM,WAAW,GAAW,EAAE,CAAC;wBAC/B,OAAO,CAAC,aAAa,CAAC,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,CAAC,CAAC;wBAE1E,WAAW,CAAC,OAAO,CAAC,UAAA,IAAI;;4BACpB,MAAA,OAAO,CAAC,UAAU,0CAAE,SAAS,CAAC,IAAI,EAAE,SAAS,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;wBAC9D,CAAC,CAAC,CAAC;oBACP,CAAC,CAAC,CAAC;iBACN;YACL,CAAC,CAAC;YAEF,IAAI,oBAAoB,EAAE;gBACtB,IAAA,yBAAW,EAAC,OAAO,EAAE,eAAe,EAAE,cAAc,CAAC,CAAC;gBAEtD,IAAA,yBAAW,EAAC,SAAS,EAAE,OAAO,CAAC,cAAc,CAAC,KAAK,EAAE,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;gBAChF,IAAA,yBAAW,EAAC,SAAS,EAAE,OAAO,CAAC,cAAc,CAAC,SAAS,EAAE,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;gBACpF,IAAA,yBAAW,EACP,SAAS,EACT,OAAO,CAAC,cAAc,CAAC,cAAc,EACrC,eAAe,EACf,OAAO,CACV,CAAC;aACL;iBAAM;gBACH,cAAc,EAAE,CAAC;aACpB;YAED,IAAA,mBAAQ,EAAC,SAAS,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"handleParagraph.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-dom/lib/modelToDom/handlers/handleParagraph.ts"],"names":[],"mappings":"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","sourcesContent":["import { applyFormat } from '../utils/applyFormat';\nimport { getObjectKeys } from '../../domUtils/getObjectKeys';\nimport { optimize } from '../optimizers/optimize';\nimport { reuseCachedElement } from '../../domUtils/reuseCachedElement';\nimport { stackFormat } from '../utils/stackFormat';\nimport { unwrap } from '../../domUtils/unwrap';\nimport type {\n ContentModelBlockHandler,\n ContentModelParagraph,\n ModelToDomContext,\n} from 'roosterjs-content-model-types';\n\nconst DefaultParagraphTag = 'div';\n\n/**\n * @internal\n */\nexport const handleParagraph: ContentModelBlockHandler<ContentModelParagraph> = (\n doc: Document,\n parent: Node,\n paragraph: ContentModelParagraph,\n context: ModelToDomContext,\n refNode: Node | null\n) => {\n let container = context.allowCacheElement ? paragraph.cachedElement : undefined;\n\n if (container && paragraph.segments.every(x => x.segmentType != 'General' && !x.isSelected)) {\n refNode = reuseCachedElement(parent, container, refNode);\n } else {\n stackFormat(context, paragraph.decorator?.tagName || null, () => {\n const needParagraphWrapper =\n !paragraph.isImplicit ||\n !!paragraph.decorator ||\n (getObjectKeys(paragraph.format).length > 0 &&\n paragraph.segments.some(segment => segment.segmentType != 'SelectionMarker'));\n const formatOnWrapper = needParagraphWrapper\n ? {\n ...(paragraph.decorator?.format || {}),\n ...paragraph.segmentFormat,\n }\n : {};\n\n container = doc.createElement(paragraph.decorator?.tagName || DefaultParagraphTag);\n\n parent.insertBefore(container, refNode);\n\n context.regularSelection.current = {\n block: needParagraphWrapper ? container : container.parentNode,\n segment: null,\n };\n\n const handleSegments = () => {\n const parent = container;\n\n if (parent) {\n const firstSegment = paragraph.segments[0];\n\n if (firstSegment?.segmentType == 'SelectionMarker') {\n // Make sure there is a segment created before selection marker.\n // If selection marker is the first selected segment in a paragraph, create a dummy text node,\n // so after rewrite, the regularSelection object can have a valid segment object set to the text node.\n context.modelHandlers.text(\n doc,\n parent,\n {\n ...firstSegment,\n segmentType: 'Text',\n text: '',\n },\n context,\n []\n );\n }\n\n paragraph.segments.forEach(segment => {\n const newSegments: Node[] = [];\n context.modelHandlers.segment(doc, parent, segment, context, newSegments);\n\n newSegments.forEach(node => {\n context.domIndexer?.onSegment(node, paragraph, [segment]);\n });\n });\n }\n };\n\n if (needParagraphWrapper) {\n stackFormat(context, formatOnWrapper, handleSegments);\n\n applyFormat(container, context.formatAppliers.block, paragraph.format, context);\n applyFormat(container, context.formatAppliers.container, paragraph.format, context);\n applyFormat(\n container,\n context.formatAppliers.segmentOnBlock,\n formatOnWrapper,\n context\n );\n } else {\n handleSegments();\n }\n\n optimize(container, context);\n\n // It is possible the next sibling node is changed during processing child segments\n // e.g. When this paragraph is an implicit paragraph and it contains an inline entity segment\n // The segment will be appended to container as child then the container will be removed\n // since this paragraph it is implicit. In that case container.nextSibling will become original\n // inline entity's next sibling. So reset refNode to its real next sibling (after change) here\n // to make sure the value is correct.\n refNode = container.nextSibling;\n\n if (container) {\n context.onNodeCreated?.(paragraph, container);\n context.domIndexer?.onParagraph(container);\n }\n\n if (needParagraphWrapper) {\n if (context.allowCacheElement) {\n paragraph.cachedElement = container;\n }\n } else {\n unwrap(container);\n container = undefined;\n }\n });\n }\n\n return refNode;\n};\n"]}
|
|
@@ -2,12 +2,13 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.optimize = void 0;
|
|
4
4
|
var entityUtils_1 = require("../../domUtils/entityUtils");
|
|
5
|
+
var isNodeOfType_1 = require("../../domUtils/isNodeOfType");
|
|
5
6
|
var mergeNode_1 = require("./mergeNode");
|
|
6
7
|
var removeUnnecessarySpan_1 = require("./removeUnnecessarySpan");
|
|
7
8
|
/**
|
|
8
9
|
* @internal
|
|
9
10
|
*/
|
|
10
|
-
function optimize(root) {
|
|
11
|
+
function optimize(root, context) {
|
|
11
12
|
/**
|
|
12
13
|
* Do no do any optimization to entity
|
|
13
14
|
*/
|
|
@@ -17,8 +18,46 @@ function optimize(root) {
|
|
|
17
18
|
(0, removeUnnecessarySpan_1.removeUnnecessarySpan)(root);
|
|
18
19
|
(0, mergeNode_1.mergeNode)(root);
|
|
19
20
|
for (var child = root.firstChild; child; child = child.nextSibling) {
|
|
20
|
-
optimize(child);
|
|
21
|
+
optimize(child, context);
|
|
21
22
|
}
|
|
23
|
+
normalizeTextNode(root, context);
|
|
22
24
|
}
|
|
23
25
|
exports.optimize = optimize;
|
|
26
|
+
// Merge continuous text nodes into one single node (same with normalize()),
|
|
27
|
+
// and update selection and dom indexes
|
|
28
|
+
function normalizeTextNode(root, context) {
|
|
29
|
+
var _a, _b, _c, _d;
|
|
30
|
+
var lastText = null;
|
|
31
|
+
var child;
|
|
32
|
+
var next;
|
|
33
|
+
var selection = context.regularSelection;
|
|
34
|
+
for (child = root.firstChild, next = child ? child.nextSibling : null; child; child = next, next = child ? child.nextSibling : null) {
|
|
35
|
+
if (!(0, isNodeOfType_1.isNodeOfType)(child, 'TEXT_NODE')) {
|
|
36
|
+
lastText = null;
|
|
37
|
+
}
|
|
38
|
+
else if (!lastText) {
|
|
39
|
+
lastText = child;
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
var originalLength = (_b = (_a = lastText.nodeValue) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0;
|
|
43
|
+
(_c = context.domIndexer) === null || _c === void 0 ? void 0 : _c.onMergeText(lastText, child);
|
|
44
|
+
lastText.nodeValue += (_d = child.nodeValue) !== null && _d !== void 0 ? _d : '';
|
|
45
|
+
if (selection) {
|
|
46
|
+
updateSelection(selection.start, lastText, child, originalLength);
|
|
47
|
+
updateSelection(selection.end, lastText, child, originalLength);
|
|
48
|
+
}
|
|
49
|
+
root.removeChild(child);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
function updateSelection(mark, lastText, nextText, lastTextOriginalLength) {
|
|
54
|
+
if (mark && mark.offset == undefined) {
|
|
55
|
+
if (mark.segment == lastText) {
|
|
56
|
+
mark.offset = lastTextOriginalLength;
|
|
57
|
+
}
|
|
58
|
+
else if (mark.segment == nextText) {
|
|
59
|
+
mark.segment = lastText;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
24
63
|
//# sourceMappingURL=optimize.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"optimize.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-dom/lib/modelToDom/optimizers/optimize.ts"],"names":[],"mappings":";;;AAAA,0DAA6D;AAC7D,yCAAwC;AACxC,iEAAgE;
|
|
1
|
+
{"version":3,"file":"optimize.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-dom/lib/modelToDom/optimizers/optimize.ts"],"names":[],"mappings":";;;AAAA,0DAA6D;AAC7D,4DAA2D;AAC3D,yCAAwC;AACxC,iEAAgE;AAMhE;;GAEG;AACH,SAAgB,QAAQ,CAAC,IAAU,EAAE,OAA0B;IAC3D;;OAEG;IACH,IAAI,IAAA,6BAAe,EAAC,IAAI,CAAC,EAAE;QACvB,OAAO;KACV;IAED,IAAA,6CAAqB,EAAC,IAAI,CAAC,CAAC;IAC5B,IAAA,qBAAS,EAAC,IAAI,CAAC,CAAC;IAEhB,KAAK,IAAI,KAAK,GAAG,IAAI,CAAC,UAAU,EAAE,KAAK,EAAE,KAAK,GAAG,KAAK,CAAC,WAAW,EAAE;QAChE,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;KAC5B;IAED,iBAAiB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;AACrC,CAAC;AAhBD,4BAgBC;AAED,4EAA4E;AAC5E,uCAAuC;AACvC,SAAS,iBAAiB,CAAC,IAAU,EAAE,OAA0B;;IAC7D,IAAI,QAAQ,GAAgB,IAAI,CAAC;IACjC,IAAI,KAAkB,CAAC;IACvB,IAAI,IAAiB,CAAC;IACtB,IAAM,SAAS,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAE3C,KACI,KAAK,GAAG,IAAI,CAAC,UAAU,EAAE,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,EAChE,KAAK,EACL,KAAK,GAAG,IAAI,EAAE,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,EACvD;QACE,IAAI,CAAC,IAAA,2BAAY,EAAC,KAAK,EAAE,WAAW,CAAC,EAAE;YACnC,QAAQ,GAAG,IAAI,CAAC;SACnB;aAAM,IAAI,CAAC,QAAQ,EAAE;YAClB,QAAQ,GAAG,KAAK,CAAC;SACpB;aAAM;YACH,IAAM,cAAc,GAAG,MAAA,MAAA,QAAQ,CAAC,SAAS,0CAAE,MAAM,mCAAI,CAAC,CAAC;YAEvD,MAAA,OAAO,CAAC,UAAU,0CAAE,WAAW,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;YACjD,QAAQ,CAAC,SAAS,IAAI,MAAA,KAAK,CAAC,SAAS,mCAAI,EAAE,CAAC;YAE5C,IAAI,SAAS,EAAE;gBACX,eAAe,CAAC,SAAS,CAAC,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,cAAc,CAAC,CAAC;gBAClE,eAAe,CAAC,SAAS,CAAC,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,cAAc,CAAC,CAAC;aACnE;YAED,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;SAC3B;KACJ;AACL,CAAC;AAED,SAAS,eAAe,CACpB,IAA+C,EAC/C,QAAc,EACd,QAAc,EACd,sBAA8B;IAE9B,IAAI,IAAI,IAAI,IAAI,CAAC,MAAM,IAAI,SAAS,EAAE;QAClC,IAAI,IAAI,CAAC,OAAO,IAAI,QAAQ,EAAE;YAC1B,IAAI,CAAC,MAAM,GAAG,sBAAsB,CAAC;SACxC;aAAM,IAAI,IAAI,CAAC,OAAO,IAAI,QAAQ,EAAE;YACjC,IAAI,CAAC,OAAO,GAAG,QAAQ,CAAC;SAC3B;KACJ;AACL,CAAC","sourcesContent":["import { isEntityElement } from '../../domUtils/entityUtils';\nimport { isNodeOfType } from '../../domUtils/isNodeOfType';\nimport { mergeNode } from './mergeNode';\nimport { removeUnnecessarySpan } from './removeUnnecessarySpan';\nimport type {\n ModelToDomBlockAndSegmentNode,\n ModelToDomContext,\n} from 'roosterjs-content-model-types';\n\n/**\n * @internal\n */\nexport function optimize(root: Node, context: ModelToDomContext) {\n /**\n * Do no do any optimization to entity\n */\n if (isEntityElement(root)) {\n return;\n }\n\n removeUnnecessarySpan(root);\n mergeNode(root);\n\n for (let child = root.firstChild; child; child = child.nextSibling) {\n optimize(child, context);\n }\n\n normalizeTextNode(root, context);\n}\n\n// Merge continuous text nodes into one single node (same with normalize()),\n// and update selection and dom indexes\nfunction normalizeTextNode(root: Node, context: ModelToDomContext) {\n let lastText: Text | null = null;\n let child: Node | null;\n let next: Node | null;\n const selection = context.regularSelection;\n\n for (\n child = root.firstChild, next = child ? child.nextSibling : null;\n child;\n child = next, next = child ? child.nextSibling : null\n ) {\n if (!isNodeOfType(child, 'TEXT_NODE')) {\n lastText = null;\n } else if (!lastText) {\n lastText = child;\n } else {\n const originalLength = lastText.nodeValue?.length ?? 0;\n\n context.domIndexer?.onMergeText(lastText, child);\n lastText.nodeValue += child.nodeValue ?? '';\n\n if (selection) {\n updateSelection(selection.start, lastText, child, originalLength);\n updateSelection(selection.end, lastText, child, originalLength);\n }\n\n root.removeChild(child);\n }\n }\n}\n\nfunction updateSelection(\n mark: ModelToDomBlockAndSegmentNode | undefined,\n lastText: Text,\n nextText: Text,\n lastTextOriginalLength: number\n) {\n if (mark && mark.offset == undefined) {\n if (mark.segment == lastText) {\n mark.offset = lastTextOriginalLength;\n } else if (mark.segment == nextText) {\n mark.segment = lastText;\n }\n }\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
define(["require", "exports", "../../domToModel/utils/areSameFormats", "../creators/createBr", "./isEmpty", "../../domUtils/isWhiteSpacePreserved", "./mutate", "./normalizeSegment"], function (require, exports, areSameFormats_1, createBr_1, isEmpty_1, isWhiteSpacePreserved_1, mutate_1, normalizeSegment_1) {
|
|
1
|
+
define(["require", "exports", "tslib", "../../domToModel/utils/areSameFormats", "../creators/createBr", "./isEmpty", "../../domUtils/isWhiteSpacePreserved", "./mutate", "./normalizeSegment"], function (require, exports, tslib_1, areSameFormats_1, createBr_1, isEmpty_1, isWhiteSpacePreserved_1, mutate_1, normalizeSegment_1) {
|
|
2
2
|
"use strict";
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
4
|
exports.normalizeParagraph = void 0;
|
|
@@ -31,6 +31,7 @@ define(["require", "exports", "../../domToModel/utils/areSameFormats", "../creat
|
|
|
31
31
|
}
|
|
32
32
|
removeEmptyLinks(paragraph);
|
|
33
33
|
removeEmptySegments(paragraph);
|
|
34
|
+
mergeTextSegments(paragraph);
|
|
34
35
|
moveUpSegmentFormat(paragraph);
|
|
35
36
|
}
|
|
36
37
|
exports.normalizeParagraph = normalizeParagraph;
|
|
@@ -48,6 +49,40 @@ define(["require", "exports", "../../domToModel/utils/areSameFormats", "../creat
|
|
|
48
49
|
}
|
|
49
50
|
}
|
|
50
51
|
}
|
|
52
|
+
function mergeTextSegments(block) {
|
|
53
|
+
var lastText = null;
|
|
54
|
+
for (var i = 0; i < block.segments.length; i++) {
|
|
55
|
+
var segment = block.segments[i];
|
|
56
|
+
if (segment.segmentType != 'Text') {
|
|
57
|
+
lastText = null;
|
|
58
|
+
}
|
|
59
|
+
else if (!lastText || !segmentsWithSameFormat(lastText, segment)) {
|
|
60
|
+
lastText = segment;
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
var _a = (0, tslib_1.__read)((0, mutate_1.mutateSegments)(block, [lastText, segment]), 2), mutableBlock = _a[0], _b = (0, tslib_1.__read)(_a[1], 1), mutableLastText = _b[0];
|
|
64
|
+
mutableLastText.text += segment.text;
|
|
65
|
+
mutableBlock.segments.splice(i, 1);
|
|
66
|
+
i--;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
function segmentsWithSameFormat(seg1, seg2) {
|
|
71
|
+
return (!!seg1.isSelected == !!seg2.isSelected &&
|
|
72
|
+
(0, areSameFormats_1.areSameFormats)(seg1.format, seg2.format) &&
|
|
73
|
+
areSameLinks(seg1.link, seg2.link) &&
|
|
74
|
+
areSameCodes(seg1.code, seg2.code));
|
|
75
|
+
}
|
|
76
|
+
function areSameLinks(link1, link2) {
|
|
77
|
+
return ((!link1 && !link2) ||
|
|
78
|
+
(link1 &&
|
|
79
|
+
link2 &&
|
|
80
|
+
(0, areSameFormats_1.areSameFormats)(link1.format, link2.format) &&
|
|
81
|
+
(0, areSameFormats_1.areSameFormats)(link1.dataset, link2.dataset)));
|
|
82
|
+
}
|
|
83
|
+
function areSameCodes(code1, code2) {
|
|
84
|
+
return (!code1 && !code2) || (code1 && code2 && (0, areSameFormats_1.areSameFormats)(code1.format, code2.format));
|
|
85
|
+
}
|
|
51
86
|
function removeEmptyLinks(paragraph) {
|
|
52
87
|
var marker = paragraph.segments.find(function (x) { return x.segmentType == 'SelectionMarker'; });
|
|
53
88
|
if (marker) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"normalizeParagraph.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-dom/lib/modelApi/common/normalizeParagraph.ts"],"names":[],"mappings":"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","sourcesContent":["import { areSameFormats } from '../../domToModel/utils/areSameFormats';\nimport { createBr } from '../creators/createBr';\nimport { isSegmentEmpty } from './isEmpty';\nimport { isWhiteSpacePreserved } from '../../domUtils/isWhiteSpacePreserved';\nimport { mutateBlock, mutateSegment } from './mutate';\nimport { normalizeAllSegments } from './normalizeSegment';\nimport type {\n ContentModelSegmentFormat,\n ReadonlyContentModelParagraph,\n ReadonlyContentModelSegment,\n} from 'roosterjs-content-model-types';\n\n/**\n * @param paragraph The paragraph to normalize\n * Normalize a paragraph. If it is empty, add a BR segment to make sure it can insert content\n */\nexport function normalizeParagraph(paragraph: ReadonlyContentModelParagraph) {\n const segments = paragraph.segments;\n\n if (!paragraph.isImplicit && segments.length > 0) {\n const last = segments[segments.length - 1];\n const secondLast = segments[segments.length - 2];\n\n if (\n last.segmentType == 'SelectionMarker' &&\n (!secondLast || secondLast.segmentType == 'Br')\n ) {\n mutateBlock(paragraph).segments.push(createBr(last.format));\n } else if (segments.length > 1 && segments[segments.length - 1].segmentType == 'Br') {\n const noMarkerSegments = segments.filter(x => x.segmentType != 'SelectionMarker');\n\n // When there is content with a <BR> tag at the end, we can remove the BR.\n // But if there are more than one <BR> at the end, do not remove them.\n if (\n noMarkerSegments.length > 1 &&\n noMarkerSegments[noMarkerSegments.length - 2].segmentType != 'Br'\n ) {\n mutateBlock(paragraph).segments.pop();\n }\n }\n\n normalizeParagraphStyle(paragraph);\n }\n\n if (!isWhiteSpacePreserved(paragraph.format.whiteSpace)) {\n normalizeAllSegments(paragraph);\n }\n\n removeEmptyLinks(paragraph);\n\n removeEmptySegments(paragraph);\n\n moveUpSegmentFormat(paragraph);\n}\n\nfunction normalizeParagraphStyle(paragraph: ReadonlyContentModelParagraph) {\n // New paragraph should not have white-space style\n if (\n paragraph.format.whiteSpace &&\n paragraph.segments.every(\n seg => seg.segmentType == 'Br' || seg.segmentType == 'SelectionMarker'\n )\n ) {\n delete mutateBlock(paragraph).format.whiteSpace;\n }\n}\n\nfunction removeEmptySegments(block: ReadonlyContentModelParagraph) {\n for (let j = block.segments.length - 1; j >= 0; j--) {\n if (isSegmentEmpty(block.segments[j])) {\n mutateBlock(block).segments.splice(j, 1);\n }\n }\n}\n\nfunction removeEmptyLinks(paragraph: ReadonlyContentModelParagraph) {\n const marker = paragraph.segments.find(x => x.segmentType == 'SelectionMarker');\n if (marker) {\n const markerIndex = paragraph.segments.indexOf(marker);\n const prev = paragraph.segments[markerIndex - 1];\n const next = paragraph.segments[markerIndex + 1];\n\n if (\n (prev &&\n !prev.link &&\n areSameFormats(prev.format, marker.format) &&\n (!next || (!next.link && areSameFormats(next.format, marker.format))) &&\n marker.link) ||\n (!prev &&\n marker.link &&\n next &&\n !next.link &&\n areSameFormats(next.format, marker.format))\n ) {\n mutateSegment(paragraph, marker, mutableMarker => {\n delete mutableMarker.link;\n });\n }\n }\n}\n\ntype FormatsToMoveUp = 'fontFamily' | 'fontSize' | 'textColor';\nconst formatsToMoveUp: FormatsToMoveUp[] = ['fontFamily', 'fontSize', 'textColor'];\n\n// When all segments are sharing the same segment format (font name, size and color), we can move its format to paragraph\nfunction moveUpSegmentFormat(paragraph: ReadonlyContentModelParagraph) {\n if (!paragraph.decorator) {\n const segments = paragraph.segments.filter(x => x.segmentType != 'SelectionMarker');\n const target = paragraph.segmentFormat || {};\n let changed = false;\n\n formatsToMoveUp.forEach(key => {\n changed = internalMoveUpSegmentFormat(segments, target, key) || changed;\n });\n\n if (changed) {\n mutateBlock(paragraph).segmentFormat = target;\n }\n }\n}\n\nfunction internalMoveUpSegmentFormat(\n segments: ReadonlyContentModelSegment[],\n target: ContentModelSegmentFormat,\n formatKey: FormatsToMoveUp\n): boolean {\n const firstFormat = segments[0]?.format;\n\n if (\n firstFormat?.[formatKey] &&\n segments.every(segment => segment.format[formatKey] == firstFormat[formatKey]) &&\n target[formatKey] != firstFormat[formatKey]\n ) {\n target[formatKey] = firstFormat[formatKey];\n return true;\n } else {\n return false;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"normalizeParagraph.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-dom/lib/modelApi/common/normalizeParagraph.ts"],"names":[],"mappings":"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","sourcesContent":["import { areSameFormats } from '../../domToModel/utils/areSameFormats';\nimport { createBr } from '../creators/createBr';\nimport { isSegmentEmpty } from './isEmpty';\nimport { isWhiteSpacePreserved } from '../../domUtils/isWhiteSpacePreserved';\nimport { mutateBlock, mutateSegment, mutateSegments } from './mutate';\nimport { normalizeAllSegments } from './normalizeSegment';\nimport type {\n ContentModelSegmentFormat,\n ContentModelText,\n ReadonlyContentModelCode,\n ReadonlyContentModelLink,\n ReadonlyContentModelParagraph,\n ReadonlyContentModelSegment,\n ReadonlyContentModelText,\n} from 'roosterjs-content-model-types';\n\n/**\n * @param paragraph The paragraph to normalize\n * Normalize a paragraph. If it is empty, add a BR segment to make sure it can insert content\n */\nexport function normalizeParagraph(paragraph: ReadonlyContentModelParagraph) {\n const segments = paragraph.segments;\n\n if (!paragraph.isImplicit && segments.length > 0) {\n const last = segments[segments.length - 1];\n const secondLast = segments[segments.length - 2];\n\n if (\n last.segmentType == 'SelectionMarker' &&\n (!secondLast || secondLast.segmentType == 'Br')\n ) {\n mutateBlock(paragraph).segments.push(createBr(last.format));\n } else if (segments.length > 1 && segments[segments.length - 1].segmentType == 'Br') {\n const noMarkerSegments = segments.filter(x => x.segmentType != 'SelectionMarker');\n\n // When there is content with a <BR> tag at the end, we can remove the BR.\n // But if there are more than one <BR> at the end, do not remove them.\n if (\n noMarkerSegments.length > 1 &&\n noMarkerSegments[noMarkerSegments.length - 2].segmentType != 'Br'\n ) {\n mutateBlock(paragraph).segments.pop();\n }\n }\n\n normalizeParagraphStyle(paragraph);\n }\n\n if (!isWhiteSpacePreserved(paragraph.format.whiteSpace)) {\n normalizeAllSegments(paragraph);\n }\n\n removeEmptyLinks(paragraph);\n removeEmptySegments(paragraph);\n mergeTextSegments(paragraph);\n moveUpSegmentFormat(paragraph);\n}\n\nfunction normalizeParagraphStyle(paragraph: ReadonlyContentModelParagraph) {\n // New paragraph should not have white-space style\n if (\n paragraph.format.whiteSpace &&\n paragraph.segments.every(\n seg => seg.segmentType == 'Br' || seg.segmentType == 'SelectionMarker'\n )\n ) {\n delete mutateBlock(paragraph).format.whiteSpace;\n }\n}\n\nfunction removeEmptySegments(block: ReadonlyContentModelParagraph) {\n for (let j = block.segments.length - 1; j >= 0; j--) {\n if (isSegmentEmpty(block.segments[j])) {\n mutateBlock(block).segments.splice(j, 1);\n }\n }\n}\n\nfunction mergeTextSegments(block: ReadonlyContentModelParagraph) {\n let lastText: ReadonlyContentModelText | null = null;\n\n for (let i = 0; i < block.segments.length; i++) {\n const segment = block.segments[i];\n\n if (segment.segmentType != 'Text') {\n lastText = null;\n } else if (!lastText || !segmentsWithSameFormat(lastText, segment)) {\n lastText = segment;\n } else {\n const [mutableBlock, [mutableLastText]] = mutateSegments(block, [lastText, segment]);\n\n (mutableLastText as ContentModelText).text += segment.text;\n mutableBlock.segments.splice(i, 1);\n i--;\n }\n }\n}\n\nfunction segmentsWithSameFormat(\n seg1: ReadonlyContentModelSegment,\n seg2: ReadonlyContentModelSegment\n) {\n return (\n !!seg1.isSelected == !!seg2.isSelected &&\n areSameFormats(seg1.format, seg2.format) &&\n areSameLinks(seg1.link, seg2.link) &&\n areSameCodes(seg1.code, seg2.code)\n );\n}\n\nfunction areSameLinks(\n link1: ReadonlyContentModelLink | undefined,\n link2: ReadonlyContentModelLink | undefined\n) {\n return (\n (!link1 && !link2) ||\n (link1 &&\n link2 &&\n areSameFormats(link1.format, link2.format) &&\n areSameFormats(link1.dataset, link2.dataset))\n );\n}\n\nfunction areSameCodes(\n code1: ReadonlyContentModelCode | undefined,\n code2: ReadonlyContentModelCode | undefined\n) {\n return (!code1 && !code2) || (code1 && code2 && areSameFormats(code1.format, code2.format));\n}\n\nfunction removeEmptyLinks(paragraph: ReadonlyContentModelParagraph) {\n const marker = paragraph.segments.find(x => x.segmentType == 'SelectionMarker');\n if (marker) {\n const markerIndex = paragraph.segments.indexOf(marker);\n const prev = paragraph.segments[markerIndex - 1];\n const next = paragraph.segments[markerIndex + 1];\n\n if (\n (prev &&\n !prev.link &&\n areSameFormats(prev.format, marker.format) &&\n (!next || (!next.link && areSameFormats(next.format, marker.format))) &&\n marker.link) ||\n (!prev &&\n marker.link &&\n next &&\n !next.link &&\n areSameFormats(next.format, marker.format))\n ) {\n mutateSegment(paragraph, marker, mutableMarker => {\n delete mutableMarker.link;\n });\n }\n }\n}\n\ntype FormatsToMoveUp = 'fontFamily' | 'fontSize' | 'textColor';\nconst formatsToMoveUp: FormatsToMoveUp[] = ['fontFamily', 'fontSize', 'textColor'];\n\n// When all segments are sharing the same segment format (font name, size and color), we can move its format to paragraph\nfunction moveUpSegmentFormat(paragraph: ReadonlyContentModelParagraph) {\n if (!paragraph.decorator) {\n const segments = paragraph.segments.filter(x => x.segmentType != 'SelectionMarker');\n const target = paragraph.segmentFormat || {};\n let changed = false;\n\n formatsToMoveUp.forEach(key => {\n changed = internalMoveUpSegmentFormat(segments, target, key) || changed;\n });\n\n if (changed) {\n mutateBlock(paragraph).segmentFormat = target;\n }\n }\n}\n\nfunction internalMoveUpSegmentFormat(\n segments: ReadonlyContentModelSegment[],\n target: ContentModelSegmentFormat,\n formatKey: FormatsToMoveUp\n): boolean {\n const firstFormat = segments[0]?.format;\n\n if (\n firstFormat?.[formatKey] &&\n segments.every(segment => segment.format[formatKey] == firstFormat[formatKey]) &&\n target[formatKey] != firstFormat[formatKey]\n ) {\n target[formatKey] = firstFormat[formatKey];\n return true;\n } else {\n return false;\n }\n}\n"]}
|
|
@@ -51,14 +51,17 @@ define(["require", "exports", "../domUtils/isNodeOfType", "../domUtils/toArray"]
|
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
53
|
function calcPosition(pos) {
|
|
54
|
-
var _a, _b, _c;
|
|
54
|
+
var _a, _b, _c, _d, _e;
|
|
55
55
|
var result;
|
|
56
56
|
if (pos.block) {
|
|
57
57
|
if (!pos.segment) {
|
|
58
58
|
result = { container: pos.block, offset: 0 };
|
|
59
59
|
}
|
|
60
60
|
else if ((0, isNodeOfType_1.isNodeOfType)(pos.segment, 'TEXT_NODE')) {
|
|
61
|
-
result = {
|
|
61
|
+
result = {
|
|
62
|
+
container: pos.segment,
|
|
63
|
+
offset: (_c = (_a = pos.offset) !== null && _a !== void 0 ? _a : (_b = pos.segment.nodeValue) === null || _b === void 0 ? void 0 : _b.length) !== null && _c !== void 0 ? _c : 0,
|
|
64
|
+
};
|
|
62
65
|
}
|
|
63
66
|
else if (pos.segment.parentNode) {
|
|
64
67
|
result = {
|
|
@@ -77,7 +80,7 @@ define(["require", "exports", "../domUtils/isNodeOfType", "../domUtils/toArray"]
|
|
|
77
80
|
result = {
|
|
78
81
|
container: container,
|
|
79
82
|
offset: (0, isNodeOfType_1.isNodeOfType)(container, 'TEXT_NODE')
|
|
80
|
-
? (
|
|
83
|
+
? (_e = (_d = container.nodeValue) === null || _d === void 0 ? void 0 : _d.length) !== null && _e !== void 0 ? _e : 0
|
|
81
84
|
: container.childNodes.length,
|
|
82
85
|
};
|
|
83
86
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contentModelToDom.js","sourceRoot":"","sources":["../../../../packages/roosterjs-content-model-dom/lib/modelToDom/contentModelToDom.ts"],"names":[],"mappings":";;;;IAUA;;;;;;;;;OASG;IACH,SAAgB,iBAAiB,CAC7B,GAAa,EACb,IAAU,EACV,KAA2B,EAC3B,OAA0B;QAE1B,OAAO,CAAC,aAAa,CAAC,kBAAkB,CAAC,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;QAEpE,IAAM,KAAK,GAAG,qBAAqB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QAElD,IAAI,KAAK,CAAC,yBAAyB,IAAI,CAAA,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,IAAI,KAAI,OAAO,EAAE;YAC3D,KAAK,CAAC,UAAU,GAAG,IAAI,CAAC;SAC3B;QAED,IAAI,OAAO,CAAC,UAAU,IAAI,OAAO,CAAC,iBAAiB,EAAE;YAChD,KAAgD,CAAC,YAAY,GAAG,IAAI,CAAC;SACzE;QAED,IAAI,CAAC,SAAS,EAAE,CAAC;QAEjB,OAAO,KAAK,CAAC;IACjB,CAAC;IArBD,8CAqBC;IAED,SAAS,qBAAqB,CAAC,GAAa,EAAE,OAA0B;QAEhE,IAAA,KAGA,OAAO,iBAHyB,EAAZ,KAAK,WAAA,EAAE,GAAG,SAAA,EAC9B,cAAc,GAEd,OAAO,eAFO,EACd,cAAc,GACd,OAAO,eADO,CACN;QAEZ,IAAI,aAA8D,CAAC;QACnE,IAAI,WAA4D,CAAC;QAEjE,IAAI,cAAc,EAAE;YAChB,OAAO,cAAc,CAAC;SACzB;aAAM,IACH,CAAC,aAAa,GAAG,KAAK,IAAI,YAAY,CAAC,KAAK,CAAC,CAAC;YAC9C,CAAC,WAAW,GAAG,GAAG,IAAI,YAAY,CAAC,GAAG,CAAC,CAAC,EAC1C;YACE,IAAM,KAAK,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC;YAEhC,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,SAAS,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;YAC9D,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC,SAAS,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;YAExD,OAAO;gBACH,IAAI,EAAE,OAAO;gBACb,KAAK,OAAA;gBACL,UAAU,EAAE,KAAK;aACpB,CAAC;SACL;aAAM,IAAI,cAAc,EAAE;YACvB,OAAO,cAAc,CAAC;SACzB;aAAM;YACH,OAAO,IAAI,CAAC;SACf;IACL,CAAC;IAED,SAAS,YAAY,CACjB,GAAkC;;QAElC,IAAI,MAAuD,CAAC;QAE5D,IAAI,GAAG,CAAC,KAAK,EAAE;YACX,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE;gBACd,MAAM,GAAG,EAAE,SAAS,EAAE,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;aAChD;iBAAM,IAAI,IAAA,2BAAY,EAAC,GAAG,CAAC,OAAO,EAAE,WAAW,CAAC,EAAE;gBAC/C,MAAM,GAAG,
|
|
1
|
+
{"version":3,"file":"contentModelToDom.js","sourceRoot":"","sources":["../../../../packages/roosterjs-content-model-dom/lib/modelToDom/contentModelToDom.ts"],"names":[],"mappings":"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","sourcesContent":["import { isNodeOfType } from '../domUtils/isNodeOfType';\nimport { toArray } from '../domUtils/toArray';\nimport type { ContentModelDocumentWithPersistedCache } from '../modelApi/selection/iterateSelections';\nimport type {\n ContentModelDocument,\n DOMSelection,\n ModelToDomBlockAndSegmentNode,\n ModelToDomContext,\n} from 'roosterjs-content-model-types';\n\n/**\n * Create DOM tree fragment from Content Model document\n * @param doc Document object of the target DOM tree\n * @param root Target node that will become the container of new DOM tree.\n * When a DOM node with existing node is passed, it will be merged with content model so that unchanged blocks\n * won't be touched.\n * @param model The content model document to generate DOM tree from\n * @param context The context object for Content Model to DOM conversion\n * @returns The selection range created in DOM tree from this model, or null when there is no selection\n */\nexport function contentModelToDom(\n doc: Document,\n root: Node,\n model: ContentModelDocument,\n context: ModelToDomContext\n): DOMSelection | null {\n context.modelHandlers.blockGroupChildren(doc, root, model, context);\n\n const range = extractSelectionRange(doc, context);\n\n if (model.hasRevertedRangeSelection && range?.type == 'range') {\n range.isReverted = true;\n }\n\n if (context.domIndexer && context.allowCacheElement) {\n (model as ContentModelDocumentWithPersistedCache).persistCache = true;\n }\n\n root.normalize();\n\n return range;\n}\n\nfunction extractSelectionRange(doc: Document, context: ModelToDomContext): DOMSelection | null {\n const {\n regularSelection: { start, end },\n tableSelection,\n imageSelection,\n } = context;\n\n let startPosition: { container: Node; offset: number } | undefined;\n let endPosition: { container: Node; offset: number } | undefined;\n\n if (imageSelection) {\n return imageSelection;\n } else if (\n (startPosition = start && calcPosition(start)) &&\n (endPosition = end && calcPosition(end))\n ) {\n const range = doc.createRange();\n\n range.setStart(startPosition.container, startPosition.offset);\n range.setEnd(endPosition.container, endPosition.offset);\n\n return {\n type: 'range',\n range,\n isReverted: false,\n };\n } else if (tableSelection) {\n return tableSelection;\n } else {\n return null;\n }\n}\n\nfunction calcPosition(\n pos: ModelToDomBlockAndSegmentNode\n): { container: Node; offset: number } | undefined {\n let result: { container: Node; offset: number } | undefined;\n\n if (pos.block) {\n if (!pos.segment) {\n result = { container: pos.block, offset: 0 };\n } else if (isNodeOfType(pos.segment, 'TEXT_NODE')) {\n result = {\n container: pos.segment,\n offset: pos.offset ?? pos.segment.nodeValue?.length ?? 0,\n };\n } else if (pos.segment.parentNode) {\n result = {\n container: pos.segment.parentNode,\n offset:\n toArray(pos.segment.parentNode.childNodes as NodeListOf<Node>).indexOf(\n pos.segment\n ) + 1,\n };\n }\n }\n\n if (result && isNodeOfType(result.container, 'DOCUMENT_FRAGMENT_NODE')) {\n const childNodes = result.container.childNodes;\n\n if (childNodes.length > result.offset) {\n result = { container: childNodes[result.offset], offset: 0 };\n } else if (result.container.lastChild) {\n const container = result.container.lastChild;\n result = {\n container,\n offset: isNodeOfType(container, 'TEXT_NODE')\n ? container.nodeValue?.length ?? 0\n : container.childNodes.length,\n };\n } else {\n result = undefined;\n }\n }\n\n return result;\n}\n"]}
|
|
@@ -56,7 +56,7 @@ define(["require", "exports", "tslib", "../utils/applyFormat", "../../domUtils/g
|
|
|
56
56
|
else {
|
|
57
57
|
handleSegments();
|
|
58
58
|
}
|
|
59
|
-
(0, optimize_1.optimize)(container);
|
|
59
|
+
(0, optimize_1.optimize)(container, context);
|
|
60
60
|
// It is possible the next sibling node is changed during processing child segments
|
|
61
61
|
// e.g. When this paragraph is an implicit paragraph and it contains an inline entity segment
|
|
62
62
|
// The segment will be appended to container as child then the container will be removed
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handleParagraph.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-dom/lib/modelToDom/handlers/handleParagraph.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"handleParagraph.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-dom/lib/modelToDom/handlers/handleParagraph.ts"],"names":[],"mappings":"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","sourcesContent":["import { applyFormat } from '../utils/applyFormat';\nimport { getObjectKeys } from '../../domUtils/getObjectKeys';\nimport { optimize } from '../optimizers/optimize';\nimport { reuseCachedElement } from '../../domUtils/reuseCachedElement';\nimport { stackFormat } from '../utils/stackFormat';\nimport { unwrap } from '../../domUtils/unwrap';\nimport type {\n ContentModelBlockHandler,\n ContentModelParagraph,\n ModelToDomContext,\n} from 'roosterjs-content-model-types';\n\nconst DefaultParagraphTag = 'div';\n\n/**\n * @internal\n */\nexport const handleParagraph: ContentModelBlockHandler<ContentModelParagraph> = (\n doc: Document,\n parent: Node,\n paragraph: ContentModelParagraph,\n context: ModelToDomContext,\n refNode: Node | null\n) => {\n let container = context.allowCacheElement ? paragraph.cachedElement : undefined;\n\n if (container && paragraph.segments.every(x => x.segmentType != 'General' && !x.isSelected)) {\n refNode = reuseCachedElement(parent, container, refNode);\n } else {\n stackFormat(context, paragraph.decorator?.tagName || null, () => {\n const needParagraphWrapper =\n !paragraph.isImplicit ||\n !!paragraph.decorator ||\n (getObjectKeys(paragraph.format).length > 0 &&\n paragraph.segments.some(segment => segment.segmentType != 'SelectionMarker'));\n const formatOnWrapper = needParagraphWrapper\n ? {\n ...(paragraph.decorator?.format || {}),\n ...paragraph.segmentFormat,\n }\n : {};\n\n container = doc.createElement(paragraph.decorator?.tagName || DefaultParagraphTag);\n\n parent.insertBefore(container, refNode);\n\n context.regularSelection.current = {\n block: needParagraphWrapper ? container : container.parentNode,\n segment: null,\n };\n\n const handleSegments = () => {\n const parent = container;\n\n if (parent) {\n const firstSegment = paragraph.segments[0];\n\n if (firstSegment?.segmentType == 'SelectionMarker') {\n // Make sure there is a segment created before selection marker.\n // If selection marker is the first selected segment in a paragraph, create a dummy text node,\n // so after rewrite, the regularSelection object can have a valid segment object set to the text node.\n context.modelHandlers.text(\n doc,\n parent,\n {\n ...firstSegment,\n segmentType: 'Text',\n text: '',\n },\n context,\n []\n );\n }\n\n paragraph.segments.forEach(segment => {\n const newSegments: Node[] = [];\n context.modelHandlers.segment(doc, parent, segment, context, newSegments);\n\n newSegments.forEach(node => {\n context.domIndexer?.onSegment(node, paragraph, [segment]);\n });\n });\n }\n };\n\n if (needParagraphWrapper) {\n stackFormat(context, formatOnWrapper, handleSegments);\n\n applyFormat(container, context.formatAppliers.block, paragraph.format, context);\n applyFormat(container, context.formatAppliers.container, paragraph.format, context);\n applyFormat(\n container,\n context.formatAppliers.segmentOnBlock,\n formatOnWrapper,\n context\n );\n } else {\n handleSegments();\n }\n\n optimize(container, context);\n\n // It is possible the next sibling node is changed during processing child segments\n // e.g. When this paragraph is an implicit paragraph and it contains an inline entity segment\n // The segment will be appended to container as child then the container will be removed\n // since this paragraph it is implicit. In that case container.nextSibling will become original\n // inline entity's next sibling. So reset refNode to its real next sibling (after change) here\n // to make sure the value is correct.\n refNode = container.nextSibling;\n\n if (container) {\n context.onNodeCreated?.(paragraph, container);\n context.domIndexer?.onParagraph(container);\n }\n\n if (needParagraphWrapper) {\n if (context.allowCacheElement) {\n paragraph.cachedElement = container;\n }\n } else {\n unwrap(container);\n container = undefined;\n }\n });\n }\n\n return refNode;\n};\n"]}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
define(["require", "exports", "../../domUtils/entityUtils", "./mergeNode", "./removeUnnecessarySpan"], function (require, exports, entityUtils_1, mergeNode_1, removeUnnecessarySpan_1) {
|
|
1
|
+
define(["require", "exports", "../../domUtils/entityUtils", "../../domUtils/isNodeOfType", "./mergeNode", "./removeUnnecessarySpan"], function (require, exports, entityUtils_1, isNodeOfType_1, mergeNode_1, removeUnnecessarySpan_1) {
|
|
2
2
|
"use strict";
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
4
|
exports.optimize = void 0;
|
|
5
5
|
/**
|
|
6
6
|
* @internal
|
|
7
7
|
*/
|
|
8
|
-
function optimize(root) {
|
|
8
|
+
function optimize(root, context) {
|
|
9
9
|
/**
|
|
10
10
|
* Do no do any optimization to entity
|
|
11
11
|
*/
|
|
@@ -15,9 +15,47 @@ define(["require", "exports", "../../domUtils/entityUtils", "./mergeNode", "./re
|
|
|
15
15
|
(0, removeUnnecessarySpan_1.removeUnnecessarySpan)(root);
|
|
16
16
|
(0, mergeNode_1.mergeNode)(root);
|
|
17
17
|
for (var child = root.firstChild; child; child = child.nextSibling) {
|
|
18
|
-
optimize(child);
|
|
18
|
+
optimize(child, context);
|
|
19
19
|
}
|
|
20
|
+
normalizeTextNode(root, context);
|
|
20
21
|
}
|
|
21
22
|
exports.optimize = optimize;
|
|
23
|
+
// Merge continuous text nodes into one single node (same with normalize()),
|
|
24
|
+
// and update selection and dom indexes
|
|
25
|
+
function normalizeTextNode(root, context) {
|
|
26
|
+
var _a, _b, _c, _d;
|
|
27
|
+
var lastText = null;
|
|
28
|
+
var child;
|
|
29
|
+
var next;
|
|
30
|
+
var selection = context.regularSelection;
|
|
31
|
+
for (child = root.firstChild, next = child ? child.nextSibling : null; child; child = next, next = child ? child.nextSibling : null) {
|
|
32
|
+
if (!(0, isNodeOfType_1.isNodeOfType)(child, 'TEXT_NODE')) {
|
|
33
|
+
lastText = null;
|
|
34
|
+
}
|
|
35
|
+
else if (!lastText) {
|
|
36
|
+
lastText = child;
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
var originalLength = (_b = (_a = lastText.nodeValue) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0;
|
|
40
|
+
(_c = context.domIndexer) === null || _c === void 0 ? void 0 : _c.onMergeText(lastText, child);
|
|
41
|
+
lastText.nodeValue += (_d = child.nodeValue) !== null && _d !== void 0 ? _d : '';
|
|
42
|
+
if (selection) {
|
|
43
|
+
updateSelection(selection.start, lastText, child, originalLength);
|
|
44
|
+
updateSelection(selection.end, lastText, child, originalLength);
|
|
45
|
+
}
|
|
46
|
+
root.removeChild(child);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
function updateSelection(mark, lastText, nextText, lastTextOriginalLength) {
|
|
51
|
+
if (mark && mark.offset == undefined) {
|
|
52
|
+
if (mark.segment == lastText) {
|
|
53
|
+
mark.offset = lastTextOriginalLength;
|
|
54
|
+
}
|
|
55
|
+
else if (mark.segment == nextText) {
|
|
56
|
+
mark.segment = lastText;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
22
60
|
});
|
|
23
61
|
//# sourceMappingURL=optimize.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"optimize.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-dom/lib/modelToDom/optimizers/optimize.ts"],"names":[],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"optimize.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-dom/lib/modelToDom/optimizers/optimize.ts"],"names":[],"mappings":";;;;IASA;;OAEG;IACH,SAAgB,QAAQ,CAAC,IAAU,EAAE,OAA0B;QAC3D;;WAEG;QACH,IAAI,IAAA,6BAAe,EAAC,IAAI,CAAC,EAAE;YACvB,OAAO;SACV;QAED,IAAA,6CAAqB,EAAC,IAAI,CAAC,CAAC;QAC5B,IAAA,qBAAS,EAAC,IAAI,CAAC,CAAC;QAEhB,KAAK,IAAI,KAAK,GAAG,IAAI,CAAC,UAAU,EAAE,KAAK,EAAE,KAAK,GAAG,KAAK,CAAC,WAAW,EAAE;YAChE,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;SAC5B;QAED,iBAAiB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACrC,CAAC;IAhBD,4BAgBC;IAED,4EAA4E;IAC5E,uCAAuC;IACvC,SAAS,iBAAiB,CAAC,IAAU,EAAE,OAA0B;;QAC7D,IAAI,QAAQ,GAAgB,IAAI,CAAC;QACjC,IAAI,KAAkB,CAAC;QACvB,IAAI,IAAiB,CAAC;QACtB,IAAM,SAAS,GAAG,OAAO,CAAC,gBAAgB,CAAC;QAE3C,KACI,KAAK,GAAG,IAAI,CAAC,UAAU,EAAE,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,EAChE,KAAK,EACL,KAAK,GAAG,IAAI,EAAE,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,EACvD;YACE,IAAI,CAAC,IAAA,2BAAY,EAAC,KAAK,EAAE,WAAW,CAAC,EAAE;gBACnC,QAAQ,GAAG,IAAI,CAAC;aACnB;iBAAM,IAAI,CAAC,QAAQ,EAAE;gBAClB,QAAQ,GAAG,KAAK,CAAC;aACpB;iBAAM;gBACH,IAAM,cAAc,GAAG,MAAA,MAAA,QAAQ,CAAC,SAAS,0CAAE,MAAM,mCAAI,CAAC,CAAC;gBAEvD,MAAA,OAAO,CAAC,UAAU,0CAAE,WAAW,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;gBACjD,QAAQ,CAAC,SAAS,IAAI,MAAA,KAAK,CAAC,SAAS,mCAAI,EAAE,CAAC;gBAE5C,IAAI,SAAS,EAAE;oBACX,eAAe,CAAC,SAAS,CAAC,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,cAAc,CAAC,CAAC;oBAClE,eAAe,CAAC,SAAS,CAAC,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,cAAc,CAAC,CAAC;iBACnE;gBAED,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;aAC3B;SACJ;IACL,CAAC;IAED,SAAS,eAAe,CACpB,IAA+C,EAC/C,QAAc,EACd,QAAc,EACd,sBAA8B;QAE9B,IAAI,IAAI,IAAI,IAAI,CAAC,MAAM,IAAI,SAAS,EAAE;YAClC,IAAI,IAAI,CAAC,OAAO,IAAI,QAAQ,EAAE;gBAC1B,IAAI,CAAC,MAAM,GAAG,sBAAsB,CAAC;aACxC;iBAAM,IAAI,IAAI,CAAC,OAAO,IAAI,QAAQ,EAAE;gBACjC,IAAI,CAAC,OAAO,GAAG,QAAQ,CAAC;aAC3B;SACJ;IACL,CAAC","sourcesContent":["import { isEntityElement } from '../../domUtils/entityUtils';\nimport { isNodeOfType } from '../../domUtils/isNodeOfType';\nimport { mergeNode } from './mergeNode';\nimport { removeUnnecessarySpan } from './removeUnnecessarySpan';\nimport type {\n ModelToDomBlockAndSegmentNode,\n ModelToDomContext,\n} from 'roosterjs-content-model-types';\n\n/**\n * @internal\n */\nexport function optimize(root: Node, context: ModelToDomContext) {\n /**\n * Do no do any optimization to entity\n */\n if (isEntityElement(root)) {\n return;\n }\n\n removeUnnecessarySpan(root);\n mergeNode(root);\n\n for (let child = root.firstChild; child; child = child.nextSibling) {\n optimize(child, context);\n }\n\n normalizeTextNode(root, context);\n}\n\n// Merge continuous text nodes into one single node (same with normalize()),\n// and update selection and dom indexes\nfunction normalizeTextNode(root: Node, context: ModelToDomContext) {\n let lastText: Text | null = null;\n let child: Node | null;\n let next: Node | null;\n const selection = context.regularSelection;\n\n for (\n child = root.firstChild, next = child ? child.nextSibling : null;\n child;\n child = next, next = child ? child.nextSibling : null\n ) {\n if (!isNodeOfType(child, 'TEXT_NODE')) {\n lastText = null;\n } else if (!lastText) {\n lastText = child;\n } else {\n const originalLength = lastText.nodeValue?.length ?? 0;\n\n context.domIndexer?.onMergeText(lastText, child);\n lastText.nodeValue += child.nodeValue ?? '';\n\n if (selection) {\n updateSelection(selection.start, lastText, child, originalLength);\n updateSelection(selection.end, lastText, child, originalLength);\n }\n\n root.removeChild(child);\n }\n }\n}\n\nfunction updateSelection(\n mark: ModelToDomBlockAndSegmentNode | undefined,\n lastText: Text,\n nextText: Text,\n lastTextOriginalLength: number\n) {\n if (mark && mark.offset == undefined) {\n if (mark.segment == lastText) {\n mark.offset = lastTextOriginalLength;\n } else if (mark.segment == nextText) {\n mark.segment = lastText;\n }\n }\n}\n"]}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import { __read } from "tslib";
|
|
1
2
|
import { areSameFormats } from '../../domToModel/utils/areSameFormats';
|
|
2
3
|
import { createBr } from '../creators/createBr';
|
|
3
4
|
import { isSegmentEmpty } from './isEmpty';
|
|
4
5
|
import { isWhiteSpacePreserved } from '../../domUtils/isWhiteSpacePreserved';
|
|
5
|
-
import { mutateBlock, mutateSegment } from './mutate';
|
|
6
|
+
import { mutateBlock, mutateSegment, mutateSegments } from './mutate';
|
|
6
7
|
import { normalizeAllSegments } from './normalizeSegment';
|
|
7
8
|
/**
|
|
8
9
|
* @param paragraph The paragraph to normalize
|
|
@@ -33,6 +34,7 @@ export function normalizeParagraph(paragraph) {
|
|
|
33
34
|
}
|
|
34
35
|
removeEmptyLinks(paragraph);
|
|
35
36
|
removeEmptySegments(paragraph);
|
|
37
|
+
mergeTextSegments(paragraph);
|
|
36
38
|
moveUpSegmentFormat(paragraph);
|
|
37
39
|
}
|
|
38
40
|
function normalizeParagraphStyle(paragraph) {
|
|
@@ -49,6 +51,40 @@ function removeEmptySegments(block) {
|
|
|
49
51
|
}
|
|
50
52
|
}
|
|
51
53
|
}
|
|
54
|
+
function mergeTextSegments(block) {
|
|
55
|
+
var lastText = null;
|
|
56
|
+
for (var i = 0; i < block.segments.length; i++) {
|
|
57
|
+
var segment = block.segments[i];
|
|
58
|
+
if (segment.segmentType != 'Text') {
|
|
59
|
+
lastText = null;
|
|
60
|
+
}
|
|
61
|
+
else if (!lastText || !segmentsWithSameFormat(lastText, segment)) {
|
|
62
|
+
lastText = segment;
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
var _a = __read(mutateSegments(block, [lastText, segment]), 2), mutableBlock = _a[0], _b = __read(_a[1], 1), mutableLastText = _b[0];
|
|
66
|
+
mutableLastText.text += segment.text;
|
|
67
|
+
mutableBlock.segments.splice(i, 1);
|
|
68
|
+
i--;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
function segmentsWithSameFormat(seg1, seg2) {
|
|
73
|
+
return (!!seg1.isSelected == !!seg2.isSelected &&
|
|
74
|
+
areSameFormats(seg1.format, seg2.format) &&
|
|
75
|
+
areSameLinks(seg1.link, seg2.link) &&
|
|
76
|
+
areSameCodes(seg1.code, seg2.code));
|
|
77
|
+
}
|
|
78
|
+
function areSameLinks(link1, link2) {
|
|
79
|
+
return ((!link1 && !link2) ||
|
|
80
|
+
(link1 &&
|
|
81
|
+
link2 &&
|
|
82
|
+
areSameFormats(link1.format, link2.format) &&
|
|
83
|
+
areSameFormats(link1.dataset, link2.dataset)));
|
|
84
|
+
}
|
|
85
|
+
function areSameCodes(code1, code2) {
|
|
86
|
+
return (!code1 && !code2) || (code1 && code2 && areSameFormats(code1.format, code2.format));
|
|
87
|
+
}
|
|
52
88
|
function removeEmptyLinks(paragraph) {
|
|
53
89
|
var marker = paragraph.segments.find(function (x) { return x.segmentType == 'SelectionMarker'; });
|
|
54
90
|
if (marker) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"normalizeParagraph.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-dom/lib/modelApi/common/normalizeParagraph.ts"],"names":[],"mappings":"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","sourcesContent":["import { areSameFormats } from '../../domToModel/utils/areSameFormats';\nimport { createBr } from '../creators/createBr';\nimport { isSegmentEmpty } from './isEmpty';\nimport { isWhiteSpacePreserved } from '../../domUtils/isWhiteSpacePreserved';\nimport { mutateBlock, mutateSegment } from './mutate';\nimport { normalizeAllSegments } from './normalizeSegment';\nimport type {\n ContentModelSegmentFormat,\n ReadonlyContentModelParagraph,\n ReadonlyContentModelSegment,\n} from 'roosterjs-content-model-types';\n\n/**\n * @param paragraph The paragraph to normalize\n * Normalize a paragraph. If it is empty, add a BR segment to make sure it can insert content\n */\nexport function normalizeParagraph(paragraph: ReadonlyContentModelParagraph) {\n const segments = paragraph.segments;\n\n if (!paragraph.isImplicit && segments.length > 0) {\n const last = segments[segments.length - 1];\n const secondLast = segments[segments.length - 2];\n\n if (\n last.segmentType == 'SelectionMarker' &&\n (!secondLast || secondLast.segmentType == 'Br')\n ) {\n mutateBlock(paragraph).segments.push(createBr(last.format));\n } else if (segments.length > 1 && segments[segments.length - 1].segmentType == 'Br') {\n const noMarkerSegments = segments.filter(x => x.segmentType != 'SelectionMarker');\n\n // When there is content with a <BR> tag at the end, we can remove the BR.\n // But if there are more than one <BR> at the end, do not remove them.\n if (\n noMarkerSegments.length > 1 &&\n noMarkerSegments[noMarkerSegments.length - 2].segmentType != 'Br'\n ) {\n mutateBlock(paragraph).segments.pop();\n }\n }\n\n normalizeParagraphStyle(paragraph);\n }\n\n if (!isWhiteSpacePreserved(paragraph.format.whiteSpace)) {\n normalizeAllSegments(paragraph);\n }\n\n removeEmptyLinks(paragraph);\n\n removeEmptySegments(paragraph);\n\n moveUpSegmentFormat(paragraph);\n}\n\nfunction normalizeParagraphStyle(paragraph: ReadonlyContentModelParagraph) {\n // New paragraph should not have white-space style\n if (\n paragraph.format.whiteSpace &&\n paragraph.segments.every(\n seg => seg.segmentType == 'Br' || seg.segmentType == 'SelectionMarker'\n )\n ) {\n delete mutateBlock(paragraph).format.whiteSpace;\n }\n}\n\nfunction removeEmptySegments(block: ReadonlyContentModelParagraph) {\n for (let j = block.segments.length - 1; j >= 0; j--) {\n if (isSegmentEmpty(block.segments[j])) {\n mutateBlock(block).segments.splice(j, 1);\n }\n }\n}\n\nfunction removeEmptyLinks(paragraph: ReadonlyContentModelParagraph) {\n const marker = paragraph.segments.find(x => x.segmentType == 'SelectionMarker');\n if (marker) {\n const markerIndex = paragraph.segments.indexOf(marker);\n const prev = paragraph.segments[markerIndex - 1];\n const next = paragraph.segments[markerIndex + 1];\n\n if (\n (prev &&\n !prev.link &&\n areSameFormats(prev.format, marker.format) &&\n (!next || (!next.link && areSameFormats(next.format, marker.format))) &&\n marker.link) ||\n (!prev &&\n marker.link &&\n next &&\n !next.link &&\n areSameFormats(next.format, marker.format))\n ) {\n mutateSegment(paragraph, marker, mutableMarker => {\n delete mutableMarker.link;\n });\n }\n }\n}\n\ntype FormatsToMoveUp = 'fontFamily' | 'fontSize' | 'textColor';\nconst formatsToMoveUp: FormatsToMoveUp[] = ['fontFamily', 'fontSize', 'textColor'];\n\n// When all segments are sharing the same segment format (font name, size and color), we can move its format to paragraph\nfunction moveUpSegmentFormat(paragraph: ReadonlyContentModelParagraph) {\n if (!paragraph.decorator) {\n const segments = paragraph.segments.filter(x => x.segmentType != 'SelectionMarker');\n const target = paragraph.segmentFormat || {};\n let changed = false;\n\n formatsToMoveUp.forEach(key => {\n changed = internalMoveUpSegmentFormat(segments, target, key) || changed;\n });\n\n if (changed) {\n mutateBlock(paragraph).segmentFormat = target;\n }\n }\n}\n\nfunction internalMoveUpSegmentFormat(\n segments: ReadonlyContentModelSegment[],\n target: ContentModelSegmentFormat,\n formatKey: FormatsToMoveUp\n): boolean {\n const firstFormat = segments[0]?.format;\n\n if (\n firstFormat?.[formatKey] &&\n segments.every(segment => segment.format[formatKey] == firstFormat[formatKey]) &&\n target[formatKey] != firstFormat[formatKey]\n ) {\n target[formatKey] = firstFormat[formatKey];\n return true;\n } else {\n return false;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"normalizeParagraph.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-dom/lib/modelApi/common/normalizeParagraph.ts"],"names":[],"mappings":"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","sourcesContent":["import { areSameFormats } from '../../domToModel/utils/areSameFormats';\nimport { createBr } from '../creators/createBr';\nimport { isSegmentEmpty } from './isEmpty';\nimport { isWhiteSpacePreserved } from '../../domUtils/isWhiteSpacePreserved';\nimport { mutateBlock, mutateSegment, mutateSegments } from './mutate';\nimport { normalizeAllSegments } from './normalizeSegment';\nimport type {\n ContentModelSegmentFormat,\n ContentModelText,\n ReadonlyContentModelCode,\n ReadonlyContentModelLink,\n ReadonlyContentModelParagraph,\n ReadonlyContentModelSegment,\n ReadonlyContentModelText,\n} from 'roosterjs-content-model-types';\n\n/**\n * @param paragraph The paragraph to normalize\n * Normalize a paragraph. If it is empty, add a BR segment to make sure it can insert content\n */\nexport function normalizeParagraph(paragraph: ReadonlyContentModelParagraph) {\n const segments = paragraph.segments;\n\n if (!paragraph.isImplicit && segments.length > 0) {\n const last = segments[segments.length - 1];\n const secondLast = segments[segments.length - 2];\n\n if (\n last.segmentType == 'SelectionMarker' &&\n (!secondLast || secondLast.segmentType == 'Br')\n ) {\n mutateBlock(paragraph).segments.push(createBr(last.format));\n } else if (segments.length > 1 && segments[segments.length - 1].segmentType == 'Br') {\n const noMarkerSegments = segments.filter(x => x.segmentType != 'SelectionMarker');\n\n // When there is content with a <BR> tag at the end, we can remove the BR.\n // But if there are more than one <BR> at the end, do not remove them.\n if (\n noMarkerSegments.length > 1 &&\n noMarkerSegments[noMarkerSegments.length - 2].segmentType != 'Br'\n ) {\n mutateBlock(paragraph).segments.pop();\n }\n }\n\n normalizeParagraphStyle(paragraph);\n }\n\n if (!isWhiteSpacePreserved(paragraph.format.whiteSpace)) {\n normalizeAllSegments(paragraph);\n }\n\n removeEmptyLinks(paragraph);\n removeEmptySegments(paragraph);\n mergeTextSegments(paragraph);\n moveUpSegmentFormat(paragraph);\n}\n\nfunction normalizeParagraphStyle(paragraph: ReadonlyContentModelParagraph) {\n // New paragraph should not have white-space style\n if (\n paragraph.format.whiteSpace &&\n paragraph.segments.every(\n seg => seg.segmentType == 'Br' || seg.segmentType == 'SelectionMarker'\n )\n ) {\n delete mutateBlock(paragraph).format.whiteSpace;\n }\n}\n\nfunction removeEmptySegments(block: ReadonlyContentModelParagraph) {\n for (let j = block.segments.length - 1; j >= 0; j--) {\n if (isSegmentEmpty(block.segments[j])) {\n mutateBlock(block).segments.splice(j, 1);\n }\n }\n}\n\nfunction mergeTextSegments(block: ReadonlyContentModelParagraph) {\n let lastText: ReadonlyContentModelText | null = null;\n\n for (let i = 0; i < block.segments.length; i++) {\n const segment = block.segments[i];\n\n if (segment.segmentType != 'Text') {\n lastText = null;\n } else if (!lastText || !segmentsWithSameFormat(lastText, segment)) {\n lastText = segment;\n } else {\n const [mutableBlock, [mutableLastText]] = mutateSegments(block, [lastText, segment]);\n\n (mutableLastText as ContentModelText).text += segment.text;\n mutableBlock.segments.splice(i, 1);\n i--;\n }\n }\n}\n\nfunction segmentsWithSameFormat(\n seg1: ReadonlyContentModelSegment,\n seg2: ReadonlyContentModelSegment\n) {\n return (\n !!seg1.isSelected == !!seg2.isSelected &&\n areSameFormats(seg1.format, seg2.format) &&\n areSameLinks(seg1.link, seg2.link) &&\n areSameCodes(seg1.code, seg2.code)\n );\n}\n\nfunction areSameLinks(\n link1: ReadonlyContentModelLink | undefined,\n link2: ReadonlyContentModelLink | undefined\n) {\n return (\n (!link1 && !link2) ||\n (link1 &&\n link2 &&\n areSameFormats(link1.format, link2.format) &&\n areSameFormats(link1.dataset, link2.dataset))\n );\n}\n\nfunction areSameCodes(\n code1: ReadonlyContentModelCode | undefined,\n code2: ReadonlyContentModelCode | undefined\n) {\n return (!code1 && !code2) || (code1 && code2 && areSameFormats(code1.format, code2.format));\n}\n\nfunction removeEmptyLinks(paragraph: ReadonlyContentModelParagraph) {\n const marker = paragraph.segments.find(x => x.segmentType == 'SelectionMarker');\n if (marker) {\n const markerIndex = paragraph.segments.indexOf(marker);\n const prev = paragraph.segments[markerIndex - 1];\n const next = paragraph.segments[markerIndex + 1];\n\n if (\n (prev &&\n !prev.link &&\n areSameFormats(prev.format, marker.format) &&\n (!next || (!next.link && areSameFormats(next.format, marker.format))) &&\n marker.link) ||\n (!prev &&\n marker.link &&\n next &&\n !next.link &&\n areSameFormats(next.format, marker.format))\n ) {\n mutateSegment(paragraph, marker, mutableMarker => {\n delete mutableMarker.link;\n });\n }\n }\n}\n\ntype FormatsToMoveUp = 'fontFamily' | 'fontSize' | 'textColor';\nconst formatsToMoveUp: FormatsToMoveUp[] = ['fontFamily', 'fontSize', 'textColor'];\n\n// When all segments are sharing the same segment format (font name, size and color), we can move its format to paragraph\nfunction moveUpSegmentFormat(paragraph: ReadonlyContentModelParagraph) {\n if (!paragraph.decorator) {\n const segments = paragraph.segments.filter(x => x.segmentType != 'SelectionMarker');\n const target = paragraph.segmentFormat || {};\n let changed = false;\n\n formatsToMoveUp.forEach(key => {\n changed = internalMoveUpSegmentFormat(segments, target, key) || changed;\n });\n\n if (changed) {\n mutateBlock(paragraph).segmentFormat = target;\n }\n }\n}\n\nfunction internalMoveUpSegmentFormat(\n segments: ReadonlyContentModelSegment[],\n target: ContentModelSegmentFormat,\n formatKey: FormatsToMoveUp\n): boolean {\n const firstFormat = segments[0]?.format;\n\n if (\n firstFormat?.[formatKey] &&\n segments.every(segment => segment.format[formatKey] == firstFormat[formatKey]) &&\n target[formatKey] != firstFormat[formatKey]\n ) {\n target[formatKey] = firstFormat[formatKey];\n return true;\n } else {\n return false;\n }\n}\n"]}
|
|
@@ -48,14 +48,17 @@ function extractSelectionRange(doc, context) {
|
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
50
|
function calcPosition(pos) {
|
|
51
|
-
var _a, _b, _c;
|
|
51
|
+
var _a, _b, _c, _d, _e;
|
|
52
52
|
var result;
|
|
53
53
|
if (pos.block) {
|
|
54
54
|
if (!pos.segment) {
|
|
55
55
|
result = { container: pos.block, offset: 0 };
|
|
56
56
|
}
|
|
57
57
|
else if (isNodeOfType(pos.segment, 'TEXT_NODE')) {
|
|
58
|
-
result = {
|
|
58
|
+
result = {
|
|
59
|
+
container: pos.segment,
|
|
60
|
+
offset: (_c = (_a = pos.offset) !== null && _a !== void 0 ? _a : (_b = pos.segment.nodeValue) === null || _b === void 0 ? void 0 : _b.length) !== null && _c !== void 0 ? _c : 0,
|
|
61
|
+
};
|
|
59
62
|
}
|
|
60
63
|
else if (pos.segment.parentNode) {
|
|
61
64
|
result = {
|
|
@@ -74,7 +77,7 @@ function calcPosition(pos) {
|
|
|
74
77
|
result = {
|
|
75
78
|
container: container,
|
|
76
79
|
offset: isNodeOfType(container, 'TEXT_NODE')
|
|
77
|
-
? (
|
|
80
|
+
? (_e = (_d = container.nodeValue) === null || _d === void 0 ? void 0 : _d.length) !== null && _e !== void 0 ? _e : 0
|
|
78
81
|
: container.childNodes.length,
|
|
79
82
|
};
|
|
80
83
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contentModelToDom.js","sourceRoot":"","sources":["../../../../packages/roosterjs-content-model-dom/lib/modelToDom/contentModelToDom.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAS9C;;;;;;;;;GASG;AACH,MAAM,UAAU,iBAAiB,CAC7B,GAAa,EACb,IAAU,EACV,KAA2B,EAC3B,OAA0B;IAE1B,OAAO,CAAC,aAAa,CAAC,kBAAkB,CAAC,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;IAEpE,IAAM,KAAK,GAAG,qBAAqB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAElD,IAAI,KAAK,CAAC,yBAAyB,IAAI,CAAA,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,IAAI,KAAI,OAAO,EAAE;QAC3D,KAAK,CAAC,UAAU,GAAG,IAAI,CAAC;KAC3B;IAED,IAAI,OAAO,CAAC,UAAU,IAAI,OAAO,CAAC,iBAAiB,EAAE;QAChD,KAAgD,CAAC,YAAY,GAAG,IAAI,CAAC;KACzE;IAED,IAAI,CAAC,SAAS,EAAE,CAAC;IAEjB,OAAO,KAAK,CAAC;AACjB,CAAC;AAED,SAAS,qBAAqB,CAAC,GAAa,EAAE,OAA0B;IAEhE,IAAA,KAGA,OAAO,iBAHyB,EAAZ,KAAK,WAAA,EAAE,GAAG,SAAA,EAC9B,cAAc,GAEd,OAAO,eAFO,EACd,cAAc,GACd,OAAO,eADO,CACN;IAEZ,IAAI,aAA8D,CAAC;IACnE,IAAI,WAA4D,CAAC;IAEjE,IAAI,cAAc,EAAE;QAChB,OAAO,cAAc,CAAC;KACzB;SAAM,IACH,CAAC,aAAa,GAAG,KAAK,IAAI,YAAY,CAAC,KAAK,CAAC,CAAC;QAC9C,CAAC,WAAW,GAAG,GAAG,IAAI,YAAY,CAAC,GAAG,CAAC,CAAC,EAC1C;QACE,IAAM,KAAK,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC;QAEhC,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,SAAS,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;QAC9D,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC,SAAS,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;QAExD,OAAO;YACH,IAAI,EAAE,OAAO;YACb,KAAK,OAAA;YACL,UAAU,EAAE,KAAK;SACpB,CAAC;KACL;SAAM,IAAI,cAAc,EAAE;QACvB,OAAO,cAAc,CAAC;KACzB;SAAM;QACH,OAAO,IAAI,CAAC;KACf;AACL,CAAC;AAED,SAAS,YAAY,CACjB,GAAkC;;IAElC,IAAI,MAAuD,CAAC;IAE5D,IAAI,GAAG,CAAC,KAAK,EAAE;QACX,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE;YACd,MAAM,GAAG,EAAE,SAAS,EAAE,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;SAChD;aAAM,IAAI,YAAY,CAAC,GAAG,CAAC,OAAO,EAAE,WAAW,CAAC,EAAE;YAC/C,MAAM,GAAG,
|
|
1
|
+
{"version":3,"file":"contentModelToDom.js","sourceRoot":"","sources":["../../../../packages/roosterjs-content-model-dom/lib/modelToDom/contentModelToDom.ts"],"names":[],"mappings":"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","sourcesContent":["import { isNodeOfType } from '../domUtils/isNodeOfType';\nimport { toArray } from '../domUtils/toArray';\nimport type { ContentModelDocumentWithPersistedCache } from '../modelApi/selection/iterateSelections';\nimport type {\n ContentModelDocument,\n DOMSelection,\n ModelToDomBlockAndSegmentNode,\n ModelToDomContext,\n} from 'roosterjs-content-model-types';\n\n/**\n * Create DOM tree fragment from Content Model document\n * @param doc Document object of the target DOM tree\n * @param root Target node that will become the container of new DOM tree.\n * When a DOM node with existing node is passed, it will be merged with content model so that unchanged blocks\n * won't be touched.\n * @param model The content model document to generate DOM tree from\n * @param context The context object for Content Model to DOM conversion\n * @returns The selection range created in DOM tree from this model, or null when there is no selection\n */\nexport function contentModelToDom(\n doc: Document,\n root: Node,\n model: ContentModelDocument,\n context: ModelToDomContext\n): DOMSelection | null {\n context.modelHandlers.blockGroupChildren(doc, root, model, context);\n\n const range = extractSelectionRange(doc, context);\n\n if (model.hasRevertedRangeSelection && range?.type == 'range') {\n range.isReverted = true;\n }\n\n if (context.domIndexer && context.allowCacheElement) {\n (model as ContentModelDocumentWithPersistedCache).persistCache = true;\n }\n\n root.normalize();\n\n return range;\n}\n\nfunction extractSelectionRange(doc: Document, context: ModelToDomContext): DOMSelection | null {\n const {\n regularSelection: { start, end },\n tableSelection,\n imageSelection,\n } = context;\n\n let startPosition: { container: Node; offset: number } | undefined;\n let endPosition: { container: Node; offset: number } | undefined;\n\n if (imageSelection) {\n return imageSelection;\n } else if (\n (startPosition = start && calcPosition(start)) &&\n (endPosition = end && calcPosition(end))\n ) {\n const range = doc.createRange();\n\n range.setStart(startPosition.container, startPosition.offset);\n range.setEnd(endPosition.container, endPosition.offset);\n\n return {\n type: 'range',\n range,\n isReverted: false,\n };\n } else if (tableSelection) {\n return tableSelection;\n } else {\n return null;\n }\n}\n\nfunction calcPosition(\n pos: ModelToDomBlockAndSegmentNode\n): { container: Node; offset: number } | undefined {\n let result: { container: Node; offset: number } | undefined;\n\n if (pos.block) {\n if (!pos.segment) {\n result = { container: pos.block, offset: 0 };\n } else if (isNodeOfType(pos.segment, 'TEXT_NODE')) {\n result = {\n container: pos.segment,\n offset: pos.offset ?? pos.segment.nodeValue?.length ?? 0,\n };\n } else if (pos.segment.parentNode) {\n result = {\n container: pos.segment.parentNode,\n offset:\n toArray(pos.segment.parentNode.childNodes as NodeListOf<Node>).indexOf(\n pos.segment\n ) + 1,\n };\n }\n }\n\n if (result && isNodeOfType(result.container, 'DOCUMENT_FRAGMENT_NODE')) {\n const childNodes = result.container.childNodes;\n\n if (childNodes.length > result.offset) {\n result = { container: childNodes[result.offset], offset: 0 };\n } else if (result.container.lastChild) {\n const container = result.container.lastChild;\n result = {\n container,\n offset: isNodeOfType(container, 'TEXT_NODE')\n ? container.nodeValue?.length ?? 0\n : container.childNodes.length,\n };\n } else {\n result = undefined;\n }\n }\n\n return result;\n}\n"]}
|
|
@@ -59,7 +59,7 @@ export var handleParagraph = function (doc, parent, paragraph, context, refNode)
|
|
|
59
59
|
else {
|
|
60
60
|
handleSegments();
|
|
61
61
|
}
|
|
62
|
-
optimize(container);
|
|
62
|
+
optimize(container, context);
|
|
63
63
|
// It is possible the next sibling node is changed during processing child segments
|
|
64
64
|
// e.g. When this paragraph is an implicit paragraph and it contains an inline entity segment
|
|
65
65
|
// The segment will be appended to container as child then the container will be removed
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handleParagraph.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-dom/lib/modelToDom/handlers/handleParagraph.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"handleParagraph.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-dom/lib/modelToDom/handlers/handleParagraph.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAClD,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AACvE,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAO/C,IAAM,mBAAmB,GAAG,KAAK,CAAC;AAElC;;GAEG;AACH,MAAM,CAAC,IAAM,eAAe,GAAoD,UAC5E,GAAa,EACb,MAAY,EACZ,SAAgC,EAChC,OAA0B,EAC1B,OAAoB;;IAEpB,IAAI,SAAS,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS,CAAC;IAEhF,IAAI,SAAS,IAAI,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,UAAA,CAAC,IAAI,OAAA,CAAC,CAAC,WAAW,IAAI,SAAS,IAAI,CAAC,CAAC,CAAC,UAAU,EAA3C,CAA2C,CAAC,EAAE;QACzF,OAAO,GAAG,kBAAkB,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;KAC5D;SAAM;QACH,WAAW,CAAC,OAAO,EAAE,CAAA,MAAA,SAAS,CAAC,SAAS,0CAAE,OAAO,KAAI,IAAI,EAAE;;YACvD,IAAM,oBAAoB,GACtB,CAAC,SAAS,CAAC,UAAU;gBACrB,CAAC,CAAC,SAAS,CAAC,SAAS;gBACrB,CAAC,aAAa,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,MAAM,GAAG,CAAC;oBACvC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,UAAA,OAAO,IAAI,OAAA,OAAO,CAAC,WAAW,IAAI,iBAAiB,EAAxC,CAAwC,CAAC,CAAC,CAAC;YACtF,IAAM,eAAe,GAAG,oBAAoB;gBACxC,CAAC,uBACQ,CAAC,CAAA,MAAA,SAAS,CAAC,SAAS,0CAAE,MAAM,KAAI,EAAE,CAAC,GACnC,SAAS,CAAC,aAAa,EAEhC,CAAC,CAAC,EAAE,CAAC;YAET,SAAS,GAAG,GAAG,CAAC,aAAa,CAAC,CAAA,MAAA,SAAS,CAAC,SAAS,0CAAE,OAAO,KAAI,mBAAmB,CAAC,CAAC;YAEnF,MAAM,CAAC,YAAY,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;YAExC,OAAO,CAAC,gBAAgB,CAAC,OAAO,GAAG;gBAC/B,KAAK,EAAE,oBAAoB,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,UAAU;gBAC9D,OAAO,EAAE,IAAI;aAChB,CAAC;YAEF,IAAM,cAAc,GAAG;gBACnB,IAAM,MAAM,GAAG,SAAS,CAAC;gBAEzB,IAAI,MAAM,EAAE;oBACR,IAAM,YAAY,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;oBAE3C,IAAI,CAAA,YAAY,aAAZ,YAAY,uBAAZ,YAAY,CAAE,WAAW,KAAI,iBAAiB,EAAE;wBAChD,gEAAgE;wBAChE,8FAA8F;wBAC9F,sGAAsG;wBACtG,OAAO,CAAC,aAAa,CAAC,IAAI,CACtB,GAAG,EACH,MAAM,wBAEC,YAAY,KACf,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,EAAE,KAEZ,OAAO,EACP,EAAE,CACL,CAAC;qBACL;oBAED,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC,UAAA,OAAO;wBAC9B,IAAM,WAAW,GAAW,EAAE,CAAC;wBAC/B,OAAO,CAAC,aAAa,CAAC,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,CAAC,CAAC;wBAE1E,WAAW,CAAC,OAAO,CAAC,UAAA,IAAI;;4BACpB,MAAA,OAAO,CAAC,UAAU,0CAAE,SAAS,CAAC,IAAI,EAAE,SAAS,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;wBAC9D,CAAC,CAAC,CAAC;oBACP,CAAC,CAAC,CAAC;iBACN;YACL,CAAC,CAAC;YAEF,IAAI,oBAAoB,EAAE;gBACtB,WAAW,CAAC,OAAO,EAAE,eAAe,EAAE,cAAc,CAAC,CAAC;gBAEtD,WAAW,CAAC,SAAS,EAAE,OAAO,CAAC,cAAc,CAAC,KAAK,EAAE,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;gBAChF,WAAW,CAAC,SAAS,EAAE,OAAO,CAAC,cAAc,CAAC,SAAS,EAAE,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;gBACpF,WAAW,CACP,SAAS,EACT,OAAO,CAAC,cAAc,CAAC,cAAc,EACrC,eAAe,EACf,OAAO,CACV,CAAC;aACL;iBAAM;gBACH,cAAc,EAAE,CAAC;aACpB;YAED,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;YAE7B,mFAAmF;YACnF,6FAA6F;YAC7F,wFAAwF;YACxF,+FAA+F;YAC/F,8FAA8F;YAC9F,qCAAqC;YACrC,OAAO,GAAG,SAAS,CAAC,WAAW,CAAC;YAEhC,IAAI,SAAS,EAAE;gBACX,MAAA,OAAO,CAAC,aAAa,+CAArB,OAAO,EAAiB,SAAS,EAAE,SAAS,CAAC,CAAC;gBAC9C,MAAA,OAAO,CAAC,UAAU,0CAAE,WAAW,CAAC,SAAS,CAAC,CAAC;aAC9C;YAED,IAAI,oBAAoB,EAAE;gBACtB,IAAI,OAAO,CAAC,iBAAiB,EAAE;oBAC3B,SAAS,CAAC,aAAa,GAAG,SAAS,CAAC;iBACvC;aACJ;iBAAM;gBACH,MAAM,CAAC,SAAS,CAAC,CAAC;gBAClB,SAAS,GAAG,SAAS,CAAC;aACzB;QACL,CAAC,CAAC,CAAC;KACN;IAED,OAAO,OAAO,CAAC;AACnB,CAAC,CAAC","sourcesContent":["import { applyFormat } from '../utils/applyFormat';\nimport { getObjectKeys } from '../../domUtils/getObjectKeys';\nimport { optimize } from '../optimizers/optimize';\nimport { reuseCachedElement } from '../../domUtils/reuseCachedElement';\nimport { stackFormat } from '../utils/stackFormat';\nimport { unwrap } from '../../domUtils/unwrap';\nimport type {\n ContentModelBlockHandler,\n ContentModelParagraph,\n ModelToDomContext,\n} from 'roosterjs-content-model-types';\n\nconst DefaultParagraphTag = 'div';\n\n/**\n * @internal\n */\nexport const handleParagraph: ContentModelBlockHandler<ContentModelParagraph> = (\n doc: Document,\n parent: Node,\n paragraph: ContentModelParagraph,\n context: ModelToDomContext,\n refNode: Node | null\n) => {\n let container = context.allowCacheElement ? paragraph.cachedElement : undefined;\n\n if (container && paragraph.segments.every(x => x.segmentType != 'General' && !x.isSelected)) {\n refNode = reuseCachedElement(parent, container, refNode);\n } else {\n stackFormat(context, paragraph.decorator?.tagName || null, () => {\n const needParagraphWrapper =\n !paragraph.isImplicit ||\n !!paragraph.decorator ||\n (getObjectKeys(paragraph.format).length > 0 &&\n paragraph.segments.some(segment => segment.segmentType != 'SelectionMarker'));\n const formatOnWrapper = needParagraphWrapper\n ? {\n ...(paragraph.decorator?.format || {}),\n ...paragraph.segmentFormat,\n }\n : {};\n\n container = doc.createElement(paragraph.decorator?.tagName || DefaultParagraphTag);\n\n parent.insertBefore(container, refNode);\n\n context.regularSelection.current = {\n block: needParagraphWrapper ? container : container.parentNode,\n segment: null,\n };\n\n const handleSegments = () => {\n const parent = container;\n\n if (parent) {\n const firstSegment = paragraph.segments[0];\n\n if (firstSegment?.segmentType == 'SelectionMarker') {\n // Make sure there is a segment created before selection marker.\n // If selection marker is the first selected segment in a paragraph, create a dummy text node,\n // so after rewrite, the regularSelection object can have a valid segment object set to the text node.\n context.modelHandlers.text(\n doc,\n parent,\n {\n ...firstSegment,\n segmentType: 'Text',\n text: '',\n },\n context,\n []\n );\n }\n\n paragraph.segments.forEach(segment => {\n const newSegments: Node[] = [];\n context.modelHandlers.segment(doc, parent, segment, context, newSegments);\n\n newSegments.forEach(node => {\n context.domIndexer?.onSegment(node, paragraph, [segment]);\n });\n });\n }\n };\n\n if (needParagraphWrapper) {\n stackFormat(context, formatOnWrapper, handleSegments);\n\n applyFormat(container, context.formatAppliers.block, paragraph.format, context);\n applyFormat(container, context.formatAppliers.container, paragraph.format, context);\n applyFormat(\n container,\n context.formatAppliers.segmentOnBlock,\n formatOnWrapper,\n context\n );\n } else {\n handleSegments();\n }\n\n optimize(container, context);\n\n // It is possible the next sibling node is changed during processing child segments\n // e.g. When this paragraph is an implicit paragraph and it contains an inline entity segment\n // The segment will be appended to container as child then the container will be removed\n // since this paragraph it is implicit. In that case container.nextSibling will become original\n // inline entity's next sibling. So reset refNode to its real next sibling (after change) here\n // to make sure the value is correct.\n refNode = container.nextSibling;\n\n if (container) {\n context.onNodeCreated?.(paragraph, container);\n context.domIndexer?.onParagraph(container);\n }\n\n if (needParagraphWrapper) {\n if (context.allowCacheElement) {\n paragraph.cachedElement = container;\n }\n } else {\n unwrap(container);\n container = undefined;\n }\n });\n }\n\n return refNode;\n};\n"]}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { isEntityElement } from '../../domUtils/entityUtils';
|
|
2
|
+
import { isNodeOfType } from '../../domUtils/isNodeOfType';
|
|
2
3
|
import { mergeNode } from './mergeNode';
|
|
3
4
|
import { removeUnnecessarySpan } from './removeUnnecessarySpan';
|
|
4
5
|
/**
|
|
5
6
|
* @internal
|
|
6
7
|
*/
|
|
7
|
-
export function optimize(root) {
|
|
8
|
+
export function optimize(root, context) {
|
|
8
9
|
/**
|
|
9
10
|
* Do no do any optimization to entity
|
|
10
11
|
*/
|
|
@@ -14,7 +15,45 @@ export function optimize(root) {
|
|
|
14
15
|
removeUnnecessarySpan(root);
|
|
15
16
|
mergeNode(root);
|
|
16
17
|
for (var child = root.firstChild; child; child = child.nextSibling) {
|
|
17
|
-
optimize(child);
|
|
18
|
+
optimize(child, context);
|
|
19
|
+
}
|
|
20
|
+
normalizeTextNode(root, context);
|
|
21
|
+
}
|
|
22
|
+
// Merge continuous text nodes into one single node (same with normalize()),
|
|
23
|
+
// and update selection and dom indexes
|
|
24
|
+
function normalizeTextNode(root, context) {
|
|
25
|
+
var _a, _b, _c, _d;
|
|
26
|
+
var lastText = null;
|
|
27
|
+
var child;
|
|
28
|
+
var next;
|
|
29
|
+
var selection = context.regularSelection;
|
|
30
|
+
for (child = root.firstChild, next = child ? child.nextSibling : null; child; child = next, next = child ? child.nextSibling : null) {
|
|
31
|
+
if (!isNodeOfType(child, 'TEXT_NODE')) {
|
|
32
|
+
lastText = null;
|
|
33
|
+
}
|
|
34
|
+
else if (!lastText) {
|
|
35
|
+
lastText = child;
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
var originalLength = (_b = (_a = lastText.nodeValue) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0;
|
|
39
|
+
(_c = context.domIndexer) === null || _c === void 0 ? void 0 : _c.onMergeText(lastText, child);
|
|
40
|
+
lastText.nodeValue += (_d = child.nodeValue) !== null && _d !== void 0 ? _d : '';
|
|
41
|
+
if (selection) {
|
|
42
|
+
updateSelection(selection.start, lastText, child, originalLength);
|
|
43
|
+
updateSelection(selection.end, lastText, child, originalLength);
|
|
44
|
+
}
|
|
45
|
+
root.removeChild(child);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
function updateSelection(mark, lastText, nextText, lastTextOriginalLength) {
|
|
50
|
+
if (mark && mark.offset == undefined) {
|
|
51
|
+
if (mark.segment == lastText) {
|
|
52
|
+
mark.offset = lastTextOriginalLength;
|
|
53
|
+
}
|
|
54
|
+
else if (mark.segment == nextText) {
|
|
55
|
+
mark.segment = lastText;
|
|
56
|
+
}
|
|
18
57
|
}
|
|
19
58
|
}
|
|
20
59
|
//# sourceMappingURL=optimize.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"optimize.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-dom/lib/modelToDom/optimizers/optimize.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"optimize.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-dom/lib/modelToDom/optimizers/optimize.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAMhE;;GAEG;AACH,MAAM,UAAU,QAAQ,CAAC,IAAU,EAAE,OAA0B;IAC3D;;OAEG;IACH,IAAI,eAAe,CAAC,IAAI,CAAC,EAAE;QACvB,OAAO;KACV;IAED,qBAAqB,CAAC,IAAI,CAAC,CAAC;IAC5B,SAAS,CAAC,IAAI,CAAC,CAAC;IAEhB,KAAK,IAAI,KAAK,GAAG,IAAI,CAAC,UAAU,EAAE,KAAK,EAAE,KAAK,GAAG,KAAK,CAAC,WAAW,EAAE;QAChE,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;KAC5B;IAED,iBAAiB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;AACrC,CAAC;AAED,4EAA4E;AAC5E,uCAAuC;AACvC,SAAS,iBAAiB,CAAC,IAAU,EAAE,OAA0B;;IAC7D,IAAI,QAAQ,GAAgB,IAAI,CAAC;IACjC,IAAI,KAAkB,CAAC;IACvB,IAAI,IAAiB,CAAC;IACtB,IAAM,SAAS,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAE3C,KACI,KAAK,GAAG,IAAI,CAAC,UAAU,EAAE,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,EAChE,KAAK,EACL,KAAK,GAAG,IAAI,EAAE,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,EACvD;QACE,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,WAAW,CAAC,EAAE;YACnC,QAAQ,GAAG,IAAI,CAAC;SACnB;aAAM,IAAI,CAAC,QAAQ,EAAE;YAClB,QAAQ,GAAG,KAAK,CAAC;SACpB;aAAM;YACH,IAAM,cAAc,GAAG,MAAA,MAAA,QAAQ,CAAC,SAAS,0CAAE,MAAM,mCAAI,CAAC,CAAC;YAEvD,MAAA,OAAO,CAAC,UAAU,0CAAE,WAAW,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;YACjD,QAAQ,CAAC,SAAS,IAAI,MAAA,KAAK,CAAC,SAAS,mCAAI,EAAE,CAAC;YAE5C,IAAI,SAAS,EAAE;gBACX,eAAe,CAAC,SAAS,CAAC,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,cAAc,CAAC,CAAC;gBAClE,eAAe,CAAC,SAAS,CAAC,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,cAAc,CAAC,CAAC;aACnE;YAED,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;SAC3B;KACJ;AACL,CAAC;AAED,SAAS,eAAe,CACpB,IAA+C,EAC/C,QAAc,EACd,QAAc,EACd,sBAA8B;IAE9B,IAAI,IAAI,IAAI,IAAI,CAAC,MAAM,IAAI,SAAS,EAAE;QAClC,IAAI,IAAI,CAAC,OAAO,IAAI,QAAQ,EAAE;YAC1B,IAAI,CAAC,MAAM,GAAG,sBAAsB,CAAC;SACxC;aAAM,IAAI,IAAI,CAAC,OAAO,IAAI,QAAQ,EAAE;YACjC,IAAI,CAAC,OAAO,GAAG,QAAQ,CAAC;SAC3B;KACJ;AACL,CAAC","sourcesContent":["import { isEntityElement } from '../../domUtils/entityUtils';\nimport { isNodeOfType } from '../../domUtils/isNodeOfType';\nimport { mergeNode } from './mergeNode';\nimport { removeUnnecessarySpan } from './removeUnnecessarySpan';\nimport type {\n ModelToDomBlockAndSegmentNode,\n ModelToDomContext,\n} from 'roosterjs-content-model-types';\n\n/**\n * @internal\n */\nexport function optimize(root: Node, context: ModelToDomContext) {\n /**\n * Do no do any optimization to entity\n */\n if (isEntityElement(root)) {\n return;\n }\n\n removeUnnecessarySpan(root);\n mergeNode(root);\n\n for (let child = root.firstChild; child; child = child.nextSibling) {\n optimize(child, context);\n }\n\n normalizeTextNode(root, context);\n}\n\n// Merge continuous text nodes into one single node (same with normalize()),\n// and update selection and dom indexes\nfunction normalizeTextNode(root: Node, context: ModelToDomContext) {\n let lastText: Text | null = null;\n let child: Node | null;\n let next: Node | null;\n const selection = context.regularSelection;\n\n for (\n child = root.firstChild, next = child ? child.nextSibling : null;\n child;\n child = next, next = child ? child.nextSibling : null\n ) {\n if (!isNodeOfType(child, 'TEXT_NODE')) {\n lastText = null;\n } else if (!lastText) {\n lastText = child;\n } else {\n const originalLength = lastText.nodeValue?.length ?? 0;\n\n context.domIndexer?.onMergeText(lastText, child);\n lastText.nodeValue += child.nodeValue ?? '';\n\n if (selection) {\n updateSelection(selection.start, lastText, child, originalLength);\n updateSelection(selection.end, lastText, child, originalLength);\n }\n\n root.removeChild(child);\n }\n }\n}\n\nfunction updateSelection(\n mark: ModelToDomBlockAndSegmentNode | undefined,\n lastText: Text,\n nextText: Text,\n lastTextOriginalLength: number\n) {\n if (mark && mark.offset == undefined) {\n if (mark.segment == lastText) {\n mark.offset = lastTextOriginalLength;\n } else if (mark.segment == nextText) {\n mark.segment = lastText;\n }\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
"description": "Content Model for roosterjs",
|
|
4
4
|
"dependencies": {
|
|
5
5
|
"tslib": "^2.3.1",
|
|
6
|
-
"roosterjs-content-model-types": "^9.
|
|
6
|
+
"roosterjs-content-model-types": "^9.13.0"
|
|
7
7
|
},
|
|
8
|
-
"version": "9.
|
|
8
|
+
"version": "9.13.0",
|
|
9
9
|
"main": "./lib/index.js",
|
|
10
10
|
"typings": "./lib/index.d.ts",
|
|
11
11
|
"module": "./lib-mjs/index.js",
|