Skip to content

Commit

Permalink
feat: support currentColor in svg.symbol
Browse files Browse the repository at this point in the history
  • Loading branch information
qq15725 committed Apr 26, 2023
1 parent 93628b3 commit 322b223
Show file tree
Hide file tree
Showing 9 changed files with 85 additions and 33 deletions.
1 change: 0 additions & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@

body, html {
margin: 0;
color: white;
}
</style>
</head>
Expand Down
4 changes: 0 additions & 4 deletions src/clone-node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,6 @@ export async function cloneNode<T extends Node>(
&& (isHTMLElementNode(node) || isSVGElementNode(node))) {
const computedStyle = ownerWindow.getComputedStyle(node)

if (computedStyle.display === 'none') {
return ownerDocument.createComment(node.tagName.toLowerCase())
}

const cloned = await cloneElement(node, context)
const clonedStyle = cloned.style

Expand Down
4 changes: 2 additions & 2 deletions src/copy-css-styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ export function copyCssStyles<T extends HTMLElement | SVGElement>(
context: Context,
) {
const clonedStyle = cloned.style
const defaultStyle = getDefaultStyle(node.nodeName, null, context)
const diffStyle = getDiffStyle(computedStyle, defaultStyle, node)
const defaultStyle = getDefaultStyle(node, null, context)
const diffStyle = getDiffStyle(computedStyle, defaultStyle)

for (const [name, [value, priority]] of Object.entries(diffStyle)) {
if (ignoredStyle.includes(name)) continue
Expand Down
2 changes: 1 addition & 1 deletion src/copy-pseudo-class.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export function copyPseudoClass<T extends HTMLElement | SVGElement>(
if (!content || content === 'none') return

const klasses = [uuid()]
const defaultStyle = getDefaultStyle(node.nodeName, pseudoClass, context)
const defaultStyle = getDefaultStyle(node, pseudoClass, context)
const cloneStyle = [
`content: '${ content.replace(/'|"/g, '') }';`,
]
Expand Down
74 changes: 58 additions & 16 deletions src/get-default-style.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,42 @@
import { uuid } from './utils'
import { isSVGElementNode, uuid } from './utils'
import type { Context } from './context'

export function getDefaultStyle(nodeName: string, pseudoElement: string | null, context: Context) {
nodeName = nodeName.toLowerCase()
const ignoredStyles = [
'width',
'height',
]

const includedAttributes = [
'stroke',
'fill',
]

export function getDefaultStyle(
node: HTMLElement | SVGElement,
pseudoElement: string | null,
context: Context,
) {
const { defaultComputedStyles, ownerDocument } = context
const key = `${ nodeName }${ pseudoElement ?? '' }`

const nodeName = node.nodeName.toLowerCase()
const isSvgNode = isSVGElementNode(node) && nodeName !== 'svg'
const attributes = isSvgNode
? includedAttributes
.map(name => [name, node.getAttribute(name)])
.filter(([, value]) => value !== null)
: []

const key = [
isSvgNode && 'svg',
nodeName,
attributes.map((name, value) => `${ name }=${ value }`).join(','),
pseudoElement,
]
.filter(Boolean)
.join(':')

if (defaultComputedStyles.has(key)) return defaultComputedStyles.get(key)!

let sandbox = context.sandbox
if (!sandbox) {
if (ownerDocument) {
Expand All @@ -21,24 +52,35 @@ export function getDefaultStyle(nodeName: string, pseudoElement: string | null,
}
}
if (!sandbox) return {}

const sandboxWindow = sandbox.contentWindow
if (!sandboxWindow) return {}
const sandboxDocument = sandboxWindow.document
const el = sandboxDocument.createElement(nodeName)
sandboxDocument.body.appendChild(el)
// Ensure that there is some content, so properties like margin are applied

let root: HTMLElement | SVGSVGElement
let el: Element
if (isSvgNode) {
root = sandboxDocument.createElementNS('http://www.w3.org/2000/svg', 'svg')
el = root.ownerDocument.createElementNS(root.namespaceURI, nodeName)
attributes.forEach(([name, value]) => {
el.setAttributeNS(null, name!, value!)
})
root.appendChild(el)
} else {
root = el = sandboxDocument.createElement(nodeName)
}
el.textContent = ' '
const style = sandboxWindow.getComputedStyle(el, pseudoElement)
sandboxDocument.body.appendChild(root)
const computedStyle = sandboxWindow.getComputedStyle(el, pseudoElement)
const styles: Record<string, any> = {}
for (let i = style.length - 1; i >= 0; i--) {
const name = style.item(i)
if (name === 'width' || name === 'height') {
styles[name] = 'auto'
} else {
styles[name] = style.getPropertyValue(name)
}
for (let len = computedStyle.length, i = 0; i < len; i++) {
const name = computedStyle.item(i)
if (ignoredStyles.includes(name)) continue
styles[name] = computedStyle.getPropertyValue(name)
}
sandboxDocument.body.removeChild(el)
sandboxDocument.body.removeChild(root)

defaultComputedStyles.set(key, styles)

return styles
}
7 changes: 1 addition & 6 deletions src/get-diff-style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ const getPrefix = (name: string) => name
export function getDiffStyle(
style: CSSStyleDeclaration,
defaultStyle: Record<string, string>,
node?: HTMLElement | SVGElement,
) {
const diffStyle: Record<string, [string, string]> = {}
const diffStylePrefixs: string[] = []
Expand All @@ -23,11 +22,7 @@ export function getDiffStyle(
prefixTree[prefix][name] = [value, priority]
}

if (
defaultStyle[name] === value
&& !priority
&& (node && !node.getAttribute(name))
) continue
if (defaultStyle[name] === value && !priority) continue

if (prefix) {
diffStylePrefixs.push(prefix)
Expand Down
6 changes: 3 additions & 3 deletions test/fixtures/svg.color.html
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@
height="120"
requiredExtensions="http://www.w3.org/1999/xhtml"
>
<span
style="display: inline-block; width: 32px; height: 32px; background: red;"
/>
<span
style="display: inline-block; width: 32px; height: 32px; background: red;"
/>
</foreignObject>
</svg>
</div>
Expand Down
20 changes: 20 additions & 0 deletions test/fixtures/svg.symbol.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<template>
<div id="root">
<button style="color: red">
<svg><use xlink:href="#icon" /></svg>
</button>

<button style="color: yellow">
<svg><use xlink:href="#icon" /></svg>
</button>

<svg style="display: none">
<symbol id="icon" fill="none" viewBox="0 0 24 24">
<path
stroke="currentColor"
d="M16 22v-4a4 4 0 0 0-8 0v4m13-11.85v7.82c0 2.22-1.8 4.03-4 4.03H7c-2.2 0-4-1.8-4-4.03v-7.82c0-1.21.54-2.36 1.47-3.12l5-4.12a3.97 3.97 0 0 1 5.06 0l5 4.12A4.05 4.05 0 0 1 21 10.15Z"
/>
</symbol>
</svg>
</div>
</template>
Binary file added test/fixtures/svg.symbol.png
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 322b223

@vercel
Copy link

@vercel vercel bot commented on 322b223 Apr 26, 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.vercel.app
modern-screenshot-qq15725.vercel.app
modern-screenshot-git-main-qq15725.vercel.app

Please sign in to comment.