govspeak 6.5.0 → 6.5.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +24 -2
  3. data/README.md +6 -5
  4. data/Rakefile +7 -4
  5. data/lib/govspeak.rb +116 -116
  6. data/lib/govspeak/header_extractor.rb +1 -1
  7. data/lib/govspeak/html_sanitizer.rb +12 -9
  8. data/lib/govspeak/kramdown_overrides.rb +2 -2
  9. data/lib/govspeak/link_extractor.rb +6 -6
  10. data/lib/govspeak/post_processor.rb +34 -14
  11. data/lib/govspeak/presenters/attachment_presenter.rb +39 -39
  12. data/lib/govspeak/presenters/contact_presenter.rb +2 -2
  13. data/lib/govspeak/presenters/h_card_presenter.rb +3 -3
  14. data/lib/govspeak/presenters/image_presenter.rb +4 -4
  15. data/lib/govspeak/structured_header_extractor.rb +2 -2
  16. data/lib/govspeak/version.rb +1 -1
  17. data/lib/kramdown/parser/govuk.rb +6 -7
  18. data/test/blockquote_extra_quote_remover_test.rb +24 -26
  19. data/test/govspeak_attachment_link_test.rb +0 -2
  20. data/test/govspeak_attachment_test.rb +0 -2
  21. data/test/govspeak_attachments_image_test.rb +12 -14
  22. data/test/govspeak_attachments_inline_test.rb +22 -24
  23. data/test/govspeak_button_test.rb +29 -31
  24. data/test/govspeak_contacts_test.rb +29 -31
  25. data/test/govspeak_extract_contact_content_ids_test.rb +1 -3
  26. data/test/govspeak_images_bang_test.rb +37 -39
  27. data/test/govspeak_images_test.rb +43 -45
  28. data/test/govspeak_link_extractor_test.rb +1 -1
  29. data/test/govspeak_link_test.rb +1 -3
  30. data/test/govspeak_structured_headers_test.rb +7 -6
  31. data/test/govspeak_table_with_headers_test.rb +68 -21
  32. data/test/govspeak_test.rb +98 -101
  33. data/test/govspeak_test_helper.rb +1 -1
  34. data/test/html_sanitizer_test.rb +17 -9
  35. data/test/html_validator_test.rb +2 -2
  36. data/test/presenters/h_card_presenter_test.rb +39 -41
  37. data/test/test_helper.rb +12 -8
  38. metadata +52 -40
@@ -49,7 +49,7 @@ module GovspeakTestHelper
49
49
  lines = text.split "\n"
50
50
  digits = Math.log10(lines.size + 2).ceil
51
51
  lines.map
52
- .with_index { |line, i| "%<number>#{digits}d: %<line>s" % { number: i + 1, line: line } }
52
+ .with_index { |line, i| sprintf("%<number>#{digits}d: %<line>s", number: i + 1, line: line) }
53
53
  .join("\n")
54
54
  end
55
55
  end
@@ -31,7 +31,7 @@ class HtmlSanitizerTest < Minitest::Test
31
31
  html = "<a href='#' data-module='cross-domain-tracking' data-tracking-code='UA-XXXXXX-Y' data-tracking-name='govspeakButtonTracker'></a>"
32
32
  assert_equal(
33
33
  "<a href=\"#\" data-module=\"cross-domain-tracking\" data-tracking-code=\"UA-XXXXXX-Y\" data-tracking-name=\"govspeakButtonTracker\"></a>",
34
- Govspeak::HtmlSanitizer.new(html).sanitize
34
+ Govspeak::HtmlSanitizer.new(html).sanitize,
35
35
  )
36
36
  end
37
37
 
@@ -40,19 +40,28 @@ class HtmlSanitizerTest < Minitest::Test
40
40
 
41
41
  assert_equal(
42
42
  "<a href=\"/\" data-module=\"track-click\" data-ecommerce-path=\"/\" data-track-category=\"linkClicked\">Test Link</a>",
43
- Govspeak::HtmlSanitizer.new(html).sanitize
43
+ Govspeak::HtmlSanitizer.new(html).sanitize,
44
+ )
45
+ end
46
+
47
+ test "allow data attributes on divs" do
48
+ html = "<div data-module='toggle' data-ecommerce-path='/' data-track-category='someDiv'>Test Div</div>"
49
+
50
+ assert_equal(
51
+ "<div data-module=\"toggle\" data-ecommerce-path=\"/\" data-track-category=\"someDiv\">Test Div</div>",
52
+ Govspeak::HtmlSanitizer.new(html).sanitize,
44
53
  )
45
54
  end
46
55
 
47
56
  test "allows images on whitelisted domains" do
48
57
  html = "<img src='http://allowed.com/image.jgp'>"
49
- sanitized_html = Govspeak::HtmlSanitizer.new(html, allowed_image_hosts: ['allowed.com']).sanitize
58
+ sanitized_html = Govspeak::HtmlSanitizer.new(html, allowed_image_hosts: ["allowed.com"]).sanitize
50
59
  assert_equal "<img src=\"http://allowed.com/image.jgp\">", sanitized_html
51
60
  end
52
61
 
53
62
  test "removes images not on whitelisted domains" do
54
63
  html = "<img src='http://evil.com/image.jgp'>"
55
- assert_equal "", Govspeak::HtmlSanitizer.new(html, allowed_image_hosts: ['allowed.com']).sanitize
64
+ assert_equal "", Govspeak::HtmlSanitizer.new(html, allowed_image_hosts: ["allowed.com"]).sanitize
56
65
  end
57
66
 
58
67
  test "allows table cells and table headings without a style attribute" do
@@ -62,15 +71,14 @@ class HtmlSanitizerTest < Minitest::Test
62
71
 
63
72
  test "strips table cells and headings that appear outside a table" do
64
73
  html = "<th>thing</th></tr><tr><td>thing</td>"
65
- assert_equal 'thingthing', Govspeak::HtmlSanitizer.new(html).sanitize
74
+ assert_equal "thingthing", Govspeak::HtmlSanitizer.new(html).sanitize
66
75
  end
67
76
 
68
77
  test "normalizes table tags to inject missing rows and bodies like a browser does" do
69
78
  html = "<table><th>thing</th><td>thing</td></table>"
70
- assert_equal '<table><tbody><tr><th>thing</th><td>thing</td></tr></tbody></table>', Govspeak::HtmlSanitizer.new(html).sanitize
79
+ assert_equal "<table><tbody><tr><th>thing</th><td>thing</td></tr></tbody></table>", Govspeak::HtmlSanitizer.new(html).sanitize
71
80
  end
72
81
 
73
-
74
82
  test "allows valid text-align properties on the style attribute for table cells and table headings" do
75
83
  %w[left right center].each do |alignment|
76
84
  html = "<table><thead><tr><th style=\"text-align: #{alignment}\">thing</th></tr></thead><tbody><tr><td style=\"text-align: #{alignment}\">thing</td></tr></tbody></table>"
@@ -82,10 +90,10 @@ class HtmlSanitizerTest < Minitest::Test
82
90
  "text-align: middle",
83
91
  "text-align: left; width: 10px",
84
92
  "background-image: url(javascript:alert('XSS'))",
85
- "expression(alert('XSS'));"
93
+ "expression(alert('XSS'));",
86
94
  ].each do |style|
87
95
  html = "<table><thead><tr><th style=\"#{style}\">thing</th></tr></thead><tbody><tr><td style=\"#{style}\">thing</td></tr></tbody></table>"
88
- assert_equal '<table><thead><tr><th>thing</th></tr></thead><tbody><tr><td>thing</td></tr></tbody></table>', Govspeak::HtmlSanitizer.new(html).sanitize
96
+ assert_equal "<table><thead><tr><th>thing</th></tr></thead><tbody><tr><td>thing</td></tr></tbody></table>", Govspeak::HtmlSanitizer.new(html).sanitize
89
97
  end
90
98
  end
91
99
  end
@@ -51,7 +51,7 @@ class HtmlValidatorTest < Minitest::Test
51
51
  $P
52
52
  ",
53
53
  ":england:content goes here:england:",
54
- ":scotland:content goes here:scotland:"
54
+ ":scotland:content goes here:scotland:",
55
55
  ]
56
56
  values.each do |value|
57
57
  assert Govspeak::HtmlValidator.new(value).valid?
@@ -88,7 +88,7 @@ class HtmlValidatorTest < Minitest::Test
88
88
 
89
89
  test "optionally disallow images not on a whitelisted domain" do
90
90
  html = "<img src='http://evil.com/image.jgp'>"
91
- assert Govspeak::HtmlValidator.new(html, allowed_image_hosts: ['allowed.com']).invalid?
91
+ assert Govspeak::HtmlValidator.new(html, allowed_image_hosts: ["allowed.com"]).invalid?
92
92
  end
93
93
 
94
94
  test "allow <div> and <span> HTML elements" do
@@ -1,93 +1,91 @@
1
- # encoding: utf-8
2
-
3
- require 'test_helper'
4
- require 'ostruct'
1
+ require "test_helper"
2
+ require "ostruct"
5
3
 
6
4
  class HCardPresenterTest < Minitest::Test
7
5
  def unindent(html)
8
- html.gsub(/^\s+/, '')
6
+ html.gsub(/^\s+/, "")
9
7
  end
10
8
 
11
9
  test "renders address in UK format" do
12
- assert_equal unindent(gb_addr), HCardPresenter.new(addr_fields, 'GB').render
10
+ assert_equal unindent(gb_addr), HCardPresenter.new(addr_fields, "GB").render
13
11
  end
14
12
 
15
13
  test "renders address in Spanish format" do
16
- assert_equal unindent(es_addr), HCardPresenter.new(addr_fields, 'ES').render
14
+ assert_equal unindent(es_addr), HCardPresenter.new(addr_fields, "ES").render
17
15
  end
18
16
 
19
17
  test "renders address in Japanese format" do
20
- assert_equal unindent(jp_addr), HCardPresenter.new(addr_fields, 'JP').render
18
+ assert_equal unindent(jp_addr), HCardPresenter.new(addr_fields, "JP").render
21
19
  end
22
20
 
23
21
  test "doesn't clobber address formats" do
24
- gb_format_before = HCardPresenter.address_formats['gb'].dup
25
- HCardPresenter.new(addr_fields, 'GB').render
22
+ gb_format_before = HCardPresenter.address_formats["gb"].dup
23
+ HCardPresenter.new(addr_fields, "GB").render
26
24
 
27
- assert_equal unindent(gb_format_before), HCardPresenter.address_formats['gb']
25
+ assert_equal unindent(gb_format_before), HCardPresenter.address_formats["gb"]
28
26
  end
29
27
 
30
28
  test "blank properties do not render extra line breaks" do
31
29
  fields_without_region = addr_fields
32
- fields_without_region.delete('region')
30
+ fields_without_region.delete("region")
33
31
 
34
- assert_equal unindent(addr_without_region), HCardPresenter.new(fields_without_region, 'GB').render
32
+ assert_equal unindent(addr_without_region), HCardPresenter.new(fields_without_region, "GB").render
35
33
  end
36
34
 
37
35
  test "doesn't render a property when it's a blank string" do
38
36
  fields = addr_fields
39
37
 
40
- fields['region'] = ''
41
- assert_equal unindent(addr_without_region), HCardPresenter.new(fields, 'GB').render
38
+ fields["region"] = ""
39
+ assert_equal unindent(addr_without_region), HCardPresenter.new(fields, "GB").render
42
40
 
43
- fields['region'] = ' '
44
- assert_equal unindent(addr_without_region), HCardPresenter.new(fields, 'GB').render
41
+ fields["region"] = " "
42
+ assert_equal unindent(addr_without_region), HCardPresenter.new(fields, "GB").render
45
43
  end
46
44
 
47
- test 'uses html escaping on property values' do
45
+ test "uses html escaping on property values" do
48
46
  fields = addr_fields
49
47
 
50
- fields['region'] = 'UK & Channel Islands'
51
- assert_includes HCardPresenter.new(fields, 'GB').render, "UK &amp; Channel Islands"
48
+ fields["region"] = "UK & Channel Islands"
49
+ assert_includes HCardPresenter.new(fields, "GB").render, "UK &amp; Channel Islands"
52
50
  end
53
51
 
54
52
  test "it defaults to UK format" do
55
- assert_equal unindent(gb_addr), HCardPresenter.new(addr_fields, 'FUBAR').render
53
+ assert_equal unindent(gb_addr), HCardPresenter.new(addr_fields, "FUBAR").render
56
54
  end
57
55
 
58
56
  test "it builds from a Contact" do
59
- contact = OpenStruct.new(recipient: 'Recipient',
60
- street_address: 'Street',
61
- locality: 'Locality',
62
- region: 'Region',
63
- postal_code: 'Postcode',
64
- country_name: 'Country',
65
- country_code: 'ES')
57
+ contact = OpenStruct.new(recipient: "Recipient",
58
+ street_address: "Street",
59
+ locality: "Locality",
60
+ region: "Region",
61
+ postal_code: "Postcode",
62
+ country_name: "Country",
63
+ country_code: "ES")
66
64
  hcard = HCardPresenter.from_contact(contact)
67
65
 
68
66
  assert_equal unindent(es_addr), hcard.render
69
67
  end
70
68
 
71
69
  test "it leaves out the country name when building a GB contact" do
72
- contact = OpenStruct.new(recipient: 'Recipient',
73
- street_address: 'Street',
74
- locality: 'Locality',
75
- region: 'Region',
76
- postal_code: 'Postcode',
77
- country_name: 'Country',
78
- country_code: 'GB')
70
+ contact = OpenStruct.new(recipient: "Recipient",
71
+ street_address: "Street",
72
+ locality: "Locality",
73
+ region: "Region",
74
+ postal_code: "Postcode",
75
+ country_name: "Country",
76
+ country_code: "GB")
79
77
  hcard = HCardPresenter.from_contact(contact)
80
78
 
81
79
  assert_equal unindent(addr_without_country), hcard.render
82
80
  end
83
81
 
84
82
  def addr_fields
85
- { 'fn' => 'Recipient',
86
- 'street-address' => 'Street',
87
- 'postal-code' => 'Postcode',
88
- 'locality' => 'Locality',
89
- 'region' => 'Region',
90
- 'country-name' => 'Country' }
83
+ { "fn" => "Recipient",
84
+ "street-address" => "Street",
85
+ "postal-code" => "Postcode",
86
+ "locality" => "Locality",
87
+ "region" => "Region",
88
+ "country-name" => "Country" }
91
89
  end
92
90
 
93
91
  def gb_addr
@@ -1,22 +1,26 @@
1
- require 'simplecov'
2
- require 'simplecov-rcov'
1
+ require "simplecov"
2
+ require "simplecov-rcov"
3
3
 
4
4
  SimpleCov.start
5
5
  SimpleCov.formatter = SimpleCov::Formatter::RcovFormatter
6
6
 
7
- $:.unshift(File.expand_path("../lib")) unless $:.include?(File.expand_path("../lib"))
7
+ $LOAD_PATH.unshift(File.expand_path("../lib")) unless $LOAD_PATH.include?(File.expand_path("../lib"))
8
8
 
9
- require 'bundler'
9
+ require "bundler"
10
10
  Bundler.setup :default, :development, :test
11
11
 
12
- require 'minitest/autorun'
12
+ require "minitest/autorun"
13
13
 
14
14
  class Minitest::Test
15
15
  class << self
16
16
  def test(name, &block)
17
- clean_name = name.gsub(/\s+/, '_')
17
+ clean_name = name.gsub(/\s+/, "_")
18
18
  method = "test_#{clean_name.gsub(/\s+/, '_')}".to_sym
19
- already_defined = instance_method(method) rescue false
19
+ already_defined = begin
20
+ instance_method(method)
21
+ rescue StandardError
22
+ false
23
+ end
20
24
  raise "#{method} exists" if already_defined
21
25
 
22
26
  define_method(method, &block)
@@ -24,4 +28,4 @@ class Minitest::Test
24
28
  end
25
29
  end
26
30
 
27
- require 'govspeak'
31
+ require "govspeak"
metadata CHANGED
@@ -1,29 +1,35 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: govspeak
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.5.0
4
+ version: 6.5.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - GOV.UK Dev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-08-23 00:00:00.000000000 Z
11
+ date: 2020-08-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: actionview
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: '5.0'
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '7'
20
23
  type: :runtime
21
24
  prerelease: false
22
25
  version_requirements: !ruby/object:Gem::Requirement
23
26
  requirements:
24
- - - "~>"
27
+ - - ">="
25
28
  - !ruby/object:Gem::Version
26
29
  version: '5.0'
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '7'
27
33
  - !ruby/object:Gem::Dependency
28
34
  name: addressable
29
35
  requirement: !ruby/object:Gem::Requirement
@@ -48,16 +54,16 @@ dependencies:
48
54
  name: govuk_publishing_components
49
55
  requirement: !ruby/object:Gem::Requirement
50
56
  requirements:
51
- - - ">="
57
+ - - "~>"
52
58
  - !ruby/object:Gem::Version
53
- version: '16.16'
59
+ version: '21.4'
54
60
  type: :runtime
55
61
  prerelease: false
56
62
  version_requirements: !ruby/object:Gem::Requirement
57
63
  requirements:
58
- - - ">="
64
+ - - "~>"
59
65
  - !ruby/object:Gem::Version
60
- version: '16.16'
66
+ version: '21.4'
61
67
  - !ruby/object:Gem::Dependency
62
68
  name: htmlentities
63
69
  requirement: !ruby/object:Gem::Requirement
@@ -146,44 +152,36 @@ dependencies:
146
152
  name: sanitize
147
153
  requirement: !ruby/object:Gem::Requirement
148
154
  requirements:
149
- - - "~>"
155
+ - - ">="
156
+ - !ruby/object:Gem::Version
157
+ version: 5.2.1
158
+ - - "<"
150
159
  - !ruby/object:Gem::Version
151
- version: '5'
160
+ version: '6'
152
161
  type: :runtime
153
162
  prerelease: false
154
163
  version_requirements: !ruby/object:Gem::Requirement
155
164
  requirements:
156
- - - "~>"
157
- - !ruby/object:Gem::Version
158
- version: '5'
159
- - !ruby/object:Gem::Dependency
160
- name: govuk-lint
161
- requirement: !ruby/object:Gem::Requirement
162
- requirements:
163
- - - "~>"
165
+ - - ">="
164
166
  - !ruby/object:Gem::Version
165
- version: 3.11.5
166
- type: :development
167
- prerelease: false
168
- version_requirements: !ruby/object:Gem::Requirement
169
- requirements:
170
- - - "~>"
167
+ version: 5.2.1
168
+ - - "<"
171
169
  - !ruby/object:Gem::Version
172
- version: 3.11.5
170
+ version: '6'
173
171
  - !ruby/object:Gem::Dependency
174
172
  name: minitest
175
173
  requirement: !ruby/object:Gem::Requirement
176
174
  requirements:
177
175
  - - "~>"
178
176
  - !ruby/object:Gem::Version
179
- version: 5.8.3
177
+ version: 5.14.1
180
178
  type: :development
181
179
  prerelease: false
182
180
  version_requirements: !ruby/object:Gem::Requirement
183
181
  requirements:
184
182
  - - "~>"
185
183
  - !ruby/object:Gem::Version
186
- version: 5.8.3
184
+ version: 5.14.1
187
185
  - !ruby/object:Gem::Dependency
188
186
  name: pry-byebug
189
187
  requirement: !ruby/object:Gem::Requirement
@@ -212,6 +210,20 @@ dependencies:
212
210
  - - "~>"
213
211
  - !ruby/object:Gem::Version
214
212
  version: 0.9.0
213
+ - !ruby/object:Gem::Dependency
214
+ name: rubocop-govuk
215
+ requirement: !ruby/object:Gem::Requirement
216
+ requirements:
217
+ - - "~>"
218
+ - !ruby/object:Gem::Version
219
+ version: 3.3.2
220
+ type: :development
221
+ prerelease: false
222
+ version_requirements: !ruby/object:Gem::Requirement
223
+ requirements:
224
+ - - "~>"
225
+ - !ruby/object:Gem::Version
226
+ version: 3.3.2
215
227
  - !ruby/object:Gem::Dependency
216
228
  name: simplecov
217
229
  requirement: !ruby/object:Gem::Requirement
@@ -359,23 +371,23 @@ signing_key:
359
371
  specification_version: 4
360
372
  summary: Markup language for single domain
361
373
  test_files:
374
+ - test/blockquote_extra_quote_remover_test.rb
375
+ - test/govspeak_test_helper.rb
376
+ - test/govspeak_structured_headers_test.rb
362
377
  - test/govspeak_attachment_link_test.rb
378
+ - test/govspeak_attachments_image_test.rb
363
379
  - test/test_helper.rb
380
+ - test/govspeak_attachments_inline_test.rb
381
+ - test/html_sanitizer_test.rb
364
382
  - test/govspeak_button_test.rb
365
- - test/govspeak_test.rb
383
+ - test/govspeak_images_bang_test.rb
384
+ - test/govspeak_images_test.rb
366
385
  - test/html_validator_test.rb
367
386
  - test/govspeak_attachment_test.rb
368
- - test/govspeak_contacts_test.rb
369
- - test/govspeak_test_helper.rb
370
- - test/blockquote_extra_quote_remover_test.rb
371
- - test/govspeak_table_with_headers_test.rb
372
- - test/govspeak_attachments_image_test.rb
373
- - test/html_sanitizer_test.rb
374
- - test/govspeak_link_test.rb
375
387
  - test/govspeak_extract_contact_content_ids_test.rb
376
- - test/govspeak_structured_headers_test.rb
377
- - test/govspeak_images_test.rb
378
- - test/presenters/h_card_presenter_test.rb
379
- - test/govspeak_images_bang_test.rb
388
+ - test/govspeak_test.rb
380
389
  - test/govspeak_link_extractor_test.rb
381
- - test/govspeak_attachments_inline_test.rb
390
+ - test/govspeak_link_test.rb
391
+ - test/govspeak_contacts_test.rb
392
+ - test/presenters/h_card_presenter_test.rb
393
+ - test/govspeak_table_with_headers_test.rb