From b0128bfe0a3798365278da4000795dc229bbd8bf Mon Sep 17 00:00:00 2001 From: Robin Malfait Date: Thu, 27 May 2021 16:48:46 +0200 Subject: [PATCH] implement parallel variants --- src/jit/corePlugins.js | 28 ++++++++++++----- src/jit/lib/generateRules.js | 53 +++++++++++++++++--------------- src/jit/lib/setupContextUtils.js | 28 ++++++++++++----- tests/jit/variants.test.css | 16 ++++++++++ 4 files changed, 85 insertions(+), 40 deletions(-) diff --git a/src/jit/corePlugins.js b/src/jit/corePlugins.js index 2a49f381775f..abc108a4e618 100644 --- a/src/jit/corePlugins.js +++ b/src/jit/corePlugins.js @@ -30,23 +30,35 @@ export default { }) ) - addVariant( - 'marker', + addVariant('marker', [ + transformAllSelectors((selector) => { + let variantSelector = updateAllClasses(selector, (className) => { + return `marker${config('separator')}${className}` + }) + + return `${variantSelector} *::marker` + }), transformAllSelectors((selector) => { return updateAllClasses(selector, (className, { withPseudo }) => { return withPseudo(`marker${config('separator')}${className}`, '::marker') }) - }) - ) + }), + ]) - addVariant( - 'selection', + addVariant('selection', [ + transformAllSelectors((selector) => { + let variantSelector = updateAllClasses(selector, (className) => { + return `selection${config('separator')}${className}` + }) + + return `${variantSelector} *::selection` + }), transformAllSelectors((selector) => { return updateAllClasses(selector, (className, { withPseudo }) => { return withPseudo(`selection${config('separator')}${className}`, '::selection') }) - }) - ) + }), + ]) addVariant( 'before', diff --git a/src/jit/lib/generateRules.js b/src/jit/lib/generateRules.js index 916a64181e57..7670d064777e 100644 --- a/src/jit/lib/generateRules.js +++ b/src/jit/lib/generateRules.js @@ -100,7 +100,7 @@ function applyVariant(variant, matches, context) { } if (context.variantMap.has(variant)) { - let [variantSort, applyThisVariant] = context.variantMap.get(variant) + let variantFunctionTuples = context.variantMap.get(variant) let result = [] for (let [{ sort, layer, options }, rule] of matches) { @@ -112,36 +112,39 @@ function applyVariant(variant, matches, context) { let container = postcss.root() container.append(rule.clone()) - function modifySelectors(modifierFunction) { - container.each((rule) => { - if (rule.type !== 'rule') { - return - } - - rule.selectors = rule.selectors.map((selector) => { - return modifierFunction({ - get className() { - return getClassNameFromSelector(selector) - }, - selector, + for (let [variantSort, variantFunction] of variantFunctionTuples) { + let clone = container.clone() + function modifySelectors(modifierFunction) { + clone.each((rule) => { + if (rule.type !== 'rule') { + return + } + + rule.selectors = rule.selectors.map((selector) => { + return modifierFunction({ + get className() { + return getClassNameFromSelector(selector) + }, + selector, + }) }) }) + return clone + } + + let ruleWithVariant = variantFunction({ + container: clone, + separator: context.tailwindConfig.separator, + modifySelectors, }) - return container - } - let ruleWithVariant = applyThisVariant({ - container, - separator: context.tailwindConfig.separator, - modifySelectors, - }) + if (ruleWithVariant === null) { + continue + } - if (ruleWithVariant === null) { - continue + let withOffset = [{ sort: variantSort | sort, layer, options }, clone.nodes[0]] + result.push(withOffset) } - - let withOffset = [{ sort: variantSort | sort, layer, options }, container.nodes[0]] - result.push(withOffset) } return result diff --git a/src/jit/lib/setupContextUtils.js b/src/jit/lib/setupContextUtils.js index f6f4f19dfb5a..a6e0e2abb827 100644 --- a/src/jit/lib/setupContextUtils.js +++ b/src/jit/lib/setupContextUtils.js @@ -13,6 +13,7 @@ import isPlainObject from '../../util/isPlainObject' import escapeClassName from '../../util/escapeClassName' import nameClass from '../../util/nameClass' import { coerceValue } from '../../util/pluginUtils' +import bigSign from '../../util/bigSign' import corePlugins from '../corePlugins' import * as sharedState from './sharedState' import { env } from './sharedState' @@ -152,9 +153,11 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs } return { - addVariant(variantName, applyThisVariant, options = {}) { + addVariant(variantName, variantFunctions, options = {}) { + variantFunctions = [].concat(variantFunctions) + insertInto(variantList, variantName, options) - variantMap.set(variantName, applyThisVariant) + variantMap.set(variantName, variantFunctions) }, postcss, prefix: applyConfiguredPrefix, @@ -445,17 +448,28 @@ function registerPlugins(plugins, context) { } reservedBits += 3n - context.variantOrder = variantList.reduce( - (map, variant, i) => map.set(variant, (1n << BigInt(i)) << reservedBits), - new Map() + + let offset = 0 + context.variantOrder = new Map( + variantList + .map((variant, i) => { + let variantFunctions = variantMap.get(variant).length + let bits = (1n << BigInt(i + offset)) << reservedBits + offset += variantFunctions - 1 + return [variant, bits] + }) + .sort(([, a], [, z]) => bigSign(a - z)) ) context.minimumScreen = [...context.variantOrder.values()].shift() // Build variantMap - for (let [variantName, variantFunction] of variantMap.entries()) { + for (let [variantName, variantFunctions] of variantMap.entries()) { let sort = context.variantOrder.get(variantName) - context.variantMap.set(variantName, [sort, variantFunction]) + context.variantMap.set( + variantName, + variantFunctions.map((variantFunction, idx) => [sort << BigInt(idx), variantFunction]) + ) } } diff --git a/tests/jit/variants.test.css b/tests/jit/variants.test.css index 8eb3f867892b..02e9b8a028ef 100644 --- a/tests/jit/variants.test.css +++ b/tests/jit/variants.test.css @@ -28,6 +28,14 @@ .first-line\:underline::first-line { text-decoration: underline; } +.marker\:text-lg *::marker { + font-size: 1.125rem; + line-height: 1.75rem; +} +.marker\:text-red-500 *::marker { + --tw-text-opacity: 1; + color: rgba(239, 68, 68, var(--tw-text-opacity)); +} .marker\:text-lg::marker { font-size: 1.125rem; line-height: 1.75rem; @@ -36,6 +44,14 @@ --tw-text-opacity: 1; color: rgba(239, 68, 68, var(--tw-text-opacity)); } +.selection\:bg-blue-500 *::selection { + --tw-bg-opacity: 1; + background-color: rgba(59, 130, 246, var(--tw-bg-opacity)); +} +.selection\:text-white *::selection { + --tw-text-opacity: 1; + color: rgba(255, 255, 255, var(--tw-text-opacity)); +} .selection\:bg-blue-500::selection { --tw-bg-opacity: 1; background-color: rgba(59, 130, 246, var(--tw-bg-opacity));