Replace LICD filter with Kotlin version, add test
authorDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Sat, 11 Nov 2017 09:37:11 +0000 (10:37 +0100)
committerDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Sat, 11 Nov 2017 09:37:11 +0000 (10:37 +0100)
src/main/java/net/pterodactylus/rhynodge/filters/comics/LeastICouldDoComicFilter.java [deleted file]
src/main/java/net/pterodactylus/rhynodge/watchers/LeastICouldDoWatcher.java
src/main/kotlin/net/pterodactylus/rhynodge/filters/comics/LeastICouldDoComicFilter.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/rhynodge/filters/comics/LeastICouldDoComicFilterTest.kt [new file with mode: 0644]
src/test/resources/net/pterodactylus/rhynodge/filters/comics/least-i-could-do.html [new file with mode: 0644]

diff --git a/src/main/java/net/pterodactylus/rhynodge/filters/comics/LeastICouldDoComicFilter.java b/src/main/java/net/pterodactylus/rhynodge/filters/comics/LeastICouldDoComicFilter.java
deleted file mode 100644 (file)
index d45526a..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * rhynodge - LeastICouldDoComicFilter.java - Copyright © 2013 David Roden
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-package net.pterodactylus.rhynodge.filters.comics;
-
-import java.util.Collections;
-import java.util.List;
-
-import net.pterodactylus.rhynodge.filters.ComicSiteFilter;
-
-import com.google.common.base.Function;
-import com.google.common.base.Optional;
-import com.google.common.collect.FluentIterable;
-import org.jsoup.nodes.Document;
-import org.jsoup.nodes.Element;
-import org.jsoup.select.Elements;
-
-/**
- * {@link ComicSiteFilter} implementation that can parse “Least I Could Do.”
- *
- * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
- */
-public class LeastICouldDoComicFilter extends ComicSiteFilter {
-
-       @Override
-       protected Optional<String> extractTitle(Document document) {
-               return Optional.of("");
-       }
-
-       @Override
-       protected List<String> extractImageUrls(Document document) {
-               Elements imageTag = document.select("#comic-full img");
-               return FluentIterable.from(imageTag).transform(new Function<Element, String>() {
-
-                       @Override
-                       public String apply(Element input) {
-                               return input.attr("src");
-                       }
-               }).toList();
-       }
-
-       @Override
-       protected List<String> extractImageComments(Document document) {
-               return Collections.emptyList();
-       }
-
-}
index 406f1cb..d88f574 100644 (file)
@@ -66,7 +66,7 @@ public class LeastICouldDoWatcher extends DefaultWatcher {
 
                        @Override
                        protected Optional<String> extractUrl(Document document) {
-                               Elements linkTag = document.select("a#feature-comic");
+                               Elements linkTag = document.select("a#latest-comic");
                                return linkTag.hasAttr("href") ? Optional.of(linkTag.attr("href")) : Optional.<String>absent();
                        }
                });
diff --git a/src/main/kotlin/net/pterodactylus/rhynodge/filters/comics/LeastICouldDoComicFilter.kt b/src/main/kotlin/net/pterodactylus/rhynodge/filters/comics/LeastICouldDoComicFilter.kt
new file mode 100644 (file)
index 0000000..4f29a23
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * rhynodge - LeastICouldDoComicFilter.java - Copyright © 2013 David Roden
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.pterodactylus.rhynodge.filters.comics
+
+import com.google.common.base.Optional
+import net.pterodactylus.rhynodge.filters.ComicSiteFilter
+import org.jsoup.nodes.Document
+
+/**
+ * [ComicSiteFilter] implementation that can parse “Least I Could Do.”
+ */
+class LeastICouldDoComicFilter : ComicSiteFilter() {
+
+       override fun extractTitle(document: Document) = Optional.of("")!!
+
+       override fun extractImageUrls(document: Document) =
+                       document.select("#content-comic img.comic")
+                                       .map { it.attr("src") }
+
+       override fun extractImageComments(document: Document) = emptyList<String>()
+
+}
diff --git a/src/test/kotlin/net/pterodactylus/rhynodge/filters/comics/LeastICouldDoComicFilterTest.kt b/src/test/kotlin/net/pterodactylus/rhynodge/filters/comics/LeastICouldDoComicFilterTest.kt
new file mode 100644 (file)
index 0000000..0d88973
--- /dev/null
@@ -0,0 +1,33 @@
+package net.pterodactylus.rhynodge.filters.comics
+
+import net.pterodactylus.rhynodge.filters.ResourceLoader
+import net.pterodactylus.rhynodge.states.ComicState
+import net.pterodactylus.rhynodge.states.ComicState.Comic
+import net.pterodactylus.rhynodge.states.ComicState.Strip
+import net.pterodactylus.rhynodge.states.HtmlState
+import org.hamcrest.MatcherAssert.assertThat
+import org.hamcrest.Matchers.contains
+import org.junit.Test
+
+/**
+ * Unit test for [LeastICouldDoComicFilterTest].
+ */
+class LeastICouldDoComicFilterTest {
+
+       private val filter = LeastICouldDoComicFilter()
+       private val htmlState: HtmlState = ResourceLoader
+                       .loadDocument(javaClass, "least-i-could-do.html", baseUrl)
+                       .let { HtmlState(baseUrl, it) }
+
+       @Test
+       fun `comic is extracted correctly`() {
+               val comicState = filter.filter(htmlState) as ComicState
+               assertThat(comicState.comics(), contains(
+                               Comic("").
+                                               add(Strip("http://leasticoulddo.com/wp-content/uploads/2017/11/528B9685-DA9C-4320-8AC6-C6871DF81C3F.jpeg", ""))
+               ))
+       }
+
+}
+
+private val baseUrl = "http://leasticoulddo.com/comic/20171111"
diff --git a/src/test/resources/net/pterodactylus/rhynodge/filters/comics/least-i-could-do.html b/src/test/resources/net/pterodactylus/rhynodge/filters/comics/least-i-could-do.html
new file mode 100644 (file)
index 0000000..3879937
--- /dev/null
@@ -0,0 +1,595 @@
+<!DOCTYPE html>\r
+<html>\r
+<head>\r
+\r
+            <script src="//cdn.districtm.ca/merge/merge.v4.2.113053.js"></script>\r
+    \r
+       <title>Least I Could Do: the Comic</title>\r
+       <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />\r
+       <meta charset="utf-8" />\r
+       <meta name="description" content="A daily webcomic series about the life of Rayne Summers. Created by Ryan Sohmer and Lar deSouza." /> \r
+       <meta name="keywords" content="webcomic, comic, funny, comedy" /> \r
+       <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=1" />\r
+       <link rel="shortcut icon" href="http://leasticoulddo.com/wp-content/themes/licd2017-105-louay/favicon.ico" />\r
+       <link rel="stylesheet" type="text/css" href="http://leasticoulddo.com/wp-content/themes/licd2017-105-louay/style.css?ver=0010" />\r
+    <link href="https://fonts.googleapis.com/css?family=Oswald:300,400" rel="stylesheet"> \r
+    <meta property="fb:app_id" content="222643084853752" />\r
+    <meta property="fb:admins" content="louay.cheikh.3" />\r
+    <meta property="fb:admins" content="wattar" />\r
+\r
+            <script type='text/javascript'>\r
+\r
+      // gpt\r
+      googletag = typeof googletag === 'undefined' ? {} : googletag;\r
+      googletag.cmd = googletag.cmd || [];\r
+\r
+      // Load gpt library\r
+      (function() {\r
+          var gads = document.createElement('script');\r
+          gads.async = true;\r
+          gads.type = 'text/javascript';\r
+          var useSSL = 'https:' == document.location.protocol;\r
+          gads.src = (useSSL ? 'https:' : 'http:') +\r
+                  '//www.googletagservices.com/tag/js/gpt.js';\r
+          var node = document.getElementsByTagName('script')[0];\r
+          node.parentNode.insertBefore(gads, node);\r
+      })();\r
+\r
+    </script>\r
+\r
+    <script type='text/javascript'>\r
+\r
+      googletag.cmd.push(function() {\r
+\r
+          // // Desktop View Mapping\r
+          window.desktopAdMapping = googletag.sizeMapping().\r
+            addSize([0, 0], []).\r
+            addSize([1050, 200], [1024, 120]).\r
+            build();\r
+\r
+          // // Mobile View Mapping\r
+          window.mobileAdMapping = googletag.sizeMapping().\r
+            addSize([0,0], []).\r
+            addSize([320, 700], [300, 600]).\r
+            addSize([1050, 200], []). // Hide when larger than 1050x200\r
+            build();\r
+\r
+          // DEFINE DFP SLOTS HERE\r
+\r
+          // Leader - Front Page√\r
+          // googletag.defineSlot('/10195872/LICD_Homepage_Leaderboard_Top_728x90', [728, 90], 'div-gpt-ad-1473287030917-0').addService(googletag.pubads());     \r
+          \r
+          // Leader - Sub Page√\r
+          // googletag.defineSlot('/10195872/LICD_ROS_Leaderboard_Top_728x90', [728, 90], 'div-gpt-ad-1473287634333-0').addService(googletag.pubads());\r
+          \r
+          // Leader - New Comic Page√\r
+          // googletag.defineSlot('/10195872/LICD_NewComic_Leaderboard_Top_728x90', [728, 90], 'div-gpt-ad-1473287307484-0').addService(googletag.pubads());\r
+\r
+          // Mini√\r
+         // googletag.defineSlot('/10195872/LICD_House_Mini_235x90', [235, 90], 'div-gpt-ad-1473287723890-0').addService(googletag.pubads());\r
+\r
+          // Half - Front Page√\r
+          // googletag.defineSlot('/10195872/LICD_Homepage_HalfPage_Top_300x600', [[300, 600], [300, 250]], 'div-gpt-ad-1473287132339-0').addService(googletag.pubads());\r
+      \r
+          // Box - Front Page√ \r
+          // googletag.defineSlot('/10195872/LICD_Homepage_MPU_Bottom_300x250', [300, 250], 'div-gpt-ad-1473287181647-0').addService(googletag.pubads());\r
+          \r
+          // Box - Sub Page√\r
+          // googletag.defineSlot('/10195872/LICD_ROS_House_Bottom_300x250', [300, 250], 'div-gpt-ad-1473287677031-0').addService(googletag.pubads());\r
+          \r
+          // Box - New Comic Page√\r
+          // googletag.defineSlot('/10195872/LICD_NewComic_MPU_Bottom_300x250', [300, 250], 'div-gpt-ad-1473287452252-0').addService(googletag.pubads());\r
+\r
+          // Responsive Leader Front Page\r
+          // googletag.defineSlot('/10195872/LICD_Homepage_Mobile_Leaderboard_Top_320x50', [320, 50], 'div-gpt-ad-1485548858808-0').addService(googletag.pubads());\r
+\r
+          googletag.pubads().disableInitialLoad();\r
+          // googletag.pubads().enableSingleRequest();\r
+          googletag.pubads().enableAsyncRendering();\r
+          // googletag.pubads().setForceSafeFrame(true);\r
+          // googletag.pubads().setSafeFrameConfig({\r
+          //     sandbox: true,\r
+          //     allowOverlayExpansion: true,\r
+          //     allowPushExpansion: true\r
+          // });\r
+\r
+          googletag.enableServices();\r
+          \r
+          // cosmjs.cmd.push(function(){\r
+          //     cosmjs.init({setupSlots: false});\r
+          // });\r
+          \r
+      });\r
+\r
+    </script>    \r
+    \r
+<!-- This site is optimized with the Yoast SEO plugin v5.7.1 - https://yoast.com/wordpress/plugins/seo/ -->\r
+<link rel="canonical" href="http://leasticoulddo.com/comic/20171111" />\r
+<meta property="og:locale" content="en_US" />\r
+<meta property="og:type" content="article" />\r
+<meta property="og:title" content="20171111 - Least I Could Do" />\r
+<meta property="og:description" content="Yabba dabba don’t" />\r
+<meta property="og:url" content="http://leasticoulddo.com/comic/20171111" />\r
+<meta property="og:site_name" content="Least I Could Do" />\r
+<meta property="og:image" content="http://leasticoulddo.com/wp-content/uploads/2017/11/528B9685-DA9C-4320-8AC6-C6871DF81C3F.jpeg" />\r
+<meta property="og:image:width" content="3333" />\r
+<meta property="og:image:height" content="1122" />\r
+<meta name="twitter:card" content="summary" />\r
+<meta name="twitter:description" content="Yabba dabba don’t " />\r
+<meta name="twitter:title" content="20171111 - Least I Could Do" />\r
+<meta name="twitter:image" content="http://leasticoulddo.com/wp-content/uploads/2017/11/528B9685-DA9C-4320-8AC6-C6871DF81C3F.jpeg" />\r
+<script type='application/ld+json'>{"@context":"http:\/\/schema.org","@type":"WebSite","@id":"#website","url":"http:\/\/leasticoulddo.com\/","name":"Least I Could Do","potentialAction":{"@type":"SearchAction","target":"http:\/\/leasticoulddo.com\/?s={search_term_string}","query-input":"required name=search_term_string"}}</script>\r
+<!-- / Yoast SEO plugin. -->\r
+\r
+<link rel='dns-prefetch' href='//cdnjs.cloudflare.com' />\r
+<link rel='dns-prefetch' href='//s.w.org' />\r
+<link rel="alternate" type="application/rss+xml" title="Least I Could Do &raquo; 20171111 Comments Feed" href="http://leasticoulddo.com/comic/20171111/feed" />\r
+               <script type="text/javascript">\r
+                       window._wpemojiSettings = {"baseUrl":"https:\/\/s.w.org\/images\/core\/emoji\/2.3\/72x72\/","ext":".png","svgUrl":"https:\/\/s.w.org\/images\/core\/emoji\/2.3\/svg\/","svgExt":".svg","source":{"concatemoji":"http:\/\/leasticoulddo.com\/wp-includes\/js\/wp-emoji-release.min.js?ver=4.8.3"}};\r
+                       !function(a,b,c){function d(a){var b,c,d,e,f=String.fromCharCode;if(!k||!k.fillText)return!1;switch(k.clearRect(0,0,j.width,j.height),k.textBaseline="top",k.font="600 32px Arial",a){case"flag":return k.fillText(f(55356,56826,55356,56819),0,0),b=j.toDataURL(),k.clearRect(0,0,j.width,j.height),k.fillText(f(55356,56826,8203,55356,56819),0,0),c=j.toDataURL(),b!==c&&(k.clearRect(0,0,j.width,j.height),k.fillText(f(55356,57332,56128,56423,56128,56418,56128,56421,56128,56430,56128,56423,56128,56447),0,0),b=j.toDataURL(),k.clearRect(0,0,j.width,j.height),k.fillText(f(55356,57332,8203,56128,56423,8203,56128,56418,8203,56128,56421,8203,56128,56430,8203,56128,56423,8203,56128,56447),0,0),c=j.toDataURL(),b!==c);case"emoji4":return k.fillText(f(55358,56794,8205,9794,65039),0,0),d=j.toDataURL(),k.clearRect(0,0,j.width,j.height),k.fillText(f(55358,56794,8203,9794,65039),0,0),e=j.toDataURL(),d!==e}return!1}function e(a){var c=b.createElement("script");c.src=a,c.defer=c.type="text/javascript",b.getElementsByTagName("head")[0].appendChild(c)}var f,g,h,i,j=b.createElement("canvas"),k=j.getContext&&j.getContext("2d");for(i=Array("flag","emoji4"),c.supports={everything:!0,everythingExceptFlag:!0},h=0;h<i.length;h++)c.supports[i[h]]=d(i[h]),c.supports.everything=c.supports.everything&&c.supports[i[h]],"flag"!==i[h]&&(c.supports.everythingExceptFlag=c.supports.everythingExceptFlag&&c.supports[i[h]]);c.supports.everythingExceptFlag=c.supports.everythingExceptFlag&&!c.supports.flag,c.DOMReady=!1,c.readyCallback=function(){c.DOMReady=!0},c.supports.everything||(g=function(){c.readyCallback()},b.addEventListener?(b.addEventListener("DOMContentLoaded",g,!1),a.addEventListener("load",g,!1)):(a.attachEvent("onload",g),b.attachEvent("onreadystatechange",function(){"complete"===b.readyState&&c.readyCallback()})),f=c.source||{},f.concatemoji?e(f.concatemoji):f.wpemoji&&f.twemoji&&(e(f.twemoji),e(f.wpemoji)))}(window,document,window._wpemojiSettings);\r
+               </script>\r
+               <style type="text/css">\r
+img.wp-smiley,\r
+img.emoji {\r
+       display: inline !important;\r
+       border: none !important;\r
+       box-shadow: none !important;\r
+       height: 1em !important;\r
+       width: 1em !important;\r
+       margin: 0 .07em !important;\r
+       vertical-align: -0.1em !important;\r
+       background: none !important;\r
+       padding: 0 !important;\r
+}\r
+</style>\r
+<link rel='stylesheet' id='taxonomy-image-plugin-public-css'  href='http://leasticoulddo.com/wp-content/plugins/taxonomy-images/css/style.css?ver=0.9.6' type='text/css' media='screen' />\r
+<link rel='stylesheet' id='vsel_style-css'  href='http://leasticoulddo.com/wp-content/plugins/very-simple-event-list/css/vsel-style.css?ver=4.8.3' type='text/css' media='all' />\r
+<script type='text/javascript'>\r
+/* <![CDATA[ */\r
+var ajax_url = "http:\/\/leasticoulddo.com\/wp-admin\/admin-ajax.php";\r
+/* ]]> */\r
+</script>\r
+<script type='text/javascript' src='http://leasticoulddo.com/wp-includes/js/jquery/jquery.js?ver=1.12.4'></script>\r
+<script type='text/javascript' src='http://leasticoulddo.com/wp-includes/js/jquery/jquery-migrate.min.js?ver=1.4.1'></script>\r
+<script type='text/javascript' src='https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.15.0/moment.min.js?ver=4.8.3'></script>\r
+<script type='text/javascript' src='https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.0.10/handlebars.min.js?ver=4.8.3'></script>\r
+<link rel='https://api.w.org/' href='http://leasticoulddo.com/wp-json/' />\r
+<link rel="EditURI" type="application/rsd+xml" title="RSD" href="http://leasticoulddo.com/xmlrpc.php?rsd" />\r
+<link rel="wlwmanifest" type="application/wlwmanifest+xml" href="http://leasticoulddo.com/wp-includes/wlwmanifest.xml" /> \r
+<meta name="generator" content="WordPress 4.8.3" />\r
+<link rel='shortlink' href='http://leasticoulddo.com/?p=20396' />\r
+<link rel="alternate" type="application/json+oembed" href="http://leasticoulddo.com/wp-json/oembed/1.0/embed?url=http%3A%2F%2Fleasticoulddo.com%2Fcomic%2F20171111" />\r
+<link rel="alternate" type="text/xml+oembed" href="http://leasticoulddo.com/wp-json/oembed/1.0/embed?url=http%3A%2F%2Fleasticoulddo.com%2Fcomic%2F20171111&#038;format=xml" />\r
+<script type="text/javascript">\r
+       window._se_plugin_version = '8.1.9';\r
+</script>\r
+<meta name="Comic-Easel" content="1.14" />\r
+<meta name="Referrer" content="http://leasticoulddo.com/" />\r
+<meta property="og:image" content="http://leasticoulddo.com/wp-content/uploads/2017/11/528B9685-DA9C-4320-8AC6-C6871DF81C3F-1024x345.jpg" />\r
+    <script type="text/javascript" src="http://leasticoulddo.com/wp-content/themes/licd2017-105-louay/scripts/jquery-3.2.0.min.js"></script>\r
+    <script type="text/javascript" src="http://leasticoulddo.com/wp-content/themes/licd2017-105-louay/scripts/licd.js"></script>\r
+\r
+    <!-- Google Tag Manager -->\r
+    <script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':\r
+    new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],\r
+    j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=\r
+    'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);\r
+    })(window,document,'script','dataLayer','GTM-N97K248');</script>\r
+    <!-- End Google Tag Manager -->\r
+\r
+</head>\r
+\r
+<body class="comic-template-default single single-comic postid-20396 story-v-for-vasectomy">\r
+\r
+    <!-- Google Tag Manager (noscript) -->\r
+    <noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-N97K248"\r
+    height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>\r
+    <!-- End Google Tag Manager (noscript) -->\r
+\r
+<input type="checkbox" name="menu-state" style="display: none;" id="menu-state" />\r
+<input type="checkbox" name="patreon-menu-state" style="display: none;" id="patreon-menu-state" />\r
+\r
+<div id="header" class="header-full">\r
+\r
+    \r
+        <div id="patreon-header">\r
+<label for=""><a href="https://www.patreon.com/oauth2/authorize?response_type=code&client_id=58d1427cf9f3e2d537c4898b6dbe87f09521f46e6ec1d58d1158362586f1373f&redirect_uri=http://leasticoulddo.com/patreon-login">\r
+        <h1>Login&nbsp; With</h1>\r
+        <h1><img src="http://leasticoulddo.com/wp-content/themes/licd2017-105-louay/images/patreon-logo.png" srcset="http://leasticoulddo.com/wp-content/themes/licd2017-105-louay/images/patreon-logo@2x.png 2x" alt=""> Patreon</h1>\r
+    </a></label>\r
+        </div>\r
+\r
+        <div id="patreon-header-mini">\r
+<label for=""><a href="https://www.patreon.com/oauth2/authorize?response_type=code&client_id=58d1427cf9f3e2d537c4898b6dbe87f09521f46e6ec1d58d1158362586f1373f&redirect_uri=http://leasticoulddo.com/patreon-login"><img src="http://leasticoulddo.com/wp-content/themes/licd2017-105-louay/images/patreon-logo.png" srcset="http://leasticoulddo.com/wp-content/themes/licd2017-105-louay/images/patreon-logo@2x.png 2x" alt=""> Login</a></label>\r
+        </div>\r
+\r
+    \r
+    <a href="https://shop.blindferret.com/collections/least-i-could-do" id="header-shop"><img width="280" height="152" src="http://leasticoulddo.com/wp-content/uploads/2017/07/header-shop-graphic.jpg" class="image wp-image-19023  attachment-full size-full" alt="" style="max-width: 100%; height: auto;" srcset="http://leasticoulddo.com/wp-content/uploads/2017/07/header-shop-graphic.jpg 280w, http://leasticoulddo.com/wp-content/uploads/2017/07/header-shop-graphic-150x81.jpg 150w" sizes="(max-width: 280px) 100vw, 280px" />LICD<span>SHOP</span></a>\r
+    <label for="menu-state"><div id="header-menu-button" class="menu-off"></div></label>\r
+    <h1 id="logo"><a href="/">Least I Could Do</a></h1>\r
+</div>\r
+    \r
+<div id="menu">\r
+    <div id="menu-scroll">\r
+        <div id="menu-list">\r
+            <div id="menu-head">Menu</div>\r
+            <div class="menu-header-container"><ul id="menu-header" class="menu"><li id="menu-item-19002" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-home menu-item-19002"><a href="http://leasticoulddo.com/">Home</a></li>\r
+<li id="menu-item-19012" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-19012"><a href="http://leasticoulddo.com/new-readers">New Readers</a></li>\r
+<li id="menu-item-19004" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-19004"><a href="http://leasticoulddo.com/archive">Archive</a></li>\r
+<li id="menu-item-19007" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-19007"><a href="http://leasticoulddo.com/extras">Extras</a></li>\r
+<li id="menu-item-19009" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-19009"><a href="http://leasticoulddo.com/books">Books</a></li>\r
+<li id="menu-item-19689" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-19689"><a href="http://shop.blindferret.com/collections/least-i-could-do">Shop</a></li>\r
+<li id="menu-item-19011" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-19011"><a href="http://leasticoulddo.com/mobile-apps">Mobile Apps</a></li>\r
+<li id="menu-item-19770" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-19770"><a href="http://leasticoulddo.com/events">Upcoming Events</a></li>\r
+<li id="menu-item-19771" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-19771"><a href="http://leasticoulddo.com/social-media">Social Media</a></li>\r
+<li id="menu-item-19006" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-19006"><a href="http://leasticoulddo.com/contact">Contact Us</a></li>\r
+</ul></div>            <div class="menu-footer">                       <div class="textwidget"><p><a href="https://www.facebook.com/pages/Rayne-Summers/140632490460" target="_blank" rel="noopener"><img src="http://beta.leasticoulddo.com/wp-content/uploads/2017/09/facebook-small.jpg" width="30" height="30" /></a> <a href="https://twitter.com/blindferret" target="_blank" rel="noopener"><img src="http://beta.leasticoulddo.com/wp-content/uploads/2017/09/twitter-small.jpg" width="30" height="30" /></a> <a href="https://www.instagram.com/sohmer/" target="_blank" rel="noopener"><img src="http://beta.leasticoulddo.com/wp-content/uploads/2017/09/instagram-small.jpg" width="30" height="30" /></a> <a href="https://www.youtube.com/user/blindferretent" target="_blank" rel="noopener"><img src="http://beta.leasticoulddo.com/wp-content/uploads/2017/09/youtube-small.jpg" width="30" height="30" /></a></p>\r
+</div>\r
+               </div><div class="menu-footer">                 <div class="textwidget"><p>©2017 <a href="http://www.blindferret.com/" target="_blank" rel="noopener">Blind Ferret</a>.<br />\r
+<a href="/privacy-policy">Privacy Policy</a>. <a href="http://feeds.feedburner.com/LICD" target="_blank" rel="noopener">RSS Feed</a>.</p>\r
+</div>\r
+               </div>        </div>\r
+    </div>\r
+</div>\r
+\r
+\r
+\r
+<div id="sidenav" class="sidenav-comicpage">\r
+    <div id="sidenav-scroll">\r
+        <div id="sidenav-menu">\r
+            \r
+            <div id="sidenav-header">\r
+                Storyline Progress\r
+            </div>\r
+            \r
+                            <div class="sidenav-comic" id="nav-321" onClick="location.href='http://leasticoulddo.com/comic/20170828'" data-id="321" data-count="6">\r
+                    <div class="sidenav-selector"><div class="sidenav-progress"\r
+                                                    style="height: 100%"\r
+                                                ></div></div>\r
+                    <div class="sidenav-thumb"><img src="/wp-content/uploads/2017/09/half.jpg" alt="Going Halfsies">Going Halfsies</div>\r
+                </div>\r
+                            <div class="sidenav-comic" id="nav-322" onClick="location.href='http://leasticoulddo.com/comic/20170904'" data-id="322" data-count="13">\r
+                    <div class="sidenav-selector"><div class="sidenav-progress"\r
+                                                    style="height: 100%"\r
+                                                ></div></div>\r
+                    <div class="sidenav-thumb"><img src="/wp-content/uploads/2017/09/inv.jpg" alt="Impulse Investing">Impulse Investing</div>\r
+                </div>\r
+                            <div class="sidenav-comic" id="nav-323" onClick="location.href='http://leasticoulddo.com/comic/20170919'" data-id="323" data-count="5">\r
+                    <div class="sidenav-selector"><div class="sidenav-progress"\r
+                                                    style="height: 100%"\r
+                                                ></div></div>\r
+                    <div class="sidenav-thumb"><img src="/wp-content/uploads/2017/09/noel.jpg" alt="Catching Up With Noel">Catching Up With Noel</div>\r
+                </div>\r
+                            <div class="sidenav-comic" id="nav-324" onClick="location.href='http://leasticoulddo.com/comic/20170925'" data-id="324" data-count="6">\r
+                    <div class="sidenav-selector"><div class="sidenav-progress"\r
+                                                    style="height: 100%"\r
+                                                ></div></div>\r
+                    <div class="sidenav-thumb"><img src="/wp-content/uploads/2017/09/pot.jpg" alt="Pot and Kettle">Pot and Kettle</div>\r
+                </div>\r
+                            <div class="sidenav-comic" id="nav-325" onClick="location.href='http://leasticoulddo.com/comic/20171002'" data-id="325" data-count="30">\r
+                    <div class="sidenav-selector"><div class="sidenav-progress"\r
+                                                    style="height: 100%"\r
+                                                ></div></div>\r
+                    <div class="sidenav-thumb"><img src="/wp-content/uploads/2017/10/introducing_carter.jpg" alt="Introducing Carter">Introducing Carter</div>\r
+                </div>\r
+                            <div class="sidenav-comic" id="nav-326" onClick="location.href='http://leasticoulddo.com/comic/20171106'" data-id="326" data-count="6">\r
+                    <div class="sidenav-selector"><div class="sidenav-progress"\r
+                                                    style="height: 16.666666666667%"\r
+                                                ></div></div>\r
+                    <div class="sidenav-thumb"><img src="/wp-content/uploads/2017/11/v-for-vasectomy-storyline-thumbnail.jpg" alt="V for Vasectomy">V for Vasectomy</div>\r
+                </div>\r
+                        \r
+            <div class="storyline-thumbs-end">&nbsp;</div>\r
+            \r
+        </div>  \r
+    </div>\r
+</div>\r
+\r
+<div id="content-comic-wrap">\r
+    <div id="content-comic">\r
+\r
+        \r
+<div id="comic-20396" data-id="20396" data-title="20171111">\r
+    \r
+<div class="comic-wrap comic-responsive">\r
+    <img class="comic" src="http://leasticoulddo.com/wp-content/uploads/2017/11/528B9685-DA9C-4320-8AC6-C6871DF81C3F.jpeg" />\r
+    <div class="comicrames">\r
+        <div class="comic-frame1" style="background-image: url('http://leasticoulddo.com/wp-content/uploads/2017/11/528B9685-DA9C-4320-8AC6-C6871DF81C3F.jpeg');"></div>\r
+        <div class="comic-frame2" style="background-image: url('http://leasticoulddo.com/wp-content/uploads/2017/11/528B9685-DA9C-4320-8AC6-C6871DF81C3F.jpeg');"></div>\r
+        <div class="comic-frame3" style="background-image: url('http://leasticoulddo.com/wp-content/uploads/2017/11/528B9685-DA9C-4320-8AC6-C6871DF81C3F.jpeg');"></div>\r
+        <div class="comic-frame4" style="background-image: url('http://leasticoulddo.com/wp-content/uploads/2017/11/528B9685-DA9C-4320-8AC6-C6871DF81C3F.jpeg');"></div>\r
+        <div class="clear"></div>\r
+    </div>\r
+    <div class="comic-footer">\r
+        <div class="comic-footer-right">\r
+            <a href="https://www.facebook.com/sharer.php?u=http://leasticoulddo.com/comic/20171111" target="_blank" class="comic-footer-facebook" onclick="return !window.open(this.href, 'Facebook', 'width=500,height=500,left=24,top=24')" title="Share on Facebook">Share on Facebook</a>\r
+            <a href="https://twitter.com/intent/tweet?text=Least+I+Could+Do+&url=http://leasticoulddo.com/comic/20171111" target="_blank" class="comic-footer-twitter" onclick="return !window.open(this.href, 'Twitter', 'width=500,height=250')" title="Tweet This">Tweet This</a>\r
+            <a href="http://www.pinterest.com/pin/create/button/?url=http://leasticoulddo.com/comic/20171111&media=http://leasticoulddo.com/wp-content/uploads/2017/11/528B9685-DA9C-4320-8AC6-C6871DF81C3F.jpeg&description=Least+I+Could+Do" target="_blank" class="comic-footer-pinterest" onclick="return !window.open(this.href, 'Twitter', 'width=550,height=550')" title="Pin This">Pin This</a>\r
+            <div class="blog-comments">\r
+                <div class="comments-wrap">\r
+                    <div class="comments-button" data-id="20396">Comments</div>\r
+                    <div class="comments">\r
+                        <div class="comments-scroll">\r
+                            <div class="comments-padding">\r
+                                <div class="comments-close"></div>\r
+                                <div class="comments-spacer"></div>\r
+                                 <div class="fb-wrapper" id="fb-wrapper-20396">\r
+                                    <div class="fb-comments" data-href="http://leasticoulddo.com//comic/20171111/" data-width="100%" data-numposts="10" data-colorscheme="dark"></div>\r
+                                 </div>\r
+                            </div>\r
+                        </div>\r
+                    </div>\r
+                </div>\r
+            </div>\r
+        </div>\r
+        <div class="comic-footer-left">\r
+            <span class="comic-footer-prev"><a href="http://leasticoulddo.com/comic/20171110" rel="prev">Previous</a></span>\r
+            <a href="/archive" class="comic-footer-archive">Archive</a>\r
+            <a href="http://shop.blindferret.com/products/licd-print?c=20171111" class="comic-footer-print">Buy Print</a>\r
+                    </div>\r
+        <div class="clear"></div>\r
+    </div>\r
+</div>\r
+<div class="comic-ad-leader-wrap">\r
+    <!-- <div class="comic-ad-leader-center"> -->\r
+                    <div class="large-ad-wrapper"><div id="div-gpt-ad-1473287030917-20396">\r
+  <script type="text/javascript">\r
+\r
+    googletag.cmd.push(function(){\r
+      var slot = googletag.defineSlot('/10195872/NEW_LICD_New_Comic_Leaderboard', [[970,250],[728, 90]], 'div-gpt-ad-1473287030917-20396').addService(googletag.pubads());\r
+\r
+      googletag.display('div-gpt-ad-1473287030917-20396');\r
+\r
+      googletag.pubads().refresh([ slot ]);\r
+\r
+    });\r
+\r
+  </script>\r
+</div></div>\r
+            <div class="ad-house"></div>\r
+            <div class="ad-box"><div id="div-gpt-ad-1473287030917-20396">\r
+  <script type="text/javascript">\r
+\r
+    googletag.cmd.push(function(){\r
+      var slot = googletag.defineSlot('/10195872/NEW_LICD_New_Comic_Leaderboard', [300, 250], 'div-gpt-ad-1473287030917-20396').addService(googletag.pubads());\r
+\r
+      googletag.display('div-gpt-ad-1473287030917-20396');\r
+\r
+      googletag.pubads().refresh([ slot ]);\r
+\r
+    });\r
+\r
+  </script>\r
+</div></div>\r
+            <!-- </div> -->\r
+</div>\r
+    \r
+</div>\r
+            \r
+        <div class="fb-wrapper" id="fb-wrapper-20396">\r
+           <div class="fb-comments" data-href="http://leasticoulddo.com/comic/20171111/" data-width="100%" data-numposts="10" data-colorscheme="light"></div>\r
+        </div>\r
+\r
+         \r
+\r
+    </div> \r
+</div>\r
+\r
+<script>\r
+\r
+    var latest_chapter = 326 - 8;\r
+\r
+    jQuery(document).ready( function(){\r
+        // Show Prev Comic Link for the top comic\r
+        $('.comic-footer-prev').css('display','inline-block');\r
+        // $('.comic-footer-next').css('display','inline-block');\r
+        // Update Navigation Sidebar Progress on Page Load\r
+        $('#nav-326').css('background-color','#0b2249');\r
+        $('#nav-326 .sidenav-progress').css('height','16.666666666667%');\r
+        // When Nav Reaches End, Load More Items\r
+        $('#sidenav-scroll').bind('scroll', function() {\r
+\r
+            if ( !($('#nav-'+latest_chapter).length) && ( $('.storyline-thumbs-end').offset().top - $(window).scrollTop() ) < ( $('#sidenav').height() )  ) {\r
+                $('.sidenav-loader-img').show();\r
+                $('.storyline-thumbs-end').remove();\r
+                var url = '/sidenav-comic';\r
+                $.post( ajax_url,{\r
+                    action: 'get_next_chapters',\r
+                    from: latest_chapter\r
+                }, function(data) { \r
+                    $(data).find('#sidenav-menu').contents().appendTo('#sidenav-menu');\r
+                });\r
+            };\r
+        });\r
+    });\r
+</script>\r
+\r
+\r
+    <div style="height:200px"></div>\r
+\r
+<script src="//connect.facebook.net/en_US/sdk.js"></script>\r
+\r
+<script type="text/javascript">\r
+    window.fbAsyncInit = function() {\r
+        FB.init({\r
+            appId: '222643084853752',\r
+            xfbml: true,\r
+            version: 'v2.8'\r
+        });\r
+        FB.Event.subscribe('xfbml.render', function(){\r
+            jQuery('.fb-comments').addClass('show')\r
+        });\r
+    }\r
+</script>\r
+\r
+<script type='text/javascript' src='http://leasticoulddo.com/wp-content/plugins/comic-easel/js/keynav.js'></script>\r
+<script type='text/javascript' src='http://leasticoulddo.com/wp-includes/js/wp-embed.min.js?ver=4.8.3'></script>\r
+\r
+<!-- Comment Out\r
+<script type="text/javascript">\r
+\r
+  var _gaq = _gaq || [];\r
+  _gaq.push(['_setAccount', 'UA-12642824-1']);\r
+  _gaq.push(['_setDomainName', 'leasticoulddo.com']);\r
+  _gaq.push(['_setAllowLinker', true]);\r
+  _gaq.push(['_trackPageview']);\r
+\r
+  (function() {\r
+    var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;\r
+    ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';\r
+    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);\r
+  })();\r
+\r
+</script>\r
+-->\r
+<!-- Video Ad Mobile -->\r
+\r
+<script>\r
+// (function()\r
+// {\r
+//  var lkqdSettings = {\r
+//    pid: 314,\r
+//    sid: 408052,\r
+//    playerContainerId: '',\r
+//    playerId: '',\r
+//    playerWidth: 300,\r
+//    playerHeight: 169,\r
+//    execution: 'outstream',\r
+//    placement: 'slider',\r
+//    playInitiation: 'auto',\r
+//    volume: 0,\r
+//    trackImp: '',\r
+//    trackClick: '',\r
+//    custom1: '',\r
+//    custom2: '',\r
+//    custom3: '',\r
+//    pubMacros: '',\r
+//    dfp: false,\r
+//    lkqdId: new Date().getTime().toString() + Math.round(Math.random()*1000000000).toString()\r
+//  };\r
+\r
+//  var lkqdVPAID;\r
+//  var creativeData = '';\r
+//  var environmentVars = { slot: document.getElementById(lkqdSettings.playerContainerId), videoSlot: document.getElementById(lkqdSettings.playerId), videoSlotCanAutoPlay: true, lkqdSettings: lkqdSettings };\r
+\r
+//  function onVPAIDLoad()\r
+//  {\r
+//    lkqdVPAID.subscribe(function() { lkqdVPAID.startAd(); }, 'AdLoaded');\r
+//  }\r
+\r
+//  var vpaidFrame = document.createElement('iframe');\r
+//  vpaidFrame.id = lkqdSettings.lkqdId;\r
+//  vpaidFrame.name = lkqdSettings.lkqdId;\r
+//  vpaidFrame.style.display = 'none';\r
+//  var vpaidFrameLoaded = function() {\r
+//    vpaidLoader = vpaidFrame.contentWindow.document.createElement('script');\r
+//    vpaidLoader.src = 'https://ad.lkqd.net/vpaid/formats.js?pid=314&sid=408052';\r
+//    vpaidLoader.onload = function() {\r
+//      lkqdVPAID = vpaidFrame.contentWindow.getVPAIDAd();\r
+//      onVPAIDLoad();\r
+//      lkqdVPAID.handshakeVersion('2.0');\r
+//      lkqdVPAID.initAd(lkqdSettings.playerWidth, lkqdSettings.playerHeight, 'normal', 600, creativeData, environmentVars);\r
+//    };\r
+//    vpaidFrame.contentWindow.document.body.appendChild(vpaidLoader);\r
+//  };\r
+//  vpaidFrame.onload = vpaidFrameLoaded;\r
+//  vpaidFrame.onerror = vpaidFrameLoaded;\r
+//  document.documentElement.appendChild(vpaidFrame);\r
+// })();\r
+</script>\r
+\r
+<!-- Video Ad Desktop -->\r
+<script>\r
+// (function()\r
+// {\r
+//  var lkqdSettings = {\r
+//    pid: 314,\r
+//    sid: 408049,\r
+//    playerContainerId: '',\r
+//    playerId: '',\r
+//    playerWidth: 480,\r
+//    playerHeight: 270,\r
+//    execution: 'outstream',\r
+//    placement: 'slider',\r
+//    playInitiation: 'auto',\r
+//    volume: 0,\r
+//    trackImp: '',\r
+//    trackClick: '',\r
+//    custom1: '',\r
+//    custom2: '',\r
+//    custom3: '',\r
+//    pubMacros: '',\r
+//    dfp: false,\r
+//    lkqdId: new Date().getTime().toString() + Math.round(Math.random()*1000000000).toString()\r
+//  };\r
+\r
+//  var lkqdVPAID;\r
+//  var creativeData = '';\r
+//  var environmentVars = { slot: document.getElementById(lkqdSettings.playerContainerId), videoSlot: document.getElementById(lkqdSettings.playerId), videoSlotCanAutoPlay: true, lkqdSettings: lkqdSettings };\r
+\r
+//  function onVPAIDLoad()\r
+//  {\r
+//    lkqdVPAID.subscribe(function() { lkqdVPAID.startAd(); }, 'AdLoaded');\r
+//  }\r
+\r
+//  var vpaidFrame = document.createElement('iframe');\r
+//  vpaidFrame.id = lkqdSettings.lkqdId;\r
+//  vpaidFrame.name = lkqdSettings.lkqdId;\r
+//  vpaidFrame.style.display = 'none';\r
+//  var vpaidFrameLoaded = function() {\r
+//    vpaidLoader = vpaidFrame.contentWindow.document.createElement('script');\r
+//    vpaidLoader.src = 'https://ad.lkqd.net/vpaid/formats.js?pid=314&sid=408049';\r
+//    vpaidLoader.onload = function() {\r
+//     lkqdVPAID = vpaidFrame.contentWindow.getVPAIDAd();\r
+//      onVPAIDLoad();\r
+//      lkqdVPAID.handshakeVersion('2.0');\r
+//      lkqdVPAID.initAd(lkqdSettings.playerWidth, lkqdSettings.playerHeight, 'normal', 600, creativeData, environmentVars);\r
+//    };\r
+//    vpaidFrame.contentWindow.document.body.appendChild(vpaidLoader);\r
+//  };\r
+//  vpaidFrame.onload = vpaidFrameLoaded;\r
+//  vpaidFrame.onerror = vpaidFrameLoaded;\r
+//  document.documentElement.appendChild(vpaidFrame);\r
+// })();\r
+ </script>\r
+\r
+<style type="text/css">\r
+  body > iframe {\r
+    display: none !important;\r
+  }\r
+</style>\r
+\r
+<script async src="https://outstream.tremorvideo.com/js/out-stream/0/in-article.js"\r
+   data-insert="after-element"\r
+   data-insert-after-element-offset="0"\r
+   data-insert-after-element-selector=".comic-wrap"\r
+   data-key="bwavn29e"\r
+   data-max-width="640px"\r
+   data-mute="on-with-toggle"\r
+   data-play="while-in-viewport"\r
+   data-preload="auto"\r
+   data-skipoffset="5"\r
+   data-vast="https://fwuwb-8o5jn.ads.tremorhub.com/ad/tag?adCode=fwuwb-zl8z8&playerWidth=[PLAYER_WIDTH:REQUIRED]&playerHeight=[PLAYER_HEIGHT:REQUIRED]&playerPosition=[PLAYER_POSITION:RECOMMENDED]&mediaTitle=[MEDIA_TITLE:RECOMMENDED]&mediaId=[MEDIA_ID]&mediaUrl=[CONTENT_MEDIA_URL]&srcPageUrl=[SOURCE_PAGE_URL:REQUIRED]&contentLength=[CONTENT_LENGTH]&skip=[SKIP]&skipmin=[SKIP_MIN]&skipafter=[SKIP_AFTER]&delivery=[DELIVERY]&placement=[PLACEMENT]&videoMinBitrate=[MIN_BITRATE]&videoMaxBitrate=[MAX_BITRATE]&custom=[CUSTOM]&c2=[CUSTOM_2]&c3=[CUSTOM_3]&c4=[CUSTOM_4]"\r
+></script>\r
+\r
+<!--\r
+ <script async src="https://outstream.tremorvideo.com/js/out-stream/0/in-article.js"\r
+   data-insert="after-element"\r
+   data-insert-after-element-offset="0"\r
+   data-insert-after-element-selector="#tremor-container"\r
+   data-key="bwavn29e"\r
+   data-max-width="640px"\r
+   data-mute="on-with-toggle"\r
+   data-play="while-in-viewport"\r
+   data-preload="auto"\r
+   data-skipoffset="5"\r
+   data-vast="https://fwuwb-kvo2u.ads.tremorhub.com/ad/tag?adCode=fwuwb-n4qkp&playerWidth=[PLAYER_WIDTH:REQUIRED]&playerHeight=[PLAYER_HEIGHT:REQUIRED]&playerPosition=[PLAYER_POSITION:RECOMMENDED]&mediaTitle=[MEDIA_TITLE:RECOMMENDED]&mediaId=[MEDIA_ID]&mediaUrl=[CONTENT_MEDIA_URL]&srcPageUrl=[SOURCE_PAGE_URL:REQUIRED]&contentLength=[CONTENT_LENGTH]&skip=[SKIP]&skipmin=[SKIP_MIN]&skipafter=[SKIP_AFTER]&delivery=[DELIVERY]&placement=[PLACEMENT]&videoMinBitrate=[MIN_BITRATE]&videoMaxBitrate=[MAX_BITRATE]&custom=[CUSTOM]&c2=[CUSTOM_2]&c3=[CUSTOM_3]&c4=[CUSTOM_4]"\r
+></script>\r
+  -->\r
+</body>\r
+</html>\r
+<!-- Performance optimized by W3 Total Cache. Learn more: https://www.w3-edge.com/products/\r
+\r
+Database Caching 2/108 queries in 0.121 seconds using memcached\r
+\r
+ Served from: leasticoulddo.com @ 2017-11-11 00:00:13 by W3 Total Cache -->\r