gmi-web(1) inline media
This commit is contained in:
parent
06a8bab54a
commit
541c6345e4
|
@ -75,17 +75,20 @@ gmi.css will respect system dark mode preferences by inverting `--foreground` an
|
||||||
## gmi-web(1)
|
## gmi-web(1)
|
||||||
|
|
||||||
```
|
```
|
||||||
gmi-web [--no-css] [files..]
|
gmi-web [--css] [files..]
|
||||||
|
|
||||||
Convert .gmi to .html. See gmi-web(1) for more details.
|
Convert .gmi to .html. See gmi-web(1) for more details.
|
||||||
|
|
||||||
Positionals:
|
Positionals:
|
||||||
files .gmi files to convert to .html [required]
|
files The *.gmi files to convert [required]
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
--version Show version number [boolean]
|
--version Show version number [boolean]
|
||||||
--help Show help [boolean]
|
--help Show help [boolean]
|
||||||
--css Toggle inclusion of gmi.css. [boolean] [default: true]
|
--images Include images [boolean] [default: false]
|
||||||
|
--audio Include audio [boolean] [default: false]
|
||||||
|
--video Include video [boolean] [default: false]
|
||||||
|
--css Include gmi.css [boolean] [default: true]
|
||||||
```
|
```
|
||||||
|
|
||||||
*You will need*:
|
*You will need*:
|
||||||
|
|
34
cli.js
34
cli.js
|
@ -8,23 +8,49 @@ const toHTML = require("./to-html");
|
||||||
require("yargs")
|
require("yargs")
|
||||||
.scriptName("gmi-web")
|
.scriptName("gmi-web")
|
||||||
.command(
|
.command(
|
||||||
"$0 [--no-css] [files..]",
|
"$0 [--css] [files..]",
|
||||||
"Convert .gmi to .html. See gmi-web(1) for more details.",
|
"Convert .gmi to .html. See gmi-web(1) for more details.",
|
||||||
(yargs) =>
|
(yargs) =>
|
||||||
yargs
|
yargs
|
||||||
.positional("files", {
|
.positional("files", {
|
||||||
describe: ".gmi files to convert to .html",
|
describe: "The *.gmi files to convert",
|
||||||
})
|
})
|
||||||
.required("files", true)
|
.required("files", true)
|
||||||
|
.option("images", {
|
||||||
|
type: "boolean",
|
||||||
|
default: false,
|
||||||
|
description: "Include images",
|
||||||
|
})
|
||||||
|
.option("audio", {
|
||||||
|
type: "boolean",
|
||||||
|
default: false,
|
||||||
|
description: "Include audio",
|
||||||
|
})
|
||||||
|
.option("video", {
|
||||||
|
type: "boolean",
|
||||||
|
default: false,
|
||||||
|
description: "Include video",
|
||||||
|
})
|
||||||
.option("css", {
|
.option("css", {
|
||||||
type: "boolean",
|
type: "boolean",
|
||||||
default: true,
|
default: true,
|
||||||
description: "Toggle inclusion of gmi.css.",
|
description: "Include gmi.css",
|
||||||
}),
|
}),
|
||||||
(argv) => {
|
(argv) => {
|
||||||
fs.src(argv.files)
|
fs.src(argv.files)
|
||||||
.pipe(map(tokenize))
|
.pipe(map(tokenize))
|
||||||
.pipe(map(toHTML({ css: argv["css"] })))
|
.pipe(
|
||||||
|
map(
|
||||||
|
toHTML({
|
||||||
|
css: argv.css,
|
||||||
|
inline: {
|
||||||
|
images: argv.images,
|
||||||
|
audio: argv.audio,
|
||||||
|
video: argv.video,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
)
|
||||||
|
)
|
||||||
.pipe(fs.dest((file) => path.dirname(file.path)));
|
.pipe(fs.dest((file) => path.dirname(file.path)));
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
|
@ -6,7 +6,7 @@ gmi-web - A bridge between Gemini and HTML
|
||||||
|
|
||||||
# SYNOPSIS
|
# SYNOPSIS
|
||||||
|
|
||||||
*gmi-web* [--no-css] _files_
|
*gmi-web* [--images] [--audio] [--video] [--no-css] _files_
|
||||||
|
|
||||||
# DESCRIPTION
|
# DESCRIPTION
|
||||||
|
|
||||||
|
@ -15,6 +15,9 @@ and mobile-friendly fashion!
|
||||||
|
|
||||||
# OPTIONS
|
# OPTIONS
|
||||||
|
|
||||||
|
*--images* *--audio* *--video*
|
||||||
|
Include the respective media inline.
|
||||||
|
|
||||||
*--no-css*
|
*--no-css*
|
||||||
Do not include gmi.css in the rendered HTML markup.
|
Do not include gmi.css in the rendered HTML markup.
|
||||||
|
|
||||||
|
|
37
to-html.js
37
to-html.js
|
@ -1,24 +1,32 @@
|
||||||
const TOKENS_EXT = /\.tokens\.json$/;
|
const TOKENS_EXT = /\.tokens\.json$/;
|
||||||
module.exports = ({ css } = { css: true }) => (file, cb) => {
|
// https://developer.mozilla.org/en-US/docs/Web/Media/Formats
|
||||||
|
const IMG_EXT = /\.(apng|avif|gif|jpg|jpeg|jfif|pjpeg|pjp|png|svg|webp)$/;
|
||||||
|
const AUDIO_EXT = /\.(mp3|wav|aac|aacp|mpeg|off|flac)$/;
|
||||||
|
const VIDEO_EXT = /\.(mp4|webm)$/;
|
||||||
|
|
||||||
|
module.exports = (options) => (file, cb) => {
|
||||||
if (!TOKENS_EXT.test(file.path)) return cb(null, file);
|
if (!TOKENS_EXT.test(file.path)) return cb(null, file);
|
||||||
file.path = file.path.replace(TOKENS_EXT, ".html");
|
|
||||||
|
// TODO: meta: author, copyright, keywords, content-type, language, description, canonical
|
||||||
file.contents = Buffer.from(`<!DOCTYPE html>
|
file.contents = Buffer.from(`<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1">${
|
<meta name="viewport" content="width=device-width,initial-scale=1">${
|
||||||
css
|
options.css
|
||||||
? '\n<meta name="color-scheme" content="dark light">\n<link rel="stylesheet" href="/gmi.min.css">'
|
? '\n<meta name="color-scheme" content="dark light">\n<link rel="stylesheet" href="/gmi.min.css">'
|
||||||
: ""
|
: ""
|
||||||
}
|
}
|
||||||
<body>
|
<body>
|
||||||
${toHTML(JSON.parse(file.contents.toString("utf8")))}
|
${toHTML(JSON.parse(file.contents.toString("utf8")), options)}
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
`);
|
`);
|
||||||
|
|
||||||
|
file.path = file.path.replace(TOKENS_EXT, ".html");
|
||||||
return cb(null, file);
|
return cb(null, file);
|
||||||
};
|
};
|
||||||
|
|
||||||
function toHTML(tokens) {
|
function toHTML(tokens, options) {
|
||||||
let body = [];
|
let body = [];
|
||||||
|
|
||||||
let cursor = tokens.shift();
|
let cursor = tokens.shift();
|
||||||
|
@ -37,16 +45,29 @@ function toHTML(tokens) {
|
||||||
body.push("</ul>");
|
body.push("</ul>");
|
||||||
tokens = tokens.slice(closing + 1);
|
tokens = tokens.slice(closing + 1);
|
||||||
}
|
}
|
||||||
body.push(line(cursor));
|
body.push(line(cursor, options));
|
||||||
cursor = tokens.shift();
|
cursor = tokens.shift();
|
||||||
}
|
}
|
||||||
|
|
||||||
return body.join("\n");
|
return body.join("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
function line({ text, href, title, pre, alt, h1, h2, h3, li, quote }) {
|
function line(
|
||||||
|
{ text, href, title, pre, alt, h1, h2, h3, li, quote },
|
||||||
|
{ inline }
|
||||||
|
) {
|
||||||
|
console.log(inline)
|
||||||
if (text) return `<p>${text}</p>`;
|
if (text) return `<p>${text}</p>`;
|
||||||
if (href) return `<a href="${href}">${title || href}</a>`;
|
if (href) {
|
||||||
|
if (inline.images && IMG_EXT.test(href))
|
||||||
|
return `<img src="${href}" title="${title}"/>`;
|
||||||
|
if (inline.audio && AUDIO_EXT.test(href))
|
||||||
|
return `<audio controls src="${href}" title="${title}"></audio>`;
|
||||||
|
if (inline.video && VIDEO_EXT.test(href))
|
||||||
|
return `<video controls src="${href}" title="${title}"/></video>`;
|
||||||
|
|
||||||
|
return `<a href="${href}">${title || href}</a>`;
|
||||||
|
}
|
||||||
if (h1) return `<h1>${h1}</h1>`;
|
if (h1) return `<h1>${h1}</h1>`;
|
||||||
if (h2) return `<h2>${h2}</h2>`;
|
if (h2) return `<h2>${h2}</h2>`;
|
||||||
if (h3) return `<h3>${h3}</h3>`;
|
if (h3) return `<h3>${h3}</h3>`;
|
||||||
|
|
Loading…
Reference in a new issue