mirror of https://github.com/abpframework/abp.git
csharpabpc-sharpframeworkblazoraspnet-coredotnet-coreaspnetcorearchitecturesaasdomain-driven-designangularmulti-tenancy
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.
225 lines
8.5 KiB
225 lines
8.5 KiB
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using Scriban;
|
|
using Microsoft.Extensions.Logging;
|
|
using Microsoft.Extensions.Logging.Abstractions;
|
|
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 DocsParam = "//[doc-params]";
|
|
private const string DocsTemplates = "//[doc-template]";
|
|
|
|
public ILogger<ScribanDocumentSectionRenderer> Logger { get; set; }
|
|
|
|
public ScribanDocumentSectionRenderer()
|
|
{
|
|
Logger = NullLogger<ScribanDocumentSectionRenderer>.Instance;
|
|
}
|
|
|
|
public async Task<string> RenderAsync(string document, DocumentRenderParameters parameters = null, List<DocumentPartialTemplateContent> partialTemplates = null)
|
|
{
|
|
if (partialTemplates != null && partialTemplates.Any())
|
|
{
|
|
document = SetPartialTemplates(document, partialTemplates);
|
|
}
|
|
|
|
var scribanTemplate = Template.Parse(document);
|
|
|
|
if (parameters == null)
|
|
{
|
|
return await scribanTemplate.RenderAsync();
|
|
}
|
|
|
|
var result = await scribanTemplate.RenderAsync(parameters);
|
|
|
|
return RemoveOptionsJson(result);
|
|
}
|
|
|
|
public async Task<Dictionary<string, List<string>>> GetAvailableParametersAsync(string document)
|
|
{
|
|
try
|
|
{
|
|
if (!document.Contains(JsonOpener) || !document.Contains(DocsParam))
|
|
{
|
|
return new Dictionary<string, List<string>>();
|
|
}
|
|
|
|
var (jsonBeginningIndex, jsonEndingIndex, insideJsonSection) = GetJsonBeginEndIndexesAndPureJson(document);
|
|
|
|
if (jsonBeginningIndex < 0 || jsonEndingIndex <= 0 || string.IsNullOrWhiteSpace(insideJsonSection))
|
|
{
|
|
return new Dictionary<string, List<string>>();
|
|
}
|
|
|
|
var pureJson = insideJsonSection.Replace(DocsParam, "").Trim();
|
|
|
|
if (!DocsJsonSerializerHelper.TryDeserialize<Dictionary<string, List<string>>>(pureJson, out var availableParameters))
|
|
{
|
|
throw new UserFriendlyException("ERROR-20200327: Cannot validate JSON content for `AvailableParameters`!");
|
|
}
|
|
|
|
return await Task.FromResult(availableParameters);
|
|
}
|
|
catch (Exception)
|
|
{
|
|
Logger.LogWarning("Unable to parse parameters of document.");
|
|
return new Dictionary<string, List<string>>();
|
|
}
|
|
}
|
|
|
|
private static string RemoveOptionsJson(string document)
|
|
{
|
|
var orgDocument = document;
|
|
|
|
try
|
|
{
|
|
if (!document.Contains(JsonOpener) || !document.Contains(DocsParam))
|
|
{
|
|
return orgDocument;
|
|
}
|
|
|
|
var (jsonBeginningIndex, jsonEndingIndex, insideJsonSection) = GetJsonBeginEndIndexesAndPureJson(document);
|
|
|
|
if (jsonBeginningIndex < 0 || jsonEndingIndex <= 0 || string.IsNullOrWhiteSpace(insideJsonSection))
|
|
{
|
|
return orgDocument;
|
|
}
|
|
|
|
return document.Remove(
|
|
jsonBeginningIndex - JsonOpener.Length,
|
|
(jsonEndingIndex + JsonCloser.Length) - (jsonBeginningIndex - JsonOpener.Length)
|
|
);
|
|
}
|
|
catch (Exception)
|
|
{
|
|
return orgDocument;
|
|
}
|
|
}
|
|
|
|
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;
|
|
|
|
if (jsonBeginningIndex < 0)
|
|
{
|
|
return (-1, -1, "");
|
|
}
|
|
|
|
var jsonEndingIndex = document.Substring(jsonBeginningIndex).IndexOf(JsonCloser, StringComparison.Ordinal) + jsonBeginningIndex;
|
|
var insideJsonSection = document[jsonBeginningIndex..jsonEndingIndex];
|
|
|
|
if (insideJsonSection.IndexOf(DocsParam, StringComparison.Ordinal) < 0)
|
|
{
|
|
searchedIndex = jsonEndingIndex + JsonCloser.Length;
|
|
continue;
|
|
}
|
|
|
|
return (jsonBeginningIndex, jsonEndingIndex, insideJsonSection);
|
|
}
|
|
|
|
return (-1, -1, "");
|
|
}
|
|
|
|
public async Task<List<DocumentPartialTemplateWithValuesDto>> GetPartialTemplatesInDocumentAsync(string documentContent)
|
|
{
|
|
var templates = new List<DocumentPartialTemplateWithValuesDto>();
|
|
|
|
while (documentContent.Contains(JsonOpener))
|
|
{
|
|
var afterJsonOpener = documentContent.Substring(
|
|
documentContent.IndexOf(JsonOpener, StringComparison.Ordinal) + JsonOpener.Length
|
|
);
|
|
|
|
var betweenJsonOpenerAndCloser = afterJsonOpener.Substring(0,
|
|
afterJsonOpener.IndexOf(JsonCloser, StringComparison.Ordinal)
|
|
);
|
|
|
|
documentContent = afterJsonOpener.Substring(
|
|
afterJsonOpener.IndexOf(JsonCloser, StringComparison.Ordinal) + JsonCloser.Length
|
|
);
|
|
|
|
if (!betweenJsonOpenerAndCloser.Contains(DocsTemplates))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
var json = betweenJsonOpenerAndCloser.Substring(betweenJsonOpenerAndCloser.IndexOf(DocsTemplates, StringComparison.Ordinal) + DocsTemplates.Length);
|
|
|
|
if (!DocsJsonSerializerHelper.TryDeserialize<DocumentPartialTemplateWithValuesDto>(json, out var template))
|
|
{
|
|
throw new UserFriendlyException($"ERROR-20200327: Cannot validate JSON content for `AvailableParameters`!");
|
|
}
|
|
|
|
templates.Add(template);
|
|
}
|
|
|
|
return await Task.FromResult(templates);
|
|
}
|
|
|
|
private static string SetPartialTemplates(string document, IReadOnlyCollection<DocumentPartialTemplateContent> templates)
|
|
{
|
|
var newDocument = new StringBuilder();
|
|
|
|
while (document.Contains(JsonOpener))
|
|
{
|
|
var beforeJson = document.Substring(0,
|
|
document.IndexOf(JsonOpener, StringComparison.Ordinal) + JsonOpener.Length
|
|
);
|
|
|
|
var afterJsonOpener = document.Substring(
|
|
document.IndexOf(JsonOpener, StringComparison.Ordinal) + JsonOpener.Length
|
|
);
|
|
|
|
var betweenJsonOpenerAndCloser = afterJsonOpener.Substring(0,
|
|
afterJsonOpener.IndexOf(JsonCloser, StringComparison.Ordinal)
|
|
);
|
|
|
|
if (!betweenJsonOpenerAndCloser.Contains(DocsTemplates))
|
|
{
|
|
document = afterJsonOpener.Substring(
|
|
afterJsonOpener.IndexOf(JsonCloser, StringComparison.Ordinal) + JsonCloser.Length
|
|
);
|
|
|
|
newDocument.Append(beforeJson + betweenJsonOpenerAndCloser + JsonCloser);
|
|
continue;
|
|
}
|
|
|
|
var json = betweenJsonOpenerAndCloser.Substring(
|
|
betweenJsonOpenerAndCloser.IndexOf(DocsTemplates, StringComparison.Ordinal) + DocsTemplates.Length
|
|
);
|
|
|
|
if (DocsJsonSerializerHelper.TryDeserialize<DocumentPartialTemplateWithValuesDto>(json, out var documentPartialTemplateWithValuesDto))
|
|
{
|
|
var template = templates.FirstOrDefault(t => t.Path == documentPartialTemplateWithValuesDto.Path);
|
|
|
|
var beforeTemplate = document.Substring(0,
|
|
document.IndexOf(JsonOpener, StringComparison.Ordinal)
|
|
);
|
|
|
|
newDocument.Append(beforeTemplate + template?.Content + JsonCloser);
|
|
|
|
document = afterJsonOpener.Substring(
|
|
afterJsonOpener.IndexOf(JsonCloser, StringComparison.Ordinal) + JsonCloser.Length
|
|
);
|
|
}
|
|
}
|
|
|
|
newDocument.Append(document);
|
|
|
|
return newDocument.ToString();
|
|
}
|
|
}
|
|
}
|
|
|