govspeak 6.5.4 → 6.5.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/Rakefile +6 -3
- data/lib/govspeak.rb +51 -51
- data/lib/govspeak/html_sanitizer.rb +3 -3
- data/lib/govspeak/kramdown_overrides.rb +2 -2
- data/lib/govspeak/link_extractor.rb +3 -3
- data/lib/govspeak/post_processor.rb +7 -5
- data/lib/govspeak/presenters/attachment_presenter.rb +26 -26
- data/lib/govspeak/presenters/image_presenter.rb +2 -2
- data/lib/govspeak/structured_header_extractor.rb +2 -2
- data/lib/govspeak/version.rb +1 -1
- data/lib/kramdown/parser/govuk.rb +5 -6
- data/test/blockquote_extra_quote_remover_test.rb +24 -26
- data/test/govspeak_attachment_link_test.rb +0 -2
- data/test/govspeak_attachment_test.rb +0 -2
- data/test/govspeak_attachments_image_test.rb +2 -4
- data/test/govspeak_attachments_inline_test.rb +4 -6
- data/test/govspeak_button_test.rb +8 -10
- data/test/govspeak_contacts_test.rb +11 -13
- data/test/govspeak_extract_contact_content_ids_test.rb +0 -2
- data/test/govspeak_images_bang_test.rb +30 -32
- data/test/govspeak_images_test.rb +36 -38
- data/test/govspeak_link_extractor_test.rb +1 -1
- data/test/govspeak_link_test.rb +0 -2
- data/test/govspeak_structured_headers_test.rb +5 -4
- data/test/govspeak_table_with_headers_test.rb +67 -20
- data/test/govspeak_test.rb +80 -83
- data/test/govspeak_test_helper.rb +1 -1
- data/test/html_sanitizer_test.rb +0 -1
- data/test/presenters/h_card_presenter_test.rb +0 -2
- data/test/test_helper.rb +6 -2
- metadata +17 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 99554d6b3b3fd3287b35eebe6ff4633d6e3df24f74bede69fd65c16a81a41584
|
4
|
+
data.tar.gz: 300af892bfebf34b74161432f49d93131bde2d533354fd2580204c3d341b8031
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 033a7f0ac2134f8a7912fbb38033a07b8f51370d5631b1e6342a7b04d451b50540fc3874c5b3153af4a18b8ce892fa9f16d24ee6909ba339d2888423ea577199
|
7
|
+
data.tar.gz: df16ff9574a2b759b0bb75e53475e08b7164166af97e28d900ed1f44407826d4156ec7441bb07363362740542f698244dc78a712f4b4c1b59e9570ec598685e5
|
data/CHANGELOG.md
CHANGED
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")
|
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: [
|
18
|
+
task default: %i[test rubocop]
|
data/lib/govspeak.rb
CHANGED
@@ -108,9 +108,9 @@ module Govspeak
|
|
108
108
|
source = Govspeak::BlockquoteExtraQuoteRemover.remove(source)
|
109
109
|
source = remove_forbidden_characters(source)
|
110
110
|
self.class.extensions.each do |_, regexp, block|
|
111
|
-
source.gsub!(regexp)
|
111
|
+
source.gsub!(regexp) do
|
112
112
|
instance_exec(*Regexp.last_match.captures, &block)
|
113
|
-
|
113
|
+
end
|
114
114
|
end
|
115
115
|
source
|
116
116
|
end
|
@@ -127,20 +127,20 @@ module Govspeak
|
|
127
127
|
end
|
128
128
|
|
129
129
|
def self.surrounded_by(open, close = nil)
|
130
|
-
open = Regexp
|
130
|
+
open = Regexp.escape(open)
|
131
131
|
if close
|
132
|
-
close = Regexp
|
133
|
-
%r
|
132
|
+
close = Regexp.escape(close)
|
133
|
+
%r{(?:\r|\n|^)#{open}(.*?)#{close} *(\r|\n|$)?}m
|
134
134
|
else
|
135
|
-
%r
|
135
|
+
%r{(?:\r|\n|^)#{open}(.*?)#{open}? *(\r|\n|$)}m
|
136
136
|
end
|
137
137
|
end
|
138
138
|
|
139
139
|
def self.wrap_with_div(class_name, character, parser = Kramdown::Document)
|
140
|
-
extension(class_name, surrounded_by(character))
|
140
|
+
extension(class_name, surrounded_by(character)) do |body|
|
141
141
|
content = parser ? parser.new("#{body.strip}\n").to_html : body.strip
|
142
|
-
%
|
143
|
-
|
142
|
+
%(\n<div class="#{class_name}">\n#{content}</div>\n)
|
143
|
+
end
|
144
144
|
end
|
145
145
|
|
146
146
|
def insert_strong_inside_p(body, parser = Govspeak::Document)
|
@@ -160,7 +160,7 @@ module Govspeak
|
|
160
160
|
\s* # any whitespace between opening bracket and link
|
161
161
|
{\/button} # match ending bracket
|
162
162
|
(?:\r|\n|$) # non-capturing match to make sure end of line and linebreak
|
163
|
-
}x)
|
163
|
+
}x) do |attributes, text, href|
|
164
164
|
button_classes = "govuk-button"
|
165
165
|
/cross-domain-tracking:(?<cross_domain_tracking>.[^\s*]+)/ =~ attributes
|
166
166
|
data_attribute = ""
|
@@ -173,36 +173,36 @@ module Govspeak
|
|
173
173
|
text = text.strip
|
174
174
|
href = href.strip
|
175
175
|
|
176
|
-
%
|
177
|
-
|
176
|
+
%(\n<a role="button" class="#{button_classes}" href="#{href}" #{data_attribute}>#{text}</a>\n)
|
177
|
+
end
|
178
178
|
|
179
|
-
extension("highlight-answer")
|
180
|
-
%
|
181
|
-
#{Govspeak::Document.new(body.strip).to_html}</div>\n
|
182
|
-
|
179
|
+
extension("highlight-answer") do |body|
|
180
|
+
%(\n\n<div class="highlight-answer">
|
181
|
+
#{Govspeak::Document.new(body.strip).to_html}</div>\n)
|
182
|
+
end
|
183
183
|
|
184
|
-
extension("stat-headline", %r${stat-headline}(.*?){/stat-headline}$m)
|
185
|
-
%
|
186
|
-
#{Govspeak::Document.new(body.strip).to_html}</aside>\n
|
187
|
-
|
184
|
+
extension("stat-headline", %r${stat-headline}(.*?){/stat-headline}$m) do |body|
|
185
|
+
%(\n\n<aside class="stat-headline">
|
186
|
+
#{Govspeak::Document.new(body.strip).to_html}</aside>\n)
|
187
|
+
end
|
188
188
|
|
189
189
|
# FIXME: these surrounded_by arguments look dodgy
|
190
|
-
extension("external", surrounded_by("x[", ")x"))
|
190
|
+
extension("external", surrounded_by("x[", ")x")) do |body|
|
191
191
|
Kramdown::Document.new("[#{body.strip}){:rel='external'}").to_html
|
192
|
-
|
192
|
+
end
|
193
193
|
|
194
|
-
extension("informational", surrounded_by("^"))
|
195
|
-
%
|
196
|
-
#{Govspeak::Document.new(body.strip).to_html}</div>\n
|
197
|
-
|
194
|
+
extension("informational", surrounded_by("^")) do |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
|
+
end
|
198
198
|
|
199
|
-
extension("important", surrounded_by("@"))
|
200
|
-
%
|
201
|
-
|
199
|
+
extension("important", surrounded_by("@")) do |body|
|
200
|
+
%(\n\n<div role="note" aria-label="Important" class="advisory">#{insert_strong_inside_p(body)}</div>\n)
|
201
|
+
end
|
202
202
|
|
203
|
-
extension("helpful", surrounded_by("%"))
|
204
|
-
%
|
205
|
-
|
203
|
+
extension("helpful", surrounded_by("%")) do |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
|
+
end
|
206
206
|
|
207
207
|
extension("barchart", /{barchart(.*?)}/) do |captures|
|
208
208
|
stacked = ".mc-stacked" if captures.include? "stacked"
|
@@ -210,13 +210,13 @@ module Govspeak
|
|
210
210
|
negative = ".mc-negative" if captures.include? "negative"
|
211
211
|
|
212
212
|
[
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
213
|
+
"{:",
|
214
|
+
".js-barchart-table",
|
215
|
+
stacked,
|
216
|
+
compact,
|
217
|
+
negative,
|
218
|
+
".mc-auto-outdent",
|
219
|
+
"}",
|
220
220
|
].join(" ")
|
221
221
|
end
|
222
222
|
|
@@ -234,12 +234,12 @@ module Govspeak
|
|
234
234
|
|
235
235
|
attachment = AttachmentPresenter.new(attachment)
|
236
236
|
|
237
|
-
span_id = attachment.id ? %
|
237
|
+
span_id = attachment.id ? %( id="attachment_#{attachment.id}") : ""
|
238
238
|
# new lines inside our title cause problems with govspeak rendering as this is expected to be on one line.
|
239
239
|
title = (attachment.title || "").tr("\n", " ")
|
240
240
|
link = attachment.link(title, attachment.url)
|
241
241
|
attributes = attachment.attachment_attributes.empty? ? "" : " (#{attachment.attachment_attributes})"
|
242
|
-
%
|
242
|
+
%(<span#{span_id} class="attachment-inline">#{link}#{attributes}</span>)
|
243
243
|
end
|
244
244
|
|
245
245
|
# DEPRECATED: use 'Image:image-id' instead
|
@@ -261,10 +261,10 @@ module Govspeak
|
|
261
261
|
#
|
262
262
|
# This issue is not considered a bug by kramdown: https://github.com/gettalong/kramdown/issues/191
|
263
263
|
def render_image(image)
|
264
|
-
id_attr = image.id ? %
|
264
|
+
id_attr = image.id ? %( id="attachment_#{image.id}") : ""
|
265
265
|
lines = []
|
266
|
-
lines << %
|
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
268
|
lines << image.figcaption_html if image.figcaption?
|
269
269
|
lines << "</figure>"
|
270
270
|
lines.join
|
@@ -279,9 +279,9 @@ module Govspeak
|
|
279
279
|
wrap_with_div("example", "$E", Govspeak::Document)
|
280
280
|
wrap_with_div("call-to-action", "$CTA", Govspeak::Document)
|
281
281
|
|
282
|
-
extension("address", surrounded_by("$A"))
|
283
|
-
%
|
284
|
-
|
282
|
+
extension("address", surrounded_by("$A")) do |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
|
+
end
|
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
|
@@ -295,9 +295,9 @@ module Govspeak
|
|
295
295
|
|
296
296
|
extension("numbered list", /^[ \t]*((s\d+\.\s.*(?:\n|$))+)/) do |body|
|
297
297
|
body.gsub!(/s(\d+)\.\s(.*)(?:\n|$)/) do
|
298
|
-
"<li>#{Govspeak::Document.new(
|
298
|
+
"<li>#{Govspeak::Document.new(Regexp.last_match(2).strip).to_html}</li>\n"
|
299
299
|
end
|
300
|
-
%
|
300
|
+
%(<ol class="steps">\n#{body}</ol>)
|
301
301
|
end
|
302
302
|
|
303
303
|
def self.devolved_options
|
@@ -362,13 +362,13 @@ module Govspeak
|
|
362
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
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>)
|
372
372
|
end
|
373
373
|
|
374
374
|
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"
|
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"
|
62
|
-
"td"
|
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
|
-
#
|
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
|
-
#
|
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
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
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
|
|
@@ -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"
|
59
|
-
"csv"
|
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"
|
61
|
+
"doc" => MS_WORD_DOCUMENT_HUMANIZED_CONTENT_TYPE,
|
62
62
|
"docx" => MS_WORD_DOCUMENT_HUMANIZED_CONTENT_TYPE,
|
63
|
-
"dot"
|
64
|
-
"dxf"
|
65
|
-
"eps"
|
66
|
-
"gif"
|
67
|
-
"gml"
|
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"
|
71
|
-
"odp"
|
72
|
-
"ods"
|
73
|
-
"odt"
|
74
|
-
"pdf"
|
75
|
-
"png"
|
76
|
-
"ppt"
|
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"
|
79
|
-
"rdf"
|
80
|
-
"rtf"
|
81
|
-
"sch"
|
82
|
-
"txt"
|
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"
|
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"
|
88
|
-
"xsd"
|
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"
|
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| %
|
97
|
-
%
|
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 << %
|
37
|
-
lines << %
|
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
|
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)
|
data/lib/govspeak/version.rb
CHANGED
@@ -9,7 +9,7 @@ module Kramdown
|
|
9
9
|
end
|
10
10
|
end
|
11
11
|
|
12
|
-
define(:document_domains, Object, %w
|
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
|
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
|
27
|
+
@document_domains = options[:document_domains] || %w[www.gov.uk]
|
28
28
|
super
|
29
29
|
end
|
30
30
|
|
@@ -35,11 +35,10 @@ module Kramdown
|
|
35
35
|
unless host.nil? || @document_domains.compact.include?(host)
|
36
36
|
element.attr["rel"] = "external"
|
37
37
|
end
|
38
|
-
# rubocop:disable Lint/SuppressedException
|
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
|
-
|
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 %
|
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 %
|
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
|
-
%
|
31
|
-
%
|
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
|
-
%
|
38
|
-
%
|
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
|
-
%
|
45
|
-
%
|
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
|
-
%
|
52
|
-
%
|
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
|
-
%
|
59
|
-
%
|
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
|
-
%
|
66
|
-
%
|
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
|
-
%
|
73
|
-
%
|
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
|
-
%
|
77
|
-
%
|
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
|
-
%
|
84
|
-
%
|
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
|
-
%
|
91
|
-
%
|
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(%
|
94
|
+
assert_leaves_untouched(%(> \n> blah))
|
97
95
|
end
|
98
96
|
end
|