|
467 | 467 | let entry = await this.lookup(word); |
468 | 468 | if (!entry) return null; |
469 | 469 |
|
470 | | - // Handle redirect |
471 | | - if (entry.r) { |
| 470 | + const originalWord = word; |
| 471 | + const redirectChain = [word]; |
| 472 | + const maxRedirects = 10; // Prevent infinite loops |
| 473 | + let redirectCount = 0; |
| 474 | + |
| 475 | + // Follow the redirect chain until we find a non-redirect entry |
| 476 | + while (entry.r && redirectCount < maxRedirects) { |
472 | 477 | const headword = entry.r; |
473 | | - const definition = await this.lookup(headword); |
474 | | - return { |
475 | | - searchWord: word, |
476 | | - headword: headword, |
477 | | - isRedirect: true, |
478 | | - data: definition |
479 | | - }; |
| 478 | + |
| 479 | + // Check for circular redirects |
| 480 | + if (redirectChain.includes(headword)) { |
| 481 | + console.warn(`Circular redirect detected: ${redirectChain.join(' → ')} → ${headword}`); |
| 482 | + break; |
| 483 | + } |
| 484 | + |
| 485 | + redirectChain.push(headword); |
| 486 | + const nextEntry = await this.lookup(headword); |
| 487 | + |
| 488 | + if (!nextEntry) { |
| 489 | + console.warn(`Redirect chain broken: ${headword} not found`); |
| 490 | + break; |
| 491 | + } |
| 492 | + |
| 493 | + entry = nextEntry; |
| 494 | + redirectCount++; |
480 | 495 | } |
481 | 496 |
|
482 | | - // Direct entry |
| 497 | + if (redirectCount >= maxRedirects) { |
| 498 | + console.warn(`Maximum redirect depth reached for word: ${originalWord}`); |
| 499 | + } |
| 500 | + |
| 501 | + // Get the final headword (last in the chain) |
| 502 | + const finalHeadword = redirectChain[redirectChain.length - 1]; |
| 503 | + const isRedirect = redirectChain.length > 1; |
| 504 | + |
| 505 | + // Direct entry or final redirect target |
483 | 506 | return { |
484 | | - searchWord: word, |
485 | | - headword: word, |
486 | | - isRedirect: false, |
| 507 | + searchWord: originalWord, |
| 508 | + headword: finalHeadword, |
| 509 | + isRedirect: isRedirect, |
| 510 | + redirectChain: isRedirect ? redirectChain : null, |
487 | 511 | data: entry |
488 | 512 | }; |
489 | 513 | } |
|
580 | 604 | this.hideLoading(); |
581 | 605 | } |
582 | 606 |
|
583 | | - showSuggestions(suggestions) { |
584 | | - this.suggestions.innerHTML = suggestions.map((item, index) => { |
585 | | - const isRedirect = item.data.r; |
| 607 | + async showSuggestions(suggestions) { |
| 608 | + // Resolve redirect chains for all suggestions |
| 609 | + const resolvedSuggestions = await Promise.all( |
| 610 | + suggestions.map(async (item) => { |
| 611 | + if (item.data.r) { |
| 612 | + // Use the existing resolveWord method to get the full chain |
| 613 | + const resolved = await this.loader.resolveWord(item.word); |
| 614 | + return { |
| 615 | + ...item, |
| 616 | + redirectChain: resolved.redirectChain, |
| 617 | + finalTarget: resolved.headword |
| 618 | + }; |
| 619 | + } |
| 620 | + return item; |
| 621 | + }) |
| 622 | + ); |
| 623 | + |
| 624 | + this.suggestions.innerHTML = resolvedSuggestions.map((item, index) => { |
| 625 | + const hasRedirect = item.redirectChain && item.redirectChain.length > 1; |
586 | 626 | return ` |
587 | | - <div class="suggestion-item" data-index="${index}" data-word="${item.word}"> |
588 | | - <span class="suggestion-word">${item.word}</span> |
589 | | - ${isRedirect ? `<span class="suggestion-redirect">→ ${item.data.r}</span>` : ''} |
590 | | - </div> |
591 | | - `; |
| 627 | + <div class="suggestion-item" data-index="${index}" data-word="${item.word}"> |
| 628 | + <span class="suggestion-word">${item.word}</span> |
| 629 | + ${hasRedirect ? `<span class="suggestion-redirect">→ ${item.redirectChain.slice(1).join(' → ')}</span>` : ''} |
| 630 | + </div>`; |
592 | 631 | }).join(''); |
593 | 632 |
|
594 | 633 | this.suggestions.classList.add('visible'); |
|
640 | 679 | let html = `<div class="definition-card"> |
641 | 680 | <div class="word-header"> |
642 | 681 | <h1 class="word-title">${result.headword}</h1> |
643 | | - ${result.isRedirect ? `<div class="word-redirect">${result.searchWord} → ${result.headword}</div>` : ''} |
| 682 | + ${result.isRedirect ? `<div class="word-redirect">${result.redirectChain ? result.redirectChain.join(' → ') : result.searchWord + ' → ' + result.headword}</div>` : ''} |
644 | 683 | <div class="word-meta">`; |
645 | 684 |
|
646 | 685 | // Add pronunciation if available |
|
0 commit comments