govspeak 5.6.0 → 5.7.0

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.
@@ -6,7 +6,7 @@ module Govspeak
6
6
  end
7
7
 
8
8
  def call
9
- @links ||= extract_links
9
+ @call ||= extract_links
10
10
  end
11
11
 
12
12
  private
@@ -2,35 +2,18 @@ require 'nokogiri'
2
2
 
3
3
  module Govspeak
4
4
  class PostProcessor
5
- attr_reader :input
6
-
7
- @@extensions = []
8
-
9
- def initialize(html)
10
- @input = html
11
- end
5
+ @extensions = []
12
6
 
13
- def nokogiri_document
14
- doc = Nokogiri::HTML::Document.new
15
- doc.encoding = "UTF-8"
16
- doc.fragment(input)
7
+ def self.extensions
8
+ @extensions
17
9
  end
18
- private :nokogiri_document
19
10
 
20
11
  def self.process(html)
21
12
  new(html).output
22
13
  end
23
14
 
24
15
  def self.extension(title, &block)
25
- @@extensions << [title, block]
26
- end
27
-
28
- def output
29
- document = nokogiri_document
30
- @@extensions.each do |_, block|
31
- instance_exec(document, &block)
32
- end
33
- document.to_html
16
+ @extensions << [title, block]
34
17
  end
35
18
 
36
19
  extension("add class to last p of blockquote") do |document|
@@ -53,6 +36,7 @@ module Govspeak
53
36
  document.css("figure.image").map do |el|
54
37
  xml = el.children.to_s
55
38
  next unless xml =~ /&lt;div class="img"&gt;|&lt;figcaption&gt;/
39
+
56
40
  el.children = xml
57
41
  .gsub(
58
42
  %r{&lt;(div class="img")&gt;(.*?)&lt;(/div)&gt;},
@@ -64,5 +48,28 @@ module Govspeak
64
48
  )
65
49
  end
66
50
  end
51
+
52
+ attr_reader :input
53
+
54
+ def initialize(html)
55
+ @input = html
56
+ end
57
+
58
+ def output
59
+ document = nokogiri_document
60
+ self.class.extensions.each do |_, block|
61
+ instance_exec(document, &block)
62
+ end
63
+ document.to_html
64
+ end
65
+
66
+
67
+ private
68
+
69
+ def nokogiri_document
70
+ doc = Nokogiri::HTML::Document.new
71
+ doc.encoding = "UTF-8"
72
+ doc.fragment(input)
73
+ end
67
74
  end
68
75
  end
@@ -2,6 +2,8 @@ require "action_view"
2
2
  require "money"
3
3
  require "htmlentities"
4
4
 
5
+ Money.locale_backend = :currency
6
+
5
7
  module Govspeak
6
8
  class AttachmentPresenter
7
9
  attr_reader :attachment
@@ -36,6 +38,7 @@ module Govspeak
36
38
 
37
39
  def price
38
40
  return unless attachment[:price]
41
+
39
42
  Money.from_amount(attachment[:price], 'GBP').format
40
43
  end
41
44
 
@@ -46,6 +49,7 @@ module Govspeak
46
49
  def thumbnail_link
47
50
  return if hide_thumbnail?
48
51
  return if previewable?
52
+
49
53
  link(attachment_thumbnail, url, "aria-hidden" => "true", "class" => attachment_class)
50
54
  end
51
55
 
@@ -83,16 +87,16 @@ module Govspeak
83
87
  end
84
88
 
85
89
  def body_for_mail(attachment_info)
86
- <<-END
87
- Details of document required:
90
+ <<~TEXT
91
+ Details of document required:
88
92
 
89
- #{attachment_info.join("\n")}
93
+ #{attachment_info.join("\n")}
90
94
 
91
- Please tell us:
95
+ Please tell us:
92
96
 
93
- 1. What makes this format unsuitable for you?
94
- 2. What format you would prefer?
95
- END
97
+ 1. What makes this format unsuitable for you?
98
+ 2. What format you would prefer?
99
+ TEXT
96
100
  end
97
101
 
98
102
  def alternative_format_contact_email
@@ -256,6 +260,7 @@ END
256
260
 
257
261
  def attachment_details
258
262
  return if previewable?
263
+
259
264
  link(title, url, title_link_options)
260
265
  end
261
266
 
@@ -1,24 +1,69 @@
1
1
  require 'active_support/core_ext/array'
2
- require 'ostruct'
2
+ require 'active_support/core_ext/hash'
3
3
 
4
4
  module Govspeak
5
5
  class ContactPresenter
6
6
  attr_reader :contact
7
- delegate :id, :content_id, :title, :recipient, :street_address, :postal_code,
8
- :locality, :region, :country_code, :country_name, :email, :contact_form_url,
9
- :comments, :worldwide_organisation_path, to: :contact
10
7
 
11
8
  def initialize(contact)
12
- @contact = OpenStruct.new(contact)
9
+ @contact = ActiveSupport::HashWithIndifferentAccess.new(contact)
13
10
  end
14
11
 
15
- def contact_numbers
16
- Array.wrap(contact[:contact_numbers])
12
+ def content_id
13
+ contact[:content_id]
17
14
  end
18
15
 
19
- def has_postal_address?
20
- recipient.present? || street_address.present? || locality.present? ||
21
- region.present? || postal_code.present?
16
+ def title
17
+ contact[:title]
18
+ end
19
+
20
+ def description
21
+ contact[:description]
22
+ end
23
+
24
+ def post_addresses
25
+ @post_addresses ||= begin
26
+ addresses = contact.dig(:details, :post_addresses) || []
27
+ filter_post_addresses(addresses)
28
+ end
29
+ end
30
+
31
+ def email_addresses
32
+ @email_addresses ||= begin
33
+ emails = contact.dig(:details, :email_addresses) || []
34
+ emails.select { |e| e[:email].present? }
35
+ end
36
+ end
37
+
38
+ def phone_numbers
39
+ @phone_numbers ||= begin
40
+ phone_numbers = contact.dig(:details, :phone_numbers) || []
41
+ phone_numbers.select { |p| p[:number].present? }
42
+ end
43
+ end
44
+
45
+ def contact_form_links
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
50
+ end
51
+
52
+ private
53
+
54
+ def filter_post_addresses(addresses)
55
+ addresses.each do |address|
56
+ # A lot of the postal addresses published to the Publishing API have
57
+ # a populated array of postal addresses but each field an empty string :-(
58
+ address.delete_if do |key, value|
59
+ # Not showing United Kingdom country is a "feature" lifted and shifted
60
+ # from Whitehall:
61
+ # https://github.com/alphagov/whitehall/blob/c67d53d80f9856549c2da1941a10dbb9170be494/lib/address_formatter/formatter.rb#L17
62
+ (key == "world_location" && value.strip == "United Kingdom" || value == "")
63
+ end
64
+ end
65
+
66
+ addresses.reject(&:empty?)
22
67
  end
23
68
  end
24
69
  end
@@ -1,46 +1,26 @@
1
1
  module Govspeak
2
2
  class HCardPresenter
3
- def self.from_contact(contact)
4
- new(contact_properties(contact), contact.country_code)
5
- end
6
-
7
- def self.contact_properties(contact)
8
- { 'fn' => contact.recipient,
9
- 'street-address' => contact.street_address,
10
- 'postal-code' => contact.postal_code,
11
- 'locality' => contact.locality,
12
- 'region' => contact.region,
13
- 'country-name' => country_name(contact) }
14
- end
15
-
16
- def self.country_name(contact)
17
- contact.country_name unless contact.country_code == 'GB'
18
- end
19
-
20
- def self.property_keys
21
- ['fn', 'street-address', 'postal-code', 'locality', 'region', 'country-name']
22
- end
23
-
24
3
  def self.address_formats
25
- @address_formats ||= YAML.load_file('config/address_formats.yml')
4
+ @address_formats ||= YAML.load_file(
5
+ File.expand_path('config/address_formats.yml', Govspeak.root)
6
+ )
26
7
  end
27
8
 
28
- attr_reader :properties, :country_code
9
+ attr_reader :contact_address
29
10
 
30
- def initialize(properties, country_code)
31
- @properties = properties
32
- @country_code = country_code
11
+ def initialize(contact_address)
12
+ @contact_address = contact_address
33
13
  end
34
14
 
35
15
  def render
36
16
  "<p class=\"adr\">\n#{interpolate_address_template}\n</p>\n".html_safe
37
17
  end
38
18
 
39
- def interpolate_address_property(property_name)
40
- value = properties[property_name]
19
+ def interpolate_address_property(our_name, hcard_name)
20
+ value = contact_address[our_name]
41
21
 
42
22
  if value.present?
43
- "<span class=\"#{property_name}\">#{ERB::Util.html_escape(value)}</span>"
23
+ "<span class=\"#{hcard_name}\">#{ERB::Util.html_escape(value)}</span>"
44
24
  else
45
25
  ""
46
26
  end
@@ -51,8 +31,17 @@ module Govspeak
51
31
  def interpolate_address_template
52
32
  address = address_template
53
33
 
54
- self.class.property_keys.each do |key|
55
- address.gsub!(/\{\{#{key}\}\}/, interpolate_address_property(key))
34
+ properties = {
35
+ title: "fn",
36
+ street_address: "street-address",
37
+ locality: "locality",
38
+ region: "region",
39
+ postal_code: "postal-code",
40
+ world_location: "country-name",
41
+ }
42
+
43
+ properties.each do |our_name, hcard_name|
44
+ address.gsub!(/\{\{#{hcard_name}\}\}/, interpolate_address_property(our_name, hcard_name))
56
45
  end
57
46
 
58
47
  address.gsub(/^\n/, '') # get rid of blank lines
@@ -61,7 +50,8 @@ module Govspeak
61
50
  end
62
51
 
63
52
  def address_template
64
- (self.class.address_formats[country_code.to_s.downcase] || default_format_string).dup
53
+ country_code = contact_address[:iso2_country_code].to_s.downcase
54
+ (self.class.address_formats[country_code] || default_format_string).dup
65
55
  end
66
56
 
67
57
  def default_format_string
@@ -1,5 +1,4 @@
1
1
  module Govspeak
2
-
3
2
  StructuredHeader = Struct.new(:text, :level, :id, :headers) do
4
3
  def top_level
5
4
  2
@@ -1,3 +1,3 @@
1
1
  module Govspeak
2
- VERSION = "5.6.0".freeze
2
+ VERSION = "5.7.0".freeze
3
3
  end
@@ -4,17 +4,17 @@ require "kramdown/options"
4
4
  module Kramdown
5
5
  module Options
6
6
  class AlwaysEqual
7
- def ==(other)
7
+ def ==(_other)
8
8
  true
9
9
  end
10
10
  end
11
11
 
12
- define(:document_domains, Object, %w{www.gov.uk}, <<EOF) do |val|
13
- Defines the domains which are considered local to the document
12
+ define(:document_domains, Object, %w{www.gov.uk}, <<~DESCRIPTION) do |val|
13
+ Defines the domains which are considered local to the document
14
14
 
15
- Default: www.gov.uk
16
- Used by: KramdownWithAutomaticExternalLinks
17
- EOF
15
+ Default: www.gov.uk
16
+ Used by: KramdownWithAutomaticExternalLinks
17
+ DESCRIPTION
18
18
  simple_array_validator(val, :document_domains, AlwaysEqual.new)
19
19
  end
20
20
  end
@@ -26,16 +26,18 @@ EOF
26
26
  super
27
27
  end
28
28
 
29
- def add_link(el, href, title, alt_text = nil, ial = nil)
30
- if el.type == :a
29
+ def add_link(element, href, title, alt_text = nil, ial = nil)
30
+ if element.type == :a
31
31
  begin
32
32
  host = Addressable::URI.parse(href).host
33
- unless host.nil? || (@document_domains.compact.include?(host))
34
- el.attr['rel'] = 'external'
33
+ unless host.nil? || @document_domains.compact.include?(host)
34
+ element.attr['rel'] = 'external'
35
35
  end
36
+ # rubocop:disable Lint/HandleExceptions
36
37
  rescue Addressable::URI::InvalidURIError
37
38
  # it's safe to ignore these very *specific* exceptions
38
39
  end
40
+ # rubocop:enable Lint/HandleExceptions
39
41
  end
40
42
  super
41
43
  end
@@ -6,14 +6,14 @@
6
6
  <h2 class="title"><%= attachment.attachment_details %></h2>
7
7
  <p class="metadata">
8
8
  <% if attachment.references? %>
9
- <span class="references"><%= t('attachment.headings.reference') %>: <%= attachment.reference %></span>
9
+ <span class="references"><%= t('govspeak.attachment.headings.reference') %>: <%= attachment.reference %></span>
10
10
  <% end %>
11
11
  <% if attachment.unnumbered_paper? %>
12
12
  <span class="unnumbered-paper">
13
13
  <% if attachment.unnumbered_command_paper? %>
14
- <%= t('attachment.headings.unnumbered_command_paper') %>
14
+ <%= t('govspeak.attachment.headings.unnumbered_command_paper') %>
15
15
  <% else %>
16
- <%= t('attachment.headings.unnumbered_hoc_paper') %>
16
+ <%= t('govspeak.attachment.headings.unnumbered_hoc_paper') %>
17
17
  <% end %>
18
18
  </span>
19
19
  <% end %>
@@ -28,25 +28,25 @@
28
28
  </p>
29
29
  <% if attachment.order_url.present? %>
30
30
  <p>
31
- <%= attachment.link t('attachment.headings.order_a_copy'), attachment.order_url,
32
- class: "order_url", title: t('attachment.headings.order_a_copy_full')
31
+ <%= attachment.link t('govspeak.attachment.headings.order_a_copy'), attachment.order_url,
32
+ class: "order_url", title: t('govspeak.attachment.headings.order_a_copy_full')
33
33
  %><% if attachment.price %>(<span class="price"><%= attachment.price %></span>)<% end %>
34
34
  </p>
35
35
  <% end %>
36
36
 
37
37
  <% if attachment.opendocument? %>
38
38
  <p class="opendocument-help">
39
- <%= t('attachment.opendocument.help_html') %>
39
+ <%= t('govspeak.attachment.opendocument.help_html') %>
40
40
  </p>
41
41
  <% end %>
42
42
 
43
43
  <% unless attachment.accessible? %>
44
44
  <div data-module="toggle" class="accessibility-warning" id="<%= attachment.help_block_id %>">
45
- <h2><%= t('attachment.accessibility.heading') %>
46
- <a class="toggler" href="#<%= attachment.help_block_toggle_id %>" data-controls="<%= attachment.help_block_toggle_id %>" data-expanded="false"><%= t('attachment.accessibility.request_a_different_format') %></a>
45
+ <h2><%= t('govspeak.attachment.accessibility.heading') %>
46
+ <a class="toggler" href="#<%= attachment.help_block_toggle_id %>" data-controls="<%= attachment.help_block_toggle_id %>" data-expanded="false"><%= t('govspeak.attachment.accessibility.request_a_different_format') %></a>
47
47
  </h2>
48
48
  <p id="<%= attachment.help_block_toggle_id %>" class="js-hidden">
49
- <%= t('attachment.accessibility.full_help_html',
49
+ <%= t('govspeak.attachment.accessibility.full_help_html',
50
50
  email: attachment.alternative_format_order_link,
51
51
  title: attachment.title,
52
52
  references: attachment.references_for_title) %>
@@ -1,41 +1,38 @@
1
1
  <%
2
2
  extra_class = []
3
- extra_class << 'postal-address' if contact.has_postal_address?
3
+ extra_class << 'postal-address' if contact.post_addresses.any?
4
4
  %>
5
- <div id="contact_<%= contact.id %>" class="<%= ['contact', extra_class].flatten.join(' ') %>">
5
+ <div id="contact_<%= contact.content_id %>" class="<%= ['contact', extra_class].flatten.join(' ') %>">
6
6
  <div class="content">
7
7
  <h3><%= contact.title %></h3>
8
8
  <div class="vcard contact-inner">
9
- <% if contact.has_postal_address? %>
10
- <%= render_hcard_address(contact) %>
9
+ <% contact.post_addresses.each do |address| %>
10
+ <%= render_hcard_address(address) %>
11
11
  <% end %>
12
- <% if contact.email.present? || contact.contact_form_url.present? || contact.contact_numbers.any? %>
12
+ <% if contact.email_addresses.any? || contact.phone_numbers.any? || contact.contact_form_links.any? %>
13
13
  <div class="email-url-number">
14
- <% if contact.email.present? %>
14
+ <% contact.email_addresses.each do |email| %>
15
15
  <p class="email">
16
- <span class="type"><%= t('contact.email') %></span>
17
- <a href="mailto:<%= contact.email %>" class="email"><%= contact.email %></a>
16
+ <span class="type"><%= t('govspeak.contact.email') %></span>
17
+ <a href="mailto:<%= email[:email] %>" class="email"><%= email[:title].present? ? email[:title] : email[:email] %></a>
18
18
  </p>
19
19
  <% end %>
20
- <% if contact.contact_form_url.present? %>
20
+ <% contact.contact_form_links.each do |form_link| %>
21
21
  <p class="contact_form_url">
22
- <span class="type"><%= t('contact.contact_form') %></span>
23
- <a href="<%= contact.contact_form_url %>"><%= contact.contact_form_url.truncate(25) %></a>
22
+ <span class="type"><%= t('govspeak.contact.contact_form') %></span>
23
+ <a href="<%= form_link[:link] %>"><%= form_link[:link].truncate(25) %></a>
24
24
  </p>
25
25
  <% end %>
26
- <% contact.contact_numbers.each do |number| %>
26
+ <% contact.phone_numbers.each do |number| %>
27
27
  <p class="tel">
28
- <span class="type"><%= number[:label] %></span>
28
+ <span class="type"><%= number[:title] %></span>
29
29
  <%= number[:number] %>
30
30
  </p>
31
31
  <% end %>
32
32
  </div>
33
33
  <% end %>
34
- <% if contact.comments.present? %>
35
- <p class="comments"><%= auto_link(format_with_html_line_breaks(h(contact.comments))) %></p>
36
- <% end %>
37
- <% if contact.worldwide_organisation_path %>
38
- <a href="<%= contact.worldwide_organisation_path %>">Access and opening times</a>
34
+ <% if contact.description.present? %>
35
+ <p class="comments"><%= Rinku.auto_link(format_with_html_line_breaks(contact.description)) %></p>
39
36
  <% end %>
40
37
  </div>
41
38
  </div>