diff --git a/.eleventy.js b/.eleventy.js new file mode 100644 index 0000000..840bd6b --- /dev/null +++ b/.eleventy.js @@ -0,0 +1,14 @@ +module.exports = function (eleventyConfig) { + // ✅ Pass through static assets to the root of output + eleventyConfig.addPassthroughCopy({ "src/images": "images" }); + eleventyConfig.addPassthroughCopy({ "src/styles": "styles" }); + eleventyConfig.addPassthroughCopy({ "src/scripts": "scripts" }); + + return { + dir: { + input: "src", + output: "_site", + includes: "_includes", + }, + }; +}; diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..40b878d --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +node_modules/ \ No newline at end of file diff --git a/.nojekyll b/.nojekyll deleted file mode 100644 index 8b13789..0000000 --- a/.nojekyll +++ /dev/null @@ -1 +0,0 @@ - diff --git a/package-lock.json b/package-lock.json index 7338258..1dcaa5e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,11 +1,1545 @@ { - "name": "stackblitz-starters-rdsfw2", + "name": "BloomValleyNursery", "lockfileVersion": 3, "requires": true, "packages": { "": { "dependencies": { "servor": "^4.0.2" + }, + "devDependencies": { + "@11ty/eleventy": "^3.1.2" + } + }, + "node_modules/@11ty/dependency-tree": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@11ty/dependency-tree/-/dependency-tree-4.0.0.tgz", + "integrity": "sha512-PTOnwM8Xt+GdJmwRKg4pZ8EKAgGoK7pedZBfNSOChXu8MYk2FdEsxdJYecX4t62owpGw3xK60q9TQv/5JI59jw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@11ty/eleventy-utils": "^2.0.1" + } + }, + "node_modules/@11ty/dependency-tree-esm": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@11ty/dependency-tree-esm/-/dependency-tree-esm-2.0.0.tgz", + "integrity": "sha512-+4ySOON4aEAiyAGuH6XQJtxpGSpo6nibfG01krgix00sqjhman2+UaDUopq6Ksv8/jBB3hqkhsHe3fDE4z8rbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@11ty/eleventy-utils": "^2.0.1", + "acorn": "^8.14.0", + "dependency-graph": "^1.0.0", + "normalize-path": "^3.0.0" + } + }, + "node_modules/@11ty/eleventy": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@11ty/eleventy/-/eleventy-3.1.2.tgz", + "integrity": "sha512-IcsDlbXnBf8cHzbM1YBv3JcTyLB35EK88QexmVyFdVJVgUU6bh9g687rpxryJirHzo06PuwnYaEEdVZQfIgRGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@11ty/dependency-tree": "^4.0.0", + "@11ty/dependency-tree-esm": "^2.0.0", + "@11ty/eleventy-dev-server": "^2.0.8", + "@11ty/eleventy-plugin-bundle": "^3.0.6", + "@11ty/eleventy-utils": "^2.0.7", + "@11ty/lodash-custom": "^4.17.21", + "@11ty/posthtml-urls": "^1.0.1", + "@11ty/recursive-copy": "^4.0.2", + "@sindresorhus/slugify": "^2.2.1", + "bcp-47-normalize": "^2.3.0", + "chokidar": "^3.6.0", + "debug": "^4.4.1", + "dependency-graph": "^1.0.0", + "entities": "^6.0.1", + "filesize": "^10.1.6", + "gray-matter": "^4.0.3", + "iso-639-1": "^3.1.5", + "js-yaml": "^4.1.0", + "kleur": "^4.1.5", + "liquidjs": "^10.21.1", + "luxon": "^3.6.1", + "markdown-it": "^14.1.0", + "minimist": "^1.2.8", + "moo": "^0.5.2", + "node-retrieve-globals": "^6.0.1", + "nunjucks": "^3.2.4", + "picomatch": "^4.0.2", + "please-upgrade-node": "^3.2.0", + "posthtml": "^0.16.6", + "posthtml-match-helper": "^2.0.3", + "semver": "^7.7.2", + "slugify": "^1.6.6", + "tinyglobby": "^0.2.14" + }, + "bin": { + "eleventy": "cmd.cjs" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/11ty" + } + }, + "node_modules/@11ty/eleventy-dev-server": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/@11ty/eleventy-dev-server/-/eleventy-dev-server-2.0.8.tgz", + "integrity": "sha512-15oC5M1DQlCaOMUq4limKRYmWiGecDaGwryr7fTE/oM9Ix8siqMvWi+I8VjsfrGr+iViDvWcH/TVI6D12d93mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@11ty/eleventy-utils": "^2.0.1", + "chokidar": "^3.6.0", + "debug": "^4.4.0", + "finalhandler": "^1.3.1", + "mime": "^3.0.0", + "minimist": "^1.2.8", + "morphdom": "^2.7.4", + "please-upgrade-node": "^3.2.0", + "send": "^1.1.0", + "ssri": "^11.0.0", + "urlpattern-polyfill": "^10.0.0", + "ws": "^8.18.1" + }, + "bin": { + "eleventy-dev-server": "cmd.js" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/11ty" + } + }, + "node_modules/@11ty/eleventy-plugin-bundle": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@11ty/eleventy-plugin-bundle/-/eleventy-plugin-bundle-3.0.6.tgz", + "integrity": "sha512-wlEIMa1SEe6HE6ZyREEnPQiTw72337a2MPkyn0D1IzrqHrKU9euB17mv27LnnnyKvMJamCCqtU0985F5yyDL8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@11ty/eleventy-utils": "^2.0.2", + "debug": "^4.4.0", + "posthtml-match-helper": "^2.0.3" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/11ty" + } + }, + "node_modules/@11ty/eleventy-utils": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@11ty/eleventy-utils/-/eleventy-utils-2.0.7.tgz", + "integrity": "sha512-6QE+duqSQ0GY9rENXYb4iPR4AYGdrFpqnmi59tFp9VrleOl0QSh8VlBr2yd6dlhkdtj7904poZW5PvGr9cMiJQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/11ty" + } + }, + "node_modules/@11ty/lodash-custom": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/@11ty/lodash-custom/-/lodash-custom-4.17.21.tgz", + "integrity": "sha512-Mqt6im1xpb1Ykn3nbcCovWXK3ggywRJa+IXIdoz4wIIK+cvozADH63lexcuPpGS/gJ6/m2JxyyXDyupkMr5DHw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/11ty" + } + }, + "node_modules/@11ty/posthtml-urls": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@11ty/posthtml-urls/-/posthtml-urls-1.0.1.tgz", + "integrity": "sha512-6EFN/yYSxC/OzYXpq4gXDyDMlX/W+2MgCvvoxf11X1z76bqkqFJ8eep5RiBWfGT5j0323a1pwpelcJJdR46MCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "evaluate-value": "^2.0.0", + "http-equiv-refresh": "^2.0.1", + "list-to-array": "^1.1.0", + "parse-srcset": "^1.0.2" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@11ty/recursive-copy": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@11ty/recursive-copy/-/recursive-copy-4.0.2.tgz", + "integrity": "sha512-174nFXxL/6KcYbLYpra+q3nDbfKxLxRTNVY1atq2M1pYYiPfHse++3IFNl8mjPFsd7y2qQjxLORzIjHMjL3NDQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "errno": "^1.0.0", + "junk": "^3.1.0", + "maximatch": "^0.1.0", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sindresorhus/slugify": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@sindresorhus/slugify/-/slugify-2.2.1.tgz", + "integrity": "sha512-MkngSCRZ8JdSOCHRaYd+D01XhvU3Hjy6MGl06zhOk614hp9EOAp5gIkBeQg7wtmxpitU6eAL4kdiRMcJa2dlrw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sindresorhus/transliterate": "^1.0.0", + "escape-string-regexp": "^5.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@sindresorhus/transliterate": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/transliterate/-/transliterate-1.6.0.tgz", + "integrity": "sha512-doH1gimEu3A46VX6aVxpHTeHrytJAG6HgdxntYnCFiIFHEM/ZGpG8KiZGBChchjQmG0XFIBL552kBTjVcMZXwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^5.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/a-sync-waterfall": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/a-sync-waterfall/-/a-sync-waterfall-1.0.1.tgz", + "integrity": "sha512-RYTOHHdWipFUliRFMCS4X2Yn2X8M87V/OpSqWzKKOGhzqyUxzyVmhHDH9sAvG+ZuQf/TAOFsLCpMw09I1ufUnA==", + "dev": true, + "license": "MIT" + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/anymatch/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/array-differ": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", + "integrity": "sha512-LeZY+DZDRnvP7eMuQ6LHfCzUGxAAIViUBliK24P3hWXL6y4SortgR6Nim6xrkfSLlmH0+k+9NYNwVC2s53ZrYQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-uniq": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", + "dev": true, + "license": "MIT" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/bcp-47": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bcp-47/-/bcp-47-2.1.0.tgz", + "integrity": "sha512-9IIS3UPrvIa1Ej+lVDdDwO7zLehjqsaByECw0bu2RRGP73jALm6FYbzI5gWbgHLvNdkvfXB5YrSbocZdOS0c0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-alphabetical": "^2.0.0", + "is-alphanumerical": "^2.0.0", + "is-decimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/bcp-47-match": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/bcp-47-match/-/bcp-47-match-2.0.3.tgz", + "integrity": "sha512-JtTezzbAibu8G0R9op9zb3vcWZd9JF6M0xOYGPn0fNCd7wOpRB1mU2mH9T8gaBGbAAyIIVgB2G7xG0GP98zMAQ==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/bcp-47-normalize": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/bcp-47-normalize/-/bcp-47-normalize-2.3.0.tgz", + "integrity": "sha512-8I/wfzqQvttUFz7HVJgIZ7+dj3vUaIyIxYXaTRP1YWoSDfzt6TUmxaKZeuXR62qBmYr+nvuWINFRl6pZ5DlN4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "bcp-47": "^2.0.0", + "bcp-47-match": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/dependency-graph": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dependency-graph/-/dependency-graph-1.0.0.tgz", + "integrity": "sha512-cW3gggJ28HZ/LExwxP2B++aiKxhJXMSIt9K48FOXQkm+vuG5gyatXnLsONRJdzO/7VfjDIiaOOa/bs4l464Lwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "dev": true, + "license": "MIT", + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/dom-serializer/node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "dev": true, + "license": "BSD-2-Clause", + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "BSD-2-Clause" + }, + "node_modules/domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "domelementtype": "^2.2.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "dev": true, + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/errno": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/errno/-/errno-1.0.0.tgz", + "integrity": "sha512-3zV5mFS1E8/1bPxt/B0xxzI1snsg3uSCIh6Zo1qKg6iMw93hzPANk9oBFzSFBFrwuVoQuE3rLoouAUfwOAj1wQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prr": "~1.0.1" + }, + "bin": { + "errno": "cli.js" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "dev": true, + "license": "MIT" + }, + "node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/esm-import-transformer": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/esm-import-transformer/-/esm-import-transformer-3.0.5.tgz", + "integrity": "sha512-1GKLvfuMnnpI75l8c6sHoz0L3Z872xL5akGuBudgqTDPv4Vy6f2Ec7jEMKTxlqWl/3kSvNbHELeimJtnqgYniw==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.15.0" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/evaluate-value": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/evaluate-value/-/evaluate-value-2.0.0.tgz", + "integrity": "sha512-VonfiuDJc0z4sOO7W0Pd130VLsXN6vmBWZlrog1mCb/o7o/Nl5Lr25+Kj/nkCCAhG+zqeeGjxhkK9oHpkgTHhQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/filesize": { + "version": "10.1.6", + "resolved": "https://registry.npmjs.org/filesize/-/filesize-10.1.6.tgz", + "integrity": "sha512-sJslQKU2uM33qH5nqewAwVB2QgR6w1aMNsYUp3aN5rMRyXEwJGmZvaWzeJFNTOXWlHQyBFCWrdj3fV/fsTOX8w==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">= 10.4.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, + "node_modules/fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", + "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/gray-matter": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz", + "integrity": "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "js-yaml": "^3.13.1", + "kind-of": "^6.0.2", + "section-matter": "^1.0.0", + "strip-bom-string": "^1.0.0" + }, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/gray-matter/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/gray-matter/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/htmlparser2": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-7.2.0.tgz", + "integrity": "sha512-H7MImA4MS6cw7nbyURtLPO1Tms7C5H602LRETv95z1MxO/7CP7rDVROehUYeYBUYEON94NXXDEPmZuq+hX4sog==", + "dev": true, + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "MIT", + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.2", + "domutils": "^2.8.0", + "entities": "^3.0.1" + } + }, + "node_modules/htmlparser2/node_modules/entities": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz", + "integrity": "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/http-equiv-refresh": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-equiv-refresh/-/http-equiv-refresh-2.0.1.tgz", + "integrity": "sha512-XJpDL/MLkV3dKwLzHwr2dY05dYNfBNlyPu4STQ8WvKCFdc6vC5tPXuq28of663+gHVg03C+16pHHs/+FmmDjcw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/is-alphabetical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", + "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-alphanumerical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz", + "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-alphabetical": "^2.0.0", + "is-decimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-decimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz", + "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-json": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-json/-/is-json-2.0.1.tgz", + "integrity": "sha512-6BEnpVn1rcf3ngfmViLM6vjUjGErbdrL4rwlv+u1NO1XO8kqT4YGL8+19Q+Z/bas8tY90BTWMk2+fW1g6hQjbA==", + "dev": true, + "license": "ISC" + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/iso-639-1": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/iso-639-1/-/iso-639-1-3.1.5.tgz", + "integrity": "sha512-gXkz5+KN7HrG0Q5UGqSMO2qB9AsbEeyLP54kF1YrMsIxmu+g4BdB7rflReZTSTZGpfj8wywu6pfPBCylPIzGQA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0" + } + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/junk": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/junk/-/junk-3.1.0.tgz", + "integrity": "sha512-pBxcB3LFc8QVgdggvZWyeys+hnrNWg4OcZIU/1X59k5jQdLBlCsYGRQaz234SqoRLTCgMH00fY0xRJH+F9METQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/kleur": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", + "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "uc.micro": "^2.0.0" + } + }, + "node_modules/liquidjs": { + "version": "10.21.1", + "resolved": "https://registry.npmjs.org/liquidjs/-/liquidjs-10.21.1.tgz", + "integrity": "sha512-NZXmCwv3RG5nire3fmIn9HsOyJX3vo+ptp0yaXUHAMzSNBhx74Hm+dAGJvscUA6lNqbLuYfXgNavRQ9UbUJhQQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "commander": "^10.0.0" + }, + "bin": { + "liquid": "bin/liquid.js", + "liquidjs": "bin/liquid.js" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/liquidjs" + } + }, + "node_modules/list-to-array": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/list-to-array/-/list-to-array-1.1.0.tgz", + "integrity": "sha512-+dAZZ2mM+/m+vY9ezfoueVvrgnHIGi5FvgSymbIgJOFwiznWyA59mav95L+Mc6xPtL3s9gm5eNTlNtxJLbNM1g==", + "dev": true, + "license": "MIT" + }, + "node_modules/luxon": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.7.1.tgz", + "integrity": "sha512-RkRWjA926cTvz5rAb1BqyWkKbbjzCGchDUIKMCUvNi17j6f6j8uHGDV82Aqcqtzd+icoYpELmG3ksgGiFNNcNg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/markdown-it": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", + "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1", + "entities": "^4.4.0", + "linkify-it": "^5.0.0", + "mdurl": "^2.0.0", + "punycode.js": "^2.3.1", + "uc.micro": "^2.1.0" + }, + "bin": { + "markdown-it": "bin/markdown-it.mjs" + } + }, + "node_modules/markdown-it/node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/maximatch": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/maximatch/-/maximatch-0.1.0.tgz", + "integrity": "sha512-9ORVtDUFk4u/NFfo0vG/ND/z7UQCVZBL539YW0+U1I7H1BkZwizcPx5foFv7LCPcBnm2U6RjFnQOsIvN4/Vm2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-differ": "^1.0.0", + "array-union": "^1.0.1", + "arrify": "^1.0.0", + "minimatch": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", + "dev": true, + "license": "MIT" + }, + "node_modules/mime": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", + "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", + "dev": true, + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", + "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": "^1.54.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/moo": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.2.tgz", + "integrity": "sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/morphdom": { + "version": "2.7.7", + "resolved": "https://registry.npmjs.org/morphdom/-/morphdom-2.7.7.tgz", + "integrity": "sha512-04GmsiBcalrSCNmzfo+UjU8tt3PhZJKzcOy+r1FlGA7/zri8wre3I1WkYN9PT3sIeIKfW9bpyElA+VzOg2E24g==", + "dev": true, + "license": "MIT" + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-retrieve-globals": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/node-retrieve-globals/-/node-retrieve-globals-6.0.1.tgz", + "integrity": "sha512-j0DeFuZ/Wg3VlklfbxUgZF/mdHMTEiEipBb3q0SpMMbHaV3AVfoUQF8UGxh1s/yjqO0TgRZd4Pi/x2yRqoQ4Eg==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.14.1", + "acorn-walk": "^8.3.4", + "esm-import-transformer": "^3.0.3" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nunjucks": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/nunjucks/-/nunjucks-3.2.4.tgz", + "integrity": "sha512-26XRV6BhkgK0VOxfbU5cQI+ICFUtMLixv1noZn1tGU38kQH5A5nmmbk/O45xdyBhD1esk47nKrY0mvQpZIhRjQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "a-sync-waterfall": "^1.0.0", + "asap": "^2.0.3", + "commander": "^5.1.0" + }, + "bin": { + "nunjucks-precompile": "bin/precompile" + }, + "engines": { + "node": ">= 6.9.0" + }, + "peerDependencies": { + "chokidar": "^3.3.0" + }, + "peerDependenciesMeta": { + "chokidar": { + "optional": true + } + } + }, + "node_modules/nunjucks/node_modules/commander": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", + "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/parse-srcset": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-srcset/-/parse-srcset-1.0.2.tgz", + "integrity": "sha512-/2qh0lav6CmI15FzA3i/2Bzk2zCgQhGMkvhOhKNcBVQ1ldgpbfiNTVslmooUmWJcADi1f1kIeynbDRVzNlfR6Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/please-upgrade-node": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz", + "integrity": "sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver-compare": "^1.0.0" + } + }, + "node_modules/posthtml": { + "version": "0.16.6", + "resolved": "https://registry.npmjs.org/posthtml/-/posthtml-0.16.6.tgz", + "integrity": "sha512-JcEmHlyLK/o0uGAlj65vgg+7LIms0xKXe60lcDOTU7oVX/3LuEuLwrQpW3VJ7de5TaFKiW4kWkaIpJL42FEgxQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "posthtml-parser": "^0.11.0", + "posthtml-render": "^3.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/posthtml-match-helper": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/posthtml-match-helper/-/posthtml-match-helper-2.0.3.tgz", + "integrity": "sha512-p9oJgTdMF2dyd7WE54QI1LvpBIkNkbSiiECKezNnDVYhGhD1AaOnAkw0Uh0y5TW+OHO8iBdSqnd8Wkpb6iUqmw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "posthtml": "^0.16.6" + } + }, + "node_modules/posthtml-parser": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/posthtml-parser/-/posthtml-parser-0.11.0.tgz", + "integrity": "sha512-QecJtfLekJbWVo/dMAA+OSwY79wpRmbqS5TeXvXSX+f0c6pW4/SE6inzZ2qkU7oAMCPqIDkZDvd/bQsSFUnKyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "htmlparser2": "^7.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/posthtml-render": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/posthtml-render/-/posthtml-render-3.0.0.tgz", + "integrity": "sha512-z+16RoxK3fUPgwaIgH9NGnK1HKY9XIDpydky5eQGgAFVXTCSezalv9U2jQuNV+Z9qV1fDWNzldcw4eK0SSbqKA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-json": "^2.0.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==", + "dev": true, + "license": "MIT" + }, + "node_modules/punycode.js": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/readdirp/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/section-matter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz", + "integrity": "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "extend-shallow": "^2.0.1", + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", + "dev": true, + "license": "MIT" + }, + "node_modules/send": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz", + "integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.3.5", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "mime-types": "^3.0.1", + "ms": "^2.1.3", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 18" } }, "node_modules/servor": { @@ -15,6 +1549,159 @@ "bin": { "servor": "cli.js" } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "dev": true, + "license": "ISC" + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/slugify": { + "version": "1.6.6", + "resolved": "https://registry.npmjs.org/slugify/-/slugify-1.6.6.tgz", + "integrity": "sha512-h+z7HKHYXj6wJU+AnS/+IH8Uh9fdcX1Lrhg1/VMdf9PwoBQXFcXiAdsy2tSK0P6gKwJLXp02r90ahUCqHk9rrw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/ssri": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-11.0.0.tgz", + "integrity": "sha512-aZpUoMN/Jj2MqA4vMCeiKGnc/8SuSyHbGSBdgFbZxP8OJGF/lFkIuElzPxsN0q8TQQ+prw3P4EDfB3TBHHgfXw==", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^7.0.3" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/strip-bom-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", + "integrity": "sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz", + "integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.4.4", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/uc.micro": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", + "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", + "dev": true, + "license": "MIT" + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/urlpattern-polyfill": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-10.1.0.tgz", + "integrity": "sha512-IGjKp/o0NL3Bso1PymYURCJxMPNAf/ILOpendP9f5B6e1rTJgdgiOvgfoT8VxCAdY+Wisb9uhGaJJf3yZ2V9nw==", + "dev": true, + "license": "MIT" + }, + "node_modules/ws": { + "version": "8.18.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", + "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } } } } diff --git a/package.json b/package.json index 49d805b..7f52593 100644 --- a/package.json +++ b/package.json @@ -4,5 +4,8 @@ }, "dependencies": { "servor": "^4.0.2" + }, + "devDependencies": { + "@11ty/eleventy": "^3.1.2" } } diff --git a/about.html b/src/about.html similarity index 97% rename from about.html rename to src/about.html index edbc349..f05fbf6 100644 --- a/about.html +++ b/src/about.html @@ -1,275 +1,275 @@ - - - - - - - - About Us - Bloom Valley Nursery - - - - -
- -

Bloom Valley Nursery

- - -
- - -
-
- -
-

The Story of Bloom Valley

-

- Legend has it that in 1822, Benjamin Bloom, his wife Violet, and - their young daughter Nora stumbled upon a breathtaking valley - brimming with vibrant, rare flowers during their journey westward. - Enchanted by its beauty, they decided to settle there, abandoning - their plans to reach California. This picturesque haven became known - as Bloom Valley. -

-

- Today, on the very land where the Bloom family found their paradise, - stands Bloom Valley Nursery. Still family-owned and operated, - siblings Bethany, Vincent, and Nathaniel Bloom carry forward a - legacy of preserving and sharing the natural beauty that captivated - the hearts of their ancestors over two centuries ago. -

-

Though many things have changed through the years, our commitment to serving our community has remained the same. Let us help you cultivate joy, one bloom at a time!

-
-
-
-
-
-

We Want to Hear From You!

-

Your feedback provides us with valuable insight into where we stand in our commitment to our neighbors, friends, and the entire Bloom Valley community.

-

Feel free to contact us by filling out the form below if you have any questions, concerns, or simply want to tell us how we can better serve you in the future. You are also welcome to give us a call at the number above if you need to speak with someone directly. Our friendly staff can help answer your questions or guide you in placing custom orders as well!

-
-
-
-
-
- - -
-
- - -
-
- - -
-
-
-
- - -
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + About Us - Bloom Valley Nursery + + + + +
+ +

Bloom Valley Nursery

+ + +
+ + +
+
+ +
+

The Story of Bloom Valley

+

+ Legend has it that in 1822, Benjamin Bloom, his wife Violet, and + their young daughter Nora stumbled upon a breathtaking valley + brimming with vibrant, rare flowers during their journey westward. + Enchanted by its beauty, they decided to settle there, abandoning + their plans to reach California. This picturesque haven became known + as Bloom Valley. +

+

+ Today, on the very land where the Bloom family found their paradise, + stands Bloom Valley Nursery. Still family-owned and operated, + siblings Bethany, Vincent, and Nathaniel Bloom carry forward a + legacy of preserving and sharing the natural beauty that captivated + the hearts of their ancestors over two centuries ago. +

+

Though many things have changed through the years, our commitment to serving our community has remained the same. Let us help you cultivate joy, one bloom at a time!

+
+
+
+
+
+

We Want to Hear From You!

+

Your feedback provides us with valuable insight into where we stand in our commitment to our neighbors, friends, and the entire Bloom Valley community.

+

Feel free to contact us by filling out the form below if you have any questions, concerns, or simply want to tell us how we can better serve you in the future. You are also welcome to give us a call at the number above if you need to speak with someone directly. Our friendly staff can help answer your questions or guide you in placing custom orders as well!

+
+
+
+
+
+ + +
+
+ + +
+
+ + +
+
+
+
+ + +
+
+ +
+
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/community.html b/src/community.html similarity index 97% rename from community.html rename to src/community.html index 98e1d96..60cffeb 100644 --- a/community.html +++ b/src/community.html @@ -1,256 +1,256 @@ - - - - - - - - Community Events - Bloom Valley Nursery - - - - -
- -

Bloom Valley Nursery

- - -
- - -
-

Mark Your Calendars!

-
-
- -
-
-

Upcoming Events

-
-
-

Events at Bloom Valley Nursery

-

- All workshops at Bloom Valley Nursery are provided free of charge to - anyone interested in learning techniques and ideas for creating a - visually appealing living space that can be personalized to suite - individual needs. Registration links are provided in each Google - Calendar Event by clicking on the date of the event within the - Google Calendar on this page. -

-
    -
  • - Gardening and Landscaping 101:
    When:
    2nd Tuesday of - Every Month @ 6:30 pm.
    Join Bethany Bloom as she shares her tips for - creating a themed decor through-out the home that you will be - delighted to share with your holiday guests. -
  • -
  • - Deck the Halls
    When: Saturday @ 10:00 am.
    Join - Nathaniel and Vincent as they guide us through picking and tending - the perfect live Christmas tree for your Christmas decoration - focal-point. -
  • -
  • - Christmas Eve and Christmas Day
    Bloom Valley - Nursery will close on Christmas Eve at 8:00 pm for any last-minute - shopping.
    The nursery will remain closed until January 2nd. During - this time, we will be making improvements to the nursery grounds and - store with the aim of better serving our Bloom Valley neighbors, - friends and family. We are excited to share the new features and changes with - you in the New Year!
    Happy Holidays!!! -
  • -
-
-
-

Community-Wide Events

-

- This section includes local community events for which Bloom Valley - Nursery is in partner with or a sponsor of. These events are - typically free of charge, but can include sub-events by other local - organizations and businesses that may not be free of charge. Check - with specific organizations, businesses, and the Bloom Valley - Chamber of Commerce for specific details that may not be provided by - Bloom Valley Nursery. -

-
    -
  • - Tree Lighting Ceremony
    When:
    Thursday @ 6:00 pm.
    - Help us kick off the Holiday festivities by joining the Bloom - family, along with the Bloom Valley Chamber of Commerce, the Bloom - Valley Garden Club, and many other local businesses and - organizations, as we gather in front of City Hall for the annual Tree - Lighting Ceremony! This event will include performances by the Bloom - Valley Junior and Senior High Marching Bands, a workshop for making - tree ornaments, the annual Chili Cook-off, and much more! -
  • -
-
- -
-
- -

- For more details, to add events to this page, or to leave feedback, - click here to send us a message. -

-
- - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + Community Events - Bloom Valley Nursery + + + + +
+ +

Bloom Valley Nursery

+ + +
+ + +
+

Mark Your Calendars!

+
+
+ +
+
+

Upcoming Events

+
+
+

Events at Bloom Valley Nursery

+

+ All workshops at Bloom Valley Nursery are provided free of charge to + anyone interested in learning techniques and ideas for creating a + visually appealing living space that can be personalized to suite + individual needs. Registration links are provided in each Google + Calendar Event by clicking on the date of the event within the + Google Calendar on this page. +

+
    +
  • + Gardening and Landscaping 101:
    When:
    2nd Tuesday of + Every Month @ 6:30 pm.
    Join Bethany Bloom as she shares her tips for + creating a themed decor through-out the home that you will be + delighted to share with your holiday guests. +
  • +
  • + Deck the Halls
    When: Saturday @ 10:00 am.
    Join + Nathaniel and Vincent as they guide us through picking and tending + the perfect live Christmas tree for your Christmas decoration + focal-point. +
  • +
  • + Christmas Eve and Christmas Day
    Bloom Valley + Nursery will close on Christmas Eve at 8:00 pm for any last-minute + shopping.
    The nursery will remain closed until January 2nd. During + this time, we will be making improvements to the nursery grounds and + store with the aim of better serving our Bloom Valley neighbors, + friends and family. We are excited to share the new features and changes with + you in the New Year!
    Happy Holidays!!! +
  • +
+
+
+

Community-Wide Events

+

+ This section includes local community events for which Bloom Valley + Nursery is in partner with or a sponsor of. These events are + typically free of charge, but can include sub-events by other local + organizations and businesses that may not be free of charge. Check + with specific organizations, businesses, and the Bloom Valley + Chamber of Commerce for specific details that may not be provided by + Bloom Valley Nursery. +

+
    +
  • + Tree Lighting Ceremony
    When:
    Thursday @ 6:00 pm.
    + Help us kick off the Holiday festivities by joining the Bloom + family, along with the Bloom Valley Chamber of Commerce, the Bloom + Valley Garden Club, and many other local businesses and + organizations, as we gather in front of City Hall for the annual Tree + Lighting Ceremony! This event will include performances by the Bloom + Valley Junior and Senior High Marching Bands, a workshop for making + tree ornaments, the annual Chili Cook-off, and much more! +
  • +
+
+ +
+
+ +

+ For more details, to add events to this page, or to leave feedback, + click here to send us a message. +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gallery.html b/src/gallery.html similarity index 97% rename from gallery.html rename to src/gallery.html index 3756c36..fae1499 100644 --- a/gallery.html +++ b/src/gallery.html @@ -1,219 +1,219 @@ - - - - - - - - Gallery - Bloom Valley Nursery - - - - -
- -

Bloom Valley Nursery

- - -
- - -
- - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + Gallery - Bloom Valley Nursery + + + + +
+ +

Bloom Valley Nursery

+ + +
+ + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/images/Client1_LogoPalette2_F0C06D.png b/src/images/Client1_LogoPalette2_F0C06D.png similarity index 100% rename from images/Client1_LogoPalette2_F0C06D.png rename to src/images/Client1_LogoPalette2_F0C06D.png diff --git a/images/accessories/BirdHouse.png b/src/images/accessories/BirdHouse.png similarity index 100% rename from images/accessories/BirdHouse.png rename to src/images/accessories/BirdHouse.png diff --git a/images/accessories/PottingSoil.png b/src/images/accessories/PottingSoil.png similarity index 100% rename from images/accessories/PottingSoil.png rename to src/images/accessories/PottingSoil.png diff --git a/images/accessories/WateringCan.png b/src/images/accessories/WateringCan.png similarity index 100% rename from images/accessories/WateringCan.png rename to src/images/accessories/WateringCan.png diff --git a/images/indoor/AloePlant.png b/src/images/indoor/AloePlant.png similarity index 100% rename from images/indoor/AloePlant.png rename to src/images/indoor/AloePlant.png diff --git a/images/indoor/SpiderPlant.png b/src/images/indoor/SpiderPlant.png similarity index 100% rename from images/indoor/SpiderPlant.png rename to src/images/indoor/SpiderPlant.png diff --git a/images/indoor/StringofPearls.png b/src/images/indoor/StringofPearls.png similarity index 100% rename from images/indoor/StringofPearls.png rename to src/images/indoor/StringofPearls.png diff --git a/images/indoor/aloe-plant.jpg b/src/images/indoor/aloe-plant.jpg similarity index 100% rename from images/indoor/aloe-plant.jpg rename to src/images/indoor/aloe-plant.jpg diff --git a/images/indoor/peperomia.jpg b/src/images/indoor/peperomia.jpg similarity index 100% rename from images/indoor/peperomia.jpg rename to src/images/indoor/peperomia.jpg diff --git a/images/indoor/string-of-pearls.jpg b/src/images/indoor/string-of-pearls.jpg similarity index 100% rename from images/indoor/string-of-pearls.jpg rename to src/images/indoor/string-of-pearls.jpg diff --git a/images/indoor/venus-fly-trap.jpg b/src/images/indoor/venus-fly-trap.jpg similarity index 100% rename from images/indoor/venus-fly-trap.jpg rename to src/images/indoor/venus-fly-trap.jpg diff --git a/media/image1.jpg b/src/images/media/image1.jpg similarity index 100% rename from media/image1.jpg rename to src/images/media/image1.jpg diff --git a/media/image10.jpeg b/src/images/media/image10.jpeg similarity index 100% rename from media/image10.jpeg rename to src/images/media/image10.jpeg diff --git a/media/image11.jpeg b/src/images/media/image11.jpeg similarity index 100% rename from media/image11.jpeg rename to src/images/media/image11.jpeg diff --git a/media/image12.jpeg b/src/images/media/image12.jpeg similarity index 100% rename from media/image12.jpeg rename to src/images/media/image12.jpeg diff --git a/media/image13.jpeg b/src/images/media/image13.jpeg similarity index 100% rename from media/image13.jpeg rename to src/images/media/image13.jpeg diff --git a/media/image14.jpeg b/src/images/media/image14.jpeg similarity index 100% rename from media/image14.jpeg rename to src/images/media/image14.jpeg diff --git a/media/image15.jpeg b/src/images/media/image15.jpeg similarity index 100% rename from media/image15.jpeg rename to src/images/media/image15.jpeg diff --git a/media/image16.jpeg b/src/images/media/image16.jpeg similarity index 100% rename from media/image16.jpeg rename to src/images/media/image16.jpeg diff --git a/media/image17.jpeg b/src/images/media/image17.jpeg similarity index 100% rename from media/image17.jpeg rename to src/images/media/image17.jpeg diff --git a/media/image18.jpeg b/src/images/media/image18.jpeg similarity index 100% rename from media/image18.jpeg rename to src/images/media/image18.jpeg diff --git a/media/image19.jpeg b/src/images/media/image19.jpeg similarity index 100% rename from media/image19.jpeg rename to src/images/media/image19.jpeg diff --git a/media/image2.jpg b/src/images/media/image2.jpg similarity index 100% rename from media/image2.jpg rename to src/images/media/image2.jpg diff --git a/media/image20.jpeg b/src/images/media/image20.jpeg similarity index 100% rename from media/image20.jpeg rename to src/images/media/image20.jpeg diff --git a/media/image21.jpeg b/src/images/media/image21.jpeg similarity index 100% rename from media/image21.jpeg rename to src/images/media/image21.jpeg diff --git a/media/image22.jpeg b/src/images/media/image22.jpeg similarity index 100% rename from media/image22.jpeg rename to src/images/media/image22.jpeg diff --git a/media/image23.jpeg b/src/images/media/image23.jpeg similarity index 100% rename from media/image23.jpeg rename to src/images/media/image23.jpeg diff --git a/media/image24.jpeg b/src/images/media/image24.jpeg similarity index 100% rename from media/image24.jpeg rename to src/images/media/image24.jpeg diff --git a/media/image25.jpeg b/src/images/media/image25.jpeg similarity index 100% rename from media/image25.jpeg rename to src/images/media/image25.jpeg diff --git a/media/image26.jpeg b/src/images/media/image26.jpeg similarity index 100% rename from media/image26.jpeg rename to src/images/media/image26.jpeg diff --git a/media/image27.jpeg b/src/images/media/image27.jpeg similarity index 100% rename from media/image27.jpeg rename to src/images/media/image27.jpeg diff --git a/media/image28.jpeg b/src/images/media/image28.jpeg similarity index 100% rename from media/image28.jpeg rename to src/images/media/image28.jpeg diff --git a/media/image29.jpeg b/src/images/media/image29.jpeg similarity index 100% rename from media/image29.jpeg rename to src/images/media/image29.jpeg diff --git a/media/image3.jpeg b/src/images/media/image3.jpeg similarity index 100% rename from media/image3.jpeg rename to src/images/media/image3.jpeg diff --git a/media/image30.jpeg b/src/images/media/image30.jpeg similarity index 100% rename from media/image30.jpeg rename to src/images/media/image30.jpeg diff --git a/media/image31.jpeg b/src/images/media/image31.jpeg similarity index 100% rename from media/image31.jpeg rename to src/images/media/image31.jpeg diff --git a/media/image32.jpeg b/src/images/media/image32.jpeg similarity index 100% rename from media/image32.jpeg rename to src/images/media/image32.jpeg diff --git a/media/image4.jpeg b/src/images/media/image4.jpeg similarity index 100% rename from media/image4.jpeg rename to src/images/media/image4.jpeg diff --git a/media/image5.jpeg b/src/images/media/image5.jpeg similarity index 100% rename from media/image5.jpeg rename to src/images/media/image5.jpeg diff --git a/media/image6.jpeg b/src/images/media/image6.jpeg similarity index 100% rename from media/image6.jpeg rename to src/images/media/image6.jpeg diff --git a/media/image7.jpeg b/src/images/media/image7.jpeg similarity index 100% rename from media/image7.jpeg rename to src/images/media/image7.jpeg diff --git a/media/image8.jpeg b/src/images/media/image8.jpeg similarity index 100% rename from media/image8.jpeg rename to src/images/media/image8.jpeg diff --git a/media/image9.jpeg b/src/images/media/image9.jpeg similarity index 100% rename from media/image9.jpeg rename to src/images/media/image9.jpeg diff --git a/images/tools/birdhouse.jpg b/src/images/tools/birdhouse.jpg similarity index 100% rename from images/tools/birdhouse.jpg rename to src/images/tools/birdhouse.jpg diff --git a/images/tools/gardening-tools.jpg b/src/images/tools/gardening-tools.jpg similarity index 100% rename from images/tools/gardening-tools.jpg rename to src/images/tools/gardening-tools.jpg diff --git a/images/tools/potting-soil.jpg b/src/images/tools/potting-soil.jpg similarity index 100% rename from images/tools/potting-soil.jpg rename to src/images/tools/potting-soil.jpg diff --git a/images/tools/watering-cans.jpg b/src/images/tools/watering-cans.jpg similarity index 100% rename from images/tools/watering-cans.jpg rename to src/images/tools/watering-cans.jpg diff --git a/images/trees/AppleTree.png b/src/images/trees/AppleTree.png similarity index 100% rename from images/trees/AppleTree.png rename to src/images/trees/AppleTree.png diff --git a/images/trees/BirchTree.png b/src/images/trees/BirchTree.png similarity index 100% rename from images/trees/BirchTree.png rename to src/images/trees/BirchTree.png diff --git a/images/trees/MapleTree.png b/src/images/trees/MapleTree.png similarity index 100% rename from images/trees/MapleTree.png rename to src/images/trees/MapleTree.png diff --git a/images/trees/apple-tree.jpg b/src/images/trees/apple-tree.jpg similarity index 100% rename from images/trees/apple-tree.jpg rename to src/images/trees/apple-tree.jpg diff --git a/images/trees/crepe-mertyl.jpg b/src/images/trees/crepe-mertyl.jpg similarity index 100% rename from images/trees/crepe-mertyl.jpg rename to src/images/trees/crepe-mertyl.jpg diff --git a/images/trees/potted-spruce.jpg b/src/images/trees/potted-spruce.jpg similarity index 100% rename from images/trees/potted-spruce.jpg rename to src/images/trees/potted-spruce.jpg diff --git a/images/trees/silver-birch.jpg b/src/images/trees/silver-birch.jpg similarity index 100% rename from images/trees/silver-birch.jpg rename to src/images/trees/silver-birch.jpg diff --git a/index.html b/src/index.html similarity index 97% rename from index.html rename to src/index.html index ff5573e..7a804f1 100644 --- a/index.html +++ b/src/index.html @@ -1,239 +1,239 @@ - - - - - - - - Homepage - Bloom Valley Nursery - - - - -
- -

Bloom Valley Nursery

- - -
- - -
- - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + Homepage - Bloom Valley Nursery + + + + +
+ +

Bloom Valley Nursery

+ + +
+ + +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cart.js b/src/scripts/cart.js similarity index 97% rename from cart.js rename to src/scripts/cart.js index 4d70e02..f8e26a2 100644 --- a/cart.js +++ b/src/scripts/cart.js @@ -1,178 +1,178 @@ -document.addEventListener('DOMContentLoaded', () => { - let cart = JSON.parse(sessionStorage.getItem('cart')) || []; - - // Get modal and cart-related elements - const modal = document.getElementById('cart-modal'); - const closeModal = document.querySelector('.close-modal'); - const cartItemsContainer = document.getElementById('cart-items'); - const cartTotalContainer = document.getElementById('cart-total'); - const clearCartModalButton = document.getElementById('clear-cart-modal-btn'); - const processOrderModalButton = document.getElementById('process-order-modal-btn'); - - // Custom confirmation modals for clear cart and process order - const confirmationModal = document.getElementById('confirmation-modal'); - const confirmationMessage = document.getElementById('confirmation-message'); - const confirmationCloseButton = document.getElementById('confirmation-close-btn'); - const confirmationConfirmButton = document.getElementById('confirmation-confirm-btn'); - - // Buttons - const shoppingCartButton = document.getElementById('shopping-cart'); - const cartDetailsButton = document.getElementById('cart-details'); - - // Custom alert modal for item added - const itemAddedModal = document.getElementById('item-added-modal'); - const itemAddedMessage = document.getElementById('item-added-message'); - const itemAddedClose = document.getElementById('item-added-close'); - - // Final confirmation modal for success messages - const finalConfirmationModal = document.getElementById('final-confirmation-modal'); - const finalConfirmationMessage = document.getElementById('final-confirmation-message'); - const finalConfirmationCloseButton = document.getElementById('final-confirmation-close-btn'); - - // Function to render the cart - function renderCart() { - cart = JSON.parse(sessionStorage.getItem('cart')) || []; - cartItemsContainer.innerHTML = ''; // Clear existing items - let total = 0; - - if (cart.length === 0) { - cartItemsContainer.innerHTML = '
  • Your cart is empty.
  • '; - cartTotalContainer.textContent = ''; - return; - } - - cart.forEach(item => { - const itemTotal = item.price * item.quantity; - total += itemTotal; - - const listItem = document.createElement('li'); - listItem.textContent = `${item.name} x ${item.quantity} - $${itemTotal.toFixed(2)}`; - cartItemsContainer.appendChild(listItem); - }); - - cartTotalContainer.textContent = `Subtotal: $${total.toFixed(2)}`; - } - - // Show cart modal with current cart content - function showModal() { - renderCart(); // Always render the latest cart - modal.style.display = 'flex'; // Show the cart modal - } - - // Show confirmation modal for actions (clear or process order) - function showConfirmationModal(message, action) { - confirmationMessage.textContent = message; - confirmationModal.style.display = 'flex'; // Show the confirmation modal - - // Confirm action on the "Confirm" button - confirmationConfirmButton.onclick = () => { - action(); // Execute the passed action (clear cart, process order) - confirmationModal.style.display = 'none'; // Close the confirmation modal after confirming - }; - - // Close confirmation modal without performing any action - confirmationCloseButton.onclick = () => { - confirmationModal.style.display = 'none'; - }; - } - - // Show final confirmation modal with success message - function showFinalConfirmationModal(message) { - finalConfirmationMessage.textContent = message; - finalConfirmationModal.style.display = 'flex'; // Show the final confirmation modal - finalConfirmationCloseButton.onclick = () => { - finalConfirmationModal.style.display = 'none'; // Close final confirmation modal - }; - } - - // Show custom modal when item is added to cart - function showItemAddedModal(message) { - itemAddedMessage.textContent = message; // Set message dynamically - itemAddedModal.style.display = 'flex'; // Show the modal - itemAddedClose.addEventListener('click', () => { - itemAddedModal.style.display = 'none'; // Close the modal - }); - } - - // Attach event listeners to both cart buttons - [shoppingCartButton, cartDetailsButton].forEach(button => { - if (button) { - button.addEventListener('click', showModal); // Open modal when clicked - } - }); - - // Close modal when clicking outside of it - window.addEventListener('click', event => { - if (event.target === modal) { - modal.style.display = 'none'; - } - }); - - // Close the modal by clicking the close button (for cart modal) - if (closeModal) { - closeModal.addEventListener('click', () => { - modal.style.display = 'none'; - }); - } - - // Add to cart functionality - const addToCartButtons = document.querySelectorAll('.add-to-cart-btn'); - addToCartButtons.forEach(button => { - button.addEventListener('click', () => { - const productId = parseInt(button.dataset.productId, 10); - const product = products.find(item => item.id === productId); - - if (product) { - const existingProduct = cart.find(item => item.id === productId); - - if (existingProduct) { - existingProduct.quantity++; - } else { - cart.push({ ...product, quantity: 1 }); - } - - sessionStorage.setItem('cart', JSON.stringify(cart)); // Save cart to session storage - showItemAddedModal(`${product.name} has been added to the cart!`); // Show custom modal - } - }); - }); - - // Event listener for Clear Cart button in the modal - if (clearCartModalButton) { - clearCartModalButton.addEventListener('click', () => { - showConfirmationModal('Are you sure you want to clear the cart?', () => { - sessionStorage.removeItem('cart'); - cart = []; - renderCart(); // Re-render cart after clearing it - showFinalConfirmationModal('Cart has been cleared!'); // Show final confirmation for cart clearing - }); - }); - } - - // Event listener for Process Order button in the modal - if (processOrderModalButton) { - processOrderModalButton.addEventListener('click', () => { - if (cart.length === 0) { - showItemAddedModal('Your cart is empty. Please add items to the cart before processing the order.'); - return; - } - - showConfirmationModal('Are you sure you want to process your order?', () => { - const receiptNumber = Math.floor(Math.random() * 1000000); // Generate receipt number - showFinalConfirmationModal(`Thank you for your order!\nYour receipt number is ${receiptNumber}.`); - sessionStorage.removeItem('cart'); - cart = []; - renderCart(); // Re-render cart after processing the order - }); - }); - } -}); - -const allCloseButtons = document.querySelectorAll('.close-modal'); -allCloseButtons.forEach(button => { - button.addEventListener('click', () => { - // Close the parent modal of the button clicked - const modal = button.closest('.modal'); - modal.style.display = 'none'; - }); -}); +document.addEventListener('DOMContentLoaded', () => { + let cart = JSON.parse(sessionStorage.getItem('cart')) || []; + + // Get modal and cart-related elements + const modal = document.getElementById('cart-modal'); + const closeModal = document.querySelector('.close-modal'); + const cartItemsContainer = document.getElementById('cart-items'); + const cartTotalContainer = document.getElementById('cart-total'); + const clearCartModalButton = document.getElementById('clear-cart-modal-btn'); + const processOrderModalButton = document.getElementById('process-order-modal-btn'); + + // Custom confirmation modals for clear cart and process order + const confirmationModal = document.getElementById('confirmation-modal'); + const confirmationMessage = document.getElementById('confirmation-message'); + const confirmationCloseButton = document.getElementById('confirmation-close-btn'); + const confirmationConfirmButton = document.getElementById('confirmation-confirm-btn'); + + // Buttons + const shoppingCartButton = document.getElementById('shopping-cart'); + const cartDetailsButton = document.getElementById('cart-details'); + + // Custom alert modal for item added + const itemAddedModal = document.getElementById('item-added-modal'); + const itemAddedMessage = document.getElementById('item-added-message'); + const itemAddedClose = document.getElementById('item-added-close'); + + // Final confirmation modal for success messages + const finalConfirmationModal = document.getElementById('final-confirmation-modal'); + const finalConfirmationMessage = document.getElementById('final-confirmation-message'); + const finalConfirmationCloseButton = document.getElementById('final-confirmation-close-btn'); + + // Function to render the cart + function renderCart() { + cart = JSON.parse(sessionStorage.getItem('cart')) || []; + cartItemsContainer.innerHTML = ''; // Clear existing items + let total = 0; + + if (cart.length === 0) { + cartItemsContainer.innerHTML = '
  • Your cart is empty.
  • '; + cartTotalContainer.textContent = ''; + return; + } + + cart.forEach(item => { + const itemTotal = item.price * item.quantity; + total += itemTotal; + + const listItem = document.createElement('li'); + listItem.textContent = `${item.name} x ${item.quantity} - $${itemTotal.toFixed(2)}`; + cartItemsContainer.appendChild(listItem); + }); + + cartTotalContainer.textContent = `Subtotal: $${total.toFixed(2)}`; + } + + // Show cart modal with current cart content + function showModal() { + renderCart(); // Always render the latest cart + modal.style.display = 'flex'; // Show the cart modal + } + + // Show confirmation modal for actions (clear or process order) + function showConfirmationModal(message, action) { + confirmationMessage.textContent = message; + confirmationModal.style.display = 'flex'; // Show the confirmation modal + + // Confirm action on the "Confirm" button + confirmationConfirmButton.onclick = () => { + action(); // Execute the passed action (clear cart, process order) + confirmationModal.style.display = 'none'; // Close the confirmation modal after confirming + }; + + // Close confirmation modal without performing any action + confirmationCloseButton.onclick = () => { + confirmationModal.style.display = 'none'; + }; + } + + // Show final confirmation modal with success message + function showFinalConfirmationModal(message) { + finalConfirmationMessage.textContent = message; + finalConfirmationModal.style.display = 'flex'; // Show the final confirmation modal + finalConfirmationCloseButton.onclick = () => { + finalConfirmationModal.style.display = 'none'; // Close final confirmation modal + }; + } + + // Show custom modal when item is added to cart + function showItemAddedModal(message) { + itemAddedMessage.textContent = message; // Set message dynamically + itemAddedModal.style.display = 'flex'; // Show the modal + itemAddedClose.addEventListener('click', () => { + itemAddedModal.style.display = 'none'; // Close the modal + }); + } + + // Attach event listeners to both cart buttons + [shoppingCartButton, cartDetailsButton].forEach(button => { + if (button) { + button.addEventListener('click', showModal); // Open modal when clicked + } + }); + + // Close modal when clicking outside of it + window.addEventListener('click', event => { + if (event.target === modal) { + modal.style.display = 'none'; + } + }); + + // Close the modal by clicking the close button (for cart modal) + if (closeModal) { + closeModal.addEventListener('click', () => { + modal.style.display = 'none'; + }); + } + + // Add to cart functionality + const addToCartButtons = document.querySelectorAll('.add-to-cart-btn'); + addToCartButtons.forEach(button => { + button.addEventListener('click', () => { + const productId = parseInt(button.dataset.productId, 10); + const product = products.find(item => item.id === productId); + + if (product) { + const existingProduct = cart.find(item => item.id === productId); + + if (existingProduct) { + existingProduct.quantity++; + } else { + cart.push({ ...product, quantity: 1 }); + } + + sessionStorage.setItem('cart', JSON.stringify(cart)); // Save cart to session storage + showItemAddedModal(`${product.name} has been added to the cart!`); // Show custom modal + } + }); + }); + + // Event listener for Clear Cart button in the modal + if (clearCartModalButton) { + clearCartModalButton.addEventListener('click', () => { + showConfirmationModal('Are you sure you want to clear the cart?', () => { + sessionStorage.removeItem('cart'); + cart = []; + renderCart(); // Re-render cart after clearing it + showFinalConfirmationModal('Cart has been cleared!'); // Show final confirmation for cart clearing + }); + }); + } + + // Event listener for Process Order button in the modal + if (processOrderModalButton) { + processOrderModalButton.addEventListener('click', () => { + if (cart.length === 0) { + showItemAddedModal('Your cart is empty. Please add items to the cart before processing the order.'); + return; + } + + showConfirmationModal('Are you sure you want to process your order?', () => { + const receiptNumber = Math.floor(Math.random() * 1000000); // Generate receipt number + showFinalConfirmationModal(`Thank you for your order!\nYour receipt number is ${receiptNumber}.`); + sessionStorage.removeItem('cart'); + cart = []; + renderCart(); // Re-render cart after processing the order + }); + }); + } +}); + +const allCloseButtons = document.querySelectorAll('.close-modal'); +allCloseButtons.forEach(button => { + button.addEventListener('click', () => { + // Close the parent modal of the button clicked + const modal = button.closest('.modal'); + modal.style.display = 'none'; + }); +}); diff --git a/feedback.js b/src/scripts/feedback.js similarity index 97% rename from feedback.js rename to src/scripts/feedback.js index 1ecc2bc..5977d04 100644 --- a/feedback.js +++ b/src/scripts/feedback.js @@ -1,93 +1,93 @@ -document.addEventListener('DOMContentLoaded', () => { - const feedbackForm = document.querySelector('#feedback-form form'); - const nameInput = document.getElementById('name'); - const emailInput = document.getElementById('email'); - const phoneInput = document.getElementById('tel'); - const messageInput = document.getElementById('message'); - - const alertBox = document.getElementById('custom-alert'); - const alertMessage = document.getElementById('alert-message'); - const alertOkButton = document.getElementById('alert-ok-button'); - const alertCloseButton = document.getElementById('alert-close-btn'); - - const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/; // Email validation regex - const phoneRegex = /^[0-9]{10,15}$/; // Phone validation regex (10-15 digits) - const nameRegex = /^[a-zA-Z\s]{2,}$/; // Name validation regex (at least 2 letters) - const sqlInjectionRegex = /[;'"\\]/; // Prevent SQL injection-like characters - - // Form submission handler - feedbackForm.addEventListener('submit', (event) => { - event.preventDefault(); // Prevent form submission and page refresh - - const name = nameInput.value.trim(); - const email = emailInput.value.trim(); - const phone = phoneInput.value.trim(); - const message = messageInput.value.trim(); - - // Validate each field - if (!nameRegex.test(name)) { - showCustomAlert('Please enter a valid name (letters and spaces only).'); - return; - } - - if (!emailRegex.test(email)) { - showCustomAlert('Please enter a valid email address.'); - return; - } - - if (!phoneRegex.test(phone)) { - showCustomAlert('Please enter a valid phone number (10-15 digits).'); - return; - } - - if (sqlInjectionRegex.test(message)) { - showCustomAlert('Your message contains invalid characters.'); - return; - } - - // Save feedback to localStorage - const feedbackData = { - name, - email, - phone, - message, - timestamp: new Date().toISOString(), - }; - - // Retrieve existing feedback data or initialize an empty array - const feedbackList = JSON.parse(localStorage.getItem('feedbackList')) || []; - feedbackList.push(feedbackData); // Add new feedback to the list - localStorage.setItem('feedbackList', JSON.stringify(feedbackList)); // Save updated list to localStorage - console.log('Feedback saved to localStorage:', feedbackList); - - // Show success message - showCustomAlert('Thank you for your feedback! We appreciate hearing from you.'); - feedbackForm.reset(); // Clear the input fields after submission - }); - - // Function to show the custom alert modal - function showCustomAlert(message) { - alertMessage.textContent = message; // Set modal message - alertBox.classList.remove('hidden'); // Display the modal - alertBox.style.display = 'flex'; // Ensure the modal is visible - } - - // Function to close the custom alert modal - function closeCustomAlert() { - alertBox.classList.add('hidden'); // Hide the modal - alertBox.style.display = 'none'; // Ensure it's hidden - } - - // Close modal on "OK" button click - alertOkButton.addEventListener('click', closeCustomAlert); - - // Close modal on "X" button click - alertCloseButton.addEventListener('click', closeCustomAlert); - - // Close modal when clicking outside the modal content - window.addEventListener('click', (event) => { - if (event.target === alertBox) { - closeCustomAlert(); - } - }); -}); +document.addEventListener('DOMContentLoaded', () => { + const feedbackForm = document.querySelector('#feedback-form form'); + const nameInput = document.getElementById('name'); + const emailInput = document.getElementById('email'); + const phoneInput = document.getElementById('tel'); + const messageInput = document.getElementById('message'); + + const alertBox = document.getElementById('custom-alert'); + const alertMessage = document.getElementById('alert-message'); + const alertOkButton = document.getElementById('alert-ok-button'); + const alertCloseButton = document.getElementById('alert-close-btn'); + + const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/; // Email validation regex + const phoneRegex = /^[0-9]{10,15}$/; // Phone validation regex (10-15 digits) + const nameRegex = /^[a-zA-Z\s]{2,}$/; // Name validation regex (at least 2 letters) + const sqlInjectionRegex = /[;'"\\]/; // Prevent SQL injection-like characters + + // Form submission handler + feedbackForm.addEventListener('submit', (event) => { + event.preventDefault(); // Prevent form submission and page refresh + + const name = nameInput.value.trim(); + const email = emailInput.value.trim(); + const phone = phoneInput.value.trim(); + const message = messageInput.value.trim(); + + // Validate each field + if (!nameRegex.test(name)) { + showCustomAlert('Please enter a valid name (letters and spaces only).'); + return; + } + + if (!emailRegex.test(email)) { + showCustomAlert('Please enter a valid email address.'); + return; + } + + if (!phoneRegex.test(phone)) { + showCustomAlert('Please enter a valid phone number (10-15 digits).'); + return; + } + + if (sqlInjectionRegex.test(message)) { + showCustomAlert('Your message contains invalid characters.'); + return; + } + + // Save feedback to localStorage + const feedbackData = { + name, + email, + phone, + message, + timestamp: new Date().toISOString(), + }; + + // Retrieve existing feedback data or initialize an empty array + const feedbackList = JSON.parse(localStorage.getItem('feedbackList')) || []; + feedbackList.push(feedbackData); // Add new feedback to the list + localStorage.setItem('feedbackList', JSON.stringify(feedbackList)); // Save updated list to localStorage + console.log('Feedback saved to localStorage:', feedbackList); + + // Show success message + showCustomAlert('Thank you for your feedback! We appreciate hearing from you.'); + feedbackForm.reset(); // Clear the input fields after submission + }); + + // Function to show the custom alert modal + function showCustomAlert(message) { + alertMessage.textContent = message; // Set modal message + alertBox.classList.remove('hidden'); // Display the modal + alertBox.style.display = 'flex'; // Ensure the modal is visible + } + + // Function to close the custom alert modal + function closeCustomAlert() { + alertBox.classList.add('hidden'); // Hide the modal + alertBox.style.display = 'none'; // Ensure it's hidden + } + + // Close modal on "OK" button click + alertOkButton.addEventListener('click', closeCustomAlert); + + // Close modal on "X" button click + alertCloseButton.addEventListener('click', closeCustomAlert); + + // Close modal when clicking outside the modal content + window.addEventListener('click', (event) => { + if (event.target === alertBox) { + closeCustomAlert(); + } + }); +}); diff --git a/gallery-carousel.js b/src/scripts/gallery-carousel.js similarity index 97% rename from gallery-carousel.js rename to src/scripts/gallery-carousel.js index 97c7a20..05510b6 100644 --- a/gallery-carousel.js +++ b/src/scripts/gallery-carousel.js @@ -1,130 +1,130 @@ -// Gallery Carousel .js -const products = { - trees: [ - { id: 1, name: "Crepe Mertyl Tree", description: "Beautiful Crepe Mertyl tree.", price: 55.00, image: "images/trees/crepe-mertyl.jpg" }, - { id: 2, name: "Silver Birch Tree", description: "Sturdy Silver Birch tree.", price: 45.00, image: "images/trees/silver-birch.jpg" }, - { id: 3, name: "Apple Tree", description: "Fruitful apple tree.", price: 35.00, image: "images/trees/apple-tree.jpg" }, - { id: 4, name: "Potted Spruce Tree", description: "Miniature Spruce in a white planter.", price: 35.00, image: "images/trees/potted-spruce.jpg" } - ], - indoor: [ - { id: 5, name: "Aloe Plant", description: "Thrives with 6-8 hours of direct sunlight a day.", price: 15.00, image: "images/indoor/aloe-plant.jpg" }, - { id: 6, name: "Peperonia Plant", description: "Low-maintenance and perfect for spaces with lots of natural light.", price: 12.50, image: "images/indoor/peperonia.jpg" }, - { id: 7, name: "String-of-Pearls Plant", description: "Best placed in east-facing windows or on shaded patios and balconies.", price: 20.00, image: "images/indoor/string-of-pearls.jpg" }, - { id: 12, name: "Venus Fly Trap", description: "Perfect for young botanists or your fly problem!", price: 12.50, image: "images/indoor/venus-fly-trap.jpg"} - ], - tools: [ - { id: 8, name: "Watering Cans", description: "Galvanized aluminum watering cans (x2).", price: 25.00, image: "images/tools/watering-cans.jpg" }, - { id: 9, name: "Potting Soil", description: "Premium-blend of nutrient-rich potting soil - 10 lb bag.", price: 8.00, image: "images/tools/potting-soil.png" }, - { id: 10, name: "Bird House", description: "Handmade wooden bird house for hanging or mounting.", price: 11.00, image: "images/tools/birdhouse.jpg" }, - { id: 11, name: "Gardening Tools", description: "Wooden handled gardening tools.", price: 20.00, image: "images/tools/gardening-tools.jpg"} - ] -}; - -document.addEventListener('DOMContentLoaded', () => { - console.log("DOM fully loaded and parsed"); // Check if the DOM is ready - - const productCarousel = document.getElementById('product-carousel'); - const scrollLeftButton = document.getElementById('scroll-left'); - const scrollRightButton = document.getElementById('scroll-right'); - const categoryButtons = document.querySelectorAll('.cat-btn'); - - // Scroll button functionality - scrollLeftButton.addEventListener('click', () => { - productCarousel.scrollBy({ left: -300, behavior: 'smooth' }); - }); - - scrollRightButton.addEventListener('click', () => { - productCarousel.scrollBy({ left: 300, behavior: 'smooth' }); - }); - - // Map buttons to categories - categoryButtons.forEach(button => { - button.addEventListener('click', (event) => { - event.preventDefault(); // Prevent default navigation - const url = new URL(button.href); // Parse the URL - const category = url.searchParams.get('category'); // Get category from the query parameter - updateProductList(category); // Update the product list - }); - }); - - // Load default category or the one from the current URL - const currentUrl = new URL(window.location.href); - const defaultCategory = currentUrl.searchParams.get('category') || 'trees'; - updateProductList(defaultCategory); -}); - -function updateScrollButtons() { - const scrollLeftButton = document.getElementById('scroll-left'); - const scrollRightButton = document.getElementById('scroll-right'); - const productCarousel = document.getElementById('product-carousel'); - - scrollLeftButton.style.display = productCarousel.scrollLeft === 0 ? 'none' : 'block'; - scrollRightButton.style.display = - productCarousel.scrollWidth - productCarousel.clientWidth === productCarousel.scrollLeft - ? 'none' - : 'block'; -} - -function updateProductList(category) { - const productList = document.getElementById("product-list"); - if (!productList) { - console.error("Element with ID 'product-list' not found in the DOM."); - return; - } - - productList.innerHTML = ""; // Clear existing products - console.log(`Updating product list for category: ${category}`); // Debugging line - - const selectedProducts = products[category]; - - if (selectedProducts) { - selectedProducts.forEach(product => { - const productCard = document.createElement("div"); - productCard.className = "product-card"; - - console.log(`Creating product card for: ${product.name}`); // Debugging line - - productCard.innerHTML = ` - ${product.name} -

    ${product.name}

    -

    ${product.description}

    -

    $${product.price}

    - - `; - productList.appendChild(productCard); - - // Add event listener for "Add to Cart" button - const addToCartButton = productCard.querySelector('.add-to-cart-btn'); - addToCartButton.addEventListener('click', () => { - addToCart(product.id); - }); - }); - } else { - console.error(`No products found for category: ${category}`); - } -} - -function addToCart(productId) { - const product = findProductById(productId); - if (product) { - let cart = JSON.parse(sessionStorage.getItem('cart')) || []; - const existingProduct = cart.find(item => item.id === productId); - - if (existingProduct) { - existingProduct.quantity++; - } else { - cart.push({ ...product, quantity: 1 }); - } - - sessionStorage.setItem('cart', JSON.stringify(cart)); - alert(`${product.name} has been added to your cart!`); - } -} - -function findProductById(productId) { - for (let category in products) { - const product = products[category].find(item => item.id === productId); - if (product) return product; - } - return null; -} +// Gallery Carousel .js +const products = { + trees: [ + { id: 1, name: "Crepe Mertyl Tree", description: "Beautiful Crepe Mertyl tree.", price: 55.00, image: "images/trees/crepe-mertyl.jpg" }, + { id: 2, name: "Silver Birch Tree", description: "Sturdy Silver Birch tree.", price: 45.00, image: "images/trees/silver-birch.jpg" }, + { id: 3, name: "Apple Tree", description: "Fruitful apple tree.", price: 35.00, image: "images/trees/apple-tree.jpg" }, + { id: 4, name: "Potted Spruce Tree", description: "Miniature Spruce in a white planter.", price: 35.00, image: "images/trees/potted-spruce.jpg" } + ], + indoor: [ + { id: 5, name: "Aloe Plant", description: "Thrives with 6-8 hours of direct sunlight a day.", price: 15.00, image: "images/indoor/aloe-plant.jpg" }, + { id: 6, name: "Peperonia Plant", description: "Low-maintenance and perfect for spaces with lots of natural light.", price: 12.50, image: "images/indoor/peperonia.jpg" }, + { id: 7, name: "String-of-Pearls Plant", description: "Best placed in east-facing windows or on shaded patios and balconies.", price: 20.00, image: "images/indoor/string-of-pearls.jpg" }, + { id: 12, name: "Venus Fly Trap", description: "Perfect for young botanists or your fly problem!", price: 12.50, image: "images/indoor/venus-fly-trap.jpg"} + ], + tools: [ + { id: 8, name: "Watering Cans", description: "Galvanized aluminum watering cans (x2).", price: 25.00, image: "images/tools/watering-cans.jpg" }, + { id: 9, name: "Potting Soil", description: "Premium-blend of nutrient-rich potting soil - 10 lb bag.", price: 8.00, image: "images/tools/potting-soil.png" }, + { id: 10, name: "Bird House", description: "Handmade wooden bird house for hanging or mounting.", price: 11.00, image: "images/tools/birdhouse.jpg" }, + { id: 11, name: "Gardening Tools", description: "Wooden handled gardening tools.", price: 20.00, image: "images/tools/gardening-tools.jpg"} + ] +}; + +document.addEventListener('DOMContentLoaded', () => { + console.log("DOM fully loaded and parsed"); // Check if the DOM is ready + + const productCarousel = document.getElementById('product-carousel'); + const scrollLeftButton = document.getElementById('scroll-left'); + const scrollRightButton = document.getElementById('scroll-right'); + const categoryButtons = document.querySelectorAll('.cat-btn'); + + // Scroll button functionality + scrollLeftButton.addEventListener('click', () => { + productCarousel.scrollBy({ left: -300, behavior: 'smooth' }); + }); + + scrollRightButton.addEventListener('click', () => { + productCarousel.scrollBy({ left: 300, behavior: 'smooth' }); + }); + + // Map buttons to categories + categoryButtons.forEach(button => { + button.addEventListener('click', (event) => { + event.preventDefault(); // Prevent default navigation + const url = new URL(button.href); // Parse the URL + const category = url.searchParams.get('category'); // Get category from the query parameter + updateProductList(category); // Update the product list + }); + }); + + // Load default category or the one from the current URL + const currentUrl = new URL(window.location.href); + const defaultCategory = currentUrl.searchParams.get('category') || 'trees'; + updateProductList(defaultCategory); +}); + +function updateScrollButtons() { + const scrollLeftButton = document.getElementById('scroll-left'); + const scrollRightButton = document.getElementById('scroll-right'); + const productCarousel = document.getElementById('product-carousel'); + + scrollLeftButton.style.display = productCarousel.scrollLeft === 0 ? 'none' : 'block'; + scrollRightButton.style.display = + productCarousel.scrollWidth - productCarousel.clientWidth === productCarousel.scrollLeft + ? 'none' + : 'block'; +} + +function updateProductList(category) { + const productList = document.getElementById("product-list"); + if (!productList) { + console.error("Element with ID 'product-list' not found in the DOM."); + return; + } + + productList.innerHTML = ""; // Clear existing products + console.log(`Updating product list for category: ${category}`); // Debugging line + + const selectedProducts = products[category]; + + if (selectedProducts) { + selectedProducts.forEach(product => { + const productCard = document.createElement("div"); + productCard.className = "product-card"; + + console.log(`Creating product card for: ${product.name}`); // Debugging line + + productCard.innerHTML = ` + ${product.name} +

    ${product.name}

    +

    ${product.description}

    +

    $${product.price}

    + + `; + productList.appendChild(productCard); + + // Add event listener for "Add to Cart" button + const addToCartButton = productCard.querySelector('.add-to-cart-btn'); + addToCartButton.addEventListener('click', () => { + addToCart(product.id); + }); + }); + } else { + console.error(`No products found for category: ${category}`); + } +} + +function addToCart(productId) { + const product = findProductById(productId); + if (product) { + let cart = JSON.parse(sessionStorage.getItem('cart')) || []; + const existingProduct = cart.find(item => item.id === productId); + + if (existingProduct) { + existingProduct.quantity++; + } else { + cart.push({ ...product, quantity: 1 }); + } + + sessionStorage.setItem('cart', JSON.stringify(cart)); + alert(`${product.name} has been added to your cart!`); + } +} + +function findProductById(productId) { + for (let category in products) { + const product = products[category].find(item => item.id === productId); + if (product) return product; + } + return null; +} diff --git a/newsletter.js b/src/scripts/newsletter.js similarity index 97% rename from newsletter.js rename to src/scripts/newsletter.js index 30909e9..609a7bd 100644 --- a/newsletter.js +++ b/src/scripts/newsletter.js @@ -1,50 +1,50 @@ -document.addEventListener('DOMContentLoaded', () => { - const newsletterForm = document.getElementById('newsletter-form'); - const emailInput = document.getElementById('email-input'); - const alertBox = document.getElementById('custom-alert'); - const alertMessage = document.getElementById('alert-message'); - const alertOkButton = document.getElementById('alert-ok-button'); - const alertCloseButton = document.getElementById('alert-close-btn'); - - // Form submission handler - newsletterForm.addEventListener('submit', (event) => { - event.preventDefault(); // Prevent form from submitting and refreshing the page - - const email = emailInput.value.trim(); - const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/; - - // Check if email is valid - if (!emailRegex.test(email)) { - showCustomAlert('Please enter a valid email address.'); - return; - } - - // Show success message - showCustomAlert(`Thank you for subscribing, ${email}!`); - newsletterForm.reset(); // Clear the input field after submission - }); - - // Function to show the custom alert modal - function showCustomAlert(message) { - alertMessage.textContent = message; // Set the alert message - alertBox.classList.remove('hidden'); // Show the alert modal - alertBox.style.display = 'flex'; // Ensure the modal is displayed - - // Close the modal when the "OK" button is clicked - alertOkButton.addEventListener('click', closeCustomAlert); - alertCloseButton.addEventListener('click', closeCustomAlert); - } - - // Function to hide the custom alert modal - function closeCustomAlert() { - alertBox.classList.add('hidden'); // Hide the alert modal - alertBox.style.display = 'none'; // Ensure the modal is hidden - } - - // Close the modal if clicking outside the modal content - window.addEventListener('click', (event) => { - if (event.target === alertBox) { - closeCustomAlert(); - } - }); -}); +document.addEventListener('DOMContentLoaded', () => { + const newsletterForm = document.getElementById('newsletter-form'); + const emailInput = document.getElementById('email-input'); + const alertBox = document.getElementById('custom-alert'); + const alertMessage = document.getElementById('alert-message'); + const alertOkButton = document.getElementById('alert-ok-button'); + const alertCloseButton = document.getElementById('alert-close-btn'); + + // Form submission handler + newsletterForm.addEventListener('submit', (event) => { + event.preventDefault(); // Prevent form from submitting and refreshing the page + + const email = emailInput.value.trim(); + const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/; + + // Check if email is valid + if (!emailRegex.test(email)) { + showCustomAlert('Please enter a valid email address.'); + return; + } + + // Show success message + showCustomAlert(`Thank you for subscribing, ${email}!`); + newsletterForm.reset(); // Clear the input field after submission + }); + + // Function to show the custom alert modal + function showCustomAlert(message) { + alertMessage.textContent = message; // Set the alert message + alertBox.classList.remove('hidden'); // Show the alert modal + alertBox.style.display = 'flex'; // Ensure the modal is displayed + + // Close the modal when the "OK" button is clicked + alertOkButton.addEventListener('click', closeCustomAlert); + alertCloseButton.addEventListener('click', closeCustomAlert); + } + + // Function to hide the custom alert modal + function closeCustomAlert() { + alertBox.classList.add('hidden'); // Hide the alert modal + alertBox.style.display = 'none'; // Ensure the modal is hidden + } + + // Close the modal if clicking outside the modal content + window.addEventListener('click', (event) => { + if (event.target === alertBox) { + closeCustomAlert(); + } + }); +}); diff --git a/script.js b/src/scripts/script.js similarity index 100% rename from script.js rename to src/scripts/script.js diff --git a/styles.css b/src/styles/styles.css similarity index 100% rename from styles.css rename to src/styles/styles.css