From 73ed3b6463ee474afd5f6e371bac43128a4d1351 Mon Sep 17 00:00:00 2001 From: "gaoxiaolin.gao" Date: Tue, 6 Mar 2018 11:35:09 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=E5=AF=BC=E5=87=BAsch?= =?UTF-8?q?ema=20table?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- a.markdown | 76 +++++++++ client/components/SchemaTable/SchemaTable.js | 64 ++----- .../Project/Interface/InterfaceList/View.js | 48 ++++-- common/markdown.js | 158 +++++++++++++++++- common/shema-transformTo-table.js | 63 ++++--- exts/yapi-plugin-export-data/controller.js | 6 +- 6 files changed, 328 insertions(+), 87 deletions(-) create mode 100644 a.markdown diff --git a/a.markdown b/a.markdown new file mode 100644 index 00000000..ce16c097 --- /dev/null +++ b/a.markdown @@ -0,0 +1,76 @@ + +

swagger_test

+ + + +# eeeeeee +[TOC] + + +## 13%0A%3Ca%20id%3D13%3E%20%3C/a%3E +[TOC] + +### 基本信息 + +**Path:** /api/13 + +**Method:** GET + +**接口描述:** + + +### Request +**Query** + +| 参数名称 | 是否必须 | 示例 | 备注 | +| ------------ | ------------ | ------------ | ------------ | +| qqq | 是 | | | +| wwww | 是 | | | +| wwwww | 是 | | | + +### Reponse + + + + + + + + +
名称类型是否必须默认值备注其他信息
idnumber必须The unique identifier for a productfalse,false
namestring必须false,false,false
pricenumber必须false,

最小值: 0

arrstring []非必须bbbbbfalse,false,false,

item 类型: string

tagsobject []非必须

最小数量: 1

,

元素是否都不同: true

,false,

item 类型: object

lengthnumber非必须false,false
widthnumber非必须false,false
heightnumber非必须false,false
dimensionsobject非必须
lengthnumber必须false,false
widthnumber必须false,false
heightnumber必须false,false
+ +## 16%0A%3Ca%20id%3D16%3E%20%3C/a%3E +[TOC] + +### 基本信息 + +**Path:** /api/16 + +**Method:** GET + +**接口描述:** + + +### Request + +### Reponse + + + + + + + + +
名称类型是否必须默认值备注其他信息
successboolean必须

枚举: true,false

dataobject必须
successboolean非必须

枚举: true

dataobject非必须
countnumber非必须false,false
rowsobject []非必须false,false,false,

item 类型: object

namestring必须false,false,false
idstring非必须false,false,false
+# ee +[TOC] + + +# tag +[TOC] + + +# %u545C%u545C%u545C +[TOC] + diff --git a/client/components/SchemaTable/SchemaTable.js b/client/components/SchemaTable/SchemaTable.js index fe1e54e2..3e26dba1 100644 --- a/client/components/SchemaTable/SchemaTable.js +++ b/client/components/SchemaTable/SchemaTable.js @@ -1,5 +1,6 @@ import React, { Component } from 'react'; import { Table } from 'antd'; +import PropTypes from 'prop-types' import { schemaTransformToTable } from '../../../common/shema-transformTo-table.js'; import _ from 'underscore'; @@ -81,57 +82,13 @@ const columns = [ } ]; -const product = { - title: 'Product', - type: 'object', - properties: { - id: { - description: 'The unique identifier for a product', - type: 'number' - }, - name: { - type: 'string' - }, - price: { - type: 'number', - minimum: 0, - exclusiveMinimum: true - }, - arr: { - type: 'array', - items: { - type: 'string', - description: 'bbbbb' - }, - description: 'sdfsdf' - }, - tags: { - type: 'array', - items: { - type: 'object', - properties: { - length: { type: 'number' }, - width: { type: 'number' }, - height: { type: 'number' } - } - }, - minItems: 1, - uniqueItems: true - }, - dimensions: { - type: 'object', - properties: { - length: { type: 'number' }, - width: { type: 'number' }, - height: { type: 'number' } - }, - required: ['length', 'width', 'height'] - } - }, - required: ['id', 'name', 'price'] -}; -export default class SchemaTable extends Component { +class SchemaTable extends Component { + + static propTypes = { + dataSource: PropTypes.string + } + constructor(props) { super(props); this.state = { @@ -140,13 +97,16 @@ export default class SchemaTable extends Component { } componentDidMount() { + let product = JSON.parse(this.props.dataSource) + this.setState({ data: schemaTransformToTable(product) }); } render() { - console.log('data', this.state.data); - return ; + + return
; } } +export default SchemaTable; \ No newline at end of file diff --git a/client/containers/Project/Interface/InterfaceList/View.js b/client/containers/Project/Interface/InterfaceList/View.js index d447defe..8ed2bcf2 100755 --- a/client/containers/Project/Interface/InterfaceList/View.js +++ b/client/containers/Project/Interface/InterfaceList/View.js @@ -10,6 +10,7 @@ import ErrMsg from '../../../../components/ErrMsg/ErrMsg.js'; import variable from '../../../../constants/variable'; import constants from '../../../../constants/variable.js' import copy from 'copy-to-clipboard'; +import SchemaTable from '../../../../components/SchemaTable/SchemaTable.js' const HTTP_METHOD = constants.HTTP_METHOD; @@ -95,12 +96,17 @@ class View extends Component { } } - res_body(res_body_type, res_body) { + res_body(res_body_type, res_body, res_body_is_json_schema) { if (res_body_type === 'json') { - return
- {/*
*/} - -
+ if(res_body_is_json_schema) { + console.log('schema') + return + } else { + return
+ {/*
*/} + +
+ } } else if (res_body_type === 'raw') { return
@@ -108,6 +114,23 @@ class View extends Component { } } + req_body(req_body_type, req_body_other, req_body_is_json_schema) { + + if(req_body_is_json_schema) { + return + } else { + return ( +
+ +
+ ) + } + + } + req_query(query) { const columns = [{ title: '参数名称', @@ -275,9 +298,9 @@ class View extends Component { // statusColor = statusColor[this.props.curData.status?this.props.curData.status.toLowerCase():"undone"]; - const aceEditor =
- -
+ // const aceEditor =
+ // + //
if (!methodColor) methodColor = "get"; let res =
@@ -337,14 +360,19 @@ class View extends Component {

Body:

- {aceEditor} + {/* {aceEditor} { + + } */} + { + this.props.curData.req_body_type ==='form' ? this.req_body_form(this.props.curData.req_body_type, this.props.curData.req_body_form) + : this.req_body(this.props.curData.req_body_type, this.props.curData.req_body_other, this.props.curData.req_body_is_json_schema) }

Response

- {this.res_body(this.props.curData.res_body_type, this.props.curData.res_body)} + {this.res_body(this.props.curData.res_body_type, this.props.curData.res_body, this.props.curData.res_body_is_json_schema)}

备注

{this.props.curData.desc &&
} diff --git a/common/markdown.js b/common/markdown.js index 82d6768a..db62e16a 100644 --- a/common/markdown.js +++ b/common/markdown.js @@ -1,3 +1,52 @@ +const schema = require('./shema-transformTo-table.js') +const _ = require('underscore'); + +const messageMap = { + desc: '备注', + default: '实例', + maximum: '最大值', + minimum: '最小值', + maxItems: '最大数量', + minItems: '最小数量', + maxLength: '最大长度', + minLength: '最小长度', + uniqueItems: '元素是否都不同', + itemType: 'item 类型', + format: '版本', + enum: '枚举' + +} + +const columns = [ + { + title: '名称', + dataIndex: 'name', + key: 'name' + }, { + title: '类型', + dataIndex: 'type', + key: 'type' + }, { + title: '是否必须', + dataIndex: 'required', + key: 'required' + }, + { + title: '默认值', + dataIndex: 'default', + key: 'default' + }, + { + title: '备注', + dataIndex: 'desc', + key: 'desc' + }, + { + title: '其他信息', + dataIndex: 'sub', + key: 'sub' + } + ]; function escapeStr(str, isToc) { return isToc ? escape(str) : str; @@ -62,11 +111,112 @@ function createReqBody(req_body_type, req_body_form, req_body_other) { return ""; } -function createResponse(res_body) { +function tableHeader(columns) { + let header = ``; + columns.map(item => { + header += `
` + }) + + return header +} + +function handleObject (text) { + + if(!_.isObject(text)) { + return text + } + return Object.keys(text || {}).map((item, index) => { + let name = messageMap[item] + let value = text[item] + return( + !_.isUndefined(text[item]) && `

${name}: ${value.toString()}

` + ) + }) +} + +function tableCol(col, columns) { + let tpl = ``; + columns.map( (item ,index)=> { + let dataIndex = item.dataIndex; + let value = col[dataIndex] + value = _.isUndefined(value) ? '': value + let text = ``; + + switch (dataIndex){ + case 'sub': + text = handleObject(value); + break; + case 'type': + text = ( value === 'array' ? `${ col.sub.itemType || ''} []` : `${value}`) + break; + case 'required': + text = value ? '必须': '非必须'; + break; + case 'desc': + text = _.isUndefined(col.childrenDesc)? `${value}` : `${col.childrenDesc}` + break; + default: + text = value + } + // let text = + tpl += `` + }) + + return tpl; +} + +function tableBody(dataSource, columns) { + + // 按照columns的顺序排列数据 + let tpl = ``; + dataSource.map(col => { + let child = null; + if(!_.isUndefined(col.children)&& _.isArray(col.children)) { + + child = tableBody(col.children, columns) + } + tpl +=`${tableCol(col,columns)}` + tpl += child ? `${child}`: `` + + }) + + return tpl; + +} + + +function createSchemaTable(body){ + let template = ``; + let dataSource = schema.schemaTransformToTable(JSON.parse(body)); + template += `
${item.title}${text}
+ + + ${ + tableHeader(columns) + } + + ` + + template += `${tableBody(dataSource, columns)} + +
+ ` + + return template + +} + +function createResponse(res_body, res_body_is_json_schema) { let resTitle = `\n### Reponse\n\n`; if (res_body) { - let resBody = "```javascript" + `\n${res_body || ""}\n` + "```"; - return resTitle + resBody; + if(res_body_is_json_schema) { + let resBody = createSchemaTable(res_body) + return resTitle + resBody; + } else { + let resBody = "```javascript" + `\n${res_body || ""}\n` + "```"; + return resTitle + resBody; + } + } return ""; } @@ -91,7 +241,7 @@ function createInterMarkdown(basepath, listItem, isToc){ mdTemplate += createReqBody(listItem.req_body_type, listItem.req_body_form, listItem.req_body_other); // Response // Response-body - mdTemplate += createResponse(listItem.res_body); + mdTemplate += createResponse(listItem.res_body, listItem.res_body_is_json_schema); return mdTemplate; } diff --git a/common/shema-transformTo-table.js b/common/shema-transformTo-table.js index fa034d10..1c8e150c 100644 --- a/common/shema-transformTo-table.js +++ b/common/shema-transformTo-table.js @@ -1,4 +1,4 @@ -import _ from 'underscore'; +const _ = require('underscore'); exports.schemaTransformToTable = (schema) =>{ try{ @@ -10,18 +10,36 @@ exports.schemaTransformToTable = (schema) =>{ } } + +// 自动添加type + +function checkJsonSchema(json) { + let newJson = Object.assign({}, json) + if (_.isUndefined(json.type) && _.isObject(json.properties) ){ + newJson.type = 'object' + } + // console.log('newJson', newJson) + + return newJson; +} + const mapping = function(data, index) { switch(data.type){ case 'string': return SchemaString(data); + case 'number': return SchemaNumber(data); + case 'array': return SchemaArray(data, index); + case 'object': return SchemaObject(data, index); + case 'boolean': return SchemaBoolean(data); + case 'integer': return SchemaInt(data) default: @@ -38,8 +56,9 @@ const SchemaObject = (data, key) => { let result =[]; Object.keys(properties).map((name, index) => { let value = properties[name]; - let copiedState = JSON.parse(JSON.stringify(value)); - let optionForm = mapping(copiedState, index); + let copiedState = checkJsonSchema(JSON.parse(JSON.stringify(value))); + let optionForm = mapping(copiedState, key+''+index); + let desc = optionForm.desc; let d = optionForm.default; let children = optionForm.children; @@ -49,31 +68,33 @@ const SchemaObject = (data, key) => { delete optionForm.children; let item = { name, - type: value.type, + type: value.type || 'object', required: required.indexOf(name) != -1, sub: optionForm, desc, default: d, key: key+''+index } - + if(value.type === 'array' && !_.isUndefined(children) ){ - + if( _.isArray(children)){ item.children = children } - item = { - ...item, - childrenDesc: children.desc - } + // item = { + // ...item, + // childrenDesc: children.desc + // } + item.childrenDesc = children.desc } - if(value.type === 'object' ){ - item = { - ...item, - children: optionForm - } + if(value.type === 'object'|| _.isUndefined(value.type)){ + // item = { + // ...item, + // children: optionForm + // } + item.children = optionForm delete item.sub } @@ -81,6 +102,8 @@ const SchemaObject = (data, key) => { }) + + return result @@ -100,8 +123,9 @@ const SchemaString = (data) => { const SchemaArray =(data, index) => { data.items = data.items || {type: 'string'}; + let items = checkJsonSchema(data.items) + let optionForm = mapping(items, index); - let optionForm = mapping(data.items, index); let item = { desc: data.description, @@ -109,11 +133,11 @@ const SchemaArray =(data, index) => { minItems: data.minItems, uniqueItems: data.uniqueItems, maxItems: data.maxItems, - itemType: data.items.type, + itemType: items.type, children: optionForm } - return {...item} + return item } const SchemaNumber =(data) => { @@ -142,7 +166,8 @@ const SchemaBoolean = (data) =>{ let item = { desc: data.description, - default: data.default + default: data.default, + enum: data.enum } return item } \ No newline at end of file diff --git a/exts/yapi-plugin-export-data/controller.js b/exts/yapi-plugin-export-data/controller.js index b80ba726..78c20443 100644 --- a/exts/yapi-plugin-export-data/controller.js +++ b/exts/yapi-plugin-export-data/controller.js @@ -69,13 +69,15 @@ class exportController extends baseController { async function createHtml(list) { let md = await createMarkdown.bind(this)(list, true); - let markdown = new markdownIt({ html: true, breaks: true }); + let markdown = markdownIt({ html: true, breaks: true }); markdown.use(markdownItAnchor); // Optional, but makes sense as you really want to link to something markdown.use(markdownItTableOfContents, { markerPattern: /^\[toc\]/im }); - + + require('fs').writeFileSync('./a.markdown', md) let tp = unescape(markdown.render(md)); + let left; // console.log('tp',tp); let content = tp.replace(/[\s\S]*?<\/ul>\s*<\/div>/gi, function (match) {