diff --git a/jsHelper/spicetifyWrapper.js b/jsHelper/spicetifyWrapper.js index b05b665c01..0494518c29 100644 --- a/jsHelper/spicetifyWrapper.js +++ b/jsHelper/spicetifyWrapper.js @@ -311,6 +311,34 @@ Spicetify.LocalStorage = { set: (key, value) => localStorage.setItem(key, value), }; +Spicetify._getStyledClassName = (args, component) => { + const element = Array.from(args).find(e => e?.children || e?.dangerouslySetInnerHTML); + if (!element) return; + + let className = /(?:\w+__)?(\w+)-[\w-]+/.exec(component.componentId)?.[1]; + + const includedKeys = ["role", "variant", "semanticColor", "iconColor", "color", "weight", "buttonSize", "position", "paddingBottom", "data-encore-id"]; + + for (const key of includedKeys) { + if (typeof element[key] === "string" && element[key].length) { + className += `-${element[key]}`; + } + } + + const excludedKeys = ["children", "className", "style", "dir", "key", "ref", "as", ""]; + const excludedPrefix = ["aria-"]; + + const booleanKeys = Object.keys(element).filter(key => typeof element[key] === "boolean" && element[key]); + + for (const key of booleanKeys) { + if (excludedKeys.includes(key)) continue; + if (excludedPrefix.some(prefix => key.startsWith(prefix))) continue; + className += `-${key}`; + } + + return className; +}; + Spicetify.getFontStyle = (font) => { if (!font || !Spicetify._fontStyle) return; let rawStyle = Spicetify._fontStyle({ variant: font }).filter(style => typeof style === "string").join(""); diff --git a/src/preprocess/preprocess.go b/src/preprocess/preprocess.go index 2182eb6e14..652b2b664d 100644 --- a/src/preprocess/preprocess.go +++ b/src/preprocess/preprocess.go @@ -494,6 +494,12 @@ if (${1}.popper?.firstChild?.id === "context-menu") { `=(?:\(\w\)=>|function\(\w\)\{)\w+ ?\w=\w\.iconSize`, `=Spicetify.ReactComponent.IconComponent${0}`) + // Mapping styled-components classes + utils.Replace( + &input, + `(\w+ [\w$_]+)=[\w$_]+\([\w$_]+>>>0\)`, + `${1}=Spicetify._getStyledClassName(arguments,this)`) + return input }