cataract 0.1.0

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 (90) hide show
  1. checksums.yaml +7 -0
  2. data/.clang-tidy +30 -0
  3. data/.github/workflows/ci-macos.yml +12 -0
  4. data/.github/workflows/ci.yml +77 -0
  5. data/.github/workflows/test.yml +76 -0
  6. data/.gitignore +45 -0
  7. data/.overcommit.yml +38 -0
  8. data/.rubocop.yml +83 -0
  9. data/BENCHMARKS.md +201 -0
  10. data/CHANGELOG.md +1 -0
  11. data/Gemfile +27 -0
  12. data/LICENSE +21 -0
  13. data/RAGEL_MIGRATION.md +60 -0
  14. data/README.md +292 -0
  15. data/Rakefile +209 -0
  16. data/benchmarks/benchmark_harness.rb +193 -0
  17. data/benchmarks/benchmark_merging.rb +121 -0
  18. data/benchmarks/benchmark_optimization_comparison.rb +168 -0
  19. data/benchmarks/benchmark_parsing.rb +153 -0
  20. data/benchmarks/benchmark_ragel_removal.rb +56 -0
  21. data/benchmarks/benchmark_runner.rb +70 -0
  22. data/benchmarks/benchmark_serialization.rb +180 -0
  23. data/benchmarks/benchmark_shorthand.rb +109 -0
  24. data/benchmarks/benchmark_shorthand_expansion.rb +176 -0
  25. data/benchmarks/benchmark_specificity.rb +124 -0
  26. data/benchmarks/benchmark_string_allocation.rb +151 -0
  27. data/benchmarks/benchmark_stylesheet_to_s.rb +62 -0
  28. data/benchmarks/benchmark_to_s_cached.rb +55 -0
  29. data/benchmarks/benchmark_value_splitter.rb +54 -0
  30. data/benchmarks/benchmark_yjit.rb +158 -0
  31. data/benchmarks/benchmark_yjit_workers.rb +61 -0
  32. data/benchmarks/profile_to_s.rb +23 -0
  33. data/benchmarks/speedup_calculator.rb +83 -0
  34. data/benchmarks/system_metadata.rb +81 -0
  35. data/benchmarks/templates/benchmarks.md.erb +221 -0
  36. data/benchmarks/yjit_tests.rb +141 -0
  37. data/cataract.gemspec +34 -0
  38. data/cliff.toml +92 -0
  39. data/examples/color_conversion_visual_test/color_conversion_test.html +3603 -0
  40. data/examples/color_conversion_visual_test/generate.rb +202 -0
  41. data/examples/color_conversion_visual_test/template.html.erb +259 -0
  42. data/examples/css_analyzer/analyzer.rb +164 -0
  43. data/examples/css_analyzer/analyzers/base.rb +33 -0
  44. data/examples/css_analyzer/analyzers/colors.rb +133 -0
  45. data/examples/css_analyzer/analyzers/important.rb +88 -0
  46. data/examples/css_analyzer/analyzers/properties.rb +61 -0
  47. data/examples/css_analyzer/analyzers/specificity.rb +68 -0
  48. data/examples/css_analyzer/templates/report.html.erb +575 -0
  49. data/examples/css_analyzer.rb +69 -0
  50. data/examples/github_analysis.html +5343 -0
  51. data/ext/cataract/cataract.c +1086 -0
  52. data/ext/cataract/cataract.h +174 -0
  53. data/ext/cataract/css_parser.c +1435 -0
  54. data/ext/cataract/extconf.rb +48 -0
  55. data/ext/cataract/import_scanner.c +174 -0
  56. data/ext/cataract/merge.c +973 -0
  57. data/ext/cataract/shorthand_expander.c +902 -0
  58. data/ext/cataract/specificity.c +213 -0
  59. data/ext/cataract/value_splitter.c +116 -0
  60. data/ext/cataract_color/cataract_color.c +16 -0
  61. data/ext/cataract_color/color_conversion.c +1687 -0
  62. data/ext/cataract_color/color_conversion.h +136 -0
  63. data/ext/cataract_color/color_conversion_lab.c +571 -0
  64. data/ext/cataract_color/color_conversion_named.c +259 -0
  65. data/ext/cataract_color/color_conversion_oklab.c +547 -0
  66. data/ext/cataract_color/extconf.rb +23 -0
  67. data/ext/cataract_old/cataract.c +393 -0
  68. data/ext/cataract_old/cataract.h +250 -0
  69. data/ext/cataract_old/css_parser.c +933 -0
  70. data/ext/cataract_old/extconf.rb +67 -0
  71. data/ext/cataract_old/import_scanner.c +174 -0
  72. data/ext/cataract_old/merge.c +776 -0
  73. data/ext/cataract_old/shorthand_expander.c +902 -0
  74. data/ext/cataract_old/specificity.c +213 -0
  75. data/ext/cataract_old/stylesheet.c +290 -0
  76. data/ext/cataract_old/value_splitter.c +116 -0
  77. data/lib/cataract/at_rule.rb +97 -0
  78. data/lib/cataract/color_conversion.rb +18 -0
  79. data/lib/cataract/declarations.rb +332 -0
  80. data/lib/cataract/import_resolver.rb +210 -0
  81. data/lib/cataract/rule.rb +131 -0
  82. data/lib/cataract/stylesheet.rb +716 -0
  83. data/lib/cataract/stylesheet_scope.rb +257 -0
  84. data/lib/cataract/version.rb +5 -0
  85. data/lib/cataract.rb +107 -0
  86. data/lib/tasks/gem.rake +158 -0
  87. data/scripts/fuzzer/run.rb +828 -0
  88. data/scripts/fuzzer/worker.rb +99 -0
  89. data/scripts/generate_benchmarks_md.rb +155 -0
  90. metadata +135 -0
@@ -0,0 +1,136 @@
1
+ // color_conversion.h - Shared types and macros for CSS color conversion
2
+ #ifndef COLOR_CONVERSION_H
3
+ #define COLOR_CONVERSION_H
4
+
5
+ #include "cataract.h"
6
+
7
+ // Intermediate representation for colors
8
+ // All colors are stored as sRGB (0-255) for compatibility.
9
+ // Optionally, high-precision linear RGB can be preserved to avoid quantization loss.
10
+ struct color_ir {
11
+ // sRGB representation (0-255) - always populated
12
+ int red; // 0-255
13
+ int green; // 0-255
14
+ int blue; // 0-255
15
+ double alpha; // 0.0-1.0, or -1.0 for "no alpha"
16
+
17
+ // Optional high-precision linear RGB (0.0-1.0)
18
+ // Set has_linear_rgb = 1 if linear_* fields contain valid data
19
+ // Formatters that support high precision (e.g., oklab) should check this flag
20
+ // and prefer linear RGB over sRGB to avoid quantization errors
21
+ int has_linear_rgb;
22
+ double linear_r; // 0.0-1.0 (linear RGB, not gamma-corrected)
23
+ double linear_g; // 0.0-1.0
24
+ double linear_b; // 0.0-1.0
25
+ };
26
+
27
+ // Initialize color_ir struct with default values
28
+ #define INIT_COLOR_IR(color) do { \
29
+ (color).red = 0; \
30
+ (color).green = 0; \
31
+ (color).blue = 0; \
32
+ (color).alpha = -1.0; \
33
+ (color).has_linear_rgb = 0; \
34
+ (color).linear_r = 0.0; \
35
+ (color).linear_g = 0.0; \
36
+ (color).linear_b = 0.0; \
37
+ } while(0)
38
+
39
+ // Macros for parsing color values
40
+ #define SKIP_WHITESPACE(p) while (*(p) == ' ') (p)++
41
+ #define SKIP_SEPARATOR(p) while (*(p) == ',' || *(p) == ' ') (p)++
42
+ #define PARSE_INT(p, var) do { \
43
+ int is_negative = 0; \
44
+ if (*(p) == '-') { \
45
+ is_negative = 1; \
46
+ (p)++; \
47
+ } \
48
+ (var) = 0; \
49
+ while (*(p) >= '0' && *(p) <= '9') { \
50
+ (var) = (var) * 10 + (*(p) - '0'); \
51
+ (p)++; \
52
+ } \
53
+ if (is_negative) (var) = -(var); \
54
+ } while(0)
55
+
56
+ // Find matching closing parenthesis
57
+ // Sets 'end' pointer to character after closing paren
58
+ #define FIND_CLOSING_PAREN(start, end) do { \
59
+ int paren_count = 0; \
60
+ (end) = (start); \
61
+ while (*(end)) { \
62
+ if (*(end) == '(') paren_count++; \
63
+ if (*(end) == ')') { \
64
+ paren_count--; \
65
+ if (paren_count == 0) { \
66
+ (end)++; \
67
+ break; \
68
+ } \
69
+ } \
70
+ (end)++; \
71
+ } \
72
+ } while(0)
73
+
74
+ // Detect color format at current position
75
+ #define STARTS_WITH_RGB(p, remaining) \
76
+ ((remaining) >= 4 && (p)[0] == 'r' && (p)[1] == 'g' && (p)[2] == 'b' && ((p)[3] == '(' || (p)[3] == 'a'))
77
+
78
+ #define STARTS_WITH_HSL(p, remaining) \
79
+ ((remaining) >= 4 && (p)[0] == 'h' && (p)[1] == 's' && (p)[2] == 'l' && ((p)[3] == '(' || (p)[3] == 'a'))
80
+
81
+ #define STARTS_WITH_HWB(p, remaining) \
82
+ ((remaining) >= 4 && (p)[0] == 'h' && (p)[1] == 'w' && (p)[2] == 'b' && ((p)[3] == '(' || (p)[3] == 'a'))
83
+
84
+ #define STARTS_WITH_OKLAB(p, remaining) \
85
+ ((remaining) >= 6 && (p)[0] == 'o' && (p)[1] == 'k' && (p)[2] == 'l' && \
86
+ (p)[3] == 'a' && (p)[4] == 'b' && (p)[5] == '(')
87
+
88
+ #define STARTS_WITH_OKLCH(p, remaining) \
89
+ ((remaining) >= 6 && (p)[0] == 'o' && (p)[1] == 'k' && (p)[2] == 'l' && \
90
+ (p)[3] == 'c' && (p)[4] == 'h' && (p)[5] == '(')
91
+
92
+ #define STARTS_WITH_LAB(p, remaining) \
93
+ ((remaining) >= 4 && (p)[0] == 'l' && (p)[1] == 'a' && (p)[2] == 'b' && (p)[3] == '(')
94
+
95
+ #define STARTS_WITH_LCH(p, remaining) \
96
+ ((remaining) >= 4 && (p)[0] == 'l' && (p)[1] == 'c' && (p)[2] == 'h' && (p)[3] == '(')
97
+
98
+ // Macros for formatting color values
99
+ #define FORMAT_RGB_MODERN(buf, red, green, blue) \
100
+ snprintf(buf, sizeof(buf), "rgb(%d %d %d)", red, green, blue)
101
+ #define FORMAT_RGB_LEGACY(buf, red, green, blue) \
102
+ snprintf(buf, sizeof(buf), "rgb(%d, %d, %d)", red, green, blue)
103
+ #define FORMAT_RGBA_MODERN(buf, red, green, blue, alpha) \
104
+ snprintf(buf, sizeof(buf), "rgb(%d %d %d / %.10g)", red, green, blue, alpha)
105
+ #define FORMAT_RGBA_LEGACY(buf, red, green, blue, alpha) \
106
+ snprintf(buf, sizeof(buf), "rgba(%d, %d, %d, %.10g)", red, green, blue, alpha)
107
+ #define FORMAT_HEX(buf, red, green, blue) \
108
+ snprintf(buf, sizeof(buf), "#%02x%02x%02x", red, green, blue)
109
+ #define FORMAT_HEX_ALPHA(buf, red, green, blue, alpha_int) \
110
+ snprintf(buf, sizeof(buf), "#%02x%02x%02x%02x", red, green, blue, alpha_int)
111
+ #define FORMAT_HSL(buf, hue, sat, light) \
112
+ snprintf(buf, sizeof(buf), "hsl(%d, %d%%, %d%%)", hue, sat, light)
113
+ #define FORMAT_HSLA(buf, hue, sat, light, alpha) \
114
+ snprintf(buf, sizeof(buf), "hsl(%d, %d%%, %d%%, %.10g)", hue, sat, light, alpha)
115
+ #define FORMAT_HWB(buf, hue, white, black) \
116
+ snprintf(buf, sizeof(buf), "hwb(%d %d%% %d%%)", hue, white, black)
117
+ #define FORMAT_HWBA(buf, hue, white, black, alpha) \
118
+ snprintf(buf, sizeof(buf), "hwb(%d %d%% %d%% / %.10g)", hue, white, black, alpha)
119
+ #define FORMAT_OKLAB(buf, l, a, b) \
120
+ snprintf(buf, sizeof(buf), "oklab(%.4f %.4f %.4f)", l, a, b)
121
+ #define FORMAT_OKLAB_ALPHA(buf, l, a, b, alpha) \
122
+ snprintf(buf, sizeof(buf), "oklab(%.4f %.4f %.4f / %.10g)", l, a, b, alpha)
123
+ #define FORMAT_RGB_PERCENT(buf, r_pct, g_pct, b_pct) \
124
+ snprintf(buf, sizeof(buf), "rgb(%.3f%% %.3f%% %.3f%%)", r_pct, g_pct, b_pct)
125
+ #define FORMAT_RGB_PERCENT_ALPHA(buf, r_pct, g_pct, b_pct, alpha) \
126
+ snprintf(buf, sizeof(buf), "rgb(%.3f%% %.3f%% %.3f%% / %.10g)", r_pct, g_pct, b_pct, alpha)
127
+ #define FORMAT_LAB(buf, l, a, b) \
128
+ snprintf(buf, sizeof(buf), "lab(%.4f%% %.4f %.4f)", l, a, b)
129
+ #define FORMAT_LAB_ALPHA(buf, l, a, b, alpha) \
130
+ snprintf(buf, sizeof(buf), "lab(%.4f%% %.4f %.4f / %.10g)", l, a, b, alpha)
131
+ #define FORMAT_LCH(buf, l, c, h) \
132
+ snprintf(buf, sizeof(buf), "lch(%.4f%% %.4f %.3f)", l, c, h)
133
+ #define FORMAT_LCH_ALPHA(buf, l, c, h, alpha) \
134
+ snprintf(buf, sizeof(buf), "lch(%.4f%% %.4f %.3f / %.10g)", l, c, h, alpha)
135
+
136
+ #endif // COLOR_CONVERSION_H