Headers now generates copiable anchor links
This commit is contained in:
parent
28ac9012ff
commit
f89dbb36e9
|
@ -21,6 +21,30 @@ export default function Markdawn(props: ScenBreakProps): JSX.Element {
|
||||||
options={{
|
options={{
|
||||||
slugify: slugify,
|
slugify: slugify,
|
||||||
overrides: {
|
overrides: {
|
||||||
|
h2: {
|
||||||
|
component: (props: { id: string; children: React.ReactNode }) => {
|
||||||
|
return (
|
||||||
|
<div className="flex flex-row place-items-center place-content-center gap-3 hover:[--anchor-opacity:100] [--anchor-opacity:0]">
|
||||||
|
<h2 id={props.id}>{props.children}</h2>
|
||||||
|
<abbr title="Copy anchor link">
|
||||||
|
<span
|
||||||
|
className="material-icons opacity-[var(--anchor-opacity)] transition-all hover:text-dark cursor-pointer"
|
||||||
|
onClick={() => {
|
||||||
|
navigator.clipboard.writeText(
|
||||||
|
process.env.NEXT_PUBLIC_URL_SELF +
|
||||||
|
window.location.pathname +
|
||||||
|
"#" +
|
||||||
|
props.id
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
link
|
||||||
|
</span>
|
||||||
|
</abbr>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
Sep: {
|
Sep: {
|
||||||
component: () => {
|
component: () => {
|
||||||
return <div className="my-24"></div>;
|
return <div className="my-24"></div>;
|
||||||
|
|
|
@ -1,20 +1,23 @@
|
||||||
|
import { NextRouter } from "next/router";
|
||||||
import { slugify } from "queries/helpers";
|
import { slugify } from "queries/helpers";
|
||||||
import { preprocessMarkDawn } from "./Markdawn";
|
import { preprocessMarkDawn } from "./Markdawn";
|
||||||
|
|
||||||
type TOCProps = {
|
type TOCProps = {
|
||||||
text: string;
|
text: string;
|
||||||
title?: string;
|
title?: string;
|
||||||
|
router: NextRouter;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function TOC(props: TOCProps): JSX.Element {
|
export default function TOC(props: TOCProps): JSX.Element {
|
||||||
const toc = getTocFromMarkdawn(preprocessMarkDawn(props.text), props.title);
|
const { router, text, title } = props;
|
||||||
|
const toc = getTocFromMarkdawn(preprocessMarkDawn(text), title);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<h3 className="text-xl">Table of content</h3>
|
<h3 className="text-xl">Table of content</h3>
|
||||||
<ol className="text-left">
|
<ol className="text-left">
|
||||||
<li className="my-2 overflow-x-hidden w-full text-ellipsis whitespace-nowrap">
|
<li className="my-2 overflow-x-hidden w-full text-ellipsis whitespace-nowrap">
|
||||||
<a className="" href={`#${toc.slug}`}>
|
<a className="" onClick={() => router.replace(`#${toc.slug}`)}>
|
||||||
{<abbr title={toc.title}>{toc.title}</abbr>}
|
{<abbr title={toc.title}>{toc.title}</abbr>}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
@ -25,7 +28,7 @@ export default function TOC(props: TOCProps): JSX.Element {
|
||||||
className="my-2 overflow-x-hidden w-full text-ellipsis whitespace-nowrap"
|
className="my-2 overflow-x-hidden w-full text-ellipsis whitespace-nowrap"
|
||||||
>
|
>
|
||||||
<span className="text-dark">{`${h2Index + 1}. `}</span>
|
<span className="text-dark">{`${h2Index + 1}. `}</span>
|
||||||
<a href={`#${h2.slug}`}>
|
<a onClick={() => router.replace(`#${h2.slug}`)}>
|
||||||
{<abbr title={h2.title}>{h2.title}</abbr>}
|
{<abbr title={h2.title}>{h2.title}</abbr>}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
@ -38,7 +41,7 @@ export default function TOC(props: TOCProps): JSX.Element {
|
||||||
<span className="text-dark">{`${h2Index + 1}.${
|
<span className="text-dark">{`${h2Index + 1}.${
|
||||||
h3Index + 1
|
h3Index + 1
|
||||||
}. `}</span>
|
}. `}</span>
|
||||||
<a href={`#${h3.slug}`}>
|
<a onClick={() => router.replace(`#${h3.slug}`)}>
|
||||||
{<abbr title={h3.title}>{h3.title}</abbr>}
|
{<abbr title={h3.title}>{h3.title}</abbr>}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
|
@ -148,6 +148,7 @@ export default function ContentRead(props: ContentReadProps): JSX.Element {
|
||||||
<HorizontalLine />
|
<HorizontalLine />
|
||||||
<TOC
|
<TOC
|
||||||
text={content.text_set[0].text}
|
text={content.text_set[0].text}
|
||||||
|
router={router}
|
||||||
title={
|
title={
|
||||||
content.titles.length > 0
|
content.titles.length > 0
|
||||||
? prettyinlineTitle(
|
? prettyinlineTitle(
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
@apply transition-colors underline-offset-2 decoration-dotted underline decoration-dark hover:text-dark;
|
@apply transition-colors underline-offset-2 decoration-dotted underline decoration-dark hover:text-dark cursor-pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
*::selection {
|
*::selection {
|
||||||
|
|
Loading…
Reference in New Issue