ratatui_ruby-devtools 0.2.1 → 0.4.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.
Files changed (134) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -1
  3. data/AGENTS.md +1 -1
  4. data/CHANGELOG.md +69 -7
  5. data/README.md +62 -21
  6. data/Rakefile +1 -1
  7. data/bin/setup +20 -6
  8. data/bin/setup.ps1 +74 -0
  9. data/doc/contributors/documentation_style.md +3 -4
  10. data/exe/scaffold +8 -342
  11. data/lib/ratatui_ruby/devtools/scaffold/scaffold_config.rb +67 -0
  12. data/lib/ratatui_ruby/devtools/scaffold/template_renderer.rb +282 -0
  13. data/lib/ratatui_ruby/devtools/task_scope.rb +24 -0
  14. data/lib/ratatui_ruby/devtools/tasks/autodoc_tasks.rb +31 -0
  15. data/lib/ratatui_ruby/devtools/tasks/bump/bump_workflow.rb +71 -0
  16. data/lib/ratatui_ruby/devtools/tasks/bump/changelog.rb +60 -3
  17. data/lib/ratatui_ruby/devtools/tasks/bump/github_project.rb +26 -0
  18. data/lib/ratatui_ruby/devtools/tasks/bump/history.rb +3 -3
  19. data/lib/ratatui_ruby/devtools/tasks/bump/links.rb +39 -24
  20. data/lib/ratatui_ruby/devtools/tasks/bump/manifest.rb +9 -17
  21. data/lib/ratatui_ruby/devtools/tasks/bump/no_crate.rb +19 -0
  22. data/lib/ratatui_ruby/devtools/tasks/bump/no_links.rb +22 -0
  23. data/lib/ratatui_ruby/devtools/tasks/bump/patch_release.rb +25 -0
  24. data/lib/ratatui_ruby/devtools/tasks/bump/release_branch.rb +17 -0
  25. data/lib/ratatui_ruby/devtools/tasks/bump/release_from_trunk.rb +48 -0
  26. data/lib/ratatui_ruby/devtools/tasks/bump/repository.rb +143 -0
  27. data/lib/ratatui_ruby/devtools/tasks/bump/ruby_gem.rb +65 -59
  28. data/lib/ratatui_ruby/devtools/tasks/bump/rust_crate.rb +42 -0
  29. data/lib/ratatui_ruby/devtools/tasks/bump/sem_ver.rb +127 -10
  30. data/lib/ratatui_ruby/devtools/tasks/bump/source_hut_project.rb +26 -0
  31. data/lib/ratatui_ruby/devtools/tasks/bump/unbranched_release.rb +20 -0
  32. data/lib/ratatui_ruby/devtools/tasks/bump/unreleased_section.rb +19 -1
  33. data/lib/ratatui_ruby/devtools/tasks/bump_tasks.rb +47 -0
  34. data/lib/ratatui_ruby/devtools/tasks/cargo_tasks.rb +57 -0
  35. data/lib/ratatui_ruby/devtools/tasks/doc/documentation.rb +59 -0
  36. data/lib/ratatui_ruby/devtools/tasks/doc/link/file_url.rb +30 -0
  37. data/lib/ratatui_ruby/devtools/tasks/doc/link/relative_path.rb +61 -0
  38. data/lib/ratatui_ruby/devtools/tasks/doc/link/web_url.rb +55 -0
  39. data/lib/ratatui_ruby/devtools/tasks/doc/link.rb +52 -0
  40. data/lib/ratatui_ruby/devtools/tasks/doc/link_audit.rb +116 -0
  41. data/lib/ratatui_ruby/devtools/tasks/doc/problem.rb +40 -0
  42. data/lib/ratatui_ruby/devtools/tasks/doc/source_file.rb +93 -0
  43. data/lib/ratatui_ruby/devtools/tasks/doc_tasks.rb +937 -0
  44. data/lib/ratatui_ruby/devtools/tasks/license/blame.rb +78 -0
  45. data/lib/ratatui_ruby/devtools/tasks/license/changed_files.rb +34 -0
  46. data/lib/ratatui_ruby/devtools/tasks/license/contribution.rb +12 -0
  47. data/lib/ratatui_ruby/devtools/tasks/license/copyright.rb +47 -0
  48. data/lib/ratatui_ruby/devtools/tasks/license/directory_licensing.rb +42 -0
  49. data/lib/ratatui_ruby/devtools/tasks/license/existing_header.rb +21 -0
  50. data/lib/ratatui_ruby/devtools/tasks/license/header_revision.rb +45 -0
  51. data/lib/ratatui_ruby/devtools/tasks/license/licensed_file.rb +39 -0
  52. data/lib/ratatui_ruby/devtools/tasks/license/licensing.rb +35 -0
  53. data/lib/ratatui_ruby/devtools/tasks/license/markdown_document.rb +23 -0
  54. data/lib/ratatui_ruby/devtools/tasks/license/markdown_files.rb +31 -0
  55. data/lib/ratatui_ruby/devtools/tasks/license/markdown_header_syntax.rb +104 -0
  56. data/lib/ratatui_ruby/devtools/tasks/license/markdown_snippet_syntax.rb +159 -0
  57. data/lib/ratatui_ruby/devtools/tasks/license/missing_header.rb +18 -0
  58. data/lib/ratatui_ruby/devtools/tasks/license/rbs_files.rb +27 -0
  59. data/lib/ratatui_ruby/devtools/tasks/license/rbs_header_syntax.rb +33 -0
  60. data/lib/ratatui_ruby/devtools/tasks/license/rdoc_comment.rb +51 -0
  61. data/lib/ratatui_ruby/devtools/tasks/license/rdoc_examples.rb +41 -0
  62. data/lib/ratatui_ruby/devtools/tasks/license/rdoc_snippet_syntax.rb +119 -0
  63. data/lib/ratatui_ruby/devtools/tasks/license/renewal.rb +17 -0
  64. data/lib/ratatui_ruby/devtools/tasks/license/reuse_annotated_file.rb +12 -0
  65. data/lib/ratatui_ruby/devtools/tasks/license/reuse_tool.rb +34 -0
  66. data/lib/ratatui_ruby/devtools/tasks/license/ruby_comment_header.rb +57 -0
  67. data/lib/ratatui_ruby/devtools/tasks/license/ruby_files.rb +36 -0
  68. data/lib/ratatui_ruby/devtools/tasks/license/ruby_header_syntax.rb +47 -0
  69. data/lib/ratatui_ruby/devtools/tasks/license/rust_files.rb +27 -0
  70. data/lib/ratatui_ruby/devtools/tasks/license/rust_header_syntax.rb +68 -0
  71. data/lib/ratatui_ruby/devtools/tasks/license/snippet.rb +44 -0
  72. data/lib/ratatui_ruby/devtools/tasks/license/snippet_file.rb +29 -0
  73. data/lib/ratatui_ruby/devtools/tasks/license/snippet_opening.rb +39 -0
  74. data/lib/ratatui_ruby/devtools/tasks/license/snippet_revision.rb +75 -0
  75. data/lib/ratatui_ruby/devtools/tasks/license/spdx_header.rb +42 -0
  76. data/lib/ratatui_ruby/devtools/tasks/license/unknown_file.rb +12 -0
  77. data/lib/ratatui_ruby/devtools/tasks/license/unlicensed_files.rb +69 -0
  78. data/lib/ratatui_ruby/devtools/tasks/license/wrapped_snippet.rb +30 -0
  79. data/lib/ratatui_ruby/devtools/tasks/license_tasks.rb +71 -0
  80. data/lib/ratatui_ruby/devtools/tasks/lint/gem_lockfile.rb +29 -0
  81. data/lib/ratatui_ruby/devtools/tasks/lint/supported_rubies.rb +18 -0
  82. data/lib/ratatui_ruby/devtools/tasks/lint_tasks.rb +100 -0
  83. data/lib/ratatui_ruby/devtools/tasks/release/platform_gem.rb +21 -12
  84. data/lib/ratatui_ruby/devtools/tasks/release/versioned_binary.rb +1 -1
  85. data/lib/ratatui_ruby/devtools/tasks/release_tasks.rb +80 -0
  86. data/lib/ratatui_ruby/devtools/tasks/reuse_tasks.rb +39 -0
  87. data/lib/ratatui_ruby/devtools/tasks/{test.rake → test_tasks.rb} +13 -4
  88. data/lib/ratatui_ruby/devtools/tasks/website/hosted_source_tree.rb +24 -0
  89. data/lib/ratatui_ruby/devtools/tasks/website/index_page.rb +1 -4
  90. data/lib/ratatui_ruby/devtools/tasks/website/source_tree.rb +63 -0
  91. data/lib/ratatui_ruby/devtools/tasks/website/versioned_documentation.rb +14 -13
  92. data/lib/ratatui_ruby/devtools/tasks/website_tasks.rb +49 -0
  93. data/lib/ratatui_ruby/devtools/templates/.github/workflows/build-gems.yml.erb +15 -9
  94. data/lib/ratatui_ruby/devtools/templates/.github/workflows/ci.yml.erb +2 -2
  95. data/lib/ratatui_ruby/devtools/templates/.gitignore.erb +2 -1
  96. data/lib/ratatui_ruby/devtools/templates/.rubocop.yml.erb +1 -1
  97. data/lib/ratatui_ruby/devtools/templates/AGENTS.md.erb +1 -1
  98. data/lib/ratatui_ruby/devtools/templates/CHANGELOG.md.erb +3 -1
  99. data/lib/ratatui_ruby/devtools/templates/CONTRIBUTING.md.erb +3 -3
  100. data/lib/ratatui_ruby/devtools/templates/Gemfile.erb +2 -3
  101. data/lib/ratatui_ruby/devtools/templates/README.md.erb +7 -7
  102. data/lib/ratatui_ruby/devtools/templates/REUSE.toml.erb +1 -1
  103. data/lib/ratatui_ruby/devtools/templates/bin/setup.erb +5 -1
  104. data/lib/ratatui_ruby/devtools/templates/bin/setup.ps1.erb +5 -1
  105. data/lib/ratatui_ruby/devtools/templates/doc/concepts/application_architecture.md.erb +2 -2
  106. data/lib/ratatui_ruby/devtools/templates/doc/concepts/application_testing.md.erb +3 -3
  107. data/lib/ratatui_ruby/devtools/templates/doc/getting_started/quickstart.md.erb +4 -4
  108. data/lib/ratatui_ruby/devtools/templates/ext/Cargo.toml.erb +1 -1
  109. data/lib/ratatui_ruby/devtools/templates/gemspec.erb +1 -1
  110. data/lib/ratatui_ruby/devtools/templates/mise.toml.erb +3 -3
  111. data/lib/ratatui_ruby/devtools/version.rb +1 -1
  112. data/lib/ratatui_ruby/devtools.rb +54 -71
  113. data/mise.toml +2 -2
  114. data/sig/ratatui_ruby/devtools.rbs +16 -1
  115. metadata +93 -34
  116. data/.builds/ruby-4.0.yml +0 -38
  117. data/lib/ratatui_ruby/devtools/tasks/autodoc.rake +0 -21
  118. data/lib/ratatui_ruby/devtools/tasks/bump.rake +0 -80
  119. data/lib/ratatui_ruby/devtools/tasks/cargo.rake +0 -47
  120. data/lib/ratatui_ruby/devtools/tasks/doc.rake +0 -887
  121. data/lib/ratatui_ruby/devtools/tasks/license/headers_md.rb +0 -276
  122. data/lib/ratatui_ruby/devtools/tasks/license/headers_rb.rb +0 -236
  123. data/lib/ratatui_ruby/devtools/tasks/license/license_utils.rb +0 -143
  124. data/lib/ratatui_ruby/devtools/tasks/license/snippets_md.rb +0 -353
  125. data/lib/ratatui_ruby/devtools/tasks/license/snippets_rdoc.rb +0 -186
  126. data/lib/ratatui_ruby/devtools/tasks/license.rake +0 -91
  127. data/lib/ratatui_ruby/devtools/tasks/lint.rake +0 -80
  128. data/lib/ratatui_ruby/devtools/tasks/release.rake +0 -87
  129. data/lib/ratatui_ruby/devtools/tasks/resources/rubies.yml +0 -7
  130. data/lib/ratatui_ruby/devtools/tasks/reuse.rake +0 -104
  131. data/lib/ratatui_ruby/devtools/tasks/website.rake +0 -37
  132. data/lib/ratatui_ruby/devtools/templates/.builds/ruby.yml.erb +0 -47
  133. data/lib/ratatui_ruby/devtools/templates/tasks/resources/index.html.erb +0 -45
  134. data/lib/ratatui_ruby/devtools/templates/tasks/resources/rubies.yml.erb +0 -8
@@ -5,14 +5,23 @@
5
5
  # SPDX-License-Identifier: AGPL-3.0-or-later
6
6
  #++
7
7
 
8
+ require "rake/tasklib"
9
+ require "minitest/test_task"
10
+
8
11
  # Minitest task for pure Ruby gems.
9
12
  #
10
13
  # Consumer gems need test running. This provides a simple Minitest::TestTask
11
14
  # that discovers tests in the standard locations. Gems with Rust extensions
12
15
  # should define their own test task that includes cargo:test.
16
+ class TestTasks < Rake::TaskLib # :nodoc:
17
+ def initialize
18
+ super
19
+ define
20
+ end
13
21
 
14
- require "minitest/test_task"
15
-
16
- Minitest::TestTask.create(:test) do |t|
17
- t.test_globs = ["test/**/*_test.rb", "test/**/test_*.rb"]
22
+ private def define
23
+ Minitest::TestTask.create(:test) do |t|
24
+ t.test_globs = ["test/**/*_test.rb", "test/**/test_*.rb"]
25
+ end
26
+ end
18
27
  end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ #--
4
+ # SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
5
+ # SPDX-License-Identifier: AGPL-3.0-or-later
6
+ #++
7
+
8
+ require "fileutils"
9
+
10
+ # A version's source, built with the Rakefile, tasks, and bundle of the gem
11
+ # building the site.
12
+ class HostedSourceTree < Data.define(:path, :gemfile) # :nodoc:
13
+ def self.adopt(path)
14
+ FileUtils.cp("Rakefile", File.join(path, "Rakefile"))
15
+ FileUtils.cp_r("tasks", File.join(path, "tasks")) if Dir.exist?("tasks")
16
+ new(path:, gemfile: File.absolute_path("Gemfile"))
17
+ end
18
+
19
+ # Bundler hands its lockfile down with its Gemfile, and resolves either one
20
+ # against the other.
21
+ def run(command, env = {})
22
+ system(env.merge("BUNDLE_GEMFILE" => gemfile, "BUNDLE_LOCKFILE" => "#{gemfile}.lock"), command, chdir: path)
23
+ end
24
+ end
@@ -44,10 +44,7 @@ class IndexPage
44
44
  template_path = File.expand_path("../resources/index.html.erb", __dir__)
45
45
  template = File.read(template_path)
46
46
 
47
- versions = @versions
48
- branding = @branding
49
- # project_name is used in the ERB
50
- html_content = ERB.new(template).result(binding)
47
+ html_content = ERB.new(template).result_with_hash(versions: @versions, branding: @branding, project_name:)
51
48
 
52
49
  File.write(path, html_content)
53
50
  end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ #--
4
+ # SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
5
+ # SPDX-License-Identifier: AGPL-3.0-or-later
6
+ #++
7
+
8
+ require "bundler"
9
+ require_relative "hosted_source_tree"
10
+
11
+ # A version's source, exported to a directory. It runs commands with the Ruby
12
+ # and bundle that version declares, so each version's docs build exactly as
13
+ # they did when it was released.
14
+ class SourceTree < Data.define(:path) # :nodoc:
15
+ def ruby
16
+ mise_ruby || ruby_version_file || gemfile_ruby || RUBY_VERSION
17
+ end
18
+
19
+ def run(command, env = {})
20
+ Bundler.with_unbundled_env do
21
+ system(env, "mise", "exec", "ruby@#{ruby}", "--", "sh", "-c", command, chdir: path)
22
+ end
23
+ end
24
+
25
+ # A bundle can stop installing after its release: a gem it locked gets
26
+ # yanked, or it names a gem by a path outside the exported source. Such a
27
+ # version builds with the bundle and tasks building the site instead.
28
+ def buildable(rdoc_floor)
29
+ return self if upgrade_rdoc_to(rdoc_floor) && run("bundle install --quiet")
30
+
31
+ puts " Its own bundle won't install, so it builds with this one..."
32
+ HostedSourceTree.adopt(path)
33
+ end
34
+
35
+ private def upgrade_rdoc_to(minimum)
36
+ return true if locked_rdoc && locked_rdoc >= Gem::Version.new(minimum)
37
+
38
+ File.write(File.join(path, "Gemfile"), %(\ngem "rdoc", "#{minimum}"\n), mode: "a")
39
+ run("bundle lock --update rdoc")
40
+ end
41
+
42
+ private def locked_rdoc
43
+ version = read("Gemfile.lock")&.[](/^ rdoc \(([^)]+)\)/, 1)
44
+ Gem::Version.new(version) if version
45
+ end
46
+
47
+ private def mise_ruby
48
+ read("mise.toml")&.[](/^ruby\s*=\s*"([^"]+)"/, 1)
49
+ end
50
+
51
+ private def ruby_version_file
52
+ read(".ruby-version")&.strip&.then { |version| version unless version.empty? }
53
+ end
54
+
55
+ private def gemfile_ruby
56
+ read("Gemfile")&.[](/^ruby\s+["']([^"']+)["']/, 1)
57
+ end
58
+
59
+ private def read(name)
60
+ file = File.join(path, name)
61
+ File.read(file) if File.exist?(file)
62
+ end
63
+ end
@@ -6,6 +6,7 @@
6
6
  #++
7
7
 
8
8
  require_relative "../rdoc_config"
9
+ require_relative "source_tree"
9
10
 
10
11
  # Builds documentation for a single version.
11
12
  #
@@ -19,6 +20,12 @@ require_relative "../rdoc_config"
19
20
  #
20
21
  # Use it to build one version's documentation within a multi-version site.
21
22
  class VersionedDocumentation
23
+ # Earlier releases locked RDoc 6.15 or 7.0, which render some markup wrongly
24
+ # and predate the Aliki theme the site relies on. 7.2.0 is the oldest RDoc
25
+ # whose output the site accepts; a version locking a newer one builds with
26
+ # its own.
27
+ RDOC_FLOOR = "7.2.0"
28
+
22
29
  # Creates a VersionedDocumentation builder.
23
30
  #
24
31
  # [version] Version object to build docs for.
@@ -39,16 +46,12 @@ class VersionedDocumentation
39
46
  puts "Building documentation for #{@version.name}..."
40
47
 
41
48
  absolute_path = File.absolute_path(path)
42
- gemfile_path = File.absolute_path("Gemfile")
43
49
  custom_css_path = File.absolute_path("doc/custom.css")
44
- rakefile_path = File.absolute_path("Rakefile")
45
- tasks_dir_path = File.absolute_path("tasks")
46
50
 
47
51
  @version.checkout(globs:) do |source_path|
48
- # Copy current Rakefile and tasks into the temp directory
49
- # This ensures all versions use the latest example generation logic
50
- FileUtils.cp(rakefile_path, File.join(source_path, "Rakefile"))
51
- FileUtils.cp_r(tasks_dir_path, File.join(source_path, "tasks"))
52
+ # Each version builds with its own Ruby, bundle, and tasks where it can,
53
+ # so upgrading RDoc or the doc tasks on trunk doesn't change its docs.
54
+ tree = SourceTree.new(path: source_path).buildable(RDOC_FLOOR)
52
55
 
53
56
  Dir.chdir(source_path) do
54
57
  title = "#{project_name} #{@version.name}"
@@ -56,22 +59,20 @@ class VersionedDocumentation
56
59
 
57
60
  # Use rake rerdoc to ensure copy_examples runs
58
61
  # Set environment variables to override rdoc settings
59
- success = system(
62
+ success = tree.run(
63
+ "bundle exec rake rerdoc",
60
64
  {
61
- "BUNDLE_GEMFILE" => gemfile_path,
62
65
  "RDOC_OUTPUT" => absolute_path,
63
66
  "RDOC_TITLE" => title,
64
67
  "RDOC_CUSTOM_CSS" => custom_css_path,
65
- },
66
- "bundle exec rake rerdoc"
68
+ }
67
69
  )
68
70
 
69
71
  # Fall back to direct rdoc call if rake fails for any reason
70
72
  unless success
71
73
  puts " Rake task failed, falling back to direct rdoc call..."
72
74
  files = globs.flat_map { |glob| Dir[glob] }.uniq
73
- system(
74
- { "BUNDLE_GEMFILE" => gemfile_path },
75
+ tree.run(
75
76
  "bundle exec rdoc -o #{absolute_path} --main #{RDocConfig::MAIN} --title '#{title}' --template-stylesheets \"#{custom_css_path}\" #{files.join(' ')}"
76
77
  )
77
78
  end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ #--
4
+ # SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
5
+ # SPDX-License-Identifier: AGPL-3.0-or-later
6
+ #++
7
+
8
+ require "erb"
9
+ require "rake/tasklib"
10
+ require "fileutils"
11
+ require "tmpdir"
12
+ require_relative "rdoc_config"
13
+
14
+ # The task that builds a gem's documentation website.
15
+ class WebsiteTasks < Rake::TaskLib # :nodoc:
16
+ def initialize(gem)
17
+ super()
18
+ @gem = gem
19
+ define
20
+ end
21
+
22
+ private def define
23
+ namespace :website do
24
+ desc "Build documentation for trunk (current dir) and all git tags"
25
+ task :build do
26
+ require_relative "website/website"
27
+
28
+ spec = @gem.spec
29
+ globs = RDocConfig::RDOC_FILES + ["*.gemspec", "doc/images/**/*", "examples/**/*"]
30
+
31
+ # Allow projects to customize via website_config.rb in their tasks/ directory
32
+ config = if File.exist?("tasks/website_config.rb")
33
+ load File.expand_path("tasks/website_config.rb", Dir.pwd)
34
+ WebsiteConfig::CONFIG
35
+ else
36
+ {}
37
+ end
38
+
39
+ Website.new(
40
+ at: config[:output_dir] || "www",
41
+ project_name: spec.name,
42
+ globs:,
43
+ assets: config[:assets] || ["doc/images"],
44
+ branding: config[:branding] || {}
45
+ ).build
46
+ end
47
+ end
48
+ end
49
+ end
@@ -23,7 +23,7 @@ jobs:
23
23
  CI: "true"
24
24
  BINDGEN_EXTRA_CLANG_ARGS: "-include stdbool.h"
25
25
  steps:
26
- - uses: actions/checkout@v4
26
+ - uses: actions/checkout@v6
27
27
 
28
28
  - name: Override Ruby version in mise.toml
29
29
  shell: bash
@@ -47,7 +47,7 @@ jobs:
47
47
  rustup target add x86_64-pc-windows-gnu
48
48
 
49
49
  - name: Install toolchain via mise
50
- uses: jdx/mise-action@v2
50
+ uses: jdx/mise-action@v4
51
51
 
52
52
  - name: Setup (Unix)
53
53
  if: runner.os != 'Windows'
@@ -63,7 +63,7 @@ jobs:
63
63
  run: mise x -- bundle exec rake
64
64
 
65
65
  - name: Upload compiled binary
66
- uses: actions/upload-artifact@v4
66
+ uses: actions/upload-artifact@v7
67
67
  with:
68
68
  name: native-${{ matrix.os }}-ruby${{ matrix.ruby }}
69
69
  path: lib/<%= ext_name %>/<%= ext_name %>.*
@@ -78,7 +78,7 @@ jobs:
78
78
  matrix:
79
79
  os: [ubuntu-latest, macos-latest, windows-latest]
80
80
  steps:
81
- - uses: actions/checkout@v4
81
+ - uses: actions/checkout@v6
82
82
 
83
83
  - name: Install Ruby via RubyInstaller (Windows)
84
84
  if: runner.os == 'Windows'
@@ -93,7 +93,7 @@ jobs:
93
93
 
94
94
  - name: Install toolchain via mise (Unix)
95
95
  if: runner.os != 'Windows'
96
- uses: jdx/mise-action@v2
96
+ uses: jdx/mise-action@v4
97
97
 
98
98
  - name: Configure Windows mise (skip Ruby)
99
99
  if: runner.os == 'Windows'
@@ -103,21 +103,27 @@ jobs:
103
103
 
104
104
  - name: Install toolchain via mise (Windows)
105
105
  if: runner.os == 'Windows'
106
- uses: jdx/mise-action@v2
106
+ uses: jdx/mise-action@v4
107
107
 
108
108
  <%- rubies.map { |r| r.split(".")[0..1].join(".") }.uniq.each do |minor| -%>
109
109
  - name: Download Ruby <%= minor %> binary
110
- uses: actions/download-artifact@v4
110
+ uses: actions/download-artifact@v8
111
111
  with:
112
112
  name: native-${{ matrix.os }}-ruby<%= minor %>
113
113
  path: lib/<%= ext_name %>/<%= minor %>
114
114
 
115
115
  <%- end -%>
116
+ - name: Install gems
117
+ run: |
118
+ mise x -- bundle config set --local path vendor/bundle
119
+ mise x -- bundle config set --local frozen true
120
+ mise x -- bundle install
121
+
116
122
  - name: Build platform gem
117
- run: ruby tasks/release/platform_gem.rb
123
+ run: mise x -- bundle exec rake release:platform_gem
118
124
 
119
125
  - name: Upload gem artifact
120
- uses: actions/upload-artifact@v4
126
+ uses: actions/upload-artifact@v7
121
127
  with:
122
128
  name: gem-${{ matrix.os }}
123
129
  path: pkg/*.gem
@@ -28,7 +28,7 @@ jobs:
28
28
  BINDGEN_EXTRA_CLANG_ARGS: "-include stdbool.h"
29
29
  <%- end -%>
30
30
  steps:
31
- - uses: actions/checkout@v4
31
+ - uses: actions/checkout@v6
32
32
 
33
33
  - name: Override Ruby version in mise.toml
34
34
  shell: bash
@@ -61,7 +61,7 @@ jobs:
61
61
 
62
62
  <%- end -%>
63
63
  - name: Install toolchain via mise
64
- uses: jdx/mise-action@v2
64
+ uses: jdx/mise-action@v4
65
65
 
66
66
  - name: Setup (Unix)
67
67
  if: runner.os != 'Windows'
@@ -1,4 +1,4 @@
1
- # SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
1
+ # SPDX-FileCopyrightText: <%= Time.now.year %> <%= copyright_holder %>
2
2
  # SPDX-License-Identifier: AGPL-3.0-or-later
3
3
 
4
4
  **/.idea/
@@ -11,6 +11,7 @@
11
11
  /pkg/
12
12
  /spec/reports/
13
13
  /tmp/
14
+ /vendor/bundle/
14
15
  /www/
15
16
  <%- if has_rust -%>
16
17
  /ext/<%= gem_name %>/target/
@@ -7,4 +7,4 @@ inherit_gem:
7
7
  <%= gem_name %>: lib/<%= require_path %>/rubocop.yml
8
8
 
9
9
  AllCops:
10
- TargetRubyVersion: "3.2"
10
+ TargetRubyVersion: "3.3"
@@ -55,7 +55,7 @@ Description: <%= description %>
55
55
 
56
56
  ### Ruby Standards
57
57
 
58
- - Use `Data.define` for all value objects (Ruby 3.2+). (Prefer `class Foo < Data.define()` over `Foo = Data.define() do`).
58
+ - Use `Data.define` for all value objects (Ruby 3.3+). (Prefer `class Foo < Data.define()` over `Foo = Data.define() do`).
59
59
  - Define types in `.rbs` files. Don't use `untyped` just because it's easy; be comprehensive and accurate. Do not include `initialize` in `.rbs` files; use `self.new` for constructors instead.
60
60
  - Every public Ruby class/method must be documented for humans in RDoc (preferred)--**not** YARD--or markdown files (fallback), and must have `*.rbs` types defined.
61
61
  - Every significant architectural and design decision must be documented for contributors in markdown files. Mermaid is allowed.
@@ -1,5 +1,5 @@
1
1
  <!--
2
- SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
2
+ SPDX-FileCopyrightText: <%= Time.now.year %> <%= copyright_holder %>
3
3
  SPDX-License-Identifier: CC-BY-SA-4.0
4
4
  -->
5
5
 
@@ -16,3 +16,5 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
16
16
  ### Added
17
17
 
18
18
  - Initial release of <%= gem_name %>
19
+
20
+ [Unreleased]: https://github.com/<%= github_repo %>/tree/HEAD
@@ -23,7 +23,7 @@ Clone the repository and run the setup script for your platform.
23
23
 
24
24
  <!-- SPDX-SnippetBegin -->
25
25
  <!--
26
- SPDX-FileCopyrightText: <%= Time.now.year %> <%= copyright_holder %>
26
+ SPDX-SnippetCopyrightText: <%= Time.now.year %> <%= copyright_holder %>
27
27
  SPDX-License-Identifier: MIT-0
28
28
  -->
29
29
  ```sh
@@ -35,7 +35,7 @@ bin/setup
35
35
 
36
36
  <!-- SPDX-SnippetBegin -->
37
37
  <!--
38
- SPDX-FileCopyrightText: <%= Time.now.year %> <%= copyright_holder %>
38
+ SPDX-SnippetCopyrightText: <%= Time.now.year %> <%= copyright_holder %>
39
39
  SPDX-License-Identifier: MIT-0
40
40
  -->
41
41
  ```powershell
@@ -56,7 +56,7 @@ license checks, and the Steep type checker:
56
56
 
57
57
  <!-- SPDX-SnippetBegin -->
58
58
  <!--
59
- SPDX-FileCopyrightText: <%= Time.now.year %> <%= copyright_holder %>
59
+ SPDX-SnippetCopyrightText: <%= Time.now.year %> <%= copyright_holder %>
60
60
  SPDX-License-Identifier: MIT-0
61
61
  -->
62
62
  ```sh
@@ -14,12 +14,11 @@ gemspec
14
14
  gem "irb"
15
15
  gem "rake", "~> 13.0"
16
16
 
17
- gem "minitest", "~> 5.16"
17
+ gem "minitest", "~> 6.0"
18
18
 
19
19
  gem "rubocop", "~> 1.21"
20
- gem "rubycritic", "~> 4.11"
20
+ gem "rubycritic", "~> 5.0"
21
21
  gem "inch", "~> 0.4"
22
- gem "flog", "4.8.0"
23
22
 
24
23
  gem "nokogiri" # For RDoc sidebar post-processing
25
24
  gem "faker" # For realistic example data
@@ -20,11 +20,11 @@ Announcements](https://img.shields.io/badge/forum-announcements-3b44ac.svg?logo=
20
20
  **ratatui_ruby** is a community wrapper that is not affiliated with [the Ratatui team](https://github.com/orgs/ratatui/people).
21
21
 
22
22
  > [!WARNING]
23
- > **<%= gem_name %>** is currently in **PRE-RELEASE**. The API will change rapidly, even between minor and patch versions.
23
+ > **<%= gem_name %>** is in **initial development**, before 1.0. Its API can change in any release, even a patch.
24
24
 
25
25
  **[Why RatatuiRuby?](https://www.ratatui-ruby.dev/docs/trunk/doc/getting_started/why_md.html)** — Native Rust performance, zero runtime overhead, and Ruby's expressiveness. [See how we compare](https://www.ratatui-ruby.dev/docs/trunk/doc/getting_started/why_md.html) to CharmRuby, raw Rust, and Go.
26
26
 
27
- Please follow the [announcements](https://forum.setdef.com/tags/c/<%= gem_name.tr('_', '-') %>/announcement) to stay up-to-date on new releases. See the [`trunk` branch](https://github.com/<%= github_repo %>/tree/trunk) for pre-release updates.
27
+ Please follow the [announcements](https://forum.setdef.com/tags/c/<%= gem_name.tr('_', '-') %>/announcement) to stay up-to-date on new releases. See the [`trunk` branch](https://github.com/<%= github_repo %>/tree/trunk) for unreleased changes.
28
28
 
29
29
  ----
30
30
 
@@ -78,7 +78,7 @@ Add this line to your application's Gemfile:
78
78
 
79
79
  <!-- SPDX-SnippetBegin -->
80
80
  <!--
81
- SPDX-FileCopyrightText: <%= Time.now.year %> <%= author %>
81
+ SPDX-SnippetCopyrightText: <%= Time.now.year %> <%= copyright_holder %>
82
82
  SPDX-License-Identifier: MIT-0
83
83
  -->
84
84
  ```ruby
@@ -90,7 +90,7 @@ And then execute:
90
90
 
91
91
  <!-- SPDX-SnippetBegin -->
92
92
  <!--
93
- SPDX-FileCopyrightText: <%= Time.now.year %> <%= author %>
93
+ SPDX-SnippetCopyrightText: <%= Time.now.year %> <%= copyright_holder %>
94
94
  SPDX-License-Identifier: MIT-0
95
95
  -->
96
96
  ```bash
@@ -102,7 +102,7 @@ Or install it yourself with:
102
102
 
103
103
  <!-- SPDX-SnippetBegin -->
104
104
  <!--
105
- SPDX-FileCopyrightText: <%= Time.now.year %> <%= author %>
105
+ SPDX-SnippetCopyrightText: <%= Time.now.year %> <%= copyright_holder %>
106
106
  SPDX-License-Identifier: MIT-0
107
107
  -->
108
108
  ```bash
@@ -113,14 +113,14 @@ gem install <%= gem_name %>
113
113
 
114
114
  ## Usage
115
115
 
116
- _Because this gem is in pre-release, it lacks documentation. Please check the source files.
116
+ _Because this gem is in initial development, it lacks documentation. Please check the source files.
117
117
 
118
118
  For a full tutorial, see [the Quickstart](./doc/getting_started/quickstart.md). For an explanation of the application architecture, see [Application Architecture](./doc/concepts/application_architecture.md).
119
119
 
120
120
 
121
121
  ## Features
122
122
 
123
- _Because this gem is in pre-release, it lacks documentation. Please check the source files.
123
+ _Because this gem is in initial development, it lacks documentation. Please check the source files.
124
124
 
125
125
 
126
126
  ## Documentation
@@ -29,5 +29,5 @@ SPDX-License-Identifier = "<%= license %>"
29
29
 
30
30
  [[annotations]]
31
31
  path = 'doc/images/*'
32
- SPDX-FileCopyrightText = "2026 Kerrick Long <me@kerricklong.com>"
32
+ SPDX-FileCopyrightText = "<%= Time.now.year %> <%= copyright_holder %>"
33
33
  SPDX-License-Identifier = "CC-BY-SA-4.0"
@@ -17,9 +17,13 @@ mise install
17
17
  <%- if has_rust -%>
18
18
  mise x -- rustup component add rustfmt clippy
19
19
  <%- end -%>
20
- mise x -- pip install reuse
20
+ mise x -- pip install 'reuse[charset-normalizer]'
21
21
  mise x -- gem install bundler:4.0.3
22
22
 
23
+ # A gem in the per-user gem directory may have been built for another Ruby,
24
+ # so install the bundle inside the repo instead.
25
+ mise x -- bundle config set --local path vendor/bundle
26
+
23
27
  if [ "${CI:-}" = "true" ]; then
24
28
  bundle config set --local frozen 'true'
25
29
  fi
@@ -66,7 +66,7 @@ mise install
66
66
  mise x -- rustup target add x86_64-pc-windows-gnu
67
67
  mise x -- rustup component add rustfmt clippy
68
68
  <%- end -%>
69
- mise x -- python -m pip install reuse
69
+ mise x -- python -m pip install 'reuse[charset-normalizer]'
70
70
 
71
71
  # pip installs scripts (like reuse.exe) to Python's Scripts directory,
72
72
  # which mise does not add to PATH.
@@ -91,6 +91,10 @@ CARGO_BUILD_TARGET = "x86_64-pc-windows-gnu"
91
91
  }
92
92
  gem install bundler:4.0.3
93
93
 
94
+ # A gem in the per-user gem directory may have been built for another Ruby,
95
+ # so install the bundle inside the repo instead.
96
+ bundle config set --local path vendor/bundle
97
+
94
98
  if ($env:CI -eq "true") {
95
99
  bundle config set --local frozen true
96
100
  }
@@ -9,8 +9,8 @@ Architect robust TUI applications using core library patterns and API best pract
9
9
 
10
10
  ## Core Concepts
11
11
 
12
- _Because this gem is in pre-release, it lacks documentation. Please check the source files._
12
+ _Because this gem is in initial development, it lacks documentation. Please check the source files._
13
13
 
14
14
  ## Thread and Ractor Safety
15
15
 
16
- _Because this gem is in pre-release, it lacks documentation. Please check the source files._
16
+ _Because this gem is in initial development, it lacks documentation. Please check the source files._
@@ -20,7 +20,7 @@ First, require the test helper in your test file or `test_helper.rb`:
20
20
 
21
21
  <!-- SPDX-SnippetBegin -->
22
22
  <!--
23
- SPDX-FileCopyrightText: <%= Time.now.year %> <%= author %>
23
+ SPDX-SnippetCopyrightText: <%= Time.now.year %> <%= copyright_holder %>
24
24
  SPDX-License-Identifier: MIT-0
25
25
  -->
26
26
  ```ruby
@@ -33,7 +33,7 @@ Then, include the module in your test class:
33
33
 
34
34
  <!-- SPDX-SnippetBegin -->
35
35
  <!--
36
- SPDX-FileCopyrightText: <%= Time.now.year %> <%= author %>
36
+ SPDX-SnippetCopyrightText: <%= Time.now.year %> <%= copyright_holder %>
37
37
  SPDX-License-Identifier: MIT-0
38
38
  -->
39
39
  ```ruby
@@ -46,4 +46,4 @@ end
46
46
 
47
47
  ## Writing Tests
48
48
 
49
- _Because this gem is in pre-release, it lacks documentation. Please check the source files and automated tests._
49
+ _Because this gem is in initial development, it lacks documentation. Please check the source files and automated tests._
@@ -17,11 +17,11 @@ See [Installation in the README](../README.md#installation) for setup instructio
17
17
 
18
18
  Here is a "Hello World" application that demonstrates the core lifecycle of a **<%= gem_name %>** app.
19
19
 
20
- _Because this gem is in pre-release, it lacks documentation. Please check the source files.
20
+ _Because this gem is in initial development, it lacks documentation. Please check the source files.
21
21
 
22
22
  #### How it works
23
23
 
24
- _Because this gem is in pre-release, it lacks documentation. Please check the source files.
24
+ _Because this gem is in initial development, it lacks documentation. Please check the source files.
25
25
 
26
26
  ## Examples
27
27
 
@@ -33,7 +33,7 @@ Focused examples for individual concepts. Each demonstrates a single concept and
33
33
 
34
34
  | Widget | What it demonstrates |
35
35
  |--------|---------------------|
36
- | _Automated Tests_ | _Because this gem is in pre-release, it lacks documentation. Please check the automated tests for details._ |
36
+ | _Automated Tests_ | _Because this gem is in initial development, it lacks documentation. Please check the automated tests for details._ |
37
37
 
38
38
  ### Sample Applications
39
39
 
@@ -41,7 +41,7 @@ These larger examples combine concepts into complete applications, demonstrating
41
41
 
42
42
  | Application | Architecture | What you'll learn |
43
43
  |-------------|--------------|-------------------|
44
- | _Automated Tests_ | _Because this gem is in pre-release, it lacks documentation. Please check the automated tests for details._ |
44
+ | _Automated Tests_ | _Because this gem is in initial development, it lacks documentation. Please check the automated tests for details._ |
45
45
 
46
46
 
47
47
  ## Next Steps
@@ -12,7 +12,7 @@ edition = "2021"
12
12
  crate-type = ["cdylib", "staticlib"]
13
13
 
14
14
  [dependencies]
15
- magnus = "0.8"
15
+ magnus = "0.9"
16
16
  ratatui = { version = "0.30", features = ["widget-calendar", "layout-cache", "unstable-rendered-line-info"] }
17
17
 
18
18
  # Optional: Arena allocation to avoid Box::leak for long-lived Ruby objects
@@ -54,7 +54,7 @@ Gem::Specification.new do |spec|
54
54
 
55
55
  spec.add_dependency "ratatui_ruby"
56
56
  spec.add_development_dependency "ostruct", "~> 0.6"
57
- spec.add_development_dependency "rdoc", "~> 7.0"
57
+ spec.add_development_dependency "rdoc", "~> 8.1"
58
58
  spec.add_development_dependency "faker", "~> 3.5"
59
59
  spec.add_development_dependency "minitest-mock"
60
60
  spec.add_development_dependency "steep"
@@ -4,9 +4,9 @@
4
4
  <%# REUSE-IgnoreEnd -%>
5
5
 
6
6
  [tools]
7
- ruby = "4.0.1"
7
+ ruby = "4.0.7"
8
8
  <%- if has_rust -%>
9
- rust = "1.91.1"
9
+ rust = "1.99.0"
10
10
  <%- end -%>
11
11
  python = "3.12"
12
- pre-commit = "latest"
12
+ "pipx:pre-commit" = "latest"
@@ -8,6 +8,6 @@
8
8
  module RatatuiRuby
9
9
  module Devtools
10
10
  # Current version of the ratatui_ruby-devtools gem.
11
- VERSION = "0.2.1"
11
+ VERSION = "0.4.0"
12
12
  end
13
13
  end