govspeak 8.3.1 → 8.3.3

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 330ac68b36870075d83d6cae5223e28d12186d7b9435be02df50829f11d8c27e
4
- data.tar.gz: 3d0b8d3e7b1f98d9e3c814f141319a56a8388ac114b308aba7c3945e5661bbe4
3
+ metadata.gz: 13c63623d2836910a9a3e9c634059dfece9e7eca7a889d142ba006a8b74443db
4
+ data.tar.gz: 3235a49df7e6860a9f2a20b0e55eb92e771df6a5f16bac6ad61776e28494111a
5
5
  SHA512:
6
- metadata.gz: c23c1e930d96b6c67fcc9a46c3fc2b1e048d3c5cf9f741e55de28b94bb334e56a07108326cf5bc96c140764f860a0532ff38df87dbb9e04355576f93ebe7efad
7
- data.tar.gz: ed762ebf793ee83971ddcf4a5102379b2ad0dea4adea3134c8bd818c9c15d1d03e957b2b433549bc0846525bea1fb3a19c3574eafb1ac46dc1b98f27c59009cb
6
+ metadata.gz: 29f02ae12fd4b8388990109ba3c2fec681d85286bcf352fff8d571dd2918343410b1ca1df518a35dd8e9ef3e886e3a306ee185e619d0435b3670c57091da7bbd
7
+ data.tar.gz: 52094b3250537544d50761204701cb2ba5f32c94fd2bd2b32c81eb6ef5fbcfee1812f432f62133afcce2c02730401fd06db9e492ab67c2fea69680eaf525dfd2
data/CHANGELOG.md CHANGED
@@ -1,3 +1,11 @@
1
+ ## 8.3.3
2
+
3
+ * Fix single line formatting of call to action component ([#302](https://github.com/alphagov/govspeak/pull/302))
4
+
5
+ ## 8.3.2
6
+
7
+ * Various bug fixes related to legislative list components ([#298](https://github.com/alphagov/govspeak/pull/298))
8
+
1
9
  ## 8.3.1
2
10
 
3
11
  * Bug fixes related to block elements in call to action and legislative list components ([#293](https://github.com/alphagov/govspeak/pull/293))
@@ -167,7 +167,7 @@ module Govspeak
167
167
 
168
168
  def output
169
169
  document = nokogiri_document
170
- self.class.extensions.each do |_, block|
170
+ self.class.extensions.each do |(_, block)|
171
171
  instance_exec(document, &block)
172
172
  end
173
173
  document.to_html
@@ -59,7 +59,7 @@ module Govspeak
59
59
  # Not showing United Kingdom country is a "feature" lifted and shifted
60
60
  # from Whitehall:
61
61
  # https://github.com/alphagov/whitehall/blob/c67d53d80f9856549c2da1941a10dbb9170be494/lib/address_formatter/formatter.rb#L17
62
- (key == "world_location" && value.strip == "United Kingdom" || value == "")
62
+ key == "world_location" && value.strip == "United Kingdom" || value == ""
63
63
  end
64
64
  end
65
65
 
@@ -1,3 +1,3 @@
1
1
  module Govspeak
2
- VERSION = "8.3.1".freeze
2
+ VERSION = "8.3.3".freeze
3
3
  end
data/lib/govspeak.rb CHANGED
@@ -13,7 +13,6 @@ require "govspeak/header_extractor"
13
13
  require "govspeak/structured_header_extractor"
14
14
  require "govspeak/html_validator"
15
15
  require "govspeak/html_sanitizer"
16
- require "govspeak/kramdown_overrides"
17
16
  require "govspeak/blockquote_extra_quote_remover"
18
17
  require "govspeak/post_processor"
19
18
  require "govspeak/link_extractor"
@@ -278,7 +277,9 @@ module Govspeak
278
277
 
279
278
  extension("call-to-action", surrounded_by("$CTA")) do |body|
280
279
  <<~BODY
281
- <div class="call-to-action" markdown="1">#{body}</div>
280
+ <div class="call-to-action" markdown="1">
281
+ #{body.strip}
282
+ </div>
282
283
  BODY
283
284
  end
284
285
 
@@ -298,8 +299,8 @@ module Govspeak
298
299
  end
299
300
 
300
301
  extension("legislative list", /#{NEW_PARAGRAPH_LOOKBEHIND}\$LegislativeList\s*$(.*?)\$EndLegislativeList/m) do |body|
301
- # The surrounding div is neccessary to control flow in `parse_block_html` and
302
- # maintain the same functionality as a previous version of this extension.
302
+ # The surrounding div is neccessary to accurately identify legislative lists
303
+ # in post-processing.
303
304
  <<~BODY
304
305
  {::options ordered_lists_disabled=\"true\" /}
305
306
  <div class="legislative-list-wrapper" markdown="1">#{body}</div>
@@ -53,17 +53,111 @@ module Kramdown
53
53
  def parse_block_html
54
54
  return false if CUSTOM_INLINE_ELEMENTS.include?(@src[1].downcase)
55
55
 
56
+ super
57
+ end
58
+
59
+ # We override the parse_list method with a modified version where ordered lists are
60
+ # disabled (for use with legislative lists). The majority of the method body is copied
61
+ # over (from https://github.com/gettalong/kramdown/blob/REL_2_3_1/lib/kramdown/parser/kramdown/list.rb#L54),
62
+ # only the LIST_START is changed. Previously, we dynamically modified some of the
63
+ # class-scoped variables used in this method; this provides a thread-safe alternative.
64
+ def parse_list
56
65
  return super unless @options[:ordered_lists_disabled]
57
66
 
58
- # Kramdown loads parsers into the instance from `options` which are scoped to
59
- # the class. Because we are changing these options inside an instance, we must
60
- # reconfigure the parser before and after disbaling ordered lists.
61
- Govspeak::KramdownOverrides.with_kramdown_ordered_lists_disabled do
62
- configure_parser
63
- super
67
+ return if @src.check(LIST_START_OL)
68
+
69
+ start_line_number = @src.current_line_number
70
+ type, list_start_re = (@src.check(LIST_START_UL) ? [:ul, LIST_START_UL] : [:ol, LIST_START_OL])
71
+ list = new_block_el(type, nil, nil, location: start_line_number)
72
+
73
+ item = nil
74
+ content_re, lazy_re, indent_re = nil
75
+ eob_found = false
76
+ nested_list_found = false
77
+ last_is_blank = false
78
+ until @src.eos?
79
+ start_line_number = @src.current_line_number
80
+ if last_is_blank && @src.check(HR_START)
81
+ break
82
+ elsif @src.scan(EOB_MARKER)
83
+ eob_found = true
84
+ break
85
+ elsif @src.scan(list_start_re)
86
+ list.options[:first_list_marker] ||= @src[1].strip
87
+ item = Element.new(:li, nil, nil, location: start_line_number)
88
+ item.value, indentation, content_re, lazy_re, indent_re =
89
+ parse_first_list_line(@src[1].length, @src[2])
90
+ list.children << item
91
+
92
+ item.value.sub!(self.class::LIST_ITEM_IAL) do
93
+ parse_attribute_list(::Regexp.last_match(1), item.options[:ial] ||= {})
94
+ ""
95
+ end
96
+
97
+ list_start_re = fetch_pattern(type, indentation)
98
+ nested_list_found = (item.value =~ LIST_START_UL)
99
+ last_is_blank = false
100
+ item.value = [item.value]
101
+ elsif (result = @src.scan(content_re)) || (!last_is_blank && (result = @src.scan(lazy_re)))
102
+ result.sub!(/^(\t+)/) { " " * 4 * ::Regexp.last_match(1).length }
103
+ indentation_found = result.sub!(indent_re, "")
104
+ if !nested_list_found && indentation_found && result =~ LIST_START_UL
105
+ item.value << +""
106
+ nested_list_found = true
107
+ elsif nested_list_found && !indentation_found && result =~ LIST_START_UL
108
+ result = " " * (indentation + 4) << result
109
+ end
110
+ item.value.last << result
111
+ last_is_blank = false
112
+ elsif (result = @src.scan(BLANK_LINE))
113
+ nested_list_found = true
114
+ last_is_blank = true
115
+ item.value.last << result
116
+ else
117
+ break
118
+ end
64
119
  end
65
120
 
66
- configure_parser
121
+ @tree.children << list
122
+
123
+ last = nil
124
+ list.children.each do |it|
125
+ temp = Element.new(:temp, nil, nil, location: it.options[:location])
126
+
127
+ env = save_env
128
+ location = it.options[:location]
129
+ it.value.each do |val|
130
+ @src = ::Kramdown::Utils::StringScanner.new(val, location)
131
+ parse_blocks(temp)
132
+ location = @src.current_line_number
133
+ end
134
+ restore_env(env)
135
+
136
+ it.children = temp.children
137
+ it.value = nil
138
+
139
+ it_children = it.children
140
+ next if it_children.empty?
141
+
142
+ # Handle the case where an EOB marker is inserted by a block IAL for the first paragraph
143
+ it_children.delete_at(1) if it_children.first.type == :p &&
144
+ it_children.length >= 2 && it_children[1].type == :eob && it_children.first.options[:ial]
145
+
146
+ if it_children.first.type == :p &&
147
+ (it_children.length < 2 || it_children[1].type != :blank ||
148
+ (it == list.children.last && it_children.length == 2 && !eob_found)) &&
149
+ (list.children.last != it || list.children.size == 1 ||
150
+ list.children[0..-2].any? { |cit| !cit.children.first || cit.children.first.type != :p || cit.children.first.options[:transparent] })
151
+ it_children.first.children.first.value << "\n" if it_children.size > 1 && it_children[1].type != :blank
152
+ it_children.first.options[:transparent] = true
153
+ end
154
+
155
+ last = (it_children.last.type == :blank ? it_children.pop : nil)
156
+ end
157
+
158
+ @tree.children << last if !last.nil? && !eob_found
159
+
160
+ true
67
161
  end
68
162
  end
69
163
  end
@@ -425,6 +425,48 @@ Teston
425
425
  assert_text_output "Click here to start the tool"
426
426
  end
427
427
 
428
+ test_given_govspeak "
429
+ $CTA Click here to start the program $CTA
430
+
431
+ Here is some text" do
432
+ assert_html_output %(
433
+ <div class="call-to-action">
434
+ <p>Click here to start the program</p>
435
+ </div>
436
+
437
+ <p>Here is some text</p>)
438
+ end
439
+
440
+ test_given_govspeak "
441
+ Some text
442
+
443
+ $CTA Click there to start the program $CTA
444
+
445
+ Here is some text" do
446
+ assert_html_output %(
447
+ <p>Some text</p>
448
+ <div class="call-to-action">
449
+ <p>Click there to start the program</p>
450
+ </div>
451
+
452
+ <p>Here is some text</p>)
453
+ end
454
+
455
+ test_given_govspeak "
456
+ Some text
457
+
458
+ $CTAClick anywhere to start the program$CTA
459
+
460
+ Here is some text" do
461
+ assert_html_output %(
462
+ <p>Some text</p>
463
+ <div class="call-to-action">
464
+ <p>Click anywhere to start the program</p>
465
+ </div>
466
+
467
+ <p>Here is some text</p>)
468
+ end
469
+
428
470
  test_given_govspeak "
429
471
  Here is some text\n
430
472
 
@@ -453,7 +495,6 @@ Teston
453
495
  $CTA" do
454
496
  assert_html_output %(
455
497
  <div class="call-to-action">
456
-
457
498
  <p>This is a test:</p>
458
499
 
459
500
  <ol class="steps">
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: govspeak
3
3
  version: !ruby/object:Gem::Version
4
- version: 8.3.1
4
+ version: 8.3.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - GOV.UK Dev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-10-18 00:00:00.000000000 Z
11
+ date: 2024-01-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: actionview
@@ -190,14 +190,14 @@ dependencies:
190
190
  requirements:
191
191
  - - '='
192
192
  - !ruby/object:Gem::Version
193
- version: 4.12.0
193
+ version: 4.13.0
194
194
  type: :development
195
195
  prerelease: false
196
196
  version_requirements: !ruby/object:Gem::Requirement
197
197
  requirements:
198
198
  - - '='
199
199
  - !ruby/object:Gem::Version
200
- version: 4.12.0
200
+ version: 4.13.0
201
201
  - !ruby/object:Gem::Dependency
202
202
  name: simplecov
203
203
  requirement: !ruby/object:Gem::Requirement
@@ -235,7 +235,6 @@ files:
235
235
  - lib/govspeak/header_extractor.rb
236
236
  - lib/govspeak/html_sanitizer.rb
237
237
  - lib/govspeak/html_validator.rb
238
- - lib/govspeak/kramdown_overrides.rb
239
238
  - lib/govspeak/link_extractor.rb
240
239
  - lib/govspeak/post_processor.rb
241
240
  - lib/govspeak/presenters/attachment_image_presenter.rb
@@ -327,7 +326,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
327
326
  - !ruby/object:Gem::Version
328
327
  version: '0'
329
328
  requirements: []
330
- rubygems_version: 3.4.21
329
+ rubygems_version: 3.5.5
331
330
  signing_key:
332
331
  specification_version: 4
333
332
  summary: Markup language for single domain
@@ -1,38 +0,0 @@
1
- module Govspeak
2
- module KramdownOverrides
3
- # This depends on two internal parts of Kramdown.
4
- # 1. Parser registry (kramdown/parser/kramdown.rb#define_parser)
5
- # 2. Kramdown list regexes (kramdown/parser/kramdown/list.rb)
6
- # Updating the Kramdown gem therefore also means updating this file to to
7
- # match Kramdown's internals.
8
-
9
- def self.with_kramdown_ordered_lists_disabled
10
- original_list_start = list_start
11
- redefine_kramdown_const(:LIST_START, list_start_ul)
12
- list_parser = kramdown_parsers.delete(:list)
13
- Kramdown::Parser::Kramdown.define_parser(:list, list_start_ul)
14
-
15
- yield
16
- ensure
17
- redefine_kramdown_const(:LIST_START, original_list_start)
18
- kramdown_parsers[:list] = list_parser
19
- end
20
-
21
- def self.list_start
22
- Kramdown::Parser::Kramdown::LIST_START
23
- end
24
-
25
- def self.list_start_ul
26
- Kramdown::Parser::Kramdown::LIST_START_UL
27
- end
28
-
29
- def self.kramdown_parsers
30
- Kramdown::Parser::Kramdown.class_variable_get("@@parsers")
31
- end
32
-
33
- def self.redefine_kramdown_const(const, value)
34
- Kramdown::Parser::Kramdown.send(:remove_const, const)
35
- Kramdown::Parser::Kramdown.send(:const_set, const, value)
36
- end
37
- end
38
- end