babl-json 0.4.0 → 0.5.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 +4 -4
- data/lib/babl.rb +64 -12
- data/lib/babl/builder/chain_builder.rb +1 -5
- data/lib/babl/builder/template_base.rb +11 -8
- data/lib/babl/operators.rb +1 -0
- data/lib/babl/operators/parent.rb +1 -1
- data/lib/babl/operators/partial.rb +8 -34
- data/lib/babl/operators/pin.rb +1 -1
- data/lib/babl/operators/using.rb +19 -0
- data/lib/babl/rendering/context.rb +1 -1
- data/lib/babl/schema/fixed_array.rb +2 -2
- data/lib/babl/schema/object.rb +2 -2
- data/lib/babl/template.rb +1 -0
- data/lib/babl/utils/dsl_proxy.rb +1 -1
- data/lib/babl/utils/value.rb +32 -23
- data/lib/babl/version.rb +1 -1
- metadata +26 -25
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1bad3eaac421de5e967efa6a17096a9a95529174
|
4
|
+
data.tar.gz: e722e283eb9a3004a935a28bac8b09f8f94a10e6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fa8c6c330b936f4c1b4a3a455bba8491a43911c7c644d161b233215e8a436e2091722e6d85c0005d2b6aa89f5641d69dddb8d50ebd1cc49010368caa434633fb
|
7
|
+
data.tar.gz: 9a6a76cc67edcf4f7f2b952b645d5fa974f492294dde354925c9eb3aa794dd3c210689c55b082923ee4682eaaa960cc6db540dd78776cc10ac7fc6cb83758bc6
|
data/lib/babl.rb
CHANGED
@@ -6,32 +6,84 @@ require 'babl/rendering'
|
|
6
6
|
require 'babl/operators'
|
7
7
|
|
8
8
|
module Babl
|
9
|
+
# There is basically two ways to use BABL: the Rails way, and the clean way.
|
10
|
+
#
|
11
|
+
# Rails way
|
12
|
+
# - BABL detects Rails and integrates with it automatically (only if BABL is required AFTER Rails).
|
13
|
+
# - BABL configuration is global (defined via Babl.configure).
|
14
|
+
# - Global configuration is also used by:
|
15
|
+
# Babl.template
|
16
|
+
# Babl.compile
|
17
|
+
# Babl.source
|
18
|
+
#
|
19
|
+
# Clean way
|
20
|
+
# - You can decide not to use global configuration. It will result in more verbosity
|
21
|
+
# but it protects you from global settings.
|
22
|
+
# - Equivalences:
|
23
|
+
# Babl.template ==> Babl::Template.new
|
24
|
+
# Babl.compile ==> Babl::Template#compile
|
25
|
+
# Babl.source ==> Babl::Template#source
|
26
|
+
#
|
9
27
|
class Config
|
10
|
-
attr_accessor :
|
28
|
+
attr_accessor :preloader, # No practical use outside Bannerman today.
|
29
|
+
:pretty, # Pretty format JSON output (boolean).
|
30
|
+
:cache_templates, # Enable or disable caching of compiled templates (Rails only, boolean).
|
31
|
+
:lookup_context, # Specify how to find templates.
|
32
|
+
:using # List of user-defined modules containing custom operators.
|
11
33
|
|
12
34
|
def initialize
|
13
|
-
@search_path = nil
|
14
35
|
@preloader = Rendering::NoopPreloader
|
15
36
|
@pretty = true
|
16
37
|
@cache_templates = false
|
38
|
+
@lookup_context = nil
|
39
|
+
@using = []
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class AbsoluteLookupContext
|
44
|
+
attr_reader :search_path
|
45
|
+
|
46
|
+
def initialize(search_path)
|
47
|
+
@search_path = search_path
|
48
|
+
raise Errors::InvalidTemplate, 'Missing search path' unless search_path
|
49
|
+
end
|
50
|
+
|
51
|
+
def find(current_template, partial_name)
|
52
|
+
query = File.join(search_path, "{#{partial_name}}{.babl,}")
|
53
|
+
path = Dir[query].first
|
54
|
+
return unless path
|
55
|
+
source = File.read(path)
|
56
|
+
[current_template.source(source, path, 0), self]
|
17
57
|
end
|
18
58
|
end
|
19
59
|
|
20
60
|
class << self
|
21
|
-
def compile(&block)
|
22
|
-
|
61
|
+
def compile(*args, &block)
|
62
|
+
raise ArgumentError, 'Wrong number of arguments' if args.size > 1
|
63
|
+
raise ArgumentError, 'Template or block expected' unless args.empty? ^ block.nil?
|
64
|
+
|
65
|
+
(args.empty? ? source(&block) : template.call(args.first)).compile(
|
23
66
|
pretty: config.pretty,
|
24
|
-
preloader: config.preloader
|
67
|
+
preloader: config.preloader,
|
68
|
+
lookup_context: config.lookup_context
|
25
69
|
)
|
26
70
|
end
|
27
71
|
|
28
|
-
def source(&block)
|
29
|
-
template
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
72
|
+
def source(*args, &block)
|
73
|
+
template.source(*args, &block)
|
74
|
+
end
|
75
|
+
|
76
|
+
def template
|
77
|
+
cached = @cached_template
|
78
|
+
return cached.last if cached && config.using == cached.first
|
79
|
+
# Calling 'using' is a very inefficient operation, because
|
80
|
+
# it creates a new class. We can avoid that cost most of the
|
81
|
+
# time, assuming 'config.using' does not change often (typically
|
82
|
+
# it should only change once at startup)
|
83
|
+
modules = config.using.dup
|
84
|
+
template = Template.new.using(*modules)
|
85
|
+
@cached_template = [modules, template]
|
86
|
+
template
|
35
87
|
end
|
36
88
|
|
37
89
|
def configure
|
@@ -8,17 +8,20 @@ module Babl
|
|
8
8
|
module Builder
|
9
9
|
# TemplateBase is a thin wrapper around Builder.
|
10
10
|
#
|
11
|
-
# Since the BABL code is run via #
|
11
|
+
# Since the BABL code is run via #instance_exec within an instance of this class, we want to
|
12
12
|
# define as few methods as possible here.
|
13
|
-
class TemplateBase
|
13
|
+
class TemplateBase
|
14
|
+
attr_reader :builder
|
15
|
+
|
14
16
|
def initialize(builder = ChainBuilder.new(&:itself))
|
15
|
-
|
17
|
+
@builder = builder
|
18
|
+
freeze
|
16
19
|
end
|
17
20
|
|
18
|
-
def compile(preloader: Rendering::NoopPreloader, pretty: true, optimize: true)
|
21
|
+
def compile(preloader: Rendering::NoopPreloader, pretty: true, optimize: true, lookup_context: nil)
|
19
22
|
# Compute dependencies & schema on the non-simplified node tree in order
|
20
23
|
# to catch all errors.
|
21
|
-
tree = precompile
|
24
|
+
tree = precompile(lookup_context: lookup_context)
|
22
25
|
dependencies = tree.dependencies
|
23
26
|
schema = tree.schema
|
24
27
|
|
@@ -40,13 +43,13 @@ module Babl
|
|
40
43
|
end
|
41
44
|
|
42
45
|
def unscoped
|
43
|
-
self.class.new
|
46
|
+
self.class.new
|
44
47
|
end
|
45
48
|
|
46
49
|
protected
|
47
50
|
|
48
|
-
def precompile
|
49
|
-
builder.precompile(
|
51
|
+
def precompile(node = Nodes::TerminalValue.instance, **context)
|
52
|
+
builder.precompile(node, **context)
|
50
53
|
end
|
51
54
|
|
52
55
|
def construct_node(**new_context, &block)
|
data/lib/babl/operators.rb
CHANGED
@@ -8,40 +8,14 @@ module Babl
|
|
8
8
|
# Load a partial template given its name
|
9
9
|
# A 'lookup_context' must be defined
|
10
10
|
def partial(partial_name)
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
.
|
18
|
-
|
19
|
-
end
|
20
|
-
|
21
|
-
def with_lookup_context(lookup_context)
|
22
|
-
self.class.new(builder.dup.tap { |inst| inst.instance_variable_set(:@lookup_context, lookup_context) })
|
23
|
-
end
|
24
|
-
|
25
|
-
def lookup_context
|
26
|
-
builder.instance_variable_get(:@lookup_context)
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
class AbsoluteLookupContext
|
31
|
-
attr_reader :search_path
|
32
|
-
|
33
|
-
def initialize(search_path)
|
34
|
-
@search_path = search_path
|
35
|
-
raise Errors::InvalidTemplate, 'Invalid search path' unless search_path
|
36
|
-
end
|
37
|
-
|
38
|
-
def find(partial_name)
|
39
|
-
query = File.join(search_path, "{#{partial_name}}{.babl,}")
|
40
|
-
path = Dir[query].first
|
41
|
-
return unless path
|
42
|
-
|
43
|
-
source = File.read(path)
|
44
|
-
[path, source, self]
|
11
|
+
current_template = unscoped
|
12
|
+
construct_terminal { |ctx|
|
13
|
+
lookup_context = ctx[:lookup_context]
|
14
|
+
raise Errors::InvalidTemplate, 'Cannot use partial without lookup context' unless lookup_context
|
15
|
+
template, new_lookup_context = lookup_context.find(current_template, partial_name)
|
16
|
+
raise Errors::InvalidTemplate, "Cannot find partial '#{partial_name}'" unless template
|
17
|
+
template.precompile(Nodes::TerminalValue.instance, lookup_context: new_lookup_context)
|
18
|
+
}
|
45
19
|
end
|
46
20
|
end
|
47
21
|
end
|
data/lib/babl/operators/pin.rb
CHANGED
@@ -23,7 +23,7 @@ module Babl
|
|
23
23
|
protected
|
24
24
|
|
25
25
|
# Override TemplateBase#precompile to ensure that all pin dependencies are satisfied.
|
26
|
-
def precompile
|
26
|
+
def precompile(*)
|
27
27
|
super.tap do |node|
|
28
28
|
raise Errors::InvalidTemplate, 'Unresolved pin' unless node.pinned_dependencies.empty?
|
29
29
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Babl
|
3
|
+
module Operators
|
4
|
+
module Using
|
5
|
+
module DSL
|
6
|
+
def using(*mods, &block)
|
7
|
+
extended_self =
|
8
|
+
if mods.empty?
|
9
|
+
self
|
10
|
+
else
|
11
|
+
::Class.new(self.class) { mods.each { |mod| include mod } }.new(builder)
|
12
|
+
end
|
13
|
+
|
14
|
+
extended_self.source(&(block || -> { self }))
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -4,11 +4,11 @@ require 'babl/utils'
|
|
4
4
|
module Babl
|
5
5
|
module Schema
|
6
6
|
class FixedArray < Utils::Value.new(:items)
|
7
|
-
EMPTY = new(
|
7
|
+
EMPTY = new(Utils::Array::EMPTY)
|
8
8
|
|
9
9
|
def json
|
10
10
|
if items.empty?
|
11
|
-
{ enum: [
|
11
|
+
{ enum: [Utils::Array::EMPTY] }
|
12
12
|
else
|
13
13
|
{ type: 'array', items: items.map(&:json), additionalItems: false }
|
14
14
|
end
|
data/lib/babl/schema/object.rb
CHANGED
@@ -9,8 +9,8 @@ module Babl
|
|
9
9
|
super(properties.to_set.freeze, additional)
|
10
10
|
end
|
11
11
|
|
12
|
-
EMPTY = new(
|
13
|
-
EMPTY_WITH_ADDITIONAL = new(
|
12
|
+
EMPTY = new(Utils::Array::EMPTY, false)
|
13
|
+
EMPTY_WITH_ADDITIONAL = new(Utils::Array::EMPTY, true)
|
14
14
|
|
15
15
|
class Property < Utils::Value.new(:name, :value, :required)
|
16
16
|
def initialize(name, value, required)
|
data/lib/babl/template.rb
CHANGED
data/lib/babl/utils/dsl_proxy.rb
CHANGED
data/lib/babl/utils/value.rb
CHANGED
@@ -5,35 +5,44 @@ module Babl
|
|
5
5
|
module Utils
|
6
6
|
# Construct deeply immutable value objects
|
7
7
|
# Similar to Struct, but:
|
8
|
-
# - Properties are assumed deeply immutable (#hash is assumed constant)
|
8
|
+
# - Properties are assumed deeply immutable (#hash is assumed constant & store permanently)
|
9
9
|
# - Constructor requires all arguments
|
10
10
|
# - #== has the same meaning as #eql?
|
11
|
-
|
11
|
+
# - The object is frozen
|
12
|
+
#
|
13
|
+
# Goals :
|
14
|
+
# - Create completely immutable value objects
|
15
|
+
# - Fast comparison between instances (using precomputed hash values)
|
16
|
+
# - Low overhead (relies on native Ruby Struct)
|
17
|
+
class Value < Struct
|
12
18
|
def self.new(*fields)
|
13
|
-
|
14
|
-
|
15
|
-
const_set(:FIELDS, fields.map(&:to_sym))
|
16
|
-
class_eval <<-RUBY
|
17
|
-
def initialize(#{field_aliases.join(',')})
|
18
|
-
super(#{['nil', field_aliases].join(',')})
|
19
|
-
hash
|
20
|
-
freeze
|
21
|
-
end
|
19
|
+
fields = fields.map(&:to_sym)
|
20
|
+
field_aliases = ::Array.new(fields.size) { |i| "v#{i}" }
|
22
21
|
|
23
|
-
|
24
|
-
|
25
|
-
|
22
|
+
clazz = super(:_cached_hash, *fields)
|
23
|
+
clazz.const_set(:FIELDS, fields)
|
24
|
+
clazz.class_eval <<-RUBY
|
25
|
+
def initialize(#{field_aliases.join(',')})
|
26
|
+
super(#{['nil', field_aliases].join(',')})
|
27
|
+
hash
|
28
|
+
freeze
|
29
|
+
end
|
30
|
+
RUBY
|
26
31
|
|
27
|
-
|
28
|
-
|
29
|
-
|
32
|
+
clazz
|
33
|
+
end
|
34
|
+
|
35
|
+
def hash
|
36
|
+
self._cached_hash ||= super
|
37
|
+
end
|
38
|
+
|
39
|
+
def ==(other)
|
40
|
+
eql?(other)
|
41
|
+
end
|
30
42
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
end
|
35
|
-
RUBY
|
36
|
-
end
|
43
|
+
def self.with(hash = Utils::Hash::EMPTY)
|
44
|
+
raise ::ArgumentError unless ::Hash === hash && (hash.keys - self::FIELDS).empty?
|
45
|
+
new(*self::FIELDS.map { |f| hash.fetch(f) })
|
37
46
|
end
|
38
47
|
end
|
39
48
|
end
|
data/lib/babl/version.rb
CHANGED
metadata
CHANGED
@@ -1,113 +1,113 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: babl-json
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Frederic Terrazzoni
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-10-
|
11
|
+
date: 2017-10-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: coveralls
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '0'
|
19
|
+
version: '0.8'
|
20
20
|
type: :development
|
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: '0'
|
26
|
+
version: '0.8'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: jbuilder
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '2'
|
34
34
|
type: :development
|
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: '
|
40
|
+
version: '2'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
42
|
+
name: json-schema
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
47
|
+
version: '2.8'
|
48
48
|
type: :development
|
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: '
|
54
|
+
version: '2.8'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
56
|
+
name: pry
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
59
|
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
61
|
+
version: '0'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
68
|
+
version: '0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
70
|
+
name: rabl
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
73
|
- - "~>"
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version: '0.
|
75
|
+
version: '0.13'
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version: '0.
|
82
|
+
version: '0.13'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
84
|
+
name: rspec
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
87
|
- - "~>"
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: '
|
89
|
+
version: '3'
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
94
|
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version: '
|
96
|
+
version: '3'
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
|
-
name:
|
98
|
+
name: rubocop
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
|
-
- -
|
101
|
+
- - '='
|
102
102
|
- !ruby/object:Gem::Version
|
103
|
-
version: '0.
|
103
|
+
version: '0.51'
|
104
104
|
type: :development
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
|
-
- -
|
108
|
+
- - '='
|
109
109
|
- !ruby/object:Gem::Version
|
110
|
-
version: '0.
|
110
|
+
version: '0.51'
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
112
|
name: multi_json
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
@@ -175,6 +175,7 @@ files:
|
|
175
175
|
- lib/babl/operators/static.rb
|
176
176
|
- lib/babl/operators/switch.rb
|
177
177
|
- lib/babl/operators/typed.rb
|
178
|
+
- lib/babl/operators/using.rb
|
178
179
|
- lib/babl/operators/with.rb
|
179
180
|
- lib/babl/railtie.rb
|
180
181
|
- lib/babl/rendering.rb
|