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

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

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

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

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

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

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

MyInput
[js] 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
[/js]

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

MyModal
[js] 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[/js]

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

App.js
[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;[/js]

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

app.css
[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;
}
[/css]

Результат

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