scarpe 0.4.0 → 0.5.0
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/.cursor/rules/commit-style-preferences.mdc +72 -0
- data/.cursor/rules/component_context.mdc +82 -0
- data/.cursor/rules/debug-failed-tests.mdc +100 -0
- data/.cursor/rules/display_service_context.mdc +80 -0
- data/.cursor/rules/event_handling_context.mdc +100 -0
- data/.cursor/rules/git-pager-handling.mdc +64 -0
- data/.cursor/rules/lacci-context.mdc +52 -0
- data/.cursor/rules/scarpe_design_context.mdc +46 -0
- data/.cursor/rules/shoes_compatibility_context.mdc +75 -0
- data/.cursor/rules/timeout_context.mdc +78 -0
- data/.cursor/rules/update_lacci_and_wv.mdc +8 -0
- data/.cursor/rules/what_is_scarpe.mdc +22 -0
- data/.cursor/rules/writing-new-rules.mdc +73 -0
- data/CHANGELOG.md +10 -1
- data/CLAUDE.md +223 -0
- data/Gemfile +0 -1
- data/Gemfile.lock +78 -58
- data/README.md +4 -7
- data/Rakefile +17 -25
- data/docs/SCARPE_FEATURES.md +38 -0
- data/docs/_config.yml +13 -0
- data/docs/calzini_components_and_updates.md +78 -0
- data/docs/display_service_separation.md +39 -0
- data/docs/documentation.md +43 -0
- data/docs/event_loops.md +66 -0
- data/docs/image.png +0 -0
- data/docs/index.md +118 -0
- data/docs/lacci.md +121 -0
- data/docs/scarpe_shoes_incompatibilities.md +71 -0
- data/docs/shoes_and_display_events.md +55 -0
- data/docs/shoes_implementations.md +79 -0
- data/docs/static/manual.md +5 -0
- data/docs/static/scarpe-logo.png +0 -0
- data/docs/timeouts_and_handlers.md +66 -0
- data/docs/web_archaeology.md +76 -0
- data/examples/background_with_image.rb +14 -5
- data/examples/bloopsaphone/working/feepogram.rb +1 -1
- data/examples/bloopsaphone/working/le_dance_des_rubis.rb +135 -0
- data/examples/bloopsaphone/working/pixel_dreams_in_ruby.rb +131 -0
- data/examples/bloopsaphone/working/type_rebellion.rb +157 -0
- data/examples/border.rb +1 -1
- data/examples/internal_link_navigation.rb +19 -0
- data/examples/page_navigation_single_app.rb +42 -0
- data/examples/shoes_subclass_app.rb +25 -0
- data/examples/url_routing_example.rb +67 -0
- data/lacci/Gemfile +0 -2
- data/lacci/Gemfile.lock +4 -32
- data/lacci/lacci.gemspec +1 -1
- data/lacci/lib/lacci/version.rb +1 -1
- data/lacci/lib/scarpe/niente/app.rb +12 -1
- data/lacci/lib/scarpe/niente/shoes_spec.rb +4 -5
- data/lacci/lib/scarpe/niente.rb +1 -0
- data/lacci/lib/shoes/app.rb +166 -61
- data/lacci/lib/shoes/constants.rb +1 -0
- data/lacci/lib/shoes/drawable.rb +35 -19
- data/lacci/lib/shoes/drawables/arc.rb +2 -2
- data/lacci/lib/shoes/drawables/arrow.rb +2 -2
- data/lacci/lib/shoes/drawables/border.rb +1 -1
- data/lacci/lib/shoes/drawables/button.rb +1 -1
- data/lacci/lib/shoes/drawables/edit_line.rb +1 -1
- data/lacci/lib/shoes/drawables/flow.rb +1 -1
- data/lacci/lib/shoes/drawables/line.rb +2 -2
- data/lacci/lib/shoes/drawables/link.rb +11 -1
- data/lacci/lib/shoes/drawables/oval.rb +2 -2
- data/lacci/lib/shoes/drawables/rect.rb +2 -2
- data/lacci/lib/shoes/drawables/shape.rb +2 -2
- data/lacci/lib/shoes/drawables/slot.rb +5 -3
- data/lacci/lib/shoes/drawables/stack.rb +1 -1
- data/lacci/lib/shoes/drawables/star.rb +1 -1
- data/lacci/lib/shoes/drawables/widget.rb +1 -1
- data/lacci/lib/shoes.rb +94 -17
- data/lacci/test/test_margin_helper.rb +1 -1
- data/lacci/test/test_niente_test_infra.rb +14 -0
- data/lacci/test/test_shoes_errors.rb +15 -13
- data/lib/scarpe/assets.rb +2 -1
- data/lib/scarpe/shoes_spec.rb +2 -1
- data/lib/scarpe/version.rb +1 -1
- data/lib/scarpe/wv/edit_line.rb +2 -2
- data/lib/scarpe/wv.rb +8 -1
- data/scarpe-components/Gemfile +0 -2
- data/scarpe-components/Gemfile.lock +4 -34
- data/scarpe-components/lib/scarpe/components/calzini/misc.rb +10 -2
- data/scarpe-components/lib/scarpe/components/calzini/para.rb +6 -1
- data/scarpe-components/lib/scarpe/components/calzini/slots.rb +2 -0
- data/scarpe-components/lib/scarpe/components/port_helpers.rb +30 -0
- data/scarpe-components/lib/scarpe/components/version.rb +1 -1
- data/scarpe-components/scarpe-components.gemspec +1 -1
- data/scarpe-components/test/test_port_helpers.rb +12 -0
- metadata +60 -22
- data/.rubocop.yml +0 -94
|
@@ -62,8 +62,10 @@ class Shoes::Slot < Shoes::Drawable
|
|
|
62
62
|
# Look up the Shoes drawable and create it. But first set
|
|
63
63
|
# this slot as the current one so that draw context
|
|
64
64
|
# is handled properly.
|
|
65
|
-
|
|
66
|
-
|
|
65
|
+
@app.with_slot(self) do
|
|
66
|
+
Shoes::Drawable.with_current_app(self.app) do
|
|
67
|
+
instance = klass.new(*args, **kwargs, &block)
|
|
68
|
+
end
|
|
67
69
|
end
|
|
68
70
|
|
|
69
71
|
instance
|
|
@@ -173,6 +175,6 @@ class Shoes::Slot < Shoes::Drawable
|
|
|
173
175
|
raise(Shoes::Errors::InvalidAttributeValueError, "append requires a block!") unless block_given?
|
|
174
176
|
raise(Shoes::Errors::InvalidAttributeValueError, "Don't append to something that isn't a slot!") unless self.is_a?(Shoes::Slot)
|
|
175
177
|
|
|
176
|
-
|
|
178
|
+
@app.with_slot(self, &block)
|
|
177
179
|
end
|
|
178
180
|
end
|
|
@@ -15,7 +15,7 @@ class Shoes
|
|
|
15
15
|
|
|
16
16
|
# Create the display-side drawable *before* running the block.
|
|
17
17
|
# Then child drawables have a parent to add themselves to.
|
|
18
|
-
|
|
18
|
+
@app.with_slot(self, &block) if block_given?
|
|
19
19
|
end
|
|
20
20
|
end
|
|
21
21
|
end
|
|
@@ -67,7 +67,7 @@ class Shoes::Widget < Shoes::Slot
|
|
|
67
67
|
__widget_initialize(*args, **kwargs, &block)
|
|
68
68
|
|
|
69
69
|
# Do Widgets do this?
|
|
70
|
-
|
|
70
|
+
@app.with_slot(self, &block) if block
|
|
71
71
|
end
|
|
72
72
|
@midway_through_adding_initialize = false
|
|
73
73
|
end
|
data/lacci/lib/shoes.rb
CHANGED
|
@@ -7,47 +7,47 @@
|
|
|
7
7
|
# to handle the DSL and command-line parts of Shoes without knowing anything about how the
|
|
8
8
|
# display side works at all.
|
|
9
9
|
|
|
10
|
-
if RUBY_VERSION[0..2] <
|
|
11
|
-
Shoes::Log.logger(
|
|
10
|
+
if RUBY_VERSION[0..2] < '3.2'
|
|
11
|
+
Shoes::Log.logger('Shoes').error('Lacci (Scarpe, Shoes) requires Ruby 3.2 or higher!')
|
|
12
12
|
exit(-1)
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
class Shoes; end
|
|
16
16
|
class Shoes::Error < StandardError; end
|
|
17
|
-
require_relative
|
|
17
|
+
require_relative 'shoes/errors'
|
|
18
18
|
|
|
19
|
-
require_relative
|
|
20
|
-
require_relative
|
|
19
|
+
require_relative 'shoes/constants'
|
|
20
|
+
require_relative 'shoes/ruby_extensions'
|
|
21
21
|
|
|
22
22
|
# Shoes adds some top-level methods and constants that can be used everywhere. Kernel is where they go.
|
|
23
23
|
module Kernel
|
|
24
24
|
include Shoes::Constants
|
|
25
25
|
end
|
|
26
26
|
|
|
27
|
-
require_relative
|
|
27
|
+
require_relative 'shoes/display_service'
|
|
28
28
|
|
|
29
29
|
# Pre-declare classes that get referenced outside their own require file
|
|
30
30
|
class Shoes::Drawable < Shoes::Linkable; end
|
|
31
31
|
class Shoes::Slot < Shoes::Drawable; end
|
|
32
32
|
class Shoes::Widget < Shoes::Slot; end
|
|
33
33
|
|
|
34
|
-
require_relative
|
|
35
|
-
require_relative
|
|
34
|
+
require_relative 'shoes/log'
|
|
35
|
+
require_relative 'shoes/colors'
|
|
36
36
|
|
|
37
|
-
require_relative
|
|
37
|
+
require_relative 'shoes/builtins'
|
|
38
38
|
|
|
39
|
-
require_relative
|
|
39
|
+
require_relative 'shoes/background'
|
|
40
40
|
|
|
41
|
-
require_relative
|
|
42
|
-
require_relative
|
|
43
|
-
require_relative
|
|
41
|
+
require_relative 'shoes/drawable'
|
|
42
|
+
require_relative 'shoes/app'
|
|
43
|
+
require_relative 'shoes/drawables'
|
|
44
44
|
|
|
45
|
-
require_relative
|
|
45
|
+
require_relative 'shoes/download'
|
|
46
46
|
|
|
47
47
|
# No easy way to tell at this point whether
|
|
48
48
|
# we will later load Shoes-Spec code, e.g.
|
|
49
49
|
# by running a segmented app with test code.
|
|
50
|
-
require_relative
|
|
50
|
+
require_relative 'shoes-spec'
|
|
51
51
|
|
|
52
52
|
# The module containing Shoes in all its glory.
|
|
53
53
|
# Shoes is a platform-independent GUI library, designed to create
|
|
@@ -55,6 +55,40 @@ require_relative "shoes-spec"
|
|
|
55
55
|
#
|
|
56
56
|
class Shoes
|
|
57
57
|
class << self
|
|
58
|
+
attr_accessor :APPS
|
|
59
|
+
|
|
60
|
+
# Track the most recently defined Shoes subclass for the inheritance pattern
|
|
61
|
+
# e.g., class Book < Shoes; end; Shoes.app
|
|
62
|
+
attr_accessor :pending_app_class
|
|
63
|
+
|
|
64
|
+
# When someone does `class MyApp < Shoes`, track it
|
|
65
|
+
def inherited(subclass)
|
|
66
|
+
# Only track direct subclasses of Shoes, not Shoes::App, Shoes::Drawable, etc.
|
|
67
|
+
# Those have their own inheritance tracking
|
|
68
|
+
if self == ::Shoes
|
|
69
|
+
Shoes.pending_app_class = subclass
|
|
70
|
+
end
|
|
71
|
+
super
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Class-level url method for defining routes in Shoes subclasses
|
|
75
|
+
# e.g., class Book < Shoes; url '/', :index; end
|
|
76
|
+
def url(path, method_name)
|
|
77
|
+
@class_routes ||= {}
|
|
78
|
+
if path.is_a?(String) && path.include?('(')
|
|
79
|
+
# Convert string patterns like '/page/(\d+)' to regex
|
|
80
|
+
regex = Regexp.new("^#{path.gsub(/\(.*?\)/, '(.*?)')}$")
|
|
81
|
+
@class_routes[regex] = method_name
|
|
82
|
+
else
|
|
83
|
+
@class_routes[path] = method_name
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# Get the routes defined on this class
|
|
88
|
+
def class_routes
|
|
89
|
+
@class_routes ||= {}
|
|
90
|
+
end
|
|
91
|
+
|
|
58
92
|
# Creates a Shoes app with a new window. The block parameter is used to create
|
|
59
93
|
# drawables and set up handlers. Arguments are passed to Shoes::App.new internally.
|
|
60
94
|
#
|
|
@@ -78,7 +112,7 @@ class Shoes
|
|
|
78
112
|
# @return [void]
|
|
79
113
|
# @see Shoes::App#new
|
|
80
114
|
def app(
|
|
81
|
-
title:
|
|
115
|
+
title: 'Shoes!',
|
|
82
116
|
width: 480,
|
|
83
117
|
height: 420,
|
|
84
118
|
resizable: true,
|
|
@@ -87,6 +121,47 @@ class Shoes
|
|
|
87
121
|
)
|
|
88
122
|
f = [features].flatten # Make sure this is a list, not a single symbol
|
|
89
123
|
app = Shoes::App.new(title:, width:, height:, resizable:, features: f, &app_code_body)
|
|
124
|
+
|
|
125
|
+
# If there's a pending Shoes subclass (e.g., class Book < Shoes), use it
|
|
126
|
+
if Shoes.pending_app_class
|
|
127
|
+
subclass = Shoes.pending_app_class
|
|
128
|
+
Shoes.pending_app_class = nil # Clear it so it doesn't affect future apps
|
|
129
|
+
|
|
130
|
+
# Include the subclass as a module to get its instance methods
|
|
131
|
+
# This works because we're extending the singleton class
|
|
132
|
+
methods_to_copy = subclass.instance_methods(false)
|
|
133
|
+
|
|
134
|
+
methods_to_copy.each do |method_name|
|
|
135
|
+
# Get source location and use eval to redefine - but that's fragile
|
|
136
|
+
# Instead, let's use a delegation pattern with the app as context
|
|
137
|
+
|
|
138
|
+
# Read the method's arity and create a proper wrapper
|
|
139
|
+
um = subclass.instance_method(method_name)
|
|
140
|
+
|
|
141
|
+
# Define a wrapper that will eval the original method body in app's context
|
|
142
|
+
# This is a bit hacky but works: we store the subclass and call via instance_eval
|
|
143
|
+
app.define_singleton_method(method_name) do |*args, &block|
|
|
144
|
+
# Create a temporary subclass instance that delegates to app for Shoes methods
|
|
145
|
+
temp = subclass.allocate
|
|
146
|
+
temp.instance_variable_set(:@__shoes_app__, self)
|
|
147
|
+
|
|
148
|
+
# Define method_missing on the temp to delegate Shoes DSL calls to the app
|
|
149
|
+
temp.define_singleton_method(:method_missing) do |name, *a, **kw, &b|
|
|
150
|
+
@__shoes_app__.send(name, *a, **kw, &b)
|
|
151
|
+
end
|
|
152
|
+
temp.define_singleton_method(:respond_to_missing?) { |*| true }
|
|
153
|
+
|
|
154
|
+
# Call the original method on temp (which delegates DSL calls to app)
|
|
155
|
+
temp.send(method_name, *args, &block)
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
# Copy routes from the subclass to the app
|
|
160
|
+
subclass.class_routes.each do |path, method_name|
|
|
161
|
+
app.url(path, method_name)
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
|
|
90
165
|
app.init
|
|
91
166
|
app.run
|
|
92
167
|
nil
|
|
@@ -125,7 +200,7 @@ class Shoes
|
|
|
125
200
|
proc do |path|
|
|
126
201
|
load path
|
|
127
202
|
true
|
|
128
|
-
end
|
|
203
|
+
end
|
|
129
204
|
]
|
|
130
205
|
end
|
|
131
206
|
|
|
@@ -145,4 +220,6 @@ class Shoes
|
|
|
145
220
|
@file_loaders = loaders
|
|
146
221
|
end
|
|
147
222
|
end
|
|
223
|
+
|
|
224
|
+
Shoes.APPS ||= []
|
|
148
225
|
end
|
|
@@ -23,4 +23,18 @@ class TestNienteTestInfra < NienteTest
|
|
|
23
23
|
raise "ERROR!"
|
|
24
24
|
SHOES_SPEC
|
|
25
25
|
end
|
|
26
|
+
|
|
27
|
+
def test_multi_app_find
|
|
28
|
+
run_test_niente_code(<<~SHOES_APP, app_test_code: <<~SHOES_SPEC)
|
|
29
|
+
Shoes.app do
|
|
30
|
+
@b = button "OK"
|
|
31
|
+
end
|
|
32
|
+
Shoes.app do
|
|
33
|
+
@b2 = button "Nope"
|
|
34
|
+
end
|
|
35
|
+
SHOES_APP
|
|
36
|
+
assert_equal "OK", button("@b").text
|
|
37
|
+
assert_equal "Nope", button("@b2").text
|
|
38
|
+
SHOES_SPEC
|
|
39
|
+
end
|
|
26
40
|
end
|
|
@@ -17,19 +17,21 @@ class TestShoesErrors < NienteTest
|
|
|
17
17
|
SHOES_SPEC
|
|
18
18
|
end
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
end
|
|
20
|
+
# Niente can no longer test the TooManyInstancesError because it now
|
|
21
|
+
# supports multiple Shoes apps.
|
|
22
|
+
#def test_too_many_instances_error
|
|
23
|
+
# run_test_niente_code(<<~SHOES_APP, app_test_code: <<~SHOES_SPEC)
|
|
24
|
+
# $ruby_main = self
|
|
25
|
+
# Shoes.app do
|
|
26
|
+
# end
|
|
27
|
+
# SHOES_APP
|
|
28
|
+
# assert_raises Shoes::Errors::TooManyInstancesError do
|
|
29
|
+
# $ruby_main.instance_eval do
|
|
30
|
+
# Shoes.app {}
|
|
31
|
+
# end
|
|
32
|
+
# end
|
|
33
|
+
# SHOES_SPEC
|
|
34
|
+
#end
|
|
33
35
|
|
|
34
36
|
def test_drawables_found_errors
|
|
35
37
|
run_test_niente_code(<<~SHOES_APP, app_test_code: <<~SHOES_SPEC)
|
data/lib/scarpe/assets.rb
CHANGED
|
@@ -6,7 +6,8 @@ module Scarpe::Webview
|
|
|
6
6
|
def self.asset_server
|
|
7
7
|
return @asset_server if @asset_server
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
# A Scarpe Webview application can have only a single Shoes::App instance.
|
|
10
|
+
@asset_server = Scarpe::Components::AssetServer.new app_dir: Shoes.APPS[0].dir
|
|
10
11
|
|
|
11
12
|
# at_exit doesn't work reliably under webview. Give this a try.
|
|
12
13
|
::Scarpe::Webview::DisplayService.instance.control_interface.on_event(:shutdown) do
|
data/lib/scarpe/shoes_spec.rb
CHANGED
|
@@ -107,7 +107,8 @@ module Scarpe::ShoesSpecTest
|
|
|
107
107
|
finder_name = drawable_class.dsl_name
|
|
108
108
|
|
|
109
109
|
define_method(finder_name) do |*args|
|
|
110
|
-
|
|
110
|
+
# Scarpe-Webview only supports a single Shoes::App instance
|
|
111
|
+
app = Shoes.APPS[0]
|
|
111
112
|
|
|
112
113
|
drawables = app.find_drawables_by(drawable_class, *args)
|
|
113
114
|
raise Shoes::Errors::MultipleDrawablesFoundError, "Found more than one #{finder_name} matching #{args.inspect}!" if drawables.size > 1
|
data/lib/scarpe/version.rb
CHANGED
data/lib/scarpe/wv/edit_line.rb
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
module Scarpe::Webview
|
|
4
4
|
class EditLine < Drawable
|
|
5
|
-
attr_reader :text, :width, :stroke, :font, :tooltip
|
|
5
|
+
attr_reader :text, :width, :stroke, :font, :tooltip, :secret
|
|
6
6
|
|
|
7
7
|
def initialize(properties)
|
|
8
8
|
super
|
|
@@ -15,7 +15,7 @@ module Scarpe::Webview
|
|
|
15
15
|
send_self_event(new_text, event_name: "hover")
|
|
16
16
|
end
|
|
17
17
|
end
|
|
18
|
-
|
|
18
|
+
|
|
19
19
|
def properties_changed(changes)
|
|
20
20
|
t = changes.delete("text")
|
|
21
21
|
if t
|
data/lib/scarpe/wv.rb
CHANGED
|
@@ -7,7 +7,14 @@
|
|
|
7
7
|
require "securerandom"
|
|
8
8
|
require "json"
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
# Bloops is optional - only required if you want sound support
|
|
11
|
+
# Install with: gem install bloops (requires portaudio)
|
|
12
|
+
begin
|
|
13
|
+
require "bloops"
|
|
14
|
+
rescue LoadError
|
|
15
|
+
# Bloops not installed - sound features will not be available
|
|
16
|
+
end
|
|
17
|
+
|
|
11
18
|
require "scarpe/components/html" # HTML renderer
|
|
12
19
|
require "scarpe/components/modular_logger"
|
|
13
20
|
require "scarpe/components/promises"
|
data/scarpe-components/Gemfile
CHANGED
|
@@ -1,20 +1,18 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: ../lacci
|
|
3
3
|
specs:
|
|
4
|
-
lacci (0.
|
|
5
|
-
scarpe-components
|
|
4
|
+
lacci (0.4.0)
|
|
5
|
+
scarpe-components (~> 0.4.0)
|
|
6
6
|
|
|
7
7
|
PATH
|
|
8
8
|
remote: .
|
|
9
9
|
specs:
|
|
10
|
-
scarpe-components (0.
|
|
10
|
+
scarpe-components (0.4.0)
|
|
11
11
|
|
|
12
12
|
GEM
|
|
13
13
|
remote: https://rubygems.org/
|
|
14
14
|
specs:
|
|
15
15
|
ansi (1.5.0)
|
|
16
|
-
ast (2.4.2)
|
|
17
|
-
base64 (0.1.1)
|
|
18
16
|
builder (3.2.4)
|
|
19
17
|
debug (1.8.0)
|
|
20
18
|
irb (>= 1.5.0)
|
|
@@ -23,51 +21,25 @@ GEM
|
|
|
23
21
|
irb (1.8.0)
|
|
24
22
|
rdoc (~> 6.5)
|
|
25
23
|
reline (>= 0.3.6)
|
|
26
|
-
json (2.6.3)
|
|
27
|
-
language_server-protocol (3.17.0.3)
|
|
28
24
|
minitest (5.19.0)
|
|
29
25
|
minitest-reporters (1.6.1)
|
|
30
26
|
ansi
|
|
31
27
|
builder
|
|
32
28
|
minitest (>= 5.0)
|
|
33
29
|
ruby-progressbar
|
|
34
|
-
parallel (1.23.0)
|
|
35
|
-
parser (3.2.2.3)
|
|
36
|
-
ast (~> 2.4.1)
|
|
37
|
-
racc
|
|
38
30
|
psych (5.1.0)
|
|
39
31
|
stringio
|
|
40
|
-
racc (1.7.1)
|
|
41
|
-
rainbow (3.1.1)
|
|
42
32
|
rake (13.0.6)
|
|
43
33
|
rdoc (6.5.0)
|
|
44
34
|
psych (>= 4.0.0)
|
|
45
|
-
regexp_parser (2.8.1)
|
|
46
35
|
reline (0.3.8)
|
|
47
36
|
io-console (~> 0.5)
|
|
48
|
-
rexml (3.2.6)
|
|
49
|
-
rubocop (1.56.2)
|
|
50
|
-
base64 (~> 0.1.1)
|
|
51
|
-
json (~> 2.3)
|
|
52
|
-
language_server-protocol (>= 3.17.0)
|
|
53
|
-
parallel (~> 1.10)
|
|
54
|
-
parser (>= 3.2.2.3)
|
|
55
|
-
rainbow (>= 2.2.2, < 4.0)
|
|
56
|
-
regexp_parser (>= 1.8, < 3.0)
|
|
57
|
-
rexml (>= 3.2.5, < 4.0)
|
|
58
|
-
rubocop-ast (>= 1.28.1, < 2.0)
|
|
59
|
-
ruby-progressbar (~> 1.7)
|
|
60
|
-
unicode-display_width (>= 2.4.0, < 3.0)
|
|
61
|
-
rubocop-ast (1.29.0)
|
|
62
|
-
parser (>= 3.2.1.0)
|
|
63
|
-
rubocop-shopify (2.14.0)
|
|
64
|
-
rubocop (~> 1.51)
|
|
65
37
|
ruby-progressbar (1.13.0)
|
|
66
38
|
stringio (3.0.8)
|
|
67
|
-
unicode-display_width (2.4.2)
|
|
68
39
|
webrick (1.8.1)
|
|
69
40
|
|
|
70
41
|
PLATFORMS
|
|
42
|
+
arm64-darwin-21
|
|
71
43
|
x86_64-darwin-22
|
|
72
44
|
|
|
73
45
|
DEPENDENCIES
|
|
@@ -76,8 +48,6 @@ DEPENDENCIES
|
|
|
76
48
|
minitest (~> 5.0)
|
|
77
49
|
minitest-reporters
|
|
78
50
|
rake (~> 13.0)
|
|
79
|
-
rubocop (~> 1.21)
|
|
80
|
-
rubocop-shopify
|
|
81
51
|
scarpe-components!
|
|
82
52
|
webrick
|
|
83
53
|
|
|
@@ -22,9 +22,17 @@ module Scarpe::Components::Calzini
|
|
|
22
22
|
|
|
23
23
|
def edit_line_element(props)
|
|
24
24
|
oninput = handler_js_code("change", "this.value")
|
|
25
|
-
|
|
25
|
+
|
|
26
26
|
HTML.render do |h|
|
|
27
|
-
h.input(
|
|
27
|
+
h.input(
|
|
28
|
+
id: html_id,
|
|
29
|
+
type: props["secret"] ? :password : :text,
|
|
30
|
+
oninput: oninput,
|
|
31
|
+
onmouseover: handler_js_code("hover"),
|
|
32
|
+
value: props["text"],
|
|
33
|
+
style: edit_line_style(props),
|
|
34
|
+
title: props["tooltip"]
|
|
35
|
+
)
|
|
28
36
|
end
|
|
29
37
|
end
|
|
30
38
|
|
|
@@ -220,9 +220,14 @@ module Scarpe::Components::Calzini
|
|
|
220
220
|
private
|
|
221
221
|
|
|
222
222
|
def text_drawable_attrs(props)
|
|
223
|
+
click_value = props["click"]
|
|
224
|
+
# Internal routes (starting with /) should use onclick, not href
|
|
225
|
+
# External URLs use href for normal browser navigation
|
|
226
|
+
is_internal_route = click_value.is_a?(String) && click_value.start_with?("/")
|
|
227
|
+
|
|
223
228
|
{
|
|
224
229
|
# These properties will normally only be set by link()
|
|
225
|
-
href:
|
|
230
|
+
href: is_internal_route ? nil : click_value,
|
|
226
231
|
onclick: props["has_block"] ? handler_js_code("click") : nil,
|
|
227
232
|
}.compact
|
|
228
233
|
end
|
|
@@ -100,6 +100,8 @@ module Scarpe::Components::Calzini
|
|
|
100
100
|
"linear-gradient(45deg, #{bc.first}, #{bc.last})"
|
|
101
101
|
when ->(value) { File.exist?(value) }
|
|
102
102
|
"url(data:image/png;base64,#{encode_file_to_base64(bc)})"
|
|
103
|
+
when ->(value) { valid_url?(value) }
|
|
104
|
+
"url(#{bc})"
|
|
103
105
|
else
|
|
104
106
|
bc
|
|
105
107
|
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "socket"
|
|
4
|
+
|
|
5
|
+
module Scarpe::Components
|
|
6
|
+
module PortHelpers
|
|
7
|
+
MAX_SERVER_STARTUP_WAIT = 5.0
|
|
8
|
+
|
|
9
|
+
def port_working?(ip, port_num)
|
|
10
|
+
begin
|
|
11
|
+
TCPSocket.new(ip, port_num)
|
|
12
|
+
rescue Errno::ECONNREFUSED
|
|
13
|
+
return false
|
|
14
|
+
end
|
|
15
|
+
return true
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def wait_until_port_working(ip, port_num, max_wait: MAX_SERVER_STARTUP_WAIT)
|
|
19
|
+
t_start = Time.now
|
|
20
|
+
loop do
|
|
21
|
+
if Time.now - t_start > max_wait
|
|
22
|
+
raise "Server on port #{port_num} didn't start up in time!"
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
sleep 0.1
|
|
26
|
+
return if port_working?(ip, port_num)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -16,7 +16,7 @@ Gem::Specification.new do |spec|
|
|
|
16
16
|
# spec.metadata["allowed_push_host"] = "TODO: Set to your gem server 'https://example.com'"
|
|
17
17
|
|
|
18
18
|
spec.metadata["homepage_uri"] = spec.homepage
|
|
19
|
-
spec.metadata["source_code_uri"] = "https://github.com/scarpe-team/scarpe"
|
|
19
|
+
#spec.metadata["source_code_uri"] = "https://github.com/scarpe-team/scarpe"
|
|
20
20
|
spec.metadata["changelog_uri"] = "https://github.com/scarpe-team/scarpe/blob/main/CHANGELOG.md"
|
|
21
21
|
|
|
22
22
|
# Specify which files should be added to the gem when it is released.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "test_helper"
|
|
4
|
+
|
|
5
|
+
require "scarpe/components/port_helpers"
|
|
6
|
+
class TestPortHelpers < Minitest::Test
|
|
7
|
+
include Scarpe::Components::PortHelpers
|
|
8
|
+
|
|
9
|
+
def test_port_finder
|
|
10
|
+
assert_equal false, port_working?("127.0.0.1", 9832), "Port 9832 should be unused!"
|
|
11
|
+
end
|
|
12
|
+
end
|