UNPKG

@re-flex/styles

Version:
181 lines (180 loc) 6.38 kB
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;