mirror of
https://github.com/AustinKelsay/plebdevs.git
synced 2025-04-19 19:01:19 +00:00
Replaced all markdown displays with react-markdown and gituhb-markdown-css styles
This commit is contained in:
parent
ad6d0fd373
commit
75c2899244
60
package-lock.json
generated
60
package-lock.json
generated
@ -35,6 +35,7 @@
|
||||
"clsx": "^2.1.1",
|
||||
"cors": "^2.8.5",
|
||||
"discord.js": "^14.15.3",
|
||||
"github-markdown-css": "^5.8.1",
|
||||
"light-bolt11-decoder": "^3.1.1",
|
||||
"lucide-react": "^0.441.0",
|
||||
"next": "14.2.5",
|
||||
@ -47,6 +48,7 @@
|
||||
"react": "^18",
|
||||
"react-dom": "^18",
|
||||
"reactflow": "^11.11.4",
|
||||
"remark-breaks": "^4.0.0",
|
||||
"tailwind-merge": "^2.5.2",
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"uuid": "^10.0.0",
|
||||
@ -57,6 +59,7 @@
|
||||
"eslint": "^8",
|
||||
"eslint-config-next": "14.2.5",
|
||||
"postcss": "^8",
|
||||
"prettier": "^3.2.5",
|
||||
"tailwindcss": "^3.4.1"
|
||||
}
|
||||
},
|
||||
@ -8247,6 +8250,18 @@
|
||||
"url": "https://github.com/privatenumber/get-tsconfig?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/github-markdown-css": {
|
||||
"version": "5.8.1",
|
||||
"resolved": "https://registry.npmjs.org/github-markdown-css/-/github-markdown-css-5.8.1.tgz",
|
||||
"integrity": "sha512-8G+PFvqigBQSWLQjyzgpa2ThD9bo7+kDsriUIidGcRhXgmcaAWUIpCZf8DavJgc+xifjbCG+GvMyWr0XMXmc7g==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/github-slugger": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-2.0.0.tgz",
|
||||
@ -10416,6 +10431,20 @@
|
||||
"url": "https://opencollective.com/unified"
|
||||
}
|
||||
},
|
||||
"node_modules/mdast-util-newline-to-break": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/mdast-util-newline-to-break/-/mdast-util-newline-to-break-2.0.0.tgz",
|
||||
"integrity": "sha512-MbgeFca0hLYIEx/2zGsszCSEJJ1JSCdiY5xQxRcLDDGa8EPvlLPupJ4DSajbMPAnC0je8jfb9TiUATnxxrHUog==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/mdast": "^4.0.0",
|
||||
"mdast-util-find-and-replace": "^3.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/unified"
|
||||
}
|
||||
},
|
||||
"node_modules/mdast-util-phrasing": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz",
|
||||
@ -12145,6 +12174,22 @@
|
||||
"node": ">= 0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/prettier": {
|
||||
"version": "3.5.3",
|
||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz",
|
||||
"integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"prettier": "bin/prettier.cjs"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/prettier/prettier?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/pretty-format": {
|
||||
"version": "3.8.0",
|
||||
"resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-3.8.0.tgz",
|
||||
@ -12849,6 +12894,21 @@
|
||||
"url": "https://opencollective.com/unified"
|
||||
}
|
||||
},
|
||||
"node_modules/remark-breaks": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/remark-breaks/-/remark-breaks-4.0.0.tgz",
|
||||
"integrity": "sha512-IjEjJOkH4FuJvHZVIW0QCDWxcG96kCq7An/KVH2NfJe6rKZU2AsHeB3OEjPNRxi4QC34Xdx7I2KGYn6IpT7gxQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/mdast": "^4.0.0",
|
||||
"mdast-util-newline-to-break": "^2.0.0",
|
||||
"unified": "^11.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/unified"
|
||||
}
|
||||
},
|
||||
"node_modules/remark-gfm": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.0.tgz",
|
||||
|
@ -38,6 +38,7 @@
|
||||
"clsx": "^2.1.1",
|
||||
"cors": "^2.8.5",
|
||||
"discord.js": "^14.15.3",
|
||||
"github-markdown-css": "^5.8.1",
|
||||
"light-bolt11-decoder": "^3.1.1",
|
||||
"lucide-react": "^0.441.0",
|
||||
"next": "14.2.5",
|
||||
@ -50,6 +51,7 @@
|
||||
"react": "^18",
|
||||
"react-dom": "^18",
|
||||
"reactflow": "^11.11.4",
|
||||
"remark-breaks": "^4.0.0",
|
||||
"tailwind-merge": "^2.5.2",
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"uuid": "^10.0.0",
|
||||
|
@ -12,11 +12,9 @@ import { useZapsSubscription } from '@/hooks/nostrQueries/zaps/useZapsSubscripti
|
||||
import { getTotalFromZaps } from '@/utils/lightning';
|
||||
import { useSession } from 'next-auth/react';
|
||||
import useWindowWidth from '@/hooks/useWindowWidth';
|
||||
import dynamic from 'next/dynamic';
|
||||
import { Toast } from 'primereact/toast';
|
||||
import MoreOptionsMenu from '@/components/ui/MoreOptionsMenu';
|
||||
|
||||
const MDDisplay = dynamic(() => import('@uiw/react-markdown-preview'), { ssr: false });
|
||||
import MarkdownDisplay from '@/components/markdown/MarkdownDisplay';
|
||||
|
||||
const CombinedDetails = ({
|
||||
processedEvent,
|
||||
@ -203,7 +201,7 @@ const CombinedDetails = ({
|
||||
|
||||
const renderContent = () => {
|
||||
if (decryptedContent) {
|
||||
return <MDDisplay className="p-2 rounded-lg w-full" source={decryptedContent} />;
|
||||
return <MarkdownDisplay content={decryptedContent} className="p-2 rounded-lg w-full" />;
|
||||
}
|
||||
|
||||
if (paidResource && !decryptedContent) {
|
||||
@ -231,7 +229,7 @@ const CombinedDetails = ({
|
||||
}
|
||||
|
||||
if (processedEvent?.content) {
|
||||
return <MDDisplay className="p-4 rounded-lg w-full" source={processedEvent.content} />;
|
||||
return <MarkdownDisplay content={processedEvent.content} className="p-4 rounded-lg w-full" />;
|
||||
}
|
||||
|
||||
return null;
|
||||
|
@ -7,7 +7,6 @@ import { useZapsQuery } from '@/hooks/nostrQueries/zaps/useZapsQuery';
|
||||
import { nip19 } from 'nostr-tools';
|
||||
import { Divider } from 'primereact/divider';
|
||||
import { getTotalFromZaps } from '@/utils/lightning';
|
||||
import dynamic from 'next/dynamic';
|
||||
import useWindowWidth from '@/hooks/useWindowWidth';
|
||||
import appConfig from '@/config/appConfig';
|
||||
import useTrackVideoLesson from '@/hooks/tracking/useTrackVideoLesson';
|
||||
@ -15,10 +14,7 @@ import { Menu } from 'primereact/menu';
|
||||
import { Toast } from 'primereact/toast';
|
||||
import MoreOptionsMenu from '@/components/ui/MoreOptionsMenu';
|
||||
import { useSession } from 'next-auth/react';
|
||||
|
||||
const MDDisplay = dynamic(() => import('@uiw/react-markdown-preview'), {
|
||||
ssr: false,
|
||||
});
|
||||
import MarkdownDisplay from '@/components/markdown/MarkdownDisplay';
|
||||
|
||||
const CombinedLesson = ({ lesson, course, decryptionPerformed, isPaid, setCompleted }) => {
|
||||
const [zapAmount, setZapAmount] = useState(0);
|
||||
@ -175,7 +171,7 @@ const CombinedLesson = ({ lesson, course, decryptionPerformed, isPaid, setComple
|
||||
if (isPaid && decryptionPerformed) {
|
||||
return (
|
||||
<div ref={mdDisplayRef}>
|
||||
<MDDisplay className={'p-4 rounded-lg w-full'} source={lesson.content} />
|
||||
<MarkdownDisplay content={lesson.content} className="p-4 rounded-lg w-full" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -217,7 +213,7 @@ const CombinedLesson = ({ lesson, course, decryptionPerformed, isPaid, setComple
|
||||
if (lesson?.content) {
|
||||
return (
|
||||
<div ref={mdDisplayRef}>
|
||||
<MDDisplay className={'p-4 rounded-lg w-full'} source={lesson.content} />
|
||||
<MarkdownDisplay content={lesson.content} className="p-4 rounded-lg w-full" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -4,7 +4,6 @@ import Image from 'next/image';
|
||||
import { useImageProxy } from '@/hooks/useImageProxy';
|
||||
import { getTotalFromZaps } from '@/utils/lightning';
|
||||
import ZapDisplay from '@/components/zaps/ZapDisplay';
|
||||
import dynamic from 'next/dynamic';
|
||||
import { useZapsQuery } from '@/hooks/nostrQueries/zaps/useZapsQuery';
|
||||
import { Toast } from 'primereact/toast';
|
||||
import useTrackDocumentLesson from '@/hooks/tracking/useTrackDocumentLesson';
|
||||
@ -13,10 +12,7 @@ import { nip19 } from 'nostr-tools';
|
||||
import appConfig from '@/config/appConfig';
|
||||
import MoreOptionsMenu from '@/components/ui/MoreOptionsMenu';
|
||||
import { useSession } from 'next-auth/react';
|
||||
|
||||
const MDDisplay = dynamic(() => import('@uiw/react-markdown-preview'), {
|
||||
ssr: false,
|
||||
});
|
||||
import MarkdownDisplay from '@/components/markdown/MarkdownDisplay';
|
||||
|
||||
const CourseLesson = ({ lesson, course, decryptionPerformed, isPaid, setCompleted }) => {
|
||||
const [zapAmount, setZapAmount] = useState(0);
|
||||
@ -114,7 +110,7 @@ const CourseLesson = ({ lesson, course, decryptionPerformed, isPaid, setComplete
|
||||
|
||||
const renderContent = () => {
|
||||
if (isPaid && decryptionPerformed) {
|
||||
return <MDDisplay className="p-4 rounded-lg w-full" source={lesson.content} />;
|
||||
return <MarkdownDisplay content={lesson.content} className="p-4 rounded-lg w-full" />;
|
||||
}
|
||||
if (isPaid && !decryptionPerformed) {
|
||||
return (
|
||||
@ -124,7 +120,7 @@ const CourseLesson = ({ lesson, course, decryptionPerformed, isPaid, setComplete
|
||||
);
|
||||
}
|
||||
if (lesson?.content) {
|
||||
return <MDDisplay className="p-4 rounded-lg w-full" source={lesson.content} />;
|
||||
return <MarkdownDisplay content={lesson.content} className="p-4 rounded-lg w-full" />;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
@ -7,17 +7,13 @@ import { useZapsQuery } from '@/hooks/nostrQueries/zaps/useZapsQuery';
|
||||
import { nip19 } from 'nostr-tools';
|
||||
import { Divider } from 'primereact/divider';
|
||||
import { getTotalFromZaps } from '@/utils/lightning';
|
||||
import dynamic from 'next/dynamic';
|
||||
import useWindowWidth from '@/hooks/useWindowWidth';
|
||||
import appConfig from '@/config/appConfig';
|
||||
import useTrackDocumentLesson from '@/hooks/tracking/useTrackDocumentLesson';
|
||||
import { Toast } from 'primereact/toast';
|
||||
import MoreOptionsMenu from '@/components/ui/MoreOptionsMenu';
|
||||
import { useSession } from 'next-auth/react';
|
||||
|
||||
const MDDisplay = dynamic(() => import('@uiw/react-markdown-preview'), {
|
||||
ssr: false,
|
||||
});
|
||||
import MarkdownDisplay from '@/components/markdown/MarkdownDisplay';
|
||||
|
||||
const DocumentLesson = ({ lesson, course, decryptionPerformed, isPaid, setCompleted }) => {
|
||||
const [zapAmount, setZapAmount] = useState(0);
|
||||
@ -118,7 +114,7 @@ const DocumentLesson = ({ lesson, course, decryptionPerformed, isPaid, setComple
|
||||
|
||||
const renderContent = () => {
|
||||
if (isPaid && decryptionPerformed) {
|
||||
return <MDDisplay className="p-4 rounded-lg w-full" source={lesson.content} />;
|
||||
return <MarkdownDisplay content={lesson.content} className="p-4 rounded-lg w-full" />;
|
||||
}
|
||||
if (isPaid && !decryptionPerformed) {
|
||||
return (
|
||||
@ -133,7 +129,7 @@ const DocumentLesson = ({ lesson, course, decryptionPerformed, isPaid, setComple
|
||||
);
|
||||
}
|
||||
if (lesson?.content) {
|
||||
return <MDDisplay className="p-4 rounded-lg w-full" source={lesson.content} />;
|
||||
return <MarkdownDisplay content={lesson.content} className="p-4 rounded-lg w-full" />;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
@ -4,7 +4,6 @@ import { useImageProxy } from '@/hooks/useImageProxy';
|
||||
import { Tag } from 'primereact/tag';
|
||||
import GenericButton from '@/components/buttons/GenericButton';
|
||||
import Image from 'next/image';
|
||||
import dynamic from 'next/dynamic';
|
||||
import axios from 'axios';
|
||||
import { nip04, nip19 } from 'nostr-tools';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
@ -18,10 +17,7 @@ import { validateEvent } from '@/utils/nostr';
|
||||
import appConfig from '@/config/appConfig';
|
||||
import { useEncryptContent } from '@/hooks/encryption/useEncryptContent';
|
||||
import 'primeicons/primeicons.css';
|
||||
|
||||
const MDDisplay = dynamic(() => import('@uiw/react-markdown-preview'), {
|
||||
ssr: false,
|
||||
});
|
||||
import MarkdownDisplay from '@/components/markdown/MarkdownDisplay';
|
||||
|
||||
export default function DraftCourseDetails({ processedEvent, draftId, lessons }) {
|
||||
const [author, setAuthor] = useState(null);
|
||||
@ -467,7 +463,7 @@ export default function DraftCourseDetails({ processedEvent, draftId, lessons })
|
||||
</div>
|
||||
<div className="w-[75vw] mx-auto mt-12 p-12 border-t-2 border-gray-300 max-tab:p-0 max-mob:p-0 max-tab:max-w-[100vw] max-mob:max-w-[100vw]">
|
||||
{processedEvent?.content && (
|
||||
<MDDisplay className="p-4 rounded-lg" source={processedEvent.content} />
|
||||
<MarkdownDisplay content={processedEvent.content} className="p-4 rounded-lg" />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -6,11 +6,7 @@ import Image from 'next/image';
|
||||
import { useImageProxy } from '@/hooks/useImageProxy';
|
||||
import { formatDateTime, formatUnixTimestamp } from '@/utils/time';
|
||||
import { useRouter } from 'next/router';
|
||||
import dynamic from 'next/dynamic';
|
||||
|
||||
const MDDisplay = dynamic(() => import('@uiw/react-markdown-preview'), {
|
||||
ssr: false,
|
||||
});
|
||||
import MarkdownDisplay from '@/components/markdown/MarkdownDisplay';
|
||||
|
||||
const DraftCourseLesson = ({ lesson, course }) => {
|
||||
const [isPublished, setIsPublished] = useState(false);
|
||||
@ -149,7 +145,7 @@ const DraftCourseLesson = ({ lesson, course }) => {
|
||||
</div>
|
||||
</div>
|
||||
<div className="w-[75vw] mx-auto mt-12 p-12 border-t-2 border-gray-300 max-tab:p-0 max-mob:p-0 max-tab:max-w-[100vw] max-mob:max-w-[100vw]">
|
||||
{lesson?.content && <MDDisplay className="p-4 rounded-lg" source={lesson.content} />}
|
||||
{lesson?.content && <MarkdownDisplay content={lesson.content} className="p-4 rounded-lg" />}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -6,7 +6,6 @@ import { useImageProxy } from '@/hooks/useImageProxy';
|
||||
import { useZapsQuery } from '@/hooks/nostrQueries/zaps/useZapsQuery';
|
||||
import { nip19 } from 'nostr-tools';
|
||||
import { getTotalFromZaps } from '@/utils/lightning';
|
||||
import dynamic from 'next/dynamic';
|
||||
import { Divider } from 'primereact/divider';
|
||||
import appConfig from '@/config/appConfig';
|
||||
import useWindowWidth from '@/hooks/useWindowWidth';
|
||||
@ -14,10 +13,7 @@ import useTrackVideoLesson from '@/hooks/tracking/useTrackVideoLesson';
|
||||
import { Toast } from 'primereact/toast';
|
||||
import MoreOptionsMenu from '@/components/ui/MoreOptionsMenu';
|
||||
import { useSession } from 'next-auth/react';
|
||||
|
||||
const MDDisplay = dynamic(() => import('@uiw/react-markdown-preview'), {
|
||||
ssr: false,
|
||||
});
|
||||
import MarkdownDisplay from '@/components/markdown/MarkdownDisplay';
|
||||
|
||||
const VideoLesson = ({ lesson, course, decryptionPerformed, isPaid, setCompleted }) => {
|
||||
const [zapAmount, setZapAmount] = useState(0);
|
||||
@ -170,7 +166,7 @@ const VideoLesson = ({ lesson, course, decryptionPerformed, isPaid, setCompleted
|
||||
if (isPaid && decryptionPerformed) {
|
||||
return (
|
||||
<div ref={mdDisplayRef}>
|
||||
<MDDisplay className="p-0 rounded-lg w-full" source={lesson.content} />
|
||||
<MarkdownDisplay content={lesson.content} className="p-0 rounded-lg w-full" />
|
||||
</div>
|
||||
);
|
||||
} else if (isPaid && !decryptionPerformed) {
|
||||
@ -196,7 +192,7 @@ const VideoLesson = ({ lesson, course, decryptionPerformed, isPaid, setCompleted
|
||||
} else if (lesson?.content) {
|
||||
return (
|
||||
<div ref={mdDisplayRef}>
|
||||
<MDDisplay className="p-0 rounded-lg w-full" source={lesson.content} />
|
||||
<MarkdownDisplay content={lesson.content} className="p-0 rounded-lg w-full" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -12,13 +12,9 @@ import { useZapsSubscription } from '@/hooks/nostrQueries/zaps/useZapsSubscripti
|
||||
import { getTotalFromZaps } from '@/utils/lightning';
|
||||
import { useSession } from 'next-auth/react';
|
||||
import useWindowWidth from '@/hooks/useWindowWidth';
|
||||
import dynamic from 'next/dynamic';
|
||||
import { Toast } from 'primereact/toast';
|
||||
import MoreOptionsMenu from '@/components/ui/MoreOptionsMenu';
|
||||
|
||||
const MDDisplay = dynamic(() => import('@uiw/react-markdown-preview'), {
|
||||
ssr: false,
|
||||
});
|
||||
import MarkdownDisplay from '@/components/markdown/MarkdownDisplay';
|
||||
|
||||
const DocumentDetails = ({
|
||||
processedEvent,
|
||||
@ -211,7 +207,7 @@ const DocumentDetails = ({
|
||||
|
||||
const renderContent = () => {
|
||||
if (decryptedContent) {
|
||||
return <MDDisplay className="p-2 rounded-lg w-full" source={decryptedContent} />;
|
||||
return <MarkdownDisplay content={decryptedContent} className="p-2 rounded-lg w-full" />;
|
||||
}
|
||||
if (paidResource && !decryptedContent) {
|
||||
return (
|
||||
@ -237,7 +233,7 @@ const DocumentDetails = ({
|
||||
);
|
||||
}
|
||||
if (processedEvent?.content) {
|
||||
return <MDDisplay className="p-4 rounded-lg w-full" source={processedEvent.content} />;
|
||||
return <MarkdownDisplay content={processedEvent.content} className="p-4 rounded-lg w-full" />;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
@ -12,13 +12,9 @@ import { useZapsSubscription } from '@/hooks/nostrQueries/zaps/useZapsSubscripti
|
||||
import { getTotalFromZaps } from '@/utils/lightning';
|
||||
import { useSession } from 'next-auth/react';
|
||||
import useWindowWidth from '@/hooks/useWindowWidth';
|
||||
import dynamic from 'next/dynamic';
|
||||
import { Toast } from 'primereact/toast';
|
||||
import MoreOptionsMenu from '@/components/ui/MoreOptionsMenu';
|
||||
|
||||
const MDDisplay = dynamic(() => import('@uiw/react-markdown-preview'), {
|
||||
ssr: false,
|
||||
});
|
||||
import MarkdownDisplay from '@/components/markdown/MarkdownDisplay';
|
||||
|
||||
const VideoDetails = ({
|
||||
processedEvent,
|
||||
@ -208,7 +204,7 @@ const VideoDetails = ({
|
||||
|
||||
const renderContent = () => {
|
||||
if (decryptedContent) {
|
||||
return <MDDisplay className="p-0 rounded-lg w-full" source={decryptedContent} />;
|
||||
return <MarkdownDisplay content={decryptedContent} className="p-0 rounded-lg w-full" />;
|
||||
}
|
||||
if (paidResource && !decryptedContent) {
|
||||
return (
|
||||
@ -241,7 +237,7 @@ const VideoDetails = ({
|
||||
);
|
||||
}
|
||||
if (processedEvent?.content) {
|
||||
return <MDDisplay className="p-0 rounded-lg w-full" source={processedEvent.content} />;
|
||||
return <MarkdownDisplay content={processedEvent.content} className="p-0 rounded-lg w-full" />;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
27
src/components/markdown/MarkdownDisplay.js
Normal file
27
src/components/markdown/MarkdownDisplay.js
Normal file
@ -0,0 +1,27 @@
|
||||
import React from 'react';
|
||||
import ReactMarkdown from 'react-markdown';
|
||||
import rehypeRaw from 'rehype-raw';
|
||||
import remarkGfm from 'remark-gfm';
|
||||
import remarkBreaks from 'remark-breaks';
|
||||
import 'github-markdown-css/github-markdown-dark.css';
|
||||
|
||||
const MarkdownDisplay = ({ content, className = "" }) => {
|
||||
if (!content) return null;
|
||||
|
||||
return (
|
||||
<div className={`markdown-body bg-gray-900 ${className}`}>
|
||||
<ReactMarkdown
|
||||
remarkPlugins={[remarkGfm, remarkBreaks]}
|
||||
rehypePlugins={[rehypeRaw]}
|
||||
components={{
|
||||
a: ({node, ...props}) => <a target="_blank" rel="noopener noreferrer" {...props} />,
|
||||
img: ({node, ...props}) => <img {...props} className="max-w-full rounded my-2" />
|
||||
}}
|
||||
>
|
||||
{content}
|
||||
</ReactMarkdown>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default MarkdownDisplay;
|
@ -18,8 +18,7 @@ import ZapThreadsWrapper from '@/components/ZapThreadsWrapper';
|
||||
import useWindowWidth from '@/hooks/useWindowWidth';
|
||||
import MenuTab from '@/components/menutab/MenuTab';
|
||||
import { Tag } from 'primereact/tag';
|
||||
|
||||
const MDDisplay = dynamic(() => import('@uiw/react-markdown-preview'), { ssr: false });
|
||||
import MarkdownDisplay from '@/components/markdown/MarkdownDisplay';
|
||||
|
||||
const useCourseData = (ndk, fetchAuthor, router) => {
|
||||
const [course, setCourse] = useState(null);
|
||||
@ -430,6 +429,7 @@ const Course = () => {
|
||||
isPaid={paidCourse}
|
||||
setCompleted={setCompleted}
|
||||
/>
|
||||
|
||||
);
|
||||
} else if (lesson.type === 'video' && !lesson.topics?.includes('document')) {
|
||||
return (
|
||||
@ -456,7 +456,7 @@ const Course = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="mx-auto px-8 max-mob:px-1 mb-12 mt-4">
|
||||
<div className="mx-auto px-8 max-mob:px-0 mb-12 mt-4">
|
||||
{/* Tab navigation using MenuTab component */}
|
||||
<div className="sticky z-10 bg-transparent border-b border-gray-700/30"
|
||||
style={{
|
||||
@ -486,25 +486,25 @@ const Course = () => {
|
||||
{/* Content tab content */}
|
||||
<div className={`${activeTab === 'content' ? 'block' : 'hidden'}`}>
|
||||
{uniqueLessons.length > 0 && uniqueLessons[activeIndex] ? (
|
||||
<div className="bg-white dark:bg-gray-900 rounded-lg border border-gray-200 dark:border-gray-700 shadow-sm overflow-hidden">
|
||||
<div className="bg-gray-900 rounded-lg shadow-sm overflow-hidden">
|
||||
{renderLesson(uniqueLessons[activeIndex])}
|
||||
</div>
|
||||
) : (
|
||||
<div className="text-center bg-white dark:bg-gray-900 rounded-lg border border-gray-200 dark:border-gray-700 p-8">
|
||||
<div className="text-center bg-gray-900 rounded-lg p-8">
|
||||
<p>Select a lesson from the sidebar to begin learning.</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{course?.content && (
|
||||
<div className="mt-8 bg-white dark:bg-gray-900 rounded-lg border border-gray-200 dark:border-gray-700 shadow-sm">
|
||||
<MDDisplay className="p-4 rounded-lg" source={course.content} />
|
||||
<div className="mt-8 bg-gray-900 rounded-lg shadow-sm">
|
||||
<MarkdownDisplay content={course.content} className="p-4 rounded-lg" />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Lessons tab - only visible on mobile */}
|
||||
<div className={`${activeTab === 'lessons' && isMobileView ? 'block' : 'hidden'}`}>
|
||||
<div className="text-center bg-white dark:bg-gray-900 rounded-lg border border-gray-200 dark:border-gray-700 p-8">
|
||||
<div className="text-center bg-gray-900 rounded-lg p-8">
|
||||
<p>Please use the sidebar to navigate lessons.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -15,15 +15,11 @@ import { formatDateTime } from '@/utils/time';
|
||||
import Image from 'next/image';
|
||||
import useResponsiveImageDimensions from '@/hooks/useResponsiveImageDimensions';
|
||||
import 'primeicons/primeicons.css';
|
||||
import dynamic from 'next/dynamic';
|
||||
import { validateEvent } from '@/utils/nostr';
|
||||
import appConfig from '@/config/appConfig';
|
||||
import { useIsAdmin } from '@/hooks/useIsAdmin';
|
||||
import { useEncryptContent } from '@/hooks/encryption/useEncryptContent';
|
||||
|
||||
const MDDisplay = dynamic(() => import('@uiw/react-markdown-preview'), {
|
||||
ssr: false,
|
||||
});
|
||||
import MarkdownDisplay from '@/components/markdown/MarkdownDisplay';
|
||||
|
||||
export default function Draft() {
|
||||
const [draft, setDraft] = useState(null);
|
||||
@ -433,7 +429,7 @@ export default function Draft() {
|
||||
</div>
|
||||
</div>
|
||||
<div className="w-[75vw] mx-auto mt-12 p-12 border-t-2 border-gray-300 max-tab:p-0 max-mob:p-0 max-tab:max-w-[100vw] max-mob:max-w-[100vw]">
|
||||
{draft?.content && <MDDisplay className="p-4 rounded-lg" source={draft.content} />}
|
||||
{draft?.content && <MarkdownDisplay content={draft.content} className="p-4 rounded-lg" />}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
Loading…
x
Reference in New Issue
Block a user