Skip to content

Commit

Permalink
fix: get user-set css styles(close #66)
Browse files Browse the repository at this point in the history
  • Loading branch information
qq15725 committed Dec 18, 2023
1 parent c00e9df commit 7a99399
Show file tree
Hide file tree
Showing 7 changed files with 64 additions and 37 deletions.
23 changes: 19 additions & 4 deletions src/clone-node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ import {
import { cloneElement } from './clone-element'
import type { Context } from './context'

const excludeParentNodes = new Set([
'symbol', // test/fixtures/svg.symbol.html
])

async function appendChildNode<T extends Node>(
cloned: T,
child: ChildNode,
Expand All @@ -25,6 +29,15 @@ async function appendChildNode<T extends Node>(

if (context.filter && !context.filter(child)) return

if (
excludeParentNodes.has(cloned.nodeName)
|| excludeParentNodes.has(child.nodeName)
) {
context.currentParentNodeStyle = undefined
} else {
context.currentParentNodeStyle = context.currentNodeStyle
}

cloned.appendChild(await cloneNode(child, context))
}

Expand Down Expand Up @@ -100,15 +113,17 @@ export async function cloneNode<T extends Node>(
}
}

const diffStyle = copyCssStyles(node, cloned, isRoot, context)
const style
= context.currentNodeStyle
= copyCssStyles(node, cloned, isRoot, context)

if (isRoot) applyCssStyleWithOptions(cloned, context)

let copyScrollbar = false
if (context.isEnable('copyScrollbar')) {
const overflow = [
diffStyle.get('overflow-x')?.[0],
diffStyle.get('overflow-y')?.[1],
style.get('overflow-x')?.[0],
style.get('overflow-y')?.[1],
]
copyScrollbar = (overflow.includes('scroll'))
|| (
Expand All @@ -121,7 +136,7 @@ export async function cloneNode<T extends Node>(

copyInputValue(node, cloned)

splitFontFamily(diffStyle.get('font-family')?.[0])
splitFontFamily(style.get('font-family')?.[0])
?.forEach(val => fontFamilies.add(val))

if (!isVideoElement(node)) {
Expand Down
6 changes: 6 additions & 0 deletions src/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,12 @@ export interface InternalContext<T extends Node> {
* @param key
*/
isEnable: (key: string) => boolean

/**
* To get the node style set by the user
*/
currentNodeStyle?: Map<string, [string, string]>
currentParentNodeStyle?: Map<string, [string, string]>
}

export type Context<T extends Node = Node> = InternalContext<T> & Required<Options>
49 changes: 26 additions & 23 deletions src/copy-css-styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,52 +9,55 @@ export function copyCssStyles<T extends HTMLElement | SVGElement>(
isRoot: boolean,
context: Context,
) {
const { ownerWindow } = context
const { ownerWindow, includeStyleProperties, currentParentNodeStyle } = context
const clonedStyle = cloned.style
const computedStyle = ownerWindow!.getComputedStyle(node)
const defaultStyle = getDefaultStyle(node, null, context)
const diffStyle = getDiffStyle(computedStyle, defaultStyle, context.includeStyleProperties)
currentParentNodeStyle?.forEach((_, key) => {
defaultStyle.delete(key)
})
const style = getDiffStyle(computedStyle, defaultStyle, includeStyleProperties)

// fix
diffStyle.delete('transition-property')
diffStyle.delete('all') // svg: all
diffStyle.delete('d') // svg: d
diffStyle.delete('content') // Safari shows pseudoelements if content is set
style.delete('transition-property')
style.delete('all') // svg: all
style.delete('d') // svg: d
style.delete('content') // Safari shows pseudoelements if content is set
if (isRoot) {
diffStyle.delete('margin-top')
diffStyle.delete('margin-right')
diffStyle.delete('margin-bottom')
diffStyle.delete('margin-left')
diffStyle.delete('margin-block-start')
diffStyle.delete('margin-block-end')
diffStyle.delete('margin-inline-start')
diffStyle.delete('margin-inline-end')
diffStyle.set('box-sizing', ['border-box', ''])
style.delete('margin-top')
style.delete('margin-right')
style.delete('margin-bottom')
style.delete('margin-left')
style.delete('margin-block-start')
style.delete('margin-block-end')
style.delete('margin-inline-start')
style.delete('margin-inline-end')
style.set('box-sizing', ['border-box', ''])
}
// fix background-clip: text
if (diffStyle.get('background-clip')?.[0] === 'text') {
if (style.get('background-clip')?.[0] === 'text') {
cloned.classList.add('______background-clip--text')
}
// fix chromium
// https://github.com/RigoCorp/html-to-image/blob/master/src/cssFixes.ts
if (IN_CHROME) {
if (!diffStyle.has('font-kerning')) diffStyle.set('font-kerning', ['normal', ''])
if (!style.has('font-kerning')) style.set('font-kerning', ['normal', ''])

if (
(
diffStyle.get('overflow-x')?.[0] === 'hidden'
|| diffStyle.get('overflow-y')?.[0] === 'hidden'
style.get('overflow-x')?.[0] === 'hidden'
|| style.get('overflow-y')?.[0] === 'hidden'
)
&& diffStyle.get('text-overflow')?.[0] === 'ellipsis'
&& style.get('text-overflow')?.[0] === 'ellipsis'
&& node.scrollWidth === node.clientWidth
) {
diffStyle.set('text-overflow', ['clip', ''])
style.set('text-overflow', ['clip', ''])
}
}

diffStyle.forEach(([value, priority], name) => {
style.forEach(([value, priority], name) => {
clonedStyle.setProperty(name, value, priority)
})

return diffStyle
return style
}
23 changes: 13 additions & 10 deletions src/copy-pseudo-class.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export function copyPseudoClass<T extends HTMLElement | SVGElement>(
copyScrollbar: boolean,
context: Context,
) {
const { ownerWindow, svgStyleElement, svgStyles } = context
const { ownerWindow, svgStyleElement, svgStyles, currentNodeStyle } = context

if (!svgStyleElement || !ownerWindow) return

Expand All @@ -43,21 +43,24 @@ export function copyPseudoClass<T extends HTMLElement | SVGElement>(

const klasses = [uuid()]
const defaultStyle = getDefaultStyle(node, pseudoClass, context)
const cloneStyle = [
`content: '${ content }';`,
]

const diffStyle = getDiffStyle(computedStyle, defaultStyle, context.includeStyleProperties)
currentNodeStyle?.forEach((_, key) => {
defaultStyle.delete(key)
})
const style = getDiffStyle(computedStyle, defaultStyle, context.includeStyleProperties)

// fix
diffStyle.delete('content')
diffStyle.delete('-webkit-locale')
style.delete('content')
style.delete('-webkit-locale')
// fix background-clip: text
if (diffStyle.get('background-clip')?.[0] === 'text') {
if (style.get('background-clip')?.[0] === 'text') {
cloned.classList.add('______background-clip--text')
}

diffStyle.forEach(([value, priority], name) => {
const cloneStyle = [
`content: '${ content }';`,
]

style.forEach(([value, priority], name) => {
cloneStyle.push(`${ name }: ${ value }${ priority ? ' !important' : '' };`)
})

Expand Down
Binary file modified test/fixtures/css.font-family.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/fixtures/svg.externalsymbol.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/fixtures/svg.symbol.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

1 comment on commit 7a99399

@vercel
Copy link

@vercel vercel bot commented on 7a99399 Dec 18, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

modern-screenshot – ./

modern-screenshot-git-main-qq15725.vercel.app
modern-screenshot.vercel.app
modern-screenshot-qq15725.vercel.app

Please sign in to comment.