From b0b7648ffd9a4b995cf027916855bdcde841a5a4 Mon Sep 17 00:00:00 2001 From: christian Date: Sun, 9 Jun 2024 13:45:14 +0200 Subject: [PATCH] render description as html. added css module to parsedDescription. --- package-lock.json | 148 ++++++++++++++++++ package.json | 1 + src/app/_jobcard/JobCard.tsx | 42 +++-- .../_jobcard/JobCardDescription.module.css | 50 ++++++ src/app/page.tsx | 8 +- 5 files changed, 235 insertions(+), 14 deletions(-) create mode 100644 src/app/_jobcard/JobCardDescription.module.css diff --git a/package-lock.json b/package-lock.json index e6540f1..2bce8d4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,7 @@ "@radix-ui/react-accordion": "^1.1.2", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", + "html-react-parser": "^5.1.10", "lucide-react": "^0.390.0", "next": "14.2.3", "react": "^18", @@ -1717,6 +1718,61 @@ "node": ">=6.0.0" } }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?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==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "BSD-2-Clause" + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "license": "BSD-2-Clause", + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", + "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", + "license": "BSD-2-Clause", + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -1743,6 +1799,18 @@ "node": ">=10.13.0" } }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/es-abstract": { "version": "1.23.3", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", @@ -2841,6 +2909,56 @@ "node": ">= 0.4" } }, + "node_modules/html-dom-parser": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/html-dom-parser/-/html-dom-parser-5.0.8.tgz", + "integrity": "sha512-vuWiX9EXgu8CJ5m9EP5c7bvBmNSuQVnrY8tl0z0ZX96Uth1IPlYH/8W8VZ/hBajFf18EN+j2pukbCNd01HEd1w==", + "license": "MIT", + "dependencies": { + "domhandler": "5.0.3", + "htmlparser2": "9.1.0" + } + }, + "node_modules/html-react-parser": { + "version": "5.1.10", + "resolved": "https://registry.npmjs.org/html-react-parser/-/html-react-parser-5.1.10.tgz", + "integrity": "sha512-gV22PvLij4wdEdtrZbGVC7Zy2OVWnQ0bYhX63S196ZRSx4+K0TuutCreHSXr+saUia8KeKB+2TYziVfijpH4Tw==", + "license": "MIT", + "dependencies": { + "domhandler": "5.0.3", + "html-dom-parser": "5.0.8", + "react-property": "2.0.2", + "style-to-js": "1.1.12" + }, + "peerDependencies": { + "@types/react": "17 || 18", + "react": "0.14 || 15 || 16 || 17 || 18" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/htmlparser2": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-9.1.0.tgz", + "integrity": "sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ==", + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.1.0", + "entities": "^4.5.0" + } + }, "node_modules/ignore": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", @@ -2897,6 +3015,12 @@ "dev": true, "license": "ISC" }, + "node_modules/inline-style-parser": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.3.tgz", + "integrity": "sha512-qlD8YNDqyTKTyuITrDOffsl6Tdhv+UC4hcdAVuQsK4IMQ99nSgd1MIA/Q+jQYoh9r3hVUXhYh7urSRmXPkW04g==", + "license": "MIT" + }, "node_modules/internal-slot": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", @@ -4275,6 +4399,12 @@ "dev": true, "license": "MIT" }, + "node_modules/react-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/react-property/-/react-property-2.0.2.tgz", + "integrity": "sha512-+PbtI3VuDV0l6CleQMsx2gtK0JZbZKbpdu5ynr+lbsuvtmgbNcS3VM0tuY2QjFNOcWxvXeHjDpy42RO+4U2rug==", + "license": "MIT" + }, "node_modules/read-cache": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", @@ -4816,6 +4946,24 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/style-to-js": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.12.tgz", + "integrity": "sha512-tv+/FkgNYHI2fvCoBMsqPHh5xovwiw+C3X0Gfnss/Syau0Nr3IqGOJ9XiOYXoPnToHVbllKFf5qCNFJGwFg5mg==", + "license": "MIT", + "dependencies": { + "style-to-object": "1.0.6" + } + }, + "node_modules/style-to-object": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.6.tgz", + "integrity": "sha512-khxq+Qm3xEyZfKd/y9L3oIWQimxuc4STrQKtQn8aSDRHb8mFgpukgX1hdzfrMEW6JCjyJ8p89x+IUMVnCBI1PA==", + "license": "MIT", + "dependencies": { + "inline-style-parser": "0.2.3" + } + }, "node_modules/styled-jsx": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz", diff --git a/package.json b/package.json index 3887ee2..b9a70ae 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "@radix-ui/react-accordion": "^1.1.2", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", + "html-react-parser": "^5.1.10", "lucide-react": "^0.390.0", "next": "14.2.3", "react": "^18", diff --git a/src/app/_jobcard/JobCard.tsx b/src/app/_jobcard/JobCard.tsx index a9c1cee..633808f 100644 --- a/src/app/_jobcard/JobCard.tsx +++ b/src/app/_jobcard/JobCard.tsx @@ -1,3 +1,12 @@ +import { + Accordion, + AccordionContent, + AccordionItem, + AccordionTrigger, +} from "@/components/ui/accordion"; +import parse from "html-react-parser"; +import styles from "./JobCardDescription.module.css"; + interface JobPosting { title: string; logo: string; @@ -20,17 +29,28 @@ interface JobPosting { export default async function JobCard(props: { job: JobPosting }) { const { title, logo, company, location, type, description, link, skills } = props.job; + const parsedDescription = parse(description); + return ( -
-

{title}

-

- {company} - {location} -

-

{type}

-

{description.slice(0, 400)}...

- - Link - -
+ + + +
+

{title}

+
+ {company} + {location} + {type} +
+
+
+
+ +
+ {parsedDescription} +
+
+
+
); } diff --git a/src/app/_jobcard/JobCardDescription.module.css b/src/app/_jobcard/JobCardDescription.module.css new file mode 100644 index 0000000..0ed9324 --- /dev/null +++ b/src/app/_jobcard/JobCardDescription.module.css @@ -0,0 +1,50 @@ +/* JobCardDescription.module.css */ +.parsedDescription p { + font-family: inherit; + font-size: 1rem; + margin-bottom: 1rem; + color: #333; +} + +.parsedDescription h1, +.parsedDescription h2, +.parsedDescription h3, +.parsedDescription h4, +.parsedDescription h5, +.parsedDescription h6 { + font-family: sans-serif; + font-weight: 500; + margin-bottom: 1rem; + color: #111; +} + +.parsedDescription ul, +.parsedDescription ol { + margin-left: 1.5rem; + margin-bottom: 1rem; +} + +.parsedDescription li { + list-style-type: disc; + margin-bottom: 0.1rem; +} + +.parsedDescription a { + color: #1a73e8; + text-decoration: underline; +} + +.parsedDescription img { + max-width: 100%; + height: auto; + margin-bottom: 1rem; +} + +.parsedDescription blockquote { + border-left: 4px solid #ccc; + padding-left: 1rem; + margin-left: 0; + color: #555; + font-style: italic; + margin-bottom: 1rem; +} diff --git a/src/app/page.tsx b/src/app/page.tsx index e62cd68..436506d 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -36,9 +36,11 @@ export default async function Home() { const jobs = await fetchJobs(); return (
- {jobs.map((job, i) => ( - - ))} +
+ {jobs.map((job, i) => ( + + ))} +
); }