Render with evaluateJavaScript.
Replaced loadHTMLString based rendering for improved performance.
This commit is contained in:
parent
3b5a6f2576
commit
0b6683d073
|
@ -100,7 +100,13 @@ final class DetailWebViewController: NSViewController, WKUIDelegate {
|
|||
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(webInspectorEnabledDidChange(_:)), name: .WebInspectorEnabledDidChange, object: nil)
|
||||
|
||||
reloadHTML()
|
||||
webView.loadHTMLString(template(), baseURL: nil)
|
||||
}
|
||||
|
||||
func template() -> String {
|
||||
let path = Bundle.main.path(forResource: "page", ofType: "html")!
|
||||
let s = try! NSString(contentsOfFile: path, encoding: String.Encoding.utf8.rawValue)
|
||||
return s as String
|
||||
}
|
||||
|
||||
// MARK: Scrolling
|
||||
|
@ -162,6 +168,9 @@ extension DetailWebViewController: WKNavigationDelegate {
|
|||
}
|
||||
|
||||
// MARK: - Private
|
||||
struct TemplateData: Codable {
|
||||
let body: String
|
||||
}
|
||||
|
||||
private extension DetailWebViewController {
|
||||
|
||||
|
@ -179,8 +188,17 @@ private extension DetailWebViewController {
|
|||
case .extracted(let article, let extractedArticle):
|
||||
html = ArticleRenderer.articleHTML(article: article, extractedArticle: extractedArticle, style: style)
|
||||
}
|
||||
|
||||
let templateData = TemplateData(body: html)
|
||||
|
||||
let encoder = JSONEncoder()
|
||||
var render = "error();"
|
||||
if let data = try? encoder.encode(templateData) {
|
||||
let json = String(data: data, encoding: .utf8)!
|
||||
render = "render(\(json));"
|
||||
}
|
||||
|
||||
webView.loadHTMLString(html, baseURL: nil)
|
||||
webView.evaluateJavaScript(render)
|
||||
}
|
||||
|
||||
func fetchScrollInfo(_ callback: @escaping (ScrollInfo?) -> Void) {
|
||||
|
|
|
@ -372,6 +372,8 @@
|
|||
84FF69B11FC3793300DC198E /* FaviconURLFinder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84FF69B01FC3793300DC198E /* FaviconURLFinder.swift */; };
|
||||
9EA33BB92318F8C10097B644 /* AccountsFeedlyWebWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EA33BB72318F8C10097B644 /* AccountsFeedlyWebWindowController.swift */; };
|
||||
9EA33BBA2318F8C10097B644 /* AccountsFeedlyWeb.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9EA33BB82318F8C10097B644 /* AccountsFeedlyWeb.xib */; };
|
||||
B528F81E23333C7E00E735DD /* page.html in Resources */ = {isa = PBXBuildFile; fileRef = B528F81D23333C7E00E735DD /* page.html */; };
|
||||
B528F81F23333C7E00E735DD /* page.html in Resources */ = {isa = PBXBuildFile; fileRef = B528F81D23333C7E00E735DD /* page.html */; };
|
||||
D553738B20186C20006D8857 /* Article+Scriptability.swift in Sources */ = {isa = PBXBuildFile; fileRef = D553737C20186C1F006D8857 /* Article+Scriptability.swift */; };
|
||||
D57BE6E0204CD35F00D11AAC /* NSScriptCommand+NetNewsWire.swift in Sources */ = {isa = PBXBuildFile; fileRef = D57BE6DF204CD35F00D11AAC /* NSScriptCommand+NetNewsWire.swift */; };
|
||||
D5907D7F2004AC00005947E5 /* NSApplication+Scriptability.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5907D7E2004AC00005947E5 /* NSApplication+Scriptability.swift */; };
|
||||
|
@ -1051,10 +1053,11 @@
|
|||
84F9EAE4213660A100CF2DE4 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
84FB9A2D1EDCD6B8003D53B9 /* Sparkle.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Sparkle.framework; path = Frameworks/Vendor/Sparkle.framework; sourceTree = SOURCE_ROOT; };
|
||||
84FF69B01FC3793300DC198E /* FaviconURLFinder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FaviconURLFinder.swift; sourceTree = "<group>"; };
|
||||
B24EFD482330FF99006C6242 /* NetNewsWire-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NetNewsWire-Bridging-Header.h"; sourceTree = "<group>"; };
|
||||
B24EFD5923310109006C6242 /* WKPreferencesPrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WKPreferencesPrivate.h; sourceTree = "<group>"; };
|
||||
9EA33BB72318F8C10097B644 /* AccountsFeedlyWebWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountsFeedlyWebWindowController.swift; sourceTree = "<group>"; };
|
||||
9EA33BB82318F8C10097B644 /* AccountsFeedlyWeb.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = AccountsFeedlyWeb.xib; sourceTree = "<group>"; };
|
||||
B24EFD482330FF99006C6242 /* NetNewsWire-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NetNewsWire-Bridging-Header.h"; sourceTree = "<group>"; };
|
||||
B24EFD5923310109006C6242 /* WKPreferencesPrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WKPreferencesPrivate.h; sourceTree = "<group>"; };
|
||||
B528F81D23333C7E00E735DD /* page.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = page.html; sourceTree = "<group>"; };
|
||||
D519E74722EE553300923F27 /* NetNewsWire_safariextension_target.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = NetNewsWire_safariextension_target.xcconfig; sourceTree = "<group>"; };
|
||||
D553737C20186C1F006D8857 /* Article+Scriptability.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Article+Scriptability.swift"; sourceTree = "<group>"; };
|
||||
D57BE6DF204CD35F00D11AAC /* NSScriptCommand+NetNewsWire.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSScriptCommand+NetNewsWire.swift"; sourceTree = "<group>"; };
|
||||
|
@ -1381,6 +1384,7 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
849A977D1ED9EC42007D329B /* ArticleRenderer.swift */,
|
||||
B528F81D23333C7E00E735DD /* page.html */,
|
||||
848362FE2262A30E00DA1D35 /* template.html */,
|
||||
);
|
||||
path = "Article Rendering";
|
||||
|
@ -2223,16 +2227,16 @@
|
|||
TargetAttributes = {
|
||||
513C5CE5232571C2003D4054 = {
|
||||
CreatedOnToolsVersion = 11.0;
|
||||
DevelopmentTeam = SHJK2V3AJG;
|
||||
DevelopmentTeam = DY2XQRVWN9;
|
||||
ProvisioningStyle = Automatic;
|
||||
};
|
||||
6581C73220CED60000F4AD34 = {
|
||||
DevelopmentTeam = SHJK2V3AJG;
|
||||
ProvisioningStyle = Automatic;
|
||||
ProvisioningStyle = Manual;
|
||||
};
|
||||
840D617B2029031C009BC708 = {
|
||||
CreatedOnToolsVersion = 9.3;
|
||||
DevelopmentTeam = SHJK2V3AJG;
|
||||
DevelopmentTeam = DY2XQRVWN9;
|
||||
ProvisioningStyle = Automatic;
|
||||
SystemCapabilities = {
|
||||
com.apple.BackgroundModes = {
|
||||
|
@ -2243,7 +2247,7 @@
|
|||
849C645F1ED37A5D003D8FC0 = {
|
||||
CreatedOnToolsVersion = 8.2.1;
|
||||
DevelopmentTeam = SHJK2V3AJG;
|
||||
ProvisioningStyle = Automatic;
|
||||
ProvisioningStyle = Manual;
|
||||
SystemCapabilities = {
|
||||
com.apple.HardenedRuntime = {
|
||||
enabled = 1;
|
||||
|
@ -2252,7 +2256,7 @@
|
|||
};
|
||||
849C64701ED37A5D003D8FC0 = {
|
||||
CreatedOnToolsVersion = 8.2.1;
|
||||
DevelopmentTeam = SHJK2V3AJG;
|
||||
DevelopmentTeam = 9C84TZ7Q6Z;
|
||||
ProvisioningStyle = Automatic;
|
||||
TestTargetID = 849C645F1ED37A5D003D8FC0;
|
||||
};
|
||||
|
@ -2491,6 +2495,7 @@
|
|||
511D43EF231FBDE900FB1562 /* LaunchScreenPad.storyboard in Resources */,
|
||||
511D43D2231FA62C00FB1562 /* GlobalKeyboardShortcuts.plist in Resources */,
|
||||
84C9FCA12262A1B300D921D6 /* Main.storyboard in Resources */,
|
||||
B528F81F23333C7E00E735DD /* page.html in Resources */,
|
||||
51F85BF32272531500C787DC /* Dedication.rtf in Resources */,
|
||||
84C9FCA42262A1B800D921D6 /* LaunchScreenPhone.storyboard in Resources */,
|
||||
51F85BEB22724CB600C787DC /* About.rtf in Resources */,
|
||||
|
@ -2532,6 +2537,7 @@
|
|||
848363052262A3CC00DA1D35 /* AddFolderSheet.xib in Resources */,
|
||||
5144EA52227B8E4500D19003 /* AccountsFeedbin.xib in Resources */,
|
||||
8405DDA222168920008CE1BF /* TimelineTableView.xib in Resources */,
|
||||
B528F81E23333C7E00E735DD /* page.html in Resources */,
|
||||
8483630E2262A3FE00DA1D35 /* MainWindow.storyboard in Resources */,
|
||||
55E15BCB229D65A900D6602A /* AccountsReaderAPI.xib in Resources */,
|
||||
84BAE64921CEDAF20046DB56 /* CrashReporterWindow.xib in Resources */,
|
||||
|
|
|
@ -328,87 +328,17 @@ private extension ArticleRenderer {
|
|||
return dateFormatter.string(from: date)
|
||||
}
|
||||
|
||||
#if os(macOS)
|
||||
|
||||
func renderHTML(withBody body: String) -> String {
|
||||
|
||||
var s = "<!DOCTYPE html><html><head>\n\n"
|
||||
var s = ""
|
||||
if let baseURL = baseURL {
|
||||
s += ("<base href=\"" + baseURL + "\"\n>")
|
||||
}
|
||||
s += title.htmlBySurroundingWithTag("title")
|
||||
s += styleString().htmlBySurroundingWithTag("style")
|
||||
|
||||
s += """
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
function startup() {
|
||||
var anchors = document.getElementsByTagName("a");
|
||||
for (var i = 0; i < anchors.length; i++) {
|
||||
anchors[i].addEventListener("mouseenter", function() { mouseDidEnterLink(this) });
|
||||
anchors[i].addEventListener("mouseleave", function() { mouseDidExitLink(this) });
|
||||
}
|
||||
|
||||
document.getElementsByTagName("body")[0].querySelectorAll("style, link[rel=stylesheet]").forEach(element => element.remove());
|
||||
document.getElementsByTagName("body")[0].querySelectorAll("[style]").forEach(element => element.removeAttribute("style"));
|
||||
}
|
||||
|
||||
function mouseDidEnterLink(anchor) {
|
||||
window.webkit.messageHandlers.mouseDidEnter.postMessage(anchor.href);
|
||||
}
|
||||
|
||||
function mouseDidExitLink(anchor) {
|
||||
window.webkit.messageHandlers.mouseDidExit.postMessage(anchor.href);
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
"""
|
||||
|
||||
s += "\n\n</head><body onload='startup()'>\n\n"
|
||||
s += body
|
||||
s += "\n\n</body></html>"
|
||||
|
||||
//print(s)
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
func renderHTML(withBody body: String) -> String {
|
||||
|
||||
var s = "<!DOCTYPE html><html><head>\n"
|
||||
if let baseURL = baseURL {
|
||||
s += ("<base href=\"" + baseURL + "\"\n>")
|
||||
}
|
||||
s += "<meta name=\"viewport\" content=\"width=device-width\">\n"
|
||||
s += title.htmlBySurroundingWithTag("title")
|
||||
s += styleString().htmlBySurroundingWithTag("style")
|
||||
s += """
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
function startup() {
|
||||
document.getElementsByTagName("body")[0].querySelectorAll("style, link[rel=stylesheet]").forEach(element => element.remove());
|
||||
document.getElementsByTagName("body")[0].querySelectorAll("[style]").forEach(element => element.removeAttribute("style"));
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
"""
|
||||
|
||||
s += "\n\n</head><body onload='startup()'>\n\n"
|
||||
s += body
|
||||
s += "\n\n</body></html>"
|
||||
|
||||
return s
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
// MARK: - Article extension
|
||||
|
|
|
@ -0,0 +1,202 @@
|
|||
<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) {
|
||||
window.webkit.messageHandlers.mouseDidEnter.postMessage(anchor.href);
|
||||
}
|
||||
|
||||
function mouseDidExitLink(anchor) {
|
||||
window.webkit.messageHandlers.mouseDidExit.postMessage(anchor.href);
|
||||
}
|
||||
|
||||
function render(data) {
|
||||
document.body.innerHTML = data.body;
|
||||
var anchors = document.getElementsByTagName("a");
|
||||
for (var i = 0; i < anchors.length; i++) {
|
||||
anchors[i].addEventListener("mouseenter", function() { mouseDidEnterLink(this) });
|
||||
anchors[i].addEventListener("mouseleave", function() { mouseDidExitLink(this) });
|
||||
}
|
||||
|
||||
document.getElementsByTagName("body")[0].querySelectorAll("style, link[rel=stylesheet]").forEach(element => element.remove());
|
||||
document.getElementsByTagName("body")[0].querySelectorAll("[style]").forEach(element => element.removeAttribute("style"));
|
||||
}
|
||||
|
||||
function error() {
|
||||
document.body.innerHTML = "error";
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue