markdown features
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
rei
2022-12-30 14:14:05 +01:00
parent e545a596ec
commit d397503c66
13 changed files with 651 additions and 95 deletions

View File

@@ -8,3 +8,28 @@ export const formatDate = (date: string) => {
year: "numeric",
});
};
export const generateSlug = (str: string) => {
str = str?.replace(/^\s+|\s+$/g, "");
str = str?.toLowerCase();
const from = "àáãäâèéëêìíïîòóöôùúüûñç·/_,:;";
const to = "aaaaaeeeeiiiioooouuuunc------";
for (let i = 0, l = from.length; i < l; i++) {
str = str.replace(new RegExp(from.charAt(i), "g"), to.charAt(i));
}
str = str
?.replace(/[^a-z0-9 -]/g, "")
.replace(/\s+/g, "-")
.replace(/-+/g, "-");
return str;
};
export const readingTime = (content: string) => {
const wpm = 225;
const words = content.trim().split(/\s+/).length;
const time = Math.ceil(words / wpm);
return time;
};

View File

@@ -4,6 +4,7 @@ import fs from "fs";
import { FrontMatter, MarkdownDocument } from "../types/types";
import { remark } from "remark";
import html from "remark-html";
import remarkGfm from "remark-gfm";
export const BLOGS_PATH = join(process.cwd(), "content/blogs");
export const PROJECTS_PATH = join(process.cwd(), "content/projects");
@@ -57,7 +58,7 @@ export const getAllProjectsFrontMatter = (): Post[] => {
};
export async function markdownToHtml(markdown: any) {
const result = await remark().use(html).process(markdown);
const result = await remark().use(html).use(remarkGfm).process(markdown);
return result.toString();
}

87
utils/reactmarkdown.tsx Normal file
View File

@@ -0,0 +1,87 @@
import { generateSlug } from "./general";
import rangeParser from "parse-numeric-range";
import { PrismLight as SyntaxHighlighter } from "react-syntax-highlighter";
import tsx from "react-syntax-highlighter/dist/cjs/languages/prism/tsx";
import typescript from "react-syntax-highlighter/dist/cjs/languages/prism/typescript";
import scss from "react-syntax-highlighter/dist/cjs/languages/prism/scss";
import bash from "react-syntax-highlighter/dist/cjs/languages/prism/bash";
import markdown from "react-syntax-highlighter/dist/cjs/languages/prism/markdown";
import json from "react-syntax-highlighter/dist/cjs/languages/prism/json";
import { coldarkDark as defaulttheme } from "react-syntax-highlighter/dist/cjs/styles/prism";
import { BiCopy } from "react-icons/bi";
import { Components } from "react-markdown";
SyntaxHighlighter.registerLanguage("tsx", tsx);
SyntaxHighlighter.registerLanguage("typescript", typescript);
SyntaxHighlighter.registerLanguage("scss", scss);
SyntaxHighlighter.registerLanguage("bash", bash);
SyntaxHighlighter.registerLanguage("markdown", markdown);
SyntaxHighlighter.registerLanguage("json", json);
export const MarkdownComponents: Components = {
h3: (props: any) => {
const arr = props.children;
let heading = "";
for (let i = 0; i < arr.length; i++) {
if (arr[i]?.type !== undefined) {
for (let j = 0; j < arr[i].props.children.length; j++) {
heading += arr[i]?.props?.children[0];
}
} else heading += arr[i];
}
const slug = generateSlug(heading);
return (
<h3 id={slug}>
<a href={`#${slug}`} {...props}></a>
</h3>
);
},
code({ node, inline, className, ...props }: any) {
const match = /language-(\w+)/.exec(className || "");
const hasMeta = node?.data?.meta;
const applyHighlights: object = (applyHighlights: number) => {
if (hasMeta) {
const RE = /{([\d,-]+)}/;
const metadata = node.data.meta?.replace(/\s/g, "");
const strlineNumbers = RE?.test(metadata)
? // @ts-ignore
RE?.exec(metadata)[1]
: "0";
const highlightLines = rangeParser(strlineNumbers);
const highlight = highlightLines;
const data = highlight.includes(applyHighlights) ? "highlight" : null;
return { data };
} else {
return {};
}
};
return match ? (
<div>
<div className="w-full">
<button
className="w-fit ml-2 important"
onClick={() => navigator.clipboard.writeText(props.children)}
>
<BiCopy className="hover:text-action important" />
</button>
</div>
<SyntaxHighlighter
style={defaulttheme}
language={match[1]}
PreTag="div"
className="codeStyle bg-transparent"
showLineNumbers={true}
wrapLines={hasMeta ? true : false}
useInlineStyles={true}
lineProps={applyHighlights}
{...props}
/>
</div>
) : (
<code className={className} {...props} />
);
},
};