Skip to content

Commit 4a4ac85

Browse files
committed
rough in support for vue
1 parent ab205b8 commit 4a4ac85

File tree

9 files changed

+107
-18
lines changed

9 files changed

+107
-18
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ demo/assets
55
*.gemspec
66
Gemfile.lock
77
demo/calendar/public/assets
8+
node_modules

Rakefile

+14
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,20 @@ task :gemspec do
6969
File.open(file, "w") {|f| f << spec.to_ruby }
7070
end
7171

72+
namespace :vendor do
73+
task :vue do
74+
# [sudo] npm install -g browserify
75+
# [sudo] npm install -g uglify-es
76+
sh 'npm install'
77+
sh 'curl -s -S https://vuejs.org/js/vue.min.js > ' +
78+
'lib/wunderbar/vendor/vue.min.js'
79+
sh 'browserify -r vue -r ./data/vue-render.js:vue-server | uglifyjs >' +
80+
'lib/wunderbar/vendor/vue-server.min.js'
81+
sh %{echo "Vue=require('vue');VueServer=require('vue-server');" >> \
82+
lib/wunderbar/vendor/vue-server.min.js}
83+
end
84+
end
85+
7286
# If you don't want to generate the .gemspec file, just remove this line. Reasons
7387
# why you might want to generate a gemspec:
7488
# - using bundler with a git source

data/vue-render.js

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
const Vue = require('vue');
2+
3+
module.exports = {
4+
renderToString: function(app) {
5+
const renderer = require('vue-server-renderer').createRenderer();
6+
7+
renderer.renderToString(app, (err, html) => {
8+
if (err) {
9+
console.log('<pre>' + err.stack.replace('&', '&amp;').
10+
replace('<', '&lt;').replace('>', '&gt;') + '</pre>')
11+
} else {
12+
console.log(html)
13+
}
14+
})
15+
}
16+
}
17+
18+

lib/wunderbar/react.rb

+15-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ def self.server(common)
1616
"ReactDOMServer.renderToString(#{common})"
1717
end
1818

19-
def self.client(common, element)
19+
def self.client(common, element, target)
2020
"ReactDOM.render(#{common}, #{element})"
2121
end
2222

@@ -29,3 +29,17 @@ def self.eval(scripts, server)
2929
"</pre>"
3030
end
3131
end
32+
33+
# Monkeypatch to address https://github.com/sstephenson/execjs/pull/180
34+
require 'execjs'
35+
class ExecJS::ExternalRuntime::Context
36+
alias_method :w_write_to_tempfile, :write_to_tempfile
37+
def write_to_tempfile(*args)
38+
tmpfile = w_write_to_tempfile(*args).path.untaint
39+
tmpfile = Struct.new(:path, :to_str).new(tmpfile, tmpfile)
40+
def tmpfile.unlink
41+
File.unlink path
42+
end
43+
tmpfile
44+
end
45+
end

lib/wunderbar/render.rb

+4-17
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,10 @@ def render(container, &block)
6363
end
6464

6565
# build client and server scripts
66-
common = Ruby2JS.convert(block,
67-
Wunderbar::Render::RUBY2JS_OPTIONS.merge(scope: @_scope))
66+
options = Wunderbar::Render::RUBY2JS_OPTIONS.merge(scope: @_scope)
67+
common = Ruby2JS.convert(block, options)
6868
server = Wunderbar::Render.server(common)
69-
client = Wunderbar::Render.client(common, element)
69+
client = Wunderbar::Render.client(common, element, target)
7070

7171
# extract content of scripts
7272
scripts.map! do |script|
@@ -116,6 +116,7 @@ def render(container, &block)
116116
# concatenate and execute scripts on server
117117
scripts.unshift *setup.uniq
118118
html = Wunderbar::Render.eval(scripts, server)
119+
html.untaint
119120

120121
# insert results into target
121122
nodes = builder._ { html }
@@ -177,17 +178,3 @@ def sourcemap_etag
177178
sourcemap[:sources].map! {|source| source.sub base, ''}
178179
JSON.pretty_generate sourcemap
179180
end
180-
181-
# Monkeypatch to address https://github.com/sstephenson/execjs/pull/180
182-
require 'execjs'
183-
class ExecJS::ExternalRuntime::Context
184-
alias_method :w_write_to_tempfile, :write_to_tempfile
185-
def write_to_tempfile(*args)
186-
tmpfile = w_write_to_tempfile(*args).path.untaint
187-
tmpfile = Struct.new(:path, :to_str).new(tmpfile, tmpfile)
188-
def tmpfile.unlink
189-
File.unlink path
190-
end
191-
tmpfile
192-
end
193-
end

lib/wunderbar/vendor/vue-server.min.js

+2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/wunderbar/vendor/vue.min.js

+6
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/wunderbar/vue.rb

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
require 'wunderbar/render'
2+
require 'ruby2js/filter/vue'
3+
4+
vue = File.expand_path('../vendor/vue.min.js', __FILE__)
5+
Wunderbar::Asset.script name: 'vue.min.js', file: vue, render: true,
6+
server: File.expand_path('../vendor/vue-server.min.js', __FILE__)
7+
8+
class Wunderbar::Render
9+
RUBY2JS_OPTIONS = {vue_h: '$h'}
10+
11+
def self.server(common)
12+
"VueServer.renderToString(new Vue({render: function($h) {return #{common}}}))"
13+
end
14+
15+
def self.client(common, element, target)
16+
wrap = "$h(#{target.name.inspect}, " +
17+
"{attrs: {#{target.attrs.map {|name, value|
18+
"#{name}: #{value.inspect}"}.join(' ')}}}, [#{common}])"
19+
"new Vue({el: #{element}, render: function($h) {return #{wrap}}})"
20+
end
21+
22+
def self.eval(scripts, server)
23+
output, status = Open3.capture3 'nodejs',
24+
stdin_data: scripts.compact.join(";\n") + ";\n" + server
25+
output.untaint
26+
rescue => e
27+
Wunderbar.error e
28+
"<pre>" + e.message.gsub('&', '&amp;').gsub('<', '&lt;').gsub('>', '&gt;') +
29+
"</pre>"
30+
end
31+
end

package.json

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"package": "wunderbar-vendor",
3+
"version": "0.0.0",
4+
"license": "MIT",
5+
6+
"repository": {
7+
"type": "git",
8+
"url": "https://github.com/rubys/wunderbar"
9+
},
10+
11+
"devDependencies": {
12+
"vue": ">0",
13+
"vue-server-renderer": ">0"
14+
}
15+
}
16+

0 commit comments

Comments
 (0)