smeagol 0.5.9 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. data/.ruby +80 -0
  2. data/.yardopts +9 -0
  3. data/HISTORY.md +147 -0
  4. data/LICENSE.txt +30 -0
  5. data/README.md +132 -26
  6. data/bin/smeagol +9 -39
  7. data/bin/smeagol-init +3 -0
  8. data/bin/smeagol-preview +4 -0
  9. data/bin/smeagol-serve +4 -0
  10. data/bin/smeagol-update +4 -0
  11. data/bin/smeagold +1 -4
  12. data/lib/smeagol.rb +77 -6
  13. data/lib/smeagol/app.rb +121 -75
  14. data/lib/smeagol/cache.rb +43 -24
  15. data/lib/smeagol/cli.rb +166 -0
  16. data/lib/smeagol/config.rb +154 -0
  17. data/lib/smeagol/console.rb +369 -0
  18. data/lib/smeagol/controller.rb +275 -0
  19. data/lib/smeagol/core_ext.rb +12 -0
  20. data/lib/smeagol/gollum/blob_entry.rb +17 -0
  21. data/lib/smeagol/gollum/file.rb +44 -0
  22. data/lib/smeagol/gollum/page.rb +47 -0
  23. data/lib/smeagol/gollum/wiki.rb +31 -0
  24. data/lib/smeagol/helpers/rss.rb +96 -0
  25. data/lib/smeagol/helpers/toc.rb +69 -0
  26. data/lib/smeagol/public/assets/smeagol/gollum.css +716 -0
  27. data/lib/smeagol/public/{smeagol → assets/smeagol}/html5.js +0 -0
  28. data/lib/smeagol/public/{smeagol → assets/smeagol}/pygment.css +0 -0
  29. data/lib/smeagol/public/assets/smeagol/template.css +631 -0
  30. data/lib/smeagol/repository.rb +85 -0
  31. data/lib/smeagol/settings.rb +302 -0
  32. data/lib/smeagol/templates/layouts/page.mustache +19 -0
  33. data/lib/smeagol/templates/layouts/versions.mustache +16 -0
  34. data/lib/smeagol/templates/partials/footer.mustache +17 -0
  35. data/lib/smeagol/templates/partials/header.mustache +47 -0
  36. data/lib/smeagol/templates/settings.yml +64 -0
  37. data/lib/smeagol/version.rb +1 -1
  38. data/lib/smeagol/views/base.rb +188 -27
  39. data/lib/smeagol/views/form.rb +56 -0
  40. data/lib/smeagol/views/page.rb +126 -25
  41. data/lib/smeagol/views/post.rb +51 -0
  42. data/lib/smeagol/views/versions.rb +20 -6
  43. data/lib/smeagol/wiki.rb +25 -45
  44. data/test/helper.rb +72 -8
  45. data/test/test_app.rb +57 -0
  46. data/test/test_cache.rb +10 -11
  47. data/test/test_init.rb +27 -0
  48. data/test/test_update.rb +20 -0
  49. data/test/test_wiki.rb +13 -10
  50. metadata +142 -216
  51. data/bin/smeagol-static +0 -115
  52. data/lib/file.rb +0 -10
  53. data/lib/smeagol/hash.rb +0 -13
  54. data/lib/smeagol/option_parser.rb +0 -138
  55. data/lib/smeagol/public/smeagol/main.css +0 -234
  56. data/lib/smeagol/templates/page.mustache +0 -58
  57. data/lib/smeagol/templates/versions.mustache +0 -50
  58. data/test/test_file.rb +0 -12
  59. 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
+
@@ -1,3 +1,3 @@
1
1
  module Smeagol
2
- VERSION = "0.5.9"
2
+ VERSION = "0.6.0"
3
3
  end
@@ -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
- # wiki - The wiki that this view represents.
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 view object.
9
- def initialize(wiki, version='master')
10
- @wiki = wiki
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
- wiki.settings.title
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
- wiki.settings.tagline
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
- wiki.settings.source_url
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
- wiki.settings.tracking_id
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
- if version != 'master' && item.href.index('/') == 0
42
- prefix = "/#{version}"
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}#{item.href}\">#{item.title}</a></li>\n"
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
- # Internal Methods
69
- #
70
- ##########################################################################
71
-
72
- protected
73
-
74
- # The Gollum::Wiki that this view represents.
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
- private
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
@@ -1,27 +1,32 @@
1
1
  module Smeagol
2
+
2
3
  module Views
4
+
3
5
  class Page < Base
4
- # Initializes a new page template data object.
5
- #
6
- # page - The individual wiki page that this view represents.
7
- # version - The tagged version of the page.
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 page_title
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
- page.version.authored_date.strftime("%B %d, %Y")
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
- # Internal Methods
69
+ # TODO: Support configurable slugs.
44
70
  #
45
- ##########################################################################
46
-
47
- private
48
-
49
- # The Gollum::Page that this view represents.
50
- attr_reader :page
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