govuk_publishing_components 5.5.2 → 5.5.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +26 -1
- data/app/assets/stylesheets/govuk_publishing_components/components/_inverse-header.scss +5 -0
- data/app/models/govuk_publishing_components/component_doc_resolver.rb +1 -0
- data/app/views/govuk_publishing_components/components/_related_navigation.html.erb +1 -1
- data/app/views/govuk_publishing_components/components/_step_by_step_nav.html.erb +4 -2
- data/app/views/govuk_publishing_components/components/docs/inverse_header.yml +1 -1
- data/lib/govuk_publishing_components.rb +4 -4
- data/lib/govuk_publishing_components/app_helpers/step_nav.rb +29 -0
- data/lib/govuk_publishing_components/app_helpers/step_nav_helper.rb +91 -0
- data/lib/govuk_publishing_components/presenters/related_navigation_helper.rb +247 -0
- data/lib/govuk_publishing_components/presenters/step_by_step_nav_helper.rb +113 -0
- data/lib/govuk_publishing_components/version.rb +1 -1
- metadata +19 -5
- data/lib/govuk_publishing_components/components/related_navigation_helper.rb +0 -241
- data/lib/govuk_publishing_components/components/step_by_step_nav_helper.rb +0 -107
- data/lib/govuk_publishing_components/step_nav.rb +0 -27
- data/lib/govuk_publishing_components/step_nav_helper.rb +0 -89
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 04c80df6888c6c4100549e5343d78349aef6050112323f2caf4368d3baab6a05
|
4
|
+
data.tar.gz: 17ec1aed143598ea755942bcb5d1f57d45291f51c1c662b8ec39a97234ba7082
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 72eec3cbce81a2300714b390d4321008984f151c477bb84c35e3a1a60fe47a4052554ec958e08369d68f21db0dfa29046e362be73e435988f40e380a432558d7
|
7
|
+
data.tar.gz: a091a509f7e17c818c6e8ac1b3f6edfc826c7bbe3a2b018b0ba576bc070210a6594efd794b376dde4d85c59e308ecf159ac40dbb18625d2532bde8a3cb342552
|
data/README.md
CHANGED
@@ -1,6 +1,10 @@
|
|
1
1
|
# GOV.UK Publishing Components
|
2
2
|
|
3
|
-
|
3
|
+
This gem:
|
4
|
+
|
5
|
+
- Provides shared components for applications
|
6
|
+
- Provides helpers to generate component payloads
|
7
|
+
- Provides an application to preview components
|
4
8
|
|
5
9
|
Components should be added to this gem if they are required in more than one application, otherwise they should be added to that application.
|
6
10
|
|
@@ -15,6 +19,27 @@ Components should be added to this gem if they are required in more than one app
|
|
15
19
|
- [Run the component guide](/docs/run-component-guide.md)
|
16
20
|
- [Move a component from an application to the gem](/docs/moving-components-upstream-into-this-gem.md)
|
17
21
|
|
22
|
+
## Architecture / structure
|
23
|
+
|
24
|
+
![](https://docs.google.com/drawings/d/e/2PACX-1vRj6JM7cQvngDl3Gr_U9G4xga2gsU7Z-d2qHHQcsBdjsW4WaC9_eQdryBJIS69cLkrY7S0fK9BcrPSF/pub?w=960&h=720)
|
25
|
+
|
26
|
+
[Source](https://docs.google.com/drawings/d/1N8-kbyCN_xOvvshN6d2HnQz5i5Bqed2WIatI3Nj9gNQ/edit)
|
27
|
+
|
28
|
+
There are 2 types of helper classes in this app:
|
29
|
+
|
30
|
+
- [AppHelpers](lib/govuk_publishing_components/app_helpers). Are exposed to the applications using this gem. They should be documented using RDoc.
|
31
|
+
- [Component Presenters](lib/govuk_publishing_components/presenters). Anything in these classes is only for use within the components. They should be marked `@private`.
|
32
|
+
|
33
|
+
## Documentation
|
34
|
+
|
35
|
+
[See the rubydoc.info documentation](http://www.rubydoc.info/gems/govuk_publishing_components)
|
36
|
+
|
37
|
+
Run the documentation locally with:
|
38
|
+
|
39
|
+
```
|
40
|
+
bundle exec yard server --reload
|
41
|
+
```
|
42
|
+
|
18
43
|
## Running tests
|
19
44
|
|
20
45
|
The default rake task runs all tests:
|
@@ -1,10 +1,15 @@
|
|
1
1
|
.gem-c-inverse-header {
|
2
2
|
width: 100%;
|
3
3
|
background-color: $govuk-blue;
|
4
|
+
color: $white;
|
4
5
|
margin-bottom: $gutter;
|
5
6
|
padding: $gutter-half;
|
6
7
|
}
|
7
8
|
|
9
|
+
.gem-c-inverse-header a {
|
10
|
+
color: $white;
|
11
|
+
}
|
12
|
+
|
8
13
|
.gem-c-inverse-header--full-width {
|
9
14
|
padding-left: 0;
|
10
15
|
padding-right: 0;
|
@@ -1,4 +1,4 @@
|
|
1
|
-
<% related_nav_helper = RelatedNavigationHelper.new(local_assigns) %>
|
1
|
+
<% related_nav_helper = GovukPublishingComponents::Presenters::RelatedNavigationHelper.new(local_assigns) %>
|
2
2
|
<% related_content = related_nav_helper.related_navigation %>
|
3
3
|
<% if related_content.map(&:values).flatten.any? || related_nav_helper.other.flatten.any? %>
|
4
4
|
<% random = SecureRandom.hex(4) %>
|
@@ -13,6 +13,8 @@
|
|
13
13
|
|
14
14
|
step_count = 0
|
15
15
|
step_number = 0
|
16
|
+
|
17
|
+
step_nav_helper = GovukPublishingComponents::Presenters::StepByStepNavHelper.new
|
16
18
|
%>
|
17
19
|
<% if steps %>
|
18
20
|
<div
|
@@ -26,7 +28,7 @@
|
|
26
28
|
<%
|
27
29
|
step_is_active = step_index + 1 == highlight_step
|
28
30
|
step_count += 1
|
29
|
-
id =
|
31
|
+
id = step_nav_helper.generate_step_nav_id(step[:title])
|
30
32
|
|
31
33
|
logic = false
|
32
34
|
logic = step[:logic] if ["and", "or"].include? step[:logic]
|
@@ -71,7 +73,7 @@
|
|
71
73
|
options[:link_index] = 0
|
72
74
|
%>
|
73
75
|
<% step[:contents].each do |element| %>
|
74
|
-
<%=
|
76
|
+
<%= step_nav_helper.render_step_nav_element(element, options) %>
|
75
77
|
<%
|
76
78
|
if element[:type] == 'list'
|
77
79
|
options[:link_index] += element[:contents].length
|
@@ -1,7 +1,7 @@
|
|
1
1
|
name: Inverse header
|
2
2
|
description: A wrapper to contain header content in white text
|
3
3
|
body: |
|
4
|
-
This component can be passed a block of template code and will wrap it in a blue header. This is as light-touch as possible and doesn't attempt to deal with the margins and paddings of its content
|
4
|
+
This component can be passed a block of template code and will wrap it in a blue header. This is as light-touch as possible and doesn't attempt to deal with the margins and paddings of its content. White text is enforced on content and would need to be overriden where unwanted. Implemented to accomodate topic and list page headings and breadcrumbs but unopinionated about its contents.
|
5
5
|
|
6
6
|
accessibility_criteria: |
|
7
7
|
The component must:
|
@@ -1,10 +1,10 @@
|
|
1
1
|
require "govuk_publishing_components/config"
|
2
2
|
require "govuk_publishing_components/engine"
|
3
|
-
require "govuk_publishing_components/
|
4
|
-
require "govuk_publishing_components/
|
3
|
+
require "govuk_publishing_components/presenters/step_by_step_nav_helper"
|
4
|
+
require "govuk_publishing_components/presenters/related_navigation_helper"
|
5
5
|
|
6
|
-
require "govuk_publishing_components/step_nav"
|
7
|
-
require "govuk_publishing_components/step_nav_helper"
|
6
|
+
require "govuk_publishing_components/app_helpers/step_nav"
|
7
|
+
require "govuk_publishing_components/app_helpers/step_nav_helper"
|
8
8
|
|
9
9
|
module GovukPublishingComponents
|
10
10
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module GovukPublishingComponents
|
2
|
+
module AppHelpers
|
3
|
+
class StepNav
|
4
|
+
def initialize(content_item)
|
5
|
+
@content_item = content_item.deep_symbolize_keys
|
6
|
+
end
|
7
|
+
|
8
|
+
def title
|
9
|
+
content_item[:title]
|
10
|
+
end
|
11
|
+
|
12
|
+
def base_path
|
13
|
+
content_item[:base_path]
|
14
|
+
end
|
15
|
+
|
16
|
+
def content
|
17
|
+
content_item.dig(:details, :step_by_step_nav)
|
18
|
+
end
|
19
|
+
|
20
|
+
def steps
|
21
|
+
content_item.dig(:details, :step_by_step_nav, :steps)
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
attr_reader :content_item
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
module GovukPublishingComponents
|
2
|
+
module AppHelpers
|
3
|
+
class StepNavHelper
|
4
|
+
def initialize(content_store_response, current_path)
|
5
|
+
@content_item = content_store_response.to_h
|
6
|
+
@current_path = current_path
|
7
|
+
end
|
8
|
+
|
9
|
+
def step_navs
|
10
|
+
@step_navs ||= parsed_step_navs.map do |step_nav|
|
11
|
+
StepNav.new(step_nav)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def show_sidebar?
|
16
|
+
show_header? && first_step_nav.steps.present?
|
17
|
+
end
|
18
|
+
|
19
|
+
def show_header?
|
20
|
+
step_navs.count == 1
|
21
|
+
end
|
22
|
+
|
23
|
+
def show_related_links?
|
24
|
+
step_navs.any? && step_navs.count < 5
|
25
|
+
end
|
26
|
+
|
27
|
+
def related_links
|
28
|
+
step_navs.map do |step_nav|
|
29
|
+
{
|
30
|
+
href: step_nav.base_path,
|
31
|
+
text: step_nav.title
|
32
|
+
}
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def sidebar
|
37
|
+
if show_sidebar?
|
38
|
+
@sidebar ||= first_step_nav.content.tap do |sb|
|
39
|
+
configure_for_sidebar(sb)
|
40
|
+
sb.merge!(small: true, heading_level: 3)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def header
|
46
|
+
if show_header?
|
47
|
+
{
|
48
|
+
title: first_step_nav.title,
|
49
|
+
path: first_step_nav.base_path
|
50
|
+
}
|
51
|
+
else
|
52
|
+
{}
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
attr_reader :content_item, :current_path
|
59
|
+
|
60
|
+
def first_step_nav
|
61
|
+
step_navs.first
|
62
|
+
end
|
63
|
+
|
64
|
+
def steps
|
65
|
+
@steps ||= step_nav[:steps]
|
66
|
+
end
|
67
|
+
|
68
|
+
def parsed_step_navs
|
69
|
+
content_item.dig("links", "part_of_step_navs").to_a
|
70
|
+
end
|
71
|
+
|
72
|
+
def configure_for_sidebar(step_nav_content)
|
73
|
+
step_nav_content[:steps].each_with_index do |step, step_index|
|
74
|
+
step[:contents].each do |content|
|
75
|
+
next unless content[:contents]
|
76
|
+
|
77
|
+
content[:contents].each do |link|
|
78
|
+
if link[:href] == current_path
|
79
|
+
link[:active] = true
|
80
|
+
step_nav_content[:show_step] = step_index + 1
|
81
|
+
step_nav_content[:highlight_step] = step_index + 1
|
82
|
+
return step_nav_content
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
step_nav_content
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,247 @@
|
|
1
|
+
module GovukPublishingComponents
|
2
|
+
module Presenters
|
3
|
+
# @private
|
4
|
+
# Only used by the related_navigation component
|
5
|
+
class RelatedNavigationHelper
|
6
|
+
MAX_SECTION_LENGTH = 5
|
7
|
+
DEFINED_SECTIONS = %w(
|
8
|
+
related_guides
|
9
|
+
topics
|
10
|
+
collections
|
11
|
+
policies
|
12
|
+
topical_events
|
13
|
+
world_locations
|
14
|
+
statistical_data_sets
|
15
|
+
).freeze
|
16
|
+
|
17
|
+
def initialize(content_item)
|
18
|
+
@content_item = content_item
|
19
|
+
end
|
20
|
+
|
21
|
+
def related_navigation
|
22
|
+
@related_content ||= [
|
23
|
+
{ "related_items" => related_items },
|
24
|
+
{ "related_guides" => related_guides },
|
25
|
+
{ "collections" => related_collections },
|
26
|
+
{ "topics" => related_topics },
|
27
|
+
{ "policies" => related_policies },
|
28
|
+
{ "topical_events" => related_topical_events },
|
29
|
+
{ "world_locations" => related_world_locations },
|
30
|
+
{ "statistical_data_sets" => related_statistical_data_sets },
|
31
|
+
]
|
32
|
+
|
33
|
+
other = [related_external_links, related_contacts] || []
|
34
|
+
other.each do |sections|
|
35
|
+
sections.each do |section|
|
36
|
+
@related_content.push(
|
37
|
+
section["title"].tr(' ', '_') => section["links"]
|
38
|
+
)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
@related_content
|
43
|
+
end
|
44
|
+
|
45
|
+
def other
|
46
|
+
@other ||= []
|
47
|
+
end
|
48
|
+
|
49
|
+
def construct_section_heading(section_title)
|
50
|
+
unless section_title === "related_items"
|
51
|
+
I18n.t('components.related_navigation.' + section_title, default: section_title.tr('_', ' '))
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def section_css_class(css_class, section_title, link = {})
|
56
|
+
unless DEFINED_SECTIONS.include?(section_title) || link.fetch(:finder, false)
|
57
|
+
css_class += "--other"
|
58
|
+
end
|
59
|
+
css_class
|
60
|
+
end
|
61
|
+
|
62
|
+
def calculate_section_link_limit(links)
|
63
|
+
links.length == MAX_SECTION_LENGTH + 1 ? MAX_SECTION_LENGTH + 1 : MAX_SECTION_LENGTH
|
64
|
+
end
|
65
|
+
|
66
|
+
def remaining_link_count(links)
|
67
|
+
links.length - MAX_SECTION_LENGTH
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
def build_links_for_sidebar(collection, path_key = "base_path", additional_attr = {})
|
73
|
+
collection.map do |link|
|
74
|
+
{
|
75
|
+
path: link[path_key],
|
76
|
+
text: link["title"]
|
77
|
+
}.merge(additional_attr)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def world_location_base_path(title)
|
82
|
+
"/world/#{parameterise(title)}/news"
|
83
|
+
end
|
84
|
+
|
85
|
+
def related_items
|
86
|
+
links = build_links_for_sidebar(quick_links, "url")
|
87
|
+
mainstream_links = related_mainstream_content
|
88
|
+
related_ordered_items = link_group("ordered_related_items")
|
89
|
+
if links.any?
|
90
|
+
links + mainstream_links
|
91
|
+
else
|
92
|
+
build_links_for_sidebar(related_ordered_items) + mainstream_links
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def quick_links
|
97
|
+
@content_item.dig("details", "quick_links").to_a
|
98
|
+
end
|
99
|
+
|
100
|
+
def related_world_locations
|
101
|
+
locations = link_group("world_locations")
|
102
|
+
locations.map! { |link| link.merge("base_path" => world_location_base_path(link["title"])) }
|
103
|
+
build_links_for_sidebar(locations)
|
104
|
+
end
|
105
|
+
|
106
|
+
def related_collections
|
107
|
+
collections = filter_link_type("document_collections", "document_collection")
|
108
|
+
build_links_for_sidebar(collections)
|
109
|
+
end
|
110
|
+
|
111
|
+
def filter_link_type(group, type)
|
112
|
+
links = link_group(group)
|
113
|
+
links.select do |link|
|
114
|
+
link["document_type"] == type
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def related_policies
|
119
|
+
policies = filter_link_type("related_policies", "policy")
|
120
|
+
build_links_for_sidebar(policies)
|
121
|
+
end
|
122
|
+
|
123
|
+
def related_statistical_data_sets
|
124
|
+
statistical_data_sets = filter_link_type("related_statistical_data_sets", "statistical_data_set")
|
125
|
+
build_links_for_sidebar(statistical_data_sets)
|
126
|
+
end
|
127
|
+
|
128
|
+
def related_topics
|
129
|
+
topics = filter_link_type("topics", "topic")
|
130
|
+
links = build_links_for_sidebar(topics)
|
131
|
+
links << related_mainstream_topic << related_mainstream_parent_topic
|
132
|
+
deduplicate_topics_by_title(links.compact)
|
133
|
+
end
|
134
|
+
|
135
|
+
def related_topical_events
|
136
|
+
topical_events = filter_link_type("topical_events", "topical_event")
|
137
|
+
build_links_for_sidebar(topical_events)
|
138
|
+
end
|
139
|
+
|
140
|
+
def related_contacts
|
141
|
+
contacts = filter_link_type("related", "contact")
|
142
|
+
return [] unless contacts.any?
|
143
|
+
[
|
144
|
+
title: "Other contacts",
|
145
|
+
links: build_links_for_sidebar(contacts).map
|
146
|
+
]
|
147
|
+
end
|
148
|
+
|
149
|
+
def related_external_links
|
150
|
+
external_links = @content_item.dig("details", "external_related_links").to_a
|
151
|
+
return [] unless external_links.any?
|
152
|
+
[
|
153
|
+
"title" => "Elsewhere on the web",
|
154
|
+
"links" => build_links_for_sidebar(external_links, "url", rel: 'external')
|
155
|
+
]
|
156
|
+
end
|
157
|
+
|
158
|
+
def related_mainstream_topic
|
159
|
+
return unless tagged_to_same_mainstream_browse_page.any?
|
160
|
+
{ text: parent["title"], path: parent["base_path"] }
|
161
|
+
end
|
162
|
+
|
163
|
+
def related_mainstream_parent_topic
|
164
|
+
return unless parents_tagged_to_same_mainstream_browse_page.any?
|
165
|
+
{ text: grandparent["title"], path: grandparent["base_path"] }
|
166
|
+
end
|
167
|
+
|
168
|
+
def parent
|
169
|
+
link_group("parent").first
|
170
|
+
end
|
171
|
+
|
172
|
+
def grandparent
|
173
|
+
parent.dig("links", "parent", 0)
|
174
|
+
end
|
175
|
+
|
176
|
+
# This method post-processes the topics collated by the helper.
|
177
|
+
# We add mainstream browse page links if they are present, however
|
178
|
+
# if these have the same title as an existing topic we should prefer
|
179
|
+
# the mainstream version and remove the existing topic.
|
180
|
+
# @see spec/related_navigation_helper_spec.rb for test coverage.
|
181
|
+
def deduplicate_topics_by_title(topics)
|
182
|
+
is_dupe = lambda { |a, b| a && a != b && a[:text] == b[:text] }
|
183
|
+
|
184
|
+
topics.delete_if do |t|
|
185
|
+
is_dupe.call(related_mainstream_topic, t) ||
|
186
|
+
is_dupe.call(related_mainstream_parent_topic, t)
|
187
|
+
end
|
188
|
+
|
189
|
+
topics
|
190
|
+
end
|
191
|
+
|
192
|
+
def parameterise(str, sep = "-")
|
193
|
+
parameterised_str = str.gsub(/[^\w\-]+/, sep)
|
194
|
+
unless sep.nil? || sep.empty?
|
195
|
+
re_sep = Regexp.escape(sep)
|
196
|
+
# No more than one of the separator in a row.
|
197
|
+
parameterised_str.gsub!(/#{re_sep}{2,}/, sep)
|
198
|
+
# Remove leading/trailing separator.
|
199
|
+
parameterised_str.gsub!(/^#{re_sep}|#{re_sep}$/, '')
|
200
|
+
end
|
201
|
+
parameterised_str.downcase
|
202
|
+
end
|
203
|
+
|
204
|
+
def tagged_to_same_mainstream_browse_page
|
205
|
+
return [] unless parent
|
206
|
+
@tagged_to_same_mainstream_browse_page ||= related_links.select do |related_item|
|
207
|
+
links = related_item.dig("links", "mainstream_browse_pages") || []
|
208
|
+
content_ids = links.any? ? links.map { |page| page["content_id"] } : []
|
209
|
+
content_ids.include?(parent["content_id"])
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
def parents_tagged_to_same_mainstream_browse_page
|
214
|
+
return [] unless parent && grandparent
|
215
|
+
common_parent_content_ids = tagged_to_same_mainstream_browse_page.map { |item| item["content_id"] }
|
216
|
+
|
217
|
+
@parents_tagged_to_same_mainstream_browse_page ||= related_links.select do |related_item|
|
218
|
+
next if common_parent_content_ids.include?(related_item["content_id"])
|
219
|
+
mainstream_browse_pages = related_item.dig("links", "mainstream_browse_pages") || []
|
220
|
+
parents = mainstream_browse_pages.map { |page| page["links"]["parent"][0] }
|
221
|
+
content_ids = parents.map { |parent| parent["content_id"] }
|
222
|
+
content_ids.include?(grandparent["content_id"])
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
def related_links
|
227
|
+
link_group("ordered_related_items")
|
228
|
+
end
|
229
|
+
|
230
|
+
def related_mainstream_content
|
231
|
+
return [] unless @content_item["document_type"] == "detailed_guide"
|
232
|
+
content = link_group("related_mainstream_content")
|
233
|
+
build_links_for_sidebar(content)
|
234
|
+
end
|
235
|
+
|
236
|
+
def related_guides
|
237
|
+
return [] unless @content_item["document_type"] == "detailed_guide"
|
238
|
+
guides = link_group("related_guides")
|
239
|
+
build_links_for_sidebar(guides)
|
240
|
+
end
|
241
|
+
|
242
|
+
def link_group(type)
|
243
|
+
@content_item.dig("links", type).to_a
|
244
|
+
end
|
245
|
+
end
|
246
|
+
end
|
247
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
module GovukPublishingComponents
|
2
|
+
module Presenters
|
3
|
+
# @private
|
4
|
+
# Only used by the step by step component
|
5
|
+
class StepByStepNavHelper
|
6
|
+
include ActionView::Helpers
|
7
|
+
include ActionView::Context
|
8
|
+
|
9
|
+
def render_step_nav_element(element, options)
|
10
|
+
@options = options
|
11
|
+
@link_index = options[:link_index]
|
12
|
+
|
13
|
+
case element[:type]
|
14
|
+
when "paragraph"
|
15
|
+
paragraph(element[:text])
|
16
|
+
when "heading"
|
17
|
+
heading(element[:text])
|
18
|
+
when "list"
|
19
|
+
list(element)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# id should be lowercase, contain only numbers and letters and replace spaces with dashes
|
24
|
+
def generate_step_nav_id(step_title)
|
25
|
+
step_title.downcase.tr(" ", "-").gsub(/[^a-z0-9\-\s]/i, '')
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def paragraph(text)
|
31
|
+
content_tag(
|
32
|
+
:p,
|
33
|
+
text,
|
34
|
+
class: "gem-c-step-nav__paragraph"
|
35
|
+
)
|
36
|
+
end
|
37
|
+
|
38
|
+
def heading(text)
|
39
|
+
content_tag(
|
40
|
+
"h#{@options[:heading_level] + 1}",
|
41
|
+
text,
|
42
|
+
class: "gem-c-step-nav__heading"
|
43
|
+
)
|
44
|
+
end
|
45
|
+
|
46
|
+
def list(element)
|
47
|
+
content_tag(
|
48
|
+
get_list_element(element[:style]),
|
49
|
+
class: "gem-c-step-nav__links #{get_list_style(element[:style])}",
|
50
|
+
data: {
|
51
|
+
length: element[:contents].length
|
52
|
+
}
|
53
|
+
) do
|
54
|
+
element[:contents].collect { |contents|
|
55
|
+
concat(
|
56
|
+
content_tag(
|
57
|
+
:li,
|
58
|
+
class: "gem-c-step-nav__link js-list-item #{link_active(contents[:active])}"
|
59
|
+
) do
|
60
|
+
create_list_item_content(contents)
|
61
|
+
end
|
62
|
+
)
|
63
|
+
}
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def create_list_item_content(link)
|
68
|
+
if link[:href]
|
69
|
+
@link_index += 1
|
70
|
+
href = link_href(link[:active], link[:href])
|
71
|
+
text = "#{link_text(link[:active], link[:text])} #{create_context(link[:context])}".html_safe
|
72
|
+
|
73
|
+
link_to(
|
74
|
+
href,
|
75
|
+
rel: ("external" if href.start_with?('http')),
|
76
|
+
data: {
|
77
|
+
position: "#{@options[:step_index] + 1}.#{@link_index}"
|
78
|
+
},
|
79
|
+
class: "gem-c-step-nav__link-item js-link"
|
80
|
+
) do
|
81
|
+
text
|
82
|
+
end
|
83
|
+
else
|
84
|
+
link[:text]
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def create_context(context)
|
89
|
+
content_tag(:span, context, class: "gem-c-step-nav__context") if context
|
90
|
+
end
|
91
|
+
|
92
|
+
def get_list_style(style)
|
93
|
+
"gem-c-step-nav__links--choice" if style == "choice"
|
94
|
+
end
|
95
|
+
|
96
|
+
def get_list_element(style)
|
97
|
+
style == "choice" ? "ul" : "ol"
|
98
|
+
end
|
99
|
+
|
100
|
+
def link_href(active, href)
|
101
|
+
active ? "#content" : href
|
102
|
+
end
|
103
|
+
|
104
|
+
def link_text(active, text)
|
105
|
+
active ? content_tag(:span, "You are currently viewing: ", class: "visuallyhidden") + text : text
|
106
|
+
end
|
107
|
+
|
108
|
+
def link_active(active)
|
109
|
+
"gem-c-step-nav__link--active" if active
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: govuk_publishing_components
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.5.
|
4
|
+
version: 5.5.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- GOV.UK Dev
|
@@ -262,6 +262,20 @@ dependencies:
|
|
262
262
|
- - ">="
|
263
263
|
- !ruby/object:Gem::Version
|
264
264
|
version: '0'
|
265
|
+
- !ruby/object:Gem::Dependency
|
266
|
+
name: yard
|
267
|
+
requirement: !ruby/object:Gem::Requirement
|
268
|
+
requirements:
|
269
|
+
- - ">="
|
270
|
+
- !ruby/object:Gem::Version
|
271
|
+
version: '0'
|
272
|
+
type: :development
|
273
|
+
prerelease: false
|
274
|
+
version_requirements: !ruby/object:Gem::Requirement
|
275
|
+
requirements:
|
276
|
+
- - ">="
|
277
|
+
- !ruby/object:Gem::Version
|
278
|
+
version: '0'
|
265
279
|
description: A gem to document components in GOV.UK frontend applications
|
266
280
|
email:
|
267
281
|
- govuk-dev@digital.cabinet-office.gov.uk
|
@@ -356,13 +370,13 @@ files:
|
|
356
370
|
- lib/generators/govuk_publishing_components/templates/_component.scss
|
357
371
|
- lib/generators/govuk_publishing_components/templates/component.yml.erb
|
358
372
|
- lib/govuk_publishing_components.rb
|
359
|
-
- lib/govuk_publishing_components/
|
360
|
-
- lib/govuk_publishing_components/
|
373
|
+
- lib/govuk_publishing_components/app_helpers/step_nav.rb
|
374
|
+
- lib/govuk_publishing_components/app_helpers/step_nav_helper.rb
|
361
375
|
- lib/govuk_publishing_components/config.rb
|
362
376
|
- lib/govuk_publishing_components/engine.rb
|
363
377
|
- lib/govuk_publishing_components/minitest/component_guide_test.rb
|
364
|
-
- lib/govuk_publishing_components/
|
365
|
-
- lib/govuk_publishing_components/
|
378
|
+
- lib/govuk_publishing_components/presenters/related_navigation_helper.rb
|
379
|
+
- lib/govuk_publishing_components/presenters/step_by_step_nav_helper.rb
|
366
380
|
- lib/govuk_publishing_components/version.rb
|
367
381
|
- lib/tasks/govuk_publishing_components_tasks.rake
|
368
382
|
homepage: https://github.com/alphagov/govuk_publishing_components
|
@@ -1,241 +0,0 @@
|
|
1
|
-
class RelatedNavigationHelper
|
2
|
-
MAX_SECTION_LENGTH = 5
|
3
|
-
DEFINED_SECTIONS = %w(
|
4
|
-
related_guides
|
5
|
-
topics
|
6
|
-
collections
|
7
|
-
policies
|
8
|
-
topical_events
|
9
|
-
world_locations
|
10
|
-
statistical_data_sets
|
11
|
-
).freeze
|
12
|
-
|
13
|
-
def initialize(content_item)
|
14
|
-
@content_item = content_item
|
15
|
-
end
|
16
|
-
|
17
|
-
def related_navigation
|
18
|
-
@related_content ||= [
|
19
|
-
{ "related_items" => related_items },
|
20
|
-
{ "related_guides" => related_guides },
|
21
|
-
{ "collections" => related_collections },
|
22
|
-
{ "topics" => related_topics },
|
23
|
-
{ "policies" => related_policies },
|
24
|
-
{ "topical_events" => related_topical_events },
|
25
|
-
{ "world_locations" => related_world_locations },
|
26
|
-
{ "statistical_data_sets" => related_statistical_data_sets },
|
27
|
-
]
|
28
|
-
|
29
|
-
other = [related_external_links, related_contacts] || []
|
30
|
-
other.each do |sections|
|
31
|
-
sections.each do |section|
|
32
|
-
@related_content.push(
|
33
|
-
section["title"].tr(' ', '_') => section["links"]
|
34
|
-
)
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
@related_content
|
39
|
-
end
|
40
|
-
|
41
|
-
def other
|
42
|
-
@other ||= []
|
43
|
-
end
|
44
|
-
|
45
|
-
def construct_section_heading(section_title)
|
46
|
-
unless section_title === "related_items"
|
47
|
-
I18n.t('components.related_navigation.' + section_title, default: section_title.tr('_', ' '))
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
def section_css_class(css_class, section_title, link = {})
|
52
|
-
unless DEFINED_SECTIONS.include?(section_title) || link.fetch(:finder, false)
|
53
|
-
css_class += "--other"
|
54
|
-
end
|
55
|
-
css_class
|
56
|
-
end
|
57
|
-
|
58
|
-
def calculate_section_link_limit(links)
|
59
|
-
links.length == MAX_SECTION_LENGTH + 1 ? MAX_SECTION_LENGTH + 1 : MAX_SECTION_LENGTH
|
60
|
-
end
|
61
|
-
|
62
|
-
def remaining_link_count(links)
|
63
|
-
links.length - MAX_SECTION_LENGTH
|
64
|
-
end
|
65
|
-
|
66
|
-
private
|
67
|
-
|
68
|
-
def build_links_for_sidebar(collection, path_key = "base_path", additional_attr = {})
|
69
|
-
collection.map do |link|
|
70
|
-
{
|
71
|
-
path: link[path_key],
|
72
|
-
text: link["title"]
|
73
|
-
}.merge(additional_attr)
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
def world_location_base_path(title)
|
78
|
-
"/world/#{parameterise(title)}/news"
|
79
|
-
end
|
80
|
-
|
81
|
-
def related_items
|
82
|
-
links = build_links_for_sidebar(quick_links, "url")
|
83
|
-
mainstream_links = related_mainstream_content
|
84
|
-
related_ordered_items = link_group("ordered_related_items")
|
85
|
-
if links.any?
|
86
|
-
links + mainstream_links
|
87
|
-
else
|
88
|
-
build_links_for_sidebar(related_ordered_items) + mainstream_links
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
def quick_links
|
93
|
-
@content_item.dig("details", "quick_links").to_a
|
94
|
-
end
|
95
|
-
|
96
|
-
def related_world_locations
|
97
|
-
locations = link_group("world_locations")
|
98
|
-
locations.map! { |link| link.merge("base_path" => world_location_base_path(link["title"])) }
|
99
|
-
build_links_for_sidebar(locations)
|
100
|
-
end
|
101
|
-
|
102
|
-
def related_collections
|
103
|
-
collections = filter_link_type("document_collections", "document_collection")
|
104
|
-
build_links_for_sidebar(collections)
|
105
|
-
end
|
106
|
-
|
107
|
-
def filter_link_type(group, type)
|
108
|
-
links = link_group(group)
|
109
|
-
links.select do |link|
|
110
|
-
link["document_type"] == type
|
111
|
-
end
|
112
|
-
end
|
113
|
-
|
114
|
-
def related_policies
|
115
|
-
policies = filter_link_type("related_policies", "policy")
|
116
|
-
build_links_for_sidebar(policies)
|
117
|
-
end
|
118
|
-
|
119
|
-
def related_statistical_data_sets
|
120
|
-
statistical_data_sets = filter_link_type("related_statistical_data_sets", "statistical_data_set")
|
121
|
-
build_links_for_sidebar(statistical_data_sets)
|
122
|
-
end
|
123
|
-
|
124
|
-
def related_topics
|
125
|
-
topics = filter_link_type("topics", "topic")
|
126
|
-
links = build_links_for_sidebar(topics)
|
127
|
-
links << related_mainstream_topic << related_mainstream_parent_topic
|
128
|
-
deduplicate_topics_by_title(links.compact)
|
129
|
-
end
|
130
|
-
|
131
|
-
def related_topical_events
|
132
|
-
topical_events = filter_link_type("topical_events", "topical_event")
|
133
|
-
build_links_for_sidebar(topical_events)
|
134
|
-
end
|
135
|
-
|
136
|
-
def related_contacts
|
137
|
-
contacts = filter_link_type("related", "contact")
|
138
|
-
return [] unless contacts.any?
|
139
|
-
[
|
140
|
-
title: "Other contacts",
|
141
|
-
links: build_links_for_sidebar(contacts).map
|
142
|
-
]
|
143
|
-
end
|
144
|
-
|
145
|
-
def related_external_links
|
146
|
-
external_links = @content_item.dig("details", "external_related_links").to_a
|
147
|
-
return [] unless external_links.any?
|
148
|
-
[
|
149
|
-
"title" => "Elsewhere on the web",
|
150
|
-
"links" => build_links_for_sidebar(external_links, "url", rel: 'external')
|
151
|
-
]
|
152
|
-
end
|
153
|
-
|
154
|
-
def related_mainstream_topic
|
155
|
-
return unless tagged_to_same_mainstream_browse_page.any?
|
156
|
-
{ text: parent["title"], path: parent["base_path"] }
|
157
|
-
end
|
158
|
-
|
159
|
-
def related_mainstream_parent_topic
|
160
|
-
return unless parents_tagged_to_same_mainstream_browse_page.any?
|
161
|
-
{ text: grandparent["title"], path: grandparent["base_path"] }
|
162
|
-
end
|
163
|
-
|
164
|
-
def parent
|
165
|
-
link_group("parent").first
|
166
|
-
end
|
167
|
-
|
168
|
-
def grandparent
|
169
|
-
parent.dig("links", "parent", 0)
|
170
|
-
end
|
171
|
-
|
172
|
-
# This method post-processes the topics collated by the helper.
|
173
|
-
# We add mainstream browse page links if they are present, however
|
174
|
-
# if these have the same title as an existing topic we should prefer
|
175
|
-
# the mainstream version and remove the existing topic.
|
176
|
-
# @see spec/related_navigation_helper_spec.rb for test coverage.
|
177
|
-
def deduplicate_topics_by_title(topics)
|
178
|
-
is_dupe = lambda { |a, b| a && a != b && a[:text] == b[:text] }
|
179
|
-
|
180
|
-
topics.delete_if do |t|
|
181
|
-
is_dupe.call(related_mainstream_topic, t) ||
|
182
|
-
is_dupe.call(related_mainstream_parent_topic, t)
|
183
|
-
end
|
184
|
-
|
185
|
-
topics
|
186
|
-
end
|
187
|
-
|
188
|
-
def parameterise(str, sep = "-")
|
189
|
-
parameterised_str = str.gsub(/[^\w\-]+/, sep)
|
190
|
-
unless sep.nil? || sep.empty?
|
191
|
-
re_sep = Regexp.escape(sep)
|
192
|
-
# No more than one of the separator in a row.
|
193
|
-
parameterised_str.gsub!(/#{re_sep}{2,}/, sep)
|
194
|
-
# Remove leading/trailing separator.
|
195
|
-
parameterised_str.gsub!(/^#{re_sep}|#{re_sep}$/, '')
|
196
|
-
end
|
197
|
-
parameterised_str.downcase
|
198
|
-
end
|
199
|
-
|
200
|
-
def tagged_to_same_mainstream_browse_page
|
201
|
-
return [] unless parent
|
202
|
-
@tagged_to_same_mainstream_browse_page ||= related_links.select do |related_item|
|
203
|
-
links = related_item.dig("links", "mainstream_browse_pages") || []
|
204
|
-
content_ids = links.any? ? links.map { |page| page["content_id"] } : []
|
205
|
-
content_ids.include?(parent["content_id"])
|
206
|
-
end
|
207
|
-
end
|
208
|
-
|
209
|
-
def parents_tagged_to_same_mainstream_browse_page
|
210
|
-
return [] unless parent && grandparent
|
211
|
-
common_parent_content_ids = tagged_to_same_mainstream_browse_page.map { |item| item["content_id"] }
|
212
|
-
|
213
|
-
@parents_tagged_to_same_mainstream_browse_page ||= related_links.select do |related_item|
|
214
|
-
next if common_parent_content_ids.include?(related_item["content_id"])
|
215
|
-
mainstream_browse_pages = related_item.dig("links", "mainstream_browse_pages") || []
|
216
|
-
parents = mainstream_browse_pages.map { |page| page["links"]["parent"][0] }
|
217
|
-
content_ids = parents.map { |parent| parent["content_id"] }
|
218
|
-
content_ids.include?(grandparent["content_id"])
|
219
|
-
end
|
220
|
-
end
|
221
|
-
|
222
|
-
def related_links
|
223
|
-
link_group("ordered_related_items")
|
224
|
-
end
|
225
|
-
|
226
|
-
def related_mainstream_content
|
227
|
-
return [] unless @content_item["document_type"] == "detailed_guide"
|
228
|
-
content = link_group("related_mainstream_content")
|
229
|
-
build_links_for_sidebar(content)
|
230
|
-
end
|
231
|
-
|
232
|
-
def related_guides
|
233
|
-
return [] unless @content_item["document_type"] == "detailed_guide"
|
234
|
-
guides = link_group("related_guides")
|
235
|
-
build_links_for_sidebar(guides)
|
236
|
-
end
|
237
|
-
|
238
|
-
def link_group(type)
|
239
|
-
@content_item.dig("links", type).to_a
|
240
|
-
end
|
241
|
-
end
|
@@ -1,107 +0,0 @@
|
|
1
|
-
class StepNavHelper
|
2
|
-
include ActionView::Helpers
|
3
|
-
include ActionView::Context
|
4
|
-
|
5
|
-
def render_step_nav_element(element, options)
|
6
|
-
@options = options
|
7
|
-
@link_index = options[:link_index]
|
8
|
-
|
9
|
-
case element[:type]
|
10
|
-
when "paragraph"
|
11
|
-
paragraph(element[:text])
|
12
|
-
when "heading"
|
13
|
-
heading(element[:text])
|
14
|
-
when "list"
|
15
|
-
list(element)
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
# id should be lowercase, contain only numbers and letters and replace spaces with dashes
|
20
|
-
def generate_step_nav_id(step_title)
|
21
|
-
step_title.downcase.tr(" ", "-").gsub(/[^a-z0-9\-\s]/i, '')
|
22
|
-
end
|
23
|
-
|
24
|
-
private
|
25
|
-
|
26
|
-
def paragraph(text)
|
27
|
-
content_tag(
|
28
|
-
:p,
|
29
|
-
text,
|
30
|
-
class: "gem-c-step-nav__paragraph"
|
31
|
-
)
|
32
|
-
end
|
33
|
-
|
34
|
-
def heading(text)
|
35
|
-
content_tag(
|
36
|
-
"h#{@options[:heading_level] + 1}",
|
37
|
-
text,
|
38
|
-
class: "gem-c-step-nav__heading"
|
39
|
-
)
|
40
|
-
end
|
41
|
-
|
42
|
-
def list(element)
|
43
|
-
content_tag(
|
44
|
-
get_list_element(element[:style]),
|
45
|
-
class: "gem-c-step-nav__links #{get_list_style(element[:style])}",
|
46
|
-
data: {
|
47
|
-
length: element[:contents].length
|
48
|
-
}
|
49
|
-
) do
|
50
|
-
element[:contents].collect { |contents|
|
51
|
-
concat(
|
52
|
-
content_tag(
|
53
|
-
:li,
|
54
|
-
class: "gem-c-step-nav__link js-list-item #{link_active(contents[:active])}"
|
55
|
-
) do
|
56
|
-
create_list_item_content(contents)
|
57
|
-
end
|
58
|
-
)
|
59
|
-
}
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
def create_list_item_content(link)
|
64
|
-
if link[:href]
|
65
|
-
@link_index += 1
|
66
|
-
href = link_href(link[:active], link[:href])
|
67
|
-
text = "#{link_text(link[:active], link[:text])} #{create_context(link[:context])}".html_safe
|
68
|
-
|
69
|
-
link_to(
|
70
|
-
href,
|
71
|
-
rel: ("external" if href.start_with?('http')),
|
72
|
-
data: {
|
73
|
-
position: "#{@options[:step_index] + 1}.#{@link_index}"
|
74
|
-
},
|
75
|
-
class: "gem-c-step-nav__link-item js-link"
|
76
|
-
) do
|
77
|
-
text
|
78
|
-
end
|
79
|
-
else
|
80
|
-
link[:text]
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
def create_context(context)
|
85
|
-
content_tag(:span, context, class: "gem-c-step-nav__context") if context
|
86
|
-
end
|
87
|
-
|
88
|
-
def get_list_style(style)
|
89
|
-
"gem-c-step-nav__links--choice" if style == "choice"
|
90
|
-
end
|
91
|
-
|
92
|
-
def get_list_element(style)
|
93
|
-
style == "choice" ? "ul" : "ol"
|
94
|
-
end
|
95
|
-
|
96
|
-
def link_href(active, href)
|
97
|
-
active ? "#content" : href
|
98
|
-
end
|
99
|
-
|
100
|
-
def link_text(active, text)
|
101
|
-
active ? content_tag(:span, "You are currently viewing: ", class: "visuallyhidden") + text : text
|
102
|
-
end
|
103
|
-
|
104
|
-
def link_active(active)
|
105
|
-
"gem-c-step-nav__link--active" if active
|
106
|
-
end
|
107
|
-
end
|
@@ -1,27 +0,0 @@
|
|
1
|
-
module GovukPublishingComponents
|
2
|
-
class StepNav
|
3
|
-
def initialize(content_item)
|
4
|
-
@content_item = content_item.deep_symbolize_keys
|
5
|
-
end
|
6
|
-
|
7
|
-
def title
|
8
|
-
content_item[:title]
|
9
|
-
end
|
10
|
-
|
11
|
-
def base_path
|
12
|
-
content_item[:base_path]
|
13
|
-
end
|
14
|
-
|
15
|
-
def content
|
16
|
-
content_item.dig(:details, :step_by_step_nav)
|
17
|
-
end
|
18
|
-
|
19
|
-
def steps
|
20
|
-
content_item.dig(:details, :step_by_step_nav, :steps)
|
21
|
-
end
|
22
|
-
|
23
|
-
private
|
24
|
-
|
25
|
-
attr_reader :content_item
|
26
|
-
end
|
27
|
-
end
|
@@ -1,89 +0,0 @@
|
|
1
|
-
module GovukPublishingComponents
|
2
|
-
class StepNavHelper
|
3
|
-
def initialize(content_store_response, current_path)
|
4
|
-
@content_item = content_store_response.to_h
|
5
|
-
@current_path = current_path
|
6
|
-
end
|
7
|
-
|
8
|
-
def step_navs
|
9
|
-
@step_navs ||= parsed_step_navs.map do |step_nav|
|
10
|
-
StepNav.new(step_nav)
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
def show_sidebar?
|
15
|
-
show_header? && first_step_nav.steps.present?
|
16
|
-
end
|
17
|
-
|
18
|
-
def show_header?
|
19
|
-
step_navs.count == 1
|
20
|
-
end
|
21
|
-
|
22
|
-
def show_related_links?
|
23
|
-
step_navs.any? && step_navs.count < 5
|
24
|
-
end
|
25
|
-
|
26
|
-
def related_links
|
27
|
-
step_navs.map do |step_nav|
|
28
|
-
{
|
29
|
-
href: step_nav.base_path,
|
30
|
-
text: step_nav.title
|
31
|
-
}
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
def sidebar
|
36
|
-
if show_sidebar?
|
37
|
-
@sidebar ||= first_step_nav.content.tap do |sb|
|
38
|
-
configure_for_sidebar(sb)
|
39
|
-
sb.merge!(small: true, heading_level: 3)
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
def header
|
45
|
-
if show_header?
|
46
|
-
{
|
47
|
-
title: first_step_nav.title,
|
48
|
-
path: first_step_nav.base_path
|
49
|
-
}
|
50
|
-
else
|
51
|
-
{}
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
private
|
56
|
-
|
57
|
-
attr_reader :content_item, :current_path
|
58
|
-
|
59
|
-
def first_step_nav
|
60
|
-
step_navs.first
|
61
|
-
end
|
62
|
-
|
63
|
-
def steps
|
64
|
-
@steps ||= step_nav[:steps]
|
65
|
-
end
|
66
|
-
|
67
|
-
def parsed_step_navs
|
68
|
-
content_item.dig("links", "part_of_step_navs").to_a
|
69
|
-
end
|
70
|
-
|
71
|
-
def configure_for_sidebar(step_nav_content)
|
72
|
-
step_nav_content[:steps].each_with_index do |step, step_index|
|
73
|
-
step[:contents].each do |content|
|
74
|
-
next unless content[:contents]
|
75
|
-
|
76
|
-
content[:contents].each do |link|
|
77
|
-
if link[:href] == current_path
|
78
|
-
link[:active] = true
|
79
|
-
step_nav_content[:show_step] = step_index + 1
|
80
|
-
step_nav_content[:highlight_step] = step_index + 1
|
81
|
-
return step_nav_content
|
82
|
-
end
|
83
|
-
end
|
84
|
-
end
|
85
|
-
end
|
86
|
-
step_nav_content
|
87
|
-
end
|
88
|
-
end
|
89
|
-
end
|