screenkit 0.0.10 → 0.0.11

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.
@@ -3,8 +3,11 @@
3
3
  module ScreenKit
4
4
  module Exporter
5
5
  class Intro
6
+ using CoreExt
7
+
6
8
  include Shell
7
9
  include Utils
10
+ include ImageMagick
8
11
  extend SchemaValidator
9
12
 
10
13
  def self.schema_path
@@ -14,19 +17,15 @@ module ScreenKit
14
17
  # The intro scene configuration.
15
18
  attr_reader :config
16
19
 
17
- # The title text.
18
- attr_reader :text
19
-
20
20
  # The source path lookup instance.
21
21
  attr_reader :source
22
22
 
23
23
  # The log path.
24
24
  attr_reader :log_path
25
25
 
26
- def initialize(config:, text:, source:, log_path: nil)
26
+ def initialize(config:, source:, log_path: nil)
27
27
  self.class.validate!(config)
28
28
  @config = config
29
- @text = text
30
29
  @source = source
31
30
  @log_path = log_path
32
31
  end
@@ -75,8 +74,89 @@ module ScreenKit
75
74
  @font_path ||= source.search(title_config[:font_path])
76
75
  end
77
76
 
77
+ def render_elements(overlay_path)
78
+ padding = Spacing.new(hi_res(config.fetch(:padding, 100)))
79
+
80
+ hi_res(
81
+ image_width: 1920,
82
+ image_height: 1080,
83
+ content_width: 1920 - (padding.horizontal / 2)
84
+ ) => {
85
+ image_width:,
86
+ image_height:,
87
+ content_width:,
88
+ }
89
+
90
+ logo = hi_res({width: 350, x: 0, y: 0}.deep_merge(config[:logo]))
91
+ title = hi_res({size: 144, x: 0, y: 0}.deep_merge(config[:title]))
92
+ url = hi_res({size: 42, x: 0, y: 0}.deep_merge(config[:url]))
93
+ url_height = 0
94
+
95
+ logo_intermediary_path = overlay_path.sub_ext("_logo.png")
96
+ title_intermediary_path = overlay_path.sub_ext("_title.png")
97
+ url_intermediary_path = overlay_path.sub_ext("_url.png")
98
+
99
+ MiniMagick.convert do |image|
100
+ image << logo_path
101
+ image << "-resize"
102
+ image << "#{logo[:width]}x"
103
+ image << "PNG:#{logo_intermediary_path}"
104
+ end
105
+
106
+ title_style = TextStyle.new(source:, **title)
107
+ url_style = TextStyle.new(source:, **url)
108
+
109
+ _, _, title_height =
110
+ *render_text_image(path: title_intermediary_path,
111
+ text: title[:text],
112
+ style: title_style,
113
+ width: content_width,
114
+ type: "caption")
115
+
116
+ if url[:text]
117
+ _, _, url_height =
118
+ *render_text_image(path: url_intermediary_path,
119
+ text: url[:text],
120
+ style: url_style,
121
+ width: content_width,
122
+ type: "caption")
123
+ end
124
+
125
+ MiniMagick.convert do |image|
126
+ image << "-size"
127
+ image << "#{image_width}x#{image_height}"
128
+ image << "xc:none"
129
+
130
+ image << logo_intermediary_path
131
+ image << "-geometry"
132
+ image << "+#{padding.left}+#{padding.top}"
133
+ image << "-composite"
134
+
135
+ offset_y = (image_height - title_height) / 2
136
+
137
+ image << title_intermediary_path
138
+ image << "-geometry"
139
+ image << "+#{padding.left}+#{offset_y}"
140
+ image << "-composite"
141
+
142
+ offset_y = image_height - padding.bottom - url_height
143
+
144
+ if url[:text]
145
+ image << url_intermediary_path
146
+ image << "-geometry"
147
+ image << "+#{padding.left}+#{offset_y}"
148
+ image << "-composite"
149
+ end
150
+
151
+ image << "PNG:#{overlay_path}"
152
+ end
153
+ end
154
+
78
155
  def export(path)
79
- ffmpeg_params => {inputs:, filters:, maps:}
156
+ overlay_path = path.sub_ext(".png")
157
+ render_elements(overlay_path)
158
+
159
+ ffmpeg_params(overlay_path) => {inputs:, filters:, maps:}
80
160
 
81
161
  cmd = [
82
162
  "ffmpeg",
@@ -95,11 +175,11 @@ module ScreenKit
95
175
  run_command(*cmd, log_path:)
96
176
  end
97
177
 
98
- private def ffmpeg_params
178
+ private def ffmpeg_params(overlay_path)
99
179
  duration = Duration.parse(config[:duration])
100
180
  fade_in = Duration.parse(config.fetch(:fade_in, 0.0))
101
181
  fade_out = Duration.parse(config.fetch(:fade_out, 0.5))
102
- fade_out_start = duration - fade_out - 0.1
182
+ fade_out_start = duration - fade_out - 0.2
103
183
 
104
184
  # Build filter chain
105
185
  inputs = []
@@ -155,61 +235,15 @@ module ScreenKit
155
235
 
156
236
  current_layer = "bg"
157
237
 
158
- # Logo layer (if present)
159
- if logo_path
160
- logo_width = logo_config.fetch(:width, 350)
161
- logo_x = logo_config.fetch(:x, "center")
162
- logo_y = logo_config.fetch(:y, "center")
163
- overlay_x = logo_x == "center" ? "(W-w)/2" : logo_x
164
- overlay_y = logo_y == "center" ? "(H-h)/2" : logo_y
165
-
166
- inputs += ["-loop", "1", "-i", logo_path]
167
- filters << "[#{stream_index}:v]scale=#{logo_width}:" \
168
- "-1:flags=lanczos[logo]"
169
- filters << "[#{current_layer}][logo]overlay=#{overlay_x}:" \
170
- "#{overlay_y}[with_logo]"
171
- current_layer = "with_logo"
238
+ # Overlay layer (if present)
239
+ if overlay_path.file?
240
+ inputs += ["-loop", "1", "-i", overlay_path]
241
+ filters << "[#{stream_index}:v]scale=1920:1080[overlay]"
242
+ filters << "[#{current_layer}][overlay]overlay=0:0[with_overlay]"
243
+ current_layer = "with_overlay"
172
244
  stream_index += 1
173
245
  end
174
246
 
175
- # Title layer (if present)
176
- if title_config
177
- title_x = title_config.fetch(:x, "center")
178
- title_y = title_config.fetch(:y, "center")
179
- title_size = title_config.fetch(:size, 72)
180
- title_color = title_config.fetch(:color, "white")
181
-
182
- # Calculate max width based on x offset
183
- max_width = if title_x == "center"
184
- 1720 # 1920 - (2 * 100)
185
- else
186
- 1920 - (2 * title_x.to_i)
187
- end
188
-
189
- # Rough estimate characters per line based on font size
190
- avg_char_width = title_size * 0.7
191
- max_chars_per_line = (max_width / avg_char_width).floor
192
-
193
- # Auto-wrap text
194
- wrapped_text = wrap_text(text, max_chars_per_line)
195
-
196
- # Convert position to drawtext coordinates
197
- drawtext_x = title_x == "center" ? "(w-text_w)/2" : title_x
198
- drawtext_y = title_y == "center" ? "(h-text_h)/2" : title_y
199
-
200
- # Center align text when x is centered
201
- text_align = title_x == "center" ? ":text_align=center" : ""
202
-
203
- # Escape special characters in text
204
- wrapped_text = wrapped_text.gsub("'", "'\\\\\\''").gsub(":", "\\:")
205
-
206
- filters << "[#{current_layer}]drawtext=text='#{wrapped_text}':" \
207
- "fontfile=#{font_path}:fontsize=#{title_size}:" \
208
- "fontcolor=#{title_color}:x=#{drawtext_x}:" \
209
- "y=#{drawtext_y}#{text_align}[with_title]"
210
- current_layer = "with_title"
211
- end
212
-
213
247
  # Apply fades to final video layer
214
248
  # Use black for fade color when background is an image file
215
249
  fade_color = background_path&.file? ? "black" : background
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ScreenKit
4
+ module Exporter
5
+ class Playwright
6
+ include Shell
7
+
8
+ attr_reader :script_path, :log_path, :options
9
+
10
+ def initialize(script_path:, options: {}, log_path: nil)
11
+ @script_path = script_path
12
+ @log_path = log_path
13
+ @options = options
14
+ end
15
+
16
+ def export(output_path)
17
+ run_command "playwright-video",
18
+ "export",
19
+ script_path,
20
+ options_to_args(options),
21
+ "--output-path", output_path,
22
+ log_path:,
23
+ chdir: script_path.parent.parent
24
+ end
25
+
26
+ def options_to_args(options)
27
+ (options || {}).flat_map do |key, value|
28
+ [key.to_s.tr("_", "-").prepend("--"), value]
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -64,7 +64,19 @@ module ScreenKit
64
64
 
65
65
  log_path = format(log_path.to_s, prefix:) if log_path
66
66
 
67
- case content_path.extname.downcase.gsub(/^\./, "")
67
+ # Consider all extnames, after the first dot.
68
+ # E.g. "video.playwright.js" -> "playwright.js"
69
+ extname = content_path.basename.to_s.downcase.split(".")[1..].join(".")
70
+
71
+ case extname
72
+ when *ContentType.playwright
73
+ Exporter::Playwright
74
+ .new(
75
+ script_path: content_path,
76
+ options: episode.playwright_options,
77
+ log_path:,
78
+ )
79
+ .export(video_path)
68
80
  when *ContentType.video
69
81
  Exporter::Video
70
82
  .new(input_path: content_path, log_path:)
@@ -1,5 +1,5 @@
1
1
  ---
2
- # yaml-language-server: $schema=https://screenkit.dev/schemas/episode.json
2
+ # yaml-language-server: $schema=https://screenkit.dev/schemas/config.json
3
3
 
4
4
  # The episode title (displayed in intro scene).
5
5
  # Line breaks are inferred based on approximate text width.
@@ -8,4 +8,4 @@ title: <%= options.title.to_yaml[4..] %>
8
8
  # Episode-specific overrides for global configuration.
9
9
  # Use an editor with JSON Schema support to see available options and
10
10
  # autocomplete.
11
- # Schema: https://screenkit.dev/schemas/episode.json
11
+ # Schema: https://screenkit.dev/schemas/config.json
@@ -1,8 +1,7 @@
1
1
  ---
2
- # yaml-language-server: $schema=../../schemas/project.json
3
- ## yaml-language-server: $schema=https://screenkit.dev/schemas/project.json
2
+ # yaml-language-server: $schema=https://screenkit.dev/schemas/config.json
4
3
 
5
- # ScreenKit project configuration file.
4
+ # ScreenKit configuration version.
6
5
  schema: 1
7
6
 
8
7
  # The episodes directory is where the source files for each episode are stored.
@@ -155,10 +154,18 @@ scenes:
155
154
  # The background color/image of the intro scene.
156
155
  background: "#100f50"
157
156
 
157
+ # The padding around the intro.
158
+ padding: 100
159
+
160
+ # Show the url text in the intro scene.
161
+ url:
162
+ text: "https://screenkit.dev"
163
+ font_path: open-sans/OpenSans-SemiBold.ttf
164
+ size: 42
165
+ color: "#ffffff80"
166
+
158
167
  # The title text to be displayed in the intro scene.
159
168
  title:
160
- x: 100
161
- y: 300
162
169
  font_path: open-sans/OpenSans-ExtraBold.ttf
163
170
  size: 144
164
171
  color: "#ffffff"
@@ -168,8 +175,6 @@ scenes:
168
175
  # size it'll be displayed).
169
176
  logo:
170
177
  path: logo.png
171
- x: 100
172
- y: 200
173
178
  width: 300
174
179
 
175
180
  # The sound to be played along with the logo in the intro.
@@ -0,0 +1,106 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ScreenKit
4
+ module ImageMagick
5
+ # Wrap text to fit within the specified maximum width.
6
+ # @param text [String] The text to wrap.
7
+ # @param max_width [Integer] The maximum width in pixels.
8
+ # @param font_size [Integer] The font size in points.
9
+ # @return [Array<String>] The wrapped lines of text.
10
+ def text_wrap(text, max_width:, font_size:)
11
+ words = text.to_s.split(/\s+/)
12
+ width_factor = 0.6
13
+
14
+ [].tap do |lines|
15
+ words.each do |word|
16
+ line = lines.pop.to_s
17
+ word_width = word.size * (font_size * width_factor)
18
+ line_width = line.size * (font_size * width_factor)
19
+
20
+ if line_width + word_width <= max_width
21
+ line = [(line unless line.empty?), word].compact.join(" ")
22
+ lines << line
23
+ else
24
+ lines << line
25
+ lines << word
26
+ end
27
+ end
28
+ end
29
+ end
30
+
31
+ # Escape text for use in ImageMagick caption.
32
+ def escape_text_for_image(text)
33
+ text.gsub("'", "\\\\'")
34
+ end
35
+
36
+ # Render text into an image using MiniMagick.
37
+ # @param text [String] The text to render.
38
+ # @param style [TextStyle] The text style to apply.
39
+ # @param width [Integer] The width of the text image.
40
+ # @param type [String] The ImageMagick text type (e.g., "caption").
41
+ # @param path [String, nil] The output path.
42
+ # @return [Array] The path to the generated text image, width, and
43
+ # height.
44
+ def render_text_image(text:, style:, width:, type:, path: nil)
45
+ return [nil, 0, 0] if text.to_s.empty?
46
+
47
+ image = MiniMagick::Image.open(
48
+ create_text_image(text:, style:, width:, type:, path:)
49
+ )
50
+
51
+ [image.path, image.width, image.height]
52
+ end
53
+
54
+ # Convert values to high resolution (2x).
55
+ # @param value [Object] The value to convert.
56
+ # @return [Object] The converted value.
57
+ def hi_res(value)
58
+ case value
59
+ when Array
60
+ value.map { hi_res(it) }
61
+ when Hash
62
+ value.transform_values { hi_res(it) }
63
+ when Numeric
64
+ value * 2
65
+ else
66
+ value
67
+ end
68
+ end
69
+
70
+ # Create a text image using MiniMagick.
71
+ # @param text [String] The text to render.
72
+ # @param style [TextStyle] The text style to apply.
73
+ # @param width [Integer] The width of the text image.
74
+ # @param type [String] The ImageMagick text type (e.g., "caption").
75
+ # @param path [String, nil] The output path.
76
+ # @return [Array] The path to the generated text image, and the actual
77
+ # `Tempfile` instance.
78
+ def create_text_image(text:, style:, width:, type:, path: nil)
79
+ path ||= File.join(Dir.tmpdir, "callout-text-#{SecureRandom.hex(10)}.png")
80
+ FileUtils.mkdir_p(File.dirname(path))
81
+
82
+ MiniMagick.convert do |image|
83
+ unless type == "label"
84
+ image << "-size"
85
+ image << "#{width}x"
86
+ end
87
+
88
+ image << "-background"
89
+ image << "none"
90
+ image << "-fill"
91
+ image << style.color
92
+ image << "-font"
93
+ image << style.font_path.to_s
94
+ image << "-pointsize"
95
+ image << style.size.to_s
96
+ image << "#{type}:#{escape_text_for_image(text)}"
97
+ image << "PNG:#{path}"
98
+ end
99
+
100
+ path
101
+ rescue MiniMagick::Error => error
102
+ retry if error.message.include?("No such file or directory")
103
+ raise
104
+ end
105
+ end
106
+ end
@@ -3,8 +3,14 @@
3
3
  "$id": "https://screenkit.dev/schemas/project.json",
4
4
  "title": "ScreenKit Project Configuration (screenkit.yml)",
5
5
  "type": "object",
6
- "required": ["schema", "resources_dir", "episode_dir", "output_dir"],
6
+ "required": ["schema"],
7
7
  "properties": {
8
+ "title": {
9
+ "type": "string",
10
+ "description": "The episode title",
11
+ "minLength": 1,
12
+ "pattern": "\\S"
13
+ },
8
14
  "resources_dir": { "$ref": "refs/directory.json" },
9
15
  "backtrack": { "$ref": "refs/sound.json" },
10
16
  "tts": { "$ref": "refs/tts.json" },
@@ -31,7 +37,8 @@
31
37
  "$ref": "refs/callout_style.json"
32
38
  }
33
39
  },
34
- "demotape": { "$ref": "refs/demotape.json" }
40
+ "demotape": { "$ref": "refs/demotape.json" },
41
+ "playwright": { "$ref": "refs/playwright.json" }
35
42
  },
36
43
  "additionalProperties": false
37
44
  }
@@ -7,12 +7,16 @@
7
7
  "fade_in": { "$ref": "duration.json" },
8
8
  "fade_out": { "$ref": "duration.json" },
9
9
  "title": {
10
- "type": "object",
11
10
  "description": "Title configuration",
12
- "allOf": [{ "$ref": "text_style.json" }, { "$ref": "position.json" }]
11
+ "$ref": "text_style.json"
13
12
  },
14
13
  "background": { "$ref": "background.json" },
15
14
  "logo": { "$ref": "logo.json" },
16
- "sound": { "$ref": "sound.json" }
15
+ "sound": { "$ref": "sound.json" },
16
+ "padding": { "$ref": "spacing.json" },
17
+ "url": {
18
+ "description": "URL configuration",
19
+ "$ref": "text_style.json"
20
+ }
17
21
  }
18
22
  }
@@ -0,0 +1,13 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-04/schema#",
3
+ "$id": "https://screenkit.dev/schemas/refs/playwright.json",
4
+ "title": "playwright-video settings (https://github.com/fnando/playwright-video)",
5
+ "type": "object",
6
+ "properties": {
7
+ "color_scheme": {
8
+ "type": "string",
9
+ "description": "Color scheme to use when capturing the video.",
10
+ "enum": ["light", "dark"]
11
+ }
12
+ }
13
+ }
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ScreenKit
4
+ class TextStyle
5
+ attr_reader :color, :size, :font_path, :align
6
+
7
+ def initialize(source:, **kwargs)
8
+ @source = source
9
+
10
+ kwargs.each do |key, value|
11
+ value = case key.to_sym
12
+ when :font_path
13
+ @source.search(value)
14
+ else
15
+ value
16
+ end
17
+
18
+ instance_variable_set(:"@#{key}", value)
19
+ end
20
+ end
21
+
22
+ # Convert hex color (with optional alpha) to RGB + opacity
23
+ # #RRGGBB or #RRGGBBAA
24
+ def rgb_color
25
+ color.match(/#([0-9a-fA-F]{6})/) {|m| m[1] }
26
+ end
27
+
28
+ def opacity
29
+ if color.length == 9
30
+ color.match(/#[0-9a-fA-F]{6}([0-9a-fA-F]{2})/) do |m|
31
+ m[1].to_i(16) / 255.0
32
+ end
33
+ else
34
+ 1.0
35
+ end
36
+ end
37
+
38
+ def as_json(*)
39
+ {color:, size:, font_path:, rgb_color:, opacity:, align:}
40
+ end
41
+ end
42
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ScreenKit
4
- VERSION = "0.0.10"
4
+ VERSION = "0.0.11"
5
5
  end
data/lib/screenkit.rb CHANGED
@@ -26,14 +26,13 @@ module ScreenKit
26
26
  require_relative "screenkit/spinner"
27
27
  require_relative "screenkit/shell"
28
28
  require_relative "screenkit/http"
29
+ require_relative "screenkit/image_magick"
29
30
  require_relative "screenkit/schema_validator"
30
31
  require_relative "screenkit/generators/project"
31
32
  require_relative "screenkit/generators/episode"
32
- require_relative "screenkit/config/base"
33
- require_relative "screenkit/config/project"
34
- require_relative "screenkit/config/episode"
33
+ require_relative "screenkit/config"
35
34
  require_relative "screenkit/callout"
36
- require_relative "screenkit/callout/text_style"
35
+ require_relative "screenkit/text_style"
37
36
  require_relative "screenkit/callout/styles/base"
38
37
  require_relative "screenkit/transition"
39
38
  require_relative "screenkit/parallel_processor"
@@ -54,6 +53,7 @@ module ScreenKit
54
53
  require_relative "screenkit/exporter/segment"
55
54
  require_relative "screenkit/exporter/image"
56
55
  require_relative "screenkit/exporter/video"
56
+ require_relative "screenkit/exporter/playwright"
57
57
 
58
58
  require_files = lambda do |pattern|
59
59
  Gem.find_files_from_load_path(pattern).each do |path|
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: screenkit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.10
4
+ version: 0.0.11
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nando Vieira
@@ -304,16 +304,14 @@ files:
304
304
  - lib/screenkit/callout/styles/inline_block.rb
305
305
  - lib/screenkit/callout/styles/shadow_block.rb
306
306
  - lib/screenkit/callout/styles/social.rb
307
- - lib/screenkit/callout/text_style.rb
308
307
  - lib/screenkit/cli.rb
309
308
  - lib/screenkit/cli/base.rb
310
309
  - lib/screenkit/cli/episode.rb
311
310
  - lib/screenkit/cli/root.rb
312
- - lib/screenkit/config/base.rb
313
- - lib/screenkit/config/episode.rb
314
- - lib/screenkit/config/project.rb
311
+ - lib/screenkit/config.rb
315
312
  - lib/screenkit/content_type.rb
316
313
  - lib/screenkit/core_ext.rb
314
+ - lib/screenkit/core_ext/hash.rb
317
315
  - lib/screenkit/core_ext/json.rb
318
316
  - lib/screenkit/core_ext/string.rb
319
317
  - lib/screenkit/duration.rb
@@ -322,6 +320,7 @@ files:
322
320
  - lib/screenkit/exporter/image.rb
323
321
  - lib/screenkit/exporter/intro.rb
324
322
  - lib/screenkit/exporter/outro.rb
323
+ - lib/screenkit/exporter/playwright.rb
325
324
  - lib/screenkit/exporter/segment.rb
326
325
  - lib/screenkit/exporter/video.rb
327
326
  - lib/screenkit/generators/episode.rb
@@ -345,6 +344,7 @@ files:
345
344
  - lib/screenkit/generators/project/resources/sounds/whoosh.mp3
346
345
  - lib/screenkit/generators/project/screenkit.yml
347
346
  - lib/screenkit/http.rb
347
+ - lib/screenkit/image_magick.rb
348
348
  - lib/screenkit/logfile.rb
349
349
  - lib/screenkit/parallel_processor.rb
350
350
  - lib/screenkit/path_lookup.rb
@@ -371,8 +371,7 @@ files:
371
371
  - lib/screenkit/schemas/callout_styles/social.json
372
372
  - lib/screenkit/schemas/callouts/inline_block.json
373
373
  - lib/screenkit/schemas/callouts/shadow_block.json
374
- - lib/screenkit/schemas/episode.json
375
- - lib/screenkit/schemas/project.json
374
+ - lib/screenkit/schemas/config.json
376
375
  - lib/screenkit/schemas/refs/anchor.json
377
376
  - lib/screenkit/schemas/refs/animation.json
378
377
  - lib/screenkit/schemas/refs/background.json
@@ -385,6 +384,7 @@ files:
385
384
  - lib/screenkit/schemas/refs/intro.json
386
385
  - lib/screenkit/schemas/refs/logo.json
387
386
  - lib/screenkit/schemas/refs/outro.json
387
+ - lib/screenkit/schemas/refs/playwright.json
388
388
  - lib/screenkit/schemas/refs/position.json
389
389
  - lib/screenkit/schemas/refs/scenes.json
390
390
  - lib/screenkit/schemas/refs/size.json
@@ -402,6 +402,7 @@ files:
402
402
  - lib/screenkit/sound.rb
403
403
  - lib/screenkit/spacing.rb
404
404
  - lib/screenkit/spinner.rb
405
+ - lib/screenkit/text_style.rb
405
406
  - lib/screenkit/time_formatter.rb
406
407
  - lib/screenkit/transition.rb
407
408
  - lib/screenkit/tts/base.rb
@@ -419,10 +420,10 @@ metadata:
419
420
  rubygems_mfa_required: 'true'
420
421
  homepage_uri: https://github.com/fnando/screenkit
421
422
  bug_tracker_uri: https://github.com/fnando/screenkit/issues
422
- source_code_uri: https://github.com/fnando/screenkit/tree/v0.0.10
423
- changelog_uri: https://github.com/fnando/screenkit/tree/v0.0.10/CHANGELOG.md
424
- documentation_uri: https://github.com/fnando/screenkit/tree/v0.0.10/README.md
425
- license_uri: https://github.com/fnando/screenkit/tree/v0.0.10/LICENSE.md
423
+ source_code_uri: https://github.com/fnando/screenkit/tree/v0.0.11
424
+ changelog_uri: https://github.com/fnando/screenkit/tree/v0.0.11/CHANGELOG.md
425
+ documentation_uri: https://github.com/fnando/screenkit/tree/v0.0.11/README.md
426
+ license_uri: https://github.com/fnando/screenkit/tree/v0.0.11/LICENSE.md
426
427
  rdoc_options: []
427
428
  require_paths:
428
429
  - lib
@@ -437,7 +438,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
437
438
  - !ruby/object:Gem::Version
438
439
  version: '0'
439
440
  requirements: []
440
- rubygems_version: 3.6.9
441
+ rubygems_version: 4.0.0
441
442
  specification_version: 4
442
443
  summary: Terminal to screencast, simplified
443
444
  test_files: []