wunderbar 0.8.10 → 0.8.11
Sign up to get free protection for your applications and to get access to all the features.
- data/Manifest +1 -0
- data/README.md +21 -1
- data/demo/wiki.rb +9 -9
- data/lib/wunderbar/builder.rb +19 -7
- data/lib/wunderbar/cgi-methods.rb +1 -1
- data/lib/wunderbar/html-methods.rb +9 -4
- data/lib/wunderbar/version.rb +1 -1
- data/lib/wunderbar.rb +1 -0
- data/test/test_html_markup.rb +30 -0
- data/tools/web2script.rb +14 -10
- data/wunderbar.gemspec +2 -2
- metadata +39 -61
data/Manifest
CHANGED
data/README.md
CHANGED
@@ -9,7 +9,10 @@ the emerging results from the [XML Error Recovery Community
|
|
9
9
|
Group](http://www.w3.org/community/xml-er/wiki/Main_Page).
|
10
10
|
|
11
11
|
Wunderbar is both inspired by, and builds upon Jim Weirich's
|
12
|
-
[Builder](https://github.com/jimweirich/builder#readme)
|
12
|
+
[Builder](https://github.com/jimweirich/builder#readme), and provides
|
13
|
+
the element id and class id syntax and based on the implementation from
|
14
|
+
[Markaby](http://markaby.rubyforge.org/).
|
15
|
+
.
|
13
16
|
|
14
17
|
Quick Start
|
15
18
|
---
|
@@ -36,6 +39,14 @@ Element with both text and attributes:
|
|
36
39
|
|
37
40
|
_a 'search', href: 'http://google.com'
|
38
41
|
|
42
|
+
Element with boolean attributes:
|
43
|
+
|
44
|
+
_input 'Cheese', type: 'checkbox', name: 'cheese', checked: true
|
45
|
+
|
46
|
+
Element with optional (omitted) attributes:
|
47
|
+
|
48
|
+
_tr class: nil
|
49
|
+
|
39
50
|
Text:
|
40
51
|
|
41
52
|
_ "hello"
|
@@ -76,6 +87,15 @@ Capture exceptions:
|
|
76
87
|
raise NotImplementedError.new('page')
|
77
88
|
end
|
78
89
|
|
90
|
+
Class attribute shortcut (equivalent to class="front"):
|
91
|
+
|
92
|
+
div.front do
|
93
|
+
end
|
94
|
+
|
95
|
+
Id attributes shortcut (equivalent to id="search"):
|
96
|
+
|
97
|
+
div.search! do
|
98
|
+
end
|
79
99
|
|
80
100
|
Basic interface
|
81
101
|
---
|
data/demo/wiki.rb
CHANGED
@@ -21,7 +21,7 @@ W_.html do
|
|
21
21
|
.input {float: left; left: 1.5%}
|
22
22
|
.output {float: right; right: 1.5%; background-color: #6C6666; color: #FFF}
|
23
23
|
.buttons {clear: both; text-align: center; padding-top: 0.5em}
|
24
|
-
|
24
|
+
#message {position: fixed; left: 2%; color: #9400d3}
|
25
25
|
h1 {text-align: center; margin: 0}
|
26
26
|
form {clear: both}
|
27
27
|
.buttons form {display: inline}
|
@@ -38,7 +38,7 @@ W_.html do
|
|
38
38
|
|
39
39
|
# determine markup
|
40
40
|
if _.post? and @markup
|
41
|
-
_header
|
41
|
+
_header.status do
|
42
42
|
_h1 'Status'
|
43
43
|
if File.exist?(file) and Digest::MD5.hexdigest(File.read(file)) != @hash
|
44
44
|
_p 'Write conflict'
|
@@ -96,15 +96,15 @@ W_.html do
|
|
96
96
|
end
|
97
97
|
|
98
98
|
_form_ action: file, method: 'post' do
|
99
|
-
_textarea @markup, name: 'markup'
|
99
|
+
_textarea.input @markup, name: 'markup'
|
100
100
|
_input type: 'hidden', name: 'hash',
|
101
101
|
value: Digest::MD5.hexdigest(@markup)
|
102
|
-
_div
|
102
|
+
_div.output do
|
103
103
|
_ << RDiscount.new(@markup).to_html
|
104
104
|
end
|
105
105
|
|
106
|
-
_div
|
107
|
-
_span
|
106
|
+
_div.buttons do
|
107
|
+
_span.message!
|
108
108
|
_input name: 'comment', placeholder: 'commit message'
|
109
109
|
_input type: 'submit', value: 'save'
|
110
110
|
end
|
@@ -125,7 +125,7 @@ W_.html do
|
|
125
125
|
|
126
126
|
#display
|
127
127
|
_ << RDiscount.new(@markup).to_html
|
128
|
-
_div_
|
128
|
+
_div_.buttons do
|
129
129
|
if !rev or rev.empty?
|
130
130
|
_form action: "#{file}?", method: 'post' do
|
131
131
|
_input type: 'submit', value: 'edit'
|
@@ -153,10 +153,10 @@ W_.html do
|
|
153
153
|
$('input[name=hash]').val(_.hash);
|
154
154
|
if (_.time) {
|
155
155
|
var time = new Date(_.time).toLocaleTimeString();
|
156
|
-
$('
|
156
|
+
$('#message').text("Autosaved at " + time).show().fadeOut(5000);
|
157
157
|
} else {
|
158
158
|
$('.input').val(_.markup).attr('readonly', 'readonly');
|
159
|
-
$('
|
159
|
+
$('#message').css({'font-weight': 'bold'}).text(_.error).show();
|
160
160
|
}
|
161
161
|
});
|
162
162
|
}, 10000);
|
data/lib/wunderbar/builder.rb
CHANGED
@@ -34,13 +34,21 @@ module Wunderbar
|
|
34
34
|
end
|
35
35
|
|
36
36
|
def disable_indendation!(&block)
|
37
|
-
indent, level =
|
38
|
-
|
37
|
+
indent, level, pending_newline, pending_margin =
|
38
|
+
indentation_state! [0, 0, @pending_newline, @pending_margin]
|
39
39
|
text! " "*indent*level
|
40
40
|
block.call
|
41
41
|
ensure
|
42
|
-
|
43
|
-
|
42
|
+
indentation_state! [indent, level, pending_newline, pending_margin]
|
43
|
+
end
|
44
|
+
|
45
|
+
def indentation_state! new_state=nil
|
46
|
+
result = [@indent, @level, @pending_newline, @pending_margin]
|
47
|
+
if new_state
|
48
|
+
text! "\n" if @indent == 0 and new_state.first > 0
|
49
|
+
@indent, @level, @pending_newline, @pending_margin = new_state
|
50
|
+
end
|
51
|
+
result
|
44
52
|
end
|
45
53
|
|
46
54
|
def margin!
|
@@ -58,7 +66,7 @@ module Wunderbar
|
|
58
66
|
@pending_newline = pending_newline
|
59
67
|
end
|
60
68
|
|
61
|
-
def tag!(*args)
|
69
|
+
def tag!(sym, *args, &block)
|
62
70
|
_newline if @pending_newline
|
63
71
|
@pending_newline = @pending_margin
|
64
72
|
@first_tag = @pending_margin = false
|
@@ -85,8 +93,12 @@ module Wunderbar
|
|
85
93
|
end
|
86
94
|
|
87
95
|
# avoid method_missing overhead for the most common case
|
88
|
-
def tag!(*args, &block)
|
89
|
-
|
96
|
+
def tag!(sym, *args, &block)
|
97
|
+
if !block and (args.empty? or args == [''])
|
98
|
+
CssProxy.new(@x, @x.target!, sym, args)
|
99
|
+
else
|
100
|
+
@x.tag! sym, *args, &block
|
101
|
+
end
|
90
102
|
end
|
91
103
|
|
92
104
|
# execute a system command, echoing stdin, stdout, and stderr
|
@@ -6,7 +6,7 @@ class HtmlMarkup
|
|
6
6
|
)
|
7
7
|
|
8
8
|
def initialize(*args, &block)
|
9
|
-
@x = Wunderbar::XmlMarkup.new :indent => 2
|
9
|
+
@x = Wunderbar::XmlMarkup.new :indent => 2, :target => []
|
10
10
|
end
|
11
11
|
|
12
12
|
def html(*args, &block)
|
@@ -54,8 +54,13 @@ class HtmlMarkup
|
|
54
54
|
args.unshift '' if not VOID.include?(name) and not block
|
55
55
|
end
|
56
56
|
|
57
|
-
|
58
|
-
|
57
|
+
if Hash === args.last
|
58
|
+
# remove attributes with nil, false values
|
59
|
+
args.last.delete_if {|key, value| !value}
|
60
|
+
|
61
|
+
# replace boolean 'true' attributes with the name of the attribute
|
62
|
+
args.last.each {|key, value| args.last[key]=key if value == true}
|
63
|
+
end
|
59
64
|
end
|
60
65
|
|
61
66
|
if flag == '!'
|
@@ -133,6 +138,6 @@ class HtmlMarkup
|
|
133
138
|
end
|
134
139
|
|
135
140
|
def target!
|
136
|
-
@x.target
|
141
|
+
@x.target!.join
|
137
142
|
end
|
138
143
|
end
|
data/lib/wunderbar/version.rb
CHANGED
data/lib/wunderbar.rb
CHANGED
data/test/test_html_markup.rb
CHANGED
@@ -119,6 +119,36 @@ class HtmlMarkupTest < Test::Unit::TestCase
|
|
119
119
|
assert_match %r[<head>\s*<meta charset="utf-8"/>\s*</head>], x.target!
|
120
120
|
end
|
121
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
|
+
|
122
152
|
def test_indented_text
|
123
153
|
x = HtmlMarkup.new
|
124
154
|
x.html {_div {_ 'text'}}
|
data/tools/web2script.rb
CHANGED
@@ -64,6 +64,13 @@ def flow_attrs(line, attributes, indent)
|
|
64
64
|
end
|
65
65
|
|
66
66
|
def code(element, indent='')
|
67
|
+
# restore namespaces that Nokogiri::HTML dropped
|
68
|
+
element_name = element.name
|
69
|
+
if $namespaced[element.name]
|
70
|
+
element_name = $namespaced[element.name]
|
71
|
+
element_name += ',' unless element.attributes.empty?
|
72
|
+
end
|
73
|
+
|
67
74
|
attributes = []
|
68
75
|
element.attributes.keys.each do |key|
|
69
76
|
value = element[key]
|
@@ -74,7 +81,11 @@ def code(element, indent='')
|
|
74
81
|
end
|
75
82
|
|
76
83
|
if key =~ /^\w+$/
|
77
|
-
if key == '
|
84
|
+
if key == 'id' and value =~ /^\w+$/
|
85
|
+
element_name += ".#{value}!"
|
86
|
+
elsif key == 'class' and value =~ /^\w+$/
|
87
|
+
element_name += ".#{value}"
|
88
|
+
elsif key == 'xmlns' and %w(html svg mathml).include? element.name
|
78
89
|
# drop xmlns attributes from these elements
|
79
90
|
elsif key == 'type' and element.name == 'style' and value == 'text/css'
|
80
91
|
# drop type attributes from script elements
|
@@ -90,13 +101,6 @@ def code(element, indent='')
|
|
90
101
|
end
|
91
102
|
end
|
92
103
|
|
93
|
-
# restore namespaces that Nokogiri::HTML dropped
|
94
|
-
element_name = element.name
|
95
|
-
if $namespaced[element.name]
|
96
|
-
element_name = $namespaced[element.name]
|
97
|
-
element_name += ',' unless attributes.empty?
|
98
|
-
end
|
99
|
-
|
100
104
|
line = "#{indent}_#{element_name}#{attributes.join(',')}"
|
101
105
|
line.sub! /^_/, 'W_.' if element_name == 'html' and indent.empty?
|
102
106
|
|
@@ -117,7 +121,7 @@ def code(element, indent='')
|
|
117
121
|
end
|
118
122
|
end
|
119
123
|
end
|
120
|
-
line.sub!(/(\w)(
|
124
|
+
line.sub!(/(\w)( |\.|$)/, '\1!\2') if flatten
|
121
125
|
|
122
126
|
q "#{line} do"
|
123
127
|
|
@@ -141,7 +145,7 @@ def code(element, indent='')
|
|
141
145
|
|
142
146
|
# insert a blank line if either this or the previous block was large
|
143
147
|
if $group and start + $group < $q.length
|
144
|
-
$q[start].sub! /^(\s+_\w+) /, '\1_
|
148
|
+
$q[start].sub! /^(\s+_\w+)([ .])/, '\1_\2'
|
145
149
|
$q.insert(start,'') if not first
|
146
150
|
blank = true
|
147
151
|
else
|
data/wunderbar.gemspec
CHANGED
@@ -2,11 +2,11 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = "wunderbar"
|
5
|
-
s.version = "0.8.
|
5
|
+
s.version = "0.8.11"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Sam Ruby"]
|
9
|
-
s.date = "2012-03-
|
9
|
+
s.date = "2012-03-23"
|
10
10
|
s.description = " Provides a number of globals, helper methods, and monkey patches which\n simplify the generation of HTML and the development of CGI scripts.\n"
|
11
11
|
s.email = "rubys@intertwingly.net"
|
12
12
|
s.extra_rdoc_files = ["COPYING", "README.md", "lib/wunderbar.rb", "lib/wunderbar/builder.rb", "lib/wunderbar/cgi-methods.rb", "lib/wunderbar/environment.rb", "lib/wunderbar/html-methods.rb", "lib/wunderbar/installation.rb", "lib/wunderbar/job-control.rb", "lib/wunderbar/logger.rb", "lib/wunderbar/version.rb"]
|
metadata
CHANGED
@@ -1,57 +1,44 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: wunderbar
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.8.11
|
5
5
|
prerelease:
|
6
|
-
segments:
|
7
|
-
- 0
|
8
|
-
- 8
|
9
|
-
- 10
|
10
|
-
version: 0.8.10
|
11
6
|
platform: ruby
|
12
|
-
authors:
|
7
|
+
authors:
|
13
8
|
- Sam Ruby
|
14
9
|
autorequire:
|
15
10
|
bindir: bin
|
16
11
|
cert_chain: []
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
- !ruby/object:Gem::Dependency
|
12
|
+
date: 2012-03-23 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
21
15
|
name: builder
|
22
|
-
|
23
|
-
requirement: &id001 !ruby/object:Gem::Requirement
|
16
|
+
requirement: &10419980 !ruby/object:Gem::Requirement
|
24
17
|
none: false
|
25
|
-
requirements:
|
26
|
-
- -
|
27
|
-
- !ruby/object:Gem::Version
|
28
|
-
|
29
|
-
segments:
|
30
|
-
- 0
|
31
|
-
version: "0"
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
32
22
|
type: :runtime
|
33
|
-
version_requirements: *id001
|
34
|
-
- !ruby/object:Gem::Dependency
|
35
|
-
name: json
|
36
23
|
prerelease: false
|
37
|
-
|
24
|
+
version_requirements: *10419980
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: json
|
27
|
+
requirement: &10418220 !ruby/object:Gem::Requirement
|
38
28
|
none: false
|
39
|
-
requirements:
|
40
|
-
- -
|
41
|
-
- !ruby/object:Gem::Version
|
42
|
-
|
43
|
-
segments:
|
44
|
-
- 0
|
45
|
-
version: "0"
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
46
33
|
type: :runtime
|
47
|
-
|
48
|
-
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *10418220
|
36
|
+
description: ! " Provides a number of globals, helper methods, and monkey patches
|
37
|
+
which\n simplify the generation of HTML and the development of CGI scripts.\n"
|
49
38
|
email: rubys@intertwingly.net
|
50
39
|
executables: []
|
51
|
-
|
52
40
|
extensions: []
|
53
|
-
|
54
|
-
extra_rdoc_files:
|
41
|
+
extra_rdoc_files:
|
55
42
|
- COPYING
|
56
43
|
- README.md
|
57
44
|
- lib/wunderbar.rb
|
@@ -63,7 +50,7 @@ extra_rdoc_files:
|
|
63
50
|
- lib/wunderbar/job-control.rb
|
64
51
|
- lib/wunderbar/logger.rb
|
65
52
|
- lib/wunderbar/version.rb
|
66
|
-
files:
|
53
|
+
files:
|
67
54
|
- COPYING
|
68
55
|
- README.md
|
69
56
|
- Rakefile
|
@@ -88,44 +75,35 @@ files:
|
|
88
75
|
- Manifest
|
89
76
|
homepage: http://github.com/rubys/wunderbar
|
90
77
|
licenses: []
|
91
|
-
|
92
78
|
post_install_message:
|
93
|
-
rdoc_options:
|
79
|
+
rdoc_options:
|
94
80
|
- --line-numbers
|
95
81
|
- --inline-source
|
96
82
|
- --title
|
97
83
|
- Wunderbar
|
98
84
|
- --main
|
99
85
|
- README.md
|
100
|
-
require_paths:
|
86
|
+
require_paths:
|
101
87
|
- lib
|
102
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
88
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
103
89
|
none: false
|
104
|
-
requirements:
|
105
|
-
- -
|
106
|
-
- !ruby/object:Gem::Version
|
107
|
-
|
108
|
-
|
109
|
-
- 0
|
110
|
-
version: "0"
|
111
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
112
95
|
none: false
|
113
|
-
requirements:
|
114
|
-
- -
|
115
|
-
- !ruby/object:Gem::Version
|
116
|
-
|
117
|
-
segments:
|
118
|
-
- 1
|
119
|
-
- 2
|
120
|
-
version: "1.2"
|
96
|
+
requirements:
|
97
|
+
- - ! '>='
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: '1.2'
|
121
100
|
requirements: []
|
122
|
-
|
123
101
|
rubyforge_project: wunderbar
|
124
102
|
rubygems_version: 1.8.15
|
125
103
|
signing_key:
|
126
104
|
specification_version: 3
|
127
105
|
summary: HTML Generator and CGI application support
|
128
|
-
test_files:
|
106
|
+
test_files:
|
129
107
|
- test/test_logger.rb
|
130
108
|
- test/test_html_markup.rb
|
131
109
|
- test/test_builder.rb
|