From 79bdc0a06c5a211e3663887ef01c0f0add665846 Mon Sep 17 00:00:00 2001 From: Eoghan Murray Date: Sun, 16 Nov 2025 07:27:57 +0000 Subject: [PATCH 1/2] Prefer `includes` formulation for brevity and as it composes better (easier to understand) in longer boolean expressions with && --- packages/rrweb-snapshot/src/snapshot.ts | 46 +++++++++++-------------- packages/rrweb/src/record/index.ts | 44 +++++++++++------------ 2 files changed, 41 insertions(+), 49 deletions(-) diff --git a/packages/rrweb-snapshot/src/snapshot.ts b/packages/rrweb-snapshot/src/snapshot.ts index 8c29fa0d7f..0ba671023b 100644 --- a/packages/rrweb-snapshot/src/snapshot.ts +++ b/packages/rrweb-snapshot/src/snapshot.ts @@ -190,10 +190,7 @@ export function transformAttribute( } else if (name === 'xlink:href' && value[0] !== '#') { // xlink:href starts with # is an id pointer return absoluteToDoc(doc, value); - } else if ( - name === 'background' && - (tagName === 'table' || tagName === 'td' || tagName === 'th') - ) { + } else if (name === 'background' && ['table', 'td', 'th'].includes(tagName)) { return absoluteToDoc(doc, value); } else if (name === 'srcset') { return getAbsoluteSrcsetString(doc, value); @@ -212,7 +209,7 @@ export function ignoreAttribute( // eslint-disable-next-line @typescript-eslint/no-unused-vars _value: unknown, ): boolean { - return (tagName === 'video' || tagName === 'audio') && name === 'autoplay'; + return ['video', 'audio'].includes(tagName) && name === 'autoplay'; } export function _isBlockedElement( @@ -616,7 +613,7 @@ function serializeElementNode( } } // form fields - if (tagName === 'input' || tagName === 'textarea' || tagName === 'select') { + if (['input', 'textarea', 'select'].includes(tagName)) { const value = (n as HTMLInputElement | HTMLTextAreaElement).value; const checked = (n as HTMLInputElement).checked; if ( @@ -733,7 +730,7 @@ function serializeElementNode( else image.addEventListener('load', recordInlineImage); } // media elements - if (tagName === 'audio' || tagName === 'video') { + if (['audio', 'video'].includes(tagName)) { const mediaAttributes = attributes as mediaAttributes; mediaAttributes.rr_mediaState = (n as HTMLMediaElement).paused ? 'paused' @@ -1289,24 +1286,23 @@ function snapshot( password: true, } : maskAllInputs; - const slimDOMOptions: SlimDOMOptions = - slimDOM === true || slimDOM === 'all' - ? // if true: set of sensible options that should not throw away any information - { - script: true, - comment: true, - headFavicon: true, - headWhitespace: true, - headMetaDescKeywords: slimDOM === 'all', // destructive - headMetaSocial: true, - headMetaRobots: true, - headMetaHttpEquiv: true, - headMetaAuthorship: true, - headMetaVerification: true, - } - : slimDOM === false - ? {} - : slimDOM; + const slimDOMOptions: SlimDOMOptions = [true, 'all'].includes(slimDOM) + ? // if true: set of sensible options that should not throw away any information + { + script: true, + comment: true, + headFavicon: true, + headWhitespace: true, + headMetaDescKeywords: slimDOM === 'all', // destructive + headMetaSocial: true, + headMetaRobots: true, + headMetaHttpEquiv: true, + headMetaAuthorship: true, + headMetaVerification: true, + } + : slimDOM === false + ? {} + : slimDOM; return serializeNodeWithId(n, { doc: n, mirror, diff --git a/packages/rrweb/src/record/index.ts b/packages/rrweb/src/record/index.ts index 65da8ec801..b9ef241142 100644 --- a/packages/rrweb/src/record/index.ts +++ b/packages/rrweb/src/record/index.ts @@ -160,26 +160,25 @@ function record( ? _maskInputOptions : { password: true }; - const slimDOMOptions: SlimDOMOptions = - _slimDOMOptions === true || _slimDOMOptions === 'all' - ? { - script: true, - comment: true, - headFavicon: true, - headWhitespace: true, - headMetaSocial: true, - headMetaRobots: true, - headMetaHttpEquiv: true, - headMetaVerification: true, - // the following are off for slimDOMOptions === true, - // as they destroy some (hidden) info: - headMetaAuthorship: _slimDOMOptions === 'all', - headMetaDescKeywords: _slimDOMOptions === 'all', - headTitleMutations: _slimDOMOptions === 'all', - } - : _slimDOMOptions - ? _slimDOMOptions - : {}; + const slimDOMOptions: SlimDOMOptions = [true, 'all'].includes(_slimDOMOptions) + ? { + script: true, + comment: true, + headFavicon: true, + headWhitespace: true, + headMetaSocial: true, + headMetaRobots: true, + headMetaHttpEquiv: true, + headMetaVerification: true, + // the following are off for slimDOMOptions === true, + // as they destroy some (hidden) info: + headMetaAuthorship: _slimDOMOptions === 'all', + headMetaDescKeywords: _slimDOMOptions === 'all', + headTitleMutations: _slimDOMOptions === 'all', + } + : _slimDOMOptions + ? _slimDOMOptions + : {}; polyfill(); @@ -587,10 +586,7 @@ function record( handlers.push(observe(document)); recording = true; }; - if ( - document.readyState === 'interactive' || - document.readyState === 'complete' - ) { + if (['interactive', 'complete'].includes(document.readyState)) { init(); } else { handlers.push( From cfe1a23c1416d1dc032058cbaf296a5ba81775b9 Mon Sep 17 00:00:00 2001 From: Eoghan Murray Date: Sun, 16 Nov 2025 07:42:01 +0000 Subject: [PATCH 2/2] Noticed two different interpretations of `headMetaAuthorship` under slimDOMOptions; take the opportunity to cleanup and merge code --- .changeset/slimdom-defaults-refactor.md | 2 ++ packages/rrweb-snapshot/src/index.ts | 2 ++ packages/rrweb-snapshot/src/snapshot.ts | 45 +++++++++++++++---------- packages/rrweb/src/record/index.ts | 22 ++---------- 4 files changed, 34 insertions(+), 37 deletions(-) create mode 100644 .changeset/slimdom-defaults-refactor.md diff --git a/.changeset/slimdom-defaults-refactor.md b/.changeset/slimdom-defaults-refactor.md new file mode 100644 index 0000000000..a845151cc8 --- /dev/null +++ b/.changeset/slimdom-defaults-refactor.md @@ -0,0 +1,2 @@ +--- +--- diff --git a/packages/rrweb-snapshot/src/index.ts b/packages/rrweb-snapshot/src/index.ts index c9f91a9100..f1d4e680a4 100644 --- a/packages/rrweb-snapshot/src/index.ts +++ b/packages/rrweb-snapshot/src/index.ts @@ -2,6 +2,7 @@ import snapshot, { serializeNodeWithId, transformAttribute, ignoreAttribute, + slimDOMDefaults, visitSnapshot, cleanupSnapshot, needMaskingText, @@ -26,6 +27,7 @@ export { createCache, transformAttribute, ignoreAttribute, + slimDOMDefaults, visitSnapshot, cleanupSnapshot, needMaskingText, diff --git a/packages/rrweb-snapshot/src/snapshot.ts b/packages/rrweb-snapshot/src/snapshot.ts index 0ba671023b..b5426a1751 100644 --- a/packages/rrweb-snapshot/src/snapshot.ts +++ b/packages/rrweb-snapshot/src/snapshot.ts @@ -802,6 +802,32 @@ function lowerIfExists( } } +export function slimDOMDefaults( + _slimDOMOptions: SlimDOMOptions | 'all' | true | false | undefined, +) { + if (_slimDOMOptions === true || _slimDOMOptions === 'all') { + // if true: set of sensible options that should not throw away any information + return { + script: true, + comment: true, + headFavicon: true, + headWhitespace: true, + headMetaSocial: true, + headMetaRobots: true, + headMetaHttpEquiv: true, + headMetaVerification: true, + // the following are off for slimDOMOptions === true, + // as they destroy some (hidden) info: + headMetaAuthorship: _slimDOMOptions === 'all', + headMetaDescKeywords: _slimDOMOptions === 'all', + headTitleMutations: _slimDOMOptions === 'all', + }; + } else if (_slimDOMOptions) { + return _slimDOMOptions; + } + return {}; +} + function slimDOMExcluded( sn: serializedNode, slimDOMOptions: SlimDOMOptions, @@ -1286,23 +1312,8 @@ function snapshot( password: true, } : maskAllInputs; - const slimDOMOptions: SlimDOMOptions = [true, 'all'].includes(slimDOM) - ? // if true: set of sensible options that should not throw away any information - { - script: true, - comment: true, - headFavicon: true, - headWhitespace: true, - headMetaDescKeywords: slimDOM === 'all', // destructive - headMetaSocial: true, - headMetaRobots: true, - headMetaHttpEquiv: true, - headMetaAuthorship: true, - headMetaVerification: true, - } - : slimDOM === false - ? {} - : slimDOM; + const slimDOMOptions = slimDOMDefaults(slimDOM); + return serializeNodeWithId(n, { doc: n, mirror, diff --git a/packages/rrweb/src/record/index.ts b/packages/rrweb/src/record/index.ts index b9ef241142..fac5359790 100644 --- a/packages/rrweb/src/record/index.ts +++ b/packages/rrweb/src/record/index.ts @@ -1,7 +1,7 @@ import { snapshot, + slimDOMDefaults, type MaskInputOptions, - type SlimDOMOptions, createMirror, } from 'rrweb-snapshot'; import { initObservers, mutationBuffers } from './observer'; @@ -160,25 +160,7 @@ function record( ? _maskInputOptions : { password: true }; - const slimDOMOptions: SlimDOMOptions = [true, 'all'].includes(_slimDOMOptions) - ? { - script: true, - comment: true, - headFavicon: true, - headWhitespace: true, - headMetaSocial: true, - headMetaRobots: true, - headMetaHttpEquiv: true, - headMetaVerification: true, - // the following are off for slimDOMOptions === true, - // as they destroy some (hidden) info: - headMetaAuthorship: _slimDOMOptions === 'all', - headMetaDescKeywords: _slimDOMOptions === 'all', - headTitleMutations: _slimDOMOptions === 'all', - } - : _slimDOMOptions - ? _slimDOMOptions - : {}; + const slimDOMOptions = slimDOMDefaults(_slimDOMOptions); polyfill();