2019-01-04 18:14:53 +00:00
|
|
|
import { promises as fs } from "fs";
|
|
|
|
import path from "path";
|
|
|
|
import hljs from "highlight.js";
|
2019-01-05 02:59:52 +00:00
|
|
|
import ejs from "ejs";
|
|
|
|
import formatDate from "date-fns/format";
|
2020-07-03 20:29:51 +00:00
|
|
|
import { Metadata } from "./metadata";
|
2019-01-04 18:14:53 +00:00
|
|
|
|
|
|
|
export async function write(filePath: string, data: any) {
|
|
|
|
const dest = path.join("out", filePath);
|
|
|
|
await fs.mkdir(path.dirname(dest), {
|
|
|
|
recursive: true
|
|
|
|
});
|
|
|
|
await fs.writeFile(dest, data);
|
|
|
|
}
|
|
|
|
|
2019-11-12 02:28:52 +00:00
|
|
|
export function getWordCount(text: string): number {
|
|
|
|
return text.split(/\s+/).length;
|
|
|
|
}
|
|
|
|
|
|
|
|
export function getReadingTime(words: number): number {
|
2019-06-29 20:01:05 +00:00
|
|
|
const avgWPM = 225;
|
|
|
|
return Math.max(1, Math.round(words / avgWPM))
|
|
|
|
}
|
|
|
|
|
2019-01-04 18:14:53 +00:00
|
|
|
export function highlight(source: string, language?: string): string {
|
|
|
|
const res = language ? hljs.highlight(language, source) : hljs.highlightAuto(source);
|
|
|
|
const highlighted = res.value;
|
|
|
|
return `<pre class="hljs"><code>${highlighted}</code></pre>`;
|
|
|
|
}
|
|
|
|
|
|
|
|
interface Chunk<T> {
|
|
|
|
chunk: T[];
|
|
|
|
index: number;
|
|
|
|
}
|
|
|
|
|
|
|
|
export function chunk<T>(array: T[], size: number): Chunk<T>[] {
|
|
|
|
const chunks: Chunk<T>[] = [];
|
|
|
|
|
|
|
|
for (let i = 0; i < array.length; i += size) {
|
|
|
|
chunks.push({
|
|
|
|
chunk: array.slice(i, i + size),
|
|
|
|
index: i / size
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
return chunks;
|
2019-01-05 02:44:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
export function fancyLink(text: string, href: string, meta?: string): string {
|
2019-01-05 16:35:01 +00:00
|
|
|
return `<a href="${href}" class="fancy-link" ${meta || ""}><span aria-hidden="true">{</span>${text}<span aria-hidden="true">}</span></a>`;
|
2019-01-05 02:59:52 +00:00
|
|
|
}
|
|
|
|
|
2020-07-03 20:29:51 +00:00
|
|
|
export function video(metadata: Metadata, name: string, attributes: object): string {
|
|
|
|
if (!attributes["poster"]) {
|
|
|
|
attributes["poster"] = `${metadata.permalink}/${name}.png`;
|
|
|
|
}
|
|
|
|
if (attributes["controls"] === undefined) {
|
|
|
|
attributes["controls"] = true;
|
|
|
|
}
|
|
|
|
var attributesStr = "";
|
|
|
|
for (const k of Object.keys(attributes)) {
|
|
|
|
const v = attributes[k];
|
|
|
|
if (typeof v == "boolean" && v) {
|
|
|
|
attributesStr += `${k} `;
|
|
|
|
} else if (typeof v == "string") {
|
|
|
|
attributesStr += `${k}="${v}" `;
|
|
|
|
} else {
|
|
|
|
console.warn(`Unexpected attribute value for ${k}: ${v}`);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return `
|
|
|
|
<video ${attributesStr}>
|
|
|
|
<source src="${metadata.permalink}/${name}.mp4" type="video/mp4">
|
|
|
|
</video>
|
|
|
|
`;
|
|
|
|
}
|
|
|
|
|
2019-01-05 02:59:52 +00:00
|
|
|
export function render(template: string, data: any, filename?: string): string {
|
2020-07-09 18:14:42 +00:00
|
|
|
data.require = require;
|
2019-01-05 02:59:52 +00:00
|
|
|
data.fancyLink = fancyLink;
|
|
|
|
data.formatDate = formatDate;
|
2020-07-03 20:29:51 +00:00
|
|
|
data.video = video;
|
2019-01-05 02:59:52 +00:00
|
|
|
return ejs.render(template, data, {
|
|
|
|
filename
|
|
|
|
});
|
2019-11-12 02:28:52 +00:00
|
|
|
}
|