From 8da4ce76ffc77154f93d3071d939b022a6d5039a Mon Sep 17 00:00:00 2001 From: aiueo-1234 <130837816+aiueo-1234@users.noreply.github.com> Date: Sun, 3 Mar 2024 18:47:16 +0900 Subject: [PATCH 1/7] =?UTF-8?q?TryCreateEpubAsync=E3=82=92=E3=82=B5?= =?UTF-8?q?=E3=83=BC=E3=83=93=E3=82=B9=E3=81=A8=E3=81=97=E3=81=A6=E5=88=87?= =?UTF-8?q?=E3=82=8A=E5=87=BA=E3=81=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Contracts/Services/IEpubGeneration.cs | 8 ++ Epub/KoeBook.Epub/Models/EpubDocument.cs | 110 ++---------------- Epub/KoeBook.Epub/Services/EpubGeneration.cs | 104 +++++++++++++++++ 3 files changed, 120 insertions(+), 102 deletions(-) create mode 100644 Epub/KoeBook.Epub/Contracts/Services/IEpubGeneration.cs create mode 100644 Epub/KoeBook.Epub/Services/EpubGeneration.cs diff --git a/Epub/KoeBook.Epub/Contracts/Services/IEpubGeneration.cs b/Epub/KoeBook.Epub/Contracts/Services/IEpubGeneration.cs new file mode 100644 index 0000000..c06b3d4 --- /dev/null +++ b/Epub/KoeBook.Epub/Contracts/Services/IEpubGeneration.cs @@ -0,0 +1,8 @@ +using KoeBook.Epub.Models; + +namespace KoeBook.Epub.Contracts.Services; + +public interface IEpubGeneration +{ + ValueTask TryCreateEpubAsync(EpubDocument epubDocument, string tmpDirectory, CancellationToken ct); +} diff --git a/Epub/KoeBook.Epub/Models/EpubDocument.cs b/Epub/KoeBook.Epub/Models/EpubDocument.cs index 583d0ce..e46ac21 100644 --- a/Epub/KoeBook.Epub/Models/EpubDocument.cs +++ b/Epub/KoeBook.Epub/Models/EpubDocument.cs @@ -6,15 +6,6 @@ namespace KoeBook.Epub.Models; public class EpubDocument(string title, string author, string coverFilePath, Guid id) { - readonly string _containerXml = """ - - - - - - - """; - public string Title { get; set; } = title; public string Author { get; set; } = author; @@ -214,97 +205,12 @@ public string CreateOpf() return builder.ToString(); } - public async Task TryCreateEpubAsync(string tmpDirectory, string name, CancellationToken ct) - { - if (!File.Exists(CoverFilePath)) - { - throw new FileNotFoundException("指定されたカバーファイルが存在しません", CoverFilePath); - } - try - { - using var fs = File.Create(Path.Combine(tmpDirectory, $"{name}.epub")); - using var archive = new ZipArchive(fs, ZipArchiveMode.Create); - - var mimeTypeEntry = archive.CreateEntry("mimetype", CompressionLevel.NoCompression); - using (var mimeTypeStream = new StreamWriter(mimeTypeEntry.Open())) - { - await mimeTypeStream.WriteAsync("application/epub+zip").ConfigureAwait(false); - await mimeTypeStream.FlushAsync(ct).ConfigureAwait(false); - } - - var containerEntry = archive.CreateEntry("META-INF/container.xml"); - using (var containerStream = new StreamWriter(containerEntry.Open())) - { - await containerStream.WriteLineAsync(_containerXml).ConfigureAwait(false); - await containerStream.FlushAsync(ct).ConfigureAwait(false); - } - - archive.CreateEntryFromFile(CoverFilePath, $"OEBPS/{Path.GetFileName(CoverFilePath)}"); - - var cssEntry = archive.CreateEntry("OEBPS/style.css"); - using (var cssStream = new StreamWriter(cssEntry.Open())) - { - await cssStream.WriteLineAsync(CreateCssText()).ConfigureAwait(false); - await cssStream.FlushAsync(ct).ConfigureAwait(false); - } - - var navEntry = archive.CreateEntry("OEBPS/nav.xhtml"); - using (var navStream = new StreamWriter(navEntry.Open())) - { - await navStream.WriteLineAsync(CreateNavXhtml()).ConfigureAwait(false); - await navStream.FlushAsync(ct).ConfigureAwait(false); - } - - var opfEntry = archive.CreateEntry("OEBPS/book.opf"); - using (var opfStream = new StreamWriter(opfEntry.Open())) - { - await opfStream.WriteLineAsync(CreateOpf()).ConfigureAwait(false); - await opfStream.FlushAsync(ct).ConfigureAwait(false); - } - - for (var i = 0; i < Chapters.Count; i++) - { - for (var j = 0; j < Chapters[i].Sections.Count; j++) - { - var sectionXhtmlEntry = archive.CreateEntry($"OEBPS/{Chapters[i].Sections[j].Id}.xhtml"); - using (var sectionXhtmlStream = new StreamWriter(sectionXhtmlEntry.Open())) - { - await sectionXhtmlStream.WriteLineAsync(Chapters[i].Sections[j].CreateSectionXhtml()).ConfigureAwait(false); - await sectionXhtmlStream.FlushAsync(ct).ConfigureAwait(false); - } - var sectionSmilEntry = archive.CreateEntry($"OEBPS/{Chapters[i].Sections[j].Id}_audio.smil"); - using (var sectionSmilStream = new StreamWriter(sectionSmilEntry.Open())) - { - await sectionSmilStream.WriteLineAsync(Chapters[i].Sections[j].CreateSectionSmil()).ConfigureAwait(false); - await sectionSmilStream.FlushAsync(ct).ConfigureAwait(false); - } - for (var k = 0; k < Chapters[i].Sections[j].Elements.Count; k++) - { - var element = Chapters[i].Sections[j].Elements[k]; - if (element is Paragraph para && para.Audio != null) - { - var audioEntry = archive.CreateEntry($"OEBPS/{Chapters[i].Sections[j].Id}_p{k}.mp3"); - using var audioStream = para.Audio.GetStream(); - using var audioEntryStream = audioEntry.Open(); - await audioStream.CopyToAsync(audioEntryStream, ct).ConfigureAwait(false); - await audioEntryStream.FlushAsync(ct).ConfigureAwait(false); - } - else if (element is Picture pic && File.Exists(pic.PictureFilePath)) - { - archive.CreateEntryFromFile(pic.PictureFilePath, $"OEBPS/{Chapters[i].Sections[j].Id}_p{k}{Path.GetExtension(pic.PictureFilePath)}"); - } - } - } - } - return true; - } - catch (OperationCanceledException) - { - throw; - } - catch - { - return false; - } - } + public string CreateContainerXml() => """ + + + + + + + """; } diff --git a/Epub/KoeBook.Epub/Services/EpubGeneration.cs b/Epub/KoeBook.Epub/Services/EpubGeneration.cs new file mode 100644 index 0000000..9a724eb --- /dev/null +++ b/Epub/KoeBook.Epub/Services/EpubGeneration.cs @@ -0,0 +1,104 @@ +using KoeBook.Epub.Contracts.Services; +using KoeBook.Epub.Models; +using System.Diagnostics.CodeAnalysis; +using System.Globalization; +using System.IO.Compression; +using System.Text; + +namespace KoeBook.Epub.Services; +public class EpubGeneration : IEpubGeneration +{ + public async ValueTask TryCreateEpubAsync(EpubDocument epubDocument,string tmpDirectory, CancellationToken ct) + { + if (!File.Exists(epubDocument.CoverFilePath)) + { + throw new FileNotFoundException("指定されたカバーファイルが存在しません", epubDocument.CoverFilePath); + } + try + { + using var fs = File.Create(Path.Combine(tmpDirectory, $"{epubDocument.Id}.epub")); + using var archive = new ZipArchive(fs, ZipArchiveMode.Create); + + var mimeTypeEntry = archive.CreateEntry("mimetype", CompressionLevel.NoCompression); + using (var mimeTypeStream = new StreamWriter(mimeTypeEntry.Open())) + { + await mimeTypeStream.WriteAsync("application/epub+zip").ConfigureAwait(false); + await mimeTypeStream.FlushAsync(ct).ConfigureAwait(false); + } + + var containerEntry = archive.CreateEntry("META-INF/container.xml"); + using (var containerStream = new StreamWriter(containerEntry.Open())) + { + await containerStream.WriteLineAsync(epubDocument.CreateContainerXml()).ConfigureAwait(false); + await containerStream.FlushAsync(ct).ConfigureAwait(false); + } + + archive.CreateEntryFromFile(epubDocument.CoverFilePath, $"OEBPS/{Path.GetFileName(epubDocument.CoverFilePath)}"); + + var cssEntry = archive.CreateEntry("OEBPS/style.css"); + using (var cssStream = new StreamWriter(cssEntry.Open())) + { + await cssStream.WriteLineAsync(epubDocument.CreateCssText()).ConfigureAwait(false); + await cssStream.FlushAsync(ct).ConfigureAwait(false); + } + + var navEntry = archive.CreateEntry("OEBPS/nav.xhtml"); + using (var navStream = new StreamWriter(navEntry.Open())) + { + await navStream.WriteLineAsync(epubDocument.CreateNavXhtml()).ConfigureAwait(false); + await navStream.FlushAsync(ct).ConfigureAwait(false); + } + + var opfEntry = archive.CreateEntry("OEBPS/book.opf"); + using (var opfStream = new StreamWriter(opfEntry.Open())) + { + await opfStream.WriteLineAsync(epubDocument.CreateOpf()).ConfigureAwait(false); + await opfStream.FlushAsync(ct).ConfigureAwait(false); + } + + for (var i = 0; i < epubDocument.Chapters.Count; i++) + { + for (var j = 0; j < epubDocument.Chapters[i].Sections.Count; j++) + { + var sectionXhtmlEntry = archive.CreateEntry($"OEBPS/{epubDocument.Chapters[i].Sections[j].Id}.xhtml"); + using (var sectionXhtmlStream = new StreamWriter(sectionXhtmlEntry.Open())) + { + await sectionXhtmlStream.WriteLineAsync(epubDocument.Chapters[i].Sections[j].CreateSectionXhtml()).ConfigureAwait(false); + await sectionXhtmlStream.FlushAsync(ct).ConfigureAwait(false); + } + var sectionSmilEntry = archive.CreateEntry($"OEBPS/{epubDocument.Chapters[i].Sections[j].Id}_audio.smil"); + using (var sectionSmilStream = new StreamWriter(sectionSmilEntry.Open())) + { + await sectionSmilStream.WriteLineAsync(epubDocument.Chapters[i].Sections[j].CreateSectionSmil()).ConfigureAwait(false); + await sectionSmilStream.FlushAsync(ct).ConfigureAwait(false); + } + for (var k = 0; k < epubDocument.Chapters[i].Sections[j].Elements.Count; k++) + { + var element = epubDocument.Chapters[i].Sections[j].Elements[k]; + if (element is Paragraph para && para.Audio != null) + { + var audioEntry = archive.CreateEntry($"OEBPS/{epubDocument.Chapters[i].Sections[j].Id}_p{k}.mp3"); + using var audioStream = para.Audio.GetStream(); + using var audioEntryStream = audioEntry.Open(); + await audioStream.CopyToAsync(audioEntryStream, ct).ConfigureAwait(false); + await audioEntryStream.FlushAsync(ct).ConfigureAwait(false); + } + else if (element is Picture pic && File.Exists(pic.PictureFilePath)) + { + archive.CreateEntryFromFile(pic.PictureFilePath, $"OEBPS/{epubDocument.Chapters[i].Sections[j].Id}_p{k}{Path.GetExtension(pic.PictureFilePath)}"); + } + } + } + } + return true; + } + catch (OperationCanceledException) + { + throw; + } + catch + { + return false; + } + } +} From 00ed0be0e36d8736137a46d8763bc76671191bc9 Mon Sep 17 00:00:00 2001 From: aiueo-1234 <130837816+aiueo-1234@users.noreply.github.com> Date: Sun, 3 Mar 2024 19:05:07 +0900 Subject: [PATCH 2/7] =?UTF-8?q?=E5=90=8D=E7=A7=B0=E5=A4=89=E6=9B=B4?= =?UTF-8?q?=E3=81=A8DI=E7=99=BB=E9=8C=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Services/{IEpubGeneration.cs => IEpubCreateService.cs} | 2 +- .../Services/{EpubGeneration.cs => EpubCreateService.cs} | 4 ++-- KoeBook.Core/Services/EpubGenerateService.cs | 6 ++++-- KoeBook/App.xaml.cs | 1 + 4 files changed, 8 insertions(+), 5 deletions(-) rename Epub/KoeBook.Epub/Contracts/Services/{IEpubGeneration.cs => IEpubCreateService.cs} (84%) rename Epub/KoeBook.Epub/Services/{EpubGeneration.cs => EpubCreateService.cs} (97%) diff --git a/Epub/KoeBook.Epub/Contracts/Services/IEpubGeneration.cs b/Epub/KoeBook.Epub/Contracts/Services/IEpubCreateService.cs similarity index 84% rename from Epub/KoeBook.Epub/Contracts/Services/IEpubGeneration.cs rename to Epub/KoeBook.Epub/Contracts/Services/IEpubCreateService.cs index c06b3d4..6b9df0a 100644 --- a/Epub/KoeBook.Epub/Contracts/Services/IEpubGeneration.cs +++ b/Epub/KoeBook.Epub/Contracts/Services/IEpubCreateService.cs @@ -2,7 +2,7 @@ namespace KoeBook.Epub.Contracts.Services; -public interface IEpubGeneration +public interface IEpubCreateService { ValueTask TryCreateEpubAsync(EpubDocument epubDocument, string tmpDirectory, CancellationToken ct); } diff --git a/Epub/KoeBook.Epub/Services/EpubGeneration.cs b/Epub/KoeBook.Epub/Services/EpubCreateService.cs similarity index 97% rename from Epub/KoeBook.Epub/Services/EpubGeneration.cs rename to Epub/KoeBook.Epub/Services/EpubCreateService.cs index 9a724eb..4bfe3e0 100644 --- a/Epub/KoeBook.Epub/Services/EpubGeneration.cs +++ b/Epub/KoeBook.Epub/Services/EpubCreateService.cs @@ -6,9 +6,9 @@ using System.Text; namespace KoeBook.Epub.Services; -public class EpubGeneration : IEpubGeneration +public class EpubCreateService : IEpubCreateService { - public async ValueTask TryCreateEpubAsync(EpubDocument epubDocument,string tmpDirectory, CancellationToken ct) + public async ValueTask TryCreateEpubAsync(EpubDocument epubDocument, string tmpDirectory, CancellationToken ct) { if (!File.Exists(epubDocument.CoverFilePath)) { diff --git a/KoeBook.Core/Services/EpubGenerateService.cs b/KoeBook.Core/Services/EpubGenerateService.cs index 6052d8c..2810e8d 100644 --- a/KoeBook.Core/Services/EpubGenerateService.cs +++ b/KoeBook.Core/Services/EpubGenerateService.cs @@ -1,14 +1,16 @@ using KoeBook.Core.Contracts.Services; using KoeBook.Core.Models; using KoeBook.Epub; +using KoeBook.Epub.Contracts.Services; using KoeBook.Epub.Models; namespace KoeBook.Core.Services; -public class EpubGenerateService(ISoundGenerationService soundGenerationService, IEpubDocumentStoreService epubDocumentStoreService) : IEpubGenerateService +public class EpubGenerateService(ISoundGenerationService soundGenerationService, IEpubDocumentStoreService epubDocumentStoreService, IEpubCreateService epubCreateService) : IEpubGenerateService { private ISoundGenerationService _soundGenerationService = soundGenerationService; private IEpubDocumentStoreService _documentStoreService = epubDocumentStoreService; + private IEpubCreateService _createService = epubCreateService; public async ValueTask GenerateEpubAsync(BookScripts bookScripts, string tempDirectory, CancellationToken cancellationToken) { @@ -22,7 +24,7 @@ public async ValueTask GenerateEpubAsync(BookScripts bookScripts, string scriptLine.Paragraph.Audio = new Audio(await _soundGenerationService.GenerateLineSoundAsync(scriptLine, bookScripts.Options, cancellationToken).ConfigureAwait(false)); } - if (await document.TryCreateEpubAsync(tempDirectory, bookScripts.BookProperties.Id.ToString(), cancellationToken).ConfigureAwait(false)) + if (await _createService.TryCreateEpubAsync(document, tempDirectory, cancellationToken).ConfigureAwait(false)) { _documentStoreService.Unregister(bookScripts.BookProperties.Id); return Path.Combine(tempDirectory, $"{bookScripts.BookProperties.Id}.epub"); diff --git a/KoeBook/App.xaml.cs b/KoeBook/App.xaml.cs index ddde655..3b1e62f 100644 --- a/KoeBook/App.xaml.cs +++ b/KoeBook/App.xaml.cs @@ -102,6 +102,7 @@ public App() services.AddSingleton() .AddSingleton() .AddSingleton(); + services.AddSingleton(); // Views and ViewModels services.AddTransient(); From c6f891194839106d78a165450faf517676900100 Mon Sep 17 00:00:00 2001 From: aiueo-1234 <130837816+aiueo-1234@users.noreply.github.com> Date: Wed, 6 Mar 2024 23:07:09 +0900 Subject: [PATCH 3/7] =?UTF-8?q?EpubDocument=E5=86=85=E3=81=AE.epub?= =?UTF-8?q?=E7=94=9F=E6=88=90=E3=81=AB=E9=96=A2=E3=81=99=E3=82=8B=E3=82=B3?= =?UTF-8?q?=E3=83=BC=E3=83=89=E3=82=92=E7=A7=BB=E5=8B=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Epub/KoeBook.Epub/EpubCreateHelper.cs | 17 -- Epub/KoeBook.Epub/Models/EpubDocument.cs | 179 +----------------- .../Services/EpubCreateService.cs | 171 ++++++++++++++++- 3 files changed, 175 insertions(+), 192 deletions(-) delete mode 100644 Epub/KoeBook.Epub/EpubCreateHelper.cs diff --git a/Epub/KoeBook.Epub/EpubCreateHelper.cs b/Epub/KoeBook.Epub/EpubCreateHelper.cs deleted file mode 100644 index 936a546..0000000 --- a/Epub/KoeBook.Epub/EpubCreateHelper.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace KoeBook.Epub; - -internal static class EpubCreateHelper -{ - internal static string GetImagesMediaType(string path) - { - return Path.GetExtension(path) switch - { - ".gif" => "image/gif", - ".jpg" or ".jpeg" => "image/jpeg", - ".png" => "image/png", - ".svg" => "image/svg+xml", - ".webp" => "image/webp", - _ => "" - }; - } -} diff --git a/Epub/KoeBook.Epub/Models/EpubDocument.cs b/Epub/KoeBook.Epub/Models/EpubDocument.cs index e46ac21..e32192f 100644 --- a/Epub/KoeBook.Epub/Models/EpubDocument.cs +++ b/Epub/KoeBook.Epub/Models/EpubDocument.cs @@ -14,17 +14,17 @@ public class EpubDocument(string title, string author, string coverFilePath, Gui public Guid Id { get; } = id; public List CssClasses { get; set; } = [ - new CssClass("-epub-media-overlay-active", """ - .-epub-media-overlay-active *{ - background-color: yellow; - color: black !important; - } - """), + new CssClass("-epub-media-overlay-active", """ + .-epub-media-overlay-active *{ + background-color: yellow; + color: black !important; + } + """), new CssClass("-epub-media-overlay-unactive", """ - .-epub-media-overlay-unactive * { - color: gray; - } - """), + .-epub-media-overlay-unactive * { + color: gray; + } + """), ]; public List Chapters { get; set; } = []; @@ -54,163 +54,4 @@ internal void EnsureParagraph(int chapterIndex, int sectionIndex) if (Chapters[chapterIndex].Sections[sectionIndex].Elements.Count == 0) Chapters[chapterIndex].Sections[sectionIndex].Elements.Add(new Paragraph()); } - - public string CreateNavXhtml() - { - var builder = new StringBuilder($""" - - - - - {Title} - - - - - - """); - return builder.ToString(); - } - - public string CreateCssText() - { - var builder = new StringBuilder(); - foreach (var cssClass in CssClasses) - { - builder.AppendLine(cssClass.Text); - } - return builder.ToString(); - } - - public string CreateOpf() - { - var builder = new StringBuilder($""" - - - {Title} - {Author} - aut - urn:uuid:{Guid.NewGuid()} - ja - {DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ", CultureInfo.InvariantCulture)} - {DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ", CultureInfo.InvariantCulture)} - -epub-media-overlay-active - -epub-media-overlay-unactive - - """); - - var totalTime = TimeSpan.Zero; - for (var i = 0; i < Chapters.Count; i++) - { - for (var j = 0; j < Chapters[i].Sections.Count; j++) - { - var time = Chapters[i].Sections[j].GetTotalTime(); - totalTime += time; - builder.AppendLine($""" - {time} - """); - } - } - builder.AppendLine($""" - {totalTime} - - - - - - """); - - for (var i = 0; i < Chapters.Count; i++) - { - for (var j = 0; j < Chapters[i].Sections.Count; j++) - { - builder.AppendLine($""" - - - """); - for (var k = 0; k < Chapters[i].Sections[j].Elements.Count; k++) - { - var element = Chapters[i].Sections[j].Elements[k]; - if (element is Paragraph para && para.Audio != null) - { - builder.AppendLine(@$" "); - } - else if (element is Picture pic && File.Exists(pic.PictureFilePath)) - { - builder.AppendLine(@$" "); - } - } - } - } - - builder.AppendLine($""" - - - """); - - for (var i = 0; i < Chapters.Count; i++) - { - for (var j = 0; j < Chapters[i].Sections.Count; j++) - { - builder.AppendLine($""" - - """); - } - } - - builder.AppendLine($""" - - - """); - return builder.ToString(); - } - - public string CreateContainerXml() => """ - - - - - - - """; } diff --git a/Epub/KoeBook.Epub/Services/EpubCreateService.cs b/Epub/KoeBook.Epub/Services/EpubCreateService.cs index 4bfe3e0..02e4054 100644 --- a/Epub/KoeBook.Epub/Services/EpubCreateService.cs +++ b/Epub/KoeBook.Epub/Services/EpubCreateService.cs @@ -1,13 +1,13 @@ using KoeBook.Epub.Contracts.Services; using KoeBook.Epub.Models; -using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO.Compression; using System.Text; namespace KoeBook.Epub.Services; -public class EpubCreateService : IEpubCreateService +public class EpubCreateService(IFileExtensionService fileExtensionService) : IEpubCreateService { + private readonly IFileExtensionService _fileExtensionService = fileExtensionService; public async ValueTask TryCreateEpubAsync(EpubDocument epubDocument, string tmpDirectory, CancellationToken ct) { if (!File.Exists(epubDocument.CoverFilePath)) @@ -29,7 +29,7 @@ public async ValueTask TryCreateEpubAsync(EpubDocument epubDocument, strin var containerEntry = archive.CreateEntry("META-INF/container.xml"); using (var containerStream = new StreamWriter(containerEntry.Open())) { - await containerStream.WriteLineAsync(epubDocument.CreateContainerXml()).ConfigureAwait(false); + await containerStream.WriteLineAsync(CreateContainerXml()).ConfigureAwait(false); await containerStream.FlushAsync(ct).ConfigureAwait(false); } @@ -38,21 +38,21 @@ public async ValueTask TryCreateEpubAsync(EpubDocument epubDocument, strin var cssEntry = archive.CreateEntry("OEBPS/style.css"); using (var cssStream = new StreamWriter(cssEntry.Open())) { - await cssStream.WriteLineAsync(epubDocument.CreateCssText()).ConfigureAwait(false); + await cssStream.WriteLineAsync(CreateCssText(epubDocument)).ConfigureAwait(false); await cssStream.FlushAsync(ct).ConfigureAwait(false); } var navEntry = archive.CreateEntry("OEBPS/nav.xhtml"); using (var navStream = new StreamWriter(navEntry.Open())) { - await navStream.WriteLineAsync(epubDocument.CreateNavXhtml()).ConfigureAwait(false); + await navStream.WriteLineAsync(CreateNavXhtml(epubDocument)).ConfigureAwait(false); await navStream.FlushAsync(ct).ConfigureAwait(false); } var opfEntry = archive.CreateEntry("OEBPS/book.opf"); using (var opfStream = new StreamWriter(opfEntry.Open())) { - await opfStream.WriteLineAsync(epubDocument.CreateOpf()).ConfigureAwait(false); + await opfStream.WriteLineAsync(CreateOpf(epubDocument)).ConfigureAwait(false); await opfStream.FlushAsync(ct).ConfigureAwait(false); } @@ -101,4 +101,163 @@ public async ValueTask TryCreateEpubAsync(EpubDocument epubDocument, strin return false; } } + + internal static string CreateNavXhtml(EpubDocument epubDocument) + { + var builder = new StringBuilder($""" + + + + + {epubDocument.Title} + + + + + + """); + return builder.ToString(); + } + + internal static string CreateCssText(EpubDocument epubDocument) + { + var builder = new StringBuilder(); + foreach (var cssClass in epubDocument.CssClasses) + { + builder.AppendLine(cssClass.Text); + } + return builder.ToString(); + } + + internal string CreateOpf(EpubDocument epubDocument) + { + var builder = new StringBuilder($""" + + + {epubDocument.Title} + {epubDocument.Author} + aut + urn:uuid:{Guid.NewGuid()} + ja + {DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ", CultureInfo.InvariantCulture)} + {DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ", CultureInfo.InvariantCulture)} + -epub-media-overlay-active + -epub-media-overlay-unactive + + """); + + var totalTime = TimeSpan.Zero; + for (var i = 0; i < epubDocument.Chapters.Count; i++) + { + for (var j = 0; j < epubDocument.Chapters[i].Sections.Count; j++) + { + var time = epubDocument.Chapters[i].Sections[j].GetTotalTime(); + totalTime += time; + builder.AppendLine($""" + {time} + """); + } + } + builder.AppendLine($""" + {totalTime} + + + + + + """); + + for (var i = 0; i < epubDocument.Chapters.Count; i++) + { + for (var j = 0; j < epubDocument.Chapters[i].Sections.Count; j++) + { + builder.AppendLine($""" + + + """); + for (var k = 0; k < epubDocument.Chapters[i].Sections[j].Elements.Count; k++) + { + var element = epubDocument.Chapters[i].Sections[j].Elements[k]; + if (element is Paragraph para && para.Audio != null) + { + builder.AppendLine(@$" "); + } + else if (element is Picture pic && File.Exists(pic.PictureFilePath)) + { + builder.AppendLine(@$" "); + } + } + } + } + + builder.AppendLine($""" + + + """); + + for (var i = 0; i < epubDocument.Chapters.Count; i++) + { + for (var j = 0; j < epubDocument.Chapters[i].Sections.Count; j++) + { + builder.AppendLine($""" + + """); + } + } + + builder.AppendLine($""" + + + """); + return builder.ToString(); + } + + internal static string CreateContainerXml() => """ + + + + + + + """; } From b2816769a30d7fe01ee092f3260692e5f7cf84d3 Mon Sep 17 00:00:00 2001 From: aiueo-1234 <130837816+aiueo-1234@users.noreply.github.com> Date: Sun, 10 Mar 2024 18:17:36 +0900 Subject: [PATCH 4/7] =?UTF-8?q?=E3=82=BB=E3=82=AF=E3=82=B7=E3=83=A7?= =?UTF-8?q?=E3=83=B3=E9=83=A8=E5=88=86=E3=82=92=E4=BD=9C=E6=88=90=E3=81=99?= =?UTF-8?q?=E3=82=8B=E3=82=B3=E3=83=BC=E3=83=89=E3=82=92=E7=A7=BB=E5=8B=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Epub/KoeBook.Epub/Models/Section.cs | 67 ----------------- .../Services/EpubCreateService.cs | 71 ++++++++++++++++++- 2 files changed, 69 insertions(+), 69 deletions(-) diff --git a/Epub/KoeBook.Epub/Models/Section.cs b/Epub/KoeBook.Epub/Models/Section.cs index 81da7ec..bd283d9 100644 --- a/Epub/KoeBook.Epub/Models/Section.cs +++ b/Epub/KoeBook.Epub/Models/Section.cs @@ -8,73 +8,6 @@ public sealed class Section(string title) public string Title { get; set; } = title; public List Elements { get; set; } = []; - public string CreateSectionXhtml() - { - var builder = new StringBuilder($""" - - - - - {Title} - - - """); - - for (var i = 0; i < Elements.Count; i++) - { - if (Elements[i] is Paragraph para) - { - builder.AppendLine($""" -

- {para.Text} -

- """); - } - else if (Elements[i] is Picture pic && File.Exists(pic.PictureFilePath)) - { - builder.AppendLine($""" -

- - """); - } - } - - builder.AppendLine(""" - - - """); - return builder.ToString(); - } - - public string CreateSectionSmil() - { - var builder = new StringBuilder($""" - - - - """); - - for (var i = 0; i < Elements.Count; i++) - { - if (Elements[i] is Paragraph para && para.Audio != null) - { - builder.AppendLine($""" - - - - """); - } - } - - builder.AppendLine(""" - - - """); - return builder.ToString(); - } - public TimeSpan GetTotalTime() { var time = TimeSpan.Zero; diff --git a/Epub/KoeBook.Epub/Services/EpubCreateService.cs b/Epub/KoeBook.Epub/Services/EpubCreateService.cs index 02e4054..d47c018 100644 --- a/Epub/KoeBook.Epub/Services/EpubCreateService.cs +++ b/Epub/KoeBook.Epub/Services/EpubCreateService.cs @@ -63,13 +63,13 @@ public async ValueTask TryCreateEpubAsync(EpubDocument epubDocument, strin var sectionXhtmlEntry = archive.CreateEntry($"OEBPS/{epubDocument.Chapters[i].Sections[j].Id}.xhtml"); using (var sectionXhtmlStream = new StreamWriter(sectionXhtmlEntry.Open())) { - await sectionXhtmlStream.WriteLineAsync(epubDocument.Chapters[i].Sections[j].CreateSectionXhtml()).ConfigureAwait(false); + await sectionXhtmlStream.WriteLineAsync(CreateSectionXhtml(epubDocument.Chapters[i].Sections[j])).ConfigureAwait(false); await sectionXhtmlStream.FlushAsync(ct).ConfigureAwait(false); } var sectionSmilEntry = archive.CreateEntry($"OEBPS/{epubDocument.Chapters[i].Sections[j].Id}_audio.smil"); using (var sectionSmilStream = new StreamWriter(sectionSmilEntry.Open())) { - await sectionSmilStream.WriteLineAsync(epubDocument.Chapters[i].Sections[j].CreateSectionSmil()).ConfigureAwait(false); + await sectionSmilStream.WriteLineAsync(CreateSectionSmil(epubDocument.Chapters[i].Sections[j])).ConfigureAwait(false); await sectionSmilStream.FlushAsync(ct).ConfigureAwait(false); } for (var k = 0; k < epubDocument.Chapters[i].Sections[j].Elements.Count; k++) @@ -260,4 +260,71 @@ internal static string CreateContainerXml() => """ """; + + internal static string CreateSectionXhtml(Section section) + { + var builder = new StringBuilder($""" + + + + + {section.Title} + + + """); + + for (var i = 0; i < section.Elements.Count; i++) + { + if (section.Elements[i] is Paragraph para) + { + builder.AppendLine($""" +

+ {para.Text} +

+ """); + } + else if (section.Elements[i] is Picture pic && File.Exists(pic.PictureFilePath)) + { + builder.AppendLine($""" +

+ + """); + } + } + + builder.AppendLine(""" + + + """); + return builder.ToString(); + } + + internal static string CreateSectionSmil(Section section) + { + var builder = new StringBuilder($""" + + + + """); + + for (var i = 0; i < section.Elements.Count; i++) + { + if (section.Elements[i] is Paragraph para && para.Audio != null) + { + builder.AppendLine($""" + + + + """); + } + } + + builder.AppendLine(""" + + + """); + return builder.ToString(); + } } From 4a7ea0f7ae6b1bcff5404cb04e1c2e4153be835b Mon Sep 17 00:00:00 2001 From: aiueo-1234 <130837816+aiueo-1234@users.noreply.github.com> Date: Sun, 10 Mar 2024 18:27:14 +0900 Subject: [PATCH 5/7] =?UTF-8?q?StringBuilder=E3=81=AE=E4=B8=80=E6=9C=AC?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Services/EpubCreateService.cs | 75 ++++++++++--------- 1 file changed, 40 insertions(+), 35 deletions(-) diff --git a/Epub/KoeBook.Epub/Services/EpubCreateService.cs b/Epub/KoeBook.Epub/Services/EpubCreateService.cs index d47c018..53b5998 100644 --- a/Epub/KoeBook.Epub/Services/EpubCreateService.cs +++ b/Epub/KoeBook.Epub/Services/EpubCreateService.cs @@ -8,6 +8,8 @@ namespace KoeBook.Epub.Services; public class EpubCreateService(IFileExtensionService fileExtensionService) : IEpubCreateService { private readonly IFileExtensionService _fileExtensionService = fileExtensionService; + private readonly StringBuilder _builder = new(); + public async ValueTask TryCreateEpubAsync(EpubDocument epubDocument, string tmpDirectory, CancellationToken ct) { if (!File.Exists(epubDocument.CoverFilePath)) @@ -102,9 +104,10 @@ public async ValueTask TryCreateEpubAsync(EpubDocument epubDocument, strin } } - internal static string CreateNavXhtml(EpubDocument epubDocument) + internal string CreateNavXhtml(EpubDocument epubDocument) { - var builder = new StringBuilder($""" + _builder.Clear(); + _builder.AppendLine($""" @@ -114,13 +117,13 @@ internal static string CreateNavXhtml(EpubDocument epubDocument)

"""); - return builder.ToString(); + return _builder.ToString(); } - internal static string CreateCssText(EpubDocument epubDocument) + internal string CreateCssText(EpubDocument epubDocument) { - var builder = new StringBuilder(); + _builder.Clear(); foreach (var cssClass in epubDocument.CssClasses) { - builder.AppendLine(cssClass.Text); + _builder.AppendLine(cssClass.Text); } - return builder.ToString(); + return _builder.ToString(); } internal string CreateOpf(EpubDocument epubDocument) { - var builder = new StringBuilder($""" + _builder.Clear(); + _builder.AppendLine($""" {epubDocument.Title} @@ -183,7 +187,6 @@ internal string CreateOpf(EpubDocument epubDocument) {DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ", CultureInfo.InvariantCulture)} -epub-media-overlay-active -epub-media-overlay-unactive - """); var totalTime = TimeSpan.Zero; @@ -193,12 +196,12 @@ internal string CreateOpf(EpubDocument epubDocument) { var time = epubDocument.Chapters[i].Sections[j].GetTotalTime(); totalTime += time; - builder.AppendLine($""" + _builder.AppendLine($""" {time} """); } } - builder.AppendLine($""" + _builder.AppendLine($""" {totalTime} @@ -211,7 +214,7 @@ internal string CreateOpf(EpubDocument epubDocument) { for (var j = 0; j < epubDocument.Chapters[i].Sections.Count; j++) { - builder.AppendLine($""" + _builder.AppendLine($""" """); @@ -220,17 +223,17 @@ internal string CreateOpf(EpubDocument epubDocument) var element = epubDocument.Chapters[i].Sections[j].Elements[k]; if (element is Paragraph para && para.Audio != null) { - builder.AppendLine(@$" "); + _builder.AppendLine(@$" "); } else if (element is Picture pic && File.Exists(pic.PictureFilePath)) { - builder.AppendLine(@$" "); + _builder.AppendLine(@$" "); } } } } - builder.AppendLine($""" + _builder.AppendLine($""" """); @@ -239,17 +242,17 @@ internal string CreateOpf(EpubDocument epubDocument) { for (var j = 0; j < epubDocument.Chapters[i].Sections.Count; j++) { - builder.AppendLine($""" + _builder.AppendLine($""" """); } } - builder.AppendLine($""" + _builder.AppendLine($""" """); - return builder.ToString(); + return _builder.ToString(); } internal static string CreateContainerXml() => """ @@ -261,9 +264,10 @@ internal static string CreateContainerXml() => """ """; - internal static string CreateSectionXhtml(Section section) + internal string CreateSectionXhtml(Section section) { - var builder = new StringBuilder($""" + _builder.Clear(); + _builder.AppendLine($""" @@ -277,7 +281,7 @@ internal static string CreateSectionXhtml(Section section) { if (section.Elements[i] is Paragraph para) { - builder.AppendLine($""" + _builder.AppendLine($"""

{para.Text}

@@ -285,7 +289,7 @@ internal static string CreateSectionXhtml(Section section) } else if (section.Elements[i] is Picture pic && File.Exists(pic.PictureFilePath)) { - builder.AppendLine($""" + _builder.AppendLine($"""

@@ -293,16 +297,17 @@ internal static string CreateSectionXhtml(Section section) } } - builder.AppendLine(""" + _builder.AppendLine(""" """); - return builder.ToString(); + return _builder.ToString(); } - internal static string CreateSectionSmil(Section section) + internal string CreateSectionSmil(Section section) { - var builder = new StringBuilder($""" + _builder.Clear(); + _builder.AppendLine($""" @@ -312,7 +317,7 @@ internal static string CreateSectionSmil(Section section) { if (section.Elements[i] is Paragraph para && para.Audio != null) { - builder.AppendLine($""" + _builder.AppendLine($""" """); - return builder.ToString(); + return _builder.ToString(); } } From 409d868fc7ed96bc60bae16c0f0e454cce5b1a20 Mon Sep 17 00:00:00 2001 From: aiueo-1234 <130837816+aiueo-1234@users.noreply.github.com> Date: Sun, 10 Mar 2024 19:36:19 +0900 Subject: [PATCH 6/7] =?UTF-8?q?CreateContainerXml=E3=81=AE=E5=A4=89?= =?UTF-8?q?=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Services/EpubCreateService.cs | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Epub/KoeBook.Epub/Services/EpubCreateService.cs b/Epub/KoeBook.Epub/Services/EpubCreateService.cs index 53b5998..f96cac2 100644 --- a/Epub/KoeBook.Epub/Services/EpubCreateService.cs +++ b/Epub/KoeBook.Epub/Services/EpubCreateService.cs @@ -10,6 +10,15 @@ public class EpubCreateService(IFileExtensionService fileExtensionService) : IEp private readonly IFileExtensionService _fileExtensionService = fileExtensionService; private readonly StringBuilder _builder = new(); + internal const string ContainerXml = """ + + + + + + + """; + public async ValueTask TryCreateEpubAsync(EpubDocument epubDocument, string tmpDirectory, CancellationToken ct) { if (!File.Exists(epubDocument.CoverFilePath)) @@ -31,7 +40,7 @@ public async ValueTask TryCreateEpubAsync(EpubDocument epubDocument, strin var containerEntry = archive.CreateEntry("META-INF/container.xml"); using (var containerStream = new StreamWriter(containerEntry.Open())) { - await containerStream.WriteLineAsync(CreateContainerXml()).ConfigureAwait(false); + await containerStream.WriteLineAsync(ContainerXml).ConfigureAwait(false); await containerStream.FlushAsync(ct).ConfigureAwait(false); } @@ -255,15 +264,6 @@ internal string CreateOpf(EpubDocument epubDocument) return _builder.ToString(); } - internal static string CreateContainerXml() => """ - - - - - - - """; - internal string CreateSectionXhtml(Section section) { _builder.Clear(); From abd0a66946325b78878d64044f0bb0f1e582986d Mon Sep 17 00:00:00 2001 From: aiueo-1234 <130837816+aiueo-1234@users.noreply.github.com> Date: Sun, 10 Mar 2024 19:52:27 +0900 Subject: [PATCH 7/7] =?UTF-8?q?revert=20StringBuilder=E3=81=AE=E4=B8=80?= =?UTF-8?q?=E6=9C=AC=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Services/EpubCreateService.cs | 75 +++++++++---------- 1 file changed, 36 insertions(+), 39 deletions(-) diff --git a/Epub/KoeBook.Epub/Services/EpubCreateService.cs b/Epub/KoeBook.Epub/Services/EpubCreateService.cs index f96cac2..b34d590 100644 --- a/Epub/KoeBook.Epub/Services/EpubCreateService.cs +++ b/Epub/KoeBook.Epub/Services/EpubCreateService.cs @@ -8,7 +8,6 @@ namespace KoeBook.Epub.Services; public class EpubCreateService(IFileExtensionService fileExtensionService) : IEpubCreateService { private readonly IFileExtensionService _fileExtensionService = fileExtensionService; - private readonly StringBuilder _builder = new(); internal const string ContainerXml = """ @@ -113,10 +112,9 @@ public async ValueTask TryCreateEpubAsync(EpubDocument epubDocument, strin } } - internal string CreateNavXhtml(EpubDocument epubDocument) + internal static string CreateNavXhtml(EpubDocument epubDocument) { - _builder.Clear(); - _builder.AppendLine($""" + var builder = new StringBuilder($""" @@ -126,13 +124,13 @@ internal string CreateNavXhtml(EpubDocument epubDocument)

"""); - return _builder.ToString(); + return builder.ToString(); } - internal string CreateCssText(EpubDocument epubDocument) + internal static string CreateCssText(EpubDocument epubDocument) { - _builder.Clear(); + var builder = new StringBuilder(); foreach (var cssClass in epubDocument.CssClasses) { - _builder.AppendLine(cssClass.Text); + builder.AppendLine(cssClass.Text); } - return _builder.ToString(); + return builder.ToString(); } internal string CreateOpf(EpubDocument epubDocument) { - _builder.Clear(); - _builder.AppendLine($""" + var builder = new StringBuilder($""" {epubDocument.Title} @@ -196,6 +193,7 @@ internal string CreateOpf(EpubDocument epubDocument) {DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ", CultureInfo.InvariantCulture)} -epub-media-overlay-active -epub-media-overlay-unactive + """); var totalTime = TimeSpan.Zero; @@ -205,12 +203,12 @@ internal string CreateOpf(EpubDocument epubDocument) { var time = epubDocument.Chapters[i].Sections[j].GetTotalTime(); totalTime += time; - _builder.AppendLine($""" + builder.AppendLine($""" {time} """); } } - _builder.AppendLine($""" + builder.AppendLine($""" {totalTime} @@ -223,7 +221,7 @@ internal string CreateOpf(EpubDocument epubDocument) { for (var j = 0; j < epubDocument.Chapters[i].Sections.Count; j++) { - _builder.AppendLine($""" + builder.AppendLine($""" """); @@ -232,17 +230,17 @@ internal string CreateOpf(EpubDocument epubDocument) var element = epubDocument.Chapters[i].Sections[j].Elements[k]; if (element is Paragraph para && para.Audio != null) { - _builder.AppendLine(@$" "); + builder.AppendLine(@$" "); } else if (element is Picture pic && File.Exists(pic.PictureFilePath)) { - _builder.AppendLine(@$" "); + builder.AppendLine(@$" "); } } } } - _builder.AppendLine($""" + builder.AppendLine($""" """); @@ -251,23 +249,23 @@ internal string CreateOpf(EpubDocument epubDocument) { for (var j = 0; j < epubDocument.Chapters[i].Sections.Count; j++) { - _builder.AppendLine($""" + builder.AppendLine($""" """); } } - _builder.AppendLine($""" + builder.AppendLine($""" """); - return _builder.ToString(); + return builder.ToString(); } - internal string CreateSectionXhtml(Section section) + + internal static string CreateSectionXhtml(Section section) { - _builder.Clear(); - _builder.AppendLine($""" + var builder = new StringBuilder($""" @@ -281,7 +279,7 @@ internal string CreateSectionXhtml(Section section) { if (section.Elements[i] is Paragraph para) { - _builder.AppendLine($""" + builder.AppendLine($"""

{para.Text}

@@ -289,7 +287,7 @@ internal string CreateSectionXhtml(Section section) } else if (section.Elements[i] is Picture pic && File.Exists(pic.PictureFilePath)) { - _builder.AppendLine($""" + builder.AppendLine($"""

@@ -297,17 +295,16 @@ internal string CreateSectionXhtml(Section section) } } - _builder.AppendLine(""" + builder.AppendLine(""" """); - return _builder.ToString(); + return builder.ToString(); } - internal string CreateSectionSmil(Section section) + internal static string CreateSectionSmil(Section section) { - _builder.Clear(); - _builder.AppendLine($""" + var builder = new StringBuilder($""" @@ -317,7 +314,7 @@ internal string CreateSectionSmil(Section section) { if (section.Elements[i] is Paragraph para && para.Audio != null) { - _builder.AppendLine($""" + builder.AppendLine($""" """); - return _builder.ToString(); + return builder.ToString(); } }