"];
322 | NSInteger location = t.location + t.length;
323 |
324 | NSString *t_object = [NSString stringWithFormat:@"
%@
",object];
325 | [mut_str insertString:t_object atIndex:location];
326 |
327 | [_readerWebView loadHTMLString:mut_str baseURL:self.url];
328 | _readerWebView.alpha = 0.0f;
329 |
330 | [_webView evaluateJavaScript:@"ReaderArticleFinderJS.prepareToTransitionToReader();" completionHandler:^(id _Nullable object, NSError * _Nullable error) {}];
331 | }];
332 | }
333 | }];
334 | } else {
335 | [UIView animateWithDuration:0.2f animations:^{
336 | self.webMaskView.backgroundColor = [UIColor colorWithWhite:0.0f alpha:0.0f];
337 | self.maskLayer.frame = CGRectMake(0.0f, 0.0f, _readerWebView.frame.size.width, 0.0f);
338 | } completion:^(BOOL finished) {
339 | _readerWebView.userInteractionEnabled = NO;
340 | }];
341 | }
342 | }
343 |
344 | - (void)webViewToolbarOpenInSafari:(PFWebViewToolBar *)toolbar {
345 | UIApplication *application = [UIApplication sharedApplication];
346 | #ifndef __IPHONE_10_0
347 | #define __IPHONE_10_0 100000
348 | #endif
349 | #if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0
350 | if ([application respondsToSelector:@selector(openURL:options:completionHandler:)]) {
351 | [application openURL:self.webView.URL options:@{} completionHandler:nil];
352 | } else {
353 | [application openURL:self.webView.URL];
354 | }
355 | #else
356 | [application openURL:self.webView.URL];
357 | #endif
358 | }
359 |
360 | - (void)webViewToolbarClose:(PFWebViewToolBar *)toolbar {
361 | if (self.navigationController) {
362 | [self.navigationController popViewControllerAnimated:YES];
363 | } else {
364 | [self dismissViewControllerAnimated:YES completion:nil];
365 | }
366 | }
367 |
368 | #pragma mark - WKWebViewNavigationDelegate Methods
369 |
370 | - (void)webView:(WKWebView *)webView didCommitNavigation:(null_unspecified WKNavigation *)navigation {
371 | if ([webView isEqual:self.readerWebView]) {
372 | return;
373 | }
374 |
375 | if (![self.webView.URL.absoluteString isEqualToString:@"about:blank"]) {
376 | // Cache current url after every frame entering if not blank page
377 | self.url = self.webView.URL;
378 | isReaderMode = NO;
379 |
380 | self.toolbar.readerModeBtn.selected = NO;
381 |
382 | // Set reader mode button enabled NO when begin navigation
383 | self.toolbar.readerModeBtn.enabled = NO;
384 | }
385 | }
386 |
387 | - (void)webView:(WKWebView *)webView didFinishNavigation:(null_unspecified WKNavigation *)navigation {
388 | if (webView == _webView) {
389 | // Set reader mode button status when navigation finished
390 | [webView evaluateJavaScript:@"var ReaderArticleFinderJS = new ReaderArticleFinder(document); ReaderArticleFinderJS.isReaderModeAvailable();" completionHandler:^(id _Nullable object, NSError * _Nullable error) {
391 | if ([object integerValue] == 1) {
392 | self.toolbar.readerModeBtn.enabled = YES;
393 | } else {
394 | self.toolbar.readerModeBtn.enabled = NO;
395 | }
396 | }];
397 | }
398 | }
399 |
400 | // 拦截非 Http:// 和 Https:// 开头的请求,转成应用内跳转
401 | - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
402 | if ([webView isEqual:self.readerWebView]) {
403 | decisionHandler(WKNavigationActionPolicyAllow);
404 | return;
405 | }
406 |
407 | if (![navigationAction.request.URL.absoluteString containsString:@"http://"] && ![navigationAction.request.URL.absoluteString containsString:@"https://"]) {
408 |
409 | UIApplication *application = [UIApplication sharedApplication];
410 | #ifndef __IPHONE_10_0
411 | #define __IPHONE_10_0 100000
412 | #endif
413 | #if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0
414 | if ([application respondsToSelector:@selector(openURL:options:completionHandler:)]) {
415 | [application openURL:navigationAction.request.URL options:@{} completionHandler:nil];
416 | } else {
417 | [application openURL:navigationAction.request.URL];
418 | }
419 | #else
420 | [application openURL:navigationAction.request.URL];
421 | #endif
422 | decisionHandler(WKNavigationActionPolicyCancel);
423 | } else {
424 | decisionHandler(WKNavigationActionPolicyAllow);
425 | }
426 | }
427 |
428 | - (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler {
429 | decisionHandler(WKNavigationResponsePolicyAllow);
430 | }
431 |
432 | - (void)userContentController:(WKUserContentController *)userContentController
433 | didReceiveScriptMessage:(WKScriptMessage *)message {
434 | _readerWebView.alpha = 1.0f;
435 |
436 | dispatch_async(dispatch_get_main_queue(), ^{
437 | [UIView animateWithDuration:0.1f delay:0.2f options:UIViewAnimationOptionCurveEaseInOut animations:^{
438 | self.webMaskView.backgroundColor = [UIColor colorWithWhite:0.0f alpha:0.4f];
439 | self.maskLayer.frame = CGRectMake(0.0f, 0.0f, _readerWebView.frame.size.width, _readerWebView.frame.size.height);
440 | } completion:^(BOOL finished) {
441 | _readerWebView.userInteractionEnabled = YES;
442 | }];
443 | });
444 |
445 | }
446 |
447 | @end
448 |
--------------------------------------------------------------------------------
/PFWebViewController.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 921A45CA1D95870E0040BE3B /* PFWebViewController.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 921A45C31D95870E0040BE3B /* PFWebViewController.framework */; };
11 | 921A45CB1D95870E0040BE3B /* PFWebViewController.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 921A45C31D95870E0040BE3B /* PFWebViewController.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
12 | 921A45D01D9587300040BE3B /* PFWebViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 927D6EA51D9127420066D7BC /* PFWebViewController.h */; settings = {ATTRIBUTES = (Public, ); }; };
13 | 921A45D11D9587440040BE3B /* PFWebViewNavigationHeader.h in Headers */ = {isa = PBXBuildFile; fileRef = 927D6EA71D9127420066D7BC /* PFWebViewNavigationHeader.h */; settings = {ATTRIBUTES = (Private, ); }; };
14 | 921A45D21D9587440040BE3B /* PFWebViewToolBar.h in Headers */ = {isa = PBXBuildFile; fileRef = 927D6EA91D9127420066D7BC /* PFWebViewToolBar.h */; settings = {ATTRIBUTES = (Private, ); }; };
15 | 921A45D31D95875A0040BE3B /* PFWebViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 927D6EA61D9127420066D7BC /* PFWebViewController.m */; };
16 | 921A45D41D95875A0040BE3B /* PFWebViewNavigationHeader.m in Sources */ = {isa = PBXBuildFile; fileRef = 927D6EA81D9127420066D7BC /* PFWebViewNavigationHeader.m */; };
17 | 921A45D51D95875A0040BE3B /* PFWebViewToolBar.m in Sources */ = {isa = PBXBuildFile; fileRef = 927D6EAA1D9127420066D7BC /* PFWebViewToolBar.m */; };
18 | 921A45D61D9587600040BE3B /* PFWebViewController.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 927D6EA41D9127420066D7BC /* PFWebViewController.bundle */; };
19 | 927D6EAC1D9127420066D7BC /* PFWebViewController.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 927D6EA41D9127420066D7BC /* PFWebViewController.bundle */; };
20 | 927D6EAD1D9127420066D7BC /* PFWebViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 927D6EA61D9127420066D7BC /* PFWebViewController.m */; };
21 | 927D6EAE1D9127420066D7BC /* PFWebViewNavigationHeader.m in Sources */ = {isa = PBXBuildFile; fileRef = 927D6EA81D9127420066D7BC /* PFWebViewNavigationHeader.m */; };
22 | 927D6EAF1D9127420066D7BC /* PFWebViewToolBar.m in Sources */ = {isa = PBXBuildFile; fileRef = 927D6EAA1D9127420066D7BC /* PFWebViewToolBar.m */; };
23 | 928771851D8FDAF400491C20 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 928771841D8FDAF400491C20 /* main.m */; };
24 | 928771881D8FDAF400491C20 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 928771871D8FDAF400491C20 /* AppDelegate.m */; };
25 | 9287718B1D8FDAF400491C20 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9287718A1D8FDAF400491C20 /* ViewController.m */; };
26 | 9287718E1D8FDAF400491C20 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9287718C1D8FDAF400491C20 /* Main.storyboard */; };
27 | 928771901D8FDAF400491C20 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 9287718F1D8FDAF400491C20 /* Assets.xcassets */; };
28 | 928771931D8FDAF400491C20 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 928771911D8FDAF400491C20 /* LaunchScreen.storyboard */; };
29 | /* End PBXBuildFile section */
30 |
31 | /* Begin PBXContainerItemProxy section */
32 | 921A45C81D95870E0040BE3B /* PBXContainerItemProxy */ = {
33 | isa = PBXContainerItemProxy;
34 | containerPortal = 928771781D8FDAF400491C20 /* Project object */;
35 | proxyType = 1;
36 | remoteGlobalIDString = 921A45C21D95870E0040BE3B;
37 | remoteInfo = PFWebViewControllerFramework;
38 | };
39 | /* End PBXContainerItemProxy section */
40 |
41 | /* Begin PBXCopyFilesBuildPhase section */
42 | 921A45CF1D95870E0040BE3B /* Embed Frameworks */ = {
43 | isa = PBXCopyFilesBuildPhase;
44 | buildActionMask = 2147483647;
45 | dstPath = "";
46 | dstSubfolderSpec = 10;
47 | files = (
48 | 921A45CB1D95870E0040BE3B /* PFWebViewController.framework in Embed Frameworks */,
49 | );
50 | name = "Embed Frameworks";
51 | runOnlyForDeploymentPostprocessing = 0;
52 | };
53 | /* End PBXCopyFilesBuildPhase section */
54 |
55 | /* Begin PBXFileReference section */
56 | 50E32DDB1DACFA9D00906C27 /* libxml2.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libxml2.tbd; path = usr/lib/libxml2.tbd; sourceTree = SDKROOT; };
57 | 921A45C31D95870E0040BE3B /* PFWebViewController.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = PFWebViewController.framework; sourceTree = BUILT_PRODUCTS_DIR; };
58 | 921A45C51D95870E0040BE3B /* PFWebViewControllerFramework.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PFWebViewControllerFramework.h; sourceTree = "
"; };
59 | 921A45C61D95870E0040BE3B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
60 | 927D6EA41D9127420066D7BC /* PFWebViewController.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = PFWebViewController.bundle; sourceTree = ""; };
61 | 927D6EA51D9127420066D7BC /* PFWebViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PFWebViewController.h; sourceTree = ""; };
62 | 927D6EA61D9127420066D7BC /* PFWebViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PFWebViewController.m; sourceTree = ""; };
63 | 927D6EA71D9127420066D7BC /* PFWebViewNavigationHeader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PFWebViewNavigationHeader.h; sourceTree = ""; };
64 | 927D6EA81D9127420066D7BC /* PFWebViewNavigationHeader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PFWebViewNavigationHeader.m; sourceTree = ""; };
65 | 927D6EA91D9127420066D7BC /* PFWebViewToolBar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PFWebViewToolBar.h; sourceTree = ""; };
66 | 927D6EAA1D9127420066D7BC /* PFWebViewToolBar.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PFWebViewToolBar.m; sourceTree = ""; };
67 | 927D6EB11D912A600066D7BC /* PFWebViewToolBar.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = PFWebViewToolBar.xib; sourceTree = ""; };
68 | 928771801D8FDAF400491C20 /* PFWebViewController.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = PFWebViewController.app; sourceTree = BUILT_PRODUCTS_DIR; };
69 | 928771841D8FDAF400491C20 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
70 | 928771861D8FDAF400491C20 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
71 | 928771871D8FDAF400491C20 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
72 | 928771891D8FDAF400491C20 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; };
73 | 9287718A1D8FDAF400491C20 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; };
74 | 9287718D1D8FDAF400491C20 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
75 | 9287718F1D8FDAF400491C20 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
76 | 928771921D8FDAF400491C20 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
77 | 928771941D8FDAF400491C20 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
78 | /* End PBXFileReference section */
79 |
80 | /* Begin PBXFrameworksBuildPhase section */
81 | 921A45BF1D95870E0040BE3B /* Frameworks */ = {
82 | isa = PBXFrameworksBuildPhase;
83 | buildActionMask = 2147483647;
84 | files = (
85 | );
86 | runOnlyForDeploymentPostprocessing = 0;
87 | };
88 | 9287717D1D8FDAF400491C20 /* Frameworks */ = {
89 | isa = PBXFrameworksBuildPhase;
90 | buildActionMask = 2147483647;
91 | files = (
92 | 921A45CA1D95870E0040BE3B /* PFWebViewController.framework in Frameworks */,
93 | );
94 | runOnlyForDeploymentPostprocessing = 0;
95 | };
96 | /* End PBXFrameworksBuildPhase section */
97 |
98 | /* Begin PBXGroup section */
99 | 50E32DDA1DACFA9D00906C27 /* Frameworks */ = {
100 | isa = PBXGroup;
101 | children = (
102 | 50E32DDB1DACFA9D00906C27 /* libxml2.tbd */,
103 | );
104 | name = Frameworks;
105 | sourceTree = "";
106 | };
107 | 921A45C41D95870E0040BE3B /* PFWebViewControllerFramework */ = {
108 | isa = PBXGroup;
109 | children = (
110 | 921A45C51D95870E0040BE3B /* PFWebViewControllerFramework.h */,
111 | 921A45C61D95870E0040BE3B /* Info.plist */,
112 | );
113 | path = PFWebViewControllerFramework;
114 | sourceTree = "";
115 | };
116 | 927D6EA31D9127420066D7BC /* Classes */ = {
117 | isa = PBXGroup;
118 | children = (
119 | 927D6EA41D9127420066D7BC /* PFWebViewController.bundle */,
120 | 927D6EA51D9127420066D7BC /* PFWebViewController.h */,
121 | 927D6EA61D9127420066D7BC /* PFWebViewController.m */,
122 | 927D6EA71D9127420066D7BC /* PFWebViewNavigationHeader.h */,
123 | 927D6EA81D9127420066D7BC /* PFWebViewNavigationHeader.m */,
124 | 927D6EA91D9127420066D7BC /* PFWebViewToolBar.h */,
125 | 927D6EAA1D9127420066D7BC /* PFWebViewToolBar.m */,
126 | 927D6EB11D912A600066D7BC /* PFWebViewToolBar.xib */,
127 | );
128 | path = Classes;
129 | sourceTree = "";
130 | };
131 | 928771771D8FDAF400491C20 = {
132 | isa = PBXGroup;
133 | children = (
134 | 927D6EA31D9127420066D7BC /* Classes */,
135 | 928771821D8FDAF400491C20 /* PFWebViewController */,
136 | 921A45C41D95870E0040BE3B /* PFWebViewControllerFramework */,
137 | 928771811D8FDAF400491C20 /* Products */,
138 | 50E32DDA1DACFA9D00906C27 /* Frameworks */,
139 | );
140 | sourceTree = "";
141 | };
142 | 928771811D8FDAF400491C20 /* Products */ = {
143 | isa = PBXGroup;
144 | children = (
145 | 928771801D8FDAF400491C20 /* PFWebViewController.app */,
146 | 921A45C31D95870E0040BE3B /* PFWebViewController.framework */,
147 | );
148 | name = Products;
149 | sourceTree = "";
150 | };
151 | 928771821D8FDAF400491C20 /* PFWebViewController */ = {
152 | isa = PBXGroup;
153 | children = (
154 | 928771861D8FDAF400491C20 /* AppDelegate.h */,
155 | 928771871D8FDAF400491C20 /* AppDelegate.m */,
156 | 928771891D8FDAF400491C20 /* ViewController.h */,
157 | 9287718A1D8FDAF400491C20 /* ViewController.m */,
158 | 9287718C1D8FDAF400491C20 /* Main.storyboard */,
159 | 9287718F1D8FDAF400491C20 /* Assets.xcassets */,
160 | 928771911D8FDAF400491C20 /* LaunchScreen.storyboard */,
161 | 928771941D8FDAF400491C20 /* Info.plist */,
162 | 928771831D8FDAF400491C20 /* Supporting Files */,
163 | );
164 | path = PFWebViewController;
165 | sourceTree = "";
166 | };
167 | 928771831D8FDAF400491C20 /* Supporting Files */ = {
168 | isa = PBXGroup;
169 | children = (
170 | 928771841D8FDAF400491C20 /* main.m */,
171 | );
172 | name = "Supporting Files";
173 | sourceTree = "";
174 | };
175 | /* End PBXGroup section */
176 |
177 | /* Begin PBXHeadersBuildPhase section */
178 | 921A45C01D95870E0040BE3B /* Headers */ = {
179 | isa = PBXHeadersBuildPhase;
180 | buildActionMask = 2147483647;
181 | files = (
182 | 921A45D01D9587300040BE3B /* PFWebViewController.h in Headers */,
183 | 921A45D11D9587440040BE3B /* PFWebViewNavigationHeader.h in Headers */,
184 | 921A45D21D9587440040BE3B /* PFWebViewToolBar.h in Headers */,
185 | );
186 | runOnlyForDeploymentPostprocessing = 0;
187 | };
188 | /* End PBXHeadersBuildPhase section */
189 |
190 | /* Begin PBXNativeTarget section */
191 | 921A45C21D95870E0040BE3B /* PFWebViewControllerFramework */ = {
192 | isa = PBXNativeTarget;
193 | buildConfigurationList = 921A45CE1D95870E0040BE3B /* Build configuration list for PBXNativeTarget "PFWebViewControllerFramework" */;
194 | buildPhases = (
195 | 921A45BE1D95870E0040BE3B /* Sources */,
196 | 921A45BF1D95870E0040BE3B /* Frameworks */,
197 | 921A45C01D95870E0040BE3B /* Headers */,
198 | 921A45C11D95870E0040BE3B /* Resources */,
199 | );
200 | buildRules = (
201 | );
202 | dependencies = (
203 | );
204 | name = PFWebViewControllerFramework;
205 | productName = PFWebViewControllerFramework;
206 | productReference = 921A45C31D95870E0040BE3B /* PFWebViewController.framework */;
207 | productType = "com.apple.product-type.framework";
208 | };
209 | 9287717F1D8FDAF400491C20 /* PFWebViewController */ = {
210 | isa = PBXNativeTarget;
211 | buildConfigurationList = 928771971D8FDAF400491C20 /* Build configuration list for PBXNativeTarget "PFWebViewController" */;
212 | buildPhases = (
213 | 9287717C1D8FDAF400491C20 /* Sources */,
214 | 9287717D1D8FDAF400491C20 /* Frameworks */,
215 | 9287717E1D8FDAF400491C20 /* Resources */,
216 | 921A45CF1D95870E0040BE3B /* Embed Frameworks */,
217 | );
218 | buildRules = (
219 | );
220 | dependencies = (
221 | 921A45C91D95870E0040BE3B /* PBXTargetDependency */,
222 | );
223 | name = PFWebViewController;
224 | productName = PFWebViewController;
225 | productReference = 928771801D8FDAF400491C20 /* PFWebViewController.app */;
226 | productType = "com.apple.product-type.application";
227 | };
228 | /* End PBXNativeTarget section */
229 |
230 | /* Begin PBXProject section */
231 | 928771781D8FDAF400491C20 /* Project object */ = {
232 | isa = PBXProject;
233 | attributes = {
234 | KnownAssetTags = (
235 | PFNavigationController,
236 | );
237 | LastUpgradeCheck = 0800;
238 | ORGANIZATIONNAME = Cee;
239 | TargetAttributes = {
240 | 921A45C21D95870E0040BE3B = {
241 | CreatedOnToolsVersion = 8.0;
242 | ProvisioningStyle = Automatic;
243 | };
244 | 9287717F1D8FDAF400491C20 = {
245 | CreatedOnToolsVersion = 8.0;
246 | DevelopmentTeam = Q8H99663FH;
247 | ProvisioningStyle = Automatic;
248 | };
249 | };
250 | };
251 | buildConfigurationList = 9287717B1D8FDAF400491C20 /* Build configuration list for PBXProject "PFWebViewController" */;
252 | compatibilityVersion = "Xcode 3.2";
253 | developmentRegion = English;
254 | hasScannedForEncodings = 0;
255 | knownRegions = (
256 | en,
257 | Base,
258 | );
259 | mainGroup = 928771771D8FDAF400491C20;
260 | productRefGroup = 928771811D8FDAF400491C20 /* Products */;
261 | projectDirPath = "";
262 | projectRoot = "";
263 | targets = (
264 | 9287717F1D8FDAF400491C20 /* PFWebViewController */,
265 | 921A45C21D95870E0040BE3B /* PFWebViewControllerFramework */,
266 | );
267 | };
268 | /* End PBXProject section */
269 |
270 | /* Begin PBXResourcesBuildPhase section */
271 | 921A45C11D95870E0040BE3B /* Resources */ = {
272 | isa = PBXResourcesBuildPhase;
273 | buildActionMask = 2147483647;
274 | files = (
275 | 921A45D61D9587600040BE3B /* PFWebViewController.bundle in Resources */,
276 | );
277 | runOnlyForDeploymentPostprocessing = 0;
278 | };
279 | 9287717E1D8FDAF400491C20 /* Resources */ = {
280 | isa = PBXResourcesBuildPhase;
281 | buildActionMask = 2147483647;
282 | files = (
283 | 928771931D8FDAF400491C20 /* LaunchScreen.storyboard in Resources */,
284 | 927D6EAC1D9127420066D7BC /* PFWebViewController.bundle in Resources */,
285 | 928771901D8FDAF400491C20 /* Assets.xcassets in Resources */,
286 | 9287718E1D8FDAF400491C20 /* Main.storyboard in Resources */,
287 | );
288 | runOnlyForDeploymentPostprocessing = 0;
289 | };
290 | /* End PBXResourcesBuildPhase section */
291 |
292 | /* Begin PBXSourcesBuildPhase section */
293 | 921A45BE1D95870E0040BE3B /* Sources */ = {
294 | isa = PBXSourcesBuildPhase;
295 | buildActionMask = 2147483647;
296 | files = (
297 | 921A45D31D95875A0040BE3B /* PFWebViewController.m in Sources */,
298 | 921A45D41D95875A0040BE3B /* PFWebViewNavigationHeader.m in Sources */,
299 | 921A45D51D95875A0040BE3B /* PFWebViewToolBar.m in Sources */,
300 | );
301 | runOnlyForDeploymentPostprocessing = 0;
302 | };
303 | 9287717C1D8FDAF400491C20 /* Sources */ = {
304 | isa = PBXSourcesBuildPhase;
305 | buildActionMask = 2147483647;
306 | files = (
307 | 9287718B1D8FDAF400491C20 /* ViewController.m in Sources */,
308 | 928771881D8FDAF400491C20 /* AppDelegate.m in Sources */,
309 | 927D6EAE1D9127420066D7BC /* PFWebViewNavigationHeader.m in Sources */,
310 | 927D6EAF1D9127420066D7BC /* PFWebViewToolBar.m in Sources */,
311 | 928771851D8FDAF400491C20 /* main.m in Sources */,
312 | 927D6EAD1D9127420066D7BC /* PFWebViewController.m in Sources */,
313 | );
314 | runOnlyForDeploymentPostprocessing = 0;
315 | };
316 | /* End PBXSourcesBuildPhase section */
317 |
318 | /* Begin PBXTargetDependency section */
319 | 921A45C91D95870E0040BE3B /* PBXTargetDependency */ = {
320 | isa = PBXTargetDependency;
321 | target = 921A45C21D95870E0040BE3B /* PFWebViewControllerFramework */;
322 | targetProxy = 921A45C81D95870E0040BE3B /* PBXContainerItemProxy */;
323 | };
324 | /* End PBXTargetDependency section */
325 |
326 | /* Begin PBXVariantGroup section */
327 | 9287718C1D8FDAF400491C20 /* Main.storyboard */ = {
328 | isa = PBXVariantGroup;
329 | children = (
330 | 9287718D1D8FDAF400491C20 /* Base */,
331 | );
332 | name = Main.storyboard;
333 | sourceTree = "";
334 | };
335 | 928771911D8FDAF400491C20 /* LaunchScreen.storyboard */ = {
336 | isa = PBXVariantGroup;
337 | children = (
338 | 928771921D8FDAF400491C20 /* Base */,
339 | );
340 | name = LaunchScreen.storyboard;
341 | sourceTree = "";
342 | };
343 | /* End PBXVariantGroup section */
344 |
345 | /* Begin XCBuildConfiguration section */
346 | 921A45CC1D95870E0040BE3B /* Debug */ = {
347 | isa = XCBuildConfiguration;
348 | buildSettings = {
349 | CODE_SIGN_IDENTITY = "";
350 | CURRENT_PROJECT_VERSION = 1;
351 | DEFINES_MODULE = YES;
352 | DEVELOPMENT_TEAM = "";
353 | DYLIB_COMPATIBILITY_VERSION = 1;
354 | DYLIB_CURRENT_VERSION = 1;
355 | DYLIB_INSTALL_NAME_BASE = "@rpath";
356 | INFOPLIST_FILE = PFWebViewControllerFramework/Info.plist;
357 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
358 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
359 | OTHER_CFLAGS = "-fembed-bitcode";
360 | PRODUCT_BUNDLE_IDENTIFIER = io.Cee.PFWebViewControllerFramework;
361 | PRODUCT_MODULE_NAME = PFWebViewController;
362 | PRODUCT_NAME = PFWebViewController;
363 | SKIP_INSTALL = YES;
364 | VERSIONING_SYSTEM = "apple-generic";
365 | VERSION_INFO_PREFIX = "";
366 | };
367 | name = Debug;
368 | };
369 | 921A45CD1D95870E0040BE3B /* Release */ = {
370 | isa = XCBuildConfiguration;
371 | buildSettings = {
372 | CODE_SIGN_IDENTITY = "";
373 | CURRENT_PROJECT_VERSION = 1;
374 | DEFINES_MODULE = YES;
375 | DEVELOPMENT_TEAM = "";
376 | DYLIB_COMPATIBILITY_VERSION = 1;
377 | DYLIB_CURRENT_VERSION = 1;
378 | DYLIB_INSTALL_NAME_BASE = "@rpath";
379 | INFOPLIST_FILE = PFWebViewControllerFramework/Info.plist;
380 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
381 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
382 | OTHER_CFLAGS = "-fembed-bitcode";
383 | PRODUCT_BUNDLE_IDENTIFIER = io.Cee.PFWebViewControllerFramework;
384 | PRODUCT_MODULE_NAME = PFWebViewController;
385 | PRODUCT_NAME = PFWebViewController;
386 | SKIP_INSTALL = YES;
387 | VERSIONING_SYSTEM = "apple-generic";
388 | VERSION_INFO_PREFIX = "";
389 | };
390 | name = Release;
391 | };
392 | 928771951D8FDAF400491C20 /* Debug */ = {
393 | isa = XCBuildConfiguration;
394 | buildSettings = {
395 | ALWAYS_SEARCH_USER_PATHS = NO;
396 | CLANG_ANALYZER_NONNULL = YES;
397 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
398 | CLANG_CXX_LIBRARY = "libc++";
399 | CLANG_ENABLE_MODULES = YES;
400 | CLANG_ENABLE_OBJC_ARC = YES;
401 | CLANG_WARN_BOOL_CONVERSION = YES;
402 | CLANG_WARN_CONSTANT_CONVERSION = YES;
403 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
404 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
405 | CLANG_WARN_EMPTY_BODY = YES;
406 | CLANG_WARN_ENUM_CONVERSION = YES;
407 | CLANG_WARN_INFINITE_RECURSION = YES;
408 | CLANG_WARN_INT_CONVERSION = YES;
409 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
410 | CLANG_WARN_SUSPICIOUS_MOVES = YES;
411 | CLANG_WARN_UNREACHABLE_CODE = YES;
412 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
413 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
414 | COPY_PHASE_STRIP = NO;
415 | DEBUG_INFORMATION_FORMAT = dwarf;
416 | ENABLE_STRICT_OBJC_MSGSEND = YES;
417 | ENABLE_TESTABILITY = YES;
418 | GCC_C_LANGUAGE_STANDARD = gnu99;
419 | GCC_DYNAMIC_NO_PIC = NO;
420 | GCC_NO_COMMON_BLOCKS = YES;
421 | GCC_OPTIMIZATION_LEVEL = 0;
422 | GCC_PREPROCESSOR_DEFINITIONS = (
423 | "DEBUG=1",
424 | "$(inherited)",
425 | );
426 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
427 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
428 | GCC_WARN_UNDECLARED_SELECTOR = YES;
429 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
430 | GCC_WARN_UNUSED_FUNCTION = YES;
431 | GCC_WARN_UNUSED_VARIABLE = YES;
432 | IPHONEOS_DEPLOYMENT_TARGET = 10.0;
433 | MTL_ENABLE_DEBUG_INFO = YES;
434 | ONLY_ACTIVE_ARCH = YES;
435 | SDKROOT = iphoneos;
436 | TARGETED_DEVICE_FAMILY = "1,2";
437 | };
438 | name = Debug;
439 | };
440 | 928771961D8FDAF400491C20 /* Release */ = {
441 | isa = XCBuildConfiguration;
442 | buildSettings = {
443 | ALWAYS_SEARCH_USER_PATHS = NO;
444 | CLANG_ANALYZER_NONNULL = YES;
445 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
446 | CLANG_CXX_LIBRARY = "libc++";
447 | CLANG_ENABLE_MODULES = YES;
448 | CLANG_ENABLE_OBJC_ARC = YES;
449 | CLANG_WARN_BOOL_CONVERSION = YES;
450 | CLANG_WARN_CONSTANT_CONVERSION = YES;
451 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
452 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
453 | CLANG_WARN_EMPTY_BODY = YES;
454 | CLANG_WARN_ENUM_CONVERSION = YES;
455 | CLANG_WARN_INFINITE_RECURSION = YES;
456 | CLANG_WARN_INT_CONVERSION = YES;
457 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
458 | CLANG_WARN_SUSPICIOUS_MOVES = YES;
459 | CLANG_WARN_UNREACHABLE_CODE = YES;
460 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
461 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
462 | COPY_PHASE_STRIP = NO;
463 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
464 | ENABLE_NS_ASSERTIONS = NO;
465 | ENABLE_STRICT_OBJC_MSGSEND = YES;
466 | GCC_C_LANGUAGE_STANDARD = gnu99;
467 | GCC_NO_COMMON_BLOCKS = YES;
468 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
469 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
470 | GCC_WARN_UNDECLARED_SELECTOR = YES;
471 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
472 | GCC_WARN_UNUSED_FUNCTION = YES;
473 | GCC_WARN_UNUSED_VARIABLE = YES;
474 | IPHONEOS_DEPLOYMENT_TARGET = 10.0;
475 | MTL_ENABLE_DEBUG_INFO = NO;
476 | SDKROOT = iphoneos;
477 | TARGETED_DEVICE_FAMILY = "1,2";
478 | VALIDATE_PRODUCT = YES;
479 | };
480 | name = Release;
481 | };
482 | 928771981D8FDAF400491C20 /* Debug */ = {
483 | isa = XCBuildConfiguration;
484 | buildSettings = {
485 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
486 | DEVELOPMENT_TEAM = Q8H99663FH;
487 | INFOPLIST_FILE = PFWebViewController/Info.plist;
488 | IPHONEOS_DEPLOYMENT_TARGET = 9.0;
489 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
490 | PRODUCT_BUNDLE_IDENTIFIER = io.Cee.PFWebViewController;
491 | PRODUCT_NAME = "$(TARGET_NAME)";
492 | VALID_ARCHS = "arm64 armv7 armv7s";
493 | };
494 | name = Debug;
495 | };
496 | 928771991D8FDAF400491C20 /* Release */ = {
497 | isa = XCBuildConfiguration;
498 | buildSettings = {
499 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
500 | DEVELOPMENT_TEAM = Q8H99663FH;
501 | INFOPLIST_FILE = PFWebViewController/Info.plist;
502 | IPHONEOS_DEPLOYMENT_TARGET = 9.0;
503 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
504 | PRODUCT_BUNDLE_IDENTIFIER = io.Cee.PFWebViewController;
505 | PRODUCT_NAME = "$(TARGET_NAME)";
506 | VALID_ARCHS = "arm64 armv7 armv7s";
507 | };
508 | name = Release;
509 | };
510 | /* End XCBuildConfiguration section */
511 |
512 | /* Begin XCConfigurationList section */
513 | 921A45CE1D95870E0040BE3B /* Build configuration list for PBXNativeTarget "PFWebViewControllerFramework" */ = {
514 | isa = XCConfigurationList;
515 | buildConfigurations = (
516 | 921A45CC1D95870E0040BE3B /* Debug */,
517 | 921A45CD1D95870E0040BE3B /* Release */,
518 | );
519 | defaultConfigurationIsVisible = 0;
520 | defaultConfigurationName = Release;
521 | };
522 | 9287717B1D8FDAF400491C20 /* Build configuration list for PBXProject "PFWebViewController" */ = {
523 | isa = XCConfigurationList;
524 | buildConfigurations = (
525 | 928771951D8FDAF400491C20 /* Debug */,
526 | 928771961D8FDAF400491C20 /* Release */,
527 | );
528 | defaultConfigurationIsVisible = 0;
529 | defaultConfigurationName = Release;
530 | };
531 | 928771971D8FDAF400491C20 /* Build configuration list for PBXNativeTarget "PFWebViewController" */ = {
532 | isa = XCConfigurationList;
533 | buildConfigurations = (
534 | 928771981D8FDAF400491C20 /* Debug */,
535 | 928771991D8FDAF400491C20 /* Release */,
536 | );
537 | defaultConfigurationIsVisible = 0;
538 | defaultConfigurationName = Release;
539 | };
540 | /* End XCConfigurationList section */
541 | };
542 | rootObject = 928771781D8FDAF400491C20 /* Project object */;
543 | }
544 |
--------------------------------------------------------------------------------
/Classes/PFWebViewController.bundle/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Reader
8 |
9 |
436 |
460 |
461 |
734 |
735 |
891 |
892 |
893 |
894 |
895 |
896 |
897 |
898 |
899 |
900 |
901 |
--------------------------------------------------------------------------------
/Classes/PFWebViewController.bundle/safari-reader.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2010 Apple Inc. All rights reserved.
3 | */
4 | function articleHeight() {
5 | var e = document.getElementById("article").offsetHeight,
6 | t = parseFloat(getComputedStyle(document.getElementById("article")).marginTop);
7 | return e + 2 * t
8 | }
9 | function smoothScroll(e, t, n, i) {
10 | function a(t, n) {
11 | scrollEventIsSmoothScroll = !0, e.scrollTop = n, setTimeout(function() {
12 | scrollEventIsSmoothScroll = !1
13 | }, 0)
14 | }
15 | const o = 1e3 / 60;
16 | var r = e.scrollTop,
17 | s = r + t,
18 | l = 0,
19 | d = articleHeight() - window.innerHeight;
20 | if (l > s && (s = l), s > d && (s = d), r != s) {
21 | var c = Math.abs(s - r);
22 | if (c < Math.abs(t) && (n = n * c / Math.abs(t)), smoothScrollingAnimator) {
23 | var u = smoothScrollingAnimator.animations[0],
24 | m = u.progress,
25 | g = m > .5 ? 1 - m : m,
26 | h = n / (1 - g),
27 | p = -g * h,
28 | f = s - r,
29 | S = (.5 * f * Math.PI * Math.sin(Math.PI * m), Math.sin(Math.PI / 2 * g)),
30 | C = S * S,
31 | x = (r - s * C) / (1 - C);
32 | return abortSmoothScroll(), smoothScrollingAnimator = new AppleAnimator(h, o, i), smoothScrollingAnimation = new AppleAnimation(x, s, a), smoothScrollingAnimator.addAnimation(smoothScrollingAnimation), void smoothScrollingAnimator.start(p)
33 | }
34 | smoothScrollingAnimator = new AppleAnimator(n, o, i), smoothScrollingAnimation = new AppleAnimation(r, s, a), smoothScrollingAnimator.addAnimation(smoothScrollingAnimation), smoothScrollingAnimator.start()
35 | }
36 | }
37 | function abortSmoothScroll() {
38 | smoothScrollingAnimator.stop(AnimationTerminationCondition.Interrupted), smoothScrollingAnimator = null, smoothScrollingAnimation = null
39 | }
40 | function articleScrolled() {
41 | !scrollEventIsSmoothScroll && smoothScrollingAnimator && abortSmoothScroll()
42 | }
43 | function traverseReaderContent(e, t) {
44 | if (e) {
45 | var n = e.offsetTop,
46 | i = document.createTreeWalker(document.getElementById("article"), NodeFilter.SHOW_ELEMENT, {
47 | acceptNode: function(e) {
48 | var t = e.classList;
49 | return t.contains("page-number") || t.contains("float") || t.contains("page") || t.contains("scrollable") || "HR" === e.tagName || 0 === e.offsetHeight || "inline" === getComputedStyle(e).display || n === e.offsetTop ? NodeFilter.FILTER_SKIP : NodeFilter.FILTER_ACCEPT
50 | }
51 | });
52 | return i.currentNode = e, i[t]()
53 | }
54 | }
55 | function nextReaderContentElement(e) {
56 | return traverseReaderContent(e, "nextNode")
57 | }
58 | function previousReaderContentElement(e) {
59 | return traverseReaderContent(e, "previousNode")
60 | }
61 | function articleTitleElement() {
62 | return document.querySelector("#article .page .title")
63 | }
64 | function keyDown(e) {
65 | var t = !(e.metaKey || e.altKey || e.ctrlKey || e.shiftKey),
66 | n = !e.metaKey && !e.altKey && !e.ctrlKey && e.shiftKey;
67 | switch (e.keyCode) {
68 | case 8:
69 | break;
70 | case 74:
71 | ContentAwareScrollerJS.scroll(ContentAwareNavigationDirection.Down);
72 | break;
73 | case 75:
74 | ContentAwareScrollerJS.scroll(ContentAwareNavigationDirection.Up)
75 | }
76 | }
77 | function getArticleScrollPosition() {
78 | scrollInfo = {}, scrollInfo.version = 1;
79 | var e = document.getElementsByClassName("page");
80 | if (!e.length)
81 | return scrollInfo.pageIndex = 0, scrollInfo;
82 | scrollInfo.pageIndex = e.length - 1;
83 | var t,
84 | n = window.scrollY;
85 | for (t = 0; t < e.length; t++) {
86 | var i = e[t];
87 | if (i.offsetTop + i.offsetHeight >= n) {
88 | scrollInfo.pageIndex = t;
89 | break
90 | }
91 | }
92 | return scrollInfo
93 | }
94 | function restoreInitialArticleScrollPosition() {
95 | var e = document.getElementsByClassName("page"),
96 | t = e[initialScrollPosition.pageIndex];
97 | t && (document.body.scrollTop = t.offsetTop)
98 | }
99 | function restoreInitialArticleScrollPositionIfPossible() {
100 | if (!didRestoreInitialScrollPosition) {
101 | if (!initialScrollPosition)
102 | return void (didRestoreInitialScrollPosition = !0);
103 | var e = document.getElementsByClassName("page-number").length;
104 | initialScrollPosition.pageIndex >= e || (setTimeout(restoreInitialArticleScrollPosition, DelayBeforeRestoringScrollPositionInMs), didRestoreInitialScrollPosition = !0)
105 | }
106 | }
107 | function makeWideElementsScrollable() {
108 | for (var e = document.querySelectorAll("table, pre"), t = e.length, n = 0; t > n; ++n) {
109 | var i = e[n];
110 | if (!i.classList.contains("float") && !i.parentElement.classList.contains("scrollable")) {
111 | var a = document.createElement("div");
112 | i.parentElement.insertBefore(a, i), i.remove(), a.insertBefore(i), a.classList.add("scrollable")
113 | }
114 | }
115 | }
116 | function loadTwitterJavaScript() {
117 | window.twttr = function(e, t, n) {
118 | var i,
119 | a,
120 | o = e.getElementsByTagName(t)[0];
121 | if (!e.getElementById(n))
122 | return a = e.createElement(t), a.id = n, a.src = "https://platform.twitter.com/widgets.js", o.parentNode.insertBefore(a, o), window.twttr || (i = {
123 | _e: [],
124 | ready: function(e) {
125 | i._e.push(e)
126 | }
127 | })
128 | }(document, "script", "twitter-wjs")
129 | }
130 | function richTweetWasCreated(e) {
131 | var t = e.parentNode.querySelector(".simple-tweet");
132 | t.classList.add("hidden")
133 | }
134 | function replaceSimpleTweetsWithRichTweets() {
135 | if (ReaderJS._isJavaScriptEnabled()) {
136 | var e = document.querySelectorAll("[data-reader-tweet-id]"),
137 | t = e.length;
138 | t && (loadTwitterJavaScript(), twttr.ready(function(n) {
139 | for (var i = 0; t > i; ++i) {
140 | var a = e[i];
141 | n.widgets.createTweet(a.getAttribute("data-reader-tweet-id"), a, {
142 | dnt: !0
143 | }).then(richTweetWasCreated)
144 | }
145 | }))
146 | }
147 | }
148 | function prepareTweetsInPrintingMailingFrame(e) {
149 | for (var t = e.querySelectorAll(".tweet-wrapper"), n = t.length, i = 0; n > i; ++i) {
150 | var a = t[i],
151 | o = a.querySelector("iframe");
152 | o && o.remove();
153 | var r = a.querySelector(".simple-tweet");
154 | r && r.classList.remove("hidden")
155 | }
156 | }
157 | function localeForElement(e) {
158 | var t = "en"
159 | return "en" && t.length && "und" !== t ? t : "en"
160 | }
161 | function anchorForURL(e) {
162 | var t = document.createElement("a");
163 | return t.href = e, t
164 | }
165 | function stopExtendingElementBeyondTextColumn(e) {
166 | e.classList.remove("extendsBeyondTextColumn"), e.style.removeProperty("width"), e.style.removeProperty("-webkit-margin-start")
167 | }
168 | function leadingMarginAndPaddingAppliedToElementFromAncestors(e) {
169 | for (var t = 0, n = e.parentElement; n && !n.classList.contains("page");) {
170 | var i = getComputedStyle(n);
171 | t += parseFloat(i["-webkit-padding-start"]) + parseFloat(i["-webkit-margin-start"]), n = n.parentElement
172 | }
173 | return t
174 | }
175 | function extendElementBeyondTextColumn(e, t, n) {
176 | e.classList.add("extendsBeyondTextColumn"), e.style.setProperty("width", t + "px"), e.style.setProperty("-webkit-margin-start", (n - t) / 2 - leadingMarginAndPaddingAppliedToElementFromAncestors(e) + "px")
177 | }
178 | function textSizeIndexIsValid(e) {
179 | return "number" == typeof e && e >= MinTextZoomIndex && MaxTextZoomIndex >= e
180 | }
181 | function monitorMouseDownForPotentialDeactivation(e) {
182 | lastMouseDownWasOutsideOfPaper = e && ReaderAppearanceJS.usesPaperAppearance() && !document.getElementById("article").contains(e.target)
183 | }
184 | function deactivateIfEventIsOutsideOfPaperContainer(e) {
185 | lastMouseDownWasOutsideOfPaper && e && ReaderAppearanceJS.usesPaperAppearance() && !document.getElementById("article").contains(e.target) && (ReaderJS.readerWillEnterBackground())
186 | }
187 | function updatePageNumbers() {
188 | for (var e = document.getElementsByClassName("page-number"), t = e.length, n = ReaderJS.isLoadingNextPage(), i = 0; t > i; ++i)
189 | n ? e[i].textContent = getLocalizedString("Page %@").format(i + 1) : e[i].textContent = getLocalizedString("Page %@ of %@").format(i + 1, t)
190 | }
191 | function incomingPagePlaceholder() {
192 | return document.getElementById("incoming-page-placeholder")
193 | }
194 | function addIncomingPagePlaceholder(e) {
195 | var t = document.createElement("div");
196 | t.className = "page", t.id = "incoming-page-placeholder";
197 | var n = document.createElement("div");
198 | n.id = "incoming-page-corner";
199 | var i = document.createElement("div");
200 | i.id = "incoming-page-text", i.innerText = getLocalizedString(e ? "Loading Next Page\u2026" : "Connect to the Internet to view remaining pages."), n.appendChild(i), t.appendChild(n), document.getElementById("article").appendChild(t)
201 | }
202 | function removeIncomingPagePlaceholder() {
203 | var e = incomingPagePlaceholder();
204 | e.parentNode.removeChild(e)
205 | }
206 | function nextPageContainer() {
207 | return document.getElementById("next-page-container")
208 | }
209 | function getLocalizedString(e) {
210 | var t = "";
211 | return t ? t : e
212 | }
213 | function nextPageLoadComplete() {
214 | return null
215 | }
216 | function contentElementTouchingTopOfViewport() {
217 | var e = articleTitleElement();
218 | do {
219 | var t = e.getBoundingClientRect();
220 | if (t.top <= 0 && t.bottom >= 0)
221 | return e
222 | } while (e = nextReaderContentElement(e));
223 | return null
224 | }
225 | var LoadNextPageDelay = 250,
226 | MaxNumberOfNextPagesToLoad = 80,
227 | ReaderOperationMode = {
228 | Normal: 0,
229 | OffscreenFetching: 1,
230 | ArchiveViewing: 2
231 | },
232 | DelayBeforeRestoringScrollPositionInMs = 1e3;
233 | String.prototype.format = function() {
234 | for (var e = this.split("%@"), t = 0, n = arguments.length; n > t; ++t)
235 | e.splice(2 * t + 1, 0, arguments[t].toString());
236 | return e.join("")
237 | };
238 | var AnimationTerminationCondition = {
239 | Interrupted: 0,
240 | CompletedSuccessfully: 1
241 | };
242 | AppleAnimator = function(e, t, n) {
243 | this.startTime = 0, this.duration = e, this.interval = t, this.animations = [], this.animationFinishedCallback = n, this.currentFrameRequestID = null, this._firstTime = !0;
244 | var i = this;
245 | this.animate = function() {
246 | function e(e, t, n) {
247 | return t > e ? t : e > n ? n : e
248 | }
249 | var t,
250 | n,
251 | a,
252 | o,
253 | n = (new Date).getTime(),
254 | r = i.duration;
255 | t = e(n - i.startTime, 0, r), n = t / r, a = .5 - .5 * Math.cos(Math.PI * n), o = t >= r;
256 | for (var s = i.animations, l = s.length, d = i._firstTime, c = 0; l > c; ++c)
257 | s[c].doFrame(i, a, d, o, n);
258 | return o ? void i.stop(AnimationTerminationCondition.CompletedSuccessfully) : (i._firstTime = !1, void (this.currentFrameRequestID = requestAnimationFrame(i.animate)))
259 | }
260 | }, AppleAnimator.prototype = {
261 | start: function(e) {
262 | var t = (new Date).getTime(),
263 | n = this.interval;
264 | this.startTime = t - n, e && (this.startTime += e), this.currentFrameRequestID = requestAnimationFrame(this.animate)
265 | },
266 | stop: function(e) {
267 | this.animationFinishedCallback && this.animationFinishedCallback(e), this.currentFrameRequestID && cancelAnimationFrame(this.currentFrameRequestID)
268 | },
269 | addAnimation: function(e) {
270 | this.animations[this.animations.length] = e
271 | }
272 | }, AppleAnimation = function(e, t, n) {
273 | this.from = e, this.to = t, this.callback = n, this.now = e, this.ease = 0, this.progress = 0
274 | }, AppleAnimation.prototype = {
275 | doFrame: function(e, t, n, i, a) {
276 | var o;
277 | o = i ? this.to : this.from + (this.to - this.from) * t, this.now = o, this.ease = t, this.progress = a, this.callback(e, o, n, i)
278 | }
279 | };
280 | var scrollEventIsSmoothScroll = !1,
281 | smoothScrollingAnimator,
282 | smoothScrollingAnimation;
283 | window.addEventListener("scroll", articleScrolled, !1);
284 | const ContentAwareNavigationMarker = "reader-content-aware-navigation-marker",
285 | ContentAwareNavigationAnimationDuration = 200,
286 | ContentAwareNavigationElementOffset = 8,
287 | ContentAwareNavigationDirection = {
288 | Up: 0,
289 | Down: 1
290 | };
291 | ContentAwareScroller = function() {
292 | this._numberOfContentAwareScrollAnimationsInProgress = 0
293 | }, ContentAwareScroller.prototype = {
294 | _contentElementAtTopOfViewport: function() {
295 | var e = articleTitleElement();
296 | do if (!(e.getBoundingClientRect().top < ContentAwareNavigationElementOffset))
297 | return e;
298 | while (e = nextReaderContentElement(e));
299 | return null
300 | },
301 | _clearTargetOfContentAwareScrolling: function() {
302 | var e = document.getElementById(ContentAwareNavigationMarker);
303 | e && e.removeAttribute("id")
304 | },
305 | _contentAwareScrollFinished: function(e) {
306 | e === AnimationTerminationCondition.CompletedSuccessfully && (--this._numberOfContentAwareScrollAnimationsInProgress, this._numberOfContentAwareScrollAnimationsInProgress || (smoothScrollingAnimator = null, smoothScrollingAnimation = null, this._clearTargetOfContentAwareScrolling()))
307 | },
308 | scroll: function(e) {
309 | var t,
310 | n,
311 | i = document.getElementById(ContentAwareNavigationMarker),
312 | a = i || this._contentElementAtTopOfViewport();
313 | if (e === ContentAwareNavigationDirection.Down) {
314 | var o = Math.abs(a.getBoundingClientRect().top - ContentAwareNavigationElementOffset) < 1;
315 | t = i || o ? nextReaderContentElement(a) : a
316 | } else if (e === ContentAwareNavigationDirection.Up)
317 | if (a === articleTitleElement()) {
318 | if (0 === document.body.scrollTop)
319 | return;
320 | n = -1 * document.body.scrollTop
321 | } else
322 | t = previousReaderContentElement(a);
323 | t && (n = t.getBoundingClientRect().top - ContentAwareNavigationElementOffset), ++this._numberOfContentAwareScrollAnimationsInProgress, smoothScroll(document.body, n, ContentAwareNavigationAnimationDuration, this._contentAwareScrollFinished.bind(this)), this._clearTargetOfContentAwareScrolling(), t && (t.id = ContentAwareNavigationMarker)
324 | }
325 | }, window.addEventListener("keydown", keyDown, !1);
326 | var didRestoreInitialScrollPosition = !1,
327 | initialScrollPosition;
328 | const DefaultFontSizes = [15, 16, 17, 18, 19, 20, 21, 23, 26, 28, 37, 46],
329 | DefaultLineHeights = ["25px", "26px", "27px", "28px", "29px", "30px", "31px", "33px", "37px", "39px", "51px", "62px"],
330 | FontSettings = {
331 | System: {
332 | fontSizes: DefaultFontSizes,
333 | lineHeights: ["25px", "26px", "27px", "29px", "30px", "31px", "32px", "33px", "38px", "39px", "51px", "62px"],
334 | cssClassName: "system"
335 | },
336 | Athelas: {
337 | fontSizes: DefaultFontSizes,
338 | lineHeights: DefaultLineHeights,
339 | cssClassName: "athelas"
340 | },
341 | Charter: {
342 | fontSizes: DefaultFontSizes,
343 | lineHeights: ["25px", "26px", "27px", "28px", "29px", "30px", "32px", "34px", "38px", "39px", "51px", "62px"],
344 | cssClassName: "charter"
345 | },
346 | Georgia: {
347 | fontSizes: DefaultFontSizes,
348 | lineHeights: ["25px", "26px", "27px", "28px", "29px", "30px", "32px", "34px", "38px", "41px", "51px", "62px"],
349 | cssClassName: "georgia"
350 | },
351 | "Iowan Old Style": {
352 | fontSizes: DefaultFontSizes,
353 | lineHeights: ["25px", "26px", "27px", "28px", "29px", "30px", "32px", "34px", "38px", "39px", "51px", "62px"],
354 | cssClassName: "iowan"
355 | },
356 | Palatino: {
357 | fontSizes: DefaultFontSizes,
358 | lineHeights: ["25px", "26px", "27px", "28px", "29px", "30px", "31px", "34px", "37px", "40px", "51px", "62px"],
359 | cssClassName: "palatino"
360 | },
361 | Seravek: {
362 | fontSizes: DefaultFontSizes,
363 | lineHeights: ["25px", "26px", "27px", "28px", "28px", "30px", "31px", "34px", "37px", "39px", "51px", "62px"],
364 | cssClassName: "seravek"
365 | },
366 | "Times New Roman": {
367 | fontSizes: DefaultFontSizes,
368 | lineHeights: DefaultLineHeights,
369 | cssClassName: "times"
370 | },
371 | "Hiragino Sans W3": {
372 | fontSizes: DefaultFontSizes,
373 | lineHeights: DefaultLineHeights,
374 | cssClassName: "hiraginosans"
375 | },
376 | "Hiragino Kaku Gothic ProN": {
377 | fontSizes: DefaultFontSizes,
378 | lineHeights: DefaultLineHeights,
379 | cssClassName: "hiraginokaku"
380 | },
381 | "Hiragino Mincho ProN": {
382 | fontSizes: DefaultFontSizes,
383 | lineHeights: DefaultLineHeights,
384 | cssClassName: "hiraginomincho"
385 | },
386 | "Hiragino Maru Gothic ProN": {
387 | fontSizes: DefaultFontSizes,
388 | lineHeights: DefaultLineHeights,
389 | cssClassName: "hiraginomaru"
390 | },
391 | "PingFang SC": {
392 | fontSizes: DefaultFontSizes,
393 | lineHeights: DefaultLineHeights,
394 | cssClassName: "pingfangsc"
395 | },
396 | "Heiti SC": {
397 | fontSizes: DefaultFontSizes,
398 | lineHeights: DefaultLineHeights,
399 | cssClassName: "heitisc"
400 | },
401 | "Songti SC": {
402 | fontSizes: DefaultFontSizes,
403 | lineHeights: DefaultLineHeights,
404 | cssClassName: "songtisc"
405 | },
406 | "Kaiti SC": {
407 | fontSizes: DefaultFontSizes,
408 | lineHeights: DefaultLineHeights,
409 | cssClassName: "kaitisc"
410 | },
411 | "Yuanti SC": {
412 | fontSizes: DefaultFontSizes,
413 | lineHeights: DefaultLineHeights,
414 | cssClassName: "yuantisc"
415 | },
416 | "PingFang TC": {
417 | fontSizes: DefaultFontSizes,
418 | lineHeights: DefaultLineHeights,
419 | cssClassName: "pingfangtc"
420 | },
421 | "Heiti TC": {
422 | fontSizes: DefaultFontSizes,
423 | lineHeights: DefaultLineHeights,
424 | cssClassName: "heititc"
425 | },
426 | "Songti TC": {
427 | fontSizes: DefaultFontSizes,
428 | lineHeights: DefaultLineHeights,
429 | cssClassName: "songtitc"
430 | },
431 | "Kaiti TC": {
432 | fontSizes: DefaultFontSizes,
433 | lineHeights: DefaultLineHeights,
434 | cssClassName: "kaititc"
435 | },
436 | "Yuanti TC": {
437 | fontSizes: DefaultFontSizes,
438 | lineHeights: DefaultLineHeights,
439 | cssClassName: "yuantitc"
440 | },
441 | "Apple SD Gothic Neo": {
442 | fontSizes: DefaultFontSizes,
443 | lineHeights: DefaultLineHeights,
444 | cssClassName: "applesdgothicneo"
445 | },
446 | NanumMyeongjo: {
447 | fontSizes: DefaultFontSizes,
448 | lineHeights: DefaultLineHeights,
449 | cssClassName: "nanummyeongjo"
450 | },
451 | "Khmer Sangam MN": {
452 | fontSizes: DefaultFontSizes,
453 | lineHeights: DefaultLineHeights,
454 | cssClassName: "khmersangammn"
455 | },
456 | "Lao Sangam MN": {
457 | fontSizes: DefaultFontSizes,
458 | lineHeights: DefaultLineHeights,
459 | cssClassName: "laosangam"
460 | },
461 | Thonburi: {
462 | fontSizes: DefaultFontSizes,
463 | lineHeights: DefaultLineHeights,
464 | cssClassName: "thonburi"
465 | },
466 | Damascus: {
467 | fontSizes: DefaultFontSizes,
468 | lineHeights: DefaultLineHeights,
469 | cssClassName: "damascus"
470 | },
471 | Kefa: {
472 | fontSizes: DefaultFontSizes,
473 | lineHeights: DefaultLineHeights,
474 | cssClassName: "kefa"
475 | },
476 | "Arial Hebrew": {
477 | fontSizes: DefaultFontSizes,
478 | lineHeights: DefaultLineHeights,
479 | cssClassName: "arialhebrew"
480 | },
481 | Mshtakan: {
482 | fontSizes: DefaultFontSizes,
483 | lineHeights: DefaultLineHeights,
484 | cssClassName: "mshtakan"
485 | },
486 | "Plantagenet Cherokee": {
487 | fontSizes: DefaultFontSizes,
488 | lineHeights: DefaultLineHeights,
489 | cssClassName: "plantagenetcherokee"
490 | },
491 | "Euphemia UCAS": {
492 | fontSizes: DefaultFontSizes,
493 | lineHeights: DefaultLineHeights,
494 | cssClassName: "euphemiaucas"
495 | },
496 | "Kohinoor Bangla": {
497 | fontSizes: DefaultFontSizes,
498 | lineHeights: DefaultLineHeights,
499 | cssClassName: "kohinoorbangla"
500 | },
501 | "Bangla Sangam MN": {
502 | fontSizes: DefaultFontSizes,
503 | lineHeights: DefaultLineHeights,
504 | cssClassName: "banglasangammn"
505 | },
506 | "Gujarati Sangam MN": {
507 | fontSizes: DefaultFontSizes,
508 | lineHeights: DefaultLineHeights,
509 | cssClassName: "gujarati"
510 | },
511 | "Gurmukhi MN": {
512 | fontSizes: DefaultFontSizes,
513 | lineHeights: DefaultLineHeights,
514 | cssClassName: "gurmukhi"
515 | },
516 | "Kohinoor Devanagari": {
517 | fontSizes: DefaultFontSizes,
518 | lineHeights: DefaultLineHeights,
519 | cssClassName: "kohinoordevanagari"
520 | },
521 | "ITF Devanagari": {
522 | fontSizes: DefaultFontSizes,
523 | lineHeights: DefaultLineHeights,
524 | cssClassName: "itfdevanagari"
525 | },
526 | "Kannada Sangam MN": {
527 | fontSizes: DefaultFontSizes,
528 | lineHeights: DefaultLineHeights,
529 | cssClassName: "kannada"
530 | },
531 | "Malayalam Sangam MN": {
532 | fontSizes: DefaultFontSizes,
533 | lineHeights: DefaultLineHeights,
534 | cssClassName: "malayalam"
535 | },
536 | "Oriya Sangam MN": {
537 | fontSizes: DefaultFontSizes,
538 | lineHeights: DefaultLineHeights,
539 | cssClassName: "oriya"
540 | },
541 | "Sinhala Sangam MN": {
542 | fontSizes: DefaultFontSizes,
543 | lineHeights: DefaultLineHeights,
544 | cssClassName: "sinhala"
545 | },
546 | InaiMathi: {
547 | fontSizes: DefaultFontSizes,
548 | lineHeights: DefaultLineHeights,
549 | cssClassName: "inaimathi"
550 | },
551 | "Tamil Sangam MN": {
552 | fontSizes: DefaultFontSizes,
553 | lineHeights: DefaultLineHeights,
554 | cssClassName: "tamil"
555 | },
556 | "Kohinoor Telugu": {
557 | fontSizes: DefaultFontSizes,
558 | lineHeights: DefaultLineHeights,
559 | cssClassName: "Kohinoor Telugu"
560 | },
561 | "Telugu Sangam MN": {
562 | fontSizes: DefaultFontSizes,
563 | lineHeights: DefaultLineHeights,
564 | cssClassName: "telugu"
565 | }
566 | },
567 | ThemeSettings = {
568 | White: {
569 | cssClassName: "white"
570 | },
571 | Gray: {
572 | cssClassName: "gray"
573 | },
574 | Sepia: {
575 | cssClassName: "sepia"
576 | },
577 | Night: {
578 | cssClassName: "night"
579 | }
580 | },
581 | ConfigurationVersion = 4,
582 | ShouldSaveConfiguration = {
583 | No: !1,
584 | Yes: !0
585 | },
586 | ShouldRestoreReadingPosition = {
587 | No: !1,
588 | Yes: !0
589 | },
590 | MinTextZoomIndex = 0,
591 | MaxTextZoomIndex = 11,
592 | MaximumWidthOfImageExtendingBeyondTextContainer = 1050,
593 | ReaderConfigurationJavaScriptEnabledKey = "javaScriptEnabled";
594 | ReaderAppearanceController = function() {
595 | this._defaultTextSizeIndexProducer = function() {
596 | return 3
597 | }, this._readerSizeClassProducer = function() {
598 | return "all"
599 | }, this._shouldUsePaperAppearance = function() {
600 | return this.articleWidth() + 140 < this.documentElementWidth()
601 | }, this._canLayOutContentBeyondMainTextColumn = !0, this._defaultFontFamilyName = "System", this._defaultThemeName = "White", this.configuration = {}, this._textSizeIndex = null, this._fontFamilyName = this._defaultFontFamilyName, this._themeName = this._defaultThemeName
602 | }, ReaderAppearanceController.prototype = {
603 | initialize: function() {
604 | this.applyConfiguration(), /Macintosh/g.test(navigator.userAgent) ? document.body.classList.add("mac") : document.body.classList.add("ios")
605 | },
606 | applyConfiguration: function(e) {
607 | var t = this._validConfigurationAndValidityFromUntrustedConfiguration(e),
608 | n = t[0],
609 | i = t[1],
610 | a = n.fontSizeIndexForSizeClass[this._readerSizeClassProducer()];
611 | textSizeIndexIsValid(a) ? this.setCurrentTextSizeIndex(a, ShouldSaveConfiguration.No) : (this.setCurrentTextSizeIndex(this._defaultTextSizeIndexProducer(), ShouldSaveConfiguration.No), i = !1);
612 | var o = this._locale(),
613 | r = n.fontFamilyNameForLanguageTag[o];
614 | r && FontSettings[r] || (r = this._defaultFontFamilyNameForLanguage(o), i = !1), this.setFontFamily(r, ShouldSaveConfiguration.No), this.setTheme(n.themeName, ShouldSaveConfiguration.No), this.configuration = n, i || this._updateSavedConfiguration()
615 | },
616 | _validConfigurationAndValidityFromUntrustedConfiguration: function(e) {
617 | var t = {
618 | fontSizeIndexForSizeClass: {},
619 | fontFamilyNameForLanguageTag: {},
620 | themeName: null
621 | },
622 | n = !0;
623 | e || (e = {}, n = !1);
624 | var i = (e || {}).version;
625 | (!i || "number" != typeof i || ConfigurationVersion > i) && (e = {}, n = !1);
626 | var a = (e || {}).fontSizeIndexForSizeClass;
627 | if (a && "object" == typeof a)
628 | for (var o in a) {
629 | var r = a[o];
630 | textSizeIndexIsValid(r) ? t.fontSizeIndexForSizeClass[o] = r : n = !1
631 | }
632 | else
633 | n = !1;
634 | var s = e.fontFamilyNameForLanguageTag;
635 | s && "object" == typeof s ? t.fontFamilyNameForLanguageTag = s : (t.fontFamilyNameForLanguageTag = {}, n = !1);
636 | var l = e.themeName;
637 | return l && "string" == typeof l && ThemeSettings[l] ? t.themeName = l : (t.themeName = this._defaultThemeName, n = !1), [t, n]
638 | },
639 | _updateSavedConfiguration: function() {
640 | this.configuration.fontSizeIndexForSizeClass[this._readerSizeClassProducer()] = this._textSizeIndex, this.configuration.fontFamilyNameForLanguageTag[this._locale()] = this._fontFamilyName, this.configuration.themeName = this._themeName;
641 | var e = this.configuration;
642 | e.version = ConfigurationVersion
643 | },
644 | applyAppropriateFontSize: function() {
645 | var e = this.configuration.fontSizeIndexForSizeClass[this._readerSizeClassProducer()];
646 | e && this.setCurrentTextSizeIndex(e, ShouldSaveConfiguration.No)
647 | },
648 | makeTextLarger: function() {
649 | this._textSizeIndex < this._currentFontSettings().fontSizes.length - 1 && this.setCurrentTextSizeIndex(this._textSizeIndex + 1, ShouldSaveConfiguration.Yes)
650 | },
651 | makeTextSmaller: function() {
652 | this._textSizeIndex > 0 && this.setCurrentTextSizeIndex(this._textSizeIndex - 1, ShouldSaveConfiguration.Yes)
653 | },
654 | articleWidth: function() {
655 | return document.getElementById("article").getBoundingClientRect().width
656 | },
657 | _textColumnWidthInPoints: function() {
658 | return parseFloat(getComputedStyle(document.querySelector("#article .page")).width)
659 | },
660 | documentElementWidth: function() {
661 | return document.documentElement.clientWidth
662 | },
663 | setCurrentTextSizeIndex: function(e, t) {
664 | e !== this._textSizeIndex && (this._textSizeIndex = e, this._rebuildDynamicStyleSheet(), this.layOutContent(), t === ShouldSaveConfiguration.Yes && this._updateSavedConfiguration())
665 | },
666 | currentFontCSSClassName: function() {
667 | return this._currentFontSettings().cssClassName
668 | },
669 | _currentFontSettings: function() {
670 | return FontSettings[this._fontFamilyName]
671 | },
672 | setFontFamily: function(e, t) {
673 | var n = document.body,
674 | i = FontSettings[e];
675 | n.classList.contains(i.cssClassName) || (this._fontFamilyName && n.classList.remove(FontSettings[this._fontFamilyName].cssClassName), n.classList.add(i.cssClassName), this._fontFamilyName = e, this.layOutContent(), t === ShouldSaveConfiguration.Yes && this._updateSavedConfiguration())
676 | },
677 | _theme: function() {
678 | return ThemeSettings[this._themeName]
679 | },
680 | setTheme: function(e, t) {
681 | var n = document.body,
682 | i = ThemeSettings[e];
683 | n.classList.contains(i.cssClassName) || (this._theme() && n.classList.remove(this._theme().cssClassName), n.classList.add(i.cssClassName), this._themeName = e, t === ShouldSaveConfiguration.Yes && this._updateSavedConfiguration())
684 | },
685 | usesPaperAppearance: function() {
686 | return document.documentElement.classList.contains("paper")
687 | },
688 | layOutContent: function(e) {
689 | void 0 === e && (e = ShouldRestoreReadingPosition.Yes), this._shouldUsePaperAppearance() ? document.documentElement.classList.add("paper") : document.documentElement.classList.remove("paper"), makeWideElementsScrollable(), this._canLayOutContentBeyondMainTextColumn && (this._layOutImagesBeyondTextColumn(), this._layOutElementsContainingTextBeyondTextColumn(), this._layOutVideos()), e === ShouldRestoreReadingPosition.Yes && ReadingPositionStabilizerJS.restorePosition()
690 | },
691 | _layOutImagesBeyondTextColumn: function() {
692 | for (var e = this.canLayOutContentMaintainingAspectRatioBeyondTextColumn(), t = article.querySelectorAll("img"), n = t.length, i = 0; n > i; ++i)
693 | this.setImageShouldLayOutBeyondTextColumnIfAppropriate(t[i], e)
694 | },
695 | _layOutElementsContainingTextBeyondTextColumn: function() {
696 | const e = {
697 | PRE: !0,
698 | TABLE: !1
699 | },
700 | t = 22;
701 | for (var n = document.querySelectorAll(".scrollable pre, .scrollable table"), i = n.length, a = 0; i > a; ++a) {
702 | for (var o = n[a], r = o.parentElement, s = r; s; s = s.parentElement)
703 | "BLOCKQUOTE" === s.tagName && s.classList.add("simple");
704 | stopExtendingElementBeyondTextColumn(r);
705 | var l = o.scrollWidth,
706 | d = this._textColumnWidthInPoints();
707 | if (!(d >= l)) {
708 | var c = getComputedStyle(document.querySelector(".page")),
709 | u = 0;
710 | if (e[o.tagName]) {
711 | var m = parseFloat(c["-webkit-padding-start"]) + parseFloat(c["-webkit-margin-start"]);
712 | u = Math.min(m, t)
713 | }
714 | var g = Math.min(l, this._widthAvailableForLayout() - 2 * u);
715 | extendElementBeyondTextColumn(r, g, d)
716 | }
717 | }
718 | },
719 | _layOutVideos: function() {
720 | function e(e) {
721 | return e.src && /^(.+\.)?youtube\.com\.?$/.test(anchorForURL(e.src).hostname)
722 | }
723 | const t = 16 / 9;
724 | for (var n = article.querySelectorAll("iframe"), i = n.length, a = 0; i > a; ++a) {
725 | var o = n[a];
726 | e(o) && (o.style.width = "100%", o.style.height = this._textColumnWidthInPoints() / t + "px")
727 | }
728 | },
729 | canLayOutContentMaintainingAspectRatioBeyondTextColumn: function() {
730 | const e = 700;
731 | if (window.innerHeight >= e)
732 | return !0;
733 | const t = 1.25;
734 | return window.innerWidth / window.innerHeight <= t
735 | },
736 | setImageShouldLayOutBeyondTextColumnIfAppropriate: function(e, t) {
737 | if (t && !e.closest("blockquote, table, .float")) {
738 | var n,
739 | i = this._textColumnWidthInPoints(),
740 | a = parseFloat(e.getAttribute("width"));
741 | n = isNaN(a) ? e.naturalWidth : a;
742 | var o = Math.min(n, Math.min(MaximumWidthOfImageExtendingBeyondTextContainer, this._widthAvailableForLayout()));
743 | if (o > i)
744 | return void extendElementBeyondTextColumn(e, o, i)
745 | }
746 | stopExtendingElementBeyondTextColumn(e)
747 | },
748 | _widthAvailableForLayout: function() {
749 | return this.usesPaperAppearance() ? this.articleWidth() : this.documentElementWidth()
750 | },
751 | _rebuildDynamicStyleSheet: function() {
752 | for (var e = document.getElementById("dynamic-article-content").sheet; e.cssRules.length;)
753 | e.removeRule(0);
754 | var t = this._currentFontSettings().fontSizes[this._textSizeIndex] + "px",
755 | n = this._currentFontSettings().lineHeights[this._textSizeIndex];
756 | e.insertRule("#article { font-size: " + t + "; line-height: " + n + "; }")
757 | },
758 | _locale: function() {
759 | var e = document.getElementById("article").style.webkitLocale;
760 | return e && e.length ? e : ""
761 | },
762 | _defaultFontFamilyNameForLanguage: function(e) {
763 | const t = {
764 | am: "Kefa",
765 | ar: "Damascus",
766 | hy: "Mshtakan",
767 | bn: "Kohinoor Bangla",
768 | chr: "Plantagenet Cherokee",
769 | gu: "Gujarati Sangam MN",
770 | "pa-Guru": "Gurmukhi MN",
771 | he: "Arial Hebrew",
772 | hi: "Kohinoor Devanagari",
773 | ja: "Hiragino Mincho ProN",
774 | kn: "Kannada Sangam MN",
775 | km: "Khmer Sangam MN",
776 | ko: "Apple SD Gothic Neo",
777 | lo: "Lao Sangam MN",
778 | ml: "Malayalam Sangam MN",
779 | or: "Oriya Sangam MN",
780 | si: "Sinhala Sangam MN",
781 | ta: "InaiMathi",
782 | te: "Kohinoor Telugu",
783 | th: "Thonburi",
784 | "zh-Hans": "PingFang SC",
785 | "zh-Hant": "PingFang TC",
786 | "iu-Cans": "Euphemia UCAS"
787 | };
788 | var n = t[e];
789 | return n ? n : this._defaultFontFamilyName
790 | }
791 | };
792 | var lastMouseDownWasOutsideOfPaper = !1;
793 | ReaderController = function() {
794 | this.pageNumber = 1, this.pageURLs = [], this.articleIsLTR = !0, this.loadingNextPage = !1, this.loadingNextPageManuallyStopped = !1, this.cachedNextPageURL = null, this.lastKnownUserVisibleWidth = 0, this.lastKnownDocumentElementWidth = 0, this._readerWillBecomeVisible = function() {}, this._readerWillEnterBackground = function() {}, this._distanceFromBottomOfArticleToStartLoadingNextPage = function() {
795 | return NaN
796 | }, this._shouldRestoreScrollPositionFromOriginalPageAtActivation = !1, this._clickingOutsideOfPaperRectangleDismissesReader = !1, this._shouldSkipActivationWhenPageLoads = function() {
797 | return !1
798 | }, this._shouldConvertRelativeURLsToAbsoluteURLsWhenPrintingOrMailing = !1, this._deferSendingContentIsReadyForDisplay = !1, this._isJavaScriptEnabled = function() {
799 | return !0
800 | }
801 | }, ReaderController.prototype = {
802 | setOriginalURL: function(e) {
803 | this.originalURL = e, this.pageURLs.push(e), document.head.getElementsByTagName("base")[0].href = this.originalURL
804 | },
805 | setNextPageURL: function(e) {
806 | if (!e || -1 !== this.pageURLs.indexOf(e) || this.pageNumber + 1 === MaxNumberOfNextPagesToLoad)
807 | return void this.setLoadingNextPage(!1);
808 | this.setLoadingNextPage(!0), this.pageURLs.push(e);
809 | var t = function() {
810 | nextPageContainer().addEventListener("load", nextPageLoadComplete, !1), nextPageContainer().src = e
811 | };
812 | this.readerOperationMode == ReaderOperationMode.OffscreenFetching ? t() : this.nextPageLoadTimer = setTimeout(t, LoadNextPageDelay)
813 | },
814 | pauseLoadingNextPage: function() {
815 | },
816 | stopLoadingNextPage: function() {
817 | nextPageContainer().removeEventListener("load", nextPageLoadComplete, !1), nextPageContainer().src = null, this.nextPageLoadTimer && clearTimeout(this.nextPageLoadTimer), this.isLoadingNextPage() && (this.setLoadingNextPage(!1), this.loadingNextPageManuallyStopped = !0)
818 | },
819 | isLoadingNextPage: function() {
820 | return this.loadingNextPage
821 | },
822 | setLoadingNextPage: function(e) {
823 | this.loadingNextPage != e && (removeIncomingPagePlaceholder(), this.loadingNextPage = e)
824 | },
825 | doneLoadingAllPages: function() {
826 | },
827 | loaded: function() {
828 | if (!ReaderArticleFinderJS || this._shouldSkipActivationWhenPageLoads())
829 | return null;
830 | if (this.loadArticle(), ReaderAppearanceJS.initialize(), ReadingPositionStabilizerJS.initialize(), this._shouldRestoreScrollPositionFromOriginalPageAtActivation) {
831 | var e = 0;
832 | if (e > 0)
833 | document.body.scrollTop = e;
834 | else {
835 | var t = document.getElementById("safari-reader-element-marker");
836 | if (t) {
837 | var n = parseFloat(t.style.top) / 100,
838 | i = t.parentElement,
839 | a = i.getBoundingClientRect();
840 | document.body.scrollTop = window.scrollY + a.top + a.height * n, i.removeChild(t)
841 | }
842 | }
843 | }
844 | this._clickingOutsideOfPaperRectangleDismissesReader && (document.documentElement.addEventListener("mousedown", monitorMouseDownForPotentialDeactivation), document.documentElement.addEventListener("click", deactivateIfEventIsOutsideOfPaperContainer));
845 | var o = function() {
846 | this.setUserVisibleWidth(this.lastKnownUserVisibleWidth)
847 | }.bind(this);
848 | window.addEventListener("resize", o, !1);
849 |
850 | var article_node = document.getElementById("article");
851 | article_node.firstChild.remove();
852 |
853 | var message = { 'code' : 0 };
854 | window.webkit.messageHandlers.JSController.postMessage(message);
855 | },
856 | setUserVisibleWidth: function(e) {
857 | var t = ReaderAppearanceJS.documentElementWidth();
858 | e === this.lastKnownUserVisibleWidth && t === this.lastKnownDocumentElementWidth || (this.lastKnownUserVisibleWidth = e, this.lastKnownDocumentElementWidth = t, ReaderAppearanceJS.applyAppropriateFontSize(), ReaderAppearanceJS.layOutContent())
859 | },
860 | loadArticle: function() {
861 | var e = ReaderArticleFinderJS;
862 | e.findArticle();
863 | if (e.article || e.articleNode(!0), !e.article)
864 | return this.setOriginalURL(e.contentDocument.baseURI), void this.doneLoadingAllPages();
865 | this.routeToArticle = e.routeToArticleNode(), this.displayTitle = e.articleTitle(), this.displaySubhead = "", this.articleIsLTR = e.articleIsLTR();
866 | var t = e.adoptableArticle().ownerDocument;
867 | if (document.title = t.title, this.setOriginalURL(t.baseURI), this.readerOperationMode == ReaderOperationMode.ArchiveViewing)
868 | return void ReaderAppearanceJS.layOutContent();
869 | var n = e.adoptableArticle();
870 | if (this._isJavaScriptEnabled()) {
871 | var i = e.nextPageURL();
872 | this.setNextPageURL(i)
873 | } else {
874 | for (var a = n.querySelectorAll("iframe"), o = a.length, r = 0; o > r; ++r)
875 | a[r].remove();
876 | this.stopLoadingNextPage()
877 | }
878 | this.updateLocaleFromElement(n), this.createPageFromNode(n), i
879 | },
880 | loadNewArticle: function() {
881 | if (!ReaderArticleFinderJS)
882 | return null;
883 | for (var e = document.getElementById("article"); e.childNodes.length >= 1;)
884 | e.removeChild(e.firstChild);
885 | this.reinitialize(), document.body.scrollTop = 0, this.loadArticle()
886 | },
887 | reinitialize: function() {
888 | this.pageNumber = 1, this.pageURLs = [], this.articleIsLTR = !0, this.loadingNextPage = !1, this.loadingNextPageManuallyStopped = !1, this.routeToArticle = void 0, this.displayTitle = void 0, this.displaySubhead = void 0, this.originalURL = void 0, this.nextPageLoadTimer = void 0, this.cachedNextPageURL = null
889 | },
890 | createPageFromNode: function(e) {
891 | var t = document.createElement("div");
892 | t.className = "page", this.articleIsLTR || t.classList.add("rtl");
893 | var n = document.createElement("div");
894 | n.className = "page-number", t.appendChild(n);
895 | var i = document.createElement("h1");
896 | if (i.className = "title", i.textContent = this.displayTitle, t.appendChild(i), this.displaySubhead) {
897 | var a = document.createElement("h2");
898 | a.className = "subhead", a.textContent = this.displaySubhead, t.appendChild(a)
899 | }
900 | if (this.metadataElement && this.metadataElement.innerText) {
901 | var o = document.createElement("div");
902 | for (o.className = "metadata"; this.metadataElement.firstChild;)
903 | o.appendChild(this.metadataElement.firstChild);
904 | t.appendChild(o)
905 | }
906 | for (; e.firstChild;)
907 | t.appendChild(e.firstChild);
908 | var r = document.getElementById("article");
909 | r.insertBefore(t, incomingPagePlaceholder()), replaceSimpleTweetsWithRichTweets(), ReaderAppearanceJS.layOutContent(ShouldRestoreReadingPosition.No), updatePageNumbers(), restoreInitialArticleScrollPositionIfPossible();
910 | for (var s = t.querySelectorAll("img"), l = s.length, d = 0; l > d; ++d)
911 | s[d].onload = function(e) {
912 | var t = e.target;
913 | ReaderAppearanceJS.setImageShouldLayOutBeyondTextColumnIfAppropriate(t, ReaderAppearanceJS.canLayOutContentMaintainingAspectRatioBeyondTextColumn()), t.onload = null
914 | };
915 | this._fixImageElementsWithinPictureElements()
916 | },
917 | removeAttribute: function(e, t) {
918 | for (var n = e.querySelectorAll("[" + t + "]"), i = n.length, a = 0; i > a; a++)
919 | n[a].removeAttribute(t)
920 | },
921 | preparePrintingMailingFrame: function() {
922 | var e = this.printingMailingFrameElementId(),
923 | t = document.getElementById(e);
924 | t && document.body.removeChild(t), t = document.createElement("iframe"), t.id = e, t.style.display = "none", t.style.position = "absolute", document.body.appendChild(t);
925 | var n = t.contentDocument,
926 | i = document.createElement("base");
927 | i.href = this.originalURL, n.head.appendChild(i);
928 | var a = document.createElement("div");
929 | a.className = "original-url";
930 | var o = document.createElement("a");
931 | o.href = this.originalURL, o.textContent = this.originalURL, a.appendChild(document.createElement("br")), a.appendChild(o), a.appendChild(document.createElement("br")), a.appendChild(document.createElement("br")), n.body.appendChild(a), n.body.appendChild(this.sanitizedFullArticle()), n.head.appendChild(document.getElementById("print").cloneNode(!0));
932 | var r = n.createElement("title");
933 | r.innerText = document.title, n.head.appendChild(r)
934 | },
935 | sanitizedFullArticle: function() {
936 | var e = document.getElementById("article").cloneNode(!0);
937 | e.removeAttribute("tabindex");
938 | for (var t = e.querySelectorAll(".title"), n = 1; n < t.length; ++n)
939 | t[n].remove();
940 | for (var i = e.querySelectorAll(".page-number, #incoming-page-placeholder"), n = 0; n < i.length; ++n)
941 | i[n].remove();
942 | if (prepareTweetsInPrintingMailingFrame(e), this._shouldConvertRelativeURLsToAbsoluteURLsWhenPrintingOrMailing) {
943 | var a = e.querySelectorAll("img, video, audio, source");
944 | const o = /^http:\/\/|^https:\/\/|^data:/i;
945 | for (var n = 0; n < a.length; n++) {
946 | var r = a[n],
947 | s = r.getAttribute("src");
948 | o.test(s) || r.setAttribute("src", r.src)
949 | }
950 | }
951 | for (var l = e.querySelectorAll(".extendsBeyondTextColumn"), d = l.length, n = 0; d > n; ++n)
952 | stopExtendingElementBeyondTextColumn(l[n]);
953 | for (var c = e.querySelectorAll(".delimeter"), u = c.length, n = 0; u > n; ++n)
954 | c[n].innerText = "\u2022";
955 | e.classList.add(ReaderAppearanceJS.currentFontCSSClassName()), e.classList.add("exported");
956 | for (var m = document.getElementById("article-content").sheet.cssRules, g = m.length, h = 0; g > h; ++h) {
957 | var p = m[h].selectorText,
958 | f = m[h].style;
959 | if (f) {
960 | var S = f.cssText;
961 | e.matches(p) && (e.style.cssText += S);
962 | for (var C = e.querySelectorAll(p), x = C.length, v = 0; x > v; ++v)
963 | C[v].style.cssText += S
964 | }
965 | }
966 | return e
967 | },
968 | printingMailingFrameElementId: function() {
969 | return "printing-mailing-frame"
970 | },
971 | updateLocaleFromElement: function(e) {
972 | this._bestLocale = localeForElement(e), document.getElementById("article").style.webkitLocale = "'" + this._bestLocale + "'"
973 | },
974 | canLoadNextPage: function() {
975 | if (this.readerOperationMode != ReaderOperationMode.Normal)
976 | return !0;
977 | var e = document.querySelectorAll(".page"),
978 | t = e[e.length - 1],
979 | n = t.getBoundingClientRect(),
980 | i = this._distanceFromBottomOfArticleToStartLoadingNextPage();
981 | return isNaN(i) ? !0 : !(n.bottom - window.scrollY > i)
982 | },
983 | setCachedNextPageURL: function(e) {
984 | e ? null : this.setNextPageURL(e)
985 | },
986 | loadNextPage: function() {
987 | null != this.cachedNextPageURL && (this.setNextPageURL(this.cachedNextPageURL), this.cachedNextPageURL = null )
988 | },
989 | resumeCachedNextPageLoadIfNecessary: function() {
990 | ReaderJS.cachedNextPageURL && ReaderJS.canLoadNextPage() && ReaderJS.loadNextPage()
991 | },
992 | readerWillBecomeVisible: function() {
993 | document.body.classList.remove("cached"), this.resumeCachedNextPageLoadIfNecessary(), this._readerWillBecomeVisible()
994 | },
995 | readerWillEnterBackground: function() {
996 | (ReaderJS.isLoadingNextPage() || ReaderJS.loadingNextPageManuallyStopped) && this.pauseLoadingNextPage();
997 | for (var e = document.querySelectorAll("audio, video"), t = 0, n = e.length; n > t; ++t)
998 | e[t].pause();
999 | document.body.classList.add("cached"), this._readerWillEnterBackground()
1000 | },
1001 | _fixImageElementsWithinPictureElements: function() {
1002 | setTimeout(function() {
1003 | for (var e = !1, t = document.querySelectorAll("#article picture img"), n = t.length, i = 0; n > i; ++i) {
1004 | var a = t[i],
1005 | o = a.previousElementSibling;
1006 | o && (a.remove(), o.after(a), e = !0)
1007 | }
1008 | e && ReaderAppearanceJS.layOutContent()
1009 | }, 0)
1010 | }
1011 | }, ReadingPositionStabilizer = function() {
1012 | this.elementTouchingTopOfViewport = null, this.elementTouchingTopOfViewportOffsetFromTopOfElementRatio = 0
1013 | }, ReadingPositionStabilizer.prototype = {
1014 | initialize: function() {
1015 | this.setTrackPosition(!0)
1016 | },
1017 | setTrackPosition: function(e) {
1018 | this._positionUpdateFunction || (this._positionUpdateFunction = this._updatePosition.bind(this)), e ? window.addEventListener("scroll", this._positionUpdateFunction, !1) : window.removeEventListener("scroll", this._positionUpdateFunction, !1)
1019 | },
1020 | _updatePosition: function() {
1021 | var e = contentElementTouchingTopOfViewport();
1022 | if (!e)
1023 | return void (this.elementTouchingTopOfViewport = null);
1024 | this.elementTouchingTopOfViewport = e;
1025 | var t = this.elementTouchingTopOfViewport.getBoundingClientRect();
1026 | this.elementTouchingTopOfViewportOffsetFromTopOfElementRatio = t.height > 0 ? t.top / t.height : 0
1027 | },
1028 | restorePosition: function() {
1029 | if (this.elementTouchingTopOfViewport) {
1030 | var e = this.elementTouchingTopOfViewport.getBoundingClientRect(),
1031 | t = document.body.scrollTop + e.top - e.height * this.elementTouchingTopOfViewportOffsetFromTopOfElementRatio;
1032 | t > 0 && (document.body.scrollTop = t), this._updatePosition()
1033 | }
1034 | }
1035 | };
1036 | var ContentAwareScrollerJS = new ContentAwareScroller,
1037 | ReaderAppearanceJS = new ReaderAppearanceController,
1038 | ReadingPositionStabilizerJS = new ReadingPositionStabilizer,
1039 | ReaderJS = new ReaderController;
1040 |
--------------------------------------------------------------------------------