roosterjs-content-model-plugins 0.28.0 → 0.28.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.
@@ -25,6 +25,13 @@ function handleTabOnParagraph(model, paragraph, rawEvent) {
25
25
  var isCollapsed = selectedSegments.length === 1 && selectedSegments[0].segmentType === 'SelectionMarker';
26
26
  var isAllSelected = paragraph.segments.every(function (segment) { return segment.isSelected; });
27
27
  if ((paragraph.segments[0].segmentType === 'SelectionMarker' && isCollapsed) || isAllSelected) {
28
+ var _a = paragraph.format, marginLeft = _a.marginLeft, marginRight = _a.marginRight, direction = _a.direction;
29
+ var isRtl = direction === 'rtl';
30
+ if (rawEvent.shiftKey &&
31
+ ((!isRtl && (!marginLeft || marginLeft == '0px')) ||
32
+ (isRtl && (!marginRight || marginRight == '0px')))) {
33
+ return false;
34
+ }
28
35
  (0, roosterjs_content_model_api_1.setModelIndentation)(model, rawEvent.shiftKey ? 'outdent' : 'indent');
29
36
  }
30
37
  else {
@@ -1 +1 @@
1
- {"version":3,"file":"handleTabOnParagraph.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-plugins/lib/edit/tabUtils/handleTabOnParagraph.ts"],"names":[],"mappings":"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","sourcesContent":["import { createSelectionMarker, createText } from 'roosterjs-content-model-dom';\nimport { setModelIndentation } from 'roosterjs-content-model-api';\nimport type { ContentModelDocument, ContentModelParagraph } from 'roosterjs-content-model-types';\n\nconst tabSpaces = '    ';\nconst space = ' ';\n\n/**\n * @internal\n The handleTabOnParagraph function will handle the tab key in following scenarios:\n * 1. When the selection is collapsed and the cursor is at the end of a paragraph, add 4 spaces.\n * 2. When the selection is collapsed and the cursor is at the start of a paragraph, call setModelIndention function to indent the whole paragraph\n * 3. When the selection is collapsed and the cursor is at the middle of a paragraph, add 4 spaces.\n * 4. When the selection is not collapsed, replace the selected range with a single space.\n * 5. When the selection is not collapsed, but all segments are selected, call setModelIndention function to indent the whole paragraph\n The handleTabOnParagraph function will handle the shift + tab key in a indented paragraph in following scenarios:\n * 1. When the selection is collapsed and the cursor is at the end of a paragraph, remove 4 spaces.\n * 2. When the selection is collapsed and the cursor is at the start of a paragraph, call setModelIndention function to outdent the whole paragraph\n * 3. When the selection is collapsed and the cursor is at the middle of a paragraph, remove 4 spaces.\n * 4. When the selection is not collapsed, replace the selected range with a 4 space.\n * 5. When the selection is not collapsed, but all segments are selected, call setModelIndention function to outdent the whole paragraph\n */\nexport function handleTabOnParagraph(\n model: ContentModelDocument,\n paragraph: ContentModelParagraph,\n rawEvent: KeyboardEvent\n) {\n const selectedSegments = paragraph.segments.filter(segment => segment.isSelected);\n const isCollapsed =\n selectedSegments.length === 1 && selectedSegments[0].segmentType === 'SelectionMarker';\n const isAllSelected = paragraph.segments.every(segment => segment.isSelected);\n if ((paragraph.segments[0].segmentType === 'SelectionMarker' && isCollapsed) || isAllSelected) {\n setModelIndentation(model, rawEvent.shiftKey ? 'outdent' : 'indent');\n } else {\n if (!isCollapsed) {\n let firstSelectedSegmentIndex: number | undefined = undefined;\n let lastSelectedSegmentIndex: number | undefined = undefined;\n\n paragraph.segments.forEach((segment, index) => {\n if (segment.isSelected) {\n if (!firstSelectedSegmentIndex) {\n firstSelectedSegmentIndex = index;\n }\n lastSelectedSegmentIndex = index;\n }\n });\n if (firstSelectedSegmentIndex && lastSelectedSegmentIndex) {\n const firstSelectedSegment = paragraph.segments[firstSelectedSegmentIndex];\n const spaceText = createText(\n rawEvent.shiftKey ? tabSpaces : space,\n firstSelectedSegment.format\n );\n const marker = createSelectionMarker(firstSelectedSegment.format);\n paragraph.segments.splice(\n firstSelectedSegmentIndex,\n lastSelectedSegmentIndex - firstSelectedSegmentIndex + 1,\n spaceText,\n marker\n );\n } else {\n return false;\n }\n } else {\n const markerIndex = paragraph.segments.findIndex(\n segment => segment.segmentType === 'SelectionMarker'\n );\n if (!rawEvent.shiftKey) {\n const markerFormat = paragraph.segments[markerIndex].format;\n const tabText = createText(tabSpaces, markerFormat);\n paragraph.segments.splice(markerIndex, 0, tabText);\n } else {\n const tabText = paragraph.segments[markerIndex - 1];\n const tabSpacesLength = tabSpaces.length;\n if (tabText.segmentType == 'Text') {\n const tabSpaceTextLength = tabText.text.length - tabSpacesLength;\n if (tabText.text === tabSpaces) {\n paragraph.segments.splice(markerIndex - 1, 1);\n } else if (tabText.text.substring(tabSpaceTextLength) === tabSpaces) {\n tabText.text = tabText.text.substring(0, tabSpaceTextLength);\n } else {\n return false;\n }\n }\n }\n }\n }\n\n rawEvent.preventDefault();\n return true;\n}\n"]}
1
+ {"version":3,"file":"handleTabOnParagraph.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-plugins/lib/edit/tabUtils/handleTabOnParagraph.ts"],"names":[],"mappings":"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","sourcesContent":["import { createSelectionMarker, createText } from 'roosterjs-content-model-dom';\nimport { setModelIndentation } from 'roosterjs-content-model-api';\nimport type { ContentModelDocument, ContentModelParagraph } from 'roosterjs-content-model-types';\n\nconst tabSpaces = '    ';\nconst space = ' ';\n\n/**\n * @internal\n The handleTabOnParagraph function will handle the tab key in following scenarios:\n * 1. When the selection is collapsed and the cursor is at the end of a paragraph, add 4 spaces.\n * 2. When the selection is collapsed and the cursor is at the start of a paragraph, call setModelIndention function to indent the whole paragraph\n * 3. When the selection is collapsed and the cursor is at the middle of a paragraph, add 4 spaces.\n * 4. When the selection is not collapsed, replace the selected range with a single space.\n * 5. When the selection is not collapsed, but all segments are selected, call setModelIndention function to indent the whole paragraph\n The handleTabOnParagraph function will handle the shift + tab key in a indented paragraph in following scenarios:\n * 1. When the selection is collapsed and the cursor is at the end of a paragraph, remove 4 spaces.\n * 2. When the selection is collapsed and the cursor is at the start of a paragraph, call setModelIndention function to outdent the whole paragraph\n * 3. When the selection is collapsed and the cursor is at the middle of a paragraph, remove 4 spaces.\n * 4. When the selection is not collapsed, replace the selected range with a 4 space.\n * 5. When the selection is not collapsed, but all segments are selected, call setModelIndention function to outdent the whole paragraph\n */\nexport function handleTabOnParagraph(\n model: ContentModelDocument,\n paragraph: ContentModelParagraph,\n rawEvent: KeyboardEvent\n) {\n const selectedSegments = paragraph.segments.filter(segment => segment.isSelected);\n const isCollapsed =\n selectedSegments.length === 1 && selectedSegments[0].segmentType === 'SelectionMarker';\n const isAllSelected = paragraph.segments.every(segment => segment.isSelected);\n if ((paragraph.segments[0].segmentType === 'SelectionMarker' && isCollapsed) || isAllSelected) {\n const { marginLeft, marginRight, direction } = paragraph.format;\n const isRtl = direction === 'rtl';\n if (\n rawEvent.shiftKey &&\n ((!isRtl && (!marginLeft || marginLeft == '0px')) ||\n (isRtl && (!marginRight || marginRight == '0px')))\n ) {\n return false;\n }\n setModelIndentation(model, rawEvent.shiftKey ? 'outdent' : 'indent');\n } else {\n if (!isCollapsed) {\n let firstSelectedSegmentIndex: number | undefined = undefined;\n let lastSelectedSegmentIndex: number | undefined = undefined;\n\n paragraph.segments.forEach((segment, index) => {\n if (segment.isSelected) {\n if (!firstSelectedSegmentIndex) {\n firstSelectedSegmentIndex = index;\n }\n lastSelectedSegmentIndex = index;\n }\n });\n if (firstSelectedSegmentIndex && lastSelectedSegmentIndex) {\n const firstSelectedSegment = paragraph.segments[firstSelectedSegmentIndex];\n const spaceText = createText(\n rawEvent.shiftKey ? tabSpaces : space,\n firstSelectedSegment.format\n );\n const marker = createSelectionMarker(firstSelectedSegment.format);\n paragraph.segments.splice(\n firstSelectedSegmentIndex,\n lastSelectedSegmentIndex - firstSelectedSegmentIndex + 1,\n spaceText,\n marker\n );\n } else {\n return false;\n }\n } else {\n const markerIndex = paragraph.segments.findIndex(\n segment => segment.segmentType === 'SelectionMarker'\n );\n if (!rawEvent.shiftKey) {\n const markerFormat = paragraph.segments[markerIndex].format;\n const tabText = createText(tabSpaces, markerFormat);\n paragraph.segments.splice(markerIndex, 0, tabText);\n } else {\n const tabText = paragraph.segments[markerIndex - 1];\n const tabSpacesLength = tabSpaces.length;\n if (tabText.segmentType == 'Text') {\n const tabSpaceTextLength = tabText.text.length - tabSpacesLength;\n if (tabText.text === tabSpaces) {\n paragraph.segments.splice(markerIndex - 1, 1);\n } else if (tabText.text.substring(tabSpaceTextLength) === tabSpaces) {\n tabText.text = tabText.text.substring(0, tabSpaceTextLength);\n } else {\n return false;\n }\n }\n }\n }\n }\n rawEvent.preventDefault();\n return true;\n}\n"]}
@@ -1,10 +1,15 @@
1
- import type { BeforePasteEvent, TrustedHTMLHandler } from 'roosterjs-content-model-types';
1
+ import type { BeforePasteEvent, ElementProcessor, TrustedHTMLHandler } from 'roosterjs-content-model-types';
2
2
  /**
3
3
  * @internal
4
4
  * Convert pasted content from Excel, add borders when source doc doesn't have a border
5
5
  * @param event The BeforePaste event
6
6
  */
7
7
  export declare function processPastedContentFromExcel(event: BeforePasteEvent, trustedHTMLHandler: TrustedHTMLHandler, allowExcelNoBorderTable?: boolean): void;
8
+ /**
9
+ * @internal
10
+ * Exported only for unit test
11
+ */
12
+ export declare const childProcessor: ElementProcessor<ParentNode>;
8
13
  /**
9
14
  * @internal Export for test only
10
15
  * @param html Source html
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.excelHandler = exports.processPastedContentFromExcel = void 0;
3
+ exports.excelHandler = exports.childProcessor = exports.processPastedContentFromExcel = void 0;
4
4
  var tslib_1 = require("tslib");
5
5
  var addParser_1 = require("../utils/addParser");
6
6
  var roosterjs_content_model_dom_1 = require("roosterjs-content-model-dom");
@@ -49,19 +49,27 @@ function processPastedContentFromExcel(event, trustedHTMLHandler, allowExcelNoBo
49
49
  format.borderTop = DEFAULT_BORDER_STYLE;
50
50
  }
51
51
  });
52
- (0, setProcessor_1.setProcessor)(event.domToModelOption, 'child', function (group, element, context) {
53
- var segmentFormat = (0, tslib_1.__assign)({}, context.segmentFormat);
54
- if (group.blockGroupType === 'TableCell' && group.format.textColor) {
55
- context.segmentFormat.textColor = group.format.textColor;
56
- }
57
- context.defaultElementProcessors.child(group, element, context);
58
- if (group.blockGroupType === 'TableCell' && group.format.textColor) {
59
- context.segmentFormat = segmentFormat;
60
- delete group.format.textColor;
61
- }
62
- });
52
+ (0, setProcessor_1.setProcessor)(event.domToModelOption, 'child', exports.childProcessor);
63
53
  }
64
54
  exports.processPastedContentFromExcel = processPastedContentFromExcel;
55
+ /**
56
+ * @internal
57
+ * Exported only for unit test
58
+ */
59
+ var childProcessor = function (group, element, context) {
60
+ var segmentFormat = (0, tslib_1.__assign)({}, context.segmentFormat);
61
+ if (group.blockGroupType === 'TableCell' &&
62
+ group.format.textColor &&
63
+ !context.segmentFormat.textColor) {
64
+ context.segmentFormat.textColor = group.format.textColor;
65
+ }
66
+ context.defaultElementProcessors.child(group, element, context);
67
+ if (group.blockGroupType === 'TableCell' && group.format.textColor) {
68
+ context.segmentFormat = segmentFormat;
69
+ delete group.format.textColor;
70
+ }
71
+ };
72
+ exports.childProcessor = childProcessor;
65
73
  /**
66
74
  * @internal Export for test only
67
75
  * @param html Source html
@@ -1 +1 @@
1
- {"version":3,"file":"processPastedContentFromExcel.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-plugins/lib/paste/Excel/processPastedContentFromExcel.ts"],"names":[],"mappings":"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","sourcesContent":["import { addParser } from '../utils/addParser';\nimport { isNodeOfType, moveChildNodes } from 'roosterjs-content-model-dom';\nimport { setProcessor } from '../utils/setProcessor';\nimport type { BeforePasteEvent, TrustedHTMLHandler } from 'roosterjs-content-model-types';\n\nconst LAST_TD_END_REGEX = /<\\/\\s*td\\s*>((?!<\\/\\s*tr\\s*>)[\\s\\S])*$/i;\nconst LAST_TR_END_REGEX = /<\\/\\s*tr\\s*>((?!<\\/\\s*table\\s*>)[\\s\\S])*$/i;\nconst LAST_TR_REGEX = /<tr[^>]*>[^<]*/i;\nconst LAST_TABLE_REGEX = /<table[^>]*>[^<]*/i;\nconst DEFAULT_BORDER_STYLE = 'solid 1px #d4d4d4';\n\n/**\n * @internal\n * Convert pasted content from Excel, add borders when source doc doesn't have a border\n * @param event The BeforePaste event\n */\n\nexport function processPastedContentFromExcel(\n event: BeforePasteEvent,\n trustedHTMLHandler: TrustedHTMLHandler,\n allowExcelNoBorderTable?: boolean\n) {\n const { fragment, htmlBefore, clipboardData } = event;\n const html = clipboardData.html ? excelHandler(clipboardData.html, htmlBefore) : undefined;\n\n if (html && clipboardData.html != html) {\n const doc = new DOMParser().parseFromString(trustedHTMLHandler(html), 'text/html');\n moveChildNodes(fragment, doc?.body);\n }\n\n // For Excel Online\n const firstChild = fragment.firstChild;\n if (\n isNodeOfType(firstChild, 'ELEMENT_NODE') &&\n firstChild.tagName == 'div' &&\n firstChild.firstChild\n ) {\n const tableFound = Array.from(firstChild.childNodes).every((child: Node) => {\n // Tables pasted from Excel Online should be of the format: 0 to N META tags and 1 TABLE tag\n const tagName = isNodeOfType(child, 'ELEMENT_NODE') && child.tagName;\n\n return tagName == 'META'\n ? true\n : tagName == 'TABLE'\n ? child == firstChild.lastChild\n : false;\n });\n\n // Extract Table from Div\n if (tableFound && firstChild.lastChild) {\n event.fragment.replaceChildren(firstChild.lastChild);\n }\n }\n\n addParser(event.domToModelOption, 'tableCell', (format, element) => {\n if (!allowExcelNoBorderTable && element.style.borderStyle === 'none') {\n format.borderBottom = DEFAULT_BORDER_STYLE;\n format.borderLeft = DEFAULT_BORDER_STYLE;\n format.borderRight = DEFAULT_BORDER_STYLE;\n format.borderTop = DEFAULT_BORDER_STYLE;\n }\n });\n\n setProcessor(event.domToModelOption, 'child', (group, element, context) => {\n const segmentFormat = { ...context.segmentFormat };\n if (group.blockGroupType === 'TableCell' && group.format.textColor) {\n context.segmentFormat.textColor = group.format.textColor;\n }\n\n context.defaultElementProcessors.child(group, element, context);\n\n if (group.blockGroupType === 'TableCell' && group.format.textColor) {\n context.segmentFormat = segmentFormat;\n delete group.format.textColor;\n }\n });\n}\n\n/**\n * @internal Export for test only\n * @param html Source html\n */\n\nexport function excelHandler(html: string, htmlBefore: string): string {\n if (html.match(LAST_TD_END_REGEX)) {\n const trMatch = htmlBefore.match(LAST_TR_REGEX);\n const tr = trMatch ? trMatch[0] : '<TR>';\n html = tr + html + '</TR>';\n }\n if (html.match(LAST_TR_END_REGEX)) {\n const tableMatch = htmlBefore.match(LAST_TABLE_REGEX);\n const table = tableMatch ? tableMatch[0] : '<TABLE>';\n html = table + html + '</TABLE>';\n }\n\n return html;\n}\n"]}
1
+ {"version":3,"file":"processPastedContentFromExcel.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-plugins/lib/paste/Excel/processPastedContentFromExcel.ts"],"names":[],"mappings":"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","sourcesContent":["import { addParser } from '../utils/addParser';\nimport { isNodeOfType, moveChildNodes } from 'roosterjs-content-model-dom';\nimport { setProcessor } from '../utils/setProcessor';\nimport type {\n BeforePasteEvent,\n ElementProcessor,\n TrustedHTMLHandler,\n} from 'roosterjs-content-model-types';\n\nconst LAST_TD_END_REGEX = /<\\/\\s*td\\s*>((?!<\\/\\s*tr\\s*>)[\\s\\S])*$/i;\nconst LAST_TR_END_REGEX = /<\\/\\s*tr\\s*>((?!<\\/\\s*table\\s*>)[\\s\\S])*$/i;\nconst LAST_TR_REGEX = /<tr[^>]*>[^<]*/i;\nconst LAST_TABLE_REGEX = /<table[^>]*>[^<]*/i;\nconst DEFAULT_BORDER_STYLE = 'solid 1px #d4d4d4';\n\n/**\n * @internal\n * Convert pasted content from Excel, add borders when source doc doesn't have a border\n * @param event The BeforePaste event\n */\n\nexport function processPastedContentFromExcel(\n event: BeforePasteEvent,\n trustedHTMLHandler: TrustedHTMLHandler,\n allowExcelNoBorderTable?: boolean\n) {\n const { fragment, htmlBefore, clipboardData } = event;\n const html = clipboardData.html ? excelHandler(clipboardData.html, htmlBefore) : undefined;\n\n if (html && clipboardData.html != html) {\n const doc = new DOMParser().parseFromString(trustedHTMLHandler(html), 'text/html');\n moveChildNodes(fragment, doc?.body);\n }\n\n // For Excel Online\n const firstChild = fragment.firstChild;\n if (\n isNodeOfType(firstChild, 'ELEMENT_NODE') &&\n firstChild.tagName == 'div' &&\n firstChild.firstChild\n ) {\n const tableFound = Array.from(firstChild.childNodes).every((child: Node) => {\n // Tables pasted from Excel Online should be of the format: 0 to N META tags and 1 TABLE tag\n const tagName = isNodeOfType(child, 'ELEMENT_NODE') && child.tagName;\n\n return tagName == 'META'\n ? true\n : tagName == 'TABLE'\n ? child == firstChild.lastChild\n : false;\n });\n\n // Extract Table from Div\n if (tableFound && firstChild.lastChild) {\n event.fragment.replaceChildren(firstChild.lastChild);\n }\n }\n\n addParser(event.domToModelOption, 'tableCell', (format, element) => {\n if (!allowExcelNoBorderTable && element.style.borderStyle === 'none') {\n format.borderBottom = DEFAULT_BORDER_STYLE;\n format.borderLeft = DEFAULT_BORDER_STYLE;\n format.borderRight = DEFAULT_BORDER_STYLE;\n format.borderTop = DEFAULT_BORDER_STYLE;\n }\n });\n\n setProcessor(event.domToModelOption, 'child', childProcessor);\n}\n\n/**\n * @internal\n * Exported only for unit test\n */\nexport const childProcessor: ElementProcessor<ParentNode> = (group, element, context) => {\n const segmentFormat = { ...context.segmentFormat };\n if (\n group.blockGroupType === 'TableCell' &&\n group.format.textColor &&\n !context.segmentFormat.textColor\n ) {\n context.segmentFormat.textColor = group.format.textColor;\n }\n\n context.defaultElementProcessors.child(group, element, context);\n\n if (group.blockGroupType === 'TableCell' && group.format.textColor) {\n context.segmentFormat = segmentFormat;\n delete group.format.textColor;\n }\n};\n\n/**\n * @internal Export for test only\n * @param html Source html\n */\n\nexport function excelHandler(html: string, htmlBefore: string): string {\n if (html.match(LAST_TD_END_REGEX)) {\n const trMatch = htmlBefore.match(LAST_TR_REGEX);\n const tr = trMatch ? trMatch[0] : '<TR>';\n html = tr + html + '</TR>';\n }\n if (html.match(LAST_TR_END_REGEX)) {\n const tableMatch = htmlBefore.match(LAST_TABLE_REGEX);\n const table = tableMatch ? tableMatch[0] : '<TABLE>';\n html = table + html + '</TABLE>';\n }\n\n return html;\n}\n"]}
@@ -24,6 +24,13 @@ define(["require", "exports", "roosterjs-content-model-dom", "roosterjs-content-
24
24
  var isCollapsed = selectedSegments.length === 1 && selectedSegments[0].segmentType === 'SelectionMarker';
25
25
  var isAllSelected = paragraph.segments.every(function (segment) { return segment.isSelected; });
26
26
  if ((paragraph.segments[0].segmentType === 'SelectionMarker' && isCollapsed) || isAllSelected) {
27
+ var _a = paragraph.format, marginLeft = _a.marginLeft, marginRight = _a.marginRight, direction = _a.direction;
28
+ var isRtl = direction === 'rtl';
29
+ if (rawEvent.shiftKey &&
30
+ ((!isRtl && (!marginLeft || marginLeft == '0px')) ||
31
+ (isRtl && (!marginRight || marginRight == '0px')))) {
32
+ return false;
33
+ }
27
34
  (0, roosterjs_content_model_api_1.setModelIndentation)(model, rawEvent.shiftKey ? 'outdent' : 'indent');
28
35
  }
29
36
  else {
@@ -1 +1 @@
1
- {"version":3,"file":"handleTabOnParagraph.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-plugins/lib/edit/tabUtils/handleTabOnParagraph.ts"],"names":[],"mappings":"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","sourcesContent":["import { createSelectionMarker, createText } from 'roosterjs-content-model-dom';\nimport { setModelIndentation } from 'roosterjs-content-model-api';\nimport type { ContentModelDocument, ContentModelParagraph } from 'roosterjs-content-model-types';\n\nconst tabSpaces = '    ';\nconst space = ' ';\n\n/**\n * @internal\n The handleTabOnParagraph function will handle the tab key in following scenarios:\n * 1. When the selection is collapsed and the cursor is at the end of a paragraph, add 4 spaces.\n * 2. When the selection is collapsed and the cursor is at the start of a paragraph, call setModelIndention function to indent the whole paragraph\n * 3. When the selection is collapsed and the cursor is at the middle of a paragraph, add 4 spaces.\n * 4. When the selection is not collapsed, replace the selected range with a single space.\n * 5. When the selection is not collapsed, but all segments are selected, call setModelIndention function to indent the whole paragraph\n The handleTabOnParagraph function will handle the shift + tab key in a indented paragraph in following scenarios:\n * 1. When the selection is collapsed and the cursor is at the end of a paragraph, remove 4 spaces.\n * 2. When the selection is collapsed and the cursor is at the start of a paragraph, call setModelIndention function to outdent the whole paragraph\n * 3. When the selection is collapsed and the cursor is at the middle of a paragraph, remove 4 spaces.\n * 4. When the selection is not collapsed, replace the selected range with a 4 space.\n * 5. When the selection is not collapsed, but all segments are selected, call setModelIndention function to outdent the whole paragraph\n */\nexport function handleTabOnParagraph(\n model: ContentModelDocument,\n paragraph: ContentModelParagraph,\n rawEvent: KeyboardEvent\n) {\n const selectedSegments = paragraph.segments.filter(segment => segment.isSelected);\n const isCollapsed =\n selectedSegments.length === 1 && selectedSegments[0].segmentType === 'SelectionMarker';\n const isAllSelected = paragraph.segments.every(segment => segment.isSelected);\n if ((paragraph.segments[0].segmentType === 'SelectionMarker' && isCollapsed) || isAllSelected) {\n setModelIndentation(model, rawEvent.shiftKey ? 'outdent' : 'indent');\n } else {\n if (!isCollapsed) {\n let firstSelectedSegmentIndex: number | undefined = undefined;\n let lastSelectedSegmentIndex: number | undefined = undefined;\n\n paragraph.segments.forEach((segment, index) => {\n if (segment.isSelected) {\n if (!firstSelectedSegmentIndex) {\n firstSelectedSegmentIndex = index;\n }\n lastSelectedSegmentIndex = index;\n }\n });\n if (firstSelectedSegmentIndex && lastSelectedSegmentIndex) {\n const firstSelectedSegment = paragraph.segments[firstSelectedSegmentIndex];\n const spaceText = createText(\n rawEvent.shiftKey ? tabSpaces : space,\n firstSelectedSegment.format\n );\n const marker = createSelectionMarker(firstSelectedSegment.format);\n paragraph.segments.splice(\n firstSelectedSegmentIndex,\n lastSelectedSegmentIndex - firstSelectedSegmentIndex + 1,\n spaceText,\n marker\n );\n } else {\n return false;\n }\n } else {\n const markerIndex = paragraph.segments.findIndex(\n segment => segment.segmentType === 'SelectionMarker'\n );\n if (!rawEvent.shiftKey) {\n const markerFormat = paragraph.segments[markerIndex].format;\n const tabText = createText(tabSpaces, markerFormat);\n paragraph.segments.splice(markerIndex, 0, tabText);\n } else {\n const tabText = paragraph.segments[markerIndex - 1];\n const tabSpacesLength = tabSpaces.length;\n if (tabText.segmentType == 'Text') {\n const tabSpaceTextLength = tabText.text.length - tabSpacesLength;\n if (tabText.text === tabSpaces) {\n paragraph.segments.splice(markerIndex - 1, 1);\n } else if (tabText.text.substring(tabSpaceTextLength) === tabSpaces) {\n tabText.text = tabText.text.substring(0, tabSpaceTextLength);\n } else {\n return false;\n }\n }\n }\n }\n }\n\n rawEvent.preventDefault();\n return true;\n}\n"]}
1
+ {"version":3,"file":"handleTabOnParagraph.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-plugins/lib/edit/tabUtils/handleTabOnParagraph.ts"],"names":[],"mappings":"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","sourcesContent":["import { createSelectionMarker, createText } from 'roosterjs-content-model-dom';\nimport { setModelIndentation } from 'roosterjs-content-model-api';\nimport type { ContentModelDocument, ContentModelParagraph } from 'roosterjs-content-model-types';\n\nconst tabSpaces = '    ';\nconst space = ' ';\n\n/**\n * @internal\n The handleTabOnParagraph function will handle the tab key in following scenarios:\n * 1. When the selection is collapsed and the cursor is at the end of a paragraph, add 4 spaces.\n * 2. When the selection is collapsed and the cursor is at the start of a paragraph, call setModelIndention function to indent the whole paragraph\n * 3. When the selection is collapsed and the cursor is at the middle of a paragraph, add 4 spaces.\n * 4. When the selection is not collapsed, replace the selected range with a single space.\n * 5. When the selection is not collapsed, but all segments are selected, call setModelIndention function to indent the whole paragraph\n The handleTabOnParagraph function will handle the shift + tab key in a indented paragraph in following scenarios:\n * 1. When the selection is collapsed and the cursor is at the end of a paragraph, remove 4 spaces.\n * 2. When the selection is collapsed and the cursor is at the start of a paragraph, call setModelIndention function to outdent the whole paragraph\n * 3. When the selection is collapsed and the cursor is at the middle of a paragraph, remove 4 spaces.\n * 4. When the selection is not collapsed, replace the selected range with a 4 space.\n * 5. When the selection is not collapsed, but all segments are selected, call setModelIndention function to outdent the whole paragraph\n */\nexport function handleTabOnParagraph(\n model: ContentModelDocument,\n paragraph: ContentModelParagraph,\n rawEvent: KeyboardEvent\n) {\n const selectedSegments = paragraph.segments.filter(segment => segment.isSelected);\n const isCollapsed =\n selectedSegments.length === 1 && selectedSegments[0].segmentType === 'SelectionMarker';\n const isAllSelected = paragraph.segments.every(segment => segment.isSelected);\n if ((paragraph.segments[0].segmentType === 'SelectionMarker' && isCollapsed) || isAllSelected) {\n const { marginLeft, marginRight, direction } = paragraph.format;\n const isRtl = direction === 'rtl';\n if (\n rawEvent.shiftKey &&\n ((!isRtl && (!marginLeft || marginLeft == '0px')) ||\n (isRtl && (!marginRight || marginRight == '0px')))\n ) {\n return false;\n }\n setModelIndentation(model, rawEvent.shiftKey ? 'outdent' : 'indent');\n } else {\n if (!isCollapsed) {\n let firstSelectedSegmentIndex: number | undefined = undefined;\n let lastSelectedSegmentIndex: number | undefined = undefined;\n\n paragraph.segments.forEach((segment, index) => {\n if (segment.isSelected) {\n if (!firstSelectedSegmentIndex) {\n firstSelectedSegmentIndex = index;\n }\n lastSelectedSegmentIndex = index;\n }\n });\n if (firstSelectedSegmentIndex && lastSelectedSegmentIndex) {\n const firstSelectedSegment = paragraph.segments[firstSelectedSegmentIndex];\n const spaceText = createText(\n rawEvent.shiftKey ? tabSpaces : space,\n firstSelectedSegment.format\n );\n const marker = createSelectionMarker(firstSelectedSegment.format);\n paragraph.segments.splice(\n firstSelectedSegmentIndex,\n lastSelectedSegmentIndex - firstSelectedSegmentIndex + 1,\n spaceText,\n marker\n );\n } else {\n return false;\n }\n } else {\n const markerIndex = paragraph.segments.findIndex(\n segment => segment.segmentType === 'SelectionMarker'\n );\n if (!rawEvent.shiftKey) {\n const markerFormat = paragraph.segments[markerIndex].format;\n const tabText = createText(tabSpaces, markerFormat);\n paragraph.segments.splice(markerIndex, 0, tabText);\n } else {\n const tabText = paragraph.segments[markerIndex - 1];\n const tabSpacesLength = tabSpaces.length;\n if (tabText.segmentType == 'Text') {\n const tabSpaceTextLength = tabText.text.length - tabSpacesLength;\n if (tabText.text === tabSpaces) {\n paragraph.segments.splice(markerIndex - 1, 1);\n } else if (tabText.text.substring(tabSpaceTextLength) === tabSpaces) {\n tabText.text = tabText.text.substring(0, tabSpaceTextLength);\n } else {\n return false;\n }\n }\n }\n }\n }\n rawEvent.preventDefault();\n return true;\n}\n"]}
@@ -1,10 +1,15 @@
1
- import type { BeforePasteEvent, TrustedHTMLHandler } from 'roosterjs-content-model-types';
1
+ import type { BeforePasteEvent, ElementProcessor, TrustedHTMLHandler } from 'roosterjs-content-model-types';
2
2
  /**
3
3
  * @internal
4
4
  * Convert pasted content from Excel, add borders when source doc doesn't have a border
5
5
  * @param event The BeforePaste event
6
6
  */
7
7
  export declare function processPastedContentFromExcel(event: BeforePasteEvent, trustedHTMLHandler: TrustedHTMLHandler, allowExcelNoBorderTable?: boolean): void;
8
+ /**
9
+ * @internal
10
+ * Exported only for unit test
11
+ */
12
+ export declare const childProcessor: ElementProcessor<ParentNode>;
8
13
  /**
9
14
  * @internal Export for test only
10
15
  * @param html Source html
@@ -1,7 +1,7 @@
1
1
  define(["require", "exports", "tslib", "../utils/addParser", "roosterjs-content-model-dom", "../utils/setProcessor"], function (require, exports, tslib_1, addParser_1, roosterjs_content_model_dom_1, setProcessor_1) {
2
2
  "use strict";
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.excelHandler = exports.processPastedContentFromExcel = void 0;
4
+ exports.excelHandler = exports.childProcessor = exports.processPastedContentFromExcel = void 0;
5
5
  var LAST_TD_END_REGEX = /<\/\s*td\s*>((?!<\/\s*tr\s*>)[\s\S])*$/i;
6
6
  var LAST_TR_END_REGEX = /<\/\s*tr\s*>((?!<\/\s*table\s*>)[\s\S])*$/i;
7
7
  var LAST_TR_REGEX = /<tr[^>]*>[^<]*/i;
@@ -46,19 +46,27 @@ define(["require", "exports", "tslib", "../utils/addParser", "roosterjs-content-
46
46
  format.borderTop = DEFAULT_BORDER_STYLE;
47
47
  }
48
48
  });
49
- (0, setProcessor_1.setProcessor)(event.domToModelOption, 'child', function (group, element, context) {
50
- var segmentFormat = (0, tslib_1.__assign)({}, context.segmentFormat);
51
- if (group.blockGroupType === 'TableCell' && group.format.textColor) {
52
- context.segmentFormat.textColor = group.format.textColor;
53
- }
54
- context.defaultElementProcessors.child(group, element, context);
55
- if (group.blockGroupType === 'TableCell' && group.format.textColor) {
56
- context.segmentFormat = segmentFormat;
57
- delete group.format.textColor;
58
- }
59
- });
49
+ (0, setProcessor_1.setProcessor)(event.domToModelOption, 'child', exports.childProcessor);
60
50
  }
61
51
  exports.processPastedContentFromExcel = processPastedContentFromExcel;
52
+ /**
53
+ * @internal
54
+ * Exported only for unit test
55
+ */
56
+ var childProcessor = function (group, element, context) {
57
+ var segmentFormat = (0, tslib_1.__assign)({}, context.segmentFormat);
58
+ if (group.blockGroupType === 'TableCell' &&
59
+ group.format.textColor &&
60
+ !context.segmentFormat.textColor) {
61
+ context.segmentFormat.textColor = group.format.textColor;
62
+ }
63
+ context.defaultElementProcessors.child(group, element, context);
64
+ if (group.blockGroupType === 'TableCell' && group.format.textColor) {
65
+ context.segmentFormat = segmentFormat;
66
+ delete group.format.textColor;
67
+ }
68
+ };
69
+ exports.childProcessor = childProcessor;
62
70
  /**
63
71
  * @internal Export for test only
64
72
  * @param html Source html
@@ -1 +1 @@
1
- {"version":3,"file":"processPastedContentFromExcel.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-plugins/lib/paste/Excel/processPastedContentFromExcel.ts"],"names":[],"mappings":"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","sourcesContent":["import { addParser } from '../utils/addParser';\nimport { isNodeOfType, moveChildNodes } from 'roosterjs-content-model-dom';\nimport { setProcessor } from '../utils/setProcessor';\nimport type { BeforePasteEvent, TrustedHTMLHandler } from 'roosterjs-content-model-types';\n\nconst LAST_TD_END_REGEX = /<\\/\\s*td\\s*>((?!<\\/\\s*tr\\s*>)[\\s\\S])*$/i;\nconst LAST_TR_END_REGEX = /<\\/\\s*tr\\s*>((?!<\\/\\s*table\\s*>)[\\s\\S])*$/i;\nconst LAST_TR_REGEX = /<tr[^>]*>[^<]*/i;\nconst LAST_TABLE_REGEX = /<table[^>]*>[^<]*/i;\nconst DEFAULT_BORDER_STYLE = 'solid 1px #d4d4d4';\n\n/**\n * @internal\n * Convert pasted content from Excel, add borders when source doc doesn't have a border\n * @param event The BeforePaste event\n */\n\nexport function processPastedContentFromExcel(\n event: BeforePasteEvent,\n trustedHTMLHandler: TrustedHTMLHandler,\n allowExcelNoBorderTable?: boolean\n) {\n const { fragment, htmlBefore, clipboardData } = event;\n const html = clipboardData.html ? excelHandler(clipboardData.html, htmlBefore) : undefined;\n\n if (html && clipboardData.html != html) {\n const doc = new DOMParser().parseFromString(trustedHTMLHandler(html), 'text/html');\n moveChildNodes(fragment, doc?.body);\n }\n\n // For Excel Online\n const firstChild = fragment.firstChild;\n if (\n isNodeOfType(firstChild, 'ELEMENT_NODE') &&\n firstChild.tagName == 'div' &&\n firstChild.firstChild\n ) {\n const tableFound = Array.from(firstChild.childNodes).every((child: Node) => {\n // Tables pasted from Excel Online should be of the format: 0 to N META tags and 1 TABLE tag\n const tagName = isNodeOfType(child, 'ELEMENT_NODE') && child.tagName;\n\n return tagName == 'META'\n ? true\n : tagName == 'TABLE'\n ? child == firstChild.lastChild\n : false;\n });\n\n // Extract Table from Div\n if (tableFound && firstChild.lastChild) {\n event.fragment.replaceChildren(firstChild.lastChild);\n }\n }\n\n addParser(event.domToModelOption, 'tableCell', (format, element) => {\n if (!allowExcelNoBorderTable && element.style.borderStyle === 'none') {\n format.borderBottom = DEFAULT_BORDER_STYLE;\n format.borderLeft = DEFAULT_BORDER_STYLE;\n format.borderRight = DEFAULT_BORDER_STYLE;\n format.borderTop = DEFAULT_BORDER_STYLE;\n }\n });\n\n setProcessor(event.domToModelOption, 'child', (group, element, context) => {\n const segmentFormat = { ...context.segmentFormat };\n if (group.blockGroupType === 'TableCell' && group.format.textColor) {\n context.segmentFormat.textColor = group.format.textColor;\n }\n\n context.defaultElementProcessors.child(group, element, context);\n\n if (group.blockGroupType === 'TableCell' && group.format.textColor) {\n context.segmentFormat = segmentFormat;\n delete group.format.textColor;\n }\n });\n}\n\n/**\n * @internal Export for test only\n * @param html Source html\n */\n\nexport function excelHandler(html: string, htmlBefore: string): string {\n if (html.match(LAST_TD_END_REGEX)) {\n const trMatch = htmlBefore.match(LAST_TR_REGEX);\n const tr = trMatch ? trMatch[0] : '<TR>';\n html = tr + html + '</TR>';\n }\n if (html.match(LAST_TR_END_REGEX)) {\n const tableMatch = htmlBefore.match(LAST_TABLE_REGEX);\n const table = tableMatch ? tableMatch[0] : '<TABLE>';\n html = table + html + '</TABLE>';\n }\n\n return html;\n}\n"]}
1
+ {"version":3,"file":"processPastedContentFromExcel.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-plugins/lib/paste/Excel/processPastedContentFromExcel.ts"],"names":[],"mappings":"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","sourcesContent":["import { addParser } from '../utils/addParser';\nimport { isNodeOfType, moveChildNodes } from 'roosterjs-content-model-dom';\nimport { setProcessor } from '../utils/setProcessor';\nimport type {\n BeforePasteEvent,\n ElementProcessor,\n TrustedHTMLHandler,\n} from 'roosterjs-content-model-types';\n\nconst LAST_TD_END_REGEX = /<\\/\\s*td\\s*>((?!<\\/\\s*tr\\s*>)[\\s\\S])*$/i;\nconst LAST_TR_END_REGEX = /<\\/\\s*tr\\s*>((?!<\\/\\s*table\\s*>)[\\s\\S])*$/i;\nconst LAST_TR_REGEX = /<tr[^>]*>[^<]*/i;\nconst LAST_TABLE_REGEX = /<table[^>]*>[^<]*/i;\nconst DEFAULT_BORDER_STYLE = 'solid 1px #d4d4d4';\n\n/**\n * @internal\n * Convert pasted content from Excel, add borders when source doc doesn't have a border\n * @param event The BeforePaste event\n */\n\nexport function processPastedContentFromExcel(\n event: BeforePasteEvent,\n trustedHTMLHandler: TrustedHTMLHandler,\n allowExcelNoBorderTable?: boolean\n) {\n const { fragment, htmlBefore, clipboardData } = event;\n const html = clipboardData.html ? excelHandler(clipboardData.html, htmlBefore) : undefined;\n\n if (html && clipboardData.html != html) {\n const doc = new DOMParser().parseFromString(trustedHTMLHandler(html), 'text/html');\n moveChildNodes(fragment, doc?.body);\n }\n\n // For Excel Online\n const firstChild = fragment.firstChild;\n if (\n isNodeOfType(firstChild, 'ELEMENT_NODE') &&\n firstChild.tagName == 'div' &&\n firstChild.firstChild\n ) {\n const tableFound = Array.from(firstChild.childNodes).every((child: Node) => {\n // Tables pasted from Excel Online should be of the format: 0 to N META tags and 1 TABLE tag\n const tagName = isNodeOfType(child, 'ELEMENT_NODE') && child.tagName;\n\n return tagName == 'META'\n ? true\n : tagName == 'TABLE'\n ? child == firstChild.lastChild\n : false;\n });\n\n // Extract Table from Div\n if (tableFound && firstChild.lastChild) {\n event.fragment.replaceChildren(firstChild.lastChild);\n }\n }\n\n addParser(event.domToModelOption, 'tableCell', (format, element) => {\n if (!allowExcelNoBorderTable && element.style.borderStyle === 'none') {\n format.borderBottom = DEFAULT_BORDER_STYLE;\n format.borderLeft = DEFAULT_BORDER_STYLE;\n format.borderRight = DEFAULT_BORDER_STYLE;\n format.borderTop = DEFAULT_BORDER_STYLE;\n }\n });\n\n setProcessor(event.domToModelOption, 'child', childProcessor);\n}\n\n/**\n * @internal\n * Exported only for unit test\n */\nexport const childProcessor: ElementProcessor<ParentNode> = (group, element, context) => {\n const segmentFormat = { ...context.segmentFormat };\n if (\n group.blockGroupType === 'TableCell' &&\n group.format.textColor &&\n !context.segmentFormat.textColor\n ) {\n context.segmentFormat.textColor = group.format.textColor;\n }\n\n context.defaultElementProcessors.child(group, element, context);\n\n if (group.blockGroupType === 'TableCell' && group.format.textColor) {\n context.segmentFormat = segmentFormat;\n delete group.format.textColor;\n }\n};\n\n/**\n * @internal Export for test only\n * @param html Source html\n */\n\nexport function excelHandler(html: string, htmlBefore: string): string {\n if (html.match(LAST_TD_END_REGEX)) {\n const trMatch = htmlBefore.match(LAST_TR_REGEX);\n const tr = trMatch ? trMatch[0] : '<TR>';\n html = tr + html + '</TR>';\n }\n if (html.match(LAST_TR_END_REGEX)) {\n const tableMatch = htmlBefore.match(LAST_TABLE_REGEX);\n const table = tableMatch ? tableMatch[0] : '<TABLE>';\n html = table + html + '</TABLE>';\n }\n\n return html;\n}\n"]}
@@ -22,6 +22,13 @@ export function handleTabOnParagraph(model, paragraph, rawEvent) {
22
22
  var isCollapsed = selectedSegments.length === 1 && selectedSegments[0].segmentType === 'SelectionMarker';
23
23
  var isAllSelected = paragraph.segments.every(function (segment) { return segment.isSelected; });
24
24
  if ((paragraph.segments[0].segmentType === 'SelectionMarker' && isCollapsed) || isAllSelected) {
25
+ var _a = paragraph.format, marginLeft = _a.marginLeft, marginRight = _a.marginRight, direction = _a.direction;
26
+ var isRtl = direction === 'rtl';
27
+ if (rawEvent.shiftKey &&
28
+ ((!isRtl && (!marginLeft || marginLeft == '0px')) ||
29
+ (isRtl && (!marginRight || marginRight == '0px')))) {
30
+ return false;
31
+ }
25
32
  setModelIndentation(model, rawEvent.shiftKey ? 'outdent' : 'indent');
26
33
  }
27
34
  else {
@@ -1 +1 @@
1
- {"version":3,"file":"handleTabOnParagraph.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-plugins/lib/edit/tabUtils/handleTabOnParagraph.ts"],"names":[],"mappings":"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","sourcesContent":["import { createSelectionMarker, createText } from 'roosterjs-content-model-dom';\nimport { setModelIndentation } from 'roosterjs-content-model-api';\nimport type { ContentModelDocument, ContentModelParagraph } from 'roosterjs-content-model-types';\n\nconst tabSpaces = '    ';\nconst space = ' ';\n\n/**\n * @internal\n The handleTabOnParagraph function will handle the tab key in following scenarios:\n * 1. When the selection is collapsed and the cursor is at the end of a paragraph, add 4 spaces.\n * 2. When the selection is collapsed and the cursor is at the start of a paragraph, call setModelIndention function to indent the whole paragraph\n * 3. When the selection is collapsed and the cursor is at the middle of a paragraph, add 4 spaces.\n * 4. When the selection is not collapsed, replace the selected range with a single space.\n * 5. When the selection is not collapsed, but all segments are selected, call setModelIndention function to indent the whole paragraph\n The handleTabOnParagraph function will handle the shift + tab key in a indented paragraph in following scenarios:\n * 1. When the selection is collapsed and the cursor is at the end of a paragraph, remove 4 spaces.\n * 2. When the selection is collapsed and the cursor is at the start of a paragraph, call setModelIndention function to outdent the whole paragraph\n * 3. When the selection is collapsed and the cursor is at the middle of a paragraph, remove 4 spaces.\n * 4. When the selection is not collapsed, replace the selected range with a 4 space.\n * 5. When the selection is not collapsed, but all segments are selected, call setModelIndention function to outdent the whole paragraph\n */\nexport function handleTabOnParagraph(\n model: ContentModelDocument,\n paragraph: ContentModelParagraph,\n rawEvent: KeyboardEvent\n) {\n const selectedSegments = paragraph.segments.filter(segment => segment.isSelected);\n const isCollapsed =\n selectedSegments.length === 1 && selectedSegments[0].segmentType === 'SelectionMarker';\n const isAllSelected = paragraph.segments.every(segment => segment.isSelected);\n if ((paragraph.segments[0].segmentType === 'SelectionMarker' && isCollapsed) || isAllSelected) {\n setModelIndentation(model, rawEvent.shiftKey ? 'outdent' : 'indent');\n } else {\n if (!isCollapsed) {\n let firstSelectedSegmentIndex: number | undefined = undefined;\n let lastSelectedSegmentIndex: number | undefined = undefined;\n\n paragraph.segments.forEach((segment, index) => {\n if (segment.isSelected) {\n if (!firstSelectedSegmentIndex) {\n firstSelectedSegmentIndex = index;\n }\n lastSelectedSegmentIndex = index;\n }\n });\n if (firstSelectedSegmentIndex && lastSelectedSegmentIndex) {\n const firstSelectedSegment = paragraph.segments[firstSelectedSegmentIndex];\n const spaceText = createText(\n rawEvent.shiftKey ? tabSpaces : space,\n firstSelectedSegment.format\n );\n const marker = createSelectionMarker(firstSelectedSegment.format);\n paragraph.segments.splice(\n firstSelectedSegmentIndex,\n lastSelectedSegmentIndex - firstSelectedSegmentIndex + 1,\n spaceText,\n marker\n );\n } else {\n return false;\n }\n } else {\n const markerIndex = paragraph.segments.findIndex(\n segment => segment.segmentType === 'SelectionMarker'\n );\n if (!rawEvent.shiftKey) {\n const markerFormat = paragraph.segments[markerIndex].format;\n const tabText = createText(tabSpaces, markerFormat);\n paragraph.segments.splice(markerIndex, 0, tabText);\n } else {\n const tabText = paragraph.segments[markerIndex - 1];\n const tabSpacesLength = tabSpaces.length;\n if (tabText.segmentType == 'Text') {\n const tabSpaceTextLength = tabText.text.length - tabSpacesLength;\n if (tabText.text === tabSpaces) {\n paragraph.segments.splice(markerIndex - 1, 1);\n } else if (tabText.text.substring(tabSpaceTextLength) === tabSpaces) {\n tabText.text = tabText.text.substring(0, tabSpaceTextLength);\n } else {\n return false;\n }\n }\n }\n }\n }\n\n rawEvent.preventDefault();\n return true;\n}\n"]}
1
+ {"version":3,"file":"handleTabOnParagraph.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-plugins/lib/edit/tabUtils/handleTabOnParagraph.ts"],"names":[],"mappings":"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","sourcesContent":["import { createSelectionMarker, createText } from 'roosterjs-content-model-dom';\nimport { setModelIndentation } from 'roosterjs-content-model-api';\nimport type { ContentModelDocument, ContentModelParagraph } from 'roosterjs-content-model-types';\n\nconst tabSpaces = '    ';\nconst space = ' ';\n\n/**\n * @internal\n The handleTabOnParagraph function will handle the tab key in following scenarios:\n * 1. When the selection is collapsed and the cursor is at the end of a paragraph, add 4 spaces.\n * 2. When the selection is collapsed and the cursor is at the start of a paragraph, call setModelIndention function to indent the whole paragraph\n * 3. When the selection is collapsed and the cursor is at the middle of a paragraph, add 4 spaces.\n * 4. When the selection is not collapsed, replace the selected range with a single space.\n * 5. When the selection is not collapsed, but all segments are selected, call setModelIndention function to indent the whole paragraph\n The handleTabOnParagraph function will handle the shift + tab key in a indented paragraph in following scenarios:\n * 1. When the selection is collapsed and the cursor is at the end of a paragraph, remove 4 spaces.\n * 2. When the selection is collapsed and the cursor is at the start of a paragraph, call setModelIndention function to outdent the whole paragraph\n * 3. When the selection is collapsed and the cursor is at the middle of a paragraph, remove 4 spaces.\n * 4. When the selection is not collapsed, replace the selected range with a 4 space.\n * 5. When the selection is not collapsed, but all segments are selected, call setModelIndention function to outdent the whole paragraph\n */\nexport function handleTabOnParagraph(\n model: ContentModelDocument,\n paragraph: ContentModelParagraph,\n rawEvent: KeyboardEvent\n) {\n const selectedSegments = paragraph.segments.filter(segment => segment.isSelected);\n const isCollapsed =\n selectedSegments.length === 1 && selectedSegments[0].segmentType === 'SelectionMarker';\n const isAllSelected = paragraph.segments.every(segment => segment.isSelected);\n if ((paragraph.segments[0].segmentType === 'SelectionMarker' && isCollapsed) || isAllSelected) {\n const { marginLeft, marginRight, direction } = paragraph.format;\n const isRtl = direction === 'rtl';\n if (\n rawEvent.shiftKey &&\n ((!isRtl && (!marginLeft || marginLeft == '0px')) ||\n (isRtl && (!marginRight || marginRight == '0px')))\n ) {\n return false;\n }\n setModelIndentation(model, rawEvent.shiftKey ? 'outdent' : 'indent');\n } else {\n if (!isCollapsed) {\n let firstSelectedSegmentIndex: number | undefined = undefined;\n let lastSelectedSegmentIndex: number | undefined = undefined;\n\n paragraph.segments.forEach((segment, index) => {\n if (segment.isSelected) {\n if (!firstSelectedSegmentIndex) {\n firstSelectedSegmentIndex = index;\n }\n lastSelectedSegmentIndex = index;\n }\n });\n if (firstSelectedSegmentIndex && lastSelectedSegmentIndex) {\n const firstSelectedSegment = paragraph.segments[firstSelectedSegmentIndex];\n const spaceText = createText(\n rawEvent.shiftKey ? tabSpaces : space,\n firstSelectedSegment.format\n );\n const marker = createSelectionMarker(firstSelectedSegment.format);\n paragraph.segments.splice(\n firstSelectedSegmentIndex,\n lastSelectedSegmentIndex - firstSelectedSegmentIndex + 1,\n spaceText,\n marker\n );\n } else {\n return false;\n }\n } else {\n const markerIndex = paragraph.segments.findIndex(\n segment => segment.segmentType === 'SelectionMarker'\n );\n if (!rawEvent.shiftKey) {\n const markerFormat = paragraph.segments[markerIndex].format;\n const tabText = createText(tabSpaces, markerFormat);\n paragraph.segments.splice(markerIndex, 0, tabText);\n } else {\n const tabText = paragraph.segments[markerIndex - 1];\n const tabSpacesLength = tabSpaces.length;\n if (tabText.segmentType == 'Text') {\n const tabSpaceTextLength = tabText.text.length - tabSpacesLength;\n if (tabText.text === tabSpaces) {\n paragraph.segments.splice(markerIndex - 1, 1);\n } else if (tabText.text.substring(tabSpaceTextLength) === tabSpaces) {\n tabText.text = tabText.text.substring(0, tabSpaceTextLength);\n } else {\n return false;\n }\n }\n }\n }\n }\n rawEvent.preventDefault();\n return true;\n}\n"]}
@@ -1,10 +1,15 @@
1
- import type { BeforePasteEvent, TrustedHTMLHandler } from 'roosterjs-content-model-types';
1
+ import type { BeforePasteEvent, ElementProcessor, TrustedHTMLHandler } from 'roosterjs-content-model-types';
2
2
  /**
3
3
  * @internal
4
4
  * Convert pasted content from Excel, add borders when source doc doesn't have a border
5
5
  * @param event The BeforePaste event
6
6
  */
7
7
  export declare function processPastedContentFromExcel(event: BeforePasteEvent, trustedHTMLHandler: TrustedHTMLHandler, allowExcelNoBorderTable?: boolean): void;
8
+ /**
9
+ * @internal
10
+ * Exported only for unit test
11
+ */
12
+ export declare const childProcessor: ElementProcessor<ParentNode>;
8
13
  /**
9
14
  * @internal Export for test only
10
15
  * @param html Source html
@@ -46,18 +46,25 @@ export function processPastedContentFromExcel(event, trustedHTMLHandler, allowEx
46
46
  format.borderTop = DEFAULT_BORDER_STYLE;
47
47
  }
48
48
  });
49
- setProcessor(event.domToModelOption, 'child', function (group, element, context) {
50
- var segmentFormat = __assign({}, context.segmentFormat);
51
- if (group.blockGroupType === 'TableCell' && group.format.textColor) {
52
- context.segmentFormat.textColor = group.format.textColor;
53
- }
54
- context.defaultElementProcessors.child(group, element, context);
55
- if (group.blockGroupType === 'TableCell' && group.format.textColor) {
56
- context.segmentFormat = segmentFormat;
57
- delete group.format.textColor;
58
- }
59
- });
49
+ setProcessor(event.domToModelOption, 'child', childProcessor);
60
50
  }
51
+ /**
52
+ * @internal
53
+ * Exported only for unit test
54
+ */
55
+ export var childProcessor = function (group, element, context) {
56
+ var segmentFormat = __assign({}, context.segmentFormat);
57
+ if (group.blockGroupType === 'TableCell' &&
58
+ group.format.textColor &&
59
+ !context.segmentFormat.textColor) {
60
+ context.segmentFormat.textColor = group.format.textColor;
61
+ }
62
+ context.defaultElementProcessors.child(group, element, context);
63
+ if (group.blockGroupType === 'TableCell' && group.format.textColor) {
64
+ context.segmentFormat = segmentFormat;
65
+ delete group.format.textColor;
66
+ }
67
+ };
61
68
  /**
62
69
  * @internal Export for test only
63
70
  * @param html Source html
@@ -1 +1 @@
1
- {"version":3,"file":"processPastedContentFromExcel.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-plugins/lib/paste/Excel/processPastedContentFromExcel.ts"],"names":[],"mappings":"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","sourcesContent":["import { addParser } from '../utils/addParser';\nimport { isNodeOfType, moveChildNodes } from 'roosterjs-content-model-dom';\nimport { setProcessor } from '../utils/setProcessor';\nimport type { BeforePasteEvent, TrustedHTMLHandler } from 'roosterjs-content-model-types';\n\nconst LAST_TD_END_REGEX = /<\\/\\s*td\\s*>((?!<\\/\\s*tr\\s*>)[\\s\\S])*$/i;\nconst LAST_TR_END_REGEX = /<\\/\\s*tr\\s*>((?!<\\/\\s*table\\s*>)[\\s\\S])*$/i;\nconst LAST_TR_REGEX = /<tr[^>]*>[^<]*/i;\nconst LAST_TABLE_REGEX = /<table[^>]*>[^<]*/i;\nconst DEFAULT_BORDER_STYLE = 'solid 1px #d4d4d4';\n\n/**\n * @internal\n * Convert pasted content from Excel, add borders when source doc doesn't have a border\n * @param event The BeforePaste event\n */\n\nexport function processPastedContentFromExcel(\n event: BeforePasteEvent,\n trustedHTMLHandler: TrustedHTMLHandler,\n allowExcelNoBorderTable?: boolean\n) {\n const { fragment, htmlBefore, clipboardData } = event;\n const html = clipboardData.html ? excelHandler(clipboardData.html, htmlBefore) : undefined;\n\n if (html && clipboardData.html != html) {\n const doc = new DOMParser().parseFromString(trustedHTMLHandler(html), 'text/html');\n moveChildNodes(fragment, doc?.body);\n }\n\n // For Excel Online\n const firstChild = fragment.firstChild;\n if (\n isNodeOfType(firstChild, 'ELEMENT_NODE') &&\n firstChild.tagName == 'div' &&\n firstChild.firstChild\n ) {\n const tableFound = Array.from(firstChild.childNodes).every((child: Node) => {\n // Tables pasted from Excel Online should be of the format: 0 to N META tags and 1 TABLE tag\n const tagName = isNodeOfType(child, 'ELEMENT_NODE') && child.tagName;\n\n return tagName == 'META'\n ? true\n : tagName == 'TABLE'\n ? child == firstChild.lastChild\n : false;\n });\n\n // Extract Table from Div\n if (tableFound && firstChild.lastChild) {\n event.fragment.replaceChildren(firstChild.lastChild);\n }\n }\n\n addParser(event.domToModelOption, 'tableCell', (format, element) => {\n if (!allowExcelNoBorderTable && element.style.borderStyle === 'none') {\n format.borderBottom = DEFAULT_BORDER_STYLE;\n format.borderLeft = DEFAULT_BORDER_STYLE;\n format.borderRight = DEFAULT_BORDER_STYLE;\n format.borderTop = DEFAULT_BORDER_STYLE;\n }\n });\n\n setProcessor(event.domToModelOption, 'child', (group, element, context) => {\n const segmentFormat = { ...context.segmentFormat };\n if (group.blockGroupType === 'TableCell' && group.format.textColor) {\n context.segmentFormat.textColor = group.format.textColor;\n }\n\n context.defaultElementProcessors.child(group, element, context);\n\n if (group.blockGroupType === 'TableCell' && group.format.textColor) {\n context.segmentFormat = segmentFormat;\n delete group.format.textColor;\n }\n });\n}\n\n/**\n * @internal Export for test only\n * @param html Source html\n */\n\nexport function excelHandler(html: string, htmlBefore: string): string {\n if (html.match(LAST_TD_END_REGEX)) {\n const trMatch = htmlBefore.match(LAST_TR_REGEX);\n const tr = trMatch ? trMatch[0] : '<TR>';\n html = tr + html + '</TR>';\n }\n if (html.match(LAST_TR_END_REGEX)) {\n const tableMatch = htmlBefore.match(LAST_TABLE_REGEX);\n const table = tableMatch ? tableMatch[0] : '<TABLE>';\n html = table + html + '</TABLE>';\n }\n\n return html;\n}\n"]}
1
+ {"version":3,"file":"processPastedContentFromExcel.js","sourceRoot":"","sources":["../../../../../packages/roosterjs-content-model-plugins/lib/paste/Excel/processPastedContentFromExcel.ts"],"names":[],"mappings":"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","sourcesContent":["import { addParser } from '../utils/addParser';\nimport { isNodeOfType, moveChildNodes } from 'roosterjs-content-model-dom';\nimport { setProcessor } from '../utils/setProcessor';\nimport type {\n BeforePasteEvent,\n ElementProcessor,\n TrustedHTMLHandler,\n} from 'roosterjs-content-model-types';\n\nconst LAST_TD_END_REGEX = /<\\/\\s*td\\s*>((?!<\\/\\s*tr\\s*>)[\\s\\S])*$/i;\nconst LAST_TR_END_REGEX = /<\\/\\s*tr\\s*>((?!<\\/\\s*table\\s*>)[\\s\\S])*$/i;\nconst LAST_TR_REGEX = /<tr[^>]*>[^<]*/i;\nconst LAST_TABLE_REGEX = /<table[^>]*>[^<]*/i;\nconst DEFAULT_BORDER_STYLE = 'solid 1px #d4d4d4';\n\n/**\n * @internal\n * Convert pasted content from Excel, add borders when source doc doesn't have a border\n * @param event The BeforePaste event\n */\n\nexport function processPastedContentFromExcel(\n event: BeforePasteEvent,\n trustedHTMLHandler: TrustedHTMLHandler,\n allowExcelNoBorderTable?: boolean\n) {\n const { fragment, htmlBefore, clipboardData } = event;\n const html = clipboardData.html ? excelHandler(clipboardData.html, htmlBefore) : undefined;\n\n if (html && clipboardData.html != html) {\n const doc = new DOMParser().parseFromString(trustedHTMLHandler(html), 'text/html');\n moveChildNodes(fragment, doc?.body);\n }\n\n // For Excel Online\n const firstChild = fragment.firstChild;\n if (\n isNodeOfType(firstChild, 'ELEMENT_NODE') &&\n firstChild.tagName == 'div' &&\n firstChild.firstChild\n ) {\n const tableFound = Array.from(firstChild.childNodes).every((child: Node) => {\n // Tables pasted from Excel Online should be of the format: 0 to N META tags and 1 TABLE tag\n const tagName = isNodeOfType(child, 'ELEMENT_NODE') && child.tagName;\n\n return tagName == 'META'\n ? true\n : tagName == 'TABLE'\n ? child == firstChild.lastChild\n : false;\n });\n\n // Extract Table from Div\n if (tableFound && firstChild.lastChild) {\n event.fragment.replaceChildren(firstChild.lastChild);\n }\n }\n\n addParser(event.domToModelOption, 'tableCell', (format, element) => {\n if (!allowExcelNoBorderTable && element.style.borderStyle === 'none') {\n format.borderBottom = DEFAULT_BORDER_STYLE;\n format.borderLeft = DEFAULT_BORDER_STYLE;\n format.borderRight = DEFAULT_BORDER_STYLE;\n format.borderTop = DEFAULT_BORDER_STYLE;\n }\n });\n\n setProcessor(event.domToModelOption, 'child', childProcessor);\n}\n\n/**\n * @internal\n * Exported only for unit test\n */\nexport const childProcessor: ElementProcessor<ParentNode> = (group, element, context) => {\n const segmentFormat = { ...context.segmentFormat };\n if (\n group.blockGroupType === 'TableCell' &&\n group.format.textColor &&\n !context.segmentFormat.textColor\n ) {\n context.segmentFormat.textColor = group.format.textColor;\n }\n\n context.defaultElementProcessors.child(group, element, context);\n\n if (group.blockGroupType === 'TableCell' && group.format.textColor) {\n context.segmentFormat = segmentFormat;\n delete group.format.textColor;\n }\n};\n\n/**\n * @internal Export for test only\n * @param html Source html\n */\n\nexport function excelHandler(html: string, htmlBefore: string): string {\n if (html.match(LAST_TD_END_REGEX)) {\n const trMatch = htmlBefore.match(LAST_TR_REGEX);\n const tr = trMatch ? trMatch[0] : '<TR>';\n html = tr + html + '</TR>';\n }\n if (html.match(LAST_TR_END_REGEX)) {\n const tableMatch = htmlBefore.match(LAST_TABLE_REGEX);\n const table = tableMatch ? tableMatch[0] : '<TABLE>';\n html = table + html + '</TABLE>';\n }\n\n return html;\n}\n"]}
package/package.json CHANGED
@@ -3,12 +3,12 @@
3
3
  "description": "Content Model for roosterjs (Under development)",
4
4
  "dependencies": {
5
5
  "tslib": "^2.3.1",
6
- "roosterjs-content-model-core": "^0.28.0",
6
+ "roosterjs-content-model-core": "^0.28.1",
7
7
  "roosterjs-content-model-dom": "^0.28.0",
8
8
  "roosterjs-content-model-types": "^0.28.0",
9
9
  "roosterjs-content-model-api": "^0.28.0"
10
10
  },
11
- "version": "0.28.0",
11
+ "version": "0.28.2",
12
12
  "main": "./lib/index.js",
13
13
  "typings": "./lib/index.d.ts",
14
14
  "module": "./lib-mjs/index.js",