cataract 0.2.5 → 0.3.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.
- checksums.yaml +4 -4
- data/.github/workflows/test.yml +6 -6
- data/.gitignore +17 -3
- data/CHANGELOG.md +19 -1
- data/Gemfile +2 -2
- data/examples/css_analyzer/analyzer.rb +9 -3
- data/examples/css_analyzer/analyzers/base.rb +1 -1
- data/ext/cataract/cataract.c +247 -454
- data/ext/cataract/cataract.h +126 -15
- data/ext/cataract/css_parser.c +782 -788
- data/ext/cataract/extconf.rb +1 -2
- data/ext/cataract/flatten.c +279 -991
- data/ext/cataract/shorthand_expander.c +80 -102
- data/ext/cataract_color/color_conversion.c +1 -1
- data/lib/cataract/declarations.rb +13 -7
- data/lib/cataract/import_resolver.rb +36 -16
- data/lib/cataract/pure/byte_constants.rb +0 -1
- data/lib/cataract/pure/flatten.rb +143 -145
- data/lib/cataract/pure/parser.rb +495 -422
- data/lib/cataract/pure/serializer.rb +109 -104
- data/lib/cataract/pure/specificity.rb +112 -156
- data/lib/cataract/pure.rb +0 -7
- data/lib/cataract/stylesheet.rb +460 -412
- data/lib/cataract/version.rb +1 -1
- metadata +2 -13
- data/ext/cataract/import_scanner.c +0 -174
- data/ext/cataract_old/cataract.c +0 -393
- data/ext/cataract_old/cataract.h +0 -250
- data/ext/cataract_old/css_parser.c +0 -933
- data/ext/cataract_old/extconf.rb +0 -67
- data/ext/cataract_old/import_scanner.c +0 -174
- data/ext/cataract_old/merge.c +0 -776
- data/ext/cataract_old/shorthand_expander.c +0 -902
- data/ext/cataract_old/specificity.c +0 -213
- data/ext/cataract_old/stylesheet.c +0 -290
- data/ext/cataract_old/value_splitter.c +0 -116
data/ext/cataract_old/cataract.h
DELETED
|
@@ -1,250 +0,0 @@
|
|
|
1
|
-
#ifndef CATARACT_H
|
|
2
|
-
#define CATARACT_H
|
|
3
|
-
|
|
4
|
-
#include <ruby.h>
|
|
5
|
-
#include <ruby/encoding.h>
|
|
6
|
-
|
|
7
|
-
// ============================================================================
|
|
8
|
-
// Global struct class references (defined in cataract.c, declared extern here)
|
|
9
|
-
// ============================================================================
|
|
10
|
-
|
|
11
|
-
extern VALUE cDeclaration;
|
|
12
|
-
extern VALUE cRule;
|
|
13
|
-
|
|
14
|
-
// Error class references
|
|
15
|
-
extern VALUE eCataractError;
|
|
16
|
-
extern VALUE eParseError;
|
|
17
|
-
extern VALUE eDepthError;
|
|
18
|
-
extern VALUE eSizeError;
|
|
19
|
-
|
|
20
|
-
// ============================================================================
|
|
21
|
-
// Struct field indices
|
|
22
|
-
// ============================================================================
|
|
23
|
-
|
|
24
|
-
// Rule struct field indices (selector, declarations, specificity)
|
|
25
|
-
#define RULE_SELECTOR 0
|
|
26
|
-
#define RULE_DECLARATIONS 1
|
|
27
|
-
#define RULE_SPECIFICITY 2
|
|
28
|
-
|
|
29
|
-
// Declaration struct field indices (property, value, important)
|
|
30
|
-
#define DECL_PROPERTY 0
|
|
31
|
-
#define DECL_VALUE 1
|
|
32
|
-
#define DECL_IMPORTANT 2
|
|
33
|
-
|
|
34
|
-
// ============================================================================
|
|
35
|
-
// Macros
|
|
36
|
-
// ============================================================================
|
|
37
|
-
|
|
38
|
-
// Whitespace detection
|
|
39
|
-
#define IS_WHITESPACE(c) ((c) == ' ' || (c) == '\t' || (c) == '\n' || (c) == '\r')
|
|
40
|
-
|
|
41
|
-
// US-ASCII string literal creation (compile-time length for efficiency)
|
|
42
|
-
// Use this for string literals like "margin-top" to avoid strlen() at runtime
|
|
43
|
-
// Example: USASCII_STR("margin-top") expands to rb_usascii_str_new("margin-top", 10)
|
|
44
|
-
#define USASCII_STR(str) rb_usascii_str_new((str), sizeof(str) - 1)
|
|
45
|
-
|
|
46
|
-
// UTF-8 string literal creation (compile-time length for efficiency)
|
|
47
|
-
// Use this for string literals that may be concatenated with UTF-8 content
|
|
48
|
-
// Example: UTF8_STR("@") expands to rb_utf8_str_new("@", 1)
|
|
49
|
-
#define UTF8_STR(str) rb_utf8_str_new((str), sizeof(str) - 1)
|
|
50
|
-
|
|
51
|
-
// Debug output (disabled by default)
|
|
52
|
-
// #define CATARACT_DEBUG 1
|
|
53
|
-
|
|
54
|
-
#ifdef CATARACT_DEBUG
|
|
55
|
-
#define DEBUG_PRINTF(...) printf(__VA_ARGS__)
|
|
56
|
-
#else
|
|
57
|
-
#define DEBUG_PRINTF(...) ((void)0)
|
|
58
|
-
#endif
|
|
59
|
-
|
|
60
|
-
// String allocation optimization (enabled by default)
|
|
61
|
-
// Uses rb_str_buf_new for pre-allocation when building selector strings
|
|
62
|
-
//
|
|
63
|
-
// Disable for benchmarking baseline:
|
|
64
|
-
// Development: DISABLE_STR_BUF_OPTIMIZATION=1 rake compile
|
|
65
|
-
// Gem install: gem install cataract -- --disable-str-buf-optimization
|
|
66
|
-
//
|
|
67
|
-
#ifndef DISABLE_STR_BUF_OPTIMIZATION
|
|
68
|
-
#define STR_NEW_WITH_CAPACITY(capacity) rb_str_buf_new(capacity)
|
|
69
|
-
#define STR_NEW_CSTR(str) rb_str_new_cstr(str)
|
|
70
|
-
#else
|
|
71
|
-
#define STR_NEW_WITH_CAPACITY(capacity) rb_str_new_cstr("")
|
|
72
|
-
#define STR_NEW_CSTR(str) rb_str_new_cstr(str)
|
|
73
|
-
#endif
|
|
74
|
-
|
|
75
|
-
// Sanity limits for CSS properties and values
|
|
76
|
-
// These prevent crashes from pathological inputs (fuzzer-found edge cases)
|
|
77
|
-
// Override at compile time if needed: -DMAX_PROPERTY_NAME_LENGTH=512
|
|
78
|
-
#ifndef MAX_PROPERTY_NAME_LENGTH
|
|
79
|
-
#define MAX_PROPERTY_NAME_LENGTH 256 // Reasonable max for property names (e.g., "background-position-x")
|
|
80
|
-
#endif
|
|
81
|
-
|
|
82
|
-
#ifndef MAX_PROPERTY_VALUE_LENGTH
|
|
83
|
-
#define MAX_PROPERTY_VALUE_LENGTH 32768 // 32KB - handles large data URLs and complex values
|
|
84
|
-
#endif
|
|
85
|
-
|
|
86
|
-
#ifndef MAX_AT_RULE_BLOCK_LENGTH
|
|
87
|
-
#define MAX_AT_RULE_BLOCK_LENGTH 1048576 // 1MB - max size for @media, @supports, etc. block content
|
|
88
|
-
#endif
|
|
89
|
-
|
|
90
|
-
#ifndef MAX_PARSE_DEPTH
|
|
91
|
-
#define MAX_PARSE_DEPTH 10 // Max recursion depth for nested @media/@supports blocks
|
|
92
|
-
#endif
|
|
93
|
-
|
|
94
|
-
// ============================================================================
|
|
95
|
-
// Inline helper functions
|
|
96
|
-
// ============================================================================
|
|
97
|
-
|
|
98
|
-
// Trim leading whitespace - modifies start pointer
|
|
99
|
-
static inline void trim_leading(const char **start, const char *end) {
|
|
100
|
-
while (*start < end && IS_WHITESPACE(**start)) {
|
|
101
|
-
(*start)++;
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// Trim trailing whitespace - modifies end pointer
|
|
106
|
-
static inline void trim_trailing(const char *start, const char **end) {
|
|
107
|
-
while (*end > start && IS_WHITESPACE(*(*end - 1))) {
|
|
108
|
-
(*end)--;
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
// Strip whitespace from both ends and return new string
|
|
113
|
-
static inline VALUE strip_string(const char *str, long len) {
|
|
114
|
-
const char *start = str;
|
|
115
|
-
const char *end = str + len;
|
|
116
|
-
trim_leading(&start, end);
|
|
117
|
-
trim_trailing(start, &end);
|
|
118
|
-
return rb_str_new(start, end - start);
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
// Lowercase property name (CSS property names are ASCII-only)
|
|
122
|
-
//
|
|
123
|
-
// Performance: Manual loop unrolling (USE_LOOP_UNROLL) provides ~6.6% speedup
|
|
124
|
-
// on Apple Silicon M1 (tested with bootstrap.css parsing benchmark).
|
|
125
|
-
static inline VALUE lowercase_property(VALUE property_str) {
|
|
126
|
-
Check_Type(property_str, T_STRING);
|
|
127
|
-
|
|
128
|
-
long len = RSTRING_LEN(property_str);
|
|
129
|
-
const char *src = RSTRING_PTR(property_str);
|
|
130
|
-
|
|
131
|
-
// Create new US-ASCII string with same length (CSS property names are ASCII-only)
|
|
132
|
-
VALUE result = rb_str_buf_new(len);
|
|
133
|
-
rb_enc_associate(result, rb_usascii_encoding());
|
|
134
|
-
|
|
135
|
-
#ifndef DISABLE_LOOP_UNROLL
|
|
136
|
-
// Manual loop unrolling: process 4 chars at a time (default, ~6.6% faster on M1)
|
|
137
|
-
// Benefits: Fewer loop iterations, better ILP, fewer rb_str_buf_cat calls
|
|
138
|
-
long i = 0;
|
|
139
|
-
|
|
140
|
-
// Process 4 characters at a time
|
|
141
|
-
for (; i + 3 < len; i += 4) {
|
|
142
|
-
char c0 = src[i];
|
|
143
|
-
char c1 = src[i+1];
|
|
144
|
-
char c2 = src[i+2];
|
|
145
|
-
char c3 = src[i+3];
|
|
146
|
-
|
|
147
|
-
// Lowercase each character
|
|
148
|
-
if (c0 >= 'A' && c0 <= 'Z') c0 += 32;
|
|
149
|
-
if (c1 >= 'A' && c1 <= 'Z') c1 += 32;
|
|
150
|
-
if (c2 >= 'A' && c2 <= 'Z') c2 += 32;
|
|
151
|
-
if (c3 >= 'A' && c3 <= 'Z') c3 += 32;
|
|
152
|
-
|
|
153
|
-
char buf[4] = {c0, c1, c2, c3};
|
|
154
|
-
rb_str_buf_cat(result, buf, 4);
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
// Handle remaining characters (0-3)
|
|
158
|
-
for (; i < len; i++) {
|
|
159
|
-
char c = src[i];
|
|
160
|
-
if (c >= 'A' && c <= 'Z') {
|
|
161
|
-
c += 32;
|
|
162
|
-
}
|
|
163
|
-
rb_str_buf_cat(result, &c, 1);
|
|
164
|
-
}
|
|
165
|
-
#else
|
|
166
|
-
// Unrolling disabled: process one character at a time
|
|
167
|
-
for (long i = 0; i < len; i++) {
|
|
168
|
-
char c = src[i];
|
|
169
|
-
// Lowercase ASCII letters only (CSS properties are ASCII)
|
|
170
|
-
if (c >= 'A' && c <= 'Z') {
|
|
171
|
-
c = c + ('a' - 'A');
|
|
172
|
-
}
|
|
173
|
-
rb_str_buf_cat(result, &c, 1);
|
|
174
|
-
}
|
|
175
|
-
#endif
|
|
176
|
-
|
|
177
|
-
return result;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
// ============================================================================
|
|
181
|
-
// Function declarations (implemented in various .c/.rl files)
|
|
182
|
-
// ============================================================================
|
|
183
|
-
|
|
184
|
-
// Serialization functions (cataract.c)
|
|
185
|
-
// Helper function for internal use (called by stylesheet.c)
|
|
186
|
-
VALUE declarations_array_to_s(VALUE declarations_array);
|
|
187
|
-
|
|
188
|
-
// Stylesheet serialization (stylesheet.c)
|
|
189
|
-
VALUE stylesheet_to_s_c(VALUE self, VALUE rules_array, VALUE charset);
|
|
190
|
-
VALUE stylesheet_to_formatted_s_c(VALUE self, VALUE rules_array, VALUE charset);
|
|
191
|
-
|
|
192
|
-
// Import scanning (import_scanner.c)
|
|
193
|
-
VALUE extract_imports(VALUE self, VALUE css_string);
|
|
194
|
-
|
|
195
|
-
// Merge/cascade functions (merge.c)
|
|
196
|
-
void init_merge_constants(void);
|
|
197
|
-
VALUE cataract_merge(VALUE self, VALUE rules_array);
|
|
198
|
-
VALUE cataract_merge_wrapper(VALUE self, VALUE input);
|
|
199
|
-
|
|
200
|
-
// Shorthand expansion (shorthand_expander.rl)
|
|
201
|
-
VALUE cataract_split_value(VALUE self, VALUE value);
|
|
202
|
-
VALUE cataract_expand_margin(VALUE self, VALUE value);
|
|
203
|
-
VALUE cataract_expand_padding(VALUE self, VALUE value);
|
|
204
|
-
VALUE cataract_expand_border_color(VALUE self, VALUE value);
|
|
205
|
-
VALUE cataract_expand_border_style(VALUE self, VALUE value);
|
|
206
|
-
VALUE cataract_expand_border_width(VALUE self, VALUE value);
|
|
207
|
-
VALUE cataract_expand_border(VALUE self, VALUE value);
|
|
208
|
-
VALUE cataract_expand_border_side(VALUE self, VALUE side, VALUE value);
|
|
209
|
-
VALUE cataract_expand_font(VALUE self, VALUE value);
|
|
210
|
-
VALUE cataract_expand_list_style(VALUE self, VALUE value);
|
|
211
|
-
VALUE cataract_expand_background(VALUE self, VALUE value);
|
|
212
|
-
|
|
213
|
-
// Shorthand creation (shorthand_expander.rl)
|
|
214
|
-
VALUE cataract_create_margin_shorthand(VALUE self, VALUE properties);
|
|
215
|
-
VALUE cataract_create_padding_shorthand(VALUE self, VALUE properties);
|
|
216
|
-
VALUE cataract_create_border_width_shorthand(VALUE self, VALUE properties);
|
|
217
|
-
VALUE cataract_create_border_style_shorthand(VALUE self, VALUE properties);
|
|
218
|
-
VALUE cataract_create_border_color_shorthand(VALUE self, VALUE properties);
|
|
219
|
-
VALUE cataract_create_border_shorthand(VALUE self, VALUE properties);
|
|
220
|
-
VALUE cataract_create_background_shorthand(VALUE self, VALUE properties);
|
|
221
|
-
VALUE cataract_create_font_shorthand(VALUE self, VALUE properties);
|
|
222
|
-
VALUE cataract_create_list_style_shorthand(VALUE self, VALUE properties);
|
|
223
|
-
|
|
224
|
-
// CSS parser implementation (css_parser.c)
|
|
225
|
-
VALUE parse_css_impl(VALUE css_string, int depth, VALUE parent_media_query);
|
|
226
|
-
|
|
227
|
-
// CSS parsing helper functions (css_parser.c)
|
|
228
|
-
VALUE parse_media_query(const char *query_str, long query_len);
|
|
229
|
-
VALUE parse_declarations_string(const char *start, const char *end);
|
|
230
|
-
void capture_declarations_fn(
|
|
231
|
-
const char **decl_start_ptr,
|
|
232
|
-
const char *p,
|
|
233
|
-
VALUE *current_declarations,
|
|
234
|
-
const char *css_string_base
|
|
235
|
-
);
|
|
236
|
-
void finish_rule_fn(
|
|
237
|
-
int inside_at_rule_block,
|
|
238
|
-
VALUE *current_selectors,
|
|
239
|
-
VALUE *current_declarations,
|
|
240
|
-
VALUE *current_media_types,
|
|
241
|
-
VALUE rules_array,
|
|
242
|
-
const char **mark_ptr
|
|
243
|
-
);
|
|
244
|
-
|
|
245
|
-
// Specificity calculator (specificity.c)
|
|
246
|
-
VALUE calculate_specificity(VALUE self, VALUE selector_string);
|
|
247
|
-
|
|
248
|
-
// NOTE: Color conversion moved to separate extension (ext/cataract_color/)
|
|
249
|
-
|
|
250
|
-
#endif // CATARACT_H
|