ui: rewrite css parser -> urlResolve.ts

This commit is contained in:
nick-delirium 2024-10-30 15:04:40 +01:00
parent c36946ee9e
commit b928ddb53c
No known key found for this signature in database
GPG key ID: 93ABD695DF5FDBA0

View file

@ -1,64 +1,46 @@
export function resolveURL(baseURL: string, relURL: string): string { export function resolveURL(baseURL: string, relURL: string): string {
if (relURL.startsWith('#') || relURL === "") { if (relURL.startsWith('#') || relURL === '') {
return relURL; return relURL;
} }
return new URL(relURL, baseURL).toString(); return new URL(relURL, baseURL).toString();
} }
// url("url") or url('url') or url(url) function rewriteCSSLinks(
const re1 = /url\(("[^"]*"|'[^']*'|[^)]*)\)/g css: string,
// @import "url" or @import 'url' rewriter: (rawurl: string) => string
const re2 = /@import (["'])(.*?)\1/g ): string {
function cssUrlsIndex(css: string): Array<[number, number]> { // Replace url() functions
const idxs: Array<[number, number]> = []; css = css.replace(/url\(\s*(['"]?)(.*?)\1\s*\)/gs, (match, quote, url) => {
const i1 = css.matchAll(re1); let newurl = rewriter(url.trim());
// @ts-ignore return `url(${quote}${newurl}${quote})`;
for (let m of i1) { });
// @ts-ignore
const s: number = m.index + m[0].indexOf(m[1]); // Replace @import statements
const e: number = s + m[1].length; css = css.replace(
idxs.push([s, e]); /@import\s+(url\(\s*(['"]?)(.*?)\2\s*\)|(['"])(.*?)\4)([^;]*);?/gs,
} (match, _, quote1, url1, quote2, url2, media) => {
const i2 = css.matchAll(re2); let url = url1 || url2;
// @ts-ignore let newurl = rewriter(url.trim());
for (let m of i2) { let quote = quote1 || quote2 || '';
// @ts-ignore return `@import ${
const s = m.index + m[0].indexOf(m[1]); quote ? `url(${quote}${newurl}${quote})` : `"${newurl}"`
const e = s + m[1].length; }${media};`;
idxs.push([s, e]) }
} );
return idxs.reverse()
} // Ensure the CSS ends with a semicolon
function unquote(str: string): [string, string] { const hasSemi = css.trim().endsWith(';');
if (str.length <= 2) { return hasSemi ? css : css + ';';
return [str, ""]
}
if (str[0] == '"' && str[str.length-1] == '"') {
return [ str.substring(1, str.length-1), "\""];
}
if (str[0] == '\'' && str[str.length-1] == '\'') {
return [ str.substring(1, str.length-1), "'" ];
}
return [str, ""]
}
function rewriteCSSLinks(css: string, rewriter: (rawurl: string) => string): string {
for (let idx of cssUrlsIndex(css)) {
const f = idx[0]
const t = idx[1]
const [ rawurl, q ] = unquote(css.substring(f, t));
css = css.substring(0,f) + q + rewriter(rawurl) + q + css.substring(t);
}
return css
} }
function rewritePseudoclasses(css: string): string { function rewritePseudoclasses(css: string): string {
return css return css
.replace(/:hover/g, ".-openreplay-hover") .replace(/:hover/g, '.-openreplay-hover')
.replace(/:focus/g, ".-openreplay-focus") .replace(/:focus/g, '.-openreplay-focus');
} }
export function resolveCSS(baseURL: string, css: string): string { export function resolveCSS(baseURL: string, css: string): string {
return rewritePseudoclasses( return rewritePseudoclasses(
rewriteCSSLinks(css, rawurl => resolveURL(baseURL, rawurl)) rewriteCSSLinks(css, (rawurl) => resolveURL(baseURL, rawurl))
); );
} }