forked from yarnpkg/yarn
/
util.js
112 lines (88 loc) · 2.47 KB
/
util.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
/* @flow */
import type {PersonObject} from '../../types.js';
const path = require('path');
const validateLicense = require('validate-npm-package-license');
const PARENT_PATH = /^\.\.([\\\/]|$)/;
export function isValidLicense(license: string): boolean {
return !!license && validateLicense(license).validForNewPackages;
}
export function isValidBin(bin: string): boolean {
return !path.isAbsolute(bin) && !PARENT_PATH.test(path.normalize(bin));
}
export function stringifyPerson(person: mixed): any {
if (!person || typeof person !== 'object') {
return person;
}
const parts = [];
if (person.name) {
parts.push(person.name);
}
const email = person.email || person.mail;
if (typeof email === 'string') {
parts.push(`<${email}>`);
}
const url = person.url || person.web;
if (typeof url === 'string') {
parts.push(`(${url})`);
}
return parts.join(' ');
}
export function parsePerson(person: mixed): any {
if (typeof person !== 'string') {
return person;
}
// format: name (url) <email>
const obj = {};
let name = person.match(/^([^\(<]+)/);
if (name) {
name = name[0].trim();
if (name) {
obj.name = name;
}
}
const email = person.match(/<([^>]+)>/);
if (email) {
obj.email = email[1];
}
const url = person.match(/\(([^\)]+)\)/);
if (url) {
obj.url = url[1];
}
return obj;
}
export function normalizePerson(person: mixed): mixed | PersonObject {
return parsePerson(stringifyPerson(person));
}
export function extractDescription(readme: mixed): ?string {
if (typeof readme !== 'string' || readme === '') {
return undefined;
}
// split into lines
const lines = readme.trim().split('\n').map((line): string => line.trim());
// find the start of the first paragraph, ignore headings
let start = 0;
for (; start < lines.length; start++) {
const line = lines[start];
if (line && line.match(/^(#|$)/)) {
// line isn't empty and isn't a heading so this is the start of a paragraph
start++;
break;
}
}
// skip newlines from the header to the first line
while (start < lines.length && !lines[start]) {
start++;
}
// continue to the first non empty line
let end = start;
while (end < lines.length && lines[end]) {
end++;
}
return lines.slice(start, end).join(' ');
}
export function extractRepositoryUrl(repository: mixed): any {
if (!repository || typeof repository !== 'object') {
return repository;
}
return repository.url;
}