Don't serialize all cssRules if multiple text nodes exists (#866)

This commit is contained in:
Justin Halsall
2026-04-01 12:00:00 +08:00
committed by GitHub
parent 67554c33cc
commit ffc9185fa8
2 changed files with 60 additions and 2 deletions

View File

@@ -632,7 +632,12 @@ function serializeNode(
if (isStyle && textContent) {
try {
// try to read style sheet
if ((n.parentNode as HTMLStyleElement).sheet?.cssRules) {
if (n.nextSibling || n.previousSibling) {
// This is not the only child of the stylesheet.
// We can't read all of the sheet's .cssRules and expect them
// to _only_ include the current rule(s) added by the text node.
// So we'll be conservative and keep textContent as-is.
} else if ((n.parentNode as HTMLStyleElement).sheet?.cssRules) {
textContent = stringifyStyleSheet(
(n.parentNode as HTMLStyleElement).sheet!,
);

View File

@@ -1,5 +1,13 @@
/**
* @jest-environment jsdom
*/
import { JSDOM } from 'jsdom';
import { absoluteToStylesheet, _isBlockedElement } from '../src/snapshot';
import {
absoluteToStylesheet,
serializeNodeWithId,
_isBlockedElement,
} from '../src/snapshot';
import { serializedNodeWithId } from '../src/types';
describe('absolute url to stylesheet', () => {
const href = 'http://localhost/css/style.css';
@@ -126,3 +134,48 @@ describe('isBlockedElement()', () => {
).toEqual(true);
});
});
describe('style elements', () => {
const serializeNode = (node: Node): serializedNodeWithId | null => {
return serializeNodeWithId(node, {
doc: document,
map: {},
blockClass: 'blockblock',
blockSelector: null,
maskTextClass: 'maskmask',
maskTextSelector: null,
skipChild: false,
inlineStylesheet: true,
maskTextFn: undefined,
maskInputFn: undefined,
slimDOMOptions: {},
});
};
const render = (html: string): HTMLStyleElement => {
document.write(html);
return document.querySelector('style')!;
};
it('should serialize all rules of stylesheet when the sheet has a single child node', () => {
const styleEl = render(`<style>body { color: red; }</style>`);
styleEl.sheet?.insertRule('section { color: blue; }');
expect(serializeNode(styleEl.childNodes[0])).toMatchObject({
isStyle: true,
rootId: undefined,
textContent: 'section {color: blue;}body {color: red;}',
type: 3,
});
});
it('should serialize individual text nodes on stylesheets with multiple child nodes', () => {
const styleEl = render(`<style>body { color: red; }</style>`);
styleEl.append(document.createTextNode('section { color: blue; }'));
expect(serializeNode(styleEl.childNodes[1])).toMatchObject({
isStyle: true,
rootId: undefined,
textContent: 'section { color: blue; }',
type: 3,
});
});
});