├── .github ├── FUNDING.yml └── workflows │ └── ci.yml ├── .gitignore ├── .gitpod.yml ├── .husky └── pre-commit ├── .kktrc.ts ├── .prettierignore ├── .prettierrc ├── LICENSE ├── README.md ├── package.json ├── public ├── favicon.ico └── index.html ├── renovate.json ├── src ├── assets │ ├── logo-dark.svg │ └── logo-light.svg ├── components │ ├── Loading.tsx │ ├── Search.module.less │ └── Search.tsx ├── hook │ └── usePath.ts ├── index.css ├── index.tsx ├── models │ ├── global.ts │ └── index.tsx ├── pages │ ├── Home │ │ ├── index.module.less │ │ └── index.tsx │ └── Preview │ │ ├── Content.module.less │ │ ├── Content.tsx │ │ ├── DirectoryTrees.module.less │ │ ├── DirectoryTrees.tsx │ │ ├── github.svg │ │ ├── home.svg │ │ ├── icons │ │ ├── css3.svg │ │ ├── html5.svg │ │ ├── javascript.map.svg │ │ ├── javascript.svg │ │ ├── json.svg │ │ ├── license.svg │ │ ├── markdown.svg │ │ ├── react.svg │ │ └── typescript.svg │ │ ├── index.module.less │ │ ├── index.tsx │ │ └── npm.svg ├── react-app-env.d.ts ├── routers.ts ├── servers │ └── unpkg.ts └── utils │ ├── request.ts │ └── utils.ts └── tsconfig.json /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | ko_fi: jaywcjlove 2 | buy_me_a_coffee: jaywcjlove 3 | custom: ["https://www.paypal.me/kennyiseeyou", "https://jaywcjlove.github.io/#/sponsor"] 4 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: 3 | push: 4 | branches: 5 | - master 6 | jobs: 7 | build-deploy: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v4 11 | - uses: actions/setup-node@v4 12 | with: 13 | node-version: 20 14 | registry-url: 'https://registry.npmjs.org' 15 | 16 | - run: npm install 17 | - run: npm run build 18 | 19 | - name: Generate Contributors Images 20 | uses: jaywcjlove/github-action-contributors@main 21 | with: 22 | filter-author: (renovate\[bot\]|renovate-bot|dependabot\[bot\]) 23 | output: build/CONTRIBUTORS.svg 24 | avatarSize: 42 25 | 26 | - name: Deploy 27 | uses: peaceiris/actions-gh-pages@v3 28 | with: 29 | github_token: ${{ secrets.GITHUB_TOKEN }} 30 | publish_dir: ./build 31 | 32 | - name: Is a tag created auto? 33 | id: create_tag 34 | uses: jaywcjlove/create-tag-action@main 35 | with: 36 | token: ${{ secrets.GITHUB_TOKEN }} 37 | package-path: ./package.json 38 | 39 | - name: Generate Changelog 40 | id: changelog 41 | uses: jaywcjlove/changelog-generator@main 42 | with: 43 | token: ${{ secrets.GITHUB_TOKEN }} 44 | head-ref: ${{steps.create_tag.outputs.version}} 45 | filter-author: (renovate-bot|Renovate Bot) 46 | filter: '[R|r]elease[d]\s+[v|V]\d(\.\d+){0,2}' 47 | 48 | - name: Create Release 49 | uses: ncipollo/release-action@v1 50 | if: steps.create_tag.outputs.successful 51 | with: 52 | allowUpdates: true 53 | token: ${{ secrets.GITHUB_TOKEN }} 54 | name: ${{ steps.create_tag.outputs.version }} 55 | tag: ${{ steps.create_tag.outputs.version }} 56 | body: | 57 | [![Buy me a coffee](https://img.shields.io/badge/Buy%20me%20a%20coffee-048754?logo=buymeacoffee)](https://jaywcjlove.github.io/#/sponsor) 58 | 59 | ${{ steps.changelog.outputs.compareurl }} 60 | 61 | ${{ steps.changelog.outputs.changelog }} -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | npm-debug.log* 3 | package-lock.json 4 | # package-lock.json 5 | # dependencies 6 | node_modules 7 | .pnp 8 | .pnp.js 9 | 10 | # testing 11 | /coverage 12 | 13 | # production 14 | /build 15 | 16 | # misc 17 | .DS_Store 18 | .env.local 19 | .env.development.local 20 | .env.test.local 21 | .env.production.local 22 | 23 | .eslintcache 24 | .cache 25 | .rdoc-dist 26 | .vscode 27 | 28 | *.bak 29 | *.tem 30 | *.temp 31 | #.swp 32 | *.*~ 33 | ~*.* 34 | -------------------------------------------------------------------------------- /.gitpod.yml: -------------------------------------------------------------------------------- 1 | ports: 2 | - port: 3000 3 | onOpen: open-preview 4 | tasks: 5 | - init: npm install 6 | command: npm run start -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | npx lint-staged -------------------------------------------------------------------------------- /.kktrc.ts: -------------------------------------------------------------------------------- 1 | import webpack, { Configuration } from 'webpack'; 2 | import lessModules from '@kkt/less-modules'; 3 | import { LoaderConfOptions } from 'kkt'; 4 | import pkg from './package.json'; 5 | 6 | export default (conf: Configuration, env: 'production' | 'development', options: LoaderConfOptions) => { 7 | conf = lessModules(conf, env, options); 8 | 9 | // Get the project version. 10 | conf.plugins!.push( 11 | new webpack.DefinePlugin({ 12 | VERSION: JSON.stringify(pkg.version), 13 | }), 14 | ); 15 | 16 | /** https://github.com/kktjs/kkt/issues/446 */ 17 | conf.ignoreWarnings = [ { module: /node_modules[\\/]parse5[\\/]/ } ]; 18 | 19 | if (env === 'production') { 20 | conf.output = { ...conf.output, publicPath: './' }; 21 | conf.optimization = { 22 | ...conf.optimization, 23 | splitChunks: { 24 | cacheGroups: { 25 | reactvendor: { 26 | test: /[\\/]node_modules[\\/](react|react-dom)[\\/]/, 27 | name: 'react-vendor', 28 | chunks: 'all', 29 | }, 30 | katex: { 31 | test: /[\\/]node_modules[\\/](katex)[\\/]/, 32 | name: 'katex-vendor', 33 | chunks: 'all', 34 | }, 35 | prismjs: { 36 | test: /[\\/]node_modules[\\/](refractor)[\\/]/, 37 | name: 'refractor-vendor', 38 | chunks: 'all', 39 | }, 40 | codemirror: { 41 | test: /[\\/]node_modules[\\/](@codemirror)[\\/]/, 42 | name: 'codemirror-vendor', 43 | chunks: 'all', 44 | }, 45 | uiw: { 46 | test: /[\\/]node_modules[\\/](@uiw)[\\/]/, 47 | name: 'uiw-vendor', 48 | chunks: 'all', 49 | }, 50 | parse5: { 51 | test: /[\\/]node_modules[\\/](parse5)[\\/]/, 52 | name: 'parse5-vendor', 53 | chunks: 'all', 54 | }, 55 | }, 56 | }, 57 | }; 58 | } 59 | return conf; 60 | }; 61 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | **/*.md 2 | **/*.svg 3 | **/*.ejs 4 | **/*.yml 5 | package.json 6 | node_modules 7 | dist 8 | build 9 | lib 10 | test 11 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "trailingComma": "all", 4 | "printWidth": 120, 5 | "overrides": [ 6 | { 7 | "files": ".prettierrc", 8 | "options": { "parser": "json" } 9 | } 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 uiw 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | NPM UNPKG 2 | === 3 | 4 | [![Buy me a coffee](https://img.shields.io/badge/Buy%20me%20a%20coffee-048754?logo=buymeacoffee)](https://jaywcjlove.github.io/#/sponsor) 5 | [![CI Build & Deploy](https://github.com/uiwjs/npm-unpkg/actions/workflows/ci.yml/badge.svg)](https://github.com/uiwjs/npm-unpkg/actions/workflows/ci.yml) 6 | [![Open in Gitpod](https://shields.io/badge/Open%20in-Gitpod-green?logo=Gitpod)](https://gitpod.io/#https://github.com/uiwjs/npm-unpkg) 7 | 8 | A web application to view npm package files, Based on [`unpkg`](https://unpkg.com/). 9 | 10 | [![NPM UNPKG image](https://user-images.githubusercontent.com/1680273/133931122-784be24e-e56a-46b5-834f-50e62726fb99.png)](https://uiwjs.github.io/npm-unpkg) 11 | 12 | ## Quick Start 13 | 14 | **development** 15 | 16 | Runs the project in development mode. 17 | 18 | ```bash 19 | npm run start 20 | ``` 21 | 22 | **production** 23 | 24 | Builds the app for production to the build folder. 25 | 26 | ```bash 27 | npm run build 28 | ``` 29 | 30 | The build is minified and the filenames include the hashes. 31 | Your app is ready to be deployed! 32 | 33 | ## Contributors 34 | 35 | As always, thanks to our amazing contributors! 36 | 37 | 38 | 39 | 40 | 41 | Made with [github-action-contributors](https://github.com/jaywcjlove/github-action-contributors). 42 | 43 | ## License 44 | 45 | [MIT © Kenny Wong](https://github.com/kktjs/kkt/blob/master/LICENSE) 46 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "npm-unpkg", 3 | "version": "2.1.0", 4 | "description": "A web application to view npm package files, Based on unpkg.", 5 | "funding": "https://jaywcjlove.github.io/#/sponsor", 6 | "private": true, 7 | "scripts": { 8 | "prepare": "husky install", 9 | "start": "kkt start", 10 | "build": "kkt build", 11 | "prettier": "prettier --write \"**/*.{js,jsx,tsx,ts,less,md,json}\"" 12 | }, 13 | "repository": { 14 | "type": "git", 15 | "url": "https://github.com/uiwjs/npm-unpkg.git" 16 | }, 17 | "author": "", 18 | "license": "MIT", 19 | "dependencies": { 20 | "@babel/runtime": "^7.18.9", 21 | "@codemirror/lang-css": "^6.0.0", 22 | "@codemirror/lang-html": "^6.1.0", 23 | "@codemirror/lang-javascript": "^6.0.2", 24 | "@codemirror/lang-json": "^6.0.0", 25 | "@codemirror/lang-xml": "^6.0.0", 26 | "@codemirror/legacy-modes": "^6.1.0", 27 | "@rematch/core": "~2.2.0", 28 | "@rematch/loading": "~2.1.2", 29 | "@uiw/react-codemirror": "^4.11.4", 30 | "@uiw/react-github-corners": "^1.5.14", 31 | "@uiw/react-markdown-preview": "^5.0.0", 32 | "@uiw/reset.css": "^1.0.6", 33 | "@wcj/dark-mode": "^1.0.15", 34 | "axios": "^0.27.2", 35 | "react": "^18.2.0", 36 | "react-dom": "^18.2.0", 37 | "react-redux": "~8.1.0", 38 | "react-router-dom": "^6.14.0", 39 | "rehype-rewrite": "^4.0.0", 40 | "rehype-video": "^2.0.0", 41 | "uiw": "~4.21.19" 42 | }, 43 | "engines": { 44 | "node": "^16.0.0" 45 | }, 46 | "lint-staged": { 47 | "*.{js,jsx,tsx,ts,less,md,json}": "prettier --write" 48 | }, 49 | "devDependencies": { 50 | "@kkt/less-modules": "^7.2.0", 51 | "@types/react": "^18.0.15", 52 | "@types/react-dom": "^18.0.6", 53 | "@types/react-redux": "^7.1.24", 54 | "husky": "^8.0.1", 55 | "kkt": "^7.2.0", 56 | "lint-staged": "^13.0.3", 57 | "prettier": "^2.7.1" 58 | }, 59 | "eslintConfig": { 60 | "extends": [ 61 | "react-app", 62 | "react-app/jest" 63 | ] 64 | }, 65 | "browserslist": { 66 | "production": [ 67 | ">0.2%", 68 | "not dead", 69 | "not op_mini all" 70 | ], 71 | "development": [ 72 | "last 1 chrome version", 73 | "last 1 firefox version", 74 | "last 1 safari version" 75 | ] 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uiwjs/npm-unpkg/89322d9f8019e00dca099d669a078bf15a1c2c5f/public/favicon.ico -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | NPM UNPKG 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["config:base"], 3 | "packageRules": [ 4 | { 5 | "matchPackagePatterns": ["*"], 6 | "rangeStrategy": "replace" 7 | } 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /src/assets/logo-dark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/assets/logo-light.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/components/Loading.tsx: -------------------------------------------------------------------------------- 1 | export default function Loading() { 2 | return ( 3 |
13 | Loading... 14 |
15 | ); 16 | } 17 | -------------------------------------------------------------------------------- /src/components/Search.module.less: -------------------------------------------------------------------------------- 1 | .input { 2 | max-width: 420px; 3 | } 4 | 5 | .egLink { 6 | color: #669eb9; 7 | padding-top: 10px; 8 | span { 9 | margin-right: 10px; 10 | } 11 | a + a { 12 | margin-left: 10px; 13 | } 14 | a { 15 | color: #669eb9; 16 | transition: color 0.3s; 17 | &:hover { 18 | color: #78bfe0; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/components/Search.tsx: -------------------------------------------------------------------------------- 1 | import { useState, Fragment } from 'react'; 2 | import Input from '@uiw/react-input'; 3 | import Button from '@uiw/react-button'; 4 | import { useDispatch, useSelector } from 'react-redux'; 5 | import { Link, useNavigate } from 'react-router-dom'; 6 | import { Dispatch, RootState } from '../models'; 7 | import styles from './Search.module.less'; 8 | 9 | export default function Search() { 10 | const { package: pkg, pkgname } = useSelector(({ global }: RootState) => ({ 11 | package: global.package, 12 | pkgname: global.pkgname, 13 | })); 14 | const dispatch = useDispatch(); 15 | const [value, setValue] = useState(pkgname); 16 | const navigate = useNavigate(); 17 | const [links] = useState<{ to: string; label: string }[]>([ 18 | { 19 | to: '/pkg/uiw', 20 | label: 'uiw', 21 | }, 22 | { 23 | to: '/pkg/react', 24 | label: 'react', 25 | }, 26 | { 27 | to: '/pkg/vue', 28 | label: 'vue', 29 | }, 30 | { 31 | to: '/pkg/react@18', 32 | label: 'react@18', 33 | }, 34 | { 35 | to: '/pkg/react@18.2.0', 36 | label: 'react@18.2.0', 37 | }, 38 | ]); 39 | const name = pkg && pkg.name ? `${pkg.name}@${pkg.version}` : pkgname; 40 | const gotoPreview = () => { 41 | if (value) { 42 | dispatch.global.update({ showSearch: false }); 43 | navigate(`/pkg/${value}`); 44 | } 45 | } 46 | return ( 47 | 48 | { 54 | setValue(e.target.value); 55 | }} 56 | onKeyUp={(e) => { 57 | if (e.key === "Enter") { 58 | gotoPreview(); 59 | } 60 | }} 61 | addonAfter={ 62 | 64 | ), 65 | [Info, dispatch.global, path.pkgName], 66 | ); 67 | 68 | const unPkgView = useMemo( 69 | () => ( 70 | 71 | UNPKG 72 | 73 | ), 74 | [path.pkgName], 75 | ); 76 | return ( 77 | 78 |
79 | 80 | console.log('您点击了确定按钮!')} 87 | onCancel={() => console.log('您点击了取消按钮!')} 88 | onClosed={() => dispatch.global.update({ showSearch: false })} 89 | > 90 | 91 | 92 | {nameView} 93 | 94 | 95 | {unPkgView} 96 | 97 | {Info.name && ( 98 | 99 | 100 | 101 | 102 | 103 | {Info.repository && ( 104 | 105 | 113 | 114 | 115 | 116 | )} 117 | {Info.homepage && ( 118 | 119 | 120 | 121 | 122 | 123 | )} 124 | {Info.license && ( 125 | 126 | 127 | {Info.license} 128 | 129 | )} 130 | {Info.description && ( 131 | 132 | 133 | 134 | {Info.description} 135 | 136 | 137 | )} 138 | 139 | )} 140 | {notFindPkg && ( 141 | 142 | 143 | Cannot find package {path.pkgName}. 144 | 145 | )} 146 |
147 | 148 | 149 |
150 | 151 |
152 | 153 | 154 | 155 |
156 |
157 |
158 | ); 159 | } 160 | 161 | Component.displayName = 'PreviewPage'; 162 | -------------------------------------------------------------------------------- /src/pages/Preview/npm.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | /// 4 | 5 | declare namespace NodeJS { 6 | interface ProcessEnv { 7 | readonly NODE_ENV: 'development' | 'production' | 'test'; 8 | readonly PUBLIC_URL: string; 9 | } 10 | } 11 | 12 | declare module '*.bmp' { 13 | const src: string; 14 | export default src; 15 | } 16 | 17 | declare module '*.gif' { 18 | const src: string; 19 | export default src; 20 | } 21 | 22 | declare module '*.jpg' { 23 | const src: string; 24 | export default src; 25 | } 26 | 27 | declare module '*.jpeg' { 28 | const src: string; 29 | export default src; 30 | } 31 | 32 | declare module '*.png' { 33 | const src: string; 34 | export default src; 35 | } 36 | 37 | declare module '*.webp' { 38 | const src: string; 39 | export default src; 40 | } 41 | 42 | declare module '*.svg' { 43 | import * as React from 'react'; 44 | 45 | export const ReactComponent: React.FunctionComponent>; 46 | 47 | const src: string; 48 | export default src; 49 | } 50 | 51 | declare module '*.module.less' { 52 | const classes: { readonly [key: string]: string }; 53 | export default classes; 54 | } 55 | 56 | declare module '*.less' { 57 | const src: string; 58 | export default src; 59 | } 60 | declare module '*.module.css' { 61 | const classes: { readonly [key: string]: string }; 62 | export default classes; 63 | } 64 | 65 | declare module '*.module.scss' { 66 | const classes: { readonly [key: string]: string }; 67 | export default classes; 68 | } 69 | 70 | declare module '*.module.sass' { 71 | const classes: { readonly [key: string]: string }; 72 | export default classes; 73 | } 74 | -------------------------------------------------------------------------------- /src/routers.ts: -------------------------------------------------------------------------------- 1 | import { RouteObject } from 'react-router-dom'; 2 | 3 | export const routes: RouteObject[] = [ 4 | { 5 | path: '/', 6 | lazy: () => import('./pages/Home'), 7 | }, 8 | { 9 | path: '/pkg/:name', 10 | lazy: () => import('./pages/Preview'), 11 | }, 12 | { 13 | path: '/pkg/:name/file/:filename/*', 14 | lazy: () => import('./pages/Preview'), 15 | }, 16 | { 17 | path: '/pkg/:org/:name', 18 | lazy: () => import('./pages/Preview'), 19 | }, 20 | { 21 | path: '/pkg/:org/:name/file/:filename/*', 22 | lazy: () => import('./pages/Preview'), 23 | }, 24 | ]; 25 | -------------------------------------------------------------------------------- /src/servers/unpkg.ts: -------------------------------------------------------------------------------- 1 | import request from '../utils/request'; 2 | 3 | export function getDirectoryTrees(pkg: string) { 4 | return request(`https://unpkg.com/${pkg}/?meta`, { 5 | method: 'GET', 6 | }); 7 | } 8 | 9 | export function getFileContent(path: string) { 10 | return request(`https://unpkg.com/${path}`, { 11 | method: 'GET', 12 | }); 13 | } 14 | -------------------------------------------------------------------------------- /src/utils/request.ts: -------------------------------------------------------------------------------- 1 | import axios, { AxiosRequestConfig } from 'axios'; 2 | // import history from '../routes/history'; 3 | import { splitUrl } from './utils'; 4 | 5 | // Get the current location. 6 | // const location = history.location; 7 | const codeMessage = { 8 | 200: '服务器成功返回请求的数据。', 9 | 201: '新建或修改数据成功。', 10 | 202: '一个请求已经进入后台排队(异步任务)。', 11 | 204: '删除数据成功。', 12 | 400: '发出的请求有错误,服务器没有进行新建或修改数据的操作。', 13 | 401: '用户没有权限(令牌、用户名、密码错误)。', 14 | 403: '用户得到授权,但是访问是被禁止的。', 15 | 404: '发出的请求针对的是不存在的记录,服务器没有进行操作。', 16 | 406: '请求的格式不可得。', 17 | 410: '请求的资源被永久删除,且不会再得到的。', 18 | 422: '当创建一个对象时,发生一个验证错误。', 19 | 500: '服务器发生错误,请检查服务器。', 20 | 502: '网关错误。', 21 | 503: '服务不可用,服务器暂时过载或维护。', 22 | 504: '网关超时。', 23 | }; 24 | 25 | export interface Options extends AxiosRequestConfig { 26 | body?: any; 27 | } 28 | 29 | /** 30 | * Requests a URL, returning a promise. 31 | * 32 | * @param {string} url The URL we want to request 33 | * @param {object} [options] The options we want to pass to "fetch" 34 | * @return {object} An object containing either "data" or "err" 35 | */ 36 | export default function request(url: string, options: Options = {}) { 37 | const method = options.method || 'GET'; 38 | const newOptions: Options = { 39 | url, 40 | method, 41 | data: options.body, 42 | headers: { 43 | 'Content-Type': 'application/json; charset=utf-8', 44 | Accept: 'application/json', 45 | }, 46 | }; 47 | 48 | if (/(GET)/.test(method)) { 49 | newOptions.url = splitUrl(url, { ...options.body }); 50 | delete newOptions.body; 51 | } 52 | 53 | return axios 54 | .request(newOptions) 55 | .then((response) => { 56 | return response.data; 57 | }) 58 | .catch((err) => { 59 | const response = err.response; 60 | if (response && response.status >= 200 && response.status < 300) { 61 | return response; 62 | } 63 | if (!response) { 64 | return; 65 | } 66 | const status = response.status; 67 | const errortext = (codeMessage as any)[status] || response.statusText; 68 | // Notification.error({ 69 | // message: '错误提示:', 70 | // description: (response.data && response.data.info) || '没有错误提示', 71 | // }); 72 | const error = new Error(errortext); 73 | error.name = response.status; 74 | // error.response = response; 75 | if (response.data) { 76 | return response.data; 77 | } 78 | throw error; 79 | }); 80 | } 81 | -------------------------------------------------------------------------------- /src/utils/utils.ts: -------------------------------------------------------------------------------- 1 | import { Files } from '../models/global'; 2 | 3 | // 拼接url参数 4 | export function splitUrl(url: string, options: { [x: string]: any }) { 5 | let urlNew = url; 6 | const paramsArray: string[] = []; 7 | // Object.keys(options).forEach(key => paramsArray.push(key + '=' + options[key])); 8 | Object.keys(options).forEach((key) => paramsArray.push(`${key}=${options[key]}`)); 9 | if (Object.keys(options).length === 0) { 10 | return url; 11 | } 12 | if (/\?/.test(urlNew) === false) { 13 | urlNew = `${urlNew}?${paramsArray.join('&')}`; 14 | } else { 15 | urlNew += `&${paramsArray.join('&')}`; 16 | } 17 | return urlNew; 18 | } 19 | 20 | export function nameSort(data: Files[] = [], resule: Files[] = []) { 21 | let dirs: Files[] = []; 22 | let files: Files[] = []; 23 | data.forEach((item) => { 24 | if (item.type === 'directory') { 25 | dirs.push(item); 26 | } else if (item.type === 'file') { 27 | files.push(item); 28 | } 29 | }); 30 | dirs = dirs.sort((a, b) => { 31 | return a.path.replace(/^\//, '').localeCompare(b.path.replace(/^\//, '')); 32 | }); 33 | files = files.sort((a, b) => { 34 | return a.path.replace(/^\//, '').localeCompare(b.path.replace(/^\//, '')); 35 | }); 36 | return [...dirs, ...files]; 37 | } 38 | 39 | export function dataFilesSort(files: Files[] = [], resule: Files[] = []) { 40 | resule = nameSort(files); 41 | resule = resule.map((file) => { 42 | if (file.files) { 43 | file.files = dataFilesSort(file.files); 44 | } 45 | return file; 46 | }); 47 | return resule; 48 | } 49 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "jsx": "react-jsx", 4 | "target": "esnext", 5 | "lib": ["dom", "dom.iterable", "esnext"], 6 | "allowJs": true, 7 | "skipLibCheck": true, 8 | "esModuleInterop": true, 9 | "allowSyntheticDefaultImports": true, 10 | "strict": true, 11 | "forceConsistentCasingInFileNames": true, 12 | "module": "esnext", 13 | "moduleResolution": "node", 14 | "resolveJsonModule": true, 15 | "isolatedModules": true, 16 | "declaration": true, 17 | "baseUrl": "./src", 18 | "noFallthroughCasesInSwitch": true, 19 | "noEmit": true 20 | } 21 | } 22 | --------------------------------------------------------------------------------