sinatra-s3 0.98

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 (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