Skip to content

Commit

Permalink
fix: url(...) in css file lose efficacy
Browse files Browse the repository at this point in the history
  • Loading branch information
hzsrc committed Sep 10, 2024
1 parent 56b099e commit fc79106
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 14 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
"svg"
],
"scripts": {
"lint": "eslint 'src/**/*.{js,ts}?(x)' --fix",
"lint": "eslint src/**/*.{js,ts} --fix",
"clean": "rimraf dist es lib",
"build:esm": "tsc --module esnext --target es2017 --outDir ./es",
"build:cjs": "tsc --module commonjs --target es5 --outDir ./lib",
Expand Down
20 changes: 10 additions & 10 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { Options } from './types'
import { cloneNode } from './clone-node'
import { embedImages } from './embed-images'
//import { embedImages } from './embed-images'
import { applyStyle } from './apply-style'
import { embedWebFonts, getWebFontCSS } from './embed-webfonts'
//import { embedWebFonts, getWebFontCSS } from './embed-webfonts'
import {
getImageSize,
getPixelRatio,
Expand All @@ -19,8 +19,8 @@ export async function toSvg<T extends HTMLElement>(
): Promise<string> {
const { width, height } = getImageSize(node, options)
const clonedNode = (await cloneNode(node, options, true)) as HTMLElement
await embedWebFonts(clonedNode, options)
await embedImages(clonedNode, options)
//await embedWebFonts(clonedNode, options)
//await embedImages(clonedNode, options)
applyStyle(clonedNode, options)
const datauri = await nodeToDataURL(clonedNode, width, height, options.usePageCss)
return datauri
Expand Down Expand Up @@ -143,9 +143,9 @@ export async function toBlob<T extends HTMLElement>(
return blob
}

export async function getFontEmbedCSS<T extends HTMLElement>(
node: T,
options: Options = {},
): Promise<string> {
return getWebFontCSS(node, options)
}
// export async function getFontEmbedCSS<T extends HTMLElement>(
// node: T,
// options: Options = {},
// ): Promise<string> {
// return getWebFontCSS(node, options)
// }
59 changes: 56 additions & 3 deletions src/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,8 @@ export async function svgToDataURL(svg: SVGElement): Promise<string> {
.then(() => new XMLSerializer().serializeToString(svg))
.then(encodeURIComponent)
.then((html) => `data:image/svg+xml;charset=utf-8,${html}`)
// @ts-ignore
//.then(s => $('body').prepend(svg) && s)
}

export async function nodeToDataURL(
Expand Down Expand Up @@ -275,9 +277,8 @@ export async function nodeToDataURL(
return svgToDataURL(svg)
}

export const isInstanceOfElement = <
T extends typeof Element | typeof HTMLElement | typeof SVGImageElement,
>(
export const isInstanceOfElement = <T extends typeof Element | typeof HTMLElement | typeof SVGImageElement,
>(
node: Element | HTMLElement | SVGImageElement,
instance: T,
): node is T['prototype'] => {
Expand All @@ -304,6 +305,7 @@ export function getStyles() {
promises.push(
fetch(href)
.then((r) => r.text())
.then(tx => transRelPath(href, tx))
.catch(() => ''),
)
} else {
Expand All @@ -314,3 +316,54 @@ export function getStyles() {
return arr.join('\n\n')
})
}

function transRelPath(cssPath: string, cssText: string): Promise<string> {
const quotReg = /^\s*(['"])(.+?)\1/
const map: { [url: string]: string } = {}
//css中的图片路径是相对于css文件的,要改为相对于当前html文件
let css = cssText.replace(/url\(\s*(.+?)\s*\)/ig, (m, path) => {
path = path.replace(quotReg, '$2')
const sUrl = toRelative(cssPath, path)
const ret = 'url(' + sUrl + ')'
map[sUrl] = ret
return ret
})
//css中的图片在svg中访问失败,需要转换为dataUrl
const promises = Object.keys(map).map(url => {
return urlToDataUrl(url).then(dataUrl => {
let p: number
while ((p = css.indexOf(map[url])) > -1) {
css = css.substring(0, p) + 'url(' + dataUrl + ')' + css.substring(p + map[url].length)
}
})
})
return Promise.all(promises).then(_ => css)
}

function toRelative(compareTo: string, path: string): string {
if (path[0] === '/' || path.match(/^data:|:\/\//i)) return path
const pos = compareTo.lastIndexOf('/')
if (pos > -1) {
const dir = compareTo.substring(0, pos)
const arr = (dir + '/' + path).split('/').filter(i => i !== '.')
for (let i = arr.length - 1; i > 0; i--) {
if (arr[i] === '..' && arr[i - 1] !== '..') {
arr.splice(i - 1, 2)
i--
}
}
return arr.join('/')
}
return path
}

function urlToDataUrl(url: string): Promise<string> {
return fetch(url)
.then(response => response.blob()) // 将响应转换为Blob
.then(blob => new Promise((resolve, reject) => {
const reader = new FileReader()
reader.onload = () => resolve('' + reader.result)
reader.onerror = error => resolve('')
reader.readAsDataURL(blob) // 转换Blob为DataURL
}))
}

0 comments on commit fc79106

Please sign in to comment.