html_mockup 0.4.0 → 0.5.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/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
data/bin/mockup
CHANGED
File without changes
|
data/lib/html_mockup/cli.rb
CHANGED
@@ -6,29 +6,32 @@ require 'fileutils'
|
|
6
6
|
include FileUtils
|
7
7
|
|
8
8
|
require File.dirname(__FILE__) + "/template"
|
9
|
+
require File.dirname(__FILE__) + "/project"
|
9
10
|
require File.dirname(__FILE__) + "/w3c_validator"
|
10
11
|
|
11
12
|
module HtmlMockup
|
12
13
|
class Cli < Thor
|
13
14
|
desc "serve [directory]","Serve directory as HTML, defaults to current directory"
|
14
15
|
method_options :port => :string, # Defaults to 9000
|
15
|
-
:
|
16
|
-
:
|
16
|
+
:html_path => :string, # The document root, defaults to "[directory]/html"
|
17
|
+
:partial_path => :string, # Defaults to [directory]/partials
|
17
18
|
:handler => :string # The handler to use (defaults to mongrel)
|
18
|
-
def serve(path=".")
|
19
|
-
|
19
|
+
def serve(path=".")
|
20
|
+
# Load the project, it should take care of all the paths
|
21
|
+
@project = initialize_project(path, options)
|
20
22
|
|
21
|
-
|
23
|
+
server = @project.server
|
22
24
|
|
23
|
-
|
24
|
-
|
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)"
|
25
|
+
puts "Running HtmlMockup with #{server.handler.inspect} on port #{server.port}"
|
26
|
+
puts banner(@project)
|
30
27
|
|
31
|
-
server.run
|
28
|
+
server.run!
|
29
|
+
end
|
30
|
+
|
31
|
+
desc "release [directory]", "Create a release for the project"
|
32
|
+
def release(path=".")
|
33
|
+
project = initialize_project(path, options)
|
34
|
+
project.release.run!
|
32
35
|
end
|
33
36
|
|
34
37
|
desc "validate [directory/file]", "Validates the file or all HTML in directory"
|
@@ -84,72 +87,35 @@ module HtmlMockup
|
|
84
87
|
end
|
85
88
|
end
|
86
89
|
|
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
90
|
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]
|
91
|
+
method_options :partial_path => :string, # Defaults to [directory]/partials
|
109
92
|
:filter => :string # What files should be converted defaults to **/*.html
|
110
|
-
def extract(source_path=".",target_path="../out")
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
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).to_s
|
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
|
93
|
+
def extract(source_path=".", target_path="../out")
|
94
|
+
project = initialize_project(source_path)
|
95
|
+
extractor = HtmlMockup::Extractor.new(project, target_path)
|
96
|
+
puts "Extracting mockup"
|
97
|
+
puts banner(project)
|
98
|
+
extractor.run!
|
143
99
|
end
|
144
100
|
|
145
101
|
protected
|
146
102
|
|
147
|
-
def
|
148
|
-
|
149
|
-
|
150
|
-
[path,partial_path]
|
103
|
+
def banner(project)
|
104
|
+
puts " Html: \"#{project.html_path}\""
|
105
|
+
puts " Partials: \"#{project.partial_path}\" (#{HtmlMockup::Template.partial_files(project.partial_path).size} found)"
|
151
106
|
end
|
152
107
|
|
108
|
+
# TODO: handle options
|
109
|
+
def initialize_project(path, options={})
|
110
|
+
|
111
|
+
if((Pathname.new(path) + "../partials").exist?)
|
112
|
+
puts "[ERROR]: Don't use the \"html\" path, use the project base path instead"
|
113
|
+
exit(1)
|
114
|
+
end
|
115
|
+
|
116
|
+
Project.new(path)
|
117
|
+
end
|
118
|
+
|
153
119
|
def w3cvalidate(file)
|
154
120
|
validator = W3CValidator.new(File.read(file))
|
155
121
|
validator.validate!
|
@@ -160,19 +126,6 @@ module HtmlMockup
|
|
160
126
|
validator.valid
|
161
127
|
end
|
162
128
|
|
163
|
-
|
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.to_s =~ /\/$/) || (path.to_s =~ /^[^.]+$/)
|
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
|
129
|
+
|
177
130
|
end
|
178
131
|
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
require 'hpricot'
|
2
|
+
|
3
|
+
module HtmlMockup
|
4
|
+
class Extractor
|
5
|
+
|
6
|
+
attr_reader :project, :target_path
|
7
|
+
|
8
|
+
def initialize(project, target_path)
|
9
|
+
@project = project
|
10
|
+
@target_path = Pathname.new(target_path)
|
11
|
+
end
|
12
|
+
|
13
|
+
def run!
|
14
|
+
target_path = self.target_path
|
15
|
+
source_path, partial_path = self.project.html_path, self.project.partial_path
|
16
|
+
|
17
|
+
|
18
|
+
filter = "**/*.html"
|
19
|
+
raise ArgumentError, "Target #{target_path} already exists, please choose a new directory to extract into" if target_path.exist?
|
20
|
+
|
21
|
+
mkdir_p(target_path)
|
22
|
+
target_path = target_path.realpath
|
23
|
+
|
24
|
+
# Copy source to target first, we'll overwrite the templates later on.
|
25
|
+
cp_r(source_path.children, target_path)
|
26
|
+
|
27
|
+
Dir.chdir(source_path) do
|
28
|
+
Dir.glob(filter).each do |file_name|
|
29
|
+
source = HtmlMockup::Template.open(file_name, :partial_path => partial_path).render
|
30
|
+
cur_dir = Pathname.new(file_name).dirname
|
31
|
+
up_to_root = File.join([".."] * (file_name.split("/").size - 1))
|
32
|
+
doc = Hpricot(source)
|
33
|
+
%w{src href action}.each do |attribute|
|
34
|
+
(doc/"*[@#{attribute}]").each do |tag|
|
35
|
+
converted_url = convert_relative_url_to_absolute_url(tag[attribute], cur_dir, up_to_root)
|
36
|
+
|
37
|
+
case converted_url
|
38
|
+
when String
|
39
|
+
tag[attribute] = converted_url
|
40
|
+
when nil
|
41
|
+
puts "Could not resolve link #{tag[attribute]} in #{file_name}"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
File.open(target_path + file_name,"w"){|f| f.write(doc.to_original_html) }
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
protected
|
53
|
+
|
54
|
+
# @return [false, nil, String] False if it can't be converted, nil if it can't be resolved and the converted string if it can be resolved.
|
55
|
+
def convert_relative_url_to_absolute_url(url, cur_dir, up_to_root)
|
56
|
+
# Skip if the url doesn't start with a / (but not with //)
|
57
|
+
return false unless url =~ /\A\/[^\/]/
|
58
|
+
|
59
|
+
# Strip off anchors
|
60
|
+
anchor = nil
|
61
|
+
url.gsub!(/(#.+)\Z/) do |r|
|
62
|
+
anchor = r
|
63
|
+
""
|
64
|
+
end
|
65
|
+
|
66
|
+
# Strip off query strings
|
67
|
+
query = nil
|
68
|
+
url.gsub!(/(\?.+)\Z/) do |r|
|
69
|
+
query = r
|
70
|
+
""
|
71
|
+
end
|
72
|
+
|
73
|
+
if true_file = resolve_path(cur_dir + up_to_root + url.sub(/\A\//,""))
|
74
|
+
url = true_file.relative_path_from(cur_dir).to_s
|
75
|
+
url += query if query
|
76
|
+
url += anchor if anchor
|
77
|
+
url
|
78
|
+
else
|
79
|
+
nil
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
def resolve_path(path)
|
85
|
+
path = Pathname.new(path) unless path.kind_of?(Pathname)
|
86
|
+
# Append index.html/index.htm/index.rhtml if it's a diretory
|
87
|
+
if path.directory?
|
88
|
+
search_files = %w{.html .htm}.map!{|p| path + "index#{p}" }
|
89
|
+
# If it ends with a slash or does not contain a . and it's not a directory
|
90
|
+
# try to add .html/.htm to see if that exists.
|
91
|
+
elsif (path.to_s =~ /\/$/) || (path.to_s =~ /^[^.]+$/)
|
92
|
+
search_files = [path.to_s + ".html", path.to_s + ".htm"].map!{|p| Pathname.new(p) }
|
93
|
+
else
|
94
|
+
search_files = [path]
|
95
|
+
end
|
96
|
+
search_files.find{|p| p.exist? }
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module HtmlMockup
|
2
|
+
# Loader for mockupfile
|
3
|
+
class Mockupfile
|
4
|
+
|
5
|
+
# This is the context for the mockupfile evaluation. It should be empty except for the
|
6
|
+
# #mockup method.
|
7
|
+
class Context
|
8
|
+
|
9
|
+
def initialize(mockupfile)
|
10
|
+
@_mockupfile = mockupfile
|
11
|
+
end
|
12
|
+
|
13
|
+
def mockup
|
14
|
+
@_mockupfile
|
15
|
+
end
|
16
|
+
|
17
|
+
def binding
|
18
|
+
::Kernel.binding
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
# @attr :path [Pathname] The path of the Mockupfile for this project
|
24
|
+
attr_accessor :path, :project
|
25
|
+
|
26
|
+
def initialize(project)
|
27
|
+
@project = project
|
28
|
+
@path = Pathname.new(project.path + "Mockupfile")
|
29
|
+
end
|
30
|
+
|
31
|
+
# Actually load the mockupfile
|
32
|
+
def load
|
33
|
+
if File.exist?(@path) && !self.loaded?
|
34
|
+
@source = File.read(@path)
|
35
|
+
context = Context.new(self)
|
36
|
+
eval @source, context.binding
|
37
|
+
@loaded = true
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# Wether or not the Mockupfile has been loaded
|
42
|
+
def loaded?
|
43
|
+
@loaded
|
44
|
+
end
|
45
|
+
|
46
|
+
def release
|
47
|
+
if block_given?
|
48
|
+
yield(self.project.release)
|
49
|
+
end
|
50
|
+
self.project.release
|
51
|
+
end
|
52
|
+
|
53
|
+
def serve
|
54
|
+
if block_given?
|
55
|
+
yield(self.project.server)
|
56
|
+
end
|
57
|
+
self.project.server
|
58
|
+
end
|
59
|
+
|
60
|
+
alias :server :serve
|
61
|
+
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/release"
|
2
|
+
require File.dirname(__FILE__) + "/server"
|
3
|
+
require File.dirname(__FILE__) + "/mockupfile"
|
4
|
+
|
5
|
+
module HtmlMockup
|
6
|
+
# Loader for mockupfile
|
7
|
+
class Project
|
8
|
+
|
9
|
+
# @attr :path [Pathname] The project path
|
10
|
+
# @attr :html_path [Pathname] The path of the HTML mockup
|
11
|
+
# @attr :partial_path [Pathname] The path for the partials for this mockup
|
12
|
+
# @attr :mockupfile [Mockupfile] The Mockupfile for this project
|
13
|
+
attr_accessor :path, :html_path, :partial_path, :mockupfile
|
14
|
+
|
15
|
+
def initialize(path, options={})
|
16
|
+
@path = Pathname.new(path)
|
17
|
+
|
18
|
+
options = {
|
19
|
+
:html_path => @path + "html",
|
20
|
+
:partial_path => @path + "partials"
|
21
|
+
}.update(options)
|
22
|
+
|
23
|
+
html_path, partial_path = mockup_paths(options[:html_path], options[:partial_path])
|
24
|
+
@mockupfile = Mockupfile.new(self)
|
25
|
+
@mockupfile.load
|
26
|
+
end
|
27
|
+
|
28
|
+
def server
|
29
|
+
@server ||= Server.new(self.html_path, self.partial_path)
|
30
|
+
end
|
31
|
+
|
32
|
+
def release
|
33
|
+
@release ||= Release.new(self)
|
34
|
+
end
|
35
|
+
|
36
|
+
def html_path=(p)
|
37
|
+
@html_path = Pathname.new(p).realpath
|
38
|
+
end
|
39
|
+
|
40
|
+
def partial_path=(p)
|
41
|
+
@partial_path = Pathname.new(p).realpath
|
42
|
+
end
|
43
|
+
|
44
|
+
protected
|
45
|
+
|
46
|
+
def mockup_paths(html_path, partial_path = nil)
|
47
|
+
html_path = Pathname.new(html_path)
|
48
|
+
partial_path = partial_path && Pathname.new(partial_path) || (html_path + "../partials/")
|
49
|
+
[html_path, partial_path]
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
@@ -14,16 +14,18 @@ module HtmlMockup
|
|
14
14
|
def call(env)
|
15
15
|
path = env["PATH_INFO"]
|
16
16
|
|
17
|
-
#
|
17
|
+
# TODO: Combine with Extractor#resolve_path
|
18
|
+
|
19
|
+
# Append index.html/index.htm if it's a diretory
|
18
20
|
if File.directory?(File.join(@docroot,path))
|
19
|
-
search_files = %w{.html .htm
|
20
|
-
# If it's already a .html/.htm
|
21
|
-
elsif (path =~ /\.
|
21
|
+
search_files = %w{.html .htm}.map!{|p| File.join(@docroot,path,"index#{p}")}
|
22
|
+
# If it's already a .html/.htm file, render that file
|
23
|
+
elsif (path =~ /\.html?$/)
|
22
24
|
search_files = [File.join(@docroot,path)]
|
23
25
|
# If it ends with a slash or does not contain a . and it's not a directory
|
24
|
-
# try to add .html/.htm
|
26
|
+
# try to add .html/.htm to see if that exists.
|
25
27
|
elsif (path =~ /\/$/) || (path =~ /^[^.]+$/)
|
26
|
-
search_files = [path + ".html", path + ".htm"
|
28
|
+
search_files = [path + ".html", path + ".htm"].map!{|p| File.join(@docroot,p) }
|
27
29
|
# Otherwise don't render anything at all.
|
28
30
|
else
|
29
31
|
search_files = []
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module HtmlMockup
|
2
|
+
module Rack
|
3
|
+
# Listens to the "sleep" parameter and sleeps the amount of seconds specified by the parameter. There is however a maximum of 5 seconds.
|
4
|
+
class Sleep
|
5
|
+
|
6
|
+
def initialize(app)
|
7
|
+
@app = app
|
8
|
+
end
|
9
|
+
|
10
|
+
def call(env)
|
11
|
+
r = Rack::Request.new(env)
|
12
|
+
if r.params["sleep"]
|
13
|
+
sleeptime = [r.params["sleep"].to_i, 5].min
|
14
|
+
sleep sleeptime
|
15
|
+
end
|
16
|
+
@app.call(env)
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
# Finalizes the release into a directory in target_path
|
4
|
+
#
|
5
|
+
# The directory name will have the format PREFIX-VERSION
|
6
|
+
#
|
7
|
+
module HtmlMockup::Release::Finalizers
|
8
|
+
class Dir < Base
|
9
|
+
|
10
|
+
# @option options :prefix Prefix to put before the version (default = "html")
|
11
|
+
def call(release, options = {})
|
12
|
+
name = [(options[:prefix] || "html"), release.scm.version].join("-")
|
13
|
+
|
14
|
+
release.log(self, "Finalizing release to #{release.target_path + name}")
|
15
|
+
|
16
|
+
if File.exist?(release.target_path + name)
|
17
|
+
release.log(self, "Removing existing target #{release.target_path + name}")
|
18
|
+
FileUtils.rm_rf(release.target_path + name)
|
19
|
+
end
|
20
|
+
|
21
|
+
FileUtils.cp_r release.build_path, release.target_path + name
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module HtmlMockup::Release::Finalizers
|
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,98 @@
|
|
1
|
+
require 'tilt'
|
2
|
+
module HtmlMockup
|
3
|
+
|
4
|
+
# Inject VERSION / DATE (i.e. in TOC)
|
5
|
+
# r.inject({"VERSION" => release.version, "DATE" => release.date}, :into => %w{_doc/toc.html})
|
6
|
+
|
7
|
+
# Inject CHANGELOG
|
8
|
+
# r.inject({"CHANGELOG" => {:file => "", :filter => BlueCloth}}, :into => %w{_doc/changelog.html})
|
9
|
+
|
10
|
+
class Release::Injector
|
11
|
+
|
12
|
+
# @example Simple variable injection (replaces [VARIABLE] into all .css files)
|
13
|
+
# {"[VARIABLE]" => "replacement"}, :into => %w{**/*.css}
|
14
|
+
#
|
15
|
+
# @example Regex variable injection (replaces all matches into test.js files)
|
16
|
+
# {/\/\*\s*\[BANNER\]\s*\*\// => "replacement"}, :into => %w{javacripts/test.js}
|
17
|
+
#
|
18
|
+
# @example Simple variable injection with filtering (replaces [VARIABLE] with :content run through the markdown processor into all .html files)
|
19
|
+
# {"[VARIABLE]" => {:content => "# header one", :processor => "md"}, :into => %w{**/*.html}
|
20
|
+
#
|
21
|
+
# @example Full file injection (replaces all matches of [CHANGELOG] with the contents of "CHANGELOG.md" into _doc/changelog.html)
|
22
|
+
#
|
23
|
+
# {"CHANGELOG" => {:file => "CHANGELOG.md"}}, :into => %w{_doc/changelog.html}
|
24
|
+
#
|
25
|
+
# @example Full file injection with filtering (replaces all matches of [CHANGELOG] with the contents of "CHANGELOG" which ran through Markdown compresser into _doc/changelog.html)
|
26
|
+
#
|
27
|
+
# {"CHANGELOG" => {:file => "CHANGELOG", :processor => "md"}}, :into => %w{_doc/changelog.html}
|
28
|
+
#
|
29
|
+
# Processors are based on Tilt (https://github.com/rtomayko/tilt).
|
30
|
+
# Currently supported/tested processors are:
|
31
|
+
#
|
32
|
+
# * 'md' for Markdown (bluecloth)
|
33
|
+
#
|
34
|
+
# Injection files are relative to the :source_path
|
35
|
+
#
|
36
|
+
# @param [Hash] variables Variables to inject. See example for more info
|
37
|
+
# @option options [Array] :into An array of file globs relative to the build_path
|
38
|
+
def initialize(variables, options)
|
39
|
+
@variables = variables
|
40
|
+
@into = options[:into]
|
41
|
+
end
|
42
|
+
|
43
|
+
def call(release)
|
44
|
+
files = release.get_files(@into)
|
45
|
+
|
46
|
+
files.each do |f|
|
47
|
+
c = File.read(f)
|
48
|
+
injected_vars = []
|
49
|
+
@variables.each do |variable, injection|
|
50
|
+
if c.gsub!(variable, get_content(injection, release))
|
51
|
+
injected_vars << variable
|
52
|
+
end
|
53
|
+
end
|
54
|
+
release.log(self, "Injected variables #{injected_vars.inspect} into #{f}") if injected_vars.size > 0
|
55
|
+
File.open(f,"w") { |fh| fh.write c }
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
def get_content(injection, release)
|
61
|
+
case injection
|
62
|
+
when String
|
63
|
+
injection
|
64
|
+
when Hash
|
65
|
+
get_complex_injection(injection, release)
|
66
|
+
else
|
67
|
+
if injection.respond_to?(:to_s)
|
68
|
+
injection.to_s
|
69
|
+
else
|
70
|
+
raise ArgumentError, "Woah, what's this? #{injection.inspect}"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def get_complex_injection(injection, release)
|
76
|
+
|
77
|
+
if injection[:file]
|
78
|
+
content = File.read(release.source_path + injection[:file])
|
79
|
+
else
|
80
|
+
content = injection[:content]
|
81
|
+
end
|
82
|
+
|
83
|
+
raise ArgumentError, "No :content or :file specified" if !content
|
84
|
+
|
85
|
+
if injection[:processor]
|
86
|
+
if tmpl = Tilt[injection[:processor]]
|
87
|
+
(tmpl.new{ content }).render
|
88
|
+
else
|
89
|
+
raise ArgumentError, "Unknown processor #{injection[:processor]}"
|
90
|
+
end
|
91
|
+
else
|
92
|
+
content
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
module HtmlMockup::Release::Processors
|
3
|
+
class Requirejs < Base
|
4
|
+
|
5
|
+
# @option options [Hash] :build_files An a hash of files to build (as key) and the target directory in the release to put it as value, each one will be built in a separate directory. (default is {"javascripts/site.build.js" => "javascripts"})
|
6
|
+
# @option options [String] :node The system path for node (defaults to "node" in path)
|
7
|
+
# @option options [String] :rjs The system path to the requirejs optimizer (r.js) (defaults to "../vendor/requirejs/r.js" (relative to source_path))
|
8
|
+
def call(release, options={})
|
9
|
+
options = {
|
10
|
+
:build_files => {"javascripts/site.build.js" => "javascripts"},
|
11
|
+
:rjs => release.source_path + "../vendor/requirejs/r.js",
|
12
|
+
:node => "node"
|
13
|
+
}.update(options)
|
14
|
+
|
15
|
+
begin
|
16
|
+
`#{options[:node]} -v`
|
17
|
+
rescue Errno::ENOENT
|
18
|
+
raise RuntimeError, "Could not find node in #{node.inspect}"
|
19
|
+
end
|
20
|
+
|
21
|
+
if !File.exist?(options[:rjs])
|
22
|
+
raise RuntimeError, "Could not find r.js optimizer at #{options[:rjs].inspect}"
|
23
|
+
end
|
24
|
+
|
25
|
+
options[:build_files].each do |build_file, target|
|
26
|
+
build_file = release.build_path + build_file
|
27
|
+
target = release.build_path + target
|
28
|
+
release.log(self, "Optimizing #{build_file}")
|
29
|
+
|
30
|
+
# Hack to create tempfile in build
|
31
|
+
t = Tempfile.new("requirejs", release.build_path)
|
32
|
+
tmp_build_dir = t.path
|
33
|
+
t.close
|
34
|
+
t.unlink
|
35
|
+
|
36
|
+
# Run r.js optimizer
|
37
|
+
output = `#{options[:node]} #{options[:rjs]} -o #{build_file} dir=#{tmp_build_dir}`
|
38
|
+
|
39
|
+
# Check if r.js succeeded
|
40
|
+
unless $?.success?
|
41
|
+
raise RuntimeError, "Asset compilation with node failed.\nr.js output:\n #{output}"
|
42
|
+
end
|
43
|
+
|
44
|
+
if File.exist?(target)
|
45
|
+
release.log(self, "Removing target #{target}")
|
46
|
+
FileUtils.rm_rf(target)
|
47
|
+
end
|
48
|
+
|
49
|
+
# Move the tmp_build_dir to target
|
50
|
+
FileUtils.mv(tmp_build_dir, target)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# Use the sass gem
|
2
|
+
require 'sass'
|
3
|
+
|
4
|
+
module HtmlMockup::Release::Processors
|
5
|
+
class Sass < Base
|
6
|
+
# @param [Hash] options Options as described below, all other options will be passed to Sass.compile_file.
|
7
|
+
#
|
8
|
+
# @option options [Array] :match An array of shell globs, defaults to ["stylesheets/**/*.scss"]
|
9
|
+
# @option options [Array] :skip An array of regexps which will be skipped, defaults to [/_.*\.scss\Z/], Attention! Skipped files will be deleted as well!
|
10
|
+
def call(release, options={})
|
11
|
+
options = {
|
12
|
+
:match => ["stylesheets/**/*.scss"],
|
13
|
+
:skip => [/_.*\.scss\Z/],
|
14
|
+
:style => :expanded
|
15
|
+
}.update(options)
|
16
|
+
|
17
|
+
match = options.delete(:match)
|
18
|
+
skip = options.delete(:skip)
|
19
|
+
|
20
|
+
# Sassify SCSS files
|
21
|
+
files = release.get_files(match)
|
22
|
+
files.each do |f|
|
23
|
+
if !skip.detect{|r| r.match(f) }
|
24
|
+
release.log(self, "Processing: #{f}")
|
25
|
+
# Compile SCSS
|
26
|
+
::Sass.compile_file(f, f.gsub(/\.scss$/, ".css"), options)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# Cleanup
|
31
|
+
files.each do |f|
|
32
|
+
# Remove source file
|
33
|
+
File.unlink(f)
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|