Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(markdown-support): added markdown support #596

Merged
merged 1 commit into from
Jan 20, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ export const ApplicationForm = ({ pollId }: IApplicationFormProps): JSX.Element
<Textarea placeholder="Type project description" rows={4} />
</FormControl>

<small className="-mt-4">*Markdown Supported</small>

<div className="gap-4 md:flex">
<FormControl required className="flex-1" label="Website" name="websiteUrl">
<Input placeholder="https://" />
Expand Down Expand Up @@ -156,10 +158,14 @@ export const ApplicationForm = ({ pollId }: IApplicationFormProps): JSX.Element
<Textarea placeholder="What have your project contributed to?" rows={4} />
</FormControl>

<small className="-mt-4">*Markdown Supported</small>

<FormControl required label="Impact description" name="impactDescription">
<Textarea placeholder="What impact has your project had?" rows={4} />
</FormControl>

<small className="-mt-4">*Markdown Supported</small>

<ImpactTags />

<FieldArray
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import clsx from "clsx";
import { useMemo, type ReactNode } from "react";
import { useFormContext } from "react-hook-form";
import Markdown from "react-markdown";

import { Heading } from "~/components/ui/Heading";
import { Tag } from "~/components/ui/Tag";
Expand Down Expand Up @@ -36,13 +37,33 @@ const ValueField = ({ title, body = undefined, required = false }: IValueFieldPr
);
};

const MarkdownField = ({ title, body = undefined, required = false }: IValueFieldProps): JSX.Element => {
const emptyPlaceholder = "(empty)";

return (
<div className="flex flex-col gap-2 ">
<b className={clsx(required && "text-xs after:text-blue-400 after:content-['*'] sm:text-sm")}>{title}</b>

<div className="text-light flex flex-col flex-wrap gap-2 text-gray-400">
{body === undefined && emptyPlaceholder}

{Array.isArray(body) && body.length === 0 && emptyPlaceholder}

{typeof body === "string" && body.length === 0 && emptyPlaceholder}

{((typeof body === "string" && body.length > 0) || typeof body !== "string") && body}
</div>
</div>
);
};

export const ReviewApplicationDetails = (): JSX.Element => {
const form = useFormContext<Application>();

const application = useMemo(() => form.getValues(), [form]);

return (
<div className="flex flex-col gap-8">
<div className="markdown-support flex flex-col gap-8">
<div>
<Heading className="mb-1 font-sans text-xl font-semibold">Review & Submit</Heading>

Expand All @@ -54,7 +75,7 @@ export const ReviewApplicationDetails = (): JSX.Element => {

<ValueField required body={application.name} title="Project name" />

<ValueField required body={application.bio} title="Project description" />
<MarkdownField required body={<Markdown>{application.bio}</Markdown>} title="Project description" />

<div className="grid grid-flow-row gap-4 sm:grid-cols-2">
<ValueField required body={application.websiteUrl} title="Website" />
Expand Down Expand Up @@ -94,9 +115,17 @@ export const ReviewApplicationDetails = (): JSX.Element => {
<div className="flex flex-col gap-6 dark:text-white">
<b className="text-lg">Contribution & Impact</b>

<ValueField required body={application.contributionDescription} title="Contribution description" />
<MarkdownField
required
body={<Markdown>{application.contributionDescription}</Markdown>}
title="Contribution description"
/>

<ValueField required body={application.impactDescription} title="Impact description" />
<MarkdownField
required
body={<Markdown>{application.impactDescription}</Markdown>}
title="Impact description"
/>

<ValueField
required
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { FaGithub, FaEthereum } from "react-icons/fa";
import { RiGlobalLine } from "react-icons/ri";
import Markdown from "react-markdown";

import { Link } from "~/components/ui/Link";

Expand All @@ -23,7 +24,7 @@ export const ProjectDescriptionSection = ({
<div className="flex flex-col gap-6">
<p className="text-lg uppercase">{title}</p>

{description.length > 0 && <p className="text-lg text-gray-400">{description}</p>}
{description.length > 0 && <Markdown className="text-gray-400">{description}</Markdown>}

{contributions.length > 0 && (
<div className="border-l border-gray-200 px-4">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { type ReactNode } from "react";
import Markdown from "react-markdown";

import { Heading } from "~/components/ui/Heading";
import { Navigation } from "~/components/ui/Navigation";
Expand Down Expand Up @@ -30,7 +31,7 @@ const ProjectDetails = ({ pollId, project, action = undefined }: IProjectDetails
const roundState = useRoundState({ pollId });

return (
<div className="relative dark:text-white">
<div className="markdown-support relative dark:text-white">
<div className="mb-7 px-2">
<Navigation pollId={pollId} projectName={metadata.data?.name ?? "project name"} />
</div>
Expand All @@ -55,7 +56,7 @@ const ProjectDetails = ({ pollId, project, action = undefined }: IProjectDetails

<ProjectContacts author={payoutAddress} github={github} twitter={twitter} website={websiteUrl} />

<p className="px-2 text-gray-400">{bio}</p>
<Markdown className="px-2 text-gray-400">{bio}</Markdown>

<div className="my-8 flex flex-col gap-8 px-2">
<p className="text-xl uppercase">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { Heading } from "~/components/ui/Heading";
import { Skeleton } from "~/components/ui/Skeleton";
import { config } from "~/config";
import { formatNumber } from "~/utils/formatNumber";
import { removeMarkdown } from "~/utils/removeMarkdown";
import { useRoundState } from "~/utils/state";
import { ERoundState } from "~/utils/types";

Expand Down Expand Up @@ -53,7 +54,7 @@ export const ProjectItem = ({

<div className="mb-2 line-clamp-2 h-10 text-sm text-gray-400">
<Skeleton className="w-full" isLoading={isLoading}>
{metadata.data?.bio}
{removeMarkdown(metadata.data?.bio || "")}
kittybest marked this conversation as resolved.
Show resolved Hide resolved
</Skeleton>
</div>

Expand Down
10 changes: 10 additions & 0 deletions packages/interface/src/styles/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,14 @@
text-transform: uppercase;
color: #888888;
}

.markdown-support ul,
.markdown-support ol {
list-style: revert;
padding-left: 1.5rem;
}

.markdown-support p {
margin-top: 0.5rem;
}
}
15 changes: 15 additions & 0 deletions packages/interface/src/utils/removeMarkdown.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
export function removeMarkdown(text: string): string {
return text
.replace(/!\[.*?\]\(.*?\)/g, "") // Remove images
.replace(/\[.*?\]\(.*?\)/g, "") // Remove links
.replace(/`{1,2}[^`](.*?)`{1,2}/g, "$1") // Remove inline code
.replace(/```[\s\S]*?```/g, "") // Remove code blocks
.replace(/^[#]+ /gm, "") // Remove headers
.replace(/(\*\*|__)(.*?)\1/g, "$2") // Remove bold
.replace(/(\*|_)(.*?)\1/g, "$2") // Remove emphasis
.replace(/~~(.*?)~~/g, "$1") // Remove strikethrough
.replace(/> /gm, "") // Remove blockquotes
.replace(/^\s*\n/gm, "") // Remove empty lines
.replace(/^\s*-\s+/gm, "") // Remove list items
.replace(/^\s*\d+\.\s+/gm, ""); // Remove numbered list items
}
Loading
Loading