text: 'use strict';
  
  const path = require('path');
  const util = require('util');
  const up = require('url');
  
  const yaml = require('js-yaml');
  const safejson = require('safe-json-stringify');
  const uri = require('urijs');
  const URITemplate = require('urijs/src/URITemplate');
  const dot = require('dot');
  dot.templateSettings.strip = false;
  dot.templateSettings.varname = 'data';
  
  const xml = require('jgexml/json2xml.js');
  const jptr = require('reftools/lib/jptr.js').jptr;
  const dereference = require('reftools/lib/dereference.js').dereference;
  const clone = require('reftools/lib/clone.js').clone;
  const swagger2openapi = require('swagger2openapi');
  
  const common = require('./common.js');
  
  let templates;
  
  function convertToToc(source,data) {
      let resources = {};
      resources[data.translations.defaultTag] = { count: 0, methods: {} };
      if (source.tags) {
          for (let tag of source.tags) {
              resources[tag.name] = { count: 0, methods: {}, description: tag.description, externalDocs: tag.externalDocs };
          }
      }
      for (var p in source.paths) {
          for (var m in source.paths[p]) {
              if ((m !== 'parameters') && (m !== 'summary') && (m !== 'description') && (!m.startsWith('x-'))) {
                  var method = {};
                  method.operation = source.paths[p][m];
                  method.pathItem = source.paths[p];
                  method.verb = m;
                  method.path = p;
                  method.pathParameters = source.paths[p].parameters;
                  var sMethodUniqueName = (method.operation.operationId ? method.operation.operationId : m + '_' + p).split('/').join('_');
                  if (data.options.tocSummary && method.operation.summary) {
                      sMethodUniqueName = method.operation.summary;
                  }
                  method.slug = sMethodUniqueName.toLowerCase().split(' ').join('-'); // TODO {, } and : ?
                  var tagName = data.translations.defaultTag;
                  if (method.operation.tags && method.operation.tags.length > 0) {
                      tagName = getTagGroup(method.operation.tags[0], data.options.tagGroups);
                  }
                  if (!resources[tagName]) {
                      resources[tagName] = { count: 0, methods: {} };
                  }
                  resources[tagName].count++;
                  resources[tagName].methods[sMethodUniqueName] = method;
              }
          }
      }
      for (let r in resources) {
          if (resources[r].count <= 0) delete resources[r];
      }
      return resources;
  }
  
  function getTagGroup(tag, tagGroups){
      if (tagGroups) {
          for (let group of tagGroups) {
              if (group.tags.indexOf(tag) > -1) {
                  return group.title;
              }
          }
      }
      return tag;
  }
  
  function fakeProdCons(data) {
      data.produces = [];
      data.consumes = [];
      data.bodyParameter = {};
      data.bodyParameter.exampleValues = {};
      for (var r in data.operation.responses) {
          var response = data.operation.responses[r];
          for (var prod in response.content) {
              data.produces.push(prod);
          }
      }
      let op = data.method.operation;
      if (op.requestBody) {
          for (var rb in op.requestBody.content) {
              data.consumes.push(rb);
              if (!data.bodyParameter.exampleValues.object) {
                  data.bodyParameter.present = true;
                  data.bodyParameter.contentType = rb;
                  if (op.requestBody["x-widdershins-oldRef"]) {
                      data.bodyParameter.refName = op.requestBody["x-widdershins-oldRef"].replace('#/components/requestBodies/','');
                  }
                  data.bodyParameter.schema = op.requestBody.content[rb].schema;
                  if (op.requestBody.content[rb].examples) {
                      let key = Object.keys(op.requestBody.content[rb].examples)[0];
                      data.bodyParameter.exampleValues.object = op.requestBody.content[rb].examples[key].value;
                      data.bodyParameter.exampleValues.description = op.requestBody.content[rb].examples[key].description;
                  }
                  else {
                      data.bodyParameter.exampleValues.object = common.getSample(op.requestBody.content[rb].schema,data.options,{skipReadOnly:true},data.api);
                  }
                  if (typeof data.bodyParameter.exampleValues.object === 'object') {
                      data.bodyParameter.exampleValues.json = safejson(data.bodyParameter.exampleValues.object,null,2);
                  }
                  else {
                      data.bodyParameter.exampleValues.json = data.bodyParameter.exampleValues.object;
                  }
              }
          }
      }
  }
  
  function getParameters(data) {
  
      function stupidity(varname) {
          let s = encodeURIComponent(varname);
          s = s.split('-').join('%2D');
          s = s.split('$').join('%24');
          s = s.split('.').join('%2E');
          s = s.split('(').join('%28');
          s = s.split(')').join('%29');
          return s;
      }
  
      data.allHeaders = [];
      data.headerParameters = [];
      data.requiredParameters = [];
      let uriTemplateStr = data.method.path.split('/ /').join('/+/');
      let requiredUriTemplateStr = uriTemplateStr;
      var templateVars = {};
  
      if (data.consumes.length) {
          var contentType = {};
          contentType.name = 'Content-Type';
          contentType.type = 'string';
          contentType.in = 'header';
          contentType.exampleValues = {};
          contentType.exampleValues.json = "'" + data.consumes[0] + "'";
          contentType.exampleValues.object = data.consumes[0];
          data.allHeaders.push(contentType);
      }
      if (data.produces.length) {
          var accept = {};
          accept.name = 'Accept';
          accept.type = 'string';
          accept.in = 'header';
          accept.exampleValues = {};
          accept.exampleValues.json = "'" + data.produces[0] + "'";
          accept.exampleValues.object = data.produces[0];
          data.allHeaders.push(accept);
      }
  
      if (!Array.isArray(data.parameters)) data.parameters = [];
      data.longDescs = false;
      for (let param of data.parameters) {
          //var temp = '';
          param.exampleValues = {};
          if (!param.required) param.required = false;
          let pSchema = param.schema;
          if (!pSchema && param.content) {
              pSchema = Object.values(param.content)[0].schema;
          }
          if (pSchema && !param.safeType) {
              param.originalType = pSchema.type;
              param.safeType = pSchema.type || common.inferType(pSchema);
              if (pSchema.format) {
                  param.safeType = param.safeType+'('+pSchema.format+')';
              }
              if ((param.safeType === 'array') && (pSchema.items)) {
                  let itemsType = pSchema.items.type;
                  if (!itemsType) {
                      itemsType = common.inferType(pSchema.items);
                  }
                  param.safeType = 'array['+itemsType+']';
              }
              if (pSchema["x-widdershins-oldRef"]) {
                  let schemaName = pSchema["x-widdershins-oldRef"].replace('#/components/schemas/','');
                  param.safeType = '['+schemaName+'](#schema'+schemaName.toLowerCase()+')';
              }
              if (param.refName) param.safeType = '['+param.refName+'](#schema'+param.refName.toLowerCase()+')';
          }
          if (pSchema) {
              param.exampleValues.object = param.example || param.default || common.getSample(pSchema,data.options,{skipReadOnly:true},data.api);
              if (typeof param.exampleValues.object === 'object') {
                  param.exampleValues.json = safejson(param.exampleValues.object,null,2);
              }
              else {
                  param.exampleValues.json = "'"+param.exampleValues.object+"'";
              }
          }
          if (param.description === 'undefined') { // yes, the string
              param.description = '';
          }
          if ((typeof param.description !== 'undefined') && (typeof param.description === 'string')) {
              param.shortDesc = param.description.split('\n')[0];
              if (param.shortDesc !== param.description) data.longDescs = true;
          }
  
          if (param.in === 'cookie') {
              if (!param.style) param.style = 'form';
              // style prefixes: form
          }
          if (param.in === 'header') {
              if (!param.style) param.style = 'simple';
              data.headerParameters.push(param);
              data.allHeaders.push(param);
          }
          if (param.in === 'path') {
              let template = param.allowReserved ? '{+' : '{';
              // style prefixes: matrix, label, simple
              if (!param.style) param.style = 'simple';
              if (param.style === 'label') template += '.';
              if (param.style === 'matrix') template += ';';
              template += stupidity(param.name);
              template += param.explode ? '*}' : '}';
              uriTemplateStr = uriTemplateStr.split('{'+param.name+'}').join(template);
              requiredUriTemplateStr = requiredUriTemplateStr.split('{'+param.name+'}').join(template);
          }
          if (param.in === 'query') {
              let isFirst = uriTemplateStr.indexOf('{&') < 0;
              // Since RFC6570 doesn't support multiple operators we cannot use (?+ and (&+ for reserved parameters
              let prefix = isFirst ? '{?' : '{&';
              var template = '';
              // style prefixes: form, spaceDelimited, pipeDelimited, deepObject
              if (!param.style) param.style = 'form';
              template += stupidity(param.name);
              template += param.explode ? '*}' : '}';
              uriTemplateStr += (prefix + template);
  
              if (param.required) {
                  let isFirstRequired = requiredUriTemplateStr.indexOf('{?') < 0;
                  let reqPrefix = isFirstRequired ? '{?' : '{&';
                  requiredUriTemplateStr += (reqPrefix + template);
                  data.requiredParameters.push(param);
              }
          }
          templateVars[stupidity(param.name)] = param.exampleValues.object;
      }
  
      let effSecurity;
      let existingAuth = data.allHeaders.find(function(e,i,a){
          return e.name.toLowerCase() === 'authorization';
      });
      if (data.operation.security && data.operation.security.length) {
          effSecurity = Object.keys(data.operation.security[0]);
      }
      else if (data.api.security && data.api.security.length) {
          effSecurity = Object.keys(data.api.security[0]);
      }
      if (effSecurity && effSecurity.length && data.api.components && data.api.components.securitySchemes) {
          for (let ess of effSecurity) {
              if (data.api.components.securitySchemes[ess]) {
                  let secScheme = data.api.components.securitySchemes[ess];
                  if (!existingAuth && ((secScheme.type === 'oauth2') || (secScheme.type === 'openIdConnect') ||
                      ((secScheme.type === 'http') && (secScheme.scheme === 'bearer')))) {
                      let authHeader = {};
                      authHeader.name = 'Authorization';
                      authHeader.type = 'string';
                      authHeader.in = 'header';
                      authHeader.isAuth = true;
                      authHeader.exampleValues = {};
                      authHeader.exampleValues.object = 'Bearer {access-token}';
                      authHeader.exampleValues.json = "'" + authHeader.exampleValues.object + "'";
                      data.allHeaders.push(authHeader);
                  }
                  else if ((secScheme.type === 'apiKey') && (secScheme.in === 'header')) {
                      let authHeader = {};
                      authHeader.name = secScheme.name;
                      authHeader.type = 'string';
                      authHeader.in = 'header';
                      authHeader.isAuth = true;
                      authHeader.exampleValues = {};
                      authHeader.exampleValues.object = 'API_KEY';
                      authHeader.exampleValues.json = "'" + authHeader.exampleValues.object + "'";
                      data.allHeaders.push(authHeader);
                  }
              }
          }
      }
  
      let uriTemplate = new URITemplate(uriTemplateStr);
      let requiredUriTemplate = new URITemplate(requiredUriTemplateStr);
      data.uriExample = uriTemplate.expand(templateVars);
      data.requiredUriExample = requiredUriTemplate.expand(templateVars);
  
      //TODO deconstruct and reconstruct to cope w/ spaceDelimited/pipeDelimited
  
      data.queryString = data.uriExample.substr(data.uriExample.indexOf('?'));
      if (!data.queryString.startsWith('?')) data.queryString = '';
      data.queryString = data.queryString.split('%25').join('%');
      data.requiredQueryString = data.requiredUriExample.substr(data.requiredUriExample.indexOf('?'));
      if (!data.requiredQueryString.startsWith('?')) data.requiredQueryString = '';
      data.requiredQueryString = data.requiredQueryString.split('%25').join('%');
  }
  
  function getBodyParameterExamples(data) {
      let obj = data.bodyParameter.exampleValues.object;
      let content = '';
      let xmlWrap = false;
      if (data.bodyParameter.schema && data.bodyParameter.schema.xml) {
          xmlWrap = data.bodyParameter.schema.xml.name;
      }
      else if (data.bodyParameter.schema && data.bodyParameter.schema["x-widdershins-oldRef"]) {
          xmlWrap = data.bodyParameter.schema["x-widdershins-oldRef"].split('/').pop();
      }
      if (common.doContentType(data.consumes, 'json')) {
          content += '```json\n';
          content += safejson(obj,null,2) + '\n';
          content += '```\n\n';
      }
      if (common.doContentType(data.consumes, 'yaml')) {
          content += '```yaml\n';
          content += yaml.safeDump(obj) + '\n';
          content += '```\n\n';
      }
      if (common.doContentType(data.consumes, 'form')) {
          content += '```yaml\n';
          content += yaml.safeDump(obj) + '\n';
          content += '```\n\n';
      }
      if (common.doContentType(data.consumes, 'xml') && (typeof obj === 'object')) {
          if (xmlWrap) {
              var newObj = {};
              newObj[xmlWrap] = obj;
              obj = newObj;
          }
          content += '```xml\n';
          content += xml.getXml(JSON.parse(safejson(obj)), '@', '', true, '  ', false) + '\n';
          content += '```\n\n';
      }
      return content;
  }
  
  function fakeBodyParameter(data) {
      if (!data.parameters) data.parameters = [];
      let bodyParams = [];
      if (data.bodyParameter.schema) {
          let param = {};
          param.in = 'body';
          param.schema = data.bodyParameter.schema;
          param.name = 'body';
          param.required = data.operation.requestBody.required || false;
          param.description = data.operation.requestBody.description;
          param.refName = data.bodyParameter.refName;
          if (!data.options.omitBody || param.schema["x-widdershins-oldRef"]) {
             bodyParams.push(param);
          }
  
          if ((param.schema.type === 'object') && (data.options.expandBody || (!param.schema["x-widdershins-oldRef"]))) {
              let offset = (data.options.omitBody ? -1 : 0);
              let props = common.schemaToArray(data.bodyParameter.schema,offset,{trim:true},data);
  
              for (let block of props) {
                  for (let prop of block.rows) {
                      let param = {};
                      param.in = 'body';
                      param.schema = prop.schema;
                      param.name = prop.displayName;
                      param.required = prop.required;
                      param.description = prop.description;
                      param.safeType = prop.safeType;
                      bodyParams.push(param);
                  }
              }
          }
  
          data.parameters = data.parameters.concat(bodyParams);
      }
  }
  
  function mergePathParameters(data) {
      if (!data.parameters) data.parameters = [];
      data.parameters = data.parameters.concat(data.method.pathParameters||[]);
      data.parameters = data.parameters.filter((param, index, self) => self.findIndex((p) => {return p.name === param.name && p.in === param.in; }) === index || param.in === 'body');
  }
  
  function getResponses(data) {
      let responses = [];
      for (let r in data.operation.responses) {
          let response = data.operation.responses[r];
          let entry = {};
          entry.status = r;
          entry.meaning = (r === 'default' ? data.translations.responseDefault : data.translations.responseUnknown);
          var url = '';
          for (var s in common.statusCodes) {
              if (common.statusCodes[s].code === r) {
                  entry.meaning = common.statusCodes[s].phrase;
                  url = common.statusCodes[s].spec_href;
                  break;
              }
          }
          if (url) entry.meaning = '[' + entry.meaning + '](' + url + ')';
          entry.description = (typeof response.description === 'string' ? response.description.trim() : undefined);
          entry.schema = data.translations.schemaNone;
          for (let ct in response.content) {
              let contentType = response.content[ct];
              if (contentType.schema) {
                  entry.type = contentType.schema.type;
                  entry.schema = data.translations.schemaInline;
              }
              if (contentType.schema && contentType.schema["x-widdershins-oldRef"]) {
                  let schemaName = contentType.schema["x-widdershins-oldRef"].replace('#/components/schemas/','');
                  entry.schema = '['+schemaName+'](#schema'+schemaName.toLowerCase()+')';
                  entry.$ref = true;
              }
              else {
                  if (contentType.schema && contentType.schema.type && (contentType.schema.type !== 'object') && (contentType.schema.type !== 'array')) {
                      entry.schema = contentType.schema.type;
                  }
              }
          }
          entry.content = response.content;
          entry.links = response.links;
          responses.push(entry);
      }
      return responses;
  }
  
  function convertExample(ex) {
      if (typeof ex === 'string') {
          try {
              return yaml.safeLoad(ex);
          }
          catch (e) {
              return ex;
          }
      }
      else return ex;
  }
  
  function getResponseExamples(data) {
      let content = '';
      let examples = [];
      let autoDone = {};
      for (let resp in data.operation.responses) {
          let response = data.operation.responses[resp];
          for (let ct in response.content) {
              let contentType = response.content[ct];
              let cta = [ct];
              // support embedded examples
              if (contentType.examples) {
                  for (let ctei in contentType.examples) {
                      let example = contentType.examples[ctei];
                      examples.push({description:example.description||response.description,value: common.clean(convertExample(example.value)), cta: cta});
                  }
              }
              else if (contentType.example) {
                  examples.push({description:resp+' '+data.translations.response,value:common.clean(convertExample(contentType.example)), cta: cta});
              }
              else if (contentType.schema) {
                  let obj = contentType.schema;
                  let autoCT = '';
                  if (common.doContentType(cta, 'json')) autoCT = 'json';
                  if (common.doContentType(cta, 'yaml')) autoCT = 'yaml';
                  if (common.doContentType(cta, 'xml'))  autoCT = 'xml';
  
                  if (!autoDone[autoCT]) {
                      autoDone[autoCT] = true;
                      let xmlWrap = false;
                      if (obj && obj.xml && obj.xml.name) {
                          xmlWrap = obj.xml.name;
                      }
                      else if (obj["x-widdershins-oldRef"]) {
                          xmlWrap = obj["x-widdershins-oldRef"].split('/').pop();
                      }
                      examples.push({description:resp+' '+data.translations.response,value:common.getSample(obj,data.options,{skipWriteOnly:true},data.api), cta: cta, xmlWrap: xmlWrap});
                  }
              }
          }
      }
      let lastDesc = '';
      for (let example of examples) {
          if (example.description && example.description !== lastDesc) {
              content += '> '+example.description+'\n\n';
              lastDesc = example.description;
          }
          if (common.doContentType(example.cta, 'json')) {
              content += '```json\n';
              content += safejson(example.value, null, 2) + '\n';
              content += '```\n\n';
          }
          if (common.doContentType(example.cta, 'yaml')) {
              content += '```yaml\n';
              content += yaml.safeDump(example.value) + '\n';
              content += '```\n\n';
          }
          let xmlObj = example.value;
          if (example.xmlWrap) {
              xmlObj = {};
              xmlObj[example.xmlWrap] = example.value;
          }
          if ((typeof xmlObj === 'object') && common.doContentType(example.cta, 'xml')) {
              content += '```xml\n';
              content += xml.getXml(JSON.parse(safejson(xmlObj)), '@', '', true, '  ', false) + '\n';
              content += '```\n\n';
          }
      }
      return content;
  }
  
  function getResponseHeaders(data) {
      let headers = [];
      for (let r in data.operation.responses) {
          let response = data.operation.responses[r];
          if (response.headers) {
              for (let h in response.headers) {
                  let header = response.headers[h];
                  let entry = {};
                  entry.status = r;
                  entry.header = h;
                  entry.description = header.description;
                  entry.in = 'header';
                  entry.required = header.required;
                  entry.schema = header.schema || {};
                  entry.type = entry.schema.type;
                  entry.format = entry.schema.format;
                  headers.push(entry);
              }
          }
      }
      return headers;
  }
  
  function getAuthenticationStr(data) {
      let list = '';
      for (let s in data.security) {
          let count = 0;
          for (let sse in Object.keys(data.security[s])) {
              let secName = Object.keys(data.security[s])[sse];
              let link = '#/components/securitySchemes/' + secName;
              let secDef = jptr(data.api, link);
              let sep = (count > 0) ? ' & ' : ', ';
              list += (list ? sep : '') + (secDef ? secName : data.translations.secDefNone);
              let scopes = data.security[s][secName];
              if (Array.isArray(scopes) && (scopes.length > 0)) {
                  list += ' ( '+data.translations.secDefScopes+': ';
                  for (let scope in scopes) {
                      list += scopes[scope] + ' ';
                  }
                  list += ')';
              }
              count++;
          }
          if (count === 0) { // 'null' security
              list += (list ? ', ' : '') + data.translations.secDefNone;
          }
      }
      return list;
  }
  
  function convertInner(api, options, callback) {
      let defaults = {};
      defaults.title = 'API';
      defaults.language_tabs = [{ 'shell': 'Shell' }, { 'http': 'HTTP' }, { 'javascript': 'JavaScript' }, { 'javascript--nodejs': 'Node.JS' }, { 'ruby': 'Ruby' }, { 'python': 'Python' }, { 'java': 'Java' }, { 'go': 'Go' }];
      defaults.toc_footers = [];
      defaults.includes = [];
      defaults.search = true;
      defaults.theme = 'darkula';
      defaults.headings = 2;
      defaults.templateCallback = function(template,stage,data) { return data; };
  
      options = Object.assign({},defaults,options);
  
      let data = {};
      if (options.verbose) console.warn('starting deref',api.info.title);
      if (api.components) {
          data.components = clone(api.components);
      }
      else {
          data.components = {};
      }
      data.api = dereference(api,api,{verbose:options.verbose,$ref:'x-widdershins-oldRef'});
      if (options.verbose) console.warn('finished deref');
  
      if (data.api.components && data.api.components.schemas && data.api.components.schemas["x-widdershins-oldRef"]) {
          delete data.api.components.schemas["x-widdershins-oldRef"];
      }
  
      if (typeof templates === 'undefined') {
          templates = dot.process({ path: path.join(__dirname, 'templates', 'openapi3') });
      }
      if (options.user_templates) {
          templates = Object.assign(templates, dot.process({ path: options.user_templates }));
      }
      data.translations = {};
      templates.translations(data);
  
      data.version = (data.api.info.version.toLowerCase().startsWith('v') ? data.api.info.version : 'v'+data.api.info.version);
  
      let header = {};
      header.title = api.info.title||'API' + ' ' + data.version;
      header.language_tabs = options.language_tabs;
      header.toc_footers = [];
      if (api.externalDocs) {
          if (api.externalDocs.url) {
              header.toc_footers.push('<a href="' + api.externalDocs.url + '">' + (api.externalDocs.description ? api.externalDocs.description : data.translations.externalDocs) + '</a>');
          }
      }
      header.includes = options.includes;
      header.search = options.search;
      header.highlight_theme = options.theme;
      header.headingLevel = options.headings;
  
      data.options = options;
      data.header = header;
      data.title_prefix = (data.api.info.title.trim()||'API').split(' ').join('-');
      data.templates = templates;
      data.resources = convertToToc(api,data);
  
      if (data.api.servers && data.api.servers.length) {
          data.servers = data.api.servers;
      }
      else if (options.loadedFrom) {
          data.servers = [{url:options.loadedFrom}];
      }
      else {
          data.servers = [{url:'//'}];
      }
      data.host = up.parse(data.servers[0].url).host;
      data.protocol = up.parse(data.servers[0].url).protocol;
      if (data.protocol) data.protocol = data.protocol.replace(':','');
      data.baseUrl = data.servers[0].url;
  
      data.utils = {};
      data.utils.yaml = yaml;
      data.utils.inspect = util.inspect;
      data.utils.safejson = safejson;
      data.utils.isPrimitive = function(t) { return (t && (t !== 'object') && (t !== 'array')) };
      data.utils.toPrimitive = common.toPrimitive;
      data.utils.slashes = function(s) { return s.replace(/\/+/g, '/').replace(':/','://'); };
      data.utils.slugify = common.slugify;
      data.utils.getSample = common.getSample;
      data.utils.schemaToArray = common.schemaToArray;
      data.utils.fakeProdCons = fakeProdCons;
      data.utils.getParameters = getParameters;
      data.utils.getCodeSamples = common.getCodeSamples;
      data.utils.getBodyParameterExamples = getBodyParameterExamples;
      data.utils.fakeBodyParameter = fakeBodyParameter;
      data.utils.mergePathParameters = mergePathParameters;
      data.utils.getResponses = getResponses;
      data.utils.getResponseExamples = getResponseExamples;
      data.utils.getResponseHeaders = getResponseHeaders;
      data.utils.getAuthenticationStr = getAuthenticationStr;
      data.utils.join = function(s) {
          return s.split('\r').join('').split('\n').join(' ').trim();
      };
  
      let content = '---\n'+yaml.dump(header)+'\n---\n\n';
          data = options.templateCallback('main', 'pre', data);
          if (data.append) { content += data.append; delete data.append; }
      try {
          content += templates.main(data);
      }
      catch (ex) {
          return callback(ex);
      }
      data = options.templateCallback('main', 'post', data);
      if (data.append) { content += data.append; delete data.append; }
      content = common.removeDupeBlankLines(content);
  
      callback(null,content);
  }
  
  function convert(api, options, callback) {
      if (options.resolve) {
          swagger2openapi.convertObj(api, {resolve:true,source:options.source}, function(err, sOptions) {
          if (err) {
              console.error(err.message);
          }
          else {
              convertInner(sOptions.openapi, options, callback);
          }});
      }
      else {
          convertInner(api, options, callback);
      }
  }
  
  module.exports = {
      convert : convert
  };
  