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.

236 lines
8.3 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. exports.path = {};
  3. exports.path.getFileNameWithoutExtension = getFileNameWithoutExtension;
  4. exports.path.getDirectoryName = getDirectoryName;
  5. exports.getHtmlId = getHtmlId;
  6. exports.getViewSourceHref = getViewSourceHref;
  7. exports.getImproveTheDocHref = getImproveTheDocHref;
  8. exports.processSeeAlso = processSeeAlso;
  9. exports.isAbsolutePath = isAbsolutePath;
  10. exports.isRelativePath = isRelativePath;
  11. function getFileNameWithoutExtension(path) {
  12. if (!path || path[path.length - 1] === '/' || path[path.length - 1] === '\\') return '';
  13. var fileName = path.split('\\').pop().split('/').pop();
  14. return fileName.slice(0, fileName.lastIndexOf('.'));
  15. }
  16. function getDirectoryName(path) {
  17. if (!path) return '';
  18. var index = path.lastIndexOf('/');
  19. return path.slice(0, index + 1);
  20. }
  21. function getHtmlId(input) {
  22. if (!input) return '';
  23. return input.replace(/\W/g, '_');
  24. }
  25. // Note: the parameter `gitContribute` won't be used in this function
  26. function getViewSourceHref(item, gitContribute, gitUrlPattern) {
  27. if (!item || !item.source || !item.source.remote) return '';
  28. if (!gitContribute) gitContribute = item._gitContribute;
  29. return getRemoteUrl(item.source.remote, item.source.startLine - '0' + 1, gitContribute, gitUrlPattern);
  30. }
  31. function getImproveTheDocHref(item, gitContribute, gitUrlPattern) {
  32. if (!item) return '';
  33. if (!item.documentation || !item.documentation.remote) {
  34. return getNewFileUrl(item, gitContribute, gitUrlPattern);
  35. } else {
  36. return getRemoteUrl(item.documentation.remote, item.documentation.startLine + 1, gitContribute, gitUrlPattern);
  37. }
  38. }
  39. function processSeeAlso(item) {
  40. if (item.seealso) {
  41. for (var key in item.seealso) {
  42. addIsCref(item.seealso[key]);
  43. }
  44. }
  45. item.seealso = item.seealso || null;
  46. }
  47. function isAbsolutePath(path) {
  48. return /^(\w+:)?\/\//g.test(path);
  49. }
  50. function isRelativePath(path) {
  51. if (!path) return false;
  52. return !exports.isAbsolutePath(path);
  53. }
  54. var gitUrlPatternItems = {
  55. 'github': {
  56. // HTTPS form: https://github.com/{org}/{repo}.git
  57. // SSH form: [email protected]:{org}/{repo}.git
  58. // generate URL: https://github.com/{org}/{repo}/blob/{branch}/{path}
  59. 'testRegex': /^(https?:\/\/)?(\S+\@)?(\S+\.)?github\.com(\/|:).*/i,
  60. 'generateUrl': function (gitInfo) {
  61. var url = normalizeGitUrlToHttps(gitInfo.repo);
  62. url = getRepoWithoutGitExtension(url);
  63. url += '/blob' + '/' + gitInfo.sourceBranch + '/' + gitInfo.path;
  64. if (gitInfo.startLine && gitInfo.startLine > 0) {
  65. url += '/#L' + gitInfo.startLine;
  66. }
  67. return url;
  68. },
  69. 'generateNewFileUrl': function (gitInfo, uid) {
  70. var url = normalizeGitUrlToHttps(gitInfo.repo);
  71. url = getRepoWithoutGitExtension(url);
  72. url += '/new';
  73. url += '/' + gitInfo.branch;
  74. url += '/' + getOverrideFolder(gitInfo.apiSpecFolder);
  75. url += '/new?filename=' + getHtmlId(uid) + '.md';
  76. url += '&value=' + encodeURIComponent(getOverrideTemplate(uid));
  77. return url;
  78. }
  79. },
  80. 'vso': {
  81. // HTTPS form: https://{user}.visualstudio.com/{org}/_git/{repo}
  82. // SSH form: ssh://{user}@{user}.visualstudio.com:22/{org}/_git/{repo}
  83. // generated URL under branch: https://{user}.visualstudio.com/{org}/_git/{repo}?path={path}&version=GB{branch}
  84. // generated URL under detached HEAD: https://{user}.visualstudio.com/{org}/_git/{repo}?path={path}&version=GC{commit}
  85. 'testRegex': /^(https?:\/\/)?(ssh:\/\/\S+\@)?(\S+\.)?visualstudio\.com(\/|:).*/i,
  86. 'generateUrl': function (gitInfo) {
  87. var url = normalizeGitUrlToHttps(gitInfo.repo);
  88. var branchPrefix = /[0-9a-fA-F]{40}/.test(gitInfo.branch) ? 'GC' : 'GB';
  89. url += '?path=' + gitInfo.path + '&version=' + branchPrefix + gitInfo.branch;
  90. if (gitInfo.startLine && gitInfo.startLine > 0) {
  91. url += '&line=' + gitInfo.startLine;
  92. }
  93. return url;
  94. },
  95. 'generateNewFileUrl': function (gitInfo, uid) {
  96. return '';
  97. }
  98. },
  99. 'bitbucket': {
  100. // HTTPS form: https://{user}@bitbucket.org/{org}/{repo}.git
  101. // SSH form: [email protected]:{org}/{repo}.git
  102. // generate URL: https://bitbucket.org/{org}/{repo}/src/{branch}/{path}
  103. 'testRegex': /^(https?:\/\/)?(\S+\@)?(\S+\.)?bitbucket\.org(\/|:).*/i,
  104. 'generateUrl': function (gitInfo) {
  105. var url = normalizeGitUrlToHttps(gitInfo.repo);
  106. url = getRepoWithoutGitExtension(url);
  107. url += '/src' + '/' + gitInfo.branch + '/' + gitInfo.path;
  108. if (gitInfo.startLine && gitInfo.startLine > 0) {
  109. url += '#lines-' + gitInfo.startLine;
  110. }
  111. return url;
  112. },
  113. 'generateNewFileUrl': function (gitInfo, uid) {
  114. return '';
  115. }
  116. }
  117. }
  118. function getRepoWithoutGitExtension(repo) {
  119. if (repo.substr(-4) === '.git') {
  120. repo = repo.substr(0, repo.length - 4);
  121. }
  122. return repo;
  123. }
  124. function normalizeGitUrlToHttps(repo) {
  125. var pos = repo.indexOf('@');
  126. if (pos == -1) return repo;
  127. return 'https://' + repo.substr(pos + 1).replace(/:[0-9]+/g, '').replace(/:/g, '/');
  128. }
  129. function getNewFileUrl(item, gitContribute, gitUrlPattern) {
  130. // do not support VSO for now
  131. if (!item.source) {
  132. return '';
  133. }
  134. var gitInfo = getGitInfo(gitContribute, item.source.remote);
  135. if (!gitInfo.repo || !gitInfo.branch || !gitInfo.path) {
  136. return '';
  137. }
  138. var patternName = getPatternName(gitInfo.repo, gitUrlPattern);
  139. if (!patternName) return patternName;
  140. return gitUrlPatternItems[patternName].generateNewFileUrl(gitInfo, item.uid);
  141. }
  142. function getRemoteUrl(remote, startLine, gitContribute, gitUrlPattern) {
  143. var gitInfo = getGitInfo(gitContribute, remote);
  144. if (!gitInfo.repo || !gitInfo.branch || !gitInfo.path) {
  145. return '';
  146. }
  147. var patternName = getPatternName(gitInfo.repo, gitUrlPattern);
  148. if (!patternName) return '';
  149. gitInfo.startLine = startLine;
  150. return gitUrlPatternItems[patternName].generateUrl(gitInfo);
  151. }
  152. function getGitInfo(gitContribute, gitRemote) {
  153. // apiSpecFolder defines the folder contains overwrite files for MRef, the default value is apiSpec
  154. var defaultApiSpecFolder = 'apiSpec';
  155. var result = {};
  156. if (gitContribute && gitContribute.apiSpecFolder) {
  157. result.apiSpecFolder = gitContribute.apiSpecFolder;
  158. } else {
  159. result.apiSpecFolder = defaultApiSpecFolder;
  160. }
  161. mergeKey(gitContribute, gitRemote, result, 'repo');
  162. mergeKey(gitContribute, gitRemote, result, 'branch');
  163. mergeKey(gitContribute, gitRemote, result, 'sourceBranch');
  164. mergeKey(gitContribute, gitRemote, result, 'path');
  165. return result;
  166. function mergeKey(source, sourceFallback, dest, key) {
  167. if (source && source.hasOwnProperty(key)) {
  168. dest[key] = source[key];
  169. } else if (sourceFallback && sourceFallback.hasOwnProperty(key)) {
  170. dest[key] = sourceFallback[key];
  171. }
  172. }
  173. }
  174. function getPatternName(repo, gitUrlPattern) {
  175. if (gitUrlPattern && gitUrlPattern.toLowerCase() in gitUrlPatternItems) {
  176. return gitUrlPattern.toLowerCase();
  177. } else {
  178. for (var p in gitUrlPatternItems) {
  179. if (gitUrlPatternItems[p].testRegex.test(repo)) {
  180. return p;
  181. }
  182. }
  183. }
  184. return '';
  185. }
  186. function getOverrideFolder(path) {
  187. if (!path) return "";
  188. path = path.replace(/\\/g, '/');
  189. if (path.charAt(path.length - 1) == '/') path = path.substring(0, path.length - 1);
  190. return path;
  191. }
  192. function getOverrideTemplate(uid) {
  193. if (!uid) return "";
  194. var content = "";
  195. content += "---\n";
  196. content += "uid: " + uid + "\n";
  197. content += "summary: '*You can override summary for the API here using *MARKDOWN* syntax'\n";
  198. content += "---\n";
  199. content += "\n";
  200. content += "*Please type below more information about this API:*\n";
  201. content += "\n";
  202. return content;
  203. }
  204. function addIsCref(seealso) {
  205. if (!seealso.linkType || seealso.linkType.toLowerCase() == "cref") {
  206. seealso.isCref = true;
  207. }
  208. }