0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2024-12-16 20:26:19 -05:00

Merge pull request #1401 from logto-io/charles-log-3415-add-support-to-toc-internal-link

refactor(console): add support to toc internal link in connector README
This commit is contained in:
Charles Zhao 2022-07-04 16:33:44 +08:00 committed by GitHub
commit d08eda153d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -1,5 +1,6 @@
import { conditionalString, Optional } from '@silverhand/essentials';
import classNames from 'classnames';
import React from 'react';
import React, { memo } from 'react';
import ReactMarkdown from 'react-markdown';
import remarkGfm from 'remark-gfm';
@ -12,29 +13,57 @@ type Props = {
children: string;
};
const Markdown = ({ className, children }: Props) => (
<ReactMarkdown
remarkPlugins={[remarkGfm]}
className={classNames(styles.markdown, className)}
components={{
code: ({ node, inline, className, children, ...props }) => {
const [, codeBlockType] = /language-(\w+)/.exec(className ?? '') ?? [];
const Markdown = ({ className, children }: Props) => {
const tocIdSet = React.useRef<Set<string>>(new Set());
return inline ? (
<code className={styles.inlineCode} {...props}>
{children}
</code>
) : (
<CodeEditor isReadonly language={codeBlockType} value={String(children)} />
);
},
img: ({ src, alt }) => {
return <GithubRawImage src={src} alt={alt} />;
},
}}
>
{children}
</ReactMarkdown>
);
const generateTocId = (text: string): Optional<string> => {
const resolveIdCollision = (kebabCaseString: string, index = 0): string => {
const result = `${kebabCaseString}${conditionalString(index && `-${index}`)}`;
export default Markdown;
if (!tocIdSet.current.has(result)) {
tocIdSet.current.add(result);
return result;
}
return resolveIdCollision(kebabCaseString, index + 1);
};
const initialKebabCaseString = text.replace(/\s/g, '-').toLowerCase();
return resolveIdCollision(initialKebabCaseString);
};
return (
<ReactMarkdown
remarkPlugins={[remarkGfm]}
className={classNames(styles.markdown, className)}
components={{
code: ({ node, inline, className, children, ...props }) => {
const [, codeBlockType] = /language-(\w+)/.exec(className ?? '') ?? [];
return inline ? (
<code className={styles.inlineCode} {...props}>
{children}
</code>
) : (
<CodeEditor isReadonly language={codeBlockType} value={String(children)} />
);
},
img: ({ src, alt }) => {
return <GithubRawImage src={src} alt={alt} />;
},
h1: ({ children }) => <h1 id={generateTocId(String(children))}>{children}</h1>,
h2: ({ children }) => <h2 id={generateTocId(String(children))}>{children}</h2>,
h3: ({ children }) => <h3 id={generateTocId(String(children))}>{children}</h3>,
h4: ({ children }) => <h4 id={generateTocId(String(children))}>{children}</h4>,
h5: ({ children }) => <h5 id={generateTocId(String(children))}>{children}</h5>,
h6: ({ children }) => <h6 id={generateTocId(String(children))}>{children}</h6>,
}}
>
{children}
</ReactMarkdown>
);
};
export default memo(Markdown);