Added Swagger
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
import keywordMap from "./keyword-map"
|
||||
import getKeywordsForPath from "./get-keywords-for-path"
|
||||
|
||||
export default function getCompletions(editor, session, pos, prefix, cb, ctx, system) {
|
||||
|
||||
const { fn: { getPathForPosition }, specSelectors } = system
|
||||
|
||||
const { isOAS3 } = specSelectors
|
||||
|
||||
if(isOAS3 && isOAS3()) {
|
||||
// isOAS3 selector exists, and returns true
|
||||
return cb(null, null)
|
||||
}
|
||||
|
||||
const { AST } = ctx
|
||||
var editorValue = editor.getValue()
|
||||
const path = getPathForPosition({ pos, prefix, editorValue, AST})
|
||||
|
||||
const suggestions = getKeywordsForPath({ system, path, keywordMap })
|
||||
cb(null, suggestions)
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
import isArray from "lodash/isArray"
|
||||
import isObject from "lodash/isObject"
|
||||
import mapValues from "lodash/mapValues"
|
||||
import isPlainObject from "lodash/isPlainObject"
|
||||
import toArray from "lodash/toArray"
|
||||
import isString from "lodash/isString"
|
||||
import get from "lodash/get"
|
||||
|
||||
export default function getKeywordsForPath({ system, path, keywordMap }) {
|
||||
keywordMap = Object.assign({}, keywordMap)
|
||||
|
||||
// is getting path was not successful stop here and return no candidates
|
||||
if (!isArray(path)) {
|
||||
return [
|
||||
{
|
||||
name: "array",
|
||||
value: " ",
|
||||
score: 300,
|
||||
meta: "Couldn't load suggestions"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
if(path[path.length - 2] === "tags" && path.length > 2) {
|
||||
// 'path.length > 2' excludes top-level 'tags'
|
||||
return system.specSelectors.tags().map(tag => ({
|
||||
score: 0,
|
||||
meta: "local",
|
||||
value: tag.get("name"),
|
||||
})).toJS()
|
||||
}
|
||||
|
||||
let reversePath = path.slice(0).reverse()
|
||||
if(reversePath[1] === "security" && isNumeric(reversePath[0])) {
|
||||
// **.security[x]
|
||||
return system.specSelectors.securityDefinitions().keySeq().map(sec => ({
|
||||
score: 0,
|
||||
meta: "local",
|
||||
caption: sec,
|
||||
snippet: `${sec}: []`
|
||||
})).toJS()
|
||||
}
|
||||
|
||||
if(reversePath[0] === "security") {
|
||||
// **.security:
|
||||
return system.specSelectors.securityDefinitions().keySeq().map(sec => ({
|
||||
score: 0,
|
||||
meta: "local",
|
||||
caption: sec,
|
||||
snippet: `\n- ${sec}: []`
|
||||
})).toJS()
|
||||
}
|
||||
|
||||
// traverse down the keywordMap for each key in the path until there is
|
||||
// no key in the path
|
||||
|
||||
var key = path.shift()
|
||||
|
||||
while (key && isObject(keywordMap)) {
|
||||
keywordMap = getChild(keywordMap, key)
|
||||
key = path.shift()
|
||||
}
|
||||
|
||||
// if no keywordMap was found after the traversal return no candidates
|
||||
if (!isObject(keywordMap)) {
|
||||
return []
|
||||
}
|
||||
|
||||
// if keywordMap is an array of strings, return the array as list of
|
||||
// suggestions
|
||||
if (isArray(keywordMap) && keywordMap.every(isString)) {
|
||||
return keywordMap.map(constructAceCompletion.bind(null, "value"))
|
||||
}
|
||||
|
||||
// If keywordMap is describing an array unwrap the inner map so we can
|
||||
// suggest for array items
|
||||
if (isArray(keywordMap)) {
|
||||
if(isArray(keywordMap[0])) {
|
||||
return keywordMap[0].map(item => {
|
||||
return {
|
||||
name: "array",
|
||||
value: "- " + item,
|
||||
score: 300,
|
||||
meta: "array item"
|
||||
}
|
||||
})
|
||||
} else {
|
||||
return [{
|
||||
name: "array",
|
||||
value: "- ",
|
||||
score: 300,
|
||||
meta: "array item"
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
// if keywordMap is not an object at this point return no candidates
|
||||
if (!isObject(keywordMap)) {
|
||||
return []
|
||||
}
|
||||
|
||||
// for each key in keywordMap map construct a completion candidate and
|
||||
// return the array
|
||||
return suggestionFromSchema(keywordMap)
|
||||
}
|
||||
|
||||
function getChild(object, key) {
|
||||
var keys = Object.keys(object)
|
||||
var regex
|
||||
var isArrayAccess = /^\d+$/.test(key)
|
||||
|
||||
if(isArrayAccess && isArray(object)) {
|
||||
return object[0]
|
||||
}
|
||||
|
||||
for (var i = 0; i < keys.length; i++) {
|
||||
let childVal = object[keys[i]]
|
||||
|
||||
if(!childVal) {
|
||||
return null
|
||||
}
|
||||
|
||||
regex = new RegExp(childVal.__regex || keys[i])
|
||||
|
||||
if (regex.test(key) && childVal) {
|
||||
if(typeof childVal === "object" && !isArray(childVal)) {
|
||||
return Object.assign({}, childVal)
|
||||
} else {
|
||||
return childVal
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function suggestionFromSchema(map) {
|
||||
const res = toArray(mapValues(map, (val, key) => {
|
||||
const keyword = get(val, "__value", key)
|
||||
const meta = isPlainObject(val) ? "object" : "keyword"
|
||||
|
||||
return constructAceCompletion(meta, keyword)
|
||||
}))
|
||||
return res
|
||||
}
|
||||
|
||||
function constructAceCompletion(meta, keyword) {
|
||||
if(keyword.slice(0, 2) === "__") {
|
||||
return {}
|
||||
}
|
||||
|
||||
// Give keywords, that extra colon
|
||||
let snippet
|
||||
switch(meta) {
|
||||
case "keyword":
|
||||
snippet = `${keyword}: `
|
||||
break
|
||||
case "object":
|
||||
snippet = `${keyword}:\n `
|
||||
break
|
||||
default:
|
||||
snippet = keyword
|
||||
}
|
||||
|
||||
// snippet's treat `$` as special characters
|
||||
snippet = snippet.replace("$", "\\$")
|
||||
|
||||
return {
|
||||
snippet,
|
||||
caption: keyword,
|
||||
score: 300,
|
||||
meta,
|
||||
}
|
||||
}
|
||||
|
||||
function isNumeric(obj) {
|
||||
return !isNaN(obj)
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import * as wrapActions from "./wrap-actions"
|
||||
|
||||
export default function EditorAutosuggestKeywordsPlugin() {
|
||||
return {
|
||||
statePlugins: {
|
||||
editor: {
|
||||
wrapActions,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,265 @@
|
||||
|
||||
var Bool = ["true", "false"]
|
||||
var Anything = String
|
||||
|
||||
var combine = (...objs) => objs ? Object.assign({}, ...objs) : {}
|
||||
|
||||
var makeValue = (val = "") => {
|
||||
return {
|
||||
__value: val
|
||||
}
|
||||
}
|
||||
|
||||
var emptyValue = makeValue("")
|
||||
|
||||
var externalDocs = {
|
||||
description: String,
|
||||
url: String
|
||||
}
|
||||
|
||||
|
||||
var xml = {
|
||||
name: String,
|
||||
namespace: String,
|
||||
prefix: String,
|
||||
attribute: Bool,
|
||||
wrapped: Bool
|
||||
}
|
||||
|
||||
var schema = {
|
||||
$ref: String,
|
||||
format: String,
|
||||
title: String,
|
||||
description: String,
|
||||
default: String,
|
||||
maximum: Number,
|
||||
minimum: Number,
|
||||
exclusiveMaximum: Bool,
|
||||
exclusiveMinimum: Bool,
|
||||
maxLength: Number,
|
||||
minLength: Number,
|
||||
pattern: String,
|
||||
maxItems: Number,
|
||||
minItems: Number,
|
||||
uniqueItems: Bool,
|
||||
enum: [String],
|
||||
multipleOf: Number,
|
||||
maxProperties: Number,
|
||||
minProperties: Number,
|
||||
required: [String],
|
||||
type: ["string", "number", "integer", "boolean", "array", "object"],
|
||||
get items () { return this },
|
||||
get allOf () { return [this] },
|
||||
get properties () {
|
||||
return {
|
||||
".": this
|
||||
}
|
||||
},
|
||||
get additionalProperties () { return this },
|
||||
discriminator: String,
|
||||
readOnly: Bool,
|
||||
xml: xml,
|
||||
externalDocs: externalDocs,
|
||||
example: String
|
||||
}
|
||||
|
||||
var schemes = [
|
||||
"http",
|
||||
"https",
|
||||
"ws",
|
||||
"wss"
|
||||
]
|
||||
|
||||
var items = {
|
||||
type: ["string", "number", "integer", "boolean", "array"],
|
||||
format: String,
|
||||
get items () { return this },
|
||||
collectionFormat: ["csv"],
|
||||
default: Anything,
|
||||
minimum: String,
|
||||
maximum: String,
|
||||
exclusiveMinimum: Bool,
|
||||
exclusiveMaximum: Bool,
|
||||
minLength: String,
|
||||
maxLength: String,
|
||||
pattern: String,
|
||||
minItems: String,
|
||||
maxItems: String,
|
||||
uniqueItems: Bool,
|
||||
enum: [Anything],
|
||||
multipleOf: String
|
||||
}
|
||||
|
||||
var header = {
|
||||
description: String,
|
||||
type: String,
|
||||
format: String,
|
||||
items: items,
|
||||
collectionFormat: ["csv"],
|
||||
default: Anything,
|
||||
enum: [String],
|
||||
minimum: String,
|
||||
maximum: String,
|
||||
exclusiveMinimum: Bool,
|
||||
exclusiveMaximum: Bool,
|
||||
multipleOf: String,
|
||||
maxLength: String,
|
||||
minLength: String,
|
||||
pattern: String,
|
||||
minItems: String,
|
||||
maxItems: String,
|
||||
uniqueItems: Bool
|
||||
}
|
||||
|
||||
var parameter = {
|
||||
name: String,
|
||||
description: String,
|
||||
required: ["true", "false"],
|
||||
type: [
|
||||
"string",
|
||||
"number",
|
||||
"boolean",
|
||||
"integer",
|
||||
"array",
|
||||
"file"
|
||||
],
|
||||
format: String,
|
||||
schema: schema,
|
||||
enum: [String],
|
||||
minimum: String,
|
||||
maximum: String,
|
||||
exclusiveMinimum: Bool,
|
||||
exclusiveMaximum: Bool,
|
||||
multipleOf: String,
|
||||
maxLength: String,
|
||||
minLength: String,
|
||||
pattern: String,
|
||||
minItems: String,
|
||||
maxItems: String,
|
||||
uniqueItems: Bool,
|
||||
allowEmptyValue: Bool,
|
||||
collectionFormat: ["csv", "multi"],
|
||||
default: String,
|
||||
items: items,
|
||||
in: [
|
||||
"body",
|
||||
"formData",
|
||||
"header",
|
||||
"path",
|
||||
"query"
|
||||
]
|
||||
}
|
||||
|
||||
var reference = {
|
||||
"$ref": String
|
||||
}
|
||||
|
||||
var response = {
|
||||
description: String,
|
||||
schema: schema,
|
||||
headers: {
|
||||
".": combine(header, {
|
||||
__value: ""
|
||||
})
|
||||
},
|
||||
examples: String
|
||||
}
|
||||
|
||||
var operation = {
|
||||
summary: String,
|
||||
description: String,
|
||||
schemes: [schemes],
|
||||
externalDocs: externalDocs,
|
||||
operationId: String,
|
||||
produces: [String],
|
||||
consumes: [String],
|
||||
deprecated: Bool,
|
||||
security: [String],
|
||||
parameters: [combine(reference, parameter)],
|
||||
responses: {
|
||||
"[2-6][0-9][0-9]": combine(reference, response, emptyValue),
|
||||
"default": combine(reference, response)
|
||||
},
|
||||
tags: [String]
|
||||
}
|
||||
|
||||
var securityScheme = {
|
||||
type: ["oauth2", "apiKey", "basic"],
|
||||
description: String,
|
||||
name: String,
|
||||
in: ["query", "header"],
|
||||
flow: ["implicit", "password", "application", "accessCode"],
|
||||
authorizationUrl: String,
|
||||
tokenUrl: String,
|
||||
scopes: String // actually an object, but this is equivalent
|
||||
}
|
||||
|
||||
var info = {
|
||||
version: String,
|
||||
title: String,
|
||||
description: String,
|
||||
termsOfService: String,
|
||||
contact: {
|
||||
name: String,
|
||||
url: String,
|
||||
email: String
|
||||
},
|
||||
license: {
|
||||
name: String,
|
||||
url: String
|
||||
}
|
||||
}
|
||||
|
||||
var map = {
|
||||
swagger: ["\'2.0\'"],
|
||||
info: info,
|
||||
|
||||
host: String,
|
||||
basePath: String,
|
||||
|
||||
schemes: [schemes],
|
||||
produces: [String],
|
||||
consumes: [String],
|
||||
|
||||
paths: {
|
||||
|
||||
//path
|
||||
".": {
|
||||
__value: "",
|
||||
parameters: [combine(reference, parameter)],
|
||||
"get": operation,
|
||||
"put": operation,
|
||||
"post": operation,
|
||||
"delete": operation,
|
||||
"options": operation,
|
||||
"head": operation,
|
||||
"patch": operation,
|
||||
"$ref": String
|
||||
}
|
||||
},
|
||||
|
||||
definitions: {
|
||||
|
||||
// Definition name
|
||||
".": combine(schema, emptyValue)
|
||||
},
|
||||
|
||||
parameters: {
|
||||
".": combine(reference, parameter, emptyValue)
|
||||
},
|
||||
responses: {
|
||||
"[2-6][0-9][0-9]": combine(response, emptyValue)
|
||||
},
|
||||
securityDefinitions: {
|
||||
".": combine(securityScheme, emptyValue)
|
||||
},
|
||||
security: [String],
|
||||
tags: [{
|
||||
name: String,
|
||||
description: String,
|
||||
externalDocs: externalDocs
|
||||
}],
|
||||
externalDocs: externalDocs
|
||||
}
|
||||
|
||||
export default map
|
||||
@@ -0,0 +1,11 @@
|
||||
import getCompletions from "./get-completions"
|
||||
|
||||
// Add an autosuggest completer
|
||||
export const addAutosuggestionCompleters = (ori, system) => (context) => {
|
||||
return ori(context).concat([{
|
||||
getCompletions(...args) {
|
||||
// Add `context`, then `system` as the last args
|
||||
return getCompletions(...args, context, system)
|
||||
}
|
||||
}])
|
||||
}
|
||||
Reference in New Issue
Block a user