Spaces:
Build error
Build error
File size: 2,604 Bytes
c211499 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
import { Options } from './types'
import { resolveUrl } from './util'
import { getMimeType } from './mimes'
import { isDataUrl, makeDataUrl, resourceToDataURL } from './dataurl'
const URL_REGEX = /url\((['"]?)([^'"]+?)\1\)/g
const URL_WITH_FORMAT_REGEX = /url\([^)]+\)\s*format\((["']?)([^"']+)\1\)/g
const FONT_SRC_REGEX = /src:\s*(?:url\([^)]+\)\s*format\([^)]+\)[,;]\s*)+/g
function toRegex(url: string): RegExp {
// eslint-disable-next-line no-useless-escape
const escaped = url.replace(/([.*+?^${}()|\[\]\/\\])/g, '\\$1')
return new RegExp(`(url\\(['"]?)(${escaped})(['"]?\\))`, 'g')
}
export function parseURLs(cssText: string): string[] {
const urls: string[] = []
cssText.replace(URL_REGEX, (raw, quotation, url) => {
urls.push(url)
return raw
})
return urls.filter((url) => !isDataUrl(url))
}
export async function embed(
cssText: string,
resourceURL: string,
baseURL: string | null,
options: Options,
getContentFromUrl?: (url: string) => Promise<string>,
): Promise<string> {
try {
const resolvedURL = baseURL ? resolveUrl(resourceURL, baseURL) : resourceURL
const contentType = getMimeType(resourceURL)
let dataURL: string
if (getContentFromUrl) {
const content = await getContentFromUrl(resolvedURL)
dataURL = makeDataUrl(content, contentType)
} else {
dataURL = await resourceToDataURL(resolvedURL, contentType, options)
}
return cssText.replace(toRegex(resourceURL), `$1${dataURL}$3`)
} catch (error) {
// pass
}
return cssText
}
function filterPreferredFontFormat(
str: string,
{ preferredFontFormat }: Options,
): string {
return !preferredFontFormat
? str
: str.replace(FONT_SRC_REGEX, (match: string) => {
// eslint-disable-next-line no-constant-condition
while (true) {
const [src, , format] = URL_WITH_FORMAT_REGEX.exec(match) || []
if (!format) {
return ''
}
if (format === preferredFontFormat) {
return `src: ${src};`
}
}
})
}
export function shouldEmbed(url: string): boolean {
return url.search(URL_REGEX) !== -1
}
export async function embedResources(
cssText: string,
baseUrl: string | null,
options: Options,
): Promise<string> {
if (!shouldEmbed(cssText)) {
return cssText
}
const filteredCSSText = filterPreferredFontFormat(cssText, options)
const urls = parseURLs(filteredCSSText)
return urls.reduce(
(deferred, url) =>
deferred.then((css) => embed(css, url, baseUrl, options)),
Promise.resolve(filteredCSSText),
)
}
|