phrender 0.0.1 → 0.0.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 092133a20cb9d29d3b2a8867224a38851c3dd891
4
- data.tar.gz: 0a2f321d07614c3e4e744419c1df287d93588772
3
+ metadata.gz: ed3ad1d4b44735e82d185bca486adb853fb15fba
4
+ data.tar.gz: 1f37c26795b0cacf96926f1a3ebae75f41b15f4b
5
5
  SHA512:
6
- metadata.gz: d4d79647ef74036f80da6c17ea500fea90893da54989e90146947180a3f2a40231a0c38e4b75c6160f8841ae38d9ee714cc8feea1f138b3ac1c89225e5b7154e
7
- data.tar.gz: 33e1fa532034a483a3a7e3342c41a66be0b12008be3be5a7fba43e0e4a8fb7002d0072f99b664812bb1b16f81e9e949db4f83ddef99744a1de5341c24419025d
6
+ metadata.gz: 9b1dbdae233a0fb2754378696a7757beee1c2ee197cc5aa5a0dac36be76be5b867d9649688c24c23f84b80dbf9a1ea269dc7b113085c1b0fd09459721c65b7ee
7
+ data.tar.gz: 42bbbaac4dd4aedae6504f5c972b02794dab825a368e00ec8b88accb65a6cc667dbb87ed2ac29ca9fcbde96c341d34a16ad0b96f9f71602272695ba5861da262
data/README.md CHANGED
@@ -22,8 +22,8 @@ Then install PhantomJS:
22
22
 
23
23
  ## Usage
24
24
 
25
- *NOTE*: Ember users, there is a driver for ember. See the [Ember Driver](#Ember
26
- Driver) section.
25
+ *NOTE*: Ember users, there is a driver for ember. See the [Ember Driver](#ember-driver)
26
+ section.
27
27
 
28
28
  ### For completely static javascript sites:
29
29
 
@@ -32,23 +32,33 @@ In your rackup file:
32
32
  ```ruby
33
33
  require 'phrender'
34
34
 
35
- # Available options are timeout, which gets passed on to PhantomJS. The asset
36
- # root should reflect where your app is stored, as well as all images, fonts,
37
- # css, and other assets.
38
- phrender = Phrender::RackStatic.new("asset_root", options)
35
+ # The asset root should reflect where your app is stored, as well as all images,
36
+ # fonts, css, and other static files.
37
+ asset_root = "./"
39
38
 
40
39
  # The index file should link to no javascript on its own, or include any script
41
40
  # tags.
42
- phrender.index_file 'phrender.html'
41
+ index_file = 'phrender.html'
43
42
 
44
43
  # This is the main application. It may or may not also start up the app.
45
- phrender.add_javascript_file '/assets/application.js'
44
+ javascript_files = [ '/assets/application.js' ]
46
45
 
47
46
  # This is just raw javascript. Typically the app boot code.
48
- phrender.add_javascript "MyApp.boot()"
47
+ javascript = [ "MyApp.boot()" ]
48
+
49
+ # Javascript files and raw javascript get concatenated. Files first, then raw
50
+ # code in array order. This code is then run against the index file using
51
+ # PhantomJS
49
52
 
50
53
  # Rackup!
51
- run phrender.rack_app
54
+ run Phrender::RackStatic.new({
55
+ :asset_root => asset_root,
56
+ :index_file => index_file,
57
+ :javascript_files => javascript_files,
58
+ :javascript => javascript
59
+ })
60
+ # Additionally, you map pass the option :timeout, which gets passed on to
61
+ # PhantomJS.
52
62
  ```
53
63
 
54
64
  ### For partially dynamic javascript sites:
@@ -63,23 +73,27 @@ In your rackup file:
63
73
  require 'phrender'
64
74
  require 'my_rack_app'
65
75
 
66
- # This is what you provide
67
- app = MyRackApp.new
68
-
69
- # Available options are timeout and ssl, if, for some reason, your rack app is
76
+ # These options are the same as above, but instead of referencing actual files,
77
+ # the paths are the request paths to send to the upstream application server.
78
+ index_file = 'phrender.html'
79
+ javascript_files = [ '/assets/application.js' ]
80
+ javascript = [ "MyApp.boot()" ]
81
+
82
+ use Phrender::RackMiddleware, {
83
+ :index_file => index_file,
84
+ :javascript_files => javascript_files,
85
+ :javascript => javascript
86
+ }
87
+ # Additional options are timeout and ssl, if, for some reason, your rack app is
70
88
  # serving up SSL encrypted pages. Run `phantomjs --help` to see available
71
89
  # options, or use something falsey to disable. Both options are passed to
72
90
  # phantom.
73
- phrender = Phrender::RackMiddleware.new(app, options)
74
91
 
75
- # These options are the same as above, but instead of referencing actual files,
76
- # the paths are the request paths to send to the upstream application server.
77
- phrender.index_file 'phrender.html'
78
- phrender.add_javascript_file '/assets/application.js'
79
- phrender.add_javascript "MyApp.boot()"
92
+ # Include other middlewarn
93
+ use Rack::Static, :urls => "/assets", :root => "./assets"
80
94
 
81
95
  # Rackup!
82
- run phrender.rack_app
96
+ run MyRackApp.new
83
97
  ```
84
98
 
85
99
  ## Signalling Render Completion
@@ -1,4 +1,4 @@
1
1
  class Phrender
2
2
  EMBER_DRIVER = File.read(
3
- File.expand_path('../phrender/support/ember_driver.js', __FILE__))
3
+ File.expand_path('../support/ember_driver.js', __FILE__))
4
4
  end
@@ -3,6 +3,7 @@ require 'phrender/phantom_js_session'
3
3
 
4
4
  require 'open3'
5
5
  require 'multi_json'
6
+ require 'tempfile'
6
7
 
7
8
  class Phrender::PhantomJSEngine
8
9
 
@@ -28,8 +29,17 @@ class Phrender::PhantomJSEngine
28
29
  end
29
30
 
30
31
  def render(html, javascript, url = nil)
31
- command = app_cmd(html, javascript, url)
32
- session = Phrender::PhantomJSSession.new command, @timeout
32
+ javascript_file = make_temp_file(javascript, 'file.js')
33
+ html_file = make_temp_file(html, 'file.html')
34
+ program_options = { :html => html_file.path,
35
+ :javascript => javascript_file.path,
36
+ :url => url,
37
+ :timeout => @timeout * 1000.0 }
38
+
39
+ session = Phrender::PhantomJSSession.new @boot_cmd.join(' '), @timeout
40
+
41
+ session.stdin.puts MultiJson.dump(program_options)
42
+ session.stdin.close
33
43
 
34
44
  begin
35
45
  sleep @poll_interval
@@ -39,6 +49,10 @@ class Phrender::PhantomJSEngine
39
49
  # Clean up phantom
40
50
  session.shutdown
41
51
 
52
+ # Clean up temp files
53
+ javascript_file.unlink
54
+ html_file.unlink
55
+
42
56
  # Feed something out the chain
43
57
  if session.rendered
44
58
  session.page
@@ -51,17 +65,15 @@ class Phrender::PhantomJSEngine
51
65
  end
52
66
  end
53
67
 
54
- def app_cmd(html, javascript, url)
55
- program_options = { :html => html,
56
- :javascript => javascript,
57
- :url => url,
58
- :timeout => @timeout }
59
- encoded_options = MultiJson.dump(MultiJson.dump(program_options))
60
- "%s %s" % [ @boot_cmd.join(' '), encoded_options ]
61
- end
62
-
63
68
  protected
64
69
 
70
+ def make_temp_file(data, name)
71
+ file = Tempfile.new(name)
72
+ file.write(data)
73
+ file.close
74
+ file
75
+ end
76
+
65
77
  def parse_output(session)
66
78
  output = session.stdout.gets
67
79
  begin
@@ -18,9 +18,12 @@ class Phrender::PhantomJSSession
18
18
  end
19
19
 
20
20
  def shutdown
21
- @stdin.close
22
- @stdout.close
23
- @stderr.close
21
+ [ @stdin, @stdout, @stderr ].each do |pipe|
22
+ begin
23
+ pipe.close
24
+ rescue IOError
25
+ end
26
+ end
24
27
  begin
25
28
  Process.kill("TERM", @wait_thr.pid)
26
29
  rescue Errno::ESRCH
@@ -1,41 +1,49 @@
1
1
  require 'phrender/phantom_js_engine'
2
- require 'phrender/rack_base'
3
2
 
4
3
  require 'rack'
5
4
 
6
- class Phrender::RackMiddleware < Phrender::RackBase
7
- def initialize(backend, opts = {})
5
+ class Phrender::RackMiddleware
6
+ def initialize(app, opts = {})
7
+ @app = app
8
+ @index_file = opts[:index_file]
9
+ @javascript_paths = opts[:javascript_files]
10
+ @raw_javascript = opts[:javascript].join(';')
8
11
  @phantom = Phrender::PhantomJSEngine.new(opts)
9
- @backend = backend
10
- super
11
12
  end
12
13
 
13
- def rack_app
14
- backend = @backend
15
- @app ||= Rack::Builder.new do
16
- use Proxy
17
- run backend
14
+ def call(env)
15
+ status, headers, body = @app.call(env)
16
+ if (status == 404 || headers['Content-Type'] == 'text/html')
17
+ if (env['HTTP_USER_AGENT'].match(/PhantomJS/))
18
+ [ 500, { 'Content-Type' => 'text/html' }, [
19
+ 'Server Error: HTML file contains recursive lookup' ] ]
20
+ else
21
+ body = render(env['REQUEST_URI'])
22
+ [ 200, { 'Content-Type' => 'text/html' }, [ body ] ]
23
+ end
24
+ else
25
+ [ status, headers, body ]
18
26
  end
19
27
  end
20
28
 
21
- def render(path, app)
22
- program = load_js(app)
23
- html = load_html(app)
24
- @phantom.render(html, program)
25
- end
26
-
27
29
  protected
28
30
 
29
- def load_html(app)
31
+ def render(request_uri)
32
+ program = load_js
33
+ html = load_html
34
+ @phantom.render(html, program, request_uri)
35
+ end
36
+
37
+ def load_html
30
38
  req = Rack::MockRequest.env_for('',
31
39
  'PATH_INFO' => @index_file,
32
40
  'REQUEST_METHOD' => 'GET'
33
41
  )
34
- status, headers, body = app.call(req)
35
- body
42
+ status, headers, body = @app.call(req)
43
+ parse_body body
36
44
  end
37
45
 
38
- def load_js(app)
46
+ def load_js
39
47
  js_from_files = @javascript_paths.map do |path|
40
48
  if path == :ember_driver
41
49
  Phrender::EMBER_DRIVER
@@ -44,12 +52,22 @@ class Phrender::RackMiddleware < Phrender::RackBase
44
52
  'PATH_INFO' => path,
45
53
  'REQUEST_METHOD' => 'GET'
46
54
  )
47
- status, headers, body = app.call(req)
48
- body
55
+ status, headers, body = @app.call(req)
56
+ parse_body body
49
57
  end
50
58
  end.join(';')
51
59
  program = js_from_files + @raw_javascript
52
- program
60
+ program.to_s
61
+ end
62
+
63
+ def parse_body(body)
64
+ if body.respond_to? :each
65
+ data = ''
66
+ body.each{ |part| data << part }
67
+ data
68
+ else
69
+ body.to_s
70
+ end
53
71
  end
54
72
 
55
73
  end
@@ -1,45 +1,12 @@
1
1
  require 'phrender/phantom_js_engine'
2
- require 'phrender/rack_base'
2
+ require 'phrender/rack_middleware'
3
3
 
4
4
  require 'rack'
5
5
 
6
- class Phrender::RackStatic < Phrender::RackBase
7
- def initialize(root_directory, opts = {})
8
- @phantom = Phrender::PhantomJSEngine.new(opts)
9
- @root_directory = root_directory
10
- super
6
+ class Phrender::RackStatic < Phrender::RackMiddleware
7
+ def initialize(opts = {})
8
+ asset_root = opts.delete :asset_root
9
+ app = Rack::File.new(asset_root)
10
+ super(app, opts)
11
11
  end
12
-
13
- def rack_app
14
- static_directory = @root_directory
15
- @app ||= Rack::Builder.new do
16
- use Proxy
17
- run Rack::File.new(static_directory)
18
- end
19
- end
20
-
21
- def render(path, app)
22
- program = load_js(app)
23
- html = load_html(app)
24
- @phantom.render(html, program)
25
- end
26
-
27
- protected
28
-
29
- def load_html(app)
30
- File.read File.join(@root_directory, @index_file)
31
- end
32
-
33
- def load_js(app)
34
- js_from_files = @javascript_paths.map do |path|
35
- if path == :ember_driver
36
- Phrender::EMBER_DRIVER
37
- else
38
- File.read File.join(@root_directory, path)
39
- end
40
- end.join(';')
41
- program = js_from_files + @raw_javascript
42
- program
43
- end
44
-
45
12
  end
@@ -13,4 +13,3 @@ Ember.Route = Ember.Route.extend({
13
13
  this._super.apply(this, arguments);
14
14
  }
15
15
  });
16
-
@@ -6,13 +6,13 @@ var system = require('system'),
6
6
  var stdout = system.stdout;
7
7
 
8
8
  // global opts
9
- var options = JSON.parse(system.args[system.args.length - 1]),
9
+ var options = JSON.parse(fs.read("/dev/stdin")),
10
10
  globals = {
11
11
  "page": null,
12
12
  "timer": null,
13
13
  "expired": false,
14
14
  "rendered": false,
15
- "html": options.html
15
+ "html": fs.read(options.html)
16
16
  };
17
17
 
18
18
  // functions
@@ -61,8 +61,9 @@ printPage = function(url) {
61
61
  // Log javascript console messages
62
62
  globals.page.onConsoleMessage = function(msg) {
63
63
  if (msg.trim() === "-- PHRENDER COMPLETE --"){
64
+ logMessage('phrender complete');
64
65
  globals.rendered = true;
65
- } else {
66
+ } else if (!msg.match(/^\[✓\].+/)) {
66
67
  logMessage(msg);
67
68
  }
68
69
  };
@@ -70,9 +71,7 @@ printPage = function(url) {
70
71
  // capture errors
71
72
  globals.page.onError = logError;
72
73
 
73
- globals.page.evaluate(function(code) {
74
- eval(code);
75
- }, options.javascript);
74
+ globals.page.injectJs(options.javascript);
76
75
 
77
76
  // Catch something
78
77
  globals.timer = setTimeout(writeHtml, options.timeout);
@@ -1,3 +1,3 @@
1
1
  class Phrender
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
data/lib/phrender.rb CHANGED
@@ -1,8 +1,8 @@
1
1
  require "phrender/version"
2
2
  require "phrender/logger"
3
+ require "phrender/ember_driver"
3
4
  require "phrender/phantom_js_engine"
4
5
  require "phrender/phantom_js_session"
5
- require "phrender/rack_base"
6
6
  require "phrender/rack_middleware"
7
7
  require "phrender/rack_static"
8
8
 
@@ -14,16 +14,6 @@ describe 'Phrender::PhantomJSEngine' do
14
14
  File.read(File.expand_path('../phantom_js_engine/app.js', __FILE__))
15
15
  }
16
16
 
17
- it 'generates a startup command with escaped json' do
18
- command = phantom.app_cmd(index, app, 'http://localhost')
19
- expect(command).to match(
20
- /phantomjs (.+?)phrender\/lib\/phrender\/support\/phantom_bridge.js/
21
- )
22
- expect(command).to include("--ignore-ssl-errors=true")
23
- expect(command).to include("<html>")
24
- expect(command).to include("use strict")
25
- end
26
-
27
17
  it 'renders a simple page' do
28
18
  whitespace_regex = /(\n|^ +)/
29
19
  html = <<-HTML.strip_heredoc.gsub(whitespace_regex, '')
@@ -10,11 +10,19 @@ describe 'Phrender::RackMiddleware' do
10
10
  b
11
11
  }
12
12
  let(:app) {
13
- p = Phrender::RackMiddleware.new(backend)
14
- p.index_file = 'phrender.html'
15
- p.add_javascript_file 'app.js'
16
- p.add_javascript 'App.run'
17
- p.rack_app
13
+ _backend = backend # Needed because builder changes the block's context
14
+ Rack::Builder.new do
15
+ use Phrender::RackMiddleware, {
16
+ :index_file => 'phrender.html',
17
+ :javascript_files => [
18
+ 'app.js'
19
+ ],
20
+ :javascript => [
21
+ "App.run()"
22
+ ]
23
+ }
24
+ run _backend
25
+ end
18
26
  }
19
27
 
20
28
  it 'runs the app contained in the referenced assets' do
@@ -4,11 +4,16 @@ require 'phrender/rack_static'
4
4
  describe 'Phrender::RackStatic' do
5
5
  let(:root) { File.expand_path '../rack_static', __FILE__ }
6
6
  let(:app) {
7
- p = Phrender::RackStatic.new(root)
8
- p.index_file = 'phrender.html'
9
- p.add_javascript_file 'app.js'
10
- p.add_javascript 'App.run'
11
- p.rack_app
7
+ Phrender::RackStatic.new({
8
+ :asset_root => root,
9
+ :index_file => 'phrender.html',
10
+ :javascript_files => [
11
+ 'app.js'
12
+ ],
13
+ :javascript => [
14
+ "App.run()"
15
+ ]
16
+ })
12
17
  }
13
18
 
14
19
  it 'runs the app contained in the referenced assets' do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: phrender
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - M Smart, theScore Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-07-23 00:00:00.000000000 Z
11
+ date: 2014-07-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -153,7 +153,6 @@ files:
153
153
  - lib/phrender/logger.rb
154
154
  - lib/phrender/phantom_js_engine.rb
155
155
  - lib/phrender/phantom_js_session.rb
156
- - lib/phrender/rack_base.rb
157
156
  - lib/phrender/rack_middleware.rb
158
157
  - lib/phrender/rack_static.rb
159
158
  - lib/phrender/support/ember_driver.js
@@ -1,50 +0,0 @@
1
- class Phrender::RackBase
2
- class Proxy
3
- class << self
4
- attr_accessor :host
5
- end
6
-
7
- def initialize(app)
8
- @app = app
9
- end
10
-
11
- def call(env)
12
- self.class.host.call(env, @app)
13
- end
14
- end
15
-
16
- attr_accessor :index_file
17
-
18
- def initialize(*args)
19
- @javascript_paths = []
20
- @raw_javascript = ''
21
- Proxy.host = self
22
- end
23
-
24
- def rack_app
25
- raise NotImplementedError
26
- end
27
-
28
- def render(path, app)
29
- raise NotImplementedError
30
- end
31
-
32
- def call(env, app)
33
- status, headers, body = app.call(env)
34
- if status == 404
35
- body = render(env['PATH_INFO'], app)
36
- [ 200, { 'Content-Type' => 'text/html' }, body ]
37
- else
38
- [ status, headers, body ]
39
- end
40
- end
41
-
42
- def add_javascript_file(path)
43
- @javascript_paths.push path
44
- end
45
-
46
- def add_javascript(code)
47
- @raw_javascript << ';' + code
48
- end
49
-
50
- end