Initial commit

This commit is contained in:
Samraaj Bath
2026-06-29 15:11:48 -07:00
commit 66dfdcc58d
404 changed files with 45970 additions and 0 deletions
+121
View File
@@ -0,0 +1,121 @@
// Dumps every same-origin CSS rule as { selector, cssText } into __CLONE_CAPTURE__.cssRules,
// and extracts every url(...) asset reference (resolved to absolute URLs) into
// __CLONE_CAPTURE__.cssAssets. Catches background-images set in stylesheets that the
// response listener missed (e.g. @media-gated, ::before, mask-image, list-style-image, cursor).
(() => {
function isSameOrigin(href) {
if (!href) return true;
try {
const u = new URL(href, location.href);
return u.origin === location.origin;
} catch {
return false;
}
}
function resolveUrl(raw, baseHref) {
if (!raw) return null;
let s = raw.trim();
if (s.startsWith('"') || s.startsWith("'")) s = s.slice(1, -1);
if (s.startsWith('data:') || s.startsWith('#')) return null;
try {
return new URL(s, baseHref || location.href).href;
} catch {
return null;
}
}
function collectFromRules(rules, baseHref, out) {
if (!rules) return;
for (const rule of rules) {
const type = rule.constructor?.name || '';
if (type === 'CSSStyleRule') {
const text = rule.cssText || '';
out.rules.push({ selector: rule.selectorText, cssText: text, baseHref });
const urls = text.match(/url\(\s*([^)]+?)\s*\)/g) || [];
for (const m of urls) {
const inner = m
.slice(4, -1)
.trim()
.replace(/^['"]|['"]$/g, '');
const abs = resolveUrl(inner, baseHref);
if (abs && !out.assetSet.has(abs)) {
out.assetSet.add(abs);
out.assets.push({ source_url: abs, selector: rule.selectorText });
}
}
} else if (type === 'CSSMediaRule' || type === 'CSSSupportsRule' || type === 'CSSContainerRule') {
const condition = rule.conditionText || rule.media?.mediaText;
out.media.push({ condition, type });
collectFromRules(rule.cssRules, baseHref, out);
} else if (type === 'CSSImportRule') {
// Recurse into imported stylesheet if same-origin and accessible
try {
const importedHref = rule.styleSheet?.href || baseHref;
if (isSameOrigin(importedHref)) {
collectFromRules(rule.styleSheet?.cssRules, importedHref, out);
}
} catch {}
} else if (type === 'CSSFontFaceRule') {
const text = rule.cssText || '';
out.fontFaces.push({ cssText: text, baseHref });
const urls = text.match(/url\(\s*([^)]+?)\s*\)/g) || [];
for (const m of urls) {
const inner = m
.slice(4, -1)
.trim()
.replace(/^['"]|['"]$/g, '');
const abs = resolveUrl(inner, baseHref);
if (abs && !out.assetSet.has(abs)) {
out.assetSet.add(abs);
out.assets.push({ source_url: abs, selector: '@font-face' });
}
}
} else if (type === 'CSSKeyframesRule') {
const frames = [];
for (const k of rule.cssRules || []) frames.push({ key: k.keyText, cssText: k.style?.cssText || '' });
out.keyframes.push({ name: rule.name, frames, baseHref });
} else if (rule.cssRules) {
collectFromRules(rule.cssRules, baseHref, out);
}
}
}
function collect() {
const out = {
rules: [],
media: [],
fontFaces: [],
keyframes: [],
assets: [],
assetSet: new Set(),
crossOrigin: 0,
};
for (const sheet of document.styleSheets) {
const baseHref = sheet.href || location.href;
let rules;
try {
rules = sheet.cssRules;
} catch {
out.crossOrigin += 1;
continue;
}
collectFromRules(rules, baseHref, out);
}
delete out.assetSet;
window.__CLONE_CAPTURE__.cssRules = out;
}
const prevFinalize = window.__CLONE_FINALIZE__;
window.__CLONE_FINALIZE__ = function () {
if (prevFinalize)
try {
prevFinalize();
} catch {}
try {
collect();
} catch (e) {
window.__CLONE_CAPTURE__.cssRules = { error: String(e) };
}
};
})();