PHPackages                             devapeu/cooklang - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. devapeu/cooklang

ActiveLibrary

devapeu/cooklang
================

A Cooklang recipe parser for PHP.

00PHP

Since Jul 23Pushed todayCompare

[ Source](https://github.com/devapeu/cooklang-php)[ Packagist](https://packagist.org/packages/devapeu/cooklang)[ RSS](/packages/devapeu-cooklang/feed)WikiDiscussions main Synced today

READMEChangelogDependenciesVersions (1)Used By (0)

Cooklang PHP
============

[](#cooklang-php)

A [Cooklang](https://cooklang.org/) recipe parser for PHP.

Installation
------------

[](#installation)

```
composer require devapeu/cooklang
```

Requires PHP 8.0 or higher.

Usage
-----

[](#usage)

```
use Devapeu\Cooklang\CooklangParser;

$recipe = CooklangParser::parse(meta;         // ['servings' => '4']
$recipe->ingredients;  // Ingredient[]
$recipe->cookware;     // ['bowl']
$recipe->instructions; // Instruction[], ingredients wrapped in  tags by default
$recipe->sections;     // Section[]
```

`CooklangParser::parse()` returns a `Devapeu\Cooklang\Models\Recipe`:

PropertyTypeDescription`meta``array`Key/value metadata pairs (`>> key: value`)`ingredients``Ingredient[]`Top-level ingredients (`@ingredient`)`cookware``string[]`Top-level cookware (`#cookware`)`instructions``Instruction[]`Top-level instruction sentences`sections``Section[]`Named sections (`= Section Name`), each with its own `ingredients`, `cookware` and `instructions`Each `Ingredient` has `name`, `quantity`, `measure`, `note`, and `optional`.

Each `Instruction` implements `Stringable` (so it works directly in string interpolation, concatenation, `echo`, etc. with no cast needed), and also exposes `text()` for the raw tagged string explicitly and `plain()` to strip ingredient tags.

### Formatting ingredients, cookware, and timers

[](#formatting-ingredients-cookware-and-timers)

By default, `@ingredient`, `#cookware`, and `~{timer}` references inside `instructions` are each wrapped in a matching tag — ``, ``, and `` respectively (e.g. `2 cups of flour`) — so you can style or target them from HTML/CSS/JS.

If you don't want any markup, call `plainInstructions()` on the `Recipe` (or `Section`) to get all instructions stripped at once, or `plain()` on an individual `Instruction`:

```
echo $recipe->instructions[0];        // "Add 2 cups of flour to the mix." (implicit __toString)
$recipe->instructions[0]->text();     // "Add 2 cups of flour to the mix." (explicit)
$recipe->instructions[0]->plain();    // "Add 2 cups of flour to the mix."
$recipe->plainInstructions()[0];      // "Add 2 cups of flour to the mix."
```

### Serializing

[](#serializing)

`Recipe`, `Section`, `Ingredient`, and `Instruction` all expose `toArray()`, and implement `JsonSerializable`, so you can convert a parsed recipe (recursively, including its sections) to a plain array or JSON:

```
$recipe->toArray(); // ['meta' => [...], 'ingredients' => [...], ..., 'sections' => [...]]
json_encode($recipe);
```

Or customize/disable each tag independently at parse time via `ParserOptions`:

```
use Devapeu\Cooklang\ParserOptions;

CooklangParser::parse($source, new ParserOptions(
    ingredientTag: 'span',
    cookwareTag: 'span',
    timerTag: null, // disables timer tagging entirely
));
```

Supported syntax
----------------

[](#supported-syntax)

- Ingredients: `@name`, `@name{quantity%measure}`, `@*optional ingredient{}`
- Cookware: `#cookware`
- Timers: `~{quantity%measure}`
- Notes: `@ingredient{}(note)`
- Sections: `= Section Name` or `== Section Name ==`
- Comments: `-- line comment` and inline `-- trailing comment`
- Metadata: `>> key: value`, or a YAML frontmatter block delimited by `---` lines (parsed with [`symfony/yaml`](https://symfony.com/doc/current/components/yaml.html), so nested maps and lists are supported)

Testing
-------

[](#testing)

```
composer test
```

License
-------

[](#license)

[MIT](LICENSE)

###  Health Score

20

—

LowBetter than 12% of packages

Maintenance65

Regular maintenance activity

Popularity0

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity11

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/29587074?v=4)[Piero del Valle](/maintainers/devapeu)[@devapeu](https://github.com/devapeu)

---

Top Contributors

[![devapeu](https://avatars.githubusercontent.com/u/29587074?v=4)](https://github.com/devapeu "devapeu (6 commits)")

### Embed Badge

![Health badge](/badges/devapeu-cooklang/health.svg)

```
[![Health](https://phpackages.com/badges/devapeu-cooklang/health.svg)](https://phpackages.com/packages/devapeu-cooklang)
```

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
