summaryrefslogtreecommitdiff
path: root/source/github-helpers/github-url.ts
diff options
context:
space:
mode:
authorGravatar Fregante <opensource@bfred.it> 2020-05-28 19:00:10 +0200
committerGravatar GitHub <noreply@github.com> 2020-05-28 19:00:10 +0200
commit7589633720493550e359468ffdb4294858b74646 (patch)
tree9574de3d8a560ff0726fdb1070d561bc7e5d867a /source/github-helpers/github-url.ts
parent2235c23dedef9f5ef91cc07c53175e28e5f64b6d (diff)
downloadrefined-github-7589633720493550e359468ffdb4294858b74646.tar.gz
refined-github-7589633720493550e359468ffdb4294858b74646.tar.zst
refined-github-7589633720493550e359468ffdb4294858b74646.zip
Meta: improve GitHub URL parser (#3138)
Diffstat (limited to 'source/github-helpers/github-url.ts')
-rw-r--r--source/github-helpers/github-url.ts71
1 files changed, 71 insertions, 0 deletions
diff --git a/source/github-helpers/github-url.ts b/source/github-helpers/github-url.ts
new file mode 100644
index 00000000..395723d4
--- /dev/null
+++ b/source/github-helpers/github-url.ts
@@ -0,0 +1,71 @@
+import {getCurrentBranch} from '.';
+
+function disambiguateReference(ambiguousReference: string[]): {branch: string; filePath: string} {
+ const branch = ambiguousReference[0];
+ const filePath = ambiguousReference.slice(1).join('/');
+
+ const currentBranch = getCurrentBranch();
+ const currentBranchSections = currentBranch.split('/');
+ if (
+ ambiguousReference.length === 1 || // Ref has no slashes
+ currentBranchSections.length === 1 || // Current branch has no slashes
+ /\^|~|@{/.test(branch) // Ref is an extended revision #3137 https://git-scm.com/docs/git-rev-parse#_specifying_revisions
+ ) {
+ // Then the reference is not ambiguous
+ return {branch, filePath};
+ }
+
+ for (const [i, section] of currentBranchSections.entries()) {
+ if (ambiguousReference[i] !== section) {
+ console.warn(`The supplied path (${ambiguousReference.join('/')}) is ambiguous (current reference is \`${currentBranch}\`)`);
+ return {branch, filePath};
+ }
+ }
+
+ return {
+ branch: currentBranch,
+ filePath: ambiguousReference.slice(currentBranchSections.length).join('/')
+ };
+}
+
+export default class GitHubURL extends URL {
+ // @ts-ignore https://github.com/microsoft/TypeScript/issues/26792
+ user: string;
+ // @ts-ignore
+ repository: string;
+ // @ts-ignore
+ route: string;
+ // @ts-ignore
+ branch: string;
+ // @ts-ignore
+ filePath: string;
+ constructor(url: string) {
+ super(url);
+ this.pathname = super.pathname;
+ }
+
+ assign(replacements: Partial<GitHubURL>): this {
+ Object.assign(this, replacements);
+ return this;
+ }
+
+ get pathname() {
+ return `/${this.user}/${this.repository}/${this.route}/${this.branch}/${this.filePath}`.replace(/\/+$/, '');
+ }
+
+ set pathname(pathname) {
+ const [user, repository, route, ...ambiguousReference] = pathname.replace(/^\/|\/$/g, '').split('/');
+ const {branch, filePath} = disambiguateReference(ambiguousReference);
+ this.assign({user, repository, route, branch, filePath});
+ }
+
+ get href() {
+ // Update the actual underlying URL
+ super.pathname = this.pathname;
+ return super.href;
+ }
+
+ toString() {
+ return this.href;
+ }
+}