You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

284 rivejä
11 KiB

  1. // Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See LICENSE file in the project root for full license information.
  2. var common = require('./common.js');
  3. exports.transform = function (model) {
  4. var _fileNameWithoutExt = common.path.getFileNameWithoutExtension(model._path);
  5. model._jsonPath = _fileNameWithoutExt + ".swagger.json";
  6. model.title = model.title || model.name;
  7. model.docurl = model.docurl || common.getImproveTheDocHref(model, model._gitContribute, model._gitUrlPattern);
  8. model.sourceurl = model.sourceurl || common.getViewSourceHref(model, null, model._gitUrlPattern);
  9. model.htmlId = common.getHtmlId(model.uid);
  10. if (model.children) {
  11. for (var i = 0; i < model.children.length; i++) {
  12. var child = model.children[i];
  13. child.docurl = child.docurl || common.getImproveTheDocHref(child, model._gitContribute, model._gitUrlPattern);
  14. if (child.operation) {
  15. child.operation = child.operation.toUpperCase();
  16. }
  17. child.path = appendQueryParamsToPath(child.path, child.parameters);
  18. child.sourceurl = child.sourceurl || common.getViewSourceHref(child, null, model._gitUrlPattern);
  19. child.conceptual = child.conceptual || ''; // set to empty incase mustache looks up
  20. child.footer = child.footer || ''; // set to empty incase mustache looks up
  21. child.remarks = child.remarks || ''; // set to empty incase mustache looks up
  22. child.htmlId = common.getHtmlId(child.uid);
  23. formatExample(child.responses);
  24. resolveAllOf(child);
  25. transformReference(child);
  26. };
  27. if (!model.tags || model.tags.length === 0) {
  28. var childTags = [];
  29. for (var i = 0; i < model.children.length; i++) {
  30. var child = model.children[i];
  31. if (child.tags && child.tags.length > 0) {
  32. for (var k = 0; k < child.tags.length; k++) {
  33. // for each tag in child, add unique tag string into childTags
  34. if (childTags.indexOf(child.tags[k]) === -1) {
  35. childTags.push(child.tags[k]);
  36. }
  37. }
  38. }
  39. }
  40. // sort alphabetically
  41. childTags.sort();
  42. if (childTags.length > 0) {
  43. model.tags = [];
  44. for (var i = 0; i < childTags.length; i++) {
  45. // add tags into model
  46. model.tags.push({ "name": childTags[i] });
  47. }
  48. }
  49. }
  50. if (model.tags) {
  51. for (var i = 0; i < model.tags.length; i++) {
  52. var children = getChildrenByTag(model.children, model.tags[i].name);
  53. if (children) {
  54. // set children into tag section
  55. model.tags[i].children = children;
  56. }
  57. model.tags[i].conceptual = model.tags[i].conceptual || ''; // set to empty incase mustache looks up
  58. if (model.tags[i]["x-bookmark-id"]) {
  59. model.tags[i].htmlId = model.tags[i]["x-bookmark-id"];
  60. } else if (model.tags[i].uid) {
  61. model.tags[i].htmlId = common.getHtmlId(model.tags[i].uid);
  62. }
  63. }
  64. for (var i = 0; i < model.children.length; i++) {
  65. var child = model.children[i];
  66. if (child.includedInTags) {
  67. // set child to undefined, which is already moved to tag section
  68. model.children[i] = undefined;
  69. if (!model.isTagLayout) {
  70. // flags to indicate the model is tag layout
  71. model.isTagLayout = true;
  72. }
  73. }
  74. }
  75. // remove undefined child
  76. model.children = model.children.filter(function (o) { return o; });
  77. }
  78. }
  79. return model;
  80. function getChildrenByTag(children, tag) {
  81. if (!children) return;
  82. return children.filter(function (child) {
  83. if (child.tags && child.tags.indexOf(tag) > -1) {
  84. child.includedInTags = true;
  85. return true;
  86. }
  87. })
  88. }
  89. function formatExample(responses) {
  90. if (!responses) return;
  91. for (var i = responses.length - 1; i >= 0; i--) {
  92. var examples = responses[i].examples;
  93. if (!examples) continue;
  94. for (var j = examples.length - 1; j >= 0; j--) {
  95. var content = examples[j].content;
  96. if (!content) continue;
  97. var mimeType = examples[j].mimeType;
  98. if (mimeType === 'application/json') {
  99. try {
  100. var json = JSON.parse(content)
  101. responses[i].examples[j].content = JSON.stringify(json, null, ' ');
  102. } catch (e) {
  103. console.warn("example is not a valid JSON object.");
  104. }
  105. }
  106. }
  107. }
  108. }
  109. function resolveAllOf(obj) {
  110. if (Array.isArray(obj)) {
  111. for (var i = 0; i < obj.length; i++) {
  112. resolveAllOf(obj[i]);
  113. }
  114. }
  115. else if (typeof obj === "object") {
  116. for (var key in obj) {
  117. if (obj.hasOwnProperty(key)) {
  118. if (key === "allOf" && Array.isArray(obj[key])) {
  119. // find 'allOf' array and process
  120. processAllOfArray(obj[key], obj);
  121. // delete 'allOf' value
  122. delete obj[key];
  123. } else {
  124. resolveAllOf(obj[key]);
  125. }
  126. }
  127. }
  128. }
  129. }
  130. function processAllOfArray(allOfArray, originalObj) {
  131. // for each object in 'allOf' array, merge the values to those in the same level with 'allOf'
  132. for (var i = 0; i < allOfArray.length; i++) {
  133. var item = allOfArray[i];
  134. for (var key in item) {
  135. if (originalObj.hasOwnProperty(key)) {
  136. mergeObjByKey(originalObj[key], item[key]);
  137. } else {
  138. originalObj[key] = item[key];
  139. }
  140. }
  141. }
  142. }
  143. function mergeObjByKey(targetObj, sourceObj) {
  144. for (var key in sourceObj) {
  145. // merge only when target object doesn't define the key
  146. if (!targetObj.hasOwnProperty(key)) {
  147. targetObj[key] = sourceObj[key];
  148. }
  149. }
  150. }
  151. function transformReference(obj) {
  152. if (Array.isArray(obj)) {
  153. for (var i = 0; i < obj.length; i++) {
  154. transformReference(obj[i]);
  155. }
  156. }
  157. else if (typeof obj === "object") {
  158. for (var key in obj) {
  159. if (obj.hasOwnProperty(key)) {
  160. if (key === "schema") {
  161. // transform schema.properties from obj to key value pair
  162. transformProperties(obj[key]);
  163. } else {
  164. transformReference(obj[key]);
  165. }
  166. }
  167. }
  168. }
  169. }
  170. function transformProperties(obj) {
  171. if (obj.properties) {
  172. if (obj.required && Array.isArray(obj.required)) {
  173. for (var i = 0; i < obj.required.length; i++) {
  174. var field = obj.required[i];
  175. if (obj.properties[field]) {
  176. // add required field as property
  177. obj.properties[field].required = true;
  178. }
  179. }
  180. delete obj.required;
  181. }
  182. var array = [];
  183. for (var key in obj.properties) {
  184. if (obj.properties.hasOwnProperty(key)) {
  185. var value = obj.properties[key];
  186. // set description to null incase mustache looks up
  187. value.description = value.description || null;
  188. transformPropertiesValue(value);
  189. array.push({ key: key, value: value });
  190. }
  191. }
  192. obj.properties = array;
  193. }
  194. }
  195. function transformPropertiesValue(obj) {
  196. if (obj.type === "array" && obj.items) {
  197. // expand array to transformProperties
  198. obj.items.properties = obj.items.properties || null;
  199. obj.items['x-internal-ref-name'] = obj.items['x-internal-ref-name'] || null;
  200. obj.items['x-internal-loop-ref-name'] = obj.items['x-internal-loop-ref-name'] || null;
  201. transformProperties(obj.items);
  202. } else if (obj.properties && !obj.items) {
  203. // fill obj.properties into obj.items.properties, to be rendered in the same way with array
  204. obj.items = {};
  205. obj.items.properties = obj.properties || null;
  206. delete obj.properties;
  207. if (obj.required) {
  208. obj.items.required = obj.required;
  209. delete obj.required;
  210. }
  211. obj.items['x-internal-ref-name'] = obj['x-internal-ref-name'] || null;
  212. obj.items['x-internal-loop-ref-name'] = obj['x-internal-loop-ref-name'] || null;
  213. transformProperties(obj.items);
  214. }
  215. }
  216. function appendQueryParamsToPath(path, parameters) {
  217. if (!path || !parameters) return path;
  218. var requiredQueryParams = parameters.filter(function (p) { return p.in === 'query' && p.required; });
  219. if (requiredQueryParams.length > 0) {
  220. path = formatParams(path, requiredQueryParams, true);
  221. }
  222. var optionalQueryParams = parameters.filter(function (p) { return p.in === 'query' && !p.required; });
  223. if (optionalQueryParams.length > 0) {
  224. path += "[";
  225. path = formatParams(path, optionalQueryParams, requiredQueryParams.length === 0);
  226. path += "]";
  227. }
  228. return path;
  229. }
  230. function formatParams(path, parameters, isFirst) {
  231. for (var i = 0; i < parameters.length; i++) {
  232. if (i === 0 && isFirst) {
  233. path += "?";
  234. } else {
  235. path += "&";
  236. }
  237. path += parameters[i].name;
  238. }
  239. return path;
  240. }
  241. }
  242. exports.getBookmarks = function (model) {
  243. if (!model) return null;
  244. var bookmarks = {};
  245. bookmarks[model.uid] = "";
  246. if (model.tags) {
  247. model.tags.forEach(function (tag) {
  248. if (tag.uid) {
  249. bookmarks[tag.uid] = tag["x-bookmark-id"] ? tag["x-bookmark-id"] : common.getHtmlId(tag.uid);
  250. }
  251. if (tag.children) {
  252. tag.children.forEach(function (child) {
  253. bookmarks[child.uid] = common.getHtmlId(child.uid);
  254. })
  255. }
  256. })
  257. }
  258. if (model.children) {
  259. model.children.forEach(function (child) {
  260. bookmarks[child.uid] = common.getHtmlId(child.uid);
  261. });
  262. }
  263. return bookmarks;
  264. }