pakyow-presenter 0.8rc1 → 0.8.rc4

Sign up to get free protection for your applications and to get access to all the features.
@@ -2,58 +2,58 @@ module Pakyow
2
2
  module Presenter
3
3
  class ViewCollection
4
4
  include Enumerable
5
-
5
+
6
6
  def initialize
7
7
  @views = []
8
8
  end
9
-
9
+
10
10
  def each
11
11
  @views.each { |v| yield(v) }
12
12
  end
13
-
14
- def attributes(*args)
13
+
14
+ def attributes(attrs = {})
15
15
  collection = AttributesCollection.new
16
- self.each{|v| collection << v.attributes}
16
+ self.each{|v| collection << v.attributes(attrs)}
17
17
  return collection
18
18
  end
19
19
 
20
20
  alias :attrs :attributes
21
-
21
+
22
22
  def remove
23
23
  self.each {|e| e.remove}
24
24
  end
25
-
25
+
26
26
  alias :delete :remove
27
-
27
+
28
28
  # SEE COMMENT IN VIEW
29
29
  # def add_class(val)
30
30
  # self.each {|e| e.add_class(val)}
31
31
  # end
32
-
32
+
33
33
  # SEE COMMENT IN VIEW
34
34
  # def remove_class(val)
35
35
  # self.each {|e| e.remove_class(val)}
36
36
  # end
37
-
37
+
38
38
  def clear
39
39
  self.each {|e| e.clear}
40
40
  end
41
-
41
+
42
42
  def text
43
43
  self.map { |v| v.text }
44
44
  end
45
-
46
- def content
47
- self.map { |v| v.content }
45
+
46
+ def text=(text)
47
+ self.each {|e| e.text = text}
48
48
  end
49
-
50
- alias :html :content
51
-
52
- def content=(content)
53
- self.each {|e| e.content = content}
49
+
50
+ def html
51
+ self.map { |v| v.html }
52
+ end
53
+
54
+ def html=(html)
55
+ self.each {|e| e.html = html}
54
56
  end
55
-
56
- alias :html= :content=
57
57
 
58
58
  def to_html
59
59
  self.map { |v| v.to_html }.join('')
@@ -64,15 +64,15 @@ module Pakyow
64
64
  def append(content)
65
65
  self.each {|e| e.append(content)}
66
66
  end
67
-
67
+
68
68
  alias :render :append
69
-
69
+
70
70
  def <<(val)
71
71
  if val.is_a? View
72
72
  @views << val
73
73
  end
74
74
  end
75
-
75
+
76
76
  def [](i)
77
77
  @views[i]
78
78
  end
@@ -87,7 +87,17 @@ module Pakyow
87
87
  next unless svs = v.scope(name)
88
88
  svs.each{|sv| views << sv}
89
89
  }
90
-
90
+
91
+ views
92
+ end
93
+
94
+ def prop(name)
95
+ views = ViewCollection.new
96
+ self.each{|v|
97
+ next unless svs = v.prop(name)
98
+ svs.each{|sv| views << sv}
99
+ }
100
+
91
101
  views
92
102
  end
93
103
 
@@ -95,28 +105,31 @@ module Pakyow
95
105
  # with {|view| block}
96
106
  #
97
107
  # Creates a context in which view manipulations can be performed.
98
- #
108
+ #
99
109
  # Unlike previous versions, the context can only be referenced by the
100
110
  # block argument. No `context` method will be available.s
101
111
  #
102
112
  def with
103
113
  yield(self)
114
+ self
104
115
  end
105
116
 
106
117
  # call-seq:
107
118
  # for {|view, datum| block}
108
119
  #
109
- # Yields a view and its matching dataum. Datums are yielded until
110
- # no more views or data is available. For the ViewCollection case, this
120
+ # Yields a view and its matching dataum. Datums are yielded until
121
+ # no more views or data is available. For the ViewCollection case, this
111
122
  # means the block will be yielded self.length times.
112
- #
123
+ #
113
124
  # (this is basically Bret's `map` function)
114
125
  #
115
126
  def for(data, &block)
116
- data = [data] unless data.instance_of?(Array)
127
+ data = data.to_a if data.is_a?(Enumerator)
128
+ data = [data] if (!data.is_a?(Enumerable) || data.is_a?(Hash))
129
+
117
130
  self.each_with_index { |v,i|
118
131
  break unless datum = data[i]
119
- block.call(v, datum)
132
+ block.call(v, datum, i) if block_given?
120
133
  }
121
134
  end
122
135
 
@@ -128,7 +141,8 @@ module Pakyow
128
141
  # of self[data index] || self[-1], where n = data.length.
129
142
  #
130
143
  def match(data)
131
- data = [data] unless data.instance_of?(Array)
144
+ data = data.to_a if data.is_a?(Enumerator)
145
+ data = [data] if (!data.is_a?(Enumerable) || data.is_a?(Hash))
132
146
 
133
147
  views = ViewCollection.new
134
148
  data.each_with_index {|datum,i|
@@ -141,15 +155,17 @@ module Pakyow
141
155
  d_v = v.doc.dup
142
156
  v.doc.before(d_v)
143
157
 
144
- new_v = View.new(d_v)
158
+ new_v = View.from_doc(d_v)
145
159
 
146
160
  # find binding subset (keeps us from refinding)
147
- new_v.bindings = v.bindings
161
+ new_v.bindings = v.bindings.dup
162
+ new_v.scoped_as = v.scoped_as
148
163
 
149
164
  views << new_v
150
165
  }
151
166
 
152
- self.remove
167
+ # do not use self.remove since that refinds bindings
168
+ self.each {|v| v.doc.remove}
153
169
  views
154
170
  end
155
171
 
@@ -167,10 +183,10 @@ module Pakyow
167
183
  #
168
184
  # Binds data across existing scopes.
169
185
  #
170
- def bind(data, bindings = nil, &block)
171
- self.for(data) {|view, datum|
186
+ def bind(data, bindings = {}, &block)
187
+ self.for(data) {|view, datum, i|
172
188
  view.bind(datum, bindings)
173
- yield(view, datum) if block_given?
189
+ yield(view, datum, i) if block_given?
174
190
  }
175
191
  end
176
192
 
@@ -179,7 +195,7 @@ module Pakyow
179
195
  #
180
196
  # Matches self to data then binds data to the view.
181
197
  #
182
- def apply(data, bindings = nil, &block)
198
+ def apply(data, bindings = {}, &block)
183
199
  self.match(data).bind(data, bindings, &block)
184
200
  end
185
201
  end
@@ -0,0 +1,174 @@
1
+ module Pakyow
2
+ class ViewStore
3
+ attr_reader :name
4
+
5
+ def initialize(store_path, name = :default)
6
+ @name = name
7
+ @store_path = store_path
8
+
9
+ load_templates
10
+ load_path_info
11
+ end
12
+
13
+ def at?(view_path)
14
+ begin
15
+ at_path(view_path)
16
+ return true
17
+ rescue MissingView
18
+ return false
19
+ end
20
+ end
21
+
22
+ def template(name_or_path)
23
+ if name_or_path.is_a?(Symbol)
24
+ return template_with_name(name_or_path)
25
+ else
26
+ return at_path(name_or_path, :template)
27
+ end
28
+ end
29
+
30
+ def page(view_path)
31
+ return at_path(view_path, :page).dup
32
+ end
33
+
34
+ def view(view_path)
35
+ return at_path(view_path, :view).dup
36
+ end
37
+
38
+ def partial(view_path, name)
39
+ return at_path(view_path, :partials)[name.to_sym]
40
+ end
41
+
42
+ # iterations through known views, yielding each
43
+ def views
44
+ @path_info.each_pair do |path, info|
45
+ yield(info[:view], path)
46
+ end
47
+ end
48
+
49
+ private
50
+
51
+ def at_path(view_path, obj = nil)
52
+ normalized_path = normalize_path(view_path)
53
+ info = @path_info[normalized_path]
54
+
55
+ if info.nil?
56
+ raise MissingView, "No view at path '#{view_path}'"
57
+ else
58
+ return obj ? info[obj.to_sym] : info
59
+ end
60
+ end
61
+
62
+ def template_with_name(name)
63
+ unless template = @templates[name.to_sym]
64
+ raise MissingTemplate, "No template named '#{name}'"
65
+ end
66
+
67
+ return template
68
+ end
69
+
70
+ def load_templates
71
+ @templates = {}
72
+
73
+ if File.exists?(templates_path)
74
+ Dir.entries(templates_path).each do |file|
75
+ next if file == '.' || file == '..'
76
+
77
+ template = Template.load(File.join(templates_path, file))
78
+ @templates[template.name] = template
79
+ end
80
+ else
81
+ raise MissingTemplatesDir, "No templates found at '#{templates_path}'"
82
+ end
83
+ end
84
+
85
+ def templates_path
86
+ return File.join(@store_path, Config::Base.presenter.template_dir(@name))
87
+ end
88
+
89
+ def load_path_info
90
+ @path_info = {}
91
+
92
+ DirUtils.walk_dir(@store_path) do |path|
93
+ # skip root
94
+ next if path == @store_path
95
+
96
+ # don't include templates
97
+ next if path.include?(templates_path)
98
+
99
+ # skip partial files
100
+ next if File.basename(path)[0,1] == '_'
101
+
102
+ # skip non-empty folders (these files will be picked up)
103
+ next if !Dir.glob(File.join(path, 'index.*')).empty?
104
+
105
+ normalized_path = normalize_path(path)
106
+
107
+ # if path is a directory we know there's no index page
108
+ # so use the previous index page instead. this allows
109
+ # partials to be overridden at a path while the same
110
+ # page is used
111
+ if File.directory?(path)
112
+ # gets the path for the previous page
113
+ prev_path = normalized_path.split('/')[0..-2].join("")
114
+ page = @path_info[prev_path][:page]
115
+ else
116
+ page = Page.load(path)
117
+ end
118
+
119
+ template = template_with_name(page.template).dup
120
+
121
+ #TODO more efficient way of doing this? lot
122
+ # of redundant calls here
123
+ partials = partials_at_path(path)
124
+
125
+ # construct view
126
+ view = template.build(page.dup.build(partials))
127
+
128
+ info = {
129
+ view: view,
130
+ page: page,
131
+ template: template,
132
+ partials: partials,
133
+ }
134
+
135
+ @path_info[normalized_path] = info
136
+ end
137
+ end
138
+
139
+ def normalize_path(path)
140
+ relative_path = path.gsub(@store_path, '')
141
+ relative_path = relative_path.gsub(File.extname(relative_path), '')
142
+ relative_path = relative_path.gsub('index', '')
143
+ relative_path = StringUtils.normalize_path(relative_path)
144
+
145
+ return relative_path
146
+ end
147
+
148
+ def partials_at_path(view_path)
149
+ view_path = File.dirname(view_path) unless File.directory?(view_path)
150
+
151
+ partials = {}
152
+ DirUtils.walk_dir(@store_path) do |path|
153
+ # skip non-partials
154
+ next unless File.basename(path)[0,1] == '_'
155
+
156
+ # skip directories
157
+ next if File.directory?(path)
158
+
159
+ # skip files not within `view_path`
160
+ next unless DirUtils.dir_within_dir?(File.dirname(path), view_path)
161
+
162
+ name = File.basename(path.split('/')[-1], '.*')[1..-1]
163
+ partials[name.to_sym] = path
164
+ end
165
+
166
+ # create instances
167
+ partials.each do |name, path|
168
+ partials[name] = Partial.load(path)
169
+ end
170
+
171
+ return partials
172
+ end
173
+ end
174
+ end
metadata CHANGED
@@ -1,8 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pakyow-presenter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8rc1
5
- prerelease: 3
4
+ version: 0.8.rc4
6
5
  platform: ruby
7
6
  authors:
8
7
  - Bryan Powell
@@ -10,57 +9,66 @@ authors:
10
9
  autorequire:
11
10
  bindir: bin
12
11
  cert_chain: []
13
- date: 2013-02-11 00:00:00.000000000 Z
12
+ date: 2013-10-26 00:00:00.000000000 Z
14
13
  dependencies:
15
14
  - !ruby/object:Gem::Dependency
16
15
  name: pakyow-core
17
16
  requirement: !ruby/object:Gem::Requirement
18
- none: false
19
17
  requirements:
20
18
  - - '='
21
19
  - !ruby/object:Gem::Version
22
- version: 0.8rc1
20
+ version: 0.8.rc4
23
21
  type: :runtime
24
22
  prerelease: false
25
23
  version_requirements: !ruby/object:Gem::Requirement
26
- none: false
27
24
  requirements:
28
25
  - - '='
29
26
  - !ruby/object:Gem::Version
30
- version: 0.8rc1
27
+ version: 0.8.rc4
31
28
  - !ruby/object:Gem::Dependency
32
29
  name: nokogiri
33
30
  requirement: !ruby/object:Gem::Requirement
34
- none: false
35
31
  requirements:
36
32
  - - ~>
37
33
  - !ruby/object:Gem::Version
38
- version: '1.5'
34
+ version: '1.6'
39
35
  type: :runtime
40
36
  prerelease: false
41
37
  version_requirements: !ruby/object:Gem::Requirement
42
- none: false
43
38
  requirements:
44
39
  - - ~>
45
40
  - !ruby/object:Gem::Version
46
- version: '1.5'
41
+ version: '1.6'
47
42
  - !ruby/object:Gem::Dependency
48
- name: shoulda
43
+ name: minitest
49
44
  requirement: !ruby/object:Gem::Requirement
50
- none: false
51
45
  requirements:
52
46
  - - ~>
53
47
  - !ruby/object:Gem::Version
54
- version: '2.11'
48
+ version: '5.0'
55
49
  type: :development
56
50
  prerelease: false
57
51
  version_requirements: !ruby/object:Gem::Requirement
58
- none: false
59
52
  requirements:
60
53
  - - ~>
61
54
  - !ruby/object:Gem::Version
62
- version: '2.11'
63
- description: pakyow-presenter
55
+ version: '5.0'
56
+ - !ruby/object:Gem::Dependency
57
+ name: pry
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ~>
61
+ - !ruby/object:Gem::Version
62
+ version: '0.9'
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: '0.9'
70
+ description: A library for building a frontend for Pakyow applications, including
71
+ templating and data binding.
64
72
  email: bryan@metabahn.com
65
73
  executables: []
66
74
  extensions: []
@@ -73,38 +81,41 @@ files:
73
81
  - pakyow-presenter/lib/presenter/attributes.rb
74
82
  - pakyow-presenter/lib/presenter/base.rb
75
83
  - pakyow-presenter/lib/presenter/binder.rb
76
- - pakyow-presenter/lib/presenter/bindings.rb
77
- - pakyow-presenter/lib/presenter/configuration/base.rb
78
- - pakyow-presenter/lib/presenter/configuration/presenter.rb
84
+ - pakyow-presenter/lib/presenter/binder_set.rb
85
+ - pakyow-presenter/lib/presenter/config/presenter.rb
86
+ - pakyow-presenter/lib/presenter/doc_helpers.rb
87
+ - pakyow-presenter/lib/presenter/exceptions.rb
88
+ - pakyow-presenter/lib/presenter/ext/app.rb
79
89
  - pakyow-presenter/lib/presenter/helpers.rb
80
- - pakyow-presenter/lib/presenter/lazy_view.rb
90
+ - pakyow-presenter/lib/presenter/page.rb
91
+ - pakyow-presenter/lib/presenter/partial.rb
81
92
  - pakyow-presenter/lib/presenter/presenter.rb
93
+ - pakyow-presenter/lib/presenter/template.rb
82
94
  - pakyow-presenter/lib/presenter/view.rb
83
95
  - pakyow-presenter/lib/presenter/view_collection.rb
84
- - pakyow-presenter/lib/presenter/view_context.rb
85
- - pakyow-presenter/lib/presenter/view_lookup_store.rb
96
+ - pakyow-presenter/lib/presenter/view_store.rb
86
97
  homepage: http://pakyow.com
87
- licenses: []
98
+ licenses:
99
+ - MIT
100
+ metadata: {}
88
101
  post_install_message:
89
102
  rdoc_options: []
90
103
  require_paths:
91
104
  - pakyow-presenter/lib
92
105
  required_ruby_version: !ruby/object:Gem::Requirement
93
- none: false
94
106
  requirements:
95
- - - ! '>='
107
+ - - '>='
96
108
  - !ruby/object:Gem::Version
97
- version: 1.8.7
109
+ version: 1.9.3
98
110
  required_rubygems_version: !ruby/object:Gem::Requirement
99
- none: false
100
111
  requirements:
101
- - - ! '>'
112
+ - - '>'
102
113
  - !ruby/object:Gem::Version
103
114
  version: 1.3.1
104
115
  requirements: []
105
116
  rubyforge_project: pakyow-presenter
106
- rubygems_version: 1.8.23
117
+ rubygems_version: 2.0.0
107
118
  signing_key:
108
- specification_version: 3
109
- summary: pakyow-presenter
119
+ specification_version: 4
120
+ summary: A library for building a frontend for Pakyow applications.
110
121
  test_files: []
@@ -1,103 +0,0 @@
1
- module Pakyow
2
- module Presenter
3
- class Bindings
4
- attr_accessor :bindable
5
- attr_reader :bindings, :binding_options, :mapping
6
-
7
- include GeneralHelpers
8
-
9
- def fn(name, &block)
10
- @funcs[name] = block and return if block
11
- @funcs[name]
12
- end
13
-
14
- def self.for(block)
15
- Bindings.new(block)
16
- end
17
-
18
- def initialize(block = nil)
19
- @funcs = {}
20
- @bindings = {}
21
- @binding_options = {}
22
- self.instance_exec(&block) if block
23
- end
24
-
25
- def binding(name, func = nil, &block)
26
- @bindings[name] = func || block
27
- end
28
-
29
- def options(name, func = nil, &block)
30
- @binding_options[name] = func || block
31
- end
32
-
33
- def options_for_prop(prop)
34
- if fn = @binding_options[prop]
35
- fn.call
36
- end
37
- end
38
-
39
- def value_for_prop(prop)
40
- # mapping always overrides fns for a scope
41
- if @mapping
42
- @binder ||= Kernel.const_get(@mapping).new(@bindable)
43
- @binder.value_for_prop(prop)
44
- elsif binding = @bindings[prop]
45
- case binding.arity
46
- when 0
47
- self.instance_exec(&binding)
48
- when 1
49
- self.instance_exec(@bindable[prop], &binding)
50
- end
51
- else
52
- # default
53
- @bindable[prop]
54
- end
55
- end
56
-
57
- # Merges a Bindings instance or Hash of bindings to self
58
- def merge(bindings)
59
- if bindings.is_a?(Hash)
60
- @bindings = @bindings.merge(bindings)
61
- elsif bindings
62
- @bindings = bindings.bindings.merge(@bindings)
63
- @mapping = bindings.mapping if bindings.mapping
64
- @binding_options = bindings.binding_options if bindings.binding_options && !bindings.binding_options.empty?
65
- end
66
-
67
- self
68
- end
69
-
70
- def map(klass)
71
- #TODO make sure klass is subclass of Binder
72
- @mapping = klass
73
- self
74
-
75
- # klass must be a subclass of Binder
76
- # sets flag on self to indicate it's a mapping
77
- # value_for_prop checks flag, if set call Binder (just like 0.7)
78
- end
79
-
80
- def restful(route_group)
81
- self.binding(:action) {
82
- routes = router.group(route_group)
83
- return_data = {}
84
-
85
- if id = bindable[:id]
86
- return_data[:content] = lambda { |content|
87
- '<input type="hidden" name="_method" value="put">' + content
88
- }
89
-
90
- action = routes.populate(:update, :id => id)
91
- else
92
- action = routes.populate(:create)
93
- end
94
-
95
- return_data[:action] = action
96
- return_data[:method] = 'post'
97
- return_data
98
- }
99
- end
100
- end
101
- end
102
- end
103
-
@@ -1,12 +0,0 @@
1
- module Pakyow
2
- module Configuration
3
- autoload :Presenter, 'presenter/configuration/presenter'
4
-
5
- class Base
6
- # Fetches the server configuration
7
- def self.presenter
8
- Configuration::Presenter
9
- end
10
- end
11
- end
12
- end
@@ -1,45 +0,0 @@
1
- module Pakyow
2
- module Configuration
3
- class Presenter
4
- class << self
5
- attr_accessor :view_caching, :javascripts, :stylesheets, :view_stores, :default_view,
6
- :scope_attribute, :prop_attribute, :container_attribute
7
-
8
- # Location of javascripts
9
- def javascripts
10
- @javascripts || '/javascripts'
11
- end
12
-
13
- # Location of stylesheets
14
- def stylesheets
15
- @stylesheets || '/stylesheets'
16
- end
17
-
18
- def view_stores
19
- @view_stores ||= {:default => "#{Configuration::Base.app.root}/views"}
20
- end
21
-
22
- def view_caching
23
- @view_caching || false
24
- end
25
-
26
- def default_view
27
- @default_view || "pakyow.html"
28
- end
29
-
30
- def scope_attribute
31
- @scope_attribute || "data-scope"
32
- end
33
-
34
- def prop_attribute
35
- @prop_attribute || "data-prop"
36
- end
37
-
38
- def container_attribute
39
- @container_attribute || "data-container"
40
- end
41
-
42
- end
43
- end
44
- end
45
- end