swedbank-pay-design-guide-jekyll-theme 1.8.1 → 1.9.4
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 +4 -4
- data/_includes/iterator.html +2 -2
- data/_includes/title-header.html +32 -0
- data/_layouts/default.html +13 -32
- data/_layouts/front-page.html +24 -21
- data/_plugins/sidebar.rb +2 -1
- data/_sass/breakpoints.scss +5 -0
- data/_sass/card.scss +1 -0
- data/_sass/front-page.scss +108 -71
- data/_sass/sidebar.scss +33 -3
- data/_sass/swedbank-pay-design-guide-theme.scss +5 -0
- data/_sass/title-header.scss +3 -0
- data/_sass/variables.scss +1 -1
- data/assets/css/pygments-autumn.css +1 -1
- data/lib/gem_version.rb +1 -1
- data/lib/safe_merge.rb +28 -0
- data/lib/sanitized_filename.rb +12 -0
- data/lib/sidebar.rb +23 -196
- data/lib/sidebar_html_builder.rb +154 -0
- data/lib/sidebar_page.rb +181 -0
- data/lib/sidebar_page_collection.rb +36 -0
- data/lib/sidebar_page_title.rb +94 -0
- data/lib/sidebar_parser.rb +95 -0
- data/lib/sidebar_path.rb +62 -0
- data/lib/sidebar_renderer.rb +67 -0
- data/lib/sidebar_text_builder.rb +47 -0
- data/lib/sidebar_tree_builder.rb +86 -0
- metadata +31 -4
data/lib/sidebar_page.rb
ADDED
@@ -0,0 +1,181 @@
|
|
1
|
+
# frozen_string_literal: false
|
2
|
+
|
3
|
+
require 'jekyll'
|
4
|
+
require 'nokogiri'
|
5
|
+
require_relative 'sidebar_path'
|
6
|
+
require_relative 'sidebar_page_title'
|
7
|
+
require_relative 'sidebar_page_collection'
|
8
|
+
require_relative 'sidebar_text_builder'
|
9
|
+
|
10
|
+
module SwedbankPay
|
11
|
+
# Represents a jekyll_page in the Sidebar
|
12
|
+
class SidebarPage
|
13
|
+
FIXNUM_MAX = (2**(0.size * 8 - 2) - 1)
|
14
|
+
|
15
|
+
attr_reader :path, :title, :level, :order, :children, :name, :filename, :doc
|
16
|
+
attr_accessor :headers, :sidebar_container, :number, :parent
|
17
|
+
|
18
|
+
def initialize(jekyll_page)
|
19
|
+
raise ArgumentError, 'jekyll_page cannot be nil' if jekyll_page.nil?
|
20
|
+
raise ArgumentError, 'jekyll_page must be a Jekyll::Page' unless jekyll_page.is_a? Jekyll::Page
|
21
|
+
|
22
|
+
@filename = jekyll_page.destination('')
|
23
|
+
@jekyll_page = jekyll_page
|
24
|
+
sidebar_path = SidebarPath.new(jekyll_page['url'])
|
25
|
+
@path = sidebar_path.to_s
|
26
|
+
@parent = sidebar_path.parent
|
27
|
+
@level = sidebar_path.level
|
28
|
+
@name = sidebar_path.name
|
29
|
+
@hide_from_sidebar = jekyll_page['hide_from_sidebar'].nil? ? false : jekyll_page['hide_from_sidebar']
|
30
|
+
@title = SidebarPageTitle.parse(jekyll_page, self)
|
31
|
+
@order = menu_order(jekyll_page)
|
32
|
+
@children = SidebarPageCollection.new(self)
|
33
|
+
end
|
34
|
+
|
35
|
+
def active?(current, is_leaf: false)
|
36
|
+
current_path = find_path(current)
|
37
|
+
|
38
|
+
return true if @path == current_path
|
39
|
+
|
40
|
+
# If we're on a leaf node item, such as when rendering the first header
|
41
|
+
# item of a sub-group, its children's active state must be disregarded.
|
42
|
+
unless is_leaf
|
43
|
+
@children.each do |child|
|
44
|
+
return true if child.active?(current_path, is_leaf: is_leaf)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
false
|
49
|
+
end
|
50
|
+
|
51
|
+
def hidden?
|
52
|
+
return true if @title.nil?
|
53
|
+
return true if @hide_from_sidebar
|
54
|
+
|
55
|
+
false
|
56
|
+
end
|
57
|
+
|
58
|
+
def hidden_for?(other_page)
|
59
|
+
# The current page should be hidden for the other page unless the
|
60
|
+
# other page is also hidden.
|
61
|
+
hidden = hidden?
|
62
|
+
|
63
|
+
if other_page.nil? || !other_page.is_a?(SidebarPage)
|
64
|
+
Jekyll.logger.debug(" Sidebar: Other page '#{other_page}' is nil or not a SidebarPage")
|
65
|
+
return hidden
|
66
|
+
end
|
67
|
+
|
68
|
+
# If the other page is hidden, the current page should not be hidden
|
69
|
+
# from it.
|
70
|
+
return false if other_page.hidden? && in_same_section_as?(other_page)
|
71
|
+
|
72
|
+
hidden
|
73
|
+
end
|
74
|
+
|
75
|
+
def children=(children)
|
76
|
+
@children = SidebarPageCollection.new(self, children)
|
77
|
+
end
|
78
|
+
|
79
|
+
def to_s
|
80
|
+
SidebarTextBuilder.new(self).to_s
|
81
|
+
end
|
82
|
+
|
83
|
+
def inspect
|
84
|
+
to_s
|
85
|
+
end
|
86
|
+
|
87
|
+
def <=>(other)
|
88
|
+
return -1 if other.nil?
|
89
|
+
|
90
|
+
if @order == FIXNUM_MAX && other.order == FIXNUM_MAX
|
91
|
+
return 0 if @title.nil? && other.title.nil?
|
92
|
+
return -1 if other.title.nil?
|
93
|
+
return 1 if title.nil?
|
94
|
+
|
95
|
+
return @title <=> other.title
|
96
|
+
end
|
97
|
+
|
98
|
+
@order <=> other.order
|
99
|
+
end
|
100
|
+
|
101
|
+
def enrich_jekyll
|
102
|
+
if @title.nil?
|
103
|
+
Jekyll.logger.debug(" Sidebar: No title for #{@name}")
|
104
|
+
return
|
105
|
+
end
|
106
|
+
|
107
|
+
Jekyll.logger.debug(" Sidebar: <#{@path}>.lead_title('#{@title.lead}').main_title('#{@title.main}')")
|
108
|
+
|
109
|
+
@jekyll_page.data['lead_title'] = @title.lead
|
110
|
+
@jekyll_page.data['main_title'] = @title.main
|
111
|
+
end
|
112
|
+
|
113
|
+
def save
|
114
|
+
Jekyll.logger.debug(" Writing Sidebar: #{filename}")
|
115
|
+
|
116
|
+
File.open(@filename, 'w') do |file|
|
117
|
+
html = @doc.to_html(encoding: 'UTF-8')
|
118
|
+
file.write(html)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def children?
|
123
|
+
!children.nil? && children.any?
|
124
|
+
end
|
125
|
+
|
126
|
+
def headers?
|
127
|
+
!headers.nil? && headers.any?
|
128
|
+
end
|
129
|
+
|
130
|
+
def coordinate
|
131
|
+
return @number.to_s if @parent.nil?
|
132
|
+
return @number.to_s unless @parent.respond_to? :coordinate
|
133
|
+
|
134
|
+
"#{@parent.coordinate}.#{@number}"
|
135
|
+
end
|
136
|
+
|
137
|
+
def load
|
138
|
+
@doc = File.open(@filename) { |f| Nokogiri::HTML(f) }
|
139
|
+
@doc
|
140
|
+
end
|
141
|
+
|
142
|
+
private
|
143
|
+
|
144
|
+
def menu_order(jekyll_page)
|
145
|
+
order = jekyll_page['menu_order']
|
146
|
+
return FIXNUM_MAX if order.nil? || order.to_s.empty?
|
147
|
+
|
148
|
+
order.to_i
|
149
|
+
end
|
150
|
+
|
151
|
+
def eq?(path)
|
152
|
+
@path == path
|
153
|
+
end
|
154
|
+
|
155
|
+
def child_of?(path)
|
156
|
+
@path.split('/').length > @level && path.start_with?(@path)
|
157
|
+
end
|
158
|
+
|
159
|
+
def find_path(current)
|
160
|
+
if current.nil?
|
161
|
+
Jekyll.logger.warn(' Sidebar: Nil current_page')
|
162
|
+
return ''
|
163
|
+
end
|
164
|
+
|
165
|
+
return current if current.is_a? String
|
166
|
+
return current.path if current.respond_to?(:path)
|
167
|
+
|
168
|
+
Jekyll.logger.warn(" Sidebar: #{current.class} ('#{current}') does not respond to :path.")
|
169
|
+
|
170
|
+
''
|
171
|
+
end
|
172
|
+
|
173
|
+
def in_same_section_as?(other_page)
|
174
|
+
# If this or the other page is the root index page, just ignore the
|
175
|
+
# hidden state completely
|
176
|
+
return false if other_page.path == '/' || @path == '/'
|
177
|
+
|
178
|
+
other_page.path.start_with?(@path) || @path.start_with?(other_page.path)
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: false
|
2
|
+
|
3
|
+
require 'forwardable'
|
4
|
+
|
5
|
+
module SwedbankPay
|
6
|
+
# Arranges Sidebar pages into a tree
|
7
|
+
class SidebarPageCollection
|
8
|
+
include Enumerable
|
9
|
+
extend Forwardable
|
10
|
+
def_delegators :@pages, :each, :length, :empty?, :[]
|
11
|
+
|
12
|
+
def initialize(parent, pages = [])
|
13
|
+
raise ArgumentError, 'Pages must be an array' unless pages.is_a? Array
|
14
|
+
|
15
|
+
@pages = []
|
16
|
+
|
17
|
+
pages.each_with_index do |page, index|
|
18
|
+
page.number = index
|
19
|
+
page.parent = parent
|
20
|
+
@pages.push(page)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def count
|
25
|
+
return 0 if @pages.empty?
|
26
|
+
|
27
|
+
count = @pages.length
|
28
|
+
|
29
|
+
@pages.each do |page|
|
30
|
+
count += page.children.count
|
31
|
+
end
|
32
|
+
|
33
|
+
count
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'jekyll'
|
4
|
+
require_relative 'sidebar_page'
|
5
|
+
|
6
|
+
module SwedbankPay
|
7
|
+
# Represents the title of a SidebarPage
|
8
|
+
class SidebarPageTitle
|
9
|
+
attr_reader :main, :section
|
10
|
+
|
11
|
+
def self.parse(jekyll_page, sidebar_page)
|
12
|
+
raise ArgumentError, 'jekyll_page cannot be nil' if jekyll_page.nil?
|
13
|
+
raise ArgumentError, 'jekyll_page must be a Jekyll::Page' unless jekyll_page.is_a? Jekyll::Page
|
14
|
+
raise ArgumentError, 'sidebar_page cannot be nil' if sidebar_page.nil?
|
15
|
+
raise ArgumentError, 'sidebar_page must be a SidebarPage' unless sidebar_page.is_a? SidebarPage
|
16
|
+
|
17
|
+
title = jekyll_page['title']
|
18
|
+
section = jekyll_page['section']
|
19
|
+
|
20
|
+
return nil if title.nil? && section.nil?
|
21
|
+
|
22
|
+
SidebarPageTitle.new(title, section, sidebar_page)
|
23
|
+
end
|
24
|
+
|
25
|
+
def lead
|
26
|
+
section = find_section(@page)
|
27
|
+
return section unless section.nil?
|
28
|
+
|
29
|
+
@lead
|
30
|
+
end
|
31
|
+
|
32
|
+
def to_s
|
33
|
+
@title
|
34
|
+
end
|
35
|
+
|
36
|
+
def inspect
|
37
|
+
@title
|
38
|
+
end
|
39
|
+
|
40
|
+
def <=>(other)
|
41
|
+
return -1 if other.nil?
|
42
|
+
|
43
|
+
@title <=> other.to_s
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def initialize(title, section, page)
|
49
|
+
raise ArgumentError, 'Both title and section cannot be nil' if title.nil? && section.nil?
|
50
|
+
raise ArgumentError, 'page cannot be nil' if page.nil?
|
51
|
+
raise ArgumentError, 'page must be a SidebarPage' unless page.is_a? SidebarPage
|
52
|
+
|
53
|
+
if title.nil?
|
54
|
+
raise ArgumentError, 'section must be a String' unless section.is_a? String
|
55
|
+
|
56
|
+
title = section
|
57
|
+
elsif section.nil?
|
58
|
+
raise ArgumentError, 'title must be a String' unless title.is_a? String
|
59
|
+
end
|
60
|
+
|
61
|
+
@page = page
|
62
|
+
@title = title
|
63
|
+
parts = title.split('–')
|
64
|
+
@section = section
|
65
|
+
@lead = parts.first.strip
|
66
|
+
@main = parts.last.strip
|
67
|
+
end
|
68
|
+
|
69
|
+
def find_section(page)
|
70
|
+
raise ArgumentError, 'page cannot be nil' if page.nil?
|
71
|
+
raise ArgumentError, 'page must be a SidebarPage' unless page.is_a? SidebarPage
|
72
|
+
|
73
|
+
# Return the 'section' front matter if it can be found on the current page.
|
74
|
+
section = section_from_front_matter(page)
|
75
|
+
|
76
|
+
return section unless section.nil?
|
77
|
+
|
78
|
+
# Recurse upwards to the root (until there is no parent).
|
79
|
+
section_from_parent(page)
|
80
|
+
end
|
81
|
+
|
82
|
+
def section_from_front_matter(page)
|
83
|
+
return nil if page.nil? || page.title.nil? || page.title.section.nil? || page.title.section.empty?
|
84
|
+
|
85
|
+
page.title.section
|
86
|
+
end
|
87
|
+
|
88
|
+
def section_from_parent(page)
|
89
|
+
return nil if page.nil? || page.parent.nil?
|
90
|
+
|
91
|
+
find_section(page.parent) unless page.nil? || page.parent.nil?
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'jekyll'
|
4
|
+
require 'jekyll-redirect-from'
|
5
|
+
require_relative 'sidebar_path'
|
6
|
+
|
7
|
+
module SwedbankPay
|
8
|
+
# The Sidebar renderer
|
9
|
+
class SidebarParser
|
10
|
+
attr_reader :pages
|
11
|
+
|
12
|
+
def initialize(site)
|
13
|
+
raise ArgumentError, 'Site cannot be nil' if site.nil?
|
14
|
+
raise ArgumentError, 'Site must be a Jekyll::Site' unless site.is_a? Jekyll::Site
|
15
|
+
|
16
|
+
@pages = convert(site.pages)
|
17
|
+
end
|
18
|
+
|
19
|
+
def parse(tree)
|
20
|
+
raise ArgumentError, 'tree cannot be nil' if tree.nil?
|
21
|
+
raise ArgumentError, 'tree must be a SidebarTreeBuilder' unless tree.is_a? SidebarTreeBuilder
|
22
|
+
|
23
|
+
parse_html(tree)
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def convert(pages)
|
29
|
+
pages_hash = {}
|
30
|
+
|
31
|
+
pages.each do |jekyll_page|
|
32
|
+
if skippable? jekyll_page
|
33
|
+
Jekyll.logger.debug(" Sidebar: Skipping <#{jekyll_page['url']}>")
|
34
|
+
next
|
35
|
+
end
|
36
|
+
|
37
|
+
sidebar_page = SidebarPage.new(jekyll_page)
|
38
|
+
pages_hash[sidebar_page.path] = sidebar_page
|
39
|
+
end
|
40
|
+
|
41
|
+
pages_hash
|
42
|
+
end
|
43
|
+
|
44
|
+
def parse_html(pages)
|
45
|
+
return if pages.nil? || pages.empty?
|
46
|
+
|
47
|
+
pages.each do |page|
|
48
|
+
page.load
|
49
|
+
page.headers = find_headers(page)
|
50
|
+
page.sidebar_container = find_sidebar_container(page)
|
51
|
+
page.freeze
|
52
|
+
|
53
|
+
parse_html(page.children)
|
54
|
+
end
|
55
|
+
|
56
|
+
pages
|
57
|
+
end
|
58
|
+
|
59
|
+
def find_headers(page)
|
60
|
+
headers = []
|
61
|
+
|
62
|
+
page.doc.xpath('//h2').each do |header|
|
63
|
+
next unless header['id']
|
64
|
+
|
65
|
+
child_markup = header.last_element_child
|
66
|
+
header = {
|
67
|
+
id: header['id'],
|
68
|
+
title: header.content.strip,
|
69
|
+
hash: (child_markup['href']).to_s
|
70
|
+
}
|
71
|
+
headers.push(header)
|
72
|
+
end
|
73
|
+
|
74
|
+
headers
|
75
|
+
end
|
76
|
+
|
77
|
+
def find_sidebar_container(page)
|
78
|
+
sidebar_containers = page.doc.xpath('//*[@id="dx-sidebar-main-nav-ul"]')
|
79
|
+
|
80
|
+
if sidebar_containers.empty?
|
81
|
+
Jekyll.logger.error(" Sidebar: No sidebar container found in <#{page.filename}>!")
|
82
|
+
return nil
|
83
|
+
end
|
84
|
+
|
85
|
+
sidebar_containers.first
|
86
|
+
end
|
87
|
+
|
88
|
+
def skippable?(jekyll_page)
|
89
|
+
return true if jekyll_page.is_a? JekyllRedirectFrom::RedirectPage
|
90
|
+
return true if jekyll_page.is_a? JekyllRedirectFrom::PageWithoutAFile
|
91
|
+
|
92
|
+
false
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
data/lib/sidebar_path.rb
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'sanitized_filename'
|
4
|
+
require_relative 'sidebar_page_title'
|
5
|
+
|
6
|
+
module SwedbankPay
|
7
|
+
# Represents a page in the Sidebar
|
8
|
+
class SidebarPath
|
9
|
+
attr_reader :parent, :level, :name
|
10
|
+
|
11
|
+
def initialize(path)
|
12
|
+
@segments = segment(path)
|
13
|
+
@path = normalized(path)
|
14
|
+
@name = construct_name
|
15
|
+
@parent = find_parent
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_s
|
19
|
+
@path
|
20
|
+
end
|
21
|
+
|
22
|
+
def inspect
|
23
|
+
to_s
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def segment(path)
|
29
|
+
segments = path.sanitized.split('/').reject(&:empty?)
|
30
|
+
@level = segments.length.zero? ? 0 : segments.length - 1
|
31
|
+
segments
|
32
|
+
end
|
33
|
+
|
34
|
+
def normalized(path)
|
35
|
+
return '/' if @segments.empty?
|
36
|
+
|
37
|
+
joined = "/#{@segments.join('/')}"
|
38
|
+
|
39
|
+
# Directory paths should end with '/'.
|
40
|
+
directory?(path) ? "#{joined}/" : joined
|
41
|
+
end
|
42
|
+
|
43
|
+
def directory?(path)
|
44
|
+
path.end_with?('/') || path.end_with?('/index.html')
|
45
|
+
end
|
46
|
+
|
47
|
+
def construct_name
|
48
|
+
return '/' if @path == '/'
|
49
|
+
|
50
|
+
@segments.last
|
51
|
+
end
|
52
|
+
|
53
|
+
def find_parent
|
54
|
+
# If there's no or only one path segment, this is a root page
|
55
|
+
return nil if @segments.empty? || (@segments.length == 1)
|
56
|
+
|
57
|
+
# Return the path minus the last segment as the parent path
|
58
|
+
last = @path.sub(%r{(/#{@segments.last}/?)$}, '')
|
59
|
+
"#{last}/"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|