Référence API
Gram n'est pas seulement un format de fichier — c'est un pipeline de petites bibliothèques composables. Chaque paquet fait un seul travail et transmet un objet JSON simple au suivant. Vous pouvez utiliser tout le pipeline, ou ne prendre que la brique dont vous avez besoin (ex : uniquement le parser, pour construire un linter).
Installation
npm install @gram-lang/parser @gram-lang/kitchen @gram-lang/analyzer @gram-lang/renderer @gram-lang/format
# ou
bun add @gram-lang/parser @gram-lang/kitchen @gram-lang/analyzer @gram-lang/renderer @gram-lang/formatTous les paquets sont ESM uniquement, sans effets de bord, et s'exécutent partout où JavaScript s'exécute — Node.js, Deno, Bun, environnements edge, ou directement dans le navigateur (voir le Playground pour un exemple entièrement côté client).
Matrice des paquets
| Paquet | Rôle | Point d'entrée principal |
|---|---|---|
@gram-lang/parser | Transforme le texte source .gram en Arbre Syntaxique Abstrait (AST) | getAST(source) |
@gram-lang/kitchen | Compile l'AST en une charge utile structurée, prête au rendu (liste de courses, minutages, registre) | compile(ast, options?) |
@gram-lang/analyzer | Enrichit une recette compilée avec des propriétés physiques (masse, rendement, nutrition, pourcentages boulanger) via une base de données d'ingrédients | analyze(compiled, database, options?) |
@gram-lang/renderer | Effectue le rendu d'une recette (compilée ou analysée) en Markdown ou HTML | toMarkdown / toHTML / toPrintHTML |
@gram-lang/format | Formateur de code canonique pour fichiers .gram (13 règles unifiées) | formatGram(source, options?) |
@gram-lang/i18n | Normalisation partagée des unités/du temps et dictionnaires de chaînes UI utilisés en interne par les paquets ci-dessus | normalizeUnit, getDictionary |
L'analyse est optionnelle : compile() seul fournit déjà une recette complète et prête au rendu (avec des quantités non standardisées par défaut). @gram-lang/analyzer n'est nécessaire que pour la conversion de masse, les estimations nutritionnelles, ou les pourcentages boulanger, ce qui nécessite une base de données d'ingrédients.
Raccourci optionnel Node uniquement (@gram-lang/cli)
Si vous vous exécutez dans Node.js et n'avez pas besoin de contrôle étape par étape, @gram-lang/cli — oui, le même paquet qui fournit le binaire gram — exporte aussi une petite surface de bibliothèque :
import { runPipeline, GramCLIError } from '@gram-lang/cli';
const { content, compiled, analyzed } = await runPipeline('recette.gram', {
db: myDatabase, // optionnel — omettez pour sauter l'étape d'analyse
scaleFactor: 2, // optionnel
bakersReference: 'farine', // optionnel
});runPipeline(filePath, options?) lit le fichier, puis enchaîne getAST → compile → (seulement si db est fourni) analyze pour vous, en retournant { content, compiled, analyzed }. Elle lève une GramCLIError (une sous-classe d'Error portant un .exitCode issu de l'enum exporté ExitCode) plutôt qu'une erreur brute — pratique si vous voulez faire correspondre les échecs à vos propres codes de sortie. Elle est Node uniquement (lit le disque via node:fs) ; pour le navigateur ou les environnements edge, composez les paquets individuels comme montré ci-dessous.
Le pipeline complet
import { getAST, GramParseError } from '@gram-lang/parser';
import { compile } from '@gram-lang/kitchen';
import { analyze, validateIngredientDatabase } from '@gram-lang/analyzer';
import { toHTML } from '@gram-lang/renderer';
function renderRecipe(source: string, rawIngredientDb: unknown) {
// 1. Parser le texte .gram en AST
let ast;
try {
ast = getAST(source);
} catch (err) {
if (err instanceof GramParseError) {
console.error(`Erreur de syntaxe à l'offset ${err.offset} : attendu ${err.expected}`);
}
throw err;
}
// 2. Compiler l'AST en une recette structurée (liste de courses, minutages, registre)
const compiled = compile(ast);
// 3. Charger et valider la base de données d'ingrédients, puis enrichir avec les données physiques/nutritionnelles
const { data: database, rejected } = validateIngredientDatabase(rawIngredientDb);
if (rejected.length > 0) {
console.warn('Ingrédients invalides ignorés :', rejected);
}
const { result: analyzed, missingIngredients } = analyze(compiled, database);
// 4. Rendu en HTML
return toHTML(analyzed);
}Remarque : l'appel
analyze()ci-dessus prend la base de données d'ingrédients comme deuxième argument positionnel —analyze(compiled, database, options?)— pas comme un champ d'un objet d'options.
Gérer les erreurs de parsing et les avertissements
getAST() est la seule fonction du pipeline qui lève une exception : une erreur de syntaxe signifie qu'il n'y a pas d'AST à traiter. Chaque étape suivante collecte des avertissements à la place — une recette malformée compile quand même, afin que vous puissiez toujours l'afficher et montrer à l'utilisateur ce qui ne va pas.
GramParseError(levée pargetAST) : possède.message(le texte lisible d'ohm-js, extrait de la source inclus),.offset(décalage en caractères dans l'entrée), et.expected(ce que le parser attendait à cet endroit).CompilationResult.warnings/AnalyzedCompilationResult.warnings(retournés parcompile()et propagés paranalyze()) : un tableau d'objetsWarning— jamais de simples chaînes. Voir la référence des avertissements pour la liste complète des codes et comment les traiter comme des erreurs façon--strict.
Voir aussi : Formats de Données pour la forme des objets JSON circulant entre ces étapes, et Créer une UI personnalisée pour un tutoriel de consommation du JSON final dans un framework frontend.