@mapcss/preset-tw
Version:
Tailwind CSS preset for MapCSS
248 lines (247 loc) • 9.55 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.resolveModifierMap = exports.mergeCSSMap = exports.resolveConfig = exports.resolvePreset = exports.resolveSyntax = exports.resolvePreProcessor = exports.$resolveTheme = exports.resolveTheme = exports.resolveDeepMapIdentifier = void 0;
const deps_js_1 = require("../deps.js");
const deps_js_2 = require("../deps.js");
const assert_js_1 = require("./utils/assert.js");
function firstSplit(value, separator) {
const arr = new RegExp(`(.+?)${separator}(.+)`).exec(value);
if (!arr)
return;
const [_, ...rest] = arr;
return rest;
}
function leftSplit(value, separator) {
const _value = (0, deps_js_1.isString)(value) ? [value] : value;
const _last = (0, deps_js_1.last)(_value);
if (!_last)
return [_value];
const result = firstSplit(_last, separator);
if (!result)
return [_value];
return [_value, ...leftSplit([...(0, deps_js_1.init)(_value), ...result], separator)];
}
class MockRegExpExecArray extends Array {
constructor(input = "") {
super();
Object.defineProperty(this, "input", {
enumerable: true,
configurable: true,
writable: true,
value: input
});
Object.defineProperty(this, "index", {
enumerable: true,
configurable: true,
writable: true,
value: 0
});
}
}
function resolveDeepMapIdentifier(value, deepMapCSS, context) {
const paths = leftSplit(value, context.separator);
for (const path of paths) {
const first = (0, deps_js_1.head)(path) ?? "DEFAULT";
const rest = (0, deps_js_1.tail)(path);
const identifierContext = {
...context,
parentKey: context.key,
key: first,
path,
};
const has = deepMapCSS.has(first);
if (has) {
const definition = deepMapCSS.get(first);
if ((0, deps_js_1.isFunction)(definition)) {
if (!(0, deps_js_1.isLength0)(rest))
continue;
const result = definition(new MockRegExpExecArray(), identifierContext);
if ((0, deps_js_1.isUndefined)(result))
continue;
return handleCSSObject(result, identifierContext.className);
}
if (definition instanceof Map) {
return resolveDeepMapIdentifier(rest, definition, identifierContext);
}
if ((0, deps_js_1.isEmptyObject)(definition))
return;
return handleCSSObject(definition, identifierContext.className);
}
for (const [key, m] of deepMapCSS) {
if ((0, deps_js_1.isRegExp)(key)) {
const regExpExecResult = key.exec(first);
if (!regExpExecResult)
continue;
if ((0, deps_js_1.isFunction)(m)) {
const result = m(regExpExecResult, identifierContext);
if ((0, deps_js_1.isUndefined)(result))
continue;
return handleCSSObject(result, identifierContext.className);
}
if (m instanceof Map) {
return resolveDeepMapIdentifier(rest, m, identifierContext);
}
if ((0, deps_js_1.isEmptyObject)(m))
return;
return handleCSSObject(m, identifierContext.className);
}
}
}
}
exports.resolveDeepMapIdentifier = resolveDeepMapIdentifier;
function handleCSSObject(cssObject, selector) {
if (cssObject instanceof deps_js_1.Root) {
return cssObject;
}
else if ((0, assert_js_1.isCSSDefinition)(cssObject)) {
return (0, deps_js_2.toAST)(cssObject.value);
}
else {
return new deps_js_1.Root({
nodes: [new deps_js_1.Rule({ selector, nodes: (0, deps_js_2.toAST)(cssObject).nodes })],
});
}
}
/** resolve theme via propPath safety */
function resolveTheme(identifier, themeRoot, { separator, theme }) {
const paths = leftSplit(identifier, separator);
for (const path of paths) {
const result = (0, deps_js_1.propPath)([themeRoot, ...path], theme);
if ((0, deps_js_1.isString)(result)) {
return result;
}
}
}
exports.resolveTheme = resolveTheme;
/** new version for theme resolver */
function $resolveTheme(identifier, themeRoot, { separator, theme }) {
const recursive = (path, theme) => {
const first = (0, deps_js_1.head)(path);
if ((0, deps_js_1.isUndefined)(first))
return theme;
const result = (0, deps_js_1.prop)(first, theme);
if ((0, deps_js_1.isString)(result) || (0, deps_js_1.isUndefined)(result))
return result;
return recursive((0, deps_js_1.tail)(path), result);
};
const paths = leftSplit(identifier, separator);
for (const path of paths) {
const rootResult = (0, deps_js_1.prop)(themeRoot, theme);
if ((0, deps_js_1.isUndefined)(rootResult))
continue;
if ((0, deps_js_1.isString)(rootResult))
return rootResult;
const result = recursive(path, rootResult);
if (!(0, deps_js_1.isUndefined)(result)) {
return result;
}
}
}
exports.$resolveTheme = $resolveTheme;
function pickByName({ name }) {
return name;
}
function resolvePreProcessor(...postProcessors) {
return (0, deps_js_1.distinctBy)(postProcessors, pickByName);
}
exports.resolvePreProcessor = resolvePreProcessor;
function resolveSyntax(...syntaxes) {
return (0, deps_js_1.distinctBy)(syntaxes, pickByName);
}
exports.resolveSyntax = resolveSyntax;
function resolvePreset(preset, context) {
return (0, deps_js_1.distinctBy)(preset, pickByName).map(({ fn }) => {
const { syntax = [], cssMap = {}, modifierMap = {}, theme = {}, preProcess = [], postcssPlugin = [], css = {}, } = fn(context);
return {
syntax,
cssMap,
modifierMap,
theme,
preProcess,
postcssPlugin,
css,
};
});
}
exports.resolvePreset = resolvePreset;
/** resolve config to deep merge */
function resolveConfig({ syntax: _syntax = [], preset = [], cssMap: _cssMap = {}, theme: _theme = {}, preProcess: _postProcess = [], modifierMap: _modifierMap = {}, postcssPlugin: _postcssPlugin = [], css: _css = {}, }, context) {
const _presets = resolvePreset(preset, context);
const modifierMap = _presets.map(({ modifierMap }) => modifierMap)
.reduce((acc, cur) => {
return (0, deps_js_1.deepMerge)(acc, cur);
}, _modifierMap);
const theme = _presets.map(({ theme }) => theme).reduce((acc, cur) => {
return (0, deps_js_1.deepMerge)(acc, cur);
}, _theme);
const syntax = resolveSyntax(..._syntax, ..._presets.map(({ syntax }) => syntax).flat());
const deepMapCSS = mergeCSSMap([..._presets.map(({ cssMap }) => cssMap), _cssMap]);
const preProcess = resolvePreProcessor(..._postProcess, ..._presets.map(({ preProcess }) => preProcess).flat());
const css = [..._presets.map(({ css }) => css), _css].reduce((acc, cur) => (0, deps_js_1.deepMerge)(acc, cur), {});
const postcssPlugin = [
..._postcssPlugin,
..._presets.map(({ postcssPlugin }) => postcssPlugin).flat(),
];
return {
deepMapCSS,
theme,
modifierMap,
syntax,
preProcess,
css,
postcssPlugin,
};
}
exports.resolveConfig = resolveConfig;
function mergeCSSMap(cssMaps) {
const recursive = (id, map) => {
const entries = Array.isArray(id) ? id : Object.entries(id);
entries.forEach(([key, value]) => {
const _key = (0, deps_js_1.isRegExp)(key) ? key : String(key);
if ((0, deps_js_1.isFunction)(value) || (0, assert_js_1.isCSSObject)(value)) {
map.set(_key, value);
}
else {
map.set(_key, recursive(value, new Map()));
}
});
return map;
};
return cssMaps.reduce((acc, cur) => recursive(cur, acc), new Map());
}
exports.mergeCSSMap = mergeCSSMap;
function resolveModifierMap(modifier, modifierMap, parentNode, context) {
const { separator } = context;
const paths = leftSplit(modifier, separator);
for (const path of paths) {
const _head = (0, deps_js_1.head)(path);
const first = _head ?? "DEFAULT";
if ((0, deps_js_1.isUndefined)(first))
continue;
if (!context.path) {
context.path = path;
}
const ctx = context.path
? context
: { ...context, path };
const modifier = (0, deps_js_1.prop)(first, modifierMap);
if ((0, deps_js_1.isUndefined)(modifier)) {
context.path = undefined;
continue;
}
if ((0, deps_js_1.isFunction)(modifier)) {
const maybeRoot = modifier(parentNode, ctx);
context.path = undefined;
if ((0, deps_js_1.isUndefined)(maybeRoot))
continue;
return maybeRoot;
}
const rest = (0, deps_js_1.tail)(path);
const result = resolveModifierMap(rest, modifier, parentNode, ctx);
if (result) {
return result;
}
context.path = undefined;
}
}
exports.resolveModifierMap = resolveModifierMap;