Start implementing proof-of-concept
This commit is contained in:
commit
a114e18dc6
4 changed files with 112 additions and 0 deletions
89
PullStyles.js
Normal file
89
PullStyles.js
Normal file
|
@ -0,0 +1,89 @@
|
|||
/**
|
||||
* @param {string} href
|
||||
* @param {string} layer
|
||||
*/
|
||||
function importRule(href, layer) {
|
||||
if (layer)
|
||||
return `@import url("${href}") layer(${layer});`
|
||||
else
|
||||
return `@import url("${href}");`
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} css
|
||||
* @param {string|undefined} layer
|
||||
*/
|
||||
function wrapLayer(css, layer) {
|
||||
if (layer)
|
||||
return `@layer ${layer} { ${css} }`
|
||||
else
|
||||
return css
|
||||
}
|
||||
|
||||
class RuleCollection {
|
||||
layer
|
||||
/** @type {string[]} */
|
||||
imports = []
|
||||
/** @type {string[]} */
|
||||
inlined = []
|
||||
|
||||
/** @param {string} layer */
|
||||
constructor(layer) { this.layer = layer }
|
||||
|
||||
/** @param {HTMLStyleElement} styleSheet */
|
||||
copyInto(styleSheet) {
|
||||
for (const href of this.imports)
|
||||
styleSheet.innerHTML += importRule(href, this.layer)
|
||||
for (const block of this.inlined)
|
||||
styleSheet.innerHTML += wrapLayer(block, this.layer)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {CSSStyleSheet} sheet
|
||||
* @param {RuleCollection} target
|
||||
*/
|
||||
function collectStyles(sheet, target) {
|
||||
if (sheet.ownerRule) {
|
||||
// TODO
|
||||
} else {
|
||||
const node = sheet.ownerNode
|
||||
if (node instanceof HTMLLinkElement) {
|
||||
target.imports.push(node.href)
|
||||
} else if (node instanceof HTMLStyleElement) {
|
||||
target.inlined.push(node.innerHTML)
|
||||
} else {
|
||||
console.log(node)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default class PullStyles extends HTMLElement {
|
||||
static observedAttributes = ["adopt", "layer"]
|
||||
|
||||
attributeChangedCallback() {
|
||||
this.pullStyles()
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} adopt What to adopt
|
||||
* @param {string|undefined} layer What CSS layer to wrap the external styles in
|
||||
*/
|
||||
pullStyles(adopt=this.adopt, layer=this.layer) {
|
||||
if (adopt == "all") {
|
||||
this.replaceChildren(document.createElement("style"))
|
||||
const rules = new RuleCollection(layer)
|
||||
for (const sheet of document.styleSheets) {
|
||||
collectStyles(sheet, rules)
|
||||
}
|
||||
rules.copyInto(this.sheet)
|
||||
console.log(this.sheet.innerText)
|
||||
} else if (adopt != undefined) {
|
||||
throw new Error("Adopt must be empty or 'all'")
|
||||
}
|
||||
}
|
||||
|
||||
get sheet() { return this.querySelector("style") }
|
||||
get adopt() { return this.getAttribute("adopt") }
|
||||
get layer() { return this.getAttribute("layer") }
|
||||
}
|
21
index.html
Normal file
21
index.html
Normal file
|
@ -0,0 +1,21 @@
|
|||
<style>
|
||||
.inline { color: red }
|
||||
@layer foo {
|
||||
.layer { color: purple }
|
||||
}
|
||||
</style>
|
||||
|
||||
<link rel="stylesheet" href="/linked.css">
|
||||
|
||||
<script type="module">
|
||||
import PullStyles from "/PullStyles.js"
|
||||
customElements.define("pull-styles", PullStyles)
|
||||
</script>
|
||||
|
||||
<my-component>
|
||||
<template shadowrootmode="open">
|
||||
<pull-styles adopt="all"></pull-styles>
|
||||
<p class="inline">Inline</p>
|
||||
<p class="linked">Linked</p>
|
||||
</template>
|
||||
</my-component>
|
1
jsconfig.json
Normal file
1
jsconfig.json
Normal file
|
@ -0,0 +1 @@
|
|||
{ "compilerOptions": { "checkJs": true, "target": "es2020" } }
|
1
linked.css
Normal file
1
linked.css
Normal file
|
@ -0,0 +1 @@
|
|||
.linked { color: blue }
|
Loading…
Reference in a new issue