├── .github └── FUNDING.yml ├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── assets ├── banner.png ├── cws-1.jpg ├── cws-2.jpg ├── demo.gif ├── favicon.png ├── feature-1-example.png ├── feature-2-example.png ├── feature-3-example.png ├── icon-no-bg.png ├── icon128.png ├── icon16.png ├── icon48.png └── popup.png ├── better-github.js ├── package.json ├── popup.html ├── scripts └── build.js ├── styles.css └── yarn.lock /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | custom: "https://www.buymeacoffee.com/ceoshikhar" 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | better-github.zip 2 | better-github-chrome.zip 3 | better-github-firefox.zip 4 | manifest.json 5 | node_modules 6 | .DS_Store 7 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | # Unversioned 4 | 5 | ### Fixes 6 | 7 | - Some font names don't apply, for example 'Terminus (TTF) for Windows'. [PR #14](https://github.com/ceoshikhar/better-github/pull/14). 8 | 9 | 10 | # 1.2.0 (16-01-2022) 11 | 12 | ### Features 13 | 14 | - Apply styles to `code` HTML elements. [PR #13](https://github.com/ceoshikhar/better-github/pull/13). 15 | 16 | # 1.1.0 (16-01-2022) 17 | 18 | ### Features 19 | 20 | - Can provide just one style property and it will apply that style property instead of making the user provide values for all the style properties. [PR #12](https://github.com/ceoshikhar/better-github/pull/12). 21 | 22 | # 1.0.3 (26-12-2021) 23 | 24 | ### Features 25 | 26 | - Can customize line height. 27 | 28 | # 1.0.2 (07-07-2021) 29 | 30 | ### Fixes 31 | 32 | - Mouse cursor not falling in correct place while editing a file. [Issue #6](https://github.com/ceoshikhar/better-github/issues/6) - Fixed by [PR #10](https://github.com/ceoshikhar/better-github/pull/10). 33 | 34 | - Stopped working on github gists. [Issue #8](https://github.com/ceoshikhar/better-github/issues/8) - Fixed by [PR #9](https://github.com/ceoshikhar/better-github/pull/9). Thanks to [Aahnik Daw](https://github.com/aahnik). 35 | 36 | # 1.0.1 (01-04-2021) 37 | 38 | ### Features 39 | 40 | - Support for Firefox. Released it as an official mozilla firefox [addon](https://addons.mozilla.org/en-US/firefox/addon/bettergithub) 41 | - Scripts to build/package the extension( zip ) and generate manifest.json 42 | 43 | ### Fixes and refactors 44 | 45 | - Extra scroll( overflow ) on `
` in Popup on Firefox 46 | - Refactor Popup CSS styles to `styles.css` 47 | 48 | # 1.0.0 (29-03-2021) 49 | 50 | First public release 51 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Shikhar Sharma 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 |  2 | 3 |🎨 Enhance your code reading experience on GitHub
6 |`" blocks also known as `` tags.
38 |
39 |
40 |
41 | - Code in pull request diffs.
42 |
43 |
44 |
45 | **Note:** If the custom styles are not applied( it can happen sometimes ), refresh the page.
46 |
47 | # Motivation
48 |
49 | Default font size of code text was very small which gave me had a hard time reading code in any repository and in PR diffs. I also wanted my code editor font and GitHub font to be same.
50 |
51 | Couldn't find anything existing to help me solve my problem, so I created this simple yet powerful extension for Chrome browser. If something does exist though, let me know, alright?
52 |
53 | I called it `Better GitHub` inspired by `Better Twitch TV` and `Better Discord`.
54 |
55 | # Todos
56 |
57 | > Context: I created this list of tasks after I decided to make this extension public. Initially the code was very small and the font styles were hard coded. If I needed to modify the styles, I had to change it in the source code, reload the extension and refresh GitHub pages to reflect the updates. Consider this list as the roadmap for the project.
58 |
59 | - [x] Instead of hard coding the `fontFamily` and `fontSize`, we should be able to allow the user to choose a font size and font family of their choice (which they have installed on their machine).
60 | - [x] Create a browser action popup to show an interface to allow the user to customise their extension's settings for `fontFamily` and `fontSize`.
61 | - [x] Integrate browser action popup with chrome API to persist and read user's settings for `fontFamily` and `fontSize` from and to the storage.
62 | - [x] Apply styles without reloading whenever the settings are changed from the browser action popup interface.
63 | - [x] If no custom font styles are set, load GitHub's default font styles.
64 | - [x] User can reset font styles to GitHub's default font styles.
65 | - [x] Add GIF to show the usage( demo ) of the extension.
66 | - [x] Installation instructions on how to clone/download this repository, install the extension and use it.
67 | - [x] Logo for the extension that will be used as favicon, icon, in documentation etc.
68 | - [x] Firefox support as it was requested by [others](https://dev.to/ceoshikhar/enhance-your-code-reading-experience-on-github-with-this-chrome-extension-24ei).
69 | - [x] Publish it as an official Mozilla Firefox addon.
70 | - [x] Publish it as an official Chrome extension on Chrome Web Store.
71 | - [x] Allow user to change only one property instead of all properties being mandatory.
72 | - [ ] Add `CONTRIBUTING.md` to help others so that they can contribute to the project.
73 |
--------------------------------------------------------------------------------
/assets/banner.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ceoshikhar/better-github/ce7a2929aa762bee9e8dd9e93837704724b4d40d/assets/banner.png
--------------------------------------------------------------------------------
/assets/cws-1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ceoshikhar/better-github/ce7a2929aa762bee9e8dd9e93837704724b4d40d/assets/cws-1.jpg
--------------------------------------------------------------------------------
/assets/cws-2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ceoshikhar/better-github/ce7a2929aa762bee9e8dd9e93837704724b4d40d/assets/cws-2.jpg
--------------------------------------------------------------------------------
/assets/demo.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ceoshikhar/better-github/ce7a2929aa762bee9e8dd9e93837704724b4d40d/assets/demo.gif
--------------------------------------------------------------------------------
/assets/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ceoshikhar/better-github/ce7a2929aa762bee9e8dd9e93837704724b4d40d/assets/favicon.png
--------------------------------------------------------------------------------
/assets/feature-1-example.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ceoshikhar/better-github/ce7a2929aa762bee9e8dd9e93837704724b4d40d/assets/feature-1-example.png
--------------------------------------------------------------------------------
/assets/feature-2-example.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ceoshikhar/better-github/ce7a2929aa762bee9e8dd9e93837704724b4d40d/assets/feature-2-example.png
--------------------------------------------------------------------------------
/assets/feature-3-example.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ceoshikhar/better-github/ce7a2929aa762bee9e8dd9e93837704724b4d40d/assets/feature-3-example.png
--------------------------------------------------------------------------------
/assets/icon-no-bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ceoshikhar/better-github/ce7a2929aa762bee9e8dd9e93837704724b4d40d/assets/icon-no-bg.png
--------------------------------------------------------------------------------
/assets/icon128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ceoshikhar/better-github/ce7a2929aa762bee9e8dd9e93837704724b4d40d/assets/icon128.png
--------------------------------------------------------------------------------
/assets/icon16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ceoshikhar/better-github/ce7a2929aa762bee9e8dd9e93837704724b4d40d/assets/icon16.png
--------------------------------------------------------------------------------
/assets/icon48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ceoshikhar/better-github/ce7a2929aa762bee9e8dd9e93837704724b4d40d/assets/icon48.png
--------------------------------------------------------------------------------
/assets/popup.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ceoshikhar/better-github/ce7a2929aa762bee9e8dd9e93837704724b4d40d/assets/popup.png
--------------------------------------------------------------------------------
/better-github.js:
--------------------------------------------------------------------------------
1 | // Store the current set font styles to this object so that we don't have to
2 | // fetch them from chrome storage API again and again.
3 | // This improves the performance as we don't do the async chrome storage API
4 | // read calls every time `applyCurrentSetStyles` is called.
5 | const cache = {
6 | dirty: false,
7 | fontName: null,
8 | fontSize: null,
9 | lineHeight: null,
10 | };
11 |
12 | // These styles were taken from Google Chrome's(Windows) inspect element tool
13 | // on 24/3/2021. These default styles might change but it's not really that
14 | // important otherwise it would defeat the whole purpose of `Better Github`.
15 | const DEFAULT_FONT_FAMILY =
16 | "SFMono-Regular,Consolas,Liberation Mono,Menlo,monospace";
17 | const DEFAULT_FONT_SIZE = "12px";
18 | const DEFAULT_LINE_HEIGHT = 1.4;
19 |
20 | // Do the magic once the DOM is completely loaded.
21 | window.onload = init();
22 |
23 | // Entry point of the extension to interact with the DOM on GitHub.
24 | function init() {
25 | // Apply font styles when DOM tree is completely loaded.
26 | applyCurrentSetStyles();
27 |
28 | // Apply font styles when DOM tree is mutated.
29 | reApplyStylesOnDOMChange();
30 | }
31 |
32 | // Apply the currently set font styles if they exist
33 | async function applyCurrentSetStyles() {
34 | if (isUserEditingFile()) return;
35 |
36 | const currentSetFontStyles = await getCurrentSetFontStyles();
37 | if (!currentSetFontStyles) return;
38 |
39 | const { fontFamily, fontSize, lineHeight } = currentSetFontStyles;
40 | applyStyles(fontFamily, fontSize, lineHeight);
41 | }
42 |
43 | // Apply the custom styles whenever something on the DOM changes. Following are
44 | // some scenarios why this is important.
45 | //
46 | // 1. With larger PRs, sometimes diffs are loaded lazily. Which means, a DOM
47 | // mutation is happening. If we don't re-apply the styles, the newly loaded
48 | // code text in the diff will have the defaul styles.
49 | //
50 | // 2. GitHub is an SPA. Which means, DOM is loaded only once. When you navigate
51 | // to other "pages" on GitHub, the DOM is changing( mutation ) and if we don't
52 | // re-apply the styles, the code text on new page will have default styles.
53 | //
54 | // We don't care to check what the change is happening on the DOM, we just
55 | // re-apply the styles no matter what's happening. This shouldn't be affecting
56 | // the performance as all we are doing is changing the CSS styles, also there
57 | // are not so many DOM changes happening once the entire page content is loaded.
58 | function reApplyStylesOnDOMChange() {
59 | // We pass `applyCurrentSetStyles` as the callback to `Mutation Observer`.
60 | // This means, whenever a DOM mutation is observed it fires the callback.
61 | const observer = new MutationObserver(applyCurrentSetStyles);
62 |
63 | observer.observe(document, { childList: true, subtree: true });
64 | }
65 |
66 | // Reset the font styles to Github's default.
67 | function resetStyles() {
68 | // Clear the storage so that when we reload/refresh or visit GitHub in another
69 | // tab, we don't apply any custom styles including the above two mentioned.
70 | // The real(coming from GitHub) GitHub's default styles are used.
71 | clearStorage();
72 |
73 | // We apply the GitHub's "default styles" so that we don't have to manually
74 | // refresh the current open tabs and this makes it feel "reactive".
75 | applyStyles(DEFAULT_FONT_FAMILY, DEFAULT_FONT_SIZE, DEFAULT_LINE_HEIGHT);
76 | }
77 |
78 | // This is where the magic happens. As the name suggests, the function is
79 | // responsible for applying the font styles to the code text elements on a page.
80 | //
81 | // Apply font styles (font-name & font-size).
82 | // These styles are applied to :
83 | // - All the text inside a file while viewing( reading ) it.
84 | // - Code in README files that are inside "``" blocks also known as `` tags.
85 | // - Code in pull request diffs.
86 | function applyStyles(fontFamily, fontSize, lineHeight) {
87 | const codeTextElements = document.getElementsByClassName("blob-code-inner");
88 | const codeLineNumElements = document.getElementsByClassName("blob-num");
89 | const preElements = document.querySelectorAll("pre");
90 | const codeElements = document.querySelectorAll("code");
91 |
92 | for (let i = 0; i < codeTextElements.length; i++) {
93 | applyStyle(codeTextElements[i], "fontFamily", fontFamily);
94 | applyStyle(codeTextElements[i], "fontSize", fontSize);
95 | applyStyle(codeTextElements[i], "lineHeight", lineHeight);
96 | }
97 |
98 | for (let i = 0; i < codeLineNumElements.length; i++) {
99 | applyStyle(codeLineNumElements[i], "fontFamily", fontFamily);
100 | applyStyle(codeLineNumElements[i], "fontSize", fontSize);
101 | applyStyle(codeLineNumElements[i], "fontHeight", lineHeight);
102 | }
103 |
104 | for (let i = 0; i < preElements.length; i++) {
105 | applyStyle(preElements[i], "fontFamily", fontFamily);
106 | applyStyle(preElements[i], "fontSize", fontSize);
107 | applyStyle(preElements[i], "fontHeight", lineHeight);
108 | }
109 |
110 | for (let i = 0; i < codeElements.length; i++) {
111 | applyStyle(codeElements[i], "fontFamily", fontFamily);
112 | applyStyle(codeElements[i], "fontSize", fontSize);
113 | applyStyle(codeElements[i], "fontHeight", lineHeight);
114 | }
115 | }
116 |
117 | /**
118 | * @param {HTMLElement} el The element to apply the style to.
119 | * @param {string} prop The style property to change.
120 | * @param {string} value The value to apply for the given `prop`.
121 | *
122 | * If a falsy(inc. empty string) value is passed as `value` then that value
123 | * will not be applied and will be skipped.
124 | */
125 | function applyStyle(el, prop, value) {
126 | if (!value) {
127 | return;
128 | }
129 |
130 | el.style[prop] = value;
131 | }
132 |
133 | // Extension's browser action popup UI handling to allow user to customize the
134 | // settings of the styles. Handles the `APPLY` and `RESET` button logic.
135 | document.addEventListener("DOMContentLoaded", async function () {
136 | const setFontName = (await getCurrentSetFontName()) || "";
137 | const setFontSize = (await getCurrentSetFontSize()) || "";
138 | const setLineHeight = (await getCurrentSetLineHeight()) || "";
139 | const applyButton = document.getElementById("apply-button");
140 | const resetButton = document.getElementById("reset-button");
141 | const fontNameInput = document.getElementById("font-name-input");
142 | const fontSizeInput = document.getElementById("font-size-input");
143 | const lineHeightInput = document.getElementById("line-height-input");
144 |
145 | // Set the initial value of the inputs to be the current set styles.
146 | fontNameInput.value = setFontName;
147 | fontSizeInput.value = setFontSize;
148 | lineHeightInput.value = setLineHeight;
149 |
150 | applyButton.addEventListener("click", function () {
151 | const font = fontNameInput.value;
152 | const size = fontSizeInput.value;
153 | const height = lineHeightInput.value;
154 | const fontStyles = {
155 | font,
156 | size,
157 | height,
158 | };
159 |
160 | // We get the details of all the tabs open and send message to all the
161 | // tabs with the new font styles data. All the tabs with GitHub open
162 | // will read this message and apply the new styles sent in the message.
163 | chrome.tabs.query({}, function (tabs) {
164 | tabs.map(function (tab) {
165 | chrome.tabs.sendMessage(tab.id, { data: fontStyles });
166 | });
167 | });
168 | });
169 |
170 | resetButton.addEventListener("click", function () {
171 | // Send message to all the tabs with data saying that we should reset the
172 | // styles. All the tabs with GitHub open will read this message and reset
173 | // styles to GitHub's default styles.
174 | chrome.tabs.query({}, function (tabs) {
175 | tabs.map(function (tab) {
176 | chrome.tabs.sendMessage(tab.id, { data: { reset: true } });
177 | });
178 | });
179 | });
180 | });
181 |
182 | // We listen for messages that we earlier sent when a user clicked on `APPLY` or
183 | // `RESET` button. Based on the `request.data` of the message, we either apply
184 | // the new styles or reset the styles.
185 | chrome.runtime.onMessage.addListener(function (request, _sender, sendResponse) {
186 | const data = request.data || {};
187 | const shouldReset = data.reset === true;
188 |
189 | if (shouldReset) {
190 | resetStyles();
191 | return;
192 | }
193 |
194 | const name = data.font;
195 | const size = data.size;
196 | const height = data.height;
197 |
198 | setCurrentSetFontName(name);
199 | setCurrentSetFontSize(size);
200 | setCurrentSetLineHeight(height);
201 |
202 | const { fontFamily, fontSize, lineHeight } = genFontStyles(
203 | name,
204 | size,
205 | height
206 | );
207 | applyStyles(fontFamily, fontSize, lineHeight);
208 | sendResponse({ data, success: true });
209 | });
210 |
211 | // Chrome's storage API allows us to store & fetch user's recent applied styles.
212 | // Save to chrome's storage. `data` should be an object like `{ key: value }`.
213 | function saveToStorage(data) {
214 | chrome.storage.sync.set(data);
215 | }
216 |
217 | // Read a `value` from chromes' storage by providing the `key`. This returns a
218 | // Promise so that we can await for the `value`. If we don't use Promise, the
219 | // return value will always be `undefined` as chrome's storage read is async.
220 | function getFromStorage(key) {
221 | return new Promise(function (resolve, _reject) {
222 | chrome.storage.sync.get([`${key}`], function (result) {
223 | const value = result[`${key}`];
224 | resolve(value);
225 | });
226 | });
227 | }
228 |
229 | // Destroy everything from the chrome's storage.
230 | function clearStorage() {
231 | chrome.storage.sync.clear();
232 | }
233 |
234 | async function getCurrentSetFontName() {
235 | const currentFontName = await getFromStorage("fontName");
236 | return currentFontName;
237 | }
238 |
239 | async function getCurrentSetFontSize() {
240 | const currentFontSize = await getFromStorage("fontSize");
241 | return currentFontSize;
242 | }
243 |
244 | async function getCurrentSetLineHeight() {
245 | const currentLineHeight = await getFromStorage("lineHeight");
246 | return currentLineHeight;
247 | }
248 |
249 | function setCurrentSetFontName(name) {
250 | saveToStorage({ fontName: name });
251 | cache.fontName = name;
252 | }
253 |
254 | function setCurrentSetFontSize(size) {
255 | saveToStorage({ fontSize: size });
256 | cache.fontSize = size;
257 | }
258 |
259 | function setCurrentSetLineHeight(height) {
260 | saveToStorage({ lineHeight: height });
261 | cache.lineHeight = height;
262 | }
263 |
264 | // Generates correct styles by adding `px` for `size` and adding
265 | // `'monospace'` for `name`.
266 | function genFontStyles(name, size, height) {
267 | const fontFamily = !name ? DEFAULT_FONT_FAMILY : `'${name}', 'monospace'`;
268 | const fontSize = !size ? DEFAULT_FONT_SIZE : `${size}px`;
269 | const lineHeight = !height ? DEFAULT_LINE_HEIGHT : height;
270 |
271 | return { fontFamily, fontSize, lineHeight };
272 | }
273 |
274 | async function getCurrentSetFontStyles() {
275 | if (cache.dirty) {
276 | return genFontStyles(cache.fontName, cache.fontSize, cache.lineHeight);
277 | }
278 |
279 | // Everything below here will be executed only during the first time the
280 | // document is loaded. After that, `cache` will always have latest font styles.
281 |
282 | const currentSetFontName = await getCurrentSetFontName();
283 | const currentSetFontSize = await getCurrentSetFontSize();
284 | const currentSetLineHeight = await getCurrentSetLineHeight();
285 |
286 | // Update the cache so that we don't make the chrome storage read calls again.
287 | cache.dirty = true;
288 | if (currentSetFontName) cache.fontName = currentSetFontName;
289 | if (currentSetFontSize) cache.fontSize = currentSetFontSize;
290 | if (currentSetLineHeight) cache.lineHeight = currentSetLineHeight;
291 |
292 | return getCurrentSetFontStyles();
293 | }
294 |
295 | // This is a cheeky solution to the issue where the code editor goes whack
296 | // mode when we change the font styles on the code lines inside the editor.
297 | //
298 | // So for the time being we will not change the font styles when a user is
299 | // editing a file on GitHub.
300 | //
301 | // Maybe in the future, if I get lucky( idk wtf is GitHub doing ) or someone
302 | // in the world contributes and solves this issue where we can apply custom
303 | // font styles to editor font without making it go insane, that would be nice.
304 | //
305 | // Untill then, Better GitHub won't do it's magic when user edits a file on
306 | // GitHub. Also, who does that? xD
307 | // Check - https://github.com/ceoshikhar/better-github/issues/6 for more info.
308 | function isUserEditingFile() {
309 | function fileNameFromPath() {
310 | const words = window.location.pathname.split("/");
311 | const len = words.length;
312 | // The file being viewed/edited on GitHub is the last word in the URL path.
313 | const fileName = words[len - 1];
314 |
315 | return fileName;
316 | }
317 |
318 | // The word "edit" exists in the URL path if the user is editing the file.
319 | const wordEditInPathExists = window.location.pathname.includes("edit");
320 | const fileNameFromInputEl = document.querySelector(
321 | "input[name=filename]"
322 | )?.value;
323 |
324 | // The name of the file being edited will be same in URL path and input element on page load.
325 | if (fileNameFromPath() === fileNameFromInputEl && wordEditInPathExists) {
326 | return true;
327 | }
328 |
329 | return false;
330 | }
331 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "better-github",
3 | "version": "1.2.0",
4 | "description": "Enhance your code reading experience on GitHub",
5 | "author": {
6 | "name": "Shikhar Sharma",
7 | "email": "ceoshikhar@gmail.com"
8 | },
9 | "license": "MIT",
10 | "main": "better-github.js",
11 | "scripts": {
12 | "package:chrome": "node scripts/build chrome",
13 | "package:firefox": "node scripts/build firefox",
14 | "manifest:chrome": "node scripts/build chrome -m",
15 | "manifest:firefox": "node scripts/build firefox -m",
16 | "clean": "rm -f manifest.json better-github-chrome.zip better-github-firefox.zip"
17 | },
18 | "repository": {
19 | "type": "git",
20 | "url": "git+https://github.com/ceoshikhar/better-github.git"
21 | },
22 | "bugs": {
23 | "url": "https://github.com/ceoshikhar/better-github/issues"
24 | },
25 | "homepage": "https://github.com/ceoshikhar/better-github#readme",
26 | "dependencies": {},
27 | "devDependencies": {
28 | "chalk": "^4.1.1"
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/popup.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
9 |
10 | Better Github
11 |
12 |
13 |
14 |
15 |
16 | BETTER GITHUB
17 |
18 |
19 |
57 |
58 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/scripts/build.js:
--------------------------------------------------------------------------------
1 | /**
2 | * This is the build script that you can use to :
3 | * 1. Package the extension to better-github.zip for the specified browser.
4 | * Generally for publication or distribution of the extension.
5 | * 2. Generate manifest.json file for the specified browser.
6 | *
7 | * Prerequisites for this script to work :
8 | * 1. `zip` util binary installed, run `zip --version` to check if you have it
9 | * or not. If you get something like `command not found: zip` then you don't
10 | * have it, so install it. `zip` is not needed for generating manifest.json.
11 | * 2. `rm -rf` should work. This is available on `linux` and `unix` machines.
12 | * Don't know what you need to do for it to work on `windows`. I use WSL.
13 | *
14 | * USAGE :
15 | * - node build [options] OR you can run scripts from `package.json`
16 | *
17 | * Valid values for `` are : "chrome" and "firefox"
18 | * Valid options :
19 | * 1. `-m` : To generate only the manifest.json and not generate package.zip
20 | *
21 | * EXAMPLE :
22 | * 1. Generate better-github.zip for chrome : `node build chrome`
23 | * 2. Generate manifest.json for firefox : `node build firefox -m`
24 | */
25 |
26 | // NOTE: Update the `version` here and in `package.json` whenever a new release
27 | // of the extension is published.
28 | const VERSION = "1.2.0";
29 |
30 | const fs = require("fs");
31 | const childProcess = require("child_process");
32 | const chalk = require("chalk");
33 |
34 | function green(text) {
35 | return chalk.green(text);
36 | }
37 |
38 | function blue(text) {
39 | return chalk.blue.underline(text);
40 | }
41 |
42 | function result(text) {
43 | return chalk.black.bgYellowBright(text);
44 | }
45 |
46 | const chromeManifestContent = {
47 | manifest_version: 2,
48 | name: "Better Github",
49 | version: VERSION,
50 | description: "Enhance your code reading experience on GitHub",
51 | content_scripts: [
52 | {
53 | js: ["better-github.js"],
54 | matches: ["https://github.com/*", "https://gist.github.com/*"],
55 | },
56 | ],
57 | permissions: ["storage"],
58 | browser_action: {
59 | default_title: "Better Github",
60 | default_icon: "./assets/favicon.png",
61 | default_popup: "popup.html",
62 | },
63 | icons: {
64 | 16: "./assets/icon16.png",
65 | 48: "./assets/icon48.png",
66 | 128: "./assets/icon128.png",
67 | },
68 | };
69 |
70 | // For Firefox's manifest, we just have to add one extra property: "applications"
71 | const firefoxManifestContent = {
72 | ...chromeManifestContent,
73 | applications: {
74 | gecko: {
75 | id: "better-github@ceoshikhar.com",
76 | strict_min_version: "80.0",
77 | },
78 | },
79 | };
80 |
81 | // The first element will be 'node', the second element will be the name of the
82 | // JS file. The next elements will be any additional command line arguments.
83 | const args = process.argv.slice(2);
84 | const maxArgs = 2;
85 | const browser = args[0];
86 | const validBrowsers = ["chrome", "firefox"];
87 | const shouldBuildPackage = browser && args[1] === "-m" ? false : true;
88 | const manifestName = "manifest.json";
89 | const packageChromeName = "better-github-chrome.zip";
90 | const packageFirefoxName = "better-github-firefox.zip";
91 | const packageName = browserType().isChrome
92 | ? packageChromeName
93 | : packageFirefoxName;
94 |
95 | const thingsToZip = [
96 | "assets/icon16.png",
97 | "assets/icon48.png",
98 | "assets/icon128.png",
99 | "assets/favicon.png",
100 | "assets/icon-no-bg.png",
101 | "better-github.js",
102 | manifestName,
103 | "popup.html",
104 | "styles.css",
105 | ];
106 |
107 | function browserType() {
108 | const isChrome = browser === validBrowsers[0] ? true : false;
109 | const isFirefox = browser === validBrowsers[1] ? true : false;
110 | return { isChrome, isFirefox };
111 | }
112 |
113 | function makeSureArgsAreValid() {
114 | if (args.length > maxArgs) {
115 | throw new Error(`Maximum 2 arguments are allowed`);
116 | }
117 |
118 | if (!validBrowsers.includes(browser)) {
119 | throw new Error(
120 | `Invalid browser, "chrome" and "firefox" are only valid`
121 | );
122 | }
123 |
124 | if (shouldBuildPackage && args.length === maxArgs) {
125 | throw new Error(`Unexpected arguments`);
126 | }
127 | }
128 |
129 | function cleanUpOldFiles() {
130 | console.log(green("> Cleaning up old files if they exist"));
131 |
132 | const command = `rm -f manifest.json better-github-chrome.zip better-github-firefox.zip`;
133 | childProcess.execSync(command);
134 | }
135 |
136 | // Create new manifest.json and put `chromeManifestContent` if the build is
137 | // for Chrome browser otherwise put `firefoxManifestContent` if the build is
138 | // for Firefox browser.
139 | function buildManifest() {
140 | console.log(
141 | green(`> Building manifest for ${browser}: `) + blue(`${manifestName}`)
142 | );
143 | if (browserType().isChrome) {
144 | fs.writeFileSync(
145 | manifestName,
146 | JSON.stringify(chromeManifestContent, null, 2)
147 | );
148 | } else if (browserType().isFirefox) {
149 | fs.writeFileSync(
150 | manifestName,
151 | JSON.stringify(firefoxManifestContent, null, 2)
152 | );
153 | }
154 | }
155 |
156 | function buildPackage() {
157 | const command = `zip ${packageName} ${thingsToZip.join(" ")}`;
158 | console.log(
159 | green(`> Building package for ${browser}: `) + blue(`${packageName}`)
160 | );
161 | childProcess.execSync(command);
162 | }
163 |
164 | function main() {
165 | const t0 = Date.now();
166 |
167 | makeSureArgsAreValid();
168 | cleanUpOldFiles();
169 | buildManifest();
170 |
171 | if (shouldBuildPackage) {
172 | buildPackage();
173 | }
174 |
175 | const t1 = Date.now();
176 | console.log(result(`> 🚀 Finished in ${t1 - t0}ms`));
177 | }
178 |
179 | main();
180 |
--------------------------------------------------------------------------------
/styles.css:
--------------------------------------------------------------------------------
1 | body {
2 | width: 250px;
3 | padding: 0;
4 | margin: 0;
5 | border: 2px solid RGB(42, 46, 47);
6 | overflow: -moz-hidden-unscrollable;
7 | }
8 |
9 | h2,
10 | p,
11 | label {
12 | margin: 0;
13 | padding: 0;
14 | font-size: 1rem;
15 | color: RGB(42, 46, 47);
16 | font-family: "Poppins", sans-serif;
17 | }
18 |
19 | h2 {
20 | font-size: 1.25rem;
21 | margin: 0.25em 0;
22 | text-align: center;
23 | }
24 |
25 | p {
26 | text-align: center;
27 | font-family: "Source Code Pro", monospace;
28 | }
29 |
30 | label {
31 | display: block;
32 | text-align: left;
33 | font-weight: bold;
34 | }
35 |
36 | form {
37 | width: 100%;
38 | padding: 1em;
39 | padding-top: 0;
40 | }
41 |
42 | form input {
43 | font-family: "Source Code Pro", monospace;
44 | color: RGB(42, 46, 47);
45 | font-weight: normal;
46 | margin-top: 0.25em;
47 | border: none;
48 | border-bottom: 1px solid RGB(42, 46, 47);
49 | box-sizing: border-box;
50 | padding: 0.25em 0;
51 | outline: none;
52 | font-size: 0.85rem;
53 | width: 90%;
54 | }
55 |
56 | input::placeholder {
57 | color: RGB(42, 46, 47);
58 | opacity: 0.69;
59 | }
60 |
61 | button {
62 | width: 90%;
63 | padding: 0.5em 0.35em;
64 | font-size: 1.15rem;
65 | border: none;
66 | cursor: pointer;
67 | font-family: "Poppins", sans-serif;
68 | }
69 |
70 | #apply-button {
71 | background: RGB(42, 46, 47);
72 | color: RGB(249, 246, 239);
73 | }
74 |
75 | #reset-button {
76 | color: RGB(42, 46, 47);
77 | background: RGB(249, 246, 239);
78 | margin-top: 0.5em;
79 | }
80 |
81 | .flex {
82 | display: flex;
83 | justify-content: center;
84 | align-items: center;
85 | }
86 |
87 | .flex img {
88 | margin-right: 0.5em;
89 | }
90 |
--------------------------------------------------------------------------------
/yarn.lock:
--------------------------------------------------------------------------------
1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2 | # yarn lockfile v1
3 |
4 |
5 | ansi-styles@^4.1.0:
6 | version "4.3.0"
7 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937"
8 | integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==
9 | dependencies:
10 | color-convert "^2.0.1"
11 |
12 | chalk@^4.1.1:
13 | version "4.1.1"
14 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.1.tgz#c80b3fab28bf6371e6863325eee67e618b77e6ad"
15 | integrity sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==
16 | dependencies:
17 | ansi-styles "^4.1.0"
18 | supports-color "^7.1.0"
19 |
20 | color-convert@^2.0.1:
21 | version "2.0.1"
22 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3"
23 | integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==
24 | dependencies:
25 | color-name "~1.1.4"
26 |
27 | color-name@~1.1.4:
28 | version "1.1.4"
29 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
30 | integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
31 |
32 | has-flag@^4.0.0:
33 | version "4.0.0"
34 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
35 | integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
36 |
37 | supports-color@^7.1.0:
38 | version "7.2.0"
39 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da"
40 | integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==
41 | dependencies:
42 | has-flag "^4.0.0"
43 |
--------------------------------------------------------------------------------