feat: support scoped css
This commit is contained in:
parent
6e718c0ae6
commit
e2f3b7534f
|
@ -26,6 +26,7 @@
|
|||
You need to enable JavaScript to run this app.
|
||||
</noscript>
|
||||
<div id="root"></div>
|
||||
<div id="root2"></div>
|
||||
<!--
|
||||
This HTML file is a template.
|
||||
If you open it directly in the browser, you will see an empty page.
|
||||
|
|
|
@ -1,16 +1,27 @@
|
|||
import * as Preact from 'preact'
|
||||
|
||||
import './preact-css'
|
||||
|
||||
|
||||
function Counter() {
|
||||
|
||||
function Comp() {
|
||||
return (
|
||||
<>
|
||||
<div>Hello Preact X</div>
|
||||
<h1>Hello Preact X</h1>
|
||||
<div>Hello Preact CSS</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
Preact.render(<Counter />, document.querySelector('#root'))
|
||||
Comp.css = `
|
||||
h1{
|
||||
color: red;
|
||||
}
|
||||
`
|
||||
|
||||
Preact.render(<Comp />, document.querySelector('#root'))
|
||||
|
||||
|
||||
//Test Multiple rendering only append style once
|
||||
Preact.render(<Comp />, document.querySelector('#root2'))
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { options } from 'preact'
|
||||
|
||||
import { getStyleId, appendStyle } from './style'
|
||||
|
||||
let componentNode;
|
||||
|
||||
|
@ -24,9 +24,10 @@ options.vnode = vnode => {
|
|||
if (component) {
|
||||
// component is the component instance
|
||||
//component.css;
|
||||
component._styleId = 'abcef';
|
||||
const styleId = getStyleId(component.constructor);
|
||||
appendStyle(component.constructor.css, styleId);
|
||||
// example: assign component's unique CSS ID:
|
||||
(vnode.props || (vnode.props = {}))[component._styleId] = '';
|
||||
(vnode.props || (vnode.props = {}))[styleId] = ''
|
||||
}
|
||||
if (old) old(vnode);
|
||||
};
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
|
||||
let styleId = 0
|
||||
const styleList = []
|
||||
const cache = {}
|
||||
|
||||
export function getStyleId(ctor) {
|
||||
for (let i = 0, len = styleList.length; i < len; i++) {
|
||||
let item = styleList[i]
|
||||
|
||||
if (item.ctor === ctor) {
|
||||
return item.attrName
|
||||
}
|
||||
}
|
||||
|
||||
let attrName = '_ss' + styleId
|
||||
styleList.push({ ctor, attrName })
|
||||
styleId++
|
||||
|
||||
return attrName
|
||||
}
|
||||
|
||||
// many thanks to https://github.com/thomaspark/scoper/
|
||||
export function scoper(css, prefix) {
|
||||
console.log(css, prefix)
|
||||
prefix = '[' + prefix.toLowerCase() + ']'
|
||||
// https://www.w3.org/TR/css-syntax-3/#lexical
|
||||
css = css.replace(/\/\*[^*]*\*+([^/][^*]*\*+)*\//g, '')
|
||||
// eslint-disable-next-line
|
||||
let re = new RegExp('([^\r\n,{}:]+)(:[^\r\n,{}]+)?(,(?=[^{}]*{)|\s*{)', 'g')
|
||||
/**
|
||||
* Example:
|
||||
*
|
||||
* .classname::pesudo { color:red }
|
||||
*
|
||||
* g1 is normal selector `.classname`
|
||||
* g2 is pesudo class or pesudo element
|
||||
* g3 is the suffix
|
||||
*/
|
||||
css = css.replace(re, (g0, g1, g2, g3) => {
|
||||
if (typeof g2 === 'undefined') {
|
||||
g2 = ''
|
||||
}
|
||||
|
||||
/* eslint-ignore-next-line */
|
||||
if (
|
||||
g1.match(
|
||||
/^\s*(@media|\d+%?|@-webkit-keyframes|@keyframes|to|from|@font-face)/
|
||||
)
|
||||
) {
|
||||
return g1 + g2 + g3
|
||||
}
|
||||
|
||||
let appendClass = g1.replace(/(\s*)$/, '') + prefix + g2
|
||||
|
||||
return appendClass + g3
|
||||
})
|
||||
|
||||
return css
|
||||
}
|
||||
|
||||
export function addStyle(cssText, id) {
|
||||
id = id.toLowerCase()
|
||||
let ele = document.getElementById(id)
|
||||
let head = document.getElementsByTagName('head')[0]
|
||||
if (ele && ele.parentNode === head) {
|
||||
head.removeChild(ele)
|
||||
}
|
||||
|
||||
let someThingStyles = document.createElement('style')
|
||||
head.appendChild(someThingStyles)
|
||||
someThingStyles.setAttribute('type', 'text/css')
|
||||
someThingStyles.setAttribute('id', id)
|
||||
if (window.ActiveXObject) {
|
||||
someThingStyles.styleSheet.cssText = cssText
|
||||
} else {
|
||||
someThingStyles.textContent = cssText
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
export function appendStyle(style, attr) {
|
||||
if (!cache[attr]) {
|
||||
addStyle(scoper(style, attr), attr)
|
||||
cache[attr] = true
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue