roosterjs-content-model-dom 0.26.4 → 0.27.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/domToModel/utils/addSelectionMarker.js +15 -1
- package/lib/domToModel/utils/addSelectionMarker.js.map +1 -1
- package/lib/domUtils/entityUtils.d.ts +4 -4
- package/lib/domUtils/entityUtils.js +19 -2
- package/lib/domUtils/entityUtils.js.map +1 -1
- package/lib/domUtils/reuseCachedElement.js +2 -1
- package/lib/domUtils/reuseCachedElement.js.map +1 -1
- package/lib/formatHandlers/entity/entityFormatHandler.js +1 -8
- package/lib/formatHandlers/entity/entityFormatHandler.js.map +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.js +2 -2
- package/lib/index.js.map +1 -1
- package/lib/modelApi/common/normalizeParagraph.js +28 -0
- package/lib/modelApi/common/normalizeParagraph.js.map +1 -1
- package/lib-amd/domToModel/utils/addSelectionMarker.js +15 -1
- package/lib-amd/domToModel/utils/addSelectionMarker.js.map +1 -1
- package/lib-amd/domUtils/entityUtils.d.ts +4 -4
- package/lib-amd/domUtils/entityUtils.js +19 -2
- package/lib-amd/domUtils/entityUtils.js.map +1 -1
- package/lib-amd/domUtils/reuseCachedElement.js +2 -1
- package/lib-amd/domUtils/reuseCachedElement.js.map +1 -1
- package/lib-amd/formatHandlers/entity/entityFormatHandler.js +1 -8
- package/lib-amd/formatHandlers/entity/entityFormatHandler.js.map +1 -1
- package/lib-amd/index.d.ts +1 -1
- package/lib-amd/index.js +2 -2
- package/lib-amd/index.js.map +1 -1
- package/lib-amd/modelApi/common/normalizeParagraph.js +28 -0
- package/lib-amd/modelApi/common/normalizeParagraph.js.map +1 -1
- package/lib-mjs/domToModel/utils/addSelectionMarker.js +15 -1
- package/lib-mjs/domToModel/utils/addSelectionMarker.js.map +1 -1
- package/lib-mjs/domUtils/entityUtils.d.ts +4 -4
- package/lib-mjs/domUtils/entityUtils.js +18 -1
- package/lib-mjs/domUtils/entityUtils.js.map +1 -1
- package/lib-mjs/domUtils/reuseCachedElement.js +2 -1
- package/lib-mjs/domUtils/reuseCachedElement.js.map +1 -1
- package/lib-mjs/formatHandlers/entity/entityFormatHandler.js +2 -9
- package/lib-mjs/formatHandlers/entity/entityFormatHandler.js.map +1 -1
- package/lib-mjs/index.d.ts +1 -1
- package/lib-mjs/index.js +1 -1
- package/lib-mjs/index.js.map +1 -1
- package/lib-mjs/modelApi/common/normalizeParagraph.js +28 -0
- package/lib-mjs/modelApi/common/normalizeParagraph.js.map +1 -1
- package/package.json +2 -2
|
@@ -9,12 +9,26 @@ var createSelectionMarker_1 = require("../../modelApi/creators/createSelectionMa
|
|
|
9
9
|
* @internal
|
|
10
10
|
*/
|
|
11
11
|
function addSelectionMarker(group, context, container, offset) {
|
|
12
|
+
var lastPara = group.blocks[group.blocks.length - 1];
|
|
13
|
+
var formatFromParagraph = !lastPara || lastPara.blockType != 'Paragraph'
|
|
14
|
+
? {}
|
|
15
|
+
: lastPara.decorator
|
|
16
|
+
? {
|
|
17
|
+
fontFamily: lastPara.decorator.format.fontFamily,
|
|
18
|
+
fontSize: lastPara.decorator.format.fontSize,
|
|
19
|
+
}
|
|
20
|
+
: lastPara.segmentFormat
|
|
21
|
+
? {
|
|
22
|
+
fontFamily: lastPara.segmentFormat.fontFamily,
|
|
23
|
+
fontSize: lastPara.segmentFormat.fontSize,
|
|
24
|
+
}
|
|
25
|
+
: {};
|
|
12
26
|
var pendingFormat = context.pendingFormat &&
|
|
13
27
|
context.pendingFormat.posContainer === container &&
|
|
14
28
|
context.pendingFormat.posOffset === offset
|
|
15
29
|
? context.pendingFormat.format
|
|
16
30
|
: undefined;
|
|
17
|
-
var segmentFormat = (0, tslib_1.__assign)((0, tslib_1.__assign)((0, tslib_1.__assign)({}, context.defaultFormat), context.segmentFormat), pendingFormat);
|
|
31
|
+
var segmentFormat = (0, tslib_1.__assign)((0, tslib_1.__assign)((0, tslib_1.__assign)((0, tslib_1.__assign)({}, context.defaultFormat), formatFromParagraph), context.segmentFormat), pendingFormat);
|
|
18
32
|
var marker = (0, createSelectionMarker_1.createSelectionMarker)(segmentFormat);
|
|
19
33
|
(0, addDecorators_1.addDecorators)(marker, context);
|
|
20
34
|
(0, addSegment_1.addSegment)(group, marker, context.blockFormat, segmentFormat);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"addSelectionMarker.js","sourceRoot":"","sources":["../../../../../packages-content-model/roosterjs-content-model-dom/lib/domToModel/utils/addSelectionMarker.ts"],"names":[],"mappings":";;;;AAAA,qEAAoE;AACpE,+DAA8D;AAC9D,uFAAsF;
|
|
1
|
+
{"version":3,"file":"addSelectionMarker.js","sourceRoot":"","sources":["../../../../../packages-content-model/roosterjs-content-model-dom/lib/domToModel/utils/addSelectionMarker.ts"],"names":[],"mappings":";;;;AAAA,qEAAoE;AACpE,+DAA8D;AAC9D,uFAAsF;AAOtF;;GAEG;AACH,SAAgB,kBAAkB,CAC9B,KAA6B,EAC7B,OAA0B,EAC1B,SAAgB,EAChB,MAAe;IAEf,IAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACvD,IAAM,mBAAmB,GACrB,CAAC,QAAQ,IAAI,QAAQ,CAAC,SAAS,IAAI,WAAW;QAC1C,CAAC,CAAC,EAAE;QACJ,CAAC,CAAC,QAAQ,CAAC,SAAS;YACpB,CAAC,CAAC;gBACI,UAAU,EAAE,QAAQ,CAAC,SAAS,CAAC,MAAM,CAAC,UAAU;gBAChD,QAAQ,EAAE,QAAQ,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ;aAC/C;YACH,CAAC,CAAC,QAAQ,CAAC,aAAa;gBACxB,CAAC,CAAC;oBACI,UAAU,EAAE,QAAQ,CAAC,aAAa,CAAC,UAAU;oBAC7C,QAAQ,EAAE,QAAQ,CAAC,aAAa,CAAC,QAAQ;iBAC5C;gBACH,CAAC,CAAC,EAAE,CAAC;IAEb,IAAM,aAAa,GACf,OAAO,CAAC,aAAa;QACrB,OAAO,CAAC,aAAa,CAAC,YAAY,KAAK,SAAS;QAChD,OAAO,CAAC,aAAa,CAAC,SAAS,KAAK,MAAM;QACtC,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM;QAC9B,CAAC,CAAC,SAAS,CAAC;IACpB,IAAM,aAAa,+FACZ,OAAO,CAAC,aAAa,GACrB,mBAAmB,GACnB,OAAO,CAAC,aAAa,GACrB,aAAa,CACnB,CAAC;IACF,IAAM,MAAM,GAAG,IAAA,6CAAqB,EAAC,aAAa,CAAC,CAAC;IAEpD,IAAA,6BAAa,EAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAE/B,IAAA,uBAAU,EAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,WAAW,EAAE,aAAa,CAAC,CAAC;AAClE,CAAC;AAvCD,gDAuCC","sourcesContent":["import { addDecorators } from '../../modelApi/common/addDecorators';\nimport { addSegment } from '../../modelApi/common/addSegment';\nimport { createSelectionMarker } from '../../modelApi/creators/createSelectionMarker';\nimport type {\n ContentModelBlockGroup,\n ContentModelSegmentFormat,\n DomToModelContext,\n} from 'roosterjs-content-model-types';\n\n/**\n * @internal\n */\nexport function addSelectionMarker(\n group: ContentModelBlockGroup,\n context: DomToModelContext,\n container?: Node,\n offset?: number\n) {\n const lastPara = group.blocks[group.blocks.length - 1];\n const formatFromParagraph: ContentModelSegmentFormat =\n !lastPara || lastPara.blockType != 'Paragraph'\n ? {}\n : lastPara.decorator\n ? {\n fontFamily: lastPara.decorator.format.fontFamily,\n fontSize: lastPara.decorator.format.fontSize,\n }\n : lastPara.segmentFormat\n ? {\n fontFamily: lastPara.segmentFormat.fontFamily,\n fontSize: lastPara.segmentFormat.fontSize,\n }\n : {};\n\n const pendingFormat =\n context.pendingFormat &&\n context.pendingFormat.posContainer === container &&\n context.pendingFormat.posOffset === offset\n ? context.pendingFormat.format\n : undefined;\n const segmentFormat = {\n ...context.defaultFormat,\n ...formatFromParagraph,\n ...context.segmentFormat,\n ...pendingFormat,\n };\n const marker = createSelectionMarker(segmentFormat);\n\n addDecorators(marker, context);\n\n addSegment(group, marker, context.blockFormat, segmentFormat);\n}\n"]}
|
|
@@ -10,11 +10,11 @@ export declare function isEntityElement(node: Node): boolean;
|
|
|
10
10
|
*/
|
|
11
11
|
export declare function getAllEntityWrappers(root: HTMLElement): HTMLElement[];
|
|
12
12
|
/**
|
|
13
|
-
* Parse entity
|
|
14
|
-
* @param
|
|
15
|
-
* @
|
|
13
|
+
* Parse entity format from entity wrapper element
|
|
14
|
+
* @param wrapper The wrapper element to parse entity format from
|
|
15
|
+
* @returns Entity format
|
|
16
16
|
*/
|
|
17
|
-
export declare function
|
|
17
|
+
export declare function parseEntityFormat(wrapper: HTMLElement): ContentModelEntityFormat;
|
|
18
18
|
/**
|
|
19
19
|
* Generate Entity class names for an entity wrapper
|
|
20
20
|
* @param format The source entity format object
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.addDelimiters = exports.isEntityDelimiter = exports.generateEntityClassNames = exports.
|
|
3
|
+
exports.addDelimiters = exports.isEntityDelimiter = exports.generateEntityClassNames = exports.parseEntityFormat = exports.getAllEntityWrappers = exports.isEntityElement = void 0;
|
|
4
4
|
var tslib_1 = require("tslib");
|
|
5
5
|
var toArray_1 = require("./toArray");
|
|
6
6
|
var applyFormat_1 = require("../modelToDom/utils/applyFormat");
|
|
@@ -29,6 +29,24 @@ function getAllEntityWrappers(root) {
|
|
|
29
29
|
return (0, toArray_1.default)(root.querySelectorAll('.' + ENTITY_INFO_NAME));
|
|
30
30
|
}
|
|
31
31
|
exports.getAllEntityWrappers = getAllEntityWrappers;
|
|
32
|
+
/**
|
|
33
|
+
* Parse entity format from entity wrapper element
|
|
34
|
+
* @param wrapper The wrapper element to parse entity format from
|
|
35
|
+
* @returns Entity format
|
|
36
|
+
*/
|
|
37
|
+
function parseEntityFormat(wrapper) {
|
|
38
|
+
var isEntity = false;
|
|
39
|
+
var format = {};
|
|
40
|
+
wrapper.classList.forEach(function (name) {
|
|
41
|
+
isEntity = parseEntityClassName(name, format) || isEntity;
|
|
42
|
+
});
|
|
43
|
+
if (!isEntity) {
|
|
44
|
+
format.isFakeEntity = true;
|
|
45
|
+
format.isReadonly = !wrapper.isContentEditable;
|
|
46
|
+
}
|
|
47
|
+
return format;
|
|
48
|
+
}
|
|
49
|
+
exports.parseEntityFormat = parseEntityFormat;
|
|
32
50
|
/**
|
|
33
51
|
* Parse entity class names from entity wrapper element
|
|
34
52
|
* @param className Class names of entity
|
|
@@ -48,7 +66,6 @@ function parseEntityClassName(className, format) {
|
|
|
48
66
|
format.isReadonly = className.substring(ENTITY_READONLY_PREFIX.length) == '1';
|
|
49
67
|
}
|
|
50
68
|
}
|
|
51
|
-
exports.parseEntityClassName = parseEntityClassName;
|
|
52
69
|
/**
|
|
53
70
|
* Generate Entity class names for an entity wrapper
|
|
54
71
|
* @param format The source entity format object
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entityUtils.js","sourceRoot":"","sources":["../../../../packages-content-model/roosterjs-content-model-dom/lib/domUtils/entityUtils.ts"],"names":[],"mappings":";;;;AAAA,qCAAgC;AAChC,+DAA8D;AAC9D,qDAAoD;AACpD,+CAA8C;AAO9C,IAAM,gBAAgB,GAAG,SAAS,CAAC;AACnC,IAAM,kBAAkB,GAAG,SAAS,CAAC;AACrC,IAAM,gBAAgB,GAAG,OAAO,CAAC;AACjC,IAAM,sBAAsB,GAAG,aAAa,CAAC;AAC7C,IAAM,gBAAgB,GAAG,QAAQ,CAAC;AAClC,IAAM,gBAAgB,GAAG,uBAAuB,CAAC;AACjD,IAAM,eAAe,GAAG,sBAAsB,CAAC;AAE/C;;GAEG;AACH,SAAgB,eAAe,CAAC,IAAU;IACtC,OAAO,IAAA,2BAAY,EAAC,IAAI,EAAE,cAAc,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC;AAC3F,CAAC;AAFD,0CAEC;AAED;;;;GAIG;AACH,SAAgB,oBAAoB,CAAC,IAAiB;IAClD,OAAO,IAAA,iBAAO,EAAC,IAAI,CAAC,gBAAgB,CAAC,GAAG,GAAG,gBAAgB,CAAC,CAAkB,CAAC;AACnF,CAAC;AAFD,oDAEC;AAED;;;;GAIG;AACH,SAAgB,oBAAoB,
|
|
1
|
+
{"version":3,"file":"entityUtils.js","sourceRoot":"","sources":["../../../../packages-content-model/roosterjs-content-model-dom/lib/domUtils/entityUtils.ts"],"names":[],"mappings":"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","sourcesContent":["import toArray from './toArray';\nimport { applyFormat } from '../modelToDom/utils/applyFormat';\nimport { isElementOfType } from './isElementOfType';\nimport { isNodeOfType } from './isNodeOfType';\nimport type {\n ContentModelEntityFormat,\n ContentModelSegmentFormat,\n ModelToDomContext,\n} from 'roosterjs-content-model-types';\n\nconst ENTITY_INFO_NAME = '_Entity';\nconst ENTITY_TYPE_PREFIX = '_EType_';\nconst ENTITY_ID_PREFIX = '_EId_';\nconst ENTITY_READONLY_PREFIX = '_EReadonly_';\nconst ZERO_WIDTH_SPACE = '\\u200B';\nconst DELIMITER_BEFORE = 'entityDelimiterBefore';\nconst DELIMITER_AFTER = 'entityDelimiterAfter';\n\n/**\n * Check if the given DOM Node is an entity wrapper element\n */\nexport function isEntityElement(node: Node): boolean {\n return isNodeOfType(node, 'ELEMENT_NODE') && node.classList.contains(ENTITY_INFO_NAME);\n}\n\n/**\n * Get all entity wrapper elements under the given root element\n * @param root The root element to query from\n * @returns An array of entity wrapper elements\n */\nexport function getAllEntityWrappers(root: HTMLElement): HTMLElement[] {\n return toArray(root.querySelectorAll('.' + ENTITY_INFO_NAME)) as HTMLElement[];\n}\n\n/**\n * Parse entity format from entity wrapper element\n * @param wrapper The wrapper element to parse entity format from\n * @returns Entity format\n */\nexport function parseEntityFormat(wrapper: HTMLElement): ContentModelEntityFormat {\n let isEntity = false;\n const format: ContentModelEntityFormat = {};\n\n wrapper.classList.forEach(name => {\n isEntity = parseEntityClassName(name, format) || isEntity;\n });\n\n if (!isEntity) {\n format.isFakeEntity = true;\n format.isReadonly = !wrapper.isContentEditable;\n }\n\n return format;\n}\n\n/**\n * Parse entity class names from entity wrapper element\n * @param className Class names of entity\n * @param format The output entity format object\n */\nfunction parseEntityClassName(\n className: string,\n format: ContentModelEntityFormat\n): boolean | undefined {\n if (className == ENTITY_INFO_NAME) {\n return true;\n } else if (className.indexOf(ENTITY_TYPE_PREFIX) == 0) {\n format.entityType = className.substring(ENTITY_TYPE_PREFIX.length);\n } else if (className.indexOf(ENTITY_ID_PREFIX) == 0) {\n format.id = className.substring(ENTITY_ID_PREFIX.length);\n } else if (className.indexOf(ENTITY_READONLY_PREFIX) == 0) {\n format.isReadonly = className.substring(ENTITY_READONLY_PREFIX.length) == '1';\n }\n}\n\n/**\n * Generate Entity class names for an entity wrapper\n * @param format The source entity format object\n * @returns A combined CSS class name string for entity wrapper\n */\nexport function generateEntityClassNames(format: ContentModelEntityFormat): string {\n return format.isFakeEntity\n ? ''\n : `${ENTITY_INFO_NAME} ${ENTITY_TYPE_PREFIX}${format.entityType ?? ''} ${\n format.id ? `${ENTITY_ID_PREFIX}${format.id} ` : ''\n }${ENTITY_READONLY_PREFIX}${format.isReadonly ? '1' : '0'}`;\n}\n\n/**\n * Checks whether the node provided is a Entity delimiter\n * @param node the node to check\n * @return true if it is a delimiter\n */\nexport function isEntityDelimiter(element: HTMLElement): boolean {\n return (\n isElementOfType(element, 'span') &&\n (element.classList.contains(DELIMITER_AFTER) ||\n element.classList.contains(DELIMITER_BEFORE)) &&\n element.textContent === ZERO_WIDTH_SPACE\n );\n}\n\n/**\n * Adds delimiters to the element provided. If the delimiters already exists, will not be added\n * @param element the node to add the delimiters\n * @param format format to set to the delimiters, so when typing inside of one the format is not lost\n * @param context Model to Dom context to use.\n */\nexport function addDelimiters(\n doc: Document,\n element: HTMLElement,\n format?: ContentModelSegmentFormat | null,\n context?: ModelToDomContext\n): HTMLElement[] {\n let [delimiterAfter, delimiterBefore] = getDelimiters(element);\n\n if (!delimiterAfter) {\n delimiterAfter = insertDelimiter(doc, element, true /*isAfter*/);\n if (context && format) {\n applyFormat(delimiterAfter, context.formatAppliers.segment, format, context);\n }\n }\n\n if (!delimiterBefore) {\n delimiterBefore = insertDelimiter(doc, element, false /*isAfter*/);\n if (context && format) {\n applyFormat(delimiterBefore, context.formatAppliers.segment, format, context);\n }\n }\n\n return [delimiterAfter, delimiterBefore];\n}\n\nfunction getDelimiters(entityWrapper: HTMLElement): (HTMLElement | undefined)[] {\n const result: (HTMLElement | undefined)[] = [];\n const { nextElementSibling, previousElementSibling } = entityWrapper;\n result.push(\n isDelimiter(nextElementSibling, DELIMITER_AFTER),\n isDelimiter(previousElementSibling, DELIMITER_BEFORE)\n );\n\n return result;\n}\n\nfunction isDelimiter(el: Element | null, className: string): HTMLElement | undefined {\n return el?.classList.contains(className) && el.textContent == ZERO_WIDTH_SPACE\n ? (el as HTMLElement)\n : undefined;\n}\n\nfunction insertDelimiter(doc: Document, element: Element, isAfter: boolean) {\n const span = doc.createElement('span');\n\n span.className = isAfter ? DELIMITER_AFTER : DELIMITER_BEFORE;\n span.appendChild(doc.createTextNode(ZERO_WIDTH_SPACE));\n element.parentNode?.insertBefore(span, isAfter ? element.nextSibling : element);\n\n return span;\n}\n"]}
|
|
@@ -14,10 +14,11 @@ var entityUtils_1 = require("./entityUtils");
|
|
|
14
14
|
function reuseCachedElement(parent, element, refNode) {
|
|
15
15
|
var _a;
|
|
16
16
|
if (element.parentNode == parent) {
|
|
17
|
+
var isEntity = (0, entityUtils_1.isEntityElement)(element);
|
|
17
18
|
// Remove nodes before the one we are hitting since they don't appear in Content Model at this position.
|
|
18
19
|
// But we don't want to touch entity since it would better to keep entity at its place unless it is removed
|
|
19
20
|
// In that case we will remove it after we have handled all other nodes
|
|
20
|
-
while (refNode && refNode != element && !(0, entityUtils_1.isEntityElement)(refNode)) {
|
|
21
|
+
while (refNode && refNode != element && (isEntity || !(0, entityUtils_1.isEntityElement)(refNode))) {
|
|
21
22
|
var next = refNode.nextSibling;
|
|
22
23
|
(_a = refNode.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(refNode);
|
|
23
24
|
refNode = next;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reuseCachedElement.js","sourceRoot":"","sources":["../../../../packages-content-model/roosterjs-content-model-dom/lib/domUtils/reuseCachedElement.ts"],"names":[],"mappings":";;;AAAA,6CAAgD;AAEhD;;;;;;;;GAQG;AACH,SAAgB,kBAAkB,CAAC,MAAY,EAAE,OAAa,EAAE,OAAoB;;IAChF,IAAI,OAAO,CAAC,UAAU,IAAI,MAAM,EAAE;QAC9B,wGAAwG;QACxG,2GAA2G;QAC3G,uEAAuE;QACvE,OAAO,OAAO,IAAI,OAAO,IAAI,OAAO,IAAI,CAAC,IAAA,6BAAe,EAAC,OAAO,CAAC,EAAE;
|
|
1
|
+
{"version":3,"file":"reuseCachedElement.js","sourceRoot":"","sources":["../../../../packages-content-model/roosterjs-content-model-dom/lib/domUtils/reuseCachedElement.ts"],"names":[],"mappings":";;;AAAA,6CAAgD;AAEhD;;;;;;;;GAQG;AACH,SAAgB,kBAAkB,CAAC,MAAY,EAAE,OAAa,EAAE,OAAoB;;IAChF,IAAI,OAAO,CAAC,UAAU,IAAI,MAAM,EAAE;QAC9B,IAAM,QAAQ,GAAG,IAAA,6BAAe,EAAC,OAAO,CAAC,CAAC;QAE1C,wGAAwG;QACxG,2GAA2G;QAC3G,uEAAuE;QACvE,OAAO,OAAO,IAAI,OAAO,IAAI,OAAO,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAA,6BAAe,EAAC,OAAO,CAAC,CAAC,EAAE;YAC7E,IAAM,IAAI,GAAG,OAAO,CAAC,WAAW,CAAC;YAEjC,MAAA,OAAO,CAAC,UAAU,0CAAE,WAAW,CAAC,OAAO,CAAC,CAAC;YACzC,OAAO,GAAG,IAAI,CAAC;SAClB;QAED,IAAI,OAAO,IAAI,OAAO,IAAI,OAAO,EAAE;YAC/B,OAAO,GAAG,OAAO,CAAC,WAAW,CAAC;SACjC;aAAM;YACH,MAAM,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;SACzC;KACJ;SAAM;QACH,MAAM,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;KACzC;IAED,OAAO,OAAO,CAAC;AACnB,CAAC;AAxBD,gDAwBC;AAED;;GAEG;AACH,SAAgB,UAAU,CAAC,IAAU;;IACjC,IAAM,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC;IAC9B,MAAA,IAAI,CAAC,UAAU,0CAAE,WAAW,CAAC,IAAI,CAAC,CAAC;IAEnC,OAAO,IAAI,CAAC;AAChB,CAAC;AALD,gCAKC","sourcesContent":["import { isEntityElement } from './entityUtils';\n\n/**\n * When set a DOM tree into editor, reuse the existing element in editor and no need to change it\n * @param param Parent node of the reused element\n * @param element The element to keep in parent node\n * @param refNode Reference node, it is point to current node that is being processed. It must be a child of parent node, or null.\n * We will start processing from this node, if it is not the same with element, remove it and keep processing its next sibling,\n * until we see an element that is the same with the passed in element or null.\n * @returns The new reference element\n */\nexport function reuseCachedElement(parent: Node, element: Node, refNode: Node | null): Node | null {\n if (element.parentNode == parent) {\n const isEntity = isEntityElement(element);\n\n // Remove nodes before the one we are hitting since they don't appear in Content Model at this position.\n // But we don't want to touch entity since it would better to keep entity at its place unless it is removed\n // In that case we will remove it after we have handled all other nodes\n while (refNode && refNode != element && (isEntity || !isEntityElement(refNode))) {\n const next = refNode.nextSibling;\n\n refNode.parentNode?.removeChild(refNode);\n refNode = next;\n }\n\n if (refNode && refNode == element) {\n refNode = refNode.nextSibling;\n } else {\n parent.insertBefore(element, refNode);\n }\n } else {\n parent.insertBefore(element, refNode);\n }\n\n return refNode;\n}\n\n/**\n * @internal\n */\nexport function removeNode(node: Node): Node | null {\n const next = node.nextSibling;\n node.parentNode?.removeChild(node);\n\n return next;\n}\n"]}
|
|
@@ -7,14 +7,7 @@ var entityUtils_1 = require("../../domUtils/entityUtils");
|
|
|
7
7
|
*/
|
|
8
8
|
exports.entityFormatHandler = {
|
|
9
9
|
parse: function (format, element) {
|
|
10
|
-
|
|
11
|
-
element.classList.forEach(function (name) {
|
|
12
|
-
isEntity = (0, entityUtils_1.parseEntityClassName)(name, format) || isEntity;
|
|
13
|
-
});
|
|
14
|
-
if (!isEntity) {
|
|
15
|
-
format.isFakeEntity = true;
|
|
16
|
-
format.isReadonly = !element.isContentEditable;
|
|
17
|
-
}
|
|
10
|
+
Object.assign(format, (0, entityUtils_1.parseEntityFormat)(element));
|
|
18
11
|
},
|
|
19
12
|
apply: function (format, element) {
|
|
20
13
|
if (!format.isFakeEntity) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entityFormatHandler.js","sourceRoot":"","sources":["../../../../../packages-content-model/roosterjs-content-model-dom/lib/formatHandlers/entity/entityFormatHandler.ts"],"names":[],"mappings":";;;AAAA,
|
|
1
|
+
{"version":3,"file":"entityFormatHandler.js","sourceRoot":"","sources":["../../../../../packages-content-model/roosterjs-content-model-dom/lib/formatHandlers/entity/entityFormatHandler.ts"],"names":[],"mappings":";;;AAAA,0DAAyF;AAIzF;;GAEG;AACU,QAAA,mBAAmB,GAA+C;IAC3E,KAAK,EAAE,UAAC,MAAM,EAAE,OAAO;QACnB,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,IAAA,+BAAiB,EAAC,OAAO,CAAC,CAAC,CAAC;IACtD,CAAC;IAED,KAAK,EAAE,UAAC,MAAM,EAAE,OAAO;QACnB,IAAI,CAAC,MAAM,CAAC,YAAY,EAAE;YACtB,OAAO,CAAC,SAAS,GAAG,IAAA,sCAAwB,EAAC,MAAM,CAAC,CAAC;SACxD;QAED,IAAI,MAAM,CAAC,UAAU,EAAE;YACnB,OAAO,CAAC,eAAe,GAAG,OAAO,CAAC;SACrC;aAAM;YACH,OAAO,CAAC,eAAe,CAAC,iBAAiB,CAAC,CAAC;SAC9C;IACL,CAAC;CACJ,CAAC","sourcesContent":["import { generateEntityClassNames, parseEntityFormat } from '../../domUtils/entityUtils';\nimport type { EntityInfoFormat, IdFormat } from 'roosterjs-content-model-types';\nimport type { FormatHandler } from '../FormatHandler';\n\n/**\n * @internal\n */\nexport const entityFormatHandler: FormatHandler<EntityInfoFormat & IdFormat> = {\n parse: (format, element) => {\n Object.assign(format, parseEntityFormat(element));\n },\n\n apply: (format, element) => {\n if (!format.isFakeEntity) {\n element.className = generateEntityClassNames(format);\n }\n\n if (format.isReadonly) {\n element.contentEditable = 'false';\n } else {\n element.removeAttribute('contenteditable');\n }\n },\n};\n"]}
|
package/lib/index.d.ts
CHANGED
|
@@ -15,7 +15,7 @@ export { getObjectKeys } from './domUtils/getObjectKeys';
|
|
|
15
15
|
export { default as toArray } from './domUtils/toArray';
|
|
16
16
|
export { moveChildNodes, wrapAllChildNodes } from './domUtils/moveChildNodes';
|
|
17
17
|
export { wrap } from './domUtils/wrap';
|
|
18
|
-
export { isEntityElement, getAllEntityWrappers,
|
|
18
|
+
export { isEntityElement, getAllEntityWrappers, parseEntityFormat, generateEntityClassNames, addDelimiters, isEntityDelimiter, } from './domUtils/entityUtils';
|
|
19
19
|
export { reuseCachedElement } from './domUtils/reuseCachedElement';
|
|
20
20
|
export { isWhiteSpacePreserved } from './domUtils/isWhiteSpacePreserved';
|
|
21
21
|
export { createBr } from './modelApi/creators/createBr';
|
package/lib/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.normalizeParagraph = exports.addLink = exports.addCode = exports.addBlock = exports.createEmptyModel = exports.createListLevel = exports.createDivider = exports.createEntity = exports.createGeneralBlock = exports.createGeneralSegment = exports.createParagraphDecorator = exports.createContentModelDocument = exports.createImage = exports.createText = exports.createTableCell = exports.createTable = exports.createSelectionMarker = exports.createParagraph = exports.createFormatContainer = exports.createListItem = exports.createBr = exports.isWhiteSpacePreserved = exports.reuseCachedElement = exports.isEntityDelimiter = exports.addDelimiters = exports.generateEntityClassNames = exports.
|
|
3
|
+
exports.normalizeParagraph = exports.addLink = exports.addCode = exports.addBlock = exports.createEmptyModel = exports.createListLevel = exports.createDivider = exports.createEntity = exports.createGeneralBlock = exports.createGeneralSegment = exports.createParagraphDecorator = exports.createContentModelDocument = exports.createImage = exports.createText = exports.createTableCell = exports.createTable = exports.createSelectionMarker = exports.createParagraph = exports.createFormatContainer = exports.createListItem = exports.createBr = exports.isWhiteSpacePreserved = exports.reuseCachedElement = exports.isEntityDelimiter = exports.addDelimiters = exports.generateEntityClassNames = exports.parseEntityFormat = exports.getAllEntityWrappers = exports.isEntityElement = exports.wrap = exports.wrapAllChildNodes = exports.moveChildNodes = exports.toArray = exports.getObjectKeys = exports.isElementOfType = exports.isNodeOfType = exports.hasMetadata = exports.updateMetadata = exports.isBlockElement = exports.areSameFormats = exports.parseFormat = exports.getRegularSelectionOffsets = exports.tableProcessor = exports.entityProcessor = exports.processChildNode = exports.handleRegularSelection = exports.childProcessor = exports.contentModelToText = exports.contentModelToDom = exports.domToContentModel = void 0;
|
|
4
4
|
exports.createModelToDomConfig = exports.createModelToDomContextWithConfig = exports.createModelToDomContext = exports.createDomToModelConfig = exports.createDomToModelContextWithConfig = exports.createDomToModelContext = exports.parseColor = exports.setColor = exports.getColor = exports.DeprecatedColors = exports.BorderKeys = exports.parseValueWithUnit = exports.setParagraphNotImplicit = exports.normalizeSingleSegment = exports.isEmpty = exports.addSegment = exports.unwrapBlock = exports.isGeneralSegment = exports.normalizeContentModel = void 0;
|
|
5
5
|
var domToContentModel_1 = require("./domToModel/domToContentModel");
|
|
6
6
|
Object.defineProperty(exports, "domToContentModel", { enumerable: true, get: function () { return domToContentModel_1.domToContentModel; } });
|
|
@@ -43,7 +43,7 @@ Object.defineProperty(exports, "wrap", { enumerable: true, get: function () { re
|
|
|
43
43
|
var entityUtils_1 = require("./domUtils/entityUtils");
|
|
44
44
|
Object.defineProperty(exports, "isEntityElement", { enumerable: true, get: function () { return entityUtils_1.isEntityElement; } });
|
|
45
45
|
Object.defineProperty(exports, "getAllEntityWrappers", { enumerable: true, get: function () { return entityUtils_1.getAllEntityWrappers; } });
|
|
46
|
-
Object.defineProperty(exports, "
|
|
46
|
+
Object.defineProperty(exports, "parseEntityFormat", { enumerable: true, get: function () { return entityUtils_1.parseEntityFormat; } });
|
|
47
47
|
Object.defineProperty(exports, "generateEntityClassNames", { enumerable: true, get: function () { return entityUtils_1.generateEntityClassNames; } });
|
|
48
48
|
Object.defineProperty(exports, "addDelimiters", { enumerable: true, get: function () { return entityUtils_1.addDelimiters; } });
|
|
49
49
|
Object.defineProperty(exports, "isEntityDelimiter", { enumerable: true, get: function () { return entityUtils_1.isEntityDelimiter; } });
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../packages-content-model/roosterjs-content-model-dom/lib/index.ts"],"names":[],"mappings":";;;;AAAA,oEAAmE;AAA1D,sHAAA,iBAAiB,OAAA;AAC1B,oEAAmE;AAA1D,sHAAA,iBAAiB,OAAA;AAC1B,uEAAsE;AAA7D,wHAAA,kBAAkB,OAAA;AAE3B,yEAIgD;AAH5C,gHAAA,cAAc,OAAA;AACd,wHAAA,sBAAsB,OAAA;AACtB,kHAAA,gBAAgB,OAAA;AAEpB,2EAA0E;AAAjE,kHAAA,eAAe,OAAA;AACxB,yEAAwE;AAA/D,gHAAA,cAAc,OAAA;AACvB,4FAA2F;AAAlF,wIAAA,0BAA0B,OAAA;AACnC,8DAA6D;AAApD,0GAAA,WAAW,OAAA;AACpB,oEAAmE;AAA1D,gHAAA,cAAc,OAAA;AACvB,oEAAmE;AAA1D,gHAAA,cAAc,OAAA;AAEvB,qEAAiF;AAAxE,gHAAA,cAAc,OAAA;AAAE,6GAAA,WAAW,OAAA;AACpC,wDAAoE;AAA3D,4GAAA,YAAY,OAAA;AACrB,8DAA6D;AAApD,kHAAA,eAAe,OAAA;AACxB,0DAAyD;AAAhD,8GAAA,aAAa,OAAA;AACtB,8CAAwD;AAA/C,kGAAA,OAAO,OAAW;AAC3B,4DAA8E;AAArE,gHAAA,cAAc,OAAA;AAAE,mHAAA,iBAAiB,OAAA;AAC1C,wCAAuC;AAA9B,4FAAA,IAAI,OAAA;AACb,sDAOgC;AAN5B,8GAAA,eAAe,OAAA;AACf,mHAAA,oBAAoB,OAAA;AACpB,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../packages-content-model/roosterjs-content-model-dom/lib/index.ts"],"names":[],"mappings":"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","sourcesContent":["export { domToContentModel } from './domToModel/domToContentModel';\nexport { contentModelToDom } from './modelToDom/contentModelToDom';\nexport { contentModelToText } from './modelToText/contentModelToText';\n\nexport {\n childProcessor,\n handleRegularSelection,\n processChildNode,\n} from './domToModel/processors/childProcessor';\nexport { entityProcessor } from './domToModel/processors/entityProcessor';\nexport { tableProcessor } from './domToModel/processors/tableProcessor';\nexport { getRegularSelectionOffsets } from './domToModel/utils/getRegularSelectionOffsets';\nexport { parseFormat } from './domToModel/utils/parseFormat';\nexport { areSameFormats } from './domToModel/utils/areSameFormats';\nexport { isBlockElement } from './domToModel/utils/isBlockElement';\n\nexport { updateMetadata, hasMetadata } from './domUtils/metadata/updateMetadata';\nexport { isNodeOfType, NodeTypeMap } from './domUtils/isNodeOfType';\nexport { isElementOfType } from './domUtils/isElementOfType';\nexport { getObjectKeys } from './domUtils/getObjectKeys';\nexport { default as toArray } from './domUtils/toArray';\nexport { moveChildNodes, wrapAllChildNodes } from './domUtils/moveChildNodes';\nexport { wrap } from './domUtils/wrap';\nexport {\n isEntityElement,\n getAllEntityWrappers,\n parseEntityFormat,\n generateEntityClassNames,\n addDelimiters,\n isEntityDelimiter,\n} from './domUtils/entityUtils';\nexport { reuseCachedElement } from './domUtils/reuseCachedElement';\nexport { isWhiteSpacePreserved } from './domUtils/isWhiteSpacePreserved';\n\nexport { createBr } from './modelApi/creators/createBr';\nexport { createListItem } from './modelApi/creators/createListItem';\nexport { createFormatContainer } from './modelApi/creators/createFormatContainer';\nexport { createParagraph } from './modelApi/creators/createParagraph';\nexport { createSelectionMarker } from './modelApi/creators/createSelectionMarker';\nexport { createTable } from './modelApi/creators/createTable';\nexport { createTableCell } from './modelApi/creators/createTableCell';\nexport { createText } from './modelApi/creators/createText';\nexport { createImage } from './modelApi/creators/createImage';\nexport { createContentModelDocument } from './modelApi/creators/createContentModelDocument';\nexport { createParagraphDecorator } from './modelApi/creators/createParagraphDecorator';\nexport { createGeneralSegment } from './modelApi/creators/createGeneralSegment';\nexport { createGeneralBlock } from './modelApi/creators/createGeneralBlock';\nexport { createEntity } from './modelApi/creators/createEntity';\nexport { createDivider } from './modelApi/creators/createDivider';\nexport { createListLevel } from './modelApi/creators/createListLevel';\nexport { createEmptyModel } from './modelApi/creators/createEmptyModel';\n\nexport { addBlock } from './modelApi/common/addBlock';\nexport { addCode } from './modelApi/common/addDecorators';\nexport { addLink } from './modelApi/common/addDecorators';\nexport { normalizeParagraph } from './modelApi/common/normalizeParagraph';\n\nexport { normalizeContentModel } from './modelApi/common/normalizeContentModel';\nexport { isGeneralSegment } from './modelApi/common/isGeneralSegment';\nexport { unwrapBlock } from './modelApi/common/unwrapBlock';\nexport { addSegment } from './modelApi/common/addSegment';\nexport { isEmpty } from './modelApi/common/isEmpty';\nexport { normalizeSingleSegment } from './modelApi/common/normalizeSegment';\n\nexport { setParagraphNotImplicit } from './modelApi/block/setParagraphNotImplicit';\n\nexport { parseValueWithUnit } from './formatHandlers/utils/parseValueWithUnit';\nexport { BorderKeys } from './formatHandlers/common/borderFormatHandler';\nexport { DeprecatedColors, getColor, setColor, parseColor } from './formatHandlers/utils/color';\n\nexport {\n createDomToModelContext,\n createDomToModelContextWithConfig,\n createDomToModelConfig,\n} from './domToModel/context/createDomToModelContext';\nexport {\n createModelToDomContext,\n createModelToDomContextWithConfig,\n createModelToDomConfig,\n} from './modelToDom/context/createModelToDomContext';\n"]}
|
|
@@ -34,6 +34,7 @@ function normalizeParagraph(paragraph) {
|
|
|
34
34
|
}
|
|
35
35
|
removeEmptyLinks(paragraph);
|
|
36
36
|
removeEmptySegments(paragraph);
|
|
37
|
+
moveUpSegmentFormat(paragraph);
|
|
37
38
|
}
|
|
38
39
|
exports.normalizeParagraph = normalizeParagraph;
|
|
39
40
|
function removeEmptySegments(block) {
|
|
@@ -63,4 +64,31 @@ function removeEmptyLinks(paragraph) {
|
|
|
63
64
|
}
|
|
64
65
|
}
|
|
65
66
|
}
|
|
67
|
+
var formatsToMoveUp = ['fontFamily', 'fontSize', 'textColor'];
|
|
68
|
+
// When all segments are sharing the same segment format (font name, size and color), we can move its format to paragraph
|
|
69
|
+
function moveUpSegmentFormat(paragraph) {
|
|
70
|
+
if (!paragraph.decorator) {
|
|
71
|
+
var segments_1 = paragraph.segments.filter(function (x) { return x.segmentType != 'SelectionMarker'; });
|
|
72
|
+
var target_1 = paragraph.segmentFormat || {};
|
|
73
|
+
var changed_1 = false;
|
|
74
|
+
formatsToMoveUp.forEach(function (key) {
|
|
75
|
+
changed_1 = internalMoveUpSegmentFormat(segments_1, target_1, key) || changed_1;
|
|
76
|
+
});
|
|
77
|
+
if (changed_1) {
|
|
78
|
+
paragraph.segmentFormat = target_1;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
function internalMoveUpSegmentFormat(segments, target, formatKey) {
|
|
83
|
+
var _a;
|
|
84
|
+
var firstFormat = (_a = segments[0]) === null || _a === void 0 ? void 0 : _a.format;
|
|
85
|
+
if ((firstFormat === null || firstFormat === void 0 ? void 0 : firstFormat[formatKey]) &&
|
|
86
|
+
segments.every(function (segment) { return segment.format[formatKey] == firstFormat[formatKey]; })) {
|
|
87
|
+
target[formatKey] = firstFormat[formatKey];
|
|
88
|
+
return true;
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
66
94
|
//# sourceMappingURL=normalizeParagraph.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"normalizeParagraph.js","sourceRoot":"","sources":["../../../../../packages-content-model/roosterjs-content-model-dom/lib/modelApi/common/normalizeParagraph.ts"],"names":[],"mappings":";;;AAAA,wEAAuE;AACvE,iDAAgD;AAChD,qCAA2C;AAC3C,8EAA6E;AAC7E,uDAA0D;
|
|
1
|
+
{"version":3,"file":"normalizeParagraph.js","sourceRoot":"","sources":["../../../../../packages-content-model/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 { normalizeAllSegments } from './normalizeSegment';\nimport type {\n ContentModelParagraph,\n ContentModelSegment,\n ContentModelSegmentFormat,\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: ContentModelParagraph) {\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 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 segments.pop();\n }\n }\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 removeEmptySegments(block: ContentModelParagraph) {\n for (let j = block.segments.length - 1; j >= 0; j--) {\n if (isSegmentEmpty(block.segments[j])) {\n block.segments.splice(j, 1);\n }\n }\n}\n\nfunction removeEmptyLinks(paragraph: ContentModelParagraph) {\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 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 delete marker.link;\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: ContentModelParagraph) {\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 paragraph.segmentFormat = target;\n }\n }\n}\n\nfunction internalMoveUpSegmentFormat(\n segments: ContentModelSegment[],\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 ) {\n target[formatKey] = firstFormat[formatKey];\n return true;\n } else {\n return false;\n }\n}\n"]}
|
|
@@ -6,12 +6,26 @@ define(["require", "exports", "tslib", "../../modelApi/common/addDecorators", ".
|
|
|
6
6
|
* @internal
|
|
7
7
|
*/
|
|
8
8
|
function addSelectionMarker(group, context, container, offset) {
|
|
9
|
+
var lastPara = group.blocks[group.blocks.length - 1];
|
|
10
|
+
var formatFromParagraph = !lastPara || lastPara.blockType != 'Paragraph'
|
|
11
|
+
? {}
|
|
12
|
+
: lastPara.decorator
|
|
13
|
+
? {
|
|
14
|
+
fontFamily: lastPara.decorator.format.fontFamily,
|
|
15
|
+
fontSize: lastPara.decorator.format.fontSize,
|
|
16
|
+
}
|
|
17
|
+
: lastPara.segmentFormat
|
|
18
|
+
? {
|
|
19
|
+
fontFamily: lastPara.segmentFormat.fontFamily,
|
|
20
|
+
fontSize: lastPara.segmentFormat.fontSize,
|
|
21
|
+
}
|
|
22
|
+
: {};
|
|
9
23
|
var pendingFormat = context.pendingFormat &&
|
|
10
24
|
context.pendingFormat.posContainer === container &&
|
|
11
25
|
context.pendingFormat.posOffset === offset
|
|
12
26
|
? context.pendingFormat.format
|
|
13
27
|
: undefined;
|
|
14
|
-
var segmentFormat = (0, tslib_1.__assign)((0, tslib_1.__assign)((0, tslib_1.__assign)({}, context.defaultFormat), context.segmentFormat), pendingFormat);
|
|
28
|
+
var segmentFormat = (0, tslib_1.__assign)((0, tslib_1.__assign)((0, tslib_1.__assign)((0, tslib_1.__assign)({}, context.defaultFormat), formatFromParagraph), context.segmentFormat), pendingFormat);
|
|
15
29
|
var marker = (0, createSelectionMarker_1.createSelectionMarker)(segmentFormat);
|
|
16
30
|
(0, addDecorators_1.addDecorators)(marker, context);
|
|
17
31
|
(0, addSegment_1.addSegment)(group, marker, context.blockFormat, segmentFormat);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"addSelectionMarker.js","sourceRoot":"","sources":["../../../../../packages-content-model/roosterjs-content-model-dom/lib/domToModel/utils/addSelectionMarker.ts"],"names":[],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"addSelectionMarker.js","sourceRoot":"","sources":["../../../../../packages-content-model/roosterjs-content-model-dom/lib/domToModel/utils/addSelectionMarker.ts"],"names":[],"mappings":";;;;IASA;;OAEG;IACH,SAAgB,kBAAkB,CAC9B,KAA6B,EAC7B,OAA0B,EAC1B,SAAgB,EAChB,MAAe;QAEf,IAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACvD,IAAM,mBAAmB,GACrB,CAAC,QAAQ,IAAI,QAAQ,CAAC,SAAS,IAAI,WAAW;YAC1C,CAAC,CAAC,EAAE;YACJ,CAAC,CAAC,QAAQ,CAAC,SAAS;gBACpB,CAAC,CAAC;oBACI,UAAU,EAAE,QAAQ,CAAC,SAAS,CAAC,MAAM,CAAC,UAAU;oBAChD,QAAQ,EAAE,QAAQ,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ;iBAC/C;gBACH,CAAC,CAAC,QAAQ,CAAC,aAAa;oBACxB,CAAC,CAAC;wBACI,UAAU,EAAE,QAAQ,CAAC,aAAa,CAAC,UAAU;wBAC7C,QAAQ,EAAE,QAAQ,CAAC,aAAa,CAAC,QAAQ;qBAC5C;oBACH,CAAC,CAAC,EAAE,CAAC;QAEb,IAAM,aAAa,GACf,OAAO,CAAC,aAAa;YACrB,OAAO,CAAC,aAAa,CAAC,YAAY,KAAK,SAAS;YAChD,OAAO,CAAC,aAAa,CAAC,SAAS,KAAK,MAAM;YACtC,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM;YAC9B,CAAC,CAAC,SAAS,CAAC;QACpB,IAAM,aAAa,+FACZ,OAAO,CAAC,aAAa,GACrB,mBAAmB,GACnB,OAAO,CAAC,aAAa,GACrB,aAAa,CACnB,CAAC;QACF,IAAM,MAAM,GAAG,IAAA,6CAAqB,EAAC,aAAa,CAAC,CAAC;QAEpD,IAAA,6BAAa,EAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAE/B,IAAA,uBAAU,EAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,WAAW,EAAE,aAAa,CAAC,CAAC;IAClE,CAAC;IAvCD,gDAuCC","sourcesContent":["import { addDecorators } from '../../modelApi/common/addDecorators';\nimport { addSegment } from '../../modelApi/common/addSegment';\nimport { createSelectionMarker } from '../../modelApi/creators/createSelectionMarker';\nimport type {\n ContentModelBlockGroup,\n ContentModelSegmentFormat,\n DomToModelContext,\n} from 'roosterjs-content-model-types';\n\n/**\n * @internal\n */\nexport function addSelectionMarker(\n group: ContentModelBlockGroup,\n context: DomToModelContext,\n container?: Node,\n offset?: number\n) {\n const lastPara = group.blocks[group.blocks.length - 1];\n const formatFromParagraph: ContentModelSegmentFormat =\n !lastPara || lastPara.blockType != 'Paragraph'\n ? {}\n : lastPara.decorator\n ? {\n fontFamily: lastPara.decorator.format.fontFamily,\n fontSize: lastPara.decorator.format.fontSize,\n }\n : lastPara.segmentFormat\n ? {\n fontFamily: lastPara.segmentFormat.fontFamily,\n fontSize: lastPara.segmentFormat.fontSize,\n }\n : {};\n\n const pendingFormat =\n context.pendingFormat &&\n context.pendingFormat.posContainer === container &&\n context.pendingFormat.posOffset === offset\n ? context.pendingFormat.format\n : undefined;\n const segmentFormat = {\n ...context.defaultFormat,\n ...formatFromParagraph,\n ...context.segmentFormat,\n ...pendingFormat,\n };\n const marker = createSelectionMarker(segmentFormat);\n\n addDecorators(marker, context);\n\n addSegment(group, marker, context.blockFormat, segmentFormat);\n}\n"]}
|
|
@@ -10,11 +10,11 @@ export declare function isEntityElement(node: Node): boolean;
|
|
|
10
10
|
*/
|
|
11
11
|
export declare function getAllEntityWrappers(root: HTMLElement): HTMLElement[];
|
|
12
12
|
/**
|
|
13
|
-
* Parse entity
|
|
14
|
-
* @param
|
|
15
|
-
* @
|
|
13
|
+
* Parse entity format from entity wrapper element
|
|
14
|
+
* @param wrapper The wrapper element to parse entity format from
|
|
15
|
+
* @returns Entity format
|
|
16
16
|
*/
|
|
17
|
-
export declare function
|
|
17
|
+
export declare function parseEntityFormat(wrapper: HTMLElement): ContentModelEntityFormat;
|
|
18
18
|
/**
|
|
19
19
|
* Generate Entity class names for an entity wrapper
|
|
20
20
|
* @param format The source entity format object
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
define(["require", "exports", "tslib", "./toArray", "../modelToDom/utils/applyFormat", "./isElementOfType", "./isNodeOfType"], function (require, exports, tslib_1, toArray_1, applyFormat_1, isElementOfType_1, isNodeOfType_1) {
|
|
2
2
|
"use strict";
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
exports.addDelimiters = exports.isEntityDelimiter = exports.generateEntityClassNames = exports.
|
|
4
|
+
exports.addDelimiters = exports.isEntityDelimiter = exports.generateEntityClassNames = exports.parseEntityFormat = exports.getAllEntityWrappers = exports.isEntityElement = void 0;
|
|
5
5
|
var ENTITY_INFO_NAME = '_Entity';
|
|
6
6
|
var ENTITY_TYPE_PREFIX = '_EType_';
|
|
7
7
|
var ENTITY_ID_PREFIX = '_EId_';
|
|
@@ -25,6 +25,24 @@ define(["require", "exports", "tslib", "./toArray", "../modelToDom/utils/applyFo
|
|
|
25
25
|
return (0, toArray_1.default)(root.querySelectorAll('.' + ENTITY_INFO_NAME));
|
|
26
26
|
}
|
|
27
27
|
exports.getAllEntityWrappers = getAllEntityWrappers;
|
|
28
|
+
/**
|
|
29
|
+
* Parse entity format from entity wrapper element
|
|
30
|
+
* @param wrapper The wrapper element to parse entity format from
|
|
31
|
+
* @returns Entity format
|
|
32
|
+
*/
|
|
33
|
+
function parseEntityFormat(wrapper) {
|
|
34
|
+
var isEntity = false;
|
|
35
|
+
var format = {};
|
|
36
|
+
wrapper.classList.forEach(function (name) {
|
|
37
|
+
isEntity = parseEntityClassName(name, format) || isEntity;
|
|
38
|
+
});
|
|
39
|
+
if (!isEntity) {
|
|
40
|
+
format.isFakeEntity = true;
|
|
41
|
+
format.isReadonly = !wrapper.isContentEditable;
|
|
42
|
+
}
|
|
43
|
+
return format;
|
|
44
|
+
}
|
|
45
|
+
exports.parseEntityFormat = parseEntityFormat;
|
|
28
46
|
/**
|
|
29
47
|
* Parse entity class names from entity wrapper element
|
|
30
48
|
* @param className Class names of entity
|
|
@@ -44,7 +62,6 @@ define(["require", "exports", "tslib", "./toArray", "../modelToDom/utils/applyFo
|
|
|
44
62
|
format.isReadonly = className.substring(ENTITY_READONLY_PREFIX.length) == '1';
|
|
45
63
|
}
|
|
46
64
|
}
|
|
47
|
-
exports.parseEntityClassName = parseEntityClassName;
|
|
48
65
|
/**
|
|
49
66
|
* Generate Entity class names for an entity wrapper
|
|
50
67
|
* @param format The source entity format object
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entityUtils.js","sourceRoot":"","sources":["../../../../packages-content-model/roosterjs-content-model-dom/lib/domUtils/entityUtils.ts"],"names":[],"mappings":";;;;IAUA,IAAM,gBAAgB,GAAG,SAAS,CAAC;IACnC,IAAM,kBAAkB,GAAG,SAAS,CAAC;IACrC,IAAM,gBAAgB,GAAG,OAAO,CAAC;IACjC,IAAM,sBAAsB,GAAG,aAAa,CAAC;IAC7C,IAAM,gBAAgB,GAAG,QAAQ,CAAC;IAClC,IAAM,gBAAgB,GAAG,uBAAuB,CAAC;IACjD,IAAM,eAAe,GAAG,sBAAsB,CAAC;IAE/C;;OAEG;IACH,SAAgB,eAAe,CAAC,IAAU;QACtC,OAAO,IAAA,2BAAY,EAAC,IAAI,EAAE,cAAc,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC;IAC3F,CAAC;IAFD,0CAEC;IAED;;;;OAIG;IACH,SAAgB,oBAAoB,CAAC,IAAiB;QAClD,OAAO,IAAA,iBAAO,EAAC,IAAI,CAAC,gBAAgB,CAAC,GAAG,GAAG,gBAAgB,CAAC,CAAkB,CAAC;IACnF,CAAC;IAFD,oDAEC;IAED;;;;OAIG;IACH,SAAgB,oBAAoB,
|
|
1
|
+
{"version":3,"file":"entityUtils.js","sourceRoot":"","sources":["../../../../packages-content-model/roosterjs-content-model-dom/lib/domUtils/entityUtils.ts"],"names":[],"mappings":"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","sourcesContent":["import toArray from './toArray';\nimport { applyFormat } from '../modelToDom/utils/applyFormat';\nimport { isElementOfType } from './isElementOfType';\nimport { isNodeOfType } from './isNodeOfType';\nimport type {\n ContentModelEntityFormat,\n ContentModelSegmentFormat,\n ModelToDomContext,\n} from 'roosterjs-content-model-types';\n\nconst ENTITY_INFO_NAME = '_Entity';\nconst ENTITY_TYPE_PREFIX = '_EType_';\nconst ENTITY_ID_PREFIX = '_EId_';\nconst ENTITY_READONLY_PREFIX = '_EReadonly_';\nconst ZERO_WIDTH_SPACE = '\\u200B';\nconst DELIMITER_BEFORE = 'entityDelimiterBefore';\nconst DELIMITER_AFTER = 'entityDelimiterAfter';\n\n/**\n * Check if the given DOM Node is an entity wrapper element\n */\nexport function isEntityElement(node: Node): boolean {\n return isNodeOfType(node, 'ELEMENT_NODE') && node.classList.contains(ENTITY_INFO_NAME);\n}\n\n/**\n * Get all entity wrapper elements under the given root element\n * @param root The root element to query from\n * @returns An array of entity wrapper elements\n */\nexport function getAllEntityWrappers(root: HTMLElement): HTMLElement[] {\n return toArray(root.querySelectorAll('.' + ENTITY_INFO_NAME)) as HTMLElement[];\n}\n\n/**\n * Parse entity format from entity wrapper element\n * @param wrapper The wrapper element to parse entity format from\n * @returns Entity format\n */\nexport function parseEntityFormat(wrapper: HTMLElement): ContentModelEntityFormat {\n let isEntity = false;\n const format: ContentModelEntityFormat = {};\n\n wrapper.classList.forEach(name => {\n isEntity = parseEntityClassName(name, format) || isEntity;\n });\n\n if (!isEntity) {\n format.isFakeEntity = true;\n format.isReadonly = !wrapper.isContentEditable;\n }\n\n return format;\n}\n\n/**\n * Parse entity class names from entity wrapper element\n * @param className Class names of entity\n * @param format The output entity format object\n */\nfunction parseEntityClassName(\n className: string,\n format: ContentModelEntityFormat\n): boolean | undefined {\n if (className == ENTITY_INFO_NAME) {\n return true;\n } else if (className.indexOf(ENTITY_TYPE_PREFIX) == 0) {\n format.entityType = className.substring(ENTITY_TYPE_PREFIX.length);\n } else if (className.indexOf(ENTITY_ID_PREFIX) == 0) {\n format.id = className.substring(ENTITY_ID_PREFIX.length);\n } else if (className.indexOf(ENTITY_READONLY_PREFIX) == 0) {\n format.isReadonly = className.substring(ENTITY_READONLY_PREFIX.length) == '1';\n }\n}\n\n/**\n * Generate Entity class names for an entity wrapper\n * @param format The source entity format object\n * @returns A combined CSS class name string for entity wrapper\n */\nexport function generateEntityClassNames(format: ContentModelEntityFormat): string {\n return format.isFakeEntity\n ? ''\n : `${ENTITY_INFO_NAME} ${ENTITY_TYPE_PREFIX}${format.entityType ?? ''} ${\n format.id ? `${ENTITY_ID_PREFIX}${format.id} ` : ''\n }${ENTITY_READONLY_PREFIX}${format.isReadonly ? '1' : '0'}`;\n}\n\n/**\n * Checks whether the node provided is a Entity delimiter\n * @param node the node to check\n * @return true if it is a delimiter\n */\nexport function isEntityDelimiter(element: HTMLElement): boolean {\n return (\n isElementOfType(element, 'span') &&\n (element.classList.contains(DELIMITER_AFTER) ||\n element.classList.contains(DELIMITER_BEFORE)) &&\n element.textContent === ZERO_WIDTH_SPACE\n );\n}\n\n/**\n * Adds delimiters to the element provided. If the delimiters already exists, will not be added\n * @param element the node to add the delimiters\n * @param format format to set to the delimiters, so when typing inside of one the format is not lost\n * @param context Model to Dom context to use.\n */\nexport function addDelimiters(\n doc: Document,\n element: HTMLElement,\n format?: ContentModelSegmentFormat | null,\n context?: ModelToDomContext\n): HTMLElement[] {\n let [delimiterAfter, delimiterBefore] = getDelimiters(element);\n\n if (!delimiterAfter) {\n delimiterAfter = insertDelimiter(doc, element, true /*isAfter*/);\n if (context && format) {\n applyFormat(delimiterAfter, context.formatAppliers.segment, format, context);\n }\n }\n\n if (!delimiterBefore) {\n delimiterBefore = insertDelimiter(doc, element, false /*isAfter*/);\n if (context && format) {\n applyFormat(delimiterBefore, context.formatAppliers.segment, format, context);\n }\n }\n\n return [delimiterAfter, delimiterBefore];\n}\n\nfunction getDelimiters(entityWrapper: HTMLElement): (HTMLElement | undefined)[] {\n const result: (HTMLElement | undefined)[] = [];\n const { nextElementSibling, previousElementSibling } = entityWrapper;\n result.push(\n isDelimiter(nextElementSibling, DELIMITER_AFTER),\n isDelimiter(previousElementSibling, DELIMITER_BEFORE)\n );\n\n return result;\n}\n\nfunction isDelimiter(el: Element | null, className: string): HTMLElement | undefined {\n return el?.classList.contains(className) && el.textContent == ZERO_WIDTH_SPACE\n ? (el as HTMLElement)\n : undefined;\n}\n\nfunction insertDelimiter(doc: Document, element: Element, isAfter: boolean) {\n const span = doc.createElement('span');\n\n span.className = isAfter ? DELIMITER_AFTER : DELIMITER_BEFORE;\n span.appendChild(doc.createTextNode(ZERO_WIDTH_SPACE));\n element.parentNode?.insertBefore(span, isAfter ? element.nextSibling : element);\n\n return span;\n}\n"]}
|
|
@@ -14,10 +14,11 @@ define(["require", "exports", "./entityUtils"], function (require, exports, enti
|
|
|
14
14
|
function reuseCachedElement(parent, element, refNode) {
|
|
15
15
|
var _a;
|
|
16
16
|
if (element.parentNode == parent) {
|
|
17
|
+
var isEntity = (0, entityUtils_1.isEntityElement)(element);
|
|
17
18
|
// Remove nodes before the one we are hitting since they don't appear in Content Model at this position.
|
|
18
19
|
// But we don't want to touch entity since it would better to keep entity at its place unless it is removed
|
|
19
20
|
// In that case we will remove it after we have handled all other nodes
|
|
20
|
-
while (refNode && refNode != element && !(0, entityUtils_1.isEntityElement)(refNode)) {
|
|
21
|
+
while (refNode && refNode != element && (isEntity || !(0, entityUtils_1.isEntityElement)(refNode))) {
|
|
21
22
|
var next = refNode.nextSibling;
|
|
22
23
|
(_a = refNode.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(refNode);
|
|
23
24
|
refNode = next;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reuseCachedElement.js","sourceRoot":"","sources":["../../../../packages-content-model/roosterjs-content-model-dom/lib/domUtils/reuseCachedElement.ts"],"names":[],"mappings":";;;;IAEA;;;;;;;;OAQG;IACH,SAAgB,kBAAkB,CAAC,MAAY,EAAE,OAAa,EAAE,OAAoB;;QAChF,IAAI,OAAO,CAAC,UAAU,IAAI,MAAM,EAAE;YAC9B,wGAAwG;YACxG,2GAA2G;YAC3G,uEAAuE;YACvE,OAAO,OAAO,IAAI,OAAO,IAAI,OAAO,IAAI,CAAC,IAAA,6BAAe,EAAC,OAAO,CAAC,EAAE;
|
|
1
|
+
{"version":3,"file":"reuseCachedElement.js","sourceRoot":"","sources":["../../../../packages-content-model/roosterjs-content-model-dom/lib/domUtils/reuseCachedElement.ts"],"names":[],"mappings":";;;;IAEA;;;;;;;;OAQG;IACH,SAAgB,kBAAkB,CAAC,MAAY,EAAE,OAAa,EAAE,OAAoB;;QAChF,IAAI,OAAO,CAAC,UAAU,IAAI,MAAM,EAAE;YAC9B,IAAM,QAAQ,GAAG,IAAA,6BAAe,EAAC,OAAO,CAAC,CAAC;YAE1C,wGAAwG;YACxG,2GAA2G;YAC3G,uEAAuE;YACvE,OAAO,OAAO,IAAI,OAAO,IAAI,OAAO,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAA,6BAAe,EAAC,OAAO,CAAC,CAAC,EAAE;gBAC7E,IAAM,IAAI,GAAG,OAAO,CAAC,WAAW,CAAC;gBAEjC,MAAA,OAAO,CAAC,UAAU,0CAAE,WAAW,CAAC,OAAO,CAAC,CAAC;gBACzC,OAAO,GAAG,IAAI,CAAC;aAClB;YAED,IAAI,OAAO,IAAI,OAAO,IAAI,OAAO,EAAE;gBAC/B,OAAO,GAAG,OAAO,CAAC,WAAW,CAAC;aACjC;iBAAM;gBACH,MAAM,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;aACzC;SACJ;aAAM;YACH,MAAM,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;SACzC;QAED,OAAO,OAAO,CAAC;IACnB,CAAC;IAxBD,gDAwBC;IAED;;OAEG;IACH,SAAgB,UAAU,CAAC,IAAU;;QACjC,IAAM,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC;QAC9B,MAAA,IAAI,CAAC,UAAU,0CAAE,WAAW,CAAC,IAAI,CAAC,CAAC;QAEnC,OAAO,IAAI,CAAC;IAChB,CAAC;IALD,gCAKC","sourcesContent":["import { isEntityElement } from './entityUtils';\n\n/**\n * When set a DOM tree into editor, reuse the existing element in editor and no need to change it\n * @param param Parent node of the reused element\n * @param element The element to keep in parent node\n * @param refNode Reference node, it is point to current node that is being processed. It must be a child of parent node, or null.\n * We will start processing from this node, if it is not the same with element, remove it and keep processing its next sibling,\n * until we see an element that is the same with the passed in element or null.\n * @returns The new reference element\n */\nexport function reuseCachedElement(parent: Node, element: Node, refNode: Node | null): Node | null {\n if (element.parentNode == parent) {\n const isEntity = isEntityElement(element);\n\n // Remove nodes before the one we are hitting since they don't appear in Content Model at this position.\n // But we don't want to touch entity since it would better to keep entity at its place unless it is removed\n // In that case we will remove it after we have handled all other nodes\n while (refNode && refNode != element && (isEntity || !isEntityElement(refNode))) {\n const next = refNode.nextSibling;\n\n refNode.parentNode?.removeChild(refNode);\n refNode = next;\n }\n\n if (refNode && refNode == element) {\n refNode = refNode.nextSibling;\n } else {\n parent.insertBefore(element, refNode);\n }\n } else {\n parent.insertBefore(element, refNode);\n }\n\n return refNode;\n}\n\n/**\n * @internal\n */\nexport function removeNode(node: Node): Node | null {\n const next = node.nextSibling;\n node.parentNode?.removeChild(node);\n\n return next;\n}\n"]}
|
|
@@ -7,14 +7,7 @@ define(["require", "exports", "../../domUtils/entityUtils"], function (require,
|
|
|
7
7
|
*/
|
|
8
8
|
exports.entityFormatHandler = {
|
|
9
9
|
parse: function (format, element) {
|
|
10
|
-
|
|
11
|
-
element.classList.forEach(function (name) {
|
|
12
|
-
isEntity = (0, entityUtils_1.parseEntityClassName)(name, format) || isEntity;
|
|
13
|
-
});
|
|
14
|
-
if (!isEntity) {
|
|
15
|
-
format.isFakeEntity = true;
|
|
16
|
-
format.isReadonly = !element.isContentEditable;
|
|
17
|
-
}
|
|
10
|
+
Object.assign(format, (0, entityUtils_1.parseEntityFormat)(element));
|
|
18
11
|
},
|
|
19
12
|
apply: function (format, element) {
|
|
20
13
|
if (!format.isFakeEntity) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entityFormatHandler.js","sourceRoot":"","sources":["../../../../../packages-content-model/roosterjs-content-model-dom/lib/formatHandlers/entity/entityFormatHandler.ts"],"names":[],"mappings":";;;;IAIA;;OAEG;IACU,QAAA,mBAAmB,GAA+C;QAC3E,KAAK,EAAE,UAAC,MAAM,EAAE,OAAO;YACnB,
|
|
1
|
+
{"version":3,"file":"entityFormatHandler.js","sourceRoot":"","sources":["../../../../../packages-content-model/roosterjs-content-model-dom/lib/formatHandlers/entity/entityFormatHandler.ts"],"names":[],"mappings":";;;;IAIA;;OAEG;IACU,QAAA,mBAAmB,GAA+C;QAC3E,KAAK,EAAE,UAAC,MAAM,EAAE,OAAO;YACnB,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,IAAA,+BAAiB,EAAC,OAAO,CAAC,CAAC,CAAC;QACtD,CAAC;QAED,KAAK,EAAE,UAAC,MAAM,EAAE,OAAO;YACnB,IAAI,CAAC,MAAM,CAAC,YAAY,EAAE;gBACtB,OAAO,CAAC,SAAS,GAAG,IAAA,sCAAwB,EAAC,MAAM,CAAC,CAAC;aACxD;YAED,IAAI,MAAM,CAAC,UAAU,EAAE;gBACnB,OAAO,CAAC,eAAe,GAAG,OAAO,CAAC;aACrC;iBAAM;gBACH,OAAO,CAAC,eAAe,CAAC,iBAAiB,CAAC,CAAC;aAC9C;QACL,CAAC;KACJ,CAAC","sourcesContent":["import { generateEntityClassNames, parseEntityFormat } from '../../domUtils/entityUtils';\nimport type { EntityInfoFormat, IdFormat } from 'roosterjs-content-model-types';\nimport type { FormatHandler } from '../FormatHandler';\n\n/**\n * @internal\n */\nexport const entityFormatHandler: FormatHandler<EntityInfoFormat & IdFormat> = {\n parse: (format, element) => {\n Object.assign(format, parseEntityFormat(element));\n },\n\n apply: (format, element) => {\n if (!format.isFakeEntity) {\n element.className = generateEntityClassNames(format);\n }\n\n if (format.isReadonly) {\n element.contentEditable = 'false';\n } else {\n element.removeAttribute('contenteditable');\n }\n },\n};\n"]}
|
package/lib-amd/index.d.ts
CHANGED
|
@@ -15,7 +15,7 @@ export { getObjectKeys } from './domUtils/getObjectKeys';
|
|
|
15
15
|
export { default as toArray } from './domUtils/toArray';
|
|
16
16
|
export { moveChildNodes, wrapAllChildNodes } from './domUtils/moveChildNodes';
|
|
17
17
|
export { wrap } from './domUtils/wrap';
|
|
18
|
-
export { isEntityElement, getAllEntityWrappers,
|
|
18
|
+
export { isEntityElement, getAllEntityWrappers, parseEntityFormat, generateEntityClassNames, addDelimiters, isEntityDelimiter, } from './domUtils/entityUtils';
|
|
19
19
|
export { reuseCachedElement } from './domUtils/reuseCachedElement';
|
|
20
20
|
export { isWhiteSpacePreserved } from './domUtils/isWhiteSpacePreserved';
|
|
21
21
|
export { createBr } from './modelApi/creators/createBr';
|
package/lib-amd/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
define(["require", "exports", "./domToModel/domToContentModel", "./modelToDom/contentModelToDom", "./modelToText/contentModelToText", "./domToModel/processors/childProcessor", "./domToModel/processors/entityProcessor", "./domToModel/processors/tableProcessor", "./domToModel/utils/getRegularSelectionOffsets", "./domToModel/utils/parseFormat", "./domToModel/utils/areSameFormats", "./domToModel/utils/isBlockElement", "./domUtils/metadata/updateMetadata", "./domUtils/isNodeOfType", "./domUtils/isElementOfType", "./domUtils/getObjectKeys", "./domUtils/toArray", "./domUtils/moveChildNodes", "./domUtils/wrap", "./domUtils/entityUtils", "./domUtils/reuseCachedElement", "./domUtils/isWhiteSpacePreserved", "./modelApi/creators/createBr", "./modelApi/creators/createListItem", "./modelApi/creators/createFormatContainer", "./modelApi/creators/createParagraph", "./modelApi/creators/createSelectionMarker", "./modelApi/creators/createTable", "./modelApi/creators/createTableCell", "./modelApi/creators/createText", "./modelApi/creators/createImage", "./modelApi/creators/createContentModelDocument", "./modelApi/creators/createParagraphDecorator", "./modelApi/creators/createGeneralSegment", "./modelApi/creators/createGeneralBlock", "./modelApi/creators/createEntity", "./modelApi/creators/createDivider", "./modelApi/creators/createListLevel", "./modelApi/creators/createEmptyModel", "./modelApi/common/addBlock", "./modelApi/common/addDecorators", "./modelApi/common/addDecorators", "./modelApi/common/normalizeParagraph", "./modelApi/common/normalizeContentModel", "./modelApi/common/isGeneralSegment", "./modelApi/common/unwrapBlock", "./modelApi/common/addSegment", "./modelApi/common/isEmpty", "./modelApi/common/normalizeSegment", "./modelApi/block/setParagraphNotImplicit", "./formatHandlers/utils/parseValueWithUnit", "./formatHandlers/common/borderFormatHandler", "./formatHandlers/utils/color", "./domToModel/context/createDomToModelContext", "./modelToDom/context/createModelToDomContext"], function (require, exports, domToContentModel_1, contentModelToDom_1, contentModelToText_1, childProcessor_1, entityProcessor_1, tableProcessor_1, getRegularSelectionOffsets_1, parseFormat_1, areSameFormats_1, isBlockElement_1, updateMetadata_1, isNodeOfType_1, isElementOfType_1, getObjectKeys_1, toArray_1, moveChildNodes_1, wrap_1, entityUtils_1, reuseCachedElement_1, isWhiteSpacePreserved_1, createBr_1, createListItem_1, createFormatContainer_1, createParagraph_1, createSelectionMarker_1, createTable_1, createTableCell_1, createText_1, createImage_1, createContentModelDocument_1, createParagraphDecorator_1, createGeneralSegment_1, createGeneralBlock_1, createEntity_1, createDivider_1, createListLevel_1, createEmptyModel_1, addBlock_1, addDecorators_1, addDecorators_2, normalizeParagraph_1, normalizeContentModel_1, isGeneralSegment_1, unwrapBlock_1, addSegment_1, isEmpty_1, normalizeSegment_1, setParagraphNotImplicit_1, parseValueWithUnit_1, borderFormatHandler_1, color_1, createDomToModelContext_1, createModelToDomContext_1) {
|
|
2
2
|
"use strict";
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
exports.createModelToDomConfig = exports.createModelToDomContextWithConfig = exports.createModelToDomContext = exports.createDomToModelConfig = exports.createDomToModelContextWithConfig = exports.createDomToModelContext = exports.parseColor = exports.setColor = exports.getColor = exports.DeprecatedColors = exports.BorderKeys = exports.parseValueWithUnit = exports.setParagraphNotImplicit = exports.normalizeSingleSegment = exports.isEmpty = exports.addSegment = exports.unwrapBlock = exports.isGeneralSegment = exports.normalizeContentModel = exports.normalizeParagraph = exports.addLink = exports.addCode = exports.addBlock = exports.createEmptyModel = exports.createListLevel = exports.createDivider = exports.createEntity = exports.createGeneralBlock = exports.createGeneralSegment = exports.createParagraphDecorator = exports.createContentModelDocument = exports.createImage = exports.createText = exports.createTableCell = exports.createTable = exports.createSelectionMarker = exports.createParagraph = exports.createFormatContainer = exports.createListItem = exports.createBr = exports.isWhiteSpacePreserved = exports.reuseCachedElement = exports.isEntityDelimiter = exports.addDelimiters = exports.generateEntityClassNames = exports.
|
|
4
|
+
exports.createModelToDomConfig = exports.createModelToDomContextWithConfig = exports.createModelToDomContext = exports.createDomToModelConfig = exports.createDomToModelContextWithConfig = exports.createDomToModelContext = exports.parseColor = exports.setColor = exports.getColor = exports.DeprecatedColors = exports.BorderKeys = exports.parseValueWithUnit = exports.setParagraphNotImplicit = exports.normalizeSingleSegment = exports.isEmpty = exports.addSegment = exports.unwrapBlock = exports.isGeneralSegment = exports.normalizeContentModel = exports.normalizeParagraph = exports.addLink = exports.addCode = exports.addBlock = exports.createEmptyModel = exports.createListLevel = exports.createDivider = exports.createEntity = exports.createGeneralBlock = exports.createGeneralSegment = exports.createParagraphDecorator = exports.createContentModelDocument = exports.createImage = exports.createText = exports.createTableCell = exports.createTable = exports.createSelectionMarker = exports.createParagraph = exports.createFormatContainer = exports.createListItem = exports.createBr = exports.isWhiteSpacePreserved = exports.reuseCachedElement = exports.isEntityDelimiter = exports.addDelimiters = exports.generateEntityClassNames = exports.parseEntityFormat = exports.getAllEntityWrappers = exports.isEntityElement = exports.wrap = exports.wrapAllChildNodes = exports.moveChildNodes = exports.toArray = exports.getObjectKeys = exports.isElementOfType = exports.isNodeOfType = exports.hasMetadata = exports.updateMetadata = exports.isBlockElement = exports.areSameFormats = exports.parseFormat = exports.getRegularSelectionOffsets = exports.tableProcessor = exports.entityProcessor = exports.processChildNode = exports.handleRegularSelection = exports.childProcessor = exports.contentModelToText = exports.contentModelToDom = exports.domToContentModel = void 0;
|
|
5
5
|
Object.defineProperty(exports, "domToContentModel", { enumerable: true, get: function () { return domToContentModel_1.domToContentModel; } });
|
|
6
6
|
Object.defineProperty(exports, "contentModelToDom", { enumerable: true, get: function () { return contentModelToDom_1.contentModelToDom; } });
|
|
7
7
|
Object.defineProperty(exports, "contentModelToText", { enumerable: true, get: function () { return contentModelToText_1.contentModelToText; } });
|
|
@@ -25,7 +25,7 @@ define(["require", "exports", "./domToModel/domToContentModel", "./modelToDom/co
|
|
|
25
25
|
Object.defineProperty(exports, "wrap", { enumerable: true, get: function () { return wrap_1.wrap; } });
|
|
26
26
|
Object.defineProperty(exports, "isEntityElement", { enumerable: true, get: function () { return entityUtils_1.isEntityElement; } });
|
|
27
27
|
Object.defineProperty(exports, "getAllEntityWrappers", { enumerable: true, get: function () { return entityUtils_1.getAllEntityWrappers; } });
|
|
28
|
-
Object.defineProperty(exports, "
|
|
28
|
+
Object.defineProperty(exports, "parseEntityFormat", { enumerable: true, get: function () { return entityUtils_1.parseEntityFormat; } });
|
|
29
29
|
Object.defineProperty(exports, "generateEntityClassNames", { enumerable: true, get: function () { return entityUtils_1.generateEntityClassNames; } });
|
|
30
30
|
Object.defineProperty(exports, "addDelimiters", { enumerable: true, get: function () { return entityUtils_1.addDelimiters; } });
|
|
31
31
|
Object.defineProperty(exports, "isEntityDelimiter", { enumerable: true, get: function () { return entityUtils_1.isEntityDelimiter; } });
|
package/lib-amd/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../packages-content-model/roosterjs-content-model-dom/lib/index.ts"],"names":[],"mappings":";;;;IAAS,sHAAA,iBAAiB,OAAA;IACjB,sHAAA,iBAAiB,OAAA;IACjB,wHAAA,kBAAkB,OAAA;IAGvB,gHAAA,cAAc,OAAA;IACd,wHAAA,sBAAsB,OAAA;IACtB,kHAAA,gBAAgB,OAAA;IAEX,kHAAA,eAAe,OAAA;IACf,gHAAA,cAAc,OAAA;IACd,wIAAA,0BAA0B,OAAA;IAC1B,0GAAA,WAAW,OAAA;IACX,gHAAA,cAAc,OAAA;IACd,gHAAA,cAAc,OAAA;IAEd,gHAAA,cAAc,OAAA;IAAE,6GAAA,WAAW,OAAA;IAC3B,4GAAA,YAAY,OAAA;IACZ,kHAAA,eAAe,OAAA;IACf,8GAAA,aAAa,OAAA;IACb,kGAAA,OAAO,OAAW;IAClB,gHAAA,cAAc,OAAA;IAAE,mHAAA,iBAAiB,OAAA;IACjC,4FAAA,IAAI,OAAA;IAET,8GAAA,eAAe,OAAA;IACf,mHAAA,oBAAoB,OAAA;IACpB,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../packages-content-model/roosterjs-content-model-dom/lib/index.ts"],"names":[],"mappings":";;;;IAAS,sHAAA,iBAAiB,OAAA;IACjB,sHAAA,iBAAiB,OAAA;IACjB,wHAAA,kBAAkB,OAAA;IAGvB,gHAAA,cAAc,OAAA;IACd,wHAAA,sBAAsB,OAAA;IACtB,kHAAA,gBAAgB,OAAA;IAEX,kHAAA,eAAe,OAAA;IACf,gHAAA,cAAc,OAAA;IACd,wIAAA,0BAA0B,OAAA;IAC1B,0GAAA,WAAW,OAAA;IACX,gHAAA,cAAc,OAAA;IACd,gHAAA,cAAc,OAAA;IAEd,gHAAA,cAAc,OAAA;IAAE,6GAAA,WAAW,OAAA;IAC3B,4GAAA,YAAY,OAAA;IACZ,kHAAA,eAAe,OAAA;IACf,8GAAA,aAAa,OAAA;IACb,kGAAA,OAAO,OAAW;IAClB,gHAAA,cAAc,OAAA;IAAE,mHAAA,iBAAiB,OAAA;IACjC,4FAAA,IAAI,OAAA;IAET,8GAAA,eAAe,OAAA;IACf,mHAAA,oBAAoB,OAAA;IACpB,gHAAA,iBAAiB,OAAA;IACjB,uHAAA,wBAAwB,OAAA;IACxB,4GAAA,aAAa,OAAA;IACb,gHAAA,iBAAiB,OAAA;IAEZ,wHAAA,kBAAkB,OAAA;IAClB,8HAAA,qBAAqB,OAAA;IAErB,oGAAA,QAAQ,OAAA;IACR,gHAAA,cAAc,OAAA;IACd,8HAAA,qBAAqB,OAAA;IACrB,kHAAA,eAAe,OAAA;IACf,8HAAA,qBAAqB,OAAA;IACrB,0GAAA,WAAW,OAAA;IACX,kHAAA,eAAe,OAAA;IACf,wGAAA,UAAU,OAAA;IACV,0GAAA,WAAW,OAAA;IACX,wIAAA,0BAA0B,OAAA;IAC1B,oIAAA,wBAAwB,OAAA;IACxB,4HAAA,oBAAoB,OAAA;IACpB,wHAAA,kBAAkB,OAAA;IAClB,4GAAA,YAAY,OAAA;IACZ,8GAAA,aAAa,OAAA;IACb,kHAAA,eAAe,OAAA;IACf,oHAAA,gBAAgB,OAAA;IAEhB,oGAAA,QAAQ,OAAA;IACR,wGAAA,OAAO,OAAA;IACP,wGAAA,OAAO,OAAA;IACP,wHAAA,kBAAkB,OAAA;IAElB,8HAAA,qBAAqB,OAAA;IACrB,oHAAA,gBAAgB,OAAA;IAChB,0GAAA,WAAW,OAAA;IACX,wGAAA,UAAU,OAAA;IACV,kGAAA,OAAO,OAAA;IACP,0HAAA,sBAAsB,OAAA;IAEtB,kIAAA,uBAAuB,OAAA;IAEvB,wHAAA,kBAAkB,OAAA;IAClB,iHAAA,UAAU,OAAA;IACV,yGAAA,gBAAgB,OAAA;IAAE,iGAAA,QAAQ,OAAA;IAAE,iGAAA,QAAQ,OAAA;IAAE,mGAAA,UAAU,OAAA;IAGrD,kIAAA,uBAAuB,OAAA;IACvB,4IAAA,iCAAiC,OAAA;IACjC,iIAAA,sBAAsB,OAAA;IAGtB,kIAAA,uBAAuB,OAAA;IACvB,4IAAA,iCAAiC,OAAA;IACjC,iIAAA,sBAAsB,OAAA","sourcesContent":["export { domToContentModel } from './domToModel/domToContentModel';\nexport { contentModelToDom } from './modelToDom/contentModelToDom';\nexport { contentModelToText } from './modelToText/contentModelToText';\n\nexport {\n childProcessor,\n handleRegularSelection,\n processChildNode,\n} from './domToModel/processors/childProcessor';\nexport { entityProcessor } from './domToModel/processors/entityProcessor';\nexport { tableProcessor } from './domToModel/processors/tableProcessor';\nexport { getRegularSelectionOffsets } from './domToModel/utils/getRegularSelectionOffsets';\nexport { parseFormat } from './domToModel/utils/parseFormat';\nexport { areSameFormats } from './domToModel/utils/areSameFormats';\nexport { isBlockElement } from './domToModel/utils/isBlockElement';\n\nexport { updateMetadata, hasMetadata } from './domUtils/metadata/updateMetadata';\nexport { isNodeOfType, NodeTypeMap } from './domUtils/isNodeOfType';\nexport { isElementOfType } from './domUtils/isElementOfType';\nexport { getObjectKeys } from './domUtils/getObjectKeys';\nexport { default as toArray } from './domUtils/toArray';\nexport { moveChildNodes, wrapAllChildNodes } from './domUtils/moveChildNodes';\nexport { wrap } from './domUtils/wrap';\nexport {\n isEntityElement,\n getAllEntityWrappers,\n parseEntityFormat,\n generateEntityClassNames,\n addDelimiters,\n isEntityDelimiter,\n} from './domUtils/entityUtils';\nexport { reuseCachedElement } from './domUtils/reuseCachedElement';\nexport { isWhiteSpacePreserved } from './domUtils/isWhiteSpacePreserved';\n\nexport { createBr } from './modelApi/creators/createBr';\nexport { createListItem } from './modelApi/creators/createListItem';\nexport { createFormatContainer } from './modelApi/creators/createFormatContainer';\nexport { createParagraph } from './modelApi/creators/createParagraph';\nexport { createSelectionMarker } from './modelApi/creators/createSelectionMarker';\nexport { createTable } from './modelApi/creators/createTable';\nexport { createTableCell } from './modelApi/creators/createTableCell';\nexport { createText } from './modelApi/creators/createText';\nexport { createImage } from './modelApi/creators/createImage';\nexport { createContentModelDocument } from './modelApi/creators/createContentModelDocument';\nexport { createParagraphDecorator } from './modelApi/creators/createParagraphDecorator';\nexport { createGeneralSegment } from './modelApi/creators/createGeneralSegment';\nexport { createGeneralBlock } from './modelApi/creators/createGeneralBlock';\nexport { createEntity } from './modelApi/creators/createEntity';\nexport { createDivider } from './modelApi/creators/createDivider';\nexport { createListLevel } from './modelApi/creators/createListLevel';\nexport { createEmptyModel } from './modelApi/creators/createEmptyModel';\n\nexport { addBlock } from './modelApi/common/addBlock';\nexport { addCode } from './modelApi/common/addDecorators';\nexport { addLink } from './modelApi/common/addDecorators';\nexport { normalizeParagraph } from './modelApi/common/normalizeParagraph';\n\nexport { normalizeContentModel } from './modelApi/common/normalizeContentModel';\nexport { isGeneralSegment } from './modelApi/common/isGeneralSegment';\nexport { unwrapBlock } from './modelApi/common/unwrapBlock';\nexport { addSegment } from './modelApi/common/addSegment';\nexport { isEmpty } from './modelApi/common/isEmpty';\nexport { normalizeSingleSegment } from './modelApi/common/normalizeSegment';\n\nexport { setParagraphNotImplicit } from './modelApi/block/setParagraphNotImplicit';\n\nexport { parseValueWithUnit } from './formatHandlers/utils/parseValueWithUnit';\nexport { BorderKeys } from './formatHandlers/common/borderFormatHandler';\nexport { DeprecatedColors, getColor, setColor, parseColor } from './formatHandlers/utils/color';\n\nexport {\n createDomToModelContext,\n createDomToModelContextWithConfig,\n createDomToModelConfig,\n} from './domToModel/context/createDomToModelContext';\nexport {\n createModelToDomContext,\n createModelToDomContextWithConfig,\n createModelToDomConfig,\n} from './modelToDom/context/createModelToDomContext';\n"]}
|
|
@@ -30,6 +30,7 @@ define(["require", "exports", "../../domToModel/utils/areSameFormats", "../creat
|
|
|
30
30
|
}
|
|
31
31
|
removeEmptyLinks(paragraph);
|
|
32
32
|
removeEmptySegments(paragraph);
|
|
33
|
+
moveUpSegmentFormat(paragraph);
|
|
33
34
|
}
|
|
34
35
|
exports.normalizeParagraph = normalizeParagraph;
|
|
35
36
|
function removeEmptySegments(block) {
|
|
@@ -59,5 +60,32 @@ define(["require", "exports", "../../domToModel/utils/areSameFormats", "../creat
|
|
|
59
60
|
}
|
|
60
61
|
}
|
|
61
62
|
}
|
|
63
|
+
var formatsToMoveUp = ['fontFamily', 'fontSize', 'textColor'];
|
|
64
|
+
// When all segments are sharing the same segment format (font name, size and color), we can move its format to paragraph
|
|
65
|
+
function moveUpSegmentFormat(paragraph) {
|
|
66
|
+
if (!paragraph.decorator) {
|
|
67
|
+
var segments_1 = paragraph.segments.filter(function (x) { return x.segmentType != 'SelectionMarker'; });
|
|
68
|
+
var target_1 = paragraph.segmentFormat || {};
|
|
69
|
+
var changed_1 = false;
|
|
70
|
+
formatsToMoveUp.forEach(function (key) {
|
|
71
|
+
changed_1 = internalMoveUpSegmentFormat(segments_1, target_1, key) || changed_1;
|
|
72
|
+
});
|
|
73
|
+
if (changed_1) {
|
|
74
|
+
paragraph.segmentFormat = target_1;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
function internalMoveUpSegmentFormat(segments, target, formatKey) {
|
|
79
|
+
var _a;
|
|
80
|
+
var firstFormat = (_a = segments[0]) === null || _a === void 0 ? void 0 : _a.format;
|
|
81
|
+
if ((firstFormat === null || firstFormat === void 0 ? void 0 : firstFormat[formatKey]) &&
|
|
82
|
+
segments.every(function (segment) { return segment.format[formatKey] == firstFormat[formatKey]; })) {
|
|
83
|
+
target[formatKey] = firstFormat[formatKey];
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
62
90
|
});
|
|
63
91
|
//# sourceMappingURL=normalizeParagraph.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"normalizeParagraph.js","sourceRoot":"","sources":["../../../../../packages-content-model/roosterjs-content-model-dom/lib/modelApi/common/normalizeParagraph.ts"],"names":[],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"normalizeParagraph.js","sourceRoot":"","sources":["../../../../../packages-content-model/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 { normalizeAllSegments } from './normalizeSegment';\nimport type {\n ContentModelParagraph,\n ContentModelSegment,\n ContentModelSegmentFormat,\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: ContentModelParagraph) {\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 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 segments.pop();\n }\n }\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 removeEmptySegments(block: ContentModelParagraph) {\n for (let j = block.segments.length - 1; j >= 0; j--) {\n if (isSegmentEmpty(block.segments[j])) {\n block.segments.splice(j, 1);\n }\n }\n}\n\nfunction removeEmptyLinks(paragraph: ContentModelParagraph) {\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 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 delete marker.link;\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: ContentModelParagraph) {\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 paragraph.segmentFormat = target;\n }\n }\n}\n\nfunction internalMoveUpSegmentFormat(\n segments: ContentModelSegment[],\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 ) {\n target[formatKey] = firstFormat[formatKey];\n return true;\n } else {\n return false;\n }\n}\n"]}
|
|
@@ -6,12 +6,26 @@ import { createSelectionMarker } from '../../modelApi/creators/createSelectionMa
|
|
|
6
6
|
* @internal
|
|
7
7
|
*/
|
|
8
8
|
export function addSelectionMarker(group, context, container, offset) {
|
|
9
|
+
var lastPara = group.blocks[group.blocks.length - 1];
|
|
10
|
+
var formatFromParagraph = !lastPara || lastPara.blockType != 'Paragraph'
|
|
11
|
+
? {}
|
|
12
|
+
: lastPara.decorator
|
|
13
|
+
? {
|
|
14
|
+
fontFamily: lastPara.decorator.format.fontFamily,
|
|
15
|
+
fontSize: lastPara.decorator.format.fontSize,
|
|
16
|
+
}
|
|
17
|
+
: lastPara.segmentFormat
|
|
18
|
+
? {
|
|
19
|
+
fontFamily: lastPara.segmentFormat.fontFamily,
|
|
20
|
+
fontSize: lastPara.segmentFormat.fontSize,
|
|
21
|
+
}
|
|
22
|
+
: {};
|
|
9
23
|
var pendingFormat = context.pendingFormat &&
|
|
10
24
|
context.pendingFormat.posContainer === container &&
|
|
11
25
|
context.pendingFormat.posOffset === offset
|
|
12
26
|
? context.pendingFormat.format
|
|
13
27
|
: undefined;
|
|
14
|
-
var segmentFormat = __assign(__assign(__assign({}, context.defaultFormat), context.segmentFormat), pendingFormat);
|
|
28
|
+
var segmentFormat = __assign(__assign(__assign(__assign({}, context.defaultFormat), formatFromParagraph), context.segmentFormat), pendingFormat);
|
|
15
29
|
var marker = createSelectionMarker(segmentFormat);
|
|
16
30
|
addDecorators(marker, context);
|
|
17
31
|
addSegment(group, marker, context.blockFormat, segmentFormat);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"addSelectionMarker.js","sourceRoot":"","sources":["../../../../../packages-content-model/roosterjs-content-model-dom/lib/domToModel/utils/addSelectionMarker.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,qCAAqC,CAAC;AACpE,OAAO,EAAE,UAAU,EAAE,MAAM,kCAAkC,CAAC;AAC9D,OAAO,EAAE,qBAAqB,EAAE,MAAM,+CAA+C,CAAC;
|
|
1
|
+
{"version":3,"file":"addSelectionMarker.js","sourceRoot":"","sources":["../../../../../packages-content-model/roosterjs-content-model-dom/lib/domToModel/utils/addSelectionMarker.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,qCAAqC,CAAC;AACpE,OAAO,EAAE,UAAU,EAAE,MAAM,kCAAkC,CAAC;AAC9D,OAAO,EAAE,qBAAqB,EAAE,MAAM,+CAA+C,CAAC;AAOtF;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAC9B,KAA6B,EAC7B,OAA0B,EAC1B,SAAgB,EAChB,MAAe;IAEf,IAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACvD,IAAM,mBAAmB,GACrB,CAAC,QAAQ,IAAI,QAAQ,CAAC,SAAS,IAAI,WAAW;QAC1C,CAAC,CAAC,EAAE;QACJ,CAAC,CAAC,QAAQ,CAAC,SAAS;YACpB,CAAC,CAAC;gBACI,UAAU,EAAE,QAAQ,CAAC,SAAS,CAAC,MAAM,CAAC,UAAU;gBAChD,QAAQ,EAAE,QAAQ,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ;aAC/C;YACH,CAAC,CAAC,QAAQ,CAAC,aAAa;gBACxB,CAAC,CAAC;oBACI,UAAU,EAAE,QAAQ,CAAC,aAAa,CAAC,UAAU;oBAC7C,QAAQ,EAAE,QAAQ,CAAC,aAAa,CAAC,QAAQ;iBAC5C;gBACH,CAAC,CAAC,EAAE,CAAC;IAEb,IAAM,aAAa,GACf,OAAO,CAAC,aAAa;QACrB,OAAO,CAAC,aAAa,CAAC,YAAY,KAAK,SAAS;QAChD,OAAO,CAAC,aAAa,CAAC,SAAS,KAAK,MAAM;QACtC,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM;QAC9B,CAAC,CAAC,SAAS,CAAC;IACpB,IAAM,aAAa,2CACZ,OAAO,CAAC,aAAa,GACrB,mBAAmB,GACnB,OAAO,CAAC,aAAa,GACrB,aAAa,CACnB,CAAC;IACF,IAAM,MAAM,GAAG,qBAAqB,CAAC,aAAa,CAAC,CAAC;IAEpD,aAAa,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAE/B,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,WAAW,EAAE,aAAa,CAAC,CAAC;AAClE,CAAC","sourcesContent":["import { addDecorators } from '../../modelApi/common/addDecorators';\nimport { addSegment } from '../../modelApi/common/addSegment';\nimport { createSelectionMarker } from '../../modelApi/creators/createSelectionMarker';\nimport type {\n ContentModelBlockGroup,\n ContentModelSegmentFormat,\n DomToModelContext,\n} from 'roosterjs-content-model-types';\n\n/**\n * @internal\n */\nexport function addSelectionMarker(\n group: ContentModelBlockGroup,\n context: DomToModelContext,\n container?: Node,\n offset?: number\n) {\n const lastPara = group.blocks[group.blocks.length - 1];\n const formatFromParagraph: ContentModelSegmentFormat =\n !lastPara || lastPara.blockType != 'Paragraph'\n ? {}\n : lastPara.decorator\n ? {\n fontFamily: lastPara.decorator.format.fontFamily,\n fontSize: lastPara.decorator.format.fontSize,\n }\n : lastPara.segmentFormat\n ? {\n fontFamily: lastPara.segmentFormat.fontFamily,\n fontSize: lastPara.segmentFormat.fontSize,\n }\n : {};\n\n const pendingFormat =\n context.pendingFormat &&\n context.pendingFormat.posContainer === container &&\n context.pendingFormat.posOffset === offset\n ? context.pendingFormat.format\n : undefined;\n const segmentFormat = {\n ...context.defaultFormat,\n ...formatFromParagraph,\n ...context.segmentFormat,\n ...pendingFormat,\n };\n const marker = createSelectionMarker(segmentFormat);\n\n addDecorators(marker, context);\n\n addSegment(group, marker, context.blockFormat, segmentFormat);\n}\n"]}
|
|
@@ -10,11 +10,11 @@ export declare function isEntityElement(node: Node): boolean;
|
|
|
10
10
|
*/
|
|
11
11
|
export declare function getAllEntityWrappers(root: HTMLElement): HTMLElement[];
|
|
12
12
|
/**
|
|
13
|
-
* Parse entity
|
|
14
|
-
* @param
|
|
15
|
-
* @
|
|
13
|
+
* Parse entity format from entity wrapper element
|
|
14
|
+
* @param wrapper The wrapper element to parse entity format from
|
|
15
|
+
* @returns Entity format
|
|
16
16
|
*/
|
|
17
|
-
export declare function
|
|
17
|
+
export declare function parseEntityFormat(wrapper: HTMLElement): ContentModelEntityFormat;
|
|
18
18
|
/**
|
|
19
19
|
* Generate Entity class names for an entity wrapper
|
|
20
20
|
* @param format The source entity format object
|
|
@@ -24,12 +24,29 @@ export function isEntityElement(node) {
|
|
|
24
24
|
export function getAllEntityWrappers(root) {
|
|
25
25
|
return toArray(root.querySelectorAll('.' + ENTITY_INFO_NAME));
|
|
26
26
|
}
|
|
27
|
+
/**
|
|
28
|
+
* Parse entity format from entity wrapper element
|
|
29
|
+
* @param wrapper The wrapper element to parse entity format from
|
|
30
|
+
* @returns Entity format
|
|
31
|
+
*/
|
|
32
|
+
export function parseEntityFormat(wrapper) {
|
|
33
|
+
var isEntity = false;
|
|
34
|
+
var format = {};
|
|
35
|
+
wrapper.classList.forEach(function (name) {
|
|
36
|
+
isEntity = parseEntityClassName(name, format) || isEntity;
|
|
37
|
+
});
|
|
38
|
+
if (!isEntity) {
|
|
39
|
+
format.isFakeEntity = true;
|
|
40
|
+
format.isReadonly = !wrapper.isContentEditable;
|
|
41
|
+
}
|
|
42
|
+
return format;
|
|
43
|
+
}
|
|
27
44
|
/**
|
|
28
45
|
* Parse entity class names from entity wrapper element
|
|
29
46
|
* @param className Class names of entity
|
|
30
47
|
* @param format The output entity format object
|
|
31
48
|
*/
|
|
32
|
-
|
|
49
|
+
function parseEntityClassName(className, format) {
|
|
33
50
|
if (className == ENTITY_INFO_NAME) {
|
|
34
51
|
return true;
|
|
35
52
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entityUtils.js","sourceRoot":"","sources":["../../../../packages-content-model/roosterjs-content-model-dom/lib/domUtils/entityUtils.ts"],"names":[],"mappings":";AAAA,OAAO,OAAO,MAAM,WAAW,CAAC;AAChC,OAAO,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAO9C,IAAM,gBAAgB,GAAG,SAAS,CAAC;AACnC,IAAM,kBAAkB,GAAG,SAAS,CAAC;AACrC,IAAM,gBAAgB,GAAG,OAAO,CAAC;AACjC,IAAM,sBAAsB,GAAG,aAAa,CAAC;AAC7C,IAAM,gBAAgB,GAAG,QAAQ,CAAC;AAClC,IAAM,gBAAgB,GAAG,uBAAuB,CAAC;AACjD,IAAM,eAAe,GAAG,sBAAsB,CAAC;AAE/C;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,IAAU;IACtC,OAAO,YAAY,CAAC,IAAI,EAAE,cAAc,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC;AAC3F,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAAC,IAAiB;IAClD,OAAO,OAAO,CAAC,IAAI,CAAC,gBAAgB,CAAC,GAAG,GAAG,gBAAgB,CAAC,CAAkB,CAAC;AACnF,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,
|
|
1
|
+
{"version":3,"file":"entityUtils.js","sourceRoot":"","sources":["../../../../packages-content-model/roosterjs-content-model-dom/lib/domUtils/entityUtils.ts"],"names":[],"mappings":"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","sourcesContent":["import toArray from './toArray';\nimport { applyFormat } from '../modelToDom/utils/applyFormat';\nimport { isElementOfType } from './isElementOfType';\nimport { isNodeOfType } from './isNodeOfType';\nimport type {\n ContentModelEntityFormat,\n ContentModelSegmentFormat,\n ModelToDomContext,\n} from 'roosterjs-content-model-types';\n\nconst ENTITY_INFO_NAME = '_Entity';\nconst ENTITY_TYPE_PREFIX = '_EType_';\nconst ENTITY_ID_PREFIX = '_EId_';\nconst ENTITY_READONLY_PREFIX = '_EReadonly_';\nconst ZERO_WIDTH_SPACE = '\\u200B';\nconst DELIMITER_BEFORE = 'entityDelimiterBefore';\nconst DELIMITER_AFTER = 'entityDelimiterAfter';\n\n/**\n * Check if the given DOM Node is an entity wrapper element\n */\nexport function isEntityElement(node: Node): boolean {\n return isNodeOfType(node, 'ELEMENT_NODE') && node.classList.contains(ENTITY_INFO_NAME);\n}\n\n/**\n * Get all entity wrapper elements under the given root element\n * @param root The root element to query from\n * @returns An array of entity wrapper elements\n */\nexport function getAllEntityWrappers(root: HTMLElement): HTMLElement[] {\n return toArray(root.querySelectorAll('.' + ENTITY_INFO_NAME)) as HTMLElement[];\n}\n\n/**\n * Parse entity format from entity wrapper element\n * @param wrapper The wrapper element to parse entity format from\n * @returns Entity format\n */\nexport function parseEntityFormat(wrapper: HTMLElement): ContentModelEntityFormat {\n let isEntity = false;\n const format: ContentModelEntityFormat = {};\n\n wrapper.classList.forEach(name => {\n isEntity = parseEntityClassName(name, format) || isEntity;\n });\n\n if (!isEntity) {\n format.isFakeEntity = true;\n format.isReadonly = !wrapper.isContentEditable;\n }\n\n return format;\n}\n\n/**\n * Parse entity class names from entity wrapper element\n * @param className Class names of entity\n * @param format The output entity format object\n */\nfunction parseEntityClassName(\n className: string,\n format: ContentModelEntityFormat\n): boolean | undefined {\n if (className == ENTITY_INFO_NAME) {\n return true;\n } else if (className.indexOf(ENTITY_TYPE_PREFIX) == 0) {\n format.entityType = className.substring(ENTITY_TYPE_PREFIX.length);\n } else if (className.indexOf(ENTITY_ID_PREFIX) == 0) {\n format.id = className.substring(ENTITY_ID_PREFIX.length);\n } else if (className.indexOf(ENTITY_READONLY_PREFIX) == 0) {\n format.isReadonly = className.substring(ENTITY_READONLY_PREFIX.length) == '1';\n }\n}\n\n/**\n * Generate Entity class names for an entity wrapper\n * @param format The source entity format object\n * @returns A combined CSS class name string for entity wrapper\n */\nexport function generateEntityClassNames(format: ContentModelEntityFormat): string {\n return format.isFakeEntity\n ? ''\n : `${ENTITY_INFO_NAME} ${ENTITY_TYPE_PREFIX}${format.entityType ?? ''} ${\n format.id ? `${ENTITY_ID_PREFIX}${format.id} ` : ''\n }${ENTITY_READONLY_PREFIX}${format.isReadonly ? '1' : '0'}`;\n}\n\n/**\n * Checks whether the node provided is a Entity delimiter\n * @param node the node to check\n * @return true if it is a delimiter\n */\nexport function isEntityDelimiter(element: HTMLElement): boolean {\n return (\n isElementOfType(element, 'span') &&\n (element.classList.contains(DELIMITER_AFTER) ||\n element.classList.contains(DELIMITER_BEFORE)) &&\n element.textContent === ZERO_WIDTH_SPACE\n );\n}\n\n/**\n * Adds delimiters to the element provided. If the delimiters already exists, will not be added\n * @param element the node to add the delimiters\n * @param format format to set to the delimiters, so when typing inside of one the format is not lost\n * @param context Model to Dom context to use.\n */\nexport function addDelimiters(\n doc: Document,\n element: HTMLElement,\n format?: ContentModelSegmentFormat | null,\n context?: ModelToDomContext\n): HTMLElement[] {\n let [delimiterAfter, delimiterBefore] = getDelimiters(element);\n\n if (!delimiterAfter) {\n delimiterAfter = insertDelimiter(doc, element, true /*isAfter*/);\n if (context && format) {\n applyFormat(delimiterAfter, context.formatAppliers.segment, format, context);\n }\n }\n\n if (!delimiterBefore) {\n delimiterBefore = insertDelimiter(doc, element, false /*isAfter*/);\n if (context && format) {\n applyFormat(delimiterBefore, context.formatAppliers.segment, format, context);\n }\n }\n\n return [delimiterAfter, delimiterBefore];\n}\n\nfunction getDelimiters(entityWrapper: HTMLElement): (HTMLElement | undefined)[] {\n const result: (HTMLElement | undefined)[] = [];\n const { nextElementSibling, previousElementSibling } = entityWrapper;\n result.push(\n isDelimiter(nextElementSibling, DELIMITER_AFTER),\n isDelimiter(previousElementSibling, DELIMITER_BEFORE)\n );\n\n return result;\n}\n\nfunction isDelimiter(el: Element | null, className: string): HTMLElement | undefined {\n return el?.classList.contains(className) && el.textContent == ZERO_WIDTH_SPACE\n ? (el as HTMLElement)\n : undefined;\n}\n\nfunction insertDelimiter(doc: Document, element: Element, isAfter: boolean) {\n const span = doc.createElement('span');\n\n span.className = isAfter ? DELIMITER_AFTER : DELIMITER_BEFORE;\n span.appendChild(doc.createTextNode(ZERO_WIDTH_SPACE));\n element.parentNode?.insertBefore(span, isAfter ? element.nextSibling : element);\n\n return span;\n}\n"]}
|
|
@@ -11,10 +11,11 @@ import { isEntityElement } from './entityUtils';
|
|
|
11
11
|
export function reuseCachedElement(parent, element, refNode) {
|
|
12
12
|
var _a;
|
|
13
13
|
if (element.parentNode == parent) {
|
|
14
|
+
var isEntity = isEntityElement(element);
|
|
14
15
|
// Remove nodes before the one we are hitting since they don't appear in Content Model at this position.
|
|
15
16
|
// But we don't want to touch entity since it would better to keep entity at its place unless it is removed
|
|
16
17
|
// In that case we will remove it after we have handled all other nodes
|
|
17
|
-
while (refNode && refNode != element && !isEntityElement(refNode)) {
|
|
18
|
+
while (refNode && refNode != element && (isEntity || !isEntityElement(refNode))) {
|
|
18
19
|
var next = refNode.nextSibling;
|
|
19
20
|
(_a = refNode.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(refNode);
|
|
20
21
|
refNode = next;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reuseCachedElement.js","sourceRoot":"","sources":["../../../../packages-content-model/roosterjs-content-model-dom/lib/domUtils/reuseCachedElement.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEhD;;;;;;;;GAQG;AACH,MAAM,UAAU,kBAAkB,CAAC,MAAY,EAAE,OAAa,EAAE,OAAoB;;IAChF,IAAI,OAAO,CAAC,UAAU,IAAI,MAAM,EAAE;QAC9B,wGAAwG;QACxG,2GAA2G;QAC3G,uEAAuE;QACvE,OAAO,OAAO,IAAI,OAAO,IAAI,OAAO,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,EAAE;
|
|
1
|
+
{"version":3,"file":"reuseCachedElement.js","sourceRoot":"","sources":["../../../../packages-content-model/roosterjs-content-model-dom/lib/domUtils/reuseCachedElement.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEhD;;;;;;;;GAQG;AACH,MAAM,UAAU,kBAAkB,CAAC,MAAY,EAAE,OAAa,EAAE,OAAoB;;IAChF,IAAI,OAAO,CAAC,UAAU,IAAI,MAAM,EAAE;QAC9B,IAAM,QAAQ,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;QAE1C,wGAAwG;QACxG,2GAA2G;QAC3G,uEAAuE;QACvE,OAAO,OAAO,IAAI,OAAO,IAAI,OAAO,IAAI,CAAC,QAAQ,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,EAAE;YAC7E,IAAM,IAAI,GAAG,OAAO,CAAC,WAAW,CAAC;YAEjC,MAAA,OAAO,CAAC,UAAU,0CAAE,WAAW,CAAC,OAAO,CAAC,CAAC;YACzC,OAAO,GAAG,IAAI,CAAC;SAClB;QAED,IAAI,OAAO,IAAI,OAAO,IAAI,OAAO,EAAE;YAC/B,OAAO,GAAG,OAAO,CAAC,WAAW,CAAC;SACjC;aAAM;YACH,MAAM,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;SACzC;KACJ;SAAM;QACH,MAAM,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;KACzC;IAED,OAAO,OAAO,CAAC;AACnB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,UAAU,CAAC,IAAU;;IACjC,IAAM,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC;IAC9B,MAAA,IAAI,CAAC,UAAU,0CAAE,WAAW,CAAC,IAAI,CAAC,CAAC;IAEnC,OAAO,IAAI,CAAC;AAChB,CAAC","sourcesContent":["import { isEntityElement } from './entityUtils';\n\n/**\n * When set a DOM tree into editor, reuse the existing element in editor and no need to change it\n * @param param Parent node of the reused element\n * @param element The element to keep in parent node\n * @param refNode Reference node, it is point to current node that is being processed. It must be a child of parent node, or null.\n * We will start processing from this node, if it is not the same with element, remove it and keep processing its next sibling,\n * until we see an element that is the same with the passed in element or null.\n * @returns The new reference element\n */\nexport function reuseCachedElement(parent: Node, element: Node, refNode: Node | null): Node | null {\n if (element.parentNode == parent) {\n const isEntity = isEntityElement(element);\n\n // Remove nodes before the one we are hitting since they don't appear in Content Model at this position.\n // But we don't want to touch entity since it would better to keep entity at its place unless it is removed\n // In that case we will remove it after we have handled all other nodes\n while (refNode && refNode != element && (isEntity || !isEntityElement(refNode))) {\n const next = refNode.nextSibling;\n\n refNode.parentNode?.removeChild(refNode);\n refNode = next;\n }\n\n if (refNode && refNode == element) {\n refNode = refNode.nextSibling;\n } else {\n parent.insertBefore(element, refNode);\n }\n } else {\n parent.insertBefore(element, refNode);\n }\n\n return refNode;\n}\n\n/**\n * @internal\n */\nexport function removeNode(node: Node): Node | null {\n const next = node.nextSibling;\n node.parentNode?.removeChild(node);\n\n return next;\n}\n"]}
|
|
@@ -1,17 +1,10 @@
|
|
|
1
|
-
import { generateEntityClassNames,
|
|
1
|
+
import { generateEntityClassNames, parseEntityFormat } from '../../domUtils/entityUtils';
|
|
2
2
|
/**
|
|
3
3
|
* @internal
|
|
4
4
|
*/
|
|
5
5
|
export var entityFormatHandler = {
|
|
6
6
|
parse: function (format, element) {
|
|
7
|
-
|
|
8
|
-
element.classList.forEach(function (name) {
|
|
9
|
-
isEntity = parseEntityClassName(name, format) || isEntity;
|
|
10
|
-
});
|
|
11
|
-
if (!isEntity) {
|
|
12
|
-
format.isFakeEntity = true;
|
|
13
|
-
format.isReadonly = !element.isContentEditable;
|
|
14
|
-
}
|
|
7
|
+
Object.assign(format, parseEntityFormat(element));
|
|
15
8
|
},
|
|
16
9
|
apply: function (format, element) {
|
|
17
10
|
if (!format.isFakeEntity) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entityFormatHandler.js","sourceRoot":"","sources":["../../../../../packages-content-model/roosterjs-content-model-dom/lib/formatHandlers/entity/entityFormatHandler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,
|
|
1
|
+
{"version":3,"file":"entityFormatHandler.js","sourceRoot":"","sources":["../../../../../packages-content-model/roosterjs-content-model-dom/lib/formatHandlers/entity/entityFormatHandler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAIzF;;GAEG;AACH,MAAM,CAAC,IAAM,mBAAmB,GAA+C;IAC3E,KAAK,EAAE,UAAC,MAAM,EAAE,OAAO;QACnB,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC;IACtD,CAAC;IAED,KAAK,EAAE,UAAC,MAAM,EAAE,OAAO;QACnB,IAAI,CAAC,MAAM,CAAC,YAAY,EAAE;YACtB,OAAO,CAAC,SAAS,GAAG,wBAAwB,CAAC,MAAM,CAAC,CAAC;SACxD;QAED,IAAI,MAAM,CAAC,UAAU,EAAE;YACnB,OAAO,CAAC,eAAe,GAAG,OAAO,CAAC;SACrC;aAAM;YACH,OAAO,CAAC,eAAe,CAAC,iBAAiB,CAAC,CAAC;SAC9C;IACL,CAAC;CACJ,CAAC","sourcesContent":["import { generateEntityClassNames, parseEntityFormat } from '../../domUtils/entityUtils';\nimport type { EntityInfoFormat, IdFormat } from 'roosterjs-content-model-types';\nimport type { FormatHandler } from '../FormatHandler';\n\n/**\n * @internal\n */\nexport const entityFormatHandler: FormatHandler<EntityInfoFormat & IdFormat> = {\n parse: (format, element) => {\n Object.assign(format, parseEntityFormat(element));\n },\n\n apply: (format, element) => {\n if (!format.isFakeEntity) {\n element.className = generateEntityClassNames(format);\n }\n\n if (format.isReadonly) {\n element.contentEditable = 'false';\n } else {\n element.removeAttribute('contenteditable');\n }\n },\n};\n"]}
|
package/lib-mjs/index.d.ts
CHANGED
|
@@ -15,7 +15,7 @@ export { getObjectKeys } from './domUtils/getObjectKeys';
|
|
|
15
15
|
export { default as toArray } from './domUtils/toArray';
|
|
16
16
|
export { moveChildNodes, wrapAllChildNodes } from './domUtils/moveChildNodes';
|
|
17
17
|
export { wrap } from './domUtils/wrap';
|
|
18
|
-
export { isEntityElement, getAllEntityWrappers,
|
|
18
|
+
export { isEntityElement, getAllEntityWrappers, parseEntityFormat, generateEntityClassNames, addDelimiters, isEntityDelimiter, } from './domUtils/entityUtils';
|
|
19
19
|
export { reuseCachedElement } from './domUtils/reuseCachedElement';
|
|
20
20
|
export { isWhiteSpacePreserved } from './domUtils/isWhiteSpacePreserved';
|
|
21
21
|
export { createBr } from './modelApi/creators/createBr';
|
package/lib-mjs/index.js
CHANGED
|
@@ -15,7 +15,7 @@ export { getObjectKeys } from './domUtils/getObjectKeys';
|
|
|
15
15
|
export { default as toArray } from './domUtils/toArray';
|
|
16
16
|
export { moveChildNodes, wrapAllChildNodes } from './domUtils/moveChildNodes';
|
|
17
17
|
export { wrap } from './domUtils/wrap';
|
|
18
|
-
export { isEntityElement, getAllEntityWrappers,
|
|
18
|
+
export { isEntityElement, getAllEntityWrappers, parseEntityFormat, generateEntityClassNames, addDelimiters, isEntityDelimiter, } from './domUtils/entityUtils';
|
|
19
19
|
export { reuseCachedElement } from './domUtils/reuseCachedElement';
|
|
20
20
|
export { isWhiteSpacePreserved } from './domUtils/isWhiteSpacePreserved';
|
|
21
21
|
export { createBr } from './modelApi/creators/createBr';
|
package/lib-mjs/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../packages-content-model/roosterjs-content-model-dom/lib/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AACnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AACnE,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AAEtE,OAAO,EACH,cAAc,EACd,sBAAsB,EACtB,gBAAgB,GACnB,MAAM,wCAAwC,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,yCAAyC,CAAC;AAC1E,OAAO,EAAE,cAAc,EAAE,MAAM,wCAAwC,CAAC;AACxE,OAAO,EAAE,0BAA0B,EAAE,MAAM,+CAA+C,CAAC;AAC3F,OAAO,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAC7D,OAAO,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AACnE,OAAO,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AAEnE,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,oCAAoC,CAAC;AACjF,OAAO,EAAE,YAAY,EAAe,MAAM,yBAAyB,CAAC;AACpE,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9E,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AACvC,OAAO,EACH,eAAe,EACf,oBAAoB,EACpB,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../packages-content-model/roosterjs-content-model-dom/lib/index.ts"],"names":[],"mappings":"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","sourcesContent":["export { domToContentModel } from './domToModel/domToContentModel';\nexport { contentModelToDom } from './modelToDom/contentModelToDom';\nexport { contentModelToText } from './modelToText/contentModelToText';\n\nexport {\n childProcessor,\n handleRegularSelection,\n processChildNode,\n} from './domToModel/processors/childProcessor';\nexport { entityProcessor } from './domToModel/processors/entityProcessor';\nexport { tableProcessor } from './domToModel/processors/tableProcessor';\nexport { getRegularSelectionOffsets } from './domToModel/utils/getRegularSelectionOffsets';\nexport { parseFormat } from './domToModel/utils/parseFormat';\nexport { areSameFormats } from './domToModel/utils/areSameFormats';\nexport { isBlockElement } from './domToModel/utils/isBlockElement';\n\nexport { updateMetadata, hasMetadata } from './domUtils/metadata/updateMetadata';\nexport { isNodeOfType, NodeTypeMap } from './domUtils/isNodeOfType';\nexport { isElementOfType } from './domUtils/isElementOfType';\nexport { getObjectKeys } from './domUtils/getObjectKeys';\nexport { default as toArray } from './domUtils/toArray';\nexport { moveChildNodes, wrapAllChildNodes } from './domUtils/moveChildNodes';\nexport { wrap } from './domUtils/wrap';\nexport {\n isEntityElement,\n getAllEntityWrappers,\n parseEntityFormat,\n generateEntityClassNames,\n addDelimiters,\n isEntityDelimiter,\n} from './domUtils/entityUtils';\nexport { reuseCachedElement } from './domUtils/reuseCachedElement';\nexport { isWhiteSpacePreserved } from './domUtils/isWhiteSpacePreserved';\n\nexport { createBr } from './modelApi/creators/createBr';\nexport { createListItem } from './modelApi/creators/createListItem';\nexport { createFormatContainer } from './modelApi/creators/createFormatContainer';\nexport { createParagraph } from './modelApi/creators/createParagraph';\nexport { createSelectionMarker } from './modelApi/creators/createSelectionMarker';\nexport { createTable } from './modelApi/creators/createTable';\nexport { createTableCell } from './modelApi/creators/createTableCell';\nexport { createText } from './modelApi/creators/createText';\nexport { createImage } from './modelApi/creators/createImage';\nexport { createContentModelDocument } from './modelApi/creators/createContentModelDocument';\nexport { createParagraphDecorator } from './modelApi/creators/createParagraphDecorator';\nexport { createGeneralSegment } from './modelApi/creators/createGeneralSegment';\nexport { createGeneralBlock } from './modelApi/creators/createGeneralBlock';\nexport { createEntity } from './modelApi/creators/createEntity';\nexport { createDivider } from './modelApi/creators/createDivider';\nexport { createListLevel } from './modelApi/creators/createListLevel';\nexport { createEmptyModel } from './modelApi/creators/createEmptyModel';\n\nexport { addBlock } from './modelApi/common/addBlock';\nexport { addCode } from './modelApi/common/addDecorators';\nexport { addLink } from './modelApi/common/addDecorators';\nexport { normalizeParagraph } from './modelApi/common/normalizeParagraph';\n\nexport { normalizeContentModel } from './modelApi/common/normalizeContentModel';\nexport { isGeneralSegment } from './modelApi/common/isGeneralSegment';\nexport { unwrapBlock } from './modelApi/common/unwrapBlock';\nexport { addSegment } from './modelApi/common/addSegment';\nexport { isEmpty } from './modelApi/common/isEmpty';\nexport { normalizeSingleSegment } from './modelApi/common/normalizeSegment';\n\nexport { setParagraphNotImplicit } from './modelApi/block/setParagraphNotImplicit';\n\nexport { parseValueWithUnit } from './formatHandlers/utils/parseValueWithUnit';\nexport { BorderKeys } from './formatHandlers/common/borderFormatHandler';\nexport { DeprecatedColors, getColor, setColor, parseColor } from './formatHandlers/utils/color';\n\nexport {\n createDomToModelContext,\n createDomToModelContextWithConfig,\n createDomToModelConfig,\n} from './domToModel/context/createDomToModelContext';\nexport {\n createModelToDomContext,\n createModelToDomContextWithConfig,\n createModelToDomConfig,\n} from './modelToDom/context/createModelToDomContext';\n"]}
|
|
@@ -31,6 +31,7 @@ export function normalizeParagraph(paragraph) {
|
|
|
31
31
|
}
|
|
32
32
|
removeEmptyLinks(paragraph);
|
|
33
33
|
removeEmptySegments(paragraph);
|
|
34
|
+
moveUpSegmentFormat(paragraph);
|
|
34
35
|
}
|
|
35
36
|
function removeEmptySegments(block) {
|
|
36
37
|
for (var j = block.segments.length - 1; j >= 0; j--) {
|
|
@@ -59,4 +60,31 @@ function removeEmptyLinks(paragraph) {
|
|
|
59
60
|
}
|
|
60
61
|
}
|
|
61
62
|
}
|
|
63
|
+
var formatsToMoveUp = ['fontFamily', 'fontSize', 'textColor'];
|
|
64
|
+
// When all segments are sharing the same segment format (font name, size and color), we can move its format to paragraph
|
|
65
|
+
function moveUpSegmentFormat(paragraph) {
|
|
66
|
+
if (!paragraph.decorator) {
|
|
67
|
+
var segments_1 = paragraph.segments.filter(function (x) { return x.segmentType != 'SelectionMarker'; });
|
|
68
|
+
var target_1 = paragraph.segmentFormat || {};
|
|
69
|
+
var changed_1 = false;
|
|
70
|
+
formatsToMoveUp.forEach(function (key) {
|
|
71
|
+
changed_1 = internalMoveUpSegmentFormat(segments_1, target_1, key) || changed_1;
|
|
72
|
+
});
|
|
73
|
+
if (changed_1) {
|
|
74
|
+
paragraph.segmentFormat = target_1;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
function internalMoveUpSegmentFormat(segments, target, formatKey) {
|
|
79
|
+
var _a;
|
|
80
|
+
var firstFormat = (_a = segments[0]) === null || _a === void 0 ? void 0 : _a.format;
|
|
81
|
+
if ((firstFormat === null || firstFormat === void 0 ? void 0 : firstFormat[formatKey]) &&
|
|
82
|
+
segments.every(function (segment) { return segment.format[formatKey] == firstFormat[formatKey]; })) {
|
|
83
|
+
target[formatKey] = firstFormat[formatKey];
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
62
90
|
//# sourceMappingURL=normalizeParagraph.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"normalizeParagraph.js","sourceRoot":"","sources":["../../../../../packages-content-model/roosterjs-content-model-dom/lib/modelApi/common/normalizeParagraph.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AACvE,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,qBAAqB,EAAE,MAAM,sCAAsC,CAAC;AAC7E,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"normalizeParagraph.js","sourceRoot":"","sources":["../../../../../packages-content-model/roosterjs-content-model-dom/lib/modelApi/common/normalizeParagraph.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AACvE,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,qBAAqB,EAAE,MAAM,sCAAsC,CAAC;AAC7E,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAO1D;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,SAAgC;IAC/D,IAAM,QAAQ,GAAG,SAAS,CAAC,QAAQ,CAAC;IAEpC,IAAI,CAAC,SAAS,CAAC,UAAU,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE;QAC9C,IAAM,IAAI,GAAG,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAC3C,IAAM,UAAU,GAAG,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAEjD,IACI,IAAI,CAAC,WAAW,IAAI,iBAAiB;YACrC,CAAC,CAAC,UAAU,IAAI,UAAU,CAAC,WAAW,IAAI,IAAI,CAAC,EACjD;YACE,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;SACxC;aAAM,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,WAAW,IAAI,IAAI,EAAE;YACjF,IAAM,gBAAgB,GAAG,QAAQ,CAAC,MAAM,CAAC,UAAA,CAAC,IAAI,OAAA,CAAC,CAAC,WAAW,IAAI,iBAAiB,EAAlC,CAAkC,CAAC,CAAC;YAElF,0EAA0E;YAC1E,sEAAsE;YACtE,IACI,gBAAgB,CAAC,MAAM,GAAG,CAAC;gBAC3B,gBAAgB,CAAC,gBAAgB,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,WAAW,IAAI,IAAI,EACnE;gBACE,QAAQ,CAAC,GAAG,EAAE,CAAC;aAClB;SACJ;KACJ;IAED,IAAI,CAAC,qBAAqB,CAAC,SAAS,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE;QACrD,oBAAoB,CAAC,SAAS,CAAC,CAAC;KACnC;IAED,gBAAgB,CAAC,SAAS,CAAC,CAAC;IAE5B,mBAAmB,CAAC,SAAS,CAAC,CAAC;IAE/B,mBAAmB,CAAC,SAAS,CAAC,CAAC;AACnC,CAAC;AAED,SAAS,mBAAmB,CAAC,KAA4B;IACrD,KAAK,IAAI,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE;QACjD,IAAI,cAAc,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE;YACnC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;SAC/B;KACJ;AACL,CAAC;AAED,SAAS,gBAAgB,CAAC,SAAgC;IACtD,IAAM,MAAM,GAAG,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,UAAA,CAAC,IAAI,OAAA,CAAC,CAAC,WAAW,IAAI,iBAAiB,EAAlC,CAAkC,CAAC,CAAC;IAChF,IAAI,MAAM,EAAE;QACR,IAAM,WAAW,GAAG,SAAS,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACvD,IAAM,IAAI,GAAG,SAAS,CAAC,QAAQ,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC;QACjD,IAAM,IAAI,GAAG,SAAS,CAAC,QAAQ,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC;QACjD,IACI,CAAC,IAAI;YACD,CAAC,IAAI,CAAC,IAAI;YACV,cAAc,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC;YAC1C,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,IAAI,cAAc,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;YACrE,MAAM,CAAC,IAAI,CAAC;YAChB,CAAC,CAAC,IAAI;gBACF,MAAM,CAAC,IAAI;gBACX,IAAI;gBACJ,CAAC,IAAI,CAAC,IAAI;gBACV,cAAc,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,EACjD;YACE,OAAO,MAAM,CAAC,IAAI,CAAC;SACtB;KACJ;AACL,CAAC;AAGD,IAAM,eAAe,GAAsB,CAAC,YAAY,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC;AAEnF,yHAAyH;AACzH,SAAS,mBAAmB,CAAC,SAAgC;IACzD,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE;QACtB,IAAM,UAAQ,GAAG,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,UAAA,CAAC,IAAI,OAAA,CAAC,CAAC,WAAW,IAAI,iBAAiB,EAAlC,CAAkC,CAAC,CAAC;QACpF,IAAM,QAAM,GAAG,SAAS,CAAC,aAAa,IAAI,EAAE,CAAC;QAC7C,IAAI,SAAO,GAAG,KAAK,CAAC;QAEpB,eAAe,CAAC,OAAO,CAAC,UAAA,GAAG;YACvB,SAAO,GAAG,2BAA2B,CAAC,UAAQ,EAAE,QAAM,EAAE,GAAG,CAAC,IAAI,SAAO,CAAC;QAC5E,CAAC,CAAC,CAAC;QAEH,IAAI,SAAO,EAAE;YACT,SAAS,CAAC,aAAa,GAAG,QAAM,CAAC;SACpC;KACJ;AACL,CAAC;AAED,SAAS,2BAA2B,CAChC,QAA+B,EAC/B,MAAiC,EACjC,SAA0B;;IAE1B,IAAM,WAAW,GAAG,MAAA,QAAQ,CAAC,CAAC,CAAC,0CAAE,MAAM,CAAC;IAExC,IACI,CAAA,WAAW,aAAX,WAAW,uBAAX,WAAW,CAAG,SAAS,CAAC;QACxB,QAAQ,CAAC,KAAK,CAAC,UAAA,OAAO,IAAI,OAAA,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,WAAW,CAAC,SAAS,CAAC,EAAnD,CAAmD,CAAC,EAChF;QACE,MAAM,CAAC,SAAS,CAAC,GAAG,WAAW,CAAC,SAAS,CAAC,CAAC;QAC3C,OAAO,IAAI,CAAC;KACf;SAAM;QACH,OAAO,KAAK,CAAC;KAChB;AACL,CAAC","sourcesContent":["import { areSameFormats } from '../../domToModel/utils/areSameFormats';\nimport { createBr } from '../creators/createBr';\nimport { isSegmentEmpty } from './isEmpty';\nimport { isWhiteSpacePreserved } from '../../domUtils/isWhiteSpacePreserved';\nimport { normalizeAllSegments } from './normalizeSegment';\nimport type {\n ContentModelParagraph,\n ContentModelSegment,\n ContentModelSegmentFormat,\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: ContentModelParagraph) {\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 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 segments.pop();\n }\n }\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 removeEmptySegments(block: ContentModelParagraph) {\n for (let j = block.segments.length - 1; j >= 0; j--) {\n if (isSegmentEmpty(block.segments[j])) {\n block.segments.splice(j, 1);\n }\n }\n}\n\nfunction removeEmptyLinks(paragraph: ContentModelParagraph) {\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 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 delete marker.link;\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: ContentModelParagraph) {\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 paragraph.segmentFormat = target;\n }\n }\n}\n\nfunction internalMoveUpSegmentFormat(\n segments: ContentModelSegment[],\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 ) {\n target[formatKey] = firstFormat[formatKey];\n return true;\n } else {\n return false;\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
"description": "Content Model for roosterjs (Under development)",
|
|
4
4
|
"dependencies": {
|
|
5
5
|
"tslib": "^2.3.1",
|
|
6
|
-
"roosterjs-content-model-types": "^0.
|
|
6
|
+
"roosterjs-content-model-types": "^0.27.0"
|
|
7
7
|
},
|
|
8
|
-
"version": "0.
|
|
8
|
+
"version": "0.27.0",
|
|
9
9
|
"main": "./lib/index.js",
|
|
10
10
|
"typings": "./lib/index.d.ts",
|
|
11
11
|
"module": "./lib-mjs/index.js",
|