Skip to content

Commit 43689b7

Browse files
committed
use node.baseURI for sheetHref when handling inline styles
1 parent fd9d274 commit 43689b7

File tree

4 files changed

+58
-2
lines changed

4 files changed

+58
-2
lines changed

.changeset/angry-roses-beam.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+
use ownerNode baseURI for stringifying stylesheet href

.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: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,9 +118,9 @@ export function stringifyStylesheet(s: CSSStyleSheet): string | null {
118118
return null;
119119
}
120120
let sheetHref = s.href;
121-
if (!sheetHref && s.ownerNode && s.ownerNode.ownerDocument) {
121+
if (!sheetHref && s.ownerNode) {
122122
// an inline <style> element
123-
sheetHref = s.ownerNode.ownerDocument.location.href;
123+
sheetHref = s.ownerNode.baseURI;
124124
}
125125
const stringifiedRules = Array.from(rules, (rule: CSSRule) =>
126126
stringifyRule(rule, sheetHref),

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

Lines changed: 46 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,49 @@ 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.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 mockOwnerNode = {
315+
baseURI: 'https://example.com/fonts/',
316+
} as unknown as Node;
317+
const mockSheet = {
318+
cssRules: [mockFontFaceRule],
319+
href: null,
320+
ownerNode: mockOwnerNode,
321+
} as unknown as CSSStyleSheet;
322+
expect(
323+
stringifyStylesheet(mockSheet)?.replace(/\s+/g, ' ').trim()
324+
).toEqual(
325+
"@font-face { font-family: 'MockFont'; src: url('https://example.com/fonts/mockfont.woff2') format('woff2'); font-weight: normal; font-style: normal; }"
326+
);
327+
});
328+
});
283329
});

0 commit comments

Comments
 (0)