@nanocollective/nanocoder
Version:
A local-first CLI coding agent that brings the power of agentic coding tools like Claude Code and Gemini CLI to local models or controlled APIs like OpenRouter
219 lines • 6.83 kB
JavaScript
import { basename, extname } from 'path';
import { MAX_SECONDARY_LANGUAGES, MIN_LANGUAGE_PERCENTAGE } from '../constants.js';
export class LanguageDetector {
static LANGUAGE_MAP = {
// JavaScript/TypeScript ecosystem
'.js': 'JavaScript',
'.jsx': 'JavaScript',
'.ts': 'TypeScript',
'.tsx': 'TypeScript',
'.mjs': 'JavaScript',
'.cjs': 'JavaScript',
// Python
'.py': 'Python',
'.pyx': 'Python',
'.pyi': 'Python',
'.pyc': 'Python',
// Rust
'.rs': 'Rust',
// Go
'.go': 'Go',
// Java/Kotlin
'.java': 'Java',
'.kt': 'Kotlin',
'.kts': 'Kotlin',
// C/C++
'.c': 'C',
'.h': 'C',
'.cpp': 'C++',
'.cxx': 'C++',
'.cc': 'C++',
'.hpp': 'C++',
'.hxx': 'C++',
// C#
'.cs': 'C#',
// PHP
'.php': 'PHP',
// Ruby
'.rb': 'Ruby',
// Swift
'.swift': 'Swift',
// Dart
'.dart': 'Dart',
// Shell
'.sh': 'Shell',
'.bash': 'Shell',
'.zsh': 'Shell',
'.fish': 'Shell',
// Web technologies
'.html': 'HTML',
'.htm': 'HTML',
'.css': 'CSS',
'.scss': 'SCSS',
'.sass': 'Sass',
'.less': 'Less',
'.vue': 'Vue',
'.svelte': 'Svelte',
// Config/Data
'.json': 'JSON',
'.yaml': 'YAML',
'.yml': 'YAML',
'.toml': 'TOML',
'.xml': 'XML',
'.ini': 'INI',
// Documentation
'.md': 'Markdown',
'.mdx': 'Markdown',
'.rst': 'reStructuredText',
// SQL
'.sql': 'SQL',
// Docker
'.dockerfile': 'Dockerfile',
};
/**
* Detect languages from file list
*/
static detectLanguages(files) {
const languageCounts = {};
const totalFiles = files.length;
// Count files by language
for (const file of files) {
const ext = extname(file).toLowerCase();
const filename = basename(file).toLowerCase();
let language;
// Special case handling
if (filename === 'dockerfile' || filename.startsWith('dockerfile.')) {
language = 'Dockerfile';
}
else if (filename === 'makefile') {
language = 'Makefile';
}
else {
language = this.LANGUAGE_MAP[ext];
}
if (language) {
if (!languageCounts[language]) {
languageCounts[language] = [];
}
languageCounts[language].push(file);
}
}
// Convert to LanguageInfo array
const languageInfos = Object.entries(languageCounts)
.map(([language, fileList]) => ({
name: language,
extensions: this.getExtensionsForLanguage(language),
percentage: Math.round((fileList.length / totalFiles) * 100),
files: fileList,
}))
.sort((a, b) => b.files.length - a.files.length);
// Determine primary and secondary languages
const primary = languageInfos.length > 0 ? languageInfos[0] : null;
const secondary = languageInfos
.slice(1)
.filter(lang => lang.percentage >= MIN_LANGUAGE_PERCENTAGE) // At least MIN_LANGUAGE_PERCENTAGE% of files
.slice(0, MAX_SECONDARY_LANGUAGES); // Top MAX_SECONDARY_LANGUAGES secondary languages
return {
primary,
secondary,
all: languageInfos,
};
}
/**
* Get file extensions for a given language
*/
static getExtensionsForLanguage(language) {
return Object.entries(this.LANGUAGE_MAP)
.filter(([_, lang]) => lang === language)
.map(([ext]) => ext);
}
/**
* Get language category (for grouping related languages)
*/
static getLanguageCategory(language) {
const categories = {
'Web Frontend': [
'JavaScript',
'TypeScript',
'HTML',
'CSS',
'SCSS',
'Sass',
'Less',
'Vue',
'Svelte',
],
'Web Backend': ['Node.js', 'PHP', 'Python', 'Ruby', 'Java', 'C#', 'Go'],
'Systems Programming': ['Rust', 'C', 'C++', 'Go'],
Mobile: ['Swift', 'Kotlin', 'Dart', 'Java'],
'Data & Config': ['JSON', 'YAML', 'TOML', 'XML', 'INI', 'SQL'],
Documentation: ['Markdown', 'reStructuredText'],
DevOps: ['Shell', 'Dockerfile', 'Makefile'],
};
for (const [category, languages] of Object.entries(categories)) {
if (languages.includes(language)) {
return category;
}
}
return 'Other';
}
/**
* Suggest project type based on detected languages
*/
static suggestProjectType(languages) {
if (!languages.primary) {
return 'Unknown';
}
const primary = languages.primary.name;
const hasSecondary = (lang) => languages.secondary.some(l => l.name === lang);
// Web applications
if (primary === 'JavaScript' || primary === 'TypeScript') {
if (hasSecondary('HTML') ||
hasSecondary('CSS') ||
hasSecondary('Vue') ||
hasSecondary('Svelte')) {
return 'Web Application';
}
return 'Node.js Application';
}
// Python projects
if (primary === 'Python') {
return 'Python Application';
}
// Mobile apps
if (primary === 'Swift') {
return 'iOS Application';
}
if (primary === 'Kotlin' && hasSecondary('XML')) {
return 'Android Application';
}
if (primary === 'Dart') {
return 'Flutter Application';
}
// Systems programming
if (primary === 'Rust') {
return 'Rust Application';
}
if (primary === 'C' || primary === 'C++') {
return 'C/C++ Application';
}
if (primary === 'Go') {
return 'Go Application';
}
// Other languages
if (primary === 'Java') {
return 'Java Application';
}
if (primary === 'C#') {
return 'C# Application';
}
if (primary === 'PHP') {
return 'PHP Application';
}
if (primary === 'Ruby') {
return 'Ruby Application';
}
return `${primary} Project`;
}
}
//# sourceMappingURL=language-detector.js.map