@recipe-book/core 0.1.0 → 0.1.2
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/CHANGELOG.md +138 -0
- package/README.md +1 -1
- package/dist/{chunk-VWVIBCTG.cjs → chunk-ISRDJR2O.cjs} +227 -179
- package/dist/chunk-ISRDJR2O.cjs.map +1 -0
- package/dist/errors.js +29 -1
- package/dist/errors.js.map +1 -1
- package/dist/format/duration.js.map +1 -1
- package/dist/format/ingredient.js.map +1 -1
- package/dist/format/number.js +1 -1
- package/dist/format/number.js.map +1 -1
- package/dist/format/options.js.map +1 -1
- package/dist/format/quantity.js.map +1 -1
- package/dist/format/servings.js.map +1 -1
- package/dist/format/temperature.js.map +1 -1
- package/dist/index.cjs +87 -74
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +71 -28
- package/dist/index.d.ts +71 -28
- package/dist/index.js +6 -1
- package/dist/index.js.map +1 -1
- package/dist/ingredient/parse.js +27 -22
- package/dist/ingredient/parse.js.map +1 -1
- package/dist/issues.js.map +1 -1
- package/dist/quantity/amount.js +11 -0
- package/dist/quantity/amount.js.map +1 -1
- package/dist/quantity/parse.js +58 -81
- package/dist/quantity/parse.js.map +1 -1
- package/dist/quantity/scale.js +5 -2
- package/dist/quantity/scale.js.map +1 -1
- package/dist/recipe/ids.js.map +1 -1
- package/dist/recipe/parse.js +80 -60
- package/dist/recipe/parse.js.map +1 -1
- package/dist/recipe/schema.js +8 -6
- package/dist/recipe/schema.js.map +1 -1
- package/dist/resolve.js +6 -1
- package/dist/resolve.js.map +1 -1
- package/dist/schema-org/find.js +46 -13
- package/dist/schema-org/find.js.map +1 -1
- package/dist/schema-org/from-json-ld.js +134 -71
- package/dist/schema-org/from-json-ld.js.map +1 -1
- package/dist/schema-org/text.js.map +1 -1
- package/dist/schema-org/to-json-ld.js +12 -15
- package/dist/schema-org/to-json-ld.js.map +1 -1
- package/dist/schema-org.cjs +239 -147
- package/dist/schema-org.cjs.map +1 -1
- package/dist/schema-org.d.cts +35 -21
- package/dist/schema-org.d.ts +35 -21
- package/dist/steps/segment.js.map +1 -1
- package/dist/steps/temperature.js +13 -13
- package/dist/steps/temperature.js.map +1 -1
- package/dist/{types-DSMf45H5.d.cts → types-CKIoWsz8.d.cts} +25 -7
- package/dist/{types-DSMf45H5.d.ts → types-CKIoWsz8.d.ts} +25 -7
- package/dist/units/convert.js +16 -8
- package/dist/units/convert.js.map +1 -1
- package/dist/units/temperature.js +7 -1
- package/dist/units/temperature.js.map +1 -1
- package/dist/validation.js +1 -1
- package/dist/validation.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-VWVIBCTG.cjs.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/errors.ts","../src/issues.ts","../src/units/registry.ts","../src/suggest.ts","../src/units/lookup.ts","../src/validation.ts","../src/quantity/amount.ts","../src/quantity/parse.ts","../src/recipe/duration.ts","../src/recipe/ids.ts","../src/recipe/infer.ts","../src/recipe/nutrient-units.ts","../src/recipe/nutrition.ts","../src/recipe/url.ts","../src/recipe/parse.ts","../src/ingredient/parse.ts","../src/quantity/scale.ts","../src/units/system.ts","../src/resolve.ts","../src/format/number.ts","../src/format/options.ts","../src/format/quantity.ts","../src/format/ingredient.ts","../src/format/servings.ts"],"names":["error","count","issue","unit","readLine","label","issues","value","range","patterns","getPatterns","compilePatterns","readAmount","whole","rebalance","units","name"],"mappings":"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","file":"chunk-VWVIBCTG.cjs","sourcesContent":["import type { RecipeValidationError } from './validation'\n\nconst DOCS_ORIGIN = 'https://recipe-book.siraj.page'\n\n/**\n * Codes for errors thrown by Recipe Book. May grow in minor releases.\n *\n * @see https://recipe-book.siraj.page/errors\n */\nexport type RecipeBookErrorCode =\n | 'invalid_recipe'\n | 'invalid_quantity'\n | 'invalid_ingredient'\n | 'invalid_argument'\n | 'incompatible_units'\n | 'unknown_unit'\n | 'missing_parent'\n\n/** Codes for problems found in recipe data. May grow in minor releases. */\nexport type RecipeIssueCode =\n | 'invalid_type'\n | 'missing_field'\n | 'unknown_unit'\n | 'invalid_quantity'\n | 'invalid_amount'\n | 'invalid_range'\n | 'invalid_duration'\n | 'invalid_url'\n | 'unknown_field'\n | 'duplicate_id'\n | 'empty_list'\n | 'ignored_value'\n\n/** A problem found in recipe data. Data problems are returned as values, never thrown one by one. */\nexport type RecipeIssue = {\n code: RecipeIssueCode\n severity: 'error' | 'warning'\n /** Location in the input, e.g. `['ingredients', 0, 'quantity']`. */\n path: readonly (string | number)[]\n /** A complete sentence that names the fix. */\n message: string\n /** The value the input most likely meant, for \"did you mean\" hints. */\n suggestion?: string | undefined\n}\n\nconst ERROR_CODES: ReadonlySet<unknown> = new Set<RecipeBookErrorCode>([\n 'invalid_recipe',\n 'invalid_quantity',\n 'invalid_ingredient',\n 'invalid_argument',\n 'incompatible_units',\n 'unknown_unit',\n 'missing_parent',\n])\n\nconst ERROR_NAMES: ReadonlySet<unknown> = new Set([\n 'RecipeBookError',\n 'RecipeValidationError',\n])\n\n/**\n * Thrown for programmer errors, such as converting cups to grams or passing an\n * unknown unit id. Each error has a stable `code` and a `docsUrl` that explains the fix.\n *\n * Use {@link isRecipeBookError} rather than `instanceof` to detect it, so the\n * check also works when two copies of the package are installed.\n */\nexport class RecipeBookError extends Error {\n // Declared and assigned in the constructor, so the build needs no class-field helpers.\n declare readonly name: string\n declare readonly code: RecipeBookErrorCode\n declare readonly docsUrl: string\n\n constructor(\n code: RecipeBookErrorCode,\n message: string,\n options?: { cause?: unknown },\n ) {\n const docsUrl = `${DOCS_ORIGIN}/errors/${code}`\n super(`${message}\\nSee ${docsUrl}`, options)\n this.name = 'RecipeBookError'\n this.code = code\n this.docsUrl = docsUrl\n }\n}\n\n/** Codes for `RecipeValidationError`. May grow in minor releases. */\nexport type ValidationErrorCode =\n 'invalid_recipe' | 'invalid_quantity' | 'invalid_ingredient'\n\n/**\n * What `parseRecipe`, `parseQuantity`, and `parseIngredientLine` return. They\n * never throw for bad data: check `success`, or `throw result.error` to fail\n * loudly.\n *\n * @example\n * const result = parseRecipe(json)\n * if (!result.success) throw result.error // message lists the first 10 issues with their paths\n * result.data // Recipe\n */\nexport type ParseResult<T> =\n | { success: true; data: T; warnings: RecipeIssue[] }\n | { success: false; error: RecipeValidationError }\n\n/** True for errors thrown by any copy of Recipe Book. Checks `name` and `code`, not `instanceof`. */\nexport function isRecipeBookError(error: unknown): error is RecipeBookError {\n if (typeof error !== 'object' || error === null) {\n return false\n }\n\n try {\n const { name, code }: { name?: unknown; code?: unknown } = error\n\n return ERROR_NAMES.has(name) && ERROR_CODES.has(code)\n } catch {\n return false\n }\n}\n\n// Messages end up in logs, so they stay bounded however large the input is.\nexport const MAX_ECHOED = 60\n\n/**\n * Describes a value for an error message, short however large the value is:\n * strings are quoted and cut, functions and objects named.\n */\nexport function describeValue(value: unknown): string {\n if (typeof value === 'string') {\n return quote(value)\n }\n\n // A function's source could be any length.\n if (typeof value === 'function') {\n return 'a function'\n }\n\n // A symbol's description can hold any text, newlines included.\n if (value === null || typeof value !== 'object') {\n return quote(String(value)).slice(1, -1)\n }\n\n return Array.isArray(value) ? 'an array' : 'an object'\n}\n\n// Log viewers and editors break lines at U+0085, U+2028 and U+2029, terminals act\n// on other C1 controls, and bidi controls reorder the text around them.\nconst UNESCAPED_BY_JSON =\n /[\\x80-\\x9f\\u061c\\u200e\\u200f\\u2028-\\u202e\\u2066-\\u2069]/g\n\n/**\n * Quotes input text for a message: escaped like a JSON string, so newlines\n * can't fake extra log lines, and cut to 60 characters.\n */\nexport function quote(text: string): string {\n return JSON.stringify(truncate(text)).replace(\n UNESCAPED_BY_JSON,\n (char) => `\\\\u${char.charCodeAt(0).toString(16).padStart(4, '0')}`,\n )\n}\n\nexport function truncate(text: string): string {\n if (text.length <= MAX_ECHOED) {\n return text\n }\n\n let end = MAX_ECHOED - 1\n const last = text.charCodeAt(end - 1)\n if (last >= 0xd800 && last <= 0xdbff) {\n end--\n }\n return `${text.slice(0, end)}…`\n}\n","import type { RecipeIssue, RecipeIssueCode } from './errors'\n\nexport type Path = readonly (string | number)[]\n\nexport function warning(\n issues: RecipeIssue[],\n code: RecipeIssueCode,\n path: Path,\n message: string,\n suggestion?: string,\n): void {\n issues.push(issue('warning', code, path, message, suggestion))\n}\n\nexport function issue(\n severity: RecipeIssue['severity'],\n code: RecipeIssueCode,\n path: Path,\n message: string,\n suggestion?: string,\n): RecipeIssue {\n return {\n code,\n severity,\n path,\n message,\n ...(suggestion !== undefined && { suggestion }),\n }\n}\n\n/** A plain object: not `null`, not an array. */\nexport function isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\n/** `Object.hasOwn`, which the es2020 build target can't assume. */\nexport function hasOwn(record: object, key: string): boolean {\n return Object.prototype.hasOwnProperty.call(record, key)\n}\n","import { hasOwn } from '../issues'\n\n/** A measurement system. `'us'` is US customary. */\nexport type System = 'metric' | 'us'\n\n/** What a unit measures. Count units, such as `clove` or `pinch`, have no fixed size. */\nexport type Dimension = 'mass' | 'volume' | 'count'\n\ntype Label = { one: string; other: string }\n\ntype UnitSpec = {\n dimension: Dimension\n systems: readonly System[]\n toBase?: number\n aliases: readonly string[]\n labels: { short: Label; long: Label }\n}\n\n// Exact definitions (NIST Handbook 44, Appendix C): 1 lb = 453.59237 g, and\n// 1 tsp = 1/768 US gallon, where 1 gallon = 231 in³ = 3785.411784 mL.\nconst TSP_ML = 4.92892159375\nconst OZ_G = 28.349523125\n\n// A function rather than a module-level object, so bundlers can drop the whole\n// registry when nothing imports it: the labels are built with calls.\nfunction definitions() {\n return {\n mg: {\n dimension: 'mass',\n systems: ['metric'],\n toBase: 0.001,\n aliases: ['milligram', 'milligrams', 'milligramme', 'milligrammes'],\n labels: { short: invariable('mg'), long: label('milligram') },\n },\n g: {\n dimension: 'mass',\n systems: ['metric'],\n toBase: 1,\n aliases: ['gram', 'grams', 'gramme', 'grammes'],\n labels: { short: invariable('g'), long: label('gram') },\n },\n kg: {\n dimension: 'mass',\n systems: ['metric'],\n toBase: 1000,\n aliases: [\n 'kgs',\n 'kilo',\n 'kilos',\n 'kilogram',\n 'kilograms',\n 'kilogramme',\n 'kilogrammes',\n ],\n labels: { short: invariable('kg'), long: label('kilogram') },\n },\n oz: {\n dimension: 'mass',\n systems: ['us'],\n toBase: OZ_G,\n aliases: ['ounce', 'ounces'],\n labels: { short: invariable('oz'), long: label('ounce') },\n },\n lb: {\n dimension: 'mass',\n systems: ['us'],\n toBase: 16 * OZ_G,\n aliases: ['lbs', 'pound', 'pounds'],\n labels: { short: invariable('lb'), long: label('pound') },\n },\n ml: {\n dimension: 'volume',\n systems: ['metric'],\n toBase: 1,\n aliases: ['mL', 'milliliter', 'milliliters', 'millilitre', 'millilitres'],\n labels: { short: invariable('mL'), long: label('milliliter') },\n },\n cl: {\n dimension: 'volume',\n systems: ['metric'],\n toBase: 10,\n aliases: ['cL', 'centiliter', 'centiliters', 'centilitre', 'centilitres'],\n labels: { short: invariable('cL'), long: label('centiliter') },\n },\n dl: {\n dimension: 'volume',\n systems: ['metric'],\n toBase: 100,\n aliases: ['dL', 'deciliter', 'deciliters', 'decilitre', 'decilitres'],\n labels: { short: invariable('dL'), long: label('deciliter') },\n },\n l: {\n dimension: 'volume',\n systems: ['metric'],\n toBase: 1000,\n aliases: ['L', 'liter', 'liters', 'litre', 'litres'],\n labels: { short: invariable('L'), long: label('liter') },\n },\n tsp: {\n dimension: 'volume',\n systems: ['metric', 'us'],\n toBase: TSP_ML,\n aliases: ['t', 'tsps', 'teaspoon', 'teaspoons'],\n labels: { short: invariable('tsp'), long: label('teaspoon') },\n },\n tbsp: {\n dimension: 'volume',\n systems: ['metric', 'us'],\n toBase: 3 * TSP_ML,\n aliases: ['T', 'tbs', 'tbsps', 'tablespoon', 'tablespoons'],\n labels: { short: invariable('tbsp'), long: label('tablespoon') },\n },\n 'fl-oz': {\n dimension: 'volume',\n systems: ['us'],\n toBase: 6 * TSP_ML,\n aliases: ['fl oz', 'fluid ounce', 'fluid ounces'],\n labels: { short: invariable('fl oz'), long: label('fluid ounce') },\n },\n cup: {\n dimension: 'volume',\n systems: ['us'],\n toBase: 48 * TSP_ML,\n aliases: ['cups', 'c'],\n labels: { short: label('cup'), long: label('cup') },\n },\n pint: {\n dimension: 'volume',\n systems: ['us'],\n toBase: 96 * TSP_ML,\n aliases: ['pt', 'pts', 'pints'],\n labels: { short: invariable('pt'), long: label('pint') },\n },\n quart: {\n dimension: 'volume',\n systems: ['us'],\n toBase: 192 * TSP_ML,\n aliases: ['qt', 'qts', 'quarts'],\n labels: { short: invariable('qt'), long: label('quart') },\n },\n gallon: {\n dimension: 'volume',\n systems: ['us'],\n toBase: 768 * TSP_ML,\n aliases: ['gal', 'gals', 'gallons'],\n labels: { short: invariable('gal'), long: label('gallon') },\n },\n pinch: count('pinch', ['pinches']),\n dash: count('dash', ['dashes']),\n clove: count('clove', ['cloves']),\n slice: count('slice', ['slices']),\n piece: count('piece', ['pieces', 'pc', 'pcs']),\n can: count('can', ['cans']),\n package: count('package', ['packages', 'pkg', 'pkgs']),\n stick: count('stick', ['sticks']),\n sprig: count('sprig', ['sprigs']),\n bunch: count('bunch', ['bunches']),\n head: count('head', ['heads']),\n } as const satisfies Record<string, UnitSpec>\n}\n\nfunction label(one: string, other = `${one}s`): Label {\n return { one, other }\n}\n\nfunction invariable(one: string): Label {\n return { one, other: one }\n}\n\n/**\n * A count unit, native to both systems. `aliases` starts with the plural, which\n * the labels use. Aliases are one tuple argument so their literal types are\n * inferred from it rather than widened by the `satisfies` context.\n */\nfunction count<const Aliases extends readonly [string, ...string[]]>(\n one: string,\n aliases: Aliases,\n) {\n return {\n dimension: 'count' as const,\n systems: ['metric', 'us'] as const,\n aliases,\n labels: { short: label(one, aliases[0]), long: label(one, aliases[0]) },\n }\n}\n\ntype Definitions = ReturnType<typeof definitions>\n\n/**\n * A unit id, such as `'g'`, `'ml'`, `'cup'`, or `'fl-oz'`. Quantities always\n * store ids; use {@link findUnit} to turn author text into one. May grow in minor releases.\n */\nexport type UnitId = keyof Definitions\n\ntype AliasOf<Id extends UnitId> = Id | Definitions[Id]['aliases'][number]\n\n/**\n * A spelling of a unit in the registry, such as `'cups'`, `'T'`, or `'litre'`.\n * {@link findUnit} also accepts it in any case (except `'T'`, `'t'`, and\n * `'c'`) and with a trailing period.\n */\nexport type UnitAlias = { [Id in UnitId]: AliasOf<Id> }[UnitId]\n\n/** The id of the unit an alias names: `UnitIdOf<'tablespoons'>` is `'tbsp'`. */\nexport type UnitIdOf<Alias extends UnitAlias> = {\n [Id in UnitId]: Alias extends AliasOf<Id> ? Id : never\n}[UnitId]\n\n/** One entry in the {@link units} registry. */\nexport type UnitDefinition = {\n readonly id: UnitId\n readonly dimension: Dimension\n /** Systems where the unit is native. tsp, tbsp, and count units are native to both. */\n readonly systems: readonly System[]\n /** Exact size in grams (mass) or millilitres (volume). Absent for count units. */\n readonly toBase?: number\n /**\n * Every accepted spelling, starting with the id. Matched case-insensitively,\n * except `'T'` (tbsp), `'t'` (tsp), and `'c'` (cup).\n */\n readonly aliases: readonly UnitAlias[]\n /** English labels for one and for many, in short (`'tbsp'`) and long (`'tablespoon'`) form. */\n readonly labels: {\n readonly short: Readonly<Label>\n readonly long: Readonly<Label>\n }\n}\n\ntype Registry = {\n readonly [Id in UnitId]: UnitDefinition & { readonly id: Id }\n}\n\n/**\n * The read-only unit registry, keyed by id. Volume and mass units carry exact\n * factors to millilitres and grams.\n *\n * @example\n * units.cup.toBase // 236.5882365\n * Object.values(units).filter((unit) => unit.dimension === 'mass')\n */\nexport const units: Registry = /* @__PURE__ */ buildRegistry()\n\n/** The registry entry for a unit id, or `undefined` for anything else. */\nexport function lookupUnit(id: unknown): UnitDefinition | undefined {\n return typeof id === 'string' && hasOwn(units, id)\n ? units[id as UnitId]\n : undefined\n}\n\nfunction buildRegistry(): Registry {\n return Object.freeze(\n Object.fromEntries(\n Object.entries<UnitSpec>(definitions()).map(\n ([id, spec]): [string, UnitDefinition] => [\n id,\n Object.freeze({\n id: id as UnitId,\n ...spec,\n systems: Object.freeze(spec.systems),\n aliases: Object.freeze([id, ...spec.aliases] as UnitAlias[]),\n labels: Object.freeze({\n short: Object.freeze(spec.labels.short),\n long: Object.freeze(spec.labels.long),\n }),\n }),\n ],\n ),\n ) as Registry,\n )\n}\n","/**\n * The candidate closest to misspelled text, for \"did you mean\" hints. Case is\n * ignored. Text under 3 characters must match apart from case; text under 6\n * allows one edit, and longer text allows two. Ties go to the candidate nearest\n * in length, then to the earliest.\n */\nexport function closestMatch<Candidate extends string>(\n text: string,\n candidates: Iterable<Candidate>,\n): Candidate | undefined {\n const input = text.trim().toLowerCase()\n const maxDistance = input.length < 3 ? 0 : input.length < 6 ? 1 : 2\n\n let best: Candidate | undefined\n let bestDistance = Infinity\n let bestGap = 0\n\n for (const candidate of candidates) {\n const lengthGap = Math.abs(candidate.length - input.length)\n if (lengthGap > maxDistance) {\n continue\n }\n\n const distance = editDistance(input, candidate.toLowerCase())\n\n if (\n distance <= maxDistance &&\n (distance < bestDistance ||\n (distance === bestDistance && lengthGap < bestGap))\n ) {\n best = candidate\n bestDistance = distance\n bestGap = lengthGap\n }\n }\n\n return best\n}\n\n/**\n * Optimal string alignment distance: insertions, deletions, substitutions, and\n * adjacent swaps. A swap costs half an edit, so for \"tbps\" the swap to \"tbsp\"\n * outranks the substitution to \"tsps\".\n */\nfunction editDistance(a: string, b: string): number {\n let twoAbove: number[] = []\n let above = [0]\n for (let j = 1; j <= b.length; j++) {\n above[j] = j\n }\n\n for (let i = 1; i <= a.length; i++) {\n const row = [i]\n for (let j = 1; j <= b.length; j++) {\n const cost = a[i - 1] === b[j - 1] ? 0 : 1\n let distance = Math.min(\n above[j]! + 1,\n row[j - 1]! + 1,\n above[j - 1]! + cost,\n )\n\n if (a[i - 1] === b[j - 2] && a[i - 2] === b[j - 1]) {\n distance = Math.min(distance, twoAbove[j - 2]! + 0.5)\n }\n\n row[j] = distance\n }\n twoAbove = above\n above = row\n }\n\n return above[b.length]!\n}\n","import { describeValue, quote, RecipeBookError } from '../errors'\nimport { hasOwn } from '../issues'\nimport { closestMatch } from '../suggest'\nimport {\n lookupUnit,\n type UnitAlias,\n type UnitDefinition,\n type UnitId,\n type UnitIdOf,\n units,\n} from './registry'\n\nlet aliasIndex: ReadonlyMap<string, UnitId> | undefined\n\n// 'T' (tablespoon) and 't' (teaspoon) differ only by case, and 'C' is more\n// often Celsius than cup.\nconst CASE_SENSITIVE = /^[Ttc]$/\n\nfunction foldKey(key: string): string {\n const lower = key.toLowerCase()\n return lower === 't' || lower === 'c' ? key : lower\n}\n\n/**\n * Finds the unit that author text names. Surrounding whitespace is ignored,\n * inner whitespace is collapsed, a period that ends a word is dropped, and\n * case is ignored except for `'T'` (tbsp), `'t'` (tsp), and `'c'` (cup).\n *\n * @returns The unit id, or `undefined` when the text names no known unit.\n *\n * @example\n * findUnit('Tablespoons') // 'tbsp'\n * findUnit('T') // 'tbsp'\n * findUnit('fl. oz.') // 'fl-oz'\n * findUnit('knob') // undefined\n */\nexport function findUnit<Alias extends UnitAlias>(text: Alias): UnitIdOf<Alias>\nexport function findUnit<Alias extends UnitAlias>(\n text: `${Alias}.`,\n): UnitIdOf<Alias>\nexport function findUnit(text: string): UnitId | undefined\nexport function findUnit(text: string): UnitId | undefined {\n if (typeof text !== 'string') {\n return undefined\n }\n\n const key = unitKey(text)\n if (!aliasIndex) {\n const index = new Map<string, UnitId>()\n for (const unit of Object.values(units)) {\n for (const alias of unit.aliases) {\n index.set(foldKey(unitKey(alias)), unit.id)\n }\n }\n aliasIndex = index\n }\n\n // Folding alone finds the same unit. Trying the text as written first skips\n // lower-casing it for the usual spellings.\n return aliasIndex.get(key) ?? aliasIndex.get(foldKey(key))\n}\n\nfunction unitKey(text: string): string {\n return text\n .trim()\n .replace(/\\s+/g, ' ')\n .replace(/(\\p{L}) ?\\.(?= |$)/gu, '$1')\n}\n\n/**\n * Returns the registry entry for a unit id.\n *\n * @throws {RecipeBookError} `unknown_unit` when `id` is not a unit id.\n *\n * @example\n * getUnit('cup').toBase // 236.5882365\n */\nexport function getUnit<Id extends UnitId>(\n id: Id,\n): UnitDefinition & { readonly id: Id } {\n if (!lookupUnit(id)) {\n throw unknownUnitError(id)\n }\n\n return units[id]\n}\n\n/** Builds the `unknown_unit` error for a value that should have been a unit id. */\nexport function unknownUnitError(value: unknown): RecipeBookError {\n if (typeof value !== 'string') {\n return new RecipeBookError(\n 'unknown_unit',\n `Expected a unit id such as \"g\", \"ml\", or \"cup\", received ${describeValue(value)}.`,\n )\n }\n\n const name = value.toLowerCase()\n if (hasOwn(SYSTEM_NAMES, name)) {\n return new RecipeBookError(\n 'unknown_unit',\n `${quote(value)} is a measurement system, not a unit. To convert a quantity into a system, use toSystem(quantity, \"${SYSTEM_NAMES[name]}\").`,\n )\n }\n\n const id = findUnit(value)\n if (id) {\n return new RecipeBookError(\n 'unknown_unit',\n `${quote(value)} is not a unit id. Use the id \"${id}\"; findUnit(${quote(value)}) converts author text to ids.`,\n )\n }\n\n const suggestion = suggestUnit(value)\n return new RecipeBookError(\n 'unknown_unit',\n suggestion\n ? // The caller wants an id, so \"cupz\" suggests \"cup\" rather than the alias \"cups\".\n `Unknown unit ${quote(value)}. Did you mean \"${findUnit(suggestion)}\"?`\n : `Unknown unit ${quote(value)}. Use a unit id such as \"g\", \"ml\", or \"cup\".`,\n )\n}\n\nconst SYSTEM_NAMES: Readonly<Record<string, string>> = {\n metric: 'metric',\n us: 'us',\n}\n\n/** The closest known alias to a misspelled unit, for \"did you mean\" hints. */\nexport function suggestUnit(text: string): UnitAlias | undefined {\n // A case-sensitive alias would only be suggested for another case of it,\n // which is the spelling it rejects.\n return closestMatch(\n unitKey(text).replace(/(^|\\P{P})\\p{P}+$/u, '$1'),\n Object.values(units)\n .flatMap((unit) => unit.aliases)\n .filter((alias) => !CASE_SENSITIVE.test(alias)),\n )\n}\n","import {\n type ParseResult,\n quote,\n RecipeBookError,\n type RecipeIssue,\n type RecipeIssueCode,\n truncate,\n type ValidationErrorCode,\n} from './errors'\nimport { hasOwn, isRecord, issue, type Path, warning } from './issues'\nimport { closestMatch } from './suggest'\n\n// Only parsing and fromJsonLd use this module. Nothing React's imports from core\n// load may import it, or every page with React parts loads it once any page\n// parses. scripts/check-parser-split.js checks this.\n\n/** Thrown, or returned by the `parse*` functions, when data fails validation. */\nexport class RecipeValidationError extends RecipeBookError {\n declare readonly code: ValidationErrorCode\n /**\n * Every problem found, errors and warnings, in a stable order: fields in\n * model order (recipe fields, ingredients, steps, notes, equipment, then\n * nutrition), list items in input order, and unknown fields last within\n * their object.\n */\n declare readonly issues: readonly RecipeIssue[]\n\n /**\n * @param subject - What was validated, shown as given at the start of the\n * message, e.g. `'\"Buttermilk pancakes\"'`. Recipe Book's own errors quote\n * the recipe's name or the input text like a JSON string, cut with \"…\"\n * when longer than 60 characters.\n */\n constructor(\n code: ValidationErrorCode,\n issues: readonly RecipeIssue[],\n subject = code === 'invalid_recipe'\n ? 'Recipe'\n : code === 'invalid_quantity'\n ? 'Quantity'\n : 'Ingredient',\n ) {\n super(code, summarize(subject, issues))\n // The base class declares `name` readonly.\n Object.assign(this, { name: 'RecipeValidationError' })\n this.issues = issues\n }\n}\n\n// Messages end up in logs, so they stay bounded however large the input is.\nconst MAX_LISTED = 10\n// Keys in paths come from input, so only ASCII identifiers print bare. Others\n// print quoted, so `[\"a.b\"]` and look-alikes such as `bakeꓸtime` can't pass for nesting.\nconst IDENTIFIER = /^[A-Za-z_$][\\w$]*$/\n\nfunction summarize(subject: string, issues: readonly RecipeIssue[]): string {\n const count = issues.length\n const header = `${subject} has ${count} ${count === 1 ? 'problem' : 'problems'}:`\n const listed = issues.slice(0, MAX_LISTED)\n const paths = listed.map((issue) => formatPath(issue.path))\n const width = Math.max(0, ...paths.map((path) => path.length))\n const lines = listed.map(\n (issue, i) =>\n ` ${issue.severity === 'error' ? '✖' : '⚠'} ${paths[i]!.padEnd(width)} ${issue.message}`,\n )\n\n if (count > listed.length) {\n lines.push(\n ` …and ${count - listed.length} more. error.issues lists them all.`,\n )\n }\n\n return [header, ...lines].join('\\n')\n}\n\nfunction formatPath(path: readonly (string | number)[]): string {\n if (path.length === 0) {\n return '(root)'\n }\n\n return path.reduce<string>(\n (text, segment) =>\n typeof segment === 'number'\n ? `${text}[${segment}]`\n : IDENTIFIER.test(segment)\n ? text\n ? `${text}.${truncate(segment)}`\n : truncate(segment)\n : `${text}[${quote(segment)}]`,\n '',\n )\n}\n\n/** Records an error and returns `undefined`, so readers can `return error(...)`. */\nexport function error(\n issues: RecipeIssue[],\n code: RecipeIssueCode,\n path: Path,\n message: string,\n suggestion?: string,\n): undefined {\n issues.push(issue('error', code, path, message, suggestion))\n return undefined\n}\n\nexport function toResult<T>(\n code: RecipeValidationError['code'],\n data: T | undefined,\n issues: RecipeIssue[],\n subject?: string,\n): ParseResult<T> {\n if (\n data === undefined ||\n issues.some((issue) => issue.severity === 'error')\n ) {\n return {\n success: false,\n error: new RecipeValidationError(code, issues, subject),\n }\n }\n\n return { success: true, data, warnings: issues }\n}\n\n/**\n * A copy of an object's own enumerable fields on a null prototype, so fields\n * inherited from a prototype, including a polluted `Object.prototype`, are never read.\n */\nexport function asRecord(value: unknown): Record<string, unknown> | undefined {\n return isRecord(value)\n ? Object.assign(Object.create(null) as Record<string, unknown>, value)\n : undefined\n}\n\n/** The known keys of `T`. The type makes the compiler check that none is missing or extra. */\nexport type Fields<T> = { readonly [K in keyof T]-?: true }\n\n/**\n * Warns about each key of `record` that isn't in `fields`. Suggestions ignore\n * a trailing `Content`, so schema.org names such as `fatContent` suggest `fat`.\n */\nexport function checkFields(\n issues: RecipeIssue[],\n record: Record<string, unknown>,\n fields: Readonly<Record<string, unknown>>,\n path: Path,\n): void {\n for (const key of Object.keys(record)) {\n if (hasOwn(fields, key)) {\n continue\n }\n\n const suggestion = closestMatch(\n key.replace(/Content$/, ''),\n Object.keys(fields),\n )\n\n warning(\n issues,\n 'unknown_field',\n [...path, key],\n suggestion\n ? `Unknown field. Did you mean \"${suggestion}\"?`\n : 'Unknown field. It is ignored.',\n suggestion,\n )\n }\n}\n","import { describeValue, RecipeBookError } from '../errors'\nimport type { Amount, Range } from './types'\n\n/** The amount type an operation returns for an input amount type. */\nexport type SameAmount<A extends Amount> = A extends number ? number : Range\n\nexport function mapAmount<A extends Amount>(\n amount: A,\n fn: (value: number) => number,\n): SameAmount<A> {\n return (\n typeof amount === 'number'\n ? fn(amount)\n : { min: fn(amount.min), max: fn(amount.max) }\n ) as SameAmount<A>\n}\n\nexport function amountEnds(amount: Amount): readonly number[] {\n return typeof amount === 'number' ? [amount] : [amount.min, amount.max]\n}\n\n/**\n * Validates a quantity passed to a public function.\n *\n * @throws {RecipeBookError} `invalid_argument`, naming `fn` and the fix.\n */\nexport function checkQuantity(fn: string, quantity: unknown): Amount {\n if (\n typeof quantity !== 'object' ||\n quantity === null ||\n !('amount' in quantity)\n ) {\n throw invalidArgument(\n `${fn}: expected a quantity such as { amount: 2, unit: \"cup\" }, received ${describeValue(quantity)}.`,\n )\n }\n\n if ((quantity as { max?: unknown }).max !== undefined) {\n throw invalidArgument(\n `${fn}: a quantity has no max; use amount: { min, max }, or formatServings or formatYield.`,\n )\n }\n\n const { amount } = quantity\n\n if (typeof amount === 'number') {\n if (!isPositive(amount)) {\n throw invalidArgument(\n `${fn}: amount must be a finite number greater than 0, received ${describeValue(amount)}.`,\n )\n }\n return amount\n }\n\n if (\n typeof amount === 'object' &&\n amount !== null &&\n 'min' in amount &&\n 'max' in amount\n ) {\n const { min, max } = amount\n if (!isPositive(min) || !isPositive(max)) {\n throw invalidArgument(\n `${fn}: range ends must be finite numbers greater than 0, received { min: ${describeValue(min)}, max: ${describeValue(max)} }.`,\n )\n }\n if (min >= max) {\n throw invalidArgument(\n `${fn}: range minimum (${min}) must be less than maximum (${max}). Use a plain number when both ends are equal.`,\n )\n }\n return { min, max }\n }\n\n throw invalidArgument(\n `${fn}: amount must be a number or a { min, max } range, received ${describeValue(amount)}.`,\n )\n}\n\n/**\n * Validates a multiplier passed to a public function.\n *\n * @throws {RecipeBookError} `invalid_argument`, naming `fn` and the parameter.\n */\nexport function checkFactor(fn: string, name: string, value: unknown): void {\n if (!isPositive(value)) {\n throw invalidArgument(\n `${fn}: ${name} must be a finite number greater than 0, received ${describeValue(value)}.`,\n )\n }\n}\n\nexport function isPositive(value: unknown): value is number {\n return typeof value === 'number' && Number.isFinite(value) && value > 0\n}\n\nfunction invalidArgument(message: string): RecipeBookError {\n return new RecipeBookError('invalid_argument', message)\n}\n","import {\n describeValue,\n MAX_ECHOED,\n type ParseResult,\n quote,\n type RecipeIssue,\n type RecipeIssueCode,\n} from '../errors'\nimport type { Path } from '../issues'\nimport { findUnit, suggestUnit } from '../units/lookup'\nimport { units } from '../units/registry'\nimport { asRecord, checkFields, error, toResult } from '../validation'\nimport { isPositive } from './amount'\nimport type { Amount, Quantity } from './types'\n\nconst VULGAR_FRACTIONS: Readonly<Record<string, readonly [number, number]>> = {\n '¼': [1, 4],\n '½': [1, 2],\n '¾': [3, 4],\n '⅐': [1, 7],\n '⅑': [1, 9],\n '⅒': [1, 10],\n '⅓': [1, 3],\n '⅔': [2, 3],\n '⅕': [1, 5],\n '⅖': [2, 5],\n '⅗': [3, 5],\n '⅘': [4, 5],\n '⅙': [1, 6],\n '⅚': [5, 6],\n '⅛': [1, 8],\n '⅜': [3, 8],\n '⅝': [5, 8],\n '⅞': [7, 8],\n}\n\nconst ARTICLE = /^an?\\s+(?=\\D)/i\n\nlet patterns: ReturnType<typeof compilePatterns> | undefined\n\nfunction getPatterns() {\n return (patterns ??= compilePatterns())\n}\n\nfunction compilePatterns() {\n const vulgar = `[${Object.keys(VULGAR_FRACTIONS).join('')}]`\n const slash = '[/⁄]'\n // Alternatives are tried in order, so a fraction with an optional whole\n // number, as in \"1 1/2\", \"1/2\", \"1½\" or \"½\", comes before decimals and\n // integers.\n const number = String.raw`(?:\\d+\\s+)?\\d+\\s*${slash}\\s*\\d+|(?:\\d+\\s*)?${vulgar}|\\d+(?:\\.\\d+)?|\\.\\d+`\n\n return {\n amount: new RegExp(\n String.raw`^(${number})(?:\\s*[-–—]\\s*(${number})|\\s+to\\s+(${number}))?`,\n 'i',\n ),\n asciiFraction: new RegExp(\n String.raw`^(?:(\\d+)\\s+)?(\\d+)\\s*${slash}\\s*(\\d+)$`,\n ),\n }\n}\n\nexport type Problem = {\n code: RecipeIssueCode\n message: string\n suggestion?: string\n}\n\n/** An amount read from the start of text, as written, and the text after it. */\ntype AmountMatch = { amount: Amount; amountText: string; rest: string }\n\n/**\n * Parses quantity text, such as `'1 ½ cups'`, `'2-3 tbsp'`, `'a pinch'`, or\n * `'3'` for a bare count. Never throws.\n *\n * Accepts whole numbers, decimals, fractions (`1/2`, `½`, also with the\n * fraction slash `⁄`), mixed numbers (`1 1/2`, `1½`) and ranges (`2-3`, `2–3`,\n * `2 to 3`), each followed by an optional unit alias, and `a` or `an` for 1\n * before a unit alias, as in `'a pinch'`.\n *\n * @example\n * parseQuantity('1 ½ cups') // { success: true, data: { amount: 1.5, unit: 'cup' }, warnings: [] }\n *\n * const result = parseQuantity('2 cupz')\n * if (!result.success) {\n * result.error.message // '\"2 cupz\" has 1 problem:\\n ✖ (root) Unknown unit \"cupz\". Did you mean \"cups\"?\\nSee https://recipe-book.siraj.page/errors/invalid_quantity'\n * }\n */\nexport function parseQuantity(text: string): ParseResult<Quantity> {\n const issues: RecipeIssue[] = []\n\n if (typeof text !== 'string') {\n error(\n issues,\n 'invalid_type',\n [],\n `Expected quantity text such as \"1 ½ cups\", received ${describeValue(text)}.`,\n )\n return toResult<Quantity>('invalid_quantity', undefined, issues)\n }\n\n const quantity = readQuantityText(issues, text, [])\n return toResult('invalid_quantity', quantity, issues, quote(text))\n}\n\n/** Reads a quantity in any input form: text, a number, or `{ amount, unit }`. */\nexport function readQuantity(\n issues: RecipeIssue[],\n value: unknown,\n path: Path,\n): Quantity | undefined {\n if (typeof value === 'string') {\n return readQuantityText(issues, value, path)\n }\n\n if (typeof value === 'number') {\n const amount = readPositive(issues, value, path)\n return amount === undefined ? undefined : { amount }\n }\n\n const record = asRecord(value)\n if (record) {\n return readQuantityObject(issues, record, path)\n }\n\n return error(\n issues,\n 'invalid_type',\n path,\n `Expected a quantity such as \"2 cups\", 2, or { amount: 2, unit: \"cup\" }, received ${describeValue(value)}.`,\n )\n}\n\nfunction readQuantityText(\n issues: RecipeIssue[],\n text: string,\n path: Path,\n): Quantity | undefined {\n const result = parseText(text.replace(/\\s+/g, ' ').trim())\n\n if ('code' in result) {\n return error(issues, result.code, path, result.message, result.suggestion)\n }\n\n return result\n}\n\nfunction parseText(text: string): Quantity | Problem {\n const match = matchAmount(text)\n\n if (!match) {\n const unit = findUnit(text)\n return unit\n ? {\n code: 'invalid_quantity',\n message: `${quote(text)} has no amount. Write a full quantity, e.g. \"1 ${units[unit].labels.short.one}\".`,\n }\n : unreadable(text)\n }\n\n if ('code' in match) {\n return match\n }\n\n const { amount, amountText, rest: unitText } = match\n\n if (unitText === '') {\n return { amount }\n }\n\n if (/\\d/.test(unitText) || !/\\p{L}/u.test(unitText)) {\n return unreadable(text)\n }\n\n const unit = findUnit(unitText)\n if (unit) {\n return { amount, unit }\n }\n\n return unknownUnit(\n unitText,\n amountText.length <= MAX_ECHOED && /^\\d+(?:\\.\\d+)?$/.test(amountText)\n ? amountText\n : quote(amountText),\n )\n}\n\n/**\n * Reads the amount that starts `text`, which is trimmed with single spaces: a\n * number, fraction, mixed number, range, or \"a\" or \"an\" for 1. A comma between\n * digits anywhere in the text, as in \"1,5\", is a problem. Otherwise returns\n * `undefined` when the text doesn't start with an amount, and a problem when\n * the amount is too large to read, isn't greater than 0 (0 is allowed with\n * `allowZero`), or is a range whose low end is above its high end.\n */\nexport function matchAmount(\n text: string,\n allowZero?: boolean,\n): AmountMatch | Problem | undefined {\n // \"1,5\" is a decimal in much of Europe and \"1,500\" a thousands separator in\n // the US, so neither is guessed.\n if (/\\d,\\d/.test(text)) {\n return {\n code: 'invalid_quantity',\n message: `Couldn't read ${quote(text)}. Write decimals with a period, e.g. \"1.5\", and leave out thousands separators.`,\n }\n }\n\n const article = ARTICLE.exec(text)\n if (article) {\n return { amount: 1, amountText: '1', rest: text.slice(article[0].length) }\n }\n\n const match = getPatterns().amount.exec(text)\n if (!match) {\n return undefined\n }\n\n const [matched, lowText = '', highTextDash, highTextTo] = match\n const highText = highTextDash ?? highTextTo\n const low = toNumber(lowText)\n const high = highText === undefined ? low : toNumber(highText)\n\n if (low === Infinity || high === Infinity) {\n return {\n code: 'invalid_amount',\n message: `${quote(text)} has an amount too large to read. Check it for extra digits.`,\n }\n }\n\n if (\n !(isPositive(low) || (allowZero && low === 0)) ||\n !(isPositive(high) || (allowZero && high === 0))\n ) {\n return {\n code: 'invalid_amount',\n message: `Expected a positive amount, received ${quote(text)}.`,\n }\n }\n\n if (low > high) {\n const mixedHint =\n /^\\d+$/.test(lowText) && high < 1\n ? ` To write a mixed number, use ${quote(`${lowText} ${highText}`)}.`\n : ''\n return {\n code: 'invalid_range',\n message: `Range minimum (${truncateNumber(lowText)}) must be less than maximum (${truncateNumber(highText!)}).${mixedHint}`,\n }\n }\n\n return {\n amount: low === high ? low : { min: low, max: high },\n amountText: matched,\n rest: text.slice(matched.length).trim(),\n }\n}\n\n/**\n * The `unknown_unit` problem. `quantity` is the line's quantity without the\n * unit, as it would be written in `RecipeInput`, for the \"move the word into\n * the name\" fix.\n */\nfunction unknownUnit(unitText: string, quantity: string | undefined): Problem {\n const suggestion = suggestUnit(unitText)\n const move =\n quantity === undefined\n ? 'move the word into the name'\n : `move the word into the name: { name: ${quote(unitText)}, quantity: ${quantity} }`\n\n return {\n code: 'unknown_unit',\n message: suggestion\n ? `Unknown unit ${quote(unitText)}. Did you mean \"${suggestion}\"?`\n : `Unknown unit ${quote(unitText)}. Use a known unit, or ${move}.`,\n ...(suggestion && { suggestion }),\n }\n}\n\nfunction truncateNumber(text: string): string {\n return text.length > 20 ? `${text.slice(0, 19)}…` : text\n}\n\nfunction unreadable(text: string): Problem {\n return {\n code: 'invalid_quantity',\n message:\n text === ''\n ? 'Expected a quantity such as \"1 ½ cups\", received an empty string.'\n : `Couldn't read ${quote(text)}. Use a number or fraction, e.g. \"1 ½ cups\".`,\n }\n}\n\nfunction toNumber(text: string): number {\n const ascii = getPatterns().asciiFraction.exec(text)\n if (ascii) {\n const [, whole = '0', numerator, denominator] = ascii\n // A zero denominator reads as NaN, not Infinity, so \"1/0\" isn't too large.\n return Number(whole) + Number(numerator) / (Number(denominator) || NaN)\n }\n\n const vulgar = VULGAR_FRACTIONS[text.slice(-1)]\n if (vulgar) {\n const [numerator, denominator] = vulgar\n // Before a glyph is a whole number and any spaces, or nothing, which\n // Number reads as 0.\n return Number(text.slice(0, -1)) + numerator / denominator\n }\n\n return Number(text)\n}\n\nfunction readQuantityObject(\n issues: RecipeIssue[],\n record: Record<string, unknown>,\n path: Path,\n): Quantity | undefined {\n checkFields(issues, record, { amount: true, unit: true }, path)\n\n const amount = readAmount(issues, record.amount, [...path, 'amount'])\n const { unit } = record\n\n if (unit === undefined) {\n return amount === undefined ? undefined : { amount }\n }\n\n if (typeof unit !== 'string') {\n return error(\n issues,\n 'invalid_type',\n [...path, 'unit'],\n `Expected a unit such as \"g\" or \"cup\", received ${describeValue(unit)}.`,\n )\n }\n\n const id = findUnit(unit)\n\n if (!id) {\n const problem = unknownUnit(\n unit,\n amount === undefined\n ? undefined\n : typeof amount === 'number'\n ? String(amount)\n : `{ amount: { min: ${amount.min}, max: ${amount.max} } }`,\n )\n return error(\n issues,\n problem.code,\n [...path, 'unit'],\n problem.message,\n problem.suggestion,\n )\n }\n\n return amount === undefined ? undefined : { amount, unit: id }\n}\n\nfunction readAmount(\n issues: RecipeIssue[],\n value: unknown,\n path: Path,\n): Amount | undefined {\n if (value === undefined) {\n return error(\n issues,\n 'missing_field',\n path,\n 'Add an amount, e.g. { amount: 2, unit: \"cup\" }.',\n )\n }\n\n if (typeof value === 'number') {\n return readPositive(issues, value, path)\n }\n\n const range = asRecord(value)\n if (range && 'min' in range && 'max' in range) {\n checkFields(issues, range, { min: true, max: true }, path)\n\n const min = readPositive(issues, range.min, [...path, 'min'])\n const max = readPositive(issues, range.max, [...path, 'max'])\n\n if (min === undefined || max === undefined) {\n return undefined\n }\n\n if (min > max) {\n return error(\n issues,\n 'invalid_range',\n path,\n `Range minimum (${min}) must be less than maximum (${max}).`,\n )\n }\n\n return min === max ? min : { min, max }\n }\n\n return error(\n issues,\n 'invalid_type',\n path,\n `Expected a number or { min, max }, received ${describeValue(value)}.`,\n )\n}\n\nexport function readPositive(\n issues: RecipeIssue[],\n value: unknown,\n path: Path,\n): number | undefined {\n if (isPositive(value)) {\n return value\n }\n\n return error(\n issues,\n typeof value === 'number' ? 'invalid_amount' : 'invalid_type',\n path,\n `Expected a positive number, received ${describeValue(value)}.`,\n )\n}\n","// Years and months are left out: their length in minutes isn't fixed.\nconst ISO_DURATION =\n /^P(?!$)(?:(\\d+(?:[.,]\\d+)?)W)?(?:(\\d+(?:[.,]\\d+)?)D)?(?:T(?=\\d)(?:(\\d+(?:[.,]\\d+)?)H)?(?:(\\d+(?:[.,]\\d+)?)M)?(?:(\\d+(?:[.,]\\d+)?)S)?)?$/i\n\nconst SECONDS = [604_800, 86_400, 3600, 60, 1]\n\n/** Minutes in an ISO 8601 duration such as `'PT1H30M'`, or `undefined` if it isn't one. */\nexport function parseIsoDuration(text: string): number | undefined {\n const match = ISO_DURATION.exec(text.trim())\n\n if (!match) {\n return undefined\n }\n\n let seconds = 0\n let fractional = false\n let group = 0\n\n for (const unitSeconds of SECONDS) {\n const part = match[++group]\n if (part === undefined) {\n continue\n }\n\n // Only the smallest component may have a fraction: PT1.5H, not PT1.5H30M.\n if (fractional) {\n return undefined\n }\n\n fractional = /[.,]/.test(part)\n seconds += Number(part.replace(',', '.')) * unitSeconds\n }\n\n return Number.isFinite(seconds) ? seconds / 60 : undefined\n}\n","import { quote, type RecipeIssue } from '../errors'\nimport { issue, type Path } from '../issues'\n\n/**\n * An id to assign. `position` is where the item's issues start in the issue\n * list, so a `duplicate_id` warning can be placed in input order.\n */\nexport type IdRequest = {\n authored: string | undefined\n derived: string\n path: Path\n position: number\n}\n\nexport type PendingIssue = { position: number; issue: RecipeIssue }\n\n/**\n * Lowercase words joined by hyphens, without accents on Latin letters:\n * \"Crème fraîche\" → \"creme-fraiche\", \"わさび\" → \"わさび\".\n */\nexport function slugify(text: string): string {\n return (\n text\n .normalize('NFKD')\n // Marks in other scripts are part of the letter: dropping them turns わさび into わさひ.\n .replace(/(\\p{Script=Latin})\\p{M}+/gu, '$1')\n // Lowercase before NFC: some Greek capitals with marks, such as Ϊ́, have no precomposed form but their lowercase does.\n .toLowerCase()\n .normalize('NFC')\n // A mark with no letter before it, such as the variation selector in ❤️, would be invisible.\n .replace(/(^|[^\\p{L}\\p{M}])\\p{M}+/gu, '$1')\n .replace(/[^\\p{L}\\p{M}\\p{N}]+/gu, '-')\n .replace(/^-+|-+$/g, '')\n )\n}\n\n/**\n * Gives each request a unique id. Authored ids are claimed first, so a derived\n * id never takes one; a repeated authored id is renamed with a warning. Taken\n * ids get the next free suffix: `egg`, `egg-2`, `egg-3`.\n */\nexport function assignIds(\n requests: readonly IdRequest[],\n pending: PendingIssue[],\n): string[] {\n const used = new Set<string>()\n const nextSuffix = new Map<string, number>()\n const ids = requests.map(({ authored }) => {\n if (authored === undefined || used.has(authored)) {\n return undefined\n }\n used.add(authored)\n return authored\n })\n\n return requests.map((request, i) => {\n const claimed = ids[i]\n if (claimed !== undefined) {\n return claimed\n }\n\n const base = request.authored ?? request.derived\n let id = base\n if (used.has(id)) {\n // Resuming from the last suffix keeps many repeats of one id linear.\n let n = nextSuffix.get(base) ?? 2\n while (used.has((id = `${base}-${n}`))) {\n n++\n }\n nextSuffix.set(base, n + 1)\n }\n used.add(id)\n\n if (request.authored !== undefined) {\n pending.push({\n position: request.position,\n issue: issue(\n 'warning',\n 'duplicate_id',\n [...request.path, 'id'],\n `${quote(request.authored)} is already used; renamed to ${quote(id)}.`,\n ),\n })\n }\n\n return id\n })\n}\n\n/** Inserts pending issues at their positions, keeping input order. */\nexport function insertPending(\n issues: RecipeIssue[],\n pending: readonly PendingIssue[],\n): void {\n if (pending.length === 0) {\n return\n }\n\n const sorted = [...pending].sort((a, b) => a.position - b.position)\n const original = issues.splice(0)\n let next = 0\n for (const { position, issue } of sorted) {\n while (next < position) {\n issues.push(original[next++]!)\n }\n issues.push(issue)\n }\n while (next < original.length) {\n issues.push(original[next++]!)\n }\n}\n","import { units, type System } from '../units/registry'\nimport type { IngredientSection } from './types'\n\n/**\n * The system a recipe was written in. Counts the ingredients whose primary\n * quantity has a unit native to exactly one system; the system with more\n * ingredients wins, and on a tie the first such ingredient decides.\n * Equivalents don't count.\n *\n * @returns `undefined` for a system-neutral recipe: only counts, tsp, and tbsp.\n */\nexport function inferSystem(\n sections: readonly IngredientSection[],\n): System | undefined {\n const counts: Record<System, number> = { metric: 0, us: 0 }\n let first: System | undefined\n\n for (const { items } of sections) {\n for (const { quantity } of items) {\n const systems: readonly System[] = quantity?.unit\n ? units[quantity.unit].systems\n : []\n\n if (systems.length === 1) {\n const system = systems[0]!\n counts[system]++\n first ??= system\n }\n }\n }\n\n if (counts.metric !== counts.us) {\n return counts.metric > counts.us ? 'metric' : 'us'\n }\n\n return first\n}\n","import type { NutritionInput } from './input'\nimport type { NutrientUnit } from './nutrition'\n\nexport type NutrientKey = Exclude<keyof NutritionInput, 'servingSize'>\n\n// Kept out of parse.ts: toJsonLd reads it and React's JsonLd part imports\n// toJsonLd, so any page with React parts can load this module, and bundlers\n// that include whole modules would load the parser with it.\nexport const NUTRIENT_UNITS: Readonly<Record<NutrientKey, NutrientUnit>> = {\n calories: 'kcal',\n fat: 'g',\n saturatedFat: 'g',\n transFat: 'g',\n unsaturatedFat: 'g',\n carbohydrates: 'g',\n sugar: 'g',\n fiber: 'g',\n protein: 'g',\n sodium: 'mg',\n cholesterol: 'mg',\n}\n","import { matchAmount, type Problem } from '../quantity/parse'\nimport { findUnit } from '../units/lookup'\nimport { lookupUnit } from '../units/registry'\n\nexport type NutrientUnit = 'kcal' | 'g' | 'mg'\n\n/**\n * The amount in `unit` that nutrient text such as `'250 kcal'` or `'1.2 g'`\n * names, a problem if its number has a comma in it, or `undefined` if it isn't\n * readable as one. A number without a unit is already in `unit`. kJ convert to\n * kcal at 4.184 kJ per kcal, and masses convert through the unit registry.\n */\nexport function parseNutrient(\n text: string,\n unit: NutrientUnit,\n): number | Problem | undefined {\n const match = matchAmount(text.replace(/\\s+/g, ' '), true)\n\n if (match && 'code' in match) {\n // Keep only the comma problem. The others are worded for positive amounts\n // and ranges, which don't fit a nutrient.\n return match.code === 'invalid_quantity' ? match : undefined\n }\n\n const amount =\n match && typeof match.amount === 'number'\n ? convert(match.amount, match.rest, unit)\n : undefined\n\n return Number.isFinite(amount) ? amount : undefined\n}\n\nfunction convert(\n amount: number,\n unitText: string,\n unit: NutrientUnit,\n): number | undefined {\n if (unitText === '') {\n return amount\n }\n\n if (unit === 'kcal') {\n return /^(?:k?cals?|(?:kilo)?calories?)\\.?$/i.test(unitText)\n ? amount\n : /^(?:kj|kilojoules?)\\.?$/i.test(unitText)\n ? amount / 4.184\n : undefined\n }\n\n const mass = lookupUnit(findUnit(unitText))\n\n return mass?.dimension === 'mass' && mass.toBase !== undefined\n ? amount * (unit === 'mg' ? mass.toBase * 1000 : mass.toBase)\n : undefined\n}\n","/**\n * The scheme of a URL that a link or image must not use, such as\n * `'javascript:'`, or `undefined` for http, https, and relative URLs. The\n * scheme is read the way a browser's URL parser reads it, which skips leading\n * C0 controls and spaces and removes tabs and newlines, so\n * `' java\\tscript:alert(1)'` is `javascript:`. It reads no further than the\n * first character that can't be part of the scheme, so the rest of a long URL\n * costs nothing.\n */\nexport function disallowedScheme(url: string): string | undefined {\n const scheme = /^[\\0- ]*[a-z][\\d+.a-z\\t\\n\\r-]*:/i\n .exec(url)?.[0]\n .replace(/[\\0- ]+/g, '')\n .toLowerCase()\n\n return scheme === 'http:' || scheme === 'https:' ? undefined : scheme\n}\n","import {\n describeValue,\n type ParseResult,\n quote,\n RecipeBookError,\n type RecipeIssue,\n} from '../errors'\nimport type { IngredientLine } from '../ingredient/parse'\nimport { hasOwn, isRecord, type Path, warning } from '../issues'\nimport { isPositive } from '../quantity/amount'\nimport { matchAmount, readPositive, readQuantity } from '../quantity/parse'\nimport type { Quantity } from '../quantity/types'\nimport type { System } from '../units/registry'\nimport {\n asRecord,\n checkFields,\n error,\n type Fields,\n toResult,\n} from '../validation'\nimport { parseIsoDuration } from './duration'\nimport {\n assignIds,\n type IdRequest,\n insertPending,\n type PendingIssue,\n slugify,\n} from './ids'\nimport { inferSystem } from './infer'\nimport type {\n CustomTimeInput,\n EquipmentInput,\n IngredientInput,\n IngredientSectionInput,\n NoteInput,\n RecipeInput,\n ServingsInput,\n StepInput,\n StepSectionInput,\n TimesInput,\n YieldInput,\n} from './input'\nimport { NUTRIENT_UNITS, type NutrientKey } from './nutrient-units'\nimport { type NutrientUnit, parseNutrient } from './nutrition'\nimport type {\n CustomTime,\n Equipment,\n Ingredient,\n Note,\n Nutrition,\n Recipe,\n Servings,\n Step,\n Times,\n Yield,\n} from './types'\nimport { disallowedScheme } from './url'\n\nconst RECIPE_FIELDS: Fields<RecipeInput> = {\n id: true,\n name: true,\n description: true,\n image: true,\n servings: true,\n yield: true,\n system: true,\n times: true,\n ingredients: true,\n steps: true,\n notes: true,\n equipment: true,\n nutrition: true,\n}\nconst INGREDIENT_FIELDS: Fields<IngredientInput> = {\n id: true,\n name: true,\n plural: true,\n quantity: true,\n equivalents: true,\n note: true,\n url: true,\n optional: true,\n}\nconst SECTION_FIELDS: Fields<IngredientSectionInput & StepSectionInput> = {\n id: true,\n title: true,\n items: true,\n}\nconst STEP_FIELDS: Fields<StepInput> = {\n id: true,\n text: true,\n name: true,\n image: true,\n}\nconst SERVINGS_FIELDS: Fields<Exclude<ServingsInput, number | string>> = {\n amount: true,\n max: true,\n}\nconst YIELD_FIELDS: Fields<Exclude<YieldInput, string>> = {\n amount: true,\n max: true,\n unit: true,\n plural: true,\n}\nconst TIMES_FIELDS: Fields<TimesInput> = {\n prep: true,\n cook: true,\n total: true,\n custom: true,\n}\nconst CUSTOM_TIME_FIELDS: Fields<CustomTimeInput> = {\n id: true,\n label: true,\n minutes: true,\n}\nconst NOTE_FIELDS: Fields<NoteInput> = {\n id: true,\n title: true,\n text: true,\n}\nconst EQUIPMENT_FIELDS: Fields<EquipmentInput> = {\n id: true,\n name: true,\n plural: true,\n quantity: true,\n url: true,\n note: true,\n}\nconst NUTRIENT_EXAMPLES: Readonly<Record<NutrientUnit, string>> = {\n kcal: 'kcal, e.g. 250, \"250 kcal\", or \"1046 kJ\"',\n g: 'grams, e.g. 12 or \"12 g\"',\n mg: 'milligrams, e.g. 300, \"300 mg\", or \"0.3 g\"',\n}\n\n/**\n * Validates and normalizes recipe data: resolves unit aliases, parses quantity\n * text and ISO 8601 durations, groups items into sections, derives ids, and\n * infers the source system. Accepts `unknown`, so JSON needs no cast, and reads\n * only an object's own fields. Never throws for bad data; an error thrown by a\n * getter or proxy in the input passes through.\n *\n * Unknown fields, duplicate ids, missing or empty `ingredients` or `steps`, and\n * empty sections are warnings and don't fail the parse. Each issue has the path\n * of the value it is about.\n *\n * @example\n * import { parseRecipe } from '@recipe-book/core'\n *\n * const result = parseRecipe({\n * name: 'Pancakes',\n * ingredients: [{ name: 'flour', quantity: '1 ½ cups' }],\n * steps: ['Whisk the batter.'],\n * })\n * result.success && result.data.ingredients[0]?.items[0]?.quantity // { amount: 1.5, unit: 'cup' }\n *\n * @example\n * import { parseRecipe } from '@recipe-book/core'\n *\n * const result = parseRecipe({\n * name: 'Pancakes',\n * ingredients: [{ name: 'flour', quantity: '1 ½ cupz' }],\n * steps: ['Whisk the batter.'],\n * })\n * if (!result.success) {\n * console.error(result.error.message)\n * // \"Pancakes\" has 1 problem:\n * // ✖ ingredients[0].quantity Unknown unit \"cupz\". Did you mean \"cups\"?\n * // See https://recipe-book.siraj.page/errors/invalid_recipe\n * }\n */\nexport function parseRecipe(input: unknown): ParseResult<Recipe>\n/**\n * Parses recipe data as `parseRecipe(input)` does, and reads ingredients\n * written as text with `options.parseIngredientLine`. Without it, a text\n * ingredient is an `invalid_type` error.\n *\n * @throws {RecipeBookError} `invalid_argument` when\n * `options.parseIngredientLine` is present but isn't a function.\n *\n * @example\n * import { parseIngredientLine, parseRecipe } from '@recipe-book/core'\n *\n * const result = parseRecipe(\n * { name: 'Toast', ingredients: ['2 slices bread', '1 tbsp butter, softened'] },\n * { parseIngredientLine },\n * )\n * result.success && result.data.ingredients[0]?.items[1] // { id: 'butter', name: 'butter', quantity: { amount: 1, unit: 'tbsp' }, equivalents: [], note: 'softened', optional: false }\n */\nexport function parseRecipe(\n input: unknown,\n options: ParseRecipeOptions | undefined,\n): ParseResult<Recipe>\nexport function parseRecipe(\n input: unknown,\n options?: unknown,\n): ParseResult<Recipe> {\n const issues: RecipeIssue[] = []\n const readLine = readLineOption('parseRecipe', options)\n const recipe = readRecipe(issues, input, readLine)\n const label = recipe && quote(recipe.name)\n\n return toResult('invalid_recipe', recipe, issues, label)\n}\n\n/** Options for `parseRecipe`. */\nexport type ParseRecipeOptions = {\n /**\n * Reads ingredients written as text, such as `'2 cups flour'`. Pass\n * `parseIngredientLine`. Without it, a text ingredient is an `invalid_type` error.\n * A function of your own must return what `parseIngredientLine` returns.\n */\n parseIngredientLine?:\n ((text: string) => ParseResult<IngredientLine>) | undefined\n}\n\ntype LineReader = NonNullable<ParseRecipeOptions['parseIngredientLine']>\n\n/**\n * Reads `options.parseIngredientLine`, ignoring `options` that aren't an\n * object, as when `parseRecipe` is passed to `Array.prototype.map`.\n *\n * @throws {RecipeBookError} `invalid_argument`, naming `fn`, when\n * `parseIngredientLine` is present but isn't a function.\n */\nexport function readLineOption(\n fn: string,\n options: unknown,\n): LineReader | undefined {\n const reader = asRecord(options)?.parseIngredientLine\n\n if (reader !== undefined && typeof reader !== 'function') {\n throw new RecipeBookError(\n 'invalid_argument',\n `${fn}: parseIngredientLine must be a function such as parseIngredientLine, received ${describeValue(reader)}.`,\n )\n }\n\n return reader as LineReader | undefined\n}\n\nfunction readRecipe(\n issues: RecipeIssue[],\n value: unknown,\n readLine: LineReader | undefined,\n): Recipe | undefined {\n const input = asRecord(value)\n\n if (!input) {\n return error(\n issues,\n 'invalid_type',\n [],\n `Expected a recipe object such as { name, ingredients, steps }, received ${describeValue(value)}.`,\n )\n }\n\n const pending: PendingIssue[] = []\n const id = readText(issues, input.id, ['id'])\n const name = readText(\n issues,\n input.name,\n ['name'],\n 'Add a name for the recipe.',\n )\n const description = readText(issues, input.description, ['description'])\n const image = readUrl(issues, input.image, ['image'])\n const servings = readServings(issues, input.servings, ['servings'])\n const recipeYield = readYield(issues, input.yield, ['yield'])\n const authoredSystem = readSystem(issues, input.system, ['system'])\n const times = readTimes(issues, pending, input.times, ['times'])\n const ingredients = readList(\n issues,\n pending,\n input.ingredients,\n ['ingredients'],\n 'ingredients',\n (issues, value, path) => readIngredient(issues, value, path, readLine),\n )\n const steps = readList(\n issues,\n pending,\n input.steps,\n ['steps'],\n 'steps',\n readStep,\n )\n const notes = readItems(\n issues,\n pending,\n input.notes,\n ['notes'],\n 'notes',\n readNote,\n )\n const equipment = readItems(\n issues,\n pending,\n input.equipment,\n ['equipment'],\n 'equipment',\n readEquipment,\n )\n const nutrition = readNutrition(issues, input.nutrition, ['nutrition'])\n checkFields(issues, input, RECIPE_FIELDS, [])\n insertPending(issues, pending)\n\n if (name === undefined) {\n return undefined\n }\n\n const system = authoredSystem ?? inferSystem(ingredients)\n\n return defined({\n id: id ?? (slugify(name) || 'recipe'),\n name,\n description,\n image,\n servings,\n yield: recipeYield,\n system,\n times,\n ingredients,\n steps,\n notes,\n equipment,\n nutrition,\n })\n}\n\n/** A parsed item whose id is assigned once every id in its list is known. */\ntype Draft<T> = IdRequest & { build: (id: string) => T }\n\n/** Reads one list item. `n` is its 1-based position in the list, across sections. */\ntype ItemReader<T> = (\n issues: RecipeIssue[],\n value: unknown,\n path: Path,\n n: number,\n) => Draft<T> | undefined\n\ntype SectionDraft<T> = IdRequest & {\n title: string | undefined\n items: Draft<T>[]\n}\n\n/**\n * Reads a list of sections and loose items. Each run of loose items becomes an\n * untitled section, so the result always has one shape. `noun` names the list\n * in messages and is the id of untitled sections.\n */\nfunction readList<T>(\n issues: RecipeIssue[],\n pending: PendingIssue[],\n value: unknown,\n path: Path,\n noun: 'ingredients' | 'steps',\n readItem: ItemReader<T>,\n): { id: string; title?: string; items: T[] }[] {\n const entries =\n value === undefined ? [] : readArray(issues, value, path, noun)\n\n if (!entries) {\n return []\n }\n\n const sections: SectionDraft<T>[] = []\n let loose: SectionDraft<T> | undefined\n let count = 0\n const read = (entry: unknown, entryPath: Path) =>\n readItem(issues, entry, entryPath, ++count)\n\n entries.forEach((entry: unknown, i) => {\n const entryPath = [...path, i]\n\n const section = asSection(entry)\n\n if (section) {\n loose = undefined\n sections.push(readSection(issues, section, entryPath, noun, read))\n return\n }\n\n if (!loose) {\n loose = {\n authored: undefined,\n derived: noun,\n path: entryPath,\n position: issues.length,\n title: undefined,\n items: [],\n }\n sections.push(loose)\n }\n\n const item = read(entry, entryPath)\n if (item) {\n loose.items.push(item)\n }\n })\n\n // forEach skips holes, so a sparse array counts only the entries it has.\n if (sections.length === 0) {\n warning(issues, 'empty_list', path, `Recipe has no ${noun}.`)\n return []\n }\n\n const sectionIds = assignIds(sections, pending)\n const itemIds = assignIds(\n sections.flatMap((section) => section.items),\n pending,\n )\n\n let next = 0\n return sections.map((section, i) =>\n defined({\n id: sectionIds[i]!,\n title: section.title,\n items: section.items.map((item) => item.build(itemIds[next++]!)),\n }),\n )\n}\n\nfunction asSection(entry: unknown): Record<string, unknown> | undefined {\n const record = asRecord(entry)\n return record && 'items' in record ? record : undefined\n}\n\nfunction readSection<T>(\n issues: RecipeIssue[],\n record: Record<string, unknown>,\n path: Path,\n noun: 'ingredients' | 'steps',\n read: (value: unknown, path: Path) => Draft<T> | undefined,\n): SectionDraft<T> {\n const position = issues.length\n const authored = readText(issues, record.id, [...path, 'id'])\n const title = readText(issues, record.title, [...path, 'title'])\n const items: Draft<T>[] = []\n const itemsPath = [...path, 'items']\n const entries = readArray(issues, record.items, itemsPath, noun)\n\n if (entries) {\n let visited = 0\n entries.forEach((entry: unknown, j) => {\n visited++\n const itemPath = [...itemsPath, j]\n\n if (asSection(entry)) {\n error(\n issues,\n 'invalid_type',\n itemPath,\n `Sections can't be nested. Make this a top-level section in ${noun}.`,\n )\n return\n }\n\n const item = read(entry, itemPath)\n if (item) {\n items.push(item)\n }\n })\n\n if (visited === 0) {\n warning(issues, 'empty_list', itemsPath, `Section has no ${noun}.`)\n }\n }\n\n checkFields(issues, record, SECTION_FIELDS, path)\n\n return {\n authored,\n derived: (title && slugify(title)) || noun,\n path,\n position,\n title,\n items,\n }\n}\n\n/** Reads a flat list, such as notes or equipment. Its ids have their own namespace. */\nfunction readItems<T>(\n issues: RecipeIssue[],\n pending: PendingIssue[],\n value: unknown,\n path: Path,\n noun: string,\n readItem: ItemReader<T>,\n): T[] {\n const entries =\n value === undefined ? [] : readArray(issues, value, path, noun)\n\n if (!entries) {\n return []\n }\n\n let n = 0\n const drafts = entries.flatMap((entry: unknown, i) => {\n const draft = readItem(issues, entry, [...path, i], ++n)\n return draft ? [draft] : []\n })\n const ids = assignIds(drafts, pending)\n\n return drafts.map((draft, i) => draft.build(ids[i]!))\n}\n\nfunction readArray(\n issues: RecipeIssue[],\n value: unknown,\n path: Path,\n noun: string,\n): unknown[] | undefined {\n return Array.isArray(value)\n ? value\n : error(\n issues,\n 'invalid_type',\n path,\n `Expected a list of ${noun}, received ${describeValue(value)}.`,\n )\n}\n\nfunction readIngredient(\n issues: RecipeIssue[],\n value: unknown,\n path: Path,\n readLine?: LineReader,\n): Draft<Ingredient> | undefined {\n if (typeof value === 'string' && readLine) {\n const result = readLine(value)\n\n for (const issue of result.success\n ? result.warnings\n : result.error.issues) {\n issues.push({ ...issue, path: [...path, ...issue.path] })\n }\n\n return result.success\n ? readIngredient(issues, result.data, path)\n : undefined\n }\n\n const record = asRecord(value)\n\n if (!record) {\n return error(\n issues,\n 'invalid_type',\n path,\n `Expected an ingredient such as ${readLine ? '\"2 cups flour\" or ' : ''}{ name: \"flour\", quantity: \"2 cups\" }, received ${describeValue(value)}.${typeof value === 'string' ? ' To read ingredient lines, pass parseIngredientLine: parseRecipe(input, { parseIngredientLine }).' : ''}`,\n )\n }\n\n const position = issues.length\n const authored = readText(issues, record.id, [...path, 'id'])\n const name = readText(\n issues,\n record.name,\n [...path, 'name'],\n 'Add a name, e.g. name: \"flour\".',\n )\n const plural = readText(issues, record.plural, [...path, 'plural'])\n const quantity =\n record.quantity === undefined\n ? undefined\n : readQuantity(issues, record.quantity, [...path, 'quantity'])\n const equivalents = readEquivalents(issues, record.equivalents, [\n ...path,\n 'equivalents',\n ])\n const note = readText(issues, record.note, [...path, 'note'])\n const url = readUrl(issues, record.url, [...path, 'url'])\n const optional = readBoolean(issues, record.optional, [...path, 'optional'])\n\n if (equivalents.length > 0 && record.quantity === undefined) {\n error(\n issues,\n 'missing_field',\n [...path, 'quantity'],\n 'Add a quantity. Equivalents are alternatives to it, so they need one.',\n )\n }\n\n checkFields(issues, record, INGREDIENT_FIELDS, path)\n\n if (name === undefined) {\n return undefined\n }\n\n return {\n authored,\n derived: slugify(name) || 'ingredient',\n path,\n position,\n build: (id) =>\n defined({ id, name, plural, quantity, equivalents, note, url, optional }),\n }\n}\n\nfunction readEquivalents(\n issues: RecipeIssue[],\n value: unknown,\n path: Path,\n): Quantity[] {\n if (value === undefined) {\n return []\n }\n\n if (!Array.isArray(value)) {\n error(\n issues,\n 'invalid_type',\n path,\n `Expected a list of quantities, e.g. [\"190 g\"], received ${describeValue(value)}.`,\n )\n return []\n }\n\n return value.flatMap((entry: unknown, i) => {\n const quantity = readQuantity(issues, entry, [...path, i])\n return quantity === undefined ? [] : [quantity]\n })\n}\n\nfunction readStep(\n issues: RecipeIssue[],\n value: unknown,\n path: Path,\n n: number,\n): Draft<Step> | undefined {\n const isText = typeof value === 'string'\n const record = asRecord(isText ? { text: value } : value)\n\n if (!record) {\n return error(\n issues,\n 'invalid_type',\n path,\n `Expected a string or { text }, received ${describeValue(value)}.`,\n )\n }\n\n const position = issues.length\n const authored = readText(issues, record.id, [...path, 'id'])\n const text = readText(\n issues,\n record.text,\n isText ? path : [...path, 'text'],\n 'Add the step text.',\n )\n const name = readText(issues, record.name, [...path, 'name'])\n const image = readUrl(issues, record.image, [...path, 'image'])\n checkFields(issues, record, STEP_FIELDS, path)\n\n if (text === undefined) {\n return undefined\n }\n\n return {\n authored,\n derived: (name && slugify(name)) || `step-${n}`,\n path,\n position,\n build: (id) => defined({ id, text, name, image }),\n }\n}\n\nfunction readNote(\n issues: RecipeIssue[],\n value: unknown,\n path: Path,\n n: number,\n): Draft<Note> | undefined {\n const isText = typeof value === 'string'\n const record = asRecord(isText ? { text: value } : value)\n\n if (!record) {\n return error(\n issues,\n 'invalid_type',\n path,\n `Expected a string or { text }, received ${describeValue(value)}.`,\n )\n }\n\n const position = issues.length\n const authored = readText(issues, record.id, [...path, 'id'])\n const title = readText(issues, record.title, [...path, 'title'])\n const text = readText(\n issues,\n record.text,\n isText ? path : [...path, 'text'],\n 'Add the note text.',\n )\n checkFields(issues, record, NOTE_FIELDS, path)\n\n if (text === undefined) {\n return undefined\n }\n\n return {\n authored,\n derived: (title && slugify(title)) || `note-${n}`,\n path,\n position,\n build: (id) => defined({ id, title, text }),\n }\n}\n\nfunction readEquipment(\n issues: RecipeIssue[],\n value: unknown,\n path: Path,\n): Draft<Equipment> | undefined {\n const isText = typeof value === 'string'\n const record = asRecord(isText ? { name: value } : value)\n\n if (!record) {\n return error(\n issues,\n 'invalid_type',\n path,\n `Expected a string or { name }, received ${describeValue(value)}.`,\n )\n }\n\n const position = issues.length\n const authored = readText(issues, record.id, [...path, 'id'])\n const name = readText(\n issues,\n record.name,\n isText ? path : [...path, 'name'],\n `Add a name, e.g. ${isText ? '' : 'name: '}\"whisk\".`,\n )\n const plural = readText(issues, record.plural, [...path, 'plural'])\n const quantity =\n record.quantity === undefined\n ? undefined\n : readCount(issues, record.quantity, [...path, 'quantity'])\n const url = readUrl(issues, record.url, [...path, 'url'])\n const note = readText(issues, record.note, [...path, 'note'])\n checkFields(issues, record, EQUIPMENT_FIELDS, path)\n\n if (name === undefined) {\n return undefined\n }\n\n return {\n authored,\n derived: slugify(name) || 'equipment',\n path,\n position,\n build: (id) => defined({ id, name, plural, quantity, url, note }),\n }\n}\n\n/** `T` with each field that may be `undefined` made optional instead. */\ntype Defined<T> = {\n [K in keyof T as undefined extends T[K] ? never : K]: T[K]\n} & {\n [K in keyof T as undefined extends T[K] ? K : never]?: Exclude<\n T[K],\n undefined\n >\n}\n\n/** Copies the own fields of `fields` that aren't `undefined`, keeping their order. A polluted `Object.prototype` adds none. */\nfunction defined<T extends object>(fields: T): Defined<T> {\n const copy: Record<string, unknown> = {}\n\n for (const key in fields) {\n if (hasOwn(fields, key) && fields[key] !== undefined) {\n copy[key] = fields[key]\n }\n }\n\n return copy as Defined<T>\n}\n\nfunction readCount(\n issues: RecipeIssue[],\n value: unknown,\n path: Path,\n): number | undefined {\n if (typeof value === 'number' && Number.isInteger(value) && value > 0) {\n return value\n }\n\n return error(\n issues,\n typeof value === 'number' ? 'invalid_amount' : 'invalid_type',\n path,\n `Expected a whole number greater than 0, received ${describeValue(value)}.`,\n )\n}\n\nfunction readServings(\n issues: RecipeIssue[],\n value: unknown,\n path: Path,\n): Servings | undefined {\n if (value === undefined) {\n return undefined\n }\n\n if (typeof value === 'number') {\n const amount = readPositive(issues, value, path)\n return amount === undefined ? undefined : { amount }\n }\n\n const expected = `Expected a number of servings, e.g. 4 or \"4–6\", received ${describeValue(value)}.`\n\n if (typeof value === 'string') {\n const match = readRangeText(issues, value, path, expected)\n\n if (match?.rest) {\n return error(issues, 'invalid_quantity', path, expected)\n }\n\n return match?.range\n }\n\n const record = asRecord(value)\n\n if (!record) {\n return error(issues, 'invalid_type', path, expected)\n }\n\n const range = readRange(\n issues,\n record,\n path,\n 'Add an amount, e.g. { amount: 4, max: 6 }.',\n )\n checkFields(issues, record, SERVINGS_FIELDS, path)\n return range\n}\n\nfunction readYield(\n issues: RecipeIssue[],\n value: unknown,\n path: Path,\n): Yield | undefined {\n if (value === undefined) {\n return undefined\n }\n\n const isText = typeof value === 'string'\n const expected = `Expected a batch such as \"24 cookies\" or ${isText ? '\"3–4 loaves\"' : '{ amount, unit }'}, received ${describeValue(value)}.`\n\n if (isText) {\n const match = readRangeText(issues, value, path, expected)\n\n if (!match) {\n return undefined\n }\n\n const { range, rest } = match\n\n if (!rest) {\n return error(\n issues,\n 'missing_field',\n path,\n `Add what the recipe makes, e.g. \"24 cookies\".${servingsHint(range)}`,\n )\n }\n\n // A second number, a word or sign that joins numbers, or a dash would\n // otherwise become part of the unit and not scale: \"3 or 4 loaves\",\n // \"2 and 1/2 dozen\", \"4 & 5 loaves\", \"1 000 cookies\", \"6 ⅓-cup bowls\".\n if (\n !/\\p{L}/u.test(rest) ||\n /^(?:[-–—&]|(?:[\\d.,/\\p{No}]+|or|to|x|and)(?:\\s|$))/iu.test(rest)\n ) {\n const suggestion = suggestJoinedYield(value, range, rest)\n return error(\n issues,\n 'invalid_quantity',\n path,\n suggestion ? `${expected} Did you mean \"${suggestion}\"?` : expected,\n suggestion,\n )\n }\n\n return { ...range, unit: rest }\n }\n\n const record = asRecord(value)\n\n if (!record) {\n return error(\n issues,\n 'invalid_type',\n path,\n `${expected}${isPositive(value) ? servingsHint({ amount: value }) : ''}`,\n )\n }\n\n const range = readRange(\n issues,\n record,\n path,\n 'Add an amount, e.g. { amount: 24, unit: \"cookie\" }.',\n )\n const unit = readText(\n issues,\n record.unit,\n [...path, 'unit'],\n `Add a unit, e.g. { amount: 24, unit: \"cookie\" }.${servingsHint(range)}`,\n )\n const plural = readText(issues, record.plural, [...path, 'plural'])\n checkFields(issues, record, YIELD_FIELDS, path)\n\n if (range === undefined || unit === undefined) {\n return undefined\n }\n\n return defined({ ...range, unit, plural })\n}\n\n/**\n * Rewrites yield text whose amount is followed by \"and\" or \"&\" and a second\n * number: a fraction makes a mixed number (\"2 and 1/2 dozen\" to \"2 1/2 dozen\"),\n * and a whole number makes a range (\"4 & 5 loaves\" to \"4-5 loaves\"). Returns\n * `undefined` unless the rewritten text parses as that amount.\n */\nfunction suggestJoinedYield(\n text: string,\n { amount }: Servings,\n rest: string,\n): string | undefined {\n const joiner = /^(?:and|&)\\s*/i.exec(rest)\n const next = joiner && matchAmount(rest.slice(joiner[0].length))\n\n if (!next || 'code' in next || typeof next.amount !== 'number') {\n return undefined\n }\n\n const isFraction = next.amount < 1\n\n if (!isFraction && !Number.isInteger(next.amount)) {\n return undefined\n }\n\n const head = text.replace(/\\s+/g, ' ').trim().slice(0, -rest.length)\n const suggestion = `${head.trim()}${isFraction ? ' ' : '-'}${next.amountText} ${next.rest}`\n const parsed = readYield([], suggestion, [])\n\n return parsed &&\n (isFraction\n ? parsed.amount === amount + next.amount && parsed.max === undefined\n : parsed.amount === amount && parsed.max === next.amount)\n ? suggestion\n : undefined\n}\n\n/** Reads text that starts with an amount or range, such as \"4–6\" or \"24 cookies\". */\nfunction readRangeText(\n issues: RecipeIssue[],\n text: string,\n path: Path,\n expected: string,\n): { range: Servings; rest: string } | undefined {\n const match = matchAmount(text.replace(/\\s+/g, ' ').trim())\n\n if (!match) {\n return error(issues, 'invalid_quantity', path, expected)\n }\n\n if ('code' in match) {\n return error(issues, match.code, path, match.message)\n }\n\n const { amount, rest } = match\n return {\n range:\n typeof amount === 'number'\n ? { amount }\n : { amount: amount.min, max: amount.max },\n rest,\n }\n}\n\n/** Reads `{ amount, max }`, where `max` is optional and a `max` equal to `amount` is dropped. */\nfunction readRange(\n issues: RecipeIssue[],\n record: Record<string, unknown>,\n path: Path,\n missingAmount: string,\n): Servings | undefined {\n const value = record.amount\n const amount =\n value === undefined\n ? error(issues, 'missing_field', [...path, 'amount'], missingAmount)\n : isRecord(value) && hasOwn(value, 'min') && hasOwn(value, 'max')\n ? error(\n issues,\n 'invalid_type',\n [...path, 'amount'],\n 'Expected a positive number, received an object. Write a range as { amount: 4, max: 6 }.',\n )\n : readPositive(issues, value, [...path, 'amount'])\n const max =\n record.max === undefined\n ? undefined\n : readPositive(issues, record.max, [...path, 'max'])\n\n if (amount === undefined) {\n return undefined\n }\n\n if (max !== undefined && max < amount) {\n return error(\n issues,\n 'invalid_range',\n [...path, 'max'],\n `Expected a maximum greater than the amount (${amount}), received ${max}.`,\n )\n }\n\n return max === undefined || max === amount ? { amount } : { amount, max }\n}\n\nfunction servingsHint(servings: Servings | undefined): string {\n if (!servings) {\n return ''\n }\n\n const { amount, max } = servings\n return ` For a number of servings, use servings: ${max === undefined ? amount : quote(`${amount}–${max}`)}.`\n}\n\nfunction readSystem(\n issues: RecipeIssue[],\n value: unknown,\n path: Path,\n): System | undefined {\n if (value === undefined || value === 'metric' || value === 'us') {\n return value\n }\n\n const suggestion = value === 'imperial' ? 'us' : undefined\n\n return error(\n issues,\n 'invalid_type',\n path,\n `Expected \"metric\" or \"us\", received ${describeValue(value)}.${suggestion ? ` Did you mean \"${suggestion}\"?` : ''}`,\n suggestion,\n )\n}\n\nfunction readTimes(\n issues: RecipeIssue[],\n pending: PendingIssue[],\n value: unknown,\n path: Path,\n): Times {\n if (value === undefined) {\n return { custom: [] }\n }\n\n const record = asRecord(value)\n\n if (!record) {\n error(\n issues,\n 'invalid_type',\n path,\n `Expected { prep, cook, total, custom }, received ${describeValue(value)}.`,\n )\n return { custom: [] }\n }\n\n const prep = readDuration(issues, record.prep, [...path, 'prep'])\n const cook = readDuration(issues, record.cook, [...path, 'cook'])\n const total = readDuration(issues, record.total, [...path, 'total'])\n const custom = readItems(\n issues,\n pending,\n record.custom,\n [...path, 'custom'],\n 'custom times',\n readCustomTime,\n )\n checkFields(issues, record, TIMES_FIELDS, path)\n return defined({ prep, cook, total, custom })\n}\n\nfunction readCustomTime(\n issues: RecipeIssue[],\n value: unknown,\n path: Path,\n): Draft<CustomTime> | undefined {\n const record = asRecord(value)\n\n if (!record) {\n return error(\n issues,\n 'invalid_type',\n path,\n `Expected { label, minutes }, e.g. { label: \"Chill\", minutes: 60 }, received ${describeValue(value)}.`,\n )\n }\n\n const position = issues.length\n const authored = readText(issues, record.id, [...path, 'id'])\n const label = readText(\n issues,\n record.label,\n [...path, 'label'],\n 'Add a label, e.g. label: \"Chill\".',\n )\n const minutes =\n record.minutes === undefined\n ? error(\n issues,\n 'missing_field',\n [...path, 'minutes'],\n 'Add the time, e.g. minutes: 60 or minutes: \"PT1H\".',\n )\n : readDuration(issues, record.minutes, [...path, 'minutes'])\n checkFields(issues, record, CUSTOM_TIME_FIELDS, path)\n\n if (label === undefined || minutes === undefined) {\n return undefined\n }\n\n return {\n authored,\n derived: slugify(label) || 'time',\n path,\n position,\n build: (id) => ({ id, label, minutes }),\n }\n}\n\nfunction readDuration(\n issues: RecipeIssue[],\n value: unknown,\n path: Path,\n): number | undefined {\n if (value === undefined) {\n return undefined\n }\n\n const minutes =\n typeof value === 'number'\n ? nonNegative(value)\n : typeof value === 'string'\n ? parseIsoDuration(value)\n : undefined\n\n if (minutes === undefined) {\n return error(\n issues,\n 'invalid_duration',\n path,\n `Expected minutes or an ISO 8601 duration like \"PT30M\", received ${describeValue(value)}.`,\n )\n }\n\n return minutes\n}\n\nfunction readNutrition(\n issues: RecipeIssue[],\n value: unknown,\n path: Path,\n): Nutrition | undefined {\n if (value === undefined) {\n return undefined\n }\n\n const record = asRecord(value)\n\n if (!record) {\n return error(\n issues,\n 'invalid_type',\n path,\n `Expected nutrition for one serving, e.g. { calories: 250, fat: \"12 g\" }, received ${describeValue(value)}.`,\n )\n }\n\n const nutrition: Nutrition = {}\n const servingSize = readText(issues, record.servingSize, [\n ...path,\n 'servingSize',\n ])\n\n if (servingSize !== undefined) {\n nutrition.servingSize = servingSize\n }\n\n for (const key of Object.keys(NUTRIENT_UNITS) as NutrientKey[]) {\n const amount = readNutrient(\n issues,\n record[key],\n [...path, key],\n NUTRIENT_UNITS[key],\n )\n\n if (amount !== undefined) {\n nutrition[key] = amount\n }\n }\n\n // Spread here: a module-level spread can't be tree-shaken, so it would add NUTRIENT_UNITS to nearly every entry point.\n checkFields(issues, record, { servingSize: true, ...NUTRIENT_UNITS }, path)\n return Object.keys(nutrition).length > 0 ? nutrition : undefined\n}\n\n/** Reads an amount of `unit`. Empty text counts as absent. */\nfunction readNutrient(\n issues: RecipeIssue[],\n value: unknown,\n path: Path,\n unit: NutrientUnit,\n): number | undefined {\n const text = typeof value === 'string' ? value.trim() : undefined\n\n if (value === undefined || text === '') {\n return undefined\n }\n\n const amount =\n typeof value === 'number'\n ? nonNegative(value)\n : text === undefined\n ? undefined\n : parseNutrient(text, unit)\n\n if (typeof amount === 'number') {\n return amount\n }\n\n return error(\n issues,\n typeof value === 'number'\n ? 'invalid_amount'\n : text === undefined\n ? 'invalid_type'\n : 'invalid_quantity',\n path,\n amount?.message ??\n `Expected ${NUTRIENT_EXAMPLES[unit]}, received ${describeValue(value)}.`,\n )\n}\n\n/** `value` if it's finite and not negative, with `-0` read as `0`. */\nfunction nonNegative(value: number): number | undefined {\n return Number.isFinite(value) && value >= 0 ? Math.abs(value) : undefined\n}\n\n/**\n * Reads optional text, trimmed. Empty text counts as absent. With\n * `requiredMessage`, absent text is a `missing_field` error.\n */\nfunction readText(\n issues: RecipeIssue[],\n value: unknown,\n path: Path,\n requiredMessage?: string,\n): string | undefined {\n if (value !== undefined && typeof value !== 'string') {\n return error(\n issues,\n 'invalid_type',\n path,\n `Expected text, received ${describeValue(value)}.`,\n )\n }\n\n const text = value?.trim()\n\n if (!text) {\n return requiredMessage === undefined\n ? undefined\n : error(issues, 'missing_field', path, requiredMessage)\n }\n\n return text\n}\n\n/**\n * Reads an optional link or image URL, which must be http, https, or relative.\n * Other schemes, such as `javascript:`, are errors, so a URL is safe to render\n * as an `href` or `src`.\n */\nfunction readUrl(\n issues: RecipeIssue[],\n value: unknown,\n path: Path,\n): string | undefined {\n const url = readText(issues, value, path)\n const scheme = url === undefined ? undefined : disallowedScheme(url)\n\n return scheme === undefined\n ? url\n : error(\n issues,\n 'invalid_url',\n path,\n `Expected an http or https URL, or a relative one, received ${quote(`${scheme}…`)}.`,\n )\n}\n\nfunction readBoolean(\n issues: RecipeIssue[],\n value: unknown,\n path: Path,\n): boolean {\n if (value === undefined || typeof value === 'boolean') {\n return value ?? false\n }\n\n error(\n issues,\n 'invalid_type',\n path,\n `Expected true or false, received ${describeValue(value)}.`,\n )\n return false\n}\n","import {\n describeValue,\n type ParseResult,\n quote,\n type RecipeIssue,\n} from '../errors'\nimport { warning } from '../issues'\nimport { isPositive } from '../quantity/amount'\nimport { matchAmount, type Problem } from '../quantity/parse'\nimport type { Amount, Quantity } from '../quantity/types'\nimport { findUnit } from '../units/lookup'\nimport { units, type UnitId } from '../units/registry'\nimport { error, toResult } from '../validation'\n\nconst NUMBER_WORDS =\n 'one|two|three|four|five|six|seven|eight|nine|ten|eleven|twelve'\n\n/** A space or dash between an amount and its unit, as in \"15-ounce\". */\nconst DASH = '[ –—-]'\n\n/**\n * An ingredient read from a line of text. It has no `id`, so pass it through\n * `parseRecipe` before resolving it.\n */\nexport type IngredientLine = {\n name: string\n plural?: string | undefined\n quantity?: Quantity | undefined\n equivalents?: Quantity[] | undefined\n note?: string | undefined\n optional?: boolean | undefined\n}\n\ntype Read<T> = [value: T, end: number]\n\nconst OPTIONAL = /(?:\\(optional\\)|optional\\b ?:?) ?/iy\nconst ABOUT = /(about|approx(?:imately|\\.)?) /iy\nconst PHRASE =\n /((?:an? )?(?:handful|few|couple|little|splash|drizzle|knob|squeeze|sprinkle|dollop))(?: of)? /iy\nconst HYPHENATED_MIXED = /^(\\d+)-(?=(\\d+)[/⁄](\\d+)(?![\\d/⁄]))/\n// Text an amount can be made of, so a measure reads only up to its unit.\nconst AMOUNT_CHARS = /(?:an? )?(?:[\\d .,/⁄¼-¾⅐-⅞–—-]|to )*/iy\nconst UNIT_OF = /([a-z]+) of /iy\nconst TIMES = / ?[x×] ?(?=\\d)/iy\n// Quantity text left after a bare count, as in \"2 or 3\" or \"1 000 g\".\n// A number joined to a word, as in \"2 9-inch pie crusts\", is a name.\nconst UNREAD = / ?(?:(?:or|to|and|plus|half)\\b|[-–—/+&]|\\d+(?:\\.\\d+)?(?= |$))/iy\n// A range or alternative after the unit, as in \"1 cup to 1 ¼ cups\",\n// \"1 lb or 450 g\", or \"100g-150g\".\nconst UNREAD_AFTER_UNIT = / (?:or|to|[-–—&])(?= )|[-–—+&](?=\\d)/iy\nconst PAREN = / ?\\(([^()]*)\\)/y\nconst PARENS = / ?\\(([^()]*)\\)/g\nconst MODIFIER =\n / ?(heaping|heaped|level|scant|rounded|generous|good|small|medium|large|big)(?= )/iy\nconst JOIN = /(?: (plus|and|\\+)(?![a-z]))? ?/iy\nconst SEPARATOR = / ?[;/] ?/y\nconst OF = / ?of(?: (?:an?|the))?(?= |$)/iy\nconst PHRASE_NOTE =\n / (?=to taste|as needed|as required|plus more|plus extra|or more|or to taste|for (?:serving|garnish|dusting|greasing|frying|drizzling|decoration))/i\nconst OPTIONAL_NOTE = /(?:^|,) ?optional(?= ?(?:,|$))/gi\nconst OPTIONAL_PAREN = /^optional\\b[,;:]? ?/i\nconst CONTAINER =\n /^(?:stalk|rib|ear|sheet|loa(?:f|ves)|knob|strip|bag|box|jar|bottle|packet|envelope|tin|block|ball|handful)(?:e?s)?$/i\nconst BONELESS = /(?:^|[^a-z])(?:bone|skin)less$/i\n\nlet patterns: ReturnType<typeof compilePatterns> | undefined\n\n// A bundler drops an unused regex literal but may keep a `new RegExp` call, so\n// the patterns built from strings compile on first use.\nfunction getPatterns() {\n return (patterns ??= compilePatterns())\n}\n\nfunction compilePatterns() {\n const word = String.raw`([a-z]+(?:-[a-z]+)?)\\.?`\n const end = String.raw`(?=[ ,;()/]|[-–—+&]\\d|$)`\n return {\n count: new RegExp(`(an?|${NUMBER_WORDS}) (?=\\\\S)`, 'iy'),\n unit: new RegExp(`${DASH}?${word}${end}`, 'iy'),\n twoWordUnit: new RegExp(`${DASH}?${word} ${word}${end}`, 'iy'),\n }\n}\n\n/**\n * Parses an ingredient line, such as `'1 ½ cups (190 g) flour, sifted'`, into\n * ingredient input. Never throws. Pass the result through `parseRecipe` before\n * resolving, or pass this function to `parseRecipe` as\n * `{ parseIngredientLine }` to put lines in recipe input.\n *\n * Reads a leading amount (`2`, `1–2`, `a`, `one`) and unit, and a second\n * measure in parentheses that hold nothing but measures, or after a slash or\n * semicolon, as `equivalents`. With no amount, a unit before \"of\" reads as 1\n * when it starts the line, after any leading \"optional\" and a space or colon,\n * and is written in letters only, so `'pinch of salt'` gets\n * `quantity: { amount: 1, unit: 'pinch' }`, but `'big pinch of salt'`,\n * `'tsp. of salt'`, `'fl oz of water'` and `'Optional - pinch of salt'` get\n * none. With no\n * leading amount or unit, the first measure in parentheses that hold nothing\n * but measures is the `quantity` instead, so `'Butter (100g)'` gets\n * `quantity: { amount: 100, unit: 'g' }`. Measures after a leading \"optional\"\n * in parentheses are read the same way, except straight after the amount,\n * where the first is dropped (`'2 (optional, 15 oz) cans beans'`). A measure\n * in the same dimension, mass or volume, after \"plus\", \"and\" or \"+\", or\n * straight after the first, is added to it (`'1 lb 2 oz flour'` is 1.125 lb).\n * In parentheses, any other sum (across dimensions, in count units such as\n * \"pinch\", or of three measures) makes every measure in them part of the note\n * (`'1 cup (8 oz + 1 tbsp) milk'`).\n * It also reads a note after the first comma outside parentheses that doesn't\n * follow \"boneless\" or \"skinless\", phrases such as \"to taste\", and \"optional\"\n * at the start of the line or of text in parentheses (the innermost when they\n * nest), or as its own comma-separated item after the first comma. After a\n * leading \"optional\" and any space or colon, or \"(optional)\" and any space,\n * the rest is read as if it were the whole line, so\n * `'Optional - 2 cups flour'` gets `optional: true` and\n * `name: '- 2 cups flour'` with no quantity. With a comma there, not even\n * \"optional\" is read: `'optional, 2 cups flour'` becomes\n * `{ name: 'optional, 2 cups flour' }` with a warning. Text in parentheses\n * before the first comma that isn't a measure or a leading \"optional\"\n * (only the innermost when they nest) is a note too, ahead of the text after\n * the comma, so `'1 onion (diced), peeled'` gets `note: 'diced, peeled'`. When\n * parentheses before the first comma nest, the outer ones stay in the name with\n * their text, so `'2 onions (diced (fine)), peeled'` gets\n * `name: 'onions (diced)'` and `note: 'fine, peeled'`, and\n * `'115 g butter ((1/2 cup))'` gets `name: 'butter ()'`.\n * A bare count gets a `plural` from the word before \"of\", a leading container\n * such as \"jars\", or else the last word. There's none when that word gets no\n * other form, as when it ends in parentheses (`'2 onions (diced (fine))'`),\n * has no plural ending after a count above 1 or a range (`'12 shrimp'`), or\n * ends in \"s\" after a count of 1 or less (`'1 eggs'`, `'½ onions'`). A\n * line it can't read becomes `{ name: line }` with a warning; only blank text\n * or a value that isn't a string is an error.\n *\n * @example\n * parseIngredientLine('1 ½ cups (190 g) flour, sifted').data\n * // { name: 'flour', quantity: { amount: 1.5, unit: 'cup' }, equivalents: [{ amount: 190, unit: 'g' }], note: 'sifted' }\n * parseIngredientLine('2 large eggs').data // { name: 'large egg', plural: 'large eggs', quantity: { amount: 2 } }\n */\nexport function parseIngredientLine(text: string): ParseResult<IngredientLine> {\n const issues: RecipeIssue[] = []\n\n if (typeof text !== 'string') {\n error(\n issues,\n 'invalid_type',\n [],\n `Expected ingredient text such as \"2 cups flour\", received ${describeValue(text)}.`,\n )\n return toResult<IngredientLine>('invalid_ingredient', undefined, issues)\n }\n\n // U+200B is invisible but isn't whitespace. U+200C and U+200D are kept,\n // because they join letters in some scripts and in emoji.\n const line = text.replace(/[\\s\\u200b]+/g, ' ').trim()\n\n if (line === '') {\n error(\n issues,\n 'missing_field',\n [],\n 'Add the ingredient text, e.g. \"2 cups flour\".',\n )\n return toResult<IngredientLine>(\n 'invalid_ingredient',\n undefined,\n issues,\n quote(text),\n )\n }\n\n let ingredient = readLine(line)\n\n if (isProblem(ingredient)) {\n warning(\n issues,\n ingredient.code,\n [],\n `${ingredient.message} The whole line is kept as the name.`,\n )\n ingredient = { name: line }\n }\n\n return toResult('invalid_ingredient', ingredient, issues)\n}\n\nfunction readLine(line: string): IngredientLine | Problem {\n const p = getPatterns()\n const notes: string[] = []\n const equivalents: Quantity[] = []\n let optional = false\n let quantity: Quantity | undefined\n let amount: Amount | undefined\n let unitText = ''\n let i = 0\n let match: RegExpExecArray | null\n\n const eat = (pattern: RegExp): RegExpExecArray | null => {\n const found = exec(pattern, line, i)\n if (found) {\n i = pattern.lastIndex\n }\n return found\n }\n\n const addNote = (text: string): void => {\n const note = /[^ ,](?:.*[^ ,])?/s.exec(text)\n if (note) {\n notes.push(note[0])\n }\n }\n\n const readParen = (content: string, keep: boolean): string => {\n const text = content.replace(OPTIONAL_PAREN, () => {\n optional = true\n return ''\n })\n const measures = text ? readMeasures(text) : undefined\n\n if (measures) {\n quantity ??= measures.shift()\n // A spread passes each measure as an argument, which overflows the stack\n // for a long list.\n for (const measure of measures) {\n equivalents.push(measure)\n }\n return ''\n }\n\n if (keep && text) {\n return ` (${text})`\n }\n\n addNote(text)\n return ''\n }\n\n if (eat(OPTIONAL)) {\n optional = true\n }\n\n match = exec(ABOUT, line, i)\n if (match && readAmount(line, ABOUT.lastIndex)) {\n addNote(match[1]!)\n i = ABOUT.lastIndex\n }\n\n if ((match = eat(PHRASE))) {\n addNote(match[1]!)\n } else if ((match = eat(p.count))) {\n amount = NUMBER_WORDS.split('|').indexOf(match[1]!.toLowerCase()) + 1 || 1\n } else {\n const found = readAmount(line, i, true)\n\n if (isProblem(found)) {\n return found\n }\n if (found) {\n ;[amount, i] = found\n } else if ((match = exec(UNIT_OF, line, i))) {\n const unit = findUnit(match[1]!)\n if (unit) {\n quantity = { amount: 1, unit }\n i = UNIT_OF.lastIndex\n }\n }\n }\n\n if (amount !== undefined) {\n let each: Quantity[] | undefined\n eat(TIMES)\n\n if ((match = eat(PAREN))) {\n each = readMeasures(match[1]!)\n if (!each) {\n readParen(match[1]!, false)\n }\n } else {\n const measure = readMeasure(line, i, false)\n if (measure) {\n each = [measure[0]]\n i = measure[1]\n }\n }\n\n const start = i\n const modifier = eat(MODIFIER)\n const unit = readUnit(line, i)\n\n if (unit) {\n if (modifier) {\n addNote(modifier[1]!)\n }\n unitText = line.slice(i, unit[1])\n quantity = { amount, unit: unit[0] }\n i = unit[1]\n\n const size =\n !each &&\n units[unit[0]].dimension === 'count' &&\n readMeasure(line, i, false)\n\n if (size) {\n equivalents.push(size[0])\n i = size[1]\n } else if (!each) {\n const extended = extend(line, [quantity, i])\n if (isProblem(extended)) {\n return extended\n }\n ;[quantity, i] = extended\n }\n\n while ((match = eat(SEPARATOR))) {\n const measure = readMeasure(line, i, true)\n if (!measure) {\n return noMeasure(quote(match[0].trim()), '100 g/3½ oz')\n }\n equivalents.push(measure[0])\n i = measure[1]\n }\n } else {\n i = start\n quantity = { amount }\n }\n\n if (exec(unit ? UNREAD_AFTER_UNIT : UNREAD, line, i)) {\n return {\n code: 'invalid_quantity',\n message: `Couldn't read the quantity in ${quote(line)}. Write one amount or range before the unit, e.g. \"2-3 eggs\" or \"2 ½ cups\".`,\n }\n }\n\n for (const item of each ?? []) {\n const total = combine(amount, item.amount, (a, b) => a * b)\n if (isProblem(total)) {\n return total\n }\n equivalents.push({ ...item, amount: total })\n }\n }\n\n const of = quantity !== undefined && eat(OF)\n\n const rest = line.slice(i).trim()\n const comma = topLevelComma(rest)\n let name = rest\n .slice(0, comma)\n .replace(PARENS, (_, content: string) => readParen(content, false))\n const phrase = PHRASE_NOTE.exec(name)\n\n if (phrase) {\n addNote(name.slice(phrase.index))\n name = name.slice(0, phrase.index)\n }\n\n addNote(\n rest\n .slice(comma + 1)\n .replace(PARENS, (_, content: string) => readParen(content, true))\n .replace(OPTIONAL_NOTE, () => {\n optional = true\n return ''\n }),\n )\n name = name.trim()\n\n if (!name) {\n if (\n of ||\n !unitText ||\n !quantity?.unit ||\n units[quantity.unit].dimension !== 'count'\n ) {\n return {\n code: 'missing_field',\n message: 'Add a name after the quantity, e.g. \"2 cups flour\".',\n }\n }\n name = unitText.replace(/^[ –—-]/, '')\n quantity = { amount: quantity.amount }\n }\n\n let plural: string | undefined\n if (quantity && !quantity.unit) {\n const many = typeof quantity.amount !== 'number' || quantity.amount > 1\n ;[name, plural] = countForms(name, many)\n }\n\n return {\n name,\n ...(plural !== undefined && { plural }),\n ...(quantity && { quantity }),\n ...(equivalents.length > 0 && { equivalents }),\n ...(notes.length > 0 && { note: notes.join(', ') }),\n ...(optional && { optional }),\n }\n}\n\nfunction exec(\n pattern: RegExp,\n text: string,\n start: number,\n): RegExpExecArray | null {\n pattern.lastIndex = start\n return pattern.exec(text)\n}\n\n/**\n * Reads the amount at `start` with `matchAmount`, ending where the text after\n * it starts. In a line, \"1-1/2\" is 1 ½, where `parseQuantity` reads a reversed\n * range. Unless `whole` is set, `matchAmount` sees only the amount and the\n * character after it, so a run of measures is read in linear time; a problem's\n * message then quotes only that.\n */\nfunction readAmount(\n text: string,\n start: number,\n whole?: boolean,\n): Read<Amount> | Problem | undefined {\n exec(AMOUNT_CHARS, text, start)\n const rest = text\n .slice(start, whole ? undefined : AMOUNT_CHARS.lastIndex + 1)\n .replace(\n HYPHENATED_MIXED,\n (dash, whole: string, numerator: string, denominator: string) =>\n Number(numerator) < Number(denominator) ? `${whole} ` : dash,\n )\n // matchAmount refuses text with a \"1,5\" anywhere in it, but in a line only\n // one in the amount counts.\n const comma = rest.search(/\\d,\\d/)\n const head = comma < 0 ? rest : rest.slice(0, comma).trimEnd()\n const match = matchAmount(head)\n\n if (comma >= 0 && (match ? !('code' in match) && !match.rest : !head)) {\n return matchAmount(rest) as Problem\n }\n if (!match || 'code' in match) {\n return match\n }\n\n return [match.amount, start + head.length - match.rest.length]\n}\n\nfunction isProblem(value: unknown): value is Problem {\n return typeof value === 'object' && value !== null && 'code' in value\n}\n\nfunction readUnit(text: string, start: number): Read<UnitId> | undefined {\n const { twoWordUnit, unit } = getPatterns()\n\n for (const pattern of [twoWordUnit, unit]) {\n const match = exec(pattern, text, start)\n const id =\n match && findUnit(match[2] ? `${match[1]} ${match[2]}` : match[1]!)\n if (id) {\n return [id, pattern.lastIndex]\n }\n }\n\n return undefined\n}\n\n/** A numeric amount and a unit, such as \"190 g\", \"14-ounce\", or \"1 lb 2 oz\". */\nfunction readMeasure(\n text: string,\n start: number,\n compound: boolean,\n): Read<Quantity> | undefined {\n const amount = readAmount(text, text[start] === ' ' ? start + 1 : start)\n\n if (!amount || isProblem(amount)) {\n return undefined\n }\n\n const unit = readUnit(text, amount[1])\n\n if (!unit) {\n return undefined\n }\n\n const measure: Read<Quantity> = [\n { amount: amount[0], unit: unit[0] },\n unit[1],\n ]\n const extended = compound ? extend(text, measure) : measure\n return isProblem(extended) ? undefined : extended\n}\n\n/**\n * Adds a second measure in the same dimension, as in \"1 cup plus 2 tbsp\" or\n * \"1 lb 2 oz\". After \"plus\", \"and\", or \"+\", the second measure is required.\n */\nfunction extend(\n text: string,\n measure: Read<Quantity>,\n): Read<Quantity> | Problem {\n const [{ amount, unit }, end] = measure\n const connector = exec(JOIN, text, end)![1]\n const extra = readMeasure(text, JOIN.lastIndex, false)\n const from = units[unit!]\n const to = extra && units[extra[0].unit!]\n\n if (!from.toBase || !to?.toBase || from.dimension !== to.dimension) {\n return connector\n ? noMeasure(\n `${quote(connector)} in the same kind of unit`,\n '1 cup plus 2 tbsp',\n )\n : measure\n }\n\n const ratio = to.toBase / from.toBase\n const total = combine(amount, extra![0].amount, (a, b) => a + b * ratio)\n return isProblem(total) ? total : [{ amount: total, unit }, extra![1]]\n}\n\nfunction noMeasure(after: string, example: string): Problem {\n return {\n code: 'invalid_quantity',\n message: `Expected a measure after ${after}, e.g. \"${example}\".`,\n }\n}\n\n/** Measures separated by \";\" or \"/\", as in \"12 Tbsp; 170g\", filling `text`. */\nfunction readMeasures(text: string): Quantity[] | undefined {\n const measures: Quantity[] = []\n let i = 0\n\n for (;;) {\n const measure = readMeasure(text, i, true)\n if (!measure) {\n return undefined\n }\n measures.push(measure[0])\n i = measure[1]\n\n if (i === text.length) {\n return measures\n }\n if (!exec(SEPARATOR, text, i)) {\n return undefined\n }\n i = SEPARATOR.lastIndex\n }\n}\n\n/** Multiplies or adds two amounts. A total that overflows or underflows is a problem. */\nfunction combine(\n a: Amount,\n b: Amount,\n op: (a: number, b: number) => number,\n): Amount | Problem {\n const [aMin, aMax] = typeof a === 'number' ? [a, a] : [a.min, a.max]\n const [bMin, bMax] = typeof b === 'number' ? [b, b] : [b.min, b.max]\n const min = op(aMin, bMin)\n const max = op(aMax, bMax)\n\n if (!isPositive(min) || !isPositive(max)) {\n return {\n code: 'invalid_amount',\n message:\n 'The total amount is out of range. Write it as one amount, e.g. \"800 g\".',\n }\n }\n\n return min < max ? { min, max } : min\n}\n\n/** The first comma outside parentheses that ends a name, skipping \"boneless, skinless\". */\nfunction topLevelComma(text: string): number {\n let depth = 0\n\n for (let j = 0; j < text.length; j++) {\n const char = text[j]\n if (char === '(') {\n depth++\n } else if (char === ')') {\n depth = Math.max(0, depth - 1)\n } else if (\n char === ',' &&\n depth === 0 &&\n !BONELESS.test(text.slice(0, j).slice(-9))\n ) {\n return j\n }\n }\n\n return text.length\n}\n\n/**\n * Returns the singular name and its plural. The counted word is the one before\n * \"of\", a leading container such as \"stalks\", or else the last word.\n */\nfunction countForms(\n name: string,\n many: boolean,\n): [name: string, plural: string | undefined] {\n const words = name.split(' ')\n let k = words.indexOf('of') - 1\n\n if (k < 0) {\n k = CONTAINER.test(words[0]!) ? 0 : words.length - 1\n }\n\n const word = words[k]!\n const other = many ? singular(word) : pluralize(word)\n\n if (other === word) {\n return [name, undefined]\n }\n\n words[k] = other\n const swapped = words.join(' ')\n return many ? [swapped, name] : [name, swapped]\n}\n\nfunction singular(word: string): string {\n return word.replace(\n /(?:(lea|hal|loa)ves|([rtdv])ies|(o|ch|sh|x|ss|chill?i)es|([^su])s)$/i,\n (_, f?: string, y?: string, es?: string, s?: string) =>\n f ? `${f}f` : y ? `${y}y` : (es ?? s)!,\n )\n}\n\nfunction pluralize(word: string): string {\n return word.replace(\n /(?:(lea|hal|loa)f|([^aeiou])y|(ch|sh|x|z|tomato|potato|mango|chill?i)|[a-rt-z])$/i,\n (match, f?: string, y?: string, es?: string) =>\n f ? `${f}ves` : y ? `${y}ies` : es ? `${es}es` : `${match}s`,\n )\n}\n","import type { UnitId } from '../units/registry'\nimport {\n checkFactor,\n checkQuantity,\n mapAmount,\n type SameAmount,\n} from './amount'\nimport type { Amount, Quantity } from './types'\n\n/**\n * Multiplies a quantity by `factor`. Both ends of a range scale, the unit is\n * kept, and nothing is rounded.\n *\n * @throws {RecipeBookError} `invalid_argument` when `factor` is not a finite\n * number greater than 0, `quantity` isn't a quantity object, the amount is\n * not a finite number greater than 0 or a range of them, a range's `min`\n * isn't less than its `max`, or the quantity has `max` set, as a `Servings`\n * or `Yield` has. `resolveRecipe` scales those. The unit isn't checked.\n *\n * @example\n * scaleQuantity({ amount: 1.5, unit: 'cup' }, 2) // { amount: 3, unit: 'cup' }\n * scaleQuantity({ amount: { min: 2, max: 3 }, unit: 'tbsp' }, 2) // { amount: { min: 4, max: 6 }, unit: 'tbsp' }\n */\nexport function scaleQuantity<A extends Amount>(\n quantity: Quantity & { amount: A },\n factor: number,\n): { amount: SameAmount<A>; unit?: UnitId | undefined } {\n checkQuantity('scaleQuantity', quantity)\n checkFactor('scaleQuantity', 'factor', factor)\n\n return multiply(quantity, factor)\n}\n\n/** {@link scaleQuantity} without argument checks. */\nexport function multiply<A extends Amount>(\n quantity: Quantity & { amount: A },\n factor: number,\n): { amount: SameAmount<A>; unit?: UnitId | undefined } {\n const amount = mapAmount(quantity.amount, (value) => value * factor)\n return quantity.unit === undefined\n ? { amount }\n : { amount, unit: quantity.unit }\n}\n","import { describeValue, RecipeBookError } from '../errors'\nimport { amountEnds, mapAmount } from '../quantity/amount'\nimport type { Quantity } from '../quantity/types'\nimport {\n lookupUnit,\n type System,\n type UnitDefinition,\n type UnitId,\n} from './registry'\n\ntype Rung = {\n unit: UnitId\n /** Smallest amount, in this unit, that may use it. */\n min?: number\n /** Measuring-set fractions the amount must land near, within 5%, by denominator: 4 for quarters. */\n steps?: readonly number[]\n /** From this amount up, the steps no longer apply. */\n stepsBelow?: number\n}\n\nconst STEP_TOLERANCE = 0.05\nconst FLOAT_TOLERANCE = 1e-9\n\n// Largest unit first. The last rung has no conditions, so it always matches.\nconst LADDERS: Record<System, Record<'mass' | 'volume', readonly Rung[]>> = {\n metric: {\n mass: [{ unit: 'kg', min: 1 }, { unit: 'g' }],\n volume: [{ unit: 'l', min: 1 }, { unit: 'ml' }],\n },\n us: {\n mass: [{ unit: 'lb', min: 1 }, { unit: 'oz' }],\n volume: [\n { unit: 'cup', min: 0.25, steps: [4, 3], stepsBelow: 1 },\n { unit: 'tbsp', min: 1, steps: [2] },\n { unit: 'tsp' },\n ],\n },\n}\n\n/** {@link toSystem} without argument checks. Unknown units are returned unchanged. */\nexport function inSystem(quantity: Quantity, system: System): Quantity {\n const source = lookupUnit(quantity.unit)\n\n if (\n source?.toBase === undefined ||\n source.dimension === 'count' ||\n source.systems.includes(system)\n ) {\n return quantity\n }\n\n return onLadder(\n quantity,\n source.toBase,\n LADDERS[system][source.dimension],\n system,\n )\n}\n\n/**\n * Moves a quantity to the best unit on its own ladder that is native to\n * `system`: 6 tsp becomes 2 tbsp, and 1000 g becomes 1 kg. Quantities whose\n * unit is on no ladder, or not native to `system`, are returned unchanged.\n */\nexport function rebalance(quantity: Quantity, system: System): Quantity {\n const source = lookupUnit(quantity.unit)\n\n if (\n source?.toBase === undefined ||\n source.dimension === 'count' ||\n !source.systems.includes(system)\n ) {\n return quantity\n }\n\n for (const owner of source.systems) {\n const ladder = LADDERS[owner][source.dimension]\n if (ladder.some((rung) => rung.unit === source.id)) {\n return onLadder(quantity, source.toBase, ladder, system)\n }\n }\n\n return quantity\n}\n\nexport function isSystem(value: unknown): value is System {\n return value === 'metric' || value === 'us'\n}\n\n/** Throws `invalid_argument`, naming `fn`, unless `system` is `'metric'` or `'us'`. */\nexport function checkSystem(fn: string, system: unknown): void {\n if (!isSystem(system)) {\n throw new RecipeBookError(\n 'invalid_argument',\n `${fn}: system must be \"metric\" or \"us\", received ${describeValue(system)}.`,\n )\n }\n}\n\nfunction onLadder(\n quantity: Quantity,\n fromBase: number,\n ladder: readonly Rung[],\n system: System,\n): Quantity {\n const base = mapAmount(quantity.amount, (value) => value * fromBase)\n\n for (const rung of ladder) {\n const unit = lookupUnit(rung.unit) as UnitDefinition & { toBase: number }\n if (!unit.systems.includes(system)) {\n continue\n }\n\n const amount = mapAmount(base, (value) => value / unit.toBase)\n const ends = amountEnds(amount)\n const low = ends[0]!\n\n const tolerance = rung.steps ? STEP_TOLERANCE : FLOAT_TOLERANCE\n const meetsMin = rung.min === undefined || low >= rung.min * (1 - tolerance)\n const fitsSteps =\n !rung.steps ||\n ends.every(\n (value) =>\n (rung.stepsBelow !== undefined && value >= rung.stepsBelow) ||\n rung.steps!.some((denominator) =>\n nearMultiple(value, 1 / denominator),\n ),\n )\n\n if (meetsMin && fitsSteps) {\n return unit.id === quantity.unit ? quantity : { amount, unit: unit.id }\n }\n }\n\n return quantity\n}\n\nfunction nearMultiple(value: number, step: number): boolean {\n return (\n Math.abs(value - Math.round(value / step) * step) <= STEP_TOLERANCE * value\n )\n}\n","import { checkFactor, isPositive } from './quantity/amount'\nimport { multiply } from './quantity/scale'\nimport type { Quantity } from './quantity/types'\nimport type { Ingredient, Recipe, Servings, Step, Yield } from './recipe/types'\nimport { lookupUnit, type System } from './units/registry'\nimport { checkSystem, inSystem, isSystem, rebalance } from './units/system'\n\n/**\n * Where a resolved quantity comes from: the ingredient's `quantity`, one of its\n * `equivalents`, or a conversion into the display system. May grow in minor releases.\n */\nexport type QuantityOrigin = 'authored' | 'equivalent' | 'converted'\n\n/** An ingredient, scaled and expressed in the display system. */\nexport type ResolvedIngredient = {\n id: string\n /** The ingredient as authored, unscaled. */\n ingredient: Ingredient\n /**\n * Absent for unquantified ingredients, such as \"salt, to taste\". May be the\n * authored object; treat it as read-only.\n */\n quantity?: Quantity | undefined\n /** `'authored'` for unquantified ingredients. */\n origin: QuantityOrigin\n}\n\n/** What {@link resolveRecipe} returns: the recipe at a scale, in one system, unrounded. */\nexport type ResolvedRecipe = {\n recipe: Recipe\n /**\n * The `scale` option, else `servings` divided by the scaling base. Always\n * between 1e-6 and 1e6, and 1 when both options fall back.\n */\n scale: number\n /**\n * The recipe's servings at this scale. At 1×, the authored servings. When\n * the `servings` option sets a scale other than 1, exactly that number with\n * no `max`; with `scale`, both ends of a range scale.\n */\n servings?: Servings | undefined\n /**\n * The recipe's yield at this scale. At 1×, the authored yield. When the\n * yield is the scaling base and the `servings` option sets a scale other\n * than 1, exactly that number with no `max`; otherwise both ends of a range\n * scale.\n */\n yield?: Yield | undefined\n system: System\n /**\n * True when an ingredient's quantity has a unit that belongs to only one\n * system. Step text isn't read; `segmentStepText` finds its temperatures.\n */\n canConvert: boolean\n ingredients: Array<{\n id: string\n title?: string | undefined\n items: ResolvedIngredient[]\n }>\n /** Steps numbered from 1, continuing across sections. */\n steps: Array<{\n id: string\n title?: string | undefined\n items: Array<Step & { number: number }>\n }>\n}\n\n/** Options for {@link resolveRecipe}. */\nexport type ResolveRecipeOptions = {\n /**\n * Scales by `servings / base`, where the base is the recipe's servings\n * amount, else its yield amount, else 1. Defaults to the base. A value that\n * would scale the recipe by less than 1e-6 or more than 1e6, or isn't a\n * number, also uses the default.\n */\n servings?: number | undefined\n /**\n * A direct multiplier, for 1×, 2×, and 3× controls. Wins over `servings`.\n * A value outside 1e-6 to 1e6, or that isn't a number, is ignored.\n */\n scale?: number | undefined\n /** Defaults to `recipe.system`, then `'metric'`. An unknown system also uses the default. */\n system?: System | undefined\n /** Moves scaled amounts to a better unit on their own ladder (6 tsp to 2 tbsp). Default `true`. */\n rebalance?: boolean | undefined\n}\n\n/** Options for {@link resolveIngredient}. */\nexport type ResolveIngredientOptions = {\n scale: number\n system: System\n /** Moves scaled amounts to a better unit on their own ladder (6 tsp to 2 tbsp). Default `true`. */\n rebalance?: boolean | undefined\n}\n\n/**\n * Scales a recipe to a number of servings, or by a multiplier, and expresses\n * each ingredient in a measurement system. Pure, and never throws for an\n * unchanged recipe from `parseRecipe`: invalid options fall back to their\n * defaults, and an error thrown by a getter or proxy in the options passes\n * through. Nothing is rounded; format for display.\n *\n * Each ingredient uses the first of `[quantity, ...equivalents]` that is native to\n * the system (a bare count is native to both), scaled. When none is, `quantity`\n * is scaled, then converted with `toSystem`. Units never change dimension.\n * At any scale but 1, the chosen quantity may move along its unit's ladder, so\n * 3 tsp at 2× is 2 tbsp; pass `rebalance: false` to keep the chosen units.\n *\n * @example\n * // Serves 4–6; flour is 1 ½ cups with a 190 g equivalent.\n * const resolved = resolveRecipe(pancakes, { servings: 8, system: 'metric' })\n * resolved.scale // 2\n * resolved.servings // { amount: 8 }\n * const flour = resolved.ingredients[0]?.items[0]\n * flour?.quantity // { amount: 380, unit: 'g' }\n * flour?.origin // 'equivalent'\n *\n * resolveRecipe(pancakes, { scale: 2 }).servings // { amount: 8, max: 12 }\n */\nexport function resolveRecipe(\n recipe: Recipe,\n options?: ResolveRecipeOptions,\n): ResolvedRecipe {\n const {\n servings,\n scale: requestedScale,\n system: requestedSystem,\n rebalance,\n }: ResolveRecipeOptions = options ?? {}\n const servingsIsBase = isPositive(recipe.servings?.amount)\n const base =\n [recipe.servings?.amount, recipe.yield?.amount].find(isPositive) ?? 1\n const ratio = typeof servings === 'number' ? servings / base : Number.NaN\n const exactServings =\n isScale(requestedScale) || !isScale(ratio) || isUnity(ratio)\n ? undefined\n : servings\n const scale = isScale(requestedScale)\n ? requestedScale\n : isScale(ratio)\n ? ratio\n : 1\n const system = [requestedSystem, recipe.system].find(isSystem) ?? 'metric'\n const shouldRebalance = rebalance !== false\n let number = 0\n\n function resize<T extends Servings>(\n range: T,\n isBase: boolean,\n ): Omit<T, 'max'> & Servings {\n if (exactServings !== undefined && isBase) {\n return withRange(range, exactServings)\n }\n return isUnity(scale)\n ? range\n : withRange(range, range.amount * scale, (range.max ?? 0) * scale)\n }\n\n return {\n recipe,\n scale,\n ...(recipe.servings && {\n servings: resize(recipe.servings, servingsIsBase),\n }),\n ...(recipe.yield && { yield: resize(recipe.yield, !servingsIsBase) }),\n system,\n canConvert: recipe.ingredients.some((section) =>\n section.items.some(\n (item) => lookupUnit(item.quantity?.unit)?.systems.length === 1,\n ),\n ),\n ingredients: recipe.ingredients.map((section) => ({\n id: section.id,\n ...(section.title !== undefined && { title: section.title }),\n items: section.items.map((ingredient) =>\n resolveLine(ingredient, scale, system, shouldRebalance),\n ),\n })),\n steps: recipe.steps.map((section) => ({\n id: section.id,\n ...(section.title !== undefined && { title: section.title }),\n items: section.items.map((step) => ({ ...step, number: ++number })),\n })),\n }\n}\n\n/**\n * Resolves one ingredient the way {@link resolveRecipe} does, at a raw\n * scale factor. Unlike `resolveRecipe`, it doesn't limit the scale to\n * 1e-6 to 1e6, so a huge scale can overflow an amount to `Infinity`, which\n * the format functions reject.\n *\n * @throws {RecipeBookError} `invalid_argument` when `scale` is not a finite\n * number greater than 0, or `system` is not `'metric'` or `'us'`.\n *\n * @example\n * // salt is 3 tsp.\n * resolveIngredient(salt, { scale: 2, system: 'us' }).quantity // { amount: 2, unit: 'tbsp' }\n */\nexport function resolveIngredient(\n ingredient: Ingredient,\n options: ResolveIngredientOptions,\n): ResolvedIngredient {\n checkFactor('resolveIngredient', 'scale', options?.scale)\n checkSystem('resolveIngredient', options.system)\n\n return resolveLine(\n ingredient,\n options.scale,\n options.system,\n options.rebalance !== false,\n )\n}\n\nfunction resolveLine(\n ingredient: Ingredient,\n scale: number,\n system: System,\n shouldRebalance: boolean,\n): ResolvedIngredient {\n const { id, quantity } = ingredient\n\n if (quantity === undefined) {\n return { id, ingredient, origin: 'authored' }\n }\n\n const candidates = [quantity, ...ingredient.equivalents]\n const native = candidates.findIndex((candidate) =>\n isNative(candidate, system),\n )\n const chosen = candidates[native] ?? quantity\n const scaled = isUnity(scale) ? chosen : multiply(chosen, scale)\n\n if (native < 0) {\n return {\n id,\n ingredient,\n quantity: withEnds(inSystem(scaled, system)),\n origin: 'converted',\n }\n }\n\n return {\n id,\n ingredient,\n quantity: withEnds(\n shouldRebalance && !isUnity(scale) ? rebalance(scaled, system) : scaled,\n ),\n origin: native === 0 ? 'authored' : 'equivalent',\n }\n}\n\n// Ends a few ulps apart can round to equal when scaled or converted, so a range\n// is kept only while its ends differ.\nfunction withRange<T extends Servings>(\n range: T,\n amount: number,\n max = 0,\n): Omit<T, 'max'> & Servings {\n const { max: authoredMax, ...rest } = range\n return { ...rest, amount, ...(max > amount && { max }) }\n}\n\nfunction withEnds(quantity: Quantity): Quantity {\n const { amount } = quantity\n return typeof amount === 'number' || amount.min < amount.max\n ? quantity\n : { ...quantity, amount: amount.min }\n}\n\nfunction isScale(value: unknown): value is number {\n return typeof value === 'number' && value >= 1e-6 && value <= 1e6\n}\n\nfunction isUnity(scale: number): boolean {\n return Math.abs(scale - 1) <= 1e-9\n}\n\nexport function isNative(quantity: Quantity, system: System): boolean {\n const unit = lookupUnit(quantity.unit)\n return unit === undefined || unit.systems.includes(system)\n}\n","import { describeValue, RecipeBookError } from '../errors'\n\n// Literals, not `10 ** n`: Math.pow is implementation-approximated, so engines may disagree.\nconst POWERS = [\n 1, 10, 100, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, 1e12, 1e13, 1e14,\n 1e15,\n] as const\nconst MAX_DIGITS = 15\n\n/** Joins a number to its unit so the two never wrap apart. */\nexport const NBSP = '\\u00A0'\n\nexport type PluralForm = 'one' | 'other'\n\n/** Writes a value already rounded to `digits` fraction digits, without trailing zeros or grouping. */\nexport type NumberWriter = (value: number, digits: number) => string\n\n/**\n * Rounds half away from zero to `digits` fraction digits (0 to 15), at 15\n * significant digits so 1.005 rounds to 1.01 although its double is just\n * below. When `digits` would need more than 15 significant digits, rounds to a\n * whole number. Never returns -0.\n */\nexport function round(value: number, digits: number): number {\n const power = POWERS[digits]!\n const magnitude = Math.abs(value)\n const scaled = magnitude * power\n const rounded =\n scaled < 1e15\n ? Math.round(Number(scaled.toPrecision(15))) / power\n : Math.round(magnitude)\n\n return value < 0 && rounded !== 0 ? -rounded : rounded\n}\n\n/**\n * Rounds a positive value to at least `digits` fraction digits, adding digits\n * until the result is not 0, so a small amount never reads as 0.\n */\nexport function roundAboveZero(\n value: number,\n digits: number,\n): [rounded: number, digits: number] {\n for (let used = digits; used <= MAX_DIGITS; used++) {\n const rounded = round(value, used)\n if (rounded > 0) {\n return [rounded, used]\n }\n }\n\n return [1e-15, MAX_DIGITS]\n}\n\n// Keyed by caller input, which may come from a request, so the cache is bounded.\nconst writers = new Map<string, NumberWriter>()\nconst MAX_WRITERS = 32\n\n/**\n * The number writer for `locale`. English (`en` or `en-` and a region) is\n * hand-written, so the default output never depends on the engine's ICU data.\n * Other tags, including English ones with extensions such as\n * `en-US-u-nu-arab`, use `Intl` with the explicit locale; unsupported ones\n * fall back to English rather than to the runtime's default locale.\n *\n * @throws {RecipeBookError} `invalid_argument` when `locale` is not a valid\n * language tag. Without `Intl`, only a `locale` that isn't a string throws,\n * and every string writes English.\n */\nexport function numberWriter(\n fn: string,\n locale: unknown = 'en-US',\n): NumberWriter {\n if (typeof locale !== 'string') {\n throw invalidLocale(fn, locale)\n }\n\n if (\n /^en(?:-(?:[a-z]{2}|\\d{3}))?$/i.test(locale) ||\n typeof Intl === 'undefined'\n ) {\n return englishNumber\n }\n\n let writer = writers.get(locale)\n if (!writer) {\n writer = intlNumber(fn, locale)\n if (writer !== englishNumber) {\n if (writers.size >= MAX_WRITERS) {\n writers.clear()\n }\n writers.set(locale, writer)\n }\n }\n\n return writer\n}\n\n/**\n * The English plural form of a number written in digits, which every label\n * uses until labels are localized: `one` for 1, `other` for anything else,\n * including 0 and decimals (\"0.5 cups\").\n */\nexport function pluralForm(value: number): PluralForm {\n return Math.abs(value) === 1 ? 'one' : 'other'\n}\n\nfunction intlNumber(fn: string, locale: string): NumberWriter {\n let supported: readonly string[]\n try {\n supported = Intl.NumberFormat.supportedLocalesOf(locale)\n } catch {\n throw invalidLocale(fn, locale)\n }\n\n if (supported.length === 0) {\n return englishNumber\n }\n\n const formats: Intl.NumberFormat[] = []\n return (value, digits) => {\n let format = formats[digits]\n if (!format) {\n format = new Intl.NumberFormat(locale, {\n useGrouping: false,\n maximumFractionDigits: digits,\n })\n formats[digits] = format\n }\n\n return format.format(value)\n }\n}\n\nfunction englishNumber(value: number, digits: number): string {\n const magnitude = Math.abs(value)\n const units = Math.round(magnitude * POWERS[digits]!)\n const sign = value < 0 ? '-' : ''\n\n if (digits === 0 || units > Number.MAX_SAFE_INTEGER) {\n return sign + integerText(magnitude)\n }\n\n const text = String(units).padStart(digits + 1, '0')\n const whole = text.slice(0, -digits)\n const fraction = text.slice(-digits).replace(/0+$/, '')\n\n return sign + (fraction ? `${whole}.${fraction}` : whole)\n}\n\n/** Writes a non-negative integer in plain digits; `String` switches to exponent notation from 1e21. */\nfunction integerText(value: number): string {\n const text = String(value)\n const match = /^(\\d)(?:\\.(\\d+))?e\\+(\\d+)$/.exec(text)\n\n if (!match) {\n return text\n }\n\n const [, head, tail = '', exponent] = match\n return head + tail.padEnd(Number(exponent), '0')\n}\n\nfunction invalidLocale(fn: string, locale: unknown): RecipeBookError {\n return new RecipeBookError(\n 'invalid_argument',\n `${fn}: locale must be a BCP 47 language tag such as \"en-US\", received ${describeValue(locale)}.`,\n )\n}\n","import { describeValue, RecipeBookError } from '../errors'\nimport { type NumberWriter, numberWriter } from './number'\n\n/**\n * Options every `format*` function takes. Every default is a fixed value,\n * never read from the runtime, so server and client render the same text.\n */\nexport type FormatOptions = {\n /**\n * BCP 47 language tag. Default `'en-US'`. Labels and plurals are English in\n * 0.1; only numbers follow the locale, and they are never grouped. Numbers\n * in other languages come from the runtime's `Intl` data, so the server and\n * client need the same locale support to render the same text. A locale the\n * runtime doesn't support falls back to English.\n */\n locale?: string | undefined\n /** `'short'` (`tbsp`) or `'long'` (`tablespoons`). Default `'short'`. */\n unitDisplay?: 'short' | 'long' | undefined\n}\n\nexport type Settings = {\n number: NumberWriter\n unitDisplay: 'short' | 'long'\n}\n\nexport function readSettings(\n fn: string,\n options: FormatOptions | undefined,\n): Settings {\n return {\n number: numberWriter(fn, options?.locale),\n unitDisplay: option(fn, 'unitDisplay', options?.unitDisplay, [\n 'short',\n 'long',\n ]),\n }\n}\n\n/**\n * Reads an enumerated option; the first allowed value is the default.\n *\n * @throws {RecipeBookError} `invalid_argument` for any other value.\n */\nexport function option<const T extends string | boolean>(\n fn: string,\n name: string,\n value: unknown,\n allowed: readonly [T, ...T[]],\n): T {\n if (value === undefined) {\n return allowed[0]\n }\n\n if ((allowed as readonly unknown[]).includes(value)) {\n return value as T\n }\n\n const choices = allowed.map((choice) => JSON.stringify(choice))\n const last = choices.pop()\n throw new RecipeBookError(\n 'invalid_argument',\n `${fn}: ${name} must be ${choices.join(', ')}${choices.length > 1 ? ',' : ''} or ${last}, received ${describeValue(value)}.`,\n )\n}\n","import { describeValue, RecipeBookError } from '../errors'\nimport { amountEnds, checkQuantity } from '../quantity/amount'\nimport type { Quantity } from '../quantity/types'\nimport { lookupUnit, type UnitDefinition } from '../units/registry'\nimport { NBSP, type PluralForm, pluralForm, roundAboveZero } from './number'\nimport {\n type FormatOptions,\n option,\n readSettings,\n type Settings,\n} from './options'\n\n/**\n * Options for {@link formatQuantity}, {@link formatQuantityToParts},\n * `formatIngredient`, `formatServings`, and `formatYield`.\n */\nexport type FormatQuantityOptions = FormatOptions & {\n /**\n * Write US units and counts as fractions, such as `1 ½`. Default `true`.\n * `false` writes up to two decimals instead (`1.5 cups`, `0.33 cups`), or\n * more for an amount that would otherwise read as 0. Metric units always\n * use decimals.\n */\n fractions?: boolean | undefined\n /**\n * `'kitchen'` (default) rounds to amounts you can measure: US units to the\n * nearest ⅛ or ⅓, counts to the nearest ¼, metric units to sensible\n * decimals. `'none'` writes up to three decimals, or more for an amount\n * that would otherwise read as 0.\n */\n rounding?: 'kitchen' | 'none' | undefined\n}\n\n/**\n * One piece of a formatted quantity, in the style of `Intl` `formatToParts`.\n * Joining every `value` gives the {@link formatQuantity} text. Unlike `Intl`,\n * a range's dash is its own `rangeSeparator` part.\n */\nexport type QuantityPart = {\n /** May gain members in a minor release, so give an exhaustive `switch` a default case. */\n type: 'amount' | 'rangeSeparator' | 'unit' | 'literal'\n value: string\n}\n\n// Integer pairs rather than `1 / 8`: bundlers keep tables with arithmetic in every bundle.\ntype Step = readonly [numerator: number, denominator: number, glyph: string]\ntype Steps = readonly [Step, ...Step[]]\n\nconst EIGHTHS_AND_THIRDS: Steps = [\n [1, 8, '⅛'],\n [1, 4, '¼'],\n [1, 3, '⅓'],\n [3, 8, '⅜'],\n [1, 2, '½'],\n [5, 8, '⅝'],\n [2, 3, '⅔'],\n [3, 4, '¾'],\n [7, 8, '⅞'],\n [1, 1, ''],\n]\n\nconst QUARTERS: Steps = [\n [1, 4, '¼'],\n [1, 2, '½'],\n [3, 4, '¾'],\n [1, 1, ''],\n]\n\nexport type QuantitySettings = Settings & {\n fractions: boolean\n rounding: 'kitchen' | 'none'\n}\n\nexport type Shown = { text: string; plural: PluralForm }\n\n/**\n * Formats a quantity for display, with kitchen rounding by default.\n *\n * - US units (tsp, tbsp, cup, fl oz, pint, quart, gallon, oz, lb) round to the\n * nearest ⅛ or ⅓ and counts to the nearest ¼, written as fractions. An\n * amount below the smallest step is written as a decimal instead, never as 0.\n * - g, mL, cL, and dL use one decimal below 10 and none from 10; kg and L up\n * to two decimals; mg none. Small amounts gain digits rather than show 0.\n * - Ranges use an en dash (\"2–3 tbsp\"), and the amount and unit are joined by a\n * no-break space (U+00A0).\n * - The unit is singular for 1 and for a fraction below 1 (\"1 cup\", \"½ cup\"),\n * and plural otherwise, including decimals and ranges (\"0.5 cups\",\n * \"1 ½ cups\", \"½–1 cups\").\n *\n * For `en` alone or with a region, such as `'en-GB'`, output depends only on\n * the arguments: the locale defaults to `'en-US'`, and those numbers never go\n * through `Intl`. Other tags, including English ones with extensions such as\n * `'en-US-u-nu-arab'`, read the runtime's `Intl` data.\n *\n * @throws {RecipeBookError} `invalid_argument` for an invalid quantity or option, or a quantity with `max` set, as a `Servings` or `Yield` has (print those with `formatServings` and `formatYield`); `unknown_unit` for an unknown unit id.\n *\n * @example\n * formatQuantity({ amount: 1.5, unit: 'cup' }) // \"1 ½ cups\"\n * formatQuantity({ amount: { min: 2, max: 3 }, unit: 'tbsp' }) // \"2–3 tbsp\"\n * formatQuantity({ amount: 118.29, unit: 'ml' }) // \"118 mL\"\n * formatQuantity({ amount: 0.5, unit: 'tsp' }, { unitDisplay: 'long' }) // \"½ teaspoon\"\n */\nexport function formatQuantity(\n quantity: Quantity,\n options?: FormatQuantityOptions,\n): string {\n const fn = 'formatQuantity'\n return joinParts(\n quantityParts(fn, quantity, readQuantitySettings(fn, options)).parts,\n )\n}\n\n/**\n * Formats a quantity as parts, so a UI can style the amount and unit\n * separately without parsing the string.\n *\n * @throws {RecipeBookError} The same errors as {@link formatQuantity}, including `invalid_argument` for a quantity with `max` set.\n *\n * @example\n * formatQuantityToParts({ amount: { min: 2, max: 3 }, unit: 'tbsp' })\n * // [{ type: 'amount', value: '2' }, { type: 'rangeSeparator', value: '–' },\n * // { type: 'amount', value: '3' }, { type: 'literal', value: '\\u00A0' },\n * // { type: 'unit', value: 'tbsp' }]\n */\nexport function formatQuantityToParts(\n quantity: Quantity,\n options?: FormatQuantityOptions,\n): QuantityPart[] {\n const fn = 'formatQuantityToParts'\n return quantityParts(fn, quantity, readQuantitySettings(fn, options)).parts\n}\n\nexport function readQuantitySettings(\n fn: string,\n options: FormatQuantityOptions | undefined,\n): QuantitySettings {\n return {\n ...readSettings(fn, options),\n fractions: option(fn, 'fractions', options?.fractions, [true, false]),\n rounding: option(fn, 'rounding', options?.rounding, ['kitchen', 'none']),\n }\n}\n\nexport function quantityParts(\n fn: string,\n quantity: Quantity,\n settings: QuantitySettings,\n): { parts: QuantityPart[]; plural: PluralForm } {\n const amount = checkQuantity(fn, quantity)\n const unit =\n quantity.unit === undefined ? undefined : formatUnit(fn, quantity.unit)\n\n const [low, high = low] = amountEnds(amount).map((value) =>\n showAmount(value, settings, unit && unitSteps(unit, value)),\n ) as [Shown, Shown?]\n const isRange = high.text !== low.text\n const plural = isRange ? 'other' : low.plural\n\n const parts: QuantityPart[] = [{ type: 'amount', value: low.text }]\n if (isRange) {\n parts.push(\n { type: 'rangeSeparator', value: '–' },\n { type: 'amount', value: high.text },\n )\n }\n if (unit) {\n parts.push(\n { type: 'literal', value: NBSP },\n { type: 'unit', value: unit.labels[settings.unitDisplay][plural] },\n )\n }\n\n return { parts, plural }\n}\n\n/**\n * The registry entry for a quantity's unit. Unlike `getUnit`, the error\n * suggests no id: the alias index and edit distance behind that hint would\n * ship in every bundle that formats, though `parseRecipe` has already checked\n * the units of a parsed recipe.\n */\nfunction formatUnit(fn: string, id: unknown): UnitDefinition {\n const unit = lookupUnit(id)\n if (!unit) {\n throw new RecipeBookError(\n 'unknown_unit',\n `${fn}: unit must be a unit id such as \"g\", \"ml\", or \"cup\", received ${describeValue(id)}. findUnit converts author text to ids; parseQuantity also suggests a fix for a misspelling.`,\n )\n }\n return unit\n}\n\nexport function joinParts(parts: readonly QuantityPart[]): string {\n return parts.map((part) => part.value).join('')\n}\n\n/** One amount as text, snapped to `steps` or rounded to that many decimals; by default, as a bare count. Only callers with a unit pass `unitSteps`, so bundles that format counts alone leave out the unit tables. */\nexport function showAmount(\n value: number,\n settings: QuantitySettings,\n steps: Steps | number = QUARTERS,\n): Shown {\n const { rounding, fractions } = settings\n\n if (rounding === 'none') {\n return decimal(value, 3, settings)\n }\n\n if (typeof steps === 'number') {\n return decimal(value, steps, settings)\n }\n\n const [numerator, denominator] = steps[0]\n if (value < (numerator / denominator) * (1 - 1e-9)) {\n return decimal(value, 1, settings)\n }\n\n const [whole, part, glyph] = snap(value, steps)\n if (!fractions) {\n return decimal(whole + part, 2, settings)\n }\n\n const wholeText = settings.number(whole, 0)\n const text =\n glyph === ''\n ? wholeText\n : whole === 0\n ? glyph\n : `${wholeText}${NBSP}${glyph}`\n\n return { text, plural: whole + part <= 1 ? 'one' : 'other' }\n}\n\n/** The steps, or decimals, {@link showAmount} rounds an amount in `unit` to. */\nfunction unitSteps(unit: UnitDefinition, value: number): Steps | number {\n if (unit.dimension === 'count') {\n return QUARTERS\n }\n if (unit.systems.includes('us')) {\n return EIGHTHS_AND_THIRDS\n }\n\n switch (unit.id) {\n case 'mg':\n return 0\n case 'kg':\n case 'l':\n return 2\n default:\n return value < 10 ? 1 : 0\n }\n}\n\n/**\n * The nearest step to `value`'s fractional part; ties go to the larger step.\n * Thirds are inexact, so distances within 1e-9 count as ties.\n */\nfunction snap(\n value: number,\n steps: readonly Step[],\n): [whole: number, part: number, glyph: string] {\n const floor = Math.floor(value)\n const part = value - floor\n let nearest = 0\n let nearestGlyph = ''\n\n for (const [numerator, denominator, glyph] of steps) {\n const step = numerator / denominator\n if (Math.abs(part - step) <= Math.abs(part - nearest) + 1e-9) {\n nearest = step\n nearestGlyph = glyph\n }\n }\n\n return nearest === 1 ? [floor + 1, 0, ''] : [floor, nearest, nearestGlyph]\n}\n\nfunction decimal(\n value: number,\n digits: number,\n settings: QuantitySettings,\n): Shown {\n const [rounded, used] = roundAboveZero(value, digits)\n return { text: settings.number(rounded, used), plural: pluralForm(rounded) }\n}\n","import { describeValue, RecipeBookError } from '../errors'\nimport type { Quantity } from '../quantity/types'\nimport type { Ingredient } from '../recipe/types'\nimport { NBSP } from './number'\nimport {\n type FormatQuantityOptions,\n joinParts,\n quantityParts,\n readQuantitySettings,\n} from './quantity'\n\n/** An ingredient line as text, in pieces for styling and as one `text` line. */\nexport type FormattedIngredient = {\n /** The formatted quantity, as from `formatQuantity`. Absent for an unquantified line. */\n quantity?: string | undefined\n /** The name, or the ingredient's `plural` when a bare count takes the plural: \"2 eggs\", \"1–2 eggs\". */\n name: string\n /** The ingredient's note, such as \"sifted\". Absent when it has none. */\n note?: string | undefined\n /**\n * The whole line: `'1 ½ cups flour, sifted'`, `'2 eggs'`, `'salt, to taste'`.\n * It never says \"optional\"; mark optional ingredients in the UI.\n */\n text: string\n}\n\n/**\n * Formats an ingredient line. Accepts a resolved ingredient, or any\n * `{ ingredient, quantity? }`; without `quantity`, the ingredient's own\n * quantity is used.\n *\n * Takes the same options and rounding as `formatQuantity`. A bare count that\n * takes the plural, such as `2`, `1–2`, or `0.1`, uses the ingredient's\n * `plural`, or `name` when it has none. The name follows a no-break space\n * (U+00A0) after any bare count, `1 egg` included, and a regular space after\n * a unit.\n *\n * @throws {RecipeBookError} `invalid_argument` when `item` is not `{ ingredient, quantity? }` or the ingredient's `plural` or `note` is not a string; otherwise the same errors as `formatQuantity`, including `invalid_argument` for a quantity with `max` set.\n *\n * @example\n * formatIngredient(resolved).text // \"250 g all-purpose flour\"\n * formatIngredient({ ingredient: eggs, quantity: { amount: 2 } }).text // \"2 eggs\"\n * formatIngredient({ ingredient: salt }) // { name: 'salt', note: 'to taste', text: 'salt, to taste' }\n */\nexport function formatIngredient(\n item: { ingredient: Ingredient; quantity?: Quantity | undefined },\n options?: FormatQuantityOptions,\n): FormattedIngredient {\n const fn = 'formatIngredient'\n const ingredient = item?.ingredient\n\n if (typeof ingredient?.name !== 'string') {\n throw new RecipeBookError(\n 'invalid_argument',\n `${fn}: expected { ingredient, quantity? }, such as a resolved ingredient, received ${describeValue(item)}.`,\n )\n }\n for (const key of ['plural', 'note'] as const) {\n const value: unknown = ingredient[key]\n if (value !== undefined && typeof value !== 'string') {\n throw new RecipeBookError(\n 'invalid_argument',\n `${fn}: ingredient.${key} must be a string, received ${describeValue(value)}.`,\n )\n }\n }\n\n const settings = readQuantitySettings(fn, options)\n const quantity = item.quantity ?? ingredient.quantity\n const { note } = ingredient\n const noteText = note ? `, ${note}` : ''\n\n if (!quantity) {\n const { name } = ingredient\n return { name, ...(note && { note }), text: name + noteText }\n }\n\n const { parts, plural } = quantityParts(fn, quantity, settings)\n const quantityText = joinParts(parts)\n const isCount = quantity.unit === undefined\n const name =\n isCount && plural === 'other'\n ? (ingredient.plural ?? ingredient.name)\n : ingredient.name\n\n return {\n quantity: quantityText,\n name,\n ...(note && { note }),\n text: `${quantityText}${isCount ? NBSP : ' '}${name}${noteText}`,\n }\n}\n","import { describeValue, RecipeBookError } from '../errors'\nimport { isPositive } from '../quantity/amount'\nimport type { Servings, Yield } from '../recipe/types'\nimport { NBSP } from './number'\nimport {\n type FormatQuantityOptions,\n type QuantitySettings,\n readQuantitySettings,\n type Shown,\n showAmount,\n} from './quantity'\n\n/**\n * Formats a number of servings as only the number or range: \"4\", \"4–6\",\n * \"2 ½\". The UI adds the word, as in \"Serves 4–6\" or \"4–6 servings\".\n *\n * Numbers format as `formatQuantity` formats a bare count. It takes\n * `formatQuantity`'s options; `unitDisplay` has no effect.\n *\n * Scale with `resolveRecipe`, and print with `formatServings` and `formatYield`, not `formatQuantity`.\n *\n * @throws {RecipeBookError} `invalid_argument` for a value that isn't `{ amount, max? }` with `max` above `amount`, or for an invalid option.\n *\n * @example\n * formatServings({ amount: 4 }) // \"4\"\n * formatServings({ amount: 4, max: 6 }) // \"4–6\"\n * formatServings({ amount: 2.5 }) // \"2 ½\": 5 servings at scale 0.5\n */\nexport function formatServings(\n servings: Servings,\n options?: FormatQuantityOptions,\n): string {\n const fn = 'formatServings'\n return showRange(\n fn,\n servings,\n 'servings such as { amount: 4, max: 6 }',\n readQuantitySettings(fn, options),\n ).text\n}\n\n/**\n * Formats what a batch makes: the number or range, a no-break space\n * (U+00A0), then the yield's word, as in \"24 cookies\", \"2–3 loaves\", or\n * \"1 loaf\".\n *\n * Numbers format as `formatQuantity` formats a bare count. The word is `unit`\n * for 1 and for a fraction below 1 (\"1 loaf\", \"½ loaf\"), and `plural`\n * otherwise, including decimals and ranges (\"1 ½ loaves\", \"1–2 loaves\"). A\n * yield read from text, such as `'2 loaves'`, has no `plural`, so its unit\n * prints as written. The word is the author's and is never translated. It\n * takes `formatQuantity`'s options; `unitDisplay` has no effect.\n *\n * Scale with `resolveRecipe`, and print with `formatServings` and `formatYield`, not `formatQuantity`.\n *\n * @throws {RecipeBookError} `invalid_argument` for a value that isn't `{ amount, max?, unit, plural? }` with `max` above `amount` and string words, or for an invalid option.\n *\n * @example\n * formatYield({ amount: 24, unit: 'cookie', plural: 'cookies' }) // \"24 cookies\"\n * formatYield({ amount: 1, unit: 'loaf', plural: 'loaves' }) // \"1 loaf\"\n * formatYield({ amount: 2, max: 3, unit: 'loaf', plural: 'loaves' }) // \"2–3 loaves\"\n * formatYield({ amount: 1.5, unit: 'loaf', plural: 'loaves' }) // \"1 ½ loaves\": 3 loaves at scale 0.5\n * formatYield({ amount: 2, unit: 'loaves' }) // \"2 loaves\"\n */\nexport function formatYield(\n yield_: Yield,\n options?: FormatQuantityOptions,\n): string {\n const fn = 'formatYield'\n const { text, plural } = showRange(\n fn,\n yield_,\n 'a yield such as { amount: 24, unit: \"cookie\" }',\n readQuantitySettings(fn, options),\n )\n\n if (typeof yield_.unit !== 'string') {\n throw new RecipeBookError(\n 'invalid_argument',\n `${fn}: unit must be a string such as \"cookie\", received ${describeValue(yield_.unit)}.`,\n )\n }\n if (yield_.plural !== undefined && typeof yield_.plural !== 'string') {\n throw new RecipeBookError(\n 'invalid_argument',\n `${fn}: plural must be a string, received ${describeValue(yield_.plural)}.`,\n )\n }\n\n return `${text}${NBSP}${plural === 'other' ? (yield_.plural ?? yield_.unit) : yield_.unit}`\n}\n\n/** A servings or yield amount, or its range, as `formatQuantity` writes a bare count. */\nfunction showRange(\n fn: string,\n value: { amount?: unknown; max?: unknown },\n expected: string,\n settings: QuantitySettings,\n): Shown {\n if (typeof value !== 'object' || value === null) {\n throw new RecipeBookError(\n 'invalid_argument',\n `${fn}: expected ${expected}, received ${describeValue(value)}.`,\n )\n }\n\n const { amount, max } = value\n if (!isPositive(amount)) {\n throw new RecipeBookError(\n 'invalid_argument',\n `${fn}: amount must be a finite number greater than 0, received ${describeValue(amount)}.`,\n )\n }\n if (max !== undefined && !(isPositive(max) && max > amount)) {\n throw new RecipeBookError(\n 'invalid_argument',\n `${fn}: max must be a finite number greater than amount (${amount}), received ${describeValue(max)}. Leave max out for a single amount.`,\n )\n }\n\n const low = showAmount(amount, settings)\n const high = max === undefined ? low : showAmount(max, settings)\n return high.text === low.text\n ? low\n : { text: `${low.text}–${high.text}`, plural: 'other' }\n}\n"]}
|