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
@@ -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
 
@@ -51,14 +51,17 @@ class Govspeak::HtmlSanitizer
51
51
  def sanitize_config
52
52
  Sanitize::Config.merge(
53
53
  Sanitize::Config::RELAXED,
54
- elements: Sanitize::Config::RELAXED[:elements] + %w[govspeak-embed-attachment govspeak-embed-attachment-link],
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],
58
- "th" => Sanitize::Config::RELAXED[:attributes]["th"] + %w[style],
59
- "td" => Sanitize::Config::RELAXED[:attributes]["td"] + %w[style],
57
+ "a" => Sanitize::Config::RELAXED[:attributes]["a"] + [:data],
58
+ "svg" => Sanitize::Config::RELAXED[:attributes][:all] + %w[xmlns width height viewbox focusable],
59
+ "path" => Sanitize::Config::RELAXED[:attributes][:all] + %w[fill d],
60
+ "div" => [:data],
61
+ "th" => Sanitize::Config::RELAXED[:attributes]["th"] + %w[style],
62
+ "td" => Sanitize::Config::RELAXED[:attributes]["td"] + %w[style],
60
63
  "govspeak-embed-attachment" => %w[content-id],
61
- }
64
+ },
62
65
  )
63
66
  end
64
67
  end
@@ -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,14 +14,14 @@ 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)
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,18 +85,38 @@ 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
- 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.
102
+ end
103
+ end
104
+
105
+ extension("use gem component for buttons") do |document|
106
+ document.css(".govuk-button").map do |el|
107
+ button_html = GovukPublishingComponents.render(
108
+ "govuk_publishing_components/components/button",
109
+ text: el.content,
110
+ href: el["href"],
111
+ start: el["data-start"],
112
+ data_attributes: {
113
+ module: el["data-module"],
114
+ "tracking-code": el["data-tracking-code"],
115
+ "tracking-name": el["data-tracking-name"],
116
+ },
117
+ ).squish.gsub("> <", "><").gsub!(/\s+/, " ")
118
+
119
+ el.swap(button_html)
100
120
  end
101
121
  end
102
122
 
@@ -34,15 +34,15 @@ module Govspeak
34
34
  def attachment_attributes
35
35
  attributes = []
36
36
  if file_extension == "html"
37
- attributes << content_tag(:span, 'HTML', class: 'type')
37
+ attributes << content_tag(:span, "HTML", class: "type")
38
38
  elsif attachment[:external?]
39
- attributes << content_tag(:span, url, class: 'url')
39
+ attributes << content_tag(:span, url, class: "url")
40
40
  else
41
- attributes << content_tag(:span, humanized_content_type(file_extension), class: 'type') if file_extension
42
- attributes << content_tag(:span, number_to_human_size(attachment[:file_size]), class: 'file-size') if attachment[:file_size]
43
- attributes << content_tag(:span, pluralize(attachment[:number_of_pages], "page"), class: 'page-length') if attachment[:number_of_pages]
41
+ attributes << content_tag(:span, humanized_content_type(file_extension), class: "type") if file_extension
42
+ attributes << content_tag(:span, number_to_human_size(attachment[:file_size]), class: "file-size") if attachment[:file_size]
43
+ attributes << content_tag(:span, pluralize(attachment[:number_of_pages], "page"), class: "page-length") if attachment[:number_of_pages]
44
44
  end
45
- attributes.join(', ').html_safe
45
+ attributes.join(", ").html_safe
46
46
  end
47
47
 
48
48
  MS_WORD_DOCUMENT_HUMANIZED_CONTENT_TYPE = "MS Word Document".freeze
@@ -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'),
60
- "diff" => file_abbr_tag('DIFF', 'Plain text differences'),
61
- "doc" => MS_WORD_DOCUMENT_HUMANIZED_CONTENT_TYPE,
58
+ "chm" => file_abbr_tag("CHM", "Microsoft Compiled HTML Help"),
59
+ "csv" => file_abbr_tag("CSV", "Comma-separated Values"),
60
+ "diff" => file_abbr_tag("DIFF", "Plain text differences"),
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'),
68
- "html" => file_abbr_tag('HTML', 'Hypertext Markup Language'),
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,
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
+ "html" => file_abbr_tag("HTML", "Hypertext Markup Language"),
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,
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",
83
- "wsdl" => file_abbr_tag('WSDL', 'Web Services Description Language'),
84
- "xls" => MS_EXCEL_SPREADSHEET_HUMANIZED_CONTENT_TYPE,
85
- "xlsm" => file_abbr_tag('XLSM', 'MS Excel Macro-Enabled Workbook'),
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
+ "wsdl" => file_abbr_tag("WSDL", "Web Services Description Language"),
84
+ "xls" => MS_EXCEL_SPREADSHEET_HUMANIZED_CONTENT_TYPE,
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'),
89
- "xslt" => file_abbr_tag('XSLT', 'Extensible Stylesheet Language Transformation'),
90
- "zip" => file_abbr_tag('ZIP', 'Zip archive'),
87
+ "xlt" => file_abbr_tag("XLT", "MS Excel Spreadsheet Template"),
88
+ "xsd" => file_abbr_tag("XSD", "XML Schema"),
89
+ "xslt" => file_abbr_tag("XSLT", "Extensible Stylesheet Language Transformation"),
90
+ "zip" => file_abbr_tag("ZIP", "Zip archive"),
91
91
  }
92
- file_extension_vs_humanized_content_type.fetch(file_extension.to_s.downcase, '')
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
@@ -1,5 +1,5 @@
1
- require 'active_support/core_ext/array'
2
- require 'active_support/core_ext/hash'
1
+ require "active_support/core_ext/array"
2
+ require "active_support/core_ext/hash"
3
3
 
4
4
  module Govspeak
5
5
  class ContactPresenter
@@ -2,7 +2,7 @@ module Govspeak
2
2
  class HCardPresenter
3
3
  def self.address_formats
4
4
  @address_formats ||= YAML.load_file(
5
- File.expand_path('config/address_formats.yml', Govspeak.root)
5
+ File.expand_path("config/address_formats.yml", Govspeak.root),
6
6
  )
7
7
  end
8
8
 
@@ -44,7 +44,7 @@ module Govspeak
44
44
  address.gsub!(/\{\{#{hcard_name}\}\}/, interpolate_address_property(our_name, hcard_name))
45
45
  end
46
46
 
47
- address.gsub(/^\n/, '') # get rid of blank lines
47
+ address.gsub(/^\n/, "") # get rid of blank lines
48
48
  .strip # get rid of any trailing whitespace
49
49
  .gsub(/\n/, "<br />\n") # add break tags where appropriate
50
50
  end
@@ -55,7 +55,7 @@ module Govspeak
55
55
  end
56
56
 
57
57
  def default_format_string
58
- self.class.address_formats['gb']
58
+ self.class.address_formats["gb"]
59
59
  end
60
60
  end
61
61
  end
@@ -32,10 +32,10 @@ module Govspeak
32
32
 
33
33
  def figcaption_html
34
34
  lines = []
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?
38
- lines << '</figcaption>'
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?
38
+ lines << "</figcaption>"
39
39
  lines.join
40
40
  end
41
41
  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.0".freeze
2
+ VERSION = "6.5.5".freeze
3
3
  end
@@ -9,7 +9,7 @@ module Kramdown
9
9
  end
10
10
  end
11
11
 
12
- define(:document_domains, Object, %w{www.gov.uk}, <<~DESCRIPTION) do |val|
12
+ define(:document_domains, Object, %w[www.gov.uk], <<~DESCRIPTION) do |val|
13
13
  Defines the domains which are considered local to the document
14
14
 
15
15
  Default: www.gov.uk
@@ -21,10 +21,10 @@ module Kramdown
21
21
 
22
22
  module Parser
23
23
  class Govuk < Kramdown::Parser::Kramdown
24
- CUSTOM_INLINE_ELEMENTS = %w(govspeak-embed-attachment-link).freeze
24
+ CUSTOM_INLINE_ELEMENTS = %w[govspeak-embed-attachment-link].freeze
25
25
 
26
26
  def initialize(source, options)
27
- @document_domains = options[:document_domains] || %w(www.gov.uk)
27
+ @document_domains = options[:document_domains] || %w[www.gov.uk]
28
28
  super
29
29
  end
30
30
 
@@ -33,13 +33,12 @@ module Kramdown
33
33
  begin
34
34
  host = Addressable::URI.parse(href).host
35
35
  unless host.nil? || @document_domains.compact.include?(host)
36
- element.attr['rel'] = 'external'
36
+ element.attr["rel"] = "external"
37
37
  end
38
- # rubocop:disable Lint/HandleExceptions
39
- rescue Addressable::URI::InvalidURIError
38
+ rescue Addressable::URI::InvalidURIError # rubocop:disable Lint/SuppressedException
40
39
  # it's safe to ignore these very *specific* exceptions
41
40
  end
42
- # rubocop:enable Lint/HandleExceptions
41
+
43
42
  end
44
43
  super
45
44
  end
@@ -1,5 +1,3 @@
1
- # encoding: UTF-8
2
-
3
1
  require "test_helper"
4
2
 
5
3
  class BlockquoteExtraQuoteRemoverTest < Minitest::Test
@@ -18,81 +16,81 @@ class BlockquoteExtraQuoteRemoverTest < Minitest::Test
18
16
  end
19
17
 
20
18
  test "ignores text without double quotes" do
21
- assert_leaves_untouched %{no quotes\na few lines,\n\n\n\nbut no quotes\n\n}
19
+ assert_leaves_untouched %(no quotes\na few lines,\n\n\n\nbut no quotes\n\n)
22
20
  end
23
21
 
24
22
  test "ignores text without a quote symbol" do
25
- assert_leaves_untouched %{quotes\n"but not with a > symbol"}
23
+ assert_leaves_untouched %(quotes\n"but not with a > symbol")
26
24
  end
27
25
 
28
26
  test "transforms text with surrounding quotes" do
29
27
  assert_remover_transforms(
30
- %{He said:\n> "yes, it's true!"\n\napparently.} =>
31
- %{He said:\n> yes, it's true!\n\napparently.}
28
+ %(He said:\n> "yes, it's true!"\n\napparently.) =>
29
+ %(He said:\n> yes, it's true!\n\napparently.),
32
30
  )
33
31
  end
34
32
 
35
33
  test "leaves quotes in the middle of the string" do
36
34
  assert_remover_transforms(
37
- %{He said:\n> "yes, it's true!" whilst sipping a cocktail. "And yes, I did rather enjoy it." \n\napparently.} =>
38
- %{He said:\n> yes, it's true!" whilst sipping a cocktail. "And yes, I did rather enjoy it.\n\napparently.}
35
+ %(He said:\n> "yes, it's true!" whilst sipping a cocktail. "And yes, I did rather enjoy it." \n\napparently.) =>
36
+ %(He said:\n> yes, it's true!" whilst sipping a cocktail. "And yes, I did rather enjoy it.\n\napparently.),
39
37
  )
40
38
  end
41
39
 
42
40
  test "leaves trailing text and quote intact" do
43
41
  assert_remover_transforms(
44
- %{He said:\n> "yes, it's true!" whilst sipping a cocktail.} =>
45
- %{He said:\n> yes, it's true!" whilst sipping a cocktail.}
42
+ %(He said:\n> "yes, it's true!" whilst sipping a cocktail.) =>
43
+ %(He said:\n> yes, it's true!" whilst sipping a cocktail.),
46
44
  )
47
45
  end
48
46
 
49
47
  test "windows line breaks" do
50
48
  assert_remover_transforms(
51
- %{Sir George Young MP, said\r\n> "I welcome the positive public response to the e-petitions site, which is important way of building a bridge between people and Parliament.”\r\n## The special relationship} =>
52
- %{Sir George Young MP, said\r\n> I welcome the positive public response to the e-petitions site, which is important way of building a bridge between people and Parliament.\r\n## The special relationship}
49
+ %(Sir George Young MP, said\r\n> "I welcome the positive public response to the e-petitions site, which is important way of building a bridge between people and Parliament.”\r\n## The special relationship) =>
50
+ %(Sir George Young MP, said\r\n> I welcome the positive public response to the e-petitions site, which is important way of building a bridge between people and Parliament.\r\n## The special relationship),
53
51
  )
54
52
  end
55
53
 
56
54
  test "no space in front" do
57
55
  assert_remover_transforms(
58
- %{>"As we continue with the redundancy process we will ensure we retain the capabilities that our armed forces will require to meet the challenges of the future. The redundancy programme will not impact adversely on the current operations in Afghanistan, where our armed forces continue to fight so bravely on this country's behalf."} =>
59
- %{> As we continue with the redundancy process we will ensure we retain the capabilities that our armed forces will require to meet the challenges of the future. The redundancy programme will not impact adversely on the current operations in Afghanistan, where our armed forces continue to fight so bravely on this country's behalf.}
56
+ %(>"As we continue with the redundancy process we will ensure we retain the capabilities that our armed forces will require to meet the challenges of the future. The redundancy programme will not impact adversely on the current operations in Afghanistan, where our armed forces continue to fight so bravely on this country's behalf.") =>
57
+ %(> As we continue with the redundancy process we will ensure we retain the capabilities that our armed forces will require to meet the challenges of the future. The redundancy programme will not impact adversely on the current operations in Afghanistan, where our armed forces continue to fight so bravely on this country's behalf.),
60
58
  )
61
59
  end
62
60
 
63
61
  test "handles space after a quote" do
64
62
  assert_remover_transforms(
65
- %{>" Test"} =>
66
- %{> Test}
63
+ %(>" Test") =>
64
+ %(> Test),
67
65
  )
68
66
  end
69
67
 
70
68
  test "remove double double quotes" do
71
69
  assert_remover_transforms(
72
- %{We heard it said:\n\n> ""Today the coalition is remedying those deficiencies by putting in place a new fast track process where the people's elected representatives have responsibility for the final decisions about Britain's future instead of unelected commissioners.""} =>
73
- %{We heard it said:\n\n> Today the coalition is remedying those deficiencies by putting in place a new fast track process where the people's elected representatives have responsibility for the final decisions about Britain's future instead of unelected commissioners.}
70
+ %(We heard it said:\n\n> ""Today the coalition is remedying those deficiencies by putting in place a new fast track process where the people's elected representatives have responsibility for the final decisions about Britain's future instead of unelected commissioners."") =>
71
+ %(We heard it said:\n\n> Today the coalition is remedying those deficiencies by putting in place a new fast track process where the people's elected representatives have responsibility for the final decisions about Britain's future instead of unelected commissioners.),
74
72
  )
75
73
  assert_remover_transforms(
76
- %{> ""Today the coalition is remedying those deficiencies by putting in place a new fast track process where the people's elected representatives have responsibility for the final decisions about Britain's future instead of unelected commissioners.} =>
77
- %{> Today the coalition is remedying those deficiencies by putting in place a new fast track process where the people's elected representatives have responsibility for the final decisions about Britain's future instead of unelected commissioners.}
74
+ %(> ""Today the coalition is remedying those deficiencies by putting in place a new fast track process where the people's elected representatives have responsibility for the final decisions about Britain's future instead of unelected commissioners.) =>
75
+ %(> Today the coalition is remedying those deficiencies by putting in place a new fast track process where the people's elected representatives have responsibility for the final decisions about Britain's future instead of unelected commissioners.),
78
76
  )
79
77
  end
80
78
 
81
79
  test "removes quotes correctly from multi-line blockquotes" do
82
80
  assert_remover_transforms(
83
- %{> "Here is a block quote using 2 lines and two of the arrows.\n> I am not sure how this will render. I think it will mash them together."} =>
84
- %{> Here is a block quote using 2 lines and two of the arrows.\n> I am not sure how this will render. I think it will mash them together.}
81
+ %(> "Here is a block quote using 2 lines and two of the arrows.\n> I am not sure how this will render. I think it will mash them together.") =>
82
+ %(> Here is a block quote using 2 lines and two of the arrows.\n> I am not sure how this will render. I think it will mash them together.),
85
83
  )
86
84
  end
87
85
 
88
86
  test "preserves multiline blockquotes with plain newlines quotes" do
89
87
  assert_remover_transforms(
90
- %{> "line 1\n> \n> "line 2\n> \n> "line 3"} =>
91
- %{> line 1\n> \n> line 2\n> \n> line 3}
92
- )
88
+ %(> "line 1\n> \n> "line 2\n> \n> "line 3") =>
89
+ %(> line 1\n> \n> line 2\n> \n> line 3),
90
+ )
93
91
  end
94
92
 
95
93
  test "preserve newlines when there's a blockquote with additional text after" do
96
- assert_leaves_untouched(%{> \n> blah})
94
+ assert_leaves_untouched(%(> \n> blah))
97
95
  end
98
96
  end