cgi-spa 0.2.1 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/COPYING +18 -0
- data/README +49 -17
- data/Rakefile +1 -1
- data/cgi-spa.gemspec +4 -4
- data/lib/cgi-spa/builder.rb +102 -0
- data/lib/cgi-spa/cgi-methods.rb +51 -0
- data/lib/cgi-spa/environment.rb +45 -0
- data/lib/cgi-spa/html-methods.rb +25 -0
- data/lib/cgi-spa/installation.rb +54 -0
- data/lib/cgi-spa/job-control.rb +25 -0
- data/lib/{version.rb → cgi-spa/version.rb} +2 -2
- data/lib/cgi-spa.rb +6 -164
- metadata +18 -4
data/COPYING
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
Copyright (c) 2009 Sam Ruby <rubys@intertwingly.net>
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to
|
5
|
+
deal in the Software without restriction, including without limitation the
|
6
|
+
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
7
|
+
sell copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
16
|
+
THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
17
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
18
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README
CHANGED
@@ -1,23 +1,55 @@
|
|
1
|
-
|
2
|
-
$cgi - Common Gateway Interface
|
3
|
-
$params - Access to parameters
|
4
|
-
$x - XmlBuilder instance
|
1
|
+
= cgi-spa: Common Gateway Interface for Single Page Applications
|
5
2
|
|
6
|
-
|
7
|
-
|
8
|
-
|
3
|
+
CGI-SPA provides a number of globals, helper methods, and monkey patches which
|
4
|
+
simplify the development of single page applications in the form of CGI
|
5
|
+
scripts.
|
9
6
|
|
10
|
-
|
11
|
-
|
12
|
-
|
7
|
+
== Globals provided
|
8
|
+
* $cgi - Common Gateway Interface
|
9
|
+
* $param - Access to parameters (read-only OpenStruct like interface)
|
10
|
+
* $x - XmlBuilder instance
|
11
|
+
* $USER - Host user id
|
12
|
+
* $HOME - Home directory
|
13
|
+
* $SERVER- Server name
|
14
|
+
* SELF - Request URI
|
15
|
+
* SELF? - Request URI with '?' appended (avoids spoiling the cache)
|
13
16
|
|
14
|
-
|
15
|
-
|
17
|
+
* $USER - user
|
18
|
+
* $HOME - user's home directory
|
19
|
+
* $HOST - server host
|
16
20
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
+
* $HTTP_GET - request is an HTTP GET
|
22
|
+
* $HTTP_POST - request is an HTTP POST
|
23
|
+
* $XHR_JSON - request is XmlHttpRequest for JSON
|
24
|
+
* $XHTML - user agent accepts XHTML responses
|
21
25
|
|
22
|
-
|
26
|
+
== HTML methods
|
27
|
+
* style! - argument is indented text/data
|
28
|
+
* script! - argument is indented text/data
|
23
29
|
|
30
|
+
== CGI methods
|
31
|
+
* json - produce JSON output using the block specified
|
32
|
+
* json! - produce JSON output using the block specified and exit
|
33
|
+
* html - produce HTML output using the block specified
|
34
|
+
* html! - produce HTML output using the block specified and exit
|
35
|
+
* post - execute block only if method is POST
|
36
|
+
* post! - if POST, produce HTML output using the block specified and exit
|
37
|
+
|
38
|
+
== Helper methods
|
39
|
+
* submit: runs command (or block) as a deamon process
|
40
|
+
|
41
|
+
== Builder extensions
|
42
|
+
* indented_text: matches text indentation to markup
|
43
|
+
* indented_data: useful for script and styles in HTML syntax
|
44
|
+
* traceback!: formats an exception traceback
|
45
|
+
* method_missing: patched to ensure open tags are closed
|
46
|
+
|
47
|
+
== Command line options
|
48
|
+
When run from the command line, CGI name=value pairs can be specified.
|
49
|
+
Additionally, the following options are supported:
|
50
|
+
* --html: HTML (HTTP GET) output is expected
|
51
|
+
* --post: HTML (HTTP POST) output is expected
|
52
|
+
* --json: JSON (XML HTTP Request) output is expected
|
53
|
+
* --xhtml: XHTML output is expected
|
54
|
+
* --prompt: prompt for key/value pairs using stdin
|
55
|
+
* --install=path: produce an suexec-callable wrapper script
|
data/Rakefile
CHANGED
@@ -2,7 +2,7 @@ require 'rubygems'
|
|
2
2
|
require 'rake'
|
3
3
|
require 'echoe'
|
4
4
|
|
5
|
-
require File.expand_path(File.dirname(__FILE__) + "/lib/version")
|
5
|
+
require File.expand_path(File.dirname(__FILE__) + "/lib/cgi-spa/version")
|
6
6
|
|
7
7
|
Echoe.new('cgi-spa', CgiSpa::VERSION::STRING) do |p|
|
8
8
|
p.summary = "CGI Single Page Applications"
|
data/cgi-spa.gemspec
CHANGED
@@ -2,18 +2,18 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{cgi-spa}
|
5
|
-
s.version = "0.
|
5
|
+
s.version = "0.3.0"
|
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 = %q{2009-12-
|
9
|
+
s.date = %q{2009-12-19}
|
10
10
|
s.description = %q{ Provides a number of globals, helper methods, and monkey patches which
|
11
11
|
simplify the development of single page applications in the form of
|
12
12
|
CGI scripts.
|
13
13
|
}
|
14
14
|
s.email = %q{rubys@intertwingly.net}
|
15
|
-
s.extra_rdoc_files = ["README", "lib/cgi-spa.rb", "lib/version.rb"]
|
16
|
-
s.files = ["Manifest", "README", "Rakefile", "cgi-spa.gemspec", "lib/cgi-spa.rb", "lib/version.rb"]
|
15
|
+
s.extra_rdoc_files = ["COPYING", "README", "lib/cgi-spa.rb", "lib/cgi-spa/builder.rb", "lib/cgi-spa/cgi-methods.rb", "lib/cgi-spa/environment.rb", "lib/cgi-spa/html-methods.rb", "lib/cgi-spa/installation.rb", "lib/cgi-spa/job-control.rb", "lib/cgi-spa/version.rb"]
|
16
|
+
s.files = ["COPYING", "Manifest", "README", "Rakefile", "cgi-spa.gemspec", "lib/cgi-spa.rb", "lib/cgi-spa/builder.rb", "lib/cgi-spa/cgi-methods.rb", "lib/cgi-spa/environment.rb", "lib/cgi-spa/html-methods.rb", "lib/cgi-spa/installation.rb", "lib/cgi-spa/job-control.rb", "lib/cgi-spa/version.rb"]
|
17
17
|
s.homepage = %q{http://github.com/rubys/cgi-spa}
|
18
18
|
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Cgi-spa", "--main", "README"]
|
19
19
|
s.require_paths = ["lib"]
|
@@ -0,0 +1,102 @@
|
|
1
|
+
# add indented_text!, indented_data! and traceback! methods to builder
|
2
|
+
module Builder
|
3
|
+
class XmlMarkup
|
4
|
+
unless method_defined? :indented_text!
|
5
|
+
def indented_text!(text)
|
6
|
+
indented_data!(text) {|data| text! data}
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
unless method_defined? :indented_data!
|
11
|
+
def indented_data!(data)
|
12
|
+
return if data.strip.length == 0
|
13
|
+
lines = data.gsub(/\n\s*\n/,"\n")
|
14
|
+
unindent = lines.scan(/^ */).map {|str| str.length}.min
|
15
|
+
|
16
|
+
before = Regexp.new('^'.ljust(unindent+1))
|
17
|
+
after = " " * (@level * @indent)
|
18
|
+
data = data.gsub(before, after)
|
19
|
+
|
20
|
+
if block_given?
|
21
|
+
yield data
|
22
|
+
else
|
23
|
+
self << data
|
24
|
+
end
|
25
|
+
|
26
|
+
_newline unless data =~ /\s$/
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
unless method_defined? :traceback!
|
31
|
+
def traceback!(exception=$!, klass='traceback')
|
32
|
+
pre :class=>klass do
|
33
|
+
text! exception.inspect
|
34
|
+
_newline
|
35
|
+
exception.backtrace.each {|frame| text!((' '*@indent)+frame + "\n")}
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# monkey patch to ensure that tags are closed
|
43
|
+
test =
|
44
|
+
Builder::XmlMarkup.new.html do |x|
|
45
|
+
x.body do
|
46
|
+
begin
|
47
|
+
x.p do
|
48
|
+
raise Exception.new('boom')
|
49
|
+
end
|
50
|
+
rescue Exception => e
|
51
|
+
x.pre e
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
if test.index('<p>') and !test.index('</p>')
|
57
|
+
module Builder
|
58
|
+
class XmlMarkup
|
59
|
+
def method_missing(sym, *args, &block)
|
60
|
+
text = nil
|
61
|
+
attrs = nil
|
62
|
+
sym = "#{sym}:#{args.shift}" if args.first.kind_of?(Symbol)
|
63
|
+
args.each do |arg|
|
64
|
+
case arg
|
65
|
+
when Hash
|
66
|
+
attrs ||= {}
|
67
|
+
attrs.merge!(arg)
|
68
|
+
else
|
69
|
+
text ||= ''
|
70
|
+
text << arg.to_s
|
71
|
+
end
|
72
|
+
end
|
73
|
+
if block
|
74
|
+
unless text.nil?
|
75
|
+
raise ArgumentError, "XmlMarkup cannot mix a text argument with a block"
|
76
|
+
end
|
77
|
+
_indent
|
78
|
+
_start_tag(sym, attrs)
|
79
|
+
_newline
|
80
|
+
begin ### Added
|
81
|
+
_nested_structures(block)
|
82
|
+
ensure ### Added
|
83
|
+
_indent
|
84
|
+
_end_tag(sym)
|
85
|
+
_newline
|
86
|
+
end ### Added
|
87
|
+
elsif text.nil?
|
88
|
+
_indent
|
89
|
+
_start_tag(sym, attrs, true)
|
90
|
+
_newline
|
91
|
+
else
|
92
|
+
_indent
|
93
|
+
_start_tag(sym, attrs)
|
94
|
+
text! text
|
95
|
+
_end_tag(sym)
|
96
|
+
_newline
|
97
|
+
end
|
98
|
+
@target
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# produce json
|
2
|
+
def $cgi.json
|
3
|
+
return unless $XHR_JSON
|
4
|
+
$cgi.out 'type' => 'application/json', 'Cache-Control' => 'no-cache' do
|
5
|
+
JSON.pretty_generate(yield)+ "\n"
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
# produce json and quit
|
10
|
+
def $cgi.json! &block
|
11
|
+
return unless $XHR_JSON
|
12
|
+
json(&block)
|
13
|
+
Process.exit
|
14
|
+
end
|
15
|
+
|
16
|
+
# produce html/xhtml
|
17
|
+
def $cgi.html
|
18
|
+
return if $XHR_JSON
|
19
|
+
if $XHTML
|
20
|
+
$cgi.out 'type' => 'application/xhtml+xml', 'charset' => 'UTF-8' do
|
21
|
+
$x.declare! :DOCTYPE, :html
|
22
|
+
$x.html :xmlns => 'http://www.w3.org/1999/xhtml' do
|
23
|
+
yield $x
|
24
|
+
end
|
25
|
+
end
|
26
|
+
else
|
27
|
+
$cgi.out 'type' => 'text/html', 'charset' => 'UTF-8' do
|
28
|
+
$x.declare! :DOCTYPE, :html
|
29
|
+
$x.html do
|
30
|
+
yield $x
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# produce html and quit
|
37
|
+
def $cgi.html! &block
|
38
|
+
return if $XHR_JSON
|
39
|
+
html(&block)
|
40
|
+
Process.exit
|
41
|
+
end
|
42
|
+
|
43
|
+
# post specific logic (doesn't produce output)
|
44
|
+
def $cgi.post
|
45
|
+
yield unless $HTML_POST
|
46
|
+
end
|
47
|
+
|
48
|
+
# post specific content (produces output)
|
49
|
+
def $cgi.post! &block
|
50
|
+
html!(&block) unless $HTML_POST
|
51
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# explicit request types
|
2
|
+
$HTTP_GET = ARGV.delete('--html')
|
3
|
+
$HTTP_POST = ARGV.delete('--post')
|
4
|
+
$XHR_JSON = ARGV.delete('--json')
|
5
|
+
$XHTML = ARGV.delete('--xhtml')
|
6
|
+
|
7
|
+
# Only prompt if explicitly asked for
|
8
|
+
ARGV.push '' if ARGV.empty?
|
9
|
+
ARGV.delete('--prompt') or ARGV.delete('--offline')
|
10
|
+
|
11
|
+
# standard objects
|
12
|
+
$cgi = CGI.new
|
13
|
+
$param = $cgi.params
|
14
|
+
$x = Builder::XmlMarkup.new :indent => 2
|
15
|
+
|
16
|
+
# implied request types
|
17
|
+
$HTTP_GET ||= ($cgi.request_method == 'GET')
|
18
|
+
$HTTP_POST ||= ($cgi.request_method == 'POST')
|
19
|
+
$XHR_JSON ||= ($cgi.accept.to_s =~ /json/)
|
20
|
+
$XHTML ||= ($cgi.accept.to_s =~ /xhtml/)
|
21
|
+
|
22
|
+
# get arguments if CGI couldn't find any...
|
23
|
+
$param.merge!(CGI.parse(ARGV.join('&'))) if $param.empty?
|
24
|
+
|
25
|
+
# fast path for accessing CGI parameters
|
26
|
+
def $param.method_missing(name)
|
27
|
+
self[name.to_s].join if has_key? name.to_s
|
28
|
+
end
|
29
|
+
|
30
|
+
# quick access to request_uri
|
31
|
+
SELF = ENV['REQUEST_URI'].to_s
|
32
|
+
def SELF?
|
33
|
+
SELF + "?" # avoids spoiling the cache
|
34
|
+
end
|
35
|
+
|
36
|
+
# environment objects
|
37
|
+
$USER = ENV['USER'] ||
|
38
|
+
if RUBY_PLATFORM =~ /darwin/
|
39
|
+
`dscl . -search /Users UniqueID #{Process.uid}`.split.first
|
40
|
+
else
|
41
|
+
`getent passwd #{Process.uid}`.split(':').first
|
42
|
+
end
|
43
|
+
|
44
|
+
$HOME = ENV['HOME'] || File.expand_path('~' + $USER)
|
45
|
+
$SERVER = ENV['HTTP_HOST'] || `hostname`.chomp
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# smart style, knows that the content is indented text/data
|
2
|
+
def $x.style!(text)
|
3
|
+
text.slice! /^\n/
|
4
|
+
text.slice! /[ ]+\z/
|
5
|
+
$x.style :type => "text/css" do
|
6
|
+
if $XHTML
|
7
|
+
indented_text! text
|
8
|
+
else
|
9
|
+
indented_data! text
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
# smart script, knows that the content is indented text/data
|
15
|
+
def $x.script!(text)
|
16
|
+
text.slice! /^\n/
|
17
|
+
text.slice! /[ ]+\z/
|
18
|
+
$x.script :lang => "text/javascript" do
|
19
|
+
if $XHTML
|
20
|
+
indented_text! text
|
21
|
+
else
|
22
|
+
indented_data! text
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# option to create an suexec callable wrapper
|
2
|
+
install = ARGV.find {|arg| arg =~ /--install=(.*)/}
|
3
|
+
if install and ARGV.delete(install)
|
4
|
+
|
5
|
+
# scope out the situation
|
6
|
+
dest = File.expand_path($1)
|
7
|
+
main = File.expand_path(caller.last[/^(.*):\d+(:|$)/,1])
|
8
|
+
|
9
|
+
# if destination is a directory, determine an appropriate file name
|
10
|
+
if File.directory?(dest)
|
11
|
+
if dest =~ /\/cgi-bin\/?$/
|
12
|
+
dest = File.join(dest, File.basename(main))
|
13
|
+
else
|
14
|
+
dest = File.join(dest, File.basename(main).sub(/\.rb$/,'.cgi'))
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# prevent accidental overwrite
|
19
|
+
if File.exist?(dest) and not ARGV.delete('-f')
|
20
|
+
STDERR.puts "File #{dest} already exists. (Specify -f to overwrite)"
|
21
|
+
Process.exit
|
22
|
+
end
|
23
|
+
|
24
|
+
# ensure destination directory exists
|
25
|
+
destdir = File.dirname(dest)
|
26
|
+
if not File.exist?(destdir) or not File.directory?(destdir)
|
27
|
+
STDERR.puts "Directory #{destdir} does not exist."
|
28
|
+
Process.exit
|
29
|
+
end
|
30
|
+
|
31
|
+
# output wrapper
|
32
|
+
open(dest,'w') do |file|
|
33
|
+
# she-bang
|
34
|
+
file.puts "#!" + File.join(
|
35
|
+
RbConfig::CONFIG["bindir"],
|
36
|
+
RbConfig::CONFIG["ruby_install_name"] + RbConfig::CONFIG["EXEEXT"]
|
37
|
+
)
|
38
|
+
|
39
|
+
# Change directory
|
40
|
+
file.puts "Dir.chdir #{File.dirname(main).inspect}"
|
41
|
+
|
42
|
+
# Optional data from the script (after __END__)
|
43
|
+
file.puts DATA.read if Object.const_defined? :DATA
|
44
|
+
|
45
|
+
# Load script
|
46
|
+
file.puts "require #{File.basename(main).sub(/\.rb$/,'').inspect}"
|
47
|
+
end
|
48
|
+
|
49
|
+
# Mark wrapper as executable
|
50
|
+
File.chmod(0755, dest)
|
51
|
+
|
52
|
+
# Don't execute the script itself at this time
|
53
|
+
Process.exit
|
54
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# run command/block as a background daemon
|
2
|
+
def submit(cmd=nil)
|
3
|
+
fork do
|
4
|
+
# detach from tty
|
5
|
+
Process.setsid
|
6
|
+
fork and exit
|
7
|
+
|
8
|
+
# clear working directory and mask
|
9
|
+
Dir.chdir '/'
|
10
|
+
File.umask 0000
|
11
|
+
|
12
|
+
# close open files
|
13
|
+
STDIN.reopen '/dev/null'
|
14
|
+
STDOUT.reopen '/dev/null', 'a'
|
15
|
+
STDERR.reopen STDOUT
|
16
|
+
|
17
|
+
# setup environment
|
18
|
+
ENV['USER'] ||= $USER
|
19
|
+
ENV['HOME'] ||= $HOME
|
20
|
+
|
21
|
+
# run cmd and/or block
|
22
|
+
system cmd if cmd
|
23
|
+
yield if block_given?
|
24
|
+
end
|
25
|
+
end
|
data/lib/cgi-spa.rb
CHANGED
@@ -1,169 +1,11 @@
|
|
1
|
-
#!/usr/bin/ruby
|
2
1
|
require 'cgi'
|
3
|
-
require 'rubygems'
|
4
2
|
require 'builder'
|
5
3
|
require 'json'
|
6
4
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
5
|
+
require 'cgi-spa/environment'
|
6
|
+
require 'cgi-spa/cgi-methods'
|
7
|
+
require 'cgi-spa/html-methods'
|
8
|
+
require 'cgi-spa/job-control'
|
9
|
+
require 'cgi-spa/installation'
|
10
|
+
require 'cgi-spa/builder'
|
11
11
|
|
12
|
-
# get arguments if CGI couldn't find any...
|
13
|
-
$param.merge!(CGI.parse(ARGV.join('&'))) if $param.empty?
|
14
|
-
|
15
|
-
# fast path for accessing CGI parameters
|
16
|
-
def $param.method_missing(name)
|
17
|
-
self[name.to_s].join if has_key? name.to_s
|
18
|
-
end
|
19
|
-
|
20
|
-
# quick access to request_uri
|
21
|
-
SELF = ENV['REQUEST_URI'].to_s
|
22
|
-
def SELF?
|
23
|
-
SELF + "?" # avoids spoiling the cache
|
24
|
-
end
|
25
|
-
|
26
|
-
# environment objects
|
27
|
-
$USER = ENV['USER'] ||
|
28
|
-
if RUBY_PLATFORM =~ /darwin/
|
29
|
-
`dscl . -search /Users UniqueID #{Process.uid}`.split.first
|
30
|
-
else
|
31
|
-
`getent passwd #{Process.uid}`.split(':').first
|
32
|
-
end
|
33
|
-
|
34
|
-
$HOME = ENV['HOME'] || File.expand_path('~' + $USER)
|
35
|
-
$SERVER = ENV['HTTP_HOST'] || `hostname`.chomp
|
36
|
-
|
37
|
-
# request types
|
38
|
-
$HTTP_GET = ($cgi.request_method == 'GET')
|
39
|
-
$HTTP_POST = ($cgi.request_method == 'POST')
|
40
|
-
$XHR_JSON = (ENV['HTTP_ACCEPT'] =~ /json/)
|
41
|
-
|
42
|
-
# run command/block as a background daemon
|
43
|
-
def submit(cmd=nil)
|
44
|
-
fork do
|
45
|
-
# detach from tty
|
46
|
-
Process.setsid
|
47
|
-
fork and exit
|
48
|
-
|
49
|
-
# clear working directory and mask
|
50
|
-
Dir.chdir '/'
|
51
|
-
File.umask 0000
|
52
|
-
|
53
|
-
# close open files
|
54
|
-
STDIN.reopen '/dev/null'
|
55
|
-
STDOUT.reopen '/dev/null', 'a'
|
56
|
-
STDERR.reopen STDOUT
|
57
|
-
|
58
|
-
# setup environment
|
59
|
-
ENV['USER'] ||= $USER
|
60
|
-
ENV['HOME'] ||= $HOME
|
61
|
-
|
62
|
-
# run cmd and/or block
|
63
|
-
system cmd if cmd
|
64
|
-
yield if block_given?
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
# add indented_text!, indented_data! and traceback! methods to builder
|
69
|
-
module Builder
|
70
|
-
class XmlMarkup
|
71
|
-
unless method_defined? :indented_text!
|
72
|
-
def indented_text!(text)
|
73
|
-
indented_data!(text) {|data| text! data}
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
unless method_defined? :indented_data!
|
78
|
-
def indented_data!(data)
|
79
|
-
return if data.strip.length == 0
|
80
|
-
lines = data.gsub(/\n\s*\n/,"\n")
|
81
|
-
unindent = lines.scan(/^ */).map {|str| str.length}.min
|
82
|
-
|
83
|
-
before = Regexp.new('^'.ljust(unindent+1))
|
84
|
-
after = " " * (@level * @indent)
|
85
|
-
data = data.gsub(before, after)
|
86
|
-
|
87
|
-
if block_given?
|
88
|
-
yield data
|
89
|
-
else
|
90
|
-
self << data
|
91
|
-
end
|
92
|
-
|
93
|
-
_newline unless data =~ /\s$/
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
unless method_defined? :traceback!
|
98
|
-
def traceback!(exception=$!, klass='traceback')
|
99
|
-
pre :class=>klass do
|
100
|
-
text! exception.inspect
|
101
|
-
_newline
|
102
|
-
exception.backtrace.each {|frame| text!((' '*@indent)+frame + "\n")}
|
103
|
-
end
|
104
|
-
end
|
105
|
-
end
|
106
|
-
end
|
107
|
-
end
|
108
|
-
|
109
|
-
# monkey patch to ensure that tags are closed
|
110
|
-
test =
|
111
|
-
Builder::XmlMarkup.new.html do |x|
|
112
|
-
x.body do
|
113
|
-
begin
|
114
|
-
x.p do
|
115
|
-
raise Exception.new('boom')
|
116
|
-
end
|
117
|
-
rescue Exception => e
|
118
|
-
x.pre e
|
119
|
-
end
|
120
|
-
end
|
121
|
-
end
|
122
|
-
|
123
|
-
if test.index('<p>') and !test.index('</p>')
|
124
|
-
module Builder
|
125
|
-
class XmlMarkup
|
126
|
-
def method_missing(sym, *args, &block)
|
127
|
-
text = nil
|
128
|
-
attrs = nil
|
129
|
-
sym = "#{sym}:#{args.shift}" if args.first.kind_of?(Symbol)
|
130
|
-
args.each do |arg|
|
131
|
-
case arg
|
132
|
-
when Hash
|
133
|
-
attrs ||= {}
|
134
|
-
attrs.merge!(arg)
|
135
|
-
else
|
136
|
-
text ||= ''
|
137
|
-
text << arg.to_s
|
138
|
-
end
|
139
|
-
end
|
140
|
-
if block
|
141
|
-
unless text.nil?
|
142
|
-
raise ArgumentError, "XmlMarkup cannot mix a text argument with a block"
|
143
|
-
end
|
144
|
-
_indent
|
145
|
-
_start_tag(sym, attrs)
|
146
|
-
_newline
|
147
|
-
begin ### Added
|
148
|
-
_nested_structures(block)
|
149
|
-
ensure ### Added
|
150
|
-
_indent
|
151
|
-
_end_tag(sym)
|
152
|
-
_newline
|
153
|
-
end ### Added
|
154
|
-
elsif text.nil?
|
155
|
-
_indent
|
156
|
-
_start_tag(sym, attrs, true)
|
157
|
-
_newline
|
158
|
-
else
|
159
|
-
_indent
|
160
|
-
_start_tag(sym, attrs)
|
161
|
-
text! text
|
162
|
-
_end_tag(sym)
|
163
|
-
_newline
|
164
|
-
end
|
165
|
-
@target
|
166
|
-
end
|
167
|
-
end
|
168
|
-
end
|
169
|
-
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cgi-spa
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sam Ruby
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-12-
|
12
|
+
date: 2009-12-19 00:00:00 -05:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -39,16 +39,30 @@ executables: []
|
|
39
39
|
extensions: []
|
40
40
|
|
41
41
|
extra_rdoc_files:
|
42
|
+
- COPYING
|
42
43
|
- README
|
43
44
|
- lib/cgi-spa.rb
|
44
|
-
- lib/
|
45
|
+
- lib/cgi-spa/builder.rb
|
46
|
+
- lib/cgi-spa/cgi-methods.rb
|
47
|
+
- lib/cgi-spa/environment.rb
|
48
|
+
- lib/cgi-spa/html-methods.rb
|
49
|
+
- lib/cgi-spa/installation.rb
|
50
|
+
- lib/cgi-spa/job-control.rb
|
51
|
+
- lib/cgi-spa/version.rb
|
45
52
|
files:
|
53
|
+
- COPYING
|
46
54
|
- Manifest
|
47
55
|
- README
|
48
56
|
- Rakefile
|
49
57
|
- cgi-spa.gemspec
|
50
58
|
- lib/cgi-spa.rb
|
51
|
-
- lib/
|
59
|
+
- lib/cgi-spa/builder.rb
|
60
|
+
- lib/cgi-spa/cgi-methods.rb
|
61
|
+
- lib/cgi-spa/environment.rb
|
62
|
+
- lib/cgi-spa/html-methods.rb
|
63
|
+
- lib/cgi-spa/installation.rb
|
64
|
+
- lib/cgi-spa/job-control.rb
|
65
|
+
- lib/cgi-spa/version.rb
|
52
66
|
has_rdoc: true
|
53
67
|
homepage: http://github.com/rubys/cgi-spa
|
54
68
|
licenses: []
|