feat(core): add 26 non-code language configs with filename-based detection

Add LanguageConfig files for: markdown, yaml, json, toml, env, xml,
dockerfile, sql, graphql, protobuf, terraform, github-actions, makefile,
shell, html, css, openapi, kubernetes, docker-compose, json-schema, csv,
restructuredtext, powershell, batch, jenkinsfile, plaintext.

Add filenames? field to LanguageConfigSchema for filename-based detection
(Dockerfile, Makefile, Jenkinsfile, docker-compose.yml, .env variants).

Update LanguageRegistry.getForFile() to check filename matches first
(more specific) before falling back to extension-based lookup.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Lum1104
2026-03-28 18:34:16 +08:00
Unverified
parent 9eb220c492
commit c76b0a1f2d
29 changed files with 465 additions and 1 deletions
@@ -0,0 +1,14 @@
import type { LanguageConfig } from "../types.js";
export const batchConfig = {
id: "batch",
displayName: "Batch Script",
extensions: [".bat", ".cmd"],
concepts: ["commands", "variables", "labels", "goto", "call", "echo", "set", "for loops", "if conditions"],
filePatterns: {
entryPoints: [],
barrels: [],
tests: [],
config: [],
},
} satisfies LanguageConfig;
@@ -0,0 +1,14 @@
import type { LanguageConfig } from "../types.js";
export const cssConfig = {
id: "css",
displayName: "CSS",
extensions: [".css", ".scss", ".less"],
concepts: ["selectors", "properties", "media queries", "flexbox", "grid", "variables", "animations", "specificity"],
filePatterns: {
entryPoints: [],
barrels: [],
tests: [],
config: [],
},
} satisfies LanguageConfig;
@@ -0,0 +1,14 @@
import type { LanguageConfig } from "../types.js";
export const csvConfig = {
id: "csv",
displayName: "CSV",
extensions: [".csv", ".tsv"],
concepts: ["headers", "rows", "delimiters", "quoting", "escaping"],
filePatterns: {
entryPoints: [],
barrels: [],
tests: [],
config: [],
},
} satisfies LanguageConfig;
@@ -0,0 +1,15 @@
import type { LanguageConfig } from "../types.js";
export const dockerComposeConfig = {
id: "docker-compose",
displayName: "Docker Compose",
extensions: [],
filenames: ["docker-compose.yml", "docker-compose.yaml", "compose.yml", "compose.yaml"],
concepts: ["services", "networks", "volumes", "ports", "environment", "depends_on", "build context", "healthchecks"],
filePatterns: {
entryPoints: ["docker-compose.yml", "compose.yml"],
barrels: [],
tests: [],
config: [],
},
} satisfies LanguageConfig;
@@ -0,0 +1,15 @@
import type { LanguageConfig } from "../types.js";
export const dockerfileConfig = {
id: "dockerfile",
displayName: "Dockerfile",
extensions: [],
filenames: ["Dockerfile", "Dockerfile.dev", "Dockerfile.prod", "Dockerfile.test"],
concepts: ["multi-stage builds", "layers", "base images", "COPY/ADD", "EXPOSE", "ENTRYPOINT", "CMD", "ARG", "ENV"],
filePatterns: {
entryPoints: ["Dockerfile"],
barrels: [],
tests: [],
config: [],
},
} satisfies LanguageConfig;
@@ -0,0 +1,15 @@
import type { LanguageConfig } from "../types.js";
export const envConfig = {
id: "env",
displayName: "Environment Variables",
extensions: [".env"],
filenames: [".env", ".env.local", ".env.development", ".env.production", ".env.test", ".env.example"],
concepts: ["key-value pairs", "variable interpolation", "secrets", "environment-specific config"],
filePatterns: {
entryPoints: [],
barrels: [],
tests: [],
config: [".env", ".env.*"],
},
} satisfies LanguageConfig;
@@ -0,0 +1,14 @@
import type { LanguageConfig } from "../types.js";
export const githubActionsConfig = {
id: "github-actions",
displayName: "GitHub Actions",
extensions: [],
concepts: ["workflows", "jobs", "steps", "actions", "triggers", "secrets", "matrix strategy", "artifacts"],
filePatterns: {
entryPoints: [],
barrels: [],
tests: [],
config: [".github/workflows/*.yml"],
},
} satisfies LanguageConfig;
@@ -0,0 +1,14 @@
import type { LanguageConfig } from "../types.js";
export const graphqlConfig = {
id: "graphql",
displayName: "GraphQL",
extensions: [".graphql", ".gql"],
concepts: ["types", "queries", "mutations", "subscriptions", "resolvers", "directives", "fragments", "schema"],
filePatterns: {
entryPoints: ["schema.graphql"],
barrels: [],
tests: [],
config: [],
},
} satisfies LanguageConfig;
@@ -0,0 +1,14 @@
import type { LanguageConfig } from "../types.js";
export const htmlConfig = {
id: "html",
displayName: "HTML",
extensions: [".html", ".htm"],
concepts: ["elements", "attributes", "semantic tags", "forms", "meta tags", "scripts", "stylesheets", "accessibility"],
filePatterns: {
entryPoints: ["index.html"],
barrels: [],
tests: [],
config: [],
},
} satisfies LanguageConfig;
@@ -11,8 +11,36 @@ import { swiftConfig } from "./swift.js";
import { kotlinConfig } from "./kotlin.js";
import { cppConfig } from "./cpp.js";
import { csharpConfig } from "./csharp.js";
// Non-code language configs
import { markdownConfig } from "./markdown.js";
import { yamlConfig } from "./yaml.js";
import { jsonConfigConfig } from "./json-config.js";
import { tomlConfig } from "./toml.js";
import { envConfig } from "./env.js";
import { xmlConfig } from "./xml.js";
import { dockerfileConfig } from "./dockerfile.js";
import { sqlConfig } from "./sql.js";
import { graphqlConfig } from "./graphql.js";
import { protobufConfig } from "./protobuf.js";
import { terraformConfig } from "./terraform.js";
import { githubActionsConfig } from "./github-actions.js";
import { makefileConfig } from "./makefile.js";
import { shellConfig } from "./shell.js";
import { htmlConfig } from "./html.js";
import { cssConfig } from "./css.js";
import { openapiConfig } from "./openapi.js";
import { kubernetesConfig } from "./kubernetes.js";
import { dockerComposeConfig } from "./docker-compose.js";
import { jsonSchemaConfig } from "./json-schema.js";
import { csvConfig } from "./csv.js";
import { restructuredtextConfig } from "./restructuredtext.js";
import { powershellConfig } from "./powershell.js";
import { batchConfig } from "./batch.js";
import { jenkinsfileConfig } from "./jenkinsfile.js";
import { plaintextConfig } from "./plaintext.js";
export const builtinLanguageConfigs: LanguageConfig[] = [
// Code languages
typescriptConfig,
javascriptConfig,
pythonConfig,
@@ -25,9 +53,37 @@ export const builtinLanguageConfigs: LanguageConfig[] = [
kotlinConfig,
cppConfig,
csharpConfig,
// Non-code languages
markdownConfig,
yamlConfig,
jsonConfigConfig,
tomlConfig,
envConfig,
xmlConfig,
dockerfileConfig,
sqlConfig,
graphqlConfig,
protobufConfig,
terraformConfig,
githubActionsConfig,
makefileConfig,
shellConfig,
htmlConfig,
cssConfig,
openapiConfig,
kubernetesConfig,
dockerComposeConfig,
jsonSchemaConfig,
csvConfig,
restructuredtextConfig,
powershellConfig,
batchConfig,
jenkinsfileConfig,
plaintextConfig,
];
export {
// Code languages
typescriptConfig,
javascriptConfig,
pythonConfig,
@@ -40,4 +96,31 @@ export {
kotlinConfig,
cppConfig,
csharpConfig,
// Non-code languages
markdownConfig,
yamlConfig,
jsonConfigConfig,
tomlConfig,
envConfig,
xmlConfig,
dockerfileConfig,
sqlConfig,
graphqlConfig,
protobufConfig,
terraformConfig,
githubActionsConfig,
makefileConfig,
shellConfig,
htmlConfig,
cssConfig,
openapiConfig,
kubernetesConfig,
dockerComposeConfig,
jsonSchemaConfig,
csvConfig,
restructuredtextConfig,
powershellConfig,
batchConfig,
jenkinsfileConfig,
plaintextConfig,
};
@@ -0,0 +1,15 @@
import type { LanguageConfig } from "../types.js";
export const jenkinsfileConfig = {
id: "jenkinsfile",
displayName: "Jenkinsfile",
extensions: [],
filenames: ["Jenkinsfile"],
concepts: ["pipeline", "stages", "steps", "agents", "environment", "post actions", "parallel execution", "shared libraries"],
filePatterns: {
entryPoints: ["Jenkinsfile"],
barrels: [],
tests: [],
config: [],
},
} satisfies LanguageConfig;
@@ -0,0 +1,14 @@
import type { LanguageConfig } from "../types.js";
export const jsonConfigConfig = {
id: "json",
displayName: "JSON",
extensions: [".json", ".jsonc"],
concepts: ["objects", "arrays", "nesting", "schema references", "comments (JSONC)"],
filePatterns: {
entryPoints: ["package.json"],
barrels: [],
tests: [],
config: ["tsconfig.json", "package.json", ".eslintrc.json"],
},
} satisfies LanguageConfig;
@@ -0,0 +1,14 @@
import type { LanguageConfig } from "../types.js";
export const jsonSchemaConfig = {
id: "json-schema",
displayName: "JSON Schema",
extensions: [],
concepts: ["types", "properties", "required fields", "$ref", "$defs", "allOf/anyOf/oneOf", "patterns", "validation"],
filePatterns: {
entryPoints: [],
barrels: [],
tests: [],
config: [],
},
} satisfies LanguageConfig;
@@ -0,0 +1,14 @@
import type { LanguageConfig } from "../types.js";
export const kubernetesConfig = {
id: "kubernetes",
displayName: "Kubernetes",
extensions: [],
concepts: ["deployments", "services", "pods", "configmaps", "secrets", "ingress", "volumes", "namespaces"],
filePatterns: {
entryPoints: [],
barrels: [],
tests: [],
config: ["k8s/*.yaml", "kubernetes/*.yaml"],
},
} satisfies LanguageConfig;
@@ -0,0 +1,15 @@
import type { LanguageConfig } from "../types.js";
export const makefileConfig = {
id: "makefile",
displayName: "Makefile",
extensions: [".mk"],
filenames: ["Makefile", "GNUmakefile", "makefile"],
concepts: ["targets", "dependencies", "recipes", "variables", "pattern rules", "phony targets", "includes"],
filePatterns: {
entryPoints: ["Makefile"],
barrels: [],
tests: [],
config: [],
},
} satisfies LanguageConfig;
@@ -0,0 +1,14 @@
import type { LanguageConfig } from "../types.js";
export const markdownConfig = {
id: "markdown",
displayName: "Markdown",
extensions: [".md", ".mdx"],
concepts: ["headings", "links", "code blocks", "front matter", "lists", "tables", "images"],
filePatterns: {
entryPoints: ["README.md"],
barrels: [],
tests: [],
config: [],
},
} satisfies LanguageConfig;
@@ -0,0 +1,14 @@
import type { LanguageConfig } from "../types.js";
export const openapiConfig = {
id: "openapi",
displayName: "OpenAPI",
extensions: [],
concepts: ["paths", "operations", "schemas", "parameters", "responses", "security schemes", "tags", "servers"],
filePatterns: {
entryPoints: ["openapi.yaml", "swagger.yaml"],
barrels: [],
tests: [],
config: [],
},
} satisfies LanguageConfig;
@@ -0,0 +1,14 @@
import type { LanguageConfig } from "../types.js";
export const plaintextConfig = {
id: "plaintext",
displayName: "Plain Text",
extensions: [".txt", ".text"],
concepts: ["paragraphs", "lists", "sections"],
filePatterns: {
entryPoints: [],
barrels: [],
tests: [],
config: [],
},
} satisfies LanguageConfig;
@@ -0,0 +1,14 @@
import type { LanguageConfig } from "../types.js";
export const powershellConfig = {
id: "powershell",
displayName: "PowerShell",
extensions: [".ps1", ".psm1", ".psd1"],
concepts: ["cmdlets", "pipelines", "modules", "functions", "parameters", "variables", "error handling"],
filePatterns: {
entryPoints: [],
barrels: [],
tests: [],
config: [],
},
} satisfies LanguageConfig;
@@ -0,0 +1,14 @@
import type { LanguageConfig } from "../types.js";
export const protobufConfig = {
id: "protobuf",
displayName: "Protocol Buffers",
extensions: [".proto"],
concepts: ["messages", "services", "enums", "oneof", "repeated fields", "maps", "packages", "imports"],
filePatterns: {
entryPoints: [],
barrels: [],
tests: [],
config: [],
},
} satisfies LanguageConfig;
@@ -0,0 +1,14 @@
import type { LanguageConfig } from "../types.js";
export const restructuredtextConfig = {
id: "restructuredtext",
displayName: "reStructuredText",
extensions: [".rst"],
concepts: ["headings", "directives", "roles", "cross-references", "toctree", "code blocks", "admonitions"],
filePatterns: {
entryPoints: ["index.rst"],
barrels: [],
tests: [],
config: [],
},
} satisfies LanguageConfig;
@@ -0,0 +1,14 @@
import type { LanguageConfig } from "../types.js";
export const shellConfig = {
id: "shell",
displayName: "Shell Script",
extensions: [".sh", ".bash", ".zsh"],
concepts: ["variables", "functions", "conditionals", "loops", "pipes", "redirection", "subshells", "exit codes"],
filePatterns: {
entryPoints: [],
barrels: [],
tests: [],
config: [".bashrc", ".zshrc", ".profile"],
},
} satisfies LanguageConfig;
@@ -0,0 +1,14 @@
import type { LanguageConfig } from "../types.js";
export const sqlConfig = {
id: "sql",
displayName: "SQL",
extensions: [".sql"],
concepts: ["tables", "columns", "indexes", "foreign keys", "views", "stored procedures", "triggers", "migrations"],
filePatterns: {
entryPoints: [],
barrels: [],
tests: [],
config: [],
},
} satisfies LanguageConfig;
@@ -0,0 +1,14 @@
import type { LanguageConfig } from "../types.js";
export const terraformConfig = {
id: "terraform",
displayName: "Terraform",
extensions: [".tf", ".tfvars"],
concepts: ["resources", "data sources", "variables", "outputs", "modules", "providers", "state", "workspaces"],
filePatterns: {
entryPoints: ["main.tf"],
barrels: [],
tests: [],
config: ["terraform.tfvars", "variables.tf"],
},
} satisfies LanguageConfig;
@@ -0,0 +1,14 @@
import type { LanguageConfig } from "../types.js";
export const tomlConfig = {
id: "toml",
displayName: "TOML",
extensions: [".toml"],
concepts: ["tables", "inline tables", "arrays of tables", "key-value pairs", "dotted keys"],
filePatterns: {
entryPoints: [],
barrels: [],
tests: [],
config: ["Cargo.toml", "pyproject.toml", "netlify.toml"],
},
} satisfies LanguageConfig;
@@ -0,0 +1,14 @@
import type { LanguageConfig } from "../types.js";
export const xmlConfig = {
id: "xml",
displayName: "XML",
extensions: [".xml", ".xsl", ".xsd", ".svg", ".plist"],
concepts: ["elements", "attributes", "namespaces", "DTD", "XPath", "XSLT", "schemas"],
filePatterns: {
entryPoints: [],
barrels: [],
tests: [],
config: ["pom.xml", "web.xml", "AndroidManifest.xml"],
},
} satisfies LanguageConfig;
@@ -0,0 +1,14 @@
import type { LanguageConfig } from "../types.js";
export const yamlConfig = {
id: "yaml",
displayName: "YAML",
extensions: [".yaml", ".yml"],
concepts: ["mappings", "sequences", "anchors", "aliases", "multi-document", "tags"],
filePatterns: {
entryPoints: [],
barrels: [],
tests: [],
config: ["*.yaml", "*.yml"],
},
} satisfies LanguageConfig;
@@ -9,6 +9,7 @@ import { builtinLanguageConfigs } from "./configs/index.js";
export class LanguageRegistry {
private byId = new Map<string, LanguageConfig>();
private byExtension = new Map<string, LanguageConfig>();
private byFilename = new Map<string, LanguageConfig>();
register(config: LanguageConfig): void {
const parsed = LanguageConfigSchema.parse(config);
@@ -18,6 +19,11 @@ export class LanguageRegistry {
const key = ext.startsWith(".") ? ext : `.${ext}`;
this.byExtension.set(key, parsed);
}
if (parsed.filenames) {
for (const filename of parsed.filenames) {
this.byFilename.set(filename.toLowerCase(), parsed);
}
}
}
getById(id: string): LanguageConfig | null {
@@ -30,6 +36,11 @@ export class LanguageRegistry {
}
getForFile(filePath: string): LanguageConfig | null {
// Try filename-based lookup first (more specific: docker-compose.yml, Makefile, etc.)
const basename = filePath.split("/").pop() ?? filePath;
const filenameMatch = this.byFilename.get(basename.toLowerCase());
if (filenameMatch) return filenameMatch;
// Fall back to extension-based lookup
const lastDot = filePath.lastIndexOf(".");
if (lastDot === -1) return null;
const ext = filePath.slice(lastDot).toLowerCase();
@@ -26,7 +26,8 @@ export type FilePatternConfig = z.infer<typeof FilePatternConfigSchema>;
export const LanguageConfigSchema = z.object({
id: z.string().min(1),
displayName: z.string().min(1),
extensions: z.array(z.string()).min(1),
extensions: z.array(z.string()),
filenames: z.array(z.string()).optional(),
treeSitter: TreeSitterConfigSchema.optional(),
concepts: z.array(z.string()),
filePatterns: FilePatternConfigSchema,