Skip to content

Commit fb5f10a

Browse files
fix(repository-shorthand): support repo provider prefix (#1472)
<!-- πŸ‘‹ Hi, thanks for sending a PR to eslint-plugin-package-json! πŸ—‚ Please fill out all fields below and make sure each item is true and [x] checked. Otherwise we may not be able to review your PR. --> ## PR Checklist - [x] Addresses an existing open issue: fixes #1431 - [x] That issue was marked as [`status: accepting prs`](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/issues?q=is%3Aopen+is%3Aissue+label%3A%22status%3A+accepting+prs%22) - [x] Steps in [CONTRIBUTING.md](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/blob/main/.github/CONTRIBUTING.md) were taken ## Overview This change updates all fixers to support different repo providers, and the providers prefix in general. Now if you have repo defined in object syntax with either bitbucket, gitlab, github, or gist urls, the fixer will construct a shorthand string using the corresponding provider prefix. On the other side, if you have repo defined as a shorthand and have configured to prefer object, it'll use the correct url based on the provider prefix, if specified (assume github if not). --------- Co-authored-by: Josh Goldberg ✨ <git@joshuakgoldberg.com>
1 parent eeff2b8 commit fb5f10a

File tree

2 files changed

+218
-45
lines changed

2 files changed

+218
-45
lines changed

β€Žsrc/rules/repository-shorthand.tsβ€Ž

Lines changed: 66 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,51 @@ import { createRule } from "../createRule.ts";
44
import { findPropertyWithKeyValue } from "../utils/findPropertyWithKeyValue.ts";
55
import { isJSONStringLiteral } from "../utils/predicates.ts";
66

7-
const githubUrlRegex =
8-
/^(?:git\+)?(?:ssh:\/\/git@|http?s:\/\/)?(?:www\.)?github\.com\//;
9-
10-
const isGitHubUrl = (url: string) => githubUrlRegex.test(url);
7+
const providerRegexes = {
8+
bitbucket:
9+
/^(?:git\+)?(?:ssh:\/\/git@|http?s:\/\/)?(?:www\.)?bitbucket\.org\//,
10+
gist: /^(?:git\+)?(?:ssh:\/\/git@|http?s:\/\/)?(?:www\.)?gist\.github\.com\//,
11+
github: /^(?:git\+)?(?:ssh:\/\/git@|http?s:\/\/)?(?:www\.)?github\.com\//,
12+
gitlab: /^(?:git\+)?(?:ssh:\/\/git@|http?s:\/\/)?(?:www\.)?gitlab\.com\//,
13+
} satisfies Record<string, RegExp>;
14+
type Provider = keyof typeof providerRegexes;
15+
16+
const providerUrls = {
17+
bitbucket: "https://bitbucket.org/",
18+
gist: "https://gist.github.com/",
19+
github: "https://github.com/",
20+
gitlab: "https://gitlab.com/",
21+
} satisfies Record<Provider, string>;
22+
23+
const providers = Object.keys(providerRegexes) as Provider[];
24+
25+
const isProvider = (value: string): value is Provider =>
26+
value in providerRegexes;
27+
28+
const cleanUrl = (url: string, provider: Provider): string =>
29+
url.replace(providerRegexes[provider], "").replace(/\.git$/, "");
30+
31+
const getProviderFromUrl = (url: string) => {
32+
return providers.find((provider) => providerRegexes[provider].test(url));
33+
};
34+
35+
const createShorthand = (url: string, provider: Provider): string => {
36+
const repo = cleanUrl(url, provider);
37+
return `${provider}:${repo}`;
38+
};
39+
40+
const createUrl = (shorthand: string): string => {
41+
// Use the appropriate provider url if one is specified
42+
if (shorthand.includes(":")) {
43+
const [provider, repo] = shorthand.split(":");
44+
if (isProvider(provider)) {
45+
return `${providerUrls[provider]}${repo}`;
46+
}
47+
}
1148

12-
const cleanGitHubUrl = (url: string) =>
13-
url.replace(githubUrlRegex, "").replace(/\.git$/, "");
49+
// If the provider is missing or unrecognized, default to GitHub
50+
return `${providerUrls.github}${shorthand}`;
51+
};
1452

1553
export const rule = createRule({
1654
create(context) {
@@ -33,7 +71,7 @@ export const rule = createRule({
3371
JSON.stringify(
3472
{
3573
type: "git",
36-
url: `https://github.com/${node.value.value}`,
74+
url: createUrl(node.value.value),
3775
},
3876
null,
3977
2,
@@ -49,12 +87,15 @@ export const rule = createRule({
4987
function validateRepositoryForShorthand(node: JsonAST.JSONProperty) {
5088
if (isJSONStringLiteral(node.value)) {
5189
const { value } = node.value;
52-
if (typeof value === "string" && isGitHubUrl(value)) {
90+
const provider = getProviderFromUrl(value);
91+
if (provider) {
5392
context.report({
5493
fix(fixer) {
5594
return fixer.replaceText(
5695
node.value,
57-
JSON.stringify(cleanGitHubUrl(value)),
96+
JSON.stringify(
97+
createShorthand(value, provider),
98+
),
5899
);
59100
},
60101
messageId: "preferShorthand",
@@ -84,26 +125,28 @@ export const rule = createRule({
84125
}
85126

86127
const urlProperty = findPropertyWithKeyValue(properties, "url");
128+
87129
if (
88130
urlProperty?.value.type !== "JSONLiteral" ||
89-
typeof urlProperty.value.value !== "string" ||
90-
!isGitHubUrl(urlProperty.value.value)
131+
typeof urlProperty.value.value !== "string"
91132
) {
92133
return;
93134
}
94135

95136
const url = urlProperty.value.value;
96-
97-
context.report({
98-
fix(fixer) {
99-
return fixer.replaceText(
100-
node.value,
101-
JSON.stringify(cleanGitHubUrl(url)),
102-
);
103-
},
104-
messageId: "preferShorthand",
105-
node: node.value,
106-
});
137+
const provider = getProviderFromUrl(url);
138+
if (provider) {
139+
context.report({
140+
fix(fixer) {
141+
return fixer.replaceText(
142+
node.value,
143+
JSON.stringify(createShorthand(url, provider)),
144+
);
145+
},
146+
messageId: "preferShorthand",
147+
node: node.value,
148+
});
149+
}
107150
}
108151

109152
return {
@@ -136,7 +179,7 @@ export const rule = createRule({
136179
messages: {
137180
preferObject: "Prefer an object locator for a repository.",
138181
preferShorthand:
139-
"Prefer a shorthand locator for a GitHub repository.",
182+
"Prefer a shorthand locator for a supported repository provider.",
140183
},
141184
schema: [
142185
{

0 commit comments

Comments
Β (0)