Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/few-trees-jog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"rrweb-snapshot": patch
---

fix absolutifyURLs function calculation error in some scenario
2 changes: 1 addition & 1 deletion packages/rrweb-snapshot/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@
* Browsers sometimes incorrectly escape `@import` on `.cssText` statements.
* This function tries to correct the escaping.
* more info: https://bugs.chromium.org/p/chromium/issues/detail?id=1472259
* @param cssImportRule

Check warning on line 83 in packages/rrweb-snapshot/src/utils.ts

View workflow job for this annotation

GitHub Actions / ESLint Report Analysis

packages/rrweb-snapshot/src/utils.ts#L83

[tsdoc/syntax] tsdoc-param-tag-missing-hyphen: The @param block should be followed by a parameter name and then a hyphen
* @returns `cssText` with browser inconsistencies fixed, or null if not applicable.
*/
export function escapeImportStatement(rule: CSSImportRule): string {
Expand Down Expand Up @@ -429,7 +429,7 @@
extractOrigin(href) + filePath
}${maybeQuote})`;
}
const stack = href.split('/');
const stack = href.split('#')[0].split('/');
const parts = filePath.split('/');
stack.pop();
for (const part of parts) {
Expand Down Expand Up @@ -488,7 +488,7 @@
typeof childNodes[i].textContent === 'string'
) {
const textContentNorm = normalizeCssString(
childNodes[i].textContent!,

Check warning on line 491 in packages/rrweb-snapshot/src/utils.ts

View workflow job for this annotation

GitHub Actions / ESLint Report Analysis

packages/rrweb-snapshot/src/utils.ts#L491

[@typescript-eslint/no-non-null-assertion] Forbidden non-null assertion.
_testNoPxNorm,
);
const jLimit = 100; // how many iterations for the first part of searching
Expand Down
170 changes: 86 additions & 84 deletions packages/rrweb-snapshot/test/snapshot.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,102 +28,104 @@ const serializeNode = (node: Node): serializedNodeWithId | null => {
};

describe('absolute url to stylesheet', () => {
const href = 'http://localhost/css/style.css';

it('can handle relative path', () => {
expect(absolutifyURLs('url(a.jpg)', href)).toEqual(
`url(http://localhost/css/a.jpg)`,
);
});
const styleSheetHref = 'http://localhost/css/style.css';
const inlineStyleHref = 'http://localhost/css/#/spa-route'; // inline style fallback to node.baseURL
[styleSheetHref, inlineStyleHref].forEach((href) => {
it('can handle relative path', () => {
expect(absolutifyURLs('url(a.jpg)', href)).toEqual(
`url(http://localhost/css/a.jpg)`,
);
});

it('can handle same level path', () => {
expect(absolutifyURLs('url("./a.jpg")', href)).toEqual(
`url("http://localhost/css/a.jpg")`,
);
});
it('can handle same level path', () => {
expect(absolutifyURLs('url("./a.jpg")', href)).toEqual(
`url("http://localhost/css/a.jpg")`,
);
});

it('can handle parent level path', () => {
expect(absolutifyURLs('url("../a.jpg")', href)).toEqual(
`url("http://localhost/a.jpg")`,
);
});
it('can handle parent level path', () => {
expect(absolutifyURLs('url("../a.jpg")', href)).toEqual(
`url("http://localhost/a.jpg")`,
);
});

it('can handle absolute path', () => {
expect(absolutifyURLs('url("/a.jpg")', href)).toEqual(
`url("http://localhost/a.jpg")`,
);
});
it('can handle absolute path', () => {
expect(absolutifyURLs('url("/a.jpg")', href)).toEqual(
`url("http://localhost/a.jpg")`,
);
});

it('can handle external path', () => {
expect(absolutifyURLs('url("http://localhost/a.jpg")', href)).toEqual(
`url("http://localhost/a.jpg")`,
);
});
it('can handle external path', () => {
expect(absolutifyURLs('url("http://localhost/a.jpg")', href)).toEqual(
`url("http://localhost/a.jpg")`,
);
});

it('can handle single quote path', () => {
expect(absolutifyURLs(`url('./a.jpg')`, href)).toEqual(
`url('http://localhost/css/a.jpg')`,
);
});
it('can handle single quote path', () => {
expect(absolutifyURLs(`url('./a.jpg')`, href)).toEqual(
`url('http://localhost/css/a.jpg')`,
);
});

it('can handle no quote path', () => {
expect(absolutifyURLs('url(./a.jpg)', href)).toEqual(
`url(http://localhost/css/a.jpg)`,
);
});
it('can handle no quote path', () => {
expect(absolutifyURLs('url(./a.jpg)', href)).toEqual(
`url(http://localhost/css/a.jpg)`,
);
});

it('can handle multiple no quote paths', () => {
expect(
absolutifyURLs(
'background-image: url(images/b.jpg);background: #aabbcc url(images/a.jpg) 50% 50% repeat;',
href,
),
).toEqual(
`background-image: url(http://localhost/css/images/b.jpg);` +
`background: #aabbcc url(http://localhost/css/images/a.jpg) 50% 50% repeat;`,
);
});
it('can handle multiple no quote paths', () => {
expect(
absolutifyURLs(
'background-image: url(images/b.jpg);background: #aabbcc url(images/a.jpg) 50% 50% repeat;',
href,
),
).toEqual(
`background-image: url(http://localhost/css/images/b.jpg);` +
`background: #aabbcc url(http://localhost/css/images/a.jpg) 50% 50% repeat;`,
);
});

it('can handle data url image', () => {
expect(absolutifyURLs('url(data:image/gif;base64,ABC)', href)).toEqual(
'url(data:image/gif;base64,ABC)',
);
expect(
absolutifyURLs(
'url(data:application/font-woff;base64,d09GMgABAAAAAAm)',
href,
),
).toEqual('url(data:application/font-woff;base64,d09GMgABAAAAAAm)');
});
it('can handle data url image', () => {
expect(absolutifyURLs('url(data:image/gif;base64,ABC)', href)).toEqual(
'url(data:image/gif;base64,ABC)',
);
expect(
absolutifyURLs(
'url(data:application/font-woff;base64,d09GMgABAAAAAAm)',
href,
),
).toEqual('url(data:application/font-woff;base64,d09GMgABAAAAAAm)');
});

it('preserves quotes around inline svgs with spaces', () => {
expect(
absolutifyURLs(
it('preserves quotes around inline svgs with spaces', () => {
expect(
absolutifyURLs(
"url(\"data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%2328a745' d='M3'/%3E%3C/svg%3E\")",
href,
),
).toEqual(
"url(\"data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%2328a745' d='M3'/%3E%3C/svg%3E\")",
href,
),
).toEqual(
"url(\"data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%2328a745' d='M3'/%3E%3C/svg%3E\")",
);
expect(
absolutifyURLs(
);
expect(
absolutifyURLs(
'url(\'data:image/svg+xml;utf8,<svg width="28" height="32" viewBox="0 0 28 32" xmlns="http://www.w3.org/2000/svg"><path d="M27 14C28" fill="white"/></svg>\')',
href,
),
).toEqual(
'url(\'data:image/svg+xml;utf8,<svg width="28" height="32" viewBox="0 0 28 32" xmlns="http://www.w3.org/2000/svg"><path d="M27 14C28" fill="white"/></svg>\')',
href,
),
).toEqual(
'url(\'data:image/svg+xml;utf8,<svg width="28" height="32" viewBox="0 0 28 32" xmlns="http://www.w3.org/2000/svg"><path d="M27 14C28" fill="white"/></svg>\')',
);
expect(
absolutifyURLs(
);
expect(
absolutifyURLs(
'url("data:image/svg+xml;utf8,<svg width="28" height="32" viewBox="0 0 28 32" xmlns="http://www.w3.org/2000/svg"><path d="M27 14C28" fill="white"/></svg>")',
href,
),
).toEqual(
'url("data:image/svg+xml;utf8,<svg width="28" height="32" viewBox="0 0 28 32" xmlns="http://www.w3.org/2000/svg"><path d="M27 14C28" fill="white"/></svg>")',
href,
),
).toEqual(
'url("data:image/svg+xml;utf8,<svg width="28" height="32" viewBox="0 0 28 32" xmlns="http://www.w3.org/2000/svg"><path d="M27 14C28" fill="white"/></svg>")',
);
});
it('can handle empty path', () => {
expect(absolutifyURLs(`url('')`, href)).toEqual(`url('')`);
);
});
it('can handle empty path', () => {
expect(absolutifyURLs(`url('')`, href)).toEqual(`url('')`);
});
});
});

Expand Down
Loading