spandex 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,12 @@
1
+ .bundle
2
+ db/*.sqlite3
3
+ log/*.log
4
+ tmp/**/*
5
+ *~
6
+ *flymake*
7
+ *#
8
+ #*
9
+ .#*
10
+ bin/**
11
+ .sass-cache/**
12
+ Gemfile.lock
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gemspec
data/README.md ADDED
@@ -0,0 +1,85 @@
1
+ #Spandex is a simple content engine for Ruby, made chiefly from orangutan fur#
2
+
3
+ Spandex manages a bucket of text files written in your favorite markup (Markdown, Textile, or even Haml). You mark those files up with metadata (like date and tags), and Spandex gives you access to them. This is perfect for building a simple git-based blog or content site.
4
+
5
+ Spandex is largely extracted from [Nesta](http://nestacms.com/), a Ruby CMS. The markup is rendered using [Tilt](http://github.com/rtomayko/tilt).
6
+
7
+ ##It's super freaking easy##
8
+
9
+ Make a directory called "content".
10
+
11
+ In that directory, create a file called `things.md`:
12
+
13
+ ```
14
+ Title: I have an affinity for goats
15
+ Date: 2011/9/25
16
+ Tags: gerrymandering, hyperbolic geometry
17
+
18
+ No, really goats are *awesome*.
19
+ ```
20
+
21
+ Then use Spandex to do the work:
22
+
23
+ ```ruby
24
+ spandex = Spandex.new(File.expand_path('content', File.dirname(__FILE__))
25
+
26
+ page = spandex.get('things')
27
+ page.title #=> "I have an affinity for goats"
28
+ page.tags #=> ["gerrymandering", "hyperbolic geometry"]
29
+ page.body #=> <p>No, really goats are <em>awesome</em>.</p>\n
30
+
31
+ spandex.all_pages #=> all pages under content
32
+ spandex.all_articles #=> all pages with dates (e.g. blog posts)
33
+ spandex.tags #=> ["gerrymandering", "hyperbolic geometry"]
34
+ spandex.atom_feed #=> a bunch of XML, only finds posts with dates
35
+
36
+ spandex.find_articles(:tag => "gerrymandering")
37
+ ```
38
+
39
+ The spandex object caches the pages and does all of the right last-mod-time checking. Your application should just keep the object around.
40
+
41
+ ##Build things!##
42
+
43
+ Blog engines are great, and there are, like, three thousand of them. Sometimes, though, you just want to build a website with the tools you know. Spandex lets you do that while taking care of all the grody work of keeping track of posts. A barebones example of a Spandex-based blog is the [tinyblogofdoom](http://github.com/icambron/tinyblogofdoom).
44
+
45
+ But wait! There's more! Spandex can also implement the core functionality for a blog engine or CMS. Spandex brings the post rendering and you bring the themes, UI chrome, and plugins.
46
+
47
+ ##Some more cool stuff##
48
+
49
+ Paths can be deep:
50
+
51
+ ```ruby
52
+ page = spandex.get('subfolder/deeper/things')
53
+ ```
54
+
55
+ You can pass options through to Tilt at initialization:
56
+
57
+ ```ruby
58
+ spandex = Spandex.new(path, :fenced_code_blocks => true) #special option for Redcarpet
59
+ ```
60
+
61
+ ##The content is just Tilt##
62
+
63
+ The markup is processed using [Tilt](https://github.com/rtomayko/tilt). That means it can read a lot of different markup formats, and gives you access to all of Tilt's configuration options. You can change what extensions get bound to what template engines, and that sort of thing
64
+
65
+ You can also customize rendering by customizing Tilt. Here's how you might customize Spandex to hightlight code with Pygments:
66
+
67
+ ```ruby
68
+ require 'redcarpet'
69
+ require 'pygments'
70
+
71
+ class Syntactical < Redcarpet::Render::HTML
72
+ include Pygments
73
+ def block_code(code, language)
74
+ highlight code, :lexer => lexer_name_for(:lexer => language)
75
+ end
76
+ end
77
+
78
+ class SyntacticalTemplate < Tilt::RedcarpetTemplate::Redcarpet2
79
+ def generate_renderer
80
+ Syntactical
81
+ end
82
+ end
83
+
84
+ Tilt::register SyntacticalTemplate, 'some_file_extension'
85
+ ```
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ require 'bundler'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+ Bundler::GemHelper.install_tasks
6
+
7
+ task :default => :spec
data/lib/spandex.rb ADDED
@@ -0,0 +1,21 @@
1
+ require 'spandex/page'
2
+ require 'spandex/finder'
3
+
4
+ module Spandex
5
+ class << self
6
+
7
+ def new(base_path, render_options = {})
8
+ Spandex::Finder.new(base_path, render_options)
9
+ end
10
+
11
+ def method_missing(method, *args, &block)
12
+ return super unless new.respond_to?(method)
13
+ new.send(method, *args, &block)
14
+ end
15
+
16
+ def respond_to?(method, include_private = false)
17
+ new.respond_to?(method, include_private) || super(method, include_private)
18
+ end
19
+
20
+ end
21
+ end
@@ -0,0 +1,92 @@
1
+ require 'pathname'
2
+ require 'atom'
3
+
4
+ module Spandex
5
+ class Finder
6
+
7
+ class CaseInsensitiveHash < Hash
8
+ def [](key)
9
+ super(key.to_s.downcase)
10
+ end
11
+ end
12
+
13
+ def initialize(base_dir, render_options = {})
14
+ @base_dir = base_dir
15
+ @render_options = render_options
16
+ end
17
+
18
+ def get(path)
19
+ load(Page.file_from_path(path, @base_dir), path)
20
+ end
21
+
22
+ def get_by_filename(filename)
23
+ load(filename)
24
+ end
25
+
26
+ def all_pages
27
+ roots = []
28
+ @pages ||= CaseInsensitiveHash.new
29
+ Dir.glob(File.join(@base_dir, "**/*"))
30
+ .map{|path| Pathname.new(path)}
31
+ .select{|path| Page.registered?(path)}
32
+ .each{|path| load(path)}
33
+ @pages.values
34
+ end
35
+
36
+ def all_articles
37
+ all_pages
38
+ .select{|page| page.date}
39
+ .sort {|x, y| y.date <=> x.date }
40
+ end
41
+
42
+ def find_articles(conditions)
43
+ find_inside(all_articles, conditions)
44
+ end
45
+
46
+ def tags
47
+ @tags ||= all_pages.map{|p| p.tags}.flatten.uniq
48
+ end
49
+
50
+ def atom_feed(count, author, root, path_to_xml)
51
+ articles = all_articles.take(count)
52
+ Atom::Feed.new do |f|
53
+ f.id = root
54
+ f.links << Atom::Link.new(:href => "http://#{root}#{path_to_xml}", :rel => "self")
55
+ f.links << Atom::Link.new(:href => "http://#{root}", :rel => "alternate")
56
+ f.authors << Atom::Person.new(:name => author)
57
+ f.updated = articles[0].date if articles[0]
58
+ articles.each do |post|
59
+ f.entries << post.to_atom_entry(root)
60
+ end
61
+ end.to_xml
62
+ end
63
+
64
+ private
65
+
66
+ def load(filename, key = Page.path_from_file(filename, @base_dir))
67
+ return nil unless filename && key && File.exists?(filename)
68
+ if @pages && @pages[key] && File.mtime(filename) < @pages[key].mtime
69
+ @pages[key]
70
+ else
71
+ @pages ||= CaseInsensitiveHash.new
72
+ page = Page.from_filename(filename, @base_dir, @render_options)
73
+ @pages[key] = page
74
+ page
75
+ end
76
+ end
77
+
78
+ def find_inside(xs, conditions = {})
79
+ output = xs
80
+ conditions.each do |k, v|
81
+ next unless v
82
+ cond = case k
83
+ when :tag then lambda {|p| p.tags.include?(v) }
84
+ else lambda{|p| true}
85
+ end
86
+ output = output.select(&cond)
87
+ end
88
+ output
89
+ end
90
+
91
+ end
92
+ end
@@ -0,0 +1,131 @@
1
+ require 'time'
2
+ require 'pathname'
3
+ require 'tilt'
4
+ require 'atom'
5
+
6
+ module Spandex
7
+ class Page
8
+ attr_reader :path, :mtime, :extension, :render_options
9
+
10
+ def self.from_path(path, base_path, render_options = {})
11
+ path = fix_path path
12
+ filename = file_from_path(path, base_path)
13
+ if filename
14
+ metadata, content = parse_file(filename)
15
+ Page.new(path, content, filename.extname, metadata, render_options)
16
+ else nil
17
+ end
18
+ end
19
+
20
+ def self.from_filename(filename, base_path, render_options = {})
21
+ pathname = Pathname.new(filename)
22
+ return nil unless pathname.exist?
23
+
24
+ path = path_from_file(pathname, base_path)
25
+ metadata, content = parse_file(filename)
26
+
27
+ Page.new(path, content, pathname.extname, metadata, render_options)
28
+ end
29
+
30
+ def self.mtime(path, base_path)
31
+ file = file_from_path(path, base_path)
32
+ if File.exists?(path)
33
+ File.mtime(file)
34
+ else nil
35
+ end
36
+ end
37
+
38
+ def self.file_from_path(path, base_path)
39
+ path = fix_path path
40
+ paths = Pathname.glob(File.join(base_path, "#{path}.*"))
41
+ pathname = paths.select{|path| registered?(path)}.first
42
+ end
43
+
44
+ def self.path_from_file(pathname, base_path)
45
+ pathname = pathify(pathname)
46
+ pathname.relative_path_from(pathify(base_path)).sub_ext('')
47
+ end
48
+
49
+ def self.registered?(pathname)
50
+ pathname = pathify(pathname)
51
+ Tilt.registered?(pathname.extname.sub(/^./, ''))
52
+ end
53
+
54
+
55
+ def title
56
+ metadata("title") || "(Unknown Title)"
57
+ end
58
+
59
+ def date
60
+ @date ||= metadata("date") ? DateTime.parse(metadata("date")) : nil
61
+ end
62
+
63
+ def body
64
+ @rendered_body ||= Tilt[@extension].new(nil, 1, @render_options){@content}.render
65
+ end
66
+
67
+ def tags
68
+ @tags ||= metadata("tags", "categories") ? metadata("tags", "categories").split(",").map{|tag| tag.strip} : []
69
+ end
70
+
71
+ def to_atom_entry(root)
72
+ unless date
73
+ raise "Must have a date"
74
+ end
75
+
76
+ Atom::Entry.new do |entry|
77
+ entry.title = title
78
+ entry.updated = date
79
+ entry.id = "#{root},#{@path}"
80
+ entry.links << Atom::Link.new(:href => "http://#{root}/#{@path}")
81
+ entry.content = Atom::Content::Html.new(body)
82
+ end
83
+ end
84
+
85
+ private
86
+
87
+ def initialize(path, content, extension, metadata, render_options = {})
88
+ @path = path
89
+ @content = content
90
+ @metadata = metadata
91
+ @extension = extension.sub(/^./, '')
92
+ @mtime = Time.now
93
+ @render_options = render_options
94
+ end
95
+
96
+ def metadata(*keys)
97
+ keys.each do |key|
98
+ return @metadata[key] if @metadata.has_key? key
99
+ end
100
+ nil
101
+ end
102
+
103
+ def self.pathify(path_or_string)
104
+ path_or_string.is_a?(String) ? Pathname.new(path_or_string) : path_or_string
105
+ end
106
+
107
+ def self.parse_file(filename)
108
+ def self.metadata?(text)
109
+ text.split("\n").first =~ /^[\w ]+:/
110
+ end
111
+
112
+ contents = File.open(filename).read
113
+
114
+ first_paragraph, remaining = contents.split(/\r?\n\r?\n/, 2)
115
+ metadata = {}
116
+ if metadata?(first_paragraph)
117
+ first_paragraph.split("\n").each do |line|
118
+ key, value = line.split(/\s*:\s*/, 2)
119
+ metadata[key.downcase] = value.chomp
120
+ end
121
+ end
122
+ markup = metadata?(first_paragraph) ? remaining : contents
123
+ return metadata, markup
124
+ end
125
+
126
+ def self.fix_path(path)
127
+ path.sub(/\/$/, '')
128
+ end
129
+
130
+ end
131
+ end
@@ -0,0 +1,3 @@
1
+ module Spandex
2
+ VERSION = "0.0.2"
3
+ end
data/spandex.gemspec ADDED
@@ -0,0 +1,25 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "spandex/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "spandex"
7
+ s.version = Spandex::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Isaac Cambron"]
10
+ s.email = ["icambron@alum.mit.edu"]
11
+ s.homepage = ""
12
+ s.summary = "A simple content engine"
13
+ s.description = "Spandex manages a store of markup files and their metadata, useful in building blogs or blog engines"
14
+
15
+ s.add_dependency "tilt"
16
+ s.add_dependency "ratom"
17
+
18
+ s.add_development_dependency "rspec"
19
+ s.add_development_dependency "redcarpet", "2.0.0b5"
20
+
21
+ s.files = `git ls-files`.split("\n")
22
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
23
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
24
+ s.require_paths = ["lib"]
25
+ end
@@ -0,0 +1,215 @@
1
+ require File.expand_path('spec_helper', File.dirname(__FILE__))
2
+ require 'spandex'
3
+ require 'atom'
4
+
5
+ describe Spandex::Finder do
6
+ include PageFactory
7
+ include TempFileHelper
8
+
9
+ context "when getting all pages" do
10
+
11
+ it "can find files" do
12
+ create_file("lasers.md", "You know it's 18 when you throw your dice.")
13
+ create_file("cheese.textile", "You've climbed that mountain not only once but twice.")
14
+ make_finder.all_pages.size.should == 2
15
+ end
16
+
17
+ it "won't find repeated files roots" do
18
+ create_file("stuff.md", "Some say you're a loner but I know your kind.")
19
+ create_file("stuff.textile", "It's sad to see that's why I fake that I'm blind.")
20
+
21
+ make_finder.all_pages.size.should == 1
22
+ end
23
+
24
+ it "finds thing with populated attributes" do
25
+ create_file("stuff.md", "Some say you're a loner but I know your kind.", :title => "The")
26
+ create_file("more_stuff.textile", "It's sad to see that's why I fake that I'm blind.", :title => "Sounds")
27
+
28
+ make_finder.all_pages.map{|p| p.title}.should == ["The", "Sounds"]
29
+ end
30
+
31
+ end
32
+
33
+ context "when getting all articles" do
34
+
35
+ it "works fine when there are no articles" do
36
+ make_finder.all_articles.should be_empty
37
+ end
38
+
39
+ it "only finds pages with dates" do
40
+ create_file("stuff.md", "You don't float like butterfly or fight like Ali.", :date => "2011/5/25")
41
+ create_file("more_stuff.md", "Dress like Prince but to the lowest degree.")
42
+
43
+ results = make_finder.all_articles
44
+ results.size.should == 1
45
+ results[0].date.should == Date.civil(2011, 5, 25)
46
+ end
47
+
48
+ it "sorts by date descending" do
49
+ create_file("stuff.md", "I like that you can't slow down.", :date => "1986/5/25")
50
+ create_file("more_stuff.md", "Step back! 'Cause you ain't no one.", :date => "1982/5/25")
51
+ create_file("even_more_stuff.md", "You're living in a lie.", :date => "2011/5/25")
52
+
53
+ results = make_finder.all_articles
54
+
55
+ results.size.should == 3
56
+ [Date.civil(2011,5,25), Date.civil(1986,5,25), Date.civil(1982,5,25)].each_with_index do |date, i|
57
+ results[i].date.should == date
58
+ end
59
+ end
60
+
61
+ it "ignores stray files" do
62
+ create_file("stuff.md~", "I like that you can't slow down.", :date => "1986/5/25")
63
+ make_finder.all_articles.should be_empty
64
+ end
65
+
66
+ end
67
+
68
+ context "when generating an atom feed" do
69
+
70
+ it "generates real atom content" do
71
+ create_file("stuff.md", "You ain't nothing but a BFI", :date => "1986/5/25", :title => "BFI")
72
+ create_file("more_stuff.md", "Leaving town on a two wheeler while your kids are home", :date => "1982/5/25")
73
+
74
+ #generate and then reparse
75
+ feed = make_finder.atom_feed(3, "The Sounds", "sounds.test.org", "articles.xml")
76
+ ratom = Atom::Feed.load_feed(feed)
77
+
78
+ ratom.entries.size.should == 2
79
+ ratom.authors.first.name.should == "The Sounds"
80
+ ratom.links.size.should == 2
81
+
82
+ e = ratom.entries.first
83
+ e.title.should == "BFI"
84
+
85
+ end
86
+
87
+ it "should only show the top n articles" do
88
+ create_file("stuff.md", "Giving up your love and life for some silver chrome", :date => "1986/5/25")
89
+ create_file("more_stuff.md", "You're acting like a fool so take my advice.", :date => "1986/5/25")
90
+ create_file("even_more_stuff.md", "It's not so hard to keep your eyes on the price.", :date => "1986/5/25")
91
+
92
+ feed = make_finder.atom_feed(2, "The Sounds", "sounds.test.org", "articles.xml")
93
+ ratom = Atom::Feed.load_feed(feed)
94
+
95
+ ratom.entries.size.should == 2
96
+ end
97
+
98
+ it "only includes pages with dates" do
99
+ create_file("stuff.md", "You don't float like butterfly or fight like Ali.", :date => "2011/5/25")
100
+ create_file("more_stuff.md", "Dress like Prince but to the lowest degree.")
101
+
102
+ feed = make_finder.atom_feed(2, "The Sounds", "sounds.test.org", "articles.xml")
103
+ ratom = Atom::Feed.load_feed(feed)
104
+
105
+ ratom.entries.size.should == 1
106
+ end
107
+
108
+ end
109
+
110
+ context "when listing tags" do
111
+
112
+ it "can list tags" do
113
+ create_file("stuff.md", "Excuses are all I ever get from you", :tags => "Sweedish, New Wave")
114
+ create_file("more_stuff.md", "And we both know it's true", :tags => "Indie Rock")
115
+
116
+ tags = make_finder.tags
117
+ tags.should == ["Sweedish", "New Wave", "Indie Rock"]
118
+ end
119
+
120
+ it "has unique tags" do
121
+ create_file("stuff.md", "It's not me, it is you", :tags => "Sweedish, Indie Rock")
122
+ create_file("more_stuff.md", "And nothing matters at all", :tags => "Indie Rock")
123
+
124
+ tags = make_finder.tags
125
+ tags.should == ["Sweedish", "Indie Rock"]
126
+ end
127
+ end
128
+
129
+ context "loading a specific page" do
130
+
131
+ it "does in fact load it" do
132
+ create_file("stuff.md", "It felt so right at the time")
133
+ page = make_finder.get("stuff")
134
+ page.should_not be_nil
135
+ end
136
+
137
+ it "finds the first file tilt knows" do
138
+ create_file("stuff.snoogledoobers", "But we lost it all")
139
+ create_file("stuff.md", "You committed a crime")
140
+ page = make_finder.get("stuff")
141
+ page.extension.should == "md"
142
+ end
143
+
144
+ it "doesn't have to exist" do
145
+ page = make_finder.get("this/is/not/a/real/file")
146
+ page.should be_nil
147
+ end
148
+
149
+ it "caches individual files" do
150
+ finder = make_finder
151
+
152
+ create_file("stuff.md", "And did it matter to you", :tags => "yeah")
153
+ finder.get("stuff").tags.should == ["yeah"]
154
+
155
+ create_file("stuff.md", "Now you lost it all", :tags => "nah")
156
+ finder.get("stuff").tags.should == ["yeah"]
157
+ end
158
+
159
+ it "ignores trailing slashes" do
160
+ create_file("stuff.md", "Well, you're not so bright")
161
+ make_finder.get("stuff/").should_not be_nil
162
+ end
163
+
164
+ end
165
+
166
+ context "when loading by filename" do
167
+ it "does in fact load something" do
168
+ create_file("stuff.md", "You don't have to say you're sorry")
169
+ page = make_finder.get_by_filename(File.join(TEMP_DIR, "stuff.md"))
170
+ page.should_not be_nil
171
+ end
172
+
173
+ it "doesn't have to exist" do
174
+ page = make_finder.get_by_filename(File.join(TEMP_DIR, "this_is_not_a_file.md"))
175
+ page.should be_nil
176
+ end
177
+
178
+ end
179
+
180
+ context "when finding articles" do
181
+ it "can find them by tag" do
182
+ create_file("no.md", "You never mean it when you say you're sorry", :tags => "nono", :date => "2011/5/25")
183
+ create_file("yeah.md", "No guts, no glory, no time to worry", :tags => "yeahyeah", :date => "2011/5/26", :title => "Yeah Yeah Yeah")
184
+
185
+
186
+ results = make_finder.find_articles(:tag => "yeahyeah")
187
+ results.size.should == 1
188
+ results.first.title == "Yeah Yeah Yeah"
189
+ end
190
+
191
+ it "only finds articles" do
192
+ create_file("no.md", "No happy ending to your story", :tags => "yeahyeah")
193
+ create_file("yeah.md", "In moments like this, don't give a fuck about you", :tags => "yeahyeah", :date => "2011/5/26", :title => "Yeah Yeah Yeah")
194
+
195
+
196
+ results = make_finder.find_articles(:tag => "yeahyeah")
197
+ results.size.should == 1
198
+ results.first.title == "Yeah Yeah Yeah"
199
+ end
200
+
201
+ end
202
+
203
+ before(:each) do
204
+ create_temp_directory
205
+ end
206
+
207
+ after(:each) do
208
+ remove_temp_directory
209
+ end
210
+
211
+ def make_finder
212
+ Spandex::Finder.new(TEMP_DIR)
213
+ end
214
+
215
+ end
data/spec/page_spec.rb ADDED
@@ -0,0 +1,80 @@
1
+ require File.expand_path('spec_helper', File.dirname(__FILE__))
2
+ require 'spandex'
3
+ require 'atom'
4
+ require 'redcarpet'
5
+
6
+ describe Spandex::Page do
7
+ include PageFactory
8
+ include TempFileHelper
9
+
10
+ context "when parsing a file" do
11
+ it "determines the extension" do
12
+ page = create_page("test.md", "Oh my love we gotta save ourselves")
13
+ page.extension.should=="md"
14
+ end
15
+
16
+ it "can have a title" do
17
+ page = create_page("test.md", "If we wanna safe the world", :title => "The Best of Me")
18
+ page.title.should == "The Best of Me"
19
+ end
20
+
21
+ it "can have a tag" do
22
+ page = create_page("test.md", "Don't give in to your hate", :tags => "sappy")
23
+ page.tags.should have(1).tags
24
+ page.tags.should == ["sappy"]
25
+ end
26
+
27
+ it "can have multiple tags" do
28
+ page = create_page("test.md", "When you know you can change", :tags => "sappy,slightly trite")
29
+ page.tags.should == ['sappy', 'slightly trite']
30
+ end
31
+
32
+ it "can have multiple tags with weird spacing" do
33
+ page = create_page("test.md", "It's hitting home when you feel so strange", :tags => " sappy , slightly trite ")
34
+ page.tags.should == ['sappy', 'slightly trite']
35
+ end
36
+
37
+ it "can also have tags called 'categories'" do
38
+ page = create_page("test.md", "I wanna say those words", :categories => "sappy,slightly trite")
39
+ page.tags.should have(2).tags
40
+ end
41
+
42
+ it "can parse the body" do
43
+ page = create_page("test.md", "But it's not that easy")
44
+ page.body.should == Redcarpet::Markdown.new(Redcarpet::Render::HTML).render("But it's not that easy")
45
+ end
46
+
47
+ it "pass in rendering options" do
48
+ text = "```\nI smile but it doesn't make things right```"
49
+ create_file("test.md", text)
50
+ page = Spandex::Page.from_filename(File.join(TEMP_DIR, "test.md"), TEMP_DIR, :fenced_code_blocks => true)
51
+ page.render_options.should have_key(:fenced_code_blocks)
52
+ markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML, :fenced_code_blocks => true)
53
+ page.body.should == markdown.render(text)
54
+ end
55
+
56
+ it "can have a date" do
57
+ page = create_page("test.md", "test_content", :date => "2011/5/25")
58
+ page.date.should == Date.civil(2011, 5, 25)
59
+ end
60
+
61
+ it "can omit the date" do
62
+ page = create_page("test.md", "test_content")
63
+ page.date.should be_nil
64
+ end
65
+
66
+ it "produces good atom output" do
67
+ page = create_page("test.md", "test_content", :title => "hello!", :date => "2011/5/25")
68
+ entry = page.to_atom_entry("http://test.org")
69
+ entry.title.should == "hello!"
70
+ end
71
+ end
72
+
73
+ before(:each) do
74
+ create_temp_directory
75
+ end
76
+
77
+ after(:each) do
78
+ remove_temp_directory
79
+ end
80
+ end
@@ -0,0 +1,37 @@
1
+ module TempFileHelper
2
+ TEMP_DIR = File.expand_path('content', File.dirname(__FILE__))
3
+
4
+ def create_temp_directory
5
+ FileUtils.mkdir_p(TempFileHelper::TEMP_DIR)
6
+ end
7
+
8
+ def remove_temp_directory
9
+ FileUtils.rm_r(TempFileHelper::TEMP_DIR, :force => true)
10
+ end
11
+
12
+ def temp_path(base)
13
+ File.join(TempFileHelper::TEMP_DIR, base)
14
+ end
15
+ end
16
+
17
+ module PageFactory
18
+ include TempFileHelper
19
+
20
+ def create_file(name, content, metadata = {})
21
+ full_name = File.join(TEMP_DIR, name)
22
+ metatext = metadata.map { |key, value| "#{key}: #{value}" }.join("\n")
23
+ contents =<<-EOF
24
+ #{metatext}
25
+
26
+ #{content}
27
+ EOF
28
+ File.open(full_name, 'w') { |file| file.write(contents) }
29
+ full_name
30
+ end
31
+
32
+ def create_page(name, content, metadata = {})
33
+ full_name = create_file(name, content, metadata)
34
+ Spandex::Page.from_filename(full_name, TEMP_DIR)
35
+ end
36
+
37
+ end
@@ -0,0 +1,5 @@
1
+ describe Spandex do
2
+ it "is a finder" do
3
+ Spandex.new("somepath").is_a? Spandex::Finder
4
+ end
5
+ end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: spandex
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.0.1
5
+ version: 0.0.2
6
6
  platform: ruby
7
7
  authors:
8
8
  - Isaac Cambron
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-09-25 00:00:00 -04:00
13
+ date: 2011-09-27 00:00:00 -04:00
14
14
  default_executable:
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
@@ -52,9 +52,9 @@ dependencies:
52
52
  requirement: &id004 !ruby/object:Gem::Requirement
53
53
  none: false
54
54
  requirements:
55
- - - ">="
55
+ - - "="
56
56
  - !ruby/object:Gem::Version
57
- version: "0"
57
+ version: 2.0.0b5
58
58
  type: :development
59
59
  version_requirements: *id004
60
60
  description: Spandex manages a store of markup files and their metadata, useful in building blogs or blog engines
@@ -66,8 +66,20 @@ extensions: []
66
66
 
67
67
  extra_rdoc_files: []
68
68
 
69
- files: []
70
-
69
+ files:
70
+ - .gitignore
71
+ - Gemfile
72
+ - README.md
73
+ - Rakefile
74
+ - lib/spandex.rb
75
+ - lib/spandex/finder.rb
76
+ - lib/spandex/page.rb
77
+ - lib/spandex/version.rb
78
+ - spandex.gemspec
79
+ - spec/finder_spec.rb
80
+ - spec/page_spec.rb
81
+ - spec/spec_helper.rb
82
+ - spec/wrapper_spec.rb
71
83
  has_rdoc: true
72
84
  homepage: ""
73
85
  licenses: []