From 792875501cc8314727d13cc544046a36e7bd2511 Mon Sep 17 00:00:00 2001 From: Salih Date: Thu, 21 Mar 2024 17:33:35 +0300 Subject: [PATCH] Improve --- .../app/VoloDocs.Web/Pages/Index.cshtml.cs | 16 +- .../app/VoloDocs.Web/VoloDocsWebModule.cs | 2 + .../Documents/TagHelpers/TreeTagHelper.cs | 25 ++- .../docs/src/Volo.Docs.Web/DocsUiOptions.cs | 13 ++ .../docs/src/Volo.Docs.Web/DocsWebModule.cs | 21 ++- .../MarkdownDocumentToHtmlConverter.cs | 40 +++-- .../Pages/Documents/Index.cshtml.cs | 7 +- .../Pages/Documents/Project/Index.cshtml | 5 +- .../Pages/Documents/Project/Index.cshtml.cs | 143 +++++++++--------- 9 files changed, 163 insertions(+), 109 deletions(-) diff --git a/modules/docs/app/VoloDocs.Web/Pages/Index.cshtml.cs b/modules/docs/app/VoloDocs.Web/Pages/Index.cshtml.cs index 8e4a26db44..ce039c1acf 100644 --- a/modules/docs/app/VoloDocs.Web/Pages/Index.cshtml.cs +++ b/modules/docs/app/VoloDocs.Web/Pages/Index.cshtml.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; @@ -49,11 +48,16 @@ namespace VoloDocs.Web.Pages //Eg: "/en/abp/latest" public string GetUrlForProject(ProjectDto project, string language = "en", string version = null) { - return "." + - _urlUiOptions.RoutePrefix.EnsureStartsWith('/').EnsureEndsWith('/') + - language.EnsureEndsWith('/') + - project.ShortName.EnsureEndsWith('/') + - (version ?? DocsAppConsts.Latest); + var routeValues = new Dictionary { + { nameof(Volo.Docs.Pages.Documents.Project.IndexModel.LanguageCode), language }, + { nameof(Volo.Docs.Pages.Documents.Project.IndexModel.Version), version ?? DocsAppConsts.Latest }, + }; + + if (!_urlUiOptions.SingleProjectMode.Enable) + { + routeValues.Add(nameof(Volo.Docs.Pages.Documents.Project.IndexModel.ProjectName), project.ShortName); + } + return Url.Page("/Documents/Project/Index", routeValues); } } } diff --git a/modules/docs/app/VoloDocs.Web/VoloDocsWebModule.cs b/modules/docs/app/VoloDocs.Web/VoloDocsWebModule.cs index 3738b1071b..b218819b94 100644 --- a/modules/docs/app/VoloDocs.Web/VoloDocsWebModule.cs +++ b/modules/docs/app/VoloDocs.Web/VoloDocsWebModule.cs @@ -78,6 +78,8 @@ namespace VoloDocs.Web Configure(options => { options.RoutePrefix = null; + options.SingleProjectMode.Enable = true; + options.SingleProjectMode.ProjectName = "abp"; }); Configure(options => diff --git a/modules/docs/src/Volo.Docs.Web/Areas/Documents/TagHelpers/TreeTagHelper.cs b/modules/docs/src/Volo.Docs.Web/Areas/Documents/TagHelpers/TreeTagHelper.cs index 5a5567c81e..f30b113acc 100644 --- a/modules/docs/src/Volo.Docs.Web/Areas/Documents/TagHelpers/TreeTagHelper.cs +++ b/modules/docs/src/Volo.Docs.Web/Areas/Documents/TagHelpers/TreeTagHelper.cs @@ -1,11 +1,15 @@ using System; +using System.Collections.Generic; using System.Linq; using System.Text; +using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Razor.TagHelpers; +using Microsoft.AspNetCore.Routing; using Microsoft.Extensions.Localization; using Microsoft.Extensions.Options; using Volo.Docs.Documents; using Volo.Docs.Localization; +using Volo.Docs.Pages.Documents.Project; using Volo.Docs.Utils; namespace Volo.Docs.Areas.Documents.TagHelpers @@ -18,6 +22,8 @@ namespace Volo.Docs.Areas.Documents.TagHelpers private readonly DocsUiOptions _uiOptions; private readonly IStringLocalizer _localizer; + + private readonly LinkGenerator _linkGenerator; private const string LiItemTemplateWithLink = @"
  • {2}{3}
  • "; @@ -45,10 +51,11 @@ namespace Volo.Docs.Areas.Documents.TagHelpers [HtmlAttributeName("language")] public string LanguageCode { get; set; } - public TreeTagHelper(IOptions urlOptions, IStringLocalizer localizer) + public TreeTagHelper(IOptions urlOptions, IStringLocalizer localizer, LinkGenerator linkGenerator) { _localizer = localizer; _uiOptions = urlOptions.Value; + _linkGenerator = linkGenerator; } public override void Process(TagHelperContext context, TagHelperOutput output) @@ -172,11 +179,19 @@ namespace Volo.Docs.Areas.Documents.TagHelpers { return "javascript:;"; } - - var prefix = _uiOptions.RoutePrefix; - var sb = new StringBuilder(); - return sb.Append(prefix).Append(LanguageCode).Append("/").Append(ProjectName).Append("/").Append(Version).Append("/").Append(pathWithoutFileExtension).ToString(); + var routeValues = new Dictionary { + { nameof(IndexModel.LanguageCode), LanguageCode }, + { nameof(IndexModel.Version), Version }, + { nameof(IndexModel.DocumentName), pathWithoutFileExtension } + }; + + if (!_uiOptions.SingleProjectMode.Enable) + { + routeValues.Add(nameof(IndexModel.ProjectName), ProjectName); + } + + return _linkGenerator.GetPathByPage("/Documents/Project/Index", values: routeValues); } private string RemoveFileExtensionFromPath(string path) diff --git a/modules/docs/src/Volo.Docs.Web/DocsUiOptions.cs b/modules/docs/src/Volo.Docs.Web/DocsUiOptions.cs index c2406e15f5..2119c958c2 100644 --- a/modules/docs/src/Volo.Docs.Web/DocsUiOptions.cs +++ b/modules/docs/src/Volo.Docs.Web/DocsUiOptions.cs @@ -32,6 +32,8 @@ namespace Volo.Docs /// Default value: True; /// public bool SectionRendering = true; + + public SingleProjectModeOptions SingleProjectMode { get; } = new (); private string GetFormattedRoutePrefix() { @@ -43,4 +45,15 @@ namespace Volo.Docs return _routePrefix.EnsureEndsWith('/').EnsureStartsWith('/'); } } + + public class SingleProjectModeOptions + { + /// + /// Determines whether to enable single project mode by removing the project name from the routing. + /// When enabled, only a single project is allowed within the module. + /// + public bool Enable { get; set; } + + public string ProjectName { get; set; } + } } diff --git a/modules/docs/src/Volo.Docs.Web/DocsWebModule.cs b/modules/docs/src/Volo.Docs.Web/DocsWebModule.cs index ddc40b36a1..3fd89255cf 100644 --- a/modules/docs/src/Volo.Docs.Web/DocsWebModule.cs +++ b/modules/docs/src/Volo.Docs.Web/DocsWebModule.cs @@ -61,10 +61,23 @@ namespace Volo.Docs var routePrefix = docsOptions.RoutePrefix; - options.Conventions.AddPageRoute("/Documents/Project/Index", routePrefix + "{projectName}"); - options.Conventions.AddPageRoute("/Documents/Project/Index", routePrefix + "{languageCode}/{projectName}"); - options.Conventions.AddPageRoute("/Documents/Project/Index", routePrefix + "{languageCode}/{projectName}/{version}/{*documentName}"); - options.Conventions.AddPageRoute("/Documents/Search", routePrefix + "search/{languageCode}/{projectName}/{version}"); + if (docsOptions.SingleProjectMode.Enable) + { + if (routePrefix != "/") + { + options.Conventions.AddPageRoute("/Documents/Project/Index", routePrefix); + } + options.Conventions.AddPageRoute("/Documents/Project/Index", routePrefix + "{languageCode}"); + options.Conventions.AddPageRoute("/Documents/Project/Index", routePrefix + "{languageCode}/{version}/{*documentName}"); + options.Conventions.AddPageRoute("/Documents/Search", routePrefix + "search/{languageCode}/{version}"); + } + else + { + options.Conventions.AddPageRoute("/Documents/Project/Index", routePrefix + "{projectName}"); + options.Conventions.AddPageRoute("/Documents/Project/Index", routePrefix + "{languageCode}/{projectName}"); + options.Conventions.AddPageRoute("/Documents/Project/Index", routePrefix + "{languageCode}/{projectName}/{version}/{*documentName}"); + options.Conventions.AddPageRoute("/Documents/Search", routePrefix + "search/{languageCode}/{projectName}/{version}"); + } }); context.Services.AddAutoMapperObjectMapper(); diff --git a/modules/docs/src/Volo.Docs.Web/Markdown/MarkdownDocumentToHtmlConverter.cs b/modules/docs/src/Volo.Docs.Web/Markdown/MarkdownDocumentToHtmlConverter.cs index 48daaff769..ea3cdb02cb 100644 --- a/modules/docs/src/Volo.Docs.Web/Markdown/MarkdownDocumentToHtmlConverter.cs +++ b/modules/docs/src/Volo.Docs.Web/Markdown/MarkdownDocumentToHtmlConverter.cs @@ -1,10 +1,12 @@ using System; -using System.Diagnostics; +using System.Collections.Generic; using System.Text.RegularExpressions; +using Microsoft.AspNetCore.Routing; using Microsoft.Extensions.Options; using Volo.Abp.DependencyInjection; using Volo.Docs.Documents; using Volo.Docs.HtmlConverting; +using Volo.Docs.Pages.Documents.Project; using Volo.Docs.Projects; using Volo.Docs.Utils; @@ -16,15 +18,17 @@ namespace Volo.Docs.Markdown private readonly IMarkdownConverter _markdownConverter; private readonly DocsUiOptions _uiOptions; + private readonly LinkGenerator _linkGenerator; public MarkdownDocumentToHtmlConverter(IMarkdownConverter markdownConverter, - IOptions urlOptions) + IOptions urlOptions, LinkGenerator linkGenerator) { _markdownConverter = markdownConverter; + _linkGenerator = linkGenerator; _uiOptions = urlOptions.Value; } - private const string MdLinkFormat = "[{0}]({1}{2}/{3}/{4}{5}/{6})"; + private const string MdLinkFormat = "[{0}]({1})"; private const string MarkdownLinkRegExp = @"\[(.*?)\]\(((.*?)(\?(.*?))*?)\)"; private const string AnchorLinkRegExp = @"]+href=\""(.*?)\""[^>]*>(.*)?"; @@ -117,12 +121,7 @@ namespace Volo.Docs.Markdown return string.Format( MdLinkFormat, displayText, - _uiOptions.RoutePrefix, - languageCode, - projectShortName, - version, - documentLocalDirectoryNormalized, - documentName + GenerateUrl(languageCode, $"{version}{documentLocalDirectoryNormalized}", documentName, projectShortName) ); }); } @@ -149,12 +148,7 @@ namespace Volo.Docs.Markdown return string.Format( MdLinkFormat, displayText, - _uiOptions.RoutePrefix, - languageCode, - projectShortName, - version, - documentLocalDirectoryNormalized, - documentName + GenerateUrl(languageCode, $"{version}{documentLocalDirectoryNormalized}", documentName, projectShortName) ); }); } @@ -178,5 +172,21 @@ namespace Volo.Docs.Markdown return documentName.Left(documentName.Length - Type.Length - 1); } + + private string GenerateUrl(string languageCode, string version, string documentName, string projectShortName) + { + var routeValues = new Dictionary { + { nameof(IndexModel.LanguageCode), languageCode }, + { nameof(IndexModel.Version), version }, + { nameof(IndexModel.DocumentName), documentName } + }; + + if (!_uiOptions.SingleProjectMode.Enable) + { + routeValues.Add(nameof(IndexModel.ProjectName), projectShortName); + } + + return _linkGenerator.GetPathByPage("/Documents/Project/Index", values: routeValues); + } } } diff --git a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Index.cshtml.cs b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Index.cshtml.cs index 74fa74090d..82b43dbfca 100644 --- a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Index.cshtml.cs +++ b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Index.cshtml.cs @@ -27,13 +27,16 @@ namespace Volo.Docs.Pages.Documents public virtual async Task OnGetAsync() { - DocumentsUrlPrefix = _uiOptions.RoutePrefix; + if (_uiOptions.SingleProjectMode.Enable) + { + return RedirectToPage("/Documents/Project/Index"); + } var listResult = await _projectAppService.GetListAsync(); if (listResult.Items.Count == 1) { - return Redirect(DocumentsUrlPrefix + listResult.Items[0].ShortName); + return RedirectToPage("/Documents/Project/Index", new { shortName = listResult.Items[0].ShortName }); } Projects = listResult.Items; diff --git a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml index dfb379f5ae..f216b0cc20 100644 --- a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml +++ b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml @@ -480,7 +480,7 @@ else { model = new ErrorPageModel { - RedirectUrl = Model.DocumentsUrlPrefix, + RedirectUrl = Url.Page("/Projects/Index"), ErrorCode = "404", ErrorMessage = L.GetString("ProjectNotFound") } @@ -493,8 +493,7 @@ else { model = new ErrorPageModel { - RedirectUrl = Model.DocumentsUrlPrefix + Model.LanguageCode + "/" + Model.ProjectName + "/" - + (Model.LatestVersionInfo.IsSelected ? DocsAppConsts.Latest : Model.Version), + RedirectUrl = Model.BuildDocumentUrl(Model.ProjectName, Model.LanguageCode, Model.LatestVersionInfo.IsSelected ? DocsAppConsts.Latest : Model.Version, null), ErrorCode = "404", ErrorMessage = L.GetString("DocumentNotFound"), AutoRedirect = !Model.DocumentName.IsNullOrWhiteSpace() diff --git a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml.cs b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml.cs index e93be287f8..42c8240bea 100644 --- a/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml.cs +++ b/modules/docs/src/Volo.Docs.Web/Pages/Documents/Project/Index.cshtml.cs @@ -63,8 +63,6 @@ namespace Volo.Docs.Pages.Documents.Project public VersionInfoViewModel LatestVersionInfo { get; private set; } - public string DocumentsUrlPrefix { get; set; } - public bool ShowProjectsCombobox { get; set; } public bool ShowProjectsComboboxLabel { get; set; } @@ -149,8 +147,7 @@ namespace Volo.Docs.Pages.Documents.Project private async Task SetPageAsync() { - DocumentsUrlPrefix = _uiOptions.RoutePrefix; - ShowProjectsCombobox = _uiOptions.ShowProjectsCombobox; + ShowProjectsCombobox = _uiOptions.ShowProjectsCombobox && !_uiOptions.SingleProjectMode.Enable; ShowProjectsComboboxLabel = ShowProjectsCombobox && _uiOptions.ShowProjectsComboboxLabel; FullSearchEnabled = await _documentAppService.FullSearchEnabledAsync(); @@ -217,6 +214,29 @@ namespace Volo.Docs.Pages.Documents.Project private async Task SetProjectAsync() { + if (!_uiOptions.SingleProjectMode.Enable) + { + Project = await _projectAppService.GetAsync(ProjectName); + return; + } + + var singleProjectName = _uiOptions.SingleProjectMode.ProjectName; + if (!singleProjectName.IsNullOrWhiteSpace()) + { + Project = await _projectAppService.GetAsync(singleProjectName); + ProjectName = singleProjectName; + return; + } + + var listResult = await _projectAppService.GetListAsync(); + if (listResult.Items.Count == 1) + { + Project = listResult.Items[0]; + ProjectName = Project.ShortName; + return; + } + + ProjectName = singleProjectName; Project = await _projectAppService.GetAsync(ProjectName); } @@ -233,61 +253,63 @@ namespace Volo.Docs.Pages.Documents.Project private bool CheckLanguage() { - return LanguageConfig.Languages.Any(l => l.Code == LanguageCode); + return LanguageConfig.Languages.Any(l => l.Code.Equals(LanguageCode, StringComparison.OrdinalIgnoreCase)); } private IActionResult ReloadPageWithCulture() { - var sb = new StringBuilder(); - - var returnUrl = sb.Append(DocumentsUrlPrefix).Append(LanguageCode).Append("/").Append(ProjectName) - .Append("/").Append(LatestVersionInfo.IsSelected ? DocsAppConsts.Latest : Version).Append("/").Append(DocumentName).ToString(); - - sb.Clear(); - - return Redirect(sb.Append("/Abp/Languages/Switch?culture=").Append(LanguageCode).Append("&uiCulture=") - .Append(LanguageCode).Append("&returnUrl=").Append(returnUrl).ToString()); + return Redirect( + new StringBuilder() + .Append("/Abp/Languages/Switch?culture=") + .Append(LanguageCode).Append("&uiCulture=") + .Append(LanguageCode).Append("&returnUrl=").Append(BuildDocumentUrl(ProjectName, LanguageCode, + LatestVersionInfo.IsSelected ? DocsAppConsts.Latest : Version, DocumentName)).ToString()); } public string GetFullUrlOfTheLatestDocument() { - return Request.Scheme + "://" + Request.Host.Value + Request.PathBase + - DocumentsUrlPrefix + LanguageCode + "/" + ProjectName + "/" + - DocsAppConsts.Latest + "/" + DocumentName; + return Request.Scheme + Uri.SchemeDelimiter + Request.Host.Value + Request.PathBase + BuildDocumentUrl(ProjectName, LanguageCode, DocsAppConsts.Latest, DocumentName); } public string CreateDocumentLink(string documentName) { - return new StringBuilder() - .Append(DocumentsUrlPrefix) - .Append(LanguageCode) - .Append('/') - .Append(ProjectName) - .Append('/') - .Append(LatestVersionInfo.IsSelected ? DocsAppConsts.Latest : Version) - .Append('/') - .Append(documentName) - .ToString(); + return BuildDocumentUrl(ProjectName, LanguageCode, LatestVersionInfo.IsSelected ? DocsAppConsts.Latest : Version, documentName); + } + + public string BuildDocumentUrl(string projectName, string languageCode, string version, string documentName) + { + var routeValues = new Dictionary { + { nameof(LanguageCode), languageCode }, + { nameof(Version), version }, + { nameof(DocumentName), documentName } + }; + + if (!_uiOptions.SingleProjectMode.Enable) + { + routeValues.Add(nameof(ProjectName), projectName); + } + + return Url.Page("/Documents/Project/Index", routeValues); } private IActionResult RedirectToDefaultLanguage() { - return RedirectToPage(new { - projectName = ProjectName, - version = (LatestVersionInfo.IsSelected ? DocsAppConsts.Latest : Version), - languageCode = DefaultLanguageCode, - documentName = DocumentName - }); + return RedirectToPage(BuildDocumentUrl( + projectName : ProjectName, + version : (LatestVersionInfo.IsSelected ? DocsAppConsts.Latest : Version), + languageCode : DefaultLanguageCode, + documentName : DocumentName + )); } private IActionResult RedirectToDefaultDocument() { - return RedirectToPage(new { - projectName = ProjectName, - version = (LatestVersionInfo.IsSelected ? DocsAppConsts.Latest : Version), - documentName = "", - languageCode = DefaultLanguageCode - }); + return RedirectToPage(BuildDocumentUrl ( + projectName : ProjectName, + version : (LatestVersionInfo.IsSelected ? DocsAppConsts.Latest : Version), + documentName : "", + languageCode : DefaultLanguageCode + )); } private async Task SetProjectsAsync() @@ -308,15 +330,7 @@ namespace Volo.Docs.Pages.Documents.Project { return null; } - - return new StringBuilder() - .Append(DocumentsUrlPrefix) - .Append(LanguageCode) - .Append('/') - .Append(project.ShortName) - .Append('/') - .Append(DocsAppConsts.Latest) - .ToString(); + return BuildDocumentUrl(project.ShortName, LanguageCode, Version, null); } private async Task SetVersionAsync() @@ -458,16 +472,8 @@ namespace Volo.Docs.Pages.Documents.Project { version = DocsAppConsts.Latest; } - - var linkStringBuilder = new StringBuilder(); - linkStringBuilder.Append(DocumentsUrlPrefix).Append(LanguageCode).Append("/").Append(ProjectName).Append("/").Append(version); - - if (documentName != null) - { - linkStringBuilder.Append("/").Append(DocumentName); - } - - return linkStringBuilder.ToString(); + + return BuildDocumentUrl(ProjectName, LanguageCode, version, documentName); } public string GetSpecificVersionOrLatest() @@ -513,19 +519,15 @@ namespace Volo.Docs.Pages.Documents.Project { LanguageSelectListItems = new List(); - var sb = new StringBuilder(); - foreach (var language in LanguageConfig.Languages) { LanguageSelectListItems.Add( new SelectListItem( language.DisplayName, - sb.Append(DocumentsUrlPrefix).Append(language.Code).Append("/").Append(Project.ShortName).Append("/").Append(LatestVersionInfo.IsSelected ? DocsAppConsts.Latest : Version).Append("/").Append(DocumentName).ToString(), - language.Code == LanguageCode - ) - ); - - sb.Clear(); + BuildDocumentUrl(ProjectName, language.Code, LatestVersionInfo.IsSelected ? DocsAppConsts.Latest : Version, DocumentName), + language.Code.Equals(LanguageCode, StringComparison.OrdinalIgnoreCase) + ) + ); } } @@ -578,14 +580,7 @@ namespace Volo.Docs.Pages.Documents.Project { foreach (var parameter in partialTemplates.Parameters) { - if (!UserPreferences.ContainsKey(parameter.Key)) - { - UserPreferences.Add(parameter.Key, parameter.Value); - } - else - { - UserPreferences[parameter.Key] = parameter.Value; - } + UserPreferences[parameter.Key] = parameter.Value; } }