private async Task GetHtmlContent() { var rawTopic = new TopicInformation { OriginalName = SelectedTopic.Title, Type = SelectedTopic.Type }; ImageRootUrl = string.Empty; var normalizedLink = SelectedTopic.LinkPure.ToLowerInvariant(); if (normalizedLink.StartsWith("https://") || normalizedLink.StartsWith("http://")) { // This is an absolute link, so we can just try to load it rawTopic.OriginalContent = await WebClientEx.GetStringAsync(SelectedTopic.Link); ImageRootUrl = StringHelper.JustPath(SelectedTopic.Link) + "/"; } else if (!string.IsNullOrEmpty(normalizedLink)) { var repositoryType = RepositoryTypeHelper.GetTypeFromTypeName(GetSetting <string>(SettingsEnum.RepositoryType)); // Even if the overall repository type is something else, we will switch to different repository access for specific node types, // as they may point to other repositories or require different APIs even within the same repository if (TopicTypeHelper.IsVstsWorkItemType(rawTopic?.Type)) { repositoryType = RepositoryTypes.VstsWorkItemTracking; } switch (repositoryType) { case RepositoryTypes.GitHubRaw: var fullGitHubRawUrl = GitHubMasterUrlRaw + SelectedTopic.Link; if (string.IsNullOrEmpty(rawTopic.Type)) { rawTopic.Type = TopicTypeHelper.GetTopicTypeFromLink(fullGitHubRawUrl); } if (TopicTypeHelper.IsMatch(rawTopic.Type, TopicBodyFormats.Markdown) || TopicTypeHelper.IsMatch(rawTopic.Type, TopicBodyFormats.Html)) { rawTopic.OriginalContent = await WebClientEx.GetStringAsync(fullGitHubRawUrl); } else if (TopicTypeHelper.IsMatch(rawTopic.Type, TopicBodyFormats.ImageUrl)) { rawTopic.OriginalContent = fullGitHubRawUrl; } ImageRootUrl = StringHelper.JustPath(fullGitHubRawUrl); if (!string.IsNullOrEmpty(ImageRootUrl) && !ImageRootUrl.EndsWith("/")) { ImageRootUrl += "/"; } break; case RepositoryTypes.GitHubApi: if (TopicTypeHelper.IsMatch(rawTopic.Type, TopicBodyFormats.Markdown) || TopicTypeHelper.IsMatch(rawTopic.Type, TopicBodyFormats.Html)) { var gitHubClient = new GithubRepositoryParser(GitHubOwner, GitHubRepository, GitHubPat); var gitHubContent = await gitHubClient.GetItemContent(SelectedTopic.Link); rawTopic.OriginalContent = gitHubContent.Text; } // TODO: else if (TopicTypeHelper.IsMatch(rawTopic.Type, TopicBodyFormats.ImageUrl)) // rawTopic.OriginalContent = fullGitHubRawUrl; //ImageRootUrl = StringHelper.JustPath(fullGitHubRawUrl); //if (!string.IsNullOrEmpty(ImageRootUrl) && !ImageRootUrl.EndsWith("/")) ImageRootUrl += "/"; break; case RepositoryTypes.VstsGit: if (!string.IsNullOrEmpty(SelectedTopic.LinkPure)) { rawTopic.OriginalContent = await VstsHelper.GetFileContents(SelectedTopic.LinkPure, GetSetting <string>(SettingsEnum.VstsInstance), GetSetting <string>(SettingsEnum.VstsProjectName), GetSetting <string>(SettingsEnum.VstsDocsFolder), GetSetting <string>(SettingsEnum.VstsPat), GetSetting <string>(SettingsEnum.VstsApiVersion)); } ImageRootUrl = "/___FileProxy___?mode=" + RepositoryTypeNames.VstsGit + "&path="; if (SelectedTopic.LinkPure.Contains("/")) { ImageRootUrl += StringHelper.JustPath(SelectedTopic.LinkPure) + "/"; } break; case RepositoryTypes.VstsWorkItemTracking: if ((TopicTypeHelper.IsMatch(rawTopic?.Type, TopicBodyFormats.VstsWorkItemQuery) || TopicTypeHelper.IsMatch(rawTopic?.Type, TopicBodyFormats.VstsWorkItemQueries)) && HttpContext.Request.Query.ContainsKey("workitemnumber")) { // The current node is a work item query, but we use it as a context to get the actual work item var itemNumber = int.Parse(HttpContext.Request.Query["workitemnumber"]); rawTopic.OriginalContent = await VstsHelper.GetWorkItemJson(itemNumber, GetSetting <string>(SettingsEnum.VstsInstance), GetSetting <string>(SettingsEnum.VstsPat), GetSetting <string>(SettingsEnum.VstsApiVersion)); rawTopic.Type = TopicBodyFormats.VstsWorkItem; } else if (TopicTypeHelper.IsMatch(rawTopic?.Type, TopicBodyFormats.VstsWorkItemQueries) && HttpContext.Request.Query.ContainsKey("queryid")) { // The current node is a list of work item queries, but we use it as a context to run the actual query var queryId = HttpContext.Request.Query["queryid"]; var queryInfoJson = await VstsHelper.GetWorkItemQueriesJson(queryId, GetSetting <string>(SettingsEnum.VstsInstance), GetSetting <string>(SettingsEnum.VstsProjectName), GetSetting <string>(SettingsEnum.VstsPat), GetSetting <string>(SettingsEnum.VstsApiVersion)); dynamic queryInfo = JObject.Parse(queryInfoJson); if (queryInfo != null) { Title = "Query: " + queryInfo.name; } rawTopic.OriginalContent = await VstsHelper.RunWorkItemQueryJson(queryId, GetSetting <string>(SettingsEnum.VstsInstance), GetSetting <string>(SettingsEnum.VstsProjectName), GetSetting <string>(SettingsEnum.VstsPat), GetSetting <string>(SettingsEnum.VstsApiVersion)); if (rawTopic.OriginalContent.StartsWith("{")) { rawTopic.Type = TopicBodyFormats.VstsWorkItemQuery; } else { rawTopic.Type = TopicBodyFormats.Markdown; // Something went wrong, but one way or another, we didn't end up with JSON } } else if (TopicTypeHelper.IsMatch(rawTopic?.Type, TopicBodyFormats.VstsWorkItem)) { // Plain work item node var itemNumber = int.Parse(SelectedTopic.Link); rawTopic.OriginalContent = await VstsHelper.GetWorkItemJson(itemNumber, GetSetting <string>(SettingsEnum.VstsInstance), GetSetting <string>(SettingsEnum.VstsPat), GetSetting <string>(SettingsEnum.VstsApiVersion)); } else if (TopicTypeHelper.IsMatch(rawTopic?.Type, TopicBodyFormats.VstsWorkItemQueries)) { // Plain work item queries rawTopic.OriginalContent = await VstsHelper.GetWorkItemQueriesJson(SelectedTopic.Link, GetSetting <string>(SettingsEnum.VstsInstance), GetSetting <string>(SettingsEnum.VstsProjectName), GetSetting <string>(SettingsEnum.VstsPat), GetSetting <string>(SettingsEnum.VstsApiVersion)); Title = SelectedTopic.Title; } else if (TopicTypeHelper.IsMatch(rawTopic?.Type, TopicBodyFormats.VstsWorkItemQuery)) { // Plain work item query rawTopic.OriginalContent = await VstsHelper.RunWorkItemQueryJson(SelectedTopic.Link, GetSetting <string>(SettingsEnum.VstsInstance), GetSetting <string>(SettingsEnum.VstsProjectName), GetSetting <string>(SettingsEnum.VstsPat), GetSetting <string>(SettingsEnum.VstsApiVersion)); Title = SelectedTopic.Title; } Vsts.ImageLink = "/___FileProxy___?mode=" + RepositoryTypeNames.VstsWorkItemTracking + "&topic=" + CurrentSlug + "&path="; break; } } var renderer = TopicRendererFactory.GetTopicRenderer(rawTopic); var intermediateHtml = renderer.RenderToHtml(rawTopic, ImageRootUrl, this); if (!string.IsNullOrEmpty(intermediateHtml)) { intermediateHtml = await ProcessKavaTopic(intermediateHtml); intermediateHtml = AutoGenerateTitle(intermediateHtml); intermediateHtml = ProcessBrokenImageLinks(intermediateHtml, ImageRootUrl); } Html = intermediateHtml; Json = renderer.RenderToJson(rawTopic, ImageRootUrl, this); TemplateName = renderer.GetTemplateName(rawTopic, TemplateName, this); if (string.IsNullOrEmpty(Html) && SelectedTopic != null) { var sb = new StringBuilder(); sb.Append("<h1>" + SelectedTopic.Title + "</h1>"); if (SelectedTopic.Topics.Count > 0) { sb.Append("<ul>"); foreach (var topic in SelectedTopic.Topics) { sb.Append("<li class=\"kava-auto-link\">"); sb.Append("<a href=\"" + TopicHelper.GetNormalizedName(topic.Title) + "\">"); sb.Append(topic.Title); sb.Append("</a>"); sb.Append("</li>"); } sb.Append("</ul>"); } Html = sb.ToString(); } }
private async Task BuildToc() { string tocJson = null; var repositoryType = RepositoryTypeHelper.GetTypeFromTypeName(GetSetting <string>(SettingsEnum.RepositoryType)); var logoUrl = GetSetting <string>(SettingsEnum.LogoPath); var logoUrlLower = logoUrl.ToLowerInvariant(); var logoUrlIsAbsolute = true; if (!logoUrl.StartsWith("http://") && !logoUrl.StartsWith("https://")) { logoUrlIsAbsolute = false; } LogoUrl = logoUrl; if (UseSqlServer) // SQL server *may* provide a local tabe of contents that would override all others { tocJson = await SqlDataAccess.GetRepositoryLocalTableOfContents(CurrentPrefix); } if (string.IsNullOrEmpty(tocJson)) { switch (repositoryType) { case RepositoryTypes.GitHubRaw: tocJson = await TableOfContentsHelper.GetTocJsonFromGitHubRaw(GitHubMasterUrlRaw); if (!logoUrlIsAbsolute) { LogoUrl = GitHubMasterUrlRaw + logoUrl; } break; case RepositoryTypes.GitHubApi: tocJson = await TableOfContentsHelper.GetTocJsonFromGitHubApi(GitHubOwner, GitHubRepository, GitHubPat); // TODO: if (!logoUrlIsAbsolute) // LogoUrl = GitHubMasterUrlRaw + logoUrl; break; case RepositoryTypes.VstsGit: tocJson = await VstsHelper.GetTocJson(GetSetting <string>(SettingsEnum.VstsInstance), GetSetting <string>(SettingsEnum.VstsProjectName), GetSetting <string>(SettingsEnum.VstsDocsFolder), GetSetting <string>(SettingsEnum.VstsPat), GetSetting <string>(SettingsEnum.VstsApiVersion)); if (!logoUrlIsAbsolute) { LogoUrl = $"/___FileProxy___?mode=vstsgit&path={logoUrl}"; } break; } } if (string.IsNullOrEmpty(tocJson)) { return; } var dynamicToc = TableOfContentsHelper.GetDynamicTocFromJson(tocJson); if (dynamicToc.title != null) { RepositoryTitle = dynamicToc.title; } if (dynamicToc.owner != null) { Owner = dynamicToc.owner; } Topics = TableOfContentsHelper.BuildTocFromDynamicToc(dynamicToc, this, CurrentSlug, out List <TableOfContentsItem> flatTopicList); FlatTopics = flatTopicList; MainMenu = TableOfContentsHelper.BuildMainMenuStructureFromDynamicToc(dynamicToc); var matchingTopic = FlatTopics.FirstOrDefault(t => TopicHelper.SlugMatchesTopic(CurrentSlug, t)); if (matchingTopic == null) { matchingTopic = FlatTopics.FirstOrDefault(t => TopicHelper.SlugMatchesTopic(CurrentSlug, t, true)); } if (matchingTopic == null) { matchingTopic = FlatTopics.FirstOrDefault(t => TopicHelper.LinkMatchesTopic(CurrentSlug, t)); } if (matchingTopic == null) { matchingTopic = Topics.FirstOrDefault(); } SelectedTopic = matchingTopic; TableOfContentsHelper.EnsureExpanded(SelectedTopic); TocSettings = dynamicToc.settings; CurrentTopicSettings = SelectedTopic?.SettingsDynamic; }
public async Task <IActionResult> FileProxy(string mode, string path, string topic = "", string fileName = "") { // Special processing for file retrieval of attachments to TFS work items. This is mainly used to return images in item descriptions. if (RepositoryTypeHelper.IsMatch(mode, RepositoryTypeNames.VstsWorkItemTracking)) { var model = new TopicViewModel(topic, HttpContext); if (SqlDataAccess.CanUseSql) { var prefix = ControllerHelper.GetCurrentDomainPrefix(HttpContext.Request); var settings = await SqlDataAccess.GetSqlRepositorySettingsDynamic(prefix); if (settings == null) { return(NotFound($"Document repository {prefix} does not exist.")); } model.SetRootSettingsForRequest(settings); } await model.LoadData(buildHtml : false, buildToc : true); var instance = model.GetSetting <string>(SettingsEnum.VstsInstance); var pat = model.GetSetting <string>(SettingsEnum.VstsPat); var stream = await VstsHelper.GetWorkItemAttachmentStream(path, instance, pat); return(File(stream, GetContentTypeFromUrl(fileName), fileName)); } // If we got this far, and the path is a fully qualified URL, then we just retrieve it if (path.ToLowerInvariant().StartsWith("http://") || path.ToLowerInvariant().StartsWith("https://")) { using (var client = new WebClientEx()) { var data = await client.DownloadDataTaskAsync(new Uri(path)); return(File(data, GetContentTypeFromUrl(path), StringHelper.JustFileName(path))); } } // If it is in a VSTS Git repository, we use the API to retrieve it if (RepositoryTypeHelper.IsMatch(mode, RepositoryTypeNames.VstsGit)) { if (SqlDataAccess.CanUseSql) { var prefix = ControllerHelper.GetCurrentDomainPrefix(HttpContext.Request); var settings = await SqlDataAccess.GetSqlRepositorySettingsDynamic(prefix); if (settings == null) { return(NotFound($"Document repository {prefix} does not exist.")); } var stream = await VstsHelper.GetFileStream(path, SettingsHelper.GetSetting <string>(SettingsEnum.VstsInstance, requestRootSettings: settings), SettingsHelper.GetSetting <string>(SettingsEnum.VstsProjectName, requestRootSettings: settings), SettingsHelper.GetSetting <string>(SettingsEnum.VstsDocsFolder, requestRootSettings: settings), SettingsHelper.GetSetting <string>(SettingsEnum.VstsPat, requestRootSettings: settings), SettingsHelper.GetSetting <string>(SettingsEnum.VstsApiVersion, requestRootSettings: settings)); return(File(stream, GetContentTypeFromUrl(path), StringHelper.JustFileName(path))); } else { var stream = await VstsHelper.GetFileStream(path, SettingsHelper.GetSetting <string>(SettingsEnum.VstsInstance), SettingsHelper.GetSetting <string>(SettingsEnum.VstsProjectName), SettingsHelper.GetSetting <string>(SettingsEnum.VstsDocsFolder), SettingsHelper.GetSetting <string>(SettingsEnum.VstsPat), SettingsHelper.GetSetting <string>(SettingsEnum.VstsApiVersion)); return(File(stream, GetContentTypeFromUrl(path), StringHelper.JustFileName(path))); } } // Otherwise, we got nothing :-) return(null); }