* Add a `slimDOM` option to strip out unnecessary parts of the DOM in terms of replay - <script> tags in the <head> take up unnecessary storage space and are often injected semi randomly to become a source of unnecessary variation between recordings of the same thing - comment tags can be stripped out without affecting display - future: this option could also turn on more aggressive stripping, e.g. elements that are hidden by CSS (assuming we can handle them becoming visible after mutation events) * Mark nodes ignored due to slimDOM option, so that they can also be ignored by the mutation observer in rrweb * Introducing the `ignored` attribute violates the `serializedNodeWithId` type * slimDOM: Strip out whitespace nodes from <head> element as they have no effect but take up space - these would otherwise have to be merged after <script> elements are removed; for statcounter usecase, removing <script> elements is no good if there is still a trace of their presence due to the white space (and hence a variant <head> node is still produced) - I explored a more radical stripping of all white space nodes, but there is a problem if parent node is <pre> or otherwise rendered with `white-space: pre` and similar. detecting applied styles with getComputedStyle would be very expensive (I haven't measured it though) * Export IGNORED_NODE as a constant instead of relying on the hard-to-grok `-2` * Remove <link rel=preload as=script> which are similarly as useless as <script> tags * Make slimDOM configurable with the expecations that `slimDOMOptions: true` will only enable non-destructive options (so not all options may be turned on) * Expand slimDOM to add options to remove more elements from the <head> that should not be necessary in the replayer context
103 lines
1.8 KiB
TypeScript
103 lines
1.8 KiB
TypeScript
export enum NodeType {
|
|
Document,
|
|
DocumentType,
|
|
Element,
|
|
Text,
|
|
CDATA,
|
|
Comment,
|
|
}
|
|
|
|
export type documentNode = {
|
|
type: NodeType.Document;
|
|
childNodes: serializedNodeWithId[];
|
|
};
|
|
|
|
export type documentTypeNode = {
|
|
type: NodeType.DocumentType;
|
|
name: string;
|
|
publicId: string;
|
|
systemId: string;
|
|
};
|
|
|
|
export type attributes = {
|
|
[key: string]: string | number | boolean;
|
|
};
|
|
export type elementNode = {
|
|
type: NodeType.Element;
|
|
tagName: string;
|
|
attributes: attributes;
|
|
childNodes: serializedNodeWithId[];
|
|
isSVG?: true;
|
|
needBlock?: boolean;
|
|
};
|
|
|
|
export type textNode = {
|
|
type: NodeType.Text;
|
|
textContent: string;
|
|
isStyle?: true;
|
|
};
|
|
|
|
export type cdataNode = {
|
|
type: NodeType.CDATA;
|
|
textContent: '';
|
|
};
|
|
|
|
export type commentNode = {
|
|
type: NodeType.Comment;
|
|
textContent: string;
|
|
};
|
|
|
|
export type serializedNode =
|
|
| documentNode
|
|
| documentTypeNode
|
|
| elementNode
|
|
| textNode
|
|
| cdataNode
|
|
| commentNode;
|
|
|
|
export type serializedNodeWithId = serializedNode & { id: number };
|
|
|
|
export type tagMap = {
|
|
[key: string]: string;
|
|
};
|
|
|
|
export interface INode extends Node {
|
|
__sn: serializedNodeWithId;
|
|
}
|
|
|
|
export type idNodeMap = {
|
|
[key: number]: INode;
|
|
};
|
|
|
|
export type MaskInputOptions = Partial<{
|
|
color: boolean;
|
|
date: boolean;
|
|
'datetime-local': boolean;
|
|
email: boolean;
|
|
month: boolean;
|
|
number: boolean;
|
|
range: boolean;
|
|
search: boolean;
|
|
tel: boolean;
|
|
text: boolean;
|
|
time: boolean;
|
|
url: boolean;
|
|
week: boolean;
|
|
// unify textarea and select element with text input
|
|
textarea: boolean;
|
|
select: boolean;
|
|
}>;
|
|
|
|
export type SlimDOMOptions = Partial<{
|
|
script: boolean;
|
|
comment: boolean;
|
|
headFavicon: boolean;
|
|
headWhitespace: boolean;
|
|
headMetaDescKeywords: boolean;
|
|
headMetaSocial: boolean;
|
|
headMetaRobots: boolean;
|
|
headMetaHttpEquiv: boolean;
|
|
headMetaAuthorship: boolean;
|
|
headMetaVerification: boolean;
|
|
}>;
|