vue-helpers 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.
- checksums.yaml +7 -0
- data/.gitignore +12 -0
- data/.travis.yml +7 -0
- data/CHANGELOG.md +19 -0
- data/Gemfile +19 -0
- data/LICENSE.txt +21 -0
- data/README.md +357 -0
- data/Rakefile +21 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/lib/vue/helpers.rb +49 -0
- data/lib/vue/helpers/helper_refinements.rb +219 -0
- data/lib/vue/helpers/methods.rb +100 -0
- data/lib/vue/helpers/server.rb +43 -0
- data/lib/vue/helpers/utilities.rb +79 -0
- data/lib/vue/helpers/version.rb +5 -0
- data/lib/vue/helpers/vue_component.rb +83 -0
- data/lib/vue/helpers/vue_object.rb +201 -0
- data/lib/vue/helpers/vue_repository.rb +49 -0
- data/lib/vue/helpers/vue_root.rb +148 -0
- data/vue-helpers.gemspec +50 -0
- metadata +190 -0
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'erb'
|
2
|
+
|
3
|
+
module Vue
|
4
|
+
module Helpers
|
5
|
+
|
6
|
+
module CoreRefinements
|
7
|
+
refine String do
|
8
|
+
def interpolate(**locals)
|
9
|
+
gsub(/\#\{/, '%{') % locals
|
10
|
+
end
|
11
|
+
|
12
|
+
def camelize
|
13
|
+
#split(/[_-]/).collect(&:capitalize).join
|
14
|
+
split(/\W|_/).collect(&:capitalize).join
|
15
|
+
end
|
16
|
+
|
17
|
+
def kebabize
|
18
|
+
split(/\W|_/).collect(&:downcase).join('-')
|
19
|
+
end
|
20
|
+
|
21
|
+
def escape_backticks
|
22
|
+
gsub(/\`/,'\\\`')
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
refine Hash do
|
27
|
+
def to_html_attributes
|
28
|
+
inject(''){|o, kv| o.to_s << %Q(#{kv[0]}="#{kv[1]}")}
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
refine Dir.singleton_class do
|
33
|
+
# Args are like Dir.glob() with **opts accaptable.
|
34
|
+
#
|
35
|
+
# Returns list of files breadth-first.
|
36
|
+
# Pass :no_recurse=>true to block directory recursion.
|
37
|
+
# Pass a block to yield each found path to the block.
|
38
|
+
#
|
39
|
+
def breadth_first(pattern, flags=0, base: Dir.getwd, **opts, &block)
|
40
|
+
files, dirs = [], []
|
41
|
+
Dir.glob(File.join(base, pattern), flags).each{|path| FileTest.directory?(path) ? dirs.push(path) : files.push(path)}
|
42
|
+
|
43
|
+
files.each{|f| yield(f)} if block_given?
|
44
|
+
dirs.each{|dir| files.concat(breadth_first(pattern, flags, base:dir, &block))} unless opts[:no_recurse]
|
45
|
+
|
46
|
+
files
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end # CoreRefinements
|
50
|
+
|
51
|
+
module ErbPrepend
|
52
|
+
def initialize(*args)
|
53
|
+
#puts "ERB.new: #{args.to_yaml}"
|
54
|
+
#puts "ERB.new with eoutvar: #{args[3]}"
|
55
|
+
args[3] ||= Vue::Helpers.default_outvar
|
56
|
+
super
|
57
|
+
end
|
58
|
+
|
59
|
+
def set_eoutvar(*args)
|
60
|
+
#puts "ERB.set_eoutvar: #{args[1]}"
|
61
|
+
Thread.current.instance_variable_set(:@current_eoutvar, args[1])
|
62
|
+
super
|
63
|
+
end
|
64
|
+
end
|
65
|
+
::ERB.send(:prepend, ErbPrepend)
|
66
|
+
|
67
|
+
module ControllerPrepend
|
68
|
+
# Assign value to undefined @outvar
|
69
|
+
# TODO: This might not be needed any more, after implementation of ERB.set_eoutvar hack.
|
70
|
+
# def initialize(*args)
|
71
|
+
# super
|
72
|
+
# unless defined?(@outvar)
|
73
|
+
# @outvar ||= Vue::Helpers.default_outvar
|
74
|
+
# end
|
75
|
+
# end
|
76
|
+
end
|
77
|
+
|
78
|
+
end # Helpers
|
79
|
+
end # Vue
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require_relative 'utilities'
|
2
|
+
require_relative 'helper_refinements'
|
3
|
+
require_relative 'vue_object'
|
4
|
+
|
5
|
+
module Vue
|
6
|
+
module Helpers
|
7
|
+
using CoreRefinements
|
8
|
+
using HelperRefinements
|
9
|
+
|
10
|
+
class VueComponent < VueObject
|
11
|
+
def type; 'component'; end
|
12
|
+
|
13
|
+
#puts "VueComponent defining @defaults"
|
14
|
+
@defaults = {
|
15
|
+
root_name: nil, #Vue::Helpers.root_name,
|
16
|
+
register_local: nil,
|
17
|
+
template_literal: nil
|
18
|
+
}
|
19
|
+
|
20
|
+
attr_writer *defaults.keys
|
21
|
+
custom_attr_reader *defaults.keys
|
22
|
+
|
23
|
+
# Gets root object
|
24
|
+
def root
|
25
|
+
repo.root(root_name)
|
26
|
+
end
|
27
|
+
|
28
|
+
# Renders the html block to replace ruby vue_component tags.
|
29
|
+
# TODO: Are locals used here? Do they work?
|
30
|
+
def render(tag_name=nil, locals:{}, attributes:{}, &block)
|
31
|
+
# Adds 'is' attribute to html vue-component element,
|
32
|
+
# if the user specifies an alternate 'tag_name' (default tag_name is name-of-component).
|
33
|
+
if tag_name
|
34
|
+
attributes['is'] = name
|
35
|
+
end
|
36
|
+
|
37
|
+
block_content = context.capture_html(root_name:root_name, locals:locals, &block) if block_given?
|
38
|
+
|
39
|
+
# TODO: Are locals being passed properly here?
|
40
|
+
wrapper(:component_call_html,
|
41
|
+
name:name,
|
42
|
+
tag_name:tag_name,
|
43
|
+
el_name:(tag_name || name).to_s.kebabize,
|
44
|
+
block_content:block_content.to_s,
|
45
|
+
attributes_string:attributes.to_html_attributes,
|
46
|
+
**locals
|
47
|
+
)
|
48
|
+
end
|
49
|
+
|
50
|
+
# Builds js output string.
|
51
|
+
# TODO: Follow this backwards/upstream to determine if parsed_template, parsed_script, and locals are being handled correctly.
|
52
|
+
#def to_component_js(register_local:Vue::Helpers.register_local, template_literal:Vue::Helpers.template_literal, locals:{}) #, **options)
|
53
|
+
def to_component_js(locals:{})
|
54
|
+
# The above **options are not used yet, but need somewhere to catch extra stuff.
|
55
|
+
template_spec = template_literal ? "\`#{parsed_template(locals).to_s.escape_backticks}\`" : "'##{name}-template'"
|
56
|
+
js_output = register_local \
|
57
|
+
? 'var #{name} = {template: #{template_spec}, \2;'
|
58
|
+
: 'var #{name} = Vue.component("#{name}", {template: #{template_spec}, \2);' # ) << ")"
|
59
|
+
|
60
|
+
# TODO: Make escaping backticks optional, as they could break user templates with nested backtick blocks, like ${``}.
|
61
|
+
_parsed_script = parsed_script(locals)
|
62
|
+
_parsed_script.gsub(
|
63
|
+
/export\s+default\s*(\{|Vue.component\s*\([^\{]*\{)(.*$)/m,
|
64
|
+
js_output
|
65
|
+
).interpolate(name: name.to_s.camelize, template_spec: template_spec) if _parsed_script
|
66
|
+
end
|
67
|
+
|
68
|
+
# TODO: Follow this backwards/upstream to determine if parsed_template, parsed_script, and locals are being handled correctly.
|
69
|
+
def get_x_template(**locals)
|
70
|
+
wrapper(:x_template_html, name:name, template:parsed_template(locals), **locals)
|
71
|
+
end
|
72
|
+
|
73
|
+
# def template_literal?
|
74
|
+
# case
|
75
|
+
# when !template_literal.nil?; template_literal
|
76
|
+
# when !root.template_literal.nil?; root.template_literal
|
77
|
+
# when !Vue::Helpers.template_literal.nil?; Vue::Helpers.template_literal
|
78
|
+
# end
|
79
|
+
# end
|
80
|
+
|
81
|
+
end # VueComponent
|
82
|
+
end # Helpers
|
83
|
+
end # Vue
|
@@ -0,0 +1,201 @@
|
|
1
|
+
require_relative 'utilities'
|
2
|
+
require_relative 'helper_refinements'
|
3
|
+
|
4
|
+
module Vue
|
5
|
+
module Helpers
|
6
|
+
using CoreRefinements
|
7
|
+
using HelperRefinements
|
8
|
+
|
9
|
+
|
10
|
+
# NOTE: Vue components can be called MULTIPLE times,
|
11
|
+
# so we can't store the calling args OR the block here.
|
12
|
+
#
|
13
|
+
# But note that Vue root-apps can only be called once,
|
14
|
+
# so should we continue to store the vue-root calling args & block here,
|
15
|
+
# or pass them in at run-time as well? I think it ALL has to be dynamic.
|
16
|
+
#
|
17
|
+
class VueObject
|
18
|
+
|
19
|
+
@defaults = {
|
20
|
+
# Only what's necessary to load dot-vue file.
|
21
|
+
name: nil,
|
22
|
+
root_name: nil,
|
23
|
+
file_name: nil,
|
24
|
+
template_engine: nil,
|
25
|
+
#locals: {},
|
26
|
+
|
27
|
+
# The loaded (but not rendered or parsed) dot-vue file as Tilt teplate.
|
28
|
+
# See 'initialize_options()' below
|
29
|
+
tilt_template: nil,
|
30
|
+
|
31
|
+
# Vue-specific options to be inserted in js object.
|
32
|
+
# Remember that component data must be a function in the js object.
|
33
|
+
data: {},
|
34
|
+
watch: {},
|
35
|
+
computed: {},
|
36
|
+
|
37
|
+
# Utility
|
38
|
+
repo: nil
|
39
|
+
}
|
40
|
+
|
41
|
+
# Concatenates subclass defaults with master class defaults.
|
42
|
+
def self.defaults
|
43
|
+
super_defaults = superclass.singleton_class.method_defined?(__method__) ? superclass.defaults : (@defaults || {})
|
44
|
+
super_defaults.merge(@defaults || {})
|
45
|
+
end
|
46
|
+
|
47
|
+
# Creates custom attr readers that tie in to defaults.
|
48
|
+
def self.custom_attr_reader(*args)
|
49
|
+
args.each do |a|
|
50
|
+
define_method(a) do |use_default=true|
|
51
|
+
get_attribute(a, use_default)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
#attr_accessor :repo, *defaults.keys
|
57
|
+
attr_reader :initialized
|
58
|
+
|
59
|
+
|
60
|
+
### Internal methods
|
61
|
+
|
62
|
+
def defaults
|
63
|
+
self.class.defaults
|
64
|
+
end
|
65
|
+
|
66
|
+
# For debugging.
|
67
|
+
def print_ivars
|
68
|
+
puts "\nIVARS:"
|
69
|
+
instance_variables.each do |v|
|
70
|
+
unless v.to_s[/repo/i]
|
71
|
+
puts "#{v}: #{instance_variable_get(v)}"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def initialize(name, **options)
|
77
|
+
@name = name
|
78
|
+
#puts "VueObject created: #{name}, self: #{self}"
|
79
|
+
initialize_options(**options)
|
80
|
+
end
|
81
|
+
|
82
|
+
def initialize_options(**options)
|
83
|
+
@repo ||= options.delete(:repo)
|
84
|
+
#locals = options.delete(:locals) || {}
|
85
|
+
#puts "\n#{self.class.name}.initialize_options '#{name}' #{options.inspect}"
|
86
|
+
return self unless options.size > 0 && !@initialized
|
87
|
+
locals = options.delete(:locals) || {}
|
88
|
+
#puts "\n#{self.class.name}.initialize_options '#{name}', #{options.inspect}, locals:#{locals.inspect}"
|
89
|
+
|
90
|
+
merged_options = defaults.dup.merge(options)
|
91
|
+
|
92
|
+
# Sets each default ivar, unless ivar is already non-nil.
|
93
|
+
merged_options.each do |k,v|
|
94
|
+
#puts "Setting ivar '#{k}' with '#{v}', was previously '#{instance_variable_get('@' + k.to_s)}'"
|
95
|
+
#instance_variable_set("@#{k}", v) if v && instance_variable_get("@#{k}").nil? #!(v.respond_to?(:empty) && v.empty?)
|
96
|
+
instance_variable_set("@#{k}", v) if instance_variable_get("@#{k}").nil?
|
97
|
+
end
|
98
|
+
|
99
|
+
@file_name ||= @name
|
100
|
+
|
101
|
+
#load_dot_vue if file_name
|
102
|
+
load_tilt_template if file_name #&& !tilt_template
|
103
|
+
|
104
|
+
# We need this to discover subcomponents, otherwise
|
105
|
+
# vue_app won't know about them until it's too late.
|
106
|
+
render_template(**locals)
|
107
|
+
|
108
|
+
#puts "\n#{self.class.name} initialized."
|
109
|
+
#print_ivars
|
110
|
+
|
111
|
+
@initialized = true
|
112
|
+
#puts "VueObject initialized options: #{name}, self: #{self}"
|
113
|
+
self
|
114
|
+
end
|
115
|
+
|
116
|
+
# Loads a dot-vue into a tilt template, but doesn't render or parse it.
|
117
|
+
def load_tilt_template
|
118
|
+
self.tilt_template = context.load_template(file_name.to_sym, template_engine:template_engine(false))
|
119
|
+
end
|
120
|
+
|
121
|
+
# Renders loaded tilt_template.
|
122
|
+
# TODO: Find a way to easily insert attributes like 'name', 'root_name', etc. into locals.
|
123
|
+
# Or just insert the current vue object instance into the locals
|
124
|
+
def render_template(**locals)
|
125
|
+
@rendered_template ||= (
|
126
|
+
#puts "\n#{self.class.name} '#{name}' calling render_template with tilt_template: #{tilt_template&.file}, engine: #{template_engine}, locals: #{locals}"
|
127
|
+
context.render_ruby_template(tilt_template, template_engine:template_engine(false), locals:locals.merge(vo:self, vue_object:self)) if !tilt_template.to_s.empty?
|
128
|
+
)
|
129
|
+
end
|
130
|
+
|
131
|
+
# Parses a rendered sfc file.
|
132
|
+
# Returns [nil, template-as-html, nil, script-as-js].
|
133
|
+
# Must be HTML (already rendered from ruby template).
|
134
|
+
def parse_sfc(**locals)
|
135
|
+
@parsed_sfc ||= (
|
136
|
+
#rendered_template = render_template(**locals)
|
137
|
+
rslt = {}
|
138
|
+
rslt[:template], rslt[:script] = render_template(**locals).to_s.match(/(.*<template>(.*)<\/template>)*.*(<script>(.*)<\/script>)/m).to_a.values_at(2,4)
|
139
|
+
rslt
|
140
|
+
)
|
141
|
+
end
|
142
|
+
|
143
|
+
def parsed_template(**locals)
|
144
|
+
@parsed_template ||= (
|
145
|
+
parse_sfc(**locals)[:template]
|
146
|
+
)
|
147
|
+
end
|
148
|
+
|
149
|
+
def parsed_script(**locals)
|
150
|
+
@parsed_script ||= (
|
151
|
+
parse_sfc(**locals)[:script]
|
152
|
+
)
|
153
|
+
end
|
154
|
+
|
155
|
+
def context
|
156
|
+
repo.context
|
157
|
+
end
|
158
|
+
|
159
|
+
|
160
|
+
### Called from user-space by vue_app, vue_root, vue_component.
|
161
|
+
|
162
|
+
# Gets a defined wrapper, and interpolates it with the given locals & options.
|
163
|
+
def wrapper(wrapper_name, **locals) #, **wrapper_options)
|
164
|
+
#Vue::Helpers.send(wrapper_name).interpolate(**wrapper_options.merge(locals))
|
165
|
+
Vue::Helpers.send(wrapper_name).interpolate(locals)
|
166
|
+
end
|
167
|
+
|
168
|
+
def js_var_name
|
169
|
+
name.to_s.camelize
|
170
|
+
end
|
171
|
+
|
172
|
+
# def is_set?(setting)
|
173
|
+
# case
|
174
|
+
# when !send(setting).nil?; send(setting)
|
175
|
+
# when !root.send(setting).nil?; root.send(setting)
|
176
|
+
# when !Vue::Helpers.send(setting).nil?; Vue::Helpers.send(setting)
|
177
|
+
# end
|
178
|
+
# end
|
179
|
+
|
180
|
+
# Get attribute, considering upstream possibilities.
|
181
|
+
def get_attribute(attribute, use_default=true)
|
182
|
+
case
|
183
|
+
when
|
184
|
+
( val = instance_variable_get("@#{attribute}"); !val.nil? );
|
185
|
+
val
|
186
|
+
when
|
187
|
+
type != 'root' &&
|
188
|
+
root.respond_to?(attribute) &&
|
189
|
+
( val = root.send(attribute, use_default); !val.nil? );
|
190
|
+
val
|
191
|
+
when
|
192
|
+
use_default &&
|
193
|
+
Vue::Helpers.respond_to?(attribute) &&
|
194
|
+
( val = Vue::Helpers.send(attribute); !val.nil? );
|
195
|
+
val
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
end # VueObject
|
200
|
+
end # Helpers
|
201
|
+
end # Vue
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require_relative 'utilities'
|
2
|
+
require_relative 'helper_refinements'
|
3
|
+
require_relative 'vue_component'
|
4
|
+
require_relative 'vue_root'
|
5
|
+
|
6
|
+
module Vue
|
7
|
+
|
8
|
+
#Debug = []
|
9
|
+
|
10
|
+
module Helpers
|
11
|
+
using CoreRefinements
|
12
|
+
using HelperRefinements
|
13
|
+
|
14
|
+
# Stores ruby representations of vue objects.
|
15
|
+
# Intended for a single request cycle.
|
16
|
+
# TODO: Rename this to VueStash.
|
17
|
+
# NOTE: Always use the repository interface for vue-object crud operations from controller or views.
|
18
|
+
class VueRepository < Hash
|
19
|
+
attr_reader :context
|
20
|
+
|
21
|
+
# Always pass a context when creating a VueRepository.
|
22
|
+
def initialize(context)
|
23
|
+
#Debug << self
|
24
|
+
@context = context
|
25
|
+
end
|
26
|
+
|
27
|
+
# Master get_or_create for any object in the repository.
|
28
|
+
def get_or_create(klas, name, **options)
|
29
|
+
obj = fetch(name){ |n| self[name] = klas.new(name, **options.merge({repo:self})) }
|
30
|
+
obj.repo ||= self
|
31
|
+
obj.initialize_options(**options)
|
32
|
+
obj
|
33
|
+
end
|
34
|
+
|
35
|
+
# Gets or creates a VueRoot instance.
|
36
|
+
def root(name=nil, **options)
|
37
|
+
name ||= Vue::Helpers.root_name
|
38
|
+
get_or_create(VueRoot, name, **options)
|
39
|
+
end
|
40
|
+
#alias_method :[], :root
|
41
|
+
|
42
|
+
# Gets or creates a VueComponent instance.
|
43
|
+
def component(name, **options)
|
44
|
+
get_or_create(VueComponent, name, **options)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
end # Helpers
|
49
|
+
end # Vue
|
@@ -0,0 +1,148 @@
|
|
1
|
+
require 'securerandom'
|
2
|
+
require_relative 'utilities'
|
3
|
+
require_relative 'helper_refinements'
|
4
|
+
require_relative 'vue_object'
|
5
|
+
|
6
|
+
module Vue
|
7
|
+
module Helpers
|
8
|
+
using CoreRefinements
|
9
|
+
using HelperRefinements
|
10
|
+
|
11
|
+
class VueRoot < VueObject
|
12
|
+
def type; 'root'; end
|
13
|
+
|
14
|
+
@defaults = {
|
15
|
+
#app_name: nil,
|
16
|
+
name: Vue::Helpers.root_name,
|
17
|
+
external_resource: nil, #Vue::Helpers.external_resource,
|
18
|
+
template_literal: nil, #Vue::Helpers.template_literal,
|
19
|
+
register_local: nil, #Vue::Helpers.register_local,
|
20
|
+
minify: nil, #Vue::Helpers.minify,
|
21
|
+
#locals: {},
|
22
|
+
}
|
23
|
+
|
24
|
+
attr_writer *defaults.keys
|
25
|
+
custom_attr_reader *defaults.keys
|
26
|
+
|
27
|
+
### Under Construction
|
28
|
+
# Renders the html block to replace ruby vue_root tags.
|
29
|
+
#def render(tag_name=nil, locals:{}, attributes:{}, &block) # From vue_component
|
30
|
+
#def render(locals:{}, **options, &block)
|
31
|
+
def render(locals:{}, &block)
|
32
|
+
#puts "\nVueRoot#render with locals: #{locals}, self: #{self}"
|
33
|
+
#print_ivars
|
34
|
+
|
35
|
+
block_content = context.capture_html(root_name:name, locals:locals, &block) if block_given?
|
36
|
+
|
37
|
+
compiled_js = compile_app_js(locals:locals) #, **options)
|
38
|
+
|
39
|
+
root_script_output = case external_resource
|
40
|
+
# TODO: Handle external_resource:<some-string> if necessary.
|
41
|
+
when true;
|
42
|
+
key = SecureRandom.urlsafe_base64(32)
|
43
|
+
Vue::Helpers.cache_store[key] = compiled_js
|
44
|
+
callback_prefix = Vue::Helpers.callback_prefix
|
45
|
+
wrapper(:external_resource_html, callback_prefix:callback_prefix, key:key, **locals)
|
46
|
+
else
|
47
|
+
wrapper(:inline_script_html, compiled:compiled_js, **locals)
|
48
|
+
end
|
49
|
+
|
50
|
+
root_script_output.prepend(components_x_template(locals).to_s) unless template_literal
|
51
|
+
|
52
|
+
# TODO: Are locals being passed properly here?
|
53
|
+
if block_given?
|
54
|
+
wrapper(:root_app_html,
|
55
|
+
root_name: name,
|
56
|
+
block_content: block_content,
|
57
|
+
root_script_output: root_script_output,
|
58
|
+
**locals
|
59
|
+
)
|
60
|
+
else
|
61
|
+
root_script_output
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def app_name
|
66
|
+
@app_name || js_var_name
|
67
|
+
end
|
68
|
+
|
69
|
+
# Gets or creates a related component.
|
70
|
+
def component(_name, **component_options)
|
71
|
+
repo.component(_name, **component_options.merge({root_name:(root_name || name)}))
|
72
|
+
end
|
73
|
+
|
74
|
+
# Selects all related components.
|
75
|
+
def components
|
76
|
+
repo.select{|k,v| v.type == 'component' && v.root_name == name}.values.compact.uniq{|v| v.name.to_s}
|
77
|
+
end
|
78
|
+
|
79
|
+
def component_names
|
80
|
+
components.map{|c| c.js_var_name}.join(', ')
|
81
|
+
end
|
82
|
+
|
83
|
+
# Returns JS string of all component object definitions.
|
84
|
+
def components_js(**component_options)
|
85
|
+
#puts "\nVueRoot#componenets_js called with components: #{components.map(&:name)}"
|
86
|
+
components.map{|c| c.to_component_js(**component_options)}.join("\n")
|
87
|
+
end
|
88
|
+
|
89
|
+
# Returns HTML string of component vue templates in x-template format.
|
90
|
+
def components_x_template(**locals)
|
91
|
+
components.map{|c| c.get_x_template(locals) unless c.template_literal}.compact.join("\n")
|
92
|
+
end
|
93
|
+
|
94
|
+
# Compiles js output (components & root) for entire vue app for this root object.
|
95
|
+
# If template_literal is false, only the js object definitions are included.
|
96
|
+
# In that case, the vue template html is left to be rendered in x-template blocks.
|
97
|
+
# TODO: Clean up args, especially locals handling.
|
98
|
+
def compile_app_js(locals:{}) #, **options)
|
99
|
+
### Above is generic opts placeholder until we get the args/opts flow worked out.
|
100
|
+
### It used to bee this:
|
101
|
+
# root_name = Vue::Helpers.root_name,
|
102
|
+
# file_name:root_name,
|
103
|
+
# app_name:root_name.camelize, # Maybe obsolete, see js_var_name
|
104
|
+
# #template_engine:context.current_template_engine,
|
105
|
+
# register_local: Vue::Helpers.register_local,
|
106
|
+
# minify: Vue::Helpers.minify,
|
107
|
+
# # Block may not be needed here, it's handled in 'vue_root'.
|
108
|
+
# &block
|
109
|
+
|
110
|
+
# TODO: Make these locals accessible from anywhere within the root instance,
|
111
|
+
# as we also need them for the 'render' method.
|
112
|
+
# Should this just be moved to 'render' method?
|
113
|
+
locals = {
|
114
|
+
root_name: name.to_s.kebabize,
|
115
|
+
#app_name: (options[:app_name] || js_var_name),
|
116
|
+
app_name: js_var_name,
|
117
|
+
file_name: file_name,
|
118
|
+
template_engine: template_engine(false),
|
119
|
+
components: component_names,
|
120
|
+
vue_data_json: data.to_json
|
121
|
+
}.merge!(locals)
|
122
|
+
|
123
|
+
# {block_content:rendered_block, vue_sfc:{name:name, vue_template:template, vue_script:script}}
|
124
|
+
#rendered_root_sfc_js = \
|
125
|
+
#app_js << (
|
126
|
+
#output = components_js(locals:{}, **options) << "\n" << (
|
127
|
+
output = components_js(locals:{}) << "\n" << (
|
128
|
+
parsed_script(locals) ||
|
129
|
+
wrapper(:root_object_js, **locals) #, **options)
|
130
|
+
)
|
131
|
+
|
132
|
+
#app_js << rendered_root_sfc_js
|
133
|
+
|
134
|
+
output = if minify
|
135
|
+
#extra_spaces_removed = app_js.gsub(/(^\s+)|(\s+)|(\s+$)/){|m| {$1 => "\\\n", $2 => ' ', $3 => "\\\n"}[m]}
|
136
|
+
Uglifier.compile(output, harmony:true).gsub(/\s{2,}/, ' ')
|
137
|
+
else
|
138
|
+
output
|
139
|
+
end
|
140
|
+
|
141
|
+
# Should we have an append_output option that takes a string of js?
|
142
|
+
#output << "; App = VueApp;"
|
143
|
+
|
144
|
+
end # compile_app_js
|
145
|
+
|
146
|
+
end # VueRoot
|
147
|
+
end # Helpers
|
148
|
+
end # Vue
|