minibars 0.0.1.alpha → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +81 -0
- data/Rakefile +0 -6
- data/lib/handlebars.rb +8 -0
- data/lib/minibars/context.rb +82 -0
- data/lib/minibars/error.rb +3 -0
- data/lib/minibars/safe_string.rb +13 -0
- data/lib/minibars/template.rb +59 -0
- data/lib/minibars/version.rb +1 -1
- data/lib/minibars.rb +14 -1
- metadata +33 -35
- data/lib/tasks/minibars_tasks.rake +0 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 29dfecb36dae3be442ea406501052e3df52fa71578647ad1d1e74410e49ddc92
|
4
|
+
data.tar.gz: 767861cecb3604b98b8ee615148f784eb9478a13d35bb1bad531eea9a4a631c4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: aa966dac5605965607974dcaf968f762e5b6b0644d3b67fcfd001ba8586503b164d2a593f11051c1226c2af85f2d887a762bf5335bbdf9a2688884ad6147f289
|
7
|
+
data.tar.gz: 1c2f503e4c77cfc66e01562b61138fa3d7336dca719ade8282deff74d80c292c85caaab4424befeaafd4282584e4457ba4ff4fcbecaadabd8eed343929d96e6f
|
data/README.md
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
![Tests](https://github.com/delonnewman/minibars/workflows/tests/badge.svg)
|
2
|
+
|
3
|
+
# Minibars
|
4
|
+
|
5
|
+
A (mostly) drop-in replacement for [Handlebars.rb][3] based on [MiniRacer][1] rather than [therubyracer][2].
|
6
|
+
|
7
|
+
An appropriately revised quote from the [Handlebars.rb][3] README:
|
8
|
+
|
9
|
+
> This uses ~~therubyracer~~[MiniRacer][1] to bind to the _actual_ JavaScript implementation of [Handlebars.js](https://github.com/handlebars-lang/handlebars.js) so that you can use it from ruby.
|
10
|
+
|
11
|
+
# Why?
|
12
|
+
|
13
|
+
Minibars is a stripped down implementation of [Handlerbars.rb][3] using [MiniRacer][1]. It eschews capabilities that require two-way binding with the JS runtime, making it a good choice for those with simple Handlebars templates who need an upgrade path for their ARM64 architecture.
|
14
|
+
|
15
|
+
# Usage
|
16
|
+
|
17
|
+
## Simple Stuff
|
18
|
+
|
19
|
+
```ruby
|
20
|
+
require 'minibars'
|
21
|
+
minibars = Minibars::Context.new
|
22
|
+
template = minibars.compile("{{say}} {{what}}")
|
23
|
+
template.call(say: "Hey", what: "Yuh!") #=> "Hey Yuh!"
|
24
|
+
```
|
25
|
+
|
26
|
+
## Functions as Properties
|
27
|
+
|
28
|
+
This feature differs from [Handlebars.rb][3] since Minibars templates won't pass a `this` argument to property functions.
|
29
|
+
|
30
|
+
```ruby
|
31
|
+
template.call(say: "Hey ", what: ->{ ("yo" * 2) + "!"}) #=> "Hey yoyo!"
|
32
|
+
```
|
33
|
+
|
34
|
+
## Helpers
|
35
|
+
|
36
|
+
JavaScript helpers can be loaded as individual files or as a glob
|
37
|
+
|
38
|
+
```ruby
|
39
|
+
minibars.load_helpers("#{__dir__}/javascripts/helpers/**/*.js")
|
40
|
+
minibars.load_helper("#{__dir__}/javascripts/helpers/admin.js")
|
41
|
+
```
|
42
|
+
|
43
|
+
## Partials
|
44
|
+
|
45
|
+
You can directly register partials
|
46
|
+
|
47
|
+
```ruby
|
48
|
+
minibars.register_partial("whoami", "I am {{who}}")
|
49
|
+
minibars.compile("{{>whoami}}").call(who: 'Legend') #=> I am Legend
|
50
|
+
```
|
51
|
+
|
52
|
+
## SafeStrings
|
53
|
+
|
54
|
+
By default, handlebars will escape strings that are returned by your block helpers. To mark a string as safe:
|
55
|
+
|
56
|
+
```ruby
|
57
|
+
template = minibars.compile("{{safe}}")
|
58
|
+
template.call(safe: Minibars::SafeString.new("<pre>Totally Safe!<pre>"))
|
59
|
+
```
|
60
|
+
|
61
|
+
## Compatibility
|
62
|
+
|
63
|
+
`Handlebars::Context` aliases `Minibars::Context` and `Handlebars::SafeString` aliases `Minibars::SafeString` unless they are already defined.
|
64
|
+
|
65
|
+
```ruby
|
66
|
+
require 'handlebars` # Applies the compatibility layer found in lib/handlebars.rb and loads minibars
|
67
|
+
```
|
68
|
+
|
69
|
+
## Limitations
|
70
|
+
|
71
|
+
- No Ruby helpers
|
72
|
+
|
73
|
+
## Security
|
74
|
+
|
75
|
+
In general, you should not trust user-provided templates: a template can call any method (with no arguments) or access any property on any object in the `Minibars::Context`.
|
76
|
+
|
77
|
+
If you'd like to render user-provided templates, you'd want to make sure you do so in a sanitized Context, e.g. no filesystem access, read-only or no database access, etc.
|
78
|
+
|
79
|
+
[1]: https://github.com/rubyjs/mini_racer
|
80
|
+
[2]: https://github.com/rubyjs/therubyracer
|
81
|
+
[3]: https://github.com/cowboyd/handlebars.rb
|
data/Rakefile
CHANGED
@@ -4,14 +4,8 @@ rescue LoadError
|
|
4
4
|
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
5
5
|
end
|
6
6
|
|
7
|
-
APP_RAKEFILE = File.expand_path("../spec/internal/Rakefile", __FILE__)
|
8
|
-
load 'rails/tasks/engine.rake'
|
9
|
-
|
10
|
-
load 'rails/tasks/statistics.rake'
|
11
|
-
|
12
7
|
Bundler::GemHelper.install_tasks
|
13
8
|
|
14
|
-
|
15
9
|
# Add Rspec tasks
|
16
10
|
require 'rspec/core/rake_task'
|
17
11
|
|
data/lib/handlebars.rb
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
# Handlebars Compatibility
|
2
|
+
# Allows Minibars to be a drop in replacement for Handlebars (minus features that are not supported)
|
3
|
+
require 'minibars'
|
4
|
+
|
5
|
+
module Handlebars
|
6
|
+
Context = Minibars::Context unless defined? Context
|
7
|
+
SafeString = Minibars::SafeString unless defined? SafeString
|
8
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Minibars
|
4
|
+
# A context for compiling handlebars templates, registering partials, and loading helpers.
|
5
|
+
#
|
6
|
+
# @example
|
7
|
+
# minibars = Minibars::Context.new
|
8
|
+
# template = minibars.compile("{{say}} {{what}}")
|
9
|
+
# template.call(:say => "Hey", :what => "Yuh!") #=> "Hey Yuh!"
|
10
|
+
class Context
|
11
|
+
# Instantiate a new Minibars context, optionally, specify a handlebars file to load.
|
12
|
+
#
|
13
|
+
# @param handlebars_file [String]
|
14
|
+
def initialize(handlebars_file: Handlebars::Source.bundled_path)
|
15
|
+
@js = MiniRacer::Context.new.tap do |js|
|
16
|
+
js.load(handlebars_file)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# Compile the given template string and return a template object.
|
21
|
+
#
|
22
|
+
# @param template [String]
|
23
|
+
# @raise [Minibars::Error] if the template is not a string
|
24
|
+
#
|
25
|
+
# @return [Minibars::Template]
|
26
|
+
def compile(template)
|
27
|
+
Template.compile(self, @js, template)
|
28
|
+
end
|
29
|
+
|
30
|
+
# Register the partial with the given name.
|
31
|
+
#
|
32
|
+
# @example
|
33
|
+
# minibars.register_partial("whoami", "I am {{who}}")
|
34
|
+
# minibars.compile("{{>whoami}}").call(:who => 'Legend') #=> I am Legend
|
35
|
+
#
|
36
|
+
# @param name [String] partial name
|
37
|
+
# @param partial [String] partial content
|
38
|
+
#
|
39
|
+
# @raise [Minibars::Error] if the name or the partial content are not strings
|
40
|
+
# @return [Minibars::Context]
|
41
|
+
def register_partial(name, partial)
|
42
|
+
raise Error, 'Partial name should be a string' unless name.is_a?(String)
|
43
|
+
raise Error, 'Partial content should be a string' unless partial.is_a?(String)
|
44
|
+
|
45
|
+
@js.eval("Handlebars.registerPartial(#{name.to_json}, #{partial.to_json})")
|
46
|
+
|
47
|
+
self
|
48
|
+
end
|
49
|
+
|
50
|
+
# Load JavaScript handlebars helpers from the directory specified by the given glob pattern.
|
51
|
+
#
|
52
|
+
# @example
|
53
|
+
# minibars.load_helpers("#{__dir__}/javascripts/helpers/**/*.js")
|
54
|
+
#
|
55
|
+
# @see https://rubyapi.org/3.1/o/dir#method-c-glob Dir.glob
|
56
|
+
#
|
57
|
+
# @param helpers_pattern [String]
|
58
|
+
#
|
59
|
+
# @return [Minibars::Context]
|
60
|
+
def load_helpers(helpers_pattern)
|
61
|
+
Dir[helpers_pattern].each do |path|
|
62
|
+
load_helper(path)
|
63
|
+
end
|
64
|
+
|
65
|
+
self
|
66
|
+
end
|
67
|
+
|
68
|
+
# Load a handlebars helper from a single JavaScript file.
|
69
|
+
#
|
70
|
+
# @example
|
71
|
+
# minibars.load_helper("#{__dir__}/javascripts/helpers/admin.js")
|
72
|
+
#
|
73
|
+
# @param path [String]
|
74
|
+
#
|
75
|
+
# @return [Minibars::Context]
|
76
|
+
def load_helper(path)
|
77
|
+
@js.load(path)
|
78
|
+
|
79
|
+
self
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Minibars
|
2
|
+
# Mark a string as safe to avoid it being escaped by Handlebars
|
3
|
+
class SafeString
|
4
|
+
def initialize(string)
|
5
|
+
@string = string
|
6
|
+
end
|
7
|
+
|
8
|
+
# @api private
|
9
|
+
def to_json(*)
|
10
|
+
"new Handlebars.SafeString(#{@string.to_json})"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Minibars
|
4
|
+
# A compiled handlebars template.
|
5
|
+
class Template
|
6
|
+
attr_reader :content, :name
|
7
|
+
|
8
|
+
# @api private
|
9
|
+
def self.compile(context, js, content)
|
10
|
+
new(context, js, content).compile
|
11
|
+
end
|
12
|
+
|
13
|
+
# @api private
|
14
|
+
def initialize(context, js, content)
|
15
|
+
@content = content
|
16
|
+
@context = context
|
17
|
+
@js = js
|
18
|
+
@name = "Minibars_Template_#{hash_combine(@context.hash, @content.hash).abs}"
|
19
|
+
end
|
20
|
+
|
21
|
+
# @api private
|
22
|
+
def compile
|
23
|
+
raise Error, 'Template content should be a string' unless content.is_a?(String)
|
24
|
+
|
25
|
+
@js.eval("#{name} = Handlebars.compile(#{content.to_json})")
|
26
|
+
|
27
|
+
self
|
28
|
+
end
|
29
|
+
|
30
|
+
# Render the template with the given parameters.
|
31
|
+
#
|
32
|
+
# @param params [Hash]
|
33
|
+
#
|
34
|
+
# @return [String]
|
35
|
+
def call(params = EMPTY_HASH)
|
36
|
+
@js.eval("#{name}(#{JSON.generate process_params(params)})")
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def process_params(params)
|
42
|
+
return params if params.empty?
|
43
|
+
|
44
|
+
params.transform_values do |value|
|
45
|
+
if value.respond_to?(:call)
|
46
|
+
value.call
|
47
|
+
else
|
48
|
+
value
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def hash_combine(seed, hash)
|
54
|
+
# a la boost, a la clojure
|
55
|
+
seed ^= hash + 0x9e3779b9 + (seed << 6) + (seed >> 2)
|
56
|
+
seed
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
data/lib/minibars/version.rb
CHANGED
data/lib/minibars.rb
CHANGED
@@ -1,4 +1,17 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'json'
|
4
|
+
require 'mini_racer'
|
5
|
+
require 'handlebars/source'
|
6
|
+
|
7
|
+
require 'minibars/error'
|
8
|
+
require 'minibars/context'
|
9
|
+
require 'minibars/template'
|
10
|
+
|
11
|
+
require_relative 'minibars/safe_string'
|
12
|
+
|
13
|
+
# Make use of Handlebars templates from Ruby using mini_racer
|
3
14
|
module Minibars
|
15
|
+
EMPTY_HASH = {}.freeze
|
16
|
+
private_constant :EMPTY_HASH
|
4
17
|
end
|
metadata
CHANGED
@@ -1,59 +1,46 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: minibars
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nicholas Jakobsen
|
8
|
+
- Delon Newman
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
|
-
date:
|
12
|
+
date: 2024-07-09 00:00:00.000000000 Z
|
12
13
|
dependencies:
|
13
14
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
15
|
+
name: mini_racer
|
15
16
|
requirement: !ruby/object:Gem::Requirement
|
16
17
|
requirements:
|
17
18
|
- - "~>"
|
18
19
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
20
|
+
version: 0.6.4
|
20
21
|
type: :runtime
|
21
22
|
prerelease: false
|
22
23
|
version_requirements: !ruby/object:Gem::Requirement
|
23
24
|
requirements:
|
24
25
|
- - "~>"
|
25
26
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
27
|
+
version: 0.6.4
|
27
28
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
29
|
+
name: handlebars-source
|
29
30
|
requirement: !ruby/object:Gem::Requirement
|
30
31
|
requirements:
|
31
|
-
- - "
|
32
|
+
- - ">="
|
32
33
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
34
|
-
type: :
|
35
|
-
prerelease: false
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
37
|
-
requirements:
|
38
|
-
- - "~>"
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
version: '1.3'
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: mysql2
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - "~>"
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: 0.4.10
|
48
|
-
type: :development
|
34
|
+
version: '0'
|
35
|
+
type: :runtime
|
49
36
|
prerelease: false
|
50
37
|
version_requirements: !ruby/object:Gem::Requirement
|
51
38
|
requirements:
|
52
|
-
- - "
|
39
|
+
- - ">="
|
53
40
|
- !ruby/object:Gem::Version
|
54
|
-
version: 0
|
41
|
+
version: '0'
|
55
42
|
- !ruby/object:Gem::Dependency
|
56
|
-
name: rspec
|
43
|
+
name: rspec
|
57
44
|
requirement: !ruby/object:Gem::Requirement
|
58
45
|
requirements:
|
59
46
|
- - "~>"
|
@@ -66,25 +53,36 @@ dependencies:
|
|
66
53
|
- - "~>"
|
67
54
|
- !ruby/object:Gem::Version
|
68
55
|
version: '3.7'
|
69
|
-
description: Minibars is a stripped down
|
56
|
+
description: Minibars is a stripped down implementation of Handlerbars using MiniRacer.
|
70
57
|
It eschews capabilities that require two-way binding with the JS runtime, making
|
71
|
-
it a good
|
72
|
-
path for their
|
58
|
+
it a good choice for those with simple Handlebars templates who need an upgrade
|
59
|
+
path for their ARM64 architecture.
|
73
60
|
email:
|
74
61
|
- nicholas@combinaut.com
|
62
|
+
- contact@delonnewman.name
|
75
63
|
executables: []
|
76
64
|
extensions: []
|
77
65
|
extra_rdoc_files: []
|
78
66
|
files:
|
79
67
|
- MIT-LICENSE
|
68
|
+
- README.md
|
80
69
|
- Rakefile
|
70
|
+
- lib/handlebars.rb
|
81
71
|
- lib/minibars.rb
|
72
|
+
- lib/minibars/context.rb
|
73
|
+
- lib/minibars/error.rb
|
74
|
+
- lib/minibars/safe_string.rb
|
75
|
+
- lib/minibars/template.rb
|
82
76
|
- lib/minibars/version.rb
|
83
|
-
- lib/tasks/minibars_tasks.rake
|
84
77
|
homepage: https://github.com/combinaut/minibars
|
85
78
|
licenses:
|
86
79
|
- MIT
|
87
|
-
metadata:
|
80
|
+
metadata:
|
81
|
+
allowed_push_host: https://rubygems.org
|
82
|
+
homepage_uri: https://github.com/combinaut/minibars
|
83
|
+
source_code_uri: https://github.com/combinaut/minibars
|
84
|
+
changelog_uri: https://github.com/combinaut/minibars/blob/master/CHANGELOG.md
|
85
|
+
documentation_uri: https://www.rubydoc.info/gems/minibars
|
88
86
|
post_install_message:
|
89
87
|
rdoc_options: []
|
90
88
|
require_paths:
|
@@ -96,12 +94,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
96
94
|
version: '0'
|
97
95
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
98
96
|
requirements:
|
99
|
-
- - "
|
97
|
+
- - ">="
|
100
98
|
- !ruby/object:Gem::Version
|
101
|
-
version:
|
99
|
+
version: '0'
|
102
100
|
requirements: []
|
103
|
-
rubygems_version: 3.
|
101
|
+
rubygems_version: 3.5.13
|
104
102
|
signing_key:
|
105
103
|
specification_version: 4
|
106
|
-
summary: Minibars is a stripped down
|
104
|
+
summary: Minibars is a stripped down implementation of Handlerbars using MiniRacer.
|
107
105
|
test_files: []
|