.NET 7 + Spring Cleaning (#1677)

* Updated to net7.0

* Updated GA to .net 7

* Updated System.IO.Abstractions to use New factory.

* Converted Regex into SourceGenerator in Parser.

* Updated more regex to source generators.

* Enabled Nullability and more regex changes throughout codebase.

* Parser is 100% GeneratedRegexified

* Lots of nullability code

* Enabled nullability for all repositories.

* Fixed another unit test

* Refactored some code around and took care of some todos.

* Updating code for nullability and cleaning up methods that aren't used anymore. Refctored all uses of Parser.Normalize() to use new extension

* More nullability exercises. 500 warnings to go.

* Fixed a bug where custom file uploads for entities wouldn't save in webP.

* Nullability is done for all DTOs

* Fixed all unit tests and nullability for the project. Only OPDS is left which will be done with an upcoming OPDS enhancement.

* Use localization in book service after validating

* Code smells

* Switched to preview build of swashbuckle for .net7 support

* Fixed up merge issues

* Disable emulate comic book when on single page reader

* Fixed a regression where double page renderer wouldn't layout the images correctly

* Updated to swashbuckle which support .net 7

* Fixed a bad GA action

* Some code cleanup

* More code smells

* Took care of most of nullable issues

* Fixed a broken test due to having more than one test run in parallel

* I'm really not sure why the unit tests are failing or are so extremely slow on .net 7

* Updated all dependencies

* Fixed up build and removed hardcoded framework from build scripts. (this merge removes Regex Source generators). Unit tests are completely busted.

* Unit tests and code cleanup. Needs shakeout now.

* Adjusted Series model since a few fields are not-nullable. Removed dead imports on the project.

* Refactored to use Builder pattern for all unit tests.

* Switched nullability down to warnings. It wasn't possible to switch due to constraint issues in DB Migration.
This commit is contained in:
Joe Milazzo 2023-03-05 14:55:13 -06:00 committed by GitHub
parent 76fe3fd64a
commit 5d1dd7b3f0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
283 changed files with 4221 additions and 4593 deletions

View file

@ -33,8 +33,17 @@ public interface IBookService
{
int GetNumberOfPages(string filePath);
string GetCoverImage(string fileFilePath, string fileName, string outputDirectory, bool saveAsWebP = false);
ComicInfo GetComicInfo(string filePath);
ParserInfo ParseInfo(string filePath);
ComicInfo? GetComicInfo(string filePath);
ParserInfo? ParseInfo(string filePath);
/// <summary>
/// Scopes styles to .reading-section and replaces img src to the passed apiBase
/// </summary>
/// <param name="stylesheetHtml"></param>
/// <param name="apiBase"></param>
/// <param name="filename">If the stylesheetHtml contains Import statements, when scoping the filename, scope needs to be wrt filepath.</param>
/// <param name="book">Book Reference, needed for if you expect Import statements</param>
/// <returns></returns>
Task<string> ScopeStyles(string stylesheetHtml, string apiBase, string filename, EpubBookRef book);
/// <summary>
/// Extracts a PDF file's pages as images to an target directory
/// </summary>
@ -64,6 +73,27 @@ public class BookService : IBookService
}
};
// Use when Rosyln fixed
// [GeneratedRegex(@"/\*[\d\D]*?\*/", RegexOptions.Compiled)]
// private static partial Regex CssComment();
//
// [GeneratedRegex(@"[a-zA-Z]+#", RegexOptions.Compiled)]
// private static partial Regex WhiteSpace1();
// [GeneratedRegex(@"[\n\r]+\s*", RegexOptions.Compiled)]
// private static partial Regex WhiteSpace2();
// [GeneratedRegex(@"\s+", RegexOptions.Compiled)]
// private static partial Regex WhiteSpace3();
// [GeneratedRegex(@"\s?([:,;{}])\s?", RegexOptions.Compiled)]
// private static partial Regex WhiteSpace4();
// [GeneratedRegex(@"([\s:]0)(px|pt|%|em)", RegexOptions.Compiled)]
// private static partial Regex UnitPadding();
//
// [GeneratedRegex(@"<script(.*)(/>)", RegexOptions.Compiled)]
// private static partial Regex StartingScriptTag();
// [GeneratedRegex(@"<title(.*)(/>)", RegexOptions.Compiled)]
// private static partial Regex StartingTitleTag();
public BookService(ILogger<BookService> logger, IDirectoryService directoryService, IImageService imageService)
{
_logger = logger;
@ -163,6 +193,7 @@ public class BookService : IBookService
// @Import statements will be handled by browser, so we must inline the css into the original file that request it, so they can be Scoped
var prepend = filename.Length > 0 ? filename.Replace(Path.GetFileName(filename), string.Empty) : string.Empty;
var importBuilder = new StringBuilder();
//foreach (Match match in Tasks.Scanner.Parser.Parser.CssImportUrlRegex().Matches(stylesheetHtml))
foreach (Match match in Tasks.Scanner.Parser.Parser.CssImportUrlRegex.Matches(stylesheetHtml))
{
if (!match.Success) continue;
@ -200,7 +231,7 @@ public class BookService : IBookService
foreach (var styleRule in stylesheet.StyleRules)
{
if (styleRule.Selector.Text == CssScopeClass) continue;
if (styleRule.Selector.Text.Contains(","))
if (styleRule.Selector.Text.Contains(','))
{
styleRule.Text = styleRule.Text.Replace(styleRule.SelectorText,
string.Join(", ",
@ -214,6 +245,7 @@ public class BookService : IBookService
private static void EscapeCssImportReferences(ref string stylesheetHtml, string apiBase, string prepend)
{
//foreach (Match match in Tasks.Scanner.Parser.Parser.CssImportUrlRegex().Matches(stylesheetHtml))
foreach (Match match in Tasks.Scanner.Parser.Parser.CssImportUrlRegex.Matches(stylesheetHtml))
{
if (!match.Success) continue;
@ -224,6 +256,7 @@ public class BookService : IBookService
private static void EscapeFontFamilyReferences(ref string stylesheetHtml, string apiBase, string prepend)
{
//foreach (Match match in Tasks.Scanner.Parser.Parser.FontSrcUrlRegex().Matches(stylesheetHtml))
foreach (Match match in Tasks.Scanner.Parser.Parser.FontSrcUrlRegex.Matches(stylesheetHtml))
{
if (!match.Success) continue;
@ -234,6 +267,7 @@ public class BookService : IBookService
private static void EscapeCssImageReferences(ref string stylesheetHtml, string apiBase, EpubBookRef book)
{
//var matches = Tasks.Scanner.Parser.Parser.CssImageUrlRegex().Matches(stylesheetHtml);
var matches = Tasks.Scanner.Parser.Parser.CssImageUrlRegex.Matches(stylesheetHtml);
foreach (Match match in matches)
{
@ -260,7 +294,7 @@ public class BookService : IBookService
foreach (var image in images)
{
string key = null;
string? key = null;
if (image.Attributes["src"] != null)
{
key = "src";
@ -388,7 +422,7 @@ public class BookService : IBookService
}
}
public ComicInfo GetComicInfo(string filePath)
public ComicInfo? GetComicInfo(string filePath)
{
if (!IsValidFile(filePath) || Tasks.Scanner.Parser.Parser.IsPdf(filePath)) return null;
@ -474,7 +508,7 @@ public class BookService : IBookService
return null;
}
private static (int year, int month, int day) GetPublicationDate(string publicationDate)
{
var dateParsed = DateTime.TryParse(publicationDate, out var date);
@ -496,23 +530,19 @@ public class BookService : IBookService
return (year, month, day);
}
#nullable enable
private static string ValidateLanguage(string? language)
{
if (string.IsNullOrEmpty(language)) return string.Empty;
try
{
CultureInfo.GetCultureInfo(language);
return CultureInfo.GetCultureInfo(language).ToString();
}
catch (Exception)
{
return string.Empty;
}
return language;
}
#nullable disable
private bool IsValidFile(string filePath)
{
@ -553,6 +583,8 @@ public class BookService : IBookService
private static string EscapeTags(string content)
{
// content = StartingScriptTag().Replace(content, "<script$1></script>");
// content = StartingTitleTag().Replace(content, "<title$1></title>");
content = Regex.Replace(content, @"<script(.*)(/>)", "<script$1></script>", RegexOptions.None, Tasks.Scanner.Parser.Parser.RegexTimeout);
content = Regex.Replace(content, @"<title(.*)(/>)", "<title$1></title>", RegexOptions.None, Tasks.Scanner.Parser.Parser.RegexTimeout);
return content;
@ -588,7 +620,7 @@ public class BookService : IBookService
/// </summary>
/// <param name="filePath"></param>
/// <returns></returns>
public ParserInfo ParseInfo(string filePath)
public ParserInfo? ParseInfo(string filePath)
{
if (!Tasks.Scanner.Parser.Parser.IsEpub(filePath)) return null;
@ -656,7 +688,7 @@ public class BookService : IBookService
Edition = string.Empty,
Format = MangaFormat.Epub,
Filename = Path.GetFileName(filePath),
Title = specialName?.Trim(),
Title = specialName?.Trim() ?? string.Empty,
FullFilePath = filePath,
IsSpecial = false,
Series = series.Trim(),
@ -1037,6 +1069,12 @@ public class BookService : IBookService
}
// Remove comments from CSS
// body = CssComment().Replace(body, string.Empty);
//
// body = WhiteSpace1().Replace(body, "#");
// body = WhiteSpace2().Replace(body, string.Empty);
// body = WhiteSpace3().Replace(body, " ");
// body = WhiteSpace4().Replace(body, "$1");
body = Regex.Replace(body, @"/\*[\d\D]*?\*/", string.Empty, RegexOptions.None, Tasks.Scanner.Parser.Parser.RegexTimeout);
body = Regex.Replace(body, @"[a-zA-Z]+#", "#", RegexOptions.None, Tasks.Scanner.Parser.Parser.RegexTimeout);
@ -1052,6 +1090,7 @@ public class BookService : IBookService
//Swallow exception. Some css don't have style rules ending in ';'
}
//body = UnitPadding().Replace(body, "$1");
body = Regex.Replace(body, @"([\s:]0)(px|pt|%|em)", "$1", RegexOptions.None, Tasks.Scanner.Parser.Parser.RegexTimeout);