cooklang-parse 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +185 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +11538 -0
- package/dist/semantics.d.ts +6 -0
- package/dist/semantics.d.ts.map +1 -0
- package/dist/types.d.ts +46 -0
- package/dist/types.d.ts.map +1 -0
- package/grammars/cooklang.ohm +164 -0
- package/package.json +57 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"semantics.d.ts","sourceRoot":"","sources":["../src/semantics.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,GAAG,MAAM,QAAQ,CAAA;AAG7B,OAAO,KAAK,EACV,cAAc,EAOf,MAAM,SAAS,CAAA;AAEhB,QAAA,MAAM,OAAO,aAA6B,CAAA;AA8T1C,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc,CA0D5D;AAED,OAAO,EAAE,OAAO,EAAE,CAAA"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
export interface SourcePosition {
|
|
2
|
+
line: number;
|
|
3
|
+
column: number;
|
|
4
|
+
offset: number;
|
|
5
|
+
}
|
|
6
|
+
export interface ParseError {
|
|
7
|
+
message: string;
|
|
8
|
+
shortMessage?: string;
|
|
9
|
+
position: SourcePosition;
|
|
10
|
+
severity: "error" | "warning";
|
|
11
|
+
}
|
|
12
|
+
export interface CooklangRecipe {
|
|
13
|
+
metadata: Record<string, unknown>;
|
|
14
|
+
steps: RecipeStepItem[][];
|
|
15
|
+
ingredients: RecipeIngredient[];
|
|
16
|
+
cookware: RecipeCookware[];
|
|
17
|
+
timers: RecipeTimer[];
|
|
18
|
+
sections: string[];
|
|
19
|
+
notes: string[];
|
|
20
|
+
errors: ParseError[];
|
|
21
|
+
}
|
|
22
|
+
export type RecipeStepItem = {
|
|
23
|
+
type: "text";
|
|
24
|
+
value: string;
|
|
25
|
+
} | RecipeIngredient | RecipeCookware | RecipeTimer;
|
|
26
|
+
export interface RecipeIngredient {
|
|
27
|
+
type: "ingredient";
|
|
28
|
+
name: string;
|
|
29
|
+
quantity: number | string;
|
|
30
|
+
units: string;
|
|
31
|
+
fixed: boolean;
|
|
32
|
+
preparation?: string;
|
|
33
|
+
}
|
|
34
|
+
export interface RecipeCookware {
|
|
35
|
+
type: "cookware";
|
|
36
|
+
name: string;
|
|
37
|
+
quantity: number | string;
|
|
38
|
+
units: string;
|
|
39
|
+
}
|
|
40
|
+
export interface RecipeTimer {
|
|
41
|
+
type: "timer";
|
|
42
|
+
name: string;
|
|
43
|
+
quantity: number | string;
|
|
44
|
+
units: string;
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAA;IACf,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,QAAQ,EAAE,cAAc,CAAA;IACxB,QAAQ,EAAE,OAAO,GAAG,SAAS,CAAA;CAC9B;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACjC,KAAK,EAAE,cAAc,EAAE,EAAE,CAAA;IACzB,WAAW,EAAE,gBAAgB,EAAE,CAAA;IAC/B,QAAQ,EAAE,cAAc,EAAE,CAAA;IAC1B,MAAM,EAAE,WAAW,EAAE,CAAA;IACrB,QAAQ,EAAE,MAAM,EAAE,CAAA;IAClB,KAAK,EAAE,MAAM,EAAE,CAAA;IACf,MAAM,EAAE,UAAU,EAAE,CAAA;CACrB;AAED,MAAM,MAAM,cAAc,GACtB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAC/B,gBAAgB,GAChB,cAAc,GACd,WAAW,CAAA;AAEf,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,YAAY,CAAA;IAClB,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAA;IACzB,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,OAAO,CAAA;IACd,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,UAAU,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAA;IACzB,KAAK,EAAE,MAAM,CAAA;CACd;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,OAAO,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAA;IACzB,KAAK,EAAE,MAAM,CAAA;CACd"}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cooklang Grammar for Ohm
|
|
3
|
+
* Based on the official Cooklang specification at https://cooklang.org/docs/spec/
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
Cooklang {
|
|
7
|
+
// Main recipe structure
|
|
8
|
+
Recipe
|
|
9
|
+
= Metadata? RecipeItem*
|
|
10
|
+
|
|
11
|
+
// Recipe items can be interleaved
|
|
12
|
+
RecipeItem
|
|
13
|
+
= Section | Note | BlockComment | CommentLine | blankLine | spaceOnly | Step
|
|
14
|
+
|
|
15
|
+
// YAML front matter metadata
|
|
16
|
+
Metadata
|
|
17
|
+
= "---" YamlContent "---"
|
|
18
|
+
|
|
19
|
+
YamlContent
|
|
20
|
+
= (~"---" any)*
|
|
21
|
+
|
|
22
|
+
// Named section ==Name==
|
|
23
|
+
Section
|
|
24
|
+
= "==" sectionName "==" -- double
|
|
25
|
+
| "=" sectionName -- single
|
|
26
|
+
|
|
27
|
+
sectionName
|
|
28
|
+
= (~"==" ~newline any)+
|
|
29
|
+
|
|
30
|
+
// Recipe step - paragraphs separated by blank lines
|
|
31
|
+
Step
|
|
32
|
+
= StepLine+
|
|
33
|
+
|
|
34
|
+
StepLine
|
|
35
|
+
= ~(hspace* "-- ") ~(hspace* newline) ~sectionStart StepItem+ InlineComment? "\n"?
|
|
36
|
+
|
|
37
|
+
sectionStart
|
|
38
|
+
= "==" | "=" ~"=" ~"@"
|
|
39
|
+
|
|
40
|
+
// Items that can appear in a step
|
|
41
|
+
StepItem
|
|
42
|
+
= Ingredient | Cookware | Timer | Text
|
|
43
|
+
|
|
44
|
+
// Text without special Cooklang syntax
|
|
45
|
+
Text
|
|
46
|
+
= (~("\n" | "\r\n" | "\r" | "=" &"@" | "@" &ingredientStartChar | "#" &cookwareStartChar | "~" &wordChar | "~" &"{" | "-- " | "[-") any)+
|
|
47
|
+
|
|
48
|
+
ingredientStartChar
|
|
49
|
+
= wordChar | "@" | "&" | "?" | "+" | "-"
|
|
50
|
+
|
|
51
|
+
cookwareStartChar
|
|
52
|
+
= wordChar | "&" | "?" | "+" | "-"
|
|
53
|
+
|
|
54
|
+
// Ingredient: @name{quantity%unit} or @multi word name{}
|
|
55
|
+
// Fixed quantity: =@name{quantity%unit}
|
|
56
|
+
Ingredient
|
|
57
|
+
= FixedIndicator? "@" ingredientModifiers ingredientWord (hspace+ ingredientWord)+ ingredientAmount ingredientPreparation? -- multi
|
|
58
|
+
| FixedIndicator? "@" ingredientModifiers ingredientWord ingredientAmount? ingredientPreparation? -- single
|
|
59
|
+
|
|
60
|
+
ingredientPreparation
|
|
61
|
+
= "(" (~")" ~newline any)* ")"
|
|
62
|
+
|
|
63
|
+
ingredientModifiers
|
|
64
|
+
= ("@" | "&" | "?" | "+" | "-")*
|
|
65
|
+
|
|
66
|
+
ingredientWord
|
|
67
|
+
= componentWordChar+
|
|
68
|
+
|
|
69
|
+
ingredientAmount
|
|
70
|
+
= "{" (~"}" any)* "}"
|
|
71
|
+
|
|
72
|
+
FixedIndicator
|
|
73
|
+
= "="
|
|
74
|
+
|
|
75
|
+
// Cookware: #name or #multi word{}
|
|
76
|
+
Cookware
|
|
77
|
+
= "#" cookwareModifiers cookwareWord (hspace+ cookwareWord)+ cookwareAmount -- multi
|
|
78
|
+
| "#" cookwareModifiers cookwareWord cookwareAmount? -- single
|
|
79
|
+
|
|
80
|
+
cookwareModifiers
|
|
81
|
+
= ("&" | "?" | "+" | "-")*
|
|
82
|
+
|
|
83
|
+
cookwareWord
|
|
84
|
+
= componentWordChar+
|
|
85
|
+
|
|
86
|
+
cookwareAmount
|
|
87
|
+
= "{" (~"}" any)* "}"
|
|
88
|
+
|
|
89
|
+
// Timer: ~{quantity%unit} or ~name{quantity%unit}
|
|
90
|
+
Timer
|
|
91
|
+
= "~" timerName? "{" timerQuantity timerUnit? "}" -- withAmount
|
|
92
|
+
| "~" timerName -- word
|
|
93
|
+
|
|
94
|
+
timerName
|
|
95
|
+
= word+
|
|
96
|
+
|
|
97
|
+
timerQuantity
|
|
98
|
+
= (~"%" ~"}" any)+
|
|
99
|
+
|
|
100
|
+
timerUnit
|
|
101
|
+
= "%" (~"}" any)+
|
|
102
|
+
|
|
103
|
+
// Note lines (start with >)
|
|
104
|
+
Note
|
|
105
|
+
= ">" noteText Newline?
|
|
106
|
+
|
|
107
|
+
noteText
|
|
108
|
+
= (~"\n" ~"\r" ~">" any)+
|
|
109
|
+
|
|
110
|
+
// Inline comment: -- comment
|
|
111
|
+
InlineComment
|
|
112
|
+
= "-- " (~Newline any)*
|
|
113
|
+
|
|
114
|
+
// Full-line comments
|
|
115
|
+
CommentLine
|
|
116
|
+
= hspace* InlineComment Newline?
|
|
117
|
+
|
|
118
|
+
// Block comment: [- comment -]
|
|
119
|
+
BlockComment
|
|
120
|
+
= "[-" (~"-]" any)+ "-]"
|
|
121
|
+
|
|
122
|
+
// Component name word char - wordChar plus | for alias syntax
|
|
123
|
+
componentWordChar
|
|
124
|
+
= wordChar | "|"
|
|
125
|
+
|
|
126
|
+
// Basic tokens
|
|
127
|
+
word
|
|
128
|
+
= wordChar+
|
|
129
|
+
|
|
130
|
+
wordChar
|
|
131
|
+
= letter | digit | "_" | "-" | emoji | otherWordChar
|
|
132
|
+
|
|
133
|
+
emoji
|
|
134
|
+
= "\u{1F600}".."\u{1F64F}"
|
|
135
|
+
| "\u{1F300}".."\u{1F5FF}"
|
|
136
|
+
| "\u{1F680}".."\u{1F6FF}"
|
|
137
|
+
| "\u{2600}".."\u{26FF}"
|
|
138
|
+
| "\u{2700}".."\u{27BF}"
|
|
139
|
+
| "\u{1F900}".."\u{1F9FF}"
|
|
140
|
+
| "\u{1FA70}".."\u{1FAFF}"
|
|
141
|
+
|
|
142
|
+
otherWordChar
|
|
143
|
+
= "\u00C0".."\u00FF"
|
|
144
|
+
| "\u0100".."\u017F"
|
|
145
|
+
| "\u0400".."\u04FF"
|
|
146
|
+
|
|
147
|
+
newline
|
|
148
|
+
= "\n" | "\r\n" | "\r"
|
|
149
|
+
|
|
150
|
+
Newline
|
|
151
|
+
= newline
|
|
152
|
+
|
|
153
|
+
blankLine
|
|
154
|
+
= hspace* newline
|
|
155
|
+
|
|
156
|
+
spaceOnly
|
|
157
|
+
= hspace+ &end
|
|
158
|
+
|
|
159
|
+
hspace
|
|
160
|
+
= " " | "\t"
|
|
161
|
+
|
|
162
|
+
// Keep Ohm's implicit skipping from crossing lines.
|
|
163
|
+
space := "\t"
|
|
164
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "cooklang-parse",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "A simple, type-safe Cooklang parser built with Ohm.js",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"module": "dist/index.js",
|
|
8
|
+
"types": "dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist",
|
|
17
|
+
"grammars"
|
|
18
|
+
],
|
|
19
|
+
"license": "MIT",
|
|
20
|
+
"repository": {
|
|
21
|
+
"type": "git",
|
|
22
|
+
"url": "git+https://github.com/briansunter/cooklang-parse.git"
|
|
23
|
+
},
|
|
24
|
+
"homepage": "https://github.com/briansunter/cooklang-parse#readme",
|
|
25
|
+
"bugs": {
|
|
26
|
+
"url": "https://github.com/briansunter/cooklang-parse/issues"
|
|
27
|
+
},
|
|
28
|
+
"author": "Brian Sunter",
|
|
29
|
+
"keywords": [
|
|
30
|
+
"cooklang",
|
|
31
|
+
"parser",
|
|
32
|
+
"recipe",
|
|
33
|
+
"cooking",
|
|
34
|
+
"ohm",
|
|
35
|
+
"peg"
|
|
36
|
+
],
|
|
37
|
+
"scripts": {
|
|
38
|
+
"build": "bun build src/index.ts --outdir dist --target=node --format=esm && tsc -p tsconfig.build.json",
|
|
39
|
+
"typecheck": "tsc --noEmit",
|
|
40
|
+
"lint": "biome check src/",
|
|
41
|
+
"lint:fix": "biome check --write src/",
|
|
42
|
+
"format": "biome format --write src/",
|
|
43
|
+
"check": "biome check src/",
|
|
44
|
+
"test": "bun test"
|
|
45
|
+
},
|
|
46
|
+
"devDependencies": {
|
|
47
|
+
"@biomejs/biome": "^2.3.11",
|
|
48
|
+
"@types/bun": "latest"
|
|
49
|
+
},
|
|
50
|
+
"peerDependencies": {
|
|
51
|
+
"typescript": "^5"
|
|
52
|
+
},
|
|
53
|
+
"dependencies": {
|
|
54
|
+
"ohm-js": "^17.3.0",
|
|
55
|
+
"yaml": "^2.8.2"
|
|
56
|
+
}
|
|
57
|
+
}
|