nm 0.5.4 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -7
- data/.gitignore +1 -0
- data/.l.yml +9 -0
- data/.rubocop.yml +3 -0
- data/.ruby-version +1 -0
- data/.t.yml +6 -0
- data/Gemfile +6 -2
- data/README.md +53 -51
- data/lib/nm.rb +12 -2
- data/lib/nm/context.rb +55 -0
- data/lib/nm/ext.rb +11 -18
- data/lib/nm/render.rb +12 -0
- data/lib/nm/source.rb +60 -47
- data/lib/nm/template_behaviors.rb +96 -0
- data/lib/nm/version.rb +3 -1
- data/nm.gemspec +12 -6
- data/test/helper.rb +6 -13
- data/test/support/factory.rb +3 -2
- data/test/support/templates/_list.nm +2 -0
- data/test/support/templates/_locals.nm +4 -2
- data/test/support/templates/_obj.nm +5 -3
- data/test/support/templates/aliases.nm +8 -3
- data/test/support/templates/list.nm +2 -0
- data/test/support/templates/locals.nm +4 -2
- data/test/support/templates/locals_alt.data.inem +2 -2
- data/test/support/templates/obj.nm +6 -4
- data/test/system/.keep +0 -0
- data/test/unit/context_tests.rb +51 -0
- data/test/unit/ext_tests.rb +27 -42
- data/test/unit/nm_tests.rb +20 -0
- data/test/unit/render_tests.rb +28 -0
- data/test/unit/source_tests.rb +89 -106
- data/test/unit/template_behaviors_tests.rb +259 -0
- metadata +82 -43
- data/lib/nm/template.rb +0 -103
- data/test/unit/template_tests.rb +0 -357
@@ -0,0 +1,96 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "much-mixin"
|
4
|
+
require "nm/ext"
|
5
|
+
require "nm/render"
|
6
|
+
require "nm/source"
|
7
|
+
|
8
|
+
module Nm; end
|
9
|
+
|
10
|
+
module Nm::TemplateBehaviors
|
11
|
+
include MuchMixin
|
12
|
+
|
13
|
+
after_mixin_included do
|
14
|
+
attr_accessor :__nm_context__
|
15
|
+
|
16
|
+
alias_method :node, :__node__
|
17
|
+
alias_method :_node, :__node__
|
18
|
+
alias_method :n, :__node__
|
19
|
+
|
20
|
+
alias_method :map, :__map__
|
21
|
+
alias_method :_map, :__map__
|
22
|
+
alias_method :m, :__map__
|
23
|
+
|
24
|
+
alias_method :partial, :__partial__
|
25
|
+
alias_method :_partial, :__partial__
|
26
|
+
alias_method :p, :__partial__
|
27
|
+
end
|
28
|
+
|
29
|
+
mixin_instance_methods do
|
30
|
+
def __nm_render_stack__
|
31
|
+
@__nm_render_stack__ ||= []
|
32
|
+
end
|
33
|
+
|
34
|
+
def __nm_push_render__(locals)
|
35
|
+
__nm_render_stack__.push(
|
36
|
+
Nm::Render.new(dstack: @__nm_dstack__, locals: @__nm_locals__),
|
37
|
+
)
|
38
|
+
@__nm_dstack__ = [nil]
|
39
|
+
@__nm_locals__ = locals
|
40
|
+
end
|
41
|
+
|
42
|
+
def __nm_pop_render__
|
43
|
+
__nm_render_stack__.pop.tap do |render|
|
44
|
+
@__nm_dstack__ = render.dstack
|
45
|
+
@__nm_locals__ = render.locals
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def __nm_data__
|
50
|
+
@__nm_dstack__.last || {}
|
51
|
+
end
|
52
|
+
|
53
|
+
def __node__(key, value = nil, &block)
|
54
|
+
unless @__nm_dstack__[-1].nil? || @__nm_dstack__[-1].is_a?(::Hash)
|
55
|
+
raise Nm::InvalidError, "invalid `node` call"
|
56
|
+
end
|
57
|
+
@__nm_dstack__[-1] ||= {}
|
58
|
+
|
59
|
+
@__nm_dstack__.push(nil)
|
60
|
+
instance_exec(&(block || Proc.new{}))
|
61
|
+
@__nm_dstack__.pop.tap{ |v| @__nm_dstack__[-1][key] = (v || value) }
|
62
|
+
|
63
|
+
self
|
64
|
+
end
|
65
|
+
|
66
|
+
def __map__(list, &block)
|
67
|
+
unless list.respond_to?(:map)
|
68
|
+
raise(
|
69
|
+
ArgumentError,
|
70
|
+
"given list (`#{list.class}`) doesn't respond to `.map`",
|
71
|
+
)
|
72
|
+
end
|
73
|
+
unless @__nm_dstack__[-1].nil? || @__nm_dstack__[-1].is_a?(::Array)
|
74
|
+
raise Nm::InvalidError, "invalid `map` call"
|
75
|
+
end
|
76
|
+
@__nm_dstack__[-1] ||= []
|
77
|
+
|
78
|
+
list.map do |item|
|
79
|
+
@__nm_dstack__.push(nil)
|
80
|
+
instance_exec(item, &(block || Proc.new{}))
|
81
|
+
@__nm_dstack__.pop.tap{ |v| @__nm_dstack__[-1].push(v || item) }
|
82
|
+
end
|
83
|
+
|
84
|
+
self
|
85
|
+
end
|
86
|
+
|
87
|
+
def __partial__(*args)
|
88
|
+
@__nm_dstack__[-1] =
|
89
|
+
@__nm_dstack__[-1].__nm_add_partial_data__(
|
90
|
+
__nm_context__.partial(*args),
|
91
|
+
)
|
92
|
+
|
93
|
+
self
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
data/lib/nm/version.rb
CHANGED
data/nm.gemspec
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
|
-
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
5
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
6
|
require "nm/version"
|
5
7
|
|
@@ -8,12 +10,12 @@ Gem::Specification.new do |gem|
|
|
8
10
|
gem.version = Nm::VERSION
|
9
11
|
gem.authors = ["Kelly Redding", "Collin Redding"]
|
10
12
|
gem.email = ["kelly@kellyredding.com", "collin.redding@me.com"]
|
11
|
-
gem.summary =
|
12
|
-
gem.description =
|
13
|
+
gem.summary = "Node-Map: a data templating DSL."
|
14
|
+
gem.description = "Node-Map: a data templating DSL."
|
13
15
|
gem.homepage = "http://github.com/redding/nm"
|
14
|
-
gem.license =
|
16
|
+
gem.license = "MIT"
|
15
17
|
|
16
|
-
gem_files = `git ls-files`.split(
|
18
|
+
gem_files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
|
17
19
|
gem_files -= gem_files.grep(%r{^(bench)/})
|
18
20
|
gem_files -= gem_files.grep(%r{^(script)/})
|
19
21
|
gem.files = gem_files
|
@@ -21,6 +23,10 @@ Gem::Specification.new do |gem|
|
|
21
23
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
22
24
|
gem.require_paths = ["lib"]
|
23
25
|
|
24
|
-
gem.
|
26
|
+
gem.required_ruby_version = "~> 2.5"
|
27
|
+
|
28
|
+
gem.add_development_dependency("much-style-guide", ["~> 0.6.6"])
|
29
|
+
gem.add_development_dependency("assert", ["~> 2.19.6"])
|
25
30
|
|
31
|
+
gem.add_dependency("much-mixin", ["~> 0.2.4"])
|
26
32
|
end
|
data/test/helper.rb
CHANGED
@@ -1,24 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# this file is automatically required when you run `assert`
|
2
4
|
# put any test helpers here
|
3
5
|
|
4
|
-
require
|
6
|
+
require "pathname"
|
5
7
|
|
6
8
|
# add the root dir to the load path
|
7
9
|
ROOT = Pathname.new(File.expand_path("../..", __FILE__))
|
8
10
|
$LOAD_PATH.unshift(ROOT.to_s)
|
9
11
|
|
10
|
-
TEMPLATE_ROOT = ROOT.join(
|
12
|
+
TEMPLATE_ROOT = ROOT.join("test/support/templates")
|
11
13
|
|
12
14
|
# require pry for debugging (`binding.pry`)
|
13
|
-
require
|
14
|
-
|
15
|
-
require 'test/support/factory'
|
16
|
-
|
17
|
-
# 1.8.7 backfills
|
15
|
+
require "pry"
|
18
16
|
|
19
|
-
|
20
|
-
if !(a = Array.new).respond_to?(:sample) && a.respond_to?(:choice)
|
21
|
-
class Array
|
22
|
-
alias_method :sample, :choice
|
23
|
-
end
|
24
|
-
end
|
17
|
+
require "test/support/factory"
|
data/test/support/factory.rb
CHANGED
@@ -1,4 +1,9 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
_map(1..1) do
|
4
|
+
n "node local value", node
|
5
|
+
_node "map local value", map
|
6
|
+
__node__ "context method value", helper_method1
|
7
|
+
__node__ "context local value", key1
|
8
|
+
__node__ "render local value", key2
|
4
9
|
end
|
@@ -1,3 +1,3 @@
|
|
1
|
-
node
|
2
|
-
node
|
1
|
+
node "locals" do
|
2
|
+
node "key", key
|
3
3
|
end
|
data/test/system/.keep
ADDED
File without changes
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "assert"
|
4
|
+
require "nm/context"
|
5
|
+
|
6
|
+
require "nm/source"
|
7
|
+
require "nm/template_behaviors"
|
8
|
+
|
9
|
+
class Nm::Context
|
10
|
+
class UnitTests < Assert::Context
|
11
|
+
desc "Nm::Context"
|
12
|
+
subject{ unit_class }
|
13
|
+
|
14
|
+
let(:unit_class){ Nm::Context }
|
15
|
+
end
|
16
|
+
|
17
|
+
class InitTests < UnitTests
|
18
|
+
desc "when init"
|
19
|
+
subject{ unit_class.new(context, source: source, locals: locals) }
|
20
|
+
|
21
|
+
let(:context){ Class.new.new }
|
22
|
+
let(:template_root){ Factory.template_root }
|
23
|
+
let(:source){ Nm::Source.new(template_root) }
|
24
|
+
let(:locals){ { "key" => "a-value" } }
|
25
|
+
|
26
|
+
should have_imeths :render, :partial, :render_content
|
27
|
+
|
28
|
+
should "setup the context to render Nm templates" do
|
29
|
+
local_name, local_val = [Factory.string, Factory.string]
|
30
|
+
nm_context =
|
31
|
+
unit_class.new(
|
32
|
+
context,
|
33
|
+
source: source,
|
34
|
+
locals: { local_name => local_val },
|
35
|
+
)
|
36
|
+
|
37
|
+
assert_that(context.class).does_not_include(Nm::TemplateBehaviors)
|
38
|
+
|
39
|
+
metaclass = class << context; self; end
|
40
|
+
assert_that(metaclass).includes(Nm::TemplateBehaviors)
|
41
|
+
|
42
|
+
assert_that(context).responds_to(local_name)
|
43
|
+
assert_that(context.send(local_name)).equals(local_val)
|
44
|
+
|
45
|
+
assert_that(context.__nm_context__).equals(nm_context)
|
46
|
+
end
|
47
|
+
|
48
|
+
# See test/unit/template_behaviors_tests.rb for testing the mixed in
|
49
|
+
# template behaviors and rendering.
|
50
|
+
end
|
51
|
+
end
|
data/test/unit/ext_tests.rb
CHANGED
@@ -1,94 +1,79 @@
|
|
1
|
-
|
2
|
-
require 'nm/ext'
|
1
|
+
# frozen_string_literal: true
|
3
2
|
|
4
|
-
|
3
|
+
require "assert"
|
4
|
+
require "nm/ext"
|
5
5
|
|
6
|
+
module Nm::Ext
|
6
7
|
class UnitTests < Assert::Context
|
7
8
|
desc "Nm ruby extension"
|
8
9
|
subject{ Nm }
|
9
10
|
|
10
|
-
should "define
|
11
|
-
|
11
|
+
should "define an invalid runtime error" do
|
12
|
+
assert_that(subject::InvalidError.new).is_a(RuntimeError)
|
12
13
|
end
|
13
|
-
|
14
14
|
end
|
15
15
|
|
16
16
|
class AddCallDataTests < UnitTests
|
17
|
-
desc "
|
18
|
-
setup do
|
19
|
-
@call_name = Factory.string
|
20
|
-
end
|
17
|
+
desc "__nm_add_partial_data__"
|
21
18
|
|
22
19
|
should "be added to ::Hash" do
|
23
|
-
|
20
|
+
assert_that({}).responds_to(:__nm_add_partial_data__)
|
24
21
|
end
|
25
22
|
|
26
23
|
should "be added to ::Array" do
|
27
|
-
|
24
|
+
assert_that([]).responds_to(:__nm_add_partial_data__)
|
28
25
|
end
|
29
26
|
|
30
27
|
should "be added to nil" do
|
31
|
-
|
28
|
+
assert_that(nil).responds_to(:__nm_add_partial_data__)
|
32
29
|
end
|
33
|
-
|
34
30
|
end
|
35
31
|
|
36
32
|
class HashAddCallDataTests < AddCallDataTests
|
37
33
|
desc "on ::Hash"
|
38
|
-
|
39
|
-
|
40
|
-
end
|
34
|
+
|
35
|
+
let(:h){ { 1 => "1" } }
|
41
36
|
|
42
37
|
should "merge and return hash and nil data" do
|
43
|
-
add = { 2 =>
|
44
|
-
|
45
|
-
|
38
|
+
add = { 2 => "2" }
|
39
|
+
assert_that(h.__nm_add_partial_data__(add)).equals(h.merge(add))
|
40
|
+
assert_that(h.__nm_add_partial_data__(nil)).equals(h)
|
46
41
|
end
|
47
42
|
|
48
43
|
should "complain if adding Array data" do
|
49
44
|
add = []
|
50
|
-
|
51
|
-
@h.__nm_add_call_data__(@call_name, add)
|
52
|
-
end
|
45
|
+
assert_that{ h.__nm_add_partial_data__(add) }.raises(Nm::InvalidError)
|
53
46
|
end
|
54
|
-
|
55
47
|
end
|
56
48
|
|
57
49
|
class ArrayAddCallDataTests < AddCallDataTests
|
58
50
|
desc "on ::Array"
|
59
|
-
|
60
|
-
|
61
|
-
end
|
51
|
+
|
52
|
+
let(:a){ [1, 2] }
|
62
53
|
|
63
54
|
should "concat and return array and nil data" do
|
64
55
|
add = [3, 4]
|
65
|
-
|
66
|
-
|
56
|
+
assert_that(a.__nm_add_partial_data__(add)).equals(a.concat(add))
|
57
|
+
assert_that(a.__nm_add_partial_data__(nil)).equals(a)
|
67
58
|
end
|
68
59
|
|
69
60
|
should "complain if adding Hash data" do
|
70
61
|
add = {}
|
71
|
-
|
72
|
-
@a.__nm_add_call_data__(@call_name, add)
|
73
|
-
end
|
62
|
+
assert_that{ a.__nm_add_partial_data__(add) }.raises(Nm::InvalidError)
|
74
63
|
end
|
75
|
-
|
76
64
|
end
|
77
65
|
|
78
66
|
class NilAddCallDataTests < AddCallDataTests
|
79
67
|
desc "on nil"
|
80
|
-
|
81
|
-
|
82
|
-
end
|
68
|
+
|
69
|
+
let(:n){ nil }
|
83
70
|
|
84
71
|
should "return any given data" do
|
85
|
-
add_hash = { 1 =>
|
72
|
+
add_hash = { 1 => "1" }
|
86
73
|
add_array = [3, 4]
|
87
|
-
|
88
|
-
|
89
|
-
|
74
|
+
assert_that(n.__nm_add_partial_data__(add_hash)).equals(add_hash)
|
75
|
+
assert_that(n.__nm_add_partial_data__(add_array)).equals(add_array)
|
76
|
+
assert_that(n.__nm_add_partial_data__(nil)).equals(n)
|
90
77
|
end
|
91
|
-
|
92
78
|
end
|
93
|
-
|
94
79
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "assert"
|
4
|
+
require "nm"
|
5
|
+
|
6
|
+
module Nm
|
7
|
+
class UnitTests < Assert::Context
|
8
|
+
desc "Nm"
|
9
|
+
subject{ unit_class }
|
10
|
+
|
11
|
+
let(:unit_class){ Nm }
|
12
|
+
|
13
|
+
should have_imeths :default_context_class, :default_context
|
14
|
+
|
15
|
+
should "know its attributes" do
|
16
|
+
assert_that(subject.default_context_class).is_a(Class)
|
17
|
+
assert_that(subject.default_context).is_a(subject.default_context_class)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|