mirror of https://github.com/sveltejs/svelte
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
128 lines
3.1 KiB
128 lines
3.1 KiB
2 years ago
|
import { assert } from 'vitest';
|
||
|
|
||
|
/** @type {HTMLDivElement} */
|
||
|
let _container;
|
||
|
|
||
|
/**
|
||
|
* @param {string} html
|
||
|
* @param {{
|
||
|
* removeDataSvelte?: boolean,
|
||
|
* preserveComments?: boolean,
|
||
|
* }} options
|
||
|
*/
|
||
|
export function normalize_html(html, options = {}) {
|
||
|
const container = (_container ??= document.createElement('div'));
|
||
|
|
||
|
if (!options.preserveComments) {
|
||
|
html = html.replace(/(<!--.*?-->)/g, '');
|
||
|
}
|
||
|
|
||
|
if (options.removeDataSvelte) {
|
||
|
html = html.replace(/(data-svelte-h="[^"]+")/g, '');
|
||
|
}
|
||
|
|
||
|
html = html.replace(/>[ \t\n\r\f]+</g, '><').trim();
|
||
|
|
||
|
container.innerHTML = html;
|
||
|
|
||
|
clean_children(container);
|
||
|
|
||
|
return container.innerHTML.replace(/<\/?noscript\/?>/g, '');
|
||
|
}
|
||
|
|
||
|
/** @param {any} node */
|
||
|
function clean_children(node) {
|
||
|
// sort attributes
|
||
|
const attributes = Array.from(node.attributes).sort((a, b) => (a.name < b.name ? -1 : 1));
|
||
|
|
||
|
attributes.forEach((attr) => {
|
||
|
node.removeAttribute(attr.name);
|
||
|
});
|
||
|
|
||
|
attributes.forEach((attr) => {
|
||
|
node.setAttribute(attr.name, attr.value);
|
||
|
});
|
||
|
|
||
|
let previous = null;
|
||
|
// recurse
|
||
|
[...node.childNodes].forEach((child) => {
|
||
|
if (child.nodeType === 3) {
|
||
|
// text
|
||
|
if (
|
||
|
node.namespaceURI === 'http://www.w3.org/2000/svg' &&
|
||
|
node.tagName !== 'text' &&
|
||
|
node.tagName !== 'tspan'
|
||
|
) {
|
||
|
node.removeChild(child);
|
||
|
}
|
||
|
|
||
|
child.data = child.data.replace(/[ \t\n\r\f]+/g, '\n');
|
||
|
|
||
|
if (previous && previous.nodeType === 3) {
|
||
|
previous.data += child.data;
|
||
|
previous.data = previous.data.replace(/[ \t\n\r\f]+/g, '\n');
|
||
|
|
||
|
node.removeChild(child);
|
||
|
child = previous;
|
||
|
}
|
||
|
} else if (child.nodeType === 8) {
|
||
|
// comment
|
||
|
// do nothing
|
||
|
} else {
|
||
|
clean_children(child);
|
||
|
}
|
||
|
|
||
|
previous = child;
|
||
|
});
|
||
|
|
||
|
// collapse whitespace
|
||
|
if (node.firstChild && node.firstChild.nodeType === 3) {
|
||
|
node.firstChild.data = node.firstChild.data.replace(/^[ \t\n\r\f]+/, '');
|
||
|
if (!node.firstChild.data.length) node.removeChild(node.firstChild);
|
||
|
}
|
||
|
|
||
|
if (node.lastChild && node.lastChild.nodeType === 3) {
|
||
|
node.lastChild.data = node.lastChild.data.replace(/[ \t\n\r\f]+$/, '');
|
||
|
if (!node.lastChild.data.length) node.removeChild(node.lastChild);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
*
|
||
|
* @param {string} actual
|
||
|
* @param {string} expected
|
||
|
* @param {{
|
||
|
* message?: string,
|
||
|
* normalize_html?: {
|
||
|
* removeDataSvelte?: boolean,
|
||
|
* preserveComments?: boolean,
|
||
|
* },
|
||
|
* without_normalize?: boolean,
|
||
|
* }} options
|
||
|
*/
|
||
|
export function assert_html_equal(actual, expected, options = {}) {
|
||
|
if (options.without_normalize) {
|
||
|
actual = actual.replace(/\r\n/g, '\n');
|
||
|
expected = expected.replace(/\r\n/g, '\n');
|
||
|
|
||
|
if (options.normalize_html.removeDataSvelte) {
|
||
|
actual = actual.replace(/(\sdata-svelte-h="[^"]+")/g, '');
|
||
|
expected = expected.replace(/(\sdata-svelte-h="[^"]+")/g, '');
|
||
|
}
|
||
|
} else {
|
||
|
actual = normalize_html(actual, options.normalize_html);
|
||
|
expected = normalize_html(expected, options.normalize_html);
|
||
|
}
|
||
|
|
||
|
try {
|
||
|
assert.equal(actual, expected, options.message);
|
||
|
} catch (err) {
|
||
|
// Remove this function from the stack trace so that the error is shown in the test file
|
||
|
|
||
|
if (Error.captureStackTrace) {
|
||
|
Error.captureStackTrace(err, assert_html_equal);
|
||
|
}
|
||
|
throw err;
|
||
|
}
|
||
|
}
|