cataract 0.2.3 → 0.2.4
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/.rubocop.yml +7 -3
- data/BENCHMARKS.md +32 -32
- data/CHANGELOG.md +10 -0
- data/Gemfile +3 -0
- data/ext/cataract/cataract.c +219 -112
- data/ext/cataract/cataract.h +5 -1
- data/ext/cataract/css_parser.c +523 -33
- data/ext/cataract/flatten.c +233 -91
- data/ext/cataract/shorthand_expander.c +7 -0
- data/lib/cataract/at_rule.rb +2 -1
- data/lib/cataract/constants.rb +10 -0
- data/lib/cataract/import_resolver.rb +18 -87
- data/lib/cataract/import_statement.rb +29 -5
- data/lib/cataract/media_query.rb +98 -0
- data/lib/cataract/pure/byte_constants.rb +11 -0
- data/lib/cataract/pure/flatten.rb +127 -15
- data/lib/cataract/pure/parser.rb +637 -270
- data/lib/cataract/pure/serializer.rb +216 -115
- data/lib/cataract/pure.rb +6 -7
- data/lib/cataract/rule.rb +9 -5
- data/lib/cataract/stylesheet.rb +321 -99
- data/lib/cataract/stylesheet_scope.rb +10 -7
- data/lib/cataract/version.rb +1 -1
- data/lib/cataract.rb +4 -8
- data/lib/tasks/profile.rake +210 -0
- metadata +4 -2
- data/lib/cataract/pure/imports.rb +0 -268
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 90e5adcec05553f73e5829b769d010ecda9ca5bf5eb1b2cc621b74707758c913
|
|
4
|
+
data.tar.gz: 4a82a843a72f2cc3c944798af3b7e7a8271b5ad696c1ed53247854d5ecdda7bb
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: afb9718d653c7bc0c905eb3d273afec8a364ae37de2952ea3285ecf3ef7f5ff29b40887348ef3646adedfab0baeff873211a883750e7c9b992f3e6a25b14cbb0
|
|
7
|
+
data.tar.gz: c40ba4cefa95024f34c7d9306d93ad07b8f448e847c51231381fa83833f2b97e314e5fbab9d7fb2a8edd1fe45fea0760c6db514c79225829e397c339fd5951a6
|
data/.rubocop.yml
CHANGED
|
@@ -103,10 +103,12 @@ Naming/PredicatePrefix:
|
|
|
103
103
|
# These cosmetic style rules add overhead via method dispatch or allocation
|
|
104
104
|
|
|
105
105
|
# Disable numeric predicates in hot path - method dispatch overhead
|
|
106
|
-
# Benchmark shows
|
|
106
|
+
# Benchmark shows `length > 0` is 30% faster than `.positive?` (method dispatch overhead)
|
|
107
|
+
# `!empty?` has no perf penalty vs `length > 0` but `.positive?` is significantly slower
|
|
107
108
|
Style/NumericPredicate:
|
|
108
109
|
Exclude:
|
|
109
110
|
- 'lib/cataract/pure/**/*.rb'
|
|
111
|
+
- 'lib/cataract/stylesheet.rb'
|
|
110
112
|
|
|
111
113
|
# Disable multiple comparison style - avoid array allocation
|
|
112
114
|
# `||` chain is faster than `Array#include?` which allocates an array
|
|
@@ -114,11 +116,13 @@ Style/MultipleComparison:
|
|
|
114
116
|
Exclude:
|
|
115
117
|
- 'lib/cataract/pure/**/*.rb'
|
|
116
118
|
|
|
117
|
-
# Disable zero-length predicate
|
|
118
|
-
#
|
|
119
|
+
# Disable zero-length predicate - prefer `length > 0` for consistency with NumericPredicate
|
|
120
|
+
# While `!empty?` has no perf penalty vs `length > 0`, we use `length > 0` consistently
|
|
121
|
+
# to avoid mixing styles (since `.positive?` is 30% slower and must be avoided)
|
|
119
122
|
Style/ZeroLengthPredicate:
|
|
120
123
|
Exclude:
|
|
121
124
|
- 'lib/cataract/pure/**/*.rb'
|
|
125
|
+
- 'lib/cataract/stylesheet.rb'
|
|
122
126
|
|
|
123
127
|
# Benchmarked range vs offsets. Range has to allocated
|
|
124
128
|
# so not ideal in the hot path
|
data/BENCHMARKS.md
CHANGED
|
@@ -20,17 +20,17 @@ Time to parse CSS into internal data structures
|
|
|
20
20
|
|
|
21
21
|
| Test Case | Native | Pure (no YJIT) | Pure (YJIT) |
|
|
22
22
|
|-----------|--------|----------------|-------------|
|
|
23
|
-
| Small CSS (64 lines, 1.0KB) |
|
|
24
|
-
| Medium CSS with @media (139 lines, 1.6KB) |
|
|
25
|
-
| Selector lists (3500 lines, 62.5KB, 500 lists) |
|
|
23
|
+
| Small CSS (64 lines, 1.0KB) | 37.4K i/s | 3.25K i/s | 13.43K i/s |
|
|
24
|
+
| Medium CSS with @media (139 lines, 1.6KB) | 34.71K i/s | 2.04K i/s | 9.15K i/s |
|
|
25
|
+
| Selector lists (3500 lines, 62.5KB, 500 lists) | 471.8 i/s | 56.7 i/s | 214.1 i/s |
|
|
26
26
|
|
|
27
27
|
### Speedups
|
|
28
28
|
|
|
29
29
|
| Comparison | Speedup |
|
|
30
30
|
|------------|---------|
|
|
31
|
-
| Native vs Pure (no YJIT) | 12.
|
|
32
|
-
| Native vs Pure (YJIT) | 2.
|
|
33
|
-
| YJIT impact on Pure Ruby | 4.
|
|
31
|
+
| Native vs Pure (no YJIT) | 12.76x faster (avg) |
|
|
32
|
+
| Native vs Pure (YJIT) | 2.99x faster (avg) |
|
|
33
|
+
| YJIT impact on Pure Ruby | 4.22x faster (avg) |
|
|
34
34
|
|
|
35
35
|
---
|
|
36
36
|
|
|
@@ -40,19 +40,19 @@ Time to convert parsed CSS back to string format
|
|
|
40
40
|
|
|
41
41
|
| Test Case | Native | Pure (no YJIT) | Pure (YJIT) |
|
|
42
42
|
|-----------|--------|----------------|-------------|
|
|
43
|
-
| to_s (Bootstrap - 191KB) | 1.
|
|
44
|
-
| to_s (Compact utilities - 2.9KB) | 1.
|
|
45
|
-
| to_formatted_s (Nested CSS - 1.3KB) |
|
|
46
|
-
| to_s with selector_lists (3.4KB) |
|
|
47
|
-
| Media filtering (Bootstrap print only) |
|
|
43
|
+
| to_s (Bootstrap - 191KB) | 1.32K i/s | 360.2 i/s | 656.6 i/s |
|
|
44
|
+
| to_s (Compact utilities - 2.9KB) | 1.32K i/s | 360.2 i/s | 656.6 i/s |
|
|
45
|
+
| to_formatted_s (Nested CSS - 1.3KB) | 176.13K i/s | 60.97K i/s | 121.5K i/s |
|
|
46
|
+
| to_s with selector_lists (3.4KB) | 19.03K i/s | 8.01K i/s | 14.2K i/s |
|
|
47
|
+
| Media filtering (Bootstrap print only) | 283.24K i/s | 97.28K i/s | 161.56K i/s |
|
|
48
48
|
|
|
49
49
|
### Speedups
|
|
50
50
|
|
|
51
51
|
| Comparison | Speedup |
|
|
52
52
|
|------------|---------|
|
|
53
|
-
| Native vs Pure (no YJIT) |
|
|
54
|
-
| Native vs Pure (YJIT) |
|
|
55
|
-
| YJIT impact on Pure Ruby | 1.
|
|
53
|
+
| Native vs Pure (no YJIT) | 3.24x faster (avg) |
|
|
54
|
+
| Native vs Pure (YJIT) | 1.73x faster (avg) |
|
|
55
|
+
| YJIT impact on Pure Ruby | 1.86x faster (avg) |
|
|
56
56
|
|
|
57
57
|
---
|
|
58
58
|
|
|
@@ -62,20 +62,20 @@ Time to calculate CSS selector specificity values
|
|
|
62
62
|
|
|
63
63
|
| Test Case | Native | Pure (no YJIT) | Pure (YJIT) |
|
|
64
64
|
|-----------|--------|----------------|-------------|
|
|
65
|
-
| Simple Selectors |
|
|
66
|
-
| Compound Selectors | 6.
|
|
67
|
-
| Combinators | 5.
|
|
68
|
-
| Pseudo-classes & Pseudo-elements | 5.
|
|
69
|
-
| :not() Pseudo-class (CSS3) | 3.48M i/s | 103.
|
|
70
|
-
| Complex Real-world Selectors | 4.
|
|
65
|
+
| Simple Selectors | 7.28M i/s | 506.61K i/s | 2.45M i/s |
|
|
66
|
+
| Compound Selectors | 6.4M i/s | 186.62K i/s | 405.15K i/s |
|
|
67
|
+
| Combinators | 5.04M i/s | 147.07K i/s | 255.92K i/s |
|
|
68
|
+
| Pseudo-classes & Pseudo-elements | 5.17M i/s | 117.16K i/s | 195.12K i/s |
|
|
69
|
+
| :not() Pseudo-class (CSS3) | 3.48M i/s | 103.47K i/s | 161.34K i/s |
|
|
70
|
+
| Complex Real-world Selectors | 4.01M i/s | 52.41K i/s | 77.48K i/s |
|
|
71
71
|
|
|
72
72
|
### Speedups
|
|
73
73
|
|
|
74
74
|
| Comparison | Speedup |
|
|
75
75
|
|------------|---------|
|
|
76
|
-
| Native vs Pure (no YJIT) |
|
|
77
|
-
| Native vs Pure (YJIT) | 23.
|
|
78
|
-
| YJIT impact on Pure Ruby | 2.
|
|
76
|
+
| Native vs Pure (no YJIT) | 39.54x faster (avg) |
|
|
77
|
+
| Native vs Pure (YJIT) | 23.05x faster (avg) |
|
|
78
|
+
| YJIT impact on Pure Ruby | 2.24x faster (avg) |
|
|
79
79
|
|
|
80
80
|
---
|
|
81
81
|
|
|
@@ -85,20 +85,20 @@ Time to flatten multiple CSS rule sets with same selector
|
|
|
85
85
|
|
|
86
86
|
| Test Case | Native | Pure (no YJIT) | Pure (YJIT) |
|
|
87
87
|
|-----------|--------|----------------|-------------|
|
|
88
|
-
| No shorthand properties (large) |
|
|
89
|
-
| Simple properties |
|
|
90
|
-
| Cascade with specificity |
|
|
91
|
-
| Important declarations |
|
|
92
|
-
| Shorthand expansion |
|
|
93
|
-
| Complex flattening |
|
|
88
|
+
| No shorthand properties (large) | 13.91K i/s | 3.23K i/s | 6.39K i/s |
|
|
89
|
+
| Simple properties | 144.19K i/s | 71.11K i/s | 101.38K i/s |
|
|
90
|
+
| Cascade with specificity | 172.96K i/s | 69.16K i/s | 99.23K i/s |
|
|
91
|
+
| Important declarations | 173.35K i/s | 69.12K i/s | 100.16K i/s |
|
|
92
|
+
| Shorthand expansion | 13.91K i/s | 3.23K i/s | 6.39K i/s |
|
|
93
|
+
| Complex flattening | 29.86K i/s | 15.77K i/s | 22.09K i/s |
|
|
94
94
|
|
|
95
95
|
### Speedups
|
|
96
96
|
|
|
97
97
|
| Comparison | Speedup |
|
|
98
98
|
|------------|---------|
|
|
99
|
-
| Native vs Pure (no YJIT) |
|
|
100
|
-
| Native vs Pure (YJIT) | 1.
|
|
101
|
-
| YJIT impact on Pure Ruby | 1.
|
|
99
|
+
| Native vs Pure (no YJIT) | 2.54x faster (avg) |
|
|
100
|
+
| Native vs Pure (YJIT) | 1.63x faster (avg) |
|
|
101
|
+
| YJIT impact on Pure Ruby | 1.53x faster (avg) |
|
|
102
102
|
|
|
103
103
|
---
|
|
104
104
|
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
## [ Unreleased ]
|
|
2
2
|
|
|
3
|
+
## [0.2.4 - 2025-11-23]
|
|
4
|
+
- MediaQuery first-class objects: Refactored media queries from simple symbols to proper structs with id, type, and conditions, enabling accurate
|
|
5
|
+
serialization and proper handling of complex queries like @media screen and (min-width: 768px)
|
|
6
|
+
- Fixed import resolution: Import statements now properly merge selector lists and media query lists from imported stylesheets with correct ID offsetting,
|
|
7
|
+
preventing data loss
|
|
8
|
+
- Sequential rule ID invariant: Parser now ensures rules[i].id == i via placeholder strategy, enabling O(1) array access instead of O(N) lookups during
|
|
9
|
+
serialization
|
|
10
|
+
- Improved nested media handling: Nested media queries in imports now combine correctly (e.g., @import "file.css" screen where file contains @media
|
|
11
|
+
(min-width: 768px))
|
|
12
|
+
|
|
3
13
|
## [0.2.3 - 2025-11-18]
|
|
4
14
|
- Pure Parser: Bugs with url()
|
|
5
15
|
|
data/Gemfile
CHANGED
|
@@ -10,13 +10,16 @@ gem 'rake', '~> 13.0'
|
|
|
10
10
|
gem 'rake-compiler', '~> 1.0'
|
|
11
11
|
|
|
12
12
|
# Development/benchmarking dependencies (not needed by gem users)
|
|
13
|
+
gem 'addressable', '~> 2.8' # for custom URI resolver testing
|
|
13
14
|
gem 'benchmark-ips', '~> 2.0'
|
|
14
15
|
gem 'css_parser', '~> 1.0' # for benchmarking against
|
|
15
16
|
gem 'minitest'
|
|
16
17
|
gem 'minitest-spec'
|
|
17
18
|
gem 'nokogiri' # for docs
|
|
19
|
+
gem 'ruby-prof', require: false # for profiling
|
|
18
20
|
gem 'simplecov', require: false
|
|
19
21
|
gem 'simplecov-cobertura', require: false
|
|
22
|
+
gem 'stackprof', require: false # for profiling
|
|
20
23
|
gem 'webmock', '~> 3.0' # for testing URL loading
|
|
21
24
|
|
|
22
25
|
gem 'overcommit', '~> 0.64', group: :development
|