Eligian is a domain-specific language (DSL) and compiler for the Eligius Story Telling Engine. It dramatically reduces the verbosity of Eligius JSON configurations by 70-80% while providing type safety, IDE support, and a more intuitive syntax for creating timeline-based interactive presentations.
For a full current spec of the language check this
π File Extension: Eligian programs use the
.eligianfile extension (e.g.,my-timeline.eligian).
NOTE: This is very much a work in progress still, so the language is in flux, half-ready and far from suitable for anything production level.
Eligius is a JavaScript engine that triggers arbitrary functionality according to a timeline provider (video, audio, requestAnimationFrame, etc.). It's designed for:
- Video annotations: Overlay text, graphics, or interactive elements synchronized with video playback
- Presentation software: Create slide decks with timed transitions and animations
- Interactive infographics: Build data visualizations that unfold over time
- Audio-driven experiences: Synchronize visuals with audio narration or music
Eligius is not a game or animation engineβit's a Story Telling Engine focused on narratives structured around time.
Eligius is configured entirely through JSON, which becomes unwieldy for complex presentations. Eligian solves this with a concise, readable syntax.
Before (Eligius JSON) - verbose and error-prone:
{
"actions": [
{
"name": "fadeIn",
"startOperations": [
{
"systemName": "selectElement",
"operationData": {
"selector": "parameter:selector"
}
},
{
"systemName": "animate",
"operationData": {
"animationProperties": {
"opacity": 1
},
"animationDuration": "parameter:duration"
}
}
],
"endOperations": []
}
]
}After (Eligian DSL) - clean and intuitive:
action fadeIn(selector, duration) [
selectElement(selector)
animate({opacity: 1}, duration)
]
70-80% less code, with the same functionality!
- Action definitions: Define reusable operations with parameters and JSDoc documentation
- Timeline operations: 45+ built-in operations from Eligius (DOM, animation, data, events, etc.)
- Custom actions: Call your own defined actions alongside built-in operations
- Control flow:
if/elseconditionals,forloops,break/continuestatements - Variable references: Access loop variables (
@@item), system properties (@@currentItem,@@loopIndex) - Asset imports: CSS, HTML, and library file imports with validation
- Event actions: Runtime event handlers with compile-time validation
- Compile-time validation: Catch errors before runtime
- Type checking: Optional type annotations with inference (TypeScript-inspired)
- Semantic validation: Duplicate detection, scope checking, constraint validation
- Source location tracking: Error messages show exact line/column with helpful hints
- Syntax highlighting: Keywords, identifiers, literals beautifully colored
- Code completion:
- β Operation names with descriptions and parameter info
- β Custom action names with signatures
- β Event action skeleton generation (43 Eligius events)
- β Loop variables and system properties
- β
JSDoc template auto-generation (
/**+ Enter) - Context-aware filtering (only valid items at cursor position)
- Live preview: Compile and preview timelines in real-time with CSS hot-reload
- Real-time diagnostics: Error detection as you type
- CSS validation: Class name validation with "Did you mean?" suggestions
- Hover documentation: View JSDoc, CSS rule locations, and type information
- Built with Langium (language workbench) and TypeScript
- Multi-stage pipeline: Parse β Validate β Type Check β Transform β Optimize β Emit
- Metadata generation: Auto-generates operation registry from Eligius source
- Optimization: Constant folding, dead code elimination
- Source maps: Track DSL locations through to JSON output
- 1,758 tests passing across all packages
- Grammar parsing tests
- Semantic validation tests
- Type system tests (Typir integration)
- Compiler pipeline tests
- Code completion tests
- CSS validation tests
- JSDoc documentation tests
- 81.72% code coverage
Eligian is organized as a monorepo with three packages:
packages/
βββ language/ # Langium grammar and language server
β βββ src/
β β βββ eligian.langium # DSL grammar definition
β β βββ eligian-validator.ts # Semantic validation rules
β β βββ eligian-completion-provider.ts # Code completion
β β βββ type-system-typir/ # Typir-based type system
β β βββ compiler/ # AST β JSON transformer
β β βββ completion/ # Completion modules
β β βββ css/ # CSS validation and hover
β β βββ jsdoc/ # JSDoc parsing and generation
β β βββ __tests__/ # Comprehensive test suites
β βββ package.json
β
βββ cli/ # Command-line compiler
β βββ src/
β β βββ main.ts
β βββ package.json
β
βββ extension/ # VS Code extension
βββ src/
β βββ extension/ # Extension entry point
β β βββ preview/ # Live preview manager
β β βββ commands/ # Extension commands
β βββ language/ # Language server entry point
βββ package.json
- Language: TypeScript (compiled to JavaScript for Node.js runtime)
- Grammar Framework: Langium - TypeScript-based language workbench
- Build Tools: esbuild (fast bundling), Vitest (testing), Biome (linting/formatting)
- Target Platform: Node.js 20+ (CLI), VS Code 1.80+ (extension)
The compiler uses a six-stage pipeline:
DSL Source (.eligian)
β
[1] Parse (Langium) β AST
β
[2] Validate β Validated AST (semantic checks)
β
[3] Type Check β Typed AST (optional type annotations + inference)
β
[4] Transform β Eligius Configuration Object
β
[5] Optimize β Optimized Configuration (constant folding, etc.)
β
[6] Emit β Eligius JSON
Each stage has comprehensive error handling with source location tracking.
Following our project constitution:
- Simplicity First: Clear, well-documented code over clever abstractions
- Comprehensive Testing: 379 tests covering all components
- Functional Programming: Immutable external API, internal mutation allowed for performance
- Type Safety: Leverage TypeScript's type system
- Developer Experience: Clear error messages with source locations and actionable hints
- Node.js: v20 or later (LTS recommended)
- pnpm: v8 or later (package manager)
- VS Code: v1.80 or later (for extension)
# Clone the repository
git clone https://github.com/rolandzwaga/eligian.git
cd eligian
# Install dependencies
pnpm install
# Build all packages
pnpm run build
# Run tests
pnpm testCreate example.eligian:
// Import CSS styles
styles "./styles.css"
// Define a reusable fade-in action
action fadeIn(selector: string, duration: number) [
selectElement(selector)
animate({opacity: 1}, duration)
]
// Define a timeline with events
timeline "My First Timeline" in "#app" using raf {
// Event at 0 seconds: fade in the title
at 0s..2s [
fadeIn("#title", 1000)
] [
selectElement("#title")
animate({opacity: 0}, 500)
]
// Event at 2 seconds: show multiple items with a loop
at 2s..5s for (item in ["#item1", "#item2", "#item3"]) {
fadeIn(@@item, 500)
wait(200)
}
// Event at 5 seconds: conditional logic
at 5s..5s if (true) {
log("Timeline complete!")
}
}
The easiest way to see your Eligian program in action:
# 1. Open example.eligian in VS Code
# 2. Press Ctrl+Shift+P β "Eligian: Start Preview"
# 3. Edit your file - preview updates in real-time# CLI is in development - for now, use the VS Code extension preview
# The compiled JSON is generated automatically when you use the previewDefine reusable actions with parameters:
action fadeIn(selector, duration) [
selectElement(selector)
animate({opacity: 1}, duration)
]
// Call the action
fadeIn("#title", 500)
Add type hints for better IDE support:
action fadeIn(selector: string, duration: number) [
selectElement(selector)
animate({opacity: 1}, duration)
]
Types are optional - the compiler infers types from operation usage if not specified.
If/Else Conditionals:
action processItem(item) [
if (@@loopIndex === 0) {
selectElement(item)
} else {
animate(item, {opacity: 0.5})
}
]
For Loops:
action animateAll(items) [
for (item in items) {
fadeIn(@@item, 500) // @@item is the loop variable
}
]
Break/Continue:
for (item in items) {
if (@@currentItem.skip) {
continue // Skip to next iteration
}
if (@@currentItem.stop) {
break // Exit loop
}
processItem(@@currentItem)
}
Access system properties with @@ prefix:
@@item- Current loop variable (alias for@@currentItemin loops)@@currentItem- Current item in a loop@@loopIndex- Current loop index (0-based)@@loopLength- Total loop iterations
45+ operations from Eligius, including:
DOM Operations:
selectElement(selector)
createElement(tagName, attributes)
removeElement(selector)
Animation:
animate(properties, duration)
setStyle(selector, property, value)
Data Management:
setData(key, value)
getData(key)
mergeData(key, value)
Control Flow:
runAction(actionName, ...args)
delay(milliseconds)
See the complete list of Eligius operations in the Eligius repository.
// Single-line comment
/* Multi-line
comment */
- β Syntax Highlighting: Keywords, identifiers, literals
- β
Code Completion:
- Operation names (45+ operations) with descriptions
- Custom action names with parameter signatures and JSDoc
- Event action skeletons (43 Eligius events with auto-generated handlers)
- JSDoc template generation (
/**+ Enter above actions) - Loop variables (
@@item,@@currentItem, etc.) - Smart sorting (most relevant items first)
- β Live Preview: Compile and preview timelines in real-time with CSS hot-reload
- β Real-time Validation: Error detection as you type with helpful hints
- β
Hover Information:
- JSDoc documentation on action hover
- CSS class/ID source locations with rule snippets
- Type information from Typir type system
- β
CSS Support:
- Import CSS files with
styles "./file.css" - Real-time class name validation with "Did you mean?" suggestions
- Hot-reload CSS changes without restarting timeline
- Import CSS files with
- β³ Quick Fixes: Automatic corrections (planned)
- Open the project in VS Code
- Press F5 to launch Extension Development Host
- Create a
.eligianfile in the development window - Start typing to see code completion!
Trigger Code Completion:
- Type operation name:
selβ suggestsselectElement - Type custom action: Start typing action name β suggests defined actions with JSDoc
- Type
on eventβ triggers event action skeleton completion (43 Eligius events) - Type
/**above an action + Enter β generates JSDoc template - Type
@@β suggests loop variables and system properties - Press
Ctrl+Spaceto manually trigger
CSS Support:
- Add
styles "./styles.css"to import CSS files - Edit CSS file β preview hot-reloads automatically (no timeline restart)
- Typo in class name? β Get "Did you mean?" suggestions with Levenshtein distance
Compile & Preview:
- Press
Ctrl+Shift+Pβ "Eligian: Start Preview" - Edit your
.eligianfile - preview updates in real-time - Edit imported CSS files - styles hot-reload in preview
- Compilation errors shown in preview panel with source locations
# Install dependencies
pnpm install
# Build all packages
pnpm run build
# Run tests
pnpm test
# Watch mode (rebuild on changes)
pnpm run watchpnpm run build # Build all packages
pnpm run clean # Remove build artifacts
pnpm test # Run all tests
pnpm run check # Biome format & lint
pnpm run langium:generate # Generate Langium AST types
pnpm run generate:metadata # Generate operation metadata
pnpm run generate:registry # Generate operation registry# Run all tests
pnpm test
# Run specific package tests
cd packages/language && pnpm test
# Run specific test file
cd packages/language && pnpm test completion.spec.ts
# Watch mode
pnpm test -- --watch
# Coverage report
pnpm test -- --coverageThis project uses Biome for formatting and linting:
# Format and lint (auto-fix)
pnpm run check
# Lint only
pnpm run lint
# CI check (no modifications)
pnpm run ciAll code changes must pass Biome checks before commit (Constitution Principle XI).
- Project Constitution: Core principles and guidelines
- DSL Grammar: Complete grammar definition
- Language Specification: Full language specification
- Type System (Typir): Type checking and inference
- Completion System: Code completion modules
- CSS Validation: CSS class validation with Levenshtein suggestions
- JSDoc Support: JSDoc template generation and hover
- Feature Specs: Feature specifications and implementation plans
- JSDoc Documentation: JSDoc template generation and hover (complete)
- Typir Type System: Typir-based type checking (complete)
- CSS Validation: CSS class validation with hot-reload (complete)
- CSS Live Reload: CSS hot-reload in preview (complete)
- Event Actions: Runtime event handlers (complete)
- β Core Language: Grammar, parser, AST with Langium
- β Validation: Semantic validation, scope checking, duplicate detection
- β Type System (Typir): Type annotations, type inference, type checking with Typir
- β Compiler: AST β JSON transformation with constant folding optimization
- β Control Flow: If/else, for loops, break/continue keywords
- β Code Completion: Operations, actions, event skeletons, JSDoc templates
- β Live Preview: Real-time compilation and preview with CSS hot-reload
- β CSS Support: Import CSS files, class validation, hot-reload
- β JSDoc: Template auto-generation and hover documentation
- β Event Actions: Runtime event handlers with validation (43 events)
- β
Library Imports: Import actions from
.eligianlibrary files - β Asset Loading: CSS and HTML file imports with validation
- β Metadata Generation: Auto-generated operation registry from Eligius source
- π§ CLI Compiler: Command-line interface (architecture ready, implementation pending)
- β³ Source Maps: Debug support with source locations
- β³ Package Publishing: NPM package and VS Code marketplace
- β³ Performance Profiling: Optimize compilation and validation performance
Test Coverage: 1,758 tests passing (81.72% coverage)
Clean break and continue keywords that compile to Eligius operations:
for (item in items) {
if (@@currentItem.skip) {
continue // β continueForEach()
}
if (@@currentItem.stop) {
break // β breakForEach()
}
}
See examples/break-continue-demo.eligian for usage examples.
Optional TypeScript-inspired type system with inference:
// Type annotations (optional)
action fadeIn(selector: string, duration: number) [
selectElement(selector) // Type-checked!
animate({opacity: 1}, duration)
]
// Type inference (no annotations needed)
action fadeIn(selector, duration) [
selectElement(selector) // Infers selector: string
animate({opacity: 1}, duration) // Infers duration: number
]
See Type System README for details.
Smart, context-aware completions with intelligent sorting:
- Loop variables first:
@@item(most relevant in loops) - System properties:
@@currentItem,@@loopIndex - Action parameters: Available parameters in current scope
- Literals last:
true,false,null
Operations show full documentation including:
- Description from JSDoc
- Parameter names and types
- Dependencies and outputs
- Usage examples
See Code Completion Spec for implementation details.
- Eligius: The Story Telling Engine this DSL targets
- Langium: Language workbench used for grammar and language server
MIT License - see LICENSE file for details
- Roland Zwaga - Creator of Eligius and Eligian DSL
- Claude Code - AI pair programmer assisting with implementation
- TypeFox for creating Langium
- The TypeScript and Node.js communities
- Issues: GitHub Issues
- Discussions: GitHub Discussions
- Eligius Documentation: Eligius Docs
Built with β€οΈ using TypeScript and Langium