pakyow-presenter 0.11.3 → 1.0.0.rc1

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 (100) hide show
  1. checksums.yaml +5 -5
  2. data/{pakyow-presenter/CHANGELOG.md → CHANGELOG.md} +0 -5
  3. data/LICENSE +4 -0
  4. data/{pakyow-presenter/README.md → README.md} +1 -2
  5. data/lib/pakyow/generators/presenter/presenter_generator.rb +28 -0
  6. data/lib/pakyow/generators/presenter/templates/presenter.rb.tt +2 -0
  7. data/lib/pakyow/plugin/helpers/rendering.rb +19 -0
  8. data/lib/pakyow/presenter/actions/auto_render.rb +15 -0
  9. data/lib/pakyow/presenter/attributes/attribute.rb +22 -0
  10. data/lib/pakyow/presenter/attributes/boolean.rb +24 -0
  11. data/lib/pakyow/presenter/attributes/hash.rb +89 -0
  12. data/lib/pakyow/presenter/attributes/set.rb +61 -0
  13. data/lib/pakyow/presenter/attributes/string.rb +38 -0
  14. data/lib/pakyow/presenter/attributes.rb +126 -0
  15. data/lib/pakyow/presenter/behavior/config.rb +29 -0
  16. data/lib/pakyow/presenter/behavior/error_rendering.rb +124 -0
  17. data/lib/pakyow/presenter/behavior/exposures.rb +29 -0
  18. data/lib/pakyow/presenter/behavior/implicit_rendering.rb +21 -0
  19. data/lib/pakyow/presenter/behavior/initializing.rb +37 -0
  20. data/lib/pakyow/presenter/behavior/modes.rb +117 -0
  21. data/lib/pakyow/presenter/behavior/versions.rb +71 -0
  22. data/lib/pakyow/presenter/behavior/watching.rb +21 -0
  23. data/lib/pakyow/presenter/binder.rb +115 -0
  24. data/lib/pakyow/presenter/binding_parts.rb +64 -0
  25. data/lib/pakyow/presenter/component.rb +74 -0
  26. data/lib/pakyow/presenter/composers/component.rb +78 -0
  27. data/lib/pakyow/presenter/composers/view.rb +73 -0
  28. data/lib/pakyow/presenter/errors.rb +63 -0
  29. data/lib/pakyow/presenter/framework.rb +203 -0
  30. data/lib/pakyow/presenter/front_matter_parser.rb +42 -0
  31. data/lib/pakyow/presenter/helpers/rendering.rb +18 -0
  32. data/lib/pakyow/presenter/presentable.rb +28 -0
  33. data/lib/pakyow/presenter/presentable_error.rb +19 -0
  34. data/lib/pakyow/presenter/presenter.rb +766 -0
  35. data/lib/pakyow/presenter/presenters/endpoint.rb +158 -0
  36. data/lib/pakyow/presenter/presenters/form.rb +522 -0
  37. data/lib/pakyow/presenter/processor.rb +61 -0
  38. data/lib/pakyow/presenter/renderable.rb +28 -0
  39. data/lib/pakyow/presenter/renderer.rb +269 -0
  40. data/lib/pakyow/presenter/rendering/actions/cleanup_prototype_nodes.rb +21 -0
  41. data/lib/pakyow/presenter/rendering/actions/cleanup_unbound_bindings.rb +35 -0
  42. data/lib/pakyow/presenter/rendering/actions/create_template_nodes.rb +27 -0
  43. data/lib/pakyow/presenter/rendering/actions/insert_prototype_bar.rb +101 -0
  44. data/lib/pakyow/presenter/rendering/actions/install_authenticity.rb +42 -0
  45. data/lib/pakyow/presenter/rendering/actions/place_in_mode.rb +56 -0
  46. data/lib/pakyow/presenter/rendering/actions/render_components.rb +279 -0
  47. data/lib/pakyow/presenter/rendering/actions/set_page_title.rb +35 -0
  48. data/lib/pakyow/presenter/rendering/actions/setup_endpoints.rb +62 -0
  49. data/lib/pakyow/presenter/rendering/actions/setup_forms.rb +174 -0
  50. data/lib/pakyow/presenter/significant_nodes.rb +309 -0
  51. data/lib/pakyow/presenter/templates.rb +229 -0
  52. data/lib/pakyow/presenter/versioned_view.rb +209 -0
  53. data/lib/pakyow/presenter/view.rb +586 -0
  54. data/lib/pakyow/presenter/views/form.rb +58 -0
  55. data/lib/pakyow/presenter/views/layout.rb +32 -0
  56. data/lib/pakyow/presenter/views/page.rb +72 -0
  57. data/lib/pakyow/presenter/views/partial.rb +28 -0
  58. data/lib/pakyow/presenter.rb +33 -0
  59. data/lib/pakyow/views/errors/layouts/development_error.html +102 -0
  60. data/lib/pakyow/views/errors/layouts/production_error.html +27 -0
  61. data/lib/pakyow/views/errors/pages/404.html +12 -0
  62. data/lib/pakyow/views/errors/pages/500.html +12 -0
  63. data/lib/pakyow/views/errors/pages/development/500.html +39 -0
  64. data/lib/string_doc/attributes.rb +109 -0
  65. data/lib/string_doc/meta_attributes.rb +48 -0
  66. data/lib/string_doc/meta_node.rb +328 -0
  67. data/lib/string_doc/node.rb +377 -0
  68. data/lib/string_doc.rb +642 -0
  69. metadata +95 -75
  70. data/pakyow-presenter/LICENSE +0 -20
  71. data/pakyow-presenter/lib/pakyow/presenter/attributes.rb +0 -228
  72. data/pakyow-presenter/lib/pakyow/presenter/base.rb +0 -38
  73. data/pakyow-presenter/lib/pakyow/presenter/binder.rb +0 -116
  74. data/pakyow-presenter/lib/pakyow/presenter/binder_set.rb +0 -94
  75. data/pakyow-presenter/lib/pakyow/presenter/binding_eval.rb +0 -37
  76. data/pakyow-presenter/lib/pakyow/presenter/config/presenter.rb +0 -42
  77. data/pakyow-presenter/lib/pakyow/presenter/container.rb +0 -6
  78. data/pakyow-presenter/lib/pakyow/presenter/doc_helpers.rb +0 -17
  79. data/pakyow-presenter/lib/pakyow/presenter/exceptions.rb +0 -11
  80. data/pakyow-presenter/lib/pakyow/presenter/ext/app.rb +0 -33
  81. data/pakyow-presenter/lib/pakyow/presenter/ext/call_context.rb +0 -28
  82. data/pakyow-presenter/lib/pakyow/presenter/helpers.rb +0 -46
  83. data/pakyow-presenter/lib/pakyow/presenter/page.rb +0 -110
  84. data/pakyow-presenter/lib/pakyow/presenter/partial.rb +0 -6
  85. data/pakyow-presenter/lib/pakyow/presenter/presenter.rb +0 -232
  86. data/pakyow-presenter/lib/pakyow/presenter/string_doc.rb +0 -380
  87. data/pakyow-presenter/lib/pakyow/presenter/string_doc_parser.rb +0 -144
  88. data/pakyow-presenter/lib/pakyow/presenter/string_doc_renderer.rb +0 -18
  89. data/pakyow-presenter/lib/pakyow/presenter/template.rb +0 -51
  90. data/pakyow-presenter/lib/pakyow/presenter/view.rb +0 -541
  91. data/pakyow-presenter/lib/pakyow/presenter/view_collection.rb +0 -330
  92. data/pakyow-presenter/lib/pakyow/presenter/view_composer.rb +0 -237
  93. data/pakyow-presenter/lib/pakyow/presenter/view_context.rb +0 -111
  94. data/pakyow-presenter/lib/pakyow/presenter/view_store.rb +0 -262
  95. data/pakyow-presenter/lib/pakyow/presenter/view_store_loader.rb +0 -43
  96. data/pakyow-presenter/lib/pakyow/presenter/view_version.rb +0 -113
  97. data/pakyow-presenter/lib/pakyow/presenter.rb +0 -8
  98. data/pakyow-presenter/lib/pakyow/views/errors/404.erb +0 -26
  99. data/pakyow-presenter/lib/pakyow/views/errors/500.erb +0 -23
  100. data/pakyow-presenter/lib/pakyow-presenter.rb +0 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 5083bed2c1a6c7c03aded460060cb26708435a60
4
- data.tar.gz: 5a09f8082023ac3cb21ec975dbbc793379ab86ea
2
+ SHA256:
3
+ metadata.gz: 1bd0c274a2f3fdcfc17a93a8390f6e785280815105100977f2e57770d44b3bb3
4
+ data.tar.gz: 270e993fbfd4ff58aac7ad070ab050e8b21029204e6a356ebf0fc82cd268aa25
5
5
  SHA512:
6
- metadata.gz: dcbca0b0d95e29ad8fd4ea0de656747fc51ac02b49bb0d8d51e52cf732afa451536fbb9dd70b194b2570e70c0dceb1d0dff17f5f3727ed06c6d790316ff56db1
7
- data.tar.gz: 027ad8c270f1d8946061e1a7314d845959d77a01c5dd5d310e9ff9e9c1e85fa5f06b7131e7c85cc671bc5ef3a3869d4d6430c80f6c338fa909da73a25b0a7457
6
+ metadata.gz: 30cd88cf117723d9800598412000b59b1a4d825a3a6766250209ba5e7ac902c579273f0160ddc055e2339342e0d7fa96e6ff91474e73d3273d7666e8bf4581e0
7
+ data.tar.gz: aef3ab5a380c55076f59e6947096a7c4e92c7c630263ca96627a1cd78cd9d99f11b870db904f169d109804346a81944593b4f0da818d45c99a2c1e793b7d7562
@@ -1,8 +1,3 @@
1
- # 0.11.2
2
-
3
- * Fixes bug causing resource bindings to be incorrect in some cases
4
- * Fixes bug creating unscoped view collection from composer
5
-
6
1
  # 0.11.0
7
2
 
8
3
  * Fixes several bugs related to nested partials
data/LICENSE ADDED
@@ -0,0 +1,4 @@
1
+ Copyright (c) Metabahn, LLC
2
+
3
+ Pakyow Presenter is an open-source project licensed under the terms of the LGPLv3 license.
4
+ See <https://choosealicense.com/licenses/lgpl-3.0/> for license text.
@@ -16,8 +16,7 @@ Source code can be downloaded as part of the Pakyow project on Github:
16
16
 
17
17
  # License
18
18
 
19
- Pakyow Presenter is released free and open-source under the [MIT
20
- License](http://opensource.org/licenses/MIT).
19
+ Pakyow Presenter is free and open-source under the [LGPLv3 license](https://choosealicense.com/licenses/lgpl-3.0/).
21
20
 
22
21
  # Support
23
22
 
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "pakyow/generator"
4
+
5
+ module Pakyow
6
+ # @api private
7
+ module Generators
8
+ class Presenter < Generator
9
+ def self.source_root
10
+ File.expand_path("../", __FILE__)
11
+ end
12
+
13
+ argument :app
14
+ argument :name
15
+ argument :view_path
16
+
17
+ def create_presenter
18
+ template("templates/presenter.rb.tt", File.join(app.config.src, "presenters/#{name}_presenter.rb"))
19
+ end
20
+
21
+ protected
22
+
23
+ def normalized_view_path
24
+ File.join("/", view_path)
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,2 @@
1
+ presenter "<%= normalized_view_path %>" do
2
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "pakyow/support/extension"
4
+
5
+ module Pakyow
6
+ class Plugin
7
+ module Helpers
8
+ module Rendering
9
+ extend Support::Extension
10
+
11
+ prepend_methods do
12
+ def render(path = @connection.get(:__endpoint_path) || @connection.path, *args)
13
+ super(File.join(@connection.app.class.mount_path, path), *args)
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pakyow
4
+ module Presenter
5
+ module Actions
6
+ # Renders a view in the case a controller wasn't called.
7
+ #
8
+ class AutoRender
9
+ def call(connection)
10
+ connection.app.isolated(:Renderer).render_implicitly(connection)
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pakyow
4
+ module Presenter
5
+ class Attributes
6
+ # @api private
7
+ class Attribute
8
+ def initialize(value)
9
+ @value = value
10
+ end
11
+
12
+ def initialize_copy(_)
13
+ @value = @value.dup
14
+ end
15
+
16
+ def ==(other)
17
+ @value == other
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "pakyow/presenter/attributes/string"
4
+
5
+ module Pakyow
6
+ module Presenter
7
+ class Attributes
8
+ # Boolean is an odd attribute, since we ultimately want it to behave in this way:
9
+ #
10
+ # view.attrs[:checked] = true
11
+ # => <input checked="checked" ...>
12
+ #
13
+ # view.attrs[:checked] = false
14
+ # => <input ...>
15
+ #
16
+ # To support this, +Attributes+ manages setting / removing the value on the
17
+ # underlying object; all we do is behave like a String.
18
+ #
19
+ # @api private
20
+ class Boolean < String
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,89 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "forwardable"
4
+
5
+ require "pakyow/support/safe_string"
6
+
7
+ require "pakyow/presenter/attributes/attribute"
8
+
9
+ module Pakyow
10
+ module Presenter
11
+ class Attributes
12
+ # Wraps the value for a hash-type view attribute (e.g. style).
13
+ #
14
+ # Behaves just like a normal +Hash+.
15
+ #
16
+ class Hash < Attribute
17
+ VALUE_SEPARATOR = ":".freeze
18
+ PAIR_SEPARATOR = ";".freeze
19
+
20
+ WRITE_VALUE_SEPARATOR = ": ".freeze
21
+ WRITE_PAIR_SEPARATOR = "; ".freeze
22
+
23
+ extend Forwardable
24
+ def_delegators :@value, :any?, :empty?, :clear
25
+
26
+ include Support::SafeStringHelpers
27
+
28
+ def include?(key)
29
+ @value.include?(key.to_s)
30
+ end
31
+
32
+ def value?(value)
33
+ @value.value?(value.to_s)
34
+ end
35
+
36
+ def [](key)
37
+ @value[key.to_s]
38
+ end
39
+
40
+ def []=(key, value)
41
+ @value[ensure_html_safety(key)] = ensure_html_safety(value)
42
+ end
43
+
44
+ def delete(key)
45
+ @value.delete(key.to_s)
46
+ end
47
+
48
+ def to_s
49
+ string = ::String.new
50
+ first = true
51
+ @value.each do |key, value|
52
+ unless first
53
+ string << WRITE_PAIR_SEPARATOR
54
+ end
55
+
56
+ string << key
57
+ string << WRITE_VALUE_SEPARATOR
58
+ string << value
59
+ first = false
60
+ end
61
+
62
+ unless string.empty?
63
+ string = string + PAIR_SEPARATOR
64
+ end
65
+
66
+ string
67
+ end
68
+
69
+ class << self
70
+ include Support::SafeStringHelpers
71
+
72
+ def parse(value)
73
+ if value.is_a?(::Hash)
74
+ new(::Hash[value.map { |k, v| [ensure_html_safety(k), ensure_html_safety(v.to_s)]}])
75
+ elsif value.respond_to?(:to_s)
76
+ new(value.to_s.split(PAIR_SEPARATOR).each_with_object({}) { |style, attributes|
77
+ key, value = style.split(VALUE_SEPARATOR)
78
+ next unless key && value
79
+ attributes[ensure_html_safety(key.strip)] = ensure_html_safety(value.strip)
80
+ })
81
+ else
82
+ raise ArgumentError.new("expected value to be a Hash or String")
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "forwardable"
4
+ require "set"
5
+
6
+ require "pakyow/support/safe_string"
7
+
8
+ require "pakyow/presenter/attributes/attribute"
9
+
10
+ module Pakyow
11
+ module Presenter
12
+ class Attributes
13
+ # Wraps the value for a set-type view attribute (e.g. class).
14
+ #
15
+ # Behaves just like a normal +Set+.
16
+ #
17
+ class Set < Attribute
18
+ VALUE_SEPARATOR = " ".freeze
19
+
20
+ extend Forwardable
21
+ def_delegators :@value, :to_a, :any?, :empty?, :clear
22
+
23
+ include Support::SafeStringHelpers
24
+
25
+ def include?(value)
26
+ @value.include?(value.to_s)
27
+ end
28
+
29
+ def <<(value)
30
+ @value << ensure_html_safety(value)
31
+ end
32
+
33
+ def add(value)
34
+ @value.add(ensure_html_safety(value))
35
+ end
36
+
37
+ def delete(value)
38
+ @value.delete(value.to_s)
39
+ end
40
+
41
+ def to_s
42
+ @value.to_a.join(VALUE_SEPARATOR)
43
+ end
44
+
45
+ class << self
46
+ include Support::SafeStringHelpers
47
+
48
+ def parse(value)
49
+ if value.is_a?(Array) || value.is_a?(::Set)
50
+ new(::Set.new(value.map { |v| ensure_html_safety(v) }))
51
+ elsif value.respond_to?(:to_s)
52
+ new(::Set.new(value.to_s.split(VALUE_SEPARATOR).map { |v| ensure_html_safety(v) }))
53
+ else
54
+ raise ArgumentError.new("expected value to be an Array, Set, or String")
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "forwardable"
4
+
5
+ require "pakyow/support/safe_string"
6
+
7
+ require "pakyow/presenter/attributes/attribute"
8
+
9
+ module Pakyow
10
+ module Presenter
11
+ class Attributes
12
+ # Wraps the value for a string-type view attribute (e.g. href).
13
+ #
14
+ # Behaves just like a normal +String+.
15
+ #
16
+ class String < Attribute
17
+ extend Forwardable
18
+ def_delegators :@value, :empty?, :include?
19
+
20
+ def to_s
21
+ @value
22
+ end
23
+
24
+ def to_str
25
+ to_s
26
+ end
27
+
28
+ class << self
29
+ include Support::SafeStringHelpers
30
+
31
+ def parse(value)
32
+ new(ensure_html_safety(value.to_s))
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,126 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "forwardable"
4
+
5
+ require "pakyow/support/safe_string"
6
+
7
+ require "pakyow/presenter/attributes/boolean"
8
+ require "pakyow/presenter/attributes/hash"
9
+ require "pakyow/presenter/attributes/set"
10
+ require "pakyow/presenter/attributes/string"
11
+
12
+ module Pakyow
13
+ module Presenter
14
+ class Attributes
15
+ class << self
16
+ def typed_value_for_attribute_with_name(value, name)
17
+ type = type_of_attribute(name.to_sym)
18
+
19
+ if value.is_a?(type)
20
+ value
21
+ else
22
+ type.parse(value)
23
+ end
24
+ end
25
+
26
+ def type_of_attribute(attribute)
27
+ ATTRIBUTE_TYPES[attribute.to_sym] || ATTRIBUTE_TYPE_DEFAULT
28
+ end
29
+
30
+ def default_value_for_attribute(attribute)
31
+ type = type_of_attribute(attribute.to_sym)
32
+ if type == ATTRIBUTE_TYPE_SET
33
+ ::Set.new
34
+ elsif type == ATTRIBUTE_TYPE_HASH
35
+ ::Hash.new
36
+ elsif type == ATTRIBUTE_TYPE_BOOLEAN
37
+ false
38
+ else
39
+ ::String.new
40
+ end
41
+ end
42
+ end
43
+
44
+ # Object for hash attributes
45
+ ATTRIBUTE_TYPE_HASH = Attributes::Hash
46
+ # Object for set attributes
47
+ ATTRIBUTE_TYPE_SET = Attributes::Set
48
+ # Object for boolean attributes
49
+ ATTRIBUTE_TYPE_BOOLEAN = Attributes::Boolean
50
+ # Default attribute object
51
+ ATTRIBUTE_TYPE_DEFAULT = Attributes::String
52
+
53
+ # Maps non-default attributes to their type
54
+ ATTRIBUTE_TYPES = {
55
+ class: ATTRIBUTE_TYPE_SET,
56
+ style: ATTRIBUTE_TYPE_HASH,
57
+ selected: ATTRIBUTE_TYPE_BOOLEAN,
58
+ checked: ATTRIBUTE_TYPE_BOOLEAN,
59
+ disabled: ATTRIBUTE_TYPE_BOOLEAN,
60
+ readonly: ATTRIBUTE_TYPE_BOOLEAN,
61
+ multiple: ATTRIBUTE_TYPE_BOOLEAN,
62
+ }.freeze
63
+
64
+ extend Forwardable
65
+
66
+ include Support::SafeStringHelpers
67
+
68
+ # @!method keys
69
+ # Returns keys from {@attributes}.
70
+ #
71
+ # @!method []
72
+ # Returns value of key from {@attributes}.
73
+ #
74
+ # @!method []=
75
+ # Returns sets value for key on {@attributes}.
76
+ #
77
+ # @!method delete
78
+ # Deletes key by name from {@attributes}.
79
+ #
80
+ def_delegators :@attributes, :keys, :delete, :each
81
+
82
+ # Wraps a hash of view attributes
83
+ #
84
+ # @param attributes [Hash]
85
+ #
86
+ def initialize(attributes)
87
+ attributes.wrap do |value, name|
88
+ Attributes.typed_value_for_attribute_with_name(value, name)
89
+ end
90
+
91
+ @attributes = attributes
92
+ end
93
+
94
+ def [](attribute)
95
+ attribute = attribute.to_sym
96
+ attribute_type = self.class.type_of_attribute(attribute)
97
+
98
+ if attribute_type == ATTRIBUTE_TYPE_BOOLEAN
99
+ @attributes.key?(attribute)
100
+ else
101
+ @attributes[attribute] ||= attribute_type.new(self.class.default_value_for_attribute(attribute))
102
+ end
103
+ end
104
+
105
+ def []=(attribute, value)
106
+ attribute = ensure_html_safety(attribute.to_s).to_sym
107
+
108
+ if value.nil?
109
+ @attributes.delete(attribute)
110
+ elsif self.class.type_of_attribute(attribute) == ATTRIBUTE_TYPE_BOOLEAN
111
+ if value
112
+ @attributes[attribute] = self.class.typed_value_for_attribute_with_name(attribute, attribute)
113
+ else
114
+ @attributes.delete(attribute)
115
+ end
116
+ else
117
+ @attributes[attribute] = self.class.typed_value_for_attribute_with_name(value, attribute)
118
+ end
119
+ end
120
+
121
+ def has?(attribute)
122
+ @attributes.key?(attribute.to_sym)
123
+ end
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "pakyow/support/extension"
4
+ require "pakyow/support/path_version"
5
+
6
+ module Pakyow
7
+ module Presenter
8
+ module Behavior
9
+ module Config
10
+ extend Support::Extension
11
+
12
+ apply_extension do
13
+ configurable :presenter do
14
+ setting :path do
15
+ File.join(config.root, "frontend")
16
+ end
17
+
18
+ setting :embed_authenticity_token, true
19
+ setting :version
20
+
21
+ configurable :features do
22
+ setting :streaming, false
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,124 @@
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
+ module Presenter
14
+ module Behavior
15
+ module ErrorRendering
16
+ extend Support::Extension
17
+
18
+ def self.render_error(error, context)
19
+ context.respond_to :html do
20
+ if Pakyow.env?(:production)
21
+ context.render "/500"
22
+ else
23
+ unless error.is_a?(Pakyow::Error)
24
+ error = Pakyow::Error.build(error)
25
+ end
26
+
27
+ error.extend Support::Bindable
28
+ context.expose :pw_error, error
29
+ context.render "/development/500"
30
+ end
31
+ end
32
+ end
33
+
34
+ apply_extension do
35
+ handle 404 do
36
+ respond_to :html do
37
+ render "/404"
38
+ end
39
+ end
40
+
41
+ handle 500 do |error|
42
+ ErrorRendering.render_error(error, self)
43
+ end
44
+
45
+ handle UnknownPage, as: 404 do |error|
46
+ if Pakyow.env?(:production)
47
+ trigger 404
48
+ else
49
+ ErrorRendering.render_error(error, self)
50
+ end
51
+ end
52
+
53
+ handle ImplicitRenderingError, as: 404 do |error|
54
+ if Pakyow.env?(:production)
55
+ trigger 404
56
+ else
57
+ ErrorRendering.render_error(error, self)
58
+ end
59
+ end
60
+
61
+ binder :pw_error do
62
+ def message
63
+ html_safe(markdown.render(format(object.message)))
64
+ end
65
+
66
+ def contextual_message
67
+ if object.respond_to?(:contextual_message)
68
+ html_safe(markdown.render(format(object.contextual_message)))
69
+ else
70
+ nil
71
+ end
72
+ end
73
+
74
+ def details
75
+ html_safe(markdown.render(format(object.details)))
76
+ end
77
+
78
+ def backtrace
79
+ html_safe(object.condensed_backtrace.to_a.map { |line|
80
+ CGI.escape_html(line)
81
+ }.join("<br>"))
82
+ end
83
+
84
+ def link
85
+ part :href do
86
+ object.url
87
+ end
88
+
89
+ part :content do
90
+ object.url
91
+ end
92
+ end
93
+
94
+ private
95
+
96
+ def markdown
97
+ @markdown ||= Redcarpet::Markdown.new(
98
+ Redcarpet::Render::HTML.new({})
99
+ )
100
+ end
101
+
102
+ def format(string)
103
+ string = string.dup
104
+
105
+ # Replace `foo' with `foo` to render as inline code.
106
+ #
107
+ string.dup.scan(/`([^']*)'/).each do |match|
108
+ string.gsub!("`#{match[0]}'", "`#{match[0]}`")
109
+ end
110
+
111
+ # Format object references as inline code.
112
+ #
113
+ string.dup.scan(/#<(.*)>/).each do |match|
114
+ string.gsub!("#<#{match[0]}>", "`#<#{match[0]}>`")
115
+ end
116
+
117
+ string
118
+ end
119
+ end
120
+ end
121
+ end
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "pakyow/support/extension"
4
+
5
+ module Pakyow
6
+ module Presenter
7
+ module Behavior
8
+ module Exposures
9
+ extend Support::Extension
10
+
11
+ apply_extension do
12
+ unless ancestors.include?(Plugin)
13
+ # Copy exposures from the plugin renderer.
14
+ #
15
+ after "load.plugins" do
16
+ plugs.each do |plug|
17
+ plug.isolated(:Renderer).__expose_fns.each do |fn|
18
+ isolated(:Renderer).send(:expose) do |connection|
19
+ fn.call(connection, plug)
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "pakyow/support/extension"
4
+
5
+ module Pakyow
6
+ module Presenter
7
+ module Behavior
8
+ # Performs a render if a controller is called but doesn't explicitly render.
9
+ #
10
+ module ImplicitRendering
11
+ extend Support::Extension
12
+
13
+ apply_extension do
14
+ after :dispatch, :implicit_render do
15
+ connection.app.isolated(:Renderer).render_implicitly(connection)
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end