Skip to content

rolandzwaga/eligian

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Eligian: DSL & Compiler for Eligius Story Telling Engine

License: MIT TypeScript Node.js

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 .eligian file 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.

🎯 What is Eligius?

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.

🚨 The Problem: JSON Verbosity

Eligius is configured entirely through JSON, which becomes unwieldy for complex presentations. Eligian solves this with a concise, readable syntax.

Example: Before & After

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!

✨ Key Features

🎨 Concise, Readable Syntax

  • 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/else conditionals, for loops, break/continue statements
  • 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

πŸ”’ Type-Safe Compilation

  • 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

πŸš€ IDE Support via VS Code Extension

  • 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

⚑ Powerful Compiler

  • 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

πŸ§ͺ Comprehensive Testing

  • 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

πŸ“¦ Project Structure

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

πŸ—οΈ Architecture

Technology Stack

  • 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)

Compilation Pipeline

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.

Design Principles

Following our project constitution:

  1. Simplicity First: Clear, well-documented code over clever abstractions
  2. Comprehensive Testing: 379 tests covering all components
  3. Functional Programming: Immutable external API, internal mutation allowed for performance
  4. Type Safety: Leverage TypeScript's type system
  5. Developer Experience: Clear error messages with source locations and actionable hints

πŸš€ Quick Start

Prerequisites

  • Node.js: v20 or later (LTS recommended)
  • pnpm: v8 or later (package manager)
  • VS Code: v1.80 or later (for extension)

Installation

# 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 test

Your First Eligian Program

Create 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!")
  }
}

Preview in VS Code

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

Compile to Eligius JSON (CLI)

# CLI is in development - for now, use the VS Code extension preview
# The compiled JSON is generated automatically when you use the preview

πŸ“š DSL Syntax Overview

Action Definitions

Define reusable actions with parameters:

action fadeIn(selector, duration) [
  selectElement(selector)
  animate({opacity: 1}, duration)
]

// Call the action
fadeIn("#title", 500)

Type Annotations (Optional)

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.

Control Flow

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)
}

Variable References

Access system properties with @@ prefix:

  • @@item - Current loop variable (alias for @@currentItem in loops)
  • @@currentItem - Current item in a loop
  • @@loopIndex - Current loop index (0-based)
  • @@loopLength - Total loop iterations

Built-in Operations

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.

Comments

// Single-line comment

/* Multi-line
   comment */

🎨 VS Code Extension

Features

  • βœ… 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
  • ⏳ Quick Fixes: Automatic corrections (planned)

Installation (Development)

  1. Open the project in VS Code
  2. Press F5 to launch Extension Development Host
  3. Create a .eligian file in the development window
  4. Start typing to see code completion!

Usage

Trigger Code Completion:

  • Type operation name: sel β†’ suggests selectElement
  • 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+Space to 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 .eligian file - preview updates in real-time
  • Edit imported CSS files - styles hot-reload in preview
  • Compilation errors shown in preview panel with source locations

πŸ§ͺ Development

Setup

# Install dependencies
pnpm install

# Build all packages
pnpm run build

# Run tests
pnpm test

# Watch mode (rebuild on changes)
pnpm run watch

Project Scripts

pnpm 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

Testing

# 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 -- --coverage

Code Quality

This 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 ci

All code changes must pass Biome checks before commit (Constitution Principle XI).

πŸ“– Documentation

Recent Feature Specs

πŸ—ΊοΈ Project Status

Completed Features βœ…

  • βœ… 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 .eligian library files
  • βœ… Asset Loading: CSS and HTML file imports with validation
  • βœ… Metadata Generation: Auto-generated operation registry from Eligius source

In Progress 🚧

  • 🚧 CLI Compiler: Command-line interface (architecture ready, implementation pending)

Planned ⏳

  • ⏳ 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)

🎯 Architecture Highlights

Loop Control Syntactic Sugar

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.

Type System

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.

Code Completion

Smart, context-aware completions with intelligent sorting:

  1. Loop variables first: @@item (most relevant in loops)
  2. System properties: @@currentItem, @@loopIndex
  3. Action parameters: Available parameters in current scope
  4. 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.

🀝 Related Projects

  • Eligius: The Story Telling Engine this DSL targets
  • Langium: Language workbench used for grammar and language server

πŸ“„ License

MIT License - see LICENSE file for details

πŸ‘₯ Contributors

  • Roland Zwaga - Creator of Eligius and Eligian DSL
  • Claude Code - AI pair programmer assisting with implementation

πŸ™ Acknowledgments

  • TypeFox for creating Langium
  • The TypeScript and Node.js communities

πŸ“ž Support


Built with ❀️ using TypeScript and Langium

About

A DSL for Eligius presentations

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •