Added Editor for Markdawn

This commit is contained in:
DrMint 2022-02-17 17:55:44 +01:00
parent 877dc01586
commit b736660b06
6 changed files with 126 additions and 11 deletions

View File

@ -0,0 +1,24 @@
import Markdown from "markdown-to-jsx";
import SceneBreak from "./SceneBreak";
type ScenBreakProps = {
className?: string;
text: string;
};
export default function Markdawn(props: ScenBreakProps): JSX.Element {
return (
<Markdown
className={`prose text-black ${props.className}`}
options={{
overrides: {
hr: {
component: SceneBreak,
},
},
}}
>
{props.text}
</Markdown>
);
}

View File

@ -6,7 +6,6 @@ import Button from "components/Button";
import HorizontalLine from "components/HorizontalLine"; import HorizontalLine from "components/HorizontalLine";
import { GetWebsiteInterfaceQuery } from "graphql/operations-types"; import { GetWebsiteInterfaceQuery } from "graphql/operations-types";
import Markdown from "markdown-to-jsx"; import Markdown from "markdown-to-jsx";
import Script from "next/script";
type MainPanelProps = { type MainPanelProps = {
langui: GetWebsiteInterfaceQuery["websiteInterfaces"]["data"][number]["attributes"]; langui: GetWebsiteInterfaceQuery["websiteInterfaces"]["data"][number]["attributes"];
@ -21,16 +20,16 @@ export default function MainPanel(props: MainPanelProps): JSX.Element {
className="flex flex-col justify-center content-start p-8 gap-y-2 justify-items-center text-center" className="flex flex-col justify-center content-start p-8 gap-y-2 justify-items-center text-center"
> >
<div className=""> <div className="">
<div className="grid place-items-center mobile:grid-flow-col"> <div className="grid place-items-center">
<Link href="/" passHref> <Link href="/" passHref>
<div className="mobile:w-10 mobile:self-end w-1/2 cursor-pointer transition-[filter] hover:colorize-dark"> <div className="w-1/2 cursor-pointer transition-[filter] hover:colorize-dark">
<SVG <SVG
src={"/icons/accords.svg"} src={"/icons/accords.svg"}
alt={"Logo of Accord's Library"} alt={"Logo of Accord's Library"}
/> />
</div> </div>
</Link> </Link>
<div className="relative mt-5 mobile:self-start"> <div className="relative mt-5">
{router.locale ? ( {router.locale ? (
<Button className="absolute right-0 top-[-1.3em] text-xs !py-0.5 !px-2.5"> <Button className="absolute right-0 top-[-1.3em] text-xs !py-0.5 !px-2.5">
{router.locale.toUpperCase()} {router.locale.toUpperCase()}

85
src/pages/editor.tsx Normal file
View File

@ -0,0 +1,85 @@
import ContentPanel, {
ContentPanelWidthSizes,
} from "components/Panels/ContentPanel";
import { getWebsiteInterface } from "graphql/operations";
import { GetStaticProps } from "next";
import { GetWebsiteInterfaceQuery } from "graphql/operations-types";
import AppLayout from "components/AppLayout";
import { useCallback, useState } from "react";
import Markdawn from "components/Markdown/Markdawn";
import Script from "next/script";
type EditorProps = {
langui: GetWebsiteInterfaceQuery;
};
export default function Editor(props: EditorProps): JSX.Element {
const langui = props.langui.websiteInterfaces.data[0].attributes;
const handleInput = useCallback((e) => {
setMarkdown(e.target.value);
}, []);
const [markdown, setMarkdown] = useState("");
const contentPanel = (
<ContentPanel width={ContentPanelWidthSizes.large}>
<Script
id="autoFitTextArea"
strategy="afterInteractive"
dangerouslySetInnerHTML={{
__html: `
const el = document.querySelector("#editorTextArea")
el.addEventListener('input', function() {
this.style.height = (this.scrollHeight) + 'px';
});
`,
}}
/>
<div className="grid grid-cols-2 gap-4 h-96">
<div>
<h2>Editor</h2>
<textarea
id="editorTextArea"
onInput={handleInput}
onPaste={(event) => {
event.preventDefault();
let paste = event.clipboardData.getData("text/html");
paste = paste.replaceAll("<html>", "");
paste = paste.replaceAll("<body>", "");
paste = paste.replaceAll("</body>", "");
paste = paste.replaceAll("</html>", "");
paste = paste.replaceAll("<!--StartFragment-->", "");
paste = paste.replaceAll("<!--EndFragment-->", "");
event.target.value = paste;
}}
className="bg-mid rounded-xl p-8 w-full "
value={markdown}
/>
</div>
<div>
<h2>Preview</h2>
<div className="bg-mid rounded-xl p-8">
<Markdawn className="max-w-full" text={markdown} />
</div>
</div>
</div>
</ContentPanel>
);
return <AppLayout title="404" langui={langui} contentPanel={contentPanel} />;
}
export const getStaticProps: GetStaticProps = async (context) => {
if (context.locale) {
const props: EditorProps = {
langui: await getWebsiteInterface({
language_code: context.locale,
}),
};
return {
props: props,
};
}
return { props: {} };
};

View File

@ -13,7 +13,7 @@ export default function Home(props: HomeProps): JSX.Element {
const contentPanel = ( const contentPanel = (
<ContentPanel autoformat={true}> <ContentPanel autoformat={true}>
<div className="grid place-items-center place-content-center w-full gap-5"> <div className="grid place-items-center place-content-center w-full gap-5 text-center">
<SVG <SVG
className="w-32 mobile:w-1/2" className="w-32 mobile:w-1/2"
src={"/icons/accords.svg"} src={"/icons/accords.svg"}

View File

@ -16,6 +16,7 @@ import ReturnButton from "components/PanelComponents/ReturnButton";
import SceneBreak from "components/Markdown/SceneBreak"; import SceneBreak from "components/Markdown/SceneBreak";
import ThumbnailHeader from "components/Content/ThumbnailHeader"; import ThumbnailHeader from "components/Content/ThumbnailHeader";
import AppLayout from "components/AppLayout"; import AppLayout from "components/AppLayout";
import Markdawn from "components/Markdown/Markdawn";
type ContentReadProps = { type ContentReadProps = {
content: GetContentTextQuery; content: GetContentTextQuery;
@ -42,12 +43,7 @@ export default function ContentRead(props: ContentReadProps): JSX.Element {
<HorizontalLine /> <HorizontalLine />
{content.text_set.length > 0 ? ( {content.text_set.length > 0 ? (
<Markdown <Markdawn text={content.text_set[0].text} />
className="prose prose-lg text-black pt-12"
options={{ overrides: { hr: { component: SceneBreak } } }}
>
{content.text_set[0].text}
</Markdown>
) : ( ) : (
"" ""
)} )}

View File

@ -51,4 +51,15 @@
*::-webkit-scrollbar-thumb { *::-webkit-scrollbar-thumb {
@apply bg-dark rounded-full border-[3px] border-solid border-light; @apply bg-dark rounded-full border-[3px] border-solid border-light;
} }
/* CHANGE PROSE DEFAULTS */
.prose a {
@apply transition-colors underline-offset-2 decoration-dotted underline decoration-dark hover:text-dark;
}
.prose {
--tw-prose-bullets: theme("colors.dark") !important;
}
} }