jadof 0.1.0

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