swedbank-pay-design-guide-jekyll-theme 1.8 → 1.9.3
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/sidebar.html +1 -2
- data/_includes/title-header.html +32 -0
- data/_layouts/default.html +1 -24
- data/_layouts/front-page.html +17 -17
- data/_plugins/sidebar.rb +2 -1
- data/_sass/breakpoints.scss +5 -0
- data/_sass/card.scss +1 -0
- data/_sass/front-page.scss +93 -58
- data/_sass/swedbank-pay-design-guide-theme.scss +5 -0
- data/_sass/variables.scss +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 +25 -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
@@ -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
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'sidebar_html_builder'
|
4
|
+
|
5
|
+
module SwedbankPay
|
6
|
+
# Renders the Sidebar
|
7
|
+
class SidebarRenderer
|
8
|
+
def initialize(tree)
|
9
|
+
raise ArgumentError, 'pages cannot be nil' if tree.nil?
|
10
|
+
raise ArgumentError, 'pages must be an SidebarTreeBuilder' unless tree.is_a? SidebarTreeBuilder
|
11
|
+
|
12
|
+
@tree = tree
|
13
|
+
@html_builder = SidebarHTMLBuilder.new(@tree)
|
14
|
+
end
|
15
|
+
|
16
|
+
def enrich_jekyll
|
17
|
+
enrich_jekyll_pages(@tree)
|
18
|
+
end
|
19
|
+
|
20
|
+
def render
|
21
|
+
render_pages(@tree)
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def render_pages(pages)
|
27
|
+
return if pages.empty?
|
28
|
+
|
29
|
+
pages.each do |page|
|
30
|
+
sidebar_html = render_sidebar(page)
|
31
|
+
name = page.filename || page.name || page.to_s
|
32
|
+
|
33
|
+
if sidebar_html.nil?
|
34
|
+
Jekyll.logger.warn(" Sidebar: No HTML rendered for #{name}.")
|
35
|
+
next
|
36
|
+
end
|
37
|
+
|
38
|
+
if page.sidebar_container.nil?
|
39
|
+
Jekyll.logger.warn(" Sidebar: No sidebar container found in '#{name}'. #{page.filename}")
|
40
|
+
next
|
41
|
+
end
|
42
|
+
|
43
|
+
page.sidebar_container.inner_html = sidebar_html
|
44
|
+
|
45
|
+
page.save
|
46
|
+
|
47
|
+
render_pages(page.children)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def render_sidebar(page)
|
52
|
+
sidebar_html = nil
|
53
|
+
|
54
|
+
begin
|
55
|
+
sidebar_html = @html_builder.build(page)
|
56
|
+
|
57
|
+
File.open('_site/sidebar.html', 'w') { |f| f.write(sidebar_html) }
|
58
|
+
rescue StandardError => e
|
59
|
+
name = page.filename || page.name || page.to_s
|
60
|
+
Jekyll.logger.error(" Sidebar: Unable to render sidebar for '#{name}'.")
|
61
|
+
Jekyll.logger.debug(" Sidebar: #{e.message}. #{e.backtrace.inspect}")
|
62
|
+
end
|
63
|
+
|
64
|
+
sidebar_html
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: false
|
2
|
+
|
3
|
+
require_relative 'sidebar_page'
|
4
|
+
|
5
|
+
module SwedbankPay
|
6
|
+
# Builds a plain text representation of a Sidebar, suitable for a terminal.
|
7
|
+
class SidebarTextBuilder
|
8
|
+
def initialize(page)
|
9
|
+
raise ArgumentError, 'Page must be a SidebarPage' unless page.is_a? SidebarPage
|
10
|
+
|
11
|
+
@page = page
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_s
|
15
|
+
name = @page.name == '/' ? '/' : "/#{@page.name}"
|
16
|
+
lead_title = @page.title.nil? ? '?' : @page.title.lead
|
17
|
+
main_title = @page.title.nil? ? '?' : @page.title.main
|
18
|
+
s = "#{indent} #{@page.coordinate}. #{name}: #{lead_title} – #{main_title}\n"
|
19
|
+
|
20
|
+
if @page.children?
|
21
|
+
@page.children.each do |child|
|
22
|
+
s << child.to_s
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# Only strip extraneous whitespace at the root page
|
27
|
+
@page.level.zero? ? s.strip : s
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def indent
|
33
|
+
# Return a special character for the first root page
|
34
|
+
return '┍╾' if (@page.number.nil? || @page.number.zero?) && @page.parent.nil?
|
35
|
+
|
36
|
+
increment = @page.level > 1 ? @page.level + 1 : @page.level
|
37
|
+
|
38
|
+
"┝╾#{'─' * increment}"
|
39
|
+
end
|
40
|
+
|
41
|
+
def todo
|
42
|
+
# This 'todo' method exists to circumvent the following RuboCop error:
|
43
|
+
# lib/sidebar_text_builder.rb:39:97: C: Style/AsciiComments: Use only ascii symbols in comments.
|
44
|
+
"TODO: Add logic to find the very last page regardless of level and have indent it with '┕╾─'"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
# frozen_string_literal: false
|
2
|
+
|
3
|
+
require 'jekyll'
|
4
|
+
require 'forwardable'
|
5
|
+
require_relative 'sidebar_page_collection'
|
6
|
+
|
7
|
+
module SwedbankPay
|
8
|
+
# Arranges Sidebar pages into a tree
|
9
|
+
class SidebarTreeBuilder
|
10
|
+
include Enumerable
|
11
|
+
extend Forwardable
|
12
|
+
def_delegators :@tree, :each, :length, :empty?, :<<, :[], :count
|
13
|
+
|
14
|
+
def initialize(pages)
|
15
|
+
raise ArgumentError, 'pages cannot be nil' if pages.nil?
|
16
|
+
raise ArgumentError, 'pages must be a Hash' unless pages.is_a? Hash
|
17
|
+
|
18
|
+
@tree = tree(pages)
|
19
|
+
enrich_jekyll_pages(@tree)
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_s
|
23
|
+
stringify
|
24
|
+
end
|
25
|
+
|
26
|
+
def inspect
|
27
|
+
stringify(inspection: true)
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def stringify(inspection: false)
|
33
|
+
output = "<#{self.class} ##{count}"
|
34
|
+
|
35
|
+
if inspection
|
36
|
+
output << ":\n"
|
37
|
+
@tree.each do |page|
|
38
|
+
output << "#{page}\n"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
output << '>'
|
43
|
+
output
|
44
|
+
end
|
45
|
+
|
46
|
+
def tree(pages)
|
47
|
+
tree = []
|
48
|
+
children_of = {}
|
49
|
+
page_number = 0
|
50
|
+
|
51
|
+
sort_by_path_reversed(pages).each do |_, page|
|
52
|
+
children_of[page.path] = [] if children_of[page.path].nil?
|
53
|
+
page.children = children_of[page.path].sort
|
54
|
+
|
55
|
+
if page.parent.nil?
|
56
|
+
# Root pages are pushed directly into the root of the tree
|
57
|
+
page.number = page_number
|
58
|
+
tree.push(page)
|
59
|
+
page_number += 1
|
60
|
+
else
|
61
|
+
children_of[page.parent] = [] if children_of[page.parent].nil?
|
62
|
+
children_of[page.parent].push(page)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# Sort the root pages
|
67
|
+
tree.sort!
|
68
|
+
|
69
|
+
SidebarPageCollection.new(nil, tree)
|
70
|
+
end
|
71
|
+
|
72
|
+
def sort_by_path_reversed(pages)
|
73
|
+
pages.sort_by { |path, _| path }.reverse
|
74
|
+
end
|
75
|
+
|
76
|
+
def enrich_jekyll_pages(pages)
|
77
|
+
return if pages.empty?
|
78
|
+
|
79
|
+
pages.each do |page|
|
80
|
+
page.enrich_jekyll
|
81
|
+
|
82
|
+
enrich_jekyll_pages(page.children)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|