<< All versions
Skill v1.0.0
currentLLM-judged scan95/100yanacuti1121/yana-ai/babel-ast-transform
──Details
PublishedOctober 23, 2026 at 05:11 PM
Content Hashsha256:f99d3b036b1897bc...
Git SHA5b39442837f1
──Files
Files (1 file, 3.9 KB)
SKILL.md3.9 KBactive
SKILL.md · 148 lines · 3.9 KB
name: babel-ast-transform description: Babel plugin architecture for AST-based code transformations. Visitor pattern traversal, path/scope API, custom transform rules, and automated codemod pipelines. Sources: babel/babel (MIT). origin: yana-ai — synthesized from babel/babel (MIT) license: Apache-2.0 version: 1.0.0 compatibility: yana-ai >= 1.3.49
/babel-ast-transform
When to Use
- Write custom Babel plugins to auto-migrate legacy code patterns
- Transform syntax: class properties → ES5, CommonJS → ESM, custom macros
- Codemod pipelines: apply AST rules across an entire monorepo
- Replace manual find-and-replace with safe, scope-aware rewrites
Do NOT use for
- Runtime code evaluation (use [[repl-code-execution]])
- TypeScript-specific type manipulation (use [[ts-morph-refactor]])
Minimal Babel plugin skeleton
javascript
// my-babel-plugin.jsexport default function myPlugin({ types: t }) {return {name: 'my-plugin',visitor: {// Called for every Identifier node in the ASTIdentifier(path) {if (path.node.name === 'oldName') {path.node.name = 'newName'}},// Called for every CallExpressionCallExpression(path) {const callee = path.get('callee')if (callee.isIdentifier({ name: 'deprecatedFn' })) {// Replace deprecatedFn(x) → newFn(x)callee.node.name = 'newFn'}},},}}
Plugin with path manipulation
javascript
export default function ({ types: t }) {return {visitor: {// Remove console.log() calls entirelyExpressionStatement(path) {const expr = path.node.expressionif (t.isCallExpression(expr) &&t.isMemberExpression(expr.callee) &&t.isIdentifier(expr.callee.object, { name: 'console' }) &&t.isIdentifier(expr.callee.property, { name: 'log' })) {path.remove()}},// Add missing return type annotation to arrow functionsArrowFunctionExpression(path) {if (!path.node.returnType) {path.node.returnType = t.tsTypeAnnotation(t.tsAnyKeyword())}},},}}
Programmatic transform (codemod runner)
javascript
import { transformSync } from '@babel/core'import { readFileSync, writeFileSync } from 'fs'import { globSync } from 'glob'function runCodemod(pattern: string, pluginPath: string) {const files = globSync(pattern, { ignore: 'node_modules/**' })for (const file of files) {const source = readFileSync(file, 'utf8')const result = transformSync(source, {filename: file,plugins: [pluginPath],parserOpts: { plugins: ['typescript', 'jsx'] },retainLines: true, // preserve line numbers for diff readabilitysourceMaps: 'inline',})if (result?.code && result.code !== source) {writeFileSync(file, result.code)console.log(`[codemod] transformed ${file}`)}}}runCodemod('src/**/*.{ts,tsx}', './my-babel-plugin.js')
Scope-aware rename (respects variable shadowing)
javascript
export default function ({ types: t }) {return {visitor: {Program(path) {// Rename all references to 'oldVar' in this scope onlypath.scope.rename('oldVar', 'newVar')},},}}// path.scope.rename handles: declarations, references, shadowed inner scopes
Anti-Fake-Pass Checklist
❌ Mutating path.node directly without t.cloneNode → shared AST node corruption❌ path.remove() inside forEach on siblings → skip nodes; use path.getSibling()❌ Missing parserOpts.plugins: ['typescript'] → ts files fail to parse❌ Visitor fires on both enter and exit — specify enter/exit explicitly for order-sensitive transforms❌ scope.rename not called → manual identifier rename misses shadowed bindings❌ retainLines: false in codemods → diff unreadable across large files