jodit-react 4.0.30 → 5.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  /*!
2
2
  * jodit - Jodit is an awesome and useful wysiwyg editor with filebrowser
3
3
  * Author: Chupurnov <chupurnov@gmail.com> (https://xdsoft.net/jodit/)
4
- * Version: v4.2.10
4
+ * Version: v4.2.47
5
5
  * Url: https://xdsoft.net/jodit/
6
6
  * License(s): MIT
7
7
  */
@@ -0,0 +1,21 @@
1
+ import React from 'react';
2
+ import type { IJodit } from 'jodit/types/types/jodit';
3
+ import type { Jodit as JoditConstructorType } from 'jodit';
4
+ import { Jodit } from './include.jodit';
5
+ type DeepPartial<T> = T extends object ? {
6
+ [P in keyof T]?: DeepPartial<T[P]>;
7
+ } : T;
8
+ interface Props<T extends typeof JoditConstructorType = typeof Jodit> {
9
+ JoditConstructor?: T;
10
+ config?: DeepPartial<ReturnType<T['make']>['options']>;
11
+ className?: string;
12
+ id?: string;
13
+ name?: string;
14
+ onBlur?: (value: string, event: MouseEvent) => void;
15
+ onChange?: (value: string) => void;
16
+ tabIndex?: number;
17
+ value?: string;
18
+ editorRef?: (editor: IJodit) => void;
19
+ }
20
+ declare const JoditEditor: React.ForwardRefExoticComponent<Props<typeof JoditConstructorType> & React.RefAttributes<IJodit>>;
21
+ export default JoditEditor;
@@ -0,0 +1,3 @@
1
+ import type { Jodit as JoditConstructorType } from 'jodit';
2
+ import 'jodit/es5/jodit.min.css';
3
+ export declare const Jodit: typeof JoditConstructorType;
@@ -0,0 +1,4 @@
1
+ import JoditEditor from './JoditEditor';
2
+ import { Jodit } from './include.jodit';
3
+ export default JoditEditor;
4
+ export { Jodit };
@@ -1,6 +1,6 @@
1
1
  import './app.css';
2
2
 
3
- import React from 'react';
3
+ import React, { StrictMode } from 'react';
4
4
  import Form from './components/Form';
5
5
 
6
6
  // For React < 18
@@ -8,6 +8,10 @@ import Form from './components/Form';
8
8
  // ReactDOM.render(<Form />, document.getElementById('editor'));
9
9
 
10
10
  import { createRoot } from 'react-dom/client';
11
- const container = document.getElementById('editor');
11
+ const container = document.getElementById('editor')!;
12
12
  const root = createRoot(container);
13
- root.render(<Form />);
13
+ root.render(
14
+ <StrictMode>
15
+ <Form />
16
+ </StrictMode>
17
+ );
@@ -1,21 +1,22 @@
1
- import React, { useCallback, useState } from 'react';
1
+ import React, { type ChangeEvent, useCallback, useState } from 'react';
2
2
 
3
3
  import JoditEditor, { Jodit } from '../../src/';
4
4
  import './Form.css';
5
+ import type { IJodit } from 'jodit/types/types/jodit';
5
6
 
6
7
  /**
7
8
  * @param {Jodit} jodit
8
9
  */
9
- function preparePaste(jodit) {
10
+ function preparePaste(jodit: IJodit) {
10
11
  jodit.e.on(
11
12
  'paste',
12
13
  e => {
13
14
  if (confirm('Change pasted content?')) {
14
15
  jodit.e.stopPropagation('paste');
15
16
  jodit.s.insertHTML(
16
- Jodit.modules.Helpers.getDataTransfer(e)
17
+ Jodit.modules.Helpers.getDataTransfer(e)!
17
18
  .getData(Jodit.constants.TEXT_HTML)
18
- .replace(/a/g, 'b')
19
+ ?.replace(/a/g, 'b') ?? ''
19
20
  );
20
21
  return false;
21
22
  }
@@ -57,11 +58,14 @@ const Form = () => {
57
58
  []
58
59
  );
59
60
 
60
- const handleBlurAreaChange = useCallback((textAreaValue, event) => {
61
- console.log('handleBlurAreaChange', textAreaValue, event);
62
- }, []);
61
+ const handleBlurAreaChange = useCallback(
62
+ (textAreaValue: string, event: MouseEvent) => {
63
+ console.log('handleBlurAreaChange', textAreaValue, event);
64
+ },
65
+ []
66
+ );
63
67
 
64
- const handleWYSIWYGChange = useCallback(newTextAreaValue => {
68
+ const handleWYSIWYGChange = useCallback((newTextAreaValue: string) => {
65
69
  console.log('handleWYSIWYGChange', newTextAreaValue);
66
70
 
67
71
  setTextAreaValue(newTextAreaValue);
@@ -70,16 +74,17 @@ const Form = () => {
70
74
  return setTextAreaValue(() => newTextAreaValue);
71
75
  }, []);
72
76
 
73
- const handleNativeTextAreaChange = useCallback(e => {
74
- console.log('handleNativeTextAreaChange', e.target.value);
75
- setTextAreaValue(e.target.value);
76
- setInputValue(e.target.value);
77
+ const handleNativeTextAreaChange = useCallback((e: ChangeEvent) => {
78
+ const value = (e.target as HTMLTextAreaElement).value;
79
+ console.log('handleNativeTextAreaChange', value);
80
+ setTextAreaValue(value);
81
+ setInputValue(value);
77
82
  }, []);
78
83
 
79
84
  const handleInputChange = useCallback(
80
- e => {
81
- const { value } = e.target;
82
- setInputValue(() => value);
85
+ (e: ChangeEvent) => {
86
+ const { value } = e.target as HTMLInputElement;
87
+ setInputValue(value);
83
88
  handleWYSIWYGChange(value);
84
89
  },
85
90
  [handleWYSIWYGChange]
@@ -87,8 +92,8 @@ const Form = () => {
87
92
 
88
93
  const handleSpin = useCallback(() => setSpin(spin => ++spin), []);
89
94
 
90
- const onSourceChange = useCallback(e => {
91
- setSource(e.target.checked);
95
+ const onSourceChange = useCallback((e: ChangeEvent) => {
96
+ setSource((e.target as HTMLInputElement).checked);
92
97
  }, []);
93
98
 
94
99
  return (
@@ -31,17 +31,17 @@
31
31
  import './app.css';
32
32
 
33
33
  import React from 'react';
34
- import ReactDOM from 'react-dom';
34
+ import { createRoot } from 'react-dom/client';
35
35
 
36
36
  import JoditEditor from "../src/JoditEditor";
37
37
 
38
- ReactDOM.render(&lt;JoditEditor
39
- value={"test"}
40
- config={{
41
- readonly: false // all options from https://xdsoft.net/jodit/doc/
42
- }}
43
- onChange={console.log}
44
- />, document.getElementById('editor'));
38
+ const container = document.getElementById('editor')!;
39
+ const root = createRoot(container);
40
+ root.render(
41
+ &lt;StrictMode&gt;
42
+ &lt;Form /&gt;
43
+ &lt;/StrictMode&gt;
44
+ );
45
45
  </pre>
46
46
  </div>
47
47
  <div class="result">
@@ -62,5 +62,5 @@ ReactDOM.render(&lt;JoditEditor
62
62
  </body>
63
63
  <link href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,300i,400,400i,700,700i" rel="stylesheet">
64
64
 
65
- <script src="app.js"></script>
65
+ <script src="build/app.js"></script>
66
66
  </html>
@@ -0,0 +1,43 @@
1
+ import path from 'node:path';
2
+ import process from 'node:process';
3
+
4
+ export default {
5
+ entry: './app.tsx',
6
+ context: path.join(process.cwd(), './examples/'),
7
+ devtool: 'eval',
8
+ module: {
9
+ rules: [
10
+ {
11
+ test: /\.(js|jsx|ts|tsx)$/,
12
+ use: {
13
+ loader: 'swc-loader'
14
+ }
15
+ },
16
+ {
17
+ test: /\.css$/,
18
+ use: ['style-loader', 'css-loader']
19
+ }
20
+ ]
21
+ },
22
+
23
+ resolve: {
24
+ extensions: ['.js', '.jsx', '.ts', '.tsx']
25
+ },
26
+
27
+ output: {
28
+ path: path.join(process.cwd(), './examples/build/'),
29
+ filename: 'app.js'
30
+ },
31
+
32
+ devServer: {
33
+ static: './examples',
34
+ open: true,
35
+ allowedHosts: 'all',
36
+ client: {
37
+ progress: true,
38
+ overlay: true
39
+ },
40
+ port: 4000,
41
+ hot: true
42
+ }
43
+ };
package/index.d.ts CHANGED
@@ -1,27 +1 @@
1
- import type { Jodit } from 'jodit/esm/index';
2
- import * as React from 'react';
3
-
4
- type DeepPartial<T> = T extends object
5
- ? {
6
- [P in keyof T]?: DeepPartial<T[P]>;
7
- }
8
- : T;
9
-
10
- export interface IJoditEditorProps {
11
- value: string;
12
-
13
- className?: string;
14
-
15
- config?: DeepPartial<Jodit['options']>;
16
- // eslint-disable-next-line no-unused-vars
17
- onChange?: (newValue: string) => void;
18
- // eslint-disable-next-line no-unused-vars
19
- onBlur?: (newValue: string) => void;
20
- }
21
-
22
- declare const JoditEditor: React.ForwardRefExoticComponent<
23
- React.PropsWithoutRef<IJoditEditorProps> & React.RefAttributes<Jodit>
24
- >;
25
-
26
- export default JoditEditor;
27
- export { Jodit };
1
+ export type * from './build/types/index.d.ts';
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "jodit-react",
3
- "version": "4.0.30",
3
+ "version": "5.0.0-beta.1",
4
4
  "description": "Jodit is awesome and usefully wysiwyg editor with filebrowser",
5
5
  "main": "build/jodit-react.js",
6
- "author": "Chupurnov <chupurnov@gmail.com> (https://xdsoft.net/)s",
6
+ "author": "Chupurnov <chupurnov@gmail.com> (https://xdsoft.net/)",
7
7
  "keywords": [
8
8
  "react",
9
9
  "jodit",
@@ -16,46 +16,44 @@
16
16
  "rte"
17
17
  ],
18
18
  "dependencies": {
19
- "jodit": "^4.2.10"
19
+ "jodit": "^4.2.47"
20
20
  },
21
21
  "peerDependencies": {
22
- "react": "~0.14 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0",
23
- "react-dom": "~0.14 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0"
22
+ "react": "~0.14 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
23
+ "react-dom": "~0.14 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
24
24
  },
25
25
  "devDependencies": {
26
- "@babel/core": "^7.22.5",
27
- "@babel/eslint-parser": "^7.22.5",
28
- "@babel/preset-env": "^7.22.5",
29
- "@babel/preset-react": "^7.22.5",
30
- "@types/react": "^18.2.14",
31
- "@typescript-eslint/eslint-plugin": "^5.60.1",
32
- "@typescript-eslint/parser": "^5.60.1",
33
- "babel": "^6.23.0",
34
- "babel-cli": "^6.26.0",
35
- "babel-loader": "^9.1.2",
36
- "babel-plugin-transform-class-properties": "^6.24.1",
37
- "css-loader": "^6.8.1",
38
- "eslint": "8.43.0",
39
- "eslint-config-prettier": "^8.8.0",
40
- "eslint-plugin-prettier": "^4.2.1",
41
- "eslint-plugin-react": "^7.32.2",
42
- "eslint-plugin-react-hooks": "^4.6.0",
43
- "husky": "^8.0.3",
44
- "lint-staged": "^13.2.3",
45
- "prettier": "^2.8.8",
46
- "react": "^18.2.0",
47
- "react-dom": "^18.2.0",
48
- "style-loader": "^3.3.3",
49
- "webpack": "^5.88.1",
26
+ "@eslint/compat": "^1.2.4",
27
+ "@swc-node/register": "^1.10.9",
28
+ "@swc/core": "^1.10.1",
29
+ "@types/react": "^19.0.1",
30
+ "@types/react-dom": "^19.0.2",
31
+ "@typescript-eslint/eslint-plugin": "^8.18.0",
32
+ "css-loader": "^7.1.2",
33
+ "eslint": "9.16.0",
34
+ "eslint-config-prettier": "^9.1.0",
35
+ "eslint-plugin-prettier": "^5.2.1",
36
+ "eslint-plugin-react": "^7.37.2",
37
+ "eslint-plugin-react-hooks": "^5.1.0",
38
+ "prettier": "^3.4.2",
39
+ "react": "^18.3.1",
40
+ "react-dom": "^18.3.1",
41
+ "style-loader": "^4.0.0",
42
+ "swc-loader": "^0.2.6",
43
+ "webpack": "^5.97.1",
50
44
  "webpack-cli": "^5.1.4",
51
- "webpack-dev-server": "^4.15.1"
45
+ "webpack-dev-server": "^5.1.0"
52
46
  },
53
47
  "scripts": {
54
- "newversion": "npm version patch --no-git-tag-version && npm run github",
55
- "lint": "eslint ./",
56
- "demo": "cd examples && export NODE_ENV=development && webpack serve --config ./webpack.config.js --mode development",
48
+ "newversion": "npm version prerelease --preid=beta --no-git-tag-version && npm run github",
49
+ "lint": "npm run lint:ts && npm run lint:eslint",
50
+ "lint:ts": "tsc --noEmit",
51
+ "lint:eslint": "eslint ./",
52
+ "demo": "NODE_ENV=development node -r @swc-node/register ./node_modules/.bin/webpack serve --config ./examples/webpack.config.ts --mode development",
57
53
  "start": "npm run demo",
58
- "build": "export NODE_ENV=production && webpack --mode production",
54
+ "build": "npm run build:react && npm run build:types",
55
+ "build:react": "NODE_ENV=production node -r @swc-node/register ./node_modules/.bin/webpack --mode production",
56
+ "build:types": "rm -rf ./build/types && tsc --project tsconfig.types.json --emitDeclarationOnly",
59
57
  "github": "npm run git && git push --tags origin HEAD:main",
60
58
  "git": "git add --all && git commit -m \"New version $npm_package_version. Read more https://github.com/jodit/jodit-react/releases/tag/$npm_package_version \" && git tag $npm_package_version"
61
59
  },
@@ -67,16 +65,17 @@
67
65
  "bugs": {
68
66
  "url": "https://github.com/jodit/jodit-react/issues"
69
67
  },
70
- "husky": {
71
- "hooks": {
72
- "pre-commit": "lint-staged"
73
- }
74
- },
75
- "lint-staged": {
76
- "**/*.js": [
77
- "eslint ./ --fix",
78
- "git add"
68
+ "homepage": "https://xdsoft.net/jodit/",
69
+ "ava": {
70
+ "extensions": [
71
+ "ts",
72
+ "tsx"
73
+ ],
74
+ "require": [
75
+ "@swc-node/register"
76
+ ],
77
+ "files": [
78
+ "packages/**/*.spec.{ts,tsx}"
79
79
  ]
80
- },
81
- "homepage": "https://xdsoft.net/jodit/"
80
+ }
82
81
  }
@@ -0,0 +1,159 @@
1
+ import React, { useEffect, useRef, forwardRef, useLayoutEffect } from 'react';
2
+ import type { IJodit } from 'jodit/types/types/jodit';
3
+ import type { Jodit as JoditConstructorType } from 'jodit';
4
+ import { Jodit } from './include.jodit';
5
+
6
+ function usePrevious(value: string): string {
7
+ const ref = useRef<string>('');
8
+ useEffect(() => {
9
+ ref.current = value;
10
+ }, [value]);
11
+ return ref.current;
12
+ }
13
+
14
+ type DeepPartial<T> = T extends object
15
+ ? {
16
+ [P in keyof T]?: DeepPartial<T[P]>;
17
+ }
18
+ : T;
19
+
20
+ interface Props<T extends typeof JoditConstructorType = typeof Jodit> {
21
+ JoditConstructor?: T;
22
+ config?: DeepPartial<ReturnType<T['make']>['options']>;
23
+ className?: string;
24
+ id?: string;
25
+ name?: string;
26
+ onBlur?: (value: string, event: MouseEvent) => void;
27
+ onChange?: (value: string) => void;
28
+ tabIndex?: number;
29
+ value?: string;
30
+ editorRef?: (editor: IJodit) => void;
31
+ }
32
+
33
+ const JoditEditor = forwardRef<IJodit, Props>(
34
+ (
35
+ {
36
+ JoditConstructor = Jodit,
37
+ className,
38
+ config,
39
+ id,
40
+ name,
41
+ onBlur,
42
+ onChange,
43
+ tabIndex,
44
+ value,
45
+ editorRef
46
+ },
47
+ ref
48
+ ) => {
49
+ const textAreaRef = useRef<HTMLTextAreaElement | null>(null);
50
+ const joditRef = useRef<IJodit | null>(null);
51
+
52
+ useLayoutEffect(() => {
53
+ if (ref) {
54
+ if (typeof ref === 'function') {
55
+ ref(joditRef.current);
56
+ } else {
57
+ ref.current = joditRef.current;
58
+ }
59
+ }
60
+ }, [textAreaRef, ref]);
61
+
62
+ useEffect(() => {
63
+ const element = textAreaRef.current!;
64
+ const jodit = JoditConstructor.make(element, config);
65
+ joditRef.current = jodit;
66
+
67
+ if (typeof editorRef === 'function') {
68
+ editorRef(jodit);
69
+ }
70
+
71
+ return () => {
72
+ if (jodit) {
73
+ jodit.destruct();
74
+ }
75
+ };
76
+ }, [JoditConstructor, config, editorRef]);
77
+
78
+ const preClassName = usePrevious(className ?? '');
79
+
80
+ useEffect(() => {
81
+ const classList = joditRef.current?.container?.classList;
82
+
83
+ if (
84
+ preClassName !== className &&
85
+ typeof preClassName === 'string'
86
+ ) {
87
+ preClassName.split(/\s+/).forEach(cl => classList?.remove(cl));
88
+ }
89
+
90
+ if (className && typeof className === 'string') {
91
+ className.split(/\s+/).forEach(cl => classList?.add(cl));
92
+ }
93
+ }, [className, preClassName]);
94
+
95
+ useEffect(() => {
96
+ if (joditRef.current?.workplace) {
97
+ joditRef.current.workplace.tabIndex = tabIndex || -1;
98
+ }
99
+ }, [tabIndex]);
100
+
101
+ useEffect(() => {
102
+ const jodit = joditRef.current;
103
+ if (!jodit?.events || !(onBlur || onChange)) {
104
+ return;
105
+ }
106
+
107
+ const onBlurHandler = (event: MouseEvent) =>
108
+ onBlur && onBlur(joditRef?.current?.value ?? '', event);
109
+
110
+ const onChangeHandler = (value: string) =>
111
+ onChange && onChange(value);
112
+
113
+ // adding event handlers
114
+ jodit.events
115
+ .on('blur', onBlurHandler)
116
+ .on('change', onChangeHandler);
117
+
118
+ return () => {
119
+ // Remove event handlers
120
+ jodit.events
121
+ ?.off('blur', onBlurHandler)
122
+ .off('change', onChangeHandler);
123
+ };
124
+ }, [onBlur, onChange]);
125
+
126
+ useEffect(() => {
127
+ const jodit = joditRef.current;
128
+
129
+ const updateValue = () => {
130
+ if (jodit && value !== undefined && jodit.value !== value) {
131
+ jodit.value = value;
132
+ }
133
+ };
134
+
135
+ if (jodit) {
136
+ if (jodit.isReady) {
137
+ updateValue();
138
+ } else {
139
+ jodit.waitForReady().then(updateValue);
140
+ }
141
+ }
142
+ }, [value]);
143
+
144
+ return (
145
+ <div className={'jodit-react-container'}>
146
+ <textarea
147
+ defaultValue={value}
148
+ name={name}
149
+ id={id}
150
+ ref={textAreaRef}
151
+ />
152
+ </div>
153
+ );
154
+ }
155
+ );
156
+
157
+ JoditEditor.displayName = 'JoditEditor';
158
+
159
+ export default JoditEditor;
@@ -0,0 +1,7 @@
1
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
2
+ // @ts-ignore - Jodit Editor (https://xdsoft.net/jodit/)
3
+ import { Jodit as JoditES5 } from 'jodit/es5/jodit.fat.min';
4
+ import type { Jodit as JoditConstructorType } from 'jodit';
5
+ import 'jodit/es5/jodit.min.css';
6
+
7
+ export const Jodit: typeof JoditConstructorType = JoditES5;
package/tsconfig.json ADDED
@@ -0,0 +1,18 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "es2015",
4
+ "module": "esnext",
5
+ "outDir": "./build",
6
+ "declaration": true,
7
+ "declarationDir": "./build/types",
8
+ "strict": true,
9
+ "skipLibCheck": true,
10
+ "esModuleInterop": true,
11
+ "allowSyntheticDefaultImports": true,
12
+ "forceConsistentCasingInFileNames": true,
13
+ "verbatimModuleSyntax": true,
14
+ "jsx": "react",
15
+ "moduleResolution": "node",
16
+ "noImplicitAny": true
17
+ }
18
+ }
@@ -1,22 +1,22 @@
1
- const webpack = require('webpack');
2
- const path = require('path');
1
+ import path from 'path';
2
+ import webpack from 'webpack';
3
+ import process from 'process';
3
4
 
4
- module.exports = (env, argv, dir = process.cwd()) => {
5
+ export default (env: unknown, argv: { mode?: string }, dir = process.cwd()) => {
5
6
  const debug = !argv || !argv.mode || !argv.mode.match(/production/);
6
7
 
7
8
  return {
8
9
  context: dir,
9
10
 
10
- entry: './src/index.js',
11
+ entry: './src/index.ts',
11
12
  devtool: debug ? 'inline-source-map' : false,
12
13
 
13
14
  module: {
14
15
  rules: [
15
16
  {
16
- test: /\.js$/,
17
+ test: /\.(js|jsx|ts|tsx)$/,
17
18
  use: {
18
- loader: 'babel-loader',
19
- options: require(path.join(dir, './babel.config.json'))
19
+ loader: 'swc-loader'
20
20
  }
21
21
  },
22
22
  {
@@ -27,6 +27,7 @@ module.exports = (env, argv, dir = process.cwd()) => {
27
27
  },
28
28
 
29
29
  resolve: {
30
+ extensions: ['.ts', '.tsx', '.js', '.jsx'],
30
31
  alias: {
31
32
  'jodit-react': path.join(__dirname, './src')
32
33
  }
package/babel.config.json DELETED
@@ -1,12 +0,0 @@
1
- {
2
- "presets": [
3
- "@babel/preset-env",
4
- "@babel/preset-react"
5
- ],
6
- "plugins": [
7
- "transform-class-properties"
8
- ],
9
- "ignore": [
10
- "node_modules"
11
- ]
12
- }
package/examples/.babelrc DELETED
@@ -1,12 +0,0 @@
1
- {
2
- "presets": [
3
- "@babel/preset-env",
4
- "@babel/preset-react"
5
- ],
6
- "plugins": [
7
- "transform-class-properties"
8
- ],
9
- "ignore": [
10
- "node_modules"
11
- ]
12
- }
@@ -1,45 +0,0 @@
1
- var path = require('path');
2
-
3
- module.exports = {
4
- entry: './app.js',
5
- devtool: 'eval',
6
- module: {
7
- rules: [
8
- {
9
- test: /\.js$/,
10
- use: [
11
- {
12
- loader: 'babel-loader',
13
- options: {
14
- presets: [
15
- '@babel/preset-env',
16
- '@babel/preset-react'
17
- ]
18
- }
19
- }
20
- ]
21
- },
22
- {
23
- test: /\.css$/,
24
- use: ['style-loader', 'css-loader']
25
- }
26
- ]
27
- },
28
-
29
- output: {
30
- path: path.join(__dirname, '/build/'),
31
- filename: 'app.js'
32
- },
33
-
34
- devServer: {
35
- static: './',
36
- open: true,
37
- allowedHosts: 'all',
38
- client: {
39
- progress: true,
40
- overlay: true
41
- },
42
- port: 4000,
43
- hot: true
44
- }
45
- };