Improved markdawn by adding more functionalities

This commit is contained in:
DrMint 2022-03-19 17:35:17 +01:00
parent c48ff5249b
commit de6b0fe017
9 changed files with 100 additions and 43 deletions

View File

@ -5,18 +5,22 @@ import LightBox from "components/LightBox";
import ToolTip from "components/ToolTip"; import ToolTip from "components/ToolTip";
import { useAppLayout } from "contexts/AppLayoutContext"; import { useAppLayout } from "contexts/AppLayoutContext";
import Markdown from "markdown-to-jsx"; import Markdown from "markdown-to-jsx";
import { NextRouter } from "next/router";
import { slugify } from "queries/helpers"; import { slugify } from "queries/helpers";
import React, { useState } from "react"; import React, { useState } from "react";
type ScenBreakProps = { type MarkdawnProps = {
className?: string; className?: string;
text: string; text: string;
router: NextRouter;
}; };
export default function Markdawn(props: ScenBreakProps): JSX.Element { export default function Markdawn(props: MarkdawnProps): JSX.Element {
const appLayout = useAppLayout(); const appLayout = useAppLayout();
const text = preprocessMarkDawn(props.text); const text = preprocessMarkDawn(props.text);
const { router } = props;
const [lightboxOpen, setLightboxOpen] = useState(false); const [lightboxOpen, setLightboxOpen] = useState(false);
const [lightboxImages, setLightboxImages] = useState([""]); const [lightboxImages, setLightboxImages] = useState([""]);
const [lightboxIndex, setLightboxIndex] = useState(0); const [lightboxIndex, setLightboxIndex] = useState(0);
@ -43,12 +47,10 @@ export default function Markdawn(props: ScenBreakProps): JSX.Element {
children: React.ReactNode; children: React.ReactNode;
}) => { }) => {
return ( return (
<div className="flex flex-row place-items-center place-content-center gap-3"> <h1 id={props.id} style={props.style}>
<h1 id={props.id} style={props.style}> {props.children}
{props.children}
</h1>
<HeaderToolTip id={props.id} /> <HeaderToolTip id={props.id} />
</div> </h1>
); );
}, },
}, },
@ -59,12 +61,10 @@ export default function Markdawn(props: ScenBreakProps): JSX.Element {
children: React.ReactNode; children: React.ReactNode;
}) => { }) => {
return ( return (
<div className="flex flex-row place-items-center place-content-center gap-3"> <h2 id={props.id} style={props.style}>
<h2 id={props.id} style={props.style}> {props.children}
{props.children}
</h2>
<HeaderToolTip id={props.id} /> <HeaderToolTip id={props.id} />
</div> </h2>
); );
}, },
}, },
@ -75,12 +75,10 @@ export default function Markdawn(props: ScenBreakProps): JSX.Element {
children: React.ReactNode; children: React.ReactNode;
}) => { }) => {
return ( return (
<div className="flex flex-row place-items-center place-content-center gap-3"> <h3 id={props.id} style={props.style}>
<h3 id={props.id} style={props.style}> {props.children}
{props.children}
</h3>
<HeaderToolTip id={props.id} /> <HeaderToolTip id={props.id} />
</div> </h3>
); );
}, },
}, },
@ -91,12 +89,10 @@ export default function Markdawn(props: ScenBreakProps): JSX.Element {
children: React.ReactNode; children: React.ReactNode;
}) => { }) => {
return ( return (
<div className="flex flex-row place-items-center place-content-center gap-3"> <h4 id={props.id} style={props.style}>
<h4 id={props.id} style={props.style}> {props.children}
{props.children}
</h4>
<HeaderToolTip id={props.id} /> <HeaderToolTip id={props.id} />
</div> </h4>
); );
}, },
}, },
@ -107,12 +103,10 @@ export default function Markdawn(props: ScenBreakProps): JSX.Element {
children: React.ReactNode; children: React.ReactNode;
}) => { }) => {
return ( return (
<div className="flex flex-row place-items-center place-content-center gap-3"> <h5 id={props.id} style={props.style}>
<h5 id={props.id} style={props.style}> {props.children}
{props.children}
</h5>
<HeaderToolTip id={props.id} /> <HeaderToolTip id={props.id} />
</div> </h5>
); );
}, },
}, },
@ -123,12 +117,10 @@ export default function Markdawn(props: ScenBreakProps): JSX.Element {
children: React.ReactNode; children: React.ReactNode;
}) => { }) => {
return ( return (
<div className="flex flex-row place-items-center place-content-center gap-3"> <h6 id={props.id} style={props.style}>
<h6 id={props.id} style={props.style}> {props.children}
{props.children}
</h6>
<HeaderToolTip id={props.id} /> <HeaderToolTip id={props.id} />
</div> </h6>
); );
}, },
}, },
@ -151,6 +143,28 @@ export default function Markdawn(props: ScenBreakProps): JSX.Element {
); );
}, },
}, },
IntraLink: {
component: (props: {
children: React.ReactNode;
target?: string;
page?: string;
}) => {
const slug = props.target
? slugify(props.target)
: slugify(props.children?.toString());
return (
<a
onClick={() =>
router.replace(
`${props.page ? props.page : ""}#${slug}`
)
}
>
{props.children}
</a>
);
},
},
player: { player: {
component: () => { component: () => {
return ( return (
@ -219,6 +233,25 @@ export default function Markdawn(props: ScenBreakProps): JSX.Element {
); );
}, },
}, },
blockquote: {
component: (props: {
children: React.ReactNode;
cite?: string;
}) => {
return (
<blockquote>
{props.cite ? (
<>
&ldquo;{props.children}&rdquo;
<cite> {props.cite}</cite>
</>
) : (
props.children
)}
</blockquote>
);
},
},
img: { img: {
component: (props: { component: (props: {
alt: string; alt: string;
@ -230,7 +263,7 @@ export default function Markdawn(props: ScenBreakProps): JSX.Element {
}) => { }) => {
return ( return (
<div <div
className="my-8 cursor-pointer" className="my-8 cursor-pointer"
onClick={() => { onClick={() => {
setLightboxOpen(true); setLightboxOpen(true);
setLightboxImages([ setLightboxImages([
@ -280,8 +313,12 @@ export default function Markdawn(props: ScenBreakProps): JSX.Element {
function HeaderToolTip(props: { id: string }) { function HeaderToolTip(props: { id: string }) {
return ( return (
<ToolTip content={"Copy anchor link"} trigger="mouseenter"> <ToolTip
<ToolTip content={"Copied! 👍"} trigger="click"> content={"Copy anchor link"}
trigger="mouseenter"
className="text-sm"
>
<ToolTip content={"Copied! 👍"} trigger="click" className="text-sm">
<span <span
className="material-icons transition-color hover:text-dark cursor-pointer" className="material-icons transition-color hover:text-dark cursor-pointer"
onClick={() => { onClick={() => {

View File

@ -49,7 +49,7 @@ function TOCLevel(props: TOCLevelProps): JSX.Element {
> >
<span className="text-dark">{`${parentNumbering}${ <span className="text-dark">{`${parentNumbering}${
childIndex + 1 childIndex + 1
}.`}</span> }.`}</span>{" "}
<a onClick={() => router.replace(`#${child.slug}`)}> <a onClick={() => router.replace(`#${child.slug}`)}>
{<abbr title={child.title}>{child.title}</abbr>} {<abbr title={child.title}>{child.title}</abbr>}
</a> </a>

View File

@ -1,8 +1,10 @@
import type { AppProps } from "next/app"; import type { AppProps } from "next/app";
import "tailwind.css"; import "tailwind.css";
import "@fontsource/zen-maru-gothic/500.css"; import "@fontsource/zen-maru-gothic/500.css";
import "@fontsource/zen-maru-gothic/900.css";
import "@fontsource/vollkorn/700.css"; import "@fontsource/vollkorn/700.css";
import "@fontsource/opendyslexic/400.css"; import "@fontsource/opendyslexic/400.css";
import "@fontsource/opendyslexic/700.css";
import "@fontsource/material-icons"; import "@fontsource/material-icons";
import { AppContextProvider } from "contexts/AppLayoutContext"; import { AppContextProvider } from "contexts/AppLayoutContext";

View File

@ -187,7 +187,7 @@ export default function ContentRead(props: ContentReadProps): JSX.Element {
<HorizontalLine /> <HorizontalLine />
{content.text_set.length > 0 && content.text_set[0].text && ( {content.text_set.length > 0 && content.text_set[0].text && (
<Markdawn text={content.text_set[0].text} /> <Markdawn router={router} text={content.text_set[0].text} />
)} )}
</div> </div>
</ContentPanel> </ContentPanel>

View File

@ -7,11 +7,13 @@ import { useCallback, useState } from "react";
import Markdawn from "components/Markdown/Markdawn"; import Markdawn from "components/Markdown/Markdawn";
import Script from "next/script"; import Script from "next/script";
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps"; import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
import { useRouter } from "next/router";
interface EditorProps extends AppStaticProps {} interface EditorProps extends AppStaticProps {}
export default function Editor(props: EditorProps): JSX.Element { export default function Editor(props: EditorProps): JSX.Element {
const { langui } = props; const { langui } = props;
const router = useRouter();
const handleInput = useCallback((e) => { const handleInput = useCallback((e) => {
setMarkdown(e.target.value); setMarkdown(e.target.value);
@ -76,7 +78,7 @@ export default function Editor(props: EditorProps): JSX.Element {
<div> <div>
<h2>Preview</h2> <h2>Preview</h2>
<div className="bg-mid rounded-xl p-8"> <div className="bg-mid rounded-xl p-8">
<Markdawn className="max-w-full" text={markdown} /> <Markdawn router={router} className="max-w-full" text={markdown} />
</div> </div>
</div> </div>
</div> </div>

View File

@ -4,6 +4,7 @@ import ContentPanel from "components/Panels/ContentPanel";
import { getPost } from "graphql/operations"; import { getPost } from "graphql/operations";
import { GetPostQuery } from "graphql/operations-types"; import { GetPostQuery } from "graphql/operations-types";
import { GetStaticProps } from "next"; import { GetStaticProps } from "next";
import { useRouter } from "next/router";
import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps"; import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps";
import { prettySlug } from "queries/helpers"; import { prettySlug } from "queries/helpers";
@ -13,6 +14,8 @@ interface HomeProps extends AppStaticProps {
export default function Home(props: HomeProps): JSX.Element { export default function Home(props: HomeProps): JSX.Element {
const { post } = props; const { post } = props;
const router = useRouter();
const contentPanel = ( const contentPanel = (
<ContentPanel> <ContentPanel>
<div className="grid place-items-center place-content-center w-full gap-5 text-center"> <div className="grid place-items-center place-content-center w-full gap-5 text-center">
@ -23,7 +26,7 @@ export default function Home(props: HomeProps): JSX.Element {
</h2> </h2>
</div> </div>
{post.translations.length > 0 && ( {post.translations.length > 0 && (
<Markdawn text={post.translations[0].body} /> <Markdawn router={router} text={post.translations[0].body} />
)} )}
</ContentPanel> </ContentPanel>
); );

View File

@ -108,7 +108,7 @@ export default function LibrarySlug(props: PostProps): JSX.Element {
<HorizontalLine /> <HorizontalLine />
{post.translations.length > 0 && post.translations[0].body && ( {post.translations.length > 0 && post.translations[0].body && (
<Markdawn text={post.translations[0].body} /> <Markdawn router={router} text={post.translations[0].body} />
)} )}
</ContentPanel> </ContentPanel>
); );

View File

@ -274,8 +274,9 @@ export function getStatusDescription(
} }
} }
export function slugify(str: string): string { export function slugify(string: string | undefined): string {
return str if (!string) return "";
return string
.replace(/[ÀÁÂÃÄÅàáâãä忯]/g, "a") .replace(/[ÀÁÂÃÄÅàáâãä忯]/g, "a")
.replace(/[çÇ]/g, "c") .replace(/[çÇ]/g, "c")
.replace(/[ðÐ]/g, "d") .replace(/[ðÐ]/g, "d")

View File

@ -54,7 +54,7 @@
.formatted h4, .formatted h4,
.formatted h5, .formatted h5,
.formatted h6 { .formatted h6 {
@apply text-center; @apply text-center flex gap-3 justify-center;
} }
.formatted h1 { .formatted h1 {
@ -94,6 +94,10 @@
@apply my-2 text-justify; @apply my-2 text-justify;
} }
.formatted strong {
@apply font-black;
}
.formatted footer { .formatted footer {
@apply border-t-[3px] border-dotted pt-6; @apply border-t-[3px] border-dotted pt-6;
} }
@ -122,6 +126,14 @@
@apply list-decimal pl-4; @apply list-decimal pl-4;
} }
.formatted blockquote {
@apply border-2 border-mid rounded-lg p-5 text-center my-8;
}
.formatted blockquote cite {
@apply text-dark block;
}
/* INPUT */ /* INPUT */
input { input {