ejx 0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 7d977622dbdaa5af0afbc8c9c024439f104337c3b4133dbf2c7866656256f373
4
+ data.tar.gz: e02233b080ee6d8dce9e94135993771464e33497a9102419d75ad8cf058f8984
5
+ SHA512:
6
+ metadata.gz: e5dd9308fe7904ad51c24475de414887f92cdc62c76111f2c98ff03342d4d2874e17d44cbea939ae9dc3285670ebce7b027afb278630931b96898a40657babd1
7
+ data.tar.gz: f53c0b6ca412d595ae449f8db65f6038a152ba411f12debc9f57226d9679134c2a471f5e69a14572f8728c97bd0b797e9243322cf47e3af12532ce8719e4b6f4
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2020 Jon Bracy
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,80 @@
1
+ EJX (Embedded JavaScript) template compiler for Ruby
2
+ ====================================================
3
+
4
+ EJX templates embed JavaScript code inside `<% ... %>` tags, much like ERB. This
5
+ library is inspired by [Underscore.js](https://underscorejs.org)'s
6
+ [`_.template` function](https://underscorejs.org/#template) and
7
+ [JSX](https://reactjs.org/docs/jsx-in-depth.html), but without the virtual DOM.
8
+
9
+ The EJX tag syntax is as follows:
10
+
11
+ * `<% ... %>` silently evaluates the statement inside the tags.
12
+ * `<%= ... %>` evaluates the expression inside the tags, escapes and inserts it
13
+ into the template output.
14
+ * `<%- ... %>` behaves like `<%= ... %>` but does not escape it's output.
15
+
16
+ The functions compiled with EJX will return an array containing `Node` objects
17
+ and/or `DOMString` which can be appended to a Node via `Node.append(...)`
18
+
19
+ Examples
20
+ --------
21
+
22
+ To compile an EJX template into a Javascript module pass the template to `EJX.compile`:
23
+
24
+ ```ruby
25
+ EJX.compile("Hello <span><%= name %></span>")
26
+ # => import {append as __ejx_append} from 'ejx';
27
+ # =>
28
+ # => export default async function (locals) {
29
+ # => var __output = [], __promises = [];
30
+ # =>
31
+ # => __output.push("Hello ");
32
+ # => var __a = document.createElement("span");
33
+ # => __ejx_append(name, __a, true, __promises);
34
+ # => __ejx_append(__a, __output, false, __promises);
35
+ # =>
36
+ # => await Promise.all(__promises);
37
+ # => return __output;
38
+ # => }
39
+ JS
40
+ ```
41
+
42
+ If a evalation tag (`<%=` or `<%-`) ends with an opening of a function, the
43
+ function returns a compiled template. For example:
44
+
45
+ ```erb
46
+ <% formTag = function(template) {
47
+ var a = document.createElement("form");
48
+ a.append.apply(a, template());
49
+ return a;
50
+ } %>
51
+
52
+ <%= formTag(function () { %>
53
+ <input type="submit" />
54
+ <% }) %>
55
+ ```
56
+
57
+ generates:
58
+
59
+ ```js
60
+ import {append as __ejx_append} from 'ejx';
61
+
62
+ export default async function (locals) {
63
+ var __output = [], __promises = [];
64
+
65
+ formTag = function(template) {
66
+ var a = document.createElement("form");
67
+ a.append.apply(a, template());
68
+ return a;
69
+ }
70
+ var __a = [];
71
+ __ejx_append(formTag(function () {
72
+ var __b = document.createElement("input");
73
+ __b.setAttribute("type", "submit");
74
+ __ejx_append(__b, __a, false, __promises);
75
+ }), __output, true, __promises, __a);
76
+
77
+ await Promise.all(__promises);
78
+ return __output;
79
+ }
80
+ ```
@@ -0,0 +1,23 @@
1
+ class Condenser::EjxTransformer < Condenser::NodeProcessor
2
+
3
+ def initialize(options = {})
4
+ @options = options
5
+ end
6
+
7
+ def self.setup(environment)
8
+ require 'ejx' unless defined?(::EJX)
9
+
10
+ if !environment.path.include?(EJX::ASSET_DIR)
11
+ environment.append_path(EJX::ASSET_DIR)
12
+ end
13
+ end
14
+
15
+ def self.call(environment, input)
16
+ new.call(environment, input)
17
+ end
18
+
19
+ def call(environment, input)
20
+ input[:source] = EJX::Template.new(input[:source], @options).to_module
21
+ end
22
+
23
+ end
@@ -0,0 +1,66 @@
1
+ module EJX
2
+
3
+ class TemplateError < StandardError
4
+ end
5
+
6
+ autoload :Template, File.expand_path('../ejx/template', __FILE__)
7
+
8
+ @@settings = {
9
+ open_tag: '<%',
10
+ close_tag: '%>',
11
+
12
+ open_tag_modifiers: {
13
+ escape: '=',
14
+ unescape: '-',
15
+ comment: '#',
16
+ literal: '%'
17
+ },
18
+
19
+ close_tag_modifiers: {
20
+ trim: '-',
21
+ literal: '%'
22
+ },
23
+
24
+ escape: nil
25
+ }
26
+
27
+ ASSET_DIR = File.join(__dir__, 'ejx', 'assets')
28
+
29
+ VOID_ELEMENTS = [
30
+ 'area',
31
+ 'base',
32
+ 'br',
33
+ 'col',
34
+ 'embed',
35
+ 'hr',
36
+ 'img',
37
+ 'input',
38
+ 'link',
39
+ 'meta',
40
+ 'param',
41
+ 'source',
42
+ 'track',
43
+ 'wbr'
44
+ ]
45
+
46
+ def self.compile(source, options = {})
47
+ EJX::Template.new(source, options).to_module
48
+ end
49
+
50
+ def self.settings
51
+ @@settings
52
+ end
53
+
54
+ def self.settings=(value)
55
+ @@settings = value
56
+ end
57
+ end
58
+
59
+
60
+ if defined?(Condenser)
61
+ Condenser.configure do
62
+ autoload :EjxTransformer, 'condenser/transformers/ejx'
63
+ register_mime_type 'application/ejx', extensions: '.ejx', charset: :unicode
64
+ register_template 'application/ejx', Condenser::EjxTransformer
65
+ end
66
+ end
@@ -0,0 +1,34 @@
1
+ function repalceejx(el, withItems) {
2
+ if ( Array.isArray(withItems) ) {
3
+ withItems.forEach((i) => {
4
+ if (i instanceof Node) {
5
+ el.insertAdjacentElement('beforebegin', i)
6
+ } else {
7
+ // el.insertAdjacentHTML()
8
+ el.insertAdjacentText('beforebegin', i)
9
+ }
10
+ })
11
+ el.remove();
12
+ } else {
13
+ el.replaceWith(withItems);
14
+ }
15
+ }
16
+
17
+ export function append(items, to, escape, promises, promise_results) {
18
+ if ( Array.isArray(items) ) {
19
+ items.forEach((i) => append(i, to, escape, promises));
20
+ } else {
21
+ let method = Array.isArray(to) ? 'push' : 'append';
22
+
23
+ if (items instanceof Promise) {
24
+ let holder = document.createElement( "div");
25
+ to[method](holder);
26
+ promises.push( items.then((resolvedItems) => {
27
+ repalceejx(holder, promise_results || resolvedItems)
28
+ }));
29
+ } else {
30
+ to[method](items);
31
+ }
32
+
33
+ }
34
+ }
@@ -0,0 +1,206 @@
1
+ class EJX::Template
2
+
3
+ autoload :JS, File.expand_path('../template/js', __FILE__)
4
+ autoload :Base, File.expand_path('../template/base', __FILE__)
5
+ autoload :String, File.expand_path('../template/string', __FILE__)
6
+ autoload :HTMLTag, File.expand_path('../template/html_tag', __FILE__)
7
+ autoload :ParseHelpers, File.expand_path('../template/parse_helpers', __FILE__)
8
+ autoload :Subtemplate, File.expand_path('../template/subtemplate', __FILE__)
9
+ autoload :VarGenerator, File.expand_path('../template/var_generator', __FILE__)
10
+
11
+ include EJX::Template::ParseHelpers
12
+
13
+ attr_accessor :source
14
+
15
+ def initialize(source, options={})
16
+ @source = source.strip
17
+
18
+ @js_start_tags = [options[:open_tag] || EJX.settings[:open_tag]]
19
+ @html_start_tags = ['<']
20
+ @start_tags = @js_start_tags + @html_start_tags
21
+
22
+ @js_close_tags = [options[:close_tag] || EJX.settings[:close_tag]]
23
+ @html_close_tags = ['/>', '>']
24
+ @close_tags = @js_close_tags + @html_close_tags
25
+
26
+ @open_tag_modifiers = EJX.settings[:open_tag_modifiers].merge(options[:open_tag_modifiers] || {})
27
+ @close_tag_modifiers = EJX.settings[:close_tag_modifiers].merge(options[:close_tag_modifiers] || {})
28
+
29
+ @escape = options[:escape]
30
+ process
31
+ end
32
+
33
+ def process
34
+ seek(0)
35
+ @tree = [EJX::Template::Base.new(escape: @escape)]
36
+ @stack = [:str]
37
+
38
+ while !eos?
39
+ case @stack.last
40
+ when :str
41
+ scan_until(Regexp.new("(#{@start_tags.map{|s| Regexp.escape(s) }.join('|')}|\\z)"))
42
+ if !pre_match.strip.empty?
43
+ @tree.last.children << EJX::Template::String.new(pre_match)
44
+ end
45
+
46
+ if !matched.nil?
47
+ if @js_start_tags.include?(matched)
48
+ @stack << :js
49
+ elsif @html_start_tags.include?(matched)
50
+ @stack << :html_tag
51
+ end
52
+ end
53
+ when :js
54
+ scan_until(Regexp.new("(#{@js_close_tags.map{|s| Regexp.escape(s) }.join('|')})"))
55
+ pm = pre_match
56
+ open_modifier = @open_tag_modifiers.find { |k,v| pm.start_with?(v) }&.first
57
+ close_modifier = @close_tag_modifiers.find { |k,v| matched.end_with?(v) }&.first
58
+ pm.slice!(0, open_modifier[1].size) if open_modifier
59
+ pm.slice!(pm.size - close_modifier[1].size, close_modifier[1].size) if close_modifier
60
+
61
+ if pm =~ /\A\s*import/
62
+ import = pm.strip
63
+ import += ';' if !import.end_with?(';')
64
+ @tree.first.imports << import
65
+ @stack.pop
66
+ elsif @tree.last.is_a?(EJX::Template::Subtemplate) && pm.match(/\A\s*\}\s*\)/m) && !pm.match(/\A\s*\}.*\{\s*\Z/m)
67
+ subtemplate = @tree.pop
68
+ subtemplate.children << pm.strip
69
+ @tree.last.children << subtemplate
70
+ @stack.pop
71
+ elsif pm.match(/function\s*\([^\)]*\)\s*\{\s*\Z/m)
72
+ @tree << EJX::Template::Subtemplate.new(pm.strip, [open_modifier, close_modifier].compact)
73
+ @stack.pop
74
+ else
75
+ value = EJX::Template::JS.new(pm.strip, [open_modifier, close_modifier].compact)
76
+
77
+ @stack.pop
78
+ case @stack.last
79
+ when :html_tag
80
+ @tree.last.tag_name = value
81
+ push(:html_tag_attr_key)
82
+ when :html_tag_attr_key
83
+ @tree.last.attrs << value
84
+ when :html_tag_attr_value
85
+ @tree.last.attrs << {@stack_info.last => value}
86
+ @stack.pop
87
+ else
88
+ @tree.last.children << value
89
+ end
90
+ end
91
+ when :html_tag
92
+ scan_until(Regexp.new("(#{@js_start_tags.map{|s| Regexp.escape(s) }.join('|')}|\\/|[^\\s>]+)"))
93
+ if @js_start_tags.include?(matched)
94
+ @tree << EJX::Template::HTMLTag.new
95
+ @stack << :js
96
+ elsif matched == '/'
97
+ @stack.pop
98
+ @stack << :html_close_tag
99
+ else
100
+ @tree << EJX::Template::HTMLTag.new
101
+ @tree.last.tag_name = matched
102
+ @stack << :html_tag_attr_key
103
+ end
104
+ when :html_close_tag
105
+ scan_until(Regexp.new("(#{@js_start_tags.map{|s| Regexp.escape(s) }.join('|')}|[^\\s>]+)"))
106
+
107
+ if @js_start_tags.include?(matched)
108
+ @stack << :js
109
+ else
110
+ el = @tree.pop
111
+ if el.tag_name != matched
112
+ raise EJX::TemplateError.new("Expected to close #{el.tag_name} tag, instead closed #{matched}\n#{cursor}")
113
+ end
114
+ @tree.last.children << el
115
+ scan_until(Regexp.new("(#{@html_close_tags.map{|s| Regexp.escape(s) }.join('|')})"))
116
+ @stack.pop
117
+ end
118
+ when :html_tag_attr_key
119
+ scan_until(Regexp.new("(#{(@js_start_tags+@html_close_tags).map{|s| Regexp.escape(s) }.join('|')}|[^\\s=>]+)"))
120
+ if @js_start_tags.include?(matched)
121
+ @stack << :js
122
+ elsif @html_close_tags.include?(matched)
123
+ if matched == '/>' || EJX::VOID_ELEMENTS.include?(@tree.last.tag_name)
124
+ el = @tree.pop
125
+ @tree.last.children << el
126
+ @stack.pop
127
+ @stack.pop
128
+ else
129
+ @stack << :str
130
+ end
131
+ else
132
+ key = if matched.start_with?('"') && matched.end_with?('"')
133
+ matched[1..-2]
134
+ elsif matched.start_with?('"') && matched.end_with?('"')
135
+ matched[1..-2]
136
+ else
137
+ matched
138
+ end
139
+ @tree.last.attrs << key
140
+ @stack << :html_tag_attr_value_tx
141
+ end
142
+ when :html_tag_attr_value_tx
143
+ scan_until(Regexp.new("(#{(@js_start_tags+@html_close_tags).map{|s| Regexp.escape(s) }.join('|')}|=|\\S)"))
144
+ tag_key = @tree.last.attrs.pop
145
+ if @js_start_tags.include?(matched)
146
+ @stack << :js
147
+ elsif @html_close_tags.include?(matched)
148
+ el = @tree.last
149
+ el.attrs << tag_key
150
+ if EJX::VOID_ELEMENTS.include?(el.tag_name)
151
+ @tree.pop
152
+ @tree.last.children << el
153
+ end
154
+ @stack.pop
155
+ @stack.pop
156
+ @stack.pop
157
+ elsif matched == '='
158
+ @stack.pop
159
+ @tree.last.attrs << tag_key
160
+ @stack << :html_tag_attr_value
161
+ else
162
+ @stack.pop
163
+ @tree.last.attrs << tag_key
164
+ rewind(1)
165
+ end
166
+
167
+ when :html_tag_attr_value
168
+ scan_until(Regexp.new("(#{(@js_start_tags+@html_close_tags).map{|s| Regexp.escape(s) }.join('|')}|'|\"|\\S+)"))
169
+
170
+ if @js_start_tags.include?(matched)
171
+ push(:js)
172
+ elsif matched == '"'
173
+ @stack.pop
174
+ @stack << :html_tag_attr_value_double_quoted
175
+ elsif matched == "'"
176
+ @stack.pop
177
+ @stack << :html_tag_attr_value_single_quoted
178
+ else
179
+ @stack.pop
180
+ key = @tree.last.attrs.pop
181
+ @tree.last.namespace = matched if key == 'xmlns'
182
+ @tree.last.attrs << { key => matched }
183
+ end
184
+ when :html_tag_attr_value_double_quoted
185
+ scan_until(/[^\"]*/)
186
+ key = @tree.last.attrs.pop
187
+ @tree.last.namespace = matched if key == 'xmlns'
188
+ @tree.last.attrs << { key => matched }
189
+ scan_until(/\"/)
190
+ @stack.pop
191
+ when :html_tag_attr_value_single_quoted
192
+ scan_until(/[^']*/)
193
+ key = @tree.last.attrs.pop
194
+ @tree.last.namespace = matched if key == 'xmlns'
195
+ @tree.last.attrs << { key => matched }
196
+ scan_until(/'/)
197
+ @stack.pop
198
+ end
199
+ end
200
+ end
201
+
202
+ def to_module
203
+ @tree.first.to_module
204
+ end
205
+
206
+ end
@@ -0,0 +1,41 @@
1
+ class EJX::Template::Base
2
+
3
+ attr_accessor :children, :imports
4
+
5
+ def initialize(escape: nil)
6
+ @children = []
7
+ @escape = escape
8
+ @imports = []
9
+ end
10
+
11
+ def to_module
12
+ var_generator = EJX::Template::VarGenerator.new
13
+
14
+ output = if @escape
15
+ "import {" + @escape.split('.').reverse.join(" as escape} from '") + "';\n"
16
+ else
17
+ "import {append as __ejx_append} from 'ejx';\n"
18
+ end
19
+
20
+ @imports.each do |import|
21
+ output << import << "\n"
22
+ end
23
+
24
+ output << "\nexport default async function (locals) {\n"
25
+ output << " var __output = [], __promises = [];\n \n"
26
+
27
+ @children.each do |child|
28
+ output << case child
29
+ when EJX::Template::String
30
+ " __output.push(#{child.to_js});\n"
31
+ else
32
+ child.to_js(var_generator: var_generator)
33
+ end
34
+ end
35
+ output << "\n await Promise.all(__promises);\n"
36
+ output << " return __output;\n"
37
+ output << "}"
38
+ output
39
+ end
40
+
41
+ end
@@ -0,0 +1,53 @@
1
+ class EJX::Template::HTMLTag
2
+
3
+ attr_accessor :tag_name, :attrs, :children, :namespace
4
+
5
+ def initialize
6
+ @attrs = []
7
+ @children = []
8
+ end
9
+
10
+ def to_s
11
+ @value
12
+ end
13
+
14
+ def inspect
15
+ "#<EJX::HTMLTag:#{self.object_id} @tag_name=#{tag_name}>"
16
+ end
17
+
18
+ def to_js(append: "__output", var_generator:, indentation: 4, namespace: nil)
19
+ namespace ||= self.namespace
20
+
21
+ output_var = var_generator.next
22
+ js = "#{' '*indentation}var #{output_var} = document.createElement"
23
+ js << if namespace
24
+ "NS(#{JSON.generate(namespace)}, #{JSON.generate(tag_name)});\n"
25
+ else
26
+ "(#{JSON.generate(tag_name)});\n"
27
+ end
28
+
29
+ @attrs.each do |attr|
30
+ if attr.is_a?(Hash)
31
+ attr.each do |k, v|
32
+ js << "#{' '*indentation}#{output_var}.setAttribute(#{JSON.generate(k)}, #{JSON.generate(v)});\n"
33
+ end
34
+ else
35
+ js << "#{' '*indentation}#{output_var}.setAttribute(#{JSON.generate(attr)}, \"\");\n"
36
+ end
37
+ end
38
+
39
+ @children.each do |child|
40
+ js << if child.is_a?(EJX::Template::String)
41
+ "#{' '*indentation}__ejx_append(#{child.to_js}, #{output_var}, false, __promises);\n"
42
+ elsif child.is_a?(EJX::Template::HTMLTag)
43
+ child.to_js(var_generator: var_generator, indentation: indentation, append: output_var, namespace: namespace)
44
+ else
45
+ child.to_js(var_generator: var_generator, indentation: indentation, append: output_var)
46
+ end
47
+ end
48
+
49
+ js << "#{' '*indentation}__ejx_append(#{output_var}, #{append}, false, __promises);\n"
50
+ js
51
+ end
52
+
53
+ end
@@ -0,0 +1,19 @@
1
+ class EJX::Template::JS
2
+
3
+ def initialize(value, modifiers)
4
+ @modifiers = modifiers
5
+ @value = value
6
+ end
7
+
8
+ def to_js(indentation: 4, var_generator: nil, append: "__output")
9
+ output = @value
10
+
11
+ if @modifiers.include? :escape
12
+ "#{' '*indentation}__ejx_append(#{output}, #{append}, true, __promises);\n"
13
+ elsif @modifiers.include? :unescape
14
+ "#{' '*indentation}__ejx_append(#{output}, #{append}, false, __promises);\n"
15
+ elsif !@modifiers.include? :comment
16
+ "#{' '*indentation}#{output}\n"
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,44 @@
1
+ module EJX::Template::ParseHelpers
2
+
3
+ attr_accessor :matched
4
+
5
+ def eos?
6
+ @index >= @source.size
7
+ end
8
+
9
+ def scan_until(r)
10
+ index = @source.index(r, @index)
11
+ match = @source.match(r, @index)
12
+ @matched = match.to_s
13
+ @old_index = @index
14
+ @index = index + @matched.size
15
+ match
16
+ end
17
+
18
+ def pre_match
19
+ @source[@old_index...(@index-@matched.size)]
20
+ end
21
+
22
+ def rewind(by)
23
+ @index -= 1
24
+ end
25
+
26
+ def seek(pos)
27
+ @old_index = nil
28
+ @matched = nil
29
+ @index = pos
30
+ end
31
+
32
+ def current_line
33
+ start = (@source.rindex("\n", @old_index) || 0) + 1
34
+ uptop = @source.index("\n", @index) || (@old_index + @matched.length)
35
+ @source[start..uptop]
36
+ end
37
+
38
+ def cursor
39
+ start = (@source.rindex("\n", @old_index) || 0) + 1
40
+ uptop = @source.index("\n", @index) || (@old_index + @matched.length)
41
+ lineno = @source[0..start].count("\n") + 1
42
+ "#{lineno.to_s.rjust(4)}: " + @source[start..uptop] + "\n #{'-'* (@old_index-start)}#{'^'*(@matched.length)}"
43
+ end
44
+ end
@@ -0,0 +1,13 @@
1
+ require 'json'
2
+
3
+ class EJX::Template::String
4
+
5
+ def initialize(value)
6
+ @value = value
7
+ end
8
+
9
+ def to_js
10
+ JSON.generate(@value)
11
+ end
12
+
13
+ end
@@ -0,0 +1,33 @@
1
+ class EJX::Template::Subtemplate
2
+
3
+ attr_reader :children
4
+
5
+ def initialize(opening, modifiers)
6
+ @children = [opening]
7
+ @modifiers = modifiers
8
+ end
9
+
10
+ def to_js(indentation: 4, var_generator: nil, append: "__output")
11
+ output_var = var_generator.next
12
+ output = "#{' '*indentation}var #{output_var} = [];\n"
13
+ output << "#{' '*indentation}__ejx_append("
14
+ output << @children.first
15
+ output << "\n"
16
+
17
+ # var_generator ||= EJX::Template::VarGenerator.new
18
+ @children[1..-2].each do |child|
19
+ output << case child
20
+ when EJX::Template::String
21
+ "#{' '*(indentation+4)}__ejx_append(#{child.to_js}, #{output_var}, false, __promises);\n"
22
+ else
23
+ child.to_js(indentation: indentation + 4, var_generator: var_generator, append: output_var)
24
+ end
25
+ end
26
+ output << ' '*indentation
27
+ output << @children.last
28
+ output << ", #{append}, true, __promises, #{output_var});\n"
29
+
30
+ output
31
+ end
32
+
33
+ end
@@ -0,0 +1,10 @@
1
+ class EJX::Template::VarGenerator
2
+ def initialize
3
+ @current = nil
4
+ end
5
+
6
+ def next
7
+ @current = @current.nil? ? '__a' : @current.next
8
+ @current
9
+ end
10
+ end
@@ -0,0 +1,3 @@
1
+ module EJX
2
+ VERSION = '0.1'
3
+ end
metadata ADDED
@@ -0,0 +1,115 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ejx
3
+ version: !ruby/object:Gem::Version
4
+ version: '0.1'
5
+ platform: ruby
6
+ authors:
7
+ - Jonathan Bracy
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-04-30 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: minitest-reporters
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: |
70
+ Compile EJX (Embedded JavaScript) templates to Javascript
71
+ functions with Ruby.
72
+ email:
73
+ - jonbracy@gmail.com
74
+ executables: []
75
+ extensions: []
76
+ extra_rdoc_files: []
77
+ files:
78
+ - LICENSE
79
+ - README.md
80
+ - lib/condenser/transformers/ejx.rb
81
+ - lib/ejx.rb
82
+ - lib/ejx/assets/ejx.js
83
+ - lib/ejx/template.rb
84
+ - lib/ejx/template/base.rb
85
+ - lib/ejx/template/html_tag.rb
86
+ - lib/ejx/template/js.rb
87
+ - lib/ejx/template/parse_helpers.rb
88
+ - lib/ejx/template/string.rb
89
+ - lib/ejx/template/subtemplate.rb
90
+ - lib/ejx/template/var_generator.rb
91
+ - lib/ejx/version.rb
92
+ homepage: https://github.com/malomalo/ejx
93
+ licenses:
94
+ - MIT
95
+ metadata: {}
96
+ post_install_message:
97
+ rdoc_options: []
98
+ require_paths:
99
+ - lib
100
+ required_ruby_version: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ required_rubygems_version: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ requirements: []
111
+ rubygems_version: 3.1.2
112
+ signing_key:
113
+ specification_version: 4
114
+ summary: EJX Template Compiler
115
+ test_files: []