serbea 0.7.0 β†’ 0.9.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: 3c69f1aa7916899c197489290d683afad319c66bccff8bd32d3e9a0e943bfa41
4
- data.tar.gz: 267760c9cbbc3cbde6af0a3479b905c4bd8eca6e601dee2d1bb43cb0a819aabd
3
+ metadata.gz: 352c314f5f5a9b6df23933e1b379af39617c82c9b583f4c0703480a5f71df498
4
+ data.tar.gz: 364a353dba20ce3af4bcc071247477ec6dfa6f95c15bb94c88677520344a3cf1
5
5
  SHA512:
6
- metadata.gz: c50177a140769d470f500446902009faac98bb390ef44f7930ed28b3c1cb92ac0a499e15ee2c66384ef0c7a52e55dca892ff2c17fe3f85bc8022b92c2f1c6a6a
7
- data.tar.gz: 330296668991421be44b92b1a4a87470dc93ffd78e4b00530e26003fff1af293a9b4d51ee46fbcac2b541379a6e4c2a0179ec6365fafce14c219905ee8b73617
6
+ metadata.gz: 6bcdd89d15300e24e051f68de0d87899bec18c9f304162e3b667afc7c8a420ab5978e5eb91ab40f8dfd4201375a7fab769d9419a19562196e3ba93b85692e262
7
+ data.tar.gz: 8ba0cddf305d712c3e970adb06979e27f426aae797b2d99702f844e6e5c9248d34a96e35238134314da783e5fbd3de93b56cf7d5701ecc909690719393aa05fc
data/Gemfile CHANGED
@@ -4,5 +4,3 @@ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
4
 
5
5
  # Specify your gem's dependencies in serbea.gemspec
6
6
  gemspec
7
-
8
- gem "erubi", github: "jaredcwhite/erubi", branch: "config-literal-prefix"
data/README.md CHANGED
@@ -1,8 +1,8 @@
1
- πŸ‘‘ Serbea: Similar to ERB, Except Awesomer
1
+ # πŸ‘‘ Serbea: Similar to ERB, Except Awesomer
2
2
 
3
- The Ruby template language you always dreamed of is here. Le roi est mort, vive le roi!
3
+ The Ruby template language you've always dreamed of is finally here. _Le roi est mort, vive le roi!_
4
4
 
5
- Serbea combines the best ideas from "brace-style" template languages such as Liquid, Nunjucks, Twig, Jinja, Mustache, etc.β€”and applies them to the world of ERB. You can use Serbea in Rails application, Bridgetown static sites, or pretty much any Ruby scenario you could imagine.
5
+ Serbea combines the best ideas from "brace-style" template languages such as Liquid, Nunjucks, Twig, Jinja, Mustache, etc.β€”and applies them to the world of ERB. You can use Serbea in Rails applications, Bridgetown static sites, or pretty much any Ruby scenario you could imagine.
6
6
 
7
7
  ## Features
8
8
 
@@ -11,9 +11,9 @@ Serbea combines the best ideas from "brace-style" template languages such as Liq
11
11
  * Autoescaped variables by default within the pipeline (`{{ }}`) tags. Use the `safe`/`raw` or `escape`/`h` filters to control escaping on output.
12
12
  * Render directive `{%@ %}` as shortcut for rendering either string-named partials (`render "tmpl"`) or object instances (`render MyComponent.new`).
13
13
  * Supports every convention of ERB and builds upon it with new features (which is why it's "awesomer!").
14
- * Builtin frontmatter support (even in Rails!) so you can access the variables written into the top YAML within your templates.
14
+ * Builtin frontmatter support so you can access the variables written into the top YAML within your templates. In any Rails view, including layouts, you'll have access to the `@frontmatter` ivar which is a merged `HashWithDotAccess::Hash` with data from any part of the view tree (partials, pages, layout).
15
15
  * The filters accessible within Serbea templates are either helpers (where the variable gets passed as the first argument) or instance methods of the variable itself, so you can build extremely expressive pipelines that take advantage of the code you already know and love. (For example, in Rails you could write `{{ "My Link" | link_to: route_path }}`).
16
- * The `Serbea::Pipeline.exec` method lets you pass a pipeline template in, along with an optional input value or included helpers module, and you'll get the output as a object of any type (not converted to a string like in traditional templates). For example: `Serbea::Pipeline.exec("[1,2,3] |> map: ->(i) { i * 10 }")` will return `[10, 20, 30]`.
16
+ * The `Serbea::Pipeline.exec` method lets you pass a pipeline template in, along with an optional input value or included helpers module, and you'll get the output as a object of any type (not converted to a string like in traditional templates). For example: `Serbea::Pipeline.exec("arr |> map: ->(i) { i * 10 }", arr: [1,2,3])` will return `[10, 20, 30]`.
17
17
 
18
18
  ## What It Looks Like
19
19
 
@@ -4,14 +4,13 @@ require "tilt/erubi"
4
4
  require "serbea/helpers"
5
5
  require "serbea/pipeline"
6
6
  require "serbea/template_engine"
7
- require "serbea/component_renderer"
8
7
 
9
8
  module Tilt
10
9
  class SerbeaTemplate < ErubiTemplate
11
10
  def prepare
12
11
  @options.merge!(
13
12
  outvar: "@_erbout",
14
- bufval: "Serbea::Buffer.new",
13
+ bufval: "Serbea::OutputBuffer.new",
15
14
  literal_prefix: "{%",
16
15
  literal_postfix: "%}",
17
16
  engine_class: Serbea::TemplateEngine
@@ -32,6 +31,8 @@ if defined?(Rails::Railtie)
32
31
  initializer :serbea do |app|
33
32
  ActiveSupport.on_load(:action_view) do
34
33
  require "serbea/rails_support"
34
+
35
+ ActionController::Base.include Serbea::Rails::FrontmatterControllerActions
35
36
  end
36
37
  end
37
38
  end
@@ -40,6 +40,8 @@ module Bridgetown
40
40
  #
41
41
  # @return [String] The converted content.
42
42
  def convert(content, convertible)
43
+ return content if convertible.data[:template_engine] != "serbea"
44
+
43
45
  serb_view = Bridgetown::SerbeaView.new(convertible)
44
46
 
45
47
  serb_renderer = Tilt::SerbeaTemplate.new(convertible.relative_path) { content }
@@ -53,16 +55,17 @@ module Bridgetown
53
55
  end
54
56
  end
55
57
 
56
- def matches(ext, convertible = nil)
57
- if convertible
58
- if convertible.data[:template_engine] == "serbea" ||
59
- (convertible.data[:template_engine].nil? &&
60
- @config[:template_engine] == "serbea")
61
- return true
62
- end
58
+ def matches(ext, convertible)
59
+ if convertible.data[:template_engine] == "serbea" ||
60
+ (convertible.data[:template_engine].nil? &&
61
+ @config[:template_engine] == "serbea")
62
+ convertible.data[:template_engine] = "serbea"
63
+ return true
63
64
  end
64
65
 
65
- super(ext)
66
+ super(ext).tap do |ext_matches|
67
+ convertible.data[:template_engine] = "serbea" if ext_matches
68
+ end
66
69
  end
67
70
 
68
71
  def output_ext(ext)
@@ -71,13 +74,3 @@ module Bridgetown
71
74
  end
72
75
  end
73
76
  end
74
-
75
- Bridgetown::Hooks.register :site, :pre_render, reloadable: false do |site|
76
- # make sure Liquid doesn't find {% %} and decide to process Serbea code!
77
- site.contents.each do |convertible|
78
- convertible.data.render_with_liquid = false if convertible.extname == ".serb"
79
- end
80
- site.layouts.values.each do |convertible|
81
- convertible.data.render_with_liquid = false if convertible.ext == ".serb"
82
- end
83
- end
@@ -8,11 +8,12 @@ module Serbea
8
8
 
9
9
  def capture(obj = nil, &block)
10
10
  previous_buffer_state = @_erbout
11
- @_erbout = Serbea::Buffer.new
11
+ @_erbout = Serbea::OutputBuffer.new
12
12
 
13
13
  # For compatibility with ActionView, not used by Bridgetown normally
14
14
  previous_ob_state = @output_buffer
15
- @output_buffer = Serbea::Buffer.new
15
+ @output_buffer = Serbea::OutputBuffer.new
16
+
16
17
 
17
18
  result = instance_exec(obj, &block)
18
19
  if @output_buffer != ""
@@ -22,7 +23,7 @@ module Serbea
22
23
  @_erbout = previous_buffer_state
23
24
  @output_buffer = previous_ob_state
24
25
 
25
- result.html_safe
26
+ result&.html_safe
26
27
  end
27
28
 
28
29
  def pipeline(context, value)
@@ -32,11 +33,11 @@ module Serbea
32
33
  def helper(name, &helper_block)
33
34
  self.class.define_method(name) do |*args, &block|
34
35
  previous_buffer_state = @_erbout
35
- @_erbout = Serbea::Buffer.new
36
+ @_erbout = Serbea::OutputBuffer.new
36
37
 
37
38
  # For compatibility with ActionView, not used by Bridgetown normally
38
39
  previous_ob_state = @output_buffer
39
- @output_buffer = Serbea::Buffer.new
40
+ @output_buffer = Serbea::OutputBuffer.new
40
41
 
41
42
  result = helper_block.call(*args, &block)
42
43
  if @output_buffer != ""
@@ -1,12 +1,13 @@
1
1
  require "active_support/core_ext/string/output_safety"
2
+ require "active_support/core_ext/object/blank"
2
3
 
3
4
  module Serbea
4
5
  class Pipeline
5
- def self.exec(template, input: (no_input_passed = true; nil), include_helpers: nil)
6
+ def self.exec(template, locals = {}, include_helpers: nil, **kwargs)
6
7
  anon = Class.new do
7
8
  include Serbea::Helpers
8
9
 
9
- attr_accessor :input, :output
10
+ attr_accessor :output
10
11
  end
11
12
 
12
13
  if include_helpers
@@ -14,12 +15,11 @@ module Serbea
14
15
  end
15
16
 
16
17
  pipeline_obj = anon.new
17
- pipeline_obj.input = input unless no_input_passed
18
18
 
19
19
  full_template = "{{ #{template} | assign_to: :output }}"
20
20
 
21
21
  tmpl = Tilt::SerbeaTemplate.new { full_template }
22
- tmpl.render(pipeline_obj)
22
+ tmpl.render(pipeline_obj, locals.presence || kwargs)
23
23
 
24
24
  pipeline_obj.output
25
25
  end
@@ -54,8 +54,9 @@ module Serbea
54
54
  @value_methods_denylist ||= Set.new
55
55
  end
56
56
 
57
- def initialize(context, value)
58
- @context = context
57
+ def initialize(binding, value)
58
+ @binding = binding
59
+ @context = binding.receiver
59
60
  @value = value
60
61
  end
61
62
 
@@ -83,6 +84,19 @@ module Serbea
83
84
  else
84
85
  @value = @context.send(name, @value, *args)
85
86
  end
87
+ elsif @binding.local_variables.include?(name)
88
+ var = @binding.local_variable_get(name)
89
+ if var.respond_to?(:call)
90
+ unless kwargs.empty?
91
+ @value = var.call(@value, *args, **kwargs)
92
+ else
93
+ @value = var.call(@value, *args)
94
+ end
95
+ else
96
+ "Serbea warning: Filter #{name} does not respond to call".tap do |warning|
97
+ self.class.raise_on_missing_filters ? raise(warning) : STDERR.puts(warning)
98
+ end
99
+ end
86
100
  else
87
101
  "Serbea warning: Filter not found: #{name}".tap do |warning|
88
102
  self.class.raise_on_missing_filters ? raise(warning) : STDERR.puts(warning)
@@ -1,22 +1,40 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- # inspired by https://github.com/haml/haml/blob/main/lib/haml/plugin.rb
4
3
  module Serbea
4
+ module Rails
5
+ module FrontmatterHelpers
6
+ def set_page_frontmatter=(data)
7
+ @frontmatter ||= HashWithDotAccess::Hash.new
8
+ @frontmatter.update(data)
9
+ end
10
+ end
11
+
12
+ module FrontmatterControllerActions
13
+ extend ActiveSupport::Concern
5
14
 
6
- # This module makes Serbea work with Rails using the template handler API.
7
- class Plugin
8
- def handles_encoding?; true; end
15
+ included do
16
+ Serbea::TemplateEngine.front_matter_preamble = "self.set_page_frontmatter = local_frontmatter = YAML.load"
17
+
18
+ before_action { @frontmatter ||= HashWithDotAccess::Hash.new }
9
19
 
10
- def compile(template, source)
11
- "self.class.include(Serbea::Helpers);" + Tilt::SerbeaTemplate.new { source }.precompiled_template([])
20
+ helper Serbea::Rails::FrontmatterHelpers
21
+ end
12
22
  end
13
23
 
14
- def self.call(template, source = nil)
15
- source ||= template.source
24
+ class TemplateHandler
25
+ def handles_encoding?; true; end
26
+
27
+ def compile(template, source)
28
+ "self.class.include(Serbea::Helpers);" + Tilt::SerbeaTemplate.new { source }.precompiled_template([])
29
+ end
30
+
31
+ def self.call(template, source = nil)
32
+ source ||= template.source
16
33
 
17
- new.compile(template, source)
34
+ new.compile(template, source)
35
+ end
18
36
  end
19
37
  end
20
38
  end
21
39
 
22
- ActionView::Template.register_template_handler(:serb, Serbea::Plugin)
40
+ ActionView::Template.register_template_handler(:serb, Serbea::Rails::TemplateHandler)
@@ -1,7 +1,7 @@
1
1
  require "strscan"
2
2
 
3
3
  module Serbea
4
- class Buffer < String
4
+ class OutputBuffer < String
5
5
  def concat_to_s(input)
6
6
  concat input.to_s
7
7
  end
@@ -66,13 +66,11 @@ module Serbea
66
66
 
67
67
  # Ensure the raw "tag" will strip out all ERB-style processing
68
68
  until string.empty?
69
- text, code, string = string.partition(/{% raw %}.*?{% endraw %}/m)
69
+ text, code, string = string.partition(/{% raw %}(.*?){% endraw %}/m)
70
70
 
71
71
  buff << text
72
72
  if code.length > 0
73
- buff << code.
74
- sub("{% raw %}", "").
75
- sub("{% endraw %}", "").
73
+ buff << $1.
76
74
  gsub("{{", "__RAW_START_PRINT__").
77
75
  gsub("}}", "__RAW_END_PRINT__").
78
76
  gsub("{%", "__RAW_START_EVAL__").
@@ -84,17 +82,16 @@ module Serbea
84
82
  string = buff
85
83
  buff = ""
86
84
  until string.empty?
87
- text, code, string = string.partition(/{{.*?}}/m)
85
+ text, code, string = string.partition(/{{(.*?)}}/m)
88
86
 
89
87
  buff << text
90
88
  if code.length > 0
91
89
  original_line_length = code.lines.size
92
90
 
93
- s = StringScanner.new(code[2...-2])
94
- done = false
91
+ s = StringScanner.new($1)
95
92
  escaped_segment = ""
96
93
  segments = []
97
- while !done
94
+ until s.eos?
98
95
  portion = s.scan_until(/\|>?/)
99
96
  if portion
100
97
  if portion.end_with?('\|')
@@ -124,11 +121,11 @@ module Serbea
124
121
  # or just the rest will do
125
122
  segments << s.rest
126
123
  end
127
- done = true
124
+ s.terminate
128
125
  end
129
126
  end
130
127
 
131
- segments[0] = "pipeline(self, (#{segments[0].strip}))"
128
+ segments[0] = "pipeline(binding, (#{segments[0].strip}))"
132
129
  segments[1..-1].each_with_index do |segment, index|
133
130
  filter, args = segment.strip.match(/([^ :]*)(.*)/m).captures
134
131
  segments[index + 1] = ".filter(:" + filter
@@ -148,24 +145,15 @@ module Serbea
148
145
  end
149
146
  end
150
147
 
151
- # Process any directives
152
- #
153
- # TODO: allow custom directives! aka
154
- # {%@something whatever %}
155
- # {%@script
156
- # const foo = "really? #{really}!"
157
- # alert(foo.toLowerCase())
158
- # %}
159
- # {%@preact AwesomeChart data={#{ruby_data.to_json}} %}
148
+ # Process any render directives
160
149
  string = buff
161
150
  buff = ""
162
151
  until string.empty?
163
- text, code, string = string.partition(/{%@.*?%}/m)
152
+ text, code, string = string.partition(/{%@(.*?)%}/m)
164
153
 
165
154
  buff << text
166
155
  if code.length > 0
167
- code.sub!(/^\{%@/, "")
168
- code.sub!(/%}$/, "")
156
+ code = $1
169
157
  unless ["end", ""].include? code.strip
170
158
  original_line_length = code.lines.size
171
159
 
@@ -1,3 +1,3 @@
1
1
  module Serbea
2
- VERSION = "0.7.0"
2
+ VERSION = "0.9.0"
3
3
  end
@@ -16,8 +16,10 @@ Gem::Specification.new do |spec|
16
16
  spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r!^(test|script|spec|features)/!) }
17
17
  spec.require_paths = ["lib"]
18
18
 
19
- spec.add_runtime_dependency("rake", "~> 13.0")
20
- spec.add_runtime_dependency("erubi", "~> 1.9")
21
19
  spec.add_runtime_dependency("activesupport", "~> 6.0")
20
+ spec.add_runtime_dependency("erubi", ">= 1.10")
21
+ spec.add_runtime_dependency("hash_with_dot_access", "~> 1.1")
22
22
  spec.add_runtime_dependency("tilt", "~> 2.0")
23
+
24
+ spec.add_development_dependency("rake", "~> 13.0")
23
25
  end
metadata CHANGED
@@ -1,57 +1,57 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: serbea
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bridgetown Team
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-10-31 00:00:00.000000000 Z
11
+ date: 2020-11-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: rake
14
+ name: activesupport
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '13.0'
19
+ version: '6.0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '13.0'
26
+ version: '6.0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: erubi
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: '1.9'
33
+ version: '1.10'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - "~>"
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: '1.9'
40
+ version: '1.10'
41
41
  - !ruby/object:Gem::Dependency
42
- name: activesupport
42
+ name: hash_with_dot_access
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '6.0'
47
+ version: '1.1'
48
48
  type: :runtime
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: '6.0'
54
+ version: '1.1'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: tilt
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: '2.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '13.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '13.0'
69
83
  description:
70
84
  email: maintainers@bridgetownrb.com
71
85
  executables: []
@@ -78,7 +92,6 @@ files:
78
92
  - Rakefile
79
93
  - lib/serbea.rb
80
94
  - lib/serbea/bridgetown_support.rb
81
- - lib/serbea/component_renderer.rb
82
95
  - lib/serbea/helpers.rb
83
96
  - lib/serbea/pipeline.rb
84
97
  - lib/serbea/rails_support.rb
@@ -1,19 +0,0 @@
1
- module Serbea
2
- class ComponentRenderer
3
- include Helpers
4
-
5
- def initialize(variables = {})
6
- @variables = variables
7
- end
8
-
9
- def respond_to_missing?(key, include_private = false)
10
- @variables.key?(key)
11
- end
12
-
13
- def method_missing(key)
14
- return @variables[key] if respond_to_missing?(key)
15
-
16
- super
17
- end
18
- end
19
- end