html_mockup 0.3.2

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/README.rdoc ADDED
@@ -0,0 +1,81 @@
1
+ == HtmlMockup
2
+
3
+ HTML Mockup is a set of tools to create self-containing HTML mockups. HtmlMockup gives you the flexibility
4
+ of a templatinglanguage but at the same time keeps all HTML files viewable. HTML comments are
5
+ used to determine what partial (sub-template) to render.
6
+
7
+ HtmlMockup also provides tools for HTML validation.
8
+
9
+ === Requirements
10
+ HtmlMockup requires the following dependencies
11
+
12
+ * Ruby 1.8.x (not tested in 1.9.x)
13
+ * Rubygems
14
+ * Thor (to use mockup binary)
15
+ * Rack > 0.3 (to use mockup serve)
16
+
17
+ === Usage
18
+
19
+ Just write regular HTML files and include comment's like this:
20
+
21
+ <!-- [START:partial_name] -->Text<!-- [STOP:partial_name] -->
22
+
23
+ The data between the tags will be replaced by the partial contents. Partials are searched in
24
+ "../partials" relative to the directory the script you run resides in. This can be overridden with
25
+ commandline parameters. Partials always must have a .part.r?html ending and are evaluated as ERB during
26
+ insertion.
27
+
28
+ === Syntax for HTML files
29
+
30
+ ==== Standard partials
31
+
32
+ <!-- [START:partial_name] -->Text<!-- [STOP:partial_name] -->
33
+
34
+ ==== Pass parameters to partials
35
+
36
+ You can pass in parameters to partials in the format of key=value&key2=value2 (it's just a regular CGI
37
+ query string and is parsed by CGI#parse). The partials wich are evaluated as ERB can access the variables
38
+ through standard instance methods. The example below would create the instance variable @key.
39
+
40
+ <!-- [START:partial_name?key=value] -->Text<!-- [STOP:partial_name] -->
41
+
42
+
43
+ === Mockup commandline
44
+
45
+ ==== mockup convert [directory/file]
46
+
47
+ Convert can be called with a single html file or a directory. If a directory is specified all .html files
48
+ will be converted.
49
+
50
+ *Warning:* Convert will overwrite the file itself!
51
+
52
+ Options:
53
+ --partial_path:: the path where the partial files can be found (*.part.html), defaults to director/../partials
54
+ --filter:: The filter to use when finding templates within directory, defaults to *.html
55
+
56
+ ==== mockup serve [directory/file]
57
+
58
+ Serve can be used during development as a simple webserver (Webrick/Mongrel). It also supports
59
+ on-the-fly HTML validation.
60
+
61
+ You can also call ./script/server just above the HTML directory.
62
+
63
+ Options:
64
+ --port:: The port the server should listen on. Defaults to 9000
65
+ --partial_path:: the path where the partial files can be found (*.part.html), defaults to director/../partials
66
+ --validate:: Flag to set wether or not we should validate all html files (defaults to false)
67
+
68
+ ==== mockup generate [directory]
69
+
70
+ Generate creates a directory structure in directory for use with new HTML mockups.
71
+
72
+ ==== mockup validate [directory/file]
73
+
74
+ Validates all files within directory or just file with the W3C validator webservice.
75
+
76
+ Options:
77
+ --show_valid:: Flag to print a line for each valid file too (defaults to false)
78
+ --filter:: What files should be validated, defaults to [^_]*.html
79
+
80
+ === Copyright & license
81
+ Copyright (c) 2009 Flurin Egger, DigitPaint, MIT Style License. (see MIT-LICENSE)
data/bin/mockup ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.dirname(__FILE__) + "/../lib/html_mockup/cli"
4
+
5
+ HtmlMockup::Cli.start
@@ -0,0 +1,16 @@
1
+ require 'pathname'
2
+
3
+ begin
4
+ require File.dirname(__FILE__) + "/../vendor/html_mockup/lib/html_mockup/server"
5
+ rescue LoadError => e
6
+ require 'rubygems'
7
+ require 'html_mockup/server'
8
+ end
9
+
10
+ root_path = Pathname.new(File.dirname(__FILE__)) + "html"
11
+ partial_path = (root_path + "../partials/").realpath
12
+
13
+ mockup = HtmlMockup::Server.new(root_path,partial_path)
14
+
15
+ run mockup.application
16
+
Binary file
@@ -0,0 +1,18 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
2
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3
+
4
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
5
+ <head>
6
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
7
+
8
+ <title>untitled</title>
9
+
10
+ </head>
11
+
12
+ <body>
13
+ <!-- [START:test?id=bla] -->
14
+ <!-- [STOP:test] -->
15
+
16
+ <img src="green.gif" alt="Green" />
17
+ </body>
18
+ </html>
@@ -0,0 +1,3 @@
1
+ <div id="<%= @id || "fault" %>">
2
+ Think?
3
+ </div>
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'pathname'
4
+
5
+ begin
6
+ require File.dirname(__FILE__) + "/../vendor/html_mockup/lib/html_mockup/server"
7
+ rescue LoadError => e
8
+ require 'rubygems'
9
+ require 'html_mockup/server'
10
+ end
11
+
12
+ root_path = Pathname.new(File.dirname(__FILE__)) + "../html"
13
+ partial_path = (root_path + "../partials/").realpath
14
+
15
+ mockup = HtmlMockup::Server.new(root_path,partial_path)
16
+
17
+ # Add some of your own middleware here.
18
+ # mockup.use Rack::CommonLogger
19
+
20
+ mockup.run
@@ -0,0 +1,178 @@
1
+ require 'rubygems'
2
+ require 'thor'
3
+
4
+ require 'pathname'
5
+ require 'fileutils'
6
+ include FileUtils
7
+
8
+ require File.dirname(__FILE__) + "/template"
9
+ require File.dirname(__FILE__) + "/w3c_validator"
10
+
11
+ module HtmlMockup
12
+ class Cli < Thor
13
+ desc "serve [directory]","Serve directory as HTML, defaults to current directory"
14
+ method_options :port => :string, # Defaults to 9000
15
+ :partial_path => :string, # Defaults to [directory]/../partials
16
+ :validate => :boolean, # Automatically validate all HTML responses @ the w3c
17
+ :handler => :string # The handler to use (defaults to mongrel)
18
+ def serve(path=".")
19
+ require File.dirname(__FILE__) + '/server'
20
+
21
+ @path,@partial_path = template_paths(path,options["partial_path"])
22
+
23
+ server_options = {}
24
+ server_options[:Port] = options["port"] || "9000"
25
+
26
+ server = Server.new(@path,@partial_path,options,server_options)
27
+
28
+ puts "Running HtmlMockup with #{server.handler.inspect} on port #{server_options[:Port]}"
29
+ puts " Taking partials from #{@partial_path} (#{HtmlMockup::Template.partial_files(@partial_path).size} found)"
30
+
31
+ server.run
32
+ end
33
+
34
+ desc "validate [directory/file]", "Validates the file or all HTML in directory"
35
+ method_options :show_valid => :boolean, # Also print a line for each valid file
36
+ :filter => :string # What files should be found, defaults to [^_]*.html
37
+ def validate(path=".")
38
+ filter = options["filter"] || "[^_]*.html"
39
+
40
+ puts "Filtering on #{options["filter"]}" if options["filter"]
41
+
42
+ if File.directory?(path)
43
+ any_invalid = false
44
+
45
+ if (files = Dir.glob("#{path}/**/#{filter}")).any?
46
+ files.each do |file|
47
+ if !self.w3cvalidate(file)
48
+ any_invalid = true
49
+ end
50
+ end
51
+ if !any_invalid
52
+ puts "All files were considered valid"
53
+ end
54
+ else
55
+ puts "No files matched \"#{filter}\""
56
+ end
57
+ elsif File.readable?(path)
58
+ self.w3cvalidate(path)
59
+ else
60
+ puts "No such file/directory #{path}"
61
+ end
62
+ end
63
+
64
+ desc "generate [directory]","Create a new HTML mockup directory tree in directory"
65
+ def generate(path)
66
+ path = Pathname.new(path)
67
+ if path.directory?
68
+ puts "Directory #{path} already exists, please only use this to create new mockups"
69
+ else
70
+ example_path = Pathname.new(File.dirname(__FILE__) + "/../../examples")
71
+ path.mkpath
72
+ html_path = path + "html"
73
+ mkdir(html_path)
74
+ mkdir(html_path + "stylesheets")
75
+ mkdir(html_path + "images")
76
+ mkdir(html_path + "javascripts")
77
+
78
+ mkdir(path + "partials")
79
+
80
+ mkdir(path + "script")
81
+ cp(example_path + "script/server",path + "script/server")
82
+ cp(example_path + "config.ru",path + "config.ru")
83
+ (path + "script/server").chmod(0755)
84
+ end
85
+ end
86
+
87
+ desc "convert [directory]","Inject all partials, into all HTML files within directory"
88
+ method_options :partial_path => :string, # Defaults to [directory]/../partials
89
+ :filter => :string # What files should be converted defaults to **/*.html
90
+ def convert(path=".")
91
+ path,partial_path = template_paths(path,options["partial_path"])
92
+ filter = options["filter"] || "**/*.html"
93
+ puts "Converting #{filter} in #{path}"
94
+ puts " Taking partials from #{partial_path} (#{HtmlMockup::Template.partial_files(partial_path).size} found)"
95
+
96
+ if path.directory?
97
+ Dir.glob("#{path}/#{filter}").each do |file|
98
+ puts " Converting file: " + file
99
+ HtmlMockup::Template.open(file, :partial_path => partial_path).save
100
+ end
101
+ else
102
+ HtmlMockup::Template.open(path, :partial_path => partial_path).save
103
+ end
104
+
105
+ end
106
+
107
+ desc "extract [source_path] [target_path]", "Extract a fully relative html mockup into target_path. It will expand all absolute href's, src's and action's into relative links if they are absolute"
108
+ method_options :partial_path => :string, # Defaults to [directory]/../partials
109
+ :filter => :string # What files should be converted defaults to **/*.html
110
+ def extract(source_path=".",target_path="../out")
111
+ require 'hpricot'
112
+ source_path,target_path = Pathname.new(source_path),Pathname.new(target_path)
113
+ source_path,partial_path = template_paths(source_path,options["partial_path"])
114
+ filter = options["filter"] || "**/*.html"
115
+ raise "Target #{target_path} already exists, please choose a new directory to extract into" if target_path.exist?
116
+
117
+ mkdir_p(target_path)
118
+ target_path = target_path.realpath
119
+
120
+ # Copy source to target first, we'll overwrite the templates later on.
121
+ cp_r(source_path.children,target_path)
122
+
123
+ Dir.chdir(source_path) do
124
+ Dir.glob(filter).each do |file_name|
125
+ source = HtmlMockup::Template.open(file_name, :partial_path => partial_path).render
126
+ cur_dir = Pathname.new(file_name).dirname
127
+ up_to_root = File.join([".."] * (file_name.split("/").size - 1))
128
+ doc = Hpricot(source)
129
+ %w{src href action}.each do |attribute|
130
+ (doc/"*[@#{attribute}]").each do |tag|
131
+ next unless tag[attribute] =~ /\A\//
132
+ if true_file = resolve_path(cur_dir + up_to_root + tag[attribute].sub(/\A\//,""))
133
+ tag[attribute] = true_file.relative_path_from(cur_dir)
134
+ else
135
+ puts "Could not resolve link #{tag[attribute]} in #{file_name}"
136
+ end
137
+ end
138
+ end
139
+
140
+ File.open(target_path + file_name,"w"){|f| f.write(doc.to_original_html) }
141
+ end
142
+ end
143
+ end
144
+
145
+ protected
146
+
147
+ def template_paths(path,partial_path=nil)
148
+ path = Pathname.new(path)
149
+ partial_path = partial_path && Pathname.new(partial_path) || (path + "../partials/").realpath
150
+ [path,partial_path]
151
+ end
152
+
153
+ def w3cvalidate(file)
154
+ validator = W3CValidator.new(File.read(file))
155
+ validator.validate!
156
+ if !options["show_valid"] && !validator.valid || options["show_valid"]
157
+ print "- #{file} "
158
+ print "(errors: #{validator.errors}, warnings: #{validator.warnings})\n"
159
+ end
160
+ validator.valid
161
+ end
162
+
163
+ def resolve_path(path)
164
+ path = Pathname.new(path) unless path.kind_of?(Pathname)
165
+ # Append index.html/index.htm/index.rhtml if it's a diretory
166
+ if path.directory?
167
+ search_files = %w{.html .htm}.map!{|p| path + "index#{p}" }
168
+ # If it ends with a slash or does not contain a . and it's not a directory
169
+ # try to add .html/.htm/.rhtml to see if that exists.
170
+ elsif (path =~ /\/$/) || (path =~ /^[^.]+$/)
171
+ search_files = [path.to_s + ".html", path.to_s + ".htm"].map!{|p| Pathname.new(p) }
172
+ else
173
+ search_files = [path]
174
+ end
175
+ search_files.find{|p| p.exist? }
176
+ end
177
+ end
178
+ end
@@ -0,0 +1,56 @@
1
+ require 'rack/request'
2
+ require 'rack/response'
3
+ require 'rack/file'
4
+
5
+ module HtmlMockup
6
+ module Rack
7
+ class HtmlMockup
8
+ def initialize(root,partial_path)
9
+ @docroot = root
10
+ @partial_path = partial_path
11
+ @file_server = ::Rack::File.new(@docroot)
12
+ end
13
+
14
+ def call(env)
15
+ path = env["PATH_INFO"]
16
+
17
+ # Append index.html/index.htm/index.rhtml if it's a diretory
18
+ if File.directory?(File.join(@docroot,path))
19
+ search_files = %w{.html .htm .rhtml}.map!{|p| File.join(@docroot,path,"index#{p}")}
20
+ # If it's already a .html/.htm/.rhtml file, render that file
21
+ elsif (path =~ /\.r?html?$/)
22
+ search_files = [File.join(@docroot,path)]
23
+ # If it ends with a slash or does not contain a . and it's not a directory
24
+ # try to add .html/.htm/.rhtml to see if that exists.
25
+ elsif (path =~ /\/$/) || (path =~ /^[^.]+$/)
26
+ search_files = [path + ".html", path + ".htm", path + ".rhtml"].map!{|p| File.join(@docroot,p) }
27
+ # Otherwise don't render anything at all.
28
+ else
29
+ search_files = []
30
+ end
31
+
32
+ if template_path = search_files.find{|p| File.exist?(p)}
33
+ env["rack.errors"].puts "Rendering template #{template_path.inspect} (#{path.inspect})"
34
+ begin
35
+ templ = ::HtmlMockup::Template.open(template_path, :partial_path => @partial_path)
36
+ resp = ::Rack::Response.new do |res|
37
+ res.status = 200
38
+ res.write templ.render
39
+ end
40
+ resp.finish
41
+ rescue StandardError => e
42
+ env["rack.errors"].puts " #{e.message}"
43
+ resp = ::Rack::Response.new do |res|
44
+ res.status = 500
45
+ res.write "An error occurred"
46
+ end
47
+ resp.finish
48
+ end
49
+ else
50
+ env["rack.errors"].puts "Invoking file handler for #{path.inspect}"
51
+ @file_server.call(env)
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,26 @@
1
+ require 'rack/request'
2
+ require 'rack/response'
3
+
4
+ module HtmlMockup
5
+ module Rack
6
+ class HtmlValidator
7
+ def initialize(app)
8
+ @app = app
9
+ end
10
+
11
+ def call(env)
12
+ resp = @app.call(env)
13
+ if resp[1]["Content-Type"].to_s.include?("html")
14
+ str = ""
15
+ resp[2].each{|c| str << c}
16
+ validator = W3CValidator.new(str)
17
+ validator.validate!
18
+ if !validator.valid
19
+ env["rack.errors"].puts "Validation failed on #{env["PATH_INFO"]}: (errors: #{validator.errors}, warnings: #{validator.warnings})"
20
+ end
21
+ end
22
+ resp
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,80 @@
1
+ require 'rack'
2
+ require File.dirname(__FILE__) + "/template"
3
+ require File.dirname(__FILE__) + "/w3c_validator"
4
+ require File.dirname(__FILE__) + "/rack/html_mockup"
5
+ require File.dirname(__FILE__) + "/rack/html_validator"
6
+
7
+ module HtmlMockup
8
+ class Server
9
+ attr_accessor :options,:server_options, :root, :partial_path
10
+
11
+ def initialize(root,partial_path,options={},server_options={})
12
+ @stack = ::Rack::Builder.new
13
+
14
+ @middleware = []
15
+ @root = root
16
+ @partial_path = partial_path
17
+ @options,@server_options = options,server_options
18
+ end
19
+
20
+ # Use the specified Rack middleware
21
+ def use(middleware, *args, &block)
22
+ @middleware << [middleware, args, block]
23
+ end
24
+
25
+ def handler
26
+ if self.options[:handler]
27
+ begin
28
+ @handler = ::Rack::Handler.get(self.options[:handler])
29
+ rescue LoadError
30
+ rescue NameError
31
+ end
32
+ if @handler.nil?
33
+ puts "Handler '#{self.options[:handler]}' not found, using fallback."
34
+ end
35
+ end
36
+ @handler ||= detect_rack_handler
37
+ end
38
+
39
+ def run
40
+ self.handler.run self.application, @server_options do |server|
41
+ trap(:INT) do
42
+ ## Use thins' hard #stop! if available, otherwise just #stop
43
+ server.respond_to?(:stop!) ? server.stop! : server.stop
44
+ puts "Bby HtmlMockup"
45
+ end
46
+ end
47
+ end
48
+
49
+ def application
50
+ return @app if @app
51
+ @stack.use ::Rack::ShowExceptions
52
+ @stack.use ::Rack::Lint
53
+ @stack.use ::Rack::ConditionalGet
54
+
55
+ @middleware.each { |c,a,b| @stack.use(c, *a, &b) }
56
+
57
+ @stack.use Rack::HtmlValidator if self.options["validate"]
58
+ @stack.run Rack::HtmlMockup.new(self.root, self.partial_path)
59
+
60
+ @app = @stack.to_app
61
+ end
62
+
63
+
64
+ protected
65
+
66
+ # Sinatra's detect_rack_handler
67
+ def detect_rack_handler
68
+ servers = %w[mongrel thin webrick]
69
+ servers.each do |server_name|
70
+ begin
71
+ return ::Rack::Handler.get(server_name)
72
+ rescue LoadError
73
+ rescue NameError
74
+ end
75
+ end
76
+ raise "Server handler (#{servers.join(',')}) not found."
77
+ end
78
+
79
+ end
80
+ end
@@ -0,0 +1,129 @@
1
+ require 'pathname'
2
+ require 'strscan'
3
+ require 'erb'
4
+ require 'cgi'
5
+
6
+ module HtmlMockup
7
+
8
+ class MissingPartial < StandardError; end
9
+
10
+ class Template
11
+
12
+ class << self
13
+ def open(filename,options={})
14
+ raise "Unknown file #{filename}" unless File.exist?(filename)
15
+ self.new(File.read(filename),options.update(:target_file => filename))
16
+ end
17
+
18
+ # Returns all available partials in path
19
+ def partials(path)
20
+ available_partials = {}
21
+ path = Pathname.new(path)
22
+ self.partial_files(path).inject({}) do |mem,f|
23
+ name = f.to_s.split(".",2)[0]
24
+ mem[name] = (path + f).read
25
+ mem
26
+ end
27
+ end
28
+
29
+ def partial_files(path)
30
+ filter = "*.part.{?h,h}tml"
31
+ files = []
32
+ Dir.chdir(Pathname.new(path)) do
33
+ files = Dir.glob(filter)
34
+ end
35
+ files
36
+ end
37
+
38
+ end
39
+
40
+ # Create a new HtmlMockupTemplate
41
+ #
42
+ # ==== Parameters
43
+ # template<String>:: The template to parse
44
+ # options<Hash>:: See options
45
+ #
46
+ # ==== Options (optional)
47
+ # partial_path<String>:: Path where the partials reside (default: $0/../../partials)
48
+ #--
49
+ def initialize(template, options={})
50
+ defaults = {:partial_path => File.dirname(__FILE__) + "/../../partials/"}
51
+ @template = template
52
+ @options = defaults.update(options)
53
+ @scanner = StringScanner.new(@template)
54
+ raise "Partial path '#{self.options[:partial_path]}' not found" unless File.exist?(self.options[:partial_path])
55
+ end
56
+
57
+ attr_reader :template, :options, :scanner
58
+
59
+ # Renders the template and returns it as a string
60
+ #
61
+ # ==== Returns
62
+ # String:: The rendered template
63
+ #--
64
+ def render
65
+ out = ""
66
+ while (partial = self.parse_partial_tag!) do
67
+ tag,params,scanned = partial
68
+ # add new skipped content to output file
69
+ out << scanned
70
+
71
+ # scan until end of tag
72
+ current_content = self.scanner.scan_until(/<!-- \[STOP:#{tag}\] -->/)
73
+ out << (render_partial(tag,params) || current_content)
74
+ end
75
+ out << scanner.rest
76
+ end
77
+
78
+ def save(filename=self.options[:target_file])
79
+ File.open(filename,"w"){|f| f.write render}
80
+ end
81
+
82
+ protected
83
+
84
+ def available_partials(force=false)
85
+ return @_available_partials if @_available_partials && !force
86
+ @_available_partials = self.class.partials(self.options[:partial_path])
87
+ end
88
+
89
+ def parse_partial_tag!
90
+ params = {}
91
+ scanned = ""
92
+ begin_of_tag = self.scanner.scan_until(/<!-- \[START:/)
93
+ return nil unless begin_of_tag
94
+ scanned << begin_of_tag
95
+ scanned << tag = self.scanner.scan(/[a-z0-9_]+/)
96
+ if scanned_questionmark = self.scanner.scan(/\?/)
97
+ scanned << scanned_questionmark
98
+ scanned << raw_params = self.scanner.scan_until(/\] -->/)
99
+ raw_params.gsub!(/\] -->$/,"")
100
+
101
+ params = CGI.parse(raw_params)
102
+ params.keys.each{|k| params[k] = params[k].first }
103
+ else
104
+ scanned << self.scanner.scan_until(/\] -->/)
105
+ end
106
+
107
+ [tag,params,scanned]
108
+ end
109
+
110
+ def render_partial(tag,params)
111
+ unless self.available_partials[tag]
112
+ raise MissingPartial.new("Could not find partial '#{tag}' in partial path '#{@options[:partial_path]}'")
113
+ end
114
+ template = ERB.new(self.available_partials[tag])
115
+ context = TemplateContext.new(params)
116
+ "\n" + template.result(context.get_binding).rstrip + "\n<!-- [STOP:#{tag}] -->"
117
+ end
118
+
119
+ class TemplateContext
120
+ def initialize(params)
121
+ params.each do |k,v|
122
+ self.instance_variable_set("@#{k}",v)
123
+ end
124
+ end
125
+ def get_binding; binding(); end
126
+ end
127
+
128
+ end
129
+ end
@@ -0,0 +1,120 @@
1
+ require 'cgi'
2
+ require 'net/http'
3
+ require 'uri'
4
+ require 'yaml'
5
+
6
+ module HtmlMockup
7
+ class W3CValidator
8
+
9
+ ValidationUri = "http://validator.w3.org/check"
10
+
11
+ attr_reader :valid,:response,:errors,:warnings,:status
12
+
13
+ class << self
14
+ def validation_uri
15
+ @uri ||= URI.parse(ValidationUri)
16
+ end
17
+ end
18
+
19
+ def initialize(html)
20
+ @html = html
21
+ end
22
+
23
+ def validate!
24
+ @status = @warnings = @errors = @response = @valid = nil
25
+ options = {"output" => "json"}
26
+ query,headers = build_post_query(options)
27
+ response = self.request(:post,self.class.validation_uri.path,query,headers)
28
+ @status,@warnings,@errors = response["x-w3c-validator-status"],response["x-w3c-validator-warnings"].to_i,response["x-w3c-validator-errors"].to_i
29
+
30
+ if @status == "Valid" && @warnings == 0 && @errors == 0
31
+ return @valid = true
32
+ else
33
+ begin
34
+ @response = YAML.load(response.body)
35
+ rescue
36
+ end
37
+ return (@valid = (@errros == 0))
38
+ end
39
+
40
+ end
41
+
42
+ protected
43
+
44
+ def build_post_query(options)
45
+ boundary = "validate-this-content-please"
46
+ headers = {"Content-type" => "multipart/form-data, boundary=" + boundary + " "}
47
+
48
+ parts = []
49
+ options.each do |k,v|
50
+ parts << post_param(k,v)
51
+ end
52
+ parts << file_param("uploaded_file","index.html",@html,"text/html")
53
+
54
+ q = parts.map{|p| "--#{boundary}\r\n#{p}"}.join("") + "--#{boundary}--"
55
+ [q,headers]
56
+ end
57
+
58
+ def post_param(k,v)
59
+ "Content-Disposition: form-data; name=\"#{CGI::escape(k)}\"\r\n\r\n#{v}\r\n"
60
+ end
61
+
62
+ def file_param(k,filename,content,mime_type)
63
+ out = []
64
+ out << "Content-Disposition: form-data; name=\"#{CGI::escape(k)}\"; filename=\"#{filename}\""
65
+ out << "Content-Transfer-Encoding: binary"
66
+ out << "Content-Type: #{mime_type}"
67
+ out.join("\r\n") + "\r\n\r\n" + content + "\r\n"
68
+ end
69
+
70
+
71
+
72
+
73
+ # Makes request to remote service.
74
+ def request(method, path, *arguments)
75
+ result = nil
76
+ result = http.send(method, path, *arguments)
77
+ handle_response(result)
78
+ rescue Timeout::Error => e
79
+ raise
80
+ end
81
+
82
+ # Handles response and error codes from remote service.
83
+ def handle_response(response)
84
+ case response.code.to_i
85
+ when 301,302
86
+ raise "Redirect"
87
+ when 200...400
88
+ response
89
+ when 400
90
+ raise "Bad Request"
91
+ when 401
92
+ raise "Unauthorized Access"
93
+ when 403
94
+ raise "Forbidden Access"
95
+ when 404
96
+ raise "Rescoure not found"
97
+ when 405
98
+ raise "Method not allowed"
99
+ when 409
100
+ raise "Rescource conflict"
101
+ when 422
102
+ raise "Resource invalid"
103
+ when 401...500
104
+ raise "Client error"
105
+ when 500...600
106
+ raise "Server error"
107
+ else
108
+ raise "Unknown response: #{response.code.to_i}"
109
+ end
110
+ end
111
+
112
+ def http
113
+ site = self.class.validation_uri
114
+ http = Net::HTTP.new(site.host, site.port)
115
+ # http.use_ssl = site.is_a?(URI::HTTPS)
116
+ # http.verify_mode = OpenSSL::SSL::VERIFY_NONE if http.use_ssl
117
+ http
118
+ end
119
+ end
120
+ end
metadata ADDED
@@ -0,0 +1,86 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: html_mockup
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.2
5
+ platform: ruby
6
+ authors:
7
+ - Flurin Egger
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-11-18 00:00:00 +01:00
13
+ default_executable: mockup
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: thor
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ~>
22
+ - !ruby/object:Gem::Version
23
+ version: 0.12.0
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: rack
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 1.0.0
34
+ version:
35
+ description:
36
+ email: flurin@digitpaint.nl
37
+ executables:
38
+ - mockup
39
+ extensions: []
40
+
41
+ extra_rdoc_files:
42
+ - README.rdoc
43
+ files:
44
+ - bin/mockup
45
+ - examples/config.ru
46
+ - examples/html/green.gif
47
+ - examples/html/index.html
48
+ - examples/partials/test.part.rhtml
49
+ - examples/script/server
50
+ - lib/html_mockup/cli.rb
51
+ - lib/html_mockup/rack/html_mockup.rb
52
+ - lib/html_mockup/rack/html_validator.rb
53
+ - lib/html_mockup/server.rb
54
+ - lib/html_mockup/template.rb
55
+ - lib/html_mockup/w3c_validator.rb
56
+ - README.rdoc
57
+ has_rdoc: true
58
+ homepage: http://github.com/flurin/html_mockup
59
+ licenses: []
60
+
61
+ post_install_message:
62
+ rdoc_options:
63
+ - --charset=UTF-8
64
+ require_paths:
65
+ - lib
66
+ required_ruby_version: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: "0"
71
+ version:
72
+ required_rubygems_version: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: "0"
77
+ version:
78
+ requirements: []
79
+
80
+ rubyforge_project:
81
+ rubygems_version: 1.3.5
82
+ signing_key:
83
+ specification_version: 3
84
+ summary: HTML Mockup is a set of tools to create self-containing HTML mockups.
85
+ test_files: []
86
+