swedbank-pay-design-guide-jekyll-theme 1.6.1.pre.PullRequest0137.pre.0064 → 1.9.0

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,141 @@
1
+ # frozen_string_literal: false
2
+
3
+ require_relative 'sidebar_page'
4
+
5
+ module SwedbankPay
6
+ # The builder of HTML for the Sidebar
7
+ class SidebarHTMLBuilder
8
+ def initialize(tree)
9
+ @tree = tree
10
+ end
11
+
12
+ def build(current_page)
13
+ raise ArgumentError, 'current_page cannot be nil' if current_page.nil?
14
+ raise ArgumentError, "#{current_page.class} is not a #{SidebarPage}" unless current_page.is_a? SidebarPage
15
+
16
+ build_markup(@tree, current_page)
17
+ end
18
+
19
+ private
20
+
21
+ def build_markup(pages, current_page)
22
+ return '' if pages.empty?
23
+
24
+ current_path = current_path(current_page)
25
+ markup = ''
26
+
27
+ pages.each do |page|
28
+ next if page.ignore?
29
+
30
+ sub_items_markup = sub_items_markup(page, current_path)
31
+ markup << item_markup(page, current_path, page.level, sub_items_markup)
32
+ end
33
+
34
+ markup
35
+ end
36
+
37
+ def current_path(current_page)
38
+ if current_page.nil?
39
+ Jekyll.logger.warn(' Sidebar: Nil current_page')
40
+ return ''
41
+ end
42
+
43
+ return current_page if current_page.is_a? String
44
+ return current_page.path if current_page.respond_to?(:path)
45
+
46
+ Jekyll.logger.warn(" Sidebar: #{current_page.class} ('#{current_page}') does not respond to :path.")
47
+
48
+ ''
49
+ end
50
+
51
+ def item_markup(page, current_path, level, sub_items_markup)
52
+ title_markup = title_markup(page, level)
53
+ item_class = item_class(page, current_path, level)
54
+ group_heading_class = group_heading_class(level)
55
+
56
+ "<li class=\"#{item_class}\">
57
+ <div class=\"#{group_heading_class}\">
58
+ <i class=\"material-icons\">arrow_right</i>
59
+ #{title_markup}
60
+ </div>
61
+ #{sub_items_markup}
62
+ </li>"
63
+ end
64
+
65
+ def item_class(page, current_path, level)
66
+ active = active?(page, current_path, level)
67
+ item_class = group_class(level)
68
+ item_class += ' active' if active
69
+ item_class
70
+ end
71
+
72
+ def group_class(level)
73
+ level.zero? ? 'nav-group' : 'nav-subgroup'
74
+ end
75
+
76
+ def group_heading_class(level)
77
+ group_class = group_class(level)
78
+ "#{group_class}-heading"
79
+ end
80
+
81
+ def title_markup(page, level)
82
+ section_title = section_title(page)
83
+ return "<span>#{section_title}</span>" if level.zero?
84
+
85
+ item_title = item_title(page)
86
+ "<a href=\"#{page.path}\">#{item_title}</a>"
87
+ end
88
+
89
+ def sub_items_markup(page, current_path)
90
+ headers_markup = headers_markup(page, current_path)
91
+ child_markup = build_markup(page.children, current_path)
92
+
93
+ return '' if headers_markup.empty? && child_markup.empty?
94
+
95
+ "<ul class=\"nav-ul\">
96
+ #{headers_markup}
97
+ #{child_markup}
98
+ </ul>"
99
+ end
100
+
101
+ def headers_markup(page, current_path)
102
+ # If there's no page headers, only return a leaf item for the page itself.
103
+ return leaf_markup(page.path, page.title.item, page.level) unless page.headers?
104
+
105
+ # If there's no children, only return the headers as leaf node items.
106
+ return page.headers.map { |h| header_markup(page, h) }.join('') if page.children.empty?
107
+
108
+ headers_markup = page.headers.map { |h| header_markup(page, h) }.join('')
109
+ headers_markup = "<ul class=\"nav-ul\">#{headers_markup}</ul>"
110
+
111
+ item_markup(page, current_path, page.level + 1, headers_markup)
112
+ end
113
+
114
+ def header_markup(page, header)
115
+ hash = header[:hash]
116
+ subtitle = header[:title]
117
+ href = "#{page.path}#{hash}"
118
+ leaf_markup(href, subtitle)
119
+ end
120
+
121
+ def leaf_markup(href, title, level = 0)
122
+ leaf_class = level.positive? ? 'nav-leaf nav-subgroup-leaf' : 'nav-leaf'
123
+ "<li class=\"#{leaf_class}\"><a href=\"#{href}\">#{title}</a></li>"
124
+ end
125
+
126
+ def active?(page, current_path, level)
127
+ level.zero? ? page.active?(current_path) : page.path == current_path
128
+ end
129
+
130
+ def section_title(page)
131
+ return page.title.section unless page.title.section.nil?
132
+ return page.parent.title.to_s unless page.parent.nil? || page.parent.title.nil?
133
+
134
+ ''
135
+ end
136
+
137
+ def item_title(page)
138
+ page.title.item
139
+ end
140
+ end
141
+ end
@@ -0,0 +1,117 @@
1
+ # frozen_string_literal: false
2
+
3
+ require 'jekyll'
4
+ require_relative 'sidebar_path'
5
+ require_relative 'sidebar_page_title'
6
+ require_relative 'sidebar_page_collection'
7
+ require_relative 'sidebar_text_builder'
8
+
9
+ module SwedbankPay
10
+ # Represents a page in the Sidebar
11
+ class SidebarPage
12
+ FIXNUM_MAX = (2**(0.size * 8 - 2) - 1)
13
+
14
+ attr_reader :path, :title, :level, :order, :children, :name
15
+ attr_accessor :headers, :filename, :doc, :sidebar_container, :number, :parent
16
+
17
+ def initialize(page)
18
+ raise ArgumentError, 'Page must be a Jekyll::Page' unless page.is_a? Jekyll::Page
19
+
20
+ sidebar_path = SidebarPath.new(page['url'])
21
+ @path = sidebar_path.to_s
22
+ @parent = sidebar_path.parent
23
+ @level = sidebar_path.level
24
+ @name = sidebar_path.name
25
+ @hide_from_sidebar = page['hide_from_sidebar'].nil? ? false : page['hide_from_sidebar']
26
+ @title = page_title(page)
27
+ @order = menu_order(page)
28
+ @children = SidebarPageCollection.new(self)
29
+ end
30
+
31
+ def active?(current_path)
32
+ return true if @path == current_path
33
+
34
+ @children.each do |child|
35
+ return true if child.active?(current_path)
36
+ end
37
+
38
+ false
39
+ end
40
+
41
+ def ignore?
42
+ return true if @title.nil?
43
+ return true if @hide_from_sidebar
44
+
45
+ false
46
+ end
47
+
48
+ def children=(children)
49
+ @children = SidebarPageCollection.new(self, children)
50
+ end
51
+
52
+ def to_s
53
+ SidebarTextBuilder.new(self).to_s
54
+ end
55
+
56
+ def inspect
57
+ to_s
58
+ end
59
+
60
+ def <=>(other)
61
+ return -1 if other.nil?
62
+
63
+ if @order == FIXNUM_MAX && other.order == FIXNUM_MAX
64
+ return 0 if @title.nil? && other.title.nil?
65
+ return -1 if other.title.nil?
66
+ return 1 if title.nil?
67
+
68
+ return @title <=> other.title
69
+ end
70
+
71
+ @order <=> other.order
72
+ end
73
+
74
+ def save
75
+ Jekyll.logger.debug(" Writing Sidebar: #{filename}")
76
+
77
+ File.open(@filename, 'w') do |file|
78
+ html = @doc.to_html(encoding: 'UTF-8')
79
+ file.write(html)
80
+ end
81
+ end
82
+
83
+ def headers?
84
+ !headers.nil? && headers.any?
85
+ end
86
+
87
+ def coordinate
88
+ return @number.to_s if @parent.nil?
89
+
90
+ "#{@parent.coordinate}.#{@number}"
91
+ end
92
+
93
+ private
94
+
95
+ def page_title(page)
96
+ title = page['title']
97
+ return nil if title.nil?
98
+
99
+ SidebarPageTitle.new(title)
100
+ end
101
+
102
+ def menu_order(page)
103
+ order = page['menu_order']
104
+ return FIXNUM_MAX if order.nil? || order.to_s.empty?
105
+
106
+ order.to_i
107
+ end
108
+
109
+ def eq?(path)
110
+ @path == path
111
+ end
112
+
113
+ def child_of?(path)
114
+ @path.split('/').length > @level && path.start_with?(@path)
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,37 @@
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
+ page.freeze
21
+ @pages.push(page)
22
+ end
23
+ end
24
+
25
+ def count
26
+ return 0 if @pages.empty?
27
+
28
+ count = @pages.length
29
+
30
+ @pages.each do |page|
31
+ count += page.children.count
32
+ end
33
+
34
+ count
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SwedbankPay
4
+ # Represents the title of a SidebarPage
5
+ class SidebarPageTitle
6
+ attr_reader :section, :item
7
+
8
+ def initialize(title)
9
+ @title = title
10
+ parts = title.split('–')
11
+ @section = parts.first.strip
12
+ @item = parts.last.strip
13
+ end
14
+
15
+ def to_s
16
+ @title
17
+ end
18
+
19
+ def inspect
20
+ @title
21
+ end
22
+
23
+ def <=>(other)
24
+ return -1 if other.nil?
25
+
26
+ @title <=> other.to_s
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'sidebar_path'
4
+
5
+ module SwedbankPay
6
+ # The Sidebar renderer
7
+ class SidebarParser
8
+ def initialize(site)
9
+ @site = site
10
+ end
11
+
12
+ def parse(pages)
13
+ destination = @site.config['destination']
14
+
15
+ Dir.glob("#{destination}/**/*.html") do |filename|
16
+ doc = File.open(filename) { |f| Nokogiri::HTML(f) }
17
+ path = SidebarPath.new(filename).to_s
18
+ page = pages[path]
19
+
20
+ raise ArgumentError, "No page found for '#{path}'." if page.nil?
21
+
22
+ page.doc = doc
23
+ page.filename = filename
24
+ page.headers = find_headers(doc)
25
+ page.sidebar_container = find_sidebar_container(filename, doc)
26
+ end
27
+
28
+ pages
29
+ end
30
+
31
+ private
32
+
33
+ def find_headers(doc)
34
+ headers = []
35
+
36
+ doc.xpath('//h2').each do |header|
37
+ next unless header['id']
38
+
39
+ child_markup = header.last_element_child
40
+ header = {
41
+ id: header['id'],
42
+ title: header.content.strip,
43
+ hash: (child_markup['href']).to_s
44
+ }
45
+ headers.push(header)
46
+ end
47
+
48
+ headers
49
+ end
50
+
51
+ def find_sidebar_container(filename, doc)
52
+ sidebar_containers = doc.xpath('//*[@id="dx-sidebar-main-nav-ul"]')
53
+
54
+ unless sidebar_containers.any?
55
+ Jekyll.logger.debug(" Sidebar: No sidebar container found in #{filename}")
56
+ return nil
57
+ end
58
+
59
+ sidebar_containers.first
60
+ end
61
+ end
62
+ 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