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.
@@ -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
@@ -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