nm 0.1.0 → 0.2.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.
@@ -0,0 +1,8 @@
1
+ node 'slideshow' do
2
+ node 'start_slide', view.start_slide
3
+ node 'slides' do
4
+ map view.slides do |slide|
5
+ partial 'slide', :slide => slide
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,17 @@
1
+ require 'assert/factory'
2
+ require 'bench/slideshow'
3
+
4
+ module NmBench
5
+
6
+ class SlideshowPartialsTemplate < SlideshowTemplate
7
+
8
+ TEMPLATES[:slideshow_partials] = self
9
+
10
+ def initialize
11
+ super
12
+ @name = 'slideshow_partials'
13
+ end
14
+
15
+ end
16
+
17
+ end
@@ -0,0 +1,16 @@
1
+ module NmBench
2
+
3
+ class Template
4
+
5
+ attr_reader :name, :locals
6
+
7
+ TEMPLATES = {}
8
+ require 'bench/slideshow'
9
+
10
+ def self.find(name)
11
+ TEMPLATES[name].new
12
+ end
13
+
14
+ end
15
+
16
+ end
data/lib/nm.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require "nm/version"
2
+ require 'nm/source'
2
3
 
3
4
  module Nm
4
5
  end
@@ -0,0 +1,31 @@
1
+ module Nm
2
+
3
+ class InvalidError < RuntimeError; end
4
+
5
+ end
6
+
7
+ class ::Hash
8
+
9
+ def __nm_add_call_data__(call_name, data)
10
+ if data.is_a?(::Array)
11
+ raise Nm::InvalidError, "invalid `#{call_name}` call"
12
+ end
13
+ self.merge(data || {})
14
+ end
15
+
16
+ end
17
+
18
+ class ::Array
19
+
20
+ def __nm_add_call_data__(call_name, data)
21
+ if data.is_a?(::Hash)
22
+ raise Nm::InvalidError, "invalid `#{call_name}` call"
23
+ end
24
+ self.concat(data || [])
25
+ end
26
+
27
+ end
28
+
29
+ def nil.__nm_add_call_data__(call_name, data)
30
+ data
31
+ end
@@ -0,0 +1,49 @@
1
+ require 'pathname'
2
+ require 'nm/template'
3
+
4
+ module Nm
5
+
6
+ class Source
7
+
8
+ EXT = ".nm"
9
+
10
+ attr_reader :root
11
+
12
+ def initialize(root)
13
+ @root = Pathname.new(root.to_s)
14
+ end
15
+
16
+ def data(file_path)
17
+ File.send(File.respond_to?(:binread) ? :binread : :read, file_path)
18
+ end
19
+
20
+ def render(file_name, locals = nil)
21
+ Template.new(self, source_file_path(file_name), locals || {}).__data__
22
+ end
23
+
24
+ def partial(file_name, locals = nil)
25
+ Template.new(self, partial_file_path(file_name), locals || {}).__data__
26
+ end
27
+
28
+ private
29
+
30
+ def source_file_path(file_name)
31
+ self.root.join("#{file_name}#{EXT}").to_s
32
+ end
33
+
34
+ def partial_file_path(file_name)
35
+ basename = File.basename(file_name.to_s)
36
+ source_file_path(file_name.to_s.sub(/#{basename}\Z/, "_#{basename}"))
37
+ end
38
+
39
+ end
40
+
41
+ class DefaultSource < Source
42
+
43
+ def initialize
44
+ super('/')
45
+ end
46
+
47
+ end
48
+
49
+ end
@@ -0,0 +1,95 @@
1
+ require 'nm/source'
2
+ require 'nm/ext'
3
+
4
+ module Nm
5
+
6
+ class Template
7
+
8
+ def initialize(*args)
9
+ @__dstack__ = [ nil ]
10
+
11
+ # apply any given locals to template scope as methods
12
+ metaclass = class << self; self; end
13
+ (args.last.kind_of?(::Hash) ? args.pop : {}).each do |key, value|
14
+ metaclass.class_eval{ define_method(key){ value } }
15
+ end
16
+
17
+ source_file = args.last.kind_of?(::String) ? args.pop : ''
18
+ @__source__ = args.last.kind_of?(Source) ? args.pop : DefaultSource.new
19
+
20
+ return if source_file.empty?
21
+
22
+ unless File.exists?(source_file)
23
+ raise ArgumentError, "source file `#{source_file}` does not exist"
24
+ end
25
+ instance_eval(@__source__.data(source_file), source_file, 1)
26
+ end
27
+
28
+ def __data__
29
+ @__dstack__.last
30
+ end
31
+
32
+ def __node__(key, value = nil, &block)
33
+ unless @__dstack__[-1].nil? || @__dstack__[-1].is_a?(::Hash)
34
+ raise Nm::InvalidError, "invalid `node` call"
35
+ end
36
+ @__dstack__[-1] ||= ::Hash.new
37
+
38
+ @__dstack__.push(nil)
39
+ self.instance_exec(&(block || Proc.new {}))
40
+ @__dstack__.pop.tap{ |v| @__dstack__[-1][key] = (v || value) }
41
+
42
+ return self
43
+ end
44
+
45
+ alias_method :node, :__node__
46
+ alias_method :_node, :__node__
47
+ alias_method :n, :__node__
48
+
49
+ def __map__(list, &block)
50
+ unless list.respond_to?(:map)
51
+ raise ArgumentError, "given list (`#{list.class}`) doesn't respond to `.map`"
52
+ end
53
+ unless @__dstack__[-1].nil? || @__dstack__[-1].is_a?(::Array)
54
+ raise Nm::InvalidError, "invalid `map` call"
55
+ end
56
+ @__dstack__[-1] ||= ::Array.new
57
+
58
+ list.map do |item|
59
+ @__dstack__.push(nil)
60
+ self.instance_exec(item, &(block || Proc.new {}))
61
+ @__dstack__.pop.tap{ |v| @__dstack__[-1].push(v || item) }
62
+ end
63
+
64
+ return self
65
+ end
66
+
67
+ alias_method :map, :__map__
68
+ alias_method :_map, :__map__
69
+ alias_method :m, :__map__
70
+
71
+ def __render__(*args)
72
+ data = @__source__.render(*args)
73
+ @__dstack__[-1] = @__dstack__[-1].__nm_add_call_data__('render', data)
74
+
75
+ return self
76
+ end
77
+
78
+ alias_method :render, :__render__
79
+ alias_method :_render, :__render__
80
+ alias_method :r, :__render__
81
+
82
+ def __partial__(*args)
83
+ data = @__source__.partial(*args)
84
+ @__dstack__[-1] = @__dstack__[-1].__nm_add_call_data__('partial', data)
85
+
86
+ return self
87
+ end
88
+
89
+ alias_method :partial, :__partial__
90
+ alias_method :_partial, :__partial__
91
+ alias_method :p, :__partial__
92
+
93
+ end
94
+
95
+ end
@@ -1,3 +1,3 @@
1
1
  module Nm
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
data/nm.gemspec CHANGED
@@ -8,8 +8,8 @@ Gem::Specification.new do |gem|
8
8
  gem.version = Nm::VERSION
9
9
  gem.authors = ["Kelly Redding", "Collin Redding"]
10
10
  gem.email = ["kelly@kellyredding.com", "collin.redding@me.com"]
11
- gem.description = %q{JSON/BSON data structure template system }
12
- gem.summary = %q{JSON/BSON data structure template system }
11
+ gem.description = %q{Data templating system.}
12
+ gem.summary = %q{Data templating system.}
13
13
  gem.homepage = "http://github.com/redding/nm"
14
14
  gem.license = 'MIT'
15
15
 
@@ -0,0 +1,5 @@
1
+ # $ bundle exec ruby script/bench.rb
2
+
3
+ require 'script/bench_rabl'
4
+ require 'script/bench_nm'
5
+ require 'script/bench_nm_re_source'
@@ -0,0 +1,13 @@
1
+ # $ bundle exec ruby script/bench.rb
2
+
3
+ # require pry for debugging (`binding.pry`)
4
+ require 'pry'
5
+
6
+ require 'bench/logger'
7
+ require 'bench/slideshow'
8
+
9
+ NmBench::Logger.new('bench/results/nm.txt') do |logger|
10
+ logger.run_template(:nm, :slideshow, 1)
11
+ logger.run_template(:nm, :slideshow, 10)
12
+ logger.run_template(:nm, :slideshow, 100)
13
+ end
@@ -0,0 +1,13 @@
1
+ # $ bundle exec ruby script/bench.rb
2
+
3
+ # require pry for debugging (`binding.pry`)
4
+ require 'pry'
5
+
6
+ require 'bench/logger'
7
+ require 'bench/slideshow_partials'
8
+
9
+ NmBench::Logger.new('bench/results/nm_partials.txt') do |logger|
10
+ logger.run_template(:nm, :slideshow_partials, 1)
11
+ logger.run_template(:nm, :slideshow_partials, 10)
12
+ logger.run_template(:nm, :slideshow_partials, 100)
13
+ end
@@ -0,0 +1,13 @@
1
+ # $ bundle exec ruby script/bench.rb
2
+
3
+ # require pry for debugging (`binding.pry`)
4
+ require 'pry'
5
+
6
+ require 'bench/logger'
7
+ require 'bench/slideshow'
8
+
9
+ NmBench::Logger.new('bench/results/nm_re_source.txt') do |logger|
10
+ logger.run_template(:nm_re_source, :slideshow, 1)
11
+ logger.run_template(:nm_re_source, :slideshow, 10)
12
+ logger.run_template(:nm_re_source, :slideshow, 100)
13
+ end
@@ -0,0 +1,13 @@
1
+ # $ bundle exec ruby script/bench.rb
2
+
3
+ # require pry for debugging (`binding.pry`)
4
+ require 'pry'
5
+
6
+ require 'bench/logger'
7
+ require 'bench/slideshow'
8
+
9
+ NmBench::Logger.new('bench/results/rabl.txt') do |logger|
10
+ logger.run_template(:rabl, :slideshow, 1)
11
+ logger.run_template(:rabl, :slideshow, 10)
12
+ logger.run_template(:rabl, :slideshow, 100)
13
+ end
@@ -1,8 +1,15 @@
1
1
  # this file is automatically required when you run `assert`
2
2
  # put any test helpers here
3
3
 
4
+ require 'pathname'
5
+
4
6
  # add the root dir to the load path
5
- $LOAD_PATH.unshift(File.expand_path("../..", __FILE__))
7
+ ROOT = Pathname.new(File.expand_path("../..", __FILE__))
8
+ $LOAD_PATH.unshift(ROOT.to_s)
9
+
10
+ TEMPLATE_ROOT = ROOT.join('test/support/templates')
6
11
 
7
12
  # require pry for debugging (`binding.pry`)
8
13
  require 'pry'
14
+
15
+ require 'test/support/factory'
@@ -0,0 +1,14 @@
1
+ require 'assert/factory'
2
+
3
+ module Factory
4
+ extend Assert::Factory
5
+
6
+ def self.template_root
7
+ TEMPLATE_ROOT.to_s
8
+ end
9
+
10
+ def self.template_file(name)
11
+ TEMPLATE_ROOT.join(name).to_s
12
+ end
13
+
14
+ end
@@ -0,0 +1,3 @@
1
+ map [1, 2, 3] do |num|
2
+ node num.to_s, num
3
+ end
@@ -0,0 +1,3 @@
1
+ node 'locals' do
2
+ node 'key', key
3
+ end
@@ -0,0 +1,3 @@
1
+ node 'a', 'Aye'
2
+ node 'b', 'Bee'
3
+ node 'c', "See"
@@ -0,0 +1,4 @@
1
+ _map (1..1) do
2
+ n 'node local value', node
3
+ _node 'map local value', map
4
+ end
@@ -0,0 +1,3 @@
1
+ map [1, 2, 3] do |num|
2
+ node num.to_s, num
3
+ end
@@ -0,0 +1,3 @@
1
+ node 'locals' do
2
+ node 'key', key
3
+ end
@@ -0,0 +1,5 @@
1
+ node 'obj' do
2
+ node 'a', 'Aye'
3
+ node 'b', 'Bee'
4
+ node 'c', "See"
5
+ end
@@ -0,0 +1,94 @@
1
+ require 'assert'
2
+ require 'nm/ext'
3
+
4
+ module Nm::Ext
5
+
6
+ class UnitTests < Assert::Context
7
+ desc "Nm ruby extension"
8
+ subject{ Nm }
9
+
10
+ should "define and invalid runtime error" do
11
+ assert_kind_of ::RuntimeError, subject::InvalidError.new
12
+ end
13
+
14
+ end
15
+
16
+ class AddCallDataTests < UnitTests
17
+ desc "__nm_add_call_data__"
18
+ setup do
19
+ @call_name = Factory.string
20
+ end
21
+
22
+ should "be added to ::Hash" do
23
+ assert_responds_to :__nm_add_call_data__, ::Hash.new
24
+ end
25
+
26
+ should "be added to ::Array" do
27
+ assert_responds_to :__nm_add_call_data__, ::Array.new
28
+ end
29
+
30
+ should "be added to nil" do
31
+ assert_responds_to :__nm_add_call_data__, nil
32
+ end
33
+
34
+ end
35
+
36
+ class HashAddCallDataTests < AddCallDataTests
37
+ desc "on ::Hash"
38
+ setup do
39
+ @h = { 1 => '1' }
40
+ end
41
+
42
+ should "merge and return hash and nil data" do
43
+ add = { 2 => '2' }
44
+ assert_equal @h.merge(add), @h.__nm_add_call_data__(@call_name, add)
45
+ assert_equal @h, @h.__nm_add_call_data__(@call_name, nil)
46
+ end
47
+
48
+ should "complain if adding Array data" do
49
+ add = []
50
+ assert_raises Nm::InvalidError do
51
+ @h.__nm_add_call_data__(@call_name, add)
52
+ end
53
+ end
54
+
55
+ end
56
+
57
+ class ArrayAddCallDataTests < AddCallDataTests
58
+ desc "on ::Array"
59
+ setup do
60
+ @a = [1, 2]
61
+ end
62
+
63
+ should "concat and return array and nil data" do
64
+ add = [3, 4]
65
+ assert_equal @a.concat(add), @a.__nm_add_call_data__(@call_name, add)
66
+ assert_equal @a, @a.__nm_add_call_data__(@call_name, nil)
67
+ end
68
+
69
+ should "complain if adding Hash data" do
70
+ add = {}
71
+ assert_raises Nm::InvalidError do
72
+ @a.__nm_add_call_data__(@call_name, add)
73
+ end
74
+ end
75
+
76
+ end
77
+
78
+ class NilAddCallDataTests < AddCallDataTests
79
+ desc "on nil"
80
+ setup do
81
+ @n = nil
82
+ end
83
+
84
+ should "return any given data" do
85
+ add_hash = { 1 => '1' }
86
+ add_array = [3, 4]
87
+ assert_equal add_hash, @n.__nm_add_call_data__(@call_name, add_hash)
88
+ assert_equal add_array, @n.__nm_add_call_data__(@call_name, add_array)
89
+ assert_equal @n, @n.__nm_add_call_data__(@call_name, nil)
90
+ end
91
+
92
+ end
93
+
94
+ end