squoosh 0.3.1 → 0.3.2

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 (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: []