@canopy-iiif/app 0.6.28 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/build/assets.js +30 -0
- package/lib/build/build.js +128 -0
- package/lib/{dev.js → build/dev.js} +494 -205
- package/lib/build/facets.js +19 -0
- package/lib/{iiif.js → build/iiif.js} +242 -384
- package/lib/build/log.js +31 -0
- package/lib/{mdx.js → build/mdx.js} +13 -10
- package/lib/build/pages.js +141 -0
- package/lib/build/runtimes.js +58 -0
- package/lib/build/search-index.js +42 -0
- package/lib/build/search-workflow.js +61 -0
- package/lib/build/search.js +219 -0
- package/lib/build/styles.js +141 -0
- package/lib/{thumbnail.js → iiif/thumbnail.js} +0 -1
- package/lib/index.js +2 -3
- package/lib/{search.js → search/search.js} +8 -8
- package/package.json +2 -1
- package/lib/build.js +0 -762
- package/lib/components/IIIFCard.js +0 -102
- package/lib/log.js +0 -64
- package/lib/runtime/command-entry.jsx +0 -44
- /package/lib/{devtoast.config.json → build/devtoast.config.json} +0 -0
- /package/lib/{devtoast.css → build/devtoast.css} +0 -0
- /package/lib/{search-app.jsx → search/search-app.jsx} +0 -0
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const React = require('react');
|
|
4
|
-
const fs = require('fs');
|
|
5
|
-
const path = require('path');
|
|
6
|
-
|
|
7
|
-
// Cache of index/manifests to avoid repeated disk reads during a build
|
|
8
|
-
let CACHE = { loaded: false, byId: new Map(), bySlug: new Map() };
|
|
9
|
-
|
|
10
|
-
function safeReadJson(p) {
|
|
11
|
-
try { return JSON.parse(fs.readFileSync(p, 'utf8')); } catch (_) { return null; }
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
function loadIndexOnce() {
|
|
15
|
-
if (CACHE.loaded) return CACHE;
|
|
16
|
-
const idxPath = path.resolve('.cache/iiif/index.json');
|
|
17
|
-
const idx = safeReadJson(idxPath);
|
|
18
|
-
if (idx && Array.isArray(idx.byId)) {
|
|
19
|
-
for (const e of idx.byId) {
|
|
20
|
-
if (!e || e.type !== 'Manifest') continue;
|
|
21
|
-
const id = String(e.id || '');
|
|
22
|
-
const slug = String(e.slug || '');
|
|
23
|
-
const entry = { id, slug, parent: e.parent || '', thumbnail: e.thumbnail || '' };
|
|
24
|
-
if (id) CACHE.byId.set(id, entry);
|
|
25
|
-
if (slug) CACHE.bySlug.set(slug, entry);
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
CACHE.loaded = true;
|
|
29
|
-
return CACHE;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
function readManifestTitle(slug) {
|
|
33
|
-
try {
|
|
34
|
-
const p = path.resolve('.cache/iiif/manifests', `${slug}.json`);
|
|
35
|
-
const m = safeReadJson(p);
|
|
36
|
-
const label = m && m.label;
|
|
37
|
-
if (!label) return null;
|
|
38
|
-
if (typeof label === 'string') return label;
|
|
39
|
-
const keys = Object.keys(label || {});
|
|
40
|
-
if (!keys.length) return null;
|
|
41
|
-
const arr = label[keys[0]];
|
|
42
|
-
if (Array.isArray(arr) && arr.length) return String(arr[0]);
|
|
43
|
-
return null;
|
|
44
|
-
} catch (_) { return null; }
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
function deriveTitleFromSlug(slug) {
|
|
48
|
-
try {
|
|
49
|
-
const s = decodeURIComponent(String(slug || ''));
|
|
50
|
-
return s.replace(/[-_]+/g, ' ').replace(/\s+/g, ' ').trim() || s;
|
|
51
|
-
} catch (_) { return String(slug || ''); }
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
function IIIFCard(props) {
|
|
55
|
-
const { id, slug, href, src, title, subtitle, alt, className, style, ...rest } = props || {};
|
|
56
|
-
const { byId, bySlug } = loadIndexOnce();
|
|
57
|
-
let entry = null;
|
|
58
|
-
if (id && byId.has(String(id))) entry = byId.get(String(id));
|
|
59
|
-
else if (slug && bySlug.has(String(slug))) entry = bySlug.get(String(slug));
|
|
60
|
-
|
|
61
|
-
const resolvedSlug = (entry && entry.slug) || (slug ? String(slug) : '');
|
|
62
|
-
const resolvedHref = href || (resolvedSlug ? `/works/${resolvedSlug}.html` : '#');
|
|
63
|
-
const resolvedSrc = src || (entry && entry.thumbnail) || '';
|
|
64
|
-
const resolvedTitle = title || readManifestTitle(resolvedSlug) || deriveTitleFromSlug(resolvedSlug);
|
|
65
|
-
const resolvedAlt = alt || resolvedTitle || '';
|
|
66
|
-
|
|
67
|
-
let Card = null;
|
|
68
|
-
try {
|
|
69
|
-
// Load the UI Card component for consistent markup/styles
|
|
70
|
-
const ui = require('@canopy-iiif/app/ui');
|
|
71
|
-
Card = ui && (ui.Card || ui.default && ui.default.Card) ? (ui.Card || ui.default.Card) : null;
|
|
72
|
-
} catch (_) { Card = null; }
|
|
73
|
-
|
|
74
|
-
if (Card) {
|
|
75
|
-
return React.createElement(Card, {
|
|
76
|
-
href: resolvedHref,
|
|
77
|
-
src: resolvedSrc || undefined,
|
|
78
|
-
alt: resolvedAlt,
|
|
79
|
-
title: resolvedTitle,
|
|
80
|
-
subtitle,
|
|
81
|
-
className,
|
|
82
|
-
style,
|
|
83
|
-
...rest,
|
|
84
|
-
});
|
|
85
|
-
}
|
|
86
|
-
// Fallback minimal markup if UI is unavailable
|
|
87
|
-
return React.createElement(
|
|
88
|
-
'a',
|
|
89
|
-
{ href: resolvedHref, className, style, ...rest },
|
|
90
|
-
React.createElement(
|
|
91
|
-
'figure',
|
|
92
|
-
{ style: { margin: 0 } },
|
|
93
|
-
resolvedSrc ? React.createElement('img', { src: resolvedSrc, alt: resolvedAlt, loading: 'lazy', style: { display: 'block', width: '100%', height: 'auto', borderRadius: 4 } }) : null,
|
|
94
|
-
React.createElement('figcaption', { style: { marginTop: 8 } },
|
|
95
|
-
resolvedTitle ? React.createElement('strong', { style: { display: 'block' } }, resolvedTitle) : null,
|
|
96
|
-
subtitle ? React.createElement('span', { style: { display: 'block', color: '#6b7280' } }, subtitle) : null,
|
|
97
|
-
)
|
|
98
|
-
)
|
|
99
|
-
);
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
module.exports = IIIFCard;
|
package/lib/log.js
DELETED
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
let charm = null;
|
|
2
|
-
try {
|
|
3
|
-
charm = require('charm')();
|
|
4
|
-
} catch (_) {
|
|
5
|
-
charm = null;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
const ANSI = {
|
|
9
|
-
reset: '\u001b[0m',
|
|
10
|
-
bright: '\u001b[1m',
|
|
11
|
-
dim: '\u001b[2m',
|
|
12
|
-
underscore: '\u001b[4m',
|
|
13
|
-
colors: {
|
|
14
|
-
black: '\u001b[30m',
|
|
15
|
-
red: '\u001b[31m',
|
|
16
|
-
green: '\u001b[32m',
|
|
17
|
-
yellow: '\u001b[33m',
|
|
18
|
-
blue: '\u001b[34m',
|
|
19
|
-
magenta: '\u001b[35m',
|
|
20
|
-
cyan: '\u001b[36m',
|
|
21
|
-
white: '\u001b[37m'
|
|
22
|
-
}
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
function log(string, color = 'blue', options = { bright: false, dim: false, underscore: false }) {
|
|
26
|
-
if (charm) {
|
|
27
|
-
const c = require('charm')();
|
|
28
|
-
c.pipe(process.stdout);
|
|
29
|
-
if (options?.bright) c.display('bright');
|
|
30
|
-
if (options?.dim) c.display('dim');
|
|
31
|
-
if (options?.underscore) c.display('underscore');
|
|
32
|
-
c.foreground(color).write(String(string)).display('reset');
|
|
33
|
-
c.end();
|
|
34
|
-
} else {
|
|
35
|
-
const parts = [];
|
|
36
|
-
if (options?.bright) parts.push(ANSI.bright);
|
|
37
|
-
if (options?.dim) parts.push(ANSI.dim);
|
|
38
|
-
if (options?.underscore) parts.push(ANSI.underscore);
|
|
39
|
-
const clr = ANSI.colors[color] || '';
|
|
40
|
-
parts.push(clr);
|
|
41
|
-
parts.push(String(string));
|
|
42
|
-
parts.push(ANSI.reset);
|
|
43
|
-
process.stdout.write(parts.join(''));
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
function logLine(string, color = 'blue', options) {
|
|
48
|
-
log(string + '\n', color, options);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
function logResponse(string, response, success = true) {
|
|
52
|
-
if (success) {
|
|
53
|
-
log('✓ ', 'yellow', { dim: true });
|
|
54
|
-
log(String(string), 'yellow');
|
|
55
|
-
log(` ➜ ${response?.status ?? ''}\n`, 'yellow', { dim: true });
|
|
56
|
-
} else {
|
|
57
|
-
log('✗ ', 'red', { dim: true });
|
|
58
|
-
log(String(string), 'red');
|
|
59
|
-
log(` ➜ ${response?.status ?? ''}\n`, 'red', { dim: true });
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
module.exports = { log, logLine, logResponse };
|
|
64
|
-
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { createRoot } from 'react-dom/client';
|
|
3
|
-
import { CommandPaletteApp } from '@canopy-iiif/app/ui';
|
|
4
|
-
|
|
5
|
-
function ready(fn) {
|
|
6
|
-
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', fn, { once: true });
|
|
7
|
-
else fn();
|
|
8
|
-
}
|
|
9
|
-
function parseProps(el) {
|
|
10
|
-
try { const s = el.querySelector('script[type="application/json"]'); if (s) return JSON.parse(s.textContent || '{}'); } catch {}
|
|
11
|
-
return {};
|
|
12
|
-
}
|
|
13
|
-
function withBase(href) {
|
|
14
|
-
try {
|
|
15
|
-
const bp = (window && window.CANOPY_BASE_PATH) ? String(window.CANOPY_BASE_PATH) : '';
|
|
16
|
-
if (!bp) return href;
|
|
17
|
-
if (/^https?:/i.test(href)) return href;
|
|
18
|
-
const clean = String(href || '').replace(/^\/+/, '');
|
|
19
|
-
return (bp.endsWith('/') ? bp.slice(0, -1) : bp) + '/' + clean;
|
|
20
|
-
} catch { return href; }
|
|
21
|
-
}
|
|
22
|
-
function rootBase() { try { const bp = (window && window.CANOPY_BASE_PATH) ? String(window.CANOPY_BASE_PATH) : ''; return bp && bp.endsWith('/') ? bp.slice(0, -1) : bp; } catch { return ''; } }
|
|
23
|
-
|
|
24
|
-
ready(async function () {
|
|
25
|
-
const host = document.querySelector('[data-canopy-command]');
|
|
26
|
-
if (!host) return;
|
|
27
|
-
const cfg = parseProps(host) || {};
|
|
28
|
-
let records = [];
|
|
29
|
-
let loading = true;
|
|
30
|
-
try {
|
|
31
|
-
let v = '';
|
|
32
|
-
try { const m = await fetch(rootBase() + '/api/index.json').then((r) => r && r.ok ? r.json() : null).catch(() => null); v = (m && m.version) || ''; } catch {}
|
|
33
|
-
const res = await fetch(rootBase() + '/api/search-index.json' + (v ? ('?v=' + encodeURIComponent(v)) : '')).catch(() => null);
|
|
34
|
-
const j = res && res.ok ? await res.json().catch(() => []) : [];
|
|
35
|
-
records = Array.isArray(j) ? j : ((j && j.records) || []);
|
|
36
|
-
loading = false;
|
|
37
|
-
} catch {}
|
|
38
|
-
const ReactObj = (window && window.React) || null;
|
|
39
|
-
const RDC = (window && window.ReactDOMClient) || null;
|
|
40
|
-
if (!ReactObj || !RDC || !RDC.createRoot) return;
|
|
41
|
-
const root = RDC.createRoot(host);
|
|
42
|
-
const onSelect = (href) => { try { window.location.href = withBase(String(href || '')); } catch {} };
|
|
43
|
-
root.render(React.createElement(CommandPaletteApp, { records, loading, config: cfg, onSelect }));
|
|
44
|
-
});
|
|
File without changes
|
|
File without changes
|
|
File without changes
|