Skip to content

Commit 193b02e

Browse files
committed
Simplify plugin/theme list generation on site
1 parent 9a520d7 commit 193b02e

File tree

2 files changed

+95
-48
lines changed

2 files changed

+95
-48
lines changed

scripts/generate_site_plugins.js

Lines changed: 92 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
11
// @ts-check
2-
const PLUGIN_QUERY = `https://www.npmjs.com/search?q=keywords%3Atypedoc-plugin keywords%3Atypedocplugin`;
3-
const THEME_QUERY = `https://www.npmjs.com/search?q=keywords%3Atypedoc-theme`;
4-
52
import * as cp from "child_process";
63
import { promises as fs, mkdirSync } from "fs";
74
import semver from "semver";
85

96
const CACHE_ROOT = "tmp/site-cache";
107
mkdirSync(CACHE_ROOT, { recursive: true });
118

9+
// cspell: disable
1210
const EXCLUDED_PLUGINS = [
1311
// Fork not intended for public use.
1412
"@zamiell/typedoc-plugin-markdown",
@@ -32,6 +30,7 @@ const EXCLUDED_PLUGIN_USERS = [
3230
"silei",
3331
"tivmof",
3432
];
33+
// cspell: enable
3534

3635
/** @type {(command: string) => Promise<string>} */
3736
function exec(command) {
@@ -54,15 +53,13 @@ async function getSupportedVersions(npmPackage) {
5453
/**
5554
* @typedef {object} NpmPackage
5655
* @prop {string} name
57-
* @prop {{ name: string}} publisher
56+
* @prop {string[]} keywords
57+
* @prop {string} version
5858
* @prop {string} description
59-
* @prop {{ ts: number; rel: string}} date
59+
* @prop {{ username: string}} publisher
60+
* @prop {string} license
61+
* @prop {string} date
6062
* @prop {NpmLinks} links
61-
* @prop {string} version
62-
*/
63-
64-
/**
65-
* @typedef {NpmPackage & { peer: string}} NpmPackageWithPeer
6663
*/
6764

6865
/**
@@ -73,35 +70,22 @@ async function getSupportedVersions(npmPackage) {
7370
*/
7471

7572
/**
76-
* @typedef {object} PackagesResponse
77-
* @prop {number} total
78-
* @prop {{ package: NpmPackage }[]} objects
73+
* @typedef {NpmPackage & { peer: string}} NpmPackageWithPeer
7974
*/
8075

8176
/**
8277
* @param {string} query
8378
* @returns {Promise<NpmPackage[]>}
8479
*/
8580
async function getAllPackages(query) {
86-
let page = 0;
87-
let total = 0;
81+
const FORCE = process.env["CI"] ? " --prefer-online" : "";
82+
8883
/** @type {NpmPackage[]} */
89-
const result = [];
90-
91-
do {
92-
/** @type {PackagesResponse} */
93-
const data = await (
94-
await fetch(`${query}&page=${page++}`, {
95-
headers: {
96-
// Ask for JSON. Hasn't changed since 2018 at least...
97-
"x-spiferack": "1",
98-
},
99-
})
100-
).json();
101-
102-
total = data.total;
103-
result.push(...data.objects.map((x) => x.package));
104-
} while (result.length < total);
84+
const result = JSON.parse(
85+
await exec(
86+
`npm search "${query}" --json --long --searchlimit 1000${FORCE}`,
87+
),
88+
);
10589

10690
return result;
10791
}
@@ -117,7 +101,7 @@ function getSupportingPlugins(typedocVersion, plugins) {
117101

118102
for (const plugin of plugins) {
119103
if (EXCLUDED_PLUGINS.includes(plugin.name)) continue;
120-
if (EXCLUDED_PLUGIN_USERS.includes(plugin.publisher.name)) continue;
104+
if (EXCLUDED_PLUGIN_USERS.includes(plugin.publisher.username)) continue;
121105

122106
let version = plugin.peer.trim();
123107
if (!version) continue;
@@ -173,8 +157,46 @@ function getAllVersions(plugins) {
173157
return Promise.all(plugins.map((p) => getSupportedVersions(p.name)));
174158
}
175159

160+
/** @param {string} date */
161+
function relativeDate(date) {
162+
const nowHours = Date.now() / 1000 / 60 / 60;
163+
const dateHours = Date.parse(date) / 1000 / 60 / 60;
164+
165+
const deltaHours = nowHours - dateHours;
166+
if (deltaHours <= 24) {
167+
return "today";
168+
}
169+
170+
const deltaDays = deltaHours / 24;
171+
if (deltaDays <= 7) {
172+
if (Math.floor(deltaDays) == 1) {
173+
return "1 day ago";
174+
}
175+
return `${Math.floor(deltaDays)} days ago`;
176+
}
177+
178+
const deltaWeeks = Math.floor(deltaDays / 7);
179+
if (deltaWeeks <= 3) {
180+
return `${deltaWeeks} weeks ago`;
181+
}
182+
183+
// Close enough...
184+
const deltaMonths = Math.floor(deltaDays / 30);
185+
if (deltaMonths <= 12) {
186+
if (deltaMonths < 2) {
187+
return "1 month ago";
188+
}
189+
return `${deltaMonths} months ago`;
190+
}
191+
192+
const deltaYears = Math.floor(deltaDays / 365);
193+
if (deltaYears < 2) {
194+
return "1 year ago";
195+
}
196+
return `${deltaYears} years ago`;
197+
}
198+
176199
/**
177-
*
178200
* @param {NpmPackageWithPeer[]} plugins
179201
* @param {string[]} checkVersions
180202
* @param {string} path
@@ -184,19 +206,31 @@ async function createInclude(plugins, checkVersions, path) {
184206
const out = [];
185207

186208
for (const typedocVersion of checkVersions) {
209+
const supportingPlugins = getSupportingPlugins(
210+
typedocVersion,
211+
plugins,
212+
).sort((a, b) => Date.parse(b.date) - Date.parse(a.date));
213+
214+
if (supportingPlugins.length === 0) {
215+
continue;
216+
}
217+
187218
out.push(`## v${typedocVersion.replace(/\.\d+$/, "")}\n`);
188219

189-
for (const plugin of getSupportingPlugins(typedocVersion, plugins).sort(
190-
(a, b) => b.date.ts - a.date.ts,
191-
)) {
220+
for (const plugin of supportingPlugins) {
192221
out.push(`<div class="box">`);
193222
out.push(
194-
` <p class="title"><a href="${plugin.links.npm}" target="_blank">${plugin.name}</a></p>`,
223+
` <p class="box-title"><a href="${plugin.links.npm}" target="_blank">${plugin.name}</a></p>`,
195224
);
196225
out.push(` <p>${miniMarkdown(plugin.description || "")}</p>`);
197-
out.push(` <p>
198-
<a href="https://www.npmjs.com/~${plugin.publisher.name}" target="_blank">${plugin.publisher.name}</a> published ${plugin.version}${plugin.date.rel}
199-
</p>`);
226+
out.push(
227+
` <p>`,
228+
` <a href="https://www.npmjs.com/~${plugin.publisher.username}" target="_blank">${plugin.publisher.username}</a> •`,
229+
` ${plugin.version} •`,
230+
` ${relativeDate(plugin.date)} •`,
231+
` ${plugin.license || "no license"}`,
232+
` </p>`,
233+
);
200234
out.push(`</div>\n`);
201235
}
202236

@@ -239,15 +273,27 @@ function escapeHtml(html) {
239273
async function main() {
240274
console.log("Getting themes...");
241275
const themes = await getLocalCache("themes.json", () =>
242-
getAllPackages(THEME_QUERY),
276+
getAllPackages("keywords:typedoc-theme"),
243277
);
244278

245279
console.log("Getting plugins...");
246-
const plugins = await getLocalCache("plugins.json", async () =>
247-
(await getAllPackages(PLUGIN_QUERY)).filter(
248-
(pack) => !themes.some((t) => t.name === pack.name),
249-
),
250-
);
280+
const plugins = await getLocalCache("plugins.json", async () => {
281+
const plugins = await getAllPackages("keywords:typedoc-plugin");
282+
const plugins2 = await getAllPackages("keywords:typedocplugin");
283+
284+
/** @type {NpmPackage[]} */
285+
const result = [];
286+
for (const pack of [...plugins, ...plugins2]) {
287+
if (
288+
!result.some((p) => p.name === pack.name) &&
289+
!themes.some((p) => p.name === pack.name)
290+
) {
291+
result.push(pack);
292+
}
293+
}
294+
295+
return result;
296+
});
251297

252298
console.log("Getting typedoc versions...");
253299
const versions = await getLocalCache("versions.json", () =>

site/custom.css

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,12 @@
55
margin-bottom: 1em;
66
}
77

8-
.box .title {
8+
.box .box-title {
99
padding-left: 0;
10+
font-weight: bold;
1011
}
1112

1213
.box p {
1314
margin: 0;
14-
padding-left: 1em;
15+
padding-left: 1.5em;
1516
}

0 commit comments

Comments
 (0)