├── .gitignore ├── LICENSE.md ├── README.md ├── chrome ├── background.js ├── content.js ├── logo.png └── manifest.json └── mozilla ├── background.js ├── content.js ├── logo.png └── manifest.json /.gitignore: -------------------------------------------------------------------------------- 1 | ### 2 | ### Golang 3 | ### 4 | 5 | .env 6 | 7 | # Binaries for programs and plugins 8 | *.exe 9 | *.exe~ 10 | *.dll 11 | *.so 12 | *.dylib 13 | 14 | bin/ 15 | !bin/.gitkeep 16 | 17 | # Test binary, built with `go test -c` 18 | *.test 19 | 20 | # Output of the go coverage tool, specifically when used with LiteIDE 21 | *.out 22 | 23 | # Dependency directories (remove the comment below to include it) 24 | # vendor/ 25 | *.a[56789o] 26 | .nfs.* 27 | 28 | # User-specific stuff 29 | /.idea 30 | 31 | # File-based project format 32 | *.iws 33 | 34 | ### 35 | ### MAC OS 36 | ### 37 | 38 | # General 39 | .DS_Store 40 | .AppleDouble 41 | .LSOverride 42 | 43 | # Icon must end with two \r 44 | Icon 45 | 46 | 47 | # Thumbnails 48 | ._* 49 | 50 | # Files that might appear in the root of a volume 51 | .DocumentRevisions-V100 52 | .fseventsd 53 | .Spotlight-V100 54 | .TemporaryItems 55 | .Trashes 56 | .VolumeIcon.icns 57 | .com.apple.timemachine.donotpresent 58 | 59 | # Directories potentially created on remote AFP share 60 | .AppleDB 61 | .AppleDesktop 62 | Network Trash Folder 63 | Temporary Items 64 | .apdisk 65 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 indexStorm 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GitHub Recommender Extension 2 | 3 | 5 | 6 | This is an official repo for GitHub Recommender extension 7 | 8 | Link to extension: Chrome and Firefox 9 | 10 |

Main repository with API code

11 | 12 | indexStorm/git-rec-back 13 | 14 |

Screenshots

15 |

16 | Screenshot 2022-08-03 at 14 52 50 17 | Screenshot 2022-08-03 at 14 43 22 18 |

19 | 20 |

Made by indexStorm

21 | 22 |

Follow on Twitter @index_storm

23 | 24 |

Authors:

25 | 26 | - Mike 27 | - Evgeniy 28 | 29 |

30 | 32 | 33 |

34 | -------------------------------------------------------------------------------- /chrome/background.js: -------------------------------------------------------------------------------- 1 | chrome.tabs.onUpdated.addListener( 2 | function (tabId, changeInfo, tab) { 3 | if (changeInfo.url) { 4 | chrome.tabs.sendMessage(tabId, { 5 | message: 'url changed', 6 | url: changeInfo.url 7 | }) 8 | } 9 | } 10 | ); 11 | -------------------------------------------------------------------------------- /chrome/content.js: -------------------------------------------------------------------------------- 1 | const regex = /github\.com\/(.*\w+)$/ 2 | 3 | main() 4 | 5 | function main() { 6 | const href = location.href 7 | if ((m = regex.exec(href)) !== null) { 8 | if (m.length === 2) { 9 | const repoPath = m[1] 10 | const about = getAbout() 11 | const repoInfo = getDescription() 12 | let data = [] 13 | if (about) { 14 | data.push(about) 15 | } 16 | if (repoInfo) { 17 | data = data.concat(repoInfo) 18 | } 19 | const description = data.join(' ') 20 | if (data.length && description.length > 100) { 21 | requestSimilarRepo({ 22 | url: repoPath, 23 | description: data.join(' ') 24 | }).then(result => result.json()) 25 | .then(result => addSimilarRepo(result)) 26 | .catch(e => console.error(e)) 27 | } 28 | } 29 | } 30 | } 31 | 32 | function addSimilarRepo(repos) { 33 | if (document.getElementsByClassName('p-idx-storm').length !== 0) { 34 | return 35 | } 36 | const style = document.createElement('style'); 37 | style.innerHTML = '.p-idx-storm { padding: 12px; }'; 38 | document.getElementsByTagName('head')[0].appendChild(style); 39 | let inject = '' 40 | for (const repo of repos.slice(0, 5)) { 41 | const card = `
42 |
43 |
44 | ${repo.title} 46 |
47 |
48 |

${repo.about ?? ""}

49 |
50 |

51 | 52 | 57 | ${repo.stars} 58 | 59 |

60 |
61 |
62 | ` 63 | inject += card 64 | } 65 | let template = `

Similar repositories

66 |

Provided by indexStorm

` + inject + `
`; 67 | const fragment = document.createRange().createContextualFragment(template); 68 | const borderGrid = document.querySelector('.BorderGrid'); 69 | if (borderGrid.children.length <= 1) { 70 | borderGrid.appendChild(fragment.firstChild) 71 | } else { 72 | borderGrid.insertBefore(fragment.firstChild, borderGrid.children[1]) 73 | } 74 | } 75 | 76 | function getAbout() { 77 | const sel = document.querySelector("#repo-content-pjax-container > div > div > div.Layout.Layout--flowRow-until-md.Layout--sidebarPosition-end.Layout--sidebarPosition-flowRow-end > div.Layout-sidebar > div > div.BorderGrid-row.hide-sm.hide-md > div > p") 78 | if (sel) { 79 | return sel.innerText 80 | } 81 | } 82 | 83 | function getDescription() { 84 | const result = [] 85 | const article = document.querySelector("#readme > div.Box-body.px-5.pb-5 > article") 86 | if (!article) { 87 | return undefined 88 | } 89 | for (const child of article.children) { 90 | if (child.tagName !== 'P') continue; 91 | const text = child.innerText.trim() 92 | if (text.length) { 93 | result.push(text) 94 | } 95 | } 96 | return result.slice(0, 5) 97 | } 98 | 99 | async function requestSimilarRepo(body) { 100 | return fetch('https://git.indexstorm.com/similar', { 101 | method: 'POST', 102 | headers: { 103 | 'Accept': 'application/json', 104 | 'Content-Type': 'application/json' 105 | }, 106 | body: JSON.stringify(body) 107 | }) 108 | } 109 | 110 | chrome.runtime.onMessage.addListener( 111 | function (request, sender, sendResponse) { 112 | if (request.message === 'url changed') { 113 | main() 114 | } 115 | }); 116 | -------------------------------------------------------------------------------- /chrome/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IndexStorm/git-rec-ext/8d5934026590ca3618d67cd758fe6e6e871b19eb/chrome/logo.png -------------------------------------------------------------------------------- /chrome/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "GitHub Recommender", 3 | "description": "Get similar repositories on GitHub page", 4 | "author": "https://indexstorm.com", 5 | "version": "1.2.0", 6 | "manifest_version": 3, 7 | "background": { 8 | "service_worker": "background.js" 9 | }, 10 | "permissions": [ 11 | "tabs" 12 | ], 13 | "action": { 14 | "default_icon": { 15 | "1024": "logo.png" 16 | } 17 | }, 18 | "icons": { 19 | "1024": "logo.png" 20 | }, 21 | "content_scripts": [ 22 | { 23 | "matches": [ 24 | "*://github.com/*" 25 | ], 26 | "js": [ 27 | "content.js" 28 | ] 29 | } 30 | ] 31 | } 32 | -------------------------------------------------------------------------------- /mozilla/background.js: -------------------------------------------------------------------------------- 1 | browser.tabs.onUpdated.addListener( 2 | function(tabId, changeInfo, tab) { 3 | if (changeInfo.url) { 4 | browser.tabs.sendMessage( tabId, { 5 | message: 'url changed', 6 | url: changeInfo.url 7 | }) 8 | } 9 | } 10 | ); 11 | -------------------------------------------------------------------------------- /mozilla/content.js: -------------------------------------------------------------------------------- 1 | const regex = /github\.com\/(.*\w+)$/ 2 | 3 | main() 4 | 5 | function main() { 6 | const href = location.href 7 | if ((m = regex.exec(href)) !== null) { 8 | if (m.length === 2) { 9 | const repoPath = m[1] 10 | const about = getAbout() 11 | const repoInfo = getDescription() 12 | let data = [] 13 | if (about) { 14 | data.push(about) 15 | } 16 | if (repoInfo) { 17 | data = data.concat(repoInfo) 18 | } 19 | let description = data.join(' ') 20 | if (data.length && description.length > 100) { 21 | requestSimilarRepo({ 22 | url: repoPath, 23 | description: data.join(' ') 24 | }).then(result => result.json()) 25 | .then(result => addSimilarRepo(result)) 26 | .catch(e => console.error(e)) 27 | } 28 | } 29 | } 30 | } 31 | 32 | function addSimilarRepo(repos) { 33 | if (document.getElementsByClassName('p-idx-storm').length !== 0) { return } 34 | const style = document.createElement('style'); 35 | style.innerHTML = '.p-idx-storm { padding: 12px; }'; 36 | document.getElementsByTagName('head')[0].appendChild(style); 37 | let inject = '' 38 | for (const repo of repos.slice(0, 5)) { 39 | const card = `
40 |
41 |
42 | ${repo.title} 44 |
45 |
46 |

${repo.about ?? ""}

47 |
48 |

49 | 50 | 55 | ${repo.stars} 56 | 57 |

58 |
59 |
60 | ` 61 | inject += card 62 | } 63 | let template = `

Similar repositories

64 |

Provided by indexStorm

` + inject + `
`; 65 | const fragment = document.createRange().createContextualFragment(template); 66 | const borderGrid = document.querySelector('.BorderGrid'); 67 | if (borderGrid.children.length <= 1) { 68 | borderGrid.appendChild(fragment.firstChild) 69 | } else { 70 | borderGrid.insertBefore(fragment.firstChild, borderGrid.children[1]) 71 | } 72 | } 73 | 74 | function getAbout() { 75 | const sel = document.querySelector("#repo-content-pjax-container > div > div > div.Layout.Layout--flowRow-until-md.Layout--sidebarPosition-end.Layout--sidebarPosition-flowRow-end > div.Layout-sidebar > div > div.BorderGrid-row.hide-sm.hide-md > div > p") 76 | if (sel) { 77 | return sel.innerText 78 | } 79 | } 80 | 81 | function getDescription() { 82 | const result = [] 83 | const article = document.querySelector("#readme > div.Box-body.px-5.pb-5 > article") 84 | if (!article) { 85 | return undefined 86 | } 87 | for (const child of article.children) { 88 | if (child.tagName !== 'P') continue; 89 | const text = child.innerText.trim() 90 | if (text.length) { 91 | result.push(text) 92 | } 93 | } 94 | return result.slice(0, 5) 95 | } 96 | 97 | async function requestSimilarRepo(body) { 98 | return fetch('https://git.indexstorm.com/similar', { 99 | method: 'POST', 100 | headers: { 101 | 'Accept': 'application/json', 102 | 'Content-Type': 'application/json' 103 | }, 104 | body: JSON.stringify(body) 105 | }) 106 | } 107 | 108 | browser.runtime.onMessage.addListener( 109 | function(request, sender, sendResponse) { 110 | if (request.message === 'url changed') { 111 | main() 112 | } 113 | }); -------------------------------------------------------------------------------- /mozilla/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IndexStorm/git-rec-ext/8d5934026590ca3618d67cd758fe6e6e871b19eb/mozilla/logo.png -------------------------------------------------------------------------------- /mozilla/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "manifest_version": 2, 3 | "name": "GitHub Recommender", 4 | "version": "1.2.0", 5 | "description": "Get similar repositories on GitHub page", 6 | "author": "https://indexstorm.com", 7 | "background": { 8 | "scripts": ["background.js"] 9 | }, 10 | "icons": { 11 | "1024": "logo.png" 12 | }, 13 | "content_scripts": [ 14 | { 15 | "matches": ["*://github.com/*"], 16 | "js": ["content.js"] 17 | } 18 | ], 19 | "permissions": [ 20 | "https://git.indexstorm.com/similar", 21 | "tabs" 22 | ] 23 | } 24 | --------------------------------------------------------------------------------