Source code
Revision control
Copy as Markdown
Other Tools
function is_same_sanitizer_name(a, b) {
return a.name === b.name && a.namespace === b.namespace;
}
function assert_config_is_valid(config) {
// The config has either an elements or a removeElements key, but not both.
assert_false(
"elements" in config && "removeElements" in config,
"Either elements or a removeElements, but not both",
);
assert_true(
"elements" in config || "removeElements" in config,
"Either elements or a removeElements",
);
// The config has either an attributes or a removeAttributes key, but not both.
assert_false(
"attributes" in config && "removeAttributes" in config,
"Either attributes or a removeAttributes, but not both",
);
assert_true(
"attributes" in config || "removeAttributes" in config,
"Either attributes or removeAttributes",
);
// If both config[elements] and config[replaceWithChildrenElements] exist, then the difference of config[elements] and config[replaceWithChildrenElements] is empty.
if (config.elements && config.replaceWithChildrenElements) {
for (let element of config.elements) {
assert_false(
config.replaceWithChildrenElements.some((replaceElement) =>
is_same_sanitizer_name(element, replaceElement),
),
`replaceWithChildrenElements should not contain ${element.name}`,
);
}
}
// If both config[removeElements] and config[replaceWithChildrenElements] exist, then the difference of config[removeElements] and config[replaceWithChildrenElements] is empty.
if (config.removeElements && config.replaceWithChildrenElements) {
for (let removeElement of config.removeElements) {
assert_false(
config.replaceWithChildrenElements.some((replaceElement) =>
is_same_sanitizer_name(removeElement, replaceElement),
),
`replaceWithChildrenElements should not contain ${removeElement.name}`,
);
}
}
// If config[attributes] exists:
if (config.attributes) {
} else {
// config[dataAttributes] does not exist.
assert_false("dataAttributes" in config, "dataAttributes does not exist");
}
}
function assert_config(config, expected) {
const PROPERTIES = [
"attributes",
"removeAttributes",
"elements",
"removeElements",
"replaceWithChildrenElements",
"comments",
"dataAttributes",
];
// Prevent some typos in the expected config.
for (let key of Object.keys(expected)) {
assert_in_array(key, PROPERTIES, "expected");
}
for (let key of Object.keys(config)) {
assert_in_array(key, PROPERTIES, "config");
}
assert_config_is_valid(config);
// XXX dataAttributes
// XXX comments
// XXX duplications
// XXX other consistency checks
function assert_attrs(key, config, expected, prefix = "config") {
// XXX we allow specifying only a subset for expected.
if (!(key in expected)) {
return;
}
if (expected[key] === undefined) {
assert_false(key in config, `Unexpected '${key}' in ${prefix}`);
return;
}
assert_true(key in config, `Missing '${key}' from ${prefix}`);
assert_equals(config[key]?.length, expected[key].length, `${prefix}.${key}.length`);
for (let i = 0; i < expected[key].length; i++) {
let attribute = expected[key][i];
if (typeof attribute === "string") {
assert_object_equals(
config[key][i],
{ name: attribute, namespace: null },
`${prefix}.${key}[${i}] should match`,
);
} else {
assert_object_equals(
config[key][i],
attribute,
`${prefix}.${key}[${i}] should match`,
);
}
}
}
assert_attrs("attributes", config, expected);
assert_attrs("removeAttributes", config, expected);
function assert_elems(key) {
if (!(key in expected)) {
return;
}
if (expected[key] === undefined) {
assert_false(key in config, `Unexpected '${key}' in config`);
return;
}
assert_true(key in config, `Missing '${key}' from config`);
assert_equals(config[key]?.length, expected[key].length, `${key}.length`);
for (let i = 0; i < expected[key].length; i++) {
let element = expected[key][i];
// To make writing tests a bit easier we also support the shorthand string syntax.
if (typeof element === "string") {
let extra = key === "elements" ? { removeAttributes: [] } : { };
assert_object_equals(
config[key][i],
{ name: element, namespace: XHTML_NS, ...extra },
`${key}[${i}] should match`,
);
} else {
if (key === "elements") {
assert_equals(config[key][i].name, element.name, `${key}[${i}].name should match`);
let ns = "namespace" in element ? element.namespace : XHTML_NS;
assert_equals(config[key][i].namespace, ns, `${key}[${i}].namespace should match`);
assert_attrs("attributes", config[key][i], element, `config.elements[${i}]`);
assert_attrs("removeAttributes", config[key][i], element, `config.elements[${i}]`);
} else {
assert_object_equals(config[key][i], element, `${key}[${i}] should match`);
}
}
}
}
assert_elems("elements");
assert_elems("removeElements");
assert_elems("replaceWithChildrenElements");
}