Skip to content

Changelog

Unreleased

6.0.3

Added

  • Added document symbols for Django template structure outlines.
  • Added hover documentation for Django template tags, filters, libraries, and template references.
  • Added folding ranges for Django template block, comment, and import regions.
  • Added pre-commit hook for running djls check on Django template files.
  • Added rg-style file filtering flags to djls check: -g/--glob for glob patterns, --no-ignore to skip ignore files, -L/--follow for symlinks, -d/--max-depth for recursion depth, --color always|auto|never, and -q/--quiet.
  • Added env_file configuration option for loading environment variables from a .env file into the inspector process.
  • Filesystem cache for template library snapshots (~/.cache/djls/inspector/). On subsequent startups, cached data is loaded in ~2ms instead of waiting 200-700ms for the Python subprocess. The cache is validated in the background on every startup.
  • Internal: Added venv model scanning, workspace model discovery, and Salsa wiring for compute_model_graph — the model graph is now populated from both site-packages and workspace models.py files with automatic invalidation on edit.
  • Internal: Added just dev profile recipe for local flamegraph profiling of benchmarks.
  • Internal: Added [profile.bench] with debug = 2 to Cargo.toml for symbolized bench profiles.

Changed

  • Bumped Rust toolchain from 1.93 to 1.95.
  • Internal: Stabilized benchmarks with sized diagnostics fixtures, repeated microbench companions, validation-rendering contract assertions, and deterministic corpus input ordering.
  • Internal: Combined validation scoping checks for closing and intermediate tags into a single tag-spec pass.
  • Changed djls serve terminal warning output to plain text without decorative separator lines.
  • Improved djls check --quiet performance by counting diagnostics without rendering formatted output.
  • Internal: Consolidated djls-project and djls-python into djls-semantic as the unified Django semantic model.
  • Internal: Renamed template library snapshot types and cache APIs around backend-neutral semantic snapshots instead of inspector responses.
  • Internal: Hid template library inspector request plumbing behind a semantic snapshot fetch API.
  • Internal: Replaced the database inspector handle with a backend-neutral project introspector.
  • Internal: Added a semantic validate_template_file convenience query for file-level template validation.
  • Internal: Unified djls-corpus to repo-only format, removing the PyPI package path. All corpus entries are now [[repo]] in manifest.toml, fetched as git archives. Removed sha2, toml_edit dependencies and the add CLI command.
  • Internal: Added license file fetching to djls-corpus lock. License text is saved to crates/djls-corpus/licenses/ for attribution.
  • Internal: Replaced manual AvailableSymbols cache in TemplateValidator with SymbolIndex. Symbol availability is now precomputed per {% load %} boundary and memoized across revisions, eliminating per-walk rebuilds and hand-rolled invalidation logic.
  • Internal: Moved check_file orchestration and diagnostic rendering into djls-db. Removed djls-ide, djls-templates, and djls-project dependencies from the CLI binary.
  • Internal: Moved extraction orchestration from djls-project to djls-db. Removed unused djls-workspace dependency from djls-project.
  • Widened templatetag extraction to catch any uncaught exception in compilation functions, not just TemplateSyntaxError. Tags that raise ValueError, TypeError, or other exceptions in guards now produce validation constraints.
  • Parallelized inspector subprocess query and filesystem library discovery during startup, hiding discovery latency behind the slower inspector call.
  • Internal: LoadState now borrows &str from LoadedLibraries instead of cloning strings, and compute_loaded_libraries returns a reference via returns(ref). Eliminated all string allocations in available_at.
  • Internal: Consolidated TagIndex from three separate tracked fields into a single roles map, reducing classify from 3 Salsa field accesses to 1. TagClass now borrows from Salsa storage instead of cloning.
  • Internal: Replaced template BlockTree/SemanticForest structure analysis with TemplateTree, a structural semantic projection used by opaque-region computation and future outline features.

Removed

  • Removed support for the deprecated TagSpecs v0.4.0 flat format.
  • Dropped Django 4.2 from supported versions.
  • Dropped Django 5.1 from supported versions.

Fixed

  • Fixed template parser diagnostics to preserve structured parser errors and source spans while retaining the existing T100 diagnostic code. Malformed filter expressions now produce parser errors instead of being silently ignored.
  • Suppressed failed to send notification ERROR log spam during server shutdown by disabling the LSP log forwarding layer on shutdown.
  • Fixed djls check silently ignoring file arguments when - (stdin) was also passed. This command now returns an error for mixed stdin/path input.
  • Fixed djls serve --connection-type tcp silently using stdio. The command now errors with an unsupported-mode message.

6.0.2

Changed

  • Bumped TagSpecs v0.4.0 deprecation removal target from v6.0.2 to v6.0.3.

Fixed

  • Fixed djls check with no arguments silently reading stdin instead of discovering template files. Stdin is now triggered explicitly by passing - as a path.
  • Fixed structural validation (unclosed tags, unbalanced blocks) being silently skipped when no Python inspector data was available. builtin_tag_specs() now provides Django's standard tag definitions as a fallback.

6.0.1

Added

  • Added djls check CLI command for validating Django template files.
  • Added automated extraction of tag and filter validation rules from Python source code.
  • Added diagnostics for tag argument counts (S117), library resolution (S120, S121), and symbol scoping (S118, S119).
  • Added structural validation for {% extends %} placement (S122, S123).

Changed

  • Internal: Extracted concrete Salsa database into new djls-db crate.
  • Internal: Re-architected core analysis pipeline using Salsa for incremental computation.
  • Internal: Consolidated template validation into a single-pass visitor.
  • Internal: Updated completions and snippets to use extracted argument structures.
  • Bumped Rust toolchain from 1.90 to 1.91.

Fixed

  • Fixed a typo in the TagSpecs v0.4.0 deprecation notice; removal is targeted for v6.0.2 (matching the "two releases of warning" policy), not v6.2.0.

6.0.0

Changed

  • Updated TagSpecs to v0.6.0 format with hierarchical [[tagspecs.libraries]] structure

Deprecated

Removed

  • Removed deprecated lazy.lua Neovim plugin spec.

Fixed

  • Fixed false positive "accepts at most N arguments" errors for expressions with operators (e.g., {% if x > 0 %})
  • Fixed false positive errors for quoted strings with spaces (e.g., {% translate "Contact the owner" %})

5.2.4

Added

  • Added diagnostics.severity configuration option for configuring diagnostic severity levels
  • Added pythonpath configuration option for specifying additional Python import paths
  • Added documentation for VS Code extension
  • Added documentation for Zed extension
  • Added documentation for setting up Sublime Text
  • Added documentation for setting up Neovim 0.11+ using vim.lsp.config() and vim.lsp.enable()

Changed

  • Changed user configuration directory paths to use application name only, removing organization identifiers
  • Changed log directory to use XDG cache directories (e.g., ~/.cache/djls on Linux) with /tmp fallback
  • Internal: Refactored workspace to use domain types (FileKind) instead of LSP types (LanguageId)
  • Internal: Added client detection for LSP-specific workarounds (e.g., Sublime Text's html language ID handling)

Deprecated

  • Deprecated lazy.lua Neovim plugin spec. It now only shows a migration warning and will be removed in the next release. See Neovim client docs for the new Neovim 0.11+ configuration approach.

Removed

  • Removed clients/nvim/ directory. Neovim 0.11+ has built-in LSP configuration via vim.lsp.config() which replaces the need for the custom plugin.

5.2.3

Added

  • Added support for Python 3.14

Removed

  • Dropped support for Python 3.9

5.2.2

Added

  • Added support for djhtml file extension
  • Added standalone binary builds for direct installation
  • Added debug Neovim plugin for lsp-devtools and server logs

Changed

  • Reorganized clients directory
  • Internal: Optimized lexer performance with memchr and byte-level whitespace parsing
  • Internal: Simplified background tasks with SessionSnapshot
  • Internal: Refactored LSP boundary with extension traits

Fixed

  • Fixed stale diagnostics and references for templates open in the editor
  • Fixed template file tracking by moving Db methods to SourceDb

5.2.1

Added

  • Added support for Django 6.0
  • Added find references for extends/include tags
  • Added go to definition for extends/include tags

Changed

  • Bumped Rust toolchain from 1.88 to 1.90
  • Internal: Switched Python inspector from PyO3 to IPC-based approach
  • Internal: Refactored various internal components
  • Internal: Improved template parsing performance with token caching
  • Internal: Optimized parser performance
  • Internal: Added benchmarks for performance testing

5.2.0

Added

  • Added context-aware completions with snippets
  • Added support for loading server settings from user files (~/.config/djls/djls.toml) and project files (djls.toml, .djls.toml, and pyproject.toml via [tool.djls] table`)
  • Implemented dynamic settings reloading via workspace/didChangeConfiguration
  • Added venv_path setting to allow explicit configuration of Python virtual environment
  • Added unified file and LSP logging using tracing to server
  • Added virtual FileSystem for workspace file management
  • Implemented textDocument/didSave LSP method
  • Added typed argspecs for LSP snippets to tagspecs configuration

Changed

  • Refactored tagspecs configuration to use array of tables and consistent fields
  • Bumped Rust toolchain from 1.87 to 1.88
  • Bumped PyO3/maturin-action to 1.49.3
  • Bumped Salsa crate from git hash to 0.23.0
  • Internal: Moved task queueing functionality to djls-server crate, renamed from Worker to Queue, and simplified API
  • Internal: Improved Python environment handling, including refactored activation logic
  • Internal: Centralized Python linking build logic into a shared djls-dev crate to reduce duplication
  • Internal: Started Salsa integration for incremental computation with database structure and initial Python environment discovery functionality
  • Internal: Reorganized server crate by moving workspace related code to submodule
  • Internal: Simplified Salsa database management with Clone + Arc<Mutex<Session>>
  • Internal: Moved Salsa database ownership from Workspace to Session
  • Internal: Removed vestigial concrete Project database, keeping trait
  • Internal: Removed global client state in favor of direct Client on server
  • Internal: Simplified span struct and removed Salsa tracking
  • Internal: Added logging macros for tracing migration
  • Internal: Swapped tmux shell script for Rust binary
  • Internal: Added system module to improve reliability of environment discovery tests
  • Internal: Fixed Django project detection to prioritize LSP workspace folder
  • Internal: Added Cargo.lock and relaxed some dependency version constraints

5.2.0a0

Added

  • Added html-django as an alternative Language ID for Django templates
  • Added support for Django 5.2.

Changed

  • Bumped Rust toolchain from 1.83 to 1.86
  • Bumped PyO3 to 0.24.
  • Internal: Renamed template parsing crate to djls-templates
  • Internal: Swapped from tower-lsp to tower-lsp-server for primary LSP framework.

Removed

  • Dropped support for Django 5.0.

5.1.0a2

Added

  • Support for system-wide installation using uv tool or pipx with automatic Python environment detection and virtualenv discovery

Changed

  • Server no longer requires installation in project virtualenv, including robust Python dependency resolution using PATH and site-packages detection

5.1.0a1

Added

  • Basic Neovim plugin

5.1.0a0

Added

  • Created basic crate structure:
    • djls: Main CLI interface
    • djls-project: Django project introspection
    • djls-server: LSP server implementation
    • djls-template-ast: Template parsing
    • djls-worker: Async task management
  • Initial Language Server Protocol support:
    • Document synchronization (open, change, close)
    • Basic diagnostics for template syntax
    • Initial completion provider
  • Basic Django template parsing foundation and support
  • Project introspection capabilities
  • Django templatetag completion for apps in a project's INSTALLED_APPS

New Contributors