From 8e3121447d7a72ab5467276983f8618074a04bcf Mon Sep 17 00:00:00 2001 From: Joseph Milazzo Date: Tue, 19 Oct 2021 06:12:49 -0700 Subject: [PATCH] More EPUB Scoping Fixes (#691) * Added better handling around when importing css files that are empty. Moved comment removal on css files to before some css whitespace cleanup to get better matches. * Some enhancements on the checks to see if we need the bottom action bar on reader. Now we don't query DOM and have something that works more reliably. --- API/Controllers/BookController.cs | 5 ++++- API/Services/BookService.cs | 22 ++++++++++++++++--- .../book-reader/book-reader.component.ts | 10 +-------- 3 files changed, 24 insertions(+), 13 deletions(-) diff --git a/API/Controllers/BookController.cs b/API/Controllers/BookController.cs index 448d45c02..cf5e66e22 100644 --- a/API/Controllers/BookController.cs +++ b/API/Controllers/BookController.cs @@ -259,7 +259,10 @@ namespace API.Controllers } var styleContent = await _bookService.ScopeStyles(await book.Content.Css[key].ReadContentAsync(), apiBase, book.Content.Css[key].FileName, book); - body.PrependChild(HtmlNode.CreateNode($"")); + if (styleContent != null) + { + body.PrependChild(HtmlNode.CreateNode($"")); + } } } diff --git a/API/Services/BookService.cs b/API/Services/BookService.cs index 4449b6834..71f633e4c 100644 --- a/API/Services/BookService.cs +++ b/API/Services/BookService.cs @@ -154,6 +154,8 @@ namespace API.Services var styleContent = RemoveWhiteSpaceFromStylesheets(stylesheetHtml); styleContent = styleContent.Replace("body", ".reading-section"); + if (string.IsNullOrEmpty(styleContent)) return string.Empty; + var stylesheet = await _cssParser.ParseAsync(styleContent); foreach (var styleRule in stylesheet.StyleRules) { @@ -508,15 +510,29 @@ namespace API.Services private static string RemoveWhiteSpaceFromStylesheets(string body) { + if (string.IsNullOrEmpty(body)) + { + return string.Empty; + } + + // Remove comments from CSS + body = Regex.Replace(body, @"/\*[\d\D]*?\*/", string.Empty); + body = Regex.Replace(body, @"[a-zA-Z]+#", "#"); body = Regex.Replace(body, @"[\n\r]+\s*", string.Empty); body = Regex.Replace(body, @"\s+", " "); body = Regex.Replace(body, @"\s?([:,;{}])\s?", "$1"); - body = body.Replace(";}", "}"); + try + { + body = body.Replace(";}", "}"); + } + catch (Exception) + { + /* Swallow exception. Some css doesn't have style rules ending in ; */ + } + body = Regex.Replace(body, @"([\s:]0)(px|pt|%|em)", "$1"); - // Remove comments from CSS - body = Regex.Replace(body, @"/\*[\d\D]*?\*/", string.Empty); return body; } diff --git a/UI/Web/src/app/book-reader/book-reader/book-reader.component.ts b/UI/Web/src/app/book-reader/book-reader/book-reader.component.ts index 0eee0bfb0..514ea6a01 100644 --- a/UI/Web/src/app/book-reader/book-reader/book-reader.component.ts +++ b/UI/Web/src/app/book-reader/book-reader/book-reader.component.ts @@ -717,15 +717,7 @@ export class BookReaderComponent implements OnInit, AfterViewInit, OnDestroy { setupPage(part?: string | undefined, scrollTop?: number | undefined) { this.isLoading = false; - this.scrollbarNeeded = this.readingSectionElemRef.nativeElement.scrollHeight > this.readingSectionElemRef.nativeElement.clientHeight; - - const itemsOnScreen = Array.from(this.readingHtml.nativeElement.querySelectorAll('*')).filter(elem => (elem as HTMLElement).nodeName != 'STYLE'); - const itemsWithAbsolutePositioning = itemsOnScreen.filter(elem => (elem as HTMLElement).style.getPropertyValue('position') === 'absolute').length; - - if (itemsWithAbsolutePositioning >= itemsOnScreen.length) { - // Supress bottom actionbar. This is because of how the html is structured, with abs positioning, it will render inside images, etc. - this.scrollbarNeeded = false; - } + this.scrollbarNeeded = this.readingHtml.nativeElement.clientHeight > this.readingSectionElemRef.nativeElement.clientHeight; // Find all the part ids and their top offset this.setupPageAnchors();