sugar_bee 0.1.0 → 0.2.2
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 +4 -4
- data/README.md +1 -1
- data/Rakefile +4 -3
- data/lib/sugar_bee/errors.rb +9 -0
- data/lib/sugar_bee/parser.rb +30 -0
- data/lib/sugar_bee/srb/compiler.rb +72 -0
- data/lib/sugar_bee/srb/grammar.rb +80 -0
- data/lib/sugar_bee/template_handler.rb +15 -0
- data/lib/sugar_bee/version.rb +3 -1
- data/lib/sugar_bee.rb +4 -6
- metadata +18 -40
- data/.rspec +0 -3
- data/.standard.yml +0 -3
- data/lib/sugar_bee/handler.rb +0 -18
- data/lib/sugar_bee/railtie.rb +0 -9
- data/lib/sugar_bee/srb.rb +0 -28
- data/lib/sugar_bee/srb_to_erb.rb +0 -32
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 0f2cc41e7f639d90d331659d7eaafad8e852e512ef11384b7129bb40e3810634
|
|
4
|
+
data.tar.gz: 6c99912c8d11226b9023a1c0bc597111379db1c49844e115d8a9fe4cb8bae414
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 223214a0a2d6c7c32b92bf2da03194c86c9c7bfbc2b7aef90b72ba239702eee2ddef4988d9c5d1a72326d7c00af3a8392473c4f55476c18b6ae6a907c1ffa24d
|
|
7
|
+
data.tar.gz: 25c117707750a4e3c0ca4f6d8635e3f74142ab337057a7a635c8daf50f71c9070e42eb20a01b1efb2a8152ac0efa6fcff6b5d6e13a5714b84234a387efe4f361
|
data/README.md
CHANGED
|
@@ -26,7 +26,7 @@ TODO: Write usage instructions here
|
|
|
26
26
|
|
|
27
27
|
## Development
|
|
28
28
|
|
|
29
|
-
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake
|
|
29
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
|
30
30
|
|
|
31
31
|
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
|
32
32
|
|
data/Rakefile
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "bundler/gem_tasks"
|
|
4
|
-
|
|
4
|
+
Bundler::GemHelper.tag_prefix = "sugar_bee-"
|
|
5
|
+
require "minitest/test_task"
|
|
5
6
|
|
|
6
|
-
|
|
7
|
+
Minitest::TestTask.create
|
|
7
8
|
|
|
8
9
|
require "standard/rake"
|
|
9
10
|
|
|
10
|
-
task default: %i[
|
|
11
|
+
task default: %i[test standard]
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "parslet"
|
|
4
|
+
require_relative "errors"
|
|
5
|
+
require_relative "srb/grammar"
|
|
6
|
+
require_relative "srb/compiler"
|
|
7
|
+
|
|
8
|
+
module SugarBee
|
|
9
|
+
# Public interface: `.srb` source string in → compiled ERB string out.
|
|
10
|
+
# Pure function, no Rails coupling. Parses with the SRB::Grammar, compiles with
|
|
11
|
+
# the SRB::Compiler transform.
|
|
12
|
+
module Parser
|
|
13
|
+
def self.call(source)
|
|
14
|
+
SRB::Compiler.new.apply(SRB::Grammar.new.parse(source))
|
|
15
|
+
rescue Parslet::ParseFailed => e
|
|
16
|
+
raise ParseError, "Invalid .srb template: #{deepest_failure_line(e)}"
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# The root of `parse_failure_cause.ascii_tree` reports where the top-level
|
|
20
|
+
# repetition gave up (often "line 1 char 1"); the line that progressed
|
|
21
|
+
# furthest into the input is the one that names the actual problem.
|
|
22
|
+
def self.deepest_failure_line(error)
|
|
23
|
+
error.parse_failure_cause.ascii_tree.lines
|
|
24
|
+
.map { |line| line.strip.sub(/\A[|`\s-]+/, "") }
|
|
25
|
+
.reverse # ties resolve to the deepest (most specific) tree node
|
|
26
|
+
.max_by { |line| line.match(/line (\d+) char (\d+)\.\z/) { |m| [m[1].to_i, m[2].to_i] } || [0, 0] }
|
|
27
|
+
end
|
|
28
|
+
private_class_method :deepest_failure_line
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "parslet"
|
|
4
|
+
require_relative "../errors"
|
|
5
|
+
|
|
6
|
+
module SugarBee
|
|
7
|
+
module SRB
|
|
8
|
+
# Compiles an SRB::Grammar parse tree into an ERB string.
|
|
9
|
+
# `tokens:` is ALWAYS emitted (even empty → `%i[]`); tag pairs emit `do |c|`
|
|
10
|
+
# (the block param is the slot receiver Story 4.4 will use). Self-closing tags
|
|
11
|
+
# emit no block.
|
|
12
|
+
class Compiler < Parslet::Transform
|
|
13
|
+
# Marks a kv-pair kwarg so render_call can partition it away from plain
|
|
14
|
+
# token strings; `code` is the already-formatted Ruby value (quoted or verbatim).
|
|
15
|
+
KvPair = Struct.new(:key, :code)
|
|
16
|
+
|
|
17
|
+
rule(text: simple(:t)) { t.to_s }
|
|
18
|
+
rule(token: simple(:t)) { t.to_s }
|
|
19
|
+
rule(source: sequence(:nodes)) { nodes.join }
|
|
20
|
+
|
|
21
|
+
rule(grouped: {prefix: simple(:prefix), inner: subtree(:inner)}) do
|
|
22
|
+
Array(inner).map { |tok| "#{prefix}:#{tok}" }
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
rule(kv: {key: simple(:key), dq: subtree(:val)}) do
|
|
26
|
+
content = val.is_a?(Array) ? "" : val.to_s
|
|
27
|
+
KvPair.new(key.to_s, "\"#{content}\"")
|
|
28
|
+
end
|
|
29
|
+
rule(kv: {key: simple(:key), bare: simple(:val)}) { KvPair.new(key.to_s, val.to_s) }
|
|
30
|
+
|
|
31
|
+
rule(self_close: {name: simple(:name), args: subtree(:args)}) do
|
|
32
|
+
"<%= render(#{Compiler.render_call(name, args)}) %>"
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
rule(tag_pair: {name: simple(:name), args: subtree(:args), source: subtree(:children), close: simple(:close)}) do
|
|
36
|
+
unless name.to_s == close.to_s
|
|
37
|
+
raise SugarBee::ParseError, "Mismatched tags: <#{name}> closed by </#{close}>"
|
|
38
|
+
end
|
|
39
|
+
"<%= render(#{Compiler.render_call(name, args)}) do |c| %>#{Array(children).join}<% end %>"
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
rule(slot: {sname: simple(:sname), source: subtree(:children), close: simple(:close)}) do
|
|
43
|
+
unless sname.to_s == close.to_s
|
|
44
|
+
raise SugarBee::ParseError, "Mismatched slot tags: <:#{sname}> closed by </:#{close}>"
|
|
45
|
+
end
|
|
46
|
+
"<% c.with_#{sname} do %>#{Array(children).join}<% end %>"
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def self.render_call(name, args)
|
|
50
|
+
const = "#{name}Component"
|
|
51
|
+
unless Object.const_defined?(const)
|
|
52
|
+
raise SugarBee::UnknownComponentError, "Unknown component <#{name}>: no #{const} class is defined"
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
token_strings, kv_pairs = [], []
|
|
56
|
+
Array(args).each do |item|
|
|
57
|
+
case item
|
|
58
|
+
when KvPair
|
|
59
|
+
unless item.key.match?(/\A[a-z_][a-zA-Z0-9_]*\z/)
|
|
60
|
+
raise SugarBee::ParseError, "Invalid attribute key '#{item.key}': not a valid Ruby keyword argument"
|
|
61
|
+
end
|
|
62
|
+
kv_pairs << "#{item.key}: #{item.code}"
|
|
63
|
+
when Array then token_strings.concat(item)
|
|
64
|
+
else token_strings << item
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
kwargs = kv_pairs.empty? ? "" : ", #{kv_pairs.join(", ")}"
|
|
68
|
+
"#{const}.new(tokens: %i[#{token_strings.join(" ")}]#{kwargs})"
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "parslet"
|
|
4
|
+
|
|
5
|
+
module SugarBee
|
|
6
|
+
module SRB
|
|
7
|
+
# PEG grammar for the `.srb` template language (structure only; codegen lives
|
|
8
|
+
# in SRB::Compiler).
|
|
9
|
+
class Grammar < Parslet::Parser
|
|
10
|
+
root(:source)
|
|
11
|
+
|
|
12
|
+
rule(:source) { (erb | component | slot | passthrough).repeat.as(:source) }
|
|
13
|
+
|
|
14
|
+
# ERB tags are atomic: the whole `<% ... %>` / `<%= ... %>` run is one
|
|
15
|
+
# opaque verbatim unit, terminated by the first subsequent `%>`. The
|
|
16
|
+
# parser never looks inside — no interpretation of Ruby content (FR-25/26).
|
|
17
|
+
rule(:erb) { (erb_edge >> (str("%>").absent? >> any).repeat >> str("%>")).as(:text) }
|
|
18
|
+
|
|
19
|
+
# Verbatim text: plain HTML, lowercase tags — anything not opening/closing a component, slot, or ERB tag.
|
|
20
|
+
rule(:passthrough) { (node_edge.absent? >> any).repeat(1).as(:text) }
|
|
21
|
+
rule(:node_edge) { component_edge | slot_edge | erb_edge }
|
|
22
|
+
rule(:component_edge) { (str("<") >> match["A-Z"]) | (str("</") >> sp? >> match["A-Z"]) }
|
|
23
|
+
# Only a lowercase-initial name opens a slot, so `<:` before anything else
|
|
24
|
+
# (uppercase, space, punctuation) falls through to passthrough as verbatim
|
|
25
|
+
# text instead of hard-failing the whole parse.
|
|
26
|
+
rule(:slot_edge) { (str("<:") | str("</:")) >> match["a-z"] }
|
|
27
|
+
# Stops passthrough at `<%` so the `erb` rule claims the tag whole —
|
|
28
|
+
# without this, passthrough would consume into an ERB tag and could
|
|
29
|
+
# hard-stop at a `<`+uppercase inside it (e.g. `<%= "<Box>" %>`).
|
|
30
|
+
# `<%%` (ERB's literal-escape) is excluded: it is not an ERB opener, so
|
|
31
|
+
# neither the erb rule claims it nor does passthrough stop at it — the
|
|
32
|
+
# sequence falls through to passthrough and emits verbatim.
|
|
33
|
+
rule(:erb_edge) { str("<%") >> str("%").absent? }
|
|
34
|
+
|
|
35
|
+
rule(:component) { self_close | tag_pair }
|
|
36
|
+
rule(:self_close) { (str("<") >> cname >> args >> sp? >> str("/>")).as(:self_close) }
|
|
37
|
+
rule(:tag_pair) do
|
|
38
|
+
(str("<") >> cname >> args >> sp? >> str(">") >>
|
|
39
|
+
source >> str("</") >> sp? >> cname_close.as(:close) >> sp? >> str(">")).as(:tag_pair)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
rule(:cname) { (match["A-Z"] >> match["A-Za-z"].repeat).as(:name) }
|
|
43
|
+
rule(:cname_close) { match["A-Z"] >> match["A-Za-z"].repeat }
|
|
44
|
+
|
|
45
|
+
rule(:slot) do
|
|
46
|
+
(str("<:") >> sname >> sp? >> str(">") >>
|
|
47
|
+
source >> str("</:") >> sp? >> sname_close.as(:close) >> sp? >> str(">")).as(:slot)
|
|
48
|
+
end
|
|
49
|
+
rule(:sname) { (match["a-z"] >> match["a-zA-Z0-9_"].repeat).as(:sname) }
|
|
50
|
+
rule(:sname_close) { match["a-z"] >> match["a-zA-Z0-9_"].repeat }
|
|
51
|
+
|
|
52
|
+
# Mixed bag: tokens (bare/grouped) AND kv pairs. Compiler partitions them apart.
|
|
53
|
+
rule(:args) { (sp >> attr).repeat.as(:args) }
|
|
54
|
+
rule(:attr) { grouped | kvattr | token }
|
|
55
|
+
|
|
56
|
+
rule(:grouped) do
|
|
57
|
+
(match["^:\\[\\s"].repeat(1).as(:prefix) >> str(":[") >>
|
|
58
|
+
(group_token >> (sp >> group_token).repeat).as(:inner) >> str("]")).as(:grouped)
|
|
59
|
+
end
|
|
60
|
+
# Same charset as `token`, but a bare "]" ends the token so the group's
|
|
61
|
+
# closing bracket is never swallowed. A balanced "[...]" run (arbitrary
|
|
62
|
+
# values like gap-[13px]) is consumed whole, so its inner "]" doesn't
|
|
63
|
+
# terminate the group prematurely.
|
|
64
|
+
rule(:group_token) do
|
|
65
|
+
(bracketed | (str("/") >> str(">").absent?) | match["^\\s/>\\[\\]"]).repeat(1).as(:token)
|
|
66
|
+
end
|
|
67
|
+
rule(:bracketed) { str("[") >> match["^\\]"].repeat >> str("]") }
|
|
68
|
+
|
|
69
|
+
rule(:kvattr) { (key.as(:key) >> str("=") >> (dquoted | unquoted)).as(:kv) }
|
|
70
|
+
rule(:key) { match["a-zA-Z_\\-"].repeat(1) }
|
|
71
|
+
rule(:dquoted) { str('"') >> match['^"'].repeat.as(:dq) >> str('"') }
|
|
72
|
+
rule(:unquoted) { match["^\\s/>"].repeat(1).as(:bare) }
|
|
73
|
+
|
|
74
|
+
rule(:token) { ((str("/") >> str(">").absent?) | match["^\\s/>"]).repeat(1).as(:token) }
|
|
75
|
+
|
|
76
|
+
rule(:sp) { match["\\s"].repeat(1) }
|
|
77
|
+
rule(:sp?) { sp.maybe }
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "action_view"
|
|
4
|
+
require_relative "parser"
|
|
5
|
+
|
|
6
|
+
module SugarBee
|
|
7
|
+
module TemplateHandler
|
|
8
|
+
def self.call(template, source)
|
|
9
|
+
compiled_erb = Parser.call(source)
|
|
10
|
+
ActionView::Template.handler_for_extension(:erb).call(template, compiled_erb)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
ActionView::Template.register_template_handler(:srb, SugarBee::TemplateHandler)
|
data/lib/sugar_bee/version.rb
CHANGED
data/lib/sugar_bee.rb
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "action_view"
|
|
3
4
|
require_relative "sugar_bee/version"
|
|
4
|
-
require_relative "sugar_bee/
|
|
5
|
-
require_relative "sugar_bee/
|
|
6
|
-
|
|
7
|
-
module SugarBee
|
|
8
|
-
class Error < StandardError; end
|
|
9
|
-
end
|
|
5
|
+
require_relative "sugar_bee/errors"
|
|
6
|
+
require_relative "sugar_bee/parser"
|
|
7
|
+
require_relative "sugar_bee/template_handler"
|
metadata
CHANGED
|
@@ -1,34 +1,28 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: sugar_bee
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Fabio Papa
|
|
8
8
|
bindir: exe
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date:
|
|
10
|
+
date: 2026-07-18 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
|
-
name:
|
|
13
|
+
name: actionview
|
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
|
15
15
|
requirements:
|
|
16
16
|
- - ">="
|
|
17
17
|
- !ruby/object:Gem::Version
|
|
18
|
-
version: 7.
|
|
19
|
-
- - "<"
|
|
20
|
-
- !ruby/object:Gem::Version
|
|
21
|
-
version: 9.0.0
|
|
18
|
+
version: '7.1'
|
|
22
19
|
type: :runtime
|
|
23
20
|
prerelease: false
|
|
24
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
25
22
|
requirements:
|
|
26
23
|
- - ">="
|
|
27
24
|
- !ruby/object:Gem::Version
|
|
28
|
-
version: 7.
|
|
29
|
-
- - "<"
|
|
30
|
-
- !ruby/object:Gem::Version
|
|
31
|
-
version: 9.0.0
|
|
25
|
+
version: '7.1'
|
|
32
26
|
- !ruby/object:Gem::Dependency
|
|
33
27
|
name: parslet
|
|
34
28
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -43,45 +37,29 @@ dependencies:
|
|
|
43
37
|
- - "~>"
|
|
44
38
|
- !ruby/object:Gem::Version
|
|
45
39
|
version: '2.0'
|
|
46
|
-
|
|
47
|
-
name: rspec
|
|
48
|
-
requirement: !ruby/object:Gem::Requirement
|
|
49
|
-
requirements:
|
|
50
|
-
- - "~>"
|
|
51
|
-
- !ruby/object:Gem::Version
|
|
52
|
-
version: '3.0'
|
|
53
|
-
type: :development
|
|
54
|
-
prerelease: false
|
|
55
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
56
|
-
requirements:
|
|
57
|
-
- - "~>"
|
|
58
|
-
- !ruby/object:Gem::Version
|
|
59
|
-
version: '3.0'
|
|
60
|
-
description: Handles a new SRB template type that builds on ERB, allowing JSX-like
|
|
61
|
-
tags that render ViewComponents.`<Card></Card>` renders `CardComponent` for example.
|
|
40
|
+
description: ActionView .srb template handler for Sugar Cube.
|
|
62
41
|
email:
|
|
63
42
|
- me@fabiopapa.dev
|
|
64
43
|
executables: []
|
|
65
44
|
extensions: []
|
|
66
45
|
extra_rdoc_files: []
|
|
67
46
|
files:
|
|
68
|
-
- ".rspec"
|
|
69
|
-
- ".standard.yml"
|
|
70
47
|
- README.md
|
|
71
48
|
- Rakefile
|
|
72
49
|
- lib/sugar_bee.rb
|
|
73
|
-
- lib/sugar_bee/
|
|
74
|
-
- lib/sugar_bee/
|
|
75
|
-
- lib/sugar_bee/srb.rb
|
|
76
|
-
- lib/sugar_bee/
|
|
50
|
+
- lib/sugar_bee/errors.rb
|
|
51
|
+
- lib/sugar_bee/parser.rb
|
|
52
|
+
- lib/sugar_bee/srb/compiler.rb
|
|
53
|
+
- lib/sugar_bee/srb/grammar.rb
|
|
54
|
+
- lib/sugar_bee/template_handler.rb
|
|
77
55
|
- lib/sugar_bee/version.rb
|
|
78
56
|
- sig/sugar_bee.rbs
|
|
79
|
-
homepage: https://github.com/fapapa/sugar_bee
|
|
57
|
+
homepage: https://github.com/fapapa/sugar_cube_system/tree/main/gems/sugar_bee
|
|
80
58
|
licenses: []
|
|
81
59
|
metadata:
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
60
|
+
allowed_push_host: https://rubygems.org
|
|
61
|
+
homepage_uri: https://github.com/fapapa/sugar_cube_system/tree/main/gems/sugar_bee
|
|
62
|
+
source_code_uri: https://github.com/fapapa/sugar_cube_system/tree/main/gems/sugar_bee
|
|
85
63
|
rdoc_options: []
|
|
86
64
|
require_paths:
|
|
87
65
|
- lib
|
|
@@ -89,14 +67,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
89
67
|
requirements:
|
|
90
68
|
- - ">="
|
|
91
69
|
- !ruby/object:Gem::Version
|
|
92
|
-
version: 3.
|
|
70
|
+
version: 3.2.0
|
|
93
71
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
94
72
|
requirements:
|
|
95
73
|
- - ">="
|
|
96
74
|
- !ruby/object:Gem::Version
|
|
97
75
|
version: '0'
|
|
98
76
|
requirements: []
|
|
99
|
-
rubygems_version: 3.6.
|
|
77
|
+
rubygems_version: 3.6.2
|
|
100
78
|
specification_version: 4
|
|
101
|
-
summary:
|
|
79
|
+
summary: ActionView .srb template handler for Sugar Cube.
|
|
102
80
|
test_files: []
|
data/.rspec
DELETED
data/.standard.yml
DELETED
data/lib/sugar_bee/handler.rb
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
require "action_view"
|
|
2
|
-
require "action_view/template"
|
|
3
|
-
require_relative "srb"
|
|
4
|
-
require_relative "srb_to_erb"
|
|
5
|
-
|
|
6
|
-
module SugarBee
|
|
7
|
-
class Handler
|
|
8
|
-
def self.call(template, source)
|
|
9
|
-
processed = process(source)
|
|
10
|
-
ActionView::Template.registered_template_handler(:erb).call(template, processed)
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
def self.process(source)
|
|
14
|
-
srb = Srb.new.parse(source)
|
|
15
|
-
SrbToErb.new.apply(srb)
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
end
|
data/lib/sugar_bee/railtie.rb
DELETED
data/lib/sugar_bee/srb.rb
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "parslet"
|
|
4
|
-
|
|
5
|
-
class SugarBee::Srb < Parslet::Parser
|
|
6
|
-
root(:source)
|
|
7
|
-
rule(:source) { (non_srb | srb).repeat.as(:source) }
|
|
8
|
-
|
|
9
|
-
rule(:non_srb) { (srb_detector.absent? >> any).repeat(1).as(:erb) }
|
|
10
|
-
rule(:srb) { (self_closing_tag | tag_pair).as(:srb) }
|
|
11
|
-
rule(:self_closing_tag) do
|
|
12
|
-
str("<") >> srb_self_close_detector.absent? >> (component_name >> vattrs.maybe).as(:simple_component) >> space? >> srb_self_close_detector
|
|
13
|
-
end
|
|
14
|
-
rule(:tag_pair) { (opening_tag >> source >> closing_tag).as(:tag_pair) }
|
|
15
|
-
|
|
16
|
-
rule(:opening_tag) { (str("<") >> (component_name >> vattrs.maybe).as(:open) >> space? >> str(">")) }
|
|
17
|
-
rule(:closing_tag) { (str("</") >> space? >> component_name.as(:close) >> str(">")) }
|
|
18
|
-
rule(:component_name) { (match["A-Z"] >> match["A-Za-z"].repeat).as(:name) }
|
|
19
|
-
rule(:vattrs) { space? >> (vattr >> space?).repeat.as(:vattrs) }
|
|
20
|
-
rule(:vattr) { match["-a-z0-9"].repeat(1).as(:val) }
|
|
21
|
-
|
|
22
|
-
rule(:srb_detector) { (srb_open_detector | srb_close_detector) }
|
|
23
|
-
rule(:srb_open_detector) { str("<") >> match["A-Z"] }
|
|
24
|
-
rule(:srb_close_detector) { str("</") >> space? >> match["A-Z"] }
|
|
25
|
-
rule(:srb_self_close_detector) { str("/>") }
|
|
26
|
-
rule(:space) { str("\s") }
|
|
27
|
-
rule(:space?) { space.maybe }
|
|
28
|
-
end
|
data/lib/sugar_bee/srb_to_erb.rb
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "parslet"
|
|
4
|
-
|
|
5
|
-
class SugarBee::SrbToErb < Parslet::Transform
|
|
6
|
-
rule(source: sequence(:erb_fragments)) { erb_fragments.join }
|
|
7
|
-
rule(
|
|
8
|
-
srb: {
|
|
9
|
-
simple_component: {
|
|
10
|
-
name: simple(:component_name),
|
|
11
|
-
vattrs: sequence(:values)
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
) do
|
|
15
|
-
args = "(vattrs: %w[#{values.join(" ")}])" if values.any?
|
|
16
|
-
"<%= render(#{component_name}Component.new#{args}) %>"
|
|
17
|
-
end
|
|
18
|
-
rule(
|
|
19
|
-
srb: {
|
|
20
|
-
tag_pair: {
|
|
21
|
-
open: {name: simple(:component_name), vattrs: sequence(:values)},
|
|
22
|
-
source: sequence(:erb_fragments),
|
|
23
|
-
close: {name: simple(:component_name)}
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
) do
|
|
27
|
-
args = "(vattrs: %w[#{values.join(" ")}])" if values.any?
|
|
28
|
-
"<%= render(#{component_name}Component.new#{args}) do %>#{erb_fragments.join}<% end %>"
|
|
29
|
-
end
|
|
30
|
-
rule(erb: simple(:content)) { content }
|
|
31
|
-
rule(val: simple(:vattr)) { vattr }
|
|
32
|
-
end
|