рд╕рд╛рдордЧреНрд░реА, рдЬрд┐рд╕рдХрд╛ рдЕрдиреБрд╡рд╛рдж рдЖрдЬ рд╣рдо рдкреНрд░рдХрд╛рд╢рд┐рдд рдХрд░рддреЗ рд╣реИрдВ, HTML-рдХреЛрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЯреЗрдореНрдкрд▓реЗрдЯ рдХреЗ рд░реВрдк рдореЗрдВ рдЧрддрд┐рд╢реАрд▓ рдкреАрдбреАрдПрдл-рдлрд╛рдЗрд▓реЛрдВ рдХреЗ рдирд┐рд░реНрдорд╛рдг рдХреЗ рд▓рд┐рдП рд╕рдорд░реНрдкрд┐рдд рд╣реИред рдЕрд░реНрдерд╛рддреН, рд╣рдо рдХреБрдЫ рд╡рд╕реНрддреБрдУрдВ рдпрд╛ рд╕реЗрд╡рд╛рдУрдВ рдХреЗ рднреБрдЧрддрд╛рди рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рд░рд▓ рдЗрдирд╡реЙрдЗрд╕ рдмрдирд╛рдиреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░реЗрдВрдЧреЗ, рдЬрд┐рд╕рдореЗрдВ рд╢рд╛рдорд┐рд▓ рдбрд╛рдпрдирд╛рдорд┐рдХ рдбреЗрдЯрд╛ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рд╕реНрдерд┐рддрд┐ рдХреЗ рд░рд╛рдЬреНрдп рд╕реЗ рд▓рд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рд░рд┐рдПрдХреНрдЯ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХрд╛ рдЖрдзрд╛рд░ create-react-app рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рдерд╛, рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдХрд╛ рд╕рд░реНрд╡рд░ рд╣рд┐рд╕реНрд╕рд╛ Node.js рдкрд░ рдЖрдзрд╛рд░рд┐рдд рд╣реИ, рдФрд░ рдЗрд╕рдХреЗ рд╡рд┐рдХрд╛рд╕ рдореЗрдВ рдПрдХреНрд╕рдкреНрд░реЗрд╕ рдлреНрд░реЗрдорд╡рд░реНрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред

рдЗрд╕ рд╕рд╛рдордЧреНрд░реА рдХреЗ рд▓реЗрдЦрдХ рдиреЗ рдиреЛрдЯ рдХрд┐рдпрд╛ рдХрд┐ рдЙрдиреНрд╣реЛрдВрдиреЗ рдПрдХ
рд╡реАрдбрд┐рдпреЛ рддреИрдпрд╛рд░ рдХрд┐рдпрд╛ рдЬреЛ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЗ рд╡рд┐рдХрд╛рд╕ рдХреЛ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рддрд╛ рд╣реИред рдпрджрд┐ рдЖрдк рд╡реАрдбрд┐рдпреЛ рджреЗрдЦрдиреЗ рдФрд░ рд▓реЗрдЦ рдкрдврд╝рдиреЗ рдХрд╛ рдирд┐рд░реНрдгрдп рд▓реЗрддреЗ рд╣реИрдВ, рддреЛ рдРрд╕рд╛ рдХрд░рдиреЗ рдХреА рд╕рд┐рдлрд╛рд░рд┐рд╢ рдХреА рдЬрд╛рддреА рд╣реИред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд▓реЗрдЦ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╕реНрдХрд┐рдо рдХрд░реЗрдВ, рдлрд┐рд░ рд╡реАрдбрд┐рдпреЛ рдЪрд╛рд▓реВ рдХрд░реЗрдВ рдФрд░ рдЙрд╕ рд╕рд┐рд╕реНрдЯрдо рдХреЛ рдлрд┐рд░ рд╕реЗ рдмрдирд╛рдПрдВ рдЬреЛ рдЖрдк рд╡рд╣рд╛рдВ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░ рд░рд╣реЗ рд╣реИрдВред рдЙрд╕рдХреЗ рдмрд╛рдж, рдмрд╕ рд▓реЗрдЦ рдкрдврд╝реЗрдВред
рдкрд░рд┐рдпреЛрдЬрдирд╛ рдирд┐рд░реНрдорд╛рдг
рдПрдХ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдмрдирд╛рдПрдВ рдФрд░ рдЙрд╕ рдкрд░ рдЬрд╛рдПрдВ:
mkdir pdfGenerator && cd pdfGenerator
рдПрдХ рдирдпрд╛ рд░рд┐рдПрдХреНрдЯ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдмрдирд╛рдПрдВ:
create-react-app client
рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдирд┐рд░реНрдорд╛рдг рдкреВрд░рд╛ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рдЖрдкрдХреЗ рджреНрд╡рд╛рд░рд╛ рдмрдирд╛рдИ рдЧрдИ рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдкрд░ рдЬрд╛рдПрдВ рдФрд░ рдирд┐рд░реНрднрд░рддрд╛рдПрдВ рд╕реНрдерд╛рдкрд┐рдд рдХрд░реЗрдВ:
cd client && npm i -S axios file-saver
рдПрдХ рдПрдХреНрд╕рдкреНрд░реЗрд╕ рд╕рд░реНрд╡рд░ рдмрдирд╛рдПрдБред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдбрд╛рдпрд░реЗрдХреНрдЯрд░реА рдореЗрдВ
server
рдлрд╝реЛрд▓реНрдбрд░ рдмрдирд╛рдПрдБ рдФрд░ рдЙрд╕ рдкрд░ рдЬрд╛рдПрдБред рдЗрд╕рдореЗрдВ,
index.js
рдлрд╝рд╛рдЗрд▓ рдмрдирд╛рдПрдБ рдФрд░ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдЗрдирд┐рд╢рд┐рдпрд▓рд╛рдЗрдЬрд╝реЗрд╢рди рд╢реБрд░реВ рдХрд░реЗрдВ:
mkdir server && cd server && touch index.js && npm init
рдпрд╣рд╛рдБ,
package.json
, рдмрд╕ рдХрдИ рдмрд╛рд░
Enter
рджрдмрд╛рдПрдБред рдЙрд╕рдХреЗ рдмрд╛рдж, рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдХреЗ рд╕рд░реНрд╡рд░ рднрд╛рдЧ рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рдирд┐рд░реНрднрд░рддрд╛рдПрдБ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдирд┐рдореНрди рдХрдорд╛рдВрдб рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░реЗрдВ:
npm i -S express body-parser cors html-pdf
рдЕрдм,
client/package.json
рдлрд╝рд╛рдЗрд▓ рдореЗрдВ, рдирд┐рд░реНрднрд░рддрд╛ рд╡рд┐рд╡рд░рдг рдЕрдиреБрднрд╛рдЧ рдХреЗ рдКрдкрд░, рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдЬреЛрдбрд╝реЗрдВ:
"proxy": "http://localhost:5000/"
рдпрд╣ рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЛрдб рд╕реЗ рд╕реНрдерд╛рдиреАрдп рд╕рд░реНрд╡рд░ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдореЗрдВ рдорджрдж рдХрд░реЗрдЧрд╛ред
рдЕрдм рдЖрдкрдХреЛ рдЯрд░реНрдорд┐рдирд▓ рдХреА рджреЛ рд╡рд┐рдВрдбреЛ рдЦреЛрд▓рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред
рдкрд╣рд▓реА рд╡рд┐рдВрдбреЛ рдореЗрдВ,
client
рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдкрд░ рдЬрд╛рдПрдВ рдФрд░ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХрдорд╛рдВрдб рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░реЗрдВ:
npm start
рджреВрд╕рд░реА рд╡рд┐рдВрдбреЛ рдореЗрдВ,
server
рдлрд╝реЛрд▓реНрдбрд░ рдкрд░ рдЬрд╛рдПрдВ рдФрд░ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХрдорд╛рдВрдб рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░реЗрдВ:
nodemon index.js
рдкреНрд░рд╛рд░рдВрднрд┐рдХ рдЧреНрд░рд╛рд╣рдХ рд╕реЗрдЯрдЕрдк
рд╣рдорд╛рд░реА рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХрд╛ рдЧреНрд░рд╛рд╣рдХ рд╣рд┐рд╕реНрд╕рд╛ рдмрд╣реБрдд рд╕рд░рд▓ рд▓рдЧреЗрдЧрд╛ред
рд╢реБрд░реВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрд╡реЗрджрди
src/App.js
рдЧреНрд░рд╛рд╣рдХ рднрд╛рдЧ рдХреЗ
src/App.js
, рд╣рдо рдХреЛрдб рдореЗрдВ рдирд┐рд░реНрднрд░рддрд╛ рдХреЛ рдЖрдпрд╛рдд рдХрд░рддреЗ рд╣реИрдВ:
import axios from 'axios'; import { saveAs } from 'file-saver';
рдЙрд╕рдХреЗ рдмрд╛рдж, рдШрдЯрдХ рд╡рд┐рд╡рд░рдг рдХреЗ рд╢реАрд░реНрд╖ рдкрд░, рд░рд╛рдЬреНрдп рдХреЛ рдЗрдирд┐рд╢рд┐рдпрд▓рд╛рдЗрдЬрд╝ рдХрд░реЗрдВ:
state = { name: 'Adrian', receiptId: 0, price1: 0, price2: 0, }
рдЖрдЗрдП, рдПрдкреНрд▓рд┐рдХреЗрд╢рди
create-react-app
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдЯреЗрдореНрдкреНрд▓реЗрдЯ рдореЗрдВ рдмрдирд╛рдП рдЧрдП рдорд╛рдирдХ JSX рдорд╛рд░реНрдХрдЕрдк рдХреЛ рд╣рдЯрд╛рдПрдВ рдФрд░
render()
рд╡рд┐рдзрд┐ рд╕реЗ рд▓реМрдЯрд╛рдПрдВред рдЗрд╕рдореЗрдВ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдбрд╛рд▓реЗрдВ:
<div className="App"> <input type="text" placeholder="Name" name="name" onChange {this.handleChange}/> <input type="number" placeholder="Receipt ID" name="receiptId" onChange={this.handleChange}/> <input type="number" placeholder="Price 1" name="price1" onChange={this.handleChange}/> <input type="number" placeholder="Price 2" name="price2" onChange={this.handleChange}/> <button onClick={this.createAndDownloadPdf}>Download PDF</button></div>
рдЪрд▓рд┐рдП
handleChange
рд╡рд┐рдзрд┐ рдмрдирд╛рддреЗ рд╣реИрдВ, рдЬреЛ рдЗрдирдкреБрдЯ рдлреАрд▓реНрдб рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд╕реНрдЯреЗрдЯ рдбреЗрдЯрд╛ рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЬрд┐рдореНрдореЗрджрд╛рд░ рд╣реЛрдЧрд╛:
handleChange = ({ target: { value, name }}) => this.setState({ [name]: value })
рдЕрдм рд╣рдо рдПрдХ рдкреАрдбреАрдПрдл рдлрд╛рдЗрд▓ рдмрдирд╛рдиреЗ рдХреЗ рдХрд╛рд░реНрдп рдХреЛ рдЖрдЧреЗ рдмрдврд╝рд╛ рд╕рдХрддреЗ рд╣реИрдВред рдЗрд╕рдХрд╛ рд╡рд╣ рд╣рд┐рд╕реНрд╕рд╛, рдЬреЛ рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╣рд▓ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рд╕рд░реНрд╡рд░ рдкрд░ рдПрдХ POST рдЕрдиреБрд░реЛрдз рдмрдирд╛рдирд╛ рд╣реИред рдЕрдиреБрд░реЛрдз рдЕрдиреБрдкреНрд░рдпреЛрдЧ рд╕реНрдерд┐рддрд┐ рднреЗрдЬрддрд╛ рд╣реИ:
createAndDownloadPdf = () => { axios.post('/create-pdf', this.state) }
рдЗрд╕рд╕реЗ рдкрд╣рд▓реЗ рдХрд┐ рд╣рдо рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЗ рдХреНрд▓рд╛рдЗрдВрдЯ рдкрдХреНрд╖ рдкрд░ рдХрд╛рдо рдХрд░рдирд╛ рдЬрд╛рд░реА рд░рдЦреЗрдВ, рд╣рдореЗрдВ рд╕рд░реНрд╡рд░ рдкрд░ рдорд╛рд░реНрдЧреЛрдВ рдХреЛ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред рдпрд╣ рд╕рд░реНрд╡рд░ рдХреЛ рдХреНрд▓рд╛рдЗрдВрдЯ рд╕реЗ рдбреЗрдЯрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ, рдПрдХ рдкреАрдбреАрдПрдл рдлрд╛рдЗрд▓ рдЙрддреНрдкрдиреНрди рдХрд░рдиреЗ рдФрд░ рдЗрд╕ рдлрд╛рдЗрд▓ рдХреЛ рдХреНрд▓рд╛рдЗрдВрдЯ рдореЗрдВ рд╡рд╛рдкрд╕ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдЧрд╛ред
рдкреНрд░рд╛рд░рдВрднрд┐рдХ рд╕рд░реНрд╡рд░ рд╕реЗрдЯрдЕрдк
рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЗ рд╕рд░реНрд╡рд░ рднрд╛рдЧ рдореЗрдВ рдХреЗрд╡рд▓ рджреЛ рдорд╛рд░реНрдЧ рд╢рд╛рдорд┐рд▓ рд╣реЛрдВрдЧреЗред рдкреАрдбреАрдПрдл рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдХреА рдЬрд░реВрд░рдд рд╣реЛрддреА рд╣реИред рджреВрд╕рд░рд╛ рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЛ рдлрд╛рдЗрд▓ рднреЗрдЬрдиреЗ рдХреЗ рд▓рд┐рдП рд╣реИред
рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ,
index.js
рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рдирд┐рд░реНрднрд░рддрд╛рдПрдБ рдЖрдпрд╛рдд рдХрд░реЗрдВ:
const express = require('express'); const bodyParser = require('body-parser'); const pdf = require('html-pdf'); const cors = require('cors');
рд╣рдо рдПрдХреНрд╕рдкреНрд░реЗрд╕ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЛ рдЗрдирд┐рд╢рд┐рдпрд▓рд╛рдЗрдЬрд╝ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдкреЛрд░реНрдЯ рдХреЛ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░рддреЗ рд╣реИрдВ:
const app = express(); const port = process.env.PORT || 5000;
рдХреНрд╡реЗрд░реА рдкрд╛рд░реНрд╕рд░ рд╕реЗрдЯ рдХрд░реЗрдВред рд╣рдореЗрдВ рдЬреЛ рдЪрд╛рд╣рд┐рдП рд╡рд╣
req.body
рд░реВрдк рдореЗрдВ рдЙрдкрд▓рдмреНрдз рд╣реЛрдЧрд╛ред рд╣рдо CORS рдХреЛ рднреА рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░реЗрдВрдЧреЗ рддрд╛рдХрд┐ рд╣рдорд╛рд░реА
Cross-Origin Request Blocked
рддреНрд░реБрдЯрд┐ рд╣рдорд╛рд░реЗ рдХрд╛рдо рдореЗрдВ рд╣рд╕реНрддрдХреНрд╖реЗрдк рди рдХрд░реЗ:
app.use(cors()); app.use(bodyParser.urlencoded({ extended: true })); app.use(bodyParser.json());
рдЙрд╕рдХреЗ рдмрд╛рдж, рд╕рд░реНрд╡рд░ рд╢реБрд░реВ рдХрд░реЗрдВ:
app.listen(port, () => console.log(`Listening on port ${port}`));
рдЕрдм рд╣рдо рдкреАрдбреАрдПрдл рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЬрд┐рдореНрдореЗрджрд╛рд░ рдХреЛрдб рд╕реЗ рдирд┐рдкрдЯ рд╕рдХрддреЗ рд╣реИрдВред
PDF рдХреЗ рд▓рд┐рдП HTML рдЯреЗрдореНрдкрд▓реЗрдЯ рдмрдирд╛рдПрдВ
рдкреАрдбреАрдПрдл рдлрд╛рдЗрд▓реЛрдВ рдХреЛ рдмрдирд╛рддреЗ рд╕рдордп рд╣рдореЗрдВ рдПрдХ HTML рдЯреЗрдореНрдкрд▓реЗрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдкрдбрд╝рддрд╛ рд╣реИред рдЗрд╕ рддрд░рд╣ рдХрд╛ рдЦрд╛рдХрд╛ рдмрдирд╛рдиреЗ рдореЗрдВ, рдЕрдирдВрдд рд╕рдВрднрд╛рд╡рдирд╛рдПрдВ рд╣рдорд╛рд░реЗ рд╕рд╛рдордиреЗ рдЦреБрд▓ рдЬрд╛рддреА рд╣реИрдВред рд╢реБрджреНрдз рдПрдЪрдЯреАрдПрдордПрд▓ рдФрд░ рд╕реАрдПрд╕рдПрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдмрдирд╛рдИ рдЬрд╛ рд╕рдХрдиреЗ рд╡рд╛рд▓реА рд╣рд░ рдЪреАрдЬ рдХреЛ рдкреАрдбреАрдПрдл рдлрд╛рдЗрд▓ рдХреЗ рд░реВрдк рдореЗрдВ рджрд░реНрд╢рд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред
server
рдлрд╝реЛрд▓реНрдбрд░ рдореЗрдВ
documents
рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдмрдирд╛рдПрдВ, рдЙрд╕ рдкрд░ рдЬрд╛рдПрдВ рдФрд░ рдЗрд╕рдореЗрдВ
index.js
рдлрд╝рд╛рдЗрд▓ рдмрдирд╛рдПрдВ:
mkdir documents && cd documents && touch index.js
рдЗрд╕ рдлрд╝рд╛рдЗрд▓ рд╕реЗ, рд╣рдо рдПрдХ рддреАрд░ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдирд┐рд░реНрдпрд╛рдд рдХрд░рддреЗ рд╣реИрдВ рдЬреЛ рд╕рднреА рдЖрд╡рд╢реНрдпрдХ HTML рдХреЛрдб рд╡рд╛рдкрд╕ рдХрд░ рджреЗрдЧрд╛ред рдЗрд╕ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдХреЙрд▓ рдХрд░рддреЗ рд╕рдордп, рдЖрдк рдорд╛рдкрджрдВрдбреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЬрд┐рд╕рдХрд╛ рд╡рд░реНрдгрди рд╣рдо рдпрд╣рд╛рдВ рднреА рдХрд░реЗрдВрдЧреЗред
module.exports = ({ name, price1, price2, receiptId }) => { ... }
рдпрд╣рд╛рдБ рдореИрдВ рдЖрдкрдХреЛ
рдПрдХ HTML рдЯреЗрдореНрдкрд▓реЗрдЯ
рдХрд╛ рдЙрджрд╛рд╣рд░рдг рджреВрдВрдЧрд╛, рдФрд░ рдЖрдк рдЗрд╕реЗ рдЕрдкрдиреЗ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдореЗрдВ рдХреЙрдкреА рдХрд░ рд▓реЗрдВред рд▓реЗрдХрд┐рди рдЖрдк рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ, рдЕрдкрдирд╛ рдЦреБрдж рдХрд╛ рдЯреЗрдореНрдкрд▓реЗрдЯ рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВред
server/documents
рдлреЛрд▓реНрдбрд░ рд╕реЗ
index.js
рдХреЛрдб рдХреЛ рдирд┐рдореНрди рдлреЙрд░реНрдо рдореЗрдВ
index.js
:
module.exports = ({ name, price1, price2, receiptId }) => { const today = new Date(); return ` <!doctype html> <html> <head> <meta charset="utf-8"> <title>PDF Result Template</title> <style> .invoice-box { max-width: 800px; margin: auto; padding: 30px; border: 1px solid #eee; box-shadow: 0 0 10px rgba(0, 0, 0, .15); font-size: 16px; line-height: 24px; font-family: 'Helvetica Neue', 'Helvetica', color: #555; } .margin-top { margin-top: 50px; } .justify-center { text-align: center; } .invoice-box table { width: 100%; line-height: inherit; text-align: left; } .invoice-box table td { padding: 5px; vertical-align: top; } .invoice-box table tr td:nth-child(2) { text-align: right; } .invoice-box table tr.top table td { padding-bottom: 20px; } .invoice-box table tr.top table td.title { font-size: 45px; line-height: 45px; color: #333; } .invoice-box table tr.information table td { padding-bottom: 40px; } .invoice-box table tr.heading td { background: #eee; border-bottom: 1px solid #ddd; font-weight: bold; } .invoice-box table tr.details td { padding-bottom: 20px; } .invoice-box table tr.item td { border-bottom: 1px solid #eee; } .invoice-box table tr.item.last td { border-bottom: none; } .invoice-box table tr.total td:nth-child(2) { border-top: 2px solid #eee; font-weight: bold; } @media only screen and (max-width: 600px) { .invoice-box table tr.top table td { width: 100%; display: block; text-align: center; } .invoice-box table tr.information table td { width: 100%; display: block; text-align: center; } } </style> </head> <body> <div class="invoice-box"> <table cellpadding="0" cellspacing="0"> <tr class="top"> <td colspan="2"> <table> <tr> <td class="title"><img src="https://i2.wp.com/cleverlogos.co/wp-content/uploads/2018/05/reciepthound_1.jpg?fit=800%2C600&ssl=1" style="width:100%; max-width:156px;"></td> <td> Datum: ${`${today.getDate()}. ${today.getMonth() + 1}. ${today.getFullYear()}.`} </td> </tr> </table> </td> </tr> <tr class="information"> <td colspan="2"> <table> <tr> <td> Customer name: ${name} </td> <td> Receipt number: ${receiptId} </td> </tr> </table> </td> </tr> <tr class="heading"> <td>Bought items:</td> <td>Price</td> </tr> <tr class="item"> <td>First item:</td> <td>${price1}$</td> </tr> <tr class="item"> <td>Second item:</td> <td>${price2}$</td> </tr> </table> <br /> <h1 class="justify-center">Total price: ${parseInt(price1) + parseInt(price2)}$</h1> </div> </body> </html> `; };
server/index.js
рдЗрд╕ рдлрд╛рдЗрд▓ рдХреЛ
server/index.js
:
const pdfTemplate = require('./documents');
PDF рдмрдирд╛рдПрдБ
рдпрд╛рдж рд░рдЦреЗрдВ рдХрд┐ рд╕рд░реНрд╡рд░ рдкрд░ рд╣рдо рджреЛ рд░реВрдЯ рдмрдирд╛рдиреЗ рдЬрд╛ рд░рд╣реЗ рд╣реИрдВред POST рдорд╛рд░реНрдЧ рдХреНрд▓рд╛рдЗрдВрдЯ рд╕реЗ рдбреЗрдЯрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдФрд░ рдПрдХ рдкреАрдбреАрдПрдл рдлрд╛рдЗрд▓ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЬрд┐рдореНрдореЗрджрд╛рд░ рд╣реЛрдЧрд╛ред рдЬреАрдИрдЯреА рдорд╛рд░реНрдЧ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЛ рддреИрдпрд╛рд░ рдлрд╝рд╛рдЗрд▓ рднреЗрдЬрдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред
тЦН create-pdf рдорд╛рд░реНрдЧ
pdf.create()
html-pdf
рдореЙрдбреНрдпреВрд▓ рд╕реЗ рдЖрдпрд╛рдд рдХреА рдЧрдИ рд╡рд╕реНрддреБ рдХрд╛ рдЬрд┐рдХреНрд░ рдХрд░рддреЗ рд╣реБрдП,
create-pdf
POST рд░реВрдЯ рдореЗрдВ, рд╣рдо
pdf.create()
рдХрдорд╛рдВрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗред
pdf.create()
рд╡рд┐рдзрд┐ рдХреЗ рдкрд╣рд▓реЗ рдкреИрд░рд╛рдореАрдЯрд░ рдХреЗ рд░реВрдк рдореЗрдВ, рдПрдХ HTML рдЯреЗрдореНрдкрд▓реЗрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рд╕рд╛рде рд╣реА рдХреНрд▓рд╛рдЗрдВрдЯ рд╕реЗ рдкреНрд░рд╛рдкреНрдд рдбреЗрдЯрд╛ рднреАред
pdf.create()
рдХреЛ рд╡рд╛рдкрд╕ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо
toFile()
рдкрджреНрдзрддрд┐ рдХреЛ рдХреЙрд▓ рдХрд░рддреЗ рд╣реИрдВ, рдЗрд╕реЗ рд╡рд╣ рдирд╛рдо рджреЗрддреЗ рд╣реИрдВ рдЬрд┐рд╕реЗ рд╣рдо рдкреАрдбреАрдПрдл рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рдореЗрдВ рдЕрд╕рд╛рдЗрди рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рд╕рд╛рде рд╣реА рд╕рд╛рде рддреАрд░ рдХреЙрд▓рдмреИрдХ рдлрд╝рдВрдХреНрд╢рдиред рдпрд╣ рдлрд╝рдВрдХреНрд╢рди, рддреНрд░реБрдЯрд┐ рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ,
res.send(Promise.reject())
рдХрдорд╛рдВрдб рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░реЗрдЧрд╛ред рдЗрд╕ рдШрдЯрдирд╛ рдореЗрдВ рдХрд┐ рд╕рдм рдХреБрдЫ рдареАрдХ рд╣реЛ рдЧрдпрд╛, рд╡рд╣
res.send(Promise.resolve())
рдХрдорд╛рдВрдб
res.send(Promise.resolve())
рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░реЗрдЧрд╛ред
app.post('/create-pdf', (req, res) => { pdf.create(pdfTemplate(req.body), {}).toFile('result.pdf', (err) => { if(err) { res.send(Promise.reject()); } res.send(Promise.resolve()); }); });
тЦНрдлреЗрдЯ-рдкреАрдбреАрдПрдл рд░реВрдЯ
рдЙрд╕реА рд╕рдордп, рд╣рдо рдПрдХ рдорд╛рд░реНрдЧ рдмрдирд╛рдПрдВрдЧреЗ рдЬрд┐рд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдЧреНрд░рд╛рд╣рдХ рдХреЗ рдЕрдиреБрд░реЛрдз рдкрд░, рдкреАрдбреАрдПрдл рдлрд╛рдЗрд▓ рд╕рдлрд▓рддрд╛рдкреВрд░реНрд╡рдХ рдмрдирдиреЗ рдХреЗ рдмрд╛рдж рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред рдпрд╣рд╛рдВ рд╣рдо рдХреЗрд╡рд▓ рддреИрдпрд╛рд░ рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рд▓реЗрддреЗ рд╣реИрдВ рдФрд░ рдЗрд╕реЗ
res.sendFile()
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЛ рднреЗрдЬрддреЗ рд╣реИрдВ:
app.get('/fetch-pdf', (req, res) => { res.sendFile(`${__dirname}/result.pdf`) })
рдХреНрд▓рд╛рдЗрдВрдЯ рдлрд╝рдВрдХреНрд╢рди createAndDownloadPdf
рдЕрдм рд╣рдо рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЛрдб рдкрд░ рд▓реМрдЯ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░
createAndDownloadPdf
рдлрд╝рдВрдХреНрд╢рди рдкрд░ рдХрд╛рдо рдХрд░рдирд╛ рдЬрд╛рд░реА рд░рдЦ рд╕рдХрддреЗ рд╣реИрдВред рдпрд╣рд╛рдВ рд╣рдо
axios
рдореЙрдбреНрдпреВрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╕рд░реНрд╡рд░ рдХреЗ рд▓рд┐рдП рдПрдХ POST рдЕрдиреБрд░реЛрдз рдХрд░рддреЗ рд╣реИрдВред рдЕрдм рдпрд╣ рдлрд╝рдВрдХреНрд╢рди рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддрд╛ рд╣реИ:
createAndDownloadPdf = () => { axios.post('/create-pdf', this.state) }
рдпрджрд┐ рд╕рд░реНрд╡рд░ рдкрд░ рдПрдХ POST рдЕрдиреБрд░реЛрдз рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж рдПрдХ рдкреАрдбреАрдПрдл рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рдерд╛, рддреЛ рд╣рдореЗрдВ рдПрдХ GET рдЕрдиреБрд░реЛрдз рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдЬрд┐рд╕рдХреЗ рдЬрд╡рд╛рдм рдореЗрдВ рд╕рд░реНрд╡рд░ рдЧреНрд░рд╛рд╣рдХ рдХреЛ рддреИрдпрд╛рд░ рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рднреЗрдЬреЗрдЧрд╛ред
рдЗрд╕ рд╡реНрдпрд╡рд╣рд╛рд░ рдпреЛрдЬрдирд╛ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо
axios.post()
рдХреЙрд▓ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж рдХреЙрд▓ рдХрд░рддреЗ рд╣реИрдВред
then()
ред рдпрд╣ рд╣рдореЗрдВ рдРрд╕рд╛ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ рдХрд┐ рдЧреНрд░рд╛рд╣рдХ рдХреЗ POST рдЕрдиреБрд░реЛрдз рдХреЗ рдЬрд╡рд╛рдм рдореЗрдВ, рд╣рдо рдЙрд╕ рд╕рд░реНрд╡рд░ рд╕реЗ рдПрдХ рд╡рд╛рджрд╛ рд╡рд╛рдкрд╕ рдХрд░рддреЗ рд╣реИрдВ рдЬрд┐рд╕реЗ рдпрд╛ рддреЛ рд╕рдлрд▓рддрд╛рдкреВрд░реНрд╡рдХ рд╣рд▓ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдпрд╛ рдЕрд╕реНрд╡реАрдХрд╛рд░ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред
рд╣рдо рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХреЛрдб рдХреЗ рд╕рд╛рде рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдкреВрд░рдХ рдХрд░рддреЗ рд╣реИрдВ:
.then(() => axios.get('/fetch-pdf', { responseType: 'blob' })) .then(( res) => {})
рдпрд╣рд╛рдВ рдЖрдк рдЗрд╕ рддрдереНрдп рдкрд░ рдзреНрдпрд╛рди рджреЗ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐
blob
рдЙрдкрдпреЛрдЧ
responseType
рд░реВрдк
blob
рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЗрд╕рд╕реЗ рдкрд╣рд▓реЗ рдХрд┐ рд╣рдо рдЖрдЧреЗ рдмрдврд╝реЗрдВ, рдЖрдЗрдП рд╣рдо рдЗрд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░рддреЗ рд╣реИрдВред
рдмреВрдБрдж рд╡рд╕реНрддреБрдУрдВ
рдмреВрдБрдж рдХреБрдЫ рдЕрдкрд░рд┐рд╖реНрдХреГрдд рдбреЗрдЯрд╛ рдХрд╛ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдХрд░рдиреЗ рд╡рд╛рд▓реА рдПрдХ рдЕрдкрд░рд┐рд╡рд░реНрддрдиреАрдп рд╡рд╕реНрддреБ рд╣реИред рдРрд╕реА рд╡рд╕реНрддреБрдУрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдЕрдХреНрд╕рд░ рдЙрди рдбреЗрдЯрд╛ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдЬреЛ рджреЗрд╢реА рдЬрд╛рд╡рд╛рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдкреНрд░рд╛рд░реВрдк рдореЗрдВ рдирд╣реАрдВ рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВред рдРрд╕реЗ рдСрдмреНрдЬреЗрдХреНрдЯ рдмрд╛рдЗрдЯреНрд╕ рдХреЗ рдЕрдиреБрдХреНрд░рдо рд╣реЛрддреЗ рд╣реИрдВ рдЬреЛ рд╕реНрдЯреЛрд░ рдХрд░рддреЗ рд╣реИрдВ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдлрд╝рд╛рдЗрд▓ рдбреЗрдЯрд╛ред рдРрд╕рд╛ рд▓рдЧ рд╕рдХрддрд╛ рд╣реИ рдХрд┐
Blob
рдСрдмреНрдЬреЗрдХреНрдЯ рдХрд┐рд╕реА рдлрд╝рд╛рдЗрд▓ рдХреЗ рд▓рд┐рдВрдХ рдХреЛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░ рд░рд╣рд╛ рд╣реИ, рд▓реЗрдХрд┐рди рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдпрд╣ рдирд╣реАрдВ рд╣реИред рдпреЗ рдСрдмреНрдЬреЗрдХреНрдЯ рдбреЗрдЯрд╛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рддреЗ рд╣реИрдВ, рдЬрд┐рдирдХреЗ рд╕рд╛рде рдЖрдк рдХрд╛рдо рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП - рдЙрдиреНрд╣реЗрдВ рдлрд╛рдЗрд▓реЛрдВ рдореЗрдВ рд╕рд╣реЗрдЬрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред
рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдкреВрд░рд╛ рд╣реЛрдирд╛
рдЕрдм рдЬрдм рд╣рдо рдЬрд╛рдирддреЗ рд╣реИрдВ рдХрд┐
Blob
рдСрдмреНрдЬреЗрдХреНрдЯреНрд╕ рдХреНрдпрд╛ рд╣реИрдВ, рддреЛ рд╣рдо res.data рдХреЗ рдЖрдзрд╛рд░ рдкрд░, рдЗрд╕рдореЗрдВ
res.data
рдирдИ
Blob
рдСрдмреНрдЬреЗрдХреНрдЯ
res.data
.then
.then()
рдХреЙрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдЗрд╕ рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЛ рдмрдирд╛рддреЗ рд╕рдордп, рд╣рдо рдЗрд╕рдХреЗ рдирд┐рд░реНрдорд╛рддрд╛ рдХреЛ рдПрдХ рдкреИрд░рд╛рдореАрдЯрд░ рдкрд╛рд╕ рдХрд░реЗрдВрдЧреЗ, рдЬреЛ рдпрд╣ рджрд░реНрд╢рд╛рддрд╛ рд╣реИ рдХрд┐ рдСрдмреНрдЬреЗрдХреНрдЯ рдЬреЛ рдбреЗрдЯрд╛ рд╕реНрдЯреЛрд░ рдХрд░реЗрдЧрд╛, рд╡рд╣
application/pdf
рдкреНрд░рдХрд╛рд░ рдХрд╛ рд╣реИред рдЙрд╕рдХреЗ рдмрд╛рдж, рд╣рдо
saveAs()
рд╡рд┐рдзрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЬреЛ
file-saver
рдореЙрдбреНрдпреВрд▓ рд╕реЗ рдЖрдпрд╛рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рдФрд░ рдбреЗрдЯрд╛ рдХреЛ рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рд╕рд╣реЗрдЬреЗрдВред рдирддреАрдЬрддрди,
createAndDowndloadPdf
рд╡рд┐рдзрд┐ рдХрд╛ рдХреЛрдб рдиреАрдЪреЗ рджрд┐рдЦрд╛рдП рдЧрдП рдЬреИрд╕рд╛ рджрд┐рдЦреЗрдЧрд╛:
createAndDownloadPdf = () => { axios.post('/create-pdf', this.state) .then(() => axios.get('fetch-pdf', { responseType: 'blob' })) .then((res) => { const pdfBlob = new Blob([res.data], { type: 'application/pdf' }); saveAs(pdfBlob, 'newPdf.pdf'); }) }
рдпрд╣ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдЬреИрд╕рд╛ рджрд┐рдЦрддрд╛ рд╣реИред
рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдореЗрдВ рдЕрдиреБрдкреНрд░рдпреЛрдЧрдЦреЗрддреЛрдВ рдореЗрдВ рднрд░рдиреЗ рдФрд░
Download PDF
рдмрдЯрди рдкрд░ рдХреНрд▓рд┐рдХ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рдбреЗрдЯрд╛ рд╕рд░реНрд╡рд░ рдкрд░ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдПрдХ рдкреАрдбреАрдПрдл рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рдЗрд╕рд╕реЗ рдбрд╛рдЙрдирд▓реЛрдб рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
рдкреАрдбреАрдПрдл рдбрд╛рдЙрдирд▓реЛрдб рдХрд░реЗрдВрдФрд░ рдпрд╣рд╛рдБ рдкреАрдбреАрдПрдл рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рд╣реА рд╣реИред
рд╕реЙрдлреНрдЯрд╡реЗрдпрд░ рдЙрддреНрдкрдиреНрди рдкреАрдбреАрдПрдлрдкрд░рд┐рдгрд╛рдо
рд╣рдордиреЗ рдПрдХ рдРрд╕рд╛ рддрдВрддреНрд░ рджреЗрдЦрд╛, рдЬреЛ рдЖрдкрдХреЛ рдкреАрдбреАрдПрдл рдлрд╛рдЗрд▓реЛрдВ рдХреЛ рдкреНрд░реЛрдЧреНрд░рд╛рдо рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред
рдпрд╣рд╛рдБ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдХреЛрдб рдХреЗ рд╕рд╛рде
рдПрдХ GitHub рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рд╣реИред рд╣рдореЗрдВ рдЙрдореНрдореАрдж рд╣реИ рдХрд┐ рдЗрд╕ рд╕рд╛рдордЧреНрд░реА рдореЗрдВ рдЖрдкрдХреЗ рджреНрд╡рд╛рд░рд╛ рдорд┐рд▓реЗ рд╡рд┐рдЪрд╛рд░реЛрдВ рдХреЛ рдЖрдкрдХреЗ рд╡рд┐рдХрд╛рд╕ рдореЗрдВ рдЖрд╡реЗрджрди рдорд┐рд▓реЗрдЧрд╛ред
рдкреНрд░рд┐рдп рдкрд╛рдардХреЛрдВ! рдЖрдк рдкреНрд░реЛрдЧреНрд░рд╛рдо рдХреЛ Node.js рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ PDF рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЛ рдмрдирд╛рдиреЗ рдХреА рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреИрд╕реЗ рдЬрд╛рдПрдВрдЧреЗ?