govspeak 6.7.1 → 6.7.5

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: 3b07175e22a88ddf687631c2a157d00f9649efc118ab3e535d95cbda00918d43
4
- data.tar.gz: 430f7d18852c8fdd549812c0260b118108292f34f2767902217c9d57a80d1f8b
3
+ metadata.gz: fb4fa452bfd1c6f1cdff6b638f91dfbc9961ea2bd7568f4feadd12fe73772532
4
+ data.tar.gz: 925ff3efcbb3b3a9a1aa6e0319e9f5a3ec1540febd0168b8517c5aa884e6e69c
5
5
  SHA512:
6
- metadata.gz: 0fd6c1d0b6e8a416fdeb6d7aba99868dfb8e9ccf80191666dc771dcdf56a9bf396297569759c172608c31daf7bf75a891914e98713fc0e99b8458220b3dd7934
7
- data.tar.gz: 8a04ab8364ea6ac989b4a1549ce8c4f152ad57988144183f7db00b5b256fce4b5823d79ac611a4078f75ccee5bd1d42f5a81344140979d2066916c2693a35dc4
6
+ metadata.gz: 574ea02a4f90e336a7c2a3b6642a7c1fe91924e8d71f4c55eb71053875c607c19de73aefbb34218d0cbe563c8e95982baf18ce42860a1002e58008efab20a93e
7
+ data.tar.gz: db21f5a85823c27024ff78970ec8d8dab64584910f90fdbed5649516abfbf5110fca8c52c99b978c54db3e060e1c654ac46e0995b87f5b8ab400c9dfa971b756
data/CHANGELOG.md CHANGED
@@ -1,4 +1,19 @@
1
- ## Unreleased
1
+ ## 6.7.5
2
+
3
+ * Fix footnotes in call-to-action boxes [222](https://github.com/alphagov/govspeak/pull/222)
4
+
5
+ ## 6.7.4
6
+
7
+ * Remove Nokogumbo dependency to [resolve warning](https://github.com/sparklemotion/nokogiri/issues/2205) [220](https://github.com/alphagov/govspeak/pull/220)
8
+
9
+ ## 6.7.3
10
+
11
+ * Fix regex for footnotes in legislative lists [218](https://github.com/alphagov/govspeak/pull/218)
12
+
13
+ ## 6.7.2
14
+
15
+ * Minimum Ruby version specified at 2.6 [215](https://github.com/alphagov/govspeak/pull/215)
16
+ * Fix footnotes in legislative lists [216](https://github.com/alphagov/govspeak/pull/216)
2
17
 
3
18
  ## 6.7.1
4
19
 
@@ -30,9 +30,10 @@ module Govspeak
30
30
  def find_headers(parent)
31
31
  headers = []
32
32
 
33
- if parent.type == :header
33
+ case parent.type
34
+ when :header
34
35
  headers << build_header(parent)
35
- elsif parent.type == :html_element
36
+ when :html_element
36
37
  parent.children.each do |child|
37
38
  if child.type == :header
38
39
  headers << build_header(child)
@@ -126,7 +126,7 @@ module Govspeak
126
126
  el.content = "[footnote #{footnote_number}]"
127
127
  end
128
128
  document.css("[role='doc-backlink']").map do |el|
129
- backlink_number = " " + el.css("sup")[0].content if el.css("sup")[0].present?
129
+ backlink_number = " #{el.css('sup')[0].content}" if el.css("sup")[0].present?
130
130
  el["aria-label"] = "go to where this is referenced#{backlink_number}"
131
131
  end
132
132
  end
@@ -4,6 +4,7 @@ require "htmlentities"
4
4
  module Govspeak
5
5
  class AttachmentPresenter
6
6
  attr_reader :attachment
7
+
7
8
  include ActionView::Helpers::TagHelper
8
9
  include ActionView::Helpers::NumberHelper
9
10
  include ActionView::Helpers::TextHelper
@@ -25,7 +26,7 @@ module Govspeak
25
26
  end
26
27
 
27
28
  def file_extension
28
- # Note: this is a separate parameter rather than being calculated from the
29
+ # NOTE: this is a separate parameter rather than being calculated from the
29
30
  # filename because at the time of writing not all apps were using the effects
30
31
  # of this field.
31
32
  attachment[:file_extension]
@@ -23,30 +23,30 @@ module Govspeak
23
23
 
24
24
  def post_addresses
25
25
  @post_addresses ||= begin
26
- addresses = contact.dig(:details, :post_addresses) || []
27
- filter_post_addresses(addresses)
28
- end
26
+ addresses = contact.dig(:details, :post_addresses) || []
27
+ filter_post_addresses(addresses)
28
+ end
29
29
  end
30
30
 
31
31
  def email_addresses
32
32
  @email_addresses ||= begin
33
- emails = contact.dig(:details, :email_addresses) || []
34
- emails.select { |e| e[:email].present? }
35
- end
33
+ emails = contact.dig(:details, :email_addresses) || []
34
+ emails.select { |e| e[:email].present? }
35
+ end
36
36
  end
37
37
 
38
38
  def phone_numbers
39
39
  @phone_numbers ||= begin
40
- phone_numbers = contact.dig(:details, :phone_numbers) || []
41
- phone_numbers.select { |p| p[:number].present? }
42
- end
40
+ phone_numbers = contact.dig(:details, :phone_numbers) || []
41
+ phone_numbers.select { |p| p[:number].present? }
42
+ end
43
43
  end
44
44
 
45
45
  def contact_form_links
46
46
  @contact_form_links ||= begin
47
- contact_form_links = contact.dig(:details, :contact_form_links) || []
48
- contact_form_links.select { |c| c[:link].present? }
49
- end
47
+ contact_form_links = contact.dig(:details, :contact_form_links) || []
48
+ contact_form_links.select { |c| c[:link].present? }
49
+ end
50
50
  end
51
51
 
52
52
  private
@@ -1,3 +1,3 @@
1
1
  module Govspeak
2
- VERSION = "6.7.1".freeze
2
+ VERSION = "6.7.5".freeze
3
3
  end
data/lib/govspeak.rb CHANGED
@@ -6,7 +6,6 @@ require "htmlentities"
6
6
  require "kramdown"
7
7
  require "kramdown/parser/govuk"
8
8
  require "nokogiri"
9
- require "nokogumbo"
10
9
  require "rinku"
11
10
  require "sanitize"
12
11
  require "govspeak/header_extractor"
@@ -62,18 +61,30 @@ module Govspeak
62
61
  sanitize: true,
63
62
  syntax_highlighter: nil }.merge(options)
64
63
  @options[:entity_output] = :symbolic
64
+ @footnote_definition_html = nil
65
+ @acronyms = []
65
66
  end
66
67
 
67
68
  def to_html
68
69
  @to_html ||= begin
69
- html = if @options[:sanitize]
70
- HtmlSanitizer.new(kramdown_doc.to_html).sanitize(allowed_elements: @allowed_elements)
71
- else
72
- kramdown_doc.to_html
73
- end
70
+ html = if @options[:sanitize]
71
+ HtmlSanitizer.new(kramdown_doc.to_html).sanitize(allowed_elements: @allowed_elements)
72
+ else
73
+ kramdown_doc.to_html
74
+ end
75
+
76
+ unless @footnote_definition_html.nil?
77
+ regex = /<div class="footnotes".*[<\/div>]/m
78
+
79
+ if html.scan(regex).empty?
80
+ html << @footnote_definition_html
81
+ else
82
+ html.gsub!(regex, @footnote_definition_html)
83
+ end
84
+ end
74
85
 
75
- Govspeak::PostProcessor.process(html, self)
76
- end
86
+ Govspeak::PostProcessor.process(html, self)
87
+ end
77
88
  end
78
89
 
79
90
  def to_liquid
@@ -110,6 +121,9 @@ module Govspeak
110
121
  def preprocess(source)
111
122
  source = Govspeak::BlockquoteExtraQuoteRemover.remove(source)
112
123
  source = remove_forbidden_characters(source)
124
+
125
+ footnote_definitions(source)
126
+
113
127
  self.class.extensions.each do |_, regexp, block|
114
128
  source.gsub!(regexp) do
115
129
  instance_exec(*Regexp.last_match.captures, &block)
@@ -118,6 +132,40 @@ module Govspeak
118
132
  source
119
133
  end
120
134
 
135
+ def footnote_definitions(source)
136
+ is_legislative_list = source.scan(/\$LegislativeList.*?\[\^\d\]*.*?\$EndLegislativeList/m).size.positive?
137
+ is_cta = source.scan(/\$CTA.*?\[\^\d\]*.*?\$CTA/m).size.positive?
138
+ footnotes = source.scan(/\[\^(\d+)\]:(.*)/)
139
+ @acronyms = source.scan(/(?<=\*)\[(.*)\]:(.*)/)
140
+ if (is_legislative_list || is_cta) && footnotes.size.positive?
141
+ list_items = footnotes.map do |footnote|
142
+ number = footnote[0]
143
+ text = footnote[1].strip
144
+ footnote_definition = Govspeak::Document.new(text).to_html[/(?<=<p>).*(?=<\/p>)/]
145
+
146
+ <<~HTML_SNIPPET
147
+ <li id="fn:#{number}" role="doc-endnote">
148
+ <p>
149
+ #{footnote_definition}<a href="#fnref:#{number}" class="reversefootnote" role="doc-backlink" aria-label="go to where this is referenced">↩</a>
150
+ </p>
151
+ </li>
152
+ HTML_SNIPPET
153
+ end
154
+
155
+ @footnote_definition_html = <<~HTML_CONTAINER
156
+ <div class="footnotes" role="doc-endnotes">
157
+ <ol>
158
+ #{list_items.join.strip}
159
+ </ol>
160
+ </div>
161
+ HTML_CONTAINER
162
+ end
163
+
164
+ unless @footnote_definition_html.nil? && @acronyms.size.positive?
165
+ add_acronym_alt_text(@footnote_definition_html)
166
+ end
167
+ end
168
+
121
169
  def remove_forbidden_characters(source)
122
170
  # These are characters that are not deemed not suitable for
123
171
  # markup: https://www.w3.org/TR/unicode-xml/#Charlist
@@ -161,7 +209,7 @@ module Govspeak
161
209
  ([^)]+) # capture inside of link text markdown
162
210
  \) # match end of link text markdown
163
211
  \s* # any whitespace between opening bracket and link
164
- {\/button} # match ending bracket
212
+ {/button} # match ending bracket
165
213
  (?:\r|\n|$) # non-capturing match to make sure end of line and linebreak
166
214
  }x) do |attributes, text, href|
167
215
  button_classes = "govuk-button"
@@ -273,10 +321,26 @@ module Govspeak
273
321
  lines.join
274
322
  end
275
323
 
324
+ extension("call-to-action", surrounded_by("$CTA")) do |body|
325
+ doc = Kramdown::Document.new(body.strip).to_html
326
+ doc = %(\n<div class="call-to-action">\n#{doc}</div>\n)
327
+ footnotes = body.scan(/\[\^(\d+)\]/).flatten
328
+
329
+ footnotes.each do |footnote|
330
+ html = "<sup id=\"fnref:#{footnote}\" role=\"doc-noteref\">" \
331
+ "<a href=\"#fn:#{footnote}\" class=\"footnote\" rel=\"footnote\">" \
332
+ "[footnote #{footnote}]</a></sup>"
333
+
334
+ doc.sub!(/(\[\^#{footnote}\])/, html)
335
+ end
336
+
337
+ add_acronym_alt_text(doc) if @acronyms.size.positive?
338
+ doc
339
+ end
340
+
276
341
  # More specific tags must be defined first. Those defined earlier have a
277
342
  # higher precedence for being matched. For example $CTA must be defined
278
343
  # before $C otherwise the first ($C)TA fill be matched to a contact tag.
279
- wrap_with_div("call-to-action", "$CTA", Govspeak::Document)
280
344
  wrap_with_div("summary", "$!")
281
345
  wrap_with_div("form-download", "$D")
282
346
  wrap_with_div("contact", "$C")
@@ -295,6 +359,18 @@ module Govspeak
295
359
  doc.gsub!("<ul>", "<ol>")
296
360
  doc.gsub!("</ul>", "</ol>")
297
361
  doc.sub!("<ol>", '<ol class="legislative-list">')
362
+
363
+ footnotes = body.scan(/\[\^(\d+)\]/).flatten
364
+
365
+ footnotes.each do |footnote|
366
+ html = "<sup id=\"fnref:#{footnote}\" role=\"doc-noteref\">" \
367
+ "<a href=\"#fn:#{footnote}\" class=\"footnote\" rel=\"footnote\">" \
368
+ "[footnote #{footnote}]</a></sup>"
369
+
370
+ doc.sub!(/(\[\^#{footnote}\])/, html)
371
+ end
372
+
373
+ add_acronym_alt_text(doc) if @acronyms.size.positive?
298
374
  end
299
375
  end
300
376
  end
@@ -386,6 +462,12 @@ module Govspeak
386
462
  def encode(text)
387
463
  HTMLEntities.new.encode(text)
388
464
  end
465
+
466
+ def add_acronym_alt_text(html)
467
+ @acronyms.each do |acronym|
468
+ html.gsub!(acronym[0], "<abbr title=\"#{acronym[1].strip}\">#{acronym[0]}</abbr>")
469
+ end
470
+ end
389
471
  end
390
472
  end
391
473
 
@@ -17,7 +17,7 @@ class GovspeakAttachmentTest < Minitest::Test
17
17
  }
18
18
 
19
19
  rendered = render_govspeak("[Attachment:attachment.pdf]", [attachment])
20
- assert_match(/<section class="gem-c-attachment">/, rendered)
20
+ assert_match(/<section class="gem-c-attachment/, rendered)
21
21
  assert_match(/Attachment Title/, rendered)
22
22
  end
23
23
 
@@ -32,7 +32,7 @@ class GovspeakAttachmentTest < Minitest::Test
32
32
  assert_equal("<p>some text [Attachment:attachment.pdf]</p>\n", rendered)
33
33
 
34
34
  rendered = render_govspeak("[Attachment:attachment.pdf] some text", [attachment])
35
- assert_match(/<section class="gem-c-attachment">/, rendered)
35
+ assert_match(/<section class="gem-c-attachment/, rendered)
36
36
  assert_match(/<p>some text<\/p>/, rendered)
37
37
  end
38
38
  end
@@ -15,7 +15,7 @@ class GovspeakAttachmentsImageTest < Minitest::Test
15
15
  end
16
16
 
17
17
  def compress_html(html)
18
- html.gsub(/[\n\r]+[\s]*/, "")
18
+ html.gsub(/[\n\r]+\s*/, "")
19
19
  end
20
20
 
21
21
  test "renders an empty string for an image attachment not found" do
@@ -7,34 +7,34 @@ class GovspeakTest < Minitest::Test
7
7
  include GovspeakTestHelper
8
8
 
9
9
  test_given_govspeak "{button start cross-domain-tracking:UA-23066786-5}[Start now](https://www.registertovote.service.gov.uk/register-to-vote/start){/button}" do
10
- assert_html_output '<p><a class="gem-c-button govuk-button govuk-button--start" role="button" data-module="cross-domain-tracking" data-tracking-code="UA-23066786-5" data-tracking-name="govspeakButtonTracker" href="https://www.registertovote.service.gov.uk/register-to-vote/start"> Start now <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></a></p>'
10
+ assert_html_selector 'a.gem-c-button.govuk-button--start[data-module="cross-domain-tracking"][data-tracking-code="UA-23066786-5"][href="https://www.registertovote.service.gov.uk/register-to-vote/start"]'
11
11
  assert_text_output "Start now"
12
12
  end
13
13
 
14
14
  # The same as above but with line breaks
15
15
  test_given_govspeak "{button start cross-domain-tracking:UA-23066786-5}\n\n\n[Start now](https://www.registertovote.service.gov.uk/register-to-vote/start)\n\n\n{/button}" do
16
- assert_html_output '<p><a class="gem-c-button govuk-button govuk-button--start" role="button" data-module="cross-domain-tracking" data-tracking-code="UA-23066786-5" data-tracking-name="govspeakButtonTracker" href="https://www.registertovote.service.gov.uk/register-to-vote/start"> Start now <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></a></p>'
16
+ assert_html_selector 'a.gem-c-button.govuk-button--start[data-module="cross-domain-tracking"][data-tracking-code="UA-23066786-5"][href="https://www.registertovote.service.gov.uk/register-to-vote/start"]'
17
17
  assert_text_output "Start now"
18
18
  end
19
19
 
20
20
  test_given_govspeak "{button cross-domain-tracking:UA-23066786-5}[Start now](https://www.registertovote.service.gov.uk/register-to-vote/start){/button}" do
21
- assert_html_output '<p><a class="gem-c-button govuk-button" role="button" data-module="cross-domain-tracking" data-tracking-code="UA-23066786-5" data-tracking-name="govspeakButtonTracker" href="https://www.registertovote.service.gov.uk/register-to-vote/start">Start now</a></p>'
21
+ assert_html_selector 'a.gem-c-button:not(.govuk-button--start)[data-module="cross-domain-tracking"][data-tracking-code="UA-23066786-5"][href="https://www.registertovote.service.gov.uk/register-to-vote/start"]'
22
22
  assert_text_output "Start now"
23
23
  end
24
24
 
25
25
  test_given_govspeak "{button start}[Start now](https://www.registertovote.service.gov.uk/register-to-vote/start){/button}" do
26
- assert_html_output '<p><a class="gem-c-button govuk-button govuk-button--start" role="button" href="https://www.registertovote.service.gov.uk/register-to-vote/start"> Start now <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></a></p>'
26
+ assert_html_selector 'a.gem-c-button.govuk-button--start[href="https://www.registertovote.service.gov.uk/register-to-vote/start"]'
27
27
  assert_text_output "Start now"
28
28
  end
29
29
 
30
30
  test_given_govspeak "{button}[Start now](https://www.registertovote.service.gov.uk/register-to-vote/start){/button}" do
31
- assert_html_output '<p><a class="gem-c-button govuk-button" role="button" href="https://www.registertovote.service.gov.uk/register-to-vote/start">Start now</a></p>'
31
+ assert_html_selector 'a.gem-c-button:not(.govuk-button--start)[href="https://www.registertovote.service.gov.uk/register-to-vote/start"]'
32
32
  assert_text_output "Start now"
33
33
  end
34
34
 
35
35
  # Test other text outputs
36
36
  test_given_govspeak "{button}[Something else](https://www.registertovote.service.gov.uk/register-to-vote/start){/button}" do
37
- assert_html_output '<p><a class="gem-c-button govuk-button" role="button" href="https://www.registertovote.service.gov.uk/register-to-vote/start">Something else</a></p>'
37
+ assert_html_selector 'a.gem-c-button[href="https://www.registertovote.service.gov.uk/register-to-vote/start"]'
38
38
  assert_text_output "Something else"
39
39
  end
40
40
 
@@ -54,22 +54,6 @@ class GovspeakTest < Minitest::Test
54
54
  assert_text_output "Text before the button with line breaks Start Now test after the button"
55
55
  end
56
56
 
57
- # Test README examples
58
- test_given_govspeak "{button}[Continue](https://gov.uk/random){/button}" do
59
- assert_html_output '<p><a class="gem-c-button govuk-button" role="button" href="https://gov.uk/random">Continue</a></p>'
60
- assert_text_output "Continue"
61
- end
62
-
63
- test_given_govspeak "{button start}[Start Now](https://gov.uk/random){/button}" do
64
- assert_html_output '<p><a class="gem-c-button govuk-button govuk-button--start" role="button" href="https://gov.uk/random"> Start Now <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></a></p>'
65
- assert_text_output "Start Now"
66
- end
67
-
68
- test_given_govspeak "{button start cross-domain-tracking:UA-XXXXXX-Y}[Start Now](https://example.com/external-service/start-now){/button}" do
69
- assert_html_output '<p><a class="gem-c-button govuk-button govuk-button--start" role="button" data-module="cross-domain-tracking" data-tracking-code="UA-XXXXXX-Y" data-tracking-name="govspeakButtonTracker" href="https://example.com/external-service/start-now"> Start Now <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></a></p>'
70
- assert_text_output "Start Now"
71
- end
72
-
73
57
  # Test indenting button govspeak results in no render, useful in guides
74
58
  test_given_govspeak " {button start cross-domain-tracking:UA-XXXXXX-Y}[Example](https://example.com/external-service/start-now){/button}" do
75
59
  assert_html_output %{
@@ -107,7 +91,7 @@ class GovspeakTest < Minitest::Test
107
91
  lorem lorem lorem
108
92
  lorem lorem lorem
109
93
 
110
- {button start}[Start Now](https://gov.uk/random){/button}
94
+ {button}[Random page](https://gov.uk/random){/button}
111
95
 
112
96
  lorem lorem lorem
113
97
  lorem lorem lorem
@@ -120,7 +104,7 @@ class GovspeakTest < Minitest::Test
120
104
  <p>lorem lorem lorem
121
105
  lorem lorem lorem</p>
122
106
 
123
- <p><a class="gem-c-button govuk-button govuk-button--start" role="button" href="https://gov.uk/random"> Start Now <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></a></p>
107
+ <p><a class="gem-c-button govuk-button" role="button" href="https://gov.uk/random">Random page</a></p>
124
108
 
125
109
  <p>lorem lorem lorem
126
110
  lorem lorem lorem</p>
@@ -51,7 +51,7 @@ class GovspeakContactsTest < Minitest::Test
51
51
  end
52
52
 
53
53
  def compress_html(html)
54
- html.gsub(/[\n\r]+[\s]*/, "")
54
+ html.gsub(/[\n\r]+\s*/, "")
55
55
  end
56
56
 
57
57
  test "contact is rendered when present in options[:contacts]" do
@@ -18,9 +18,7 @@ class GovspeakImagesBangTest < Minitest::Test
18
18
  test "!!n syntax renders an image in options[:images]" do
19
19
  given_govspeak "!!1", images: [Image.new] do
20
20
  assert_html_output(
21
- %(<figure class="image embedded">) +
22
- %(<div class="img"><img src="http://example.com/image.jpg" alt="my alt"></div>) +
23
- %(</figure>),
21
+ "<figure class=\"image embedded\"><div class=\"img\"><img src=\"http://example.com/image.jpg\" alt=\"my alt\"></div></figure>",
24
22
  )
25
23
  end
26
24
  end
@@ -28,9 +26,7 @@ class GovspeakImagesBangTest < Minitest::Test
28
26
  test "!!n syntax escapes alt text" do
29
27
  given_govspeak "!!1", images: [Image.new(alt_text: %(my alt '&"<>))] do
30
28
  assert_html_output(
31
- %(<figure class="image embedded">) +
32
- %(<div class="img"><img src="http://example.com/image.jpg" alt="my alt '&amp;&quot;&lt;&gt;"></div>) +
33
- %(</figure>),
29
+ "<figure class=\"image embedded\"><div class=\"img\"><img src=\"http://example.com/image.jpg\" alt=\"my alt '&amp;&quot;&lt;&gt;\"></div></figure>",
34
30
  )
35
31
  end
36
32
  end
@@ -48,10 +44,7 @@ class GovspeakImagesBangTest < Minitest::Test
48
44
  test "!!n syntax adds image caption if given" do
49
45
  given_govspeak "!!1", images: [Image.new(caption: "My Caption & so on")] do
50
46
  assert_html_output(
51
- %(<figure class="image embedded">) +
52
- %(<div class="img"><img src="http://example.com/image.jpg" alt="my alt"></div>\n) +
53
- %(<figcaption><p>My Caption &amp; so on</p></figcaption>) +
54
- %(</figure>),
47
+ "<figure class=\"image embedded\"><div class=\"img\"><img src=\"http://example.com/image.jpg\" alt=\"my alt\"></div>\n<figcaption><p>My Caption &amp; so on</p></figcaption></figure>",
55
48
  )
56
49
  end
57
50
  end
@@ -59,9 +52,7 @@ class GovspeakImagesBangTest < Minitest::Test
59
52
  test "!!n syntax ignores a blank caption" do
60
53
  given_govspeak "!!1", images: [Image.new(caption: " ")] do
61
54
  assert_html_output(
62
- %(<figure class="image embedded">) +
63
- %(<div class="img"><img src="http://example.com/image.jpg" alt="my alt"></div>) +
64
- %(</figure>),
55
+ "<figure class=\"image embedded\"><div class=\"img\"><img src=\"http://example.com/image.jpg\" alt=\"my alt\"></div></figure>",
65
56
  )
66
57
  end
67
58
  end
@@ -69,10 +60,7 @@ class GovspeakImagesBangTest < Minitest::Test
69
60
  test "¡¡n syntax adds image credit if given" do
70
61
  given_govspeak "!!1", images: [Image.new(credit: "My Credit & so on")] do
71
62
  assert_html_output(
72
- %(<figure class="image embedded">) +
73
- %(<div class="img"><img src="http://example.com/image.jpg" alt="my alt"></div>\n) +
74
- %(<figcaption><p>Image credit: My Credit &amp; so on</p></figcaption>) +
75
- %(</figure>),
63
+ "<figure class=\"image embedded\"><div class=\"img\"><img src=\"http://example.com/image.jpg\" alt=\"my alt\"></div>\n<figcaption><p>Image credit: My Credit &amp; so on</p></figcaption></figure>",
76
64
  )
77
65
  end
78
66
  end
@@ -80,9 +68,7 @@ class GovspeakImagesBangTest < Minitest::Test
80
68
  test "!!n syntax ignores a blank credit" do
81
69
  given_govspeak "!!1", images: [Image.new(credit: " ")] do
82
70
  assert_html_output(
83
- %(<figure class="image embedded">) +
84
- %(<div class="img"><img src="http://example.com/image.jpg" alt="my alt"></div>) +
85
- %(</figure>),
71
+ "<figure class=\"image embedded\"><div class=\"img\"><img src=\"http://example.com/image.jpg\" alt=\"my alt\"></div></figure>",
86
72
  )
87
73
  end
88
74
  end
@@ -90,13 +76,7 @@ class GovspeakImagesBangTest < Minitest::Test
90
76
  test "!!n syntax adds image caption and credit if given" do
91
77
  given_govspeak "!!1", images: [Image.new(caption: "My Caption & so on", credit: "My Credit & so on")] do
92
78
  assert_html_output(
93
- %(<figure class="image embedded">) +
94
- %(<div class="img"><img src="http://example.com/image.jpg" alt="my alt"></div>\n) +
95
- %(<figcaption>) +
96
- %(<p>My Caption &amp; so on</p>\n) +
97
- %(<p>Image credit: My Credit &amp; so on</p>) +
98
- %(</figcaption>) +
99
- %(</figure>),
79
+ "<figure class=\"image embedded\"><div class=\"img\"><img src=\"http://example.com/image.jpg\" alt=\"my alt\"></div>\n<figcaption><p>My Caption &amp; so on</p>\n<p>Image credit: My Credit &amp; so on</p></figcaption></figure>",
100
80
  )
101
81
  end
102
82
  end
@@ -14,9 +14,7 @@ class GovspeakImagesTest < Minitest::Test
14
14
  test "Image:image-id syntax renders an image in options[:images]" do
15
15
  given_govspeak "[Image:image-id]", images: [build_image] do
16
16
  assert_html_output(
17
- %(<figure class="image embedded">) +
18
- %(<div class="img"><img src="http://example.com/image.jpg" alt="my alt"></div>) +
19
- %(</figure>),
17
+ "<figure class=\"image embedded\"><div class=\"img\"><img src=\"http://example.com/image.jpg\" alt=\"my alt\"></div></figure>",
20
18
  )
21
19
  end
22
20
  end
@@ -24,9 +22,7 @@ class GovspeakImagesTest < Minitest::Test
24
22
  test "Image:image-id syntax escapes alt text" do
25
23
  given_govspeak "[Image:image-id]", images: [build_image(alt_text: %(my alt '&"<>))] do
26
24
  assert_html_output(
27
- %(<figure class="image embedded">) +
28
- %(<div class="img"><img src="http://example.com/image.jpg" alt="my alt '&amp;&quot;&lt;&gt;"></div>) +
29
- %(</figure>),
25
+ "<figure class=\"image embedded\"><div class=\"img\"><img src=\"http://example.com/image.jpg\" alt=\"my alt '&amp;&quot;&lt;&gt;\"></div></figure>",
30
26
  )
31
27
  end
32
28
  end
@@ -39,10 +35,7 @@ class GovspeakImagesTest < Minitest::Test
39
35
  test "Image:image-id syntax adds image caption if given" do
40
36
  given_govspeak "[Image:image-id]", images: [build_image(caption: "My Caption & so on")] do
41
37
  assert_html_output(
42
- %(<figure class="image embedded">) +
43
- %(<div class="img"><img src="http://example.com/image.jpg" alt="my alt"></div>\n) +
44
- %(<figcaption><p>My Caption &amp; so on</p></figcaption>) +
45
- %(</figure>),
38
+ "<figure class=\"image embedded\"><div class=\"img\"><img src=\"http://example.com/image.jpg\" alt=\"my alt\"></div>\n<figcaption><p>My Caption &amp; so on</p></figcaption></figure>",
46
39
  )
47
40
  end
48
41
  end
@@ -50,9 +43,7 @@ class GovspeakImagesTest < Minitest::Test
50
43
  test "Image:image-id syntax ignores a blank caption" do
51
44
  given_govspeak "[Image:image-id]", images: [build_image(caption: " ")] do
52
45
  assert_html_output(
53
- %(<figure class="image embedded">) +
54
- %(<div class="img"><img src="http://example.com/image.jpg" alt="my alt"></div>) +
55
- %(</figure>),
46
+ "<figure class=\"image embedded\"><div class=\"img\"><img src=\"http://example.com/image.jpg\" alt=\"my alt\"></div></figure>",
56
47
  )
57
48
  end
58
49
  end
@@ -60,10 +51,7 @@ class GovspeakImagesTest < Minitest::Test
60
51
  test "Image:image-id syntax adds image credit if given" do
61
52
  given_govspeak "[Image:image-id]", images: [build_image(credit: "My Credit & so on")] do
62
53
  assert_html_output(
63
- %(<figure class="image embedded">) +
64
- %(<div class="img"><img src="http://example.com/image.jpg" alt="my alt"></div>\n) +
65
- %(<figcaption><p>Image credit: My Credit &amp; so on</p></figcaption>) +
66
- %(</figure>),
54
+ "<figure class=\"image embedded\"><div class=\"img\"><img src=\"http://example.com/image.jpg\" alt=\"my alt\"></div>\n<figcaption><p>Image credit: My Credit &amp; so on</p></figcaption></figure>",
67
55
  )
68
56
  end
69
57
  end
@@ -71,9 +59,7 @@ class GovspeakImagesTest < Minitest::Test
71
59
  test "Image:image-id syntax ignores a blank credit" do
72
60
  given_govspeak "[Image:image-id]", images: [build_image(credit: " ")] do
73
61
  assert_html_output(
74
- %(<figure class="image embedded">) +
75
- %(<div class="img"><img src="http://example.com/image.jpg" alt="my alt"></div>) +
76
- %(</figure>),
62
+ "<figure class=\"image embedded\"><div class=\"img\"><img src=\"http://example.com/image.jpg\" alt=\"my alt\"></div></figure>",
77
63
  )
78
64
  end
79
65
  end
@@ -81,13 +67,7 @@ class GovspeakImagesTest < Minitest::Test
81
67
  test "Image:image-id syntax adds image caption and credit if given" do
82
68
  given_govspeak "[Image:image-id]", images: [build_image(caption: "My Caption & so on", credit: "My Credit & so on")] do
83
69
  assert_html_output(
84
- %(<figure class="image embedded">) +
85
- %(<div class="img"><img src="http://example.com/image.jpg" alt="my alt"></div>\n) +
86
- %(<figcaption>) +
87
- %(<p>My Caption &amp; so on</p>\n) +
88
- %(<p>Image credit: My Credit &amp; so on</p>) +
89
- %(</figcaption>) +
90
- %(</figure>),
70
+ "<figure class=\"image embedded\"><div class=\"img\"><img src=\"http://example.com/image.jpg\" alt=\"my alt\"></div>\n<figcaption><p>My Caption &amp; so on</p>\n<p>Image credit: My Credit &amp; so on</p></figcaption></figure>",
91
71
  )
92
72
  end
93
73
  end
@@ -99,18 +79,13 @@ class GovspeakImagesTest < Minitest::Test
99
79
 
100
80
  given_govspeak "[Image:image-id]", images: [build_image] do
101
81
  assert_html_output(
102
- %(<figure class="image embedded">) +
103
- %(<div class="img"><img src="http://example.com/image.jpg" alt="my alt"></div>) +
104
- %(</figure>),
82
+ "<figure class=\"image embedded\"><div class=\"img\"><img src=\"http://example.com/image.jpg\" alt=\"my alt\"></div></figure>",
105
83
  )
106
84
  end
107
85
 
108
86
  given_govspeak "[Image:image-id] some text", images: [build_image] do
109
87
  assert_html_output(
110
- %(<figure class="image embedded">) +
111
- %(<div class="img"><img src="http://example.com/image.jpg" alt="my alt"></div>) +
112
- %(</figure>\n) +
113
- %(<p>some text</p>),
88
+ "<figure class=\"image embedded\"><div class=\"img\"><img src=\"http://example.com/image.jpg\" alt=\"my alt\"></div></figure>\n<p>some text</p>",
114
89
  )
115
90
  end
116
91
  end
@@ -473,6 +473,101 @@ Teston
473
473
  </div>)
474
474
  end
475
475
 
476
+ test_given_govspeak "
477
+ $CTA
478
+ Click here to start the tool[^1]
479
+ $CTA
480
+ [^1]: Footnote definition one
481
+ " do
482
+ assert_html_output %(
483
+ <div class="call-to-action">
484
+ <p>Click here to start the tool<sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">[footnote 1]</a></sup></p>
485
+ </div>
486
+ <div class="footnotes" role="doc-endnotes">
487
+ <ol>
488
+ <li id="fn:1" role="doc-endnote">
489
+ <p>
490
+ Footnote definition one<a href="#fnref:1" class="reversefootnote" role="doc-backlink" aria-label="go to where this is referenced">↩</a>
491
+ </p>
492
+ </li>
493
+ </ol>
494
+ </div>
495
+ )
496
+ end
497
+
498
+ test_given_govspeak "
499
+ $CTA
500
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit.
501
+ Fusce felis ante[^1], lobortis non quam sit amet, tempus interdum justo.
502
+ $CTA
503
+ $CTA
504
+ Pellentesque quam enim, egestas sit amet congue sit amet[^2], ultrices vitae arcu.
505
+ Fringilla, metus dui scelerisque est.
506
+ $CTA
507
+ [^1]: Footnote definition one
508
+ [^2]: Footnote definition two
509
+ " do
510
+ assert_html_output %(
511
+ <div class="call-to-action">
512
+ <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.
513
+ Fusce felis ante<sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">[footnote 1]</a></sup>, lobortis non quam sit amet, tempus interdum justo.</p>
514
+ </div>
515
+
516
+ <div class="call-to-action">
517
+ <p>Pellentesque quam enim, egestas sit amet congue sit amet<sup id="fnref:2" role="doc-noteref"><a href="#fn:2" class="footnote" rel="footnote">[footnote 2]</a></sup>, ultrices vitae arcu.
518
+ Fringilla, metus dui scelerisque est.</p>
519
+ </div>
520
+ <div class="footnotes" role="doc-endnotes">
521
+ <ol>
522
+ <li id="fn:1" role="doc-endnote">
523
+ <p>
524
+ Footnote definition one<a href="#fnref:1" class="reversefootnote" role="doc-backlink" aria-label="go to where this is referenced">↩</a>
525
+ </p>
526
+ </li>
527
+ <li id="fn:2" role="doc-endnote">
528
+ <p>
529
+ Footnote definition two<a href="#fnref:2" class="reversefootnote" role="doc-backlink" aria-label="go to where this is referenced">↩</a>
530
+ </p>
531
+ </li>
532
+ </ol>
533
+ </div>
534
+ )
535
+ end
536
+
537
+ test_given_govspeak "
538
+ $CTA
539
+ Click here to start the tool[^1]
540
+ $CTA
541
+
542
+ Lorem ipsum dolor sit amet[^2]
543
+
544
+ [^1]: Footnote definition 1
545
+ [^2]: Footnote definition 2
546
+ " do
547
+ assert_html_output %(
548
+ <div class="call-to-action">
549
+ <p>Click here to start the tool<sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">[footnote 1]</a></sup></p>
550
+ </div>
551
+
552
+ <p>Lorem ipsum dolor sit amet<sup id="fnref:2" role="doc-noteref"><a href="#fn:2" class="footnote" rel="footnote">[footnote 2]</a></sup></p>
553
+
554
+ <div class="footnotes" role="doc-endnotes">
555
+ <ol>
556
+ <li id="fn:1" role="doc-endnote">
557
+ <p>
558
+ Footnote definition 1<a href="#fnref:1" class="reversefootnote" role="doc-backlink" aria-label="go to where this is referenced">↩</a>
559
+ </p>
560
+ </li>
561
+ <li id="fn:2" role="doc-endnote">
562
+ <p>
563
+ Footnote definition 2<a href="#fnref:2" class="reversefootnote" role="doc-backlink" aria-label="go to where this is referenced">↩</a>
564
+ </p>
565
+ </li>
566
+ </ol>
567
+ </div>
568
+ )
569
+ end
570
+
476
571
  test_given_govspeak "
477
572
  1. rod
478
573
  2. jane
@@ -591,6 +686,352 @@ Teston
591
686
  }
592
687
  end
593
688
 
689
+ test_given_govspeak "
690
+ $LegislativeList
691
+ * 1. Item 1[^1]
692
+ * 2. Item 2[^2]
693
+ * 3. Item 3
694
+ $EndLegislativeList
695
+
696
+ [^1]: Footnote definition one
697
+ [^2]: Footnote definition two
698
+ " do
699
+ assert_html_output %(
700
+ <ol class="legislative-list">
701
+ <li>1. Item 1<sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">[footnote 1]</a></sup>
702
+ </li>
703
+ <li>2. Item 2<sup id="fnref:2" role="doc-noteref"><a href="#fn:2" class="footnote" rel="footnote">[footnote 2]</a></sup>
704
+ </li>
705
+ <li>3. Item 3</li>
706
+ </ol>
707
+
708
+ <div class="footnotes" role="doc-endnotes">
709
+ <ol>
710
+ <li id="fn:1" role="doc-endnote">
711
+ <p>
712
+ Footnote definition one<a href="#fnref:1" class="reversefootnote" role="doc-backlink" aria-label="go to where this is referenced">↩</a>
713
+ </p>
714
+ </li>
715
+ <li id="fn:2" role="doc-endnote">
716
+ <p>
717
+ Footnote definition two<a href="#fnref:2" class="reversefootnote" role="doc-backlink" aria-label="go to where this is referenced">↩</a>
718
+ </p>
719
+ </li>
720
+ </ol>
721
+ </div>
722
+ )
723
+ end
724
+
725
+ test_given_govspeak "
726
+ $LegislativeList
727
+ * 1. Item 1[^1]
728
+ * 2. Item 2
729
+ * 3. Item 3
730
+ $EndLegislativeList
731
+
732
+ This is a paragraph with a footnote[^2].
733
+
734
+ $LegislativeList
735
+ * 1. Item 1
736
+ * 2. Item 2[^3]
737
+ * 3. Item 3
738
+ $EndLegislativeList
739
+
740
+ [^1]: Footnote definition one
741
+ [^2]: Footnote definition two
742
+ [^3]: Footnote definition two
743
+ " do
744
+ assert_html_output %(
745
+ <ol class="legislative-list">
746
+ <li>1. Item 1<sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">[footnote 1]</a></sup>
747
+ </li>
748
+ <li>2. Item 2</li>
749
+ <li>3. Item 3</li>
750
+ </ol>
751
+
752
+ <p>This is a paragraph with a footnote<sup id="fnref:2" role="doc-noteref"><a href="#fn:2" class="footnote" rel="footnote">[footnote 2]</a></sup>.</p>
753
+
754
+ <ol class="legislative-list">
755
+ <li>1. Item 1</li>
756
+ <li>2. Item 2<sup id="fnref:3" role="doc-noteref"><a href="#fn:3" class="footnote" rel="footnote">[footnote 3]</a></sup>
757
+ </li>
758
+ <li>3. Item 3</li>
759
+ </ol>
760
+
761
+ <div class="footnotes" role="doc-endnotes">
762
+ <ol>
763
+ <li id="fn:1" role="doc-endnote">
764
+ <p>
765
+ Footnote definition one<a href="#fnref:1" class="reversefootnote" role="doc-backlink" aria-label="go to where this is referenced">↩</a>
766
+ </p>
767
+ </li>
768
+ <li id="fn:2" role="doc-endnote">
769
+ <p>
770
+ Footnote definition two<a href="#fnref:2" class="reversefootnote" role="doc-backlink" aria-label="go to where this is referenced">↩</a>
771
+ </p>
772
+ </li>
773
+ <li id="fn:3" role="doc-endnote">
774
+ <p>
775
+ Footnote definition two<a href="#fnref:3" class="reversefootnote" role="doc-backlink" aria-label="go to where this is referenced">↩</a>
776
+ </p>
777
+ </li>
778
+ </ol>
779
+ </div>
780
+ )
781
+ end
782
+
783
+ test_given_govspeak "
784
+ $LegislativeList
785
+ * 1. Item 1[^1]
786
+ * 2. Item 2[^2]
787
+ * 3. Item 3[^3]
788
+ $EndLegislativeList
789
+
790
+ This is a paragraph with a footnote[^4].
791
+
792
+ $LegislativeList
793
+ * 1. Item 1[^5]
794
+ * 2. Item 2[^6]
795
+ * 3. Item 3[^7]
796
+ $EndLegislativeList
797
+
798
+ This is a paragraph with a footnote[^8].
799
+
800
+ $LegislativeList
801
+ * 1. Item 1[^9]
802
+ * 2. Item 2[^10]
803
+ * 3. Item 3[^11]
804
+ $EndLegislativeList
805
+
806
+ This is a paragraph with a footnote[^12].
807
+
808
+ [^1]: Footnote definition 1
809
+ [^2]: Footnote definition 2
810
+ [^3]: Footnote definition 3
811
+ [^4]: Footnote definition 4
812
+ [^5]: Footnote definition 5
813
+ [^6]: Footnote definition 6
814
+ [^7]: Footnote definition 7
815
+ [^8]: Footnote definition 8
816
+ [^9]: Footnote definition 9
817
+ [^10]: Footnote definition 10
818
+ [^11]: Footnote definition 11
819
+ [^12]: Footnote definition 12
820
+ " do
821
+ assert_html_output %(
822
+ <ol class="legislative-list">
823
+ <li>1. Item 1<sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">[footnote 1]</a></sup>
824
+ </li>
825
+ <li>2. Item 2<sup id="fnref:2" role="doc-noteref"><a href="#fn:2" class="footnote" rel="footnote">[footnote 2]</a></sup>
826
+ </li>
827
+ <li>3. Item 3<sup id="fnref:3" role="doc-noteref"><a href="#fn:3" class="footnote" rel="footnote">[footnote 3]</a></sup>
828
+ </li>
829
+ </ol>
830
+
831
+ <p>This is a paragraph with a footnote<sup id="fnref:4" role="doc-noteref"><a href="#fn:4" class="footnote" rel="footnote">[footnote 4]</a></sup>.</p>
832
+
833
+ <ol class="legislative-list">
834
+ <li>1. Item 1<sup id="fnref:5" role="doc-noteref"><a href="#fn:5" class="footnote" rel="footnote">[footnote 5]</a></sup>
835
+ </li>
836
+ <li>2. Item 2<sup id="fnref:6" role="doc-noteref"><a href="#fn:6" class="footnote" rel="footnote">[footnote 6]</a></sup>
837
+ </li>
838
+ <li>3. Item 3<sup id="fnref:7" role="doc-noteref"><a href="#fn:7" class="footnote" rel="footnote">[footnote 7]</a></sup>
839
+ </li>
840
+ </ol>
841
+
842
+ <p>This is a paragraph with a footnote<sup id="fnref:8" role="doc-noteref"><a href="#fn:8" class="footnote" rel="footnote">[footnote 8]</a></sup>.</p>
843
+
844
+ <ol class="legislative-list">
845
+ <li>1. Item 1<sup id="fnref:9" role="doc-noteref"><a href="#fn:9" class="footnote" rel="footnote">[footnote 9]</a></sup>
846
+ </li>
847
+ <li>2. Item 2<sup id="fnref:10" role="doc-noteref"><a href="#fn:10" class="footnote" rel="footnote">[footnote 10]</a></sup>
848
+ </li>
849
+ <li>3. Item 3<sup id="fnref:11" role="doc-noteref"><a href="#fn:11" class="footnote" rel="footnote">[footnote 11]</a></sup>
850
+ </li>
851
+ </ol>
852
+
853
+ <p>This is a paragraph with a footnote<sup id="fnref:12" role="doc-noteref"><a href="#fn:12" class="footnote" rel="footnote">[footnote 12]</a></sup>.</p>
854
+
855
+ <div class="footnotes" role="doc-endnotes">
856
+ <ol>
857
+ <li id="fn:1" role="doc-endnote">
858
+ <p>
859
+ Footnote definition 1<a href="#fnref:1" class="reversefootnote" role="doc-backlink" aria-label="go to where this is referenced">↩</a>
860
+ </p>
861
+ </li>
862
+ <li id="fn:2" role="doc-endnote">
863
+ <p>
864
+ Footnote definition 2<a href="#fnref:2" class="reversefootnote" role="doc-backlink" aria-label="go to where this is referenced">↩</a>
865
+ </p>
866
+ </li>
867
+ <li id="fn:3" role="doc-endnote">
868
+ <p>
869
+ Footnote definition 3<a href="#fnref:3" class="reversefootnote" role="doc-backlink" aria-label="go to where this is referenced">↩</a>
870
+ </p>
871
+ </li>
872
+ <li id="fn:4" role="doc-endnote">
873
+ <p>
874
+ Footnote definition 4<a href="#fnref:4" class="reversefootnote" role="doc-backlink" aria-label="go to where this is referenced">↩</a>
875
+ </p>
876
+ </li>
877
+ <li id="fn:5" role="doc-endnote">
878
+ <p>
879
+ Footnote definition 5<a href="#fnref:5" class="reversefootnote" role="doc-backlink" aria-label="go to where this is referenced">↩</a>
880
+ </p>
881
+ </li>
882
+ <li id="fn:6" role="doc-endnote">
883
+ <p>
884
+ Footnote definition 6<a href="#fnref:6" class="reversefootnote" role="doc-backlink" aria-label="go to where this is referenced">↩</a>
885
+ </p>
886
+ </li>
887
+ <li id="fn:7" role="doc-endnote">
888
+ <p>
889
+ Footnote definition 7<a href="#fnref:7" class="reversefootnote" role="doc-backlink" aria-label="go to where this is referenced">↩</a>
890
+ </p>
891
+ </li>
892
+ <li id="fn:8" role="doc-endnote">
893
+ <p>
894
+ Footnote definition 8<a href="#fnref:8" class="reversefootnote" role="doc-backlink" aria-label="go to where this is referenced">↩</a>
895
+ </p>
896
+ </li>
897
+ <li id="fn:9" role="doc-endnote">
898
+ <p>
899
+ Footnote definition 9<a href="#fnref:9" class="reversefootnote" role="doc-backlink" aria-label="go to where this is referenced">↩</a>
900
+ </p>
901
+ </li>
902
+ <li id="fn:10" role="doc-endnote">
903
+ <p>
904
+ Footnote definition 10<a href="#fnref:10" class="reversefootnote" role="doc-backlink" aria-label="go to where this is referenced">↩</a>
905
+ </p>
906
+ </li>
907
+ <li id="fn:11" role="doc-endnote">
908
+ <p>
909
+ Footnote definition 11<a href="#fnref:11" class="reversefootnote" role="doc-backlink" aria-label="go to where this is referenced">↩</a>
910
+ </p>
911
+ </li>
912
+ <li id="fn:12" role="doc-endnote">
913
+ <p>
914
+ Footnote definition 12<a href="#fnref:12" class="reversefootnote" role="doc-backlink" aria-label="go to where this is referenced">↩</a>
915
+ </p>
916
+ </li>
917
+ </ol>
918
+ </div>
919
+ )
920
+ end
921
+
922
+ test_given_govspeak "
923
+ $LegislativeList
924
+ * 1. Item 1[^1] with a [link](http://www.gov.uk)
925
+ * 2. Item 2
926
+ * 3. Item 3
927
+ $EndLegislativeList
928
+
929
+ This is a paragraph with a footnote[^2]
930
+
931
+ [^1]: Footnote definition one
932
+ [^2]: Footnote definition two
933
+ " do
934
+ assert_html_output %(
935
+ <ol class="legislative-list">
936
+ <li>1. Item 1<sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">[footnote 1]</a></sup> with a <a href="http://www.gov.uk">link</a>
937
+ </li>
938
+ <li>2. Item 2</li>
939
+ <li>3. Item 3</li>
940
+ </ol>
941
+
942
+ <p>This is a paragraph with a footnote<sup id="fnref:2" role="doc-noteref"><a href="#fn:2" class="footnote" rel="footnote">[footnote 2]</a></sup></p>
943
+
944
+ <div class="footnotes" role="doc-endnotes">
945
+ <ol>
946
+ <li id="fn:1" role="doc-endnote">
947
+ <p>
948
+ Footnote definition one<a href="#fnref:1" class="reversefootnote" role="doc-backlink" aria-label="go to where this is referenced">↩</a>
949
+ </p>
950
+ </li>
951
+ <li id="fn:2" role="doc-endnote">
952
+ <p>
953
+ Footnote definition two<a href="#fnref:2" class="reversefootnote" role="doc-backlink" aria-label="go to where this is referenced">↩</a>
954
+ </p>
955
+ </li>
956
+ </ol>
957
+ </div>
958
+ )
959
+ end
960
+
961
+ test_given_govspeak "
962
+ $LegislativeList
963
+ * 1. Item 1[^1] with a [link](http://www.gov.uk)
964
+ * 2. Item 2
965
+ * 3. Item 3[^2]
966
+ $EndLegislativeList
967
+
968
+ [^1]: Footnote definition one with a [link](http://www.gov.uk) included
969
+ [^2]: Footnote definition two with an external [link](http://www.google.com)
970
+ " do
971
+ assert_html_output %(
972
+ <ol class="legislative-list">
973
+ <li>1. Item 1<sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">[footnote 1]</a></sup> with a <a href="http://www.gov.uk">link</a>
974
+ </li>
975
+ <li>2. Item 2</li>
976
+ <li>3. Item 3<sup id="fnref:2" role="doc-noteref"><a href="#fn:2" class="footnote" rel="footnote">[footnote 2]</a></sup>
977
+ </li>
978
+ </ol>
979
+
980
+ <div class="footnotes" role="doc-endnotes">
981
+ <ol>
982
+ <li id="fn:1" role="doc-endnote">
983
+ <p>
984
+ Footnote definition one with a <a href="http://www.gov.uk">link</a> included<a href="#fnref:1" class="reversefootnote" role="doc-backlink" aria-label="go to where this is referenced">↩</a>
985
+ </p>
986
+ </li>
987
+ <li id="fn:2" role="doc-endnote">
988
+ <p>
989
+ Footnote definition two with an external <a rel="external" href="http://www.google.com">link</a><a href="#fnref:2" class="reversefootnote" role="doc-backlink" aria-label="go to where this is referenced">↩</a>
990
+ </p>
991
+ </li>
992
+ </ol>
993
+ </div>
994
+ )
995
+ end
996
+
997
+ test_given_govspeak "
998
+ $LegislativeList
999
+ * 1. Item 1[^1] with an ACRONYM
1000
+ * 2. Item 2[^2]
1001
+ * 3. Item 3
1002
+ $EndLegislativeList
1003
+
1004
+ [^1]: Footnote definition one
1005
+ [^2]: Footnote definition two with an ACRONYM
1006
+
1007
+ *[ACRONYM]: This is the acronym explanation
1008
+ " do
1009
+ assert_html_output %(
1010
+ <ol class="legislative-list">
1011
+ <li>1. Item 1<sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">[footnote 1]</a></sup> with an <abbr title="This is the acronym explanation">ACRONYM</abbr>
1012
+ </li>
1013
+ <li>2. Item 2<sup id="fnref:2" role="doc-noteref"><a href="#fn:2" class="footnote" rel="footnote">[footnote 2]</a></sup>
1014
+ </li>
1015
+ <li>3. Item 3</li>
1016
+ </ol>
1017
+
1018
+ <div class="footnotes" role="doc-endnotes">
1019
+ <ol>
1020
+ <li id="fn:1" role="doc-endnote">
1021
+ <p>
1022
+ Footnote definition one<a href="#fnref:1" class="reversefootnote" role="doc-backlink" aria-label="go to where this is referenced">↩</a>
1023
+ </p>
1024
+ </li>
1025
+ <li id="fn:2" role="doc-endnote">
1026
+ <p>
1027
+ Footnote definition two with an <abbr title="This is the acronym explanation">ACRONYM</abbr><a href="#fnref:2" class="reversefootnote" role="doc-backlink" aria-label="go to where this is referenced">↩</a>
1028
+ </p>
1029
+ </li>
1030
+ </ol>
1031
+ </div>
1032
+ )
1033
+ end
1034
+
594
1035
  test_given_govspeak "
595
1036
  The quick brown
596
1037
  $LegislativeList
@@ -26,6 +26,12 @@ module GovspeakTestHelper
26
26
  @testcase.assert expected.strip == actual, describe_error(@govspeak, expected.strip, actual)
27
27
  end
28
28
 
29
+ def assert_html_selector(selector)
30
+ html = document.to_html
31
+ fragment = Nokogiri::HTML.fragment(html)
32
+ @testcase.assert fragment.css(selector).any?, "Expected to find #{selector} within #{html}"
33
+ end
34
+
29
35
  def remove_indentation(raw)
30
36
  lines = raw.split("\n")
31
37
  if lines.first.empty?
@@ -33,7 +39,7 @@ module GovspeakTestHelper
33
39
  nonblanks = lines.reject { |l| l.match(/^ *$/) }
34
40
  indentation = nonblanks.map { |line| line.match(/^ */)[0].size }.min
35
41
  unindented = lines.map do |line|
36
- line[indentation..-1]
42
+ line[indentation..]
37
43
  end
38
44
  unindented.join "\n"
39
45
  else
data/test/test_helper.rb CHANGED
@@ -17,10 +17,10 @@ class Minitest::Test
17
17
  clean_name = name.gsub(/\s+/, "_")
18
18
  method = "test_#{clean_name.gsub(/\s+/, '_')}".to_sym
19
19
  already_defined = begin
20
- instance_method(method)
21
- rescue StandardError
22
- false
23
- end
20
+ instance_method(method)
21
+ rescue StandardError
22
+ false
23
+ end
24
24
  raise "#{method} exists" if already_defined
25
25
 
26
26
  define_method(method, &block)
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.7.1
4
+ version: 6.7.5
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: 2021-05-17 00:00:00.000000000 Z
11
+ date: 2021-11-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: actionview
@@ -112,28 +112,14 @@ dependencies:
112
112
  requirements:
113
113
  - - "~>"
114
114
  - !ruby/object:Gem::Version
115
- version: '1.5'
115
+ version: '1.12'
116
116
  type: :runtime
117
117
  prerelease: false
118
118
  version_requirements: !ruby/object:Gem::Requirement
119
119
  requirements:
120
120
  - - "~>"
121
121
  - !ruby/object:Gem::Version
122
- version: '1.5'
123
- - !ruby/object:Gem::Dependency
124
- name: nokogumbo
125
- requirement: !ruby/object:Gem::Requirement
126
- requirements:
127
- - - "~>"
128
- - !ruby/object:Gem::Version
129
- version: '2'
130
- type: :runtime
131
- prerelease: false
132
- version_requirements: !ruby/object:Gem::Requirement
133
- requirements:
134
- - - "~>"
135
- - !ruby/object:Gem::Version
136
- version: '2'
122
+ version: '1.12'
137
123
  - !ruby/object:Gem::Dependency
138
124
  name: rinku
139
125
  requirement: !ruby/object:Gem::Requirement
@@ -152,20 +138,14 @@ dependencies:
152
138
  name: sanitize
153
139
  requirement: !ruby/object:Gem::Requirement
154
140
  requirements:
155
- - - ">="
156
- - !ruby/object:Gem::Version
157
- version: 5.2.1
158
- - - "<"
141
+ - - "~>"
159
142
  - !ruby/object:Gem::Version
160
143
  version: '6'
161
144
  type: :runtime
162
145
  prerelease: false
163
146
  version_requirements: !ruby/object:Gem::Requirement
164
147
  requirements:
165
- - - ">="
166
- - !ruby/object:Gem::Version
167
- version: 5.2.1
168
- - - "<"
148
+ - - "~>"
169
149
  - !ruby/object:Gem::Version
170
150
  version: '6'
171
151
  - !ruby/object:Gem::Dependency
@@ -216,14 +196,14 @@ dependencies:
216
196
  requirements:
217
197
  - - "~>"
218
198
  - !ruby/object:Gem::Version
219
- version: 3.17.1
199
+ version: 4.1.0
220
200
  type: :development
221
201
  prerelease: false
222
202
  version_requirements: !ruby/object:Gem::Requirement
223
203
  requirements:
224
204
  - - "~>"
225
205
  - !ruby/object:Gem::Version
226
- version: 3.17.1
206
+ version: 4.1.0
227
207
  - !ruby/object:Gem::Dependency
228
208
  name: simplecov
229
209
  requirement: !ruby/object:Gem::Requirement
@@ -360,36 +340,36 @@ required_ruby_version: !ruby/object:Gem::Requirement
360
340
  requirements:
361
341
  - - ">="
362
342
  - !ruby/object:Gem::Version
363
- version: '0'
343
+ version: '2.6'
364
344
  required_rubygems_version: !ruby/object:Gem::Requirement
365
345
  requirements:
366
346
  - - ">="
367
347
  - !ruby/object:Gem::Version
368
348
  version: '0'
369
349
  requirements: []
370
- rubygems_version: 3.1.4
350
+ rubygems_version: 3.0.3
371
351
  signing_key:
372
352
  specification_version: 4
373
353
  summary: Markup language for single domain
374
354
  test_files:
355
+ - test/test_helper.rb
356
+ - test/blockquote_extra_quote_remover_test.rb
375
357
  - test/govspeak_images_bang_test.rb
376
- - test/govspeak_attachment_test.rb
358
+ - test/govspeak_contacts_test.rb
359
+ - test/govspeak_table_with_headers_test.rb
377
360
  - test/govspeak_link_extractor_test.rb
378
- - test/govspeak_attachments_inline_test.rb
379
- - test/govspeak_button_test.rb
380
- - test/govspeak_structured_headers_test.rb
381
361
  - test/govspeak_attachments_image_test.rb
382
- - test/govspeak_attachment_link_test.rb
362
+ - test/html_validator_test.rb
363
+ - test/govspeak_button_test.rb
383
364
  - test/govspeak_extract_contact_content_ids_test.rb
384
- - test/presenters/h_card_presenter_test.rb
385
- - test/govspeak_test.rb
386
- - test/html_sanitizer_test.rb
365
+ - test/govspeak_test_helper.rb
387
366
  - test/govspeak_footnote_test.rb
388
- - test/blockquote_extra_quote_remover_test.rb
389
- - test/test_helper.rb
390
- - test/govspeak_table_with_headers_test.rb
391
- - test/govspeak_images_test.rb
392
367
  - test/govspeak_link_test.rb
393
- - test/html_validator_test.rb
394
- - test/govspeak_contacts_test.rb
395
- - test/govspeak_test_helper.rb
368
+ - test/govspeak_structured_headers_test.rb
369
+ - test/html_sanitizer_test.rb
370
+ - test/govspeak_images_test.rb
371
+ - test/govspeak_test.rb
372
+ - test/govspeak_attachment_link_test.rb
373
+ - test/govspeak_attachment_test.rb
374
+ - test/presenters/h_card_presenter_test.rb
375
+ - test/govspeak_attachments_inline_test.rb