sandhog
Version:
A virtual Open Source project maintainer
760 lines (722 loc) • 26.9 kB
JavaScript
import {
SECTION_KINDS,
findLicense,
findPackage
} from "./chunk-4KN5GL56.js";
import {
formatContributor
} from "./chunk-VWKPPDPS.js";
import {
listFormat
} from "./chunk-VZLM7UUV.js";
import {
getContributorsFromPackage
} from "./chunk-H3ZAQGMJ.js";
import {
CONSTANT
} from "./chunk-VYUMLP7D.js";
// src/code-style/find-code-style/find-code-styles.ts
import _fs from "fs";
import prettier from "prettier";
import path from "crosspath";
import eslintModule from "eslint";
// src/badge/generate-badge-url/generate-badge-url.ts
function generateBadgeUrl({ color, status, subject }) {
return `${CONSTANT.shieldRestEndpoint}/${subject}/${status}/${color}.svg`;
}
// src/code-style/get-code-style-for-code-style-kind/get-code-style-for-code-style-kind.ts
function getCodeStyleForCodeStyleKind(kind) {
switch (kind) {
case "prettier" /* PRETTIER */:
return {
kind,
badgeUrl: "https://img.shields.io/badge/code_style-prettier-ff69b4.svg",
url: "https://github.com/prettier/prettier"
};
case "Standard" /* STANDARD */:
return {
kind,
badgeUrl: "https://img.shields.io/badge/code%20style-standard-green.svg",
url: "https://github.com/feross/standard"
};
case "Airbnb" /* AIRBNB */:
return {
kind,
badgeUrl: "https://badgen.net/badge/code%20style/airbnb/ff5a5f",
url: "https://github.com/airbnb/javascript"
};
case "Idiomatic.js" /* IDIOMATIC */:
return {
kind,
badgeUrl: generateBadgeUrl({ subject: "code style", status: kind, color: "green" }),
url: "https://github.com/rwaldron/idiomatic.js"
};
case "Google" /* GOOGLE */:
return {
kind,
badgeUrl: generateBadgeUrl({ subject: "code style", status: kind, color: "green" }),
url: "https://google.github.io/styleguide/jsguide.html"
};
case "XO" /* XO */:
return {
kind,
badgeUrl: "https://img.shields.io/badge/code_style-XO-5ed9c7.svg",
url: "https://github.com/xojs/xo"
};
}
}
// src/code-style/find-code-style/find-code-styles.ts
async function findCodeStyles({
logger,
root = process.cwd(),
fs = { existsSync: _fs.existsSync, readFileSync: _fs.readFileSync },
pkg
}) {
if (pkg == null) {
pkg = (await findPackage({ root, logger, fs })).pkg;
}
const codeStyles = [];
logger.debug(`Trying to detect code style from root: '${root}'`);
if (await isPrettier(root)) {
logger.debug(`Detected "Prettier" as a project code style.`);
codeStyles.push("prettier" /* PRETTIER */);
}
if (isXo(pkg)) {
logger.debug(`Detected "XO" as a project code style.`);
codeStyles.push("XO" /* XO */);
}
if (isStandard(pkg)) {
logger.debug(`Detected "Standard" as a project code style.`);
codeStyles.push("Standard" /* STANDARD */);
}
const eslintConfig = await findEslintConfig(root);
if (eslintConfig != null) {
logger.debug(`Found an ESLint config within the root. Parsing it for code styles`);
const eslintCodeStyles = getCodeStylesFromEslintConfig(eslintConfig);
eslintCodeStyles.length > 0 ? logger.debug(
`Detected ${listFormat(
eslintCodeStyles.map((style) => `"${style}"`),
"and"
)} as project code style${eslintCodeStyles.length === 1 ? "" : "s"}`
) : logger.debug(`No code styles detected inside ESLint config`);
codeStyles.push(...eslintCodeStyles);
}
return [...new Set(codeStyles)].map(getCodeStyleForCodeStyleKind);
}
function getCodeStylesFromEslintConfig(config) {
const codeStyles = [];
const pluginNames = new Set(Object.keys(config.plugins ?? {}));
const containsAirbnb = pluginNames.has(CONSTANT.eslintAirbnbCodeStyleName);
if (containsAirbnb) {
codeStyles.push("Airbnb" /* AIRBNB */);
}
const containsGoogle = pluginNames.has(CONSTANT.eslintGoogleCodeStyleName);
if (containsGoogle) {
codeStyles.push("Google" /* GOOGLE */);
}
const containsPrettier = pluginNames.has(CONSTANT.eslintPrettierCodeStyleName);
if (containsPrettier) {
codeStyles.push("prettier" /* PRETTIER */);
}
const containsIdiomatic = pluginNames.has(CONSTANT.eslintIdiomaticCodeStyleName);
if (containsIdiomatic) {
codeStyles.push("Idiomatic.js" /* IDIOMATIC */);
}
const containsStandard = pluginNames.has(CONSTANT.eslintStandardCodeStyleName);
if (containsStandard) {
codeStyles.push("Standard" /* STANDARD */);
}
const containsXo = pluginNames.has(CONSTANT.eslintXoCodeStyleName);
if (containsXo) {
codeStyles.push("XO" /* XO */);
}
return codeStyles;
}
async function findEslintConfig(root) {
const eslint = new eslintModule.ESLint({});
try {
return await eslint.calculateConfigForFile(path.native.join(root, "package.js"));
} catch {
return void 0;
}
}
async function isPrettier(root) {
try {
const config = await prettier.resolveConfig(root);
return config != null;
} catch {
return true;
}
}
function isXo(pkg) {
return "xo" in pkg || pkg.dependencies != null && "xo" in pkg.dependencies || pkg.devDependencies != null && "xo" in pkg.devDependencies;
}
function isStandard(pkg) {
return "standard" in pkg || pkg.dependencies != null && "standard" in pkg.dependencies || pkg.devDependencies != null && "standard" in pkg.devDependencies;
}
// src/markdown/format-url/format-url.ts
function formatUrl({ inner, url }) {
return `<a href="${url}">${inner}</a>`;
}
// src/markdown/format-image/format-image.ts
function formatImage({ alt, url, height, width, kind = "html" }) {
if (kind === "html") {
return `<img ${alt != null ? `alt="${alt}"` : ""} src="${url}" ${height == null ? "" : `height="${height}"`} ${width == null ? "" : `width="${width}"`} />`;
} else {
return ``;
}
}
// src/package/take-github-repository-name/take-github-repository-name.ts
var REGEX = /(http?s?:\/\/?)?(www\.)?github.com\//g;
function takeGithubRepositoryName(pkg) {
if (pkg.repository?.url == null) return void 0;
return pkg.repository.url.replace(REGEX, "").replace(".git", "");
}
// src/license/get-license-for-license-name/get-license-for-license-name.ts
function getLicenseForLicenseName(licenseName) {
switch (licenseName) {
case "APACHE-2.0":
return {
licenseName,
url: "https://opensource.org/licenses/Apache-2.0",
badgeUrl: "https://img.shields.io/badge/License-Apache%202.0-blue.svg"
};
case "BSD-2-CLAUSE":
return {
licenseName,
url: "https://opensource.org/licenses/BSD-2-Clause",
badgeUrl: "https://img.shields.io/badge/License-BSD%202--Clause-orange.svg"
};
case "BSD-3-CLAUSE":
return {
licenseName,
url: "https://opensource.org/licenses/BSD-3-Clause",
badgeUrl: "https://img.shields.io/badge/License-BSD%203--Clause-blue.svg"
};
case "CC-BY-4.0":
return {
licenseName,
url: "https://creativecommons.org/licenses/by/4.0/",
badgeUrl: "https://img.shields.io/badge/License-CC%20BY%204.0-lightgrey.svg"
};
case "CC-BY-SA-4.0":
return {
licenseName,
url: "https://creativecommons.org/licenses/by-sa/4.0/",
badgeUrl: "https://img.shields.io/badge/License-CC%20BY--SA%204.0-lightgrey.svg"
};
case "EPL-1.0":
return {
licenseName,
url: "https://opensource.org/licenses/EPL-1.0",
badgeUrl: "https://img.shields.io/badge/License-EPL%201.0-red.svg"
};
case "GPL-3.0":
return {
licenseName,
url: "https://img.shields.io/badge/License-GPL%20v3-blue.svg",
badgeUrl: "https://www.gnu.org/licenses/gpl-3.0"
};
case "GPL-2.0":
return {
licenseName,
url: "https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html",
badgeUrl: "https://img.shields.io/badge/License-GPL%20v2-blue.svg"
};
case "AGPL-3.0":
return {
licenseName,
url: "https://www.gnu.org/licenses/agpl-3.0",
badgeUrl: "https://img.shields.io/badge/License-AGPL%20v3-blue.svg"
};
case "LGPL-3.0":
return {
licenseName,
url: "https://www.gnu.org/licenses/lgpl-3.0",
badgeUrl: "https://img.shields.io/badge/License-LGPL%20v3-blue.svg"
};
case "MIT":
return {
licenseName,
url: "https://opensource.org/licenses/MIT",
badgeUrl: "https://img.shields.io/badge/License-MIT-yellow.svg"
};
case "MPL-2.0":
return {
licenseName,
url: "https://opensource.org/licenses/MPL-2.0",
badgeUrl: "https://img.shields.io/badge/License-MPL%202.0-brightgreen.svg"
};
case "ARTISTIC-2.0":
return {
licenseName,
url: "https://opensource.org/licenses/Artistic-2.0",
badgeUrl: "https://img.shields.io/badge/License-Artistic%202.0-0298c3.svg"
};
case "ZLIB":
return {
licenseName,
url: "https://opensource.org/licenses/Zlib",
badgeUrl: "https://img.shields.io/badge/License-Zlib-lightgrey.svg"
};
}
}
// src/badge/get-badges/get-badges.ts
async function getBadges(options) {
const result = {};
const badgeOptions = options.config.readme.badges;
const excluded = new Set(badgeOptions.exclude);
const encodedName = options.pkg.name == null ? void 0 : encodeURIComponent(options.pkg.name);
const repoUrl = takeGithubRepositoryName(options.pkg);
const encodedRepoUrl = repoUrl == null ? void 0 : encodeURIComponent(repoUrl);
if (!excluded.has("downloads") && encodedName != null) {
result.downloads = [
formatUrl({
url: `https://npmcharts.com/compare/${encodedName}?minimal=true`,
inner: formatImage({
alt: "Downloads per month",
url: `https://img.shields.io/npm/dm/${encodedName}.svg`
})
})
];
}
if (!excluded.has("npm") && encodedName != null) {
result.npm = [
formatUrl({
url: `https://www.npmjs.com/package/${encodedName}`,
inner: formatImage({
url: `https://badge.fury.io/js/${encodedName}.svg`,
alt: `NPM version`
})
})
];
}
if (!excluded.has("dependencies") && repoUrl != null && encodedRepoUrl != null) {
result.dependencies = [
formatImage({
alt: `Dependencies`,
url: `https://img.shields.io/librariesio/github/${encodedRepoUrl}.svg`
})
];
}
if (!excluded.has("contributors") && encodedName != null && repoUrl != null && encodedRepoUrl != null) {
result.contributors = [
formatUrl({
url: `https://github.com/${repoUrl}/graphs/contributors`,
inner: formatImage({
alt: `Contributors`,
url: `https://img.shields.io/github/contributors/${encodedRepoUrl}.svg`
})
})
];
}
if (!excluded.has("code_style")) {
const codeStyles = await findCodeStyles(options);
if (codeStyles.length > 0) {
result.code_style = codeStyles.map(
({ kind, url, badgeUrl }) => formatUrl({
url,
inner: formatImage({
alt: `code style: ${kind}`,
url: badgeUrl
})
})
);
}
}
if (!excluded.has("license")) {
const licenseName = await findLicense(options);
if (licenseName != null) {
const { badgeUrl, url } = getLicenseForLicenseName(licenseName);
result.license = [
formatUrl({
url,
inner: formatImage({
alt: `License: ${licenseName}`,
url: badgeUrl
})
})
];
}
}
if (!excluded.has("patreon") && options.config.donate?.patreon?.userId != null) {
result.patreon = [
formatUrl({
url: CONSTANT.patreonDonateUrl(options.config.donate.patreon.userId),
inner: formatImage({
alt: `Support on Patreon`,
url: `https://img.shields.io/badge/patreon-donate-green.svg`
})
})
];
}
if (!excluded.has("open_collective_donate") && options.config.donate?.openCollective?.project != null) {
result.open_collective_donate = [
formatUrl({
url: CONSTANT.openCollectiveDonateUrl(options.config.donate.openCollective.project),
inner: formatImage({
alt: `Support on Open Collective`,
url: `https://img.shields.io/badge/opencollective-donate-green.svg`
})
})
];
}
if (!excluded.has("open_collective_backers") && options.config.donate?.openCollective?.project != null) {
result.open_collective_backers = [
formatUrl({
url: CONSTANT.openCollectiveContributorsUrl(options.config.donate.openCollective.project),
inner: formatImage({
alt: `Backers on Open Collective`,
url: `https://opencollective.com/${options.config.donate.openCollective.project}/backers/badge.svg`
})
})
];
}
if (!excluded.has("open_collective_sponsors") && options.config.donate?.openCollective?.project != null) {
result.open_collective_sponsors = [
formatUrl({
url: CONSTANT.openCollectiveContributorsUrl(options.config.donate.openCollective.project),
inner: formatImage({
alt: `Sponsors on Open Collective`,
url: `https://opencollective.com/${options.config.donate.openCollective.project}/sponsors/badge.svg`
})
})
];
}
return result;
}
// src/section/get-relevant-sections/get-relevant-sections.ts
function getRelevantSections({ config }) {
const excluded = new Set(config.readme.sections.exclude ?? []);
return new Set(SECTION_KINDS.filter((value) => !excluded.has(value)));
}
// src/readme/get-shadow-section-mark/get-shadow-section-mark.ts
function getShadowSectionMark(kind, startOrEnd) {
return `<!-- SHADOW_SECTION_${kind}_${startOrEnd} -->`.toUpperCase();
}
// src/readme/generate-readme/generate-readme.ts
import toc from "@effect/markdown-toc";
import path2 from "crosspath";
async function generateReadme(options) {
const sections = getRelevantSections(options);
const context = {
...options,
sections,
str: options.existingReadme ?? ""
};
if (sections.has("logo")) {
generateLogoSection(context);
}
if (sections.has("description_short")) {
generateDescriptionShortSection(context);
}
if (sections.has("badges")) {
generateBadgesSection(context);
}
if (sections.has("description_long")) {
generateDescriptionLongSection(context);
}
if (sections.has("features")) {
generateFeaturesSection(context);
}
if (sections.has("feature_image")) {
generateFeatureImageSection(context);
}
if (sections.has("backers")) {
generateBackersSection(context);
}
if (sections.has("toc")) {
generateTableOfContentsSection(context, true);
}
if (sections.has("install")) {
generateInstallSection(context);
}
if (sections.has("usage")) {
generateUsageSection(context);
}
if (sections.has("contributing")) {
generateContributingSection(context);
}
if (sections.has("maintainers")) {
generateMaintainersSection(context);
}
if (sections.has("faq")) {
generateFaqSection(context);
}
if (sections.has("license")) {
await generateLicenseSection(context);
}
if (sections.has("toc")) {
generateTableOfContentsSection(context, false);
}
return options.prettier.format(context.str, {
...options.config.prettier,
parser: "markdown"
});
}
function setSection(context, sectionKind, content, outro) {
const startMark = getShadowSectionMark(sectionKind, "start");
const endMark = getShadowSectionMark(sectionKind, "end");
const startMarkIndex = context.str.indexOf(startMark);
const endMarkIndex = context.str.indexOf(endMark);
const markedContent = startMark + "\n\n" + content + "\n\n" + endMark + "\n\n" + (outro == null ? "" : outro + "\n\n");
if (startMarkIndex >= 0 && endMarkIndex >= 0) {
const before = context.str.slice(0, startMarkIndex);
const after = context.str.slice(endMarkIndex + endMark.length);
context.str = before + markedContent + after;
} else {
context.str += markedContent;
}
}
function generateLogoSection(context) {
setSection(
context,
"logo",
// Don't proceed if there is no logo to generate an image for
context.config.logo.url == null ? "" : `<div>${formatImage({
url: context.config.logo.url,
alt: "Logo",
height: context.config.logo.height
})}</div>`
);
}
function generateFeatureImageSection(context) {
setSection(
context,
"feature_image",
// Don't proceed if there is no feature image to generate an image for
context.config.featureImage.url == null ? "" : `<div>${formatImage({
url: context.config.featureImage.url,
alt: "Feature image",
height: context.config.featureImage.height
})}</div><br>`
);
}
function generateTableOfContentsSection(context, reserveOnly = false) {
setSection(
context,
"toc",
`## Table of Contents
` + (reserveOnly ? (
// Only reserve the spot within the README with an empty placeholder that can be replaced later on
``
) : toc(context.str).content)
);
}
async function generateBadgesSection(context) {
const badges = await getBadges(context);
const content = Object.values(badges).map((value) => {
if (value == null) return "";
return value.join("\n");
}).join("\n");
setSection(context, "badges", content);
}
function generateDescriptionShortSection(context) {
if (context.pkg.description == null) return;
setSection(context, "description_short", `> ${context.pkg.description}`);
}
function generateDescriptionLongSection(context) {
setSection(context, "description_long", `## Description`);
}
function generateFeaturesSection(context) {
setSection(context, "features", `### Features
`);
}
function generateFaqSection(context) {
setSection(context, "faq", `## FAQ
`);
}
function generateNpxStep(binName, requiredPeerDependencies, context) {
const canUseShorthand = binName === context.pkg.name;
const simpleCommand = `\`\`\`
$ npx ${canUseShorthand ? `${context.pkg.name}` : `-p ${context.pkg.name} ${binName}`}
\`\`\``;
if (requiredPeerDependencies.length < 1) {
return simpleCommand;
} else if (canUseShorthand) {
return `First, add ${requiredPeerDependencies.length === 1 ? "the peer dependency" : "the peer dependencies"} ${listFormat(
requiredPeerDependencies,
"and",
(element) => `\`${element}\``
)} as${requiredPeerDependencies.length === 1 ? " a" : ""}${context.config.isDevelopmentPackage ? " development " : ""}${requiredPeerDependencies.length === 1 ? " dependency" : "dependencies"} to the package from which you're going to run \`${binName}\`. Alternatively, if you want to run it from _anywhere_, you can also install ${requiredPeerDependencies.length === 1 ? "it" : "them"} globally: \`npm i -g ${requiredPeerDependencies.join(" ")}\`. Now, you can simply run:
` + simpleCommand + `
You can also run \`${binName}\` along with its peer dependencies in one combined command:
\`\`\`
$ npx${requiredPeerDependencies.map((requiredPeerDependency) => ` -p ${requiredPeerDependency}`).join("")} -p ${context.pkg.name} ${binName}
\`\`\`
`;
} else {
return `\`\`\`
$ npx${requiredPeerDependencies.map((requiredPeerDependency) => ` -p ${requiredPeerDependency}`).join("")} -p ${context.pkg.name} ${binName}
\`\`\`
`;
}
}
function generateInstallSection(context) {
if (context.pkg.name == null) return;
const peerDependencies = context.pkg.peerDependencies == null ? [] : Object.keys(context.pkg.peerDependencies).map((peerDependency) => ({
peerDependency,
optional: Boolean(context.pkg.peerDependenciesMeta?.[peerDependency]?.optional)
}));
const requiredPeerDependencies = peerDependencies.filter(({ optional }) => !optional).map(({ peerDependency }) => peerDependency);
const optionalPeerDependencies = peerDependencies.filter(({ optional }) => optional).map(({ peerDependency }) => peerDependency);
const firstBinName = context.pkg.bin == null ? void 0 : Object.keys(context.pkg.bin)[0];
setSection(
context,
"install",
`## Install
### npm
\`\`\`
$ npm install ${context.pkg.name}${context.config.isDevelopmentPackage ? ` --save-dev` : ``}
\`\`\`
### Yarn
\`\`\`
$ yarn add ${context.pkg.name}${context.config.isDevelopmentPackage ? ` --dev` : ``}
\`\`\`
### pnpm
\`\`\`
$ pnpm add ${context.pkg.name}${context.config.isDevelopmentPackage ? ` --save-dev` : ``}
\`\`\`` + (firstBinName == null ? "" : `
### Run once with npx
` + generateNpxStep(firstBinName, requiredPeerDependencies, context)) + (peerDependencies.length < 1 ? "" : `
### Peer Dependencies
` + (requiredPeerDependencies.length < 1 ? "" : `\`${context.pkg.name}\` depends on ${listFormat(requiredPeerDependencies, "and", (element) => `\`${element}\``)}, so you need to manually install ${requiredPeerDependencies.length === 1 ? "this" : "these"}${context.config.isDevelopmentPackage ? ` as ${requiredPeerDependencies.length === 1 ? "a development dependency" : "development dependencies"}` : ``} as well.`) + (optionalPeerDependencies.length < 1 ? "" : (requiredPeerDependencies.length < 1 ? `You may` : `
You may also`) + ` need to install ${optionalPeerDependencies.length < 2 ? `\`${optionalPeerDependencies[0]}\`` : `${requiredPeerDependencies.length < 1 ? "" : "additional "}peer dependencies such as ${listFormat(
optionalPeerDependencies,
"or",
(element) => `\`${element}\``
)}`} depending on the features you are going to use. Refer to the documentation for the specific cases where ${optionalPeerDependencies.length < 2 ? "it" : "any of these"} may be relevant.`))
);
}
function generateUsageSection(context) {
setSection(context, "usage", `## Usage`);
}
function generateContributingSection(context) {
const contributingFilePath = path2.join(context.root, CONSTANT.codeOfConductFilename);
const nativeContributingFilePath = path2.native.normalize(contributingFilePath);
setSection(
context,
"contributing",
!context.fs.existsSync(nativeContributingFilePath) ? "" : `## Contributing
Do you want to contribute? Awesome! Please follow [these recommendations](./${CONSTANT.contributingFilename}).`
);
}
function generateContributorTable(contributors) {
let str = "\n|";
contributors.forEach((contributor) => {
const inner = contributor.imageUrl == null ? void 0 : formatImage({
alt: contributor.name,
url: contributor.imageUrl,
height: CONSTANT.contributorImageUrlHeight
});
const formattedImageWithUrl = inner == null ? "" : contributor.email != null ? formatUrl({ url: `mailto:${contributor.email}`, inner }) : contributor.url != null ? formatUrl({ url: contributor.url, inner }) : inner;
str += formattedImageWithUrl;
str += "|";
});
str += "\n|";
contributors.forEach(() => {
str += "-----------|";
});
str += "\n|";
contributors.forEach((contributor) => {
if (contributor.name != null) {
if (contributor.email != null) {
str += `[${contributor.name}](mailto:${contributor.email})`;
} else if (contributor.url != null) {
str += `[${contributor.name}](${contributor.url})`;
} else {
str += contributor.name;
}
}
if (contributor.twitter != null) {
str += `<br><strong>Twitter</strong>: [@${contributor.twitter}](https://twitter.com/${contributor.twitter})`;
}
if (contributor.github != null) {
str += `<br><strong>Github</strong>: [@${contributor.github}](https://github.com/${contributor.github})`;
}
if (contributor.role != null) {
str += `<br>_${contributor.role}_`;
}
str += "|";
});
return str;
}
function generateMaintainersSection(context) {
const contributors = getContributorsFromPackage(context.pkg);
setSection(context, "maintainers", contributors.length < 1 ? "" : `## Maintainers
` + generateContributorTable(contributors));
}
function guessPreferredFundingUrlForOtherDonations(context) {
if (context.config.donate.other.fundingUrl != null) {
return context.config.donate.other.fundingUrl;
}
if (context.pkg.funding != null) {
if (typeof context.pkg.funding === "string") {
return context.pkg.funding;
} else if (context.pkg.funding.url != null) {
return context.pkg.funding.url;
}
}
return void 0;
}
function generateBackersSection(context) {
let content = "";
if (context.config.donate.other.donors.length > 0) {
const preferredFundingUrl = guessPreferredFundingUrlForOtherDonations(context);
content += (preferredFundingUrl != null ? `[Become a sponsor/backer](${preferredFundingUrl}) and get your logo listed here.
` : "") + generateContributorTable(context.config.donate.other.donors) + "\n\n";
}
if (context.config.donate.openCollective.project != null) {
content += `### Open Collective
[Become a sponsor/backer](${CONSTANT.openCollectiveDonateUrl(context.config.donate.openCollective.project)}) and get your logo listed here.
#### Sponsors
` + formatUrl({
url: CONSTANT.openCollectiveContributorsUrl(context.config.donate.openCollective.project),
inner: formatImage({
url: CONSTANT.openCollectiveSponsorsBadgeUrl(context.config.donate.openCollective.project),
alt: "Sponsors on Open Collective",
width: 500
})
}) + `
#### Backers
` + formatUrl({
url: CONSTANT.openCollectiveContributorsUrl(context.config.donate.openCollective.project),
inner: formatImage({
url: CONSTANT.openCollectiveBackersBadgeUrl(context.config.donate.openCollective.project),
alt: "Backers on Open Collective"
})
}) + "\n\n";
}
if (context.config.donate.patreon.userId != null && context.config.donate.patreon.username != null) {
content += `### Patreon
` + formatUrl({
url: CONSTANT.patreonDonateUrl(context.config.donate.patreon.userId),
inner: formatImage({
url: CONSTANT.patreonBadgeUrl(context.config.donate.patreon.username),
alt: "Patrons on Patreon",
width: 200
})
}) + "\n\n";
}
setSection(context, "backers", context.config.donate.patreon.userId == null && context.config.donate.openCollective.project == null ? "" : `## Backers
` + content);
}
async function generateLicenseSection(context) {
const license = await findLicense(context);
const contributors = getContributorsFromPackage(context.pkg);
const licenseFilePath = path2.join(context.root, CONSTANT.licenseFilename);
const nativeLicenseFilePath = path2.native.normalize(licenseFilePath);
setSection(
context,
"license",
license == null || !context.fs.existsSync(nativeLicenseFilePath) ? "" : `## License
${license} \xA9 ${listFormat(
contributors.map((contributor) => formatContributor(contributor, "markdown")),
"and"
)}`
);
}
export {
generateReadme
};
//# sourceMappingURL=chunk-C3ACRQH5.js.map