Объявление настраиваемого компонента React-Markdown, как я могу объявить в средстве визуализации для использования настраиваемого компонента?
Проблема
Используя React-Markdown, я могу полностью использовать свои собственные компоненты. Но это с конкретными заранее созданными ключевыми словами в уценке. Как абзац или изображения. Это работает ОТЛИЧНО. Но проблема в том, что все они кажутся заранее созданными словами / условиями, такими как абзацы, заголовки или изображения.
Я не могу найти способ добавить что-нибудь новое ключевое слово в мою уценку, например «CustomComponent», которое будет использоваться. Это все, что мне нужно на данный момент><
Это прекрасно работает для меня, чтобы превратить изображение уценки в специальный компонент «нижний колонтитул», который я сделал где-то еще. Я знаю, что это смешно, но это работает. Но я понятия не имею, как заставить этот рендерер принимать / создавать новое ключевое слово, например «emoji», «customComponent» или «somethingSilly».
let body =
`![Fullstack React](https://dzxbosgk90qga.cloudfront.net/fit-in/504x658/n/20190131015240478_fullstack-react-cover-medium%402x.png)`;
const renderers = {
image: () => <Footer/>
};
<ReactMarkdown source={body} renderers={renderers} />;
Некоторые прошлые работы, которые я сделал:
Некоторая документация:https://reposhub.com/react/miscellaneous/rexxars-react-markdown.html https://github.com/rexxars/commonmark-react-renderer/blob/master/src/commonmark-react-renderer.js#L50
Но ничто не указывает на то, как я могу использовать «CustomComponent», чтобы указать, что нужно внедрить специальный компонент.
Пример использования / фон
Я пытаюсь получить статью из своей базы данных, которая отформатирована таким же образом в разметке (в основном это гигантская строка). Я использую обычную реакцию с машинописным текстом и сокращением - это единственная часть моего приложения, которая в этом нуждается.
"
# Title
## Here is a subtitle
Some text
<CustomComponentIMade/>
Even more text after.
<CustomComponentIMade/>
"
2 ответа
Я знаю, что это, скорее всего, немного поздно для ваших целей, но мне удалось решить эту проблему с помощью специального компонента примечания.
По сути, вам нужно будет использовать плагин, а также небольшой настраиваемый плагин замечаний (я получил этот плагин прямо из
remark-directive
документы)
Затем в ответной уценке вы можете указать плагины, настраиваемые средства визуализации и настраиваемые теги, например.
import React from 'react'
import ReactMarkdown from 'react-markdown'
import {render} from 'react-dom'
import directive from 'remark-directive'
import { MyCustomComponent } from './MyCustomComponent'
// react markdown components list
const components = {
image: () => <Footer/>,
myTag: MyCustomComponent
}
// remark plugin to add a custom tag to the AST
function htmlDirectives() {
return transform
function transform(tree) {
visit(tree, ['textDirective', 'leafDirective', 'containerDirective'], ondirective)
}
function ondirective(node) {
var data = node.data || (node.data = {})
var hast = h(node.name, node.attributes)
data.hName = hast.tagName
data.hProperties = hast.properties
}
}
render(
<ReactMarkdown components={components} remarkPlugins={[directive, htmlDirectives]}>
Some markdown with a :myTag[custom directive]{title="My custom tag"}
</ReactMarkdown>,
document.body
)
Итак, в вашей уценке везде, где у вас есть что-то вроде
:myTag[...]{...attributes}
вы должны сделать
MyCustomComponent
с участием
attributes
как реквизит.
Извините, я не тестировал код, но, надеюсь, он передает суть вещей. Если вам нужен рабочий пример, дайте мне знать, и я сделаю все возможное, чтобы его настроить.
Я пробовал этот способ, и это сработало для меня
import CustomNextImage from '@commonComponentsDependent/CustomNextImage';
import dynamic from 'next/dynamic';
import Link from 'next/link';
import { FC } from 'react';
import ReactMarkdown from 'react-markdown';
import { Options } from 'react-markdown/lib/ast-to-react';
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
import remarkGfm from 'remark-gfm';
const SyntaxHighlighterDynamic = dynamic(() => import('./SyntaxHighlighter'));
import classes from './styles.module.css';
interface Props {
content: string;
}
type TCustomComponents = Options['components'];
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
const MdToHTML: FC<Props> = ({ content }) => {
const customComponents: TCustomComponents = {
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
img(image) {
if (!image.src) return <></>;
return (
<div className={classes['img-container']}>
<CustomNextImage
src={image.src}
alt={image.alt}
/>
</div>
);
},
a({ href, children, node }) {
if (!href) return <></>;
if (
href.startsWith('/') ||
href.startsWith('https://lognmaze.com')
) {
return (
<Link href={href} prefetch={false} passHref>
<a>{children}</a>
</Link>
);
}
return (
<a
href={href}
target='_blank'
rel='noopener noreferrer'
>
{children}
</a>
);
},
code({ node, inline, className, children, ...props }) {
const match = /language-(\w+)/.exec(className || '');
return !inline && match ? (
<SyntaxHighlighterDynamic language={match[1]} PreTag='div' {...props}>
{String(children).replace(/\n$/, '')}
</SyntaxHighlighterDynamic>
) : (
<code className={className} {...props} data-code-inline='true'>
{children}
</code>
);
},
};
return (
<ReactMarkdown
components={customComponents}
remarkPlugins={[remarkGfm]}
>
{content}
</ReactMarkdown>
);
};
export default MdToHTML;