proscenium 0.15.0.beta.4-aarch64-linux → 0.15.0.beta.5-aarch64-linux
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/README.md +5 -5
- data/lib/proscenium/builder.rb +6 -4
- data/lib/proscenium/ext/proscenium +0 -0
- data/lib/proscenium/libs/custom_element.js +54 -0
- data/lib/proscenium/libs/stimulus-loading.js +33 -51
- data/lib/proscenium/libs/ujs/class.js +7 -9
- data/lib/proscenium/middleware/base.rb +1 -1
- data/lib/proscenium/middleware/engines.rb +12 -4
- data/lib/proscenium/middleware/esbuild.rb +1 -1
- data/lib/proscenium/middleware.rb +12 -3
- data/lib/proscenium/phlex/css_modules.rb +2 -2
- data/lib/proscenium/phlex/react_component.rb +2 -2
- data/lib/proscenium/railtie.rb +16 -0
- data/lib/proscenium/resolver.rb +2 -0
- data/lib/proscenium/side_load.rb +4 -4
- data/lib/proscenium/ui/breadcrumbs/component.module.css +14 -0
- data/lib/proscenium/ui/breadcrumbs/component.rb +79 -0
- data/lib/proscenium/ui/breadcrumbs/computed_element.rb +69 -0
- data/lib/proscenium/ui/breadcrumbs/control.rb +95 -0
- data/lib/proscenium/ui/breadcrumbs/mixins.css +83 -0
- data/lib/proscenium/ui/breadcrumbs.rb +72 -0
- data/lib/proscenium/ui/component.rb +11 -0
- data/lib/proscenium/ui/test.js +1 -0
- data/lib/proscenium/ui.rb +14 -0
- data/lib/proscenium/version.rb +1 -1
- data/lib/proscenium.rb +9 -0
- metadata +55 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1617ec045da7aeb75e675881fbf33d926cbac0fc9e8a859df65332439b0238e2
|
4
|
+
data.tar.gz: 3bc2b29ffe41770149e14502c814291939c524f52254f793b2ea59486eaeee19
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: df241bdca15174d8ede8d40af92929d62f3b2ac652b7bfa8582afec5533725407e987e99592b56438ae54c73b77021b845bd024428180cc682ab570437350dab
|
7
|
+
data.tar.gz: c3888dc4ee531bc6a764aff7f750db398c2f3ec4c5f55557c1380d8c75ec2559348cd0929f85c9315e3f7a5f32abe96bfc2b3c51e3e4089e32ef2be96948d82c
|
data/README.md
CHANGED
@@ -681,7 +681,7 @@ console.log(version);
|
|
681
681
|
|
682
682
|
```ruby
|
683
683
|
class MyView < Proscenium::Phlex
|
684
|
-
def
|
684
|
+
def view_template
|
685
685
|
h1 { 'Hello World' }
|
686
686
|
end
|
687
687
|
end
|
@@ -693,7 +693,7 @@ In your layouts, include `Proscenium::Phlex::AssetInclusions`, and call the `inc
|
|
693
693
|
class ApplicationLayout < Proscenium::Phlex
|
694
694
|
include Proscenium::Phlex::AssetInclusions # <--
|
695
695
|
|
696
|
-
def
|
696
|
+
def view_template(&)
|
697
697
|
doctype
|
698
698
|
html do
|
699
699
|
head do
|
@@ -721,7 +721,7 @@ Within your Phlex classes, any class names that begin with `@` will be treated a
|
|
721
721
|
```ruby
|
722
722
|
# /app/views/users/show_view.rb
|
723
723
|
class Users::ShowView < Proscenium::Phlex
|
724
|
-
def
|
724
|
+
def view_template
|
725
725
|
h1 class: :@user_name do
|
726
726
|
@user.name
|
727
727
|
end
|
@@ -750,7 +750,7 @@ You can of course continue to reference regular class names in your view, and th
|
|
750
750
|
```ruby
|
751
751
|
# /app/views/users/show_view.rb
|
752
752
|
class Users::ShowView < Proscenium::Phlex
|
753
|
-
def
|
753
|
+
def view_template
|
754
754
|
h1 class: :[@user_name, :title] do
|
755
755
|
@user.name
|
756
756
|
end
|
@@ -785,7 +785,7 @@ Any ViewComponent class that inherits `Proscenium::ViewComponent` will automatic
|
|
785
785
|
```ruby
|
786
786
|
# /app/components/user_component.rb
|
787
787
|
class UserComponent < Proscenium::ViewComponent
|
788
|
-
def
|
788
|
+
def view_template
|
789
789
|
div.h1 @user.name, class: css_module(:user_name)
|
790
790
|
end
|
791
791
|
end
|
data/lib/proscenium/builder.rb
CHANGED
@@ -71,7 +71,7 @@ module Proscenium
|
|
71
71
|
msg << " at #{location['file']}:#{location['line']}:#{location['column']}"
|
72
72
|
end
|
73
73
|
|
74
|
-
super
|
74
|
+
super(msg)
|
75
75
|
end
|
76
76
|
end
|
77
77
|
|
@@ -79,7 +79,7 @@ module Proscenium
|
|
79
79
|
attr_reader :error_msg, :path
|
80
80
|
|
81
81
|
def initialize(path, error_msg)
|
82
|
-
super
|
82
|
+
super("Failed to resolve '#{path}' -- #{error_msg}")
|
83
83
|
end
|
84
84
|
end
|
85
85
|
|
@@ -100,7 +100,7 @@ module Proscenium
|
|
100
100
|
@base_url = base_url
|
101
101
|
end
|
102
102
|
|
103
|
-
def build_to_path(path)
|
103
|
+
def build_to_path(path)
|
104
104
|
ActiveSupport::Notifications.instrument('build_to_path.proscenium',
|
105
105
|
identifier: path,
|
106
106
|
cached: Proscenium.cache.exist?(path)) do
|
@@ -163,7 +163,9 @@ module Proscenium
|
|
163
163
|
end
|
164
164
|
|
165
165
|
def engines
|
166
|
-
Proscenium.config.engines.to_h { |e| [e.engine_name, e.root.to_s] }
|
166
|
+
Proscenium.config.engines.to_h { |e| [e.engine_name, e.root.to_s] }.tap do |x|
|
167
|
+
x['proscenium/ui'] = Proscenium.ui_path.to_s
|
168
|
+
end
|
167
169
|
end
|
168
170
|
|
169
171
|
def import_map
|
Binary file
|
@@ -0,0 +1,54 @@
|
|
1
|
+
/**
|
2
|
+
* Base class for custom elements, providing support for event delegation, and idempotent
|
3
|
+
* customElement registration.
|
4
|
+
*
|
5
|
+
* The `handleEvent` method is called any time an event defined in `delegatedEvents` is triggered.
|
6
|
+
* It's a central handler to handle events for this custom element.
|
7
|
+
*
|
8
|
+
* @example
|
9
|
+
* class MyComponent extends CustomElement {
|
10
|
+
* static componentName = 'my-component'
|
11
|
+
* static delegatedEvents = ['click']
|
12
|
+
*
|
13
|
+
* handleEvent(event) {
|
14
|
+
* console.log('Hello, world!')
|
15
|
+
* }
|
16
|
+
* }
|
17
|
+
* MyComponent.register()
|
18
|
+
*/
|
19
|
+
export default class CustomElement extends HTMLElement {
|
20
|
+
/**
|
21
|
+
* Register the component as a custom element, inferring the component name from the kebab-cased
|
22
|
+
* class name. You can override the component name by setting a static `componentName` property.
|
23
|
+
*
|
24
|
+
* This method is idempotent.
|
25
|
+
*/
|
26
|
+
static register() {
|
27
|
+
if (this.componentName === undefined) {
|
28
|
+
this.componentName = this.name
|
29
|
+
.replaceAll(/(.)([A-Z])/g, "$1-$2")
|
30
|
+
.toLowerCase();
|
31
|
+
}
|
32
|
+
|
33
|
+
if (!customElements.get(this.componentName)) {
|
34
|
+
customElements.define(this.componentName, this);
|
35
|
+
}
|
36
|
+
}
|
37
|
+
|
38
|
+
/**
|
39
|
+
* A list of event types to be delegated for the lifetime of the custom element.
|
40
|
+
*
|
41
|
+
* @type {Array}
|
42
|
+
*/
|
43
|
+
static delegatedEvents = [];
|
44
|
+
|
45
|
+
constructor() {
|
46
|
+
super();
|
47
|
+
|
48
|
+
if (typeof this.handleEvent !== "undefined") {
|
49
|
+
this.constructor.delegatedEvents?.forEach((event) => {
|
50
|
+
this.addEventListener(event, this);
|
51
|
+
});
|
52
|
+
}
|
53
|
+
}
|
54
|
+
}
|
@@ -1,22 +1,9 @@
|
|
1
|
-
|
2
|
-
const
|
1
|
+
export function lazyLoadControllersFrom(under, app, element = document) {
|
2
|
+
const { controllerAttribute } = app.schema;
|
3
3
|
|
4
|
-
|
5
|
-
under,
|
6
|
-
application,
|
7
|
-
element = document
|
8
|
-
) {
|
9
|
-
lazyLoadExistingControllers(under, application, element);
|
10
|
-
lazyLoadNewControllers(under, application, element);
|
11
|
-
}
|
12
|
-
|
13
|
-
function lazyLoadExistingControllers(under, application, element) {
|
14
|
-
queryControllerNamesWithin(element).forEach((controllerName) =>
|
15
|
-
loadController(controllerName, under, application)
|
16
|
-
);
|
17
|
-
}
|
4
|
+
lazyLoadExistingControllers(element);
|
18
5
|
|
19
|
-
|
6
|
+
// Lazy load new controllers.
|
20
7
|
new MutationObserver((mutationsList) => {
|
21
8
|
for (const { attributeName, target, type } of mutationsList) {
|
22
9
|
switch (type) {
|
@@ -26,13 +13,13 @@ function lazyLoadNewControllers(under, application, element) {
|
|
26
13
|
target.getAttribute(controllerAttribute)
|
27
14
|
) {
|
28
15
|
extractControllerNamesFrom(target).forEach((controllerName) =>
|
29
|
-
loadController(controllerName
|
16
|
+
loadController(controllerName)
|
30
17
|
);
|
31
18
|
}
|
32
19
|
}
|
33
20
|
|
34
21
|
case "childList": {
|
35
|
-
lazyLoadExistingControllers(
|
22
|
+
lazyLoadExistingControllers(target);
|
36
23
|
}
|
37
24
|
}
|
38
25
|
}
|
@@ -41,43 +28,38 @@ function lazyLoadNewControllers(under, application, element) {
|
|
41
28
|
subtree: true,
|
42
29
|
childList: true,
|
43
30
|
});
|
44
|
-
}
|
45
31
|
|
46
|
-
function
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
function extractControllerNamesFrom(element) {
|
53
|
-
return element
|
54
|
-
.getAttribute(controllerAttribute)
|
55
|
-
.split(/\s+/)
|
56
|
-
.filter((content) => content.length);
|
57
|
-
}
|
32
|
+
function lazyLoadExistingControllers(element) {
|
33
|
+
Array.from(element.querySelectorAll(`[${controllerAttribute}]`))
|
34
|
+
.map(extractControllerNamesFrom)
|
35
|
+
.flat()
|
36
|
+
.forEach(loadController);
|
37
|
+
}
|
58
38
|
|
59
|
-
function
|
60
|
-
|
61
|
-
|
62
|
-
.
|
63
|
-
.
|
64
|
-
console.error(`Failed to autoload controller: ${name}`, error)
|
65
|
-
);
|
39
|
+
function extractControllerNamesFrom(element) {
|
40
|
+
return element
|
41
|
+
.getAttribute(controllerAttribute)
|
42
|
+
.split(/\s+/)
|
43
|
+
.filter((content) => content.length);
|
66
44
|
}
|
67
|
-
}
|
68
45
|
|
69
|
-
function
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
}
|
46
|
+
function loadController(name) {
|
47
|
+
if (canRegisterController(name)) {
|
48
|
+
const fileToImport = `${under}/${name
|
49
|
+
.replace(/--/g, "/")
|
50
|
+
.replace(/-/g, "_")}_controller.js`;
|
74
51
|
|
75
|
-
|
76
|
-
|
77
|
-
|
52
|
+
import(fileToImport)
|
53
|
+
.then((module) => {
|
54
|
+
canRegisterController(name) && app.register(name, module.default);
|
55
|
+
})
|
56
|
+
.catch((error) =>
|
57
|
+
console.error(`Failed to autoload controller: ${name}`, error)
|
58
|
+
);
|
59
|
+
}
|
78
60
|
}
|
79
|
-
}
|
80
61
|
|
81
|
-
function canRegisterController(name
|
82
|
-
|
62
|
+
function canRegisterController(name) {
|
63
|
+
return !app.router.modulesByIdentifier.has(name);
|
64
|
+
}
|
83
65
|
}
|
@@ -3,15 +3,13 @@ import DataDisableWith from "./data_disable_with";
|
|
3
3
|
|
4
4
|
export default class UJS {
|
5
5
|
constructor() {
|
6
|
-
|
7
|
-
|
6
|
+
this.dc = new DataConfirm();
|
7
|
+
this.ddw = new DataDisableWith();
|
8
8
|
|
9
|
-
document.
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
{ capture: true }
|
15
|
-
);
|
9
|
+
document.addEventListener("submit", this, { capture: true });
|
10
|
+
}
|
11
|
+
|
12
|
+
handleEvent(event) {
|
13
|
+
this.dc.onSubmit(event) && this.ddw.onSubmit(event);
|
16
14
|
}
|
17
15
|
}
|
@@ -20,18 +20,26 @@ module Proscenium
|
|
20
20
|
#
|
21
21
|
class Engines < Esbuild
|
22
22
|
def real_path
|
23
|
-
@real_path ||= Pathname.new(@request.path.delete_prefix("/#{
|
23
|
+
@real_path ||= Pathname.new(@request.path.delete_prefix("/#{engine_name}")).to_s
|
24
24
|
end
|
25
25
|
|
26
26
|
def root_for_readable
|
27
|
-
engine.root
|
27
|
+
ui? ? Proscenium.ui_path : engine.root
|
28
28
|
end
|
29
29
|
|
30
30
|
def engine
|
31
|
-
@engine ||= Proscenium.config.engines.find do |
|
32
|
-
@request.path.start_with?("/#{
|
31
|
+
@engine ||= Proscenium.config.engines.find do |x|
|
32
|
+
@request.path.start_with?("/#{x.engine_name}")
|
33
33
|
end
|
34
34
|
end
|
35
|
+
|
36
|
+
def engine_name
|
37
|
+
ui? ? 'proscenium/ui' : engine.engine_name
|
38
|
+
end
|
39
|
+
|
40
|
+
def ui?
|
41
|
+
@request.path.start_with?('/proscenium/ui/')
|
42
|
+
end
|
35
43
|
end
|
36
44
|
end
|
37
45
|
end
|
@@ -45,17 +45,26 @@ module Proscenium
|
|
45
45
|
return Runtime if request.path.match?(%r{^/@proscenium/})
|
46
46
|
return Esbuild if Pathname.new(request.path).fnmatch?(app_path_glob, File::FNM_EXTGLOB)
|
47
47
|
|
48
|
-
|
48
|
+
pathname = Pathname.new(request.path)
|
49
|
+
Engines if pathname.fnmatch?(ui_path_glob, File::FNM_EXTGLOB) ||
|
50
|
+
pathname.fnmatch?(engines_path_glob, File::FNM_EXTGLOB)
|
49
51
|
end
|
50
52
|
|
51
53
|
def app_path_glob
|
52
|
-
"/{#{Proscenium::ALLOWED_DIRECTORIES}}/**.{#{
|
54
|
+
"/{#{Proscenium::ALLOWED_DIRECTORIES}}/**.{#{file_extensions}}"
|
53
55
|
end
|
54
56
|
|
55
57
|
def engines_path_glob
|
56
58
|
names = Proscenium.config.engines.map(&:engine_name)
|
59
|
+
"/{#{names.join(',')}}/{#{Proscenium::ALLOWED_DIRECTORIES}}/**.{#{file_extensions}}"
|
60
|
+
end
|
61
|
+
|
62
|
+
def ui_path_glob
|
63
|
+
"/proscenium/ui/**.{#{file_extensions}}"
|
64
|
+
end
|
57
65
|
|
58
|
-
|
66
|
+
def file_extensions
|
67
|
+
@file_extensions ||= FILE_EXTENSIONS.join(',')
|
59
68
|
end
|
60
69
|
|
61
70
|
# TODO: handle precompiled assets
|
@@ -40,7 +40,7 @@ module Proscenium
|
|
40
40
|
#
|
41
41
|
# # app/components/user/component.rb
|
42
42
|
# class User::Component < Proscenium::Phlex
|
43
|
-
# def
|
43
|
+
# def view_template
|
44
44
|
# div class: :@user_name do
|
45
45
|
# 'Joel Moss'
|
46
46
|
# end
|
@@ -54,7 +54,7 @@ module Proscenium
|
|
54
54
|
# add the CSS Module name `name` to the <div>.
|
55
55
|
#
|
56
56
|
# class User::Component < Proscenium::Phlex
|
57
|
-
# def
|
57
|
+
# def view_template
|
58
58
|
# div class: '/lib/users@name' do
|
59
59
|
# 'Joel Moss'
|
60
60
|
# end
|
@@ -18,14 +18,14 @@ module Proscenium
|
|
18
18
|
# Override this to provide your own loading UI.
|
19
19
|
#
|
20
20
|
# @example
|
21
|
-
# def
|
21
|
+
# def view_template(**attributes, &block)
|
22
22
|
# super do
|
23
23
|
# 'Look at me! I am loading now...'
|
24
24
|
# end
|
25
25
|
# end
|
26
26
|
#
|
27
27
|
# @yield the given block to a `div` within the top level component div.
|
28
|
-
def
|
28
|
+
def view_template(**attributes, &block)
|
29
29
|
send root_tag, **{ data: data_attributes }.deep_merge(attributes), &block
|
30
30
|
end
|
31
31
|
end
|
data/lib/proscenium/railtie.rb
CHANGED
@@ -49,6 +49,12 @@ module Proscenium
|
|
49
49
|
end
|
50
50
|
end
|
51
51
|
|
52
|
+
initializer 'proscenium.ui' do
|
53
|
+
ActiveSupport::Inflector.inflections(:en) do |inflect|
|
54
|
+
inflect.acronym 'UI'
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
52
58
|
initializer 'proscenium.debugging' do
|
53
59
|
if Rails.gem_version >= Gem::Version.new('7.1.0')
|
54
60
|
tpl_path = root.join('lib', 'proscenium', 'templates').to_s
|
@@ -75,6 +81,16 @@ module Proscenium
|
|
75
81
|
ActionView::PartialRenderer.prepend Monkey::PartialRenderer
|
76
82
|
end
|
77
83
|
end
|
84
|
+
|
85
|
+
initializer 'proscenium.public_path' do |app|
|
86
|
+
if app.config.public_file_server.enabled
|
87
|
+
headers = app.config.public_file_server.headers || {}
|
88
|
+
index = app.config.public_file_server.index_name || 'index'
|
89
|
+
|
90
|
+
app.middleware.insert_after(ActionDispatch::Static, ActionDispatch::Static,
|
91
|
+
root.join('public').to_s, index: index, headers: headers)
|
92
|
+
end
|
93
|
+
end
|
78
94
|
end
|
79
95
|
end
|
80
96
|
|
data/lib/proscenium/resolver.rb
CHANGED
@@ -23,6 +23,8 @@ module Proscenium
|
|
23
23
|
|
24
24
|
if path.start_with?('@proscenium/')
|
25
25
|
"/#{path}"
|
26
|
+
elsif path.start_with?(Proscenium.ui_path.to_s)
|
27
|
+
path.delete_prefix Proscenium.root.join('lib').to_s
|
26
28
|
elsif (engine = Proscenium.config.engines.find { |e| path.start_with? "#{e.root}/" })
|
27
29
|
path.sub(/^#{engine.root}/, "/#{engine.engine_name}")
|
28
30
|
elsif path.start_with?("#{Rails.root}/")
|
data/lib/proscenium/side_load.rb
CHANGED
@@ -10,7 +10,7 @@ module Proscenium
|
|
10
10
|
|
11
11
|
append_after_action :capture_and_replace_proscenium_stylesheets,
|
12
12
|
:capture_and_replace_proscenium_javascripts,
|
13
|
-
if: -> {
|
13
|
+
if: -> { response.content_type&.include?('html') }
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
@@ -20,7 +20,7 @@ module Proscenium
|
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
|
-
def capture_and_replace_proscenium_stylesheets
|
23
|
+
def capture_and_replace_proscenium_stylesheets
|
24
24
|
return if response_body.nil?
|
25
25
|
return if response_body.first.blank? || !Proscenium::Importer.css_imported?
|
26
26
|
return unless response_body.first.include? '<!-- [PROSCENIUM_STYLESHEETS] -->'
|
@@ -52,7 +52,7 @@ module Proscenium
|
|
52
52
|
response_body.first.gsub! '<!-- [PROSCENIUM_STYLESHEETS] -->', out.join.html_safe
|
53
53
|
end
|
54
54
|
|
55
|
-
def capture_and_replace_proscenium_javascripts
|
55
|
+
def capture_and_replace_proscenium_javascripts
|
56
56
|
return if response_body.nil?
|
57
57
|
return if response_body.first.blank? || !Proscenium::Importer.js_imported?
|
58
58
|
|
@@ -108,7 +108,7 @@ module Proscenium
|
|
108
108
|
#
|
109
109
|
# If the class responds to `.sideload`, it will be called instead of the regular side loading.
|
110
110
|
# You can use this to customise what is side loaded.
|
111
|
-
def sideload_inheritance_chain(obj, options)
|
111
|
+
def sideload_inheritance_chain(obj, options)
|
112
112
|
return unless Proscenium.config.side_load
|
113
113
|
|
114
114
|
options = {} if options.nil?
|
@@ -0,0 +1,14 @@
|
|
1
|
+
@layer proscenium-ui-component {
|
2
|
+
/*
|
3
|
+
* Custom properties:
|
4
|
+
*
|
5
|
+
* --puiBreadcrumbs--link-color: LinkText;
|
6
|
+
* --puiBreadcrumbs--link-hover-color: HighlightText;
|
7
|
+
* --puiBreadcrumbs--separator-color: GrayText;
|
8
|
+
* --puiBreadcrumbs--separator: url("/proscenium/icons/angle-right-regular.svg");
|
9
|
+
*/
|
10
|
+
|
11
|
+
.base {
|
12
|
+
@mixin breadcrumbs from url("./mixins.css");
|
13
|
+
}
|
14
|
+
}
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Proscenium::UI
|
4
|
+
class Breadcrumbs::Component < Component
|
5
|
+
include Phlex::Rails::Helpers::URLFor
|
6
|
+
|
7
|
+
# The path (route) to use as the HREF for the home segment. Defaults to `:root`.
|
8
|
+
option :home_path, Types::String | Types::Symbol, default: -> { :root }
|
9
|
+
|
10
|
+
# Assign false to hide the home segment.
|
11
|
+
option :with_home, Types::Bool, default: -> { true }
|
12
|
+
|
13
|
+
# One or more class name(s) for the base div element which will be appended to the default.
|
14
|
+
option :class, Types::Coercible::String | Types::Array.of(Types::Coercible::String),
|
15
|
+
as: :class_name, default: -> { [] }
|
16
|
+
|
17
|
+
# One or more class name(s) for the base div element which will replace the default. If both
|
18
|
+
# `class` and `class!` are provided, all values will be merged. Defaults to `:@base`.
|
19
|
+
option :class!, Types::Coercible::String | Types::Array.of(Types::Coercible::String),
|
20
|
+
as: :class_name_override, default: -> { :@base }
|
21
|
+
|
22
|
+
def view_template
|
23
|
+
div class: [*class_name_override, *class_name] do
|
24
|
+
ol do
|
25
|
+
if with_home
|
26
|
+
li do
|
27
|
+
home_template
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
breadcrumbs.each do |ce|
|
32
|
+
li do
|
33
|
+
path = ce.path
|
34
|
+
path.nil? ? ce.name : a(href: url_for(path)) { ce.name }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
# Override this to customise the home breadcrumb. You can call super with a block to use the
|
44
|
+
# default template, but with custom content.
|
45
|
+
#
|
46
|
+
# @example
|
47
|
+
# def home_template
|
48
|
+
# super { 'hello' }
|
49
|
+
# end
|
50
|
+
def home_template(&block)
|
51
|
+
a(href: url_for(home_path)) do
|
52
|
+
if block
|
53
|
+
yield
|
54
|
+
else
|
55
|
+
svg role: 'img', xmlns: 'http://www.w3.org/2000/svg', viewBox: '0 0 576 512' do |s|
|
56
|
+
s.path fill: 'currentColor',
|
57
|
+
d: 'M488 312.7V456c0 13.3-10.7 24-24 24H348c-6.6 0-12-5.4-12-12V356c0-6.6-5.4-' \
|
58
|
+
'12-12-12h-72c-6.6 0-12 5.4-12 12v112c0 6.6-5.4 12-12 12H112c-13.3 0-24-10.' \
|
59
|
+
'7-24-24V312.7c0-3.6 1.6-7 4.4-9.3l188-154.8c4.4-3.6 10.8-3.6 15.3 0l188 15' \
|
60
|
+
'4.8c2.7 2.3 4.3 5.7 4.3 9.3zm83.6-60.9L488 182.9V44.4c0-6.6-5.4-12-12-12h-' \
|
61
|
+
'56c-6.6 0-12 5.4-12 12V117l-89.5-73.7c-17.7-14.6-43.3-14.6-61 0L4.4 251.8c' \
|
62
|
+
'-5.1 4.2-5.8 11.8-1.6 16.9l25.5 31c4.2 5.1 11.8 5.8 16.9 1.6l235.2-193.7c4' \
|
63
|
+
'.4-3.6 10.8-3.6 15.3 0l235.2 193.7c5.1 4.2 12.7 3.5 16.9-1.6l25.5-31c4.2-5' \
|
64
|
+
'.2 3.4-12.7-1.7-16.9z'
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
# Don't render if @hide_breadcrumbs is true.
|
71
|
+
def render?
|
72
|
+
helpers.assigns['hide_breadcrumbs'] != true
|
73
|
+
end
|
74
|
+
|
75
|
+
def breadcrumbs
|
76
|
+
helpers.controller.breadcrumbs.map { |e| Breadcrumbs::ComputedElement.new e, helpers }
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Proscenium::UI::Breadcrumbs
|
4
|
+
class ComputedElement
|
5
|
+
def initialize(element, context)
|
6
|
+
@element = element
|
7
|
+
@context = context
|
8
|
+
end
|
9
|
+
|
10
|
+
# If name is a Symbol of a controller method, that method is called.
|
11
|
+
# If name is a Symbol of a controller instance variable, that variable is returned.
|
12
|
+
# If name is a Proc, it is executed in the context of the controller instance.
|
13
|
+
#
|
14
|
+
# @return [String] the content of the breadcrumb element.
|
15
|
+
def name
|
16
|
+
@name ||= case name = @element.name
|
17
|
+
when Symbol
|
18
|
+
if name.to_s.starts_with?('@')
|
19
|
+
name = get_instance_variable(name)
|
20
|
+
name.respond_to?(:for_breadcrumb) ? name.for_breadcrumb : name.to_s
|
21
|
+
else
|
22
|
+
res = @context.controller.send(name)
|
23
|
+
res.try(:for_breadcrumb) || res.to_s
|
24
|
+
end
|
25
|
+
when Proc
|
26
|
+
@context.controller.instance_exec(&name)
|
27
|
+
else
|
28
|
+
name.respond_to?(:for_breadcrumb) ? name.for_breadcrumb : name.to_s
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# If path is a Symbol of a controller method, that method is called.
|
33
|
+
# If path is a Symbol of a controller instance variable, that variable is returned.
|
34
|
+
# If path is an Array, each element is processed as above.
|
35
|
+
# If path is a Proc, it is executed in the context of the controller instance.
|
36
|
+
#
|
37
|
+
# No matter what, the result is always passed to `url_for` before being returned.
|
38
|
+
#
|
39
|
+
# @return [String] the URL for the element
|
40
|
+
def path
|
41
|
+
@path ||= unless @element.path.nil?
|
42
|
+
case path = @element.path
|
43
|
+
when Array
|
44
|
+
path.map! { |x| x.to_s.starts_with?('@') ? get_instance_variable(x) : x }
|
45
|
+
when Symbol
|
46
|
+
if path.to_s.starts_with?('@')
|
47
|
+
path = get_instance_variable(path)
|
48
|
+
elsif @context.controller.respond_to?(path, true)
|
49
|
+
path = @context.controller.send(path)
|
50
|
+
end
|
51
|
+
when Proc
|
52
|
+
path = @context.controller.instance_exec(&path)
|
53
|
+
end
|
54
|
+
|
55
|
+
@context.url_for path
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
def get_instance_variable(element)
|
62
|
+
unless @context.instance_variable_defined?(element)
|
63
|
+
raise NameError, "undefined instance variable `#{element}' for breadcrumb", caller
|
64
|
+
end
|
65
|
+
|
66
|
+
@context.instance_variable_get element
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Proscenium::UI::Breadcrumbs
|
4
|
+
# Include this module in your controller to add support for adding breadcrumb elements. You can
|
5
|
+
# then use the `add_breadcrumb` and `prepend_breadcrumb` class methods to append and/or prepend
|
6
|
+
# breadcrumb elements.
|
7
|
+
module Control
|
8
|
+
extend ActiveSupport::Concern
|
9
|
+
include ActionView::Helpers::SanitizeHelper
|
10
|
+
|
11
|
+
included do
|
12
|
+
helper_method :breadcrumbs_as_json, :breadcrumbs_for_title if respond_to?(:helper_method)
|
13
|
+
end
|
14
|
+
|
15
|
+
module ClassMethods
|
16
|
+
# Appends a new breadcrumb element into the collection.
|
17
|
+
#
|
18
|
+
# @param name [String, Symbol, Proc, #for_breadcrumb] The name or content of the breadcrumb.
|
19
|
+
# @param path [String, Symbol, Array, Proc, nil] The path (route) to use as the HREF for the
|
20
|
+
# breadcrumb.
|
21
|
+
# @param filter_options [Hash] Options to pass through to the before_action filter.
|
22
|
+
def add_breadcrumb(name, path = nil, **filter_options)
|
23
|
+
element_options = filter_options.delete(:options) || {}
|
24
|
+
|
25
|
+
before_action(filter_options) do |controller|
|
26
|
+
controller.send :add_breadcrumb, name, path, element_options
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# Prepend a new breadcrumb element into the collection.
|
31
|
+
#
|
32
|
+
# @param name [String, Symbol, Proc, #for_breadcrumb] The name or content of the breadcrumb.
|
33
|
+
# @param path [String, Symbol, Array, Proc, nil] The path (route) to use as the HREF for the
|
34
|
+
# breadcrumb.
|
35
|
+
# @param filter_options [Hash] Options to pass through to the before_action filter.
|
36
|
+
def prepend_breadcrumb(name, path = nil, **filter_options)
|
37
|
+
element_options = filter_options.delete(:options) || {}
|
38
|
+
|
39
|
+
before_action(filter_options) do |controller|
|
40
|
+
controller.send :prepend_breadcrumb, name, path, element_options
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# Pushes a new breadcrumb element into the collection.
|
46
|
+
#
|
47
|
+
# @param name [String, Symbol, Proc, #for_breadcrumb] The name or content of the breadcrumb.
|
48
|
+
# @param path [String, Symbol, Array, Proc, nil] The path (route) to use as the HREF for the
|
49
|
+
# breadcrumb.
|
50
|
+
# @param options [Hash]
|
51
|
+
def add_breadcrumb(name, path = nil, options = {})
|
52
|
+
breadcrumbs << Element.new(name, path, options)
|
53
|
+
end
|
54
|
+
|
55
|
+
# Prepend a new breadcrumb element into the collection.
|
56
|
+
#
|
57
|
+
# @param name [String, Symbol, Proc, #for_breadcrumb] The name or content of the breadcrumb.
|
58
|
+
# @param path [String, Symbol, Array, Proc, nil] The path (route) to use as the HREF for the
|
59
|
+
# breadcrumb.
|
60
|
+
# @param options [Hash]
|
61
|
+
def prepend_breadcrumb(name, path = nil, options = {})
|
62
|
+
breadcrumbs.prepend Element.new(name, path, options)
|
63
|
+
end
|
64
|
+
|
65
|
+
def breadcrumbs
|
66
|
+
@breadcrumbs ||= []
|
67
|
+
end
|
68
|
+
|
69
|
+
def breadcrumbs_as_json
|
70
|
+
computed_breadcrumbs.map do |ele|
|
71
|
+
path = ele.path
|
72
|
+
|
73
|
+
{ name: ele.name, path: ele.path.nil? || helpers.current_page?(path) ? nil : path }
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# @param primary [Boolean] whether to return only the primary breadcrumb.
|
78
|
+
def breadcrumbs_for_title(primary: false)
|
79
|
+
names = computed_breadcrumbs.map(&:name)
|
80
|
+
return names.pop if primary
|
81
|
+
|
82
|
+
out = [names.pop]
|
83
|
+
out << names.join(': ') unless names.empty?
|
84
|
+
strip_tags out.join(' - ')
|
85
|
+
end
|
86
|
+
|
87
|
+
private
|
88
|
+
|
89
|
+
def computed_breadcrumbs
|
90
|
+
@computed_breadcrumbs ||= breadcrumbs.map do |ele|
|
91
|
+
ComputedElement.new ele, helpers
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
@define-mixin breadcrumbs {
|
2
|
+
/* Default properties */
|
3
|
+
--_puiBreadcrumbs--separator-color: GrayText;
|
4
|
+
--_puiBreadcrumbs--separator: url("/proscenium/icons/angle-right-regular.svg");
|
5
|
+
|
6
|
+
margin: 10px;
|
7
|
+
|
8
|
+
ol {
|
9
|
+
list-style: none;
|
10
|
+
padding: 0;
|
11
|
+
margin: 0;
|
12
|
+
display: flex;
|
13
|
+
align-items: baseline;
|
14
|
+
|
15
|
+
li {
|
16
|
+
text-transform: uppercase;
|
17
|
+
display: flex;
|
18
|
+
align-items: center;
|
19
|
+
|
20
|
+
@media (max-width: 426px) {
|
21
|
+
&:not(:nth-last-child(2)) {
|
22
|
+
display: none;
|
23
|
+
}
|
24
|
+
|
25
|
+
&:nth-last-child(2)::before {
|
26
|
+
@mixin _separator;
|
27
|
+
margin: 0 0.5rem 0 0;
|
28
|
+
transform: rotate(180deg);
|
29
|
+
}
|
30
|
+
}
|
31
|
+
|
32
|
+
@media (min-width: 427px) {
|
33
|
+
&:not(:last-child)::after {
|
34
|
+
@mixin _separator;
|
35
|
+
margin: 0 0.5rem;
|
36
|
+
}
|
37
|
+
}
|
38
|
+
|
39
|
+
&:last-child {
|
40
|
+
font-weight: 500;
|
41
|
+
text-transform: none;
|
42
|
+
}
|
43
|
+
|
44
|
+
&:last-child > a {
|
45
|
+
font-weight: 500;
|
46
|
+
text-transform: none;
|
47
|
+
}
|
48
|
+
|
49
|
+
a {
|
50
|
+
color: var(--puiBreadcrumbs--link-color, revert);
|
51
|
+
display: flex;
|
52
|
+
|
53
|
+
&:hover {
|
54
|
+
color: var(--puiBreadcrumbs--link-hover-color, revert);
|
55
|
+
}
|
56
|
+
}
|
57
|
+
|
58
|
+
svg {
|
59
|
+
height: 1em;
|
60
|
+
width: 1em;
|
61
|
+
}
|
62
|
+
}
|
63
|
+
}
|
64
|
+
}
|
65
|
+
|
66
|
+
@define-mixin _separator {
|
67
|
+
display: inline-block;
|
68
|
+
content: "";
|
69
|
+
height: 1rem;
|
70
|
+
width: 1rem;
|
71
|
+
-webkit-mask: var(
|
72
|
+
--puiBreadcrumbs--separator,
|
73
|
+
var(--_puiBreadcrumbs--separator)
|
74
|
+
)
|
75
|
+
no-repeat center center;
|
76
|
+
mask: var(--puiBreadcrumbs--separator, var(--_puiBreadcrumbs--separator))
|
77
|
+
no-repeat center center;
|
78
|
+
vertical-align: sub;
|
79
|
+
background-color: var(
|
80
|
+
--puiBreadcrumbs--separator-color,
|
81
|
+
var(--_puiBreadcrumbs--separator-color)
|
82
|
+
);
|
83
|
+
}
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Proscenium::UI
|
4
|
+
# Provides breadcrumb functionality for controllers and views. Breadcrumbs are a type of
|
5
|
+
# navigation that show the user where they are in the application's hierarchy.
|
6
|
+
# The `Proscenium::UI::Breadcrumbs::Control` module provides the `add_breadcrumb` and
|
7
|
+
# `prepend_breadcrumb` class methods for adding breadcrumb elements, and is intended to be
|
8
|
+
# included in your controllers.
|
9
|
+
#
|
10
|
+
# The `add_breadcrumb` method adds a new breadcrumb element to the end of the collection, while
|
11
|
+
# the `prepend_breadcrumb` method adds a new breadcrumb element to the beginning of the
|
12
|
+
# collection. Both methods take a name, and path as arguments. The name argument is the name or
|
13
|
+
# content of the breadcrumb, while the path argument is the path (route) to use as the HREF for
|
14
|
+
# the breadcrumb.
|
15
|
+
#
|
16
|
+
# class UsersController < ApplicationController
|
17
|
+
# include Proscenium::UI::Breadcrumbs::Control
|
18
|
+
# add_breadcrumb 'Users', :users_path
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# Display the breadcrumbs in your views with the breadcrumbs component.
|
22
|
+
# @see `Proscenium::UI::Breadcrumbs::Component`.
|
23
|
+
#
|
24
|
+
# At it's simplest, you can add a breadcrumb with a name of "User", and a path of "/users" like
|
25
|
+
# this:
|
26
|
+
#
|
27
|
+
# add_breadcrumb 'Foo', '/foo'
|
28
|
+
#
|
29
|
+
# The value of the path is always passed to `url_for` before being rendered. It is also optional,
|
30
|
+
# and if omitted, the breadcrumb will be rendered as plain text.
|
31
|
+
#
|
32
|
+
# Both name and path can be given a Symbol, which can be used to call a method of the same name on
|
33
|
+
# the controller. If a Symbol is given as the path, and no method of the same name exists, then
|
34
|
+
# `url_for` will be called with the Symbol as the argument. Likewise, if an Array is given as the
|
35
|
+
# path, then `url_for` will be called with the Array as the argument.
|
36
|
+
#
|
37
|
+
# If a Symbol is given as the path or name, and it begins with `@` (eg. `:@foo`), then the
|
38
|
+
# instance variable of the same name will be called.
|
39
|
+
#
|
40
|
+
# add_breadcrumb :@foo, :@bar
|
41
|
+
#
|
42
|
+
# A Proc can also be given as the name and/or path. The Proc will be called within the context of
|
43
|
+
# the controller.
|
44
|
+
#
|
45
|
+
# add_breadcrumb -> { @foo }, -> { @bar }
|
46
|
+
#
|
47
|
+
# Passing an object that responds to `#for_breadcrumb` as the name will call that method on the
|
48
|
+
# object to get the breadcrumb name.
|
49
|
+
#
|
50
|
+
module Breadcrumbs
|
51
|
+
extend ActiveSupport::Autoload
|
52
|
+
|
53
|
+
autoload :Control
|
54
|
+
autoload :ComputedElement
|
55
|
+
autoload :Component
|
56
|
+
|
57
|
+
# Represents a navigation element in the breadcrumb collection.
|
58
|
+
class Element
|
59
|
+
attr_accessor :name, :path, :options
|
60
|
+
|
61
|
+
# @param name [String] the element/link name
|
62
|
+
# @param path [String] the element/link URL
|
63
|
+
# @param options [Hash] the element/link options
|
64
|
+
# @return [Element]
|
65
|
+
def initialize(name, path = nil, options = {})
|
66
|
+
self.name = name
|
67
|
+
self.path = path
|
68
|
+
self.options = options
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
console.log("/proscenium/ui/test.js");
|
data/lib/proscenium/version.rb
CHANGED
data/lib/proscenium.rb
CHANGED
@@ -27,6 +27,7 @@ module Proscenium
|
|
27
27
|
autoload :Builder
|
28
28
|
autoload :Importer
|
29
29
|
autoload :Resolver
|
30
|
+
autoload :UI
|
30
31
|
|
31
32
|
class Deprecator
|
32
33
|
def deprecation_warning(name, message, _caller_backtrace = nil)
|
@@ -55,6 +56,14 @@ module Proscenium
|
|
55
56
|
def cache
|
56
57
|
@cache ||= config.cache || ActiveSupport::Cache::NullStore.new
|
57
58
|
end
|
59
|
+
|
60
|
+
def ui_path
|
61
|
+
Railtie.root.join('lib', 'proscenium', 'ui')
|
62
|
+
end
|
63
|
+
|
64
|
+
def root
|
65
|
+
Railtie.root
|
66
|
+
end
|
58
67
|
end
|
59
68
|
end
|
60
69
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: proscenium
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.15.0.beta.
|
4
|
+
version: 0.15.0.beta.5
|
5
5
|
platform: aarch64-linux
|
6
6
|
authors:
|
7
7
|
- Joel Moss
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-04-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -30,6 +30,34 @@ dependencies:
|
|
30
30
|
- - "<"
|
31
31
|
- !ruby/object:Gem::Version
|
32
32
|
version: '8.0'
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: dry-initializer
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '3.1'
|
40
|
+
type: :runtime
|
41
|
+
prerelease: false
|
42
|
+
version_requirements: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - "~>"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '3.1'
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: dry-types
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - "~>"
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '1.7'
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - "~>"
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '1.7'
|
33
61
|
- !ruby/object:Gem::Dependency
|
34
62
|
name: ffi
|
35
63
|
requirement: !ruby/object:Gem::Requirement
|
@@ -58,6 +86,20 @@ dependencies:
|
|
58
86
|
- - "~>"
|
59
87
|
- !ruby/object:Gem::Version
|
60
88
|
version: '3.13'
|
89
|
+
- !ruby/object:Gem::Dependency
|
90
|
+
name: phlex-rails
|
91
|
+
requirement: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - "~>"
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: 1.2.1
|
96
|
+
type: :runtime
|
97
|
+
prerelease: false
|
98
|
+
version_requirements: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - "~>"
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: 1.2.1
|
61
103
|
- !ruby/object:Gem::Dependency
|
62
104
|
name: railties
|
63
105
|
requirement: !ruby/object:Gem::Requirement
|
@@ -114,6 +156,7 @@ files:
|
|
114
156
|
- lib/proscenium/ext/proscenium.h
|
115
157
|
- lib/proscenium/helper.rb
|
116
158
|
- lib/proscenium/importer.rb
|
159
|
+
- lib/proscenium/libs/custom_element.js
|
117
160
|
- lib/proscenium/libs/react-manager/index.jsx
|
118
161
|
- lib/proscenium/libs/react-manager/react.js
|
119
162
|
- lib/proscenium/libs/stimulus-loading.js
|
@@ -140,6 +183,15 @@ files:
|
|
140
183
|
- lib/proscenium/side_load.rb
|
141
184
|
- lib/proscenium/source_path.rb
|
142
185
|
- lib/proscenium/templates/rescues/build_error.html.erb
|
186
|
+
- lib/proscenium/ui.rb
|
187
|
+
- lib/proscenium/ui/breadcrumbs.rb
|
188
|
+
- lib/proscenium/ui/breadcrumbs/component.module.css
|
189
|
+
- lib/proscenium/ui/breadcrumbs/component.rb
|
190
|
+
- lib/proscenium/ui/breadcrumbs/computed_element.rb
|
191
|
+
- lib/proscenium/ui/breadcrumbs/control.rb
|
192
|
+
- lib/proscenium/ui/breadcrumbs/mixins.css
|
193
|
+
- lib/proscenium/ui/component.rb
|
194
|
+
- lib/proscenium/ui/test.js
|
143
195
|
- lib/proscenium/utils.rb
|
144
196
|
- lib/proscenium/version.rb
|
145
197
|
- lib/proscenium/view_component.rb
|
@@ -169,7 +221,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
169
221
|
- !ruby/object:Gem::Version
|
170
222
|
version: '0'
|
171
223
|
requirements: []
|
172
|
-
rubygems_version: 3.5.
|
224
|
+
rubygems_version: 3.5.7
|
173
225
|
signing_key:
|
174
226
|
specification_version: 4
|
175
227
|
summary: The engine powering your Rails frontend
|