fix #811 expose inlineImages to record

This commit is contained in:
Yanzhen Yu
2026-04-01 12:00:00 +08:00
parent 73bfb6a59d
commit a7ea00cbec
10 changed files with 67 additions and 42 deletions

View File

@@ -132,7 +132,7 @@ setInterval(save, 10 * 1000);
`rrweb.record(config)` 的 config 部分接受以下参数 `rrweb.record(config)` 的 config 部分接受以下参数
| key | 默认值 | 功能 | | key | 默认值 | 功能 |
| -------------------- | ------------------ | ------------------------------------------------------------ | | -------------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| emit | 必填 | 获取当前录制的数据 | | emit | 必填 | 获取当前录制的数据 |
| checkoutEveryNth | - | 每 N 次事件重新制作一次全量快照<br />详见[“重新制作快照”](#重新制作快照)章节 | | checkoutEveryNth | - | 每 N 次事件重新制作一次全量快照<br />详见[“重新制作快照”](#重新制作快照)章节 |
| checkoutEveryNms | - | 每 N 毫秒重新制作一次全量快照<br />详见[“重新制作快照”](#重新制作快照)章节 | | checkoutEveryNms | - | 每 N 毫秒重新制作一次全量快照<br />详见[“重新制作快照”](#重新制作快照)章节 |
@@ -151,6 +151,7 @@ setInterval(save, 10 * 1000);
| packFn | - | 数据压缩函数,详见[优化存储策略](./docs/recipes/optimize-storage.zh_CN.md) | | packFn | - | 数据压缩函数,详见[优化存储策略](./docs/recipes/optimize-storage.zh_CN.md) |
| sampling | - | 数据抽样策略,详见[优化存储策略](./docs/recipes/optimize-storage.zh_CN.md) | | sampling | - | 数据抽样策略,详见[优化存储策略](./docs/recipes/optimize-storage.zh_CN.md) |
| recordCanvas | false | 是否记录 canvas 内容 | | recordCanvas | false | 是否记录 canvas 内容 |
| inlineImages | false | 是否将图片内容记内联录制 |
| collectFonts | false | 是否记录页面中的字体文件 | | collectFonts | false | 是否记录页面中的字体文件 |
| userTriggeredOnInput | false | [什么是 `userTriggered`](https://github.com/rrweb-io/rrweb/pull/495) | | userTriggeredOnInput | false | [什么是 `userTriggered`](https://github.com/rrweb-io/rrweb/pull/495) |
| plugins | [] | 加载插件以获得额外的录制功能. [什么是插件?](./docs/recipes/plugin.zh_CN.md) | | plugins | [] | 加载插件以获得额外的录制功能. [什么是插件?](./docs/recipes/plugin.zh_CN.md) |
@@ -282,7 +283,7 @@ replayer.pause(5000);
可以通过 `new rrweb.Replayer(events, options)` 的方式向 rrweb 传递回放时的配置参数,具体配置如下: 可以通过 `new rrweb.Replayer(events, options)` 的方式向 rrweb 传递回放时的配置参数,具体配置如下:
| key | 默认值 | 功能 | | key | 默认值 | 功能 |
| ------------------- | ------------- | ------------------------------------------------------------ | | ------------------- | ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| speed | 1 | 回放倍速 | | speed | 1 | 回放倍速 |
| root | document.body | 回放时使用的 HTML 元素 | | root | document.body | 回放时使用的 HTML 元素 |
| loadTimeout | 0 | 加载异步样式表的超时时长 | | loadTimeout | 0 | 加载异步样式表的超时时长 |

View File

@@ -59,6 +59,7 @@ function record<T = eventWithTime>(
recordCanvas = false, recordCanvas = false,
userTriggeredOnInput = false, userTriggeredOnInput = false,
collectFonts = false, collectFonts = false,
inlineImages = false,
plugins, plugins,
keepIframeSrcFn = () => false, keepIframeSrcFn = () => false,
} = options; } = options;
@@ -197,6 +198,7 @@ function record<T = eventWithTime>(
maskTextFn, maskTextFn,
maskInputFn, maskInputFn,
recordCanvas, recordCanvas,
inlineImages,
sampling, sampling,
slimDOMOptions, slimDOMOptions,
iframeManager, iframeManager,
@@ -228,6 +230,7 @@ function record<T = eventWithTime>(
maskTextFn, maskTextFn,
slimDOM: slimDOMOptions, slimDOM: slimDOMOptions,
recordCanvas, recordCanvas,
inlineImages,
onSerialize: (n) => { onSerialize: (n) => {
if (isIframeINode(n)) { if (isIframeINode(n)) {
iframeManager.addIframe(n); iframeManager.addIframe(n);
@@ -390,6 +393,7 @@ function record<T = eventWithTime>(
inlineStylesheet, inlineStylesheet,
sampling, sampling,
recordCanvas, recordCanvas,
inlineImages,
userTriggeredOnInput, userTriggeredOnInput,
collectFonts, collectFonts,
doc, doc,

View File

@@ -172,6 +172,7 @@ export default class MutationBuffer {
private maskTextFn: MaskTextFn | undefined; private maskTextFn: MaskTextFn | undefined;
private maskInputFn: MaskInputFn | undefined; private maskInputFn: MaskInputFn | undefined;
private recordCanvas: boolean; private recordCanvas: boolean;
private inlineImages: boolean;
private slimDOMOptions: SlimDOMOptions; private slimDOMOptions: SlimDOMOptions;
private doc: Document; private doc: Document;
@@ -190,6 +191,7 @@ export default class MutationBuffer {
maskTextFn: MaskTextFn | undefined, maskTextFn: MaskTextFn | undefined,
maskInputFn: MaskInputFn | undefined, maskInputFn: MaskInputFn | undefined,
recordCanvas: boolean, recordCanvas: boolean,
inlineImages: boolean,
slimDOMOptions: SlimDOMOptions, slimDOMOptions: SlimDOMOptions,
doc: Document, doc: Document,
mirror: Mirror, mirror: Mirror,
@@ -205,6 +207,7 @@ export default class MutationBuffer {
this.maskTextFn = maskTextFn; this.maskTextFn = maskTextFn;
this.maskInputFn = maskInputFn; this.maskInputFn = maskInputFn;
this.recordCanvas = recordCanvas; this.recordCanvas = recordCanvas;
this.inlineImages = inlineImages;
this.slimDOMOptions = slimDOMOptions; this.slimDOMOptions = slimDOMOptions;
this.emissionCallback = cb; this.emissionCallback = cb;
this.doc = doc; this.doc = doc;
@@ -296,6 +299,7 @@ export default class MutationBuffer {
maskInputFn: this.maskInputFn, maskInputFn: this.maskInputFn,
slimDOMOptions: this.slimDOMOptions, slimDOMOptions: this.slimDOMOptions,
recordCanvas: this.recordCanvas, recordCanvas: this.recordCanvas,
inlineImages: this.inlineImages,
onSerialize: (currentN) => { onSerialize: (currentN) => {
if (isIframeINode(currentN)) { if (isIframeINode(currentN)) {
this.iframeManager.addIframe(currentN); this.iframeManager.addIframe(currentN);
@@ -504,7 +508,8 @@ export default class MutationBuffer {
} }
} }
for (const pname of Array.from(old.style)) { for (const pname of Array.from(old.style)) {
if (target.style.getPropertyValue(pname) === '') { // "if not set, returns the empty string" if (target.style.getPropertyValue(pname) === '') {
// "if not set, returns the empty string"
styleObj[pname] = false; // delete styleObj[pname] = false; // delete
} }
} }

View File

@@ -97,6 +97,7 @@ export function initMutationObserver(
maskTextFn: MaskTextFn | undefined, maskTextFn: MaskTextFn | undefined,
maskInputFn: MaskInputFn | undefined, maskInputFn: MaskInputFn | undefined,
recordCanvas: boolean, recordCanvas: boolean,
inlineImages: boolean,
slimDOMOptions: SlimDOMOptions, slimDOMOptions: SlimDOMOptions,
mirror: Mirror, mirror: Mirror,
iframeManager: IframeManager, iframeManager: IframeManager,
@@ -117,6 +118,7 @@ export function initMutationObserver(
maskTextFn, maskTextFn,
maskInputFn, maskInputFn,
recordCanvas, recordCanvas,
inlineImages,
slimDOMOptions, slimDOMOptions,
doc, doc,
mirror, mirror,
@@ -951,6 +953,7 @@ export function initObservers(
o.maskTextFn, o.maskTextFn,
o.maskInputFn, o.maskInputFn,
o.recordCanvas, o.recordCanvas,
o.inlineImages,
o.slimDOMOptions, o.slimDOMOptions,
o.mirror, o.mirror,
o.iframeManager, o.iframeManager,

View File

@@ -25,6 +25,7 @@ type BypassOptions = {
maskTextFn: MaskTextFn | undefined; maskTextFn: MaskTextFn | undefined;
maskInputFn: MaskInputFn | undefined; maskInputFn: MaskInputFn | undefined;
recordCanvas: boolean; recordCanvas: boolean;
inlineImages: boolean;
sampling: SamplingStrategy; sampling: SamplingStrategy;
slimDOMOptions: SlimDOMOptions; slimDOMOptions: SlimDOMOptions;
iframeManager: IframeManager; iframeManager: IframeManager;
@@ -61,6 +62,7 @@ export class ShadowDomManager {
this.bypassOptions.maskTextFn, this.bypassOptions.maskTextFn,
this.bypassOptions.maskInputFn, this.bypassOptions.maskInputFn,
this.bypassOptions.recordCanvas, this.bypassOptions.recordCanvas,
this.bypassOptions.inlineImages,
this.bypassOptions.slimDOMOptions, this.bypassOptions.slimDOMOptions,
this.mirror, this.mirror,
this.bypassOptions.iframeManager, this.bypassOptions.iframeManager,

View File

@@ -230,6 +230,7 @@ export type recordOptions<T> = {
recordCanvas?: boolean; recordCanvas?: boolean;
userTriggeredOnInput?: boolean; userTriggeredOnInput?: boolean;
collectFonts?: boolean; collectFonts?: boolean;
inlineImages?: boolean;
plugins?: RecordPlugin[]; plugins?: RecordPlugin[];
// departed, please use sampling options // departed, please use sampling options
mousemoveWait?: number; mousemoveWait?: number;
@@ -259,6 +260,7 @@ export type observerParam = {
fontCb: fontCallback; fontCb: fontCallback;
sampling: SamplingStrategy; sampling: SamplingStrategy;
recordCanvas: boolean; recordCanvas: boolean;
inlineImages: boolean;
userTriggeredOnInput: boolean; userTriggeredOnInput: boolean;
collectFonts: boolean; collectFonts: boolean;
slimDOMOptions: SlimDOMOptions; slimDOMOptions: SlimDOMOptions;

View File

@@ -23,12 +23,13 @@ export default class MutationBuffer {
private maskTextFn; private maskTextFn;
private maskInputFn; private maskInputFn;
private recordCanvas; private recordCanvas;
private inlineImages;
private slimDOMOptions; private slimDOMOptions;
private doc; private doc;
private mirror; private mirror;
private iframeManager; private iframeManager;
private shadowDomManager; private shadowDomManager;
init(cb: mutationCallBack, blockClass: blockClass, blockSelector: string | null, maskTextClass: maskTextClass, maskTextSelector: string | null, inlineStylesheet: boolean, maskInputOptions: MaskInputOptions, maskTextFn: MaskTextFn | undefined, maskInputFn: MaskInputFn | undefined, recordCanvas: boolean, slimDOMOptions: SlimDOMOptions, doc: Document, mirror: Mirror, iframeManager: IframeManager, shadowDomManager: ShadowDomManager): void; init(cb: mutationCallBack, blockClass: blockClass, blockSelector: string | null, maskTextClass: maskTextClass, maskTextSelector: string | null, inlineStylesheet: boolean, maskInputOptions: MaskInputOptions, maskTextFn: MaskTextFn | undefined, maskInputFn: MaskInputFn | undefined, recordCanvas: boolean, inlineImages: boolean, slimDOMOptions: SlimDOMOptions, doc: Document, mirror: Mirror, iframeManager: IframeManager, shadowDomManager: ShadowDomManager): void;
freeze(): void; freeze(): void;
unfreeze(): void; unfreeze(): void;
isFrozen(): boolean; isFrozen(): boolean;

View File

@@ -4,7 +4,7 @@ import MutationBuffer from './mutation';
import { IframeManager } from './iframe-manager'; import { IframeManager } from './iframe-manager';
import { ShadowDomManager } from './shadow-dom-manager'; import { ShadowDomManager } from './shadow-dom-manager';
export declare const mutationBuffers: MutationBuffer[]; export declare const mutationBuffers: MutationBuffer[];
export declare function initMutationObserver(cb: mutationCallBack, doc: Document, blockClass: blockClass, blockSelector: string | null, maskTextClass: maskTextClass, maskTextSelector: string | null, inlineStylesheet: boolean, maskInputOptions: MaskInputOptions, maskTextFn: MaskTextFn | undefined, maskInputFn: MaskInputFn | undefined, recordCanvas: boolean, slimDOMOptions: SlimDOMOptions, mirror: Mirror, iframeManager: IframeManager, shadowDomManager: ShadowDomManager, rootEl: Node): MutationObserver; export declare function initMutationObserver(cb: mutationCallBack, doc: Document, blockClass: blockClass, blockSelector: string | null, maskTextClass: maskTextClass, maskTextSelector: string | null, inlineStylesheet: boolean, maskInputOptions: MaskInputOptions, maskTextFn: MaskTextFn | undefined, maskInputFn: MaskInputFn | undefined, recordCanvas: boolean, inlineImages: boolean, slimDOMOptions: SlimDOMOptions, mirror: Mirror, iframeManager: IframeManager, shadowDomManager: ShadowDomManager, rootEl: Node): MutationObserver;
export declare function initScrollObserver(cb: scrollCallback, doc: Document, mirror: Mirror, blockClass: blockClass, sampling: SamplingStrategy): listenerHandler; export declare function initScrollObserver(cb: scrollCallback, doc: Document, mirror: Mirror, blockClass: blockClass, sampling: SamplingStrategy): listenerHandler;
export declare const INPUT_TAGS: string[]; export declare const INPUT_TAGS: string[];
export declare function initObservers(o: observerParam, hooks?: hooksParam): listenerHandler; export declare function initObservers(o: observerParam, hooks?: hooksParam): listenerHandler;

View File

@@ -11,6 +11,7 @@ declare type BypassOptions = {
maskTextFn: MaskTextFn | undefined; maskTextFn: MaskTextFn | undefined;
maskInputFn: MaskInputFn | undefined; maskInputFn: MaskInputFn | undefined;
recordCanvas: boolean; recordCanvas: boolean;
inlineImages: boolean;
sampling: SamplingStrategy; sampling: SamplingStrategy;
slimDOMOptions: SlimDOMOptions; slimDOMOptions: SlimDOMOptions;
iframeManager: IframeManager; iframeManager: IframeManager;

View File

@@ -122,6 +122,7 @@ export declare type SamplingStrategy = Partial<{
mousemoveCallback: number; mousemoveCallback: number;
mouseInteraction: boolean | Record<string, boolean | undefined>; mouseInteraction: boolean | Record<string, boolean | undefined>;
scroll: number; scroll: number;
media: number;
input: 'all' | 'last'; input: 'all' | 'last';
}>; }>;
export declare type RecordPlugin<TOptions = unknown> = { export declare type RecordPlugin<TOptions = unknown> = {
@@ -150,6 +151,7 @@ export declare type recordOptions<T> = {
recordCanvas?: boolean; recordCanvas?: boolean;
userTriggeredOnInput?: boolean; userTriggeredOnInput?: boolean;
collectFonts?: boolean; collectFonts?: boolean;
inlineImages?: boolean;
plugins?: RecordPlugin[]; plugins?: RecordPlugin[];
mousemoveWait?: number; mousemoveWait?: number;
keepIframeSrcFn?: KeepIframeSrcFn; keepIframeSrcFn?: KeepIframeSrcFn;
@@ -177,6 +179,7 @@ export declare type observerParam = {
fontCb: fontCallback; fontCb: fontCallback;
sampling: SamplingStrategy; sampling: SamplingStrategy;
recordCanvas: boolean; recordCanvas: boolean;
inlineImages: boolean;
userTriggeredOnInput: boolean; userTriggeredOnInput: boolean;
collectFonts: boolean; collectFonts: boolean;
slimDOMOptions: SlimDOMOptions; slimDOMOptions: SlimDOMOptions;
@@ -349,12 +352,15 @@ export declare type inputCallback = (v: inputValue & {
export declare const enum MediaInteractions { export declare const enum MediaInteractions {
Play = 0, Play = 0,
Pause = 1, Pause = 1,
Seeked = 2 Seeked = 2,
VolumeChange = 3
} }
export declare type mediaInteractionParam = { export declare type mediaInteractionParam = {
type: MediaInteractions; type: MediaInteractions;
id: number; id: number;
currentTime?: number; currentTime?: number;
volume?: number;
muted?: boolean;
}; };
export declare type mediaInteractionCallback = (p: mediaInteractionParam) => void; export declare type mediaInteractionCallback = (p: mediaInteractionParam) => void;
export declare type DocumentDimension = { export declare type DocumentDimension = {