pakyow-presenter 1.0.0.rc5 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (27) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +3 -108
  3. data/lib/pakyow/application/actions/presenter/auto_render.rb +17 -0
  4. data/lib/pakyow/application/behavior/presenter/error_rendering.rb +127 -0
  5. data/lib/pakyow/application/behavior/presenter/exposures.rb +31 -0
  6. data/lib/pakyow/application/behavior/presenter/implicit_rendering.rb +23 -0
  7. data/lib/pakyow/application/behavior/presenter/initializing.rb +69 -0
  8. data/lib/pakyow/application/behavior/presenter/modes.rb +120 -0
  9. data/lib/pakyow/application/behavior/presenter/versions.rb +73 -0
  10. data/lib/pakyow/application/behavior/presenter/watching.rb +23 -0
  11. data/lib/pakyow/{presenter/behavior/config.rb → application/config/presenter.rb} +3 -3
  12. data/lib/pakyow/application/helpers/presenter/rendering.rb +20 -0
  13. data/lib/pakyow/plugin/helpers/presenter/rendering.rb +34 -0
  14. data/lib/pakyow/presenter/errors.rb +1 -3
  15. data/lib/pakyow/presenter/framework.rb +18 -18
  16. data/lib/pakyow/presenter.rb +1 -1
  17. metadata +23 -24
  18. data/lib/pakyow/actions/presenter/auto_render.rb +0 -15
  19. data/lib/pakyow/plugin/helpers/rendering.rb +0 -32
  20. data/lib/pakyow/presenter/behavior/error_rendering.rb +0 -125
  21. data/lib/pakyow/presenter/behavior/exposures.rb +0 -29
  22. data/lib/pakyow/presenter/behavior/implicit_rendering.rb +0 -21
  23. data/lib/pakyow/presenter/behavior/initializing.rb +0 -67
  24. data/lib/pakyow/presenter/behavior/modes.rb +0 -118
  25. data/lib/pakyow/presenter/behavior/versions.rb +0 -71
  26. data/lib/pakyow/presenter/behavior/watching.rb +0 -21
  27. data/lib/pakyow/presenter/helpers/rendering.rb +0 -18
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b9c5ded933f632e265d0b327876438738c77bce50a049293a2983686edd48906
4
- data.tar.gz: 0e9f53b49ed7459f2fccd800f25fdbe23ee9569b1cace8c7cdc10886316bd913
3
+ metadata.gz: 684f68ffcb0cc1beb6e24ffd407b5dcd71238cd08342ebcab0aed8f53329e28a
4
+ data.tar.gz: 582b3a284d885de7587b72dbffe85f8d5c8a6119d7b6ab56c0b96f8422d47249
5
5
  SHA512:
6
- metadata.gz: 19eac50259216de2e775bf7d149cae08c0fc464ad42f2cceca3928523f2a424a374aee67863eb22e85e8dfd361b8943183a81482bd4eccbfba9ad322dbc2db43
7
- data.tar.gz: 4ab0bad959c389aa8bbcf36fccfe5b6f096ab454d937a36b58bec6d86a3a2d564362e334477cb239fb74e8cbf0387a3b469b51bea9136a14a8f6cf3df6cd2be6
6
+ metadata.gz: 116abaea114cf8c7779de420e803ce9fd72f62ccbdd7060425a28cf18093e031780bca8f7cc23812fcca1c02a2aebded8e3d3d3b919b71051d4a9e4ebef785e8
7
+ data.tar.gz: 8b450ea512a99c840560da6565501f9999334ca82d2391a6b75ec1cb16d30305cc248da55515aced259069c713a6c64af244c4a1d85c61893f5123c2358b9a39
data/CHANGELOG.md CHANGED
@@ -1,110 +1,5 @@
1
- # 0.11.0
1
+ # UNRELEASED
2
2
 
3
- * Fixes several bugs related to nested partials
4
- * Reprocesses view contents with html processor
5
- * Fixes a bug causing partials not to be duped
6
- * Automatically defines bindings as restful
7
- * Introduces binding parts
8
- * Fixes a bug removing a node from StringDoc
9
- * Renames `app.all_views_visible` config option to `presenter.require_route`
10
- * Fixes some bugs caused by not properly duping view objects
11
- * Replaces Nokogiri with Oga
12
- * Moves everything into the Pakyow namespace
13
- * Adds support for versioned props
14
- * Prioritize root view paths over child paths
15
- * ViewVersion state is now properly updated when matching
3
+ # 1.0
16
4
 
17
- # 0.10.0 / 2015-10-19
18
-
19
- * Adds precomposition to composer
20
- * Fixes binding action for nested resources
21
- * Fixes variable name in remap_partials
22
- * Setup form on `_root` rather than `action` prop
23
- * Handles view paths that don't define an `index` view
24
- * Adds `ViewCollection#scoped_as` convenience method
25
- * Renames default template to `default` (instead of `pakyow`)
26
- * Adds convenience method to check for view existence
27
- * Support binding hashes with `String` keys
28
- * Fixes a bug when a node is inserted after another node that also has a sibling
29
- * Fixes binding to props nested in partial
30
- * Now allows views for a view store to be fragmented across multiple directories
31
- * Adds versioned scopes with auto empty handling
32
- * Now sets scope name explicitly for `ViewCollection` built from a `View`
33
- * Adds a helper method for checking if a attribute exists
34
- * Adds support for components and channels (realtime ftw)
35
- * Adds id of object to scoped node during binding
36
- * Fixes a bug with view contexts in presenter helpers
37
- * Ported all tests to rspec
38
- * Fixes a bug finding scopes in a nested partial
39
- * Fixes a bug where unused partials still being included as parts in the composer
40
- * Fixes a `StringDoc` bug when structure is empty
41
- * Fixes bug preventing passed binding functions from being used when no binding sets are registered for scope
42
- * Fixes namespace collisions
43
- * Fixes error when matching data empty collection
44
- * Renames `inner_html` to `html`
45
- * Now only reloads a view store if the contents have changed
46
- * Yields `prop` node rather than full `scope` in bindings
47
- * Handles `AttributesCollection#<<` for all use cases
48
- * Adds `to_html` method on composer
49
- * No longer complains about a view store missing a template directory
50
- * Now finds view info for a path that doesn't contain a page
51
- * Allows root nodes to be appendable in string doc
52
- * Removes nokogiri doc
53
-
54
- # 0.9.1 / 2014-12-06
55
-
56
- * Fixes bug where name attribute wasn't set on form fields when binding without a value
57
- * Fixes bug causing all partials (not just available ones) to be defined as view parts
58
- * Fixes bug causing form action binding to break
59
-
60
- # 0.9.0 / 2014-11-09
61
-
62
- * Introduces StringDoc, replacing Nokogiri for view rendering with a performant alternative
63
- * Adds the ability to set an empty first option in bindings
64
- * Remove the annoying "no content" for container log message
65
- * Binding context must now be explicitly passed when binding
66
- * Yield bindable value before bindable in view binding fns
67
- * Fixes bug causing non-html view contents to be processed twice
68
- * Removes support for Ruby versions < 2.0.0
69
-
70
- # 0.8.0 / 2014-03-02
71
-
72
- * Major rewrite, including new view syntax, composer, and transformation api
73
-
74
- # 0.7.2 / 2012-02-29
75
-
76
- * No changes -- bumped version to be consistent
77
-
78
- # 0.7.1 / 2012-01-08
79
-
80
- * View caching fixes
81
- * Changed binder to allow definition for multiple endpoints
82
- * Changed in_context to accept context as block argument
83
- * Changed action binder to add leading slash if needed
84
- * Change to allow a view's content to be set to nil
85
- * Fixed Views#find method
86
-
87
- # 0.7.0 / 2011-11-19
88
-
89
- * Cleaned up core/presenter interface
90
- * Optimized view caching
91
- * Binding occurs on the label an object is being bound to, not the object type
92
- * Root view override in index directories no longer specify a root view for siblings
93
- * Fixed problem binding to a checkbox who’s value attribute is not set
94
-
95
- # 0.6.3 / 2011-09-13
96
-
97
- * Fixes binding to bindings defined by HTML 'name' attribute
98
-
99
- # 0.6.2 / 2011-08-20
100
-
101
- * Fixes issue binding object to root nodes
102
- * JRuby Support
103
-
104
- # 0.6.1 / 2011-08-20
105
-
106
- * Fixes gemspec problem
107
-
108
- # 0.6.0 / 2011-08-20
109
-
110
- * Initial gem release of 0.6.0 codebase
5
+ * Hello, Web
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pakyow
4
+ class Application
5
+ module Actions
6
+ module Presenter
7
+ # Renders a view in the case a controller wasn't called.
8
+ #
9
+ class AutoRender
10
+ def call(connection)
11
+ connection.app.isolated(:Renderer).render_implicitly(connection)
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,127 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "cgi"
4
+
5
+ require "redcarpet"
6
+
7
+ require "pakyow/support/bindable"
8
+ require "pakyow/support/extension"
9
+
10
+ require "pakyow/error"
11
+
12
+ module Pakyow
13
+ class Application
14
+ module Behavior
15
+ module Presenter
16
+ module ErrorRendering
17
+ extend Support::Extension
18
+
19
+ # @api private
20
+ def self.render_error(error, context)
21
+ context.respond_to :html do
22
+ if Pakyow.env?(:production)
23
+ context.render "/500"
24
+ else
25
+ unless error.is_a?(Pakyow::Error)
26
+ error = Pakyow::Error.build(error)
27
+ end
28
+
29
+ error.extend Support::Bindable
30
+ context.expose :pw_error, error
31
+ context.render "/development/500"
32
+ end
33
+ end
34
+ end
35
+
36
+ apply_extension do
37
+ handle 404 do
38
+ respond_to :html do
39
+ render "/404"
40
+ end
41
+ end
42
+
43
+ handle 500 do |error|
44
+ ErrorRendering.render_error(error, self)
45
+ end
46
+
47
+ handle Pakyow::Presenter::UnknownPage, as: 404 do |error|
48
+ if Pakyow.env?(:production)
49
+ trigger 404
50
+ else
51
+ ErrorRendering.render_error(error, self)
52
+ end
53
+ end
54
+
55
+ handle Pakyow::Presenter::ImplicitRenderingError, as: 404 do |error|
56
+ if Pakyow.env?(:production)
57
+ trigger 404
58
+ else
59
+ ErrorRendering.render_error(error, self)
60
+ end
61
+ end
62
+
63
+ binder :pw_error do
64
+ def message
65
+ html_safe(markdown.render(format(object.message)))
66
+ end
67
+
68
+ def contextual_message
69
+ if object.respond_to?(:contextual_message)
70
+ html_safe(markdown.render(format(object.contextual_message)))
71
+ else
72
+ nil
73
+ end
74
+ end
75
+
76
+ def details
77
+ html_safe(markdown.render(format(object.details)))
78
+ end
79
+
80
+ def backtrace
81
+ html_safe(object.condensed_backtrace.to_a.map { |line|
82
+ CGI.escape_html(line)
83
+ }.join("<br>"))
84
+ end
85
+
86
+ def link
87
+ part :href do
88
+ object.url
89
+ end
90
+
91
+ part :content do
92
+ object.url
93
+ end
94
+ end
95
+
96
+ private
97
+
98
+ def markdown
99
+ @markdown ||= Redcarpet::Markdown.new(
100
+ Redcarpet::Render::HTML.new({})
101
+ )
102
+ end
103
+
104
+ def format(string)
105
+ string = string.dup
106
+
107
+ # Replace `foo' with `foo` to render as inline code.
108
+ #
109
+ string.dup.scan(/`([^']*)'/).each do |match|
110
+ string.gsub!("`#{match[0]}'", "`#{match[0]}`")
111
+ end
112
+
113
+ # Format object references as inline code.
114
+ #
115
+ string.dup.scan(/#<(.*)>/).each do |match|
116
+ string.gsub!("#<#{match[0]}>", "`#<#{match[0]}>`")
117
+ end
118
+
119
+ string
120
+ end
121
+ end
122
+ end
123
+ end
124
+ end
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "pakyow/support/extension"
4
+
5
+ module Pakyow
6
+ class Application
7
+ module Behavior
8
+ module Presenter
9
+ module Exposures
10
+ extend Support::Extension
11
+
12
+ apply_extension do
13
+ unless ancestors.include?(Plugin)
14
+ # Copy exposures from the plugin renderer.
15
+ #
16
+ after "load.plugins" do
17
+ plugs.each do |plug|
18
+ plug.isolated(:Renderer).__expose_fns.each do |fn|
19
+ isolated(:Renderer).send(:expose) do |connection|
20
+ fn.call(connection, plug)
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "pakyow/support/extension"
4
+
5
+ module Pakyow
6
+ class Application
7
+ module Behavior
8
+ module Presenter
9
+ # Performs a render if a controller is called but doesn't explicitly render.
10
+ #
11
+ module ImplicitRendering
12
+ extend Support::Extension
13
+
14
+ apply_extension do
15
+ after :dispatch, :implicit_render do
16
+ connection.app.isolated(:Renderer).render_implicitly(connection)
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "pakyow/support/extension"
4
+
5
+ require "pakyow/plugin"
6
+
7
+ module Pakyow
8
+ class Application
9
+ module Behavior
10
+ module Presenter
11
+ module Initializing
12
+ extend Support::Extension
13
+
14
+ apply_extension do
15
+ unless ancestors.include?(Plugin)
16
+ after "initialize", "initialize.presenter", priority: :high do
17
+ state(:templates) << Pakyow::Presenter::Templates.new(
18
+ :default,
19
+ config.presenter.path,
20
+ processor: Pakyow::Presenter::ProcessorCaller.new(
21
+ state(:processor).map { |processor|
22
+ processor.new(self)
23
+ }
24
+ )
25
+ )
26
+
27
+ state(:templates) << Pakyow::Presenter::Templates.new(:errors, File.join(File.expand_path("../../../../", __FILE__), "views", "errors"))
28
+ end
29
+
30
+ after "load.plugins" do
31
+ # Load plugin frontend after the app so that app has priority.
32
+ #
33
+ @plugs.each(&:load_frontend)
34
+ end
35
+ end
36
+
37
+ # Build presenter classes for compound components.
38
+ #
39
+ after "initialize", priority: :high do
40
+ state(:templates).each do |templates|
41
+ templates.each do |template|
42
+ template.object.each_significant_node(:component, descend: true) do |node|
43
+ if node.label(:components).count > 1
44
+ component_classes = node.label(:components).each_with_object([]) { |component_label, arr|
45
+ component_class = state(:component).find { |component|
46
+ component.__object_name.name == component_label[:name]
47
+ }
48
+
49
+ if component_class
50
+ arr << component_class
51
+ end
52
+ }
53
+
54
+ if component_classes.count > 1
55
+ state(:presenter) << Pakyow::Presenter::Renderer::Behavior::RenderComponents.find_or_build_compound_presenter(
56
+ self, component_classes
57
+ )
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,120 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "pakyow/support/extension"
4
+
5
+ module Pakyow
6
+ class Application
7
+ module Behavior
8
+ module Presenter
9
+ module Modes
10
+ # @api private
11
+ class ModeCallContext
12
+ def initialize(connection)
13
+ @connection = connection
14
+ end
15
+ end
16
+
17
+ extend Support::Extension
18
+
19
+ attr_accessor :__ui_modes
20
+
21
+ def mode(name, &block)
22
+ @__ui_modes[name.to_sym] = wrap_mode_block(block)
23
+ end
24
+
25
+ private def wrap_mode_block(block)
26
+ if is_a?(Plugin)
27
+ wrap_mode_block_for_plug(self, block)
28
+ else
29
+ Proc.new do |connection|
30
+ isolated(:ModeCallContext).new(connection).instance_eval(&block)
31
+ end
32
+ end
33
+ end
34
+
35
+ private def wrap_mode_block_for_plug(plug, block)
36
+ Proc.new do |connection|
37
+ plug.helper_caller(:passive, connection, plug).instance_eval(&block)
38
+ end
39
+ end
40
+
41
+ prepend_methods do
42
+ def initialize(*)
43
+ @__ui_modes = Hash[
44
+ self.class.__ui_modes.map { |name, block|
45
+ [name, wrap_mode_block(block)]
46
+ }
47
+ ]
48
+
49
+ super
50
+ end
51
+ end
52
+
53
+ apply_extension do
54
+ class_state :__ui_modes, default: {}, inheritable: true
55
+
56
+ after "load" do
57
+ ([:html] + state(:processor).map(&:extensions).flatten).uniq.each do |extension|
58
+ config.process.watched_paths << File.join(config.presenter.path, "**/*.#{extension}")
59
+ end
60
+ end
61
+
62
+ isolate ModeCallContext
63
+
64
+ on "load" do
65
+ self.class.include_helpers :passive, isolated(:ModeCallContext)
66
+ end
67
+
68
+ if ancestors.include?(Plugin)
69
+ # Copy ui modes from other plugins to this plugin.
70
+ #
71
+ after "load" do
72
+ parent.plugs.each do |plug|
73
+ plug.__ui_modes.each do |mode, block|
74
+ unless @__ui_modes.key?(mode)
75
+ plug_namespace = plug.class.__object_name.namespace.parts.last
76
+
77
+ full_mode = if plug_namespace == :default
78
+ :"@#{plug.class.plugin_name}.#{mode}"
79
+ else
80
+ :"@#{plug.class.plugin_name}(#{plug_namespace}).#{mode}"
81
+ end
82
+
83
+ @__ui_modes[full_mode] = block
84
+ end
85
+ end
86
+ end
87
+ end
88
+ else
89
+ # Copy ui modes from plugins to the app.
90
+ #
91
+ after "load.plugins" do
92
+ plugs.each do |plug|
93
+ plug.__ui_modes.each do |mode, block|
94
+ unless @__ui_modes.key?(mode)
95
+ plug_namespace = plug.class.__object_name.namespace.parts.last
96
+
97
+ full_mode = if plug_namespace == :default
98
+ :"@#{plug.class.plugin_name}.#{mode}"
99
+ else
100
+ :"@#{plug.class.plugin_name}(#{plug_namespace}).#{mode}"
101
+ end
102
+
103
+ @__ui_modes[full_mode] = block
104
+ end
105
+ end
106
+ end
107
+ end
108
+ end
109
+ end
110
+
111
+ class_methods do
112
+ def mode(name, &block)
113
+ @__ui_modes[name.to_sym] = block
114
+ end
115
+ end
116
+ end
117
+ end
118
+ end
119
+ end
120
+ end
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "pakyow/support/extension"
4
+
5
+ module Pakyow
6
+ class Application
7
+ module Behavior
8
+ module Presenter
9
+ module Versions
10
+ extend Support::Extension
11
+
12
+ apply_extension do
13
+ if ancestors.include?(Plugin)
14
+ # Copy global versioning logic from other plugins to this plugin.
15
+ #
16
+ after "load" do
17
+ presenters = [isolated(:Presenter)].concat(state(:presenter))
18
+
19
+ parent.plugs.each do |plug|
20
+ plug.isolated(:Presenter).__versioning_logic.each_pair do |version, logic_arr|
21
+ logic_arr.each do |logic|
22
+ presenters.each do |presenter|
23
+ unless presenter.__versioning_logic.include?(version)
24
+ plug_namespace = plug.class.__object_name.namespace.parts.last
25
+
26
+ prefix = if plug_namespace == :default
27
+ plug.class.plugin_name
28
+ else
29
+ "#{plug.class.plugin_name}(#{plug_namespace})"
30
+ end
31
+
32
+ presenter.version :"@#{prefix}.#{version}" do |object|
33
+ instance_exec(object, plug, &logic[:block])
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ else
42
+ # Copy global versioning logic from plugin presenters.
43
+ #
44
+ after "load.plugins" do
45
+ presenters = [isolated(:Presenter)].concat(state(:presenter))
46
+
47
+ plugs.each do |plug|
48
+ plug.isolated(:Presenter).__versioning_logic.each_pair do |version, logic_arr|
49
+ logic_arr.each do |logic|
50
+ presenters.each do |presenter|
51
+ plug_namespace = plug.class.__object_name.namespace.parts.last
52
+
53
+ prefix = if plug_namespace == :default
54
+ plug.class.plugin_name
55
+ else
56
+ "#{plug.class.plugin_name}(#{plug_namespace})"
57
+ end
58
+
59
+ presenter.version :"@#{prefix}.#{version}" do |object|
60
+ instance_exec(object, plug, &logic[:block])
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "pakyow/support/extension"
4
+
5
+ module Pakyow
6
+ class Application
7
+ module Behavior
8
+ module Presenter
9
+ module Watching
10
+ extend Support::Extension
11
+
12
+ apply_extension do
13
+ after "load" do
14
+ ([:html] + state(:processor).map(&:extensions).flatten).uniq.each do |extension|
15
+ config.process.watched_paths << File.join(config.presenter.path, "**/*.#{extension}")
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -4,9 +4,9 @@ require "pakyow/support/extension"
4
4
  require "pakyow/support/path_version"
5
5
 
6
6
  module Pakyow
7
- module Presenter
8
- module Behavior
9
- module Config
7
+ class Application
8
+ module Config
9
+ module Presenter
10
10
  extend Support::Extension
11
11
 
12
12
  apply_extension do
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pakyow
4
+ class Application
5
+ module Helpers
6
+ module Presenter
7
+ module Rendering
8
+ def render(view_path = nil, as: nil, modes: [:default])
9
+ @connection.app.isolated(:Renderer).render(
10
+ @connection,
11
+ view_path: view_path,
12
+ presenter_path: as,
13
+ modes: modes
14
+ )
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "pakyow/support/extension"
4
+
5
+ module Pakyow
6
+ class Plugin
7
+ module Helpers
8
+ module Presenter
9
+ module Rendering
10
+ extend Support::Extension
11
+
12
+ prepend_methods do
13
+ def render(view_path = nil, as: nil, modes: [:default])
14
+ super(File.join(@connection.app.class.mount_path, view_path), as: as, modes: modes)
15
+ rescue Pakyow::Presenter::UnknownPage
16
+ # Try rendering the view from the app.
17
+ #
18
+ connection = @connection.app.parent.isolated(:Connection).from_connection(
19
+ @connection, :@app => @connection.app.parent
20
+ )
21
+
22
+ connection.app.isolated(:Renderer).render(
23
+ connection,
24
+ view_path: view_path,
25
+ presenter_path: as,
26
+ modes: modes
27
+ )
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end