рефакторинг
This commit is contained in:
28
README.md
28
README.md
@@ -1,27 +1 @@
|
|||||||
# React + TypeScript + Vite
|
Сайт с калькулятором на mathjs
|
||||||
|
|
||||||
This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
|
|
||||||
|
|
||||||
Currently, two official plugins are available:
|
|
||||||
|
|
||||||
- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
|
|
||||||
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
|
|
||||||
|
|
||||||
## Expanding the ESLint configuration
|
|
||||||
|
|
||||||
If you are developing a production application, we recommend updating the configuration to enable type aware lint rules:
|
|
||||||
|
|
||||||
- Configure the top-level `parserOptions` property like this:
|
|
||||||
|
|
||||||
```js
|
|
||||||
parserOptions: {
|
|
||||||
ecmaVersion: 'latest',
|
|
||||||
sourceType: 'module',
|
|
||||||
project: ['./tsconfig.json', './tsconfig.node.json'],
|
|
||||||
tsconfigRootDir: __dirname,
|
|
||||||
},
|
|
||||||
```
|
|
||||||
|
|
||||||
- Replace `plugin:@typescript-eslint/recommended` to `plugin:@typescript-eslint/recommended-type-checked` or `plugin:@typescript-eslint/strict-type-checked`
|
|
||||||
- Optionally add `plugin:@typescript-eslint/stylistic-type-checked`
|
|
||||||
- Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and add `plugin:react/recommended` & `plugin:react/jsx-runtime` to the `extends` list
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<link rel="icon" type="image/svg" href="./favicon.svg" />
|
<link rel="icon" type="image/svg" href="./favicon.svg" />
|
||||||
<link rel="manifest" href="./manifest.webmanifest" />
|
<link rel="manifest" href="./manifest.webmanifest" />
|
||||||
<title>Calculator</title>
|
<title>calculator</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
|
|||||||
53
src/App.tsx
53
src/App.tsx
@@ -1,53 +0,0 @@
|
|||||||
import { noop } from 'lodash'
|
|
||||||
import { Editor } from './Editor'
|
|
||||||
|
|
||||||
export const App = () => {
|
|
||||||
return <Editor text={testText} onChange={noop} />
|
|
||||||
}
|
|
||||||
|
|
||||||
const testText = `
|
|
||||||
# Welcome to calculator (написать норм приветствие и описать принцип работы калькулятора)
|
|
||||||
# Lines starting with # are ignored
|
|
||||||
|
|
||||||
# Basic math
|
|
||||||
2 + 2
|
|
||||||
6 - 3
|
|
||||||
10 / 4
|
|
||||||
5 * 1.5
|
|
||||||
2 + 2 * 2
|
|
||||||
(2 + 2) * 2
|
|
||||||
0.1 + 0.2
|
|
||||||
|
|
||||||
# Units
|
|
||||||
10 inch in cm
|
|
||||||
2 feet to m
|
|
||||||
15 degC to degF
|
|
||||||
3 tbsp to tsp
|
|
||||||
9 km/h to m/s
|
|
||||||
|
|
||||||
# Functions
|
|
||||||
sqrt(3^2 + 4^2)
|
|
||||||
cos(pi rad)
|
|
||||||
sin(30 deg)
|
|
||||||
|
|
||||||
# Variables
|
|
||||||
a = 25
|
|
||||||
b = a * 2
|
|
||||||
|
|
||||||
2 * 2
|
|
||||||
last + 1
|
|
||||||
|
|
||||||
# Function declaration
|
|
||||||
pow2(x) = x ^ 2
|
|
||||||
pow2(6)
|
|
||||||
|
|
||||||
f(x) = (sin(x) + cos(x/2)) * 5
|
|
||||||
|
|
||||||
# Matrices
|
|
||||||
a = [1, 2, 3; 2+2, 5, 6]
|
|
||||||
a[2, 3]
|
|
||||||
a[1:2, 2]
|
|
||||||
b = [1, 2; 3, 4]
|
|
||||||
b * a
|
|
||||||
a[3, 1:3] = [7, 8, 9]
|
|
||||||
`
|
|
||||||
@@ -1,33 +1,89 @@
|
|||||||
import { defaultKeymap, historyKeymap, history } from '@codemirror/commands'
|
import { defaultKeymap, historyKeymap, history } from '@codemirror/commands'
|
||||||
import { EditorView, drawSelection, dropCursor, keymap } from '@codemirror/view'
|
import { EditorView, drawSelection, dropCursor, keymap, placeholder } from '@codemirror/view'
|
||||||
import { defaultHighlightStyle, indentOnInput, syntaxHighlighting } from '@codemirror/language'
|
import { defaultHighlightStyle, indentOnInput, syntaxHighlighting } from '@codemirror/language'
|
||||||
import { Extension } from '@codemirror/state'
|
import { Extension } from '@codemirror/state'
|
||||||
import { closeBrackets, closeBracketsKeymap } from '@codemirror/autocomplete'
|
import { closeBrackets, closeBracketsKeymap } from '@codemirror/autocomplete'
|
||||||
import { searchKeymap } from '@codemirror/search'
|
import { searchKeymap } from '@codemirror/search'
|
||||||
import { useEffect, useRef } from 'react'
|
import { useEffect, useRef } from 'react'
|
||||||
import { textObserverPlugin } from './textObserverPlugin'
|
|
||||||
import { mathPlugin } from './mathPlugin'
|
import { mathPlugin } from './mathPlugin'
|
||||||
|
|
||||||
type Props = {
|
const testText = `# Welcome to calculator
|
||||||
text: string
|
# Lines starting with # are ignored
|
||||||
onChange: (text: string) => void
|
|
||||||
}
|
|
||||||
|
|
||||||
export const Editor = ({ text, onChange }: Props) => {
|
# Basic math
|
||||||
|
2 + 2
|
||||||
|
6 - 3
|
||||||
|
10 / 4
|
||||||
|
5 * 1.5
|
||||||
|
2 + 2 * 2
|
||||||
|
(2 + 2) * 2
|
||||||
|
0.1 + 0.2
|
||||||
|
|
||||||
|
# Units
|
||||||
|
10 inch in cm
|
||||||
|
2 feet to m
|
||||||
|
15 degC to degF
|
||||||
|
3 tbsp to tsp
|
||||||
|
9 km/h to m/s
|
||||||
|
|
||||||
|
# Functions
|
||||||
|
sqrt(3^2 + 4^2)
|
||||||
|
cos(pi rad)
|
||||||
|
sin(30 deg)
|
||||||
|
|
||||||
|
# Variables
|
||||||
|
a = 25
|
||||||
|
b = a * 2
|
||||||
|
|
||||||
|
2 * 2
|
||||||
|
last + 1
|
||||||
|
|
||||||
|
# Function declaration
|
||||||
|
pow2(x) = x ^ 2
|
||||||
|
pow2(6)
|
||||||
|
|
||||||
|
f(x) = (sin(x) + cos(x/2)) * 5
|
||||||
|
|
||||||
|
# Matrices
|
||||||
|
a = [1, 2, 3; 2+2, 5, 6]
|
||||||
|
a[2, 3]
|
||||||
|
a[1:2, 2]
|
||||||
|
b = [1, 2; 3, 4]
|
||||||
|
b * a
|
||||||
|
a[3, 1:3] = [7, 8, 9]
|
||||||
|
`
|
||||||
|
|
||||||
|
export const Editor = () => {
|
||||||
const ref = useRef<HTMLDivElement>(null)
|
const ref = useRef<HTMLDivElement>(null)
|
||||||
const view = useRef<EditorView>()
|
const view = useRef<EditorView>()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
view.current = new EditorView({
|
view.current = new EditorView({
|
||||||
doc: text,
|
doc: '',
|
||||||
extensions: [basicSetup, textObserverPlugin(onChange)],
|
extensions: [basicSetup],
|
||||||
parent: ref.current!,
|
parent: ref.current!,
|
||||||
})
|
})
|
||||||
|
|
||||||
return () => view.current?.destroy()
|
return () => view.current?.destroy()
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
return <div className="cm-editor-mount" ref={ref}></div>
|
return (
|
||||||
|
<div className="wrapper">
|
||||||
|
<div className="header">
|
||||||
|
<button
|
||||||
|
className="example-button"
|
||||||
|
onClick={() => {
|
||||||
|
view.current?.dispatch({
|
||||||
|
changes: { from: 0, to: view.current?.state.doc.length, insert: testText },
|
||||||
|
})
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
tutorial
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div className="cm-editor-mount" ref={ref}></div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const basicSetup: Extension = [
|
const basicSetup: Extension = [
|
||||||
@@ -39,4 +95,5 @@ const basicSetup: Extension = [
|
|||||||
closeBrackets(),
|
closeBrackets(),
|
||||||
keymap.of([...closeBracketsKeymap, ...defaultKeymap, ...searchKeymap, ...historyKeymap]),
|
keymap.of([...closeBracketsKeymap, ...defaultKeymap, ...searchKeymap, ...historyKeymap]),
|
||||||
mathPlugin(),
|
mathPlugin(),
|
||||||
|
placeholder('0.1 + 0.2 = 0.3'),
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -22,6 +22,10 @@ body {
|
|||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.cm-scroller {
|
||||||
|
margin-right: -14px;
|
||||||
|
}
|
||||||
|
|
||||||
.math-result {
|
.math-result {
|
||||||
color: rgb(80, 80, 80);
|
color: rgb(80, 80, 80);
|
||||||
margin-left: 8px;
|
margin-left: 8px;
|
||||||
@@ -52,3 +56,26 @@ body {
|
|||||||
border-left: 0;
|
border-left: 0;
|
||||||
margin-left: 6px;
|
margin-left: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.example-button {
|
||||||
|
background-color: black;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 8px 16px;
|
||||||
|
font-family: monospace;
|
||||||
|
font-size: 14px;
|
||||||
|
cursor: pointer;
|
||||||
|
margin: 8px 0;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.example-button:hover {
|
||||||
|
background-color: #333;
|
||||||
|
transform: translateY(-3px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.example-button:active {
|
||||||
|
transform: translateY(3px);
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import ReactDOM from 'react-dom/client'
|
import ReactDOM from 'react-dom/client'
|
||||||
import { App } from './App.tsx'
|
import { Editor } from './Editor.tsx'
|
||||||
import './index.css'
|
import './index.css'
|
||||||
|
|
||||||
const root = document.getElementById('root')
|
const root = document.getElementById('root')
|
||||||
@@ -8,7 +8,7 @@ const root = document.getElementById('root')
|
|||||||
if (root) {
|
if (root) {
|
||||||
ReactDOM.createRoot(root).render(
|
ReactDOM.createRoot(root).render(
|
||||||
<React.StrictMode>
|
<React.StrictMode>
|
||||||
<App />
|
<Editor />
|
||||||
</React.StrictMode>,
|
</React.StrictMode>,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
import { create, all } from 'mathjs'
|
|
||||||
|
|
||||||
export const math = create(all)
|
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
import { Decoration, DecorationSet, EditorView, ViewPlugin, ViewUpdate, WidgetType } from '@codemirror/view'
|
import { Decoration, DecorationSet, EditorView, ViewPlugin, ViewUpdate, WidgetType } from '@codemirror/view'
|
||||||
import { math } from './math'
|
import { create, all } from 'mathjs'
|
||||||
|
|
||||||
|
const math = create(all)
|
||||||
|
|
||||||
export const mathPlugin = () =>
|
export const mathPlugin = () =>
|
||||||
ViewPlugin.fromClass(
|
ViewPlugin.fromClass(
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
import { ViewPlugin, ViewUpdate } from '@codemirror/view'
|
|
||||||
|
|
||||||
export const textObserverPlugin = (callback: (text: string) => void) =>
|
|
||||||
ViewPlugin.define(() => ({
|
|
||||||
update(update: ViewUpdate) {
|
|
||||||
if (update.docChanged) {
|
|
||||||
callback(update.state.doc.toString())
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}))
|
|
||||||
Reference in New Issue
Block a user