UniversalReference.common.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  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. var classCategory = 'class';
  4. var namespaceCategory = 'ns';
  5. exports.transform = function (model) {
  6. if (!model) return
  7. handleItem(model, model._gitContribute, model._gitUrlPattern);
  8. if (model.children) {
  9. normalizeLanguageValuePairs(model.children).forEach(function (item) {
  10. handleItem(item, model._gitContribute, model._gitUrlPattern);
  11. });
  12. };
  13. if (model.type) {
  14. switch (model.type.toLowerCase()) {
  15. // packages and namespaces are both containers for other elements
  16. case 'package':
  17. case 'namespace':
  18. model.isNamespace = true;
  19. if (model.children) groupChildren(model, namespaceCategory);
  20. model[getTypePropertyName(model.type)] = true;
  21. break;
  22. case 'class':
  23. case 'interface':
  24. case 'struct':
  25. case 'delegate':
  26. model.isClass = true;
  27. if (model.children) groupChildren(model, classCategory);
  28. model[getTypePropertyName(model.type)] = true;
  29. break;
  30. case 'enum':
  31. model.isEnum = true;
  32. if (model.children) groupChildren(model, classCategory);
  33. model[getTypePropertyName(model.type)] = true;
  34. break;
  35. default:
  36. break;
  37. }
  38. }
  39. return model;
  40. }
  41. exports.getBookmarks = function (model, ignoreChildren) {
  42. if (!model || !model.type || model.type.toLowerCase() === "namespace") return null;
  43. var bookmarks = {};
  44. if (typeof ignoreChildren == 'undefined' || ignoreChildren === false) {
  45. if (model.children) {
  46. normalizeLanguageValuePairs(model.children).forEach(function (item) {
  47. bookmarks[item.uid] = common.getHtmlId(item.uid);
  48. if (item.overload && item.overload.uid) {
  49. bookmarks[item.overload.uid] = common.getHtmlId(item.overload.uid);
  50. }
  51. });
  52. }
  53. }
  54. // Reference's first level bookmark should have no anchor
  55. bookmarks[model.uid] = "";
  56. return bookmarks;
  57. }
  58. function handleItem(vm, gitContribute, gitUrlPattern) {
  59. // get contribution information
  60. vm.docurl = common.getImproveTheDocHref(vm, gitContribute, gitUrlPattern);
  61. vm.sourceurl = common.getViewSourceHref(vm, null, gitUrlPattern);
  62. // set to null incase mustache looks up
  63. vm.summary = vm.summary || null;
  64. vm.remarks = vm.remarks || null;
  65. vm.conceptual = vm.conceptual || null;
  66. vm.syntax = vm.syntax || null;
  67. vm.implements = vm.implements || null;
  68. vm.example = vm.example || null;
  69. vm.inheritance = vm.inheritance || null;
  70. if (vm.inheritance) {
  71. normalizeLanguageValuePairs(vm.inheritance).forEach(handleInheritance);
  72. }
  73. common.processSeeAlso(vm);
  74. // id is used as default template's bookmark
  75. vm.id = common.getHtmlId(vm.uid);
  76. if (vm.overload && vm.overload.uid) {
  77. vm.overload.id = common.getHtmlId(vm.overload.uid);
  78. }
  79. // concatenate multiple types with `|`
  80. if (vm.syntax) {
  81. var syntax = vm.syntax;
  82. if (syntax.parameters) {
  83. syntax.parameters = syntax.parameters.map(function (p) {
  84. return joinType(p);
  85. })
  86. syntax.parameters = groupParameters(syntax.parameters);
  87. }
  88. if (syntax.return) {
  89. syntax.return = joinType(syntax.return);
  90. }
  91. }
  92. }
  93. function handleInheritance(tree) {
  94. tree.type = tree.type || null;
  95. tree.inheritance = tree.inheritance || null;
  96. if (tree.inheritance) {
  97. tree.inheritance.forEach(handleInheritance);
  98. }
  99. }
  100. function joinType(parameter) {
  101. // change type in syntax from array to string
  102. var joinTypeProperty = function (type, key) {
  103. if (!type || !type[0] || !type[0][key]) return null;
  104. var value = type.map(function (t) {
  105. if (!t) return null;
  106. if (!t[key]) return t.uid;
  107. return t[key][0].value;
  108. }).join(' | ');
  109. return [{
  110. lang: type[0][key][0].lang,
  111. value: value
  112. }];
  113. };
  114. if (parameter.type) {
  115. parameter.type = {
  116. name: joinTypeProperty(parameter.type, "name"),
  117. nameWithType: joinTypeProperty(parameter.type, "nameWithType"),
  118. fullName: joinTypeProperty(parameter.type, "fullName"),
  119. specName: joinTypeProperty(parameter.type, "specName")
  120. }
  121. }
  122. return parameter;
  123. }
  124. function groupParameters(parameters) {
  125. // group parameter with properties
  126. if (!parameters || parameters.length == 0) return parameters;
  127. var groupedParameters = [];
  128. var stack = [];
  129. for (var i = 0; i < parameters.length; i++) {
  130. var parameter = parameters[i];
  131. parameter.properties = null;
  132. var prefixLength = 0;
  133. while (stack.length > 0) {
  134. var top = stack.pop();
  135. var prefix = top.id + '.';
  136. if (parameter.id.indexOf(prefix) == 0) {
  137. prefixLength = prefix.length;
  138. if (!top.parameter.properties) {
  139. top.parameter.properties = [];
  140. }
  141. top.parameter.properties.push(parameter);
  142. stack.push(top);
  143. break;
  144. }
  145. if (stack.length == 0) {
  146. groupedParameters.push(top.parameter);
  147. }
  148. }
  149. stack.push({ id: parameter.id, parameter: parameter });
  150. parameter.id = parameter.id.substring(prefixLength);
  151. }
  152. while (stack.length > 0) {
  153. top = stack.pop();
  154. }
  155. groupedParameters.push(top.parameter);
  156. return groupedParameters;
  157. }
  158. function groupChildren(model, category, typeChildrenItems) {
  159. if (!model || !model.type) {
  160. return;
  161. }
  162. if (!typeChildrenItems) {
  163. var typeChildrenItems = getDefinitions(category);
  164. }
  165. var grouped = {};
  166. normalizeLanguageValuePairs(model.children).forEach(function (c) {
  167. if (c.isEii) {
  168. var type = "eii";
  169. } else {
  170. var type = c.type.toLowerCase();
  171. }
  172. if (!grouped.hasOwnProperty(type)) {
  173. grouped[type] = [];
  174. }
  175. // special handle for field
  176. if (type === "field" && c.syntax) {
  177. c.syntax.fieldValue = c.syntax.return;
  178. c.syntax.return = undefined;
  179. }
  180. // special handle for property
  181. if (type === "property" && c.syntax) {
  182. c.syntax.propertyValue = c.syntax.return;
  183. c.syntax.return = undefined;
  184. }
  185. // special handle for event
  186. if (type === "event" && c.syntax) {
  187. c.syntax.eventType = c.syntax.return;
  188. c.syntax.return = undefined;
  189. }
  190. if (type === "variable" && c.syntax) {
  191. c.syntax.variableValue = c.syntax.return;
  192. c.syntax.return = undefined;
  193. }
  194. if (type === "typealias" && c.syntax) {
  195. c.syntax.typeAliasType = c.syntax.return;
  196. c.syntax.return = undefined;
  197. }
  198. grouped[type].push(c);
  199. })
  200. var children = [];
  201. for (var key in typeChildrenItems) {
  202. if (typeChildrenItems.hasOwnProperty(key) && grouped.hasOwnProperty(key)) {
  203. var typeChildrenItem = typeChildrenItems[key];
  204. var items = grouped[key];
  205. if (items && items.length > 0) {
  206. var item = {};
  207. for (var itemKey in typeChildrenItem) {
  208. if (typeChildrenItem.hasOwnProperty(itemKey)){
  209. item[itemKey] = typeChildrenItem[itemKey];
  210. }
  211. }
  212. item.children = items;
  213. children.push(item);
  214. }
  215. }
  216. }
  217. model.children = children;
  218. }
  219. function getTypePropertyName(type) {
  220. if (!type) {
  221. return undefined;
  222. }
  223. var loweredType = type.toLowerCase();
  224. var definition = getDefinition(loweredType);
  225. if (definition) {
  226. return definition.typePropertyName;
  227. }
  228. return undefined;
  229. }
  230. function getCategory(type) {
  231. var classItems = getDefinitions(classCategory);
  232. if (classItems.hasOwnProperty(type)) {
  233. return classCategory;
  234. }
  235. var namespaceItems = getDefinitions(namespaceCategory);
  236. if (namespaceItems.hasOwnProperty(type)) {
  237. return namespaceCategory;
  238. }
  239. return undefined;
  240. }
  241. function getDefinition(type) {
  242. var classItems = getDefinitions(classCategory);
  243. if (classItems.hasOwnProperty(type)) {
  244. return classItems[type];
  245. }
  246. var namespaceItems = getDefinitions(namespaceCategory);
  247. if (namespaceItems.hasOwnProperty(type)) {
  248. return namespaceItems[type];
  249. }
  250. return undefined;
  251. }
  252. function getDefinitions(category) {
  253. var namespaceItems = {
  254. "package": { inPackage: true, typePropertyName: "inPackage", id: "packages" },
  255. "namespace": { inNamespace: true, typePropertyName: "inNamespace", id: "namespaces" },
  256. "class": { inClass: true, typePropertyName: "inClass", id: "classes" },
  257. "struct": { inStruct: true, typePropertyName: "inStruct", id: "structs" },
  258. "interface": { inInterface: true, typePropertyName: "inInterface", id: "interfaces" },
  259. "enum": { inEnum: true, typePropertyName: "inEnum", id: "enums" },
  260. "delegate": { inDelegate: true, typePropertyName: "inDelegate", id: "delegates" },
  261. "function": { inFunction: true, typePropertyName: "inFunction", id: "functions", isEmbedded: true },
  262. "variable": { inVariable: true, typePropertyName: "inVariable", id: "variables", isEmbedded: true },
  263. "typealias": { inTypeAlias: true, typePropertyName: "inTypeAlias", id: "typealiases", isEmbedded: true },
  264. };
  265. var classItems = {
  266. "constructor": { inConstructor: true, typePropertyName: "inConstructor", id: "constructors" },
  267. "field": { inField: true, typePropertyName: "inField", id: "fields" },
  268. "property": { inProperty: true, typePropertyName: "inProperty", id: "properties" },
  269. "method": { inMethod: true, typePropertyName: "inMethod", id: "methods" },
  270. "event": { inEvent: true, typePropertyName: "inEvent", id: "events" },
  271. "operator": { inOperator: true, typePropertyName: "inOperator", id: "operators" },
  272. "eii": { inEii: true, typePropertyName: "inEii", id: "eii" },
  273. "member": { inMember: true, typePropertyName: "inMember", id: "members"},
  274. "function": { inFunction: true, typePropertyName: "inFunction", id: "functions" }
  275. };
  276. if (category === 'class') {
  277. return classItems;
  278. }
  279. if (category === 'ns') {
  280. return namespaceItems;
  281. }
  282. console.err("category '" + category + "' is not valid.");
  283. return undefined;
  284. }
  285. function normalizeLanguageValuePairs(list) {
  286. if (list[0] && list[0].lang && list[0].value) {
  287. return list[0].value;
  288. }
  289. return list;
  290. }