diff --git a/package-lock.json b/package-lock.json index f34a88e..231468f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,9 @@ "version": "0.0.1", "dependencies": { "fp-ts": "^2.16.1", - "io-ts": "^2.2.20" + "io-ts": "^2.2.20", + "slugify": "^1.6.6", + "svelte-markdown": "^0.4.0" }, "devDependencies": { "@sveltejs/adapter-auto": "^2.0.0", @@ -30,7 +32,6 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", - "dev": true, "dependencies": { "@jridgewell/gen-mapping": "^0.3.0", "@jridgewell/trace-mapping": "^0.3.9" @@ -404,7 +405,6 @@ "version": "0.3.3", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", - "dev": true, "dependencies": { "@jridgewell/set-array": "^1.0.1", "@jridgewell/sourcemap-codec": "^1.4.10", @@ -418,7 +418,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", - "dev": true, "engines": { "node": ">=6.0.0" } @@ -427,7 +426,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", - "dev": true, "engines": { "node": ">=6.0.0" } @@ -435,14 +433,12 @@ "node_modules/@jridgewell/sourcemap-codec": { "version": "1.4.15", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "dev": true + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.20", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz", "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==", - "dev": true, "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" @@ -749,8 +745,12 @@ "node_modules/@types/estree": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", - "dev": true + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==" + }, + "node_modules/@types/marked": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@types/marked/-/marked-5.0.2.tgz", + "integrity": "sha512-OucS4KMHhFzhz27KxmWg7J+kIYqyqoW5kdIEI319hqARQQUTqhao3M/F+uFnDXD0Rg72iDDZxZNxq5gvctmLlg==" }, "node_modules/@types/pug": { "version": "2.0.9", @@ -780,7 +780,6 @@ "version": "8.11.2", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", - "dev": true, "bin": { "acorn": "bin/acorn" }, @@ -805,7 +804,6 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", - "dev": true, "dependencies": { "dequal": "^2.0.3" } @@ -814,7 +812,6 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.2.1.tgz", "integrity": "sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==", - "dev": true, "dependencies": { "dequal": "^2.0.3" } @@ -984,7 +981,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/code-red/-/code-red-1.0.4.tgz", "integrity": "sha512-7qJWqItLA8/VPVlKJlFXU+NBlo/qyfs39aJcuMT/2ere32ZqvF5OSxgdM5xOfJJ7O429gg2HM47y8v9P+9wrNw==", - "dev": true, "dependencies": { "@jridgewell/sourcemap-codec": "^1.4.15", "@types/estree": "^1.0.1", @@ -1068,7 +1064,6 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", - "dev": true, "dependencies": { "mdn-data": "2.0.30", "source-map-js": "^1.0.1" @@ -1131,7 +1126,6 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", - "dev": true, "engines": { "node": ">=6" } @@ -1234,7 +1228,6 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", - "dev": true, "dependencies": { "@types/estree": "^1.0.0" } @@ -1578,7 +1571,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.2.tgz", "integrity": "sha512-v3rht/LgVcsdZa3O2Nqs+NMowLOxeOm7Ay9+/ARQ2F+qEoANRcqrjAZKGN0v8ymUetZGgkp26LTnGT7H0Qo9Pg==", - "dev": true, "dependencies": { "@types/estree": "*" } @@ -1595,8 +1587,7 @@ "node_modules/locate-character": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-character/-/locate-character-3.0.0.tgz", - "integrity": "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==", - "dev": true + "integrity": "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==" }, "node_modules/lorem-ipsum": { "version": "2.0.8", @@ -1630,7 +1621,6 @@ "version": "0.30.5", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.5.tgz", "integrity": "sha512-7xlpfBaQaP/T6Vh8MO/EqXSW5En6INHEvEXQiuff7Gku0PWjU3uf6w/j9o7O+SpB5fOAkrI5HeoNgwjEO0pFsA==", - "dev": true, "dependencies": { "@jridgewell/sourcemap-codec": "^1.4.15" }, @@ -1638,11 +1628,21 @@ "node": ">=12" } }, + "node_modules/marked": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/marked/-/marked-5.1.2.tgz", + "integrity": "sha512-ahRPGXJpjMjwSOlBoTMZAK7ATXkli5qCPxZ21TG44rx1KEo44bii4ekgTDQPNRQ4Kh7JMb9Ub1PVk1NxRSsorg==", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 16" + } + }, "node_modules/mdn-data": { "version": "2.0.30", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", - "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", - "dev": true + "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==" }, "node_modules/merge2": { "version": "1.4.1", @@ -1841,7 +1841,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/periscopic/-/periscopic-3.1.0.tgz", "integrity": "sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==", - "dev": true, "dependencies": { "@types/estree": "^1.0.0", "estree-walker": "^3.0.0", @@ -2285,6 +2284,14 @@ "node": ">= 10" } }, + "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==", + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/sorcery": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/sorcery/-/sorcery-0.11.0.tgz", @@ -2304,7 +2311,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -2365,7 +2371,6 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/svelte/-/svelte-4.2.3.tgz", "integrity": "sha512-sqmG9KC6uUc7fb3ZuWoxXvqk6MI9Uu4ABA1M0fYDgTlFYu1k02xp96u6U9+yJZiVm84m9zge7rrA/BNZdFpOKw==", - "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.1", "@jridgewell/sourcemap-codec": "^1.4.15", @@ -2419,6 +2424,18 @@ "svelte": "^3.19.0 || ^4.0.0" } }, + "node_modules/svelte-markdown": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/svelte-markdown/-/svelte-markdown-0.4.0.tgz", + "integrity": "sha512-d8xYJoPhhiLn/tFrO54V5p22q2+I7It8w3CpTv+O+h99LlgehxK9XwdISVBl2aNcLbLX128Nz/vu7GScWhVZjw==", + "dependencies": { + "@types/marked": "^5.0.1", + "marked": "^5.1.2" + }, + "peerDependencies": { + "svelte": "^4.0.0" + } + }, "node_modules/svelte-preprocess": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/svelte-preprocess/-/svelte-preprocess-5.1.0.tgz", diff --git a/package.json b/package.json index 61c198d..595beca 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,8 @@ "type": "module", "dependencies": { "fp-ts": "^2.16.1", - "io-ts": "^2.2.20" + "io-ts": "^2.2.20", + "slugify": "^1.6.6", + "svelte-markdown": "^0.4.0" } } diff --git a/src/lib/assets/plants/dracaena-fragrans.toml b/src/lib/assets/plants/dracaena-fragrans.toml new file mode 100644 index 0000000..382e750 --- /dev/null +++ b/src/lib/assets/plants/dracaena-fragrans.toml @@ -0,0 +1,46 @@ +slug = "dracaena-fragrans" +name = "Dracaena Fragrans" +bin_name = "Dracaena Fragrans" + +[image] +remote = "https://upload.wikimedia.org/wikipedia/commons/6/64/Dracaena_fragrans_a1.jpg" +source = "https://commons.wikimedia.org/wiki/File:Dracaena_fragrans_a1.jpg" +alt = """ +Dracaena Fragrans. \ +A plant with long leaves with a dark green middle part and \ +yellow edges on the leaves. The plant grows a green stalk with \ +leaves on it.""" + +[temp] +death = 10 +lower = 18 +upper = 25 + +[site] +description = """ +Dracaena Fragrans grows best in a shade with at most some direct sun exposure. It can grow in normal humidity. If Dracaena Fragrans gets too much light, its leaves will be scorced. If it get's too little light newly grown leaves will be smaller. +""" +light = "shade, some sun" +humidity = "normal" + + +[care] +description = """ +Dracaena Fragrans needs to be watered every twelve days when the top layer starts to dry out. But on't let the soil dry out completely. To increase humidity mist the plant weekly. It can be fertilized ever month with common fertilizer. +""" +water_schedule = "12 days" +mist_schedule = "week" +fertilize_schedule = "month" + +[common_issues] +description = """ +### Root Rot + +Signs for root rot might be yellow and dull leaves. In that case check the +roots for any visible rot (mushy roots are an indicator). The plant can be saved +by cutting away the rotten roots. + +### Pests + +Frequently Check the underside of leaves for any infestations. +""" diff --git a/src/lib/plants.ts b/src/lib/plants.ts index 64bfef1..efae7ed 100644 --- a/src/lib/plants.ts +++ b/src/lib/plants.ts @@ -1,9 +1,12 @@ -import aloeVera from "$lib/assets/plants/aloe-vera.toml"; -import monsteraDeliciosa from "$lib/assets/plants/monstera-deliciosa.toml"; import { isLeft } from "fp-ts/lib/Either"; import * as t from "io-ts"; import { PathReporter } from "io-ts/lib/PathReporter"; +const plantModules = import.meta.glob("$lib/assets/plants/*.toml", { + import: "default", + eager: true, +}); + const PlantDataTS = t.type({ slug: t.string, name: t.string, @@ -34,21 +37,27 @@ const PlantDataTS = t.type({ light: t.string, humidity: t.union([t.string, t.undefined]), }), + common_issues: t.union([ + t.type({ + description: t.string, + }), + t.undefined, + ]), }); export type PlantData = t.TypeOf; type PlantMap = { [key: PlantData["slug"]]: PlantData }; -export const plants: PlantMap = [aloeVera, monsteraDeliciosa].reduce( - (acc, cur) => { +export const plants: PlantMap = Object.values(plantModules).reduce( + (acc: PlantMap, cur) => { const decoded = PlantDataTS.decode(cur); if (isLeft(decoded)) { throw Error( `Invalid plant data ${PathReporter.report(decoded).join("\n")}`, ); } - acc[cur.slug] = decoded.right; + acc[decoded.right.slug] = decoded.right; return acc; }, {} as PlantMap, diff --git a/src/routes/plants/[plant]/+page.svelte b/src/routes/plants/[plant]/+page.svelte index c0b25db..8803185 100644 --- a/src/routes/plants/[plant]/+page.svelte +++ b/src/routes/plants/[plant]/+page.svelte @@ -2,7 +2,9 @@ import type { PageData } from "./$types"; import Badge from "./Badge.svelte"; import PlantImage from "./PlantImage.svelte"; + import Section from "./Section.svelte"; import TempBar from "./TempBar.svelte"; + import SvelteMarkdown from "svelte-markdown"; export let data: PageData; @@ -10,53 +12,59 @@

{data.name} ({data.bin_name})

-
-

Site

- +
+
+ - - - {#if data.site.humidity} - {/if} + + {#if data.site.humidity} + + {/if} +

- {@html data.site.description} +

-
-
-

Care

- - - - {#if data.care.mist_schedule} +
+
+
- {/if} - {#if data.care.clean_schedule} - - {/if} + {#if data.care.mist_schedule} + + {/if} + + {#if data.care.clean_schedule} + + {/if} +
-

{data.care.description}

-
+ +
+ {#if data.common_issues != null} +
+ +
+ {/if}
diff --git a/src/routes/plants/[plant]/Section.svelte b/src/routes/plants/[plant]/Section.svelte new file mode 100644 index 0000000..a86721a --- /dev/null +++ b/src/routes/plants/[plant]/Section.svelte @@ -0,0 +1,11 @@ + + +
+

{title}

+ + +