nm3clol-express-app/app/page/router.mts

274 lines
10 KiB
TypeScript

console.log(`Loading nm3clol-express-app directory router module...`);
import { config } from '../config.mjs';
import express from 'express';
import serve from './vercel-serve.mjs';
import path from 'path';
import { globSync } from 'glob';
import matter from 'gray-matter';
import ejs from 'ejs';
import helpers from '../helpers/functions.mjs';
import fs from 'fs';
import { readFile } from 'fs/promises';
import { Breadcrumb } from '../helpers/breadcrumbs.mjs';
export default function () {
const pageRouter = express.Router();
// // Serve static files (CSS, JavaScript, images, etc.)
// app.use(serve('../public', {
// dotfiles: 'ignore',
// index: false,
// }));
// app.get('/', (req, res) => {
// res.send('Hello World!');
// })
// console.log("Setting route for /ads.txt");
// app.get('/ads.txt', (req, res) => {
// res.setHeader("Content-Type", "text/plain");
// res.setHeader("Cache-Control", "no-cache");
// res.send(`google.com, pub-8937572456576531, DIRECT, f08c47fec0942fa0`);
// });
console.log(`Serving /robots.txt from memory.`);
pageRouter.get('/robots.txt', (req, res) => {
res.setHeader("Content-Type", "text/plain");
res.setHeader("Cache-Control", "no-cache");
// TODO: Implement Site Map feature and provide sitemap url in robots.txt
res.send(
`User-agent: *
Allow: /
# TODO: Implement Site Map feature and provide sitemap url in robots.txt
#sitemap: https://no-moss-3-carbo-landfill-library.online/sitemap.xml`
);//end of res.send() for robots.txt
});
// Endpoints for all the site's pages.
console.log(`Scanning for pages in ${config.pagesPath} to create routes.`);
globSync('**/*.md', {
cwd: config.pagesPath,
matchBase: true,
follow: true,
}).forEach((filePath) => {
const expressRoutePathFromFilePath = (filePath: string) => {
filePath = filePath.substring(0, filePath.length - path.extname(filePath).length).replaceAll(path.sep, path.posix.sep);
if (!filePath.startsWith('/') && filePath.length > 0) {
filePath = `/${filePath}`;
}
return filePath;
};
const route = expressRoutePathFromFilePath(filePath);
const fullFilePath = path.join(config.pagesPath, filePath);
let paths = route.split(path.posix.sep);
console.log(`Serving ${route} route as a page at ${fullFilePath}.`);
pageRouter.get(route, async (req, res) => {
const fm = matter.read(fullFilePath);
const fmData = { fm: fm.data, excerpt: fm.excerpt };
const content = helpers.md.render(fm.content, fmData );
let breadcrumbs: Breadcrumb[] = [];
paths.forEach((path, index) => {
if (index == 0) {
breadcrumbs.push({ title: config.siteName, url: '/' });
}
else {
breadcrumbs.push({ title: fmData.fm['title']||path.replaceAll('_', ' ').replaceAll('-', ' '), url: helpers.trimSlashes(helpers.leftTrimFirstDirectory(path)) });
}
});
const renderData = { breadcrumbs, content, filePath, fullFilePath, paths, req, route, ...fmData };
res.render("page", { h: helpers, ...renderData });
});
});
// console.log("Scanning for documents to create routes.");
// glob.globSync('**/*{.pdf,.docx,.xlsx,.pptx,.doc,.xls,.ppt}', {
// cwd: path.join(config.publicPath),
// matchBase: true,
// follow: true,
// }).forEach((filePath) => {
// const expressRoutePathFromFilePath = (filePath) => {
// return filePath.substring(0, filePath.length - path.extname(filePath).length).replaceAll(path.sep, path.posix.sep);
// };
// const route = expressRoutePathFromFilePath(filePath);
// const fullFilePath = path.join(config.publicPath, filePath);
// let paths = route.split(path.posix.sep);
// paths[0] = 'public';
// console.log(`Setting route for ${route}`);
// app.get(route, async (req, res) => {
// const fm = matter.read(fullFilePath);
// const fmData = { fm: fm.data, excerpt: fm.excerpt };
// const content = helpers.md.render(fm.content, fmData );
// const renderData = { content, route, filePath, fullFilePath, req, paths, ...fmData };
// res.render("page", { h: helpers, ...renderData });
// });
// });
//TODO: Rewrite this facility so that it utilizes Git index as a filesystem.
console.log("Scanning for web archive HTML documents to create routes.");
globSync('Web_Site_Archives/**/*{.htm,.html}', {
cwd: config.publicPath,
matchBase: true,
follow: true,
}).forEach((filePath) => {
const expressRoutePathFromFilePath = (filePath: string) => {
return '/' + filePath.replaceAll(path.sep, path.posix.sep);
};
const route = expressRoutePathFromFilePath(filePath);
const fullFilePath = path.join(config.publicPath, filePath);
let paths = route.split(path.posix.sep);
paths[0] = 'public';
console.log(`Setting route for ${route}`);
pageRouter.get(route, async (req, res) => {
const html = fs.readFileSync(fullFilePath).toString();
const renderData = { route, filePath, fullFilePath, req, paths, html };
res.render("archive", { h: helpers, ...renderData });
});
});
//TODO: Rewrite this facility so that it utilizes Git index as a filesystem.
console.log("Scanning for archived videos to create routes.");
globSync(['Russell_County/Board_of_Supervisors/YouTube_Archive/**/*.info.json', 'Virginia_Energy/YouTube_Archive/**/*.info.json', 'Virginia_Governor/**/*.info.json'], {
cwd: config.publicPath,
matchBase: true,
follow: true,
}).forEach((filePath: string) => {
const expressRoutePathFromFilePath = (filePath: string) => {
return path.posix.sep+filePath.substring(0, filePath.lastIndexOf(path.sep)).replaceAll(path.sep, path.posix.sep);
};
const dirFromFilePath = (filePath: string) => {
return filePath.substring(0, filePath.lastIndexOf(path.sep));
}
const directory = dirFromFilePath(filePath);
let videoURL = ""+globSync("*.{mpg,mpeg,mp4,mkv,webm}", {
cwd: path.join(config.publicPath, directory),
matchBase: true,
follow: true,
}).pop();
let subtitleURL = ""+globSync("*.en.vtt", {
cwd: path.join(config.publicPath, directory),
matchBase: true,
follow: true,
}).pop();
let subtitleFile = path.join(config.publicPath, directory, subtitleURL);
const route = encodeURI(expressRoutePathFromFilePath(filePath));
let paths = filePath
.substring(0, filePath.lastIndexOf(path.sep) > 0 ? filePath.lastIndexOf(path.sep) : filePath.length-1)
.split(path.sep)
.map((name, idx, aPaths) => {
let url = aPaths.slice(0, idx+1).join(path.posix.sep);
return {
name,
url,
};
});
const fullFilePath = path.join(config.publicPath, filePath);
console.log(`Setting route for ${route}`);
pageRouter.get(route, async (req, res) => {
if (!req.path.endsWith('/')) {
res.redirect(req.path + '/');
}
else {
let info = JSON.parse((await readFile(fullFilePath)).toString());
let subtitleVTT = fs.existsSync(subtitleFile) ? (await readFile(subtitleFile)).toString() : '';
const renderData = { route, filePath, fullFilePath, req, paths, directory: path.join('public', directory), videoURL, subtitleURL, subtitleVTT, info };
res.render("video-player", { h: helpers, ...renderData });
}
});
});
//app.get('/OCR-Encoded-PDFs/Russell-County-Web-Site_2024-02-13_19_50_Modified-With-OCR-Encoding**', rewriter.rewrite('/Web_Site_Archives/Russell_County_Web_Site-2024-02-13_19_50_Modified_With_OCR_Encoding/$1'));
console.log(`Serving /vendor/**/* route for all files in ${path.join(config.assetsPath, 'vendor')}`);;
pageRouter.get('/vendor/**/*', async (req, res) => {
await serve(req, res, {
public: config.assetsPath,
symlinks: true,
trailingSlash: true,
cleanUrls: false,
renderSingle: false,
unlisted: [
".DS_Store",
".git",
"Thumbs.db",
"README*",
],
});
});
console.log(`Serving /css/*.css route for all files in ${path.join(config.assetsPath, 'css')}`);;
pageRouter.get('/css/*.css', async (req, res) => {
await serve(req, res, {
public: config.assetsPath,
symlinks: true,
trailingSlash: true,
cleanUrls: false,
renderSingle: false,
unlisted: [
".DS_Store",
".git",
"Thumbs.db",
"README*",
],
});
});
console.log(`Serving /svg/*.svg route for all files in ${path.join(config.assetsPath, 'svg')}`);;
pageRouter.get('/svg/*.svg', async (req, res) => {
await serve(req, res, {
public: config.assetsPath,
symlinks: true,
trailingSlash: true,
cleanUrls: false,
renderSingle: false,
unlisted: [
".DS_Store",
".git",
"Thumbs.db",
"README*",
],
});
});
//TODO: Rewrite this facility so that it utilizes Git index as a filesystem.
console.log(`Serving * default route for all files in ${config.publicPath}`);;
pageRouter.get('*', async (req, res) => {
await serve(req, res, {
public: config.publicPath,
symlinks: true,
trailingSlash: true,
cleanUrls: false,
renderSingle: false,
unlisted: [
".*", //dot files/folders
"Thumbs.db"
],
redirects: [
{
source: "/:year(\d{4})-:mo(\d{2})-:dd(\d{2})_:hh(\d{2})_:mm(\d{2})/",
destination: "/Web_Site_Archives/Russell_County_Web_Site-:year-:mo-:dd_:hh_:mm/"
},
{
source: "/OCR-Encoded-PDFs",
destination: "/Web_Site_Archives"
},
{
source: "/OCR-Encoded-PDFs/Russell-County-Web-Site_2024-02-13_19_50_Modified-With-OCR-Encoding.zip",
destination: "/Web_Site_Archives/Russell_County_Web_Site-2024-02-13_19_50_Modified_With_OCR_Encoding.zip"
},
{
source: "/OCR-Encoded-PDFs/Russell-County-Web-Site_2024-02-13_19_50_Modified-With-OCR-Encoding/:u(.*)",
destination: "/Web_Site_Archives/Russell_County_Web_Site-2024-02-13_19_50_Modified_With_OCR_Encoding:u"
},
{ source: '/YouTube Channel', destination: '/Russell_County/Board_of_Supervisors/YouTube_Archive/@russellcountyvirginia8228' },
// { source: '/YouTube Channel.zip', destination: '/Russell_County_BOS/YouTube_Channel.zip' },
// { source: '/YouTube Channel/:u?', destination: '/Russell_County_BOS/YouTube_Channel/:u' },
{ source: '/Project Reclaim [WI19KR9Ogwg].mkv', destination: '/YouTube_Archives/@VADMME/Project Reclaim [WI19KR9Ogwg].mkv' },
]
});
});
return pageRouter;
};