middleman-toc 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f854b8ef57495ea5b094ed90d3b4e509e0978c21
4
+ data.tar.gz: fc7e54f5ded46ca96834fae5b8c969caf283689d
5
+ SHA512:
6
+ metadata.gz: 908ae6a3625b281fd30f68dab7b49ac61b6c555f460e034bcaed39282248d0506e793873cddc2ce2b9116030f9a6bf5fa460e221f632df4e7d5298986e3d0a3e
7
+ data.tar.gz: 295f8764e0986ab0309231b77b882e4668e9e5eccfb1447b3f1ed10eb5feff9cc8eafe135352978e4aca12bd27c0e8eec6195de884688f9638dc076baadf9ee1
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+ gem 'middleman'
5
+
6
+ group :test do
7
+ gem 'rspec'
8
+ gem 'mocha'
9
+ end
@@ -0,0 +1,140 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ middleman-toc (0.0.1)
5
+ titleize
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ activesupport (4.1.8)
11
+ i18n (~> 0.6, >= 0.6.9)
12
+ json (~> 1.7, >= 1.7.7)
13
+ minitest (~> 5.1)
14
+ thread_safe (~> 0.1)
15
+ tzinfo (~> 1.1)
16
+ celluloid (0.16.0)
17
+ timers (~> 4.0.0)
18
+ chunky_png (1.3.3)
19
+ coffee-script (2.3.0)
20
+ coffee-script-source
21
+ execjs
22
+ coffee-script-source (1.8.0)
23
+ compass (1.0.1)
24
+ chunky_png (~> 1.2)
25
+ compass-core (~> 1.0.1)
26
+ compass-import-once (~> 1.0.5)
27
+ rb-fsevent (>= 0.9.3)
28
+ rb-inotify (>= 0.9)
29
+ sass (>= 3.3.13, < 3.5)
30
+ compass-core (1.0.1)
31
+ multi_json (~> 1.0)
32
+ sass (>= 3.3.0, < 3.5)
33
+ compass-import-once (1.0.5)
34
+ sass (>= 3.2, < 3.5)
35
+ diff-lcs (1.2.5)
36
+ erubis (2.7.0)
37
+ execjs (2.2.2)
38
+ ffi (1.9.6)
39
+ haml (4.0.6)
40
+ tilt
41
+ hike (1.2.3)
42
+ hitimes (1.2.2)
43
+ hooks (0.4.0)
44
+ uber (~> 0.0.4)
45
+ i18n (0.6.11)
46
+ json (1.8.2)
47
+ kramdown (1.5.0)
48
+ listen (2.8.5)
49
+ celluloid (>= 0.15.2)
50
+ rb-fsevent (>= 0.9.3)
51
+ rb-inotify (>= 0.9)
52
+ metaclass (0.0.4)
53
+ middleman (3.3.7)
54
+ coffee-script (~> 2.2)
55
+ compass (>= 1.0.0, < 2.0.0)
56
+ compass-import-once (= 1.0.5)
57
+ execjs (~> 2.0)
58
+ haml (>= 4.0.5)
59
+ kramdown (~> 1.2)
60
+ middleman-core (= 3.3.7)
61
+ middleman-sprockets (>= 3.1.2)
62
+ sass (>= 3.4.0, < 4.0)
63
+ uglifier (~> 2.5)
64
+ middleman-core (3.3.7)
65
+ activesupport (~> 4.1.0)
66
+ bundler (~> 1.1)
67
+ erubis
68
+ hooks (~> 0.3)
69
+ i18n (~> 0.6.9)
70
+ listen (>= 2.7.9, < 3.0)
71
+ padrino-helpers (~> 0.12.3)
72
+ rack (>= 1.4.5, < 2.0)
73
+ rack-test (~> 0.6.2)
74
+ thor (>= 0.15.2, < 2.0)
75
+ tilt (~> 1.4.1, < 2.0)
76
+ middleman-sprockets (3.4.1)
77
+ middleman-core (>= 3.3)
78
+ sprockets (~> 2.12.1)
79
+ sprockets-helpers (~> 1.1.0)
80
+ sprockets-sass (~> 1.3.0)
81
+ minitest (5.5.1)
82
+ mocha (1.1.0)
83
+ metaclass (~> 0.0.1)
84
+ multi_json (1.10.1)
85
+ padrino-helpers (0.12.4)
86
+ i18n (~> 0.6, >= 0.6.7)
87
+ padrino-support (= 0.12.4)
88
+ tilt (~> 1.4.1)
89
+ padrino-support (0.12.4)
90
+ activesupport (>= 3.1)
91
+ rack (1.6.0)
92
+ rack-test (0.6.2)
93
+ rack (>= 1.0)
94
+ rb-fsevent (0.9.4)
95
+ rb-inotify (0.9.5)
96
+ ffi (>= 0.5.0)
97
+ rspec (3.1.0)
98
+ rspec-core (~> 3.1.0)
99
+ rspec-expectations (~> 3.1.0)
100
+ rspec-mocks (~> 3.1.0)
101
+ rspec-core (3.1.7)
102
+ rspec-support (~> 3.1.0)
103
+ rspec-expectations (3.1.2)
104
+ diff-lcs (>= 1.2.0, < 2.0)
105
+ rspec-support (~> 3.1.0)
106
+ rspec-mocks (3.1.3)
107
+ rspec-support (~> 3.1.0)
108
+ rspec-support (3.1.2)
109
+ sass (3.4.9)
110
+ sprockets (2.12.3)
111
+ hike (~> 1.2)
112
+ multi_json (~> 1.0)
113
+ rack (~> 1.0)
114
+ tilt (~> 1.1, != 1.3.0)
115
+ sprockets-helpers (1.1.0)
116
+ sprockets (~> 2.0)
117
+ sprockets-sass (1.3.1)
118
+ sprockets (~> 2.0)
119
+ tilt (~> 1.1)
120
+ thor (0.19.1)
121
+ thread_safe (0.3.4)
122
+ tilt (1.4.1)
123
+ timers (4.0.1)
124
+ hitimes
125
+ titleize (1.3.0)
126
+ tzinfo (1.2.2)
127
+ thread_safe (~> 0.1)
128
+ uber (0.0.12)
129
+ uglifier (2.6.1)
130
+ execjs (>= 0.3.0)
131
+ json (>= 1.8.0)
132
+
133
+ PLATFORMS
134
+ ruby
135
+
136
+ DEPENDENCIES
137
+ middleman
138
+ middleman-toc!
139
+ mocha
140
+ rspec
@@ -0,0 +1,3 @@
1
+ # Middleman Table of Contents
2
+
3
+ Render a table of contents. See http://ruby-for-beginners.rubymonstas.org
@@ -0,0 +1,183 @@
1
+ require 'middleman'
2
+ require 'middleman_toc/extension'
3
+ require 'forwardable'
4
+
5
+ class MiddlemanToc
6
+ module Indent
7
+ def indent(string)
8
+ string.split("\n").map { |line| "#{' ' * (level)}#{line}" }.join("\n")
9
+ end
10
+ end
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 Tree
43
+ extend Forwardable
44
+ include Indent
45
+
46
+ def_delegators :@children, :empty?
47
+ attr_reader :level, :path, :children, :active
48
+
49
+ def initialize(level, path)
50
+ @level = level
51
+ @path = path
52
+ @children = []
53
+ end
54
+
55
+ def <<(child)
56
+ children << child
57
+ end
58
+
59
+ def activate(active)
60
+ children.each { |child| child.activate(active) }
61
+ @active = level == 1 || active == path || children.any?(&:active?)
62
+ end
63
+
64
+ def render
65
+ "<ul#{' class="active"' if active}>\n#{indent(children.map(&:render).join("\n"))}\n</ul>"
66
+ end
67
+ end
68
+
69
+ class Page < Struct.new(:level, :page, :path, :directory?)
70
+ include Indent
71
+
72
+ attr_reader :active, :active
73
+
74
+ def activate(active)
75
+ @active = active == path
76
+ end
77
+
78
+ def render
79
+ html = title
80
+ html = link("/#{path}.html", html) if File.file?(filename)
81
+ html = item(html)
82
+ html
83
+ end
84
+
85
+ def link(href, content)
86
+ %(<a href="#{href}">#{content}</a>)
87
+ end
88
+
89
+ def item(content)
90
+ %(<li#{%( class="#{classes}") if classes}>#{content}</li>)
91
+ end
92
+
93
+ def active?
94
+ # current == path
95
+ @active
96
+ end
97
+
98
+ def classes
99
+ classes = []
100
+ classes << 'active' if active?
101
+ classes << 'directory' if directory?
102
+ classes.join(' ')
103
+ end
104
+
105
+ def title
106
+ title = page_title if page
107
+ title || path_title
108
+ end
109
+
110
+ def page_title
111
+ if page.data.title
112
+ page.data.title
113
+ else
114
+ html = page.render(layout: false, no_images: true)
115
+ matches = html.match(/<h.+>(.*?)<\/h1>/)
116
+ matches[1] if matches
117
+ end
118
+ end
119
+
120
+ def path_title
121
+ path.sub(/[\d]{2}-/, '').titleize
122
+ end
123
+
124
+ def filename
125
+ "source/#{path}.md"
126
+ end
127
+ end
128
+
129
+ class Link < Struct.new(:href, :content, :options)
130
+ def render
131
+ %(<a href="#{href}" class="#{options[:class]}">#{content}</a>)
132
+ end
133
+ end
134
+
135
+ attr_reader :sitemap, :paths, :tree
136
+
137
+ def initialize(sitemap)
138
+ @sitemap = sitemap
139
+ @paths = Paths.new(sitemap)
140
+ @tree = build('.')
141
+ end
142
+
143
+ def render(current_path)
144
+ tree.activate(current_path.sub('.html', ''))
145
+ tree.render
146
+ end
147
+
148
+ def prev(current_path)
149
+ page = page_for(current_path)
150
+ href = paths.prev(page.path)
151
+ Link.new(href, 'Previous', class: 'prev').render if href
152
+ end
153
+
154
+ def next(current_path)
155
+ page = page_for(current_path)
156
+ href = paths.next(page.path)
157
+ Link.new(href, 'Next', class: 'next').render if href
158
+ end
159
+
160
+ private
161
+
162
+ def build(dir, level = 1)
163
+ tree = Tree.new(level, dir.sub('./', ''))
164
+ paths.select(dir).each do |path|
165
+ child = build(path, level + 1)
166
+ path = path.sub('./', '')
167
+ page = page_for("#{path}.html")
168
+ tree.children << Page.new(level, page, path, !child.empty?)
169
+ tree << child unless child.empty?
170
+ end
171
+ tree
172
+ end
173
+
174
+ def page_for(path)
175
+ sitemap.find_resource_by_path(path)
176
+ end
177
+
178
+ def title_for(path)
179
+ File.read(path)
180
+ end
181
+ end
182
+
183
+ Middleman::Extensions.register(:toc, MiddlemanToc::Extension)
@@ -0,0 +1,10 @@
1
+ require 'middleman_toc/helpers'
2
+
3
+ class MiddlemanToc
4
+ class Extension < ::Middleman::Extension
5
+ # option :ignore, ['sitemap.xml', 'robots.txt'], 'Ignored files and directories.'
6
+ # option :titles, { 'index.md' => 'Home' }, 'Default link titles.'
7
+
8
+ self.defined_helpers = [Helpers]
9
+ end
10
+ end
@@ -0,0 +1,19 @@
1
+ class MiddlemanToc
2
+ module Helpers
3
+ def _toc
4
+ @_toc ||= MiddlemanToc.new(sitemap)
5
+ end
6
+
7
+ def toc
8
+ _toc.render(current_page.path)
9
+ end
10
+
11
+ def prev_page
12
+ _toc.prev(current_page.path)
13
+ end
14
+
15
+ def next_page
16
+ _toc.next(current_page.path)
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,3 @@
1
+ class MiddlemanToc
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,7 @@
1
+ require 'middleman-toc'
2
+ require 'middleman-core/configuration'
3
+
4
+ RSpec.configure do |c|
5
+ c.expect_with :rspec
6
+ c.mock_with :mocha
7
+ end
@@ -0,0 +1,47 @@
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
metadata ADDED
@@ -0,0 +1,66 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: middleman-toc
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Sven Fuchs
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-01-16 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: titleize
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ description:
28
+ email: me@svenfuchs.com
29
+ executables: []
30
+ extensions: []
31
+ extra_rdoc_files: []
32
+ files:
33
+ - Gemfile
34
+ - Gemfile.lock
35
+ - README.md
36
+ - lib/middleman_toc.rb
37
+ - lib/middleman_toc/extension.rb
38
+ - lib/middleman_toc/helpers.rb
39
+ - lib/middleman_toc/version.rb
40
+ - spec/spec_helper.rb
41
+ - spec/toc_spec.rb
42
+ homepage: https://github.com/svenfuchs/middleman-toc
43
+ licenses: []
44
+ metadata: {}
45
+ post_install_message:
46
+ rdoc_options: []
47
+ require_paths:
48
+ - lib
49
+ required_ruby_version: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ required_rubygems_version: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: '0'
59
+ requirements: []
60
+ rubyforge_project: "[none]"
61
+ rubygems_version: 2.2.2
62
+ signing_key:
63
+ specification_version: 4
64
+ summary: Middleman Table of Contents
65
+ test_files: []
66
+ has_rdoc: