diff --git a/CLAUDE.md b/CLAUDE.md
new file mode 100644
index 0000000..2f77550
--- /dev/null
+++ b/CLAUDE.md
@@ -0,0 +1,47 @@
+# CLAUDE.md
+
+This file provides guidance to Claude Code (claude.ai/code) when working with code in this
+repository.
+
+## Project Overview
+
+Docuservix docs — шаблон документационного сайта на Docusaurus 3.10 (React 19, TypeScript 6).
+Конфигурация сайта читается из `.docuservix.yml` (title, project.org, project.repo, dirs). Локаль —
+русский (`ru`).
+
+## Commands
+
+Используется **yarn**.
+
+- `yarn start` — dev-сервер
+- `yarn build` — production-сборка в `build/`
+- `yarn typecheck` — проверка типов (tsc)
+- `yarn prettier:check` — проверка форматирования
+- `yarn prettier:fix` — автоформатирование
+
+## Architecture
+
+- `docusaurus.config.ts` — главный конфиг; читает `.docuservix.yml` через `js-yaml`
+- `src/pages/` — кастомные страницы (index.tsx — главная)
+- `src/css/custom.css` — глобальные CSS-переменные (`--ifm-*`)
+- `docs/` — Markdown/MDX-документация
+- `blog/` — блог (опционально, включается через `dirs.blog` в `.docuservix.yml`)
+- Mermaid-диаграммы включены (`@docusaurus/theme-mermaid`)
+- Docusaurus future v4 compatibility flag включён
+
+## Code Style
+
+- Prettier: 4 пробела, single quotes, trailing commas, `printWidth: 100`,
+ `singleAttributePerLine: true`
+- JSON: `printWidth: 10` (каждое свойство на отдельной строке)
+- Markdown/MDX: `proseWrap: always`
+- Husky + lint-staged: prettier запускается автоматически на pre-commit
+- CSS Modules (`*.module.css`) с camelCase именами классов
+- **Без default export** в shared/UI компонентах; default export допустим только для Docusaurus
+ route-компонентов (page components)
+
+## Environment
+
+- Node >= 20
+- Env vars: `DOCUSERVIX_URL` (production URL), `DOCUSERVIX_ON_BROKEN_LINKS` (override onBrokenLinks)
+- Gitea instance: `git.jt4d.ru`
diff --git a/docusaurus.config.ts b/docusaurus.config.ts
index 79ae98c..4e46379 100644
--- a/docusaurus.config.ts
+++ b/docusaurus.config.ts
@@ -6,6 +6,8 @@ import type { Config } from '@docusaurus/types';
import yaml from 'js-yaml';
import { themes as prismThemes } from 'prism-react-renderer';
+import docuservix from './plugins/docuservix';
+
interface DocsConfig {
title: string;
project: { org: string; repo: string };
@@ -16,7 +18,7 @@ const docsConfig = yaml.load(fs.readFileSync('./.docuservix.yml', 'utf8')) as Do
const { title } = docsConfig;
-const url = process.env.DOCUSERVIX_URL;
+const url = process.env.DOCUSERVIX_URL || 'http://example.com';
const { org, repo } = docsConfig.project;
@@ -33,6 +35,7 @@ const config: Config = {
markdown: {
mermaid: true,
},
+ plugins: [docuservix()],
themes: ['@docusaurus/theme-mermaid'],
// Future flags, see https://docusaurus.io/docs/api/docusaurus-config#future
diff --git a/package.json b/package.json
index 7709f6f..ce868b3 100644
--- a/package.json
+++ b/package.json
@@ -43,11 +43,14 @@
"@docusaurus/preset-classic": "3.10.1",
"@docusaurus/theme-mermaid": "3.10.1",
"@mdx-js/react": "^3.0.0",
+ "bem-css-modules": "^1.4.3",
"clsx": "^2.0.0",
"js-yaml": "^4.2.0",
"prism-react-renderer": "^2.3.0",
"react": "^19.0.0",
- "react-dom": "^19.0.0"
+ "react-dom": "^19.0.0",
+ "react-markdown": "^10.1.0",
+ "remark-gfm": "^4.0.1"
},
"devDependencies": {
"@docusaurus/module-type-aliases": "3.10.1",
diff --git a/plugins/docuservix/entities/markdown/MD.module.css b/plugins/docuservix/entities/markdown/MD.module.css
new file mode 100644
index 0000000..94c3868
--- /dev/null
+++ b/plugins/docuservix/entities/markdown/MD.module.css
@@ -0,0 +1,59 @@
+.MD p:last-child {
+ margin-bottom: 0;
+}
+
+.MD p:first-child {
+ margin-top: 0;
+}
+
+.MD code {
+ padding: 0.15em 0.4em;
+ border-radius: 4px;
+ background: var(--ifm-color-emphasis-200);
+ font-size: 0.85em;
+}
+
+.MD pre {
+ margin: 0.5em 0;
+ padding: 0.75em;
+ overflow-x: auto;
+ border-radius: 6px;
+ background: var(--ifm-color-emphasis-100);
+}
+
+.MD pre code {
+ padding: 0;
+ background: none;
+}
+
+.MD ul,
+.MD ol {
+ padding-left: 1.5em;
+ margin: 0.5em 0;
+}
+
+.MD table {
+ width: 100%;
+ margin: 0.5em 0;
+ border-collapse: collapse;
+ font-size: 0.9em;
+}
+
+.MD th,
+.MD td {
+ padding: 0.4em 0.75em;
+ border: 1px solid var(--ifm-color-emphasis-300);
+ text-align: left;
+}
+
+.MD th {
+ background: var(--ifm-color-emphasis-100);
+ font-weight: var(--ifm-font-weight-semibold);
+}
+
+.MD blockquote {
+ margin: 0.5em 0;
+ padding: 0.25em 1em;
+ border-left: 3px solid var(--ifm-color-emphasis-300);
+ color: var(--ifm-color-emphasis-700);
+}
diff --git a/plugins/docuservix/entities/markdown/MD.tsx b/plugins/docuservix/entities/markdown/MD.tsx
new file mode 100644
index 0000000..add0a1d
--- /dev/null
+++ b/plugins/docuservix/entities/markdown/MD.tsx
@@ -0,0 +1,17 @@
+import React, { ReactNode } from 'react';
+import Markdown from 'react-markdown';
+import remarkGfm from 'remark-gfm';
+
+import styles from './MD.module.css';
+
+interface MDProps {
+ children: string;
+}
+
+export function MD({ children }: MDProps): ReactNode {
+ return (
+
+ {children}
+
+ );
+}
diff --git a/plugins/docuservix/entities/markdown/index.ts b/plugins/docuservix/entities/markdown/index.ts
new file mode 100644
index 0000000..3288ffa
--- /dev/null
+++ b/plugins/docuservix/entities/markdown/index.ts
@@ -0,0 +1 @@
+export { MD } from './MD';
diff --git a/plugins/docuservix/index.ts b/plugins/docuservix/index.ts
new file mode 100644
index 0000000..50dbf9c
--- /dev/null
+++ b/plugins/docuservix/index.ts
@@ -0,0 +1,31 @@
+import path from 'path';
+
+import type { LoadContext, Plugin } from '@docusaurus/types';
+
+export default function docuservix() {
+ return function pluginDocuservix(_context: LoadContext): Plugin {
+ return {
+ name: 'docuservix',
+
+ configureWebpack() {
+ return {
+ resolve: {
+ alias: {
+ '@docuservix': path.resolve(__dirname),
+ },
+ },
+ };
+ },
+
+ async contentLoaded({ actions }) {
+ const { addRoute } = actions;
+
+ addRoute({
+ path: '/chat',
+ component: '@docuservix/pages/chat',
+ exact: true,
+ });
+ },
+ };
+ };
+}
diff --git a/plugins/docuservix/models/chat.ts b/plugins/docuservix/models/chat.ts
new file mode 100644
index 0000000..bdc8330
--- /dev/null
+++ b/plugins/docuservix/models/chat.ts
@@ -0,0 +1,8 @@
+export interface IChat {
+ messages: IChatMessage[];
+}
+
+export interface IChatMessage {
+ role: 'user' | 'assistant';
+ content: string;
+}
diff --git a/plugins/docuservix/pages/chat/ChatPage.tsx b/plugins/docuservix/pages/chat/ChatPage.tsx
new file mode 100644
index 0000000..8783705
--- /dev/null
+++ b/plugins/docuservix/pages/chat/ChatPage.tsx
@@ -0,0 +1,32 @@
+import Layout from '@theme/Layout';
+import { ReactNode } from 'react';
+
+import { IChat } from '@docuservix/models/chat';
+import { Chat } from '@docuservix/widgets/chat';
+
+const dialog: IChat = {
+ messages: [
+ {
+ role: 'user',
+ content: 'Can you show me some CSS animations? It can be simple tools like chatbots...',
+ },
+ {
+ role: 'assistant',
+ content: "Hello! I'm your **AI assistant**. How can I help you today?",
+ },
+ ],
+};
+
+export function ChatPage(): ReactNode {
+ return (
+
+
+
+
+
+ );
+}
diff --git a/plugins/docuservix/pages/chat/index.ts b/plugins/docuservix/pages/chat/index.ts
new file mode 100644
index 0000000..74f3d81
--- /dev/null
+++ b/plugins/docuservix/pages/chat/index.ts
@@ -0,0 +1,3 @@
+import { ChatPage } from './ChatPage';
+
+export default ChatPage;
diff --git a/plugins/docuservix/widgets/chat/Chat.module.css b/plugins/docuservix/widgets/chat/Chat.module.css
new file mode 100644
index 0000000..1ff1edd
--- /dev/null
+++ b/plugins/docuservix/widgets/chat/Chat.module.css
@@ -0,0 +1,24 @@
+.Chat {
+ display: flex;
+ flex-direction: column;
+ width: 100%;
+ background: var(--ifm-background-color);
+ border: 1px solid var(--ifm-color-emphasis-200);
+ border-radius: var(--ifm-global-radius);
+ overflow: hidden;
+}
+
+.Chat__statusMessage {
+ font-size: .65rem;
+ color: #666;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ padding: .75rem 2.5rem;
+ background: #eee;
+}
+
+.Chat__statusMessage i {
+ margin-right: .25rem;
+ color: #667eea;
+}
diff --git a/plugins/docuservix/widgets/chat/Chat.tsx b/plugins/docuservix/widgets/chat/Chat.tsx
new file mode 100644
index 0000000..01d377d
--- /dev/null
+++ b/plugins/docuservix/widgets/chat/Chat.tsx
@@ -0,0 +1,37 @@
+import block from 'bem-css-modules';
+import React, { ReactNode } from 'react';
+
+import { IChat } from '@docuservix/models/chat';
+
+import styles from './Chat.module.css';
+import { Header } from './Header';
+import { Input } from './Input';
+import { Messages } from './Messages';
+
+const b = block(styles, 'Chat');
+
+interface ChatProps {
+ dialog: IChat;
+ typing?: boolean;
+ statusMessage?: string;
+ onSend?: (text: string) => void;
+}
+
+export function Chat({ dialog, typing, statusMessage, onSend }: ChatProps): ReactNode {
+ const { messages } = dialog;
+
+ return (
+
+
+
+ {statusMessage &&
{statusMessage}
}
+
+
+ );
+}
diff --git a/plugins/docuservix/widgets/chat/Header.module.css b/plugins/docuservix/widgets/chat/Header.module.css
new file mode 100644
index 0000000..e48bbde
--- /dev/null
+++ b/plugins/docuservix/widgets/chat/Header.module.css
@@ -0,0 +1,32 @@
+.Header {
+ display: flex;
+ align-items: center;
+ gap: 1rem;
+ padding: 1rem 1.25rem;
+ border-bottom: 1px solid var(--ifm-color-emphasis-200);
+}
+
+.Header__avatar {
+ width: 50px;
+ height: 50px;
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+ border-radius: 50%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ color: white;
+ font-size: 1.5rem;
+ flex-shrink: 0;
+}
+
+.Header__info h3 {
+ margin: 0 0 0.25rem;
+ color: var(--ifm-font-color-base);
+ font-size: 1.125rem;
+}
+
+.Header__info p {
+ margin: 0;
+ color: var(--ifm-color-emphasis-600);
+ font-size: 0.85rem;
+}
diff --git a/plugins/docuservix/widgets/chat/Header.tsx b/plugins/docuservix/widgets/chat/Header.tsx
new file mode 100644
index 0000000..b438758
--- /dev/null
+++ b/plugins/docuservix/widgets/chat/Header.tsx
@@ -0,0 +1,21 @@
+import block from 'bem-css-modules';
+import React, { ReactNode } from 'react';
+
+import styles from './Header.module.css';
+import { RobotIcon } from './icons';
+
+const b = block(styles, 'Header');
+
+export function Header(): ReactNode {
+ return (
+
+
+
+
+
+
AI Assistant
+
Ready to help
+
+
+ );
+}
diff --git a/plugins/docuservix/widgets/chat/Input.module.css b/plugins/docuservix/widgets/chat/Input.module.css
new file mode 100644
index 0000000..2ab1f43
--- /dev/null
+++ b/plugins/docuservix/widgets/chat/Input.module.css
@@ -0,0 +1,58 @@
+.Input {
+ display: flex;
+ align-items: flex-end;
+ gap: 0.75rem;
+ padding: 1rem 1.25rem;
+ border-top: 1px solid var(--ifm-color-emphasis-200);
+}
+
+.Input__field {
+ flex: 1;
+ padding: 0.75rem 1rem;
+ border: 2px solid var(--ifm-color-emphasis-200);
+ border-radius: 1.5rem;
+ font-size: 1rem;
+ font-family: inherit;
+ color: var(--ifm-font-color-base);
+ background: var(--ifm-background-surface-color);
+ outline: none;
+ transition: border-color 0.3s;
+ resize: none;
+ min-height: 3.25rem;
+ max-height: 8rem;
+ field-sizing: content;
+}
+
+.Input__field:focus {
+ border-color: #667eea;
+}
+
+.Input__field:disabled {
+ opacity: 0.6;
+ cursor: not-allowed;
+}
+
+.Input__send {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ width: 3.25rem;
+ height: 3.25rem;
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+ border: none;
+ border-radius: 50%;
+ color: white;
+ font-size: 1.125rem;
+ cursor: pointer;
+ flex-shrink: 0;
+ transition: transform 0.3s;
+}
+
+.Input__send:hover:not(:disabled) {
+ transform: scale(1.1);
+}
+
+.Input__send:disabled {
+ opacity: 0.5;
+ cursor: not-allowed;
+}
diff --git a/plugins/docuservix/widgets/chat/Input.tsx b/plugins/docuservix/widgets/chat/Input.tsx
new file mode 100644
index 0000000..d61777d
--- /dev/null
+++ b/plugins/docuservix/widgets/chat/Input.tsx
@@ -0,0 +1,55 @@
+import block from 'bem-css-modules';
+import React, { ReactNode, useState } from 'react';
+
+import { PaperPlaneIcon } from './icons';
+import styles from './Input.module.css';
+
+const b = block(styles, 'Input');
+
+interface InputProps {
+ disabled?: boolean;
+ onSend?: (text: string) => void;
+}
+
+export function Input({ disabled, onSend }: InputProps): ReactNode {
+ const [input, setInput] = useState('');
+
+ const handleSend = () => {
+ const text = input.trim();
+
+ if (!text || disabled) {
+ return;
+ }
+
+ setInput('');
+ onSend?.(text);
+ };
+
+ const handleKeyDown = (e: React.KeyboardEvent) => {
+ if (e.key === 'Enter' && !e.shiftKey) {
+ e.preventDefault();
+ handleSend();
+ }
+ };
+
+ return (
+
+ );
+}
diff --git a/plugins/docuservix/widgets/chat/Message.module.css b/plugins/docuservix/widgets/chat/Message.module.css
new file mode 100644
index 0000000..4e3d362
--- /dev/null
+++ b/plugins/docuservix/widgets/chat/Message.module.css
@@ -0,0 +1,41 @@
+.Message {
+ max-width: 90%;
+ animation: slideIn 0.3s ease-out;
+}
+
+@keyframes slideIn {
+ from { opacity: 0; transform: translateY(10px); }
+ to { opacity: 1; transform: translateY(0); }
+}
+
+.Message_role_assistant {
+ align-self: flex-start;
+}
+
+.Message_role_user {
+ align-self: flex-end;
+}
+
+.Message__content {
+ padding: 0.75rem 1rem;
+ border-radius: 1.25rem;
+ line-height: 1.5;
+}
+
+.Message_role_assistant .Message__content {
+ background: var(--ifm-color-emphasis-100);
+ color: var(--ifm-font-color-base);
+ border-top-left-radius: 0.25rem;
+}
+
+.Message_role_user .Message__content {
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+ color: #fff;
+ border-bottom-right-radius: 0.25rem;
+}
+
+@media (max-width: 576px) {
+ .Message {
+ max-width: 100%;
+ }
+}
diff --git a/plugins/docuservix/widgets/chat/Message.tsx b/plugins/docuservix/widgets/chat/Message.tsx
new file mode 100644
index 0000000..a09498f
--- /dev/null
+++ b/plugins/docuservix/widgets/chat/Message.tsx
@@ -0,0 +1,23 @@
+import block from 'bem-css-modules';
+import React, { ReactNode } from 'react';
+
+import { MD } from '@docuservix/entities/markdown';
+
+import styles from './Message.module.css';
+
+const b = block(styles, 'Message');
+
+interface MessageProps {
+ role: 'user' | 'assistant';
+ content: string;
+}
+
+export function Message({ role, content }: MessageProps): ReactNode {
+ return (
+
+ );
+}
diff --git a/plugins/docuservix/widgets/chat/Messages.module.css b/plugins/docuservix/widgets/chat/Messages.module.css
new file mode 100644
index 0000000..1a2ad88
--- /dev/null
+++ b/plugins/docuservix/widgets/chat/Messages.module.css
@@ -0,0 +1,65 @@
+.Messages {
+ flex: 1;
+ overflow-y: auto;
+ padding: 1rem 1.25rem;
+ display: flex;
+ flex-direction: column;
+ gap: 1rem;
+}
+
+/* Typing indicator */
+.Messages__typing {
+ display: flex;
+ align-items: center;
+ align-self: flex-start;
+}
+
+.Messages__typingIndicator {
+ display: flex;
+ gap: 0.25rem;
+ padding: 0.75rem 1rem;
+ background: var(--ifm-color-emphasis-100);
+ border-radius: 1.25rem;
+ border-top-left-radius: 0.25rem;
+}
+
+.Messages__typingIndicator span {
+ width: 0.5rem;
+ height: 0.5rem;
+ background: var(--ifm-color-emphasis-500);
+ border-radius: 50%;
+ animation: bounce 1.4s infinite ease-in-out;
+}
+
+.Messages__typingIndicator span:nth-child(1) { animation-delay: -0.32s; }
+.Messages__typingIndicator span:nth-child(2) { animation-delay: -0.16s; }
+
+@keyframes bounce {
+ 0%, 80%, 100% { transform: scale(0); }
+ 40% { transform: scale(1); }
+}
+
+/* Scrollbar */
+.Messages::-webkit-scrollbar {
+ width: 6px;
+}
+
+.Messages::-webkit-scrollbar-track {
+ background: transparent;
+ border-radius: 3px;
+}
+
+.Messages::-webkit-scrollbar-thumb {
+ background: var(--ifm-color-emphasis-300);
+ border-radius: 3px;
+}
+
+.Messages::-webkit-scrollbar-thumb:hover {
+ background: var(--ifm-color-emphasis-400);
+}
+
+@media (min-width: 576px) {
+ .Messages {
+ padding: 1.5rem;
+ }
+}
diff --git a/plugins/docuservix/widgets/chat/Messages.tsx b/plugins/docuservix/widgets/chat/Messages.tsx
new file mode 100644
index 0000000..776b728
--- /dev/null
+++ b/plugins/docuservix/widgets/chat/Messages.tsx
@@ -0,0 +1,38 @@
+import block from 'bem-css-modules';
+import React, { ReactNode } from 'react';
+
+import { IChatMessage } from '@docuservix/models/chat';
+
+import { Message } from './Message';
+import styles from './Messages.module.css';
+
+const b = block(styles, 'Messages');
+
+interface MessagesProps {
+ messages: IChatMessage[];
+ typing?: boolean;
+}
+
+export function Messages({ messages, typing }: MessagesProps): ReactNode {
+ return (
+
+ {messages.map((msg, i) => (
+
+ ))}
+
+ {typing && (
+
+ )}
+
+ );
+}
diff --git a/plugins/docuservix/widgets/chat/icons.tsx b/plugins/docuservix/widgets/chat/icons.tsx
new file mode 100644
index 0000000..b977f2e
--- /dev/null
+++ b/plugins/docuservix/widgets/chat/icons.tsx
@@ -0,0 +1,30 @@
+import React, { ReactNode } from 'react';
+
+export function RobotIcon(): ReactNode {
+ return (
+
+ );
+}
+
+export function PaperPlaneIcon(): ReactNode {
+ return (
+
+ );
+}
diff --git a/plugins/docuservix/widgets/chat/index.ts b/plugins/docuservix/widgets/chat/index.ts
new file mode 100644
index 0000000..eeadfe5
--- /dev/null
+++ b/plugins/docuservix/widgets/chat/index.ts
@@ -0,0 +1 @@
+export { Chat } from './Chat';
diff --git a/tsconfig.json b/tsconfig.json
index 3035635..aee51ac 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -5,6 +5,11 @@
"extends": "@docusaurus/tsconfig",
"compilerOptions": {
"baseUrl": ".",
+ "paths": {
+ "@docuservix/*": [
+ "plugins/docuservix/*"
+ ]
+ },
"ignoreDeprecations": "6.0",
"strict": true
},
diff --git a/yarn.lock b/yarn.lock
index 333ae1f..9d77e06 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -4505,6 +4505,11 @@ batch@0.6.1:
resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16"
integrity sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==
+bem-css-modules@^1.4.3:
+ version "1.4.3"
+ resolved "https://registry.yarnpkg.com/bem-css-modules/-/bem-css-modules-1.4.3.tgz#b5a55bf5275c958b26691cea3d5afba77e888239"
+ integrity sha512-oB+hoRw5+M6Tt8N/DY5IpVYQEWbxd9UoGZeFJiMdpaO676zTuQhHJns9d+tfJw3yAIvg9oCf/7QlffT+vPGgEA==
+
big.js@^5.2.2:
version "5.2.2"
resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328"
@@ -7303,6 +7308,11 @@ html-tags@^3.3.1:
resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-3.3.1.tgz#a04026a18c882e4bba8a01a3d39cfe465d40b5ce"
integrity sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==
+html-url-attributes@^3.0.0:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/html-url-attributes/-/html-url-attributes-3.0.1.tgz#83b052cd5e437071b756cd74ae70f708870c2d87"
+ integrity sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ==
+
html-void-elements@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/html-void-elements/-/html-void-elements-3.0.0.tgz#fc9dbd84af9e747249034d4d62602def6517f1d7"
@@ -10551,6 +10561,23 @@ react-loadable-ssr-addon-v5-slorber@^1.0.3:
dependencies:
"@types/react" "*"
+react-markdown@^10.1.0:
+ version "10.1.0"
+ resolved "https://registry.yarnpkg.com/react-markdown/-/react-markdown-10.1.0.tgz#e22bc20faddbc07605c15284255653c0f3bad5ca"
+ integrity sha512-qKxVopLT/TyA6BX3Ue5NwabOsAzm0Q7kAPwq6L+wWDwisYs7R8vZ0nRXqq6rkueboxpkjvLGU9fWifiX/ZZFxQ==
+ dependencies:
+ "@types/hast" "^3.0.0"
+ "@types/mdast" "^4.0.0"
+ devlop "^1.0.0"
+ hast-util-to-jsx-runtime "^2.0.0"
+ html-url-attributes "^3.0.0"
+ mdast-util-to-hast "^13.0.0"
+ remark-parse "^11.0.0"
+ remark-rehype "^11.0.0"
+ unified "^11.0.0"
+ unist-util-visit "^5.0.0"
+ vfile "^6.0.0"
+
react-router-config@^5.1.1:
version "5.1.1"
resolved "https://registry.yarnpkg.com/react-router-config/-/react-router-config-5.1.1.tgz#0f4263d1a80c6b2dc7b9c1902c9526478194a988"
@@ -10804,7 +10831,7 @@ remark-frontmatter@^5.0.0:
micromark-extension-frontmatter "^2.0.0"
unified "^11.0.0"
-remark-gfm@^4.0.0:
+remark-gfm@^4.0.0, remark-gfm@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/remark-gfm/-/remark-gfm-4.0.1.tgz#33227b2a74397670d357bf05c098eaf8513f0d6b"
integrity sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==