cgi-spa 0.2.1 → 0.3.0
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.
- 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: []
|