govspeak 6.4.0 → 6.5.4

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.
@@ -1,4 +1,4 @@
1
- require 'test_helper'
1
+ require "test_helper"
2
2
 
3
3
  class GovspeakStructuredHeadersTest < Minitest::Test
4
4
  def document_body
@@ -90,7 +90,7 @@ class GovspeakStructuredHeadersTest < Minitest::Test
90
90
  text: "Sub sub heading 2.2.1",
91
91
  level: 4,
92
92
  id: "sub-sub-heading-221",
93
- headers: []
93
+ headers: [],
94
94
  },
95
95
  ],
96
96
  },
@@ -1,4 +1,4 @@
1
- require 'test_helper'
1
+ require "test_helper"
2
2
 
3
3
  class GovspeakTableWithHeadersTest < Minitest::Test
4
4
  def expected_outcome
@@ -1,9 +1,9 @@
1
1
  # encoding: UTF-8
2
2
 
3
- require 'test_helper'
4
- require 'govspeak_test_helper'
3
+ require "test_helper"
4
+ require "govspeak_test_helper"
5
5
 
6
- require 'ostruct'
6
+ require "ostruct"
7
7
 
8
8
  class GovspeakTest < Minitest::Test
9
9
  include GovspeakTestHelper
@@ -20,7 +20,7 @@ class GovspeakTest < Minitest::Test
20
20
 
21
21
  test "strips forbidden unicode characters" do
22
22
  rendered = Govspeak::Document.new(
23
- "this is text with forbidden characters \ufffc\u2028\ufeff\u202c\u202a"
23
+ "this is text with forbidden characters \u0008\u000b\ufffe\u{2ffff}\u{5fffe}",
24
24
  ).to_html
25
25
  assert_equal "<p>this is text with forbidden characters</p>\n", rendered
26
26
  end
@@ -44,17 +44,17 @@ class GovspeakTest < Minitest::Test
44
44
  ## Medium title
45
45
  }
46
46
  assert_equal [
47
- Govspeak::Header.new('Big title', 1, 'big-title'),
48
- Govspeak::Header.new('Small subtitle', 3, 'small-subtitle'),
49
- Govspeak::Header.new('Medium title', 2, 'medium-title')
47
+ Govspeak::Header.new("Big title", 1, "big-title"),
48
+ Govspeak::Header.new("Small subtitle", 3, "small-subtitle"),
49
+ Govspeak::Header.new("Medium title", 2, "medium-title"),
50
50
  ], document.headers
51
51
  end
52
52
 
53
53
  test "extracts different ids for duplicate headers" do
54
54
  document = Govspeak::Document.new("## Duplicate header\n\n## Duplicate header")
55
55
  assert_equal [
56
- Govspeak::Header.new('Duplicate header', 2, 'duplicate-header'),
57
- Govspeak::Header.new('Duplicate header', 2, 'duplicate-header-1')
56
+ Govspeak::Header.new("Duplicate header", 2, "duplicate-header"),
57
+ Govspeak::Header.new("Duplicate header", 2, "duplicate-header-1"),
58
58
  ], document.headers
59
59
  end
60
60
 
@@ -76,10 +76,10 @@ class GovspeakTest < Minitest::Test
76
76
  </div>
77
77
  }
78
78
  assert_equal [
79
- Govspeak::Header.new('First title', 1, 'first-title'),
80
- Govspeak::Header.new('Nested subtitle', 2, 'nested-subtitle'),
81
- Govspeak::Header.new('Double nested subtitle', 3, 'double-nested-subtitle'),
82
- Govspeak::Header.new('Second double subtitle', 3, 'second-double-subtitle')
79
+ Govspeak::Header.new("First title", 1, "first-title"),
80
+ Govspeak::Header.new("Nested subtitle", 2, "nested-subtitle"),
81
+ Govspeak::Header.new("Double nested subtitle", 3, "double-nested-subtitle"),
82
+ Govspeak::Header.new("Second double subtitle", 3, "second-double-subtitle"),
83
83
  ], document.headers
84
84
  end
85
85
 
@@ -90,8 +90,8 @@ class GovspeakTest < Minitest::Test
90
90
  ## Second title {#special}
91
91
  }
92
92
  assert_equal [
93
- Govspeak::Header.new('First title', 1, 'first-title'),
94
- Govspeak::Header.new('Second title', 2, 'special'),
93
+ Govspeak::Header.new("First title", 1, "first-title"),
94
+ Govspeak::Header.new("Second title", 2, "special"),
95
95
  ], document.headers
96
96
  end
97
97
 
@@ -360,7 +360,7 @@ Teston
360
360
  # TODO: review whether we should require closing symbols for these extensions
361
361
  # need to check all existing content.
362
362
  test_given_govspeak "xaa" do
363
- assert_html_output '<p>xaa</p>'
363
+ assert_html_output "<p>xaa</p>"
364
364
  assert_text_output "xaa"
365
365
  end
366
366
 
@@ -639,12 +639,12 @@ Teston
639
639
  }
640
640
  end
641
641
 
642
- test 'sanitize source input by default' do
642
+ test "sanitize source input by default" do
643
643
  document = Govspeak::Document.new("<script>doBadThings();</script>")
644
644
  assert_equal "", document.to_html.strip
645
645
  end
646
646
 
647
- test 'it can have sanitizing disabled' do
647
+ test "it can have sanitizing disabled" do
648
648
  document = Govspeak::Document.new("<script>doGoodThings();</script>", sanitize: false)
649
649
  assert_equal "<script>doGoodThings();</script>", document.to_html.strip
650
650
  end
@@ -31,19 +31,37 @@ 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
+ )
36
+ end
37
+
38
+ test "allow data attributes on links" do
39
+ html = "<a href='/' data-module='track-click' data-ecommerce-path='/' data-track-category='linkClicked'>Test Link</a>"
40
+
41
+ assert_equal(
42
+ "<a href=\"/\" data-module=\"track-click\" data-ecommerce-path=\"/\" data-track-category=\"linkClicked\">Test Link</a>",
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,
35
53
  )
36
54
  end
37
55
 
38
56
  test "allows images on whitelisted domains" do
39
57
  html = "<img src='http://allowed.com/image.jgp'>"
40
- 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
41
59
  assert_equal "<img src=\"http://allowed.com/image.jgp\">", sanitized_html
42
60
  end
43
61
 
44
62
  test "removes images not on whitelisted domains" do
45
63
  html = "<img src='http://evil.com/image.jgp'>"
46
- 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
47
65
  end
48
66
 
49
67
  test "allows table cells and table headings without a style attribute" do
@@ -53,12 +71,12 @@ class HtmlSanitizerTest < Minitest::Test
53
71
 
54
72
  test "strips table cells and headings that appear outside a table" do
55
73
  html = "<th>thing</th></tr><tr><td>thing</td>"
56
- assert_equal 'thingthing', Govspeak::HtmlSanitizer.new(html).sanitize
74
+ assert_equal "thingthing", Govspeak::HtmlSanitizer.new(html).sanitize
57
75
  end
58
76
 
59
77
  test "normalizes table tags to inject missing rows and bodies like a browser does" do
60
78
  html = "<table><th>thing</th><td>thing</td></table>"
61
- 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
62
80
  end
63
81
 
64
82
 
@@ -73,10 +91,10 @@ class HtmlSanitizerTest < Minitest::Test
73
91
  "text-align: middle",
74
92
  "text-align: left; width: 10px",
75
93
  "background-image: url(javascript:alert('XSS'))",
76
- "expression(alert('XSS'));"
94
+ "expression(alert('XSS'));",
77
95
  ].each do |style|
78
96
  html = "<table><thead><tr><th style=\"#{style}\">thing</th></tr></thead><tbody><tr><td style=\"#{style}\">thing</td></tr></tbody></table>"
79
- assert_equal '<table><thead><tr><th>thing</th></tr></thead><tbody><tr><td>thing</td></tr></tbody></table>', Govspeak::HtmlSanitizer.new(html).sanitize
97
+ assert_equal "<table><thead><tr><th>thing</th></tr></thead><tbody><tr><td>thing</td></tr></tbody></table>", Govspeak::HtmlSanitizer.new(html).sanitize
80
98
  end
81
99
  end
82
100
  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,93 @@
1
1
  # encoding: utf-8
2
2
 
3
- require 'test_helper'
4
- require 'ostruct'
3
+ require "test_helper"
4
+ require "ostruct"
5
5
 
6
6
  class HCardPresenterTest < Minitest::Test
7
7
  def unindent(html)
8
- html.gsub(/^\s+/, '')
8
+ html.gsub(/^\s+/, "")
9
9
  end
10
10
 
11
11
  test "renders address in UK format" do
12
- assert_equal unindent(gb_addr), HCardPresenter.new(addr_fields, 'GB').render
12
+ assert_equal unindent(gb_addr), HCardPresenter.new(addr_fields, "GB").render
13
13
  end
14
14
 
15
15
  test "renders address in Spanish format" do
16
- assert_equal unindent(es_addr), HCardPresenter.new(addr_fields, 'ES').render
16
+ assert_equal unindent(es_addr), HCardPresenter.new(addr_fields, "ES").render
17
17
  end
18
18
 
19
19
  test "renders address in Japanese format" do
20
- assert_equal unindent(jp_addr), HCardPresenter.new(addr_fields, 'JP').render
20
+ assert_equal unindent(jp_addr), HCardPresenter.new(addr_fields, "JP").render
21
21
  end
22
22
 
23
23
  test "doesn't clobber address formats" do
24
- gb_format_before = HCardPresenter.address_formats['gb'].dup
25
- HCardPresenter.new(addr_fields, 'GB').render
24
+ gb_format_before = HCardPresenter.address_formats["gb"].dup
25
+ HCardPresenter.new(addr_fields, "GB").render
26
26
 
27
- assert_equal unindent(gb_format_before), HCardPresenter.address_formats['gb']
27
+ assert_equal unindent(gb_format_before), HCardPresenter.address_formats["gb"]
28
28
  end
29
29
 
30
30
  test "blank properties do not render extra line breaks" do
31
31
  fields_without_region = addr_fields
32
- fields_without_region.delete('region')
32
+ fields_without_region.delete("region")
33
33
 
34
- assert_equal unindent(addr_without_region), HCardPresenter.new(fields_without_region, 'GB').render
34
+ assert_equal unindent(addr_without_region), HCardPresenter.new(fields_without_region, "GB").render
35
35
  end
36
36
 
37
37
  test "doesn't render a property when it's a blank string" do
38
38
  fields = addr_fields
39
39
 
40
- fields['region'] = ''
41
- assert_equal unindent(addr_without_region), HCardPresenter.new(fields, 'GB').render
40
+ fields["region"] = ""
41
+ assert_equal unindent(addr_without_region), HCardPresenter.new(fields, "GB").render
42
42
 
43
- fields['region'] = ' '
44
- assert_equal unindent(addr_without_region), HCardPresenter.new(fields, 'GB').render
43
+ fields["region"] = " "
44
+ assert_equal unindent(addr_without_region), HCardPresenter.new(fields, "GB").render
45
45
  end
46
46
 
47
- test 'uses html escaping on property values' do
47
+ test "uses html escaping on property values" do
48
48
  fields = addr_fields
49
49
 
50
- fields['region'] = 'UK & Channel Islands'
51
- assert_includes HCardPresenter.new(fields, 'GB').render, "UK &amp; Channel Islands"
50
+ fields["region"] = "UK & Channel Islands"
51
+ assert_includes HCardPresenter.new(fields, "GB").render, "UK &amp; Channel Islands"
52
52
  end
53
53
 
54
54
  test "it defaults to UK format" do
55
- assert_equal unindent(gb_addr), HCardPresenter.new(addr_fields, 'FUBAR').render
55
+ assert_equal unindent(gb_addr), HCardPresenter.new(addr_fields, "FUBAR").render
56
56
  end
57
57
 
58
58
  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')
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")
66
66
  hcard = HCardPresenter.from_contact(contact)
67
67
 
68
68
  assert_equal unindent(es_addr), hcard.render
69
69
  end
70
70
 
71
71
  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')
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")
79
79
  hcard = HCardPresenter.from_contact(contact)
80
80
 
81
81
  assert_equal unindent(addr_without_country), hcard.render
82
82
  end
83
83
 
84
84
  def addr_fields
85
- { 'fn' => 'Recipient',
86
- 'street-address' => 'Street',
87
- 'postal-code' => 'Postcode',
88
- 'locality' => 'Locality',
89
- 'region' => 'Region',
90
- 'country-name' => 'Country' }
85
+ { "fn" => "Recipient",
86
+ "street-address" => "Street",
87
+ "postal-code" => "Postcode",
88
+ "locality" => "Locality",
89
+ "region" => "Region",
90
+ "country-name" => "Country" }
91
91
  end
92
92
 
93
93
  def gb_addr
@@ -1,20 +1,20 @@
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
7
  $:.unshift(File.expand_path("../lib")) unless $:.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
19
  already_defined = instance_method(method) rescue false
20
20
  raise "#{method} exists" if already_defined
@@ -24,4 +24,4 @@ class Minitest::Test
24
24
  end
25
25
  end
26
26
 
27
- require 'govspeak'
27
+ 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.4.0
4
+ version: 6.5.4
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-07-22 00:00:00.000000000 Z
11
+ date: 2020-07-01 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,30 +152,22 @@ 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
@@ -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:
362
- - test/govspeak_attachments_inline_test.rb
363
- - test/govspeak_attachment_test.rb
364
374
  - test/govspeak_attachment_link_test.rb
365
- - test/govspeak_images_test.rb
366
- - test/govspeak_table_with_headers_test.rb
367
- - test/govspeak_link_test.rb
368
- - test/govspeak_images_bang_test.rb
369
- - test/govspeak_link_extractor_test.rb
370
- - test/govspeak_contacts_test.rb
371
375
  - test/test_helper.rb
376
+ - test/govspeak_button_test.rb
372
377
  - test/govspeak_test.rb
373
- - test/govspeak_attachments_image_test.rb
374
378
  - test/html_validator_test.rb
375
- - test/govspeak_structured_headers_test.rb
376
- - test/govspeak_extract_contact_content_ids_test.rb
377
- - test/blockquote_extra_quote_remover_test.rb
378
- - test/presenters/h_card_presenter_test.rb
379
- - test/govspeak_button_test.rb
379
+ - test/govspeak_attachment_test.rb
380
+ - test/govspeak_contacts_test.rb
380
381
  - test/govspeak_test_helper.rb
382
+ - test/blockquote_extra_quote_remover_test.rb
383
+ - test/govspeak_table_with_headers_test.rb
384
+ - test/govspeak_attachments_image_test.rb
381
385
  - test/html_sanitizer_test.rb
386
+ - test/govspeak_link_test.rb
387
+ - test/govspeak_extract_contact_content_ids_test.rb
388
+ - test/govspeak_structured_headers_test.rb
389
+ - test/govspeak_images_test.rb
390
+ - test/presenters/h_card_presenter_test.rb
391
+ - test/govspeak_images_bang_test.rb
392
+ - test/govspeak_link_extractor_test.rb
393
+ - test/govspeak_attachments_inline_test.rb