Небольшой пример на React. Модальное окно, Markdown отображение

Представленное ниже приложение делает следующее:

  1. Показывает модальное окно с текстовым полем
  2. Модальное окно служит для ввода текста в формате Markdown
  3. Выводит текст введенный текст в отформатированом виде

Вывод производится с помощью функционального компонента

Используемые библиотеки, помимо React

  • bootstrap — для оформления
  • react-bootstrap — Для использования модальности
  • markdown-it — для конвертации Markdown в html
  • html-to-react — для отображения html уже отформатированым, а не чистым текстом на странице
  • refractor — для раскрашивания блоков кода
  • rehype — для преобразования блоков кода в html

Элемент ввода текста MyInput

MyInput
import React from 'react'
import './my-input.css'
const MyInput = (props) => {
    const {caption, setCaption} = props;

    const handleChange = (e) => {
        setCaption(e.target.value);
    };

    return (
        <>
            <textarea value={caption} onChange={handleChange} className="form-control" placeholder="Input text" />
        </>
    )
};

export default MyInput

Модальное окно MyModal

MyModal
import React from "react";
import {Modal, Button} from "react-bootstrap";
import MyInput from "../my-input";


const MyModal = (props) => {
    const {show, handleShow, caption, setCaption} = props;

    return (
        <>
            <Button onClick={handleShow} variant={"primary"}>
                Launch
            </Button>
            <Modal show={show} onHide={handleShow}>
                <Modal.Header closeButton>
                    <Modal.Title>Just a head</Modal.Title>
                </Modal.Header>
                <Modal.Body>
                    <p>
                        <MyInput {...{caption, setCaption}} />
                    </p>
                </Modal.Body>
                <Modal.Footer>
                    <Button variant="secondary" onClick={handleShow}>
                        Close
                    </Button>
                    <Button variant="primary" onClick={handleShow}>
                        Save
                    </Button>
                </Modal.Footer>
            </Modal>
            <div>
                {show ? 'show' : 'hide'}
            </div>
        </>
    )
};

export default MyModal

Главный компонент App.js

App.js
import React, {useState} from 'react';
import './App.css';
import MyModal from "./components/my-modal";

import 'bootstrap/dist/css/bootstrap.min.css'

import MarkdownIt from 'markdown-it';
import {Parser} from 'html-to-react'
import refractor from 'refractor';
import Rehype from 'rehype'

const rehype = Rehype();

const parser = new Parser();
const md = MarkdownIt({
    html: true,
    xhtmlOut: true,
    highlight: (code, lang) => {
        console.log("CODE===>", code);
        try {
            const result = refractor.highlight(code, lang);
            const html = rehype.stringify({type: 'root', children: result}).toString();
            console.log(html);
            return html;
        }catch(__){}
    }
});
function App() {
    const [show, setShow] = useState(false);
    const [caption, setCaption] = useState('');

    const handleShow = () => {
        setShow(!show);
    };

    return (
        <div className="container App">
            <MyModal {...{show, handleShow, caption, setCaption}}/>
            {parser.parse(md.render(caption))}
        </div>
    );
}

export default App;

Стили для раскраски текста app.css

app.css
.App {
  text-align: left;
  margin-top: 40px;
}

.language-jsx {
  padding: 20px;
  display: block;
  background: black;
  color: white;
}

.language-jsx .keyword {
  color: tomato;
}

.language-jsx .function {
  color: green;
  font-weight: bold;
}

.language-jsx .operator {
  color: red;
}

.language-jsx .punctuation{
  color: blue;
  font-size: 0.9rem;
}

.language-jsx .tag {
  color: darkcyan;
}

.language-jsx .comment {
  color: gray;
}

.language-jsx .parameter {
  color: bisque;
}

Результат

modal
Закладка Постоянная ссылка.