const css = new CSSStyleSheet()
css.replaceSync(text)
これで作った CSSStyleSheet オブジェクトから CSS のテキストを取り出したいです
目的は text の変数に入ってる CSS を有効な形に修正することです
HTML や CSS は構文がおかしくてもブラウザ側で不正なものは適当に修正してくれるのでその結果がほしいです
HTML なら
const div = document.createElement("div")
div.innerHTML = `<div><p>aa`
div.innerHTML
// '<div><p>aa</p></div>'
というふうにできるのですが CSS ってこういうのがないです
cssRules にルールが入ってますが 色々分かれてしまっています
いい感じに取り出すのは難しそうかなと思ってたのですが 単純に個々の cssRules の cssText を取得して結合すればいい感じになりました
「@」 を使ったものやネストなどに不安がありましたが MDN にあるサンプルコードを適当にコピペして試した感じではほぼ完全に復元できました
以下が確認済みです
@font-face
@keyframes
@media
@page
@container
@layer
@namespace
@counter-style
@supports
@property
@scope
@import は replace / replaceSync で使えないので確認してません
@charset は出力されなかったですがパース後には元の文字コードを保持する必要がないのでそういうものなのだと思います
もしかするとマイナーなところで出力できない部分があるかもしれないですが 基本的なものでは問題なく使えるレベルだと思います
const formatCSS = (text) => {
const css = new CSSStyleSheet()
css.replaceSync(text)
return [...css.cssRules].map(rule => rule.cssText).join("\n")
}
少し気になったところでは ネストするとインデントがおかしくなります
console.log(formatCSS(`
.foo {
.bar {
.baz {
}
}
}
`))
.foo {
.bar {
.baz { }
}
}
読むことを目的としてないので実害はないですが ネストの対応はこの辺まで完璧じゃないようですね
ちなみにこの方法 自分で作った CSSStyleSheet 以外の style タグや link タグでも使えました
link タグの場合は取得する CSS ファイルが同じオリジンである必要があります
const sheetToCSS = (sheet) => {
return [...sheet.cssRules].map(rule => rule.cssText).join("\n")
}
console.log(sheetToCSS(document.querySelector("style").sheet))
console.log(sheetToCSS(document.querySelector(`link[rel="stylesheet"]`).sheet))