trenni 3.7.1 → 3.12.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (104) hide show
  1. checksums.yaml +4 -4
  2. data/bake/trenni/entities.rb +57 -0
  3. data/bake/trenni/parsers.rb +66 -0
  4. data/ext/Rakefile +1 -0
  5. data/ext/tmp/x86_64-linux/lib/trenni/trenni.so +0 -0
  6. data/ext/tmp/x86_64-linux/trenni/2.4.0/Makefile +263 -0
  7. data/ext/tmp/x86_64-linux/trenni/2.4.0/escape.o +0 -0
  8. data/ext/tmp/x86_64-linux/trenni/2.4.0/markup.o +0 -0
  9. data/ext/tmp/x86_64-linux/trenni/2.4.0/mkmf.log +108 -0
  10. data/ext/tmp/x86_64-linux/trenni/2.4.0/tag.o +0 -0
  11. data/ext/tmp/x86_64-linux/trenni/2.4.0/template.o +0 -0
  12. data/ext/tmp/x86_64-linux/trenni/2.4.0/trenni.o +0 -0
  13. data/ext/tmp/x86_64-linux/trenni/2.4.0/trenni.so +0 -0
  14. data/ext/tmp/x86_64-linux/trenni/2.7.0/Makefile +266 -0
  15. data/ext/tmp/x86_64-linux/trenni/2.7.0/escape.o +0 -0
  16. data/ext/tmp/x86_64-linux/trenni/2.7.0/markup.o +0 -0
  17. data/ext/tmp/x86_64-linux/trenni/2.7.0/mkmf.log +113 -0
  18. data/ext/tmp/x86_64-linux/trenni/2.7.0/query.o +0 -0
  19. data/ext/tmp/x86_64-linux/trenni/2.7.0/tag.o +0 -0
  20. data/ext/tmp/x86_64-linux/trenni/2.7.0/template.o +0 -0
  21. data/ext/tmp/x86_64-linux/trenni/2.7.0/trenni.o +0 -0
  22. data/ext/tmp/x86_64-linux/trenni/2.7.0/trenni.so +0 -0
  23. data/ext/tmp/x86_64-linux/trenni/2.7.1/Makefile +266 -0
  24. data/ext/tmp/x86_64-linux/trenni/2.7.1/escape.o +0 -0
  25. data/ext/tmp/x86_64-linux/trenni/2.7.1/markup.o +0 -0
  26. data/ext/tmp/x86_64-linux/trenni/2.7.1/mkmf.log +113 -0
  27. data/ext/tmp/x86_64-linux/trenni/2.7.1/query.o +0 -0
  28. data/ext/tmp/x86_64-linux/trenni/2.7.1/tag.o +0 -0
  29. data/ext/tmp/x86_64-linux/trenni/2.7.1/template.o +0 -0
  30. data/ext/tmp/x86_64-linux/trenni/2.7.1/trenni.o +0 -0
  31. data/ext/tmp/x86_64-linux/trenni/2.7.1/trenni.so +0 -0
  32. data/ext/trenni/extconf.rb +1 -0
  33. data/ext/trenni/markup.c +85 -85
  34. data/ext/trenni/markup.rl +11 -11
  35. data/ext/trenni/query.c +619 -0
  36. data/ext/trenni/query.h +6 -0
  37. data/ext/trenni/query.rl +82 -0
  38. data/ext/trenni/tag.c +8 -6
  39. data/ext/trenni/template.c +57 -57
  40. data/ext/trenni/template.rl +4 -4
  41. data/ext/trenni/trenni.c +9 -1
  42. data/ext/trenni/trenni.h +8 -3
  43. data/lib/trenni.rb +4 -0
  44. data/lib/trenni/buffer.rb +2 -0
  45. data/lib/trenni/builder.rb +64 -12
  46. data/lib/trenni/entities.rb +2082 -2082
  47. data/lib/trenni/entities.trenni +1 -3
  48. data/lib/trenni/{parse_error.rb → error.rb} +6 -1
  49. data/lib/trenni/fallback/markup.rb +1623 -1575
  50. data/lib/trenni/fallback/markup.rl +3 -2
  51. data/lib/trenni/fallback/markup.rl.dot +278 -0
  52. data/lib/trenni/fallback/markup.rl.pdf +0 -0
  53. data/lib/trenni/fallback/query.rb +565 -0
  54. data/lib/trenni/fallback/query.rl +105 -0
  55. data/lib/trenni/fallback/query.rl.dot +54 -0
  56. data/lib/trenni/fallback/query.rl.pdf +0 -0
  57. data/lib/trenni/fallback/template.rb +756 -747
  58. data/lib/trenni/fallback/template.rl +1 -1
  59. data/lib/trenni/fallback/template.rl.dot +270 -0
  60. data/lib/trenni/fallback/template.rl.pdf +0 -0
  61. data/lib/trenni/markup.rb +2 -0
  62. data/lib/trenni/native.rb +3 -1
  63. data/lib/trenni/parse_delegate.rb +2 -0
  64. data/lib/trenni/parsers.rb +2 -0
  65. data/lib/trenni/query.rb +94 -0
  66. data/lib/trenni/reference.rb +125 -0
  67. data/lib/trenni/strings.rb +17 -4
  68. data/lib/trenni/tag.rb +2 -0
  69. data/lib/trenni/template.rb +25 -22
  70. data/lib/trenni/trenni.so +0 -0
  71. data/lib/trenni/uri.rb +3 -0
  72. data/lib/trenni/version.rb +3 -1
  73. data/parsers/trenni/query.rl +23 -0
  74. data/spec/spec_helper.rb +1 -0
  75. data/spec/trenni/builder_spec.rb +14 -1
  76. data/spec/trenni/corpus/large.rb +2 -0
  77. data/spec/trenni/markup_parser_spec.rb +1 -0
  78. data/spec/trenni/markup_performance_spec.rb +15 -2
  79. data/spec/trenni/markup_spec.rb +1 -0
  80. data/spec/trenni/parsers_performance_spec.rb +32 -0
  81. data/spec/trenni/query_spec.rb +51 -0
  82. data/spec/trenni/reference_spec.rb +87 -0
  83. data/spec/trenni/strings_spec.rb +1 -0
  84. data/spec/trenni/tag_spec.rb +2 -0
  85. data/spec/trenni/template_error_spec.rb +1 -0
  86. data/spec/trenni/template_performance_spec.rb +1 -0
  87. data/spec/trenni/template_spec.rb +1 -0
  88. data/spec/trenni/template_spec/builder.trenni +2 -2
  89. data/spec/trenni/uri_spec.rb +1 -0
  90. metadata +95 -62
  91. data/.gitignore +0 -19
  92. data/.rspec +0 -5
  93. data/.simplecov +0 -9
  94. data/.travis.yml +0 -23
  95. data/Gemfile +0 -20
  96. data/README.md +0 -312
  97. data/Rakefile +0 -19
  98. data/benchmark/call_vs_yield.rb +0 -51
  99. data/benchmark/interpolation_vs_concat.rb +0 -29
  100. data/benchmark/io_vs_string.rb +0 -90
  101. data/entities.json +0 -2233
  102. data/tasks/entities.rake +0 -33
  103. data/tasks/parsers.rake +0 -43
  104. data/trenni.gemspec +0 -33
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
4
  # Copyright, 2012, by Samuel G. D. Williams. <http://www.codeotaku.com>
4
5
  #
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Copyright, 2012, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
4
  #
3
5
  # Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env rspec
2
+ # frozen_string_literal: true
2
3
 
3
4
  # Copyright, 2016, by Samuel G. D. Williams. <http://www.codeotaku.com>
4
5
  #
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
 
2
3
  require 'benchmark/ips'
3
4
  require 'trenni/parsers'
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env rspec
2
+ # frozen_string_literal: true
2
3
 
3
4
  # Copyright, 2012, by Samuel G. D. Williams. <http://www.codeotaku.com>
4
5
  #
@@ -1,8 +1,8 @@
1
1
  <?r
2
2
  def append_to_buffer(&block)
3
- Trenni::Builder.fragment do |builder|
3
+ Trenni::Builder.fragment(block.binding) do |builder|
4
4
  builder.capture(&block)
5
- end >> block
5
+ end
6
6
  end
7
7
 
8
8
  append_to_buffer do ?>Hello World!<?r end ?>
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
4
  # Copyright, 2012, by Samuel G. D. Williams. <http://www.codeotaku.com>
4
5
  #
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: trenni
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.7.1
4
+ version: 3.12.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-09-10 00:00:00.000000000 Z
11
+ date: 2020-06-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake-compiler
@@ -25,7 +25,7 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: bundler
28
+ name: bake-bundler
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
@@ -39,21 +39,35 @@ dependencies:
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
- name: rspec
42
+ name: bake-modernize
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - "~>"
45
+ - - ">="
46
46
  - !ruby/object:Gem::Version
47
- version: '3.4'
47
+ version: '0'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - "~>"
52
+ - - ">="
53
53
  - !ruby/object:Gem::Version
54
- version: '3.4'
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: bundler
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'
55
69
  - !ruby/object:Gem::Dependency
56
- name: rake
70
+ name: covered
57
71
  requirement: !ruby/object:Gem::Requirement
58
72
  requirements:
59
73
  - - ">="
@@ -66,35 +80,66 @@ dependencies:
66
80
  - - ">="
67
81
  - !ruby/object:Gem::Version
68
82
  version: '0'
69
- description: "\tTrenni is a templating system built on top of SGML/XML. It uses efficient\n\tnative
70
- parsers where possible and compiles templates into efficient Ruby.\n\t\n\tIn addition,
71
- Trenni includes an SGML/XML builder to assist with the generation\n\tof pleasantly
72
- formatted markup which is compatible with the included parsers.\n"
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '3.4'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '3.4'
97
+ description:
73
98
  email:
74
- - samuel.williams@oriontransfer.co.nz
75
99
  executables: []
76
100
  extensions:
77
101
  - ext/Rakefile
78
102
  extra_rdoc_files: []
79
103
  files:
80
- - ".gitignore"
81
- - ".rspec"
82
- - ".simplecov"
83
- - ".travis.yml"
84
- - Gemfile
85
- - README.md
86
- - Rakefile
87
- - benchmark/call_vs_yield.rb
88
- - benchmark/interpolation_vs_concat.rb
89
- - benchmark/io_vs_string.rb
90
- - entities.json
104
+ - bake/trenni/entities.rb
105
+ - bake/trenni/parsers.rb
91
106
  - ext/Rakefile
107
+ - ext/tmp/x86_64-linux/lib/trenni/trenni.so
108
+ - ext/tmp/x86_64-linux/trenni/2.4.0/Makefile
109
+ - ext/tmp/x86_64-linux/trenni/2.4.0/escape.o
110
+ - ext/tmp/x86_64-linux/trenni/2.4.0/markup.o
111
+ - ext/tmp/x86_64-linux/trenni/2.4.0/mkmf.log
112
+ - ext/tmp/x86_64-linux/trenni/2.4.0/tag.o
113
+ - ext/tmp/x86_64-linux/trenni/2.4.0/template.o
114
+ - ext/tmp/x86_64-linux/trenni/2.4.0/trenni.o
115
+ - ext/tmp/x86_64-linux/trenni/2.4.0/trenni.so
116
+ - ext/tmp/x86_64-linux/trenni/2.7.0/Makefile
117
+ - ext/tmp/x86_64-linux/trenni/2.7.0/escape.o
118
+ - ext/tmp/x86_64-linux/trenni/2.7.0/markup.o
119
+ - ext/tmp/x86_64-linux/trenni/2.7.0/mkmf.log
120
+ - ext/tmp/x86_64-linux/trenni/2.7.0/query.o
121
+ - ext/tmp/x86_64-linux/trenni/2.7.0/tag.o
122
+ - ext/tmp/x86_64-linux/trenni/2.7.0/template.o
123
+ - ext/tmp/x86_64-linux/trenni/2.7.0/trenni.o
124
+ - ext/tmp/x86_64-linux/trenni/2.7.0/trenni.so
125
+ - ext/tmp/x86_64-linux/trenni/2.7.1/Makefile
126
+ - ext/tmp/x86_64-linux/trenni/2.7.1/escape.o
127
+ - ext/tmp/x86_64-linux/trenni/2.7.1/markup.o
128
+ - ext/tmp/x86_64-linux/trenni/2.7.1/mkmf.log
129
+ - ext/tmp/x86_64-linux/trenni/2.7.1/query.o
130
+ - ext/tmp/x86_64-linux/trenni/2.7.1/tag.o
131
+ - ext/tmp/x86_64-linux/trenni/2.7.1/template.o
132
+ - ext/tmp/x86_64-linux/trenni/2.7.1/trenni.o
133
+ - ext/tmp/x86_64-linux/trenni/2.7.1/trenni.so
92
134
  - ext/trenni/escape.c
93
135
  - ext/trenni/escape.h
94
136
  - ext/trenni/extconf.rb
95
137
  - ext/trenni/markup.c
96
138
  - ext/trenni/markup.h
97
139
  - ext/trenni/markup.rl
140
+ - ext/trenni/query.c
141
+ - ext/trenni/query.h
142
+ - ext/trenni/query.rl
98
143
  - ext/trenni/tag.c
99
144
  - ext/trenni/tag.h
100
145
  - ext/trenni/template.c
@@ -107,22 +152,34 @@ files:
107
152
  - lib/trenni/builder.rb
108
153
  - lib/trenni/entities.rb
109
154
  - lib/trenni/entities.trenni
155
+ - lib/trenni/error.rb
110
156
  - lib/trenni/fallback/markup.rb
111
157
  - lib/trenni/fallback/markup.rl
158
+ - lib/trenni/fallback/markup.rl.dot
159
+ - lib/trenni/fallback/markup.rl.pdf
160
+ - lib/trenni/fallback/query.rb
161
+ - lib/trenni/fallback/query.rl
162
+ - lib/trenni/fallback/query.rl.dot
163
+ - lib/trenni/fallback/query.rl.pdf
112
164
  - lib/trenni/fallback/template.rb
113
165
  - lib/trenni/fallback/template.rl
166
+ - lib/trenni/fallback/template.rl.dot
167
+ - lib/trenni/fallback/template.rl.pdf
114
168
  - lib/trenni/markup.rb
115
169
  - lib/trenni/native.rb
116
170
  - lib/trenni/parse_delegate.rb
117
- - lib/trenni/parse_error.rb
118
171
  - lib/trenni/parsers.rb
172
+ - lib/trenni/query.rb
173
+ - lib/trenni/reference.rb
119
174
  - lib/trenni/strings.rb
120
175
  - lib/trenni/tag.rb
121
176
  - lib/trenni/template.rb
177
+ - lib/trenni/trenni.so
122
178
  - lib/trenni/uri.rb
123
179
  - lib/trenni/version.rb
124
180
  - parsers/trenni/entities.rl
125
181
  - parsers/trenni/markup.rl
182
+ - parsers/trenni/query.rl
126
183
  - parsers/trenni/template.rl
127
184
  - spec/spec_helper.rb
128
185
  - spec/trenni/builder_spec.rb
@@ -132,6 +189,8 @@ files:
132
189
  - spec/trenni/markup_performance_spec.rb
133
190
  - spec/trenni/markup_spec.rb
134
191
  - spec/trenni/parsers_performance_spec.rb
192
+ - spec/trenni/query_spec.rb
193
+ - spec/trenni/reference_spec.rb
135
194
  - spec/trenni/strings_spec.rb
136
195
  - spec/trenni/tag_spec.rb
137
196
  - spec/trenni/template_error_spec.rb
@@ -149,13 +208,12 @@ files:
149
208
  - spec/trenni/template_spec/lines.trenni
150
209
  - spec/trenni/template_spec/nested.trenni
151
210
  - spec/trenni/uri_spec.rb
152
- - tasks/entities.rake
153
- - tasks/parsers.rake
154
- - trenni.gemspec
155
211
  homepage: https://github.com/ioquatix/trenni
156
- licenses: []
157
- metadata: {}
158
- post_install_message:
212
+ licenses:
213
+ - MIT
214
+ metadata:
215
+ funding_uri: https://github.com/sponsors/ioquatix
216
+ post_install_message:
159
217
  rdoc_options: []
160
218
  require_paths:
161
219
  - lib
@@ -163,40 +221,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
163
221
  requirements:
164
222
  - - "~>"
165
223
  - !ruby/object:Gem::Version
166
- version: '2.1'
224
+ version: '2.4'
167
225
  required_rubygems_version: !ruby/object:Gem::Requirement
168
226
  requirements:
169
227
  - - ">="
170
228
  - !ruby/object:Gem::Version
171
229
  version: '0'
172
230
  requirements: []
173
- rubygems_version: 3.0.4
174
- signing_key:
231
+ rubygems_version: 3.1.2
232
+ signing_key:
175
233
  specification_version: 4
176
234
  summary: A fast native templating system that compiles directly to Ruby code.
177
- test_files:
178
- - spec/spec_helper.rb
179
- - spec/trenni/builder_spec.rb
180
- - spec/trenni/corpus/large.rb
181
- - spec/trenni/corpus/large.xhtml
182
- - spec/trenni/markup_parser_spec.rb
183
- - spec/trenni/markup_performance_spec.rb
184
- - spec/trenni/markup_spec.rb
185
- - spec/trenni/parsers_performance_spec.rb
186
- - spec/trenni/strings_spec.rb
187
- - spec/trenni/tag_spec.rb
188
- - spec/trenni/template_error_spec.rb
189
- - spec/trenni/template_performance_spec.rb
190
- - spec/trenni/template_spec.rb
191
- - spec/trenni/template_spec/basic.trenni
192
- - spec/trenni/template_spec/buffer.trenni
193
- - spec/trenni/template_spec/builder.trenni
194
- - spec/trenni/template_spec/capture.trenni
195
- - spec/trenni/template_spec/error.trenni
196
- - spec/trenni/template_spec/escaped.trenni
197
- - spec/trenni/template_spec/interpolations.trenni
198
- - spec/trenni/template_spec/large.erb
199
- - spec/trenni/template_spec/large.trenni
200
- - spec/trenni/template_spec/lines.trenni
201
- - spec/trenni/template_spec/nested.trenni
202
- - spec/trenni/uri_spec.rb
235
+ test_files: []
data/.gitignore DELETED
@@ -1,19 +0,0 @@
1
- *.gem
2
- *.rbc
3
- .bundle
4
- .config
5
- .yardoc
6
- Gemfile.lock
7
- InstalledFiles
8
- _yardoc
9
- coverage
10
- doc/
11
- lib/bundler/man
12
- pkg
13
- rdoc
14
- spec/reports
15
- test/tmp
16
- test/version_tmp
17
- tmp
18
-
19
- lib/trenni/trenni.bundle
data/.rspec DELETED
@@ -1,5 +0,0 @@
1
- --color
2
- --format documentation
3
- --backtrace
4
- --warnings
5
- --require spec_helper
data/.simplecov DELETED
@@ -1,9 +0,0 @@
1
-
2
- SimpleCov.start do
3
- add_filter "/spec/"
4
- end
5
-
6
- if ENV['TRAVIS']
7
- require 'coveralls'
8
- Coveralls.wear!
9
- end
@@ -1,23 +0,0 @@
1
- language: ruby
2
- cache: bundler
3
-
4
- before_script:
5
- - sh -c "cd ext && bundle exec rake compile"
6
-
7
- matrix:
8
- include:
9
- - rvm: 2.3
10
- - rvm: 2.4
11
- - rvm: 2.5
12
- - rvm: 2.6
13
- - rvm: 2.6
14
- env: TRENNI_PREFER_FALLBACK=y
15
- - rvm: 2.6
16
- env: COVERAGE=Summary
17
- - rvm: ruby-head
18
- - rvm: jruby-head
19
- - rvm: truffleruby
20
- allow_failures:
21
- - rvm: "truffleruby"
22
- - rvm: "ruby-head"
23
- - rvm: "jruby-head"
data/Gemfile DELETED
@@ -1,20 +0,0 @@
1
- source 'https://rubygems.org'
2
-
3
- # Specify your gem's dependencies in trenni.gemspec
4
- gemspec
5
-
6
- group :development do
7
- gem 'pry'
8
- gem "rake-compiler"
9
- gem "ruby-beautify"
10
- end
11
-
12
- group :test do
13
- gem 'ruby-prof', platforms: [:mri]
14
- gem "benchmark-ips"
15
-
16
- gem 'covered'
17
-
18
- # For comparisons:
19
- gem "nokogiri"
20
- end
data/README.md DELETED
@@ -1,312 +0,0 @@
1
- # Trenni
2
-
3
- Trenni is a templating system built loosely on top of XHTML markup. It uses efficient native parsers where possible and compiles templates into efficient Ruby. It also includes a markup builder to assist with the generation of pleasantly formatted markup which is compatible with the included parsers.
4
-
5
- [![Build Status](https://secure.travis-ci.org/ioquatix/trenni.svg)](http://travis-ci.org/ioquatix/trenni)
6
- [![Code Climate](https://codeclimate.com/github/ioquatix/trenni.svg)](https://codeclimate.com/github/ioquatix/trenni)
7
- [![Coverage Status](https://coveralls.io/repos/ioquatix/trenni/badge.svg)](https://coveralls.io/r/ioquatix/trenni)
8
-
9
- ## Motivation
10
-
11
- Trenni was designed for [Utopia](https://github.com/ioquatix/utopia). When I originally looked at template engines, I was surprised by the level of complexity and the effort involved in processing a template to produce useful output. In particular, many template engines generate an AST and walk over it to generate output (e.g. ERB, at least at the time I last checked). This is exceedingly slow in Ruby.
12
-
13
- At the time (around 2008?) I was playing around with [ramaze](https://github.com/Ramaze/ramaze) and found a template engine I really liked the design of, called [ezamar](https://github.com/manveru/ezamar). The template compilation process actually generates Ruby code which can then be compiled and executed efficiently. Another engine, by the same author, [nagoro](https://github.com/manveru/nagoro), also provided some inspiration.
14
-
15
- More recently I was doing some investigation regarding using `eval` for executing the code. The problem is that it's [not possible to replace the binding](http://stackoverflow.com/questions/27391909/replace-evalcode-string-binding-with-lambda/27392437) of a `Proc` once it's created, so template engines that evaluate code in a given binding cannot use a compiled proc, they must parse the code every time. By using a `Proc` we can generate a Ruby function which *can* be compiled to a faster representation by the VM.
16
-
17
- In addition, I wanted a simple markup parser and builder for HTML style markup. These are used heavily by Utopia for implementing it's tag based evaluation. `Trenni::Builder` is a simple and efficient way to generate markup, it's not particularly notable, except that it doesn't use `method_missing` to [implement normal behaviour](https://github.com/sparklemotion/nokogiri/blob/b6679e928924529b56dcc0f3164224c040d14555/lib/nokogiri/xml/builder.rb#L355) which is [sort of slow](http://franck.verrot.fr/blog/2015/07/12/benchmarking-ruby-method-missing-and-define-method/).
18
-
19
- The 2nd release of Trenni in 2016 saw an overhaul of the internal parsers. I used [Ragel](http://www.colm.net/open-source/ragel/) to implement efficient event-based markup and template parsers, which can be compiled to both C and Ruby. This provides a native code path where possible giving speed-ups between 10x - 20x. In addition, the formal grammar is more robust.
20
-
21
- The 3rd release of Trenni in 2017 was primarily focused on performance, by moving more of the critical parsing, escaping and tag generation functions to C. In practical usage, this gave about a 40-50% improvement in performance overall.
22
-
23
- ## Is it fast?
24
-
25
- It's faster than Nokogiri for parsing markup:
26
-
27
- Trenni::Native
28
- Warming up --------------------------------------
29
- Large (Trenni) 71.000 i/100ms
30
- Large (Nokogiri) 28.000 i/100ms
31
- Calculating -------------------------------------
32
- Large (Trenni) 662.050 (± 3.9%) i/s - 3.337k in 5.048115s
33
- Large (Nokogiri) 266.878 (±10.9%) i/s - 1.316k in 5.008464s
34
-
35
- Comparison:
36
- Large (Trenni): 662.1 i/s
37
- Large (Nokogiri): 266.9 i/s - 2.48x slower
38
-
39
- It's significantly faster than ERB:
40
-
41
- Trenni::Template
42
- Warming up --------------------------------------
43
- Trenni (object) 75.667k i/100ms
44
- ERB (binding) 6.940k i/100ms
45
- Calculating -------------------------------------
46
- Trenni (object) 1.095M (± 7.9%) i/s - 5.448M in 5.007244s
47
- ERB (binding) 69.381k (± 7.1%) i/s - 347.000k in 5.027333s
48
-
49
- Comparison:
50
- Trenni (object): 1094979.9 i/s
51
- ERB (binding): 69381.1 i/s - 15.78x slower
52
-
53
- ## Installation
54
-
55
- Add this line to your application's Gemfile:
56
-
57
- gem 'trenni'
58
-
59
- And then execute:
60
-
61
- $ bundle
62
-
63
- Or install it yourself as:
64
-
65
- $ gem install trenni
66
-
67
- ## Usage
68
-
69
- ### Markup Parser
70
-
71
- The markup parser parses a loose super-set of HTML in a way that's useful for content processing, similar to an XSLT processor. It's designed to be faster and easier to use, and integrate directly into an output pipeline.
72
-
73
- To invoke the markup parser:
74
-
75
- ```ruby
76
- require 'trenni'
77
-
78
- buffer = Trenni::Buffer(string)
79
-
80
- # Custom entities, or could use Trenni::Entities::HTML5
81
- entities = {'amp' => '&', 'lt', => '<', 'gt' => '>', 'quot' => '"'}
82
-
83
- # Modify this class to accumulate events or pass them on somewhere else.
84
- class Delegate
85
- # Called when encountering an open tag: `<` name
86
- def open_tag_begin(name, offset)
87
- end
88
-
89
- # Called when encountering an attribute after open_tag_begin
90
- def attribute(key, value)
91
- end
92
-
93
- # Called when encountering the end of the opening tag.
94
- def open_tag_end(self_closing)
95
- end
96
-
97
- # Called when encountering the closing tag: '</' name '>'
98
- def close_tag(name, offset)
99
- end
100
-
101
- # Called with the full doctype: '<!DOCTYPE html>'
102
- def doctype(string)
103
- end
104
-
105
- # Called with the full comment: '<!-- comment -->'
106
- def comment(string)
107
- end
108
-
109
- # Called with the parsed instruction: '<?' identifier space+ body '?>'
110
- def instruction(string)
111
- end
112
-
113
- # Called with a cdata block: '<![CDATA[text]]>'
114
- def cdata(string)
115
- end
116
-
117
- # Called with any arbitrary pcdata text (e.g. between tags).
118
- def text(string)
119
- end
120
- end
121
-
122
- # Do the actual work:
123
- Trenni::Parsers.parse_markup(buffer, Delegate.new, entities)
124
- ```
125
-
126
- ### Templates
127
-
128
- Trenni templates work essentially the same way as all other templating systems:
129
-
130
- ```ruby
131
- buffer = Trenni::Buffer('<?r self.each do |item| ?>#{item}<?r end ?>')
132
- template = Trenni::Template.new(buffer)
133
-
134
- items = 1..4
135
-
136
- template.to_string(items) # => "1234"
137
- ```
138
-
139
- The code above demonstrate the only two constructs, `<?r expression ?>` and `#{output}`.
140
-
141
- Trenni doesn't support using `binding` for evaluation, as this is a slow code path. It uses `instance_exec`
142
-
143
- ### Builder
144
-
145
- Trenni can help construct XML/HTML using a simple DSL:
146
-
147
- ```ruby
148
- Trenni::Builder.fragment do |builder|
149
- builder.inline 'p' do
150
- builder.tag 'strong' do
151
- builder.text 'Hello'
152
- end
153
- builder.text ' World'
154
- end
155
- end.to_s
156
- # => "<p><strong>Hello</strong> World</p>"
157
- ```
158
-
159
- ### Testing
160
-
161
- To test the Ruby parsers:
162
-
163
- rake generate_fallback_parsers && TRENNI_PREFER_FALLBACK=y rspec
164
-
165
- To test the native C parsers:
166
-
167
- rake generate_native_parsers && rake compile && rspec
168
-
169
- ### Benchmarks
170
-
171
- Trenni has a pure Ruby implemenation, with performance critical operations implemented natively. All critical code paths have benchmark specs.
172
-
173
- #### Parser Performance
174
-
175
- You can evaluate and compare template performance with ERB:
176
-
177
- ```
178
- rspec spec/trenni/parsers_performance_spec.rb
179
-
180
- Trenni::Native
181
- #parse_markup
182
- Warming up --------------------------------------
183
- Large (Trenni) 64.000 i/100ms
184
- Large (Nokogiri) 30.000 i/100ms
185
- Calculating -------------------------------------
186
- Large (Trenni) 637.720 (± 6.4%) i/s - 3.200k in 5.038187s
187
- Large (Nokogiri) 294.762 (± 5.8%) i/s - 1.470k in 5.004284s
188
-
189
- Comparison:
190
- Large (Trenni): 637.7 i/s
191
- Large (Nokogiri): 294.8 i/s - 2.16x slower
192
-
193
- should be fast to parse large documents
194
- #parse_template
195
- Warming up --------------------------------------
196
- Large (Trenni) 7.791k i/100ms
197
- Large (ERB) 488.000 i/100ms
198
- Calculating -------------------------------------
199
- Large (Trenni) 87.889k (± 9.5%) i/s - 436.296k in 5.024283s
200
- Large (ERB) 4.844k (± 5.6%) i/s - 24.400k in 5.053247s
201
-
202
- Comparison:
203
- Large (Trenni): 87889.4 i/s
204
- Large (ERB): 4844.5 i/s - 18.14x slower
205
-
206
- should have better performance using instance
207
-
208
- Finished in 28.2 seconds (files took 0.14204 seconds to load)
209
- 2 examples, 0 failures
210
- ```
211
-
212
- To run this with the pure ruby implementation, use `TRENNI_PREFER_FALLBACK=y rspec spec/trenni/parsers_performance_spec.rb`.
213
-
214
- #### Markup String Performance
215
-
216
- Markup safe strings require escaping characters. Doing this natively makes sense, and in MRI, `CGI.escape_html` is implemented in C. Strings that include characters that need to be escaped are a bit slower because a new string must be allocated and modified. So, we test these two cases.
217
-
218
- ```
219
- rspec spec/trenni/markup_performance_spec.rb
220
-
221
- Trenni::Markup
222
- Warming up --------------------------------------
223
- General String 179.396k i/100ms
224
- Code String 85.050k i/100ms
225
- Calculating -------------------------------------
226
- General String 4.773M (±10.0%) i/s - 23.680M in 5.027576s
227
- Code String 1.469M (± 5.7%) i/s - 7.399M in 5.052467s
228
-
229
- Comparison:
230
- General String: 4773201.3 i/s
231
- Code String: 1469345.5 i/s - 3.25x slower
232
-
233
- should be fast to parse large documents
234
-
235
- Finished in 14.11 seconds (files took 0.09696 seconds to load)
236
- 1 example, 0 failures
237
- ```
238
-
239
- #### Template Evaluation Performance
240
-
241
- Evaluating templates and generating output is critical to performance. You can compare Trenni with ERB. The primary factor affecting performance, is the number of interpolations, because each interpolation requires evaluation and concatenation.
242
-
243
- ```
244
- rspec spec/trenni/template_performance_spec.rb
245
-
246
- Trenni::Template
247
- Warming up --------------------------------------
248
- Trenni 79.000 i/100ms
249
- Calculating -------------------------------------
250
- Trenni 817.703 (± 7.7%) i/s - 4.108k in 5.071586s
251
- should be fast for lots of interpolations
252
- Warming up --------------------------------------
253
- Trenni (object) 79.149k i/100ms
254
- ERB (binding) 5.416k i/100ms
255
- Calculating -------------------------------------
256
- Trenni (object) 1.081M (± 3.7%) i/s - 5.461M in 5.059151s
257
- ERB (binding) 59.016k (± 4.7%) i/s - 297.880k in 5.058614s
258
-
259
- Comparison:
260
- Trenni (object): 1080909.2 i/s
261
- ERB (binding): 59016.3 i/s - 18.32x slower
262
-
263
- should be fast for basic templates
264
- Warming up --------------------------------------
265
- Trenni 34.204k i/100ms
266
- Calculating -------------------------------------
267
- Trenni 407.905k (± 9.0%) i/s - 2.018M in 5.001248s
268
- should be fast with capture
269
-
270
- Finished in 28.25 seconds (files took 0.09765 seconds to load)
271
- 3 examples, 0 failures
272
- ```
273
-
274
- ## See Also
275
-
276
- - [language-trenni](https://atom.io/packages/language-trenni) package for the [Atom text editor](https://atom.io). It provides syntax highlighting and integration when Trenni is used with the [utopia web framework](https://github.com/ioquatix/utopia).
277
-
278
- - [vim-trenni](https://github.com/huba/vim-trenni) package for Vim.
279
-
280
- - [Trenni Formatters](https://github.com/ioquatix/trenni-formatters) is a separate gem that uses `Trenni::Builder` to generate HTML forms easily.
281
-
282
- ## Contributing
283
-
284
- 1. Fork it
285
- 2. Create your feature branch (`git checkout -b my-new-feature`)
286
- 3. Commit your changes (`git commit -am 'Add some feature'`)
287
- 4. Push to the branch (`git push origin my-new-feature`)
288
- 5. Create new Pull Request
289
-
290
- ## License
291
-
292
- Released under the MIT license.
293
-
294
- Copyright, 2017, by [Samuel G. D. Williams](http://www.codeotaku.com/samuel-williams).
295
-
296
- Permission is hereby granted, free of charge, to any person obtaining a copy
297
- of this software and associated documentation files (the "Software"), to deal
298
- in the Software without restriction, including without limitation the rights
299
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
300
- copies of the Software, and to permit persons to whom the Software is
301
- furnished to do so, subject to the following conditions:
302
-
303
- The above copyright notice and this permission notice shall be included in
304
- all copies or substantial portions of the Software.
305
-
306
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
307
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
308
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
309
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
310
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
311
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
312
- THE SOFTWARE.