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