Skip to content

Commit

Permalink
Fix #35 and prepare 1.3.1
Browse files Browse the repository at this point in the history
  • Loading branch information
kminami committed Sep 11, 2018
1 parent 60d9c30 commit 7f4c66f
Show file tree
Hide file tree
Showing 6 changed files with 140 additions and 100 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "apib2swagger",
"version": "1.3.0",
"version": "1.3.1",
"description": "Convert API Blueprint to Swagger.",
"bin": "./bin/apib2swagger.js",
"scripts": {
Expand Down
14 changes: 7 additions & 7 deletions src/escape_json_pointer.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// RFC 6901
function escapeJSONPointer(input) {
s = input.replace(/~/g, '~0')
return s.replace(/\//g, '~1')
}

module.exports = escapeJSONPointer;
// RFC 6901
function escapeJSONPointer(input) {
s = input.replace(/~/g, '~0')
return s.replace(/\//g, '~1')
}

module.exports = escapeJSONPointer;
184 changes: 92 additions & 92 deletions src/mson_to_json_schema.js
Original file line number Diff line number Diff line change
@@ -1,93 +1,93 @@
var escapeJSONPointer = require('./escape_json_pointer');

function convertMsonToJsonSchema(content) {
// for apib._version = "4.0"
var mson = content.content[0];
if (mson.element === 'array') {
if (!mson.content || mson.content.length === 0) {
return {type: 'array', items: {}};
} else if (mson.content.length === 1) {
return {type: 'array', items: {'$ref': '#/definitions/' + escapeJSONPointer(mson.content[0].element)}};
} else if (mson.content.length > 1) {
var items = [];
for (var i = 0; i < mson.content.length; i++) {
items.push({'$ref': '#/definitions/' + escapeJSONPointer(mson.content[i].element)});
}
return {type: 'array', items: {'anyOf': items}};
}
}
if (mson.element === 'enum') {
return convertEnum(mson.content);
}
if (mson.element !== 'object' && !mson.content) {
return {'$ref': '#/definitions/' + escapeJSONPointer(mson.element)};
}
// object
var schema = {};
schema.type = 'object';
schema.required = [];
schema.properties = {};
for (var j = 0; j < mson.content.length; j++) {
var member = mson.content[j];
if (member.element !== "member") continue;
// MEMO: member.meta.description
if (member.content.value.element === 'array') {
// TODO: use member.content.value.content (schema for items)
schema.properties[member.content.key.content] = {type: 'array', items: {}};
} else if (member.content.value.element === 'enum') {
var body = {type: member.content.key.element};
body.enum = member.content.value.content.map(function(a) {
return a.content;
});
schema.properties[member.content.key.content] = body;
} else {
schema.properties[member.content.key.content] = {type: member.content.value.element};
}
if (!member.attributes || !member.attributes.typeAttributes) continue;
for (var k = 0; k < member.attributes.typeAttributes.length; k++) {
if (member.attributes.typeAttributes[k] === "fixedType") {
// handle when we have attributes containing objects
if (member.content.value.element === 'array'){
schema.properties[member.content.key.content] = {
'type': "array",
'items': {
'$ref': '#/definitions/' + escapeJSONPointer(member.content.value.content[0].element)
}
};
} else {
schema.properties[member.content.key.content] = {'$ref': '#/definitions/' + escapeJSONPointer(member.content.value.element)};
}
}
if (member.attributes.typeAttributes[k] === "required") {
schema.required.push(member.content.key.content);
}
}
}

// According to schema definition, required is a stringArray, which must be non-empty
if (schema.required.length === 0) {
delete schema.required
}

if (mson.element !== 'object') {
return {'allOf': [{'$ref':'#/definitions/' + escapeJSONPointer(mson.element)}, schema]};
}

return schema;
}

function convertEnum(contents) {
var schema = {type: '', enum: []};
for (var i = 0; i < contents.length; i++) {
var content = contents[i];
if (!schema.type) {
schema.type = content.element;
} else if (schema.type != content.element) {
// WARN!! mixed type enum
}
schema.enum.push(content.content);
}
return schema;
}

var escapeJSONPointer = require('./escape_json_pointer');

function convertMsonToJsonSchema(content) {
// for apib._version = "4.0"
var mson = content.content[0];
if (mson.element === 'array') {
if (!mson.content || mson.content.length === 0) {
return {type: 'array', items: {}};
} else if (mson.content.length === 1) {
return {type: 'array', items: {'$ref': '#/definitions/' + escapeJSONPointer(mson.content[0].element)}};
} else if (mson.content.length > 1) {
var items = [];
for (var i = 0; i < mson.content.length; i++) {
items.push({'$ref': '#/definitions/' + escapeJSONPointer(mson.content[i].element)});
}
return {type: 'array', items: {'anyOf': items}};
}
}
if (mson.element === 'enum') {
return convertEnum(mson.content);
}
if (mson.element !== 'object' && !mson.content) {
return {'$ref': '#/definitions/' + escapeJSONPointer(mson.element)};
}
// object
var schema = {};
schema.type = 'object';
schema.required = [];
schema.properties = {};
for (var j = 0; mson.content && j < mson.content.length; j++) {
var member = mson.content[j];
if (member.element !== "member") continue;
// MEMO: member.meta.description
if (member.content.value.element === 'array') {
// TODO: use member.content.value.content (schema for items)
schema.properties[member.content.key.content] = {type: 'array', items: {}};
} else if (member.content.value.element === 'enum') {
var body = {type: member.content.key.element};
body.enum = member.content.value.content.map(function(a) {
return a.content;
});
schema.properties[member.content.key.content] = body;
} else {
schema.properties[member.content.key.content] = {type: member.content.value.element};
}
if (!member.attributes || !member.attributes.typeAttributes) continue;
for (var k = 0; k < member.attributes.typeAttributes.length; k++) {
if (member.attributes.typeAttributes[k] === "fixedType") {
// handle when we have attributes containing objects
if (member.content.value.element === 'array'){
schema.properties[member.content.key.content] = {
'type': "array",
'items': {
'$ref': '#/definitions/' + escapeJSONPointer(member.content.value.content[0].element)
}
};
} else {
schema.properties[member.content.key.content] = {'$ref': '#/definitions/' + escapeJSONPointer(member.content.value.element)};
}
}
if (member.attributes.typeAttributes[k] === "required") {
schema.required.push(member.content.key.content);
}
}
}

// According to schema definition, required is a stringArray, which must be non-empty
if (schema.required.length === 0) {
delete schema.required
}

if (mson.element !== 'object') {
return {'allOf': [{'$ref':'#/definitions/' + escapeJSONPointer(mson.element)}, schema]};
}

return schema;
}

function convertEnum(contents) {
var schema = {type: '', enum: []};
for (var i = 0; i < contents.length; i++) {
var content = contents[i];
if (!schema.type) {
schema.type = content.element;
} else if (schema.type != content.element) {
// WARN!! mixed type enum
}
schema.enum.push(content.content);
}
return schema;
}

module.exports = convertMsonToJsonSchema;
8 changes: 8 additions & 0 deletions test/input/Issue-#35.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
FORMAT: 1A

# Data Structures

# some category of data structures
## Config
+ alice (string, required) - information about alice
+ bob (string, required) - information about bob
31 changes: 31 additions & 0 deletions test/output/Issue-#35.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"swagger": "2.0",
"info": {
"title": "",
"version": "",
"description": ""
},
"paths": {},
"definitions": {
"some category of data structures": {
"type": "object",
"properties": {}
},
"Config": {
"type": "object",
"required": [
"alice",
"bob"
],
"properties": {
"alice": {
"type": "string"
},
"bob": {
"type": "string"
}
}
}
},
"tags": []
}
1 change: 1 addition & 0 deletions test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ var remote = 'https://raw.githubusercontent.com/apiaryio/api-blueprint/format-1A
'Issue-#26.md',
'Issue-#29.md',
'Issue-#33.md',
'Issue-#35.md',
'apiblueprint_uber.md',
'apiblueprint_valid_simple.md'
];
Expand Down

0 comments on commit 7f4c66f

Please sign in to comment.