ln.templates/ln.templates.service/TemplateService.cs

187 lines
6.6 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using Jint.Native.Object;
using ln.patterns;
using ln.templates.service.render;
namespace ln.templates.service
{
public class TemplateService
{
public string StoragePath { get; }
public RecursiveResolver Resolver { get; }
public TemplateService(string storagePath)
{
StoragePath = Path.GetFullPath(storagePath);
Initialize();
Resolver = new RecursiveResolver(Path.Combine(StoragePath, "templates"));
}
private void Initialize()
{
EnsureDirectory("");
EnsureDirectory("templates");
EnsureDirectory("resources");
EnsureDirectory("spool");
EnsureDirectory("out");
}
private void EnsureDirectory(string directoryName)
{
string finalPath = Path.Combine(StoragePath, directoryName);
if (!Directory.Exists(finalPath))
Directory.CreateDirectory(finalPath);
}
public bool StoreTemplate(string templatePath, Stream sourceStream)
{
string finalPath = Path.GetFullPath(Path.Combine(StoragePath, "templates", templatePath));
if (finalPath.StartsWith(StoragePath))
{
string finalDirectory = Path.GetDirectoryName(finalPath);
if (!Directory.Exists(finalDirectory))
{
Span<string> finalDirectoryParts = Path.GetRelativePath(StoragePath,finalDirectory).Split(Path.DirectorySeparatorChar);
string currentPath = StoragePath;
for (int n = 0; n < finalDirectoryParts.Length; n++)
{
currentPath = Path.Combine(currentPath, finalDirectoryParts[n]);
if (!Directory.Exists(currentPath))
Directory.CreateDirectory(currentPath);
}
}
using (FileStream fs = new FileStream(finalPath, FileMode.Create))
sourceStream.CopyTo(fs);
return true;
}
return false;
}
public bool StoreTemplateMetadata(string templatePath, Stream sourceStream)
{
string finalPath = Path.GetFullPath(Path.Combine(StoragePath, "templates", templatePath));
if (finalPath.StartsWith(StoragePath))
{
if (File.Exists(finalPath))
{
string metaFileName = Path.Combine(Path.GetDirectoryName(finalPath), String.Format("{0}.json",Path.GetFileNameWithoutExtension(finalPath)));
using (FileStream fs = new FileStream(metaFileName, FileMode.Create))
sourceStream.CopyTo(fs);
return true;
}
}
return false;
}
public bool GetTemplateSource(string templatePath, out Stream sourceStream)
{
string finalPath = Path.GetFullPath(Path.Combine(StoragePath, "templates", templatePath));
if (finalPath.StartsWith(StoragePath))
{
sourceStream = new FileStream(finalPath, FileMode.Open, FileAccess.Read);
return true;
}
sourceStream = null;
return false;
}
public String[] ListTemplates()
{
List<string> templateFileNames = new List<string>();
Queue<string> subdirs = new Queue<string>();
string templatesPath = Path.Combine(StoragePath, "templates");
subdirs.Enqueue(templatesPath);
while (subdirs.Count > 0)
{
string currentSubDir = subdirs.Dequeue();
foreach (var file in Directory.GetFiles(currentSubDir, "*.html"))
{
templateFileNames.Add(Path.GetRelativePath(templatesPath, file));
}
foreach (var directory in Directory.GetDirectories(currentSubDir))
{
subdirs.Enqueue(directory);
}
}
return templateFileNames.ToArray();
}
public bool RenderTemplate(string templatePath, ObjectInstance o, out Stream templateStream)
=> RenderTemplate(templatePath, o).TryGetValue(out templateStream);
public Optional<Stream> RenderTemplate(string templatePath, ObjectInstance o)
{
if (templatePath is null)
throw new NullReferenceException();
string directoryPath = Path.GetDirectoryName(templatePath);
string templateFilename = Path.GetFileName(templatePath);
var resolver = Resolver
.FindResolver(directoryPath);
if (resolver is null)
return new FileNotFoundException("", directoryPath);
Template template = resolver.GetTemplate(templateFilename);
if (template is null)
return new FileNotFoundException("", templatePath);
TempFileStream tempFileStream = new TempFileStream(".html");
Context context = new Context(template.Resolver, new StreamWriter(tempFileStream));
try
{
template.Render(context, o);
}
catch (Exception e)
{
return e;
}
tempFileStream.Position = 0;
return tempFileStream;
}
public bool RenderPDF(string templatePath, ObjectInstance o, out Stream targetStream) =>
RenderPDF(templatePath, o).TryGetValue(out targetStream);
public Optional<Stream> RenderPDF(string templatePath, ObjectInstance o)
{
if (templatePath is null)
throw new NullReferenceException();
string directoryPath = Path.GetDirectoryName(templatePath);
string templateFilename = Path.GetFileName(templatePath);
var resolver = Resolver
.FindResolver(directoryPath);
if (resolver is null)
return new FileNotFoundException("", directoryPath);
Template template = resolver.GetTemplate(templateFilename);
if (template is null)
return new FileNotFoundException("", templatePath);
return PuppeteerRenderer.RenderTemplate(
template,
String.Format("file://{0}", Path.Combine(StoragePath, "resources/")),
o
);
}
}
}