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/cataract.h
CHANGED
|
@@ -51,12 +51,16 @@ extern VALUE eParseError;
|
|
|
51
51
|
#define DECL_VALUE 1
|
|
52
52
|
#define DECL_IMPORTANT 2
|
|
53
53
|
|
|
54
|
-
// AtRule struct field indices (id, selector, content, specificity)
|
|
55
|
-
// Matches Rule interface for duck-typing
|
|
54
|
+
// AtRule struct field indices (id, selector, content, specificity, media_query_id)
|
|
55
|
+
// Matches Rule interface for duck-typing, but AtRule has fewer members - its
|
|
56
|
+
// indices do NOT line up with Rule's past AT_RULE_SPECIFICITY (e.g. index 4
|
|
57
|
+
// is media_query_id here but parent_rule_id on Rule), so never read a field
|
|
58
|
+
// off an AtRule using a RULE_* index beyond AT_RULE_SPECIFICITY.
|
|
56
59
|
#define AT_RULE_ID 0
|
|
57
60
|
#define AT_RULE_SELECTOR 1
|
|
58
61
|
#define AT_RULE_CONTENT 2
|
|
59
62
|
#define AT_RULE_SPECIFICITY 3
|
|
63
|
+
#define AT_RULE_MEDIA_QUERY_ID 4
|
|
60
64
|
|
|
61
65
|
// ============================================================================
|
|
62
66
|
// Macros
|
|
@@ -88,6 +92,116 @@ static inline void trim_trailing(const char *start, const char **end) {
|
|
|
88
92
|
}
|
|
89
93
|
}
|
|
90
94
|
|
|
95
|
+
// Detect and strip a trailing '!important' marker from a value range.
|
|
96
|
+
// Assumes [val_start, *val_end) has already had trailing whitespace trimmed.
|
|
97
|
+
// Shared by every declaration-value scanner (css_parser.c's parse_declarations
|
|
98
|
+
// and parse_mixed_block, and cataract.c's declaration-string parser) so they
|
|
99
|
+
// all agree on what counts as important.
|
|
100
|
+
//
|
|
101
|
+
// The CSS2.1 grammar defines the IMPORTANT_SYM lexical token as:
|
|
102
|
+
// "!"({w}|{comment})*{I}{M}{P}{O}{R}{T}{A}{N}{T}
|
|
103
|
+
// (https://www.w3.org/TR/CSS2/grammar.html) - i.e. zero or more whitespace
|
|
104
|
+
// tokens are allowed between '!' and 'important'.
|
|
105
|
+
//
|
|
106
|
+
// On match, *val_end is updated to exclude the marker (not including any
|
|
107
|
+
// whitespace immediately before the '!' - callers should trim_trailing again)
|
|
108
|
+
// and 1 is returned. Otherwise *val_end is left untouched and 0 is returned.
|
|
109
|
+
static inline int extract_important(const char *val_start, const char **val_end) {
|
|
110
|
+
const char *check = *val_end;
|
|
111
|
+
if (check - val_start < 10) return 0; // strlen("!important") = 10
|
|
112
|
+
|
|
113
|
+
while (check > val_start && IS_WHITESPACE(*(check - 1))) check--;
|
|
114
|
+
|
|
115
|
+
if (check - val_start < 9 || strncmp(check - 9, "important", 9) != 0) return 0;
|
|
116
|
+
check -= 9;
|
|
117
|
+
|
|
118
|
+
while (check > val_start && IS_WHITESPACE(*(check - 1))) check--;
|
|
119
|
+
|
|
120
|
+
if (check <= val_start || *(check - 1) != '!') return 0;
|
|
121
|
+
check--;
|
|
122
|
+
|
|
123
|
+
*val_end = check;
|
|
124
|
+
return 1;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Property/value/important spans found by parse_one_declaration(), in terms
|
|
128
|
+
// of offsets into the original CSS buffer - callers build whatever VALUEs
|
|
129
|
+
// (Declaration structs, error messages, etc.) they need from these.
|
|
130
|
+
struct declaration_span {
|
|
131
|
+
const char *prop_start;
|
|
132
|
+
const char *prop_end; // trimmed
|
|
133
|
+
const char *val_start;
|
|
134
|
+
const char *val_end; // trimmed; excludes a trailing '!important' marker
|
|
135
|
+
int is_important;
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
// Scans one "prop: value" declaration starting at *pos_ptr, stopping at
|
|
139
|
+
// `end` (never reads past it). On success, fills `span`, advances *pos_ptr
|
|
140
|
+
// past the terminating ';' (leaving it at a '}' or `end` if there wasn't
|
|
141
|
+
// one), and returns 1. On failure - no ':' found before a stop character -
|
|
142
|
+
// *pos_ptr is left at the stop character (or `end`) and 0 is returned,
|
|
143
|
+
// leaving recovery (skip-to-semicolon, raise, etc.) to the caller, since
|
|
144
|
+
// that differs by call site.
|
|
145
|
+
//
|
|
146
|
+
// stop_prop_scan_early: if true, ';' and '{' also terminate the property-name
|
|
147
|
+
// scan (used by the two block-oriented parsers, so a missing colon is
|
|
148
|
+
// detected without scanning past the declaration's boundary); if false,
|
|
149
|
+
// only ':' terminates it (used by the standalone declaration-list parser,
|
|
150
|
+
// whose input never contains braces).
|
|
151
|
+
//
|
|
152
|
+
// The value scan always tracks paren depth (so a ';' inside url(...) or
|
|
153
|
+
// rgba(...) doesn't end the value early) and always stops at an unguarded
|
|
154
|
+
// '}', which is harmless for callers whose `end` never contains one.
|
|
155
|
+
static inline int parse_one_declaration(const char **pos_ptr, const char *end,
|
|
156
|
+
int stop_prop_scan_early,
|
|
157
|
+
struct declaration_span *span) {
|
|
158
|
+
const char *pos = *pos_ptr;
|
|
159
|
+
const char *prop_start = pos;
|
|
160
|
+
|
|
161
|
+
if (stop_prop_scan_early) {
|
|
162
|
+
while (pos < end && *pos != ':' && *pos != ';' && *pos != '{') pos++;
|
|
163
|
+
} else {
|
|
164
|
+
while (pos < end && *pos != ':') pos++;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
if (pos >= end || *pos != ':') {
|
|
168
|
+
*pos_ptr = pos;
|
|
169
|
+
return 0;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
const char *prop_end = pos;
|
|
173
|
+
trim_trailing(prop_start, &prop_end);
|
|
174
|
+
trim_leading(&prop_start, prop_end);
|
|
175
|
+
|
|
176
|
+
pos++; // Skip ':'
|
|
177
|
+
while (pos < end && IS_WHITESPACE(*pos)) pos++;
|
|
178
|
+
|
|
179
|
+
const char *val_start = pos;
|
|
180
|
+
int paren_depth = 0;
|
|
181
|
+
while (pos < end && *pos != '}') {
|
|
182
|
+
if (*pos == '(') paren_depth++;
|
|
183
|
+
else if (*pos == ')') paren_depth--;
|
|
184
|
+
else if (*pos == ';' && paren_depth == 0) break;
|
|
185
|
+
pos++;
|
|
186
|
+
}
|
|
187
|
+
const char *val_end = pos;
|
|
188
|
+
trim_trailing(val_start, &val_end);
|
|
189
|
+
|
|
190
|
+
int is_important = extract_important(val_start, &val_end) ? 1 : 0;
|
|
191
|
+
trim_trailing(val_start, &val_end);
|
|
192
|
+
|
|
193
|
+
if (pos < end && *pos == ';') pos++;
|
|
194
|
+
|
|
195
|
+
span->prop_start = prop_start;
|
|
196
|
+
span->prop_end = prop_end;
|
|
197
|
+
span->val_start = val_start;
|
|
198
|
+
span->val_end = val_end;
|
|
199
|
+
span->is_important = is_important;
|
|
200
|
+
|
|
201
|
+
*pos_ptr = pos;
|
|
202
|
+
return 1;
|
|
203
|
+
}
|
|
204
|
+
|
|
91
205
|
// Strip whitespace from both ends and return new string
|
|
92
206
|
static inline VALUE strip_string(const char *str, long len) {
|
|
93
207
|
const char *start = str;
|
|
@@ -157,21 +271,18 @@ void init_flatten_constants(void);
|
|
|
157
271
|
// Specificity (specificity.c)
|
|
158
272
|
VALUE calculate_specificity(VALUE self, VALUE selector);
|
|
159
273
|
|
|
160
|
-
// Import scanner (import_scanner.c)
|
|
161
|
-
VALUE extract_imports(VALUE self, VALUE css_string);
|
|
162
|
-
|
|
163
274
|
// Shorthand expander (shorthand_expander_new.c)
|
|
164
275
|
VALUE cataract_split_value(VALUE self, VALUE value);
|
|
165
|
-
VALUE cataract_expand_margin(VALUE self, VALUE value);
|
|
166
|
-
VALUE cataract_expand_padding(VALUE self, VALUE value);
|
|
167
|
-
VALUE cataract_expand_border(VALUE self, VALUE value);
|
|
168
|
-
VALUE cataract_expand_border_color(VALUE self, VALUE value);
|
|
169
|
-
VALUE cataract_expand_border_style(VALUE self, VALUE value);
|
|
170
|
-
VALUE cataract_expand_border_width(VALUE self, VALUE value);
|
|
171
|
-
VALUE cataract_expand_border_side(VALUE self, VALUE side, VALUE value);
|
|
172
|
-
VALUE cataract_expand_font(VALUE self, VALUE value);
|
|
173
|
-
VALUE cataract_expand_list_style(VALUE self, VALUE value);
|
|
174
|
-
VALUE cataract_expand_background(VALUE self, VALUE value);
|
|
276
|
+
VALUE cataract_expand_margin(VALUE self, VALUE value, VALUE important);
|
|
277
|
+
VALUE cataract_expand_padding(VALUE self, VALUE value, VALUE important);
|
|
278
|
+
VALUE cataract_expand_border(VALUE self, VALUE value, VALUE important);
|
|
279
|
+
VALUE cataract_expand_border_color(VALUE self, VALUE value, VALUE important);
|
|
280
|
+
VALUE cataract_expand_border_style(VALUE self, VALUE value, VALUE important);
|
|
281
|
+
VALUE cataract_expand_border_width(VALUE self, VALUE value, VALUE important);
|
|
282
|
+
VALUE cataract_expand_border_side(VALUE self, VALUE side, VALUE value, VALUE important);
|
|
283
|
+
VALUE cataract_expand_font(VALUE self, VALUE value, VALUE important);
|
|
284
|
+
VALUE cataract_expand_list_style(VALUE self, VALUE value, VALUE important);
|
|
285
|
+
VALUE cataract_expand_background(VALUE self, VALUE value, VALUE important);
|
|
175
286
|
VALUE cataract_expand_shorthand(VALUE self, VALUE decl);
|
|
176
287
|
VALUE cataract_create_margin_shorthand(VALUE self, VALUE properties);
|
|
177
288
|
VALUE cataract_create_padding_shorthand(VALUE self, VALUE properties);
|