cataract 0.1.2 → 0.1.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.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci-manual-rubies.yml +27 -0
  3. data/.overcommit.yml +1 -1
  4. data/.rubocop.yml +62 -0
  5. data/.rubocop_todo.yml +186 -0
  6. data/BENCHMARKS.md +60 -139
  7. data/CHANGELOG.md +14 -0
  8. data/README.md +30 -2
  9. data/Rakefile +49 -22
  10. data/cataract.gemspec +4 -1
  11. data/ext/cataract/cataract.c +47 -47
  12. data/ext/cataract/css_parser.c +17 -33
  13. data/ext/cataract/merge.c +58 -2
  14. data/lib/cataract/at_rule.rb +8 -9
  15. data/lib/cataract/declaration.rb +18 -0
  16. data/lib/cataract/import_resolver.rb +3 -4
  17. data/lib/cataract/pure/byte_constants.rb +69 -0
  18. data/lib/cataract/pure/helpers.rb +35 -0
  19. data/lib/cataract/pure/imports.rb +255 -0
  20. data/lib/cataract/pure/merge.rb +1146 -0
  21. data/lib/cataract/pure/parser.rb +1236 -0
  22. data/lib/cataract/pure/serializer.rb +590 -0
  23. data/lib/cataract/pure/specificity.rb +206 -0
  24. data/lib/cataract/pure.rb +130 -0
  25. data/lib/cataract/rule.rb +22 -13
  26. data/lib/cataract/stylesheet.rb +14 -9
  27. data/lib/cataract/version.rb +1 -1
  28. data/lib/cataract.rb +18 -5
  29. metadata +12 -25
  30. data/benchmarks/benchmark_harness.rb +0 -193
  31. data/benchmarks/benchmark_merging.rb +0 -121
  32. data/benchmarks/benchmark_optimization_comparison.rb +0 -168
  33. data/benchmarks/benchmark_parsing.rb +0 -153
  34. data/benchmarks/benchmark_ragel_removal.rb +0 -56
  35. data/benchmarks/benchmark_runner.rb +0 -70
  36. data/benchmarks/benchmark_serialization.rb +0 -180
  37. data/benchmarks/benchmark_shorthand.rb +0 -109
  38. data/benchmarks/benchmark_shorthand_expansion.rb +0 -176
  39. data/benchmarks/benchmark_specificity.rb +0 -124
  40. data/benchmarks/benchmark_string_allocation.rb +0 -151
  41. data/benchmarks/benchmark_stylesheet_to_s.rb +0 -62
  42. data/benchmarks/benchmark_to_s_cached.rb +0 -55
  43. data/benchmarks/benchmark_value_splitter.rb +0 -54
  44. data/benchmarks/benchmark_yjit.rb +0 -158
  45. data/benchmarks/benchmark_yjit_workers.rb +0 -61
  46. data/benchmarks/profile_to_s.rb +0 -23
  47. data/benchmarks/speedup_calculator.rb +0 -83
  48. data/benchmarks/system_metadata.rb +0 -81
  49. data/benchmarks/templates/benchmarks.md.erb +0 -221
  50. data/benchmarks/yjit_tests.rb +0 -141
  51. data/scripts/fuzzer/run.rb +0 -828
  52. data/scripts/fuzzer/worker.rb +0 -99
  53. data/scripts/generate_benchmarks_md.rb +0 -155
@@ -0,0 +1,206 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Pure Ruby CSS parser - Specificity calculation
4
+ # NO REGEXP ALLOWED - char-by-char parsing only
5
+
6
+ module Cataract
7
+ # Calculate CSS specificity for a selector
8
+ #
9
+ # @param selector [String] CSS selector
10
+ # @return [Integer] Specificity value
11
+ #
12
+ # Specificity calculation (per CSS spec):
13
+ # - Count IDs (#id) - each worth 100
14
+ # - Count classes/attributes/pseudo-classes (.class, [attr], :pseudo) - each worth 10
15
+ # - Count elements/pseudo-elements (div, ::before) - each worth 1
16
+ def self.calculate_specificity(selector)
17
+ return 0 if selector.nil? || selector.empty?
18
+
19
+ # Counters for specificity components
20
+ id_count = 0
21
+ class_count = 0
22
+ attr_count = 0
23
+ pseudo_class_count = 0
24
+ pseudo_element_count = 0
25
+ element_count = 0
26
+
27
+ i = 0
28
+ len = selector.length
29
+
30
+ pseudo_element_kwords = %w[before after first-line first-letter selection]
31
+
32
+ while i < len
33
+ byte = selector.getbyte(i)
34
+
35
+ # Skip whitespace and combinators
36
+ if byte == BYTE_SPACE || byte == BYTE_TAB || byte == BYTE_NEWLINE || byte == BYTE_CR ||
37
+ byte == BYTE_GT || byte == BYTE_PLUS || byte == BYTE_TILDE || byte == BYTE_COMMA
38
+ i += 1
39
+ next
40
+ end
41
+
42
+ # ID selector: #id
43
+ if byte == BYTE_HASH
44
+ id_count += 1
45
+ i += 1
46
+ # Skip the identifier
47
+ while i < len && ident_char?(selector.getbyte(i))
48
+ i += 1
49
+ end
50
+ next
51
+ end
52
+
53
+ # Class selector: .class
54
+ if byte == BYTE_DOT
55
+ class_count += 1
56
+ i += 1
57
+ # Skip the identifier
58
+ while i < len && ident_char?(selector.getbyte(i))
59
+ i += 1
60
+ end
61
+ next
62
+ end
63
+
64
+ # Attribute selector: [attr]
65
+ if byte == BYTE_LBRACKET
66
+ attr_count += 1
67
+ i += 1
68
+ # Skip to closing bracket
69
+ bracket_depth = 1
70
+ while i < len && bracket_depth > 0
71
+ b = selector.getbyte(i)
72
+ if b == BYTE_LBRACKET
73
+ bracket_depth += 1
74
+ elsif b == BYTE_RBRACKET
75
+ bracket_depth -= 1
76
+ end
77
+ i += 1
78
+ end
79
+ next
80
+ end
81
+
82
+ # Pseudo-element (::) or pseudo-class (:)
83
+ if byte == BYTE_COLON
84
+ i += 1
85
+ is_pseudo_element = false
86
+
87
+ # Check for double colon (::)
88
+ if i < len && selector.getbyte(i) == BYTE_COLON
89
+ is_pseudo_element = true
90
+ i += 1
91
+ end
92
+
93
+ # Extract pseudo name
94
+ pseudo_start = i
95
+ while i < len && ident_char?(selector.getbyte(i))
96
+ i += 1
97
+ end
98
+ pseudo_name = selector[pseudo_start...i]
99
+
100
+ # Check for legacy pseudo-elements (single colon but should be double)
101
+ is_legacy_pseudo_element = false
102
+ if !is_pseudo_element && !pseudo_name.empty?
103
+ is_legacy_pseudo_element = pseudo_element_kwords.include?(pseudo_name)
104
+ end
105
+
106
+ # Check for :not() - it doesn't count itself, but its content does
107
+ is_not = (pseudo_name == 'not')
108
+
109
+ # Skip function arguments if present
110
+ if i < len && selector.getbyte(i) == BYTE_LPAREN
111
+ i += 1
112
+ paren_depth = 1
113
+
114
+ # If it's :not(), calculate specificity of the content
115
+ if is_not
116
+ not_content_start = i
117
+
118
+ # Find closing paren
119
+ while i < len && paren_depth > 0
120
+ b = selector.getbyte(i)
121
+ if b == BYTE_LPAREN
122
+ paren_depth += 1
123
+ elsif b == BYTE_RPAREN
124
+ paren_depth -= 1
125
+ end
126
+ i += 1 if paren_depth > 0
127
+ end
128
+
129
+ not_content = selector[not_content_start...i]
130
+
131
+ # Recursively calculate specificity of :not() content
132
+ unless not_content.empty?
133
+ not_specificity = calculate_specificity(not_content)
134
+
135
+ # Add :not() content's specificity to our counts
136
+ additional_a = not_specificity / 100
137
+ additional_b = (not_specificity % 100) / 10
138
+ additional_c = not_specificity % 10
139
+
140
+ id_count += additional_a
141
+ class_count += additional_b
142
+ element_count += additional_c
143
+ end
144
+
145
+ i += 1 # Skip closing paren
146
+ else
147
+ # Skip other function arguments
148
+ while i < len && paren_depth > 0
149
+ b = selector.getbyte(i)
150
+ if b == BYTE_LPAREN
151
+ paren_depth += 1
152
+ elsif b == BYTE_RPAREN
153
+ paren_depth -= 1
154
+ end
155
+ i += 1
156
+ end
157
+
158
+ # Count the pseudo-class/element
159
+ if is_pseudo_element || is_legacy_pseudo_element
160
+ pseudo_element_count += 1
161
+ else
162
+ pseudo_class_count += 1
163
+ end
164
+ end
165
+ else
166
+ # No function arguments - count the pseudo-class/element
167
+ if is_not
168
+ # :not without parens is invalid, but don't count it
169
+ elsif is_pseudo_element || is_legacy_pseudo_element
170
+ pseudo_element_count += 1
171
+ else
172
+ pseudo_class_count += 1
173
+ end
174
+ end
175
+ next
176
+ end
177
+
178
+ # Universal selector: *
179
+ if byte == BYTE_ASTERISK
180
+ # Universal selector has specificity 0, don't count
181
+ i += 1
182
+ next
183
+ end
184
+
185
+ # Type selector (element name): div, span, etc.
186
+ if letter?(byte)
187
+ element_count += 1
188
+ # Skip the identifier
189
+ while i < len && ident_char?(selector.getbyte(i))
190
+ i += 1
191
+ end
192
+ next
193
+ end
194
+
195
+ # Unknown character, skip it
196
+ i += 1
197
+ end
198
+
199
+ # Calculate specificity using W3C formula
200
+ specificity = (id_count * 100) +
201
+ ((class_count + attr_count + pseudo_class_count) * 10) +
202
+ ((element_count + pseudo_element_count) * 1)
203
+
204
+ specificity
205
+ end
206
+ end
@@ -0,0 +1,130 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Pure Ruby implementation of Cataract CSS parser
4
+ #
5
+ # This is a character-by-character parser that closely mirrors the C implementation.
6
+ # ==================================================================
7
+ # NO REGEXP ALLOWED - consume chars one at a time like the C version.
8
+ # ==================================================================
9
+ #
10
+ # Load this instead of the C extension with:
11
+ # require 'cataract/pure'
12
+ #
13
+ # Or run tests with:
14
+ # CATARACT_PURE=1 rake test
15
+
16
+ # Check if C extension is already loaded
17
+ if defined?(Cataract::NATIVE_EXTENSION_LOADED)
18
+ raise LoadError, 'Cataract C extension is already loaded. Cannot load pure Ruby version.'
19
+ end
20
+
21
+ # Define base module and error classes first
22
+ module Cataract
23
+ class Error < StandardError; end
24
+ class DepthError < Error; end
25
+ class SizeError < Error; end
26
+ end
27
+
28
+ require_relative 'version'
29
+
30
+ # Load struct definitions and supporting files
31
+ # (These are also loaded by lib/cataract.rb, but we need them here for direct require)
32
+ require_relative 'declaration'
33
+ require_relative 'rule'
34
+ require_relative 'at_rule'
35
+ require_relative 'stylesheet_scope'
36
+ require_relative 'stylesheet'
37
+ require_relative 'declarations'
38
+ require_relative 'import_resolver'
39
+
40
+ # Add to_s method to Declarations class for pure Ruby mode
41
+ module Cataract
42
+ class Declarations
43
+ # Serialize declarations to CSS string
44
+ def to_s
45
+ result = String.new
46
+ @values.each_with_index do |decl, i|
47
+ result << decl.property
48
+ result << ': '
49
+ result << decl.value
50
+ result << ' !important' if decl.important
51
+ result << ';'
52
+ result << ' ' if i < @values.length - 1 # Add space after semicolon except for last
53
+ end
54
+ result
55
+ end
56
+ end
57
+ end
58
+
59
+ # Load pure Ruby implementation modules
60
+ require_relative 'pure/byte_constants'
61
+ require_relative 'pure/helpers'
62
+ require_relative 'pure/specificity'
63
+ require_relative 'pure/imports'
64
+ require_relative 'pure/serializer'
65
+ require_relative 'pure/parser'
66
+ require_relative 'pure/merge'
67
+
68
+ module Cataract
69
+ # Flag to indicate pure Ruby version is loaded
70
+ PURE_RUBY_LOADED = true
71
+
72
+ # Implementation type constant
73
+ IMPLEMENTATION = :ruby
74
+
75
+ # Compile flags (mimic C version)
76
+ COMPILE_FLAGS = {
77
+ debug: false,
78
+ str_buf_optimization: false,
79
+ pure_ruby: true
80
+ }.freeze
81
+
82
+ # Parse CSS string and return hash with rules, media_index, charset, etc.
83
+ #
84
+ # @api private
85
+ # @param css_string [String] CSS to parse
86
+ # @return [Hash] {
87
+ # rules: Array<Rule>, # Flat array of Rule/AtRule structs
88
+ # _media_index: Hash, # Symbol => Array of rule IDs
89
+ # charset: String|nil, # @charset value if present
90
+ # _has_nesting: Boolean # Whether any nested rules exist
91
+ # }
92
+ def self._parse_css(css_string)
93
+ parser = Parser.new(css_string)
94
+ parser.parse
95
+ end
96
+
97
+ # NOTE: Copied from cataract.rb
98
+ # Need to untangle this eventually
99
+ def self.parse_css(css, imports: false)
100
+ css = ImportResolver.resolve(css, imports) if imports
101
+
102
+ Stylesheet.parse(css)
103
+ end
104
+
105
+ # Merge stylesheet rules according to CSS cascade rules
106
+ #
107
+ # @param stylesheet [Stylesheet] Stylesheet to merge
108
+ # @return [Stylesheet] New stylesheet with merged rules
109
+ def self.merge(stylesheet)
110
+ Merge.merge(stylesheet, mutate: false)
111
+ end
112
+
113
+ # Merge stylesheet rules in-place (mutates receiver)
114
+ #
115
+ # @param stylesheet [Stylesheet] Stylesheet to merge
116
+ # @return [Stylesheet] Same stylesheet (mutated)
117
+ def self.merge!(stylesheet)
118
+ Merge.merge(stylesheet, mutate: true)
119
+ end
120
+
121
+ # Add stub method to Stylesheet for pure Ruby implementation
122
+ class Stylesheet
123
+ # Color conversion is only available in the native C extension
124
+ #
125
+ # @raise [NotImplementedError] Always raises - color conversion requires C extension
126
+ def convert_colors!(*_args)
127
+ raise NotImplementedError, 'convert_colors! is only available in the native C extension'
128
+ end
129
+ end
130
+ end
data/lib/cataract/rule.rb CHANGED
@@ -1,16 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Cataract
4
- # Represents a CSS rule with a selector and declarations.
5
- #
6
- # Rule is a C struct defined as: `Struct.new(:id, :selector, :declarations, :specificity)`
7
- #
8
- # Rules are created by the parser and stored in Stylesheet objects. Each rule
9
- # contains:
4
+ # Rules are created by the parser and stored in Stylesheet objects. Each rule contains:
10
5
  # - An ID (position in the stylesheet)
11
6
  # - A CSS selector string
12
7
  # - An array of Declaration structs
13
8
  # - A specificity value (calculated lazily)
9
+ # - Parent rule ID for nested rules (nil if top-level)
10
+ # - Nesting style (0=implicit, 1=explicit, nil=not nested)
14
11
  #
15
12
  # Media query information is stored separately in Stylesheet's media_index.
16
13
  #
@@ -25,6 +22,17 @@ module Cataract
25
22
  # @attr [String] selector The CSS selector (e.g., "body", ".class", "#id")
26
23
  # @attr [Array<Declaration>] declarations Array of CSS property declarations
27
24
  # @attr [Integer, nil] specificity CSS specificity value (calculated lazily)
25
+ # @attr [Integer, nil] parent_rule_id Parent rule ID for nested rules
26
+ # @attr [Integer, nil] nesting_style 0=implicit, 1=explicit, nil=not nested
27
+ Rule = Struct.new(
28
+ :id,
29
+ :selector,
30
+ :declarations,
31
+ :specificity,
32
+ :parent_rule_id,
33
+ :nesting_style
34
+ )
35
+
28
36
  class Rule
29
37
  # Silence warning about method redefinition. We redefine below to lazily calculate
30
38
  # specificity
@@ -112,19 +120,20 @@ module Cataract
112
120
  end
113
121
  end
114
122
 
115
- # Compare rules by their attributes rather than object identity.
123
+ # Compare rules for logical equality based on CSS semantics.
116
124
  #
117
- # Two rules are equal if they have the same id, selector, declarations, and specificity.
125
+ # Two rules are equal if they have the same selector and declarations.
126
+ # Internal implementation details (id, specificity) are not considered
127
+ # since they don't affect the CSS semantics. Specificity is derived from
128
+ # the selector, so if selectors match, specificity must match too.
118
129
  #
119
130
  # @param other [Object] Object to compare with
120
- # @return [Boolean] true if rules have same attributes
131
+ # @return [Boolean] true if rules have same selector and declarations
121
132
  def ==(other)
122
133
  return false unless other.is_a?(Rule)
123
134
 
124
- id == other.id &&
125
- selector == other.selector &&
126
- declarations == other.declarations &&
127
- specificity == other.specificity
135
+ selector == other.selector &&
136
+ declarations == other.declarations
128
137
  end
129
138
  alias eql? ==
130
139
  end
@@ -48,6 +48,9 @@ module Cataract
48
48
  @rules = [] # Flat array of Rule structs
49
49
  @_media_index = {} # Hash: Symbol => Array of rule IDs
50
50
  @charset = nil
51
+ @_has_nesting = nil # Set by parser (nil or boolean)
52
+ @_last_rule_id = nil # Tracks next rule ID for add_block
53
+ @selectors = nil # Memoized cache of selectors
51
54
  end
52
55
 
53
56
  # Parse CSS and return a new Stylesheet
@@ -297,12 +300,13 @@ module Cataract
297
300
  Cataract._stylesheet_to_s(@rules, @_media_index, @charset, @_has_nesting || false)
298
301
  else
299
302
  # Collect all rule IDs that match the requested media types
300
- matching_rule_ids = Set.new
303
+ matching_rule_ids = []
301
304
  which_media_array.each do |media_sym|
302
305
  if @_media_index[media_sym]
303
- matching_rule_ids.merge(@_media_index[media_sym])
306
+ matching_rule_ids.concat(@_media_index[media_sym])
304
307
  end
305
308
  end
309
+ matching_rule_ids.uniq! # Dedupe: same rule can be in multiple media indexes
306
310
 
307
311
  # Build filtered rules array (keep original IDs, no recreation needed)
308
312
  filtered_rules = matching_rule_ids.sort.map! { |rule_id| @rules[rule_id] }
@@ -311,7 +315,7 @@ module Cataract
311
315
  filtered_media_index = {}
312
316
  which_media_array.each do |media_sym|
313
317
  if @_media_index[media_sym]
314
- filtered_media_index[media_sym] = @_media_index[media_sym] & matching_rule_ids.to_a
318
+ filtered_media_index[media_sym] = @_media_index[media_sym] & matching_rule_ids
315
319
  end
316
320
  end
317
321
 
@@ -353,20 +357,21 @@ module Cataract
353
357
  Cataract._stylesheet_to_formatted_s(@rules, @_media_index, @charset, @_has_nesting || false)
354
358
  else
355
359
  # Collect all rule IDs that match the requested media types
356
- matching_rule_ids = Set.new
360
+ matching_rule_ids = []
357
361
 
358
362
  # Include rules not in any media query (they apply to all media)
359
363
  media_rule_ids = @_media_index.values.flatten.uniq
360
364
  all_rule_ids = (0...@rules.length).to_a
361
365
  non_media_rule_ids = all_rule_ids - media_rule_ids
362
- matching_rule_ids.merge(non_media_rule_ids)
366
+ matching_rule_ids.concat(non_media_rule_ids)
363
367
 
364
368
  # Include rules from requested media types
365
369
  which_media_array.each do |media_sym|
366
370
  if @_media_index[media_sym]
367
- matching_rule_ids.merge(@_media_index[media_sym])
371
+ matching_rule_ids.concat(@_media_index[media_sym])
368
372
  end
369
373
  end
374
+ matching_rule_ids.uniq! # Dedupe: same rule can be in multiple media indexes
370
375
 
371
376
  # Build filtered rules array (keep original IDs, no recreation needed)
372
377
  filtered_rules = matching_rule_ids.sort.map! { |rule_id| @rules[rule_id] }
@@ -375,7 +380,7 @@ module Cataract
375
380
  filtered_media_index = {}
376
381
  which_media_array.each do |media_sym|
377
382
  if @_media_index[media_sym]
378
- filtered_media_index[media_sym] = @_media_index[media_sym] & matching_rule_ids.to_a
383
+ filtered_media_index[media_sym] = @_media_index[media_sym] & matching_rule_ids
379
384
  end
380
385
  end
381
386
 
@@ -499,7 +504,7 @@ module Cataract
499
504
  filter_media = media_types ? Array(media_types).map(&:to_sym) : nil
500
505
 
501
506
  # Find rules to remove
502
- rules_to_remove = Set.new
507
+ rules_to_remove = []
503
508
  @rules.each_with_index do |rule, rule_id|
504
509
  # Check selector match
505
510
  next if selector && rule.selector != selector
@@ -522,7 +527,7 @@ module Cataract
522
527
  rules_to_remove << rule_id
523
528
  end
524
529
 
525
- # Remove rules and update media_index
530
+ # Remove rules and update media_index (sort in reverse to maintain indices during deletion)
526
531
  rules_to_remove.sort.reverse_each do |rule_id|
527
532
  @rules.delete_at(rule_id)
528
533
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Cataract
4
- VERSION = '0.1.2'
4
+ VERSION = '0.1.4'
5
5
  end
data/lib/cataract.rb CHANGED
@@ -1,9 +1,20 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'cataract/version'
4
- require_relative 'cataract/native_extension'
4
+
5
+ # Load struct definitions first (before C extension or pure Ruby)
6
+ require_relative 'cataract/declaration'
5
7
  require_relative 'cataract/rule'
6
8
  require_relative 'cataract/at_rule'
9
+
10
+ # Load pure Ruby or C extension based on ENV var
11
+ if %w[1 true].include?(ENV.fetch('CATARACT_PURE', nil)) || RUBY_ENGINE == 'jruby'
12
+ require_relative 'cataract/pure'
13
+ else
14
+ require_relative 'cataract/native_extension'
15
+ end
16
+
17
+ # Load supporting Ruby files (used by both implementations)
7
18
  require_relative 'cataract/stylesheet_scope'
8
19
  require_relative 'cataract/stylesheet'
9
20
  require_relative 'cataract/declarations'
@@ -60,11 +71,13 @@ module Cataract
60
71
  #
61
72
  # @see Stylesheet#parse
62
73
  # @see Stylesheet.parse
63
- def parse_css(css, imports: false)
64
- # Resolve @import statements if requested
65
- css = ImportResolver.resolve(css, imports) if imports
74
+ unless method_defined?(:parse_css)
75
+ def parse_css(css, imports: false)
76
+ # Resolve @import statements if requested
77
+ css = ImportResolver.resolve(css, imports) if imports
66
78
 
67
- Stylesheet.parse(css)
79
+ Stylesheet.parse(css)
80
+ end
68
81
  end
69
82
 
70
83
  # Merge CSS rules according to CSS cascade rules.
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cataract
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - James Cook
@@ -21,12 +21,14 @@ extra_rdoc_files: []
21
21
  files:
22
22
  - ".clang-tidy"
23
23
  - ".github/workflows/ci-macos.yml"
24
+ - ".github/workflows/ci-manual-rubies.yml"
24
25
  - ".github/workflows/ci.yml"
25
26
  - ".github/workflows/docs.yml"
26
27
  - ".github/workflows/test.yml"
27
28
  - ".gitignore"
28
29
  - ".overcommit.yml"
29
30
  - ".rubocop.yml"
31
+ - ".rubocop_todo.yml"
30
32
  - BENCHMARKS.md
31
33
  - CHANGELOG.md
32
34
  - Gemfile
@@ -34,27 +36,6 @@ files:
34
36
  - RAGEL_MIGRATION.md
35
37
  - README.md
36
38
  - Rakefile
37
- - benchmarks/benchmark_harness.rb
38
- - benchmarks/benchmark_merging.rb
39
- - benchmarks/benchmark_optimization_comparison.rb
40
- - benchmarks/benchmark_parsing.rb
41
- - benchmarks/benchmark_ragel_removal.rb
42
- - benchmarks/benchmark_runner.rb
43
- - benchmarks/benchmark_serialization.rb
44
- - benchmarks/benchmark_shorthand.rb
45
- - benchmarks/benchmark_shorthand_expansion.rb
46
- - benchmarks/benchmark_specificity.rb
47
- - benchmarks/benchmark_string_allocation.rb
48
- - benchmarks/benchmark_stylesheet_to_s.rb
49
- - benchmarks/benchmark_to_s_cached.rb
50
- - benchmarks/benchmark_value_splitter.rb
51
- - benchmarks/benchmark_yjit.rb
52
- - benchmarks/benchmark_yjit_workers.rb
53
- - benchmarks/profile_to_s.rb
54
- - benchmarks/speedup_calculator.rb
55
- - benchmarks/system_metadata.rb
56
- - benchmarks/templates/benchmarks.md.erb
57
- - benchmarks/yjit_tests.rb
58
39
  - cataract.gemspec
59
40
  - cliff.toml
60
41
  - docs/files/EXAMPLE.md
@@ -99,16 +80,22 @@ files:
99
80
  - lib/cataract.rb
100
81
  - lib/cataract/at_rule.rb
101
82
  - lib/cataract/color_conversion.rb
83
+ - lib/cataract/declaration.rb
102
84
  - lib/cataract/declarations.rb
103
85
  - lib/cataract/import_resolver.rb
86
+ - lib/cataract/pure.rb
87
+ - lib/cataract/pure/byte_constants.rb
88
+ - lib/cataract/pure/helpers.rb
89
+ - lib/cataract/pure/imports.rb
90
+ - lib/cataract/pure/merge.rb
91
+ - lib/cataract/pure/parser.rb
92
+ - lib/cataract/pure/serializer.rb
93
+ - lib/cataract/pure/specificity.rb
104
94
  - lib/cataract/rule.rb
105
95
  - lib/cataract/stylesheet.rb
106
96
  - lib/cataract/stylesheet_scope.rb
107
97
  - lib/cataract/version.rb
108
98
  - lib/tasks/gem.rake
109
- - scripts/fuzzer/run.rb
110
- - scripts/fuzzer/worker.rb
111
- - scripts/generate_benchmarks_md.rb
112
99
  homepage: https://github.com/jamescook/cataract
113
100
  licenses:
114
101
  - MIT