Use ES modules
use language for <html lang=""> too
This commit is contained in:
parent
dd66069a7f
commit
54280ba8d3
13
cli.js
13
cli.js
|
@ -1,9 +1,10 @@
|
|||
#!/usr/bin/env node
|
||||
const path = require("path");
|
||||
const fs = require("vinyl-fs");
|
||||
const map = require("map-stream");
|
||||
const tokenize = require("./tokenize");
|
||||
const toHTML = require("./to-html");
|
||||
import path from "path";
|
||||
import fs from "vinyl-fs";
|
||||
import map from "map-stream";
|
||||
import tokenize from "./tokenize.js";
|
||||
import toHTML from "./to-html.js";
|
||||
import yargs from "yargs";
|
||||
|
||||
// TODO: automatically pull these in from gmi.css (also for gmi.css(5))
|
||||
const GMI_CSS_VARS = [
|
||||
|
@ -28,7 +29,7 @@ const GMI_CSS_VARS = [
|
|||
"sans-serif",
|
||||
];
|
||||
|
||||
require("yargs")
|
||||
yargs(process.argv.slice(2))
|
||||
.scriptName("gmi-web")
|
||||
.config()
|
||||
.command(
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<!DOCTYPE html>
|
||||
<html style="">
|
||||
<html lang="en" style="">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta language="en">
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
module.exports = /^((=>\s?(?<href>[^\s]+)(\s(?<title>.+))?)|(?<pre>```\s?(?<alt>.+)?)|(###\s?(?<h3>.+))|(##\s?(?<h2>.+))|(#\s?(?<h1>.+))|(\*\s?(?<li>.+))|(>\s?(?<quote>.+))|(?<text>(.+)?))$/;
|
|
@ -3,6 +3,7 @@
|
|||
"version": "1.0.7-rc.1",
|
||||
"description": "A bridge between HTML and Gemini",
|
||||
"main": "cli.js",
|
||||
"type": "module",
|
||||
"bin": {
|
||||
"gmi-web": "cli.js"
|
||||
},
|
||||
|
|
1
test.sh
1
test.sh
|
@ -1,3 +1,4 @@
|
|||
rm -rf "example/test.html"
|
||||
./cli.js --lang en --images --audio --video "example/*.gmi"
|
||||
if cmp -s "example/test.html" "example/expected.html"; then
|
||||
printf "PASS: test.html matches expected.html!\n"
|
||||
|
|
57
to-html.js
57
to-html.js
|
@ -1,32 +1,20 @@
|
|||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const escape = require("escape-html");
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
import escape from "escape-html";
|
||||
|
||||
const TOKENS_EXT = /\.tokens\.json$/;
|
||||
// https://developer.mozilla.org/en-US/docs/Web/Media/Formats
|
||||
const IMG_EXT = (exports.IMG_EXT = /\.(apng|avif|gif|jpg|jpeg|jfif|pjpeg|pjp|png|svg|webp)$/);
|
||||
const AUDIO_EXT = (exports.AUDIO_EXT = /\.(mp3|wav|aac|aacp|mpeg|off|flac)$/);
|
||||
const VIDEO_EXT = (exports.VIDEO_EXT = /\.(mp4|webm)$/);
|
||||
const BASE_STYLE = (exports.BASE_STYLE =
|
||||
"<style>p,a,pre,h1,h2,h3,ul,blockquote,img,audio,video{display:block;max-width:100%;margin:0;padding:0;overflow-wrap:anywhere;}</style>");
|
||||
const GMI_CSS = fs.readFileSync(
|
||||
path.resolve(__dirname, "./gmi.min.css"),
|
||||
export const IMG_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)$/;
|
||||
export const BASE_STYLE =
|
||||
"<style>p,a,pre,h1,h2,h3,ul,blockquote,img,audio,video{display:block;max-width:100%;margin:0;padding:0;overflow-wrap:anywhere;}</style>";
|
||||
export const GMI_CSS = fs.readFileSync(
|
||||
path.resolve(path.dirname(new URL(import.meta.url).pathname), "./gmi.min.css"),
|
||||
"utf8"
|
||||
);
|
||||
|
||||
const toHTML = (exports.toHTML = (file, options) => {
|
||||
const tokens = JSON.parse(file.contents.toString("utf8"));
|
||||
const title = tokens[0].h1;
|
||||
return `<!DOCTYPE html>
|
||||
<html style="${options.override}">
|
||||
${head(file.path, title, options)}<body>
|
||||
${gemtext(tokens, options)}
|
||||
</body>
|
||||
</html>
|
||||
`;
|
||||
});
|
||||
|
||||
module.exports = (options) => (file, cb) => {
|
||||
export default (options) => (file, cb) => {
|
||||
if (!TOKENS_EXT.test(file.path)) return cb(null);
|
||||
file.contents = Buffer.from(toHTML(file, options));
|
||||
file.path = file.path.replace(TOKENS_EXT, ".html");
|
||||
|
@ -34,7 +22,19 @@ module.exports = (options) => (file, cb) => {
|
|||
return cb(null, file);
|
||||
};
|
||||
|
||||
function head(file, title, options) {
|
||||
export function toHTML (file, options) {
|
||||
const tokens = JSON.parse(file.contents.toString("utf8"));
|
||||
const title = tokens[0].h1;
|
||||
return `<!DOCTYPE html>
|
||||
<html lang="${options.language}" style="${options.override}">
|
||||
${head(file.path, title, options)}<body>
|
||||
${gemtext(tokens, options)}
|
||||
</body>
|
||||
</html>
|
||||
`;
|
||||
};
|
||||
|
||||
export function head(file, title, options) {
|
||||
return `<head>
|
||||
<meta charset="utf-8">
|
||||
<meta language="${options.language}">
|
||||
|
@ -45,14 +45,14 @@ function head(file, title, options) {
|
|||
}${
|
||||
!options.canonical
|
||||
? ""
|
||||
: `<link rel="canonical" href="${ options.canonical }}">`
|
||||
: `<link rel="canonical" href="${options.canonical}}">`
|
||||
}
|
||||
<title>${title}</title>
|
||||
</head>
|
||||
`;
|
||||
}
|
||||
|
||||
function gemtext(tokens, options) {
|
||||
export function gemtext(tokens, options) {
|
||||
let body = [];
|
||||
|
||||
let cursor = tokens.shift();
|
||||
|
@ -86,9 +86,8 @@ function line(
|
|||
) {
|
||||
if (text) return `<p>${escape(text)}</p>`;
|
||||
if (href) {
|
||||
const titleProp = title ? ` title="${title}"` : ""
|
||||
if (images && IMG_EXT.test(href))
|
||||
return `<img src="${href}"${titleProp}/>`;
|
||||
const titleProp = title ? ` title="${title}"` : "";
|
||||
if (images && IMG_EXT.test(href)) return `<img src="${href}"${titleProp}/>`;
|
||||
if (audio && AUDIO_EXT.test(href))
|
||||
return `<audio controls src="${href}"${titleProp}></audio>`;
|
||||
if (video && VIDEO_EXT.test(href))
|
||||
|
|
17
tokenize.js
17
tokenize.js
|
@ -1,17 +1,14 @@
|
|||
const GMI_EXT = /\.gmi$/;
|
||||
const GMI_REGEX = require("./gmi.regex");
|
||||
const tokenize = (exports.tokenize = (file) =>
|
||||
export const GMI_REGEX = /^((=>\s?(?<href>[^\s]+)(\s(?<title>.+))?)|(?<pre>```\s?(?<alt>.+)?)|(###\s?(?<h3>.+))|(##\s?(?<h2>.+))|(#\s?(?<h1>.+))|(\*\s?(?<li>.+))|(>\s?(?<quote>.+))|(?<text>(.+)?))$/;
|
||||
export const GMI_EXT = /\.gmi$/;
|
||||
export const tokenize = (gemtext) =>
|
||||
JSON.stringify(
|
||||
file.contents
|
||||
.toString("utf8")
|
||||
.split("\n")
|
||||
.map((line) => GMI_REGEX.exec(line).groups),
|
||||
gemtext.split("\n").map((line) => GMI_REGEX.exec(line).groups),
|
||||
null,
|
||||
2
|
||||
));
|
||||
module.exports = (file, cb) => {
|
||||
);
|
||||
export default (file, cb) => {
|
||||
if (!GMI_EXT.test(file.path)) return cb(null, file);
|
||||
file.contents = Buffer.from(tokenize(file));
|
||||
file.contents = Buffer.from(tokenize(file.contents.toString("utf8")));
|
||||
file.path = file.path.replace(GMI_EXT, ".tokens.json");
|
||||
cb(null, file);
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue