pakyow-presenter 0.11.3 → 1.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "pakyow/support/core_refinements/string/normalization"
4
+
5
+ require "pakyow/error"
6
+
7
+ module Pakyow
8
+ module Presenter
9
+ class Error < Pakyow::Error
10
+ end
11
+
12
+ class FrontMatterParsingError < Error
13
+ end
14
+
15
+ class UnknownPage < Error
16
+ using Support::Refinements::String::Normalization
17
+
18
+ def contextual_message
19
+ <<~MESSAGE
20
+ Pakyow couldn't render a view for `#{String.normalize_path(@context)}`. Try creating a view template for this path:
21
+
22
+ frontend/pages#{template_path}.html
23
+
24
+ * [Learn about view templates &rarr;](https://pakyow.com/docs/frontend/composition/)
25
+ MESSAGE
26
+ end
27
+
28
+ private
29
+
30
+ def template_path
31
+ if @context.to_s.empty? || @context.to_s == "/"
32
+ "/index"
33
+ else
34
+ @context
35
+ end
36
+ end
37
+ end
38
+
39
+ class ImplicitRenderingError < UnknownPage
40
+ def name
41
+ "Unknown page"
42
+ end
43
+
44
+ def contextual_message
45
+ if Pakyow.env?(:prototype)
46
+ super
47
+ else
48
+ <<~MESSAGE
49
+ #{super}
50
+
51
+ If you want to call backend code instead, create a controller endpoint that handles this request:
52
+
53
+ get "#{@context}" do
54
+ # your code here
55
+ end
56
+
57
+ * [Learn about controllers &rarr;](https://pakyow.com/docs/routing/)
58
+ MESSAGE
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,203 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "pakyow/framework"
4
+
5
+ require "pakyow/support/indifferentize"
6
+ require "pakyow/support/core_refinements/string/normalization"
7
+
8
+ require "pakyow/presenter/behavior/config"
9
+ require "pakyow/presenter/behavior/error_rendering"
10
+ require "pakyow/presenter/behavior/exposures"
11
+ require "pakyow/presenter/behavior/implicit_rendering"
12
+ require "pakyow/presenter/behavior/initializing"
13
+ require "pakyow/presenter/behavior/modes"
14
+ require "pakyow/presenter/behavior/versions"
15
+ require "pakyow/presenter/behavior/watching"
16
+
17
+ require "pakyow/presenter/helpers/rendering"
18
+
19
+ require "pakyow/presenter/renderable"
20
+
21
+ require "pakyow/presenter/renderer"
22
+
23
+ require "pakyow/presenter/rendering/actions/cleanup_prototype_nodes"
24
+ require "pakyow/presenter/rendering/actions/cleanup_unbound_bindings"
25
+ require "pakyow/presenter/rendering/actions/create_template_nodes"
26
+ require "pakyow/presenter/rendering/actions/insert_prototype_bar"
27
+ require "pakyow/presenter/rendering/actions/install_authenticity"
28
+ require "pakyow/presenter/rendering/actions/place_in_mode"
29
+ require "pakyow/presenter/rendering/actions/render_components"
30
+ require "pakyow/presenter/rendering/actions/set_page_title"
31
+ require "pakyow/presenter/rendering/actions/setup_endpoints"
32
+ require "pakyow/presenter/rendering/actions/setup_forms"
33
+
34
+ module Pakyow
35
+ module Presenter
36
+ class Framework < Pakyow::Framework(:presenter)
37
+ using Support::Indifferentize
38
+ using Support::Refinements::String::Normalization
39
+
40
+ def boot
41
+ require "pakyow/presenter/presentable_error"
42
+
43
+ object.class_eval do
44
+ isolate Binder
45
+ isolate Presenter
46
+
47
+ # Make sure component presenters inherit from this app's presenter.
48
+ #
49
+ isolated_presenter = isolated(:Presenter)
50
+ isolate Component do
51
+ @__presenter_class = isolated_presenter
52
+ end
53
+
54
+ isolate Renderer do
55
+ include Actions::CleanupPrototypeNodes
56
+ include Actions::CleanupUnboundBindings
57
+ include Actions::InsertPrototypeBar
58
+ include Actions::InstallAuthenticity
59
+ include Actions::PlaceInMode
60
+ include Actions::CreateTemplateNodes
61
+ include Actions::SetupEndpoints
62
+ include Actions::SetupForms
63
+ include Actions::SetPageTitle
64
+ end
65
+
66
+ after "load" do
67
+ isolated(:Renderer) do
68
+ include Actions::RenderComponents
69
+ end
70
+ end
71
+
72
+ # Build presenter classes for compound components.
73
+ #
74
+ after :initialize, priority: :high do
75
+ state(:templates).each do |templates|
76
+ templates.each do |template|
77
+ template.object.each_significant_node(:component, descend: true) do |node|
78
+ if node.label(:components).count > 1
79
+ component_classes = node.label(:components).each_with_object([]) { |component_label, arr|
80
+ component_class = state(:component).find { |component|
81
+ component.__object_name.name == component_label[:name]
82
+ }
83
+
84
+ if component_class
85
+ arr << component_class
86
+ end
87
+ }
88
+
89
+ if component_classes.count > 1
90
+ state(:presenter) << Actions::RenderComponents.find_or_build_compound_presenter(
91
+ self, component_classes
92
+ )
93
+ end
94
+ end
95
+ end
96
+ end
97
+ end
98
+ end
99
+
100
+ def presenter_for_context(presenter_class, context)
101
+ presenter_class.new(
102
+ context.view, app: context.app, presentables: context.presentables
103
+ )
104
+ end
105
+
106
+ stateful :binder, isolated(:Binder)
107
+ stateful :component, isolated(:Component)
108
+ stateful :presenter, isolated(:Presenter)
109
+
110
+ stateful :processor, Processor
111
+ stateful :templates, Templates
112
+
113
+ aspect :binders
114
+ aspect :components
115
+ aspect :presenters
116
+
117
+ register_helper :active, Helpers::Rendering
118
+
119
+ isolated :Connection do
120
+ include Renderable
121
+ end
122
+
123
+ isolated :Controller do
124
+ include Behavior::ImplicitRendering
125
+
126
+ action :verify_form_metadata do
127
+ if metadata = params[:_form]
128
+ connection.set(
129
+ :__form,
130
+ JSON.parse(
131
+ connection.verifier.verify(metadata)
132
+ ).indifferentize
133
+ )
134
+
135
+ params.delete(:_form)
136
+ end
137
+ end
138
+ end
139
+
140
+ on "load" do
141
+ self.class.include_helpers :global, isolated(:Binder)
142
+ self.class.include_helpers :global, isolated(:Presenter)
143
+ self.class.include_helpers :active, isolated(:Component)
144
+
145
+ # Override the app helper so that config returns the component config.
146
+ # FIXME: Find a clearer way to do this.
147
+ #
148
+ isolated(:Component) do
149
+ if instance_methods(false).include?(:config)
150
+ remove_method :config
151
+ end
152
+
153
+ attr_reader :config
154
+ end
155
+ end
156
+
157
+ # Let each renderer action attach renders to the app's presenter.
158
+ #
159
+ after "initialize", priority: :low do
160
+ [isolated(:Presenter)].concat(
161
+ state(:presenter)
162
+ ).concat(
163
+ state(:component).map(&:__presenter_class)
164
+ ).uniq.each do |presenter|
165
+ isolated(:Renderer).attach!(presenter, app: self)
166
+ end
167
+ end
168
+
169
+ # Update the presenter version and rebuild the app version.
170
+ #
171
+ after "initialize" do
172
+ config.presenter.version = Support::PathVersion.build(config.presenter.path)
173
+
174
+ app_version = Digest::SHA1.new
175
+ app_version.update(config.version)
176
+ app_version.update(config.presenter.version)
177
+ config.version = app_version.to_s
178
+ end
179
+
180
+ include Behavior::Config
181
+ include Behavior::ErrorRendering
182
+ include Behavior::Exposures
183
+ include Behavior::Initializing
184
+ include Behavior::Modes
185
+ include Behavior::Versions
186
+ include Behavior::Watching
187
+
188
+ def view_info_for_path(path)
189
+ path = String.collapse_path(path)
190
+
191
+ state(:templates).lazy.map { |store|
192
+ store.info(path)
193
+ }.find(&:itself)
194
+ end
195
+
196
+ def view?(path)
197
+ !view_info_for_path(path).nil?
198
+ end
199
+ end
200
+ end
201
+ end
202
+ end
203
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "pakyow/support/indifferentize"
4
+
5
+ module Pakyow
6
+ module Presenter
7
+ # Parses front matter from text files.
8
+ #
9
+ # @api private
10
+ module FrontMatterParser
11
+ MATTER_MATCHER = /\A---\s*\n(.*?\n?)^---\s*$\n?/m
12
+
13
+ # Parses HTML and returns a hash of front matter info
14
+ #
15
+ def self.parse(html_string, _file = nil)
16
+ unless match = html_string.match(MATTER_MATCHER)
17
+ return Support::IndifferentHash.new
18
+ end
19
+
20
+ begin
21
+ Support::IndifferentHash.deep(YAML.load(match.captures[0]).to_h)
22
+ rescue Psych::SyntaxError => error
23
+ raise FrontMatterParsingError.build(error, context: match.captures[0])
24
+ end
25
+ end
26
+
27
+ # Returns HTML with front matter removed
28
+ #
29
+ def self.scrub(html_string)
30
+ html_string.gsub(MATTER_MATCHER, "")
31
+ end
32
+
33
+ # Parses HTML and returns:
34
+ # - a hash of front matter info
35
+ # - the HTML with front matter removed
36
+ #
37
+ def self.parse_and_scrub(html_string)
38
+ return parse(html_string), scrub(html_string)
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pakyow
4
+ module Presenter
5
+ module Helpers
6
+ module Rendering
7
+ def render(view_path = nil, as: nil, modes: [:default])
8
+ @connection.app.isolated(:Renderer).render(
9
+ @connection,
10
+ view_path: view_path,
11
+ presenter_path: as,
12
+ modes: modes
13
+ )
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pakyow
4
+ module Presenter
5
+ module Presentable
6
+ def method_missing(method_name, *args, &block)
7
+ if presentable?(method_name)
8
+ @presentables[args.unshift(method_name).join(":").to_sym]
9
+ else
10
+ super
11
+ end
12
+ end
13
+
14
+ def respond_to_missing?(method_name, include_private = false)
15
+ presentable?(method_name) || super
16
+ end
17
+
18
+ private
19
+
20
+ def presentable?(presentable_key)
21
+ presentable_key = presentable_key.to_s
22
+ instance_variable_defined?(:@presentables) && @presentables.any? { |key, _|
23
+ key.to_s.start_with?(presentable_key)
24
+ }
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "pakyow/error"
4
+
5
+ module Pakyow
6
+ class Error
7
+ def [](key)
8
+ if respond_to?(key)
9
+ public_send(key)
10
+ else
11
+ nil
12
+ end
13
+ end
14
+
15
+ def include?(key)
16
+ respond_to?(key)
17
+ end
18
+ end
19
+ end