@ogxjs/core 0.1.1 → 0.2.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/dist/builder.d.ts +5 -0
  2. package/dist/builder.d.ts.map +1 -1
  3. package/dist/builder.js +11 -1
  4. package/dist/cache/hash.d.ts +66 -0
  5. package/dist/cache/hash.d.ts.map +1 -0
  6. package/dist/cache/hash.js +161 -0
  7. package/dist/cache/index.d.ts +10 -0
  8. package/dist/cache/index.d.ts.map +1 -0
  9. package/dist/cache/index.js +12 -0
  10. package/dist/cache/lru.d.ts +122 -0
  11. package/dist/cache/lru.d.ts.map +1 -0
  12. package/dist/cache/lru.js +269 -0
  13. package/dist/cache/snapshot.d.ts +116 -0
  14. package/dist/cache/snapshot.d.ts.map +1 -0
  15. package/dist/cache/snapshot.js +204 -0
  16. package/dist/cache.d.ts +2 -2
  17. package/dist/cache.js +2 -2
  18. package/dist/css.d.ts +19 -6
  19. package/dist/css.d.ts.map +1 -1
  20. package/dist/index.d.ts +18 -4
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +41 -10
  23. package/dist/ogx.js +2 -2
  24. package/dist/perf/index.d.ts +8 -0
  25. package/dist/perf/index.d.ts.map +1 -0
  26. package/dist/perf/index.js +7 -0
  27. package/dist/perf/timing.d.ts +160 -0
  28. package/dist/perf/timing.d.ts.map +1 -0
  29. package/dist/perf/timing.js +305 -0
  30. package/dist/presets/blog.js +1 -1
  31. package/dist/presets/docs.d.ts +2 -0
  32. package/dist/presets/docs.d.ts.map +1 -1
  33. package/dist/presets/docs.js +26 -23
  34. package/dist/presets/minimal.d.ts +2 -0
  35. package/dist/presets/minimal.d.ts.map +1 -1
  36. package/dist/presets/minimal.js +8 -16
  37. package/dist/presets/social.d.ts +2 -0
  38. package/dist/presets/social.d.ts.map +1 -1
  39. package/dist/presets/social.js +28 -18
  40. package/dist/render-png.d.ts.map +1 -1
  41. package/dist/render-png.js +9 -1
  42. package/dist/render-svg.d.ts.map +1 -1
  43. package/dist/render-svg.js +11 -1
  44. package/dist/tailwind/class-cache.d.ts +141 -0
  45. package/dist/tailwind/class-cache.d.ts.map +1 -0
  46. package/dist/tailwind/class-cache.js +212 -0
  47. package/dist/tailwind/index.d.ts +14 -1
  48. package/dist/tailwind/index.d.ts.map +1 -1
  49. package/dist/tailwind/index.js +15 -1
  50. package/dist/tailwind/lookup-tables.d.ts +30 -0
  51. package/dist/tailwind/lookup-tables.d.ts.map +1 -0
  52. package/dist/tailwind/lookup-tables.js +427 -0
  53. package/dist/tailwind/parser-v2.d.ts +54 -0
  54. package/dist/tailwind/parser-v2.d.ts.map +1 -0
  55. package/dist/tailwind/parser-v2.js +250 -0
  56. package/dist/tailwind/parser.d.ts +1 -0
  57. package/dist/tailwind/parser.d.ts.map +1 -1
  58. package/dist/tailwind/parser.js +1 -0
  59. package/dist/tailwind/prefix-handlers.d.ts +68 -0
  60. package/dist/tailwind/prefix-handlers.d.ts.map +1 -0
  61. package/dist/tailwind/prefix-handlers.js +931 -0
  62. package/package.json +17 -2
@@ -0,0 +1,250 @@
1
+ /**
2
+ * @ogxjs/core - Tailwind Parser v2 "Turbo"
3
+ * High-performance Tailwind CSS parser with O(1) lookups
4
+ *
5
+ * @description
6
+ * Complete rewrite of the parser for maximum performance:
7
+ * - O(1) static class lookup via Map
8
+ * - Efficient prefix matching via ordered prefix list
9
+ * - Multi-level caching (class + string level)
10
+ * - Minimal allocations
11
+ *
12
+ * @performance
13
+ * v0.1.x: ~5ms for 100 classes (O(n) if/else chain)
14
+ * v0.2.0: ~0.5ms for 100 classes (O(1) lookups + cache)
15
+ *
16
+ * @version 0.2.0 "Turbo"
17
+ */
18
+ import { classCache, stringCache } from "./class-cache";
19
+ import { getStaticClass, isStaticClass } from "./lookup-tables";
20
+ import { findPrefixHandler, handleArbitraryValue, } from "./prefix-handlers";
21
+ // MAIN PARSER
22
+ /**
23
+ * Parse Tailwind classes to CSS properties
24
+ *
25
+ * @param tw - Tailwind class string or array
26
+ * @param theme - Optional theme config for custom colors
27
+ * @param colorScheme - Optional color scheme for dark: variants
28
+ * @returns CSS properties object
29
+ *
30
+ * @example
31
+ * ```ts
32
+ * parseTailwind("flex bg-blue-500 p-4")
33
+ * // → { display: "flex", backgroundColor: "#3b82f6", padding: 16 }
34
+ *
35
+ * parseTailwind(["flex", "items-center", "gap-4"])
36
+ * // → { display: "flex", alignItems: "center", gap: 16 }
37
+ * ```
38
+ */
39
+ export function parseTailwind(tw, theme, colorScheme) {
40
+ // Normalize input to array of classes (optimized for common cases)
41
+ const classes = normalizeClasses(tw);
42
+ // Early return for empty input
43
+ if (classes.length === 0) {
44
+ return { display: "flex" };
45
+ }
46
+ // Build cache key (only if no custom theme)
47
+ // Use colorScheme inline to avoid extra string allocation
48
+ const cacheKey = theme
49
+ ? null
50
+ : colorScheme === "dark"
51
+ ? `${classes.join(" ")}|dark`
52
+ : `${classes.join(" ")}|light`;
53
+ // Check string-level cache first
54
+ if (cacheKey) {
55
+ const cached = stringCache.get(cacheKey);
56
+ if (cached) {
57
+ // Return a copy to allow mutations by caller
58
+ return { ...cached };
59
+ }
60
+ }
61
+ // Initialize style object with flex default
62
+ const style = { display: "flex" };
63
+ const gradient = {};
64
+ const isDark = colorScheme === "dark";
65
+ const hasTheme = theme !== undefined;
66
+ // Parse context for handlers (reused object)
67
+ const ctx = {
68
+ style,
69
+ gradient,
70
+ theme,
71
+ colorScheme,
72
+ };
73
+ // Process each class with optimized loop
74
+ const len = classes.length;
75
+ for (let i = 0; i < len; i++) {
76
+ parseClass(classes[i], ctx, isDark, hasTheme);
77
+ }
78
+ // Apply gradient if direction is set
79
+ if (gradient.direction) {
80
+ applyGradient(style, gradient);
81
+ }
82
+ // Cache the result (store copy since we return original)
83
+ if (cacheKey) {
84
+ stringCache.set(cacheKey, { ...style });
85
+ }
86
+ return style;
87
+ }
88
+ // CLASS PARSING
89
+ /**
90
+ * Parse a single Tailwind class
91
+ * @performance Inline checks to avoid function call overhead
92
+ */
93
+ function parseClass(cls, ctx, isDark, hasTheme) {
94
+ // Handle dark: variant inline
95
+ if (cls.charCodeAt(0) === 100 && cls.startsWith("dark:")) {
96
+ // 'd' = 100
97
+ if (!isDark)
98
+ return;
99
+ cls = cls.slice(5);
100
+ }
101
+ // Check class-level cache (only for non-theme classes)
102
+ if (!hasTheme) {
103
+ const cached = classCache.get(cls);
104
+ if (cached) {
105
+ Object.assign(ctx.style, cached);
106
+ return;
107
+ }
108
+ }
109
+ // Try static lookup first (O(1))
110
+ if (isStaticClass(cls)) {
111
+ const props = getStaticClass(cls);
112
+ Object.assign(ctx.style, props);
113
+ // Cache for future use (static classes are immutable)
114
+ if (!hasTheme) {
115
+ classCache.set(cls, props);
116
+ }
117
+ return;
118
+ }
119
+ // Check for arbitrary values: p-[32px], bg-[#ff0000]
120
+ // Optimized: check for '[' before regex
121
+ if (cls.includes("[")) {
122
+ const bracketIdx = cls.indexOf("[");
123
+ if (bracketIdx > 1 && cls.charCodeAt(bracketIdx - 1) === 45) {
124
+ // '-' = 45
125
+ const prefix = cls.slice(0, bracketIdx - 1);
126
+ const value = cls.slice(bracketIdx + 1, -1);
127
+ handleArbitraryValue(prefix, value, ctx);
128
+ return;
129
+ }
130
+ }
131
+ // Try prefix handlers
132
+ const prefixMatch = findPrefixHandler(cls);
133
+ if (prefixMatch) {
134
+ const [handler, value] = prefixMatch;
135
+ // If no theme, we want to cache the result
136
+ // Create temporary style object to capture just this class's effect
137
+ if (!hasTheme) {
138
+ const tempStyle = {};
139
+ const tempCtx = {
140
+ style: tempStyle,
141
+ gradient: ctx.gradient,
142
+ theme: ctx.theme,
143
+ colorScheme: ctx.colorScheme,
144
+ };
145
+ handler(value, tempCtx);
146
+ // Apply to main style and cache
147
+ Object.assign(ctx.style, tempStyle);
148
+ // Only cache if something was set
149
+ const keys = Object.keys(tempStyle);
150
+ if (keys.length > 0) {
151
+ classCache.set(cls, tempStyle);
152
+ }
153
+ }
154
+ else {
155
+ // With theme, apply directly (no caching)
156
+ handler(value, ctx);
157
+ }
158
+ return;
159
+ }
160
+ // Unknown class - ignore silently in production
161
+ if (process.env.NODE_ENV !== "production") {
162
+ // Only warn for classes that look like Tailwind (have a hyphen)
163
+ if (cls.includes("-")) {
164
+ console.debug?.(`OGX: Unknown Tailwind class "${cls}"`);
165
+ }
166
+ }
167
+ }
168
+ // HELPERS
169
+ /**
170
+ * Normalize input to flat array of class strings
171
+ * @performance Optimized for common cases with minimal allocations
172
+ */
173
+ function normalizeClasses(tw) {
174
+ // Fast path: single string (most common case)
175
+ if (typeof tw === "string") {
176
+ // Check if it contains spaces
177
+ if (!tw.includes(" ")) {
178
+ return tw.length > 0 ? [tw] : [];
179
+ }
180
+ // Split on whitespace
181
+ const result = [];
182
+ let start = 0;
183
+ let inWhitespace = true;
184
+ for (let i = 0; i <= tw.length; i++) {
185
+ const isSpace = i === tw.length || tw.charCodeAt(i) <= 32;
186
+ if (isSpace && !inWhitespace) {
187
+ result.push(tw.slice(start, i));
188
+ inWhitespace = true;
189
+ }
190
+ else if (!isSpace && inWhitespace) {
191
+ start = i;
192
+ inWhitespace = false;
193
+ }
194
+ }
195
+ return result;
196
+ }
197
+ // Array path: flatten and split
198
+ const result = [];
199
+ const len = tw.length;
200
+ for (let i = 0; i < len; i++) {
201
+ const t = tw[i];
202
+ if (typeof t === "string" && t.length > 0) {
203
+ if (!t.includes(" ")) {
204
+ result.push(t);
205
+ }
206
+ else {
207
+ // Split this string and add each part
208
+ const parts = t.split(/\s+/);
209
+ for (let j = 0; j < parts.length; j++) {
210
+ if (parts[j].length > 0) {
211
+ result.push(parts[j]);
212
+ }
213
+ }
214
+ }
215
+ }
216
+ }
217
+ return result;
218
+ }
219
+ /**
220
+ * Apply gradient to style object
221
+ */
222
+ function applyGradient(style, gradient) {
223
+ const from = gradient.from || "transparent";
224
+ const to = gradient.to || "transparent";
225
+ if (gradient.via) {
226
+ style.backgroundImage = `linear-gradient(${gradient.direction}, ${from}, ${gradient.via}, ${to})`;
227
+ }
228
+ else {
229
+ style.backgroundImage = `linear-gradient(${gradient.direction}, ${from}, ${to})`;
230
+ }
231
+ }
232
+ // BATCH PARSING
233
+ /**
234
+ * Parse multiple class strings in batch
235
+ * More efficient than calling parseTailwind multiple times
236
+ *
237
+ * @param items - Array of class strings
238
+ * @param theme - Optional theme config
239
+ * @param colorScheme - Optional color scheme
240
+ * @returns Array of CSS properties in same order
241
+ */
242
+ export function parseTailwindBatch(items, theme, colorScheme) {
243
+ return items.map((tw) => parseTailwind(tw, theme, colorScheme));
244
+ }
245
+ // RE-EXPORTS
246
+ export { clearAllCaches, getCacheStats } from "./class-cache";
247
+ export { colors } from "./colors";
248
+ export { getStaticClass, isStaticClass, STATIC_CLASSES } from "./lookup-tables";
249
+ export { ORDERED_PREFIXES, PREFIX_HANDLERS, parseSpacingValue, resolveColorValue, } from "./prefix-handlers";
250
+ export { borderRadius, fontSize, fontWeight, opacity, spacing } from "./scales";
@@ -8,6 +8,7 @@ export interface GradientState {
8
8
  }
9
9
  /**
10
10
  * Main Tailwind parser function
11
+ * @deprecated Use parseTailwind from parser-v2 instead (exported from tailwind/index)
11
12
  */
12
13
  export declare function parseTailwind(tw: string | string[], theme?: ThemeConfig, colorScheme?: "light" | "dark"): CSSProperties;
13
14
  export { colors } from "./colors";
@@ -1 +1 @@
1
- {"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../src/tailwind/parser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AAC5C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAY5C,MAAM,WAAW,aAAa;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAID;;GAEG;AACH,wBAAgB,aAAa,CAC5B,EAAE,EAAE,MAAM,GAAG,MAAM,EAAE,EACrB,KAAK,CAAC,EAAE,WAAW,EACnB,WAAW,CAAC,EAAE,OAAO,GAAG,MAAM,GAC5B,aAAa,CAwCf;AAyhCD,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC"}
1
+ {"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../src/tailwind/parser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AAC5C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAY5C,MAAM,WAAW,aAAa;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAID;;;GAGG;AACH,wBAAgB,aAAa,CAC5B,EAAE,EAAE,MAAM,GAAG,MAAM,EAAE,EACrB,KAAK,CAAC,EAAE,WAAW,EACnB,WAAW,CAAC,EAAE,OAAO,GAAG,MAAM,GAC5B,aAAa,CAwCf;AAyhCD,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC"}
@@ -4,6 +4,7 @@ import { borderRadius, boxShadow, fontSize, fontWeight, opacity, spacing, } from
4
4
  const parserCache = new Map();
5
5
  /**
6
6
  * Main Tailwind parser function
7
+ * @deprecated Use parseTailwind from parser-v2 instead (exported from tailwind/index)
7
8
  */
8
9
  export function parseTailwind(tw, theme, colorScheme) {
9
10
  const style = { display: "flex" };
@@ -0,0 +1,68 @@
1
+ /**
2
+ * @ogxjs/core - Tailwind Prefix Handlers
3
+ * Modular handlers for dynamic Tailwind classes with prefixes
4
+ *
5
+ * @description
6
+ * Instead of a giant if/else chain, we use a Map of prefix -> handler.
7
+ * This allows O(1) prefix lookup + targeted parsing.
8
+ *
9
+ * @performance
10
+ * - Before: O(n) linear scan through all if/else conditions
11
+ * - After: O(1) prefix lookup + O(1) value parsing
12
+ *
13
+ * @version 0.2.0 "Turbo"
14
+ */
15
+ import type { CSSProperties } from "../css";
16
+ import type { ThemeConfig } from "../types";
17
+ export interface GradientState {
18
+ from?: string;
19
+ via?: string;
20
+ to?: string;
21
+ direction?: string;
22
+ }
23
+ export interface ParseContext {
24
+ style: CSSProperties;
25
+ gradient: GradientState;
26
+ theme?: ThemeConfig;
27
+ colorScheme?: "light" | "dark";
28
+ }
29
+ /**
30
+ * Handler function type for prefix-based classes
31
+ * @param value - The value after the prefix (e.g., "4" from "p-4")
32
+ * @param ctx - Parse context with style object and gradient state
33
+ */
34
+ export type PrefixHandler = (value: string, ctx: ParseContext) => void;
35
+ /**
36
+ * Parse a spacing value from Tailwind scale or fraction
37
+ */
38
+ export declare function parseSpacingValue(value: string): number | string | undefined;
39
+ /**
40
+ * Resolve a color value from theme or palette with opacity support
41
+ */
42
+ export declare function resolveColorValue(name: string, theme?: ThemeConfig): string | undefined;
43
+ /**
44
+ * Parse arbitrary value from brackets [value]
45
+ */
46
+ export declare function parseArbitraryValue(value: string): string | number;
47
+ /**
48
+ * Map of prefix -> handler function
49
+ * Order matters for prefixes that share common starts (e.g., "px-" before "p-")
50
+ */
51
+ export declare const PREFIX_HANDLERS: ReadonlyMap<string, PrefixHandler>;
52
+ /**
53
+ * Handle arbitrary values like p-[32px], bg-[#ff0000]
54
+ */
55
+ export declare function handleArbitraryValue(prefix: string, value: string, ctx: ParseContext): void;
56
+ /**
57
+ * Ordered list of prefixes for matching (longest first to avoid false matches)
58
+ */
59
+ export declare const ORDERED_PREFIXES: readonly string[];
60
+ /**
61
+ * Find matching prefix handler for a class
62
+ * @performance O(k) where k = prefixes starting with same char (usually 2-4)
63
+ *
64
+ * @param cls - Tailwind class name
65
+ * @returns [handler, value] tuple or undefined
66
+ */
67
+ export declare function findPrefixHandler(cls: string): [PrefixHandler, string] | undefined;
68
+ //# sourceMappingURL=prefix-handlers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prefix-handlers.d.ts","sourceRoot":"","sources":["../../src/tailwind/prefix-handlers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AAC5C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAO5C,MAAM,WAAW,aAAa;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC5B,KAAK,EAAE,aAAa,CAAC;IACrB,QAAQ,EAAE,aAAa,CAAC;IACxB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,WAAW,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;CAC/B;AAED;;;;GAIG;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,YAAY,KAAK,IAAI,CAAC;AAIvE;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,CAuB5E;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAChC,IAAI,EAAE,MAAM,EACZ,KAAK,CAAC,EAAE,WAAW,GACjB,MAAM,GAAG,SAAS,CA6BpB;AASD;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CA6BlE;AAID;;;GAGG;AACH,eAAO,MAAM,eAAe,EAAE,WAAW,CAAC,MAAM,EAAE,aAAa,CA6e7D,CAAC;AA2EH;;GAEG;AACH,wBAAgB,oBAAoB,CACnC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,YAAY,GACf,IAAI,CAkKN;AAID;;GAEG;AACH,eAAO,MAAM,gBAAgB,EAAE,SAAS,MAAM,EAiD7C,CAAC;AA0BF;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAChC,GAAG,EAAE,MAAM,GACT,CAAC,aAAa,EAAE,MAAM,CAAC,GAAG,SAAS,CAoBrC"}