roosterjs-content-model-dom 9.29.0 → 9.29.2

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.
@@ -0,0 +1,4 @@
1
+ /**
2
+ * @internal
3
+ */
4
+ export declare function isGenericRoleElement(element: Element | null): element is Element;
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isGenericRoleElement = void 0;
4
+ // List of elements that have generic roles by default
5
+ var genericRoleElements = new Set([
6
+ 'div',
7
+ 'span',
8
+ 'p',
9
+ 'section',
10
+ 'article',
11
+ 'aside',
12
+ 'header',
13
+ 'footer',
14
+ 'main',
15
+ 'nav',
16
+ 'address',
17
+ 'blockquote',
18
+ 'pre',
19
+ 'figure',
20
+ 'figcaption',
21
+ 'hgroup',
22
+ ]);
23
+ /**
24
+ * @internal
25
+ */
26
+ function isGenericRoleElement(element) {
27
+ if (!element) {
28
+ return false;
29
+ }
30
+ var tagName = element.tagName.toLowerCase();
31
+ return genericRoleElements.has(tagName);
32
+ }
33
+ exports.isGenericRoleElement = isGenericRoleElement;
34
+ //# sourceMappingURL=isGenericRoleElement.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"isGenericRoleElement.js","sourceRoot":"","sources":["../../../../packages/roosterjs-content-model-dom/lib/domUtils/isGenericRoleElement.ts"],"names":[],"mappings":";;;AAAA,sDAAsD;AACtD,IAAM,mBAAmB,GAAG,IAAI,GAAG,CAAC;IAChC,KAAK;IACL,MAAM;IACN,GAAG;IACH,SAAS;IACT,SAAS;IACT,OAAO;IACP,QAAQ;IACR,QAAQ;IACR,MAAM;IACN,KAAK;IACL,SAAS;IACT,YAAY;IACZ,KAAK;IACL,QAAQ;IACR,YAAY;IACZ,QAAQ;CACX,CAAC,CAAC;AAEH;;GAEG;AACH,SAAgB,oBAAoB,CAAC,OAAuB;IACxD,IAAI,CAAC,OAAO,EAAE;QACV,OAAO,KAAK,CAAC;KAChB;IAED,IAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC;IAE9C,OAAO,mBAAmB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AAC5C,CAAC;AARD,oDAQC","sourcesContent":["// List of elements that have generic roles by default\nconst genericRoleElements = new Set([\n 'div',\n 'span',\n 'p',\n 'section',\n 'article',\n 'aside',\n 'header',\n 'footer',\n 'main',\n 'nav',\n 'address',\n 'blockquote',\n 'pre',\n 'figure',\n 'figcaption',\n 'hgroup',\n]);\n\n/**\n * @internal\n */\nexport function isGenericRoleElement(element: Element | null): element is Element {\n if (!element) {\n return false;\n }\n\n const tagName = element.tagName.toLowerCase();\n\n return genericRoleElements.has(tagName);\n}\n"]}
@@ -8,7 +8,7 @@ exports.normalizeFontFamily = void 0;
8
8
  * @returns The normalized font family string
9
9
  */
10
10
  function normalizeFontFamily(fontFamily) {
11
- var existingQuotedFontsRegex = /".*?"/g;
11
+ var existingQuotedFontsRegex = /(".*?")|('.*?')/g;
12
12
  var match = existingQuotedFontsRegex.exec(fontFamily);
13
13
  var start = 0;
14
14
  var result = [];
@@ -1 +1 @@
1
- {"version":3,"file":"normalizeFontFamily.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-dom/lib/domUtils/style/normalizeFontFamily.ts"],"names":[],"mappings":";;;AAAA;;;;;GAKG;AACH,SAAgB,mBAAmB,CAAC,UAAkB;IAClD,IAAM,wBAAwB,GAAG,QAAQ,CAAC;IAC1C,IAAI,KAAK,GAAG,wBAAwB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACtD,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAM,MAAM,GAAa,EAAE,CAAC;IAE5B,OAAO,KAAK,EAAE;QACV,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;QAEhD,KAAK,GAAG,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;QACtC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAEtB,KAAK,GAAG,wBAAwB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;KACrD;IAED,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC;IAEtD,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC7B,CAAC;AAlBD,kDAkBC;AAED,SAAS,OAAO,CAAC,UAAkB,EAAE,MAAgB,EAAE,KAAa,EAAE,GAAW;IAC7E,IAAM,QAAQ,GAAG,UAAU,CAAC,SAAS,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAE7D,QAAQ,CAAC,OAAO,CAAC,UAAA,MAAM;QACnB,MAAM,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;QAEvB,IAAI,MAAM,EAAE;YACR,gEAAgE;YAChE,IAAI,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE;gBAC/B,MAAM,CAAC,IAAI,CAAC,OAAI,MAAM,OAAG,CAAC,CAAC;aAC9B;iBAAM;gBACH,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;aACvB;SACJ;IACL,CAAC,CAAC,CAAC;AACP,CAAC","sourcesContent":["/**\n * Normalize font family string to a standard format\n * Add quotes around font family names that contain non-alphanumeric/dash characters\n * @param fontFamily The font family string to normalize\n * @returns The normalized font family string\n */\nexport function normalizeFontFamily(fontFamily: string): string {\n const existingQuotedFontsRegex = /\".*?\"/g;\n let match = existingQuotedFontsRegex.exec(fontFamily);\n let start = 0;\n const result: string[] = [];\n\n while (match) {\n process(fontFamily, result, start, match.index);\n\n start = match.index + match[0].length;\n result.push(match[0]);\n\n match = existingQuotedFontsRegex.exec(fontFamily);\n }\n\n process(fontFamily, result, start, fontFamily.length);\n\n return result.join(', ');\n}\n\nfunction process(fontFamily: string, result: string[], start: number, end: number) {\n const families = fontFamily.substring(start, end).split(',');\n\n families.forEach(family => {\n family = family.trim();\n\n if (family) {\n // Check if the family name contains non-alphanumeric characters\n if (/[^a-zA-Z0-9\\-]/.test(family)) {\n result.push(`\"${family}\"`);\n } else {\n result.push(family);\n }\n }\n });\n}\n"]}
1
+ {"version":3,"file":"normalizeFontFamily.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-dom/lib/domUtils/style/normalizeFontFamily.ts"],"names":[],"mappings":";;;AAAA;;;;;GAKG;AACH,SAAgB,mBAAmB,CAAC,UAAkB;IAClD,IAAM,wBAAwB,GAAG,kBAAkB,CAAC;IACpD,IAAI,KAAK,GAAG,wBAAwB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACtD,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAM,MAAM,GAAa,EAAE,CAAC;IAE5B,OAAO,KAAK,EAAE;QACV,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;QAEhD,KAAK,GAAG,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;QACtC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAEtB,KAAK,GAAG,wBAAwB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;KACrD;IAED,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC;IAEtD,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC7B,CAAC;AAlBD,kDAkBC;AAED,SAAS,OAAO,CAAC,UAAkB,EAAE,MAAgB,EAAE,KAAa,EAAE,GAAW;IAC7E,IAAM,QAAQ,GAAG,UAAU,CAAC,SAAS,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAE7D,QAAQ,CAAC,OAAO,CAAC,UAAA,MAAM;QACnB,MAAM,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;QAEvB,IAAI,MAAM,EAAE;YACR,gEAAgE;YAChE,IAAI,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE;gBAC/B,MAAM,CAAC,IAAI,CAAC,OAAI,MAAM,OAAG,CAAC,CAAC;aAC9B;iBAAM;gBACH,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;aACvB;SACJ;IACL,CAAC,CAAC,CAAC;AACP,CAAC","sourcesContent":["/**\n * Normalize font family string to a standard format\n * Add quotes around font family names that contain non-alphanumeric/dash characters\n * @param fontFamily The font family string to normalize\n * @returns The normalized font family string\n */\nexport function normalizeFontFamily(fontFamily: string): string {\n const existingQuotedFontsRegex = /(\".*?\")|('.*?')/g;\n let match = existingQuotedFontsRegex.exec(fontFamily);\n let start = 0;\n const result: string[] = [];\n\n while (match) {\n process(fontFamily, result, start, match.index);\n\n start = match.index + match[0].length;\n result.push(match[0]);\n\n match = existingQuotedFontsRegex.exec(fontFamily);\n }\n\n process(fontFamily, result, start, fontFamily.length);\n\n return result.join(', ');\n}\n\nfunction process(fontFamily: string, result: string[], start: number, end: number) {\n const families = fontFamily.substring(start, end).split(',');\n\n families.forEach(family => {\n family = family.trim();\n\n if (family) {\n // Check if the family name contains non-alphanumeric characters\n if (/[^a-zA-Z0-9\\-]/.test(family)) {\n result.push(`\"${family}\"`);\n } else {\n result.push(family);\n }\n }\n });\n}\n"]}
@@ -3,9 +3,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.handleListItem = void 0;
4
4
  var applyFormat_1 = require("../utils/applyFormat");
5
5
  var applyMetadata_1 = require("../utils/applyMetadata");
6
+ var isGenericRoleElement_1 = require("../../domUtils/isGenericRoleElement");
6
7
  var setParagraphNotImplicit_1 = require("../../modelApi/block/setParagraphNotImplicit");
7
8
  var stackFormat_1 = require("../utils/stackFormat");
8
9
  var unwrap_1 = require("../../domUtils/unwrap");
10
+ var HtmlRoleAttribute = 'role';
11
+ var PresentationRoleValue = 'presentation';
9
12
  /**
10
13
  * @internal
11
14
  */
@@ -38,6 +41,15 @@ var handleListItem = function (doc, parent, listItem, context, refNode) {
38
41
  context.modelHandlers.blockGroupChildren(doc, li, listItem, context);
39
42
  (0, unwrap_1.unwrap)(li);
40
43
  }
44
+ // Add role="presentation" to all generic role elements inside the LI element
45
+ // This is to make sure the elements are announced correctly by screen readers
46
+ // when using arrow keys to navigate the list.
47
+ for (var index = 0; index < li.children.length; index++) {
48
+ var element = li.children.item(index);
49
+ if ((0, isGenericRoleElement_1.isGenericRoleElement)(element)) {
50
+ element.setAttribute(HtmlRoleAttribute, PresentationRoleValue);
51
+ }
52
+ }
41
53
  (_b = context.onNodeCreated) === null || _b === void 0 ? void 0 : _b.call(context, listItem, li);
42
54
  return refNode;
43
55
  };
@@ -1 +1 @@
1
- {"version":3,"file":"handleListItem.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-dom/lib/modelToDom/handlers/handleListItem.ts"],"names":[],"mappings":";;;AAAA,oDAAmD;AACnD,wDAAuD;AACvD,wFAAuF;AACvF,oDAAmD;AACnD,gDAA+C;AAO/C;;GAEG;AACI,IAAM,cAAc,GAAmD,UAC1E,GAAa,EACb,MAAY,EACZ,QAA8B,EAC9B,OAA0B,EAC1B,OAAoB;;IAEpB,OAAO,GAAG,OAAO,CAAC,aAAa,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IAEtE,IAAA,SAAS,GAAK,OAAO,CAAC,UAAU,UAAvB,CAAwB;IAEzC,IAAM,UAAU,GAAG,CAAA,MAAA,SAAS,aAAT,SAAS,uBAAT,SAAS,CAAG,CAAA,SAAS,aAAT,SAAS,uBAAT,SAAS,CAAE,MAAM,IAAG,CAAC,CAAC,0CAAE,IAAI,KAAI,MAAM,CAAC;IACtE,IAAM,EAAE,GAAG,GAAG,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;IACnC,IAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAE1D,2DAA2D;IAC3D,sEAAsE;IACtE,UAAU,CAAC,YAAY,CAAC,EAAE,EAAE,CAAA,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,UAAU,KAAI,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAChF,OAAO,CAAC,gBAAgB,CAAC,kBAAkB,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAErD,IAAI,KAAK,EAAE;QACP,IAAA,yBAAW,EAAC,EAAE,EAAE,OAAO,CAAC,cAAc,CAAC,OAAO,EAAE,QAAQ,CAAC,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACvF,IAAA,yBAAW,EAAC,EAAE,EAAE,OAAO,CAAC,cAAc,CAAC,cAAc,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAE9E,kIAAkI;QAClI,IAAA,6BAAa,EAAC,KAAK,EAAE,OAAO,CAAC,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAElF,uIAAuI;QACvI,IAAA,yBAAW,EAAC,EAAE,EAAE,OAAO,CAAC,cAAc,CAAC,eAAe,EAAE,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAElF,IAAA,yBAAW,EAAC,OAAO,EAAE,QAAQ,CAAC,YAAY,CAAC,MAAM,EAAE;YAC/C,OAAO,CAAC,aAAa,CAAC,kBAAkB,CAAC,GAAG,EAAE,EAAE,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;QACzE,CAAC,CAAC,CAAC;KACN;SAAM;QACH,sFAAsF;QACtF,wHAAwH;QACxH,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,iDAAuB,CAAC,CAAC;QAEjD,OAAO,CAAC,aAAa,CAAC,kBAAkB,CAAC,GAAG,EAAE,EAAE,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;QAErE,IAAA,eAAM,EAAC,EAAE,CAAC,CAAC;KACd;IAED,MAAA,OAAO,CAAC,aAAa,+CAArB,OAAO,EAAiB,QAAQ,EAAE,EAAE,CAAC,CAAC;IAEtC,OAAO,OAAO,CAAC;AACnB,CAAC,CAAC;AA9CW,QAAA,cAAc,kBA8CzB","sourcesContent":["import { applyFormat } from '../utils/applyFormat';\nimport { applyMetadata } from '../utils/applyMetadata';\nimport { setParagraphNotImplicit } from '../../modelApi/block/setParagraphNotImplicit';\nimport { stackFormat } from '../utils/stackFormat';\nimport { unwrap } from '../../domUtils/unwrap';\nimport type {\n ContentModelBlockHandler,\n ContentModelListItem,\n ModelToDomContext,\n} from 'roosterjs-content-model-types';\n\n/**\n * @internal\n */\nexport const handleListItem: ContentModelBlockHandler<ContentModelListItem> = (\n doc: Document,\n parent: Node,\n listItem: ContentModelListItem,\n context: ModelToDomContext,\n refNode: Node | null\n) => {\n refNode = context.modelHandlers.list(doc, parent, listItem, context, refNode);\n\n const { nodeStack } = context.listFormat;\n\n const listParent = nodeStack?.[nodeStack?.length - 1]?.node || parent;\n const li = doc.createElement('li');\n const level = listItem.levels[listItem.levels.length - 1];\n\n // It is possible listParent is the same with parent param.\n // This happens when outdent a list item to cause it has no list level\n listParent.insertBefore(li, refNode?.parentNode == listParent ? refNode : null);\n context.rewriteFromModel.addedBlockElements.push(li);\n\n if (level) {\n applyFormat(li, context.formatAppliers.segment, listItem.formatHolder.format, context);\n applyFormat(li, context.formatAppliers.listItemThread, level.format, context);\n\n // Need to apply metadata after applying listItem format since the list numbers value relies on the result of list thread handling\n applyMetadata(level, context.metadataAppliers.listItem, listItem.format, context);\n\n // Need to apply listItemElement formats after applying metadata since the list numbers value relies on the result of metadata handling\n applyFormat(li, context.formatAppliers.listItemElement, listItem.format, context);\n\n stackFormat(context, listItem.formatHolder.format, () => {\n context.modelHandlers.blockGroupChildren(doc, li, listItem, context);\n });\n } else {\n // There is no level for this list item, that means it should be moved out of the list\n // For each paragraph, make it not implicit so it will have a DIV around it, to avoid more paragraphs connected together\n listItem.blocks.forEach(setParagraphNotImplicit);\n\n context.modelHandlers.blockGroupChildren(doc, li, listItem, context);\n\n unwrap(li);\n }\n\n context.onNodeCreated?.(listItem, li);\n\n return refNode;\n};\n"]}
1
+ {"version":3,"file":"handleListItem.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-dom/lib/modelToDom/handlers/handleListItem.ts"],"names":[],"mappings":"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","sourcesContent":["import { applyFormat } from '../utils/applyFormat';\nimport { applyMetadata } from '../utils/applyMetadata';\nimport { isGenericRoleElement } from '../../domUtils/isGenericRoleElement';\nimport { setParagraphNotImplicit } from '../../modelApi/block/setParagraphNotImplicit';\nimport { stackFormat } from '../utils/stackFormat';\nimport { unwrap } from '../../domUtils/unwrap';\nimport type {\n ContentModelBlockHandler,\n ContentModelListItem,\n ModelToDomContext,\n} from 'roosterjs-content-model-types';\n\nconst HtmlRoleAttribute = 'role';\nconst PresentationRoleValue = 'presentation';\n\n/**\n * @internal\n */\nexport const handleListItem: ContentModelBlockHandler<ContentModelListItem> = (\n doc: Document,\n parent: Node,\n listItem: ContentModelListItem,\n context: ModelToDomContext,\n refNode: Node | null\n) => {\n refNode = context.modelHandlers.list(doc, parent, listItem, context, refNode);\n\n const { nodeStack } = context.listFormat;\n\n const listParent = nodeStack?.[nodeStack?.length - 1]?.node || parent;\n const li = doc.createElement('li');\n const level = listItem.levels[listItem.levels.length - 1];\n\n // It is possible listParent is the same with parent param.\n // This happens when outdent a list item to cause it has no list level\n listParent.insertBefore(li, refNode?.parentNode == listParent ? refNode : null);\n context.rewriteFromModel.addedBlockElements.push(li);\n\n if (level) {\n applyFormat(li, context.formatAppliers.segment, listItem.formatHolder.format, context);\n applyFormat(li, context.formatAppliers.listItemThread, level.format, context);\n\n // Need to apply metadata after applying listItem format since the list numbers value relies on the result of list thread handling\n applyMetadata(level, context.metadataAppliers.listItem, listItem.format, context);\n\n // Need to apply listItemElement formats after applying metadata since the list numbers value relies on the result of metadata handling\n applyFormat(li, context.formatAppliers.listItemElement, listItem.format, context);\n\n stackFormat(context, listItem.formatHolder.format, () => {\n context.modelHandlers.blockGroupChildren(doc, li, listItem, context);\n });\n } else {\n // There is no level for this list item, that means it should be moved out of the list\n // For each paragraph, make it not implicit so it will have a DIV around it, to avoid more paragraphs connected together\n listItem.blocks.forEach(setParagraphNotImplicit);\n\n context.modelHandlers.blockGroupChildren(doc, li, listItem, context);\n\n unwrap(li);\n }\n\n // Add role=\"presentation\" to all generic role elements inside the LI element\n // This is to make sure the elements are announced correctly by screen readers\n // when using arrow keys to navigate the list.\n for (let index = 0; index < li.children.length; index++) {\n const element = li.children.item(index);\n if (isGenericRoleElement(element)) {\n element.setAttribute(HtmlRoleAttribute, PresentationRoleValue);\n }\n }\n\n context.onNodeCreated?.(listItem, li);\n\n return refNode;\n};\n"]}
@@ -0,0 +1,4 @@
1
+ /**
2
+ * @internal
3
+ */
4
+ export declare function isGenericRoleElement(element: Element | null): element is Element;
@@ -0,0 +1,36 @@
1
+ define(["require", "exports"], function (require, exports) {
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.isGenericRoleElement = void 0;
5
+ // List of elements that have generic roles by default
6
+ var genericRoleElements = new Set([
7
+ 'div',
8
+ 'span',
9
+ 'p',
10
+ 'section',
11
+ 'article',
12
+ 'aside',
13
+ 'header',
14
+ 'footer',
15
+ 'main',
16
+ 'nav',
17
+ 'address',
18
+ 'blockquote',
19
+ 'pre',
20
+ 'figure',
21
+ 'figcaption',
22
+ 'hgroup',
23
+ ]);
24
+ /**
25
+ * @internal
26
+ */
27
+ function isGenericRoleElement(element) {
28
+ if (!element) {
29
+ return false;
30
+ }
31
+ var tagName = element.tagName.toLowerCase();
32
+ return genericRoleElements.has(tagName);
33
+ }
34
+ exports.isGenericRoleElement = isGenericRoleElement;
35
+ });
36
+ //# sourceMappingURL=isGenericRoleElement.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"isGenericRoleElement.js","sourceRoot":"","sources":["../../../../packages/roosterjs-content-model-dom/lib/domUtils/isGenericRoleElement.ts"],"names":[],"mappings":";;;;IAAA,sDAAsD;IACtD,IAAM,mBAAmB,GAAG,IAAI,GAAG,CAAC;QAChC,KAAK;QACL,MAAM;QACN,GAAG;QACH,SAAS;QACT,SAAS;QACT,OAAO;QACP,QAAQ;QACR,QAAQ;QACR,MAAM;QACN,KAAK;QACL,SAAS;QACT,YAAY;QACZ,KAAK;QACL,QAAQ;QACR,YAAY;QACZ,QAAQ;KACX,CAAC,CAAC;IAEH;;OAEG;IACH,SAAgB,oBAAoB,CAAC,OAAuB;QACxD,IAAI,CAAC,OAAO,EAAE;YACV,OAAO,KAAK,CAAC;SAChB;QAED,IAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC;QAE9C,OAAO,mBAAmB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAC5C,CAAC;IARD,oDAQC","sourcesContent":["// List of elements that have generic roles by default\nconst genericRoleElements = new Set([\n 'div',\n 'span',\n 'p',\n 'section',\n 'article',\n 'aside',\n 'header',\n 'footer',\n 'main',\n 'nav',\n 'address',\n 'blockquote',\n 'pre',\n 'figure',\n 'figcaption',\n 'hgroup',\n]);\n\n/**\n * @internal\n */\nexport function isGenericRoleElement(element: Element | null): element is Element {\n if (!element) {\n return false;\n }\n\n const tagName = element.tagName.toLowerCase();\n\n return genericRoleElements.has(tagName);\n}\n"]}
@@ -9,7 +9,7 @@ define(["require", "exports"], function (require, exports) {
9
9
  * @returns The normalized font family string
10
10
  */
11
11
  function normalizeFontFamily(fontFamily) {
12
- var existingQuotedFontsRegex = /".*?"/g;
12
+ var existingQuotedFontsRegex = /(".*?")|('.*?')/g;
13
13
  var match = existingQuotedFontsRegex.exec(fontFamily);
14
14
  var start = 0;
15
15
  var result = [];
@@ -1 +1 @@
1
- {"version":3,"file":"normalizeFontFamily.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-dom/lib/domUtils/style/normalizeFontFamily.ts"],"names":[],"mappings":";;;;IAAA;;;;;OAKG;IACH,SAAgB,mBAAmB,CAAC,UAAkB;QAClD,IAAM,wBAAwB,GAAG,QAAQ,CAAC;QAC1C,IAAI,KAAK,GAAG,wBAAwB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACtD,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,IAAM,MAAM,GAAa,EAAE,CAAC;QAE5B,OAAO,KAAK,EAAE;YACV,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;YAEhD,KAAK,GAAG,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;YACtC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;YAEtB,KAAK,GAAG,wBAAwB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;SACrD;QAED,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC;QAEtD,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC7B,CAAC;IAlBD,kDAkBC;IAED,SAAS,OAAO,CAAC,UAAkB,EAAE,MAAgB,EAAE,KAAa,EAAE,GAAW;QAC7E,IAAM,QAAQ,GAAG,UAAU,CAAC,SAAS,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAE7D,QAAQ,CAAC,OAAO,CAAC,UAAA,MAAM;YACnB,MAAM,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;YAEvB,IAAI,MAAM,EAAE;gBACR,gEAAgE;gBAChE,IAAI,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE;oBAC/B,MAAM,CAAC,IAAI,CAAC,OAAI,MAAM,OAAG,CAAC,CAAC;iBAC9B;qBAAM;oBACH,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;iBACvB;aACJ;QACL,CAAC,CAAC,CAAC;IACP,CAAC","sourcesContent":["/**\n * Normalize font family string to a standard format\n * Add quotes around font family names that contain non-alphanumeric/dash characters\n * @param fontFamily The font family string to normalize\n * @returns The normalized font family string\n */\nexport function normalizeFontFamily(fontFamily: string): string {\n const existingQuotedFontsRegex = /\".*?\"/g;\n let match = existingQuotedFontsRegex.exec(fontFamily);\n let start = 0;\n const result: string[] = [];\n\n while (match) {\n process(fontFamily, result, start, match.index);\n\n start = match.index + match[0].length;\n result.push(match[0]);\n\n match = existingQuotedFontsRegex.exec(fontFamily);\n }\n\n process(fontFamily, result, start, fontFamily.length);\n\n return result.join(', ');\n}\n\nfunction process(fontFamily: string, result: string[], start: number, end: number) {\n const families = fontFamily.substring(start, end).split(',');\n\n families.forEach(family => {\n family = family.trim();\n\n if (family) {\n // Check if the family name contains non-alphanumeric characters\n if (/[^a-zA-Z0-9\\-]/.test(family)) {\n result.push(`\"${family}\"`);\n } else {\n result.push(family);\n }\n }\n });\n}\n"]}
1
+ {"version":3,"file":"normalizeFontFamily.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-dom/lib/domUtils/style/normalizeFontFamily.ts"],"names":[],"mappings":";;;;IAAA;;;;;OAKG;IACH,SAAgB,mBAAmB,CAAC,UAAkB;QAClD,IAAM,wBAAwB,GAAG,kBAAkB,CAAC;QACpD,IAAI,KAAK,GAAG,wBAAwB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACtD,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,IAAM,MAAM,GAAa,EAAE,CAAC;QAE5B,OAAO,KAAK,EAAE;YACV,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;YAEhD,KAAK,GAAG,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;YACtC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;YAEtB,KAAK,GAAG,wBAAwB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;SACrD;QAED,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC;QAEtD,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC7B,CAAC;IAlBD,kDAkBC;IAED,SAAS,OAAO,CAAC,UAAkB,EAAE,MAAgB,EAAE,KAAa,EAAE,GAAW;QAC7E,IAAM,QAAQ,GAAG,UAAU,CAAC,SAAS,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAE7D,QAAQ,CAAC,OAAO,CAAC,UAAA,MAAM;YACnB,MAAM,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;YAEvB,IAAI,MAAM,EAAE;gBACR,gEAAgE;gBAChE,IAAI,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE;oBAC/B,MAAM,CAAC,IAAI,CAAC,OAAI,MAAM,OAAG,CAAC,CAAC;iBAC9B;qBAAM;oBACH,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;iBACvB;aACJ;QACL,CAAC,CAAC,CAAC;IACP,CAAC","sourcesContent":["/**\n * Normalize font family string to a standard format\n * Add quotes around font family names that contain non-alphanumeric/dash characters\n * @param fontFamily The font family string to normalize\n * @returns The normalized font family string\n */\nexport function normalizeFontFamily(fontFamily: string): string {\n const existingQuotedFontsRegex = /(\".*?\")|('.*?')/g;\n let match = existingQuotedFontsRegex.exec(fontFamily);\n let start = 0;\n const result: string[] = [];\n\n while (match) {\n process(fontFamily, result, start, match.index);\n\n start = match.index + match[0].length;\n result.push(match[0]);\n\n match = existingQuotedFontsRegex.exec(fontFamily);\n }\n\n process(fontFamily, result, start, fontFamily.length);\n\n return result.join(', ');\n}\n\nfunction process(fontFamily: string, result: string[], start: number, end: number) {\n const families = fontFamily.substring(start, end).split(',');\n\n families.forEach(family => {\n family = family.trim();\n\n if (family) {\n // Check if the family name contains non-alphanumeric characters\n if (/[^a-zA-Z0-9\\-]/.test(family)) {\n result.push(`\"${family}\"`);\n } else {\n result.push(family);\n }\n }\n });\n}\n"]}
@@ -1,7 +1,9 @@
1
- define(["require", "exports", "../utils/applyFormat", "../utils/applyMetadata", "../../modelApi/block/setParagraphNotImplicit", "../utils/stackFormat", "../../domUtils/unwrap"], function (require, exports, applyFormat_1, applyMetadata_1, setParagraphNotImplicit_1, stackFormat_1, unwrap_1) {
1
+ define(["require", "exports", "../utils/applyFormat", "../utils/applyMetadata", "../../domUtils/isGenericRoleElement", "../../modelApi/block/setParagraphNotImplicit", "../utils/stackFormat", "../../domUtils/unwrap"], function (require, exports, applyFormat_1, applyMetadata_1, isGenericRoleElement_1, setParagraphNotImplicit_1, stackFormat_1, unwrap_1) {
2
2
  "use strict";
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
4
  exports.handleListItem = void 0;
5
+ var HtmlRoleAttribute = 'role';
6
+ var PresentationRoleValue = 'presentation';
5
7
  /**
6
8
  * @internal
7
9
  */
@@ -34,6 +36,15 @@ define(["require", "exports", "../utils/applyFormat", "../utils/applyMetadata",
34
36
  context.modelHandlers.blockGroupChildren(doc, li, listItem, context);
35
37
  (0, unwrap_1.unwrap)(li);
36
38
  }
39
+ // Add role="presentation" to all generic role elements inside the LI element
40
+ // This is to make sure the elements are announced correctly by screen readers
41
+ // when using arrow keys to navigate the list.
42
+ for (var index = 0; index < li.children.length; index++) {
43
+ var element = li.children.item(index);
44
+ if ((0, isGenericRoleElement_1.isGenericRoleElement)(element)) {
45
+ element.setAttribute(HtmlRoleAttribute, PresentationRoleValue);
46
+ }
47
+ }
37
48
  (_b = context.onNodeCreated) === null || _b === void 0 ? void 0 : _b.call(context, listItem, li);
38
49
  return refNode;
39
50
  };
@@ -1 +1 @@
1
- {"version":3,"file":"handleListItem.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-dom/lib/modelToDom/handlers/handleListItem.ts"],"names":[],"mappings":";;;;IAWA;;OAEG;IACI,IAAM,cAAc,GAAmD,UAC1E,GAAa,EACb,MAAY,EACZ,QAA8B,EAC9B,OAA0B,EAC1B,OAAoB;;QAEpB,OAAO,GAAG,OAAO,CAAC,aAAa,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QAEtE,IAAA,SAAS,GAAK,OAAO,CAAC,UAAU,UAAvB,CAAwB;QAEzC,IAAM,UAAU,GAAG,CAAA,MAAA,SAAS,aAAT,SAAS,uBAAT,SAAS,CAAG,CAAA,SAAS,aAAT,SAAS,uBAAT,SAAS,CAAE,MAAM,IAAG,CAAC,CAAC,0CAAE,IAAI,KAAI,MAAM,CAAC;QACtE,IAAM,EAAE,GAAG,GAAG,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;QACnC,IAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAE1D,2DAA2D;QAC3D,sEAAsE;QACtE,UAAU,CAAC,YAAY,CAAC,EAAE,EAAE,CAAA,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,UAAU,KAAI,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAChF,OAAO,CAAC,gBAAgB,CAAC,kBAAkB,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAErD,IAAI,KAAK,EAAE;YACP,IAAA,yBAAW,EAAC,EAAE,EAAE,OAAO,CAAC,cAAc,CAAC,OAAO,EAAE,QAAQ,CAAC,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;YACvF,IAAA,yBAAW,EAAC,EAAE,EAAE,OAAO,CAAC,cAAc,CAAC,cAAc,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;YAE9E,kIAAkI;YAClI,IAAA,6BAAa,EAAC,KAAK,EAAE,OAAO,CAAC,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;YAElF,uIAAuI;YACvI,IAAA,yBAAW,EAAC,EAAE,EAAE,OAAO,CAAC,cAAc,CAAC,eAAe,EAAE,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;YAElF,IAAA,yBAAW,EAAC,OAAO,EAAE,QAAQ,CAAC,YAAY,CAAC,MAAM,EAAE;gBAC/C,OAAO,CAAC,aAAa,CAAC,kBAAkB,CAAC,GAAG,EAAE,EAAE,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;YACzE,CAAC,CAAC,CAAC;SACN;aAAM;YACH,sFAAsF;YACtF,wHAAwH;YACxH,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,iDAAuB,CAAC,CAAC;YAEjD,OAAO,CAAC,aAAa,CAAC,kBAAkB,CAAC,GAAG,EAAE,EAAE,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;YAErE,IAAA,eAAM,EAAC,EAAE,CAAC,CAAC;SACd;QAED,MAAA,OAAO,CAAC,aAAa,+CAArB,OAAO,EAAiB,QAAQ,EAAE,EAAE,CAAC,CAAC;QAEtC,OAAO,OAAO,CAAC;IACnB,CAAC,CAAC;IA9CW,QAAA,cAAc,kBA8CzB","sourcesContent":["import { applyFormat } from '../utils/applyFormat';\nimport { applyMetadata } from '../utils/applyMetadata';\nimport { setParagraphNotImplicit } from '../../modelApi/block/setParagraphNotImplicit';\nimport { stackFormat } from '../utils/stackFormat';\nimport { unwrap } from '../../domUtils/unwrap';\nimport type {\n ContentModelBlockHandler,\n ContentModelListItem,\n ModelToDomContext,\n} from 'roosterjs-content-model-types';\n\n/**\n * @internal\n */\nexport const handleListItem: ContentModelBlockHandler<ContentModelListItem> = (\n doc: Document,\n parent: Node,\n listItem: ContentModelListItem,\n context: ModelToDomContext,\n refNode: Node | null\n) => {\n refNode = context.modelHandlers.list(doc, parent, listItem, context, refNode);\n\n const { nodeStack } = context.listFormat;\n\n const listParent = nodeStack?.[nodeStack?.length - 1]?.node || parent;\n const li = doc.createElement('li');\n const level = listItem.levels[listItem.levels.length - 1];\n\n // It is possible listParent is the same with parent param.\n // This happens when outdent a list item to cause it has no list level\n listParent.insertBefore(li, refNode?.parentNode == listParent ? refNode : null);\n context.rewriteFromModel.addedBlockElements.push(li);\n\n if (level) {\n applyFormat(li, context.formatAppliers.segment, listItem.formatHolder.format, context);\n applyFormat(li, context.formatAppliers.listItemThread, level.format, context);\n\n // Need to apply metadata after applying listItem format since the list numbers value relies on the result of list thread handling\n applyMetadata(level, context.metadataAppliers.listItem, listItem.format, context);\n\n // Need to apply listItemElement formats after applying metadata since the list numbers value relies on the result of metadata handling\n applyFormat(li, context.formatAppliers.listItemElement, listItem.format, context);\n\n stackFormat(context, listItem.formatHolder.format, () => {\n context.modelHandlers.blockGroupChildren(doc, li, listItem, context);\n });\n } else {\n // There is no level for this list item, that means it should be moved out of the list\n // For each paragraph, make it not implicit so it will have a DIV around it, to avoid more paragraphs connected together\n listItem.blocks.forEach(setParagraphNotImplicit);\n\n context.modelHandlers.blockGroupChildren(doc, li, listItem, context);\n\n unwrap(li);\n }\n\n context.onNodeCreated?.(listItem, li);\n\n return refNode;\n};\n"]}
1
+ {"version":3,"file":"handleListItem.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-dom/lib/modelToDom/handlers/handleListItem.ts"],"names":[],"mappings":"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","sourcesContent":["import { applyFormat } from '../utils/applyFormat';\nimport { applyMetadata } from '../utils/applyMetadata';\nimport { isGenericRoleElement } from '../../domUtils/isGenericRoleElement';\nimport { setParagraphNotImplicit } from '../../modelApi/block/setParagraphNotImplicit';\nimport { stackFormat } from '../utils/stackFormat';\nimport { unwrap } from '../../domUtils/unwrap';\nimport type {\n ContentModelBlockHandler,\n ContentModelListItem,\n ModelToDomContext,\n} from 'roosterjs-content-model-types';\n\nconst HtmlRoleAttribute = 'role';\nconst PresentationRoleValue = 'presentation';\n\n/**\n * @internal\n */\nexport const handleListItem: ContentModelBlockHandler<ContentModelListItem> = (\n doc: Document,\n parent: Node,\n listItem: ContentModelListItem,\n context: ModelToDomContext,\n refNode: Node | null\n) => {\n refNode = context.modelHandlers.list(doc, parent, listItem, context, refNode);\n\n const { nodeStack } = context.listFormat;\n\n const listParent = nodeStack?.[nodeStack?.length - 1]?.node || parent;\n const li = doc.createElement('li');\n const level = listItem.levels[listItem.levels.length - 1];\n\n // It is possible listParent is the same with parent param.\n // This happens when outdent a list item to cause it has no list level\n listParent.insertBefore(li, refNode?.parentNode == listParent ? refNode : null);\n context.rewriteFromModel.addedBlockElements.push(li);\n\n if (level) {\n applyFormat(li, context.formatAppliers.segment, listItem.formatHolder.format, context);\n applyFormat(li, context.formatAppliers.listItemThread, level.format, context);\n\n // Need to apply metadata after applying listItem format since the list numbers value relies on the result of list thread handling\n applyMetadata(level, context.metadataAppliers.listItem, listItem.format, context);\n\n // Need to apply listItemElement formats after applying metadata since the list numbers value relies on the result of metadata handling\n applyFormat(li, context.formatAppliers.listItemElement, listItem.format, context);\n\n stackFormat(context, listItem.formatHolder.format, () => {\n context.modelHandlers.blockGroupChildren(doc, li, listItem, context);\n });\n } else {\n // There is no level for this list item, that means it should be moved out of the list\n // For each paragraph, make it not implicit so it will have a DIV around it, to avoid more paragraphs connected together\n listItem.blocks.forEach(setParagraphNotImplicit);\n\n context.modelHandlers.blockGroupChildren(doc, li, listItem, context);\n\n unwrap(li);\n }\n\n // Add role=\"presentation\" to all generic role elements inside the LI element\n // This is to make sure the elements are announced correctly by screen readers\n // when using arrow keys to navigate the list.\n for (let index = 0; index < li.children.length; index++) {\n const element = li.children.item(index);\n if (isGenericRoleElement(element)) {\n element.setAttribute(HtmlRoleAttribute, PresentationRoleValue);\n }\n }\n\n context.onNodeCreated?.(listItem, li);\n\n return refNode;\n};\n"]}
@@ -0,0 +1,4 @@
1
+ /**
2
+ * @internal
3
+ */
4
+ export declare function isGenericRoleElement(element: Element | null): element is Element;
@@ -0,0 +1,30 @@
1
+ // List of elements that have generic roles by default
2
+ var genericRoleElements = new Set([
3
+ 'div',
4
+ 'span',
5
+ 'p',
6
+ 'section',
7
+ 'article',
8
+ 'aside',
9
+ 'header',
10
+ 'footer',
11
+ 'main',
12
+ 'nav',
13
+ 'address',
14
+ 'blockquote',
15
+ 'pre',
16
+ 'figure',
17
+ 'figcaption',
18
+ 'hgroup',
19
+ ]);
20
+ /**
21
+ * @internal
22
+ */
23
+ export function isGenericRoleElement(element) {
24
+ if (!element) {
25
+ return false;
26
+ }
27
+ var tagName = element.tagName.toLowerCase();
28
+ return genericRoleElements.has(tagName);
29
+ }
30
+ //# sourceMappingURL=isGenericRoleElement.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"isGenericRoleElement.js","sourceRoot":"","sources":["../../../../packages/roosterjs-content-model-dom/lib/domUtils/isGenericRoleElement.ts"],"names":[],"mappings":"AAAA,sDAAsD;AACtD,IAAM,mBAAmB,GAAG,IAAI,GAAG,CAAC;IAChC,KAAK;IACL,MAAM;IACN,GAAG;IACH,SAAS;IACT,SAAS;IACT,OAAO;IACP,QAAQ;IACR,QAAQ;IACR,MAAM;IACN,KAAK;IACL,SAAS;IACT,YAAY;IACZ,KAAK;IACL,QAAQ;IACR,YAAY;IACZ,QAAQ;CACX,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAAC,OAAuB;IACxD,IAAI,CAAC,OAAO,EAAE;QACV,OAAO,KAAK,CAAC;KAChB;IAED,IAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC;IAE9C,OAAO,mBAAmB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AAC5C,CAAC","sourcesContent":["// List of elements that have generic roles by default\nconst genericRoleElements = new Set([\n 'div',\n 'span',\n 'p',\n 'section',\n 'article',\n 'aside',\n 'header',\n 'footer',\n 'main',\n 'nav',\n 'address',\n 'blockquote',\n 'pre',\n 'figure',\n 'figcaption',\n 'hgroup',\n]);\n\n/**\n * @internal\n */\nexport function isGenericRoleElement(element: Element | null): element is Element {\n if (!element) {\n return false;\n }\n\n const tagName = element.tagName.toLowerCase();\n\n return genericRoleElements.has(tagName);\n}\n"]}
@@ -5,7 +5,7 @@
5
5
  * @returns The normalized font family string
6
6
  */
7
7
  export function normalizeFontFamily(fontFamily) {
8
- var existingQuotedFontsRegex = /".*?"/g;
8
+ var existingQuotedFontsRegex = /(".*?")|('.*?')/g;
9
9
  var match = existingQuotedFontsRegex.exec(fontFamily);
10
10
  var start = 0;
11
11
  var result = [];
@@ -1 +1 @@
1
- {"version":3,"file":"normalizeFontFamily.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-dom/lib/domUtils/style/normalizeFontFamily.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CAAC,UAAkB;IAClD,IAAM,wBAAwB,GAAG,QAAQ,CAAC;IAC1C,IAAI,KAAK,GAAG,wBAAwB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACtD,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAM,MAAM,GAAa,EAAE,CAAC;IAE5B,OAAO,KAAK,EAAE;QACV,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;QAEhD,KAAK,GAAG,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;QACtC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAEtB,KAAK,GAAG,wBAAwB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;KACrD;IAED,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC;IAEtD,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC7B,CAAC;AAED,SAAS,OAAO,CAAC,UAAkB,EAAE,MAAgB,EAAE,KAAa,EAAE,GAAW;IAC7E,IAAM,QAAQ,GAAG,UAAU,CAAC,SAAS,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAE7D,QAAQ,CAAC,OAAO,CAAC,UAAA,MAAM;QACnB,MAAM,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;QAEvB,IAAI,MAAM,EAAE;YACR,gEAAgE;YAChE,IAAI,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE;gBAC/B,MAAM,CAAC,IAAI,CAAC,OAAI,MAAM,OAAG,CAAC,CAAC;aAC9B;iBAAM;gBACH,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;aACvB;SACJ;IACL,CAAC,CAAC,CAAC;AACP,CAAC","sourcesContent":["/**\n * Normalize font family string to a standard format\n * Add quotes around font family names that contain non-alphanumeric/dash characters\n * @param fontFamily The font family string to normalize\n * @returns The normalized font family string\n */\nexport function normalizeFontFamily(fontFamily: string): string {\n const existingQuotedFontsRegex = /\".*?\"/g;\n let match = existingQuotedFontsRegex.exec(fontFamily);\n let start = 0;\n const result: string[] = [];\n\n while (match) {\n process(fontFamily, result, start, match.index);\n\n start = match.index + match[0].length;\n result.push(match[0]);\n\n match = existingQuotedFontsRegex.exec(fontFamily);\n }\n\n process(fontFamily, result, start, fontFamily.length);\n\n return result.join(', ');\n}\n\nfunction process(fontFamily: string, result: string[], start: number, end: number) {\n const families = fontFamily.substring(start, end).split(',');\n\n families.forEach(family => {\n family = family.trim();\n\n if (family) {\n // Check if the family name contains non-alphanumeric characters\n if (/[^a-zA-Z0-9\\-]/.test(family)) {\n result.push(`\"${family}\"`);\n } else {\n result.push(family);\n }\n }\n });\n}\n"]}
1
+ {"version":3,"file":"normalizeFontFamily.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-dom/lib/domUtils/style/normalizeFontFamily.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CAAC,UAAkB;IAClD,IAAM,wBAAwB,GAAG,kBAAkB,CAAC;IACpD,IAAI,KAAK,GAAG,wBAAwB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACtD,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAM,MAAM,GAAa,EAAE,CAAC;IAE5B,OAAO,KAAK,EAAE;QACV,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;QAEhD,KAAK,GAAG,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;QACtC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAEtB,KAAK,GAAG,wBAAwB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;KACrD;IAED,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC;IAEtD,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC7B,CAAC;AAED,SAAS,OAAO,CAAC,UAAkB,EAAE,MAAgB,EAAE,KAAa,EAAE,GAAW;IAC7E,IAAM,QAAQ,GAAG,UAAU,CAAC,SAAS,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAE7D,QAAQ,CAAC,OAAO,CAAC,UAAA,MAAM;QACnB,MAAM,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;QAEvB,IAAI,MAAM,EAAE;YACR,gEAAgE;YAChE,IAAI,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE;gBAC/B,MAAM,CAAC,IAAI,CAAC,OAAI,MAAM,OAAG,CAAC,CAAC;aAC9B;iBAAM;gBACH,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;aACvB;SACJ;IACL,CAAC,CAAC,CAAC;AACP,CAAC","sourcesContent":["/**\n * Normalize font family string to a standard format\n * Add quotes around font family names that contain non-alphanumeric/dash characters\n * @param fontFamily The font family string to normalize\n * @returns The normalized font family string\n */\nexport function normalizeFontFamily(fontFamily: string): string {\n const existingQuotedFontsRegex = /(\".*?\")|('.*?')/g;\n let match = existingQuotedFontsRegex.exec(fontFamily);\n let start = 0;\n const result: string[] = [];\n\n while (match) {\n process(fontFamily, result, start, match.index);\n\n start = match.index + match[0].length;\n result.push(match[0]);\n\n match = existingQuotedFontsRegex.exec(fontFamily);\n }\n\n process(fontFamily, result, start, fontFamily.length);\n\n return result.join(', ');\n}\n\nfunction process(fontFamily: string, result: string[], start: number, end: number) {\n const families = fontFamily.substring(start, end).split(',');\n\n families.forEach(family => {\n family = family.trim();\n\n if (family) {\n // Check if the family name contains non-alphanumeric characters\n if (/[^a-zA-Z0-9\\-]/.test(family)) {\n result.push(`\"${family}\"`);\n } else {\n result.push(family);\n }\n }\n });\n}\n"]}
@@ -1,8 +1,11 @@
1
1
  import { applyFormat } from '../utils/applyFormat';
2
2
  import { applyMetadata } from '../utils/applyMetadata';
3
+ import { isGenericRoleElement } from '../../domUtils/isGenericRoleElement';
3
4
  import { setParagraphNotImplicit } from '../../modelApi/block/setParagraphNotImplicit';
4
5
  import { stackFormat } from '../utils/stackFormat';
5
6
  import { unwrap } from '../../domUtils/unwrap';
7
+ var HtmlRoleAttribute = 'role';
8
+ var PresentationRoleValue = 'presentation';
6
9
  /**
7
10
  * @internal
8
11
  */
@@ -35,6 +38,15 @@ export var handleListItem = function (doc, parent, listItem, context, refNode) {
35
38
  context.modelHandlers.blockGroupChildren(doc, li, listItem, context);
36
39
  unwrap(li);
37
40
  }
41
+ // Add role="presentation" to all generic role elements inside the LI element
42
+ // This is to make sure the elements are announced correctly by screen readers
43
+ // when using arrow keys to navigate the list.
44
+ for (var index = 0; index < li.children.length; index++) {
45
+ var element = li.children.item(index);
46
+ if (isGenericRoleElement(element)) {
47
+ element.setAttribute(HtmlRoleAttribute, PresentationRoleValue);
48
+ }
49
+ }
38
50
  (_b = context.onNodeCreated) === null || _b === void 0 ? void 0 : _b.call(context, listItem, li);
39
51
  return refNode;
40
52
  };
@@ -1 +1 @@
1
- {"version":3,"file":"handleListItem.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-dom/lib/modelToDom/handlers/handleListItem.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,uBAAuB,EAAE,MAAM,8CAA8C,CAAC;AACvF,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAO/C;;GAEG;AACH,MAAM,CAAC,IAAM,cAAc,GAAmD,UAC1E,GAAa,EACb,MAAY,EACZ,QAA8B,EAC9B,OAA0B,EAC1B,OAAoB;;IAEpB,OAAO,GAAG,OAAO,CAAC,aAAa,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IAEtE,IAAA,SAAS,GAAK,OAAO,CAAC,UAAU,UAAvB,CAAwB;IAEzC,IAAM,UAAU,GAAG,CAAA,MAAA,SAAS,aAAT,SAAS,uBAAT,SAAS,CAAG,CAAA,SAAS,aAAT,SAAS,uBAAT,SAAS,CAAE,MAAM,IAAG,CAAC,CAAC,0CAAE,IAAI,KAAI,MAAM,CAAC;IACtE,IAAM,EAAE,GAAG,GAAG,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;IACnC,IAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAE1D,2DAA2D;IAC3D,sEAAsE;IACtE,UAAU,CAAC,YAAY,CAAC,EAAE,EAAE,CAAA,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,UAAU,KAAI,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAChF,OAAO,CAAC,gBAAgB,CAAC,kBAAkB,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAErD,IAAI,KAAK,EAAE;QACP,WAAW,CAAC,EAAE,EAAE,OAAO,CAAC,cAAc,CAAC,OAAO,EAAE,QAAQ,CAAC,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACvF,WAAW,CAAC,EAAE,EAAE,OAAO,CAAC,cAAc,CAAC,cAAc,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAE9E,kIAAkI;QAClI,aAAa,CAAC,KAAK,EAAE,OAAO,CAAC,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAElF,uIAAuI;QACvI,WAAW,CAAC,EAAE,EAAE,OAAO,CAAC,cAAc,CAAC,eAAe,EAAE,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAElF,WAAW,CAAC,OAAO,EAAE,QAAQ,CAAC,YAAY,CAAC,MAAM,EAAE;YAC/C,OAAO,CAAC,aAAa,CAAC,kBAAkB,CAAC,GAAG,EAAE,EAAE,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;QACzE,CAAC,CAAC,CAAC;KACN;SAAM;QACH,sFAAsF;QACtF,wHAAwH;QACxH,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,uBAAuB,CAAC,CAAC;QAEjD,OAAO,CAAC,aAAa,CAAC,kBAAkB,CAAC,GAAG,EAAE,EAAE,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;QAErE,MAAM,CAAC,EAAE,CAAC,CAAC;KACd;IAED,MAAA,OAAO,CAAC,aAAa,+CAArB,OAAO,EAAiB,QAAQ,EAAE,EAAE,CAAC,CAAC;IAEtC,OAAO,OAAO,CAAC;AACnB,CAAC,CAAC","sourcesContent":["import { applyFormat } from '../utils/applyFormat';\nimport { applyMetadata } from '../utils/applyMetadata';\nimport { setParagraphNotImplicit } from '../../modelApi/block/setParagraphNotImplicit';\nimport { stackFormat } from '../utils/stackFormat';\nimport { unwrap } from '../../domUtils/unwrap';\nimport type {\n ContentModelBlockHandler,\n ContentModelListItem,\n ModelToDomContext,\n} from 'roosterjs-content-model-types';\n\n/**\n * @internal\n */\nexport const handleListItem: ContentModelBlockHandler<ContentModelListItem> = (\n doc: Document,\n parent: Node,\n listItem: ContentModelListItem,\n context: ModelToDomContext,\n refNode: Node | null\n) => {\n refNode = context.modelHandlers.list(doc, parent, listItem, context, refNode);\n\n const { nodeStack } = context.listFormat;\n\n const listParent = nodeStack?.[nodeStack?.length - 1]?.node || parent;\n const li = doc.createElement('li');\n const level = listItem.levels[listItem.levels.length - 1];\n\n // It is possible listParent is the same with parent param.\n // This happens when outdent a list item to cause it has no list level\n listParent.insertBefore(li, refNode?.parentNode == listParent ? refNode : null);\n context.rewriteFromModel.addedBlockElements.push(li);\n\n if (level) {\n applyFormat(li, context.formatAppliers.segment, listItem.formatHolder.format, context);\n applyFormat(li, context.formatAppliers.listItemThread, level.format, context);\n\n // Need to apply metadata after applying listItem format since the list numbers value relies on the result of list thread handling\n applyMetadata(level, context.metadataAppliers.listItem, listItem.format, context);\n\n // Need to apply listItemElement formats after applying metadata since the list numbers value relies on the result of metadata handling\n applyFormat(li, context.formatAppliers.listItemElement, listItem.format, context);\n\n stackFormat(context, listItem.formatHolder.format, () => {\n context.modelHandlers.blockGroupChildren(doc, li, listItem, context);\n });\n } else {\n // There is no level for this list item, that means it should be moved out of the list\n // For each paragraph, make it not implicit so it will have a DIV around it, to avoid more paragraphs connected together\n listItem.blocks.forEach(setParagraphNotImplicit);\n\n context.modelHandlers.blockGroupChildren(doc, li, listItem, context);\n\n unwrap(li);\n }\n\n context.onNodeCreated?.(listItem, li);\n\n return refNode;\n};\n"]}
1
+ {"version":3,"file":"handleListItem.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-dom/lib/modelToDom/handlers/handleListItem.ts"],"names":[],"mappings":"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","sourcesContent":["import { applyFormat } from '../utils/applyFormat';\nimport { applyMetadata } from '../utils/applyMetadata';\nimport { isGenericRoleElement } from '../../domUtils/isGenericRoleElement';\nimport { setParagraphNotImplicit } from '../../modelApi/block/setParagraphNotImplicit';\nimport { stackFormat } from '../utils/stackFormat';\nimport { unwrap } from '../../domUtils/unwrap';\nimport type {\n ContentModelBlockHandler,\n ContentModelListItem,\n ModelToDomContext,\n} from 'roosterjs-content-model-types';\n\nconst HtmlRoleAttribute = 'role';\nconst PresentationRoleValue = 'presentation';\n\n/**\n * @internal\n */\nexport const handleListItem: ContentModelBlockHandler<ContentModelListItem> = (\n doc: Document,\n parent: Node,\n listItem: ContentModelListItem,\n context: ModelToDomContext,\n refNode: Node | null\n) => {\n refNode = context.modelHandlers.list(doc, parent, listItem, context, refNode);\n\n const { nodeStack } = context.listFormat;\n\n const listParent = nodeStack?.[nodeStack?.length - 1]?.node || parent;\n const li = doc.createElement('li');\n const level = listItem.levels[listItem.levels.length - 1];\n\n // It is possible listParent is the same with parent param.\n // This happens when outdent a list item to cause it has no list level\n listParent.insertBefore(li, refNode?.parentNode == listParent ? refNode : null);\n context.rewriteFromModel.addedBlockElements.push(li);\n\n if (level) {\n applyFormat(li, context.formatAppliers.segment, listItem.formatHolder.format, context);\n applyFormat(li, context.formatAppliers.listItemThread, level.format, context);\n\n // Need to apply metadata after applying listItem format since the list numbers value relies on the result of list thread handling\n applyMetadata(level, context.metadataAppliers.listItem, listItem.format, context);\n\n // Need to apply listItemElement formats after applying metadata since the list numbers value relies on the result of metadata handling\n applyFormat(li, context.formatAppliers.listItemElement, listItem.format, context);\n\n stackFormat(context, listItem.formatHolder.format, () => {\n context.modelHandlers.blockGroupChildren(doc, li, listItem, context);\n });\n } else {\n // There is no level for this list item, that means it should be moved out of the list\n // For each paragraph, make it not implicit so it will have a DIV around it, to avoid more paragraphs connected together\n listItem.blocks.forEach(setParagraphNotImplicit);\n\n context.modelHandlers.blockGroupChildren(doc, li, listItem, context);\n\n unwrap(li);\n }\n\n // Add role=\"presentation\" to all generic role elements inside the LI element\n // This is to make sure the elements are announced correctly by screen readers\n // when using arrow keys to navigate the list.\n for (let index = 0; index < li.children.length; index++) {\n const element = li.children.item(index);\n if (isGenericRoleElement(element)) {\n element.setAttribute(HtmlRoleAttribute, PresentationRoleValue);\n }\n }\n\n context.onNodeCreated?.(listItem, li);\n\n return refNode;\n};\n"]}
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "tslib": "^2.3.1",
6
6
  "roosterjs-content-model-types": "^9.29.0"
7
7
  },
8
- "version": "9.29.0",
8
+ "version": "9.29.2",
9
9
  "main": "./lib/index.js",
10
10
  "typings": "./lib/index.d.ts",
11
11
  "module": "./lib-mjs/index.js",