smeagol 0.5.9 → 0.6.0
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.
- data/.ruby +80 -0
- data/.yardopts +9 -0
- data/HISTORY.md +147 -0
- data/LICENSE.txt +30 -0
- data/README.md +132 -26
- data/bin/smeagol +9 -39
- data/bin/smeagol-init +3 -0
- data/bin/smeagol-preview +4 -0
- data/bin/smeagol-serve +4 -0
- data/bin/smeagol-update +4 -0
- data/bin/smeagold +1 -4
- data/lib/smeagol.rb +77 -6
- data/lib/smeagol/app.rb +121 -75
- data/lib/smeagol/cache.rb +43 -24
- data/lib/smeagol/cli.rb +166 -0
- data/lib/smeagol/config.rb +154 -0
- data/lib/smeagol/console.rb +369 -0
- data/lib/smeagol/controller.rb +275 -0
- data/lib/smeagol/core_ext.rb +12 -0
- data/lib/smeagol/gollum/blob_entry.rb +17 -0
- data/lib/smeagol/gollum/file.rb +44 -0
- data/lib/smeagol/gollum/page.rb +47 -0
- data/lib/smeagol/gollum/wiki.rb +31 -0
- data/lib/smeagol/helpers/rss.rb +96 -0
- data/lib/smeagol/helpers/toc.rb +69 -0
- data/lib/smeagol/public/assets/smeagol/gollum.css +716 -0
- data/lib/smeagol/public/{smeagol → assets/smeagol}/html5.js +0 -0
- data/lib/smeagol/public/{smeagol → assets/smeagol}/pygment.css +0 -0
- data/lib/smeagol/public/assets/smeagol/template.css +631 -0
- data/lib/smeagol/repository.rb +85 -0
- data/lib/smeagol/settings.rb +302 -0
- data/lib/smeagol/templates/layouts/page.mustache +19 -0
- data/lib/smeagol/templates/layouts/versions.mustache +16 -0
- data/lib/smeagol/templates/partials/footer.mustache +17 -0
- data/lib/smeagol/templates/partials/header.mustache +47 -0
- data/lib/smeagol/templates/settings.yml +64 -0
- data/lib/smeagol/version.rb +1 -1
- data/lib/smeagol/views/base.rb +188 -27
- data/lib/smeagol/views/form.rb +56 -0
- data/lib/smeagol/views/page.rb +126 -25
- data/lib/smeagol/views/post.rb +51 -0
- data/lib/smeagol/views/versions.rb +20 -6
- data/lib/smeagol/wiki.rb +25 -45
- data/test/helper.rb +72 -8
- data/test/test_app.rb +57 -0
- data/test/test_cache.rb +10 -11
- data/test/test_init.rb +27 -0
- data/test/test_update.rb +20 -0
- data/test/test_wiki.rb +13 -10
- metadata +142 -216
- data/bin/smeagol-static +0 -115
- data/lib/file.rb +0 -10
- data/lib/smeagol/hash.rb +0 -13
- data/lib/smeagol/option_parser.rb +0 -138
- data/lib/smeagol/public/smeagol/main.css +0 -234
- data/lib/smeagol/templates/page.mustache +0 -58
- data/lib/smeagol/templates/versions.mustache +0 -50
- data/test/test_file.rb +0 -12
- data/test/test_hash.rb +0 -18
@@ -0,0 +1,64 @@
|
|
1
|
+
---
|
2
|
+
# Gollum wiki url.
|
3
|
+
# e.g. `git@github.com:trans/trans.github.com.wiki.git`
|
4
|
+
|
5
|
+
wiki_origin: {{ wiki_origin }}
|
6
|
+
|
7
|
+
# Website address.
|
8
|
+
# e.g. `http://trans.github.com`
|
9
|
+
|
10
|
+
url: {{ url }}
|
11
|
+
|
12
|
+
# Source site, if applicable.
|
13
|
+
# e.g. `http://github.com/trans`
|
14
|
+
|
15
|
+
source_url: {{ source_url }}
|
16
|
+
|
17
|
+
# Title of site.
|
18
|
+
|
19
|
+
title: My Site
|
20
|
+
|
21
|
+
# Single line description of site.
|
22
|
+
|
23
|
+
tagline: Welcome to My Site
|
24
|
+
|
25
|
+
# Detailed description of site.
|
26
|
+
|
27
|
+
description:
|
28
|
+
This is my awesome site.
|
29
|
+
|
30
|
+
# Webmaster of site.
|
31
|
+
|
32
|
+
author: {{ author }}
|
33
|
+
|
34
|
+
# Menu that can be used in site template.
|
35
|
+
#
|
36
|
+
# e.g.
|
37
|
+
#
|
38
|
+
# menu:
|
39
|
+
# - title: Home
|
40
|
+
# href: /
|
41
|
+
# - title: Projects
|
42
|
+
# href: /Projects/
|
43
|
+
# - title: Tools
|
44
|
+
# href: /Tools/
|
45
|
+
# - title: Reads
|
46
|
+
# href: /Reads/
|
47
|
+
|
48
|
+
menu:
|
49
|
+
- title: Home
|
50
|
+
href: /
|
51
|
+
|
52
|
+
# Google analytics tracking id. Could be used for other such
|
53
|
+
# services if custom template is used.
|
54
|
+
|
55
|
+
tracking_id: ~
|
56
|
+
|
57
|
+
# Include a GitHub "Fork Me" ribbon in corner of page. Entry
|
58
|
+
# should give color and position separated by a space.
|
59
|
+
# The resulting ribbon will have a link to `source_url`.
|
60
|
+
#
|
61
|
+
# NOTE: Will be renamed to `github_forkme` or something like that.
|
62
|
+
|
63
|
+
ribbon: red right
|
64
|
+
|
data/lib/smeagol/version.rb
CHANGED
data/lib/smeagol/views/base.rb
CHANGED
@@ -1,35 +1,80 @@
|
|
1
1
|
module Smeagol
|
2
|
+
|
2
3
|
module Views
|
4
|
+
|
5
|
+
# Base class for all views.
|
6
|
+
#
|
7
|
+
# FAQ: Why aren't layouts versioned, i.e. pulled from the git repo
|
8
|
+
# like pages and posts? B/c we might want to look at content
|
9
|
+
# history, but that doesn't mean we want to look at it via
|
10
|
+
# an old layout.
|
11
|
+
#
|
3
12
|
class Base < ::Mustache
|
4
13
|
# Initializes a new mustache view template data object.
|
5
14
|
#
|
6
|
-
#
|
15
|
+
# master - Master controller, which creates all the views.
|
16
|
+
# page - The individual wiki page that this view represents.
|
17
|
+
# version - The tagged version of the page.
|
7
18
|
#
|
8
|
-
# Returns a new
|
9
|
-
def initialize(
|
10
|
-
@
|
19
|
+
# Returns a new page object.
|
20
|
+
def initialize(master, file, version='master')
|
21
|
+
@master = master
|
22
|
+
@file = file
|
23
|
+
@wiki = file.wiki
|
11
24
|
@version = version || 'master'
|
25
|
+
|
26
|
+
setup_template_path
|
12
27
|
end
|
28
|
+
|
29
|
+
# The Gollum::Wiki that this view represents.
|
30
|
+
attr_reader :wiki
|
13
31
|
|
32
|
+
# The tagged version that is being viewed.
|
33
|
+
attr_reader :version
|
34
|
+
|
35
|
+
#
|
36
|
+
def setup_template_path
|
37
|
+
# See FAQ for Views::Base class
|
38
|
+
dir = ::File.join(wiki.path, settings.partials)
|
39
|
+
if ::File.directory?(dir)
|
40
|
+
self.class.template_path = dir
|
41
|
+
else
|
42
|
+
self.class.template_path = ::File.join(LIBDIR, 'templates', 'partials')
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# The Gollum::Page or Gollum::File that this view represents.
|
47
|
+
attr_reader :file
|
48
|
+
|
49
|
+
#
|
50
|
+
def filename
|
51
|
+
file.filename
|
52
|
+
end
|
53
|
+
|
54
|
+
# Page name.
|
55
|
+
def name
|
56
|
+
file.name
|
57
|
+
end
|
58
|
+
|
14
59
|
# Public: The title of the wiki. This is set in the settings file.
|
15
60
|
def wiki_title
|
16
|
-
|
61
|
+
settings.title
|
17
62
|
end
|
18
|
-
|
63
|
+
|
19
64
|
# Public: The tagline for the wiki. This is set in the settings file.
|
20
65
|
def tagline
|
21
|
-
|
66
|
+
settings.tagline
|
22
67
|
end
|
23
68
|
|
24
69
|
# Public: The URL of the project source code. This is set in the settings
|
25
70
|
# file.
|
26
71
|
def source_url
|
27
|
-
|
72
|
+
settings.source_url
|
28
73
|
end
|
29
74
|
|
30
75
|
# Public: The Google Analytics tracking id from the settings file.
|
31
76
|
def tracking_id
|
32
|
-
|
77
|
+
settings.tracking_id
|
33
78
|
end
|
34
79
|
|
35
80
|
# Public: The HTML menu generated from the settings.yml file.
|
@@ -38,12 +83,13 @@ module Smeagol
|
|
38
83
|
if !menu.nil?
|
39
84
|
html = "<ul>\n"
|
40
85
|
menu.each do |item|
|
41
|
-
|
42
|
-
|
86
|
+
title, href = item['title'], item['href']
|
87
|
+
if version != 'master' && item['href'].index('/') == 0
|
88
|
+
prefix = version.start_with?('v') ? "/#{version}" : "/v#{version}"
|
43
89
|
else
|
44
90
|
prefix = ""
|
45
91
|
end
|
46
|
-
html << "<li><a href=\"#{prefix}#{
|
92
|
+
html << "<li class=\"minibutton\"><a href=\"#{prefix}#{href}\">#{title}</a></li>\n"
|
47
93
|
end
|
48
94
|
html << "</ul>\n"
|
49
95
|
end
|
@@ -62,23 +108,38 @@ module Smeagol
|
|
62
108
|
end
|
63
109
|
end
|
64
110
|
|
111
|
+
# Public: The string base path to prefix internal links.
|
112
|
+
def base_path
|
113
|
+
wiki.base_path
|
114
|
+
end
|
65
115
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
attr_reader :wiki
|
76
|
-
|
77
|
-
# The tagged version that is being viewed.
|
78
|
-
attr_reader :version
|
79
|
-
|
116
|
+
# List of posts.
|
117
|
+
def posts
|
118
|
+
@posts ||= @master.posts
|
119
|
+
#@posts ||= (
|
120
|
+
# filter(@wiki.pages){ |p| p.post? }.map do |page|
|
121
|
+
# Smeagol::Views::Post.new(page, @version)
|
122
|
+
# end
|
123
|
+
#)
|
124
|
+
end
|
80
125
|
|
81
|
-
|
126
|
+
=begin
|
127
|
+
#
|
128
|
+
def filter(paths, &selection)
|
129
|
+
result = []
|
130
|
+
paths.map do |file|
|
131
|
+
unless settings.include.any?{ |x| File.fnmatch?(x, file.path) }
|
132
|
+
next if file.path.split('/').any? do |x|
|
133
|
+
x.start_with?('_') or x.start_with?('.')
|
134
|
+
end
|
135
|
+
next if settings.exclude.any?{ |x| File.fnmatch?(x, file.path) }
|
136
|
+
end
|
137
|
+
result << file
|
138
|
+
end
|
139
|
+
result = result.select(&selection)
|
140
|
+
result
|
141
|
+
end
|
142
|
+
=end
|
82
143
|
|
83
144
|
# Generates the correct ribbon url
|
84
145
|
def ribbon_url(name, pos)
|
@@ -89,6 +150,106 @@ module Smeagol
|
|
89
150
|
name
|
90
151
|
end
|
91
152
|
end
|
153
|
+
|
154
|
+
# TODO: Actual slug support ?
|
155
|
+
#def slug(page,blob)
|
156
|
+
# date = page.version.authored_date
|
157
|
+
# name = blob.name[name.index(/[A-Za-z]/)..-1]
|
158
|
+
#
|
159
|
+
# if slug = @wiki.settings.slug
|
160
|
+
# slug = date.strftime(slug)
|
161
|
+
# slug = slug.sub(':name', name)
|
162
|
+
# else
|
163
|
+
# slug = name
|
164
|
+
# end
|
165
|
+
# slug
|
166
|
+
#end
|
167
|
+
|
168
|
+
# Get the layout template for the view.
|
169
|
+
def layout
|
170
|
+
return nil if custom_layout? && !custom_layout
|
171
|
+
custom_layout || standard_layout || default_layout
|
172
|
+
end
|
173
|
+
|
174
|
+
# Does the metadata specify a custom layout?
|
175
|
+
def custom_layout?
|
176
|
+
metadata.key?('layout')
|
177
|
+
end
|
178
|
+
|
179
|
+
# Value of layout metadata setting.
|
180
|
+
def custom_layout
|
181
|
+
metadata['layout']
|
182
|
+
end
|
183
|
+
|
184
|
+
# The Mustache template to use for rendering.
|
185
|
+
#
|
186
|
+
# Returns the content of the specified template file in the
|
187
|
+
# wiki repository if it exists. Otherwise, it returns `nil`.
|
188
|
+
def standard_layout
|
189
|
+
name = metadata['layout'] || 'page.mustache'
|
190
|
+
dir = ::File.expand_path(::File.join(wiki.path, ::File.dirname(file.path)))
|
191
|
+
root = ::File.expand_path(wiki.path)
|
192
|
+
home = ::File.expand_path('~')
|
193
|
+
layout = nil
|
194
|
+
loop do
|
195
|
+
f = ::File.join(dir, '_layouts', name)
|
196
|
+
break (layout = IO.read(f)) if ::File.exist?(f)
|
197
|
+
break nil if dir == root
|
198
|
+
break nil if dir == home # just in case
|
199
|
+
break nil if dir == '/'
|
200
|
+
dir = ::File.dirname(dir)
|
201
|
+
end
|
202
|
+
return layout
|
203
|
+
#names.each do |name|
|
204
|
+
# file = "#{@wiki.path}/#{settings.layout_dir}/#{name}.mustache"
|
205
|
+
# if ::File.exists?(file)
|
206
|
+
# return IO.read(file)
|
207
|
+
# end
|
208
|
+
#end
|
209
|
+
#nil
|
210
|
+
end
|
211
|
+
|
212
|
+
# Default template.
|
213
|
+
#
|
214
|
+
# Returns [String] The template included with the Smeagol package.
|
215
|
+
def default_layout
|
216
|
+
@default_layout ||= (
|
217
|
+
IO.read(LIBDIR + "/templates/layouts/page.mustache")
|
218
|
+
)
|
219
|
+
end
|
220
|
+
|
221
|
+
#
|
222
|
+
def post?
|
223
|
+
false
|
224
|
+
end
|
225
|
+
|
226
|
+
# Support mathjax?
|
227
|
+
def mathjax
|
228
|
+
settings.mathjax
|
229
|
+
end
|
230
|
+
|
231
|
+
#
|
232
|
+
def settings
|
233
|
+
@master.settings
|
234
|
+
end
|
235
|
+
|
236
|
+
# Embedded metadata.
|
237
|
+
#
|
238
|
+
# TODO: Can use file.metadata in future version of Gollum.
|
239
|
+
#
|
240
|
+
# Returns [Hash] of metadata.
|
241
|
+
def metadata
|
242
|
+
@metadata ||= (
|
243
|
+
if md = /\<\!\-\-\-(.*?)\-{2,3}\>\s*\Z/m.match(content)
|
244
|
+
YAML.load(md[1])
|
245
|
+
else
|
246
|
+
{}
|
247
|
+
end
|
248
|
+
)
|
249
|
+
end
|
250
|
+
|
92
251
|
end
|
252
|
+
|
93
253
|
end
|
254
|
+
|
94
255
|
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module Smeagol
|
2
|
+
|
3
|
+
module Views
|
4
|
+
|
5
|
+
# The form view is used for generic files that are not
|
6
|
+
# Gollum wiki pages. These are typically html or xml
|
7
|
+
# files and they are rendered as mustache templates.
|
8
|
+
#
|
9
|
+
class Form < Base
|
10
|
+
|
11
|
+
# The Gollum::File that this view represents. This is
|
12
|
+
# the same as `#file`.
|
13
|
+
alias form file
|
14
|
+
|
15
|
+
# Public: Rendered content of the file.
|
16
|
+
def content
|
17
|
+
@content ||= Mustache.render(file.raw_data, self)
|
18
|
+
end
|
19
|
+
|
20
|
+
#
|
21
|
+
def title
|
22
|
+
filename # TODO: better idea for form title?
|
23
|
+
end
|
24
|
+
alias_method :page_title, :title
|
25
|
+
|
26
|
+
#
|
27
|
+
#def content=(text)
|
28
|
+
# @content = text
|
29
|
+
#end
|
30
|
+
|
31
|
+
# Public: A flag stating that this is not the home file.
|
32
|
+
def not_home?
|
33
|
+
filename != "index.html"
|
34
|
+
end
|
35
|
+
|
36
|
+
# Public: static href, used when generating static site.
|
37
|
+
def href
|
38
|
+
dir = ::File.dirname(file.path)
|
39
|
+
ext = ::File.extname(file.path)
|
40
|
+
|
41
|
+
if dir != '.'
|
42
|
+
::File.join(dir, name.chomp(ext)) #file.path)
|
43
|
+
else
|
44
|
+
if name == settings.index #|| 'Home'
|
45
|
+
'index.html'
|
46
|
+
else
|
47
|
+
name.chomp(ext) #file.path
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
end #Form
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
data/lib/smeagol/views/page.rb
CHANGED
@@ -1,27 +1,32 @@
|
|
1
1
|
module Smeagol
|
2
|
+
|
2
3
|
module Views
|
4
|
+
|
3
5
|
class Page < Base
|
4
|
-
|
5
|
-
#
|
6
|
-
#
|
7
|
-
|
8
|
-
|
9
|
-
# Returns a new page object.
|
10
|
-
def initialize(page, version='master')
|
11
|
-
super(page.wiki, version)
|
12
|
-
@page = page
|
13
|
-
end
|
14
|
-
|
6
|
+
|
7
|
+
# The Gollum::Page that this view represents. This is
|
8
|
+
# the same as `#file`.
|
9
|
+
alias page file
|
10
|
+
|
15
11
|
# Public: The title of the page.
|
16
|
-
def
|
12
|
+
def title
|
17
13
|
page.title
|
18
14
|
end
|
19
|
-
|
15
|
+
|
16
|
+
# TODO: temporary alias
|
17
|
+
alias_method :page_title, :title
|
18
|
+
|
20
19
|
# Public: The HTML formatted content of the page.
|
21
20
|
def content
|
22
21
|
page.formatted_data
|
23
22
|
end
|
24
23
|
|
24
|
+
#
|
25
|
+
def summary
|
26
|
+
i = content.index('</p>')
|
27
|
+
i ? content[0..i+3] : content # any other way if no i, 5 line limit?
|
28
|
+
end
|
29
|
+
|
25
30
|
# Public: The last author of this page.
|
26
31
|
def author
|
27
32
|
page.version.author.name
|
@@ -29,25 +34,121 @@ module Smeagol
|
|
29
34
|
|
30
35
|
# Public: The last edit date of this page.
|
31
36
|
def date
|
32
|
-
|
37
|
+
post_date || commit_date
|
38
|
+
end
|
39
|
+
|
40
|
+
# Public: The last edit date of this page.
|
41
|
+
def commit_date
|
42
|
+
page.version.authored_date.strftime(settings.date_format)
|
33
43
|
end
|
34
|
-
|
44
|
+
|
35
45
|
# Public: A flag stating that this is not the home page.
|
36
46
|
def not_home?
|
37
|
-
page.title != "Home"
|
47
|
+
page.title != "Home" # settings.index
|
38
48
|
end
|
39
49
|
|
40
|
-
|
41
|
-
|
50
|
+
# Public: static href, used when generating static site.
|
51
|
+
def href
|
52
|
+
dir = ::File.dirname(page.path)
|
53
|
+
name = slug(page.filename_stripped)
|
54
|
+
ext = ::File.extname(page.path)
|
55
|
+
|
56
|
+
if dir != '.'
|
57
|
+
::File.join(dir, name, 'index.html')
|
58
|
+
else
|
59
|
+
if name == settings.index #|| 'Home'
|
60
|
+
'index.html'
|
61
|
+
else
|
62
|
+
::File.join(name, 'index.html')
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# Internal: Apply slug rules to name.
|
42
68
|
#
|
43
|
-
#
|
69
|
+
# TODO: Support configurable slugs.
|
44
70
|
#
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
71
|
+
# Returns [String] Sluggified name.
|
72
|
+
def slug(name)
|
73
|
+
if /^\d\d+\-/ =~ name
|
74
|
+
dirs = []
|
75
|
+
parts = name.split('-')
|
76
|
+
while /^\d+$/ =~ parts.first
|
77
|
+
dirs << parts.shift
|
78
|
+
end
|
79
|
+
dirs << parts.join('-')
|
80
|
+
dirs.join('/')
|
81
|
+
else
|
82
|
+
name
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
# If the name of the page begins with a date, then it is the "post date"
|
87
|
+
# and is taken to be a blog entry, rather then an ordinary static page.
|
88
|
+
def post_date
|
89
|
+
if md = /^(\d\d\d\d-\d\d-\d\d)/.match(filename)
|
90
|
+
Time.parse(md[1]).strftime(settings.date_format)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
#
|
95
|
+
def post?
|
96
|
+
/^(\d\d\d\d-\d\d-\d\d)/.match(filename)
|
97
|
+
end
|
98
|
+
|
99
|
+
def has_header
|
100
|
+
@header = (@page.header || false) if @header.nil?
|
101
|
+
!!@header
|
102
|
+
end
|
103
|
+
|
104
|
+
def header_content
|
105
|
+
has_header && @header.formatted_data
|
106
|
+
end
|
107
|
+
|
108
|
+
def header_format
|
109
|
+
has_header && @header.format.to_s
|
110
|
+
end
|
111
|
+
|
112
|
+
def has_footer
|
113
|
+
@footer = (@page.footer || false) if @footer.nil?
|
114
|
+
!!@footer
|
115
|
+
end
|
116
|
+
|
117
|
+
def footer_content
|
118
|
+
has_footer && @footer.formatted_data
|
119
|
+
end
|
120
|
+
|
121
|
+
def footer_format
|
122
|
+
has_footer && @footer.format.to_s
|
123
|
+
end
|
124
|
+
|
125
|
+
def has_sidebar
|
126
|
+
@sidebar = (@page.sidebar || false) if @sidebar.nil?
|
127
|
+
!!@sidebar
|
128
|
+
end
|
129
|
+
|
130
|
+
def sidebar_content
|
131
|
+
has_sidebar && @sidebar.formatted_data
|
132
|
+
end
|
133
|
+
|
134
|
+
def sidebar_format
|
135
|
+
has_sidebar && @sidebar.format.to_s
|
136
|
+
end
|
137
|
+
|
138
|
+
def has_toc
|
139
|
+
!@toc_content.nil?
|
140
|
+
end
|
141
|
+
|
142
|
+
def toc_content
|
143
|
+
@toc_content
|
144
|
+
end
|
145
|
+
|
146
|
+
def mathjax
|
147
|
+
@mathjax
|
148
|
+
end
|
149
|
+
|
51
150
|
end
|
151
|
+
|
52
152
|
end
|
153
|
+
|
53
154
|
end
|