vanilla 1.17.1 → 1.17.2
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/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
|