govspeak 6.5.0 → 6.5.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 691092344fa56f8643bda4f29f8f0a18344515254b042fb15771375489395015
4
- data.tar.gz: 529021924ad18fccfabda572204e59b33867578e548816ab093e2d51b30e059f
3
+ metadata.gz: d1153c71bd7cd224750aa162c1ea63c89a902309cd08238a888d07a60f079d89
4
+ data.tar.gz: a7efca4529a1c6017224a77965e45994d30eba3a3e05f6d209dadff85a516cd9
5
5
  SHA512:
6
- metadata.gz: a870b551730a2a07f5a85bdb06df18b56018f3a700d21469d8c1804fe51d044ae7beb5455a8d1e332f44e003ed2d6231eb9f36fd72b0578de19cc408973074f0
7
- data.tar.gz: d0b4ca4cf824216c139094d33fdd1a9ddf98800db9aa94b077b454cfce35e98713b1b6e850c63817242f5cc3e381aaa9633062d1b01c3a7450ec6a64876632ee
6
+ metadata.gz: 33209bc51e340ccc5a2a0dc3b43f887eddbd464b687232fb4a17c6c34ae0a3097321f7f51da3ba17762e6ad1307424204872c3374dfa99eeb0100992641f4911
7
+ data.tar.gz: ab00d13be257f7730b4b7c2a858a9a9eba3802148dfc851f60fdf91eb65acdb80510a5c67a1e599f2cedbf945502cf29d6567526d695872118025ebb384318f9
data/CHANGELOG.md CHANGED
@@ -1,12 +1,17 @@
1
+ ## 6.5.1
2
+ * Change unicode testing characters after external gem change
3
+ * Move from govuk-lint to rubocop-govuk
4
+ * Allow version 6 of actionview
5
+
1
6
  ## 6.5.0
2
7
 
3
8
  * Allow data attributes on links
4
9
 
5
10
  ## 6.4.0
6
11
 
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)
12
+ * 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
13
 
9
- ## 6.3.0
14
+ ## 6.3.0
10
15
 
11
16
  * Unicode characters forbidden in HTML are stripped from input
12
17
  * Validation is now more lenient for HTML input
data/Rakefile CHANGED
@@ -7,7 +7,7 @@ Bundler::GemHelper.install_tasks
7
7
  desc "Run basic tests"
8
8
  Rake::TestTask.new("test") { |t|
9
9
  t.libs << "test"
10
- t.pattern = 'test/*_test.rb'
10
+ t.pattern = "test/*_test.rb"
11
11
  t.verbose = true
12
12
  t.warning = true
13
13
  }
data/lib/govspeak.rb CHANGED
@@ -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 = {})
@@ -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)
@@ -147,7 +147,7 @@ module Govspeak
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
@@ -176,51 +176,51 @@ module Govspeak
176
176
  %{\n<a role="button" class="#{button_classes}" href="#{href}" #{data_attribute}>#{text}</a>\n}
177
177
  }
178
178
 
179
- extension('highlight-answer') { |body|
179
+ extension("highlight-answer") { |body|
180
180
  %{\n\n<div class="highlight-answer">
181
181
  #{Govspeak::Document.new(body.strip).to_html}</div>\n}
182
182
  }
183
183
 
184
- extension('stat-headline', %r${stat-headline}(.*?){/stat-headline}$m) { |body|
184
+ extension("stat-headline", %r${stat-headline}(.*?){/stat-headline}$m) { |body|
185
185
  %{\n\n<aside class="stat-headline">
186
186
  #{Govspeak::Document.new(body.strip).to_html}</aside>\n}
187
187
  }
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")) { |body|
191
191
  Kramdown::Document.new("[#{body.strip}){:rel='external'}").to_html
192
192
  }
193
193
 
194
- extension('informational', surrounded_by("^")) { |body|
194
+ extension("informational", surrounded_by("^")) { |body|
195
195
  %{\n\n<div role="note" aria-label="Information" class="application-notice info-notice">
196
196
  #{Govspeak::Document.new(body.strip).to_html}</div>\n}
197
197
  }
198
198
 
199
- extension('important', surrounded_by("@")) { |body|
199
+ extension("important", surrounded_by("@")) { |body|
200
200
  %{\n\n<div role="note" aria-label="Important" class="advisory">#{insert_strong_inside_p(body)}</div>\n}
201
201
  }
202
202
 
203
- extension('helpful', surrounded_by("%")) { |body|
203
+ extension("helpful", surrounded_by("%")) { |body|
204
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
  }
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',
213
+ "{:",
214
+ ".js-barchart-table",
215
215
  stacked,
216
216
  compact,
217
217
  negative,
218
- '.mc-auto-outdent',
219
- '}'
220
- ].join(' ')
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,7 +228,7 @@ 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
 
@@ -243,7 +243,7 @@ module Govspeak
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
 
@@ -266,29 +266,29 @@ module Govspeak
266
266
  lines << %{<figure#{id_attr} class="image embedded">}
267
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|
282
+ extension("address", surrounded_by("$A")) { |body|
283
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
  }
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
@@ -301,12 +301,12 @@ module Govspeak
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,28 +344,28 @@ 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
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
371
  %{<govspeak-embed-attachment-link id="#{attachment_id}"></govspeak-embed-attachment-link>}
@@ -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
  )
@@ -20,7 +20,7 @@ module Govspeak
20
20
  private
21
21
 
22
22
  def id(element)
23
- element.attr.fetch('id', generate_id(element.options[:raw_text]))
23
+ element.attr.fetch("id", generate_id(element.options[:raw_text]))
24
24
  end
25
25
 
26
26
  def build_header(element)
@@ -1,4 +1,4 @@
1
- require 'addressable/uri'
1
+ require "addressable/uri"
2
2
 
3
3
  class Govspeak::HtmlSanitizer
4
4
  class ImageSourceWhitelister
@@ -10,7 +10,7 @@ class Govspeak::HtmlSanitizer
10
10
  return unless sanitize_context[:node_name] == "img"
11
11
 
12
12
  node = sanitize_context[:node]
13
- image_uri = Addressable::URI.parse(node['src'])
13
+ image_uri = Addressable::URI.parse(node["src"])
14
14
  unless image_uri.relative? || @allowed_image_hosts.include?(image_uri.host)
15
15
  node.unlink # the node isn't sanitary. Remove it from the document.
16
16
  end
@@ -25,8 +25,8 @@ class Govspeak::HtmlSanitizer
25
25
 
26
26
  # Kramdown uses text-align to allow table cells to be aligned
27
27
  # http://kramdown.gettalong.org/quickref.html#tables
28
- if invalid_style_attribute?(node['style'])
29
- node.remove_attribute('style')
28
+ if invalid_style_attribute?(node["style"])
29
+ node.remove_attribute("style")
30
30
  end
31
31
  end
32
32
 
@@ -58,7 +58,7 @@ class Govspeak::HtmlSanitizer
58
58
  "th" => Sanitize::Config::RELAXED[:attributes]["th"] + %w[style],
59
59
  "td" => Sanitize::Config::RELAXED[:attributes]["td"] + %w[style],
60
60
  "govspeak-embed-attachment" => %w[content-id],
61
- }
61
+ },
62
62
  )
63
63
  end
64
64
  end
@@ -20,8 +20,8 @@ module Govspeak
20
20
  end
21
21
 
22
22
  def extract_href_from_link(link)
23
- href = link['href'] || ''
24
- if website_root && href.start_with?('/')
23
+ href = link["href"] || ""
24
+ if website_root && href.start_with?("/")
25
25
  "#{website_root}#{href}"
26
26
  else
27
27
  href
@@ -29,7 +29,7 @@ module Govspeak
29
29
  end
30
30
 
31
31
  def document_anchors
32
- processed_govspeak.css('a[href]').css('a:not([href^="mailto"])').css('a:not([href^="#"])')
32
+ processed_govspeak.css("a[href]").css('a:not([href^="mailto"])').css('a:not([href^="#"])')
33
33
  end
34
34
 
35
35
  def processed_govspeak
@@ -2,8 +2,8 @@ module Govspeak
2
2
  class PostProcessor
3
3
  @extensions = []
4
4
 
5
- def self.extensions
6
- @extensions
5
+ class << self
6
+ attr_reader :extensions
7
7
  end
8
8
 
9
9
  def self.process(html, govspeak_document)
@@ -38,11 +38,11 @@ module Govspeak
38
38
  el.children = xml
39
39
  .gsub(
40
40
  %r{&lt;(div class="img")&gt;(.*?)&lt;(/div)&gt;},
41
- "<\\1>\\2<\\3>"
41
+ "<\\1>\\2<\\3>",
42
42
  )
43
43
  .gsub(
44
44
  %r{&lt;(figcaption)&gt;(.*?)&lt;(/figcaption&)gt;},
45
- "<\\1>\\2<\\3>"
45
+ "<\\1>\\2<\\3>",
46
46
  )
47
47
  end
48
48
  end
@@ -59,7 +59,7 @@ module Govspeak
59
59
  attachment_html = GovukPublishingComponents.render(
60
60
  "govuk_publishing_components/components/attachment",
61
61
  attachment: attachment,
62
- locale: govspeak_document.locale
62
+ locale: govspeak_document.locale,
63
63
  )
64
64
  el.swap(attachment_html)
65
65
  end
@@ -77,7 +77,7 @@ module Govspeak
77
77
  attachment_html = GovukPublishingComponents.render(
78
78
  "govuk_publishing_components/components/attachment_link",
79
79
  attachment: attachment,
80
- locale: govspeak_document.locale
80
+ locale: govspeak_document.locale,
81
81
  )
82
82
  el.swap(attachment_html)
83
83
  end
@@ -85,17 +85,17 @@ module Govspeak
85
85
 
86
86
  extension("Add table headers and row / column scopes") do |document|
87
87
  document.css("thead th").map do |el|
88
- el.content = el.content.gsub(/^# /, '')
89
- el.content = el.content.gsub(/[[:space:]]/, '') if el.content.blank? # Removes a strange whitespace in the cell if the cell is already blank.
90
- el.name = 'td' if el.content.blank? # This prevents a `th` with nothing inside it; a `td` is preferable.
88
+ el.content = el.content.gsub(/^# /, "")
89
+ el.content = el.content.gsub(/[[:space:]]/, "") if el.content.blank? # Removes a strange whitespace in the cell if the cell is already blank.
90
+ el.name = "td" if el.content.blank? # This prevents a `th` with nothing inside it; a `td` is preferable.
91
91
  el[:scope] = "col" if el.content.present? # `scope` shouldn't be used if there's nothing in the table heading.
92
92
  end
93
93
 
94
94
  document.css(":not(thead) tr td:first-child").map do |el|
95
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.
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
99
  end
100
100
  end
101
101
  end