@sprig-and-prose/sprig-ui-csr 0.1.2 → 0.2.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.
- package/dist/assets/index-59_3EkH_.css +1 -0
- package/dist/assets/index-B6I7oo2K.js +1 -0
- package/dist/assets/index-BzteO077.js +4 -0
- package/{index.html → dist/index.html} +2 -1
- package/package.json +6 -1
- package/src/App.svelte +30 -7
- package/src/lib/components/GlobalSearch.svelte +17 -1
- package/src/lib/data/universeStore.js +4 -3
- package/src/lib/router.js +12 -0
- package/src/pages/ConceptPage.svelte +146 -296
- package/src/pages/ReferencePage.svelte +104 -0
- package/src/pages/SeriesPage.svelte +146 -296
- package/biome.json +0 -37
- package/manifest.json +0 -10711
- package/src/lib/references/isWildcardPath.js +0 -9
- package/src/lib/references/linkForPath.js +0 -65
- package/src/lib/references/linkForRepository.js +0 -42
- package/tsconfig.json +0 -16
- package/vite.config.js +0 -10
|
@@ -5,9 +5,7 @@
|
|
|
5
5
|
import ContentsCard from '../lib/components/ContentsCard.svelte';
|
|
6
6
|
import FooterStatus from '../lib/components/FooterStatus.svelte';
|
|
7
7
|
import PageHeader from '../lib/components/PageHeader.svelte';
|
|
8
|
-
|
|
9
|
-
import { linkForRepository } from '../lib/references/linkForRepository.js';
|
|
10
|
-
import { isWildcardPath } from '../lib/references/isWildcardPath.js';
|
|
8
|
+
// Reference routing stays internal for concept pages
|
|
11
9
|
|
|
12
10
|
/** @type {{ universe: string, id: string }} */
|
|
13
11
|
export let params;
|
|
@@ -17,7 +15,7 @@
|
|
|
17
15
|
|
|
18
16
|
/**
|
|
19
17
|
* @typedef {{ raw?:string, normalized?:string, source?:any }} TextBlock
|
|
20
|
-
* @typedef {{
|
|
18
|
+
* @typedef {{ id:string, name:string, kind?:string, title?:string, describe?:TextBlock, note?:TextBlock, urls?:string[], paths?:string[], repositoryRef?:string }} ReferenceModel
|
|
21
19
|
*/
|
|
22
20
|
|
|
23
21
|
// Decode the node ID from URL
|
|
@@ -84,133 +82,50 @@
|
|
|
84
82
|
.filter((node) => node.kind === 'chapter' && node.id !== currentNode.id);
|
|
85
83
|
})();
|
|
86
84
|
|
|
85
|
+
$: referenceItems = (currentNode?.references || [])
|
|
86
|
+
.map((id) => $universeGraph?.references?.[id])
|
|
87
|
+
.filter(Boolean);
|
|
88
|
+
|
|
87
89
|
/**
|
|
88
|
-
*
|
|
89
|
-
* @param {
|
|
90
|
-
* @returns {Array<{path:string, describe?:TextBlock}>}
|
|
90
|
+
* @param {string} url
|
|
91
|
+
* @param {string | undefined} label
|
|
91
92
|
*/
|
|
92
|
-
function
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
// Shape B: paths is array of objects
|
|
96
|
-
if (typeof ref.paths[0] === 'object' && ref.paths[0] !== null && 'path' in ref.paths[0]) {
|
|
97
|
-
return ref.paths.map((/** @type {{path:string, describe?:TextBlock}} */ p) => ({
|
|
98
|
-
path: p.path,
|
|
99
|
-
describe: p.describe,
|
|
100
|
-
}));
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
// Shape A: paths is array of strings
|
|
104
|
-
return ref.paths.map((/** @type {string} */ p) => ({
|
|
105
|
-
path: p,
|
|
106
|
-
describe: undefined,
|
|
107
|
-
}));
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
// Group references by repository, preserving source order
|
|
111
|
-
$: groupedReferences = (() => {
|
|
112
|
-
const refs = currentNode?.references || [];
|
|
113
|
-
if (refs.length === 0) return [];
|
|
114
|
-
|
|
115
|
-
const groups = new Map();
|
|
116
|
-
const order = [];
|
|
117
|
-
|
|
118
|
-
for (const ref of refs) {
|
|
119
|
-
const repo = ref.repository;
|
|
120
|
-
if (!groups.has(repo)) {
|
|
121
|
-
groups.set(repo, {
|
|
122
|
-
referenceGroups: [],
|
|
123
|
-
});
|
|
124
|
-
order.push(repo);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
const group = groups.get(repo);
|
|
128
|
-
const normalizedPaths = normalizePaths(ref);
|
|
129
|
-
const pathEntries = normalizedPaths.map((pathEntry) => ({
|
|
130
|
-
path: pathEntry.path,
|
|
131
|
-
perPathDescribe: pathEntry.describe,
|
|
132
|
-
}));
|
|
133
|
-
|
|
134
|
-
group.referenceGroups.push({
|
|
135
|
-
paths: pathEntries,
|
|
136
|
-
groupDescribe: ref.describe?.normalized || undefined,
|
|
137
|
-
});
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
return order.map((repo) => ({
|
|
141
|
-
repository: repo,
|
|
142
|
-
referenceGroups: groups.get(repo).referenceGroups,
|
|
143
|
-
}));
|
|
144
|
-
})();
|
|
93
|
+
function makeLinkLabel(url, label) {
|
|
94
|
+
return label && label.trim().length > 0 ? label : url;
|
|
95
|
+
}
|
|
145
96
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
97
|
+
/**
|
|
98
|
+
* @param {ReferenceModel} ref
|
|
99
|
+
*/
|
|
100
|
+
function getRepositoryForReference(ref) {
|
|
101
|
+
if (!ref.repositoryRef || !$universeGraph?.repositories) return null;
|
|
102
|
+
return $universeGraph.repositories[ref.repositoryRef] || null;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
$: referenceGroups = (() => {
|
|
106
|
+
/** @type {Array<{ repo: any | null, refs: ReferenceModel[] }>} */
|
|
107
|
+
const groups = [];
|
|
108
|
+
const byRepo = new Map();
|
|
109
|
+
|
|
110
|
+
for (const ref of referenceItems) {
|
|
111
|
+
if (!ref) continue;
|
|
112
|
+
if (ref.repositoryRef) {
|
|
113
|
+
let group = byRepo.get(ref.repositoryRef);
|
|
114
|
+
if (!group) {
|
|
115
|
+
const repo = getRepositoryForReference(ref);
|
|
116
|
+
group = { repo, refs: [] };
|
|
117
|
+
byRepo.set(ref.repositoryRef, group);
|
|
118
|
+
groups.push(group);
|
|
161
119
|
}
|
|
162
|
-
|
|
163
|
-
}
|
|
164
|
-
return urls;
|
|
165
|
-
})();
|
|
166
|
-
|
|
167
|
-
// Helper function to generate path URLs reactively
|
|
168
|
-
function getPathUrl(repository, path) {
|
|
169
|
-
const graph = $universeGraph;
|
|
170
|
-
if (!graph?.repositories) return null;
|
|
171
|
-
const repoConfig = graph.repositories[repository];
|
|
172
|
-
if (!repoConfig) return null;
|
|
173
|
-
const { kind, options } = repoConfig;
|
|
174
|
-
const defaultBranch = options?.defaultBranch || 'main';
|
|
175
|
-
|
|
176
|
-
if (kind === 'sprig-repository-github') {
|
|
177
|
-
let baseUrl;
|
|
178
|
-
if (options?.url) {
|
|
179
|
-
baseUrl = options.url;
|
|
180
|
-
} else if (options?.owner && options?.repo) {
|
|
181
|
-
baseUrl = `https://github.com/${options.owner}/${options.repo}`;
|
|
120
|
+
group.refs.push(ref);
|
|
182
121
|
} else {
|
|
183
|
-
|
|
184
|
-
}
|
|
185
|
-
const normalizedBaseUrl = baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl;
|
|
186
|
-
const normalizedPath = path.startsWith('/') ? path : `/${path}`;
|
|
187
|
-
|
|
188
|
-
if (isWildcardPath(path)) {
|
|
189
|
-
const lastSlashIndex = normalizedPath.lastIndexOf('/');
|
|
190
|
-
if (lastSlashIndex > 0) {
|
|
191
|
-
const folderPath = normalizedPath.slice(0, lastSlashIndex);
|
|
192
|
-
return `${normalizedBaseUrl}/tree/${defaultBranch}${folderPath}`;
|
|
193
|
-
}
|
|
194
|
-
return `${normalizedBaseUrl}/tree/${defaultBranch}`;
|
|
122
|
+
groups.push({ repo: null, refs: [ref] });
|
|
195
123
|
}
|
|
196
|
-
return `${normalizedBaseUrl}/blob/${defaultBranch}${normalizedPath}`;
|
|
197
124
|
}
|
|
198
|
-
return null;
|
|
199
|
-
}
|
|
200
125
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
*/
|
|
204
|
-
function toggleGroup(repository) {
|
|
205
|
-
if (expandedGroups.has(repository)) {
|
|
206
|
-
expandedGroups.delete(repository);
|
|
207
|
-
} else {
|
|
208
|
-
expandedGroups.add(repository);
|
|
209
|
-
}
|
|
210
|
-
expandedGroups = expandedGroups; // Trigger reactivity
|
|
211
|
-
}
|
|
126
|
+
return groups;
|
|
127
|
+
})();
|
|
212
128
|
|
|
213
|
-
const DEFAULT_VISIBLE_PATHS = 3;
|
|
214
129
|
|
|
215
130
|
$: subtitle = (() => {
|
|
216
131
|
if (showContextLine) {
|
|
@@ -321,100 +236,68 @@
|
|
|
321
236
|
</section>
|
|
322
237
|
{/if}
|
|
323
238
|
|
|
324
|
-
{#if
|
|
239
|
+
{#if referenceItems.length > 0}
|
|
325
240
|
<section class="references">
|
|
326
241
|
<h2 class="references-title">References</h2>
|
|
327
242
|
<p class="references-subtitle">Where this concept appears in code and docs.</p>
|
|
328
243
|
|
|
329
|
-
|
|
330
|
-
{
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
{#if url}
|
|
373
|
-
<a class="reference-path-link sprig-link sprig-link--quiet" href={url} target="_blank" rel="noopener noreferrer">
|
|
374
|
-
<span class="reference-path-text">{path}</span>
|
|
375
|
-
{#if isWildcard}
|
|
376
|
-
<span class="reference-path-wildcard">(pattern)</span>
|
|
377
|
-
{/if}
|
|
378
|
-
</a>
|
|
379
|
-
{:else}
|
|
380
|
-
<span class="reference-path-text">{path}</span>
|
|
381
|
-
{#if isWildcard}
|
|
382
|
-
<span class="reference-path-wildcard">(pattern)</span>
|
|
244
|
+
<ul class="reference-list">
|
|
245
|
+
{#each referenceGroups as group}
|
|
246
|
+
<li class="reference-item">
|
|
247
|
+
{#if group.repo}
|
|
248
|
+
<a
|
|
249
|
+
class="reference-repo-pill sprig-link"
|
|
250
|
+
href={group.repo.url}
|
|
251
|
+
target="_blank"
|
|
252
|
+
rel="noopener noreferrer"
|
|
253
|
+
>
|
|
254
|
+
{group.repo.title || group.repo.name}
|
|
255
|
+
</a>
|
|
256
|
+
{/if}
|
|
257
|
+
<ul class="reference-group-list">
|
|
258
|
+
{#each group.refs as ref}
|
|
259
|
+
<li class="reference-group-item">
|
|
260
|
+
{#if ref.urls && ref.urls.length > 0}
|
|
261
|
+
{#if ref.urls.length === 1}
|
|
262
|
+
{@const label = makeLinkLabel(ref.urls[0], ref.paths?.[0])}
|
|
263
|
+
<div class="reference-row">
|
|
264
|
+
<a class="reference-path-link sprig-link" href={ref.urls[0]} target="_blank" rel="noopener noreferrer">
|
|
265
|
+
{label}
|
|
266
|
+
</a>
|
|
267
|
+
{#if ref.kind}
|
|
268
|
+
<span class="reference-kind">{ref.kind}</span>
|
|
269
|
+
{/if}
|
|
270
|
+
</div>
|
|
271
|
+
{:else}
|
|
272
|
+
<ul class="reference-links-list">
|
|
273
|
+
{#each ref.urls as url, index}
|
|
274
|
+
{@const label = makeLinkLabel(url, ref.paths?.[index])}
|
|
275
|
+
<li class="reference-links-item">
|
|
276
|
+
<div class="reference-row">
|
|
277
|
+
<a class="reference-path-link sprig-link" href={url} target="_blank" rel="noopener noreferrer">
|
|
278
|
+
{label}
|
|
279
|
+
</a>
|
|
280
|
+
{#if ref.kind && index === 0}
|
|
281
|
+
<span class="reference-kind">{ref.kind}</span>
|
|
282
|
+
{/if}
|
|
283
|
+
</div>
|
|
284
|
+
</li>
|
|
285
|
+
{/each}
|
|
286
|
+
</ul>
|
|
383
287
|
{/if}
|
|
384
288
|
{/if}
|
|
385
|
-
{#if
|
|
386
|
-
<p class="reference-description
|
|
289
|
+
{#if ref.describe?.normalized}
|
|
290
|
+
<p class="reference-description">{ref.describe.normalized}</p>
|
|
291
|
+
{/if}
|
|
292
|
+
{#if ref.note?.normalized}
|
|
293
|
+
<p class="reference-note">{ref.note.normalized}</p>
|
|
387
294
|
{/if}
|
|
388
295
|
</li>
|
|
389
296
|
{/each}
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
{/if}
|
|
395
|
-
{/each}
|
|
396
|
-
</ul>
|
|
397
|
-
|
|
398
|
-
{#if hiddenCount > 0 && !isExpanded}
|
|
399
|
-
<button
|
|
400
|
-
class="reference-expand-button"
|
|
401
|
-
on:click={() => toggleGroup(group.repository)}
|
|
402
|
-
type="button"
|
|
403
|
-
>
|
|
404
|
-
+ {hiddenCount} more path{hiddenCount === 1 ? '' : 's'}
|
|
405
|
-
</button>
|
|
406
|
-
{/if}
|
|
407
|
-
{#if isExpanded && hiddenCount > 0}
|
|
408
|
-
<button
|
|
409
|
-
class="reference-expand-button"
|
|
410
|
-
on:click={() => toggleGroup(group.repository)}
|
|
411
|
-
type="button"
|
|
412
|
-
>
|
|
413
|
-
Show less
|
|
414
|
-
</button>
|
|
415
|
-
{/if}
|
|
416
|
-
</div>
|
|
417
|
-
{/each}
|
|
297
|
+
</ul>
|
|
298
|
+
</li>
|
|
299
|
+
{/each}
|
|
300
|
+
</ul>
|
|
418
301
|
</section>
|
|
419
302
|
{/if}
|
|
420
303
|
|
|
@@ -577,13 +460,13 @@
|
|
|
577
460
|
|
|
578
461
|
.relationship-label {
|
|
579
462
|
font-family: var(--font-ui);
|
|
580
|
-
font-size: var(--sp-font-
|
|
463
|
+
font-size: var(--sp-font-small);
|
|
581
464
|
color: var(--text-secondary);
|
|
582
465
|
}
|
|
583
466
|
|
|
584
467
|
.relationship-separator {
|
|
585
468
|
font-family: var(--font-ui);
|
|
586
|
-
font-size: var(--sp-font-
|
|
469
|
+
font-size: var(--sp-font-small);
|
|
587
470
|
color: var(--text-tertiary);
|
|
588
471
|
opacity: 0.6;
|
|
589
472
|
}
|
|
@@ -637,101 +520,59 @@
|
|
|
637
520
|
margin: 0 0 1.5rem 0;
|
|
638
521
|
}
|
|
639
522
|
|
|
640
|
-
.reference-
|
|
523
|
+
.reference-list {
|
|
524
|
+
list-style: none;
|
|
525
|
+
padding: 0;
|
|
526
|
+
margin: 0;
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
.reference-item {
|
|
641
530
|
margin-bottom: 2rem;
|
|
642
531
|
}
|
|
643
532
|
|
|
644
|
-
.reference-
|
|
533
|
+
.reference-item:last-child {
|
|
645
534
|
margin-bottom: 0;
|
|
646
535
|
}
|
|
647
536
|
|
|
537
|
+
|
|
648
538
|
.reference-repo-pill {
|
|
649
539
|
display: inline-flex;
|
|
650
540
|
align-items: center;
|
|
651
541
|
gap: 6px;
|
|
652
|
-
padding:
|
|
653
|
-
|
|
654
|
-
border-radius: 6px;
|
|
655
|
-
text-decoration: none;
|
|
656
|
-
color: inherit;
|
|
657
|
-
margin-bottom: 0.75rem;
|
|
658
|
-
transition: opacity 0.2s;
|
|
659
|
-
}
|
|
660
|
-
|
|
661
|
-
.reference-repo-pill:hover {
|
|
662
|
-
opacity: 0.8;
|
|
663
|
-
}
|
|
664
|
-
|
|
665
|
-
.reference-repo-pill--no-link {
|
|
666
|
-
cursor: default;
|
|
667
|
-
}
|
|
668
|
-
|
|
669
|
-
.reference-repo-pill--no-link:hover {
|
|
670
|
-
opacity: 1;
|
|
671
|
-
}
|
|
672
|
-
|
|
673
|
-
.reference-repo-label {
|
|
542
|
+
padding: 2px 10px;
|
|
543
|
+
border-radius: 999px;
|
|
674
544
|
font-family: var(--font-ui);
|
|
675
|
-
font-size: var(--sp-font-
|
|
676
|
-
letter-spacing: 0.05em;
|
|
545
|
+
font-size: var(--sp-font-small);
|
|
677
546
|
text-transform: lowercase;
|
|
678
547
|
color: var(--text-tertiary);
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
.reference-repo-name {
|
|
683
|
-
font-family: var(--font-ui);
|
|
684
|
-
font-size: var(--sp-font-tiny);
|
|
685
|
-
color: var(--text-secondary);
|
|
686
|
-
font-weight: 400;
|
|
687
|
-
}
|
|
688
|
-
|
|
689
|
-
.reference-paths-list {
|
|
690
|
-
list-style: none;
|
|
691
|
-
padding: 0;
|
|
692
|
-
margin: 0;
|
|
693
|
-
}
|
|
694
|
-
|
|
695
|
-
.reference-path-item {
|
|
696
|
-
margin-bottom: 0.75rem;
|
|
697
|
-
}
|
|
698
|
-
|
|
699
|
-
.reference-path-item:last-child {
|
|
700
|
-
margin-bottom: 0;
|
|
701
|
-
}
|
|
702
|
-
|
|
703
|
-
.reference-path-item--tight {
|
|
704
|
-
margin-bottom: 0.25rem;
|
|
705
|
-
}
|
|
706
|
-
|
|
707
|
-
.reference-path-item--spaced {
|
|
708
|
-
margin-top: 0.75rem;
|
|
709
|
-
}
|
|
710
|
-
|
|
711
|
-
.reference-path-item--describe {
|
|
712
|
-
margin-top: 0.5rem;
|
|
713
|
-
margin-bottom: 0.75rem;
|
|
548
|
+
border: 1px solid var(--hairline);
|
|
549
|
+
margin-bottom: 1rem;
|
|
550
|
+
text-decoration: none;
|
|
714
551
|
}
|
|
715
552
|
|
|
716
553
|
.reference-path-link {
|
|
717
554
|
display: block;
|
|
718
|
-
|
|
719
|
-
}
|
|
720
|
-
|
|
721
|
-
.reference-path-text {
|
|
555
|
+
margin-top: 2px;
|
|
722
556
|
font-family: ui-monospace, 'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', Consolas, 'Courier New', monospace;
|
|
723
557
|
font-size: var(--sp-font-body);
|
|
724
558
|
color: inherit;
|
|
725
|
-
|
|
726
|
-
|
|
559
|
+
text-decoration: underline;
|
|
560
|
+
text-decoration-thickness: 1px;
|
|
561
|
+
text-underline-offset: 0.1875rem;
|
|
562
|
+
text-decoration-color: var(--sprig-link-underline);
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
.reference-row {
|
|
566
|
+
display: flex;
|
|
567
|
+
align-items: baseline;
|
|
568
|
+
gap: 8px;
|
|
727
569
|
}
|
|
728
570
|
|
|
729
|
-
.reference-
|
|
571
|
+
.reference-kind {
|
|
572
|
+
margin-left: auto;
|
|
730
573
|
font-family: var(--font-ui);
|
|
731
|
-
font-size: var(--sp-font-
|
|
574
|
+
font-size: var(--sp-font-small);
|
|
732
575
|
color: var(--text-tertiary);
|
|
733
|
-
margin-left: 4px;
|
|
734
|
-
font-weight: 400;
|
|
735
576
|
}
|
|
736
577
|
|
|
737
578
|
.reference-description {
|
|
@@ -743,29 +584,37 @@
|
|
|
743
584
|
max-width: 70ch;
|
|
744
585
|
}
|
|
745
586
|
|
|
746
|
-
.reference-
|
|
747
|
-
margin
|
|
587
|
+
.reference-note {
|
|
588
|
+
margin: 6px 0 0 0;
|
|
589
|
+
font-family: var(--font-prose);
|
|
590
|
+
font-size: var(--sp-font-body);
|
|
591
|
+
color: var(--text-secondary);
|
|
592
|
+
line-height: 1.5;
|
|
593
|
+
max-width: 70ch;
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
.reference-links-list {
|
|
597
|
+
list-style: none;
|
|
598
|
+
padding: 0;
|
|
599
|
+
margin: 8px 0 0 0;
|
|
748
600
|
}
|
|
749
601
|
|
|
750
|
-
.reference-
|
|
602
|
+
.reference-group-list {
|
|
603
|
+
list-style: none;
|
|
604
|
+
padding: 0;
|
|
751
605
|
margin: 0;
|
|
752
606
|
}
|
|
753
607
|
|
|
754
|
-
.reference-
|
|
755
|
-
|
|
756
|
-
border: none;
|
|
757
|
-
color: var(--text-tertiary);
|
|
758
|
-
font-family: var(--font-ui);
|
|
759
|
-
font-size: var(--sp-font-tiny);
|
|
760
|
-
padding: 4px 0;
|
|
761
|
-
margin-top: 0.5rem;
|
|
762
|
-
cursor: pointer;
|
|
763
|
-
text-decoration: underline;
|
|
764
|
-
text-underline-offset: 2px;
|
|
608
|
+
.reference-group-item + .reference-group-item {
|
|
609
|
+
margin-top: 2rem;
|
|
765
610
|
}
|
|
766
611
|
|
|
767
|
-
.reference-
|
|
768
|
-
|
|
612
|
+
.reference-links-item {
|
|
613
|
+
margin-bottom: 6px;
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
.reference-links-item:last-child {
|
|
617
|
+
margin-bottom: 0;
|
|
769
618
|
}
|
|
770
619
|
|
|
771
620
|
.documentation {
|
|
@@ -871,3 +720,4 @@
|
|
|
871
720
|
}
|
|
872
721
|
</style>
|
|
873
722
|
|
|
723
|
+
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { universeGraph, currentUniverseName, universeRootNode } from '../lib/data/universeStore.js';
|
|
3
|
+
import PageHeader from '../lib/components/PageHeader.svelte';
|
|
4
|
+
import Prose from '../lib/components/Prose.svelte';
|
|
5
|
+
import FooterStatus from '../lib/components/FooterStatus.svelte';
|
|
6
|
+
|
|
7
|
+
/** @type {{ universe: string, id: string }} */
|
|
8
|
+
export let params;
|
|
9
|
+
|
|
10
|
+
$: currentUniverseName.set(params.universe);
|
|
11
|
+
$: referenceId = decodeURIComponent(params.id);
|
|
12
|
+
$: reference = $universeGraph?.references?.[referenceId];
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @param {string} url
|
|
16
|
+
* @param {string | undefined} label
|
|
17
|
+
*/
|
|
18
|
+
function makeLinkLabel(url, label) {
|
|
19
|
+
return label && label.trim().length > 0 ? label : url;
|
|
20
|
+
}
|
|
21
|
+
</script>
|
|
22
|
+
|
|
23
|
+
{#if reference}
|
|
24
|
+
{@const displayTitle = reference.title || reference.name}
|
|
25
|
+
<PageHeader title={displayTitle} subtitle={reference.kind || ''} />
|
|
26
|
+
|
|
27
|
+
<section class="reference-section">
|
|
28
|
+
{#if reference.describe}
|
|
29
|
+
<Prose textBlock={reference.describe} />
|
|
30
|
+
{/if}
|
|
31
|
+
</section>
|
|
32
|
+
|
|
33
|
+
{#if reference.note}
|
|
34
|
+
<section class="reference-section">
|
|
35
|
+
<h2 class="reference-section-title">Note</h2>
|
|
36
|
+
<Prose textBlock={reference.note} />
|
|
37
|
+
</section>
|
|
38
|
+
{/if}
|
|
39
|
+
|
|
40
|
+
<section class="reference-section">
|
|
41
|
+
<h2 class="reference-section-title">Links</h2>
|
|
42
|
+
{#if reference.urls.length === 1}
|
|
43
|
+
{@const label = makeLinkLabel(reference.urls[0], reference.paths?.[0])}
|
|
44
|
+
<a class="reference-link sprig-link" href={reference.urls[0]} target="_blank" rel="noopener noreferrer">
|
|
45
|
+
{label}
|
|
46
|
+
</a>
|
|
47
|
+
{:else}
|
|
48
|
+
<ul class="reference-links-list">
|
|
49
|
+
{#each reference.urls as url, index}
|
|
50
|
+
{@const label = makeLinkLabel(url, reference.paths?.[index])}
|
|
51
|
+
<li class="reference-links-item">
|
|
52
|
+
<a class="reference-link sprig-link" href={url} target="_blank" rel="noopener noreferrer">
|
|
53
|
+
{label}
|
|
54
|
+
</a>
|
|
55
|
+
</li>
|
|
56
|
+
{/each}
|
|
57
|
+
</ul>
|
|
58
|
+
{/if}
|
|
59
|
+
</section>
|
|
60
|
+
|
|
61
|
+
<FooterStatus graph={$universeGraph} root={$universeRootNode} />
|
|
62
|
+
{:else}
|
|
63
|
+
<div class="loading">Reference not found.</div>
|
|
64
|
+
{/if}
|
|
65
|
+
|
|
66
|
+
<style>
|
|
67
|
+
.reference-section {
|
|
68
|
+
margin-top: 24px;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
.reference-section-title {
|
|
72
|
+
font-family: var(--font-ui);
|
|
73
|
+
font-size: var(--sp-font-tiny);
|
|
74
|
+
color: var(--text-secondary);
|
|
75
|
+
margin: 0 0 0.75rem 0;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.reference-links-list {
|
|
79
|
+
list-style: none;
|
|
80
|
+
padding: 0;
|
|
81
|
+
margin: 0;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.reference-links-item {
|
|
85
|
+
margin-bottom: 0.5rem;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.reference-links-item:last-child {
|
|
89
|
+
margin-bottom: 0;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.reference-link {
|
|
93
|
+
display: inline-block;
|
|
94
|
+
font-family: ui-monospace, 'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', Consolas, 'Courier New', monospace;
|
|
95
|
+
font-size: var(--sp-font-body);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.loading {
|
|
99
|
+
color: var(--text-tertiary);
|
|
100
|
+
padding: 24px 0;
|
|
101
|
+
}
|
|
102
|
+
</style>
|
|
103
|
+
|
|
104
|
+
|