refactor html.js
This commit is contained in:
parent
cae16d74db
commit
62d529a633
106
html.js
106
html.js
|
@ -11,6 +11,26 @@ export const tokenize = (gemtext) =>
|
|||
)
|
||||
);
|
||||
|
||||
export function toHTML(gemtext, options) {
|
||||
options.inlineCSS = options.inlineCSS || CSS.inline(options);
|
||||
options.styleTag = options.styleTag || CSS.style(options);
|
||||
|
||||
const tokens = tokenize(gemtext);
|
||||
|
||||
if (options.body) return body(tokens, options);
|
||||
|
||||
return `<!DOCTYPE html>
|
||||
<html lang="${options.html}" dir="${
|
||||
options.dir || "ltr"
|
||||
}" style='${options.inlineCSS("html")}'>
|
||||
<head>${head(tokens, options)}</head>
|
||||
<body${options.inlineCSS("body")}>
|
||||
${body(tokens, options)}
|
||||
</body>
|
||||
</html>
|
||||
`;
|
||||
}
|
||||
|
||||
export function block(
|
||||
{ text, href, title, pre, alt, h1, h2, h3, li, quote },
|
||||
options = {}
|
||||
|
@ -21,6 +41,14 @@ export function block(
|
|||
if (text) {
|
||||
content = text;
|
||||
}
|
||||
if (li) {
|
||||
type = "li";
|
||||
content = li;
|
||||
}
|
||||
if (quote) {
|
||||
type = "blockquote";
|
||||
content = quote;
|
||||
}
|
||||
if (h1) {
|
||||
type = "h1";
|
||||
content = h1;
|
||||
|
@ -33,17 +61,10 @@ export function block(
|
|||
type = "h3";
|
||||
content = h3;
|
||||
}
|
||||
if (li) {
|
||||
type = "li";
|
||||
content = li;
|
||||
}
|
||||
if (quote) {
|
||||
type = "blockquote";
|
||||
content = quote;
|
||||
}
|
||||
if (href) {
|
||||
const matchesExt = (url, exts) =>
|
||||
exts.some((ext) => new RegExp(`\.${ext}$`).test(url));
|
||||
|
||||
if (options.image && matchesExt(href, options.image)) {
|
||||
type = "img";
|
||||
props += ` src="${href}"`;
|
||||
|
@ -62,10 +83,12 @@ export function block(
|
|||
props += ` href="${href}"`;
|
||||
}
|
||||
}
|
||||
if (options.body || options.inline)
|
||||
|
||||
if (options.body || options.inline) {
|
||||
props += options.inlineCSS(
|
||||
type === "p" && content === "" ? "p:empty" : type
|
||||
);
|
||||
}
|
||||
|
||||
return `<${type}${props}>${escape(content)}</${type}>`;
|
||||
}
|
||||
|
@ -102,52 +125,7 @@ export function body(tokens, options) {
|
|||
return blocks.join("\n");
|
||||
}
|
||||
|
||||
export function toHTML(gemtext, options) {
|
||||
options.inlineCSS = options.inlineCSS || CSS.inline(options);
|
||||
options.styleTag = options.styleTag || CSS.style(options);
|
||||
|
||||
const tokens = tokenize(gemtext);
|
||||
|
||||
if (options.body) return body(tokens, options);
|
||||
|
||||
return `<!DOCTYPE html>
|
||||
<html lang="${options.html}" dir="${
|
||||
options.dir || "ltr"
|
||||
}" style='${options.inlineCSS("html")}'>
|
||||
<head>${head(
|
||||
Object.assign(options, {
|
||||
title: tokens[0].h1,
|
||||
description: description(tokens, options),
|
||||
})
|
||||
)}</head>
|
||||
<body${options.inlineCSS("body")}>
|
||||
${body(tokens, options)}
|
||||
</body>
|
||||
</html>
|
||||
`;
|
||||
}
|
||||
|
||||
export function head(options) {
|
||||
return `
|
||||
<meta charset="${options.charset || "utf-8"}">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">${
|
||||
options.styleTag
|
||||
}
|
||||
<title>${options.title}</title>${
|
||||
!options.author ? "" : `\n<meta name="author" content="${options.author}">`
|
||||
}${
|
||||
!options.description
|
||||
? ""
|
||||
: `\n<meta name="description" content="${escape(options.description)}">`
|
||||
}${
|
||||
!options.canonical
|
||||
? ""
|
||||
: `\n<link rel="canonical" href="${options.canonical}">`
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
||||
function description(tokens, options) {
|
||||
export function head(tokens, options) {
|
||||
const truncate = (text, limit) =>
|
||||
text.length > limit ? `${text.substring(0, limit)}...` : text;
|
||||
|
||||
|
@ -158,7 +136,23 @@ function description(tokens, options) {
|
|||
})
|
||||
: false;
|
||||
|
||||
return description && truncate(description.text, options.description);
|
||||
return `
|
||||
<meta charset="${options.charset || "utf-8"}">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">${
|
||||
options.styleTag
|
||||
}
|
||||
<title>${tokens.find(({h1}) => h1).h1 || ""}</title>${
|
||||
options.author ? `\n<meta name="author" content="${options.author}">` : ""
|
||||
}${
|
||||
description
|
||||
? `\n<meta name="description" content="${escape(truncate(description.text, options.description))}">`
|
||||
: ""
|
||||
}${
|
||||
options.canonical
|
||||
? `\n<link rel="canonical" href="${options.canonical}">`
|
||||
: ""
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
||||
export const GMI_EXT = /\.gmi$/;
|
||||
|
|
|
@ -178,7 +178,7 @@ test("--image, --audio, --video", () => {
|
|||
});
|
||||
|
||||
test("tokenize", () => {
|
||||
expect(tokenize(gemtext, { body: true })).toMatchInlineSnapshot(`
|
||||
expect(tokenize(gemtext)).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
Object {
|
||||
"h1": "gmi-web",
|
||||
|
|
17
package.json
17
package.json
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "gmi-web-cli",
|
||||
"version": "1.0.0-rc.4",
|
||||
"description": "A bridge between HTML and Gemini",
|
||||
"description": "A bridge between Gemini and HTML",
|
||||
"main": "html.js",
|
||||
"type": "module",
|
||||
"bin": {
|
||||
|
@ -11,17 +11,18 @@
|
|||
"./gmi-web.1"
|
||||
],
|
||||
"files": [
|
||||
"UNLICENSE",
|
||||
"README.md",
|
||||
"CONTRIBUTING.md",
|
||||
"gmi-web.1",
|
||||
"gmi-web.css",
|
||||
"gmi.css",
|
||||
"html.js",
|
||||
"html.spec.js",
|
||||
"css.js",
|
||||
"css.spec.js",
|
||||
"cli.js"
|
||||
"gmi.css",
|
||||
"gmi-web.css",
|
||||
"cli.js",
|
||||
"README.md",
|
||||
"CONTRIBUTING.md",
|
||||
"gmi-web.1",
|
||||
"example.gmi",
|
||||
"UNLICENSE"
|
||||
],
|
||||
"scripts": {
|
||||
"test": "NODE_OPTIONS=--experimental-vm-modules jest",
|
||||
|
|
Loading…
Reference in a new issue