Skip to content

Commit 2fd1d45

Browse files
committed
docs: add guide for product catalog syntax
1 parent 1240f53 commit 2fd1d45

3 files changed

Lines changed: 127 additions & 0 deletions

File tree

docs/.vitepress/config.mts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ export default defineConfig({
3939
{ text: "Extensions", link: "/guide-extensions" },
4040
{ text: "Unit conversion", link: "/guide-unit-conversion" },
4141
{ text: "Rendering recipes", link: "/guide-rendering" },
42+
{ text: "Product catalog syntax", link: "/guide-product-catalog" },
4243
],
4344
collapsed: true
4445
},

docs/guide-product-catalog.md

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
---
2+
outline: deep
3+
---
4+
5+
# Guide: product catalog syntax
6+
7+
`ProductCatalog` reads a TOML catalog that groups purchasable products by ingredient name. The format is intentionally compact, but it supports a few equivalent ways to describe the same product entries.
8+
9+
## Overview
10+
11+
At the top level, each TOML table is an ingredient name such as `eggs` or `flour`. Inside that table you can define:
12+
13+
- `aliases`: optional alternative ingredient names
14+
- product entries:
15+
- keys can be any string except the reserved `aliases` key
16+
- each entry must include `name`, `size`, and `price`.
17+
- arbitrary extra metadata can also be defined
18+
19+
20+
## Catalog shapes
21+
22+
You can write product entries in either canonical nested-table form or dotted-table form. Both parse to the same catalog.
23+
24+
### Canonical nested form
25+
26+
```toml
27+
[eggs]
28+
aliases = ["oeuf", "huevo"]
29+
single = { name = "Single Egg", size = "1", price = 2 }
30+
pack-6 = { name = "Pack of 6 eggs", size = "6", price = 10 }
31+
32+
[flour]
33+
aliases = ["farine", "Mehl"]
34+
01124 = { name = "Small pack", size = "100%g", price = 1.5 }
35+
14141 = { name = "Big pack", size = "6%kg", price = 10, image = "flour.png" }
36+
```
37+
38+
### Equivalent dotted-table form
39+
40+
```toml
41+
[eggs.pack-6]
42+
price = 10
43+
name = "Pack of 6 eggs"
44+
size = "6"
45+
46+
[eggs.single]
47+
price = 2
48+
name = "Single Egg"
49+
size = "1"
50+
51+
[flour.big-pack]
52+
price = 10
53+
name = "Big pack"
54+
size = "6%kg"
55+
56+
[flour.small-pack]
57+
price = 1.5
58+
name = "Small pack"
59+
size = "100%g"
60+
```
61+
62+
## Size syntax
63+
64+
The `size` field accepts either a single string or an array of strings.
65+
66+
Single sizes:
67+
68+
```toml
69+
[eggs]
70+
single = { name = "Single Egg", size = "1", price = 2 }
71+
```
72+
73+
Sizes with a unit:
74+
75+
```toml
76+
[flour]
77+
small-pack = { name = "Small pack", size = "100%g", price = 1.5 }
78+
```
79+
80+
Multiple equivalent sizes for the same product:
81+
82+
```toml
83+
[eggs]
84+
pack-of-12 = { name = "Pack of 12 eggs", size = ["1%dozen", "12"], price = 18 }
85+
```
86+
87+
## Metadata and aliases
88+
89+
Any additional keys on a product entry are preserved as metadata when parsing and are written back when stringifying.
90+
91+
```toml
92+
[flour]
93+
small-pack = { name = "Small pack", size = "100%g", price = 1.5, image = "flour.png" }
94+
```
95+
96+
`aliases` belongs on the ingredient table, not on the product entry. It is parsed as an array of alternate ingredient names:
97+
98+
```toml
99+
[eggs]
100+
aliases = ["oeuf", "huevo"]
101+
single = { name = "Single Egg", size = "1", price = 2 }
102+
```
103+
104+
## Full example
105+
106+
```typescript
107+
import { ProductCatalog } from "@tmlmt/cooklang-parser";
108+
109+
const catalog = new ProductCatalog(`
110+
[eggs]
111+
aliases = ["oeuf", "huevo"]
112+
01123 = { name = "Single Egg", size = "1", price = 2 }
113+
11244 = { name = "Pack of 6 eggs", size = "6", price = 10 }
114+
115+
[flour]
116+
aliases = ["farine", "Mehl"]
117+
01124 = { name = "Small pack", size = "100%g", price = 1.5 }
118+
14141 = { name = "Big pack", size = "6%kg", price = 10, image = "flour.png" }
119+
`);
120+
121+
const eggs = catalog.products.find((product) => product.ingredientName === "eggs");
122+
```
123+
124+
If you only need a compact reference, the API page for [ProductCatalog](/api/classes/ProductCatalog) links back here.

src/classes/product_catalog.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ import { InvalidProductCatalogFormat } from "../errors";
3030
* `size` can be a single string such as `"1"` or `"100%g"`, or an array of equivalent sizes such as `['1%dozen', '12']`.
3131
* - arbitrary metadata on each product entry, which is preserved when parsing.
3232
*
33+
* See the [product catalog guide](/guide-product-catalog) for the full syntax and examples.
34+
*
3335
* @category Classes
3436
*
3537
* @example

0 commit comments

Comments
 (0)