144 lines
4.1 KiB
TypeScript
144 lines
4.1 KiB
TypeScript
import fs from "fs";
|
|
import {
|
|
copyFile,
|
|
readFileAsText,
|
|
writeTextAsFile,
|
|
} from "./toolchain-helpers.js";
|
|
import { toHtml } from "./markdown-parser.js";
|
|
import { IPluginBuilder, MenuManifest, Plugin } from "./typings.js";
|
|
import { path } from "@ffmpeg-installer/ffmpeg";
|
|
import ffmpeg from "fluent-ffmpeg";
|
|
|
|
type MarkdownLoaderManifestOptions = {
|
|
notesRootPath: string;
|
|
noteFileName: string;
|
|
assetsDirectoryName: string;
|
|
imageWidth?: number;
|
|
};
|
|
|
|
type MarkdownLoaderManifest = {
|
|
directoryName: string;
|
|
name: string;
|
|
markdown: string;
|
|
assetDirectoryPath: string;
|
|
publicAssetDirectoryPath: string;
|
|
assetFiles: { path: string; name: string }[];
|
|
}[];
|
|
|
|
const createMarkdownLoaderManifest = ({
|
|
notesRootPath,
|
|
assetsDirectoryName,
|
|
noteFileName,
|
|
}: MarkdownLoaderManifestOptions): MarkdownLoaderManifest => {
|
|
const directoryNames = fs.readdirSync(notesRootPath);
|
|
return directoryNames.map((noteDirectory) => {
|
|
const assetDirectoryPath = `${notesRootPath}/${noteDirectory}/${assetsDirectoryName}`;
|
|
return {
|
|
directoryName: noteDirectory,
|
|
name: noteDirectory,
|
|
markdown: fs.readFileSync(
|
|
`${notesRootPath}/${noteDirectory}/${noteFileName}`,
|
|
{ encoding: "utf-8" }
|
|
),
|
|
assetDirectoryPath,
|
|
publicAssetDirectoryPath: `/${noteDirectory}_`,
|
|
assetFiles: fs.existsSync(assetDirectoryPath)
|
|
? fs.readdirSync(assetDirectoryPath).map((name) => ({
|
|
path: `${assetDirectoryPath}/${name}`,
|
|
name,
|
|
}))
|
|
: [],
|
|
};
|
|
});
|
|
};
|
|
|
|
const copyAssetsToOutputDirectory = (
|
|
manifest: MarkdownLoaderManifest,
|
|
outputDirectory: string,
|
|
options: MarkdownLoaderOptions
|
|
) => {
|
|
ffmpeg.setFfmpegPath(path);
|
|
manifest.forEach((m) => {
|
|
return m.assetFiles.forEach((asset) => {
|
|
const isImage = asset.path.match(/\.(png|jpe?g|gif|webp)$/);
|
|
if (isImage) {
|
|
console.log("Processing image", asset.path);
|
|
ffmpeg(asset.path)
|
|
.output(`${outputDirectory}/${m.name}_${asset.name}`)
|
|
.size(`${options.imageWidth ?? 200}x?`)
|
|
.run();
|
|
} else {
|
|
return copyFile(
|
|
asset.path,
|
|
`${outputDirectory}/${m.name}_${asset.name}`
|
|
);
|
|
}
|
|
});
|
|
});
|
|
};
|
|
|
|
const writeMarkdownAsHtmlToOutputDirectory = (
|
|
markdownManifest: MarkdownLoaderManifest,
|
|
noteHtmlTemplate: string,
|
|
markdownHtmlReplacementTag: string,
|
|
outputDirectory: string
|
|
) => {
|
|
markdownManifest.forEach((m) => {
|
|
const markdownAsHtml = toHtml(m.markdown, m.publicAssetDirectoryPath);
|
|
const titleWithoutDashesOrNumbers = (m.name.slice(m.name.indexOf('-') + 1) ?? "").replaceAll('-', ' ');
|
|
const noteHtmlDocument = noteHtmlTemplate.replace(
|
|
markdownHtmlReplacementTag,
|
|
markdownAsHtml
|
|
|
|
).replace("{{title}}", titleWithoutDashesOrNumbers);
|
|
writeTextAsFile(
|
|
`${outputDirectory}/${m.directoryName}.html`,
|
|
noteHtmlDocument
|
|
);
|
|
});
|
|
};
|
|
|
|
type MarkdownLoaderOptions = {
|
|
rootPath: string;
|
|
assetsDirectoryName: string;
|
|
noteFileName: string;
|
|
noteHtmlTemplatePath: string;
|
|
markdownHtmlReplacementTag: string;
|
|
imageWidth?: number;
|
|
};
|
|
export class MarkdownLoader implements IPluginBuilder {
|
|
options: MarkdownLoaderOptions;
|
|
constructor(options: MarkdownLoaderOptions) {
|
|
this.options = options;
|
|
}
|
|
build(): Plugin {
|
|
return (builderContext) => {
|
|
const markdownManifest = createMarkdownLoaderManifest({
|
|
notesRootPath: this.options.rootPath,
|
|
assetsDirectoryName: this.options.assetsDirectoryName,
|
|
noteFileName: this.options.noteFileName,
|
|
});
|
|
builderContext.menuManifest.push(
|
|
...markdownManifest.map((m) => ({
|
|
name: m.name,
|
|
link: `/${m.directoryName}.html`,
|
|
}))
|
|
);
|
|
const noteHtmlTemplate = readFileAsText(
|
|
this.options.noteHtmlTemplatePath
|
|
);
|
|
writeMarkdownAsHtmlToOutputDirectory(
|
|
markdownManifest,
|
|
noteHtmlTemplate,
|
|
this.options.markdownHtmlReplacementTag,
|
|
builderContext.outputDirectory
|
|
);
|
|
copyAssetsToOutputDirectory(
|
|
markdownManifest,
|
|
builderContext.outputDirectory,
|
|
this.options
|
|
);
|
|
};
|
|
}
|
|
}
|