UNPKG

mr-class-style-generator

Version:

A utility to apply inline styles from custom class names like mr-fs-[10vw]

194 lines (173 loc) 8.13 kB
function ApplyMrStyles({ startWith = "mr", breakpoint = { "xs": "425px", "sm": "575px", "md": "768px", "lg": "992px", "xl": "1200px", "2xl": "1400px", "3xl": "1600px", "4xl": "1800px", } }) { const matchedClassNames = []; function traverse(element) { for (const child of element.children) { try { const classAttr = child.getAttribute("class")?.trim(); if (classAttr && classAttr.startsWith(startWith) && classAttr.length > 3) { matchedClassNames.push(classAttr); } } catch (err) { console.warn("Error reading class attribute:", err); } traverse(child); } } function generateDynamicStyles(classNames) { const cssObj = { defaultCssText: "", maxDeviceCssText: "", minDeviceCssText: "" }; const cssMapObj = new Map(); let cssText = ""; const tempArrData = []; classNames .map((className) => { try { const escapedClass = className.replace(/\[/g, "\\[").replace(/\]/g, "\\]"); const multiClassArr = className.split(" "); const classList = multiClassArr.map((item, index) => { return item.split("-").slice(1, item.split("-").length); } ); console.log('escapedClass', escapedClass) console.log('multiClassArr', multiClassArr) console.log('classList', classList); const [prefix, key1, key2] = className.split("-"); const value = key2.replace(/\[|\]/g, ""); const newObj = new Map(); const temArr = []; classList.forEach((element, index) => { console.log('element', element, index) let temObj = { withType: "", fontSize: "", fontSizeNumber: 0, breakPoint: "", className: multiClassArr[index], styleType: "", breakPointNumber: 0 }; element.forEach(sub => { console.log('sub', sub) if (sub == "max") { temObj.withType = "max"; temObj.styleType = "max-devices"; } if (sub == "min") { temObj.withType = "min"; temObj.styleType = "min-devices"; } if (sub?.includes("[")) { const value = sub.replace(/\[|\]/g, ""); console.log('fontSize', temObj); temObj.fontSize = value; temObj.fontSizeNumber = Number(value.replaceAll("px", "")); } if (breakpoint[sub]) { temObj.breakPoint = breakpoint[sub]; temObj.breakPointNumber = Number((breakpoint[sub]).replaceAll("px", "")); } if (temObj.styleType == "") { temObj.styleType = "default"; } }) console.log('temObj', Object.values(temObj)); temArr.push(temObj); temObj = {}; }); tempArrData.push(temArr); return cssText; } catch (err) { console.warn(`Error parsing class "${className}":`, err); return ''; } }) .filter(Boolean) .join("\n\n"); const dataMap = processStyleData(tempArrData); dataMap.forEach((item, index) => ( cssText += item )) console.log('dataMap', { cssText }) return { cssText }; } function processStyleData(data) { const dataMap = new Map(); if (data) { const arrayData = data.flat(); const defaultStyleList = [...arrayData].filter((item, index) => (item.withType == "")); const minStyleList = [...arrayData].filter((item, index) => (item.withType == "min")); const maxStyleList = [...arrayData].filter((item, index) => (item.withType == "max")); const sortDefaultStyleList = [...defaultStyleList].sort((a, b) => { return a.fontSizeNumber - b.fontSizeNumber; }); const sortMinStyleList = [...minStyleList].sort((a, b) => { return a.breakPointNumber - b.breakPointNumber; }); const sortMaxStyleList = [...maxStyleList].sort((a, b) => { return b.breakPointNumber - a.breakPointNumber; }); const mergeStyleList = [ ...sortDefaultStyleList, ...sortMinStyleList, ...sortMaxStyleList, ] console.log('defaultStyleList', { mergeStyleList }); mergeStyleList.forEach((item, index) => { console.log('temArr-item', item); if (item.styleType == "default") { const currentClassName = item.className.replaceAll("[", "\\[").replaceAll("]", "\\]").replaceAll(startWith, `.${startWith}`); console.log('currentClassName', currentClassName); const cssStyle = `\n\n${currentClassName} {\n font-size: ${item.fontSize} !important;\n}` dataMap.set(currentClassName, cssStyle); } if (item.styleType === "max-devices") { if (item.withType) { const currentClassName = item.className.replaceAll("[", "\\[").replaceAll("]", "\\]").replaceAll(startWith, `.${startWith}`); const cssStyle = `\n@media screen and (${item.withType}-width:${item.breakPoint}){\n${currentClassName}{\n font-size: ${item.fontSize} !important;\n}}\n` dataMap.set(`${item.withType}-width:${item.breakPoint}`, cssStyle); } } if (item.styleType === "min-devices") { if (item.withType) { const currentClassName = item.className.replaceAll("[", "\\[").replaceAll("]", "\\]").replaceAll(startWith, `.${startWith}`); const cssStyle = `\n@media screen and (${item.withType}-width:${item.breakPoint}){\n${currentClassName}{\n font-size: ${item.fontSize} !important;\n}}\n` dataMap.set(`${item.withType}-width:${item.breakPoint}`, cssStyle); } } }) console.log('dataMap', dataMap) return dataMap; } } function injectStyles(cssRules) { try { const style = document.createElement("style"); style.textContent = cssRules; console.log('cssRules', cssRules) style.setAttribute(`data-mr-style-sheets`, ""); document.head.appendChild(style); } catch (err) { console.error("Failed to inject styles:", err); } } try { traverse(document.body); if (matchedClassNames.length > 0) { const { cssText } = generateDynamicStyles(matchedClassNames); console.log('generateDynamicStyles', cssText); console.log('matchedClassNames', matchedClassNames); injectStyles(cssText); } } catch (err) { console.error(`Error applying ${startWith} styles:`, err); } } export default ApplyMrStyles;