Melody Twig Template Parser
melody-parser is an extensible JavaScript parser specifically designed for the Twig template language, generating a detailed Abstract Syntax Tree (AST) from source code. Currently at version 1.7.5, the library maintains a steady release cadence with focus on robustness and extensibility. A key differentiator is its ability to be extended with custom parsing rules via "extensions," allowing it to handle custom Twig tags or specialized template syntaxes beyond standard Twig. It also provides granular control over error handling for unknown tags, differentiating between strict parsing for code generation and lenient parsing for mere AST inspection. It is an essential component for projects requiring deep analysis, transformation, or tooling around Twig templates.
Common errors
-
Error: Unknown tag "mytag"
cause The parser encountered a Twig tag not recognized by its built-in rules or any provided extensions, and the `allowUnknownTags` option was not enabled.fixEnable the `allowUnknownTags` option: `parse(code, { allowUnknownTags: true })`. If 'mytag' is a custom tag you intend to support fully, create and pass a `melody-parser` extension that defines how to parse 'mytag'.
Warnings
- gotcha By default, `melody-parser` throws an error when it encounters an unknown Twig tag. This is strict behavior intended for scenarios where all tags must be explicitly handled (e.g., code generation).
- gotcha Ensure `melody-types` peer dependency is installed and compatible. This package defines the AST node types, and version mismatches could lead to unexpected type errors or runtime issues, especially in TypeScript projects.
Install
-
npm install melody-parser -
yarn add melody-parser -
pnpm add melody-parser
Imports
- parse
const { parse } = require('melody-parser');import { parse } from 'melody-parser'; - coreExtensions (named import from melody-extension-core)
import coreExtensions from 'melody-extension-core';
import { extension as coreExtensions } from 'melody-extension-core'; - customExtension (default import from a custom module)
import customExtension from 'melody-extension-custom';
Quickstart
import { parse } from 'melody-parser';
import { extension as coreExtensions } from 'melody-extension-core';
// Example 1: Basic parsing
const twigCodeBasic = '{% spaceless %} Hello, {{ name }}! {% endspaceless %}';
const astBasic = parse(twigCodeBasic);
console.log('Basic AST:', JSON.stringify(astBasic, null, 2));
// Example 2: Parsing with options
const twigCodeWithOptions = '{# This is a comment #} {{ var }}';
const astWithOptions = parse(twigCodeWithOptions, {
ignoreComments: false, // Ensure comments are included in the AST
decodeEntities: true,
});
console.log('AST with options:', JSON.stringify(astWithOptions, null, 2));
// Example 3: Parsing with extensions (core and a hypothetical custom one)
// For a real custom extension, you'd implement its parser logic.
const customExtension = {
tags: {
exit: {
parse(parser, token) {
// Simplified parsing for an {% exit 404 %} tag
parser.advance(); // consume 'exit'
const parts = [parser.expression()];
parser.expect(token.type, 'end of tag');
return {
type: 'GenericTwigTag',
tagName: 'exit',
parts: parts,
sections: [],
};
}
}
}
};
const twigCodeWithExtensions = '{% exit 404 %}';
const astWithExtensions = parse(
twigCodeWithExtensions,
{ allowUnknownTags: true }, // Important for custom or unknown tags
coreExtensions,
customExtension
);
console.log('AST with extensions:', JSON.stringify(astWithExtensions, null, 2));