middleman-toc 0.0.2 → 0.0.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/Gemfile.lock +1 -1
- data/lib/middleman_toc.rb +22 -163
- data/lib/middleman_toc/builder.rb +28 -0
- data/lib/middleman_toc/extension.rb +7 -1
- data/lib/middleman_toc/helpers.rb +4 -8
- data/lib/middleman_toc/node.rb +45 -0
- data/lib/middleman_toc/renderer.rb +38 -0
- data/lib/middleman_toc/tag.rb +24 -0
- data/lib/middleman_toc/title.rb +25 -0
- data/lib/middleman_toc/toc.rb +51 -0
- data/lib/middleman_toc/validator.rb +50 -0
- data/lib/middleman_toc/version.rb +2 -2
- data/middleman-toc.gemspec +19 -0
- data/spec/spec_helper.rb +2 -2
- metadata +11 -8
- data/lib/middleman_toc/link.rb +0 -7
- data/lib/middleman_toc/page.rb +0 -95
- data/lib/middleman_toc/paths.rb +0 -31
- data/spec/toc_spec.rb +0 -47
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9878fe65c1884c356621be680c01b083115a5c36
|
4
|
+
data.tar.gz: bc806aa5c08d4f29cfbc8ab318e4935e388bcb29
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3ce628078149e15537da2e668693c394a919f0b8bfb42332ca27af6a219422c3779b0b17e37feb67820c42ca25bedf9edda07e8e2ede676515295ee6e4da8c99
|
7
|
+
data.tar.gz: b50206b8fa190abaafe5f93d7e3962b2837fbd4824461b4d8b3f64effa4a33fa8cac062df2fd8c55fda674a38fa9a539f175f951c4611e732b2b5fe0d8283632
|
data/Gemfile.lock
CHANGED
data/lib/middleman_toc.rb
CHANGED
@@ -1,182 +1,41 @@
|
|
1
1
|
require 'middleman'
|
2
|
+
require 'yaml'
|
2
3
|
require 'middleman_toc/extension'
|
3
|
-
require '
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
class Paths < Struct.new(:sitemap)
|
13
|
-
def prev(path)
|
14
|
-
path = paths[index(path) - 1]
|
15
|
-
"#{path.sub('.', '')}.html" if path
|
16
|
-
end
|
17
|
-
|
18
|
-
def next(path)
|
19
|
-
path = paths[index(path) + 1]
|
20
|
-
"#{path.sub('.', '')}.html" if path
|
21
|
-
end
|
22
|
-
|
23
|
-
def select(dir)
|
24
|
-
paths.select { |path| path =~ %r(#{dir}/) }.reject { |path| path =~ %r(#{dir}/.+/) }
|
25
|
-
end
|
26
|
-
|
27
|
-
def paths
|
28
|
-
@paths ||= begin
|
29
|
-
paths = sitemap.resources.map(&:path)
|
30
|
-
paths = paths.select { |path| path =~ /.html$/ }
|
31
|
-
paths = paths.map { |path| "./#{path.sub(/.html$/, '')}" }
|
32
|
-
paths = paths + paths.map { |path| ::File.dirname(path) } - ['.']
|
33
|
-
paths.sort.unshift('./index').uniq
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
def index(path)
|
38
|
-
paths.index("./#{path.sub('.html', '')}")
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
class Page
|
43
|
-
extend Forwardable
|
44
|
-
include Indent
|
45
|
-
|
46
|
-
def_delegators :@children, :empty?
|
47
|
-
|
48
|
-
attr_reader :level, :path, :page, :children, :active
|
49
|
-
|
50
|
-
def initialize(level, path, page)
|
51
|
-
@level = level
|
52
|
-
@path = path
|
53
|
-
@page = page
|
54
|
-
@children = []
|
55
|
-
end
|
56
|
-
|
57
|
-
def <<(child)
|
58
|
-
children << child
|
59
|
-
end
|
60
|
-
|
61
|
-
def activate(active)
|
62
|
-
children.each { |child| child.activate(active) }
|
63
|
-
@active = active == path
|
64
|
-
end
|
65
|
-
|
66
|
-
def render
|
67
|
-
if level == 1
|
68
|
-
render_children
|
69
|
-
else
|
70
|
-
html = title
|
71
|
-
html = link("/#{path}.html", html) if File.file?(filename)
|
72
|
-
html = [html, render_children].join("\n") unless children.empty?
|
73
|
-
item(html)
|
4
|
+
require 'middleman_toc/toc'
|
5
|
+
require 'middleman_toc/validator'
|
6
|
+
|
7
|
+
module MiddlemanToc
|
8
|
+
class << self
|
9
|
+
def instance(sitemap)
|
10
|
+
@instance ||= Toc.new(pages(sitemap)).tap do |toc|
|
11
|
+
Validator.new(toc.pages, toc.root).validate!
|
74
12
|
end
|
75
13
|
end
|
76
14
|
|
77
|
-
def
|
78
|
-
|
79
|
-
end
|
80
|
-
|
81
|
-
def link(href, content)
|
82
|
-
%(<a href="#{href}">#{content}</a>)
|
83
|
-
end
|
84
|
-
|
85
|
-
def item(content)
|
86
|
-
%(<li#{%( class="#{classes}") unless classes.empty?}>#{content}</li>)
|
87
|
-
end
|
88
|
-
|
89
|
-
def classes
|
90
|
-
classes = []
|
91
|
-
classes << 'active' if active?
|
92
|
-
classes << 'directory' if directory?
|
93
|
-
classes << 'expanded' if active? && !children.empty? || expanded?
|
94
|
-
classes.join(' ')
|
95
|
-
end
|
96
|
-
|
97
|
-
def directory?
|
98
|
-
!children.empty?
|
99
|
-
end
|
100
|
-
|
101
|
-
def active?
|
102
|
-
@active
|
15
|
+
def toc(sitemap, path)
|
16
|
+
rendering { instance(sitemap).toc(path) } # .tap { |html| puts html }
|
103
17
|
end
|
104
18
|
|
105
|
-
def
|
106
|
-
|
19
|
+
def prev_page(sitemap, path)
|
20
|
+
rendering { instance(sitemap).prev_page(path) }
|
107
21
|
end
|
108
22
|
|
109
|
-
def
|
110
|
-
|
111
|
-
title || path_title
|
23
|
+
def next_page(sitemap, path)
|
24
|
+
rendering { instance(sitemap).next_page(path) }
|
112
25
|
end
|
113
26
|
|
114
|
-
def
|
115
|
-
|
116
|
-
page.
|
117
|
-
else
|
118
|
-
html = page.render(layout: false, no_images: true)
|
119
|
-
matches = html.match(/<h.+>(.*?)<\/h1>/)
|
120
|
-
matches[1] if matches
|
27
|
+
def pages(sitemap)
|
28
|
+
sitemap.resources.inject({}) do |pages, page|
|
29
|
+
pages.merge(page.path.gsub(%r((^|\/)[\d]+\-), '').sub('.html', '\1') => page)
|
121
30
|
end
|
122
31
|
end
|
123
32
|
|
124
|
-
def
|
125
|
-
|
33
|
+
def rendering
|
34
|
+
return if @rendering
|
35
|
+
@rendering = true
|
36
|
+
yield.tap { @rendering = false }
|
126
37
|
end
|
127
|
-
|
128
|
-
def filename
|
129
|
-
"source/#{path}.md"
|
130
|
-
end
|
131
|
-
end
|
132
|
-
|
133
|
-
class Link < Struct.new(:href, :content, :options)
|
134
|
-
def render
|
135
|
-
%(<a href="#{href}" class="#{options[:class]}">#{content}</a>)
|
136
|
-
end
|
137
|
-
end
|
138
|
-
|
139
|
-
attr_reader :sitemap, :paths, :tree
|
140
|
-
|
141
|
-
def initialize(sitemap)
|
142
|
-
@sitemap = sitemap
|
143
|
-
@paths = Paths.new(sitemap)
|
144
|
-
@tree = build('.')
|
145
|
-
end
|
146
|
-
|
147
|
-
def render(current_path)
|
148
|
-
tree.activate(current_path.sub('.html', ''))
|
149
|
-
tree.render
|
150
|
-
end
|
151
|
-
|
152
|
-
def prev(current_path)
|
153
|
-
page = page_for(current_path)
|
154
|
-
href = paths.prev(page.path)
|
155
|
-
Link.new(href, 'Previous', class: 'prev').render if href
|
156
|
-
end
|
157
|
-
|
158
|
-
def next(current_path)
|
159
|
-
page = page_for(current_path)
|
160
|
-
href = paths.next(page.path)
|
161
|
-
Link.new(href, 'Next', class: 'next').render if href
|
162
38
|
end
|
163
|
-
|
164
|
-
private
|
165
|
-
|
166
|
-
def build(path, level = 1)
|
167
|
-
path = path.sub('./', '')
|
168
|
-
page = Page.new(level, path, page_for("#{path}.html"))
|
169
|
-
paths.select(path).each { |path| page.children << build(path, level + 1) }
|
170
|
-
page
|
171
|
-
end
|
172
|
-
|
173
|
-
def page_for(path)
|
174
|
-
sitemap.find_resource_by_path(path)
|
175
|
-
end
|
176
|
-
|
177
|
-
def title_for(path)
|
178
|
-
File.read(path)
|
179
|
-
end
|
180
39
|
end
|
181
40
|
|
182
41
|
Middleman::Extensions.register(:toc, MiddlemanToc::Extension)
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'middleman_toc/node'
|
2
|
+
require 'middleman_toc/title'
|
3
|
+
|
4
|
+
module MiddlemanToc
|
5
|
+
class Builder < Struct.new(:manifest, :pages)
|
6
|
+
def build
|
7
|
+
Node.new(0, nil, nil, nodes(manifest))
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def nodes(data, parents = [])
|
13
|
+
data.inject([]) do |pages, data|
|
14
|
+
pages << node(data['path'], data['children'], parents)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def node(path, children, parents)
|
19
|
+
path = parents + [path]
|
20
|
+
children = nodes(children, path) if children
|
21
|
+
Node.new(path.size, path.join('/'), title_for(path.join('/')), children)
|
22
|
+
end
|
23
|
+
|
24
|
+
def title_for(path)
|
25
|
+
Title.new(path, pages[path]).title
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -1,10 +1,16 @@
|
|
1
1
|
require 'middleman_toc/helpers'
|
2
2
|
|
3
|
-
|
3
|
+
module MiddlemanToc
|
4
4
|
class Extension < ::Middleman::Extension
|
5
5
|
# option :ignore, ['sitemap.xml', 'robots.txt'], 'Ignored files and directories.'
|
6
6
|
# option :titles, { 'index.md' => 'Home' }, 'Default link titles.'
|
7
7
|
|
8
8
|
self.defined_helpers = [Helpers]
|
9
|
+
|
10
|
+
def manipulate_resource_list(resources)
|
11
|
+
resources.each do |resource|
|
12
|
+
resource.destination_path.gsub!(/(^|\/)[\d]+\-/, '\1')
|
13
|
+
end
|
14
|
+
end
|
9
15
|
end
|
10
16
|
end
|
@@ -1,19 +1,15 @@
|
|
1
|
-
|
1
|
+
module MiddlemanToc
|
2
2
|
module Helpers
|
3
|
-
def _toc
|
4
|
-
@_toc ||= MiddlemanToc.new(sitemap)
|
5
|
-
end
|
6
|
-
|
7
3
|
def toc
|
8
|
-
|
4
|
+
MiddlemanToc.toc(sitemap, current_path)
|
9
5
|
end
|
10
6
|
|
11
7
|
def prev_page
|
12
|
-
|
8
|
+
MiddlemanToc.prev_page(sitemap, current_path)
|
13
9
|
end
|
14
10
|
|
15
11
|
def next_page
|
16
|
-
|
12
|
+
MiddlemanToc.next_page(sitemap, current_path)
|
17
13
|
end
|
18
14
|
end
|
19
15
|
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'middleman_toc/renderer'
|
2
|
+
|
3
|
+
module MiddlemanToc
|
4
|
+
class Node < Struct.new(:level, :path, :title, :children)
|
5
|
+
attr_reader :active
|
6
|
+
|
7
|
+
def find(path)
|
8
|
+
flatten.detect { |node| node.path == path }
|
9
|
+
end
|
10
|
+
|
11
|
+
def flatten
|
12
|
+
[self, children.map(&:flatten)].flatten
|
13
|
+
end
|
14
|
+
|
15
|
+
def activate(path)
|
16
|
+
@active = path == self.path
|
17
|
+
children.each { |child| child.activate(path) }
|
18
|
+
end
|
19
|
+
|
20
|
+
def render
|
21
|
+
Renderer.new(self).render
|
22
|
+
end
|
23
|
+
|
24
|
+
def children
|
25
|
+
super || []
|
26
|
+
end
|
27
|
+
|
28
|
+
def root?
|
29
|
+
level == 0
|
30
|
+
end
|
31
|
+
|
32
|
+
def directory?
|
33
|
+
children.any?
|
34
|
+
end
|
35
|
+
|
36
|
+
def active?
|
37
|
+
@active
|
38
|
+
end
|
39
|
+
|
40
|
+
def expanded?
|
41
|
+
directory? && active? || children.any?(&:active?)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'middleman_toc/tag'
|
2
|
+
|
3
|
+
module MiddlemanToc
|
4
|
+
class Renderer < Struct.new(:node)
|
5
|
+
def render
|
6
|
+
if node.root?
|
7
|
+
children
|
8
|
+
else
|
9
|
+
html = node.title
|
10
|
+
html = link("/#{node.path}.html", html)
|
11
|
+
html = [html, children].join("\n") if node.directory?
|
12
|
+
item(html)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def children
|
19
|
+
Tag.new(:ul, node.children.map(&:render)).render
|
20
|
+
end
|
21
|
+
|
22
|
+
def link(href, content)
|
23
|
+
Tag.new(:a, content, href: href).render
|
24
|
+
end
|
25
|
+
|
26
|
+
def item(content)
|
27
|
+
Tag.new(:li, content, class: classes).render
|
28
|
+
end
|
29
|
+
|
30
|
+
def classes
|
31
|
+
%w(active directory expanded).select { |name| node.send(:"#{name}?") }
|
32
|
+
end
|
33
|
+
|
34
|
+
def indent(string)
|
35
|
+
string.split("\n").map { |line| " #{line}" }.join("\n")
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module MiddlemanToc
|
2
|
+
class Tag < Struct.new(:name, :content, :attrs)
|
3
|
+
class Attr < Struct.new(:key, :value)
|
4
|
+
end
|
5
|
+
|
6
|
+
def render
|
7
|
+
"<#{name} #{attrs}".strip + ">\n#{indent(content)}\n</#{name}>"
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def attrs
|
13
|
+
Array(super).map { |key, value| attr(key, value) }.compact.join(' ')
|
14
|
+
end
|
15
|
+
|
16
|
+
def attr(key, value)
|
17
|
+
%(#{key}="#{Array(value).join(' ')}") unless value.nil? || value.empty?
|
18
|
+
end
|
19
|
+
|
20
|
+
def indent(lines)
|
21
|
+
Array(lines).join("\n").split("\n").map { |line| " #{line}" }.join("\n")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module MiddlemanToc
|
2
|
+
class Title < Struct.new(:path, :page)
|
3
|
+
def title
|
4
|
+
from_data || from_html || from_path
|
5
|
+
end
|
6
|
+
|
7
|
+
private
|
8
|
+
|
9
|
+
def from_data
|
10
|
+
page.data.title if page
|
11
|
+
end
|
12
|
+
|
13
|
+
def from_html
|
14
|
+
html.match(/<h.+>(.*?)<\/h1>/) && $1
|
15
|
+
end
|
16
|
+
|
17
|
+
def html
|
18
|
+
page ? page.render(layout: false, no_images: true) : ''
|
19
|
+
end
|
20
|
+
|
21
|
+
def from_path
|
22
|
+
File.basename(path).sub(/[\d]{2}-/, '').titleize if path
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'middleman_toc/builder'
|
2
|
+
|
3
|
+
module MiddlemanToc
|
4
|
+
class Toc < Struct.new(:pages)
|
5
|
+
attr_reader :root
|
6
|
+
|
7
|
+
def initialize(*)
|
8
|
+
super
|
9
|
+
@root = Builder.new(manifest, pages).build
|
10
|
+
end
|
11
|
+
|
12
|
+
def toc(path)
|
13
|
+
root.activate(normalize_path(path))
|
14
|
+
root.render
|
15
|
+
end
|
16
|
+
|
17
|
+
def prev_page(path)
|
18
|
+
node = root.find(normalize_path(path)).try(:prev)
|
19
|
+
Tag.new(:a, node.path, 'Previous', class: 'prev').render if node
|
20
|
+
end
|
21
|
+
|
22
|
+
def next_page(path)
|
23
|
+
node = root.find(normalize_path(path)).try(:next)
|
24
|
+
Tag.new(:a, node.path, 'Next', class: 'next').render if node
|
25
|
+
end
|
26
|
+
|
27
|
+
def normalize_path(path)
|
28
|
+
path.sub('.html', '')
|
29
|
+
end
|
30
|
+
|
31
|
+
def manifest
|
32
|
+
raise 'Could not load data/toc.yml' unless File.exists?('data/toc.yml')
|
33
|
+
normalize_nodes(YAML.load_file('data/toc.yml'))
|
34
|
+
end
|
35
|
+
|
36
|
+
def normalize_nodes(nodes)
|
37
|
+
Array(nodes).map do |node|
|
38
|
+
case node
|
39
|
+
when Array
|
40
|
+
normalize_nodes(node)
|
41
|
+
when String
|
42
|
+
{ 'path' => node }
|
43
|
+
when Hash
|
44
|
+
node.merge('children' => normalize_nodes(node['children']))
|
45
|
+
else
|
46
|
+
node
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'thor/shell/color'
|
2
|
+
|
3
|
+
module MiddlemanToc
|
4
|
+
class Validator < Struct.new(:pages, :node)
|
5
|
+
INDENT = ' '
|
6
|
+
|
7
|
+
def validate!
|
8
|
+
hrefs.each do |href|
|
9
|
+
missing_page(href) unless exists?(href)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def missing_page(href)
|
16
|
+
puts [INDENT, warn("Link to local page is missing in the table of contents: #{href}")].join
|
17
|
+
end
|
18
|
+
|
19
|
+
def exists?(href)
|
20
|
+
paths.include?(href)
|
21
|
+
end
|
22
|
+
|
23
|
+
def warn(message)
|
24
|
+
"#{ansi('warning', :red, :bold)}: #{message}"
|
25
|
+
end
|
26
|
+
|
27
|
+
def ansi(string, *attrs)
|
28
|
+
Thor::Shell::Color.new.set_color('warning', *attrs)
|
29
|
+
end
|
30
|
+
|
31
|
+
def hrefs
|
32
|
+
pages.map { |path, page| hrefs_from(page) }.flatten
|
33
|
+
end
|
34
|
+
|
35
|
+
def paths
|
36
|
+
pages.keys
|
37
|
+
end
|
38
|
+
|
39
|
+
def hrefs_from(page)
|
40
|
+
html = render(page) || ''
|
41
|
+
html.scan(%r(<a.+href="/([^"]+)")).flatten.map do |href|
|
42
|
+
href.sub('.html', '')
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def render(page)
|
47
|
+
page.render(layout: false, no_images: true)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -1,3 +1,3 @@
|
|
1
|
-
|
2
|
-
VERSION = "0.0.
|
1
|
+
module MiddlemanToc
|
2
|
+
VERSION = "0.0.3"
|
3
3
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
$:.unshift File.expand_path('../lib', __FILE__)
|
4
|
+
require 'middleman_toc/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = "middleman-toc"
|
8
|
+
s.version = MiddlemanToc::VERSION
|
9
|
+
s.authors = ["Sven Fuchs"]
|
10
|
+
s.email = "me@svenfuchs.com"
|
11
|
+
s.homepage = "https://github.com/svenfuchs/middleman-toc"
|
12
|
+
s.summary = "Middleman Table of Contents"
|
13
|
+
s.files = Dir['{lib/**/*,spec/**/*,[A-Z]*}']
|
14
|
+
s.platform = Gem::Platform::RUBY
|
15
|
+
s.require_path = 'lib'
|
16
|
+
s.rubyforge_project = '[none]'
|
17
|
+
|
18
|
+
s.add_dependency 'titleize'
|
19
|
+
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: middleman-toc
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sven Fuchs
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-05-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: titleize
|
@@ -34,14 +34,18 @@ files:
|
|
34
34
|
- Gemfile.lock
|
35
35
|
- README.md
|
36
36
|
- lib/middleman_toc.rb
|
37
|
+
- lib/middleman_toc/builder.rb
|
37
38
|
- lib/middleman_toc/extension.rb
|
38
39
|
- lib/middleman_toc/helpers.rb
|
39
|
-
- lib/middleman_toc/
|
40
|
-
- lib/middleman_toc/
|
41
|
-
- lib/middleman_toc/
|
40
|
+
- lib/middleman_toc/node.rb
|
41
|
+
- lib/middleman_toc/renderer.rb
|
42
|
+
- lib/middleman_toc/tag.rb
|
43
|
+
- lib/middleman_toc/title.rb
|
44
|
+
- lib/middleman_toc/toc.rb
|
45
|
+
- lib/middleman_toc/validator.rb
|
42
46
|
- lib/middleman_toc/version.rb
|
47
|
+
- middleman-toc.gemspec
|
43
48
|
- spec/spec_helper.rb
|
44
|
-
- spec/toc_spec.rb
|
45
49
|
homepage: https://github.com/svenfuchs/middleman-toc
|
46
50
|
licenses: []
|
47
51
|
metadata: {}
|
@@ -61,9 +65,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
61
65
|
version: '0'
|
62
66
|
requirements: []
|
63
67
|
rubyforge_project: "[none]"
|
64
|
-
rubygems_version: 2.
|
68
|
+
rubygems_version: 2.4.5
|
65
69
|
signing_key:
|
66
70
|
specification_version: 4
|
67
71
|
summary: Middleman Table of Contents
|
68
72
|
test_files: []
|
69
|
-
has_rdoc:
|
data/lib/middleman_toc/link.rb
DELETED
data/lib/middleman_toc/page.rb
DELETED
@@ -1,95 +0,0 @@
|
|
1
|
-
class MiddlemanToc
|
2
|
-
class Page
|
3
|
-
extend Forwardable
|
4
|
-
|
5
|
-
def_delegators :@children, :empty?
|
6
|
-
|
7
|
-
attr_reader :level, :path, :page, :children, :active
|
8
|
-
|
9
|
-
def initialize(level, path, page)
|
10
|
-
@level = level
|
11
|
-
@path = path
|
12
|
-
@page = page
|
13
|
-
@children = []
|
14
|
-
end
|
15
|
-
|
16
|
-
def <<(child)
|
17
|
-
children << child
|
18
|
-
end
|
19
|
-
|
20
|
-
def activate(active)
|
21
|
-
children.each { |child| child.activate(active) }
|
22
|
-
@active = active == path
|
23
|
-
end
|
24
|
-
|
25
|
-
def render
|
26
|
-
if level == 1
|
27
|
-
render_children
|
28
|
-
else
|
29
|
-
html = title
|
30
|
-
html = link("/#{path}.html", html) if File.file?(filename)
|
31
|
-
html = [html, render_children].join("\n") unless children.empty?
|
32
|
-
item(html)
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
def render_children
|
37
|
-
%(<ul#{%( class="active") if active?}>\n#{indent(children.map(&:render).join("\n"))}\n</ul>)
|
38
|
-
end
|
39
|
-
|
40
|
-
def link(href, content)
|
41
|
-
%(<a href="#{href}">#{content}</a>)
|
42
|
-
end
|
43
|
-
|
44
|
-
def item(content)
|
45
|
-
%(<li#{%( class="#{classes}") unless classes.empty?}>#{content}</li>)
|
46
|
-
end
|
47
|
-
|
48
|
-
def classes
|
49
|
-
classes = []
|
50
|
-
classes << 'active' if active?
|
51
|
-
classes << 'directory' if directory?
|
52
|
-
classes << 'expanded' if active? && !children.empty? || expanded?
|
53
|
-
classes.join(' ')
|
54
|
-
end
|
55
|
-
|
56
|
-
def directory?
|
57
|
-
!children.empty?
|
58
|
-
end
|
59
|
-
|
60
|
-
def active?
|
61
|
-
@active
|
62
|
-
end
|
63
|
-
|
64
|
-
def expanded?
|
65
|
-
level == 1 || children.any?(&:active?)
|
66
|
-
end
|
67
|
-
|
68
|
-
def title
|
69
|
-
title = page_title if page
|
70
|
-
title || path_title
|
71
|
-
end
|
72
|
-
|
73
|
-
def page_title
|
74
|
-
if page.data.title
|
75
|
-
page.data.title
|
76
|
-
else
|
77
|
-
html = page.render(layout: false, no_images: true)
|
78
|
-
matches = html.match(/<h.+>(.*?)<\/h1>/)
|
79
|
-
matches[1] if matches
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
def path_title
|
84
|
-
File.basename(path).sub(/[\d]{2}-/, '').titleize
|
85
|
-
end
|
86
|
-
|
87
|
-
def filename
|
88
|
-
"source/#{path}.md"
|
89
|
-
end
|
90
|
-
|
91
|
-
def indent(string)
|
92
|
-
string.split("\n").map { |line| "#{' ' * (level)}#{line}" }.join("\n")
|
93
|
-
end
|
94
|
-
end
|
95
|
-
end
|
data/lib/middleman_toc/paths.rb
DELETED
@@ -1,31 +0,0 @@
|
|
1
|
-
class MiddlemanToc
|
2
|
-
class Paths < Struct.new(:sitemap)
|
3
|
-
def prev(path)
|
4
|
-
path = paths[index(path) - 1]
|
5
|
-
"#{path.sub('.', '')}.html" if path
|
6
|
-
end
|
7
|
-
|
8
|
-
def next(path)
|
9
|
-
path = paths[index(path) + 1]
|
10
|
-
"#{path.sub('.', '')}.html" if path
|
11
|
-
end
|
12
|
-
|
13
|
-
def select(dir)
|
14
|
-
paths.select { |path| path =~ %r(#{dir}/) }.reject { |path| path =~ %r(#{dir}/.+/) }
|
15
|
-
end
|
16
|
-
|
17
|
-
def paths
|
18
|
-
@paths ||= begin
|
19
|
-
paths = sitemap.resources.map(&:path)
|
20
|
-
paths = paths.select { |path| path =~ /.html$/ }
|
21
|
-
paths = paths.map { |path| "./#{path.sub(/.html$/, '')}" }
|
22
|
-
paths = paths + paths.map { |path| ::File.dirname(path) } - ['.']
|
23
|
-
paths.sort.unshift('./index').uniq
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
def index(path)
|
28
|
-
paths.index("./#{path.sub('.html', '')}")
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
data/spec/toc_spec.rb
DELETED
@@ -1,47 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Middleman::Toc do
|
4
|
-
let(:titles) { ['Title 1', 'Title 2', 'Title 2-1', 'Title 2-2', 'Book'] }
|
5
|
-
let(:paths) { %w(1.html 2.html 2/2-1.html 2/2-2.html index.html) }
|
6
|
-
let(:pages) { paths.map { |path| stub(path: path) } }
|
7
|
-
let(:sitemap) { stub(resources: pages) }
|
8
|
-
let(:toc) { Middleman::Toc.new(sitemap) }
|
9
|
-
|
10
|
-
subject { toc.render }
|
11
|
-
|
12
|
-
before do
|
13
|
-
pages.map do |page|
|
14
|
-
sitemap.stubs(:find_resource_by_path).with(page.path).returns(page)
|
15
|
-
page.stubs(:data).returns(stub(title: nil))
|
16
|
-
File.stubs(:file?).with("source/#{page.path.sub('html', 'md')}").returns(page.path != '2.html')
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
describe 'with a directory that has an equivalent file' do
|
21
|
-
end
|
22
|
-
|
23
|
-
describe 'with page data title attribute set' do
|
24
|
-
before do
|
25
|
-
pages.map.with_index do |resource, ix|
|
26
|
-
resource.stubs(:data).returns(stub(title: "Data: #{titles[ix]}"))
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
it 'uses the page data title attribute' do
|
31
|
-
expect(subject).to include('<a href="1.html">Data: Title 1</a>')
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
describe 'with page data title attribute not set' do
|
36
|
-
before do
|
37
|
-
pages.map.with_index do |resource, ix|
|
38
|
-
resource.stubs(:render).returns("<h1>Html: #{titles[ix]}</h1>")
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
it 'renders and parses the page for a <h1> tag' do
|
43
|
-
puts subject
|
44
|
-
expect(subject).to include('<a href="1.html">Html: Title 1</a>')
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|