@portabletext/schema
Version:
Portable Text Schema
198 lines (197 loc) • 6.99 kB
JavaScript
function isBlockOfMember(member) {
return member.type === "block";
}
function isInlineObjectOfMember(member) {
return member.type === "object";
}
function compileOfMember(member, inheritance) {
return isBlockOfMember(member) ? compileBlockOfMember(member, inheritance) : isInlineObjectOfMember(member) ? compileInlineObjectOfMember(member, inheritance) : member;
}
function resolveBlockInheritance(member, inheritance) {
return {
styles: member.styles ? member.styles.map((style) => ({ ...style, value: style.name })) : inheritance.styles,
decorators: member.decorators ? member.decorators.map((decorator) => ({
...decorator,
value: decorator.name
})) : inheritance.decorators,
annotations: member.annotations ? member.annotations.map((annotation) => ({
...annotation,
fields: annotation.fields?.map(
(field) => compileField(field, inheritance)
) ?? []
})) : inheritance.annotations,
lists: member.lists ? member.lists.map((list) => ({ ...list, value: list.name })) : inheritance.lists,
inlineObjects: member.inlineObjects ? member.inlineObjects.map((inlineObject) => ({
...inlineObject,
fields: inlineObject.fields?.map(
(field) => compileField(field, inheritance)
) ?? []
})) : inheritance.inlineObjects
};
}
function compileBlockOfMember(member, inheritance) {
return { ...member, ...resolveBlockInheritance(member, inheritance) };
}
function compileInlineObjectOfMember(member, inheritance) {
return {
...member,
fields: member.fields.map((field) => compileField(field, inheritance))
};
}
function compileField(field, inheritance) {
if (field.type === "array" && field.of) {
const blockMember = field.of.find(isBlockOfMember), childInheritance = blockMember ? resolveBlockInheritance(blockMember, inheritance) : inheritance;
return {
...field,
of: field.of.map(
(member) => (
// The block member is `childInheritance` already resolved against the
// enclosing `inheritance`; reuse it rather than resolving twice. Its
// sibling containers inherit it.
member === blockMember ? { ...member, ...childInheritance } : compileOfMember(member, childInheritance)
)
)
};
}
return field;
}
function compileBaseDefinitionWithValue(definition) {
return { ...definition, value: definition.name };
}
function compileSchema(definition) {
const userStyles = (definition.styles ?? []).map(
compileBaseDefinitionWithValue
), styles = userStyles.some((style) => style.value === "normal") ? userStyles : [
{ value: "normal", name: "normal", title: "Normal" },
...userStyles
], lists = (definition.lists ?? []).map(compileBaseDefinitionWithValue), decorators = (definition.decorators ?? []).map(
compileBaseDefinitionWithValue
), annotationsShallow = (definition.annotations ?? []).map(
(annotation) => ({
...annotation,
fields: annotation.fields ?? []
})
), inlineObjectsShallow = (definition.inlineObjects ?? []).map(
(inlineObject) => ({
...inlineObject,
fields: inlineObject.fields ?? []
})
), inheritance = {
styles,
decorators,
annotations: annotationsShallow,
lists,
inlineObjects: inlineObjectsShallow
}, blockFields = [];
if (definition.block?.fields)
for (const field of definition.block.fields) {
if (field.name === "_type" || field.name === "_key" || field.name === "children" || field.name === "markDefs" || field.name === "style" || field.name === "listItem" || field.name === "level") {
console.warn(
`"${field.name}" is a reserved field name on Portable Text blocks`
);
continue;
}
blockFields.push(compileField(field, inheritance));
}
return {
block: {
name: definition.block?.name ?? "block",
...blockFields.length > 0 ? { fields: blockFields } : {}
},
span: {
name: "span"
},
styles,
lists,
decorators,
annotations: (definition.annotations ?? []).map((annotation) => ({
...annotation,
fields: annotation.fields?.map((field) => compileField(field, inheritance)) ?? []
})),
blockObjects: (definition.blockObjects ?? []).map((blockObject) => ({
...blockObject,
fields: blockObject.fields?.map((field) => compileField(field, inheritance)) ?? []
})),
inlineObjects: (definition.inlineObjects ?? []).map((inlineObject) => ({
...inlineObject,
fields: inlineObject.fields?.map((field) => compileField(field, inheritance)) ?? []
}))
};
}
function asNamedTypes(resolved) {
if (resolved)
return resolved.map((entry) => ({ ...entry, value: entry.name }));
}
function asFieldedTypes(resolved) {
if (resolved)
return resolved.map(
(entry) => ({ ...entry, fields: entry.fields ?? [] })
);
}
function getSubSchema(schema, of) {
const blockMember = of.find(
(member) => member.type === "block"
), blockObjects = of.filter(
(member) => member.type !== "block"
).map((member) => {
const objectMember = member, name = objectMember.name ?? objectMember.type;
if (objectMember.fields === void 0 && objectMember.type !== "object") {
const declared = schema.blockObjects.find(
(blockObject) => blockObject.name === name
);
if (declared)
return declared;
}
return {
name,
title: objectMember.title,
fields: objectMember.fields ?? []
};
});
return blockMember ? {
block: {
name: blockMember.name ?? schema.block.name,
fields: schema.block.fields
},
span: { name: schema.span.name },
styles: asNamedTypes(blockMember.styles) ?? schema.styles,
decorators: asNamedTypes(blockMember.decorators) ?? schema.decorators,
annotations: asFieldedTypes(blockMember.annotations) ?? schema.annotations,
lists: asNamedTypes(blockMember.lists) ?? schema.lists,
inlineObjects: asFieldedTypes(blockMember.inlineObjects) ?? schema.inlineObjects,
blockObjects
} : {
block: { name: schema.block.name, fields: schema.block.fields },
span: { name: schema.span.name },
styles: [],
decorators: [],
annotations: [],
lists: [],
inlineObjects: [],
blockObjects
};
}
function defineSchema(definition) {
return definition;
}
function isTypedObject(object) {
return isRecord(object) && typeof object._type == "string";
}
function isRecord(value) {
return !!value && (typeof value == "object" || typeof value == "function");
}
function isTextBlock(context, block) {
return !(!isTypedObject(block) || block._type !== context.schema.block.name || !Array.isArray(block.children));
}
function isSpan(context, child) {
return !(!isTypedObject(child) || child._type !== context.schema.span.name || typeof child.text != "string");
}
export {
compileSchema,
defineSchema,
getSubSchema,
isSpan,
isTextBlock,
isTypedObject
};
//# sourceMappingURL=index.js.map