brut 0.0.12 → 0.0.20
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.
- checksums.yaml +4 -4
- data/Gemfile.lock +4 -6
- data/brut.gemspec +1 -3
- data/lib/brut/back_end.rb +7 -0
- data/lib/brut/cli/apps/scaffold.rb +16 -24
- data/lib/brut/framework/config.rb +4 -43
- data/lib/brut/framework/mcp.rb +1 -1
- data/lib/brut/front_end/asset_path_resolver.rb +15 -0
- data/lib/brut/front_end/component.rb +66 -234
- data/lib/brut/front_end/components/constraint_violations.rb +9 -9
- data/lib/brut/front_end/components/form_tag.rb +16 -28
- data/lib/brut/front_end/components/i18n_translations.rb +12 -13
- data/lib/brut/front_end/components/input.rb +0 -1
- data/lib/brut/front_end/components/inputs/csrf_token.rb +2 -2
- data/lib/brut/front_end/components/inputs/radio_button.rb +6 -6
- data/lib/brut/front_end/components/inputs/select.rb +13 -20
- data/lib/brut/front_end/components/inputs/text_field.rb +18 -33
- data/lib/brut/front_end/components/inputs/textarea.rb +11 -26
- data/lib/brut/front_end/components/locale_detection.rb +2 -2
- data/lib/brut/front_end/components/page_identifier.rb +3 -5
- data/lib/brut/front_end/components/{time.rb → time_tag.rb} +13 -10
- data/lib/brut/front_end/components/traceparent.rb +5 -6
- data/lib/brut/front_end/generic_response.rb +33 -0
- data/lib/brut/front_end/handler.rb +2 -0
- data/lib/brut/front_end/http_method.rb +4 -0
- data/lib/brut/front_end/inline_svg_locator.rb +21 -0
- data/lib/brut/front_end/layout.rb +3 -0
- data/lib/brut/front_end/page.rb +16 -29
- data/lib/brut/front_end/request_context.rb +15 -0
- data/lib/brut/front_end/routing.rb +3 -2
- data/lib/brut/front_end.rb +41 -0
- data/lib/brut/i18n/base_methods.rb +14 -8
- data/lib/brut/i18n/for_back_end.rb +5 -0
- data/lib/brut/i18n/for_cli.rb +2 -1
- data/lib/brut/i18n/for_html.rb +9 -1
- data/lib/brut/i18n.rb +1 -0
- data/lib/brut/sinatra_helpers.rb +14 -7
- data/lib/brut/spec_support/component_support.rb +9 -9
- data/lib/brut/spec_support/e2e_support.rb +4 -0
- data/lib/brut/spec_support/matchers/have_i18n_string.rb +5 -0
- data/lib/brut/spec_support/rspec_setup.rb +1 -0
- data/lib/brut/spec_support.rb +4 -3
- data/lib/brut/version.rb +1 -1
- data/lib/brut.rb +2 -45
- metadata +16 -43
- data/lib/brut/front_end/template.rb +0 -47
- data/lib/brut/front_end/templates/block_filter.rb +0 -61
- data/lib/brut/front_end/templates/erb_engine.rb +0 -26
- data/lib/brut/front_end/templates/erb_parser.rb +0 -84
- data/lib/brut/front_end/templates/escapable_filter.rb +0 -20
- data/lib/brut/front_end/templates/html_safe_string.rb +0 -68
- data/lib/brut/front_end/templates/locator.rb +0 -60
data/lib/brut/front_end/page.rb
CHANGED
@@ -14,7 +14,6 @@
|
|
14
14
|
# @see Brut::FrontEnd::Component
|
15
15
|
class Brut::FrontEnd::Page < Brut::FrontEnd::Component
|
16
16
|
include Brut::FrontEnd::HandlingResults
|
17
|
-
using Brut::FrontEnd::Templates::HTMLSafeString::Refinement
|
18
17
|
|
19
18
|
# Returns the name of the layout for this page. This string is used to find an ERB file in `app/src/front_end/layouts`. Every page
|
20
19
|
# must have a layout. If you wish to render a page with no layout, create an empty layout in your app and use that.
|
@@ -31,43 +30,35 @@ class Brut::FrontEnd::Page < Brut::FrontEnd::Component
|
|
31
30
|
# @return [URI|Brut::FrontEnd::HttpStatus|Object] If you return a `URI` (mostly likely by returning the result of calling {Brut::FrontEnd::HandlingResults#redirect_to}), the user is redirected and {#render} is never called. If you return a {Brut::FrontEnd::HttpStatus} (mostly likely by returning the result of calling {Brut::FrontEnd::HandlingResults#http_status}), {#render} is skipped and that status is returned with no content. If anything else is returned, {#render} is called as normal.
|
32
31
|
def before_render = nil
|
33
32
|
|
34
|
-
|
33
|
+
def with_layout(&block)
|
34
|
+
layout_class = Module.const_get(
|
35
|
+
layout_class = RichString.new([
|
36
|
+
self.layout,
|
37
|
+
"layout"
|
38
|
+
].join("_")).camelize
|
39
|
+
)
|
40
|
+
render layout_class.new(page_name:,&block)
|
41
|
+
end
|
42
|
+
|
43
|
+
|
35
44
|
def handle!
|
36
45
|
case before_render
|
37
46
|
in URI => uri
|
38
|
-
Brut.container.instrumentation.add_event("before_render got a URI", uri: uri)
|
39
47
|
uri
|
40
48
|
in Brut::FrontEnd::HttpStatus => http_status
|
41
|
-
Brut.container.instrumentation.add_event("before_render got status", http_status: http_status)
|
42
49
|
http_status
|
43
50
|
else
|
44
|
-
|
51
|
+
self.call
|
45
52
|
end
|
46
53
|
end
|
47
54
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
#
|
52
|
-
# Also, generally don't override this unles you need to do something unusual. Overriding this will completely bypass the layout
|
53
|
-
# system and skip all ERB processing. Unlike {Brut::FrontEnd::Component#render}, overriding this method does not provide access to injected data from the request context.
|
54
|
-
#
|
55
|
-
# @return [Brut::FrontEnd::Templates::HTMLSafeString] string containing the page's full HTML.
|
56
|
-
def render
|
57
|
-
layout_template = Brut.container.layout_locator.locate(self.layout).
|
58
|
-
then { |layout_erb_file| Brut::FrontEnd::Template.new(layout_erb_file) }
|
59
|
-
|
60
|
-
template = Brut.container.page_locator.locate(self.template_name).
|
61
|
-
then { |erb_file| Brut::FrontEnd::Template.new(erb_file) }
|
62
|
-
|
63
|
-
Brut.container.instrumentation.add_event("templates found", layout: layout_template.template_file_path, page: template.template_file_path)
|
64
|
-
|
65
|
-
page = template.render_template(self).html_safe!
|
66
|
-
layout_template.render_template(self) do
|
67
|
-
page
|
55
|
+
def view_template
|
56
|
+
with_layout do
|
57
|
+
page_template
|
68
58
|
end
|
69
59
|
end
|
70
60
|
|
61
|
+
|
71
62
|
# @return [String] name of this page for use in debugging or for whatever reason you may want to dynamically refer to the page's name. The default value is the class name.
|
72
63
|
def self.page_name = self.name
|
73
64
|
|
@@ -77,10 +68,6 @@ class Brut::FrontEnd::Page < Brut::FrontEnd::Component
|
|
77
68
|
# @!visibility private
|
78
69
|
def component_name = raise Brut::Framework::Errors::Bug,"#{self.class} is not a component"
|
79
70
|
|
80
|
-
private
|
81
|
-
|
82
|
-
def template_name = RichString.new(self.class.name).underscorized.to_s.gsub(/^pages\//,"")
|
83
|
-
|
84
71
|
end
|
85
72
|
|
86
73
|
# Holds pages included with the Brut framework
|
@@ -8,6 +8,19 @@
|
|
8
8
|
# and create an initializer for it that accepts the `clock:` keyword argument, the managed instance of {Clock} will be passed into it
|
9
9
|
# when Brut creates an instance of the class.
|
10
10
|
class Brut::FrontEnd::RequestContext
|
11
|
+
|
12
|
+
def self.current
|
13
|
+
Thread.current.thread_variable_get(:request_context)
|
14
|
+
end
|
15
|
+
|
16
|
+
# Create an instance of klass injected with the request context.
|
17
|
+
def self.inject(klass, request_params: nil)
|
18
|
+
self.current.then { |request_context|
|
19
|
+
request_context.as_constructor_args(klass,request_params:)
|
20
|
+
}.then { |constructor_args|
|
21
|
+
klass.new(**constructor_args)
|
22
|
+
}
|
23
|
+
end
|
11
24
|
# Create a new RequestContext based on some of the information provided by Rack
|
12
25
|
#
|
13
26
|
# @param [Hash] env the Rack `env` object, as available to any middleware
|
@@ -177,6 +190,8 @@ private
|
|
177
190
|
args[name] = route
|
178
191
|
elsif !request_params.nil? && (request_params[name.to_s] || request_params[name.to_sym])
|
179
192
|
args[name] = RichString.new(request_params[name.to_s] || request_params[name.to_sym]).to_s_or_nil
|
193
|
+
elsif name == :raw_params
|
194
|
+
args[name] = request_params || {}
|
180
195
|
elsif type == :keyreq
|
181
196
|
request_params_message = if request_params.nil?
|
182
197
|
"no request params provied"
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require "uri"
|
2
|
+
require "phlex"
|
2
3
|
|
3
4
|
# Holds the registered routes for this app.
|
4
5
|
class Brut::FrontEnd::Routing
|
@@ -218,11 +219,11 @@ private
|
|
218
219
|
end
|
219
220
|
uri = URI(joined_path)
|
220
221
|
uri.query = URI.encode_www_form(query_string_params)
|
221
|
-
uri
|
222
|
+
uri.extend(Phlex::SGML::SafeObject)
|
222
223
|
end
|
223
224
|
|
224
225
|
def url(**query_string_params)
|
225
|
-
request_context =
|
226
|
+
request_context = Brut::FrontEnd::RequestContext.current
|
226
227
|
path = self.path(**query_string_params)
|
227
228
|
host = if request_context
|
228
229
|
request_context[:host]
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# In Brut, the _front end_ is considered anything that interacts directly with a web browser or HTTP. This includes rendering HTML,
|
2
|
+
# managing JavaScript and CSS, and processing form submissions. It contrasts to {Brut::BackEnd}, which handles the business logic
|
3
|
+
# and database.
|
4
|
+
#
|
5
|
+
# You {Brut::App} defines pages, forms, and actions. A page is backed by a subclass of {Brut::FrontEnd::Page}, which provides
|
6
|
+
# dynamic data for rendering. A page can reference {Brut::FrontEnd::Component} subclasses to allow functional decomposition of front
|
7
|
+
# end logic and markup, as well as re-use. Both pages and components have ERB files that describe the HTML to be rendered.
|
8
|
+
#
|
9
|
+
# A {Brut::FrontEnd::Form} subclass defines a form that a browser will submit to your app. That
|
10
|
+
# submission is processed by a {Brut::FrontEnd::Handler} subclass. Handlers can also respond to other HTTP requests.
|
11
|
+
#
|
12
|
+
# In addition to responding to requests, you can subclass {Brut::FrontEnd::RouteHook} or {Brut::FrontEnd::Middleware} to perform
|
13
|
+
# further manipulation of the request.
|
14
|
+
#
|
15
|
+
# The entire front-end is based on Rack, so you should be able to achieve anything you need to.
|
16
|
+
module Brut::FrontEnd
|
17
|
+
autoload(:AssetMetadata, "brut/front_end/asset_metadata")
|
18
|
+
autoload(:AssetPathResolver, "brut/front_end/asset_path_resolver")
|
19
|
+
autoload(:Component, "brut/front_end/component")
|
20
|
+
autoload(:Components, "brut/front_end/component")
|
21
|
+
autoload(:Download, "brut/front_end/download")
|
22
|
+
autoload(:Flash, "brut/front_end/flash")
|
23
|
+
autoload(:Form, "brut/front_end/form")
|
24
|
+
autoload(:GenericResponse, "brut/front_end/generic_response")
|
25
|
+
autoload(:Handler, "brut/front_end/handler")
|
26
|
+
autoload(:Handlers, "brut/front_end/handler")
|
27
|
+
autoload(:HandlingResults, "brut/front_end/handling_results")
|
28
|
+
autoload(:HttpMethod, "brut/front_end/http_method")
|
29
|
+
autoload(:HttpStatus, "brut/front_end/http_status")
|
30
|
+
autoload(:InlineSvgLocator, "brut/front_end/inline_svg_locator")
|
31
|
+
autoload(:Layout, "brut/front_end/layout")
|
32
|
+
autoload(:Middleware, "brut/front_end/middleware")
|
33
|
+
autoload(:Middlewares, "brut/front_end/middleware")
|
34
|
+
autoload(:Page, "brut/front_end/page")
|
35
|
+
autoload(:Pages, "brut/front_end/page")
|
36
|
+
autoload(:RequestContext, "brut/front_end/request_context")
|
37
|
+
autoload(:RouteHook, "brut/front_end/route_hook")
|
38
|
+
autoload(:RouteHooks, "brut/front_end/route_hook")
|
39
|
+
autoload(:Routing, "brut/front_end/routing")
|
40
|
+
autoload(:Session, "brut/front_end/session")
|
41
|
+
end
|
@@ -1,6 +1,11 @@
|
|
1
|
-
# Interface for translations
|
2
|
-
#
|
3
|
-
#
|
1
|
+
# Interface for translations, preferred over Ruby's I18n classes. Note that this is a
|
2
|
+
# base module and not intended to be directly used in your classes. Include one of
|
3
|
+
# the other modules in this namespace:
|
4
|
+
#
|
5
|
+
# * {Brut::I18n::ForHTML} for components or pages, or anything use Phlex
|
6
|
+
# * {Brut::I18n::ForCLI} for CLI apps
|
7
|
+
# * {Brut::I18n::ForBackEnd} for back-end classes that aren't generating HTML
|
8
|
+
#
|
4
9
|
module Brut::I18n::BaseMethods
|
5
10
|
|
6
11
|
# Access a translation and insert interpolated elemens as needed. This will use the provided key to determine
|
@@ -101,7 +106,7 @@ module Brut::I18n::BaseMethods
|
|
101
106
|
# }
|
102
107
|
# # in your code for HomePage
|
103
108
|
# t(page: [ :captions, :new ]) # => New Widgets
|
104
|
-
def t(key=:look_in_rest,**rest)
|
109
|
+
def t(key=:look_in_rest,**rest,&block)
|
105
110
|
if key == :look_in_rest
|
106
111
|
|
107
112
|
page = rest.delete(:page)
|
@@ -126,13 +131,14 @@ module Brut::I18n::BaseMethods
|
|
126
131
|
key = Array(key).join('.')
|
127
132
|
key = [key,"general.#{key}"]
|
128
133
|
end
|
129
|
-
if
|
134
|
+
if !block.nil?
|
130
135
|
if rest[:block]
|
131
136
|
raise ArgumentError,"t was given a block and a block: param. You can't do both "
|
132
137
|
end
|
133
|
-
|
138
|
+
block_contents = safe(capture(&block))
|
139
|
+
rest[:block] = block_contents
|
134
140
|
end
|
135
|
-
|
141
|
+
t_direct(key,**rest)
|
136
142
|
rescue I18n::MissingInterpolationArgument => ex
|
137
143
|
if ex.key.to_s == "block"
|
138
144
|
raise ArgumentError,"One of the keys #{key.join(", ")} contained a %{block} interpolation value: '#{ex.string}'. This means you must use t_html *and* yield a block to it"
|
@@ -168,7 +174,7 @@ module Brut::I18n::BaseMethods
|
|
168
174
|
}
|
169
175
|
escaped_interpolated_values = interpolated_values.map { |key,value|
|
170
176
|
if value.kind_of?(String)
|
171
|
-
[ key,
|
177
|
+
[ key, CGI.escapeHTML(value) ]
|
172
178
|
else
|
173
179
|
[ key, value ]
|
174
180
|
end
|
data/lib/brut/i18n/for_cli.rb
CHANGED
data/lib/brut/i18n/for_html.rb
CHANGED
@@ -1,4 +1,12 @@
|
|
1
|
+
# I18n for components or pages, which are assumed to be Phlex components.
|
2
|
+
# To use this outside of a Phlex context, you must define these two
|
3
|
+
# methods to ensure proper HTML escaping happens:
|
4
|
+
#
|
5
|
+
# * `safe` to accept a string and return a string.
|
6
|
+
# * `capture` to accept a block and return its contents as a string.
|
1
7
|
module Brut::I18n::ForHTML
|
2
8
|
include Brut::I18n::BaseMethods
|
3
|
-
def
|
9
|
+
def t(...)
|
10
|
+
safe(super)
|
11
|
+
end
|
4
12
|
end
|
data/lib/brut/i18n.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# I18n holds all the code useful for translating and localizing information. It's based on Ruby's I18n.
|
2
2
|
module Brut::I18n
|
3
3
|
autoload(:BaseMethods, "brut/i18n/base_methods")
|
4
|
+
autoload(:ForBackEnd, "brut/i18n/for_back_end")
|
4
5
|
autoload(:ForCLI, "brut/i18n/for_cli")
|
5
6
|
autoload(:ForHTML, "brut/i18n/for_html")
|
6
7
|
autoload(:HTTPAcceptLanguage, "brut/i18n/http_accept_language")
|
data/lib/brut/sinatra_helpers.rb
CHANGED
@@ -77,15 +77,16 @@ module Brut::SinatraHelpers
|
|
77
77
|
|
78
78
|
Brut.container.instrumentation.span(page_class.name) do |span|
|
79
79
|
span.add_prefixed_attributes("brut", type: :page, class: page_class)
|
80
|
-
|
81
|
-
constructor_args = request_context.as_constructor_args(
|
80
|
+
constructor_args = Brut::FrontEnd::RequestContext.current.as_constructor_args(
|
82
81
|
page_class,
|
83
82
|
request_params: params,
|
84
83
|
route: brut_route,
|
85
84
|
)
|
86
85
|
span.add_prefixed_attributes("brut.initializer.args", constructor_args.map { |k,v| [k.to_s,v.class.name] }.to_h)
|
87
86
|
page_instance = page_class.new(**constructor_args)
|
87
|
+
|
88
88
|
result = page_instance.handle!
|
89
|
+
|
89
90
|
span.add_prefixed_attributes("brut", result_class: result.class)
|
90
91
|
case result
|
91
92
|
in URI => uri
|
@@ -177,7 +178,6 @@ module Brut::SinatraHelpers
|
|
177
178
|
form_class: form_class,
|
178
179
|
)
|
179
180
|
|
180
|
-
request_context = Thread.current.thread_variable_get(:request_context)
|
181
181
|
handler = handler_class.new
|
182
182
|
form = if form_class.nil?
|
183
183
|
nil
|
@@ -185,7 +185,7 @@ module Brut::SinatraHelpers
|
|
185
185
|
form_class.new(params: params)
|
186
186
|
end
|
187
187
|
|
188
|
-
process_args =
|
188
|
+
process_args = Brut::FrontEnd::RequestContext.current.as_method_args(handler,:handle,request_params: params,form: form,route:brut_route)
|
189
189
|
|
190
190
|
result = handler.handle!(**process_args)
|
191
191
|
|
@@ -193,16 +193,23 @@ module Brut::SinatraHelpers
|
|
193
193
|
in URI => uri
|
194
194
|
redirect to(uri.to_s)
|
195
195
|
in Brut::FrontEnd::Component => component_instance
|
196
|
-
|
197
|
-
in [
|
196
|
+
component_instance.call.to_s
|
197
|
+
in [
|
198
|
+
Brut::FrontEnd::Component => component_instance,
|
199
|
+
Brut::FrontEnd::HttpStatus => http_status,
|
200
|
+
]
|
201
|
+
|
198
202
|
[
|
199
203
|
http_status.to_i,
|
200
|
-
|
204
|
+
component_instance.call.to_s,
|
201
205
|
]
|
206
|
+
|
202
207
|
in Brut::FrontEnd::HttpStatus => http_status
|
203
208
|
http_status.to_i
|
204
209
|
in Brut::FrontEnd::Download => download
|
205
210
|
[ 200, download.headers, download.data ]
|
211
|
+
in Brut::FrontEnd::GenericResponse => response
|
212
|
+
response.to_ary
|
206
213
|
else
|
207
214
|
raise NoMatchingPatternError, "Result from #{handler.class}'s handle! method was a #{result.class}, which cannot be used to understand the response to generate"
|
208
215
|
end
|
@@ -8,7 +8,7 @@ module Brut::SpecSupport::ComponentSupport
|
|
8
8
|
include Brut::SpecSupport::FlashSupport
|
9
9
|
include Brut::SpecSupport::SessionSupport
|
10
10
|
include Brut::SpecSupport::ClockSupport
|
11
|
-
include Brut::I18n::
|
11
|
+
include Brut::I18n::BaseMethods
|
12
12
|
|
13
13
|
# Render a component into its text representation. This mimics what happens when a component is used
|
14
14
|
# inside a template. You typically don't want this, but should use {#render_and_parse}, since that will
|
@@ -20,8 +20,13 @@ module Brut::SpecSupport::ComponentSupport
|
|
20
20
|
end
|
21
21
|
component.handle!
|
22
22
|
else
|
23
|
-
|
24
|
-
|
23
|
+
if block.nil?
|
24
|
+
component.call
|
25
|
+
else
|
26
|
+
component.call do
|
27
|
+
component.raw(component.safe(block.()))
|
28
|
+
end
|
29
|
+
end
|
25
30
|
end
|
26
31
|
end
|
27
32
|
|
@@ -41,7 +46,7 @@ module Brut::SpecSupport::ComponentSupport
|
|
41
46
|
# @return [Brut::SpecSupport::EnhancedNode] a wrapper around a Nokogiri node to provide convienience methods.
|
42
47
|
def render_and_parse(component,&block)
|
43
48
|
rendered_text = render(component,&block)
|
44
|
-
if !rendered_text.kind_of?(String)
|
49
|
+
if !rendered_text.kind_of?(String)
|
45
50
|
if rendered_text.kind_of?(URI::Generic)
|
46
51
|
raise "#{component.class} redirected to #{rendered_text} instead of rendering"
|
47
52
|
else
|
@@ -80,9 +85,4 @@ module Brut::SpecSupport::ComponentSupport
|
|
80
85
|
def routing_for(klass,**args)
|
81
86
|
Brut.container.routing.path(klass,**args)
|
82
87
|
end
|
83
|
-
|
84
|
-
# Escape HTML using the same code Brut uses for rendering templates.
|
85
|
-
def escape_html(...)
|
86
|
-
Brut::FrontEnd::Templates::EscapableFilter.escape_html(...)
|
87
|
-
end
|
88
88
|
end
|
@@ -80,6 +80,7 @@ class Brut::SpecSupport::RSpecSetup
|
|
80
80
|
@config.include Brut::SpecSupport::GeneralSupport
|
81
81
|
@config.include Brut::SpecSupport::ComponentSupport, component: true
|
82
82
|
@config.include Brut::SpecSupport::HandlerSupport, handler: true
|
83
|
+
@config.include Brut::SpecSupport::E2eSupport, e2e: true
|
83
84
|
@config.include Playwright::Test::Matchers, e2e: true
|
84
85
|
|
85
86
|
@config.around do |example|
|
data/lib/brut/spec_support.rb
CHANGED
@@ -5,11 +5,12 @@ module Brut
|
|
5
5
|
module SpecSupport
|
6
6
|
end
|
7
7
|
end
|
8
|
-
require_relative "spec_support/matcher"
|
9
8
|
require_relative "spec_support/component_support"
|
10
|
-
require_relative "spec_support/
|
11
|
-
require_relative "spec_support/general_support"
|
9
|
+
require_relative "spec_support/e2e_support"
|
12
10
|
require_relative "spec_support/e2e_test_server"
|
11
|
+
require_relative "spec_support/general_support"
|
12
|
+
require_relative "spec_support/handler_support"
|
13
|
+
require_relative "spec_support/matcher"
|
13
14
|
require_relative "spec_support/rspec_setup"
|
14
15
|
require_relative "factory_bot"
|
15
16
|
# Convention here is different. We don't want to autoload
|
data/lib/brut/version.rb
CHANGED
data/lib/brut.rb
CHANGED
@@ -9,51 +9,8 @@ require_relative "brut/framework"
|
|
9
9
|
#
|
10
10
|
# Have fun!
|
11
11
|
module Brut
|
12
|
-
|
13
|
-
|
14
|
-
# and database.
|
15
|
-
#
|
16
|
-
# You {Brut::App} defines pages, forms, and actions. A page is backed by a subclass of {Brut::FrontEnd::Page}, which provides
|
17
|
-
# dynamic data for rendering. A page can reference {Brut::FrontEnd::Component} subclasses to allow functional decomposition of front
|
18
|
-
# end logic and markup, as well as re-use. Both pages and components have ERB files that describe the HTML to be rendered.
|
19
|
-
#
|
20
|
-
# A {Brut::FrontEnd::Form} subclass defines a form that a browser will submit to your app. That
|
21
|
-
# submission is processed by a {Brut::FrontEnd::Handler} subclass. Handlers can also respond to other HTTP requests.
|
22
|
-
#
|
23
|
-
# In addition to responding to requests, you can subclass {Brut::FrontEnd::RouteHook} or {Brut::FrontEnd::Middleware} to perform
|
24
|
-
# further manipulation of the request.
|
25
|
-
#
|
26
|
-
# The entire front-end is based on Rack, so you should be able to achieve anything you need to.
|
27
|
-
module FrontEnd
|
28
|
-
autoload(:AssetMetadata, "brut/front_end/asset_metadata")
|
29
|
-
autoload(:Component, "brut/front_end/component")
|
30
|
-
autoload(:Components, "brut/front_end/component")
|
31
|
-
autoload(:Download, "brut/front_end/download")
|
32
|
-
autoload(:Flash, "brut/front_end/flash")
|
33
|
-
autoload(:Form, "brut/front_end/form")
|
34
|
-
autoload(:Handler, "brut/front_end/handler")
|
35
|
-
autoload(:Handlers, "brut/front_end/handler")
|
36
|
-
autoload(:HandlingResults, "brut/front_end/handling_results")
|
37
|
-
autoload(:HttpMethod, "brut/front_end/http_method")
|
38
|
-
autoload(:HttpStatus, "brut/front_end/http_status")
|
39
|
-
autoload(:Middleware, "brut/front_end/middleware")
|
40
|
-
autoload(:Middlewares, "brut/front_end/middleware")
|
41
|
-
autoload(:Page, "brut/front_end/page")
|
42
|
-
autoload(:Pages, "brut/front_end/page")
|
43
|
-
autoload(:RequestContext, "brut/front_end/request_context")
|
44
|
-
autoload(:RouteHook, "brut/front_end/route_hook")
|
45
|
-
autoload(:RouteHooks, "brut/front_end/route_hook")
|
46
|
-
autoload(:Routing, "brut/front_end/routing")
|
47
|
-
autoload(:Session, "brut/front_end/session")
|
48
|
-
end
|
49
|
-
# The _back end_ of a Brut app is where your app's business logic and database are managed. While the bulk of your Brut app's code
|
50
|
-
# will be in the back end, Brut is far less prescriptive about how to manage that than it is the front end.
|
51
|
-
module BackEnd
|
52
|
-
autoload(:Validators, "brut/back_end/validator")
|
53
|
-
autoload(:Sidekiq, "brut/back_end/sidekiq")
|
54
|
-
# Do not put SeedData here - it must be loaded only when needed
|
55
|
-
end
|
56
|
-
# I18n is where internationalization and localization support lives.
|
12
|
+
autoload(:FrontEnd, "brut/front_end")
|
13
|
+
autoload(:BackEnd, "brut/back_end")
|
57
14
|
autoload(:I18n, "brut/i18n")
|
58
15
|
autoload(:Instrumentation,"brut/instrumentation")
|
59
16
|
autoload(:SinatraHelpers, "brut/sinatra_helpers")
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: brut
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.20
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Bryant Copeland
|
8
8
|
bindir: exe
|
9
9
|
cert_chain: []
|
10
|
-
date:
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: irb
|
@@ -80,7 +80,7 @@ dependencies:
|
|
80
80
|
- !ruby/object:Gem::Version
|
81
81
|
version: '0'
|
82
82
|
- !ruby/object:Gem::Dependency
|
83
|
-
name:
|
83
|
+
name: phlex
|
84
84
|
requirement: !ruby/object:Gem::Requirement
|
85
85
|
requirements:
|
86
86
|
- - ">="
|
@@ -94,7 +94,7 @@ dependencies:
|
|
94
94
|
- !ruby/object:Gem::Version
|
95
95
|
version: '0'
|
96
96
|
- !ruby/object:Gem::Dependency
|
97
|
-
name:
|
97
|
+
name: prism
|
98
98
|
requirement: !ruby/object:Gem::Requirement
|
99
99
|
requirements:
|
100
100
|
- - ">="
|
@@ -108,7 +108,7 @@ dependencies:
|
|
108
108
|
- !ruby/object:Gem::Version
|
109
109
|
version: '0'
|
110
110
|
- !ruby/object:Gem::Dependency
|
111
|
-
name:
|
111
|
+
name: rack-protection
|
112
112
|
requirement: !ruby/object:Gem::Requirement
|
113
113
|
requirements:
|
114
114
|
- - ">="
|
@@ -122,7 +122,7 @@ dependencies:
|
|
122
122
|
- !ruby/object:Gem::Version
|
123
123
|
version: '0'
|
124
124
|
- !ruby/object:Gem::Dependency
|
125
|
-
name:
|
125
|
+
name: rackup
|
126
126
|
requirement: !ruby/object:Gem::Requirement
|
127
127
|
requirements:
|
128
128
|
- - ">="
|
@@ -177,34 +177,6 @@ dependencies:
|
|
177
177
|
- - ">="
|
178
178
|
- !ruby/object:Gem::Version
|
179
179
|
version: '0'
|
180
|
-
- !ruby/object:Gem::Dependency
|
181
|
-
name: temple
|
182
|
-
requirement: !ruby/object:Gem::Requirement
|
183
|
-
requirements:
|
184
|
-
- - ">="
|
185
|
-
- !ruby/object:Gem::Version
|
186
|
-
version: '0'
|
187
|
-
type: :runtime
|
188
|
-
prerelease: false
|
189
|
-
version_requirements: !ruby/object:Gem::Requirement
|
190
|
-
requirements:
|
191
|
-
- - ">="
|
192
|
-
- !ruby/object:Gem::Version
|
193
|
-
version: '0'
|
194
|
-
- !ruby/object:Gem::Dependency
|
195
|
-
name: tilt
|
196
|
-
requirement: !ruby/object:Gem::Requirement
|
197
|
-
requirements:
|
198
|
-
- - ">="
|
199
|
-
- !ruby/object:Gem::Version
|
200
|
-
version: '0'
|
201
|
-
type: :runtime
|
202
|
-
prerelease: false
|
203
|
-
version_requirements: !ruby/object:Gem::Requirement
|
204
|
-
requirements:
|
205
|
-
- - ">="
|
206
|
-
- !ruby/object:Gem::Version
|
207
|
-
version: '0'
|
208
180
|
- !ruby/object:Gem::Dependency
|
209
181
|
name: tzinfo
|
210
182
|
requirement: !ruby/object:Gem::Requirement
|
@@ -454,6 +426,7 @@ files:
|
|
454
426
|
- dx/start
|
455
427
|
- dx/stop
|
456
428
|
- lib/brut.rb
|
429
|
+
- lib/brut/back_end.rb
|
457
430
|
- lib/brut/back_end/seed_data.rb
|
458
431
|
- lib/brut/back_end/sidekiq.rb
|
459
432
|
- lib/brut/back_end/sidekiq/middlewares.rb
|
@@ -491,7 +464,9 @@ files:
|
|
491
464
|
- lib/brut/framework/mcp.rb
|
492
465
|
- lib/brut/framework/patch_semantic_logger.rb
|
493
466
|
- lib/brut/framework/project_environment.rb
|
467
|
+
- lib/brut/front_end.rb
|
494
468
|
- lib/brut/front_end/asset_metadata.rb
|
469
|
+
- lib/brut/front_end/asset_path_resolver.rb
|
495
470
|
- lib/brut/front_end/component.rb
|
496
471
|
- lib/brut/front_end/components/constraint_violations.rb
|
497
472
|
- lib/brut/front_end/components/form_tag.rb
|
@@ -504,7 +479,7 @@ files:
|
|
504
479
|
- lib/brut/front_end/components/inputs/textarea.rb
|
505
480
|
- lib/brut/front_end/components/locale_detection.rb
|
506
481
|
- lib/brut/front_end/components/page_identifier.rb
|
507
|
-
- lib/brut/front_end/components/
|
482
|
+
- lib/brut/front_end/components/time_tag.rb
|
508
483
|
- lib/brut/front_end/components/traceparent.rb
|
509
484
|
- lib/brut/front_end/download.rb
|
510
485
|
- lib/brut/front_end/flash.rb
|
@@ -518,6 +493,7 @@ files:
|
|
518
493
|
- lib/brut/front_end/forms/select_input.rb
|
519
494
|
- lib/brut/front_end/forms/select_input_definition.rb
|
520
495
|
- lib/brut/front_end/forms/validity_state.rb
|
496
|
+
- lib/brut/front_end/generic_response.rb
|
521
497
|
- lib/brut/front_end/handler.rb
|
522
498
|
- lib/brut/front_end/handlers/csp_reporting_handler.rb
|
523
499
|
- lib/brut/front_end/handlers/instrumentation_handler.rb
|
@@ -526,6 +502,8 @@ files:
|
|
526
502
|
- lib/brut/front_end/handling_results.rb
|
527
503
|
- lib/brut/front_end/http_method.rb
|
528
504
|
- lib/brut/front_end/http_status.rb
|
505
|
+
- lib/brut/front_end/inline_svg_locator.rb
|
506
|
+
- lib/brut/front_end/layout.rb
|
529
507
|
- lib/brut/front_end/layouts/_internal.html.erb
|
530
508
|
- lib/brut/front_end/middleware.rb
|
531
509
|
- lib/brut/front_end/middlewares/annotate_brut_owned_paths.rb
|
@@ -544,15 +522,9 @@ files:
|
|
544
522
|
- lib/brut/front_end/route_hooks/setup_request_context.rb
|
545
523
|
- lib/brut/front_end/routing.rb
|
546
524
|
- lib/brut/front_end/session.rb
|
547
|
-
- lib/brut/front_end/template.rb
|
548
|
-
- lib/brut/front_end/templates/block_filter.rb
|
549
|
-
- lib/brut/front_end/templates/erb_engine.rb
|
550
|
-
- lib/brut/front_end/templates/erb_parser.rb
|
551
|
-
- lib/brut/front_end/templates/escapable_filter.rb
|
552
|
-
- lib/brut/front_end/templates/html_safe_string.rb
|
553
|
-
- lib/brut/front_end/templates/locator.rb
|
554
525
|
- lib/brut/i18n.rb
|
555
526
|
- lib/brut/i18n/base_methods.rb
|
527
|
+
- lib/brut/i18n/for_back_end.rb
|
556
528
|
- lib/brut/i18n/for_cli.rb
|
557
529
|
- lib/brut/i18n/for_html.rb
|
558
530
|
- lib/brut/i18n/http_accept_language.rb
|
@@ -564,6 +536,7 @@ files:
|
|
564
536
|
- lib/brut/spec_support.rb
|
565
537
|
- lib/brut/spec_support/clock_support.rb
|
566
538
|
- lib/brut/spec_support/component_support.rb
|
539
|
+
- lib/brut/spec_support/e2e_support.rb
|
567
540
|
- lib/brut/spec_support/e2e_test_server.rb
|
568
541
|
- lib/brut/spec_support/enhanced_node.rb
|
569
542
|
- lib/brut/spec_support/flash_support.rb
|
@@ -610,7 +583,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
610
583
|
- !ruby/object:Gem::Version
|
611
584
|
version: '0'
|
612
585
|
requirements: []
|
613
|
-
rubygems_version: 3.6.
|
586
|
+
rubygems_version: 3.6.7
|
614
587
|
specification_version: 4
|
615
588
|
summary: NOT YET RELEASED - Web Framework Built around Ruby, Web Standards, Simplicity,
|
616
589
|
and Object-Orientation
|