Skip to content

Commit

Permalink
[Enhancement] Support Cloning Custom Elements (#129)
Browse files Browse the repository at this point in the history
* feat(custom-elements): ✨ obtain children of shadow node for custom elements

Inspired by tsayen/dom-to-image#370

If element has `shadowRoot` property it is custom
(and the shadow node is open) so fetch it's children.

Closes #128

* fix: 🐛 add safety checks to support special/custom elements

Introduced by 021f124
Access to shadow node exposes the code to custom elements that break the current code.
Was breaking because of elements without a style node.
This commit fixes these bugs with simple, NON-BREAKING safety checks.

* test(htmltoimage): 🚨 Added tests covering custom elements

renders mathfield custom element
https://github.com/arnog/mathlive
  • Loading branch information
ShaMan123 committed May 17, 2021
1 parent 50ed80e commit b93825e
Show file tree
Hide file tree
Showing 6 changed files with 55 additions and 3 deletions.
6 changes: 4 additions & 2 deletions src/cloneNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ async function cloneChildren(
clonedNode: HTMLElement,
filter?: Function,
): Promise<HTMLElement> {
const children = toArray<HTMLElement>(nativeNode.childNodes)
const children = toArray<HTMLElement>(
(nativeNode.shadowRoot ?? nativeNode).childNodes,
)
if (children.length === 0) {
return Promise.resolve(clonedNode)
}
Expand Down Expand Up @@ -65,7 +67,7 @@ async function decorate(
function cloneCssStyle(nativeNode: HTMLElement, clonedNode: HTMLElement) {
const source = window.getComputedStyle(nativeNode)
const target = clonedNode.style

if (!target) return
if (source.cssText) {
target.cssText = source.cssText
} else {
Expand Down
2 changes: 1 addition & 1 deletion src/embedImages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ async function embedBackground(
clonedNode: HTMLElement,
options: Options,
): Promise<HTMLElement> {
const background = clonedNode.style.getPropertyValue('background')
const background = clonedNode.style?.getPropertyValue('background')
if (!background) {
return Promise.resolve(clonedNode)
}
Expand Down
40 changes: 40 additions & 0 deletions test/spec/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,46 @@ describe('html to image', () => {
.then(done)
.catch(done)
})

describe('custom element', () => {
let link: HTMLLinkElement
beforeAll(() => {
const script = document.createElement('script')
script.src = 'https://unpkg.com/mathlive/dist/mathlive.min.js'
link = document.createElement('link')
link.rel = 'stylesheet'
link.href = 'https://unpkg.com/mathlive/dist/mathlive-fonts.css'
const tasks = [
new Promise((resolve, reject) => {
script.onload = resolve
script.onerror = reject
}),
new Promise((resolve, reject) => {
link.onload = resolve
link.onerror = reject
}),
]
document.head.append(script, link)
return Promise.all(tasks)
})

afterAll(() => {
link.remove()
})

it('should render content from shadow node of custom element', (done) => {
Helper.bootstrap(
'custom-element/node.html',
'custom-element/style.css',
'custom-element/image',
)
.then(util.delay(1000))
.then(Helper.renderAndCheck)
.then(util.delay(1000))
.then(done)
.catch(done)
})
})
})

describe('work with svg', () => {
Expand Down
1 change: 1 addition & 0 deletions test/spec/resources/custom-element/image
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
data:image/png;base64,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
9 changes: 9 additions & 0 deletions test/spec/resources/custom-element/node.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<math-field
value="S_{\triangle }=\frac{ab\sin \left(\gamma \right)}{2}"
scrollingelement="[object HTMLHtmlElement]"
class="math no-touch"
role="textbox"
tabindex="0"
read-only=""
>S_{\triangle }=\frac{ab\sin \left(\gamma \right)}{2}
</math-field>
Empty file.

0 comments on commit b93825e

Please sign in to comment.