import { escapeHtml, sanitizeUrl } from "../utils"; export interface Language { id: string; name: string; icon: string; extension: string; } export interface RecipeVariant { doc: string; example: string | null; } export interface Recipe { id: string; name: string; description: string; tags: string[]; languages: string[]; variants: Record; external?: boolean; url?: string | null; author?: { name: string; url?: string } | null; } export interface Cookbook { id: string; name: string; description: string; path: string; featured: boolean; languages: Language[]; recipes: Recipe[]; } export interface CookbookRecipeMatch { cookbook: Cookbook; recipe: Recipe; highlightedName?: string; } export function getRecipeResultsCountText( filteredCount: number, totalCount: number ): string { if (filteredCount === totalCount) { return `${totalCount} recipe${totalCount !== 1 ? "s" : ""}`; } return `${filteredCount} of ${totalCount} recipe${ totalCount !== 1 ? "s" : "" }`; } export function renderCookbookSectionsHtml( matches: CookbookRecipeMatch[], options: { selectedLanguage?: string | null; } = {} ): string { if (matches.length === 0) { return `

No Results Found

Try adjusting your search or filters.

`; } const { selectedLanguage = null } = options; const byCookbook = new Map< string, { cookbook: Cookbook; recipes: { recipe: Recipe; highlightedName?: string }[] } >(); matches.forEach(({ cookbook, recipe, highlightedName }) => { if (!byCookbook.has(cookbook.id)) { byCookbook.set(cookbook.id, { cookbook, recipes: [] }); } byCookbook.get(cookbook.id)?.recipes.push({ recipe, highlightedName }); }); let html = ""; byCookbook.forEach(({ cookbook, recipes }) => { html += renderCookbookSection(cookbook, recipes, selectedLanguage); }); return html; } function renderCookbookSection( cookbook: Cookbook, recipes: { recipe: Recipe; highlightedName?: string }[], selectedLanguage: string | null ): string { const languageTabs = cookbook.languages .map( (language) => ` ` ) .join(""); const recipeCards = recipes .map(({ recipe, highlightedName }) => renderRecipeCard(cookbook, recipe, selectedLanguage, highlightedName) ) .join(""); return `

${escapeHtml(cookbook.name)}

${escapeHtml(cookbook.description)}

${languageTabs}
${recipeCards}
`; } function renderRecipeCard( cookbook: Cookbook, recipe: Recipe, selectedLanguage: string | null, highlightedName?: string ): string { const recipeKey = `${cookbook.id}-${recipe.id}`; const tags = recipe.tags .map((tag) => `${escapeHtml(tag)}`) .join(""); const titleHtml = highlightedName || escapeHtml(recipe.name); if (recipe.external && recipe.url) { const authorHtml = recipe.author ? `by ${ recipe.author.url ? `${escapeHtml( recipe.author.name )}` : escapeHtml(recipe.author.name) }` : ""; return `

${titleHtml}

Community

${escapeHtml(recipe.description)}

${authorHtml ? `
${authorHtml}
` : ""}
${tags}
`; } const displayLanguage = selectedLanguage || cookbook.languages?.[0]?.id || "nodejs"; const variant = recipe.variants[displayLanguage]; const langIndicators = (cookbook.languages ?? []) .filter((language) => recipe.variants[language.id]) .map( (language) => `${escapeHtml( language.icon )}` ) .join(""); return `

${titleHtml}

${langIndicators}

${escapeHtml(recipe.description)}

${tags}
${ variant ? ` ${ variant.example ? ` ` : "" } GitHub ` : 'Not available for selected language' }
`; }