├── design ├── vue.png └── logo.html ├── shortcut ├── logo.png ├── dragging.gif ├── ele-info.png └── vue-web-terminal.gif ├── tsconfig.node.json ├── .github └── ISSUE_TEMPLATE │ ├── Feature or Suggestion.md │ └── Bug.md ├── vue-web-terminal.iml ├── .npmignore ├── index.html ├── test ├── main.ts └── App.vue ├── src ├── components │ ├── TViewerCode.vue │ ├── TViewerNormal.vue │ ├── TViewerTable.vue │ ├── TViewerJson.vue │ ├── TEditor.vue │ ├── THelpBox.vue │ └── THeader.vue ├── index.ts ├── env.d.ts ├── common │ ├── configuration.ts │ ├── api │ │ └── index.ts │ ├── store │ │ └── index.ts │ └── util.ts ├── css │ ├── scrollbar.css │ ├── theme │ │ ├── light.css │ │ └── dark.css │ ├── ansi.css │ └── style.css ├── ansi │ ├── ansi-256-colors.json │ └── index.ts ├── types │ └── index.ts └── Terminal.vue ├── .gitignore ├── tsconfig.json ├── package.js ├── publish.py ├── package.json ├── vite.config.ts ├── README_ZH.md ├── README.md └── LICENSE /design/vue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tzfun/vue-web-terminal/HEAD/design/vue.png -------------------------------------------------------------------------------- /shortcut/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tzfun/vue-web-terminal/HEAD/shortcut/logo.png -------------------------------------------------------------------------------- /shortcut/dragging.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tzfun/vue-web-terminal/HEAD/shortcut/dragging.gif -------------------------------------------------------------------------------- /shortcut/ele-info.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tzfun/vue-web-terminal/HEAD/shortcut/ele-info.png -------------------------------------------------------------------------------- /shortcut/vue-web-terminal.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tzfun/vue-web-terminal/HEAD/shortcut/vue-web-terminal.gif -------------------------------------------------------------------------------- /tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "skipLibCheck": true, 5 | "module": "ESNext", 6 | "moduleResolution": "bundler", 7 | "allowSyntheticDefaultImports": true 8 | }, 9 | "include": ["vite.config.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/Feature or Suggestion.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature or Suggestion 3 | about: Provide some better suggestions or optimizations 4 | title: '' 5 | labels: enhancement 6 | assignees: tzfun 7 | 8 | --- 9 | 10 | **Feature or optimization description** 11 | 12 | **Applicable scene** 13 | -------------------------------------------------------------------------------- /vue-web-terminal.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .* 2 | *.md 3 | *.yml 4 | *.iml 5 | *.lock 6 | *.html 7 | tsconfig.json 8 | tsconfig.node.json 9 | vite.config.ts 10 | build/ 11 | node_modules/ 12 | src/ 13 | test/ 14 | dist/ 15 | public/ 16 | gulpfile.js 17 | babel.config.js 18 | webpack.config.js 19 | vue.config.js 20 | package.js 21 | lib/*.html 22 | lib/*.chunk.* 23 | lib/*.txt 24 | lib/*.png 25 | lib/*.gif 26 | lib/*.jpg 27 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | vue-web-terminal demo 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /test/main.ts: -------------------------------------------------------------------------------- 1 | // @ts-ignore 2 | import App from './App.vue' 3 | import {createApp} from "vue"; 4 | import { createTerminal } from '../src' 5 | 6 | const app = createApp(App) 7 | 8 | const terminal = createTerminal() 9 | terminal.configStoreName("test-terminal") 10 | terminal.configMaxStoredCommandCountPerInstance(2) 11 | 12 | // 这行代码是一个错误示例 13 | // terminal.configTheme("custom", "s") 14 | 15 | app.use(terminal) 16 | 17 | app.mount('#app') 18 | -------------------------------------------------------------------------------- /src/components/TViewerCode.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 16 | 17 | 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | # local env files 11 | .env.local 12 | .env.*.local 13 | 14 | node_modules 15 | dist 16 | dist-ssr 17 | *.local 18 | /lib 19 | 20 | # Editor directories and files 21 | .vscode/* 22 | !.vscode/extensions.json 23 | .idea 24 | .vscode 25 | .DS_Store 26 | *.suo 27 | *.ntvs* 28 | *.njsproj 29 | *.sln 30 | *.sw? 31 | 32 | /vue-web-terminal.css 33 | /vue-web-terminal.js 34 | stats.html 35 | /docs/ 36 | /docs/.vuepress/ 37 | pnpm-lock.yaml 38 | /yarn.lock 39 | -------------------------------------------------------------------------------- /src/components/TViewerNormal.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 21 | 22 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/Bug.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: bug 6 | assignees: tzfun 7 | 8 | --- 9 | 10 | **Bug description** 11 | A clear and concise description of what the bug is. 12 | 13 | **Steps to reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Screenshot** 21 | If applicable, add screenshots to help explain your problem. 22 | 23 | **Reproduce environment:** 24 | - OS: [e.g. iOS] 25 | - Browser [e.g. chrome, safari] 26 | - Version [e.g. 2.0.4] 27 | 28 | **Detailed Description** 29 | Add any other context about the problem here. 30 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "target": "ES2020", 5 | "useDefineForClassFields": true, 6 | "module": "ESNext", 7 | "lib": ["ES2020", "DOM", "DOM.Iterable"], 8 | "skipLibCheck": true, 9 | "paths": { 10 | "~/*": ["src/*"] 11 | }, 12 | /* Bundler mode */ 13 | "moduleResolution": "bundler", 14 | "allowImportingTsExtensions": true, 15 | "resolveJsonModule": true, 16 | "isolatedModules": true, 17 | "jsx": "preserve", 18 | "noEmit": false, 19 | "emitDeclarationOnly": true, 20 | "declaration": true, 21 | "declarationDir": "lib" 22 | }, 23 | "include": [ 24 | "src/**/*.ts", 25 | "src/**/*.d.ts", 26 | "src/**/*.tsx", 27 | "src/**/*.vue" 28 | ], 29 | "references": [{ "path": "./tsconfig.node.json" }] 30 | } 31 | -------------------------------------------------------------------------------- /src/components/TViewerTable.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 27 | 28 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import './css/scrollbar.css' 2 | import './css/ansi.css' 3 | import './css/style.css' 4 | import 'vue-json-viewer/style.css' 5 | import type {App} from 'vue' 6 | import TerminalApi, {configMaxStoredCommandCountPerInstance, configStoreName, configTheme} from "./common/api" 7 | import Terminal from "./Terminal.vue" 8 | import {TerminalAsk, TerminalFlash, VueWebTerminal} from "./types" 9 | import {getStore, initStore} from "~/common/store"; 10 | 11 | const install = (app: App): void => { 12 | initStore() 13 | app.component(Terminal.__name as string, Terminal) 14 | } 15 | 16 | const createTerminal = (): VueWebTerminal => { 17 | return { 18 | install, 19 | configTheme, 20 | configStoreName, 21 | configMaxStoredCommandCountPerInstance 22 | } 23 | } 24 | 25 | export * from './types' 26 | 27 | export { 28 | Terminal, 29 | TerminalApi, 30 | TerminalAsk, 31 | TerminalFlash, 32 | createTerminal, 33 | getStore 34 | } 35 | 36 | export default Terminal 37 | -------------------------------------------------------------------------------- /src/env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | import '@vue/runtime-core' 4 | 5 | export {} 6 | 7 | declare module '@vue/runtime-core' { 8 | export interface GlobalComponents { 9 | THeader: typeof import("~/components/THeader.vue")['default'] 10 | TEditor: typeof import("~/components/TEditor.vue")['default'] 11 | THelpBox: typeof import("~/components/THelpBox.vue")['default'] 12 | TViewerCode: typeof import("~/components/TViewerCode.vue")['default'] 13 | TViewerJson: typeof import("~/components/TViewerJson.vue")['default'] 14 | TViewerNormal: typeof import("~/components/TViewerNormal.vue")['default'] 15 | TViewerTable: typeof import("~/components/TViewerTable.vue")['default'] 16 | JsonViewer: typeof import("vue-json-viewer")['default'] 17 | Terminal: typeof import("~/Terminal.vue")['default'] 18 | } 19 | } 20 | 21 | declare module "*.vue" { 22 | import { DefineComponent } from "vue"; 23 | const component: DefineComponent<{}, {}, any>; 24 | export default component; 25 | } 26 | -------------------------------------------------------------------------------- /src/components/TViewerJson.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 36 | 37 | 40 | -------------------------------------------------------------------------------- /package.js: -------------------------------------------------------------------------------- 1 | import path from 'path' 2 | import fs from 'fs' 3 | 4 | function copyDir(src, dest) { 5 | fs.mkdirSync(dest) 6 | for (let f of fs.readdirSync(src)) { 7 | fs.copyFileSync(path.join(src, f), path.join(dest, f)); 8 | } 9 | console.log('copied', `'${src}'`, '-->', `'${dest}'`) 10 | } 11 | 12 | function deleteFile(fileOrDirName) { 13 | let stat = fs.statSync(fileOrDirName) 14 | if (stat.isDirectory()) { 15 | for (let f of fs.readdirSync(fileOrDirName)) { 16 | let filePath = path.join(fileOrDirName, f) 17 | deleteFile(filePath) 18 | } 19 | fs.rmdirSync(fileOrDirName) 20 | } else { 21 | fs.unlinkSync(fileOrDirName) 22 | console.log(`deleted ==> ${fileOrDirName}`) 23 | } 24 | } 25 | 26 | function deleteFileWithPattern(dir, regexp) { 27 | for (let f of fs.readdirSync(dir)) { 28 | if (f.match(regexp)) { 29 | fs.unlinkSync(path.join(dir, f)) 30 | console.log(`deleted ==> ${dir}/${f}`) 31 | } 32 | } 33 | } 34 | 35 | function copyTypes() { 36 | fs.copyFileSync('./lib/types/index.d.ts', './lib/types.d.ts') 37 | deleteFile('./lib/types') 38 | console.log(`copied types.d.ts`) 39 | } 40 | 41 | // copyDir('./src/css/theme', './lib/theme'); 42 | deleteFile('./lib/ansi') 43 | deleteFile('./lib/common') 44 | deleteFile('./lib/components') 45 | deleteFileWithPattern('./lib', /\.(png|gif|jpg)/) 46 | // copyTypes() 47 | -------------------------------------------------------------------------------- /publish.py: -------------------------------------------------------------------------------- 1 | # encoding=utf8 2 | 3 | import subprocess 4 | import platform 5 | 6 | NPM_REPOSITORY="https://registry.npmjs.org" 7 | NPM_REPOSITORY_MIRROR="https://registry.npmmirror.com" 8 | NODE_VERSION = 18 9 | ENCODING = "gbk" if platform.system().lower() == 'windows' else 'utf-8' 10 | 11 | def execute(command, with_result = False,encoding = ENCODING): 12 | print(f"[calling]: {command}") 13 | if with_result: 14 | p = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, encoding=encoding) 15 | stdout,stderr = p.communicate() 16 | if p.returncode == 0: 17 | return stdout 18 | else: 19 | raise Exception(f"exit with {p.returncode}, stderr: {stderr}") 20 | else: 21 | returncode = subprocess.call(command, shell=True, encoding=encoding) 22 | if returncode != 0: 23 | raise Exception(f"exit with {returncode}") 24 | 25 | if __name__ == '__main__': 26 | registry = execute(f'npm config get registry', with_result=True) 27 | node_version = execute(f'node -v', with_result=True) 28 | if not node_version.startswith(f'v{NODE_VERSION}'): 29 | raise Exception(f'Node version must be {NODE_VERSION}') 30 | try: 31 | execute(f'pnpm install') 32 | execute(f'pnpm run build') 33 | execute(f'npm config set registry {NPM_REPOSITORY}') 34 | execute(f'npm publish') 35 | finally: 36 | execute(f'npm config set registry {registry}') 37 | -------------------------------------------------------------------------------- /src/components/TEditor.vue: -------------------------------------------------------------------------------- 1 | 28 | 29 |