brut 0.0.7 → 0.0.8

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 37f9d27495d7269447632af6383a1f4e3f24f98bbfcc1838d1a118c09005815f
4
- data.tar.gz: ef05ae07379e79cef2914b16567b5d57856cb402c152e823ce658b4bc4cb8a69
3
+ metadata.gz: 9fcc1f1288e34fb2c9a4c5a5e7fbc879ab9a4d56abbbaf1e8e3f3f5456cf38ad
4
+ data.tar.gz: c8a659fdb48e8a36f74d34daa60a1e96d0a799828372c28fa5888e2e135ab3ac
5
5
  SHA512:
6
- metadata.gz: ba995eb4d298f52064d3866eb7712a8cdf62e92e2e1415fb5545a8f8a8e59c3861da28861175c0b83df8b71428a235404b5170e188faab9f1c2ab18d6e3dfc73
7
- data.tar.gz: 2a4ccedddbc0c8ab977124e40a59f12aaae21e7ba140dd7580a709ae17c8de8b8da49d59db473f8270baf8a34c30e36c96e1d937d6b6ce63bec08a6d88e385a3
6
+ metadata.gz: f1297609ba764ce576b69d1d493466e005ff1e759464cb4e1025856311508f34dbb7abbb474a097de87a1c65ea4ddeab022c36221a41b0c763e88832512ba1d2
7
+ data.tar.gz: d30fde661e26d6f0df839b5609264eb71cb34339e5609c610f590d6c82ebd25890daf22cfaf140349b1dea8d0862e8ce1a4a319b2bad5e35a9ba9abe7f87ddc7
data/Dockerfile.dx CHANGED
@@ -2,7 +2,7 @@ FROM ruby:3.3
2
2
 
3
3
  SHELL [ "/bin/bash", "-o", "pipefail", "-c" ]
4
4
 
5
- ENV DEBIAN_FRONTEND noninteractive
5
+ ENV DEBIAN_FRONTEND=noninteractive
6
6
 
7
7
  # These packages are needed to set up other repos to install other
8
8
  # packages and/or are useful in installing other software
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- brut (0.0.7)
4
+ brut (0.0.8)
5
5
  concurrent-ruby
6
6
  i18n
7
7
  irb
@@ -52,8 +52,10 @@ class Brut::FrontEnd::Component
52
52
  end
53
53
  end
54
54
 
55
- # Allows helpers that create components to pass the block they were given to the component
56
- attr_writer :yielded_block
55
+ # Allows helpers that create components to pass the block they were given to the component.
56
+ # This can be read for the purposes of nested components passing a yielded block to an inner
57
+ # component
58
+ attr_accessor :yielded_block
57
59
 
58
60
  # Intended to be called by subclasses to render the yielded block wherever it makes sense in their markup.
59
61
  def render_yielded_block
@@ -184,11 +186,12 @@ class Brut::FrontEnd::Component
184
186
  end
185
187
 
186
188
  # Render the {Brut::FrontEnd::Components::ConstraintViolations} component for the given form's input.
187
- def constraint_violations(form:, input_name:, message_html_attributes: {}, **html_attributes)
189
+ def constraint_violations(form:, input_name:, index: nil, message_html_attributes: {}, **html_attributes)
188
190
  component(
189
191
  Brut::FrontEnd::Components::ConstraintViolations.new(
190
192
  form:,
191
193
  input_name:,
194
+ index:,
192
195
  message_html_attributes:,
193
196
  **html_attributes
194
197
  )
@@ -7,8 +7,7 @@ module Brut::FrontEnd::HandlingResults
7
7
  # @param [Class] klass A page or handler class whose route should be redirected-to. Note that if parameters are required, they must
8
8
  # be provided in `query_string_params` or this will raise an error. Note that the class must be for a GET route, since you cannot
9
9
  # redirect to a non-GET.
10
- # @param [Hash] query_string_params arguments and parameters for the route. Any values that correspond to route parameters will be
11
- # used to build the route. Remaining will be used as query parameters.
10
+ # @param [Hash] query_string_params arguments and parameters for the route. Any values that correspond to route parameters will be used to build the route. A value of 'anchor' will be used as the hash/anchor part of the URL and should not contain a hash sign. Remaining will be used as query parameters.
12
11
  #
13
12
  # @raise [ArgumentError] if `klass` is not a `Class` or if `klass` is not for a `GET`
14
13
  # @raise [Brut::Framework::Errors::MissingParameter] if any required route parameters were not provided
@@ -19,6 +19,9 @@ class Brut::FrontEnd::Page < Brut::FrontEnd::Component
19
19
  # 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
20
  # must have a layout. If you wish to render a page with no layout, create an empty layout in your app and use that.
21
21
  #
22
+ # Note that the layout can be dynamic. It is requested when {#render} is called, so you can override this
23
+ # method and use any ivar set in your constructor to change what layout is used.
24
+ #
22
25
  # @return [String] The name of the layout. May not be `nil`.
23
26
  def layout = "default"
24
27
 
@@ -13,6 +13,8 @@ class Brut::FrontEnd::RouteHooks::CSPNoInlineScripts < Brut::FrontEnd::RouteHook
13
13
  private
14
14
 
15
15
  def header_value
16
+ x = "sha256-d21f9b773d3cfad25f041a96ab08376e944e9ad4843f2060ecbdbefb12d91b1d"
17
+ x = "sha256-0h+bdz08+tJfBBqWqwg3bpROmtSEPyBg7L2++xLZGx0="
16
18
  [
17
19
  "default-src 'self'",
18
20
  "script-src-elem 'self'",
@@ -8,6 +8,12 @@ class Brut::FrontEnd::RouteHooks::CSPNoInlineStylesOrScripts < Brut::FrontEnd::R
8
8
  continue
9
9
  end
10
10
 
11
+ # TODO: A way for app to pass in stuff to modify this in part.
12
+ # In particular a hash for a <style>, calculated as follows:
13
+ # - textContent is sha265'ed
14
+ # - that is Base64'ed
15
+ # - that is put as 'sha256–«base64edvalue»` into the directive
16
+
11
17
  # Sets content security policy headers that only report the use inline scripts and inline styles, but do allow them.
12
18
  # This is useful for existing apps where you want to migrate to a more secure policy, but cannot.
13
19
  # @see Brut::FrontEnd::Handlers::CspReportingHandler
@@ -26,6 +32,8 @@ class Brut::FrontEnd::RouteHooks::CSPNoInlineStylesOrScripts < Brut::FrontEnd::R
26
32
  private
27
33
 
28
34
  def header_value
35
+ x = "sha256-d21f9b773d3cfad25f041a96ab08376e944e9ad4843f2060ecbdbefb12d91b1d"
36
+ x = "sha256-0h+bdz08+tJfBBqWqwg3bpROmtSEPyBg7L2++xLZGx0="
29
37
  [
30
38
  "default-src 'self'",
31
39
  "script-src-elem 'self'",
@@ -139,9 +139,6 @@ class Brut::FrontEnd::Routing
139
139
 
140
140
  def add_routing_method(route)
141
141
  handler_class = route.handler_class
142
- if handler_class.respond_to?(:routing) && handler_class.method(:routing).owner != Brut::FrontEnd::Form
143
- raise ArgumentError,"#{handler_class} (that handles path #{route.path_template}) got it's ::routing method from #{handler_class.method(:routing).owner}, meaning it has overridden the value fro Brut::FrontEnd::Form"
144
- end
145
142
  form_class = route.respond_to?(:form_class) ? route.form_class : nil
146
143
  [ handler_class, form_class ].compact.each do |klass|
147
144
  klass.class_eval do
@@ -180,6 +177,7 @@ class Brut::FrontEnd::Routing
180
177
  end
181
178
 
182
179
  def path(**query_string_params)
180
+ anchor = query_string_params.delete(:anchor) || query_string_params.delete("anchor")
183
181
  path = @path_template.split(/\//).map { |path_part|
184
182
  if path_part =~ /^:(.+)$/
185
183
  param_name = $1.to_sym
@@ -199,6 +197,9 @@ class Brut::FrontEnd::Routing
199
197
  if joined_path == ""
200
198
  joined_path = "/"
201
199
  end
200
+ if anchor
201
+ joined_path = joined_path + "#" + URI.encode_uri_component(anchor)
202
+ end
202
203
  uri = URI(joined_path)
203
204
  uri.query = URI.encode_www_form(query_string_params)
204
205
  uri
@@ -42,7 +42,11 @@ module Brut::SpecSupport::ComponentSupport
42
42
  def render_and_parse(component,&block)
43
43
  rendered_text = render(component,&block)
44
44
  if !rendered_text.kind_of?(String) && !rendered_text.kind_of?(Brut::FrontEnd::Templates::HTMLSafeString)
45
- raise "#{component.class} returned a #{rendered_text.class} - you should not attempt to parse this. Instead, call render(component)"
45
+ if rendered_text.kind_of?(URI::Generic)
46
+ raise "#{component.class} redirected to #{rendered_text} instead of rendering"
47
+ else
48
+ raise "#{component.class} returned a #{rendered_text.class} - you should not attempt to parse this. Instead, call render(component)"
49
+ end
46
50
  end
47
51
  nokogiri_node = Nokogiri::HTML5(rendered_text)
48
52
  if !component.kind_of?(Brut::FrontEnd::Page)
@@ -65,7 +69,11 @@ module Brut::SpecSupport::ComponentSupport
65
69
  end
66
70
  nokogiri_node = non_blank_text_elements[0]
67
71
  end
68
- Brut::SpecSupport::EnhancedNode.new(nokogiri_node)
72
+ if nokogiri_node
73
+ Brut::SpecSupport::EnhancedNode.new(nokogiri_node)
74
+ else
75
+ nil
76
+ end
69
77
  end
70
78
 
71
79
  # @!visibility private
@@ -12,7 +12,12 @@ class Brut::SpecSupport::EnhancedNode < SimpleDelegator
12
12
  element = css(css_selector)
13
13
  if (element.kind_of?(Nokogiri::XML::NodeSet))
14
14
  expect(element.length).to be < 2
15
- return Brut::SpecSupport::EnhancedNode.new(element.first)
15
+ first_element = element.first
16
+ if first_element
17
+ return Brut::SpecSupport::EnhancedNode.new(first_element)
18
+ else
19
+ return nil
20
+ end
16
21
  else
17
22
  expect([Nokogiri::XML::Node, Nokogiri::XML::Element]).to include(element.class)
18
23
  return Brut::SpecSupport::EnhancedNode.new(element)
@@ -37,6 +42,7 @@ class Brut::SpecSupport::EnhancedNode < SimpleDelegator
37
42
  def first!(css_selector)
38
43
  element = css(css_selector)
39
44
  if (element.kind_of?(Nokogiri::XML::NodeSet))
45
+ expect(element.first).not_to eq(nil), "No elements matching #{css_selector}"
40
46
  return Brut::SpecSupport::EnhancedNode.new(element.first)
41
47
  else
42
48
  expect([Nokogiri::XML::Node, Nokogiri::XML::Element]).to include(element.class)
data/lib/brut/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  module Brut
2
2
  # @!visibility private
3
- VERSION = "0.0.7"
3
+ VERSION = "0.0.8"
4
4
  end
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.7
4
+ version: 0.0.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Bryant Copeland
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2025-03-02 00:00:00.000000000 Z
10
+ date: 2025-03-15 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: irb
@@ -605,7 +605,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
605
605
  - !ruby/object:Gem::Version
606
606
  version: '0'
607
607
  requirements: []
608
- rubygems_version: 3.6.4
608
+ rubygems_version: 3.6.6
609
609
  specification_version: 4
610
610
  summary: NOT YET RELEASED - Web Framework Built around Ruby, Web Standards, Simplicity,
611
611
  and Object-Orientation