wunderbar 0.8.13 → 0.8.14

Sign up to get free protection for your applications and to get access to all the features.
data/demo/wiki.html DELETED
@@ -1,73 +0,0 @@
1
- <!DOCTYPE html>
2
- <html xmlns="http://www.w3.org/1999/xhtml">
3
- <head>
4
- <meta charset="utf-8"/>
5
- <title>Wunderbar Wiki</title>
6
- </head>
7
- <body>
8
- <h2>Wunderbar Wiki</h2>
9
-
10
- <p>Note: demo code requires Ruby 1.9.2 or later. Wunderbar itself works with
11
- Ruby 1.8.7 or later.</p>
12
-
13
- <p>Prereqs:</p>
14
-
15
- <ul>
16
- <li><code>gem install wunderbar rdiscount</code></li>
17
- <li><code>apt-get install git</code></li>
18
- <li><a href="http://jquery.com/">jQuery</a></li>
19
- <li><a href="http://www.showdown.im/">Showdown</a></li>
20
- </ul>
21
-
22
-
23
- <p>Create a data directory (one per wiki):</p>
24
-
25
- <ul>
26
- <li>Must be writeable by your web server</li>
27
- <li>Should not be in the Document Root</li>
28
- </ul>
29
-
30
-
31
- <p>Configure git:</p>
32
-
33
- <ul>
34
- <li>Follow <a
35
- href="http://help.github.com/set-your-user-name-email-and-github-token/]">Step
36
- 1</a>.</li>
37
- <li>Note that this needs to be done for the user that the webserver runs the
38
- script under. If you are not running <a
39
- href="http://httpd.apache.org/docs/2.0/suexec.html">suexec</a>, this is
40
- typically <code>www-data</code> on Unix or <code>www</code> on Mac OS/X.</li>
41
- </ul>
42
-
43
-
44
- <p>Configure Apache:</p>
45
-
46
- <pre><code> Options +ExecCGI +MultiViews
47
- MultiViewsMatch Any
48
- AddHandler cgi-script .cgi
49
- </code></pre>
50
-
51
- <blockquote><p>Optionally configure <a href="http://httpd.apache.org/docs/2.4/howto/auth.html">Authentication</a> for multiple users.</p></blockquote>
52
-
53
- <p>Install scripts:</p>
54
-
55
- <ul>
56
- <li>Copy <code>jquery-min.js</code> and <code>showdown.js</code> into your
57
- document root</li>
58
- </ul>
59
-
60
-
61
- <p>Install wiki (one per wiki):</p>
62
-
63
- <pre><code> ruby wiki.rb --install=/var/www/wikiname.cgi --WIKIDATA="/full/path/to/data/directory"
64
- </code></pre>
65
-
66
- <blockquote><p>Optionally tailor the setting of the $EMAIL variable in the script. The current default logic is based on a Unix like operating system (such as Linux, Mac OS/X) with users having email addresses on this machine. Replace as needed.</p></blockquote>
67
-
68
- <p>Access your wiki:</p>
69
-
70
- <pre><code> http://localhost/wikiname/
71
- </code>
72
- </body>
73
- </html>
data/demo/wiki.rb DELETED
@@ -1,214 +0,0 @@
1
- #!/usr/bin/ruby
2
- require 'wunderbar'
3
- require 'rdiscount'
4
- require 'digest/md5'
5
-
6
- Dir.chdir WIKIDATA
7
-
8
- # parse request
9
- %r{/(?<file>.\w+)((?<flag>/)(?<rev>\w*))?$} =~ $env.PATH_INFO
10
- flag ||= '?' if $env.REQUEST_URI.include? '?'
11
- file ||= 'index'
12
-
13
- W_.html do
14
- _head_ do
15
- _title file
16
- _style %{
17
- body {background-color: #{(flag=='?') ? '#E0D8D8' : '#FFF'}}
18
- .status {border: 2px solid #000; border-radius: 1em; background: #FAFAD2; padding: 0.5em}
19
- .input, .output {border: 1px solid #888; position: relative; width: 47.5%; height: 400px; overflow: auto}
20
- .input {float: left; left: 1.5%}
21
- .output {float: right; right: 1.5%; background-color: #6C6666; color: #FFF}
22
- .buttons {clear: both; text-align: center; padding-top: 0.5em}
23
- #message {position: fixed; left: 2%; color: #9400d3}
24
- h1 {text-align: center; margin: 0}
25
- form {clear: both}
26
- .buttons form {display: inline}
27
- ._stdin:before {content: '$ '}
28
- ._stdin {color: #9400D3; margin-bottom: 0}
29
- ._stdout {margin: 0}
30
- ._stderr {margin: 0; color: red}
31
- }
32
- _script src: '/showdown.js'
33
- _script src: '/jquery.min.js'
34
- end
35
-
36
- _body? do
37
-
38
- # determine markup
39
- if _.post? and @markup
40
- _header.status do
41
- _h1 'Status'
42
- if File.exist?(file) and Digest::MD5.hexdigest(File.read(file)) != @hash
43
- _p 'Write conflict'
44
- else
45
- File.open(file, 'w') {|fh| fh.write @markup}
46
- _.system 'git init' unless Dir.exist? '.git'
47
- if `git status --porcelain #{file}`.empty?
48
- _p 'Nothing changed'
49
- else
50
- _.system "git add #{file}"
51
-
52
- commit = %w(git commit)
53
- commit << '--author' << $EMAIL if defined? $EMAIL and $EMAIL
54
- commit << '--message' << @comment
55
- commit << file
56
-
57
- _.system commit
58
- end
59
- end
60
- end
61
-
62
- elsif File.exist? file
63
- # existing file
64
- if !rev or rev.empty?
65
- @markup = File.read(file)
66
- else
67
- @markup = `git show #{rev}:#{file}`
68
- flag = nil
69
- end
70
-
71
- else
72
- # new file: go directly into edit mode
73
- @markup = "#{file}\n#{'-'*file.length}\n\nEnter your text here..."
74
- flag = '?'
75
- end
76
-
77
- # produce HTML
78
- if file == '_index'
79
-
80
- # index
81
- index = Hash[`git ls-tree HEAD --name-only`.scan(/(\w+)()/)].
82
- merge Hash[*`git status --porcelain`.scan(/(..) (\w+)/).flatten.reverse]
83
- _table do
84
- _tbody do
85
- index.sort.each do |name, status|
86
- _tr do
87
- _td status
88
- _td {_a name, href: name}
89
- end
90
- end
91
- end
92
- end
93
-
94
- elsif flag == '?'
95
-
96
- # edit mode
97
- _header do
98
- _h1 "~~~ #{file} ~~~"
99
- _span 'Input', style: 'float: left; margin-left: 2em'
100
- _span 'Output', style: 'float: right; margin-right: 2em'
101
- end
102
-
103
- _form_ action: file, method: 'post' do
104
- _textarea.input @markup, name: 'markup'
105
- _input type: 'hidden', name: 'hash',
106
- value: Digest::MD5.hexdigest(@markup)
107
- _div.output do
108
- _ << RDiscount.new(@markup).to_html
109
- end
110
-
111
- _div.buttons do
112
- _span.message!
113
- _input name: 'comment', placeholder: 'commit message'
114
- _input type: 'submit', value: 'save'
115
- end
116
- end
117
-
118
- elsif flag == '/'
119
-
120
- # revision history
121
- _h2 "Revision history for #{file}"
122
- _ul do
123
- `git log --format="%H|%ai|%an|%s" #{file}`.lines.each do |line|
124
- hash, date, author, subject = line.split('|')
125
- _li! {_a date, href: hash; _ " #{subject} by #{author}"}
126
- end
127
- end
128
-
129
- else
130
-
131
- #display
132
- _ << RDiscount.new(@markup).to_html
133
- _div_.buttons do
134
- if !rev or rev.empty?
135
- _form action: "#{file}?", method: 'post' do
136
- _input type: 'submit', value: 'edit'
137
- end
138
- end
139
- _form action: "#{file}/" do
140
- _input type: 'submit', value: 'history'
141
- end
142
- end
143
- end
144
-
145
- _script %{
146
- // autosave every 10 seconds
147
- var dirty = false;
148
- setInterval(function() {
149
- if (!dirty) return;
150
- dirty = false;
151
-
152
- var params = {
153
- markup: $('textarea[name=markup]').val(),
154
- hash: $('input[name=hash]').val()
155
- };
156
-
157
- $.getJSON("#{SELF}", params, function(_) {
158
- $('input[name=hash]').val(_.hash);
159
- if (_.time) {
160
- var time = new Date(_.time).toLocaleTimeString();
161
- $('#message').text("Autosaved at " + time).show().fadeOut(5000);
162
- } else {
163
- $('.input').val(_.markup).attr('readonly', 'readonly');
164
- $('#message').css({'font-weight': 'bold'}).text(_.error).show();
165
- }
166
- });
167
- }, 10000);
168
-
169
- // regenerate output every 0.5 seconds
170
- var updated = false;
171
- setInterval(function() {
172
- if (!updated) return;
173
- updated = false;
174
- $('.output').html(converter.makeHtml($('.input').val()));
175
- }, 500);
176
-
177
- // update output pane and mark dirty whenever input changes
178
- var converter = new Showdown.converter();
179
- $('.input').bind('input', function() {
180
- updated = dirty = true;
181
- }).trigger('input');
182
-
183
- // resize based on window size
184
- var reserve = $('header').height() * 3 + $('.buttons').height();
185
- $(window).resize(function() {
186
- $('.input,.output').height($(window).height()-reserve);
187
- }).trigger('resize');
188
- }
189
- end
190
- end
191
-
192
- # process autosave requests
193
- W_.json do
194
- hash = Digest::MD5.hexdigest(@markup)
195
- if File.exist?(file) and Digest::MD5.hexdigest(File.read(file)) != @hash
196
- {error: "Write conflict", markup: File.read(file), hash: hash}
197
- else
198
- File.open(file, 'w') {|fh| fh.write @markup} unless @hash == hash
199
- {time: Time.now.to_i*1000, hash: hash}
200
- end
201
- end
202
-
203
- __END__
204
- # Customize where the wiki data is stored
205
- WIKIDATA = '/full/path/to/data/directory'
206
-
207
- # git author e-mail address override
208
- require 'etc'
209
- begin
210
- name = Etc.getpwnam($USER).gecos.split(',').first
211
- $EMAIL = "#{name} <#{$USER}@#{$env.SERVER_NAME}>"
212
- $EMAIL = nil if %w(www-data _www).include?($USER)
213
- rescue
214
- end
data/test/test_builder.rb DELETED
@@ -1,35 +0,0 @@
1
- require 'test/unit'
2
- require 'rubygems'
3
- require 'wunderbar'
4
-
5
- class BuilderTest < Test::Unit::TestCase
6
- def test_empty
7
- x = Wunderbar::XmlMarkup.new :indent => 2
8
- x.tag!(:script) { x.indented_text! '' }
9
- assert_equal %{<script>\n</script>\n}, x.target!
10
- end
11
-
12
- def test_unindented_input
13
- x = Wunderbar::XmlMarkup.new :indent => 2
14
- x.tag!(:script) { x.indented_text! "{\n x: 1\n}" }
15
- assert_equal %{<script>\n {\n x: 1\n }\n</script>\n}, x.target!
16
- end
17
-
18
- def test_indented_input
19
- x = Wunderbar::XmlMarkup.new :indent => 2
20
- x.tag!(:script) { x.indented_text! " alert('danger');" }
21
- assert_equal %{<script>\n alert('danger');\n</script>\n}, x.target!
22
- end
23
-
24
- def test_exception
25
- x = Wunderbar::XmlMarkup.new :indent => 2
26
- x.tag!(:body) do
27
- begin
28
- x.tag!(:p) { raise Exception.new('boom') }
29
- rescue Exception => e
30
- x.tag!(:pre, e)
31
- end
32
- end
33
- assert x.target!.include? '<p>' and x.target!.include? '</p>'
34
- end
35
- end
@@ -1,200 +0,0 @@
1
- require 'test/unit'
2
- require 'rubygems'
3
- require 'wunderbar'
4
-
5
- class HtmlMarkupTest < Test::Unit::TestCase
6
- def setup
7
- @original_log_level = Wunderbar.logger.level
8
- Wunderbar.log_level = :fatal
9
- end
10
-
11
- def teardown
12
- Wunderbar.logger.level = @original_log_level
13
- end
14
-
15
- def test_html
16
- x = HtmlMarkup.new
17
- x.html {}
18
- assert_equal %{<html>\n</html>\n}, x.target!
19
- end
20
-
21
- def test_void_element
22
- x = HtmlMarkup.new
23
- x.html {_br}
24
- assert_match %r{<br/>}, x.target!
25
- end
26
-
27
- def test_normal_element
28
- x = HtmlMarkup.new
29
- x.html {_textarea}
30
- assert_match %r{<textarea></textarea>}, x.target!
31
- end
32
-
33
- def test_script_lang
34
- x = HtmlMarkup.new
35
- x.html {_script}
36
- assert_match %r[<script lang="text/javascript">], x.target!
37
- end
38
-
39
- def test_style_type
40
- x = HtmlMarkup.new
41
- x.html {_style}
42
- assert_match %r[<style type="text/css">], x.target!
43
- end
44
-
45
- def test_script_plain
46
- x = HtmlMarkup.new
47
- x.html {_script! 'alert("foo");'}
48
- assert_match %r[<script>alert\("foo"\);</script>], x.target!
49
- end
50
-
51
- def test_script_indent
52
- x = HtmlMarkup.new
53
- x.html {_script "if (i<1) {}"}
54
- assert_match %r[^ if], x.target!
55
- end
56
-
57
- def test_script_html
58
- $XHTML = false
59
- x = HtmlMarkup.new
60
- x.html {_script "if (i<1) {}"}
61
- assert_match %r[<script.*>\s*if \(i<1\) \{\}\s*</script>], x.target!
62
- end
63
-
64
- def test_script_xhtml
65
- $XHTML = true
66
- x = HtmlMarkup.new
67
- x.html {_script "if (i<1) {}"}
68
- assert_match %r[<script.*>\s*if \(i&lt;1\) \{\}\s*</script>], x.target!
69
- end
70
-
71
- def test_disable_indent
72
- x = HtmlMarkup.new
73
- x.html {_div! {_ "one "; _strong "two"; _ " three"}}
74
- assert_match %r[<div>one <strong>two</strong> three</div>], x.target!
75
- end
76
-
77
- def test_spaced_embedded
78
- x = HtmlMarkup.new
79
- x.html {_div {_p 'one'; _hr_; _p 'two'}}
80
- assert_match %r[<div>\n +<p>one</p>\n\n +<hr/>\n\n +<p>two</p>\n +</div>],
81
- x.target!
82
- end
83
-
84
- def test_spaced_collapsed
85
- x = HtmlMarkup.new
86
- x.html {_div {_p_ 'one'; _hr_; _p_ 'two'}}
87
- assert_match %r[<div>\n +<p>one</p>\n\n +<hr/>\n\n +<p>two</p>\n +</div>],
88
- x.target!
89
- end
90
-
91
- def test_traceback
92
- x = HtmlMarkup.new
93
- x.html {_body? {boom}}
94
- assert_match %r[<pre.*>#&lt;NameError: .*boom],
95
- x.target!
96
- end
97
-
98
- def test_traceback_default_style
99
- x = HtmlMarkup.new
100
- x.html {_body? {boom}}
101
- assert_match %r[<pre style="background-color:#ff0.*">], x.target!
102
- end
103
-
104
- def test_traceback_style_override
105
- x = HtmlMarkup.new
106
- x.html {_body?(:traceback_style => 'color:red') {boom}}
107
- assert_match %r[<pre style="color:red"], x.target!
108
- end
109
-
110
- def test_traceback_class_override
111
- x = HtmlMarkup.new
112
- x.html {_body?(:traceback_class => 'traceback') {boom}}
113
- assert_match %r[<pre class="traceback"], x.target!
114
- end
115
-
116
- def test_meta_charset
117
- x = HtmlMarkup.new
118
- x.html {_head}
119
- assert_match %r[<head>\s*<meta charset="utf-8"/>\s*</head>], x.target!
120
- end
121
-
122
- def test_nil_attribute
123
- x = HtmlMarkup.new
124
- x.html {_div :class => nil}
125
- assert_match %r[^ <div></div>], x.target!
126
- end
127
-
128
- def test_class_attribute
129
- x = HtmlMarkup.new
130
- x.html {_div.header {_span.text 'foo'}}
131
- assert_match %r[<div class="header">.*</div>]m, x.target!
132
- end
133
-
134
- def test_id_attribute
135
- x = HtmlMarkup.new
136
- x.html {_h1.content! 'Content'}
137
- assert_match %r[^ <h1 id="content">Content</h1>], x.target!
138
- end
139
-
140
- def test_boolean_attribute_false
141
- x = HtmlMarkup.new
142
- x.html {_option :selected => false}
143
- assert_match %r[^ <option></option>], x.target!
144
- end
145
-
146
- def test_boolean_attribute_true
147
- x = HtmlMarkup.new
148
- x.html {_option :selected => true}
149
- assert_match %r[^ <option selected="selected"></option>], x.target!
150
- end
151
-
152
- def test_indented_text
153
- x = HtmlMarkup.new
154
- x.html {_div {_ 'text'}}
155
- assert_match %r[^ <div>\n text\n </div>], x.target!
156
- end
157
-
158
- def test_unindented_text
159
- x = HtmlMarkup.new
160
- x.html {_div {_! "text\n"}}
161
- assert_match %r[^ <div>\ntext\n </div>], x.target!
162
- end
163
-
164
- def test_declare
165
- x = HtmlMarkup.new
166
- x._.declare :DOCTYPE, 'html'
167
- assert_equal %{<!DOCTYPE "html">\n}, x.target!
168
- end
169
-
170
- def test_comment
171
- x = HtmlMarkup.new
172
- x._.comment 'foo'
173
- assert_equal %{<!-- foo -->\n}, x.target!
174
- end
175
-
176
- def test_svg
177
- x = HtmlMarkup.new
178
- x.html {_svg}
179
- assert_match %r[^ <svg xmlns="http://www.w3.org/2000/svg"/>], x.target!
180
- end
181
-
182
- def test_math
183
- x = HtmlMarkup.new
184
- x.html {_math}
185
- assert_match %r[^ <math xmlns="http://www.w3.org/1998/Math/MathML"/>], x.target!
186
- end
187
-
188
- begin
189
- require 'coffee-script'
190
-
191
- def test_coffeescript
192
- x = HtmlMarkup.new
193
- x.html {_coffeescript 'alert "foo"'}
194
- assert_match %r[<script\slang="text/javascript">\s+\(function\(\)\s
195
- \{\s+alert\("foo"\);\s+\}\).call\(this\);\s+</script>]x, x.target!
196
- end
197
- rescue LoadError
198
- end
199
-
200
- end
data/test/test_logger.rb DELETED
@@ -1,76 +0,0 @@
1
- require 'test/unit'
2
- require 'rubygems'
3
- require 'wunderbar'
4
- require 'logger'
5
-
6
- class TestLogger
7
- attr_accessor :messages
8
- def initialize
9
- @messages = Hash.new {|hash, key| hash[key] = Array.new}
10
- @original_logger = Wunderbar.logger
11
- logger = self
12
- Wunderbar.instance_eval {@logger = logger}
13
- end
14
-
15
- def method_missing(method, *args)
16
- if [:debug, :info, :warn, :error, :fatal].include? method
17
- @messages[method] << args.first
18
- else
19
- @original_logger.send(method, *args)
20
- end
21
- end
22
-
23
- def teardown
24
- logger = @original_logger
25
- Wunderbar.instance_eval {@logger = logger}
26
- end
27
- end
28
-
29
- class LoggerTest < Test::Unit::TestCase
30
- def setup
31
- @logger = TestLogger.new
32
- end
33
-
34
- def teardown
35
- @logger.teardown
36
- end
37
-
38
- def test_debug
39
- Wunderbar.debug 'Sneezy'
40
- assert @logger.messages[:debug].include? 'Sneezy'
41
- end
42
-
43
- def test_info
44
- Wunderbar.info 'Sleepy'
45
- assert @logger.messages[:info].include? 'Sleepy'
46
- end
47
-
48
- def test_warn
49
- Wunderbar.warn 'Dopey'
50
- assert @logger.messages[:warn].include? 'Dopey'
51
- end
52
-
53
- def test_error
54
- Wunderbar.error 'Doc'
55
- assert @logger.messages[:error].include? 'Doc'
56
- end
57
-
58
- def test_fatal
59
- Wunderbar.fatal 'Happy'
60
- assert @logger.messages[:fatal].include? 'Happy'
61
- end
62
-
63
- def test_loglevel
64
- assert Wunderbar.logger.level == Logger::WARN
65
- Wunderbar.log_level = 'debug'
66
- assert Wunderbar.logger.level == Logger::DEBUG
67
- Wunderbar.log_level = 'info'
68
- assert Wunderbar.logger.level == Logger::INFO
69
- Wunderbar.log_level = 'warn'
70
- assert Wunderbar.logger.level == Logger::WARN
71
- Wunderbar.log_level = 'error'
72
- assert Wunderbar.logger.level == Logger::ERROR
73
- Wunderbar.log_level = 'fatal'
74
- assert Wunderbar.logger.level == Logger::FATAL
75
- end
76
- end