From 2ade53f268df7c34bc334895ab0cc360732a8140 Mon Sep 17 00:00:00 2001 From: Talon Poole Date: Thu, 11 Feb 2021 23:26:29 +0000 Subject: [PATCH] three --css modes: gmi.css, base and none when "none" inline tags will be wrapped in

--image, --audio and --video now accept the extensions to inline so what's possible to load isn't maintained here --lang is now referred to as --html --html and --body are mutually exclusive --- .prettierignore | 1 + Makefile | 12 +++----- cli.js | 62 ++++++++++++++++++++++++++---------------- gmi-web.1 | 2 +- gmi.html.js => html.js | 34 ++++++++++++++++------- package.json | 6 ++-- test.sh | 2 +- 7 files changed, 71 insertions(+), 48 deletions(-) create mode 100644 .prettierignore rename gmi.html.js => html.js (83%) diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..90c978b --- /dev/null +++ b/.prettierignore @@ -0,0 +1 @@ +example/ diff --git a/Makefile b/Makefile index 78c5298..8e440f2 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,5 @@ -build: format gmi-web.1 gmi.css.5 +build: gmi-web.1 gmi.css.5 + npm install gmi-web.1: gmi-web.1.scd scdoc < $< > $@ @@ -6,15 +7,10 @@ gmi-web.1: gmi-web.1.scd gmi.css.5: gmi.css.5.scd scdoc < $< > $@ -format: - ./node_modules/prettier/bin-prettier.js --write README.md - ./node_modules/prettier/bin-prettier.js --write gmi.css - ./node_modules/prettier/bin-prettier.js --write *.js !*.min.js - example/test.html: example/test.gmi ./test.sh clean: - rm -rf gmi.min.* gmi-web.1 gmi.css.5 node_modules + rm -rf gmi-web.1 gmi.css.5 node_modules -.PHONY: clean format +.PHONY: clean diff --git a/cli.js b/cli.js index 954daac..e80272b 100755 --- a/cli.js +++ b/cli.js @@ -5,33 +5,38 @@ import fs from "vinyl-fs"; import map from "map-stream"; import yargs from "yargs"; import CleanCSS from "clean-css"; -import toHTML, { BASE_CSS, html } from "./gmi.html.js"; +import toHTML, { BASE_CSS, html } from "./html.js"; const cli = yargs(process.argv.slice(2)) .scriptName("gmi-web") - .command("$0 [files..]", "Convert text/gemini to text/html.", (yargs) => yargs - //yargs.positional("files") + .command("$0 [files..]", "Convert text/gemini to text/html.", (yargs) => + yargs + .example("$0 --html en $(find ~/my-capsule -name '*.gmi')") + .example("$0 --body < ~/my-capsule/index.gmi") ) .options({ - language: { - alias: "lang", - required: true, + html: { + type: "string", + requiresArg: true, }, css: { + choices: ["gmi.css", "base", "none"], + default: "gmi.css", + }, + body: { type: "boolean", - default: true, }, }); cli.options({ - images: { - type: "boolean", + image: { + type: "array", }, audio: { - type: "boolean", + type: "array", }, video: { - type: "boolean", + type: "array", }, }); @@ -59,24 +64,24 @@ const GMI_CSS_VARS = [ "sans-serif", ].map((key) => { cli.option(key); + cli.conflicts(key, "body"); return key; }); const argv = cli - .group(["language", "css"], "Core:") + .conflicts("html", "body") + .group(["html", "css", "body"], "Core:") .group(GMI_CSS_VARS, "CSS Variables:") .group(["images", "audio", "video"], "Inline Media:") + .alias("html", "language") + .alias("html", "lang") .config() - .example("$0 --lang en $(find ~/my-capsule -name '*.gmi')") - .example("cat ~/my-capsule/index.gmi | $0 --lang en") .epilog("See the gmi-web(1) man page for more information!") .showHelpOnFail(true) .help().argv; -argv.css = argv.css || BASE_CSS; - let styles = ""; -if (argv.css) { +if (argv.css === "gmi.css") { styles = GMI_CSS_VARS.reduce((style, key) => { if (argv[key]) { style += `--${key}: ${argv[key]};`; @@ -93,19 +98,28 @@ if (argv.css) { "utf8" ) ).styles; +} else if (argv.css === "base") { + argv.css = BASE_CSS; +} else { + argv.css = ""; +} + +if (!argv.lang && !argv.body) { + cli.showHelp(); + console.error(`\nMissing required argument: --html or --body`); + cli.exit(1); } if (!argv.files) { - let gemtext + let gemtext; try { - gemtext = readFileSync(process.stdin.fd) + gemtext = readFileSync(process.stdin.fd); } catch (e) { - console.error("Either send a file to this program from stdin") - console.error("or provide [files..]\n") - console.error("See --help or read gmi-web(1) for usage details.") - process.exit(1) + console.error(`Either send a file to this program from stdin or provide [files..] +See --help or read gmi-web(1) for usage details.`); + cli.exit(1); } - console.log(html({ contents: gemtext }, argv)) + console.log(html({ contents: gemtext }, argv)); } else { fs.src(argv.files) .pipe( diff --git a/gmi-web.1 b/gmi-web.1 index 54f5fcf..ceee27b 100644 --- a/gmi-web.1 +++ b/gmi-web.1 @@ -5,7 +5,7 @@ .nh .ad l .\" Begin generated content: -.TH "gmi-web" "1" "2021-02-10" "1.0.7-rc.1" +.TH "gmi-web" "1" "2021-02-11" "1.0.7-rc.1" .P .SH NAME .P diff --git a/gmi.html.js b/html.js similarity index 83% rename from gmi.html.js rename to html.js index de1e0f0..f130813 100644 --- a/gmi.html.js +++ b/html.js @@ -29,8 +29,12 @@ export const BASE_CSS = "p,a,pre,h1,h2,h3,ul,blockquote,img,audio,video{display:block;max-width:100%;margin:0;padding:0;overflow-wrap:anywhere;}"; export function head(options) { return ` - - +${ + options.css !== "" + ? `` + : "" +} +${options.css !== "" ? `` : ""} @@ -46,31 +50,41 @@ export function head(options) { `; } -export const IMAGE_EXT = /\.(apng|avif|gif|jpg|jpeg|jfif|pjpeg|pjp|png|svg|webp)$/; -export const AUDIO_EXT = /\.(mp3|wav|aac|aacp|mpeg|off|flac)$/; -export const VIDEO_EXT = /\.(mp4|webm)$/; - function line( { text, href, title, pre, alt, h1, h2, h3, li, quote }, - { images, audio, video } = {} + { image, audio, video, css } = {} ) { if (text) return `

${escape(text)}

`; + + const matchesExt = (url, exts) => + exts.some((ext) => new RegExp(`\.${ext}$`).test(url)); if (href) { const titleProp = title ? ` title="${title}"` : ""; - if (images && IMAGE_EXT.test(href)) + if (image && matchesExt(href, image)) { return ``; - if (audio && AUDIO_EXT.test(href)) + } + if (audio && matchesExt(href, audio)) { + if (css === "") { + return `

`; + } return ``; - if (video && VIDEO_EXT.test(href)) + } + if (video && matchesExt(href, video)) return ``; + if (css === "") { + return `

${title ? escape(title) : href}

`; + } return `${title ? escape(title) : href}`; } + if (h1) return `

${escape(h1)}

`; if (h2) return `

${escape(h2)}

`; if (h3) return `

${escape(h3)}

`; if (li) return `
  • ${escape(li)}
  • `; + if (quote) return `
    ${escape(quote)}
    `; + return `


    `; } diff --git a/package.json b/package.json index 69a397a..f9a0d1c 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "gmi-web-cli", "version": "1.0.7-rc.1", "description": "A bridge between HTML and Gemini", - "main": "cli.js", + "main": "html.js", "type": "module", "bin": { "gmi-web": "cli.js" @@ -23,9 +23,7 @@ "gmi.css.5" ], "scripts": { - "build": "npm install && make", - "prepare": "make", - "clean": "make clean" + "prepare": "prettier --write ." }, "dependencies": { "clean-css": "^5.0.1", diff --git a/test.sh b/test.sh index 808e2bb..50355ca 100755 --- a/test.sh +++ b/test.sh @@ -1,5 +1,5 @@ rm -rf "example/test.html" -./cli.js --lang en --images --audio --video "example/*.gmi" +./cli.js --image jpg --audio mp3 --video mp4 --html en "example/*.gmi" if cmp -s "example/test.html" "example/expected.html"; then printf "PASS: test.html matches expected.html!\n" else