-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Make 404 pages more useful #1558
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
19 commits
Select commit
Hold shift + click to select a range
a616c8b
Add more useful 404 page feature
dertieran ad2baf4
Check if the href of the anchor is reachable
dertieran 83ca869
Replace file links with more useful commit history
dertieran 6541347
Make feature more general
dertieran 719c163
Various improvements
fregante 67852be
Add link to commit history
fregante af8d1cc
Fix cache.getSet
fregante 2507a80
Add default branch API getter
fregante 4aee828
Fetch default branch for the branch buttons
fregante 1c22343
Avoid merge conflict
fregante 869e08b
Repetition kills you
fregante adaf0f2
Merge branch 'default-branch-api' into DerTieran-useful-404-page
fregante 0645f9b
Add link to files on default branch
fregante 63548c8
Avoid / before user name
fregante 10e5e82
Mention in readme
fregante a6b7ccb
Skip checking the last part, it's always a 404
fregante dd085c2
Add some comments
fregante 6153252
Update useful-not-found-page.js
sindresorhus fadea7a
Review changes
fregante File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,104 @@ | ||
| /* | ||
| This feature adds more useful 404 (not found) page. | ||
| - Display the full URL clickable piece by piece | ||
| - Strikethrough all anchor that return a 404 status code | ||
| */ | ||
|
|
||
| import {h} from 'dom-chef'; | ||
| import select from 'select-dom'; | ||
| import {getCleanPathname} from '../libs/page-detect'; | ||
| import getDefaultBranch from '../libs/get-default-branch'; | ||
|
|
||
| async function is404(url) { | ||
| const {status} = await fetch(url, {method: 'head'}); | ||
| return status === 404; | ||
| } | ||
|
|
||
| function getStrikeThrough(text) { | ||
| return <del style={{color: '#6a737d'}}>{text}</del>; | ||
| } | ||
|
|
||
| async function checkAnchor(anchor) { | ||
| if (await is404(anchor.href)) { | ||
| anchor.replaceWith(getStrikeThrough(anchor.textContent)); | ||
| } | ||
| } | ||
|
|
||
| function parseCurrentURL() { | ||
| const parts = getCleanPathname().split('/'); | ||
| if (parts[2] === 'blob') { // Blob URLs are never useful | ||
| parts[2] = 'tree'; | ||
| } | ||
| return parts; | ||
| } | ||
|
|
||
| // If the resource was deleted, link to the commit history | ||
| async function addCommitHistoryLink(bar) { | ||
| const parts = parseCurrentURL(); | ||
| if (parts[2] !== 'tree') { | ||
| return; | ||
| } | ||
| parts[2] = 'commits'; | ||
| const url = '/' + parts.join('/'); | ||
| if (await is404(url)) { | ||
| return; | ||
| } | ||
| bar.after( | ||
| <p class="container"> | ||
| See also the file’s {<a href={url}>commit history</a>} | ||
| </p> | ||
| ); | ||
| } | ||
|
|
||
| // If the resource exists in the default branch, link to it | ||
| async function addDefaultBranchLink(bar) { | ||
| const parts = getCleanPathname().split('/'); | ||
| const branch = parts[3]; | ||
| if (!branch) { | ||
| return; | ||
| } | ||
| const defaultBranch = await getDefaultBranch(); | ||
| if (!defaultBranch || branch === defaultBranch) { | ||
| return; | ||
| } | ||
| parts[3] = defaultBranch; // Change branch | ||
| const url = '/' + parts.join('/'); | ||
| if (await is404(url)) { | ||
| return; | ||
| } | ||
| bar.after( | ||
| <p class="container"> | ||
| See also the file on the {<a href={url}>default branch</a>} | ||
| </p> | ||
| ); | ||
| } | ||
|
|
||
| export default function () { | ||
| const parts = parseCurrentURL(); | ||
| const bar = <h2 class="container"/>; | ||
|
|
||
| for (const [i, part] of parts.entries()) { | ||
| if (i === 2 && part === 'tree') { | ||
| // `/tree/` is not a real part of the URL | ||
| continue; | ||
| } | ||
| if (i === parts.length - 1) { | ||
| // The last part of the URL is a known 404 | ||
| bar.append(' / ', getStrikeThrough(part)); | ||
| } else { | ||
| const pathname = '/' + parts.slice(0, i + 1).join('/'); | ||
| bar.append(i ? ' / ' : '', <a href={pathname}>{part}</a>); | ||
| } | ||
| } | ||
|
|
||
| // NOTE: We need to append it after the parallax_wrapper because other elements might not be available yet. | ||
| select('#parallax_wrapper').after(bar); | ||
|
|
||
| // Check parts from right to left; skip the last part | ||
| for (let i = bar.children.length - 2; i >= 0; i--) { | ||
| checkAnchor(bar.children[i]); | ||
| } | ||
|
|
||
| addCommitHistoryLink(bar); | ||
| addDefaultBranchLink(bar); | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| import select from 'select-dom'; | ||
| import * as cache from './cache'; | ||
| import * as api from './api'; | ||
| import {getOwnerAndRepo} from './page-detect'; | ||
|
|
||
| // This regex should match all of these combinations: | ||
| // "This branch is even with master." | ||
| // "This branch is 1 commit behind master." | ||
| // "This branch is 1 commit ahead of master." | ||
| // "This branch is 1 commit ahead, 27 commits behind master." | ||
| const branchInfoRegex = /([^ ]+)\.$/; | ||
|
|
||
| function parseBranchFromDom() { | ||
| if (select.exists('.repohead h1 .octicon-repo-forked')) { | ||
| return; // It's a fork, no "default branch" info available #1132 | ||
| } | ||
|
|
||
| // We can find the name in the infobar, available in folder views | ||
| const branchInfo = select('.branch-infobar'); | ||
| if (!branchInfo) { | ||
| return; | ||
| } | ||
|
|
||
| // Parse the infobar | ||
| const [, branchName] = branchInfo.textContent.trim().match(branchInfoRegex) || []; | ||
| return branchName; // `string` or undefined | ||
| } | ||
|
|
||
| async function fetchFromApi(user, repo) { | ||
| const response = await api.v3(`repos/${user}/${repo}`); | ||
| if (response && response.default_branch) { | ||
| return response.default_branch; | ||
| } | ||
| } | ||
|
|
||
| export default function () { | ||
| const {ownerName, repoName} = getOwnerAndRepo(); | ||
| return cache.getSet(`default-branch:${ownerName}/${repoName}`, | ||
| () => parseBranchFromDom() || fetchFromApi(ownerName, repoName) | ||
| ); | ||
| } |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Small nitpick if the user is not found then the slash is appended.
Is that intended?