Documents: use WinziPrint instead of WeasyPrint
This commit is contained in:
@ -3,14 +3,12 @@ using System.Threading.Tasks;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using Elwig.Helpers;
|
using Elwig.Helpers;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
namespace Elwig.Documents {
|
namespace Elwig.Documents {
|
||||||
public abstract partial class Document : IDisposable {
|
public abstract partial class Document : IDisposable {
|
||||||
|
|
||||||
private TempFile? _pdfFile = null;
|
private TempFile? _pdfFile = null;
|
||||||
private string? _renderedHtml = null;
|
|
||||||
|
|
||||||
public bool ShowFoldMarks = App.Config.Debug;
|
public bool ShowFoldMarks = App.Config.Debug;
|
||||||
|
|
||||||
@ -39,18 +37,6 @@ namespace Elwig.Documents {
|
|||||||
Date = DateTime.Today;
|
Date = DateTime.Today;
|
||||||
}
|
}
|
||||||
|
|
||||||
[GeneratedRegex(@"</body>.*?</footer>\s*</div>", RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.Compiled)]
|
|
||||||
private static partial Regex GeneratedDocumentHeaderRegex();
|
|
||||||
private static readonly Regex DocumentHeaderRegex = GeneratedDocumentHeaderRegex();
|
|
||||||
|
|
||||||
[GeneratedRegex(@"<style>.*?/style>", RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.Compiled)]
|
|
||||||
private static partial Regex GeneratedHtmlStyleRegex();
|
|
||||||
private static readonly Regex HtmlStyleRegex = GeneratedHtmlStyleRegex();
|
|
||||||
|
|
||||||
[GeneratedRegex(@"<link[^>]*>", RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.Compiled)]
|
|
||||||
private static partial Regex GeneratedHtmlLinkRegex();
|
|
||||||
private static readonly Regex HtmlLinkRegex = GeneratedHtmlLinkRegex();
|
|
||||||
|
|
||||||
~Document() {
|
~Document() {
|
||||||
Dispose();
|
Dispose();
|
||||||
}
|
}
|
||||||
@ -62,33 +48,10 @@ namespace Elwig.Documents {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static async Task<Document> Merge(IEnumerable<Document> docs) {
|
public static async Task<Document> Merge(IEnumerable<Document> docs) {
|
||||||
string html = "";
|
return new MergedDocument(docs);
|
||||||
var styles = new List<string>();
|
|
||||||
foreach (var d in docs) {
|
|
||||||
var h = await d.Render();
|
|
||||||
var s = HtmlStyleRegex.Matches(h).Select(m => m.Value).ToList();
|
|
||||||
var l = HtmlLinkRegex.Matches(h).Select(m => m.Value).ToList();
|
|
||||||
if (s.All(styles.Contains)) {
|
|
||||||
h = HtmlStyleRegex.Replace(h, "");
|
|
||||||
} else {
|
|
||||||
styles.AddRange(s);
|
|
||||||
}
|
|
||||||
if (l.All(styles.Contains)) {
|
|
||||||
h = HtmlLinkRegex.Replace(h, "");
|
|
||||||
} else {
|
|
||||||
styles.AddRange(l);
|
|
||||||
}
|
|
||||||
html += h;
|
|
||||||
}
|
|
||||||
html = DocumentHeaderRegex.Replace(html, "<div class='document-break'/>");
|
|
||||||
return new InternalDocument("Mehrere Dokumente") {
|
|
||||||
_renderedHtml = html,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<string> Render() {
|
private async Task<string> Render() {
|
||||||
if (_renderedHtml != null)
|
|
||||||
return _renderedHtml;
|
|
||||||
string name;
|
string name;
|
||||||
if (this is BusinessLetter) {
|
if (this is BusinessLetter) {
|
||||||
name = "BusinessLetter";
|
name = "BusinessLetter";
|
||||||
@ -109,11 +72,25 @@ namespace Elwig.Documents {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async Task<string> Render(string name) {
|
private async Task<string> Render(string name) {
|
||||||
_renderedHtml = await Html.CompileRenderAsync(name, this);
|
return await Html.CompileRenderAsync(name, this); ;
|
||||||
return _renderedHtml;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Generate() {
|
public async Task Generate() {
|
||||||
|
if (this is MergedDocument m) {
|
||||||
|
var pdf = new TempFile("pdf");
|
||||||
|
var tmpHtmls = new List<TempFile>();
|
||||||
|
foreach (var doc in m.Documents) {
|
||||||
|
var tmpHtml = new TempFile("html");
|
||||||
|
await doc.Render();
|
||||||
|
await File.WriteAllTextAsync(tmpHtml.FilePath, await doc.Render(), Utils.UTF8);
|
||||||
|
tmpHtmls.Add(tmpHtml);
|
||||||
|
}
|
||||||
|
await Pdf.Convert(tmpHtmls.Select(f => f.FilePath), pdf.FilePath);
|
||||||
|
foreach (var tmp in tmpHtmls) {
|
||||||
|
tmp.Dispose();
|
||||||
|
}
|
||||||
|
_pdfFile = pdf;
|
||||||
|
} else {
|
||||||
var pdf = new TempFile("pdf");
|
var pdf = new TempFile("pdf");
|
||||||
using (var tmpHtml = new TempFile("html")) {
|
using (var tmpHtml = new TempFile("html")) {
|
||||||
await File.WriteAllTextAsync(tmpHtml.FilePath, await Render(), Utils.UTF8);
|
await File.WriteAllTextAsync(tmpHtml.FilePath, await Render(), Utils.UTF8);
|
||||||
@ -121,6 +98,7 @@ namespace Elwig.Documents {
|
|||||||
}
|
}
|
||||||
_pdfFile = pdf;
|
_pdfFile = pdf;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void SaveTo(string pdfPath) {
|
public void SaveTo(string pdfPath) {
|
||||||
if (_pdfFile == null) throw new InvalidOperationException("Pdf file has not been generated yet");
|
if (_pdfFile == null) throw new InvalidOperationException("Pdf file has not been generated yet");
|
||||||
@ -137,8 +115,11 @@ namespace Elwig.Documents {
|
|||||||
Pdf.Show(_pdfFile.NewReference(), Title + (this is BusinessDocument b ? $" - {b.Member.Name}" : ""));
|
Pdf.Show(_pdfFile.NewReference(), Title + (this is BusinessDocument b ? $" - {b.Member.Name}" : ""));
|
||||||
}
|
}
|
||||||
|
|
||||||
private class InternalDocument : Document {
|
private class MergedDocument : Document {
|
||||||
public InternalDocument(string title) : base(title) { }
|
public IEnumerable<Document> Documents;
|
||||||
|
public MergedDocument(IEnumerable<Document> docs) : base("Mehrere Dokumente") {
|
||||||
|
Documents = docs;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,44 +2,50 @@ using System.Threading.Tasks;
|
|||||||
using Elwig.Helpers;
|
using Elwig.Helpers;
|
||||||
using Elwig.Windows;
|
using Elwig.Windows;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using Balbarak.WeasyPrint;
|
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace Elwig.Documents {
|
namespace Elwig.Documents {
|
||||||
public static class Pdf {
|
public static class Pdf {
|
||||||
|
|
||||||
private static readonly string PdfToPrinter = App.ExePath + "PDFtoPrinter.exe";
|
private static readonly string PdfToPrinter = App.ExePath + "PDFtoPrinter.exe";
|
||||||
private static readonly FilesManager WeasyPrintManager = new();
|
private static readonly string WinziPrint = App.ExePath + "WinziPrint.exe";
|
||||||
private static string? WeasyPrintPython = null;
|
private static Process? WinziPrintProc;
|
||||||
private static string? WeasyPrintDir => WeasyPrintManager.FolderPath;
|
public static bool IsReady => WinziPrintProc != null;
|
||||||
public static bool IsReady => WeasyPrintPython != null && WeasyPrintDir != null;
|
|
||||||
|
|
||||||
public static async Task Init(Action evtHandler) {
|
public static async Task Init(Action evtHandler) {
|
||||||
if (!WeasyPrintManager.IsFilesExsited()) {
|
var p = new Process() { StartInfo = new() {
|
||||||
await WeasyPrintManager.InitFilesAsync();
|
FileName = WinziPrint,
|
||||||
}
|
Arguments = "-",
|
||||||
WeasyPrintPython = Path.Combine(WeasyPrintManager.FolderPath, "python.exe");
|
CreateNoWindow = true,
|
||||||
|
UseShellExecute = false,
|
||||||
|
RedirectStandardInput = true,
|
||||||
|
RedirectStandardOutput = true
|
||||||
|
} };
|
||||||
|
p.Start();
|
||||||
|
WinziPrintProc = p;
|
||||||
evtHandler();
|
evtHandler();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task Convert(string htmlPath, string pdfPath) {
|
public static async Task<IEnumerable<int>> Convert(string htmlPath, string pdfPath) {
|
||||||
var p = new Process() { StartInfo = new() {
|
return await Convert(new string[] { htmlPath }, pdfPath);
|
||||||
FileName = WeasyPrintPython,
|
}
|
||||||
CreateNoWindow = true,
|
|
||||||
WorkingDirectory = WeasyPrintDir,
|
public static async Task<IEnumerable<int>> Convert(IEnumerable<string> htmlPath, string pdfPath) {
|
||||||
RedirectStandardError = true,
|
if (WinziPrintProc == null) throw new InvalidOperationException("The WinziPrint process has not been initialized yet");
|
||||||
} };
|
await WinziPrintProc.StandardInput.WriteLineAsync($"{string.Join(';', htmlPath)};{pdfPath}");
|
||||||
p.StartInfo.EnvironmentVariables["PATH"] = "Scripts;gtk3;" + Environment.GetEnvironmentVariable("PATH");
|
var line = await WinziPrintProc.StandardOutput.ReadLineAsync() ?? throw new IOException("Invalid response from WinziPrint");
|
||||||
p.StartInfo.ArgumentList.Add("scripts/weasyprint.exe");
|
if (line.StartsWith("error:")) {
|
||||||
p.StartInfo.ArgumentList.Add("-e");
|
MessageBox.Show(line[6..].Trim(), "Fehler", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||||
p.StartInfo.ArgumentList.Add("utf8");
|
return Array.Empty<int>();
|
||||||
p.StartInfo.ArgumentList.Add(htmlPath);
|
}
|
||||||
p.StartInfo.ArgumentList.Add(pdfPath);
|
var m = Regex.Match(line, @"\(([0-9, ]+)\)");
|
||||||
p.Start();
|
return m.Groups[1].Value.Split(", ").Select(n => int.Parse(n));
|
||||||
await p.WaitForExitAsync();
|
|
||||||
var stderr = await p.StandardError.ReadToEndAsync();
|
|
||||||
if (p.ExitCode != 0) throw new Exception(stderr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Show(TempFile file, string title) {
|
public static void Show(TempFile file, string title) {
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Balbarak.WeasyPrint" Version="2.0.2" />
|
|
||||||
<PackageReference Include="Extended.Wpf.Toolkit" Version="4.5.1" />
|
<PackageReference Include="Extended.Wpf.Toolkit" Version="4.5.1" />
|
||||||
<PackageReference Include="ini-parser" Version="2.5.2" />
|
<PackageReference Include="ini-parser" Version="2.5.2" />
|
||||||
<PackageReference Include="LinqKit" Version="1.2.4" />
|
<PackageReference Include="LinqKit" Version="1.2.4" />
|
||||||
|
Reference in New Issue
Block a user