govspeak 6.5.0 → 6.5.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 +4 -4
- data/CHANGELOG.md +7 -2
- data/Rakefile +1 -1
- data/lib/govspeak.rb +74 -74
- data/lib/govspeak/header_extractor.rb +1 -1
- data/lib/govspeak/html_sanitizer.rb +5 -5
- data/lib/govspeak/link_extractor.rb +3 -3
- data/lib/govspeak/post_processor.rb +12 -12
- data/lib/govspeak/presenters/attachment_presenter.rb +32 -32
- data/lib/govspeak/presenters/contact_presenter.rb +2 -2
- data/lib/govspeak/presenters/h_card_presenter.rb +3 -3
- data/lib/govspeak/presenters/image_presenter.rb +2 -2
- data/lib/govspeak/version.rb +1 -1
- data/lib/kramdown/parser/govuk.rb +1 -1
- data/test/blockquote_extra_quote_remover_test.rb +10 -10
- data/test/govspeak_attachments_image_test.rb +10 -10
- data/test/govspeak_attachments_inline_test.rb +18 -18
- data/test/govspeak_button_test.rb +4 -4
- data/test/govspeak_contacts_test.rb +18 -18
- data/test/govspeak_extract_contact_content_ids_test.rb +1 -1
- data/test/govspeak_images_bang_test.rb +14 -14
- data/test/govspeak_images_test.rb +16 -16
- data/test/govspeak_link_test.rb +1 -1
- data/test/govspeak_structured_headers_test.rb +2 -2
- data/test/govspeak_table_with_headers_test.rb +1 -1
- data/test/govspeak_test.rb +18 -18
- data/test/html_sanitizer_test.rb +8 -8
- data/test/html_validator_test.rb +2 -2
- data/test/presenters/h_card_presenter_test.rb +39 -39
- data/test/test_helper.rb +6 -6
- metadata +38 -32
data/test/html_sanitizer_test.rb
CHANGED
@@ -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,19 @@ 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
44
|
)
|
45
45
|
end
|
46
46
|
|
47
47
|
test "allows images on whitelisted domains" do
|
48
48
|
html = "<img src='http://allowed.com/image.jgp'>"
|
49
|
-
sanitized_html = Govspeak::HtmlSanitizer.new(html, allowed_image_hosts: [
|
49
|
+
sanitized_html = Govspeak::HtmlSanitizer.new(html, allowed_image_hosts: ["allowed.com"]).sanitize
|
50
50
|
assert_equal "<img src=\"http://allowed.com/image.jgp\">", sanitized_html
|
51
51
|
end
|
52
52
|
|
53
53
|
test "removes images not on whitelisted domains" do
|
54
54
|
html = "<img src='http://evil.com/image.jgp'>"
|
55
|
-
assert_equal "", Govspeak::HtmlSanitizer.new(html, allowed_image_hosts: [
|
55
|
+
assert_equal "", Govspeak::HtmlSanitizer.new(html, allowed_image_hosts: ["allowed.com"]).sanitize
|
56
56
|
end
|
57
57
|
|
58
58
|
test "allows table cells and table headings without a style attribute" do
|
@@ -62,12 +62,12 @@ class HtmlSanitizerTest < Minitest::Test
|
|
62
62
|
|
63
63
|
test "strips table cells and headings that appear outside a table" do
|
64
64
|
html = "<th>thing</th></tr><tr><td>thing</td>"
|
65
|
-
assert_equal
|
65
|
+
assert_equal "thingthing", Govspeak::HtmlSanitizer.new(html).sanitize
|
66
66
|
end
|
67
67
|
|
68
68
|
test "normalizes table tags to inject missing rows and bodies like a browser does" do
|
69
69
|
html = "<table><th>thing</th><td>thing</td></table>"
|
70
|
-
assert_equal
|
70
|
+
assert_equal "<table><tbody><tr><th>thing</th><td>thing</td></tr></tbody></table>", Govspeak::HtmlSanitizer.new(html).sanitize
|
71
71
|
end
|
72
72
|
|
73
73
|
|
@@ -82,10 +82,10 @@ class HtmlSanitizerTest < Minitest::Test
|
|
82
82
|
"text-align: middle",
|
83
83
|
"text-align: left; width: 10px",
|
84
84
|
"background-image: url(javascript:alert('XSS'))",
|
85
|
-
"expression(alert('XSS'));"
|
85
|
+
"expression(alert('XSS'));",
|
86
86
|
].each do |style|
|
87
87
|
html = "<table><thead><tr><th style=\"#{style}\">thing</th></tr></thead><tbody><tr><td style=\"#{style}\">thing</td></tr></tbody></table>"
|
88
|
-
assert_equal
|
88
|
+
assert_equal "<table><thead><tr><th>thing</th></tr></thead><tbody><tr><td>thing</td></tr></tbody></table>", Govspeak::HtmlSanitizer.new(html).sanitize
|
89
89
|
end
|
90
90
|
end
|
91
91
|
end
|
data/test/html_validator_test.rb
CHANGED
@@ -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: [
|
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
|
4
|
-
require
|
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,
|
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,
|
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,
|
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[
|
25
|
-
HCardPresenter.new(addr_fields,
|
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[
|
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(
|
32
|
+
fields_without_region.delete("region")
|
33
33
|
|
34
|
-
assert_equal unindent(addr_without_region), HCardPresenter.new(fields_without_region,
|
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[
|
41
|
-
assert_equal unindent(addr_without_region), HCardPresenter.new(fields,
|
40
|
+
fields["region"] = ""
|
41
|
+
assert_equal unindent(addr_without_region), HCardPresenter.new(fields, "GB").render
|
42
42
|
|
43
|
-
fields[
|
44
|
-
assert_equal unindent(addr_without_region), HCardPresenter.new(fields,
|
43
|
+
fields["region"] = " "
|
44
|
+
assert_equal unindent(addr_without_region), HCardPresenter.new(fields, "GB").render
|
45
45
|
end
|
46
46
|
|
47
|
-
test
|
47
|
+
test "uses html escaping on property values" do
|
48
48
|
fields = addr_fields
|
49
49
|
|
50
|
-
fields[
|
51
|
-
assert_includes HCardPresenter.new(fields,
|
50
|
+
fields["region"] = "UK & Channel Islands"
|
51
|
+
assert_includes HCardPresenter.new(fields, "GB").render, "UK & 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,
|
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:
|
60
|
-
street_address:
|
61
|
-
locality:
|
62
|
-
region:
|
63
|
-
postal_code:
|
64
|
-
country_name:
|
65
|
-
country_code:
|
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:
|
73
|
-
street_address:
|
74
|
-
locality:
|
75
|
-
region:
|
76
|
-
postal_code:
|
77
|
-
country_name:
|
78
|
-
country_code:
|
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
|
-
{
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
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
|
data/test/test_helper.rb
CHANGED
@@ -1,20 +1,20 @@
|
|
1
|
-
require
|
2
|
-
require
|
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
|
9
|
+
require "bundler"
|
10
10
|
Bundler.setup :default, :development, :test
|
11
11
|
|
12
|
-
require
|
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
|
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.5.
|
4
|
+
version: 6.5.1
|
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-
|
11
|
+
date: 2019-11-19 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
|
@@ -156,20 +162,6 @@ dependencies:
|
|
156
162
|
- - "~>"
|
157
163
|
- !ruby/object:Gem::Version
|
158
164
|
version: '5'
|
159
|
-
- !ruby/object:Gem::Dependency
|
160
|
-
name: govuk-lint
|
161
|
-
requirement: !ruby/object:Gem::Requirement
|
162
|
-
requirements:
|
163
|
-
- - "~>"
|
164
|
-
- !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
|
-
- - "~>"
|
171
|
-
- !ruby/object:Gem::Version
|
172
|
-
version: 3.11.5
|
173
165
|
- !ruby/object:Gem::Dependency
|
174
166
|
name: minitest
|
175
167
|
requirement: !ruby/object:Gem::Requirement
|
@@ -212,6 +204,20 @@ dependencies:
|
|
212
204
|
- - "~>"
|
213
205
|
- !ruby/object:Gem::Version
|
214
206
|
version: 0.9.0
|
207
|
+
- !ruby/object:Gem::Dependency
|
208
|
+
name: rubocop-govuk
|
209
|
+
requirement: !ruby/object:Gem::Requirement
|
210
|
+
requirements:
|
211
|
+
- - "~>"
|
212
|
+
- !ruby/object:Gem::Version
|
213
|
+
version: '1'
|
214
|
+
type: :development
|
215
|
+
prerelease: false
|
216
|
+
version_requirements: !ruby/object:Gem::Requirement
|
217
|
+
requirements:
|
218
|
+
- - "~>"
|
219
|
+
- !ruby/object:Gem::Version
|
220
|
+
version: '1'
|
215
221
|
- !ruby/object:Gem::Dependency
|
216
222
|
name: simplecov
|
217
223
|
requirement: !ruby/object:Gem::Requirement
|
@@ -359,23 +365,23 @@ signing_key:
|
|
359
365
|
specification_version: 4
|
360
366
|
summary: Markup language for single domain
|
361
367
|
test_files:
|
368
|
+
- test/govspeak_attachments_inline_test.rb
|
369
|
+
- test/govspeak_attachment_test.rb
|
362
370
|
- test/govspeak_attachment_link_test.rb
|
371
|
+
- test/govspeak_images_test.rb
|
372
|
+
- test/govspeak_table_with_headers_test.rb
|
373
|
+
- test/govspeak_link_test.rb
|
374
|
+
- test/govspeak_images_bang_test.rb
|
375
|
+
- test/govspeak_link_extractor_test.rb
|
376
|
+
- test/govspeak_contacts_test.rb
|
363
377
|
- test/test_helper.rb
|
364
|
-
- test/govspeak_button_test.rb
|
365
378
|
- test/govspeak_test.rb
|
366
|
-
- test/html_validator_test.rb
|
367
|
-
- 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
379
|
- test/govspeak_attachments_image_test.rb
|
373
|
-
- test/
|
374
|
-
- test/govspeak_link_test.rb
|
375
|
-
- test/govspeak_extract_contact_content_ids_test.rb
|
380
|
+
- test/html_validator_test.rb
|
376
381
|
- test/govspeak_structured_headers_test.rb
|
377
|
-
- test/
|
382
|
+
- test/govspeak_extract_contact_content_ids_test.rb
|
383
|
+
- test/blockquote_extra_quote_remover_test.rb
|
378
384
|
- test/presenters/h_card_presenter_test.rb
|
379
|
-
- test/
|
380
|
-
- test/
|
381
|
-
- test/
|
385
|
+
- test/govspeak_button_test.rb
|
386
|
+
- test/govspeak_test_helper.rb
|
387
|
+
- test/html_sanitizer_test.rb
|