Browse Source

#closes 3381

pull/3399/head
Alper Ebicoglu 7 years ago
parent
commit
84890bb919
  1. 7
      modules/docs/app/VoloDocs.Web/Controllers/HomeController.cs
  2. 5
      modules/docs/app/VoloDocs.Web/Pages/Index.cshtml
  3. 29
      modules/docs/app/VoloDocs.Web/Pages/Index.cshtml.cs
  4. 2796
      modules/docs/app/VoloDocs.Web/package-lock.json
  5. 2
      modules/docs/app/VoloDocs.Web/package.json
  6. 12
      modules/docs/src/Volo.Docs.Admin.Application/Volo/Docs/Admin/Documents/DocumentAdminAppService.cs
  7. 20
      modules/docs/src/Volo.Docs.Application/Volo/Docs/Documents/DocumentAppService.cs
  8. 7
      modules/docs/src/Volo.Docs.Domain/Volo/Docs/DocsDomainConsts.cs
  9. 15
      modules/docs/src/Volo.Docs.Domain/Volo/Docs/FileSystem/Documents/FileSystemDocumentSource.cs
  10. 15
      modules/docs/src/Volo.Docs.Domain/Volo/Docs/GitHub/Documents/GithubDocumentSource.cs
  11. 22
      modules/docs/src/Volo.Docs.Domain/Volo/Extensions/NewtonsoftJsonExtensions.cs
  12. 109
      modules/docs/src/Volo.Docs.Web/HtmlConverting/ScribanDocumentSectionRenderer.cs
  13. 1
      modules/docs/src/Volo.Docs.Web/Volo.Docs.Web.csproj

7
modules/docs/app/VoloDocs.Web/Controllers/HomeController.cs

@ -6,7 +6,14 @@ namespace VoloDocs.Web.Controllers
{
public void Index()
{
//if (!_urlUiOptions.RoutePrefix.IsNullOrWhiteSpace())
//{
// return Redirect("." + _urlUiOptions.RoutePrefix);
//}
//return Page();
//return Redirect("/en/abp/latest");
}
}
}

5
modules/docs/app/VoloDocs.Web/Pages/Index.cshtml

@ -1,5 +0,0 @@
@page
@model VoloDocs.Web.Pages.IndexModel
@{
}

29
modules/docs/app/VoloDocs.Web/Pages/Index.cshtml.cs

@ -1,29 +0,0 @@
using System;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Options;
using Volo.Docs;
namespace VoloDocs.Web.Pages
{
public class IndexModel : PageModel
{
private readonly DocsUiOptions _urlUiOptions;
public IndexModel(IOptions<DocsUiOptions> urlOptions)
{
_urlUiOptions = urlOptions.Value;
}
public IActionResult OnGet()
{
//TODO: Create HomeController & Index instead of Page. Otherwise, we have an empty Index.cshtml file.
if (!_urlUiOptions.RoutePrefix.IsNullOrWhiteSpace())
{
return Redirect("." + _urlUiOptions.RoutePrefix);
}
return Page();
}
}
}

2796
modules/docs/app/VoloDocs.Web/package-lock.json

File diff suppressed because it is too large

2
modules/docs/app/VoloDocs.Web/package.json

@ -6,4 +6,4 @@
"@abp/aspnetcore.mvc.ui.theme.basic": "^1.0.2",
"@abp/docs": "^1.0.2"
}
}
}

12
modules/docs/src/Volo.Docs.Admin.Application/Volo/Docs/Admin/Documents/DocumentAdminAppService.cs

@ -4,11 +4,13 @@ using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Newtonsoft.Json;
using Volo.Abp;
using Volo.Abp.Application.Services;
using Volo.Abp.Caching;
using Volo.Docs.Documents;
using Volo.Docs.Documents.FullSearch.Elastic;
using Volo.Docs.Projects;
using Volo.Extensions;
namespace Volo.Docs.Admin.Documents
{
@ -38,15 +40,19 @@ namespace Volo.Docs.Admin.Documents
{
var project = await _projectRepository.GetAsync(input.ProjectId);
var navigationFile = await GetDocumentAsync(
var navigationDocument = await GetDocumentAsync(
project,
project.NavigationDocumentName,
input.LanguageCode,
input.Version
);
var nav = JsonConvert.DeserializeObject<NavigationNode>(navigationFile.Content);
var leafs = nav.Items.GetAllNodes(x => x.Items)
if (!JsonConvertExtensions.TryDeserializeObject<NavigationNode>(navigationDocument.Content, out var navigation))
{
throw new UserFriendlyException($"Cannot validate navigation file '{project.NavigationDocumentName}' for the project {project.Name}.");
}
var leafs = navigation.Items.GetAllNodes(x => x.Items)
.Where(x => x.IsLeaf && !x.Path.IsNullOrWhiteSpace())
.ToList();

20
modules/docs/src/Volo.Docs.Application/Volo/Docs/Documents/DocumentAppService.cs

@ -7,9 +7,11 @@ using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using Volo.Abp;
using Volo.Abp.Caching;
using Volo.Docs.Documents.FullSearch.Elastic;
using Volo.Docs.Projects;
using Volo.Extensions;
namespace Volo.Docs.Documents
{
@ -32,8 +34,8 @@ namespace Volo.Docs.Documents
IDistributedCache<LanguageConfig> languageCache,
IDistributedCache<DocumentResourceDto> resourceCache,
IDistributedCache<DocumentUpdateInfo> documentUpdateCache,
IHostEnvironment hostEnvironment,
IDocumentFullSearch documentFullSearch,
IHostEnvironment hostEnvironment,
IDocumentFullSearch documentFullSearch,
IOptions<DocsElasticSearchOptions> docsElasticSearchOptions)
{
_projectRepository = projectRepository;
@ -82,7 +84,10 @@ namespace Volo.Docs.Documents
input.Version
);
var navigationNode = JsonConvert.DeserializeObject<NavigationNode>(navigationDocument.Content);
if (!JsonConvertExtensions.TryDeserializeObject<NavigationNode>(navigationDocument.Content, out var navigationNode))
{
throw new UserFriendlyException($"Cannot validate navigation file '{project.NavigationDocumentName}' for the project {project.Name}.");
}
var leafs = navigationNode.Items.GetAllNodes(x => x.Items)
.Where(x => !x.Path.IsNullOrWhiteSpace())
@ -173,11 +178,16 @@ namespace Volo.Docs.Documents
input.Version
);
return JsonConvert.DeserializeObject<DocumentParametersDto>(document.Content);
if (!JsonConvertExtensions.TryDeserializeObject<DocumentParametersDto>(document.Content, out var documentParameters))
{
throw new UserFriendlyException($"Cannot validate document parameters file '{project.ParametersDocumentName}' for the project {project.Name}.");
}
return documentParameters;
}
catch (DocumentNotFoundException)
{
Logger.LogWarning($"Parameter file ({project.ParametersDocumentName}) not found.");
Logger.LogWarning($"Parameter file ({project.ParametersDocumentName}) not found!");
return new DocumentParametersDto();
}
}

7
modules/docs/src/Volo.Docs.Domain/Volo/Docs/DocsDomainConsts.cs

@ -0,0 +1,7 @@
namespace Volo.Docs
{
public class DocsDomainConsts
{
public static string LanguageConfigFileName = "docs-langs.json";
}
}

15
modules/docs/src/Volo.Docs.Domain/Volo/Docs/FileSystem/Documents/FileSystemDocumentSource.cs

@ -4,11 +4,13 @@ using System.IO;
using System.Security;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Volo.Abp;
using Volo.Abp.Domain.Services;
using Volo.Abp.IO;
using Volo.Docs.Documents;
using Volo.Docs.FileSystem.Projects;
using Volo.Docs.Projects;
using Volo.Extensions;
namespace Volo.Docs.FileSystem.Documents
{
@ -22,7 +24,7 @@ namespace Volo.Docs.FileSystem.Documents
var path = Path.Combine(projectFolder, languageCode, documentName);
CheckDirectorySecurity(projectFolder, path);
var content = await FileHelper.ReadAllTextAsync(path);
var localDirectory = "";
@ -55,10 +57,15 @@ namespace Volo.Docs.FileSystem.Documents
public async Task<LanguageConfig> GetLanguageListAsync(Project project, string version)
{
var path = Path.Combine(project.GetFileSystemPath(), "docs-langs.json");
var configAsJson = await FileHelper.ReadAllTextAsync(path);
var path = Path.Combine(project.GetFileSystemPath(), DocsDomainConsts.LanguageConfigFileName);
var configJsonContent = await FileHelper.ReadAllTextAsync(path);
if (!JsonConvertExtensions.TryDeserializeObject<LanguageConfig>(configJsonContent, out var languageConfig))
{
throw new UserFriendlyException($"Cannot validate language config file '{DocsDomainConsts.LanguageConfigFileName}' for the project {project.Name}.");
}
return JsonConvert.DeserializeObject<LanguageConfig>(configAsJson);
return languageConfig;
}
public async Task<DocumentResource> GetResource(Project project, string resourceName, string languageCode, string version)

15
modules/docs/src/Volo.Docs.Domain/Volo/Docs/GitHub/Documents/GithubDocumentSource.cs

@ -10,6 +10,8 @@ using Volo.Docs.GitHub.Projects;
using Volo.Docs.Projects;
using Newtonsoft.Json.Linq;
using Octokit;
using Volo.Abp;
using Volo.Extensions;
using Project = Volo.Docs.Projects.Project;
namespace Volo.Docs.GitHub.Documents
@ -55,11 +57,11 @@ namespace Volo.Docs.GitHub.Documents
var lastSignificantUpdateTime = !isNavigationDocument && !isParameterDocument && version == project.LatestVersionBranchName ?
await GetLastSignificantUpdateTime(
fileCommits,
project,
project,
project.GetGitHubInnerUrl(languageCode, documentName),
lastKnownSignificantUpdateTime,
documentCreationTime
) ?? lastKnownSignificantUpdateTime
) ?? lastKnownSignificantUpdateTime
: null;
var document = new Document(GuidGenerator.Create(),
@ -179,11 +181,16 @@ namespace Volo.Docs.GitHub.Documents
var rootUrl = project.GetGitHubUrl(version);
var userAgent = project.GetGithubUserAgentOrNull();
var url = CalculateRawRootUrl(rootUrl) + "docs-langs.json";
var url = CalculateRawRootUrl(rootUrl) + DocsDomainConsts.LanguageConfigFileName;
var configAsJson = await DownloadWebContentAsStringAsync(url, token, userAgent);
return JsonConvert.DeserializeObject<LanguageConfig>(configAsJson);
if (!JsonConvertExtensions.TryDeserializeObject<LanguageConfig>(configAsJson, out var languageConfig))
{
throw new UserFriendlyException($"Cannot validate language config file '{DocsDomainConsts.LanguageConfigFileName}' for the project {project.Name} - v{version}.");
}
return languageConfig;
}
private async Task<IReadOnlyList<Release>> GetReleasesAsync(Project project)

22
modules/docs/src/Volo.Docs.Domain/Volo/Extensions/NewtonsoftJsonExtensions.cs

@ -0,0 +1,22 @@
using System;
using Newtonsoft.Json;
namespace Volo.Extensions
{
public static class JsonConvertExtensions
{
public static bool TryDeserializeObject<T>(string jsonContent, out T result)
{
try
{
result = JsonConvert.DeserializeObject<T>(jsonContent);
return true;
}
catch
{
result = default;
return false;
}
}
}
}

109
modules/docs/src/Volo.Docs.Web/HtmlConverting/ScribanDocumentSectionRenderer.cs

@ -7,16 +7,17 @@ using Newtonsoft.Json;
using Scriban;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Volo.Docs.Documents;
using Volo.Abp;
using Volo.Extensions;
namespace Volo.Docs.HtmlConverting
{
public class ScribanDocumentSectionRenderer : IDocumentSectionRenderer
{
private const string jsonOpener = "````json";
private const string jsonCloser = "````";
private const string docs_param = "//[doc-params]";
private const string docs_templates = "//[doc-template]";
private const string JsonOpener = "````json";
private const string JsonCloser = "````";
private const string DocsParam = "//[doc-params]";
private const string DocsTemplates = "//[doc-template]";
public ILogger<ScribanDocumentSectionRenderer> Logger { get; set; }
@ -40,6 +41,7 @@ namespace Volo.Docs.HtmlConverting
}
var result = await scribanTemplate.RenderAsync(parameters);
return RemoveOptionsJson(result);
}
@ -47,7 +49,7 @@ namespace Volo.Docs.HtmlConverting
{
try
{
if (!document.Contains(jsonOpener) || !document.Contains(docs_param))
if (!document.Contains(JsonOpener) || !document.Contains(DocsParam))
{
return new Dictionary<string, List<string>>();
}
@ -59,9 +61,14 @@ namespace Volo.Docs.HtmlConverting
return new Dictionary<string, List<string>>();
}
var pureJson = insideJsonSection.Replace(docs_param, "").Trim();
var pureJson = insideJsonSection.Replace(DocsParam, "").Trim();
if (!JsonConvertExtensions.TryDeserializeObject<Dictionary<string, List<string>>>(pureJson, out var availableParameters))
{
throw new UserFriendlyException("ERROR-20200327: Cannot validate JSON content for `AvailableParameters`!");
}
return JsonConvert.DeserializeObject<Dictionary<string, List<string>>>(pureJson);
return await Task.FromResult(availableParameters);
}
catch (Exception)
{
@ -70,12 +77,13 @@ namespace Volo.Docs.HtmlConverting
}
}
private string RemoveOptionsJson(string document)
private static string RemoveOptionsJson(string document)
{
var orgDocument = document;
try
{
if (!document.Contains(jsonOpener) || !document.Contains(docs_param))
if (!document.Contains(JsonOpener) || !document.Contains(DocsParam))
{
return orgDocument;
}
@ -88,8 +96,9 @@ namespace Volo.Docs.HtmlConverting
}
return document.Remove(
jsonBeginningIndex - jsonOpener.Length, (jsonEndingIndex + jsonCloser.Length) - (jsonBeginningIndex - jsonOpener.Length)
);
jsonBeginningIndex - JsonOpener.Length,
(jsonEndingIndex + JsonCloser.Length) - (jsonBeginningIndex - JsonOpener.Length)
);
}
catch (Exception)
{
@ -97,25 +106,25 @@ namespace Volo.Docs.HtmlConverting
}
}
private (int, int, string) GetJsonBeginEndIndexesAndPureJson(string document)
private static (int, int, string) GetJsonBeginEndIndexesAndPureJson(string document)
{
var searchedIndex = 0;
while (searchedIndex < document.Length)
{
var jsonBeginningIndex = document.Substring(searchedIndex).IndexOf(jsonOpener, StringComparison.Ordinal) + jsonOpener.Length + searchedIndex;
var jsonBeginningIndex = document.Substring(searchedIndex).IndexOf(JsonOpener, StringComparison.Ordinal) + JsonOpener.Length + searchedIndex;
if (jsonBeginningIndex < 0)
{
return (-1, -1, "");
}
var jsonEndingIndex = document.Substring(jsonBeginningIndex).IndexOf(jsonCloser, StringComparison.Ordinal) + jsonBeginningIndex;
var jsonEndingIndex = document.Substring(jsonBeginningIndex).IndexOf(JsonCloser, StringComparison.Ordinal) + jsonBeginningIndex;
var insideJsonSection = document[jsonBeginningIndex..jsonEndingIndex];
if (insideJsonSection.IndexOf(docs_param) < 0)
if (insideJsonSection.IndexOf(DocsParam, StringComparison.Ordinal) < 0)
{
searchedIndex = jsonEndingIndex + jsonCloser.Length;
searchedIndex = jsonEndingIndex + JsonCloser.Length;
continue;
}
@ -129,68 +138,84 @@ namespace Volo.Docs.HtmlConverting
{
var templates = new List<DocumentPartialTemplateWithValuesDto>();
while (documentContent.Contains(jsonOpener))
while (documentContent.Contains(JsonOpener))
{
var afterJsonOpener = documentContent.Substring(
documentContent.IndexOf(jsonOpener, StringComparison.Ordinal) + jsonOpener.Length);
documentContent.IndexOf(JsonOpener, StringComparison.Ordinal) + JsonOpener.Length
);
var betweenJsonOpenerAndCloser = afterJsonOpener.Substring(0,
afterJsonOpener.IndexOf(jsonCloser, StringComparison.Ordinal));
afterJsonOpener.IndexOf(JsonCloser, StringComparison.Ordinal)
);
documentContent = afterJsonOpener.Substring(
afterJsonOpener.IndexOf(jsonCloser, StringComparison.Ordinal) + jsonCloser.Length);
afterJsonOpener.IndexOf(JsonCloser, StringComparison.Ordinal) + JsonCloser.Length
);
if (!betweenJsonOpenerAndCloser.Contains(docs_templates))
if (!betweenJsonOpenerAndCloser.Contains(DocsTemplates))
{
continue;
}
var json = betweenJsonOpenerAndCloser.Substring(betweenJsonOpenerAndCloser.IndexOf(docs_templates, StringComparison.Ordinal) + docs_templates.Length);
var json = betweenJsonOpenerAndCloser.Substring(betweenJsonOpenerAndCloser.IndexOf(DocsTemplates, StringComparison.Ordinal) + DocsTemplates.Length);
var template = JsonConvert.DeserializeObject<DocumentPartialTemplateWithValuesDto>(json);
if (!JsonConvertExtensions.TryDeserializeObject<DocumentPartialTemplateWithValuesDto>(json, out var template))
{
throw new UserFriendlyException($"ERROR-20200327: Cannot validate JSON content for `AvailableParameters`!");
}
templates.Add(template);
}
return templates;
return await Task.FromResult(templates);
}
private string SetPartialTemplates(string document, List<DocumentPartialTemplateContent> templates)
private static string SetPartialTemplates(string document, IReadOnlyCollection<DocumentPartialTemplateContent> templates)
{
var newDocument = new StringBuilder();
while (document.Contains(jsonOpener))
while (document.Contains(JsonOpener))
{
var beforeJson = document.Substring(0,
document.IndexOf(jsonOpener, StringComparison.Ordinal) + jsonOpener.Length);
document.IndexOf(JsonOpener, StringComparison.Ordinal) + JsonOpener.Length
);
var afterJsonOpener = document.Substring(
document.IndexOf(jsonOpener, StringComparison.Ordinal) + jsonOpener.Length);
document.IndexOf(JsonOpener, StringComparison.Ordinal) + JsonOpener.Length
);
var betweenJsonOpenerAndCloser = afterJsonOpener.Substring(0,
afterJsonOpener.IndexOf(jsonCloser, StringComparison.Ordinal));
afterJsonOpener.IndexOf(JsonCloser, StringComparison.Ordinal)
);
if (!betweenJsonOpenerAndCloser.Contains(docs_templates))
if (!betweenJsonOpenerAndCloser.Contains(DocsTemplates))
{
document = afterJsonOpener.Substring(
afterJsonOpener.IndexOf(jsonCloser, StringComparison.Ordinal) + jsonCloser.Length);
newDocument.Append(beforeJson + betweenJsonOpenerAndCloser + jsonCloser);
afterJsonOpener.IndexOf(JsonCloser, StringComparison.Ordinal) + JsonCloser.Length
);
newDocument.Append(beforeJson + betweenJsonOpenerAndCloser + JsonCloser);
continue;
}
var json = betweenJsonOpenerAndCloser.Substring(betweenJsonOpenerAndCloser.IndexOf(docs_templates, StringComparison.Ordinal) + docs_templates.Length);
var templatePath = JsonConvert.DeserializeObject<DocumentPartialTemplateWithValuesDto>(json)?.Path;
var json = betweenJsonOpenerAndCloser.Substring(
betweenJsonOpenerAndCloser.IndexOf(DocsTemplates, StringComparison.Ordinal) + DocsTemplates.Length
);
var template = templates.FirstOrDefault(t => t.Path == templatePath);
if (JsonConvertExtensions.TryDeserializeObject<DocumentPartialTemplateWithValuesDto>(json, out var documentPartialTemplateWithValuesDto))
{
var template = templates.FirstOrDefault(t => t.Path == documentPartialTemplateWithValuesDto.Path);
var beforeTemplate = document.Substring(0,
document.IndexOf(jsonOpener, StringComparison.Ordinal));
var beforeTemplate = document.Substring(0,
document.IndexOf(JsonOpener, StringComparison.Ordinal)
);
newDocument.Append(beforeTemplate + template?.Content + jsonCloser);
newDocument.Append(beforeTemplate + template?.Content + JsonCloser);
document = afterJsonOpener.Substring(
afterJsonOpener.IndexOf(jsonCloser, StringComparison.Ordinal) + jsonCloser.Length);
document = afterJsonOpener.Substring(
afterJsonOpener.IndexOf(JsonCloser, StringComparison.Ordinal) + JsonCloser.Length
);
}
}
newDocument.Append(document);

1
modules/docs/src/Volo.Docs.Web/Volo.Docs.Web.csproj

@ -19,6 +19,7 @@
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.AspNetCore.Mvc.UI.Bootstrap\Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.csproj" />
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.AspNetCore.Mvc.UI.Packages\Volo.Abp.AspNetCore.Mvc.UI.Packages.csproj" />
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared\Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared.csproj" />
<ProjectReference Include="..\Volo.Docs.Domain\Volo.Docs.Domain.csproj" />
<ProjectReference Include="..\Volo.Docs.HttpApi\Volo.Docs.HttpApi.csproj" />
<PackageReference Include="Markdig.Signed" Version="0.18.0" />
<PackageReference Include="Scriban" Version="2.1.1" />

Loading…
Cancel
Save