add --author and --descriptions options
This commit is contained in:
parent
45e90e61ac
commit
5254445e77
23
cli.js
23
cli.js
|
@ -9,7 +9,7 @@ import toHTML, { BASE_CSS, html } from "./html.js";
|
|||
|
||||
const cli = yargs(process.argv.slice(2))
|
||||
.config("config", function (path) {
|
||||
return JSON.parse(readFileSync(path))
|
||||
return JSON.parse(readFileSync(path));
|
||||
})
|
||||
.scriptName("gmi-web")
|
||||
.command("$0 [files..]", "Convert text/gemini to text/html.", (yargs) =>
|
||||
|
@ -30,15 +30,23 @@ const cli = yargs(process.argv.slice(2))
|
|||
type: "string",
|
||||
requiresArg: true,
|
||||
},
|
||||
charset: {
|
||||
author: {
|
||||
type: "string",
|
||||
default: "utf-8",
|
||||
requiresArg: true,
|
||||
},
|
||||
descriptions: {
|
||||
type: "boolean",
|
||||
},
|
||||
css: {
|
||||
choices: ["gmi.css", "base", "none"],
|
||||
default: "gmi.css",
|
||||
},
|
||||
charset: {
|
||||
type: "string",
|
||||
hidden: true,
|
||||
default: "utf-8",
|
||||
requiresArg: true,
|
||||
},
|
||||
});
|
||||
|
||||
cli.options({
|
||||
|
@ -85,10 +93,13 @@ const GMI_CSS_VARS = [
|
|||
});
|
||||
|
||||
const argv = cli
|
||||
.conflicts("author", "body")
|
||||
.conflicts("description", "body")
|
||||
.conflicts("html", "body")
|
||||
.group(["html", "css", "body"], "Core:")
|
||||
.group(GMI_CSS_VARS, "gmi.css:")
|
||||
.group(["html", "body"], "Core:")
|
||||
.group(["author", "description", "css"], "HTML:")
|
||||
.group(["image", "audio", "video"], "Inline Media:")
|
||||
.group(GMI_CSS_VARS, "gmi.css:")
|
||||
.alias("html", "language")
|
||||
.alias("html", "lang")
|
||||
.showHelpOnFail(true)
|
||||
|
@ -100,7 +111,7 @@ if (argv.css === "gmi.css") {
|
|||
if (argv[key]) {
|
||||
style += `--${key}: ${argv[key]};`;
|
||||
}
|
||||
return style
|
||||
return style;
|
||||
}, styles);
|
||||
|
||||
argv.css = new CleanCSS().minify(
|
||||
|
|
12
gmi-web.1
12
gmi-web.1
|
@ -31,6 +31,18 @@ Generate a full HTML5 document with the provided \fILANG\fR.
|
|||
\fBgmi-web\fR --html en < doc.gmi
|
||||
.P
|
||||
.RE
|
||||
\fB--descriptions\fR
|
||||
.RS 4
|
||||
If this flag is set the first non-empty text line of each Gemini file will
|
||||
be used for the description <meta> tag. This will be truncated to 200
|
||||
characters using an ellipsis.
|
||||
.P
|
||||
.RE
|
||||
\fB--author\fR
|
||||
.RS 4
|
||||
If provided this will be used for the author <meta> tag on every file.
|
||||
.P
|
||||
.RE
|
||||
\fB--body\fR
|
||||
.RS 4
|
||||
Generate only the HTML for the lines of the Gemini document.
|
||||
|
|
|
@ -22,6 +22,14 @@ and mobile-friendly fashion!
|
|||
|
||||
*gmi-web* --html en < doc.gmi
|
||||
|
||||
*--descriptions*
|
||||
If this flag is set the first non-empty text line of each Gemini file will
|
||||
be used for the description <meta> tag. This will be truncated to 200
|
||||
characters using an ellipsis.
|
||||
|
||||
*--author*
|
||||
If provided this will be used for the author <meta> tag on every file.
|
||||
|
||||
*--body*
|
||||
Generate only the HTML for the lines of the Gemini document.
|
||||
|
||||
|
|
17
html.js
17
html.js
|
@ -2,12 +2,20 @@ import escape from "escape-html";
|
|||
|
||||
export const GMI_REGEX = /^((=>\s?(?<href>[^\s]+)(\s(?<title>.+))?)|(?<pre>```\s?(?<alt>.+)?)|(###\s?(?<h3>.+))|(##\s?(?<h2>.+))|(#\s?(?<h1>.+))|(\*\s?(?<li>.+))|(>\s?(?<quote>.+))|(?<text>(.+)?))$/;
|
||||
|
||||
const truncate = (text, limit) =>
|
||||
text.length > limit ? `${text.substring(0, limit)}...` : text;
|
||||
export function html(file, options) {
|
||||
const tokens = file.contents
|
||||
.toString("utf8")
|
||||
.split("\n")
|
||||
.map((line) => GMI_REGEX.exec(line).groups);
|
||||
|
||||
let description = options.descriptions
|
||||
? tokens.find((token) => {
|
||||
return token.text && token.text !== "";
|
||||
})
|
||||
: false;
|
||||
|
||||
if (options.body) return body(tokens, options);
|
||||
|
||||
return `<!DOCTYPE html>
|
||||
|
@ -15,7 +23,7 @@ export function html(file, options) {
|
|||
<head>${head(
|
||||
Object.assign(options, {
|
||||
title: tokens[0].h1,
|
||||
// TODO: description, canonical
|
||||
description: description && truncate(description.text, 200),
|
||||
})
|
||||
)}</head>
|
||||
<body>
|
||||
|
@ -27,6 +35,7 @@ ${body(tokens, options)}
|
|||
|
||||
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 charset="${options.charset}">
|
||||
|
@ -34,13 +43,15 @@ export function head(options) {
|
|||
${options.css !== "" ? `<meta name="color-scheme" content="dark light">` : ""}
|
||||
${options.css !== "" ? `<style>${options.css}</style>` : ""}
|
||||
<title>${options.title}</title>${
|
||||
!options.author ? "" : `<meta name="author" content="${options.author}">`
|
||||
}${
|
||||
!options.description
|
||||
? ""
|
||||
: `<meta name="description" content="${options.description}}">`
|
||||
: `<meta name="description" content="${escape(options.description)}">`
|
||||
}${
|
||||
!options.canonical
|
||||
? ""
|
||||
: `<link rel="canonical" href="${options.canonical}}">`
|
||||
: `<link rel="canonical" href="${options.canonical}">`
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue