three --css modes: gmi.css, base and none
when "none" inline tags will be wrapped in <p> --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
This commit is contained in:
parent
9184e2c792
commit
2ade53f268
1
.prettierignore
Normal file
1
.prettierignore
Normal file
|
@ -0,0 +1 @@
|
|||
example/
|
12
Makefile
12
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
|
||||
|
|
62
cli.js
62
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(
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 `
|
||||
<meta name="color-scheme" content="dark light">
|
||||
<style>${options.css}</style>
|
||||
${
|
||||
options.css !== ""
|
||||
? `<meta name="color-scheme" content="dark light">`
|
||||
: ""
|
||||
}
|
||||
${options.css !== "" ? `<style>${options.css}</style>` : ""}
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<meta charset="${options.charset}">
|
||||
<meta language="${options.language}">
|
||||
|
@ -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 `<p>${escape(text)}</p>`;
|
||||
|
||||
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 `<img src="${href}"${titleProp}/>`;
|
||||
if (audio && AUDIO_EXT.test(href))
|
||||
}
|
||||
if (audio && matchesExt(href, audio)) {
|
||||
if (css === "") {
|
||||
return `<p><audio controls src="${href}"${titleProp}></audio><p>`;
|
||||
}
|
||||
return `<audio controls src="${href}"${titleProp}></audio>`;
|
||||
if (video && VIDEO_EXT.test(href))
|
||||
}
|
||||
if (video && matchesExt(href, video))
|
||||
return `<video controls src="${href}"${titleProp}/></video>`;
|
||||
|
||||
if (css === "") {
|
||||
return `<p><a href="${href}">${title ? escape(title) : href}</a></p>`;
|
||||
}
|
||||
return `<a href="${href}">${title ? escape(title) : href}</a>`;
|
||||
}
|
||||
|
||||
if (h1) return `<h1>${escape(h1)}</h1>`;
|
||||
if (h2) return `<h2>${escape(h2)}</h2>`;
|
||||
if (h3) return `<h3>${escape(h3)}</h3>`;
|
||||
if (li) return `<li>${escape(li)}</li>`;
|
||||
|
||||
if (quote) return `<blockquote>${escape(quote)}</blockquote>`;
|
||||
|
||||
return `<p><br></p>`;
|
||||
}
|
||||
|
|
@ -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",
|
||||
|
|
2
test.sh
2
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
|
||||
|
|
Loading…
Reference in a new issue