govspeak 6.5.4 → 6.5.9

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a09b3928e9718aa64cd781681dbc8ac51d8534ddc27b26f54e8416b21f60e501
4
- data.tar.gz: f8b6da3c1bf3c3b4c7792263853837886b42f7dc6abe6346d81289695ea7986d
3
+ metadata.gz: 948aced50c3d3842255ea4206a651229de59b2beef42e0c50e55e204354d9b5f
4
+ data.tar.gz: cc55abe4b54b112a3aa1cb350a94270b11b9f0c11a5ca71479f55bb0efbf657d
5
5
  SHA512:
6
- metadata.gz: 9de09348513cfd10e76a9960bfe8012213a99447244cf9d89a2e3da8cb18f93b28e8b63dd63304de06c51a6e3b9e82bc5b1f2de43ff531dfb23f4832d1a18e0b
7
- data.tar.gz: 0b464f824b1ff7f8ee77619d2dd1195a22c8777b79b675d9e7fbb1b88011075552f496b294e26d9b65908f2a26031de30ff93c1a12ba3a9743786a4219cfb2de
6
+ metadata.gz: 1e0c1b0d6ca1fe4999e4135536328ecdc60bd34f368d986a808cee6de687f58198a080c19beffd47df6d80130edd2010eb1a09ccd840ea8adb9375c0b747e533
7
+ data.tar.gz: e47aeeabecc4ffccff7342d1a1ad2e1ddd6cd8aabf5850f740fa3bf5ecdd9395bbded84222d55a5c8998748d7491a649793c550ab49564cd098486623684b275
@@ -1,3 +1,23 @@
1
+ ## 6.5.9
2
+
3
+ * Adjust footnote markup to accommodate multiple references (PR#198)
4
+
5
+ ## 6.5.8
6
+
7
+ * Customise footnote markup for accessibility (PR#192)
8
+
9
+ ## 6.5.7
10
+
11
+ * Update GOV.UK Publishing components to version to 23.0.0 or greater
12
+
13
+ ## 6.5.6
14
+
15
+ * Update Kramdown version to 2.3.0 or greater
16
+
17
+ ## 6.5.5
18
+
19
+ * Prevent links in table headers being stripped (PR#187)
20
+
1
21
  ## 6.5.4
2
22
 
3
23
  * Require Sanitize to be at least 5.2.1 due to https://nvd.nist.gov/vuln/detail/CVE-2020-4054
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
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]
@@ -57,7 +57,9 @@ module Govspeak
57
57
  @links = Array.wrap(options.delete(:links))
58
58
  @contacts = Array.wrap(options.delete(:contacts))
59
59
  @locale = options.fetch(:locale, "en")
60
- @options = { input: PARSER_CLASS_NAME, sanitize: true }.merge(options)
60
+ @options = { input: PARSER_CLASS_NAME,
61
+ sanitize: true,
62
+ syntax_highlighter: nil }.merge(options)
61
63
  @options[:entity_output] = :symbolic
62
64
  end
63
65
 
@@ -108,9 +110,9 @@ module Govspeak
108
110
  source = Govspeak::BlockquoteExtraQuoteRemover.remove(source)
109
111
  source = remove_forbidden_characters(source)
110
112
  self.class.extensions.each do |_, regexp, block|
111
- source.gsub!(regexp) {
113
+ source.gsub!(regexp) do
112
114
  instance_exec(*Regexp.last_match.captures, &block)
113
- }
115
+ end
114
116
  end
115
117
  source
116
118
  end
@@ -127,20 +129,20 @@ module Govspeak
127
129
  end
128
130
 
129
131
  def self.surrounded_by(open, close = nil)
130
- open = Regexp::escape(open)
132
+ open = Regexp.escape(open)
131
133
  if close
132
- close = Regexp::escape(close)
133
- %r+(?:\r|\n|^)#{open}(.*?)#{close} *(\r|\n|$)?+m
134
+ close = Regexp.escape(close)
135
+ %r{(?:\r|\n|^)#{open}(.*?)#{close} *(\r|\n|$)?}m
134
136
  else
135
- %r+(?:\r|\n|^)#{open}(.*?)#{open}? *(\r|\n|$)+m
137
+ %r{(?:\r|\n|^)#{open}(.*?)#{open}? *(\r|\n|$)}m
136
138
  end
137
139
  end
138
140
 
139
141
  def self.wrap_with_div(class_name, character, parser = Kramdown::Document)
140
- extension(class_name, surrounded_by(character)) { |body|
142
+ extension(class_name, surrounded_by(character)) do |body|
141
143
  content = parser ? parser.new("#{body.strip}\n").to_html : body.strip
142
- %{\n<div class="#{class_name}">\n#{content}</div>\n}
143
- }
144
+ %(\n<div class="#{class_name}">\n#{content}</div>\n)
145
+ end
144
146
  end
145
147
 
146
148
  def insert_strong_inside_p(body, parser = Govspeak::Document)
@@ -160,7 +162,7 @@ module Govspeak
160
162
  \s* # any whitespace between opening bracket and link
161
163
  {\/button} # match ending bracket
162
164
  (?:\r|\n|$) # non-capturing match to make sure end of line and linebreak
163
- }x) { |attributes, text, href|
165
+ }x) do |attributes, text, href|
164
166
  button_classes = "govuk-button"
165
167
  /cross-domain-tracking:(?<cross_domain_tracking>.[^\s*]+)/ =~ attributes
166
168
  data_attribute = ""
@@ -173,36 +175,36 @@ module Govspeak
173
175
  text = text.strip
174
176
  href = href.strip
175
177
 
176
- %{\n<a role="button" class="#{button_classes}" href="#{href}" #{data_attribute}>#{text}</a>\n}
177
- }
178
+ %(\n<a role="button" class="#{button_classes}" href="#{href}" #{data_attribute}>#{text}</a>\n)
179
+ end
178
180
 
179
- extension("highlight-answer") { |body|
180
- %{\n\n<div class="highlight-answer">
181
- #{Govspeak::Document.new(body.strip).to_html}</div>\n}
182
- }
181
+ extension("highlight-answer") do |body|
182
+ %(\n\n<div class="highlight-answer">
183
+ #{Govspeak::Document.new(body.strip).to_html}</div>\n)
184
+ end
183
185
 
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
- }
186
+ 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)
189
+ end
188
190
 
189
191
  # FIXME: these surrounded_by arguments look dodgy
190
- extension("external", surrounded_by("x[", ")x")) { |body|
192
+ extension("external", surrounded_by("x[", ")x")) do |body|
191
193
  Kramdown::Document.new("[#{body.strip}){:rel='external'}").to_html
192
- }
194
+ end
193
195
 
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
- }
196
+ extension("informational", surrounded_by("^")) do |body|
197
+ %(\n\n<div role="note" aria-label="Information" class="application-notice info-notice">
198
+ #{Govspeak::Document.new(body.strip).to_html}</div>\n)
199
+ end
198
200
 
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
- }
201
+ extension("important", surrounded_by("@")) do |body|
202
+ %(\n\n<div role="note" aria-label="Important" class="advisory">#{insert_strong_inside_p(body)}</div>\n)
203
+ end
202
204
 
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
- }
205
+ extension("helpful", surrounded_by("%")) do |body|
206
+ %(\n\n<div role="note" aria-label="Warning" class="application-notice help-notice">\n#{Govspeak::Document.new(body.strip).to_html}</div>\n)
207
+ end
206
208
 
207
209
  extension("barchart", /{barchart(.*?)}/) do |captures|
208
210
  stacked = ".mc-stacked" if captures.include? "stacked"
@@ -210,13 +212,13 @@ module Govspeak
210
212
  negative = ".mc-negative" if captures.include? "negative"
211
213
 
212
214
  [
213
- "{:",
214
- ".js-barchart-table",
215
- stacked,
216
- compact,
217
- negative,
218
- ".mc-auto-outdent",
219
- "}",
215
+ "{:",
216
+ ".js-barchart-table",
217
+ stacked,
218
+ compact,
219
+ negative,
220
+ ".mc-auto-outdent",
221
+ "}",
220
222
  ].join(" ")
221
223
  end
222
224
 
@@ -234,12 +236,12 @@ module Govspeak
234
236
 
235
237
  attachment = AttachmentPresenter.new(attachment)
236
238
 
237
- span_id = attachment.id ? %{ id="attachment_#{attachment.id}"} : ""
239
+ span_id = attachment.id ? %( id="attachment_#{attachment.id}") : ""
238
240
  # new lines inside our title cause problems with govspeak rendering as this is expected to be on one line.
239
241
  title = (attachment.title || "").tr("\n", " ")
240
242
  link = attachment.link(title, attachment.url)
241
243
  attributes = attachment.attachment_attributes.empty? ? "" : " (#{attachment.attachment_attributes})"
242
- %{<span#{span_id} class="attachment-inline">#{link}#{attributes}</span>}
244
+ %(<span#{span_id} class="attachment-inline">#{link}#{attributes}</span>)
243
245
  end
244
246
 
245
247
  # DEPRECATED: use 'Image:image-id' instead
@@ -261,10 +263,10 @@ module Govspeak
261
263
  #
262
264
  # This issue is not considered a bug by kramdown: https://github.com/gettalong/kramdown/issues/191
263
265
  def render_image(image)
264
- id_attr = image.id ? %{ id="attachment_#{image.id}"} : ""
266
+ id_attr = image.id ? %( id="attachment_#{image.id}") : ""
265
267
  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>}
268
+ lines << %(<figure#{id_attr} class="image embedded">)
269
+ lines << %(<div class="img"><img src="#{encode(image.url)}" alt="#{encode(image.alt_text)}"></div>)
268
270
  lines << image.figcaption_html if image.figcaption?
269
271
  lines << "</figure>"
270
272
  lines.join
@@ -279,9 +281,9 @@ module Govspeak
279
281
  wrap_with_div("example", "$E", Govspeak::Document)
280
282
  wrap_with_div("call-to-action", "$CTA", Govspeak::Document)
281
283
 
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
- }
284
+ extension("address", surrounded_by("$A")) do |body|
285
+ %(\n<div class="address"><div class="adr org fn"><p>\n#{body.sub("\n", '').gsub("\n", '<br />')}\n</p></div></div>\n)
286
+ end
285
287
 
286
288
  extension("legislative list", /#{NEW_PARAGRAPH_LOOKBEHIND}\$LegislativeList\s*$(.*?)\$EndLegislativeList/m) do |body|
287
289
  Govspeak::KramdownOverrides.with_kramdown_ordered_lists_disabled do
@@ -295,9 +297,9 @@ module Govspeak
295
297
 
296
298
  extension("numbered list", /^[ \t]*((s\d+\.\s.*(?:\n|$))+)/) do |body|
297
299
  body.gsub!(/s(\d+)\.\s(.*)(?:\n|$)/) do
298
- "<li>#{Govspeak::Document.new($2.strip).to_html}</li>\n"
300
+ "<li>#{Govspeak::Document.new(Regexp.last_match(2).strip).to_html}</li>\n"
299
301
  end
300
- %{<ol class="steps">\n#{body}</ol>}
302
+ %(<ol class="steps">\n#{body}</ol>)
301
303
  end
302
304
 
303
305
  def self.devolved_options
@@ -362,13 +364,13 @@ module Govspeak
362
364
  extension("Attachment", /#{NEW_PARAGRAPH_LOOKBEHIND}\[Attachment:\s*(.*?)\s*\]/) do |attachment_id|
363
365
  next "" if attachments.none? { |a| a[:id] == attachment_id }
364
366
 
365
- %{<govspeak-embed-attachment id="#{attachment_id}"></govspeak-embed-attachment>}
367
+ %(<govspeak-embed-attachment id="#{attachment_id}"></govspeak-embed-attachment>)
366
368
  end
367
369
 
368
370
  extension("AttachmentLink", /\[AttachmentLink:\s*(.*?)\s*\]/) do |attachment_id|
369
371
  next "" if attachments.none? { |a| a[:id] == attachment_id }
370
372
 
371
- %{<govspeak-embed-attachment-link id="#{attachment_id}"></govspeak-embed-attachment-link>}
373
+ %(<govspeak-embed-attachment-link id="#{attachment_id}"></govspeak-embed-attachment-link>)
372
374
  end
373
375
 
374
376
  private
@@ -54,12 +54,12 @@ class Govspeak::HtmlSanitizer
54
54
  elements: Sanitize::Config::RELAXED[:elements] + %w[govspeak-embed-attachment govspeak-embed-attachment-link svg path],
55
55
  attributes: {
56
56
  :all => Sanitize::Config::RELAXED[:attributes][:all] + %w[role aria-label],
57
- "a" => Sanitize::Config::RELAXED[:attributes]["a"] + [:data],
57
+ "a" => Sanitize::Config::RELAXED[:attributes]["a"] + [:data],
58
58
  "svg" => Sanitize::Config::RELAXED[:attributes][:all] + %w[xmlns width height viewbox focusable],
59
59
  "path" => Sanitize::Config::RELAXED[:attributes][:all] + %w[fill d],
60
60
  "div" => [:data],
61
- "th" => Sanitize::Config::RELAXED[:attributes]["th"] + %w[style],
62
- "td" => Sanitize::Config::RELAXED[:attributes]["td"] + %w[style],
61
+ "th" => Sanitize::Config::RELAXED[:attributes]["th"] + %w[style],
62
+ "td" => Sanitize::Config::RELAXED[:attributes]["td"] + %w[style],
63
63
  "govspeak-embed-attachment" => %w[content-id],
64
64
  },
65
65
  )
@@ -1,9 +1,9 @@
1
1
  module Govspeak
2
2
  module KramdownOverrides
3
- # This depends on two internal parts of Kramdown.
3
+ # This depends on two internal parts of Kramdown.
4
4
  # 1. Parser registry (kramdown/parser/kramdown.rb#define_parser)
5
5
  # 2. Kramdown list regexes (kramdown/parser/kramdown/list.rb)
6
- # Updating the Kramdown gem therefore also means updating this file to to
6
+ # Updating the Kramdown gem therefore also means updating this file to to
7
7
  # match Kramdown's internals.
8
8
 
9
9
  def self.with_kramdown_ordered_lists_disabled
@@ -14,9 +14,9 @@ module Govspeak
14
14
  attr_reader :document, :website_root
15
15
 
16
16
  def extract_links
17
- document_anchors.
18
- map { |link| extract_href_from_link(link) }.
19
- reject(&:blank?)
17
+ document_anchors
18
+ .map { |link| extract_href_from_link(link) }
19
+ .reject(&:blank?)
20
20
  end
21
21
 
22
22
  def extract_href_from_link(link)
@@ -92,11 +92,13 @@ module Govspeak
92
92
  end
93
93
 
94
94
  document.css(":not(thead) tr td:first-child").map do |el|
95
- if el.content.match?(/^#($|\s.*$)/)
96
- el.content = el.content.gsub(/^#($|\s)/, "") # Replace '# ' and '#', but not '#Word'.
97
- el.name = "th" if el.content.present? # This also prevents a `th` with nothing inside it; a `td` is preferable.
98
- el[:scope] = "row" if el.content.present? # `scope` shouldn't be used if there's nothing in the table heading.
99
- end
95
+ next unless el.content.match?(/^#($|\s.*$)/)
96
+
97
+ # Replace '# ' and '#', but not '#Word'.
98
+ # This runs on the first child of the element to preserve any links
99
+ el.children.first.content = el.children.first.content.gsub(/^#($|\s)/, "")
100
+ el.name = "th" if el.content.present? # This also prevents a `th` with nothing inside it; a `td` is preferable.
101
+ el[:scope] = "row" if el.content.present? # `scope` shouldn't be used if there's nothing in the table heading.
100
102
  end
101
103
  end
102
104
 
@@ -118,6 +120,17 @@ module Govspeak
118
120
  end
119
121
  end
120
122
 
123
+ extension("use custom footnotes") do |document|
124
+ document.css("a.footnote").map do |el|
125
+ footnote_number = el[:href].gsub(/\D/, "")
126
+ el.content = "[footnote #{footnote_number}]"
127
+ end
128
+ document.css("[role='doc-backlink']").map do |el|
129
+ backlink_number = " " + el.css("sup")[0].content if el.css("sup")[0].present?
130
+ el["aria-label"] = "go to where this is referenced#{backlink_number}"
131
+ end
132
+ end
133
+
121
134
  attr_reader :input, :govspeak_document
122
135
 
123
136
  def initialize(html, govspeak_document)
@@ -55,46 +55,46 @@ module Govspeak
55
55
 
56
56
  def humanized_content_type(file_extension)
57
57
  file_extension_vs_humanized_content_type = {
58
- "chm" => file_abbr_tag("CHM", "Microsoft Compiled HTML Help"),
59
- "csv" => file_abbr_tag("CSV", "Comma-separated Values"),
58
+ "chm" => file_abbr_tag("CHM", "Microsoft Compiled HTML Help"),
59
+ "csv" => file_abbr_tag("CSV", "Comma-separated Values"),
60
60
  "diff" => file_abbr_tag("DIFF", "Plain text differences"),
61
- "doc" => MS_WORD_DOCUMENT_HUMANIZED_CONTENT_TYPE,
61
+ "doc" => MS_WORD_DOCUMENT_HUMANIZED_CONTENT_TYPE,
62
62
  "docx" => MS_WORD_DOCUMENT_HUMANIZED_CONTENT_TYPE,
63
- "dot" => file_abbr_tag("DOT", "MS Word Document Template"),
64
- "dxf" => file_abbr_tag("DXF", "AutoCAD Drawing Exchange Format"),
65
- "eps" => file_abbr_tag("EPS", "Encapsulated PostScript"),
66
- "gif" => file_abbr_tag("GIF", "Graphics Interchange Format"),
67
- "gml" => file_abbr_tag("GML", "Geography Markup Language"),
63
+ "dot" => file_abbr_tag("DOT", "MS Word Document Template"),
64
+ "dxf" => file_abbr_tag("DXF", "AutoCAD Drawing Exchange Format"),
65
+ "eps" => file_abbr_tag("EPS", "Encapsulated PostScript"),
66
+ "gif" => file_abbr_tag("GIF", "Graphics Interchange Format"),
67
+ "gml" => file_abbr_tag("GML", "Geography Markup Language"),
68
68
  "html" => file_abbr_tag("HTML", "Hypertext Markup Language"),
69
69
  "ics" => file_abbr_tag("ICS", "iCalendar file"),
70
- "jpg" => "JPEG",
71
- "odp" => file_abbr_tag("ODP", "OpenDocument Presentation"),
72
- "ods" => file_abbr_tag("ODS", "OpenDocument Spreadsheet"),
73
- "odt" => file_abbr_tag("ODT", "OpenDocument Text document"),
74
- "pdf" => file_abbr_tag("PDF", "Portable Document Format"),
75
- "png" => file_abbr_tag("PNG", "Portable Network Graphic"),
76
- "ppt" => MS_POWERPOINT_PRESENTATION_HUMANIZED_CONTENT_TYPE,
70
+ "jpg" => "JPEG",
71
+ "odp" => file_abbr_tag("ODP", "OpenDocument Presentation"),
72
+ "ods" => file_abbr_tag("ODS", "OpenDocument Spreadsheet"),
73
+ "odt" => file_abbr_tag("ODT", "OpenDocument Text document"),
74
+ "pdf" => file_abbr_tag("PDF", "Portable Document Format"),
75
+ "png" => file_abbr_tag("PNG", "Portable Network Graphic"),
76
+ "ppt" => MS_POWERPOINT_PRESENTATION_HUMANIZED_CONTENT_TYPE,
77
77
  "pptx" => MS_POWERPOINT_PRESENTATION_HUMANIZED_CONTENT_TYPE,
78
- "ps" => file_abbr_tag("PS", "PostScript"),
79
- "rdf" => file_abbr_tag("RDF", "Resource Description Framework"),
80
- "rtf" => file_abbr_tag("RTF", "Rich Text Format"),
81
- "sch" => file_abbr_tag("SCH", "XML based Schematic"),
82
- "txt" => "Plain text",
78
+ "ps" => file_abbr_tag("PS", "PostScript"),
79
+ "rdf" => file_abbr_tag("RDF", "Resource Description Framework"),
80
+ "rtf" => file_abbr_tag("RTF", "Rich Text Format"),
81
+ "sch" => file_abbr_tag("SCH", "XML based Schematic"),
82
+ "txt" => "Plain text",
83
83
  "wsdl" => file_abbr_tag("WSDL", "Web Services Description Language"),
84
- "xls" => MS_EXCEL_SPREADSHEET_HUMANIZED_CONTENT_TYPE,
84
+ "xls" => MS_EXCEL_SPREADSHEET_HUMANIZED_CONTENT_TYPE,
85
85
  "xlsm" => file_abbr_tag("XLSM", "MS Excel Macro-Enabled Workbook"),
86
86
  "xlsx" => MS_EXCEL_SPREADSHEET_HUMANIZED_CONTENT_TYPE,
87
- "xlt" => file_abbr_tag("XLT", "MS Excel Spreadsheet Template"),
88
- "xsd" => file_abbr_tag("XSD", "XML Schema"),
87
+ "xlt" => file_abbr_tag("XLT", "MS Excel Spreadsheet Template"),
88
+ "xsd" => file_abbr_tag("XSD", "XML Schema"),
89
89
  "xslt" => file_abbr_tag("XSLT", "Extensible Stylesheet Language Transformation"),
90
- "zip" => file_abbr_tag("ZIP", "Zip archive"),
90
+ "zip" => file_abbr_tag("ZIP", "Zip archive"),
91
91
  }
92
92
  file_extension_vs_humanized_content_type.fetch(file_extension.to_s.downcase, "")
93
93
  end
94
94
 
95
95
  def link(body, url, options = {})
96
- options_str = options.map { |k, v| %{#{encode(k)}="#{encode(v)}"} }.join(" ")
97
- %{<a href="#{encode(url)}" #{options_str}>#{body}</a>}
96
+ options_str = options.map { |k, v| %(#{encode(k)}="#{encode(v)}") }.join(" ")
97
+ %(<a href="#{encode(url)}" #{options_str}>#{body}</a>)
98
98
  end
99
99
 
100
100
  private
@@ -33,8 +33,8 @@ module Govspeak
33
33
  def figcaption_html
34
34
  lines = []
35
35
  lines << "<figcaption>"
36
- lines << %{<p>#{caption}</p>} if caption.present?
37
- lines << %{<p>#{I18n.t('govspeak.image.figure.credit', credit: credit)}</p>} if credit.present?
36
+ lines << %(<p>#{caption}</p>) if caption.present?
37
+ lines << %(<p>#{I18n.t('govspeak.image.figure.credit', credit: credit)}</p>) if credit.present?
38
38
  lines << "</figcaption>"
39
39
  lines.join
40
40
  end
@@ -48,9 +48,9 @@ module Govspeak
48
48
  private :doc, :stack, :structured_headers
49
49
 
50
50
  def headers_list
51
- @headers_list ||= doc.headers.map { |h|
51
+ @headers_list ||= doc.headers.map do |h|
52
52
  StructuredHeader.new(h.text, h.level, h.id, [])
53
- }
53
+ end
54
54
  end
55
55
 
56
56
  def add_top_level(header)
@@ -1,3 +1,3 @@
1
1
  module Govspeak
2
- VERSION = "6.5.4".freeze
2
+ VERSION = "6.5.9".freeze
3
3
  end