minibars 0.0.1.alpha → 0.2.0

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: 66c72e077ae845e99620f99cace6436fbee1531c1de7bf61e3c57bd619b3a562
4
- data.tar.gz: 573d6b494c9b427fd3c79b9408faa9bf8ac5426284ab8abf11a2a94ae1ba6d66
3
+ metadata.gz: 29dfecb36dae3be442ea406501052e3df52fa71578647ad1d1e74410e49ddc92
4
+ data.tar.gz: 767861cecb3604b98b8ee615148f784eb9478a13d35bb1bad531eea9a4a631c4
5
5
  SHA512:
6
- metadata.gz: 20e5a241a27a1214634f9a126cdb785c9b6defe7ee104eaf70705c4eee67aab2d6944b849eded5db5bff2b5f009e3120e95061601fe855b1efa70797cfb95885
7
- data.tar.gz: 52b47d651c260ae2e16ef8e2b3498a91d2e4929feeec4510e5f22540818adf029355351b52e904c85322d58b194f3d4463414a200cc2088096fbd27740fa627b
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,3 @@
1
+ module Minibars
2
+ class Error < RuntimeError; end
3
+ 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
@@ -1,3 +1,3 @@
1
1
  module Minibars
2
- VERSION = "0.0.1.alpha"
2
+ VERSION = "0.2.0"
3
3
  end
data/lib/minibars.rb CHANGED
@@ -1,4 +1,17 @@
1
- require 'rails/all'
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.1.alpha
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: 2021-11-29 00:00:00.000000000 Z
12
+ date: 2024-07-09 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
- name: rails
15
+ name: mini_racer
15
16
  requirement: !ruby/object:Gem::Requirement
16
17
  requirements:
17
18
  - - "~>"
18
19
  - !ruby/object:Gem::Version
19
- version: '5.0'
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: '5.0'
27
+ version: 0.6.4
27
28
  - !ruby/object:Gem::Dependency
28
- name: combustion
29
+ name: handlebars-source
29
30
  requirement: !ruby/object:Gem::Requirement
30
31
  requirements:
31
- - - "~>"
32
+ - - ">="
32
33
  - !ruby/object:Gem::Version
33
- version: '1.3'
34
- type: :development
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.4.10
41
+ version: '0'
55
42
  - !ruby/object:Gem::Dependency
56
- name: rspec-rails
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 implmentation of Handlerbars using MiniRacer.
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 upgrade path for those with simple Handlebars templates who need an upgrade
72
- path for their Arm64 architecture.
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: 1.3.1
99
+ version: '0'
102
100
  requirements: []
103
- rubygems_version: 3.0.8
101
+ rubygems_version: 3.5.13
104
102
  signing_key:
105
103
  specification_version: 4
106
- summary: Minibars is a stripped down implmentation of Handlerbars using MiniRacer.
104
+ summary: Minibars is a stripped down implementation of Handlerbars using MiniRacer.
107
105
  test_files: []
@@ -1,2 +0,0 @@
1
- namespace :minibars do
2
- end