https://github.com/jptmoore/maniiifest
Typesafe IIIF presentation v3 parsing without external dependencies
https://github.com/jptmoore/maniiifest
iiif iiif-presentation-3 manifest parser
Last synced: 8 months ago
JSON representation
Typesafe IIIF presentation v3 parsing without external dependencies
- Host: GitHub
- URL: https://github.com/jptmoore/maniiifest
- Owner: jptmoore
- License: mit
- Created: 2024-08-01T13:27:52.000Z (over 1 year ago)
- Default Branch: main
- Last Pushed: 2025-03-31T10:47:30.000Z (8 months ago)
- Last Synced: 2025-03-31T11:33:18.082Z (8 months ago)
- Topics: iiif, iiif-presentation-3, manifest, parser
- Language: TypeScript
- Homepage:
- Size: 731 KB
- Stars: 12
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Maniiifest
## Description
Maniiifest provides methods to parse and manipulate [IIIF Presentation API 3.0](https://iiif.io/api/presentation/3.0/) specification and [W3C web annotations](https://www.w3.org/TR/annotation-model/). It ensures type safety and offers utility functions for working with IIIF data. Maniiifest takes a parser generator approach to generating TypeScript type definitions using a domain-specific language (DSL). The current specification is available [here](https://raw.githubusercontent.com/jptmoore/maniiifest/main/src/specification.atd).
A typechecker/validator built using maniiifest is available online [here](https://maniiifest.onrender.com/).
## Installation
Install the package using npm:
```sh
npm install maniiifest --save-dev
```
## Usage
Import and use the functions in your TypeScript project:
```typescript
import { Maniiifest } from 'maniiifest';
const manifest = {
"id": "https://iiif.io/api/cookbook/recipe/0032-collection/manifest-02.json",
"type": "Manifest",
"label": { "en": ["Northeaster"] }
}
const parser = new Maniiifest(manifest);
const label = parser.getManifestLabelByLanguage('en');
console.log(label?.['en']);
```
To parse web annotations you need to provide the type of annotation to the constructor. For example:
```typescript
const annotationParser = new Maniiifest(annotation, "Annotation");
const annotationPageParser = new Maniiifest(annotation_page, "AnnotationPage");
const annotationCollectionParser = new Maniiifest(annotation_collection, "AnnotationCollection");
```
The aim is to support the most relevant subset of the W3C standard as used within IIIF manifests.
## Documentation
Documentation for the current supported get methods and generators available [here](https://jptmoore.github.io/maniiifest/classes/Maniiifest.html). If you would like to see other methods added please raise an issue.
## Tutorial
In this example we will use generators to work with a complex collection that nests manifests within it.
```typescript
import { Maniiifest } from 'maniiifest';
async function main() {
const response = await fetch('https://iiif.wellcomecollection.org/presentation/b19974760');
const jsonData = await response.json();
const parser = new Maniiifest(jsonData);
const manifests = parser.iterateCollectionManifest();
let count = 0;
for (const item of manifests) {
if (count >= 25) break;
const manifestRef = new Maniiifest(item);
const metadata = manifestRef.iterateManifestMetadata();
for (const item of metadata) {
console.log(item);
}
count++;
}
}
main()
```
The output will be the metadata from the first 25 manifests:
```sh
❯ ts-node tutorial.ts
{ label: { en: [ 'Volume' ] }, value: { none: [ '1' ] } }
{ label: { en: [ 'Year' ] }, value: { none: [ '1859' ] } }
{ label: { en: [ 'Month' ] }, value: { en: [ 'September' ] } }
{
label: { en: [ 'DisplayDate' ] },
value: { en: [ '15. September 1859' ] }
}
{ label: { en: [ 'Volume' ] }, value: { none: [ '1' ] } }
{ label: { en: [ 'Year' ] }, value: { none: [ '1859' ] } }
{ label: { en: [ 'Month' ] }, value: { en: [ 'October' ] } }
.....
```
In this example we will work with externally referenced W3C annotations.
```typescript
import { Maniiifest } from 'maniiifest';
async function main() {
const response = await fetch('https://iiif.io/api/cookbook/recipe/0269-embedded-or-referenced-annotations/manifest.json');
const jsonData = await response.json();
const parser = new Maniiifest(jsonData);
const annotationPages = parser.iterateManifestCanvasW3cAnnotationPage();
for (const annotationPage of annotationPages) {
const response = await fetch(annotationPage.id);
const jsonData = await response.json();
const parser = new Maniiifest(jsonData, "AnnotationPage");
const annotations = parser.iterateAnnotationPageAnnotation();
for (const annotation of annotations) {
console.log(annotation.body?.value);
}
}
}
main()
```
The output will the commenting value from the single annotation:
```
Göttinger Marktplatz mit Gänseliesel Brunnen
```
In this example we will work with an annotation that uses the [georeference](https://iiif.io/api/extension/georef/) extension.
```typescript
import { Maniiifest } from 'maniiifest';
async function main() {
const response = await fetch('https://annotations.allmaps.org/maps/cde9210870a2652a');
const jsonData = await response.json();
const annotation = new Maniiifest(jsonData, "Annotation");
const points = Array.from(annotation.iterateAnnotationGeometryPointCoordinates());
for (let i = 0; i < points.length; i += 2) {
console.log(`x: ${points[i]}, y: ${points[i + 1]}`);
}
}
main()
```
The output will be all the point coordinates:
```
x: -70.9375518, y: 42.4811769
x: -70.9398138, y: 42.4825027
x: -70.9403993, y: 42.4821228
x: -70.9434097, y: 42.480079
x: -70.9373183, y: 42.4793787
x: -70.9454651, y: 42.4765122
x: -70.9364491, y: 42.4804618
x: -70.9377961, y: 42.4788144
x: -70.935966, y: 42.4809988
x: -70.9390062, y: 42.4772977
x: -70.9398389, y: 42.4815905
x: -70.9369067, y: 42.4798999
```
More examples of parsing complex manifests and collections can be found [here](https://github.com/jptmoore/maniiitest).
## Scripts
- `npm run build`: Compile the TypeScript code.
- `npm run test`: Run the tests using Jest.
- `npm start`: Run the example script.
- `npm run generate-docs`: Generate documentation using TypeDoc.
## License
This project is licensed under the MIT License.