Skip to content

Commit 40f15a5

Browse files
committed
use document.baseURI for sheetHref when handling inline styles
1 parent fd9d274 commit 40f15a5

File tree

3 files changed

+56
-1
lines changed

3 files changed

+56
-1
lines changed

.changeset/twelve-nails-occur.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"rrweb-snapshot": patch
3+
---
4+
5+
Prefer the <base href> for resolving inline <style> URLs, falling back to document location if not present.

packages/rrweb-snapshot/src/utils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ export function stringifyStylesheet(s: CSSStyleSheet): string | null {
120120
let sheetHref = s.href;
121121
if (!sheetHref && s.ownerNode && s.ownerNode.ownerDocument) {
122122
// an inline <style> element
123-
sheetHref = s.ownerNode.ownerDocument.location.href;
123+
sheetHref = s.ownerNode.ownerDocument.baseURI;
124124
}
125125
const stringifiedRules = Array.from(rules, (rule: CSSRule) =>
126126
stringifyRule(rule, sheetHref),

packages/rrweb-snapshot/test/utils.test.ts

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
extractFileExtension,
88
fixSafariColons,
99
isNodeMetaEqual,
10+
stringifyStylesheet
1011
} from '../src/utils';
1112
import { NodeType } from '@rrweb/types';
1213
import type { serializedNode, serializedNodeWithId } from '@rrweb/types';
@@ -280,4 +281,53 @@ describe('utils', () => {
280281
expect(out3).toEqual('[data-aa\\:other] { color: red; }');
281282
});
282283
});
284+
285+
describe('stringifyStylesheet', () => {
286+
it('returns null if rules are missing', () => {
287+
const mockSheet = {
288+
rules: null,
289+
cssRules: null,
290+
} as unknown as CSSStyleSheet;
291+
expect(stringifyStylesheet(mockSheet)).toBeNull();
292+
});
293+
294+
it('stringifies rules using .cssRules if .rules is missing', () => {
295+
const mockRule1 = { cssText: 'div { margin: 0; }' } as CSSRule;
296+
const mockSheet = {
297+
cssRules: [mockRule1],
298+
href: 'https://example.com/main.css',
299+
} as unknown as CSSStyleSheet;
300+
expect(stringifyStylesheet(mockSheet)).toBe('div { margin: 0; }');
301+
});
302+
303+
it('uses ownerNode.ownerDocument.baseURI for inline styles', () => {
304+
const mockFontFaceRule = {
305+
cssText: `
306+
@font-face {
307+
font-family: 'MockFont';
308+
src: url('../fonts/mockfont.woff2') format('woff2');
309+
font-weight: normal;
310+
font-style: normal;
311+
}
312+
`
313+
} as CSSRule;
314+
const mockOwnerDocument = {
315+
location: { href: 'https://example.com/page.html' },
316+
baseURI: 'https://example.com/fonts/',
317+
} as unknown as Document;
318+
const mockOwnerNode = {
319+
ownerDocument: mockOwnerDocument,
320+
} as unknown as Node;
321+
const mockSheet = {
322+
cssRules: [mockFontFaceRule],
323+
href: null,
324+
ownerNode: mockOwnerNode,
325+
} as unknown as CSSStyleSheet;
326+
expect(
327+
stringifyStylesheet(mockSheet)?.replace(/\s+/g, ' ').trim()
328+
).toEqual(
329+
"@font-face { font-family: 'MockFont'; src: url('https://example.com/fonts/mockfont.woff2') format('woff2'); font-weight: normal; font-style: normal; }"
330+
);
331+
});
332+
});
283333
});

0 commit comments

Comments
 (0)