eduardo-vanilla 1.0.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.
Files changed (56) hide show
  1. data/README +53 -0
  2. data/Rakefile +121 -0
  3. data/bin/vanilla +9 -0
  4. data/config.example.yml +5 -0
  5. data/config.ru +9 -0
  6. data/lib/defensio.rb +59 -0
  7. data/lib/tasks/vanilla.rake +178 -0
  8. data/lib/vanilla.rb +20 -0
  9. data/lib/vanilla/app.rb +87 -0
  10. data/lib/vanilla/console.rb +3 -0
  11. data/lib/vanilla/dynasnip.rb +110 -0
  12. data/lib/vanilla/dynasnips/code.rb +16 -0
  13. data/lib/vanilla/dynasnips/comments.rb +108 -0
  14. data/lib/vanilla/dynasnips/current_snip.rb +32 -0
  15. data/lib/vanilla/dynasnips/debug.rb +13 -0
  16. data/lib/vanilla/dynasnips/edit.rb +63 -0
  17. data/lib/vanilla/dynasnips/edit_link.rb +24 -0
  18. data/lib/vanilla/dynasnips/index.rb +11 -0
  19. data/lib/vanilla/dynasnips/kind.rb +70 -0
  20. data/lib/vanilla/dynasnips/link_to.rb +14 -0
  21. data/lib/vanilla/dynasnips/link_to_current_snip.rb +16 -0
  22. data/lib/vanilla/dynasnips/login.rb +56 -0
  23. data/lib/vanilla/dynasnips/new.rb +14 -0
  24. data/lib/vanilla/dynasnips/notes.rb +42 -0
  25. data/lib/vanilla/dynasnips/pre.rb +19 -0
  26. data/lib/vanilla/dynasnips/rand.rb +27 -0
  27. data/lib/vanilla/dynasnips/raw.rb +19 -0
  28. data/lib/vanilla/dynasnips/url_to.rb +7 -0
  29. data/lib/vanilla/renderers/base.rb +78 -0
  30. data/lib/vanilla/renderers/bold.rb +9 -0
  31. data/lib/vanilla/renderers/erb.rb +16 -0
  32. data/lib/vanilla/renderers/markdown.rb +13 -0
  33. data/lib/vanilla/renderers/raw.rb +9 -0
  34. data/lib/vanilla/renderers/ruby.rb +35 -0
  35. data/lib/vanilla/renderers/textile.rb +13 -0
  36. data/lib/vanilla/request.rb +68 -0
  37. data/lib/vanilla/routes.rb +29 -0
  38. data/lib/vanilla/snip_handling.rb +33 -0
  39. data/lib/vanilla/snips/start.rb +18 -0
  40. data/lib/vanilla/snips/system.rb +76 -0
  41. data/lib/vanilla/snips/tutorial.rb +158 -0
  42. data/lib/vanilla/test_snips.rb +85 -0
  43. data/spec/dynasnip_spec.rb +31 -0
  44. data/spec/renderers/base_renderer_spec.rb +40 -0
  45. data/spec/renderers/erb_renderer_spec.rb +27 -0
  46. data/spec/renderers/markdown_renderer_spec.rb +29 -0
  47. data/spec/renderers/raw_renderer_spec.rb +21 -0
  48. data/spec/renderers/ruby_renderer_spec.rb +42 -0
  49. data/spec/renderers/vanilla_app_detecting_renderer_spec.rb +35 -0
  50. data/spec/soup_test.db +0 -0
  51. data/spec/spec_helper.rb +64 -0
  52. data/spec/vanilla_app_spec.rb +38 -0
  53. data/spec/vanilla_presenting_spec.rb +84 -0
  54. data/spec/vanilla_request_spec.rb +73 -0
  55. data/spec/vanilla_snip_finding_spec.rb +28 -0
  56. metadata +173 -0
data/README ADDED
@@ -0,0 +1,53 @@
1
+ --~::{ Vanilla.rb }::~---
2
+ =========================
3
+
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
+
9
+ - H.P. Gemcraft, 1914
10
+
11
+ A Preface; A Warning
12
+ ====================
13
+
14
+ The base flavour. The classic ice cream. Except riddled through with blood-red gemstones - Ruby gemstones.
15
+ This mad gelato will break your teeth.
16
+
17
+ ... and run the freakiest wiki-wonki-wiki-wonki-wiki-wonki-wickedy-wiki you've ever seen.
18
+
19
+ But you must not fear: fear is the mind-killer; fear is the little death that brings total oblivion;
20
+ fear is the chilling terror that makes you believe that *everything* is better when Model lays with
21
+ Controller and View in peace.
22
+
23
+ Vanilla.rb cries "HERESY!" upon that layered orgy of filth. Vanilla.rb says "EMBRACE CHAOS!". Vanilla.rb
24
+ says "EVERY SNIP FOR THEMSELVES!". Vanilla.rb waits quietly, in the dark corners.
25
+
26
+ Use at your own risk; really. I showed it to a cat, and the cat started talking in French.
27
+ It was MESSED. UP.
28
+
29
+
30
+ Thee Darke Invocation
31
+ =====================
32
+
33
+ $ gem install vanilla
34
+
35
+ $ vanilla my_app_name
36
+
37
+ ... a bunch of stuff gets created
38
+
39
+ $ cd my_app_name
40
+ $ rackup
41
+
42
+ ... the wonki starts. THE PAIN BEGINS.
43
+
44
+ (Try going to http://localhost:9292/vanilla-rb-tutorial to salve the chafing.)
45
+
46
+
47
+ Working with Vanilla
48
+ ====================
49
+
50
+ Currently unknowable; soon I hope to compile such a nercronomicon as to allow mortal kind to
51
+ conjure up Snips and Dynasnips and Renderers...
52
+
53
+ For the moment, see http://interblah.net/vanilla-rb-tutorial
data/Rakefile ADDED
@@ -0,0 +1,121 @@
1
+ $LOAD_PATH.unshift File.join(File.dirname(__FILE__), 'lib')
2
+ require 'vanilla'
3
+
4
+ require 'spec'
5
+ require 'spec/rake/spectask'
6
+ Spec::Rake::SpecTask.new do |t|
7
+ t.spec_opts = %w(--format specdoc --colour)
8
+ t.libs = ["spec"]
9
+ end
10
+
11
+ task :default => :spec
12
+
13
+
14
+ require "rubygems"
15
+ require "rake/gempackagetask"
16
+ require "rake/rdoctask"
17
+
18
+ # This builds the actual gem. For details of what all these options
19
+ # mean, and other ones you can add, check the documentation here:
20
+ #
21
+ # http://rubygems.org/read/chapter/20
22
+ #
23
+ spec = Gem::Specification.new do |s|
24
+
25
+ # Change these as appropriate
26
+ s.name = "vanilla"
27
+ s.version = "1.0.1"
28
+ s.summary = "A bliki-type web content thing."
29
+ s.author = "James Adam"
30
+ s.email = "james@lazyatom.com.com"
31
+ s.homepage = "http://github.com/lazyatom/vanilla-rb"
32
+
33
+ s.has_rdoc = true
34
+ s.extra_rdoc_files = %w(README)
35
+ s.rdoc_options = %w(--main README)
36
+
37
+ # Add any extra files to include in the gem
38
+ s.files = %w(config.example.yml config.ru Rakefile README) + Dir.glob("{spec,lib,bin}/**/*")
39
+ s.executables = ['vanilla']
40
+ s.require_paths = ["lib"]
41
+
42
+ # All the other gems we need.
43
+ s.add_dependency("rack", ">= 0.9.1")
44
+ s.add_dependency("soup", ">= 0.2.1")
45
+ s.add_dependency("ratom", ">= 0.3.5")
46
+ s.add_dependency("RedCloth", ">= 4.1.1")
47
+ s.add_dependency("BlueCloth", ">= 1.0.0")
48
+
49
+ s.add_development_dependency("rspec") # add any other gems for testing/development
50
+
51
+ # If you want to publish automatically to rubyforge, you'll may need
52
+ # to tweak this, and the publishing task below too.
53
+ s.rubyforge_project = "vanilla"
54
+ end
55
+
56
+ # This task actually builds the gem. We also regenerate a static
57
+ # .gemspec file, which is useful if something (i.e. GitHub) will
58
+ # be automatically building a gem for this project. If you're not
59
+ # using GitHub, edit as appropriate.
60
+ Rake::GemPackageTask.new(spec) do |pkg|
61
+ pkg.gem_spec = spec
62
+
63
+ # Generate the gemspec file for github.
64
+ file = File.dirname(__FILE__) + "/#{spec.name}.gemspec"
65
+ File.open(file, "w") {|f| f << spec.to_ruby }
66
+ end
67
+
68
+ # Generate documentation
69
+ Rake::RDocTask.new do |rd|
70
+ rd.main = "README"
71
+ rd.rdoc_files.include("README", "lib/**/*.rb")
72
+ rd.rdoc_dir = "rdoc"
73
+ end
74
+
75
+ desc 'Clear out RDoc and generated packages'
76
+ task :clean => [:clobber_rdoc, :clobber_package] do
77
+ rm "#{spec.name}.gemspec"
78
+ end
79
+
80
+ # If you want to publish to RubyForge automatically, here's a simple
81
+ # task to help do that. If you don't, just get rid of this.
82
+ # Be sure to set up your Rubyforge account details with the Rubyforge
83
+ # gem; you'll need to run `rubyforge setup` and `rubyforge config` at
84
+ # the very least.
85
+ begin
86
+ require "rake/contrib/sshpublisher"
87
+ namespace :rubyforge do
88
+
89
+ desc "Release gem and RDoc documentation to RubyForge"
90
+ task :release => ["rubyforge:release:gem", "rubyforge:release:docs"]
91
+
92
+ namespace :release do
93
+ desc "Release a new version of this gem"
94
+ task :gem => [:package] do
95
+ require 'rubyforge'
96
+ rubyforge = RubyForge.new
97
+ rubyforge.configure
98
+ rubyforge.login
99
+ rubyforge.userconfig['release_notes'] = spec.summary
100
+ path_to_gem = File.join(File.dirname(__FILE__), "pkg", "#{spec.name}-#{spec.version}.gem")
101
+ puts "Publishing #{spec.name}-#{spec.version.to_s} to Rubyforge..."
102
+ rubyforge.add_release(spec.rubyforge_project, spec.name, spec.version.to_s, path_to_gem)
103
+ end
104
+
105
+ desc "Publish RDoc to RubyForge."
106
+ task :docs => [:rdoc] do
107
+ config = YAML.load(
108
+ File.read(File.expand_path('~/.rubyforge/user-config.yml'))
109
+ )
110
+
111
+ host = "#{config['username']}@rubyforge.org"
112
+ remote_dir = "/var/www/gforge-projects/vanilla-rb/" # Should be the same as the rubyforge project name
113
+ local_dir = 'rdoc'
114
+
115
+ Rake::SshDirPublisher.new(host, remote_dir, local_dir).upload
116
+ end
117
+ end
118
+ end
119
+ rescue LoadError
120
+ puts "Rake SshDirPublisher is unavailable or your rubyforge environment is not configured."
121
+ end
data/bin/vanilla ADDED
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rubygems'
3
+ require 'rake'
4
+ load File.join(File.dirname(__FILE__), *%w[.. lib tasks vanilla.rake])
5
+
6
+ mkdir(ARGV[0])
7
+ cd(ARGV[0])
8
+
9
+ Rake::Task['vanilla:setup'].invoke
@@ -0,0 +1,5 @@
1
+ ---
2
+ :filename: config.example.yml
3
+ :secret: a6bc097eff86cabd92ee72ba4687c3f057b7556deaa3e4a6b284460871056b87ba3e91548c37dcc44fbc10241cee5b386556e6bcc2946fd9b609dc3bc1b24488
4
+ :credentials:
5
+ admin: 5f4dcc3b5aa765d61d8327deb882cf99
data/config.ru ADDED
@@ -0,0 +1,9 @@
1
+ require 'vanilla'
2
+
3
+ app = Vanilla::App.new(ENV['VANILLA_CONFIG'])
4
+ use Rack::Session::Cookie, :key => 'vanilla.session',
5
+ :path => '/',
6
+ :expire_after => 2592000,
7
+ :secret => app.config[:secret]
8
+ use Rack::Static, :urls => ["/public"], :root => File.join(File.dirname(__FILE__))
9
+ run app
data/lib/defensio.rb ADDED
@@ -0,0 +1,59 @@
1
+ class Defensio
2
+ class << self
3
+ attr_accessor :format
4
+ attr_accessor :service_type
5
+ attr_accessor :api_version
6
+ attr_accessor :api_key
7
+ attr_accessor :owner_url
8
+ end
9
+
10
+ self.format = :xml
11
+ self.service_type = :app # Can be :blog
12
+ self.api_version = '1.2'
13
+
14
+ def self.configure(confhash)
15
+ if confhash['test']
16
+ @mock = true
17
+ self.owner_url = 'http://www.example.com'
18
+ return
19
+ else
20
+ confhash.each do |prop, val|
21
+ self.send("#{prop}=", val)
22
+ end
23
+ end
24
+ end
25
+
26
+ def self.method_missing(name, *args)
27
+ self.post(name.to_s.dasherize, *args)
28
+ end
29
+
30
+ private
31
+ def self.connection
32
+ uri = URI.parse('http://api.defensio.com/')
33
+ Net::HTTP.start(uri.host, uri.port)
34
+ end
35
+
36
+ def self.post(action, params = {})
37
+ resp = connection.post(real_path(action), params_from_hash(params))
38
+ raise "Problem with request: #{action}" unless resp.code == '200'
39
+ parse_response(resp.body)
40
+ end
41
+
42
+ def self.real_path(action)
43
+ "/#{service_type}/#{api_version}/#{action}/#{api_key}.#{format}"
44
+ end
45
+
46
+ def self.params_from_hash(params = {})
47
+ # Thanks Net::HTTPHeader
48
+ params.stringify_keys.merge('owner-url' => owner_url).map {|k,v| "#{CGI.escape(k.dasherize.to_s)}=#{CGI.escape(v.to_s)}" }.join('&')
49
+ end
50
+
51
+ def self.parse_response(body)
52
+ case format
53
+ when :yaml
54
+ YAML.load(body)
55
+ when :xml
56
+ Hash.from_xml(body)
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,178 @@
1
+ $LOAD_PATH.unshift(File.expand_path(File.join(File.dirname(__FILE__), '..')))
2
+ require 'vanilla'
3
+
4
+ namespace :vanilla do
5
+ desc "Open an irb session preloaded with this library"
6
+ task :console do
7
+ sh "irb -Ilib -rubygems -rvanilla -rvanilla/console"
8
+ end
9
+
10
+ task :clean do
11
+ # TODO: get the database name from Soup
12
+ FileUtils.rm "soup.db" if File.exist?("soup.db")
13
+ end
14
+
15
+ task :prepare do
16
+ Soup.prepare
17
+ end
18
+
19
+ task :load_snips => :prepare do
20
+ Dynasnip.persist_all!(overwrite=true)
21
+
22
+ Dir[File.join(File.dirname(__FILE__), '..', 'vanilla', 'snips', '*.rb')].each do |f|
23
+ p "loading #{f}"
24
+ load f
25
+ end
26
+
27
+ load File.join(File.dirname(__FILE__), *%w[.. vanilla test_snips.rb])
28
+
29
+ puts "The soup is simmering. Loaded #{Soup.tuple_class.count} tuples"
30
+ end
31
+
32
+ desc 'Resets the soup to contain the base snips only. Dangerous!'
33
+ task :reset => [:clean, :load_snips]
34
+
35
+ namespace :upgrade do
36
+ desc 'Upgrade the dynasnips'
37
+ task :dynasnips => :prepare do
38
+ Dynasnip.all.each do |dynasnip|
39
+ print "Upgrading #{dynasnip.snip_name}... "
40
+ # TODO: our confused Soup interface might return an array.
41
+ snip = Soup[dynasnip.snip_name]
42
+ if snip.empty? || snip.nil?
43
+ # it's a new dyna
44
+ Soup << dynasnip.snip_attributes
45
+ puts "(new)"
46
+ elsif snip.created_at == snip.updated_at
47
+ # it's not been changed, let's upgrade
48
+ snip.destroy
49
+ Soup << dynasnip.snip_attributes
50
+ puts "(unedited)"
51
+ else
52
+ # the dyna exists and has been changed
53
+ dynasnip.snip_attributes.each do |name, value|
54
+ unless (existing_value = snip.get_value(name)) == value
55
+ puts "Conflict in attribute '#{name}':"
56
+ puts "> Your soup: '#{existing_value}'"
57
+ puts "> New soup: '#{value}"
58
+ print "Upgrade? [Y/n]: "
59
+ upgrade_value = ["Y", "y", ""].include? STDIN.gets.chomp.strip
60
+ snip.set_value(name, value) if upgrade_value
61
+ end
62
+ end
63
+ snip.save
64
+ end
65
+ end
66
+ end
67
+ end
68
+
69
+ desc 'Upgrade dynasnips and system snips'
70
+ task :upgrade => ["upgrade:dynasnips"]
71
+
72
+ desc 'Add a user (or change an existing password)'
73
+ task :add_user => :prepare do
74
+ puts "Adding a new user"
75
+ # config_file = ENV['VANILLA_CONFIG'] || 'config.yml'
76
+ # config_file = YAML.load(File.open(config_file)) rescue {}
77
+ app = Vanilla::App.new(ENV['VANILLA_CONFIG'])
78
+ print "Username: "
79
+ username = STDIN.gets.chomp.strip
80
+ print "Password: "
81
+ password = STDIN.gets.chomp.strip
82
+ print "Confirm password: "
83
+ confirm_password = STDIN.gets.chomp.strip
84
+ if password != confirm_password
85
+ raise "Passwords don't match!"
86
+ else
87
+ app.config[:credentials] ||= {}
88
+ app.config[:credentials][username] = MD5.md5(password).to_s
89
+ app.config.save!
90
+ puts "User '#{username}' added."
91
+ end
92
+ end
93
+
94
+ desc 'Generate file containing secret for cookie-based session storage'
95
+ task :generate_secret do
96
+ # Adapted from old rails secret generator.
97
+ require 'openssl'
98
+ if !File.exist?("/dev/urandom")
99
+ # OpenSSL transparently seeds the random number generator with
100
+ # data from /dev/urandom. On platforms where that is not
101
+ # available, such as Windows, we have to provide OpenSSL with
102
+ # our own seed. Unfortunately there's no way to provide a
103
+ # secure seed without OS support, so we'll have to do with
104
+ # rand() and Time.now.usec().
105
+ OpenSSL::Random.seed(rand(0).to_s + Time.now.usec.to_s)
106
+ end
107
+ data = OpenSSL::BN.rand(2048, -1, false).to_s
108
+ secret = OpenSSL::Digest::SHA512.new(data).hexdigest
109
+ app = Vanilla::App.new(ENV['VANILLA_CONFIG'])
110
+ app.config[:secret] = secret
111
+ app.config.save!
112
+ puts "Secret generated."
113
+ end
114
+
115
+ desc 'Prepare standard files to run Vanilla'
116
+ task :prepare_files do
117
+ cp File.join(File.dirname(__FILE__), *%w[.. .. config.ru]), 'config.ru'
118
+ cp_r File.join(File.dirname(__FILE__), *%w[.. .. public]), 'public'
119
+ mkdir 'tmp'
120
+ File.open("Rakefile", "w") do |f|
121
+ rakefile =<<-EOF
122
+ require 'vanilla'
123
+ load 'tasks/vanilla.rake'
124
+
125
+ # Add any other tasks here.
126
+ EOF
127
+ f.write rakefile.strip
128
+ end
129
+ end
130
+
131
+
132
+ desc 'Prepare a new vanilla.rb installation'
133
+ task :setup do
134
+ puts <<-EOM
135
+
136
+ ===================~ Vanilla.rb ~====================
137
+
138
+ Congratulations! You have elected to try out the weirdest web thing ever.
139
+ Lets get started. Firstly, I'm going to cook you some soup:
140
+
141
+
142
+ EOM
143
+ Rake::Task['vanilla:load_snips'].invoke
144
+
145
+ puts <<-EOM
146
+
147
+ Now I'm going to generate your configuration. This will be stored either in
148
+ 'config.yml' in the current directory, or in the path you provide via the
149
+ environment variable VANILLA_CONFIG.
150
+
151
+ Generating the secret for cookie-based session storage.
152
+ EOM
153
+ Rake::Task['vanilla:prepare_files'].invoke
154
+ Rake::Task['vanilla:generate_secret'].invoke
155
+
156
+ puts <<-EOM
157
+
158
+
159
+ Now that we've got our broth, you'll want to add a user, so you can edit stuff.
160
+ Lets do that now:
161
+
162
+
163
+ EOM
164
+ Rake::Task['vanilla:add_user'].invoke
165
+ puts <<-EOM
166
+
167
+
168
+ OK! You're ready to go. To start vanilla.rb, you'll want to get it running under
169
+ a webserver that supports Rack. The easiest way to do this locally is via 'rackup':
170
+
171
+ $ rackup
172
+
173
+ Then go to http://localhost:9292
174
+
175
+ I'm going now, Goodbye!
176
+ EOM
177
+ end
178
+ end
data/lib/vanilla.rb ADDED
@@ -0,0 +1,20 @@
1
+ require 'rubygems'
2
+
3
+ gem 'soup', '>= 0.1.4'
4
+ require 'soup'
5
+ require 'vanilla/snip_handling'
6
+
7
+ module Vanilla
8
+ include SnipHandling
9
+ end
10
+
11
+ # Load all the other renderer subclasses
12
+ Dir[File.join(File.dirname(__FILE__), 'vanilla', 'renderers', '*.rb')].each { |f| require f }
13
+
14
+ # Load the routing information
15
+ require 'vanilla/routes'
16
+
17
+ # Load all the base dynasnip classes
18
+ Dir[File.join(File.dirname(__FILE__), 'vanilla', 'dynasnips', '*.rb')].each do |dynasnip|
19
+ require dynasnip
20
+ end