diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..3f19022 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,54 @@ +name: Build & Deploy +on: + push: + branches: + - main + +env: + SKIP_PREFLIGHT_CHECK: true + +jobs: + build-deploy: + runs-on: ubuntu-18.04 + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v2 + with: + node-version: 14 + + - run: npm install + - run: npm run build + - run: npm run test:coverage + + - name: Create Tag + id: create_tag + uses: jaywcjlove/create-tag-action@v1.2.0 + with: + token: ${{ secrets.GITHUB_TOKEN }} + package-path: ./package.json + + - name: Generate Changelog + id: changelog + uses: jaywcjlove/changelog-generator@v1.4.2 + with: + token: ${{ secrets.GITHUB_TOKEN }} + head-ref: ${{steps.create_tag.outputs.version}} + filter-author: (jaywcjlove|小弟调调™|dependabot\[bot\]|Renovate Bot) + filter: '[R|r]elease[d]\s+[v|V]\d(\.\d+){0,2}' + + - name: Deploy + uses: peaceiris/actions-gh-pages@v3 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: ./build + + - name: Create Release + uses: ncipollo/release-action@v1 + if: steps.create_tag.outputs.successful + with: + token: ${{ secrets.GITHUB_TOKEN }} + name: ${{ steps.create_tag.outputs.version }} + tag: ${{ steps.create_tag.outputs.version }} + body: | + ${{ steps.changelog.outputs.compareurl }} + ${{ steps.changelog.outputs.changelog }} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5dc5b0f --- /dev/null +++ b/.gitignore @@ -0,0 +1,18 @@ +build +coverage +node_modules +npm-debug.log* +package-lock.json +.eslintcache +.DS_Store +.cache +.vscode + +*.lerna_backup +*.log +*.bak +*.tem +*.temp +#.swp +*.*~ +~*.* diff --git a/.kktrc.ts b/.kktrc.ts new file mode 100644 index 0000000..9e0f6c9 --- /dev/null +++ b/.kktrc.ts @@ -0,0 +1,15 @@ +import webpack, { Configuration } from 'webpack'; +import lessModules from '@kkt/less-modules'; +import { LoaderConfOptions } from 'kkt'; +import pkg from './package.json'; + +export default (conf: Configuration, env: 'development' | 'production', options: LoaderConfOptions) => { + conf = lessModules(conf, env, options); + // Get the project version. + conf.plugins!.push( + new webpack.DefinePlugin({ + VERSION: JSON.stringify(pkg.version), + }), + ); + return conf; +}; diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..e7d1213 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,11 @@ +**/*.md +**/*.svg +**/*.ejs +**/*.html +package.json +dist +build +website/web/build +lib +coverage +node_modules \ No newline at end of file diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..4247c44 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,11 @@ +{ + "singleQuote": true, + "trailingComma": "all", + "printWidth": 130, + "overrides": [ + { + "files": ".prettierrc", + "options": { "parser": "json" } + } + ] +} diff --git a/README.md b/README.md new file mode 100644 index 0000000..8a69eb1 --- /dev/null +++ b/README.md @@ -0,0 +1,7 @@ +[`Keycode Info`](https://uiwjs.github.io/keycode-info) + +JavaScript Keycodes of KeyboardEvent + +https://uiwjs.github.io/keycode-info + +A simple web page that responds to the pressed key and returns information about the JavaScript'on-key press' key. diff --git a/package.json b/package.json new file mode 100644 index 0000000..04ef820 --- /dev/null +++ b/package.json @@ -0,0 +1,61 @@ +{ + "name": "keycode-info", + "homepage": "https://uiwjs.github.io/keycode-info", + "version": "1.0.0", + "description": "A simple web page that responds to the pressed key and returns information about the JavaScript'on-key press' key.", + "private": true, + "scripts": { + "start": "kkt start", + "build": "kkt build", + "test": "kkt test --env=jsdom", + "test:coverage": "kkt test --env=jsdom --coverage", + "prettier": "prettier --write '**/*.{js,jsx,tsx,ts,less,md,json}'" + }, + "repository": { + "type": "git", + "url": "https://github.com/kktjs/kkt.git" + }, + "author": "", + "license": "MIT", + "dependencies": { + "@uiw/react-copy-to-clipboard": "4.9.1", + "@uiw/react-github-corners": "1.4.0", + "react": "17.0.2", + "react-dom": "17.0.2", + "react-json-view": "1.21.3" + }, + "devDependencies": { + "@kkt/less-modules": "6.10.4", + "@types/jest": "26.0.23", + "@types/react": "17.0.11", + "@types/react-dom": "17.0.8", + "kkt": "6.10.4", + "prettier": "2.3.2" + }, + "jest": { + "testMatch": [ + "/src/**/*.test.{ts,tsx}" + ], + "collectCoverageFrom": [ + "/src/app/*.{tsx,ts}" + ] + }, + "eslintConfig": { + "extends": [ + "react-app", + "react-app/jest" + ] + }, + "browserslist": { + "production": [ + ">0.2%", + "not dead", + "not op_mini all" + ], + "development": [ + "last 1 chrome version", + "last 1 firefox version", + "last 1 safari version" + ] + } +} diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000..a11777c Binary files /dev/null and b/public/favicon.ico differ diff --git a/public/index.html b/public/index.html new file mode 100644 index 0000000..0c5dee7 --- /dev/null +++ b/public/index.html @@ -0,0 +1,20 @@ + + + + + + + + + + Keycode Info + + + + +
+ + + \ No newline at end of file diff --git a/src/app/App.css b/src/app/App.css new file mode 100644 index 0000000..26d8422 --- /dev/null +++ b/src/app/App.css @@ -0,0 +1,73 @@ +.App { + text-align: center; +} + +.App-header { + background-color: #282c34; + min-height: 100vh; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + color: white; +} + +.help, .json-view { + display: inline-block; + color: #f2f4f8; + text-decoration: none; + text-align: center; + margin: 20px auto; + padding: 15px 20px; + background: rgb(0 0 0 / 15%); + border-radius: 5px; + min-width: 24px; +} +.help { + font-size: 26px; + box-shadow: 0 14px 26px rgb(0 0 0 / 4%); +} + +.json-view { + text-align: initial; + min-width: 320px; + font-size: 16px; + background-color: rgb(43, 48, 59); +} + +.key-which { + font-size: 40vmin; + text-align: center; +} +.keyboard { + color: #333; +} +.keyboard > span + span { + margin-left: 10px; + display: inline-block; +} +.keyboard .copied kbd { + background: #03a132; +} +.keyboard kbd { + display: inline-block; + background: #eff0f2; + border-radius: 3px; + padding: 5px 10px; + border-top: 1px solid #f5f5f5; + box-shadow: inset 0 0 25px #e8e8e8, 0 1px 0 #c3c3c3, 0 2px 0 #c9c9c9, 0 2px 3px #333; + text-shadow: 0px 1px 0px #f5f5f5; + cursor: pointer; + user-select: none; + transition: background-color 0.3s; +} + +.copied-info { + position: absolute; + top: 10px; + left: 10px; + background-color: #03a132; + color: #fff; + padding: 2px 5px; + border-radius: 2px; +} \ No newline at end of file diff --git a/src/app/App.test.tsx b/src/app/App.test.tsx new file mode 100644 index 0000000..8cf609b --- /dev/null +++ b/src/app/App.test.tsx @@ -0,0 +1,17 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; +import { render, fireEvent } from '@testing-library/react'; +import App from './App'; + +it('renders without crashing', () => { + const div = document.createElement('div'); + ReactDOM.render(, div); + ReactDOM.unmountComponentAtNode(div); +}); + +it('MDEditor commands code `ctrlcmd+j`', async () => { + const { getByTitle } = render(); + // const input = getByTitle('test'); + fireEvent.keyDown(document, { key: 'J', code: 'KeyJ', ctrlKey: true, shiftKey: true }); + // expect(handleChange).toHaveReturnedWith('```\nHello\n```'); +}); diff --git a/src/app/App.tsx b/src/app/App.tsx new file mode 100644 index 0000000..67cecc2 --- /dev/null +++ b/src/app/App.tsx @@ -0,0 +1,107 @@ +import React, { Fragment, useEffect, useState } from 'react'; +import ReactJson from 'react-json-view'; +import CopyToClipboard from '@uiw/react-copy-to-clipboard'; +import './App.css'; + +type Writeable = { -readonly [P in keyof T]: T[P] }; + +type KeyboardEventType = Writeable + +const App = () => { + const [data, setData] = useState(); + const [copied, setCopied] = useState(false); + function keypressHandle(evn: KeyboardEvent) { + evn.preventDefault(); + const protoKeys: (keyof KeyboardEventType)[] = [ + 'altKey', + 'code', + 'ctrlKey', + 'isComposing', + 'key', + // 'locale', + 'location', + 'metaKey', + 'repeat', + 'shiftKey', + 'char', + 'charCode', + 'keyCode', + // 'keyIdentifier', + // 'keyLocation', + 'which', + + 'cancelBubble', + 'cancelable', + 'composed', + 'defaultPrevented', + 'detail', + 'eventPhase', + 'isTrusted', + 'timeStamp', + 'returnValue', + 'type', + ]; + const result = {} as any; + for (let key of protoKeys) { + result[key] = evn[key]; + } + setData(result as KeyboardEventType); + } + let timer: NodeJS.Timeout; + function handleClick(text: string, isCopy: boolean, event: React.MouseEvent) { + const target = event.target as HTMLSpanElement; + target.parentElement!.classList.add('copied'); + if (timer) clearTimeout(timer); + setCopied(true); + timer = setTimeout(() => { + setCopied(false); + target.parentElement!.classList.remove('copied') + clearTimeout(timer); + }, 1000); + } + useEffect(() => { + document.addEventListener('keydown', keypressHandle); + return () => { + document.removeEventListener('keydown', keypressHandle); + }; + }, []); + return ( +
+ {copied &&
copied
} +
+ {!data &&
Press any key to get the JavaScript event keycode
} + {data && ( + + {data.which} +
+ + {data.key} + + + {data.location} + + + + {data.which} + + + + + {data.keyCode} + + + + {data.code} + +
+
+ +
+
+ )} +
+
+ ); +}; + +export default App; diff --git a/src/index.css b/src/index.css new file mode 100644 index 0000000..be7760f --- /dev/null +++ b/src/index.css @@ -0,0 +1,11 @@ +body { + margin: 0; + padding: 0; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", + "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", + sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-size: 14px; + background-color: #282c34; +} diff --git a/src/index.tsx b/src/index.tsx new file mode 100644 index 0000000..c021c10 --- /dev/null +++ b/src/index.tsx @@ -0,0 +1,6 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; +import App from './app/App'; +import './index.css'; + +ReactDOM.render(, document.getElementById('root')); diff --git a/src/react-app-env.d.ts b/src/react-app-env.d.ts new file mode 100644 index 0000000..94d8709 --- /dev/null +++ b/src/react-app-env.d.ts @@ -0,0 +1,11 @@ +/// + +declare module '*.module.less' { + const classes: { readonly [key: string]: string }; + export default classes; +} + +declare module '*.less' { + const classes: { readonly [key: string]: string }; + export default classes; +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..66266e0 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,23 @@ +{ + "compilerOptions": { + "target": "es5", + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "module": "esnext", + "moduleResolution": "node", + "resolveJsonModule": true, + "isolatedModules": true, + "declaration": true, + "baseUrl": ".", + "jsx": "react-jsx", + "noFallthroughCasesInSwitch": true, + "noEmit": true, + "types": ["jest", "node"] + }, + "include": ["src", ".kktrc.ts"] +}