Epub Table of Generation fixes for Sigil (#1689)

* Fixed generating table of contents where key lookup could fail with how Sigil packs the epubs.

* Tweaked Kavita's fallback ToC generation (when one doesn't exist in the epub) to also use CoalesceKey.

* Code smells
This commit is contained in:
Joe Milazzo 2022-12-11 07:04:22 -06:00 committed by GitHub
parent fcd9f8f118
commit ebbaf2d060
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 27 additions and 71 deletions

View File

@ -213,12 +213,6 @@ public class SettingsController : BaseApiController
}
}
if (setting.Key == ServerSettingKey.EnableSwaggerUi && updateSettingsDto.EnableSwaggerUi + string.Empty != setting.Value)
{
setting.Value = updateSettingsDto.EnableSwaggerUi + string.Empty;
_unitOfWork.SettingsRepository.Update(setting);
}
if (setting.Key == ServerSettingKey.TotalBackups && updateSettingsDto.TotalBackups + string.Empty != setting.Value)
{
if (updateSettingsDto.TotalBackups > 30 || updateSettingsDto.TotalBackups < 1)

View File

@ -49,11 +49,6 @@ public class ServerSettingDto
/// </summary>
public bool ConvertBookmarkToWebP { get; set; }
/// <summary>
/// If the Swagger UI Should be exposed. Does not require authentication, but does require a JWT.
/// </summary>
[Obsolete("Being removed in v0.7 in favor of dedicated hosted api")]
public bool EnableSwaggerUi { get; set; }
/// <summary>
/// The amount of Backups before cleanup
/// </summary>
/// <remarks>Value should be between 1 and 30</remarks>

View File

@ -98,7 +98,6 @@ public static class Seed
new() {Key = ServerSettingKey.BookmarkDirectory, Value = directoryService.BookmarkDirectory},
new() {Key = ServerSettingKey.EmailServiceUrl, Value = EmailService.DefaultApiUrl},
new() {Key = ServerSettingKey.ConvertBookmarkToWebP, Value = "false"},
new() {Key = ServerSettingKey.EnableSwaggerUi, Value = "false"},
new() {Key = ServerSettingKey.TotalBackups, Value = "30"},
new() {Key = ServerSettingKey.TotalLogs, Value = "30"},
new() {Key = ServerSettingKey.EnableFolderWatching, Value = "false"},

View File

@ -3,6 +3,9 @@ using System.ComponentModel;
namespace API.Entities.Enums;
/// <summary>
/// 15 is blocked as it was EnableSwaggerUi, which is no longer used
/// </summary>
public enum ServerSettingKey
{
/// <summary>
@ -83,12 +86,6 @@ public enum ServerSettingKey
[Description("ConvertBookmarkToWebP")]
ConvertBookmarkToWebP = 14,
/// <summary>
/// If the Swagger UI Should be exposed. Does not require authentication, but does require a JWT.
/// </summary>
[Description("EnableSwaggerUi")]
[Obsolete("Being removed in v0.7 in favor of dedicated hosted api")]
EnableSwaggerUi = 15,
/// <summary>
/// Total Number of Backups to maintain before cleaning. Default 30, min 1.
/// </summary>
[Description("TotalBackups")]

View File

@ -145,7 +145,6 @@ public class AutoMapperProfiles : Profile
CreateMap<ReadingList, ReadingListDto>();
CreateMap<ReadingListItem, ReadingListItemDto>();
//.AfterMap((src, dest) => dest.Title = ReadingListHelper.FormatTitle(dest));
CreateMap<Series, SearchResultDto>()
.ForMember(dest => dest.SeriesId,

View File

@ -54,9 +54,6 @@ public class ServerSettingConverter : ITypeConverter<IEnumerable<ServerSetting>,
case ServerSettingKey.ConvertCoverToWebP:
destination.ConvertCoverToWebP = bool.Parse(row.Value);
break;
case ServerSettingKey.EnableSwaggerUi:
destination.EnableSwaggerUi = bool.Parse(row.Value);
break;
case ServerSettingKey.TotalBackups:
destination.TotalBackups = int.Parse(row.Value);
break;

View File

@ -717,6 +717,20 @@ public class BookService : IBookService
return PrepareFinalHtml(doc, body);
}
private static string CoalesceKey(EpubBookRef book, IDictionary<string, int> mappings, string key)
{
if (mappings.ContainsKey(CleanContentKeys(key))) return key;
// Fallback to searching for key (bad epub metadata)
var correctedKey = book.Content.Html.Keys.SingleOrDefault(s => s.EndsWith(key));
if (!string.IsNullOrEmpty(correctedKey))
{
key = correctedKey;
}
return key;
}
/// <summary>
/// This will return a list of mappings from ID -> page num. ID will be the xhtml key and page num will be the reading order
/// this is used to rewrite anchors in the book text so that we always load properly in our reader.
@ -743,7 +757,7 @@ public class BookService : IBookService
foreach (var nestedChapter in navigationItem.NestedItems.Where(n => n.Link != null))
{
var key = BookService.CleanContentKeys(nestedChapter.Link.ContentFileName);
var key = CoalesceKey(book, mappings, nestedChapter.Link.ContentFileName);
if (mappings.ContainsKey(key))
{
nestedChapters.Add(new BookChapterItem()
@ -760,7 +774,7 @@ public class BookService : IBookService
}
if (chaptersList.Count != 0) return chaptersList;
// Generate from TOC
// Generate from TOC from links (any point past this, Kavita is generating as a TOC doesn't exist)
var tocPage = book.Content.Html.Keys.FirstOrDefault(k => k.ToUpper().Contains("TOC"));
if (tocPage == null) return chaptersList;
@ -775,16 +789,7 @@ public class BookService : IBookService
{
if (!anchor.Attributes.Contains("href")) continue;
var key = BookService.CleanContentKeys(anchor.Attributes["href"].Value).Split("#")[0];
if (!mappings.ContainsKey(key))
{
// Fallback to searching for key (bad epub metadata)
var correctedKey = book.Content.Html.Keys.SingleOrDefault(s => s.EndsWith(key));
if (!string.IsNullOrEmpty(correctedKey))
{
key = correctedKey;
}
}
var key = CoalesceKey(book, mappings, anchor.Attributes["href"].Value.Split("#")[0]);
if (string.IsNullOrEmpty(key) || !mappings.ContainsKey(key)) continue;
var part = string.Empty;

View File

@ -90,12 +90,6 @@ public class CacheService : ICacheService
return path;
}
/// <summary>
/// Caches the files for the given chapter to CacheDirectory
/// </summary>
/// <param name="chapterId"></param>
/// <returns>This will always return the Chapter for the chapterId</returns>
public async Task<Chapter> Ensure(int chapterId, bool extractPdfToImages = false)
{
_directoryService.ExistOrCreate(_directoryService.CacheDirectory);

View File

@ -246,21 +246,14 @@ public class Startup
app.UseMiddleware<ExceptionMiddleware>();
Task.Run(async () =>
if (env.IsDevelopment())
{
var allowSwaggerUi = (await unitOfWork.SettingsRepository.GetSettingsDtoAsync())
.EnableSwaggerUi;
if (env.IsDevelopment() || allowSwaggerUi)
app.UseSwagger();
app.UseSwaggerUI(c =>
{
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "Kavita API " + BuildInfo.Version);
});
}
});
c.SwaggerEndpoint("/swagger/v1/swagger.json", "Kavita API " + BuildInfo.Version);
});
}
if (env.IsDevelopment())
{

View File

@ -11,7 +11,6 @@ export interface ServerSettings {
emailServiceUrl: string;
convertBookmarkToWebP: boolean;
convertCoverToWebP: boolean;
enableSwaggerUi: boolean;
totalBackups: number;
totalLogs: number;
enableFolderWatching: boolean;

View File

@ -88,15 +88,6 @@
</div>
</div>
<div class="mb-3">
<label for="swagger-ui" class="form-label" aria-describedby="swaggerui-info">Expose Swagger UI</label>
<p class="accent" id="swaggerui-info">Allows Swagger UI to be exposed via swagger/ on your server. Authentication is not required, but a valid JWT token is. Requires a restart to take effect. Swagger is hosted on yourip:5000/swagger</p>
<div class="form-check form-switch">
<input id="swagger-ui" type="checkbox" class="form-check-input" formControlName="enableSwaggerUi" role="switch">
<label for="swagger-ui" class="form-check-label">Enable Swagger UI</label>
</div>
</div>
<!-- TODO: Move this to Plugins tab once we build out some basic tables -->
<div class="mb-3">
<label for="opds" aria-describedby="opds-info" class="form-label">OPDS</label>

View File

@ -47,7 +47,6 @@ export class ManageSettingsComponent implements OnInit {
this.settingsForm.addControl('enableOpds', new FormControl(this.serverSettings.enableOpds, [Validators.required]));
this.settingsForm.addControl('baseUrl', new FormControl(this.serverSettings.baseUrl, [Validators.required]));
this.settingsForm.addControl('emailServiceUrl', new FormControl(this.serverSettings.emailServiceUrl, [Validators.required]));
this.settingsForm.addControl('enableSwaggerUi', new FormControl(this.serverSettings.enableSwaggerUi, [Validators.required]));
this.settingsForm.addControl('totalBackups', new FormControl(this.serverSettings.totalBackups, [Validators.required, Validators.min(1), Validators.max(30)]));
this.settingsForm.addControl('totalLogs', new FormControl(this.serverSettings.totalLogs, [Validators.required, Validators.min(1), Validators.max(30)]));
this.settingsForm.addControl('enableFolderWatching', new FormControl(this.serverSettings.enableFolderWatching, [Validators.required]));
@ -66,7 +65,6 @@ export class ManageSettingsComponent implements OnInit {
this.settingsForm.get('enableOpds')?.setValue(this.serverSettings.enableOpds);
this.settingsForm.get('baseUrl')?.setValue(this.serverSettings.baseUrl);
this.settingsForm.get('emailServiceUrl')?.setValue(this.serverSettings.emailServiceUrl);
this.settingsForm.get('enableSwaggerUi')?.setValue(this.serverSettings.enableSwaggerUi);
this.settingsForm.get('totalBackups')?.setValue(this.serverSettings.totalBackups);
this.settingsForm.get('totalLogs')?.setValue(this.serverSettings.totalLogs);
this.settingsForm.get('enableFolderWatching')?.setValue(this.serverSettings.enableFolderWatching);

View File

@ -7,7 +7,7 @@
"name": "GPL-3.0",
"url": "https://github.com/Kareadita/Kavita/blob/develop/LICENSE"
},
"version": "0.6.1.8"
"version": "0.6.1.9"
},
"servers": [
{
@ -12843,11 +12843,6 @@
"type": "boolean",
"description": "If the server should save bookmarks as WebP encoding"
},
"enableSwaggerUi": {
"type": "boolean",
"description": "If the Swagger UI Should be exposed. Does not require authentication, but does require a JWT.",
"deprecated": true
},
"totalBackups": {
"type": "integer",
"description": "The amount of Backups before cleanup",