diff --git a/.gitignore b/.gitignore
index 4d0235a..3aaec90 100644
--- a/.gitignore
+++ b/.gitignore
@@ -11,3 +11,4 @@
/docs/*
/spec/
/*.gem
+/guide/
diff --git a/.ruby-version b/.ruby-version
index aedc15b..ec1cf33 100644
--- a/.ruby-version
+++ b/.ruby-version
@@ -1 +1 @@
-2.5.3
+2.6.3
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9ff1f0c..f4dff50 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -13,3 +13,4 @@
- Vue on Rails application template using `rails new app -m https://vueonrails.com/vue -d postgresql`
- Support Babel 7
- Support webpack 4 & Webpacker 4
+- Support pre-processor like pug
diff --git a/README.md b/README.md
index f50f403..62c9619 100644
--- a/README.md
+++ b/README.md
@@ -1,22 +1,24 @@
-# Welcome to Vue on Rails 💎
+
-> Vue for your favorite Rails projects
+> Vue for your favorite Rails products
-The Vue on Rails gem makes it easy to build Vue components on your Rails application.
+The Vue on Rails gem makes it easy to build Vue components on your Rails products.
-It uses Rails 5.x, Vue 2.x, Webpacker 3.x, Ruby 2.x, Node 11.x, Yarn 1.12.x.
+It uses Rails 5.x, Vue 2.x, Webpacker 4.x, Ruby 2.x, Node 11.x, Yarn 1.12.x.
-- 💎 Compatible with Rails 6/5/4 and Webpacker
-- 🌎 Internationalization for component parts
- 🖖 Vue UI ready
-- 🔨 Component generators and scaffolds
-- 📦 Out of the box configuration
-- ✂️ Specific-page Vue
+- 🐶 Support pug
- 🤡 Jest test ready
+- ✂️ Specific-page Vue
+- 👷🏻️ Asset pipeline helpers
- 🎯 Simple state management
+- 📦 Out of the box configuration
+- 🔨 Component generators and scaffolds
+- ❄️ Server Side Rendering using Hypernova
- 🗃 Easily migrate to Vuex state management
-- 👷🏻️ Asset pipeline helpers
-- 🏎 Kickstart with our Vue on Rails application template at https://vueonrails.com/vue
+- 🌎 Internationalization for component parts
+- 💎 Compatible with Rails 6/5/4 and Webpacker
+- 🏎 Kickstart with our application template at https://vueonrails.com/vue
It ships out-of-the-box configuration, component generators and other solutions to make life easy for both Vue and Rails.
diff --git a/app/helpers/syntax_helper.rb b/app/helpers/syntax_helper.rb
index 3fba8de..18ba7ff 100644
--- a/app/helpers/syntax_helper.rb
+++ b/app/helpers/syntax_helper.rb
@@ -25,4 +25,9 @@ def vue_component(identifier, variable=nil)
}; nil
end
end
+
+ #server side rendering via hypernova
+ def render_vue_component(id, data = {})
+ render_react_component(id, data)
+ end
end
diff --git a/lib/generators/options/pug.rb b/lib/generators/options/pug.rb
new file mode 100644
index 0000000..910a57b
--- /dev/null
+++ b/lib/generators/options/pug.rb
@@ -0,0 +1,14 @@
+pugtemplate = <<-eos
+
+ ##{name}
+ p {{ message }}
+
+eos
+
+if options[:seperate] == true
+ gsub_file Rails.root.join("#{PARTS_PATH}/#{name}/#{name}.vue").to_s,
+ /[^\]]*<\/template>/, pugtemplate
+else
+ gsub_file Rails.root.join("#{PARTS_PATH}/#{name}.vue").to_s,
+ /[^\]]*<\/template>/, pugtemplate
+end
diff --git a/lib/generators/options/ssr.rb b/lib/generators/options/ssr.rb
new file mode 100644
index 0000000..90acceb
--- /dev/null
+++ b/lib/generators/options/ssr.rb
@@ -0,0 +1,10 @@
+template "ssr/component.js.erb", "#{SSR_PATH}/#{name}.js"
+
+puts "\nAdd the following line into your ssr.js:
+
+getComponent(name) {
+// Add this!
+if (name === '#{name}.js') {
+ return require('./app/javascript/ssr/#{name}.js')
+}
+"
diff --git a/lib/generators/templates/I18n/cn.yml b/lib/generators/templates/i18n/cn.yml
similarity index 100%
rename from lib/generators/templates/I18n/cn.yml
rename to lib/generators/templates/i18n/cn.yml
diff --git a/lib/generators/templates/I18n/index.js b/lib/generators/templates/i18n/index.js
similarity index 100%
rename from lib/generators/templates/I18n/index.js
rename to lib/generators/templates/i18n/index.js
diff --git a/lib/generators/templates/ssr/component.js.erb b/lib/generators/templates/ssr/component.js.erb
new file mode 100644
index 0000000..607460c
--- /dev/null
+++ b/lib/generators/templates/ssr/component.js.erb
@@ -0,0 +1,11 @@
+// Generated by Vue on Rails https://github.com/vueonrails/vueonrails
+// To embed this component in Rails view, use <%= render_vue_component "component.js" %>
+// To generate this component, run `rails generate vue something --ssr`
+
+console.log("Hello, <%= name %>")
+const Vue = require("vue")
+const renderVue = require("hypernova-vue").renderVue
+const component = Vue.extend({
+ template: 'hello, <%= name %>
'
+})
+module.exports = renderVue("<%= name %>.js", component)
diff --git a/lib/generators/vue/vue_generator.rb b/lib/generators/vue/vue_generator.rb
index 7247ca5..dde7ec7 100644
--- a/lib/generators/vue/vue_generator.rb
+++ b/lib/generators/vue/vue_generator.rb
@@ -4,6 +4,7 @@ class VueGenerator < Rails::Generators::NamedBase
PACKS_PATH = "app/javascript/packs"
PARTS_PATH = "app/javascript/parts"
TESTS_PATH = "app/javascript/tests"
+ SSR_PATH = "app/javascript/ssr"
source_root File.expand_path('../../templates', __FILE__)
@@ -18,8 +19,11 @@ class VueGenerator < Rails::Generators::NamedBase
table: {type: :boolean, default: false},
modal: {type: :boolean, default: false},
click: {type: :boolean, default: false},
+ pug: {type: :boolean, default: false}
}.freeze
+ class_option :ssr, type: :string, default: nil
+
class_option :child, type: :string, default: nil
class_option :parent, type: :string, default: nil
class_option :seperate, type: :boolean, default: false
@@ -32,7 +36,9 @@ class VueGenerator < Rails::Generators::NamedBase
def vue
return if name.empty?
- if options[:child]
+ if options[:ssr]
+ add_ssr_component()
+ elsif options[:child]
adding_nested_component(:child, name, nil, options[:child])
elsif options[:parent]
adding_nested_component(:parent, name, options[:parent], nil)
@@ -95,6 +101,14 @@ def adding_nested_component(example, name, parent, child)
eval erbtemplate
end
+ def add_ssr_component()
+ namespace = OpenStruct.new(SSR_PATH: SSR_PATH)
+ template = File.read(File.expand_path("../options/ssr.rb", __dir__))
+ erbtemplate = ERB.new(template).result(namespace.instance_eval { binding })
+ eval erbtemplate
+
+ end
+
def add_to_component(example, name)
namespace = OpenStruct.new(TESTS_PATH: TESTS_PATH, PARTS_PATH: PARTS_PATH, PACKS_PATH: PACKS_PATH, name: name)
template = File.read(File.expand_path("../options/#{example}.rb", __dir__))
diff --git a/lib/installs/i18n.rb b/lib/installs/i18n.rb
new file mode 100644
index 0000000..546606c
--- /dev/null
+++ b/lib/installs/i18n.rb
@@ -0,0 +1,3 @@
+# Insert locale.js as a default i18n and add second locale cn.yml
+copy_file "#{__dir__}/../generators/templates/i18n/index.js", Rails.root.join("app/javascript/locales/locale.js").to_s
+copy_file "#{__dir__}/../generators/templates/i18n/cn.yml", Rails.root.join("config/locales/cn.yml").to_s
diff --git a/lib/installs/loaders/pug.js b/lib/installs/loaders/pug.js
new file mode 100644
index 0000000..1a145e9
--- /dev/null
+++ b/lib/installs/loaders/pug.js
@@ -0,0 +1,15 @@
+// Generated by Vue on Rails https://github.com/vueonrails/vueonrails
+// This is required to support Pug in Vue on Rails.
+
+module.exports = {
+ test: /\.pug$/,
+ oneOf: [
+ {
+ resourceQuery: /^\?vue/,
+ use: ['pug-plain-loader']
+ },
+ {
+ use: ['raw-loader', 'pug-plain-loader']
+ }
+ ]
+}
diff --git a/lib/installs/locale.rb b/lib/installs/locale.rb
deleted file mode 100644
index 2ba9e77..0000000
--- a/lib/installs/locale.rb
+++ /dev/null
@@ -1 +0,0 @@
-run "yarn add vue-i18n"
\ No newline at end of file
diff --git a/lib/installs/pug.rb b/lib/installs/pug.rb
new file mode 100644
index 0000000..a72a16e
--- /dev/null
+++ b/lib/installs/pug.rb
@@ -0,0 +1,12 @@
+# install pug dependencies
+run "yarn add pug pug-plain-loader"
+
+# add the pug loader
+copy_file "#{__dir__}/loaders/pug.js", Rails.root.join("config/webpack/loaders/pug.js").to_s
+
+# insert pug into the environment.js
+insert_into_file Rails.root.join("config/webpack/environment.js").to_s,
+"const pug = require('./loaders/pug')\n", after: "require('@rails/webpacker')\n"
+
+insert_into_file Rails.root.join("config/webpack/environment.js").to_s,
+"environment.loaders.prepend('pug', pug)\n", before: "module.exports = environment"
diff --git a/lib/installs/setup.rb b/lib/installs/setup.rb
index 217c6d7..15129ad 100644
--- a/lib/installs/setup.rb
+++ b/lib/installs/setup.rb
@@ -1,3 +1,29 @@
+# Check for the lack of .babelrc or webpacker 4
+def check_version_and_babel
+ #should i check for evidence of webpacker:install?
+ (File.exists?(Rails.root.join(".babelrc")) == true) \
+ || ((Gem.loaded_specs["webpacker"].version >= Gem::Version.new('4.x')) == false)
+end
+
+begin
+ if(check_version_and_babel)
+ say "You are using Vue on Rails #{Vueonrails::VERSION} and it does not support webpacker 4.
+
+ Please use the latest Vue on Rails (1.x) in your Gemfile:
+ gem 'webpacker', '~> 4.x'
+ gem 'vueonrails', '~> 1.x'
+
+ or switch back to webpacker 3:
+ gem 'webpacker', '~> 3.x'
+ gem 'vueonrails', '~> 0.x'", :yellow
+ exit!
+ end
+rescue Errno::ENOENT => e
+ say "You need webpacker 4."
+ exit!
+end
+
+# the start of the setup script
say "Adding vueonrails, internationalization, @vue/test-utils and other Jest devdependencies"
run "yarn add vueonrails vue-i18n @vue/test-utils jest jest-serializer-vue vue-jest babel-jest --dev"
@@ -7,10 +33,17 @@
"const alias = require('./alias/alias')\n", after: "require('@rails/webpacker')\n"
# Add *_pack_tag into application.html.erb This is essential for specific-page vue setup.
-pack_tag = <<-eos
- <%= javascript_pack_tag 'application' %>
- <%= stylesheet_pack_tag 'application' %>
-eos
+if (Gem.loaded_specs["rails"].version >= Gem::Version.new('6.x')) # rails 6 has default javascript_pack_tag
+ pack_tag = <<-eos
+ <%= stylesheet_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
+ eos
+else # non-rails 6
+ pack_tag = <<-eos
+ <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
+ <%= stylesheet_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
+ eos
+end
+
insert_into_file Rails.root.join("app/views/layouts/application.html.erb").to_s,
pack_tag, before: " \n"
@@ -56,19 +89,6 @@
insert_into_file Rails.root.join("package.json").to_s,
scripts, after: "\"private\": true,\n"
-babelrc = <<-eos
- "env": {
- "test": {
- "presets": [
- ["env", { "targets": { "node": "current" }}]
- ]
- }
- },
-eos
-
-insert_into_file Rails.root.join(".babelrc").to_s,
-babelrc, before: " \"presets\": ["
-
# Insert locale.js as a default i18n and add second locale cn.yml
copy_file "#{__dir__}/../generators/templates/i18n/index.js", Rails.root.join("app/javascript/locales/locale.js").to_s
copy_file "#{__dir__}/../generators/templates/i18n/cn.yml", Rails.root.join("config/locales/cn.yml").to_s
diff --git a/lib/installs/specific_page_vue.rb b/lib/installs/spv.rb
similarity index 51%
rename from lib/installs/specific_page_vue.rb
rename to lib/installs/spv.rb
index 9639959..9721903 100644
--- a/lib/installs/specific_page_vue.rb
+++ b/lib/installs/spv.rb
@@ -3,10 +3,17 @@
gsub_file Rails.root.join("app/views/layouts/application.html.erb").to_s,
/<\/body>/, '<% end %>'
-pack_tag = <<-eos
- <%= javascript_pack_tag 'application' %>
- <%= stylesheet_pack_tag 'application' %>
-eos
+if (Gem.loaded_specs["rails"].version >= Gem::Version.new('6.x')) # rails 6 has default javascript_pack_tag
+ pack_tag = <<-eos
+ <%= stylesheet_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
+ eos
+else # non-rails 6
+ pack_tag = <<-eos
+ <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
+ <%= stylesheet_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
+ eos
+end
+
insert_into_file Rails.root.join("app/views/layouts/application.html.erb").to_s,
pack_tag,
@@ -18,4 +25,4 @@
insert_into_file Rails.root.join("app/assets/javascripts/application.js").to_s,
vue_on_rails,
-before: "//= require_tree ."
\ No newline at end of file
+before: "//= require_tree ."
diff --git a/lib/installs/ssr.rb b/lib/installs/ssr.rb
new file mode 100644
index 0000000..c161295
--- /dev/null
+++ b/lib/installs/ssr.rb
@@ -0,0 +1,26 @@
+# Check that webpacker + vueonrails are installed before proceeding
+begin
+ $stdout.puts "Webpacker: #{Webpacker::VERSION}"
+rescue NameError
+ $stdout.puts "Webpacker: Not installed"
+end
+
+# install the dependencies
+gem 'hypernova'
+run "yarn add hypernova hypernova-vue vue-server-renderer"
+
+#insert the application helper and also import
+insert_into_file Rails.root.join("app/controllers/application_controller.rb").to_s,
+"require 'hypernova'\n", before: "class"
+
+insert_into_file Rails.root.join("app/controllers/application_controller.rb").to_s,
+"around_action :hypernova_render_support\n", before: "end"
+
+# copy the configuration file into config/initializer
+copy_file "#{__dir__}/ssr/hypernova.rb", Rails.root.join("config/initializers/hypernova.rb").to_s
+
+# copy hypernova.js to the project root level
+copy_file "#{__dir__}/ssr/ssr.js", Rails.root.join("ssr.js").to_s
+
+# copy the first component server-rendered into the
+copy_file "#{__dir__}/ssr/component.js", Rails.root.join("app/javascript/ssr/component.js").to_s
diff --git a/lib/installs/ssr/component.js b/lib/installs/ssr/component.js
new file mode 100644
index 0000000..6b7a77f
--- /dev/null
+++ b/lib/installs/ssr/component.js
@@ -0,0 +1,11 @@
+// Generated by Vue on Rails https://github.com/vueonrails/vueonrails
+// To embed this component in Rails view, use <%= render_vue_component "component.js" %>
+// To generate this component, run `rails generate vue something --ssr`
+
+console.log("hello, component")
+const Vue = require("vue")
+const renderVue = require("hypernova-vue").renderVue
+const component = Vue.extend({
+ template: 'hello world
'
+})
+module.exports = renderVue("component.js", component)
diff --git a/lib/installs/ssr/hypernova.rb b/lib/installs/ssr/hypernova.rb
new file mode 100644
index 0000000..b33dc40
--- /dev/null
+++ b/lib/installs/ssr/hypernova.rb
@@ -0,0 +1,9 @@
+require 'hypernova'
+require 'hypernova/plugins/development_mode_plugin'
+
+Hypernova.add_plugin!(DevelopmentModePlugin.new)
+
+Hypernova.configure do |config|
+ config.host = "0.0.0.0"
+ config.port = 7777 # The port where the node service is listening
+end
diff --git a/lib/installs/ssr/ssr.js b/lib/installs/ssr/ssr.js
new file mode 100644
index 0000000..9c3c248
--- /dev/null
+++ b/lib/installs/ssr/ssr.js
@@ -0,0 +1,17 @@
+// Generated by Vue on Rails https://github.com/vueonrails/vueonrails
+// To run this script, simply run `node ssr`
+
+var hypernova = require('hypernova/server');
+
+hypernova({
+ devMode: true,
+ getComponent(name) {
+ // Console.log("The component name is -> " + name)
+ // Make sure you state the corresponding name correctly. In this case, 'component.js'
+ if (name === 'component.js') {
+ return require('./app/javascript/ssr/component.js')
+ }
+ return null;
+ },
+ port: 7777,
+});
diff --git a/lib/installs/store.rb b/lib/installs/store.rb
new file mode 100644
index 0000000..906ad33
--- /dev/null
+++ b/lib/installs/store.rb
@@ -0,0 +1,2 @@
+# Insert store.js as a simple store for components' state
+copy_file "#{__dir__}/../generators/templates/stores/index.js", Rails.root.join("app/javascript/parts/store.js").to_s
diff --git a/lib/installs/test.rb b/lib/installs/test.rb
index 9512c11..adb624a 100644
--- a/lib/installs/test.rb
+++ b/lib/installs/test.rb
@@ -28,16 +28,4 @@
"#{scripts}",
after: "\"private\": true,\n"
-babelrc = <<-eos
- "test": {
- "presets": [
- ["env", { "targets": { "node": "current" }}]
- ]
- },
-eos
-
-insert_into_file Rails.root.join(".babelrc").to_s,
- "#{babelrc}",
- before: " \"presets\": ["
-
-run "yarn add jest-serializer-vue vue-jest babel-jest --no-progress --silent"
\ No newline at end of file
+run "yarn add jest-serializer-vue vue-jest babel-jest --no-progress --silent"
diff --git a/lib/installs/ui.rb b/lib/installs/ui.rb
index 83887b8..42816a6 100644
--- a/lib/installs/ui.rb
+++ b/lib/installs/ui.rb
@@ -1 +1,37 @@
-run "yarn list @vue/cli-service --no-progress --silent"
\ No newline at end of file
+# Jest and scripts configuration. Essential for Jest test and Vue Ui
+scripts = <<-eos
+ "scripts": {
+ "yarn test": "jest",
+ "yarn install": "yarn install --check-files",
+ "rails assets:precompile": "yarn install --check-files; rails assets:precompile",
+ "rails server": "rails server",
+ "webpack-dev-server": "./bin/webpack-dev-server"
+ },
+ "jest": {
+ "moduleFileExtensions": [
+ "js",
+ "vue"
+ ],
+ "moduleNameMapper": {
+ "^@/(.*)$": "/app/javascript/parts/$1"
+ },
+ "transform": {
+ "^.+\\\\\\.js$": "/node_modules/babel-jest",
+ ".*\\\\\\.(vue)$": "/node_modules/vue-jest"
+ },
+ "transformIgnorePatterns": [
+ "node_modules/(?!(vueonrails)/)"
+ ],
+ "testPathIgnorePatterns": [
+ "/config/webpack/"
+ ],
+ "snapshotSerializers": [
+ "/node_modules/jest-serializer-vue"
+ ]
+ },
+eos
+
+insert_into_file Rails.root.join("package.json").to_s,
+scripts, after: "\"private\": true,\n"
+
+puts "Vue UI Ready!"
diff --git a/lib/tasks/translate.rake b/lib/tasks/translate.rake
index f839666..4c6b50c 100644
--- a/lib/tasks/translate.rake
+++ b/lib/tasks/translate.rake
@@ -2,7 +2,7 @@ namespace :vue do
desc "Translate Rails' locale into Vue's locale"
task :translate do
Dir.foreach("config/locales/").each do |locale|
- next if locale == '.' or locale == '..'
+ next if File.extname(locale).strip.downcase != ".yml"
config = YAML.load_file("config/locales/#{locale}")
name = locale.to_s.split('.').first if locale.to_s.split('.') != nil
if name != nil
@@ -16,4 +16,4 @@ namespace :vue do
end
end
end
-end
\ No newline at end of file
+end
diff --git a/lib/tasks/vue.rake b/lib/tasks/vue.rake
index c95b5c0..26f1b46 100644
--- a/lib/tasks/vue.rake
+++ b/lib/tasks/vue.rake
@@ -1,13 +1,15 @@
bin_path = ENV["BUNDLE_BIN"] || "./bin"
TASKS = {
- locale: "install vue-i18n",
+ spv: "Install Specific-page Vue",
+ store: "Install simple state management",
+ i18n: "Install i18n dependencies",
+ ssr: "Install server-side rendering using hypernova",
+ setup: "Setup and install Vue on Rails dependencies",
+ test: "Install Jest tests",
+ ui: "Check if Vue-ui is installed",
+ vuex: "Check if Vuex is installed",
turbolinks: "Check Vue-turbolinks ready",
- setup: "Check Vue on Rails ready",
- test: "Check Jest tests ready",
- vuex: "Check Vuex ready",
- ui: "Check Vue-ui ready",
- specific_page_vue: "Check Specific-page Vue ready?"
}.freeze
namespace :vue do
diff --git a/lib/vueonrails/version.rb b/lib/vueonrails/version.rb
index 7e8f009..b36a3c5 100644
--- a/lib/vueonrails/version.rb
+++ b/lib/vueonrails/version.rb
@@ -1,3 +1,3 @@
module Vueonrails
- VERSION = "0.3.0"
+ VERSION = "1.0.0.beta4"
end
diff --git a/logo.png b/logo.png
new file mode 100644
index 0000000..4062358
Binary files /dev/null and b/logo.png differ