├── .gitignore ├── .npmignore ├── README.md ├── build ├── config.js └── webpack.common.js ├── dist └── json-schema-editor.min.js ├── docs ├── css │ ├── app.478317e2.css │ └── chunk-vendors.c470e980.css ├── favicon.ico ├── fonts │ ├── element-icons.535877f5.woff │ └── element-icons.732389de.ttf ├── index.html └── js │ ├── app.51aae14f.js │ ├── app.51aae14f.js.map │ ├── chunk-vendors.d43c2cc5.js │ └── chunk-vendors.d43c2cc5.js.map ├── example ├── .eslintignore ├── README.md ├── babel.config.js ├── package.json ├── public │ ├── favicon.ico │ └── index.html ├── src │ ├── App.vue │ ├── assets │ │ └── logo.png │ ├── components │ │ └── HelloWorld.vue │ └── main.js └── yarn.lock ├── json-schema-editor.png ├── package.json ├── src ├── MockSelect │ └── index.vue ├── Schema │ ├── DropPlus.vue │ ├── SchemaArray.vue │ ├── SchemaItem.vue │ ├── SchemaObject.vue │ └── index.vue ├── common.js ├── dialog │ ├── ArrayDialog.vue │ ├── BasicDialog.vue │ ├── BooleanDialog.vue │ ├── NumberDialog.vue │ ├── ObjectDialog.vue │ ├── RawDialog.vue │ ├── StringDialog.vue │ └── index.js ├── event.js ├── index.js ├── json-editor │ ├── index.js │ └── src │ │ └── json-editor.vue ├── json-schema-editor.vue ├── jsonschema.scss └── utils.js └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | 4 | # local env files 5 | .env.local 6 | .env.*.local 7 | 8 | # Log files 9 | lerna-debug.log* 10 | npm-debug.log* 11 | yarn-debug.log* 12 | yarn-error.log* 13 | pnpm-debug.log* 14 | # Editor directories and files 15 | .idea 16 | .vscode 17 | *.suo 18 | *.ntvs* 19 | *.njsproj 20 | *.sln 21 | *.sw? 22 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | 4 | # local env files 5 | .env.local 6 | .env.*.local 7 | docs/* 8 | # Log files 9 | lerna-debug.log* 10 | npm-debug.log* 11 | yarn-debug.log* 12 | yarn-error.log* 13 | pnpm-debug.log* 14 | # Editor directories and files 15 | .idea 16 | .vscode 17 | *.suo 18 | *.ntvs* 19 | *.njsproj 20 | *.sln 21 | *.sw? 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vue-json-schema-editor-visual 2 | 3 | [![](https://img.shields.io/npm/v/vue-json-schema-editor-visual.svg?style=flat-square)](https://www.npmjs.com/package/vue-json-schema-editor-visual) 4 | 5 | A json-schema editor of high efficient and easy-to-use, base on Vue & Element UI. 6 | 7 | 一个高效易用的基于 Vue + Element UI 的 json-schema 编辑器。 模仿 Yapi React 版本 [json-schema-editor-visual](https://github.com/YMFE/json-schema-editor-visual) 实现 8 | 9 | ![](./json-schema-editor.png) 10 | 11 | ## Usage 12 | 13 | ```js 14 | import JsonSchemaEditor from 'vue-json-schema-editor-visual'; 15 | 16 | Vue.use(JsonSchemaEditor); 17 | ``` 18 | 19 | 在线 Demo 20 | 21 | - [Sinokit json-schema-editor](http://blog.giscafer.com/sinokit/#/./components/jsonschema-editor) 22 | - [CodeSandbox Demo](https://codesandbox.io/s/practical-pond-jpteu?file=/src/App.vue) 23 | 24 | ## API 25 | 26 | ### Attributes 27 | 28 | | 参数 | 说明 | 类型 | 默认值 | 29 | | :------------------: | ------------------------------------- | :-------: | :-----: | 30 | | `schema` | json schema 对象 | `Object` | - | 31 | | `show-raw` | 是否显示 RAW 弹窗,可查看 json schema | `Boolean` | `false` | 32 | | `is-mock` | 是否支持 mock (WIP) | `Boolean` | `false` | 33 | | `show-default-value` | 是否展示默认值输入框 | `Boolean` | `false` | 34 | 35 | ### Events 36 | 37 | | 事件名称 | 说明 | 回调参数 | 38 | | :-------------: | --------------------------- | :-------------------: | 39 | | `schema-change` | schema 发生变化时的回调函数 | 新的 json schema 对象 | 40 | 41 | ## Related 42 | 43 | - [json-schema-editor-vue](https://github.com/zyqwst/json-schema-editor-vue) vue + ant-design-vue 44 | 45 | 其他 json editor 46 | 47 | - [jsoneditor](https://github.com/josdejong/jsoneditor) 48 | - [json-editor/json-editor](https://github.com/json-editor/json-editor) 49 | - [jinkin1995/vue-json-edit](https://github.com/jinkin1995/vue-json-edit) 50 | 51 | ## License 52 | 53 | MIT 54 | -------------------------------------------------------------------------------- /build/config.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var nodeExternals = require('webpack-node-externals'); 3 | 4 | externals = [ 5 | Object.assign({ 6 | vue: 'vue', 7 | }), 8 | nodeExternals(), 9 | ]; 10 | 11 | exports.externals = externals; 12 | 13 | exports.alias = { 14 | main: path.resolve(__dirname, '../src'), 15 | }; 16 | 17 | exports.vue = { 18 | root: 'Vue', 19 | commonjs: 'vue', 20 | commonjs2: 'vue', 21 | amd: 'vue', 22 | }; 23 | 24 | exports.jsexclude = /node_modules|utils\/popper\.js|utils\/date\.js/; 25 | -------------------------------------------------------------------------------- /build/webpack.common.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const ProgressBarPlugin = require('progress-bar-webpack-plugin'); 3 | const VueLoaderPlugin = require('vue-loader/lib/plugin'); 4 | 5 | const config = require('./config'); 6 | 7 | module.exports = { 8 | mode: 'production', 9 | entry: { 10 | app: ['./src/index.js'], 11 | }, 12 | output: { 13 | path: path.resolve(__dirname, '../dist'), 14 | publicPath: '../dist/', 15 | filename: 'json-schema-editor.min.js', 16 | library: 'JsonSchemaEditor', 17 | libraryTarget: 'umd', 18 | umdNamedDefine: true, 19 | }, 20 | resolve: { 21 | extensions: ['.js', '.vue', '.json'], 22 | alias: config.alias, 23 | modules: ['node_modules'], 24 | }, 25 | externals: { 26 | vue: config.vue, 27 | }, 28 | performance: { 29 | hints: false, 30 | }, 31 | stats: { 32 | children: false, 33 | }, 34 | optimization: { 35 | minimize: true, 36 | }, 37 | 38 | module: { 39 | rules: [ 40 | { 41 | test: /\.(jsx?|babel|es6)$/, 42 | include: process.cwd(), 43 | exclude: config.jsexclude, 44 | loader: 'babel-loader', 45 | }, 46 | { 47 | test: /\.vue$/, 48 | loader: 'vue-loader', 49 | options: { 50 | compilerOptions: { 51 | preserveWhitespace: false, 52 | }, 53 | }, 54 | }, 55 | { 56 | test: /\.css$/, 57 | use: [ 58 | { 59 | loader: 'style-loader', // 将 JS 字符串生成为 style 节点 60 | }, 61 | { 62 | loader: 'css-loader', 63 | options: { 64 | import: true, 65 | }, 66 | }, 67 | ], 68 | }, 69 | { 70 | test: /\.scss$/, 71 | loaders: ['style-loader', 'css-loader', 'sass-loader'], 72 | }, 73 | { 74 | test: /\.(svg|otf|ttf|woff2?|eot|gif|png|jpe?g)(\?\S*)?$/, 75 | loader: 'url-loader', 76 | query: { 77 | limit: 10000, 78 | name: path.posix.join('static', '[name].[hash:7].[ext]'), 79 | }, 80 | }, 81 | ], 82 | }, 83 | plugins: [new ProgressBarPlugin(), new VueLoaderPlugin()], 84 | }; 85 | -------------------------------------------------------------------------------- /docs/css/app.478317e2.css: -------------------------------------------------------------------------------- 1 | #app{font-family:Avenir,Helvetica,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;text-align:center;color:#2c3e50;margin-top:100px} -------------------------------------------------------------------------------- /docs/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/giscafer/vue-json-schema-editor-visual/72c7dd1b359ee8104844de17e73b00ba563c0b4d/docs/favicon.ico -------------------------------------------------------------------------------- /docs/fonts/element-icons.535877f5.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/giscafer/vue-json-schema-editor-visual/72c7dd1b359ee8104844de17e73b00ba563c0b4d/docs/fonts/element-icons.535877f5.woff -------------------------------------------------------------------------------- /docs/fonts/element-icons.732389de.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/giscafer/vue-json-schema-editor-visual/72c7dd1b359ee8104844de17e73b00ba563c0b4d/docs/fonts/element-icons.732389de.ttf -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | vue-demo 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | Fork me on GitHub 35 |
36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /example/.eslintignore: -------------------------------------------------------------------------------- 1 | 2 | 3 | **/*/*.min.js 4 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | # vue-json-schema-editor-visual-demo 2 | 3 | ## Project setup 4 | 5 | ``` 6 | npm install 7 | ``` 8 | 9 | ### Compiles and hot-reloads for development 10 | 11 | ``` 12 | npm run serve 13 | ``` 14 | 15 | ### Compiles and minifies for production 16 | 17 | ``` 18 | npm run build 19 | ``` 20 | 21 | ### Lints and fixes files 22 | 23 | ``` 24 | npm run lint 25 | ``` 26 | 27 | ### Customize configuration 28 | 29 | See [Configuration Reference](https://cli.vuejs.org/config/). 30 | -------------------------------------------------------------------------------- /example/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/cli-plugin-babel/preset' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-demo", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "serve": "vue-cli-service serve", 7 | "build": "vue-cli-service build", 8 | "lint": "vue-cli-service lint" 9 | }, 10 | "dependencies": { 11 | "@sinokit/components": "^0.1.23", 12 | "core-js": "^3.6.5", 13 | "element-ui": "^2.15.1", 14 | "vue": "^2.6.11" 15 | }, 16 | "devDependencies": { 17 | "@vue/cli-plugin-babel": "~4.5.0", 18 | "@vue/cli-plugin-eslint": "~4.5.0", 19 | "@vue/cli-service": "~4.5.0", 20 | "babel-eslint": "^10.1.0", 21 | "eslint": "^6.7.2", 22 | "eslint-plugin-vue": "^6.2.2", 23 | "vue-template-compiler": "^2.6.11" 24 | }, 25 | "eslintConfig": { 26 | "root": true, 27 | "env": { 28 | "node": true 29 | }, 30 | "extends": [ 31 | "plugin:vue/essential", 32 | "eslint:recommended" 33 | ], 34 | "parserOptions": { 35 | "parser": "babel-eslint" 36 | }, 37 | "rules": {} 38 | }, 39 | "browserslist": [ 40 | "> 1%", 41 | "last 2 versions", 42 | "not dead" 43 | ] 44 | } 45 | -------------------------------------------------------------------------------- /example/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/giscafer/vue-json-schema-editor-visual/72c7dd1b359ee8104844de17e73b00ba563c0b4d/example/public/favicon.ico -------------------------------------------------------------------------------- /example/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | <%= htmlWebpackPlugin.options.title %> 9 | 10 | 11 | Fork me on GitHub 23 | 30 |
31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /example/src/App.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 28 | 29 | 39 | -------------------------------------------------------------------------------- /example/src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/giscafer/vue-json-schema-editor-visual/72c7dd1b359ee8104844de17e73b00ba563c0b4d/example/src/assets/logo.png -------------------------------------------------------------------------------- /example/src/components/HelloWorld.vue: -------------------------------------------------------------------------------- 1 | 2 | 25 | -------------------------------------------------------------------------------- /example/src/main.js: -------------------------------------------------------------------------------- 1 | import ElementUI from 'element-ui'; 2 | import 'element-ui/lib/theme-chalk/index.css'; 3 | import Vue from 'vue'; 4 | import JsonSchemaEditor from '../../dist/json-schema-editor.min.js'; 5 | import App from './App.vue'; 6 | 7 | Vue.use(ElementUI, { size: 'small' }); 8 | Vue.use(JsonSchemaEditor); 9 | 10 | Vue.config.productionTip = false; 11 | 12 | new Vue({ 13 | render: (h) => h(App), 14 | }).$mount('#app'); 15 | -------------------------------------------------------------------------------- /json-schema-editor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/giscafer/vue-json-schema-editor-visual/72c7dd1b359ee8104844de17e73b00ba563c0b4d/json-schema-editor.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-json-schema-editor-visual", 3 | "version": "0.2.6", 4 | "description": "A json-schema editor of high efficient and easy-to-use, base on Vue.", 5 | "keywords": [ 6 | "json-schema" 7 | ], 8 | "author": "giscafer ", 9 | "homepage": "https://github.com/giscafer/vue-json-schema-editor-visual", 10 | "license": "MIT", 11 | "main": "dist/json-schema-editor.min.js", 12 | "unpkg": "dist/json-schema-editor.min.js", 13 | "directories": { 14 | "dist": "dist", 15 | "src": "src", 16 | "test": "__tests__" 17 | }, 18 | "files": [ 19 | "dist", 20 | "src" 21 | ], 22 | "publishConfig": { 23 | "access": "public", 24 | "registry": "https://registry.npmjs.org/" 25 | }, 26 | "repository": { 27 | "type": "git", 28 | "url": "https://github.com/giscafer/vue-json-schema-editor-visual.git" 29 | }, 30 | "scripts": { 31 | "clean": "rimraf dist", 32 | "build": "npm run clean && webpack --config build/webpack.common.js --optimize-max-chunks 1", 33 | "lint": "eslint lib/**/* build/**/* --quiet", 34 | "test": "echo \"Error: run tests from root\" && exit 1" 35 | }, 36 | "dependencies": { 37 | "codemirror": "^5.58.1", 38 | "element-ui": "2.13.2", 39 | "json-schema-faker": "^0.5.0-rcv.24", 40 | "lodash": "^4.17.19", 41 | "mockjs": "^1.1.0", 42 | "vue": "^2.6.11", 43 | "json-templater": "^1.2.0", 44 | "jsonlint": "^1.6.3" 45 | }, 46 | "devDependencies": { 47 | "@babel/core": "^7.11.6", 48 | "babel": "^6.23.0", 49 | "babel-loader": "^8.1.0", 50 | "css-loader": "^4.1.0", 51 | "node-sass": "^4.14.1", 52 | "progress-bar-webpack-plugin": "^2.1.0", 53 | "sass-loader": "^9.0.2", 54 | "script-loader": "^0.7.2", 55 | "style-loader": "^1.2.1", 56 | "terser-webpack-plugin": "^3.0.8", 57 | "uppercamelcase": "^3.0.0", 58 | "url-loader": "^4.1.0", 59 | "vue-loader": "^15.9.3", 60 | "vue-template-compiler": "^2.6.12", 61 | "webpack": "^4.44.0", 62 | "webpack-cli": "^3.3.12", 63 | "webpack-node-externals": "^2.5.0" 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/MockSelect/index.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 62 | 63 | 65 | -------------------------------------------------------------------------------- /src/Schema/DropPlus.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 43 | 44 | 46 | -------------------------------------------------------------------------------- /src/Schema/SchemaArray.vue: -------------------------------------------------------------------------------- 1 | 140 | 225 | -------------------------------------------------------------------------------- /src/Schema/SchemaItem.vue: -------------------------------------------------------------------------------- 1 | 184 | 291 | -------------------------------------------------------------------------------- /src/Schema/SchemaObject.vue: -------------------------------------------------------------------------------- 1 | 16 | 55 | -------------------------------------------------------------------------------- /src/Schema/index.vue: -------------------------------------------------------------------------------- 1 | 25 | 66 | -------------------------------------------------------------------------------- /src/common.js: -------------------------------------------------------------------------------- 1 | const Mock = require('mockjs'); 2 | const jsf = require('json-schema-faker'); 3 | 4 | jsf.extend('mock', function() { 5 | return { 6 | mock: function(xx) { 7 | return Mock.mock(xx); 8 | } 9 | }; 10 | }); 11 | 12 | const defaultOptions = { 13 | failOnInvalidTypes: false, 14 | failOnInvalidFormat: false, 15 | alwaysFakeOptionals: true, 16 | useDefaultValue: true 17 | }; 18 | 19 | export const schemaToJson = (schema, options = {}) => { 20 | Object.assign(options, defaultOptions); 21 | 22 | jsf.option(options); 23 | let result; 24 | try { 25 | result = jsf.generate(schema); 26 | } catch (err) { 27 | result = err.message; 28 | } 29 | jsf.option(defaultOptions); 30 | return result; 31 | }; 32 | -------------------------------------------------------------------------------- /src/dialog/ArrayDialog.vue: -------------------------------------------------------------------------------- 1 | 40 | 41 | 83 | -------------------------------------------------------------------------------- /src/dialog/BasicDialog.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 63 | 64 | 66 | -------------------------------------------------------------------------------- /src/dialog/BooleanDialog.vue: -------------------------------------------------------------------------------- 1 | 34 | 84 | -------------------------------------------------------------------------------- /src/dialog/NumberDialog.vue: -------------------------------------------------------------------------------- 1 | 97 | 170 | -------------------------------------------------------------------------------- /src/dialog/ObjectDialog.vue: -------------------------------------------------------------------------------- 1 | 29 | 79 | -------------------------------------------------------------------------------- /src/dialog/RawDialog.vue: -------------------------------------------------------------------------------- 1 | 20 | 42 | 44 | -------------------------------------------------------------------------------- /src/dialog/StringDialog.vue: -------------------------------------------------------------------------------- 1 | 94 | 164 | -------------------------------------------------------------------------------- /src/dialog/index.js: -------------------------------------------------------------------------------- 1 | import BasicDialog from './BasicDialog'; 2 | import StringDialog from './StringDialog'; 3 | import NumberDialog from './NumberDialog'; 4 | import ArrayDialog from './ArrayDialog'; 5 | import BooleanDialog from './BooleanDialog'; 6 | import ObjectDialog from './ObjectDialog'; 7 | import RawDialog from './RawDialog'; 8 | 9 | export { 10 | BasicDialog, 11 | StringDialog, 12 | NumberDialog, 13 | ArrayDialog, 14 | BooleanDialog, 15 | ObjectDialog, 16 | RawDialog 17 | }; 18 | -------------------------------------------------------------------------------- /src/event.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author: giscafer ,https://github.com/giscafer 3 | * @date: 2020-05-21 17:21:29 4 | * @description: 用一个Vue实例封装事件常用的方法并赋值给全局的变量,以便在任何一个组件都可调用这些方法来实现全局事件管理 5 | * 6 | * 使用如下: 7 | * mounted(){ 8 | this.$jsEditorEvent.on('change_value',id); 9 | this.$jsEditorEvent.emit('change_value',1); 10 | ... 11 | } 12 | */ 13 | 14 | import Vue from 'vue'; 15 | 16 | const eventHub = new Vue({ 17 | methods: { 18 | on(...args) { 19 | this.$on.apply(this, args); 20 | }, 21 | emit(...args) { 22 | this.$emit.apply(this, args); 23 | }, 24 | off(...args) { 25 | this.$off.apply(this, args); 26 | }, 27 | once(...args) { 28 | this.$once.apply(this, args); 29 | }, 30 | }, 31 | }); 32 | 33 | /* const CustomEventPlugin = V => 34 | Object.defineProperty(V.prototype, '$event', { 35 | value: eventHub, 36 | writable: true 37 | }); */ 38 | 39 | const CustomEventPlugin = { 40 | install: function(V) { 41 | Object.defineProperty(V.prototype, '$jsEditorEvent', { 42 | value: eventHub, 43 | writable: true, 44 | }); 45 | }, 46 | }; 47 | 48 | export default CustomEventPlugin; 49 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import JsonSchemaEditor from './json-schema-editor.vue'; 2 | import CustomEventPlugin from './event'; 3 | 4 | const install = function(Vue) { 5 | Vue.use(CustomEventPlugin); 6 | 7 | Vue.component(JsonSchemaEditor.name, JsonSchemaEditor); 8 | }; 9 | 10 | JsonSchemaEditor.install = install; 11 | 12 | /* istanbul ignore if */ 13 | if (typeof window !== 'undefined' && window.Vue) { 14 | install(window.Vue); 15 | } 16 | 17 | export default JsonSchemaEditor; 18 | -------------------------------------------------------------------------------- /src/json-editor/index.js: -------------------------------------------------------------------------------- 1 | import JsonEditor from './src/json-editor'; 2 | 3 | /* istanbul ignore next */ 4 | JsonEditor.install = function(Vue) { 5 | Vue.component(JsonEditor.name, JsonEditor); 6 | }; 7 | 8 | export default JsonEditor; 9 | -------------------------------------------------------------------------------- /src/json-editor/src/json-editor.vue: -------------------------------------------------------------------------------- 1 |