govspeak 8.3.1 → 8.3.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 330ac68b36870075d83d6cae5223e28d12186d7b9435be02df50829f11d8c27e
4
- data.tar.gz: 3d0b8d3e7b1f98d9e3c814f141319a56a8388ac114b308aba7c3945e5661bbe4
3
+ metadata.gz: 5a58c52e5a9797911c326259920750977c19b81068825b6b947728fe6af410de
4
+ data.tar.gz: de9ac98e971c04c0ac4cc6d7e8f1cc987b2a5310ce2efb5bae4aa2b6ec5ccdc0
5
5
  SHA512:
6
- metadata.gz: c23c1e930d96b6c67fcc9a46c3fc2b1e048d3c5cf9f741e55de28b94bb334e56a07108326cf5bc96c140764f860a0532ff38df87dbb9e04355576f93ebe7efad
7
- data.tar.gz: ed762ebf793ee83971ddcf4a5102379b2ad0dea4adea3134c8bd818c9c15d1d03e957b2b433549bc0846525bea1fb3a19c3574eafb1ac46dc1b98f27c59009cb
6
+ metadata.gz: 21b984b959a200d44869aad30b0d4db910feba0985d701b918152df0fb507cc46710ce0ee9c661f32e93686955f6c2aa722abeb2e95a96527cf3122d53742497
7
+ data.tar.gz: b33b3accc379b22a62a3354d041b943fdde26a5a3bc040308008d1eb1ebcd2d63b27d18d12a40a774b30b1052ef6b9741f733c6b9f5e3ab495831c305df233f5
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ ## 8.3.2
2
+
3
+ * Various bug fixes related to legislative list components ([#298](https://github.com/alphagov/govspeak/pull/298))
4
+
1
5
  ## 8.3.1
2
6
 
3
7
  * Bug fixes related to block elements in call to action and legislative list components ([#293](https://github.com/alphagov/govspeak/pull/293))
@@ -1,3 +1,3 @@
1
1
  module Govspeak
2
- VERSION = "8.3.1".freeze
2
+ VERSION = "8.3.2".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"
@@ -298,8 +297,8 @@ module Govspeak
298
297
  end
299
298
 
300
299
  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.
300
+ # The surrounding div is neccessary to accurately identify legislative lists
301
+ # in post-processing.
303
302
  <<~BODY
304
303
  {::options ordered_lists_disabled=\"true\" /}
305
304
  <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
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.2
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: 2023-12-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: actionview
@@ -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.4.22
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