vanilla 1.17.1 → 1.17.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README +4 -4
- data/Rakefile +18 -7
- data/lib/vanilla.rb +4 -1
- data/lib/vanilla/app.rb +17 -2
- data/lib/vanilla/atom_feed.rb +77 -0
- data/lib/vanilla/dynasnip.rb +47 -33
- data/lib/vanilla/snip_reference_parser.rb +6 -2
- data/lib/vanilla/test_helper.rb +6 -0
- data/pristine_app/config.ru +2 -1
- data/pristine_app/soups/base/feed.rb +12 -0
- data/pristine_app/soups/system/current_snip.rb +1 -0
- data/pristine_app/soups/system/index.rb +1 -1
- data/pristine_app/soups/system/link_to.rb +6 -4
- data/pristine_app/soups/system/pre.rb +2 -1
- data/pristine_app/soups/system/raw.rb +2 -1
- data/pristine_app/soups/tutorial/tutorial-layout.snip +7 -3
- data/test/core/atom_feed_test.rb +214 -0
- data/test/core/configuration_test.rb +4 -0
- data/test/core/dynasnip_test.rb +37 -2
- data/test/core/snip_reference_parser_test.rb +4 -0
- data/test/core/vanilla_app_test.rb +1 -1
- data/test/pristine_app/feed_test.rb +9 -28
- data/test/pristine_app/index_test.rb +10 -0
- data/test/pristine_app/site_test.rb +21 -0
- data/test/pristine_app/test_helper.rb +1 -0
- metadata +39 -38
- data/pristine_app/Gemfile.lock +0 -35
- data/pristine_app/soups/system/feed.rb +0 -30
- data/pristine_app/tmp/restart.txt +0 -0
data/README
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
--~::{ Vanilla.rb }::~---
|
2
2
|
=========================
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
4
|
+
A wandering soul; a repo clone'd -
|
5
|
+
his meta_klass and methods honed.
|
6
|
+
But tarry he 'ponst what dark endeavour
|
7
|
+
with code of such unknowable terror?
|
8
8
|
|
9
9
|
- H.P. Gemcraft, 1914
|
10
10
|
|
data/Rakefile
CHANGED
@@ -18,7 +18,6 @@ namespace :test do
|
|
18
18
|
t.verbose = true
|
19
19
|
end
|
20
20
|
|
21
|
-
require "rake/testtask"
|
22
21
|
Rake::TestTask.new(:app) do |t|
|
23
22
|
t.libs << "test/pristine_app"
|
24
23
|
t.ruby_opts << "-rubygems"
|
@@ -28,6 +27,20 @@ namespace :test do
|
|
28
27
|
end
|
29
28
|
|
30
29
|
if Object.const_defined?(:Gem)
|
30
|
+
|
31
|
+
def files_for_inclusion
|
32
|
+
base_files = %w(Rakefile README .gemtest) + Dir.glob("{test,lib,bin,pristine_app}/**/*")
|
33
|
+
files_to_ignore = File.readlines(".gitignore").inject([]) do |a,p|
|
34
|
+
path = p.strip
|
35
|
+
a += Dir.glob(path)
|
36
|
+
if File.directory?(path)
|
37
|
+
a += Dir.glob(path + "/*")
|
38
|
+
end
|
39
|
+
a
|
40
|
+
end
|
41
|
+
base_files - files_to_ignore
|
42
|
+
end
|
43
|
+
|
31
44
|
# This builds the actual gem. For details of what all these options
|
32
45
|
# mean, and other ones you can add, check the documentation here:
|
33
46
|
#
|
@@ -48,13 +61,13 @@ if Object.const_defined?(:Gem)
|
|
48
61
|
s.rdoc_options = %w(--main README)
|
49
62
|
|
50
63
|
# Add any extra files to include in the gem
|
51
|
-
s.files =
|
64
|
+
s.files = files_for_inclusion
|
52
65
|
s.executables = ['vanilla']
|
53
66
|
s.require_paths = ["lib"]
|
54
67
|
|
55
68
|
# All the other gems we need.
|
56
69
|
s.add_dependency("rack", ">= 0.9.1")
|
57
|
-
s.add_dependency("soup", ">= 1.0.
|
70
|
+
s.add_dependency("soup", ">= 1.0.9")
|
58
71
|
s.add_dependency("ratom", ">= 0.3.5")
|
59
72
|
s.add_dependency("RedCloth", ">= 4.1.1")
|
60
73
|
s.add_dependency("BlueCloth", ">= 1.0.0")
|
@@ -62,7 +75,7 @@ if Object.const_defined?(:Gem)
|
|
62
75
|
s.add_dependency("parslet", ">= 1.2.0")
|
63
76
|
s.add_dependency("rack-test", ">=0.5.7")
|
64
77
|
|
65
|
-
s.add_development_dependency("kintama", ">= 0.1.
|
78
|
+
s.add_development_dependency("kintama", ">= 0.1.7") # add any other gems for testing/development
|
66
79
|
s.add_development_dependency("mocha")
|
67
80
|
s.add_development_dependency("capybara")
|
68
81
|
s.add_development_dependency("launchy")
|
@@ -111,9 +124,7 @@ if Object.const_defined?(:Gem)
|
|
111
124
|
end
|
112
125
|
|
113
126
|
desc 'Clear out RDoc and generated packages'
|
114
|
-
task :clean => [:clobber_rdoc, :clobber_package]
|
115
|
-
rm "#{spec.name}.gemspec"
|
116
|
-
end
|
127
|
+
task :clean => [:clobber_rdoc, :clobber_package]
|
117
128
|
|
118
129
|
desc 'Tag the repository in git with gem version number'
|
119
130
|
task :tag => [:gemspec, :package] do
|
data/lib/vanilla.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
module Vanilla
|
2
|
-
VERSION = "1.17.
|
2
|
+
VERSION = "1.17.2"
|
3
3
|
|
4
4
|
autoload :Renderers, "vanilla/renderers"
|
5
5
|
autoload :App, "vanilla/app"
|
@@ -9,8 +9,11 @@ module Vanilla
|
|
9
9
|
autoload :Routing, "vanilla/routing"
|
10
10
|
autoload :Static, "vanilla/static"
|
11
11
|
autoload :SnipReferenceParser, "vanilla/snip_reference_parser"
|
12
|
+
autoload :AtomFeed, "vanilla/atom_feed"
|
12
13
|
autoload :TestHelper, "vanilla/test_helper"
|
13
14
|
|
15
|
+
class MissingRendererError < RuntimeError; end
|
16
|
+
|
14
17
|
class << self
|
15
18
|
# The set of currently loaded Vanilla::App subclasses
|
16
19
|
def apps
|
data/lib/vanilla/app.rb
CHANGED
@@ -68,7 +68,13 @@ module Vanilla
|
|
68
68
|
# Returns the renderer class for a given snip
|
69
69
|
def renderer_for(snip)
|
70
70
|
if snip
|
71
|
-
|
71
|
+
renderer_name = snip.render_as || snip.extension
|
72
|
+
renderer_name = nil if renderer_name == ''
|
73
|
+
else
|
74
|
+
renderer_name = nil
|
75
|
+
end
|
76
|
+
if renderer_name
|
77
|
+
find_renderer(renderer_name)
|
72
78
|
else
|
73
79
|
config.default_renderer
|
74
80
|
end
|
@@ -87,6 +93,10 @@ module Vanilla
|
|
87
93
|
end
|
88
94
|
end
|
89
95
|
|
96
|
+
def atom_feed(options={})
|
97
|
+
AtomFeed.new(options.merge(:app => self))
|
98
|
+
end
|
99
|
+
|
90
100
|
private
|
91
101
|
|
92
102
|
def prepare_renderers
|
@@ -94,13 +104,18 @@ module Vanilla
|
|
94
104
|
end
|
95
105
|
|
96
106
|
def find_renderer(name)
|
97
|
-
@renderers
|
107
|
+
if @renderers.has_key?(name.downcase)
|
108
|
+
@renderers[name.downcase]
|
109
|
+
else
|
110
|
+
raise MissingRendererError.new(name)
|
111
|
+
end
|
98
112
|
end
|
99
113
|
|
100
114
|
def rendering_and_handling_errors(snip)
|
101
115
|
renderer_instance = renderer_for(snip).new(self)
|
102
116
|
yield renderer_instance
|
103
117
|
rescue Exception => e
|
118
|
+
response.status = 500
|
104
119
|
snip_name = snip ? snip.name : nil
|
105
120
|
"<pre>[Error rendering '#{snip_name}' - \"" +
|
106
121
|
e.message.gsub("<", "<").gsub(">", ">") + "\"]\n" +
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require "atom"
|
2
|
+
|
3
|
+
module Vanilla
|
4
|
+
class AtomFeed
|
5
|
+
attr_reader :domain, :app, :title
|
6
|
+
|
7
|
+
def initialize(params={})
|
8
|
+
@domain = params[:domain] || "yourdomain.example.com"
|
9
|
+
@title = params[:title] || domain
|
10
|
+
@app = params[:app]
|
11
|
+
@criteria = params[:matching]
|
12
|
+
@snips = params[:snips]
|
13
|
+
if @snips.nil?
|
14
|
+
if @criteria.nil?
|
15
|
+
@snips = app.soup.all_snips
|
16
|
+
else
|
17
|
+
@snips = app.soup[@criteria]
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_s
|
23
|
+
Atom::Feed.new do |f|
|
24
|
+
f.title = title
|
25
|
+
f.updated = most_recent_updated_at
|
26
|
+
f.id = "tag:x,2008-06-01:kind/x"
|
27
|
+
f.entries = entries
|
28
|
+
end.to_xml
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def snips
|
34
|
+
@snips.sort_by { |s| atom_time(s.updated_at) }.reverse
|
35
|
+
end
|
36
|
+
|
37
|
+
def most_recent_updated_at
|
38
|
+
if snips.first
|
39
|
+
atom_time(snips.first.updated_at)
|
40
|
+
else
|
41
|
+
atom_time(nil)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def entries
|
46
|
+
snips.map do |snip|
|
47
|
+
Atom::Entry.new do |e|
|
48
|
+
e.published = atom_time(snip.created_at)
|
49
|
+
e.updated = atom_time(snip.updated_at || snip.created_at)
|
50
|
+
e.content = Atom::Content::Html.new(externalise_links(app.render(snip)))
|
51
|
+
e.title = snip.title || snip.name
|
52
|
+
e.authors = [Atom::Person.new(:name => snip.author || domain)]
|
53
|
+
e.links << Atom::Link.new(:href => "http://#{domain}#{app.url_to(snip.name)}")
|
54
|
+
e.id = "tag:#{domain},#{atom_time(snip.created_at || Time.now).split("T")[0]}:/#{snip.name}"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def atom_time(time)
|
60
|
+
return Time.at(0) if time.nil?
|
61
|
+
time = Time.parse(time) unless time.respond_to?(:strftime)
|
62
|
+
time.strftime("%Y-%m-%dT%H:%M:%S%z").insert(-3, ":")
|
63
|
+
end
|
64
|
+
|
65
|
+
def externalise_links(content)
|
66
|
+
content.gsub(/(href|src)=(["'])(\/?.*)\2/) do
|
67
|
+
type, quote, link = $1, $2, $3
|
68
|
+
if link =~ /^http/
|
69
|
+
"#{type}=#{quote}#{link}#{quote}"
|
70
|
+
else
|
71
|
+
absolute_link = "http://#{domain}" + (link =~ /^\// ? "" : "/") + link
|
72
|
+
"#{type}=#{quote}#{absolute_link}#{quote}"
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
data/lib/vanilla/dynasnip.rb
CHANGED
@@ -2,40 +2,53 @@ require 'vanilla/renderers/base'
|
|
2
2
|
require 'enumerator'
|
3
3
|
|
4
4
|
class Dynasnip < Vanilla::Renderers::Base
|
5
|
-
|
5
|
+
|
6
6
|
def self.all
|
7
7
|
ObjectSpace.enum_for(:each_object, class << self; self; end).to_a - [self]
|
8
8
|
end
|
9
|
-
|
10
|
-
def self.snip_name(new_name=nil)
|
11
|
-
if new_name
|
12
|
-
@snip_name = new_name.to_s
|
13
|
-
else
|
14
|
-
# borrowed from ActiveSupport
|
15
|
-
@snip_name ||= self.name.gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
16
|
-
gsub(/([a-z\d])([A-Z])/,'\1_\2').
|
17
|
-
tr("-", "_").
|
18
|
-
downcase
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
9
|
+
|
22
10
|
def self.attribute(attribute_name, attribute_value=nil)
|
23
11
|
@attributes ||= {}
|
24
12
|
@attributes[attribute_name.to_sym] = attribute_value if attribute_value
|
25
13
|
@attributes[attribute_name.to_sym]
|
26
14
|
end
|
27
|
-
|
28
|
-
def self.
|
29
|
-
|
15
|
+
|
16
|
+
def self.default_snip_name
|
17
|
+
# borrowed from ActiveSupport
|
18
|
+
formatted_name = self.name.
|
19
|
+
split("::").last.
|
20
|
+
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
21
|
+
gsub(/([a-z\d])([A-Z])/,'\1_\2').
|
22
|
+
tr("-", "_").
|
23
|
+
downcase
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.snip_name(new_name=nil)
|
27
|
+
if new_name.nil?
|
28
|
+
if name = attribute(:snip_name)
|
29
|
+
name
|
30
|
+
else
|
31
|
+
name = default_snip_name
|
32
|
+
attribute :snip_name, name
|
33
|
+
name
|
34
|
+
end
|
35
|
+
else
|
36
|
+
attribute :snip_name, new_name
|
37
|
+
new_name
|
38
|
+
end
|
30
39
|
end
|
31
|
-
|
40
|
+
|
41
|
+
def self.usage(str=nil)
|
42
|
+
attribute :usage, str
|
43
|
+
end
|
44
|
+
|
32
45
|
def self.snip_attributes
|
33
46
|
full_snip_attributes = {:name => snip_name, :content => self.name, :render_as => "Ruby"}
|
34
47
|
@attributes ? full_snip_attributes.merge!(@attributes) : full_snip_attributes
|
35
48
|
end
|
36
|
-
|
49
|
+
|
37
50
|
attr_accessor :enclosing_snip
|
38
|
-
|
51
|
+
|
39
52
|
def method_missing(method, *args)
|
40
53
|
if snip
|
41
54
|
snip.__send__(method)
|
@@ -45,28 +58,29 @@ class Dynasnip < Vanilla::Renderers::Base
|
|
45
58
|
super
|
46
59
|
end
|
47
60
|
end
|
48
|
-
|
61
|
+
|
49
62
|
# dynasnips gain access to the app in the same way as Render::Base
|
50
63
|
# subclasses
|
51
|
-
|
64
|
+
|
52
65
|
protected
|
53
|
-
|
66
|
+
|
67
|
+
def requesting_this_snip?
|
68
|
+
app.request.snip_name == snip_name
|
69
|
+
end
|
70
|
+
|
54
71
|
def snip_name
|
55
72
|
self.class.snip_name
|
56
73
|
end
|
57
|
-
|
74
|
+
|
75
|
+
def usage
|
76
|
+
str = self.class.attribute(:usage)
|
77
|
+
self.class.escape_curly_braces(str).strip if str
|
78
|
+
end
|
79
|
+
|
58
80
|
def snip
|
59
81
|
app.soup[snip_name]
|
60
82
|
end
|
61
|
-
|
62
|
-
def show_usage
|
63
|
-
if snip.usage
|
64
|
-
Vanilla::Renderers::Markdown.render(snip_name, :usage)
|
65
|
-
else
|
66
|
-
"No usage information for #{snip_name}"
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
83
|
+
|
70
84
|
def cleaned_params
|
71
85
|
p = app.request.params.dup
|
72
86
|
p.delete(:snip)
|
@@ -26,8 +26,12 @@ module Vanilla
|
|
26
26
|
rule(:spaces?) { spaces.maybe }
|
27
27
|
rule(:comma) { match(',') }
|
28
28
|
rule(:dot) { str(".") }
|
29
|
-
rule(:
|
30
|
-
rule(:
|
29
|
+
rule(:normal_squote) { str("'") }
|
30
|
+
rule(:html_squote) { str("‘") | str('’') }
|
31
|
+
rule(:squote) { normal_squote | html_squote }
|
32
|
+
rule(:normal_dquote) { str('"') }
|
33
|
+
rule(:html_dquote) { str('“') | str('”') }
|
34
|
+
rule(:dquote) { normal_dquote | html_dquote }
|
31
35
|
rule(:escaped_dquote) { str('"') }
|
32
36
|
rule(:left_brace) { str("{") }
|
33
37
|
rule(:right_brace) { str("}") }
|
data/lib/vanilla/test_helper.rb
CHANGED
@@ -2,10 +2,12 @@ require "vanilla"
|
|
2
2
|
require "rack/test"
|
3
3
|
require "tmpdir"
|
4
4
|
require "fileutils"
|
5
|
+
require "soup"
|
5
6
|
|
6
7
|
module Vanilla
|
7
8
|
module TestHelper
|
8
9
|
include Rack::Test::Methods
|
10
|
+
include Soup::TestHelper
|
9
11
|
|
10
12
|
def app(klass=Vanilla.apps.first)
|
11
13
|
unless @__app
|
@@ -54,5 +56,9 @@ module Vanilla
|
|
54
56
|
def vanilla_teardown
|
55
57
|
FileUtils.rm_rf(test_soup_path)
|
56
58
|
end
|
59
|
+
|
60
|
+
def stub_app_soup(*snips)
|
61
|
+
app.stubs(:soup).returns(stub_soup(*snips))
|
62
|
+
end
|
57
63
|
end
|
58
64
|
end
|
data/pristine_app/config.ru
CHANGED
@@ -0,0 +1,12 @@
|
|
1
|
+
require "vanilla/dynasnip"
|
2
|
+
|
3
|
+
class Feed < Dynasnip
|
4
|
+
def handle(*args)
|
5
|
+
app.atom_feed({
|
6
|
+
:domain => "yourdomain.example.com", # change this
|
7
|
+
:title => "My Feed", # and this,
|
8
|
+
:matching => {:kind => "blog"}, # but probably not this, although you can if you like.
|
9
|
+
})
|
10
|
+
end
|
11
|
+
self
|
12
|
+
end
|
@@ -3,7 +3,7 @@ require 'vanilla/dynasnip'
|
|
3
3
|
class Index < Dynasnip
|
4
4
|
def get(*args)
|
5
5
|
list = app.soup.all_snips.sort_by { |a| a.updated_at || Time.at(0) }.reverse.map { |snip|
|
6
|
-
|
6
|
+
%{<li>{link_to "#{snip.name}"}</li>}
|
7
7
|
}
|
8
8
|
%{<ol id="index">#{list}</ol>}
|
9
9
|
end
|
@@ -8,11 +8,13 @@ The link_to dyna lets you create links between snips:
|
|
8
8
|
|
9
9
|
would insert a link to the blah snip.|
|
10
10
|
|
11
|
-
def handle(
|
12
|
-
if
|
13
|
-
|
11
|
+
def handle(name=nil, link_text=name, part=nil)
|
12
|
+
return usage if requesting_this_snip?
|
13
|
+
return "You must provide a snip name" unless name
|
14
|
+
if app.soup[name]
|
15
|
+
%{<a href="#{url_to(name, part)}">#{link_text}</a>}
|
14
16
|
else
|
15
|
-
%{<a class="missing" href="#{url_to(
|
17
|
+
%{<a class="missing" href="#{url_to(name, part)}">#{link_text}</a>}
|
16
18
|
end
|
17
19
|
end
|
18
20
|
|
@@ -13,7 +13,8 @@ class ShowContentInPreTag < Dynasnip
|
|
13
13
|
{pre my_snip,specific_part}
|
14
14
|
|
|
15
15
|
|
16
|
-
def handle(snip_name, part=:content)
|
16
|
+
def handle(snip_name=nil, part=:content)
|
17
|
+
return usage if requesting_this_snip?
|
17
18
|
%{<pre>#{app.soup[snip_name].__send__(part || :content)}</pre>}
|
18
19
|
end
|
19
20
|
|
@@ -14,7 +14,8 @@ class ShowRawContent < Dynasnip
|
|
14
14
|
{raw my_snip,specific_part}
|
15
15
|
|
|
16
16
|
|
17
|
-
def handle(snip_name, part=:content)
|
17
|
+
def handle(snip_name=nil, part=:content)
|
18
|
+
return usage if requesting_this_snip?
|
18
19
|
%{#{Dynasnip.escape_curly_braces(CGI.escapeHTML(app.soup[snip_name].__send__(part || :content)))}}
|
19
20
|
end
|
20
21
|
|
@@ -23,19 +23,23 @@ Here's the source of `current_snip`:
|
|
23
23
|
|
24
24
|
{raw current_snip}
|
25
25
|
|
26
|
-
The default case
|
26
|
+
The default case just renders a string corresponding to snip inclusion of whichever snip was actually requested. In the case of `/start`, this will generate the string "{start}", which Vanilla itself then deals with, including the contents of that snip using the right renderer and so on, placing our snip in the appropriate place in the layout.
|
27
27
|
|
28
28
|
|
29
29
|
Other dynas
|
30
30
|
-----------
|
31
31
|
|
32
|
-
Of course, you can put other plain content in your layout, and other dynasnips too. In the provided layout there are calls to
|
32
|
+
Of course, you can put other plain content in your layout, and other dynasnips too. In the provided layout there are calls to three other dynasnips.
|
33
33
|
|
34
34
|
The first is `page_title`, which simply places a (hopefully) meaningful string in the title element of the page. Snips can set the title to be used by defining a `:page_title` attribute. As usual, the source explains it more clearly:
|
35
35
|
|
36
36
|
{raw page_title}
|
37
37
|
|
38
|
-
The second
|
38
|
+
The second is `link_to`, which is used to create links to other snips by name; although of course you can still just write HTML, this is often more convenient and wiki-esque. Here's the source:
|
39
|
+
|
40
|
+
{raw link_to}
|
41
|
+
|
42
|
+
The third dynasnip used is `link_to_current_snip`, which returns an HTML link to the snip that's currently being rendered. I'll let you figure out how to view the source yourself.
|
39
43
|
|
40
44
|
|
41
45
|
Other layouts
|
@@ -0,0 +1,214 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
require "atom"
|
3
|
+
|
4
|
+
context "An atom feed" do
|
5
|
+
should "include snips" do
|
6
|
+
stub_app_soup({:name => "Hello", :content => "This is the content"},
|
7
|
+
{:name => "Goodbye", :content => "More content"})
|
8
|
+
|
9
|
+
feed_xml = Vanilla::AtomFeed.new(:domain => "yourdomain.example.com", :app => app).to_s
|
10
|
+
feed = Atom::Feed.load_feed(feed_xml)
|
11
|
+
assert_equal 2, feed.entries.length
|
12
|
+
end
|
13
|
+
|
14
|
+
context "when making links absolute" do
|
15
|
+
should "handle double quoted a tags" do
|
16
|
+
stub_app_soup({:name => "x", :content => %|<a href="/x">x</a>.|})
|
17
|
+
|
18
|
+
feed = get_feed
|
19
|
+
assert feed.entries.first.content =~ %r{http://yourdomain\.example\.com/x},
|
20
|
+
"double-quoted links external should work (got: #{feed.entries.first.content})"
|
21
|
+
end
|
22
|
+
|
23
|
+
should "handle single quoted a tags" do
|
24
|
+
stub_app_soup({:name => "x", :content => %|<a href='/x'>x</a>.|})
|
25
|
+
|
26
|
+
feed = get_feed
|
27
|
+
assert feed.entries.first.content =~ %r{http://yourdomain\.example\.com/x},
|
28
|
+
"single-quoted links external should work (got: #{feed.entries.first.content})"
|
29
|
+
end
|
30
|
+
|
31
|
+
should "handle double quoted a tags without slahes" do
|
32
|
+
stub_app_soup({:name => "x", :content => %|<a href="x">x</a>.|})
|
33
|
+
|
34
|
+
feed = get_feed
|
35
|
+
assert feed.entries.first.content =~ %r{http://yourdomain\.example\.com/x},
|
36
|
+
"double-quoted links external should work (got: #{feed.entries.first.content})"
|
37
|
+
end
|
38
|
+
|
39
|
+
should "handle single quoted a tags without slashes" do
|
40
|
+
stub_app_soup({:name => "x", :content => %|<a href='x'>x</a>.|})
|
41
|
+
|
42
|
+
feed = get_feed
|
43
|
+
assert feed.entries.first.content =~ %r{http://yourdomain\.example\.com/x},
|
44
|
+
"single-quoted links external should work (got: #{feed.entries.first.content})"
|
45
|
+
end
|
46
|
+
|
47
|
+
should "handle double quoted img tags" do
|
48
|
+
stub_app_soup({:name => "x", :content => %|<img src="/x.jpg" />|})
|
49
|
+
|
50
|
+
feed = get_feed
|
51
|
+
assert feed.entries.first.content =~ %r{http://yourdomain\.example\.com/x.jpg},
|
52
|
+
"single-quoted links external should work (got: #{feed.entries.first.content})"
|
53
|
+
end
|
54
|
+
|
55
|
+
should "handle single quoted img tags" do
|
56
|
+
stub_app_soup({:name => "x", :content => %|<img src='/x.jpg' />|})
|
57
|
+
|
58
|
+
feed = get_feed
|
59
|
+
assert feed.entries.first.content =~ %r{http://yourdomain\.example\.com/x.jpg},
|
60
|
+
"single-quoted links external should work (got: #{feed.entries.first.content})"
|
61
|
+
end
|
62
|
+
|
63
|
+
should "handle double quoted img tags without slashes" do
|
64
|
+
stub_app_soup({:name => "x", :content => %|<img src="x.jpg" />|})
|
65
|
+
|
66
|
+
feed = get_feed
|
67
|
+
assert feed.entries.first.content =~ %r{http://yourdomain\.example\.com/x.jpg},
|
68
|
+
"single-quoted links external should work (got: #{feed.entries.first.content})"
|
69
|
+
end
|
70
|
+
|
71
|
+
should "handle single quoted img tags without slashes" do
|
72
|
+
stub_app_soup({:name => "x", :content => %|<img src='x.jpg' />|})
|
73
|
+
|
74
|
+
feed = get_feed
|
75
|
+
assert feed.entries.first.content =~ %r{http://yourdomain\.example\.com/x.jpg},
|
76
|
+
"single-quoted links external should work (got: #{feed.entries.first.content})"
|
77
|
+
end
|
78
|
+
|
79
|
+
should "not alter urls that are already absolute" do
|
80
|
+
stub_app_soup({:name => "x", :content => %|<img src='http://x.com/' />|})
|
81
|
+
|
82
|
+
feed = get_feed
|
83
|
+
assert feed.entries.first.content =~ %r{src='http://x\.com/'},
|
84
|
+
"should not alter absolute links (got: #{feed.entries.first.content})"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
should "allow inclusion of only specific snips" do
|
89
|
+
snip_a_data = {:name => "a", :content => "x"}
|
90
|
+
snip_b_data = {:name => "b", :content => "x"}
|
91
|
+
stub_app_soup(snip_a_data, snip_b_data)
|
92
|
+
|
93
|
+
feed_xml = app.atom_feed(:domain => "whatever", :snips => [app.soup["a"]]).to_s
|
94
|
+
feed = Atom::Feed.load_feed(feed_xml)
|
95
|
+
assert_equal 1, feed.entries.length
|
96
|
+
assert_equal "a", feed.entries.first.title
|
97
|
+
end
|
98
|
+
|
99
|
+
should "allow filtering of snips by matching criteria" do
|
100
|
+
stub_app_soup({:name => "a", :content => "x", :kind => "blog"},
|
101
|
+
{:name => "b", :content => "x", :kind => "draft"},
|
102
|
+
{:name => "c", :content => "x", :kind => "blog"})
|
103
|
+
|
104
|
+
feed_xml = app.atom_feed(:domain => "whatever", :matching => {:kind => "blog"}).to_s
|
105
|
+
feed = Atom::Feed.load_feed(feed_xml)
|
106
|
+
assert_equal 2, feed.entries.length
|
107
|
+
assert_same_elements ["a", "c"], feed.entries.map { |e| e.title }
|
108
|
+
end
|
109
|
+
|
110
|
+
should "set updated to be the latest updated_at of the included snips" do
|
111
|
+
snip_a_data = {:name => "a", :content => "x", :updated_at => Time.parse("2011-05-22 12:00")}
|
112
|
+
snip_b_data = {:name => "b", :content => "x", :updated_at => Time.parse("2011-05-23 12:34")}
|
113
|
+
snip_c_data = {:name => "c", :content => "x", :updated_at => Time.parse("2011-05-24 12:34")}
|
114
|
+
stub_app_soup(snip_a_data, snip_b_data, snip_c_data)
|
115
|
+
|
116
|
+
feed_xml = app.atom_feed(:domain => "whatever", :snips => [app.soup["a"], app.soup["b"]]).to_s
|
117
|
+
feed = Atom::Feed.load_feed(feed_xml)
|
118
|
+
assert_equal Time.parse("2011-05-23 12:34"), feed.updated
|
119
|
+
end
|
120
|
+
|
121
|
+
should "format updated_at as an RFC-3339 date-time" do
|
122
|
+
stub_app_soup({:name => "x", :content => "y", :updated_at => Time.parse("2011-01-01 12:23 +0000").to_s})
|
123
|
+
|
124
|
+
feed_xml = app.atom_feed(:domain => "whatever", :snips => [app.soup["x"]]).to_s
|
125
|
+
assert_match %r{2011\-01\-01T12\:23\:00\+00\:00}, feed_xml
|
126
|
+
end
|
127
|
+
|
128
|
+
should "work even without any snips" do
|
129
|
+
feed_xml = app.atom_feed(:domain => "whatever", :snips => []).to_s
|
130
|
+
feed = Atom::Feed.load_feed(feed_xml)
|
131
|
+
end
|
132
|
+
|
133
|
+
context "title" do
|
134
|
+
setup do
|
135
|
+
stub_app_soup
|
136
|
+
end
|
137
|
+
|
138
|
+
should "be settable via the initialiser" do
|
139
|
+
feed_xml = app.atom_feed(:domain => "yourdomain.example.com", :title => "My Title").to_s
|
140
|
+
feed = Atom::Feed.load_feed(feed_xml)
|
141
|
+
assert_equal "My Title", feed.title
|
142
|
+
end
|
143
|
+
|
144
|
+
should "default to the domain" do
|
145
|
+
feed_xml = app.atom_feed(:domain => "yourdomain.example.com").to_s
|
146
|
+
feed = Atom::Feed.load_feed(feed_xml)
|
147
|
+
assert_equal "yourdomain.example.com", feed.title
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
context "entry" do
|
152
|
+
setup do
|
153
|
+
stub_app_soup({:name => "Hello", :content => "The *content*",
|
154
|
+
:render_as => "markdown", :created_at => Time.parse("2011-01-01 12:23").to_s})
|
155
|
+
end
|
156
|
+
|
157
|
+
context "titles" do
|
158
|
+
should "default to be the name of the snip" do
|
159
|
+
assert_equal "Hello", get_feed.entries.first.title
|
160
|
+
end
|
161
|
+
|
162
|
+
should "use the title of the snip if present" do
|
163
|
+
stub_app_soup({:name => "hello-mammy", :content => "x", :title => "Hello, Mammy"})
|
164
|
+
assert_equal "Hello, Mammy", get_feed.entries.first.title
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
context "authors" do
|
169
|
+
should "set the author to be the domain by default" do
|
170
|
+
assert_equal ["yourdomain.example.com"], get_feed.entries.first.authors.map { |a| a.name }
|
171
|
+
end
|
172
|
+
|
173
|
+
should "set the authors if the snip provides" do
|
174
|
+
stub_app_soup({:name => "a", :content => "x", :author => "james"})
|
175
|
+
assert_equal ["james"], get_feed.entries.first.authors.map { |a| a.name }
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
should "included rendered snip contents" do
|
180
|
+
assert_equal "<p>The <em>content</em></p>", get_feed.entries.first.content
|
181
|
+
end
|
182
|
+
|
183
|
+
|
184
|
+
should "include a link to the snip" do
|
185
|
+
assert_equal ["http://yourdomain.example.com/Hello"], get_feed.entries.first.links.map { |l| l.href }
|
186
|
+
end
|
187
|
+
|
188
|
+
should "set the ID based on the domain, timestamp and snip name" do
|
189
|
+
assert_equal "tag:yourdomain.example.com,2011-01-01:/Hello", get_feed.entries.first.id
|
190
|
+
end
|
191
|
+
|
192
|
+
should "set the published date based on the snip created_at date" do
|
193
|
+
assert_equal Time.parse("2011-01-01 12:23"), get_feed.entries.first.published
|
194
|
+
end
|
195
|
+
|
196
|
+
context "updated at" do
|
197
|
+
should "default to the published date" do
|
198
|
+
assert_equal Time.parse("2011-01-01 12:23"), get_feed.entries.first.updated
|
199
|
+
end
|
200
|
+
|
201
|
+
should "set the updated at to the snip attribute if it exists" do
|
202
|
+
stub_app_soup({:name => "Hello", :content => "the content", :updated_at => Time.parse("2011-01-02 13:45").to_s})
|
203
|
+
assert_equal Time.parse("2011-01-02 13:45"), get_feed.entries.first.updated
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
private
|
209
|
+
|
210
|
+
def get_feed
|
211
|
+
feed_xml = app.atom_feed(:domain => "yourdomain.example.com").to_s
|
212
|
+
Atom::Feed.load_feed(feed_xml)
|
213
|
+
end
|
214
|
+
end
|
@@ -65,6 +65,10 @@ context "Configuring a Vanilla app" do
|
|
65
65
|
should "use only the specified soups" do
|
66
66
|
assert_equal ["blah", "monkey"], TestConfigurationApp.new.config.soups
|
67
67
|
end
|
68
|
+
|
69
|
+
teardown do
|
70
|
+
["blah", "monkey"].each { |dir| FileUtils.rm_rf(dir) }
|
71
|
+
end
|
68
72
|
end
|
69
73
|
|
70
74
|
context "with new renderers" do
|
data/test/core/dynasnip_test.rb
CHANGED
@@ -4,7 +4,7 @@ require 'vanilla/dynasnip'
|
|
4
4
|
describe Dynasnip do
|
5
5
|
context "when storing attributes" do
|
6
6
|
|
7
|
-
class
|
7
|
+
class TestDyna < Dynasnip
|
8
8
|
attribute :test_attribute, "test attribute content"
|
9
9
|
end
|
10
10
|
|
@@ -27,16 +27,51 @@ describe Dynasnip do
|
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
30
|
+
context "determining name" do
|
31
|
+
module X
|
32
|
+
class TestDyna < Dynasnip
|
33
|
+
def handle(*args)
|
34
|
+
"name: #{snip_name}"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
should "strip out modules from the name" do
|
40
|
+
assert_equal "test_dyna", X::TestDyna.snip_name
|
41
|
+
end
|
42
|
+
|
43
|
+
should "allow the snip to reference its own name" do
|
44
|
+
assert_equal "name: test_dyna", X::TestDyna.new(app).handle
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
context "setting name" do
|
49
|
+
class AnotherDyna < Dynasnip
|
50
|
+
end
|
51
|
+
|
52
|
+
should "be possible" do
|
53
|
+
AnotherDyna.snip_name "some_other_name"
|
54
|
+
assert_equal "some_other_name", AnotherDyna.snip_name
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
30
58
|
context "when rendering usage" do
|
31
59
|
class ::ShowUsage < Dynasnip
|
32
|
-
usage "This is the usage"
|
33
60
|
def handle
|
34
61
|
usage
|
35
62
|
end
|
36
63
|
end
|
37
64
|
|
38
65
|
should "show the usage defined in the snip" do
|
66
|
+
ShowUsage.usage "This is the usage"
|
67
|
+
|
39
68
|
assert_equal "This is the usage", ShowUsage.new(app).handle
|
40
69
|
end
|
70
|
+
|
71
|
+
should "automatically escape curly braces to prevent snip inclusion" do
|
72
|
+
ShowUsage.usage "like {this}"
|
73
|
+
|
74
|
+
assert_equal "like {this}", ShowUsage.new(app).handle
|
75
|
+
end
|
41
76
|
end
|
42
77
|
end
|
@@ -83,6 +83,10 @@ context "The SnipReference parser" do
|
|
83
83
|
%|{s 'arg, comma'}| => {:snip => 's', :attribute => nil, :arguments => ['arg, comma']},
|
84
84
|
# %|{s "arg { open"}| => {:snip => 's', :attribute => nil, :arguments => ['arg { open']},
|
85
85
|
# %|{s "arg } close"}| => {:snip => 's', :attribute => nil, :arguments => ['arg } close']}
|
86
|
+
},
|
87
|
+
|
88
|
+
:html_quoting_arguments => {
|
89
|
+
%|{s “arg”}| => {:snip => 's', :attribute => nil, :arguments => ['arg']},
|
86
90
|
}
|
87
91
|
}
|
88
92
|
|
@@ -45,7 +45,7 @@ describe Vanilla::App do
|
|
45
45
|
|
46
46
|
should "raise an error if the specified renderer doesn't exist" do
|
47
47
|
snip = create_snip(:name => "blah", :render_as => "NonExistentClass")
|
48
|
-
assert_raises(
|
48
|
+
assert_raises(Vanilla::MissingRendererError) { app.renderer_for(snip) }
|
49
49
|
end
|
50
50
|
end
|
51
51
|
end
|
@@ -1,12 +1,13 @@
|
|
1
1
|
require "test_helper"
|
2
2
|
require "atom"
|
3
|
+
require "base/feed"
|
3
4
|
|
4
5
|
context "The feed dynasnip" do
|
5
|
-
should "include snips" do
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
6
|
+
should "include snips of the specified kind" do
|
7
|
+
stub_app_soup({:name => "Hello", :content => "This is the content", :kind => "blog"},
|
8
|
+
{:name => "Goodbye", :content => "More content", :kind => "blog"},
|
9
|
+
{:name => "system", :content => "not to be shown"},
|
10
|
+
Feed.snip_attributes)
|
10
11
|
|
11
12
|
visit "/feed.xml"
|
12
13
|
|
@@ -15,33 +16,13 @@ context "The feed dynasnip" do
|
|
15
16
|
end
|
16
17
|
|
17
18
|
should "included rendered snip contents" do
|
18
|
-
|
19
|
-
|
20
|
-
|
19
|
+
stub_app_soup({:name => "Hello", :content => "This is *the* content",
|
20
|
+
:render_as => "markdown", :kind => "blog"},
|
21
|
+
Feed.snip_attributes)
|
21
22
|
|
22
23
|
visit "/feed.xml"
|
23
24
|
|
24
25
|
feed = Atom::Feed.load_feed(page.source)
|
25
26
|
assert_equal "<p>This is <em>the</em> content</p>", feed.entries.first.content
|
26
27
|
end
|
27
|
-
|
28
|
-
should "ensure that all links are made absolute"
|
29
|
-
|
30
|
-
context "each entry" do
|
31
|
-
setup do
|
32
|
-
end
|
33
|
-
should "set the name to be the name of the snip"
|
34
|
-
should "use the title of the snip as name if present"
|
35
|
-
should "set the authors"
|
36
|
-
should "include a link to the snip"
|
37
|
-
should "set the ID"
|
38
|
-
should "set the published date"
|
39
|
-
should "set the updated at"
|
40
|
-
end
|
41
|
-
|
42
|
-
private
|
43
|
-
|
44
|
-
def snip(attributes)
|
45
|
-
Soup::Snip.new(attributes, nil)
|
46
|
-
end
|
47
28
|
end
|
@@ -26,6 +26,16 @@ context "The index dynasnip" do
|
|
26
26
|
assert_equal %w(beta alpha gamma), links
|
27
27
|
end
|
28
28
|
|
29
|
+
should "render links to snips with weird characters and spaces" do
|
30
|
+
app.soup.stubs(:all_snips).returns([
|
31
|
+
snip(:name => "fun fun", :updated_at => Time.at(20))
|
32
|
+
])
|
33
|
+
|
34
|
+
visit "/index"
|
35
|
+
links = page.all("ol#index li a").map { |l| l.text }
|
36
|
+
assert_equal ["fun fun"], links
|
37
|
+
end
|
38
|
+
|
29
39
|
private
|
30
40
|
|
31
41
|
def snip(attributes)
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
require "timeout"
|
3
|
+
|
4
|
+
context "Every snip" do
|
5
|
+
should "return a 200 response code" do
|
6
|
+
snips = app.soup.all_snips
|
7
|
+
snips.each do |snip|
|
8
|
+
expected_code = 200
|
9
|
+
expected_code = 500 if %w(test bad_dynasnip).include?(snip.name)
|
10
|
+
begin
|
11
|
+
Timeout.timeout(1) do
|
12
|
+
get snip.name
|
13
|
+
assert_equal expected_code, last_response.status,
|
14
|
+
"#{snip.name} returned a #{last_response.status} response:\n#{last_response.body}"
|
15
|
+
end
|
16
|
+
rescue Timeout::Error
|
17
|
+
flunk "#{snip.name} timed out rendering"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vanilla
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 87
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 1
|
8
8
|
- 17
|
9
|
-
-
|
10
|
-
version: 1.17.
|
9
|
+
- 2
|
10
|
+
version: 1.17.2
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- James Adam
|
@@ -15,10 +15,12 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-
|
18
|
+
date: 2011-11-01 00:00:00 +00:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
22
|
+
name: rack
|
23
|
+
prerelease: false
|
22
24
|
version_requirements: &id001 !ruby/object:Gem::Requirement
|
23
25
|
none: false
|
24
26
|
requirements:
|
@@ -31,26 +33,26 @@ dependencies:
|
|
31
33
|
- 1
|
32
34
|
version: 0.9.1
|
33
35
|
type: :runtime
|
34
|
-
prerelease: false
|
35
36
|
requirement: *id001
|
36
|
-
name: rack
|
37
37
|
- !ruby/object:Gem::Dependency
|
38
|
+
name: soup
|
39
|
+
prerelease: false
|
38
40
|
version_requirements: &id002 !ruby/object:Gem::Requirement
|
39
41
|
none: false
|
40
42
|
requirements:
|
41
43
|
- - ">="
|
42
44
|
- !ruby/object:Gem::Version
|
43
|
-
hash:
|
45
|
+
hash: 5
|
44
46
|
segments:
|
45
47
|
- 1
|
46
48
|
- 0
|
47
|
-
-
|
48
|
-
version: 1.0.
|
49
|
+
- 9
|
50
|
+
version: 1.0.9
|
49
51
|
type: :runtime
|
50
|
-
prerelease: false
|
51
52
|
requirement: *id002
|
52
|
-
name: soup
|
53
53
|
- !ruby/object:Gem::Dependency
|
54
|
+
name: ratom
|
55
|
+
prerelease: false
|
54
56
|
version_requirements: &id003 !ruby/object:Gem::Requirement
|
55
57
|
none: false
|
56
58
|
requirements:
|
@@ -63,10 +65,10 @@ dependencies:
|
|
63
65
|
- 5
|
64
66
|
version: 0.3.5
|
65
67
|
type: :runtime
|
66
|
-
prerelease: false
|
67
68
|
requirement: *id003
|
68
|
-
name: ratom
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
|
+
name: RedCloth
|
71
|
+
prerelease: false
|
70
72
|
version_requirements: &id004 !ruby/object:Gem::Requirement
|
71
73
|
none: false
|
72
74
|
requirements:
|
@@ -79,10 +81,10 @@ dependencies:
|
|
79
81
|
- 1
|
80
82
|
version: 4.1.1
|
81
83
|
type: :runtime
|
82
|
-
prerelease: false
|
83
84
|
requirement: *id004
|
84
|
-
name: RedCloth
|
85
85
|
- !ruby/object:Gem::Dependency
|
86
|
+
name: BlueCloth
|
87
|
+
prerelease: false
|
86
88
|
version_requirements: &id005 !ruby/object:Gem::Requirement
|
87
89
|
none: false
|
88
90
|
requirements:
|
@@ -95,10 +97,10 @@ dependencies:
|
|
95
97
|
- 0
|
96
98
|
version: 1.0.0
|
97
99
|
type: :runtime
|
98
|
-
prerelease: false
|
99
100
|
requirement: *id005
|
100
|
-
name: BlueCloth
|
101
101
|
- !ruby/object:Gem::Dependency
|
102
|
+
name: haml
|
103
|
+
prerelease: false
|
102
104
|
version_requirements: &id006 !ruby/object:Gem::Requirement
|
103
105
|
none: false
|
104
106
|
requirements:
|
@@ -110,10 +112,10 @@ dependencies:
|
|
110
112
|
- 1
|
111
113
|
version: "3.1"
|
112
114
|
type: :runtime
|
113
|
-
prerelease: false
|
114
115
|
requirement: *id006
|
115
|
-
name: haml
|
116
116
|
- !ruby/object:Gem::Dependency
|
117
|
+
name: parslet
|
118
|
+
prerelease: false
|
117
119
|
version_requirements: &id007 !ruby/object:Gem::Requirement
|
118
120
|
none: false
|
119
121
|
requirements:
|
@@ -126,10 +128,10 @@ dependencies:
|
|
126
128
|
- 0
|
127
129
|
version: 1.2.0
|
128
130
|
type: :runtime
|
129
|
-
prerelease: false
|
130
131
|
requirement: *id007
|
131
|
-
name: parslet
|
132
132
|
- !ruby/object:Gem::Dependency
|
133
|
+
name: rack-test
|
134
|
+
prerelease: false
|
133
135
|
version_requirements: &id008 !ruby/object:Gem::Requirement
|
134
136
|
none: false
|
135
137
|
requirements:
|
@@ -142,26 +144,26 @@ dependencies:
|
|
142
144
|
- 7
|
143
145
|
version: 0.5.7
|
144
146
|
type: :runtime
|
145
|
-
prerelease: false
|
146
147
|
requirement: *id008
|
147
|
-
name: rack-test
|
148
148
|
- !ruby/object:Gem::Dependency
|
149
|
+
name: kintama
|
150
|
+
prerelease: false
|
149
151
|
version_requirements: &id009 !ruby/object:Gem::Requirement
|
150
152
|
none: false
|
151
153
|
requirements:
|
152
154
|
- - ">="
|
153
155
|
- !ruby/object:Gem::Version
|
154
|
-
hash:
|
156
|
+
hash: 21
|
155
157
|
segments:
|
156
158
|
- 0
|
157
159
|
- 1
|
158
|
-
-
|
159
|
-
version: 0.1.
|
160
|
+
- 7
|
161
|
+
version: 0.1.7
|
160
162
|
type: :development
|
161
|
-
prerelease: false
|
162
163
|
requirement: *id009
|
163
|
-
name: kintama
|
164
164
|
- !ruby/object:Gem::Dependency
|
165
|
+
name: mocha
|
166
|
+
prerelease: false
|
165
167
|
version_requirements: &id010 !ruby/object:Gem::Requirement
|
166
168
|
none: false
|
167
169
|
requirements:
|
@@ -172,10 +174,10 @@ dependencies:
|
|
172
174
|
- 0
|
173
175
|
version: "0"
|
174
176
|
type: :development
|
175
|
-
prerelease: false
|
176
177
|
requirement: *id010
|
177
|
-
name: mocha
|
178
178
|
- !ruby/object:Gem::Dependency
|
179
|
+
name: capybara
|
180
|
+
prerelease: false
|
179
181
|
version_requirements: &id011 !ruby/object:Gem::Requirement
|
180
182
|
none: false
|
181
183
|
requirements:
|
@@ -186,10 +188,10 @@ dependencies:
|
|
186
188
|
- 0
|
187
189
|
version: "0"
|
188
190
|
type: :development
|
189
|
-
prerelease: false
|
190
191
|
requirement: *id011
|
191
|
-
name: capybara
|
192
192
|
- !ruby/object:Gem::Dependency
|
193
|
+
name: launchy
|
194
|
+
prerelease: false
|
193
195
|
version_requirements: &id012 !ruby/object:Gem::Requirement
|
194
196
|
none: false
|
195
197
|
requirements:
|
@@ -200,9 +202,7 @@ dependencies:
|
|
200
202
|
- 0
|
201
203
|
version: "0"
|
202
204
|
type: :development
|
203
|
-
prerelease: false
|
204
205
|
requirement: *id012
|
205
|
-
name: launchy
|
206
206
|
description:
|
207
207
|
email: james@lazyatom.com.com
|
208
208
|
executables:
|
@@ -215,6 +215,7 @@ files:
|
|
215
215
|
- Rakefile
|
216
216
|
- README
|
217
217
|
- .gemtest
|
218
|
+
- test/core/atom_feed_test.rb
|
218
219
|
- test/core/configuration_test.rb
|
219
220
|
- test/core/dynasnip_test.rb
|
220
221
|
- test/core/renderers/base_renderer_test.rb
|
@@ -237,8 +238,10 @@ files:
|
|
237
238
|
- test/pristine_app/link_to_test.rb
|
238
239
|
- test/pristine_app/page_title_test.rb
|
239
240
|
- test/pristine_app/raw_test.rb
|
241
|
+
- test/pristine_app/site_test.rb
|
240
242
|
- test/pristine_app/test_helper.rb
|
241
243
|
- lib/vanilla/app.rb
|
244
|
+
- lib/vanilla/atom_feed.rb
|
242
245
|
- lib/vanilla/config.rb
|
243
246
|
- lib/vanilla/console.rb
|
244
247
|
- lib/vanilla/dynasnip.rb
|
@@ -261,9 +264,9 @@ files:
|
|
261
264
|
- pristine_app/application.rb
|
262
265
|
- pristine_app/config.ru
|
263
266
|
- pristine_app/Gemfile
|
264
|
-
- pristine_app/Gemfile.lock
|
265
267
|
- pristine_app/public/vanilla.css
|
266
268
|
- pristine_app/README
|
269
|
+
- pristine_app/soups/base/feed.rb
|
267
270
|
- pristine_app/soups/base/layout.snip
|
268
271
|
- pristine_app/soups/base/start.snip
|
269
272
|
- pristine_app/soups/extras/comments.rb
|
@@ -272,7 +275,6 @@ files:
|
|
272
275
|
- pristine_app/soups/extras/url_to.rb
|
273
276
|
- pristine_app/soups/system/current_snip.rb
|
274
277
|
- pristine_app/soups/system/debug.rb
|
275
|
-
- pristine_app/soups/system/feed.rb
|
276
278
|
- pristine_app/soups/system/index.rb
|
277
279
|
- pristine_app/soups/system/link_to.rb
|
278
280
|
- pristine_app/soups/system/link_to_current_snip.rb
|
@@ -296,7 +298,6 @@ files:
|
|
296
298
|
- pristine_app/soups/tutorial/tutorial.snip.markdown
|
297
299
|
- pristine_app/soups/tutorial/vanilla-rb.snip
|
298
300
|
- pristine_app/soups/tutorial/vanilla.snip
|
299
|
-
- pristine_app/tmp/restart.txt
|
300
301
|
has_rdoc: true
|
301
302
|
homepage: http://github.com/lazyatom/vanilla-rb
|
302
303
|
licenses: []
|
@@ -328,7 +329,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
328
329
|
requirements: []
|
329
330
|
|
330
331
|
rubyforge_project: vanilla
|
331
|
-
rubygems_version: 1.
|
332
|
+
rubygems_version: 1.6.2
|
332
333
|
signing_key:
|
333
334
|
specification_version: 3
|
334
335
|
summary: A bliki-type web content thing.
|
data/pristine_app/Gemfile.lock
DELETED
@@ -1,35 +0,0 @@
|
|
1
|
-
PATH
|
2
|
-
remote: /Users/james/Code/lazyatom/vanilla-rb
|
3
|
-
specs:
|
4
|
-
vanilla (1.17)
|
5
|
-
BlueCloth (>= 1.0.0)
|
6
|
-
RedCloth (>= 4.1.1)
|
7
|
-
haml (>= 3.1)
|
8
|
-
parslet (>= 1.2.0)
|
9
|
-
rack (>= 0.9.1)
|
10
|
-
rack-test (>= 0.5.7)
|
11
|
-
ratom (>= 0.3.5)
|
12
|
-
soup (>= 1.0.8)
|
13
|
-
|
14
|
-
GEM
|
15
|
-
remote: http://rubygems.org/
|
16
|
-
specs:
|
17
|
-
BlueCloth (1.0.1)
|
18
|
-
RedCloth (4.2.7)
|
19
|
-
blankslate (2.1.2.4)
|
20
|
-
haml (3.1.1)
|
21
|
-
libxml-ruby (2.0.5)
|
22
|
-
parslet (1.2.0)
|
23
|
-
blankslate (~> 2.0)
|
24
|
-
rack (1.2.2)
|
25
|
-
rack-test (0.5.7)
|
26
|
-
rack (>= 1.0)
|
27
|
-
ratom (0.6.8)
|
28
|
-
libxml-ruby (>= 1.1.2)
|
29
|
-
soup (1.0.8)
|
30
|
-
|
31
|
-
PLATFORMS
|
32
|
-
ruby
|
33
|
-
|
34
|
-
DEPENDENCIES
|
35
|
-
vanilla!
|
@@ -1,30 +0,0 @@
|
|
1
|
-
require "vanilla/dynasnip"
|
2
|
-
|
3
|
-
class Feed < Dynasnip
|
4
|
-
def handle(*args)
|
5
|
-
Atom::Feed.new do |f|
|
6
|
-
f.title = "blah"
|
7
|
-
f.updated = Time.now
|
8
|
-
f.id = "tag:x,2008-06-01:kind/x"
|
9
|
-
f.entries = entries
|
10
|
-
end.to_xml
|
11
|
-
end
|
12
|
-
|
13
|
-
private
|
14
|
-
|
15
|
-
def entries
|
16
|
-
app.soup.all_snips.map do |snip|
|
17
|
-
Atom::Entry.new do |e|
|
18
|
-
# e.published = snip.created_at
|
19
|
-
# e.updated = snip.updated_at || snip.created_at
|
20
|
-
e.content = Atom::Content::Html.new(app.render(snip))
|
21
|
-
# e.title = snip.name
|
22
|
-
# e.authors = [Atom::Person.new(:name => snip.author || domain)]
|
23
|
-
# e.links << Atom::Link.new(:href => "http://#{domain}#{url_to(snip.name)}")
|
24
|
-
# e.id = "tag:#{domain},#{(snip.created_at.to_s || Date.today.to_s).split[0]}:/#{snip.name}"
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
self
|
30
|
-
end
|
File without changes
|