Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 82 additions & 0 deletions src/clone-node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,87 @@ async function cloneChildren<T extends HTMLElement>(
return clonedNode
}

function localizeClipPathUrl(value: string): string {
const urlMatch = value.match(/^url\(\s*(['"]?)(.*?)\1\s*\)$/i)
if (!urlMatch) {
return value
}

const urlRef = urlMatch[2].trim()
if (!urlRef) {
return value
}

if (urlRef.startsWith('#')) {
return `url(${urlRef})`
}

try {
const targetUrl = new URL(urlRef, document.baseURI)
const currentUrl = new URL(document.baseURI)

if (
targetUrl.origin === currentUrl.origin &&
targetUrl.pathname === currentUrl.pathname &&
targetUrl.search === currentUrl.search &&
targetUrl.hash
) {
return `url(${targetUrl.hash})`
}
} catch {
// Invalid URL, leave as-is
}

return value
}

function hasStyle(
element: Element,
): element is Element & ElementCSSInlineStyle {
return 'style' in element
}

function normalizeClipPathForClone<T extends HTMLElement>(clonedNode: T): T {
if (!isInstanceOfElement(clonedNode, Element)) {
return clonedNode
}

const elements = [
clonedNode,
...Array.from(clonedNode.querySelectorAll('[clip-path], [style]')),
]

elements.forEach((element) => {
const clipPathAttr = element.getAttribute('clip-path')
if (clipPathAttr) {
const localizedAttr = localizeClipPathUrl(clipPathAttr)
if (localizedAttr !== clipPathAttr) {
element.setAttribute('clip-path', localizedAttr)
}
}

if (!hasStyle(element)) {
return
}

const clipPath = element.style.getPropertyValue('clip-path')
if (!clipPath) {
return
}

const localizedStyle = localizeClipPathUrl(clipPath)
if (localizedStyle !== clipPath) {
element.style.setProperty(
'clip-path',
localizedStyle,
element.style.getPropertyPriority('clip-path'),
)
}
})

return clonedNode
}

function cloneCSSStyle<T extends HTMLElement>(
nativeNode: T,
clonedNode: T,
Expand Down Expand Up @@ -261,5 +342,6 @@ export async function cloneNode<T extends HTMLElement>(
.then((clonedNode) => cloneSingleNode(clonedNode, options) as Promise<T>)
.then((clonedNode) => cloneChildren(node, clonedNode, options))
.then((clonedNode) => decorate(node, clonedNode, options))
.then((clonedNode) => normalizeClipPathForClone(clonedNode))
.then((clonedNode) => ensureSVGSymbols(clonedNode, options))
}
1 change: 1 addition & 0 deletions test/resources/svg-clip-path/image
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
data:image/png;base64,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
47 changes: 47 additions & 0 deletions test/resources/svg-clip-path/node.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<!DOCTYPE html>
<html lang="en">
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Best Practice: Page has no mechanism to bypass repeated content. Add a <main> landmark or skip link.

Page must have a mechanism to bypass repeated blocks of content.

Details

Missing: no landmarks (<main>, <nav>, <header>, <footer>), no skip link, no headings

Keyboard users must be able to skip repetitive content like navigation. Provide a skip link at the top of the page that links to the main content (e.g., <a href="#main">Skip to main content</a>), or use a <main> landmark. Screen readers can jump directly to landmarks, so a properly marked-up <main> element satisfies this requirement.


Best Practice: Page does not contain a level-one heading.

Page should contain a level-one heading.

Details

Page title: "SVG clip-path cases"

A level-one heading (<h1> or role='heading' with aria-level='1') helps users understand the page topic and provides a landmark for screen reader navigation. Each page should have exactly one h1 that describes the main content, typically matching or similar to the page title.


Best Practice: Page has no main landmark.

Page should have exactly one main landmark.

Details

The main landmark contains the primary content of the page. Screen readers allow users to jump directly to main content. Use a single <main> element (or role='main') to wrap the central content, excluding headers, footers, and navigation.

<head>
<meta charset="utf-8" />
<title>SVG clip-path cases</title>
</head>
<body>
<svg
width="680"
height="180"
viewBox="0 0 680 180"
xmlns="http://www.w3.org/2000/svg"
>
<defs>
<clipPath id="clip1">
<circle cx="80" cy="90" r="65" />
</clipPath>
<clipPath id="clip2">
<circle cx="305" cy="90" r="65" />
</clipPath>
<clipPath id="clip3">
<circle cx="530" cy="90" r="65" />
</clipPath>
</defs>

<!-- Case 2: clip-path from inline style -->
<rect
x="235"
y="25"
width="210"
height="130"
fill="#ef6c00"
style="clip-path: url('/context.html#clip2')"
/>

<!-- Case 3: clip-path from SVG presentation attribute -->
<rect
x="460"
y="25"
width="210"
height="130"
fill="#2e7d32"
clip-path="url('/context.html#clip3')"
/>
</svg>
</body>
</html>
7 changes: 7 additions & 0 deletions test/spec/svg.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,11 @@ describe('work with svg element', () => {
.then(done)
.catch(done)
})

it('should render SVG with clip-path', function (done) {
bootstrap('svg-clip-path/node.html', undefined, 'svg-clip-path/image')
.then(renderAndCheck)
.then(done)
.catch(done)
})
})
Loading