minicss 0.1.6 → 0.1.7

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b31b0ee62d4d3638efdefc213d952351190bf264fd55161f0a31202a5017cdaf
4
- data.tar.gz: d34ac8bce2f2a7ebe262ba138213c8ad129c8295e9c5b998e195377ff8a94365
3
+ metadata.gz: 16612d43e7df5f3009024e820ff052502397894b193a68bc89132d9c495b5b25
4
+ data.tar.gz: 9647f9e3c808d1a55296d4b8f43ba6f4a251ba9d30c686fe0d97052a696ada5f
5
5
  SHA512:
6
- metadata.gz: 499001401bd13f3d0210dd808cfd89328270267427e19abd18322b07c78bfb8e014f530c9a5c8338d3025ad736de0c5430dafa2a3ab5efe8292a3ae3bd18649c
7
- data.tar.gz: fa90afda73f0ea372b8c150e5a6127c13e8b867f62f8d5c6a695924c5410c8b0630237c64469a580d9312150127db1f5097f65493e0ac27a6ab54a1b0528e00f
6
+ metadata.gz: 0cb89925ade3b7e37d9de3cc747f7dd9273490ffc7cdd09e052d65000b2286e07e6f42afda093d35f112294c413b86bc07134ac80fc6a6f2229ad0bffc9452be
7
+ data.tar.gz: 112f32326403cce9b098c2f0ca65f580e3cc075b21e656aad858e33215d79f860753da6b2c90387f516b443c906505c81b87ac35253947069c61e7ef9b729bf0
data/.rubocop.yml CHANGED
@@ -1,3 +1,5 @@
1
+ plugins: rubocop-performance
2
+
1
3
  AllCops:
2
4
  TargetRubyVersion: 3.4
3
5
  NewCops: enable
@@ -5,6 +7,7 @@ AllCops:
5
7
  Exclude:
6
8
  - spec/parsing_tests/*
7
9
  - vendor/**/*
10
+ - benchmarks/**/*
8
11
 
9
12
  Style/StringLiterals:
10
13
  EnforcedStyle: double_quotes
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 3.4.5
data/README.md CHANGED
@@ -1,14 +1,12 @@
1
1
  # MiniCSS
2
2
 
3
- MiniCSS is a pure Ruby implementation of the CSS Syntax Level 3 tokenizer,
3
+ MiniCSS is a Ruby implementation of the CSS Syntax Level 3 tokenizer,
4
4
  parser, serializer, and selector toolkit. It provides fast, dependency-free
5
- primitives for building linters, minifiers, and other CSS-aware tooling
6
- without reaching for native extensions.
5
+ primitives for building linters, minifiers, and other CSS-aware tooling.
7
6
 
8
7
  ## Features
9
8
 
10
- - Pure Ruby tokenizer and parser with zero native dependencies and support
11
- for Ruby 3.4+.
9
+ - C tokenizer and parser for Ruby 3.4+.
12
10
  - Battle-tested against the JSON-based `css-parsing-tests` suite for
13
11
  standards-compliant parsing.
14
12
  - High-level AST wrappers (`MiniCSS::AST::Rule`, `Decl`, `AtRule`, `Function`,
@@ -137,6 +135,7 @@ You can introspect the original token stream to report accurate diagnostics.
137
135
  - Clone the repository, and run `git submodule update --init` to fetch the
138
136
  required fixtures.
139
137
  - Install dependencies: `bundle install`
138
+ - Compile native extensions: `bundle exec rake compile`
140
139
  - Run the test suite: `bundle exec rspec`
141
140
  - Check style and linting: `bundle exec rubocop`
142
141
  - Run everything: `bundle exec rake`
@@ -146,6 +145,126 @@ Helpful utilities:
146
145
  - `bin/console` starts an IRB session with MiniCSS preloaded.
147
146
  - `bin/gen-specs.rb` regenerates the specs under `spec/parsing_tests` from the
148
147
  external `css-parsing-tests` fixtures.
148
+ - `benchmarks/ruby_prof.rb` runs tokenization, parsing, and serialization against
149
+ ruby-prof for spotting slow code.
150
+ - `benchmarks/stylesheet.rb` runs a benchmark for each parsing and serialization
151
+ step against Crass.
152
+ - `benchmarks/selectors.rb` runs a benchmark for selector parsing, serialization,
153
+ and specificity.
154
+
155
+
156
+ ## Benchmarks
157
+
158
+ As MiniCSS now relies on C extensions for performance, comparisons below are not
159
+ really fair, considering Crass is a pure-ruby solution. However, MiniCSS
160
+ provides support for extra CSS features and a different way of handling ASTs.
161
+
162
+ Results below are running MiniCSS and Crass on the Bootstrap 4 CSS on both
163
+ minified and unminified versions:
164
+
165
+ ### Tokenizing
166
+
167
+ > [!WARNING]
168
+ > MiniCSS uses C extension for full tokenization. Comparisons below are not
169
+ > fair.
170
+
171
+ ```
172
+ == Tokenize bootstrap-4.css ==
173
+ ruby 3.4.5 (2025-07-16 revision 20cda200d3) +PRISM [arm64-darwin24]
174
+ Warming up --------------------------------------
175
+ MiniCSS tokenize 3.000 i/100ms
176
+ Crass tokenize 1.000 i/100ms
177
+ Calculating -------------------------------------
178
+ MiniCSS tokenize 31.449 (± 3.2%) i/s (31.80 ms/i) - 159.000 in 5.058992s
179
+ Crass tokenize 12.731 (± 0.0%) i/s (78.55 ms/i) - 64.000 in 5.036126s
180
+
181
+ Comparison:
182
+ MiniCSS tokenize: 31.4 i/s
183
+ Crass tokenize: 12.7 i/s - 2.47x slower
184
+
185
+ == Tokenize bootstrap-4.min.css ==
186
+ ruby 3.4.5 (2025-07-16 revision 20cda200d3) +PRISM [arm64-darwin24]
187
+ Warming up --------------------------------------
188
+ MiniCSS tokenize 4.000 i/100ms
189
+ Crass tokenize 1.000 i/100ms
190
+ Calculating -------------------------------------
191
+ MiniCSS tokenize 39.820 (± 2.5%) i/s (25.11 ms/i) - 200.000 in 5.026530s
192
+ Crass tokenize 15.902 (± 6.3%) i/s (62.89 ms/i) - 80.000 in 5.036493s
193
+
194
+ Comparison:
195
+ MiniCSS tokenize: 39.8 i/s
196
+ Crass tokenize: 15.9 i/s - 2.50x slower
197
+ ```
198
+
199
+ ### Parsing
200
+
201
+ > [!NOTE]
202
+ > MiniCSS uses a pure-ruby implementation for this section, except for the
203
+ > `TokenStream` class, which relies on a C extension.
204
+
205
+ ```
206
+ == Parse bootstrap-4.css ==
207
+ ruby 3.4.5 (2025-07-16 revision 20cda200d3) +PRISM [arm64-darwin24]
208
+ Warming up --------------------------------------
209
+ MiniCSS parse 1.000 i/100ms
210
+ Crass parse 1.000 i/100ms
211
+ Calculating -------------------------------------
212
+ MiniCSS parse 7.837 (± 0.0%) i/s (127.61 ms/i) - 40.000 in 5.105947s
213
+ Crass parse 8.554 (±11.7%) i/s (116.90 ms/i) - 43.000 in 5.061931s
214
+
215
+ Comparison:
216
+ Crass parse: 8.6 i/s
217
+ MiniCSS parse: 7.8 i/s - same-ish: difference falls within error
218
+
219
+ == Parse bootstrap-4.min.css ==
220
+ ruby 3.4.5 (2025-07-16 revision 20cda200d3) +PRISM [arm64-darwin24]
221
+ Warming up --------------------------------------
222
+ MiniCSS parse 1.000 i/100ms
223
+ Crass parse 1.000 i/100ms
224
+ Calculating -------------------------------------
225
+ MiniCSS parse 10.086 (± 0.0%) i/s (99.15 ms/i) - 51.000 in 5.058562s
226
+ Crass parse 11.333 (± 0.0%) i/s (88.24 ms/i) - 57.000 in 5.035570s
227
+
228
+ Comparison:
229
+ Crass parse: 11.3 i/s
230
+ MiniCSS parse: 10.1 i/s - 1.12x slower
231
+ ```
232
+
233
+ ### Serializing
234
+
235
+ > [!NOTE]
236
+ > MiniCSS uses a pure-ruby implementaiton for this section. No C extensions are
237
+ > leveraged.
238
+
239
+ ```
240
+ == Serialize bootstrap-4.css ==
241
+ ruby 3.4.5 (2025-07-16 revision 20cda200d3) +PRISM [arm64-darwin24]
242
+ Warming up --------------------------------------
243
+ MiniCSS serialize 26.000 i/100ms
244
+ Crass stringify 13.000 i/100ms
245
+ Calculating -------------------------------------
246
+ MiniCSS serialize 267.680 (± 1.1%) i/s (3.74 ms/i) - 1.352k in 5.051372s
247
+ Crass stringify 134.551 (± 3.0%) i/s (7.43 ms/i) - 676.000 in 5.028420s
248
+
249
+ Comparison:
250
+ MiniCSS serialize: 267.7 i/s
251
+ Crass stringify: 134.6 i/s - 1.99x slower
252
+
253
+ == Serialize bootstrap-4.min.css ==
254
+ ruby 3.4.5 (2025-07-16 revision 20cda200d3) +PRISM [arm64-darwin24]
255
+ Warming up --------------------------------------
256
+ MiniCSS serialize 26.000 i/100ms
257
+ Crass stringify 18.000 i/100ms
258
+ Calculating -------------------------------------
259
+ MiniCSS serialize 255.343 (± 5.1%) i/s (3.92 ms/i) - 1.300k in 5.105550s
260
+ Crass stringify 181.703 (± 5.0%) i/s (5.50 ms/i) - 918.000 in 5.065818s
261
+
262
+ Comparison:
263
+ MiniCSS serialize: 255.3 i/s
264
+ Crass stringify: 181.7 i/s - 1.41x slower
265
+ ```
266
+
267
+
149
268
 
150
269
  ## Contributing
151
270
 
data/Rakefile CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  require "bundler/gem_tasks"
4
4
  require "rspec/core/rake_task"
5
+ require "rake/extensiontask"
5
6
 
6
7
  RSpec::Core::RakeTask.new(:spec)
7
8
 
@@ -9,4 +10,27 @@ require "rubocop/rake_task"
9
10
 
10
11
  RuboCop::RakeTask.new
11
12
 
12
- task default: %i[spec rubocop]
13
+ task default: %i[compile spec rubocop]
14
+
15
+ namespace :bench do
16
+ desc "Run stylesheet benchmarks"
17
+ task :stylesheet do
18
+ ruby "benchmarks/stylesheet.rb"
19
+ end
20
+
21
+ desc "Run selector benchmarks"
22
+ task :selectors do
23
+ ruby "benchmarks/selectors.rb"
24
+ end
25
+ end
26
+
27
+ desc "Run all benchmarks"
28
+ task bench: %w[bench:stylesheet bench:selectors]
29
+
30
+ Rake::ExtensionTask.new("minicss_scanner") do |ext|
31
+ ext.lib_dir = "lib"
32
+ end
33
+
34
+ Rake::ExtensionTask.new("minicss_token_stream") do |ext|
35
+ ext.lib_dir = "lib"
36
+ end