Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
168 changes: 75 additions & 93 deletions dist/swagger-editor-bundle.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/swagger-editor-bundle.js.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

26 changes: 13 additions & 13 deletions dist/swagger-editor-standalone-preset.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/swagger-editor-standalone-preset.js.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dist/swagger-editor.css

Large diffs are not rendered by default.

12 changes: 6 additions & 6 deletions dist/swagger-editor.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/swagger-editor.js.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 13 additions & 9 deletions dist/validation.worker.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/validation.worker.js.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
"lint": "eslint --cache --ext '.js,.jsx' src test",
"lint-errors": "eslint --cache --quiet --ext '.js,.jsx' src test",
"lint-fix": "eslint --cache --ext '.js,.jsx' src test --fix",
"test": "npm run lint-errors && npm run just-test-in-node",
"test": "npm run just-test-in-node && npm run lint-errors",
"test-in-node": "npm run lint-errors && npm run just-test-in-node",
"just-test": "karma start --config karma.conf.js",
"just-test-in-node": "mocha --recursive --compilers js:babel-core/register test",
Expand All @@ -40,14 +40,14 @@
"watch": "webpack --config ./webpack-dist.config.js --watch --progress"
},
"dependencies": {
"ajv": "^5.2.2",
"boron": "^0.2.3",
"bowser": "1.6.1",
"classnames": "^2.1.3",
"core-js": "^2.4.1",
"immutable": "^3.x.x",
"js-yaml": "^3.5.5",
"json-beautify": "^1.0.1",
"jsonschema": "^1.1.0",
"react": "^15.x",
"react-addons-css-transition-group": "^15.4.2",
"react-dd-menu": "^2.0.0",
Expand All @@ -57,7 +57,7 @@
"react-transition-group": "^1.1.1",
"redux": "^3.x.x",
"swagger-client": "3.0.19",
"swagger-ui": "3.0.21",
"swagger-ui": "swagger-api/swagger-ui#ft/oas3",
"whatwg-fetch": "^2.0.3"
},
"devDependencies": {
Expand Down
2 changes: 2 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import ValidationApiPlugin from "./plugins/validation/apis"
import EditorAutosuggestPlugin from "./plugins/editor-autosuggest"
import EditorAutosuggestSnippetsPlugin from "./plugins/editor-autosuggest-snippets"
import EditorAutosuggestKeywordsPlugin from "./plugins/editor-autosuggest-keywords"
import EditorAutosuggestOAS3KeywordsPlugin from "./plugins/editor-autosuggest-oas3-keywords"
import EditorAutosuggestRefsPlugin from "./plugins/editor-autosuggest-refs"

// eslint-disable-next-line no-undef
Expand All @@ -26,6 +27,7 @@ const plugins = {
EditorAutosuggestSnippetsPlugin,
EditorAutosuggestKeywordsPlugin,
EditorAutosuggestRefsPlugin,
EditorAutosuggestOAS3KeywordsPlugin,
}

const defaults = {
Expand Down
10 changes: 9 additions & 1 deletion src/plugins/editor-autosuggest-keywords/get-completions.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,15 @@ import getKeywordsForPath from "./get-keywords-for-path"

export default function getCompletions(editor, session, pos, prefix, cb, ctx, system) {

const { fn: { getPathForPosition } } = 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})
Expand Down
21 changes: 21 additions & 0 deletions src/plugins/editor-autosuggest-oas3-keywords/get-completions.js
Original file line number Diff line number Diff line change
@@ -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 false
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)
}
170 changes: 170 additions & 0 deletions src/plugins/editor-autosuggest-oas3-keywords/get-keywords-for-path.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
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"

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]]
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 = val.__value === undefined ? key : val.__value
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)
}
11 changes: 11 additions & 0 deletions src/plugins/editor-autosuggest-oas3-keywords/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import * as wrapActions from "./wrap-actions"

export default function EditorAutosuggestOAS3KeywordsPlugin() {
return {
statePlugins: {
editor: {
wrapActions,
}
}
}
}
20 changes: 20 additions & 0 deletions src/plugins/editor-autosuggest-oas3-keywords/keyword-map.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import {
ExternalDocumentation,
Info,
SecurityRequirement,
Server,
Tag,
Components,
Paths
} from "./oas3-objects.js"

export default {
openapi: String,
info: Info,
servers: [Server],
paths: Paths,
components: Components,
security: [SecurityRequirement],
tags: [Tag],
externalDocs: ExternalDocumentation
}
Loading