wunderbar 0.15.0 → 0.16.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +11 -6
- data/lib/wunderbar/builder.rb +86 -0
- data/lib/wunderbar/html-methods.rb +21 -72
- data/lib/wunderbar/installation.rb +5 -1
- data/lib/wunderbar/server.rb +11 -0
- data/lib/wunderbar/sinatra.rb +1 -1
- data/lib/wunderbar/version.rb +1 -1
- data/wunderbar.gemspec +2 -2
- metadata +4 -4
data/README.md
CHANGED
@@ -80,13 +80,17 @@ Element with optional (omitted) attributes:
|
|
80
80
|
|
81
81
|
_tr class: nil
|
82
82
|
|
83
|
+
Text (markup characters are escaped):
|
84
|
+
|
85
|
+
_ "<3"
|
86
|
+
|
83
87
|
Text (may contain markup):
|
84
88
|
|
85
|
-
_
|
89
|
+
_{"<em>hello</em>!!!"}
|
86
90
|
|
87
|
-
|
91
|
+
Import of HTML/XML:
|
88
92
|
|
89
|
-
_
|
93
|
+
_[Nokogiri::XML "<em>hello</em>"]
|
90
94
|
|
91
95
|
Mixed content (autospaced):
|
92
96
|
|
@@ -192,7 +196,7 @@ argument inserts markup, respecting indendation. Inserting markup without
|
|
192
196
|
reguard to indendatation is done using "`_ << text`". A number of other
|
193
197
|
convenience methods are defined:
|
194
198
|
|
195
|
-
* `_
|
199
|
+
* `_`: insert text with indentation matching the current output
|
196
200
|
* `_!`: insert text without indenting
|
197
201
|
* `_.post?` -- was this invoked via HTTP POST?
|
198
202
|
* `_.system` -- invokes a shell command, captures stdin, stdout, and stderr
|
@@ -325,8 +329,9 @@ Secure by default
|
|
325
329
|
---
|
326
330
|
|
327
331
|
Wunderbar will properly escape all HTML and JSON output, eliminating problems
|
328
|
-
of HTML or JavaScript injection. This includes calls to `_` to insert
|
329
|
-
directly
|
332
|
+
of HTML or JavaScript injection. This includes calls to `_` to insert text
|
333
|
+
directly. Even calls to insert markup (`_{...}`) will escape the markup if
|
334
|
+
the input is `tainted` and not explicitly marked as `html-safe?`
|
330
335
|
(when using Rails).
|
331
336
|
|
332
337
|
For all environments other than Rails, unless you call `Wunderbar.unsafe!` at
|
data/lib/wunderbar/builder.rb
CHANGED
@@ -142,6 +142,26 @@ module Wunderbar
|
|
142
142
|
|
143
143
|
# avoid method_missing overhead for the most common case
|
144
144
|
def tag!(sym, *args, &block)
|
145
|
+
if sym.respond_to? :children
|
146
|
+
node = sym
|
147
|
+
attributes = node.attributes
|
148
|
+
if node.attribute_nodes.any?(&:namespace)
|
149
|
+
attributes = Hash[node.attribute_nodes.map { |attr|
|
150
|
+
name = attr.name
|
151
|
+
name = "#{attr.namespace.prefix}:#{name}" if attr.namespace
|
152
|
+
[name, attr.value]
|
153
|
+
}]
|
154
|
+
end
|
155
|
+
attributes.merge!(node.namespaces) if node.namespaces
|
156
|
+
args.push attributes
|
157
|
+
if node.namespace and node.namespace.prefix
|
158
|
+
args.unshift node.name.to_sym
|
159
|
+
sym = node.namespace.prefix
|
160
|
+
else
|
161
|
+
sym = node.name
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
145
165
|
if !block and (args.empty? or args == [''])
|
146
166
|
CssProxy.new(@_builder, @_builder.target!, sym, args)
|
147
167
|
else
|
@@ -254,6 +274,72 @@ module Wunderbar
|
|
254
274
|
rescue LoadError
|
255
275
|
@_builder << data
|
256
276
|
end
|
277
|
+
|
278
|
+
def [](*children)
|
279
|
+
if children.length == 1 and children.first.respond_to? :root
|
280
|
+
children = [children.first.root]
|
281
|
+
end
|
282
|
+
|
283
|
+
# remove leading and trailing space
|
284
|
+
if children.first.text? and children.first.text.strip.empty?
|
285
|
+
children.shift
|
286
|
+
end
|
287
|
+
|
288
|
+
if not children.empty?
|
289
|
+
children.pop if children.last.text? and children.last.text.strip.empty?
|
290
|
+
end
|
291
|
+
|
292
|
+
children.each do |child|
|
293
|
+
if child.text? or child.cdata?
|
294
|
+
text = child.text
|
295
|
+
if text.strip.empty?
|
296
|
+
text! "\n" if text.count("\n")>1
|
297
|
+
elsif indentation_state!.first == 0
|
298
|
+
indented_text! text.gsub(/\s+/, ' ')
|
299
|
+
else
|
300
|
+
indented_text! text.strip
|
301
|
+
end
|
302
|
+
elsif child.comment?
|
303
|
+
comment! child.text.sub(/\A /,'').sub(/ \Z/, '')
|
304
|
+
elsif HtmlMarkup.flatten? child.children
|
305
|
+
block_element = Proc.new do |node|
|
306
|
+
node.element? and HtmlMarkup::HTML5_BLOCK.include?(node.name)
|
307
|
+
end
|
308
|
+
|
309
|
+
if child.children.any?(&block_element)
|
310
|
+
# indent children, but disable indentation on consecutive
|
311
|
+
# sequences of non-block-elements. Put another way: break
|
312
|
+
# out block elements to a new line.
|
313
|
+
tag!(child) do
|
314
|
+
children = child.children.to_a
|
315
|
+
while not children.empty?
|
316
|
+
stop = children.index(&block_element)
|
317
|
+
if stop == 0
|
318
|
+
self[children.shift]
|
319
|
+
else
|
320
|
+
disable_indentation! do
|
321
|
+
self[*children.shift(stop || children.length)]
|
322
|
+
end
|
323
|
+
end
|
324
|
+
end
|
325
|
+
end
|
326
|
+
else
|
327
|
+
# disable indentation on the entire element
|
328
|
+
disable_indentation! do
|
329
|
+
tag!(child) {self[*child.children]}
|
330
|
+
end
|
331
|
+
end
|
332
|
+
elsif child.children.empty? and HtmlMarkup::VOID.include? child.name
|
333
|
+
tag!(child)
|
334
|
+
elsif child.children.all?(&:text?)
|
335
|
+
tag!(child, child.text.strip)
|
336
|
+
elsif child.children.any?(&:cdata?) and child.text =~ /[<&]/
|
337
|
+
self << child
|
338
|
+
else
|
339
|
+
tag!(child) {self[*child.children]}
|
340
|
+
end
|
341
|
+
end
|
342
|
+
end
|
257
343
|
end
|
258
344
|
|
259
345
|
require 'stringio'
|
@@ -96,11 +96,9 @@ module Wunderbar
|
|
96
96
|
end
|
97
97
|
|
98
98
|
if String === args.first and args.first.respond_to? :html_safe?
|
99
|
-
if args.first.html_safe? and not block
|
100
|
-
|
101
|
-
|
102
|
-
block = Proc.new {_ markup}
|
103
|
-
end
|
99
|
+
if args.first.html_safe? and not block and args.first =~ /[>&]/
|
100
|
+
markup = args.shift
|
101
|
+
block = Proc.new {_ {markup}}
|
104
102
|
end
|
105
103
|
end
|
106
104
|
|
@@ -187,21 +185,32 @@ module Wunderbar
|
|
187
185
|
end
|
188
186
|
@x.tag! :math, *args, &block
|
189
187
|
end
|
190
|
-
|
191
|
-
def
|
192
|
-
@x.
|
188
|
+
|
189
|
+
def _pre(*args, &block)
|
190
|
+
@x.disable_indentation! { @x.tag! :pre, *args, &block }
|
193
191
|
end
|
194
192
|
|
195
193
|
def _!(text)
|
196
194
|
@x.text! text.to_s
|
197
195
|
end
|
198
196
|
|
199
|
-
def _(
|
200
|
-
|
197
|
+
def _(text=nil, &block)
|
198
|
+
unless block
|
199
|
+
if text
|
200
|
+
if text.respond_to? :html_safe? and text.html_safe?
|
201
|
+
_ {text}
|
202
|
+
else
|
203
|
+
@x.indented_text! text.to_s
|
204
|
+
end
|
205
|
+
end
|
206
|
+
return @x
|
207
|
+
end
|
208
|
+
|
209
|
+
children = block.call
|
201
210
|
|
202
211
|
if String === children
|
203
212
|
safe = !children.tainted?
|
204
|
-
safe ||= children.html_safe?
|
213
|
+
safe ||= children.html_safe? if children.respond_to? :html_safe?
|
205
214
|
|
206
215
|
if safe and (children.include? '<' or children.include? '&')
|
207
216
|
require 'nokogiri'
|
@@ -210,67 +219,7 @@ module Wunderbar
|
|
210
219
|
return @x.indented_text! children
|
211
220
|
end
|
212
221
|
end
|
213
|
-
|
214
|
-
# remove leading and trailing space
|
215
|
-
if children.first.text? and children.first.text.strip.empty?
|
216
|
-
children.shift
|
217
|
-
end
|
218
|
-
|
219
|
-
if not children.empty?
|
220
|
-
children.pop if children.last.text? and children.last.text.strip.empty?
|
221
|
-
end
|
222
|
-
|
223
|
-
children.each do |child|
|
224
|
-
if child.text? or child.cdata?
|
225
|
-
text = child.text
|
226
|
-
if text.strip.empty?
|
227
|
-
@x.text! "\n" if text.count("\n")>1
|
228
|
-
elsif @x.indentation_state!.first == 0
|
229
|
-
@x.indented_text! text.gsub(/\s+/, ' ')
|
230
|
-
else
|
231
|
-
@x.indented_text! text.strip
|
232
|
-
end
|
233
|
-
elsif child.comment?
|
234
|
-
@x.comment! child.text.sub(/\A /,'').sub(/ \Z/, '')
|
235
|
-
elsif self.class.flatten? child.children
|
236
|
-
block_element = Proc.new do |node|
|
237
|
-
node.element? and HTML5_BLOCK.include?(node.name)
|
238
|
-
end
|
239
|
-
|
240
|
-
if child.children.any?(&block_element)
|
241
|
-
# indent children, but disable indentation on consecutive
|
242
|
-
# sequences of non-block-elements. Put another way: break
|
243
|
-
# out block elements to a new line.
|
244
|
-
@x.tag!(child.name, child.attributes) do
|
245
|
-
children = child.children.to_a
|
246
|
-
while not children.empty?
|
247
|
-
stop = children.index(&block_element)
|
248
|
-
if stop == 0
|
249
|
-
_ [children.shift]
|
250
|
-
else
|
251
|
-
@x.disable_indentation! do
|
252
|
-
_ children.shift(stop || children.length)
|
253
|
-
end
|
254
|
-
end
|
255
|
-
end
|
256
|
-
end
|
257
|
-
else
|
258
|
-
# disable indentation on the entire element
|
259
|
-
@x.disable_indentation! do
|
260
|
-
@x.tag!(child.name, child.attributes) {_ child.children}
|
261
|
-
end
|
262
|
-
end
|
263
|
-
elsif child.children.empty? and VOID.include? child.name
|
264
|
-
@x.tag!(child.name, child.attributes)
|
265
|
-
elsif child.children.all? {|gchild| gchild.text?}
|
266
|
-
@x.tag!(child.name, child.text.strip, child.attributes)
|
267
|
-
elsif child.children.any? {|gchild| gchild.cdata?} and
|
268
|
-
(child.text.include? '<' or child.text.include? '&')
|
269
|
-
@x << child
|
270
|
-
else
|
271
|
-
@x.tag!(child.name, child.attributes) {_ child.children}
|
272
|
-
end
|
273
|
-
end
|
222
|
+
@x[*children]
|
274
223
|
end
|
275
224
|
|
276
225
|
def _coffeescript(text)
|
@@ -58,7 +58,11 @@ if install and ARGV.delete(install)
|
|
58
58
|
file.puts "\n#{Wunderbar.data}\n" if Object.const_defined? :DATA
|
59
59
|
|
60
60
|
# Load script
|
61
|
-
|
61
|
+
if main.end_with? '.rb'
|
62
|
+
require = "require #{"./#{File.basename(main).chomp('.rb')}".inspect}"
|
63
|
+
else
|
64
|
+
require = "load #{"./#{File.basename(main)}".inspect}"
|
65
|
+
end
|
62
66
|
if ARGV.delete('--rescue') or ARGV.delete('--backtrace')
|
63
67
|
file.puts <<-EOF.gsub(/^ {8}/,'')
|
64
68
|
begin
|
data/lib/wunderbar/server.rb
CHANGED
@@ -54,6 +54,17 @@ else
|
|
54
54
|
ENV['USER'] ||= $USER
|
55
55
|
end
|
56
56
|
|
57
|
+
if ENV['HTTP_AUTH']
|
58
|
+
# RewriteEngine on
|
59
|
+
# RewriteRule ^.*$ - [E=HTTP_AUTH:%{HTTP:Authorization}]
|
60
|
+
begin
|
61
|
+
require 'base64'
|
62
|
+
$PASSWORD = Base64.decode64(ENV['HTTP_AUTH'] \
|
63
|
+
[/^Basic ([A-Za-z0-9+\/=]+)$/,1])[/^#{$USER}:(.*)/,1]
|
64
|
+
rescue
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
57
68
|
$HOME = ENV['HOME']
|
58
69
|
$HOME ||= Dir.home($USER) rescue nil
|
59
70
|
$HOME ||= File.expand_path("~#{$USER}") rescue nil
|
data/lib/wunderbar/sinatra.rb
CHANGED
data/lib/wunderbar/version.rb
CHANGED
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.
|
5
|
+
s.version = "0.16.0"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Sam Ruby"]
|
9
|
-
s.date = "2012-05-
|
9
|
+
s.date = "2012-05-17"
|
10
10
|
s.description = " Wunderbar makes it easy to produce valid HTML5, wellformed XHTML, Unicode\n (utf-8), consistently indented, readable applications. This includes\n output that conforms to the Polyglot specification and the emerging\n results from the XML Error Recovery Community Group.\n"
|
11
11
|
s.email = "rubys@intertwingly.net"
|
12
12
|
s.files = ["wunderbar.gemspec", "README.md", "COPYING", "lib/wunderbar.rb", "lib/wunderbar", "lib/wunderbar/installation.rb", "lib/wunderbar/html-methods.rb", "lib/wunderbar/job-control.rb", "lib/wunderbar/server.rb", "lib/wunderbar/logger.rb", "lib/wunderbar/rack.rb", "lib/wunderbar/builder.rb", "lib/wunderbar/websocket.rb", "lib/wunderbar/sinatra.rb", "lib/wunderbar/environment.rb", "lib/wunderbar/rails.rb", "lib/wunderbar/cgi-methods.rb", "lib/wunderbar/cssproxy.rb", "lib/wunderbar/version.rb"]
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: wunderbar
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 95
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
8
|
+
- 16
|
9
9
|
- 0
|
10
|
-
version: 0.
|
10
|
+
version: 0.16.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Sam Ruby
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2012-05-
|
18
|
+
date: 2012-05-17 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
name: builder
|