jadof 0.1.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/lib/jadof/page.rb ADDED
@@ -0,0 +1,250 @@
1
+ module JADOF #:nodoc:
2
+
3
+ # This is the class interface for {Page}.
4
+ #
5
+ # This is split out into a separate module so we can
6
+ # extend other classes (that inherit from Page) with
7
+ # this.
8
+ #
9
+ # Actually, if you inherit from Page, you automatically
10
+ # get this module extended into your class.
11
+ module PageAPI
12
+
13
+ # @return [String] The root directory that pages are loaded from. Defaults to "./pages/"
14
+ attr_accessor :dir
15
+
16
+ attr_accessor :formatters
17
+
18
+ # This can be set to a standard cache object and, if it is set,
19
+ # all pages will be cached so they don't have to be re-opened
20
+ # and we don't have to look for the files.
21
+ #
22
+ # Any cache object that supports these standard methods is supported:
23
+ #
24
+ # get(key)
25
+ # set(key, value)
26
+ # clear
27
+ #
28
+ # @return [#get, #set, #clear]
29
+ attr_accessor :cache
30
+
31
+ def dir
32
+ @dir ||= File.expand_path DEFAULT_DIR
33
+ end
34
+
35
+ # When dir is set, we save it as an expanded path.
36
+ # We also clear the cache (if it's enabled)
37
+ def dir= value
38
+ cache.clear if cache
39
+ @dir = File.expand_path value
40
+ end
41
+
42
+ # A Hash of available formatters. The key is used to match
43
+ # a given file extension and the value should be something
44
+ # that you can #call (like a lambda) with text which returns
45
+ # the formatted text.
46
+ # @return [Hash{String => #call}]
47
+ def formatters
48
+ @formatters ||= DEFAULT_FORMATTERS
49
+ end
50
+
51
+ # @return [Page] Get a Page by name
52
+ def get name
53
+ first :full_name => name.to_s
54
+ end
55
+
56
+ # @return [Page] Alias for Page.get
57
+ def [] name
58
+ get name
59
+ end
60
+
61
+ # @return [Array(Page)] Get all Pages in Page.dir
62
+ def all
63
+ cache_for 'all' do
64
+ Dir[ File.join(dir, "**/*") ].reject {|path| File.directory?(path) }.map {|path| from_path(path) }
65
+ end
66
+ end
67
+
68
+ # @return [Fixnum] Returns the count of all Pages
69
+ def count
70
+ all.length
71
+ end
72
+
73
+ # @return [Page, nil] Returns the last Page
74
+ def last
75
+ all.last
76
+ end
77
+
78
+ # @return [Array(Page)] Gets pages given some simple conditions (only == equality is supported)
79
+ def where conditions
80
+ all.select { |page| matches_conditions? page, conditions }
81
+ end
82
+
83
+ # @return [Page, nil] Gets a page given some simple conditions
84
+ def first conditions = nil
85
+ if conditions
86
+ all.find { |page| matches_conditions? page, conditions }
87
+ else
88
+ all.first
89
+ end
90
+ end
91
+
92
+ # @return [Page] Loads a Page from a given path to a file
93
+ def from_path path
94
+ path = File.expand_path path
95
+ filename = File.basename path
96
+ name = filename[/^[^\.]+/] # get everything before a .
97
+ body = File.read path
98
+
99
+ # Remove YAML from top of body and get the YAML variables from it.
100
+ # Then we can merge in the name, path, etc, and use it to inialize a page
101
+ body.sub! /^---(.*)\n---\n/m, ''
102
+ variables = $1 ? YAML.load($1) : {}
103
+ variables.merge! :name => name, :path => path, :filename => filename, :body => body
104
+
105
+ # If the file is in a subdirectory, get the name of the subdirectory[ies]
106
+ # and set it as :parent, so it's easily accessible from the Page.
107
+ # Also, we strip the first and last '/' characters off of it.
108
+ variables[:parent] = File.dirname(path).sub(dir, '').sub(/^\//, '')
109
+
110
+ new variables
111
+ end
112
+
113
+ # @return [String] Using the #filename of the page given and available
114
+ # Page.formatters, we render and return the page #body.
115
+ def to_html page
116
+ html = page.body
117
+
118
+ page.filename.scan(/\.([^\.]+)/).reverse.each do |match| # [ ["markdown"], ["erb"] ]
119
+ if formatter = formatters[ match.first ]
120
+ html = formatter.call(html)
121
+ end
122
+ end
123
+
124
+ html
125
+ end
126
+
127
+ # @private
128
+ # Helper for caching. Will check to see if the {Page.cache}
129
+ # contains the given key and, if not, it will set the cache by calling
130
+ # the block given
131
+ def cache_for key, &block
132
+ return block.call unless cache
133
+
134
+ from_cache = cache.get(key)
135
+ unless from_cache
136
+ from_cache = block.call
137
+ cache.set(key, from_cache)
138
+ end
139
+ from_cache
140
+ end
141
+
142
+ # @private
143
+ # @return [true, false] Helper for #where and #first
144
+ def matches_conditions? page, conditions
145
+ matches = true
146
+ conditions.each {|k,v| matches = false unless page.send(k) == v }
147
+ matches
148
+ end
149
+
150
+ # @private
151
+ # When a class inheritcs from Page (or from any class that inherits page),
152
+ # we extend that class with {PageAPI} so it will get methods like `Page.all`.
153
+ def inherited base
154
+ base.extend PageAPI
155
+ end
156
+ end
157
+
158
+ # A {Page} wraps a file on the filesystem.
159
+ #
160
+ # If you set `Page.dir` to a directory, `Page.all` will
161
+ # give you all of the files inside that directory as {Page}
162
+ # objects.
163
+ #
164
+ # For all of the available class methods, see {PageAPI}.
165
+ #
166
+ class Page
167
+ extend PageAPI
168
+ include IndifferentVariableHash
169
+
170
+ DEFAULT_DIR = './pages/'
171
+
172
+ DEFAULT_FORMATTERS = {
173
+ 'markdown' => lambda { |text| require 'maruku'; Maruku.new(text).to_html },
174
+ 'erb' => lambda { |text| require 'erb'; ERB.new(text).result }
175
+ }
176
+
177
+ # @return [String] A simple name for this {Page}.
178
+ #
179
+ # If the filename is `foo.markdown`, the name will be `foo`
180
+ #
181
+ # If the file is in a subdirectory below `Page.dir`, eg.
182
+ # `foo/bar.markdown`, the name will be `bar` but the
183
+ # #full_name will be `foo/bar`.
184
+ attr_accessor :name
185
+
186
+ # @return [String] The full system path to this file
187
+ attr_accessor :path
188
+
189
+ # @return [String] The filename (without a directory), eg. `foo.markdown`
190
+ attr_accessor :filename
191
+
192
+ # @return [String] The body of the file, *without* the YAML at
193
+ # the top of the file (if YAML was included).
194
+ #
195
+ # We strip out the YAML and use it to set variables on
196
+ # the Page. If you need the *full* text from the file,
197
+ # you should `File.read(@page.path)`.
198
+ attr_accessor :body
199
+
200
+ # @return [String] The parent directory of this file, if this file is
201
+ # in a subdirectory below `Page.dir`. This will be `""` if
202
+ # it is in `Page.dir` or it will be `"sub/directories"` if
203
+ # it is in subdirectories.
204
+ attr_accessor :parent
205
+
206
+ # A page is a dumb object and doesn't know how to load itself from
207
+ # a file on the filesystem. See `Page.from_path` to load a {Page}
208
+ # from a file.
209
+ #
210
+ # @param [Hash] of attributes
211
+ def initialize options = nil
212
+ options.each {|attribute, value| send "#{attribute}=", value } if options
213
+ end
214
+
215
+ # @return [String] combines {#name} with {#parent}
216
+ def full_name
217
+ parent == '' ? name : File.join(parent, name)
218
+ end
219
+
220
+ # Returns the formatted {#body} of this {Page} using `Page.formatters`.
221
+ #
222
+ # The file extensions from the {#filename} are used to match formatters.
223
+ #
224
+ # For `foo.markdown`, `Page.formatters['markdown']` will be used.
225
+ # For `foo.markdown.erb`, `Page.formatters['erb']` and `Page.formatters['markdown']` will be used.
226
+ #
227
+ # With multiple extensions, the *last* extension is used first, and then the second-to-last, etc.
228
+ def to_html
229
+ self.class.to_html self
230
+ end
231
+
232
+ # @return [true, false] If 2 pages have the same system path, they're the same.
233
+ def == other_page
234
+ return false unless other_page.is_a? Page
235
+ return other_page.path == path
236
+ end
237
+
238
+ # @return [String] This page as a string. Defaults to {#full_name}.
239
+ def to_s
240
+ full_name
241
+ end
242
+
243
+ # @return [String] A param representation of this page for us in web applications. Defaults to {#full_name}.
244
+ def to_param
245
+ full_name
246
+ end
247
+
248
+ end
249
+
250
+ end
data/lib/jadof/post.rb ADDED
@@ -0,0 +1,26 @@
1
+ require 'time'
2
+
3
+ module JADOF #:nodoc:
4
+
5
+ # Represents a blog post. Has the same functionality as {Page}
6
+ # but with a {#date} added (which makes {#to_param}) include
7
+ # a date, in the conventional way: `2010/01/31/name-of-post`
8
+ class Post < Page
9
+
10
+ # @return [Time] the date that this post was created.
11
+ # If a [String] is passed in, it will be parsed as a time.
12
+ attr_accessor :date
13
+
14
+ def date= value
15
+ @date = Time.parse value.to_s
16
+ end
17
+
18
+ # @return [String] The conventional way to display blog
19
+ # post urls, eg. `2010/01/31/name-of-post`
20
+ def to_param
21
+ date ? "#{ date.strftime('%Y/%m/%d') }/#{ full_name }" : super
22
+ end
23
+
24
+ end
25
+
26
+ end
@@ -0,0 +1,324 @@
1
+ shared_examples_for "JADOF Page" do
2
+
3
+ describe ':: Behaves like JADOF Page' do
4
+
5
+ before do
6
+ @jadof_page_class ||= JADOF::Page # override this in your specs to test a different class!
7
+
8
+ @root_page_directory ||= './jadof_spec_pages/'
9
+ @jadof_page_class.dir = File.join(@root_page_directory, 'pages')
10
+ delete_root_page_directory
11
+ end
12
+
13
+ after :all do
14
+ delete_root_page_directory
15
+ end
16
+
17
+ it '#create_page works as expected for creating fake pages for these specs' do
18
+ path = File.join(@jadof_page_class.dir, '/foo.markdown')
19
+ File.file?(path).should be_false
20
+
21
+ create_page 'foo.markdown'
22
+
23
+ File.file?(path).should be_true
24
+ @jadof_page_class[:foo].body.should == ''
25
+
26
+ create_page 'foo.markdown', %{
27
+ it should fix
28
+ the spaces
29
+ for me
30
+ }
31
+
32
+ @jadof_page_class[:foo].body.should == "it should fix\n the spaces\nfor me"
33
+ end
34
+
35
+ it 'can set the @jadof_page_class.dir to specify the directory to fetch pages from' do
36
+ dir1, dir2 = @jadof_page_class.dir, File.join(@root_page_directory, '/more_pages')
37
+
38
+ create_page 'foo.markdown', 'hello world', dir1
39
+ create_page 'bar.markdown', 'hello world', dir2
40
+
41
+ @jadof_page_class[:foo].should_not be_nil
42
+ @jadof_page_class[:bar].should be_nil
43
+
44
+ @jadof_page_class.dir = dir2
45
+
46
+ @jadof_page_class[:foo].should be_nil
47
+ @jadof_page_class[:bar].should_not be_nil
48
+ end
49
+
50
+ it 'has a filename (the actual filename, without a path)' do
51
+ create_page 'foo.markdown'
52
+
53
+ @jadof_page_class[:foo].should_not be_nil
54
+ @jadof_page_class[:foo].filename.should == 'foo.markdown'
55
+ end
56
+
57
+ it 'has a path (the full system path to the file)' do
58
+ create_page 'foo.markdown'
59
+
60
+ @jadof_page_class[:foo].should_not be_nil
61
+ @jadof_page_class[:foo].path.should == File.expand_path(File.join(@jadof_page_class.dir, '/foo.markdown'))
62
+ end
63
+
64
+ it 'has a name (the name of the file, without extensions)' do
65
+ create_page 'foo.markdown'
66
+
67
+ @jadof_page_class[:foo].should_not be_nil
68
+ @jadof_page_class[:foo].name.should == 'foo'
69
+ end
70
+
71
+ it 'has a body (the content of the file)' do
72
+ create_page 'foo.markdown'
73
+ @jadof_page_class[:foo].body.should == ''
74
+
75
+ create_page 'foo.markdown', %{
76
+ Hello World!
77
+ }
78
+
79
+ @jadof_page_class[:foo].body.strip.should == 'Hello World!'
80
+ end
81
+
82
+ it 'can return all pages' do
83
+ @jadof_page_class.count.should == 0
84
+ @jadof_page_class.all.length.should == 0
85
+
86
+ create_page 'foo.markdown'
87
+
88
+ @jadof_page_class.count.should == 1
89
+ @jadof_page_class.all.length.should == 1
90
+ end
91
+
92
+ it 'can return #first and #last page' do
93
+ create_page 'foo.markdown'
94
+ create_page 'bar.markdown'
95
+
96
+ @jadof_page_class.first.should == @jadof_page_class.all.first
97
+ @jadof_page_class.last.should == @jadof_page_class.all.last
98
+
99
+ @jadof_page_class.first.should_not == @jadof_page_class.last
100
+ end
101
+
102
+ it 'can get a page by name' do
103
+ @jadof_page_class.get(:foo).should be_nil
104
+ @jadof_page_class[:foo].should be_nil
105
+
106
+ create_page 'foo.markdown'
107
+
108
+ @jadof_page_class.get(:foo).should_not be_nil
109
+ @jadof_page_class[:foo].should_not be_nil
110
+ end
111
+
112
+ it 'supports 1 level of sub-directories' do
113
+ create_page 'hi.markdown'
114
+ @jadof_page_class['hi'].parent.should == ''
115
+
116
+ create_page 'foo/bar.markdown'
117
+
118
+ @jadof_page_class['foo/bar'].name.should == 'bar'
119
+ @jadof_page_class['foo/bar'].full_name.should == 'foo/bar'
120
+ @jadof_page_class['foo/bar'].parent.should == 'foo'
121
+ @jadof_page_class['foo/bar'].filename.should == 'bar.markdown'
122
+ @jadof_page_class['foo/bar'].path.should include('foo/bar.markdown')
123
+
124
+ @jadof_page_class.first(:name => 'bar').name.should == 'bar'
125
+ @jadof_page_class.first(:name => 'bar').filename.should == 'bar.markdown'
126
+ @jadof_page_class.first(:name => 'bar').path.should include('foo/bar.markdown')
127
+ end
128
+
129
+ it 'supports n levels of sub-directories' do
130
+ create_page 'foo/bar/hello/there/crazy/person-123.markdown'
131
+
132
+ @jadof_page_class['foo/bar/hello/there/crazy/person-123'].name.should == 'person-123'
133
+ @jadof_page_class['foo/bar/hello/there/crazy/person-123'].full_name.should == 'foo/bar/hello/there/crazy/person-123'
134
+ @jadof_page_class['foo/bar/hello/there/crazy/person-123'].parent.should == 'foo/bar/hello/there/crazy'
135
+ @jadof_page_class['foo/bar/hello/there/crazy/person-123'].filename.should == 'person-123.markdown'
136
+ @jadof_page_class['foo/bar/hello/there/crazy/person-123'].path.should include('/crazy/person-123.markdown')
137
+
138
+ @jadof_page_class.first(:name => 'person-123').name.should == 'person-123'
139
+ @jadof_page_class.first(:name => 'person-123').filename.should == 'person-123.markdown'
140
+ @jadof_page_class.first(:name => 'person-123').path.should include('/crazy/person-123.markdown')
141
+ end
142
+
143
+ it 'implements #to_s (defaults to #full_name)' do
144
+ create_page 'hi.markdown'
145
+ create_page 'foo/bar/hello/there/crazy/person-123.markdown'
146
+
147
+ @jadof_page_class[:hi].to_s.should == 'hi'
148
+ @jadof_page_class.first(:name => 'person-123').to_s.should == 'foo/bar/hello/there/crazy/person-123'
149
+ end
150
+
151
+ it 'implements #to_param (defaults to #full_name)' do
152
+ create_page 'hi.markdown'
153
+ create_page 'foo/bar/hello/there/crazy/person-123.markdown'
154
+
155
+ @jadof_page_class[:hi].to_param.should == 'hi'
156
+ @jadof_page_class.first(:name => 'person-123').to_param.should == 'foo/bar/hello/there/crazy/person-123'
157
+ end
158
+
159
+ describe ':: YAML header' do
160
+
161
+ it 'can add any kind of arbitrary data to a page via YAML' do
162
+ create_page 'foo.markdown'
163
+ @jadof_page_class[:foo].foo.should be_nil # @jadof_page_class's don't raise NoMethodError's
164
+
165
+ create_page 'foo.markdown', %{
166
+ ---
167
+ foo: bar
168
+ ---
169
+ Hello World!
170
+ }
171
+
172
+ @jadof_page_class[:foo].foo.should == 'bar' # got value from YAML
173
+ end
174
+
175
+ it 'can get a page by the value of any arbitrary data (from the YAML)' do
176
+ create_page 'foo.markdown', %{
177
+ ---
178
+ foo: bar
179
+ ---
180
+ Hello World!
181
+ }
182
+
183
+ @jadof_page_class.first(:foo => 'not bar').should be_nil
184
+ @jadof_page_class.first(:foo => 'bar' ).should_not be_nil
185
+ @jadof_page_class.first(:foo => 'bar' ).foo.should == 'bar'
186
+ end
187
+
188
+ it 'can get a page by *multiple* arbitrary conditions' do
189
+ create_page 'foo.markdown', %{
190
+ ---
191
+ foo: bar
192
+ ---
193
+ Hello World!
194
+ }
195
+
196
+ @jadof_page_class.where(:foo => 'bar', :name => 'not foo').should be_empty
197
+ @jadof_page_class.where(:foo => 'not bar', :name => 'foo').should be_empty
198
+ @jadof_page_class.where(:foo => 'bar', :name => 'foo').should_not be_empty
199
+ @jadof_page_class.where(:foo => 'bar', :name => 'foo').first.name.should == 'foo'
200
+ end
201
+
202
+ end
203
+
204
+ describe ':: Rendering' do
205
+
206
+ before do
207
+ @jadof_page_class.formatters = {}
208
+ end
209
+
210
+ it 'should render plain text if formatter not found for file extension' do
211
+ create_page 'foo.markdown', %{
212
+ **Hello World!**
213
+ }
214
+
215
+ @jadof_page_class[:foo].to_html.should == '**Hello World!**'
216
+ end
217
+
218
+ it 'should render using formatter if found for file extension' do
219
+ @jadof_page_class.formatters['markdown'] = lambda {|text| Maruku.new(text).to_html }
220
+
221
+ create_page 'foo.markdown', %{
222
+ **Hello World!**
223
+ }
224
+
225
+ @jadof_page_class[:foo].to_html.should == '<p><strong>Hello World!</strong></p>'
226
+ end
227
+
228
+ it 'should support multiple file extensions, eg. foo.markdown.erb (erb renders first, then markdown)' do
229
+ @jadof_page_class.formatters['markdown'] = lambda {|text| Maruku.new(text).to_html }
230
+
231
+ create_page 'foo.markdown.erb', %{
232
+ <%= '*' * 2 %>Hello World!<%= '*' * 2 %>
233
+ }
234
+
235
+ @jadof_page_class[:foo].to_html.should ==
236
+ '<p>&lt;%= &#8217;<em>&#8217;</em> 2 %&gt;Hello World!&lt;%= &#8217;<em>&#8217;</em> 2 %&gt;</p>'
237
+
238
+
239
+ @jadof_page_class.formatters['erb'] = lambda {|text| ERB.new(text).result }
240
+ @jadof_page_class[:foo].to_html.should == '<p><strong>Hello World!</strong></p>'
241
+ end
242
+
243
+ it 'should have markdown and erb out of the box' do
244
+ create_page 'foo.markdown.erb', %{
245
+ <%= '*' * 2 %>Hello World!<%= '*' * 2 %>
246
+ }
247
+
248
+ @jadof_page_class.formatters = @jadof_page_class::DEFAULT_FORMATTERS
249
+ @jadof_page_class[:foo].to_html.should == '<p><strong>Hello World!</strong></p>'
250
+ end
251
+
252
+ end
253
+
254
+ describe ':: Caching' do
255
+
256
+ before do
257
+ @jadof_page_class.cache = Hash::Cache.new # Hash that has #get(k) and #set(k,v) methods and #clear
258
+ end
259
+
260
+ it 'with the cache enabled, files should only be #read once' do
261
+ create_page 'foo.markdown'
262
+ path = File.join @jadof_page_class.dir, 'foo.markdown'
263
+
264
+ File.should_receive(:read).with(File.expand_path(path)).once.and_return('') # only once!
265
+
266
+ @jadof_page_class[:foo]
267
+ @jadof_page_class[:foo]
268
+ end
269
+
270
+ it 'with the cache enabled, Dir[] should only look for files once' do
271
+ create_page 'foo.markdown'
272
+ create_page 'bar.markdown'
273
+
274
+ dir = @root_page_directory
275
+ Dir.should_receive(:[]).once.and_return([File.join(dir, '/pages/bar.markdown'), File.join(dir, '/pages/foo.markdown')])
276
+ File.should_receive(:read).twice.and_return('')
277
+
278
+ @jadof_page_class.all
279
+ @jadof_page_class.all # calls everyhing again if caching is disabled (@jadof_page_class.cache is nil or false)
280
+ end
281
+
282
+ it 'with the cache disabled, Dir[] should only look for files more than once' do
283
+ @jadof_page_class.cache = false
284
+
285
+ create_page 'foo.markdown'
286
+ create_page 'bar.markdown'
287
+
288
+ dir = @root_page_directory
289
+ Dir.should_receive(:[]).twice.and_return([File.join(dir, '/pages/bar.markdown'), File.join(dir, '/pages/foo.markdown')])
290
+ File.should_receive(:read).exactly(4).times.and_return('')
291
+
292
+ @jadof_page_class.all
293
+ @jadof_page_class.all # calls everyhing again if caching is disabled (@jadof_page_class.cache is nil or false)
294
+ end
295
+
296
+ it 'should be able to clear the cache' do
297
+ @jadof_page_class.cache.get('all').should be_nil
298
+ @jadof_page_class.all
299
+ @jadof_page_class.cache.get('all').should_not be_nil
300
+
301
+ @jadof_page_class.cache.clear
302
+
303
+ @jadof_page_class.cache.get('all').should be_nil
304
+ @jadof_page_class.all
305
+ @jadof_page_class.cache.get('all').should_not be_nil
306
+ end
307
+
308
+ it 'should clear the cache when the @jadof_page_class.dir is changed' do
309
+ @jadof_page_class.cache.get('all').should be_nil
310
+ @jadof_page_class.all
311
+ @jadof_page_class.cache.get('all').should_not be_nil
312
+
313
+ @jadof_page_class.dir = File.join(@root_page_directory, 'different-directory')
314
+
315
+ @jadof_page_class.cache.get('all').should be_nil
316
+ @jadof_page_class.all
317
+ @jadof_page_class.cache.get('all').should_not be_nil
318
+ end
319
+
320
+ end
321
+
322
+ end
323
+
324
+ end
@@ -0,0 +1,33 @@
1
+ shared_examples_for "JADOF Post" do
2
+
3
+ describe ':: Behaves like JADOF Post' do
4
+
5
+ before do
6
+ @jadof_post_class ||= JADOF::Post # override this in your specs to test a different class!
7
+
8
+ @root_page_directory ||= './jadof_spec_pages/'
9
+ @jadof_post_class.dir = File.join(@root_page_directory, 'posts')
10
+ delete_root_page_directory
11
+ end
12
+
13
+ after :all do
14
+ delete_root_page_directory
15
+ end
16
+
17
+ it 'it should have a date (which is used in to_param)' do
18
+ create_page 'foo.markdown', %{
19
+ ---
20
+ date: 01/31/2010
21
+ ---
22
+
23
+ hello world
24
+ }, @jadof_post_class.dir
25
+
26
+ @jadof_post_class.first.name.should == 'foo'
27
+ @jadof_post_class.first.to_s.should == 'foo'
28
+ @jadof_post_class.first.to_param.should == '2010/01/31/foo'
29
+ end
30
+
31
+ end
32
+
33
+ end
@@ -0,0 +1,34 @@
1
+ # Helper for creating page files in the specs, at spec/pages/
2
+ #
3
+ # create_page 'foo.markdown'
4
+ #
5
+ # create_page 'foo.markdown', %{
6
+ # This is the body
7
+ # of the page that will
8
+ # be created.
9
+ # }
10
+ #
11
+ # create_page 'foo.markdown', 'body', './directory/to/create/page/in/'
12
+ #
13
+ def create_page filename, body = '', page_dir = @jadof_page_class.dir
14
+ body.sub!("\n", '') if body.lines.first == "\n" # get rid of first empty line
15
+ body.sub!(/\n\s+$/, '') if body.lines.count > 0 # get rid of last empty line
16
+
17
+ # grab the spaces (if any) from the 1st line and remove that
18
+ # many spaces from the rest of the lines so our specs look clean
19
+ if body.lines.first
20
+ spaces = body.lines.first[/^[ ]+/]
21
+ body.gsub!(/^#{spaces}/, '') if spaces
22
+ end
23
+
24
+ body ||= '' # if it's nil for some reason, make it an empty string
25
+
26
+ path = File.join(page_dir, filename)
27
+ FileUtils.mkdir_p File.dirname(path)
28
+ File.open(path, 'w'){|f| f << body }
29
+ end
30
+
31
+ # Deletes the root directory that we create pages in
32
+ def delete_root_page_directory
33
+ FileUtils.rm_rf @root_page_directory
34
+ end
data/lib/jadof/spec.rb ADDED
@@ -0,0 +1,32 @@
1
+ # If you want to extend JADOF, you'll probably want to
2
+ # create specs to make sure that your functionality works.
3
+ #
4
+ # You'll probably also want to run the JADOF specs, as
5
+ # regression tests, so you know if you break any of the
6
+ # core functionality.
7
+ #
8
+ # For that, we use RSpec shared examples so, in your specs,
9
+ # you can require 'jadof/test' and then add this to your specs:
10
+ #
11
+ # it_should_behave_like "JADOF Page"
12
+ #
13
+ # The shared examples use a few instance variables which you
14
+ # can override.
15
+ #
16
+ # @root_page_directory
17
+ # : the directory to save fake pages in while the
18
+ # tests run. these are cleaned up by the tests.
19
+ # default: './jadof_spec_pages/'. we delete this
20
+ # directory when running specs do don't use a
21
+ # directory with things you care about!
22
+ #
23
+ require 'rubygems'
24
+ require 'spec'
25
+ require 'fileutils' # for creating/deleting directories for fake pages
26
+ require 'hash-cache' # for testing caching
27
+ require 'maruku' # for testing rendering
28
+ require 'erb' # for testing rendering
29
+ require File.dirname(__FILE__) + '/../jadof' unless defined? JADOF
30
+ require File.dirname(__FILE__) + '/spec/helpers'
31
+ require File.dirname(__FILE__) + '/spec/examples_for_page'
32
+ require File.dirname(__FILE__) + '/spec/examples_for_post'
data/lib/jadof.rb ADDED
@@ -0,0 +1,13 @@
1
+ $LOAD_PATH.unshift File.dirname(__FILE__)
2
+
3
+ require 'indifferent-variable-hash'
4
+
5
+ # Just A Directory Of Files
6
+ #
7
+ # See {JADOF::Page} and {JADOF::Post}
8
+ #
9
+ module JADOF
10
+ end
11
+
12
+ require 'jadof/page'
13
+ require 'jadof/post'
metadata ADDED
@@ -0,0 +1,61 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jadof
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - remi
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-01-10 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description:
17
+ email: remi@remitaylor.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files: []
23
+
24
+ files:
25
+ - lib/jadof/spec/examples_for_post.rb
26
+ - lib/jadof/spec/examples_for_page.rb
27
+ - lib/jadof/spec/helpers.rb
28
+ - lib/jadof/post.rb
29
+ - lib/jadof/spec.rb
30
+ - lib/jadof/page.rb
31
+ - lib/jadof.rb
32
+ has_rdoc: true
33
+ homepage: http://github.com/remi/jadof
34
+ licenses: []
35
+
36
+ post_install_message:
37
+ rdoc_options: []
38
+
39
+ require_paths:
40
+ - lib
41
+ required_ruby_version: !ruby/object:Gem::Requirement
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ version: "0"
46
+ version:
47
+ required_rubygems_version: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ version: "0"
52
+ version:
53
+ requirements: []
54
+
55
+ rubyforge_project:
56
+ rubygems_version: 1.3.5
57
+ signing_key:
58
+ specification_version: 3
59
+ summary: Just A Directory Of Files (JADOF)
60
+ test_files: []
61
+