diff --git a/README.md b/README.md index b291d3b..e58ba44 100644 --- a/README.md +++ b/README.md @@ -1,23 +1,42 @@ # react-cli +node 15+ react-typescript-router-mobx-redux-hook +```html +main 分支为 路由版本 +redux 分支为 redux 结构 +mobx 分支为 mobx 结构代码 补充中... +rematch 分支为reamatch 结构代码 补充中... +整体在维护中 +``` +> 切换到分支 redux 可以看到完整redux 搭建的代码 -#### step1 -```cmd -eg: -mv react-cli/tpl react-cli/projectName -eg +## step1 +```cmd +把demo 文件改成自己需要的项目名,然后移动。后期会维护一步创建. +``` +##### step1-1 +```cmd +进入文件夹: cd react-cli +``` +##### step1-2 +```cmd 改名 mv tpl candy-react -移动 +``` +##### step1-3 +```cmd +移动到上一级 mv tpl ../ +``` +##### step1-4 +```cmd +退出当前文件夹 cd .. rm -rf react-cli ``` - -#### step2 - +## step2 ```cmd node -v v14.15.3 @@ -25,7 +44,8 @@ yarn config get registry yarn config set registry http://registry.npm.taobao.org/ ``` -#### step3 +## step3 ```cmd - +yarn +yarn start ``` diff --git a/read/md/redux.md b/read/md/redux.md new file mode 100644 index 0000000..ad5e920 --- /dev/null +++ b/read/md/redux.md @@ -0,0 +1,8 @@ +yarn add @types/react-redux react-redux redux redux-thunk + +目录创建 未完成 +1、servers +2、epics +3、helpers +4、untils +5、enums diff --git a/tpl/package.json b/tpl/package.json index 527ee09..d7a4a12 100644 --- a/tpl/package.json +++ b/tpl/package.json @@ -15,6 +15,7 @@ "@types/node": "^12.0.0", "@types/react": "^17.0.0", "@types/react-dom": "^17.0.0", + "@types/react-redux": "^7.1.20", "@types/react-router-dom": "^5.3.2", "@typescript-eslint/eslint-plugin": "^4.5.0", "@typescript-eslint/parser": "^4.5.0", @@ -65,8 +66,11 @@ "react-app-polyfill": "^2.0.0", "react-dev-utils": "^11.0.3", "react-dom": "^17.0.2", + "react-redux": "^7.2.6", "react-refresh": "^0.8.3", "react-router-dom": "^5.3.0", + "redux": "^4.1.2", + "redux-thunk": "^2.4.0", "resolve": "1.18.1", "resolve-url-loader": "^3.1.2", "sass-loader": "^10.0.5", @@ -169,5 +173,7 @@ "devDependencies": { "@loadable/babel-plugin": "^5.13.2", "@loadable/webpack-plugin": "^5.15.1" - } + }, + "author": "llqfront@aliyun.com", + "license": "ISC" } diff --git a/tpl/src/App.tsx b/tpl/src/App.tsx index 54101fe..0319de4 100644 --- a/tpl/src/App.tsx +++ b/tpl/src/App.tsx @@ -1,12 +1,26 @@ import React from 'react'; import { BrowserRouter, HashRouter} from 'react-router-dom'; +import {Provider} from 'react-redux'; -import Router from '@/router/'; +import RootStore from '@/stores'; +import Router from '@/router'; +const unsubscribe = RootStore().subscribe(() =>{ + // console.log(Store.getState()) + localStorage.setItem("LJMRoot", JSON.stringify(RootStore().getState())); +}) +// +function newJson(str){ + var json = (new Function("return " + str))(); + return json; +} +let prevStore = newJson(localStorage.getItem("LJMRoot"))||{}; const App = () => ( - + + + ) export default App; diff --git a/tpl/src/actions/add.ts b/tpl/src/actions/add.ts new file mode 100644 index 0000000..8dad92b --- /dev/null +++ b/tpl/src/actions/add.ts @@ -0,0 +1,3 @@ +const NAMESPACE = 'ADDPAGE/'; +export const FETCH_USER = `${NAMESPACE}/FETCH_USER`; +export const FETCH_USER_FULFILLED = `${NAMESPACE}/FETCH_USER_FULFILLED`; diff --git a/tpl/src/actions/ajaxpage.ts b/tpl/src/actions/ajaxpage.ts new file mode 100644 index 0000000..244df2d --- /dev/null +++ b/tpl/src/actions/ajaxpage.ts @@ -0,0 +1,3 @@ +const NAMESPACE = 'ADDPAGE/'; +export const GETPDD = `${NAMESPACE}/GETPDD`; +export const PDDDATA = `${NAMESPACE}/PDDDATA`; diff --git a/tpl/src/actions/index.ts b/tpl/src/actions/index.ts new file mode 100644 index 0000000..a0af013 --- /dev/null +++ b/tpl/src/actions/index.ts @@ -0,0 +1,9 @@ +import * as actionAdd from './add'; +import * as actionOld from './old'; +import * as actionAjaxPage from './ajaxpage'; + +export { + actionAdd, + actionOld, + actionAjaxPage +} diff --git a/tpl/src/actions/old.ts b/tpl/src/actions/old.ts new file mode 100644 index 0000000..9b76614 --- /dev/null +++ b/tpl/src/actions/old.ts @@ -0,0 +1,4 @@ +const NAMESPACE = 'OLDPAGE/'; +export const ADD_TODO = `${NAMESPACE}/ADD_TODO`; +export const DEL_TODO = `${NAMESPACE}/DEL_TODO`; +export const EDIT_TODO = `${NAMESPACE}/EDIT_TODO`; diff --git a/tpl/src/doc/readme.md b/tpl/src/doc/readme.md new file mode 100644 index 0000000..0b78330 --- /dev/null +++ b/tpl/src/doc/readme.md @@ -0,0 +1,11 @@ +目录介绍: +- components: +- doc: +- enums: +- epics: +- images: +- router: +- services: +- stores: +- utils: +- views: diff --git a/tpl/src/enums/index.ts b/tpl/src/enums/index.ts new file mode 100644 index 0000000..e69de29 diff --git a/tpl/src/epics/index.ts b/tpl/src/epics/index.ts new file mode 100644 index 0000000..e69de29 diff --git a/tpl/src/reducers/addPageReducer.ts b/tpl/src/reducers/addPageReducer.ts new file mode 100644 index 0000000..1c0d316 --- /dev/null +++ b/tpl/src/reducers/addPageReducer.ts @@ -0,0 +1,14 @@ +import { actionAdd } from '@/actions'; + + +export default (state = {},action)=>{ + switch (action.type) { + case actionAdd.FETCH_USER_FULFILLED: + return { + ...state, + success:action.payload + }; + default: + return state; + } +} diff --git a/tpl/src/reducers/ajaxPageReducer.ts b/tpl/src/reducers/ajaxPageReducer.ts new file mode 100644 index 0000000..b3ea917 --- /dev/null +++ b/tpl/src/reducers/ajaxPageReducer.ts @@ -0,0 +1,14 @@ +import { actionAjaxPage } from '@/actions'; + +export default (state = {}, action)=>{ + switch (action.type) { + case actionAjaxPage.PDDDATA: + return { + ...state, + action + }; + default: + return state; + } + +} diff --git a/tpl/src/reducers/index.ts b/tpl/src/reducers/index.ts new file mode 100644 index 0000000..798d690 --- /dev/null +++ b/tpl/src/reducers/index.ts @@ -0,0 +1,11 @@ +import { combineReducers } from 'redux'; +import addReducer from './addPageReducer'; +import oldReducer from './oldPageReducer'; +import ajaxReducer from './ajaxPageReducer'; + +const rootReducer = combineReducers({ + addReducer, + oldReducer, + ajaxReducer +}) +export default rootReducer; diff --git a/tpl/src/reducers/oldPageReducer.ts b/tpl/src/reducers/oldPageReducer.ts new file mode 100644 index 0000000..6670a4c --- /dev/null +++ b/tpl/src/reducers/oldPageReducer.ts @@ -0,0 +1,17 @@ +import { actionOld } from '@/actions'; + +export default (state=[],action)=>{ + switch (action.type) { + case actionOld.ADD_TODO: + return [ + { + type:action.type, + text:action.type + }, + ...state + ] + default: + return state; + } + +} diff --git a/tpl/src/router/index.tsx b/tpl/src/router/index.tsx index 6026b6c..c77d367 100644 --- a/tpl/src/router/index.tsx +++ b/tpl/src/router/index.tsx @@ -2,7 +2,8 @@ import React , { Component,Suspense} from 'react'; import { lazy } from '@loadable/component'; import {NavLink,Redirect,Switch,Route} from 'react-router-dom'; const Home = lazy(() => import('@/views/Home')); -const Test = lazy(() => import('@/views/Test')); +const Action = lazy(() => import('@/views/Action/index.tsx')); +const AjaxPage = lazy(() => import('@/views/AjaxPage/index.tsx')); class Router extends Component { render(){ return( @@ -10,7 +11,8 @@ class Router extends Component { Loading...}> - + + diff --git a/tpl/src/services/index.ts b/tpl/src/services/index.ts new file mode 100644 index 0000000..89a3944 --- /dev/null +++ b/tpl/src/services/index.ts @@ -0,0 +1,5 @@ +import * as pddApi from './pddService.ts'; + +export { + pddApi, +} diff --git a/tpl/src/services/pddService.ts b/tpl/src/services/pddService.ts new file mode 100644 index 0000000..94d8dea --- /dev/null +++ b/tpl/src/services/pddService.ts @@ -0,0 +1,5 @@ +import { ajaxs } from '@/utils'; + +export const pddFnApi = (params)=>{ + return ajaxs.getApi2('/home/mediareports',params) +} diff --git a/tpl/src/setupProxy.js b/tpl/src/setupProxy.js index d1a5f90..2347dd7 100644 --- a/tpl/src/setupProxy.js +++ b/tpl/src/setupProxy.js @@ -2,13 +2,7 @@ const { createProxyMiddleware } = require('http-proxy-middleware'); module.exports = function(app) { app.use( '/home',createProxyMiddleware({ - target: 'https://####.com/', - changeOrigin: true, - }) - ); - app.use( - '/api',createProxyMiddleware({ - target: 'http://####.cn/', + target: 'https://home-api.pinduoduo.com/', changeOrigin: true, }) ); diff --git a/tpl/src/stores/index.ts b/tpl/src/stores/index.ts new file mode 100644 index 0000000..656ee3f --- /dev/null +++ b/tpl/src/stores/index.ts @@ -0,0 +1,21 @@ +import {createStore, applyMiddleware} from 'redux'; +import thunk from 'redux-thunk'; + +import rootReducer from '@/reducers'; + +const configureStore = (prevStore)=> { + const store = createStore( + rootReducer, + prevStore, + applyMiddleware(thunk) + ); + return store; +} +let store = configureStore(); + +const RootStore = (prevStore?) =>{ + store = configureStore(prevStore); + return store; +} + +export default RootStore; diff --git a/tpl/src/utils/ajax.ts b/tpl/src/utils/ajax.ts new file mode 100644 index 0000000..323b0e3 --- /dev/null +++ b/tpl/src/utils/ajax.ts @@ -0,0 +1,86 @@ +import axios from 'axios'; +import qs from 'qs'; +export const getApi = async(ajaxCfg)=>{ + let data = await axios.get( + ajaxCfg.url,{ + params:ajaxCfg.cfg + }, + { + headers: ajaxCfg.headers, + }) + return data; +} +export const getApi2 = async(url,cfg,headers)=>{ + let data = await axios.get( + url,{ + params:cfg + }, + { + headers: headers, + }) + return data; +} +// async postApi(url,cfg,headers){ +// let fd = new FormData(); +// for(let key in cfg){ +// fd.append(key, cfg[key]); +// } +// let data = await axios.post(url,fd, +// { +// headers: headers +// }) +// return data; +// }, +// async putApi(url,cfg,headers){ +// let data = await axios.put(url,qs.stringify(cfg),{ +// headers: { +// 'Content-Type':'application/x-www-form-urlencoded', +// } +// }) +// return data; +// }, +// async _postApi(url,cfg,headers){ +// let data = await axios.post(url,cfg, +// { +// headers: headers +// }) +// return data; +// }, +// async __postApi(url,cfg,headers){ +// let data = await axios.post(url,qs.stringify(cfg),{ +// headers: { +// 'Content-Type':'application/x-www-form-urlencoded', +// } +// }) +// return data; +// }, +// async delApi(url,cfg,headers){ +// let data = await axios.delete(url,{params:cfg},{ +// headers: headers +// }) +// return data; +// }, +// async requestApi(cfg,headers,file){ +// let fd = new FormData(); +// fd.append('param', JSON.stringify(cfg)); +// if(file){ +// // 上传证明 +// if(file.length){ +// for(let i=0,len=file.length;i( + type:string, + payload?:T, + handleCallback?:(res:ResponseData)=>void, +):T =>{ + return { + type, + payload:payload || {}, + handleCallback + } +} +// export function createAction( +// type: string, +// payload?: T, +// handleCallback?: (res: ResponseData) => void, +// ){ +// return { +// type, +// payload:payload || {}, +// handleCallback, +// }; +// } diff --git a/tpl/src/utils/index.ts b/tpl/src/utils/index.ts new file mode 100644 index 0000000..60387bf --- /dev/null +++ b/tpl/src/utils/index.ts @@ -0,0 +1,5 @@ +import * as helpers from './helpers'; +import * as ajaxs from './ajax.ts'; + + +export { helpers,ajaxs }; diff --git a/tpl/src/utils/types.ts b/tpl/src/utils/types.ts new file mode 100644 index 0000000..97e550c --- /dev/null +++ b/tpl/src/utils/types.ts @@ -0,0 +1,6 @@ +export interface ResponseData{ + code?: number; + status_code?: number; + data?: any; + msg?: string +} diff --git a/tpl/src/views/Action/index.tsx b/tpl/src/views/Action/index.tsx new file mode 100644 index 0000000..2d8a597 --- /dev/null +++ b/tpl/src/views/Action/index.tsx @@ -0,0 +1,39 @@ +import React , { Component } from 'react'; +import { connect } from 'react-redux'; + +import { helpers } from '@/utils'; +import { actionOld } from '@/actions'; + +class View extends Component { + onAddFn = () => { + const {dispatch} = this.props; + dispatch( + helpers.createAction( + actionOld.ADD_TODO + ) + ) + } + render(){ + return ( + + action页面
+ +
+ ) + } +} +const mapStateToProps = (state) => { + console.log(state) + return { + addList:state + } +} +// const mapDispatchToProps = (dispatch, ownProps) => { +// return { +// onAddFn:()=>dispatch(actionsAdd.add()) +// } +// }; +export default connect(mapStateToProps,null)(View); diff --git a/tpl/src/views/AjaxPage/index.tsx b/tpl/src/views/AjaxPage/index.tsx new file mode 100644 index 0000000..1477101 --- /dev/null +++ b/tpl/src/views/AjaxPage/index.tsx @@ -0,0 +1,96 @@ +import React, { Component } from 'react'; +import {connect} from 'react-redux'; +import { helpers } from '@/utils'; +import { actionAjaxPage } from '@/actions'; +import { pddApi } from '@/services'; + + +class View extends Component { + constructor(props){ + super(props); + this.state = { + } + } + // handleCallback(){ + // const {dispatch} = this.props; + // const ajaxCfg = { + // url:'/home/mediareports', + // cfg:{ + // page_number:1, + // page_size:10, + // }, + // headers:{} + // } + // Unit.getApi(ajaxCfg).then((res)=>{ + // dispatch( + // helpers.createAction(actionAjaxPage.PDDDATA,res.data) + // ) + // }) + // } + // pageGetPdd(){ + // const {dispatch} = this.props; + // dispatch( + // helpers.createAction(actionAjaxPage.GETPDD,{},this.handleCallback()) + // ) + // } + handleCallback2(){ + const {dispatch} = this.props; + const params = { + page_number:1, + page_size:10, + } + // Unit.getApi(ajaxCfg).then((res)=>{ + // dispatch( + // helpers.createAction(actionAjaxPage.PDDDATA,res.data) + // ) + // }) + // 把url 提到services中 + pddApi.pddFnApi(params).then((res)=>{ + dispatch( + helpers.createAction(actionAjaxPage.PDDDATA,res.data) + // helpers.createAction(actionAjaxPage.PDDDATA,res.data,this.handleCallback()) + ) + }) + } + newApi(){ + const {dispatch} = this.props; + dispatch( + helpers.createAction(actionAjaxPage.GETPDD,{},this.handleCallback2()) + ) + } + componentDidMount(){ + // this.pageGetPdd() + this.newApi(); + } + lists(data){ + return data.map((val,index)=>{ + return( +
  • + {val.id} +
  • + ) + }) + } + render(){ + // const {pddData} = this.props; + return( +
    + {/* + pddData.length!==0 + ? +
      {this.lists(pddData.data.data)}
    + : + '' + */} + asdfasdf +
    + ) + } +} +const mapStateToProps = (state)=>{ + console.log(state) + return { + // pddData:state.pddReducer + } +} +export default connect(mapStateToProps,null)(View); diff --git a/tpl/src/views/Test/index.jsx b/tpl/src/views/Test/index.jsx deleted file mode 100644 index a5738c5..0000000 --- a/tpl/src/views/Test/index.jsx +++ /dev/null @@ -1,15 +0,0 @@ -import React, { Component } from 'react'; -class View extends Component { - render(){ - const obj = { - a:'1' - } - let index = 1; - return( -
    - test -
    - ) - } -} -export default View; diff --git a/tpl/yarn.lock b/tpl/yarn.lock index 8324168..727f223 100644 --- a/tpl/yarn.lock +++ b/tpl/yarn.lock @@ -1172,6 +1172,13 @@ dependencies: regenerator-runtime "^0.13.4" +"@babel/runtime@^7.15.4": + version "7.16.3" + resolved "https://registry.npmmirror.com/@babel/runtime/download/@babel/runtime-7.16.3.tgz?cache=0&sync_timestamp=1636494819594&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2F%40babel%2Fruntime%2Fdownload%2F%40babel%2Fruntime-7.16.3.tgz#b86f0db02a04187a3c17caa77de69840165d42d5" + integrity sha512-WBwekcqacdY2e9AF/Q7WLFUWmdJGJTkbjqTjoMDgXkVZ3ZRUvOPsLb5KdwISoQVsbP+DQzVZW4Zhci0DvpbNTQ== + dependencies: + regenerator-runtime "^0.13.4" + "@babel/template@^7.10.4", "@babel/template@^7.16.0", "@babel/template@^7.3.3": version "7.16.0" resolved "https://registry.npmmirror.com/@babel/template/download/@babel/template-7.16.0.tgz#d16a35ebf4cd74e202083356fab21dd89363ddd6" @@ -1848,6 +1855,14 @@ resolved "https://registry.nlark.com/@types/history/download/@types/history-4.7.9.tgz#1cfb6d60ef3822c589f18e70f8b12f9a28ce8724" integrity sha1-HPttYO84IsWJ8Y5w+LEvmijOhyQ= +"@types/hoist-non-react-statics@^3.3.0": + version "3.3.1" + resolved "https://registry.nlark.com/@types/hoist-non-react-statics/download/@types/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f" + integrity sha1-ESSq/lEYy1kZd66xzqrtEHDrA58= + dependencies: + "@types/react" "*" + hoist-non-react-statics "^3.3.0" + "@types/html-minifier-terser@^5.0.0": version "5.1.2" resolved "https://registry.nlark.com/@types/html-minifier-terser/download/@types/html-minifier-terser-5.1.2.tgz?cache=0&sync_timestamp=1631043806613&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40types%2Fhtml-minifier-terser%2Fdownload%2F%40types%2Fhtml-minifier-terser-5.1.2.tgz#693b316ad323ea97eed6b38ed1a3cc02b1672b57" @@ -1952,6 +1967,16 @@ dependencies: "@types/react" "*" +"@types/react-redux@^7.1.20": + version "7.1.20" + resolved "https://registry.npmmirror.com/@types/react-redux/download/@types/react-redux-7.1.20.tgz?cache=0&sync_timestamp=1634764733589&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2F%40types%2Freact-redux%2Fdownload%2F%40types%2Freact-redux-7.1.20.tgz#42f0e61ababb621e12c66c96dda94c58423bd7df" + integrity sha1-QvDmGrq7Yh4SxmyW3alMWEI7198= + dependencies: + "@types/hoist-non-react-statics" "^3.3.0" + "@types/react" "*" + hoist-non-react-statics "^3.3.0" + redux "^4.0.0" + "@types/react-router-dom@^5.3.2": version "5.3.2" resolved "https://registry.npmmirror.com/@types/react-router-dom/download/@types/react-router-dom-5.3.2.tgz#ebd8e145cf056db5c66eb1dac63c72f52e8542ee" @@ -5636,7 +5661,7 @@ hmac-drbg@^1.0.1: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.1" -hoist-non-react-statics@^3.1.0, hoist-non-react-statics@^3.3.1: +hoist-non-react-statics@^3.1.0, hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.1, hoist-non-react-statics@^3.3.2: version "3.3.2" resolved "https://registry.nlark.com/hoist-non-react-statics/download/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" integrity sha1-7OCsr3HWLClpwuxZ/v9CpLGoW0U= @@ -9342,11 +9367,23 @@ react-is@^16.12.0, react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1: resolved "https://registry.npmmirror.com/react-is/download/react-is-16.13.1.tgz?cache=0&sync_timestamp=1636043968803&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Freact-is%2Fdownload%2Freact-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha1-eJcppNw23imZ3BVt1sHZwYzqVqQ= -react-is@^17.0.1: +react-is@^17.0.1, react-is@^17.0.2: version "17.0.2" resolved "https://registry.npmmirror.com/react-is/download/react-is-17.0.2.tgz?cache=0&sync_timestamp=1636043968803&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Freact-is%2Fdownload%2Freact-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" integrity sha1-5pHUqOnHiTZWVVOas3J2Kw77VPA= +react-redux@^7.2.6: + version "7.2.6" + resolved "https://registry.npmmirror.com/react-redux/download/react-redux-7.2.6.tgz#49633a24fe552b5f9caf58feb8a138936ddfe9aa" + integrity sha1-SWM6JP5VK1+cr1j+uKE4k23f6ao= + dependencies: + "@babel/runtime" "^7.15.4" + "@types/react-redux" "^7.1.20" + hoist-non-react-statics "^3.3.2" + loose-envify "^1.4.0" + prop-types "^15.7.2" + react-is "^17.0.2" + react-refresh@^0.8.3: version "0.8.3" resolved "https://registry.npmmirror.com/react-refresh/download/react-refresh-0.8.3.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Freact-refresh%2Fdownload%2Freact-refresh-0.8.3.tgz#721d4657672d400c5e3c75d063c4a85fb2d5d68f" @@ -9470,6 +9507,18 @@ redent@^3.0.0: indent-string "^4.0.0" strip-indent "^3.0.0" +redux-thunk@^2.4.0: + version "2.4.0" + resolved "https://registry.npmmirror.com/redux-thunk/download/redux-thunk-2.4.0.tgz?cache=0&sync_timestamp=1635214108732&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fredux-thunk%2Fdownload%2Fredux-thunk-2.4.0.tgz#ac89e1d6b9bdb9ee49ce69a69071be41bbd82d67" + integrity sha1-rInh1rm9ue5JzmmmkHG+QbvYLWc= + +redux@^4.0.0, redux@^4.1.2: + version "4.1.2" + resolved "https://registry.npmmirror.com/redux/download/redux-4.1.2.tgz#140f35426d99bb4729af760afcf79eaaac407104" + integrity sha1-FA81Qm2Zu0cpr3YK/PeeqqxAcQQ= + dependencies: + "@babel/runtime" "^7.9.2" + regenerate-unicode-properties@^9.0.0: version "9.0.0" resolved "https://registry.nlark.com/regenerate-unicode-properties/download/regenerate-unicode-properties-9.0.0.tgz?cache=0&sync_timestamp=1631617208210&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fregenerate-unicode-properties%2Fdownload%2Fregenerate-unicode-properties-9.0.0.tgz#54d09c7115e1f53dc2314a974b32c1c344efe326"