-
Notifications
You must be signed in to change notification settings - Fork 2
Description
During work on the Manifest Editor, some new patterns for create IIIF were created. Usually focussed on creating IIIF from users input. At the moment it's tied to that UI layer, but I think it could be useful as a standalone piece of iiif builder.
Examples
Here is a minimal definition:
interface CreatePlaintextPayload {
url: string;
label?: InternationalString;
}
async function createPlaintext(data: CreatePlaintextPayload, ctx: CreatorFunctionContext) {
return ctx.embed({
id: data.url,
type: "Text",
label: data.label,
format: "text/plain",
});
}
export const plaintextCreator: CreatorDefinition = {
id: "@manifest-editor/plaintext-creator",
create: createPlaintext,
label: "Plaintext",
summary: "Add link to an plaintext",
resourceType: "ContentResource",
resourceFields: ["label", "format"],
supports: {
parentFields: ["seeAlso", "rendering", "homepage"],
},
staticFields: {
format: "text/plain",
},
};It fully describes taking user input:
{
"id": "https://example.org/some-link",
"label": { "en": ["Some link"] }
}And producing:
{
"id": "https://example.org/some-link",
"type": "Text",
"label": { "en": ["Some link"] },
"format": "text/plain"
}This example is not a groundbreaking abstraction. But it does allow for more information to be attached. For example, human readable label/summary for what will be created, where this resource is valid from a IIIF point of view, which fields are created - and which are static.
Nesting definitions
Having a "Library" of these definitions allows the Manifest Editor to compose them together.
interface Payload {
label?: InternationalString;
body: InternationalString;
motivation?: string;
height?: number;
width?: number;
}
async function createHtmlAnnotation(data: Payload, ctx: CreatorFunctionContext) {
const annotation = {
id: ctx.generateId("annotation"),
type: "Annotation",
};
const targetType = ctx.options.targetType as "Annotation" | "Canvas";
const languages = Object.keys(data.body);
const bodies = [];
for (const language of languages) {
const body = (data.body as any)[language].join("\n");
if (body) {
bodies.push(
await ctx.create(
"@manifest-editor/html-body-creator",
{
language,
body,
},
{ parent: { resource: annotation, property: "items" } }
)
);
}
}
if (targetType === "Annotation") {
return ctx.embed({
...annotation,
motivation: data.motivation || ctx.options.initialData?.motivation || "painting",
body: bodies,
target: ctx.getTarget(),
});
}
if (targetType === "Canvas") {
const canvasId = ctx.generateId("canvas");
const pageId = ctx.generateId("annotation-page", { id: canvasId, type: "Canvas" });
const annotationResource = ctx.embed({
...annotation,
motivation: "painting",
body: bodies,
target: { type: "SpecificResource", source: { id: canvasId, type: "Canvas" } },
});
const page = ctx.embed({
id: pageId,
type: "AnnotationPage",
items: [annotationResource],
});
return ctx.embed({
id: canvasId,
type: "Canvas",
label: data.label || { en: ["Untitled HTML canvas"] },
height: data.height || 1000,
width: data.width || 1000,
items: [page],
});
}
}There is a lot going on in this one, but if you look at the definition you can see what it supports:
export const htmlAnnotation: CreatorDefinition = {
id: "@manifest-editor/html-annotation",
create: createHtmlAnnotation,
label: "HTML Annotation",
summary: "Add HTML annotation",
resourceType: "Annotation",
resourceFields: ["id", "type", "motivation", "body", "target"],
additionalTypes: ["Canvas"],
supports: {
initialData: true,
parentTypes: ["AnnotationPage", "Manifest"],
parentFields: ["items"],
},
staticFields: {
type: "Annotation",
},
};So this produces an Annotation and can be created on:
AnnotationPage- Annotation added directly to the pageManifest- A new canvas is created, and the annotation added
In the creator example, there is a "nested" example, which is calling out to another definition:
await ctx.create(
"@manifest-editor/html-body-creator",
{
language,
body,
},
{ parent: { resource: annotation, property: "items" } }
);So you can compose them together.
With IIIF Builder, you could install or create "plugins" and use them to build IIIF either statically, or incrementally in a UI, similar to the Manifest Editor.