Fixes formatting issues with lists in event type description and bio (#7505)
* fix ul and ol in editor * fix imports * disable list for team about section * fix event type description in list --------- Co-authored-by: CarinaWolli <wollencarina@gmail.com> Co-authored-by: Peer Richelsen <peeroke@gmail.com>pull/7458/head^2
parent
c8b01f6992
commit
47e948fbbc
|
@ -1,7 +1,6 @@
|
|||
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { isValidPhoneNumber } from "libphonenumber-js";
|
||||
import MarkdownIt from "markdown-it";
|
||||
import { Trans } from "next-i18next";
|
||||
import Link from "next/link";
|
||||
import type { EventTypeSetupProps, FormValues } from "pages/event-types/[type]";
|
||||
|
@ -14,6 +13,7 @@ import type { EventLocationType } from "@calcom/app-store/locations";
|
|||
import { getEventLocationType, MeetLocationType, LocationType } from "@calcom/app-store/locations";
|
||||
import { CAL_URL } from "@calcom/lib/constants";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import { md } from "@calcom/lib/markdownIt";
|
||||
import { slugify } from "@calcom/lib/slugify";
|
||||
import turndown from "@calcom/lib/turndownService";
|
||||
import { Button, Editor, Label, Select, SettingsToggle, Skeleton, TextField } from "@calcom/ui";
|
||||
|
@ -23,8 +23,6 @@ import { EditLocationDialog } from "@components/dialog/EditLocationDialog";
|
|||
import type { SingleValueLocationOption, LocationOption } from "@components/ui/form/LocationSelect";
|
||||
import LocationSelect from "@components/ui/form/LocationSelect";
|
||||
|
||||
const md = new MarkdownIt("default", { html: true, breaks: true, linkify: true });
|
||||
|
||||
const getLocationFromType = (
|
||||
type: EventLocationType["type"],
|
||||
locationOptions: Pick<EventTypeSetupProps, "locationOptions">["locationOptions"]
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import { ArrowRightIcon } from "@heroicons/react/solid";
|
||||
import MarkdownIt from "markdown-it";
|
||||
import { useRouter } from "next/router";
|
||||
import type { FormEvent } from "react";
|
||||
import { useRef, useState } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import { md } from "@calcom/lib/markdownIt";
|
||||
import { telemetryEventTypes, useTelemetry } from "@calcom/lib/telemetry";
|
||||
import turndown from "@calcom/lib/turndownService";
|
||||
import { trpc } from "@calcom/trpc/react";
|
||||
|
@ -14,8 +14,6 @@ import { Avatar } from "@calcom/ui";
|
|||
|
||||
import type { IOnboardingPageProps } from "../../../pages/getting-started/[[...step]]";
|
||||
|
||||
const md = new MarkdownIt("default", { html: true, breaks: true, linkify: true });
|
||||
|
||||
type FormData = {
|
||||
bio: string;
|
||||
};
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
import MarkdownIt from "markdown-it";
|
||||
import Link from "next/link";
|
||||
import type { TeamPageProps } from "pages/team/[slug]";
|
||||
|
||||
import { WEBAPP_URL } from "@calcom/lib/constants";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import { md } from "@calcom/lib/markdownIt";
|
||||
import { Avatar } from "@calcom/ui";
|
||||
|
||||
const md = new MarkdownIt("default", { html: true, breaks: true, linkify: true });
|
||||
|
||||
type TeamType = TeamPageProps["team"];
|
||||
type MembersType = TeamType["members"];
|
||||
type MemberType = MembersType[number];
|
||||
|
@ -19,7 +17,7 @@ const Member = ({ member, teamName }: { member: MemberType; teamName: string | n
|
|||
|
||||
return (
|
||||
<Link key={member.id} href={`/${member.username}`}>
|
||||
<div className="sm:min-w-80 sm:max-w-80 dark:bg-darkgray-200 dark:hover:bg-darkgray-300 group flex min-h-full flex-col space-y-2 rounded-md bg-white p-4 hover:cursor-pointer hover:bg-gray-50 ">
|
||||
<div className="sm:min-w-80 sm:max-w-80 dark:bg-darkgray-200 dark:hover:bg-darkgray-300 group flex min-h-full flex-col space-y-2 rounded-md bg-white p-4 hover:cursor-pointer hover:bg-gray-50 ">
|
||||
<Avatar
|
||||
size="md"
|
||||
alt={member.name || ""}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import { BadgeCheckIcon } from "@heroicons/react/solid";
|
||||
import classNames from "classnames";
|
||||
import MarkdownIt from "markdown-it";
|
||||
import type { GetServerSidePropsContext } from "next";
|
||||
import Link from "next/link";
|
||||
import { useRouter } from "next/router";
|
||||
|
@ -24,6 +23,7 @@ import defaultEvents, {
|
|||
} from "@calcom/lib/defaultEvents";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import useTheme from "@calcom/lib/hooks/useTheme";
|
||||
import { md } from "@calcom/lib/markdownIt";
|
||||
import { collectPageParameters, telemetryEventTypes, useTelemetry } from "@calcom/lib/telemetry";
|
||||
import prisma from "@calcom/prisma";
|
||||
import { baseEventTypeSelect } from "@calcom/prisma/selects";
|
||||
|
@ -36,8 +36,6 @@ import type { EmbedProps } from "@lib/withEmbedSsr";
|
|||
|
||||
import { ssrInit } from "@server/lib/ssr";
|
||||
|
||||
const md = new MarkdownIt("default", { html: true, breaks: true, linkify: true });
|
||||
|
||||
export default function User(props: inferSSRProps<typeof getServerSideProps> & EmbedProps) {
|
||||
const { users, profile, eventTypes, isDynamicGroup, dynamicNames, dynamicUsernames, isSingleUser } = props;
|
||||
const [user] = users; //To be used when we only have a single user, not dynamic group
|
||||
|
@ -147,7 +145,7 @@ export default function User(props: inferSSRProps<typeof getServerSideProps> & E
|
|||
{!isBioEmpty && (
|
||||
<>
|
||||
<div
|
||||
className="dark:text-darkgray-600 text-sm text-gray-500 [&_a]:text-blue-500 [&_a]:underline [&_a]:hover:text-blue-600"
|
||||
className=" dark:text-darkgray-600 text-sm text-gray-500 [&_a]:text-blue-500 [&_a]:underline [&_a]:hover:text-blue-600"
|
||||
dangerouslySetInnerHTML={{ __html: md.render(user.bio || "") }}
|
||||
/>
|
||||
</>
|
||||
|
|
|
@ -5,6 +5,7 @@ import type { LocationObject } from "@calcom/app-store/locations";
|
|||
import { IS_TEAM_BILLING_ENABLED, WEBAPP_URL } from "@calcom/lib/constants";
|
||||
import hasKeyInMetadata from "@calcom/lib/hasKeyInMetadata";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import { addListFormatting } from "@calcom/lib/markdownIt";
|
||||
import type { User } from "@calcom/prisma/client";
|
||||
|
||||
import { isBrandingHidden } from "@lib/isBrandingHidden";
|
||||
|
@ -152,7 +153,7 @@ async function getUserPageProps(context: GetStaticPropsContext) {
|
|||
metadata: EventTypeMetaDataSchema.parse(eventType.metadata || {}),
|
||||
recurringEvent: parseRecurringEvent(eventType.recurringEvent),
|
||||
locations: privacyFilteredLocations(locations),
|
||||
descriptionAsSafeHTML: eventType.description ? md.render(eventType.description) : null,
|
||||
descriptionAsSafeHTML: eventType.description ? addListFormatting(md.render(eventType.description)) : null,
|
||||
});
|
||||
// Check if the user you are logging into has any active teams or premium user name
|
||||
const hasActiveTeam =
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import { IdentityProvider } from "@prisma/client";
|
||||
import crypto from "crypto";
|
||||
import MarkdownIt from "markdown-it";
|
||||
import { signOut } from "next-auth/react";
|
||||
import type { BaseSyntheticEvent } from "react";
|
||||
import { useRef, useState } from "react";
|
||||
|
@ -10,6 +9,7 @@ import { getLayout } from "@calcom/features/settings/layouts/SettingsLayout";
|
|||
import { ErrorCode } from "@calcom/lib/auth";
|
||||
import { APP_NAME } from "@calcom/lib/constants";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import { md } from "@calcom/lib/markdownIt";
|
||||
import turndown from "@calcom/lib/turndownService";
|
||||
import type { TRPCClientErrorLike } from "@calcom/trpc/client";
|
||||
import { trpc } from "@calcom/trpc/react";
|
||||
|
@ -41,8 +41,6 @@ import { FiAlertTriangle, FiTrash2 } from "@calcom/ui/components/icon";
|
|||
import TwoFactor from "@components/auth/TwoFactor";
|
||||
import { UsernameAvailabilityField } from "@components/ui/UsernameAvailability";
|
||||
|
||||
const md = new MarkdownIt("default", { html: true, breaks: true, linkify: true });
|
||||
|
||||
const SkeletonLoader = ({ title, description }: { title: string; description: string }) => {
|
||||
return (
|
||||
<SkeletonContainer>
|
||||
|
@ -371,6 +369,7 @@ const ProfileForm = ({
|
|||
formMethods.setValue("bio", turndown(value), { shouldDirty: true });
|
||||
}}
|
||||
excludedToolbarItems={["blockType"]}
|
||||
disableLists
|
||||
/>
|
||||
</div>
|
||||
<Button disabled={isDisabled} color="primary" className="mt-8" type="submit">
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import classNames from "classnames";
|
||||
import MarkdownIt from "markdown-it";
|
||||
import type { GetServerSidePropsContext } from "next";
|
||||
import Link from "next/link";
|
||||
import { useRouter } from "next/router";
|
||||
|
@ -11,6 +10,7 @@ import { CAL_URL } from "@calcom/lib/constants";
|
|||
import { getPlaceholderAvatar } from "@calcom/lib/getPlaceholderAvatar";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import useTheme from "@calcom/lib/hooks/useTheme";
|
||||
import { md } from "@calcom/lib/markdownIt";
|
||||
import { getTeamWithMembers } from "@calcom/lib/server/queries/teams";
|
||||
import { collectPageParameters, telemetryEventTypes, useTelemetry } from "@calcom/lib/telemetry";
|
||||
import { Avatar, Button, HeadSeo, AvatarGroup } from "@calcom/ui";
|
||||
|
@ -23,8 +23,6 @@ import Team from "@components/team/screens/Team";
|
|||
|
||||
import { ssrInit } from "@server/lib/ssr";
|
||||
|
||||
const md = new MarkdownIt("default", { html: true, breaks: true, linkify: true });
|
||||
|
||||
export type TeamPageProps = inferSSRProps<typeof getServerSideProps>;
|
||||
function TeamPage({ team }: TeamPageProps) {
|
||||
useTheme(team.theme);
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import type { Prisma } from "@prisma/client";
|
||||
import { MembershipRole } from "@prisma/client";
|
||||
import MarkdownIt from "markdown-it";
|
||||
import { useSession } from "next-auth/react";
|
||||
import Link from "next/link";
|
||||
import { useRouter } from "next/router";
|
||||
|
@ -11,6 +10,7 @@ import { z } from "zod";
|
|||
import { IS_TEAM_BILLING_ENABLED, WEBAPP_URL } from "@calcom/lib/constants";
|
||||
import { getPlaceholderAvatar } from "@calcom/lib/getPlaceholderAvatar";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import { md } from "@calcom/lib/markdownIt";
|
||||
import objectKeys from "@calcom/lib/objectKeys";
|
||||
import turndown from "@calcom/lib/turndownService";
|
||||
import { trpc } from "@calcom/trpc/react";
|
||||
|
@ -33,8 +33,6 @@ import { FiExternalLink, FiLink, FiTrash2, FiLogOut } from "@calcom/ui/component
|
|||
|
||||
import { getLayout } from "../../../settings/layouts/SettingsLayout";
|
||||
|
||||
const md = new MarkdownIt("default", { html: true, breaks: true });
|
||||
|
||||
const regex = new RegExp("^[a-zA-Z0-9-]*$");
|
||||
|
||||
const teamProfileFormSchema = z.object({
|
||||
|
@ -225,6 +223,7 @@ const ProfileView = () => {
|
|||
getText={() => md.render(form.getValues("bio") || "")}
|
||||
setText={(value: string) => form.setValue("bio", turndown(value))}
|
||||
excludedToolbarItems={["blockType"]}
|
||||
disableLists
|
||||
/>
|
||||
</div>
|
||||
<p className="mt-2 text-sm text-gray-600">{t("team_description")}</p>
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { SchedulingType } from "@prisma/client";
|
||||
import { isValidPhoneNumber } from "libphonenumber-js";
|
||||
import MarkdownIt from "markdown-it";
|
||||
import { useRouter } from "next/router";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { z } from "zod";
|
||||
|
@ -9,6 +8,7 @@ import { z } from "zod";
|
|||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import { useTypedQuery } from "@calcom/lib/hooks/useTypedQuery";
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import { md } from "@calcom/lib/markdownIt";
|
||||
import slugify from "@calcom/lib/slugify";
|
||||
import turndown from "@calcom/lib/turndownService";
|
||||
import { createEventTypeInput } from "@calcom/prisma/zod/custom/eventtype";
|
||||
|
@ -26,8 +26,6 @@ import {
|
|||
Editor,
|
||||
} from "@calcom/ui";
|
||||
|
||||
const md = new MarkdownIt("default", { html: true, breaks: true, linkify: true });
|
||||
|
||||
// this describes the uniform data needed to create a new event type on Profile or Team
|
||||
export interface EventTypeParent {
|
||||
teamId: number | null | undefined; // if undefined, then it's a profile
|
||||
|
@ -203,26 +201,26 @@ export default function CreateEventTypeDialog() {
|
|||
message={form.formState.errors.schedulingType.message}
|
||||
/>
|
||||
)}
|
||||
<RadioArea.Group className="flex mt-1 space-x-4">
|
||||
<RadioArea.Group className="mt-1 flex space-x-4">
|
||||
<RadioArea.Item
|
||||
{...register("schedulingType")}
|
||||
value={SchedulingType.COLLECTIVE}
|
||||
className="w-1/2 text-sm">
|
||||
<strong className="block mb-1">{t("collective")}</strong>
|
||||
<strong className="mb-1 block">{t("collective")}</strong>
|
||||
<p>{t("collective_description")}</p>
|
||||
</RadioArea.Item>
|
||||
<RadioArea.Item
|
||||
{...register("schedulingType")}
|
||||
value={SchedulingType.ROUND_ROBIN}
|
||||
className="w-1/2 text-sm">
|
||||
<strong className="block mb-1">{t("round_robin")}</strong>
|
||||
<strong className="mb-1 block">{t("round_robin")}</strong>
|
||||
<p>{t("round_robin_description")}</p>
|
||||
</RadioArea.Item>
|
||||
</RadioArea.Group>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex flex-row-reverse mt-8 gap-x-2">
|
||||
<div className="mt-8 flex flex-row-reverse gap-x-2">
|
||||
<Button type="submit" loading={createMutation.isLoading}>
|
||||
{t("continue")}
|
||||
</Button>
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
import { Prisma, SchedulingType } from "@prisma/client";
|
||||
import MarkdownIt from "markdown-it";
|
||||
import type { Prisma } from "@prisma/client";
|
||||
import { SchedulingType } from "@prisma/client";
|
||||
import { useMemo } from "react";
|
||||
import { FormattedNumber, IntlProvider } from "react-intl";
|
||||
import { z } from "zod";
|
||||
import type { z } from "zod";
|
||||
|
||||
import { classNames, parseRecurringEvent } from "@calcom/lib";
|
||||
import getPaymentAppData from "@calcom/lib/getPaymentAppData";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import { baseEventTypeSelect } from "@calcom/prisma";
|
||||
import { EventTypeModel } from "@calcom/prisma/zod";
|
||||
import { addListFormatting, md } from "@calcom/lib/markdownIt";
|
||||
import type { baseEventTypeSelect } from "@calcom/prisma";
|
||||
import type { EventTypeModel } from "@calcom/prisma/zod";
|
||||
import { Badge } from "@calcom/ui";
|
||||
import {
|
||||
FiClock,
|
||||
|
@ -29,11 +30,9 @@ export type EventTypeDescriptionProps = {
|
|||
seatsPerTimeSlot?: number;
|
||||
};
|
||||
className?: string;
|
||||
shortenDescription?: true;
|
||||
shortenDescription?: boolean;
|
||||
};
|
||||
|
||||
const md = new MarkdownIt("default", { html: true, breaks: false, linkify: true });
|
||||
|
||||
export const EventTypeDescription = ({
|
||||
eventType,
|
||||
className,
|
||||
|
@ -58,9 +57,7 @@ export const EventTypeDescription = ({
|
|||
shortenDescription ? "line-clamp-4" : ""
|
||||
)}
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: shortenDescription
|
||||
? md.render(eventType.description?.replace(/<p><br><\/p>|\n/g, " "))
|
||||
: md.render(eventType.description),
|
||||
__html: addListFormatting(md.render(eventType.description)),
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
import MarkdownIt from "markdown-it";
|
||||
|
||||
export const md = new MarkdownIt("default", { html: true, breaks: true, linkify: true });
|
||||
|
||||
export function addListFormatting(html: string) {
|
||||
return html
|
||||
.replaceAll("<ul>", "<ul style='list-style-type: disc; list-style-position: inside; margin-left: 12px'>")
|
||||
.replaceAll(
|
||||
"<ol>",
|
||||
"<ol style='list-style-type: decimal; list-style-position: inside; margin-left: 12px'>"
|
||||
);
|
||||
}
|
|
@ -1,7 +1,6 @@
|
|||
import type { PrismaClient, EventType } from "@prisma/client";
|
||||
import MarkdownIt from "markdown-it";
|
||||
|
||||
const md = new MarkdownIt("default", { html: true, breaks: true, linkify: true });
|
||||
import { md } from "@calcom/lib/markdownIt";
|
||||
|
||||
function parseAndSanitize(description: string) {
|
||||
const parsedMarkdown = md.render(description);
|
||||
|
|
|
@ -31,6 +31,7 @@ export type TextEditorProps = {
|
|||
variables?: string[];
|
||||
height?: string;
|
||||
placeholder?: string;
|
||||
disableLists?: boolean;
|
||||
};
|
||||
|
||||
const editorConfig = {
|
||||
|
@ -74,7 +75,15 @@ export const Editor = (props: TextEditorProps) => {
|
|||
<ListPlugin />
|
||||
<LinkPlugin />
|
||||
<AutoLinkPlugin />
|
||||
<MarkdownShortcutPlugin transformers={TRANSFORMERS} />
|
||||
<MarkdownShortcutPlugin
|
||||
transformers={
|
||||
props.disableLists
|
||||
? TRANSFORMERS.filter((value, index) => {
|
||||
if (index !== 3 && index !== 4) return value;
|
||||
})
|
||||
: TRANSFORMERS
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</LexicalComposer>
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
text-align: left;
|
||||
border-color: #D1D5DB;
|
||||
border-width: 1px;
|
||||
padding: 1px
|
||||
padding: 1px;
|
||||
}
|
||||
|
||||
.editor-inner {
|
||||
|
@ -37,6 +37,7 @@
|
|||
overflow: scroll;
|
||||
resize: vertical;
|
||||
height: auto;
|
||||
min-height: 40px;
|
||||
}
|
||||
|
||||
.editor-input {
|
||||
|
|
Loading…
Reference in New Issue