|
|
|
@ -23,23 +23,23 @@ public class ProjectPdfGenerator : IProjectPdfGenerator, ITransientDependency |
|
|
|
protected IDocumentToHtmlConverterFactory DocumentToHtmlConverterFactory { get; } |
|
|
|
protected IDocumentRepository DocumentRepository { get; } |
|
|
|
protected IDocumentSectionRenderer DocumentSectionRenderer { get; } |
|
|
|
protected IOptions<DocsProjectPdfGeneratorOptions> Options { get; } |
|
|
|
protected IOptions<DocsProjectPdfGeneratorOptions> Options { get; } |
|
|
|
protected IProjectPdfFileStore ProjectPdfFileStore { get; } |
|
|
|
protected IHtmlToPdfRenderer HtmlToPdfRenderer { get; } |
|
|
|
protected ILogger<ProjectPdfGenerator> Logger { get; set; } |
|
|
|
protected IDocumentSource DocumentSource { get; set; } |
|
|
|
protected DocumentParams DocumentParams { get; set; } |
|
|
|
protected Project Project { get; set; } |
|
|
|
protected List<PdfDocument> AllPdfDocuments { get; private set; } = []; |
|
|
|
protected List<PdfDocument> AllPdfDocuments { get; } = []; |
|
|
|
|
|
|
|
public ProjectPdfGenerator( |
|
|
|
IDocumentSourceFactory documentStoreFactory, |
|
|
|
IDocumentSourceFactory documentStoreFactory, |
|
|
|
IDocumentRepository documentRepository, |
|
|
|
IOptions<DocsProjectPdfGeneratorOptions> options, |
|
|
|
IDocumentSectionRenderer documentSectionRenderer, |
|
|
|
IProjectPdfFileStore projectPdfFileStore, |
|
|
|
IHtmlToPdfRenderer htmlToPdfRenderer, |
|
|
|
IDocumentToHtmlConverterFactory documentToHtmlConverterFactory, |
|
|
|
IProjectPdfFileStore projectPdfFileStore, |
|
|
|
IHtmlToPdfRenderer htmlToPdfRenderer, |
|
|
|
IDocumentToHtmlConverterFactory documentToHtmlConverterFactory, |
|
|
|
ILogger<ProjectPdfGenerator> logger) |
|
|
|
{ |
|
|
|
DocumentStoreFactory = documentStoreFactory; |
|
|
|
@ -51,55 +51,44 @@ public class ProjectPdfGenerator : IProjectPdfGenerator, ITransientDependency |
|
|
|
DocumentToHtmlConverterFactory = documentToHtmlConverterFactory; |
|
|
|
Logger = logger; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public virtual async Task GenerateAsync(Project project, string version, string languageCode) |
|
|
|
{ |
|
|
|
Project = project; |
|
|
|
DocumentSource = DocumentStoreFactory.Create(project.DocumentStoreType); |
|
|
|
DocumentParams = await GetDocumentParamsAsync(project, version, languageCode); |
|
|
|
|
|
|
|
|
|
|
|
var navigation = await GetNavigationAsync(project, version, languageCode); |
|
|
|
AllPdfDocuments = new List<PdfDocument>(); |
|
|
|
await SetAllPdfDocumentsAsync(navigation.Items, project, version, languageCode); |
|
|
|
|
|
|
|
var title = Options.Value.CalculatePdfFileTitle?.Invoke(project) ?? project.Name; |
|
|
|
var tempStreams = new List<(PdfDocument pdfDocument, Stream stream)>(); |
|
|
|
var tempFiles = new List<(PdfDocument pdfDocument, Stream stream)>(); |
|
|
|
|
|
|
|
try |
|
|
|
{ |
|
|
|
var index = 0; |
|
|
|
foreach (var document in AllPdfDocuments) |
|
|
|
for (var i = 0; i < AllPdfDocuments.Count; i++) |
|
|
|
{ |
|
|
|
try |
|
|
|
{ |
|
|
|
var document = AllPdfDocuments[i]; |
|
|
|
Logger.LogInformation("Processing chunk {Index}/{Total}", i + 1, AllPdfDocuments.Count); |
|
|
|
|
|
|
|
Logger.LogInformation("Processing chunk {Index}/{Total}", index + 1, AllPdfDocuments.Count); |
|
|
|
var chunkHtml = await BuildHtmlAsync([document]); |
|
|
|
|
|
|
|
var chunkHtml = await BuildHtmlAsync([document]); |
|
|
|
var pdfStream = HtmlToPdfRenderer.Render($"{title} - Part {document.Title}", chunkHtml, [document]); |
|
|
|
|
|
|
|
var pdfStream = await HtmlToPdfRenderer.RenderAsync($"{title} - Part {document.Title}", chunkHtml, [document]); |
|
|
|
|
|
|
|
Logger.LogInformation("Chunk {Index} rendered to PDF", index + 1); |
|
|
|
Logger.LogInformation("Chunk {Index} rendered to PDF", i + 1); |
|
|
|
|
|
|
|
tempStreams.Add((document, pdfStream)); |
|
|
|
|
|
|
|
index++; |
|
|
|
} |
|
|
|
catch (Exception e) |
|
|
|
{ |
|
|
|
Logger.LogError(e, "Error processing chunk {Index} for project {ProjectName}", index + 1, project.Name); |
|
|
|
} |
|
|
|
tempFiles.Add((document, pdfStream)); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Logger.LogInformation("All chunks processed, merging PDF files"); |
|
|
|
|
|
|
|
var mergedPdfStream = await MergePdfFilesAsync(tempStreams, title); |
|
|
|
var mergedPdfStream = await MergePdfFilesAsync(tempFiles); |
|
|
|
await ProjectPdfFileStore.SetAsync(project, version, languageCode, mergedPdfStream); |
|
|
|
} |
|
|
|
catch(Exception e) |
|
|
|
catch (Exception e) |
|
|
|
{ |
|
|
|
Logger.LogError(e, "An error occurred while generating the PDF for project {ProjectName}", project.Name); |
|
|
|
foreach (var tempStream in tempStreams) |
|
|
|
foreach (var tempStream in tempFiles) |
|
|
|
{ |
|
|
|
try |
|
|
|
{ |
|
|
|
@ -113,6 +102,7 @@ public class ProjectPdfGenerator : IProjectPdfGenerator, ITransientDependency |
|
|
|
} |
|
|
|
finally |
|
|
|
{ |
|
|
|
AllPdfDocuments.Clear(); |
|
|
|
GC.Collect(); |
|
|
|
GC.WaitForPendingFinalizers(); |
|
|
|
} |
|
|
|
@ -121,15 +111,15 @@ public class ProjectPdfGenerator : IProjectPdfGenerator, ITransientDependency |
|
|
|
protected virtual async Task<string> BuildHtmlAsync(List<PdfDocument> pdfDocuments) |
|
|
|
{ |
|
|
|
var htmlContent = await ConvertDocumentsToHtmlAsync(pdfDocuments); |
|
|
|
|
|
|
|
|
|
|
|
var htmlBuilder = new StringBuilder(); |
|
|
|
htmlBuilder.Append(Options.Value.HtmlLayout); |
|
|
|
htmlBuilder.Replace(DocsProjectPdfGeneratorOptions.StylePlaceholder, Options.Value.HtmlStyle); |
|
|
|
htmlBuilder.Replace(DocsProjectPdfGeneratorOptions.ContentPlaceholder, htmlContent); |
|
|
|
|
|
|
|
|
|
|
|
return htmlBuilder.ToString(); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
protected virtual async Task<string> ConvertDocumentsToHtmlAsync(List<PdfDocument> pdfDocuments) |
|
|
|
{ |
|
|
|
var contentBuilder = new StringBuilder(); |
|
|
|
@ -140,7 +130,9 @@ public class ProjectPdfGenerator : IProjectPdfGenerator, ITransientDependency |
|
|
|
{ |
|
|
|
var renderedDocument = await RenderDocumentAsync(pdfDocument); |
|
|
|
var documentToHtmlConverter = GetDocumentToHtmlConverter(Project, pdfDocument); |
|
|
|
var htmlContent = documentToHtmlConverter.Convert(new PdfDocumentToHtmlConverterContext(renderedDocument, pdfDocument, DocumentParams)); |
|
|
|
var htmlContent = |
|
|
|
documentToHtmlConverter.Convert( |
|
|
|
new PdfDocumentToHtmlConverterContext(renderedDocument, pdfDocument, DocumentParams)); |
|
|
|
contentBuilder.AppendLine(htmlContent); |
|
|
|
} |
|
|
|
|
|
|
|
@ -149,11 +141,12 @@ public class ProjectPdfGenerator : IProjectPdfGenerator, ITransientDependency |
|
|
|
contentBuilder.AppendLine(await ConvertDocumentsToHtmlAsync(pdfDocument.Children)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return contentBuilder.ToString(); |
|
|
|
} |
|
|
|
|
|
|
|
protected virtual async Task<MemoryStream> MergePdfFilesAsync(List<(PdfDocument pdfDocument, Stream stream)> pdfFiles, string title) |
|
|
|
protected virtual async Task<MemoryStream> MergePdfFilesAsync( |
|
|
|
List<(PdfDocument pdfDocument, Stream stream)> pdfFiles) |
|
|
|
{ |
|
|
|
if (pdfFiles.Count == 0) |
|
|
|
{ |
|
|
|
@ -162,50 +155,59 @@ public class ProjectPdfGenerator : IProjectPdfGenerator, ITransientDependency |
|
|
|
|
|
|
|
var zipStream = new MemoryStream(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
using (var zipArchive = new ZipArchive(zipStream, ZipArchiveMode.Create, true)) |
|
|
|
{ |
|
|
|
using var zipArchive = new ZipArchive(zipStream, ZipArchiveMode.Create, true); |
|
|
|
foreach (var (doc, pdfFile) in pdfFiles) |
|
|
|
for (var index = 0; index < pdfFiles.Count; index++) |
|
|
|
{ |
|
|
|
if (pdfFile.CanSeek) |
|
|
|
{ |
|
|
|
pdfFile.Position = 0; |
|
|
|
} |
|
|
|
|
|
|
|
var entry = zipArchive.CreateEntry($"{title}_{doc.Title}.pdf", CompressionLevel.Fastest); |
|
|
|
var (doc, pdfFile) = pdfFiles[index]; |
|
|
|
var entry = zipArchive.CreateEntry($"{index + 1}_{doc.Title}.pdf", CompressionLevel.Fastest); |
|
|
|
await using var entryStream = entry.Open(); |
|
|
|
await pdfFile.CopyToAsync(entryStream); |
|
|
|
|
|
|
|
await pdfFile.DisposeAsync(); |
|
|
|
try |
|
|
|
{ |
|
|
|
await pdfFile.DisposeAsync(); |
|
|
|
} |
|
|
|
catch (Exception e) |
|
|
|
{ |
|
|
|
Logger.LogWarning(e, "Error disposing PDF file stream for document {DocumentTitle}", doc.Title); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
zipStream.Position = 0; |
|
|
|
return zipStream; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
protected virtual IDocumentToHtmlConverter<PdfDocumentToHtmlConverterContext> GetDocumentToHtmlConverter(Project project, PdfDocument pdfDocument) |
|
|
|
|
|
|
|
protected virtual IDocumentToHtmlConverter<PdfDocumentToHtmlConverterContext> GetDocumentToHtmlConverter( |
|
|
|
Project project, PdfDocument pdfDocument) |
|
|
|
{ |
|
|
|
return DocumentToHtmlConverterFactory.Create<PdfDocumentToHtmlConverterContext>(DocsDomainConsts.PdfDocumentToHtmlConverterPrefix +(pdfDocument.Document.Format ?? project.Format)); |
|
|
|
return DocumentToHtmlConverterFactory.Create<PdfDocumentToHtmlConverterContext>( |
|
|
|
DocsDomainConsts.PdfDocumentToHtmlConverterPrefix + (pdfDocument.Document.Format ?? project.Format)); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
protected virtual async Task<string> RenderDocumentAsync(PdfDocument pdfDocument) |
|
|
|
{ |
|
|
|
var parameters = new DocumentRenderParameters(); |
|
|
|
if (pdfDocument.RenderParameters != null) |
|
|
|
if (pdfDocument.RenderParameters == null) |
|
|
|
{ |
|
|
|
foreach (var renderParameter in pdfDocument.RenderParameters) |
|
|
|
{ |
|
|
|
var documentParam = DocumentParams.Parameters.FirstOrDefault(p => p.Name == renderParameter.Key); |
|
|
|
parameters.Add(renderParameter.Key, renderParameter.Value); |
|
|
|
parameters.Add(renderParameter.Key + "_Value",documentParam?.Values[renderParameter.Value] ?? renderParameter.Value); |
|
|
|
} |
|
|
|
return await DocumentSectionRenderer.RenderAsync(pdfDocument.Document.Content, parameters); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
foreach (var renderParameter in pdfDocument.RenderParameters) |
|
|
|
{ |
|
|
|
var documentParam = DocumentParams.Parameters.FirstOrDefault(p => p.Name == renderParameter.Key); |
|
|
|
parameters.Add(renderParameter.Key, renderParameter.Value); |
|
|
|
parameters.Add(renderParameter.Key + "_Value", |
|
|
|
documentParam?.Values[renderParameter.Value] ?? renderParameter.Value); |
|
|
|
} |
|
|
|
|
|
|
|
return await DocumentSectionRenderer.RenderAsync(pdfDocument.Document.Content, parameters); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
protected virtual async Task SetAllPdfDocumentsAsync( |
|
|
|
List<NavigationNode> navigations, |
|
|
|
Project project, |
|
|
|
@ -228,10 +230,11 @@ public class ProjectPdfGenerator : IProjectPdfGenerator, ITransientDependency |
|
|
|
{ |
|
|
|
Title = navigation.Text, |
|
|
|
IgnoreOnOutline = navigation.Path == Options.Value.IndexPagePath, |
|
|
|
Id = UrlHelper.IsExternalLink(navigation.Path) ? navigation.Path: null |
|
|
|
Id = UrlHelper.IsExternalLink(navigation.Path) ? navigation.Path : null |
|
|
|
}; |
|
|
|
|
|
|
|
if (!navigation.Path.IsNullOrWhiteSpace() && !UrlHelper.IsExternalLink(navigation.Path) && !navigation.HasChildItems) |
|
|
|
if (!navigation.Path.IsNullOrWhiteSpace() && !UrlHelper.IsExternalLink(navigation.Path) && |
|
|
|
!navigation.HasChildItems) |
|
|
|
{ |
|
|
|
await HandleLeafDocumentAsync( |
|
|
|
navigation, |
|
|
|
@ -255,7 +258,7 @@ public class ProjectPdfGenerator : IProjectPdfGenerator, ITransientDependency |
|
|
|
parentPdfDocument.Children.AddIfNotContains(pdfDocument); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (navigation.HasChildItems) |
|
|
|
{ |
|
|
|
AddParameterCombinationsDocuments(parentPdfDocument, groupedCombinationsDocuments); |
|
|
|
@ -269,11 +272,12 @@ public class ProjectPdfGenerator : IProjectPdfGenerator, ITransientDependency |
|
|
|
} |
|
|
|
catch (Exception e) |
|
|
|
{ |
|
|
|
Logger.LogWarning(e, $"Cannot get document for the path '{navigation.Path}' in the project {project.Name}."); |
|
|
|
Logger.LogWarning(e, |
|
|
|
$"Cannot get document for the path '{navigation.Path}' in the project {project.Name}."); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private async Task HandleLeafDocumentAsync( |
|
|
|
NavigationNode navigation, |
|
|
|
Project project, |
|
|
|
@ -309,22 +313,25 @@ public class ProjectPdfGenerator : IProjectPdfGenerator, ITransientDependency |
|
|
|
groupedCombinationsDocuments[key] = []; |
|
|
|
} |
|
|
|
|
|
|
|
var combinationDocument = i == 0 ? leafDocument : new PdfDocument |
|
|
|
{ |
|
|
|
Document = document, |
|
|
|
Id = GetDocumentId(document.Name, document.Format ?? project.Format, combination, false), |
|
|
|
Title = GetDocumentTitle(navigation.Text, combination, DocumentParams), |
|
|
|
RenderParameters = combination |
|
|
|
}; |
|
|
|
var combinationDocument = i == 0 |
|
|
|
? leafDocument |
|
|
|
: new PdfDocument |
|
|
|
{ |
|
|
|
Document = document, |
|
|
|
Id = GetDocumentId(document.Name, document.Format ?? project.Format, combination, false), |
|
|
|
Title = GetDocumentTitle(navigation.Text, combination, DocumentParams), |
|
|
|
RenderParameters = combination |
|
|
|
}; |
|
|
|
|
|
|
|
groupedCombinationsDocuments[key].Add(combinationDocument); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private void AddParameterCombinationsDocuments(PdfDocument parentPdfDocument, Dictionary<string,List<PdfDocument>> groupedCombinationsDocuments) |
|
|
|
} |
|
|
|
|
|
|
|
private void AddParameterCombinationsDocuments(PdfDocument parentPdfDocument, |
|
|
|
Dictionary<string, List<PdfDocument>> groupedCombinationsDocuments) |
|
|
|
{ |
|
|
|
foreach (var combinations in groupedCombinationsDocuments) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (parentPdfDocument == null) |
|
|
|
{ |
|
|
|
AllPdfDocuments.AddIfNotContains(combinations.Value); |
|
|
|
@ -334,33 +341,31 @@ public class ProjectPdfGenerator : IProjectPdfGenerator, ITransientDependency |
|
|
|
parentPdfDocument.Children.AddIfNotContains(combinations.Value); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
groupedCombinationsDocuments.Clear(); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private async Task<NavigationNode> GetNavigationAsync( |
|
|
|
Project project, |
|
|
|
string version, |
|
|
|
string languageCode) |
|
|
|
{ |
|
|
|
var navigationDocument = await GetDocumentAsync(project, project.NavigationDocumentName, version, languageCode); |
|
|
|
|
|
|
|
|
|
|
|
if (!DocsJsonSerializerHelper.TryDeserialize<NavigationNode>(navigationDocument.Content, out var navigation)) |
|
|
|
{ |
|
|
|
throw new UserFriendlyException($"Cannot validate navigation file '{project.NavigationDocumentName}' for the project {project.Name}."); |
|
|
|
throw new UserFriendlyException( |
|
|
|
$"Cannot validate navigation file '{project.NavigationDocumentName}' for the project {project.Name}."); |
|
|
|
} |
|
|
|
|
|
|
|
if (!Options.Value.IndexPagePath.IsNullOrWhiteSpace()) |
|
|
|
{ |
|
|
|
navigation.Items.Insert(0, new NavigationNode |
|
|
|
{ |
|
|
|
Path = Options.Value.IndexPagePath |
|
|
|
}); |
|
|
|
navigation.Items.Insert(0, new NavigationNode { Path = Options.Value.IndexPagePath }); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return navigation; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private async Task<DocumentParams> GetDocumentParamsAsync( |
|
|
|
Project project, |
|
|
|
string version, |
|
|
|
@ -373,13 +378,16 @@ public class ProjectPdfGenerator : IProjectPdfGenerator, ITransientDependency |
|
|
|
|
|
|
|
try |
|
|
|
{ |
|
|
|
var documentParamsDocument = await GetDocumentAsync(project, project.ParametersDocumentName, version, languageCode); |
|
|
|
|
|
|
|
if (!DocsJsonSerializerHelper.TryDeserialize<DocumentParams>(documentParamsDocument.Content, out var documentParams)) |
|
|
|
var documentParamsDocument = |
|
|
|
await GetDocumentAsync(project, project.ParametersDocumentName, version, languageCode); |
|
|
|
|
|
|
|
if (!DocsJsonSerializerHelper.TryDeserialize<DocumentParams>(documentParamsDocument.Content, |
|
|
|
out var documentParams)) |
|
|
|
{ |
|
|
|
throw new UserFriendlyException($"Cannot validate document params file '{project.ParametersDocumentName}' for the project {project.Name}."); |
|
|
|
throw new UserFriendlyException( |
|
|
|
$"Cannot validate document params file '{project.ParametersDocumentName}' for the project {project.Name}."); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return documentParams; |
|
|
|
} |
|
|
|
catch (Exception e) |
|
|
|
@ -388,25 +396,25 @@ public class ProjectPdfGenerator : IProjectPdfGenerator, ITransientDependency |
|
|
|
return new DocumentParams(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private async Task<Document> GetDocumentAsync( |
|
|
|
Project project, |
|
|
|
Project project, |
|
|
|
string documentName, |
|
|
|
string version, |
|
|
|
string languageCode) |
|
|
|
{ |
|
|
|
version = string.IsNullOrWhiteSpace(version) ? project.LatestVersionBranchName : version; |
|
|
|
|
|
|
|
|
|
|
|
Document document = null; |
|
|
|
Exception firstException = null; |
|
|
|
|
|
|
|
|
|
|
|
var possibleNames = GetPossibleNames(documentName, project.Format); |
|
|
|
document = await DocumentRepository.FindAsync(project.Id, possibleNames, languageCode, version); |
|
|
|
if (document != null) |
|
|
|
{ |
|
|
|
return document; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
foreach (var name in possibleNames) |
|
|
|
{ |
|
|
|
try |
|
|
|
@ -421,15 +429,16 @@ public class ProjectPdfGenerator : IProjectPdfGenerator, ITransientDependency |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if(document == null) |
|
|
|
if (document == null) |
|
|
|
{ |
|
|
|
throw firstException!; |
|
|
|
} |
|
|
|
|
|
|
|
return document; |
|
|
|
} |
|
|
|
|
|
|
|
private List<DocumentRenderParameters> GenerateAllParameterCombinations(List<string> parameterKeys, Dictionary<string, List<string>> parameters) |
|
|
|
|
|
|
|
private static List<DocumentRenderParameters> GenerateAllParameterCombinations(List<string> parameterKeys, |
|
|
|
Dictionary<string, List<string>> parameters) |
|
|
|
{ |
|
|
|
var parameterCombinations = new List<DocumentRenderParameters>(); |
|
|
|
|
|
|
|
@ -437,7 +446,7 @@ public class ProjectPdfGenerator : IProjectPdfGenerator, ITransientDependency |
|
|
|
{ |
|
|
|
return parameterCombinations; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
GenerateCombinations(0, new DocumentRenderParameters()); |
|
|
|
return parameterCombinations; |
|
|
|
|
|
|
|
@ -458,33 +467,35 @@ public class ProjectPdfGenerator : IProjectPdfGenerator, ITransientDependency |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private static string GetDocumentId(string documentName, string format, DocumentRenderParameters parameters, bool isFirstCombinationDocument) |
|
|
|
private static string GetDocumentId(string documentName, string format, DocumentRenderParameters parameters, |
|
|
|
bool isFirstCombinationDocument) |
|
|
|
{ |
|
|
|
var id = documentName.Replace("." + format, string.Empty).Replace("/","-").Replace(" ", "-").ToLower(); |
|
|
|
if (parameters != null && !isFirstCombinationDocument) |
|
|
|
{ |
|
|
|
id = $"{id}{parameters.Select(x => $"{x.Key}_{x.Value}").JoinAsString("-")}"; |
|
|
|
} |
|
|
|
|
|
|
|
return id; |
|
|
|
var id = documentName.Replace("." + format, string.Empty).Replace("/", "-").Replace(" ", "-").ToLower(); |
|
|
|
if (parameters != null && !isFirstCombinationDocument) |
|
|
|
{ |
|
|
|
id = $"{id}{parameters.Select(x => $"{x.Key}_{x.Value}").JoinAsString("-")}"; |
|
|
|
} |
|
|
|
|
|
|
|
return id; |
|
|
|
} |
|
|
|
|
|
|
|
private static string GetDocumentTitle(string title, DocumentRenderParameters parameters, DocumentParams documentParams) |
|
|
|
|
|
|
|
private static string GetDocumentTitle(string title, DocumentRenderParameters parameters, |
|
|
|
DocumentParams documentParams) |
|
|
|
{ |
|
|
|
if (parameters == null || parameters.Count <= 0) |
|
|
|
{ |
|
|
|
return title; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
var paramValues = parameters.Select(x => |
|
|
|
{ |
|
|
|
var documentParam = documentParams.Parameters.FirstOrDefault(p => p.Name == x.Key); |
|
|
|
return $"{documentParam?.DisplayName ?? x.Key} : {documentParam?.Values[x.Value] ?? x.Value}"; |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
return title.Trim() + $" ({string.Join(", ", paramValues)})"; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private static List<string> GetPossibleNames(string originalDocumentName, string format) |
|
|
|
{ |
|
|
|
var extension = Path.GetExtension(originalDocumentName); |
|
|
|
@ -492,7 +503,7 @@ public class ProjectPdfGenerator : IProjectPdfGenerator, ITransientDependency |
|
|
|
{ |
|
|
|
extension = "." + format; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (!extension.Equals("." + format, StringComparison.OrdinalIgnoreCase)) |
|
|
|
{ |
|
|
|
return [originalDocumentName]; |
|
|
|
@ -502,33 +513,36 @@ public class ProjectPdfGenerator : IProjectPdfGenerator, ITransientDependency |
|
|
|
var titleCaseIndex = "Index." + format; |
|
|
|
var indexLength = lowerCaseIndex.Length; |
|
|
|
|
|
|
|
var possibleNames = new List<string> {originalDocumentName}; |
|
|
|
if (originalDocumentName.EndsWith("/" + lowerCaseIndex, StringComparison.OrdinalIgnoreCase) || originalDocumentName.Equals(lowerCaseIndex, StringComparison.OrdinalIgnoreCase)) |
|
|
|
var possibleNames = new List<string> { originalDocumentName }; |
|
|
|
if (originalDocumentName.EndsWith("/" + lowerCaseIndex, StringComparison.OrdinalIgnoreCase) || |
|
|
|
originalDocumentName.Equals(lowerCaseIndex, StringComparison.OrdinalIgnoreCase)) |
|
|
|
{ |
|
|
|
var indexPart = originalDocumentName.Right(indexLength); |
|
|
|
|
|
|
|
var documentNameWithoutIndex = originalDocumentName.Left(originalDocumentName.Length - lowerCaseIndex.Length); |
|
|
|
var documentNameWithoutIndex = |
|
|
|
originalDocumentName.Left(originalDocumentName.Length - lowerCaseIndex.Length); |
|
|
|
|
|
|
|
if(indexPart != lowerCaseIndex) |
|
|
|
if (indexPart != lowerCaseIndex) |
|
|
|
{ |
|
|
|
possibleNames.Add(documentNameWithoutIndex + lowerCaseIndex); |
|
|
|
} |
|
|
|
|
|
|
|
if(indexPart != titleCaseIndex) |
|
|
|
if (indexPart != titleCaseIndex) |
|
|
|
{ |
|
|
|
possibleNames.Add(documentNameWithoutIndex + titleCaseIndex); |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
var documentNameWithoutExtension = RemoveFileExtensionFromPath(originalDocumentName, format).EnsureEndsWith('/'); |
|
|
|
var documentNameWithoutExtension = |
|
|
|
RemoveFileExtensionFromPath(originalDocumentName, format).EnsureEndsWith('/'); |
|
|
|
possibleNames.Add(documentNameWithoutExtension + lowerCaseIndex); |
|
|
|
possibleNames.Add(documentNameWithoutExtension + titleCaseIndex); |
|
|
|
} |
|
|
|
|
|
|
|
return possibleNames; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private static string RemoveFileExtensionFromPath(string path, string format) |
|
|
|
{ |
|
|
|
if (path == null) |
|
|
|
|