Browse Source

Merge pull request #20325 from abpframework/salihozkara/ImproveDocsSection

Support for Rendering Custom JSON Sections Starting with  "```"
pull/20392/head
Gizem Mutu Kurt 2 years ago
committed by GitHub
parent
commit
701cc9f7a1
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 236
      modules/docs/src/Volo.Docs.Web/HtmlConverting/ScribanDocumentSectionRenderer.cs

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

@ -13,8 +13,11 @@ namespace Volo.Docs.HtmlConverting
{ {
public class ScribanDocumentSectionRenderer : IDocumentSectionRenderer public class ScribanDocumentSectionRenderer : IDocumentSectionRenderer
{ {
private const string JsonOpener = "````json"; private readonly static List<DocsJsonSection> DocsJsonSections = new List<DocsJsonSection>
private const string JsonCloser = "````"; {
new DocsJsonSection("````json", "````"),
new DocsJsonSection("```json", "```")
};
private const string DocsParam = "//[doc-params]"; private const string DocsParam = "//[doc-params]";
private const string DocsTemplates = "//[doc-template]"; private const string DocsTemplates = "//[doc-template]";
private const string DocsNav = "//[doc-nav]"; private const string DocsNav = "//[doc-nav]";
@ -59,12 +62,12 @@ namespace Volo.Docs.HtmlConverting
{ {
try try
{ {
if (!document.Contains(JsonOpener) || !document.Contains(sectionName)) if (!HasJsonSection(document) || !document.Contains(sectionName))
{ {
return new T(); return new T();
} }
var (jsonBeginningIndex, jsonEndingIndex, insideJsonSection) = GetJsonBeginEndIndexesAndPureJson(document, sectionName); var (jsonBeginningIndex, jsonEndingIndex, insideJsonSection, _) = GetJsonBeginEndIndexesAndPureJson(document, sectionName);
if (jsonBeginningIndex < 0 || jsonEndingIndex <= 0 || string.IsNullOrWhiteSpace(insideJsonSection)) if (jsonBeginningIndex < 0 || jsonEndingIndex <= 0 || string.IsNullOrWhiteSpace(insideJsonSection))
{ {
@ -96,12 +99,12 @@ namespace Volo.Docs.HtmlConverting
try try
{ {
if (!document.Contains(JsonOpener) || !document.Contains(sectionName)) if (!HasJsonSection(document) || !document.Contains(sectionName))
{ {
continue; continue;
} }
var (jsonBeginningIndex, jsonEndingIndex, insideJsonSection) = GetJsonBeginEndIndexesAndPureJson(document, sectionName); var (jsonBeginningIndex, jsonEndingIndex, insideJsonSection, jsonSection) = GetJsonBeginEndIndexesAndPureJson(document, sectionName);
if (jsonBeginningIndex < 0 || jsonEndingIndex <= 0 || string.IsNullOrWhiteSpace(insideJsonSection)) if (jsonBeginningIndex < 0 || jsonEndingIndex <= 0 || string.IsNullOrWhiteSpace(insideJsonSection))
{ {
@ -109,8 +112,8 @@ namespace Volo.Docs.HtmlConverting
} }
document = document.Remove( document = document.Remove(
jsonBeginningIndex - JsonOpener.Length, jsonBeginningIndex - jsonSection.Opener.Length,
(jsonEndingIndex + JsonCloser.Length) - (jsonBeginningIndex - JsonOpener.Length) (jsonEndingIndex + jsonSection.Closer.Length) - (jsonBeginningIndex - jsonSection.Opener.Length)
); );
} }
catch (Exception) catch (Exception)
@ -121,122 +124,193 @@ namespace Volo.Docs.HtmlConverting
return document; return document;
} }
private static (int, int, string) GetJsonBeginEndIndexesAndPureJson(string document, string sectionName) private static bool HasJsonSection(string document)
{ {
var searchedIndex = 0; return DocsJsonSections.Any(section => document.Contains(section.Opener) && document.Contains(section.Closer));
}
while (searchedIndex < document.Length) private static (int, int, string, DocsJsonSection) GetJsonBeginEndIndexesAndPureJson(string document, string sectionName)
{
foreach (var section in DocsJsonSections)
{ {
var jsonBeginningIndex = document.Substring(searchedIndex).IndexOf(JsonOpener, StringComparison.Ordinal) + JsonOpener.Length + searchedIndex; var (jsonBeginningIndex, jsonEndingIndex, insideJsonSection) = section.GetJsonBeginEndIndexesAndPureJson(document, sectionName);
if (jsonBeginningIndex < 0)
{
return (-1, -1, "");
}
var jsonEndingIndex = document.Substring(jsonBeginningIndex).IndexOf(JsonCloser, StringComparison.Ordinal) + jsonBeginningIndex;
var insideJsonSection = document[jsonBeginningIndex..jsonEndingIndex];
if (insideJsonSection.IndexOf(sectionName, StringComparison.Ordinal) < 0) if (jsonBeginningIndex >= 0 && jsonEndingIndex > 0 && !string.IsNullOrWhiteSpace(insideJsonSection))
{ {
searchedIndex = jsonEndingIndex + JsonCloser.Length; return (jsonBeginningIndex, jsonEndingIndex, insideJsonSection, section);
continue;
} }
return (jsonBeginningIndex, jsonEndingIndex, insideJsonSection);
} }
return (-1, -1, ""); return (-1, -1, "", null);
} }
public async Task<List<DocumentPartialTemplateWithValuesDto>> GetPartialTemplatesInDocumentAsync(string documentContent) public async Task<List<DocumentPartialTemplateWithValuesDto>> GetPartialTemplatesInDocumentAsync(string documentContent)
{ {
var templates = new List<DocumentPartialTemplateWithValuesDto>(); var templates = new List<DocumentPartialTemplateWithValuesDto>();
while (documentContent.Contains(JsonOpener)) foreach (var section in DocsJsonSections)
{ {
var afterJsonOpener = documentContent.Substring( templates.AddRange(await section.GetPartialTemplatesInDocumentAsync(documentContent));
documentContent.IndexOf(JsonOpener, StringComparison.Ordinal) + JsonOpener.Length }
);
var betweenJsonOpenerAndCloser = afterJsonOpener.Substring(0, return templates;
afterJsonOpener.IndexOf(JsonCloser, StringComparison.Ordinal) }
);
private static string SetPartialTemplates(string document, IReadOnlyCollection<DocumentPartialTemplateContent> templates)
{
foreach (var section in DocsJsonSections)
{
document = section.SetPartialTemplates(document, templates);
}
return document;
}
private class DocsJsonSection
{
public string Opener { get; }
public string Closer { get; }
public DocsJsonSection(string opener, string closer)
{
Opener = opener;
Closer = closer;
}
documentContent = afterJsonOpener.Substring( public (int, int, string) GetJsonBeginEndIndexesAndPureJson(string document, string sectionName)
afterJsonOpener.IndexOf(JsonCloser, StringComparison.Ordinal) + JsonCloser.Length {
); var searchedIndex = 0;
if (!betweenJsonOpenerAndCloser.Contains(DocsTemplates)) while (searchedIndex < document.Length)
{ {
continue; var jsonBeginningIndex = document.Substring(searchedIndex).IndexOf(Opener, StringComparison.Ordinal);
}
var json = betweenJsonOpenerAndCloser.Substring(betweenJsonOpenerAndCloser.IndexOf(DocsTemplates, StringComparison.Ordinal) + DocsTemplates.Length); if (jsonBeginningIndex < 0)
{
return (-1, -1, "");
}
jsonBeginningIndex += Opener.Length + searchedIndex;
if (!DocsJsonSerializerHelper.TryDeserialize<DocumentPartialTemplateWithValuesDto>(json, out var template)) var jsonEndingIndex = document.Substring(jsonBeginningIndex).IndexOf(Closer, StringComparison.Ordinal);
{ if (jsonEndingIndex < 0)
throw new UserFriendlyException($"ERROR-20200327: Cannot validate JSON content for `AvailableParameters`!"); {
} return (-1, -1, "");
}
jsonEndingIndex += jsonBeginningIndex;
var insideJsonSection = document[jsonBeginningIndex..jsonEndingIndex];
templates.Add(template); if (insideJsonSection.IndexOf(sectionName, StringComparison.Ordinal) < 0)
} {
searchedIndex = jsonEndingIndex + Closer.Length;
continue;
}
return await Task.FromResult(templates); return (jsonBeginningIndex, jsonEndingIndex, insideJsonSection);
} }
private static string SetPartialTemplates(string document, IReadOnlyCollection<DocumentPartialTemplateContent> templates) return (-1, -1, "");
{ }
var newDocument = new StringBuilder();
while (document.Contains(JsonOpener)) public async Task<List<DocumentPartialTemplateWithValuesDto>> GetPartialTemplatesInDocumentAsync(
string documentContent)
{ {
var beforeJson = document.Substring(0, var templates = new List<DocumentPartialTemplateWithValuesDto>();
document.IndexOf(JsonOpener, StringComparison.Ordinal) + JsonOpener.Length
);
var afterJsonOpener = document.Substring( while (documentContent.Contains(Opener))
document.IndexOf(JsonOpener, StringComparison.Ordinal) + JsonOpener.Length {
); var afterJsonOpener = documentContent.Substring(
documentContent.IndexOf(Opener, StringComparison.Ordinal) + Opener.Length
);
var betweenJsonOpenerAndCloser = afterJsonOpener.Substring(0, var betweenJsonOpenerAndCloser = afterJsonOpener.Substring(0,
afterJsonOpener.IndexOf(JsonCloser, StringComparison.Ordinal) afterJsonOpener.IndexOf(Closer, StringComparison.Ordinal)
); );
if (!betweenJsonOpenerAndCloser.Contains(DocsTemplates)) documentContent = afterJsonOpener.Substring(
{ afterJsonOpener.IndexOf(Closer, StringComparison.Ordinal) + Closer.Length
document = afterJsonOpener.Substring(
afterJsonOpener.IndexOf(JsonCloser, StringComparison.Ordinal) + JsonCloser.Length
); );
newDocument.Append(beforeJson + betweenJsonOpenerAndCloser + JsonCloser); if (!betweenJsonOpenerAndCloser.Contains(DocsTemplates))
continue; {
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);
} }
var json = betweenJsonOpenerAndCloser.Substring( return await Task.FromResult(templates);
betweenJsonOpenerAndCloser.IndexOf(DocsTemplates, StringComparison.Ordinal) + DocsTemplates.Length }
);
public string SetPartialTemplates(string document,
IReadOnlyCollection<DocumentPartialTemplateContent> templates)
{
var newDocument = new StringBuilder();
if (DocsJsonSerializerHelper.TryDeserialize<DocumentPartialTemplateWithValuesDto>(json, out var documentPartialTemplateWithValuesDto)) while (document.Contains(Opener))
{ {
var template = templates.FirstOrDefault(t => t.Path == documentPartialTemplateWithValuesDto.Path); var beforeJson = document.Substring(0,
document.IndexOf(Opener, StringComparison.Ordinal) + Opener.Length
);
var beforeTemplate = document.Substring(0, var afterJsonOpener = document.Substring(
document.IndexOf(JsonOpener, StringComparison.Ordinal) document.IndexOf(Opener, StringComparison.Ordinal) + Opener.Length
); );
newDocument.Append(beforeTemplate + template?.Content + JsonCloser); var betweenJsonOpenerAndCloser = afterJsonOpener.Substring(0,
afterJsonOpener.IndexOf(Closer, StringComparison.Ordinal)
);
if (!betweenJsonOpenerAndCloser.Contains(DocsTemplates))
{
document = afterJsonOpener.Substring(
afterJsonOpener.IndexOf(Closer, StringComparison.Ordinal) + Closer.Length
);
newDocument.Append(beforeJson + betweenJsonOpenerAndCloser + Closer);
continue;
}
document = afterJsonOpener.Substring( var json = betweenJsonOpenerAndCloser.Substring(
afterJsonOpener.IndexOf(JsonCloser, StringComparison.Ordinal) + JsonCloser.Length 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(Opener, StringComparison.Ordinal)
);
newDocument.Append(beforeTemplate + template?.Content + Closer);
document = afterJsonOpener.Substring(
afterJsonOpener.IndexOf(Closer, StringComparison.Ordinal) + Closer.Length
);
}
} }
}
newDocument.Append(document); newDocument.Append(document);
return newDocument.ToString(); return newDocument.ToString();
}
} }
} }
} }

Loading…
Cancel
Save