Slim dom defaults refactor (#1758)

* Prefer `includes` formulation for brevity and as it composes better (easier to understand) in longer boolean expressions with &&

* Noticed two different interpretations of `headMetaAuthorship` under slimDOMOptions; take the opportunity to cleanup and merge code
This commit is contained in:
Eoghan Murray
2026-04-01 12:00:00 +08:00
committed by GitHub
parent 3c1989a5f7
commit aa1abaf200
4 changed files with 39 additions and 50 deletions

View File

@@ -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,

View File

@@ -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'
@@ -805,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,
@@ -1289,24 +1312,8 @@ 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 = slimDOMDefaults(slimDOM);
return serializeNodeWithId(n, {
doc: n,
mirror,

View File

@@ -1,7 +1,7 @@
import {
snapshot,
slimDOMDefaults,
type MaskInputOptions,
type SlimDOMOptions,
createMirror,
} from 'rrweb-snapshot';
import { initObservers, mutationBuffers } from './observer';
@@ -160,26 +160,7 @@ function record<T = eventWithTime>(
? _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 = slimDOMDefaults(_slimDOMOptions);
polyfill();
@@ -587,10 +568,7 @@ function record<T = eventWithTime>(
handlers.push(observe(document));
recording = true;
};
if (
document.readyState === 'interactive' ||
document.readyState === 'complete'
) {
if (['interactive', 'complete'].includes(document.readyState)) {
init();
} else {
handlers.push(