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