govspeak 8.3.1 → 8.3.2

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: 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