forked from squidfunk/mkdocs-material
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fixes to "staying on the same page functionality"
This is squidfunk#7350 with the tests removed, as requested in squidfunk#7350 (comment) . I do urge you to reconsider and merge something like squidfunk#7350 (including the tests I wrote) instead. Without tests, I suspect this code will break like its [previous version did]( squidfunk@ceacfe5) . Once the code does break, it might be difficult to fix without tests. Even if other parts of the theme work without tests, and even if you aren't in love with how I set up the infrastructure in squidfunk#7350 or squidfunk#7338, I think this logic is complex enough to need tests to be maintainable. Again, I wouldn't be able to check this code's correctness without the tests that aren't included in this PR. Of course, this is your project to maintain, so do what works best for you. I just hope this bugfix helps. --------------------- Fixes squidfunk#7226 Additionally, this allows using the version switcher even if the website is published at a different URL than the `site_url`. In particular, the version switcher should now work locally when serving the site with `mike serve`.
- Loading branch information
Showing
3 changed files
with
117 additions
and
13 deletions.
There are no files selected for viewing
This file contains 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
102 changes: 102 additions & 0 deletions
102
src/templates/assets/javascripts/integrations/version/correspondingPage.ts
This file contains 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,102 @@ | ||
import { Sitemap } from "../sitemap" | ||
|
||
type CorrespondingURLParams = { | ||
selectedVersionSitemap: Sitemap | ||
selectedVersionBaseURL: URL | ||
currentLocation: URL | ||
currentBaseURL: string | ||
} | ||
|
||
/** | ||
* Choose a URL to navigate to when the user chooses a version in the version | ||
* selector. | ||
* | ||
* @param selectedVersionSitemap - as obtained by fetchSitemap from `${selectedVersionBaseURL}/sitemap.xml` | ||
* @param selectedVersionBaseURL - usually `${currentBaseURL}/../selectedVersion` | ||
* @param currentLocation - current web browser location | ||
* @param currentBaseURL - as obtained from `config.base` | ||
* @returns the URL to navigate to or null if we can't be sure that the | ||
* corresponding page to the current page exists in the selected version | ||
*/ | ||
export function selectedVersionCorrespondingURL( | ||
{selectedVersionSitemap, | ||
selectedVersionBaseURL, | ||
currentLocation, | ||
currentBaseURL}: CorrespondingURLParams | ||
): URL | undefined { | ||
const current_path = (new URL(currentBaseURL)).pathname | ||
const currentRelativePath = stripPrefix(currentLocation.pathname, current_path) | ||
if (currentRelativePath === undefined) { | ||
return | ||
} | ||
const sitemapCommonPrefix = shortestCommonPrefix(selectedVersionSitemap.keys()) | ||
if (!selectedVersionSitemap.has(sitemapCommonPrefix)) { | ||
// We could also check that `commonSitemapPrefix` ends in the canonical version, | ||
// similarly to https://github.com/squidfunk/mkdocs-material/pull/7227. However, | ||
// I don't believe that Mike/MkDocs ever generate sitemaps where it would matter | ||
return | ||
} | ||
|
||
const potentialSitemapURL = new URL(currentRelativePath, sitemapCommonPrefix) | ||
if (!selectedVersionSitemap.has(potentialSitemapURL.href)) { | ||
return | ||
} | ||
|
||
const result = new URL(currentRelativePath, selectedVersionBaseURL) | ||
result.hash = currentLocation.hash | ||
result.search = currentLocation.search | ||
return result | ||
} | ||
|
||
// Basic string manipulation | ||
|
||
/** | ||
* | ||
* @param s - string | ||
* @param prefix - prefix to strip | ||
* | ||
* @returns either the string with the prefix stripped or undefined if the | ||
* string did not begin with the prefix. | ||
*/ | ||
export function stripPrefix(s: string, prefix: string): string | undefined { | ||
if (s.startsWith(prefix)) { | ||
return s.slice(prefix.length) | ||
} | ||
return undefined | ||
} | ||
|
||
/** | ||
* | ||
* @param s1 - first string | ||
* @param s2 - second string | ||
* | ||
* @returns - the length of the longest common prefix of the two strings. | ||
*/ | ||
function commonPrefixLen(s1: string, s2: string): number { | ||
const max = Math.min(s1.length, s2.length) | ||
let result | ||
for (result = 0; result < max; ++result) { | ||
if (s1[result] !== s2[result]) { | ||
break | ||
} | ||
} | ||
return result | ||
} | ||
|
||
/** | ||
* | ||
* @param strs - an iterable of strings | ||
* | ||
* @returns the longest common prefix of all the strings | ||
*/ | ||
export function shortestCommonPrefix(strs: Iterable<string>): string { | ||
let result // Undefined if no iterations happened | ||
for (const s of strs) { | ||
if (result === undefined) { | ||
result = s | ||
} else { | ||
result = result.slice(0, commonPrefixLen(result, s)) | ||
} | ||
} | ||
return result ?? "" | ||
} |
This file contains 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