govspeak 6.5.9 → 6.7.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 +23 -0
- data/README.md +23 -6
- data/lib/govspeak.rb +8 -4
- data/lib/govspeak/html_sanitizer.rb +5 -4
- data/lib/govspeak/version.rb +1 -1
- data/lib/templates/contact.html.erb +1 -1
- data/test/govspeak_contacts_test.rb +2 -2
- data/test/govspeak_footnote_test.rb +4 -4
- data/test/govspeak_test.rb +25 -1
- data/test/html_sanitizer_test.rb +6 -0
- metadata +8 -14
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3b07175e22a88ddf687631c2a157d00f9649efc118ab3e535d95cbda00918d43
|
|
4
|
+
data.tar.gz: 430f7d18852c8fdd549812c0260b118108292f34f2767902217c9d57a80d1f8b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 0fd6c1d0b6e8a416fdeb6d7aba99868dfb8e9ccf80191666dc771dcdf56a9bf396297569759c172608c31daf7bf75a891914e98713fc0e99b8458220b3dd7934
|
|
7
|
+
data.tar.gz: 8a04ab8364ea6ac989b4a1549ce8c4f152ad57988144183f7db00b5b256fce4b5823d79ac611a4078f75ccee5bd1d42f5a81344140979d2066916c2693a35dc4
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,26 @@
|
|
|
1
|
+
## Unreleased
|
|
2
|
+
|
|
3
|
+
## 6.7.1
|
|
4
|
+
|
|
5
|
+
* Update failing test [212](https://github.com/alphagov/govspeak/pull/212)
|
|
6
|
+
* Fix stats headline HTML semantics [213](https://github.com/alphagov/govspeak/pull/213)
|
|
7
|
+
|
|
8
|
+
## 6.7.0
|
|
9
|
+
|
|
10
|
+
* Update heading & docs [#206](https://github.com/alphagov/govspeak/pull/206)
|
|
11
|
+
|
|
12
|
+
## 6.6.0
|
|
13
|
+
|
|
14
|
+
* Allow passed elements to be relaxed from sanitization [#203](https://github.com/alphagov/govspeak/pull/203)
|
|
15
|
+
|
|
16
|
+
## 6.5.11
|
|
17
|
+
|
|
18
|
+
* Fix issue rendering $CTA blocks before $C (PR#202)
|
|
19
|
+
|
|
20
|
+
## 6.5.10
|
|
21
|
+
|
|
22
|
+
* Be optimistic in versions of govuk_publishing_components and i18n allowed (PR#200)
|
|
23
|
+
|
|
1
24
|
## 6.5.9
|
|
2
25
|
|
|
3
26
|
* Adjust footnote markup to accommodate multiple references (PR#198)
|
data/README.md
CHANGED
|
@@ -18,6 +18,23 @@ then create a new document
|
|
|
18
18
|
doc = Govspeak::Document.new "^Test^"
|
|
19
19
|
puts doc.to_html
|
|
20
20
|
|
|
21
|
+
## Changes appearing across GOV.UK
|
|
22
|
+
|
|
23
|
+
Some additional steps or considerations are needed to ensure changes to govspeak cascade across GOV.UK in a holistic way.
|
|
24
|
+
|
|
25
|
+
Once govspeak has been updated and version incremented then:
|
|
26
|
+
- [`govuk_publishing_components` govspeak](https://components.publishing.service.gov.uk/component-guide/govspeak) will also need updating to reflect your most recent change.
|
|
27
|
+
- [Publishing apps](https://docs.publishing.service.gov.uk/apps.html) (including but not limited to [content-publisher](https://github.com/alphagov/content-publisher) & [whitehall](https://github.com/alphagov/whitehall)) also use govspeak, these apps will need to be released with the new govspeak version present.
|
|
28
|
+
|
|
29
|
+
Also, consider if:
|
|
30
|
+
- [whitehall](https://github.com/alphagov/whitehall) needs updating (as custom govspeak changes are present)
|
|
31
|
+
- [govuk-content-schema](https://github.com/alphagov/govuk-content-schemas) needs updating
|
|
32
|
+
- [govpspeak-preview](https://github.com/alphagov/govspeak-preview) is worth updating
|
|
33
|
+
|
|
34
|
+
Any pages that use govspeak to generate Content will need to *republished* in order for the new changes to be reflected.
|
|
35
|
+
|
|
36
|
+
- Data Labs can help identify which pages need updating by [submitting a request](https://gov-uk.atlassian.net/wiki/spaces/GOVUK/pages/1860075525/GOV.UK+Data+Labs#Submitting-a-data-science-request) and [#govuk-2ndline](https://docs.publishing.service.gov.uk/manual/2nd-line.html) can help with republishing
|
|
37
|
+
|
|
21
38
|
# Extensions
|
|
22
39
|
|
|
23
40
|
In addition to the [standard Markdown syntax](http://daringfireball.net/projects/markdown/syntax "Markdown syntax"), we have added our own extensions.
|
|
@@ -65,7 +82,7 @@ creates an example box
|
|
|
65
82
|
|
|
66
83
|
## Highlights
|
|
67
84
|
|
|
68
|
-
### Advisory
|
|
85
|
+
### Advisory (DEPRECATED: marked for removal. Use 'Information callouts' instead.)
|
|
69
86
|
|
|
70
87
|
@This is a very important message or warning@
|
|
71
88
|
|
|
@@ -77,7 +94,7 @@ highlights the enclosed text in yellow
|
|
|
77
94
|
</h3>
|
|
78
95
|
```
|
|
79
96
|
|
|
80
|
-
### Answer
|
|
97
|
+
### Answer (DEPRECATED: marked for removal)
|
|
81
98
|
|
|
82
99
|
{::highlight-answer}
|
|
83
100
|
The VAT rate is *20%*
|
|
@@ -106,9 +123,9 @@ Statistic headlines highlight important numbers in content. Displays a statistic
|
|
|
106
123
|
Creates the following:
|
|
107
124
|
|
|
108
125
|
```html
|
|
109
|
-
<
|
|
126
|
+
<div class="stat-headline">
|
|
110
127
|
<p><em>13.8bn</em> years since the big bang</p>
|
|
111
|
-
</
|
|
128
|
+
</div>
|
|
112
129
|
```
|
|
113
130
|
|
|
114
131
|
## Points of Contact
|
|
@@ -598,8 +615,8 @@ will output
|
|
|
598
615
|
```html
|
|
599
616
|
<div id="contact_123" class="contact">
|
|
600
617
|
<div class="content">
|
|
601
|
-
<h3>Government Digital Service</h3>
|
|
602
618
|
<div class="vcard contact-inner">
|
|
619
|
+
<p>Government Digital Service</p>
|
|
603
620
|
<div class="email-url-number">
|
|
604
621
|
<p class="email">
|
|
605
622
|
<span class="type">Email</span>
|
|
@@ -676,4 +693,4 @@ which outputs
|
|
|
676
693
|
Start Now
|
|
677
694
|
<svg class="govuk-button__start-icon" xmlns="http://www.w3.org/2000/svg" width="17.5" height="19" viewBox="0 0 33 40" role="presentation" focusable="false"><path fill="currentColor" d="M0 0h13l20 20-20 20H0l20-20z"></path></svg>
|
|
678
695
|
</a>
|
|
679
|
-
```
|
|
696
|
+
```
|
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
|
|
@@ -184,8 +185,8 @@ module Govspeak
|
|
|
184
185
|
end
|
|
185
186
|
|
|
186
187
|
extension("stat-headline", %r${stat-headline}(.*?){/stat-headline}$m) do |body|
|
|
187
|
-
%(\n\n<
|
|
188
|
-
#{Govspeak::Document.new(body.strip).to_html}</
|
|
188
|
+
%(\n\n<div class="stat-headline">
|
|
189
|
+
#{Govspeak::Document.new(body.strip).to_html}</div>\n)
|
|
189
190
|
end
|
|
190
191
|
|
|
191
192
|
# FIXME: these surrounded_by arguments look dodgy
|
|
@@ -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],
|
data/lib/govspeak/version.rb
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
%>
|
|
5
5
|
<div id="contact_<%= contact.content_id %>" class="<%= ['contact', extra_class].flatten.join(' ') %>">
|
|
6
6
|
<div class="content">
|
|
7
|
-
<h3><%= contact.title %></h3>
|
|
8
7
|
<div class="vcard contact-inner">
|
|
8
|
+
<p><%= contact.title %></p>
|
|
9
9
|
<% contact.post_addresses.each do |address| %>
|
|
10
10
|
<%= Govspeak::HCardPresenter.new(address).render %>
|
|
11
11
|
<% end %>
|
|
@@ -62,8 +62,8 @@ class GovspeakContactsTest < Minitest::Test
|
|
|
62
62
|
expected_html_output = %(
|
|
63
63
|
<div id="contact_4f3383e4-48a2-4461-a41d-f85ea8b89ba0" class="contact postal-address">
|
|
64
64
|
<div class="content">
|
|
65
|
-
<h3>Government Digital Service</h3>
|
|
66
65
|
<div class="vcard contact-inner">
|
|
66
|
+
<p>Government Digital Service</p>
|
|
67
67
|
<p class="adr">
|
|
68
68
|
<span class="street-address">125 Kingsway</span><br>
|
|
69
69
|
<span class="locality">Holborn</span><br>
|
|
@@ -106,8 +106,8 @@ class GovspeakContactsTest < Minitest::Test
|
|
|
106
106
|
expected_html_output = %(
|
|
107
107
|
<div id="contact_4f3383e4-48a2-4461-a41d-f85ea8b89ba0" class="contact">
|
|
108
108
|
<div class="content">
|
|
109
|
-
<h3>Government Digital Service</h3>
|
|
110
109
|
<div class="vcard contact-inner">
|
|
110
|
+
<p>Government Digital Service</p>
|
|
111
111
|
<div class="email-url-number">
|
|
112
112
|
<p class="email">
|
|
113
113
|
<span class="type">Email</span>
|
|
@@ -20,13 +20,13 @@ class GovspeakFootnoteTest < Minitest::Test
|
|
|
20
20
|
[^3]: And then they both point here." do
|
|
21
21
|
assert_html_output(
|
|
22
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>
|
|
23
|
+
<p>Footnotes can be added<sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">[footnote 1]</a></sup>.</p>
|
|
24
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>
|
|
25
|
+
<p>Footnotes can be added too<sup id="fnref:2" role="doc-noteref"><a href="#fn:2" class="footnote" rel="footnote">[footnote 2]</a></sup>.</p>
|
|
26
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>
|
|
27
|
+
<p>This footnote has a reference number<sup id="fnref:3" role="doc-noteref"><a href="#fn:3" class="footnote" rel="footnote">[footnote 3]</a></sup>.</p>
|
|
28
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>
|
|
29
|
+
<p>And this footnote has the same reference number<sup id="fnref:3:1" role="doc-noteref"><a href="#fn:3" class="footnote" rel="footnote">[footnote 3]</a></sup>.</p>
|
|
30
30
|
|
|
31
31
|
<div class="footnotes" role="doc-endnotes">
|
|
32
32
|
<ol>
|
data/test/govspeak_test.rb
CHANGED
|
@@ -30,7 +30,7 @@ class GovspeakTest < Minitest::Test
|
|
|
30
30
|
|
|
31
31
|
test "stat-headline block extension" do
|
|
32
32
|
rendered = Govspeak::Document.new("this \n{stat-headline}*13.8bn* Age of the universe in years{/stat-headline}").to_html
|
|
33
|
-
assert_equal %(<p>this</p>\n\n<
|
|
33
|
+
assert_equal %(<p>this</p>\n\n<div class="stat-headline">\n<p><em>13.8bn</em> Age of the universe in years</p>\n</div>\n), rendered
|
|
34
34
|
end
|
|
35
35
|
|
|
36
36
|
test "extracts headers with text, level and generated id" do
|
|
@@ -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.7.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:
|
|
11
|
+
date: 2021-05-17 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: actionview
|
|
@@ -56,20 +56,14 @@ dependencies:
|
|
|
56
56
|
requirements:
|
|
57
57
|
- - ">="
|
|
58
58
|
- !ruby/object:Gem::Version
|
|
59
|
-
version: '23
|
|
60
|
-
- - "<"
|
|
61
|
-
- !ruby/object:Gem::Version
|
|
62
|
-
version: '23.4'
|
|
59
|
+
version: '23'
|
|
63
60
|
type: :runtime
|
|
64
61
|
prerelease: false
|
|
65
62
|
version_requirements: !ruby/object:Gem::Requirement
|
|
66
63
|
requirements:
|
|
67
64
|
- - ">="
|
|
68
65
|
- !ruby/object:Gem::Version
|
|
69
|
-
version: '23
|
|
70
|
-
- - "<"
|
|
71
|
-
- !ruby/object:Gem::Version
|
|
72
|
-
version: '23.4'
|
|
66
|
+
version: '23'
|
|
73
67
|
- !ruby/object:Gem::Dependency
|
|
74
68
|
name: htmlentities
|
|
75
69
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -88,14 +82,14 @@ dependencies:
|
|
|
88
82
|
name: i18n
|
|
89
83
|
requirement: !ruby/object:Gem::Requirement
|
|
90
84
|
requirements:
|
|
91
|
-
- - "
|
|
85
|
+
- - ">="
|
|
92
86
|
- !ruby/object:Gem::Version
|
|
93
87
|
version: '0.7'
|
|
94
88
|
type: :runtime
|
|
95
89
|
prerelease: false
|
|
96
90
|
version_requirements: !ruby/object:Gem::Requirement
|
|
97
91
|
requirements:
|
|
98
|
-
- - "
|
|
92
|
+
- - ">="
|
|
99
93
|
- !ruby/object:Gem::Version
|
|
100
94
|
version: '0.7'
|
|
101
95
|
- !ruby/object:Gem::Dependency
|
|
@@ -180,14 +174,14 @@ dependencies:
|
|
|
180
174
|
requirements:
|
|
181
175
|
- - "~>"
|
|
182
176
|
- !ruby/object:Gem::Version
|
|
183
|
-
version: 5.14
|
|
177
|
+
version: '5.14'
|
|
184
178
|
type: :development
|
|
185
179
|
prerelease: false
|
|
186
180
|
version_requirements: !ruby/object:Gem::Requirement
|
|
187
181
|
requirements:
|
|
188
182
|
- - "~>"
|
|
189
183
|
- !ruby/object:Gem::Version
|
|
190
|
-
version: 5.14
|
|
184
|
+
version: '5.14'
|
|
191
185
|
- !ruby/object:Gem::Dependency
|
|
192
186
|
name: pry-byebug
|
|
193
187
|
requirement: !ruby/object:Gem::Requirement
|