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
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Contact Us
-
-
Phone:
-
(555) 123-4567
-
- Hours of Operation
-
-
Monday - Friday:
-
9:00 AM - 6:00 PM
-
Saturday & Sunday:
-
10:00 AM - 5:00 PM
-
-
-
-
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!
-
-
-
-
-
-
-
-
-
-
- ×
-
Newsletter Subscription
-
-
- Subscribe
-
-
-
-
-
-
-
-
-
-
-
×
-
Your Shopping Cart
-
-
-
- Clear Cart
- Process Order
-
-
-
-
-
-
-
-
-
-
-
×
-
-
Confirm
-
Close
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
About Us - Bloom Valley Nursery
+
+
+
+
+
+
+
+
+ Bloom Valley Nursery
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Contact Us
+
+
Phone:
+
(555) 123-4567
+
+ Hours of Operation
+
+
Monday - Friday:
+
9:00 AM - 6:00 PM
+
Saturday & Sunday:
+
10:00 AM - 5:00 PM
+
+
+
+
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!
+
+
+
+
+
+
+
+
+
+
+ ×
+
Newsletter Subscription
+
+
+ Subscribe
+
+
+
+
+
+
+
+
+
+
+
×
+
Your Shopping Cart
+
+
+
+ Clear Cart
+ Process Order
+
+
+
+
+
+
+
+
+
+
+
×
+
+
Confirm
+
Close
+
+
+
+
+
+
+
+
+
+
+
+
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
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ×
-
Newsletter Subscription
-
-
- Subscribe
-
-
-
-
-
-
-
-
-
-
-
×
-
Your Shopping Cart
-
-
-
- Clear Cart
- Process Order
-
-
-
-
-
-
-
-
-
-
-
×
-
-
Confirm
-
Close
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
Community Events - Bloom Valley Nursery
+
+
+
+
+
+
+
+
+ Bloom Valley Nursery
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ×
+
Newsletter Subscription
+
+
+ Subscribe
+
+
+
+
+
+
+
+
+
+
+
×
+
Your Shopping Cart
+
+
+
+ Clear Cart
+ Process Order
+
+
+
+
+
+
+
+
+
+
+
×
+
+
Confirm
+
Close
+
+
+
+
+
+
+
+
+
+
+
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
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Products by Category
-
-
-
-
-
- View Shopping Cart
-
-
-
-
-
-
-
-
- ×
-
Newsletter Subscription
-
-
- Subscribe
-
-
-
-
-
-
-
-
-
-
-
×
-
Your Shopping Cart
-
-
-
- Clear Cart
- Process Order
-
-
-
-
-
-
-
-
-
-
-
×
-
-
Confirm
-
Close
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
Gallery - Bloom Valley Nursery
+
+
+
+
+
+
+
+
+ Bloom Valley Nursery
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Products by Category
+
+
+
+
+
+ View Shopping Cart
+
+
+
+
+
+
+
+
+ ×
+
Newsletter Subscription
+
+
+ Subscribe
+
+
+
+
+
+
+
+
+
+
+
×
+
Your Shopping Cart
+
+
+
+ Clear Cart
+ Process Order
+
+
+
+
+
+
+
+
+
+
+
×
+
+
Confirm
+
Close
+
+
+
+
+
+
+
+
+
+
+
+
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
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Shopper Perks
-
-
- 50% Off Deal -
-
New subscribers to our newsletter this month will receive a coupon for 50% off their first purchase! Click here for details! Terms and conditions apply.
-
-
-
Exceptional Quality
-
Every plant is carefully cultivated from seed or bulb to maturity, offering you vibrant, healthy specimens.
-
-
-
Expert Guidance
-
Our knowledgeable team is here to help, from selecting the perfect plants to offering planting tips.
-
-
-
Eco-Friendly Practices
-
We prioritize sustainability by using environmentally conscious growing methods, so you can feel good about your choices.
-
-
-
-
What Others Say
-
-
-
"My order arrived the very next day. The speed of delivery and high-quality products provided by Bloom Valley Nursery helped my project go smoothly from start to finish!"
-
- Caroline N.
-
-
-
"Thanks to the Gardening 101 Workshop with Bethany and Bloom Valley Nursery's amazing line of products, I won 'Best Azaleas' at the 2024 Royal Horticultural Society's American Cup!"
-
- Morris F.
-
-
-
"Bloom Valley Nursery's community garden inspired me take charge of my health. I was able to lose 50 pounds!"
-
- Gladis B.
-
-
-
-
-
- This Week's Featured Items
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
×
-
Your Shopping Cart
-
-
-
- Clear Cart
- Process Order
-
-
-
-
-
-
-
-
-
-
-
×
-
-
Confirm
-
Close
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
Homepage - Bloom Valley Nursery
+
+
+
+
+
+
+
+
+ Bloom Valley Nursery
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Shopper Perks
+
+
- 50% Off Deal -
+
New subscribers to our newsletter this month will receive a coupon for 50% off their first purchase! Click here for details! Terms and conditions apply.
+
+
+
Exceptional Quality
+
Every plant is carefully cultivated from seed or bulb to maturity, offering you vibrant, healthy specimens.
+
+
+
Expert Guidance
+
Our knowledgeable team is here to help, from selecting the perfect plants to offering planting tips.
+
+
+
Eco-Friendly Practices
+
We prioritize sustainability by using environmentally conscious growing methods, so you can feel good about your choices.
+
+
+
+
What Others Say
+
+
+
"My order arrived the very next day. The speed of delivery and high-quality products provided by Bloom Valley Nursery helped my project go smoothly from start to finish!"
+
- Caroline N.
+
+
+
"Thanks to the Gardening 101 Workshop with Bethany and Bloom Valley Nursery's amazing line of products, I won 'Best Azaleas' at the 2024 Royal Horticultural Society's American Cup!"
+
- Morris F.
+
+
+
"Bloom Valley Nursery's community garden inspired me take charge of my health. I was able to lose 50 pounds!"
+
- Gladis B.
+
+
+
+
+
+ This Week's Featured Items
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
×
+
Your Shopping Cart
+
+
+
+ Clear Cart
+ Process Order
+
+
+
+
+
+
+
+
+
+
+
×
+
+
Confirm
+
Close
+
+
+
+
+
+
+
+
+
+
+
+
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.description}
-
$${product.price}
-
Add to Cart
- `;
- 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.description}
+
$${product.price}
+
Add to Cart
+ `;
+ 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