From 7a08d39f32513daf3de9656ed133c95ed5a10906 Mon Sep 17 00:00:00 2001 From: Xe Iaso Date: Fri, 14 Apr 2023 19:07:27 -0400 Subject: [PATCH] generate epub files Signed-off-by: Xe Iaso --- index.ts | 43 ++++++++++++++++++++++++++++++++++++++++++- package-lock.json | 24 ++++-------------------- package.json | 1 + wordcount.lua | 20 ++++++++++++++++++++ 4 files changed, 67 insertions(+), 21 deletions(-) create mode 100644 wordcount.lua diff --git a/index.ts b/index.ts index 18219e7..b64f998 100644 --- a/index.ts +++ b/index.ts @@ -1,11 +1,12 @@ import { Command } from "commander"; import * as dotenv from "dotenv"; import { Configuration, OpenAIApi } from "openai"; -import PlotGenerator, { Plot } from "@xeserv/plottoriffic"; +import { Plot } from "@xeserv/plottoriffic"; import { generateName } from "@kotofurumiya/th-namegen"; import * as fs from "node:fs/promises"; import { existsSync as fileExists } from "fs"; import { readPackage } from "read-pkg"; +import { execa } from "execa"; import * as book from "./book.js"; @@ -179,4 +180,44 @@ program await fs.writeFile(`${dir}/fnames.json`, JSON.stringify(fnames, undefined, " ")); }); +program + .command("buildEbook ") + .description("generate the .epub file for the novel") + .action(async (dir) => { + if (!fileExists(dir)) { + console.error(`${dir} does not exist, run init?`); + process.exit(1); + } + if (!fileExists(`${dir}/summary.json`)) { + console.error(`plot summary does not exist in ${dir}, run genSummary?`); + process.exit(1); + } + if (!fileExists(`${dir}/fnames.json`)) { + console.error(`file name list doesn't exist in ${dir}, run writeScenes?`); + process.exit(1); + } + + const summary: book.Summary = JSON.parse(await fs.readFile(`${dir}/summary.json`, "utf8")); + const fnames: string[] = JSON.parse(await fs.readFile(`${dir}/fnames.json`, "utf8")); + + await fs.writeFile( + `${dir}/src/title.txt`, + `--- +title: "${summary.title}" +author: Midori Yasomi +rights: All rights reserved +language: en-US +--- +` + ); + + await fs.writeFile(`${dir}/src/aboutAuthor.txt`, "---\n\n" + book.authorBio); + + let args = ["-o", `${dir}/ebook.epub`, "--to", "epub", `${dir}/src/title.txt`]; + args = args.concat(fnames.map((fname) => `${dir}/src/${fname}`)); + args = args.concat([`${dir}/src/aboutAuthor.txt`]); + + console.log(await execa("pandoc", args)); + }); + program.parse(); diff --git a/package-lock.json b/package-lock.json index 915715b..d5ee081 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,7 @@ "@xeserv/plottoriffic": "^2.2.0", "commander": "^10.0.0", "dotenv": "^16.0.3", + "execa": "^7.1.1", "openai": "^3.2.1", "read-pkg": "^8.0.0" }, @@ -510,7 +511,6 @@ "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -625,7 +625,6 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-7.1.1.tgz", "integrity": "sha512-wH0eMf/UXckdUYnO21+HDztteVv05rq2GXksxT4fCGeHkBhw1DROXh40wcjMcRqDOWE7iPJ4n3M7e2+YFP+76Q==", - "dev": true, "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^6.0.1", @@ -751,7 +750,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, "engines": { "node": ">=10" }, @@ -857,7 +855,6 @@ "version": "4.3.1", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz", "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==", - "dev": true, "engines": { "node": ">=14.18.0" } @@ -982,7 +979,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", - "dev": true, "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, @@ -1005,8 +1001,7 @@ "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" }, "node_modules/js-tokens": { "version": "4.0.0", @@ -1240,8 +1235,7 @@ "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" }, "node_modules/micromatch": { "version": "4.0.5", @@ -1279,7 +1273,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", - "dev": true, "engines": { "node": ">=12" }, @@ -1384,7 +1377,6 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==", - "dev": true, "dependencies": { "path-key": "^4.0.0" }, @@ -1399,7 +1391,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", - "dev": true, "engines": { "node": ">=12" }, @@ -1429,7 +1420,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", - "dev": true, "dependencies": { "mimic-fn": "^4.0.0" }, @@ -1545,7 +1535,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, "engines": { "node": ">=8" } @@ -1762,7 +1751,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, "dependencies": { "shebang-regex": "^3.0.0" }, @@ -1774,7 +1762,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, "engines": { "node": ">=8" } @@ -1782,8 +1769,7 @@ "node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" }, "node_modules/slice-ansi": { "version": "5.0.0", @@ -1892,7 +1878,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", - "dev": true, "engines": { "node": ">=12" }, @@ -1989,7 +1974,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, "dependencies": { "isexe": "^2.0.0" }, diff --git a/package.json b/package.json index df3f9e8..9d9cb66 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,7 @@ "@xeserv/plottoriffic": "^2.2.0", "commander": "^10.0.0", "dotenv": "^16.0.3", + "execa": "^7.1.1", "openai": "^3.2.1", "read-pkg": "^8.0.0" }, diff --git a/wordcount.lua b/wordcount.lua new file mode 100644 index 0000000..19d9f8e --- /dev/null +++ b/wordcount.lua @@ -0,0 +1,20 @@ +-- counts words in a document +-- from https://pandoc.org/lua-filters.html#examples + +words = 0 + +wordcount = { + Str = function(el) + -- we don't count a word if it's entirely punctuation: + if el.text:match("%P") then + words = words + 1 + end + end +} + +function Pandoc(el) + -- skip metadata, just count body: + pandoc.walk_block(pandoc.Div(el.blocks), wordcount) + print(words .. " words in body") + os.exit(0) +end