smeagol 0.1.1 → 0.2.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.
@@ -1,6 +1,8 @@
1
1
  $:.unshift(File.dirname(__FILE__))
2
2
  require 'smeagol/app'
3
+ require 'smeagol/hash'
3
4
  require 'smeagol/updater'
5
+ require 'smeagol/wiki'
4
6
  require 'smeagol/version'
5
7
  require 'rdiscount'
6
8
  require 'RedCloth'
@@ -1,6 +1,7 @@
1
1
  require 'gollum'
2
2
  require 'sinatra'
3
3
  require 'mustache'
4
+ require 'smeagol/views/page'
4
5
 
5
6
  module Smeagol
6
7
  class App < Sinatra::Base
@@ -33,16 +34,14 @@ module Smeagol
33
34
  name = params[:splat].first
34
35
  name = "Home" if name == ""
35
36
 
36
- wiki = Gollum::Wiki.new(settings.gollum_path)
37
+ # Load the wiki settings
38
+ wiki = Smeagol::Wiki.new(settings.gollum_path)
37
39
  if page = wiki.page(name)
38
- Mustache.render(page_template,
39
- :page => page,
40
- :title => page.title,
41
- :content => page.formatted_data
42
- )
40
+ Mustache.render(page_template, Smeagol::Views::Page.new(page))
43
41
  elsif file = wiki.file(name)
44
- content_type file.mime_type
45
42
  file.raw_data
43
+ else
44
+ raise Sinatra::NotFound
46
45
  end
47
46
  end
48
47
 
@@ -0,0 +1,13 @@
1
+ class Hash
2
+ # Recursively converts a Hash object to an OpenStruct object.
3
+ #
4
+ # Returns a copy of the hash as an OpenStruct.
5
+ def to_ostruct()
6
+ struct = OpenStruct.new(self.clone())
7
+ each do |k, v|
8
+ struct.__send__("#{k}=", v.to_ostruct()) if v.is_a?(Hash)
9
+ struct.__send__(k).map! {|x| x.is_a?(Hash) ? x.to_ostruct() : x} if v.is_a?(Array)
10
+ end
11
+ return struct
12
+ end
13
+ end
@@ -1,6 +1,48 @@
1
- h1 {
2
- padding-bottom: 3px;
3
- border-bottom: 3px solid #ccc;
1
+ body {
2
+ font: normal normal normal 13.34px/normal helvetica, arial, sans-serif;
3
+ font-size: 14px;
4
+ line-height: 1.4em;
5
+ }
6
+
7
+ header {
8
+ }
9
+
10
+ nav {
11
+ border-top: 2px solid #ddd;
12
+ border-bottom: 2px solid #ddd;
13
+ margin-bottom: 0.5em;
14
+ }
15
+
16
+ nav ul {
17
+ padding: 2px 2px;
18
+ margin: 3px 0px 0px;
19
+ white-space: nowrap;
20
+ }
21
+
22
+ nav ul li {
23
+ display: inline;
24
+ list-style-type: none;
25
+ padding: 0px 35px 0px 0px;
26
+ }
27
+
28
+ nav ul li a {
29
+ color: #333;
30
+ font-weight: bold;
31
+ text-decoration: none;
32
+ }
33
+
34
+ nav ul li a:hover {
35
+ color: black;
36
+ }
37
+
38
+ footer {
39
+ border-top: 3px solid #ccc;
40
+ padding-top: 1px;
41
+ margin-bottom: 0.5em;
42
+ }
43
+
44
+ .tagline {
45
+ font-style: italic;
4
46
  }
5
47
 
6
48
  #container {
@@ -8,3 +50,74 @@ h1 {
8
50
  margin-right: auto;
9
51
  width: 650px;
10
52
  }
53
+
54
+ h1 {
55
+ font-size: 250%;
56
+ margin-bottom: 0.25em;
57
+ }
58
+
59
+ article h1 {
60
+ font-size: 175%;
61
+ }
62
+
63
+ #content {
64
+ color: #333;
65
+ }
66
+
67
+ #content h1 {
68
+ color: black;
69
+ border-top: 4px solid #aaa;
70
+ margin-top: 1.5em;
71
+ padding-top: 0.5em;
72
+ }
73
+
74
+ #content h2 {
75
+ color: black;
76
+ border-top: 4px solid #e0e0e0;
77
+ margin-top: 1.5em;
78
+ padding-top: 0.5em;
79
+ }
80
+
81
+ #content h3 {
82
+ margin-top: 1em;
83
+ font-size: 1.17em;
84
+ }
85
+
86
+ #content p {
87
+ line-height: 1.5em;
88
+ margin: 1em 0px;
89
+ }
90
+
91
+ #content ol {
92
+ padding: 0px;
93
+ margin: 1em 0px 1em 2em;
94
+ display: block;
95
+ list-style-type: decimal;
96
+ }
97
+
98
+ #content ul {
99
+ padding: 0px;
100
+ margin: 1em 0px 1em 2em;
101
+ display: block;
102
+ list-style-type: disc;
103
+ }
104
+
105
+ #content li {
106
+ margin-bottom: 0.5em;
107
+ margin-top: 0.5em;
108
+ }
109
+
110
+ pre {
111
+ background-color: ghostWhite;
112
+ border: 1px solid #ddd;
113
+ color: #444;
114
+ font-size: 12px;
115
+ line-height: 1.5em;
116
+ margin: 1em 0px;
117
+ overflow: auto;
118
+ padding: 0.5em;
119
+ }
120
+
121
+ pre, code {
122
+ font: normal normal normal 12px/normal Monaco, 'Courier New', monospace;
123
+ }
@@ -2,17 +2,35 @@
2
2
  <html>
3
3
  <head>
4
4
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
5
- <title>{{title}}</title>
5
+ <title>{{wiki_title}} - {{page_title}}</title>
6
6
  <link rel="stylesheet" href="/smeagol/main.css" type="text/css"/>
7
7
  <link rel="stylesheet" href="/smeagol/pygment.css" type="text/css"/>
8
8
  </head>
9
9
 
10
10
  <body>
11
11
  <div id="container">
12
- <h1>{{title}}</h1>
13
- <div>
12
+ <header>
13
+ <h1>{{wiki_title}}</h1>
14
+ </header>
15
+
16
+ <nav>
17
+ {{{menu_html}}}
18
+ </nav>
19
+
20
+ <article>
21
+ {{#is_not_home?}}
22
+ <h1>{{page_title}}</h1>
23
+ {{/is_not_home?}}
24
+ <div id="content">
14
25
  {{{content}}}
15
- </div>
26
+ </div>
27
+ </article>
28
+
29
+ {{#is_not_home?}}
30
+ <footer>
31
+ <small>Last edited by <b>{{author}}</b> on {{date}}.</small>
32
+ </footer>
33
+ {{/is_not_home?}}
16
34
  </div>
17
35
  </body>
18
36
  </html>
@@ -1,3 +1,3 @@
1
1
  module Smeagol
2
- VERSION = "0.1.1"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -0,0 +1,73 @@
1
+ module Smeagol
2
+ module Views
3
+ class Page < Mustache
4
+ # Initializes a new page template data object.
5
+ #
6
+ # page - The individual wiki page that this view represents.
7
+ #
8
+ # Returns a new page object.
9
+ def initialize(page)
10
+ @page = page
11
+ end
12
+
13
+ # Public: The title of the wiki. This is set in the settings file.
14
+ def wiki_title
15
+ page.wiki.settings.title
16
+ end
17
+
18
+ # Public: The tagline for the wiki. This is set in the settings file.
19
+ def tagline
20
+ page.wiki.settings.tagline
21
+ end
22
+
23
+ # Public: The title of the page.
24
+ def page_title
25
+ page.title
26
+ end
27
+
28
+ # Public: The HTML formatted content of the page.
29
+ def content
30
+ page.formatted_data
31
+ end
32
+
33
+ # Public: The last author of this page.
34
+ def author
35
+ page.version.author.name
36
+ end
37
+
38
+ # Public: The last edit date of this page.
39
+ def date
40
+ page.version.authored_date.strftime("%B %d, %Y")
41
+ end
42
+
43
+ # Public: A flag stating that this is not the home page.
44
+ def is_not_home?
45
+ page.title != "Home"
46
+ end
47
+
48
+ # Public: The HTML menu generated from the settings.yaml file.
49
+ def menu_html
50
+ menu = @page.wiki.settings.menu
51
+ if !menu.nil?
52
+ html = "<ul>\n"
53
+ menu.each do |item|
54
+ html << "<li><a href=\"#{item.href}\">#{item.title}</a></li>\n"
55
+ end
56
+ html << "</ul>\n"
57
+ end
58
+ end
59
+
60
+
61
+ ##########################################################################
62
+ #
63
+ # Internal Methods
64
+ #
65
+ ##########################################################################
66
+
67
+ private
68
+
69
+ # The Gollum::Page that this view represents.
70
+ attr_reader :page
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,30 @@
1
+ require 'gollum'
2
+ require 'ostruct'
3
+ require 'yaml'
4
+
5
+ module Smeagol
6
+ class Wiki < Gollum::Wiki
7
+ ##############################################################################
8
+ #
9
+ # Settings
10
+ #
11
+ ##############################################################################
12
+
13
+ # The Smeagol wiki settings. These can be found in the smeagol.yaml file at
14
+ # the root of the repository.
15
+ #
16
+ # Returns an OpenStruct of settings.
17
+ def settings
18
+ # Cache settings if already read
19
+ if @settings.nil?
20
+ file = "#{path}/settings.yaml"
21
+ if File.readable?(file)
22
+ @settings = YAML::load(IO.read(file)).to_ostruct
23
+ else
24
+ @settings = OpenStruct.new
25
+ end
26
+ end
27
+ return @settings
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,13 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+ require 'minitest/autorun'
4
+ require 'mocha'
5
+
6
+ $:.unshift(File.dirname(__FILE__))
7
+ require File.expand_path(File.dirname(__FILE__) + '/../lib/smeagol')
8
+
9
+ # Stop test if test wiki path is not set
10
+ if !ENV.has_key?('SMEAGOL_TEST_WIKI_PATH')
11
+ puts 'You must set SMEAGOL_TEST_WIKI_PATH in your environment to run the tests.'
12
+ exit(1);
13
+ end
@@ -0,0 +1,18 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class HashTestCase < MiniTest::Unit::TestCase
4
+ def test_create_ostruct_root_copy
5
+ hash = {:a => 1}
6
+ assert_kind_of OpenStruct, hash.to_ostruct
7
+ end
8
+
9
+ def test_should_create_deep_copy_hashes
10
+ hash = {:a => 1, :b => {:c => 2}}
11
+ assert_kind_of OpenStruct, hash.to_ostruct.b
12
+ end
13
+
14
+ def test_should_create_deep_copy_arrays
15
+ hash = {:a => 1, :b => [{:c => 2}]}
16
+ assert_kind_of OpenStruct, hash.to_ostruct.b[0]
17
+ end
18
+ end
@@ -0,0 +1,15 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class WikiTestCase < MiniTest::Unit::TestCase
4
+ def setup
5
+ @wiki = Smeagol::Wiki.new(ENV['SMEAGOL_TEST_WIKI_PATH'])
6
+ end
7
+
8
+ def test_settings_should_be_open_struct
9
+ assert_kind_of OpenStruct, @wiki.settings
10
+ end
11
+
12
+ def test_settings_should_be_read_from_file
13
+ assert_equal 'Smeagol', @wiki.settings.title
14
+ end
15
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: smeagol
3
3
  version: !ruby/object:Gem::Version
4
- hash: 25
4
+ hash: 23
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 1
9
- - 1
10
- version: 0.1.1
8
+ - 2
9
+ - 0
10
+ version: 0.2.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Ben Johnson
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-09-20 00:00:00 -06:00
18
+ date: 2010-09-23 00:00:00 -06:00
19
19
  default_executable: smeagol
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -159,6 +159,38 @@ dependencies:
159
159
  prerelease: false
160
160
  - !ruby/object:Gem::Dependency
161
161
  version_requirements: &id010 !ruby/object:Gem::Requirement
162
+ none: false
163
+ requirements:
164
+ - - ~>
165
+ - !ruby/object:Gem::Version
166
+ hash: 11
167
+ segments:
168
+ - 1
169
+ - 7
170
+ - 0
171
+ version: 1.7.0
172
+ requirement: *id010
173
+ type: :development
174
+ name: minitest
175
+ prerelease: false
176
+ - !ruby/object:Gem::Dependency
177
+ version_requirements: &id011 !ruby/object:Gem::Requirement
178
+ none: false
179
+ requirements:
180
+ - - ~>
181
+ - !ruby/object:Gem::Version
182
+ hash: 43
183
+ segments:
184
+ - 0
185
+ - 9
186
+ - 8
187
+ version: 0.9.8
188
+ requirement: *id011
189
+ type: :development
190
+ name: mocha
191
+ prerelease: false
192
+ - !ruby/object:Gem::Dependency
193
+ version_requirements: &id012 !ruby/object:Gem::Requirement
162
194
  none: false
163
195
  requirements:
164
196
  - - ~>
@@ -169,12 +201,12 @@ dependencies:
169
201
  - 8
170
202
  - 5
171
203
  version: 0.8.5
172
- requirement: *id010
204
+ requirement: *id012
173
205
  type: :development
174
206
  name: cucumber
175
207
  prerelease: false
176
208
  - !ruby/object:Gem::Dependency
177
- version_requirements: &id011 !ruby/object:Gem::Requirement
209
+ version_requirements: &id013 !ruby/object:Gem::Requirement
178
210
  none: false
179
211
  requirements:
180
212
  - - ~>
@@ -185,12 +217,12 @@ dependencies:
185
217
  - 3
186
218
  - 0
187
219
  version: 1.3.0
188
- requirement: *id011
220
+ requirement: *id013
189
221
  type: :development
190
222
  name: rspec
191
223
  prerelease: false
192
224
  - !ruby/object:Gem::Dependency
193
- version_requirements: &id012 !ruby/object:Gem::Requirement
225
+ version_requirements: &id014 !ruby/object:Gem::Requirement
194
226
  none: false
195
227
  requirements:
196
228
  - - ~>
@@ -201,7 +233,7 @@ dependencies:
201
233
  - 3
202
234
  - 9
203
235
  version: 0.3.9
204
- requirement: *id012
236
+ requirement: *id014
205
237
  type: :development
206
238
  name: capybara
207
239
  prerelease: false
@@ -216,13 +248,19 @@ extra_rdoc_files: []
216
248
 
217
249
  files:
218
250
  - lib/smeagol/app.rb
251
+ - lib/smeagol/hash.rb
219
252
  - lib/smeagol/public/smeagol/main.css
220
253
  - lib/smeagol/public/smeagol/pygment.css
221
254
  - lib/smeagol/templates/page.mustache
222
255
  - lib/smeagol/updater.rb
223
256
  - lib/smeagol/version.rb
257
+ - lib/smeagol/views/page.rb
258
+ - lib/smeagol/wiki.rb
224
259
  - lib/smeagol.rb
225
260
  - README.md
261
+ - test/helper.rb
262
+ - test/test_hash.rb
263
+ - test/test_wiki.rb
226
264
  - bin/smeagol
227
265
  has_rdoc: true
228
266
  homepage: http://smeagolrb.info
@@ -258,5 +296,7 @@ rubygems_version: 1.3.7
258
296
  signing_key:
259
297
  specification_version: 3
260
298
  summary: A read-only server for Gollum wikis
261
- test_files: []
262
-
299
+ test_files:
300
+ - test/helper.rb
301
+ - test/test_hash.rb
302
+ - test/test_wiki.rb