|
9 | 9 | import ArrowSquareOut from "phosphor-svelte/lib/ArrowSquareOut"; |
10 | 10 | import DownloadSimple from "phosphor-svelte/lib/DownloadSimple"; |
11 | 11 |
|
12 | | - let pluginDetails: { repository: string; name: string; author: string; download_url: string | undefined }; |
13 | | - let readme = "## Loading plugin details..."; |
14 | | - let download_count = 0; |
| 12 | + type Plugin = { repository: string; name: string; author: string; download_url: string | undefined }; |
| 13 | +
|
| 14 | + let pluginDetails: Plugin | 0; |
| 15 | + let readme = "<strong>Loading plugin details...</strong>"; |
| 16 | + let downloadCount = 0; |
15 | 17 |
|
16 | 18 | async function getTotalDownloadCount(repo: string): Promise<number> { |
17 | 19 | const response = await fetch("https://api.github.com/repos/" + repo + "/releases"); |
| 20 | + if (!response.ok) return 0; |
18 | 21 | const releases = await response.json(); |
19 | 22 |
|
20 | 23 | let totalCount = 0; |
21 | | - for (let release of releases) { |
22 | | - for (let asset of release.assets) { |
| 24 | + for (const release of releases) { |
| 25 | + for (const asset of release.assets) { |
23 | 26 | totalCount += asset.download_count; |
24 | 27 | } |
25 | 28 | } |
|
28 | 31 | } |
29 | 32 |
|
30 | 33 | async function getReadme(repo: string): Promise<string> { |
31 | | - let response = await fetch("https://raw.githubusercontent.com/" + repo + "/master/README.md"); |
32 | | - marked.use(baseUrl("https://raw.githubusercontent.com/" + repo + "/master/")); |
33 | | - return DOMPurify.sanitize(await response.text()); |
| 34 | + const renderer = new marked.Renderer(); |
| 35 | + renderer.link = function (token) { |
| 36 | + const rendered = marked.Renderer.prototype.link.call(this, token); |
| 37 | + return rendered.replace("<a", `<a target="_blank" `); |
| 38 | + }; |
| 39 | + marked.use({ renderer }); |
| 40 | + const urls = [ |
| 41 | + "https://raw.githubusercontent.com/" + repo + "/main/README.md", |
| 42 | + "https://raw.githubusercontent.com/" + repo + "/main/readme.md", |
| 43 | + "https://raw.githubusercontent.com/" + repo + "/master/README.md", |
| 44 | + "https://raw.githubusercontent.com/" + repo + "/master/readme.md", |
| 45 | + ]; |
| 46 | + for (const url of urls) { |
| 47 | + const response = await fetch(url); |
| 48 | + if (response.ok) { |
| 49 | + marked.use(baseUrl(url)); |
| 50 | + return await marked.parse(DOMPurify.sanitize(await response.text()).replace(/<a/g, '<a target="_blank" ')); |
| 51 | + } |
| 52 | + } |
| 53 | + return await marked.parse("**Plugin README file not found**\n\n[View plugin on GitHub](https://github.com/" + repo + ")"); |
34 | 54 | } |
35 | 55 |
|
36 | 56 | onMount(async () => { |
37 | 57 | const response = await fetch("https://openactionapi.github.io/plugins/catalogue.json"); |
38 | 58 | if (!response.ok) return; |
39 | 59 |
|
40 | 60 | const data = await response.json(); |
41 | | - pluginDetails = data[$page.params.id]; |
| 61 | + pluginDetails = data[$page.params.id!]; |
42 | 62 | if (!pluginDetails) { |
43 | | - // @ts-expect-error |
44 | | - pluginDetails = -1; |
| 63 | + pluginDetails = 0; |
45 | 64 | return; |
46 | 65 | } |
47 | 66 |
|
48 | 67 | const repo = pluginDetails.repository.split("/")[3] + "/" + pluginDetails.repository.split("/")[4]; |
49 | 68 | readme = await getReadme(repo); |
50 | | - download_count = await getTotalDownloadCount(repo); |
| 69 | + downloadCount = await getTotalDownloadCount(repo); |
51 | 70 | }); |
52 | 71 |
|
53 | 72 | function openDeepLink() { |
54 | | - let iframe = document.getElementById("deeplink-iframe") as HTMLIFrameElement; |
| 73 | + const iframe = document.getElementById("deeplink-iframe") as HTMLIFrameElement; |
55 | 74 | iframe.src = "opendeck://installPlugin/" + $page.params.id; |
56 | 75 | } |
57 | | -
|
58 | | - function getDownloadAction(): string { |
59 | | - if (pluginDetails.download_url) return pluginDetails.download_url; |
60 | | - return pluginDetails.repository + "/releases/latest"; |
61 | | - } |
62 | 76 | </script> |
63 | 77 |
|
64 | 78 | <svelte:head> |
|
72 | 86 | /> |
73 | 87 | </svelte:head> |
74 | 88 |
|
75 | | -{#if pluginDetails} |
76 | | - <div class="mx-[2.5%] my-[2.5%] p-10 w-[95vw] h-[90vh] flex flex-col bg-neutral-700 rounded-3xl"> |
| 89 | +<h1 class="px-6 py-4 font-semibold text-center md:text-left text-2xl text-neutral-200 bg-neutral-900"> |
| 90 | + <a href="/">OpenAction Marketplace</a> |
| 91 | +</h1> |
| 92 | + |
| 93 | +{#if pluginDetails == 0} |
| 94 | + <div class="m-4 text-center md:text-left text-red-200"> |
| 95 | + <h1 class="mb-1 font-semibold text-2xl">404: Plugin Not Found</h1> |
| 96 | + <h1 class="text-xl">Please check that the plugin ID was entered correctly</h1> |
| 97 | + </div> |
| 98 | +{:else if pluginDetails} |
| 99 | + <div class="m-6 md:m-8"> |
77 | 100 | <div class="flex flex-col md:flex-row items-center md:items-start justify-between"> |
78 | 101 | <div class="flex flex-row items-center md:items-start"> |
79 | 102 | <img |
80 | 103 | src={"https://openactionapi.github.io/plugins/icons/" + $page.params.id + ".png"} |
81 | 104 | alt={pluginDetails.name} |
82 | 105 | class="size-16 md:size-48 rounded-2xl" |
83 | 106 | /> |
84 | | - <div class="ml-8 flex flex-col"> |
| 107 | + <div class="flex flex-col ml-8"> |
85 | 108 | <div class="text-3xl text-neutral-200">{pluginDetails.name}</div> |
86 | | - <div class="mt-2 flex items-center text-lg text-neutral-400"> |
| 109 | + <div class="flex items-center mt-2 text-lg text-neutral-400"> |
87 | 110 | <span class="mr-2">by</span> |
88 | 111 | <img |
89 | | - src={"https://avatars.githubusercontent.com/" + |
90 | | - pluginDetails.repository.split("/")[3]} |
| 112 | + src={"https://avatars.githubusercontent.com/" + pluginDetails.repository.split("/")[3]} |
91 | 113 | alt="Avatar URL" |
92 | | - class="mr-1.5 size-7 rounded-full" |
| 114 | + class="size-7 mr-1.5 rounded-full" |
93 | 115 | /> |
94 | 116 | <a |
95 | 117 | href={"https://github.com/" + pluginDetails.repository.split("/")[3]} |
|
106 | 128 |
|
107 | 129 | <button |
108 | 130 | on:click={() => openDeepLink()} |
109 | | - class="px-8 py-1.5 md:py-3 active:translate-y-0.5 font-semibold text-lg text-neutral-100 bg-indigo-600 rounded-l-lg" |
| 131 | + class="active:translate-y-0.5 px-8 py-1.5 md:py-3 font-semibold text-lg text-neutral-100 bg-indigo-600 rounded-l-lg" |
110 | 132 | > |
111 | 133 | Install |
112 | 134 | </button> |
113 | 135 |
|
114 | 136 | <button |
115 | | - on:click={async () => window.open(getDownloadAction())} |
116 | | - class="ml-1 p-2 md:p-3.5 active:translate-y-0.5 text-lg text-neutral-100 bg-indigo-600 rounded-r-lg" |
| 137 | + on:click={async () => |
| 138 | + window.open( |
| 139 | + (pluginDetails as Plugin).download_url ?? (pluginDetails as Plugin).repository + "/releases/latest", |
| 140 | + )} |
| 141 | + class="active:translate-y-0.5 ml-1 p-2 md:p-3.5 text-lg text-neutral-100 bg-indigo-600 rounded-r-lg" |
117 | 142 | > |
118 | 143 | <ArrowSquareOut size={24} /> |
119 | 144 | </button> |
120 | 145 |
|
121 | | - {#if download_count} |
122 | | - <div class="flex flex-row text-neutral-300 ml-8"> |
123 | | - <span class="mr-1 text-lg"> {download_count} </span> |
| 146 | + {#if downloadCount} |
| 147 | + <div class="flex flex-row ml-8 text-neutral-300"> |
| 148 | + <span class="mr-1 text-lg"> {downloadCount} </span> |
124 | 149 | <DownloadSimple size={28} /> |
125 | 150 | </div> |
126 | 151 | {/if} |
127 | 152 | </div> |
128 | 153 | </div> |
129 | 154 |
|
130 | | - <div class="md:mt-8 p-6 h-full overflow-scroll border-4 border-neutral-600 rounded-xl"> |
| 155 | + <div class="md:mt-8 p-6 border-4 border-neutral-600 rounded-xl"> |
131 | 156 | <p class="readme text-neutral-300"> |
132 | | - {@html marked.parse(readme)} |
| 157 | + {@html readme} |
133 | 158 | </p> |
134 | 159 | </div> |
135 | 160 | </div> |
136 | | -{:else if pluginDetails == -1} |
137 | | - <div class="m-auto p-4 items-center"> |
138 | | - <h1 class="font-bold text-3xl text-neutral-200">404 Plugin not found</h1> |
139 | | - <h1 class="font-semibold text-xl text-neutral-200">Please check that the plugin ID was entered correctly</h1> |
140 | | - </div> |
141 | 161 | {/if} |
0 commit comments