-
Notifications
You must be signed in to change notification settings - Fork 166
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
2,823 additions
and
2,823 deletions.
There are no files selected for viewing
904 changes: 452 additions & 452 deletions
904
packages/roosterjs-content-model-core/test/command/paste/pasteTest.ts
Large diffs are not rendered by default.
Oops, something went wrong.
76 changes: 38 additions & 38 deletions
76
packages/roosterjs-content-model-dom/lib/modelToDom/optimizers/optimize.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,38 +1,38 @@ | ||
import { enumerateInheritedStyle, removeUnnecessaryStyle } from './removeUnnecessaryStyle'; | ||
import { isEntityElement } from '../../domUtils/entityUtils'; | ||
import { mergeNode } from './mergeNode'; | ||
import { removeUnnecessaryAttribute } from './removeUnnecessaryAttribute'; | ||
import { removeUnnecessarySpan } from './removeUnnecessarySpan'; | ||
|
||
/** | ||
* @internal | ||
*/ | ||
export function optimize(root: Node, isRecursive: boolean = false) { | ||
/** | ||
* Do no do any optimization to entity | ||
*/ | ||
if (isEntityElement(root)) { | ||
return; | ||
} | ||
if (!isRecursive && root.parentElement != null) { | ||
const computedAttributes = {} as Record<string, Attr>; | ||
// html doesn't provide computed attributes, use parent's attributes directly | ||
Array.from(root.parentElement.attributes).forEach(attr => { | ||
computedAttributes[attr.name] = attr; | ||
}); | ||
removeUnnecessaryAttribute(root, computedAttributes); | ||
|
||
const computedStyle = {} as Record<string, Set<string>>; | ||
enumerateInheritedStyle(root.parentElement, (key, values) => { | ||
computedStyle[key] = values; | ||
}); | ||
removeUnnecessaryStyle(root, computedStyle); | ||
} | ||
|
||
removeUnnecessarySpan(root); | ||
mergeNode(root); | ||
|
||
for (let child = root.firstChild; child; child = child.nextSibling) { | ||
optimize(child, true); | ||
} | ||
} | ||
import { enumerateInheritedStyle, removeUnnecessaryStyle } from './removeUnnecessaryStyle'; | ||
import { isEntityElement } from '../../domUtils/entityUtils'; | ||
import { mergeNode } from './mergeNode'; | ||
import { removeUnnecessaryAttribute } from './removeUnnecessaryAttribute'; | ||
import { removeUnnecessarySpan } from './removeUnnecessarySpan'; | ||
|
||
/** | ||
* @internal | ||
*/ | ||
export function optimize(root: Node, isRecursive: boolean = false) { | ||
/** | ||
* Do no do any optimization to entity | ||
*/ | ||
if (isEntityElement(root)) { | ||
return; | ||
} | ||
if (!isRecursive && root.parentElement != null) { | ||
const computedAttributes = {} as Record<string, Attr>; | ||
// html doesn't provide computed attributes, use parent's attributes directly | ||
Array.from(root.parentElement.attributes).forEach(attr => { | ||
computedAttributes[attr.name] = attr; | ||
}); | ||
removeUnnecessaryAttribute(root, computedAttributes); | ||
|
||
const computedStyle = {} as Record<string, Set<string>>; | ||
enumerateInheritedStyle(root.parentElement, (key, values) => { | ||
computedStyle[key] = values; | ||
}); | ||
removeUnnecessaryStyle(root, computedStyle); | ||
} | ||
|
||
removeUnnecessarySpan(root); | ||
mergeNode(root); | ||
|
||
for (let child = root.firstChild; child; child = child.nextSibling) { | ||
optimize(child, true); | ||
} | ||
} |
56 changes: 28 additions & 28 deletions
56
packages/roosterjs-content-model-dom/lib/modelToDom/optimizers/removeUnnecessaryAttribute.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,28 +1,28 @@ | ||
import { isNodeOfType } from '../../domUtils/isNodeOfType'; | ||
|
||
/** | ||
* @internal | ||
*/ | ||
export function removeUnnecessaryAttribute(root: Node, computedAttributes: Record<string, Attr>) { | ||
if (!isNodeOfType(root, 'ELEMENT_NODE')) { | ||
return; | ||
} | ||
const newComputedAttributes = { | ||
...computedAttributes, | ||
}; | ||
for (let i = root.attributes.length - 1; i >= 0; i--) { | ||
const attr = root.attributes[i]; | ||
if (attr.name === 'style') { | ||
continue; | ||
} | ||
if (newComputedAttributes[attr.name]?.isEqualNode(attr) ?? false) { | ||
root.removeAttribute(attr.name); | ||
} else { | ||
newComputedAttributes[attr.name] = attr; | ||
} | ||
} | ||
|
||
for (let child = root.firstChild; child; child = child.nextSibling) { | ||
removeUnnecessaryAttribute(child, newComputedAttributes); | ||
} | ||
} | ||
import { isNodeOfType } from '../../domUtils/isNodeOfType'; | ||
|
||
/** | ||
* @internal | ||
*/ | ||
export function removeUnnecessaryAttribute(root: Node, computedAttributes: Record<string, Attr>) { | ||
if (!isNodeOfType(root, 'ELEMENT_NODE')) { | ||
return; | ||
} | ||
const newComputedAttributes = { | ||
...computedAttributes, | ||
}; | ||
for (let i = root.attributes.length - 1; i >= 0; i--) { | ||
const attr = root.attributes[i]; | ||
if (attr.name === 'style') { | ||
continue; | ||
} | ||
if (newComputedAttributes[attr.name]?.isEqualNode(attr) ?? false) { | ||
root.removeAttribute(attr.name); | ||
} else { | ||
newComputedAttributes[attr.name] = attr; | ||
} | ||
} | ||
|
||
for (let child = root.firstChild; child; child = child.nextSibling) { | ||
removeUnnecessaryAttribute(child, newComputedAttributes); | ||
} | ||
} |
74 changes: 37 additions & 37 deletions
74
packages/roosterjs-content-model-dom/lib/modelToDom/optimizers/removeUnnecessarySpan.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,37 +1,37 @@ | ||
import { isNodeOfType } from '../../domUtils/isNodeOfType'; | ||
|
||
/** | ||
* @internal | ||
*/ | ||
export function removeUnnecessarySpan(root: Node) { | ||
for (let child = root.firstChild; child; ) { | ||
if ( | ||
isNodeOfType(child, 'ELEMENT_NODE') && | ||
child.tagName == 'SPAN' && | ||
child.attributes.length == 0 && | ||
!isImageSpan(child) | ||
) { | ||
const node = child; | ||
let refNode = child.nextSibling; | ||
child = child.nextSibling; | ||
|
||
while (node.lastChild) { | ||
const newNode = node.lastChild; | ||
root.insertBefore(newNode, refNode); | ||
refNode = newNode; | ||
} | ||
|
||
root.removeChild(node); | ||
} else { | ||
child = child.nextSibling; | ||
} | ||
} | ||
} | ||
|
||
const isImageSpan = (child: HTMLElement) => { | ||
return ( | ||
isNodeOfType(child.firstChild, 'ELEMENT_NODE') && | ||
child.firstChild.tagName == 'IMG' && | ||
child.firstChild == child.lastChild | ||
); | ||
}; | ||
import { isNodeOfType } from '../../domUtils/isNodeOfType'; | ||
|
||
/** | ||
* @internal | ||
*/ | ||
export function removeUnnecessarySpan(root: Node) { | ||
for (let child = root.firstChild; child; ) { | ||
if ( | ||
isNodeOfType(child, 'ELEMENT_NODE') && | ||
child.tagName == 'SPAN' && | ||
child.attributes.length == 0 && | ||
!isImageSpan(child) | ||
) { | ||
const node = child; | ||
let refNode = child.nextSibling; | ||
child = child.nextSibling; | ||
|
||
while (node.lastChild) { | ||
const newNode = node.lastChild; | ||
root.insertBefore(newNode, refNode); | ||
refNode = newNode; | ||
} | ||
|
||
root.removeChild(node); | ||
} else { | ||
child = child.nextSibling; | ||
} | ||
} | ||
} | ||
|
||
const isImageSpan = (child: HTMLElement) => { | ||
return ( | ||
isNodeOfType(child.firstChild, 'ELEMENT_NODE') && | ||
child.firstChild.tagName == 'IMG' && | ||
child.firstChild == child.lastChild | ||
); | ||
}; |
110 changes: 55 additions & 55 deletions
110
packages/roosterjs-content-model-dom/lib/modelToDom/optimizers/removeUnnecessaryStyle.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,55 +1,55 @@ | ||
import { INHERITABLE_PROPERTIES } from 'roosterjs-editor-types'; | ||
import { isNodeOfType } from '../../domUtils/isNodeOfType'; | ||
|
||
/** | ||
* @internal | ||
*/ | ||
export function enumerateInheritedStyle( | ||
element: HTMLElement, | ||
handler: (key: string, value: Set<string>) => void | ||
) { | ||
element.style.cssText.split(';').forEach(value => { | ||
const [key, valueText] = value.split(':').map(part => part.trim()); | ||
if ( | ||
!key || | ||
!valueText || | ||
(element.tagName == 'A' && key === 'color') || // The color of a link is not inherited | ||
!INHERITABLE_PROPERTIES.includes(key) | ||
) { | ||
return; | ||
} | ||
const values = new Set(valueText.split(',').map(value => value.trim())); | ||
|
||
handler(key, values); | ||
}); | ||
} | ||
|
||
/** | ||
* @internal | ||
*/ | ||
export function removeUnnecessaryStyle(root: Node, computedCSS: Record<string, Set<string>>) { | ||
if (!isNodeOfType(root, 'ELEMENT_NODE')) { | ||
return; | ||
} | ||
const newComputedCSS = { | ||
...computedCSS, | ||
}; | ||
enumerateInheritedStyle(root, (key, values) => { | ||
if ( | ||
computedCSS[key]?.size === values.size && | ||
[...computedCSS[key]].every(value => values.has(value)) | ||
) { | ||
root.style.removeProperty(key); | ||
} else { | ||
newComputedCSS[key] = values; | ||
} | ||
}); | ||
|
||
if (root.style.cssText === '') { | ||
root.removeAttribute('style'); | ||
} | ||
|
||
for (let child = root.firstChild; child; child = child.nextSibling) { | ||
removeUnnecessaryStyle(child, newComputedCSS); | ||
} | ||
} | ||
import { INHERITABLE_PROPERTIES } from 'roosterjs-editor-types'; | ||
import { isNodeOfType } from '../../domUtils/isNodeOfType'; | ||
|
||
/** | ||
* @internal | ||
*/ | ||
export function enumerateInheritedStyle( | ||
element: HTMLElement, | ||
handler: (key: string, value: Set<string>) => void | ||
) { | ||
element.style.cssText.split(';').forEach(value => { | ||
const [key, valueText] = value.split(':').map(part => part.trim()); | ||
if ( | ||
!key || | ||
!valueText || | ||
(element.tagName == 'A' && key === 'color') || // The color of a link is not inherited | ||
!INHERITABLE_PROPERTIES.includes(key) | ||
) { | ||
return; | ||
} | ||
const values = new Set(valueText.split(',').map(value => value.trim())); | ||
|
||
handler(key, values); | ||
}); | ||
} | ||
|
||
/** | ||
* @internal | ||
*/ | ||
export function removeUnnecessaryStyle(root: Node, computedCSS: Record<string, Set<string>>) { | ||
if (!isNodeOfType(root, 'ELEMENT_NODE')) { | ||
return; | ||
} | ||
const newComputedCSS = { | ||
...computedCSS, | ||
}; | ||
enumerateInheritedStyle(root, (key, values) => { | ||
if ( | ||
computedCSS[key]?.size === values.size && | ||
[...computedCSS[key]].every(value => values.has(value)) | ||
) { | ||
root.style.removeProperty(key); | ||
} else { | ||
newComputedCSS[key] = values; | ||
} | ||
}); | ||
|
||
if (root.style.cssText === '') { | ||
root.removeAttribute('style'); | ||
} | ||
|
||
for (let child = root.firstChild; child; child = child.nextSibling) { | ||
removeUnnecessaryStyle(child, newComputedCSS); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,11 @@ | ||
{ | ||
"name": "roosterjs-content-model-dom", | ||
"description": "Content Model for roosterjs", | ||
"dependencies": { | ||
"tslib": "^2.3.1", | ||
"roosterjs-content-model-types": "", | ||
"roosterjs-editor-types": "" | ||
}, | ||
"version": "0.0.0", | ||
"main": "./lib/index.ts" | ||
} | ||
{ | ||
"name": "roosterjs-content-model-dom", | ||
"description": "Content Model for roosterjs", | ||
"dependencies": { | ||
"tslib": "^2.3.1", | ||
"roosterjs-content-model-types": "", | ||
"roosterjs-editor-types": "" | ||
}, | ||
"version": "0.0.0", | ||
"main": "./lib/index.ts" | ||
} |
Oops, something went wrong.