Skip to content

Instantly share code, notes, and snippets.

@hail2u

hail2u/inline-css.js

Last active May 8, 2020
Embed
What would you like to do?
HTMLファイルを渡すと、参照しているCSSファイルを読み、必要なルールだけインライン化するやつ
// $ node inline-css.js <path-to-html-file>
import fs from "fs/promises";
import jsdom from "jsdom";
import postcss from "postcss";
const { JSDOM } = jsdom;
const hasNode = (document, selector) => {
if (selector.includes(":")) {
return true;
}
if (document.querySelector(selector) !== null) {
return true;
}
return false;
};
const optimizeCSS = (css, document) => {
const root = postcss.parse(css);
root.walkRules((rule) => {
if (!rule.selectors.some(hasNode.bind(null, document))) {
rule.remove();
}
});
return root.toString();
};
const main = async () => {
const html = await fs.readFile(process.argv.slice(2).shift(), "utf8");
const dom = new JSDOM(html);
const { document } = dom.window;
const stylesheets = document.querySelectorAll('link[rel="stylesheet"]');
for (const stylesheet of stylesheets) {
const css = await fs.readFile(stylesheet.href, "utf8");
const optimized = optimizeCSS(css, document);
const style = document.createElement("style");
style.append(optimized);
stylesheet.replaceWith(style);
}
console.log(dom.serialize());
};
main().catch((e) => {
console.trace(e);
process.exitCode = 1;
});
@hail2u

This comment has been minimized.

Copy link
Owner Author

@hail2u hail2u commented May 7, 2020

前に作ったやつは、HTMLメールを想定していたので、style属性に追加していくけど、今度のやつはlink[rel="stylesheet"]style要素で差し替える。

  • 最初のlink[rel="stylesheet"]しか処理していない
  • スラッシュで始まる絶対パスで書かれているとCSSファイルが読めない
  • URLも読めない
  • 空の@mediaが残る
  • 疑似要素をちゃんとするのは面倒そうなので、コロンが入っているセレクターは常に含まれる
  • const { window: { document } } = new JSDOM(html)っていう行が頭悪そう

などの問題がまだある。あと遅い。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.