From 91359866b503f9def5bcdbff84eaea240060e1df Mon Sep 17 00:00:00 2001 From: Francis Meng Date: Mon, 3 Jun 2019 14:51:54 -0700 Subject: [PATCH 1/5] Add getTextContent --- .../lib/editor/Editor.ts | 40 +++++++++++++++---- 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/packages/roosterjs-editor-core/lib/editor/Editor.ts b/packages/roosterjs-editor-core/lib/editor/Editor.ts index db768ab616f..5a899b76ac7 100644 --- a/packages/roosterjs-editor-core/lib/editor/Editor.ts +++ b/packages/roosterjs-editor-core/lib/editor/Editor.ts @@ -104,10 +104,10 @@ export default class Editor { if (Browser.isFirefox) { this.core.document.execCommand(DocumentCommand.EnableObjectResizing, false, < string - >(false)); + >(false)); this.core.document.execCommand(DocumentCommand.EnableInlineTableEditing, false, < string - >(false)); + >(false)); } else if (Browser.isIE) { // Change the default paragraph separater to DIV. This is mainly for IE since its default setting is P this.core.document.execCommand( @@ -116,7 +116,7 @@ export default class Editor { 'div' ); } - } catch (e) {} + } catch (e) { } // 9. Let plugins know that we are ready this.triggerEvent( @@ -385,7 +385,33 @@ export default class Editor { * @returns The text content inside editor */ public getTextContent(): string { - return this.core.contentDiv.innerText; + const traverser = this.getBodyTraverser(); + let block = traverser && traverser.currentBlockElement; + let blocks: BlockElement[] = []; + let textContent: string = ''; + + while (block) { + blocks.push(block); + block = traverser.getNextBlockElement(); + } + + blocks.forEach((block, index) => { + const blockTextContent = this.getBlockTextContent(block); + if (blockTextContent) { + textContent = `${textContent}${blockTextContent}`; + } + if (index != blocks.length - 1) { + textContent = `${textContent}\n` + } + }); + + return textContent; + } + + private getBlockTextContent(block: BlockElement) { + return block.getStartNode() == block.getEndNode() + ? block.getStartNode().textContent + : createRange(block.getStartNode(), block.getEndNode()).toString(); } /** @@ -406,7 +432,7 @@ export default class Editor { this.deleteNode(pathComment); let range = getRangeFromSelectionPath(contentDiv, path); this.select(range); - } catch {} + } catch { } } if (triggerContentChangedEvent) { @@ -621,8 +647,8 @@ export default class Editor { nameOrMap: | string | { - [eventName: string]: (event: UIEvent) => void; - }, + [eventName: string]: (event: UIEvent) => void; + }, handler?: (event: UIEvent) => void ): () => void { if (nameOrMap instanceof Object) { From d80e4fff5daa690f97f7bdb141e99133b13fcd80 Mon Sep 17 00:00:00 2001 From: Francis Meng Date: Mon, 3 Jun 2019 17:51:06 -0700 Subject: [PATCH 2/5] address comments for getTextContent --- .../lib/editor/Editor.ts | 29 +------------- .../lib/utils/getBlockElementTextContent.ts | 40 +++++++++++++++++++ 2 files changed, 42 insertions(+), 27 deletions(-) create mode 100644 packages/roosterjs-editor-dom/lib/utils/getBlockElementTextContent.ts diff --git a/packages/roosterjs-editor-core/lib/editor/Editor.ts b/packages/roosterjs-editor-core/lib/editor/Editor.ts index 5a899b76ac7..08d8745f1c2 100644 --- a/packages/roosterjs-editor-core/lib/editor/Editor.ts +++ b/packages/roosterjs-editor-core/lib/editor/Editor.ts @@ -29,6 +29,7 @@ import { findClosestElementAncestor, fromHtml, getBlockElementAtNode, + getBlockElementTextContent, getInlineElementAtNode, getPositionRect, getRangeFromSelectionPath, @@ -385,33 +386,7 @@ export default class Editor { * @returns The text content inside editor */ public getTextContent(): string { - const traverser = this.getBodyTraverser(); - let block = traverser && traverser.currentBlockElement; - let blocks: BlockElement[] = []; - let textContent: string = ''; - - while (block) { - blocks.push(block); - block = traverser.getNextBlockElement(); - } - - blocks.forEach((block, index) => { - const blockTextContent = this.getBlockTextContent(block); - if (blockTextContent) { - textContent = `${textContent}${blockTextContent}`; - } - if (index != blocks.length - 1) { - textContent = `${textContent}\n` - } - }); - - return textContent; - } - - private getBlockTextContent(block: BlockElement) { - return block.getStartNode() == block.getEndNode() - ? block.getStartNode().textContent - : createRange(block.getStartNode(), block.getEndNode()).toString(); + return getBlockElementTextContent(this.core.contentDiv); } /** diff --git a/packages/roosterjs-editor-dom/lib/utils/getBlockElementTextContent.ts b/packages/roosterjs-editor-dom/lib/utils/getBlockElementTextContent.ts new file mode 100644 index 00000000000..8d6973248dc --- /dev/null +++ b/packages/roosterjs-editor-dom/lib/utils/getBlockElementTextContent.ts @@ -0,0 +1,40 @@ +import { BlockElement } from 'roosterjs-editor-types'; +import ContentTraverser from '../contentTraverser/ContentTraverser'; +import createRange from '../selection/createRange'; + +/** + * get block element's text content. + * @param rootNode Root node that the get the textContent of. + * @param startNode Node the node start traverser to start traversing. + * @returns text content of given text content. + */ +export default function getBlockElementTextContent(rootNode: Node, startNode?: Node): string { + const traverser = ContentTraverser.createBodyTraverser(rootNode, startNode); + let block = traverser && traverser.currentBlockElement; + let blocks: BlockElement[] = []; + let textContent: string = ''; + + while (block) { + blocks.push(block); + block = traverser.getNextBlockElement(); + } + + blocks.forEach((block, index) => { + const blockTextContent = getBlockTextContent(block); + if (blockTextContent) { + textContent = `${textContent}${blockTextContent}`; + } + if (index != blocks.length - 1) { + textContent = `${textContent}\n` + } + }); + + return textContent; +} + +function getBlockTextContent(block: BlockElement) { + return block.getStartNode() == block.getEndNode() + ? block.getStartNode().textContent + : createRange(block.getStartNode(), block.getEndNode()).toString(); +} + From 6c7fb025b93e9c9dbae2f6902326b0d2fb68c5b2 Mon Sep 17 00:00:00 2001 From: Francis Meng Date: Tue, 4 Jun 2019 16:02:45 -0700 Subject: [PATCH 3/5] Address comment --- .../lib/editor/Editor.ts | 4 +- .../lib/blockElements/NodeBlockElement.ts | 9 ++++- .../lib/blockElements/StartEndBlockElement.ts | 10 ++++- packages/roosterjs-editor-dom/lib/index.ts | 1 + .../lib/utils/getBlockElementTextContent.ts | 40 ------------------- .../lib/utils/getTextContent.ts | 20 ++++++++++ .../lib/interface/BlockElement.ts | 5 +++ 7 files changed, 45 insertions(+), 44 deletions(-) delete mode 100644 packages/roosterjs-editor-dom/lib/utils/getBlockElementTextContent.ts create mode 100644 packages/roosterjs-editor-dom/lib/utils/getTextContent.ts diff --git a/packages/roosterjs-editor-core/lib/editor/Editor.ts b/packages/roosterjs-editor-core/lib/editor/Editor.ts index 08d8745f1c2..8775e5aa799 100644 --- a/packages/roosterjs-editor-core/lib/editor/Editor.ts +++ b/packages/roosterjs-editor-core/lib/editor/Editor.ts @@ -29,7 +29,7 @@ import { findClosestElementAncestor, fromHtml, getBlockElementAtNode, - getBlockElementTextContent, + getTextContent, getInlineElementAtNode, getPositionRect, getRangeFromSelectionPath, @@ -386,7 +386,7 @@ export default class Editor { * @returns The text content inside editor */ public getTextContent(): string { - return getBlockElementTextContent(this.core.contentDiv); + return getTextContent(this.core.contentDiv); } /** diff --git a/packages/roosterjs-editor-dom/lib/blockElements/NodeBlockElement.ts b/packages/roosterjs-editor-dom/lib/blockElements/NodeBlockElement.ts index 798b5931f16..4f574fec052 100644 --- a/packages/roosterjs-editor-dom/lib/blockElements/NodeBlockElement.ts +++ b/packages/roosterjs-editor-dom/lib/blockElements/NodeBlockElement.ts @@ -7,7 +7,7 @@ import { BlockElement } from 'roosterjs-editor-types'; * In most cases, it corresponds to an HTML block level element, i.e. P, DIV, LI, TD etc. */ export default class NodeBlockElement implements BlockElement { - constructor(private element: HTMLElement) {} + constructor(private element: HTMLElement) { } /** * Collapse this element to a single DOM element. @@ -56,4 +56,11 @@ export default class NodeBlockElement implements BlockElement { public contains(node: Node): boolean { return contains(this.element, node, true /*treatSameNodeAsContain*/); } + + /** + * Get the text content of this block element + */ + public getTextContent(): string { + return this.getStartNode().textContent; + } } diff --git a/packages/roosterjs-editor-dom/lib/blockElements/StartEndBlockElement.ts b/packages/roosterjs-editor-dom/lib/blockElements/StartEndBlockElement.ts index a211bb9bf86..7e767c9e574 100644 --- a/packages/roosterjs-editor-dom/lib/blockElements/StartEndBlockElement.ts +++ b/packages/roosterjs-editor-dom/lib/blockElements/StartEndBlockElement.ts @@ -6,6 +6,7 @@ import isNodeAfter from '../utils/isNodeAfter'; import wrap from '../utils/wrap'; import { BlockElement } from 'roosterjs-editor-types'; import { splitBalancedNodeRange } from '../utils/splitParentNode'; +import createRange from '../selection/createRange'; const STRUCTURE_NODE_TAGS = ['TD', 'TH', 'LI', 'BLOCKQUOTE']; @@ -18,7 +19,7 @@ const STRUCTURE_NODE_TAGS = ['TD', 'TH', 'LI', 'BLOCKQUOTE']; * This start and end must be in same sibling level and have same parent in DOM tree */ export default class StartEndBlockElement implements BlockElement { - constructor(private rootNode: Node, private startNode: Node, private endNode: Node) {} + constructor(private rootNode: Node, private startNode: Node, private endNode: Node) { } static getBlockContext(node: Node): HTMLElement { while (node && !isBlockElement(node)) { @@ -94,4 +95,11 @@ export default class StartEndBlockElement implements BlockElement { (isNodeAfter(node, this.startNode) && isNodeAfter(this.endNode, node)) ); } + + /** + * Get the text content of this block element + */ + public getTextContent(): string { + return createRange(this.getStartNode(), this.getEndNode()).toString(); + } } diff --git a/packages/roosterjs-editor-dom/lib/index.ts b/packages/roosterjs-editor-dom/lib/index.ts index 1194059b26c..91c9eeb728a 100644 --- a/packages/roosterjs-editor-dom/lib/index.ts +++ b/packages/roosterjs-editor-dom/lib/index.ts @@ -34,6 +34,7 @@ export { default as unwrap } from './utils/unwrap'; export { default as wrap } from './utils/wrap'; export { getNextLeafSibling, getPreviousLeafSibling } from './utils/getLeafSibling'; export { getFirstLeafNode, getLastLeafNode } from './utils/getLeafNode'; +export { default as getTextContent } from './utils/getTextContent'; export { default as VTable, VCell } from './table/VTable'; diff --git a/packages/roosterjs-editor-dom/lib/utils/getBlockElementTextContent.ts b/packages/roosterjs-editor-dom/lib/utils/getBlockElementTextContent.ts deleted file mode 100644 index 8d6973248dc..00000000000 --- a/packages/roosterjs-editor-dom/lib/utils/getBlockElementTextContent.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { BlockElement } from 'roosterjs-editor-types'; -import ContentTraverser from '../contentTraverser/ContentTraverser'; -import createRange from '../selection/createRange'; - -/** - * get block element's text content. - * @param rootNode Root node that the get the textContent of. - * @param startNode Node the node start traverser to start traversing. - * @returns text content of given text content. - */ -export default function getBlockElementTextContent(rootNode: Node, startNode?: Node): string { - const traverser = ContentTraverser.createBodyTraverser(rootNode, startNode); - let block = traverser && traverser.currentBlockElement; - let blocks: BlockElement[] = []; - let textContent: string = ''; - - while (block) { - blocks.push(block); - block = traverser.getNextBlockElement(); - } - - blocks.forEach((block, index) => { - const blockTextContent = getBlockTextContent(block); - if (blockTextContent) { - textContent = `${textContent}${blockTextContent}`; - } - if (index != blocks.length - 1) { - textContent = `${textContent}\n` - } - }); - - return textContent; -} - -function getBlockTextContent(block: BlockElement) { - return block.getStartNode() == block.getEndNode() - ? block.getStartNode().textContent - : createRange(block.getStartNode(), block.getEndNode()).toString(); -} - diff --git a/packages/roosterjs-editor-dom/lib/utils/getTextContent.ts b/packages/roosterjs-editor-dom/lib/utils/getTextContent.ts new file mode 100644 index 00000000000..c05f364341e --- /dev/null +++ b/packages/roosterjs-editor-dom/lib/utils/getTextContent.ts @@ -0,0 +1,20 @@ +import ContentTraverser from '../contentTraverser/ContentTraverser'; + +/** + * get block element's text content. + * @param rootNode Root node that the get the textContent of. + * @param startNode Node the node start traverser to start traversing. + * @returns text content of given text content. + */ +export default function getTextContent(rootNode: Node): string { + const traverser = ContentTraverser.createBodyTraverser(rootNode); + let block = traverser && traverser.currentBlockElement; + let textContent: string[] = []; + + while (block) { + textContent.push(block.getTextContent()); + block = traverser.getNextBlockElement(); + } + + return textContent.join('\n'); +} diff --git a/packages/roosterjs-editor-types/lib/interface/BlockElement.ts b/packages/roosterjs-editor-types/lib/interface/BlockElement.ts index 36561981339..6c91a868042 100644 --- a/packages/roosterjs-editor-types/lib/interface/BlockElement.ts +++ b/packages/roosterjs-editor-types/lib/interface/BlockElement.ts @@ -34,4 +34,9 @@ export default interface BlockElement { * Check if the given node is within this block element */ contains(node: Node): boolean; + + /** + * Get the text content of this block element + */ + getTextContent(): string; } From 4e3bdb731576905c271084c4e091b7dc60fb0190 Mon Sep 17 00:00:00 2001 From: Francis Meng Date: Tue, 4 Jun 2019 16:05:07 -0700 Subject: [PATCH 4/5] change some element to use the class param --- .../roosterjs-editor-dom/lib/blockElements/NodeBlockElement.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/roosterjs-editor-dom/lib/blockElements/NodeBlockElement.ts b/packages/roosterjs-editor-dom/lib/blockElements/NodeBlockElement.ts index 4f574fec052..2a69da679aa 100644 --- a/packages/roosterjs-editor-dom/lib/blockElements/NodeBlockElement.ts +++ b/packages/roosterjs-editor-dom/lib/blockElements/NodeBlockElement.ts @@ -61,6 +61,6 @@ export default class NodeBlockElement implements BlockElement { * Get the text content of this block element */ public getTextContent(): string { - return this.getStartNode().textContent; + return this.element.textContent; } } From 90628f96384eb2e3a30f81e843aa441e0ed47fc3 Mon Sep 17 00:00:00 2001 From: Francis Meng Date: Wed, 5 Jun 2019 14:02:15 -0700 Subject: [PATCH 5/5] remove comments --- packages/roosterjs-editor-dom/lib/utils/getTextContent.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/roosterjs-editor-dom/lib/utils/getTextContent.ts b/packages/roosterjs-editor-dom/lib/utils/getTextContent.ts index c05f364341e..cbeedf412ac 100644 --- a/packages/roosterjs-editor-dom/lib/utils/getTextContent.ts +++ b/packages/roosterjs-editor-dom/lib/utils/getTextContent.ts @@ -3,7 +3,6 @@ import ContentTraverser from '../contentTraverser/ContentTraverser'; /** * get block element's text content. * @param rootNode Root node that the get the textContent of. - * @param startNode Node the node start traverser to start traversing. * @returns text content of given text content. */ export default function getTextContent(rootNode: Node): string {