gmi-web/css.js

91 lines
2.4 KiB
JavaScript
Raw Normal View History

2021-02-15 20:56:41 +00:00
import { readFileSync } from "fs";
import path from "path";
import { stringify, parse } from "css";
export { stringify, parse };
export const CORE = parse(`p, pre, ul, blockquote, h1, h2, h3 {
margin-top: 0;
margin-bottom: 0;
overflow-wrap: break-word;
hyphens: auto;
}
a { display: block; }
2021-02-15 20:56:41 +00:00
img, audio, video {
2021-02-15 20:56:41 +00:00
display: block;
max-width: 100%;
}
`);
2021-02-15 20:56:41 +00:00
// TODO import.meta.resolve is supposed to accomplish this without "path"
export const FULL = parse(
readFileSync(
path.resolve(path.dirname(new URL(import.meta.url).pathname), "./gmi.css"),
"utf-8"
)
);
2021-02-15 20:56:41 +00:00
export function rootVariables({ stylesheet }) {
return stylesheet.rules
.find(
({ type, selectors }) => type === "rule" && selectors.includes(":root")
)
.declarations.reduce(
(obj, { property, value }) =>
!/^\-\-/.test(property)
? obj
: Object.assign(obj, { [property.replace("--", "")]: value }),
{}
);
}
export function override(options) {
if (options.css !== "full") return "";
const vars = rootVariables(FULL);
return Object.keys(vars).reduce((styles, key) => {
if (typeof options[key] !== undefined && options[key] !== vars[key]) {
let value = options[key];
if (["a-prefix", "ul-bullet"].includes(key) && value !== "none") {
value = `"${value}"`;
}
styles += `--${key}:${value};`;
}
return styles;
2021-02-18 19:11:03 +00:00
}, " ");
}
2021-02-18 19:11:03 +00:00
export function style({ inline, css }) {
if (inline || css === "none") return "";
if (css === "core")
return `<style>${stringify(CORE, { compress: true })}</style>`;
if (css === "full")
return `<style>${stringify(FULL, { compress: true })}</style>`;
2021-02-18 19:11:03 +00:00
return `<style>${stringify(load(css, { compress: true }))}</style>`;
}
2021-02-18 19:11:03 +00:00
export function inline(tag, { inline, css }) {
if (!inline || css === "full") return "";
const { stylesheet } = css === "core" ? CORE : load(css);
const styles = stylesheet.rules
.filter(({ type, selectors }) => type === "rule" && selectors.includes(tag))
.reduce((style, { declarations }) => {
declarations.forEach(({ property, value }) => {
style = `${style}${property}:${value};`;
});
return style;
}, "");
return styles !== "" ? ` style="${styles}"` : "";
}
export function load(file, options) {
2021-02-18 19:11:03 +00:00
if (fs.existsSync(file)) {
return parse(readFileSync(path.resolve(file), "utf-8"));
} else {
2021-02-18 19:11:03 +00:00
throw new Error(`Cannot find file ${file}.`);
}
2021-02-15 20:56:41 +00:00
}