handlebars-engine 0.2.0 → 0.3.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0b6bc490b95cc268a0cc7ee638660caecbfe9d978a13335b8c3588f89e16c3db
4
- data.tar.gz: 014eb30c05c4edba8b9f9a340e3539a8542edabd94954efa189b2611456e10d8
3
+ metadata.gz: 554df376a361ca161ddf847bbe992c6d75d1cac32ba355d16c22a849781462fc
4
+ data.tar.gz: ec2e1de82a986c6dd024b1ec90af293c39f49becf8d03a628625b3cf5beada10
5
5
  SHA512:
6
- metadata.gz: a092e8fdae258e997d6afb3505b20a67898caf7d08bfd37efee1a50f663b0e084648902b6d396fe392acb46a8e5587deee277e2ec750f31ce103ad8dd42d1d6b
7
- data.tar.gz: 99c271de356730e76c660fb806d8dd619edb0f522951a5e822f6460e0e415c02e20311aab2e5be55e89f9b2ffd161e87b75784726512df26d5c59d002ec06f9a
6
+ metadata.gz: d4e2470b91cae56cc9f6f18c079d763c10babd1eaa66d0660b13f68afce67f9513504f1515b12a6850739d0b9b19fa47a64c2e57e040fc34ebbbd43694cba55d
7
+ data.tar.gz: 0270460ce862b0e079f27b96e20829e28d84059a5b3f4d0d2301fd5257d62804cc35489db0cf39aed45c263ae74144f10fa573a89e352ee21e8b119ef9ea023b
data/CHANGELOG.md CHANGED
@@ -7,6 +7,34 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.3.3] - 2022-02-17
11
+
12
+ ### Changed
13
+ - `engine/function`: remove object finalizer (fixes [#14](https://github.com/gi/handlebars-ruby/issues/14))
14
+
15
+ ## [0.3.2] - 2022-02-17
16
+
17
+ ### Changed
18
+ - `engine`: fixed issue with memory leak ([#15](https://github.com/gi/handlebars-ruby/pull/15))
19
+
20
+ ## [0.3.1] - 2022-02-04
21
+
22
+ ### Added
23
+ - `engine`: added `Error` class
24
+ - `specs`: added tests for (pre)compiling with options
25
+
26
+ ### Changed
27
+ - `gem`/`readme`: updated description
28
+
29
+ ## [0.3.0] - 2022-01-31
30
+
31
+ ### Added
32
+ - `initialize`: add path parameter ([#5](https://github.com/gi/handlebars-ruby/pull/5))
33
+ - `register_helper`: accept multiple helpers as keyword parameters ([#6](https://github.com/gi/handlebars-ruby/pull/6))
34
+ - `register_helper`: accept javascript function as string ([#7](https://github.com/gi/handlebars-ruby/pull/7))
35
+ - `ci`: verify gem builds ([#8](https://github.com/gi/handlebars-ruby/pull/8))
36
+ - `require`: allow loading from `handlebars-engine` and `handlebars/engine` ([#8](https://github.com/gi/handlebars-ruby/pull/8))
37
+
10
38
  ## [0.2.0] - 2022-01-27
11
39
 
12
40
  This is the initial implementation, wrapping the JavaScript Handlebars.
data/README.md CHANGED
@@ -1,12 +1,22 @@
1
1
  # Handlebars::Engine
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/handlebars-engine.svg)](https://rubygems.org/gems/handlebars-engine)
4
- [![Build Status](https://github.com/gi/handlebars-ruby/actions/workflows/ci.yml/badge.svg)](https://github.com/gi/handlebars-ruby/actions/workflows/ci.yml)
4
+ [![CI Status](https://github.com/gi/handlebars-ruby/actions/workflows/ci.yml/badge.svg)](https://github.com/gi/handlebars-ruby/actions/workflows/ci.yml)
5
5
  [![Test Coverage](https://api.codeclimate.com/v1/badges/45d98ad9e12ee3384161/test_coverage)](https://codeclimate.com/github/gi/handlebars-ruby/test_coverage)
6
6
  [![Maintainability](https://api.codeclimate.com/v1/badges/45d98ad9e12ee3384161/maintainability)](https://codeclimate.com/github/gi/handlebars-ruby/maintainability)
7
7
  [![MIT License](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE.txt)
8
8
 
9
- A simple interface to [Handlebars.js](https://handlebarsjs.com) for Ruby.
9
+ A complete interface to [Handlebars.js](https://handlebarsjs.com) for Ruby.
10
+
11
+ `Handlebars::Engine` provides a complete Ruby API for the official JavaScript
12
+ version of Handlebars, including the abilities to register Ruby blocks/procs as
13
+ Handlebars helper functions and to dynamically register partials.
14
+
15
+ It uses [MiniRacer](https://github.com/rubyjs/mini_racer) for the bridge between
16
+ Ruby and the V8 JavaScript engine.
17
+
18
+ `Handlebars::Engine` was created as a replacement for
19
+ [handlebars.rb](https://github.com/cowboyd/handlebars.rb).
10
20
 
11
21
  ## Installation
12
22
 
@@ -82,6 +92,32 @@ See https://handlebarsjs.com/guide/#custom-helpers.
82
92
 
83
93
  ### Block Helpers
84
94
 
95
+ Block helpers make it possible to define custom iterators and other
96
+ functionality that can invoke the passed block with a new context.
97
+
98
+ Currently, there is a limitation with the underlying JavaScript engine: it does
99
+ not allow for reentrant calls from within attached Ruby functions: see
100
+ [MiniRacer#225](https://github.com/rubyjs/mini_racer/issues/225). Thus, the
101
+ block function returned to the helper (in `options.fn`) cannot be invoked.
102
+
103
+ Thus, for block helpers, a string of JavaScript must define the helper function:
104
+ ```ruby
105
+ handlebars = Handlebars::Engine.new
106
+ handlebars.register_helper(map: <<~JS)
107
+ function(...args) {
108
+ const ctx = this;
109
+ const opts = args.pop();
110
+ const items = args[0];
111
+ const separator = args[1];
112
+ const mapped = items.map((item) => opts.fn(item));
113
+ return mapped.join(separator);
114
+ }
115
+ JS
116
+ template = handlebars.compile("{{#map items '|'}}'{{this}}'{{/map}}")
117
+ template.call({ items: [1, 2, 3] })
118
+ # => "'1'|2'|'3'"
119
+ ```
120
+
85
121
  See https://handlebarsjs.com/guide/#block-helpers.
86
122
 
87
123
  ### Partials
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Handlebars
4
+ class Engine
5
+ # A proxy for a JavaScript function defined in the context.
6
+ class Function
7
+ def initialize(context, name)
8
+ @context = context
9
+ @name = name
10
+ end
11
+
12
+ def call(*args)
13
+ @context.call(@name, *args)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Handlebars
4
4
  class Engine
5
- VERSION = "0.2.0"
5
+ VERSION = "0.3.3"
6
6
  end
7
7
  end
@@ -4,6 +4,7 @@ require "handlebars/source"
4
4
  require "json"
5
5
  require "mini_racer"
6
6
  require "securerandom"
7
+ require_relative "engine/function"
7
8
  require_relative "engine/version"
8
9
 
9
10
  module Handlebars
@@ -12,11 +13,16 @@ module Handlebars
12
13
  # This API follows the JavaScript API as closely as possible:
13
14
  # https://handlebarsjs.com/api-reference/.
14
15
  class Engine
16
+ Error = MiniRacer::RuntimeError
17
+
15
18
  # Creates a new instance.
16
19
  #
17
20
  # @param lazy [true, false] immediately loads and initializes the JavaScript
18
21
  # environment.
19
- def initialize(lazy: false)
22
+ # @param path [String, nil] the path to the version of Handlebars to load.
23
+ # If `nil`, the contents of `Handlebars::Source.bundled_path` is loaded.
24
+ def initialize(lazy: false, path: nil)
25
+ @path = path
20
26
  init! unless lazy
21
27
  end
22
28
 
@@ -60,14 +66,29 @@ module Handlebars
60
66
 
61
67
  # Registers helpers accessible by any template in the environment.
62
68
  #
69
+ # The function can be either a proc or a string:
70
+ # * When the function is a proc, it can be either passed in as a normal
71
+ # parameter or as a block.
72
+ # * When the function is a string, it is interpreted as a JavaScript
73
+ # function.
74
+ #
63
75
  # @param name [String, Symbol] the name of the helper
76
+ # @param function [Proc, String] the helper function
64
77
  # @yieldparam context [Hash] the current context
65
78
  # @yieldparam arguments [Object] the arguments (optional)
66
79
  # @yieldparam options [Hash] the options hash (optional)
67
80
  # @see https://handlebarsjs.com/api-reference/runtime.html#handlebars-registerhelper-name-helper
68
- def register_helper(name, &block)
69
- attach(name, &block)
70
- call(:registerHelper, [name.to_s, name.to_sym], eval: true)
81
+ def register_helper(name = nil, function = nil, **helpers, &block)
82
+ helpers[name] = block || function if name
83
+ helpers.each do |n, f|
84
+ case f
85
+ when Proc
86
+ attach(n, &f)
87
+ evaluate("registerHelper('#{n}', #{n})")
88
+ when String, Symbol
89
+ evaluate("Handlebars.registerHelper('#{n}', #{f})")
90
+ end
91
+ end
71
92
  end
72
93
 
73
94
  # Unregisters a previously registered helper.
@@ -179,9 +200,7 @@ module Handlebars
179
200
  result = evaluate(code)
180
201
 
181
202
  if var && result.is_a?(MiniRacer::JavaScriptFunction)
182
- result = ->(*a) { @context.call(var, *a) }
183
- finalizer = ->(*) { evaluate("delete #{var}") }
184
- ObjectSpace.define_finalizer(result, finalizer)
203
+ result = Function.new(@context, var)
185
204
  end
186
205
 
187
206
  result
@@ -204,21 +223,14 @@ module Handlebars
204
223
  return if @init
205
224
 
206
225
  @context = MiniRacer::Context.new
207
- @context.load(::Handlebars::Source.bundled_path)
226
+ @context.load(@path || ::Handlebars::Source.bundled_path)
208
227
  @context.load(File.absolute_path("engine/init.js", __dir__))
209
228
 
210
229
  @init = true
211
230
  end
212
231
 
213
232
  def js_args(args)
214
- args.map { |arg|
215
- case arg
216
- when Symbol
217
- arg
218
- else
219
- JSON.generate(arg)
220
- end
221
- }
233
+ args.map { |arg| JSON.generate(arg) }
222
234
  end
223
235
  end
224
236
  end
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "handlebars/engine"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: handlebars-engine
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Zach Gianos
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-01-27 00:00:00.000000000 Z
11
+ date: 2022-02-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: handlebars-source
@@ -38,7 +38,16 @@ dependencies:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
- description: " A simple interface to Handlebars.js for Ruby.\n"
41
+ description: |2
42
+ A complete interface to Handlebars.js for Ruby.
43
+
44
+ Handlebars::Engine provides a complete Ruby API for the official JavaScript
45
+ version of Handlebars, including the abilities to register Ruby blocks/procs
46
+ as Handlebars helper functions and to dynamically register partials.
47
+
48
+ It uses MiniRacer for the bridge between Ruby and the V8 JavaScript engine.
49
+
50
+ Handlebars::Engine was created as a replacement for handlebars.rb.
42
51
  email:
43
52
  - zach.gianos+git@gmail.com
44
53
  executables:
@@ -50,7 +59,9 @@ files:
50
59
  - LICENSE
51
60
  - README.md
52
61
  - exe/handlebars
62
+ - lib/handlebars-engine.rb
53
63
  - lib/handlebars/engine.rb
64
+ - lib/handlebars/engine/function.rb
54
65
  - lib/handlebars/engine/init.js
55
66
  - lib/handlebars/engine/version.rb
56
67
  homepage: https://github.com/gi/handlebars-ruby
@@ -61,7 +72,7 @@ metadata:
61
72
  github_repo: https://github.com/gi/handlebars-ruby
62
73
  homepage_uri: https://github.com/gi/handlebars-ruby
63
74
  source_code_uri: https://github.com/gi/handlebars-ruby
64
- post_install_message:
75
+ post_install_message:
65
76
  rdoc_options: []
66
77
  require_paths:
67
78
  - lib
@@ -76,8 +87,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
76
87
  - !ruby/object:Gem::Version
77
88
  version: '0'
78
89
  requirements: []
79
- rubygems_version: 3.2.22
80
- signing_key:
90
+ rubygems_version: 3.3.3
91
+ signing_key:
81
92
  specification_version: 4
82
- summary: A simple interface to Handlebars.js for Ruby.
93
+ summary: A complete interface to Handlebars.js for Ruby.
83
94
  test_files: []