vueck 1.0.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: fb2e9df97919a0cf450ce3c03e19c9361a24d108
4
+ data.tar.gz: 5f3a25d9b685f76611f7e729d2ae280667a4fce1
5
+ SHA512:
6
+ metadata.gz: 5afb7564a4720812a647c4704907da8eb3b9be1c59462b763d3072e7bf40cc0fd7b633db23a0204c3ccb28c6f78a5141b03aadbb2a9deac3c29514e44d934e88
7
+ data.tar.gz: 0b7d32e8dfcbd99128f259ba2d38eabd1dadd2c03e069b14304bcb2fac2d16306b273aa50603e53b6ac19d9c0a24c089788f2c25c8ed483810732e61df287872
data/.bundle/config ADDED
@@ -0,0 +1,2 @@
1
+ ---
2
+ BUNDLE_PATH: "vendor/bundle"
data/.gitignore ADDED
@@ -0,0 +1,3 @@
1
+ vendor
2
+ .sass-cache
3
+ .vueck_cache
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "oga"
4
+ gem "pry"
5
+ gem "tilt"
6
+ gem "slim"
7
+ gem "sass"
8
+ gem "cssminify"
data/Gemfile.lock ADDED
@@ -0,0 +1,45 @@
1
+ GEM
2
+ remote: https://rubygems.org/
3
+ specs:
4
+ ansi (1.5.0)
5
+ ast (2.4.0)
6
+ coderay (1.1.2)
7
+ cssminify (1.0.2)
8
+ ffi (1.9.18)
9
+ method_source (0.9.0)
10
+ oga (2.13)
11
+ ast
12
+ ruby-ll (~> 2.1)
13
+ pry (0.11.3)
14
+ coderay (~> 1.1.0)
15
+ method_source (~> 0.9.0)
16
+ rb-fsevent (0.10.2)
17
+ rb-inotify (0.9.10)
18
+ ffi (>= 0.5.0, < 2)
19
+ ruby-ll (2.1.2)
20
+ ansi
21
+ ast
22
+ sass (3.5.5)
23
+ sass-listen (~> 4.0.0)
24
+ sass-listen (4.0.0)
25
+ rb-fsevent (~> 0.9, >= 0.9.4)
26
+ rb-inotify (~> 0.9, >= 0.9.7)
27
+ slim (3.0.9)
28
+ temple (>= 0.7.6, < 0.9)
29
+ tilt (>= 1.3.3, < 2.1)
30
+ temple (0.8.0)
31
+ tilt (2.0.8)
32
+
33
+ PLATFORMS
34
+ ruby
35
+
36
+ DEPENDENCIES
37
+ cssminify
38
+ oga
39
+ pry
40
+ sass
41
+ slim
42
+ tilt
43
+
44
+ BUNDLED WITH
45
+ 1.16.1
data/README.md ADDED
@@ -0,0 +1,46 @@
1
+ # VueCK
2
+ ### VueJS component compiler middleware for Rack
3
+ ## Introduction
4
+ VueCK makes it easy to integrate VueJS single file components into Rack applications. VueCK offers the following features:
5
+ * Compiles all of your project's components into sinlge Javascript and CSS files
6
+ * Minifies CSS and HTML
7
+ * (Probably) supports any flavor of HTML, Javscript, or CSS that Tilt supports, including Slim, Sass, Less, ERB, etc
8
+ * Caches compiled components for faster requests
9
+ * No server-side Javascript infrastructure required!
10
+ ## Usage
11
+ VueCK is easy to use.
12
+
13
+ Install the gem:
14
+ ```bash
15
+ $ gem install vueck
16
+ ```
17
+ or include it in your Gemfile
18
+ ```ruby
19
+ gem 'vueck'
20
+ ```
21
+ and then install
22
+ ```
23
+ $ bundler install
24
+ ```
25
+ Add VueCK to your `config.ru`
26
+ ```ruby
27
+ require 'vueck'
28
+ use VueCK::Plugin
29
+ ```
30
+ Create a directory in the root of your project called `vue` and place your SFC files (with a `.vue` extension) in that directory.
31
+ Finally, add the `vue.js` and `vue.css` requests into your layout:
32
+ ```html
33
+ script type="text/javascript" src="/vue.js"
34
+ link rel="stylesheet" type='text/css' href="/vue.css"
35
+ ```
36
+ That's it!
37
+ ## Rationale
38
+ VueJS is amazing and Vue single file components (SFCs) increase productivity, make your code easier to mantain, and are generally awesome. However, using SFCs traditionally means bringing some server side Javascript into your environment. This can be both a hassle and a bit silly if you've already got a robust Ruby stack working for you. VueCK lets you take advantage of SFCs without any Javascript dependencies.
39
+ ## Format
40
+ VueCK isn't 100% compatible with official VueJS SFCs. It's a from-the-ground-up reimplementation of the SFC compiler and thus has some differences. These are minor however and you can probably get any SFC you can find working in VueCK just by adding one or two attributes. Here's what you need to know:
41
+ * VueCK SFCs are enclosed in a parent `<component/>` element
42
+ * The `<component/>` element needs to have a `name` attribute. This is the name that will be used for the Javascript object for your component.
43
+ * Styles in VueCK are not scoped. Vue's official compiler achieves the illusion of scoped styles by appending random charecters to class names.
44
+ ## Notes
45
+ * VueCK should support any templating or preprocessing tools Tilt does; that said, I only care about Slim and Sass, so I can't be 100% sure. If anyone is interested in ensuring compatibility with others I would welcome the contribution!
46
+
@@ -0,0 +1,26 @@
1
+ module VueCK
2
+ class BatchRenderer
3
+ def initialize(opts={})
4
+ @path = opts[:path] || DIRS[:components]
5
+ end
6
+
7
+ def render
8
+ out = {components:"",style:""}
9
+ file_iterator do |file|
10
+ component = SFC.new file
11
+ out[:components] += component.render_component
12
+ out[:style] += component.render_style
13
+ end
14
+ out
15
+ end
16
+
17
+ private
18
+
19
+ def file_iterator(&block)
20
+ Dir.glob("#{@path}*.vue") do |item|
21
+ next if item == '.' or item == '..'
22
+ yield item
23
+ end
24
+ end
25
+ end
26
+ end
data/lib/element.rb ADDED
@@ -0,0 +1,32 @@
1
+ module VueCK
2
+ class Element
3
+ def initialize(doc, type)
4
+ @node = doc.css(ELEMENTS[type])
5
+ @type = type
6
+ verify
7
+ end
8
+
9
+ def verify
10
+ return unless REQUIRED[@type]
11
+ raise ComonentRenderError if @node.empty?
12
+ end
13
+
14
+ def lang
15
+ @node.attribute(ATTRIBUTES[:lang]).first.value || LANG_DEFALTS[type]
16
+ end
17
+
18
+ def empty?
19
+ @node.empty?
20
+ end
21
+
22
+ def text
23
+ @node.first.children.text
24
+ end
25
+
26
+ def render
27
+ return text if lang == LANG_DEFALTS[:script]
28
+ raise InvalidTemplateEngine unless Tilt[lang]
29
+ Tilt[lang].new { text }.render
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,53 @@
1
+ module VueCK
2
+ class FileManager
3
+ def initialize(filename)
4
+ @filename = filename
5
+ @js_cache = "#{DIRS[:cache]}#{FILES[:javascript]}"
6
+ @css_cache = "#{DIRS[:cache]}#{FILES[:style]}"
7
+ end
8
+
9
+ def serve
10
+ return render unless cachedir_exists?
11
+ return render unless cachefiles_exist?
12
+ return render unless cachefiles_fresh?
13
+ read_file
14
+ end
15
+
16
+ private
17
+
18
+ def render
19
+ renders = BatchRenderer.new.render
20
+ File.write(@js_cache, renders[:components])
21
+ File.write(@css_cache, renders[:style])
22
+ read_file
23
+ end
24
+
25
+ def read_file
26
+ cache_file = @js_cache if @filename == FILES[:javascript]
27
+ cache_file = @css_cache if @filename == FILES[:style]
28
+ File.read(cache_file)
29
+ end
30
+
31
+ def cachedir_exists?
32
+ return true if File.exists? DIRS[:cache]
33
+ Dir.mkdir DIRS[:cache]
34
+ false
35
+ end
36
+
37
+ def cachefiles_exist?
38
+ return File.exists?(@js_cache) && File.exists?(@css_cache)
39
+ end
40
+
41
+ def cachefiles_fresh?
42
+ cache_mtime = newest_file_in_dir(DIRS[:cache])
43
+ source_mtime = newest_file_in_dir(DIRS[:components])
44
+ return cache_mtime > source_mtime
45
+ end
46
+
47
+ def newest_file_in_dir(path)
48
+ Dir.glob(File.join(path, '*.*')).max { |a,b| File.mtime(a) <=> File.mtime(b) }
49
+ end
50
+
51
+ end
52
+ end
53
+
data/lib/plugin.rb ADDED
@@ -0,0 +1,28 @@
1
+ module VueCK
2
+ class Plugin
3
+ RESPONSE_TYPES = {
4
+ "vue.js" => "application/javascript",
5
+ "vue.css" => "text/css"
6
+ }
7
+
8
+ def initialize(app={})
9
+ @app = app
10
+ end
11
+
12
+ def call(env)
13
+ return unless env["REQUEST_METHOD"] == "GET"
14
+ file = env["PATH_INFO"][1..-1]
15
+ return unless file == FILES[:javascript] || file == FILES[:style]
16
+ vueck = VueCK.new(file)
17
+ content = vueck.serve_file
18
+ response(content, file)
19
+ end
20
+
21
+ def response(content, file)
22
+ ["200", {
23
+ "Content-Type" => RESPONSE_TYPES[file],
24
+ "Content-Length" => content.size.to_s },
25
+ [content]]
26
+ end
27
+ end
28
+ end
data/lib/sfc.rb ADDED
@@ -0,0 +1,40 @@
1
+ module VueCK
2
+ class SFC
3
+ attr_accessor :xml, :script, :style, :template, :name
4
+
5
+ def initialize(component_file)
6
+ @path = component_file
7
+ @xml = component_xml
8
+ @name = @xml.attribute(ATTRIBUTES[:name]).value
9
+ end
10
+
11
+ def render_component
12
+ reduce_whitespace "var #{@name} = Vue.component('#{@name}',{template:'#{render(:template)}', #{render(:script)}});"
13
+ end
14
+
15
+ def render_style
16
+ style = Element.new(@xml, :style)
17
+ return "" if style.empty?
18
+ CSSminify.compress reduce_whitespace(style.render)
19
+ end
20
+
21
+ private
22
+
23
+ def reduce_whitespace(text)
24
+ text.gsub(/\s+/, " ")
25
+ end
26
+
27
+ def load
28
+ Oga.parse_xml File.open @path
29
+ end
30
+
31
+ def component_xml
32
+ load.css(ELEMENTS[:component]).first
33
+ end
34
+
35
+ def render(type)
36
+ Element.new(@xml, type).render
37
+ end
38
+
39
+ end
40
+ end
data/lib/vueck.rb ADDED
@@ -0,0 +1,54 @@
1
+ require 'batchrenderer'
2
+ require 'element'
3
+ require 'filemanager'
4
+ require 'sfc'
5
+ require 'tilt'
6
+ require 'oga'
7
+ require 'cssminify'
8
+ require 'plugin'
9
+
10
+ module VueCK
11
+ FILES = {
12
+ javascript: "vue.js",
13
+ style: "vue.css"
14
+ }
15
+ DIRS = {
16
+ cache: ".vueck_cache/",
17
+ components: "vue/"
18
+ }
19
+ ELEMENTS = {
20
+ component: "component",
21
+ template: "template",
22
+ script: "script",
23
+ style: "style"
24
+ }
25
+ ATTRIBUTES = {
26
+ name: "name",
27
+ lang: "lang"
28
+ }
29
+ LANG_DEFALTS = {
30
+ script: "javascript",
31
+ style: "css",
32
+ template: "html"
33
+ }
34
+ REQUIRED = {
35
+ script: true,
36
+ style: false,
37
+ template: true
38
+ }
39
+
40
+ class InvalidTemplateEngine < StandardError
41
+ end
42
+ class ComonentRenderError < StandardError
43
+ end
44
+
45
+ class VueCK
46
+ def initialize(filename)
47
+ @filename = filename
48
+ return unless FILES[:javascript] || FILES[:style]
49
+ end
50
+ def serve_file
51
+ FileManager.new(@filename).serve
52
+ end
53
+ end
54
+ end
data/test/test.rb ADDED
@@ -0,0 +1,20 @@
1
+ require 'minitest/autorun'
2
+ require 'vueck'
3
+
4
+ class VueCKTest < Minitest::Test
5
+ CSS = ["200", {"Content-Type"=>"text/css", "Content-Length"=>"48"}, [".post{color:red}.post{color:green}h1{color:pink}"]]
6
+ JS = ["200",{"Content-Type"=>"application/javascript", "Content-Length"=>"735"},["var test_component = Vue.component('test_component',{template:'<div class=\"post\"><h1>Adam</h1></div>', props: [\"test\"], data: { adam: true }, methods: { yo: function() { } } });var test_component = Vue.component('test_component',{template:'<div class=\"post\"><h1>Other Guy</h1><h1>Oh hai mark</h1></div>', props: [\"test\"], data: { adam: true, drew: true }, methods: { yo: function() { } } });var test_component = Vue.component('test_component',{template:'<Oh>, Hai Mark!</Oh>', props: [\"test\"], data: { adam: true, drew: true }, methods: { yo: function() { } } });var test_component = Vue.component('test_component',{template:'<Oh>, Hai Mark!</Oh>', props: [\"test\"], data: { adam: true, drew: true }, methods: { yo: function() { } } });"]]
7
+
8
+ def test_render_css
9
+ plugin = VueCK::Plugin.new()
10
+ response = plugin.call({"PATH_INFO"=>"/vue.css", "REQUEST_METHOD"=>"GET"})
11
+ require pry ; binding.pry
12
+ assert response == CSS
13
+ end
14
+
15
+ def test_render_js
16
+ plugin = VueCK::Plugin.new()
17
+ response = plugin.call({"PATH_INFO"=>"/vue.js", "REQUEST_METHOD"=>"GET"})
18
+ assert response == JS
19
+ end
20
+ end
data/test/vue/test.vue ADDED
@@ -0,0 +1,23 @@
1
+ <component name="test_component">
2
+ <template lang="slim">
3
+ .post
4
+ h1 Adam
5
+ </template>
6
+
7
+ <script lang="javascript">
8
+ props: ["test"],
9
+ data: {
10
+ adam: true
11
+ },
12
+ methods: {
13
+ yo: function() {
14
+
15
+ }
16
+ }
17
+ </script>
18
+
19
+ <style lang="sass">
20
+ .post
21
+ color: red
22
+ </style>
23
+ </component>
@@ -0,0 +1,27 @@
1
+ <component name="test_component">
2
+ <template lang="slim">
3
+ .post
4
+ h1 Other Guy
5
+ h1 Oh hai mark
6
+ </template>
7
+
8
+ <script lang="javascript">
9
+ props: ["test"],
10
+ data: {
11
+ adam: true,
12
+ drew: true
13
+ },
14
+ methods: {
15
+ yo: function() {
16
+
17
+ }
18
+ }
19
+ </script>
20
+
21
+ <style lang="sass">
22
+ .post
23
+ color: green
24
+ h1
25
+ color: pink
26
+ </style>
27
+ </component>
@@ -0,0 +1,21 @@
1
+ <component name="test_component">
2
+ <template lang="slim">
3
+ <div>
4
+ <h1>Oh, Hai Mark!</h1>
5
+ </div>
6
+ </template>
7
+
8
+ <script lang="javascript">
9
+ props: ["test"],
10
+ data: {
11
+ adam: true,
12
+ drew: true
13
+ },
14
+ methods: {
15
+ yo: function() {
16
+
17
+ }
18
+ }
19
+ </script>
20
+
21
+ </component>
@@ -0,0 +1,21 @@
1
+ <component name="test_component">
2
+ <template lang="slim">
3
+ <div>
4
+ <h1>Oh, Hai Mark!</h1>
5
+ </div>
6
+ </template>
7
+
8
+ <script lang="javascript">
9
+ props: ["test"],
10
+ data: {
11
+ adam: true,
12
+ drew: true
13
+ },
14
+ methods: {
15
+ yo: function() {
16
+
17
+ }
18
+ }
19
+ </script>
20
+
21
+ </component>
data/vueck.gemspec ADDED
@@ -0,0 +1,19 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'vueck'
3
+ s.homepage = 'https://github.com/adamrdrew/vueck'
4
+ s.version = '1.0.0'
5
+ s.date = '2018-01-30'
6
+ s.summary = "VueCK"
7
+ s.description = "Rack middleware for compiling and serving VueJS single file components"
8
+ s.authors = ["Adam Drew"]
9
+ s.email = 'adamrdrew@live.com'
10
+ s.files = %x{git ls-files}.split("\n")
11
+ s.licenses = ['LGPL3']
12
+
13
+ s.add_runtime_dependency "oga", "~> 2.9", ">= 2.9.0"
14
+ s.add_runtime_dependency "tilt", "~> 2.0", ">= 2.0.0"
15
+ s.add_runtime_dependency "cssminify", '~> 1.0', '>= 1.0.2'
16
+ s.add_runtime_dependency "slim", '~> 3.0', '>= 3.0.0'
17
+ s.add_runtime_dependency "sass", '~> 3.5', '>= 3.5.5'
18
+ end
19
+
metadata ADDED
@@ -0,0 +1,160 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: vueck
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Adam Drew
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-01-30 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: oga
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.9'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 2.9.0
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '2.9'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 2.9.0
33
+ - !ruby/object:Gem::Dependency
34
+ name: tilt
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '2.0'
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: 2.0.0
43
+ type: :runtime
44
+ prerelease: false
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - "~>"
48
+ - !ruby/object:Gem::Version
49
+ version: '2.0'
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: 2.0.0
53
+ - !ruby/object:Gem::Dependency
54
+ name: cssminify
55
+ requirement: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - "~>"
58
+ - !ruby/object:Gem::Version
59
+ version: '1.0'
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: 1.0.2
63
+ type: :runtime
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: '1.0'
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: 1.0.2
73
+ - !ruby/object:Gem::Dependency
74
+ name: slim
75
+ requirement: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - "~>"
78
+ - !ruby/object:Gem::Version
79
+ version: '3.0'
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: 3.0.0
83
+ type: :runtime
84
+ prerelease: false
85
+ version_requirements: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '3.0'
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ version: 3.0.0
93
+ - !ruby/object:Gem::Dependency
94
+ name: sass
95
+ requirement: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - "~>"
98
+ - !ruby/object:Gem::Version
99
+ version: '3.5'
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: 3.5.5
103
+ type: :runtime
104
+ prerelease: false
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - "~>"
108
+ - !ruby/object:Gem::Version
109
+ version: '3.5'
110
+ - - ">="
111
+ - !ruby/object:Gem::Version
112
+ version: 3.5.5
113
+ description: Rack middleware for compiling and serving VueJS single file components
114
+ email: adamrdrew@live.com
115
+ executables: []
116
+ extensions: []
117
+ extra_rdoc_files: []
118
+ files:
119
+ - ".bundle/config"
120
+ - ".gitignore"
121
+ - Gemfile
122
+ - Gemfile.lock
123
+ - README.md
124
+ - lib/batchrenderer.rb
125
+ - lib/element.rb
126
+ - lib/filemanager.rb
127
+ - lib/plugin.rb
128
+ - lib/sfc.rb
129
+ - lib/vueck.rb
130
+ - test/test.rb
131
+ - test/vue/test.vue
132
+ - test/vue/test2.vue
133
+ - test/vue/test3.vue
134
+ - test/vue/test4.vue
135
+ - vueck.gemspec
136
+ homepage: https://github.com/adamrdrew/vueck
137
+ licenses:
138
+ - LGPL3
139
+ metadata: {}
140
+ post_install_message:
141
+ rdoc_options: []
142
+ require_paths:
143
+ - lib
144
+ required_ruby_version: !ruby/object:Gem::Requirement
145
+ requirements:
146
+ - - ">="
147
+ - !ruby/object:Gem::Version
148
+ version: '0'
149
+ required_rubygems_version: !ruby/object:Gem::Requirement
150
+ requirements:
151
+ - - ">="
152
+ - !ruby/object:Gem::Version
153
+ version: '0'
154
+ requirements: []
155
+ rubyforge_project:
156
+ rubygems_version: 2.5.1
157
+ signing_key:
158
+ specification_version: 4
159
+ summary: VueCK
160
+ test_files: []