squoosh 0.3.1 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (5) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +5 -3
  3. data/lib/squoosh.rb +106 -67
  4. data/lib/squoosh/version.rb +1 -1
  5. metadata +22 -8
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8db4818a215da1002e475a6ab271f274448d983ec4f9b90aff346bd08705c6c2
4
- data.tar.gz: 3155d597ba38ce21b1fcb59c6550bff5c76fc50b9b8ab63d251588a83448b063
3
+ metadata.gz: 8ad27922ec33d0ecfea5e58f69ce3a39ea9b1a62732e8a4db9725443dbdbe97b
4
+ data.tar.gz: 7dc0576cdd2206091677ee36ea6b836ad537ee5527e83309b649314c51100ddf
5
5
  SHA512:
6
- metadata.gz: 6f4147816e466cfa7b1da925fb064ea65c3fec6ee3e8678b3afd8a2cb41a2fc40bea9825320fe67d3692dccd2ba14ff913f308672a9575d25e07a84f51a33a13
7
- data.tar.gz: 693b6d9d3d20fe099926c67b571b53b9955d2ab2d2700c2b8b912b848729d14a6fda0c04fbc29414a08e43aa7efa29b042f45229021ebcc9493710fd771c639d
6
+ metadata.gz: 24d38fd5136f531d5ac21aec36fb71b031803f52a6786f313eb5d5aa31469d5fd6cae4d3a873ede1c7404758053e639ec792b1c1d315caaa6470c35443f99897
7
+ data.tar.gz: 8dac02921bebd2bc963352ce9173dc53b6eae041de2ccc44d4a3fecd8e89de02f3a854cfa91ff24f833f87519675b2f699f41cd3e36ace652110f1323bedc531
data/README.md CHANGED
@@ -1,10 +1,12 @@
1
+ [![Travis-CI Build
2
+ Status](https://travis-ci.org/stevecheckoway/squoosh.svg)](https://travis-ci.org/stevecheckoway/squoosh)
3
+ [![Coverage
4
+ Status](https://coveralls.io/repos/github/stevecheckoway/squoosh/badge.svg?branch=master)](https://coveralls.io/github/stevecheckoway/squoosh?branch=master)
5
+
1
6
  # Squoosh
2
7
 
3
8
  Minifies HTML, JavaScript, and CSS, including inline JavaScript and CSS.
4
9
 
5
- [![Travis-CI Build
6
- Status](https://travis-ci.org/stevecheckoway/squoosh.svg)](https://travis-ci.org/stevecheckoway/squoosh)
7
-
8
10
  CSS minification is handled by [Sassc](http://www.rubydoc.info/gems/sassc)
9
11
  whereas JavaScript minification is handled by
10
12
  [Uglifier](http://www.rubydoc.info/gems/uglifier) which requires node.js.
@@ -204,6 +204,7 @@ module Squoosh
204
204
  false
205
205
  end
206
206
 
207
+ # rubocop:disable Style/StringConcatenation
207
208
  EVENT_HANDLERS_XPATH = (
208
209
  # Select all attribute nodes whose names start with "on";
209
210
  '//@*[starts-with(name(),"on")]' +
@@ -233,6 +234,7 @@ module Squoosh
233
234
  ')' \
234
235
  ']'
235
236
  ).freeze
237
+ # rubocop:enable Style/StringConcatenation
236
238
  private_constant :EVENT_HANDLERS_XPATH
237
239
 
238
240
  def uglify(content, options)
@@ -345,7 +347,7 @@ module Squoosh
345
347
  # value.gsub!(/&([a-zA-Z0-9]+;|#[0-9]+|#[xX][a-fA-F0-9]+)/, '&\1')
346
348
  value = (attr.value || '').gsub('&', '&')
347
349
  if value.empty?
348
- output << ' ' + name
350
+ output << " #{name}"
349
351
  elsif /[\t\n\f\r "'`=<>]/ !~ value
350
352
  last_attr_unquoted = true
351
353
  output << " #{name}=#{value}"
@@ -391,15 +393,17 @@ module Squoosh
391
393
 
392
394
  uri = ns.href
393
395
  if uri == Nokogiri::HTML5::XML_NAMESPACE
394
- 'xml:' + attr.name
396
+ "xml:#{attr.name}"
395
397
  elsif uri == Nokogiri::HTML5::XMLNS_NAMESPACE && attr.name == 'xmlns'
396
398
  'xmlns'
397
399
  elsif uri == Nokogiri::HTML5::XMLNS_NAMESPACE
398
- 'xmlns:' + attr.name
400
+ "xmlns:#{attr.name}"
399
401
  elsif uri == Nokogiri::HTML5::XLINK_NAMESPACE
400
- 'xlink:' + attr.name
402
+ "xlink:#{attr.name}"
401
403
  else
404
+ # :nocov:
402
405
  raise 'Unreachable!'
406
+ # :nocov:
403
407
  end
404
408
  end
405
409
 
@@ -411,6 +415,53 @@ module Squoosh
411
415
  foreign_element?(node) && node.children.empty?
412
416
  end
413
417
 
418
+ def content_node?(node)
419
+ # Inter-element whitespace, comment nodes, and processing instruction
420
+ # nodes must be ignored when establishing whether an element's contents
421
+ # match the element's content model or not, and must be ignored when
422
+ # following algorithms that define document and element semantics.
423
+ !(node.comment? ||
424
+ node.processing_instruction? ||
425
+ inter_element_whitespace?(node))
426
+ end
427
+
428
+ def previous_sibling_content_node(node)
429
+ while (node = node.previous_sibling)
430
+ return node if content_node?(node)
431
+ end
432
+ nil
433
+ end
434
+
435
+ def next_sibling_content_node(node)
436
+ while (node = node.next_sibling)
437
+ return node if content_node?(node)
438
+ end
439
+ nil
440
+ end
441
+
442
+ def first_child_content_node(node)
443
+ return nil if node.children.empty?
444
+
445
+ node = node.children[0]
446
+ return node if content_node?(node)
447
+
448
+ next_sibling_content_node(node)
449
+ end
450
+
451
+ def next_sibling_is_nil_or_one_of?(node, elements)
452
+ node = next_sibling_content_node(node)
453
+ node.nil? || (node.element? && elements.include?(node.name))
454
+ end
455
+
456
+ def next_sibling_is_one_of?(node, elements)
457
+ node = next_sibling_content_node(node)
458
+ node&.element? && elements.include?(node.name)
459
+ end
460
+
461
+ def parent_contains_more_content?(node)
462
+ !next_sibling_content_node(node).nil?
463
+ end
464
+
414
465
  def omit_start_tag?(node)
415
466
  return false unless @options[:omit_tags]
416
467
  return false unless node.attributes.empty?
@@ -445,37 +496,26 @@ module Squoosh
445
496
  # inside the colgroup element is a col element, and if the element is
446
497
  # not immediately preceded by another colgroup element whose end tag
447
498
  # has been omitted. (It can't be omitted if the element is empty.)
448
- return false if node.children.empty?
449
- return false unless node.children[0].name == 'col'
499
+ child = first_child_content_node(node)
500
+ return false if child.nil? || !child.element? || child.name != 'col'
450
501
 
451
- prev_elm = node.previous_element
452
- return prev_elm.nil? ||
453
- prev_elm.name != 'col' ||
454
- !omit_end_tag?(prev_elm)
502
+ prev_node = previous_sibling_content_node(node)
503
+ return !(prev_node&.element? &&
504
+ prev_node.name == 'colgroup' &&
505
+ omit_end_tag?(prev_node))
455
506
 
456
507
  when 'tbody'
457
508
  # A tbody element's start tag may be omitted if the first thing inside
458
509
  # the tbody element is a tr element, and if the element is not
459
510
  # immediately preceded by a tbody, thead, or tfoot element whose end
460
511
  # tag has been omitted. (It can't be omitted if the element is empty.)
461
- return false if node.children.empty?
462
- return false unless node.children[0].name == 'tr'
512
+ child = first_child_content_node(node)
513
+ return false if child.nil? || !child.element? || child.name != 'tr'
463
514
 
464
- prev_elm = node.previous_element
465
- return prev_elm.nil? ||
466
- !%w[tbody thead tfoot].include?(prev_elm.name) ||
467
- !omit_end_tag?(prev_elm)
468
- end
469
- false
470
- end
471
-
472
- def parent_contains_more_content?(node)
473
- while (node = node.next_sibling)
474
- next if node.comment?
475
- next if node.processing_instruction?
476
- next if inter_element_whitespace? node
477
-
478
- return true
515
+ prev_node = previous_sibling_content_node(node)
516
+ return !(prev_node&.element? &&
517
+ %w[tbody thead tfoot].include?(prev_node.name) &&
518
+ omit_end_tag?(prev_node))
479
519
  end
480
520
  false
481
521
  end
@@ -486,7 +526,6 @@ module Squoosh
486
526
  return false if node.parent.name == 'noscript'
487
527
 
488
528
  next_node = node.next_sibling
489
- next_elm = node.next_element
490
529
  case node.name
491
530
  when 'html'
492
531
  # An html element's end tag may be omitted if the html element is not
@@ -509,33 +548,40 @@ module Squoosh
509
548
  # An li element's end tag may be omitted if the li element is
510
549
  # immediately followed by another li element or if there is no more
511
550
  # content in the parent element.
512
- return next_elm&.name == 'li' || !parent_contains_more_content?(node)
551
+ return next_sibling_is_nil_or_one_of?(node, ['li'])
513
552
 
514
553
  when 'dt'
515
554
  # A dt element's end tag may be omitted if the dt element is immediately
516
555
  # followed by another dt element or a dd element.
517
- return %w[dt dd].include? next_elm&.name
556
+ return next_sibling_is_one_of?(node, %w[dt dd])
518
557
 
519
558
  when 'dd'
520
559
  # A dd element's end tag may be omitted if the dd element is immediately
521
560
  # followed by another dd element or a dt element, or if there is no more
522
561
  # content in the parent element.
523
- return %w[dt dd].include?(next_elm&.name) ||
524
- !parent_contains_more_content?(node)
562
+ return next_sibling_is_nil_or_one_of?(node, %w[dt dd])
525
563
 
526
564
  when 'p'
527
- # A p element's end tag may be omitted if the p element is immediately
528
- # followed by an address, article, aside, blockquote, div, dl,
529
- # fieldset, footer, form, h1, h2, h3, h4, h5, h6, header, hgroup, hr,
530
- # main, nav, ol, p, pre, section, table, or ul, element, or if there
531
- # is no more content in the parent element and the parent element is
532
- # not an a element.
533
- return true if %w[address article aside blockquote div dl
534
- fieldset footer form h1 h2 h3 h4
535
- h5 h6 header hgroup hr main nav ol
536
- p pre section table ul].include? next_elm&.name
537
-
538
- return node.parent.name != 'a' && !parent_contains_more_content?(node)
565
+ # A p element's end tag can be omitted if the p element is immediately
566
+ # followed by an address, article, aside, blockquote, details, div,
567
+ # dl, fieldset, figcaption, figure, footer, form, h1, h2, h3, h4, h5,
568
+ # h6, header, hgroup, hr, main, menu, nav, ol, p, pre, section, table,
569
+ # or ul element, or if there is no more content in the parent element
570
+ # and the parent element is an HTML element that is not an a, audio,
571
+ # del, ins, map, noscript, or video element, or an autonomous custom
572
+ # element.
573
+ return true if next_sibling_is_one_of?(
574
+ node,
575
+ %w[
576
+ address article aside blockquote details div dl fieldset figcaption
577
+ figure footer form h1 h2 h3 h4 h5 h6 header hgroup hr main menu nav
578
+ ol p pre section table ul
579
+ ]
580
+ )
581
+ return false if foreign_element?(node.parent)
582
+
583
+ return !parent_contains_more_content?(node) &&
584
+ !%(a audio del ins map noscript video).include?(node.parent.name)
539
585
 
540
586
  when 'rb', 'rt', 'rp'
541
587
  # An rb element's end tag may be omitted if the rb element is
@@ -549,62 +595,56 @@ module Squoosh
549
595
  # An rp element's end tag may be omitted if the rp element is
550
596
  # immediately followed by an rb, rt, rtc or rp element, or if there is
551
597
  # no more content in the parent element.
552
- return %w[rb rt rtc rp].include?(next_elm&.name) ||
553
- !parent_contains_more_content?(node)
598
+ return next_sibling_is_nil_or_one_of?(node, %w[rb rt rtc rp])
599
+
554
600
  when 'rtc'
555
601
  # An rtc element's end tag may be omitted if the rtc element is
556
602
  # immediately followed by an rb, rtc or rp element, or if there is no
557
603
  # more content in the parent element.
558
- return %w[rb rtc rp].include?(next_elm&.name) ||
559
- !parent_contains_more_content?(node)
604
+ return next_sibling_is_nil_or_one_of?(node, %w[rb rtc rp])
560
605
 
561
606
  when 'optgroup'
562
607
  # An optgroup element's end tag may be omitted if the optgroup element
563
608
  # is immediately followed by another optgroup element, or if there is
564
609
  # no more content in the parent element.
565
- return next_elm&.name == 'optgroup' ||
566
- !parent_contains_more_content?(node)
610
+ return next_sibling_is_nil_or_one_of?(node, ['optgroup'])
567
611
 
568
612
  when 'option'
569
613
  # An option element's end tag may be omitted if the option element is
570
614
  # immediately followed by another option element, or if it is
571
615
  # immediately followed by an optgroup element, or if there is no more
572
616
  # content in the parent element.
573
- return %w[option optgroup].include?(next_elm&.name) ||
574
- !parent_contains_more_content?(node)
617
+ return next_sibling_is_nil_or_one_of?(node, %w[option optgroup])
575
618
 
576
619
  when 'colgroup'
577
620
  # A colgroup element's end tag may be omitted if the colgroup element is
578
621
  # not immediately followed by a space character or a comment.
579
- return next_node.nil? ||
580
- (next_node.text? && !next_node.content.start_with(' ')) ||
581
- !next_node.comment?
622
+ return true if next_node.nil?
623
+ return !next_node.content.start_with?(' ') if next_node.text?
624
+
625
+ return !next_node.comment?
582
626
 
583
627
  when 'thead'
584
628
  # A thead element's end tag may be omitted if the thead element is
585
629
  # immediately followed by a tbody or tfoot element.
586
- return %w[tbody tfoot].include? next_elm&.name
630
+ return next_sibling_is_one_of?(node, %w[tbody tfoot])
587
631
 
588
632
  when 'tbody'
589
633
  # A tbody element's end tag may be omitted if the tbody element is
590
634
  # immediately followed by a tbody or tfoot element, or if there is no
591
635
  # more content in the parent element.
592
- return %w[tbody tfoot].include?(next_elm&.name) ||
593
- !parent_contains_more_content?(node)
636
+ return next_sibling_is_nil_or_one_of?(node, %w[tbody tfoot])
594
637
 
595
638
  when 'tfoot'
596
- # A tfoot element's end tag may be omitted if the tfoot element is
597
- # immediately followed by a tbody element, or if there is no more
598
- # content in the parent element.
599
- return next_elm&.name == 'tbody' ||
600
- !parent_contains_more_content?(node)
639
+ # A tfoot element's end tag can be omitted if there is no more content
640
+ # in the parent element.
641
+ return !parent_contains_more_content?(node)
601
642
 
602
643
  when 'tr'
603
644
  # A tr element's end tag may be omitted if the tr element is immediately
604
645
  # followed by another tr element, or if there is no more content in the
605
646
  # parent element.
606
- return next_elm&.name == 'tr' ||
607
- !parent_contains_more_content?(node)
647
+ return next_sibling_is_nil_or_one_of?(node, ['tr'])
608
648
 
609
649
  when 'td', 'th'
610
650
  # A td element's end tag may be omitted if the td element is immediately
@@ -614,8 +654,7 @@ module Squoosh
614
654
  # A th element's end tag may be omitted if the th element is immediately
615
655
  # followed by a td or th element, or if there is no more content in the
616
656
  # parent element.
617
- return %w[td th].include?(next_elm&.name) ||
618
- !parent_contains_more_content?(node)
657
+ return next_sibling_is_nil_or_one_of?(node, %w[td th])
619
658
  end
620
659
  false
621
660
  end
@@ -2,5 +2,5 @@
2
2
 
3
3
  module Squoosh
4
4
  # The version of squoosh.
5
- VERSION = '0.3.1'
5
+ VERSION = '0.3.2'
6
6
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: squoosh
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stephen Checkoway
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-08-23 00:00:00.000000000 Z
11
+ date: 2020-08-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: coveralls
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: rake
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -136,7 +150,7 @@ dependencies:
136
150
  - - "~>"
137
151
  - !ruby/object:Gem::Version
138
152
  version: '4.1'
139
- description:
153
+ description:
140
154
  email:
141
155
  - s@pahtak.org
142
156
  executables: []
@@ -155,7 +169,7 @@ metadata:
155
169
  changelog_uri: https://github.com/stevecheckoway/squoosh/blob/master/CHANGELOG.md
156
170
  homepage_uri: https://github.com/stevecheckoway/squoosh
157
171
  source_code_uri: https://github.com/stevecheckoway/squoosh
158
- post_install_message:
172
+ post_install_message:
159
173
  rdoc_options: []
160
174
  require_paths:
161
175
  - lib
@@ -163,15 +177,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
163
177
  requirements:
164
178
  - - "~>"
165
179
  - !ruby/object:Gem::Version
166
- version: '2.3'
180
+ version: '2.5'
167
181
  required_rubygems_version: !ruby/object:Gem::Requirement
168
182
  requirements:
169
183
  - - ">="
170
184
  - !ruby/object:Gem::Version
171
185
  version: '0'
172
186
  requirements: []
173
- rubygems_version: 3.0.6
174
- signing_key:
187
+ rubygems_version: 3.1.2
188
+ signing_key:
175
189
  specification_version: 4
176
190
  summary: Minify HTML/CSS/JavaScript files.
177
191
  test_files: []