From 7e4fe93c7fd4bfbbf3ebbae96df788443272941d Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Mon, 21 Oct 2024 23:10:54 +0300 Subject: [PATCH] Proper support for alternate selectors --- src/components/modal/modals.style.js | 2 +- src/components/scrollbar.style.js | 2 +- src/services/style_setter/style_setter.js | 34 +--------- src/services/theme_data/iss_utils.js | 79 ++++++++++++++++------- 4 files changed, 59 insertions(+), 58 deletions(-) diff --git a/src/components/modal/modals.style.js b/src/components/modal/modals.style.js index f53a5f90..1cb4a34a 100644 --- a/src/components/modal/modals.style.js +++ b/src/components/modal/modals.style.js @@ -1,6 +1,6 @@ export default { name: 'Modals', - selector: '.modal-view', + selector: ['.modal-view', '#modal', '.shout-panel'], lazy: true, notEditable: true, validInnerComponents: [ diff --git a/src/components/scrollbar.style.js b/src/components/scrollbar.style.js index 714e9c81..1168f67d 100644 --- a/src/components/scrollbar.style.js +++ b/src/components/scrollbar.style.js @@ -1,6 +1,6 @@ export default { name: 'Scrollbar', - selector: '::-webkit-scrollbar', + selector: ['::-webkit-scrollbar-button', '::-webkit-scrollbar-thumb', '::-webkit-resizer'], notEditable: true, // for now defaultRules: [ { diff --git a/src/services/style_setter/style_setter.js b/src/services/style_setter/style_setter.js index 441b8965..73779cfb 100644 --- a/src/services/style_setter/style_setter.js +++ b/src/services/style_setter/style_setter.js @@ -56,22 +56,7 @@ export const generateTheme = (inputRuleset, callbacks, debug) => { getCssRules(themes3.eager, debug).forEach(rule => { // Hacks to support multiple selectors on same component - if (rule.match(/::-webkit-scrollbar-button/)) { - const parts = rule.split(/[{}]/g) - const newRule = [ - parts[0], - ', ', - parts[0].replace(/button/, 'thumb'), - ', ', - parts[0].replace(/scrollbar-button/, 'resizer'), - ' {', - parts[1], - '}' - ].join('') - onNewRule(newRule, false) - } else { - onNewRule(rule, false) - } + onNewRule(rule, false) }) onEagerFinished() @@ -85,22 +70,7 @@ export const generateTheme = (inputRuleset, callbacks, debug) => { const chunk = chunks[counter] Promise.all(chunk.map(x => x())).then(result => { getCssRules(result.filter(x => x), debug).forEach(rule => { - if (rule.match(/\.modal-view/)) { - const parts = rule.split(/[{}]/g) - const newRule = [ - parts[0], - ', ', - parts[0].replace(/\.modal-view/, '#modal'), - ', ', - parts[0].replace(/\.modal-view/, '.shout-panel'), - ' {', - parts[1], - '}' - ].join('') - onNewRule(newRule, true) - } else { - onNewRule(rule, true) - } + onNewRule(rule, true) }) // const t1 = performance.now() // console.debug('Chunk ' + counter + ' took ' + (t1 - t0) + 'ms') diff --git a/src/services/theme_data/iss_utils.js b/src/services/theme_data/iss_utils.js index 75f8dd93..a0914ee2 100644 --- a/src/services/theme_data/iss_utils.js +++ b/src/services/theme_data/iss_utils.js @@ -56,43 +56,74 @@ export const getAllPossibleCombinations = (array) => { * * @returns {String} CSS selector (or path) */ -export const genericRuleToSelector = components => (rule, ignoreOutOfTreeSelector, isParent) => { +export const genericRuleToSelector = components => (rule, ignoreOutOfTreeSelector, liteMode, children) => { + const isParent = !!children if (!rule && !isParent) return null const component = components[rule.component] - const { states = {}, variants = {}, selector, outOfTreeSelector } = component + const { states = {}, variants = {}, outOfTreeSelector } = component - const applicableStates = ((rule.state || []).filter(x => x !== 'normal')).map(state => states[state]) + const expand = (array = [], subArray = []) => { + if (array.length === 0) return subArray.map(x => [x]) + if (subArray.length === 0) return array.map(x => [x]) + return array.map(a => { + return subArray.map(b => [a, b]) + }).flat() + } + + let componentSelectors = Array.isArray(component.selector) ? component.selector : [component.selector] + if (ignoreOutOfTreeSelector || liteMode) componentSelectors = [componentSelectors[0]] + componentSelectors = componentSelectors.map(selector => { + if (selector === ':root') { + return '' + } else if (isParent) { + return selector + } else { + if (outOfTreeSelector && !ignoreOutOfTreeSelector) return outOfTreeSelector + return selector + } + }) const applicableVariantName = (rule.variant || 'normal') - let applicableVariant = '' + let variantSelectors = null if (applicableVariantName !== 'normal') { - applicableVariant = variants[applicableVariantName] + variantSelectors = variants[applicableVariantName] } else { - applicableVariant = variants?.normal ?? '' + variantSelectors = variants?.normal ?? '' } + variantSelectors = Array.isArray(variantSelectors) ? variantSelectors : [variantSelectors] + if (ignoreOutOfTreeSelector || liteMode) variantSelectors = [variantSelectors[0]] - let realSelector - if (selector === ':root') { - realSelector = '' - } else if (isParent) { - realSelector = selector - } else { - if (outOfTreeSelector && !ignoreOutOfTreeSelector) realSelector = outOfTreeSelector - else realSelector = selector - } + const applicableStates = (rule.state || []).filter(x => x !== 'normal') + // const applicableStates = (rule.state || []) + const statesSelectors = applicableStates.map(state => { + const selector = states[state] || '' + let arraySelector = Array.isArray(selector) ? selector : [selector] + if (ignoreOutOfTreeSelector || liteMode) arraySelector = [arraySelector[0]] + arraySelector + .sort((a, b) => { + if (a.startsWith(':')) return 1 + if (/^[a-z]/.exec(a)) return -1 + else return 0 + }) + .join('') + return arraySelector + }) - const selectors = [realSelector, applicableVariant, ...applicableStates] - .sort((a, b) => { - if (a.startsWith(':')) return 1 - if (/^[a-z]/.exec(a)) return -1 - else return 0 - }) - .join('') + const statesSelectorsFlat = statesSelectors.reduce((acc, s) => { + return expand(acc, s).map(st => st.join('')) + }, []) + + const componentVariant = expand(componentSelectors, variantSelectors).map(cv => cv.join('')) + const componentVariantStates = expand(componentVariant, statesSelectorsFlat).map(cvs => cvs.join('')) + const selectors = expand(componentVariantStates, children).map(cvsc => cvsc.join(' ')) + /* + */ if (rule.parent) { - return (genericRuleToSelector(components)(rule.parent, ignoreOutOfTreeSelector, true) + ' ' + selectors).trim() + return genericRuleToSelector(components)(rule.parent, ignoreOutOfTreeSelector, liteMode, selectors) } - return selectors.trim() + + return selectors.join(', ').trim() } /**