UNPKG

11.1 kBJavaScriptView Raw
1import { getLink } from './util.js'
2function 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 // build a map
122 const linksMap = {}
123 for (const link of linksArray) {
124 linksMap[link.text.toLowerCase()] = getLink(link)
125 }
126 // do the replacement
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}
135function 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}
170function 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}
187function 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}
208function 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}
229function 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}
249function 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}
269function 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}
290function 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}
301function 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}
311function 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 // handle the editions standard 1.3 and below
322 // can't use substring, as we don't know if we have 1.3 and below or not
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 // Autoloaders
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 // Compile result
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 // Add links
359 return hydrateTextWithLinks(result)
360}
361// Define
362export function getInstallInstructions(data) {
363 const parts = ['<h2>Install</h2>']
364 // DocPad
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 // Node
373 if (data.filenamesForPackageFiles.package) {
374 parts.push(getNpmInstructions(data))
375 // Deno
376 if (data.deno) {
377 parts.push(getDenoInstructions(data))
378 }
379 // Browser
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 // Component
389 if (data.filenamesForPackageFiles.component) {
390 parts.push(getComponentInstructions(data))
391 }
392 // Bower
393 if (data.filenamesForPackageFiles.bower) {
394 parts.push(getBowerInstructions(data))
395 }
396 // Editions
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}