search_ember_docs
Search across Ember.js API docs, guides, and community content to find official documentation for your queries.
Instructions
Search through Ember.js documentation including API docs, guides, and community content. Returns relevant documentation with links to official sources. Use this for general queries about Ember concepts, features, or usage.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | Search query (e.g., 'component lifecycle', 'tracked properties', 'routing') | |
| category | No | Filter by documentation category (default: all) | |
| limit | No | Maximum number of results (default: 5) |
Implementation Reference
- lib/documentation-service.js:214-314 (helper)Core search logic in DocumentationService. Filters sections by category, scores results by relevance (exact phrase, title match, term frequency, all-terms presence, proximity), generates excerpts and URLs, and returns top results sorted by score.
async search(query, category = "all", limit = 5) { const results = []; const queryLower = query.toLowerCase(); const searchTerms = queryLower.split(/\s+/).filter(term => term.length > 0); const sectionsToSearch = category === "all" ? Object.keys(this.sections) : category === "api" ? ["api-docs"] : category === "guides" ? Object.keys(this.sections).filter( (s) => !["api-docs", "community-bloggers"].includes(s) ) : category === "community" ? ["community-bloggers"] : []; for (const sectionName of sectionsToSearch) { const sectionItems = this.sections[sectionName] || []; for (const item of sectionItems) { const content = item.content.toLowerCase(); const title = this.extractTitle(item.content); const titleLower = title.toLowerCase(); // Calculate relevance score with better weighting let score = 0; let matchedTerms = []; let termPositions = []; // Exact phrase match - highest value if (content.includes(queryLower)) { score += SEARCH_CONFIG.EXACT_PHRASE_BONUS; matchedTerms.push(queryLower); } // Check each term searchTerms.forEach((term) => { const matches = (content.match(new RegExp(term, "gi")) || []).length; if (matches > 0) { matchedTerms.push(term); // Title matches are highly relevant if (titleLower.includes(term)) { score += SEARCH_CONFIG.TITLE_MATCH_BONUS; } // Base score for term presence score += matches * SEARCH_CONFIG.TERM_MATCH_WEIGHT; // Find first position of this term for proximity scoring const pos = content.indexOf(term); if (pos !== -1) { termPositions.push({ term, pos }); } } }); // All terms present - significant bonus if (matchedTerms.length === searchTerms.length) { score += SEARCH_CONFIG.ALL_TERMS_BONUS; // Proximity bonus: terms close together are more relevant if (termPositions.length > 1) { termPositions.sort((a, b) => a.pos - b.pos); const spread = termPositions[termPositions.length - 1].pos - termPositions[0].pos; // If all terms within proximity threshold, add proximity bonus if (spread < SEARCH_CONFIG.PROXIMITY_THRESHOLD) { score += Math.floor((SEARCH_CONFIG.PROXIMITY_THRESHOLD - spread) / SEARCH_CONFIG.PROXIMITY_BONUS_DIVISOR); } } } // Only include results with meaningful matches // Require at least 2 terms or a high-value single match if (score >= SEARCH_CONFIG.MIN_SCORE && (matchedTerms.length >= 2 || score >= SEARCH_CONFIG.MIN_SCORE_SINGLE_TERM)) { const excerpt = this.extractExcerpt(item.content, searchTerms, termPositions); // Check if this result is for a deprecated API const deprecationInfo = this.deprecationManager.checkSearchResult({ title, content: item.content }); results.push({ title, category: this.categorizeSectionName(sectionName), excerpt, score, url: generateUrl(sectionName, title), apiLink: generateApiLink(item.content), matchedTerms: matchedTerms.length, totalTerms: searchTerms.length, deprecationInfo: deprecationInfo, }); } } } // Sort by score and return top results results.sort((a, b) => b.score - a.score); return results.slice(0, limit); } - lib/formatters.js:14-57 (helper)Helper function that formats search results into markdown. Includes title, category, match quality, deprecation warnings, excerpt, URL, and API reference links for each result.
export function formatSearchResults(results, deprecationManager) { let output = `# Ember Documentation Search Results\n\n`; output += `Found ${results.length} result(s):\n\n`; results.forEach((result, index) => { output += `## ${index + 1}. ${result.title}`; // Add deprecation indicator if applicable if (result.deprecationInfo && result.deprecationInfo.status !== 'possibly-deprecated') { output += ` ${deprecationManager.generateWarning(result.title, 'short')}`; } output += `\n\n`; output += `**Category:** ${result.category}`; // Show match quality if (result.matchedTerms !== undefined && result.totalTerms !== undefined) { output += ` | **Match:** ${result.matchedTerms}/${result.totalTerms} terms`; } if (result.score !== undefined) { output += ` (relevance: ${result.score})`; } output += `\n\n`; // Add inline deprecation warning if applicable if (result.deprecationInfo && result.deprecationInfo.status !== 'possibly-deprecated') { output += `${deprecationManager.generateWarning(result.title, 'inline')}\n\n`; } output += `${result.excerpt}\n\n`; if (result.url) { output += `**Link:** ${result.url}\n\n`; } if (result.apiLink) { output += `**API Reference:** ${result.apiLink}\n\n`; } output += `---\n\n`; }); return output; }