express_templates 0.11.10 → 0.11.11
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 +4 -4
- data/README.md +45 -110
- data/lib/express_templates/compiler.rb +8 -3
- data/lib/express_templates/components/base.rb +14 -14
- data/lib/express_templates/components/forms/basic_fields.rb +0 -7
- data/lib/express_templates/components/forms/form_component.rb +1 -1
- data/lib/express_templates/template/handler.rb +0 -2
- data/lib/express_templates/version.rb +1 -1
- data/lib/express_templates.rb +2 -3
- data/test/dummy/app/views/hello/show.html.et +2 -2
- data/test/express_templates_test.rb +20 -0
- data/test/test_helper.rb +7 -3
- metadata +6 -30
- data/LICENSE +0 -21
- data/lib/express_templates/indenter.rb +0 -47
- data/lib/express_templates/interpolator.rb +0 -36
- data/test/indenter_test.rb +0 -27
- data/test/interpolator_test.rb +0 -80
- data/test/performance_test.rb +0 -97
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3e40896f62363f0d0d56561edadcfc3bed0ff65c
|
|
4
|
+
data.tar.gz: eed5459b88dbba34fbbb3b333aa3d7b84deb7bb6
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 730210a7b8ea70b45d4668d7da93e0756e52f1e1a3771919b547e74e75958efac1baa6c374a100f04f9da7a710e9dde9265b76265daf704065d761c0c88bde16
|
|
7
|
+
data.tar.gz: e1d8537af4ef7094e9d29ae3b67f9083dfb3e14aa583849811b07ba741bf16b5cf1d684b55fa973cc469e8a5d4c4d319a4b50d0e1eadf3cbbd85902e0aeeeb87
|
data/README.md
CHANGED
|
@@ -1,142 +1,77 @@
|
|
|
1
|
-
|
|
1
|
+
## ExpressTemplates - Reusable view components in Ruby
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
### Write templates in Ruby
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
this gem now uses [ActiveAdmin's arbre](https://github.com/activeadmin/arbre). Arbre is widely
|
|
7
|
-
used as part of ActiveAdmin, has a long history and many contributors and is conceptually much simpler.
|
|
8
|
-
|
|
9
|
-
## Usage
|
|
10
|
-
|
|
11
|
-
Add this to your gemfile:
|
|
5
|
+
Use a declarative style of Ruby to write template code based on [Arbre](https://github.com/aelogica/arbre).
|
|
12
6
|
|
|
13
7
|
```ruby
|
|
14
|
-
|
|
8
|
+
content_for :title, "Hello, world"
|
|
9
|
+
|
|
10
|
+
div {
|
|
11
|
+
h1 "#{hello}"
|
|
12
|
+
p 'Find me in app/views/hello/show.html.et'
|
|
13
|
+
}
|
|
15
14
|
```
|
|
16
15
|
|
|
17
|
-
|
|
16
|
+
[Learn more](https://github.com/aelogica/express-gems/wiki/Express-Templates-HOWTO)
|
|
18
17
|
|
|
19
|
-
|
|
18
|
+
### Use Rails' form tag helpers
|
|
20
19
|
|
|
21
20
|
```ruby
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
title {
|
|
27
|
-
content_for(:title)
|
|
28
|
-
}
|
|
29
|
-
stylesheet_link_tag "application", media: 'all', 'data-turbolinks-track' => true
|
|
30
|
-
csrf_meta_tags
|
|
31
|
-
}
|
|
32
|
-
body {
|
|
33
|
-
current_arbre_element.add_child yield
|
|
34
|
-
javascript_include_tag "application"
|
|
21
|
+
form(action: invites_path, method: "POST") {
|
|
22
|
+
div(class: 'form-group') {
|
|
23
|
+
label_tag(:invite_code, "Invite Code:")
|
|
24
|
+
text_field_tag('invite_code', '', class: 'form-control')
|
|
35
25
|
}
|
|
36
26
|
}
|
|
37
27
|
```
|
|
38
28
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
Set your editor syntax for .et files to Ruby.
|
|
42
|
-
|
|
43
|
-
You can now utilize components which are found with documentation and examples in <tt>ExpressTemplates::Components</tt>.
|
|
44
|
-
|
|
45
|
-
Components are the real strength of both arbre and express_templates.
|
|
46
|
-
|
|
47
|
-
express_templates now *is* arbre + some components + some conventions. ExpressTemplates::Components::Base provides a little syntactic sugar in the form of the emits class method.
|
|
29
|
+
### Compose templates to build components
|
|
48
30
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
Control flow should only be used in Components. This is currently not enforced but it will be in the future.
|
|
52
|
-
|
|
53
|
-
The purpose of express_templates is to provide a foundation for a library of reusable UX components which we can enhance for drag-and-drop style UX construction and template editing.
|
|
54
|
-
|
|
55
|
-
## Dependencies
|
|
56
|
-
|
|
57
|
-
To set a label's "for" value, you must use a version of arbre that allows for this. Place this in your app:
|
|
31
|
+
Components are reusable pieces of user interface code. See [Express UI](https://github.com/express-gems/tree/master/express_ui).
|
|
58
32
|
|
|
59
33
|
```ruby
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
li %Q(#{@three})
|
|
76
|
-
}
|
|
34
|
+
class PageHeader < ExpressTemplates::Components::Base
|
|
35
|
+
|
|
36
|
+
contains -> {
|
|
37
|
+
if content_for?(:page_header)
|
|
38
|
+
h1 {
|
|
39
|
+
content_for(:page_header)
|
|
40
|
+
}
|
|
41
|
+
end
|
|
42
|
+
if content_for?(:page_header_lead)
|
|
43
|
+
para(class: 'lead') {
|
|
44
|
+
content_for(:page_header_lead)
|
|
45
|
+
}
|
|
46
|
+
end
|
|
47
|
+
}
|
|
48
|
+
end
|
|
77
49
|
```
|
|
78
50
|
|
|
79
|
-
|
|
51
|
+
[Learn more](https://example.com)
|
|
80
52
|
|
|
81
|
-
|
|
82
|
-
<ul>
|
|
83
|
-
<li>one</li>
|
|
84
|
-
<li>two</li>
|
|
85
|
-
<li>three</li>
|
|
86
|
-
</ul>
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
## Components
|
|
53
|
+
### Philosophy
|
|
90
54
|
|
|
91
|
-
|
|
55
|
+
1. It's just Ruby.
|
|
92
56
|
|
|
93
|
-
|
|
57
|
+
2. Write less markup code with reusable components.
|
|
94
58
|
|
|
95
|
-
|
|
59
|
+
[Learn more](https://example.com)
|
|
96
60
|
|
|
97
|
-
|
|
98
|
-
@list = %w(one two three)
|
|
99
|
-
```
|
|
61
|
+
### Download and installation
|
|
100
62
|
|
|
101
|
-
|
|
63
|
+
Download the latest version of ExpressTemplates from RubyGems:
|
|
102
64
|
|
|
103
|
-
```ruby
|
|
104
|
-
class ListComponent < ExpressTemplates::Components::Base
|
|
105
|
-
emits -> {
|
|
106
|
-
ul {
|
|
107
|
-
# assumes view provides list
|
|
108
|
-
list.each do |item|
|
|
109
|
-
li {
|
|
110
|
-
item
|
|
111
|
-
}
|
|
112
|
-
end
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
end
|
|
116
65
|
```
|
|
117
|
-
|
|
118
|
-
This would be used in a view template just as if it were a tag, like so:
|
|
119
|
-
|
|
120
|
-
```ruby
|
|
121
|
-
div(class: "active") {
|
|
122
|
-
list_component
|
|
123
|
-
}
|
|
66
|
+
$ gem install express_templates
|
|
124
67
|
```
|
|
125
68
|
|
|
126
|
-
|
|
69
|
+
Source code is on GitHub as part of the express-gems project:
|
|
127
70
|
|
|
128
|
-
|
|
129
|
-
<div class="active">
|
|
130
|
-
<ul>
|
|
131
|
-
<li>one</li>
|
|
132
|
-
<li>two</li>
|
|
133
|
-
<li>three</li>
|
|
134
|
-
</ul>
|
|
135
|
-
</div>
|
|
136
|
-
```
|
|
71
|
+
* https://github.com/aelogica/express-gems/tree/master/express_templates
|
|
137
72
|
|
|
138
|
-
|
|
73
|
+
### License
|
|
139
74
|
|
|
140
|
-
ExpressTemplates is
|
|
75
|
+
ExpressTemplates is released under the MIT license:
|
|
141
76
|
|
|
142
|
-
|
|
77
|
+
* http://www.opensource.org/licenses/MIT
|
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
module ExpressTemplates
|
|
2
2
|
module Compiler
|
|
3
3
|
def compile(template_or_src=nil, &block)
|
|
4
|
-
|
|
5
4
|
template, src = _normalize(template_or_src)
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
%Q{
|
|
6
|
+
assigns.merge!(template_virtual_path: @virtual_path)
|
|
7
|
+
if defined?(local_assigns)
|
|
8
|
+
Arbre::Context.new(assigns.merge(local_assigns), self) { #{src || block.source_body} }.to_s
|
|
9
|
+
else
|
|
10
|
+
Arbre::Context.new(assigns, self) { #{src || block.source_body} }.to_s
|
|
11
|
+
end
|
|
12
|
+
}
|
|
8
13
|
end
|
|
9
14
|
|
|
10
15
|
private
|
|
@@ -7,9 +7,11 @@ module ExpressTemplates
|
|
|
7
7
|
#
|
|
8
8
|
module Components
|
|
9
9
|
|
|
10
|
-
# Components::Base is the base class for ExpressTemplates view components.
|
|
10
|
+
# ExpressTemplates::Components::Base is the base class for ExpressTemplates view components.
|
|
11
11
|
#
|
|
12
|
+
# Subclasses can attach hooks.
|
|
12
13
|
#
|
|
14
|
+
# An ET component may adopt other capabilities (e.g. support RESTful options).
|
|
13
15
|
class Base < Arbre::Component
|
|
14
16
|
|
|
15
17
|
class_attribute :before_build_hooks
|
|
@@ -32,9 +34,7 @@ module ExpressTemplates
|
|
|
32
34
|
|
|
33
35
|
abstract_component
|
|
34
36
|
|
|
35
|
-
#
|
|
36
|
-
# in Express Designer unless parent is present
|
|
37
|
-
#
|
|
37
|
+
# Define the parent component (i.e., can't be used in Express Designer unless parent is present)
|
|
38
38
|
@parent_component = nil
|
|
39
39
|
|
|
40
40
|
def self.require_parent(component)
|
|
@@ -46,14 +46,18 @@ module ExpressTemplates
|
|
|
46
46
|
@parent_component
|
|
47
47
|
end
|
|
48
48
|
|
|
49
|
+
# Defines an instance method using Arbre's BuilderMethods
|
|
50
|
+
#
|
|
51
|
+
# @param String method_name (component)
|
|
52
|
+
#
|
|
53
|
+
# @param Class klass
|
|
49
54
|
def self.builder_method_and_class(method_name, klass)
|
|
50
55
|
Arbre::Element::BuilderMethods.class_eval <<-EOF, __FILE__, __LINE__
|
|
51
|
-
def #{method_name}(*args, &block)
|
|
52
|
-
insert_tag ::#{klass.name}, *args, &block
|
|
53
|
-
end
|
|
56
|
+
def #{method_name}(*args, &block) # def checkbox(*args, &block)
|
|
57
|
+
insert_tag ::#{klass.name}, *args, &block # insert_tag ::Checkbox, *args, &block
|
|
58
|
+
end # end
|
|
54
59
|
EOF
|
|
55
60
|
self.builder_method_name = method_name
|
|
56
|
-
# puts "added #{method_name} -> #{klass.name}"
|
|
57
61
|
end
|
|
58
62
|
|
|
59
63
|
def initialize(*)
|
|
@@ -100,12 +104,9 @@ module ExpressTemplates
|
|
|
100
104
|
}
|
|
101
105
|
end
|
|
102
106
|
|
|
103
|
-
def resource
|
|
104
|
-
helpers.resource
|
|
105
|
-
end
|
|
106
|
-
|
|
107
107
|
def self.inherited(subclass)
|
|
108
|
-
|
|
108
|
+
method_name = subclass.to_s.demodulize.underscore
|
|
109
|
+
subclass.builder_method_and_class(method_name, subclass)
|
|
109
110
|
end
|
|
110
111
|
|
|
111
112
|
def self.builder_method(name)
|
|
@@ -149,7 +150,6 @@ module ExpressTemplates
|
|
|
149
150
|
def self._default_classes=(classes)
|
|
150
151
|
@default_classes = classes
|
|
151
152
|
end
|
|
152
|
-
|
|
153
153
|
end
|
|
154
154
|
end
|
|
155
155
|
end
|
|
@@ -21,13 +21,6 @@ RUBY
|
|
|
21
21
|
end
|
|
22
22
|
end
|
|
23
23
|
|
|
24
|
-
# class Email < FormComponent
|
|
25
|
-
# contains {
|
|
26
|
-
# label_tag label_name, label_text
|
|
27
|
-
# email_field field_name_attribute, field_value, field_helper_options
|
|
28
|
-
# }
|
|
29
|
-
# end
|
|
30
|
-
|
|
31
24
|
class File < FormComponent
|
|
32
25
|
contains {
|
|
33
26
|
label_tag(label_name, label_text)
|
|
@@ -8,8 +8,6 @@ module ExpressTemplates
|
|
|
8
8
|
end
|
|
9
9
|
|
|
10
10
|
def call(template)
|
|
11
|
-
# call ripper stuff method
|
|
12
|
-
|
|
13
11
|
# returns a string to be eval'd
|
|
14
12
|
source = "(#{ExpressTemplates.compile(template)}).html_safe"
|
|
15
13
|
warn_contains_logic(source) if ENV['NO_TEMPLATE_WARN'].nil? # pass the source code
|
data/lib/express_templates.rb
CHANGED
|
@@ -3,16 +3,15 @@ module ExpressTemplates
|
|
|
3
3
|
require 'arbre/patches'
|
|
4
4
|
require 'core_extensions/proc'
|
|
5
5
|
require 'core_extensions/string'
|
|
6
|
-
require 'express_templates/indenter'
|
|
7
6
|
require 'express_templates/components'
|
|
8
7
|
require 'express_templates/template/handler'
|
|
9
8
|
require 'express_templates/renderer'
|
|
10
9
|
require 'express_templates/compiler'
|
|
11
|
-
|
|
10
|
+
|
|
12
11
|
extend Renderer
|
|
13
12
|
extend Compiler
|
|
13
|
+
|
|
14
14
|
if defined?(Rails)
|
|
15
15
|
::ActionView::Template.register_template_handler :et, ExpressTemplates::Template::Handler
|
|
16
16
|
end
|
|
17
|
-
|
|
18
17
|
end
|
|
@@ -20,4 +20,24 @@ class ExpressTemplatesTest < ActiveSupport::TestCase
|
|
|
20
20
|
assert_equal "<ul>\n <li>one</li>\n <li>two</li>\n <li>three</li>\n</ul>\n", result
|
|
21
21
|
end
|
|
22
22
|
|
|
23
|
+
test "ExpressTemplates.render renders a template with local_assigns" do
|
|
24
|
+
class Foo
|
|
25
|
+
def assigns
|
|
26
|
+
{}
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def local_assigns
|
|
30
|
+
{}
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
f = Foo.new
|
|
35
|
+
|
|
36
|
+
result = ExpressTemplates.render(f) do
|
|
37
|
+
para { 'All your base are belong to us.' }
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
assert_equal "<p>All your base are belong to us.</p>\n", result
|
|
41
|
+
end
|
|
42
|
+
|
|
23
43
|
end
|
data/test/test_helper.rb
CHANGED
|
@@ -21,7 +21,6 @@ end
|
|
|
21
21
|
ECB = ExpressTemplates::Components::Base
|
|
22
22
|
ETC = ExpressTemplates::Components
|
|
23
23
|
ET = ExpressTemplates
|
|
24
|
-
Interpolator = ExpressTemplates::Interpolator
|
|
25
24
|
|
|
26
25
|
require 'arbre'
|
|
27
26
|
Tag = Arbre::HTML::Tag
|
|
@@ -47,7 +46,6 @@ end
|
|
|
47
46
|
|
|
48
47
|
module ActiveSupport
|
|
49
48
|
class TestCase
|
|
50
|
-
|
|
51
49
|
class Context
|
|
52
50
|
def assigns
|
|
53
51
|
{}
|
|
@@ -61,12 +59,15 @@ module ActiveSupport
|
|
|
61
59
|
def arbre(additional_assigns = {}, &block)
|
|
62
60
|
Arbre::Context.new assigns.merge(additional_assigns), helpers, &block
|
|
63
61
|
end
|
|
62
|
+
|
|
64
63
|
def assigns
|
|
65
64
|
@arbre_assigns ||={}
|
|
66
65
|
end
|
|
66
|
+
|
|
67
67
|
def helpers
|
|
68
68
|
mock_action_view
|
|
69
69
|
end
|
|
70
|
+
|
|
70
71
|
def mock_action_view &block
|
|
71
72
|
controller = ActionView::TestCase::TestController.new
|
|
72
73
|
ActionView::Base.send :include, ActionView::Helpers
|
|
@@ -91,7 +92,6 @@ module ActiveSupport
|
|
|
91
92
|
gender: 'Male'
|
|
92
93
|
)
|
|
93
94
|
end
|
|
94
|
-
|
|
95
95
|
end
|
|
96
96
|
end
|
|
97
97
|
|
|
@@ -190,3 +190,7 @@ end
|
|
|
190
190
|
false
|
|
191
191
|
end
|
|
192
192
|
end
|
|
193
|
+
|
|
194
|
+
# Setup code coverage
|
|
195
|
+
require 'simplecov'
|
|
196
|
+
SimpleCov.start if ENV["COVERAGE"]
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: express_templates
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.11.
|
|
4
|
+
version: 0.11.11
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Steven Talcott Smith
|
|
@@ -9,7 +9,7 @@ authors:
|
|
|
9
9
|
autorequire:
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
|
-
date: 2016-
|
|
12
|
+
date: 2016-03-17 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: activesupport
|
|
@@ -25,20 +25,6 @@ dependencies:
|
|
|
25
25
|
- - "~>"
|
|
26
26
|
- !ruby/object:Gem::Version
|
|
27
27
|
version: '4.2'
|
|
28
|
-
- !ruby/object:Gem::Dependency
|
|
29
|
-
name: parslet
|
|
30
|
-
requirement: !ruby/object:Gem::Requirement
|
|
31
|
-
requirements:
|
|
32
|
-
- - "~>"
|
|
33
|
-
- !ruby/object:Gem::Version
|
|
34
|
-
version: '1.6'
|
|
35
|
-
type: :runtime
|
|
36
|
-
prerelease: false
|
|
37
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
38
|
-
requirements:
|
|
39
|
-
- - "~>"
|
|
40
|
-
- !ruby/object:Gem::Version
|
|
41
|
-
version: '1.6'
|
|
42
28
|
- !ruby/object:Gem::Dependency
|
|
43
29
|
name: arbre
|
|
44
30
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -165,9 +151,7 @@ dependencies:
|
|
|
165
151
|
- - ">="
|
|
166
152
|
- !ruby/object:Gem::Version
|
|
167
153
|
version: '0'
|
|
168
|
-
description:
|
|
169
|
-
declartive style of Ruby. With ExpressTemplates you may easily create a library
|
|
170
|
-
of components for use across projects.
|
|
154
|
+
description: Write templates in Ruby for building reusable view components
|
|
171
155
|
email:
|
|
172
156
|
- steve@aelogica.com
|
|
173
157
|
- eumir@aelogica.com
|
|
@@ -175,7 +159,6 @@ executables: []
|
|
|
175
159
|
extensions: []
|
|
176
160
|
extra_rdoc_files: []
|
|
177
161
|
files:
|
|
178
|
-
- LICENSE
|
|
179
162
|
- README.md
|
|
180
163
|
- Rakefile
|
|
181
164
|
- lib/arbre/patches.rb
|
|
@@ -201,8 +184,6 @@ files:
|
|
|
201
184
|
- lib/express_templates/components/forms/select_collection.rb
|
|
202
185
|
- lib/express_templates/components/forms/submit.rb
|
|
203
186
|
- lib/express_templates/components/tree_for.rb
|
|
204
|
-
- lib/express_templates/indenter.rb
|
|
205
|
-
- lib/express_templates/interpolator.rb
|
|
206
187
|
- lib/express_templates/renderer.rb
|
|
207
188
|
- lib/express_templates/template/handler.rb
|
|
208
189
|
- lib/express_templates/version.rb
|
|
@@ -257,9 +238,6 @@ files:
|
|
|
257
238
|
- test/dummy/test/helpers/hello_helper_test.rb
|
|
258
239
|
- test/express_templates_test.rb
|
|
259
240
|
- test/handler_test.rb
|
|
260
|
-
- test/indenter_test.rb
|
|
261
|
-
- test/interpolator_test.rb
|
|
262
|
-
- test/performance_test.rb
|
|
263
241
|
- test/test_helper.rb
|
|
264
242
|
homepage: https://github.com/aelogica/express_templates
|
|
265
243
|
licenses:
|
|
@@ -281,10 +259,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
281
259
|
version: '0'
|
|
282
260
|
requirements: []
|
|
283
261
|
rubyforge_project:
|
|
284
|
-
rubygems_version: 2.
|
|
262
|
+
rubygems_version: 2.5.1
|
|
285
263
|
signing_key:
|
|
286
264
|
specification_version: 4
|
|
287
|
-
summary:
|
|
265
|
+
summary: Reusable view components
|
|
288
266
|
test_files:
|
|
289
267
|
- test/compiler_test.rb
|
|
290
268
|
- test/components/base_test.rb
|
|
@@ -336,7 +314,5 @@ test_files:
|
|
|
336
314
|
- test/dummy/test/helpers/hello_helper_test.rb
|
|
337
315
|
- test/express_templates_test.rb
|
|
338
316
|
- test/handler_test.rb
|
|
339
|
-
- test/indenter_test.rb
|
|
340
|
-
- test/interpolator_test.rb
|
|
341
|
-
- test/performance_test.rb
|
|
342
317
|
- test/test_helper.rb
|
|
318
|
+
has_rdoc:
|
data/LICENSE
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
The MIT License (MIT)
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2014 ÆLOGICA | Build it better here.
|
|
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.
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
module ExpressTemplates
|
|
2
|
-
|
|
3
|
-
# Tracks current indent level scoped to the current thread.
|
|
4
|
-
#
|
|
5
|
-
# May be used to track multiple indents simultaneously through
|
|
6
|
-
# namespacing.
|
|
7
|
-
class Indenter
|
|
8
|
-
|
|
9
|
-
DEFAULT = 2
|
|
10
|
-
WHITESPACE = " "*DEFAULT
|
|
11
|
-
|
|
12
|
-
# Returns whitespace for the named indenter or yields to a block
|
|
13
|
-
# for the named indentor.
|
|
14
|
-
#
|
|
15
|
-
# The block is passed the current whitespace indent.
|
|
16
|
-
#
|
|
17
|
-
# For convenience an optional second parameter is passed to the block
|
|
18
|
-
# containing a newline at the beginning of the indent.
|
|
19
|
-
def self.for name
|
|
20
|
-
if block_given?
|
|
21
|
-
current_indenters[name] += 1
|
|
22
|
-
begin
|
|
23
|
-
indent = WHITESPACE * current_indenters[name]
|
|
24
|
-
yield indent, "\n#{indent}"
|
|
25
|
-
ensure
|
|
26
|
-
if current_indenters[name].eql?(-1)
|
|
27
|
-
# if we have long-lived threads for some reason
|
|
28
|
-
# we want to clean up after ourselves
|
|
29
|
-
current_indenters.delete(name)
|
|
30
|
-
else
|
|
31
|
-
current_indenters[name] -= 1
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
else
|
|
35
|
-
return WHITESPACE * current_indenters[name]
|
|
36
|
-
end
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
private
|
|
40
|
-
# For thread safety, scope indentation to the current thread
|
|
41
|
-
def self.current_indenters
|
|
42
|
-
Thread.current[:indenters] ||= Hash.new {|hsh, key| hsh[key] = -1 }
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
end
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
require 'parslet'
|
|
2
|
-
|
|
3
|
-
module ExpressTemplates
|
|
4
|
-
class Interpolator < Parslet::Parser
|
|
5
|
-
rule(:lbrace) { str('{{') }
|
|
6
|
-
rule(:rbrace) { str('}}') }
|
|
7
|
-
rule(:delim) { lbrace | rbrace }
|
|
8
|
-
rule(:lpart) { (lbrace.absnt? >> any).repeat.as(:lpart) }
|
|
9
|
-
rule(:rpart) { (rbrace.absnt? >> any).repeat.as(:rpart) }
|
|
10
|
-
rule(:expression) { (text_with_interpolations).as(:expression) }
|
|
11
|
-
rule(:interpolation) { (lbrace>>expression>>rbrace).as(:interpolation) }
|
|
12
|
-
rule(:text) { (delim.absnt? >> any).repeat(1) }
|
|
13
|
-
rule(:text_with_interpolations) { (text.as(:text) | interpolation).repeat }
|
|
14
|
-
root(:text_with_interpolations)
|
|
15
|
-
|
|
16
|
-
def self.transform(s)
|
|
17
|
-
begin
|
|
18
|
-
Transformer.new.apply(new.parse(s)).flatten.join
|
|
19
|
-
rescue Parslet::ParseFailed => failure
|
|
20
|
-
puts s
|
|
21
|
-
puts failure.cause.ascii_tree
|
|
22
|
-
raise failure
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
class Transformer < Parslet::Transform
|
|
28
|
-
rule(:interpolation => simple(:expression)) {
|
|
29
|
-
'#{'+expression+'}'
|
|
30
|
-
}
|
|
31
|
-
rule(:expression => sequence(:exp)) do
|
|
32
|
-
exp.map(&:to_s).join.gsub('\\"', '"')
|
|
33
|
-
end
|
|
34
|
-
rule(:text => simple(:s)) { s.to_s }
|
|
35
|
-
end
|
|
36
|
-
end
|
data/test/indenter_test.rb
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
require 'test_helper'
|
|
2
|
-
|
|
3
|
-
class IndenterTest < ActiveSupport::TestCase
|
|
4
|
-
|
|
5
|
-
Indenter = ExpressTemplates::Indenter
|
|
6
|
-
|
|
7
|
-
test ".for(:name) takes a block receiving whitespace" do
|
|
8
|
-
Indenter.for(:foo) do
|
|
9
|
-
assert_equal "\n ", Indenter.for(:foo) { |indent, indent_with_newline| indent_with_newline }
|
|
10
|
-
assert_equal " ", Indenter.for(:foo) { |indent, indent_with_newline| indent }
|
|
11
|
-
end
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
test "nesting blocks increases whitespace accordingly" do
|
|
15
|
-
nested_whitespace = Indenter.for(:foo) do |ws1|
|
|
16
|
-
Indenter.for(:foo) do |ws2|
|
|
17
|
-
ws2
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
assert_equal " ", nested_whitespace
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
test ".for(:name) returns current indent without newline when block is not given" do
|
|
24
|
-
assert_equal "", Indenter.for(:foo) { |_| Indenter.for(:foo) }
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
end
|
data/test/interpolator_test.rb
DELETED
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
require 'test_helper'
|
|
2
|
-
require 'express_templates/interpolator'
|
|
3
|
-
require 'parslet/convenience'
|
|
4
|
-
|
|
5
|
-
class InterpolatorTest < ActiveSupport::TestCase
|
|
6
|
-
|
|
7
|
-
def parse(s)
|
|
8
|
-
parser = ExpressTemplates::Interpolator.new
|
|
9
|
-
parsed = parser.parse_with_debug(s)
|
|
10
|
-
pp parsed if ENV['DEBUG'].eql?('true')
|
|
11
|
-
parsed
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
def transform(s)
|
|
15
|
-
trans = ExpressTemplates::Transformer.new
|
|
16
|
-
trans.apply(parse(s)).flatten.join
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
test "simplest expression parses" do
|
|
20
|
-
tree = parse("{{something}}")
|
|
21
|
-
expected = [{:interpolation=>{:expression=>[{:text=>"something"}]}}]
|
|
22
|
-
assert_equal expected, tree
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
test "simple expression with surrounding text parses" do
|
|
26
|
-
tree = parse('whatever {{something}} something else')
|
|
27
|
-
expected = [{:text=>"whatever "},
|
|
28
|
-
{:interpolation=>{:expression=>[{:text=>"something"}]}},
|
|
29
|
-
{:text=>" something else"}]
|
|
30
|
-
assert_equal expected, tree
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
test "nested without outer text parses" do
|
|
34
|
-
tree = parse('{{some {{thing}} foo}}')
|
|
35
|
-
expected = [{:interpolation=>
|
|
36
|
-
{:expression=>
|
|
37
|
-
[{:text=>"some "},
|
|
38
|
-
{:interpolation=>{:expression=>[{:text=>"thing"}]}},
|
|
39
|
-
{:text=>" foo"}]}}]
|
|
40
|
-
assert_equal expected, tree
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
test "nested with outer text parses" do
|
|
44
|
-
tree = parse('a lot of {{something {{good}}}}')
|
|
45
|
-
expected = [{:text=>"a lot of "},
|
|
46
|
-
{:interpolation=>
|
|
47
|
-
{:expression=>
|
|
48
|
-
[{:text=>"something "},
|
|
49
|
-
{:interpolation=>{:expression=>[{:text=>"good"}]}}]}}]
|
|
50
|
-
assert_equal expected, tree
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
test 'nested with multiple nested expressions parses' do
|
|
54
|
-
tree = parse(%q(%Q({{foo("{{xyz}}", "{{zyx}}", bar: "baz")}})))
|
|
55
|
-
expected = [{:text=>"%Q("},
|
|
56
|
-
{:interpolation=>
|
|
57
|
-
{:expression=>
|
|
58
|
-
[{:text=>"foo(\""},
|
|
59
|
-
{:interpolation=>{:expression=>[{:text=>"xyz"}]}},
|
|
60
|
-
{:text=>"\", \""},
|
|
61
|
-
{:interpolation=>{:expression=>[{:text=>"zyx"}]}},
|
|
62
|
-
{:text=>"\", bar: \"baz\")"}]}},
|
|
63
|
-
{:text=>")"}]
|
|
64
|
-
assert_equal expected, tree
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
test '"{{something}}" transforms to "#{something}"' do
|
|
69
|
-
assert_equal '#{something}', transform("{{something}}")
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
test '"{{some {{thing}} foo}}" transforms to "#{some #{thing} foo}"' do
|
|
73
|
-
assert_equal '#{some #{thing} foo}', transform("{{some {{thing}} foo}}")
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
test %('a lot of {{something "{{good}}"}}' transforms) do
|
|
77
|
-
assert_equal 'a lot of #{something "#{good}"}', transform('a lot of {{something "{{good}}"}}')
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
end
|
data/test/performance_test.rb
DELETED
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
require 'test_helper'
|
|
2
|
-
require 'haml'
|
|
3
|
-
|
|
4
|
-
class PerformanceTest < ActiveSupport::TestCase
|
|
5
|
-
|
|
6
|
-
GARA_EXAMPLE =<<-RUBY
|
|
7
|
-
html(lang: "en") {
|
|
8
|
-
head {
|
|
9
|
-
meta charset: 'utf-8'
|
|
10
|
-
meta name: 'viewport', content: "width=device-width, initial-scale=1.0"
|
|
11
|
-
stylesheet_link_tag "application", media: 'all', 'data-turbolinks-track' => true
|
|
12
|
-
csrf_meta_tags
|
|
13
|
-
}
|
|
14
|
-
body {
|
|
15
|
-
h1 "Hello"
|
|
16
|
-
para "Some text"
|
|
17
|
-
javascript_include_tag "application"
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
RUBY
|
|
21
|
-
|
|
22
|
-
ERB_EXAMPLE = <<-ERB
|
|
23
|
-
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
|
|
24
|
-
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
|
|
25
|
-
<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
|
26
|
-
<meta charset="utf-8" />
|
|
27
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
28
|
-
<%= stylesheet_link_tag 'application' %>
|
|
29
|
-
<%= csrf_meta_tags %>
|
|
30
|
-
</head>
|
|
31
|
-
<body>
|
|
32
|
-
<h1>Hello</h1>
|
|
33
|
-
<p>Some text</p>
|
|
34
|
-
<%= javascript_include_tag 'application' %>
|
|
35
|
-
</body>
|
|
36
|
-
</html>
|
|
37
|
-
ERB
|
|
38
|
-
|
|
39
|
-
HAML_EXAMPLE = <<-HAML
|
|
40
|
-
%html{:xmlns => "http://www.w3.org/1999/xhtml", :lang => "en", 'xml:lang' => "en"}
|
|
41
|
-
%head
|
|
42
|
-
%meta{'http-equiv' => "Content-Type", 'content' => "text/html; charset=UTF-8"}
|
|
43
|
-
%meta{ 'charset' => 'utf-8'}
|
|
44
|
-
%meta{'name' => 'viewport', 'content' => 'width=device-width, initial-scale=1.0'}
|
|
45
|
-
= stylesheet_link_tag 'application'
|
|
46
|
-
= csrf_meta_tags
|
|
47
|
-
%body
|
|
48
|
-
%h1 Hello
|
|
49
|
-
%p Some text
|
|
50
|
-
= javascript_include_tag 'application'
|
|
51
|
-
HAML
|
|
52
|
-
# class Context
|
|
53
|
-
def javascript_include_tag(name, *args)
|
|
54
|
-
%Q(<script data-turbolinks-track="true" src="/assets/#{name}.js"></script>)
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
def stylesheet_link_tag(name, *args)
|
|
58
|
-
%Q(<link data-turbolinks-track="true" href="/assets/#{name}.css" media="all" rel="stylesheet" />)
|
|
59
|
-
end
|
|
60
|
-
def csrf_meta_tags
|
|
61
|
-
%Q(<meta content="authenticity_token" name="csrf-param" />
|
|
62
|
-
<meta content="NF7iiBSErALM5A24Iw07wMH9e8rzxehE50Sv6iPYo98=" name="csrf-token" />
|
|
63
|
-
)
|
|
64
|
-
end
|
|
65
|
-
# end
|
|
66
|
-
|
|
67
|
-
def assigns
|
|
68
|
-
{}
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
def measure_time(count)
|
|
72
|
-
start_time = Time.now
|
|
73
|
-
1.upto(100) { yield }
|
|
74
|
-
end_time = Time.now
|
|
75
|
-
return end_time - start_time
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
# test "performance is okay" do
|
|
79
|
-
# duration = measure_time(100) { ExpressTemplates.render(self, "#{GARA_EXAMPLE}") }
|
|
80
|
-
# assert_operator 1.0, :>, duration
|
|
81
|
-
# end
|
|
82
|
-
|
|
83
|
-
# test "performance no more than 3.5x slower than erubis" do
|
|
84
|
-
# eruby = Erubis::Eruby.new
|
|
85
|
-
# duration_erb = measure_time(100) { eval(eruby.convert(ERB_EXAMPLE)) }
|
|
86
|
-
# duration_express_templates = measure_time(100) { ExpressTemplates.render(self, "#{GARA_EXAMPLE}") }
|
|
87
|
-
# assert_operator 4.0, :>, (duration_express_templates/duration_erb)
|
|
88
|
-
# end
|
|
89
|
-
|
|
90
|
-
# test "performance better than haml" do
|
|
91
|
-
# duration_haml = measure_time(100) { Haml::Engine.new(HAML_EXAMPLE).render(self) }
|
|
92
|
-
# duration_express_templates = measure_time(100) { ExpressTemplates.render(self, "#{GARA_EXAMPLE}") }
|
|
93
|
-
# assert_operator 0.5, :>, (duration_express_templates/duration_haml)
|
|
94
|
-
# end
|
|
95
|
-
|
|
96
|
-
end
|
|
97
|
-
|