Event description now supports markdown formatting (#3688)
* yarn * yarn update * added Mardown style formatting with sanitized inputs * Revert "yarn" This reverts commit 46eb3595cf687504c6783315749b3124936080b9. * Revert "yarn" This reverts commit 46eb3595cf687504c6783315749b3124936080b9. * Revert "yarn update" This reverts commit f4600d83a67b930c6dd72e292827578856ca5428. * Revert "yarn" This reverts commit 46eb3595cf687504c6783315749b3124936080b9. * Revert "yarn update" This reverts commit f4600d83a67b930c6dd72e292827578856ca5428. * Revert "Revert "yarn update"" This reverts commit 8ccab5ee237fb228115229f3c89cf4b848bc9449. * Revert "Revert "yarn"" This reverts commit 78a755eb39cb518eb0526272a3c11882c48004de. * yarn.lock removed * Parses using prisma middleware * Reverting changes * Fixes hydration warning * Fixes Dom warnings * Update yarn.lock Co-authored-by: Peer Richelsen <peeroke@gmail.com> Co-authored-by: zomars <zomars@me.com>
This commit is contained in:
co-authored by
Peer Richelsen
zomars
parent
be16b72400
commit
ff3bd5fc61
@@ -10,10 +10,10 @@ import { z } from "zod";
|
||||
import { AppStoreLocationType, LocationObject, LocationType } from "@calcom/app-store/locations";
|
||||
import dayjs, { Dayjs } from "@calcom/dayjs";
|
||||
import {
|
||||
useIsEmbed,
|
||||
useEmbedStyles,
|
||||
useEmbedNonStylesConfig,
|
||||
useEmbedStyles,
|
||||
useIsBackgroundTransparent,
|
||||
useIsEmbed,
|
||||
} from "@calcom/embed-core/embed-iframe";
|
||||
import { useContracts } from "@calcom/features/ee/web3/contexts/contractsContext";
|
||||
import CustomBranding from "@calcom/lib/CustomBranding";
|
||||
@@ -36,6 +36,7 @@ import { isBrandingHidden } from "@lib/isBrandingHidden";
|
||||
|
||||
import AvailableTimes from "@components/booking/AvailableTimes";
|
||||
import TimeOptions from "@components/booking/TimeOptions";
|
||||
import EventTypeDescriptionSafeHTML from "@components/eventtype/EventTypeDescriptionSafeHTML";
|
||||
import { HeadSeo } from "@components/seo/head-seo";
|
||||
import AvatarGroup from "@components/ui/AvatarGroup";
|
||||
import PoweredByCal from "@components/ui/PoweredByCal";
|
||||
@@ -431,10 +432,12 @@ const AvailabilityPage = ({ profile, eventType }: Props) => {
|
||||
</h1>
|
||||
<div className="flex flex-col space-y-2">
|
||||
{eventType?.description && (
|
||||
<p className="text-gray-600 dark:text-white">
|
||||
<Icon.FiInfo className="mr-[10px] ml-[2px] -mt-1 inline-block h-4 w-4 text-gray-500" />
|
||||
{eventType.description}
|
||||
</p>
|
||||
<div className="flex py-1 text-sm font-medium text-gray-600 dark:text-white">
|
||||
<div>
|
||||
<Icon.FiInfo className="mr-[10px] ml-[2px] -mt-1 inline-block h-4 w-4 text-gray-400" />
|
||||
</div>
|
||||
<EventTypeDescriptionSafeHTML eventType={eventType} />
|
||||
</div>
|
||||
)}
|
||||
{eventType?.requiresConfirmation && (
|
||||
<p className="text-gray-600 dark:text-white">
|
||||
@@ -574,7 +577,7 @@ const AvailabilityPage = ({ profile, eventType }: Props) => {
|
||||
<div>
|
||||
<Icon.FiInfo className="mr-[10px] ml-[2px] -mt-1 inline-block h-4 w-4 text-gray-500" />
|
||||
</div>
|
||||
<p>{eventType.description}</p>
|
||||
<EventTypeDescriptionSafeHTML eventType={eventType} />
|
||||
</div>
|
||||
)}
|
||||
{eventType?.requiresConfirmation && (
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
export type EventTypeDescriptionSafeProps = {
|
||||
eventType: { description: string | null };
|
||||
};
|
||||
|
||||
export const EventTypeDescriptionSafeHTML = ({ eventType }: EventTypeDescriptionSafeProps) => {
|
||||
const props: JSX.IntrinsicElements["div"] = { suppressHydrationWarning: true };
|
||||
// @ts-expect-error: @see packages/prisma/middleware/eventTypeDescriptionParseAndSanitize.ts
|
||||
if (eventType.description) props.dangerouslySetInnerHTML = { __html: eventType.descriptionAsSafeHTML };
|
||||
return <div {...props} />;
|
||||
};
|
||||
|
||||
export default EventTypeDescriptionSafeHTML;
|
||||
@@ -76,6 +76,7 @@
|
||||
"kbar": "^0.1.0-beta.36",
|
||||
"libphonenumber-js": "^1.9.53",
|
||||
"lodash": "^4.17.21",
|
||||
"markdown-it": "^13.0.1",
|
||||
"memory-cache": "^0.2.0",
|
||||
"micro": "^9.3.4",
|
||||
"mime-types": "^2.1.35",
|
||||
@@ -131,6 +132,7 @@
|
||||
"@types/glidejs__glide": "^3.4.2",
|
||||
"@types/jest": "^27.5.1",
|
||||
"@types/lodash": "^4.14.182",
|
||||
"@types/markdown-it": "^12.2.3",
|
||||
"@types/memory-cache": "^0.2.2",
|
||||
"@types/micro": "7.3.6",
|
||||
"@types/mime-types": "^2.1.1",
|
||||
|
||||
@@ -1469,7 +1469,7 @@ const EventTypePage = (props: inferSSRProps<typeof getServerSideProps>) => {
|
||||
/>
|
||||
<select
|
||||
id=""
|
||||
className="block w-full rounded-sm border-gray-300 py-2 pl-3 pr-10 text-base text-sm focus:outline-none"
|
||||
className="block w-full rounded-sm border-gray-300 py-2 pl-3 pr-10 text-sm focus:outline-none"
|
||||
{...formMethods.register("periodCountCalendarDays")}
|
||||
defaultValue={eventType.periodCountCalendarDays ? "1" : "0"}>
|
||||
<option value="1">{t("calendar_days")}</option>
|
||||
|
||||
@@ -29,7 +29,7 @@ export const LOGO = "/calendso-logo-white-word.svg";
|
||||
export const LOGO_ICON = "/cal-com-icon-white.svg";
|
||||
export const ROADMAP = "https://cal.com/roadmap";
|
||||
export const JOIN_SLACK = "https://cal.com/slack";
|
||||
export const POWERED_BY_URL = `${WEBSITE_URL}?utm_source=embed&utm_medium=powered-by-button`;
|
||||
export const POWERED_BY_URL = `${WEBSITE_URL}/?utm_source=embed&utm_medium=powered-by-button`;
|
||||
export const DOCS_URL = "https://docs.cal.com";
|
||||
export const SEO_IMG_DEFAULT = `${WEBSITE_URL}/og-image.png`;
|
||||
export const SEO_IMG_OGIMG = "https://og-image-one-pi.vercel.app/";
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Prisma, PrismaClient } from "@prisma/client";
|
||||
|
||||
import { bookingReferenceMiddleware } from "./middleware";
|
||||
import { bookingReferenceMiddleware, eventTypeDescriptionParseAndSanitizeMiddleware } from "./middleware";
|
||||
|
||||
declare global {
|
||||
// eslint-disable-next-line no-var
|
||||
@@ -21,6 +21,7 @@ if (process.env.NODE_ENV !== "production") {
|
||||
}
|
||||
// If any changed on middleware server restart is required
|
||||
bookingReferenceMiddleware(prisma);
|
||||
eventTypeDescriptionParseAndSanitizeMiddleware(prisma);
|
||||
|
||||
export default prisma;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { PrismaClient } from "@prisma/client";
|
||||
|
||||
async function middleware(prisma: PrismaClient) {
|
||||
function middleware(prisma: PrismaClient) {
|
||||
/***********************************/
|
||||
/* SOFT DELETE MIDDLEWARE */
|
||||
/***********************************/
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
import type { PrismaClient } from "@prisma/client";
|
||||
import MarkdownIt from "markdown-it";
|
||||
|
||||
const md = new MarkdownIt("zero").enable([
|
||||
//
|
||||
"emphasis",
|
||||
"list",
|
||||
"newline",
|
||||
"strikethrough",
|
||||
]);
|
||||
|
||||
function parseAndSanitize(description: string) {
|
||||
const parsedMarkdown = md.render(description);
|
||||
return parsedMarkdown;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses event type descriptions and treat them as markdown,
|
||||
* then sanitizes the resulting HTML and adds a new `descriptionAsSafeHTML` property.
|
||||
*/
|
||||
function eventTypeDescriptionParseAndSanitize(prisma: PrismaClient) {
|
||||
prisma.$use(async (params, next) => {
|
||||
if (params.model === "EventType") {
|
||||
const result = await next(params);
|
||||
if (result) {
|
||||
const results = Array.isArray(result) ? result : [result];
|
||||
const parsedResults = results.map((record) => ({
|
||||
...record,
|
||||
descriptionAsSafeHTML: record.description ? parseAndSanitize(record.description) : null,
|
||||
}));
|
||||
/* If the original result was an array, return the parsed array, otherwise is a single record */
|
||||
return Array.isArray(result) ? parsedResults : parsedResults[0];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return next(params);
|
||||
});
|
||||
}
|
||||
|
||||
export default eventTypeDescriptionParseAndSanitize;
|
||||
@@ -1 +1,2 @@
|
||||
export { default as bookingReferenceMiddleware } from "./bookingReference";
|
||||
export { default as eventTypeDescriptionParseAndSanitizeMiddleware } from "./eventTypeDescriptionParseAndSanitize";
|
||||
|
||||
@@ -6124,6 +6124,11 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee"
|
||||
integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4=
|
||||
|
||||
"@types/linkify-it@*":
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/linkify-it/-/linkify-it-3.0.2.tgz#fd2cd2edbaa7eaac7e7f3c1748b52a19143846c9"
|
||||
integrity sha512-HZQYqbiFVWufzCwexrvh694SOim8z2d+xJl5UNamcvQFejLY/2YUtzXHYi3cHdI7PMlS8ejH2slRAOJQ32aNbA==
|
||||
|
||||
"@types/lodash@^4.14.167", "@types/lodash@^4.14.182":
|
||||
version "4.14.182"
|
||||
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.182.tgz#05301a4d5e62963227eaafe0ce04dd77c54ea5c2"
|
||||
@@ -6134,6 +6139,14 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.181.tgz#d1d3740c379fda17ab175165ba04e2d03389385d"
|
||||
integrity sha512-n3tyKthHJbkiWhDZs3DkhkCzt2MexYHXlX0td5iMplyfwketaOeKboEVBqzceH7juqvEg3q5oUoBFxSLu7zFag==
|
||||
|
||||
"@types/markdown-it@^12.2.3":
|
||||
version "12.2.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/markdown-it/-/markdown-it-12.2.3.tgz#0d6f6e5e413f8daaa26522904597be3d6cd93b51"
|
||||
integrity sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==
|
||||
dependencies:
|
||||
"@types/linkify-it" "*"
|
||||
"@types/mdurl" "*"
|
||||
|
||||
"@types/mdast@^3.0.0":
|
||||
version "3.0.10"
|
||||
resolved "https://registry.yarnpkg.com/@types/mdast/-/mdast-3.0.10.tgz#4724244a82a4598884cbbe9bcfd73dff927ee8af"
|
||||
@@ -6141,7 +6154,7 @@
|
||||
dependencies:
|
||||
"@types/unist" "*"
|
||||
|
||||
"@types/mdurl@^1.0.0":
|
||||
"@types/mdurl@*", "@types/mdurl@^1.0.0":
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/mdurl/-/mdurl-1.0.2.tgz#e2ce9d83a613bacf284c7be7d491945e39e1f8e9"
|
||||
integrity sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==
|
||||
@@ -10505,6 +10518,11 @@ entities@^2.0.0:
|
||||
resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55"
|
||||
integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==
|
||||
|
||||
entities@~3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/entities/-/entities-3.0.1.tgz#2b887ca62585e96db3903482d336c1006c3001d4"
|
||||
integrity sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==
|
||||
|
||||
env-cmd@10.1.0, env-cmd@^10.1.0:
|
||||
version "10.1.0"
|
||||
resolved "https://registry.yarnpkg.com/env-cmd/-/env-cmd-10.1.0.tgz#c7f5d3b550c9519f137fdac4dd8fb6866a8c8c4b"
|
||||
@@ -15593,6 +15611,13 @@ lines-and-columns@^1.1.6:
|
||||
resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632"
|
||||
integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==
|
||||
|
||||
linkify-it@^4.0.1:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-4.0.1.tgz#01f1d5e508190d06669982ba31a7d9f56a5751ec"
|
||||
integrity sha512-C7bfi1UZmoj8+PQx22XyeXCuBlokoyWQL5pWSP+EI6nzRylyThouddufc2c1NDIcP9k5agmN9fLpA7VNJfIiqw==
|
||||
dependencies:
|
||||
uc.micro "^1.0.1"
|
||||
|
||||
lint-staged@^12.4.1:
|
||||
version "12.4.1"
|
||||
resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-12.4.1.tgz#63fa27bfc8a33515f6902f63f6670864f1fb233c"
|
||||
@@ -16067,6 +16092,17 @@ markdown-extensions@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/markdown-extensions/-/markdown-extensions-1.1.1.tgz#fea03b539faeaee9b4ef02a3769b455b189f7fc3"
|
||||
integrity sha512-WWC0ZuMzCyDHYCasEGs4IPvLyTGftYwh6wIEOULOF0HXcqZlhwRzrK0w2VUlxWA98xnvb/jszw4ZSkJ6ADpM6Q==
|
||||
|
||||
markdown-it@^13.0.1:
|
||||
version "13.0.1"
|
||||
resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-13.0.1.tgz#c6ecc431cacf1a5da531423fc6a42807814af430"
|
||||
integrity sha512-lTlxriVoy2criHP0JKRhO2VDG9c2ypWCsT237eDiLqi09rmbKoUetyGHq2uOIRoRS//kfoJckS0eUzzkDR+k2Q==
|
||||
dependencies:
|
||||
argparse "^2.0.1"
|
||||
entities "~3.0.1"
|
||||
linkify-it "^4.0.1"
|
||||
mdurl "^1.0.1"
|
||||
uc.micro "^1.0.5"
|
||||
|
||||
markdown-table@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/markdown-table/-/markdown-table-2.0.0.tgz#194a90ced26d31fe753d8b9434430214c011865b"
|
||||
@@ -16343,10 +16379,10 @@ mdast-util-to-string@^3.0.0, mdast-util-to-string@^3.1.0:
|
||||
resolved "https://registry.yarnpkg.com/mdast-util-to-string/-/mdast-util-to-string-3.1.0.tgz#56c506d065fbf769515235e577b5a261552d56e9"
|
||||
integrity sha512-n4Vypz/DZgwo0iMHLQL49dJzlp7YtAJP+N07MZHpjPf/5XJuHUWstviF4Mn2jEiR/GNmtnRRqnwsXExk3igfFA==
|
||||
|
||||
mdurl@^1.0.0:
|
||||
mdurl@^1.0.0, mdurl@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e"
|
||||
integrity sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=
|
||||
integrity sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==
|
||||
|
||||
media-typer@0.3.0:
|
||||
version "0.3.0"
|
||||
@@ -22820,6 +22856,11 @@ tzdata@^1.0.30:
|
||||
resolved "https://registry.yarnpkg.com/tzdata/-/tzdata-1.0.30.tgz#d9d5a4b4b5e1ed95f6255f98c0564c4256316f52"
|
||||
integrity sha512-/0yogZsIRUVhGIEGZahL+Nnl9gpMD6jtQ9MlVtPVofFwhaqa+cFTgRy1desTAKqdmIJjS6CL+i6F/mnetrLaxw==
|
||||
|
||||
uc.micro@^1.0.1, uc.micro@^1.0.5:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.6.tgz#9c411a802a409a91fc6cf74081baba34b24499ac"
|
||||
integrity sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==
|
||||
|
||||
uglify-js@^3.1.4:
|
||||
version "3.15.3"
|
||||
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.15.3.tgz#9aa82ca22419ba4c0137642ba0df800cb06e0471"
|
||||
|
||||
Reference in New Issue
Block a user