@re-flex/styles
Version:
Core Style Util Package
181 lines (180 loc) • 6.38 kB
JavaScript
import { cssPropertyAlias, cssPropertyPrefixFlags, cssValuePrefixFlags, } from "style-vendorizer";
let newRule = /(?:([\u0080-\uFFFF\w-%@]+) *:? *([^{;]+?);|([^;}{]*?) *{)|(}\s*)/g;
let ruleClean = /\/\*[^]*?\*\/|\s\s+|\n/g;
const vendorizerCache = new Map();
const autoPrefixer = (property, value) => {
if (vendorizerCache.has(property + ":" + value)) {
return vendorizerCache.get(property + ":" + value);
}
let cssText = "";
const propertyAlias = cssPropertyAlias(property);
if (propertyAlias)
cssText += `${propertyAlias}:${value};`;
const propertyFlags = cssPropertyPrefixFlags(property);
if (propertyFlags & 0b001)
cssText += `-webkit-${property} : ${value}; `;
if (propertyFlags & 0b010)
cssText += `-moz-${property} : ${value}; `;
if (propertyFlags & 0b100)
cssText += `-ms-${property} : ${value}; `;
const valueFlags = cssValuePrefixFlags(property, value);
if (valueFlags & 0b001)
cssText += `${property} : -webkit-${value}; `;
else if (valueFlags & 0b010)
cssText += `${property} : -moz-${value}; `;
else if (valueFlags & 0b100)
cssText += `${property} : -ms-${value}; `;
cssText += `${property} : ${value}; `;
vendorizerCache.set(property + ":" + value, cssText);
return cssText;
};
class RxUtils {
LINK_ID = "__reflex";
DOM_TARGET = document.head;
SSR = {
data: "",
};
sheet;
renderCount = 0;
nextRenderCount = 0;
sheetData = [];
cache = new Map();
constructor(linkID, target = document.head) {
this.LINK_ID = linkID;
this.DOM_TARGET = target;
this.sheet = this.getSheet();
this.cache = new Map();
this.sheetData = [];
setInterval(() => {
if (this.renderCount !== this.nextRenderCount) {
console.log("this.renderCount", this.renderCount);
this.sheet.innerHTML = this.sheetData.reduce((t, c) => t + c, "");
this.renderCount = this.nextRenderCount;
}
}, 2);
}
astish(val) {
let tree = [{}];
let block;
while ((block = newRule.exec(val.replace(ruleClean, "")))) {
if (block[4]) {
tree.shift();
}
else if (block[3]) {
tree.unshift((tree[0][block[3]] = tree[0][block[3]] || {}));
}
else {
tree[0][block[1]] = block[2];
}
}
return tree[0];
}
compile(str, defs) {
return str.reduce((out, next, i) => {
let tail = defs[i];
if (tail && tail.call) {
let res = tail();
let className = res && res.props && res.props.className;
let end = className || (/^rui_/.test(res) && res);
if (end) {
tail = "." + end;
}
else if (res && typeof res == "object") {
tail = res.props ? "" : this.parse(res, "");
}
else {
tail = res === false ? "" : res;
}
}
return out + next + (tail === null ? "" : tail);
}, "");
}
getSheet() {
let linkItem = this.DOM_TARGET.querySelector("#" + this.LINK_ID);
if (linkItem === null) {
linkItem = document.createElement("style");
linkItem.id = this.LINK_ID;
linkItem.innerHTML = " ";
this.DOM_TARGET.appendChild(linkItem);
}
return linkItem;
}
stringify(data) {
if (typeof data === "object") {
let out = "";
for (let p in data)
out += p + this.stringify(data[p]);
return out;
}
else {
return data;
}
}
hash(compiled, config) {
let stringifiedCompiled = this.stringify(compiled);
let className = this.toHash(stringifiedCompiled);
if (this.cache.has(className) === false) {
let ast = typeof compiled === "object" ? compiled : this.astish(compiled);
this.cache.set(className, this.parse(config.keyframes ? { ["@keyframes " + className]: ast } : ast, config.global ? "" : "." + className));
this.update(this.cache.get(className), config.append);
}
return className;
}
parse(obj, selector) {
let outer = "";
let blocks = "";
let current = "";
Object.entries(obj).forEach(([key, val]) => {
if (key[0] == "@") {
if (key[1] == "i") {
outer = key + " " + val + ";";
}
else if (key[1] == "f") {
blocks += this.parse(val, key);
}
else {
blocks +=
key + "{" + this.parse(val, key[1] == "k" ? "" : selector) + "}";
}
}
else if (typeof val == "object") {
blocks += this.parse(val, selector
?
selector.replace(/([^,])+/g, (sel) => {
return key.replace(/(^:.*)|([^,])+/g, (k) => {
if (/&/.test(k))
return k.replace(/&/g, sel);
return sel ? sel + " " + k : k;
});
})
: key);
}
else if (val != undefined) {
key = /^--/.test(key)
? key
: key.replace(/[A-Z]/g, "-$&").toLowerCase();
current += autoPrefixer(key, val);
}
});
return (outer +
(selector && current ? selector + "{" + current + "}" : current) +
blocks);
}
toHash(str) {
let i = 0, out = 11;
while (i < str.length)
out = (101 * out + str.charCodeAt(i++)) >>> 0;
return "rui_" + out;
}
extractCss() {
let out = this.sheet.innerHTML;
this.sheet.innerHTML = "";
return out;
}
update(css, append) {
if (this.sheetData.findIndex((dcss) => dcss === css) === -1) {
this.sheet.innerHTML += css;
}
}
}
export default RxUtils;