This commit is contained in:
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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
87
utils/reactmarkdown.tsx
Normal 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} />
|
||||
);
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user