govspeak 6.5.7 → 6.6.0
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 +20 -0
- data/README.md +2 -2
- data/lib/govspeak.rb +6 -2
- data/lib/govspeak/html_sanitizer.rb +5 -4
- data/lib/govspeak/post_processor.rb +11 -0
- data/lib/govspeak/version.rb +1 -1
- data/test/govspeak_footnote_test.rb +46 -0
- data/test/govspeak_test.rb +24 -0
- data/test/html_sanitizer_test.rb +6 -0
- metadata +12 -10
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6369a640dd1ca0303f548954b3cd69f176707200d83d460408eadbb7c7b35158
|
|
4
|
+
data.tar.gz: fb487bd7275c39da3b3ff34fb4bbb016c77e4666a778c42dd8098c0ef50b3ea5
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 85fe44ebb3c921918bb22148c4d53394d3e5921b1c5b778815bb09120832e7820805555aa68756799a257a05c4fb5efdeb5df53a453009b2333db528fafa5f29
|
|
7
|
+
data.tar.gz: 82dc434b862384862420ea07e45d00e2020b5ea20fd7a52ee5196bb5a6786d4c3facd15e64917c0bfd700ac0a1c3aaaa7e761c6970640c60b118f40ca5a1f0e8
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,23 @@
|
|
|
1
|
+
## 6.6.0
|
|
2
|
+
|
|
3
|
+
* Allow passed elements to be relaxed from sanitization [#203](https://github.com/alphagov/govspeak/pull/203)
|
|
4
|
+
|
|
5
|
+
## 6.5.11
|
|
6
|
+
|
|
7
|
+
* Fix issue rendering $CTA blocks before $C (PR#202)
|
|
8
|
+
|
|
9
|
+
## 6.5.10
|
|
10
|
+
|
|
11
|
+
* Be optimistic in versions of govuk_publishing_components and i18n allowed (PR#200)
|
|
12
|
+
|
|
13
|
+
## 6.5.9
|
|
14
|
+
|
|
15
|
+
* Adjust footnote markup to accommodate multiple references (PR#198)
|
|
16
|
+
|
|
17
|
+
## 6.5.8
|
|
18
|
+
|
|
19
|
+
* Customise footnote markup for accessibility (PR#192)
|
|
20
|
+
|
|
1
21
|
## 6.5.7
|
|
2
22
|
|
|
3
23
|
* Update GOV.UK Publishing components to version to 23.0.0 or greater
|
data/README.md
CHANGED
|
@@ -65,7 +65,7 @@ creates an example box
|
|
|
65
65
|
|
|
66
66
|
## Highlights
|
|
67
67
|
|
|
68
|
-
### Advisory
|
|
68
|
+
### Advisory (DEPRECATED: marked for removal. Use 'Information callouts' instead.)
|
|
69
69
|
|
|
70
70
|
@This is a very important message or warning@
|
|
71
71
|
|
|
@@ -77,7 +77,7 @@ highlights the enclosed text in yellow
|
|
|
77
77
|
</h3>
|
|
78
78
|
```
|
|
79
79
|
|
|
80
|
-
### Answer
|
|
80
|
+
### Answer (DEPRECATED: marked for removal)
|
|
81
81
|
|
|
82
82
|
{::highlight-answer}
|
|
83
83
|
The VAT rate is *20%*
|
data/lib/govspeak.rb
CHANGED
|
@@ -53,6 +53,7 @@ module Govspeak
|
|
|
53
53
|
@source = source ? source.dup : ""
|
|
54
54
|
|
|
55
55
|
@images = options.delete(:images) || []
|
|
56
|
+
@allowed_elements = options.delete(:allowed_elements) || []
|
|
56
57
|
@attachments = Array.wrap(options.delete(:attachments))
|
|
57
58
|
@links = Array.wrap(options.delete(:links))
|
|
58
59
|
@contacts = Array.wrap(options.delete(:contacts))
|
|
@@ -66,7 +67,7 @@ module Govspeak
|
|
|
66
67
|
def to_html
|
|
67
68
|
@to_html ||= begin
|
|
68
69
|
html = if @options[:sanitize]
|
|
69
|
-
HtmlSanitizer.new(kramdown_doc.to_html).sanitize
|
|
70
|
+
HtmlSanitizer.new(kramdown_doc.to_html).sanitize(allowed_elements: @allowed_elements)
|
|
70
71
|
else
|
|
71
72
|
kramdown_doc.to_html
|
|
72
73
|
end
|
|
@@ -272,6 +273,10 @@ module Govspeak
|
|
|
272
273
|
lines.join
|
|
273
274
|
end
|
|
274
275
|
|
|
276
|
+
# More specific tags must be defined first. Those defined earlier have a
|
|
277
|
+
# higher precedence for being matched. For example $CTA must be defined
|
|
278
|
+
# before $C otherwise the first ($C)TA fill be matched to a contact tag.
|
|
279
|
+
wrap_with_div("call-to-action", "$CTA", Govspeak::Document)
|
|
275
280
|
wrap_with_div("summary", "$!")
|
|
276
281
|
wrap_with_div("form-download", "$D")
|
|
277
282
|
wrap_with_div("contact", "$C")
|
|
@@ -279,7 +284,6 @@ module Govspeak
|
|
|
279
284
|
wrap_with_div("information", "$I", Govspeak::Document)
|
|
280
285
|
wrap_with_div("additional-information", "$AI")
|
|
281
286
|
wrap_with_div("example", "$E", Govspeak::Document)
|
|
282
|
-
wrap_with_div("call-to-action", "$CTA", Govspeak::Document)
|
|
283
287
|
|
|
284
288
|
extension("address", surrounded_by("$A")) do |body|
|
|
285
289
|
%(\n<div class="address"><div class="adr org fn"><p>\n#{body.sub("\n", '').gsub("\n", '<br />')}\n</p></div></div>\n)
|
|
@@ -40,18 +40,19 @@ class Govspeak::HtmlSanitizer
|
|
|
40
40
|
@allowed_image_hosts = options[:allowed_image_hosts]
|
|
41
41
|
end
|
|
42
42
|
|
|
43
|
-
def sanitize
|
|
43
|
+
def sanitize(allowed_elements: [])
|
|
44
44
|
transformers = [TableCellTextAlignWhitelister.new]
|
|
45
45
|
if @allowed_image_hosts && @allowed_image_hosts.any?
|
|
46
46
|
transformers << ImageSourceWhitelister.new(@allowed_image_hosts)
|
|
47
47
|
end
|
|
48
|
-
|
|
48
|
+
|
|
49
|
+
Sanitize.clean(@dirty_html, Sanitize::Config.merge(sanitize_config(allowed_elements: allowed_elements), transformers: transformers))
|
|
49
50
|
end
|
|
50
51
|
|
|
51
|
-
def sanitize_config
|
|
52
|
+
def sanitize_config(allowed_elements: [])
|
|
52
53
|
Sanitize::Config.merge(
|
|
53
54
|
Sanitize::Config::RELAXED,
|
|
54
|
-
elements: Sanitize::Config::RELAXED[:elements] + %w[govspeak-embed-attachment govspeak-embed-attachment-link svg path],
|
|
55
|
+
elements: Sanitize::Config::RELAXED[:elements] + %w[govspeak-embed-attachment govspeak-embed-attachment-link svg path].concat(allowed_elements),
|
|
55
56
|
attributes: {
|
|
56
57
|
:all => Sanitize::Config::RELAXED[:attributes][:all] + %w[role aria-label],
|
|
57
58
|
"a" => Sanitize::Config::RELAXED[:attributes]["a"] + [:data],
|
|
@@ -120,6 +120,17 @@ module Govspeak
|
|
|
120
120
|
end
|
|
121
121
|
end
|
|
122
122
|
|
|
123
|
+
extension("use custom footnotes") do |document|
|
|
124
|
+
document.css("a.footnote").map do |el|
|
|
125
|
+
footnote_number = el[:href].gsub(/\D/, "")
|
|
126
|
+
el.content = "[footnote #{footnote_number}]"
|
|
127
|
+
end
|
|
128
|
+
document.css("[role='doc-backlink']").map do |el|
|
|
129
|
+
backlink_number = " " + el.css("sup")[0].content if el.css("sup")[0].present?
|
|
130
|
+
el["aria-label"] = "go to where this is referenced#{backlink_number}"
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
123
134
|
attr_reader :input, :govspeak_document
|
|
124
135
|
|
|
125
136
|
def initialize(html, govspeak_document)
|
data/lib/govspeak/version.rb
CHANGED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
require "test_helper"
|
|
2
|
+
require "govspeak_test_helper"
|
|
3
|
+
|
|
4
|
+
class GovspeakFootnoteTest < Minitest::Test
|
|
5
|
+
include GovspeakTestHelper
|
|
6
|
+
|
|
7
|
+
test_given_govspeak "
|
|
8
|
+
Footnotes can be added[^1].
|
|
9
|
+
|
|
10
|
+
[^1]: And then later defined.
|
|
11
|
+
|
|
12
|
+
Footnotes can be added too[^2].
|
|
13
|
+
|
|
14
|
+
[^2]: And then later defined too.
|
|
15
|
+
|
|
16
|
+
This footnote has a reference number[^3].
|
|
17
|
+
|
|
18
|
+
And this footnote has the same reference number[^3].
|
|
19
|
+
|
|
20
|
+
[^3]: And then they both point here." do
|
|
21
|
+
assert_html_output(
|
|
22
|
+
%(
|
|
23
|
+
<p>Footnotes can be added<sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote">[footnote 1]</a></sup>.</p>
|
|
24
|
+
|
|
25
|
+
<p>Footnotes can be added too<sup id="fnref:2" role="doc-noteref"><a href="#fn:2" class="footnote">[footnote 2]</a></sup>.</p>
|
|
26
|
+
|
|
27
|
+
<p>This footnote has a reference number<sup id="fnref:3" role="doc-noteref"><a href="#fn:3" class="footnote">[footnote 3]</a></sup>.</p>
|
|
28
|
+
|
|
29
|
+
<p>And this footnote has the same reference number<sup id="fnref:3:1" role="doc-noteref"><a href="#fn:3" class="footnote">[footnote 3]</a></sup>.</p>
|
|
30
|
+
|
|
31
|
+
<div class="footnotes" role="doc-endnotes">
|
|
32
|
+
<ol>
|
|
33
|
+
<li id="fn:1" role="doc-endnote">
|
|
34
|
+
<p>And then later defined. <a href="#fnref:1" class="reversefootnote" role="doc-backlink" aria-label="go to where this is referenced">↩</a></p>
|
|
35
|
+
</li>
|
|
36
|
+
<li id="fn:2" role="doc-endnote">
|
|
37
|
+
<p>And then later defined too. <a href="#fnref:2" class="reversefootnote" role="doc-backlink" aria-label="go to where this is referenced">↩</a></p>
|
|
38
|
+
</li>
|
|
39
|
+
<li id="fn:3" role="doc-endnote">
|
|
40
|
+
<p>And then they both point here. <a href="#fnref:3" class="reversefootnote" role="doc-backlink" aria-label="go to where this is referenced">↩</a> <a href="#fnref:3:1" class="reversefootnote" role="doc-backlink" aria-label="go to where this is referenced 2">↩<sup>2</sup></a></p>
|
|
41
|
+
</li>
|
|
42
|
+
</ol>
|
|
43
|
+
</div>),
|
|
44
|
+
)
|
|
45
|
+
end
|
|
46
|
+
end
|
data/test/govspeak_test.rb
CHANGED
|
@@ -440,6 +440,25 @@ Teston
|
|
|
440
440
|
</div>)
|
|
441
441
|
end
|
|
442
442
|
|
|
443
|
+
test_given_govspeak "
|
|
444
|
+
$CTA
|
|
445
|
+
Click here to start the tool
|
|
446
|
+
$CTA
|
|
447
|
+
|
|
448
|
+
$C
|
|
449
|
+
Here is some text
|
|
450
|
+
$C
|
|
451
|
+
" do
|
|
452
|
+
assert_html_output %(
|
|
453
|
+
<div class="call-to-action">
|
|
454
|
+
<p>Click here to start the tool</p>
|
|
455
|
+
</div>
|
|
456
|
+
|
|
457
|
+
<div class="contact">
|
|
458
|
+
<p>Here is some text</p>
|
|
459
|
+
</div>)
|
|
460
|
+
end
|
|
461
|
+
|
|
443
462
|
test_given_govspeak "
|
|
444
463
|
[internal link](http://www.not-external.com)
|
|
445
464
|
|
|
@@ -647,6 +666,11 @@ Teston
|
|
|
647
666
|
assert_equal "<script>doGoodThings();</script>", document.to_html.strip
|
|
648
667
|
end
|
|
649
668
|
|
|
669
|
+
test "it can exclude stipulated elements from sanitization" do
|
|
670
|
+
document = Govspeak::Document.new("<uncommon-element>some content</uncommon-element>", allowed_elements: %w[uncommon-element])
|
|
671
|
+
assert_equal "<uncommon-element>some content</uncommon-element>", document.to_html.strip
|
|
672
|
+
end
|
|
673
|
+
|
|
650
674
|
test "identifies a Govspeak document containing malicious HTML as invalid" do
|
|
651
675
|
document = Govspeak::Document.new("<script>doBadThings();</script>")
|
|
652
676
|
refute document.valid?
|
data/test/html_sanitizer_test.rb
CHANGED
|
@@ -96,4 +96,10 @@ class HtmlSanitizerTest < Minitest::Test
|
|
|
96
96
|
assert_equal "<table><thead><tr><th>thing</th></tr></thead><tbody><tr><td>thing</td></tr></tbody></table>", Govspeak::HtmlSanitizer.new(html).sanitize
|
|
97
97
|
end
|
|
98
98
|
end
|
|
99
|
+
|
|
100
|
+
test "excludes specified elements from sanitization" do
|
|
101
|
+
html = "<custom-allowed-element><p>text</p></custom-allowed-element>"
|
|
102
|
+
assert_equal "<p>text</p>", Govspeak::HtmlSanitizer.new(html).sanitize
|
|
103
|
+
assert_equal html, Govspeak::HtmlSanitizer.new(html).sanitize(allowed_elements: %w[custom-allowed-element])
|
|
104
|
+
end
|
|
99
105
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: govspeak
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 6.
|
|
4
|
+
version: 6.6.0
|
|
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:
|
|
11
|
+
date: 2021-01-14 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: actionview
|
|
@@ -54,16 +54,16 @@ dependencies:
|
|
|
54
54
|
name: govuk_publishing_components
|
|
55
55
|
requirement: !ruby/object:Gem::Requirement
|
|
56
56
|
requirements:
|
|
57
|
-
- - "
|
|
57
|
+
- - ">="
|
|
58
58
|
- !ruby/object:Gem::Version
|
|
59
|
-
version: 23
|
|
59
|
+
version: '23'
|
|
60
60
|
type: :runtime
|
|
61
61
|
prerelease: false
|
|
62
62
|
version_requirements: !ruby/object:Gem::Requirement
|
|
63
63
|
requirements:
|
|
64
|
-
- - "
|
|
64
|
+
- - ">="
|
|
65
65
|
- !ruby/object:Gem::Version
|
|
66
|
-
version: 23
|
|
66
|
+
version: '23'
|
|
67
67
|
- !ruby/object:Gem::Dependency
|
|
68
68
|
name: htmlentities
|
|
69
69
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -82,14 +82,14 @@ dependencies:
|
|
|
82
82
|
name: i18n
|
|
83
83
|
requirement: !ruby/object:Gem::Requirement
|
|
84
84
|
requirements:
|
|
85
|
-
- - "
|
|
85
|
+
- - ">="
|
|
86
86
|
- !ruby/object:Gem::Version
|
|
87
87
|
version: '0.7'
|
|
88
88
|
type: :runtime
|
|
89
89
|
prerelease: false
|
|
90
90
|
version_requirements: !ruby/object:Gem::Requirement
|
|
91
91
|
requirements:
|
|
92
|
-
- - "
|
|
92
|
+
- - ">="
|
|
93
93
|
- !ruby/object:Gem::Version
|
|
94
94
|
version: '0.7'
|
|
95
95
|
- !ruby/object:Gem::Dependency
|
|
@@ -174,14 +174,14 @@ dependencies:
|
|
|
174
174
|
requirements:
|
|
175
175
|
- - "~>"
|
|
176
176
|
- !ruby/object:Gem::Version
|
|
177
|
-
version: 5.14
|
|
177
|
+
version: '5.14'
|
|
178
178
|
type: :development
|
|
179
179
|
prerelease: false
|
|
180
180
|
version_requirements: !ruby/object:Gem::Requirement
|
|
181
181
|
requirements:
|
|
182
182
|
- - "~>"
|
|
183
183
|
- !ruby/object:Gem::Version
|
|
184
|
-
version: 5.14
|
|
184
|
+
version: '5.14'
|
|
185
185
|
- !ruby/object:Gem::Dependency
|
|
186
186
|
name: pry-byebug
|
|
187
187
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -336,6 +336,7 @@ files:
|
|
|
336
336
|
- test/govspeak_button_test.rb
|
|
337
337
|
- test/govspeak_contacts_test.rb
|
|
338
338
|
- test/govspeak_extract_contact_content_ids_test.rb
|
|
339
|
+
- test/govspeak_footnote_test.rb
|
|
339
340
|
- test/govspeak_images_bang_test.rb
|
|
340
341
|
- test/govspeak_images_test.rb
|
|
341
342
|
- test/govspeak_link_extractor_test.rb
|
|
@@ -382,6 +383,7 @@ test_files:
|
|
|
382
383
|
- test/govspeak_button_test.rb
|
|
383
384
|
- test/govspeak_extract_contact_content_ids_test.rb
|
|
384
385
|
- test/govspeak_test_helper.rb
|
|
386
|
+
- test/govspeak_footnote_test.rb
|
|
385
387
|
- test/govspeak_link_test.rb
|
|
386
388
|
- test/govspeak_structured_headers_test.rb
|
|
387
389
|
- test/html_sanitizer_test.rb
|