raml2html-slate-theme
Version:
A raml2html template for rendering RAML to a Slate like layout
186 lines (169 loc) • 6.09 kB
JavaScript
const curlCommandBuilder = require('./curl-command-builder')
/**
* Ensure a string is safe to use as a html id attribute
* @param {string} id The potentially unsafe id string
* @return {string} The safe id string
*/
function getSafeId (id) {
if (id === undefined) id = ''
return id.toLowerCase().replace(/ /g, '-')
}
/**
* Check whether the given array contains an element with an
* examples attribute
* @param {array<object>} data An array of RAML nodes (methods, parameters)
* @return {boolean}
*/
function hasExamples (data) {
if (!Array.isArray(data)) return false
return data.reduce((current, item) => current || (Boolean(item.examples) && item.examples.length > 0), false)
}
/**
* Get all unique response headers of a method
* Only the first instance of a header will be returned
* @param {object} method A method object as found in a parsed RAML file
* @return {array} An array of header objects
*/
function getResponseHeaders (method) {
if (!method || !method.responses) return []
return method.responses
.map((resp) => resp.headers ? resp.headers : [])
.reduce((current, resp) => current.concat(resp), [])
.filter((header, index, array) => array.findIndex((item) => item.key === header.key) === index)
}
/**
* TODO add tests
* Generate a cURL statement for a method on a resource
* @param {object} securitySchemes A securitySchemes object as generated by RAML
* @param {string} baseUri The baseUri of the API (if any)
* @param {object} method A method object as generated by RAML
* @param {object} resource A resource object as generated by RAML
* @param {boolean} allcommands Whether or not to return all curl commands, or just the first
* @return {string} A example curl statement that calls the API
*/
function getCurlStatement (securitySchemes, baseUri, method, resource, allCommands) {
baseUri = baseUri || ''
if (baseUri.endsWith('/')) baseUri = baseUri.slice(0, -1)
method.headers = method.headers || []
method.queryParameters = method.queryParameters || []
method.method = method.method || 'get'
const payload = ['patch', 'post', 'put'].includes(method.method) ? ' \\\n\t-d @request_body' : ''
const parentUrl = resource.parentUrl || ''
const relativeUri = resource.relativeUri || '/'
const headers = method.headers
.filter((header) => header.examples && header.examples.length !== 0)
.map((header) => `-H "${header.key}: ${header.examples[0].value}"`)
const params = method.queryParameters
.filter((param) => param.examples && param.examples.length !== 0)
.map((param) => `${param.key}=${param.examples[0].value}`)
const methodParams = {
method: method.method,
baseUri: baseUri,
path: `${parentUrl}${relativeUri}`,
params: params,
headers: headers,
payload: payload,
securedBy: method.securedBy
}
let commands = curlCommandBuilder.forMethod(methodParams, securitySchemes)
if (!allCommands) { commands = commands.slice(0, 1) }
return commands.join('\n\n or \n\n')
}
/**
* Return a short string for use in the language tabs based on the input mime type
* @param {string} mime A mime type
* @return {string} A short version of the mime type we can use in a css classname
*/
function getLanguage (mime) {
if (/json/.test(mime)) {
return 'json'
} else if (/xml/.test(mime)) {
return 'xml'
} else if (mime === 'text/event-stream') {
return 'sse'
} else {
return ''
}
}
/**
* Parses a ramlObj and returns an object containing the top level type definitions
* Takes care of the differences between the legacy `schemas` and new `types` attributes
* return the same structure regardless of which attributes are used in the input
* @this {object} The nunjucks global, which has a ctx (context) attribute that is the current ramlObj
* @return {array} An array containing the top level schemas with some meta data
*/
function getTypeDefinitions () {
const ramlObj = this.ctx || {}
// The new `types` property is prefered
if (ramlObj.types) {
return Object.keys(ramlObj.types)
.map((item) => ramlObj.types[item])
.map((item) => item.typePropertyKind === 'TYPE_EXPRESSION'
? typeToJson(item)
: item
)
}
if (ramlObj.schemas) {
return ramlObj.schemas
.map((item) => item[Object.keys(item)[0]])
.map((item) => {
if (item.typePropertyKind === 'TYPE_EXPRESSION') return typeToJson(item)
item.content = item.type
item.type = 'json'
return item
})
}
return []
}
/**
* Convert a TYPE_EXPRESSION into a shape that resembles a JSON schema
* @param {object} type A TYPE_EXPRESSION from a raml type or schema
* @return {object} A TYPE_EXPRESSION enriched with a json schema-like key
*/
function typeToJson (type) {
const content = JSON.stringify({
name: type.name,
type: type.type,
description: type.description,
properties: type.properties
}, null, 2)
type.content = content
return type
}
/**
* Test whether the current ramlObject has a type specified
* Accounts for depecrated schema and new type attributes
* @param {object} item A raml item
* @return {Boolean}
*/
function hasType (item) {
item = item || {}
return Boolean(item.type) || Boolean(item.schema)
}
/**
* Returns the type property from a ramlObject
* Accounts for depecrated schema and new type atttributes. A type is prefered
* over a schema
* Will return a common structure regardless of the input
* @param {object} item A ramlObject with an associated schema or type
* @return {object} The schema or type
*/
function getType (item) {
item = item || {}
let output = item.type || item.schema
if (!output) return ''
if (Array.isArray(output)) output = output[0]
if (typeof output !== 'string') output = JSON.stringify(output, null, 2)
return output
}
module.exports = {
getCurlStatement,
getLanguage,
getResponseHeaders,
getSafeId,
hasExamples,
getTypeDefinitions,
hasType,
getType
}