forked from nm3clol/nm3clol-express-app
208 lines
8.6 KiB
TypeScript
208 lines
8.6 KiB
TypeScript
import path from 'path';
|
|
// import { globSync } from 'glob';
|
|
import fs from 'fs';
|
|
import { config } from '../config.mjs';
|
|
import markdownIt from 'markdown-it';
|
|
import markdownItAttrs from 'markdown-it-attrs';
|
|
import momentJs from 'moment-timezone';
|
|
import { inspect } from 'util';
|
|
import matter from 'gray-matter';
|
|
const moment = momentJs.tz.setDefault("UTC");
|
|
const md = markdownIt({
|
|
html: true,
|
|
linkify: true,
|
|
typographer: true,
|
|
}).use(
|
|
markdownItAttrs, {
|
|
// optional, these are default options
|
|
leftDelimiter: '{',
|
|
rightDelimiter: '}',
|
|
allowedAttributes: [] // empty array = all attributes are allowed
|
|
}
|
|
);
|
|
|
|
const getSiteName = () => config.siteName;
|
|
|
|
const trimSlashes = (dirPath: string) => {
|
|
return dirPath.replace(/^[\/\\]|[\/\\]$/g, '');
|
|
};
|
|
|
|
const getLeftMostDirectory = (directory: string) => {
|
|
if (directory.indexOf(path.sep)) {
|
|
return directory.substring(0, directory.indexOf(path.sep));
|
|
}
|
|
return directory;
|
|
}
|
|
|
|
const leftTrimFirstDirectory = (directory: string) => {
|
|
if (directory.indexOf(path.sep)) {
|
|
return directory.substring(directory.indexOf(path.sep));
|
|
}
|
|
return directory;
|
|
}
|
|
|
|
const getDirectoryName = (directory: string) => {
|
|
directory = trimSlashes(directory);
|
|
const leftMostDirectory = getLeftMostDirectory(directory);
|
|
let title = trimSlashes(leftTrimFirstDirectory(directory)).replaceAll(path.sep, path.posix.sep);
|
|
return (trimSlashes(directory)==leftMostDirectory) ? getSiteName() : title;
|
|
};
|
|
const getDirectoryTitle = (directory: string) => {
|
|
const leftMostDirectory = getLeftMostDirectory(directory);
|
|
let title = trimSlashes(leftTrimFirstDirectory(directory))
|
|
.replaceAll(path.sep, path.posix.sep)
|
|
.replaceAll('_', ' ')
|
|
.split('/')
|
|
.reverse()
|
|
.join(' - ');
|
|
return (trimSlashes(directory)==leftMostDirectory) ? getSiteName() : `${title} - ${getSiteName()}`;
|
|
};
|
|
const getSiteWelcomeMessage = () => config.siteWelcomeMessage;
|
|
const shouldShowDirectorySeparator = (index: number) => (index > 0);
|
|
const shouldShowSiteWelcomeMessage = (paths: string[]) => (paths.length == 1);
|
|
const shouldOmitLinkOnLastBreadcrumb = (paths: string[], index: number) => (index == paths.length-1);
|
|
|
|
const resolveReadmeFile: (directory: string) => string|undefined = (directory) => {
|
|
const resolveFile = (file: string) => {
|
|
const pathToFile = path.join(config.publicPath, trimSlashes(leftTrimFirstDirectory(directory)), file);
|
|
return fs.existsSync(pathToFile) ? pathToFile : "";
|
|
};
|
|
return (
|
|
resolveFile("README.md") ||
|
|
resolveFile("README.txt") ||
|
|
resolveFile("README") ||
|
|
resolveFile("README.html") ||
|
|
undefined
|
|
);
|
|
};
|
|
const directoryContainsReadme = (directory: string) => resolveReadmeFile(directory);
|
|
// const printMarkdownFile = (file) => {
|
|
// };
|
|
const readmeFm = (directory: string) => {
|
|
const readmeFile = resolveReadmeFile(directory);
|
|
if (readmeFile) {
|
|
return matter.read(readmeFile).data;
|
|
}
|
|
};
|
|
const printReadme = (directory: string) => {
|
|
const readmeFile = resolveReadmeFile(directory);
|
|
if (readmeFile) {
|
|
const fm = matter.read(readmeFile);
|
|
const fmData = { fm: fm.data, excerpt: fm.excerpt };
|
|
const content = md.render(fm.content, fmData );
|
|
return content;
|
|
}
|
|
};
|
|
const stripWebVTT = (webvttText: string) => {
|
|
const searchHeader = "WEBVTT\nKind: captions\nLanguage: en\n\n";
|
|
if (webvttText.startsWith(searchHeader)) {
|
|
webvttText = webvttText.substring(searchHeader.length-1); // remove WEBVTT header
|
|
webvttText = webvttText.replaceAll(' align:start position:0%', ''); // remove this align and position junk
|
|
webvttText = webvttText
|
|
.split('\n')
|
|
.map((line) => { return line.replaceAll(/.*<\d{2}:\d{2}:\d{2}.\d{3}>.*/g, '').trim() }) // remove all the animated subtitles and trim the whitespace on each line
|
|
.join('\n');
|
|
while (webvttText.indexOf('\n\n\n') > -1) {
|
|
webvttText = webvttText.replace('\n\n\n', '\n\n'); // remove every instance of triple vertical white space, while allowing double vertical white space
|
|
}
|
|
webvttText = webvttText.replaceAll(/(\d{2}:\d{2}:\d{2}.\d{3}) --> (\d{2}:\d{2}:\d{2}.\d{3})\n(.*)\n\n(\2) --> (\d{2}:\d{2}:\d{2}.\d{3})\n\3\n/g, '$1 --> $5\n$3\n'); // remove every duplicate entry detected
|
|
webvttText = webvttText.replaceAll('\n', '<br/>'); // convert \n to <br/>
|
|
}
|
|
return webvttText;
|
|
};
|
|
const renderArchive = (html: string, paths: string[]) => {
|
|
// Header and Footer content
|
|
const headHeaderContent = ``;
|
|
const headFooterContent = `
|
|
<!-- Dynamically Inserted Code by ${getSiteName()} -->
|
|
<style>
|
|
.__archived__content__, .__archived__content__ p { background-color: #f44336; color: #fff; font-size: 12pt; font-family: "Noto Serif", Times, "Times New Roman", serif; text-align: center; }
|
|
.__archived__content__ h1 { font-family: "Cinzel Decorative", Verdana, Arial, sans-serif; color: #fff; font-weight: 700; font-size: 18pt; text-align: center; }
|
|
.__archived__content__ h2 { font-family: "Covered By Your Grace", Verdana, Arial, sans-serif; color: #fff; font-weight: 700; font-size: 18pt; text-align: center; }
|
|
.__archived__content__ { padding: 2rem; }
|
|
.__archived__content__:first-of-type { margin-top: 0; margin-bottom: 0; }
|
|
.__archived__content__:last-of-type { margin-top: 1rem; margin-bottom: 0; }
|
|
.__archived__content__ .__archived__content__ p { margin-top: 1rem; }
|
|
.__archived__content__ a:link, .__archived__content__ a:visited { color: #fff; }
|
|
.__archived__content__ a:hover, .__archived__content__ a:active { text-decoration: none; }
|
|
.__archived__content__ ::selection {
|
|
background-color: #fff;
|
|
color: #f44336;
|
|
}
|
|
.__archived__content__ ::-moz-selection {
|
|
background-color: #fff;
|
|
color: #f44336;
|
|
}
|
|
</style>
|
|
<link href="https://fonts.googleapis.com/css?family=Cinzel+Decorative:100,200,300,400,500,600,700,800,900" rel="stylesheet">
|
|
<link href="https://fonts.googleapis.com/css?family=Covered+By+Your+Grace:100,200,300,400,500,600,700,800,900" rel="stylesheet">
|
|
<link href="https://fonts.googleapis.com/css?family=Noto+Serif:100,200,300,400,500,600,700,800,900" rel="stylesheet">
|
|
<!-- Google tag (gtag.js) -->
|
|
<script async src="https://www.googletagmanager.com/gtag/js?id=G-HQR3Z1EZQM"></script>
|
|
<script>
|
|
window.dataLayer = window.dataLayer || [];
|
|
function gtag(){dataLayer.push(arguments);}
|
|
gtag('js', new Date());
|
|
|
|
gtag('config', 'G-HQR3Z1EZQM');
|
|
</script>
|
|
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-8937572456576531" crossorigin="anonymous"></script>
|
|
<!-- End dynamically inserted code -->
|
|
`;
|
|
const bodyHeaderContent = `
|
|
<!-- Dynamically Inserted Code by ${getSiteName()} -->
|
|
<div class="__archived__content__">
|
|
<h1>${getSiteName()}</h1>
|
|
<h2>Archived Web Site</h2>
|
|
<p>
|
|
This is an archived version of the original website. Online features will not be functional. Do not submit any personal information to this archive.
|
|
</p>
|
|
<p>
|
|
<a href="./">Current Directory Listing</a> | <a href="/">Back to Library Home</a>
|
|
</p>
|
|
</div>
|
|
<!-- End dynamically inserted code -->
|
|
`;
|
|
const bodyFooterContent = `
|
|
<!-- Dynamically Inserted Code by ${getSiteName()} -->
|
|
<div class="__archived__content__">
|
|
<p>
|
|
This is an archived version of the original website. Online features will not be functional. Do not submit any personal information to this archive.
|
|
</p>
|
|
<p>
|
|
<a href="./">Current Directory Listing</a> | <a href="/">Back to Library Home</a>
|
|
</p>
|
|
</div>
|
|
<!-- End dynamically inserted code -->
|
|
`;
|
|
|
|
// Add archive branding
|
|
html = html.substring(0, html.indexOf('>', html.indexOf('<head')) + '>'.length) + headHeaderContent + html.substring(html.indexOf('>', html.indexOf('<head')) + '>'.length);
|
|
html = html.substring(0, html.indexOf('</head>') + '</head>'.length) + headFooterContent + html.substring(html.indexOf('</head>') + '</head>'.length);
|
|
html = html.substring(0, html.indexOf('>', html.indexOf('<body')) + '>'.length) + bodyHeaderContent + html.substring(html.indexOf('>', html.indexOf('<body')) + '>'.length);
|
|
html = html.substring(0, html.indexOf('</body>') + '</body>'.length) + bodyFooterContent + html.substring(html.indexOf('</body>') + '</body>'.length);
|
|
|
|
// Output the modified HTML content
|
|
return html;
|
|
}
|
|
|
|
export default {
|
|
leftTrimFirstDirectory,
|
|
trimSlashes,
|
|
getSiteName,
|
|
getDirectoryName,
|
|
getDirectoryTitle,
|
|
getSiteWelcomeMessage,
|
|
shouldShowDirectorySeparator,
|
|
shouldShowSiteWelcomeMessage,
|
|
shouldOmitLinkOnLastBreadcrumb,
|
|
directoryContainsReadme,
|
|
readmeFm,
|
|
printReadme,
|
|
stripWebVTT,
|
|
renderArchive,
|
|
config,
|
|
inspect,
|
|
md,
|
|
moment,
|
|
}; |