html_mockup 0.6.5 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## Version 0.7.0
4
+ * Replace --quiet with -s in as it's no longer supported in newer GIT versions
5
+ * Add support for ENV passing to the partials
6
+ * Add support for single file processing and env passing in the extractor (release)
7
+ * Refactor path and url resolving
8
+ * Allow `.html` files to be processed by ERB (both in release and serve)
9
+ * Pass "MOCKUP_PROJECT" variable to env (both in release and serve)
10
+
3
11
  ## Version 0.6.5
4
12
  * Allow disabling of URL relativizing in the extractor with `release.extract :url_relativize => false`
5
13
  * Add missing Hpricot dependency to gem
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = "html_mockup"
5
- s.version = "0.6.5"
5
+ s.version = "0.7.0"
6
6
 
7
7
  s.authors = ["Flurin Egger", "Edwin van der Graaf"]
8
8
  s.email = ["info@digitpaint.nl", "flurin@digitpaint.nl"]
@@ -1,4 +1,5 @@
1
1
  require 'hpricot'
2
+ require File.dirname(__FILE__) + '/resolver'
2
3
 
3
4
  module HtmlMockup
4
5
  class Extractor
@@ -12,21 +13,27 @@ module HtmlMockup
12
13
 
13
14
  # @option options [Array] :url_attributes The element attributes to parse and relativize
14
15
  # @option options [Array] :url_relativize Wether or not we should relativize
16
+ # @option options [Array] :env ENV variable to pass to template renderer.
15
17
  def initialize(project, target_path, options={})
16
18
  @project = project
17
19
  @target_path = Pathname.new(target_path)
20
+ @resolver = Resolver.new(self.target_path)
21
+
18
22
 
19
23
  @options = {
20
24
  :url_attributes => %w{src href action},
21
- :url_relativize => true
25
+ :url_relativize => true,
26
+ :env => {}
22
27
  }
23
28
 
24
29
  @options.update(options) if options
30
+
31
+ env.update("MOCKUP_PROJECT" => project)
25
32
  end
26
33
 
27
34
  def run!
28
35
  target_path = self.target_path
29
- source_path, partial_path = self.project.html_path, self.project.partial_path
36
+ source_path = self.project.html_path
30
37
 
31
38
 
32
39
  filter = "**/*.html"
@@ -39,86 +46,48 @@ module HtmlMockup
39
46
  cp_r(source_path.children, target_path)
40
47
 
41
48
  Dir.chdir(source_path) do
42
- Dir.glob(filter).each do |file_name|
43
- source = HtmlMockup::Template.open(file_name, :partial_path => partial_path).render
44
-
45
- if @options[:url_relativize]
46
- source = relativize_urls(source, file_name)
47
- end
48
-
49
- File.open(target_path + file_name,"w"){|f| f.write(source) }
49
+ Dir.glob(filter).each do |file_path|
50
+ self.run_on_file!(file_path, @options[:env])
50
51
  end
51
52
  end
52
53
  end
54
+
55
+ def run_on_file!(file_path, env = {})
56
+ source = self.extract_source_from_file(file_path, env)
57
+ File.open(target_path + file_path,"w"){|f| f.write(source) }
58
+ end
59
+
60
+ # Runs the extractor on a single file and return processed source.
61
+ def extract_source_from_file(file_path, env = {})
62
+ source = HtmlMockup::Template.open(file_path, :partial_path => self.project.partial_path).render(env)
63
+
64
+ if @options[:url_relativize]
65
+ source = relativize_urls(source, file_path)
66
+ end
53
67
 
68
+ source
69
+ end
70
+
54
71
 
55
72
  protected
56
73
 
57
- def relativize_urls(source, file_name)
58
- cur_dir = Pathname.new(file_name).dirname
59
- up_to_root = File.join([".."] * (file_name.split("/").size - 1))
60
-
74
+ def relativize_urls(source, file_path)
61
75
  doc = Hpricot(source)
62
76
  @options[:url_attributes].each do |attribute|
63
77
  (doc/"*[@#{attribute}]").each do |tag|
64
- converted_url = convert_relative_url_to_absolute_url(tag[attribute], cur_dir, up_to_root)
78
+ converted_url = @resolver.url_to_relative_url(tag[attribute], file_path)
65
79
 
66
80
  case converted_url
67
81
  when String
68
82
  tag[attribute] = converted_url
69
83
  when nil
70
- puts "Could not resolve link #{tag[attribute]} in #{file_name}"
84
+ puts "Could not resolve link #{tag[attribute]} in #{file_path}"
71
85
  end
72
86
  end
73
87
  end
74
88
 
75
89
  doc.to_original_html
76
90
  end
77
-
78
- # @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.
79
- def convert_relative_url_to_absolute_url(url, cur_dir, up_to_root)
80
- # Skip if the url doesn't start with a / (but not with //)
81
- return false unless url =~ /\A\/[^\/]/
82
-
83
- # Strip off anchors
84
- anchor = nil
85
- url.gsub!(/(#.+)\Z/) do |r|
86
- anchor = r
87
- ""
88
- end
89
-
90
- # Strip off query strings
91
- query = nil
92
- url.gsub!(/(\?.+)\Z/) do |r|
93
- query = r
94
- ""
95
- end
96
-
97
- if true_file = resolve_path(cur_dir + up_to_root + url.sub(/\A\//,""))
98
- url = true_file.relative_path_from(cur_dir).to_s
99
- url += query if query
100
- url += anchor if anchor
101
- url
102
- else
103
- nil
104
- end
105
-
106
- end
107
-
108
- def resolve_path(path)
109
- path = Pathname.new(path) unless path.kind_of?(Pathname)
110
- # Append index.html/index.htm/index.rhtml if it's a diretory
111
- if path.directory?
112
- search_files = %w{.html .htm}.map!{|p| path + "index#{p}" }
113
- # If it ends with a slash or does not contain a . and it's not a directory
114
- # try to add .html/.htm to see if that exists.
115
- elsif (path.to_s =~ /\/$/) || (path.to_s =~ /^[^.]+$/)
116
- search_files = [path.to_s + ".html", path.to_s + ".htm"].map!{|p| Pathname.new(p) }
117
- else
118
- search_files = [path]
119
- end
120
- search_files.find{|p| p.exist? }
121
- end
122
-
91
+
123
92
  end
124
93
  end
@@ -2,42 +2,37 @@ require 'rack/request'
2
2
  require 'rack/response'
3
3
  require 'rack/file'
4
4
 
5
+ require File.dirname(__FILE__) + '/../resolver'
6
+
5
7
  module HtmlMockup
6
8
  module Rack
9
+
7
10
  class HtmlMockup
8
- def initialize(root,partial_path)
11
+
12
+ attr_reader :project
13
+
14
+ def initialize(project)
15
+ @project = project
16
+ root,partial_path = project.html_path, project.partial_path
17
+
9
18
  @docroot = root
10
19
  @partial_path = partial_path
11
20
  @file_server = ::Rack::File.new(@docroot)
12
21
  end
13
22
 
14
23
  def call(env)
15
- path = env["PATH_INFO"]
16
-
17
- # TODO: Combine with Extractor#resolve_path
24
+ url = env["PATH_INFO"]
25
+ env["MOCKUP_PROJECT"] = project
18
26
 
19
- # Append index.html/index.htm if it's a diretory
20
- if File.directory?(File.join(@docroot,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?$/)
24
- search_files = [File.join(@docroot,path)]
25
- # If it ends with a slash or does not contain a . and it's not a directory
26
- # try to add .html/.htm to see if that exists.
27
- elsif (path =~ /\/$/) || (path =~ /^[^.]+$/)
28
- search_files = [path + ".html", path + ".htm"].map!{|p| File.join(@docroot,p) }
29
- # Otherwise don't render anything at all.
30
- else
31
- search_files = []
32
- end
27
+ resolver = Resolver.new(@docroot)
33
28
 
34
- if template_path = search_files.find{|p| File.exist?(p)}
35
- env["rack.errors"].puts "Rendering template #{template_path.inspect} (#{path.inspect})"
29
+ if template_path = resolver.url_to_path(url)
30
+ env["rack.errors"].puts "Rendering template #{template_path.inspect} (#{url.inspect})"
36
31
  begin
37
32
  templ = ::HtmlMockup::Template.open(template_path, :partial_path => @partial_path)
38
33
  resp = ::Rack::Response.new do |res|
39
34
  res.status = 200
40
- res.write templ.render
35
+ res.write templ.render(env)
41
36
  end
42
37
  resp.finish
43
38
  rescue StandardError => e
@@ -49,7 +44,7 @@ module HtmlMockup
49
44
  resp.finish
50
45
  end
51
46
  else
52
- env["rack.errors"].puts "Invoking file handler for #{path.inspect}"
47
+ env["rack.errors"].puts "Invoking file handler for #{url.inspect}"
53
48
  @file_server.call(env)
54
49
  end
55
50
  end
@@ -61,7 +61,7 @@ module HtmlMockup::Release::Scm
61
61
 
62
62
  if $?.to_i > 0
63
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`
64
+ @_version = `git --git-dir=#{git_dir} show #{ref} --format=format:"%h" -s 2>&1`
65
65
  else
66
66
  # HEAD is a tagged version, if version is prefixed with "v" it will be stripped off
67
67
  @_version.gsub!(/^v/,"")
@@ -69,7 +69,7 @@ module HtmlMockup::Release::Scm
69
69
  @_version.strip!
70
70
 
71
71
  # Get the date in epoch time
72
- date = `git --git-dir=#{git_dir} show #{ref} --format=format:"%ct" --quiet 2>&1`
72
+ date = `git --git-dir=#{git_dir} show #{ref} --format=format:"%ct" -s 2>&1`
73
73
  if date =~ /\d+/
74
74
  @_date = Time.at(date.to_i)
75
75
  else
@@ -0,0 +1,95 @@
1
+ module HtmlMockup
2
+ class Resolver
3
+
4
+ def initialize(path)
5
+ @base = Pathname.new(path)
6
+ end
7
+
8
+ def url_to_path(url, exact_match = false)
9
+ path, qs, anch = strip_query_string_and_anchor(url.to_s)
10
+
11
+ extensions = %w{html htm}
12
+
13
+ # Append index.extension if it's a diretory
14
+ if File.directory?(File.join(@base,path))
15
+ search_files = extensions.map{|p| File.join(@base,path,"index.#{p}")}
16
+ # If it's already a .extension file, return that file
17
+ elsif extensions.detect{|e| path =~ /\.#{e}\Z/ }
18
+ search_files = [File.join(@base,path)]
19
+ # If it ends with a slash or does not contain a . and it's not a directory
20
+ # try to add extenstions to see if that exists.
21
+ elsif (path =~ /\/$/) || (path =~ /^[^.]+$/)
22
+ search_files = extensions.map{|e| File.join(@base,"#{path}.#{e}") }
23
+ # Otherwise don't return anything at all.
24
+ else
25
+ if exact_match
26
+ search_files = [File.join(@base,path)]
27
+ else
28
+ search_files = []
29
+ end
30
+ end
31
+
32
+ if file = search_files.find{|p| File.exist?(p) }
33
+ Pathname.new(file)
34
+ end
35
+ end
36
+
37
+
38
+ # Convert a disk path on file to an url
39
+ def path_to_url(path, relative_to = nil)
40
+
41
+ path = Pathname.new(path).relative_path_from(@base).cleanpath
42
+
43
+ if relative_to
44
+ if relative_to.to_s =~ /\A\//
45
+ relative_to = Pathname.new(File.dirname(relative_to.to_s)).relative_path_from(@base).cleanpath
46
+ else
47
+ relative_to = Pathname.new(File.dirname(relative_to.to_s))
48
+ end
49
+ path = Pathname.new("/" + path.to_s).relative_path_from(Pathname.new("/" + relative_to.to_s))
50
+ path.to_s
51
+ else
52
+ "/" + path.to_s
53
+ end
54
+
55
+ end
56
+
57
+ def url_to_relative_url(url, relative_to_path)
58
+ # Skip if the url doesn't start with a / (but not with //)
59
+ return false unless url =~ /\A\/[^\/]/
60
+
61
+ path, qs, anch = strip_query_string_and_anchor(url)
62
+
63
+ # Get disk path
64
+ if true_path = self.url_to_path(path, true)
65
+ path = self.path_to_url(true_path, relative_to_path)
66
+ path += qs if qs
67
+ path += anch if anch
68
+ path
69
+ else
70
+ false
71
+ end
72
+ end
73
+
74
+ def strip_query_string_and_anchor(url)
75
+ url = url.dup
76
+
77
+ # Strip off anchors
78
+ anchor = nil
79
+ url.gsub!(/(#.+)\Z/) do |r|
80
+ anchor = r
81
+ ""
82
+ end
83
+
84
+ # Strip off query strings
85
+ query = nil
86
+ url.gsub!(/(\?.+)\Z/) do |r|
87
+ query = r
88
+ ""
89
+ end
90
+
91
+ [url, query, anchor]
92
+ end
93
+
94
+ end
95
+ end
@@ -65,7 +65,7 @@ module HtmlMockup
65
65
  return @app if @app
66
66
 
67
67
  @stack.use Rack::HtmlValidator if self.options[:validate]
68
- @stack.run Rack::HtmlMockup.new(self.project.html_path, self.project.partial_path)
68
+ @stack.run Rack::HtmlMockup.new(self.project)
69
69
 
70
70
  @app = @stack
71
71
  end
@@ -2,6 +2,7 @@ require 'pathname'
2
2
  require 'strscan'
3
3
  require 'erb'
4
4
  require 'cgi'
5
+ require 'tilt'
5
6
 
6
7
  module HtmlMockup
7
8
 
@@ -10,7 +11,7 @@ module HtmlMockup
10
11
  class Template
11
12
 
12
13
  class << self
13
- def open(filename,options={})
14
+ def open(filename, options={})
14
15
  raise "Unknown file #{filename}" unless File.exist?(filename)
15
16
  self.new(File.read(filename),options.update(:target_file => filename))
16
17
  end
@@ -39,18 +40,17 @@ module HtmlMockup
39
40
 
40
41
  # Create a new HtmlMockupTemplate
41
42
  #
42
- # ==== Parameters
43
- # template<String>:: The template to parse
44
- # options<Hash>:: See options
43
+ # @param [String] source The template to parse
44
+ # @param [Hash] options See options
45
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
46
+ # @option options [String] partial_path Path where the partials reside (default: $0/../../partials)
47
+ def initialize(source, options={})
48
+ defaults = {
49
+ :partial_path => File.dirname(__FILE__) + "/../../partials/"
50
+ }
51
+ @source = source
52
+ @template = Tilt::ERBTemplate.new{ @source }
52
53
  @options = defaults.update(options)
53
- @scanner = StringScanner.new(@template)
54
54
  raise "Partial path '#{self.options[:partial_path]}' not found" unless File.exist?(self.options[:partial_path])
55
55
  end
56
56
 
@@ -65,6 +65,7 @@ module HtmlMockup
65
65
  # String:: The rendered template
66
66
  #--
67
67
  def render(env={})
68
+ @scanner = StringScanner.new(@template.render(Object.new, :env => env))
68
69
  out = ""
69
70
  while (partial = self.parse_partial_tag!) do
70
71
  tag,params,scanned = partial
@@ -73,7 +74,7 @@ module HtmlMockup
73
74
 
74
75
  # scan until end of tag
75
76
  current_content = self.scanner.scan_until(/<!-- \[STOP:#{tag}\] -->/)
76
- out << (render_partial(tag, params) || current_content)
77
+ out << (render_partial(tag, params, env) || current_content)
77
78
  end
78
79
  out << scanner.rest
79
80
  end
@@ -115,24 +116,18 @@ module HtmlMockup
115
116
  unless self.available_partials[tag]
116
117
  raise MissingPartial.new("Could not find partial '#{tag}' in partial path '#{@options[:partial_path]}'")
117
118
  end
118
- template = ERB.new(self.available_partials[tag])
119
- context = TemplateContext.new(params, env)
120
- "\n" + template.result(context.get_binding).rstrip + "\n<!-- [STOP:#{tag}] -->"
119
+ template = Tilt::ERBTemplate.new{ self.available_partials[tag] }
120
+ context = TemplateContext.new(params)
121
+ "\n" + template.render(context, :env => env).rstrip + "\n<!-- [STOP:#{tag}] -->"
121
122
  end
122
123
 
123
124
  class TemplateContext
124
125
  # Params will be set as instance variables
125
- def initialize(params, env = {})
126
+ def initialize(params)
126
127
  params.each do |k,v|
127
128
  self.instance_variable_set("@#{k}",v)
128
129
  end
129
-
130
- @_env = env;
131
- end
132
-
133
- def env; @_env; end
134
-
135
- def get_binding; binding(); end
130
+ end
136
131
  end
137
132
 
138
133
  end
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.6.5
4
+ version: 0.7.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,11 +10,11 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2012-12-10 00:00:00.000000000 Z
13
+ date: 2013-01-22 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: thor
17
- requirement: &70323203509020 !ruby/object:Gem::Requirement
17
+ requirement: &70345877984660 !ruby/object:Gem::Requirement
18
18
  none: false
19
19
  requirements:
20
20
  - - ~>
@@ -22,10 +22,10 @@ dependencies:
22
22
  version: 0.16.0
23
23
  type: :runtime
24
24
  prerelease: false
25
- version_requirements: *70323203509020
25
+ version_requirements: *70345877984660
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: rack
28
- requirement: &70323203508540 !ruby/object:Gem::Requirement
28
+ requirement: &70345877984180 !ruby/object:Gem::Requirement
29
29
  none: false
30
30
  requirements:
31
31
  - - ! '>='
@@ -33,10 +33,10 @@ dependencies:
33
33
  version: 1.0.0
34
34
  type: :runtime
35
35
  prerelease: false
36
- version_requirements: *70323203508540
36
+ version_requirements: *70345877984180
37
37
  - !ruby/object:Gem::Dependency
38
38
  name: tilt
39
- requirement: &70323202817780 !ruby/object:Gem::Requirement
39
+ requirement: &70345877983700 !ruby/object:Gem::Requirement
40
40
  none: false
41
41
  requirements:
42
42
  - - ! '>='
@@ -44,10 +44,10 @@ dependencies:
44
44
  version: '0'
45
45
  type: :runtime
46
46
  prerelease: false
47
- version_requirements: *70323202817780
47
+ version_requirements: *70345877983700
48
48
  - !ruby/object:Gem::Dependency
49
49
  name: hpricot
50
- requirement: &70323202816620 !ruby/object:Gem::Requirement
50
+ requirement: &70345877983200 !ruby/object:Gem::Requirement
51
51
  none: false
52
52
  requirements:
53
53
  - - ! '>='
@@ -55,7 +55,7 @@ dependencies:
55
55
  version: 0.6.4
56
56
  type: :runtime
57
57
  prerelease: false
58
- version_requirements: *70323202816620
58
+ version_requirements: *70345877983200
59
59
  description:
60
60
  email:
61
61
  - info@digitpaint.nl
@@ -101,6 +101,7 @@ files:
101
101
  - lib/html_mockup/release/processors/yuicompressor.rb
102
102
  - lib/html_mockup/release/scm.rb
103
103
  - lib/html_mockup/release/scm/git.rb
104
+ - lib/html_mockup/resolver.rb
104
105
  - lib/html_mockup/server.rb
105
106
  - lib/html_mockup/template.rb
106
107
  - lib/html_mockup/w3c_validator.rb