Skip to content

Commit 32dcc82

Browse files
committed
Rewrite extensions list
1 parent b3b6ac1 commit 32dcc82

File tree

7 files changed

+660
-126
lines changed

7 files changed

+660
-126
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,5 @@ pnpm-debug.log*
2222
# shut up
2323
/.vscode
2424
/.idea
25+
26+
/.extensions-list-cache.json

astro.config.mjs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,10 @@ export default defineConfig({
7676
{
7777
label: "moonlight developers",
7878
autogenerate: { directory: "dev" }
79+
},
80+
{
81+
label: "Extensions list",
82+
link: "/extensions-list"
7983
}
8084
],
8185
components: {
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
---
2+
import type { ExtensionManifest } from "./shared";
3+
import ExtensionInfo from "./ExtensionInfo.astro";
4+
import { Tabs, TabItem, LinkButton } from "@astrojs/starlight/components";
5+
import AnchorHeading from "@astrojs/starlight/components/AnchorHeading.astro";
6+
import { marked } from "marked";
7+
import type { StarlightIcon } from "@astrojs/starlight/types";
8+
9+
interface Props {
10+
extensions: ExtensionManifest[];
11+
ext: ExtensionManifest;
12+
}
13+
14+
const { extensions, ext } = Astro.props;
15+
16+
const tagline = ext.meta?.tagline;
17+
const description = ext.meta?.description;
18+
const changelog = ext.meta?.changelog;
19+
const settings = ext.settings;
20+
21+
type ExtensionLink = {
22+
href?: string;
23+
icon: StarlightIcon;
24+
title: string;
25+
};
26+
27+
const links = (
28+
[
29+
{
30+
href: ext.meta?.source,
31+
icon: "seti:html",
32+
title: "View source"
33+
},
34+
{
35+
href: ext.meta?.donate,
36+
icon: "heart",
37+
title: "Donate"
38+
},
39+
{
40+
href: ext.download,
41+
icon: "download",
42+
title: "Download .asar"
43+
}
44+
] satisfies ExtensionLink[]
45+
).filter((link) => link.href != null);
46+
---
47+
48+
<AnchorHeading level="2" id={ext.id}>
49+
{ext.meta?.name || ext.id}
50+
</AnchorHeading>
51+
52+
{
53+
tagline != null && (
54+
<div class="tagline">
55+
<Fragment set:html={marked(tagline)} />
56+
</div>
57+
)
58+
}
59+
60+
<Tabs>
61+
<TabItem label="Info">
62+
<ExtensionInfo {extensions} {ext} />
63+
</TabItem>
64+
65+
{
66+
description != null && (
67+
<TabItem label="Description">
68+
<Fragment set:html={marked(description)} />
69+
</TabItem>
70+
)
71+
}
72+
73+
{
74+
changelog != null && (
75+
<TabItem label="Changelog">
76+
<Fragment set:html={marked(changelog)} />
77+
</TabItem>
78+
)
79+
}
80+
81+
{
82+
settings != null && (
83+
<TabItem label="Settings">
84+
<ul>
85+
{Object.entries(settings).map(([key, value]) => (
86+
<li>
87+
<span title={value.description}>{value.displayName ?? key}</span>
88+
</li>
89+
))}
90+
</ul>
91+
</TabItem>
92+
)
93+
}
94+
95+
{
96+
links.length !== 0 && (
97+
<TabItem label="Links">
98+
{links.map((link) => (
99+
<LinkButton
100+
href={link.href!}
101+
icon={link.icon}
102+
iconPlacement="start"
103+
variant="secondary"
104+
>
105+
{link.title}
106+
</LinkButton>
107+
))}
108+
</TabItem>
109+
)
110+
}
111+
</Tabs>
112+
113+
<style>
114+
.tagline {
115+
margin: 0;
116+
}
117+
</style>
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
---
2+
import InfoSection from "./InfoSection.astro";
3+
import { Badge } from "@astrojs/starlight/components";
4+
import {
5+
tryGetExtensionName,
6+
tagNames,
7+
ExtensionTag,
8+
DependencyType,
9+
type ExtensionManifest,
10+
type Dependency
11+
} from "./shared";
12+
13+
interface Props {
14+
extensions: ExtensionManifest[];
15+
ext: ExtensionManifest;
16+
}
17+
18+
const { extensions, ext } = Astro.props;
19+
20+
const authors = ext.meta?.authors;
21+
const tags = ext.meta?.tags;
22+
const version = ext.version;
23+
24+
const dependencies: Dependency[] = [];
25+
const incompatible: Dependency[] = [];
26+
27+
if (ext.dependencies != null) {
28+
dependencies.push(
29+
...ext.dependencies.map((dep) => ({
30+
id: dep,
31+
type: DependencyType.Dependency
32+
}))
33+
);
34+
}
35+
36+
if (ext.suggested != null) {
37+
dependencies.push(
38+
...ext.suggested.map((dep) => ({
39+
id: dep,
40+
type: DependencyType.Optional
41+
}))
42+
);
43+
}
44+
45+
if (ext.incompatible != null) {
46+
incompatible.push(
47+
...ext.incompatible.map((dep) => ({
48+
id: dep,
49+
type: DependencyType.Incompatible
50+
}))
51+
);
52+
}
53+
---
54+
55+
<div class="extensionInfo">
56+
{
57+
authors != null && (
58+
<InfoSection title="Authors">
59+
<span>
60+
{authors
61+
.map((author) =>
62+
typeof author === "string" ? author : author.name
63+
)
64+
.join(", ")}
65+
</span>
66+
</InfoSection>
67+
)
68+
}
69+
70+
{
71+
tags != null && (
72+
<InfoSection title="Tags">
73+
{tags.map((tag) => (
74+
<Badge
75+
class="badge"
76+
text={tagNames[tag]}
77+
variant={tag === ExtensionTag.DangerZone ? "danger" : "note"}
78+
/>
79+
))}
80+
</InfoSection>
81+
)
82+
}
83+
84+
{
85+
dependencies.length > 0 && (
86+
<InfoSection title="Dependencies">
87+
{dependencies.map((dep) => (
88+
<Badge class="badge" text={tryGetExtensionName(extensions, dep.id)} />
89+
))}
90+
</InfoSection>
91+
)
92+
}
93+
94+
{
95+
incompatible.length > 0 && (
96+
<InfoSection title="Incompatible">
97+
{incompatible.map((dep) => (
98+
<Badge class="badge" text={tryGetExtensionName(extensions, dep.id)} />
99+
))}
100+
</InfoSection>
101+
)
102+
}
103+
104+
{
105+
version != null && (
106+
<InfoSection title="Version">
107+
<span>{version}</span>
108+
</InfoSection>
109+
)
110+
}
111+
</div>
112+
113+
<style>
114+
.extensionInfo {
115+
display: flex;
116+
gap: 1rem;
117+
flex-wrap: wrap;
118+
}
119+
120+
.badge {
121+
margin-right: 0.4em;
122+
}
123+
</style>
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
---
2+
interface Props {
3+
title: string;
4+
}
5+
6+
const { title } = Astro.props;
7+
---
8+
9+
<div class="infoSection">
10+
<span class="infoSectionTitle">{title}</span>
11+
<slot />
12+
</div>
13+
14+
<style>
15+
.infoSection {
16+
margin: 0 !important;
17+
}
18+
19+
.infoSectionTitle {
20+
font-weight: 700;
21+
display: block;
22+
}
23+
</style>

0 commit comments

Comments
 (0)