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 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