mirror of
https://github.com/github/awesome-copilot.git
synced 2026-02-21 10:55:13 +00:00
feat(website): add samples/cookbook page with recipe browser
Integrates the cookbook/ folder into the website's Samples page: Data Structure: - Add cookbook/cookbook.yml manifest defining cookbooks and recipes - Add .schemas/cookbook.schema.json for validation - Add COOKBOOK_DIR constant to eng/constants.mjs Build Integration: - Add generateSamplesData() to generate samples.json from cookbook.yml - Include recipe variants with file paths for each language - Add samples count to manifest.json Website UI: - Create samples.ts with FuzzySearch, language/tag filtering - Replace placeholder samples.astro with functional recipe browser - Recipe cards with language indicators and action buttons - Language tabs for switching between implementations - View Recipe/View Example buttons open modal - GitHub link for each recipe Features: - Search recipes by name/description - Filter by programming language (Node.js, Python, .NET, Go) - Filter by tags (multi-select with Choices.js) - 5 recipes across 4 languages = 20 recipe variants
This commit is contained in:
@@ -123,6 +123,7 @@ const PROMPTS_DIR = path.join(ROOT_FOLDER, "prompts");
|
||||
const AGENTS_DIR = path.join(ROOT_FOLDER, "agents");
|
||||
const SKILLS_DIR = path.join(ROOT_FOLDER, "skills");
|
||||
const COLLECTIONS_DIR = path.join(ROOT_FOLDER, "collections");
|
||||
const COOKBOOK_DIR = path.join(ROOT_FOLDER, "cookbook");
|
||||
const MAX_COLLECTION_ITEMS = 50;
|
||||
|
||||
// Agent Skills validation constants
|
||||
@@ -145,6 +146,7 @@ export {
|
||||
AGENTS_DIR,
|
||||
SKILLS_DIR,
|
||||
COLLECTIONS_DIR,
|
||||
COOKBOOK_DIR,
|
||||
MAX_COLLECTION_ITEMS,
|
||||
SKILL_NAME_MIN_LENGTH,
|
||||
SKILL_NAME_MAX_LENGTH,
|
||||
|
||||
@@ -16,6 +16,7 @@ import {
|
||||
PROMPTS_DIR,
|
||||
SKILLS_DIR,
|
||||
COLLECTIONS_DIR,
|
||||
COOKBOOK_DIR,
|
||||
ROOT_FOLDER,
|
||||
} from "./constants.mjs";
|
||||
import {
|
||||
@@ -559,6 +560,89 @@ function generateSearchIndex(agents, prompts, instructions, skills, collections)
|
||||
return index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate samples/cookbook data from cookbook.yml
|
||||
*/
|
||||
function generateSamplesData() {
|
||||
const cookbookYamlPath = path.join(COOKBOOK_DIR, "cookbook.yml");
|
||||
|
||||
if (!fs.existsSync(cookbookYamlPath)) {
|
||||
console.warn("Warning: cookbook/cookbook.yml not found, skipping samples generation");
|
||||
return { cookbooks: [], totalRecipes: 0, totalCookbooks: 0, filters: { languages: [], tags: [] } };
|
||||
}
|
||||
|
||||
const cookbookManifest = parseYamlFile(cookbookYamlPath);
|
||||
if (!cookbookManifest || !cookbookManifest.cookbooks) {
|
||||
console.warn("Warning: Invalid cookbook.yml format");
|
||||
return { cookbooks: [], totalRecipes: 0, totalCookbooks: 0, filters: { languages: [], tags: [] } };
|
||||
}
|
||||
|
||||
const allLanguages = new Set();
|
||||
const allTags = new Set();
|
||||
let totalRecipes = 0;
|
||||
|
||||
const cookbooks = cookbookManifest.cookbooks.map(cookbook => {
|
||||
// Collect languages
|
||||
cookbook.languages.forEach(lang => allLanguages.add(lang.id));
|
||||
|
||||
// Process recipes and add file paths
|
||||
const recipes = cookbook.recipes.map(recipe => {
|
||||
// Collect tags
|
||||
if (recipe.tags) {
|
||||
recipe.tags.forEach(tag => allTags.add(tag));
|
||||
}
|
||||
|
||||
// Build variants with file paths for each language
|
||||
const variants = {};
|
||||
cookbook.languages.forEach(lang => {
|
||||
const docPath = `${cookbook.path}/${lang.id}/${recipe.id}.md`;
|
||||
const examplePath = `${cookbook.path}/${lang.id}/recipe/${recipe.id}${lang.extension}`;
|
||||
|
||||
// Check if files exist
|
||||
const docFullPath = path.join(ROOT_FOLDER, docPath);
|
||||
const exampleFullPath = path.join(ROOT_FOLDER, examplePath);
|
||||
|
||||
if (fs.existsSync(docFullPath)) {
|
||||
variants[lang.id] = {
|
||||
doc: docPath,
|
||||
example: fs.existsSync(exampleFullPath) ? examplePath : null
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
totalRecipes++;
|
||||
|
||||
return {
|
||||
id: recipe.id,
|
||||
name: recipe.name,
|
||||
description: recipe.description,
|
||||
tags: recipe.tags || [],
|
||||
variants
|
||||
};
|
||||
});
|
||||
|
||||
return {
|
||||
id: cookbook.id,
|
||||
name: cookbook.name,
|
||||
description: cookbook.description,
|
||||
path: cookbook.path,
|
||||
featured: cookbook.featured || false,
|
||||
languages: cookbook.languages,
|
||||
recipes
|
||||
};
|
||||
});
|
||||
|
||||
return {
|
||||
cookbooks,
|
||||
totalRecipes,
|
||||
totalCookbooks: cookbooks.length,
|
||||
filters: {
|
||||
languages: Array.from(allLanguages).sort(),
|
||||
tags: Array.from(allTags).sort()
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Main function
|
||||
*/
|
||||
@@ -592,6 +676,9 @@ async function main() {
|
||||
const tools = toolsData.items;
|
||||
console.log(`✓ Generated ${tools.length} tools (${toolsData.filters.categories.length} categories)`);
|
||||
|
||||
const samplesData = generateSamplesData();
|
||||
console.log(`✓ Generated ${samplesData.totalRecipes} recipes in ${samplesData.totalCookbooks} cookbooks (${samplesData.filters.languages.length} languages, ${samplesData.filters.tags.length} tags)`);
|
||||
|
||||
const searchIndex = generateSearchIndex(agents, prompts, instructions, skills, collections);
|
||||
console.log(`✓ Generated search index with ${searchIndex.length} items`);
|
||||
|
||||
@@ -626,6 +713,11 @@ async function main() {
|
||||
JSON.stringify(toolsData, null, 2)
|
||||
);
|
||||
|
||||
fs.writeFileSync(
|
||||
path.join(WEBSITE_DATA_DIR, "samples.json"),
|
||||
JSON.stringify(samplesData, null, 2)
|
||||
);
|
||||
|
||||
fs.writeFileSync(
|
||||
path.join(WEBSITE_DATA_DIR, "search-index.json"),
|
||||
JSON.stringify(searchIndex, null, 2)
|
||||
@@ -641,6 +733,7 @@ async function main() {
|
||||
skills: skills.length,
|
||||
collections: collections.length,
|
||||
tools: tools.length,
|
||||
samples: samplesData.totalRecipes,
|
||||
total: searchIndex.length,
|
||||
},
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user