gmi-web/cli.js

137 lines
3.2 KiB
JavaScript
Raw Normal View History

2021-01-28 06:16:46 +00:00
#!/usr/bin/env node
2021-02-15 20:56:41 +00:00
import { readFileSync, existsSync } from "fs";
import path from "path";
import fs from "vinyl-fs";
import map from "map-stream";
import yargs from "yargs";
2021-02-15 20:56:41 +00:00
import * as CSS from "./css.js";
import toHTML, { html } from "./html.js";
const cli = yargs(process.argv.slice(2))
.config("config", function (path) {
2021-02-15 20:56:41 +00:00
return JSON.parse(readFileSync(path), "utf-8");
})
.scriptName("gmi-web")
.command("$0 [files..]", "Convert text/gemini to text/html.", (yargs) =>
yargs
2021-02-15 20:56:41 +00:00
.example("$0 --body < ~/my-capsule/index.gmi")
.example("$0 --html en $(find ~/my-capsule -name '*.gmi')")
2021-02-12 20:41:43 +00:00
.example(
"$0 --foreground '#000000' --background '#EEEEEE' --html en < doc.gmi"
)
2021-02-11 23:49:39 +00:00
.example("$0 --image jpg --audio mp3 --image png --body < doc.gmi")
.epilog("See the gmi-web(1) man page for more information")
)
.options({
2021-02-11 23:49:39 +00:00
body: {
type: "boolean",
},
html: {
type: "string",
requiresArg: true,
},
2021-02-15 17:17:16 +00:00
dir: {
type: "string",
choices: ["rtl", "ltr"],
default: "ltr",
requiresArg: true,
},
author: {
2021-02-12 01:59:02 +00:00
type: "string",
requiresArg: true,
},
descriptions: {
type: "boolean",
},
css: {
2021-02-15 20:56:41 +00:00
default: "full",
2021-02-15 17:17:16 +00:00
requiresArg: true,
},
charset: {
type: "string",
hidden: true,
default: "utf-8",
requiresArg: true,
},
2021-02-15 20:56:41 +00:00
image: {
type: "array",
requiresArg: true,
},
audio: {
type: "array",
requiresArg: true,
},
video: {
type: "array",
requiresArg: true,
},
});
2021-02-15 20:56:41 +00:00
const CSS_VARS = CSS.rootVariables(CSS.FULL);
Object.keys(CSS_VARS).map((key) => {
cli.option(key, { default: CSS_VARS[key] });
return key;
});
2021-01-29 22:32:30 +00:00
const argv = cli
.conflicts("author", "body")
2021-02-15 20:56:41 +00:00
.conflicts("descriptions", "body")
.conflicts("html", "body")
.group(["html", "body"], "Core:")
2021-02-15 20:56:41 +00:00
.group(["author", "descriptions", "css", "dir"], "HTML:")
2021-02-11 23:49:39 +00:00
.group(["image", "audio", "video"], "Inline Media:")
2021-02-15 20:56:41 +00:00
.group(Object.keys(CSS_VARS), "CSS:")
.alias("html", "language")
.alias("html", "lang")
2021-02-15 20:56:41 +00:00
.coerce("css", (arg) => {
if (arg === "full") {
return CSS.stringify(CSS.FULL, { compress: true });
} else if (arg === "core") {
return CSS.stringify(CSS.CORE, { compress: true });
} else if (arg !== "none" && arg !== "") {
if (existsSync(path.resolve(arg))) {
return CSS.resolve(arg, { compress: true });
} else {
return CSS.parse(arg);
}
}
})
.showHelpOnFail(true)
2021-01-28 06:16:46 +00:00
.help().argv;
2021-02-15 20:56:41 +00:00
if (!argv.html && !argv.body) {
cli.showHelp();
console.error(`\nMissing required argument: --html or --body`);
cli.exit(1);
}
2021-02-15 20:56:41 +00:00
let styles = Object.keys(CSS_VARS).reduce((style, key) => {
if (argv[key]) {
style += `--${key}: ${argv[key]};`;
}
return style;
}, "");
if (!argv.files) {
let gemtext;
try {
2021-02-15 20:56:41 +00:00
gemtext = readFileSync(process.stdin.fd, "utf-8");
} catch (e) {
2021-02-12 01:59:02 +00:00
cli.showHelp();
console.error("\nMissing files: pipe from stdin or provide [files..]");
cli.exit(1);
}
console.log(html({ contents: gemtext }, argv));
} else {
fs.src(argv.files)
.pipe(
map(
toHTML({
...argv,
styles,
})
)
)
.pipe(fs.dest((file) => path.dirname(file.path)));
}