smeagol 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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