gmi-web/cli.js
2021-02-22 00:26:56 +00:00

130 lines
3.1 KiB
JavaScript
Executable file

#!/usr/bin/env node
import { readFileSync, existsSync } from "fs";
import path from "path";
import fs from "vinyl-fs";
import yargs from "yargs";
import * as CSS from "./css.js";
import { streamHTML, toHTML } from "./html.js";
const cli = yargs(process.argv.slice(2))
.config("config", function (path) {
return JSON.parse(readFileSync(path), "utf-8");
})
.scriptName("gmi-web")
.command("$0 [files..]", "Convert text/gemini to text/html.", (yargs) =>
yargs
.example("$0 --body < ~/my-capsule/index.gmi")
.example("$0 --html en $(find ~/my-capsule -name '*.gmi')")
.example(
"$0 --foreground '#000000' --background '#EEEEEE' --html en < doc.gmi"
)
.example("$0 --image jpg --audio mp3 --image png --body < doc.gmi")
.epilog("See the gmi-web(1) man page for more information.")
)
.options({
body: {
type: "boolean",
group: "Core:",
},
html: {
type: "string",
requiresArg: true,
group: "Core:",
},
css: {
requiresArg: true,
group: "Core:",
},
dir: {
type: "string",
hidden: true,
choices: ["rtl", "ltr"],
default: "ltr",
requiresArg: true,
group: "HTML:",
},
author: {
type: "string",
requiresArg: true,
group: "HTML:",
},
descriptions: {
coerce: (arg) => (typeof arg === "number" ? arg : arg ? Infinity : 0),
group: "HTML:",
},
charset: {
type: "string",
hidden: true,
default: "utf-8",
requiresArg: true,
group: "HTML:",
},
image: {
type: "array",
requiresArg: true,
group: "Media:",
},
audio: {
type: "array",
requiresArg: true,
group: "Media:",
},
video: {
type: "array",
requiresArg: true,
group: "Media:",
},
inline: {
type: "boolean",
hidden: true,
group: "CSS:",
},
});
// TODO: checks for any .css arg, instead of parsing --css
const css = process.argv.find(arg => /\.css$/.test(arg)) || "gmi-web.css"
const CSS_VARS = CSS.rootVariables(CSS.load({ css }));
Object.keys(CSS_VARS).forEach((key) => {
const opt = key.replace("--", "");
cli.option(opt, { default: CSS_VARS[key] });
cli.conflicts(opt, "core");
cli.conflicts(opt, "none");
});
cli.group(
Object.keys(CSS_VARS).map((key) => key.replace("--", "")),
`${css}:`
);
const argv = cli
.conflicts("author", "body")
.conflicts("html", "body")
.alias("html", "language")
.alias("html", "lang")
.showHelpOnFail(true)
.help().argv;
if (!argv.html && !argv.body) {
cli.showHelp();
console.error(`\nMissing required argument: --html or --body`);
cli.exit(1);
}
argv.inlineCSS = CSS.inline(argv);
argv.styleTag = CSS.style(argv);
if (!argv.files) {
let gemtext;
try {
gemtext = readFileSync(process.stdin.fd, "utf-8");
} catch (e) {
cli.showHelp();
console.error("\nMissing files: pipe from stdin or provide [files..]");
cli.exit(1);
}
console.log(toHTML(gemtext, argv));
} else {
fs.src(argv.files)
.pipe(streamHTML(argv))
.pipe(fs.dest((file) => path.dirname(file.path)));
}