pakyow-presenter 1.0.0.rc5 → 1.0.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.
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