gemstar 1.0.4 → 1.1
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/CHANGELOG.md +25 -1
- data/README.md +28 -3
- data/bin/gemstar +5 -1
- data/lib/gemstar/cache_warmer.rb +93 -35
- data/lib/gemstar/change_log.rb +123 -33
- data/lib/gemstar/cli.rb +5 -1
- data/lib/gemstar/commands/diff.rb +197 -31
- data/lib/gemstar/commands/server.rb +93 -10
- data/lib/gemstar/data/importmap_package_metadata.json +22 -0
- data/lib/gemstar/data/ruby_gems_metadata.json +9 -0
- data/lib/gemstar/git_repo.rb +41 -3
- data/lib/gemstar/importmap_file.rb +193 -0
- data/lib/gemstar/npm_metadata.rb +159 -0
- data/lib/gemstar/outputs/html.rb +53 -4
- data/lib/gemstar/outputs/markdown.rb +29 -3
- data/lib/gemstar/package_lock_file.rb +101 -0
- data/lib/gemstar/project.rb +319 -35
- data/lib/gemstar/ruby_gems_metadata.rb +77 -2
- data/lib/gemstar/version.rb +1 -1
- data/lib/gemstar/web/app.rb +377 -67
- data/lib/gemstar/web/templates/app.css +35 -0
- data/lib/gemstar/web/templates/app.js.erb +51 -16
- data/lib/gemstar/web/templates/page.html.erb +2 -1
- data/lib/gemstar.rb +3 -0
- metadata +6 -1
|
@@ -210,6 +210,18 @@
|
|
|
210
210
|
margin: 0.3rem 0 0;
|
|
211
211
|
color: var(--muted);
|
|
212
212
|
}
|
|
213
|
+
.detail-subtitle > :first-child {
|
|
214
|
+
margin-top: 0;
|
|
215
|
+
}
|
|
216
|
+
.detail-subtitle > :last-child {
|
|
217
|
+
margin-bottom: 0;
|
|
218
|
+
}
|
|
219
|
+
.detail-subtitle a[href] {
|
|
220
|
+
color: #2563c9;
|
|
221
|
+
}
|
|
222
|
+
.detail-subtitle a[href]:hover {
|
|
223
|
+
text-decoration: underline;
|
|
224
|
+
}
|
|
213
225
|
.detail-origin {
|
|
214
226
|
margin: 0;
|
|
215
227
|
color: var(--ink);
|
|
@@ -236,6 +248,9 @@
|
|
|
236
248
|
gap: 0.28rem;
|
|
237
249
|
flex-wrap: wrap;
|
|
238
250
|
}
|
|
251
|
+
.list-filters-secondary {
|
|
252
|
+
padding-top: 0.05rem;
|
|
253
|
+
}
|
|
239
254
|
.list-filter-button {
|
|
240
255
|
border: 1px solid var(--line);
|
|
241
256
|
border-radius: 999px;
|
|
@@ -296,6 +311,12 @@
|
|
|
296
311
|
justify-content: space-between;
|
|
297
312
|
gap: 0.5rem;
|
|
298
313
|
}
|
|
314
|
+
.gem-name-lockup {
|
|
315
|
+
display: inline-flex;
|
|
316
|
+
align-items: center;
|
|
317
|
+
gap: 0.38rem;
|
|
318
|
+
min-width: 0;
|
|
319
|
+
}
|
|
299
320
|
.gem-updated-dot {
|
|
300
321
|
width: 0.45rem;
|
|
301
322
|
height: 0.45rem;
|
|
@@ -311,6 +332,20 @@
|
|
|
311
332
|
color: var(--muted);
|
|
312
333
|
font-size: 0.76rem;
|
|
313
334
|
}
|
|
335
|
+
.package-type-tag {
|
|
336
|
+
display: inline-flex;
|
|
337
|
+
align-items: center;
|
|
338
|
+
border: 1px solid #ded6c8;
|
|
339
|
+
border-radius: 999px;
|
|
340
|
+
padding: 0.02rem 0.33rem;
|
|
341
|
+
background: #fbf7ef;
|
|
342
|
+
color: #786d61;
|
|
343
|
+
font-size: 0.62rem;
|
|
344
|
+
font-weight: 600;
|
|
345
|
+
letter-spacing: 0.01em;
|
|
346
|
+
line-height: 1.25;
|
|
347
|
+
flex: 0 0 auto;
|
|
348
|
+
}
|
|
314
349
|
.gem-row.status-added .gem-version {
|
|
315
350
|
color: var(--green);
|
|
316
351
|
font-weight: 600;
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
const toSelect = document.querySelector("[data-to-select]");
|
|
5
5
|
const sidebarPanel = document.querySelector("[data-sidebar-panel]");
|
|
6
6
|
const filterButtons = Array.from(document.querySelectorAll("[data-filter-button]"));
|
|
7
|
+
const ecosystemButtons = Array.from(document.querySelectorAll("[data-ecosystem-button]"));
|
|
7
8
|
const gemSearch = document.querySelector("[data-gem-search]");
|
|
8
9
|
const emptyGemList = document.querySelector("[data-gem-list-empty]");
|
|
9
10
|
let detailPanel = document.querySelector("[data-detail-panel]");
|
|
@@ -13,8 +14,10 @@
|
|
|
13
14
|
let detailRequestToken = 0;
|
|
14
15
|
let activeDetailUrl = detailPanel ? detailPanel.dataset.detailUrl : null;
|
|
15
16
|
let currentFilter = <%= selected_filter_json %>;
|
|
17
|
+
let currentPackageScope = <%= selected_package_scope_json %>;
|
|
16
18
|
let currentSearch = "";
|
|
17
19
|
const emptyDetailHtml = <%= empty_detail_html_json %>;
|
|
20
|
+
const packageCollectionLabel = <%= (@selected_project&.package_collection_label || "Packages").downcase.dump %>;
|
|
18
21
|
const detailDisclosureStorageKey = "gemstar.detailDisclosureOpen";
|
|
19
22
|
|
|
20
23
|
const visibleGemLinks = () => gemLinks.filter((link) => !link.hidden);
|
|
@@ -24,16 +27,18 @@
|
|
|
24
27
|
link.classList.remove("is-selected");
|
|
25
28
|
});
|
|
26
29
|
};
|
|
27
|
-
const
|
|
30
|
+
const packageNameParam = (url) => url.searchParams.get("package") || url.searchParams.get("gem");
|
|
31
|
+
const requestedGemName = () => packageNameParam(new URL(window.location.href));
|
|
28
32
|
const currentDetailGemName = () => {
|
|
29
33
|
if (!detailPanel || !detailPanel.dataset.detailUrl) return null;
|
|
30
34
|
|
|
31
35
|
try {
|
|
32
|
-
return new URL(detailPanel.dataset.detailUrl, window.location.origin)
|
|
36
|
+
return packageNameParam(new URL(detailPanel.dataset.detailUrl, window.location.origin));
|
|
33
37
|
} catch (_error) {
|
|
34
38
|
return null;
|
|
35
39
|
}
|
|
36
40
|
};
|
|
41
|
+
const detailNeedsInitialFetch = () => detailPanel && detailPanel.dataset.detailDeferred === "true" && !!detailPanel.dataset.detailUrl;
|
|
37
42
|
const isSidebarFocused = () => document.activeElement === sidebarPanel;
|
|
38
43
|
const isDetailFocused = () => detailPanel && document.activeElement === detailPanel;
|
|
39
44
|
const focusSidebar = () => {
|
|
@@ -77,15 +82,20 @@
|
|
|
77
82
|
button.classList.toggle("is-active", button.dataset.filterButton === filter);
|
|
78
83
|
});
|
|
79
84
|
|
|
85
|
+
ecosystemButtons.forEach((button) => {
|
|
86
|
+
button.classList.toggle("is-active", button.dataset.ecosystemButton === currentPackageScope);
|
|
87
|
+
});
|
|
88
|
+
|
|
80
89
|
gemLinks.forEach((link) => {
|
|
81
90
|
const updated = link.dataset.gemUpdated === "true";
|
|
82
91
|
const pinned = pinnedGemName && link.dataset.gemName === pinnedGemName;
|
|
92
|
+
const matchesScope = currentPackageScope === "all" || link.dataset.packageScope === currentPackageScope;
|
|
83
93
|
const matchesSearch = searchTerm === "" || link.dataset.gemName.toLowerCase().includes(searchTerm);
|
|
84
|
-
link.hidden = ((filter === "updated" && !updated && !pinned) || !matchesSearch);
|
|
94
|
+
link.hidden = (!matchesScope || (filter === "updated" && !updated && !pinned) || !matchesSearch);
|
|
85
95
|
});
|
|
86
96
|
|
|
87
97
|
if (emptyGemList) {
|
|
88
|
-
const emptyMessage = searchTerm === "" ?
|
|
98
|
+
const emptyMessage = searchTerm === "" ? `No updated ${packageCollectionLabel} in this revision range.` : `No ${packageCollectionLabel} match this filter.`;
|
|
89
99
|
emptyGemList.hidden = visibleGemLinks().length !== 0;
|
|
90
100
|
const text = emptyGemList.querySelector("p");
|
|
91
101
|
if (text) text.textContent = emptyMessage;
|
|
@@ -93,12 +103,14 @@
|
|
|
93
103
|
|
|
94
104
|
if (currentSelectedIndex() === -1) {
|
|
95
105
|
clearSidebarSelection();
|
|
96
|
-
|
|
106
|
+
if (visibleGemLinks().length === 0) {
|
|
107
|
+
replaceDetail(emptyDetailHtml);
|
|
108
|
+
}
|
|
97
109
|
}
|
|
98
110
|
};
|
|
99
111
|
|
|
100
112
|
const syncSidebarSelection = (gemName = null, keepVisible = false) => {
|
|
101
|
-
const effectiveGemName = gemName ||
|
|
113
|
+
const effectiveGemName = gemName || requestedGemName();
|
|
102
114
|
if (!effectiveGemName) {
|
|
103
115
|
clearSidebarSelection();
|
|
104
116
|
return;
|
|
@@ -180,11 +192,12 @@
|
|
|
180
192
|
const detailUrl = new URL(url, window.location.origin);
|
|
181
193
|
pageUrl.search = detailUrl.search;
|
|
182
194
|
pageUrl.searchParams.set("filter", currentFilter);
|
|
195
|
+
pageUrl.searchParams.set("scope", currentPackageScope);
|
|
183
196
|
const historyMethod = historyMode === "replace" ? "replaceState" : "pushState";
|
|
184
197
|
window.history[historyMethod]({}, "", pageUrl);
|
|
185
198
|
}
|
|
186
199
|
const detailUrl = new URL(url, window.location.origin);
|
|
187
|
-
syncSidebarSelection(detailUrl
|
|
200
|
+
syncSidebarSelection(packageNameParam(detailUrl));
|
|
188
201
|
})
|
|
189
202
|
.catch(() => {
|
|
190
203
|
stopDetailLoading();
|
|
@@ -203,21 +216,29 @@
|
|
|
203
216
|
};
|
|
204
217
|
|
|
205
218
|
const ensureInitialGemSelection = () => {
|
|
206
|
-
|
|
219
|
+
const requested = requestedGemName();
|
|
207
220
|
|
|
208
221
|
const detailGemName = currentDetailGemName();
|
|
209
222
|
const detailLink = detailGemName ? visibleGemLinks().find((link) => link.dataset.gemName === detailGemName) : null;
|
|
210
223
|
|
|
211
224
|
if (detailLink) {
|
|
212
225
|
syncSidebarSelection(detailGemName, true);
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
226
|
+
if (!requested) {
|
|
227
|
+
const pageUrl = new URL(window.location.href);
|
|
228
|
+
const detailUrl = new URL(detailLink.dataset.detailUrl || detailLink.href, window.location.origin);
|
|
229
|
+
pageUrl.search = detailUrl.search;
|
|
230
|
+
pageUrl.searchParams.set("filter", currentFilter);
|
|
231
|
+
pageUrl.searchParams.set("scope", currentPackageScope);
|
|
232
|
+
window.history.replaceState({}, "", pageUrl);
|
|
233
|
+
}
|
|
234
|
+
if (detailNeedsInitialFetch()) {
|
|
235
|
+
fetchDetail(detailLink.dataset.detailUrl || detailLink.href, requested ? "none" : "replace");
|
|
236
|
+
}
|
|
218
237
|
return;
|
|
219
238
|
}
|
|
220
239
|
|
|
240
|
+
if (requested) return;
|
|
241
|
+
|
|
221
242
|
const firstVisibleLink = visibleGemLinks()[0];
|
|
222
243
|
if (firstVisibleLink) {
|
|
223
244
|
activateGemLink(firstVisibleLink, "replace", true);
|
|
@@ -263,6 +284,20 @@
|
|
|
263
284
|
});
|
|
264
285
|
});
|
|
265
286
|
|
|
287
|
+
ecosystemButtons.forEach((button) => {
|
|
288
|
+
button.addEventListener("click", () => {
|
|
289
|
+
currentPackageScope = button.dataset.ecosystemButton;
|
|
290
|
+
applyGemFilter(currentFilter);
|
|
291
|
+
if (sidebarPanel) {
|
|
292
|
+
sidebarPanel.scrollTop = 0;
|
|
293
|
+
}
|
|
294
|
+
const url = new URL(window.location.href);
|
|
295
|
+
url.searchParams.set("scope", currentPackageScope);
|
|
296
|
+
window.history.replaceState({}, "", url);
|
|
297
|
+
syncSidebarSelection(null, true);
|
|
298
|
+
});
|
|
299
|
+
});
|
|
300
|
+
|
|
266
301
|
if (gemSearch) {
|
|
267
302
|
gemSearch.addEventListener("input", (event) => {
|
|
268
303
|
currentSearch = event.target.value || "";
|
|
@@ -293,19 +328,19 @@
|
|
|
293
328
|
event.target.value = "<%= selected_project_index %>";
|
|
294
329
|
return;
|
|
295
330
|
}
|
|
296
|
-
navigate({ project: event.target.value, from: null, to: "worktree", filter: currentFilter, gem: null });
|
|
331
|
+
navigate({ project: event.target.value, from: null, to: "worktree", filter: currentFilter, scope: currentPackageScope, package: null, gem: null });
|
|
297
332
|
});
|
|
298
333
|
}
|
|
299
334
|
|
|
300
335
|
if (fromSelect) {
|
|
301
336
|
fromSelect.addEventListener("change", (event) => {
|
|
302
|
-
navigate({ from: event.target.value, filter: currentFilter, gem: null });
|
|
337
|
+
navigate({ from: event.target.value, filter: currentFilter, scope: currentPackageScope, package: null, gem: null });
|
|
303
338
|
});
|
|
304
339
|
}
|
|
305
340
|
|
|
306
341
|
if (toSelect) {
|
|
307
342
|
toSelect.addEventListener("change", (event) => {
|
|
308
|
-
navigate({ to: event.target.value, filter: currentFilter, gem: null });
|
|
343
|
+
navigate({ to: event.target.value, filter: currentFilter, scope: currentPackageScope, package: null, gem: null });
|
|
309
344
|
});
|
|
310
345
|
}
|
|
311
346
|
|
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
<meta charset="utf-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
6
|
<title><%= title %></title>
|
|
7
|
-
<link rel="icon" href="
|
|
7
|
+
<link rel="icon" href="/favicon.svg" type="image/svg+xml">
|
|
8
|
+
<link rel="shortcut icon" href="/favicon.ico">
|
|
8
9
|
<style>
|
|
9
10
|
<%= styles_css %>
|
|
10
11
|
</style>
|
data/lib/gemstar.rb
CHANGED
|
@@ -15,7 +15,10 @@ require "gemstar/outputs/markdown"
|
|
|
15
15
|
require "gemstar/cache"
|
|
16
16
|
require "gemstar/change_log"
|
|
17
17
|
require "gemstar/git_hub"
|
|
18
|
+
require "gemstar/importmap_file"
|
|
18
19
|
require "gemstar/lock_file"
|
|
20
|
+
require "gemstar/npm_metadata"
|
|
21
|
+
require "gemstar/package_lock_file"
|
|
19
22
|
require "gemstar/project"
|
|
20
23
|
require "gemstar/remote_repository"
|
|
21
24
|
require "gemstar/utils"
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: gemstar
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: '1.1'
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Florian Dejako
|
|
@@ -243,12 +243,17 @@ files:
|
|
|
243
243
|
- lib/gemstar/commands/diff.rb
|
|
244
244
|
- lib/gemstar/commands/server.rb
|
|
245
245
|
- lib/gemstar/config.rb
|
|
246
|
+
- lib/gemstar/data/importmap_package_metadata.json
|
|
247
|
+
- lib/gemstar/data/ruby_gems_metadata.json
|
|
246
248
|
- lib/gemstar/git_hub.rb
|
|
247
249
|
- lib/gemstar/git_repo.rb
|
|
250
|
+
- lib/gemstar/importmap_file.rb
|
|
248
251
|
- lib/gemstar/lock_file.rb
|
|
252
|
+
- lib/gemstar/npm_metadata.rb
|
|
249
253
|
- lib/gemstar/outputs/basic.rb
|
|
250
254
|
- lib/gemstar/outputs/html.rb
|
|
251
255
|
- lib/gemstar/outputs/markdown.rb
|
|
256
|
+
- lib/gemstar/package_lock_file.rb
|
|
252
257
|
- lib/gemstar/project.rb
|
|
253
258
|
- lib/gemstar/remote_repository.rb
|
|
254
259
|
- lib/gemstar/request_logger.rb
|