sourceapproutescodex.js

import Database from "better-sqlite3";
import express from "express";

import grimm from "../grimm.js";
import {
	getRubricFilters,
	highlightFilter,
	getComments,
	comparePages,
	prettyRender,
	rubric
} from "../helpers.js";

const router = express.Router();
const db = new Database("./db/site.db");
db.pragma("journal_mode = DELETE");

rubric.templates.th = {
	html: (node, opt, lang) => (opt?.noOldChars ? "th" : "þ")
};
rubric.templates.Th = {
	html: (node, opt, lang) => (opt?.noOldChars ? "Th" : "Þ")
};
rubric.templates.dh = {
	html: (node, opt, lang) => (opt?.noOldChars ? "th" : "ð")
};
rubric.templates.Dh = {
	html: (node, opt, lang) => (opt?.noOldChars ? "Th" : "Ð")
};
rubric.templates.r = {
	html: (node, opt, lang) =>
		opt?.noOldChars ? "r" : '<span class="r-rotunda">ꝛ</span>'
};
rubric.templates.s = {
	html: (node, opt, lang) => (opt?.noOldChars ? "s" : "ſ")
};
rubric.templates.ij = {
	html: (node, opt, lang) => (opt?.noOldChars ? "ij" : "ÿ")
};
rubric.templates.IJ = {
	html: (node, opt, lang) => (opt?.noOldChars ? "IJ" : "Ÿ")
};

rubric.langs.html.els.heading = (node, opt, lang) => {
	const parsed = lang.parse(node.text, opt);
	const plainerParsed = lang.parse(
		node.text,
		Object.assign({ noOldChars: true }, opt)
	);
	const headerSlug = grimm.slugify(plainerParsed, { html: true });
	return `\n<h${node.level}${
		opt.hyperlinkHeadings && node.level > 1 ? ` id="${headerSlug}"` : ""
	} data-fraktur="${lang.escapeQuotes(
		parsed
	)}" data-antiqua="${lang.escapeQuotes(plainerParsed)}">${
		opt.hyperlinkHeadings && node.level > 1 && !parsed.includes("<a ")
			? `<a href="#${headerSlug}">${parsed}</a>`
			: parsed
	}</h${node.level}>\n`;
};

const filters = Object.assign(getRubricFilters(rubric), highlightFilter);

const displaySubpage = async (slug, res, next) => {
	const page = db
		.prepare(
			`Select * From editions
			Join pagesets
			On editions.translates = pagesets.pagesetID
			Where editions.editionID = ?`
		)
		.get(slug);

	if (page === undefined) {
		return next();
	}

	page.cache = page?.cache === 1 || page?.cache === true;

	const comments = getComments(slug);

	const translations = page.translates
		? db
				.prepare(
					`Select * From editions
					Join pagesets
					On editions.translates = pagesets.pagesetID
					Where editions.translates = ?`
				)
				.all(page.translates)
				.sort(comparePages)
		: [];

	const toSendOver = {
		slug: slug,
		comments: comments,
		translations: translations,

		grimm: grimm,
		tr: grimm.translator(page.lang),

		baseDomain: "satyrs.eu",

		qua: text => `/${page.translates}/${text}`, // Short for “qualify”
		compileDebug: true,
		filters: filters
	};

	try {
		toSendOver.annexe = (
			await import(`../../hypertext/public/${page.translates}/annexe`)
		).default;
	} catch (e) {}

	Object.assign(toSendOver, page);

	const subpage = page.translates.match(/^(codex\/.*?)\/(.*)$/);

	return prettyRender(
		res,
		next,
		subpage
			? `${subpage[1]}/` +
					`${page.lang}_` +
					`${subpage[2].replace(/\//g, "_")}`
			: `${page.translates}/${page.lang}`,
		toSendOver
	);
};

const displayIndex = async (res, next) => {
	const page = db
		.prepare(
			`Select * From editions
			Join pagesets
			On editions.translates = pagesets.pagesetID
			Where editions.editionID = 'codex'`
		)
		.get();

	if (page === undefined) {
		return next();
	}

	page.cache = page?.cache === 1 || page?.cache === true;

	const comments = getComments("codex");

	const toSendOver = {
		slug: "codex",
		comments: comments,
		translations: [],

		grimm: grimm,
		tr: grimm.translator(page.lang),

		baseDomain: "satyrs.eu",

		qua: text => `/${page.translates}/${text}`, // Short for “qualify”
		compileDebug: true,
		filters: filters
	};

	const entries = db
		.prepare(
			`Select editionID, lang, translates, original, alexandrine, codexLink, codexVerb
		From editions
		Join pagesets
		On editions.translates = pagesets.pagesetID
		Where editions.translates Like 'codex/%'
		And editions.translates Not Like 'codex/%/%'`
		)
		.all();

	let books = {};

	for (const entry of entries) {
		const cleanID = entry.editionID.replace("codex/", "");
		const cleanTranslates = entry.translates.replace("codex/", "");
		if (cleanTranslates in books) {
			books[cleanTranslates].translations.push({
				lang: entry.lang,
				editionID: cleanID,
				original: entry.original.replace("codex/", "")
			});
		} else {
			books[cleanTranslates] = {
				alexandrine: entry.alexandrine,
				codexLink: entry.codexLink,
				codexVerb: entry.codexVerb,
				original: entry.original.replace("codex/", ""),
				translations: [
					{
						lang: entry.lang,
						editionID: cleanID,
						original: entry.original.replace("codex/", "")
					}
				]
			};
		}
	}

	for (const book in books) {
		books[book].translations = books[book].translations.sort(comparePages);
	}

	toSendOver.codexBooks = books;

	try {
		toSendOver.annexe = (
			await import(`../../hypertext/public/${page.translates}/annexe`)
		).default;
	} catch (e) {}

	Object.assign(toSendOver, page);

	return prettyRender(
		res,
		next,
		`${page.translates}/${page.lang}`,
		toSendOver
	);
};

router.get(
	"/:pageSlug([^\\.]+)",
	async (req, res, next) =>
		await displaySubpage(
			`codex/${req.params.pageSlug.replace(/\/$/, "")}`,
			res,
			next
		)
);

router.get("/", async (req, res, next) => await displayIndex(res, next));

export default router;