|
3 | 3 | const STORAGE_KEY = 'slime-doc-lang'; |
4 | 4 | const AVAILABLE = ['en','zh']; |
5 | 5 | function detectCurrent(){ |
6 | | - const parts = window.location.pathname.split('/').filter(Boolean); |
7 | | - if(parts.length>0 && AVAILABLE.includes(parts[0])) return parts[0]; |
| 6 | + const { parts, langIndex } = analyzePath(); |
| 7 | + if(langIndex !== -1) return parts[langIndex]; |
8 | 8 | return 'en'; |
9 | 9 | } |
10 | 10 | function otherLang(lang){ return lang === 'en' ? 'zh' : 'en'; } |
| 11 | + /** |
| 12 | + * Analyze current pathname to figure out repo root + language segment pattern. |
| 13 | + * Supports patterns: |
| 14 | + * /en/… (language as first segment) |
| 15 | + * /slime/en/… (GitHub Pages project site repo root, language second) |
| 16 | + * /slime/ (no lang yet) -> insert /slime/zh/ |
| 17 | + * / (no lang) -> insert /zh/ |
| 18 | + */ |
| 19 | + function analyzePath(){ |
| 20 | + const rawParts = window.location.pathname.split('/').filter(Boolean); |
| 21 | + let parts = rawParts.slice(); |
| 22 | + let repoRoot = null; |
| 23 | + let langIndex = -1; |
| 24 | + |
| 25 | + if(parts[0] && AVAILABLE.includes(parts[0])){ |
| 26 | + langIndex = 0; // /en/... |
| 27 | + } else if(parts.length > 1 && AVAILABLE.includes(parts[1])){ |
| 28 | + repoRoot = parts[0]; |
| 29 | + langIndex = 1; // /slime/en/... |
| 30 | + } else { |
| 31 | + // No explicit language; try to detect repo root (GitHub Pages typical) so we insert AFTER it. |
| 32 | + // Heuristic: if host ends with github.io OR first segment matches known repo name 'slime'. |
| 33 | + if(parts.length > 0 && (window.location.host.endsWith('github.io') || parts[0] === 'slime')){ |
| 34 | + repoRoot = parts[0]; |
| 35 | + } |
| 36 | + } |
| 37 | + return { parts, repoRoot, langIndex }; |
| 38 | + } |
| 39 | + |
11 | 40 | function buildTargetUrl(target){ |
12 | 41 | const url = new URL(window.location.href); |
13 | | - const parts = url.pathname.split('/').filter(Boolean); |
14 | | - if(parts.length === 0){ |
15 | | - url.pathname = `/${target}/`; |
16 | | - return url.toString(); |
| 42 | + const trailingSlash = url.pathname.endsWith('/') || url.pathname === '/'; |
| 43 | + const { parts, repoRoot, langIndex } = analyzePath(); |
| 44 | + |
| 45 | + if(langIndex === 0){ |
| 46 | + // replace first |
| 47 | + parts[0] = target; |
| 48 | + } else if(langIndex === 1){ |
| 49 | + parts[1] = target; // replace second (/repo/en/) |
| 50 | + } else if(repoRoot){ |
| 51 | + // insert after repo root |
| 52 | + if(parts.length === 1){ |
| 53 | + parts.push(target); // /repo/ -> /repo/zh/ |
| 54 | + } else { |
| 55 | + parts.splice(1, 0, target); |
| 56 | + } |
| 57 | + } else { |
| 58 | + // no repo root detected; put language first |
| 59 | + parts.unshift(target); |
17 | 60 | } |
18 | | - if(AVAILABLE.includes(parts[0])) parts[0] = target; else parts.unshift(target); |
19 | | - url.pathname = '/' + parts.join('/') + (url.pathname.endsWith('/') ? '' : ''); |
| 61 | + |
| 62 | + let newPath = '/' + parts.join('/'); |
| 63 | + // Add trailing slash if original had it and new path doesn't look like a file (no extension) |
| 64 | + if(trailingSlash && !/\.[a-zA-Z0-9]+$/.test(parts[parts.length-1] || '')) newPath += '/'; |
| 65 | + url.pathname = newPath; |
20 | 66 | return url.toString(); |
21 | 67 | } |
22 | 68 | function createButton(){ |
|
0 commit comments