UNPKG

@tenoxui/moxie

Version:

Very lightweight utility-first CSS engine for style generation

386 lines (385 loc) 13.6 kB
function R(h) { return h.replace(/^(\d)/, "\\3$1 ").replace(/([#{}.:;?%&,@+*~'"!^$[\]()=>|/])/g, "\\$1"); } function P(h) { if (/^(webkit|moz|ms|o)[A-Z]/.test(h)) { const e = h.match(/^(webkit|moz|ms|o)/); if (e) { const s = e[0]; return `-${s}${h.slice(s.length).replace(/[A-Z]/g, (t) => `-${t.toLowerCase()}`)}`; } } return h.replace(/[A-Z]/g, (e) => `-${e.toLowerCase()}`); } function b(h, e, s, t, l, n) { return `${h ? `${h}:` : ""}${e}${s ? "-" : ""}${s}${t}${l ? `/${l}${n}` : ""}`; } function V(h) { return h.replace(/[.*+?^${}()|[\]\\/\\-]/g, "\\$&"); } function S(h) { if (!h) return []; const e = /* @__PURE__ */ new Set(); return Object.entries(h).forEach(([s, t]) => { t && typeof t == "object" && Object.keys(t).forEach((l) => { e.add(l); }); }), Array.from(e); } function Z({ safelist: h = [], property: e = {}, classes: s = {} } = {}) { const t = s, l = Object.keys(e); if (!t) return [...l, ...h].sort((c, o) => o.length - c.length); const a = [...S(t)]; return [...l, ...a, ...h].sort((c, o) => o.length - c.length); } function z({ inputPrefixChars: h = [], safelist: e = [], property: s = {}, classes: t = {} } = {}) { let l = Z({ safelist: e, property: s, classes: t }).map( V ); l.length > 0 && (l = l.join("|") + "|"); const n = "\\[[^\\]]+\\]", a = "\\([^()]*(?:\\([^()]*\\)[^()]*)*\\)", c = "\\{[^{}]*(?:\\{[^{}]*\\}[^{}]*)*\\}", o = `[${["a-zA-Z0-9_\\-", ...h].join("")}]`, r = ( // Simple prefix (hover, md, focus, etc.) o + "+|" + // value-like prefix (nth-(4), max-[445px], etc.) o + "+(?:-(?:" + n + "|" + a + "|" + c + "))|" + // added support for custom secondValue for prefix o + "+(?:-(?:" + n + "|" + a + "|" + c + "))?(?:\\/[a-zA-Z0-9_\\-]+)|" + // Direct bracket, parenthesis, or brace content n + "|" + a + "|" + c ), d = `(${l}\\[[^\\]]+\\])`, i = "(?:-)", $ = "(-?(?:\\d+(?:\\.\\d+)?)|(?:[a-zA-Z0-9_]+(?:-[a-zA-Z0-9_]+)*(?:-[a-zA-Z0-9_]+)*)|(?:#[0-9a-fA-F]+)|" + // Hex colors n + "|" + // Bracket content c + "|" + // Curly brace content a + "|(?:\\$[^\\s\\/]+))", A = "([a-zA-Z%]*)", f = "(?:\\/(-?(?:\\d+(?:\\.\\d+)?)|(?:[a-zA-Z0-9_]+(?:-[a-zA-Z0-9_]+)*(?:-[a-zA-Z0-9_]+)*)|(?:#[0-9a-fA-F]+)|" + n + "|" + c + "|" + a + "|(?:\\$[^\\s\\/]+))([a-zA-Z%]*))?"; return { prefix: r, type: d, separator: i, value: $, unit: A, secondValuePattern: f, all: "^(?:(" + r + "):)?" + d + i + $ + A + f + "$" }; } class _ { constructor({ property: e = {}, values: s = {}, classes: t = {}, prefixChars: l = [] } = {}) { this.property = e, this.values = s, this.classes = t, this.prefixChars = l.map(V); } regexp(e) { return z({ safelist: e, property: this.property, classes: this.classes, inputPrefixChars: this.prefixChars }); } parse(e, s) { const t = this.regexp(s), l = e.match(new RegExp(t.all)); if (l) { const [, a, c, o, r, d, i] = l; return [a, c, o, r || "", d, i]; } const n = e.match( new RegExp(`^(?:(${t.prefix}):)?${t.type}$`) ); return n ? [n[1], n[2], "", "", void 0, void 0] : null; } // unique value parser processValue(e, s, t) { if (!e) return ""; const l = (n) => n.replace(/\{([^}]+)\}/g, (a, c) => { const o = this.values, r = o !== null ? typeof o[t] == "object" ? o[t][c] : o[c] : void 0; return typeof r == "string" ? r : a; }); if (typeof this.values == "object" && this.values !== null && (this.values[t] && typeof this.values[t] == "object" && this.values[t][e] || this.values[e])) return typeof this.values[t] == "object" && this.values[t] !== null ? this.values[t][e] : this.values[e]; if (e.startsWith("$")) return `var(--${e.slice(1)})`; if (e.startsWith("[") && e.endsWith("]") || e.startsWith("(") && e.endsWith(")")) { const n = e.slice(1, -1).replace(/\\\_/g, "m0x13c55").replace(/\_/g, " ").replace(/m0x13c55/g, "_"); return n.includes("{") ? l(n) : n.startsWith("--") ? `var(${n})` : n; } return e + (s || ""); } processShorthand(e = "", s = "", t = "", l, n = "", a = "", c = "", o) { const r = this.property[e]; if (typeof r == "object" && !Array.isArray(r) && !("property" in r)) return null; const d = /^(?:\(|\[)([^:]+):(.+)(?:\)|\])$/; let i = null, $ = s || ""; const A = $.match(d); if (A && (i = A[1].trim(), $ = A[2].trim()), (typeof r == "string" && !r.includes(":") || Array.isArray(r)) && (!s || s.includes(i + ":") || n)) return null; let f; s.includes(i + ":") ? f = s.startsWith("(") ? `(${$})` : `[${$}]` : f = s; const y = this.processValue(f, t, e), g = this.processValue(n, a, e); if (e.startsWith("[") && e.endsWith("]")) { if (!s || n) return null; const u = e.slice(1, -1).split(",").map( (C) => C.trim().startsWith("--") ? String(C.trim()) : P(String(C.trim())) ); return { className: b(l, e, s, t), cssRules: u.length === 1 ? u[0] : u, value: y, prefix: l }; } if (r) { if (typeof r == "object" && "property" in r) { const C = r.group && this.values[r.group][y] ? this.values[r.group][y] : t ? s : y, p = ( // handle `properties.property` function typeof r.property == "function" ? r.property({ value: s.startsWith("[") ? y : C, unit: s.startsWith("[") ? "" : t, secondValue: s.startsWith("[") ? "" : a ? n : g, secondUnit: s.startsWith("[") ? "" : a, key: i, raw: o }) : ( // defaulting to string property // e.g. { property: { p: { property: 'padding', value: '{0} {1}' } } // the `p` is the type or the shorthand for `padding` property - // and has support for second value r.property ) ); if (p && typeof p == "object" && !Array.isArray(p) && "cssRules" in p) { const { className: W, cssRules: j = null, value: v = null, prefix: w } = p; return { className: W || c, cssRules: j, value: v, prefix: w || l, isCustom: !!W }; } const m = r.value || "{0}"; let x; if (typeof m == "function") x = m({ value: C, unit: t, secondValue: a ? n : g, secondUnit: a, key: i, raw: o }); else if (typeof m == "string") { const W = r.group || e, j = this.processValue(f, t, W); this.values[W] && typeof this.values[W] == "object" && this.values[W][f] ? x = this.values[W][f] : m.includes("{") ? x = this.parseValuePattern( W, m, j, "", g, "" ) : typeof m == "string" && !m.includes("{") ? x = m : x = y; } else if (Array.isArray(m)) { if (!m.includes(s + t) || n) return null; x = s + t; } else x = null; return (typeof r.property == "string" || Array.isArray(r.property)) && typeof m == "string" && (s.includes(i + ":") || !m.includes("{1") && n) || // check if the property is string or array of properties // but the value is null (typeof r.property == "string" || Array.isArray(r.property)) && m === null || // check if the type is a direct rules but has `value` defined typeof r.property == "string" && r.property.includes(":") && s || (typeof r.property == "string" || Array.isArray(r.property)) && typeof r.value == "string" && !r.value.includes("{") && s ? null : { className: b(l, e, s, t, n, a), cssRules: ( // if not property, or when `properties.property` as function return null p ? Array.isArray(p) ? p : ( // is direct CSS rules typeof p == "string" && (p.includes(":") || p.includes("value:")) && p.includes("value:") ? p.slice(6) : ( // basic string property P(String(p)) ) ) : null ), value: m === null || p === null || p.includes(":") || p.includes("value:") ? null : s.startsWith("[") ? y : x, prefix: l }; } const u = ( // handle `properties` as function // e.g. m: ({ value, unit }) => `margin: ${value}${unit || 'px'}` // m-4 => margin: 4px // m-4rem => margin: 4rem typeof r == "function" ? r({ value: s.startsWith("[") ? y : t ? s : y, unit: s.startsWith("[") ? "" : t, secondValue: s.startsWith("[") ? "" : a ? n : g, secondUnit: s.startsWith("[") ? "" : a, key: i, raw: o }) : ( // e.g. { property: { bg: 'background' } } // the `bg` is the type or the shorthand for `background` property r ) ); if (u && typeof u == "object" && !Array.isArray(u) && "cssRules" in u) { const { className: C, cssRules: p = null, value: m = null, prefix: x } = u; return { className: C || c, cssRules: p, value: m, prefix: x || l, isCustom: !!C }; } return { className: b(l, e, s, t, n, a), cssRules: u ? Array.isArray(u) ? u : typeof u == "string" && (u.includes(":") || u.startsWith("value:")) && u.startsWith("value:") ? u.slice(6) : P(String(u)) : null, value: typeof u == "string" && u.includes(":") ? null : y, prefix: l }; } return null; } parseValuePattern(e, s, t, l, n, a) { if (!s.includes("{0}") && !s.includes("{1") && !s.includes("||")) return s; const [c, o] = s.split("||").map((i) => i.trim()), r = this.processValue(t, l, e), d = this.processValue(n, a, e); if (s.includes("{0}") && s.includes("{1") || s.includes("{1")) { let i = c; if (t && (i = i.replace(/\{0\}/g, r)), s.includes("{1")) { s.includes("{1}") && (n ? i = n.startsWith("[") ? d : i.replace(/\{1\}/g, d) : i = o || c); const $ = /\{1([^}]*)\}/g; let A; for (; (A = $.exec(i)) !== null; ) { const f = A[0], y = A[1].trim(); let g = d; !g && y.includes("|") ? g = y.split("|")[1].trim() : g || (g = ""), i = t.startsWith("[") ? r : i.replace(f, g); } } return t ? i : o || c; } else return t ? t.startsWith("[") ? r : c.replace(/\{0\}/g, r) : o || c; } getParentClass(e) { return Object.keys(this.classes).filter( (s) => Object.prototype.hasOwnProperty.call( this.classes[s], e ) ); } processCustomClass(e, s = "", t = "", l = "", n = "", a = "") { if (!e) return null; const c = this.getParentClass(e), o = s && e.endsWith(`-${s}${t}`); if (c.length > 0) { const r = c.map((d) => { const i = this.classes[d]; if (!i || s && !o && i[e] && !i[e].includes("{0}") && !i[e].includes("|")) return null; const $ = this.parseValuePattern( e, i[e] || "", s, t, n, a ); return `${P(String(d))}: ${$}`; }).filter(Boolean).join("; "); return { className: o ? e : b(l, e, s, t, n, a), cssRules: r, value: null, prefix: l }; } return null; } process(e) { try { const s = Array.isArray(e) ? e : e.split(/\s+/), t = []; for (const l of s) try { if (!l) continue; const n = this.parse(l); if (!n) continue; const [a, c, o, r, d, i] = n; if (!c) continue; const $ = [...n, b(a, c, o, r, d, i)], A = this.getParentClass(`${c}-${o}`).length > 0 ? `${c}-${o}` : c; try { const f = this.processCustomClass( A, o, r, a, d, i ); if (f) { const { className: y, cssRules: g, prefix: u } = f; if (!g || g === "null") continue; t.push({ className: R(y), cssRules: g, value: null, prefix: u, raw: $ }); continue; } } catch (f) { console.warn(`Error processing custom class "${l}":`, f); } try { const f = this.processShorthand( c, o, r, a, d, i, l, $ ); if (f) { const { className: y, cssRules: g, value: u, prefix: C, isCustom: p } = f; if (!g || g === "null") continue; t.push({ className: p ? y : R(y), cssRules: g, value: u, prefix: C, raw: $ }); } } catch (f) { console.warn(`Error processing shorthand "${l}":`, f); } } catch (n) { console.warn(`Failed to process class \`${l}\`:`, n); } return t; } catch (s) { return console.error("Critical error in process method:", s), []; } } } export { _ as TenoxUI, b as constructRaw, _ as default, R as escapeCSSSelector, z as regexp, P as toKebabCase };