swedbank-pay-design-guide-jekyll-theme 1.7 → 1.9.1
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 +4 -28
- data/_layouts/front-page.html +112 -0
- 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 +24 -196
- data/lib/sidebar_html_builder.rb +136 -0
- data/lib/sidebar_page.rb +164 -0
- data/lib/sidebar_page_collection.rb +37 -0
- data/lib/sidebar_page_title.rb +71 -0
- data/lib/sidebar_parser.rb +82 -0
- data/lib/sidebar_path.rb +62 -0
- data/lib/sidebar_renderer.rb +70 -0
- data/lib/sidebar_text_builder.rb +46 -0
- data/lib/sidebar_tree_builder.rb +73 -0
- metadata +46 -5
- data/_includes/front-page.html +0 -240
@@ -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,71 @@
|
|
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
|
+
return nil if title.nil?
|
20
|
+
|
21
|
+
SidebarPageTitle.new(title, section, sidebar_page)
|
22
|
+
end
|
23
|
+
|
24
|
+
def lead
|
25
|
+
section = find_section(@page)
|
26
|
+
return section unless section.nil?
|
27
|
+
|
28
|
+
@lead
|
29
|
+
end
|
30
|
+
|
31
|
+
def to_s
|
32
|
+
@title
|
33
|
+
end
|
34
|
+
|
35
|
+
def inspect
|
36
|
+
@title
|
37
|
+
end
|
38
|
+
|
39
|
+
def <=>(other)
|
40
|
+
return -1 if other.nil?
|
41
|
+
|
42
|
+
@title <=> other.to_s
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def initialize(title, section, page)
|
48
|
+
raise ArgumentError, 'title cannot be nil' if title.nil?
|
49
|
+
raise ArgumentError, 'title must be a String' unless title.is_a? String
|
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
|
+
@page = page
|
54
|
+
@title = title
|
55
|
+
parts = title.split('–')
|
56
|
+
@section = section
|
57
|
+
@lead = parts.first.strip
|
58
|
+
@main = parts.last.strip
|
59
|
+
end
|
60
|
+
|
61
|
+
def find_section(page)
|
62
|
+
# Return the 'section' front matter if it can be found on the current page.
|
63
|
+
return page.title.section unless page.nil? || page.title.nil? || page.title.section.nil? || page.title.section.empty?
|
64
|
+
|
65
|
+
# Recurse upwards to the root (until there is no parent).
|
66
|
+
return find_section(page.parent) unless page.nil? || page.parent.nil?
|
67
|
+
|
68
|
+
nil
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'jekyll'
|
4
|
+
require_relative 'sidebar_path'
|
5
|
+
|
6
|
+
module SwedbankPay
|
7
|
+
# The Sidebar renderer
|
8
|
+
class SidebarParser
|
9
|
+
def initialize(site)
|
10
|
+
raise ArgumentError, 'Site cannot be nil' if site.nil?
|
11
|
+
raise ArgumentError, 'Site must be a Jekyll::Site' unless site.is_a? Jekyll::Site
|
12
|
+
|
13
|
+
@site = site
|
14
|
+
end
|
15
|
+
|
16
|
+
def parse
|
17
|
+
pages = build_pages_hash
|
18
|
+
|
19
|
+
destination = @site.config['destination']
|
20
|
+
|
21
|
+
Dir.glob("#{destination}/**/*.html") do |filename|
|
22
|
+
doc = File.open(filename) { |f| Nokogiri::HTML(f) }
|
23
|
+
path = SidebarPath.new(filename).to_s
|
24
|
+
page = pages[path]
|
25
|
+
|
26
|
+
if page.nil?
|
27
|
+
Jekyll.logger.debug(" Sidebar: No page found for <#{path}>.")
|
28
|
+
next
|
29
|
+
end
|
30
|
+
|
31
|
+
page.doc = doc
|
32
|
+
page.filename = filename
|
33
|
+
page.headers = find_headers(doc)
|
34
|
+
page.sidebar_container = find_sidebar_container(filename, doc)
|
35
|
+
end
|
36
|
+
|
37
|
+
pages
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def build_pages_hash
|
43
|
+
pages_hash = {}
|
44
|
+
|
45
|
+
@site.pages.each do |jekyll_page|
|
46
|
+
sidebar_page = SidebarPage.new(jekyll_page)
|
47
|
+
pages_hash[sidebar_page.path] = sidebar_page
|
48
|
+
end
|
49
|
+
|
50
|
+
pages_hash
|
51
|
+
end
|
52
|
+
|
53
|
+
def find_headers(doc)
|
54
|
+
headers = []
|
55
|
+
|
56
|
+
doc.xpath('//h2').each do |header|
|
57
|
+
next unless header['id']
|
58
|
+
|
59
|
+
child_markup = header.last_element_child
|
60
|
+
header = {
|
61
|
+
id: header['id'],
|
62
|
+
title: header.content.strip,
|
63
|
+
hash: (child_markup['href']).to_s
|
64
|
+
}
|
65
|
+
headers.push(header)
|
66
|
+
end
|
67
|
+
|
68
|
+
headers
|
69
|
+
end
|
70
|
+
|
71
|
+
def find_sidebar_container(filename, doc)
|
72
|
+
sidebar_containers = doc.xpath('//*[@id="dx-sidebar-main-nav-ul"]')
|
73
|
+
|
74
|
+
unless sidebar_containers.any?
|
75
|
+
Jekyll.logger.debug(" Sidebar: No sidebar container found in #{filename}")
|
76
|
+
return nil
|
77
|
+
end
|
78
|
+
|
79
|
+
sidebar_containers.first
|
80
|
+
end
|
81
|
+
end
|
82
|
+
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,70 @@
|
|
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
|
+
end
|
14
|
+
|
15
|
+
def enrich_jekyll
|
16
|
+
enrich_jekyll_pages(@tree)
|
17
|
+
end
|
18
|
+
|
19
|
+
def render
|
20
|
+
render_pages(@tree)
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def enrich_jekyll_pages(pages)
|
26
|
+
return if pages.empty?
|
27
|
+
|
28
|
+
pages.each do |page|
|
29
|
+
page.enrich_jekyll
|
30
|
+
|
31
|
+
enrich_jekyll_pages(page.children)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def render_pages(pages)
|
36
|
+
return if pages.empty?
|
37
|
+
|
38
|
+
pages.each do |page|
|
39
|
+
sidebar_html = render_page(page)
|
40
|
+
|
41
|
+
next if sidebar_html.nil?
|
42
|
+
next if page.sidebar_container.nil?
|
43
|
+
|
44
|
+
page.sidebar_container.inner_html = sidebar_html
|
45
|
+
|
46
|
+
page.save
|
47
|
+
|
48
|
+
render_pages(page.children)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def render_page(page)
|
53
|
+
sidebar_html = nil
|
54
|
+
|
55
|
+
begin
|
56
|
+
builder = SidebarHTMLBuilder.new(@tree)
|
57
|
+
sidebar_html = builder.build(page)
|
58
|
+
|
59
|
+
File.open('_site/sidebar.html', 'w') { |f| f.write(sidebar_html) }
|
60
|
+
rescue StandardError => e
|
61
|
+
name = page.filename || page.name
|
62
|
+
Jekyll.logger.error(" Sidebar: Unable to render sidebar for '#{name}'.")
|
63
|
+
Jekyll.logger.debug(" Sidebar: #{e.message}. #{e.backtrace.inspect}")
|
64
|
+
return nil
|
65
|
+
end
|
66
|
+
|
67
|
+
sidebar_html
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,46 @@
|
|
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
|
+
title = @page.title.nil? ? '?' : @page.title.main
|
17
|
+
s = "#{indent} #{name}: #{title} (#{@page.coordinate})\n"
|
18
|
+
|
19
|
+
unless @page.children.empty?
|
20
|
+
@page.children.each do |child|
|
21
|
+
s << child.to_s
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# Only strip extraneous whitespace at the root page
|
26
|
+
@page.level.zero? ? s.strip : s
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def indent
|
32
|
+
# Return a special character for the first root page
|
33
|
+
return '┍╾' if (@page.number.nil? || @page.number.zero?) && @page.parent.nil?
|
34
|
+
|
35
|
+
increment = @page.level > 1 ? @page.level + 1 : @page.level
|
36
|
+
|
37
|
+
"┝╾#{'─' * increment}"
|
38
|
+
end
|
39
|
+
|
40
|
+
def todo
|
41
|
+
# This 'todo' method exists to circumvent the following RuboCop error:
|
42
|
+
# lib/sidebar_text_builder.rb:39:97: C: Style/AsciiComments: Use only ascii symbols in comments.
|
43
|
+
"TODO: Add logic to find the very last page regardless of level and have indent it with '┕╾─'"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# frozen_string_literal: false
|
2
|
+
|
3
|
+
require 'forwardable'
|
4
|
+
require_relative 'sidebar_page_collection'
|
5
|
+
|
6
|
+
module SwedbankPay
|
7
|
+
# Arranges Sidebar pages into a tree
|
8
|
+
class SidebarTreeBuilder
|
9
|
+
include Enumerable
|
10
|
+
extend Forwardable
|
11
|
+
def_delegators :@pages, :each, :length, :empty?, :<<, :[], :count
|
12
|
+
|
13
|
+
def initialize(pages)
|
14
|
+
raise ArgumentError, 'Pages must be a Hash' unless pages.is_a? Hash
|
15
|
+
|
16
|
+
@pages = tree(pages)
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_s
|
20
|
+
stringify
|
21
|
+
end
|
22
|
+
|
23
|
+
def inspect
|
24
|
+
stringify(inspection: true)
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def stringify(inspection: false)
|
30
|
+
output = "<#{self.class} ##{count}"
|
31
|
+
|
32
|
+
if inspection
|
33
|
+
output << ":\n"
|
34
|
+
@pages.each do |page|
|
35
|
+
output << "#{page}\n"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
output << '>'
|
40
|
+
output
|
41
|
+
end
|
42
|
+
|
43
|
+
def tree(pages)
|
44
|
+
tree = []
|
45
|
+
children_of = {}
|
46
|
+
page_number = 0
|
47
|
+
|
48
|
+
sort_by_path_reversed(pages).each do |_, page|
|
49
|
+
children_of[page.path] = [] if children_of[page.path].nil?
|
50
|
+
page.children = children_of[page.path].sort
|
51
|
+
|
52
|
+
if page.parent.nil?
|
53
|
+
# Root pages are pushed directly into the root of the tree
|
54
|
+
page.number = page_number
|
55
|
+
tree.push(page)
|
56
|
+
page_number += 1
|
57
|
+
else
|
58
|
+
children_of[page.parent] = [] if children_of[page.parent].nil?
|
59
|
+
children_of[page.parent].push(page)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# Sort the root pages
|
64
|
+
tree.sort!
|
65
|
+
|
66
|
+
SidebarPageCollection.new(nil, tree)
|
67
|
+
end
|
68
|
+
|
69
|
+
def sort_by_path_reversed(pages)
|
70
|
+
pages.sort_by { |path, _| path }.reverse
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|