2
0
mirror of https://github.com/tenrok/vue-json-viewer.git synced 2026-06-11 18:02:29 +03:00
This commit is contained in:
陈峰
2017-10-18 11:45:31 +08:00
commit c09807c798
14 changed files with 6042 additions and 0 deletions
+149
View File
@@ -0,0 +1,149 @@
# Created by https://www.gitignore.io/api/node,webstorm,netbeans,sublimetext,vim
### Node ###
# Logs
logs
*.log
npm-debug.log*
# Runtime data
pids
*.pid
*.seed
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# node-waf configuration
.lock-wscript
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules
jspm_packages
# Optional npm cache directory
.npm
# Optional REPL history
.node_repl_history
### WebStorm ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
.idea/
# User-specific stuff:
.idea/workspace.xml
.idea/tasks.xml
.idea/dictionaries
.idea/vcs.xml
.idea/jsLibraryMappings.xml
# Sensitive or high-churn files:
.idea/dataSources.ids
.idea/dataSources.xml
.idea/dataSources.local.xml
.idea/sqlDataSources.xml
.idea/dynamic.xml
.idea/uiDesigner.xml
# Gradle:
.idea/gradle.xml
.idea/libraries
# Mongo Explorer plugin:
.idea/mongoSettings.xml
## File-based project format:
*.iws
## Plugin-specific files:
# IntelliJ
/out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
### WebStorm Patch ###
# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
# *.iml
# modules.xml
### NetBeans ###
nbproject/private/
public/build/bundle
nbbuild/
dist/
nbdist/
nbactions.xml
.nb-gradle/
### SublimeText ###
# cache files for sublime text
*.tmlanguage.cache
*.tmPreferences.cache
*.stTheme.cache
# workspace files are user-specific
*.sublime-workspace
# project files should be checked into the repository, unless a significant
# proportion of contributors will probably not be using SublimeText
# *.sublime-project
# sftp configuration file
sftp-config.json
### Vim ###
# swap
[._]*.s[a-w][a-z]
[._]s[a-w][a-z]
# session
Session.vim
# temporary
.netrwhist
*~
# auto-generated tag files
tags
### VS Code ###
.vscode/
### YOHO ###
public/dist/
public/img/sprite.*
public/css/*
public/bundle/*
.eslintcache
*.log.*
nbproject/*
.DS_Store
.devhost
examples/dist/
+22
View File
@@ -0,0 +1,22 @@
import Vue from 'vue';
import JsonViewer from '../';
new Vue({
el: '#app',
render: h => h(JsonViewer, {
domProps: {
id: '123'
},
props: {
value: {
name: [
{name: 2}
],
val: {
a: 1
}
},
showCopy: true
}
})
})
+66
View File
@@ -0,0 +1,66 @@
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './examples/app.js',
output: {
path: path.join(__dirname, '../dist'),
filename: 'main.js'
},
devtool: 'cheap-module-source-map',
devServer: {
port: 8080
},
resolve: {
extensions: ['.js', '.vue'],
alias: {
vue$: 'vue/dist/vue.esm.js'
},
modules: [
path.join(__dirname, '../'),
'node_modules'
]
},
module: {
rules: [
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/
},
{
test: /\.css$/,
use: ['vue-style-loader', 'css-loader', 'autoprefixer-loader']
},
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: 'img/[name].[ext]'
}
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: 'fonts/[name].[ext]'
}
},
{
test: /\.vue$/,
use: [{
loader: 'vue-loader'
}]
}
]
},
plugins: [
new HtmlWebpackPlugin({
filename: 'index.html',
template: './examples/index.html',
inject: true
}),
]
}
+12
View File
@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>examples</title>
</head>
<body>
<div id="app"></div>
</body>
</html>
+6
View File
@@ -0,0 +1,6 @@
import JsonView from './json-viewer';
const install = (Vue) => {
Vue.components('JsonViewer', JsonView);
}
export default Object.assign(JsonView, {install});
+91
View File
@@ -0,0 +1,91 @@
<template>
<div class="node">
<span class="key" v-if="keyName">
<i class="icon" v-if="isObject" :class="{'ion-arrow-down-b': toggle, 'ion-arrow-up-b': !toggle}" @click.stop="toggleNode"></i>
{{keyName}}:
</span>
<commponent :is="`Json${valueType}`" :json-value="value" v-model="toggle" :key-name="keyName"></commponent>
</div>
</template>
<script>
import JsonString from './types/json-string';
import JsonNumber from './types/json-number';
import JsonBoolean from './types/json-boolean';
import JsonObject from './types/json-object';
import JsonArray from './types/json-array';
export default {
name: 'JsonBox',
props: {
value: [Object, Array, String, Number, Boolean],
keyName: String
},
data() {
return {
toggle: true
};
},
methods: {
toggleNode() {
this.toggle = !this.toggle;
}
},
computed: {
valueType() {
if (Array.isArray(this.value)) {
return 'Array';
} else if (typeof this.value === 'object') {
return 'Object';
} else if (typeof this.value === 'number') {
return 'Number';
} else if (typeof this.value === 'string') {
return 'String';
} else if (typeof this.value === 'boolean') {
return 'Boolean';
}
},
isObject() {
return this.valueType == 'Array' || this.valueType == 'Object'; // eslint-disable-line
}
},
components: {
JsonString,
JsonNumber,
JsonBoolean,
JsonObject,
JsonArray
}
};
</script>
<style lang="scss">
.node {
font-size: 14px;
position: relative;
color: #525252;
font-family: Consolas,Menlo,Courier,monospace;
&:after {
content: ','
}
&:last-child {
&:after {
content: ''
}
}
.icon {
position: absolute;
left: -12px;
font-size: 12px;
top: 3px;
color: #80848f;
cursor: pointer;
}
& .node {
margin-left: 25px;
}
}
</style>
+136
View File
@@ -0,0 +1,136 @@
<template>
<div class="json-viewer">
<div class="tooltip">
<i class="icon ion-qr-scanner" @click.native="bigger" v-if="showBigger"></i>
<i class="icon ion-checkmark copied" v-if="copied"></i>
<i class="icon ion-md-clipboard copy" @click.native="clip" v-if="showCopy && !copied"></i>
</div>
<div class="code-box" :class="{'more': moreCode}">
<json-box :value="value" :key-name="keyName"></json-box>
</div>
<div class="more-code" @click="toggleMoreCode">
<i class="icon" :class="{'ion-ios-arrow-up': moreCode, 'ion-ios-arrow-down': !moreCode}"></i>
</div>
</div>
</template>
<script>
import Vue from 'vue';
import JsonBox from './json-box';
import Clipboard from 'clipboard';
Vue.component(JsonBox.name, JsonBox);
export default {
name: 'JsonViewer',
props: {
value: [Object, Array, String, Number, Boolean],
keyName: String,
showCopy: {
type: Boolean,
default: true
},
showBigger: {
type: Boolean,
default: false
}
},
data() {
return {
copied: false,
biggerModal: false,
moreCode: false
};
},
methods: {
clip() {
const clipBoard = new Clipboard('.copy', {
text: () => {
return JSON.stringify(this.$attrs.value, null, 2);
}
});
clipBoard.on('success', () => {
this.copied = true;
setTimeout(() => {
this.copied = false;
}, 2000);
this.$Message.success('Code copied');
clipBoard.destroy();
});
},
bigger() {
this.biggerModal = true;
},
toggleMoreCode() {
this.moreCode = !this.moreCode;
}
}
};
</script>
<style lang="scss">
.json-viewer {
box-sizing: border-box;
border: 1px solid #eee;
border-radius: 6px;
position: relative;
&:hover {
box-shadow:0 2px 7px rgba(0,0,0,.15);border-color:transparent;position:relative
}
.code-box {
height: 300px;
overflow: hidden;
padding: 20px;
&.more {
height: auto;
overflow: auto;
}
}
.more-code {
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
position: absolute;
bottom: 0;
left: 0;
right: 0;
text-align: center;
cursor: pointer;
.icon {
position: relative;
z-index: 2;
}
&:after {
content: "";
width: 100%;
height: 100%;
position: absolute;
bottom: 0;
left: 0;
z-index: 1;
box-shadow: inset 0 -15px 30px #fff;
}
}
.tooltip {
position: absolute;
right: 12px;
top: 5px;
font-size: 18px;
color: #b2b2b2;
cursor: pointer;
.copied {
color: #19be6b;
}
.icon {
margin-left: 5px;
}
}
}
</style>
+55
View File
@@ -0,0 +1,55 @@
{
"name": "vue-json-viewer",
"version": "1.0.0",
"description": "vuejs展示json的组件",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"examples": "webpack-dev-server --config ./examples/build/webpack.dev.conf.js"
},
"repository": {
"type": "git",
"url": "git+https://github.com/chenfengjw163/vue-json-viewer.git"
},
"keywords": [
"vue",
"json"
],
"author": "chenfengjw@hotmail.com",
"license": "ISC",
"bugs": {
"url": "https://github.com/chenfengjw163/vue-json-viewer/issues"
},
"homepage": "https://github.com/chenfengjw163/vue-json-viewer#readme",
"dependencies": {
"vue": "^2.5.2"
},
"devDependencies": {
"autoprefixer": "^7.1.5",
"autoprefixer-loader": "^3.2.0",
"babel-core": "^6.26.0",
"babel-eslint": "^8.0.1",
"babel-loader": "^7.1.2",
"babel-plugin-syntax-dynamic-import": "^6.18.0",
"babel-plugin-transform-object-rest-spread": "^6.26.0",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-preset-es2015": "^6.24.1",
"babel-runtime": "^6.26.0",
"clipboard": "^1.7.1",
"css-loader": "^0.28.7",
"eslint": "^4.9.0",
"eslint-plugin-html": "^4.0.0-alpha.1",
"file-loader": "^1.1.5",
"html-webpack-plugin": "^2.30.1",
"node-sass": "^4.5.3",
"sass-loader": "^6.0.6",
"style-loader": "^0.19.0",
"url-loader": "^0.6.2",
"vue-loader": "^13.3.0",
"vue-style-loader": "^3.0.3",
"vue-template-compiler": "^2.5.2",
"webpack": "^3.8.1",
"webpack-dev-server": "^2.9.2",
"webpack-merge": "^4.1.0"
}
}
+31
View File
@@ -0,0 +1,31 @@
<template>
<span>
<i v-if="!keyName" class="icon" :class="{'ion-arrow-down-b': value, 'ion-arrow-up-b': !value}" @click.stop="toggle"></i>
<span>[</span>
<template v-if="jsonValue.length">
<json-box v-show="value" v-for="(val, index) in jsonValue" :key="index" :value="val"></json-box>
<span v-show="!value" class="node-ellipsis">...</span>
</template>
<span>]</span>
</span>
</template>
<script>
export default {
name: 'JsonArray',
props: {
jsonValue: Array,
keyName: String,
value: Boolean
},
methods: {
toggle() {
this.$emit('input', !this.value);
}
}
};
</script>
<style>
</style>
+18
View File
@@ -0,0 +1,18 @@
<template>
<span class="json-boolean">{{jsonValue}}</span>
</template>
<script>
export default {
name: 'JsonBoolean',
props: {
jsonValue: Boolean
}
};
</script>
<style lang="scss">
.json-boolean {
color: #fc1e70;
}
</style>
+18
View File
@@ -0,0 +1,18 @@
<template>
<span class="json-number">{{jsonValue}}</span>
</template>
<script>
export default {
name: 'JsonNumber',
props: {
jsonValue: Number
}
};
</script>
<style lang="scss">
.json-number {
color: #fc1e70;
}
</style>
+32
View File
@@ -0,0 +1,32 @@
<template>
<span>
<i v-if="!keyName" class="icon" :class="{'ion-arrow-down-b': value, 'ion-arrow-up-b': !value}" @click.stop="toggle"></i>
<span>{</span>
<template v-if="Object.keys(jsonValue).length">
<json-box v-show="value" v-for="(v, k) in jsonValue" :key="k" :key-name="k" :value="v"></json-box>
<span v-show="!value" class="node-ellipsis">...</span>
</template>
<span>}</span>
</span>
</template>
<script>
export default {
name: 'JsonObject',
props: {
jsonValue: Object,
keyName: String,
value: Boolean
},
methods: {
toggle() {
console.log('toggle')
this.$emit('input', !this.value);
}
}
};
</script>
<style>
</style>
+18
View File
@@ -0,0 +1,18 @@
<template>
<span class="json-string">"{{jsonValue}}"</span>
</template>
<script>
export default {
name: 'JsonString',
props: {
jsonValue: String
}
};
</script>
<style lang="scss">
.json-string {
color: #42b983;
}
</style>
+5388
View File
File diff suppressed because it is too large Load Diff