<title>Parsing Schema Data with node-html-parser</title>
<link href="https://wingmatt.dev/posts/parsing-schema-data-node-html-parser/"/>
<updated>2024-09-11T02:00:59Z</updated>
<id>https://wingmatt.dev/posts/parsing-schema-data-node-html-parser/</id>
<content type="html"><p>Did you know that there's a whole JSON object schema for providing machine-readable information about the contents of your website? Google uses the data in these objects to fill out search results and build rich snippets.</p>
<p>Here's a secret - it can power other stuff too. For example, I'm building a Node JS web app that includes the ability to plug a URL in and get a list of that recipe's ingredients.</p>
<p>Want to start parsing data yourself? Read on!</p>
<h2 id="challenges" tabindex="-1">Challenges<a class="tdbc-anchor" href="https://wingmatt.dev/posts/parsing-schema-data-node-html-parser/#challenges" aria-hidden="true">#</a></h2>
<ul>
<li>Fetching the raw HTML</li>
<li>Making the Raw HTML Parse-able</li>
<li>Finding the right Schema object out of all of the ones on the page</li>
<li>Grabbing the right data out of that schema object</li>
</ul>
<h2 id="fetching-the-raw-html" tabindex="-1">Fetching the raw HTML<a class="tdbc-anchor" href="https://wingmatt.dev/posts/parsing-schema-data-node-html-parser/#fetching-the-raw-html" aria-hidden="true">#</a></h2>
<p>First things first — we want to be able to fetch the HTML code of whatever link we end up pasting into our app.</p>
<p>There are a lot of ways to do this in Node JS. For this tutorial, we'll be using the <a href="https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch">native JavaScript <code>fetch</code> API</a>.</p>
<p>With that in mind, here's how to make <code>fetch</code> happen:</p>
<pre class="language-jsx"><code class="language-jsx"><span class="token comment">// Use an async function so we can wait for the fetch to complete</span><br /><span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">getHtmlStringFromUrl</span><span class="token punctuation">(</span><span class="token parameter">url</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">return</span> <span class="token keyword">await</span> <span class="token function">fetch</span><span class="token punctuation">(</span>url<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">response</span><span class="token punctuation">)</span> <span class="token operator">=></span><br /> response<span class="token punctuation">.</span><span class="token function">text</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">responseHtml</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br /> <span class="token comment">// responseHtml is a huge string containing the entire web page HTML.</span><br /> <span class="token comment">// In the next section, we'll process it into something we can work with</span><br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><br /> <span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
<h2 id="making-the-raw-html-parse-able" tabindex="-1">Making the Raw HTML Parse-able<a class="tdbc-anchor" href="https://wingmatt.dev/posts/parsing-schema-data-node-html-parser/#making-the-raw-html-parse-able" aria-hidden="true">#</a></h2>
<p>When we first fetch a URL and grab the response body, it's one enormous text string. There's HTML in there, but we can't really work with it yet. We need to plug this string into an HTML parser that will let us use DOM selectors to pick out the useful bits.</p>
<p>node-html-parser is my personal choice for this. It lets us use all the usual JavaScript DOM selector methods, and it's pretty fast too. Add it to your project with this terminal command:</p>
<p><code>yarn add node-html-parser</code></p>
<p>Then import the parse command from the package into the JS file where you'll be using it:</p>
<p><code>import { parse } from "node-html-parser";</code></p>
<p>Now we can take the response body string, plug it into our parser, and get to the real fun:</p>
<pre class="language-jsx"><code class="language-jsx"><span class="token keyword">import</span> <span class="token punctuation">{</span> parse <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">"node-html-parser"</span><span class="token punctuation">;</span><br /><br /><span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">getHtmlDocumentFromUrl</span><span class="token punctuation">(</span><span class="token parameter">url</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">return</span> <span class="token keyword">await</span> <span class="token function">fetch</span><span class="token punctuation">(</span>url<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">response</span><span class="token punctuation">)</span> <span class="token operator">=></span><br /> response<span class="token punctuation">.</span><span class="token function">text</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">responseHtml</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br /> <span class="token comment">// parse the HTML string into a DOM-like object we can navigate</span><br /> <span class="token keyword">const</span> document <span class="token operator">=</span> <span class="token function">parse</span><span class="token punctuation">(</span>responseHtml<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><br /> <span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
<p>That's all we need to get the HTML into something we can sift through! The returned object has all the same methods as a typical document object, such as querySelector, getElementByID, and so on.</p>
<p>So, how do we work it to find the structured data we're looking for?</p>
<h2 id="finding-the-right-schema-objects" tabindex="-1">Finding the right Schema object(s)<a class="tdbc-anchor" href="https://wingmatt.dev/posts/parsing-schema-data-node-html-parser/#finding-the-right-schema-objects" aria-hidden="true">#</a></h2>
<p>The nice thing about working with structured data is that you can make some assumptions about the data you're processing, because it <em>has</em> to be structured in a way that web crawlers can understand to be useful.</p>
<p>The structured data Schema objects we're looking for are going to be found within <code>ld+json</code> script tags. Now that we've DOMified the HTML, we can run queries on it like this:</p>
<pre class="language-jsx"><code class="language-jsx"><span class="token keyword">import</span> <span class="token punctuation">{</span> parse <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">"node-html-parser"</span><span class="token punctuation">;</span><br /><br /><span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">getSchemaNodeListFromUrl</span><span class="token punctuation">(</span><span class="token parameter">url</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">return</span> <span class="token keyword">await</span> <span class="token function">fetch</span><span class="token punctuation">(</span>url<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">response</span><span class="token punctuation">)</span> <span class="token operator">=></span><br /> response<span class="token punctuation">.</span><span class="token function">text</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">responseHtml</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br /> <span class="token keyword">const</span> document <span class="token operator">=</span> <span class="token function">parse</span><span class="token punctuation">(</span>responseHtml<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token comment">// Create a NodeList of elements containing the page's structured data JSON. So close to useful!</span><br /> <span class="token keyword">const</span> structuredData <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">querySelectorAll</span><span class="token punctuation">(</span><span class="token string">'script[type="application/ld+json"]'</span><span class="token punctuation">)</span><br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><br /> <span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
<p>That will give us a NodeList of all the matching elements. That's close to perfect, but it's not a true array and could give us errors if we try to treat it like one (which we will soon). So let's turn it into an array:</p>
<pre class="language-jsx"><code class="language-jsx"><span class="token keyword">import</span> <span class="token punctuation">{</span> parse <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">"node-html-parser"</span><span class="token punctuation">;</span><br /><br /><span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">getSchemaArrayFromUrl</span><span class="token punctuation">(</span><span class="token parameter">url</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">return</span> <span class="token keyword">await</span> <span class="token function">fetch</span><span class="token punctuation">(</span>url<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">response</span><span class="token punctuation">)</span> <span class="token operator">=></span><br /> response<span class="token punctuation">.</span><span class="token function">text</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">responseHtml</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br /> <span class="token keyword">const</span> document <span class="token operator">=</span> <span class="token function">parse</span><span class="token punctuation">(</span>responseHtml<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token comment">// Create an ARRAY of elements containing the page's structured data JSON. Just one more step!</span><br /> <span class="token keyword">const</span> structuredData <span class="token operator">=</span> Array<span class="token punctuation">.</span><span class="token function">from</span><span class="token punctuation">(</span>document<span class="token punctuation">.</span><span class="token function">querySelectorAll</span><span class="token punctuation">(</span><span class="token string">'script[type="application/ld+json"]'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><br /> <span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /></code></pre>
<p>Now we have an array of structured data nodes. In a way, we're back to square one with data that is <em>so close</em> to being useful. To make it useful, we need to grab the innerHTML of each node, which will come out as a big string. Then we can parse that into ✨real JSON!✨</p>
<pre class="language-jsx"><code class="language-jsx"><br /><span class="token keyword">import</span> <span class="token punctuation">{</span> parse <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">"node-html-parser"</span><span class="token punctuation">;</span><br /><br /><span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">getJsonFromUrl</span><span class="token punctuation">(</span><span class="token parameter">url</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">return</span> <span class="token keyword">await</span> <span class="token function">fetch</span><span class="token punctuation">(</span>url<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">response</span><span class="token punctuation">)</span> <span class="token operator">=></span><br /> response<span class="token punctuation">.</span><span class="token function">text</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">responseHtml</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br /> <span class="token keyword">const</span> document <span class="token operator">=</span> <span class="token function">parse</span><span class="token punctuation">(</span>responseHtml<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token keyword">const</span> structuredData <span class="token operator">=</span> Array<span class="token punctuation">.</span><span class="token function">from</span><span class="token punctuation">(</span>document<span class="token punctuation">.</span><span class="token function">querySelectorAll</span><span class="token punctuation">(</span><span class="token string">'script[type="application/ld+json"]'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token comment">// Get an array containing the contents of each structured data element on the page. This is the ✨useful stuff✨</span><br /> <span class="token keyword">const</span> structuredDataJson <span class="token operator">=</span> structuredData<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">node</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token constant">JSON</span><span class="token punctuation">.</span><span class="token function">parse</span><span class="token punctuation">(</span>node<span class="token punctuation">.</span>innerHTML<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">flat</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token comment">// We also flatten the array with .flat() to handle how some sites structure their schema data. See epilogue for more info</span><br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><br /> <span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
<p>Whoa, look at us. We've got the real, actual JSON object now. If you log structuredDataJson to your console, you'll see an array of structured data objects! Huzzah 🎉</p>
<p>But of course, we're not done yet! There is likely to be a ton of data you don't need in this array, in addition to whatever you're actually looking for.</p>
<h2 id="grabbing-the-right-data-out-of-that-schema-object" tabindex="-1">Grabbing the right data out of that schema object<a class="tdbc-anchor" href="https://wingmatt.dev/posts/parsing-schema-data-node-html-parser/#grabbing-the-right-data-out-of-that-schema-object" aria-hidden="true">#</a></h2>
<p>You're looking for some sort of specific data out of these objects. In my case, I'm looking for the list of <a href="https://schema.org/recipeIngredient">ingredients</a> within the <a href="https://schema.org/Recipe">Recipe object</a>. So, now that we have actual JSON, we can view certain properties and use it to whittle our array down to a single, useful, piece of data:</p>
<pre class="language-jsx"><code class="language-jsx"><span class="token keyword">import</span> <span class="token punctuation">{</span> parse <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">"node-html-parser"</span><span class="token punctuation">;</span><br /><br /><span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">getIngredientsFromUrl</span><span class="token punctuation">(</span><span class="token parameter">url</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">return</span> <span class="token keyword">await</span> <span class="token function">fetch</span><span class="token punctuation">(</span>url<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">response</span><span class="token punctuation">)</span> <span class="token operator">=></span><br /> response<span class="token punctuation">.</span><span class="token function">text</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">responseHtml</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br /> <span class="token keyword">const</span> document <span class="token operator">=</span> <span class="token function">parse</span><span class="token punctuation">(</span>responseHtml<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token keyword">const</span> structuredData <span class="token operator">=</span> Array<span class="token punctuation">.</span><span class="token function">from</span><span class="token punctuation">(</span>document<span class="token punctuation">.</span><span class="token function">querySelectorAll</span><span class="token punctuation">(</span><span class="token string">'script[type="application/ld+json"]'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token keyword">const</span> structuredDataJson <span class="token operator">=</span> structuredData<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">node</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token constant">JSON</span><span class="token punctuation">.</span><span class="token function">parse</span><span class="token punctuation">(</span>node<span class="token punctuation">.</span>innerHTML<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">flat</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token comment">// Look for a Recipe schema and return its ingredients if it exists </span><br /> <span class="token keyword">const</span> recipeData <span class="token operator">=</span> structuredDataJson<span class="token punctuation">.</span><span class="token function">find</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">schema</span><span class="token punctuation">)</span> <span class="token operator">=></span> schema<span class="token punctuation">[</span><span class="token string">"@type"</span><span class="token punctuation">]</span> <span class="token operator">==</span> <span class="token string">"Recipe"</span><span class="token punctuation">)</span><br /> <span class="token keyword">if</span> <span class="token punctuation">(</span>recipeData<span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">return</span> recipeData<span class="token punctuation">.</span>recipeIngredient<br /> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">return</span> <span class="token keyword">null</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><br /> <span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
<p>If one of the structured data objects is for a Recipe, we'll get the array of ingredients we're looking for. If not, the function will return <code>null</code> so we know it failed to find what we were looking for.</p>
<p>That's it! We've parsed the HTML into JSON into the actual thing we need 🎉</p>
<h2 id="conclusion" tabindex="-1">Conclusion<a class="tdbc-anchor" href="https://wingmatt.dev/posts/parsing-schema-data-node-html-parser/#conclusion" aria-hidden="true">#</a></h2>
<p>At this point, you have a function that takes a URL and returns an array of whatever information you're looking for. This general process can be used to do a whole lot of interesting stuff depending on what you're grabbing. <a href="https://codesandbox.io/s/nextjs-recipe-schema-data-parsing-example-tblx7">Here's an example I put together to grab the ingredients within a recipe page.</a></p>
<p><a href="https://schema.org/docs/schemas.html">Here are some of the most common schemas out there</a> for inspiration. In my case, I'm parsing recipe ingredients so I can see if they're in my pantry, and add them to my shopping list if they're not.</p>
<p>How about you? If you end up using this process to parse website data in your web app, let me know what you're doing!</p>
<h2 id="epilogue-handling-edge-cases-with-the-flat-method" tabindex="-1">Epilogue: Handling Edge Cases with the flat() method<a class="tdbc-anchor" href="https://wingmatt.dev/posts/parsing-schema-data-node-html-parser/#epilogue-handling-edge-cases-with-the-flat-method" aria-hidden="true">#</a></h2>
<p>As mentioned earlier, structured data has to be readable by web crawlers to be useful, so we can make some assumptions about what it will look like. Still, we're ultimately trusting people to build their websites according to a certain convention, so you still might run into some issues across different websites and pages.</p>
<p>When I was testing my recipe parser, I ran into a few websites that structured their data in non-standard ways, which caused some trouble early on. The most common issue I found was that some sites would wrap their schema JSON within an array. This prevented my array.find() method from finding any of the data within the nested array.</p>
<p>In my production code, I handle this by flattening the parsed JSON to remove any nested arrays before I start looking for specific data. Here's what that looks like with the example code we've been using:</p>
<pre class="language-jsx"><code class="language-jsx"><span class="token keyword">import</span> <span class="token punctuation">{</span> parse <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">"node-html-parser"</span><span class="token punctuation">;</span><br /><br /><span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">getHtmlFromUrl</span><span class="token punctuation">(</span><span class="token parameter">url</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">return</span> <span class="token keyword">await</span> <span class="token function">fetch</span><span class="token punctuation">(</span>url<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">response</span><span class="token punctuation">)</span> <span class="token operator">=></span><br /> response<span class="token punctuation">.</span><span class="token function">text</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">responseHtml</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br /> <span class="token keyword">const</span> document <span class="token operator">=</span> <span class="token function">parse</span><span class="token punctuation">(</span>responseHtml<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token keyword">const</span> structuredData <span class="token operator">=</span> Array<span class="token punctuation">.</span><span class="token function">from</span><span class="token punctuation">(</span>document<span class="token punctuation">.</span><span class="token function">querySelectorAll</span><span class="token punctuation">(</span><span class="token string">'script[type="application/ld+json"]'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token comment">// Adding .flat() to the line below handles the most common edge cases I've found so far! </span><br /> <span class="token keyword">const</span> structuredDataJson <span class="token operator">=</span> structuredData<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">node</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token constant">JSON</span><span class="token punctuation">.</span><span class="token function">parse</span><span class="token punctuation">(</span>node<span class="token punctuation">.</span>innerHTML<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">flat</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token keyword">const</span> recipeData <span class="token operator">=</span> structuredDataJson<span class="token punctuation">.</span><span class="token function">find</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">schema</span><span class="token punctuation">)</span> <span class="token operator">=></span> schema<span class="token punctuation">[</span><span class="token string">"@type"</span><span class="token punctuation">]</span> <span class="token operator">==</span> <span class="token string">"Recipe"</span><span class="token punctuation">)</span><br /> <span class="token keyword">if</span> <span class="token punctuation">(</span>recipeData<span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token keyword">return</span> recipeData<span class="token punctuation">.</span>recipeIngredient<br /> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">return</span> <span class="token keyword">null</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><br /> <span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
</content>