vue_live 0.1.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.
@@ -0,0 +1,143 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'digest'
4
+
5
+ module VueLive
6
+ # Compiles components on demand and remembers the result.
7
+ #
8
+ # In development (config.reload? == true) every fetch compares the file's mtime (and the mtimes
9
+ # of any `src="..."` dependencies and imported siblings) with the cached entry and recompiles
10
+ # when something changed. In production the first request compiles and every later one is a
11
+ # hash lookup.
12
+ #
13
+ # With config.digest_imports the relative imports inside a module get `?v=<digest>` appended,
14
+ # so a page's whole module graph can be served with immutable caching: a child's digest is part
15
+ # of its parent's code, and therefore of the parent's digest.
16
+ class Store
17
+ attr_reader :config, :resolver, :cache
18
+
19
+ def initialize(config)
20
+ @config = config
21
+ @resolver = Resolver.new(config)
22
+ @cache = Cache.build(config)
23
+ @locks = Hash.new { |h, k| h[k] = Mutex.new }
24
+ @locks_mutex = Mutex.new
25
+ end
26
+
27
+ # Compiled module for the component at +relative_path+ (e.g. "App.vue"). Raises
28
+ # Errno::ENOENT when the file is missing and CompileError when it cannot be compiled.
29
+ def fetch(relative_path)
30
+ relative_path = relative_path.sub(/\.vue\.js\z/, '.vue')
31
+ absolute = File.join(resolver.source_dir, relative_path)
32
+ raise Errno::ENOENT, absolute unless File.file?(absolute)
33
+
34
+ key = cache_key(relative_path)
35
+ hit = cache.read(key)
36
+ return hit if hit && !stale?(hit, absolute)
37
+
38
+ lock_for(key).synchronize do
39
+ hit = cache.read(key)
40
+ return hit if hit && !stale?(hit, absolute)
41
+
42
+ compiling.push(relative_path)
43
+ begin
44
+ compiled = compile(relative_path, absolute)
45
+ ensure
46
+ compiling.pop
47
+ end
48
+ cache.write(key, compiled)
49
+ end
50
+ end
51
+
52
+ # Content digest for cache-busting URLs; nil when the component does not exist or fails.
53
+ def digest(relative_path)
54
+ fetch(relative_path).digest
55
+ rescue Error, Errno::ENOENT
56
+ nil
57
+ end
58
+
59
+ # Cache-busting token for a non-component file under the root (matches the middleware's ETag).
60
+ def file_digest(relative_path)
61
+ stat = File.stat(File.join(resolver.source_dir, relative_path))
62
+ Store.file_etag(stat)
63
+ rescue Errno::ENOENT
64
+ nil
65
+ end
66
+
67
+ def self.file_etag(stat)
68
+ "#{stat.mtime.to_i.to_s(16)}-#{stat.size.to_s(16)}"
69
+ end
70
+
71
+ def clear
72
+ cache.clear
73
+ end
74
+
75
+ private
76
+
77
+ def compile(relative_path, absolute)
78
+ source = File.read(absolute)
79
+ started = Process.clock_gettime(Process::CLOCK_MONOTONIC)
80
+ result = Compiler.compile(source, relative_path: relative_path, absolute_path: absolute, config: config)
81
+ dependencies = result.dependencies.dup
82
+ code = Emitter.emit(result, relative_path: relative_path, inject_styles: config.inject_styles,
83
+ source_map: config.source_maps?) do |spec|
84
+ digest_import(spec, relative_path, dependencies)
85
+ end
86
+ ms = ((Process.clock_gettime(Process::CLOCK_MONOTONIC) - started) * 1000).round(1)
87
+ config.logger.debug("[vue_live] compiled #{relative_path} with #{result.backend} in #{ms}ms")
88
+
89
+ Compiled.new(
90
+ relative_path: relative_path,
91
+ code: code,
92
+ digest: Digest::SHA256.hexdigest(code)[0, 16],
93
+ mtime: latest_mtime([absolute] + dependencies),
94
+ dependencies: dependencies,
95
+ backend: result.backend,
96
+ scope_id: result.scope_id
97
+ )
98
+ end
99
+
100
+ # `./Child.vue.js` -> `./Child.vue.js?v=<digest>` (compiling the child if needed);
101
+ # `./util.js` -> `./util.js?v=<mtime-size>`. Imports that cannot be resolved are left alone.
102
+ def digest_import(spec, importer, dependencies)
103
+ return nil unless config.digest_imports
104
+ return nil if spec.start_with?('/') # absolute URLs may belong to another mount
105
+
106
+ target = resolver.resolve(File.expand_path(spec, "/#{File.dirname(importer)}").sub(%r{\A/}, ''))
107
+ return nil unless target
108
+
109
+ dependencies << target.absolute_path
110
+ token = if target.vue?
111
+ compiling.include?(target.relative_path) ? nil : digest(target.relative_path)
112
+ else
113
+ file_digest(target.relative_path)
114
+ end
115
+ token ? "#{spec}?v=#{token}" : nil
116
+ end
117
+
118
+ # Components whose compilation is in progress on this thread, to break import cycles.
119
+ def compiling
120
+ Thread.current[:vue_live_compiling] ||= []
121
+ end
122
+
123
+ def stale?(compiled, absolute)
124
+ return false unless config.reload?
125
+
126
+ latest_mtime([absolute] + Array(compiled.dependencies)) > compiled.mtime
127
+ rescue Errno::ENOENT
128
+ true
129
+ end
130
+
131
+ def latest_mtime(files)
132
+ files.map { |f| File.mtime(f) }.max
133
+ end
134
+
135
+ def cache_key(relative_path)
136
+ "#{config.env}:#{config.compiler}:#{relative_path}"
137
+ end
138
+
139
+ def lock_for(key)
140
+ @locks_mutex.synchronize { @locks[key] }
141
+ end
142
+ end
143
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ namespace :vue_live do
4
+ desc 'Compile every .vue component into static .vue.js modules (default: public/vue)'
5
+ task :precompile do
6
+ Rake::Task['environment'].invoke if Rake::Task.task_defined?('environment')
7
+ VueLive.load_config_file unless VueLive.rails?
8
+ manifest = VueLive::Precompiler.new.run
9
+ puts " #{manifest.size} file(s) written to #{VueLive.config.precompile_dir}"
10
+ end
11
+
12
+ desc 'Remove precompiled components and the compile cache'
13
+ task :clobber do
14
+ Rake::Task['environment'].invoke if Rake::Task.task_defined?('environment')
15
+ VueLive::Precompiler.new.clobber
16
+ VueLive.store.clear
17
+ puts " removed #{VueLive.config.precompile_dir} and #{VueLive.config.cache_dir}"
18
+ end
19
+
20
+ desc 'Verify the configuration, component directory and (if used) the Node toolchain'
21
+ task :check do
22
+ Rake::Task['environment'].invoke if Rake::Task.task_defined?('environment')
23
+ VueLive.load_config_file unless VueLive.rails?
24
+ problems = VueLive::NodeTools.problems
25
+ components = VueLive.store.resolver.components
26
+ puts " root: #{VueLive.config.root}"
27
+ puts " components: #{VueLive.config.source_dir} (#{components.size} .vue file(s))"
28
+ puts " prefix: #{VueLive.config.normalized_prefix}"
29
+ puts " compiler: #{VueLive.config.compiler}"
30
+ puts " vue: #{VueLive.config.resolved_vue_url}"
31
+ puts " node: #{VueLive::NodeTools.node_version || 'not found'}"
32
+ puts " compiler-sfc: #{VueLive::NodeTools.compiler_sfc_version || 'not installed'}"
33
+ if problems.empty?
34
+ puts 'Everything looks good.'
35
+ else
36
+ problems.each { |p| puts " problem: #{p}" }
37
+ exit 1
38
+ end
39
+ end
40
+
41
+ desc 'Install @vue/compiler-sfc and vue with npm/yarn for the :node compiler'
42
+ task :node_setup do
43
+ Rake::Task['environment'].invoke if Rake::Task.task_defined?('environment')
44
+ VueLive::NodeTools.setup
45
+ end
46
+ end
47
+
48
+ if VueLive.config.hook_assets_precompile && Rake::Task.task_defined?('assets:precompile')
49
+ Rake::Task['assets:precompile'].enhance(['vue_live:precompile'])
50
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ # `require 'vue_live/tasks'` in a Rakefile outside Rails to get the vue_live:* tasks.
4
+ require_relative '../vue_live'
5
+ load File.expand_path('tasks.rake', __dir__)
@@ -0,0 +1,48 @@
1
+ <template>
2
+ <section class="hello">
3
+ <h2>{{ greeting }}, {{ name }}!</h2>
4
+ <p>
5
+ This component was compiled by <code>vue_live</code> straight from
6
+ <code>app/vue/HelloVueLive.vue</code> — no build step.
7
+ </p>
8
+ <button type="button" @click="count++">Clicked {{ count }} time{{ count === 1 ? '' : 's' }}</button>
9
+ </section>
10
+ </template>
11
+
12
+ <script>
13
+ export default {
14
+ props: {
15
+ name: { type: String, default: 'world' }
16
+ },
17
+ data() {
18
+ return { count: 0 }
19
+ },
20
+ computed: {
21
+ greeting() {
22
+ return this.count > 4 ? 'Still hello' : 'Hello'
23
+ }
24
+ }
25
+ }
26
+ </script>
27
+
28
+ <style scoped>
29
+ .hello {
30
+ font-family: system-ui, sans-serif;
31
+ padding: 1rem 1.5rem;
32
+ border: 1px solid #42b883;
33
+ border-radius: 8px;
34
+ max-width: 32rem;
35
+ }
36
+ .hello h2 {
37
+ color: #42b883;
38
+ margin-top: 0;
39
+ }
40
+ button {
41
+ background: #35495e;
42
+ color: white;
43
+ border: 0;
44
+ border-radius: 4px;
45
+ padding: 0.5rem 1rem;
46
+ cursor: pointer;
47
+ }
48
+ </style>
@@ -0,0 +1,32 @@
1
+ # vue_live configuration. Keys mirror VueLive::Configuration; the `default` section is merged
2
+ # with the section for the current environment (RAILS_ENV / RACK_ENV / APP_ENV).
3
+ default: &default
4
+ # Directory holding your .vue components (relative to the project root).
5
+ source_path: app/vue
6
+ # URL prefix the components are served under.
7
+ prefix: /vue
8
+ # ruby - pure Ruby, zero dependencies: <template>, <script>, <style [scoped]>
9
+ # node - @vue/compiler-sfc through Node.js: adds <script setup>, TypeScript, Sass, CSS modules
10
+ # auto - Ruby, falling back to Node only for components that need it
11
+ compiler: auto
12
+ # memory | file | none
13
+ cache: memory
14
+ cache_path: tmp/cache/vue_live
15
+ # URL of Vue's ESM browser build. Leave unset to use a local copy (node_modules or
16
+ # vendor/vue_live) when one exists, otherwise the pinned jsDelivr build.
17
+ # vue_url: https://cdn.jsdelivr.net/npm/vue@3/dist/vue.esm-browser.prod.js
18
+ # Extra import-map entries available to your components:
19
+ # import_map:
20
+ # pinia: https://cdn.jsdelivr.net/npm/pinia@3/dist/pinia.esm-browser.js
21
+
22
+ development:
23
+ <<: *default
24
+ reload: true
25
+
26
+ test:
27
+ <<: *default
28
+
29
+ production:
30
+ <<: *default
31
+ reload: false
32
+ # cache: file
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module VueLive
4
+ VERSION = '0.1.0'
5
+ end
data/lib/vue_live.rb ADDED
@@ -0,0 +1,107 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'vue_live/version'
4
+ require_relative 'vue_live/errors'
5
+ require_relative 'vue_live/configuration'
6
+ require_relative 'vue_live/source_map'
7
+ require_relative 'vue_live/compiler'
8
+ require_relative 'vue_live/emitter'
9
+ require_relative 'vue_live/cache'
10
+ require_relative 'vue_live/resolver'
11
+ require_relative 'vue_live/store'
12
+ require_relative 'vue_live/live_reload'
13
+ require_relative 'vue_live/middleware'
14
+ require_relative 'vue_live/helpers'
15
+ require_relative 'vue_live/precompiler'
16
+ require_relative 'vue_live/node_tools'
17
+
18
+ # vue_live: serve Vue single-file components straight from Ruby, in production, with no build step.
19
+ #
20
+ # # Rack / Sinatra
21
+ # use VueLive::Middleware
22
+ #
23
+ # # Rails: nothing to do - the Railtie mounts the middleware and adds the view helpers.
24
+ #
25
+ # <%= vue_live_import_map_tag %>
26
+ # <%= vue_live_mount_tag 'App.vue', '#app' %>
27
+ module VueLive
28
+ class << self
29
+ def config
30
+ @config ||= Configuration.new
31
+ end
32
+
33
+ def configure
34
+ yield config if block_given?
35
+ reset_store!
36
+ config
37
+ end
38
+
39
+ # Replace the configuration wholesale (used by tests and by the Railtie).
40
+ def config=(configuration)
41
+ @config = configuration
42
+ reset_store!
43
+ end
44
+
45
+ # Load config/vue_live.yml from the project root if it exists.
46
+ def load_config_file(path = nil)
47
+ config.load_yaml(*[path].compact)
48
+ reset_store!
49
+ config
50
+ end
51
+
52
+ # The object that compiles and caches components; one per configuration.
53
+ def store
54
+ @store ||= Store.new(config)
55
+ end
56
+
57
+ def reset_store!
58
+ @store = nil
59
+ end
60
+
61
+ # Compile a component by its path relative to the source directory and return the module body.
62
+ def compile(relative_path)
63
+ store.fetch(relative_path).code
64
+ end
65
+
66
+ # Convenience: compile a .vue string with no file behind it.
67
+ def compile_source(source, filename: 'anonymous.vue')
68
+ result = Compiler.compile(source, relative_path: filename, config: config)
69
+ Emitter.emit(result, relative_path: filename, inject_styles: config.inject_styles)
70
+ end
71
+
72
+ # ---- environment detection -------------------------------------------------------------
73
+
74
+ def rails?
75
+ defined?(::Rails) && ::Rails.respond_to?(:application) && !::Rails.application.nil?
76
+ rescue StandardError
77
+ false
78
+ end
79
+
80
+ # A Rails project on disk (even when Rails itself is not loaded, e.g. from the CLI).
81
+ def rails_project?(dir = Dir.pwd)
82
+ File.file?(File.join(dir, 'config', 'application.rb')) &&
83
+ (File.file?(File.join(dir, 'bin', 'rails')) || File.file?(File.join(dir, 'config', 'environment.rb')))
84
+ end
85
+
86
+ def sinatra?
87
+ defined?(::Sinatra::Base) ? true : false
88
+ end
89
+
90
+ def detect_root
91
+ return ::Rails.root.to_s if rails? && ::Rails.root
92
+
93
+ ENV['VUE_LIVE_ROOT'] || Dir.pwd
94
+ end
95
+
96
+ def detect_env
97
+ ENV['VUE_LIVE_ENV'] || ENV['RAILS_ENV'] || ENV['RACK_ENV'] || ENV['APP_ENV'] ||
98
+ (rails? ? ::Rails.env.to_s : 'development')
99
+ end
100
+
101
+ def logger
102
+ config.logger
103
+ end
104
+ end
105
+ end
106
+
107
+ require_relative 'vue_live/railtie' if defined?(Rails::Railtie)
metadata ADDED
@@ -0,0 +1,292 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: vue_live
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Daniel P. Clark
8
+ bindir: exe
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: actionview
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: '6.1'
19
+ - - "<"
20
+ - !ruby/object:Gem::Version
21
+ version: '9'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ version: '6.1'
29
+ - - "<"
30
+ - !ruby/object:Gem::Version
31
+ version: '9'
32
+ - !ruby/object:Gem::Dependency
33
+ name: importmap-rails
34
+ requirement: !ruby/object:Gem::Requirement
35
+ requirements:
36
+ - - ">="
37
+ - !ruby/object:Gem::Version
38
+ version: '1.0'
39
+ - - "<"
40
+ - !ruby/object:Gem::Version
41
+ version: '3'
42
+ type: :development
43
+ prerelease: false
44
+ version_requirements: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: '1.0'
49
+ - - "<"
50
+ - !ruby/object:Gem::Version
51
+ version: '3'
52
+ - !ruby/object:Gem::Dependency
53
+ name: minitest
54
+ requirement: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - "~>"
57
+ - !ruby/object:Gem::Version
58
+ version: '5.11'
59
+ type: :development
60
+ prerelease: false
61
+ version_requirements: !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - "~>"
64
+ - !ruby/object:Gem::Version
65
+ version: '5.11'
66
+ - !ruby/object:Gem::Dependency
67
+ name: rack
68
+ requirement: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: '2.2'
73
+ - - "<"
74
+ - !ruby/object:Gem::Version
75
+ version: '4'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '2.2'
83
+ - - "<"
84
+ - !ruby/object:Gem::Version
85
+ version: '4'
86
+ - !ruby/object:Gem::Dependency
87
+ name: rack-test
88
+ requirement: !ruby/object:Gem::Requirement
89
+ requirements:
90
+ - - "~>"
91
+ - !ruby/object:Gem::Version
92
+ version: '2.0'
93
+ type: :development
94
+ prerelease: false
95
+ version_requirements: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - "~>"
98
+ - !ruby/object:Gem::Version
99
+ version: '2.0'
100
+ - !ruby/object:Gem::Dependency
101
+ name: rackup
102
+ requirement: !ruby/object:Gem::Requirement
103
+ requirements:
104
+ - - ">="
105
+ - !ruby/object:Gem::Version
106
+ version: '1.0'
107
+ - - "<"
108
+ - !ruby/object:Gem::Version
109
+ version: '3'
110
+ type: :development
111
+ prerelease: false
112
+ version_requirements: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: '1.0'
117
+ - - "<"
118
+ - !ruby/object:Gem::Version
119
+ version: '3'
120
+ - !ruby/object:Gem::Dependency
121
+ name: railties
122
+ requirement: !ruby/object:Gem::Requirement
123
+ requirements:
124
+ - - ">="
125
+ - !ruby/object:Gem::Version
126
+ version: '6.1'
127
+ - - "<"
128
+ - !ruby/object:Gem::Version
129
+ version: '9'
130
+ type: :development
131
+ prerelease: false
132
+ version_requirements: !ruby/object:Gem::Requirement
133
+ requirements:
134
+ - - ">="
135
+ - !ruby/object:Gem::Version
136
+ version: '6.1'
137
+ - - "<"
138
+ - !ruby/object:Gem::Version
139
+ version: '9'
140
+ - !ruby/object:Gem::Dependency
141
+ name: rake
142
+ requirement: !ruby/object:Gem::Requirement
143
+ requirements:
144
+ - - "~>"
145
+ - !ruby/object:Gem::Version
146
+ version: '13.0'
147
+ type: :development
148
+ prerelease: false
149
+ version_requirements: !ruby/object:Gem::Requirement
150
+ requirements:
151
+ - - "~>"
152
+ - !ruby/object:Gem::Version
153
+ version: '13.0'
154
+ - !ruby/object:Gem::Dependency
155
+ name: rubocop
156
+ requirement: !ruby/object:Gem::Requirement
157
+ requirements:
158
+ - - "~>"
159
+ - !ruby/object:Gem::Version
160
+ version: '1.60'
161
+ type: :development
162
+ prerelease: false
163
+ version_requirements: !ruby/object:Gem::Requirement
164
+ requirements:
165
+ - - "~>"
166
+ - !ruby/object:Gem::Version
167
+ version: '1.60'
168
+ - !ruby/object:Gem::Dependency
169
+ name: sinatra
170
+ requirement: !ruby/object:Gem::Requirement
171
+ requirements:
172
+ - - ">="
173
+ - !ruby/object:Gem::Version
174
+ version: '3.0'
175
+ - - "<"
176
+ - !ruby/object:Gem::Version
177
+ version: '5'
178
+ type: :development
179
+ prerelease: false
180
+ version_requirements: !ruby/object:Gem::Requirement
181
+ requirements:
182
+ - - ">="
183
+ - !ruby/object:Gem::Version
184
+ version: '3.0'
185
+ - - "<"
186
+ - !ruby/object:Gem::Version
187
+ version: '5'
188
+ - !ruby/object:Gem::Dependency
189
+ name: webpacker_cli
190
+ requirement: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - "~>"
193
+ - !ruby/object:Gem::Version
194
+ version: '1.0'
195
+ type: :development
196
+ prerelease: false
197
+ version_requirements: !ruby/object:Gem::Requirement
198
+ requirements:
199
+ - - "~>"
200
+ - !ruby/object:Gem::Version
201
+ version: '1.0'
202
+ - !ruby/object:Gem::Dependency
203
+ name: webrick
204
+ requirement: !ruby/object:Gem::Requirement
205
+ requirements:
206
+ - - "~>"
207
+ - !ruby/object:Gem::Version
208
+ version: '1.8'
209
+ type: :development
210
+ prerelease: false
211
+ version_requirements: !ruby/object:Gem::Requirement
212
+ requirements:
213
+ - - "~>"
214
+ - !ruby/object:Gem::Version
215
+ version: '1.8'
216
+ description: |-
217
+ vue_live compiles .vue single-file components on the fly, in Ruby, and serves them to the browser
218
+ as native ES modules. It works with any Rack application (Sinatra, Roda, plain Rack), detects a
219
+ Rails application and configures itself as a Railtie, and coexists with Sprockets, Propshaft,
220
+ Webpacker, importmap-rails and jsbundling without touching their paths. An optional Node backend
221
+ (via @vue/compiler-sfc) adds <script setup>, TypeScript and CSS preprocessors.
222
+ email:
223
+ - 6ftdan@gmail.com
224
+ executables:
225
+ - vue-live
226
+ extensions: []
227
+ extra_rdoc_files: []
228
+ files:
229
+ - CHANGELOG.md
230
+ - LICENSE-APACHE
231
+ - LICENSE-MIT
232
+ - README.md
233
+ - exe/vue-live
234
+ - lib/generators/vue_live/install/install_generator.rb
235
+ - lib/vue_live.rb
236
+ - lib/vue_live/assets/reload.js
237
+ - lib/vue_live/cache.rb
238
+ - lib/vue_live/cli.rb
239
+ - lib/vue_live/compiler.rb
240
+ - lib/vue_live/compiler/node.rb
241
+ - lib/vue_live/compiler/node/compile.js
242
+ - lib/vue_live/compiler/ruby.rb
243
+ - lib/vue_live/configuration.rb
244
+ - lib/vue_live/emitter.rb
245
+ - lib/vue_live/errors.rb
246
+ - lib/vue_live/helpers.rb
247
+ - lib/vue_live/live_reload.rb
248
+ - lib/vue_live/middleware.rb
249
+ - lib/vue_live/node_tools.rb
250
+ - lib/vue_live/precompiler.rb
251
+ - lib/vue_live/rails/helper.rb
252
+ - lib/vue_live/railtie.rb
253
+ - lib/vue_live/resolver.rb
254
+ - lib/vue_live/scoped_css.rb
255
+ - lib/vue_live/sfc/descriptor.rb
256
+ - lib/vue_live/sfc/parser.rb
257
+ - lib/vue_live/sinatra.rb
258
+ - lib/vue_live/source_map.rb
259
+ - lib/vue_live/store.rb
260
+ - lib/vue_live/tasks.rake
261
+ - lib/vue_live/tasks.rb
262
+ - lib/vue_live/templates/HelloVueLive.vue
263
+ - lib/vue_live/templates/vue_live.yml
264
+ - lib/vue_live/version.rb
265
+ homepage: https://github.com/danielpclark/vue-live
266
+ licenses:
267
+ - MIT
268
+ - Apache-2.0
269
+ metadata:
270
+ source_code_uri: https://github.com/danielpclark/vue-live
271
+ changelog_uri: https://github.com/danielpclark/vue-live/blob/main/CHANGELOG.md
272
+ bug_tracker_uri: https://github.com/danielpclark/vue-live/issues
273
+ rubygems_mfa_required: 'true'
274
+ rdoc_options: []
275
+ require_paths:
276
+ - lib
277
+ required_ruby_version: !ruby/object:Gem::Requirement
278
+ requirements:
279
+ - - ">="
280
+ - !ruby/object:Gem::Version
281
+ version: '3.0'
282
+ required_rubygems_version: !ruby/object:Gem::Requirement
283
+ requirements:
284
+ - - ">="
285
+ - !ruby/object:Gem::Version
286
+ version: '0'
287
+ requirements: []
288
+ rubygems_version: 3.6.9
289
+ specification_version: 4
290
+ summary: Serve Vue single-file components straight from Ruby, in production, with
291
+ no build step.
292
+ test_files: []