html_mockup 0.7.4 → 0.8.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.
- checksums.yaml +15 -0
- data/CHANGELOG.md +14 -0
- data/html_mockup.gemspec +5 -4
- data/lib/html_mockup/cli.rb +9 -3
- data/lib/html_mockup/extractor.rb +3 -1
- data/lib/html_mockup/mockup_template.rb +97 -0
- data/lib/html_mockup/project.rb +24 -14
- data/lib/html_mockup/rack/html_mockup.rb +15 -16
- data/lib/html_mockup/release.rb +53 -8
- data/lib/html_mockup/release/finalizers.rb +1 -0
- data/lib/html_mockup/release/finalizers/git_branch.rb +92 -0
- data/lib/html_mockup/release/finalizers/rsync.rb +34 -27
- data/lib/html_mockup/release/finalizers/zip.rb +1 -1
- data/lib/html_mockup/release/processors.rb +2 -0
- data/lib/html_mockup/release/processors/mockup.rb +87 -0
- data/lib/html_mockup/release/processors/requirejs.rb +29 -5
- data/lib/html_mockup/release/processors/url_relativizer.rb +44 -0
- data/lib/html_mockup/release/processors/yuicompressor.rb +4 -2
- data/lib/html_mockup/resolver.rb +23 -22
- data/lib/html_mockup/server.rb +11 -10
- data/lib/html_mockup/template.rb +100 -111
- data/test/project/.rvmrc +1 -0
- data/test/project/Gemfile +6 -0
- data/test/project/Gemfile.lock +35 -0
- data/test/project/Mockupfile +7 -0
- data/test/project/html/formats/erb.html.erb +5 -0
- data/test/project/html/formats/markdown.md +3 -0
- data/test/project/html/formats/mockup.html +5 -0
- data/test/project/html/front_matter/erb.html.erb +16 -0
- data/test/project/html/front_matter/markdown.md +7 -0
- data/test/project/html/layouts/erb.html.erb +19 -0
- data/test/project/html/partials/erb.html.erb +10 -0
- data/test/project/html/partials/mockup.html +13 -0
- data/test/project/layouts/test.html.erb +27 -0
- data/test/project/partials/test/erb.html.erb +1 -0
- data/test/project/partials/test/markdown.md +1 -0
- data/test/project/partials/test/mockup.part.html +1 -0
- metadata +80 -19
@@ -14,12 +14,14 @@ module HtmlMockup::Release::Finalizers
|
|
14
14
|
# @option options String :remote_path The remote path to upload to
|
15
15
|
# @option options String :host The remote host to upload to
|
16
16
|
# @option options String :username The remote username to upload to
|
17
|
+
# @option options Boolean :ask Prompt the user before uploading (default is true)
|
17
18
|
def initialize(options = {})
|
18
19
|
@options = {
|
19
20
|
:rsync => "rsync",
|
20
21
|
:remote_path => "",
|
21
22
|
:host => "",
|
22
|
-
:username => ""
|
23
|
+
:username => "",
|
24
|
+
:ask => true
|
23
25
|
}.update(options)
|
24
26
|
end
|
25
27
|
|
@@ -28,36 +30,36 @@ module HtmlMockup::Release::Finalizers
|
|
28
30
|
|
29
31
|
# Validate options
|
30
32
|
validate_options!(release, options)
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
local_path = release.build_path.to_s
|
40
|
-
remote_path = options[:remote_path]
|
41
|
-
|
42
|
-
local_path += "/" unless local_path =~ /\/\Z/
|
43
|
-
remote_path += "/" unless remote_path =~ /\/\Z/
|
44
|
-
|
45
|
-
release.log(self, "Starting upload of #{(release.build_path + "*")} to #{options[:host]}")
|
46
|
-
|
47
|
-
command = "#{options[:rsync]} -az #{Shellwords.escape(local_path)} #{Shellwords.escape(options[:username])}@#{Shellwords.escape(options[:host])}:#{Shellwords.escape(remote_path)}"
|
48
|
-
|
49
|
-
# Run r.js optimizer
|
50
|
-
output = `#{command}`
|
33
|
+
|
34
|
+
if !options[:ask] || (prompt("Do you wish to upload to #{options[:host]}? Anything other than 'yes' will cancel: ")) == 'yes'
|
35
|
+
begin
|
36
|
+
`#{@options[:rsync]} --version`
|
37
|
+
rescue Errno::ENOENT
|
38
|
+
raise RuntimeError, "Could not find rsync in #{@options[:rsync].inspect}"
|
39
|
+
end
|
51
40
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
41
|
+
local_path = release.build_path.to_s
|
42
|
+
remote_path = options[:remote_path]
|
43
|
+
|
44
|
+
local_path += "/" unless local_path =~ /\/\Z/
|
45
|
+
remote_path += "/" unless remote_path =~ /\/\Z/
|
56
46
|
|
47
|
+
release.log(self, "Starting upload of #{(release.build_path + "*")} to #{options[:host]}")
|
48
|
+
|
49
|
+
command = "#{options[:rsync]} -az #{Shellwords.escape(local_path)} #{Shellwords.escape(options[:username])}@#{Shellwords.escape(options[:host])}:#{Shellwords.escape(remote_path)}"
|
50
|
+
|
51
|
+
# Run r.js optimizer
|
52
|
+
output = `#{command}`
|
53
|
+
|
54
|
+
# Check if r.js succeeded
|
55
|
+
unless $?.success?
|
56
|
+
raise RuntimeError, "Rsync failed.\noutput:\n #{output}"
|
57
|
+
end
|
58
|
+
end
|
57
59
|
end
|
58
|
-
|
60
|
+
|
59
61
|
protected
|
60
|
-
|
62
|
+
|
61
63
|
def validate_options!(release, options)
|
62
64
|
must_have_keys = [:remote_path, :host, :username]
|
63
65
|
if (options.keys & must_have_keys).size != must_have_keys.size
|
@@ -65,6 +67,11 @@ module HtmlMockup::Release::Finalizers
|
|
65
67
|
raise "Missing keys: #{(must_have_keys - options.keys).inspect}"
|
66
68
|
end
|
67
69
|
end
|
70
|
+
|
71
|
+
def prompt(question = 'Do you wish to continue?')
|
72
|
+
print(question)
|
73
|
+
return $stdin.gets.strip
|
74
|
+
end
|
68
75
|
|
69
76
|
end
|
70
77
|
end
|
@@ -13,6 +13,8 @@ module HtmlMockup::Release::Processors
|
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
|
+
require File.dirname(__FILE__) + "/processors/mockup"
|
17
|
+
require File.dirname(__FILE__) + "/processors/url_relativizer"
|
16
18
|
require File.dirname(__FILE__) + "/processors/requirejs"
|
17
19
|
require File.dirname(__FILE__) + "/processors/sass"
|
18
20
|
require File.dirname(__FILE__) + "/processors/yuicompressor"
|
@@ -0,0 +1,87 @@
|
|
1
|
+
module HtmlMockup::Release::Processors
|
2
|
+
class Mockup < Base
|
3
|
+
|
4
|
+
attr_accessor :project
|
5
|
+
|
6
|
+
def initialize(options={})
|
7
|
+
@options = {
|
8
|
+
:env => {},
|
9
|
+
:match => ["**/*.{html,md,html.erb}"],
|
10
|
+
:skip => [/\Astylesheets/, /\Ajavascripts/]
|
11
|
+
}
|
12
|
+
|
13
|
+
@options.update(options) if options
|
14
|
+
end
|
15
|
+
|
16
|
+
def call(release, options={})
|
17
|
+
self.project = release.project
|
18
|
+
|
19
|
+
options = {}.update(@options).update(options)
|
20
|
+
|
21
|
+
options[:env].update("MOCKUP_PROJECT" => project)
|
22
|
+
|
23
|
+
release.log(self, "Processing mockup files")
|
24
|
+
|
25
|
+
release.get_files(options[:match], options[:skip]).each do |file_path|
|
26
|
+
self.run_on_file!(file_path, @options[:env])
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
def run_on_file!(file_path, env = {})
|
32
|
+
template = HtmlMockup::Template.open(file_path, :partials_path => self.project.partial_path, :layouts_path => self.project.layouts_path)
|
33
|
+
|
34
|
+
# Clean up source file
|
35
|
+
FileUtils.rm(file_path)
|
36
|
+
|
37
|
+
# Write out new file
|
38
|
+
File.open(self.target_path(file_path, template),"w"){|f| f.write(template.render(env.dup)) }
|
39
|
+
end
|
40
|
+
|
41
|
+
# Runs the extractor on a single file and return processed source.
|
42
|
+
def extract_source_from_file(file_path, env = {})
|
43
|
+
HtmlMockup::Template.open(file_path, :partials_path => self.project.partial_path, :layouts_path => self.project.layouts_path).render(env.dup)
|
44
|
+
end
|
45
|
+
|
46
|
+
protected
|
47
|
+
|
48
|
+
def target_path(path, template)
|
49
|
+
# 1. If we have a double extension we rip of the template it's own extension and be done with it
|
50
|
+
parts = File.basename(path.to_s).split(".")
|
51
|
+
dir = Pathname.new(File.dirname(path.to_s))
|
52
|
+
|
53
|
+
# 2. Try to figure out the extension based on the template's mime-type
|
54
|
+
mime_types = {
|
55
|
+
"text/html" => "html",
|
56
|
+
"text/css" => "css",
|
57
|
+
"application/javascript" => "js",
|
58
|
+
"text/xml" => "xml",
|
59
|
+
"application/xml" => "xml",
|
60
|
+
"text/csv" => "csv",
|
61
|
+
"application/json" => "json"
|
62
|
+
}
|
63
|
+
extension = mime_types[template.template.class.default_mime_type]
|
64
|
+
|
65
|
+
# Always return .html directly as it will cause too much trouble otherwise
|
66
|
+
if parts.last == "html"
|
67
|
+
return path
|
68
|
+
end
|
69
|
+
|
70
|
+
if parts.size > 2
|
71
|
+
# Strip extension
|
72
|
+
dir + parts[0..-2].join(".")
|
73
|
+
else
|
74
|
+
return path if extension.nil?
|
75
|
+
|
76
|
+
if parts.size > 1
|
77
|
+
# Strip extension and replace with extension
|
78
|
+
dir + (parts[0..-2] << extension).join(".")
|
79
|
+
else
|
80
|
+
# Let's just add the extension
|
81
|
+
dir + (parts << extension).join(".")
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
end
|
@@ -4,14 +4,14 @@ module HtmlMockup::Release::Processors
|
|
4
4
|
|
5
5
|
def initialize(options = {})
|
6
6
|
@options = {
|
7
|
-
:build_files => {"javascripts/site.build.js" => "javascripts"},
|
7
|
+
:build_files => {"javascripts/site.build.js" => {:dir => "javascripts"}},
|
8
8
|
:rjs => "r.js",
|
9
9
|
:node => "node"
|
10
10
|
}.update(options)
|
11
11
|
end
|
12
12
|
|
13
13
|
|
14
|
-
# @option options [Hash] :build_files An a hash of files to build (as key) and the target
|
14
|
+
# @option options [Hash] :build_files An a hash of files to build (as key) and the target as a hash with either {:dir => "STRING"} or {:file => "STRING"} in the release to put it as value, each one will be built in a separate directory. (default is {"javascripts/site.build.js" => {:dir => "javascripts"}})
|
15
15
|
# @option options [String] :node The system path for node (defaults to "node" in path)
|
16
16
|
# @option options [String] :rjs The system path to the requirejs optimizer (r.js) (defaults to "../vendor/requirejs/r.js" (relative to source_path))
|
17
17
|
def call(release, options={})
|
@@ -27,7 +27,21 @@ module HtmlMockup::Release::Processors
|
|
27
27
|
|
28
28
|
@options[:build_files].each do |build_file, target|
|
29
29
|
build_file = release.build_path + build_file
|
30
|
-
|
30
|
+
|
31
|
+
if target.kind_of?(Hash)
|
32
|
+
if target[:dir]
|
33
|
+
target = target[:dir]
|
34
|
+
target_type = :dir
|
35
|
+
elsif target[:file]
|
36
|
+
target = target[:file]
|
37
|
+
target_type = :file
|
38
|
+
end
|
39
|
+
else
|
40
|
+
# Old style
|
41
|
+
target_type = :dir
|
42
|
+
end
|
43
|
+
|
44
|
+
target = release.build_path + target
|
31
45
|
release.log(self, "Optimizing #{build_file}")
|
32
46
|
|
33
47
|
# Hack to create tempfile in build
|
@@ -37,7 +51,13 @@ module HtmlMockup::Release::Processors
|
|
37
51
|
t.unlink
|
38
52
|
|
39
53
|
# Run r.js optimizer
|
40
|
-
|
54
|
+
if target_type == :dir
|
55
|
+
output = `#{rjs_command} -o #{build_file} dir=#{tmp_build_dir}`
|
56
|
+
else
|
57
|
+
output = `#{rjs_command} -o #{build_file} out=#{tmp_build_dir}/out.js`
|
58
|
+
end
|
59
|
+
|
60
|
+
release.debug(self, output)
|
41
61
|
|
42
62
|
# Check if r.js succeeded
|
43
63
|
unless $?.success?
|
@@ -50,7 +70,11 @@ module HtmlMockup::Release::Processors
|
|
50
70
|
end
|
51
71
|
|
52
72
|
# Move the tmp_build_dir to target
|
53
|
-
|
73
|
+
if target_type == :dir
|
74
|
+
FileUtils.mv(tmp_build_dir, target)
|
75
|
+
end
|
76
|
+
FileUtils.mv("#{tmp_build_dir}/out.js", target)
|
77
|
+
FileUtils.rm_rf(tmp_build_dir)
|
54
78
|
end
|
55
79
|
end
|
56
80
|
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require File.dirname(__FILE__) + '../../../resolver'
|
2
|
+
|
3
|
+
module HtmlMockup::Release::Processors
|
4
|
+
class UrlRelativizer < Base
|
5
|
+
|
6
|
+
def initialize(options={})
|
7
|
+
@options = {
|
8
|
+
:url_attributes => %w{src href action},
|
9
|
+
:match => ["**/*.html"]
|
10
|
+
}
|
11
|
+
|
12
|
+
@options.update(options) if options
|
13
|
+
end
|
14
|
+
|
15
|
+
def call(release, options={})
|
16
|
+
options = {}.update(@options).update(options)
|
17
|
+
|
18
|
+
release.log(self, "Relativizing all URLS in #{options[:match].inspect} files in attributes #{options[:url_attributes].inspect}")
|
19
|
+
|
20
|
+
@resolver = HtmlMockup::Resolver.new(release.build_path)
|
21
|
+
release.get_files(options[:match]).each do |file_path|
|
22
|
+
release.debug(self, "Relativizing URLS in #{file_path}") do
|
23
|
+
orig_source = File.read(file_path)
|
24
|
+
File.open(file_path,"w") do |f|
|
25
|
+
doc = Hpricot(orig_source)
|
26
|
+
options[:url_attributes].each do |attribute|
|
27
|
+
(doc/"*[@#{attribute}]").each do |tag|
|
28
|
+
converted_url = @resolver.url_to_relative_url(tag[attribute], file_path)
|
29
|
+
release.debug(self, "Converting '#{tag[attribute]}' to '#{converted_url}'")
|
30
|
+
case converted_url
|
31
|
+
when String
|
32
|
+
tag[attribute] = converted_url
|
33
|
+
when nil
|
34
|
+
release.log(self, "Could not resolve link #{tag[attribute]} in #{file_path}")
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
f.write(doc.to_original_html)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -24,6 +24,8 @@ module HtmlMockup::Release::Processors
|
|
24
24
|
css_compressor = YUI::CssCompressor.new(compressor_options)
|
25
25
|
js_compressor = YUI::JavaScriptCompressor.new(compressor_options)
|
26
26
|
|
27
|
+
release.log self, "Minifying #{options[:match].inspect}"
|
28
|
+
|
27
29
|
# Add version numbers and minify the files
|
28
30
|
release.get_files(options[:match], options[:skip]).each do |f|
|
29
31
|
type = f[/\.([^.]+)\Z/,1]
|
@@ -36,14 +38,14 @@ module HtmlMockup::Release::Processors
|
|
36
38
|
minified = [header]
|
37
39
|
|
38
40
|
# Actual minification
|
39
|
-
release.
|
41
|
+
release.debug self, "Minifying #{f}"
|
40
42
|
case type
|
41
43
|
when "css"
|
42
44
|
minified << css_compressor.compress(data)
|
43
45
|
when "js"
|
44
46
|
minified << js_compressor.compress(data)
|
45
47
|
else
|
46
|
-
release.
|
48
|
+
release.warn self, "Error minifying: encountered unknown type \"#{type}\""
|
47
49
|
minified << data
|
48
50
|
end
|
49
51
|
|
data/lib/html_mockup/resolver.rb
CHANGED
@@ -2,37 +2,38 @@ module HtmlMockup
|
|
2
2
|
class Resolver
|
3
3
|
|
4
4
|
def initialize(path)
|
5
|
+
raise ArgumentError, "Resolver base path can't be nil" if path.nil?
|
5
6
|
@base = Pathname.new(path)
|
6
7
|
end
|
7
8
|
|
8
|
-
|
9
|
+
# @param [String] url The url to resolve to a path
|
10
|
+
# @param [true,false] exact_match Wether or not to match exact paths, this is mainly used in the path_to_url method to match .js, .css, etc files.
|
11
|
+
def find_template(url, exact_match = false)
|
9
12
|
path, qs, anch = strip_query_string_and_anchor(url.to_s)
|
10
13
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
if exact_match
|
26
|
-
search_files = [File.join(@base,path)]
|
27
|
-
else
|
28
|
-
search_files = []
|
29
|
-
end
|
14
|
+
path = File.join(@base, path)
|
15
|
+
|
16
|
+
if exact_match && File.exist?(path)
|
17
|
+
return Pathname.new(path)
|
18
|
+
end
|
19
|
+
|
20
|
+
# It's a directory, add "/index"
|
21
|
+
if File.directory?(path)
|
22
|
+
path = File.join(path, "index")
|
23
|
+
end
|
24
|
+
|
25
|
+
# 2. If it's .html,we strip of the extension
|
26
|
+
if path =~ /\.html\Z/
|
27
|
+
path.sub!(/\.html\Z/, "")
|
30
28
|
end
|
31
29
|
|
32
|
-
|
33
|
-
|
30
|
+
extensions = Tilt.mappings.keys + Tilt.mappings.keys.map{|ext| "html.#{ext}"}
|
31
|
+
|
32
|
+
if found_extension = extensions.find { |ext| File.exist?(path + "." + ext) }
|
33
|
+
Pathname.new(path + "." + found_extension)
|
34
34
|
end
|
35
35
|
end
|
36
|
+
alias :url_to_path :find_template
|
36
37
|
|
37
38
|
|
38
39
|
# Convert a disk path on file to an url
|
data/lib/html_mockup/server.rb
CHANGED
@@ -4,10 +4,13 @@ require File.dirname(__FILE__) + "/w3c_validator"
|
|
4
4
|
require File.dirname(__FILE__) + "/rack/html_mockup"
|
5
5
|
require File.dirname(__FILE__) + "/rack/html_validator"
|
6
6
|
|
7
|
+
require 'webrick'
|
8
|
+
require 'webrick/https'
|
9
|
+
|
7
10
|
module HtmlMockup
|
8
11
|
class Server
|
9
12
|
|
10
|
-
attr_reader :options
|
13
|
+
attr_reader :options, :server_options
|
11
14
|
|
12
15
|
attr_reader :project
|
13
16
|
|
@@ -18,6 +21,8 @@ module HtmlMockup
|
|
18
21
|
|
19
22
|
@project = project
|
20
23
|
|
24
|
+
@server_options = {}
|
25
|
+
|
21
26
|
set_options(options)
|
22
27
|
end
|
23
28
|
|
@@ -28,7 +33,7 @@ module HtmlMockup
|
|
28
33
|
:handler => nil, # Autodetect
|
29
34
|
:port => 9000
|
30
35
|
}.update(options)
|
31
|
-
|
36
|
+
|
32
37
|
self.port = @options[:port]
|
33
38
|
self.handler = @options[:handler]
|
34
39
|
end
|
@@ -57,6 +62,10 @@ module HtmlMockup
|
|
57
62
|
end
|
58
63
|
end
|
59
64
|
alias :run :run!
|
65
|
+
|
66
|
+
def port=(p)
|
67
|
+
self.server_options[:Port] = p
|
68
|
+
end
|
60
69
|
|
61
70
|
protected
|
62
71
|
|
@@ -104,13 +113,5 @@ module HtmlMockup
|
|
104
113
|
handler
|
105
114
|
end
|
106
115
|
|
107
|
-
|
108
|
-
# Generate server options for handler
|
109
|
-
def server_options
|
110
|
-
{
|
111
|
-
:Port => self.port
|
112
|
-
}
|
113
|
-
end
|
114
|
-
|
115
116
|
end
|
116
117
|
end
|