Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions scripts/generate-android-studio-bundle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# Generating Android Studio Skills Bundle

This guide covers the process of generating a limited version of Firebase skills for Android Studio and publishing them to the `android-studio-bundle` branch.

## Instructions for the Operator (Human or AI)

Follow these steps to regenerate the bundle and update the branch:

### 1. Run the Generation Script
Run the following command from the root of the repository on the `main` branch:
```bash
node scripts/generate_android_skills.js
```
This will create a directory `android-skills/` with the filtered skills.

### 2. Clean Up Content with LLM
Use the following prompt with an LLM to clean up the markdown files in `android-skills/` to remove dangling references and fix grammar.

#### Prompt for LLM Cleanup
```text
You are an AI assistant helping to create a limited version of Firebase skills for Android Studio.
Your task is to clean up the provided markdown file to make it focused on Android and remove broken links or dangling text left by a filtering process.

Instructions:
1. Remove any remaining links to files that have been deleted (iOS, Web, Flutter specific files).
2. Remove lines, bullet points, or sections that are exclusively about iOS, Web, or Flutter if they are left empty or dangling after link removal.
3. Rewrite sentences that list multiple platforms to only include Android (and shared platforms like Unity if relevant), ensuring correct grammar.
4. Do NOT remove content that is generic or applicable to all platforms unless it is part of a broken list.
5. Ensure the remaining text is grammatically correct and flows naturally.

Here is the file content:
[Insert file content here]
```

Apply this to all `.md` files in `android-skills/` that need cleanup (especially `SKILL.md` files).

### 3. Prepare the Branch
1. Check out a new branch from `android-studio-bundle` (or create it if it doesn't exist):
```bash
git checkout android-studio-bundle
git checkout -b update-android-bundle
```
2. Replace the content of the `skills/` directory with the content of `android-skills/`:
```bash
rm -rf skills/*
cp -r android-skills/* skills/
```
3. Commit the changes:
```bash
git add skills/
git commit -m "Update Android Studio skills bundle"
```

### 4. Open a Pull Request
1. Push the branch:
```bash
git push origin update-android-bundle
```
2. Open a Pull Request against the `android-studio-bundle` branch.

---
Note: The script `generate_android_skills.js` and this guide live on the `main` branch. The generated content lives on the `android-studio-bundle` branch in the `skills/` directory.
127 changes: 127 additions & 0 deletions scripts/generate_android_skills.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
const fs = require('fs');
const path = require('path');

const SOURCE_DIR = path.join(__dirname, '../skills');
const TARGET_DIR = path.join(__dirname, '../android-skills');

const EXCLUDED_SKILLS = [
'developing-genkit-dart',
'developing-genkit-go',
'developing-genkit-js',
'developing-genkit-python',
'xcode-project-setup',
'firebase-hosting-basics',
'firebase-app-hosting-basics'
];

const EXCLUDED_FILE_PATTERNS = [
/ios/i,
/web/i,
/flutter/i
];

function deleteFolderRecursive(directoryPath) {
if (fs.existsSync(directoryPath)) {
fs.readdirSync(directoryPath).forEach((file, index) => {
const curPath = path.join(directoryPath, file);
if (fs.lstatSync(curPath).isDirectory()) {
deleteFolderRecursive(curPath);
} else {
fs.unlinkSync(curPath);
}
});
fs.rmdirSync(directoryPath);
}
}

function copyRecursive(src, dest) {
const exists = fs.existsSync(src);
const stats = exists && fs.statSync(src);
const isDirectory = exists && stats.isDirectory();

if (isDirectory) {
if (!fs.existsSync(dest)) {
fs.mkdirSync(dest);
}
fs.readdirSync(src).forEach((childItemName) => {
copyRecursive(path.join(src, childItemName), path.join(dest, childItemName));
});
} else {
// Check if file should be excluded
const basename = path.basename(src);
const shouldExclude = EXCLUDED_FILE_PATTERNS.some(pattern => pattern.test(basename));

if (!shouldExclude) {
fs.copyFileSync(src, dest);
}
}
}

function cleanLinks(filePath) {
if (!fs.existsSync(filePath)) return;
let content = fs.readFileSync(filePath, 'utf8');

const linkRegex = /\[([^\]]+)\]\(([^)]+)\)/g;

content = content.replace(linkRegex, (match, label, href) => {
const shouldExclude = EXCLUDED_FILE_PATTERNS.some(pattern => pattern.test(href));
if (shouldExclude) {
return '';
}
return match;
});

// Clean up double commas, trailing commas in lists
content = content.replace(/,\s*,/g, ',');
content = content.replace(/,\s*or\s*,/g, ' or ');
content = content.replace(/,\s*\]/g, ']');
content = content.replace(/\[\s*,/g, '[');

// Clean up empty list items or broken sentences
content = content.replace(/Read\s*,/g, 'Read');
content = content.replace(/,\s*or\s*$/gm, '');
content = content.replace(/,\s*$/gm, '');
content = content.replace(/^\s*-\s*\*\*.*?\*\*:\s*See\s*$/gm, '');
content = content.replace(/^\s*-\s*\*\*.*?\*\*:\s*$/gm, '');
content = content.replace(/^\s*[*+-]\s*\*\*(iOS|Web|Flutter)\*\*:\s*$/gmi, '');

fs.writeFileSync(filePath, content, 'utf8');
}

function processFiles(dir) {
fs.readdirSync(dir).forEach((file) => {
const fullPath = path.join(dir, file);
if (fs.lstatSync(fullPath).isDirectory()) {
processFiles(fullPath);
} else if (path.extname(fullPath) === '.md') {
cleanLinks(fullPath);
}
});
}

function main() {
console.log('Generating Android-only skills...');

// Clear target dir
deleteFolderRecursive(TARGET_DIR);
fs.mkdirSync(TARGET_DIR, { recursive: true });

// Copy skills
fs.readdirSync(SOURCE_DIR).forEach((skill) => {
if (EXCLUDED_SKILLS.includes(skill)) {
console.log(`Skipping skill: ${skill}`);
return;
}

console.log(`Copying skill: ${skill}`);
copyRecursive(path.join(SOURCE_DIR, skill), path.join(TARGET_DIR, skill));
});

// Process files to clean links
console.log('Cleaning links...');
processFiles(TARGET_DIR);

console.log('Done!');
}

main();
Loading