1 | import { getLink } from './util.js'
|
2 | function hydrateTextWithLinks(text) {
|
3 | const linksArray = [
|
4 | {
|
5 | text: 'Deno',
|
6 | url: 'https://deno.land',
|
7 | title:
|
8 | 'Deno is a secure runtime for JavaScript and TypeScript, it is an alternative to Node.js',
|
9 | },
|
10 | {
|
11 | text: 'Editions Autoloader',
|
12 | url: 'https://github.com/bevry/editions',
|
13 | title:
|
14 | 'You can use the Editions Autoloader to autoload the appropriate edition for your consumers environment',
|
15 | },
|
16 | {
|
17 | text: 'Editions',
|
18 | url: 'https://editions.bevry.me',
|
19 | title:
|
20 | 'Editions are the best way to produce and consume packages you care about.',
|
21 | },
|
22 | {
|
23 | text: 'ESNextGuardian',
|
24 | url: 'https://github.com/bevry/esnextguardian',
|
25 | title:
|
26 | "Loads ES6+ files if the user's environment supports it, otherwise gracefully fallback to ES5 files.",
|
27 | },
|
28 | {
|
29 | text: "Babel's Polyfill",
|
30 | url: 'https://babeljs.io/docs/usage/polyfill/',
|
31 | title: 'A polyfill that emulates missing ECMAScript environment features',
|
32 | },
|
33 | {
|
34 | text: 'Babel',
|
35 | url: 'https://babeljs.io',
|
36 | title: 'The compiler for writing next generation JavaScript',
|
37 | },
|
38 | {
|
39 | text: 'CoffeeScript',
|
40 | url: 'https://coffeescript.org',
|
41 | title: 'CoffeeScript is a little language that compiles into JavaScript',
|
42 | },
|
43 | {
|
44 | text: 'Require',
|
45 | url: 'https://nodejs.org/dist/latest-v5.x/docs/api/modules.html',
|
46 | title: 'Node/CJS Modules',
|
47 | },
|
48 | {
|
49 | text: 'Import',
|
50 | url: 'https://babeljs.io/docs/learn-es2015/#modules',
|
51 | title: 'ECMAScript Modules',
|
52 | },
|
53 | {
|
54 | text: 'ESNext',
|
55 | url: 'https://en.wikipedia.org/wiki/ECMAScript#ES.Next',
|
56 | title: 'ECMAScript Next',
|
57 | },
|
58 | {
|
59 | text: 'ES2019',
|
60 | url:
|
61 | 'https://en.wikipedia.org/wiki/ECMAScript#10th_Edition_-_ECMAScript_2019',
|
62 | title: 'ECMAScript ES2019',
|
63 | },
|
64 | {
|
65 | text: 'ES2018',
|
66 | url:
|
67 | 'https://en.wikipedia.org/wiki/ECMAScript#9th_Edition_-_ECMAScript_2018',
|
68 | title: 'ECMAScript ES2018',
|
69 | },
|
70 | {
|
71 | text: 'ES2017',
|
72 | url:
|
73 | 'https://en.wikipedia.org/wiki/ECMAScript#8th_Edition_-_ECMAScript_2017',
|
74 | title: 'ECMAScript ES2017',
|
75 | },
|
76 | {
|
77 | text: 'ES2016',
|
78 | url:
|
79 | 'https://en.wikipedia.org/wiki/ECMAScript#7th_Edition_-_ECMAScript_2016',
|
80 | title: 'ECMAScript 2016',
|
81 | },
|
82 | {
|
83 | text: 'ES2015',
|
84 | url: 'https://babeljs.io/docs/en/learn#ecmascript-2015-features',
|
85 | title: 'ECMAScript 2015',
|
86 | },
|
87 | {
|
88 | text: 'JSDoc Comments',
|
89 | url: 'http://usejsdoc.org',
|
90 | title:
|
91 | 'JSDoc is an API documentation generator for JavaScript, similar to Javadoc or phpDocumentor',
|
92 | },
|
93 | {
|
94 | text: 'Flow Type Comments',
|
95 | url: 'http://flowtype.org/blog/2015/02/20/Flow-Comments.html',
|
96 | title: 'Flow is a static type checker for JavaScript',
|
97 | },
|
98 | {
|
99 | text: 'Flow Type',
|
100 | url: 'http://flowtype.org',
|
101 | title: 'Flow is a static type checker for JavaScript',
|
102 | },
|
103 | {
|
104 | text: 'JSX',
|
105 | url: 'https://facebook.github.io/jsx/',
|
106 | title: 'XML/HTML inside your JavaScript',
|
107 | },
|
108 | {
|
109 | text: 'Node.js',
|
110 | url: 'https://nodejs.org',
|
111 | title:
|
112 | "Node.js is a JavaScript runtime built on Chrome's V8 JavaScript engine",
|
113 | },
|
114 | {
|
115 | text: 'TypeScript',
|
116 | url: 'https://www.typescriptlang.org/',
|
117 | title:
|
118 | 'TypeScript is a typed superset of JavaScript that compiles to plain JavaScript. ',
|
119 | },
|
120 | ]
|
121 |
|
122 | const linksMap = {}
|
123 | for (const link of linksArray) {
|
124 | linksMap[link.text.toLowerCase()] = getLink(link)
|
125 | }
|
126 |
|
127 | const linksMatch = new RegExp(
|
128 | linksArray.map((link) => link.text).join('|'),
|
129 | 'g'
|
130 | )
|
131 | return text.replace(linksMatch, function (match) {
|
132 | return linksMap[match.toLowerCase()]
|
133 | })
|
134 | }
|
135 | function getNpmInstructionList(data, commands, local) {
|
136 | const label = `Executable${commands.length === 1 ? '' : 's'}`
|
137 | let importStatement = ''
|
138 | let requireStatement = ''
|
139 | if (local && data.main) {
|
140 | if (
|
141 | Array.isArray(data.keywords) &&
|
142 | data.keywords.includes('export-default')
|
143 | ) {
|
144 | importStatement = `import pkg from ('${data.name}')`
|
145 | requireStatement = `const pkg = require('${data.name}').default`
|
146 | } else {
|
147 | importStatement = `import * as pkg from ('${data.name}')`
|
148 | requireStatement = `const pkg = require('${data.name}')`
|
149 | }
|
150 | }
|
151 | return [
|
152 | '<ul>',
|
153 | `<li>Install: <code>npm install ${local ? '--save' : '--global'} ${
|
154 | data.name
|
155 | }</code></li>`,
|
156 | commands.length
|
157 | ? `<li>${label}: <code>${commands
|
158 | .map((command) => (local ? `npx ${command}` : command))
|
159 | .join('</code>, <code>')}</code></li>`
|
160 | : '',
|
161 | importStatement ? `<li>Import: <code>${importStatement}</code></li>` : '',
|
162 | requireStatement
|
163 | ? `<li>Require: <code>${requireStatement}</code></li>`
|
164 | : '',
|
165 | '</ul>',
|
166 | ]
|
167 | .filter((i) => i)
|
168 | .join('\n')
|
169 | }
|
170 | function getNpmInstructions(data) {
|
171 | const commands =
|
172 | typeof data.bin === 'string' ? [data.name] : Object.keys(data.bin || {})
|
173 | return [
|
174 | getLink({
|
175 | text: '<h3>npm</h3>',
|
176 | url: 'https://npmjs.com',
|
177 | title: 'npm is a package manager for javascript',
|
178 | }),
|
179 | commands.length && '<h4>Install Globally</h4>',
|
180 | commands.length && getNpmInstructionList(data, commands, false),
|
181 | commands.length && '<h4>Install Locally</h4>',
|
182 | getNpmInstructionList(data, commands, true),
|
183 | ]
|
184 | .filter((i) => i)
|
185 | .join('\n')
|
186 | }
|
187 | function getDenoInstructions(data) {
|
188 | const url =
|
189 | `https://unpkg.com/${data.name}@^${data.version}` +
|
190 | (data.deno ? `/${data.deno}` : '')
|
191 | const importer =
|
192 | Array.isArray(data.keywords) && data.keywords.includes('export-default')
|
193 | ? `pkg`
|
194 | : '* as pkg'
|
195 | return [
|
196 | getLink({
|
197 | text: '<h3>Deno</h3>',
|
198 | url: 'https://deno.land',
|
199 | title:
|
200 | 'Deno is a secure runtime for JavaScript and TypeScript, it is an alternative for Node.js',
|
201 | }),
|
202 | '',
|
203 | '``` typescript',
|
204 | `import ${importer} from '${url}'`,
|
205 | '```',
|
206 | ].join('\n')
|
207 | }
|
208 | function getUnpkgInstructions(data) {
|
209 | const url = `//unpkg.com/${data.name}@^${data.version}`
|
210 | const importer =
|
211 | Array.isArray(data.keywords) && data.keywords.includes('export-default')
|
212 | ? `pkg`
|
213 | : '* as pkg'
|
214 | return [
|
215 | getLink({
|
216 | text: '<h3>unpkg</h3>',
|
217 | url: 'https://unpkg.com',
|
218 | title:
|
219 | 'unpkg is a fast, global content delivery network for everything on npm',
|
220 | }),
|
221 | '',
|
222 | '``` html',
|
223 | '<script type="module">',
|
224 | ` import ${importer} from '${url}'`,
|
225 | `</script>`,
|
226 | '```',
|
227 | ].join('\n')
|
228 | }
|
229 | function getPikaInstructions(data) {
|
230 | const url = `//cdn.pika.dev/${data.name}/^${data.version}`
|
231 | const importer =
|
232 | Array.isArray(data.keywords) && data.keywords.includes('export-default')
|
233 | ? `pkg`
|
234 | : '* as pkg'
|
235 | return [
|
236 | getLink({
|
237 | text: '<h3>pika</h3>',
|
238 | url: 'https://www.pika.dev/cdn',
|
239 | title: '100% Native ES Modules CDN',
|
240 | }),
|
241 | '',
|
242 | '``` html',
|
243 | '<script type="module">',
|
244 | ` import ${importer} from '${url}'`,
|
245 | `</script>`,
|
246 | '```',
|
247 | ].join('\n')
|
248 | }
|
249 | function getJspmInstructions(data) {
|
250 | const url = `//dev.jspm.io/${data.name}@${data.version}`
|
251 | const importer =
|
252 | Array.isArray(data.keywords) && data.keywords.includes('export-default')
|
253 | ? `pkg`
|
254 | : '* as pkg'
|
255 | return [
|
256 | getLink({
|
257 | text: '<h3>jspm</h3>',
|
258 | url: 'https://jspm.io',
|
259 | title: 'Native ES Modules CDN',
|
260 | }),
|
261 | '',
|
262 | '``` html',
|
263 | '<script type="module">',
|
264 | ` import ${importer} from '${url}'`,
|
265 | `</script>`,
|
266 | '```',
|
267 | ].join('\n')
|
268 | }
|
269 | function getTypeScriptInstructions() {
|
270 | return [
|
271 | hydrateTextWithLinks('<h3>TypeScript</h3>'),
|
272 | '',
|
273 | hydrateTextWithLinks(
|
274 | 'This project provides its type information via inline JSDoc Comments. To make use of this in TypeScript, set your <code>maxNodeModuleJsDepth</code> compiler option to `5` or thereabouts. You can accomlish this via your `tsconfig.json` file like so:'
|
275 | ),
|
276 | '',
|
277 | '``` json',
|
278 | JSON.stringify(
|
279 | {
|
280 | compilerOptions: {
|
281 | maxNodeModuleJsDepth: 5,
|
282 | },
|
283 | },
|
284 | null,
|
285 | ' '
|
286 | ),
|
287 | '```',
|
288 | ].join('\n')
|
289 | }
|
290 | function getComponentInstructions(data) {
|
291 | return [
|
292 | getLink({
|
293 | text: '<h3>Component</h3>',
|
294 | url: 'https://github.com/componentjs/component',
|
295 | title:
|
296 | 'Frontend package manager and build tool for modular web applications',
|
297 | }),
|
298 | `<ul><li>Install: <code>component install ${data.name}</code></li></ul>`,
|
299 | ].join('\n')
|
300 | }
|
301 | function getBowerInstructions(data) {
|
302 | return [
|
303 | getLink({
|
304 | text: '<h3>Bower</h3>',
|
305 | url: 'https://bower.io',
|
306 | title: 'A package manager for the web',
|
307 | }),
|
308 | `<ul><li>Install: <code>bower install ${data.name}</code></li></ul>`,
|
309 | ].join('\n')
|
310 | }
|
311 | function getEditionsInstructions(data) {
|
312 | if (!data.editions.length) return ''
|
313 | let hasDefaultEdition = false
|
314 | const editions = []
|
315 | for (const edition of data.editions) {
|
316 | const entryParts = []
|
317 | if (edition.directory) {
|
318 | entryParts.push(edition.directory)
|
319 | }
|
320 | if (edition.entry) {
|
321 |
|
322 |
|
323 | if (edition.directory) {
|
324 | entryParts.push(
|
325 | edition.entry.replace(edition.directory.length + '/', '')
|
326 | )
|
327 | } else {
|
328 | entryParts.push(edition.entry)
|
329 | }
|
330 | }
|
331 | const entry = entryParts.join('/')
|
332 | if (entry === data.main) {
|
333 | hasDefaultEdition = true
|
334 | editions.push(
|
335 | `<code>${data.name}</code> aliases <code>${data.name}/${data.main}</code>`
|
336 | )
|
337 | }
|
338 | editions.push(
|
339 | `<code>${data.name}/${entry}</code> is ${edition.description}`
|
340 | )
|
341 | }
|
342 |
|
343 | if (!hasDefaultEdition) {
|
344 | if ('editions' in data.dependencies) {
|
345 | editions.unshift(
|
346 | `<code>${data.name}</code> aliases <code>${data.name}/${data.main}</code> which uses the Editions Autoloader to automatically select the correct edition for the consumer's environment`
|
347 | )
|
348 | } else if ('esnextguardian' in data.dependencies) {
|
349 | editions.unshift(
|
350 | `<code>${data.name}</code> aliases <code>${data.name}/${data.main}</code> which uses ESNextGuardian to automatically select the correct edition for the consumers environment`
|
351 | )
|
352 | }
|
353 | }
|
354 |
|
355 | const result = `<h3>Editions</h3>\n\n<p>This package is published with the following editions:</p>\n\n<ul><li>${editions.join(
|
356 | '</li>\n<li>'
|
357 | )}</li></ul>`
|
358 |
|
359 | return hydrateTextWithLinks(result)
|
360 | }
|
361 |
|
362 | export function getInstallInstructions(data) {
|
363 | const parts = ['<h2>Install</h2>']
|
364 |
|
365 | const prefix = 'docpad-plugin-'
|
366 | if (data.name.startsWith(prefix)) {
|
367 | const pluginName = data.name.substring(prefix.length)
|
368 | parts.push(
|
369 | `Install this DocPad plugin by entering <code>docpad install ${pluginName}</code> into your terminal.`
|
370 | )
|
371 | } else {
|
372 |
|
373 | if (data.filenamesForPackageFiles.package) {
|
374 | parts.push(getNpmInstructions(data))
|
375 |
|
376 | if (data.deno) {
|
377 | parts.push(getDenoInstructions(data))
|
378 | }
|
379 |
|
380 | if (data.browsers) {
|
381 | if (data.module) {
|
382 | parts.push(getPikaInstructions(data))
|
383 | parts.push(getUnpkgInstructions(data))
|
384 | }
|
385 | parts.push(getJspmInstructions(data))
|
386 | }
|
387 | }
|
388 |
|
389 | if (data.filenamesForPackageFiles.component) {
|
390 | parts.push(getComponentInstructions(data))
|
391 | }
|
392 |
|
393 | if (data.filenamesForPackageFiles.bower) {
|
394 | parts.push(getBowerInstructions(data))
|
395 | }
|
396 |
|
397 | if (data.editions) {
|
398 | parts.push(getEditionsInstructions(data))
|
399 | }
|
400 | }
|
401 | if (data.main && data.devDependencies && data.devDependencies.jsdoc) {
|
402 | parts.push(getTypeScriptInstructions())
|
403 | }
|
404 | return parts.filter((i) => i).join('\n\n')
|
405 | }
|