Comparing version 0.2.3 to 0.3.0
255
Canvas.js
"use strict"; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const { basename, dirname, extname, join } = require('path'); | ||
const { existsSync, readFileSync } = require('fs'); | ||
const { glob } = require('glob'); | ||
const annotationBoilerplate = require('./boilerplate/annotation'); | ||
@@ -18,6 +8,6 @@ const chalk = require('chalk'); | ||
const urljoin = require('url-join'); | ||
const yaml = require('js-yaml'); | ||
const Directory_1 = require("./Directory"); | ||
const Motivations_1 = require("./Motivations"); | ||
const glob_promise_1 = require("glob-promise"); | ||
const Utils_1 = require("./Utils"); | ||
const Motivations_1 = require("./Motivations"); | ||
const Directory_1 = require("./Directory"); | ||
class Canvas { | ||
@@ -36,126 +26,124 @@ constructor(filePath, parentDirectory) { | ||
} | ||
read(canvasJson) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
this.canvasJson = canvasJson; | ||
this._getMetadata(); | ||
this._applyMetadata(); | ||
// if the filepath starts with an underscore | ||
if (this._isCanvasDirectory()) { | ||
// first, determine if there are any custom annotations (files ending in .yml that aren't info.yml) | ||
// if there are, loop through them creating the custom annotations. | ||
// if none of them has a motivation of 'painting', loop through all paintable file types adding them to the canvas. | ||
const customAnnotationFiles = glob.sync(this.filePath + '/*.yml', { | ||
ignore: [ | ||
'**/info.yml' | ||
] | ||
}); | ||
let hasPaintingAnnotation = false; | ||
customAnnotationFiles.forEach((file) => { | ||
let directoryName = dirname(file); | ||
directoryName = directoryName.substr(directoryName.lastIndexOf('/')); | ||
const name = basename(file, extname(file)); | ||
const annotationJson = Utils_1.Utils.cloneJson(annotationBoilerplate); | ||
const yml = yaml.safeLoad(readFileSync(file, 'utf8')); | ||
annotationJson.id = urljoin(canvasJson.id, 'annotation', canvasJson.items[0].items.length); | ||
let motivation = yml.motivation; | ||
if (!motivation) { | ||
// assume painting | ||
motivation = Motivations_1.Motivations.PAINTING; | ||
console.warn(chalk.yellow('motivation property missing in ' + file + ', guessed ' + motivation)); | ||
async read(canvasJson) { | ||
this.canvasJson = canvasJson; | ||
await this._getMetadata(); | ||
this._applyMetadata(); | ||
// if the filepath starts with an underscore | ||
if (this._isCanvasDirectory()) { | ||
// first, determine if there are any custom annotations (files ending in .yml that aren't info.yml) | ||
// if there are, loop through them creating the custom annotations. | ||
// if none of them has a motivation of 'painting', loop through all paintable file types adding them to the canvas. | ||
const customAnnotationFiles = await glob_promise_1.promise(this.filePath + '/*.yml', { | ||
ignore: [ | ||
'**/info.yml' | ||
] | ||
}); | ||
let hasPaintingAnnotation = false; | ||
await Promise.all(customAnnotationFiles.map(async (file) => { | ||
let directoryName = dirname(file); | ||
directoryName = directoryName.substr(directoryName.lastIndexOf('/')); | ||
const name = basename(file, extname(file)); | ||
const annotationJson = Utils_1.Utils.cloneJson(annotationBoilerplate); | ||
const yml = await Utils_1.Utils.readYml(file); | ||
annotationJson.id = urljoin(canvasJson.id, 'annotation', canvasJson.items[0].items.length); | ||
let motivation = yml.motivation; | ||
if (!motivation) { | ||
// assume painting | ||
motivation = Motivations_1.Motivations.PAINTING; | ||
console.warn(chalk.yellow('motivation property missing in ' + file + ', guessed ' + motivation)); | ||
} | ||
annotationJson.motivation = motivation; | ||
annotationJson.target = canvasJson.id; | ||
let id; | ||
// if the motivation is painting, or isn't recognised, set the id to the path of the yml value | ||
if ((motivation.toLowerCase() === Motivations_1.Motivations.PAINTING || !config.annotation.motivations[motivation]) && yml.value && extname(yml.value)) { | ||
hasPaintingAnnotation = true; | ||
id = urljoin(this.url.href, directoryName, yml.value); | ||
} | ||
else { | ||
id = urljoin(this.url.href, 'index.json', 'annotations', name); | ||
} | ||
annotationJson.body.id = id; | ||
if (yml.type) { | ||
annotationJson.body.type = yml.type; | ||
} | ||
else if (yml.value && extname(yml.value)) { | ||
// guess the type from the extension | ||
const type = Utils_1.Utils.getTypeByExtension(motivation, extname(yml.value)); | ||
if (type) { | ||
annotationJson.body.type = type; | ||
console.warn(chalk.yellow('type property missing in ' + file + ', guessed ' + type)); | ||
} | ||
annotationJson.motivation = motivation; | ||
annotationJson.target = canvasJson.id; | ||
let id; | ||
// if the motivation is painting, or isn't recognised, set the id to the path of the yml value | ||
if ((motivation.toLowerCase() === Motivations_1.Motivations.PAINTING || !config.annotation.motivations[motivation]) && yml.value && extname(yml.value)) { | ||
hasPaintingAnnotation = true; | ||
id = urljoin(this.url.href, directoryName, yml.value); | ||
} | ||
else if (yml.format) { | ||
// guess the type from the format | ||
const type = Utils_1.Utils.getTypeByFormat(motivation, yml.format); | ||
if (type) { | ||
annotationJson.body.type = type; | ||
console.warn(chalk.yellow('type property missing in ' + file + ', guessed ' + type)); | ||
} | ||
else { | ||
id = urljoin(this.url.href, 'index.json', 'annotations', name); | ||
} | ||
if (!annotationJson.body.type) { | ||
delete annotationJson.body.type; | ||
console.warn(chalk.yellow('unable to determine type of ' + file)); | ||
} | ||
if (yml.format) { | ||
annotationJson.body.format = yml.format; | ||
} | ||
else if (yml.value && extname(yml.value) && yml.type) { | ||
// guess the format from the extension and type | ||
const format = Utils_1.Utils.getFormatByExtensionAndType(motivation, extname(yml.value), yml.type); | ||
if (format) { | ||
annotationJson.body.format = format; | ||
console.warn(chalk.yellow('format property missing in ' + file + ', guessed ' + format)); | ||
} | ||
annotationJson.body.id = id; | ||
if (yml.type) { | ||
annotationJson.body.type = yml.type; | ||
} | ||
else if (yml.value && extname(yml.value)) { | ||
// guess the format from the extension | ||
const format = Utils_1.Utils.getFormatByExtension(motivation, extname(yml.value)); | ||
if (format) { | ||
annotationJson.body.format = format; | ||
console.warn(chalk.yellow('format property missing in ' + file + ', guessed ' + format)); | ||
} | ||
else if (yml.value && extname(yml.value)) { | ||
// guess the type from the extension | ||
const type = Utils_1.Utils.getTypeByExtension(motivation, extname(yml.value)); | ||
if (type) { | ||
annotationJson.body.type = type; | ||
console.warn(chalk.yellow('type property missing in ' + file + ', guessed ' + type)); | ||
} | ||
} | ||
else if (yml.type) { | ||
// can only guess the format from the type if there is one typeformat for this motivation. | ||
const format = Utils_1.Utils.getFormatByType(motivation, yml.type); | ||
if (format) { | ||
annotationJson.body.format = format; | ||
console.warn(chalk.yellow('format property missing in ' + file + ', guessed ' + format)); | ||
} | ||
else if (yml.format) { | ||
// guess the type from the format | ||
const type = Utils_1.Utils.getTypeByFormat(motivation, yml.format); | ||
if (type) { | ||
annotationJson.body.type = type; | ||
console.warn(chalk.yellow('type property missing in ' + file + ', guessed ' + type)); | ||
} | ||
} | ||
if (!annotationJson.body.type) { | ||
delete annotationJson.body.type; | ||
console.warn(chalk.yellow('unable to determine type of ' + file)); | ||
} | ||
if (yml.format) { | ||
annotationJson.body.format = yml.format; | ||
} | ||
else if (yml.value && extname(yml.value) && yml.type) { | ||
// guess the format from the extension and type | ||
const format = Utils_1.Utils.getFormatByExtensionAndType(motivation, extname(yml.value), yml.type); | ||
if (format) { | ||
annotationJson.body.format = format; | ||
console.warn(chalk.yellow('format property missing in ' + file + ', guessed ' + format)); | ||
} | ||
} | ||
else if (yml.value && extname(yml.value)) { | ||
// guess the format from the extension | ||
const format = Utils_1.Utils.getFormatByExtension(motivation, extname(yml.value)); | ||
if (format) { | ||
annotationJson.body.format = format; | ||
console.warn(chalk.yellow('format property missing in ' + file + ', guessed ' + format)); | ||
} | ||
} | ||
else if (yml.type) { | ||
// can only guess the format from the type if there is one typeformat for this motivation. | ||
const format = Utils_1.Utils.getFormatByType(motivation, yml.type); | ||
if (format) { | ||
annotationJson.body.format = format; | ||
console.warn(chalk.yellow('format property missing in ' + file + ', guessed ' + format)); | ||
} | ||
} | ||
if (!annotationJson.body.format) { | ||
delete annotationJson.body.format; | ||
console.warn(chalk.yellow('unable to determine format of ' + file)); | ||
} | ||
annotationJson.body.label = Utils_1.Utils.getLabel(this.infoYml.label); | ||
// if there's a value, and we're using a recognised motivation (except painting) | ||
if (yml.value && config.annotation.motivations[motivation] && motivation !== Motivations_1.Motivations.PAINTING) { | ||
annotationJson.body.value = yml.value; | ||
} | ||
canvasJson.items[0].items.push(annotationJson); | ||
} | ||
if (!annotationJson.body.format) { | ||
delete annotationJson.body.format; | ||
console.warn(chalk.yellow('unable to determine format of ' + file)); | ||
} | ||
annotationJson.body.label = Utils_1.Utils.getLabel(this.infoYml.label); | ||
// if there's a value, and we're using a recognised motivation (except painting) | ||
if (yml.value && config.annotation.motivations[motivation] && motivation !== Motivations_1.Motivations.PAINTING) { | ||
annotationJson.body.value = yml.value; | ||
} | ||
canvasJson.items[0].items.push(annotationJson); | ||
})); | ||
if (!hasPaintingAnnotation) { | ||
// for each jpg/pdf/mp4/obj in the canvas directory | ||
// add a painting annotation | ||
const paintableFiles = await glob_promise_1.promise(this.filePath + '/*.*', { | ||
ignore: [ | ||
'**/thumb.*' // ignore thumbs | ||
] | ||
}); | ||
if (!hasPaintingAnnotation) { | ||
// for each jpg/pdf/mp4/obj in the canvas directory | ||
// add a painting annotation | ||
const paintableFiles = glob.sync(this.filePath + '/*.*', { | ||
ignore: [ | ||
'**/thumb.*' // ignore thumbs | ||
] | ||
}); | ||
this._annotateFiles(canvasJson, paintableFiles); | ||
} | ||
this._annotateFiles(canvasJson, paintableFiles); | ||
} | ||
else { | ||
// a file was passed (not a directory starting with an underscore) | ||
// therefore, just annotate that file onto the canvas. | ||
this._annotateFiles(canvasJson, [this.filePath]); | ||
} | ||
if (!canvasJson.items[0].items.length) { | ||
console.warn(chalk.yellow('Could not find any files to annotate onto ' + this.filePath)); | ||
} | ||
// if there's no thumb.[jpg, gif, png] generate one from the first painted image | ||
yield Utils_1.Utils.getThumbnail(this.canvasJson, this.directory, this.filePath); | ||
}); | ||
} | ||
else { | ||
// a file was passed (not a directory starting with an underscore) | ||
// therefore, just annotate that file onto the canvas. | ||
this._annotateFiles(canvasJson, [this.filePath]); | ||
} | ||
if (!canvasJson.items[0].items.length) { | ||
console.warn(chalk.yellow('Could not find any files to annotate onto ' + this.filePath)); | ||
} | ||
// if there's no thumb.[jpg, gif, png] generate one from the first painted image | ||
await Utils_1.Utils.getThumbnail(this.canvasJson, this.directory, this.filePath); | ||
} | ||
@@ -190,8 +178,9 @@ _annotateFiles(canvasJson, files) { | ||
} | ||
_getMetadata() { | ||
async _getMetadata() { | ||
this.infoYml = {}; | ||
// if there's an info.yml | ||
const ymlPath = join(this.filePath, 'info.yml'); | ||
if (existsSync(ymlPath)) { | ||
this.infoYml = yaml.safeLoad(readFileSync(ymlPath, 'utf8')); | ||
const fileExists = await Utils_1.Utils.fileExists(ymlPath); | ||
if (fileExists) { | ||
this.infoYml = await Utils_1.Utils.readYml(ymlPath); | ||
console.log(chalk.green('got metadata for: ') + this.filePath); | ||
@@ -198,0 +187,0 @@ } |
282
Directory.js
"use strict"; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const { existsSync, readFileSync, writeFileSync } = require('fs'); | ||
const { glob } = require('glob'); | ||
const { join, basename } = require('path'); | ||
@@ -17,4 +7,4 @@ const { URL } = require('url'); | ||
const urljoin = require('url-join'); | ||
const yaml = require('js-yaml'); | ||
const Canvas_1 = require("./Canvas"); | ||
const glob_promise_1 = require("glob-promise"); | ||
const Utils_1 = require("./Utils"); | ||
@@ -38,73 +28,73 @@ // boilerplate json | ||
} | ||
read() { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
// canvases are directories starting with an underscore | ||
const canvasesPattern = this.filePath + '/_*'; | ||
const canvases = glob.sync(canvasesPattern, { | ||
async read() { | ||
// canvases are directories starting with an underscore | ||
const canvasesPattern = this.filePath + '/_*'; | ||
const canvases = await glob_promise_1.promise(canvasesPattern, { | ||
ignore: [ | ||
'**/*.yml', | ||
'**/thumb.*' | ||
] | ||
}); | ||
await Promise.all(canvases.map(async (canvas) => { | ||
console.log(chalk.green('creating canvas for: ') + canvas); | ||
this.items.push(new Canvas_1.Canvas(canvas, this)); | ||
})); | ||
// directories not starting with an underscore | ||
// these can be child manifests or child collections | ||
const directoriesPattern = this.filePath + '/*'; | ||
const directories = await glob_promise_1.promise(directoriesPattern, { | ||
ignore: [ | ||
'**/*.*', | ||
'**/_*' // ignore canvas folders | ||
] | ||
}); | ||
await Promise.all(directories.map(async (directory) => { | ||
console.log(chalk.green('creating directory for: ') + directory); | ||
const name = basename(directory); | ||
const url = urljoin(this.url.href, name); | ||
const newDirectory = new Directory(directory, url, this.generateThumbs, undefined, this); | ||
await newDirectory.read(); | ||
this.directories.push(newDirectory); | ||
})); | ||
// if there are no canvas, manifest, or collection directories to read, | ||
// but there are paintable files in the current directory, | ||
// create a canvas for each. | ||
if (!this.directories.length && !canvases.length) { | ||
const paintableFiles = await glob_promise_1.promise(this.filePath + '/*.*', { | ||
ignore: [ | ||
'**/*.yml', | ||
'**/thumb.*' | ||
'**/thumb.*', | ||
'**/index.json' | ||
] | ||
}); | ||
yield Promise.all(canvases.map((canvas) => __awaiter(this, void 0, void 0, function* () { | ||
console.log(chalk.green('creating canvas for: ') + canvas); | ||
this.items.push(new Canvas_1.Canvas(canvas, this)); | ||
}))); | ||
// directories not starting with an underscore | ||
// these can be child manifests or child collections | ||
const directoriesPattern = this.filePath + '/*'; | ||
const directories = glob.sync(directoriesPattern, { | ||
ignore: [ | ||
'**/*.*', | ||
'**/_*' // ignore canvas folders | ||
] | ||
paintableFiles.forEach((file) => { | ||
console.log(chalk.green('creating canvas for: ') + file); | ||
this.items.push(new Canvas_1.Canvas(file, this)); | ||
}); | ||
yield Promise.all(directories.map((directory) => __awaiter(this, void 0, void 0, function* () { | ||
console.log(chalk.green('creating directory for: ') + directory); | ||
const name = basename(directory); | ||
const url = urljoin(this.url.href, name); | ||
const newDirectory = new Directory(directory, url, this.generateThumbs, undefined, this); | ||
yield newDirectory.read(); | ||
this.directories.push(newDirectory); | ||
}))); | ||
// if there are no canvas, manifest, or collection directories to read, | ||
// but there are paintable files in the current directory, | ||
// create a canvas for each. | ||
if (!this.directories.length && !canvases.length) { | ||
const paintableFiles = glob.sync(this.filePath + '/*.*', { | ||
ignore: [ | ||
'**/*.yml', | ||
'**/thumb.*' | ||
] | ||
}); | ||
paintableFiles.forEach((file) => { | ||
console.log(chalk.green('creating canvas for: ') + file); | ||
this.items.push(new Canvas_1.Canvas(file, this)); | ||
}); | ||
} | ||
this.isCollection = this.directories.length > 0 || await Utils_1.Utils.hasManifestsYml(this.filePath); | ||
await this._getMetadata(); | ||
await this._createIndexJson(); | ||
if (this.isCollection) { | ||
console.log(chalk.green('created collection: ') + this.filePath); | ||
// if there are canvases, warn that they are being ignored | ||
if (this.items.length) { | ||
console.warn(chalk.yellow(this.items.length + ' unused canvas directories (starting with an underscore) found in the ' + this.filePath + ' collection. Remove directories not starting with an underscore to convert into a manifest.')); | ||
} | ||
this.isCollection = this.directories.length > 0 || Utils_1.Utils.hasManifestsYML(this.filePath); | ||
this._getMetadata(); | ||
this._createIndexJson(); | ||
if (this.isCollection) { | ||
console.log(chalk.green('created collection: ') + this.filePath); | ||
// if there are canvases, warn that they are being ignored | ||
if (this.items.length) { | ||
console.warn(chalk.yellow(this.items.length + ' unused canvas directories (starting with an underscore) found in the ' + this.filePath + ' collection. Remove directories not starting with an underscore to convert into a manifest.')); | ||
} | ||
} | ||
else { | ||
console.log(chalk.green('created manifest: ') + this.filePath); | ||
// if there aren't any canvases, warn that there should be | ||
if (!this.items.length) { | ||
console.warn(chalk.yellow(this.filePath + ' is a manifest, but no canvases (directories starting with an underscore) were found. Therefore it will not have any content.')); | ||
} | ||
else { | ||
console.log(chalk.green('created manifest: ') + this.filePath); | ||
// if there aren't any canvases, warn that there should be | ||
if (!this.items.length) { | ||
console.warn(chalk.yellow(this.filePath + ' is a manifest, but no canvases (directories starting with an underscore) were found. Therefore it will not have any content.')); | ||
} | ||
} | ||
}); | ||
} | ||
} | ||
_getMetadata() { | ||
async _getMetadata() { | ||
this.infoYml = {}; | ||
// if there's an info.yml | ||
const ymlPath = join(this.filePath, 'info.yml'); | ||
if (existsSync(ymlPath)) { | ||
this.infoYml = yaml.safeLoad(readFileSync(ymlPath, 'utf8')); | ||
const fileExists = await Utils_1.Utils.fileExists(ymlPath); | ||
if (fileExists) { | ||
this.infoYml = await Utils_1.Utils.readYml(ymlPath); | ||
console.log(chalk.green('got metadata for: ') + this.filePath); | ||
@@ -120,83 +110,91 @@ } | ||
} | ||
_createIndexJson() { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (this.isCollection) { | ||
this.indexJson = Utils_1.Utils.cloneJson(collectionBoilerplate); | ||
// for each child directory, add a collectionitem or manifestitem json boilerplate to items. | ||
yield Promise.all(this.directories.map((directory) => __awaiter(this, void 0, void 0, function* () { | ||
let itemJson; | ||
if (directory.isCollection) { | ||
itemJson = Utils_1.Utils.cloneJson(collectionItemBoilerplate); | ||
async _createIndexJson() { | ||
if (this.isCollection) { | ||
this.indexJson = Utils_1.Utils.cloneJson(collectionBoilerplate); | ||
// for each child directory, add a collectionitem or manifestitem json boilerplate to items. | ||
await Promise.all(this.directories.map(async (directory) => { | ||
let itemJson; | ||
if (directory.isCollection) { | ||
itemJson = Utils_1.Utils.cloneJson(collectionItemBoilerplate); | ||
} | ||
else { | ||
itemJson = Utils_1.Utils.cloneJson(manifestItemBoilerplate); | ||
} | ||
itemJson.id = urljoin(directory.url.href, 'index.json'); | ||
itemJson.label = Utils_1.Utils.getLabel(directory.infoYml.label); | ||
await Utils_1.Utils.getThumbnail(itemJson, directory); | ||
this.indexJson.items.push(itemJson); | ||
})); | ||
// check for manifests.yml. if it exists, parse and add to items | ||
const hasManifestsYml = await Utils_1.Utils.hasManifestsYml(this.filePath); | ||
if (hasManifestsYml) { | ||
const manifestsPath = join(this.filePath, 'manifests.yml'); | ||
const manifestsYml = await Utils_1.Utils.readYml(manifestsPath); | ||
manifestsYml.manifests.forEach((manifest) => { | ||
const itemJson = Utils_1.Utils.cloneJson(collectionItemBoilerplate); | ||
itemJson.id = manifest.id; | ||
if (manifest.label) { | ||
itemJson.label = Utils_1.Utils.getLabel(manifest.label); | ||
} | ||
else { | ||
itemJson = Utils_1.Utils.cloneJson(manifestItemBoilerplate); | ||
// no label supplied, use the last fragment of the url | ||
const url = new URL(itemJson.id); | ||
const pathname = url.pathname.split('/'); | ||
if (pathname.length > 1) { | ||
itemJson.label = Utils_1.Utils.getLabel(pathname[pathname.length - 2]); | ||
} | ||
} | ||
itemJson.id = urljoin(directory.url.href, 'index.json'); | ||
itemJson.label = Utils_1.Utils.getLabel(directory.infoYml.label); | ||
yield Utils_1.Utils.getThumbnail(itemJson, directory); | ||
this.indexJson.items.push(itemJson); | ||
}))); | ||
// check for manifests.yml. if it exists, parse and add to items | ||
if (Utils_1.Utils.hasManifestsYML(this.filePath)) { | ||
const manifestsPath = join(this.filePath, 'manifests.yml'); | ||
const manifestsYml = yaml.safeLoad(readFileSync(manifestsPath, 'utf8')); | ||
manifestsYml.manifests.forEach((manifest) => { | ||
const itemJson = Utils_1.Utils.cloneJson(collectionItemBoilerplate); | ||
itemJson.id = manifest.id; | ||
if (manifest.label) { | ||
itemJson.label = Utils_1.Utils.getLabel(manifest.label); | ||
if (manifest.thumbnail) { | ||
if (typeof manifest.thumbnail === 'string') { | ||
const thumbnail = Utils_1.Utils.cloneJson(thumbnailBoilerplate); | ||
thumbnail[0].id = manifest.thumbnail; | ||
itemJson.thumbnail = thumbnail; | ||
} | ||
else { | ||
// no label supplied, use the last fragment of the url | ||
const url = new URL(itemJson.id); | ||
const pathname = url.pathname.split('/'); | ||
if (pathname.length > 1) { | ||
itemJson.label = Utils_1.Utils.getLabel(pathname[pathname.length - 2]); | ||
} | ||
itemJson.thumbnail = manifest.thumbnail; | ||
} | ||
if (manifest.thumbnail) { | ||
if (typeof manifest.thumbnail === 'string') { | ||
const thumbnail = Utils_1.Utils.cloneJson(thumbnailBoilerplate); | ||
thumbnail[0].id = manifest.thumbnail; | ||
itemJson.thumbnail = thumbnail; | ||
} | ||
else { | ||
itemJson.thumbnail = manifest.thumbnail; | ||
} | ||
} | ||
this.indexJson.items.push(itemJson); | ||
}); | ||
console.log(chalk.green('parsed manifests.yml for: ') + this.filePath); | ||
} | ||
else { | ||
console.log(chalk.green('no manifests.yml found for: ') + this.filePath); | ||
} | ||
// sort items | ||
this.indexJson.items.sort((a, b) => { | ||
if (a.label['@none'][0].toLowerCase() < b.label['@none'][0].toLowerCase()) | ||
return -1; | ||
if (a.label['@none'][0].toLowerCase() > b.label['@none'][0].toLowerCase()) | ||
return 1; | ||
return 0; | ||
} | ||
this.indexJson.items.push(itemJson); | ||
}); | ||
console.log(chalk.green('parsed manifests.yml for: ') + this.filePath); | ||
} | ||
else { | ||
this.indexJson = Utils_1.Utils.cloneJson(manifestBoilerplate); | ||
// for each canvas, add canvas json | ||
yield Promise.all(this.items.map((canvas, index) => __awaiter(this, void 0, void 0, function* () { | ||
const canvasJson = Utils_1.Utils.cloneJson(canvasBoilerplate); | ||
canvasJson.id = urljoin(this.url.href, 'index.json/canvas', index); | ||
canvasJson.items[0].id = urljoin(this.url.href, 'index.json/canvas', index, 'annotationpage/0'); | ||
yield canvas.read(canvasJson); | ||
// add canvas to items | ||
this.indexJson.items.push(canvasJson); | ||
}))); | ||
console.log(chalk.green('no manifests.yml found for: ') + this.filePath); | ||
} | ||
this.indexJson.id = urljoin(this.url.href, 'index.json'); | ||
this._applyMetadata(); | ||
Utils_1.Utils.getThumbnail(this.indexJson, this); | ||
// write index.json | ||
writeFileSync(join(this.filePath, 'index.json'), JSON.stringify(this.indexJson, null, ' ')); | ||
console.log(chalk.green('created index.json for: ') + this.filePath); | ||
}); | ||
// sort items | ||
this.indexJson.items.sort((a, b) => { | ||
if (a.label['@none'][0].toLowerCase() < b.label['@none'][0].toLowerCase()) | ||
return -1; | ||
if (a.label['@none'][0].toLowerCase() > b.label['@none'][0].toLowerCase()) | ||
return 1; | ||
return 0; | ||
}); | ||
} | ||
else { | ||
this.indexJson = Utils_1.Utils.cloneJson(manifestBoilerplate); | ||
// for each canvas, add canvas json | ||
await Promise.all(this.items.map(async (canvas, index) => { | ||
const canvasJson = Utils_1.Utils.cloneJson(canvasBoilerplate); | ||
canvasJson.id = urljoin(this.url.href, 'index.json/canvas', index); | ||
canvasJson.items[0].id = urljoin(this.url.href, 'index.json/canvas', index, 'annotationpage/0'); | ||
await canvas.read(canvasJson); | ||
// add canvas to items | ||
this.indexJson.items.push(canvasJson); | ||
})); | ||
this.indexJson.items.sort((a, b) => { | ||
if (a.id < b.id) | ||
return -1; | ||
if (a.id > b.id) | ||
return 1; | ||
return 0; | ||
}); | ||
} | ||
this.indexJson.id = urljoin(this.url.href, 'index.json'); | ||
this._applyMetadata(); | ||
await Utils_1.Utils.getThumbnail(this.indexJson, this); | ||
// write index.json | ||
const path = join(this.filePath, 'index.json'); | ||
const json = JSON.stringify(this.indexJson, null, ' '); | ||
console.log(chalk.green('creating index.json for: ') + this.filePath); | ||
await Utils_1.Utils.writeJson(path, json); | ||
} | ||
@@ -203,0 +201,0 @@ _applyMetadata() { |
20
index.js
"use strict"; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const Directory_1 = require("./Directory"); | ||
const chalk = require('chalk'); | ||
const { existsSync } = require('fs'); | ||
exports.build = (dir, url, generateThumbs = true, virtualName) => __awaiter(this, void 0, void 0, function* () { | ||
const Utils_1 = require("./Utils"); | ||
exports.build = async (dir, url, generateThumbs = true, virtualName) => { | ||
console.log(chalk.white('started biiifing ' + dir)); | ||
// validate inputs | ||
if (!existsSync(dir)) { | ||
const exists = await Utils_1.Utils.fileExists(dir); | ||
if (!exists) { | ||
throw new Error('Directory does not exist'); | ||
@@ -23,4 +16,5 @@ } | ||
} | ||
yield new Directory_1.Directory(dir, url, generateThumbs, virtualName).read(); | ||
const directory = new Directory_1.Directory(dir, url, generateThumbs, virtualName); | ||
await directory.read(); | ||
console.log(chalk.white('finished biiifing ' + dir)); | ||
}); | ||
}; |
{ | ||
"name": "biiif", | ||
"version": "0.2.3", | ||
"version": "0.3.0", | ||
"description": "A CLI to build IIIF collections", | ||
@@ -31,3 +31,3 @@ "main": "index.js", | ||
"chalk": "^2.3.0", | ||
"glob": "^7.1.2", | ||
"glob-promise": "^3.4.0", | ||
"jimp": "^0.2.28", | ||
@@ -38,8 +38,8 @@ "js-yaml": "^3.10.0", | ||
"devDependencies": { | ||
"@types/node": "^8.0.53", | ||
"@types/node": "10.3.2", | ||
"jsonfile": "^4.0.0", | ||
"mocha": "^4.0.1", | ||
"mock-fs": "^4.4.2", | ||
"typescript": "^2.6.1" | ||
"typescript": "^2.9.1" | ||
} | ||
} |
151
Utils.js
"use strict"; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const { dirname } = require('path'); | ||
const { existsSync } = require('fs'); | ||
const { glob } = require('glob'); | ||
const { join, basename } = require('path'); | ||
const chalk = require('chalk'); | ||
const config = require('./config'); | ||
const fs = require('fs'); | ||
const Jimp = require("jimp"); | ||
const jsonfile = require('jsonfile'); | ||
const labelBoilerplate = require('./boilerplate/label'); | ||
const thumbnailBoilerplate = require('./boilerplate/thumbnail'); | ||
const urljoin = require('url-join'); | ||
const yaml = require('js-yaml'); | ||
const Motivations_1 = require("./Motivations"); | ||
const glob_promise_1 = require("glob-promise"); | ||
const Types_1 = require("./Types"); | ||
@@ -105,6 +99,2 @@ class Utils { | ||
} | ||
static hasManifestsYML(filePath) { | ||
const manifestsPath = join(filePath, 'manifests.yml'); | ||
return existsSync(manifestsPath); | ||
} | ||
// If filePath is: | ||
@@ -138,45 +128,43 @@ // C://Users/edsilv/github/edsilv/biiif-workshop/collection/_abyssinian/thumb.jpeg | ||
} | ||
static getThumbnail(json, directory, filePath) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const fp = filePath || directory.filePath; | ||
const thumbnailPattern = fp + '/thumb.*'; | ||
const thumbnails = glob.sync(thumbnailPattern); | ||
if (thumbnails.length) { | ||
console.log(chalk.green('found thumbnail for: ') + fp); | ||
let thumbnail = thumbnails[0]; | ||
const thumbnailJson = Utils.cloneJson(thumbnailBoilerplate); | ||
thumbnailJson[0].id = Utils.mergePaths(directory.url, Utils.getVirtualFilePath(thumbnail, directory)); | ||
json.thumbnail = thumbnailJson; | ||
} | ||
else if (directory.generateThumbs) { | ||
// if debugging: jimp item.getitem is not a function | ||
// generate thumbnail | ||
if (json.items && json.items.length && json.items[0].items) { | ||
console.log(chalk.green('generating thumbnail for: ') + fp); | ||
// find an annotation with a painting motivation of type image. | ||
const items = json.items[0].items; | ||
for (let i = 0; i < items.length; i++) { | ||
const item = items[i]; | ||
const body = item.body; | ||
if (body && item.motivation === Motivations_1.Motivations.PAINTING) { | ||
if (body.type.toLowerCase() === Types_1.Types.IMAGE) { | ||
const imageName = body.id.substr(body.id.lastIndexOf('/')); | ||
const imagePath = join(fp, imageName); | ||
const image = yield Jimp.read(imagePath); | ||
const thumb = image.clone(); | ||
// write image buffer to disk for testing | ||
// image.getBuffer(Jimp.AUTO, (err, buffer) => { | ||
// const arrBuffer = [...buffer]; | ||
// const pathToBuffer: string = imagePath.substr(0, imagePath.lastIndexOf('/')) + '/buffer.txt'; | ||
// fs.writeFile(pathToBuffer, arrBuffer); | ||
// }); | ||
thumb.cover(config.thumbnails.width, config.thumbnails.height); | ||
const pathToThumb = join(dirname(imagePath), 'thumb.' + image.getExtension()); | ||
thumb.write(pathToThumb, () => { | ||
console.log(chalk.green('generated thumbnail for: ') + fp); | ||
}); | ||
const thumbnailJson = Utils.cloneJson(thumbnailBoilerplate); | ||
thumbnailJson[0].id = Utils.mergePaths(directory.url, Utils.getVirtualFilePath(pathToThumb, directory)); | ||
json.thumbnail = thumbnailJson; | ||
} | ||
static async getThumbnail(json, directory, filePath) { | ||
const fp = filePath || directory.filePath; | ||
const thumbnailPattern = fp + '/thumb.*'; | ||
const thumbnails = await glob_promise_1.promise(thumbnailPattern); | ||
if (thumbnails.length) { | ||
console.log(chalk.green('found thumbnail for: ') + fp); | ||
let thumbnail = thumbnails[0]; | ||
const thumbnailJson = Utils.cloneJson(thumbnailBoilerplate); | ||
thumbnailJson[0].id = Utils.mergePaths(directory.url, Utils.getVirtualFilePath(thumbnail, directory)); | ||
json.thumbnail = thumbnailJson; | ||
} | ||
else if (directory.generateThumbs) { | ||
// if debugging: jimp item.getitem is not a function | ||
// generate thumbnail | ||
if (json.items && json.items.length && json.items[0].items) { | ||
console.log(chalk.green('generating thumbnail for: ') + fp); | ||
// find an annotation with a painting motivation of type image. | ||
const items = json.items[0].items; | ||
for (let i = 0; i < items.length; i++) { | ||
const item = items[i]; | ||
const body = item.body; | ||
if (body && item.motivation === Motivations_1.Motivations.PAINTING) { | ||
if (body.type.toLowerCase() === Types_1.Types.IMAGE) { | ||
const imageName = body.id.substr(body.id.lastIndexOf('/')); | ||
const imagePath = join(fp, imageName); | ||
const image = await Jimp.read(imagePath); | ||
const thumb = image.clone(); | ||
// write image buffer to disk for testing | ||
// image.getBuffer(Jimp.AUTO, (err, buffer) => { | ||
// const arrBuffer = [...buffer]; | ||
// const pathToBuffer: string = imagePath.substr(0, imagePath.lastIndexOf('/')) + '/buffer.txt'; | ||
// fs.writeFile(pathToBuffer, arrBuffer); | ||
// }); | ||
thumb.cover(config.thumbnails.width, config.thumbnails.height); | ||
const pathToThumb = join(dirname(imagePath), 'thumb.' + image.getExtension()); | ||
thumb.write(pathToThumb, () => { | ||
console.log(chalk.green('generated thumbnail for: ') + fp); | ||
}); | ||
const thumbnailJson = Utils.cloneJson(thumbnailBoilerplate); | ||
thumbnailJson[0].id = Utils.mergePaths(directory.url, Utils.getVirtualFilePath(pathToThumb, directory)); | ||
json.thumbnail = thumbnailJson; | ||
} | ||
@@ -186,3 +174,3 @@ } | ||
} | ||
}); | ||
} | ||
} | ||
@@ -252,3 +240,50 @@ static getLabel(value) { | ||
} | ||
static async readJson(path) { | ||
return new Promise((resolve, reject) => { | ||
jsonfile.readFile(path, (err, json) => { | ||
if (err) | ||
reject(err); | ||
else | ||
resolve(json); | ||
}); | ||
}); | ||
} | ||
static async writeJson(path, json) { | ||
return new Promise((resolve, reject) => { | ||
fs.writeFile(path, json, (err) => { | ||
if (err) | ||
reject(err); | ||
else | ||
resolve(); | ||
}); | ||
}); | ||
} | ||
static async readYml(path) { | ||
return new Promise((resolve, reject) => { | ||
fs.readFile(path, (err, fileBuffer) => { | ||
if (err) { | ||
reject(err); | ||
} | ||
else { | ||
const yml = yaml.safeLoad(fileBuffer); | ||
resolve(yml); | ||
} | ||
}); | ||
}); | ||
} | ||
static async fileExists(path) { | ||
return new Promise((resolve, reject) => { | ||
const exists = fs.existsSync(path); | ||
resolve(exists); | ||
}); | ||
} | ||
static async hasManifestsYml(path) { | ||
return new Promise((resolve, reject) => { | ||
const manifestsPath = join(path, 'manifests.yml'); | ||
Utils.fileExists(manifestsPath).then((exists) => { | ||
resolve(exists); | ||
}); | ||
}); | ||
} | ||
} | ||
exports.Utils = Utils; |
Sorry, the diff of this file is not supported yet
1
47238
22
864
+ Addedglob-promise@^3.4.0
+ Added@isaacs/cliui@8.0.2(transitive)
+ Added@types/glob@8.1.0(transitive)
+ Added@types/minimatch@5.1.2(transitive)
+ Added@types/node@22.13.5(transitive)
+ Addedansi-regex@5.0.16.1.0(transitive)
+ Addedansi-styles@4.3.06.2.1(transitive)
+ Addedbrace-expansion@2.0.1(transitive)
+ Addedcolor-convert@2.0.1(transitive)
+ Addedcolor-name@1.1.4(transitive)
+ Addedcross-spawn@7.0.6(transitive)
+ Addedeastasianwidth@0.2.0(transitive)
+ Addedemoji-regex@8.0.09.2.2(transitive)
+ Addedforeground-child@3.3.0(transitive)
+ Addedglob@11.0.1(transitive)
+ Addedglob-promise@3.4.0(transitive)
+ Addedis-fullwidth-code-point@3.0.0(transitive)
+ Addedisexe@2.0.0(transitive)
+ Addedjackspeak@4.1.0(transitive)
+ Addedlru-cache@11.0.2(transitive)
+ Addedminimatch@10.0.1(transitive)
+ Addedminipass@7.1.2(transitive)
+ Addedpackage-json-from-dist@1.0.1(transitive)
+ Addedpath-key@3.1.1(transitive)
+ Addedpath-scurry@2.0.0(transitive)
+ Addedshebang-command@2.0.0(transitive)
+ Addedshebang-regex@3.0.0(transitive)
+ Addedsignal-exit@4.1.0(transitive)
+ Addedstring-width@4.2.35.1.2(transitive)
+ Addedstrip-ansi@6.0.17.1.0(transitive)
+ Addedundici-types@6.20.0(transitive)
+ Addedwhich@2.0.2(transitive)
+ Addedwrap-ansi@7.0.08.1.0(transitive)
- Removedglob@^7.1.2
- Removedbrace-expansion@1.1.11(transitive)
- Removedconcat-map@0.0.1(transitive)
- Removedfs.realpath@1.0.0(transitive)
- Removedglob@7.2.3(transitive)
- Removedinflight@1.0.6(transitive)
- Removedinherits@2.0.4(transitive)
- Removedminimatch@3.1.2(transitive)
- Removedonce@1.4.0(transitive)
- Removedpath-is-absolute@1.0.1(transitive)
- Removedwrappy@1.0.2(transitive)