govspeak 5.6.0 → 5.7.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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>