Severian's picture
Upload 7464 files
c211499
import { Options } from './types'
import { embedResources } from './embed-resources'
import { toArray, isInstanceOfElement } from './util'
import { isDataUrl, resourceToDataURL } from './dataurl'
import { getMimeType } from './mimes'
async function embedProp(
propName: string,
node: HTMLElement,
options: Options,
) {
const propValue = node.style?.getPropertyValue(propName)
if (propValue) {
const cssString = await embedResources(propValue, null, options)
node.style.setProperty(
propName,
cssString,
node.style.getPropertyPriority(propName),
)
return true
}
return false
}
async function embedBackground<T extends HTMLElement>(
clonedNode: T,
options: Options,
) {
if (!(await embedProp('background', clonedNode, options))) {
await embedProp('background-image', clonedNode, options)
}
if (!(await embedProp('mask', clonedNode, options))) {
await embedProp('mask-image', clonedNode, options)
}
}
async function embedImageNode<T extends HTMLElement | SVGImageElement>(
clonedNode: T,
options: Options,
) {
const isImageElement = isInstanceOfElement(clonedNode, HTMLImageElement)
if (
!(isImageElement && !isDataUrl(clonedNode.src)) &&
!(
isInstanceOfElement(clonedNode, SVGImageElement) &&
!isDataUrl(clonedNode.href.baseVal)
)
) {
return
}
const url = isImageElement ? clonedNode.src : clonedNode.href.baseVal
const dataURL = await resourceToDataURL(url, getMimeType(url), options)
await new Promise((resolve, reject) => {
clonedNode.onload = resolve
clonedNode.onerror = reject
const image = clonedNode as HTMLImageElement
if (image.decode) {
image.decode = resolve as any
}
if (image.loading === 'lazy') {
image.loading = 'eager'
}
if (isImageElement) {
clonedNode.srcset = ''
clonedNode.src = dataURL
} else {
clonedNode.href.baseVal = dataURL
}
})
}
async function embedChildren<T extends HTMLElement>(
clonedNode: T,
options: Options,
) {
const children = toArray<HTMLElement>(clonedNode.childNodes)
const deferreds = children.map((child) => embedImages(child, options))
await Promise.all(deferreds).then(() => clonedNode)
}
export async function embedImages<T extends HTMLElement>(
clonedNode: T,
options: Options,
) {
if (isInstanceOfElement(clonedNode, Element)) {
await embedBackground(clonedNode, options)
await embedImageNode(clonedNode, options)
await embedChildren(clonedNode, options)
}
}