add utility config map
parent
d89883b658
commit
2de4816e3c
|
@ -1,9 +1,24 @@
|
||||||
import * as path from 'path'
|
import * as path from 'path'
|
||||||
import stackTrace from 'stack-trace'
|
import stackTrace from 'stack-trace'
|
||||||
import pkgUp from 'pkg-up'
|
import pkgUp from 'pkg-up'
|
||||||
|
import { glob } from './glob'
|
||||||
|
import { isObject } from './isObject'
|
||||||
|
|
||||||
function isObject(variable) {
|
export async function getBuiltInPlugins(cwd) {
|
||||||
return Object.prototype.toString.call(variable) === '[object Object]'
|
try {
|
||||||
|
return (
|
||||||
|
await glob(path.resolve(cwd, 'node_modules/tailwindcss/lib/plugins/*.js'))
|
||||||
|
)
|
||||||
|
.map((x) => {
|
||||||
|
try {
|
||||||
|
const mod = __non_webpack_require__(x)
|
||||||
|
return mod.default ? mod.default() : mod()
|
||||||
|
} catch (_) {}
|
||||||
|
})
|
||||||
|
.filter(Boolean)
|
||||||
|
} catch (_) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function getPlugins(config) {
|
export default function getPlugins(config) {
|
||||||
|
@ -13,7 +28,7 @@ export default function getPlugins(config) {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
|
|
||||||
return plugins.map(plugin => {
|
return plugins.map((plugin) => {
|
||||||
let pluginConfig = plugin.config
|
let pluginConfig = plugin.config
|
||||||
if (!isObject(pluginConfig)) {
|
if (!isObject(pluginConfig)) {
|
||||||
pluginConfig = {}
|
pluginConfig = {}
|
||||||
|
@ -25,7 +40,7 @@ export default function getPlugins(config) {
|
||||||
: [],
|
: [],
|
||||||
variants: isObject(pluginConfig.variants)
|
variants: isObject(pluginConfig.variants)
|
||||||
? Object.keys(pluginConfig.variants)
|
? Object.keys(pluginConfig.variants)
|
||||||
: []
|
: [],
|
||||||
}
|
}
|
||||||
|
|
||||||
const fn = plugin.handler || plugin
|
const fn = plugin.handler || plugin
|
||||||
|
@ -40,32 +55,32 @@ export default function getPlugins(config) {
|
||||||
const trace = stackTrace.parse(e)
|
const trace = stackTrace.parse(e)
|
||||||
if (trace.length === 0)
|
if (trace.length === 0)
|
||||||
return {
|
return {
|
||||||
name: fnName
|
name: fnName,
|
||||||
}
|
}
|
||||||
const file = trace[0].fileName
|
const file = trace[0].fileName
|
||||||
const dir = path.dirname(file)
|
const dir = path.dirname(file)
|
||||||
let pkg = pkgUp.sync({ cwd: dir })
|
let pkg = pkgUp.sync({ cwd: dir })
|
||||||
if (!pkg)
|
if (!pkg)
|
||||||
return {
|
return {
|
||||||
name: fnName
|
name: fnName,
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
pkg = __non_webpack_require__(pkg)
|
pkg = __non_webpack_require__(pkg)
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
return {
|
return {
|
||||||
name: fnName
|
name: fnName,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (pkg.name && path.resolve(dir, pkg.main || 'index.js') === file) {
|
if (pkg.name && path.resolve(dir, pkg.main || 'index.js') === file) {
|
||||||
return {
|
return {
|
||||||
name: pkg.name,
|
name: pkg.name,
|
||||||
homepage: pkg.homepage,
|
homepage: pkg.homepage,
|
||||||
contributes
|
contributes,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
name: fnName
|
name: fnName,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
import { runPlugin } from './runPlugin'
|
||||||
|
import { getBuiltInPlugins } from './getPlugins'
|
||||||
|
import { isObject } from './isObject'
|
||||||
|
|
||||||
|
const proxyHandler = (base = []) => ({
|
||||||
|
get(target, key) {
|
||||||
|
if (isObject(target[key])) {
|
||||||
|
return new Proxy(target[key], proxyHandler([...base, key]))
|
||||||
|
} else {
|
||||||
|
if (
|
||||||
|
[...base, key].every((x) => typeof x === 'string') &&
|
||||||
|
target.hasOwnProperty(key)
|
||||||
|
) {
|
||||||
|
return '$dep$' + [...base, key].join('.')
|
||||||
|
}
|
||||||
|
return target[key]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
export async function getUtilityConfigMap({ cwd, resolvedConfig, postcss }) {
|
||||||
|
const builtInPlugins = await getBuiltInPlugins(cwd)
|
||||||
|
const userPlugins = Array.isArray(resolvedConfig.plugins)
|
||||||
|
? resolvedConfig.plugins
|
||||||
|
: []
|
||||||
|
|
||||||
|
try {
|
||||||
|
const classNameConfigMap = {}
|
||||||
|
const proxiedConfig = new Proxy(resolvedConfig, proxyHandler())
|
||||||
|
|
||||||
|
;[...builtInPlugins, ...userPlugins].forEach((plugin) => {
|
||||||
|
runPlugin(plugin, {
|
||||||
|
postcss,
|
||||||
|
config: proxiedConfig,
|
||||||
|
addUtilities: (utilities) => {
|
||||||
|
Object.keys(utilities).forEach((util) => {
|
||||||
|
let props = Object.keys(utilities[util])
|
||||||
|
if (
|
||||||
|
props.length === 1 &&
|
||||||
|
/^\.[^\s]+$/.test(util) &&
|
||||||
|
typeof utilities[util][props[0]] === 'string' &&
|
||||||
|
utilities[util][props[0]].substr(0, 5) === '$dep$'
|
||||||
|
) {
|
||||||
|
classNameConfigMap[util.substr(1)] = utilities[util][
|
||||||
|
props[0]
|
||||||
|
].substr(5)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
return classNameConfigMap
|
||||||
|
} catch (_) {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
import semver from 'semver'
|
import semver from 'semver'
|
||||||
import dlv from 'dlv'
|
import { runPlugin } from './runPlugin'
|
||||||
|
|
||||||
export default function getVariants({ config, version, postcss }) {
|
export default function getVariants({ config, version, postcss }) {
|
||||||
let variants = ['responsive', 'hover']
|
let variants = ['responsive', 'hover']
|
||||||
|
@ -11,28 +11,16 @@ export default function getVariants({ config, version, postcss }) {
|
||||||
variants.push('first', 'last', 'odd', 'even', 'disabled', 'visited')
|
variants.push('first', 'last', 'odd', 'even', 'disabled', 'visited')
|
||||||
semver.gte(version, '1.3.0') && variants.push('group-focus')
|
semver.gte(version, '1.3.0') && variants.push('group-focus')
|
||||||
|
|
||||||
let plugins = config.plugins
|
let plugins = Array.isArray(config.plugins) ? config.plugins : []
|
||||||
if (!Array.isArray(plugins)) {
|
|
||||||
plugins = []
|
|
||||||
}
|
|
||||||
plugins.forEach((plugin) => {
|
plugins.forEach((plugin) => {
|
||||||
try {
|
runPlugin(plugin, {
|
||||||
;(plugin.handler || plugin)({
|
postcss,
|
||||||
addUtilities: () => {},
|
config,
|
||||||
addComponents: () => {},
|
|
||||||
addBase: () => {},
|
|
||||||
addVariant: (name) => {
|
addVariant: (name) => {
|
||||||
variants.push(name)
|
variants.push(name)
|
||||||
},
|
},
|
||||||
e: (x) => x,
|
|
||||||
prefix: (x) => x,
|
|
||||||
theme: (path, defaultValue) =>
|
|
||||||
dlv(config, `theme.${path}`, defaultValue),
|
|
||||||
variants: () => [],
|
|
||||||
config: (path, defaultValue) => dlv(config, path, defaultValue),
|
|
||||||
postcss,
|
|
||||||
})
|
})
|
||||||
} catch (_) {}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return variants
|
return variants
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
import nodeGlob from 'glob'
|
||||||
|
import dlv from 'dlv'
|
||||||
|
import * as path from 'path'
|
||||||
|
|
||||||
|
export function glob(pattern, options = {}) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
let g = new nodeGlob.Glob(pattern, options)
|
||||||
|
let matches = []
|
||||||
|
let max = dlv(options, 'max', Infinity)
|
||||||
|
g.on('match', (match) => {
|
||||||
|
matches.push(path.resolve(options.cwd || process.cwd(), match))
|
||||||
|
if (matches.length === max) {
|
||||||
|
g.abort()
|
||||||
|
resolve(matches)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
g.on('end', () => {
|
||||||
|
resolve(matches)
|
||||||
|
})
|
||||||
|
g.on('error', reject)
|
||||||
|
})
|
||||||
|
}
|
|
@ -3,8 +3,6 @@ import Hook from './hook.mjs'
|
||||||
import dlv from 'dlv'
|
import dlv from 'dlv'
|
||||||
import dset from 'dset'
|
import dset from 'dset'
|
||||||
import importFrom from 'import-from'
|
import importFrom from 'import-from'
|
||||||
import nodeGlob from 'glob'
|
|
||||||
import * as path from 'path'
|
|
||||||
import chokidar from 'chokidar'
|
import chokidar from 'chokidar'
|
||||||
import semver from 'semver'
|
import semver from 'semver'
|
||||||
import invariant from 'tiny-invariant'
|
import invariant from 'tiny-invariant'
|
||||||
|
@ -12,6 +10,8 @@ import getPlugins from './getPlugins'
|
||||||
import getVariants from './getVariants'
|
import getVariants from './getVariants'
|
||||||
import resolveConfig from './resolveConfig'
|
import resolveConfig from './resolveConfig'
|
||||||
import * as util from 'util'
|
import * as util from 'util'
|
||||||
|
import { glob } from './glob'
|
||||||
|
import { getUtilityConfigMap } from './getUtilityConfigMap'
|
||||||
|
|
||||||
function TailwindConfigError(error) {
|
function TailwindConfigError(error) {
|
||||||
Error.call(this)
|
Error.call(this)
|
||||||
|
@ -24,25 +24,6 @@ function TailwindConfigError(error) {
|
||||||
|
|
||||||
util.inherits(TailwindConfigError, Error)
|
util.inherits(TailwindConfigError, Error)
|
||||||
|
|
||||||
function glob(pattern, options = {}) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
let g = new nodeGlob.Glob(pattern, options)
|
|
||||||
let matches = []
|
|
||||||
let max = dlv(options, 'max', Infinity)
|
|
||||||
g.on('match', (match) => {
|
|
||||||
matches.push(path.resolve(options.cwd || process.cwd(), match))
|
|
||||||
if (matches.length === max) {
|
|
||||||
g.abort()
|
|
||||||
resolve(matches)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
g.on('end', () => {
|
|
||||||
resolve(matches)
|
|
||||||
})
|
|
||||||
g.on('error', reject)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function arraysEqual(arr1, arr2) {
|
function arraysEqual(arr1, arr2) {
|
||||||
return (
|
return (
|
||||||
JSON.stringify(arr1.concat([]).sort()) ===
|
JSON.stringify(arr1.concat([]).sort()) ===
|
||||||
|
@ -109,14 +90,21 @@ export default async function getClassNames(
|
||||||
delete config[sepLocation]
|
delete config[sepLocation]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const resolvedConfig = resolveConfig({ cwd, config })
|
||||||
|
|
||||||
return {
|
return {
|
||||||
configPath,
|
configPath,
|
||||||
config: resolveConfig({ cwd, config }),
|
config: resolvedConfig,
|
||||||
separator: typeof userSeperator === 'undefined' ? ':' : userSeperator,
|
separator: typeof userSeperator === 'undefined' ? ':' : userSeperator,
|
||||||
classNames: await extractClassNames(ast),
|
classNames: await extractClassNames(ast),
|
||||||
dependencies: hook.deps,
|
dependencies: hook.deps,
|
||||||
plugins: getPlugins(config),
|
plugins: getPlugins(config),
|
||||||
variants: getVariants({ config, version, postcss }),
|
variants: getVariants({ config, version, postcss }),
|
||||||
|
utilityConfigMap: await getUtilityConfigMap({
|
||||||
|
cwd,
|
||||||
|
resolvedConfig,
|
||||||
|
postcss,
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
export function isObject(thing) {
|
||||||
|
return Object.prototype.toString.call(thing) === '[object Object]'
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
import dlv from 'dlv'
|
||||||
|
|
||||||
|
export function runPlugin(plugin, params = {}) {
|
||||||
|
const { config, ...rest } = params
|
||||||
|
try {
|
||||||
|
;(plugin.handler || plugin)({
|
||||||
|
addUtilities: () => {},
|
||||||
|
addComponents: () => {},
|
||||||
|
addBase: () => {},
|
||||||
|
addVariant: () => {},
|
||||||
|
e: (x) => x,
|
||||||
|
prefix: (x) => x,
|
||||||
|
theme: (path, defaultValue) => dlv(config, `theme.${path}`, defaultValue),
|
||||||
|
variants: () => [],
|
||||||
|
config: (path, defaultValue) => dlv(config, path, defaultValue),
|
||||||
|
...rest,
|
||||||
|
})
|
||||||
|
} catch (_) {}
|
||||||
|
}
|
Loading…
Reference in New Issue