cataract 0.3.0 → 0.4.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/.gitignore +0 -3
- data/.rubocop_todo.yml +11 -19
- data/BENCHMARKS.md +40 -40
- data/CHANGELOG.md +9 -0
- data/ext/cataract/cataract.c +72 -103
- data/ext/cataract/cataract.h +0 -1
- data/ext/cataract/css_parser.c +0 -18
- data/lib/cataract/declarations.rb +14 -4
- data/lib/cataract/native.rb +30 -0
- data/lib/cataract/pure/byte_constants.rb +70 -66
- data/lib/cataract/pure/declarations.rb +125 -0
- data/lib/cataract/pure/flatten.rb +1197 -1182
- data/lib/cataract/pure/parser.rb +1725 -1729
- data/lib/cataract/pure/serializer.rb +575 -715
- data/lib/cataract/pure/specificity.rb +165 -144
- data/lib/cataract/pure.rb +73 -101
- data/lib/cataract/rule.rb +6 -3
- data/lib/cataract/stylesheet.rb +19 -7
- data/lib/cataract/version.rb +1 -1
- data/lib/cataract.rb +41 -30
- data/lib/tasks/profile.rake +6 -3
- metadata +3 -2
- data/lib/cataract/pure/helpers.rb +0 -35
data/lib/cataract/version.rb
CHANGED
data/lib/cataract.rb
CHANGED
|
@@ -1,34 +1,18 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative 'cataract/version'
|
|
4
|
-
require_relative 'cataract/error'
|
|
5
|
-
require_relative 'cataract/constants'
|
|
6
|
-
|
|
7
|
-
# Load struct definitions first (before C extension or pure Ruby)
|
|
8
|
-
require_relative 'cataract/declaration'
|
|
9
|
-
require_relative 'cataract/rule'
|
|
10
|
-
require_relative 'cataract/at_rule'
|
|
11
|
-
require_relative 'cataract/media_query'
|
|
12
|
-
require_relative 'cataract/import_statement'
|
|
13
|
-
|
|
14
|
-
# Load pure Ruby or C extension based on ENV var
|
|
15
|
-
if %w[1 true].include?(ENV.fetch('CATARACT_PURE', nil)) || RUBY_ENGINE == 'jruby'
|
|
16
|
-
require_relative 'cataract/pure'
|
|
17
|
-
else
|
|
18
|
-
require_relative 'cataract/native_extension'
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
# Load supporting Ruby files (used by both implementations)
|
|
22
|
-
require_relative 'cataract/stylesheet_scope'
|
|
23
|
-
require_relative 'cataract/stylesheet'
|
|
24
|
-
require_relative 'cataract/declarations'
|
|
25
|
-
require_relative 'cataract/import_resolver'
|
|
26
|
-
|
|
27
3
|
# Cataract is a high-performance CSS parser written in C with a Ruby interface.
|
|
28
4
|
#
|
|
29
5
|
# It provides fast CSS parsing, rule querying, cascade merging, and serialization.
|
|
30
6
|
# Designed for performance-critical applications that need to process large amounts of CSS.
|
|
31
7
|
#
|
|
8
|
+
# Pure Ruby and native each live entirely under their own Backends::Pure /
|
|
9
|
+
# Backends::Native namespace (no shared method/constant is ever defined by
|
|
10
|
+
# a backend directly on Cataract or on a shared value type), so both can be
|
|
11
|
+
# required in the same process - e.g. to compare their output directly.
|
|
12
|
+
# Backends.active is the one this process picked by default (below); it's
|
|
13
|
+
# what shared value types (Stylesheet, Declarations, Rule) fall back to
|
|
14
|
+
# when they aren't otherwise told which backend produced them.
|
|
15
|
+
#
|
|
32
16
|
# @example Basic usage
|
|
33
17
|
# require 'cataract'
|
|
34
18
|
#
|
|
@@ -44,6 +28,33 @@ require_relative 'cataract/import_resolver'
|
|
|
44
28
|
# @see Stylesheet Main class for working with parsed CSS
|
|
45
29
|
# @see Rule Represents individual CSS rules
|
|
46
30
|
module Cataract
|
|
31
|
+
module Backends
|
|
32
|
+
class << self
|
|
33
|
+
attr_accessor :active
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
if %w[1 true].include?(ENV.fetch('CATARACT_PURE', nil)) || RUBY_ENGINE == 'jruby'
|
|
39
|
+
require_relative 'cataract/pure'
|
|
40
|
+
Cataract::Backends.active = Cataract::Backends::Pure
|
|
41
|
+
else
|
|
42
|
+
require_relative 'cataract/native'
|
|
43
|
+
Cataract::Backends.active = Cataract::Backends::Native
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
module Cataract
|
|
47
|
+
# Mirror the active backend's identity constants at the top level.
|
|
48
|
+
#
|
|
49
|
+
# Native is a Module (IMPLEMENTATION/COMPILE_FLAGS live on it directly);
|
|
50
|
+
# Pure is a frozen instance (they live on its class instead), so reach
|
|
51
|
+
# through .class only when active isn't already a Module itself.
|
|
52
|
+
backend_const_holder = Backends.active.is_a?(Module) ? Backends.active : Backends.active.class
|
|
53
|
+
IMPLEMENTATION = backend_const_holder::IMPLEMENTATION
|
|
54
|
+
COMPILE_FLAGS = backend_const_holder::COMPILE_FLAGS
|
|
55
|
+
NATIVE_EXTENSION_LOADED = true if defined?(Backends::Native) && Backends.active == Backends::Native
|
|
56
|
+
PURE_RUBY_LOADED = true if defined?(Backends::Pure) && Backends.active == Backends::Pure
|
|
57
|
+
|
|
47
58
|
class << self
|
|
48
59
|
# Parse a CSS string into a Stylesheet object.
|
|
49
60
|
#
|
|
@@ -75,10 +86,8 @@ module Cataract
|
|
|
75
86
|
#
|
|
76
87
|
# @see Stylesheet#parse
|
|
77
88
|
# @see Stylesheet.parse
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
Stylesheet.parse(css, **options)
|
|
81
|
-
end
|
|
89
|
+
def parse_css(css, **options)
|
|
90
|
+
Stylesheet.parse(css, **options)
|
|
82
91
|
end
|
|
83
92
|
|
|
84
93
|
# Flatten CSS rules according to CSS cascade rules.
|
|
@@ -113,9 +122,11 @@ module Cataract
|
|
|
113
122
|
#
|
|
114
123
|
# @note This is a module-level convenience method. The same functionality is available
|
|
115
124
|
# as an instance method: `stylesheet.flatten`
|
|
116
|
-
# @note Implemented in C (see ext/cataract/flatten.c)
|
|
117
125
|
#
|
|
118
126
|
# @see Stylesheet#flatten
|
|
119
|
-
|
|
127
|
+
def flatten(stylesheet_or_css)
|
|
128
|
+
stylesheet_or_css = Stylesheet.parse(stylesheet_or_css) if stylesheet_or_css.is_a?(String)
|
|
129
|
+
stylesheet_or_css.flatten
|
|
130
|
+
end
|
|
120
131
|
end
|
|
121
132
|
end
|
data/lib/tasks/profile.rake
CHANGED
|
@@ -35,7 +35,7 @@ namespace :profile do
|
|
|
35
35
|
puts "CSS size: #{css_content.bytesize} bytes"
|
|
36
36
|
puts
|
|
37
37
|
|
|
38
|
-
require_relative '../../lib/cataract
|
|
38
|
+
require_relative '../../lib/cataract'
|
|
39
39
|
require 'json'
|
|
40
40
|
|
|
41
41
|
# Use higher sampling rate (interval in microseconds, default is 1000)
|
|
@@ -74,6 +74,9 @@ namespace :profile do
|
|
|
74
74
|
abort('stackprof gem not found. Install with: gem install stackprof')
|
|
75
75
|
end
|
|
76
76
|
|
|
77
|
+
# Ensure we're using pure Ruby implementation
|
|
78
|
+
ENV['CATARACT_PURE'] = '1'
|
|
79
|
+
|
|
77
80
|
fixture_path = File.expand_path('../../test/fixtures/bootstrap.css', __dir__)
|
|
78
81
|
unless File.exist?(fixture_path)
|
|
79
82
|
abort("Fixture not found: #{fixture_path}")
|
|
@@ -94,7 +97,7 @@ namespace :profile do
|
|
|
94
97
|
puts "CSS size: #{css_content.bytesize} bytes"
|
|
95
98
|
puts
|
|
96
99
|
|
|
97
|
-
require_relative '../../lib/cataract
|
|
100
|
+
require_relative '../../lib/cataract'
|
|
98
101
|
require 'json'
|
|
99
102
|
|
|
100
103
|
# Parse once outside profiling to get stylesheet
|
|
@@ -162,7 +165,7 @@ namespace :profile do
|
|
|
162
165
|
puts "CSS size: #{css_content.bytesize} bytes"
|
|
163
166
|
puts
|
|
164
167
|
|
|
165
|
-
require_relative '../../lib/cataract
|
|
168
|
+
require_relative '../../lib/cataract'
|
|
166
169
|
require 'json'
|
|
167
170
|
|
|
168
171
|
# Parse once outside profiling to get stylesheet
|
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.
|
|
4
|
+
version: 0.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- James Cook
|
|
@@ -76,10 +76,11 @@ files:
|
|
|
76
76
|
- lib/cataract/import_resolver.rb
|
|
77
77
|
- lib/cataract/import_statement.rb
|
|
78
78
|
- lib/cataract/media_query.rb
|
|
79
|
+
- lib/cataract/native.rb
|
|
79
80
|
- lib/cataract/pure.rb
|
|
80
81
|
- lib/cataract/pure/byte_constants.rb
|
|
82
|
+
- lib/cataract/pure/declarations.rb
|
|
81
83
|
- lib/cataract/pure/flatten.rb
|
|
82
|
-
- lib/cataract/pure/helpers.rb
|
|
83
84
|
- lib/cataract/pure/parser.rb
|
|
84
85
|
- lib/cataract/pure/serializer.rb
|
|
85
86
|
- lib/cataract/pure/specificity.rb
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
# Pure Ruby CSS parser - Helper methods
|
|
4
|
-
# NO REGEXP ALLOWED - char-by-char parsing only
|
|
5
|
-
|
|
6
|
-
module Cataract
|
|
7
|
-
# Check if a byte is whitespace (space, tab, newline, CR)
|
|
8
|
-
# @param byte [Integer] Byte value from String#getbyte
|
|
9
|
-
# @return [Boolean] true if whitespace
|
|
10
|
-
def self.is_whitespace?(byte)
|
|
11
|
-
byte == BYTE_SPACE || byte == BYTE_TAB || byte == BYTE_NEWLINE || byte == BYTE_CR
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
# Check if byte is a letter (a-z, A-Z)
|
|
15
|
-
# @param byte [Integer] Byte value from String#getbyte
|
|
16
|
-
# @return [Boolean] true if letter
|
|
17
|
-
def self.letter?(byte)
|
|
18
|
-
(byte >= BYTE_LOWER_A && byte <= BYTE_LOWER_Z) ||
|
|
19
|
-
(byte >= BYTE_UPPER_A && byte <= BYTE_UPPER_Z)
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
# Check if byte is a digit (0-9)
|
|
23
|
-
# @param byte [Integer] Byte value from String#getbyte
|
|
24
|
-
# @return [Boolean] true if digit
|
|
25
|
-
def self.digit?(byte)
|
|
26
|
-
byte >= BYTE_DIGIT_0 && byte <= BYTE_DIGIT_9
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
# Check if byte is alphanumeric, hyphen, or underscore (CSS identifier char)
|
|
30
|
-
# @param byte [Integer] Byte value from String#getbyte
|
|
31
|
-
# @return [Boolean] true if valid identifier character
|
|
32
|
-
def self.ident_char?(byte)
|
|
33
|
-
letter?(byte) || digit?(byte) || byte == BYTE_HYPHEN || byte == BYTE_UNDERSCORE
|
|
34
|
-
end
|
|
35
|
-
end
|