govspeak 6.5.0 → 6.5.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +24 -2
  3. data/README.md +6 -5
  4. data/Rakefile +7 -4
  5. data/lib/govspeak.rb +116 -116
  6. data/lib/govspeak/header_extractor.rb +1 -1
  7. data/lib/govspeak/html_sanitizer.rb +12 -9
  8. data/lib/govspeak/kramdown_overrides.rb +2 -2
  9. data/lib/govspeak/link_extractor.rb +6 -6
  10. data/lib/govspeak/post_processor.rb +34 -14
  11. data/lib/govspeak/presenters/attachment_presenter.rb +39 -39
  12. data/lib/govspeak/presenters/contact_presenter.rb +2 -2
  13. data/lib/govspeak/presenters/h_card_presenter.rb +3 -3
  14. data/lib/govspeak/presenters/image_presenter.rb +4 -4
  15. data/lib/govspeak/structured_header_extractor.rb +2 -2
  16. data/lib/govspeak/version.rb +1 -1
  17. data/lib/kramdown/parser/govuk.rb +6 -7
  18. data/test/blockquote_extra_quote_remover_test.rb +24 -26
  19. data/test/govspeak_attachment_link_test.rb +0 -2
  20. data/test/govspeak_attachment_test.rb +0 -2
  21. data/test/govspeak_attachments_image_test.rb +12 -14
  22. data/test/govspeak_attachments_inline_test.rb +22 -24
  23. data/test/govspeak_button_test.rb +29 -31
  24. data/test/govspeak_contacts_test.rb +29 -31
  25. data/test/govspeak_extract_contact_content_ids_test.rb +1 -3
  26. data/test/govspeak_images_bang_test.rb +37 -39
  27. data/test/govspeak_images_test.rb +43 -45
  28. data/test/govspeak_link_extractor_test.rb +1 -1
  29. data/test/govspeak_link_test.rb +1 -3
  30. data/test/govspeak_structured_headers_test.rb +7 -6
  31. data/test/govspeak_table_with_headers_test.rb +68 -21
  32. data/test/govspeak_test.rb +98 -101
  33. data/test/govspeak_test_helper.rb +1 -1
  34. data/test/html_sanitizer_test.rb +17 -9
  35. data/test/html_validator_test.rb +2 -2
  36. data/test/presenters/h_card_presenter_test.rb +39 -41
  37. data/test/test_helper.rb +12 -8
  38. metadata +52 -40
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 691092344fa56f8643bda4f29f8f0a18344515254b042fb15771375489395015
4
- data.tar.gz: 529021924ad18fccfabda572204e59b33867578e548816ab093e2d51b30e059f
3
+ metadata.gz: 99554d6b3b3fd3287b35eebe6ff4633d6e3df24f74bede69fd65c16a81a41584
4
+ data.tar.gz: 300af892bfebf34b74161432f49d93131bde2d533354fd2580204c3d341b8031
5
5
  SHA512:
6
- metadata.gz: a870b551730a2a07f5a85bdb06df18b56018f3a700d21469d8c1804fe51d044ae7beb5455a8d1e332f44e003ed2d6231eb9f36fd72b0578de19cc408973074f0
7
- data.tar.gz: d0b4ca4cf824216c139094d33fdd1a9ddf98800db9aa94b077b454cfce35e98713b1b6e850c63817242f5cc3e381aaa9633062d1b01c3a7450ec6a64876632ee
6
+ metadata.gz: 033a7f0ac2134f8a7912fbb38033a07b8f51370d5631b1e6342a7b04d451b50540fc3874c5b3153af4a18b8ce892fa9f16d24ee6909ba339d2888423ea577199
7
+ data.tar.gz: df16ff9574a2b759b0bb75e53475e08b7164166af97e28d900ed1f44407826d4156ec7441bb07363362740542f698244dc78a712f4b4c1b59e9570ec598685e5
@@ -1,12 +1,34 @@
1
+ ## 6.5.5
2
+
3
+ * Prevent links in table headers being stripped (PR#187)
4
+
5
+ ## 6.5.4
6
+
7
+ * Require Sanitize to be at least 5.2.1 due to https://nvd.nist.gov/vuln/detail/CVE-2020-4054
8
+
9
+ ## 6.5.3
10
+
11
+ * Use button component for buttons (PR#176)
12
+
13
+ ## 6.5.2
14
+
15
+ * Allow `data` attributes on `div` tags (PR#173)
16
+
17
+ ## 6.5.1
18
+
19
+ * Change unicode testing characters after external gem change
20
+ * Move from govuk-lint to rubocop-govuk
21
+ * Allow version 6 of actionview
22
+
1
23
  ## 6.5.0
2
24
 
3
25
  * Allow data attributes on links
4
26
 
5
27
  ## 6.4.0
6
28
 
7
- * Add table heading syntax that allows a table cell outside of `thead` to be marked as a table heading with a scope of row. (PR#161)
29
+ * Add table heading syntax that allows a table cell outside of `thead` to be marked as a table heading with a scope of row. (PR#161)
8
30
 
9
- ## 6.3.0
31
+ ## 6.3.0
10
32
 
11
33
  * Unicode characters forbidden in HTML are stripped from input
12
34
  * Validation is now more lenient for HTML input
data/README.md CHANGED
@@ -619,8 +619,7 @@ will output
619
619
 
620
620
  An accessible way to add button links into content, that can also allow cross domain tracking with [Google Analytics](https://support.google.com/analytics/answer/7372977?hl=en)
621
621
 
622
- This button component is [extended from static](http://govuk-static.herokuapp.com/component-guide/button) for [use in govspeak](http://govuk-static.herokuapp.com/component-guide/govspeak/button)
623
- Note: Ideally we'd use the original component directly but this currently isnt possible
622
+ This button component uses the component from the [components gem](https://components.publishing.service.gov.uk/component-guide/button) for use in govspeak.
624
623
 
625
624
  You must use the [link](https://daringfireball.net/projects/markdown/syntax#link) syntax within the button tags.
626
625
 
@@ -635,7 +634,7 @@ To get the most basic button.
635
634
  which outputs
636
635
 
637
636
  ```html
638
- <a role="button" class="button" href="https://gov.uk/random">
637
+ <a role="button" class="gem-c-button govuk-button" href="https://gov.uk/random">
639
638
  Continue
640
639
  </a>
641
640
  ```
@@ -649,8 +648,9 @@ To turn a button into a ['Start now' button](https://www.gov.uk/service-manual/d
649
648
  which outputs
650
649
 
651
650
  ```html
652
- <a role="button" class="button button-start" href="https://gov.uk/random">
651
+ <a role="button" class="gem-c-button govuk-button govuk-button--start" href="https://gov.uk/random">
653
652
  Start Now
653
+ <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>
654
654
  </a>
655
655
  ```
656
656
 
@@ -667,12 +667,13 @@ which outputs
667
667
  ```html
668
668
  <a
669
669
  role="button"
670
- class="button button-start"
670
+ class="gem-c-button govuk-button govuk-button--start"
671
671
  href="https://example.com/external-service/start-now"
672
672
  data-module="cross-domain-tracking"
673
673
  data-tracking-code="UA-XXXXXX-Y"
674
674
  data-tracking-name="govspeakButtonTracker"
675
675
  >
676
676
  Start Now
677
+ <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>
677
678
  </a>
678
679
  ```
data/Rakefile CHANGED
@@ -1,15 +1,18 @@
1
1
  require "rake"
2
2
  require "rake/testtask"
3
+ require "rubocop/rake_task"
3
4
  require "bundler"
4
5
 
5
6
  Bundler::GemHelper.install_tasks
6
7
 
8
+ RuboCop::RakeTask.new
9
+
7
10
  desc "Run basic tests"
8
- Rake::TestTask.new("test") { |t|
11
+ Rake::TestTask.new("test") do |t|
9
12
  t.libs << "test"
10
- t.pattern = 'test/*_test.rb'
13
+ t.pattern = "test/*_test.rb"
11
14
  t.verbose = true
12
15
  t.warning = true
13
- }
16
+ end
14
17
 
15
- task default: [:test]
18
+ task default: %i[test rubocop]
@@ -1,32 +1,32 @@
1
- require 'active_support/core_ext/hash'
2
- require 'active_support/core_ext/array'
3
- require 'erb'
4
- require 'govuk_publishing_components'
5
- require 'htmlentities'
6
- require 'kramdown'
7
- require 'kramdown/parser/govuk'
8
- require 'nokogiri'
9
- require 'nokogumbo'
10
- require 'rinku'
11
- require 'sanitize'
12
- require 'govspeak/header_extractor'
13
- require 'govspeak/structured_header_extractor'
14
- require 'govspeak/html_validator'
15
- require 'govspeak/html_sanitizer'
16
- require 'govspeak/kramdown_overrides'
17
- require 'govspeak/blockquote_extra_quote_remover'
18
- require 'govspeak/post_processor'
19
- require 'govspeak/link_extractor'
20
- require 'govspeak/template_renderer'
21
- require 'govspeak/presenters/attachment_presenter'
22
- require 'govspeak/presenters/contact_presenter'
23
- require 'govspeak/presenters/h_card_presenter'
24
- require 'govspeak/presenters/image_presenter'
25
- require 'govspeak/presenters/attachment_image_presenter'
1
+ require "active_support/core_ext/hash"
2
+ require "active_support/core_ext/array"
3
+ require "erb"
4
+ require "govuk_publishing_components"
5
+ require "htmlentities"
6
+ require "kramdown"
7
+ require "kramdown/parser/govuk"
8
+ require "nokogiri"
9
+ require "nokogumbo"
10
+ require "rinku"
11
+ require "sanitize"
12
+ require "govspeak/header_extractor"
13
+ require "govspeak/structured_header_extractor"
14
+ require "govspeak/html_validator"
15
+ require "govspeak/html_sanitizer"
16
+ require "govspeak/kramdown_overrides"
17
+ require "govspeak/blockquote_extra_quote_remover"
18
+ require "govspeak/post_processor"
19
+ require "govspeak/link_extractor"
20
+ require "govspeak/template_renderer"
21
+ require "govspeak/presenters/attachment_presenter"
22
+ require "govspeak/presenters/contact_presenter"
23
+ require "govspeak/presenters/h_card_presenter"
24
+ require "govspeak/presenters/image_presenter"
25
+ require "govspeak/presenters/attachment_image_presenter"
26
26
 
27
27
  module Govspeak
28
28
  def self.root
29
- File.expand_path('..', File.dirname(__FILE__))
29
+ File.expand_path("..", File.dirname(__FILE__))
30
30
  end
31
31
 
32
32
  class Document
@@ -44,8 +44,8 @@ module Govspeak
44
44
  new(source, options).to_html
45
45
  end
46
46
 
47
- def self.extensions
48
- @extensions
47
+ class << self
48
+ attr_reader :extensions
49
49
  end
50
50
 
51
51
  def initialize(source, options = {})
@@ -108,9 +108,9 @@ module Govspeak
108
108
  source = Govspeak::BlockquoteExtraQuoteRemover.remove(source)
109
109
  source = remove_forbidden_characters(source)
110
110
  self.class.extensions.each do |_, regexp, block|
111
- source.gsub!(regexp) {
111
+ source.gsub!(regexp) do
112
112
  instance_exec(*Regexp.last_match.captures, &block)
113
- }
113
+ end
114
114
  end
115
115
  source
116
116
  end
@@ -118,7 +118,7 @@ module Govspeak
118
118
  def remove_forbidden_characters(source)
119
119
  # These are characters that are not deemed not suitable for
120
120
  # markup: https://www.w3.org/TR/unicode-xml/#Charlist
121
- source.gsub(Sanitize::REGEX_UNSUITABLE_CHARS, '')
121
+ source.gsub(Sanitize::REGEX_UNSUITABLE_CHARS, "")
122
122
  end
123
123
 
124
124
  def self.extension(title, regexp = nil, &block)
@@ -127,27 +127,27 @@ module Govspeak
127
127
  end
128
128
 
129
129
  def self.surrounded_by(open, close = nil)
130
- open = Regexp::escape(open)
130
+ open = Regexp.escape(open)
131
131
  if close
132
- close = Regexp::escape(close)
133
- %r+(?:\r|\n|^)#{open}(.*?)#{close} *(\r|\n|$)?+m
132
+ close = Regexp.escape(close)
133
+ %r{(?:\r|\n|^)#{open}(.*?)#{close} *(\r|\n|$)?}m
134
134
  else
135
- %r+(?:\r|\n|^)#{open}(.*?)#{open}? *(\r|\n|$)+m
135
+ %r{(?:\r|\n|^)#{open}(.*?)#{open}? *(\r|\n|$)}m
136
136
  end
137
137
  end
138
138
 
139
139
  def self.wrap_with_div(class_name, character, parser = Kramdown::Document)
140
- extension(class_name, surrounded_by(character)) { |body|
140
+ extension(class_name, surrounded_by(character)) do |body|
141
141
  content = parser ? parser.new("#{body.strip}\n").to_html : body.strip
142
- %{\n<div class="#{class_name}">\n#{content}</div>\n}
143
- }
142
+ %(\n<div class="#{class_name}">\n#{content}</div>\n)
143
+ end
144
144
  end
145
145
 
146
146
  def insert_strong_inside_p(body, parser = Govspeak::Document)
147
147
  parser.new(body.strip).to_html.sub(/^<p>(.*)<\/p>$/, "<p><strong>\\1</strong></p>")
148
148
  end
149
149
 
150
- extension('button', %r{
150
+ extension("button", %r{
151
151
  (?:\r|\n|^) # non-capturing match to make sure start of line and linebreak
152
152
  {button(.*?)} # match opening bracket and capture attributes
153
153
  \s* # any whitespace between opening bracket and link
@@ -160,11 +160,11 @@ module Govspeak
160
160
  \s* # any whitespace between opening bracket and link
161
161
  {\/button} # match ending bracket
162
162
  (?:\r|\n|$) # non-capturing match to make sure end of line and linebreak
163
- }x) { |attributes, text, href|
164
- button_classes = "button"
165
- button_classes << " button-start" if attributes =~ /start/
163
+ }x) do |attributes, text, href|
164
+ button_classes = "govuk-button"
166
165
  /cross-domain-tracking:(?<cross_domain_tracking>.[^\s*]+)/ =~ attributes
167
166
  data_attribute = ""
167
+ data_attribute << " data-start='true'" if attributes =~ /start/
168
168
  if cross_domain_tracking
169
169
  data_attribute << " data-module='cross-domain-tracking'"
170
170
  data_attribute << " data-tracking-code='#{cross_domain_tracking.strip}'"
@@ -173,54 +173,54 @@ module Govspeak
173
173
  text = text.strip
174
174
  href = href.strip
175
175
 
176
- %{\n<a role="button" class="#{button_classes}" href="#{href}" #{data_attribute}>#{text}</a>\n}
177
- }
176
+ %(\n<a role="button" class="#{button_classes}" href="#{href}" #{data_attribute}>#{text}</a>\n)
177
+ end
178
178
 
179
- extension('highlight-answer') { |body|
180
- %{\n\n<div class="highlight-answer">
181
- #{Govspeak::Document.new(body.strip).to_html}</div>\n}
182
- }
179
+ extension("highlight-answer") do |body|
180
+ %(\n\n<div class="highlight-answer">
181
+ #{Govspeak::Document.new(body.strip).to_html}</div>\n)
182
+ end
183
183
 
184
- extension('stat-headline', %r${stat-headline}(.*?){/stat-headline}$m) { |body|
185
- %{\n\n<aside class="stat-headline">
186
- #{Govspeak::Document.new(body.strip).to_html}</aside>\n}
187
- }
184
+ extension("stat-headline", %r${stat-headline}(.*?){/stat-headline}$m) do |body|
185
+ %(\n\n<aside class="stat-headline">
186
+ #{Govspeak::Document.new(body.strip).to_html}</aside>\n)
187
+ end
188
188
 
189
189
  # FIXME: these surrounded_by arguments look dodgy
190
- extension('external', surrounded_by("x[", ")x")) { |body|
190
+ extension("external", surrounded_by("x[", ")x")) do |body|
191
191
  Kramdown::Document.new("[#{body.strip}){:rel='external'}").to_html
192
- }
192
+ end
193
193
 
194
- extension('informational', surrounded_by("^")) { |body|
195
- %{\n\n<div role="note" aria-label="Information" class="application-notice info-notice">
196
- #{Govspeak::Document.new(body.strip).to_html}</div>\n}
197
- }
194
+ extension("informational", surrounded_by("^")) do |body|
195
+ %(\n\n<div role="note" aria-label="Information" class="application-notice info-notice">
196
+ #{Govspeak::Document.new(body.strip).to_html}</div>\n)
197
+ end
198
198
 
199
- extension('important', surrounded_by("@")) { |body|
200
- %{\n\n<div role="note" aria-label="Important" class="advisory">#{insert_strong_inside_p(body)}</div>\n}
201
- }
199
+ extension("important", surrounded_by("@")) do |body|
200
+ %(\n\n<div role="note" aria-label="Important" class="advisory">#{insert_strong_inside_p(body)}</div>\n)
201
+ end
202
202
 
203
- extension('helpful', surrounded_by("%")) { |body|
204
- %{\n\n<div role="note" aria-label="Warning" class="application-notice help-notice">\n#{Govspeak::Document.new(body.strip).to_html}</div>\n}
205
- }
203
+ extension("helpful", surrounded_by("%")) do |body|
204
+ %(\n\n<div role="note" aria-label="Warning" class="application-notice help-notice">\n#{Govspeak::Document.new(body.strip).to_html}</div>\n)
205
+ end
206
206
 
207
- extension('barchart', /{barchart(.*?)}/) do |captures|
208
- stacked = '.mc-stacked' if captures.include? 'stacked'
209
- compact = '.compact' if captures.include? 'compact'
210
- negative = '.mc-negative' if captures.include? 'negative'
207
+ extension("barchart", /{barchart(.*?)}/) do |captures|
208
+ stacked = ".mc-stacked" if captures.include? "stacked"
209
+ compact = ".compact" if captures.include? "compact"
210
+ negative = ".mc-negative" if captures.include? "negative"
211
211
 
212
212
  [
213
- '{:',
214
- '.js-barchart-table',
215
- stacked,
216
- compact,
217
- negative,
218
- '.mc-auto-outdent',
219
- '}'
220
- ].join(' ')
213
+ "{:",
214
+ ".js-barchart-table",
215
+ stacked,
216
+ compact,
217
+ negative,
218
+ ".mc-auto-outdent",
219
+ "}",
220
+ ].join(" ")
221
221
  end
222
222
 
223
- extension('attached-image', /^!!([0-9]+)/) do |image_number|
223
+ extension("attached-image", /^!!([0-9]+)/) do |image_number|
224
224
  image = images[image_number.to_i - 1]
225
225
  next "" unless image
226
226
 
@@ -228,22 +228,22 @@ module Govspeak
228
228
  end
229
229
 
230
230
  # DEPRECATED: use 'AttachmentLink:attachment-id' instead
231
- extension('embed attachment inline', /\[embed:attachments:inline:\s*(.*?)\s*\]/) do |content_id|
231
+ extension("embed attachment inline", /\[embed:attachments:inline:\s*(.*?)\s*\]/) do |content_id|
232
232
  attachment = attachments.detect { |a| a[:content_id] == content_id }
233
233
  next "" unless attachment
234
234
 
235
235
  attachment = AttachmentPresenter.new(attachment)
236
236
 
237
- span_id = attachment.id ? %{ id="attachment_#{attachment.id}"} : ""
237
+ span_id = attachment.id ? %( id="attachment_#{attachment.id}") : ""
238
238
  # new lines inside our title cause problems with govspeak rendering as this is expected to be on one line.
239
239
  title = (attachment.title || "").tr("\n", " ")
240
240
  link = attachment.link(title, attachment.url)
241
241
  attributes = attachment.attachment_attributes.empty? ? "" : " (#{attachment.attachment_attributes})"
242
- %{<span#{span_id} class="attachment-inline">#{link}#{attributes}</span>}
242
+ %(<span#{span_id} class="attachment-inline">#{link}#{attributes}</span>)
243
243
  end
244
244
 
245
245
  # DEPRECATED: use 'Image:image-id' instead
246
- extension('attachment image', /\[embed:attachments:image:\s*(.*?)\s*\]/) do |content_id|
246
+ extension("attachment image", /\[embed:attachments:image:\s*(.*?)\s*\]/) do |content_id|
247
247
  attachment = attachments.detect { |a| a[:content_id] == content_id }
248
248
  next "" unless attachment
249
249
 
@@ -261,52 +261,52 @@ module Govspeak
261
261
  #
262
262
  # This issue is not considered a bug by kramdown: https://github.com/gettalong/kramdown/issues/191
263
263
  def render_image(image)
264
- id_attr = image.id ? %{ id="attachment_#{image.id}"} : ""
264
+ id_attr = image.id ? %( id="attachment_#{image.id}") : ""
265
265
  lines = []
266
- lines << %{<figure#{id_attr} class="image embedded">}
267
- lines << %{<div class="img"><img src="#{encode(image.url)}" alt="#{encode(image.alt_text)}"></div>}
266
+ lines << %(<figure#{id_attr} class="image embedded">)
267
+ lines << %(<div class="img"><img src="#{encode(image.url)}" alt="#{encode(image.alt_text)}"></div>)
268
268
  lines << image.figcaption_html if image.figcaption?
269
- lines << '</figure>'
269
+ lines << "</figure>"
270
270
  lines.join
271
271
  end
272
272
 
273
- wrap_with_div('summary', '$!')
274
- wrap_with_div('form-download', '$D')
275
- wrap_with_div('contact', '$C')
276
- wrap_with_div('place', '$P', Govspeak::Document)
277
- wrap_with_div('information', '$I', Govspeak::Document)
278
- wrap_with_div('additional-information', '$AI')
279
- wrap_with_div('example', '$E', Govspeak::Document)
280
- wrap_with_div('call-to-action', '$CTA', Govspeak::Document)
273
+ wrap_with_div("summary", "$!")
274
+ wrap_with_div("form-download", "$D")
275
+ wrap_with_div("contact", "$C")
276
+ wrap_with_div("place", "$P", Govspeak::Document)
277
+ wrap_with_div("information", "$I", Govspeak::Document)
278
+ wrap_with_div("additional-information", "$AI")
279
+ wrap_with_div("example", "$E", Govspeak::Document)
280
+ wrap_with_div("call-to-action", "$CTA", Govspeak::Document)
281
281
 
282
- extension('address', surrounded_by("$A")) { |body|
283
- %{\n<div class="address"><div class="adr org fn"><p>\n#{body.sub("\n", '').gsub("\n", '<br />')}\n</p></div></div>\n}
284
- }
282
+ extension("address", surrounded_by("$A")) do |body|
283
+ %(\n<div class="address"><div class="adr org fn"><p>\n#{body.sub("\n", '').gsub("\n", '<br />')}\n</p></div></div>\n)
284
+ end
285
285
 
286
286
  extension("legislative list", /#{NEW_PARAGRAPH_LOOKBEHIND}\$LegislativeList\s*$(.*?)\$EndLegislativeList/m) do |body|
287
287
  Govspeak::KramdownOverrides.with_kramdown_ordered_lists_disabled do
288
288
  Kramdown::Document.new(body.strip).to_html.tap do |doc|
289
- doc.gsub!('<ul>', '<ol>')
290
- doc.gsub!('</ul>', '</ol>')
291
- doc.sub!('<ol>', '<ol class="legislative-list">')
289
+ doc.gsub!("<ul>", "<ol>")
290
+ doc.gsub!("</ul>", "</ol>")
291
+ doc.sub!("<ol>", '<ol class="legislative-list">')
292
292
  end
293
293
  end
294
294
  end
295
295
 
296
296
  extension("numbered list", /^[ \t]*((s\d+\.\s.*(?:\n|$))+)/) do |body|
297
297
  body.gsub!(/s(\d+)\.\s(.*)(?:\n|$)/) do
298
- "<li>#{Govspeak::Document.new($2.strip).to_html}</li>\n"
298
+ "<li>#{Govspeak::Document.new(Regexp.last_match(2).strip).to_html}</li>\n"
299
299
  end
300
- %{<ol class="steps">\n#{body}</ol>}
300
+ %(<ol class="steps">\n#{body}</ol>)
301
301
  end
302
302
 
303
303
  def self.devolved_options
304
- { 'scotland' => 'Scotland',
305
- 'england' => 'England',
306
- 'england-wales' => 'England and Wales',
307
- 'northern-ireland' => 'Northern Ireland',
308
- 'wales' => 'Wales',
309
- 'london' => 'London' }
304
+ { "scotland" => "Scotland",
305
+ "england" => "England",
306
+ "england-wales" => "England and Wales",
307
+ "northern-ireland" => "Northern Ireland",
308
+ "wales" => "Wales",
309
+ "london" => "London" }
310
310
  end
311
311
 
312
312
  devolved_options.each do |k, v|
@@ -333,7 +333,7 @@ module Govspeak
333
333
  end
334
334
  end
335
335
 
336
- extension('embed link', /\[embed:link:\s*(.*?)\s*\]/) do |content_id|
336
+ extension("embed link", /\[embed:link:\s*(.*?)\s*\]/) do |content_id|
337
337
  link = links.detect { |l| l[:content_id] == content_id }
338
338
  next "" unless link
339
339
 
@@ -344,31 +344,31 @@ module Govspeak
344
344
  end
345
345
  end
346
346
 
347
- extension('Contact', /\[Contact:\s*(.*?)\s*\]/) do |content_id|
347
+ extension("Contact", /\[Contact:\s*(.*?)\s*\]/) do |content_id|
348
348
  contact = contacts.detect { |c| c[:content_id] == content_id }
349
349
  next "" unless contact
350
350
 
351
- renderer = TemplateRenderer.new('contact.html.erb', locale)
351
+ renderer = TemplateRenderer.new("contact.html.erb", locale)
352
352
  renderer.render(contact: ContactPresenter.new(contact))
353
353
  end
354
354
 
355
- extension('Image', /#{NEW_PARAGRAPH_LOOKBEHIND}\[Image:\s*(.*?)\s*\]/) do |image_id|
355
+ extension("Image", /#{NEW_PARAGRAPH_LOOKBEHIND}\[Image:\s*(.*?)\s*\]/) do |image_id|
356
356
  image = images.detect { |c| c.is_a?(Hash) && c[:id] == image_id }
357
357
  next "" unless image
358
358
 
359
359
  render_image(ImagePresenter.new(image))
360
360
  end
361
361
 
362
- extension('Attachment', /#{NEW_PARAGRAPH_LOOKBEHIND}\[Attachment:\s*(.*?)\s*\]/) do |attachment_id|
362
+ extension("Attachment", /#{NEW_PARAGRAPH_LOOKBEHIND}\[Attachment:\s*(.*?)\s*\]/) do |attachment_id|
363
363
  next "" if attachments.none? { |a| a[:id] == attachment_id }
364
364
 
365
- %{<govspeak-embed-attachment id="#{attachment_id}"></govspeak-embed-attachment>}
365
+ %(<govspeak-embed-attachment id="#{attachment_id}"></govspeak-embed-attachment>)
366
366
  end
367
367
 
368
- extension('AttachmentLink', /\[AttachmentLink:\s*(.*?)\s*\]/) do |attachment_id|
368
+ extension("AttachmentLink", /\[AttachmentLink:\s*(.*?)\s*\]/) do |attachment_id|
369
369
  next "" if attachments.none? { |a| a[:id] == attachment_id }
370
370
 
371
- %{<govspeak-embed-attachment-link id="#{attachment_id}"></govspeak-embed-attachment-link>}
371
+ %(<govspeak-embed-attachment-link id="#{attachment_id}"></govspeak-embed-attachment-link>)
372
372
  end
373
373
 
374
374
  private
@@ -384,5 +384,5 @@ module Govspeak
384
384
  end
385
385
 
386
386
  I18n.load_path.unshift(
387
- *Dir.glob(File.expand_path('locales/*.yml', Govspeak.root))
387
+ *Dir.glob(File.expand_path("locales/*.yml", Govspeak.root)),
388
388
  )