middleman-toc 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|