html_mockup 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/mockup +0 -0
- data/lib/html_mockup/cli.rb +38 -85
- data/lib/html_mockup/extractor.rb +100 -0
- data/lib/html_mockup/mockupfile.rb +63 -0
- data/lib/html_mockup/project.rb +54 -0
- data/lib/html_mockup/rack/html_mockup.rb +8 -6
- data/lib/html_mockup/rack/sleep.rb +21 -0
- data/lib/html_mockup/release/finalizers/dir.rb +24 -0
- data/lib/html_mockup/release/finalizers/zip.rb +4 -0
- data/lib/html_mockup/release/finalizers.rb +11 -0
- data/lib/html_mockup/release/injector.rb +98 -0
- data/lib/html_mockup/release/processors/requirejs.rb +54 -0
- data/lib/html_mockup/release/processors/sass.rb +38 -0
- data/lib/html_mockup/release/processors/yuicompressor.rb +53 -0
- data/lib/html_mockup/release/processors.rb +11 -0
- data/lib/html_mockup/release/scm/git.rb +101 -0
- data/lib/html_mockup/release/scm.rb +32 -0
- data/lib/html_mockup/release.rb +312 -0
- data/lib/html_mockup/server.rb +30 -10
- metadata +36 -8
@@ -0,0 +1,53 @@
|
|
1
|
+
# Use the ruby-yui-compressor gem.
|
2
|
+
require 'yui/compressor'
|
3
|
+
|
4
|
+
module HtmlMockup::Release::Processors
|
5
|
+
class Yuicompressor < Base
|
6
|
+
|
7
|
+
# Compresses all JS and CSS files, it will keep all lines before
|
8
|
+
#
|
9
|
+
# /* -------------------------------------------------------------------------------- */
|
10
|
+
#
|
11
|
+
# (80 dashes)
|
12
|
+
#
|
13
|
+
# @options options [Array] match Files to match, default to ["**/*.{css,js}"]
|
14
|
+
# @options options [Regexp] :delimiter An array of header delimiters. Defaults to the one above. The delimiter will be removed from the output.
|
15
|
+
# @options options [Array[Regexp]] :skip An array of file regular expressions to specifiy which files to skip. Defaults to [/javascripts\/vendor\/.\*.js\Z/, /_doc\/.*/]
|
16
|
+
def call(release, options={})
|
17
|
+
options = {
|
18
|
+
:match => ["**/*.{css,js}"],
|
19
|
+
:skip => [/javascripts\/vendor\/.*\.js\Z/, /_doc\/.*/],
|
20
|
+
:delimiter => Regexp.escape("/* -------------------------------------------------------------------------------- */")
|
21
|
+
}.update(options)
|
22
|
+
|
23
|
+
compressor_options = {:line_break => 80}
|
24
|
+
css_compressor = YUI::CssCompressor.new(compressor_options)
|
25
|
+
js_compressor = YUI::JavaScriptCompressor.new(compressor_options)
|
26
|
+
|
27
|
+
# Add version numbers and minify the files
|
28
|
+
release.get_files(options[:match], options[:skip]).each do |f|
|
29
|
+
type = f[/\.(.+)$/,1]
|
30
|
+
|
31
|
+
data = File.read(f);
|
32
|
+
File.open(f,"w") do |fh|
|
33
|
+
|
34
|
+
# Extract header and store for later use
|
35
|
+
header = data[/\A(.+?)\n#{options[:delimiter]}\s*\n/m,1]
|
36
|
+
minified = [header]
|
37
|
+
|
38
|
+
# Actual minification
|
39
|
+
release.log self, "Minifying #{f}"
|
40
|
+
case type
|
41
|
+
when "css"
|
42
|
+
minified << css_compressor.compress(data)
|
43
|
+
when "js"
|
44
|
+
minified << js_compressor.compress(data)
|
45
|
+
end
|
46
|
+
|
47
|
+
fh.write minified.join("\n")
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module HtmlMockup::Release::Processors
|
2
|
+
class Base
|
3
|
+
def call(release, options = {})
|
4
|
+
raise ArgumentError, "Implement in subclass"
|
5
|
+
end
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
require File.dirname(__FILE__) + "/finalizers/zip"
|
10
|
+
require File.dirname(__FILE__) + "/finalizers/dir"
|
11
|
+
|
@@ -0,0 +1,101 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
|
3
|
+
module HtmlMockup::Release::Scm
|
4
|
+
class Git < Base
|
5
|
+
|
6
|
+
# @option config [String] :ref Ref to use for current tag
|
7
|
+
# @option config [String, Pathname] :path Path to working dir
|
8
|
+
def initialize(config={})
|
9
|
+
super(config)
|
10
|
+
@config[:ref] ||= "HEAD"
|
11
|
+
end
|
12
|
+
|
13
|
+
# Version is either:
|
14
|
+
# - the tagged version number (first "v" will be stripped) or
|
15
|
+
# - the return value of "git describe --tags HEAD"
|
16
|
+
# - the short SHA1 if there hasn't been a previous tag
|
17
|
+
def version
|
18
|
+
get_scm_data if @_version.nil?
|
19
|
+
@_version
|
20
|
+
end
|
21
|
+
|
22
|
+
# Date will be Time.now if it can't be determined from GIT repository
|
23
|
+
def date
|
24
|
+
get_scm_data if @_date.nil?
|
25
|
+
@_date
|
26
|
+
end
|
27
|
+
|
28
|
+
def previous
|
29
|
+
self.class.new(@config.dup.update(:ref => get_previous_tag_name))
|
30
|
+
end
|
31
|
+
|
32
|
+
protected
|
33
|
+
|
34
|
+
def get_previous_tag_name
|
35
|
+
# Get list of SHA1 that have a ref
|
36
|
+
begin
|
37
|
+
sha1s = `git --git-dir=#{git_dir} log --pretty='%H' --simplify-by-decoration`.split("\n")
|
38
|
+
tags = []
|
39
|
+
while tags.size < 2 && sha1s.any?
|
40
|
+
sha1 = sha1s.shift
|
41
|
+
tag = `git --git-dir=#{git_dir} describe --tags --exact-match #{sha1} 2>/dev/null`.strip
|
42
|
+
tags << tag if !tag.empty?
|
43
|
+
end
|
44
|
+
tags.last
|
45
|
+
rescue
|
46
|
+
raise "Could not get previous tag"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def git_dir
|
51
|
+
@git_dir ||= find_git_dir(@config[:path])
|
52
|
+
end
|
53
|
+
|
54
|
+
# Some hackery to determine if we're on a tagged version or not
|
55
|
+
def get_scm_data(ref = @config[:ref])
|
56
|
+
@_version = ""
|
57
|
+
@_date = Time.now
|
58
|
+
begin
|
59
|
+
if File.exist?(git_dir)
|
60
|
+
@_version = `git --git-dir=#{git_dir} describe --tags #{ref} 2>&1`
|
61
|
+
|
62
|
+
if $?.to_i > 0
|
63
|
+
# HEAD is not a tagged verison, get the short SHA1 instead
|
64
|
+
@_version = `git --git-dir=#{git_dir} show #{ref} --format=format:"%h" --quiet 2>&1`
|
65
|
+
else
|
66
|
+
# HEAD is a tagged version, if version is prefixed with "v" it will be stripped off
|
67
|
+
@_version.gsub!(/^v/,"")
|
68
|
+
end
|
69
|
+
@_version.strip!
|
70
|
+
|
71
|
+
# Get the date in epoch time
|
72
|
+
date = `git --git-dir=#{git_dir} show #{ref} --format=format:"%ct" --quiet 2>&1`
|
73
|
+
if date =~ /\d+/
|
74
|
+
@_date = Time.at(date.to_i)
|
75
|
+
else
|
76
|
+
@_date = Time.now
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
rescue RuntimeError => e
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
# Find the git dir
|
86
|
+
def find_git_dir(path)
|
87
|
+
path = Pathname.new(path).realpath
|
88
|
+
while path.parent != path && !(path + ".git").directory?
|
89
|
+
path = path.parent
|
90
|
+
end
|
91
|
+
|
92
|
+
path = path + ".git"
|
93
|
+
|
94
|
+
raise "Could not find suitable .git dir in #{path}" if !path.directory?
|
95
|
+
|
96
|
+
path
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module HtmlMockup::Release::Scm
|
2
|
+
class Base
|
3
|
+
|
4
|
+
attr_reader :config
|
5
|
+
|
6
|
+
def initialize(config={})
|
7
|
+
@config = config
|
8
|
+
end
|
9
|
+
|
10
|
+
# Returns the release version string from the SCM
|
11
|
+
#
|
12
|
+
# @return String The current version string
|
13
|
+
def version
|
14
|
+
raise "Implement in subclass"
|
15
|
+
end
|
16
|
+
|
17
|
+
# Returns the release version date from the SCM
|
18
|
+
def date
|
19
|
+
raise "Implement in subclass"
|
20
|
+
end
|
21
|
+
|
22
|
+
# Returns a Release::Scm object with the previous version's data
|
23
|
+
#
|
24
|
+
# @return HtmlMockup::Release::Scm The previous version
|
25
|
+
def previous
|
26
|
+
raise "Implement in subclass"
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
require File.dirname(__FILE__) + "/scm/git"
|
@@ -0,0 +1,312 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/cli"
|
2
|
+
|
3
|
+
module HtmlMockup
|
4
|
+
class Release
|
5
|
+
|
6
|
+
attr_reader :config, :project
|
7
|
+
|
8
|
+
attr_reader :finalizers, :injections, :stack, :cleanups
|
9
|
+
|
10
|
+
def self.default_stack
|
11
|
+
[]
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.default_finalizers
|
15
|
+
[[:dir, {}]]
|
16
|
+
end
|
17
|
+
|
18
|
+
# @option config [Symbol] :scm The SCM to use (default = :git)
|
19
|
+
# @option config [String, Pathname] :target_path The path/directory to put the release into
|
20
|
+
# @option config [String, Pathname]:build_path Temporary path used to build the release
|
21
|
+
# @option config [Boolean] :cleanup_build Wether or not to remove the build_path after we're done (default = true)
|
22
|
+
def initialize(project, config = {})
|
23
|
+
defaults = {
|
24
|
+
:scm => :git,
|
25
|
+
:source_path => Pathname.new(Dir.pwd) + "html",
|
26
|
+
:target_path => Pathname.new(Dir.pwd) + "releases",
|
27
|
+
:build_path => Pathname.new(Dir.pwd) + "build",
|
28
|
+
:cleanup_build => true
|
29
|
+
}
|
30
|
+
|
31
|
+
@config = {}.update(defaults).update(config)
|
32
|
+
@project = project
|
33
|
+
@finalizers = []
|
34
|
+
@injections = []
|
35
|
+
@stack = []
|
36
|
+
@cleanups = []
|
37
|
+
end
|
38
|
+
|
39
|
+
# Accessor for target_path
|
40
|
+
# The target_path is the path where the finalizers will put the release
|
41
|
+
#
|
42
|
+
# @return Pathname the target_path
|
43
|
+
def target_path
|
44
|
+
Pathname.new(self.config[:target_path])
|
45
|
+
end
|
46
|
+
|
47
|
+
# Accessor for build_path
|
48
|
+
# The build_path is a temporary directory where the release will be built
|
49
|
+
#
|
50
|
+
# @return Pathname the build_path
|
51
|
+
def build_path
|
52
|
+
Pathname.new(self.config[:build_path])
|
53
|
+
end
|
54
|
+
|
55
|
+
# Accessor for source_path
|
56
|
+
# The source path is the root of the mockup
|
57
|
+
#
|
58
|
+
# @return Pathanem the source_path
|
59
|
+
def source_path
|
60
|
+
Pathname.new(self.config[:source_path])
|
61
|
+
end
|
62
|
+
|
63
|
+
# Get the current SCM object
|
64
|
+
def scm(force = false)
|
65
|
+
return @_scm if @_scm && !force
|
66
|
+
|
67
|
+
case self.config[:scm]
|
68
|
+
when :git
|
69
|
+
@_scm = Release::Scm::Git.new(:path => self.source_path)
|
70
|
+
else
|
71
|
+
raise "Unknown SCM #{options[:scm].inspect}"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# Inject variables into files with an optional filter
|
76
|
+
#
|
77
|
+
# @examples
|
78
|
+
# release.inject({"VERSION" => release.version, "DATE" => release.date}, :into => %w{_doc/toc.html})
|
79
|
+
# release.inject({"CHANGELOG" => {:file => "", :filter => BlueCloth}}, :into => %w{_doc/changelog.html})
|
80
|
+
def inject(variables, options)
|
81
|
+
@injections << [variables, options]
|
82
|
+
end
|
83
|
+
|
84
|
+
# Use a certain pre-processor
|
85
|
+
#
|
86
|
+
# @examples
|
87
|
+
# release.use :sprockets, sprockets_config
|
88
|
+
def use(processor, options = {})
|
89
|
+
@stack << [processor, options]
|
90
|
+
end
|
91
|
+
|
92
|
+
# Write out the whole release into a directory, zip file or anything you can imagine
|
93
|
+
# #finalize can be called multiple times, it just will run all of them.
|
94
|
+
#
|
95
|
+
# The default finalizer is :dir
|
96
|
+
#
|
97
|
+
# @param [Symbol, Proc] Finalizer to use
|
98
|
+
#
|
99
|
+
# @examples
|
100
|
+
# release.finalize :zip
|
101
|
+
def finalize(finalizer, options = {})
|
102
|
+
@finalizers << [finalizer, options]
|
103
|
+
end
|
104
|
+
|
105
|
+
# Files to clean up in the build directory just before finalization happens
|
106
|
+
#
|
107
|
+
# @param [String] Pattern to glob within build directory
|
108
|
+
#
|
109
|
+
# @examples
|
110
|
+
# release.cleanup "**/.DS_Store"
|
111
|
+
def cleanup(pattern)
|
112
|
+
@cleanups << pattern
|
113
|
+
end
|
114
|
+
|
115
|
+
# Generates a banner if a block is given, or returns the currently set banner.
|
116
|
+
# It automatically takes care of adding comment marks around the banner.
|
117
|
+
#
|
118
|
+
# The default banner looks like this:
|
119
|
+
#
|
120
|
+
# =======================
|
121
|
+
# = Version : v1.0.0 =
|
122
|
+
# = Date : 2012-06-20 =
|
123
|
+
# =======================
|
124
|
+
#
|
125
|
+
#
|
126
|
+
# @option options [:css,:js,:html,false] :comment Wether or not to comment the output and in what style. (default=js)
|
127
|
+
def banner(options = {}, &block)
|
128
|
+
options = {
|
129
|
+
:comment => :js
|
130
|
+
}.update(options)
|
131
|
+
|
132
|
+
if block_given?
|
133
|
+
@_banner = yield.to_s
|
134
|
+
elsif !@_banner
|
135
|
+
banner = []
|
136
|
+
banner << "Version : #{self.scm.version}"
|
137
|
+
banner << "Date : #{self.scm.date.strftime("%Y-%m-%d")}"
|
138
|
+
|
139
|
+
size = banner.inject(0){|mem,b| b.size > mem ? b.size : mem }
|
140
|
+
banner.map!{|b| "= #{b.ljust(size)} =" }
|
141
|
+
div = "=" * banner.first.size
|
142
|
+
banner.unshift(div)
|
143
|
+
banner << div
|
144
|
+
@_banner = banner.join("\n")
|
145
|
+
end
|
146
|
+
|
147
|
+
if options[:comment]
|
148
|
+
self.comment(@_banner, :style => options[:comment])
|
149
|
+
else
|
150
|
+
@_banner
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
# Actually perform the release
|
155
|
+
def run!
|
156
|
+
# Validate paths
|
157
|
+
validate_paths!
|
158
|
+
|
159
|
+
# Extract valid mockup
|
160
|
+
extract!
|
161
|
+
|
162
|
+
# Run stack
|
163
|
+
run_stack!
|
164
|
+
|
165
|
+
# Run injections
|
166
|
+
run_injections!
|
167
|
+
|
168
|
+
# Run cleanups
|
169
|
+
run_cleanups!
|
170
|
+
|
171
|
+
# Run finalizers
|
172
|
+
run_finalizers!
|
173
|
+
|
174
|
+
# Cleanup
|
175
|
+
cleanup! if self.config[:cleanup_build]
|
176
|
+
|
177
|
+
end
|
178
|
+
|
179
|
+
def log(part, msg)
|
180
|
+
puts part.class.to_s + " : " + msg.to_s
|
181
|
+
end
|
182
|
+
|
183
|
+
# @param [Array] globs an array of file path globs that will be globbed against the build_path
|
184
|
+
# @param [Array] excludes an array of regexps that will be excluded from the result
|
185
|
+
def get_files(globs, excludes = [])
|
186
|
+
files = globs.map{|g| Dir.glob(self.build_path + g) }.flatten
|
187
|
+
if excludes.any?
|
188
|
+
files.reject{|c| excludes.detect{|e| e.match(c) } }
|
189
|
+
else
|
190
|
+
files
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
protected
|
195
|
+
|
196
|
+
# ==============
|
197
|
+
# = The runway =
|
198
|
+
# ==============
|
199
|
+
|
200
|
+
def validate_paths!
|
201
|
+
# Make sure the build_path is empty
|
202
|
+
raise ArgumentError, "Build path \"#{self.build_path}\" is not empty" if self.build_path.exist?
|
203
|
+
|
204
|
+
# Make sure the target_path exists
|
205
|
+
raise ArgumentError, "Target path \"#{self.target_path}\" does not exist" if !self.target_path.exist?
|
206
|
+
end
|
207
|
+
|
208
|
+
def extract!
|
209
|
+
extractor = Extractor.new(self.project, self.build_path)
|
210
|
+
extractor.run!
|
211
|
+
end
|
212
|
+
|
213
|
+
def run_stack!
|
214
|
+
@stack = self.class.default_stack.dup if @stack.empty?
|
215
|
+
@stack.each do |processor, options|
|
216
|
+
get_callable(processor, HtmlMockup::Release::Processors).call(self, options)
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
def run_injections!
|
221
|
+
@injections.each do |injection|
|
222
|
+
Injector.new(injection[0], injection[1]).call(self)
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
def run_finalizers!
|
227
|
+
@finalizers = self.class.default_finalizers.dup if @finalizers.empty?
|
228
|
+
@finalizers.each do |finalizer, options|
|
229
|
+
get_callable(finalizer, HtmlMockup::Release::Finalizers).call(self, options)
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
def run_cleanups!
|
234
|
+
# We switch to the build path and append the globbed files for safety, so even if you manage to sneak in a
|
235
|
+
# pattern like "/**/*" it won't do you any good as it will be reappended to the path
|
236
|
+
Dir.chdir(self.build_path.to_s) do
|
237
|
+
@cleanups.each do |pattern|
|
238
|
+
Dir.glob(pattern).each do |file|
|
239
|
+
path = File.join(self.build_path.to_s, file)
|
240
|
+
log(self, "Cleaning up \"#{path}\" in build")
|
241
|
+
rm(path)
|
242
|
+
end
|
243
|
+
end
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
def cleanup!
|
248
|
+
log(self, "Cleaning up build path #{self.build_path}")
|
249
|
+
rm_rf(self.build_path)
|
250
|
+
end
|
251
|
+
|
252
|
+
# Makes callable into a object that responds to call.
|
253
|
+
#
|
254
|
+
# @param [#call, Symbol, Class] callable If callable already responds to #call will just return callable, a Symbol will be searched for in the scope parameter, a class will be instantiated (and checked if it will respond to #call)
|
255
|
+
# @param [Module] scope The scope in which to search callable in if it's a Symbol
|
256
|
+
def get_callable(callable, scope)
|
257
|
+
return callable if callable.respond_to?(:call)
|
258
|
+
|
259
|
+
if callable.kind_of?(Symbol)
|
260
|
+
# TODO camelcase callable
|
261
|
+
callable = callable.to_s.capitalize.to_sym
|
262
|
+
if scope.constants.include?(callable)
|
263
|
+
c = scope.const_get(callable)
|
264
|
+
callable = c if c.is_a?(Class)
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
if callable.kind_of?(Class)
|
269
|
+
callable = callable.new
|
270
|
+
end
|
271
|
+
|
272
|
+
if callable.respond_to?(:call)
|
273
|
+
callable
|
274
|
+
else
|
275
|
+
raise ArgumentError, "Could not resolve #{callable.inspect}. Callable must be an object that responds to #call or a symbol that resolve to such an object or a class with a #call instance method."
|
276
|
+
end
|
277
|
+
|
278
|
+
end
|
279
|
+
|
280
|
+
# @param [String] string The string to comment
|
281
|
+
#
|
282
|
+
# @option options [:html, :css, :js] :style The comment style to use (default=:js, which is the same as :css)
|
283
|
+
# @option options [Boolean] :per_line Comment per line or make one block? (default=true)
|
284
|
+
def comment(string, options = {})
|
285
|
+
options = {
|
286
|
+
:style => :css,
|
287
|
+
:per_line => true
|
288
|
+
}.update(options)
|
289
|
+
|
290
|
+
commenters = {
|
291
|
+
:html => Proc.new{|s| "<!-- #{s} -->" },
|
292
|
+
:css => Proc.new{|s| "/* #{s} */" },
|
293
|
+
:js => Proc.new{|s| "/* #{s} */" }
|
294
|
+
}
|
295
|
+
|
296
|
+
commenter = commenters[options[:style]] || commenters[:js]
|
297
|
+
|
298
|
+
if options[:per_line]
|
299
|
+
string = string.split(/\r?\n/)
|
300
|
+
string.map{|s| commenter.call(s) }.join("\n")
|
301
|
+
else
|
302
|
+
commenter.call(s)
|
303
|
+
end
|
304
|
+
end
|
305
|
+
end
|
306
|
+
end
|
307
|
+
|
308
|
+
require File.dirname(__FILE__) + "/extractor"
|
309
|
+
require File.dirname(__FILE__) + "/release/scm"
|
310
|
+
require File.dirname(__FILE__) + "/release/injector"
|
311
|
+
require File.dirname(__FILE__) + "/release/finalizers"
|
312
|
+
require File.dirname(__FILE__) + "/release/processors"
|
data/lib/html_mockup/server.rb
CHANGED
@@ -6,17 +6,28 @@ require File.dirname(__FILE__) + "/rack/html_validator"
|
|
6
6
|
|
7
7
|
module HtmlMockup
|
8
8
|
class Server
|
9
|
-
attr_accessor :options,:server_options, :root, :partial_path
|
10
9
|
|
11
|
-
|
10
|
+
attr_reader :options
|
11
|
+
|
12
|
+
attr_accessor :html_path, :partial_path
|
13
|
+
|
14
|
+
attr_accessor :port, :handler
|
15
|
+
|
16
|
+
def initialize(html_path, partial_path, options={})
|
12
17
|
@stack = ::Rack::Builder.new
|
13
18
|
|
14
19
|
@middleware = []
|
15
|
-
@
|
20
|
+
@html_path = html_path
|
16
21
|
@partial_path = partial_path
|
17
|
-
@options
|
22
|
+
@options = {
|
23
|
+
:handler => nil, # Autodetect
|
24
|
+
:port => 9000
|
25
|
+
}.update(options)
|
26
|
+
|
27
|
+
@port = @options[:port]
|
28
|
+
@handler = @options[:handler]
|
18
29
|
end
|
19
|
-
|
30
|
+
|
20
31
|
# Use the specified Rack middleware
|
21
32
|
def use(middleware, *args, &block)
|
22
33
|
@middleware << [middleware, args, block]
|
@@ -25,7 +36,7 @@ module HtmlMockup
|
|
25
36
|
def handler
|
26
37
|
if self.options[:handler]
|
27
38
|
begin
|
28
|
-
@handler = ::Rack::Handler.get(self.
|
39
|
+
@handler = ::Rack::Handler.get(self.handler)
|
29
40
|
rescue LoadError
|
30
41
|
rescue NameError
|
31
42
|
end
|
@@ -35,9 +46,9 @@ module HtmlMockup
|
|
35
46
|
end
|
36
47
|
@handler ||= detect_rack_handler
|
37
48
|
end
|
38
|
-
|
39
|
-
def run
|
40
|
-
self.handler.run self.application,
|
49
|
+
|
50
|
+
def run!
|
51
|
+
self.handler.run self.application, self.server_options do |server|
|
41
52
|
trap(:INT) do
|
42
53
|
## Use thins' hard #stop! if available, otherwise just #stop
|
43
54
|
server.respond_to?(:stop!) ? server.stop! : server.stop
|
@@ -45,6 +56,7 @@ module HtmlMockup
|
|
45
56
|
end
|
46
57
|
end
|
47
58
|
end
|
59
|
+
alias :run :run!
|
48
60
|
|
49
61
|
def application
|
50
62
|
return @app if @app
|
@@ -56,7 +68,7 @@ module HtmlMockup
|
|
56
68
|
@middleware.each { |c,a,b| @stack.use(c, *a, &b) }
|
57
69
|
|
58
70
|
@stack.use Rack::HtmlValidator if self.options["validate"]
|
59
|
-
@stack.run Rack::HtmlMockup.new(self.
|
71
|
+
@stack.run Rack::HtmlMockup.new(self.html_path, self.partial_path)
|
60
72
|
|
61
73
|
@app = @stack.to_app
|
62
74
|
end
|
@@ -64,6 +76,14 @@ module HtmlMockup
|
|
64
76
|
|
65
77
|
protected
|
66
78
|
|
79
|
+
# Generate server options for handler
|
80
|
+
def server_options
|
81
|
+
{
|
82
|
+
:Port => self.port
|
83
|
+
}
|
84
|
+
end
|
85
|
+
|
86
|
+
|
67
87
|
# Sinatra's detect_rack_handler
|
68
88
|
def detect_rack_handler
|
69
89
|
servers = %w[mongrel thin webrick]
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: html_mockup
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,22 +9,27 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-10-08 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: thor
|
16
|
-
requirement:
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
20
20
|
- !ruby/object:Gem::Version
|
21
|
-
version: 0.
|
21
|
+
version: 0.16.0
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements:
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 0.16.0
|
25
30
|
- !ruby/object:Gem::Dependency
|
26
31
|
name: rack
|
27
|
-
requirement:
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
28
33
|
none: false
|
29
34
|
requirements:
|
30
35
|
- - ! '>='
|
@@ -32,7 +37,12 @@ dependencies:
|
|
32
37
|
version: 1.0.0
|
33
38
|
type: :runtime
|
34
39
|
prerelease: false
|
35
|
-
version_requirements:
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 1.0.0
|
36
46
|
description:
|
37
47
|
email: flurin@digitpaint.nl
|
38
48
|
executables:
|
@@ -48,8 +58,23 @@ files:
|
|
48
58
|
- examples/partials/test.part.rhtml
|
49
59
|
- examples/script/server
|
50
60
|
- lib/html_mockup/cli.rb
|
61
|
+
- lib/html_mockup/extractor.rb
|
62
|
+
- lib/html_mockup/mockupfile.rb
|
63
|
+
- lib/html_mockup/project.rb
|
51
64
|
- lib/html_mockup/rack/html_mockup.rb
|
52
65
|
- lib/html_mockup/rack/html_validator.rb
|
66
|
+
- lib/html_mockup/rack/sleep.rb
|
67
|
+
- lib/html_mockup/release.rb
|
68
|
+
- lib/html_mockup/release/finalizers.rb
|
69
|
+
- lib/html_mockup/release/finalizers/dir.rb
|
70
|
+
- lib/html_mockup/release/finalizers/zip.rb
|
71
|
+
- lib/html_mockup/release/injector.rb
|
72
|
+
- lib/html_mockup/release/processors.rb
|
73
|
+
- lib/html_mockup/release/processors/requirejs.rb
|
74
|
+
- lib/html_mockup/release/processors/sass.rb
|
75
|
+
- lib/html_mockup/release/processors/yuicompressor.rb
|
76
|
+
- lib/html_mockup/release/scm.rb
|
77
|
+
- lib/html_mockup/release/scm/git.rb
|
53
78
|
- lib/html_mockup/server.rb
|
54
79
|
- lib/html_mockup/template.rb
|
55
80
|
- lib/html_mockup/w3c_validator.rb
|
@@ -66,6 +91,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
66
91
|
- - ! '>='
|
67
92
|
- !ruby/object:Gem::Version
|
68
93
|
version: '0'
|
94
|
+
segments:
|
95
|
+
- 0
|
96
|
+
hash: -1984595046850543499
|
69
97
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
70
98
|
none: false
|
71
99
|
requirements:
|
@@ -74,7 +102,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
74
102
|
version: '0'
|
75
103
|
requirements: []
|
76
104
|
rubyforge_project:
|
77
|
-
rubygems_version: 1.8.
|
105
|
+
rubygems_version: 1.8.24
|
78
106
|
signing_key:
|
79
107
|
specification_version: 3
|
80
108
|
summary: HTML Mockup is a set of tools to create self-containing HTML mockups.
|