Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

fellow

Package Overview
Dependencies
Maintainers
1
Versions
118
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

fellow - npm Package Compare versions

Comparing version 7.0.2 to 7.0.3-next.1703635100.eb05eaabeb2a1367e665495a73d70661c8953365

200

edition-browsers/index.js

@@ -0,1 +1,31 @@

// external
import { a, ma } from '@bevry/render';
/** Verify an email */
function verifyEmail(email) {
if (!email)
return false;
return /.+?@.+/.test(email);
}
/** Verify a URL */
async function fetchOk(url) {
const resp = await fetch(url, { method: 'HEAD' });
return resp.ok;
}
/** Verify the failure of a URL */
async function fetchNotOk(url) {
const ok = await fetchOk(url);
return !ok;
}
/** A rendering style for {@link Fellow} */
export var Format;
(function (Format) {
/** Use {@link Fellow.toString} */
Format["string"] = "string";
/** Use {@link Fellow.toText} */
Format["text"] = "text";
/** Use {@link Fellow.toMarkdown} */
Format["markdown"] = "markdown";
/** Use {@link Fellow.toHtml} */
Format["html"] = "html";
})(Format || (Format = {}));
/** Prevent GitHub username matches for the following. Generated by experience and with GitHub Copilot. */

@@ -189,3 +219,3 @@ const githubInvalidUsernames = [

}
/** Get {@link Follow.nomen} if resolved, otherwise {@link Fellow.username} */
/** Get {@link Fellow.nomen} if resolved, otherwise {@link Fellow.username} */
get name() {

@@ -385,2 +415,43 @@ return this.nomen || this.username || '';

];
/** Remove invalid username urls */
async verifyUrls() {
for (const field of this.urlFields) {
const url = this[field];
if (!url)
continue;
switch (field) {
case 'githubUrl':
if (await fetchNotOk(url))
this.githubUsername = '';
break;
case 'gitlabUrl':
if (await fetchNotOk(url))
this.gitlabUsername = '';
break;
case 'thanksdevUrl':
if (await fetchNotOk(url))
this._thanksdevUrlEnabled = false;
break;
case 'opencollectiveUrl':
if (await fetchNotOk(url))
this.opencollectiveUsername = '';
break;
case 'patreonUrl':
if (await fetchNotOk(url))
this.patreonUsername = '';
break;
case 'twitterUrl':
if (await fetchNotOk(url))
this.twitterUsername = '';
break;
case 'facebookUrl':
if (await fetchNotOk(url))
this.facebookUsername = '';
break;
default:
// unknown, ignore
continue;
}
}
}
/** Get all unique resolved URLs */

@@ -398,4 +469,6 @@ get urls() {

if (input) {
// convert to https
input = input.replace(/^http:\/\//, 'https://');
// convert to https and trim www. as it is 2023
input = input.replace(/^http:\/\//, 'https://').replace(/^www\./, '');
if (input.startsWith('https://') === false)
input = `https://${input}`;
// slice 1 to skip websiteUrl

@@ -435,3 +508,3 @@ for (const field of this.urlFields) {

input = trim(input);
if (!input)
if (!verifyEmail(input))
return;

@@ -738,10 +811,10 @@ this.emails.add(input);

*/
toString(format = {}) {
const parts = [];
toString(opts = {}) {
if (!this.name)
return '';
const parts = [];
// copyright
if (format.displayCopyright)
if (opts.displayCopyright)
parts.push('Copyright ©');
if (format.displayYears && this.years)
if (opts.displayYears && this.years)
parts.push(this.years);

@@ -751,8 +824,8 @@ // name

// email
if (format.displayEmail !== false && this.email) {
if (opts.displayEmail !== false && this.email) {
parts.push(`<${this.email}>`);
}
// urls
const urls = format.urlFields?.length
? this.getFields(format.urlFields)
const urls = opts.urlFields?.length
? this.getFields(opts.urlFields)
: this.urls;

@@ -762,8 +835,8 @@ for (const url of urls) {

}
// description
if (format.displayDescription && this.description) {
parts.push(`: ${this.description}`);
// add description without space before :, and return
let result = parts.join(' ');
if (opts.displayDescription && this.description) {
result += `: ${this.description}`;
}
// return
return parts.join(' ');
return result;
}

@@ -774,3 +847,3 @@ /**

*/
toText(format = {}) {
toText(opts = {}) {
if (!this.name)

@@ -782,14 +855,14 @@ return '';

// email
if (format.displayEmail && this.email) {
if (opts.displayEmail && this.email) {
parts.push(`✉️ ${this.email}`);
}
// description
if (format.displayDescription !== false && this.description) {
if (opts.displayDescription !== false && this.description) {
parts.push(`📝 ${this.description}`);
}
// url
const url = format.displayUrl === false
const url = opts.displayUrl === false
? ''
: format.urlFields?.length
? this.getFirstField(format.urlFields)
: opts.urlFields?.length
? this.getFirstField(opts.urlFields)
: this.url;

@@ -805,3 +878,3 @@ if (url)

*/
toMarkdown(format = {}) {
toMarkdown(opts = {}) {
if (!this.name)

@@ -811,29 +884,32 @@ return '';

// copyright
if (format.displayCopyright)
if (opts.displayCopyright)
parts.push('Copyright &copy;');
if (format.displayYears && this.years)
if (opts.displayYears && this.years)
parts.push(this.years);
// name + url
const url = format.displayUrl === false
const url = opts.displayUrl === false
? ''
: format.urlFields?.length
? this.getFirstField(format.urlFields)
: opts.urlFields?.length
? this.getFirstField(opts.urlFields)
: this.url;
if (url)
parts.push(`[${this.name}](${url})`);
parts.push(ma({ url, inner: this.name }));
else
parts.push(this.name);
// email
if (format.displayEmail && this.email) {
if (opts.displayEmail && this.email) {
parts.push(`<${this.email}>`);
}
// contributions
if (format.displayContributions &&
format.githubRepoSlug &&
this.githubUsername) {
const contributionsUrl = `https://github.com/${format.githubRepoSlug}/commits?author=${this.githubUsername}`;
parts.push(`— [view contributions](${contributionsUrl} "View the GitHub contributions of ${this.name} on repository ${format.githubRepoSlug}")`);
if (opts.displayContributions && opts.githubSlug && this.githubUsername) {
const contributionsUrl = `https://github.com/${opts.githubSlug}/commits?author=${this.githubUsername}`;
parts.push('— ' +
ma({
url: contributionsUrl,
inner: 'view contributions',
title: `View the GitHub contributions of ${this.name} on repository ${opts.githubSlug}`,
}));
}
// description
if (format.displayDescription && this.description) {
if (opts.displayDescription && this.description) {
parts.push(`— ${this.description}`);

@@ -845,3 +921,3 @@ }

/** Convert the fellow into the usual HTML format */
toHtml(format = {}) {
toHtml(opts = {}) {
if (!this.name)

@@ -851,29 +927,36 @@ return '';

// copyright
if (format.displayCopyright)
if (opts.displayCopyright)
parts.push('Copyright &copy;');
if (format.displayYears && this.years)
if (opts.displayYears && this.years)
parts.push(this.years);
// name + url
const url = format.displayUrl === false
const url = opts.displayUrl === false
? ''
: format.urlFields?.length
? this.getFirstField(format.urlFields)
: opts.urlFields?.length
? this.getFirstField(opts.urlFields)
: this.url;
if (url)
parts.push(`<a href="${url}">${this.name}</a>`);
parts.push(a({ url, inner: this.name }));
else
parts.push(this.name);
// email
if (format.displayEmail && this.email) {
parts.push(`<a href="mailto:${this.email}" title="Email ${this.name}">&lt;${this.email}&gt;</a>`);
if (opts.displayEmail && this.email) {
parts.push(a({
url: `mailto:${this.email}`,
inner: `&lt;${this.email}&gt;`,
title: `Email ${this.name}`,
}));
}
// contributions
if (format.displayContributions &&
format.githubRepoSlug &&
this.githubUsername) {
const contributionsUrl = `https://github.com/${format.githubRepoSlug}/commits?author=${this.githubUsername}`;
parts.push(`— <a href="${contributionsUrl}" title="View the GitHub contributions of ${this.name} on repository ${format.githubRepoSlug}">view contributions</a>`);
if (opts.displayContributions && opts.githubSlug && this.githubUsername) {
const contributionsUrl = `https://github.com/${opts.githubSlug}/commits?author=${this.githubUsername}`;
parts.push('— ' +
a({
url: contributionsUrl,
inner: 'view contributions',
title: `View the GitHub contributions of ${this.name} on repository ${opts.githubSlug}`,
}));
}
// description
if (format.displayDescription && this.description) {
if (opts.displayDescription && this.description) {
parts.push(`— ${this.description}`);

@@ -884,2 +967,17 @@ }

}
/** Convert the fellow into the specified format */
toFormat(opts) {
switch (opts.format) {
case Format.string:
return this.toString(opts);
case Format.text:
return this.toText(opts);
case Format.markdown:
return this.toMarkdown(opts);
case Format.html:
return this.toHtml(opts);
default:
throw new Error(`Invalid format: ${opts.format}`);
}
}
}

@@ -0,1 +1,34 @@

// external
import { a, ma } from 'https://esm.sh/@bevry/render@^1.0.0'
/** Verify an email */
function verifyEmail(email: string): boolean {
if (!email) return false
return /.+?@.+/.test(email)
}
/** Verify a URL */
async function fetchOk(url: string): Promise<boolean> {
const resp = await fetch(url, { method: 'HEAD' })
return resp.ok
}
/** Verify the failure of a URL */
async function fetchNotOk(url: string): Promise<boolean> {
const ok = await fetchOk(url)
return !ok
}
/** A rendering style for {@link Fellow} */
export enum Format {
/** Use {@link Fellow.toString} */
string = 'string',
/** Use {@link Fellow.toText} */
text = 'text',
/** Use {@link Fellow.toMarkdown} */
markdown = 'markdown',
/** Use {@link Fellow.toHtml} */
html = 'html',
}
/**

@@ -7,2 +40,5 @@ * Options for formatting the rendered outputs.

export interface FormatOptions {
/** When used with {@link Fellow.toFormat} this determines the format that is used. */
format?: Format | null
/** Whether or not to display {@link Fellow.url} */

@@ -23,7 +59,7 @@ displayUrl?: boolean

/** Whether or not to display a link to the user's contributions. Requires {@link FormatOptions.githubRepoSlug} */
/** Whether or not to display a link to the user's contributions. Requires {@link FormatOptions.githubSlug} */
displayContributions?: boolean
/** The repository for when using with {@link FormatOptions.displayContributions} */
githubRepoSlug?: string
/** The repository for using with {@link FormatOptions.displayContributions} */
githubSlug?: string

@@ -250,3 +286,3 @@ /** An array of fields to prefer for the URL. {@link Fellow.toString} will output each one. */

/** Get {@link Follow.nomen} if resolved, otherwise {@link Fellow.username} */
/** Get {@link Fellow.nomen} if resolved, otherwise {@link Fellow.username} */
get name(): string {

@@ -450,2 +486,36 @@ return this.nomen || this.username || ''

/** Remove invalid username urls */
async verifyUrls(): Promise<void> {
for (const field of this.urlFields) {
const url = this[field]
if (!url) continue
switch (field) {
case 'githubUrl':
if (await fetchNotOk(url)) this.githubUsername = ''
break
case 'gitlabUrl':
if (await fetchNotOk(url)) this.gitlabUsername = ''
break
case 'thanksdevUrl':
if (await fetchNotOk(url)) this._thanksdevUrlEnabled = false
break
case 'opencollectiveUrl':
if (await fetchNotOk(url)) this.opencollectiveUsername = ''
break
case 'patreonUrl':
if (await fetchNotOk(url)) this.patreonUsername = ''
break
case 'twitterUrl':
if (await fetchNotOk(url)) this.twitterUsername = ''
break
case 'facebookUrl':
if (await fetchNotOk(url)) this.facebookUsername = ''
break
default:
// unknown, ignore
continue
}
}
}
/** Get all unique resolved URLs */

@@ -464,4 +534,5 @@ get urls() {

if (input) {
// convert to https
input = input.replace(/^http:\/\//, 'https://')
// convert to https and trim www. as it is 2023
input = input.replace(/^http:\/\//, 'https://').replace(/^www\./, '')
if (input.startsWith('https://') === false) input = `https://${input}`
// slice 1 to skip websiteUrl

@@ -503,3 +574,3 @@ for (const field of this.urlFields) {

input = trim(input)
if (!input) return
if (!verifyEmail(input)) return
this.emails.add(input)

@@ -845,9 +916,9 @@ }

*/
toString(format: FormatOptions = {}): string {
toString(opts: FormatOptions = {}): string {
if (!this.name) return ''
const parts = []
if (!this.name) return ''
// copyright
if (format.displayCopyright) parts.push('Copyright &copy;')
if (format.displayYears && this.years) parts.push(this.years)
if (opts.displayCopyright) parts.push('Copyright &copy;')
if (opts.displayYears && this.years) parts.push(this.years)

@@ -858,3 +929,3 @@ // name

// email
if (format.displayEmail !== false && this.email) {
if (opts.displayEmail !== false && this.email) {
parts.push(`<${this.email}>`)

@@ -864,4 +935,4 @@ }

// urls
const urls = format.urlFields?.length
? this.getFields(format.urlFields)
const urls = opts.urlFields?.length
? this.getFields(opts.urlFields)
: this.urls

@@ -872,9 +943,8 @@ for (const url of urls) {

// description
if (format.displayDescription && this.description) {
parts.push(`: ${this.description}`)
// add description without space before :, and return
let result = parts.join(' ')
if (opts.displayDescription && this.description) {
result += `: ${this.description}`
}
// return
return parts.join(' ')
return result
}

@@ -886,3 +956,3 @@

*/
toText(format: FormatOptions = {}): string {
toText(opts: FormatOptions = {}): string {
if (!this.name) return ''

@@ -895,3 +965,3 @@ const parts = []

// email
if (format.displayEmail && this.email) {
if (opts.displayEmail && this.email) {
parts.push(`✉️ ${this.email}`)

@@ -901,3 +971,3 @@ }

// description
if (format.displayDescription !== false && this.description) {
if (opts.displayDescription !== false && this.description) {
parts.push(`📝 ${this.description}`)

@@ -908,6 +978,6 @@ }

const url =
format.displayUrl === false
opts.displayUrl === false
? ''
: format.urlFields?.length
? this.getFirstField(format.urlFields)
: opts.urlFields?.length
? this.getFirstField(opts.urlFields)
: this.url

@@ -924,3 +994,3 @@ if (url) parts.push(`🔗 ${this.url}`)

*/
toMarkdown(format: FormatOptions = {}): string {
toMarkdown(opts: FormatOptions = {}): string {
if (!this.name) return ''

@@ -930,17 +1000,17 @@ const parts = []

// copyright
if (format.displayCopyright) parts.push('Copyright &copy;')
if (format.displayYears && this.years) parts.push(this.years)
if (opts.displayCopyright) parts.push('Copyright &copy;')
if (opts.displayYears && this.years) parts.push(this.years)
// name + url
const url =
format.displayUrl === false
opts.displayUrl === false
? ''
: format.urlFields?.length
? this.getFirstField(format.urlFields)
: opts.urlFields?.length
? this.getFirstField(opts.urlFields)
: this.url
if (url) parts.push(`[${this.name}](${url})`)
if (url) parts.push(ma({ url, inner: this.name }))
else parts.push(this.name)
// email
if (format.displayEmail && this.email) {
if (opts.displayEmail && this.email) {
parts.push(`<${this.email}>`)

@@ -950,10 +1020,11 @@ }

// contributions
if (
format.displayContributions &&
format.githubRepoSlug &&
this.githubUsername
) {
const contributionsUrl = `https://github.com/${format.githubRepoSlug}/commits?author=${this.githubUsername}`
if (opts.displayContributions && opts.githubSlug && this.githubUsername) {
const contributionsUrl = `https://github.com/${opts.githubSlug}/commits?author=${this.githubUsername}`
parts.push(
`— [view contributions](${contributionsUrl} "View the GitHub contributions of ${this.name} on repository ${format.githubRepoSlug}")`,
'— ' +
ma({
url: contributionsUrl,
inner: 'view contributions',
title: `View the GitHub contributions of ${this.name} on repository ${opts.githubSlug}`,
}),
)

@@ -963,3 +1034,3 @@ }

// description
if (format.displayDescription && this.description) {
if (opts.displayDescription && this.description) {
parts.push(`— ${this.description}`)

@@ -973,3 +1044,3 @@ }

/** Convert the fellow into the usual HTML format */
toHtml(format: FormatOptions = {}): string {
toHtml(opts: FormatOptions = {}): string {
if (!this.name) return ''

@@ -979,19 +1050,23 @@ const parts = []

// copyright
if (format.displayCopyright) parts.push('Copyright &copy;')
if (format.displayYears && this.years) parts.push(this.years)
if (opts.displayCopyright) parts.push('Copyright &copy;')
if (opts.displayYears && this.years) parts.push(this.years)
// name + url
const url =
format.displayUrl === false
opts.displayUrl === false
? ''
: format.urlFields?.length
? this.getFirstField(format.urlFields)
: opts.urlFields?.length
? this.getFirstField(opts.urlFields)
: this.url
if (url) parts.push(`<a href="${url}">${this.name}</a>`)
if (url) parts.push(a({ url, inner: this.name }))
else parts.push(this.name)
// email
if (format.displayEmail && this.email) {
if (opts.displayEmail && this.email) {
parts.push(
`<a href="mailto:${this.email}" title="Email ${this.name}">&lt;${this.email}&gt;</a>`,
a({
url: `mailto:${this.email}`,
inner: `&lt;${this.email}&gt;`,
title: `Email ${this.name}`,
}),
)

@@ -1001,10 +1076,11 @@ }

// contributions
if (
format.displayContributions &&
format.githubRepoSlug &&
this.githubUsername
) {
const contributionsUrl = `https://github.com/${format.githubRepoSlug}/commits?author=${this.githubUsername}`
if (opts.displayContributions && opts.githubSlug && this.githubUsername) {
const contributionsUrl = `https://github.com/${opts.githubSlug}/commits?author=${this.githubUsername}`
parts.push(
`— <a href="${contributionsUrl}" title="View the GitHub contributions of ${this.name} on repository ${format.githubRepoSlug}">view contributions</a>`,
'— ' +
a({
url: contributionsUrl,
inner: 'view contributions',
title: `View the GitHub contributions of ${this.name} on repository ${opts.githubSlug}`,
}),
)

@@ -1014,3 +1090,3 @@ }

// description
if (format.displayDescription && this.description) {
if (opts.displayDescription && this.description) {
parts.push(`— ${this.description}`)

@@ -1022,2 +1098,18 @@ }

}
/** Convert the fellow into the specified format */
toFormat(opts: FormatOptions & { format: Format }): string {
switch (opts.format) {
case Format.string:
return this.toString(opts)
case Format.text:
return this.toText(opts)
case Format.markdown:
return this.toMarkdown(opts)
case Format.html:
return this.toHtml(opts)
default:
throw new Error(`Invalid format: ${opts.format}`)
}
}
}

@@ -0,1 +1,31 @@

// external
import { a, ma } from '@bevry/render';
/** Verify an email */
function verifyEmail(email) {
if (!email)
return false;
return /.+?@.+/.test(email);
}
/** Verify a URL */
async function fetchOk(url) {
const resp = await fetch(url, { method: 'HEAD' });
return resp.ok;
}
/** Verify the failure of a URL */
async function fetchNotOk(url) {
const ok = await fetchOk(url);
return !ok;
}
/** A rendering style for {@link Fellow} */
export var Format;
(function (Format) {
/** Use {@link Fellow.toString} */
Format["string"] = "string";
/** Use {@link Fellow.toText} */
Format["text"] = "text";
/** Use {@link Fellow.toMarkdown} */
Format["markdown"] = "markdown";
/** Use {@link Fellow.toHtml} */
Format["html"] = "html";
})(Format || (Format = {}));
/** Prevent GitHub username matches for the following. Generated by experience and with GitHub Copilot. */

@@ -160,3 +190,3 @@ const githubInvalidUsernames = [

}
/** Get {@link Follow.nomen} if resolved, otherwise {@link Fellow.username} */
/** Get {@link Fellow.nomen} if resolved, otherwise {@link Fellow.username} */
get name() {

@@ -339,2 +369,43 @@ return this.nomen || this.username || '';

}
/** Remove invalid username urls */
async verifyUrls() {
for (const field of this.urlFields) {
const url = this[field];
if (!url)
continue;
switch (field) {
case 'githubUrl':
if (await fetchNotOk(url))
this.githubUsername = '';
break;
case 'gitlabUrl':
if (await fetchNotOk(url))
this.gitlabUsername = '';
break;
case 'thanksdevUrl':
if (await fetchNotOk(url))
this._thanksdevUrlEnabled = false;
break;
case 'opencollectiveUrl':
if (await fetchNotOk(url))
this.opencollectiveUsername = '';
break;
case 'patreonUrl':
if (await fetchNotOk(url))
this.patreonUsername = '';
break;
case 'twitterUrl':
if (await fetchNotOk(url))
this.twitterUsername = '';
break;
case 'facebookUrl':
if (await fetchNotOk(url))
this.facebookUsername = '';
break;
default:
// unknown, ignore
continue;
}
}
}
/** Get all unique resolved URLs */

@@ -352,4 +423,6 @@ get urls() {

if (input) {
// convert to https
input = input.replace(/^http:\/\//, 'https://');
// convert to https and trim www. as it is 2023
input = input.replace(/^http:\/\//, 'https://').replace(/^www\./, '');
if (input.startsWith('https://') === false)
input = `https://${input}`;
// slice 1 to skip websiteUrl

@@ -385,3 +458,3 @@ for (const field of this.urlFields) {

input = trim(input);
if (!input)
if (!verifyEmail(input))
return;

@@ -737,11 +810,11 @@ this.emails.add(input);

*/
toString(format = {}) {
toString(opts = {}) {
var _a;
const parts = [];
if (!this.name)
return '';
const parts = [];
// copyright
if (format.displayCopyright)
if (opts.displayCopyright)
parts.push('Copyright &copy;');
if (format.displayYears && this.years)
if (opts.displayYears && this.years)
parts.push(this.years);

@@ -751,8 +824,8 @@ // name

// email
if (format.displayEmail !== false && this.email) {
if (opts.displayEmail !== false && this.email) {
parts.push(`<${this.email}>`);
}
// urls
const urls = ((_a = format.urlFields) === null || _a === void 0 ? void 0 : _a.length)
? this.getFields(format.urlFields)
const urls = ((_a = opts.urlFields) === null || _a === void 0 ? void 0 : _a.length)
? this.getFields(opts.urlFields)
: this.urls;

@@ -762,8 +835,8 @@ for (const url of urls) {

}
// description
if (format.displayDescription && this.description) {
parts.push(`: ${this.description}`);
// add description without space before :, and return
let result = parts.join(' ');
if (opts.displayDescription && this.description) {
result += `: ${this.description}`;
}
// return
return parts.join(' ');
return result;
}

@@ -774,3 +847,3 @@ /**

*/
toText(format = {}) {
toText(opts = {}) {
var _a;

@@ -783,14 +856,14 @@ if (!this.name)

// email
if (format.displayEmail && this.email) {
if (opts.displayEmail && this.email) {
parts.push(`✉️ ${this.email}`);
}
// description
if (format.displayDescription !== false && this.description) {
if (opts.displayDescription !== false && this.description) {
parts.push(`📝 ${this.description}`);
}
// url
const url = format.displayUrl === false
const url = opts.displayUrl === false
? ''
: ((_a = format.urlFields) === null || _a === void 0 ? void 0 : _a.length)
? this.getFirstField(format.urlFields)
: ((_a = opts.urlFields) === null || _a === void 0 ? void 0 : _a.length)
? this.getFirstField(opts.urlFields)
: this.url;

@@ -806,3 +879,3 @@ if (url)

*/
toMarkdown(format = {}) {
toMarkdown(opts = {}) {
var _a;

@@ -813,29 +886,32 @@ if (!this.name)

// copyright
if (format.displayCopyright)
if (opts.displayCopyright)
parts.push('Copyright &copy;');
if (format.displayYears && this.years)
if (opts.displayYears && this.years)
parts.push(this.years);
// name + url
const url = format.displayUrl === false
const url = opts.displayUrl === false
? ''
: ((_a = format.urlFields) === null || _a === void 0 ? void 0 : _a.length)
? this.getFirstField(format.urlFields)
: ((_a = opts.urlFields) === null || _a === void 0 ? void 0 : _a.length)
? this.getFirstField(opts.urlFields)
: this.url;
if (url)
parts.push(`[${this.name}](${url})`);
parts.push(ma({ url, inner: this.name }));
else
parts.push(this.name);
// email
if (format.displayEmail && this.email) {
if (opts.displayEmail && this.email) {
parts.push(`<${this.email}>`);
}
// contributions
if (format.displayContributions &&
format.githubRepoSlug &&
this.githubUsername) {
const contributionsUrl = `https://github.com/${format.githubRepoSlug}/commits?author=${this.githubUsername}`;
parts.push(`— [view contributions](${contributionsUrl} "View the GitHub contributions of ${this.name} on repository ${format.githubRepoSlug}")`);
if (opts.displayContributions && opts.githubSlug && this.githubUsername) {
const contributionsUrl = `https://github.com/${opts.githubSlug}/commits?author=${this.githubUsername}`;
parts.push('— ' +
ma({
url: contributionsUrl,
inner: 'view contributions',
title: `View the GitHub contributions of ${this.name} on repository ${opts.githubSlug}`,
}));
}
// description
if (format.displayDescription && this.description) {
if (opts.displayDescription && this.description) {
parts.push(`— ${this.description}`);

@@ -847,3 +923,3 @@ }

/** Convert the fellow into the usual HTML format */
toHtml(format = {}) {
toHtml(opts = {}) {
var _a;

@@ -854,29 +930,36 @@ if (!this.name)

// copyright
if (format.displayCopyright)
if (opts.displayCopyright)
parts.push('Copyright &copy;');
if (format.displayYears && this.years)
if (opts.displayYears && this.years)
parts.push(this.years);
// name + url
const url = format.displayUrl === false
const url = opts.displayUrl === false
? ''
: ((_a = format.urlFields) === null || _a === void 0 ? void 0 : _a.length)
? this.getFirstField(format.urlFields)
: ((_a = opts.urlFields) === null || _a === void 0 ? void 0 : _a.length)
? this.getFirstField(opts.urlFields)
: this.url;
if (url)
parts.push(`<a href="${url}">${this.name}</a>`);
parts.push(a({ url, inner: this.name }));
else
parts.push(this.name);
// email
if (format.displayEmail && this.email) {
parts.push(`<a href="mailto:${this.email}" title="Email ${this.name}">&lt;${this.email}&gt;</a>`);
if (opts.displayEmail && this.email) {
parts.push(a({
url: `mailto:${this.email}`,
inner: `&lt;${this.email}&gt;`,
title: `Email ${this.name}`,
}));
}
// contributions
if (format.displayContributions &&
format.githubRepoSlug &&
this.githubUsername) {
const contributionsUrl = `https://github.com/${format.githubRepoSlug}/commits?author=${this.githubUsername}`;
parts.push(`— <a href="${contributionsUrl}" title="View the GitHub contributions of ${this.name} on repository ${format.githubRepoSlug}">view contributions</a>`);
if (opts.displayContributions && opts.githubSlug && this.githubUsername) {
const contributionsUrl = `https://github.com/${opts.githubSlug}/commits?author=${this.githubUsername}`;
parts.push('— ' +
a({
url: contributionsUrl,
inner: 'view contributions',
title: `View the GitHub contributions of ${this.name} on repository ${opts.githubSlug}`,
}));
}
// description
if (format.displayDescription && this.description) {
if (opts.displayDescription && this.description) {
parts.push(`— ${this.description}`);

@@ -887,2 +970,17 @@ }

}
/** Convert the fellow into the specified format */
toFormat(opts) {
switch (opts.format) {
case Format.string:
return this.toString(opts);
case Format.text:
return this.toText(opts);
case Format.markdown:
return this.toMarkdown(opts);
case Format.html:
return this.toHtml(opts);
default:
throw new Error(`Invalid format: ${opts.format}`);
}
}
}

@@ -889,0 +987,0 @@ /** A singleton attached to the class that stores it's instances to enable convergence of data */

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.comparator = void 0;
exports.comparator = exports.Format = void 0;
// external
const render_1 = require("@bevry/render");
/** Verify an email */
function verifyEmail(email) {
if (!email)
return false;
return /.+?@.+/.test(email);
}
/** Verify a URL */
async function fetchOk(url) {
const resp = await fetch(url, { method: 'HEAD' });
return resp.ok;
}
/** Verify the failure of a URL */
async function fetchNotOk(url) {
const ok = await fetchOk(url);
return !ok;
}
/** A rendering style for {@link Fellow} */
var Format;
(function (Format) {
/** Use {@link Fellow.toString} */
Format["string"] = "string";
/** Use {@link Fellow.toText} */
Format["text"] = "text";
/** Use {@link Fellow.toMarkdown} */
Format["markdown"] = "markdown";
/** Use {@link Fellow.toHtml} */
Format["html"] = "html";
})(Format || (exports.Format = Format = {}));
/** Prevent GitHub username matches for the following. Generated by experience and with GitHub Copilot. */

@@ -164,3 +194,3 @@ const githubInvalidUsernames = [

}
/** Get {@link Follow.nomen} if resolved, otherwise {@link Fellow.username} */
/** Get {@link Fellow.nomen} if resolved, otherwise {@link Fellow.username} */
get name() {

@@ -343,2 +373,43 @@ return this.nomen || this.username || '';

}
/** Remove invalid username urls */
async verifyUrls() {
for (const field of this.urlFields) {
const url = this[field];
if (!url)
continue;
switch (field) {
case 'githubUrl':
if (await fetchNotOk(url))
this.githubUsername = '';
break;
case 'gitlabUrl':
if (await fetchNotOk(url))
this.gitlabUsername = '';
break;
case 'thanksdevUrl':
if (await fetchNotOk(url))
this._thanksdevUrlEnabled = false;
break;
case 'opencollectiveUrl':
if (await fetchNotOk(url))
this.opencollectiveUsername = '';
break;
case 'patreonUrl':
if (await fetchNotOk(url))
this.patreonUsername = '';
break;
case 'twitterUrl':
if (await fetchNotOk(url))
this.twitterUsername = '';
break;
case 'facebookUrl':
if (await fetchNotOk(url))
this.facebookUsername = '';
break;
default:
// unknown, ignore
continue;
}
}
}
/** Get all unique resolved URLs */

@@ -356,4 +427,6 @@ get urls() {

if (input) {
// convert to https
input = input.replace(/^http:\/\//, 'https://');
// convert to https and trim www. as it is 2023
input = input.replace(/^http:\/\//, 'https://').replace(/^www\./, '');
if (input.startsWith('https://') === false)
input = `https://${input}`;
// slice 1 to skip websiteUrl

@@ -389,3 +462,3 @@ for (const field of this.urlFields) {

input = trim(input);
if (!input)
if (!verifyEmail(input))
return;

@@ -741,11 +814,11 @@ this.emails.add(input);

*/
toString(format = {}) {
toString(opts = {}) {
var _a;
const parts = [];
if (!this.name)
return '';
const parts = [];
// copyright
if (format.displayCopyright)
if (opts.displayCopyright)
parts.push('Copyright &copy;');
if (format.displayYears && this.years)
if (opts.displayYears && this.years)
parts.push(this.years);

@@ -755,8 +828,8 @@ // name

// email
if (format.displayEmail !== false && this.email) {
if (opts.displayEmail !== false && this.email) {
parts.push(`<${this.email}>`);
}
// urls
const urls = ((_a = format.urlFields) === null || _a === void 0 ? void 0 : _a.length)
? this.getFields(format.urlFields)
const urls = ((_a = opts.urlFields) === null || _a === void 0 ? void 0 : _a.length)
? this.getFields(opts.urlFields)
: this.urls;

@@ -766,8 +839,8 @@ for (const url of urls) {

}
// description
if (format.displayDescription && this.description) {
parts.push(`: ${this.description}`);
// add description without space before :, and return
let result = parts.join(' ');
if (opts.displayDescription && this.description) {
result += `: ${this.description}`;
}
// return
return parts.join(' ');
return result;
}

@@ -778,3 +851,3 @@ /**

*/
toText(format = {}) {
toText(opts = {}) {
var _a;

@@ -787,14 +860,14 @@ if (!this.name)

// email
if (format.displayEmail && this.email) {
if (opts.displayEmail && this.email) {
parts.push(`✉️ ${this.email}`);
}
// description
if (format.displayDescription !== false && this.description) {
if (opts.displayDescription !== false && this.description) {
parts.push(`📝 ${this.description}`);
}
// url
const url = format.displayUrl === false
const url = opts.displayUrl === false
? ''
: ((_a = format.urlFields) === null || _a === void 0 ? void 0 : _a.length)
? this.getFirstField(format.urlFields)
: ((_a = opts.urlFields) === null || _a === void 0 ? void 0 : _a.length)
? this.getFirstField(opts.urlFields)
: this.url;

@@ -810,3 +883,3 @@ if (url)

*/
toMarkdown(format = {}) {
toMarkdown(opts = {}) {
var _a;

@@ -817,29 +890,32 @@ if (!this.name)

// copyright
if (format.displayCopyright)
if (opts.displayCopyright)
parts.push('Copyright &copy;');
if (format.displayYears && this.years)
if (opts.displayYears && this.years)
parts.push(this.years);
// name + url
const url = format.displayUrl === false
const url = opts.displayUrl === false
? ''
: ((_a = format.urlFields) === null || _a === void 0 ? void 0 : _a.length)
? this.getFirstField(format.urlFields)
: ((_a = opts.urlFields) === null || _a === void 0 ? void 0 : _a.length)
? this.getFirstField(opts.urlFields)
: this.url;
if (url)
parts.push(`[${this.name}](${url})`);
parts.push((0, render_1.ma)({ url, inner: this.name }));
else
parts.push(this.name);
// email
if (format.displayEmail && this.email) {
if (opts.displayEmail && this.email) {
parts.push(`<${this.email}>`);
}
// contributions
if (format.displayContributions &&
format.githubRepoSlug &&
this.githubUsername) {
const contributionsUrl = `https://github.com/${format.githubRepoSlug}/commits?author=${this.githubUsername}`;
parts.push(`— [view contributions](${contributionsUrl} "View the GitHub contributions of ${this.name} on repository ${format.githubRepoSlug}")`);
if (opts.displayContributions && opts.githubSlug && this.githubUsername) {
const contributionsUrl = `https://github.com/${opts.githubSlug}/commits?author=${this.githubUsername}`;
parts.push('— ' +
(0, render_1.ma)({
url: contributionsUrl,
inner: 'view contributions',
title: `View the GitHub contributions of ${this.name} on repository ${opts.githubSlug}`,
}));
}
// description
if (format.displayDescription && this.description) {
if (opts.displayDescription && this.description) {
parts.push(`— ${this.description}`);

@@ -851,3 +927,3 @@ }

/** Convert the fellow into the usual HTML format */
toHtml(format = {}) {
toHtml(opts = {}) {
var _a;

@@ -858,29 +934,36 @@ if (!this.name)

// copyright
if (format.displayCopyright)
if (opts.displayCopyright)
parts.push('Copyright &copy;');
if (format.displayYears && this.years)
if (opts.displayYears && this.years)
parts.push(this.years);
// name + url
const url = format.displayUrl === false
const url = opts.displayUrl === false
? ''
: ((_a = format.urlFields) === null || _a === void 0 ? void 0 : _a.length)
? this.getFirstField(format.urlFields)
: ((_a = opts.urlFields) === null || _a === void 0 ? void 0 : _a.length)
? this.getFirstField(opts.urlFields)
: this.url;
if (url)
parts.push(`<a href="${url}">${this.name}</a>`);
parts.push((0, render_1.a)({ url, inner: this.name }));
else
parts.push(this.name);
// email
if (format.displayEmail && this.email) {
parts.push(`<a href="mailto:${this.email}" title="Email ${this.name}">&lt;${this.email}&gt;</a>`);
if (opts.displayEmail && this.email) {
parts.push((0, render_1.a)({
url: `mailto:${this.email}`,
inner: `&lt;${this.email}&gt;`,
title: `Email ${this.name}`,
}));
}
// contributions
if (format.displayContributions &&
format.githubRepoSlug &&
this.githubUsername) {
const contributionsUrl = `https://github.com/${format.githubRepoSlug}/commits?author=${this.githubUsername}`;
parts.push(`— <a href="${contributionsUrl}" title="View the GitHub contributions of ${this.name} on repository ${format.githubRepoSlug}">view contributions</a>`);
if (opts.displayContributions && opts.githubSlug && this.githubUsername) {
const contributionsUrl = `https://github.com/${opts.githubSlug}/commits?author=${this.githubUsername}`;
parts.push('— ' +
(0, render_1.a)({
url: contributionsUrl,
inner: 'view contributions',
title: `View the GitHub contributions of ${this.name} on repository ${opts.githubSlug}`,
}));
}
// description
if (format.displayDescription && this.description) {
if (opts.displayDescription && this.description) {
parts.push(`— ${this.description}`);

@@ -891,2 +974,17 @@ }

}
/** Convert the fellow into the specified format */
toFormat(opts) {
switch (opts.format) {
case Format.string:
return this.toString(opts);
case Format.text:
return this.toText(opts);
case Format.markdown:
return this.toMarkdown(opts);
case Format.html:
return this.toHtml(opts);
default:
throw new Error(`Invalid format: ${opts.format}`);
}
}
}

@@ -893,0 +991,0 @@ /** A singleton attached to the class that stores it's instances to enable convergence of data */

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.comparator = void 0;
exports.comparator = exports.Format = void 0;
// external
const render_1 = require("@bevry/render");
/** Verify an email */
function verifyEmail(email) {
if (!email)
return false;
return /.+?@.+/.test(email);
}
/** Verify a URL */
async function fetchOk(url) {
const resp = await fetch(url, { method: 'HEAD' });
return resp.ok;
}
/** Verify the failure of a URL */
async function fetchNotOk(url) {
const ok = await fetchOk(url);
return !ok;
}
/** A rendering style for {@link Fellow} */
var Format;
(function (Format) {
/** Use {@link Fellow.toString} */
Format["string"] = "string";
/** Use {@link Fellow.toText} */
Format["text"] = "text";
/** Use {@link Fellow.toMarkdown} */
Format["markdown"] = "markdown";
/** Use {@link Fellow.toHtml} */
Format["html"] = "html";
})(Format || (exports.Format = Format = {}));
/** Prevent GitHub username matches for the following. Generated by experience and with GitHub Copilot. */

@@ -193,3 +223,3 @@ const githubInvalidUsernames = [

}
/** Get {@link Follow.nomen} if resolved, otherwise {@link Fellow.username} */
/** Get {@link Fellow.nomen} if resolved, otherwise {@link Fellow.username} */
get name() {

@@ -389,2 +419,43 @@ return this.nomen || this.username || '';

];
/** Remove invalid username urls */
async verifyUrls() {
for (const field of this.urlFields) {
const url = this[field];
if (!url)
continue;
switch (field) {
case 'githubUrl':
if (await fetchNotOk(url))
this.githubUsername = '';
break;
case 'gitlabUrl':
if (await fetchNotOk(url))
this.gitlabUsername = '';
break;
case 'thanksdevUrl':
if (await fetchNotOk(url))
this._thanksdevUrlEnabled = false;
break;
case 'opencollectiveUrl':
if (await fetchNotOk(url))
this.opencollectiveUsername = '';
break;
case 'patreonUrl':
if (await fetchNotOk(url))
this.patreonUsername = '';
break;
case 'twitterUrl':
if (await fetchNotOk(url))
this.twitterUsername = '';
break;
case 'facebookUrl':
if (await fetchNotOk(url))
this.facebookUsername = '';
break;
default:
// unknown, ignore
continue;
}
}
}
/** Get all unique resolved URLs */

@@ -402,4 +473,6 @@ get urls() {

if (input) {
// convert to https
input = input.replace(/^http:\/\//, 'https://');
// convert to https and trim www. as it is 2023
input = input.replace(/^http:\/\//, 'https://').replace(/^www\./, '');
if (input.startsWith('https://') === false)
input = `https://${input}`;
// slice 1 to skip websiteUrl

@@ -439,3 +512,3 @@ for (const field of this.urlFields) {

input = trim(input);
if (!input)
if (!verifyEmail(input))
return;

@@ -742,10 +815,10 @@ this.emails.add(input);

*/
toString(format = {}) {
const parts = [];
toString(opts = {}) {
if (!this.name)
return '';
const parts = [];
// copyright
if (format.displayCopyright)
if (opts.displayCopyright)
parts.push('Copyright &copy;');
if (format.displayYears && this.years)
if (opts.displayYears && this.years)
parts.push(this.years);

@@ -755,8 +828,8 @@ // name

// email
if (format.displayEmail !== false && this.email) {
if (opts.displayEmail !== false && this.email) {
parts.push(`<${this.email}>`);
}
// urls
const urls = format.urlFields?.length
? this.getFields(format.urlFields)
const urls = opts.urlFields?.length
? this.getFields(opts.urlFields)
: this.urls;

@@ -766,8 +839,8 @@ for (const url of urls) {

}
// description
if (format.displayDescription && this.description) {
parts.push(`: ${this.description}`);
// add description without space before :, and return
let result = parts.join(' ');
if (opts.displayDescription && this.description) {
result += `: ${this.description}`;
}
// return
return parts.join(' ');
return result;
}

@@ -778,3 +851,3 @@ /**

*/
toText(format = {}) {
toText(opts = {}) {
if (!this.name)

@@ -786,14 +859,14 @@ return '';

// email
if (format.displayEmail && this.email) {
if (opts.displayEmail && this.email) {
parts.push(`✉️ ${this.email}`);
}
// description
if (format.displayDescription !== false && this.description) {
if (opts.displayDescription !== false && this.description) {
parts.push(`📝 ${this.description}`);
}
// url
const url = format.displayUrl === false
const url = opts.displayUrl === false
? ''
: format.urlFields?.length
? this.getFirstField(format.urlFields)
: opts.urlFields?.length
? this.getFirstField(opts.urlFields)
: this.url;

@@ -809,3 +882,3 @@ if (url)

*/
toMarkdown(format = {}) {
toMarkdown(opts = {}) {
if (!this.name)

@@ -815,29 +888,32 @@ return '';

// copyright
if (format.displayCopyright)
if (opts.displayCopyright)
parts.push('Copyright &copy;');
if (format.displayYears && this.years)
if (opts.displayYears && this.years)
parts.push(this.years);
// name + url
const url = format.displayUrl === false
const url = opts.displayUrl === false
? ''
: format.urlFields?.length
? this.getFirstField(format.urlFields)
: opts.urlFields?.length
? this.getFirstField(opts.urlFields)
: this.url;
if (url)
parts.push(`[${this.name}](${url})`);
parts.push((0, render_1.ma)({ url, inner: this.name }));
else
parts.push(this.name);
// email
if (format.displayEmail && this.email) {
if (opts.displayEmail && this.email) {
parts.push(`<${this.email}>`);
}
// contributions
if (format.displayContributions &&
format.githubRepoSlug &&
this.githubUsername) {
const contributionsUrl = `https://github.com/${format.githubRepoSlug}/commits?author=${this.githubUsername}`;
parts.push(`— [view contributions](${contributionsUrl} "View the GitHub contributions of ${this.name} on repository ${format.githubRepoSlug}")`);
if (opts.displayContributions && opts.githubSlug && this.githubUsername) {
const contributionsUrl = `https://github.com/${opts.githubSlug}/commits?author=${this.githubUsername}`;
parts.push('— ' +
(0, render_1.ma)({
url: contributionsUrl,
inner: 'view contributions',
title: `View the GitHub contributions of ${this.name} on repository ${opts.githubSlug}`,
}));
}
// description
if (format.displayDescription && this.description) {
if (opts.displayDescription && this.description) {
parts.push(`— ${this.description}`);

@@ -849,3 +925,3 @@ }

/** Convert the fellow into the usual HTML format */
toHtml(format = {}) {
toHtml(opts = {}) {
if (!this.name)

@@ -855,29 +931,36 @@ return '';

// copyright
if (format.displayCopyright)
if (opts.displayCopyright)
parts.push('Copyright &copy;');
if (format.displayYears && this.years)
if (opts.displayYears && this.years)
parts.push(this.years);
// name + url
const url = format.displayUrl === false
const url = opts.displayUrl === false
? ''
: format.urlFields?.length
? this.getFirstField(format.urlFields)
: opts.urlFields?.length
? this.getFirstField(opts.urlFields)
: this.url;
if (url)
parts.push(`<a href="${url}">${this.name}</a>`);
parts.push((0, render_1.a)({ url, inner: this.name }));
else
parts.push(this.name);
// email
if (format.displayEmail && this.email) {
parts.push(`<a href="mailto:${this.email}" title="Email ${this.name}">&lt;${this.email}&gt;</a>`);
if (opts.displayEmail && this.email) {
parts.push((0, render_1.a)({
url: `mailto:${this.email}`,
inner: `&lt;${this.email}&gt;`,
title: `Email ${this.name}`,
}));
}
// contributions
if (format.displayContributions &&
format.githubRepoSlug &&
this.githubUsername) {
const contributionsUrl = `https://github.com/${format.githubRepoSlug}/commits?author=${this.githubUsername}`;
parts.push(`— <a href="${contributionsUrl}" title="View the GitHub contributions of ${this.name} on repository ${format.githubRepoSlug}">view contributions</a>`);
if (opts.displayContributions && opts.githubSlug && this.githubUsername) {
const contributionsUrl = `https://github.com/${opts.githubSlug}/commits?author=${this.githubUsername}`;
parts.push('— ' +
(0, render_1.a)({
url: contributionsUrl,
inner: 'view contributions',
title: `View the GitHub contributions of ${this.name} on repository ${opts.githubSlug}`,
}));
}
// description
if (format.displayDescription && this.description) {
if (opts.displayDescription && this.description) {
parts.push(`— ${this.description}`);

@@ -888,3 +971,18 @@ }

}
/** Convert the fellow into the specified format */
toFormat(opts) {
switch (opts.format) {
case Format.string:
return this.toString(opts);
case Format.text:
return this.toText(opts);
case Format.markdown:
return this.toMarkdown(opts);
case Format.html:
return this.toHtml(opts);
default:
throw new Error(`Invalid format: ${opts.format}`);
}
}
}
exports.default = Fellow;

@@ -0,1 +1,12 @@

/** A rendering style for {@link Fellow} */
export declare enum Format {
/** Use {@link Fellow.toString} */
string = "string",
/** Use {@link Fellow.toText} */
text = "text",
/** Use {@link Fellow.toMarkdown} */
markdown = "markdown",
/** Use {@link Fellow.toHtml} */
html = "html"
}
/**

@@ -7,2 +18,4 @@ * Options for formatting the rendered outputs.

export interface FormatOptions {
/** When used with {@link Fellow.toFormat} this determines the format that is used. */
format?: Format | null;
/** Whether or not to display {@link Fellow.url} */

@@ -18,6 +31,6 @@ displayUrl?: boolean;

displayYears?: boolean;
/** Whether or not to display a link to the user's contributions. Requires {@link FormatOptions.githubRepoSlug} */
/** Whether or not to display a link to the user's contributions. Requires {@link FormatOptions.githubSlug} */
displayContributions?: boolean;
/** The repository for when using with {@link FormatOptions.displayContributions} */
githubRepoSlug?: string;
/** The repository for using with {@link FormatOptions.displayContributions} */
githubSlug?: string;
/** An array of fields to prefer for the URL. {@link Fellow.toString} will output each one. */

@@ -74,3 +87,3 @@ urlFields?: Array<string>;

set nomen(input: string);
/** Get {@link Follow.nomen} if resolved, otherwise {@link Fellow.username} */
/** Get {@link Fellow.nomen} if resolved, otherwise {@link Fellow.username} */
get name(): string;

@@ -129,2 +142,4 @@ /** Alias for {@link Fellow.nomen} */

protected readonly urlFields: string[];
/** Remove invalid username urls */
verifyUrls(): Promise<void>;
/** Get all unique resolved URLs */

@@ -242,3 +257,3 @@ get urls(): string[];

*/
toString(format?: FormatOptions): string;
toString(opts?: FormatOptions): string;
/**

@@ -248,3 +263,3 @@ * Convert the fellow into the usual text format

*/
toText(format?: FormatOptions): string;
toText(opts?: FormatOptions): string;
/**

@@ -254,6 +269,10 @@ * Convert the fellow into the usual markdown format

*/
toMarkdown(format?: FormatOptions): string;
toMarkdown(opts?: FormatOptions): string;
/** Convert the fellow into the usual HTML format */
toHtml(format?: FormatOptions): string;
toHtml(opts?: FormatOptions): string;
/** Convert the fellow into the specified format */
toFormat(opts: FormatOptions & {
format: Format;
}): string;
}
//# sourceMappingURL=index.d.ts.map
{
"name": "fellow",
"version": "7.0.2",
"version": "7.0.3-next.1703635100.eb05eaabeb2a1367e665495a73d70661c8953365",
"license": "Artistic-2.0",

@@ -87,2 +87,5 @@ "description": "Fellow is a package for creating people that can be unified by their shared values via a singleton list on the class",

],
"donors": [
"Skunk Team (https://skunk.team) (https://github.com/skunkteam)"
],
"engines": {

@@ -207,2 +210,3 @@ "node": ">=10"

"dependencies": {
"@bevry/render": "^1.0.0",
"editions": "^6.19.0"

@@ -212,5 +216,5 @@ },

"@types/node": "^20.10.5",
"@typescript-eslint/eslint-plugin": "^6.15.0",
"@typescript-eslint/parser": "^6.15.0",
"assert-helpers": "^11.9.0",
"@typescript-eslint/eslint-plugin": "^6.16.0",
"@typescript-eslint/parser": "^6.16.0",
"assert-helpers": "^11.10.0",
"eslint": "^8.56.0",

@@ -220,3 +224,3 @@ "eslint-config-bevry": "^5.3.0",

"eslint-plugin-babel": "^5.3.1",
"eslint-plugin-prettier": "^5.1.0",
"eslint-plugin-prettier": "^5.1.2",
"kava": "^7.5.0",

@@ -271,2 +275,2 @@ "make-deno-edition": "^2.1.0",

}
}
}

@@ -54,3 +54,3 @@ <!-- TITLE/ -->

``` typescript
import pkg from 'https://unpkg.com/fellow@^7.0.2/edition-deno/index.ts'
import pkg from 'https://unpkg.com/fellow@^7.0.3/edition-deno/index.ts'
```

@@ -62,3 +62,3 @@

<script type="module">
import pkg from '//cdn.skypack.dev/fellow@^7.0.2'
import pkg from '//cdn.skypack.dev/fellow@^7.0.3'
</script>

@@ -71,3 +71,3 @@ ```

<script type="module">
import pkg from '//unpkg.com/fellow@^7.0.2'
import pkg from '//unpkg.com/fellow@^7.0.3'
</script>

@@ -80,3 +80,3 @@ ```

<script type="module">
import pkg from '//dev.jspm.io/fellow@7.0.2'
import pkg from '//dev.jspm.io/fellow@7.0.3'
</script>

@@ -83,0 +83,0 @@ ```

@@ -0,1 +1,34 @@

// external
import { a, ma } from '@bevry/render'
/** Verify an email */
function verifyEmail(email: string): boolean {
if (!email) return false
return /.+?@.+/.test(email)
}
/** Verify a URL */
async function fetchOk(url: string): Promise<boolean> {
const resp = await fetch(url, { method: 'HEAD' })
return resp.ok
}
/** Verify the failure of a URL */
async function fetchNotOk(url: string): Promise<boolean> {
const ok = await fetchOk(url)
return !ok
}
/** A rendering style for {@link Fellow} */
export enum Format {
/** Use {@link Fellow.toString} */
string = 'string',
/** Use {@link Fellow.toText} */
text = 'text',
/** Use {@link Fellow.toMarkdown} */
markdown = 'markdown',
/** Use {@link Fellow.toHtml} */
html = 'html',
}
/**

@@ -7,2 +40,5 @@ * Options for formatting the rendered outputs.

export interface FormatOptions {
/** When used with {@link Fellow.toFormat} this determines the format that is used. */
format?: Format | null
/** Whether or not to display {@link Fellow.url} */

@@ -23,7 +59,7 @@ displayUrl?: boolean

/** Whether or not to display a link to the user's contributions. Requires {@link FormatOptions.githubRepoSlug} */
/** Whether or not to display a link to the user's contributions. Requires {@link FormatOptions.githubSlug} */
displayContributions?: boolean
/** The repository for when using with {@link FormatOptions.displayContributions} */
githubRepoSlug?: string
/** The repository for using with {@link FormatOptions.displayContributions} */
githubSlug?: string

@@ -250,3 +286,3 @@ /** An array of fields to prefer for the URL. {@link Fellow.toString} will output each one. */

/** Get {@link Follow.nomen} if resolved, otherwise {@link Fellow.username} */
/** Get {@link Fellow.nomen} if resolved, otherwise {@link Fellow.username} */
get name(): string {

@@ -450,2 +486,36 @@ return this.nomen || this.username || ''

/** Remove invalid username urls */
async verifyUrls(): Promise<void> {
for (const field of this.urlFields) {
const url = this[field]
if (!url) continue
switch (field) {
case 'githubUrl':
if (await fetchNotOk(url)) this.githubUsername = ''
break
case 'gitlabUrl':
if (await fetchNotOk(url)) this.gitlabUsername = ''
break
case 'thanksdevUrl':
if (await fetchNotOk(url)) this._thanksdevUrlEnabled = false
break
case 'opencollectiveUrl':
if (await fetchNotOk(url)) this.opencollectiveUsername = ''
break
case 'patreonUrl':
if (await fetchNotOk(url)) this.patreonUsername = ''
break
case 'twitterUrl':
if (await fetchNotOk(url)) this.twitterUsername = ''
break
case 'facebookUrl':
if (await fetchNotOk(url)) this.facebookUsername = ''
break
default:
// unknown, ignore
continue
}
}
}
/** Get all unique resolved URLs */

@@ -464,4 +534,5 @@ get urls() {

if (input) {
// convert to https
input = input.replace(/^http:\/\//, 'https://')
// convert to https and trim www. as it is 2023
input = input.replace(/^http:\/\//, 'https://').replace(/^www\./, '')
if (input.startsWith('https://') === false) input = `https://${input}`
// slice 1 to skip websiteUrl

@@ -503,3 +574,3 @@ for (const field of this.urlFields) {

input = trim(input)
if (!input) return
if (!verifyEmail(input)) return
this.emails.add(input)

@@ -845,9 +916,9 @@ }

*/
toString(format: FormatOptions = {}): string {
toString(opts: FormatOptions = {}): string {
if (!this.name) return ''
const parts = []
if (!this.name) return ''
// copyright
if (format.displayCopyright) parts.push('Copyright &copy;')
if (format.displayYears && this.years) parts.push(this.years)
if (opts.displayCopyright) parts.push('Copyright &copy;')
if (opts.displayYears && this.years) parts.push(this.years)

@@ -858,3 +929,3 @@ // name

// email
if (format.displayEmail !== false && this.email) {
if (opts.displayEmail !== false && this.email) {
parts.push(`<${this.email}>`)

@@ -864,4 +935,4 @@ }

// urls
const urls = format.urlFields?.length
? this.getFields(format.urlFields)
const urls = opts.urlFields?.length
? this.getFields(opts.urlFields)
: this.urls

@@ -872,9 +943,8 @@ for (const url of urls) {

// description
if (format.displayDescription && this.description) {
parts.push(`: ${this.description}`)
// add description without space before :, and return
let result = parts.join(' ')
if (opts.displayDescription && this.description) {
result += `: ${this.description}`
}
// return
return parts.join(' ')
return result
}

@@ -886,3 +956,3 @@

*/
toText(format: FormatOptions = {}): string {
toText(opts: FormatOptions = {}): string {
if (!this.name) return ''

@@ -895,3 +965,3 @@ const parts = []

// email
if (format.displayEmail && this.email) {
if (opts.displayEmail && this.email) {
parts.push(`✉️ ${this.email}`)

@@ -901,3 +971,3 @@ }

// description
if (format.displayDescription !== false && this.description) {
if (opts.displayDescription !== false && this.description) {
parts.push(`📝 ${this.description}`)

@@ -908,6 +978,6 @@ }

const url =
format.displayUrl === false
opts.displayUrl === false
? ''
: format.urlFields?.length
? this.getFirstField(format.urlFields)
: opts.urlFields?.length
? this.getFirstField(opts.urlFields)
: this.url

@@ -924,3 +994,3 @@ if (url) parts.push(`🔗 ${this.url}`)

*/
toMarkdown(format: FormatOptions = {}): string {
toMarkdown(opts: FormatOptions = {}): string {
if (!this.name) return ''

@@ -930,17 +1000,17 @@ const parts = []

// copyright
if (format.displayCopyright) parts.push('Copyright &copy;')
if (format.displayYears && this.years) parts.push(this.years)
if (opts.displayCopyright) parts.push('Copyright &copy;')
if (opts.displayYears && this.years) parts.push(this.years)
// name + url
const url =
format.displayUrl === false
opts.displayUrl === false
? ''
: format.urlFields?.length
? this.getFirstField(format.urlFields)
: opts.urlFields?.length
? this.getFirstField(opts.urlFields)
: this.url
if (url) parts.push(`[${this.name}](${url})`)
if (url) parts.push(ma({ url, inner: this.name }))
else parts.push(this.name)
// email
if (format.displayEmail && this.email) {
if (opts.displayEmail && this.email) {
parts.push(`<${this.email}>`)

@@ -950,10 +1020,11 @@ }

// contributions
if (
format.displayContributions &&
format.githubRepoSlug &&
this.githubUsername
) {
const contributionsUrl = `https://github.com/${format.githubRepoSlug}/commits?author=${this.githubUsername}`
if (opts.displayContributions && opts.githubSlug && this.githubUsername) {
const contributionsUrl = `https://github.com/${opts.githubSlug}/commits?author=${this.githubUsername}`
parts.push(
`— [view contributions](${contributionsUrl} "View the GitHub contributions of ${this.name} on repository ${format.githubRepoSlug}")`,
'— ' +
ma({
url: contributionsUrl,
inner: 'view contributions',
title: `View the GitHub contributions of ${this.name} on repository ${opts.githubSlug}`,
}),
)

@@ -963,3 +1034,3 @@ }

// description
if (format.displayDescription && this.description) {
if (opts.displayDescription && this.description) {
parts.push(`— ${this.description}`)

@@ -973,3 +1044,3 @@ }

/** Convert the fellow into the usual HTML format */
toHtml(format: FormatOptions = {}): string {
toHtml(opts: FormatOptions = {}): string {
if (!this.name) return ''

@@ -979,19 +1050,23 @@ const parts = []

// copyright
if (format.displayCopyright) parts.push('Copyright &copy;')
if (format.displayYears && this.years) parts.push(this.years)
if (opts.displayCopyright) parts.push('Copyright &copy;')
if (opts.displayYears && this.years) parts.push(this.years)
// name + url
const url =
format.displayUrl === false
opts.displayUrl === false
? ''
: format.urlFields?.length
? this.getFirstField(format.urlFields)
: opts.urlFields?.length
? this.getFirstField(opts.urlFields)
: this.url
if (url) parts.push(`<a href="${url}">${this.name}</a>`)
if (url) parts.push(a({ url, inner: this.name }))
else parts.push(this.name)
// email
if (format.displayEmail && this.email) {
if (opts.displayEmail && this.email) {
parts.push(
`<a href="mailto:${this.email}" title="Email ${this.name}">&lt;${this.email}&gt;</a>`,
a({
url: `mailto:${this.email}`,
inner: `&lt;${this.email}&gt;`,
title: `Email ${this.name}`,
}),
)

@@ -1001,10 +1076,11 @@ }

// contributions
if (
format.displayContributions &&
format.githubRepoSlug &&
this.githubUsername
) {
const contributionsUrl = `https://github.com/${format.githubRepoSlug}/commits?author=${this.githubUsername}`
if (opts.displayContributions && opts.githubSlug && this.githubUsername) {
const contributionsUrl = `https://github.com/${opts.githubSlug}/commits?author=${this.githubUsername}`
parts.push(
`— <a href="${contributionsUrl}" title="View the GitHub contributions of ${this.name} on repository ${format.githubRepoSlug}">view contributions</a>`,
'— ' +
a({
url: contributionsUrl,
inner: 'view contributions',
title: `View the GitHub contributions of ${this.name} on repository ${opts.githubSlug}`,
}),
)

@@ -1014,3 +1090,3 @@ }

// description
if (format.displayDescription && this.description) {
if (opts.displayDescription && this.description) {
parts.push(`— ${this.description}`)

@@ -1022,2 +1098,18 @@ }

}
/** Convert the fellow into the specified format */
toFormat(opts: FormatOptions & { format: Format }): string {
switch (opts.format) {
case Format.string:
return this.toString(opts)
case Format.text:
return this.toText(opts)
case Format.markdown:
return this.toMarkdown(opts)
case Format.html:
return this.toHtml(opts)
default:
throw new Error(`Invalid format: ${opts.format}`)
}
}
}

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc