#!/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", }, html: { type: "string", requiresArg: true, }, dir: { type: "string", choices: ["rtl", "ltr"], default: "ltr", requiresArg: true, }, author: { type: "string", requiresArg: true, }, descriptions: { type: "number", default: 0, }, css: { default: "full", requiresArg: true, }, inline: { type: "boolean", group: "CSS:", }, image: { type: "array", requiresArg: true, }, audio: { type: "array", requiresArg: true, }, video: { type: "array", requiresArg: true, }, charset: { type: "string", hidden: true, default: "utf-8", requiresArg: true, }, schemes: { type: "boolean", hidden: true, default: false, group: "CSS:", }, }) .group(["html", "body"], "Core:") .group(["author", "descriptions", "css", "schemes", "dir"], "HTML:") .group(["image", "audio", "video"], "Inline Media:"); const CSS_VARS = CSS.rootVariables(CSS.FULL); Object.keys(CSS_VARS).map((key) => { cli.option(key, { default: CSS_VARS[key] }); cli.conflicts(key, "core"); cli.conflicts(key, "none"); return key; }); cli.group(Object.keys(CSS_VARS), "CSS:"); const argv = cli .conflicts("author", "body") .conflicts("html", "body") .alias("html", "language") .alias("html", "lang") .showHelpOnFail(true) .help().argv; if (argv.inline && argv.css === "full") { cli.showHelp(); console.error(`\n--inline is not compatible with --css full`); cli.exit(1); } if (!argv.html && !argv.body) { cli.showHelp(); console.error(`\nMissing required argument: --html or --body`); cli.exit(1); } 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))); }