update borders
This commit is contained in:
1 parent
531a32e394
commit
c66f9a1e2a
12 files changed
+378
-9
No files matched your search
+102
-2
@@ -24,6 +24,11 @@ const PRECACHE = [
|
||||
'./css/app.css',
|
||||
'./fonts/DayLeafInitials.woff2',
|
||||
'./ornaments/group-l-49.svg',
|
||||
'./ornaments/mural-311a.svg',
|
||||
'./ornaments/uniform-rule-corner-tl.svg',
|
||||
'./ornaments/uniform-rule-corner-tr.svg',
|
||||
'./ornaments/uniform-rule-corner-bl.svg',
|
||||
'./ornaments/uniform-rule-corner-br.svg',
|
||||
'./js/htmx.min.js'
|
||||
].concat(TEMPLATE_URLS);
|
||||
|
||||
@@ -123,6 +128,71 @@ const view = createRenderer(readTemplate);
|
||||
|
||||
const router = new Router(new URL('./', location.href).pathname);
|
||||
|
||||
const VERSES_URL = './verses.json';
|
||||
|
||||
let verses = null;
|
||||
|
||||
function readVerses() {
|
||||
if (!verses) {
|
||||
verses = readText(pageRequest(VERSES_URL))
|
||||
.then(JSON.parse)
|
||||
.catch((err) => { verses = null; throw err; });
|
||||
}
|
||||
return verses;
|
||||
}
|
||||
|
||||
function parseAnchor(id) {
|
||||
const chapter = /^ch(\d+)$/.exec(id || '');
|
||||
if (chapter) return { chapter: +chapter[1], verse: null };
|
||||
const verse = /^v(\d+)_[0-9-]+$/.exec(id || '');
|
||||
if (verse) return { chapter: +verse[1], verse: id };
|
||||
return null;
|
||||
}
|
||||
|
||||
function verseLabels(chapters, number) {
|
||||
const entry = chapters[number - 1];
|
||||
if (typeof entry !== 'number') return entry || [];
|
||||
const out = [];
|
||||
for (let i = 1; i <= entry; i++) out.push(String(i));
|
||||
return out;
|
||||
}
|
||||
|
||||
function referenceFor(map, code, anchor) {
|
||||
const chapters = map && Object.prototype.hasOwnProperty.call(map, code)
|
||||
? map[code] : null;
|
||||
if (!chapters || !chapters.length) return null;
|
||||
|
||||
if (!chapters.some((entry) => (typeof entry === 'number' ? entry : entry.length))) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const at = parseAnchor(anchor) || { chapter: 1, verse: null };
|
||||
const number = at.chapter >= 1 && at.chapter <= chapters.length ? at.chapter : 1;
|
||||
const verse = at.chapter === number ? at.verse : null;
|
||||
|
||||
return {
|
||||
book: code,
|
||||
chapter: 'ch' + number,
|
||||
chapters: chapters.map((_, i) => ({ id: 'ch' + (i + 1), label: String(i + 1) })),
|
||||
verse: verse,
|
||||
verses: verseLabels(chapters, number)
|
||||
.map((label) => ({ id: 'v' + number + '_' + label, label: label }))
|
||||
};
|
||||
}
|
||||
|
||||
function bookOf(url) {
|
||||
return url ? router.relative(url).slice(1) : '';
|
||||
}
|
||||
|
||||
async function referenceOf(code, anchor) {
|
||||
if (!code) return null;
|
||||
try {
|
||||
return referenceFor(await readVerses(), code, anchor);
|
||||
} catch (err) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
const OFFLINE_NOTICE = ['Not available offline',
|
||||
'This page has not been opened on this device, so there is no copy stored ' +
|
||||
'here. Reconnect and try again, or open one you have read before.'];
|
||||
@@ -143,9 +213,13 @@ async function servePage(path, code, call) {
|
||||
if (!code) {
|
||||
fragment += '\n' + await view.render('version.njk', { version: VERSIONS });
|
||||
}
|
||||
if (!call.navigate && !call.restore) return fragment;
|
||||
const chrome = { sidebar: !!code, reference: await referenceOf(code, null) };
|
||||
if (!call.navigate && !call.restore) {
|
||||
return fragment + '\n'
|
||||
+ await view.render('sidebar.njk', Object.assign({ oob: true }, chrome));
|
||||
}
|
||||
try {
|
||||
return await view.compose(fragment);
|
||||
return await view.compose(fragment, chrome);
|
||||
} catch (err) {
|
||||
console.error('compose failed: ' + err.message);
|
||||
return fragment;
|
||||
@@ -156,6 +230,32 @@ router.get('/', (call) => servePage('./', '', call));
|
||||
router.get('/:page', (call) =>
|
||||
servePage('./' + call.params.page, call.params.page, call));
|
||||
|
||||
router.get('/api/reference', async (call) => {
|
||||
const params = call.url.searchParams;
|
||||
const page = call.currentUrl();
|
||||
const moved = params.has('at') ? params.get('at') : null;
|
||||
|
||||
const code = bookOf(page);
|
||||
const reference = await referenceOf(
|
||||
code, moved === null ? (page && page.hash.slice(1)) : moved);
|
||||
|
||||
if (moved === null) {
|
||||
return view.render('sidebar.njk',
|
||||
{ sidebar: !!code, reference: reference, settled: true });
|
||||
}
|
||||
if (!reference) return new Response('', { status: 204 });
|
||||
|
||||
const target = reference.verse || reference.chapter;
|
||||
return new Response(await view.render('verses.njk', { reference: reference }), {
|
||||
headers: {
|
||||
'Content-Type': 'text/html; charset=utf-8',
|
||||
'Cache-Control': 'no-store',
|
||||
'HX-Reswap': 'innerHTML settle:0 show:#' + target + ':top',
|
||||
'HX-Replace-Url': page.pathname + page.search + '#' + target
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
let filling = null;
|
||||
let complete = false;
|
||||
|
||||
|
||||
Reference in new issue
Block a user