Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support constructed stylesheets in shadow DOM instances #3

Merged
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,16 @@

rrweb refers to 'record and replay the web', which is a tool for recording and replaying users' interactions on the web.

## Publishing @chromaui/rrweb-snapshot

Chromatic maintains this fork of `rrweb-io/rrweb` solely to publish a version of `rrweb-snapshot` that supports constructable stylesheets for Chromatic e2e capture purposes.

To distinguish Chromatic-specific builds from those coming from rrweb-io, a `-noAbsolute` label is appended to the end of the package version. If more than one Chromatic build is produced based off of the same rrweb-io version, a number is appended to the end of that label (e.g. `2.0.0-alpha.17-noAbsolute.1`).

1. In `packages/rrweb-snapshot/package.json`, set the appropriate `-noAbsolute.X` version
2. CD to `packages/rrweb-snapshot`
3. Run `npm publish`

## Guide

[**📚 Read the rrweb guide here. 📚**](./guide.md)
Expand Down
12 changes: 6 additions & 6 deletions packages/rrweb-snapshot/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "rrweb-snapshot",
"version": "2.0.0-alpha.17",
"name": "@chromaui/rrweb-snapshot",
"version": "2.0.0-alpha.17-noAbsolute",
"description": "rrweb's component to take a snapshot of DOM, aka DOM serializer",
"scripts": {
"prepare": "npm run prepack",
Expand All @@ -12,15 +12,15 @@
"test:update": "yarn build && vitest run --update",
"bench": "vite build && vitest bench",
"dev": "vite build --watch",
"build": "yarn turbo prepublish -F rrweb-snapshot",
"build": "yarn turbo prepublish -F @chromaui/rrweb-snapshot",
"check-types": "tsc --noEmit",
"prepublish": "yarn check-types && vite build",
"lint": "yarn eslint src"
},
"type": "module",
"repository": {
"type": "git",
"url": "git+https://github.com/rrweb-io/rrweb.git"
"url": "git+https://github.com/chromaui/rrweb.git"
},
"keywords": [
"rrweb",
Expand Down Expand Up @@ -50,9 +50,9 @@
"author": "[email protected]",
"license": "MIT",
"bugs": {
"url": "https://github.com/rrweb-io/rrweb/issues"
"url": "https://github.com/chromaui/rrweb/issues"
},
"homepage": "https://github.com/rrweb-io/rrweb/tree/master/packages/rrweb-snapshot#readme",
"homepage": "https://github.com/chromaui/rrweb/tree/master/packages/rrweb-snapshot#readme",
"devDependencies": {
"@rrweb/utils": "^2.0.0-alpha.17",
"@types/jsdom": "^20.0.0",
Expand Down
9 changes: 8 additions & 1 deletion packages/rrweb-snapshot/src/rebuild.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ export function buildStyleNode(
}

function buildNode(
n: serializedNodeWithId,
n: serializedNodeWithId & { chromaticAdoptedStylesheets?: string[] },
options: {
doc: Document;
hackCss: boolean;
Expand Down Expand Up @@ -380,6 +380,13 @@ function buildNode(
*/
if (!node.shadowRoot) {
node.attachShadow({ mode: 'open' });
n.chromaticAdoptedStylesheets?.forEach(
(chromaticAdoptedStylesheet) => {
const styleSheet = new CSSStyleSheet();
styleSheet.replaceSync(chromaticAdoptedStylesheet);
node.shadowRoot?.adoptedStyleSheets.push(styleSheet);
},
);
} else {
while (node.shadowRoot.firstChild) {
node.shadowRoot.removeChild(node.shadowRoot.firstChild);
Expand Down
14 changes: 12 additions & 2 deletions packages/rrweb-snapshot/src/snapshot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@
// should warn? maybe a text node isn't attached to a parent node yet?
return false;
} else {
el = dom.parentElement(node)!;

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

View workflow job for this annotation

GitHub Actions / ESLint Check and Report Upload

Forbidden non-null assertion

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

View workflow job for this annotation

GitHub Actions / ESLint Check and Report Upload

Forbidden non-null assertion

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

View workflow job for this annotation

GitHub Actions / ESLint Report Analysis

packages/rrweb-snapshot/src/snapshot.ts#L283

[@typescript-eslint/no-non-null-assertion] Forbidden non-null assertion.
}
try {
if (typeof maskTextClass === 'string') {
Expand Down Expand Up @@ -700,10 +700,10 @@
const recordInlineImage = () => {
image.removeEventListener('load', recordInlineImage);
try {
canvasService!.width = image.naturalWidth;

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

View workflow job for this annotation

GitHub Actions / ESLint Check and Report Upload

Forbidden non-null assertion

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

View workflow job for this annotation

GitHub Actions / ESLint Check and Report Upload

Forbidden non-null assertion

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

View workflow job for this annotation

GitHub Actions / ESLint Report Analysis

packages/rrweb-snapshot/src/snapshot.ts#L703

[@typescript-eslint/no-non-null-assertion] Forbidden non-null assertion.
canvasService!.height = image.naturalHeight;

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

View workflow job for this annotation

GitHub Actions / ESLint Check and Report Upload

Forbidden non-null assertion

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

View workflow job for this annotation

GitHub Actions / ESLint Check and Report Upload

Forbidden non-null assertion

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

View workflow job for this annotation

GitHub Actions / ESLint Report Analysis

packages/rrweb-snapshot/src/snapshot.ts#L704

[@typescript-eslint/no-non-null-assertion] Forbidden non-null assertion.
canvasCtx!.drawImage(image, 0, 0);

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

View workflow job for this annotation

GitHub Actions / ESLint Check and Report Upload

Forbidden non-null assertion

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

View workflow job for this annotation

GitHub Actions / ESLint Check and Report Upload

Forbidden non-null assertion

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

View workflow job for this annotation

GitHub Actions / ESLint Report Analysis

packages/rrweb-snapshot/src/snapshot.ts#L705

[@typescript-eslint/no-non-null-assertion] Forbidden non-null assertion.
attributes.rr_dataURL = canvasService!.toDataURL(

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

View workflow job for this annotation

GitHub Actions / ESLint Check and Report Upload

Forbidden non-null assertion

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

View workflow job for this annotation

GitHub Actions / ESLint Check and Report Upload

Forbidden non-null assertion

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

View workflow job for this annotation

GitHub Actions / ESLint Report Analysis

packages/rrweb-snapshot/src/snapshot.ts#L706

[@typescript-eslint/no-non-null-assertion] Forbidden non-null assertion.
dataURLOptions.type,
dataURLOptions.quality,
);
Expand Down Expand Up @@ -1008,7 +1008,10 @@
id = genId();
}

const serializedNode = Object.assign(_serializedNode, { id });
const serializedNode: serializedNode & {
id: number;
chromaticAdoptedStylesheets?: Array<string | null>;
} = Object.assign(_serializedNode, { id });
// add IGNORED_NODE to mirror to track nextSiblings
mirror.add(n, serializedNode);

Expand All @@ -1025,8 +1028,15 @@
// this property was not needed in replay side
delete serializedNode.needBlock;
const shadowRootEl = dom.shadowRoot(n);
if (shadowRootEl && isNativeShadowDom(shadowRootEl))
if (shadowRootEl && isNativeShadowDom(shadowRootEl)) {
serializedNode.isShadowHost = true;
if (shadowRootEl.adoptedStyleSheets.length > 0) {
serializedNode.chromaticAdoptedStylesheets =
shadowRootEl.adoptedStyleSheets.map((stylesheet) =>
stringifyStylesheet(stylesheet),
);
}
}
}
if (
(serializedNode.type === NodeType.Document ||
Expand Down
2 changes: 2 additions & 0 deletions packages/rrweb/src/record/mutation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,8 @@
onStylesheetLoad: (link, childSn) => {
this.stylesheetManager.attachLinkElement(link, childSn);
},
// @ts-expect-error cssCaptured isn't specified as an accepted property,
// but we didn't touch anything near here, so ignoring for now
cssCaptured,
});
if (sn) {
Expand All @@ -362,13 +364,13 @@
};

while (this.mapRemoves.length) {
this.mirror.removeNodeFromMap(this.mapRemoves.shift()!);

Check warning on line 367 in packages/rrweb/src/record/mutation.ts

View workflow job for this annotation

GitHub Actions / ESLint Check and Report Upload

Forbidden non-null assertion

Check warning on line 367 in packages/rrweb/src/record/mutation.ts

View workflow job for this annotation

GitHub Actions / ESLint Check and Report Upload

Forbidden non-null assertion

Check warning on line 367 in packages/rrweb/src/record/mutation.ts

View workflow job for this annotation

GitHub Actions / ESLint Report Analysis

packages/rrweb/src/record/mutation.ts#L367

[@typescript-eslint/no-non-null-assertion] Forbidden non-null assertion.
}

for (const n of this.movedSet) {
if (
isParentRemoved(this.removes, n, this.mirror) &&
!this.movedSet.has(dom.parentNode(n)!)

Check warning on line 373 in packages/rrweb/src/record/mutation.ts

View workflow job for this annotation

GitHub Actions / ESLint Report Analysis

packages/rrweb/src/record/mutation.ts#L373

[@typescript-eslint/no-non-null-assertion] Forbidden non-null assertion.
) {
continue;
}
Expand Down
21 changes: 17 additions & 4 deletions packages/rrweb/test/__snapshots__/record.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -628,7 +628,10 @@ exports[`record > captures adopted stylesheets in nested shadow doms and iframes
\\"childNodes\\": [],
\\"rootId\\": 29,
\\"id\\": 33,
\\"isShadowHost\\": true
\\"isShadowHost\\": true,
\\"chromaticAdoptedStylesheets\\": [
\\"div { font-size: large; }\\"
]
}
],
\\"rootId\\": 29,
Expand Down Expand Up @@ -849,7 +852,11 @@ exports[`record > captures adopted stylesheets in shadow doms and iframe 1`] = `
}
],
\\"id\\": 10,
\\"isShadowHost\\": true
\\"isShadowHost\\": true,
\\"chromaticAdoptedStylesheets\\": [
\\"div { color: yellow; }h2 { color: orange; }h3 { font-size: larger; }\\",
\\"span { color: red; }\\"
]
},
{
\\"type\\": 3,
Expand Down Expand Up @@ -1204,7 +1211,10 @@ exports[`record > captures adopted stylesheets of shadow doms in checkout full s
}
],
\\"id\\": 7,
\\"isShadowHost\\": true
\\"isShadowHost\\": true,
\\"chromaticAdoptedStylesheets\\": [
\\"h1 { color: blue; }\\"
]
},
{
\\"type\\": 3,
Expand Down Expand Up @@ -1304,7 +1314,10 @@ exports[`record > captures adopted stylesheets of shadow doms in checkout full s
}
],
\\"id\\": 7,
\\"isShadowHost\\": true
\\"isShadowHost\\": true,
\\"chromaticAdoptedStylesheets\\": [
\\"h1 { color: blue; }\\"
]
},
{
\\"type\\": 3,
Expand Down
Loading