diff --git a/_config/eleventy-plugin-cooklang.js b/_config/eleventy-plugin-cooklang.js new file mode 100644 index 0000000..13aeb3d --- /dev/null +++ b/_config/eleventy-plugin-cooklang.js @@ -0,0 +1,81 @@ +import { Recipe, Parser, getImageURL } from '@cooklang/cooklang-ts'; +import fs from 'fs'; + +let config = {} +export default function (eleventyConfig, pluginOptions) { + config = pluginOptions; + eleventyConfig.addTemplateFormats('cook'); + eleventyConfig.addExtension("cook", cookExtension); +}; + +const cookExtension = { + getData: async function (inputPath) { + const content = fs.readFileSync(inputPath, "utf-8").split("---")[2]; + + // Parse recipe using cooklang-ts + const recipe = new Recipe(content); + + let steps = []; + let ingredients = []; + let cookware = []; + const recipeTags = recipe?.metadata?.tags?.split(",") || []; + + function getStepTokenHTML(token) { + const { quantity, units, name, value, type } = token; + let tagContent = ""; + + if (token.type == "timer") { + tagContent = `${quantity} ${units}`; + } else { + tagContent = token.name || token.value; + } + + if (config.outputHtml) { + return `${tagContent}`; + } else { + return `${tagContent}`; + } + } + + recipe.steps.forEach((stepTokens, i) => { + if (!steps[i]) steps[i] = []; + + stepTokens.forEach((token) => { + if (token.type == "ingredient") { + let { name, quantity, units } = token; + + if ( + config.limitIngredientDecimals && + !isNaN(config.limitIngredientDecimals) + ) { + const decimalPlaces = parseInt(config.limitIngredientDecimals); + // Parsing float twice removes any trailing 0s + quantity = parseFloat(parseFloat(quantity).toFixed(decimalPlaces)); + } + ingredients.push({ name, quantity, units }); + } + + if (token.type == "cookware") { + const { name } = token; + cookware.push({ name }); + } + + steps[i].push(getStepTokenHTML(token)); + }); + }); + + return { + recipe, + steps, + ingredients, + cookware, + recipeTags, + }; + }, + compile: async (inputContent) => { + // We probably don't need the raw content but it's here if we want + return async () => { + return inputContent; + }; + }, +}; \ No newline at end of file diff --git a/eleventy.config.js b/eleventy.config.js index 78fe2da..2e60f59 100644 --- a/eleventy.config.js +++ b/eleventy.config.js @@ -8,6 +8,7 @@ import Image from '@11ty/eleventy-img'; import util from 'util'; import eleventyNavigationPlugin from "@11ty/eleventy-navigation"; +import eleventyCooklang from "./_config/eleventy-plugin-cooklang.js"; const emojiRegex = /[\u{1f300}-\u{1f5ff}\u{1f900}-\u{1f9ff}\u{1f600}-\u{1f64f}\u{1f680}-\u{1f6ff}\u{2600}-\u{26ff}\u{2700}-\u{27bf}\u{1f1e6}-\u{1f1ff}\u{1f191}-\u{1f251}\u{1f004}\u{1f0cf}\u{1f170}-\u{1f171}\u{1f17e}-\u{1f17f}\u{1f18e}\u{3030}\u{2b50}\u{2b55}\u{2934}-\u{2935}\u{2b05}-\u{2b07}\u{2b1b}-\u{2b1c}\u{3297}\u{3299}\u{303d}\u{00a9}\u{00ae}\u{2122}\u{23f3}\u{24c2}\u{23e9}-\u{23ef}\u{25b6}\u{23f8}-\u{23fa}]/ug @@ -21,6 +22,7 @@ export default async function (eleventyConfig) { eleventyConfig.addPassthroughCopy('src/admin'); eleventyConfig.addPlugin(eleventyNavigationPlugin); + eleventyConfig.addPlugin(eleventyCooklang); /* Collections */ eleventyConfig.addCollection('recipes', collection => { diff --git a/package-lock.json b/package-lock.json index 9a2c167..d5836c1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "version": "0.1.0", "license": "MIT", "dependencies": { + "@cooklang/cooklang-ts": "^1.2.7", "alpinejs": "^2.8.2", "decap-cms-app": "^3.6.2", "decap-server": "^3.2.0" @@ -520,6 +521,12 @@ "node": ">=0.1.90" } }, + "node_modules/@cooklang/cooklang-ts": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@cooklang/cooklang-ts/-/cooklang-ts-1.2.7.tgz", + "integrity": "sha512-eVjyZ7HUbboP4y76L+OvsoEvY+oncIAqLr4vbXG5c0DuZEroRz1q+7JxYX8EEoa1ZKbIk5We0CHkUH6N49JMLw==", + "license": "MIT" + }, "node_modules/@dabh/diagnostics": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.3.tgz", @@ -11127,6 +11134,11 @@ "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz", "integrity": "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==" }, + "@cooklang/cooklang-ts": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@cooklang/cooklang-ts/-/cooklang-ts-1.2.7.tgz", + "integrity": "sha512-eVjyZ7HUbboP4y76L+OvsoEvY+oncIAqLr4vbXG5c0DuZEroRz1q+7JxYX8EEoa1ZKbIk5We0CHkUH6N49JMLw==" + }, "@dabh/diagnostics": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.3.tgz", diff --git a/package.json b/package.json index 2b93ef8..d246a13 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,7 @@ "sass": "^1.86.3" }, "dependencies": { + "@cooklang/cooklang-ts": "^1.2.7", "alpinejs": "^2.8.2", "decap-cms-app": "^3.6.2", "decap-server": "^3.2.0"