/** * The bridge between canonical annotation documents and Mango's editor. * * The rule this file exists to enforce: the canonical document is the truth, * and `ResolvedAnnotation` is a lens over it. Nothing here rebuilds a document * from a projection — edits are patch operations addressed at canonical paths, * so a body Mango does not display, a refined selector it cannot draw, and a * vendor extension it has never heard of all survive an edit to the text. * * That is the difference from the adapter this replaces, which serialized a * flattened value back over the top of the original and lost everything it had * not modelled. */ import { type CanonicalAnnotation, type CanonicalAnnotationPage, type CanonicalStylesheet, type Diagnostic, type NeutralShape, type TemporalFragment } from '@mango-iiif/w3c-parser'; import type { ResolvedAnnotation } from '../../iiif/annotationResolver'; import type { ChapterAnnotationTool } from '../../core/types/story'; import type { AnnotationProvenance } from './model'; export type ProjectionPolicy = { /** Languages to prefer when an annotation carries text in several. */ preferredLanguages?: readonly string[]; }; /** The editor tool that authors a given shape, or null when none does. */ export declare const shapeTool: (shape: NeutralShape) => Exclude | null; /** * The neutral shape a `ResolvedAnnotation`'s geometry describes. * * `shapeType` is authoritative because every path shape shares the `polygon` * slot and the slot alone cannot say whether the last point joins the first. */ export declare const shapeFromResolved: (annotation: Pick) => NeutralShape; /** * Projects a canonical annotation into the shape the renderer and list use. * * The projection carries `document` and `targetPath` so any consumer can get * back to the resource that produced a value in order to patch it. That back * reference is what makes this a lens rather than a copy. */ export declare const projectToResolved: (annotation: CanonicalAnnotation, options?: { provenance?: AnnotationProvenance; canvasId?: string; policy?: ProjectionPolicy; }) => ResolvedAnnotation | null; /** Parses one annotation and projects it, keeping the parser's diagnostics. */ export declare const resolveAnnotationJson: (json: unknown, options?: { provenance?: AnnotationProvenance; canvasId?: string; policy?: ProjectionPolicy; }) => { annotation: ResolvedAnnotation | null; diagnostics: Diagnostic[]; }; /** Parses an AnnotationPage and projects every annotation on it. */ export declare const resolvePageJson: (json: unknown, options?: { provenance?: AnnotationProvenance; canvasId?: string; policy?: ProjectionPolicy; }) => { page: CanonicalAnnotationPage | null; annotations: ResolvedAnnotation[]; diagnostics: Diagnostic[]; }; export type CreateInput = { id?: string; canvasId: string; shape: NeutralShape; temporal?: TemporalFragment; text?: string; /** * Parallel publishable text bodies, for example translations of the same * annotation. `text` remains the convenient single-body authoring form; * callers that already have a language map should use this collection so no * translation has to be collapsed into a display projection first. */ textBodies?: readonly { value: string; purpose?: string; format?: string; language?: string; textDirection?: string; }[]; label?: string; note?: string; tags?: readonly string[]; motivation?: string; bodyPurpose?: string; language?: string; styleClass?: string; stylesheet?: CanonicalStylesheet | null; }; /** * Builds a canonical annotation from an authoring action. * * `motivation` defaults to `commenting` and `styleClass` is a separate argument * from it, which is the structural reason `motivation: "mine"` cannot recur: * there is no parameter through which a layer name could reach the motivation * field, and `createAnnotation` would refuse it if there were. */ export declare const createMangoAnnotation: (input: CreateInput) => CanonicalAnnotation; export type ApplyResult = { document: CanonicalAnnotation; diagnostics: Diagnostic[]; changed: boolean; }; /** * Applies a Mango-level edit to a canonical document. * * Notes and stylesheets are applied outside `patchAnnotation` because they are * not W3C body or target operations — the note is a Mango extension and the * stylesheet is annotation-level. Everything the parser owns goes through the * parser, so a rejected operation rejects the whole patch instead of leaving * the document half-changed. */ export declare const applyPatch: (annotation: CanonicalAnnotation, patch: Partial, options?: { language?: string; bodyPurpose?: string; textDirection?: string; bodyPath?: string; createBody?: boolean; stylesheet?: CanonicalStylesheet | null; }) => ApplyResult; /** * Applies an edit to a projection by way of its canonical document. * * The projection is rebuilt from the patched document rather than merged over * the old one, so the two cannot disagree about what the annotation now says. * A projection with no document behind it — one built by hand, or supplied by a * host as a plain object — falls back to a shallow merge, which is lossy but is * the most that can be done when there is no document to be lossless about. */ export declare const applyResolvedPatch: (annotation: ResolvedAnnotation, patch: Partial, options?: { language?: string; bodyPurpose?: string; textDirection?: string; bodyPath?: string; createBody?: boolean; stylesheet?: CanonicalStylesheet | null; }) => ResolvedAnnotation; /** Plain text for search and list display, HTML bodies included. */ export declare const searchTextFor: (annotation: ResolvedAnnotation) => string;