sinatra-s3 0.98

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. data/README +23 -0
  2. data/Rakefile +51 -0
  3. data/bin/sinatra-s3 +30 -0
  4. data/db/migrate/001_create_bits.rb +28 -0
  5. data/db/migrate/002_create_users.rb +24 -0
  6. data/db/migrate/003_create_bits_users.rb +16 -0
  7. data/db/migrate/004_create_torrents.rb +22 -0
  8. data/db/migrate/005_create_torrent_peers.rb +26 -0
  9. data/examples/README +9 -0
  10. data/examples/wiki.rb +199 -0
  11. data/examples/wiki.ru +5 -0
  12. data/examples/wikicloth/MIT-LICENSE +20 -0
  13. data/examples/wikicloth/README +81 -0
  14. data/examples/wikicloth/Rakefile +23 -0
  15. data/examples/wikicloth/init.rb +1 -0
  16. data/examples/wikicloth/install.rb +0 -0
  17. data/examples/wikicloth/lib/core_ext.rb +43 -0
  18. data/examples/wikicloth/lib/wiki_buffer/html_element.rb +237 -0
  19. data/examples/wikicloth/lib/wiki_buffer/link.rb +70 -0
  20. data/examples/wikicloth/lib/wiki_buffer/table.rb +159 -0
  21. data/examples/wikicloth/lib/wiki_buffer/var.rb +77 -0
  22. data/examples/wikicloth/lib/wiki_buffer.rb +279 -0
  23. data/examples/wikicloth/lib/wiki_cloth.rb +61 -0
  24. data/examples/wikicloth/lib/wiki_link_handler.rb +138 -0
  25. data/examples/wikicloth/lib/wikicloth.rb +5 -0
  26. data/examples/wikicloth/run_tests.rb +48 -0
  27. data/examples/wikicloth/sample_documents/air_force_one.wiki +170 -0
  28. data/examples/wikicloth/sample_documents/cheatsheet.wiki +205 -0
  29. data/examples/wikicloth/sample_documents/default.css +34 -0
  30. data/examples/wikicloth/sample_documents/elements.wiki +7 -0
  31. data/examples/wikicloth/sample_documents/george_washington.wiki +526 -0
  32. data/examples/wikicloth/sample_documents/images.wiki +15 -0
  33. data/examples/wikicloth/sample_documents/lists.wiki +421 -0
  34. data/examples/wikicloth/sample_documents/pipe_trick.wiki +68 -0
  35. data/examples/wikicloth/sample_documents/random.wiki +55 -0
  36. data/examples/wikicloth/sample_documents/tv.wiki +312 -0
  37. data/examples/wikicloth/sample_documents/wiki.png +0 -0
  38. data/examples/wikicloth/sample_documents/wiki_tables.wiki +410 -0
  39. data/examples/wikicloth/tasks/wikicloth_tasks.rake +0 -0
  40. data/examples/wikicloth/test/test_helper.rb +3 -0
  41. data/examples/wikicloth/test/wiki_cloth_test.rb +8 -0
  42. data/examples/wikicloth/uninstall.rb +0 -0
  43. data/examples/wikicloth/wikicloth-0.1.3.gem +0 -0
  44. data/examples/wikicloth/wikicloth.gemspec +69 -0
  45. data/lib/sinatra-s3/admin.rb +626 -0
  46. data/lib/sinatra-s3/base.rb +526 -0
  47. data/lib/sinatra-s3/errors.rb +51 -0
  48. data/lib/sinatra-s3/ext.rb +20 -0
  49. data/lib/sinatra-s3/helpers/acp.rb +100 -0
  50. data/lib/sinatra-s3/helpers/admin.rb +41 -0
  51. data/lib/sinatra-s3/helpers/tracker.rb +42 -0
  52. data/lib/sinatra-s3/helpers/versioning.rb +27 -0
  53. data/lib/sinatra-s3/helpers.rb +79 -0
  54. data/lib/sinatra-s3/models/bit.rb +180 -0
  55. data/lib/sinatra-s3/models/bucket.rb +81 -0
  56. data/lib/sinatra-s3/models/file_info.rb +3 -0
  57. data/lib/sinatra-s3/models/git_bucket.rb +3 -0
  58. data/lib/sinatra-s3/models/slot.rb +47 -0
  59. data/lib/sinatra-s3/models/torrent.rb +6 -0
  60. data/lib/sinatra-s3/models/torrent_peer.rb +5 -0
  61. data/lib/sinatra-s3/models/user.rb +35 -0
  62. data/lib/sinatra-s3/s3.rb +57 -0
  63. data/lib/sinatra-s3/tasks.rb +62 -0
  64. data/lib/sinatra-s3/tracker.rb +134 -0
  65. data/lib/sinatra-s3.rb +1 -0
  66. data/public/css/control.css +225 -0
  67. data/public/css/wiki.css +47 -0
  68. data/public/images/external-link.gif +0 -0
  69. data/public/js/prototype.js +2539 -0
  70. data/public/js/upload_status.js +117 -0
  71. data/public/test.html +8 -0
  72. data/s3.yml.example +17 -0
  73. data/test/s3api_test.rb +121 -0
  74. data/test/test_helper.rb +25 -0
  75. metadata +156 -0
data/README ADDED
@@ -0,0 +1,23 @@
1
+ An implementation of the S3 API in Sinatra. Most of the code was originaly taken from
2
+ ParkPlace, another S3 clone written by _why.
3
+
4
+ Requirements
5
+ -------------------------------------------------------
6
+
7
+ gem install sinatra haml aws-s3
8
+
9
+ Optional Torrent Support
10
+ -------------------------------------------------------
11
+
12
+ If you are interested in using Sinatra-S3 as a Bittorrent tracker you will need a custom
13
+ version of RubyTorrent found at http://github.com/nricciar/rubytorrent.
14
+
15
+ Install
16
+ -------------------------------------------------------
17
+
18
+ 1) cp s3.yml.example s3.yml
19
+ 2) edit s3.yml to suit your needs
20
+ 3) rake db:migrate
21
+ 4) rackup config.ru -p 6060
22
+ 5) go to http://localhost:6060/control/ and login with the username admin and the
23
+ password pass@word1
data/Rakefile ADDED
@@ -0,0 +1,51 @@
1
+ $:.unshift "./lib"
2
+ require 'rake'
3
+ require 'rake/testtask'
4
+ require 'rake/gempackagetask'
5
+ require 'sinatra-s3'
6
+ require 'sinatra-s3/tasks'
7
+
8
+ spec = Gem::Specification.new do |s|
9
+ s.name = "sinatra-s3"
10
+ s.version = S3::VERSION
11
+ s.author = "David Ricciardi"
12
+ s.email = "nricciar@gmail.com"
13
+ s.homepage = "http://github.com/nricciar/sinatra-s3"
14
+ s.platform = Gem::Platform::RUBY
15
+ s.summary = "An implementation of the Amazon S3 API in Ruby"
16
+ s.files = FileList["{bin,lib,public,examples}/**/*"].to_a +
17
+ FileList["db/migrate/*"].to_a +
18
+ ["Rakefile","s3.yml.example"]
19
+ s.require_path = "lib"
20
+ s.executables = ['sinatra-s3']
21
+ s.test_files = FileList["{test}/*.rb"].to_a
22
+ s.has_rdoc = false
23
+ s.extra_rdoc_files = ["README"]
24
+ s.add_dependency("sinatra", ">= 1.0")
25
+ s.add_dependency("aws-s3", ">= 0.6.2")
26
+ s.add_dependency("haml", ">= 2.2.15")
27
+ end
28
+
29
+ Rake::GemPackageTask.new(spec) do |pkg|
30
+ pkg.need_tar = true
31
+ end
32
+
33
+ namespace :test do
34
+ find_file = lambda do |name|
35
+ file_name = lambda {|path| File.join(path, "#{name}.rb")}
36
+ root = $:.detect do |path|
37
+ File.exist?(file_name[path])
38
+ end
39
+ file_name[root] if root
40
+ end
41
+
42
+ TEST_LOADER = find_file['rake/rake_test_loader']
43
+ multiruby = lambda do |glob|
44
+ system 'multiruby', TEST_LOADER, *Dir.glob(glob)
45
+ end
46
+
47
+ Rake::TestTask.new(:all) do |test|
48
+ test.pattern = 'test/**/*_test.rb'
49
+ test.verbose = true
50
+ end
51
+ end
data/bin/sinatra-s3 ADDED
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rubygems'
3
+ require 'sinatra-s3'
4
+
5
+ if ARGV.any? { |arg| %w(--version -v).any? { |flag| arg == flag } }
6
+ puts "Sinatra-S3 #{S3::VERSION}"
7
+ exit 0
8
+ end
9
+
10
+ app_path = ARGV.last
11
+ install_success = false
12
+
13
+ unless File.exists?(app_path)
14
+ FileUtils.mkdir_p(app_path)
15
+
16
+ config_ru = "require 'rubygems'\nrequire 'sinatra-s3'"
17
+ if ARGV.any? { |arg| %w(--include-wiki --wiki).any? { |flag| arg == flag } }
18
+ FileUtils.copy(File.join(S3::ROOT_DIR,"examples","wiki.rb"), File.join(app_path,"wiki.rb"))
19
+ config_ru += "\nrequire 'wiki'"
20
+ end
21
+ config_ru += "\n\nuse S3::Tracker if defined?(RubyTorrent)\nuse S3::Admin\nrun S3::Application"
22
+ File.open(File.join(app_path,"config.ru"),"w") { |f| f.write(config_ru) }
23
+
24
+ File.open(File.join(app_path,"Rakefile"),"w") { |f| f.write("require 'sinatra-s3/tasks'") }
25
+ FileUtils.copy(File.join(S3::ROOT_DIR,"s3.yml.example"), File.join(app_path,"s3.yml"))
26
+
27
+ puts "Sinatra-S3 installed in #{app_path}."
28
+ else
29
+ puts "Unable to install Sinatra-S3. Install dir already exists."
30
+ end
@@ -0,0 +1,28 @@
1
+ class CreateBits < ActiveRecord::Migration
2
+
3
+ def self.up
4
+ create_table :bits do |t|
5
+ t.column :id, :integer, :null => false
6
+ t.column :owner_id, :integer
7
+ t.column :parent_id, :integer
8
+ t.column :lft, :integer
9
+ t.column :rgt, :integer
10
+ t.column :type, :string, :limit => 6
11
+ t.column :name, :string, :limit => 255
12
+ t.column :created_at, :timestamp
13
+ t.column :updated_at, :timestamp
14
+ t.column :access, :integer
15
+ t.column :meta, :text
16
+ t.column :obj, :text
17
+ t.column :size, :integer, :default => 0
18
+ t.column :version, :string
19
+ t.column :deleted, :integer, :default => 0
20
+ end
21
+ add_index :bits, :name
22
+ end
23
+
24
+ def self.down
25
+ drop_table :bits
26
+ end
27
+
28
+ end
@@ -0,0 +1,24 @@
1
+ class CreateUsers < ActiveRecord::Migration
2
+
3
+ def self.up
4
+ create_table :users do |t|
5
+ t.column :id, :integer, :null => false
6
+ t.column :login, :string, :limit => 40
7
+ t.column :password, :string, :limit => 40
8
+ t.column :email, :string, :limit => 64
9
+ t.column :key, :string, :limit => 64
10
+ t.column :secret, :string, :limit => 64
11
+ t.column :created_at, :datetime
12
+ t.column :updated_at, :timestamp
13
+ t.column :activated_at, :datetime
14
+ t.column :superuser, :integer, :default => 0
15
+ t.column :deleted, :integer, :default => 0
16
+ end
17
+ end
18
+
19
+ def self.down
20
+ drop_table :users
21
+ end
22
+
23
+ end
24
+
@@ -0,0 +1,16 @@
1
+ class CreateBitsUsers < ActiveRecord::Migration
2
+
3
+ def self.up
4
+ create_table :bits_users do |t|
5
+ t.column :bit_id, :integer
6
+ t.column :user_id, :integer
7
+ t.column :access, :integer
8
+ end
9
+ end
10
+
11
+ def self.down
12
+ drop_table :bits_users
13
+ end
14
+
15
+ end
16
+
@@ -0,0 +1,22 @@
1
+ class CreateTorrents < ActiveRecord::Migration
2
+
3
+ def self.up
4
+ create_table :torrents do |t|
5
+ t.column :id, :integer, :null => false
6
+ t.column :bit_id, :integer
7
+ t.column :info_hash, :string, :limit => 40
8
+ t.column :metainfo, :binary
9
+ t.column :seeders, :integer, :null => false, :default => 0
10
+ t.column :leechers, :integer, :null => false, :default => 0
11
+ t.column :hits, :integer, :null => false, :default => 0
12
+ t.column :total, :integer, :null => false, :default => 0
13
+ t.column :updated_at, :timestamp
14
+ end
15
+ end
16
+
17
+ def self.down
18
+ drop_table :torrents
19
+ end
20
+
21
+ end
22
+
@@ -0,0 +1,26 @@
1
+ class CreateTorrentPeers < ActiveRecord::Migration
2
+
3
+ def self.up
4
+ create_table :torrent_peers do |t|
5
+ t.column :id, :integer, :null => false
6
+ t.column :torrent_id, :integer
7
+ t.column :guid, :string, :limit => 40
8
+ t.column :ipaddr, :string
9
+ t.column :port, :integer
10
+ t.column :uploaded, :integer, :null => false, :default => 0
11
+ t.column :downloaded, :integer, :null => false, :default => 0
12
+ t.column :remaining, :integer, :null => false, :default => 0
13
+ t.column :compact, :integer, :null => false, :default => 0
14
+ t.column :event, :integer, :null => false, :default => 0
15
+ t.column :key, :string, :limit => 55
16
+ t.column :created_at, :timestamp
17
+ t.column :updated_at, :timestamp
18
+ end
19
+ end
20
+
21
+ def self.down
22
+ drop_table :torrent_peers
23
+ end
24
+
25
+ end
26
+
data/examples/README ADDED
@@ -0,0 +1,9 @@
1
+ To use the example wiki application insure you first have the wikicloth and ruby-git
2
+ gems installed, and you have followed all the Sinatra-S3 install instructions. Once
3
+ you have Sinatra-S3 running correctly run the following commands in the Sinatra-S3
4
+ root directory.
5
+
6
+ rake setup:wiki
7
+ rackup examples/wiki.ru -p 6060
8
+
9
+ Access your Wiki at http://localhost:6060/ and admin at http://localhost:6060/control/
data/examples/wiki.rb ADDED
@@ -0,0 +1,199 @@
1
+ require 'sinatra-s3'
2
+ require 'wikicloth'
3
+
4
+ S3::Application.callback :mime_type => 'text/wiki' do
5
+ headers["Content-Type"] = "text/html"
6
+ if params.has_key?('edit')
7
+ r :edit, "Editing #{@slot.name.gsub(/_/,' ')}"
8
+ elsif params.has_key?('diff')
9
+ @from = Bit.find_by_version(params[:diff])
10
+ @to = Bit.find_by_version(params[:to])
11
+ @diff = @from.diff(@to)
12
+ r :diff, "Changes to #{@slot.name.gsub(/_/,' ')}"
13
+ elsif params.has_key?('history')
14
+ @history = Slot.find(:all, :conditions => [ 'name = ? AND parent_id = ?', @slot.name, @slot.parent_id ], :order => "id DESC", :limit => 20)
15
+ r :history, "Revision history for #{@slot.name.gsub(/_/,' ')}"
16
+ else
17
+ p = {}
18
+ headers.each { |k,v| p[$1.upcase.gsub(/\-/,'_')] = v if k =~ /x-amz-(.*)/ }
19
+ @wiki = WikiCloth::WikiCloth.new({
20
+ :data => response.body.respond_to?(:read) ? response.body.read : response.body.to_s,
21
+ :link_handler => CustomLinkHandler.new,
22
+ :params => p
23
+ })
24
+ r :wiki, @slot.name.gsub(/_/,' ')
25
+ end
26
+ end
27
+
28
+ S3::Application.callback :error => 'NoSuchKey' do
29
+ headers["Content-Type"] = "text/html"
30
+ if params.has_key?('edit')
31
+ r :edit, "Edit Page"
32
+ else
33
+ r :does_not_exist, "Page Does Not Exist"
34
+ end
35
+ end
36
+
37
+ S3::Application.callback :error => 'AccessDenied' do
38
+ if env['PATH_INFO'].nil? || env['PATH_INFO'] == '/'
39
+ redirect '/wiki/Main_Page'
40
+ else
41
+ status 401
42
+ headers["WWW-Authenticate"] = %(Basic realm="wiki")
43
+ headers["Content-Type"] = "text/html"
44
+ r :access_denied, "Access Denied"
45
+ end
46
+ end
47
+
48
+ S3::Application.callback :when => 'before' do
49
+ #fix some caching issues
50
+ if params.has_key?('edit') || params.has_key?('history') || params.has_key?('diff')
51
+ env.delete('HTTP_IF_MODIFIED_SINCE')
52
+ env.delete('HTTP_IF_NONE_MATCH')
53
+ end
54
+
55
+ auth = Rack::Auth::Basic::Request.new(env)
56
+ next unless auth.provided? && auth.basic?
57
+
58
+ user = User.find_by_login(auth.credentials[0])
59
+ next if user.nil?
60
+
61
+ # Convert a valid basic authorization into a proper S3 AWS
62
+ # Authorization header
63
+ if user.password == hmac_sha1( auth.credentials[1], user.secret )
64
+ uri = env['PATH_INFO']
65
+ uri += "?" + env['QUERY_STRING'] if S3::RESOURCE_TYPES.include?(env['QUERY_STRING'])
66
+ canonical = [env['REQUEST_METHOD'], env['HTTP_CONTENT_MD5'], env['CONTENT_TYPE'],
67
+ (env['HTTP_X_AMZ_DATE'] || env['HTTP_DATE']), uri]
68
+ env['HTTP_AUTHORIZATION'] = "AWS #{user.key}:" + hmac_sha1(user.secret, canonical.map{|v|v.to_s.strip} * "\n")
69
+ end
70
+ end
71
+
72
+ class CustomLinkHandler < WikiCloth::WikiLinkHandler
73
+ def url_for(page)
74
+ page = page.strip.gsub(/\s+/,'_')
75
+ page = "/#{$1.downcase}/#{$2}" if page =~ /^([A-Za-z]+):(.*)$/
76
+ page
77
+ end
78
+
79
+ def link_attributes_for(page)
80
+ { :href => url_for(page) }
81
+ end
82
+
83
+ def external_link(url,text)
84
+ self.external_links << url
85
+ elem.a({ :href => url, :target => "_blank", :class => "exlink" }) { |x| x << (text.blank? ? url : text) }
86
+ end
87
+
88
+ def include_resource(resource,options=[])
89
+ if params[resource].nil?
90
+ begin
91
+ bucket = Bucket.find_root('templates')
92
+ slot = bucket.find_slot(resource)
93
+ unless slot.nil?
94
+ file = open(File.join(S3::STORAGE_PATH, slot.obj.path))
95
+ wiki_page = WikiCloth::WikiCloth.new({
96
+ :data => file.instance_of?(File) ? file.read : file.to_s,
97
+ :link_handler => self,
98
+ :params => params
99
+ })
100
+ return wiki_page.to_html
101
+ end
102
+ rescue S3::NoSuchKey
103
+ puts "Unknown resource #{resource}"
104
+ end
105
+ else
106
+ return params[resource]
107
+ end
108
+ end
109
+ end
110
+
111
+ class S3::Application < Sinatra::Base; enable :inline_templates; end
112
+
113
+ __END__
114
+
115
+ @@ layout
116
+ %html
117
+ %head
118
+ %title #{@title}
119
+ %style{:type => "text/css"}
120
+ @import '/control/s/css/control.css';
121
+ %style{:type => "text/css"}
122
+ @import '/control/s/css/wiki.css';
123
+ %body
124
+ %div#header
125
+ %h1
126
+ %a{:href => "/"} Wiki on Sinatra-S3
127
+ %div#page
128
+ - if status < 300
129
+ %div.menu
130
+ %ul
131
+ %li
132
+ %a{ :href => "#{env['PATH_INFO']}", :class => (!params.has_key?('diff') && !params.has_key?('history') && !params.has_key?('edit') ? "active" : "") } Content
133
+ %li
134
+ %a{ :href => "#{env['PATH_INFO']}?edit", :class => (params.has_key?('edit') ? "active" : "") } Edit
135
+ - if defined?(Git)
136
+ %li
137
+ %a{ :href => "#{env['PATH_INFO']}?history", :class => (params.has_key?('history') || params.has_key?('diff') ? "active" : "") } History
138
+ %h1 #{env['PATH_INFO'] =~ /\/([^\/]+)$/ ? "#{$1.gsub('_',' ')}" : "Sinatra-S3 Wiki"}
139
+ = yield
140
+
141
+ @@ access_denied
142
+ %h2 Access Denied
143
+ %p You are not authorized to access the specified resource.
144
+
145
+ @@ diff
146
+ %div#content
147
+ %p Change Summary: #{@diff.stats[:total][:insertions]} insertions and #{@diff.stats[:total][:deletions]} deletions
148
+ - @lines = @diff.patch.gsub('<','&lt;').gsub('>','&gt;').split("\n")
149
+ - @lines[4..-1].each do |line|
150
+ - case
151
+ - when line =~ /\-([0-9]+)(,([0-9]+)|) \+([0-9]+),([0-9]+)/
152
+ %div{ :style => "font-weight:bold;padding:5px 0" } Line #{$1}
153
+ - when line[0,1] == "\\"
154
+ - when line[0,1] == "+"
155
+ %ins{ :style => "background-color:#99ff99" } &nbsp;#{line[1,line.length]}
156
+ - when line[0,1] == "-"
157
+ %del{ :style => "background-color:#ff9999" } &nbsp;#{line[1,line.length]}
158
+ - else
159
+ %div{ :style => "background-color:#ebebeb" } &nbsp;#{line}
160
+
161
+ @@ does_not_exist
162
+ %h2 Page Does Not Exist
163
+ %p
164
+ The page you were trying to access does not exist. Perhaps you would like to
165
+ %a{ :href => "#{env['PATH_INFO']}?edit" } create it
166
+ ?
167
+
168
+ @@ edit
169
+ %h2 #{@slot.nil? ? "Edit Page" : "Editing #{@slot.name.gsub(/_/,' ')}"}
170
+ %form.create{ :method => "POST", :action => env['PATH_INFO'] }
171
+ %input{ :type => "hidden", :name => "redirect", :value => env['PATH_INFO'] }
172
+ %input{ :type => "hidden", :name => "Content-Type", :value => "text/wiki" }
173
+ %div.required
174
+ - page_contents = status >= 300 ? "" : (response.body.respond_to?(:read) ? response.body.read : response.body.to_s)
175
+ %label{ :for => "page_contents" } Contents
176
+ %textarea{ :name => "file", :id => "page_contents", :style => "width:100%;height:20em" } #{page_contents}
177
+ %div.required
178
+ %label{ :for => "page_comment" } Comment:
179
+ %input{ :type => "text", :name => "x-amz-meta-comment", :id => "page_comment" }
180
+ %input{ :type => "submit", :value => "Update" }
181
+
182
+ @@ history
183
+ %h2 Revision history of #{@slot.name.gsub(/_/,' ')}
184
+ %form{ :action => env['PATH_INFO'], :method => "GET" }
185
+ %table#revision_history
186
+ - @history.each_with_index do |rev, count|
187
+ %tr
188
+ %td.check
189
+ %input{ :type => "radio", :name => "diff", :value => rev.version }
190
+ %td.check
191
+ %input{ :type => "radio", :name => "to", :value => rev.version }
192
+ %td
193
+ %a{ :href => "#{env['PATH_INFO']}?version-id=#{rev.version}" } #{rev.meta['comment']}
194
+ on #{rev.updated_at}
195
+ %input{ :type => "submit", :value => "Compare Revisions" }
196
+
197
+ @@ wiki
198
+ %div#wiki_page
199
+ = preserve @wiki.to_html
data/examples/wiki.ru ADDED
@@ -0,0 +1,5 @@
1
+ $:.unshift "./lib"
2
+ require File.join(File.dirname(__FILE__), "wiki")
3
+
4
+ use S3::Admin
5
+ run S3::Application
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,81 @@
1
+ Ruby implementation of the MediaWiki markup language.
2
+
3
+ Supports
4
+ ---------------------------------------------------
5
+
6
+ * Variables, Templates {{ ... }}
7
+ * Links
8
+ o External Links [ ... ]
9
+ o Internal Links, Images [[ ... ]]
10
+ + (see also pipe trick)
11
+ * Wikimedia Markup
12
+ o == Headings ==
13
+ o Lists (*#;:)
14
+ o bold ('''), italic ('') or both (''''')
15
+ o Horizontal rule (----)
16
+ o Tables
17
+ * <code>,<nowiki>,<pre> (disable wiki markup)
18
+ o space at the beginning of a line (<pre>)
19
+ * <ref> and <references/> support
20
+ * html sanitization
21
+
22
+ Install
23
+ ---------------------------------------------------
24
+
25
+ git clone git://github.com/nricciar/wikicloth.git
26
+ cd wikicloth/
27
+ gem build wikicloth.gemspec
28
+ sudo gem install wikicloth-0.1.3.gem
29
+
30
+ Usage
31
+ ---------------------------------------------------
32
+
33
+ include WikiCloth
34
+
35
+ @wiki = WikiCloth.new({
36
+ :data => "<nowiki>{{test}}</nowiki> ''Hello {{test}}!''\n",
37
+ :params => { "test" => "World" } })
38
+ @wiki.to_html => "<p>&#123;&#123;test&#125;&#125; <i>Hello World!</i></p>"
39
+
40
+
41
+ Wiki Links and Variable/Template Handling
42
+ ---------------------------------------------------
43
+
44
+ Use the url_for and link_attributes_for methods to override the default URL for
45
+ an [[internal link]]. If you need even more control, the link_for can also be
46
+ used to return raw html.
47
+
48
+ class CustomLinkHandler < WikiCloth::WikiLinkHandler
49
+
50
+ def url_for(page)
51
+ "javascript:alert('You clicked on: #{page}');"
52
+ end
53
+
54
+ def link_attributes_for(page)
55
+ { :href => url_for(page) }
56
+ end
57
+
58
+ def include_resource(resource,options=[])
59
+ case resource
60
+ when "date"
61
+ Time.now.to_s
62
+ else
63
+ # default behavior
64
+ super(resource,options)
65
+ end
66
+ end
67
+
68
+ end
69
+
70
+
71
+ @wiki = WikiCloth::WikiCloth.new({
72
+ :params => { "PAGENAME" => "Testing123" },
73
+ :link_handler => CustomLinkHandler.new,
74
+ :data => "Hello World From {{ PAGENAME }} on {{ date }}\n"
75
+ })
76
+
77
+ @wiki.to_html =>
78
+ <p>
79
+ <a href="javascript:alert('You clicked on: Hello World');">Hello World</a> From Testing123 on Wed Jul 08 22:23:44 -0400 2009
80
+ </p>
81
+
@@ -0,0 +1,23 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rake/rdoctask'
4
+
5
+ desc 'Default: run unit tests.'
6
+ task :default => :test
7
+
8
+ desc 'Test the wikicloth plugin.'
9
+ Rake::TestTask.new(:test) do |t|
10
+ t.libs << 'lib'
11
+ t.libs << 'test'
12
+ t.pattern = 'test/**/*_test.rb'
13
+ t.verbose = true
14
+ end
15
+
16
+ desc 'Generate documentation for the wikicloth plugin.'
17
+ Rake::RDocTask.new(:rdoc) do |rdoc|
18
+ rdoc.rdoc_dir = 'rdoc'
19
+ rdoc.title = 'WikiCloth'
20
+ rdoc.options << '--line-numbers' << '--inline-source'
21
+ rdoc.rdoc_files.include('README')
22
+ rdoc.rdoc_files.include('lib/**/*.rb')
23
+ end
@@ -0,0 +1 @@
1
+ require File.join(File.expand_path(File.dirname(__FILE__)), "lib", "wikicloth")
File without changes
@@ -0,0 +1,43 @@
1
+ module ExtendedString
2
+
3
+ def blank?
4
+ respond_to?(:empty?) ? empty? : !self
5
+ end
6
+
7
+ def to_slug
8
+ self.gsub(/\W+/, '-').gsub(/^-+/,'').gsub(/-+$/,'').downcase
9
+ end
10
+
11
+ def auto_link
12
+ url_check = Regexp.new( '(^|[\n ])([\w]+?://[\w]+[^ \"\r\n\t<]*)', Regexp::MULTILINE | Regexp::IGNORECASE )
13
+ www_check = Regexp.new( '(^|[\n ])((www)\.[^ \"\t\n\r<]*)', Regexp::MULTILINE | Regexp::IGNORECASE )
14
+ self.gsub!(url_check, '\1<a href="\2">\2</a>')
15
+ self.gsub!(www_check, '\1<a href="http://\2">\2</a>')
16
+ to_s
17
+ end
18
+
19
+ def dump()
20
+ ret = to_s
21
+ delete!(to_s)
22
+ ret
23
+ end
24
+
25
+ def smart_split(char)
26
+ ret = []
27
+ tmp = ""
28
+ inside = 0
29
+ to_s.each_char do |x|
30
+ if x == char && inside == 0
31
+ ret << tmp
32
+ tmp = ""
33
+ else
34
+ inside += 1 if x == "[" || x == "{" || x == "<"
35
+ inside -= 1 if x == "]" || x == "}" || x == ">"
36
+ tmp += x
37
+ end
38
+ end
39
+ ret << tmp unless tmp.empty?
40
+ ret
41
+ end
42
+
43
+ end