govspeak 6.5.9 → 6.7.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 948aced50c3d3842255ea4206a651229de59b2beef42e0c50e55e204354d9b5f
4
- data.tar.gz: cc55abe4b54b112a3aa1cb350a94270b11b9f0c11a5ca71479f55bb0efbf657d
3
+ metadata.gz: 3b07175e22a88ddf687631c2a157d00f9649efc118ab3e535d95cbda00918d43
4
+ data.tar.gz: 430f7d18852c8fdd549812c0260b118108292f34f2767902217c9d57a80d1f8b
5
5
  SHA512:
6
- metadata.gz: 1e0c1b0d6ca1fe4999e4135536328ecdc60bd34f368d986a808cee6de687f58198a080c19beffd47df6d80130edd2010eb1a09ccd840ea8adb9375c0b747e533
7
- data.tar.gz: e47aeeabecc4ffccff7342d1a1ad2e1ddd6cd8aabf5850f740fa3bf5ecdd9395bbded84222d55a5c8998748d7491a649793c550ab49564cd098486623684b275
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
- <aside class="stat-headline">
126
+ <div class="stat-headline">
110
127
  <p><em>13.8bn</em> years since the big bang</p>
111
- </aside>
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<aside class="stat-headline">
188
- #{Govspeak::Document.new(body.strip).to_html}</aside>\n)
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
- Sanitize.clean(@dirty_html, Sanitize::Config.merge(sanitize_config, transformers: transformers))
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],
@@ -1,3 +1,3 @@
1
1
  module Govspeak
2
- VERSION = "6.5.9".freeze
2
+ VERSION = "6.7.1".freeze
3
3
  end
@@ -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>
@@ -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<aside class="stat-headline">\n<p><em>13.8bn</em> Age of the universe in years</p>\n</aside>\n), rendered
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?
@@ -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.5.9
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: 2020-11-09 00:00:00.000000000 Z
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.0'
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.0'
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.1
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.1
184
+ version: '5.14'
191
185
  - !ruby/object:Gem::Dependency
192
186
  name: pry-byebug
193
187
  requirement: !ruby/object:Gem::Requirement