From 0274c34e520d4128760842dc973afdd854bf5f13 Mon Sep 17 00:00:00 2001 From: stretch4x4 Date: Sat, 15 Aug 2026 14:49:02 +1000 Subject: [PATCH] Add whitespace to fill config --- Makefile | 4 ++ README.md | 17 ++++++++ build/wide-github.user.css | 48 ++++++++++++++-------- build/wide-github.user.js | 43 ++++++++++++-------- chrome/manifest.json | 6 +++ makecss.js | 8 ++++ mozilla/manifest.json | 6 +++ options.html | 81 ++++++++++++++++++++++++++++++++++++++ options.js | 23 +++++++++++ wide-github-toggle.js | 14 +++++++ wide-github.css | 43 ++++++++++++-------- 11 files changed, 242 insertions(+), 51 deletions(-) create mode 100644 options.html create mode 100644 options.js diff --git a/Makefile b/Makefile index baa5398..cc223f1 100644 --- a/Makefile +++ b/Makefile @@ -14,6 +14,8 @@ chrome-extension: cp chrome/background.js build/chrome/background.js cp wide-github.css build/chrome/wide-github.css cp wide-github-toggle.js build/chrome/wide-github-toggle.js + cp options.html build/chrome/options.html + cp options.js build/chrome/options.js cp -rT icons build/chrome/icons/ cd build/chrome/ && zip -r wide-github.tmp.zip * mv build/chrome/wide-github.tmp.zip build/wide-github-chrome.zip @@ -25,6 +27,8 @@ mozilla-extension: cp mozilla/background.js build/mozilla/background.js cp wide-github.css build/mozilla/wide-github.css cp wide-github-toggle.js build/mozilla/wide-github-toggle.js + cp options.html build/mozilla/options.html + cp options.js build/mozilla/options.js cp -rT icons build/mozilla/icons/ cd build/mozilla/ && zip -r wide-github.tmp.zip * mv build/mozilla/wide-github.tmp.zip build/wide-github-mozilla.zip diff --git a/README.md b/README.md index 03a81c9..0349e4b 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,23 @@ As a Stylus / UserCSS This style can be installed into Stylus by going here: [wide-github.user.css](https://raw.githubusercontent.com/xthexder/wide-github/master/build/wide-github.user.css) +Configuring +----------- + +By default, GitHub pages are stretched to the full width of the window. On a wide +monitor that can be too much, so the amount of whitespace that gets filled is +adjustable: at 40%, the content grows through 40% of the unused space and the +remaining 60% stays as margin down each side. Pages are never made narrower than +GitHub's own layout, so this has no effect below 1280px. + +* **Chrome extension / Firefox addon:** right-click the toolbar icon and choose + Options (Preferences in Firefox), then drag the "Whitespace to fill" slider. + Open tabs update immediately. +* **Stylus / UserCSS:** open the style's settings and drag the + "Whitespace to fill (%)" slider. +* **Greasemonkey / UserScript:** edit the `--wgh-fill-percent` value near the top + of the installed script. + Development ----------- diff --git a/build/wide-github.user.css b/build/wide-github.user.css index e4bc6c7..4a5e6b8 100644 --- a/build/wide-github.user.css +++ b/build/wide-github.user.css @@ -14,18 +14,29 @@ @version 1.7.4 @homepageURL https://github.com/xthexder/wide-github @supportURL https://github.com/xthexder/wide-github/issues +@preprocessor default +@var range wghFillPercent "Whitespace to fill (%)" [100, 0, 100, 5] ==/UserStyle== */ @-moz-document regexp("^https://(?:gist\\.)?github\\.com/.*") { + /* Percentage (0-100) of the unused horizontal whitespace to fill. */ + /* 100 fills the window completely, 40 fills 40% of the whitespace */ + /* and keeps 60% of it split down each side of the content. */ + :root { + --wgh-fill-percent: 100; + --wgh-base-width: 1280px; + --wgh-max-width: max(var(--wgh-base-width), calc(var(--wgh-base-width) + (100vw - var(--wgh-base-width)) * var(--wgh-fill-percent) / 100)); + } + /* General full-page container */ body:not(.wgh-disabled) .application-main .container-xl { - max-width: none !important; + max-width: var(--wgh-max-width) !important; } /* General content sub-container */ body:not(.wgh-disabled) .application-main .container-lg { - max-width: none !important; - margin-left: 0px !important; + max-width: var(--wgh-max-width) !important; + margin-left: auto !important; } /* Repository home sidebar */ @@ -35,7 +46,7 @@ /* Commit History and Branches page */ body:not(.wgh-disabled) #js-repo-pjax-container div[style^="--sticky-pane-height:"] > div[class^='Box-sc-']:first-child { - max-width: none; + max-width: var(--wgh-max-width); } /* Repository Tags page */ @@ -52,62 +63,65 @@ /* Issues list page */ body:not(.wgh-disabled) .application-main div[style^="--sticky-pane-height:"] > div[class^='Box-sc-'] > div[class^='Box-sc-'] > div[class^='Box-sc-'] > div[class^='Box-sc-']:nth-child(2) > div[class^='Box-sc-'] { - max-width: none; + max-width: var(--wgh-max-width); } /* Issue page */ body:not(.wgh-disabled) #js-repo-pjax-container div[data-target="react-app.reactRoot"] > div[class^='Box-sc-'] > div[class^='Box-sc-'] > div[class^='Box-sc-'] > div[class^='Box-sc-'] { - max-width: none; + max-width: var(--wgh-max-width); } /* New React layout (2025) */ /* Issues list page */ body:not(.wgh-disabled) .application-main div[data-target="react-app.reactRoot"] div[class^='prc-PageLayout-Content-'] > div[class^='Box-sc-'] { - max-width: none; + max-width: var(--wgh-max-width); } /* Issues list page (July 2025) */ body:not(.wgh-disabled) .application-main div[data-target="react-app.reactRoot"] div[class^='ThreePanesLayout-module__ThreePanesLayoutMiddleOnlyPane-'] { - max-width: none; + max-width: var(--wgh-max-width); } /* Issues list page (Feb 2026) */ body:not(.wgh-disabled) .application-main div[data-target="react-app.reactRoot"] div[class^='ThreePanesLayout-module__ThreePanesLayoutMiddleOnlyPane__'] { - max-width: none; + max-width: var(--wgh-max-width); } /* Issue page */ body:not(.wgh-disabled) .application-main div[data-target="react-app.reactRoot"] > div[class^='Box-sc-'] > div[class^='Box-sc-'] > div[class^='Box-sc-'] > div[class^='Box-sc-'] { - max-width: none; + max-width: var(--wgh-max-width); } /* Issue page (July 2025) */ body:not(.wgh-disabled) .application-main div[data-target="react-app.reactRoot"] div[class^='IssueViewer-module__issueViewerContainer-'] > div[class^='Box-sc-'] { - max-width: none; + max-width: var(--wgh-max-width); } /* Issue page (Jan 2026) */ body:not(.wgh-disabled) .application-main div[data-target="react-app.reactRoot"] div[class^='ContentWrapper-module__contentContainer--'] { - max-width: none; + max-width: var(--wgh-max-width); } /* Issue page (Feb 2026) */ body:not(.wgh-disabled) .application-main div[data-target="react-app.reactRoot"] div[class^='prc-PageLayout-Content-'] { - max-width: none; + max-width: var(--wgh-max-width); } body:not(.wgh-disabled) .application-main div[data-target="react-app.reactRoot"] div[class^='ContentWrapper-module__contentContainer__'] { - max-width: none; + max-width: var(--wgh-max-width); } /* New issue page */ body:not(.wgh-disabled) .application-main div[data-target="react-app.reactRoot"] div[class^='IssueCreatePage-module__createPaneContainer-'] { - max-width: none; + max-width: var(--wgh-max-width); } /* Commit list page */ body:not(.wgh-disabled) .application-main div[data-target="react-app.reactRoot"] div[class^='prc-PageLayout-PageLayoutWrapper-'] { - max-width: none; + max-width: var(--wgh-max-width); } /* PR Page (May 2026) */ body:not(.wgh-disabled) .application-main div[data-target="react-app.reactRoot"] div[class^='prc-PageLayout-ContentWrapper'] { - max-width: none; + max-width: var(--wgh-max-width); } + :root { + --wgh-fill-percent: var(--wghFillPercent); + } } diff --git a/build/wide-github.user.js b/build/wide-github.user.js index a8f2df5..8eec68d 100644 --- a/build/wide-github.user.js +++ b/build/wide-github.user.js @@ -24,14 +24,23 @@ // ==/UserScript== var styleSheet = "" + +// Percentage (0-100) of the unused horizontal whitespace to fill. +// 100 fills the window completely, 40 fills 40% of the whitespace +// and keeps 60% of it split down each side of the content. +":root {" + + "--wgh-fill-percent: 100;" + + "--wgh-base-width: 1280px;" + + "--wgh-max-width: max(var(--wgh-base-width), calc(var(--wgh-base-width) + (100vw - var(--wgh-base-width)) * var(--wgh-fill-percent) / 100));" + +"}" + + // General full-page container "body:not(.wgh-disabled) .application-main .container-xl {" + - "max-width: none !important;" + + "max-width: var(--wgh-max-width) !important;" + "}" + // General content sub-container "body:not(.wgh-disabled) .application-main .container-lg {" + - "max-width: none !important;" + - "margin-left: 0px !important;" + + "max-width: var(--wgh-max-width) !important;" + + "margin-left: auto !important;" + "}" + // Repository home sidebar @@ -41,7 +50,7 @@ var styleSheet = "" + // Commit History and Branches page "body:not(.wgh-disabled) #js-repo-pjax-container div[style^=\"--sticky-pane-height:\"] > div[class^='Box-sc-']:first-child {" + - "max-width: none;" + + "max-width: var(--wgh-max-width);" + "}" + // Repository Tags page @@ -58,62 +67,62 @@ var styleSheet = "" + // Issues list page "body:not(.wgh-disabled) .application-main div[style^=\"--sticky-pane-height:\"] > div[class^='Box-sc-'] > div[class^='Box-sc-'] > div[class^='Box-sc-'] > div[class^='Box-sc-']:nth-child(2) > div[class^='Box-sc-'] {" + - "max-width: none;" + + "max-width: var(--wgh-max-width);" + "}" + // Issue page "body:not(.wgh-disabled) #js-repo-pjax-container div[data-target=\"react-app.reactRoot\"] > div[class^='Box-sc-'] > div[class^='Box-sc-'] > div[class^='Box-sc-'] > div[class^='Box-sc-'] {" + - "max-width: none;" + + "max-width: var(--wgh-max-width);" + "}" + // New React layout (2025) // Issues list page "body:not(.wgh-disabled) .application-main div[data-target=\"react-app.reactRoot\"] div[class^='prc-PageLayout-Content-'] > div[class^='Box-sc-'] {" + - "max-width: none;" + + "max-width: var(--wgh-max-width);" + "}" + // Issues list page (July 2025) "body:not(.wgh-disabled) .application-main div[data-target=\"react-app.reactRoot\"] div[class^='ThreePanesLayout-module__ThreePanesLayoutMiddleOnlyPane-'] {" + - "max-width: none;" + + "max-width: var(--wgh-max-width);" + "}" + // Issues list page (Feb 2026) "body:not(.wgh-disabled) .application-main div[data-target=\"react-app.reactRoot\"] div[class^='ThreePanesLayout-module__ThreePanesLayoutMiddleOnlyPane__'] {" + - "max-width: none;" + + "max-width: var(--wgh-max-width);" + "}" + // Issue page "body:not(.wgh-disabled) .application-main div[data-target=\"react-app.reactRoot\"] > div[class^='Box-sc-'] > div[class^='Box-sc-'] > div[class^='Box-sc-'] > div[class^='Box-sc-'] {" + - "max-width: none;" + + "max-width: var(--wgh-max-width);" + "}" + // Issue page (July 2025) "body:not(.wgh-disabled) .application-main div[data-target=\"react-app.reactRoot\"] div[class^='IssueViewer-module__issueViewerContainer-'] > div[class^='Box-sc-'] {" + - "max-width: none;" + + "max-width: var(--wgh-max-width);" + "}" + // Issue page (Jan 2026) "body:not(.wgh-disabled) .application-main div[data-target=\"react-app.reactRoot\"] div[class^='ContentWrapper-module__contentContainer--'] {" + - "max-width: none;" + + "max-width: var(--wgh-max-width);" + "}" + // Issue page (Feb 2026) "body:not(.wgh-disabled) .application-main div[data-target=\"react-app.reactRoot\"] div[class^='prc-PageLayout-Content-'] {" + - "max-width: none;" + + "max-width: var(--wgh-max-width);" + "}" + "body:not(.wgh-disabled) .application-main div[data-target=\"react-app.reactRoot\"] div[class^='ContentWrapper-module__contentContainer__'] {" + - "max-width: none;" + + "max-width: var(--wgh-max-width);" + "}" + // New issue page "body:not(.wgh-disabled) .application-main div[data-target=\"react-app.reactRoot\"] div[class^='IssueCreatePage-module__createPaneContainer-'] {" + - "max-width: none;" + + "max-width: var(--wgh-max-width);" + "}" + // Commit list page "body:not(.wgh-disabled) .application-main div[data-target=\"react-app.reactRoot\"] div[class^='prc-PageLayout-PageLayoutWrapper-'] {" + - "max-width: none;" + + "max-width: var(--wgh-max-width);" + "}" + // PR Page (May 2026) "body:not(.wgh-disabled) .application-main div[data-target=\"react-app.reactRoot\"] div[class^='prc-PageLayout-ContentWrapper'] {" + - "max-width: none;" + + "max-width: var(--wgh-max-width);" + "}" + ""; diff --git a/chrome/manifest.json b/chrome/manifest.json index ef205ea..8b32794 100644 --- a/chrome/manifest.json +++ b/chrome/manifest.json @@ -11,10 +11,16 @@ "128": "icons/icon128.png" }, + "permissions": ["storage"], + "action": { "default_icon": "icons/icon.png", "default_title": "Toggle Wide GitHub" }, + "options_ui": { + "page": "options.html", + "open_in_tab": false + }, "content_scripts": [ { "matches": ["https://github.com/*", "https://gist.github.com/*"], diff --git a/makecss.js b/makecss.js index eeea5a5..1250de4 100644 --- a/makecss.js +++ b/makecss.js @@ -21,12 +21,20 @@ var header = "" + "@version " + manifest["version"] + "\n" + "@homepageURL https://github.com/xthexder/wide-github\n" + "@supportURL https://github.com/xthexder/wide-github/issues\n" + +"@preprocessor default\n" + +"@var range wghFillPercent \"Whitespace to fill (%)\" [100, 0, 100, 5]\n" + "==/UserStyle== */\n" + "\n" + "@-moz-document regexp(\"^https://(?:gist\\\\.)?github\\\\.com/.*\") {\n" + "\n"; +// Stylus exposes the @var value as a --wghFillPercent custom property on :root. +// Reading it through var() here keeps this independent of where Stylus places +// its own :root block relative to this one. var footer = "" + +" :root {\n" + +" --wgh-fill-percent: var(--wghFillPercent);\n" + +" }\n" + "}\n" var styleSheet = fs.readFileSync('wide-github.css'); diff --git a/mozilla/manifest.json b/mozilla/manifest.json index 668d1fb..52ddcb0 100644 --- a/mozilla/manifest.json +++ b/mozilla/manifest.json @@ -16,10 +16,16 @@ } }, + "permissions": ["storage"], + "browser_action": { "default_icon": "icons/icon.png", "default_title": "Toggle Wide GitHub" }, + "options_ui": { + "page": "options.html", + "open_in_tab": false + }, "content_scripts": [ { "matches": ["https://github.com/*", "https://gist.github.com/*"], diff --git a/options.html b/options.html new file mode 100644 index 0000000..e1179ef --- /dev/null +++ b/options.html @@ -0,0 +1,81 @@ + + + + + Wide GitHub Options + + + +

Wide GitHub

+ + +
+ + 100% +
+

+ How much of the unused space each side of the page to fill. + 100% uses the full window width; 40% fills 40% of the unused space + and keeps the remaining 60% as margin down each side. +

+

+ Pages are never made narrower than GitHub's own layout, so this has + no effect on windows narrower than 1280px. +

+ + + + diff --git a/options.js b/options.js new file mode 100644 index 0000000..6e64b82 --- /dev/null +++ b/options.js @@ -0,0 +1,23 @@ +var DEFAULT_FILL_PERCENT = 100; + +var slider = document.getElementById('fill-percent'); +var readout = document.getElementById('fill-percent-value'); + +function render(percent) { + slider.value = percent; + readout.textContent = percent + "%"; +} + +chrome.storage.sync.get({fillPercent: DEFAULT_FILL_PERCENT}, function(items) { + render(items.fillPercent); +}); + +// Update the readout while dragging, but only write on release to stay well +// under chrome.storage.sync's write rate quota. +slider.addEventListener('input', function() { + readout.textContent = slider.value + "%"; +}); + +slider.addEventListener('change', function() { + chrome.storage.sync.set({fillPercent: parseInt(slider.value, 10)}); +}); diff --git a/wide-github-toggle.js b/wide-github-toggle.js index 53c87e1..828c357 100644 --- a/wide-github-toggle.js +++ b/wide-github-toggle.js @@ -6,8 +6,22 @@ function setDisabledClass(obj) { } } +function setFillPercent(percent) { + document.documentElement.style.setProperty('--wgh-fill-percent', percent); +} + chrome.runtime.onMessage.addListener((request, sender, callback) => { setDisabledClass(request); }); chrome.runtime.sendMessage({reload: true}, setDisabledClass); + +chrome.storage.sync.get({fillPercent: 100}, (items) => { + setFillPercent(items.fillPercent); +}); + +chrome.storage.onChanged.addListener((changes) => { + if (changes.fillPercent) { + setFillPercent(changes.fillPercent.newValue); + } +}); diff --git a/wide-github.css b/wide-github.css index c142d97..bc8f326 100644 --- a/wide-github.css +++ b/wide-github.css @@ -1,11 +1,20 @@ +/* Percentage (0-100) of the unused horizontal whitespace to fill. */ +/* 100 fills the window completely, 40 fills 40% of the whitespace */ +/* and keeps 60% of it split down each side of the content. */ +:root { + --wgh-fill-percent: 100; + --wgh-base-width: 1280px; + --wgh-max-width: max(var(--wgh-base-width), calc(var(--wgh-base-width) + (100vw - var(--wgh-base-width)) * var(--wgh-fill-percent) / 100)); +} + /* General full-page container */ body:not(.wgh-disabled) .application-main .container-xl { - max-width: none !important; + max-width: var(--wgh-max-width) !important; } /* General content sub-container */ body:not(.wgh-disabled) .application-main .container-lg { - max-width: none !important; - margin-left: 0px !important; + max-width: var(--wgh-max-width) !important; + margin-left: auto !important; } /* Repository home sidebar */ @@ -15,7 +24,7 @@ body:not(.wgh-disabled) .react-repos-overview-margin { /* Commit History and Branches page */ body:not(.wgh-disabled) #js-repo-pjax-container div[style^="--sticky-pane-height:"] > div[class^='Box-sc-']:first-child { - max-width: none; + max-width: var(--wgh-max-width); } /* Repository Tags page */ @@ -32,60 +41,60 @@ body:not(.wgh-disabled) #js-repo-pjax-container .js-issue-row .text-right { /* Issues list page */ body:not(.wgh-disabled) .application-main div[style^="--sticky-pane-height:"] > div[class^='Box-sc-'] > div[class^='Box-sc-'] > div[class^='Box-sc-'] > div[class^='Box-sc-']:nth-child(2) > div[class^='Box-sc-'] { - max-width: none; + max-width: var(--wgh-max-width); } /* Issue page */ body:not(.wgh-disabled) #js-repo-pjax-container div[data-target="react-app.reactRoot"] > div[class^='Box-sc-'] > div[class^='Box-sc-'] > div[class^='Box-sc-'] > div[class^='Box-sc-'] { - max-width: none; + max-width: var(--wgh-max-width); } /* New React layout (2025) */ /* Issues list page */ body:not(.wgh-disabled) .application-main div[data-target="react-app.reactRoot"] div[class^='prc-PageLayout-Content-'] > div[class^='Box-sc-'] { - max-width: none; + max-width: var(--wgh-max-width); } /* Issues list page (July 2025) */ body:not(.wgh-disabled) .application-main div[data-target="react-app.reactRoot"] div[class^='ThreePanesLayout-module__ThreePanesLayoutMiddleOnlyPane-'] { - max-width: none; + max-width: var(--wgh-max-width); } /* Issues list page (Feb 2026) */ body:not(.wgh-disabled) .application-main div[data-target="react-app.reactRoot"] div[class^='ThreePanesLayout-module__ThreePanesLayoutMiddleOnlyPane__'] { - max-width: none; + max-width: var(--wgh-max-width); } /* Issue page */ body:not(.wgh-disabled) .application-main div[data-target="react-app.reactRoot"] > div[class^='Box-sc-'] > div[class^='Box-sc-'] > div[class^='Box-sc-'] > div[class^='Box-sc-'] { - max-width: none; + max-width: var(--wgh-max-width); } /* Issue page (July 2025) */ body:not(.wgh-disabled) .application-main div[data-target="react-app.reactRoot"] div[class^='IssueViewer-module__issueViewerContainer-'] > div[class^='Box-sc-'] { - max-width: none; + max-width: var(--wgh-max-width); } /* Issue page (Jan 2026) */ body:not(.wgh-disabled) .application-main div[data-target="react-app.reactRoot"] div[class^='ContentWrapper-module__contentContainer--'] { - max-width: none; + max-width: var(--wgh-max-width); } /* Issue page (Feb 2026) */ body:not(.wgh-disabled) .application-main div[data-target="react-app.reactRoot"] div[class^='prc-PageLayout-Content-'] { - max-width: none; + max-width: var(--wgh-max-width); } body:not(.wgh-disabled) .application-main div[data-target="react-app.reactRoot"] div[class^='ContentWrapper-module__contentContainer__'] { - max-width: none; + max-width: var(--wgh-max-width); } /* New issue page */ body:not(.wgh-disabled) .application-main div[data-target="react-app.reactRoot"] div[class^='IssueCreatePage-module__createPaneContainer-'] { - max-width: none; + max-width: var(--wgh-max-width); } /* Commit list page */ body:not(.wgh-disabled) .application-main div[data-target="react-app.reactRoot"] div[class^='prc-PageLayout-PageLayoutWrapper-'] { - max-width: none; + max-width: var(--wgh-max-width); } /* PR Page (May 2026) */ body:not(.wgh-disabled) .application-main div[data-target="react-app.reactRoot"] div[class^='prc-PageLayout-ContentWrapper'] { - max-width: none; + max-width: var(--wgh-max-width); }