@nacelle/rich-text-utils
Version:
A set of Typescript types and helpers to work with Rich Text fields.
107 lines • 4.42 kB
JavaScript
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
import { allowedAttributes, allowedMarks, allowedChildren, inlineNodeTypes, } from './definitions';
export function validate(document) {
if (document === null || document === undefined) {
return { valid: true };
}
if (document.schema !== 'rast') {
return {
valid: false,
message: `.schema is not "rast":\n\n ${JSON.stringify(document, null, 2)}`,
};
}
const nodes = [document.document];
let node = document.document;
while (nodes.length > 0) {
const next = nodes.pop();
if (!next) {
break;
}
node = next;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { type } = node, attributes = __rest(node, ["type"]);
const invalidAttribute = Object.keys(attributes).find((attr) => !allowedAttributes[node.type].includes(attr));
if (invalidAttribute) {
return {
valid: false,
message: `"${node.type}" has an invalid attribute "${invalidAttribute}":\n\n ${JSON.stringify(node, null, 2)}`,
};
}
if ('meta' in node) {
if (!Array.isArray(node.meta)) {
return {
valid: false,
message: `"${node.type}"'s meta is not an Array:\n\n ${JSON.stringify(node, null, 2)}`,
};
}
const invalidMeta = node.meta.find((entry) => typeof entry !== 'object' ||
!('id' in entry) ||
!('value' in entry) ||
typeof entry.value !== 'string');
if (invalidMeta) {
return {
valid: false,
message: `"${node.type}" has an invalid meta ${JSON.stringify(invalidMeta)}:\n\n ${JSON.stringify(node, null, 2)}`,
};
}
}
if ('marks' in node) {
if (!Array.isArray(node.marks)) {
return {
valid: false,
message: `"${node.type}"'s marks is not an Array:\n\n ${JSON.stringify(node, null, 2)}`,
};
}
const invalidMark = node.marks.find((mark) => !allowedMarks.includes(mark));
if (invalidMark) {
return {
valid: false,
message: `"${node.type}" has an invalid mark "${invalidMark}":\n\n ${JSON.stringify(node, null, 2)}`,
};
}
}
if ('children' in node) {
if (!Array.isArray(node.children)) {
return {
valid: false,
message: `"${node.type}"'s children is not an Array:\n\n ${JSON.stringify(node, null, 2)}`,
};
}
if (node.children.length === 0) {
return {
valid: false,
message: `"${node.type}"'s children cannot be an empty Array:\n\n ${JSON.stringify(node, null, 2)}`,
};
}
let allowed = allowedChildren[node.type];
if (typeof allowed === 'string' && allowed === 'inlineNodes') {
allowed = inlineNodeTypes;
}
const invalidChildIndex = node.children.findIndex((child) => !child || !allowed.includes(child.type));
if (invalidChildIndex !== -1) {
const invalidChild = node.children[invalidChildIndex];
return {
valid: false,
message: `"${node.type}" has invalid child "${invalidChild ? invalidChild.type : invalidChild}":\n\n ${JSON.stringify(node, null, 2)}`,
};
}
for (let i = node.children.length - 1; i >= 0; i--) {
nodes.push(node.children[i]);
}
}
}
return {
valid: true,
};
}
//# sourceMappingURL=validate.js.map