rubylens 0.1.0.pre.1 → 0.2.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/README.md +181 -30
- data/assets/runtime/report.js +3234 -455
- data/assets/shells/report.html +54 -10
- data/assets/shells/showcase.html +7 -3
- data/assets/styles/report.css +93 -25
- data/assets/styles/showcase.css +43 -4
- data/exe/rubylens +2 -1
- data/lib/rubylens/art_model_builder.rb +103 -25
- data/lib/rubylens/artifact_marker.rb +17 -0
- data/lib/rubylens/atomic_output.rb +27 -0
- data/lib/rubylens/cli.rb +85 -51
- data/lib/rubylens/clip/chrome_page.rb +183 -0
- data/lib/rubylens/clip/deadline_io.rb +28 -0
- data/lib/rubylens/clip/renderer.rb +113 -0
- data/lib/rubylens/clip/toolchain.rb +82 -0
- data/lib/rubylens/clip/web_socket_channel.rb +116 -0
- data/lib/rubylens/clip_generator.rb +102 -0
- data/lib/rubylens/default_output.rb +24 -0
- data/lib/rubylens/dependency_warning.rb +17 -0
- data/lib/rubylens/errors.rb +1 -1
- data/lib/rubylens/generator.rb +23 -28
- data/lib/rubylens/git_repository.rb +20 -29
- data/lib/rubylens/index/manifest.rb +240 -16
- data/lib/rubylens/index/rspec_extractor.rb +77 -0
- data/lib/rubylens/index/rubydex_adapter.rb +385 -167
- data/lib/rubylens/index/source_path.rb +40 -0
- data/lib/rubylens/model/dependency_aggregation.rb +12 -74
- data/lib/rubylens/morphology_classifier.rb +257 -0
- data/lib/rubylens/report_writer.rb +8 -26
- data/lib/rubylens/showcase_generator.rb +13 -21
- data/lib/rubylens/showcase_model.rb +127 -12
- data/lib/rubylens/showcase_writer.rb +3 -10
- data/lib/rubylens/version.rb +1 -1
- data/lib/rubylens.rb +15 -7
- metadata +18 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d79e23df4b2738a967167958385f2ef8b6c8dd6bd333f70a96690ed3c6f35823
|
|
4
|
+
data.tar.gz: '09f0c64309ee0427d3b3cf326187d9aaf9e6cf3d3b6766fd7951c3ba4fccd5e0'
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e1edf50d830b80dd72f9d033f6d1f9a74a51a90a559c6cc37329701b3762891145fe2e86a4b9f412224af2092a3c4b5c128473b0d453a19d83a689ff9c0570b0
|
|
7
|
+
data.tar.gz: 22e667b3baec097b8bb30c48ba9aa1c8fcd4817993479c0680b45f1605880ff8351f8ee0355e9ac3e06a3a3cc588471a0fd8953ea1561628e3fa411880d0961b
|
data/README.md
CHANGED
|
@@ -1,67 +1,218 @@
|
|
|
1
1
|
# RubyLens
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Your Ruby codebase, as a galaxy.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
[](docs/images/galaxy-morphology-families.jpg)
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
RubyLens reads a Ruby project and writes one self-contained HTML file: classes and modules as magenta stars, tests as a cyan halo, gems as orbiting gold clouds. The galaxy's shape is derived from the code: spiral, elliptical, barred, lenticular, or irregular.
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
```ruby
|
|
10
|
+
# Gemfile
|
|
11
|
+
gem "rubylens", require: false
|
|
12
|
+
```
|
|
10
13
|
|
|
11
14
|
```sh
|
|
12
|
-
bundle exec rubylens report
|
|
15
|
+
bundle exec rubylens report
|
|
13
16
|
```
|
|
14
17
|
|
|
15
|
-
|
|
18
|
+
Open `rubylens-report.html` in your browser. No server needed.
|
|
16
19
|
|
|
17
|
-
|
|
20
|
+
Three levels of disclosure:
|
|
18
21
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
| For | Command | Reveals |
|
|
23
|
+
| --- | --- | --- |
|
|
24
|
+
| Yourself | `rubylens report` | Real class, module, and gem names, sparse reference topology, and full interaction |
|
|
25
|
+
| Your team or a talk | `rubylens clip --details` | Project name, shape, scale, sparse reference topology, stats, and selected names |
|
|
26
|
+
| Anyone | `rubylens clip` | Project name, galaxy shape and scale, and sparse anonymous reference topology |
|
|
27
|
+
|
|
28
|
+
> [!IMPORTANT]
|
|
29
|
+
> Nothing is uploaded and no source code is embedded. Outputs still describe your project: they name it, can name classes and gems, and reveal some relationship topology. See [Privacy and sharing](#privacy-and-sharing).
|
|
30
|
+
|
|
31
|
+
https://github.com/user-attachments/assets/43570623-6d98-46c9-9303-7faa4035b2a7
|
|
32
|
+
|
|
33
|
+
*The Explorer on Rails: search, fly to a class, expand a gem cloud.*
|
|
34
|
+
|
|
35
|
+
https://github.com/user-attachments/assets/bb266de5-bbd7-4ccd-814b-15961b45bd39
|
|
36
|
+
|
|
37
|
+
*A `--details` clip: what your team sees.*
|
|
38
|
+
|
|
39
|
+
## Setup notes
|
|
40
|
+
|
|
41
|
+
RubyLens runs from inside an existing Ruby project's bundle, and the project must be inside a Git repository.
|
|
42
|
+
|
|
43
|
+
`clip` needs Chrome (or Chromium) and ffmpeg; see [Using Clip](#using-clip). Swap in `rubylens showcase [--details]` for the self-playing HTML page alone.
|
|
44
|
+
|
|
45
|
+
RubyLens uses the current directory when you omit `TARGET`. To visualize a subdirectory while using the current project's bundle and root lockfile, run:
|
|
46
|
+
|
|
47
|
+
```sh
|
|
48
|
+
bundle exec rubylens report components/payments --lockfile Gemfile.lock
|
|
24
49
|
```
|
|
25
50
|
|
|
26
|
-
|
|
51
|
+
For complete gem clouds, generate from a project with a readable `Gemfile.lock` after `bundle install`. Without a lockfile, RubyLens still shows Core and Tests but omits Gems and reports a warning. It never fetches missing dependencies during generation.
|
|
52
|
+
|
|
53
|
+
## Privacy and sharing
|
|
54
|
+
|
|
55
|
+
RubyLens indexes and renders locally. Generated HTML files contain their scripts, styles, fonts, and data, make no network requests, and open without Node or an HTTP server. Clip rendering also stays local: it drives your own Chrome and ffmpeg over loopback and never uploads anything.
|
|
56
|
+
|
|
57
|
+
But the outputs still describe your project:
|
|
58
|
+
|
|
59
|
+
- Explorer embeds fully qualified class, module, and gem names. It omits source text, comments, paths, and names for individual dependency stars.
|
|
60
|
+
- Minimal Showcase omits code and gem names, but still reveals the project name, the galaxy's shape and scale, and a sparse anonymous sample of constant-reference topology.
|
|
61
|
+
- Details Showcase adds aggregate statistics and selected code/dependency names to the same topology.
|
|
62
|
+
- Clip shows on screen exactly what the recorded Showcase shows, in a format anyone can replay.
|
|
63
|
+
|
|
64
|
+
Galaxy shape is also information: a package's rendered shape can make the rough makeup of that gem easier to see, even though it reveals no source text. Relationship topology is information too: a travel line means that one rendered namespace contains a resolved reference to another rendered declaration.
|
|
27
65
|
|
|
28
|
-
`
|
|
66
|
+
Default outputs are written atomically with owner-only `0600` permissions. RubyLens also adds the exact default output and its temporary-file pattern to the repository's local `.git/info/exclude`, so it does not change the shared `.gitignore`.
|
|
29
67
|
|
|
30
|
-
|
|
68
|
+
RubyLens updates its own existing default output, but refuses to overwrite a tracked file or an unrelated file at that path.
|
|
31
69
|
|
|
32
|
-
|
|
70
|
+
Custom output paths are written exactly where requested, may replace an existing file there, and are not added to Git's local excludes. Choose the path carefully and review the HTML before sharing it.
|
|
33
71
|
|
|
34
|
-
|
|
72
|
+
## Using Explorer
|
|
73
|
+
|
|
74
|
+
Explorer lets you search and move through Core code, Tests, and Gems while the galaxy continues to drift.
|
|
75
|
+
|
|
76
|
+
While drift runs, RubyLens scales traffic with the rendered project population: very small reports show one flight at a time, and larger reports show at most two simultaneous flights. Individual launches follow one seeded stream with varied gaps, and a finished flight frees capacity for another after a short randomized breath. There are no synchronized bursts or two-second pauses. Routes to exact Gem declaration stars are preferred three times out of four while workspace-only routes stay eligible. Admission skips very short or out-of-bounds guides and rejects capacity-conflicting or shared-endpoint routes. Each admitted 2.2-second flight follows one immutable world-space quadratic with a compact tapered wake whose thickest end overlaps one elongated same-hue drop. Admission checks a screen-space guide, then unprojects its control point; the live camera projects the resulting path throughout the flight. A rotating Gem star may move away after departure. Orbit, pan, zoom, and camera flights keep active paths visible; pausing drift or requesting reduced motion clears them.
|
|
77
|
+
|
|
78
|
+
- Drag to orbit.
|
|
79
|
+
- Scroll at the cursor to zoom.
|
|
80
|
+
- Shift-drag, use Pan mode, or use the arrow keys to move across the galaxy.
|
|
81
|
+
- Search for classes, modules, and gems from the side panel.
|
|
82
|
+
- Select a class, module, or dependency system to fly to a top-down comparison that keeps Core visible for scale.
|
|
83
|
+
- Double-click a gem cloud to expand its existing stars.
|
|
84
|
+
- Press Space or use the toolbar to pause/resume drift.
|
|
85
|
+
- Use Reset to restore the default camera without changing your drift choice.
|
|
86
|
+
|
|
87
|
+
Explorer requires WebGL2 to render the complete galaxy. If WebGL2 is missing or the browser loses the context, RubyLens shows a warning rather than quietly drawing a partial galaxy.
|
|
88
|
+
|
|
89
|
+
## Using Showcase
|
|
90
|
+
|
|
91
|
+
Showcase is self-playing and noninteractive. It opens directly, rotates once per minute, and contains no Explorer controls, search, hover, or navigation.
|
|
92
|
+
|
|
93
|
+
Use the default Minimal mode when the visual shape is enough:
|
|
94
|
+
|
|
95
|
+
```sh
|
|
96
|
+
bundle exec rubylens showcase
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Use `--details` when you want aggregate statistics and one-at-a-time cinematic labels:
|
|
35
100
|
|
|
36
101
|
```sh
|
|
37
|
-
bundle exec rubylens showcase
|
|
102
|
+
bundle exec rubylens showcase --details
|
|
38
103
|
```
|
|
39
104
|
|
|
40
|
-
|
|
105
|
+
Both Showcase modes include the same bounded, anonymous travel flights. Showcase also requires WebGL2. A browser with `prefers-reduced-motion` enabled receives one stable frame with no travel flights or cinematic labels.
|
|
41
106
|
|
|
42
|
-
|
|
107
|
+
## Using Clip
|
|
43
108
|
|
|
44
|
-
|
|
109
|
+
Clip records the Showcase into `rubylens-clip.mp4`: one full camera rotation at 1920×1080 and 30 frames per second, encoded as H.264 for compatibility with Slack, X, LinkedIn, and slide decks. The camera ends where it started, so the loop has no visible cut.
|
|
45
110
|
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
|
|
111
|
+
```sh
|
|
112
|
+
bundle exec rubylens clip
|
|
113
|
+
bundle exec rubylens clip --details
|
|
49
114
|
```
|
|
50
115
|
|
|
51
|
-
|
|
116
|
+
Clip needs two locally installed tools and checks for them before doing any work:
|
|
117
|
+
|
|
118
|
+
- **Chrome or Chromium** for headless WebGL2 rendering. Discovery checks `PATH` and common install locations; set `RUBYLENS_CHROME` to point at a specific binary.
|
|
119
|
+
- **ffmpeg** for H.264 encoding (`brew install ffmpeg` or `apt install ffmpeg`); set `RUBYLENS_FFMPEG` to override discovery.
|
|
120
|
+
|
|
121
|
+
Frames render deterministically off-screen, so nothing flashes across your display, and progress is reported as the 1,800 frames encode. Expect a few minutes on machines without GPU acceleration. The showcase HTML is always written next to the video, so a failed render still leaves you a shareable page.
|
|
122
|
+
|
|
123
|
+
## What the stars mean
|
|
124
|
+
|
|
125
|
+
- **Core** is magenta. Its stars represent classes and modules from the project's main Ruby code.
|
|
126
|
+
- **Tests** are cyan. They represent test classes and modules. RubyLens also adds class-like stars for RSpec `describe` and `context` calls under `spec/` or `specs/`.
|
|
127
|
+
- **Gems** are warm gold. Each gem forms a cloud of anonymous stars. Related gems from the same materialized Git source can appear together as one dependency system.
|
|
128
|
+
|
|
129
|
+
RubyLens uses Rubydex to find classes, modules, methods, constants, inheritance, reopenings, and references. Shuttle flights draw from resolved references whose occurrences belong to Core or Test namespaces; their targets may be another workspace namespace or an exact anonymous Gem declaration star. Core-to-Core, Core-to-Test, Test-to-Core, Test-to-Test, and workspace-to-Gem flights are included; top-level, ambiguous, exact-self, and non-workspace origins are omitted. Flights travel from the referenced declaration to the referrer and show a bounded visual sample, not call edges or a complete relationship graph. RubyLens never executes the project or its tests.
|
|
52
130
|
|
|
53
|
-
|
|
131
|
+
RubyLens analyzes tracked `.rb`, `.rake`, `.rbs`, and `.ru` files inside the target, plus untracked files of those types that Git does not ignore. It reads dependency versions from `Gemfile.lock` and analyzes gem code already installed locally.
|
|
132
|
+
|
|
133
|
+
RubyLens is not a type checker, whole-program call graph, source browser, route explorer, or per-dependency-star inspector.
|
|
134
|
+
|
|
135
|
+
## Galaxy morphology
|
|
136
|
+
|
|
137
|
+
RubyLens uses the [Hubble sequence](https://science.nasa.gov/asset/hubble/the-hubble-tuning-fork-classification-of-galaxies/) as a visual vocabulary. It uses broad code counts to choose a repeatable shape for the central Core/Test galaxy and each dependency package independently. A package never inherits the project's, host's, or dependency system's decision.
|
|
138
|
+
|
|
139
|
+
Very large dependency packages that would otherwise render as smooth elliptical or lenticular clouds use a deterministic Spiral or Barred Spiral enrichment. This keeps their visual mass structured while smaller packages retain their aggregate-derived family.
|
|
140
|
+
|
|
141
|
+
The morphology describes the rendered shape. It is not a claim about the project's architecture, purpose, quality, or correctness.
|
|
142
|
+
|
|
143
|
+
[](docs/images/galaxy-morphology-variations.jpg)
|
|
144
|
+
|
|
145
|
+
*Representative endpoints inside the elliptical, spiral, and barred-spiral families.*
|
|
146
|
+
|
|
147
|
+
Read the [accepted morphology design](docs/specs/2026-07-14-galaxy-morphology-design.md) or [stellar design research](docs/STELLAR_DESIGN_RESEARCH.md) for the full visual model.
|
|
148
|
+
|
|
149
|
+
## CLI reference
|
|
150
|
+
|
|
151
|
+
```text
|
|
152
|
+
rubylens report [OPTIONS] [TARGET]
|
|
153
|
+
rubylens clip [OPTIONS] [TARGET]
|
|
154
|
+
rubylens showcase [OPTIONS] [TARGET]
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
All commands accept:
|
|
158
|
+
|
|
159
|
+
- `-o FILE` / `--output FILE` to choose an output path
|
|
160
|
+
- `--lockfile FILE` to use a specific `Gemfile.lock`
|
|
161
|
+
- `-h` / `--help` to show command help
|
|
162
|
+
|
|
163
|
+
`rubylens clip` and `rubylens showcase` also accept `--details`. A custom `rubylens clip --output movie.mp4` writes the recorded showcase to `movie.html` next to it.
|
|
164
|
+
|
|
165
|
+
## Ruby API
|
|
166
|
+
|
|
167
|
+
```ruby
|
|
168
|
+
require "rubylens"
|
|
169
|
+
|
|
170
|
+
report = RubyLens.generate_report(path: ".")
|
|
171
|
+
puts report.output_path
|
|
172
|
+
puts report.counts
|
|
173
|
+
puts report.warnings
|
|
174
|
+
|
|
175
|
+
showcase = RubyLens.generate_showcase(path: ".", details: true)
|
|
176
|
+
puts showcase.output_path
|
|
177
|
+
|
|
178
|
+
clip = RubyLens.generate_clip(path: ".", progress: ->(done, total) { puts "#{done}/#{total}" })
|
|
179
|
+
puts clip.output_path # the MP4
|
|
180
|
+
puts clip.showcase_path # the showcase HTML it recorded
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
Passing `output:` selects a custom path. The caller is responsible for keeping custom outputs private.
|
|
54
184
|
|
|
55
185
|
## Development
|
|
56
186
|
|
|
57
|
-
RubyLens supports Ruby 3.2 through 4.0.
|
|
187
|
+
RubyLens supports Ruby 3.2 through 4.0. The repository's `.ruby-version` and `.node-version` select the development runtimes. Activate Ruby with your version manager, then install the Ruby and JavaScript dependencies:
|
|
58
188
|
|
|
59
189
|
```sh
|
|
60
|
-
source /opt/homebrew/share/chruby/chruby.sh
|
|
61
|
-
chruby ruby-4.0.5
|
|
62
190
|
bundle install
|
|
191
|
+
npm ci
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
Run the Ruby and JavaScript unit tests:
|
|
195
|
+
|
|
196
|
+
```sh
|
|
63
197
|
bundle exec rake test
|
|
198
|
+
npm run test:unit
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
Run the browser tests:
|
|
202
|
+
|
|
203
|
+
```sh
|
|
204
|
+
npx playwright install chromium
|
|
205
|
+
npm run test:browser
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
Build the gem:
|
|
209
|
+
|
|
210
|
+
```sh
|
|
64
211
|
gem build rubylens.gemspec
|
|
65
212
|
```
|
|
66
213
|
|
|
67
|
-
The
|
|
214
|
+
The product and design contracts live in [PRODUCT.md](PRODUCT.md) and [DESIGN.md](DESIGN.md). Scale and benchmark notes live in [docs/PERFORMANCE.md](docs/PERFORMANCE.md).
|
|
215
|
+
|
|
216
|
+
## License
|
|
217
|
+
|
|
218
|
+
RubyLens is available under the [MIT License](LICENSE.txt).
|