ficdown/Ficdown.Parser/Render/HtmlRenderer.cs

98 lines
3.7 KiB
C#

namespace Ficdown.Parser.Render
{
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Markdig;
using Model.Parser;
using Parser;
public class HtmlRenderer : IRenderer
{
private static Logger _logger = Logger.GetLogger<HtmlRenderer>();
private readonly string _language;
public List<FicdownException> Warnings { private get; set; }
public string IndexTemplate { get; set; }
public string SceneTemplate { get; set; }
public string StylesTemplate { get; set; }
public string ImageDir { get; set; }
protected ResolvedStory Story { get; set; }
public HtmlRenderer(string language)
{
_language = language;
}
public virtual void Render(ResolvedStory story, string outPath, bool debug = false)
{
Story = story;
GenerateHtml(story, outPath, debug);
}
private string FillTemplate(string template, Dictionary<string, string> values)
{
return values.Aggregate(template,
(current, pair) => current.Replace(string.Format("@{0}", pair.Key), pair.Value));
}
protected void GenerateHtml(ResolvedStory story, string outPath, bool debug)
{
_logger.Debug("Generating HTML...");
var index = FillTemplate(IndexTemplate ?? Template.Index, new Dictionary<string, string>
{
{"Language", _language},
{"Title", story.Name},
{"Description", Markdown.ToHtml(story.Description)},
{"FirstScene", string.Format("{0}.html", story.FirstPage)}
});
File.WriteAllText(Path.Combine(outPath, "index.html"), index);
foreach (var page in story.Pages)
{
File.WriteAllText(Path.Combine(outPath, "styles.css"), StylesTemplate ?? Template.Styles);
var content = page.Content;
foreach (var anchor in Utilities.GetInstance(Warnings, page.Name).ParseAnchors(page.Content))
{
var newAnchor = string.Format("[{0}]({1}.html)", anchor.Text, anchor.Href.Target);
content = content.Replace(anchor.Original, newAnchor);
}
if (debug)
{
content += string.Format("\n\n### State Debug\n\n{0}",
string.Join("\n", page.ActiveToggles.Select(t => string.Format("- {0}", t)).ToArray()));
}
var scene = FillTemplate(SceneTemplate ?? Template.Scene, new Dictionary<string, string>
{
{"Language", _language},
{"Title", story.Name},
{"Content", Markdown.ToHtml(content)}
});
File.WriteAllText(Path.Combine(outPath, string.Format("{0}.html", page.Name)), scene);
}
if (!string.IsNullOrWhiteSpace(ImageDir))
{
var dirname = ImageDir.Substring(ImageDir.LastIndexOf(Path.DirectorySeparatorChar) + 1);
Directory.CreateDirectory(Path.Combine(outPath, dirname));
CopyFilesRecursively(ImageDir, Path.Combine(outPath, dirname));
}
}
private static void CopyFilesRecursively(string sourcePath, string destinationPath)
{
foreach (var dirPath in Directory.GetDirectories(sourcePath, "*", SearchOption.AllDirectories))
Directory.CreateDirectory(dirPath.Replace(sourcePath, destinationPath));
foreach (var newPath in Directory.GetFiles(sourcePath, "*.*", SearchOption.AllDirectories))
File.Copy(newPath, newPath.Replace(sourcePath, destinationPath));
}
}
}