diff --git a/package-lock.json b/package-lock.json index 25e003a..70fa1e4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -31,6 +31,141 @@ "node": ">=6.9.0" } }, + "node_modules/@ffmpeg-installer/darwin-arm64": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@ffmpeg-installer/darwin-arm64/-/darwin-arm64-4.1.5.tgz", + "integrity": "sha512-hYqTiP63mXz7wSQfuqfFwfLOfwwFChUedeCVKkBtl/cliaTM7/ePI9bVzfZ2c+dWu3TqCwLDRWNSJ5pqZl8otA==", + "cpu": [ + "arm64" + ], + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@ffmpeg-installer/darwin-x64": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@ffmpeg-installer/darwin-x64/-/darwin-x64-4.1.0.tgz", + "integrity": "sha512-Z4EyG3cIFjdhlY8wI9aLUXuH8nVt7E9SlMVZtWvSPnm2sm37/yC2CwjUzyCQbJbySnef1tQwGG2Sx+uWhd9IAw==", + "cpu": [ + "x64" + ], + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@ffmpeg-installer/ffmpeg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@ffmpeg-installer/ffmpeg/-/ffmpeg-1.1.0.tgz", + "integrity": "sha512-Uq4rmwkdGxIa9A6Bd/VqqYbT7zqh1GrT5/rFwCwKM70b42W5gIjWeVETq6SdcL0zXqDtY081Ws/iJWhr1+xvQg==", + "dev": true, + "optionalDependencies": { + "@ffmpeg-installer/darwin-arm64": "4.1.5", + "@ffmpeg-installer/darwin-x64": "4.1.0", + "@ffmpeg-installer/linux-arm": "4.1.3", + "@ffmpeg-installer/linux-arm64": "4.1.4", + "@ffmpeg-installer/linux-ia32": "4.1.0", + "@ffmpeg-installer/linux-x64": "4.1.0", + "@ffmpeg-installer/win32-ia32": "4.1.0", + "@ffmpeg-installer/win32-x64": "4.1.0" + } + }, + "node_modules/@ffmpeg-installer/linux-arm": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@ffmpeg-installer/linux-arm/-/linux-arm-4.1.3.tgz", + "integrity": "sha512-NDf5V6l8AfzZ8WzUGZ5mV8O/xMzRag2ETR6+TlGIsMHp81agx51cqpPItXPib/nAZYmo55Bl2L6/WOMI3A5YRg==", + "cpu": [ + "arm" + ], + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@ffmpeg-installer/linux-arm64": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@ffmpeg-installer/linux-arm64/-/linux-arm64-4.1.4.tgz", + "integrity": "sha512-dljEqAOD0oIM6O6DxBW9US/FkvqvQwgJ2lGHOwHDDwu/pX8+V0YsDL1xqHbj1DMX/+nP9rxw7G7gcUvGspSoKg==", + "cpu": [ + "arm64" + ], + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@ffmpeg-installer/linux-ia32": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@ffmpeg-installer/linux-ia32/-/linux-ia32-4.1.0.tgz", + "integrity": "sha512-0LWyFQnPf+Ij9GQGD034hS6A90URNu9HCtQ5cTqo5MxOEc7Rd8gLXrJvn++UmxhU0J5RyRE9KRYstdCVUjkNOQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@ffmpeg-installer/linux-x64": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@ffmpeg-installer/linux-x64/-/linux-x64-4.1.0.tgz", + "integrity": "sha512-Y5BWhGLU/WpQjOArNIgXD3z5mxxdV8c41C+U15nsE5yF8tVcdCGet5zPs5Zy3Ta6bU7haGpIzryutqCGQA/W8A==", + "cpu": [ + "x64" + ], + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@ffmpeg-installer/win32-ia32": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@ffmpeg-installer/win32-ia32/-/win32-ia32-4.1.0.tgz", + "integrity": "sha512-FV2D7RlaZv/lrtdhaQ4oETwoFUsUjlUiasiZLDxhEUPdNDWcH1OU9K1xTvqz+OXLdsmYelUDuBS/zkMOTtlUAw==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@ffmpeg-installer/win32-x64": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@ffmpeg-installer/win32-x64/-/win32-x64-4.1.0.tgz", + "integrity": "sha512-Drt5u2vzDnIONf4ZEkKtFlbvwj6rI3kxw1Ck9fpudmtgaZIHD4ucsWB2lCZBXRxJgXR+2IMSti+4rtM4C4rXgg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@types/fluent-ffmpeg": { + "version": "2.1.27", + "resolved": "https://registry.npmjs.org/@types/fluent-ffmpeg/-/fluent-ffmpeg-2.1.27.tgz", + "integrity": "sha512-QiDWjihpUhriISNoBi2hJBRUUmoj/BMTYcfz+F+ZM9hHWBYABFAE6hjP/TbCZC0GWwlpa3FzvHH9RzFeRusZ7A==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/node": { "version": "20.11.5", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.5.tgz", @@ -198,6 +333,12 @@ "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", "dev": true }, + "node_modules/async": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "integrity": "sha512-eAkdoKxU6/LkKDBzLpT+t6Ff5EtfSF4wx1WfJiPEEV7WNLnDaRXk0oVysiEPm262roaachGexwUv94WhSgN5TQ==", + "dev": true + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -746,6 +887,31 @@ "node": ">=8" } }, + "node_modules/fluent-ffmpeg": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/fluent-ffmpeg/-/fluent-ffmpeg-2.1.3.tgz", + "integrity": "sha512-Be3narBNt2s6bsaqP6Jzq91heDgOEaDCJAXcE3qcma/EJBSy5FB4cvO31XBInuAuKBx8Kptf8dkhjK0IOru39Q==", + "dev": true, + "dependencies": { + "async": "^0.2.9", + "which": "^1.1.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/fluent-ffmpeg/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -1734,6 +1900,11 @@ "license": "ISC", "bin": { "zblog-toolchain": "bin/index.js" + }, + "devDependencies": { + "@ffmpeg-installer/ffmpeg": "^1.1.0", + "@types/fluent-ffmpeg": "^2.1.27", + "fluent-ffmpeg": "^2.1.3" } } } diff --git a/packages/@zblog/toolchain/package.json b/packages/@zblog/toolchain/package.json index e173676..6ee73d9 100644 --- a/packages/@zblog/toolchain/package.json +++ b/packages/@zblog/toolchain/package.json @@ -13,5 +13,10 @@ "build": "tsc -p tsconfig.json" }, "author": "", - "license": "ISC" -} + "license": "ISC", + "devDependencies": { + "@ffmpeg-installer/ffmpeg": "^1.1.0", + "@types/fluent-ffmpeg": "^2.1.27", + "fluent-ffmpeg": "^2.1.3" + } +} \ No newline at end of file diff --git a/packages/@zblog/toolchain/src/file-loader.ts b/packages/@zblog/toolchain/src/file-loader.ts index 77b2990..640b273 100644 --- a/packages/@zblog/toolchain/src/file-loader.ts +++ b/packages/@zblog/toolchain/src/file-loader.ts @@ -1,8 +1,11 @@ import { IPluginBuilder, Plugin } from "./typings.js"; import { copyFile } from "./toolchain-helpers.js"; +import { path } from "@ffmpeg-installer/ffmpeg"; +import ffmpeg from "fluent-ffmpeg"; type Options = { files: { path: string; menuEntry?: boolean; nameOverride?: string }[]; + imageWidth?: number; }; export class FileLoader implements IPluginBuilder { @@ -11,13 +14,24 @@ export class FileLoader implements IPluginBuilder { this.options = options; } build(): Plugin { + ffmpeg.setFfmpegPath(path); return async (builderContext) => { const { menuManifest } = builderContext; const { files } = this.options; files.forEach((file) => { const fileName = file.nameOverride ?? file.path.split("/").pop() ?? file.path; - copyFile(file.path, `${builderContext.outputDirectory}/${fileName}`); + const isImage = fileName.match(/\.(png|jpe?g|gif|webp)$/); + if (isImage) { + console.log("Processing image", file.path); + ffmpeg(file.path) + .output(`${builderContext.outputDirectory}/${fileName}`) + .size(`${this.options.imageWidth ?? 200}x?`) + .run(); + } else { + console.log("Copying file", file.path); + copyFile(file.path, `${builderContext.outputDirectory}/${fileName}`); + } if (file.menuEntry) { menuManifest.push({ name: fileName, diff --git a/packages/@zblog/toolchain/src/markdown-loader.ts b/packages/@zblog/toolchain/src/markdown-loader.ts index 83f09d6..38d7171 100644 --- a/packages/@zblog/toolchain/src/markdown-loader.ts +++ b/packages/@zblog/toolchain/src/markdown-loader.ts @@ -6,11 +6,14 @@ import { } 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 = { @@ -51,13 +54,27 @@ const createMarkdownLoaderManifest = ({ const copyAssetsToOutputDirectory = ( manifest: MarkdownLoaderManifest, - outputDirectory: string + outputDirectory: string, + options: MarkdownLoaderOptions ) => { - manifest.forEach((m) => - m.assetFiles.forEach((asset) => - copyFile(asset.path, `${outputDirectory}/${m.name}_${asset.name}`) - ) - ); + 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 = ( @@ -85,6 +102,7 @@ type MarkdownLoaderOptions = { noteFileName: string; noteHtmlTemplatePath: string; markdownHtmlReplacementTag: string; + imageWidth?: number; }; export class MarkdownLoader implements IPluginBuilder { options: MarkdownLoaderOptions; @@ -115,7 +133,8 @@ export class MarkdownLoader implements IPluginBuilder { ); copyAssetsToOutputDirectory( markdownManifest, - builderContext.outputDirectory + builderContext.outputDirectory, + this.options ); }; } diff --git a/packages/@zblog/toolchain/src/markdown-parser.ts b/packages/@zblog/toolchain/src/markdown-parser.ts index 4bb875b..6f2fb92 100644 --- a/packages/@zblog/toolchain/src/markdown-parser.ts +++ b/packages/@zblog/toolchain/src/markdown-parser.ts @@ -417,7 +417,7 @@ class ImageLink extends Symbol { } render() { - return `${this.alt}`; + return `${this.alt}`; } } diff --git a/src/index.ts b/src/index.ts index 1207dcc..fe5a073 100644 --- a/src/index.ts +++ b/src/index.ts @@ -18,6 +18,7 @@ new ToolchainBuilder(paths) markdownHtmlReplacementTag: "{{markdown}}", noteFileName: "note.md", noteHtmlTemplatePath: `src/templates/note.html`, + imageWidth: 800, }), new FileLoader({ files: [