ratatui_ruby-ui 0.1.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.
data/README.md ADDED
@@ -0,0 +1,124 @@
1
+ <!--
2
+ SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
3
+ SPDX-License-Identifier: CC-BY-SA-4.0
4
+ -->
5
+ # ratatui_ruby-ui
6
+
7
+ [![
8
+ builds.sr.ht status](https://builds.sr.ht/~kerrick/ratatui_ruby-ui.svg)](https://builds.sr.ht/~kerrick/ratatui_ruby-ui?) [![
9
+ License](https://img.shields.io/badge/dynamic/regex?url=https%3A%2F%2Fgit.sr.ht%2F~kerrick%2Fratatui_ruby-ui%2Fblob%2Fstable%2Fratatui_ruby-ui.gemspec&search=spec%5C.license%20%3D%20%22(.*)%22&replace=%241&label=License&color=a2c93e)](https://spdx.org/licenses/AGPL-3.0-or-later.html) [![
10
+ Gem Total Downloads](https://img.shields.io/gem/dt/ratatui_ruby-ui)](https://rubygems.org/gems/ratatui_ruby-ui) [![
11
+ Gem Version](https://img.shields.io/gem/v/ratatui_ruby-ui)](https://rubygems.org/gems/ratatui_ruby-ui) [![
12
+ Mailing List: Discussion](https://img.shields.io/badge/mailing_list-discussion-5865F2.svg?logo=data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9IiNmZmZmZmYiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBjbGFzcz0iaWNvbiBpY29uLXRhYmxlciBpY29ucy10YWJsZXItb3V0bGluZSBpY29uLXRhYmxlci1tYWlsIj48cGF0aCBzdHJva2U9Im5vbmUiIGQ9Ik0wIDBoMjR2MjRIMHoiIGZpbGw9Im5vbmUiLz48cGF0aCBkPSJNMyA3YTIgMiAwIDAgMSAyIC0yaDE0YTIgMiAwIDAgMSAyIDJ2MTBhMiAyIDAgMCAxIC0yIDJoLTE0YTIgMiAwIDAgMSAtMiAtMnYtMTB6IiAvPjxwYXRoIGQ9Ik0zIDdsOSA2bDkgLTYiIC8+PC9zdmc+Cg==)](https://lists.sr.ht/~kerrick/ratatui_ruby-discuss) [![
13
+ Mailing List: Development](https://img.shields.io/badge/mailing_list-development-4954d5.svg?logo=data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9IiNmZmZmZmYiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBjbGFzcz0iaWNvbiBpY29uLXRhYmxlciBpY29ucy10YWJsZXItb3V0bGluZSBpY29uLXRhYmxlci1tYWlsIj48cGF0aCBzdHJva2U9Im5vbmUiIGQ9Ik0wIDBoMjR2MjRIMHoiIGZpbGw9Im5vbmUiLz48cGF0aCBkPSJNMyA3YTIgMiAwIDAgMSAyIC0yaDE0YTIgMiAwIDAgMSAyIDJ2MTBhMiAyIDAgMCAxIC0yIDJoLTE0YTIgMiAwIDAgMSAtMiAtMnYtMTB6IiAvPjxwYXRoIGQ9Ik0zIDdsOSA2bDkgLTYiIC8+PC9zdmc+Cg==)](https://lists.sr.ht/~kerrick/ratatui_ruby-devel) [![
14
+ Mailing List: Announcements](https://img.shields.io/badge/mailing_list-announcements-3b44ac.svg?logo=data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0IiBmaWxsPSJub25lIiBzdHJva2U9IiNmZmZmZmYiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBjbGFzcz0iaWNvbiBpY29uLXRhYmxlciBpY29ucy10YWJsZXItb3V0bGluZSBpY29uLXRhYmxlci1tYWlsIj48cGF0aCBzdHJva2U9Im5vbmUiIGQ9Ik0wIDBoMjR2MjRIMHoiIGZpbGw9Im5vbmUiLz48cGF0aCBkPSJNMyA3YTIgMiAwIDAgMSAyIC0yaDE0YTIgMiAwIDAgMSAyIDJ2MTBhMiAyIDAgMCAxIC0yIDJoLTE0YTIgMiAwIDAgMSAtMiAtMnYtMTB6IiAvPjxwYXRoIGQ9Ik0zIDdsOSA2bDkgLTYiIC8+PC9zdmc+Cg==)](https://lists.sr.ht/~kerrick/ratatui_ruby-announce)
15
+
16
+
17
+ ## Introduction
18
+
19
+ **ratatui_ruby-ui** is a gem in the [RatatuiRuby ecosystem](https://sr.ht/~kerrick/ratatui_ruby/).
20
+ **ratatui_ruby** is a community wrapper that is not affiliated with [the Ratatui team](https://github.com/orgs/ratatui/people).
21
+
22
+ > [!WARNING]
23
+ > **ratatui_ruby-ui** is currently in **PRE-RELEASE**. The API will change rapidly, even between minor and patch versions.
24
+
25
+ **[Why RatatuiRuby?](https://man.sr.ht/~kerrick/ratatui_ruby/why.md)** — Native Rust performance, zero runtime overhead, and Ruby's expressiveness. [See how we compare](https://man.sr.ht/~kerrick/ratatui_ruby/why.md) to CharmRuby, raw Rust, and Go.
26
+
27
+ Please join the **announce** mailing list at https://lists.sr.ht/~kerrick/ratatui_ruby-announce to stay up-to-date on new releases and announcements. See the [`trunk` branch](https://git.sr.ht/~kerrick/ratatui_ruby-ui/tree/trunk) for pre-release updates.
28
+
29
+
30
+ ## Compatibility
31
+
32
+ **ratatui_ruby-ui** is designed to run on [everything Ruby does](https://www.ruby-lang.org/en/documentation/installation/), including:
33
+
34
+ - GNU/Linux, macOS, Windows, OpenBSD, and FreeBSD; and
35
+ - x86_64 (AMD, Intel) and ARM (Apple Silicon, Raspberry Pi).
36
+
37
+ We support the latest minor version of every
38
+ [non-eol Ruby version](https://www.ruby-lang.org/en/downloads/branches/),
39
+ including Ruby 4.
40
+
41
+
42
+ ## Installation
43
+
44
+ Add this line to your application's Gemfile:
45
+
46
+ <!-- SPDX-SnippetBegin -->
47
+ <!--
48
+ SPDX-FileCopyrightText: 2026 Kerrick Long
49
+ SPDX-License-Identifier: MIT-0
50
+ -->
51
+ ```ruby
52
+ gem "ratatui_ruby-ui"
53
+ ```
54
+ <!-- SPDX-SnippetEnd -->
55
+
56
+ And then execute:
57
+
58
+ <!-- SPDX-SnippetBegin -->
59
+ <!--
60
+ SPDX-FileCopyrightText: 2026 Kerrick Long
61
+ SPDX-License-Identifier: MIT-0
62
+ -->
63
+ ```bash
64
+ bundle install
65
+ ```
66
+ <!-- SPDX-SnippetEnd -->
67
+
68
+ Or install it yourself with:
69
+
70
+ <!-- SPDX-SnippetBegin -->
71
+ <!--
72
+ SPDX-FileCopyrightText: 2026 Kerrick Long
73
+ SPDX-License-Identifier: MIT-0
74
+ -->
75
+ ```bash
76
+ gem install ratatui_ruby-ui
77
+ ```
78
+ <!-- SPDX-SnippetEnd -->
79
+
80
+
81
+ ## Usage
82
+
83
+ _Because this gem is in pre-release, it lacks documentation. Please check the source files.
84
+
85
+ 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).
86
+
87
+
88
+ ## Features
89
+
90
+ _Because this gem is in pre-release, it lacks documentation. Please check the source files.
91
+
92
+
93
+ ## Documentation
94
+
95
+ | Resource | Description |
96
+ |----------|-------------|
97
+ | [Quickstart](./doc/getting_started/quickstart.md) | Get running in 5 minutes |
98
+ | [Application Architecture](./doc/concepts/application_architecture.md) | Patterns for scaling your app |
99
+ | [Guides](./doc/index.md) | Tutorials, examples, and more |
100
+ | API Reference | To generate full RDoc documentation, run `bundle exec rake rdoc` |
101
+ | [Wiki](https://man.sr.ht/~kerrick/ratatui_ruby) | Learn more about the RatatuiRuby ecosystem |
102
+
103
+
104
+ ## Contributing
105
+
106
+ Bug reports and pull requests are welcome on [sourcehut](https://sourcehut.org) at https://sr.ht/~kerrick/ratatui_ruby/. This project is intended to be a safe, productive collaboration, and contributors are expected to adhere to the [Code of Conduct](https://man.sr.ht/~kerrick/ratatui_ruby/code_of_conduct.md).
107
+
108
+
109
+ Want to help develop **ratatui_ruby-ui**? Check out the [contribution guide on the wiki](https://man.sr.ht/~kerrick/ratatui_ruby/contributing.md).
110
+
111
+ **Note**: Active development happens on the `trunk` branch. Use `trunk` if you are a contributor or want the latest cutting-edge features. `stable` is for stable releases only.
112
+
113
+
114
+ ## Copyright & License
115
+
116
+ **ratatui_ruby-ui** is copyright 2026, Kerrick Long.
117
+
118
+ The library is [AGPL-3.0-or-later](./LICENSES/AGPL-3.0-or-later.txt). Documentation snippets and widget examples are [MIT-0](./LICENSES/MIT-0.txt): copy and use them without attribution.
119
+
120
+ Documentation is [CC-BY-SA-4.0](./LICENSES/CC-BY-SA-4.0.txt). Build tooling and full app examples are [AGPL-3.0-or-later](./LICENSES/AGPL-3.0-or-later.txt). See each file's SPDX comment for specifics.
121
+
122
+ Some parts of this program are copied from other sources under appropriate reuse licenses, and the copyright belongs to their respective owners. See the [REUSE Specification – Version 3.3](https://reuse.software/spec-3.3/) for details.
123
+
124
+ This program was created with significant assistance from multiple LLMs. The process was human-controlled through creative prompts, with human contributions to each commit. See commit footers for model attribution. [declare-ai.org](https://declare-ai.org/1.0.0/creative.html)
data/REUSE.toml ADDED
@@ -0,0 +1,24 @@
1
+ # SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
2
+ # SPDX-License-Identifier: AGPL-3.0-or-later
3
+
4
+ version = 1
5
+
6
+ [[annotations]]
7
+ path = 'Gemfile.lock'
8
+ SPDX-FileCopyrightText = "2026 Kerrick Long <me@kerricklong.com>"
9
+ SPDX-License-Identifier = "CC0-1.0"
10
+
11
+ [[annotations]]
12
+ path = '**/snapshots/*.txt'
13
+ SPDX-FileCopyrightText = "2026 Kerrick Long <me@kerricklong.com>"
14
+ SPDX-License-Identifier = "AGPL-3.0-or-later"
15
+
16
+ [[annotations]]
17
+ path = '**/snapshots/*.ansi'
18
+ SPDX-FileCopyrightText = "2026 Kerrick Long <me@kerricklong.com>"
19
+ SPDX-License-Identifier = "AGPL-3.0-or-later"
20
+
21
+ [[annotations]]
22
+ path = 'doc/images/*'
23
+ SPDX-FileCopyrightText = "2026 Kerrick Long <me@kerricklong.com>"
24
+ SPDX-License-Identifier = "CC-BY-SA-4.0"
data/Rakefile ADDED
@@ -0,0 +1,16 @@
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/gem_tasks"
9
+ require "ratatui_ruby/devtools"
10
+
11
+ RatatuiRuby::Devtools.install!
12
+
13
+ # Import project-specific tasks
14
+ Dir.glob("tasks/*.rake").each { |r| import r }
15
+
16
+ task default: %w[lint:fix test lint reuse]
@@ -0,0 +1,16 @@
1
+ <!--
2
+ SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
3
+ SPDX-License-Identifier: CC-BY-SA-4.0
4
+ -->
5
+
6
+ # Application Architecture
7
+
8
+ Architect robust TUI applications using core library patterns and API best practices.
9
+
10
+ ## Core Concepts
11
+
12
+ _Because this gem is in pre-release, it lacks documentation. Please check the source files._
13
+
14
+ ## Thread and Ractor Safety
15
+
16
+ _Because this gem is in pre-release, it lacks documentation. Please check the source files._
@@ -0,0 +1,49 @@
1
+ <!--
2
+ SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
3
+ SPDX-License-Identifier: CC-BY-SA-4.0
4
+ -->
5
+ # Application Testing Guide
6
+
7
+ This guide explains how to test your RatatuiRuby applications using the provided `RatatuiRuby::TestHelper`.
8
+
9
+ ## Overview
10
+
11
+ You need to verify that your application looks and behaves correctly. Manually checking every character on a terminal screen is tedious. Dealing with race conditions and complex state management in tests creates friction.
12
+
13
+ The `TestHelper` module solves this. It provides a headless "test terminal" to capture output and a suite of robust assertions to verify state.
14
+
15
+ Use it to write fast, deterministic tests for your TUI applications.
16
+
17
+ ## Setup
18
+
19
+ First, require the test helper in your test file or `test_helper.rb`:
20
+
21
+ <!-- SPDX-SnippetBegin -->
22
+ <!--
23
+ SPDX-FileCopyrightText: 2026 Kerrick Long
24
+ SPDX-License-Identifier: MIT-0
25
+ -->
26
+ ```ruby
27
+ require "ratatui_ruby/test_helper"
28
+ require "minitest/autorun" # or your preferred test framework
29
+ ```
30
+ <!-- SPDX-SnippetEnd -->
31
+
32
+ Then, include the module in your test class:
33
+
34
+ <!-- SPDX-SnippetBegin -->
35
+ <!--
36
+ SPDX-FileCopyrightText: 2026 Kerrick Long
37
+ SPDX-License-Identifier: MIT-0
38
+ -->
39
+ ```ruby
40
+ class MyApplicationTest < Minitest::Test
41
+ include RatatuiRuby::TestHelper
42
+ # ...
43
+ end
44
+ ```
45
+ <!-- SPDX-SnippetEnd -->
46
+
47
+ ## Writing Tests
48
+
49
+ _Because this gem is in pre-release, it lacks documentation. Please check the source files and automated tests._
data/doc/custom.css ADDED
@@ -0,0 +1,22 @@
1
+ /*
2
+ * SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
3
+ * SPDX-License-Identifier: AGPL-3.0-or-later
4
+ */
5
+
6
+ img {
7
+ max-width: 100%;
8
+ height: auto;
9
+ }
10
+
11
+ .theme-toggle {
12
+ margin-left: 0 !important;
13
+ }
14
+
15
+ /* Terminal Previews (Native PNGs)
16
+ * The images already contain the window chrome and shadows.
17
+ * We just need to center them and ensure they scale down on mobile.
18
+ */
19
+ img[src*="images/"] {
20
+ display: block;
21
+ margin: 2em auto;
22
+ }
@@ -0,0 +1,56 @@
1
+ <!--
2
+ SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
3
+ SPDX-License-Identifier: CC-BY-SA-4.0
4
+ -->
5
+ # Quickstart
6
+
7
+ Welcome to **ratatui_ruby-ui**! This guide will help you get up and running with your first Terminal User Interface in Ruby.
8
+
9
+ ## Installation
10
+
11
+ See [Installation in the README](../README.md#installation) for setup instructions.
12
+
13
+
14
+ ## Tutorials
15
+
16
+ ### Basic Application
17
+
18
+ Here is a "Hello World" application that demonstrates the core lifecycle of a **ratatui_ruby-ui** app.
19
+
20
+ _Because this gem is in pre-release, it lacks documentation. Please check the source files.
21
+
22
+ #### How it works
23
+
24
+ _Because this gem is in pre-release, it lacks documentation. Please check the source files.
25
+
26
+ ## Examples
27
+
28
+ These examples showcase the full power of **ratatui_ruby-ui**. You can find their source code in the [examples directory](../examples).
29
+
30
+ ### Widget Demos
31
+
32
+ Focused examples for individual concepts. Each demonstrates a single concept and ways to interact with it.
33
+
34
+ | Widget | What it demonstrates |
35
+ |--------|---------------------|
36
+ | _Automated Tests_ | _Because this gem is in pre-release, it lacks documentation. Please check the automated tests for details._ |
37
+
38
+ ### Sample Applications
39
+
40
+ These larger examples combine concepts into complete applications, demonstrating real-world TUI patterns and architectures.
41
+
42
+ | Application | Architecture | What you'll learn |
43
+ |-------------|--------------|-------------------|
44
+ | _Automated Tests_ | _Because this gem is in pre-release, it lacks documentation. Please check the automated tests for details._ |
45
+
46
+
47
+ ## Next Steps
48
+
49
+ Now that you've seen what **ratatui_ruby-ui** can do:
50
+
51
+ - **Deep dive**: Read the [Application Architecture](../concepts/application_architecture.md) guide for scaling patterns
52
+ - **Test your TUI**: See the [Testing Guide](../concepts/application_testing.md) for snapshot and style assertions
53
+ - **Avoid common mistakes**: See [Terminal Output During TUI Sessions](https://man.sr.ht/~kerrick/ratatui_ruby/troubleshooting/tui_output.md) to prevent screen corruption
54
+ - **Explore the API**: Browse the [full documentation](../index.md)
55
+ - **Learn the philosophy**: Read [Why RatatuiRuby?](https://man.sr.ht/~kerrick/ratatui_ruby/why.md) for comparisons and design decisions
56
+ - **Get help**: Join the [discussion mailing list](https://lists.sr.ht/~kerrick/ratatui_ruby-discuss)
File without changes
data/doc/index.md ADDED
@@ -0,0 +1,25 @@
1
+ <!--
2
+ SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
3
+ SPDX-License-Identifier: CC-BY-SA-4.0
4
+ -->
5
+ # Start Here
6
+
7
+
8
+ ## Documentation for Users
9
+
10
+ - [README](../README.md): Project overview and installation
11
+
12
+ ### Getting Started
13
+
14
+ - [Why RatatuiRuby?](https://man.sr.ht/~kerrick/ratatui_ruby/why.md): Philosophy, comparisons, and what makes us different
15
+ - [Quickstart](./getting_started/quickstart.md): Build your first TUI app
16
+
17
+ ### Concepts
18
+
19
+ - [Application Architecture](./concepts/application_architecture.md): Lifecycle patterns and API choices
20
+ - [Testing Your Application](./concepts/application_testing.md): Snapshot testing and style assertions
21
+
22
+
23
+ ## Documentation for Contributors
24
+
25
+ - [Contributing Guidelines](https://man.sr.ht/~kerrick/ratatui_ruby/contributing.md): How to contribute patches and features
data/exe/.gitkeep ADDED
File without changes
@@ -0,0 +1,14 @@
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
+ module RatatuiRuby # :nodoc: Documented in the ratatui_ruby gem.
9
+ module Ui
10
+ # The version of this gem.
11
+ # See https://semver.org/spec/v2.0.0.html
12
+ VERSION = "0.1.0"
13
+ end
14
+ end
@@ -0,0 +1,21 @@
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_relative "ui/version"
9
+
10
+ # Entry point for the ratatui_ruby-ui gem.
11
+ #
12
+ # Ruby libraries benefit from a clear namespace. Gems need a central module.
13
+ #
14
+ # This module serves as the namespace root. All classes and utilities live here.
15
+ #
16
+ # Require this file to load the library.
17
+ module RatatuiRuby # :nodoc: Documented in the ratatui_ruby gem.
18
+ # Namespace for library functionality.
19
+ module Ui
20
+ end
21
+ end
data/mise.toml ADDED
@@ -0,0 +1,7 @@
1
+ # SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
2
+ # SPDX-License-Identifier: AGPL-3.0-or-later
3
+
4
+ [tools]
5
+ ruby = "4.0.0"
6
+ python = "3.12"
7
+ pre-commit = "latest"
@@ -0,0 +1,172 @@
1
+ <%#
2
+ SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
3
+ SPDX-License-Identifier: AGPL-3.0-or-later
4
+ %>
5
+ <!DOCTYPE html>
6
+ <html lang="en">
7
+ <head>
8
+ <meta charset="UTF-8">
9
+ <meta name="viewport" content="width=device-width, initial-scale=1">
10
+ <title><%= page_title %> - Example Viewer</title>
11
+
12
+ <script>
13
+ var rdoc_rel_prefix = "<%= doc_root_link.sub('index.html', '') %>";
14
+ var index_rel_prefix = "<%= '../' * (relative_path.split('/').size - 1) %>";
15
+ </script>
16
+
17
+ <script src="<%= '../' * (relative_path.split('/').size - 1) %>js/search_navigation.js" defer></script>
18
+ <script src="<%= '../' * (relative_path.split('/').size - 1) %>js/search_data.js" defer></script>
19
+ <script src="<%= '../' * (relative_path.split('/').size - 1) %>js/search_ranker.js" defer></script>
20
+ <script src="<%= '../' * (relative_path.split('/').size - 1) %>js/search_controller.js" defer></script>
21
+ <script src="<%= '../' * (relative_path.split('/').size - 1) %>js/aliki.js" defer></script>
22
+
23
+ <link href="<%= doc_root_link.sub('index.html', '') %>css/rdoc.css" rel="stylesheet">
24
+ <link href="<%= doc_root_link.sub('index.html', '') %>custom.css" rel="stylesheet">
25
+ </head>
26
+ <body class="file<%= ' has-toc' unless toc_items.empty? %>">
27
+ <%= icons_svg %>
28
+ <header class="top-navbar">
29
+ <div class="navbar-brand">
30
+ Example Viewer
31
+ </div>
32
+
33
+ <!-- Desktop search bar -->
34
+ <div class="navbar-search navbar-search-desktop" role="search">
35
+ <form action="#" method="get" accept-charset="utf-8">
36
+ <input id="search-field" role="combobox" aria-label="Search"
37
+ aria-autocomplete="list" aria-controls="search-results-desktop"
38
+ type="text" name="search" placeholder="Search (/) examples..."
39
+ spellcheck="false" autocomplete="off"
40
+ title="Type to search, Up and Down to navigate, Enter to load">
41
+ <ul id="search-results-desktop" aria-label="Search Results"
42
+ aria-busy="false" aria-expanded="false"
43
+ aria-atomic="false" class="initially-hidden search-results"></ul>
44
+ </form>
45
+ </div>
46
+
47
+ <!-- Mobile search icon button -->
48
+ <button id="search-toggle" class="navbar-search-mobile" aria-label="Open search" type="button">
49
+ <span aria-hidden="true">🔍</span>
50
+ </button>
51
+
52
+ <button id="theme-toggle" class="theme-toggle" aria-label="Switch to dark mode" type="button" onclick="cycleColorMode()">
53
+ <span class="theme-toggle-icon" aria-hidden="true">🌙</span>
54
+ </button>
55
+ </header>
56
+
57
+ <!-- Search Modal (Mobile) -->
58
+ <div id="search-modal" class="search-modal" hidden aria-modal="true" role="dialog" aria-label="Search">
59
+ <div class="search-modal-backdrop"></div>
60
+ <div class="search-modal-content">
61
+ <div class="search-modal-header">
62
+ <form class="search-modal-form" action="#" method="get" accept-charset="utf-8">
63
+ <span class="search-modal-icon" aria-hidden="true">🔍</span>
64
+ <input id="search-field-mobile" role="combobox" aria-label="Search"
65
+ aria-autocomplete="list" aria-controls="search-results-mobile"
66
+ type="text" name="search" placeholder="Search examples"
67
+ spellcheck="false" autocomplete="off">
68
+ <button type="button" class="search-modal-close" aria-label="Close search" id="search-modal-close">
69
+ <span aria-hidden="true">esc</span>
70
+ </button>
71
+ </form>
72
+ </div>
73
+ <div class="search-modal-body">
74
+ <ul id="search-results-mobile" aria-label="Search Results"
75
+ aria-busy="false" aria-expanded="false"
76
+ aria-atomic="false" class="search-results search-modal-results initially-hidden"></ul>
77
+ <div class="search-modal-empty">
78
+ <p>No recent searches</p>
79
+ </div>
80
+ </div>
81
+ </div>
82
+ </div>
83
+
84
+ <nav id="navigation" role="navigation">
85
+ <div id="fileindex-section" class="nav-section">
86
+ <details class="nav-section-collapsible" open>
87
+ <summary class="nav-section-header">
88
+ <span class="nav-section-icon">
89
+ <svg><use href="#icon-file"></use></svg>
90
+ </span>
91
+ <span class="nav-section-title">Examples</span>
92
+ <span class="nav-section-chevron">
93
+ <svg><use href="#icon-chevron"></use></svg>
94
+ </span>
95
+ </summary>
96
+ <ul class="nav-list">
97
+ <li><a href="<%= doc_root_link %>">← Back to Docs</a></li>
98
+ </ul>
99
+ </details>
100
+ </div>
101
+ <div class="nav-section">
102
+ <details class="nav-section-collapsible" open>
103
+ <summary class="nav-section-header">
104
+ <span class="nav-section-icon">
105
+ <svg><use href="#icon-layers"></use></svg>
106
+ </span>
107
+ <span class="nav-section-title">Files</span>
108
+ <span class="nav-section-chevron">
109
+ <svg><use href="#icon-chevron"></use></svg>
110
+ </span>
111
+ </summary>
112
+ <ul class="link-list nav-list">
113
+ <%= render_tree(tree_data, relative_path, current_file_html) %>
114
+ </ul>
115
+ </details>
116
+ </div>
117
+ </nav>
118
+
119
+ <main role="main">
120
+ <div class="breadcrumb">
121
+ <%= breadcrumb_path %>
122
+ </div>
123
+ <%= file_header_html %>
124
+ <div class="content">
125
+ <%= file_content_html %>
126
+ </div>
127
+ </main>
128
+
129
+ <% unless toc_items.empty? %>
130
+ <aside class="table-of-contents" role="complementary" aria-label="Table of Contents">
131
+ <div class="toc-sticky">
132
+ <div class="toc-list">
133
+ <h3>On This Page</h3>
134
+ <%= render_toc(toc_items) %>
135
+ </div>
136
+ </div>
137
+ </aside>
138
+ <% end %>
139
+
140
+
141
+ <script>
142
+ const modes = ['auto', 'light', 'dark'];
143
+ const icons = { auto: '🌓', light: '☀️', dark: '🌙' };
144
+
145
+ function setColorMode(mode) {
146
+ if (mode === 'auto') {
147
+ document.documentElement.removeAttribute('data-theme');
148
+ const systemTheme = (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) ? 'dark' : 'light';
149
+ document.documentElement.setAttribute('data-theme', systemTheme);
150
+ } else {
151
+ document.documentElement.setAttribute('data-theme', mode);
152
+ }
153
+
154
+ const icon = icons[mode];
155
+ const toggle = document.getElementById('theme-toggle');
156
+ toggle.querySelector('.theme-toggle-icon').textContent = icon;
157
+
158
+ localStorage.setItem('rdoc-theme', mode);
159
+ }
160
+
161
+ function cycleColorMode() {
162
+ const current = localStorage.getItem('rdoc-theme') || 'auto';
163
+ const currentIndex = modes.indexOf(current);
164
+ const nextMode = modes[(currentIndex + 1) % modes.length];
165
+ setColorMode(nextMode);
166
+ }
167
+
168
+ const savedMode = localStorage.getItem('rdoc-theme') || 'auto';
169
+ setColorMode(savedMode);
170
+ </script>
171
+ </body>
172
+ </html>
@@ -0,0 +1,60 @@
1
+ # SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
2
+ # SPDX-License-Identifier: AGPL-3.0-or-later
3
+
4
+ image: archlinux
5
+ packages:
6
+ - bash
7
+ - base-devel
8
+ - curl
9
+ - openssl
10
+ - libyaml
11
+ - zlib
12
+ - readline
13
+ - gdbm
14
+ - ncurses
15
+ - libffi
16
+ <%- if has_rust -%>
17
+ - clang
18
+ <%- end -%>
19
+ - git
20
+ artifacts:
21
+ - <%= gem_name %>/pkg/<%= gem_filename %>
22
+ sources:
23
+ - https://git.sr.ht/~kerrick/<%= gem_name %>
24
+ tasks:
25
+ - setup: |
26
+ curl https://mise.jdx.dev/install.sh | sh
27
+ echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.buildenv
28
+ echo 'eval "$($HOME/.local/bin/mise activate bash)"' >> ~/.buildenv
29
+ echo 'export LANG="en_US.UTF-8"' >> ~/.buildenv
30
+ echo 'export LC_ALL="en_US.UTF-8"' >> ~/.buildenv
31
+ <%- if has_rust -%>
32
+ echo 'export BINDGEN_EXTRA_CLANG_ARGS="-include stdbool.h"' >> ~/.buildenv
33
+ <%- end -%>
34
+ . ~/.buildenv
35
+ export CI="true"
36
+ cd <%= gem_name %>
37
+ sed -i 's/ruby = .*/ruby = "<%= ruby_version %>"/' mise.toml
38
+ mise install
39
+ mise x -- pip install reuse
40
+ mise x -- gem install bundler:<%= bundler_version %>
41
+ mise reshim
42
+ mise x -- bundle config set --local frozen 'true'
43
+ mise x -- bundle install
44
+ <%- if has_rust -%>
45
+ mise x -- bundle exec rake compile
46
+ <%- end -%>
47
+ - test: |
48
+ . ~/.buildenv
49
+ cd <%= gem_name %>
50
+ echo "Testing Ruby <%= ruby_version %>"
51
+ mise x -- bundle exec rake test
52
+ - lint: |
53
+ . ~/.buildenv
54
+ cd <%= gem_name %>
55
+ echo "Linting Ruby <%= ruby_version %>"
56
+ mise x -- bundle exec rake lint
57
+ - package: |
58
+ . ~/.buildenv
59
+ cd <%= gem_name %>
60
+ mise x -- bundle exec rake build
@@ -0,0 +1,44 @@
1
+ <!--
2
+ SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
3
+
4
+ SPDX-License-Identifier: AGPL-3.0-or-later
5
+ -->
6
+
7
+ <!DOCTYPE html>
8
+ <html>
9
+ <head>
10
+ <title><%= project_name %> documentation</title>
11
+ <meta name="viewport" content="width=device-width, initial-scale=1">
12
+ <style>
13
+ :root { color-scheme: light dark; }
14
+ body { font-family: system-ui, sans-serif; max-width: 800px; margin: 0 auto; padding: 2rem; line-height: 1.5; color: light-dark(#111, #eee); background: light-dark(#fff, #111); }
15
+ h1 { border-bottom: 2px solid light-dark(#eee, #333); padding-bottom: 0.5rem; }
16
+ ul { list-style: none; padding: 0; }
17
+ li { margin: 0.5rem 0; border: 1px solid light-dark(#ddd, #444); border-radius: 4px; }
18
+ a { display: block; padding: 1rem; text-decoration: none; color: light-dark(#0055aa, #44aaff); font-weight: bold; }
19
+ a:hover { background: light-dark(#f5f5f5, #222); }
20
+ .meta { font-weight: normal; color: light-dark(#666, #aaa); font-size: 0.9em; float: right; }
21
+ </style>
22
+ </head>
23
+ <body>
24
+ <h1><%= project_name %> documentation</h1>
25
+ <ul>
26
+ <% versions.each do |version| %>
27
+ <li>
28
+ <a href='<%= version.slug %>/index.html'>
29
+ <%= version.name %>
30
+ <span class='meta'>
31
+ <% if version.latest? %>
32
+ Latest
33
+ <% elsif version.edge? %>
34
+ Edge
35
+ <% else %>
36
+ Historical
37
+ <% end %>
38
+ </span>
39
+ </a>
40
+ </li>
41
+ <% end %>
42
+ </ul>
43
+ </body>
44
+ </html>