@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.
Files changed (60) hide show
  1. package/CHANGELOG.md +138 -0
  2. package/README.md +1 -1
  3. package/dist/{chunk-VWVIBCTG.cjs → chunk-ISRDJR2O.cjs} +227 -179
  4. package/dist/chunk-ISRDJR2O.cjs.map +1 -0
  5. package/dist/errors.js +29 -1
  6. package/dist/errors.js.map +1 -1
  7. package/dist/format/duration.js.map +1 -1
  8. package/dist/format/ingredient.js.map +1 -1
  9. package/dist/format/number.js +1 -1
  10. package/dist/format/number.js.map +1 -1
  11. package/dist/format/options.js.map +1 -1
  12. package/dist/format/quantity.js.map +1 -1
  13. package/dist/format/servings.js.map +1 -1
  14. package/dist/format/temperature.js.map +1 -1
  15. package/dist/index.cjs +87 -74
  16. package/dist/index.cjs.map +1 -1
  17. package/dist/index.d.cts +71 -28
  18. package/dist/index.d.ts +71 -28
  19. package/dist/index.js +6 -1
  20. package/dist/index.js.map +1 -1
  21. package/dist/ingredient/parse.js +27 -22
  22. package/dist/ingredient/parse.js.map +1 -1
  23. package/dist/issues.js.map +1 -1
  24. package/dist/quantity/amount.js +11 -0
  25. package/dist/quantity/amount.js.map +1 -1
  26. package/dist/quantity/parse.js +58 -81
  27. package/dist/quantity/parse.js.map +1 -1
  28. package/dist/quantity/scale.js +5 -2
  29. package/dist/quantity/scale.js.map +1 -1
  30. package/dist/recipe/ids.js.map +1 -1
  31. package/dist/recipe/parse.js +80 -60
  32. package/dist/recipe/parse.js.map +1 -1
  33. package/dist/recipe/schema.js +8 -6
  34. package/dist/recipe/schema.js.map +1 -1
  35. package/dist/resolve.js +6 -1
  36. package/dist/resolve.js.map +1 -1
  37. package/dist/schema-org/find.js +46 -13
  38. package/dist/schema-org/find.js.map +1 -1
  39. package/dist/schema-org/from-json-ld.js +134 -71
  40. package/dist/schema-org/from-json-ld.js.map +1 -1
  41. package/dist/schema-org/text.js.map +1 -1
  42. package/dist/schema-org/to-json-ld.js +12 -15
  43. package/dist/schema-org/to-json-ld.js.map +1 -1
  44. package/dist/schema-org.cjs +239 -147
  45. package/dist/schema-org.cjs.map +1 -1
  46. package/dist/schema-org.d.cts +35 -21
  47. package/dist/schema-org.d.ts +35 -21
  48. package/dist/steps/segment.js.map +1 -1
  49. package/dist/steps/temperature.js +13 -13
  50. package/dist/steps/temperature.js.map +1 -1
  51. package/dist/{types-DSMf45H5.d.cts → types-CKIoWsz8.d.cts} +25 -7
  52. package/dist/{types-DSMf45H5.d.ts → types-CKIoWsz8.d.ts} +25 -7
  53. package/dist/units/convert.js +16 -8
  54. package/dist/units/convert.js.map +1 -1
  55. package/dist/units/temperature.js +7 -1
  56. package/dist/units/temperature.js.map +1 -1
  57. package/dist/validation.js +1 -1
  58. package/dist/validation.js.map +1 -1
  59. package/package.json +1 -1
  60. package/dist/chunk-VWVIBCTG.cjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/schema-org/find.ts","../src/schema-org/nutrients.ts","../src/schema-org/text.ts","../src/schema-org/from-json-ld.ts","../src/schema-org/to-json-ld.ts"],"names":["asRecord","RecipeBookError","describeValue","text","isRecord","hasOwn","toResult","issue","warning","quote","parseRecipe","parseIngredientLine","disallowedScheme","image","matchAmount","amount","parseIsoDuration","key","resolveRecipe","formatYield","formatServings","formatIngredient","isNative","formatQuantity","multiply","round","NUTRIENT_UNITS"],"mappings":"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","file":"schema-org.cjs","sourcesContent":["import { describeValue, RecipeBookError } from '../errors'\nimport { isRecord, type Path } from '../issues'\nimport { asRecord } from '../validation'\n\n/** A JSON-LD node, as passed in, and its path in the input. */\nexport type Located = { node: Record<string, unknown>; path: Path }\n\n/**\n * The longest path read in JSON-LD. Real markup nests about ten levels, and\n * the bound keeps a hostile page from overflowing the stack.\n */\nexport const MAX_DEPTH = 32\n\n/**\n * Finds the Recipe nodes in parsed JSON-LD documents, in order, through arrays,\n * `@graph`, and one level of `mainEntity`. It indexes by `@id` each Recipe, and\n * each node at the top level of the JSON-LD, or reached from there through\n * arrays and `@graph`, so references can be followed. An `@id` names its first\n * node, and a Recipe with the `@id` of an earlier Recipe is left out, unless\n * the earlier one holds nothing but keywords such as `@type`: then it takes\n * that one's place in `recipes`, and in `ids` when that one was the first node\n * with its `@id`. An empty `@id` is no `@id`.\n */\nexport function locate(documents: readonly unknown[]): {\n recipes: Located[]\n ids: Map<string, Located>\n} {\n const recipes: Located[] = []\n const ids = new Map<string, Located>()\n // A stub Recipe, or `true` once the `@id`'s Recipe holds content, so a\n // duplicate never rescans the first one's keys.\n const recipeIds = new Map<unknown, Located | true>()\n\n const visit = (value: unknown, path: Path, mainEntity = false): void => {\n if (path.length > MAX_DEPTH) {\n return\n }\n\n if (Array.isArray(value)) {\n value.forEach((entry: unknown, i) =>\n visit(entry, [...path, i], mainEntity),\n )\n return\n }\n\n const fields = asRecord(value)\n if (!fields) {\n return\n }\n\n const type = fields['@type']\n const isRecipe = [type]\n .flat()\n .some(\n (name) => typeof name === 'string' && /(?:^|[/:#])Recipe$/.test(name),\n )\n\n if (mainEntity && !isRecipe) {\n return\n }\n\n const located = { node: value as Record<string, unknown>, path }\n const id = fields['@id'] || undefined\n if (typeof id === 'string' && !ids.has(id)) {\n ids.set(id, located)\n }\n\n if (isRecipe) {\n const earlier = recipeIds.get(id)\n if (!earlier) {\n recipes.push(located)\n if (typeof id === 'string') {\n recipeIds.set(id, hasContent(fields) || located)\n }\n } else if (earlier !== true && hasContent(fields)) {\n // `recipes` holds this same object, and so does `ids` when the stub was\n // the first node with its `@id`, so a reference to the recipe still\n // finds the recipe itself.\n Object.assign(earlier, located)\n recipeIds.set(id, true)\n }\n } else {\n visit(fields['@graph'], [...path, '@graph'])\n visit(fields.mainEntity, [...path, 'mainEntity'], true)\n }\n }\n\n for (const document of documents) {\n visit(document, [])\n }\n return { recipes, ids }\n}\n\nfunction hasContent(node: Record<string, unknown>): boolean {\n return Object.keys(node).some((key) => key[0] !== '@')\n}\n\n/**\n * Finds the schema.org Recipe nodes in a page's\n * `<script type=\"application/ld+json\">` tags, without a DOM. Pass one to\n * `fromJsonLd`.\n *\n * Reads arrays and `@graph`, as Yoast and WP Recipe Maker write them, and a\n * Recipe in a node's `mainEntity`, and matches a node whose `@type` is or\n * includes `\"Recipe\"`. A tag whose JSON doesn't parse is retried with the raw\n * line breaks and tabs inside its strings escaped, as real pages have them,\n * and skipped if it still doesn't. A tag inside an HTML comment is skipped,\n * and a `<!--` in an attribute value or in a `style` or `textarea` element is\n * text, as in a browser. A quote starts an attribute value only right after\n * `=`, so a stray one, as in `content=\"a 9\" pan\"`, doesn't hide later tags. A\n * Recipe node with the `@id` of an earlier one is returned once, where the\n * first appears. When the first holds only keywords, such as a `mainEntity`\n * of `{ \"@type\": \"Recipe\", \"@id\": \"#recipe\" }`, the later node is returned in\n * its place. An empty `@id` is no `@id`, so it merges nothing.\n *\n * In each Recipe node returned, an image that is an `@id` reference to a node\n * at the top level of the JSON-LD, or reached from there through arrays and\n * `@graph`, holds that node instead of the reference, an object that holds only\n * that `@id`. That applies to the recipe's `image` and each step's `image` in\n * `recipeInstructions`, and lets `fromJsonLd` read them. A reference to a node\n * in any other field, such as an `Organization`'s `logo` or an `ImageObject` in\n * a `WebPage`'s `mainEntity`, isn't followed. Other references, such as\n * `author` and `mainEntityOfPage`, and references inside the node an image\n * holds, stay as the page wrote them.\n *\n * @param html - The page's HTML, such as `await response.text()`.\n * @returns Every Recipe node, in document order, or `[]` when there are none.\n * @throws {RecipeBookError} `invalid_argument` when `html` isn't a string.\n *\n * @example\n * const [node] = findRecipeJsonLd(await response.text())\n * const result = fromJsonLd(node)\n */\nexport function findRecipeJsonLd(html: string): Record<string, unknown>[] {\n if (typeof html !== 'string') {\n throw new RecipeBookError(\n 'invalid_argument',\n `findRecipeJsonLd: html must be a string, such as await response.text(), received ${describeValue(html)}.`,\n )\n }\n\n const documents: unknown[] = []\n\n // At each `<`, in this order: a script, style, or textarea element with its\n // content; a comment, where `<!-->` and `<!--->` close at once; or any other\n // tag with its quoted attribute values. What one of these holds, such as a\n // `<!--` in an attribute value, starts nothing, as in a browser. A quote\n // starts a value only right after `=`, so a stray one, as in\n // `content=\"a 9\" pan\"`, is text. The element's attributes are read once, in\n // a lookahead, then matched by backreference, so a tag with no `>` fails\n // without retrying other splits of them, which would be exponential.\n for (const [, element, attributes = '', body = ''] of html.matchAll(\n /<(script|style|textarea)(?=[\\s/>])(?=((?:=\\s*(?:\"[^\"]*\"|'[^']*')|[^<>])*))\\2>([\\s\\S]*?)(?:<\\/\\1\\s*>|$)|<!--(?:-?>|[\\s\\S]*?(?:--!?>|$))|<\\/?[a-z][^\\s/>]*(?:=\\s*(?:\"[^\"]*\"|'[^']*')|[^<>])*/gi,\n )) {\n if (\n element?.toLowerCase() === 'script' &&\n /[\\s/]type\\s*=\\s*[\"']?application\\/ld\\+json\\b/i.test(attributes)\n ) {\n const text = body\n .replace(/^\\s*(?:\\/\\/\\s*)?(?:<!--|<!\\[CDATA\\[)/, '')\n .replace(/(?:\\/\\/\\s*)?(?:-->|\\]\\]>)\\s*$/, '')\n const json =\n parseJson(text) ??\n parseJson(\n text.replace(/\"(?:[^\"\\\\]|\\\\[\\s\\S]?)*(?:\"|$)/g, (string) =>\n string.replace(/[\\n\\r\\t]/g, (c) => JSON.stringify(c).slice(1, -1)),\n ),\n )\n\n documents.push(json)\n }\n }\n\n const { recipes, ids } = locate(documents)\n return recipes.map(({ node }) => withImages(node, ids))\n}\n\n/**\n * A copy of a Recipe node with each image that is a one-hop reference to\n * another node replaced by that node: the recipe's `image`, and each step's\n * `image` in `recipeInstructions`, through sections, `ItemList`s, and\n * `ListItem`s. The fields `fromJsonLd` doesn't read keep their references.\n */\nfunction withImages(\n node: Record<string, unknown>,\n ids: Map<string, Located>,\n): Record<string, unknown> {\n const follow = (value: unknown): unknown => {\n const id =\n isRecord(value) && Object.keys(value).length === 1 && value['@id']\n const target = typeof id === 'string' && ids.get(id)?.node\n return target && target !== node ? target : value\n }\n const images = (value: unknown): unknown =>\n Array.isArray(value) ? value.map(follow) : follow(value)\n const copy = (value: unknown, depth: number, keys: string[]): unknown => {\n if (depth > MAX_DEPTH) {\n return value\n }\n if (Array.isArray(value)) {\n return value.map((entry: unknown) => copy(entry, depth + 1, keys))\n }\n\n const fields = asRecord(value)\n if (!fields) {\n return value\n }\n\n const result = { ...fields }\n for (const key of keys) {\n if (fields[key] !== undefined) {\n result[key] =\n key === 'image'\n ? images(fields[key])\n : copy(fields[key], depth + 1, ['itemListElement', 'item', 'image'])\n }\n }\n return result\n }\n\n return copy(node, 0, ['image', 'recipeInstructions']) as typeof node\n}\n\nfunction parseJson(text: string): unknown {\n try {\n return JSON.parse(text)\n } catch {\n return undefined\n }\n}\n","import type { Nutrition } from '../recipe/types'\nimport type { SchemaOrgNutritionInformation } from './types'\n\n/** The schema.org `NutritionInformation` name for each `Nutrition` field. */\nexport const NUTRIENTS: Readonly<\n Record<keyof Nutrition, Exclude<keyof SchemaOrgNutritionInformation, '@type'>>\n> = {\n servingSize: 'servingSize',\n calories: 'calories',\n fat: 'fatContent',\n saturatedFat: 'saturatedFatContent',\n transFat: 'transFatContent',\n unsaturatedFat: 'unsaturatedFatContent',\n carbohydrates: 'carbohydrateContent',\n sugar: 'sugarContent',\n fiber: 'fiberContent',\n protein: 'proteinContent',\n sodium: 'sodiumContent',\n cholesterol: 'cholesterolContent',\n}\n","import { hasOwn } from '../issues'\n\nconst NAMED_ENTITIES: Readonly<Record<string, string>> = {\n amp: '&',\n lt: '<',\n gt: '>',\n quot: '\"',\n apos: \"'\",\n nbsp: ' ',\n ensp: ' ',\n emsp: ' ',\n thinsp: ' ',\n shy: '',\n zwj: '',\n zwnj: '',\n deg: '°',\n colon: ':',\n Tab: '\\t',\n NewLine: '\\n',\n euro: '€',\n pound: '£',\n yen: '¥',\n cent: '¢',\n half: '½',\n frac12: '½',\n frac14: '¼',\n frac34: '¾',\n frac13: '⅓',\n frac23: '⅔',\n frac15: '⅕',\n frac25: '⅖',\n frac35: '⅗',\n frac45: '⅘',\n frac16: '⅙',\n frac56: '⅚',\n frac18: '⅛',\n frac38: '⅜',\n frac58: '⅝',\n frac78: '⅞',\n frasl: '⁄',\n ndash: '–',\n mdash: '—',\n minus: '−',\n hellip: '…',\n lsquo: '‘',\n rsquo: '’',\n sbquo: '‚',\n ldquo: '“',\n rdquo: '”',\n bdquo: '„',\n laquo: '«',\n raquo: '»',\n times: '×',\n divide: '÷',\n middot: '·',\n bull: '•',\n micro: 'µ',\n sup1: '¹',\n sup2: '²',\n sup3: '³',\n ordm: 'º',\n ordf: 'ª',\n copy: '©',\n reg: '®',\n trade: '™',\n iexcl: '¡',\n iquest: '¿',\n szlig: 'ß',\n aelig: 'æ',\n AElig: 'Æ',\n oelig: 'œ',\n OElig: 'Œ',\n oslash: 'ø',\n Oslash: 'Ø',\n}\n\n// `&eacute;` and the like decode to the letter plus a combining mark, then NFC.\nconst MARKS: Readonly<Record<string, string>> = {\n grave: '\\u0300',\n acute: '\\u0301',\n circ: '\\u0302',\n tilde: '\\u0303',\n uml: '\\u0308',\n ring: '\\u030A',\n cedil: '\\u0327',\n}\n\n// A comment, a script or style element with its content, or a tag, with its\n// name captured if it's a block tag. As in a browser, a quote starts an\n// attribute value only right after `=`. A value can hold a `>`, and a `<`\n// that can't start a tag, as in `a < b`. A tag with no `>` is tried again at\n// each `<` in it, so the attributes end at any `<` that can start a tag, which\n// keeps each try short. They're read once, in a lookahead, then matched by\n// backreference, so a failed tag doesn't retry other splits of them, which\n// would be exponential. A literal, unlike `new RegExp`, lets bundlers drop it.\nconst MARKUP =\n /<!--[\\s\\S]*?(?:-->|$)|<(script|style)(?=[\\s/>])(?=((?:=\\s*(?:\"(?:[^\"<]|<(?![a-z/!?]))*\"|'(?:[^'<]|<(?![a-z/!?]))*')|[^<>])*))\\2>[\\s\\S]*?(?:<\\/\\1\\s*>|$)|<(?:(\\/?(?:br|p|li|div|h[1-6])\\b)|[/!?]?[a-z])(?=((?:=\\s*(?:\"(?:[^\"<]|<(?![a-z/!?]))*\"|'(?:[^'<]|<(?![a-z/!?]))*')|[^<>])*))\\4>/gi\n\n// Removing a tag can join the text around it into a new one, as in\n// `<scr<b></b>ipt>`, so stripping repeats. Real markup needs a pass or two;\n// the cap keeps hostile nesting linear.\nconst MAX_PASSES = 8\n\n/**\n * JSON-LD text with its tags removed, then its HTML entities decoded, on one\n * line with single spaces. An encoded tag, such as `&lt;b&gt;`, stays as text.\n */\nexport function cleanText(text: string): string {\n return cleanLines(text).join(' ')\n}\n\n/** {@link cleanText} for each line, split at line breaks and block tags. Empty lines are left out. */\nexport function cleanLines(text: string): string[] {\n return stripTags(text)\n .replace(\n /&(?:#(\\d{1,7})|#x([\\da-f]{1,6})|([a-z][a-z\\d]*));/gi,\n (entity, decimal?: string, hex?: string, name?: string) => {\n if (name === undefined) {\n const code = decimal === undefined ? parseInt(hex!, 16) : +decimal\n return code > 0 &&\n code <= 0x10ffff &&\n (code < 0xd800 || code > 0xdfff)\n ? String.fromCodePoint(code)\n : entity\n }\n\n if (hasOwn(NAMED_ENTITIES, name)) {\n return NAMED_ENTITIES[name]!\n }\n\n const accent = /^([aceinouyACEINOUY])([a-z]+)$/.exec(name)\n return accent && hasOwn(MARKS, accent[2]!)\n ? `${accent[1]}${MARKS[accent[2]!]}`.normalize('NFC')\n : entity\n },\n )\n .split(/[\\n\\r\\u2028\\u2029]/)\n .map((line) => line.replace(/\\s+/g, ' ').trim())\n .filter(Boolean)\n}\n\n/**\n * Removes comments, tags, and the content of `script` and `style`, and ends a\n * line at block tags. Strips again until nothing changes, then removes any `<`\n * that could still open a tag: one before a letter, `/`, `!`, or `?` with a\n * `>` after it, as in `<a <>`. A `<` with no `>` after it, as in `x<y`, stays.\n */\nfunction stripTags(text: string): string {\n let stripped = text\n\n for (let pass = 0; pass < MAX_PASSES; pass++) {\n const next = stripped.replace(\n MARKUP,\n (_, _element, _attributes, block?: string) => (block ? '\\n' : ''),\n )\n if (next === stripped) {\n break\n }\n stripped = next\n }\n\n const end = stripped.lastIndexOf('>') + 1\n return (\n stripped\n .slice(0, end)\n .replace(/<+([/!?a-z]?)/gi, (run, next: string) => next || run) +\n stripped.slice(end)\n )\n}\n","import {\n describeValue,\n quote,\n type RecipeIssue,\n type RecipeIssueCode,\n} from '../errors'\nimport { parseIngredientLine } from '../ingredient/parse'\nimport { issue, type Path, warning } from '../issues'\nimport { matchAmount } from '../quantity/parse'\nimport { parseIsoDuration } from '../recipe/duration'\nimport { parseRecipe } from '../recipe/parse'\nimport type { Nutrition, Recipe } from '../recipe/types'\nimport { disallowedScheme } from '../recipe/url'\nimport { asRecord, toResult } from '../validation'\nimport { type Located, locate, MAX_DEPTH } from './find'\nimport { NUTRIENTS } from './nutrients'\nimport { cleanLines, cleanText } from './text'\nimport type { FromJsonLdResult } from './types'\n\n/**\n * The node's fields that `fromJsonLd` reads or that core owns, so `extra`\n * leaves them out, in the order issues are reported.\n */\nconst READ_FIELDS: readonly string[] = [\n '@context',\n '@type',\n 'name',\n 'description',\n 'image',\n 'recipeYield',\n 'prepTime',\n 'cookTime',\n 'totalTime',\n 'recipeIngredient',\n 'recipeInstructions',\n 'tool',\n 'nutrition',\n]\n\nconst TIMES = [\n ['prep', 'prepTime'],\n ['cook', 'cookTime'],\n ['total', 'totalTime'],\n] as const\n\nconst SERVINGS_WORD =\n /^(?:servings?|portions?|(?:serving|portion)\\(s\\)|people|persons?)\\.?$/i\n\ntype Reader = {\n /** The Recipe node, as passed in. */\n recipe: Record<string, unknown>\n ids: Map<string, Located>\n warnings: RecipeIssue[]\n /** The JSON-LD path of each value in the recipe input, keyed by its path there. */\n sources: Map<string, Path>\n /** The recipe input paths of the values a failed parse drops. */\n droppable: Set<string>\n /** The image each node that an image references holds, and whether reading it warned. */\n images: Map<Located, [image: Image | undefined, warned: boolean]>\n /** Set when an image reaches a node whose warnings were given earlier. */\n repeated?: boolean\n}\n\ntype Image = { url: string; source: Path }\n\n/** A value read from `recipeYield`. */\ntype Batch = {\n source: Path\n /** The value as text, to name it in a message. */\n label: string\n /** The amount, or the low end of its range. */\n amount: number\n servings?: unknown\n /** Servings with a word, such as \"4 servings\", not a bare number. */\n worded?: boolean\n yield?: unknown\n /** The yield's amount is \"a\" or \"an\", as in \"a few\", not a number. */\n article?: boolean\n}\n\n/** A list item read from JSON-LD, and where its fields came from. */\ntype Item = {\n value: unknown\n source: Path\n fields?: [field: string, source: Path, droppable: boolean][]\n}\n\n/**\n * Reads a schema.org Recipe from JSON-LD, as recipe sites publish it for\n * search engines: a Recipe node, or an array, `@graph`, or `mainEntity` that\n * holds one, such as a node from `findRecipeJsonLd` or `JSON.parse` of a\n * script tag. Never throws for bad data; an error thrown by a getter or proxy\n * in the input passes through.\n *\n * Every string has its tags removed, then its HTML entities decoded, so an\n * encoded tag such as `&lt;b&gt;` stays as text. Ingredient lines are read\n * with `parseIngredientLine`. Issue paths point into the JSON-LD, such as\n * `recipeIngredient[3]`.\n *\n * Reading is forgiving. A value the recipe can't hold, such as a `data:`\n * image or nutrition of \"N/A\", is left out with a warning that keeps its usual\n * code and ends \"It is ignored.\" A second Recipe node, a second number of\n * servings, or a second yield is an `ignored_value` warning. The result fails\n * only when there is no Recipe node, the recipe's name is missing or isn't\n * text, or a problem remains that leaving a value out can't fix.\n *\n * @returns The recipe or the error, and `extra`: the node's fields the recipe\n * doesn't model, such as `author` and `keywords`, as they were. Pass `extra`\n * to `toJsonLd` to write them back. It is `{}` when no Recipe node is found.\n *\n * @example\n * const result = fromJsonLd(node)\n * if (!result.success) {\n * console.error(result.error.message)\n * // Recipe has 1 problem:\n * // ✖ name Add a name for the recipe.\n * // See https://recipe-book.siraj.page/errors/invalid_recipe\n * return\n * }\n * result.data.ingredients[0].items[0] // { id: 'flour', name: 'flour', quantity: { amount: 2, unit: 'cup' }, … }\n * result.extra.author // { '@type': 'Person', name: 'Ada' }\n */\nexport function fromJsonLd(input: unknown): FromJsonLdResult {\n const { recipes, ids } = locate([input])\n const [found] = recipes\n\n if (!found) {\n return {\n ...toResult<Recipe>('invalid_recipe', undefined, [\n issue(\n 'error',\n 'invalid_type',\n [],\n `Expected a schema.org Recipe, or an array, @graph, or mainEntity that holds one, received ${describeValue(input)}.`,\n ),\n ]),\n extra: {},\n }\n }\n\n const node = asRecord(found.node)!\n const reader: Reader = {\n recipe: found.node,\n ids,\n warnings: [],\n sources: new Map(),\n droppable: new Set(),\n images: new Map(),\n }\n const name = text(node.name)\n\n if (recipes.length > 1) {\n warning(\n reader.warnings,\n 'ignored_value',\n [],\n `Found ${recipes.length} recipes. Only the first${typeof name === 'string' ? `, ${quote(name)},` : ''} is read.`,\n )\n }\n\n const model = readRecipe(reader, node, found.path)\n const parse = () => parseRecipe(model, { parseIngredientLine })\n let result = parse()\n const dropped: RecipeIssue[] = []\n\n if (!result.success) {\n for (const error of result.error.issues) {\n const target =\n error.severity === 'error' ? droppableAt(reader, error.path) : undefined\n\n if (target) {\n remove(model, target)\n dropped.push({\n ...error,\n severity: 'warning',\n message: `${error.message} It is ignored.`,\n })\n }\n }\n if (dropped.length > 0) {\n result = parse()\n }\n }\n\n // An object's unknown fields sort after its other issues, as in parseRecipe.\n const order = ({ code, path }: RecipeIssue): number[] => [\n READ_FIELDS.indexOf(String(path[found.path.length])),\n ...path\n .slice(found.path.length + 1)\n .filter((key) => typeof key === 'number'),\n ...(code === 'unknown_field' ? [Infinity] : []),\n ]\n const issues = [\n ...reader.warnings,\n ...[\n ...dropped,\n ...(result.success ? result.warnings : result.error.issues),\n ].map((issue) => ({ ...issue, path: sourceOf(reader, issue.path) })),\n ].sort((a, b) => compareOrder(order(a), order(b)))\n\n return {\n ...toResult(\n 'invalid_recipe',\n result.success ? result.data : undefined,\n issues,\n typeof name === 'string' ? quote(name) : undefined,\n ),\n extra: Object.fromEntries(\n Object.entries(node).filter(([key]) => !READ_FIELDS.includes(key)),\n ),\n }\n}\n\n/** Builds `parseRecipe` input from a Recipe node, and links each value to its JSON-LD path. */\nfunction readRecipe(\n reader: Reader,\n node: Record<string, unknown>,\n base: Path,\n): Record<string, unknown> {\n const at = (...path: Path): Path => [...base, ...path]\n const model: Record<string, unknown> = {\n name: text(node.name),\n description: text(node.description),\n }\n link(reader, [], base)\n link(reader, ['name'], at('name'))\n link(reader, ['description'], at('description'), true)\n\n const image = readImage(reader, node.image, at('image'))\n if (image) {\n model.image = image.url\n link(reader, ['image'], image.source, true)\n }\n\n readYield(reader, model, node.recipeYield, at('recipeYield'))\n\n const times: Record<string, number> = {}\n for (const [key, field] of TIMES) {\n const minutes = readTime(reader, node[field], at(field))\n if (minutes !== undefined) {\n times[key] = minutes\n }\n }\n model.times = times\n\n model.ingredients = readList(\n reader,\n 'ingredients',\n node.recipeIngredient,\n at('recipeIngredient'),\n readLine,\n 'an ingredient line such as \"2 cups flour\"',\n )\n model.steps = readList(\n reader,\n 'steps',\n node.recipeInstructions,\n at('recipeInstructions'),\n readStep,\n 'a step such as \"Whisk the eggs.\" or a HowToStep',\n )\n model.equipment = readTools(reader, node.tool, at('tool'))\n model.nutrition = readNutrition(reader, node.nutrition, at('nutrition'))\n return model\n}\n\nfunction readImage(\n reader: Reader,\n value: unknown,\n source: Path,\n): Image | undefined {\n if (isAbsent(value)) {\n return undefined\n }\n\n const warnings = reader.warnings.length\n reader.repeated = false\n const image = findImage(reader, value, source)\n if (!image && !reader.repeated && reader.warnings.length === warnings) {\n ignore(\n reader,\n 'invalid_type',\n source,\n `Expected an image URL, an ImageObject with a url, or a list of them, received ${describeValue(value)}.`,\n )\n }\n return image\n}\n\n/**\n * The first URL a recipe can hold in an image, a list of them, an\n * ImageObject, or a reference to one. Each URL before it with another scheme,\n * such as `data:`, and a reference to the recipe itself get a warning. Follows\n * one reference, so references that cycle end, and reads each node it reaches\n * once, so many references to one node cost one read and warn once.\n */\nfunction findImage(\n reader: Reader,\n value: unknown,\n source: Path,\n referenced = false,\n): Image | undefined {\n if (typeof value === 'string') {\n const url = cleanText(value)\n const scheme = disallowedScheme(url)\n if (scheme) {\n ignore(\n reader,\n 'invalid_url',\n source,\n `Expected an http or https URL, or a relative one, received ${quote(`${scheme}…`)}.`,\n )\n return undefined\n }\n return url ? { url, source } : undefined\n }\n\n if (source.length > MAX_DEPTH) {\n return undefined\n }\n\n if (Array.isArray(value)) {\n for (const [i, entry] of value.entries()) {\n const image = findImage(reader, entry, [...source, i], referenced)\n if (image) {\n return image\n }\n }\n return undefined\n }\n\n const record = asRecord(value)\n if (!record) {\n return undefined\n }\n\n const id = record['@id']\n const target =\n typeof id === 'string' && !referenced ? reader.ids.get(id) : undefined\n const image =\n findImage(reader, record.url, [...source, 'url'], referenced) ??\n findImage(reader, record.contentUrl, [...source, 'contentUrl'], referenced)\n\n if (image || !target) {\n return image\n }\n if (target.node === reader.recipe) {\n ignore(\n reader,\n 'invalid_type',\n source,\n 'Expected an image URL, an ImageObject with a url, or a list of them, received a reference to the recipe itself.',\n )\n return undefined\n }\n\n let read = reader.images.get(target)\n if (!read) {\n const warnings = reader.warnings.length\n const found = findImage(reader, target.node, target.path, true)\n read = [found, reader.warnings.length > warnings]\n reader.images.set(target, read)\n } else if (read[1]) {\n reader.repeated = true\n }\n return read[0]\n}\n\n/**\n * Reads servings and the yield from `recipeYield`'s values, and from the\n * comma-separated values in a string, as in \"4 servings, 24 cookies\". A bare\n * number equal to the yield's amount, as in WP Recipe Maker's `[\"28\", \"28-32\n * cookies\"]`, is the yield's count, not servings. The yield is the first one\n * with an amount, so \"One 9-inch pie, 8 slices\" yields 8 slices, but one whose\n * amount is a number comes before one whose amount is \"a\" or \"an\", so\n * `[\"a few\", \"24 cookies\"]` yields 24 cookies.\n */\nfunction readYield(\n reader: Reader,\n model: Record<string, unknown>,\n value: unknown,\n source: Path,\n): void {\n const entries: [unknown, Path][] = Array.isArray(value)\n ? value.map((entry: unknown, i) => [entry, [...source, i]])\n : [[value, source]]\n const batches = entries\n .flatMap(([entry, entrySource]) =>\n (typeof entry === 'string' ? entry.split(/,\\s+/) : [entry]).map((part) =>\n readBatch(reader, part, entrySource),\n ),\n )\n .filter((batch) => batch !== undefined)\n const yields = batches.filter((batch) => batch.yield !== undefined)\n const servings = batches.filter((batch) => batch.servings !== undefined)\n const kept = yields.find((batch) => !batch.article) ?? yields[0]\n const keptServings =\n servings.find((batch) => batch.worded) ??\n servings.find((batch) => batch.amount !== kept?.amount)\n\n for (const batch of servings) {\n if (\n keptServings &&\n batch.amount !== keptServings.amount &&\n (batch.worded || batch.amount !== kept?.amount)\n ) {\n warning(\n reader.warnings,\n 'ignored_value',\n batch.source,\n `Only one number of servings is read, ${quote(keptServings.label)}, so this one is ignored.`,\n )\n }\n }\n\n for (const batch of yields) {\n if (batch !== kept) {\n warning(\n reader.warnings,\n 'ignored_value',\n batch.source,\n `Only one yield is read, ${quote(kept!.label)}, so this one is ignored.`,\n )\n }\n }\n\n if (keptServings) {\n model.servings = keptServings.servings\n link(reader, ['servings'], keptServings.source, true)\n }\n if (kept) {\n model.yield = kept.yield\n link(reader, ['yield'], kept.source, true)\n }\n}\n\nfunction readBatch(\n reader: Reader,\n value: unknown,\n source: Path,\n): Batch | undefined {\n if (typeof value === 'number') {\n return { source, label: String(value), amount: value, servings: value }\n }\n\n if (typeof value === 'string') {\n const label = cleanText(value)\n\n if (!label) {\n return undefined\n }\n\n const text = label.replace(\n /^(?:(?:serves|servings?|yields?|makes)\\s*:?\\s*)?(?:about\\s+)?/i,\n '',\n )\n const match = matchAmount(text)\n\n if (!match || 'code' in match) {\n ignore(\n reader,\n match?.code ?? 'invalid_quantity',\n source,\n match?.message ??\n `Expected a batch such as \"24 cookies\" or \"3–4 loaves\", received ${describeValue(label)}.`,\n )\n return undefined\n }\n\n const amount =\n typeof match.amount === 'number' ? match.amount : match.amount.min\n const rest = match.rest.trim()\n\n return !rest || SERVINGS_WORD.test(rest)\n ? { source, label, amount, servings: match.amountText, worded: !!rest }\n : { source, label, amount, yield: text, article: /^an?\\s/i.test(text) }\n }\n\n const record = asRecord(value)\n const amount = toNumber(record?.value ?? record?.minValue)\n\n if (record && amount !== undefined) {\n const max = toNumber(record.maxValue)\n const unit =\n typeof record.unitText === 'string' ? cleanText(record.unitText) : ''\n const range = {\n amount,\n ...(max !== undefined && max !== amount && { max }),\n }\n const label = `${amount}${range.max ? `–${range.max}` : ''}${unit && ` ${unit}`}`\n\n return !unit || SERVINGS_WORD.test(unit)\n ? { source, label, amount, servings: range, worded: !!unit }\n : { source, label, amount, yield: { ...range, unit } }\n }\n\n if (!isAbsent(value)) {\n ignore(\n reader,\n 'invalid_type',\n source,\n `Expected a yield such as \"4 servings\" or \"24 cookies\", received ${describeValue(value)}.`,\n )\n }\n return undefined\n}\n\n/**\n * Reads an ISO 8601 duration. Zero, as in `PT0S`, counts as absent, and a time\n * longer than `Number.MAX_SAFE_INTEGER` minutes is ignored, as `toJsonLd`\n * ignores it.\n */\nfunction readTime(\n reader: Reader,\n value: unknown,\n source: Path,\n): number | undefined {\n if (isAbsent(value)) {\n return undefined\n }\n\n const minutes =\n typeof value === 'string' ? parseIsoDuration(cleanText(value)) : undefined\n\n if (minutes === undefined || minutes > Number.MAX_SAFE_INTEGER) {\n ignore(\n reader,\n 'invalid_duration',\n source,\n `Expected an ISO 8601 duration such as \"PT30M\", received ${describeValue(value)}${minutes === undefined ? '' : ', which is too long'}.`,\n )\n return undefined\n }\n\n return minutes > 0 ? minutes : undefined\n}\n\n/**\n * Reads `recipeIngredient` or `recipeInstructions`. A named `HowToSection` or\n * `ItemList` becomes a titled section, an unnamed or nested one adds its items\n * where it is, and a string adds one item per line.\n */\nfunction readList(\n reader: Reader,\n key: 'ingredients' | 'steps',\n value: unknown,\n source: Path,\n readItem: (\n reader: Reader,\n value: unknown,\n source: Path,\n ) => Item[] | undefined,\n expected: string,\n): unknown[] {\n const list: unknown[] = []\n link(reader, [key], source)\n\n const add = (\n items: unknown[],\n path: Path,\n entry: unknown,\n entrySource: Path,\n inSection: boolean,\n ): void => {\n if (isAbsent(entry)) {\n return\n }\n\n if (entrySource.length > MAX_DEPTH) {\n ignore(\n reader,\n 'invalid_type',\n entrySource,\n `Expected ${expected}, received ${describeValue(entry)} nested more than ${MAX_DEPTH} levels deep.`,\n )\n return\n }\n\n if (Array.isArray(entry)) {\n const positions = entry.map((element: unknown) =>\n toNumber(asRecord(element)?.position),\n )\n const order = [...entry.keys()]\n if (!positions.includes(undefined)) {\n order.sort((a, b) => positions[a]! - positions[b]!)\n }\n for (const i of order) {\n add(items, path, entry[i], [...entrySource, i], inSection)\n }\n return\n }\n\n const record = asRecord(entry)\n const elements = [...entrySource, 'itemListElement']\n\n if (record?.itemListElement !== undefined && record.text === undefined) {\n const title =\n typeof record.name === 'string' ? cleanText(record.name) : ''\n\n if (title && !inSection) {\n const section = { title, items: [] as unknown[] }\n const sectionPath = [key, list.length]\n list.push(section)\n link(reader, sectionPath, entrySource)\n link(reader, [...sectionPath, 'title'], [...entrySource, 'name'])\n add(\n section.items,\n [...sectionPath, 'items'],\n record.itemListElement,\n elements,\n true,\n )\n } else {\n add(items, path, record.itemListElement, elements, inSection)\n }\n return\n }\n\n const read = readItem(reader, entry, entrySource)\n\n if (!read) {\n ignore(\n reader,\n 'invalid_type',\n entrySource,\n `Expected ${expected}, received ${describeValue(entry)}.`,\n )\n return\n }\n\n for (const item of read) {\n const itemPath = [...path, items.length]\n items.push(item.value)\n link(reader, itemPath, item.source, true)\n\n for (const [field, fieldSource, droppable] of item.fields ?? []) {\n link(reader, [...itemPath, field], fieldSource, droppable)\n }\n }\n }\n\n add(list, [key], value, source, false)\n return list\n}\n\n/** Reads an ingredient line: text, a `PropertyValue`, or a `ListItem`. */\nfunction readLine(\n reader: Reader,\n value: unknown,\n source: Path,\n): Item[] | undefined {\n if (typeof value === 'string') {\n return cleanLines(value).map((line) => ({ value: line, source }))\n }\n\n const record = asRecord(value)\n\n if (record?.item !== undefined && source.length < MAX_DEPTH) {\n return readLine(reader, record.item, [...source, 'item'])\n }\n\n const parts = [record?.value, record?.unitText, record?.name ?? record?.text]\n .filter((part) => typeof part === 'string' || typeof part === 'number')\n .join(' ')\n\n return parts\n ? cleanLines(parts).map((line) => ({ value: line, source }))\n : undefined\n}\n\n/**\n * Reads a step: text, a `HowToStep`, or a `ListItem`. A step's name is kept\n * only when it says something its text doesn't, unlike \"Step 1\" or the start\n * of the text.\n */\nfunction readStep(\n reader: Reader,\n value: unknown,\n source: Path,\n): Item[] | undefined {\n if (typeof value === 'string') {\n return cleanLines(value).map((line) => ({ value: line, source }))\n }\n\n const record = asRecord(value)\n\n if (!record) {\n return undefined\n }\n\n if (record.item !== undefined && source.length < MAX_DEPTH) {\n return readStep(reader, record.item, [...source, 'item'])\n }\n\n const name = typeof record.name === 'string' ? cleanText(record.name) : ''\n const body = text(record.text) ?? name\n const image = readImage(reader, record.image, [...source, 'image'])\n const lead = name.replace(/(?:…|\\.\\.\\.)$/, '').trim()\n const hasName =\n typeof body === 'string' &&\n !body.startsWith(lead) &&\n !/^step\\s*\\d*[.:]?$/i.test(name)\n const fields: NonNullable<Item['fields']> = [\n ['text', [...source, name && body === name ? 'name' : 'text'], false],\n ]\n\n if (image) {\n fields.push(['image', image.source, true])\n }\n\n return [\n {\n value: {\n text: body,\n ...(hasName && { name }),\n ...(image && { image: image.url }),\n },\n source,\n fields,\n },\n ]\n}\n\nfunction readTools(reader: Reader, value: unknown, source: Path): unknown[] {\n const entries: [unknown, Path][] = Array.isArray(value)\n ? value.map((entry: unknown, i) => [entry, [...source, i]])\n : [[value, source]]\n const equipment: unknown[] = []\n link(reader, ['equipment'], source)\n\n for (const [entry, entrySource] of entries) {\n const record = asRecord(entry)\n const item = record\n ? {\n name: text(record.name),\n ...(record.requiredQuantity !== undefined && {\n quantity:\n toNumber(\n asRecord(record.requiredQuantity)?.value ??\n record.requiredQuantity,\n ) ?? record.requiredQuantity,\n }),\n ...(record.url !== undefined && { url: text(record.url) }),\n }\n : text(entry)\n\n if (item === undefined) {\n continue\n }\n\n const path = ['equipment', equipment.length]\n equipment.push(item)\n link(reader, path, entrySource, true)\n link(reader, [...path, 'name'], [...entrySource, 'name'])\n link(\n reader,\n [...path, 'quantity'],\n [...entrySource, 'requiredQuantity'],\n true,\n )\n link(reader, [...path, 'url'], [...entrySource, 'url'], true)\n }\n\n return equipment\n}\n\nfunction readNutrition(\n reader: Reader,\n value: unknown,\n source: Path,\n): Record<string, unknown> | undefined {\n link(reader, ['nutrition'], source)\n\n if (isAbsent(value)) {\n return undefined\n }\n\n const record = asRecord(value)\n\n if (!record) {\n ignore(\n reader,\n 'invalid_type',\n source,\n `Expected NutritionInformation, such as { \"calories\": \"250 kcal\" }, received ${describeValue(value)}.`,\n )\n return undefined\n }\n\n const nutrition: Record<string, unknown> = {}\n const keys = Object.keys(NUTRIENTS) as (keyof Nutrition)[]\n\n for (const [field, amount] of Object.entries(record)) {\n const key = keys.find((key) => NUTRIENTS[key] === field)\n\n if (key) {\n nutrition[key] = text(amount)\n link(reader, ['nutrition', key], [...source, field], true)\n } else if (!field.startsWith('@')) {\n ignore(reader, 'unknown_field', [...source, field], 'Unknown field.')\n }\n }\n\n return nutrition\n}\n\n/** Cleaned text, with empty text and `null` as absent. Other values pass through for `parseRecipe` to report. */\nfunction text(value: unknown): unknown {\n return typeof value === 'string'\n ? cleanText(value) || undefined\n : (value ?? undefined)\n}\n\nfunction toNumber(value: unknown): number | undefined {\n const number =\n typeof value === 'string' && value.trim() ? Number(value) : value\n return typeof number === 'number' && Number.isFinite(number)\n ? number\n : undefined\n}\n\nfunction isAbsent(value: unknown): boolean {\n return (\n value === undefined ||\n value === null ||\n (typeof value === 'string' && !value.trim())\n )\n}\n\nfunction ignore(\n reader: Reader,\n code: RecipeIssueCode,\n path: Path,\n message: string,\n): void {\n warning(reader.warnings, code, path, `${message} It is ignored.`)\n}\n\nfunction link(\n reader: Reader,\n path: Path,\n source: Path,\n droppable = false,\n): void {\n const key = JSON.stringify(path)\n reader.sources.set(key, source)\n if (droppable) {\n reader.droppable.add(key)\n }\n}\n\n/** The JSON-LD path of a path in the recipe input, through the longest linked prefix. */\nfunction sourceOf(reader: Reader, path: Path): Path {\n for (let n = path.length; n >= 0; n--) {\n const source = reader.sources.get(JSON.stringify(path.slice(0, n)))\n if (source) {\n return source\n }\n }\n return []\n}\n\nfunction compareOrder(a: number[], b: number[]): number {\n for (const [i, n] of a.entries()) {\n const m = b[i]\n if (m === undefined) {\n return 1\n }\n if (n !== m) {\n return n - m\n }\n }\n return a.length - b.length\n}\n\nfunction droppableAt(reader: Reader, path: Path): Path | undefined {\n for (let n = path.length; n > 0; n--) {\n const at = path.slice(0, n)\n if (reader.droppable.has(JSON.stringify(at))) {\n return at\n }\n }\n return undefined\n}\n\n/**\n * Deletes a value from the recipe input, unless a value holding it is already\n * gone. A list keeps a hole, so later items keep their paths.\n */\nfunction remove(model: Record<string, unknown>, path: Path): void {\n const parent = path\n .slice(0, -1)\n .reduce<unknown>(\n (value, key) =>\n (value as Record<string | number, unknown> | undefined)?.[key],\n model,\n ) as Record<string | number, unknown> | undefined\n\n if (parent) {\n delete parent[path[path.length - 1]!]\n }\n}\n","import { describeValue, type RecipeIssue } from '../errors'\nimport { formatIngredient } from '../format/ingredient'\nimport { round } from '../format/number'\nimport { formatQuantity } from '../format/quantity'\nimport { formatServings, formatYield } from '../format/servings'\nimport { hasOwn, isRecord, warning } from '../issues'\nimport { multiply } from '../quantity/scale'\nimport { NUTRIENT_UNITS, type NutrientKey } from '../recipe/nutrient-units'\nimport type { Nutrition, Recipe, Step } from '../recipe/types'\nimport { isNative, type ResolvedIngredient, resolveRecipe } from '../resolve'\nimport type { System } from '../units/registry'\nimport { NUTRIENTS } from './nutrients'\nimport type {\n SchemaOrgHowToSection,\n SchemaOrgHowToStep,\n SchemaOrgNutritionInformation,\n SchemaOrgRecipe,\n ToJsonLdOptions,\n ToJsonLdResult,\n} from './types'\n\n/**\n * Writes a recipe as schema.org Recipe JSON-LD, for search engines' recipe\n * results. Writes it at its own servings and in `recipe.system`, else metric,\n * unless the options say otherwise; invalid options fall back to these, as in\n * `resolveRecipe`. Never throws for an unchanged recipe from `parseRecipe` or\n * `fromJsonLd`.\n *\n * `data` is plain JSON when `extra` is. Write it into a\n * `<script type=\"application/ld+json\">` tag with `<` escaped as `\\u003c`, so\n * recipe text can't end the tag. An `image` passed in `extra` is a URL; for an\n * `ImageObject` or several images, spread `data` into a new object with your\n * own `image`.\n *\n * Ingredient lines read back with `parseIngredientLine`: a quantity's\n * alternatives follow it in parentheses, as in `\"1 ½ cups (190 g) flour,\n * sifted\"` and `\"2 eggs (100 g)\"`, and an optional ingredient ends\n * `\" (optional)\"`. schema.org has no place for ingredient section titles, the\n * recipe's notes, custom times, an ingredient's `url`, or equipment beyond its\n * name, so they aren't written. Reading `data` back with `fromJsonLd` gives a\n * similar recipe, not the same one.\n *\n * `warnings` names the fields Google requires for recipe results that `data`\n * lacks, with paths that use the schema.org names: `image`, and `recipeYield`\n * when there is nutrition. A time longer than `Number.MAX_SAFE_INTEGER`\n * minutes is left out, as `fromJsonLd` leaves it out, and so is a `NaN` time,\n * each with an `invalid_duration` warning at its path in the recipe, such as\n * `['times', 'cook']`.\n *\n * @example\n * const { data } = toJsonLd(recipe, { url: 'https://example.com/pancakes' })\n * data.recipeYield // ['4', '4 servings']\n * data.recipeIngredient // ['1 ½ cups (190 g) flour, sifted', '2 eggs', 'salt, to taste']\n */\nexport function toJsonLd(\n recipe: Recipe,\n options?: ToJsonLdOptions,\n): ToJsonLdResult {\n const { servings, system, url, extra } = options ?? {}\n const resolved = resolveRecipe(recipe, { servings, system })\n // Up to the first `#` after the last line break. Anchored at the start, so\n // a long run of `#` before a line break isn't rescanned from each one.\n const page =\n typeof url === 'string'\n ? /^(?:[\\s\\S]*[\\n\\r\\u2028\\u2029])?[^#\\n\\r\\u2028\\u2029]*/.exec(url)![0]\n : undefined\n const yields = [\n ...(resolved.servings ? servingsText(resolved.servings) : []),\n ...(resolved.yield\n ? [formatYield(resolved.yield, { fractions: false })]\n : []),\n ]\n const ingredients = resolved.ingredients.flatMap(({ items }) =>\n items.map((item) => ingredientLine(item, resolved.scale, resolved.system)),\n )\n const steps = resolved.steps.flatMap(\n ({ title, items }): (SchemaOrgHowToStep | SchemaOrgHowToSection)[] => {\n const howToSteps = items.map((step) => howToStep(step, page))\n return title === undefined || howToSteps.length === 0\n ? howToSteps\n : [\n {\n '@type': 'HowToSection',\n name: title,\n itemListElement: howToSteps,\n },\n ]\n },\n )\n const { description, image, times, equipment, nutrition } = recipe\n const warnings: RecipeIssue[] = []\n\n const written: SchemaOrgRecipe = {\n '@context': 'https://schema.org',\n '@type': 'Recipe',\n name: recipe.name,\n ...(description !== undefined && { description }),\n ...(image !== undefined && { image }),\n ...(yields.length > 0 && { recipeYield: yields.map(plainSpaces) }),\n ...duration(warnings, 'prep', times.prep),\n ...duration(warnings, 'cook', times.cook),\n ...duration(warnings, 'total', times.total),\n ...(ingredients.length > 0 && { recipeIngredient: ingredients }),\n ...(steps.length > 0 && { recipeInstructions: steps }),\n ...(equipment.length > 0 && { tool: equipment.map(({ name }) => name) }),\n ...(nutrition !== undefined && {\n nutrition: nutritionInformation(nutrition),\n }),\n }\n const data: SchemaOrgRecipe = {\n ...written,\n ...Object.fromEntries(\n Object.entries(isRecord(extra) ? extra : {}).filter(\n ([field, value]) => value !== undefined && !hasOwn(written, field),\n ),\n ),\n }\n\n if (data.image === undefined) {\n warning(\n warnings,\n 'missing_field',\n ['image'],\n 'Add an image. Google requires one for recipe results.',\n )\n }\n if (data.nutrition !== undefined && data.recipeYield === undefined) {\n warning(\n warnings,\n 'missing_field',\n ['recipeYield'],\n 'Add servings or a yield. Google requires one with nutrition, which is for one serving.',\n )\n }\n\n return { data, warnings }\n}\n\n/** `[\"4\", \"4 servings\"]`, in decimals, so the text reads back as a number. */\nfunction servingsText(servings: {\n amount: number\n max?: number | undefined\n}): string[] {\n const amount = formatServings(servings, { fractions: false })\n const word =\n servings.amount === 1 && servings.max === undefined ? 'serving' : 'servings'\n return [amount, `${amount} ${word}`]\n}\n\n/**\n * The line as `formatIngredient` writes it, with the quantity's alternatives\n * in parentheses after it, or after the name for a bare count, and\n * \" (optional)\" at the end.\n */\nfunction ingredientLine(\n item: ResolvedIngredient,\n scale: number,\n system: System,\n): string {\n const { ingredient, origin } = item\n const { quantity, name, note } = formatIngredient(item)\n const authored = ingredient.quantity\n ? [ingredient.quantity, ...ingredient.equivalents]\n : []\n const shown =\n origin === 'authored'\n ? 0\n : origin === 'equivalent'\n ? 1 + ingredient.equivalents.findIndex((q) => isNative(q, system))\n : -1\n const alternatives = authored\n .filter((_, i) => i !== shown)\n .map((q) => formatQuantity(scale === 1 ? q : multiply(q, scale)))\n .join('; ')\n const inParentheses = alternatives && ` (${alternatives})`\n const head =\n quantity === undefined\n ? name\n : item.quantity?.unit === undefined\n ? `${quantity} ${name}${inParentheses}`\n : `${quantity}${inParentheses} ${name}`\n\n return plainSpaces(\n `${head}${note ? `, ${note}` : ''}${ingredient.optional ? ' (optional)' : ''}`,\n )\n}\n\nfunction howToStep(step: Step, page: string | undefined): SchemaOrgHowToStep {\n return {\n '@type': 'HowToStep',\n ...(step.name !== undefined && { name: step.name }),\n text: step.text,\n ...(step.image !== undefined && { image: step.image }),\n ...(page !== undefined && {\n // encodeURIComponent throws on a lone surrogate. With the u flag,\n // \\p{Cs} matches only those, as a pair reads as one code point.\n url: `${page}#${encodeURIComponent(step.id.replace(/\\p{Cs}/gu, '\\uFFFD'))}`,\n }),\n }\n}\n\n/**\n * An ISO 8601 duration to the second, or nothing for an absent or zero time,\n * or one it can't write: `NaN`, which `parseRecipe` rejects but a recipe built\n * by hand can hold, or a time longer than `Number.MAX_SAFE_INTEGER` minutes.\n * Below that bound, the hours fit in a safe integer, so they print in plain\n * digits.\n */\nfunction duration(\n warnings: RecipeIssue[],\n key: 'prep' | 'cook' | 'total',\n minutes: number | undefined,\n): Partial<SchemaOrgRecipe> {\n if (minutes === undefined) {\n return {}\n }\n if (Number.isNaN(minutes) || minutes > Number.MAX_SAFE_INTEGER) {\n warning(\n warnings,\n 'invalid_duration',\n ['times', key],\n `Expected minutes such as 30, received ${describeValue(minutes)}${Number.isNaN(minutes) ? '' : ', which is too long'}. It is ignored.`,\n )\n return {}\n }\n\n const seconds = Math.round(minutes * 60)\n\n if (seconds <= 0) {\n return {}\n }\n\n const parts = [\n [Math.floor(seconds / 3600), 'H'],\n [Math.floor(seconds / 60) % 60, 'M'],\n [seconds % 60, 'S'],\n ] as const\n\n return {\n [`${key}Time`]: `PT${parts.map(([n, unit]) => (n ? `${n}${unit}` : '')).join('')}`,\n }\n}\n\nfunction nutritionInformation(\n nutrition: Nutrition,\n): SchemaOrgNutritionInformation {\n const information: SchemaOrgNutritionInformation = {\n '@type': 'NutritionInformation',\n }\n\n for (const key of Object.keys(NUTRIENTS) as (keyof Nutrition)[]) {\n const value = nutrition[key]\n if (value !== undefined) {\n information[NUTRIENTS[key]] =\n typeof value === 'string'\n ? value\n : `${round(value, 3)} ${NUTRIENT_UNITS[key as NutrientKey]}`\n }\n }\n\n return information\n}\n\nfunction plainSpaces(text: string): string {\n return text.replace(/\\u00A0/g, ' ')\n}\n"]}
1
+ {"version":3,"sources":["../src/schema-org/find.ts","../src/schema-org/nutrients.ts","../src/schema-org/text.ts","../src/schema-org/from-json-ld.ts","../src/schema-org/to-json-ld.ts"],"names":["asRecord","hasOwn","RecipeBookError","describeValue","text","isRecord","toResult","issue","warning","quote","parseRecipeWith","parseIngredientLine","disallowedScheme","image","matchAmount","amount","parseIsoDuration","elements","key","resolveRecipe","formatYield","formatServings","formatIngredient","isNative","formatQuantity","multiply","round","NUTRIENT_UNITS"],"mappings":"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","file":"schema-org.cjs","sourcesContent":["import { describeValue, RecipeBookError } from '../errors'\nimport { hasOwn, isRecord, type Path } from '../issues'\nimport { asRecord } from '../validation'\n\n/** A JSON-LD node, as passed in, and its path in the input. */\nexport type Located = { node: Record<string, unknown>; path: Path }\n\n/**\n * The longest path read in JSON-LD. Real markup nests about ten levels, and\n * the bound keeps a hostile page from overflowing the stack.\n */\nexport const MAX_DEPTH = 32\n\n/**\n * Finds the Recipe nodes in parsed JSON-LD documents, in order, through arrays,\n * `@graph`, and one level of `mainEntity`, or, when that finds none, also\n * through each `ItemList`'s `itemListElement` and each `ListItem`'s `item`, to\n * `MAX_DEPTH`. It indexes by `@id` each Recipe, and each node at the top level\n * of the JSON-LD, or reached from there through arrays and `@graph`, so\n * references can be followed. An `@id` names its first node, and a Recipe\n * with the `@id` of an earlier Recipe is left out, unless the earlier one\n * holds nothing but keywords such as `@type`: then it takes that one's place\n * in `recipes`, and in `ids` when that one was the first node with its `@id`.\n * An empty `@id` is no `@id`.\n */\nexport function locate(documents: readonly unknown[]): {\n recipes: Located[]\n ids: Map<string, Located>\n} {\n const direct = scan(documents, false)\n return direct.recipes.length > 0 ? direct : scan(documents, true)\n}\n\n/** How `scan` reached a value, which decides what it reads there. */\ntype Reach = 'any' | 'mainEntity' | 'entry' | 'item'\n\nfunction scan(\n documents: readonly unknown[],\n lists: boolean,\n): { recipes: Located[]; ids: Map<string, Located> } {\n const recipes: Located[] = []\n const ids = new Map<string, Located>()\n // A stub Recipe, or `true` once the `@id`'s Recipe holds content, so a\n // duplicate never rescans the first one's keys.\n const recipeIds = new Map<unknown, Located | true>()\n\n const visit = (value: unknown, path: Path, reach: Reach = 'any'): void => {\n if (path.length > MAX_DEPTH) {\n return\n }\n\n if (Array.isArray(value)) {\n for (const [entry, entryPath] of entriesOf(value, path)) {\n visit(entry, entryPath, reach)\n }\n return\n }\n\n const fields = asRecord(value)\n if (!fields) {\n return\n }\n\n const isRecipe = hasType(fields, 'Recipe')\n const isList = lists && hasType(fields, 'ItemList')\n\n if (reach !== 'any' && !isRecipe) {\n if (isList && reach === 'mainEntity') {\n visit(fields.itemListElement, [...path, 'itemListElement'], 'entry')\n } else if (lists && reach === 'entry' && hasType(fields, 'ListItem')) {\n visit(fields.item, [...path, 'item'], 'item')\n }\n return\n }\n\n const located = { node: value as Record<string, unknown>, path }\n const id = fields['@id'] || undefined\n if (typeof id === 'string' && !ids.has(id)) {\n ids.set(id, located)\n }\n\n if (isRecipe) {\n const earlier = recipeIds.get(id)\n if (!earlier) {\n recipes.push(located)\n if (typeof id === 'string') {\n recipeIds.set(id, hasContent(fields) || located)\n }\n } else if (earlier !== true && hasContent(fields)) {\n // `recipes` holds this same object, and so does `ids` when the stub was\n // the first node with its `@id`, so a reference to the recipe still\n // finds the recipe itself.\n Object.assign(earlier, located)\n recipeIds.set(id, true)\n }\n } else {\n visit(fields['@graph'], [...path, '@graph'])\n visit(fields.mainEntity, [...path, 'mainEntity'], 'mainEntity')\n if (isList) {\n visit(fields.itemListElement, [...path, 'itemListElement'], 'entry')\n }\n }\n }\n\n for (const document of documents) {\n visit(document, [])\n }\n return { recipes, ids }\n}\n\nconst TYPES = {\n Recipe: /(?:^|[/:#])Recipe$/,\n ItemList: /(?:^|[/:#])ItemList$/,\n ListItem: /(?:^|[/:#])ListItem$/,\n}\n\nfunction hasType(\n node: Record<string, unknown>,\n name: keyof typeof TYPES,\n): boolean {\n return entriesOf(node['@type'], []).some(\n ([type]) => typeof type === 'string' && TYPES[name].test(type),\n )\n}\n\nfunction hasContent(node: Record<string, unknown>): boolean {\n return Object.keys(node).some((key) => !key.startsWith('@'))\n}\n\n/**\n * An array's elements with their paths, or a value that isn't an array with\n * its own path. A hole in an array, which a program can leave but\n * `JSON.parse` can't, is left out. It reads by index, because a program can\n * also give an array another prototype, or a `constructor` that isn't one,\n * and then array methods such as `flatMap` throw.\n */\nexport function entriesOf(value: unknown, path: Path): [unknown, Path][] {\n if (!Array.isArray(value)) {\n return [[value, path]]\n }\n const entries: [unknown, Path][] = []\n for (let i = 0; i < value.length; i++) {\n if (hasOwn(value, i)) {\n entries.push([value[i], [...path, i]])\n }\n }\n return entries\n}\n\n/**\n * Finds the schema.org Recipe nodes in a page's\n * `<script type=\"application/ld+json\">` tags, without a DOM. Pass one to\n * `fromJsonLd`.\n *\n * Reads arrays and `@graph`, as Yoast and WP Recipe Maker write them, and the\n * `mainEntity` of a node there, up to 32 levels deep, and matches a node whose\n * `@type` is or includes `\"Recipe\"`. When that finds none, it also reads each\n * `ItemList` in those places, as a roundup page lists its recipes, taking each\n * Recipe in its `itemListElement`, or in a `ListItem`'s `item` there. A\n * `ListItem` with only a `url` is skipped: fetch that page and call\n * `findRecipeJsonLd` on it. A `mainEntity`, or an entry of a `mainEntity`\n * array, that is neither a Recipe nor an `ItemList` is skipped with everything\n * in it, and a Recipe anywhere else, such as inside another Recipe or in a list\n * inside a `ListItem` or another list, isn't found.\n *\n * A tag whose JSON doesn't parse is retried with the raw line breaks and tabs\n * inside its strings escaped, as real pages have them, and skipped if it still\n * doesn't. A tag inside an HTML comment is skipped, and a `<!--` in an\n * attribute value or in a `style` or `textarea` element is text, as in a\n * browser. A quote starts an attribute value only right after `=`, so a stray\n * one, as in `content=\"a 9\" pan\"`, doesn't hide later tags. A Recipe node with\n * the `@id` of an earlier one is returned once, where the first appears. When\n * the first holds only keywords, such as a `mainEntity` of\n * `{ \"@type\": \"Recipe\", \"@id\": \"#recipe\" }`, the later node is returned in its\n * place. An empty `@id` is no `@id`, so it merges nothing.\n *\n * In each Recipe node returned, an image that is an `@id` reference to a node\n * at the top level of the JSON-LD, or reached from there through arrays and\n * `@graph`, holds that node instead of the reference, an object that holds only\n * that `@id`. That applies to the recipe's `image` and each step's `image` in\n * `recipeInstructions`, and lets `fromJsonLd` read them. A reference to a node\n * in any other field, such as an `Organization`'s `logo` or an `ImageObject` in\n * a `WebPage`'s `mainEntity`, isn't followed. Other references, such as\n * `author` and `mainEntityOfPage`, and references inside the node an image\n * holds, stay as the page wrote them.\n *\n * @param html - The page's HTML, such as `await response.text()`.\n * @returns The Recipe nodes it finds, in document order, or `[]` when there\n * are none.\n * @throws {RecipeBookError} `invalid_argument` when `html` isn't a string.\n *\n * @example\n * const [node] = findRecipeJsonLd(await response.text())\n * const result = fromJsonLd(node)\n */\nexport function findRecipeJsonLd(html: string): Record<string, unknown>[] {\n if (typeof html !== 'string') {\n throw new RecipeBookError(\n 'invalid_argument',\n `findRecipeJsonLd: html must be a string, such as await response.text(), received ${describeValue(html)}.`,\n )\n }\n\n const documents: unknown[] = []\n\n // At each `<`, in this order: a script, style, or textarea element with its\n // content; a comment, where `<!-->` and `<!--->` close at once; or any other\n // tag with its quoted attribute values. What one of these holds, such as a\n // `<!--` in an attribute value, starts nothing, as in a browser. A quote\n // starts a value only right after `=`, so a stray one, as in\n // `content=\"a 9\" pan\"`, is text. The element's attributes are read once, in\n // a lookahead, then matched by backreference, so a tag with no `>` fails\n // without retrying other splits of them, which would be exponential.\n for (const [, element, attributes = '', body = ''] of html.matchAll(\n /<(script|style|textarea)(?=[\\s/>])(?=((?:=\\s*(?:\"[^\"]*\"|'[^']*')|[^<>])*))\\2>([\\s\\S]*?)(?:<\\/\\1\\s*>|$)|<!--(?:-?>|[\\s\\S]*?(?:--!?>|$))|<\\/?[a-z][^\\s/>]*(?:=\\s*(?:\"[^\"]*\"|'[^']*')|[^<>])*/gi,\n )) {\n if (\n element?.toLowerCase() === 'script' &&\n /[\\s/]type\\s*=\\s*[\"']?application\\/ld\\+json\\b/i.test(attributes)\n ) {\n const text = body\n .replace(/^\\s*(?:\\/\\/\\s*)?(?:<!--|<!\\[CDATA\\[)/, '')\n .replace(/(?:\\/\\/\\s*)?(?:-->|\\]\\]>)\\s*$/, '')\n const json =\n parseJson(text) ??\n parseJson(\n text.replace(/\"(?:[^\"\\\\]|\\\\[\\s\\S]?)*(?:\"|$)/g, (string) =>\n string.replace(/[\\n\\r\\t]/g, (c) => JSON.stringify(c).slice(1, -1)),\n ),\n )\n\n documents.push(json)\n }\n }\n\n const { recipes, ids } = locate(documents)\n return recipes.map(({ node }) => withImages(node, ids))\n}\n\n/**\n * A copy of a Recipe node with each image that is a one-hop reference to\n * another node replaced by that node: the recipe's `image`, and each step's\n * `image` in `recipeInstructions`, through sections, `ItemList`s, and\n * `ListItem`s. The fields `fromJsonLd` doesn't read keep their references.\n */\nfunction withImages(\n node: Record<string, unknown>,\n ids: Map<string, Located>,\n): Record<string, unknown> {\n const follow = (value: unknown): unknown => {\n const id =\n isRecord(value) && Object.keys(value).join() === '@id' && value['@id']\n const target = typeof id === 'string' && ids.get(id)?.node\n return target && target !== node ? target : value\n }\n const images = (value: unknown): unknown =>\n Array.isArray(value) ? value.map(follow) : follow(value)\n const copy = (value: unknown, depth: number, keys: string[]): unknown => {\n if (depth > MAX_DEPTH) {\n return value\n }\n if (Array.isArray(value)) {\n return value.map((entry: unknown) => copy(entry, depth + 1, keys))\n }\n\n const fields = asRecord(value)\n if (!fields) {\n return value\n }\n\n const result = { ...fields }\n for (const key of keys) {\n if (fields[key] !== undefined) {\n result[key] =\n key === 'image'\n ? images(fields[key])\n : copy(fields[key], depth + 1, ['itemListElement', 'item', 'image'])\n }\n }\n return result\n }\n\n return copy(node, 0, ['image', 'recipeInstructions']) as typeof node\n}\n\nfunction parseJson(text: string): unknown {\n try {\n return JSON.parse(text)\n } catch {\n return undefined\n }\n}\n","import type { Nutrition } from '../recipe/types'\nimport type { SchemaOrgNutritionInformation } from './types'\n\n/** The schema.org `NutritionInformation` name for each `Nutrition` field. */\nexport const NUTRIENTS: Readonly<\n Record<keyof Nutrition, Exclude<keyof SchemaOrgNutritionInformation, '@type'>>\n> = {\n servingSize: 'servingSize',\n calories: 'calories',\n fat: 'fatContent',\n saturatedFat: 'saturatedFatContent',\n transFat: 'transFatContent',\n unsaturatedFat: 'unsaturatedFatContent',\n carbohydrates: 'carbohydrateContent',\n sugar: 'sugarContent',\n fiber: 'fiberContent',\n protein: 'proteinContent',\n sodium: 'sodiumContent',\n cholesterol: 'cholesterolContent',\n}\n","import { hasOwn } from '../issues'\n\nconst NAMED_ENTITIES: Readonly<Record<string, string>> = {\n amp: '&',\n lt: '<',\n gt: '>',\n quot: '\"',\n apos: \"'\",\n nbsp: ' ',\n ensp: ' ',\n emsp: ' ',\n thinsp: ' ',\n shy: '',\n zwj: '',\n zwnj: '',\n deg: '°',\n colon: ':',\n Tab: '\\t',\n NewLine: '\\n',\n euro: '€',\n pound: '£',\n yen: '¥',\n cent: '¢',\n half: '½',\n frac12: '½',\n frac14: '¼',\n frac34: '¾',\n frac13: '⅓',\n frac23: '⅔',\n frac15: '⅕',\n frac25: '⅖',\n frac35: '⅗',\n frac45: '⅘',\n frac16: '⅙',\n frac56: '⅚',\n frac18: '⅛',\n frac38: '⅜',\n frac58: '⅝',\n frac78: '⅞',\n frasl: '⁄',\n ndash: '–',\n mdash: '—',\n minus: '−',\n hellip: '…',\n lsquo: '‘',\n rsquo: '’',\n sbquo: '‚',\n ldquo: '“',\n rdquo: '”',\n bdquo: '„',\n laquo: '«',\n raquo: '»',\n times: '×',\n divide: '÷',\n middot: '·',\n bull: '•',\n micro: 'µ',\n sup1: '¹',\n sup2: '²',\n sup3: '³',\n ordm: 'º',\n ordf: 'ª',\n copy: '©',\n reg: '®',\n trade: '™',\n iexcl: '¡',\n iquest: '¿',\n szlig: 'ß',\n aelig: 'æ',\n AElig: 'Æ',\n oelig: 'œ',\n OElig: 'Œ',\n oslash: 'ø',\n Oslash: 'Ø',\n}\n\n// `&eacute;` and the like decode to the letter plus a combining mark, then NFC.\nconst MARKS: Readonly<Record<string, string>> = {\n grave: '\\u0300',\n acute: '\\u0301',\n circ: '\\u0302',\n tilde: '\\u0303',\n uml: '\\u0308',\n ring: '\\u030A',\n cedil: '\\u0327',\n}\n\n// A comment, a script or style element with its content, or a tag, with its\n// name captured if it's a block tag. As in a browser, a quote starts an\n// attribute value only right after `=`. A value can hold a `>`, and a `<`\n// that can't start a tag, as in `a < b`. A tag with no `>` is tried again at\n// each `<` in it, so the attributes end at any `<` that can start a tag, which\n// keeps each try short. They're read once, in a lookahead, then matched by\n// backreference, so a failed tag doesn't retry other splits of them, which\n// would be exponential. A literal, unlike `new RegExp`, lets bundlers drop it.\nconst MARKUP =\n /<!--[\\s\\S]*?(?:-->|$)|<(script|style)(?=[\\s/>])(?=((?:=\\s*(?:\"(?:[^\"<]|<(?![a-z/!?]))*\"|'(?:[^'<]|<(?![a-z/!?]))*')|[^<>])*))\\2>[\\s\\S]*?(?:<\\/\\1\\s*>|$)|<(?:(\\/?(?:br|p|li|div|h[1-6])\\b)|[/!?]?[a-z])(?=((?:=\\s*(?:\"(?:[^\"<]|<(?![a-z/!?]))*\"|'(?:[^'<]|<(?![a-z/!?]))*')|[^<>])*))\\4>/gi\n\n// Removing a tag can join the text around it into a new one, as in\n// `<scr<b></b>ipt>`, so stripping repeats. Real markup needs a pass or two;\n// the cap keeps hostile nesting linear.\nconst MAX_PASSES = 8\n\n/**\n * JSON-LD text with its tags removed, then its HTML entities decoded, on one\n * line with single spaces. An encoded tag, such as `&lt;b&gt;`, stays as text.\n */\nexport function cleanText(text: string): string {\n return cleanLines(text).join(' ')\n}\n\n/** {@link cleanText} for each line, split at line breaks and block tags. Empty lines are left out. */\nexport function cleanLines(text: string): string[] {\n return stripTags(text)\n .replace(\n /&(?:#(\\d{1,7})|#x([\\da-f]{1,6})|([a-z][a-z\\d]*));/gi,\n (entity, decimal?: string, hex?: string, name?: string) => {\n if (name === undefined) {\n const code = decimal === undefined ? parseInt(hex!, 16) : +decimal\n return code > 0 &&\n code <= 0x10ffff &&\n (code < 0xd800 || code > 0xdfff)\n ? String.fromCodePoint(code)\n : entity\n }\n\n if (hasOwn(NAMED_ENTITIES, name)) {\n return NAMED_ENTITIES[name]!\n }\n\n const accent = /^([aceinouyACEINOUY])([a-z]+)$/.exec(name)\n return accent && hasOwn(MARKS, accent[2]!)\n ? `${accent[1]}${MARKS[accent[2]!]}`.normalize('NFC')\n : entity\n },\n )\n .split(/[\\n\\r\\u2028\\u2029]/)\n .map((line) => line.replace(/\\s+/g, ' ').trim())\n .filter(Boolean)\n}\n\n/**\n * Removes comments, tags, and the content of `script` and `style`, and ends a\n * line at block tags. Strips again until nothing changes, for up to\n * `MAX_PASSES` passes, so a ninth nested level stays as text such as `b>`.\n * Then removes any `<` that could still open a tag: one before a letter, `/`,\n * `!`, or `?` with a `>` after it, as in `<a <>`. A `<` with no `>` after it,\n * as in `x<y`, stays.\n */\nfunction stripTags(text: string): string {\n let stripped = text\n\n for (let pass = 0; pass < MAX_PASSES; pass++) {\n const next = stripped.replace(\n MARKUP,\n (_, _element, _attributes, block?: string) => (block ? '\\n' : ''),\n )\n if (next === stripped) {\n break\n }\n stripped = next\n }\n\n const end = stripped.lastIndexOf('>') + 1\n return (\n stripped\n .slice(0, end)\n .replace(/<+([/!?a-z]?)/gi, (run, next: string) => next || run) +\n stripped.slice(end)\n )\n}\n","import {\n describeValue,\n quote,\n type RecipeIssue,\n type RecipeIssueCode,\n} from '../errors'\nimport { parseIngredientLine } from '../ingredient/parse'\nimport { issue, type Path, warning } from '../issues'\nimport { matchAmount } from '../quantity/parse'\nimport { parseIsoDuration } from '../recipe/duration'\nimport { parseRecipeWith } from '../recipe/parse'\nimport type { Nutrition, Recipe } from '../recipe/types'\nimport { disallowedScheme } from '../recipe/url'\nimport { asRecord, toResult } from '../validation'\nimport { entriesOf, type Located, locate, MAX_DEPTH } from './find'\nimport { NUTRIENTS } from './nutrients'\nimport { cleanLines, cleanText } from './text'\nimport type { FromJsonLdResult } from './types'\n\n/**\n * The node's fields that `fromJsonLd` reads or that core owns, so `extra`\n * leaves them out, in the order issues are reported.\n */\nconst READ_FIELDS: readonly string[] = [\n '@context',\n '@type',\n 'name',\n 'description',\n 'image',\n 'recipeYield',\n 'prepTime',\n 'cookTime',\n 'totalTime',\n 'recipeIngredient',\n 'recipeInstructions',\n 'tool',\n 'nutrition',\n]\n\n/**\n * The longest image URL kept. Each step that refers to an image node holds\n * its own copy of the URL, so the bound keeps the recipe's JSON from growing\n * with the URL's length times the number of steps.\n */\nconst MAX_URL_LENGTH = 4096\n\nconst SERVINGS_WORD =\n /^(?:servings?|portions?|(?:serving|portion)\\(s\\)|people|persons?)\\.?$/i\n\ntype Reader = {\n /** The Recipe node, as passed in. */\n recipe: Record<string, unknown>\n ids: Map<string, Located>\n warnings: RecipeIssue[]\n /** The JSON-LD path of each value in the recipe input, keyed by its path there. */\n sources: Map<string, Path>\n /** The recipe input paths of the values a failed parse drops. */\n droppable: Set<string>\n /**\n * Each node's reads as an image: the image it holds, how many warnings\n * reading it gave, how far below the node the read went, and the path length\n * it was read at. Read directly, and read through a reference, which doesn't\n * follow another.\n */\n images: [direct: Map<unknown, Read[]>, referenced: Map<unknown, Read[]>]\n /** How many warnings reading those nodes again would have repeated. */\n repeated: number\n /**\n * The longest path the current read has gone to. Only the path's length\n * decides where `MAX_DEPTH` cuts a read off, so a read is reused at the\n * length it was read at, and one that stayed within the limit also anywhere\n * reading the node again would, so reusing a read never changes the result.\n */\n deepest: number\n}\n\ntype Image = { url: string; source: Path }\n\ntype Read = [\n image: Image | undefined,\n warnings: number,\n depth: number,\n length: number,\n]\n\n/** A value read from `recipeYield`. */\ntype Batch = {\n source: Path\n /** The value as text, to name it in a message. */\n label: string\n /** The amount, or the low end of its range. */\n amount: number\n servings?: unknown\n /** Servings with a word, such as \"4 servings\", not a bare number. */\n worded?: boolean\n yield?: unknown\n /** The yield's amount is \"a\" or \"an\", as in \"a few\", not a number. */\n article?: boolean\n}\n\n/** A list item read from JSON-LD, and where its fields came from. */\ntype Item = {\n value: unknown\n source: Path\n fields: [field: string, source: Path, droppable: boolean][]\n}\n\n/**\n * Reads a schema.org Recipe from JSON-LD, as recipe sites publish it for\n * search engines: a Recipe node, or an array, `@graph`, `mainEntity`, or\n * `ItemList` that holds one, such as a node from `findRecipeJsonLd` or\n * `JSON.parse` of a script tag. An `ItemList` is read only when no other\n * Recipe is found, as in `findRecipeJsonLd`. Never throws for bad data; an\n * error thrown by a getter or proxy in the input passes through.\n *\n * Every string has its tags removed, then its HTML entities decoded, so an\n * encoded tag such as `&lt;b&gt;` stays as text. Ingredient lines are read\n * with `parseIngredientLine`. Issue paths point into the JSON-LD, such as\n * `recipeIngredient[3]`.\n *\n * Reading is forgiving. A value the recipe can't hold, such as a `data:`\n * image or nutrition of \"N/A\", is left out with a warning that keeps its usual\n * code and ends \"It is ignored.\" A second Recipe node, a second number of\n * servings, or a second yield is an `ignored_value` warning. The result fails\n * only when there is no Recipe node, the recipe's name is missing or isn't\n * text, or a problem remains that leaving a value out can't fix.\n *\n * @returns The recipe or the error, and `extra`: the node's fields the recipe\n * doesn't model, such as `author` and `keywords`, as they were. A field that\n * nests more than 32 levels deep, counted from the top of `input`, is left\n * out, with a warning. Pass `extra` to `toJsonLd` to write them back. It is\n * `{}` when no Recipe node is found.\n *\n * @example\n * const result = fromJsonLd(node)\n * if (!result.success) {\n * console.error(result.error.message)\n * // Recipe has 1 problem:\n * // ✖ name Add a name for the recipe.\n * // See https://recipe-book.siraj.page/errors/invalid_recipe/\n * return\n * }\n * result.data.ingredients[0].items[0] // { id: 'flour', name: 'flour', quantity: { amount: 2, unit: 'cup' }, … }\n * result.extra.author // { '@type': 'Person', name: 'Ada' }\n */\nexport function fromJsonLd(input: unknown): FromJsonLdResult {\n const { recipes, ids } = locate([input])\n const [found] = recipes\n\n if (!found) {\n return {\n ...toResult<Recipe>('invalid_recipe', undefined, [\n issue(\n 'error',\n 'invalid_type',\n [],\n `Expected a schema.org Recipe, or an array, @graph, mainEntity, or ItemList that holds one, received ${describeValue(input)}.`,\n ),\n ]),\n extra: {},\n }\n }\n\n const node = asRecord(found.node)!\n const reader: Reader = {\n recipe: found.node,\n ids,\n warnings: [],\n sources: new Map(),\n droppable: new Set(),\n images: [new Map(), new Map()],\n repeated: 0,\n deepest: 0,\n }\n const name = text(node.name)\n\n if (recipes.length > 1) {\n warning(\n reader.warnings,\n 'ignored_value',\n [],\n `Found ${recipes.length} recipes. Only the first${typeof name === 'string' ? `, ${quote(name)},` : ''} is read.`,\n )\n }\n\n const model = readRecipe(reader, node, found.path)\n const parse = () => parseRecipeWith(model, parseIngredientLine)\n let result = parse()\n const dropped: RecipeIssue[] = []\n\n if (!result.success) {\n const targets: Path[] = []\n for (const error of result.error.issues) {\n const target =\n error.severity === 'error' ? droppableAt(reader, error.path) : undefined\n\n if (target) {\n targets.push(target)\n dropped.push({\n ...error,\n severity: 'warning',\n message: `${error.message} It is ignored.`,\n })\n }\n }\n // Deepest first, so no removal walks through a hole an earlier one left,\n // where a polluted `Object.prototype` would stand in for the missing item.\n targets\n .sort((a, b) => b.length - a.length)\n .forEach((target) => remove(model, target))\n if (dropped.length > 0) {\n result = parse()\n }\n }\n\n // An object's unknown fields sort after its other issues, as in parseRecipe.\n const order = ({ code, path }: RecipeIssue): number[] => [\n path.length > found.path.length\n ? READ_FIELDS.indexOf(String(path[found.path.length]))\n : -1,\n ...path\n .slice(found.path.length + 1)\n .filter((key) => typeof key === 'number'),\n ...(code === 'unknown_field' ? [Infinity] : []),\n ]\n const issues = [\n ...reader.warnings,\n ...[\n ...dropped,\n ...(result.success ? result.warnings : result.error.issues),\n ].map((issue) => ({ ...issue, path: sourceOf(reader, issue.path) })),\n ].sort((a, b) => compareOrder(order(a), order(b)))\n\n const checked = new Map<object, number>()\n const extra = Object.fromEntries(\n Object.entries(node).filter(([key, value]) => {\n if (READ_FIELDS.includes(key)) {\n return false\n }\n const path = [...found.path, key]\n if (tooDeep(value, path.length, checked)) {\n warning(\n issues,\n 'invalid_type',\n path,\n `Expected a value to keep in extra, received ${describeValue(value)} nested more than ${MAX_DEPTH} levels deep. It is ignored.`,\n )\n return false\n }\n return true\n }),\n )\n\n return {\n ...toResult(\n 'invalid_recipe',\n result.success ? result.data : undefined,\n issues,\n typeof name === 'string' ? quote(name) : undefined,\n ),\n extra,\n }\n}\n\n/**\n * Whether a value at a JSON-LD path of `length` keys, or a value it holds, is\n * more than `MAX_DEPTH` keys deep, so `extra` stays shallow enough to\n * serialize. `checked` holds the longest path each object was found shallow\n * at, so objects shared in the input are read a bounded number of times.\n */\nfunction tooDeep(\n value: unknown,\n length: number,\n checked: Map<object, number>,\n): boolean {\n if (length > MAX_DEPTH) {\n return true\n }\n if (\n typeof value !== 'object' ||\n value === null ||\n (checked.get(value) ?? 0) >= length\n ) {\n return false\n }\n const deep = Object.values(value).some((child) =>\n tooDeep(child, length + 1, checked),\n )\n if (!deep) {\n checked.set(value, length)\n }\n return deep\n}\n\n/** Builds `parseRecipe` input from a Recipe node, and links each value to its JSON-LD path. */\nfunction readRecipe(\n reader: Reader,\n node: Record<string, unknown>,\n base: Path,\n): Record<string, unknown> {\n const at = (...path: Path): Path => [...base, ...path]\n const model: Record<string, unknown> = {\n name: text(node.name),\n description: text(node.description),\n }\n link(reader, [], base)\n link(reader, ['name'], at('name'))\n link(reader, ['description'], at('description'), true)\n\n const image = readImage(reader, node.image, at('image'))\n if (image) {\n model.image = image.url\n link(reader, ['image'], image.source, true)\n }\n\n readYield(reader, model, node.recipeYield, at('recipeYield'))\n\n const times: Record<string, number> = {}\n for (const key of ['prep', 'cook', 'total']) {\n const field = `${key}Time`\n const minutes = readTime(reader, node[field], at(field))\n if (minutes !== undefined) {\n times[key] = minutes\n }\n }\n model.times = times\n\n model.ingredients = readList(\n reader,\n 'ingredients',\n node.recipeIngredient,\n at('recipeIngredient'),\n readLine,\n 'an ingredient line such as \"2 cups flour\"',\n )\n model.steps = readList(\n reader,\n 'steps',\n node.recipeInstructions,\n at('recipeInstructions'),\n readStep,\n 'a step such as \"Whisk the eggs.\" or a HowToStep',\n )\n model.equipment = readTools(reader, node.tool, at('tool'))\n model.nutrition = readNutrition(reader, node.nutrition, at('nutrition'))\n return model\n}\n\nfunction readImage(\n reader: Reader,\n value: unknown,\n source: Path,\n): Image | undefined {\n if (isAbsent(value)) {\n return undefined\n }\n\n const warnings = reader.warnings.length + reader.repeated\n const image = findImage(reader, value, source)\n if (!image && reader.warnings.length + reader.repeated === warnings) {\n ignore(\n reader,\n 'invalid_type',\n source,\n `Expected an image URL, an ImageObject with a url, or a list of them, received ${describeValue(value)}.`,\n )\n }\n return image\n}\n\n/**\n * The first URL a recipe can hold in an image, a list of them, an\n * ImageObject, or a reference to one. Each URL before it that's longer than\n * `MAX_URL_LENGTH` or has another scheme, such as `data:`, each value more\n * than `MAX_DEPTH` levels deep, and a reference to the recipe itself get a\n * warning. Follows one reference, so references that cycle end. A node that\n * several images reference or hold is read and warns once, where it's first\n * read, or near `MAX_DEPTH`, where how deep a read starts decides where it's\n * cut off, once at each depth.\n */\nfunction findImage(\n reader: Reader,\n value: unknown,\n source: Path,\n referenced = false,\n): Image | undefined {\n reader.deepest = Math.max(reader.deepest, source.length)\n if (source.length > MAX_DEPTH) {\n if (!isAbsent(value)) {\n ignore(\n reader,\n 'invalid_type',\n source,\n `Expected an image URL, an ImageObject with a url, or a list of them, received ${describeValue(value)} nested more than ${MAX_DEPTH} levels deep.`,\n )\n }\n return undefined\n }\n if (typeof value === 'string') {\n const url = cleanText(value)\n const scheme = disallowedScheme(url)\n if (scheme) {\n ignore(\n reader,\n 'invalid_url',\n source,\n `Expected an http or https URL, or a relative one, received ${quote(`${scheme}…`)}.`,\n )\n return undefined\n }\n if (url.length > MAX_URL_LENGTH) {\n ignore(\n reader,\n 'invalid_url',\n source,\n `Expected a URL of at most ${MAX_URL_LENGTH} UTF-16 code units, received ${url.length}.`,\n )\n return undefined\n }\n return url ? { url, source } : undefined\n }\n\n if (Array.isArray(value)) {\n for (const [entry, entrySource] of entriesOf(value, source)) {\n const image = findImage(reader, entry, entrySource, referenced)\n if (image) {\n return image\n }\n }\n return undefined\n }\n\n const images = reader.images[referenced ? 1 : 0]\n const reads = images.get(value) ?? []\n const read = reads.find(\n ([, , depth, length]) =>\n length === source.length ||\n Math.max(length, source.length) + depth <= MAX_DEPTH,\n )\n if (read) {\n reader.repeated += read[1]\n reader.deepest = Math.max(reader.deepest, source.length + read[2])\n return read[0]\n }\n\n const record = asRecord(value)\n if (!record) {\n return undefined\n }\n\n images.set(value, reads)\n const warnings = reader.warnings.length + reader.repeated\n const deepest = reader.deepest\n reader.deepest = source.length\n const id = record['@id']\n const target =\n typeof id === 'string' && !referenced ? reader.ids.get(id) : undefined\n let image =\n findImage(reader, record.url, [...source, 'url'], referenced) ??\n findImage(reader, record.contentUrl, [...source, 'contentUrl'], referenced)\n\n if (!image && target) {\n if (target.node === reader.recipe) {\n ignore(\n reader,\n 'invalid_type',\n source,\n 'Expected an image URL, an ImageObject with a url, or a list of them, received a reference to the recipe itself.',\n )\n } else {\n image = findImage(reader, target.node, target.path, true)\n }\n }\n reads.push([\n image,\n reader.warnings.length + reader.repeated - warnings,\n reader.deepest - source.length,\n source.length,\n ])\n reader.deepest = Math.max(reader.deepest, deepest)\n return image\n}\n\n/**\n * Reads servings and the yield from `recipeYield`'s values, and from the\n * comma-separated values in a string, as in \"4 servings, 24 cookies\". A bare\n * number equal to the yield's amount, as in WP Recipe Maker's `[\"28\", \"28-32\n * cookies\"]`, is the yield's count, not servings. The yield is the first one\n * with an amount, so \"One 9-inch pie, 8 slices\" yields 8 slices, but one whose\n * amount is a number comes before one whose amount is \"a\" or \"an\", so\n * `[\"a few\", \"24 cookies\"]` yields 24 cookies.\n */\nfunction readYield(\n reader: Reader,\n model: Record<string, unknown>,\n value: unknown,\n source: Path,\n): void {\n const batches = entriesOf(value, source)\n .flatMap(([entry, entrySource]) =>\n (typeof entry === 'string' ? entry.split(/,\\s+/) : [entry]).map((part) =>\n readBatch(reader, part, entrySource),\n ),\n )\n .filter((batch) => batch !== undefined)\n const yields = batches.filter((batch) => batch.yield !== undefined)\n const servings = batches.filter((batch) => batch.servings !== undefined)\n const kept =\n yields.find((batch) => !batch.article) ??\n yields.find((batch) => batch.article)\n const keptServings =\n servings.find((batch) => batch.worded) ??\n servings.find((batch) => batch.amount !== kept?.amount)\n\n for (const batch of servings) {\n if (\n keptServings &&\n batch.amount !== keptServings.amount &&\n (batch.worded || batch.amount !== kept?.amount)\n ) {\n warning(\n reader.warnings,\n 'ignored_value',\n batch.source,\n `Only one number of servings is read, ${quote(keptServings.label)}, so this one is ignored.`,\n )\n }\n }\n\n for (const batch of yields) {\n if (batch !== kept) {\n warning(\n reader.warnings,\n 'ignored_value',\n batch.source,\n `Only one yield is read, ${quote(kept!.label)}, so this one is ignored.`,\n )\n }\n }\n\n if (keptServings) {\n model.servings = keptServings.servings\n link(reader, ['servings'], keptServings.source, true)\n }\n if (kept) {\n model.yield = kept.yield\n link(reader, ['yield'], kept.source, true)\n }\n}\n\nfunction readBatch(\n reader: Reader,\n value: unknown,\n source: Path,\n): Batch | undefined {\n if (typeof value === 'number') {\n return { source, label: String(value), amount: value, servings: value }\n }\n\n if (typeof value === 'string') {\n const label = cleanText(value)\n\n if (!label) {\n return undefined\n }\n\n const text = label.replace(\n /^(?:(?:serves|servings?|yields?|makes)\\s*:?\\s*)?(?:about\\s+)?/i,\n '',\n )\n const match = matchAmount(text)\n\n if (!match || 'code' in match) {\n ignore(\n reader,\n match?.code ?? 'invalid_quantity',\n source,\n match?.message ??\n `Expected a batch such as \"24 cookies\" or \"3–4 loaves\", received ${describeValue(label)}.`,\n )\n return undefined\n }\n\n const amount =\n typeof match.amount === 'number' ? match.amount : match.amount.min\n const rest = match.rest.trim()\n\n return !rest || SERVINGS_WORD.test(rest)\n ? { source, label, amount, servings: match.amountText, worded: !!rest }\n : { source, label, amount, yield: text, article: /^an?\\s/i.test(text) }\n }\n\n const record = asRecord(value)\n const amount = toNumber(record?.value ?? record?.minValue)\n\n if (record && amount !== undefined) {\n const max = toNumber(record.maxValue)\n const unit =\n typeof record.unitText === 'string' ? cleanText(record.unitText) : ''\n const range = {\n amount,\n ...(max !== undefined && max !== amount && { max }),\n }\n const label = `${amount}${max !== amount && max ? `–${max}` : ''}${unit && ` ${unit}`}`\n\n return !unit || SERVINGS_WORD.test(unit)\n ? { source, label, amount, servings: range, worded: !!unit }\n : { source, label, amount, yield: { ...range, unit } }\n }\n\n if (!isAbsent(value)) {\n ignore(\n reader,\n 'invalid_type',\n source,\n `Expected a yield such as \"4 servings\" or \"24 cookies\", received ${describeValue(value)}.`,\n )\n }\n return undefined\n}\n\n/**\n * Reads an ISO 8601 duration. Zero, as in `PT0S`, counts as absent, and a time\n * longer than `Number.MAX_SAFE_INTEGER` minutes is ignored, as `toJsonLd`\n * ignores it.\n */\nfunction readTime(\n reader: Reader,\n value: unknown,\n source: Path,\n): number | undefined {\n if (isAbsent(value)) {\n return undefined\n }\n\n const minutes =\n typeof value === 'string' ? parseIsoDuration(cleanText(value)) : undefined\n\n if (minutes === undefined || minutes > Number.MAX_SAFE_INTEGER) {\n ignore(\n reader,\n 'invalid_duration',\n source,\n `Expected an ISO 8601 duration such as \"PT30M\", received ${describeValue(value)}${minutes === undefined ? '' : ', which is too long'}.`,\n )\n return undefined\n }\n\n return minutes > 0 ? minutes : undefined\n}\n\n/**\n * Reads `recipeIngredient` or `recipeInstructions`. A named `HowToSection` or\n * `ItemList` becomes a titled section, an unnamed or nested one adds its items\n * where it is, a `ListItem` stands for its `item`, and a string adds one item\n * per line.\n */\nfunction readList(\n reader: Reader,\n key: 'ingredients' | 'steps',\n value: unknown,\n source: Path,\n readItem: (\n reader: Reader,\n value: unknown,\n source: Path,\n ) => Item[] | undefined,\n expected: string,\n): unknown[] {\n const list: unknown[] = []\n link(reader, [key], source)\n\n const add = (\n items: unknown[],\n path: Path,\n entry: unknown,\n entrySource: Path,\n inSection: boolean,\n ): void => {\n if (isAbsent(entry)) {\n return\n }\n\n if (entrySource.length > MAX_DEPTH) {\n ignore(\n reader,\n 'invalid_type',\n entrySource,\n `Expected ${expected}, received ${describeValue(entry)} nested more than ${MAX_DEPTH} levels deep.`,\n )\n return\n }\n\n if (Array.isArray(entry)) {\n const elements = entriesOf(entry, entrySource)\n const positions = elements.map(([element]) =>\n toNumber(asRecord(element)?.position),\n )\n const order = [...elements.keys()]\n if (!positions.includes(undefined)) {\n order.sort((a, b) => positions[a]! - positions[b]!)\n }\n for (const i of order) {\n const [element, elementSource] = elements[i]!\n add(items, path, element, elementSource, inSection)\n }\n return\n }\n\n const record = asRecord(entry)\n const elements = [...entrySource, 'itemListElement']\n\n if (record?.itemListElement !== undefined && record.text === undefined) {\n const title =\n typeof record.name === 'string' ? cleanText(record.name) : ''\n\n if (title && !inSection) {\n const section = { title, items: [] as unknown[] }\n const sectionPath = [key, list.length]\n list.push(section)\n link(reader, sectionPath, entrySource)\n link(reader, [...sectionPath, 'title'], [...entrySource, 'name'])\n add(\n section.items,\n [...sectionPath, 'items'],\n record.itemListElement,\n elements,\n true,\n )\n } else {\n add(items, path, record.itemListElement, elements, inSection)\n }\n return\n }\n\n if (record && !isAbsent(record.item)) {\n add(items, path, record.item, [...entrySource, 'item'], inSection)\n return\n }\n\n const read = readItem(reader, entry, entrySource)\n\n if (!read) {\n ignore(\n reader,\n 'invalid_type',\n entrySource,\n `Expected ${expected}, received ${describeValue(entry)}.`,\n )\n return\n }\n\n for (const item of read) {\n const itemPath = [...path, items.length]\n items.push(item.value)\n link(reader, itemPath, item.source, true)\n\n for (const [field, fieldSource, droppable] of item.fields) {\n link(reader, [...itemPath, field], fieldSource, droppable)\n }\n }\n }\n\n add(list, [key], value, source, false)\n return list\n}\n\n/** Reads an ingredient line: text or a `PropertyValue`. */\nfunction readLine(\n reader: Reader,\n value: unknown,\n source: Path,\n): Item[] | undefined {\n const record = asRecord(value)\n const parts =\n typeof value === 'string'\n ? value\n : [record?.value, record?.unitText, record?.name ?? record?.text]\n .filter(\n (part) => typeof part === 'string' || typeof part === 'number',\n )\n .join(' ')\n\n return parts\n ? cleanLines(parts).map((line) => ({ value: line, source, fields: [] }))\n : undefined\n}\n\n/**\n * Reads a step: text or a `HowToStep`. A step's name is kept\n * only when it says something its text doesn't, unlike \"Step 1\" or the start\n * of the text.\n */\nfunction readStep(\n reader: Reader,\n value: unknown,\n source: Path,\n): Item[] | undefined {\n if (typeof value === 'string') {\n return cleanLines(value).map((line) => ({\n value: line,\n source,\n fields: [],\n }))\n }\n\n const record = asRecord(value)\n\n if (!record) {\n return undefined\n }\n\n const name = typeof record.name === 'string' ? cleanText(record.name) : ''\n const body = text(record.text) ?? name\n const image = readImage(reader, record.image, [...source, 'image'])\n const lead = name.replace(/(?:…|\\.\\.\\.)$/, '').trim()\n const hasName =\n typeof body === 'string' &&\n !body.startsWith(lead) &&\n !/^step\\s*\\d*[.:]?$/i.test(name)\n const fields: Item['fields'] = [\n ['text', [...source, name && body === name ? 'name' : 'text'], false],\n ]\n\n if (image) {\n fields.push(['image', image.source, true])\n }\n\n return [\n {\n value: {\n text: body,\n ...(hasName && { name }),\n ...(image && { image: image.url }),\n },\n source,\n fields,\n },\n ]\n}\n\nfunction readTools(reader: Reader, value: unknown, source: Path): unknown[] {\n const equipment: unknown[] = []\n link(reader, ['equipment'], source)\n\n for (const [entry, entrySource] of entriesOf(value, source)) {\n const record = asRecord(entry)\n const item = record\n ? {\n name: text(record.name),\n ...(record.requiredQuantity !== undefined && {\n quantity:\n toNumber(\n asRecord(record.requiredQuantity)?.value ??\n record.requiredQuantity,\n ) ?? record.requiredQuantity,\n }),\n ...(record.url !== undefined && { url: text(record.url) }),\n }\n : text(entry)\n\n if (item === undefined) {\n continue\n }\n\n const path = ['equipment', equipment.length]\n equipment.push(item)\n link(reader, path, entrySource, true)\n link(reader, [...path, 'name'], [...entrySource, 'name'])\n link(\n reader,\n [...path, 'quantity'],\n [...entrySource, 'requiredQuantity'],\n true,\n )\n link(reader, [...path, 'url'], [...entrySource, 'url'], true)\n }\n\n return equipment\n}\n\nfunction readNutrition(\n reader: Reader,\n value: unknown,\n source: Path,\n): Record<string, unknown> | undefined {\n link(reader, ['nutrition'], source)\n\n if (isAbsent(value)) {\n return undefined\n }\n\n const record = asRecord(value)\n\n if (!record) {\n ignore(\n reader,\n 'invalid_type',\n source,\n `Expected NutritionInformation, such as { \"calories\": \"250 kcal\" }, received ${describeValue(value)}.`,\n )\n return undefined\n }\n\n const nutrition: Record<string, unknown> = {}\n const keys = Object.keys(NUTRIENTS) as (keyof Nutrition)[]\n\n for (const [field, amount] of Object.entries(record)) {\n const key = keys.find((key) => NUTRIENTS[key] === field)\n\n if (key) {\n nutrition[key] = text(amount)\n link(reader, ['nutrition', key], [...source, field], true)\n } else if (!field.startsWith('@')) {\n ignore(reader, 'unknown_field', [...source, field], 'Unknown field.')\n }\n }\n\n return nutrition\n}\n\n/** Cleaned text, with empty text and `null` as absent. Other values pass through for `parseRecipe` to report. */\nfunction text(value: unknown): unknown {\n return typeof value === 'string'\n ? cleanText(value) || undefined\n : (value ?? undefined)\n}\n\nfunction toNumber(value: unknown): number | undefined {\n const number =\n typeof value === 'string' && value.trim() ? Number(value) : value\n return typeof number === 'number' && Number.isFinite(number)\n ? number\n : undefined\n}\n\nfunction isAbsent(value: unknown): boolean {\n return (\n value === undefined ||\n value === null ||\n (typeof value === 'string' && !value.trim())\n )\n}\n\nfunction ignore(\n reader: Reader,\n code: RecipeIssueCode,\n path: Path,\n message: string,\n): void {\n warning(reader.warnings, code, path, `${message} It is ignored.`)\n}\n\nfunction link(\n reader: Reader,\n path: Path,\n source: Path,\n droppable = false,\n): void {\n const key = JSON.stringify(path)\n reader.sources.set(key, source)\n if (droppable) {\n reader.droppable.add(key)\n }\n}\n\n/** The JSON-LD path of a path in the recipe input, through the longest linked prefix. */\nfunction sourceOf(reader: Reader, path: Path): Path {\n for (let n = path.length; n >= 0; n--) {\n const source = reader.sources.get(JSON.stringify(path.slice(0, n)))\n if (source) {\n return source\n }\n }\n return []\n}\n\nfunction compareOrder(a: number[], b: number[]): number {\n for (const [i, n] of a.entries()) {\n if (i === b.length) {\n return 1\n }\n const m = b[i]!\n if (n !== m) {\n return n - m\n }\n }\n return a.length - b.length\n}\n\nfunction droppableAt(reader: Reader, path: Path): Path | undefined {\n for (let n = path.length; n > 0; n--) {\n const at = path.slice(0, n)\n if (reader.droppable.has(JSON.stringify(at))) {\n return at\n }\n }\n return undefined\n}\n\n/**\n * Deletes a value from the recipe input, unless a value holding it is already\n * gone. A list keeps a hole, so later items keep their paths.\n */\nfunction remove(model: Record<string, unknown>, path: Path): void {\n const parent = path\n .slice(0, -1)\n .reduce<unknown>(\n (value, key) =>\n (value as Record<string | number, unknown> | undefined)?.[key],\n model,\n ) as Record<string | number, unknown> | undefined\n\n if (parent) {\n delete parent[path[path.length - 1]!]\n }\n}\n","import { describeValue, type RecipeIssue } from '../errors'\nimport { formatIngredient } from '../format/ingredient'\nimport { round } from '../format/number'\nimport { formatQuantity } from '../format/quantity'\nimport { formatServings, formatYield } from '../format/servings'\nimport { hasOwn, isRecord, warning } from '../issues'\nimport { multiply } from '../quantity/scale'\nimport { NUTRIENT_UNITS, type NutrientKey } from '../recipe/nutrient-units'\nimport type { Nutrition, Recipe } from '../recipe/types'\nimport { isNative, type ResolvedIngredient, resolveRecipe } from '../resolve'\nimport type { System } from '../units/registry'\nimport { NUTRIENTS } from './nutrients'\nimport type {\n SchemaOrgHowToSection,\n SchemaOrgHowToStep,\n SchemaOrgNutritionInformation,\n SchemaOrgRecipe,\n ToJsonLdOptions,\n ToJsonLdResult,\n} from './types'\n\n/**\n * Writes a recipe as schema.org Recipe JSON-LD, for search engines' recipe\n * results. Writes it at its own servings and in `recipe.system`, else metric,\n * unless the options say otherwise; invalid options fall back to these, as in\n * `resolveRecipe`. Never throws for an unchanged recipe from `parseRecipe` or\n * `fromJsonLd`, though an error thrown by a getter or proxy in the options\n * passes through.\n *\n * `data` is plain JSON when `extra` is. Write it into a\n * `<script type=\"application/ld+json\">` tag with `<` escaped as `\\u003c`, so\n * recipe text can't end the tag. An `image` passed in `extra` is a URL; for an\n * `ImageObject` or several images, spread `data` into a new object with your\n * own `image`.\n *\n * Ingredient lines read back with `parseIngredientLine`: a quantity's\n * alternatives follow it in parentheses, as in `\"1 ½ cups (190 g) flour,\n * sifted\"` and `\"2 eggs (100 g)\"`, and an optional ingredient ends\n * `\" (optional)\"`. schema.org has no place for ingredient section titles, the\n * recipe's notes, custom times, an ingredient's `url`, or equipment beyond its\n * name, so they aren't written. Reading `data` back with `fromJsonLd` gives a\n * similar recipe, not the same one.\n *\n * `warnings` names the fields Google requires for recipe results that `data`\n * lacks, with paths that use the schema.org names: `image`, and `recipeYield`\n * when there is nutrition. A time longer than `Number.MAX_SAFE_INTEGER`\n * minutes is left out, as `fromJsonLd` leaves it out, and so is a `NaN` time,\n * each with an `invalid_duration` warning at its path in the recipe, such as\n * `['times', 'cook']`.\n *\n * @example\n * const { data } = toJsonLd(recipe, { url: 'https://example.com/pancakes' })\n * data.recipeYield // ['4', '4 servings']\n * data.recipeIngredient // ['1 ½ cups (190 g) flour, sifted', '2 eggs', 'salt, to taste']\n */\nexport function toJsonLd(\n recipe: Recipe,\n options?: ToJsonLdOptions,\n): ToJsonLdResult {\n const { servings, system, url, extra } = options ?? {}\n const resolved = resolveRecipe(recipe, { servings, system })\n // `s`, so a line break doesn't end the fragment.\n const page = typeof url === 'string' ? url.replace(/#.*/s, '') : undefined\n const yields = [\n ...(resolved.servings ? servingsText(resolved.servings) : []),\n ...(resolved.yield\n ? [formatYield(resolved.yield, { fractions: false })]\n : []),\n ]\n const ingredients = resolved.ingredients.flatMap(({ items }) =>\n items.map((item) => ingredientLine(item, resolved.scale, resolved.system)),\n )\n const steps = resolved.steps.flatMap(\n ({ title, items }): (SchemaOrgHowToStep | SchemaOrgHowToSection)[] => {\n const howToSteps = items.map((step): SchemaOrgHowToStep => ({\n '@type': 'HowToStep',\n ...(step.name !== undefined && { name: step.name }),\n text: step.text,\n ...(step.image !== undefined && { image: step.image }),\n ...(page !== undefined && {\n // encodeURIComponent throws on a lone surrogate. With the u flag,\n // \\p{Cs} matches only those, as a pair reads as one code point.\n url: `${page}#${encodeURIComponent(step.id.replace(/\\p{Cs}/gu, '\\uFFFD'))}`,\n }),\n }))\n return title === undefined || howToSteps.length === 0\n ? howToSteps\n : [\n {\n '@type': 'HowToSection',\n name: title,\n itemListElement: howToSteps,\n },\n ]\n },\n )\n const { description, image, times, equipment, nutrition } = recipe\n const warnings: RecipeIssue[] = []\n\n const written: SchemaOrgRecipe = {\n '@context': 'https://schema.org',\n '@type': 'Recipe',\n name: recipe.name,\n ...(description !== undefined && { description }),\n ...(image !== undefined && { image }),\n ...(yields.length > 0 && { recipeYield: yields.map(plainSpaces) }),\n ...duration(warnings, 'prep', times.prep),\n ...duration(warnings, 'cook', times.cook),\n ...duration(warnings, 'total', times.total),\n ...(ingredients.length > 0 && { recipeIngredient: ingredients }),\n ...(steps.length > 0 && { recipeInstructions: steps }),\n ...(equipment.length > 0 && { tool: equipment.map(({ name }) => name) }),\n ...(nutrition !== undefined && {\n nutrition: nutritionInformation(nutrition),\n }),\n }\n const data: SchemaOrgRecipe = {\n ...written,\n ...Object.fromEntries(\n Object.entries(isRecord(extra) ? extra : {}).filter(\n ([field, value]) => value !== undefined && !hasOwn(written, field),\n ),\n ),\n }\n\n if (data.image === undefined) {\n warning(\n warnings,\n 'missing_field',\n ['image'],\n 'Add an image. Google requires one for recipe results.',\n )\n }\n if (data.nutrition !== undefined && data.recipeYield === undefined) {\n warning(\n warnings,\n 'missing_field',\n ['recipeYield'],\n 'Add servings or a yield. Google requires one with nutrition, which is for one serving.',\n )\n }\n\n return { data, warnings }\n}\n\n/** `[\"4\", \"4 servings\"]`, in decimals, so the text reads back as a number. */\nfunction servingsText(servings: {\n amount: number\n max?: number | undefined\n}): string[] {\n const amount = formatServings(servings, { fractions: false })\n const word =\n servings.amount === 1 && servings.max === undefined ? 'serving' : 'servings'\n return [amount, `${amount} ${word}`]\n}\n\n/**\n * The line as `formatIngredient` writes it, with the quantity's alternatives\n * in parentheses after it, or after the name for a bare count, and\n * \" (optional)\" at the end.\n */\nfunction ingredientLine(\n item: ResolvedIngredient,\n scale: number,\n system: System,\n): string {\n const { ingredient, origin } = item\n const { quantity, name, note } = formatIngredient(item)\n const authored = ingredient.quantity\n ? [ingredient.quantity, ...ingredient.equivalents]\n : []\n const shown =\n origin === 'authored'\n ? 0\n : origin === 'equivalent'\n ? 1 + ingredient.equivalents.findIndex((q) => isNative(q, system))\n : -1\n const alternatives = authored\n .filter((_, i) => i !== shown)\n .map((q) => formatQuantity(scale === 1 ? q : multiply(q, scale)))\n .join('; ')\n const inParentheses = alternatives && ` (${alternatives})`\n const head =\n quantity === undefined\n ? name\n : item.quantity?.unit === undefined\n ? `${quantity} ${name}${inParentheses}`\n : `${quantity}${inParentheses} ${name}`\n\n return plainSpaces(\n `${head}${note ? `, ${note}` : ''}${ingredient.optional ? ' (optional)' : ''}`,\n )\n}\n\n/**\n * An ISO 8601 duration to the second, or nothing for an absent or zero time,\n * or one it can't write: `NaN`, which `parseRecipe` rejects but a recipe built\n * by hand can hold, or a time longer than `Number.MAX_SAFE_INTEGER` minutes.\n * Below that bound, the hours fit in a safe integer, so they print in plain\n * digits.\n */\nfunction duration(\n warnings: RecipeIssue[],\n key: 'prep' | 'cook' | 'total',\n minutes: number | undefined,\n): Partial<SchemaOrgRecipe> {\n if (minutes === undefined) {\n return {}\n }\n if (Number.isNaN(minutes) || minutes > Number.MAX_SAFE_INTEGER) {\n warning(\n warnings,\n 'invalid_duration',\n ['times', key],\n `Expected minutes such as 30, received ${describeValue(minutes)}${Number.isNaN(minutes) ? '' : ', which is too long'}. It is ignored.`,\n )\n return {}\n }\n\n const seconds = Math.round(minutes * 60)\n\n if (seconds <= 0) {\n return {}\n }\n\n const parts = [\n [Math.floor(seconds / 3600), 'H'],\n [Math.floor(seconds / 60) % 60, 'M'],\n [seconds % 60, 'S'],\n ] as const\n\n return {\n [`${key}Time`]: `PT${parts.map(([n, unit]) => (n ? `${n}${unit}` : '')).join('')}`,\n }\n}\n\nfunction nutritionInformation(\n nutrition: Nutrition,\n): SchemaOrgNutritionInformation {\n const information: SchemaOrgNutritionInformation = {\n '@type': 'NutritionInformation',\n }\n\n for (const key of Object.keys(NUTRIENTS) as (keyof Nutrition)[]) {\n const value = nutrition[key]\n if (value !== undefined) {\n information[NUTRIENTS[key]] =\n typeof value === 'string'\n ? value\n : `${round(value, 3)} ${NUTRIENT_UNITS[key as NutrientKey]}`\n }\n }\n\n return information\n}\n\nfunction plainSpaces(text: string): string {\n return text.replace(/\\u00A0/g, ' ')\n}\n"]}
@@ -5,18 +5,27 @@ import { ParseResult, Recipe, System, RecipeIssue } from './index.cjs';
5
5
  * `<script type="application/ld+json">` tags, without a DOM. Pass one to
6
6
  * `fromJsonLd`.
7
7
  *
8
- * Reads arrays and `@graph`, as Yoast and WP Recipe Maker write them, and a
9
- * Recipe in a node's `mainEntity`, and matches a node whose `@type` is or
10
- * includes `"Recipe"`. A tag whose JSON doesn't parse is retried with the raw
11
- * line breaks and tabs inside its strings escaped, as real pages have them,
12
- * and skipped if it still doesn't. A tag inside an HTML comment is skipped,
13
- * and a `<!--` in an attribute value or in a `style` or `textarea` element is
14
- * text, as in a browser. A quote starts an attribute value only right after
15
- * `=`, so a stray one, as in `content="a 9" pan"`, doesn't hide later tags. A
16
- * Recipe node with the `@id` of an earlier one is returned once, where the
17
- * first appears. When the first holds only keywords, such as a `mainEntity`
18
- * of `{ "@type": "Recipe", "@id": "#recipe" }`, the later node is returned in
19
- * its place. An empty `@id` is no `@id`, so it merges nothing.
8
+ * Reads arrays and `@graph`, as Yoast and WP Recipe Maker write them, and the
9
+ * `mainEntity` of a node there, up to 32 levels deep, and matches a node whose
10
+ * `@type` is or includes `"Recipe"`. When that finds none, it also reads each
11
+ * `ItemList` in those places, as a roundup page lists its recipes, taking each
12
+ * Recipe in its `itemListElement`, or in a `ListItem`'s `item` there. A
13
+ * `ListItem` with only a `url` is skipped: fetch that page and call
14
+ * `findRecipeJsonLd` on it. A `mainEntity`, or an entry of a `mainEntity`
15
+ * array, that is neither a Recipe nor an `ItemList` is skipped with everything
16
+ * in it, and a Recipe anywhere else, such as inside another Recipe or in a list
17
+ * inside a `ListItem` or another list, isn't found.
18
+ *
19
+ * A tag whose JSON doesn't parse is retried with the raw line breaks and tabs
20
+ * inside its strings escaped, as real pages have them, and skipped if it still
21
+ * doesn't. A tag inside an HTML comment is skipped, and a `<!--` in an
22
+ * attribute value or in a `style` or `textarea` element is text, as in a
23
+ * browser. A quote starts an attribute value only right after `=`, so a stray
24
+ * one, as in `content="a 9" pan"`, doesn't hide later tags. A Recipe node with
25
+ * the `@id` of an earlier one is returned once, where the first appears. When
26
+ * the first holds only keywords, such as a `mainEntity` of
27
+ * `{ "@type": "Recipe", "@id": "#recipe" }`, the later node is returned in its
28
+ * place. An empty `@id` is no `@id`, so it merges nothing.
20
29
  *
21
30
  * In each Recipe node returned, an image that is an `@id` reference to a node
22
31
  * at the top level of the JSON-LD, or reached from there through arrays and
@@ -29,7 +38,8 @@ import { ParseResult, Recipe, System, RecipeIssue } from './index.cjs';
29
38
  * holds, stay as the page wrote them.
30
39
  *
31
40
  * @param html - The page's HTML, such as `await response.text()`.
32
- * @returns Every Recipe node, in document order, or `[]` when there are none.
41
+ * @returns The Recipe nodes it finds, in document order, or `[]` when there
42
+ * are none.
33
43
  * @throws {RecipeBookError} `invalid_argument` when `html` isn't a string.
34
44
  *
35
45
  * @example
@@ -136,10 +146,11 @@ type FromJsonLdResult = ParseResult<Recipe> & {
136
146
 
137
147
  /**
138
148
  * Reads a schema.org Recipe from JSON-LD, as recipe sites publish it for
139
- * search engines: a Recipe node, or an array, `@graph`, or `mainEntity` that
140
- * holds one, such as a node from `findRecipeJsonLd` or `JSON.parse` of a
141
- * script tag. Never throws for bad data; an error thrown by a getter or proxy
142
- * in the input passes through.
149
+ * search engines: a Recipe node, or an array, `@graph`, `mainEntity`, or
150
+ * `ItemList` that holds one, such as a node from `findRecipeJsonLd` or
151
+ * `JSON.parse` of a script tag. An `ItemList` is read only when no other
152
+ * Recipe is found, as in `findRecipeJsonLd`. Never throws for bad data; an
153
+ * error thrown by a getter or proxy in the input passes through.
143
154
  *
144
155
  * Every string has its tags removed, then its HTML entities decoded, so an
145
156
  * encoded tag such as `&lt;b&gt;` stays as text. Ingredient lines are read
@@ -154,8 +165,10 @@ type FromJsonLdResult = ParseResult<Recipe> & {
154
165
  * text, or a problem remains that leaving a value out can't fix.
155
166
  *
156
167
  * @returns The recipe or the error, and `extra`: the node's fields the recipe
157
- * doesn't model, such as `author` and `keywords`, as they were. Pass `extra`
158
- * to `toJsonLd` to write them back. It is `{}` when no Recipe node is found.
168
+ * doesn't model, such as `author` and `keywords`, as they were. A field that
169
+ * nests more than 32 levels deep, counted from the top of `input`, is left
170
+ * out, with a warning. Pass `extra` to `toJsonLd` to write them back. It is
171
+ * `{}` when no Recipe node is found.
159
172
  *
160
173
  * @example
161
174
  * const result = fromJsonLd(node)
@@ -163,7 +176,7 @@ type FromJsonLdResult = ParseResult<Recipe> & {
163
176
  * console.error(result.error.message)
164
177
  * // Recipe has 1 problem:
165
178
  * // ✖ name Add a name for the recipe.
166
- * // See https://recipe-book.siraj.page/errors/invalid_recipe
179
+ * // See https://recipe-book.siraj.page/errors/invalid_recipe/
167
180
  * return
168
181
  * }
169
182
  * result.data.ingredients[0].items[0] // { id: 'flour', name: 'flour', quantity: { amount: 2, unit: 'cup' }, … }
@@ -176,7 +189,8 @@ declare function fromJsonLd(input: unknown): FromJsonLdResult;
176
189
  * results. Writes it at its own servings and in `recipe.system`, else metric,
177
190
  * unless the options say otherwise; invalid options fall back to these, as in
178
191
  * `resolveRecipe`. Never throws for an unchanged recipe from `parseRecipe` or
179
- * `fromJsonLd`.
192
+ * `fromJsonLd`, though an error thrown by a getter or proxy in the options
193
+ * passes through.
180
194
  *
181
195
  * `data` is plain JSON when `extra` is. Write it into a
182
196
  * `<script type="application/ld+json">` tag with `<` escaped as `\u003c`, so