mirror of
https://github.com/Ranchero-Software/NetNewsWire
synced 2025-08-12 06:26:36 +00:00
Make stylesheet external to page.html
This commit is contained in:
@@ -161,6 +161,7 @@ extension DetailWebViewController: WKNavigationDelegate {
|
||||
if waitingForFirstReload {
|
||||
assert(webView.isHidden)
|
||||
waitingForFirstReload = false
|
||||
reloadHTML()
|
||||
|
||||
// Waiting for the first navigation to complete isn't long enough to avoid the flash of white.
|
||||
// A hard coded value is awful, but 5/100th of a second seems to be enough.
|
||||
@@ -173,6 +174,7 @@ extension DetailWebViewController: WKNavigationDelegate {
|
||||
|
||||
// MARK: - Private
|
||||
struct TemplateData: Codable {
|
||||
let style: String
|
||||
let body: String
|
||||
}
|
||||
|
||||
@@ -180,20 +182,20 @@ private extension DetailWebViewController {
|
||||
|
||||
func reloadHTML() {
|
||||
let style = ArticleStylesManager.shared.currentStyle
|
||||
let html: String
|
||||
let rendering: ArticleRendering
|
||||
|
||||
switch state {
|
||||
case .noSelection:
|
||||
html = ArticleRenderer.noSelectionHTML(style: style)
|
||||
rendering = ArticleRenderer.noSelectionHTML(style: style)
|
||||
case .multipleSelection:
|
||||
html = ArticleRenderer.multipleSelectionHTML(style: style)
|
||||
rendering = ArticleRenderer.multipleSelectionHTML(style: style)
|
||||
case .article(let article):
|
||||
html = ArticleRenderer.articleHTML(article: article, style: style)
|
||||
rendering = ArticleRenderer.articleHTML(article: article, style: style)
|
||||
case .extracted(let article, let extractedArticle):
|
||||
html = ArticleRenderer.articleHTML(article: article, extractedArticle: extractedArticle, style: style)
|
||||
rendering = ArticleRenderer.articleHTML(article: article, extractedArticle: extractedArticle, style: style)
|
||||
}
|
||||
|
||||
let templateData = TemplateData(body: html)
|
||||
let templateData = TemplateData(style: rendering.style, body: rendering.html)
|
||||
|
||||
let encoder = JSONEncoder()
|
||||
var render = "error();"
|
||||
|
||||
@@ -20,7 +20,8 @@ import RSCore
|
||||
static let articleUTIInternalType = NSPasteboard.PasteboardType(rawValue: articleUTIInternal)
|
||||
|
||||
private lazy var renderedHTML: String = {
|
||||
return ArticleRenderer.articleHTML(article: article, style: ArticleStylesManager.shared.currentStyle)
|
||||
let rendering = ArticleRenderer.articleHTML(article: article, style: ArticleStylesManager.shared.currentStyle)
|
||||
return rendering.html
|
||||
}()
|
||||
|
||||
init(article: Article) {
|
||||
|
||||
@@ -11,6 +11,8 @@ import RSCore
|
||||
import Articles
|
||||
import Account
|
||||
|
||||
typealias ArticleRendering = (style: String, html: String)
|
||||
|
||||
struct ArticleRenderer {
|
||||
|
||||
private let article: Article?
|
||||
@@ -36,24 +38,24 @@ struct ArticleRenderer {
|
||||
|
||||
// MARK: - API
|
||||
|
||||
static func articleHTML(article: Article, extractedArticle: ExtractedArticle? = nil, style: ArticleStyle) -> String {
|
||||
static func articleHTML(article: Article, extractedArticle: ExtractedArticle? = nil, style: ArticleStyle) -> ArticleRendering {
|
||||
let renderer = ArticleRenderer(article: article, extractedArticle: extractedArticle, style: style)
|
||||
return renderer.articleHTML
|
||||
return (renderer.styleString(), renderer.articleHTML)
|
||||
}
|
||||
|
||||
static func multipleSelectionHTML(style: ArticleStyle) -> String {
|
||||
static func multipleSelectionHTML(style: ArticleStyle) -> ArticleRendering {
|
||||
let renderer = ArticleRenderer(article: nil, extractedArticle: nil, style: style)
|
||||
return renderer.multipleSelectionHTML
|
||||
return (renderer.styleString(), renderer.multipleSelectionHTML)
|
||||
}
|
||||
|
||||
static func noSelectionHTML(style: ArticleStyle) -> String {
|
||||
static func noSelectionHTML(style: ArticleStyle) -> ArticleRendering {
|
||||
let renderer = ArticleRenderer(article: nil, extractedArticle: nil, style: style)
|
||||
return renderer.noSelectionHTML
|
||||
return (renderer.styleString(), renderer.noSelectionHTML)
|
||||
}
|
||||
|
||||
static func noContentHTML(style: ArticleStyle) -> String {
|
||||
static func noContentHTML(style: ArticleStyle) -> ArticleRendering {
|
||||
let renderer = ArticleRenderer(article: nil, extractedArticle: nil, style: style)
|
||||
return renderer.noContentHTML
|
||||
return (renderer.styleString(), renderer.noContentHTML)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,175 +1,6 @@
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
body {
|
||||
margin-top: 20px;
|
||||
margin-bottom: 64px;
|
||||
margin-left: 64px;
|
||||
margin-right: 64px;
|
||||
font-family: -apple-system;
|
||||
font-size: 18px;
|
||||
word-wrap: break-word; /* break long words or URLs */
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
}
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
.feedlink {
|
||||
font-weight: bold;
|
||||
}
|
||||
.headerTable {
|
||||
width: 100%;
|
||||
height: 68px;
|
||||
}
|
||||
|
||||
.systemMessage {
|
||||
position: absolute;
|
||||
top: 45%;
|
||||
left: 50%;
|
||||
transform: translateX(-55%) translateY(-50%);
|
||||
}
|
||||
|
||||
:root {
|
||||
--body-color: #444;
|
||||
--body-background-color: -apple-system-text-background;
|
||||
--link-color: hsla(215, 99%, 43%, 1);
|
||||
--header-table-border-color: rgba(0, 0, 0, 0.1);
|
||||
--header-color: rgba(0, 0, 0, 0.3);
|
||||
--header-link-color: rgba(0, 0, 0, 0.3);
|
||||
--body-code-color: #666;
|
||||
--system-message-color: #cbcbcb;
|
||||
--feedlink-color: rgba(0, 0, 0, 0.6);
|
||||
}
|
||||
|
||||
@media(prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--body-color: #d2d2d2;
|
||||
--body-background-color: #2d2d2d;
|
||||
--link-color: #4490e2;
|
||||
--header-table-border-color: rgba(255, 255, 255, 0.1);
|
||||
--header-color: #d2d2d2;
|
||||
--header-link-color: #4490e2;
|
||||
--body-code-color: #b2b2b2;
|
||||
--system-message-color: #5f5f5f
|
||||
}
|
||||
}
|
||||
|
||||
body {
|
||||
color: var(--body-color);
|
||||
background-color: var(--body-background-color);
|
||||
}
|
||||
|
||||
body a, body a:link, body a:visited {
|
||||
color: var(--link-color);
|
||||
}
|
||||
body .headerTable {
|
||||
border-bottom: 1px solid var(--header-table-border-color);
|
||||
}
|
||||
body .header {
|
||||
color: var(--header-color);
|
||||
}
|
||||
body .header a:link, body .header a:visited {
|
||||
color: var(--header-link-color);
|
||||
}
|
||||
body .articleDateline, body .articleDateLine.a:link, body .articleDateline a:visited {
|
||||
color: var(--header-color);
|
||||
}
|
||||
|
||||
body code, body pre {
|
||||
color: var(--body-code-color);
|
||||
}
|
||||
|
||||
body > .systemMessage {
|
||||
color: var(--system-message-color);
|
||||
}
|
||||
|
||||
.feedlink a:link, .feedlink a:visited {
|
||||
color: var(--feed-link-color);
|
||||
}
|
||||
.avatar img {
|
||||
border-radius: 4px;
|
||||
}
|
||||
.feedIcon {
|
||||
border-radius: 4px;
|
||||
}
|
||||
.rightAlign {
|
||||
text-align: right;
|
||||
}
|
||||
.leftAlign {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.articleTitle {
|
||||
margin-top: 26px;
|
||||
}
|
||||
|
||||
.articleDateline {
|
||||
margin-bottom: 25px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.articleBody {
|
||||
line-height: 1.6em;
|
||||
}
|
||||
h1 {
|
||||
line-height: 1.15em;
|
||||
font-weight: bold;
|
||||
}
|
||||
code, pre {
|
||||
font-family: "SF Mono", Menlo, "Courier New", Courier, monospace;
|
||||
font-size: 14px;
|
||||
}
|
||||
pre {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
img, figure, video, iframe, div {
|
||||
max-width: 100%;
|
||||
height: auto !important;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
figcaption {
|
||||
font-size: 14px;
|
||||
line-height: 1.3em;
|
||||
}
|
||||
|
||||
/*Block ads and junk*/
|
||||
|
||||
iframe[src*="feedads"],
|
||||
iframe[src*="doubleclick"],
|
||||
iframe[src*="plusone.google"] {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
a[href*=".ads."],
|
||||
a[href*="feedads"],
|
||||
a[href*="doubleclick"],
|
||||
a[href*="//ads."],
|
||||
a[href*="api.tweetmeme"],
|
||||
a[href*="delicious.com/post?"],
|
||||
a[href*="digg.com/submit?"],
|
||||
a[href*="google.com/bookmarks/mark?"],
|
||||
a[href*="posterous.com/share?"],
|
||||
a[href*="tumblr.com/share?"],
|
||||
a[href*="linkedin.com/shareArticle?"],
|
||||
a[href*="facebook.com/share.php?"],
|
||||
a[href*="http://twitter.com/home?"],
|
||||
a[href*="addtoany.com/share_save"] {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
img[src*=".ads."],
|
||||
img[src*="//ads."],
|
||||
img[src*="doubleclick"],
|
||||
img[src*="feedads"],
|
||||
img[src*="feedburner"],
|
||||
img[src*="feedblitz"],
|
||||
img[src*="share-buttons"] {
|
||||
display: none !important;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
function mouseDidEnterLink(anchor) {
|
||||
@@ -181,6 +12,7 @@
|
||||
}
|
||||
|
||||
function render(data) {
|
||||
document.getElementsByTagName("style")[0].innerHTML = data.style;
|
||||
document.body.innerHTML = data.body;
|
||||
window.scrollTo(0, 0);
|
||||
var anchors = document.getElementsByTagName("a");
|
||||
|
||||
@@ -104,7 +104,7 @@ class DetailViewController: UIViewController {
|
||||
return
|
||||
}
|
||||
let style = ArticleStylesManager.shared.currentStyle
|
||||
let html = ArticleRenderer.articleHTML(article: article, style: style)
|
||||
let (styleSheet, html) = ArticleRenderer.articleHTML(article: article, style: style)
|
||||
webView.loadHTMLString(html, baseURL: nil)
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user