@ttwtf/ng-parser
v1.6.0
Published
Advanced Angular parser with RAG-optimized output and extensible visitor architecture
Maintainers
Readme
ng-parser
Advanced Angular parser with RAG-optimized output and extensible visitor architecture.
Features
- 🔍 Deep Angular Analysis - Components, Services, Modules, Directives, Pipes
- 🧩 Two-Layer Architecture - Core parsing + Extensible custom visitors
- 🎯 Modern Angular Support - Standalone components, Signals (Angular 18-20)
- 📊 Knowledge Graph - Entities, relationships, hierarchical clustering
- 🎨 Template & Style Analysis - Parse HTML templates and SCSS files with full dependency tracking
- 🌐 Git Integration - Automatic source URLs for GitHub, GitLab, Bitbucket, Azure DevOps
- 🎯 Global Styles - Auto-detect and parse global SCSS files (styles.scss, theme.scss, etc.)
- 🤖 RAG Optimized - JSON outputs optimized for LLM consumption
- ⚡ Maintainable - Built on official @angular/compiler-cli
- 🔌 Extensible - Create custom visitors for your analysis needs
- 🛡️ Built-in Visitors - RxJS patterns, Security, Performance analysis
Installation
npm install @ttwtf/ng-parserPeer Dependencies (automatically uses your project's Angular version):
npm install @angular/compiler @angular/compiler-cli @angular/coreSupported versions: Angular 18.x, 19.x, 20.x
Quick Start
CLI (Recommended)
# Parse an Angular project (core parsing only, fastest)
ng-parser parse ./src
# Enable specific visitors
ng-parser parse ./src --visitors rxjs,security
# Export to file
ng-parser parse ./src -o analysis.json
# Export all formats (JSON, SimpleJSON, HTML)
ng-parser parse ./src -f all -o ./output/my-projectSee CLI Documentation for complete CLI reference.
Programmatic API
import { NgParser } from '@ttwtf/ng-parser';
const parser = new NgParser({ rootDir: './src' });
const result = await parser.parse();
console.log(`Found ${result.metadata.totalEntities} Angular entities`);
console.log(`Found ${result.metadata.totalRelationships} relationships`);
// Access parsed entities
for (const entity of result.entities.values()) {
console.log(`[${entity.type}] ${entity.name}`);
}With Built-in Visitors
import {
NgParser,
RxJSPatternVisitor,
SecurityVisitor,
PerformanceVisitor
} from '@ttwtf/ng-parser';
const parser = new NgParser({ rootDir: './src' });
// Register pattern extraction visitors
parser.registerVisitor(new RxJSPatternVisitor());
parser.registerVisitor(new SecurityVisitor());
parser.registerVisitor(new PerformanceVisitor());
const result = await parser.parse();
// Access visitor results (raw patterns, not evaluations)
const rxjsResults = result.customAnalysis.get('RxJSPatternVisitor');
console.log(`RxJS observables found: ${rxjsResults.totalObservables}`);
console.log(`In components: ${rxjsResults.observablesInComponents}`);
const securityResults = result.customAnalysis.get('SecurityVisitor');
console.log(`Security patterns found: ${securityResults.totalPatterns}`);
console.log(`By pattern:`, securityResults.byPattern);Export to Multiple Formats
// JSON export (complete data, optimized)
const json = result.toJSON();
// SimpleJSON export (ng-analyzer compatible)
const simple = result.toSimpleJSON();
// HTML export (interactive D3.js visualization)
const html = result.toHTML();Two-Layer Architecture
ng-parser uses a strict two-layer separation between parsing and analysis:
Layer 1: Core Angular Parsers (Built-in, Non-Extensible)
Pure extraction of Angular concepts with guaranteed quality:
- ✅ ComponentParser - Standalone, signals, inputs/outputs, lifecycle
- ✅ ServiceParser - Dependency injection, providedIn
- ✅ ModuleParser - Declarations, imports, exports, providers
- ✅ DirectiveParser - Inputs, outputs, standalone
- ✅ PipeParser - Pure/impure, standalone
- ✅ TemplateParser - HTML template analysis (inline & external)
- ✅ StyleParser - SCSS
@importand@useextraction - ✅ GitRemoteParser - Git repository detection and source URL generation
Role: Transform source code → structured data (AST, entities, relationships)
Layer 2: Custom Visitors (Extensible, User-Defined)
Pattern extraction from parsed entities - NO evaluation or recommendations:
- RxJSPatternVisitor - Extracts Observable/Subject usage and lifecycle hooks
- SecurityVisitor - Extracts innerHTML, eval(), HTTP URLs, potential secrets
- PerformanceVisitor - Extracts change detection, trackBy, imports, constructors
Role: Extract additional patterns → structured facts (no judgments)
Important: Visitors perform extraction only. They don't evaluate severity, don't recommend fixes, and don't judge code quality. They simply identify and categorize patterns. Analysis/evaluation tools can be built on top of the extracted data.
Create your own visitors to extract domain-specific patterns!
Built-in Visitors
RxJSPatternVisitor
Extracts RxJS usage patterns:
const rxjsResults = result.customAnalysis.get('RxJSPatternVisitor');
console.log(`Total observables: ${rxjsResults.totalObservables}`);
console.log(`In components: ${rxjsResults.observablesInComponents}`);
console.log(`Components with ngOnDestroy:`, rxjsResults.componentsWithNgOnDestroy);
console.log(`Components without ngOnDestroy:`, rxjsResults.componentsWithoutNgOnDestroy);
// Access individual patterns
rxjsResults.patterns.forEach(pattern => {
console.log(`${pattern.type} in ${pattern.entityName} - has ngOnDestroy: ${pattern.hasNgOnDestroy}`);
});Extracts:
- Observable/Subject/BehaviorSubject/ReplaySubject properties
- Component lifecycle (presence of ngOnDestroy)
- Location of each pattern
SecurityVisitor
Extracts security-relevant patterns:
const securityResults = result.customAnalysis.get('SecurityVisitor');
console.log(`Total patterns: ${securityResults.totalPatterns}`);
console.log(`By pattern:`, securityResults.byPattern);
// Example output: { innerHTML: 3, eval: 1, potential_secret: 2, http_url: 5 }Extracts:
- innerHTML/outerHTML usage
- bypassSecurityTrust* calls
- eval() and Function() usage
- HTTP URLs (non-HTTPS)
- Potential hardcoded secrets (API keys, passwords, tokens)
- XSRF protection configuration
PerformanceVisitor
Extracts performance-relevant patterns:
const perfResults = result.customAnalysis.get('PerformanceVisitor');
console.log(`Total patterns: ${perfResults.totalPatterns}`);
console.log(`By pattern:`, perfResults.byPattern);
// Example output:
// {
// change_detection_default: 15,
// ngfor_without_trackby: 8,
// function_in_template: 3
// }Extracts:
- Change detection strategy (Default/OnPush)
- *ngFor with/without trackBy
- Function calls in templates
- HTTP calls in constructors
- Loops in constructors
- Large library imports (lodash, moment, rxjs)
- Array operation chains
- Storage operations in loops
Advanced Features
Template Analysis
Parse both inline and external HTML templates automatically:
// Component with external template
@Component({
templateUrl: './my-component.html',
// ...
})
// Parser automatically extracts:
const component = result.entities.get('component:...:MyComponent');
console.log(component.templateLocation); // File path + Git URL
console.log(component.templateAnalysis); // Analysis resultsExtracted data:
- Used components: Custom component selectors found in template
- Used directives: Structural (
*ngIf,*ngFor) and attribute directives - Used pipes: All pipes with names (
| date,| async, custom pipes) - Bindings: Property
[prop], event(click), two-way[(ngModel)], etc. - Template refs:
#myRefreferences - Complexity score: Based on nesting depth and structural directives
{
"templateAnalysis": {
"usedComponents": ["app-child", "app-card"],
"usedDirectives": ["*ngIf", "*ngFor", "appHighlight"],
"usedPipes": ["date", "async", "customPipe"],
"bindings": [
{"type": "property", "name": "disabled", "expression": "!isValid"},
{"type": "event", "name": "click", "expression": "onSave()"}
],
"templateRefs": ["form", "input"],
"complexity": 85
}
}Style Analysis
Parse SCSS files and extract dependencies:
// Component with styles
@Component({
styleUrls: [
'./my-component.scss',
'./my-component-responsive.scss'
]
})
// Parser extracts all @import and @use statements
const component = result.entities.get('component:...:MyComponent');
console.log(component.styleAnalysis);Extracted data:
- @import statements: Path, full statement, line number, resolved path
- @use statements: Path, namespace, statement, line number, resolved path
- File locations: All style files with Git URLs
{
"styleAnalysis": {
"files": [
{
"filePath": "src/app/components/my-component.scss",
"sourceUrl": "https://github.com/.../my-component.scss",
"imports": [
{
"path": "../styles/mixins",
"statement": "@import '../styles/mixins'",
"line": 3
}
],
"uses": [
{
"path": "../styles/variables",
"statement": "@use '../styles/variables' as vars",
"namespace": "vars",
"line": 1
}
]
}
]
}
}Global Styles
Automatically detects and parses global SCSS files:
Auto-detected files (no configuration needed):
styles.scss,style.scsstheme.scssvariables.scss,_variables.scss
Searched locations:
- Project root
src/directory
const result = await parser.parse();
console.log(result.metadata.globalStyles);{
"metadata": {
"globalStyles": [
{
"filePath": "src/styles.scss",
"sourceUrl": "https://github.com/.../src/styles.scss",
"imports": [
{"path": "./theme", "statement": "@import './theme'", "line": 2}
],
"uses": [
{"path": "sass:color", "statement": "@use 'sass:color'", "line": 1}
]
}
]
}
}Git Integration
Automatic Git repository detection with source URLs:
Supported providers:
- GitHub
- GitLab
- Bitbucket
- Azure DevOps
Features:
- Auto-detects repository from
.gitdirectory - Generates source URLs for all files
- Line-specific URLs for entities (e.g.,
#L42) - Branch-aware URLs
- Works with SSH and HTTPS remotes
const result = await parser.parse();
console.log(result.metadata.repository);
// {
// provider: 'github',
// url: 'https://github.com/user/repo',
// branch: 'main',
// rootDir: '/path/to/project'
// }
// All entities include source URLs
const entity = result.entities.get('component:...:MyComponent');
console.log(entity.location.sourceUrl);
// "https://github.com/user/repo/blob/main/src/app/my-component.ts#L15"Creating Custom Visitors
Extend ng-parser with your own pattern extraction:
import { BaseVisitor, type VisitorContext, type Entity } from '@ttwtf/ng-parser';
import * as ts from 'typescript';
interface MyPattern {
pattern: 'my_pattern_type';
entityName: string;
location: any;
}
interface MyResult {
patterns: MyPattern[];
totalPatterns: number;
}
class MyCustomVisitor extends BaseVisitor<MyResult> {
readonly name = 'MyCustomVisitor';
readonly description = 'Extracts custom patterns';
readonly priority = 50;
readonly version = '1.0.0';
private patterns: MyPattern[] = [];
// Visit TypeScript AST nodes to extract patterns
async visitNode(node: ts.Node, context: VisitorContext): Promise<void> {
if (ts.isClassDeclaration(node)) {
// Extract pattern - NO evaluation
this.patterns.push({
pattern: 'my_pattern_type',
entityName: node.name?.getText() || 'unknown',
location: { /* ... */ }
});
}
}
// Visit Angular entities to extract patterns
async visitEntity(entity: Entity, context: VisitorContext): Promise<void> {
if (entity.type === 'component') {
// Extract fact about component
const hasTemplate = !!entity.template;
// Store the FACT, don't evaluate if it's good/bad
}
}
getResults(): MyResult {
return {
patterns: this.patterns,
totalPatterns: this.patterns.length
};
}
reset(): void {
super.reset();
this.patterns = [];
}
}
// Use it
parser.registerVisitor(new MyCustomVisitor());Remember: Visitors should extract patterns, not evaluate them. Leave analysis and recommendations to separate tools that consume the extracted data.
Export Formats
JSON Export
Complete data export with all information:
const json = result.toJSON();Contains: All entities, relationships, metadata, custom analysis, warnings, errors, metrics
Optimizations:
- Removes empty arrays and default values
- Optimized entity structure
- Ready for LLM consumption
SimpleJSON Export
ng-analyzer compatible format:
const simple = result.toSimpleJSON();Features:
- Simplified structure for basic analysis
- Compatible with legacy ng-analyzer tools
- Lightweight output
HTML Export
Interactive visualization with D3.js:
const html = result.toHTML();Features:
- 🎨 Interactive D3.js force-directed dependency graph
- 🔍 Searchable entity explorer
- 📊 Visitor results dashboards (RxJS, Security, Performance)
- 🔗 Clickable Git source URLs
- 📱 Responsive design (mobile-friendly)
- 💾 Self-contained (works offline, no build required)
Use cases:
- Team onboarding - Visual learning for new developers
- Architecture presentations - Interactive demos in meetings
- Code reviews - Shareable offline documentation
- CI/CD docs - Auto-generated project documentation
Examples
Complete working examples in examples/:
| Example | Description | |---------|-------------| | 01-quick-start.ts | Basic parsing with built-in visitors | | 02-custom-visitors.ts | Creating custom analysis visitors | | 03-complete-analysis.ts | Complete workflow with all features |
Run examples:
# Quick start
npx ts-node examples/01-quick-start.ts
# Custom visitors
npx ts-node examples/02-custom-visitors.ts
# Complete analysis
npx ts-node examples/03-complete-analysis.tsConfiguration
const parser = new NgParser({
rootDir: './src', // Required: source directory
includeTests: false, // Optional: include test files
maxDepth: 20, // Optional: directory depth limit
});Use Cases
- 🤖 RAG/LLM Training - Generate structured documentation for AI models
- 📊 Code Analysis Foundations - Extract patterns for analysis tools to evaluate
- 🔍 Codebase Exploration - Understand large Angular projects structure
- 🔒 Security Pattern Detection - Identify security-relevant code for auditing tools
- ⚡ Performance Pattern Detection - Extract patterns for performance analysis
- 📝 Documentation - Auto-generate architecture docs from parsed entities
- 🔄 Migration Analysis - Extract patterns to prepare for Angular upgrades
- 🏗️ Analysis Tool Development - Build custom analyzers on top of extracted data
Requirements
- Node.js ≥ 18.0.0
- TypeScript ≥ 5.4.0
- Angular ≥ 18.0.0 (peer dependency)
Documentation
- CLI Documentation - Command-line interface reference
- Getting Started Guide - Step-by-step tutorial
- Examples - Complete examples with sample app
- Architecture Guide - Two-layer architecture explained
- Code Review Standards - Quality standards
- API Reference - Complete API documentation
- Changelog - Version history
Version Strategy
ng-parser uses peerDependencies to support multiple Angular versions with a single codebase:
- ✅ Your project's Angular version is automatically used
- ✅ No version conflicts
- ✅ Supports Angular 18, 19, and 20
- ✅ Minimal maintenance overhead
FAQ
Q: Can I analyze a specific file instead of the whole project? Currently ng-parser works at the project level. For single-file analysis, use TypeScript Compiler API directly.
Q: What if I only want specific visitors? Only register the visitors you need:
parser.registerVisitor(new SecurityVisitor()); // Only security analysisQ: How do I access specific entity types?
const components = Array.from(result.entities.values())
.filter(e => e.type === 'component');Q: Can I use this in a CI/CD pipeline? Yes! ng-parser works great in automated workflows for code quality checks.
Contributing
Contributions welcome! Please read our Code Review Standards before submitting PRs.
License
MIT © [Your Name]
Support
Made with ❤️ for the Angular community
