p_css 0.3.0 → 0.3.1

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: 56d14cfeff071d56fbc439f7dc2ad0cd9827bcc21ff1ff26b5d459e832855a91
4
- data.tar.gz: 5c576b9cccd85b7be148ed868a90b90072e164a69e317ce56ecdb921e731d3be
3
+ metadata.gz: 223962d85169a337ff087e759a5bce186ece7182cd15ead418c280228fdde208
4
+ data.tar.gz: 4ccd0ca9e312dec47fc8f41f4d0b02d6918f86c47279d463f1c6c3e2e75549b8
5
5
  SHA512:
6
- metadata.gz: badef00c5dc20716c989010581b364ede57d843bf4e31d4263d66e001eb7150f1e7f7f8572a4b53ffa6f49d897f93d93f47bc23ee92d7017b3489fa2475de134
7
- data.tar.gz: 98ac482f74beb6fe2726cd8876083402e3995127d7a2205bc5c94063efe5d63bfc0f799d0dee7c5645ad4039af8f567b064e3d71e522e2e7cdb74d9162d39955
6
+ metadata.gz: 9a4e563505c86e0939c03410c1d75be48b5fc1e9b9ada13dc422ee0b290dba215a94d4cd5dced0c2c4984cd15770bd2797b667436b77709766e7c9d64b750280
7
+ data.tar.gz: dae2b3b18a78f04eb9dc9babd31e0b1f7e17102740f2fd4cfe34112b24095c8d2c1453e2e67ffb0cd91949d31c35ea4ef42d71c620d8cc0c86cfb67632592f18
data/lib/css/cascade.rb CHANGED
@@ -18,7 +18,10 @@ module CSS
18
18
  # not modeled — `@layer`, `@supports`, `@container`, `@scope`, and
19
19
  # `@starting-style` blocks are descended into unconditionally.
20
20
  class Cascade
21
- Match = Data.define(:declaration, :specificity, :inline, :order)
21
+ # Allocated once per matching declaration on every resolve; Struct
22
+ # constructs noticeably faster than Data, and Match never escapes
23
+ # `resolve`, so it doesn't need Data's immutability guarantees.
24
+ Match = Struct.new(:declaration, :specificity, :inline, :order)
22
25
 
23
26
  RuleEntry = Data.define(:selector_pairs, :declarations)
24
27
 
@@ -56,14 +59,14 @@ module CSS
56
59
 
57
60
  entry.declarations.each do |decl|
58
61
  order += 1
59
- matches << Match.new(declaration: decl, specificity: spec, inline: false, order: order)
62
+ matches << Match.new(decl, spec, false, order)
60
63
  end
61
64
  end
62
65
 
63
66
  if inline_style
64
67
  inline_declarations(inline_style).each do |decl|
65
68
  order += 1
66
- matches << Match.new(declaration: decl, specificity: Selectors::Specificity::ZERO, inline: true, order: order)
69
+ matches << Match.new(decl, Selectors::Specificity::ZERO, true, order)
67
70
  end
68
71
  end
69
72
 
@@ -216,6 +219,14 @@ module CSS
216
219
  end
217
220
 
218
221
  def best_matching_specificity(element, selector_pairs, cache, state)
222
+ # The single-selector case is the dominant shape in real stylesheets
223
+ # (`.foo { ... }`, `div > a { ... }`), so skip the each/block frame
224
+ # and the running-max compare for it.
225
+ if selector_pairs.size == 1
226
+ sel, spec = selector_pairs[0]
227
+ return Selectors::Matcher.matches?(element, sel, cache: cache, state: state) ? spec : nil
228
+ end
229
+
219
230
  best = nil
220
231
 
221
232
  selector_pairs.each do |sel, spec|
data/lib/css/parser.rb CHANGED
@@ -105,7 +105,7 @@ module CSS
105
105
  groups = []
106
106
  current = []
107
107
 
108
- loop do
108
+ while true
109
109
  case peek.type
110
110
  when :eof
111
111
  groups << current
@@ -151,7 +151,7 @@ module CSS
151
151
  def consume_rule_list(top_level:)
152
152
  rules = []
153
153
 
154
- loop do
154
+ while true
155
155
  t = peek
156
156
 
157
157
  case t.type
@@ -183,7 +183,7 @@ module CSS
183
183
  prelude = []
184
184
  block = nil
185
185
 
186
- loop do
186
+ while true
187
187
  t = peek
188
188
 
189
189
  case t.type
@@ -214,7 +214,7 @@ module CSS
214
214
  def consume_qualified_rule(nested:)
215
215
  prelude = []
216
216
 
217
- loop do
217
+ while true
218
218
  t = peek
219
219
 
220
220
  case t.type
@@ -254,7 +254,7 @@ module CSS
254
254
  def collect_block_items(stop_at_close_brace:)
255
255
  items = []
256
256
 
257
- loop do
257
+ while true
258
258
  t = peek
259
259
 
260
260
  case t.type
@@ -306,7 +306,7 @@ module CSS
306
306
 
307
307
  value = []
308
308
 
309
- loop do
309
+ while true
310
310
  t = peek
311
311
 
312
312
  case t.type
@@ -350,7 +350,7 @@ module CSS
350
350
  end_type = BRACKET_CLOSE_TYPE.fetch(open_type)
351
351
  values = []
352
352
 
353
- loop do
353
+ while true
354
354
  t = peek
355
355
 
356
356
  case t.type
@@ -371,7 +371,7 @@ module CSS
371
371
  name = consume.value
372
372
  values = []
373
373
 
374
- loop do
374
+ while true
375
375
  t = peek
376
376
 
377
377
  case t.type
@@ -99,7 +99,17 @@ module CSS
99
99
  end
100
100
 
101
101
  def match_compound(element, compound, cache, state)
102
- compound.components.all? { match_simple(element, _1, cache, state) }
102
+ components = compound.components
103
+ i = 0
104
+ n = components.size
105
+
106
+ while i < n
107
+ return false unless match_simple(element, components[i], cache, state)
108
+
109
+ i += 1
110
+ end
111
+
112
+ true
103
113
  end
104
114
 
105
115
  def match_simple(element, simple, cache, state)
@@ -285,7 +295,12 @@ module CSS
285
295
  return nil if p.nil?
286
296
 
287
297
  siblings = element_children(p)
288
- siblings = siblings.select { tag(_1).casecmp?(tag(element)) } if of_type
298
+
299
+ if of_type
300
+ own_tag = tag(element)
301
+ siblings = siblings.select { tag(_1) == own_tag }
302
+ end
303
+
289
304
  siblings = siblings.reverse if from_end
290
305
 
291
306
  idx = siblings.index { same_node?(_1, element) }
data/lib/css/token.rb CHANGED
@@ -15,12 +15,12 @@ module CSS
15
15
  colon semicolon comma
16
16
  lbracket rbracket lparen rparen lbrace rbrace
17
17
  eof
18
- ].freeze
18
+ ].to_h { [_1, true] }.freeze
19
19
 
20
20
  attr_reader :type, :value, :flag, :unit
21
21
 
22
22
  def initialize(type, value = nil, flag: nil, unit: nil, position: nil)
23
- raise ArgumentError, "unknown token type: #{type.inspect}" unless TYPES.include?(type)
23
+ raise ArgumentError, "unknown token type: #{type.inspect}" unless TYPES[type]
24
24
 
25
25
  @type = type
26
26
  @value = value
data/lib/css/tokenizer.rb CHANGED
@@ -34,7 +34,7 @@ module CSS
34
34
  def tokenize
35
35
  tokens = []
36
36
 
37
- loop do
37
+ while true
38
38
  token = next_token
39
39
  break if token.type == :eof
40
40
 
@@ -45,7 +45,7 @@ module CSS
45
45
  end
46
46
 
47
47
  def next_token
48
- consume_comments unless @preserve_comments
48
+ consume_comments if !@preserve_comments && @chars[@pos] == '/'
49
49
 
50
50
  return Token.new(:eof) if @pos >= @length
51
51
 
@@ -62,7 +62,7 @@ module CSS
62
62
 
63
63
  c = consume
64
64
 
65
- return consume_whitespace if whitespace?(c)
65
+ return consume_whitespace if c == ' ' || c == "\n" || c == "\t"
66
66
  return consume_string_token(c) if c == '"' || c == "'"
67
67
 
68
68
  if (c == '+' || c == '-' || c == '.') && number_starts?(c, peek, peek(1))
@@ -252,7 +252,9 @@ module CSS
252
252
  end
253
253
 
254
254
  def consume_whitespace
255
- consume while whitespace?(peek)
255
+ while (c = @chars[@pos]) && (c == ' ' || c == "\n" || c == "\t")
256
+ @pos += 1
257
+ end
256
258
 
257
259
  Token.new(:whitespace)
258
260
  end
@@ -261,7 +263,7 @@ module CSS
261
263
  def consume_string_token(ending)
262
264
  buf = +''
263
265
 
264
- loop do
266
+ while true
265
267
  c = consume
266
268
 
267
269
  case c
@@ -306,22 +308,41 @@ module CSS
306
308
  end
307
309
  end
308
310
 
309
- # §4.3.11.
311
+ # §4.3.11. Fast path: walk @chars while the run is pure ident code points,
312
+ # then slice and return. Escapes (rare in real CSS) switch to a buf-based
313
+ # slow path that mirrors the spec's append-each-char semantics.
310
314
  def consume_ident_sequence
311
- buf = +''
315
+ start = @pos
316
+ c = nil
312
317
 
313
- loop do
314
- c = consume
318
+ while (c = @chars[@pos])
319
+ o = c.ord
320
+ break unless o >= 128 || IDENT_CP_TABLE[o]
321
+
322
+ @pos += 1
323
+ end
324
+
325
+ return @chars[start, @pos - start].join unless c == '\\' && (n = @chars[@pos + 1]) && n != "\n"
326
+
327
+ buf = @chars[start, @pos - start].join.dup
328
+ @pos += 1
329
+ buf << consume_escaped_code_point
330
+
331
+ while (c = @chars[@pos])
332
+ o = c.ord
315
333
 
316
- if ident_code_point?(c)
334
+ if o >= 128 || IDENT_CP_TABLE[o]
317
335
  buf << c
318
- elsif valid_escape?(c, peek)
336
+ @pos += 1
337
+ elsif c == '\\' && (n = @chars[@pos + 1]) && n != "\n"
338
+ @pos += 1
319
339
  buf << consume_escaped_code_point
320
340
  else
321
- reconsume unless c.nil?
322
- return buf
341
+ break
323
342
  end
324
343
  end
344
+
345
+ buf
325
346
  end
326
347
 
327
348
  # §4.3.4.
@@ -355,7 +376,7 @@ module CSS
355
376
 
356
377
  consume while whitespace?(peek)
357
378
 
358
- loop do
379
+ while true
359
380
  c = consume
360
381
 
361
382
  case c
@@ -396,7 +417,7 @@ module CSS
396
417
 
397
418
  # §4.3.14.
398
419
  def consume_bad_url_remnants
399
- loop do
420
+ while true
400
421
  c = consume
401
422
 
402
423
  return if c.nil? || c == ')'
@@ -419,17 +440,27 @@ module CSS
419
440
  end
420
441
  end
421
442
 
422
- # §4.3.12. Returns [numeric_value, :integer | :number].
443
+ # §4.3.12. Returns [numeric_value, :integer | :number]. The three digit
444
+ # runs inline DIGIT_TABLE so the loop bodies stay in the same frame.
423
445
  def consume_number
424
446
  repr = +''
425
447
  flag = :integer
426
448
 
427
449
  repr << consume if peek == '+' || peek == '-'
428
- repr << consume while digit?(peek)
450
+
451
+ while (c = @chars[@pos]) && (o = c.ord) < 128 && DIGIT_TABLE[o]
452
+ repr << c
453
+ @pos += 1
454
+ end
429
455
 
430
456
  if peek == '.' && digit?(peek(1))
431
457
  repr << consume
432
- repr << consume while digit?(peek)
458
+
459
+ while (c = @chars[@pos]) && (o = c.ord) < 128 && DIGIT_TABLE[o]
460
+ repr << c
461
+ @pos += 1
462
+ end
463
+
433
464
  flag = :number
434
465
  end
435
466
 
@@ -437,7 +468,12 @@ module CSS
437
468
  (digit?(peek(1)) || ((peek(1) == '+' || peek(1) == '-') && digit?(peek(2))))
438
469
  repr << consume
439
470
  repr << consume if peek == '+' || peek == '-'
440
- repr << consume while digit?(peek)
471
+
472
+ while (c = @chars[@pos]) && (o = c.ord) < 128 && DIGIT_TABLE[o]
473
+ repr << c
474
+ @pos += 1
475
+ end
476
+
441
477
  flag = :number
442
478
  end
443
479
 
data/lib/css/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module CSS
2
- VERSION = '0.3.0'
2
+ VERSION = '0.3.1'
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: p_css
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Keita Urashima