Skip to content

Commit

Permalink
Refactor GitHubInfo.tsx into a reusable module
Browse files Browse the repository at this point in the history
  • Loading branch information
humphd committed Apr 12, 2022
1 parent 8d3a8f7 commit d56306a
Show file tree
Hide file tree
Showing 15 changed files with 342 additions and 16 deletions.
22 changes: 6 additions & 16 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions pnpm-workspace.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ packages:
- 'src/api/*'
# satellite
- 'src/satellite'
# github-url-parser
- 'src/github-url-parser'
# autodeployment
- 'tools/*'
# Prisma
Expand Down
10 changes: 10 additions & 0 deletions src/github-url-parser/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
module.exports = {
extends: ['@senecacdot/eslint-config-telescope'],

env: {
node: true,
browser: true,
commonjs: true,
jest: true,
},
};
8 changes: 8 additions & 0 deletions src/github-url-parser/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
const baseConfig = require('../../jest.config.base');

module.exports = {
...baseConfig,
rootDir: '../..',
testMatch: ['<rootDir>/src/github-url-parser/test/**/*.test.js'],
collectCoverageFrom: ['<rootDir>/src/github-url-parser/src/**/*.js'],
};
21 changes: 21 additions & 0 deletions src/github-url-parser/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"name": "@senecacdot/github-url-parser",
"version": "0.1.0",
"description": "A library for parsing GitHub URLs from HTM text",
"main": "src/index.js",
"scripts": {
"test": "jest -c jest.config.js",
"coverage": "jest -c jest.config.js --collect-coverage",
"eslint": "eslint --config .eslintrc.js \"./**/*.js\"",
"eslint-fix": "eslint --config .eslintrc.js \"./**/*.js\" --fix",
"lint": "pnpm eslint"
},
"repository": "Seneca-CDOT/telescope",
"license": "BSD-2-Clause",
"bugs": {
"url": "https://github.com/Seneca-CDOT/telescope/issues"
},
"devDependencies": {
"jsdom": "18.1.1"
}
}
65 changes: 65 additions & 0 deletions src/github-url-parser/src/extract-github-info.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
const parseGitHubUrl = require('./parse-github-url');
const reservedNames = require('./reserved-names');

module.exports = (gitHubUrls) => {
const issues = new Set();
const pullRequests = new Set();
const repos = new Set();
const commits = new Set();
const users = new Set();

gitHubUrls
.map((url) => parseGitHubUrl(url))
.filter(Boolean)
.filter((url) => !reservedNames.includes(url.pathname.split('/').slice(1, 2)[0]))
.forEach((url) => {
const { pathname } = url;

// Match urls that start with /<user> and optionally end with /<repo> or /<repo>/<anything-in-between>/<type>/<id>
// <id> can be number, or a mixed of 40 alphanumeric (commit id)
// Ex: /Seneca-CDOT/telescope/pull/2367 ✅
// Ex: /Seneca-CDOT/telescope ✅
// Ex: /Seneca-CDOT/telescope/pull/2367/commits/d3fagd3fagd3fagd3fagd3fagd3fag4d41265748 ✅
// Ex: /Seneca-CDOT/telescope/issues ✅
const matches =
/^\/(?<user>[^/]+)(\/(?<repo>[^/]+)((\/(.*))?(\/(?<type>[^/]+)?\/(?<id>(\d+|\w{40}))\/?$))?)?/gi.exec(
pathname
);

if (!matches?.groups) {
return;
}

const { type, user, repo } = matches.groups;

if (repo) {
const repoUrl = `${user}/${repo}`;
repos.add(repoUrl);
}

users.add(user);

switch (type?.toLowerCase()) {
case 'pull':
pullRequests.add(pathname);
break;
case 'issues':
issues.add(pathname);
break;
case 'commit':
case 'commits':
commits.add(pathname);
break;
default:
break;
}
});

return {
repos: Array.from(repos),
issues: Array.from(issues),
pullRequests: Array.from(pullRequests),
commits: Array.from(commits),
users: Array.from(users),
};
};
11 changes: 11 additions & 0 deletions src/github-url-parser/src/html-to-urls.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module.exports = (htmlString, parser) => {
const doc = parser.parseFromString(htmlString, 'text/html');

const allGithubLinks = Array.from(
// all links that have href that starts with 'https://github.com'
doc.querySelectorAll("a[href^='https://github.com']"),
(element) => element.href
);

return [...new Set(allGithubLinks)];
};
16 changes: 16 additions & 0 deletions src/github-url-parser/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
const extractGitHubInfo = require('./extract-github-info');
const htmlToUrls = require('./html-to-urls');

/**
* Extract all GitHub URL info from an HTML string
* @param {string} htmlString - a string of HTML
* @param {{ DOMParser }} parser - an HTML DOM Parser
*/
module.exports = (htmlString, { parser }) => {
if (!parser && !('DOMParser' in globalThis)) {
throw new Error('Missing parser property and environment does not support DOMParser');
}

const urls = htmlToUrls(htmlString, parser || new globalThis.DOMParser());
return extractGitHubInfo(urls);
};
11 changes: 11 additions & 0 deletions src/github-url-parser/src/parse-github-url.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module.exports = (url) => {
try {
const ghUrl = new URL(url);
if (ghUrl.hostname !== 'github.com') {
return null;
}
return ghUrl;
} catch (err) {
return null;
}
};
27 changes: 27 additions & 0 deletions src/github-url-parser/src/reserved-names.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
module.exports = [
'team',
'enterprise',
'explore',
'marketplace',
'pricing',
'topics',
'collections',
'trending',
'readme',
'events',
'sponsors',
'mobile',
'features',
'customer-stories',
'pulls',
'issues',
'notifications',
'new',
'organizations',
'users',
'settings',
'discussions',
'account',
'about',
'security',
];
Loading

0 comments on commit d56306a

Please sign in to comment.