Skip to content

Commit

Permalink
Merge pull request #413 from conwnet/master
Browse files Browse the repository at this point in the history
release 0.7.4
  • Loading branch information
conwnet authored May 29, 2022
2 parents d9d7c95 + a5748f8 commit 86f63da
Show file tree
Hide file tree
Showing 29 changed files with 432 additions and 134 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ For example, try it on the VS Code repo:

![VS Code - GitHub1s](https://raw.githubusercontent.com/conwnet/github1s/master/resources/images/vs-code-github1s.png)

You can also use [https://gitlab1s.com](https://gitlab1s.com) or [https://npmjs1s.com](https://npmjs1s.com) in the same way.

For browser extensions, see [Third-party Related Projects](https://github.com/conwnet/github1s#third-party-related-projects).

Or save the following code snippet as a bookmarklet, you can use it to quickly switch between github.com and github1s.com (GitHub markdown doesn't allow js links, so just copy it into a bookmark).
Expand Down Expand Up @@ -151,7 +153,7 @@ The continued development and maintenance of GitHub1s is made possible by these
- Github1s Extension ([Darkempire78/GitHub1s-Extension](https://github.com/Darkempire78/GitHub1s-Extension))
- [Github Web IDE](https://chrome.google.com/webstore/detail/adjiklnjodbiaioggfpbpkhbfcnhgkfe) ([zvizvi/Github-Web-IDE](https://github.com/zvizvi/Github-Web-IDE))
- [shortcut to github1s](https://chrome.google.com/webstore/detail/shortcut-to-github1s/gfcdbodapcbfckbfpmgeldfkkgjknceo) ([katsuhisa91/github1s-shortcut](https://github.com/katsuhisa91/github1s-shortcut))
- [Github1s Shortut - Open source](https://github.com/Fauzdar1/Github1s)
- [Github1s Shortut - Open source](https://github.com/Fauzdar1/Github1s)

### Firefox Extensions

Expand Down
2 changes: 1 addition & 1 deletion docs/guide.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# How it works

GitHub1s is based on [VS Code 1.60.0](https://github.com/microsoft/vscode/tree/1.60.0) now. VS Code can be built for a browser version officially. I also used the code and got inspired by [Code Server](https://github.com/cdr/code-server).
GitHub1s is based on [VS Code 1.66.2](https://github.com/microsoft/vscode/tree/1.66.2) now. VS Code can be built for a browser version officially. I also used the code and got inspired by [Code Server](https://github.com/cdr/code-server).

Thanks to the very powerful and flexible extensibility of VS Code, we can easily implement a VS Code extension that provides the custom File IO ability using [FileSystemProvider API](https://code.visualstudio.com/api/references/vscode-api#FileSystemProvider). There is an official demo named [vscode-web-playground](https://github.com/microsoft/vscode-web-playground) which shows how it is used.

Expand Down
30 changes: 19 additions & 11 deletions extensions/github1s/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
"activationEvents": [
"onFileSystem:github1s",
"onFileSystem:gitlab1s",
"onFileSystem:bitbucket1s"
"onFileSystem:bitbucket1s",
"onFileSystem:npmjs1s"
],
"browser": "./dist/extension",
"engines": {
Expand Down Expand Up @@ -197,7 +198,7 @@
"dark": "assets/icons/dark/open-left-file.svg",
"light": "assets/icons/light/open-left-file.svg"
},
"enablement": "isInDiffEditor && resourceScheme =~ /^github1s/ && resource =~ /^(?![^?]*\\?[^#]*(%26|\\b)base(=|%3D|%3d)github1s-empty-file)/"
"enablement": "isInDiffEditor && resourceScheme =~ /^(github1s|gitlab1s|bitbucket1s)/ && resource =~ /^(?![^?]*\\?[^#]*(%26|\\b)base(=|%3D|%3d)github1s-empty-file)/"
},
{
"command": "github1s.commands.diffViewOpenRightFile",
Expand All @@ -207,14 +208,14 @@
"dark": "assets/icons/dark/open-right-file.svg",
"light": "assets/icons/light/open-right-file.svg"
},
"enablement": "isInDiffEditor && resourceScheme =~ /^github1s/ && resource =~ /^(?![^?]*\\?[^#]*(%26|\\b)head(=|%3D|%3d)github1s-empty-file)/"
"enablement": "isInDiffEditor && resourceScheme =~ /^(github1s|gitlab1s|bitbucket1s)/ && resource =~ /^(?![^?]*\\?[^#]*(%26|\\b)head(=|%3D|%3d)github1s-empty-file)/"
},
{
"command": "github1s.commands.openFilePreviousRevision",
"title": "Open Previous Revision",
"category": "GitHub1s",
"icon": "$(arrow-left)",
"enablement": "resourceScheme =~ /^github1s$/ && resource =~ /^(?![^?]*\\?[^#]*(%26|\\b)base(=|%3D|%3d)github1s-empty-file)/"
"enablement": "resourceScheme =~ /^(github1s|gitlab1s|bitbucket1s)$/ && resource =~ /^(?![^?]*\\?[^#]*(%26|\\b)base(=|%3D|%3d)github1s-empty-file)/"
},
{
"command": "github1s.commands.openFileNextRevision",
Expand Down Expand Up @@ -270,12 +271,19 @@
"icon": "$(globe)",
"enablement": "github1s:adapters:default:platformName == 'Bitbucket'"
},
{
"command": "github1s.commands.openOnNpm",
"title": "Open on npm",
"category": "GitHub1s",
"icon": "$(globe)",
"enablement": "github1s:adapters:default:platformName == 'npm'"
},
{
"command": "github1s.commands.openOnOfficialPage",
"title": "Open on Official Page",
"category": "GitHub1s",
"icon": "$(globe)",
"enablement": "github1s:adapters:default:platformName != 'GitHub' && github1s:adapters:default:platformName != 'GitLab' && github1s:adapters:default:platformName != 'Bitbucket'"
"enablement": "github1s:adapters:default:platformName != 'GitHub' && github1s:adapters:default:platformName != 'GitLab' && github1s:adapters:default:platformName != 'Bitbucket' && github1s:adapters:default:platformName != 'npm'"
}
],
"colors": [
Expand Down Expand Up @@ -492,7 +500,7 @@
},
{
"command": "github1s.commands.openCodeReviewOnOfficialPage",
"when": "viewItem == 'github1s:viewItems:codeReviewListItem' && github1s:adapters:default:platformName != 'GitHub' && github1s:adapters:default:platformName != 'GitLab' && github1s:adapters:default:platformName != 'Bitbucket'",
"when": "viewItem == 'github1s:viewItems:codeReviewListItem' && github1s:adapters:default:platformName != 'GitHub' && github1s:adapters:default:platformName != 'GitLab' && github1s:adapters:default:platformName != 'Bitbucket' && github1s:adapters:default:platformName != 'npm'",
"group": "inline@2"
},
{
Expand All @@ -517,7 +525,7 @@
},
{
"command": "github1s.commands.openCommitOnOfficialPage",
"when": "viewItem == 'github1s:viewItems:commitListItem' && github1s:adapters:default:platformName != 'GitHub' && github1s:adapters:default:platformName != 'GitLab' && github1s:adapters:default:platformName != 'Bitbucket'",
"when": "viewItem == 'github1s:viewItems:commitListItem' && github1s:adapters:default:platformName != 'GitHub' && github1s:adapters:default:platformName != 'GitLab' && github1s:adapters:default:platformName != 'Bitbucket' && github1s:adapters:default:platformName != 'npm'",
"group": "inline@2"
}
],
Expand All @@ -539,22 +547,22 @@
},
{
"command": "github1s.commands.openFilePreviousRevision",
"when": "resourceScheme =~ /^github1s/",
"when": "resourceScheme =~ /^(github1s|gitlab1s|bitbucket1s)/",
"group": "navigation@98"
},
{
"command": "github1s.commands.openFileNextRevision",
"when": "resourceScheme =~ /^github1s/",
"when": "resourceScheme =~ /^(github1s|gitlab1s|bitbucket1s)/",
"group": "navigation@99"
},
{
"command": "github1s.commands.openEditorGutterBlame",
"when": "!isInDiffEditor && !github1s:blames:gutterBlameOpen",
"when": "!isInDiffEditor && github1s:features:gutterBlame:enabled && !github1s:features:gutterBlame:open",
"group": "navigation@4"
},
{
"command": "github1s.commands.closeEditorGutterBlame",
"when": "!isInDiffEditor && github1s:blames:gutterBlameOpen",
"when": "!isInDiffEditor && github1s:features:gutterBlame:enabled && github1s:features:gutterBlame:open",
"group": "navigation@4"
}
]
Expand Down
2 changes: 2 additions & 0 deletions extensions/github1s/src/adapters/bitbucket1s/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,12 @@ export class BitbucketAdapter implements Adapter {
activateAsDefault() {
setVSCodeContext('github1s:views:commitList:visible', true);
setVSCodeContext('github1s:views:fileHistory:visible', true);
setVSCodeContext('github1s:features:gutterBlame:enabled', true);
}

deactivateAsDefault() {
setVSCodeContext('github1s:views:commitList:visible', false);
setVSCodeContext('github1s:views:fileHistory:visible', false);
setVSCodeContext('github1s:features:gutterBlame:enabled', false);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export class BitbucketRouterParser extends adapterTypes.RouterParser {
return `/${repo}/pull-requests`;
}

buildCodeReviewPath(repo: string, codeReviewId: string): adapterTypes.Promisable<string> {
buildCodeReviewPath(repo: string, codeReviewId: string): string {
return `/${repo}/pull-requests/${codeReviewId}`;
}

Expand Down
125 changes: 67 additions & 58 deletions extensions/github1s/src/adapters/github1s/data-source.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ import {
} from '../types';
import { toUint8Array } from 'js-base64';
import { matchSorter } from 'match-sorter';
import { reuseable } from '@/helpers/func';
import { FILE_BLAME_QUERY } from './graphql';
import { GitHubFetcher } from './fetcher';
import { SourcegraphDataSource } from '../sourcegraph/data-source';
Expand Down Expand Up @@ -80,9 +79,10 @@ const trySourcegraphApiFirst = (_target: any, propertyKey: string, descriptor: P

export class GitHub1sDataSource extends DataSource {
private static instance: GitHub1sDataSource | null = null;
private cachedBranches: Branch[] | null = null;
private cachedTags: Branch[] | null = null;
private pathRefs: string[] = [];
private branchesPromiseMap: Map<string, Promise<Branch[]>> = new Map();
private tagsPromiseMap: Map<string, Promise<Tag[]>> = new Map();
private refPathPromiseMap: Map<string, Promise<{ ref: string; path: string }>> = new Map();
private matchedRefsMap = new Map<string, string[]>();

public static getInstance(): GitHub1sDataSource {
if (GitHub1sDataSource.instance) {
Expand Down Expand Up @@ -121,83 +121,92 @@ export class GitHub1sDataSource extends DataSource {
return { content: toUint8Array((data as any).content) };
}

getMatchingRefs = reuseable(
async (repoFullName: string, ref: 'heads' | 'tags'): Promise<Branch | Tag[]> => {
const fetcher = GitHubFetcher.getInstance();
const { owner, repo } = parseRepoFullName(repoFullName);
const requestParams = { owner, repo, ref };
const { data } = await fetcher.request('GET /repos/{owner}/{repo}/git/matching-refs/{ref}', requestParams);
return data.map((item) => ({
name: item.ref.slice(ref === 'heads' ? 11 : 10),
commitSha: item.object.sha,
description: `${ref === 'heads' ? 'Branch' : 'Tag'} at ${item.object.sha.slice(0, 8)}`,
}));
}
);
async getMatchingRefs(repoFullName: string, ref: 'heads' | 'tags'): Promise<Branch[] | Tag[]> {
const fetcher = GitHubFetcher.getInstance();
const { owner, repo } = parseRepoFullName(repoFullName);
const requestParams = { owner, repo, ref };
const { data } = await fetcher.request('GET /repos/{owner}/{repo}/git/matching-refs/{ref}', requestParams);
return data.map((item) => ({
name: item.ref.slice(ref === 'heads' ? 11 : 10),
commitSha: item.object.sha,
description: `${ref === 'heads' ? 'Branch' : 'Tag'} at ${item.object.sha.slice(0, 8)}`,
}));
}

@trySourcegraphApiFirst
async extractRefPath(repoFullName: string, refAndPath: string): Promise<{ ref: string; path: string }> {
if (!refAndPath || refAndPath.match(/^HEAD(\/.*)?$/i)) {
return { ref: 'HEAD', path: refAndPath.slice(5) };
if (!this.matchedRefsMap.has(repoFullName)) {
this.matchedRefsMap.set(repoFullName, []);
}
const pathRef = this.pathRefs.find((ref) => refAndPath.startsWith(`${ref}/`) || refAndPath === ref);
if (pathRef) {
return { ref: pathRef, path: refAndPath.slice(pathRef.length + 1) };
const matchPathRef = (ref) => refAndPath.startsWith(`${ref}/`) || refAndPath === ref;
const matchedRef = this.matchedRefsMap.get(repoFullName)?.find(matchPathRef);
if (matchedRef) {
return { ref: matchedRef, path: refAndPath.slice(matchedRef.length + 1) };
}
const fetcher = GitHubFetcher.getInstance();
const { owner, repo } = parseRepoFullName(repoFullName);
const requestParams = { owner, repo, refAndPath };
const response = await fetcher.request(`GET /repos/{owner}/{repo}/git/extract-ref/{refAndPath}`, requestParams);
response.data?.ref && this.pathRefs.push(response.data.ref);
return response.data || { ref: 'HEAD', path: '' };
const mapKey = `${repoFullName} ${refAndPath}`;
if (!this.refPathPromiseMap.has(mapKey)) {
const refPathPromise = new Promise<{ ref: string; path: string }>(async (resolve, reject) => {
if (!refAndPath || refAndPath.match(/^HEAD(\/.*)?$/i)) {
return resolve({ ref: 'HEAD', path: refAndPath.slice(5) });
}

const fetcher = GitHubFetcher.getInstance();
const { owner, repo } = parseRepoFullName(repoFullName);
const requestParams = { owner, repo, refAndPath };
const requestUrl = `GET /repos/{owner}/{repo}/git/extract-ref/{refAndPath}`;
const response = await fetcher.request(requestUrl, requestParams).catch(reject);
response?.data?.ref && this.matchedRefsMap.get(repoFullName)?.push(response.data.ref);
return resolve(response?.data || { ref: 'HEAD', path: '' });
});
this.refPathPromiseMap.set(mapKey, refPathPromise);
}
return this.refPathPromiseMap.get(mapKey)!;
}

@trySourcegraphApiFirst
async provideBranches(repoFullName: string, options?: CommonQueryOptions): Promise<Branch[]> {
if (!this.cachedBranches) {
this.cachedBranches = (await this.getMatchingRefs(repoFullName, 'heads')) as Branch[];
if (!this.branchesPromiseMap.has(repoFullName)) {
this.branchesPromiseMap.set(repoFullName, this.getMatchingRefs(repoFullName, 'heads'));
}
const matchedBranches = options?.query
? matchSorter(this.cachedBranches, options.query, { keys: ['name'] })
: this.cachedBranches;
if (options?.pageSize) {
const page = options.page || 1;
const pageSize = options.pageSize;
return matchedBranches.slice(pageSize * (page - 1), pageSize * page);
}
return matchedBranches;
return this.branchesPromiseMap.get(repoFullName)!.then((branches) => {
const matchOptions = { keys: ['name'] };
const matchedBranches = options?.query ? matchSorter(branches, options.query, matchOptions) : branches;
if (options?.pageSize) {
const page = options.page || 1;
const pageSize = options.pageSize;
return matchedBranches.slice(pageSize * (page - 1), pageSize * page);
}
return matchedBranches;
});
}

@trySourcegraphApiFirst
async provideBranch(repoFullName: string, branchName: string): Promise<Branch | null> {
if (!this.cachedBranches) {
this.cachedBranches = (await this.getMatchingRefs(repoFullName, 'heads')) as Branch[];
}
return this.cachedBranches.find((item) => item.name === branchName) || null;
const branches = await this.provideBranches(repoFullName);
return branches.find((item) => item.name === branchName) || null;
}

@trySourcegraphApiFirst
async provideTags(repoFullName: string, options?: CommonQueryOptions): Promise<Tag[]> {
if (!this.cachedTags) {
this.cachedTags = (await this.getMatchingRefs(repoFullName, 'tags')) as Tag[];
}
const matchedTags = options?.query
? matchSorter(this.cachedTags, options.query, { keys: ['name'] })
: this.cachedTags;
if (options?.pageSize) {
const page = options.page || 1;
const pageSize = options.pageSize;
return matchedTags.slice(pageSize * (page - 1), pageSize * page);
if (!this.tagsPromiseMap.has(repoFullName)) {
this.tagsPromiseMap.set(repoFullName, this.getMatchingRefs(repoFullName, 'tags'));
}
return matchedTags;
return this.tagsPromiseMap.get(repoFullName)!.then((tags) => {
const matchOptions = { keys: ['name'] };
const matchedTags = options?.query ? matchSorter(tags, options.query, matchOptions) : tags;
if (options?.pageSize) {
const page = options.page || 1;
const pageSize = options.pageSize;
return matchedTags.slice(pageSize * (page - 1), pageSize * page);
}
return matchedTags;
});
}

@trySourcegraphApiFirst
async provideTag(repoFullName: string, tagName: string): Promise<Tag | null> {
if (!this.cachedTags) {
this.cachedTags = (await this.getMatchingRefs(repoFullName, 'heads')) as Tag[];
}
return this.cachedTags.find((item) => item.name === tagName) || null;
const tags = await this.provideTags(repoFullName);
return tags.find((item) => item.name === tagName) || null;
}

async provideTextSearchResults(
Expand Down
2 changes: 2 additions & 0 deletions extensions/github1s/src/adapters/github1s/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export class GitHub1sAdapter implements Adapter {
setVSCodeContext('github1s:views:codeReviewList:visible', true);
setVSCodeContext('github1s:views:commitList:visible', true);
setVSCodeContext('github1s:views:fileHistory:visible', true);
setVSCodeContext('github1s:features:gutterBlame:enabled', true);

vscode.window.registerWebviewViewProvider(
GitHub1sSettingsViewProvider.viewType,
Expand All @@ -45,5 +46,6 @@ export class GitHub1sAdapter implements Adapter {
setVSCodeContext('github1s:views:codeReviewList:visible', false);
setVSCodeContext('github1s:views:commitList:visible', false);
setVSCodeContext('github1s:views:fileHistory:visible', false);
setVSCodeContext('github1s:features:gutterBlame:enabled', false);
}
}
2 changes: 1 addition & 1 deletion extensions/github1s/src/adapters/github1s/router-parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export class GitHub1sRouterParser extends adapterTypes.RouterParser {
return `/${repo}/pulls`;
}

buildCodeReviewPath(repo: string, codeReviewId: string): adapterTypes.Promisable<string> {
buildCodeReviewPath(repo: string, codeReviewId: string): string {
return `/${repo}/pull/${codeReviewId}`;
}

Expand Down
2 changes: 2 additions & 0 deletions extensions/github1s/src/adapters/gitlab1s/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,12 @@ export class GitLab1sAdapter implements Adapter {
activateAsDefault() {
setVSCodeContext('github1s:views:commitList:visible', true);
setVSCodeContext('github1s:views:fileHistory:visible', true);
setVSCodeContext('github1s:features:gutterBlame:enabled', true);
}

deactivateAsDefault() {
setVSCodeContext('github1s:views:commitList:visible', false);
setVSCodeContext('github1s:views:fileHistory:visible', false);
setVSCodeContext('github1s:features:gutterBlame:enabled', false);
}
}
2 changes: 1 addition & 1 deletion extensions/github1s/src/adapters/gitlab1s/router-parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export class GitLab1sRouterParser extends adapterTypes.RouterParser {
return `/${repo}/-/merge_requests`;
}

buildCodeReviewPath(repo: string, codeReviewId: string): adapterTypes.Promisable<string> {
buildCodeReviewPath(repo: string, codeReviewId: string): string {
return `/${repo}/-/merge_requests/${codeReviewId}`;
}

Expand Down
2 changes: 2 additions & 0 deletions extensions/github1s/src/adapters/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@ import adapterManager from './manager';
import { GitHub1sAdapter } from './github1s';
import { GitLab1sAdapter } from './gitlab1s';
import { BitbucketAdapter } from './bitbucket1s';
import { Npmjs1sAdapter } from './npmjs1s';

export const registerAdapters = async (): Promise<void> => {
await Promise.all([
adapterManager.registerAdapter(new GitHub1sAdapter()),
adapterManager.registerAdapter(new GitLab1sAdapter()),
adapterManager.registerAdapter(new BitbucketAdapter()),
adapterManager.registerAdapter(new Npmjs1sAdapter()),
]);
};

Expand Down
Loading

1 comment on commit 86f63da

@vercel
Copy link

@vercel vercel bot commented on 86f63da May 29, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.