unocss-preset-useful
Version:
My useful preset about unocss usage.
444 lines (423 loc) • 15.5 kB
JavaScript
;
Object.defineProperty(exports, '__esModule', { value: true });
const core = require('@unocss/core');
const postcss = require('postcss');
const postcssJs = require('postcss-js');
const utils = require('@unocss/preset-mini/utils');
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
const postcss__default = /*#__PURE__*/_interopDefaultCompat(postcss);
const postcssJs__default = /*#__PURE__*/_interopDefaultCompat(postcssJs);
const extractors = [
{
name: "unocss-preset-useful-extractor-includes-base64",
order: 0,
extract({ code }) {
return [...new Set(code.split(/[\\:]?[\s'"`{}]|;(?!base64)+/g))];
}
}
];
function createFilter(include, exclude) {
const includePattern = core.toArray(include || []);
const excludePattern = core.toArray(exclude || []);
return (id) => {
if (excludePattern.some((p) => id.match(p)))
return false;
return includePattern.some((p) => id.match(p));
};
}
function importantProcess(importantOptions) {
const keyFilter = createFilter(importantOptions.includes, importantOptions.excludes);
return (util) => {
for (const item of util.entries) {
if (keyFilter(item[0])) {
if (item[1] != null && !String(item[1]).includes("!important")) {
item[1] += " !important";
}
} else {
if (item[1] != null && String(item[1]).includes("!important")) {
item[1] = String(item[1]).replace(/\s*!important/g, "");
}
}
}
};
}
const rgbRE = /rgb\(([\d\s]+?)\s*\/\s*([^)]+)\)/;
const rgbaRE = /rgba\(([\d\s,]+),\s*([^)]+)\)/;
function postprocessWithUnColor(unColor) {
return (util) => {
util.entries.forEach((i) => {
const value = i[1];
if (typeof value === "string") {
let match = value.match(rgbaRE);
if (match != null) {
i[1] = value.replace(rgbaRE, `rgba(var(${unColor}) , $2)`);
util.entries.unshift([unColor, match[1]]);
} else {
match = value.match(rgbRE);
if (match != null) {
i[1] = value.replace(rgbRE, `rgb(var(${unColor}) / $2)`);
util.entries.unshift([unColor, match[1].trim()]);
}
}
}
});
};
}
function postprocess(options) {
const { unColor, important } = options;
return [
unColor ? postprocessWithUnColor(unColor) : void 0,
important ? importantProcess(important) : void 0
].filter(Boolean);
}
const PRESET_NAME = "useful";
const layerMeta = {
layer: PRESET_NAME
};
const resetCSS = `*,::before,::after{box-sizing:border-box;border-width:0;border-style:solid;border-color:var(--un-default-border-color,#e5e7eb);}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent;}body{margin:0;line-height:inherit;}hr{height:0;color:inherit;border-top-width:1px;}abbr:where([title]){text-decoration:underline dotted;}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit;}a{color:inherit;text-decoration:inherit;}b,strong{font-weight:bolder;}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em;}small{font-size:80%;}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline;}sub{bottom:-0.25em;}sup{top:-0.5em;}table{text-indent:0;border-color:inherit;border-collapse:collapse;}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;color:inherit;margin:0;padding:0;}button,select{text-transform:none;}button,[type='button'],[type='reset'],[type='submit']{-webkit-appearance:button;background-color:transparent;background-image:none;}:-moz-focusring{outline:auto;}:-moz-ui-invalid{box-shadow:none;}progress{vertical-align:baseline;}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto;}[type='search']{-webkit-appearance:textfield;outline-offset:-2px;}::-webkit-search-decoration{-webkit-appearance:none;}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit;}summary{display:list-item;}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0;}fieldset{margin:0;padding:0;}legend{padding:0;}ol,ul,menu{list-style:none;margin:0;padding:0;}dialog{padding:0;}textarea{resize:vertical;}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af;}button,[role="button"]{cursor:pointer;}:disabled{cursor:default;}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle;}img,video{max-width:100%;height:auto;}[hidden]{display:none;}`;
function compressCSS(css) {
return css.replace(/\s+/g, " ").replace(/\/\*[\s\S]*?\*\//g, "");
}
const resetPreflight = {
getCSS: () => compressCSS(resetCSS),
layer: layerMeta.layer
};
function preflights(options) {
if (typeof options.preflights === "boolean") {
return options.preflights ? [
resetPreflight
].filter(Boolean) : [];
}
return [
options.enableResetStyles || options.preflights.reset ? resetPreflight : void 0
].filter(Boolean);
}
const rules = [
[/^([^:]+)::(\S|[^:]+)$/, ([, n, v], { theme }) => {
const color = utils.parseColor(v, theme);
if (color?.cssColor?.type === "rgb" && color.cssColor.components) {
return {
[`--${n}`]: `${color.cssColor.components.join(",")}`
};
}
return {
[`--${n}`]: v
};
}]
];
normalizeRuleMeta(layerMeta);
function normalizeRuleMeta(ruleMeta) {
for (const r of rules)
r[2] = Object.assign(r[2] || {}, ruleMeta);
}
const _shortcuts = [
// position
["pr", "relative"],
["pa", "absolute"],
["pf", "fixed"],
["ps", "sticky"],
// position layout
[["pxc", "p-x-c"], "pa left-1/2 -translate-x-1/2"],
[["pyc", "p-y-c"], "pa top-1/2 -translate-y-1/2"],
[["pcc", "pc", "p-c", "p-c-c"], "pxc pyc"],
// flex layout
[["f-c", "fcc"], "flex justify-center items-center"],
[["f-c-c", "fccc"], "f-c flex-col"],
[["fc", "fxc", "f-x-c"], "flex justify-center"],
[["fi", "fyc", "f-y-c"], "flex items-center"],
[["fs", "fxs"], "flex justify-start"],
["fsc", "flex justify-start items-center"],
["fse", "flex justify-start items-end"],
[["fe", "fxe"], "flex justify-end"],
["fec", "flex justify-end items-center"],
["fb", "flex justify-between"],
["fbc", "flex justify-between items-center"],
["fa", "flex justify-around"],
["fac", "flex justify-around items-center"],
["fw", "flex flex-wrap"],
["fwr", "flex flex-wrap-reverse"],
// transition
["trans", "transition-all-350 ease-DEFAULT"]
];
const shortcuts = normalizeShortcut(_shortcuts);
normalizeShortcutMeta(layerMeta);
function normalizeShortcutMeta(ruleMeta) {
for (const r of shortcuts)
r[2] = Object.assign(r[2] || {}, ruleMeta);
}
function normalizeShortcut(shortcut) {
return shortcut.flatMap((s) => {
if (Array.isArray(s[0]))
return s[0].map((i) => [i, s[1], s[2]]);
return [s];
});
}
function nomarlizeTheme(theme) {
return {
...theme
};
}
const v_active = {
name: "@active",
match(matcher) {
if (!matcher.startsWith("@active"))
return matcher;
return {
matcher: matcher.slice(8),
selector: (s) => `${s}.active`
};
}
};
function variants(_options) {
return [
v_active
];
}
const animationRegExp = /^([a-z-]+)\s+([0-9.]+m?s?|[*+])?\s?([a-z-]+(?:\([^)]+\))?|[*+])?\s*([a-z0-9-]+|[*+])?$/i;
function resolveAnimation(extend_animation) {
const animation = {};
const keys = ["durations", "timingFns", "counts"];
const shortcuts = [];
for (const k in extend_animation) {
const v = extend_animation[k];
const match = v.match(animationRegExp);
if (match != null) {
const [, name, duration, timing, count] = match;
const values = [duration, timing, count];
if (name !== k)
shortcuts.push([`animate-${k}`, `animate-${name}`]);
for (let i = 0; i < keys.length; i++) {
const key = keys[i];
const value = values[i];
if (value != null) {
if (value === "*") {
continue;
}
if (animation[key]) {
animation[key][name] = values[i] === "+" ? "" : values[i];
} else {
animation[key] = {
[name]: values[i] === "+" ? "" : values[i]
};
}
}
}
}
}
return {
animation,
shortcuts
};
}
function deepMerge(original, patch) {
const o = original;
const p = patch;
if (Array.isArray(o) && Array.isArray(p))
return [...o, ...p];
if (Array.isArray(o))
return [...o];
const output = { ...o };
if (isObject(o) && isObject(p)) {
Object.keys(p).forEach((key) => {
if (isObject(p[key])) {
if (!(key in o))
Object.assign(output, { [key]: p[key] });
else
output[key] = deepMerge(o[key], p[key]);
} else {
Object.assign(output, { [key]: p[key] });
}
});
}
return output;
}
function isObject(val) {
return val !== null && typeof val === "object";
}
function getKeyframes(css) {
const root = postcss__default.parse(css);
const obj = postcssJs.objectify(root);
return Object.keys(obj).reduce((acc, key) => {
if (key.startsWith("@keyframes"))
acc[key] = obj[key];
return acc;
}, {});
}
function cssObj2StrSync(style) {
return Object.keys(style).reduce((str, key) => {
return `${str}${key}${stringifyObj(style[key])}`;
}, "").replace(/\n/g, "");
}
function stringifyObj(obj) {
return `{${Object.keys(obj).reduce((str, key) => {
return `${str}${camelToHyphen(key)}:${obj[key]};`;
}, "")}}`;
}
async function cssObj2StrAsync(style) {
return postcss__default().process(style, { parser: postcssJs__default }).then((result) => result.css);
}
function toArray(val) {
return Array.isArray(val) ? val : [val];
}
function camelToHyphen(str) {
return str.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
}
const defaultOptions = {
theme: {},
important: false,
enableDefaultShortcuts: true,
/**
* @deprecated Use `magicss` option instead
*/
enableMagicAnimations: false,
/**
* @deprecated Use `preflights.reset` instead
*/
enableResetStyles: true,
preflights: {
reset: true
},
// presets
uno: { preflight: "on-demand" },
attributify: true,
icons: true,
webFonts: false,
typography: false,
tagify: false,
remToPx: false,
scrollbar: false,
magicss: false,
// transformers
directives: true,
variantGroup: true,
compileClass: false
};
const defaultPresetOptions = {
webFonts: {
provider: "fontsource"
}
};
const defaultImportantOptions = {
excludes: [],
includes: [/.*/g]
};
async function resolveOptions(options) {
const optionsWithDefault = Object.assign({}, defaultOptions, options);
optionsWithDefault.unColor = typeof optionsWithDefault.unColor === "string" ? optionsWithDefault.unColor : optionsWithDefault.unColor ? "--un-color" : false;
optionsWithDefault.important = typeof optionsWithDefault.important === "object" ? Object.assign({}, defaultImportantOptions, optionsWithDefault.important) : optionsWithDefault.important === true ? defaultImportantOptions : false;
const presets = await resolvePresets(optionsWithDefault);
const transformers = await resolveTransformers(optionsWithDefault);
const { theme: t_theme, shortcuts } = resolveExtend(optionsWithDefault.theme.extend ?? {});
const _theme = deepMerge(optionsWithDefault.theme, t_theme);
return {
...optionsWithDefault,
theme: nomarlizeTheme(_theme),
meta: {
presets,
shortcuts,
transformers
}
};
}
function resolveExtend(extend) {
const _shortcuts = [];
const { animation, keyframes } = extend;
const { animation: resolvedAnimation, shortcuts } = resolveAnimation(animation ?? {});
_shortcuts.push(...shortcuts);
resolvedAnimation.keyframes = {};
for (const key in keyframes)
resolvedAnimation.keyframes[key] = `{${cssObj2StrSync(keyframes[key])}}`;
return {
theme: { animation: resolvedAnimation },
shortcuts: _shortcuts
};
}
async function resolvePresets(options) {
const presets = [];
const presetMap = {
uno: import('@unocss/preset-uno').then((m) => m.presetUno),
attributify: import('@unocss/preset-attributify').then((m) => m.presetAttributify),
icons: import('@unocss/preset-icons').then((m) => m.presetIcons),
webFonts: import('@unocss/preset-web-fonts').then((m) => m.presetWebFonts),
typography: import('@unocss/preset-typography').then((m) => m.presetTypography),
tagify: import('@unocss/preset-tagify').then((m) => m.presetTagify),
remToPx: import('@unocss/preset-rem-to-px').then((m) => m.default),
scrollbar: import('unocss-preset-scrollbar').then((m) => m.presetScrollbar),
magicss: import('unocss-preset-magicss').then((m) => m.presetMagicss)
};
for (const [key, preset] of Object.entries(presetMap)) {
const option = options[key];
if (option) {
const p = await preset;
const presetOptions = defaultPresetOptions[key];
if (typeof option === "object")
presets.push(p({ ...presetOptions, ...option }));
else
presets.push(p(presetOptions ?? {}));
}
}
return presets;
}
async function resolveTransformers(options) {
const transformers = [];
const transformerMap = {
directives: import('unocss').then((m) => m.transformerDirectives),
variantGroup: import('unocss').then((m) => m.transformerVariantGroup),
compileClass: import('unocss').then((m) => m.transformerCompileClass)
};
for (const [key, transformer] of Object.entries(transformerMap)) {
const option = options[key];
if (option) {
const t = await transformer;
transformers.push(t(typeof option === "boolean" ? {} : option));
}
}
return transformers;
}
const presetUseful = core.definePreset(async (options) => {
const resolvedOptions = await resolveOptions(options ?? {});
const { enableDefaultShortcuts, theme, meta } = resolvedOptions;
return {
name: `unocss-preset-${PRESET_NAME}`,
layers: {
[PRESET_NAME]: 2
},
rules,
theme,
variants: variants(),
shortcuts: [...enableDefaultShortcuts ? shortcuts : [], ...meta.shortcuts],
extractors,
postprocess: postprocess(resolvedOptions),
presets: meta.presets,
transformers: meta.transformers,
preflights: preflights(resolvedOptions),
options: resolvedOptions
};
});
function defineConfig(config) {
return config;
}
function defineUsefulConfig(options = {}, config = {}) {
return core.mergeConfigs([
defineConfig({
presets: [
presetUseful(options)
]
}),
config
]);
}
exports.animationRegExp = animationRegExp;
exports.camelToHyphen = camelToHyphen;
exports.cssObj2StrAsync = cssObj2StrAsync;
exports.cssObj2StrSync = cssObj2StrSync;
exports.deepMerge = deepMerge;
exports.default = presetUseful;
exports.defineConfig = defineConfig;
exports.defineUsefulConfig = defineUsefulConfig;
exports.getKeyframes = getKeyframes;
exports.isObject = isObject;
exports.presetUseful = presetUseful;
exports.resolveAnimation = resolveAnimation;
exports.stringifyObj = stringifyObj;
exports.toArray = toArray;