1
1
// @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
-
5
2
import * as cp from "child_process" ;
6
3
import { promises as fs , mkdirSync } from "fs" ;
7
4
import semver from "semver" ;
8
5
9
6
const CACHE_ROOT = "tmp/site-cache" ;
10
7
mkdirSync ( CACHE_ROOT , { recursive : true } ) ;
11
8
9
+ // cspell: disable
12
10
const EXCLUDED_PLUGINS = [
13
11
// Fork not intended for public use.
14
12
"@zamiell/typedoc-plugin-markdown" ,
@@ -32,6 +30,7 @@ const EXCLUDED_PLUGIN_USERS = [
32
30
"silei" ,
33
31
"tivmof" ,
34
32
] ;
33
+ // cspell: enable
35
34
36
35
/** @type {(command: string) => Promise<string> } */
37
36
function exec ( command ) {
@@ -54,15 +53,13 @@ async function getSupportedVersions(npmPackage) {
54
53
/**
55
54
* @typedef {object } NpmPackage
56
55
* @prop {string } name
57
- * @prop {{ name: string} } publisher
56
+ * @prop {string[] } keywords
57
+ * @prop {string } version
58
58
* @prop {string } description
59
- * @prop {{ ts: number; rel: string} } date
59
+ * @prop {{ username: string} } publisher
60
+ * @prop {string } license
61
+ * @prop {string } date
60
62
* @prop {NpmLinks } links
61
- * @prop {string } version
62
- */
63
-
64
- /**
65
- * @typedef {NpmPackage & { peer: string} } NpmPackageWithPeer
66
63
*/
67
64
68
65
/**
@@ -73,35 +70,22 @@ async function getSupportedVersions(npmPackage) {
73
70
*/
74
71
75
72
/**
76
- * @typedef {object } PackagesResponse
77
- * @prop {number } total
78
- * @prop {{ package: NpmPackage }[] } objects
73
+ * @typedef {NpmPackage & { peer: string} } NpmPackageWithPeer
79
74
*/
80
75
81
76
/**
82
77
* @param {string } query
83
78
* @returns {Promise<NpmPackage[]> }
84
79
*/
85
80
async function getAllPackages ( query ) {
86
- let page = 0 ;
87
- let total = 0 ;
81
+ const FORCE = process . env [ "CI" ] ? " --prefer-online" : "" ;
82
+
88
83
/** @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
+ ) ;
105
89
106
90
return result ;
107
91
}
@@ -117,7 +101,7 @@ function getSupportingPlugins(typedocVersion, plugins) {
117
101
118
102
for ( const plugin of plugins ) {
119
103
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 ;
121
105
122
106
let version = plugin . peer . trim ( ) ;
123
107
if ( ! version ) continue ;
@@ -173,8 +157,46 @@ function getAllVersions(plugins) {
173
157
return Promise . all ( plugins . map ( ( p ) => getSupportedVersions ( p . name ) ) ) ;
174
158
}
175
159
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
+
176
199
/**
177
- *
178
200
* @param {NpmPackageWithPeer[] } plugins
179
201
* @param {string[] } checkVersions
180
202
* @param {string } path
@@ -184,19 +206,31 @@ async function createInclude(plugins, checkVersions, path) {
184
206
const out = [ ] ;
185
207
186
208
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
+
187
218
out . push ( `## v${ typedocVersion . replace ( / \. \d + $ / , "" ) } \n` ) ;
188
219
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 ) {
192
221
out . push ( `<div class="box">` ) ;
193
222
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>` ,
195
224
) ;
196
225
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
+ ) ;
200
234
out . push ( `</div>\n` ) ;
201
235
}
202
236
@@ -239,15 +273,27 @@ function escapeHtml(html) {
239
273
async function main ( ) {
240
274
console . log ( "Getting themes..." ) ;
241
275
const themes = await getLocalCache ( "themes.json" , ( ) =>
242
- getAllPackages ( THEME_QUERY ) ,
276
+ getAllPackages ( "keywords:typedoc-theme" ) ,
243
277
) ;
244
278
245
279
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
+ } ) ;
251
297
252
298
console . log ( "Getting typedoc versions..." ) ;
253
299
const versions = await getLocalCache ( "versions.json" , ( ) =>
0 commit comments