ruby-readability 0.6.0 → 0.6.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7c4e7dd91c7e7dbd34238150565daacd14d19c4f
4
- data.tar.gz: fa8ef220bba559a5e3621de373bc3cb5295f9583
3
+ metadata.gz: 7452ade635ade3314c5eb992de803b2ed6d103e0
4
+ data.tar.gz: 90c7b2d34dd4d6070e06c589d5e01f5ebb5e76db
5
5
  SHA512:
6
- metadata.gz: 37f7e00448f2390cf87166899d967ad8521413b727e89a97f977310ceedf51e2f4a99201b046484bde645257ff9828ea3e1365056575776f107f50d0d1a8d15d
7
- data.tar.gz: 2e4bcfceac1c8be2b2cd9cc9ed725f459f57bebfc87beaf940e972a2ed8b37e73d5681955b71a8cebc9ffee246e92b3f33cc8c983ec2ee97b201268149555e73
6
+ metadata.gz: 09a7bfef009fdc001749a2695876d0c0adfcb12ca7cdce31ef494227cd9712133b6ba7a18ffd8340b7a2f233954f6e1cf83e1470b70052d9cb64ad66db24d0c8
7
+ data.tar.gz: cf7b9884f2339f8e2cc99c0a17fc4170a3a97e7f59c9c1e0a0b40417f45c059d2df31d54253b6535f942915096b11e0592d2f8cd2ff735c0bb9edd5ae465afe8
@@ -1,6 +1,6 @@
1
1
  language: ruby
2
2
  rvm:
3
+ - 2.1.1
3
4
  - 2.0.0
4
5
  - 1.9.3
5
- - 1.9.2
6
6
  script: "bundle exec rspec"
data/Gemfile CHANGED
@@ -2,6 +2,8 @@ source "http://rubygems.org"
2
2
 
3
3
  gem 'fastimage', '~> 1.2.13'
4
4
  gem 'rake'
5
+ gem 'guard'
6
+ gem 'guard-rspec'
5
7
 
6
8
  group :test do
7
9
  gem "fakeweb", "~> 1.3.0"
@@ -0,0 +1,9 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard :rspec do
5
+ watch(%r{^spec/.+_spec\.rb$})
6
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
7
+ watch('spec/spec_helper.rb') { "spec" }
8
+ end
9
+
data/README.md CHANGED
@@ -51,6 +51,7 @@ You may provide options to `Readability::Document.new`, including:
51
51
  `:ignore_image_format => ["gif", "png"]`;
52
52
  * `:min_image_height`: set a minimum image height for `#images`;
53
53
  * `:min_image_width`: set a minimum image width for `#images`.
54
+ * `:blacklist` and `:whitelist` allow you to explicitly scope to, or remove, CSS selectors.
54
55
 
55
56
 
56
57
  Command Line Tool
@@ -74,6 +75,10 @@ feature requires that the `fastimage` gem be installed.
74
75
  rbody = Readability::Document.new(body, :tags => %w[div p img a], :attributes => %w[src href], :remove_empty_nodes => false)
75
76
  rbody.images
76
77
 
78
+ Related Projects
79
+ ----------------
80
+
81
+ * [newspaper](https://github.com/codelucas/newspaper) is an advanced news extraction, article extraction, and content curation library for Python.
77
82
 
78
83
  Potential Issues
79
84
  ----------------
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env ruby
1
+ #!/usr/bin/env ruby
2
2
  require 'rubygems'
3
3
  require 'open-uri'
4
4
  require 'optparse'
@@ -29,11 +29,13 @@ if ARGV.length != 1
29
29
  end
30
30
 
31
31
  text = open(ARGV.first).read
32
- if options[:images]
33
- puts Readability::Document.new(text, :tags => %w[div p img a],
34
- :attributes => %w[src href],
35
- :remove_empty_nodes => false,
36
- :debug => options[:debug]).content
32
+ params = if options[:images]
33
+ { :tags => %w[div p img a],
34
+ :attributes => %w[src href],
35
+ :remove_empty_nodes => false,
36
+ :debug => options[:debug] }
37
37
  else
38
- puts Readability::Document.new(text, :debug => options[:debug]).content
38
+ { :debug => options[:debug] }
39
39
  end
40
+
41
+ puts Readability::Document.new(text, params).content
@@ -15,7 +15,9 @@ module Readability
15
15
  :remove_empty_nodes => true,
16
16
  :min_image_width => 130,
17
17
  :min_image_height => 80,
18
- :ignore_image_format => []
18
+ :ignore_image_format => [],
19
+ :blacklist => nil,
20
+ :whitelist => nil
19
21
  }.freeze
20
22
 
21
23
  attr_accessor :options, :html, :best_candidate, :candidates, :best_candidate_has_image
@@ -35,18 +37,42 @@ module Readability
35
37
  @clean_conditionally = @options[:clean_conditionally]
36
38
  @best_candidate_has_image = true
37
39
  make_html
40
+ handle_exclusions!(@options[:whitelist], @options[:blacklist])
38
41
  end
39
42
 
40
43
  def prepare_candidates
41
44
  @html.css("script, style").each { |i| i.remove }
42
45
  remove_unlikely_candidates! if @remove_unlikely_candidates
43
46
  transform_misused_divs_into_paragraphs!
44
-
47
+
45
48
  @candidates = score_paragraphs(options[:min_text_length])
46
49
  @best_candidate = select_best_candidate(@candidates)
47
50
  end
48
51
 
49
- def make_html
52
+ def handle_exclusions!(whitelist, blacklist)
53
+ return unless whitelist || blacklist
54
+
55
+ if blacklist
56
+ elems = @html.css(blacklist)
57
+ if elems
58
+ elems.each do |e|
59
+ e.remove
60
+ end
61
+ end
62
+ end
63
+
64
+ if whitelist
65
+ elems = @html.css(whitelist).to_s
66
+
67
+ if body = @html.at_css('body')
68
+ body.inner_html = elems
69
+ end
70
+ end
71
+
72
+ @input = @html.to_s
73
+ end
74
+
75
+ def make_html(whitelist=nil, blacklist=nil)
50
76
  @html = Nokogiri::HTML(@input, nil, @options[:encoding])
51
77
  # In case document has no body, such as from empty string or redirect
52
78
  @html = Nokogiri::HTML('<body />', nil, @options[:encoding]) if @html.css('body').length == 0
@@ -78,16 +104,16 @@ module Readability
78
104
  url = element["src"].value
79
105
  height = element["height"].nil? ? 0 : element["height"].value.to_i
80
106
  width = element["width"].nil? ? 0 : element["width"].value.to_i
81
-
107
+
82
108
  if url =~ /\Ahttps?:\/\//i && (height.zero? || width.zero?)
83
- image = get_image_size(url)
109
+ image = get_image_size(url)
84
110
  next unless image
85
111
  else
86
112
  image = {:width => width, :height => height}
87
113
  end
88
-
114
+
89
115
  image[:format] = File.extname(url).gsub(".", "")
90
-
116
+
91
117
  if tested_images.include?(url)
92
118
  debug("Image was tested: #{url}")
93
119
  next
@@ -105,14 +131,12 @@ module Readability
105
131
  end
106
132
 
107
133
  def get_image_size(url)
108
- begin
109
- w, h = FastImage.size(url)
110
- raise "Couldn't get size." if w.nil? || h.nil?
111
- {:width => w, :height => h}
112
- rescue => e
113
- debug("Image error: #{e}")
114
- nil
115
- end
134
+ w, h = FastImage.size(url)
135
+ raise "Couldn't get size." if w.nil? || h.nil?
136
+ {:width => w, :height => h}
137
+ rescue => e
138
+ debug("Image error: #{e}")
139
+ nil
116
140
  end
117
141
 
118
142
  def image_meets_criteria?(image)
@@ -148,9 +172,7 @@ module Readability
148
172
  author_elements = @html.xpath('//meta[@name = "dc.creator"]')
149
173
  unless author_elements.empty?
150
174
  author_elements.each do |element|
151
- if element['content']
152
- return element['content'].strip
153
- end
175
+ return element['content'].strip if element['content']
154
176
  end
155
177
  end
156
178
 
@@ -160,9 +182,7 @@ module Readability
160
182
  author_elements = @html.xpath('//*[contains(@class, "vcard")]//*[contains(@class, "fn")]')
161
183
  unless author_elements.empty?
162
184
  author_elements.each do |element|
163
- if element.text
164
- return element.text.strip
165
- end
185
+ return element.text.strip if element.text
166
186
  end
167
187
  end
168
188
 
@@ -172,18 +192,14 @@ module Readability
172
192
  author_elements = @html.xpath('//a[@rel = "author"]')
173
193
  unless author_elements.empty?
174
194
  author_elements.each do |element|
175
- if element.text
176
- return element.text.strip
177
- end
195
+ return element.text.strip if element.text
178
196
  end
179
197
  end
180
198
 
181
199
  author_elements = @html.xpath('//*[@id = "author"]')
182
200
  unless author_elements.empty?
183
201
  author_elements.each do |element|
184
- if element.text
185
- return element.text.strip
186
- end
202
+ return element.text.strip if element.text
187
203
  end
188
204
  end
189
205
  end
@@ -230,10 +246,10 @@ module Readability
230
246
  node_content = sibling.text
231
247
  node_length = node_content.length
232
248
 
233
- if node_length > 80 && link_density < 0.25
234
- append = true
249
+ append = if node_length > 80 && link_density < 0.25
250
+ true
235
251
  elsif node_length < 80 && link_density == 0 && node_content =~ /\.( |$)/
236
- append = true
252
+ true
237
253
  end
238
254
  end
239
255
 
@@ -302,40 +318,28 @@ module Readability
302
318
  return weight unless @weight_classes
303
319
 
304
320
  if e[:class] && e[:class] != ""
305
- if e[:class] =~ REGEXES[:negativeRe]
306
- weight -= 25
307
- end
308
-
309
- if e[:class] =~ REGEXES[:positiveRe]
310
- weight += 25
311
- end
321
+ weight -= 25 if e[:class] =~ REGEXES[:negativeRe]
322
+ weight += 25 if e[:class] =~ REGEXES[:positiveRe]
312
323
  end
313
324
 
314
325
  if e[:id] && e[:id] != ""
315
- if e[:id] =~ REGEXES[:negativeRe]
316
- weight -= 25
317
- end
318
-
319
- if e[:id] =~ REGEXES[:positiveRe]
320
- weight += 25
321
- end
326
+ weight -= 25 if e[:id] =~ REGEXES[:negativeRe]
327
+ weight += 25 if e[:id] =~ REGEXES[:positiveRe]
322
328
  end
323
329
 
324
330
  weight
325
331
  end
326
332
 
333
+ ELEMENT_SCORES = {
334
+ 'div' => 5,
335
+ 'blockquote' => 3,
336
+ 'form' => -3,
337
+ 'th' => -5
338
+ }.freeze
339
+
327
340
  def score_node(elem)
328
341
  content_score = class_weight(elem)
329
- case elem.name.downcase
330
- when "div"
331
- content_score += 5
332
- when "blockquote"
333
- content_score += 3
334
- when "form"
335
- content_score -= 3
336
- when "th"
337
- content_score -= 5
338
- end
342
+ content_score += ELEMENT_SCORES.fetch(elem.name.downcase, 0)
339
343
  { :content_score => content_score, :elem => elem }
340
344
  end
341
345
 
@@ -373,7 +377,7 @@ module Readability
373
377
  end
374
378
  end
375
379
 
376
- def sanitize(node, candidates, options = {})
380
+ def sanitize(node, candidates, options = {})
377
381
  node.css("h1, h2, h3, h4, h5, h6").each do |header|
378
382
  header.remove if class_weight(header) < 0 || get_link_density(header) > 0.33
379
383
  end
@@ -450,38 +454,35 @@ module Readability
450
454
 
451
455
  content_length = el.text.strip.length # Count the text length excluding any surrounding whitespace
452
456
  link_density = get_link_density(el)
453
- to_remove = false
454
- reason = ""
455
-
456
- if counts["img"] > counts["p"]
457
- reason = "too many images"
458
- to_remove = true
459
- elsif counts["li"] > counts["p"] && name != "ul" && name != "ol"
460
- reason = "more <li>s than <p>s"
461
- to_remove = true
462
- elsif counts["input"] > (counts["p"] / 3).to_i
463
- reason = "less than 3x <p>s than <input>s"
464
- to_remove = true
465
- elsif content_length < (options[:min_text_length] || TEXT_LENGTH_THRESHOLD) && (counts["img"] == 0 || counts["img"] > 2)
466
- reason = "too short a content length without a single image"
467
- to_remove = true
468
- elsif weight < 25 && link_density > 0.2
469
- reason = "too many links for its weight (#{weight})"
470
- to_remove = true
471
- elsif weight >= 25 && link_density > 0.5
472
- reason = "too many links for its weight (#{weight})"
473
- to_remove = true
474
- elsif (counts["embed"] == 1 && content_length < 75) || counts["embed"] > 1
475
- reason = "<embed>s with too short a content length, or too many <embed>s"
476
- to_remove = true
477
- end
478
457
 
479
- if to_remove
458
+ reason = clean_conditionally_reason?(counts, content_length, options, weight, link_density)
459
+ if reason
480
460
  debug("Conditionally cleaned #{name}##{el[:id]}.#{el[:class]} with weight #{weight} and content score #{content_score} because it has #{reason}.")
481
461
  el.remove
482
462
  end
483
463
  end
484
464
  end
485
465
  end
466
+
467
+ def clean_conditionally_reason?(counts, content_length, options, weight, link_density)
468
+ if counts["img"] > counts["p"]
469
+ "too many images"
470
+ elsif counts["li"] > counts["p"] && name != "ul" && name != "ol"
471
+ "more <li>s than <p>s"
472
+ elsif counts["input"] > (counts["p"] / 3).to_i
473
+ "less than 3x <p>s than <input>s"
474
+ elsif content_length < (options[:min_text_length] || TEXT_LENGTH_THRESHOLD) && (counts["img"] == 0 || counts["img"] > 2)
475
+ "too short a content length without a single image"
476
+ elsif weight < 25 && link_density > 0.2
477
+ "too many links for its weight (#{weight})"
478
+ elsif weight >= 25 && link_density > 0.5
479
+ "too many links for its weight (#{weight})"
480
+ elsif (counts["embed"] == 1 && content_length < 75) || counts["embed"] > 1
481
+ "<embed>s with too short a content length, or too many <embed>s"
482
+ else
483
+ nil
484
+ end
485
+ end
486
+
486
487
  end
487
488
  end
@@ -3,7 +3,7 @@ $:.push File.expand_path("../lib", __FILE__)
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = "ruby-readability"
6
- s.version = '0.6.0'
6
+ s.version = '0.6.1'
7
7
  s.authors = ["Andrew Cantino", "starrhorne", "libc", "Kyle Maxwell"]
8
8
  s.email = ["andrew@iterationlabs.com"]
9
9
  s.homepage = "http://github.com/cantino/ruby-readability"
@@ -0,0 +1,876 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <title>Tick, tick, tick - Boing Boing</title><meta charset="utf-8">
5
+ <meta property="twitter:account_id" content="5971922" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=1" />
7
+ <link rel="stylesheet" href="http://media.boingboing.net/wp-content/themes/2012/style.css?v=33" type="text/css" charset="utf-8" />
8
+ <!--[if lt IE 9]> <link rel="stylesheet" href="http://media.boingboing.net/wp-content/themes/2012/style_IE.css?v=3" type="text/css" charset="utf-8" /><![endif]-->
9
+ <script type="text/javascript" src="//use.typekit.net/its8tor.js"></script>
10
+ <script type="text/javascript">try{Typekit.load();}catch(e){}</script>
11
+
12
+ <meta property="fb:admins" content="1219680052" />
13
+ <meta property="og:site_name" content="Boing Boing" />
14
+ <link rel="apple-touch-icon" href="/wp-content/themes/2012/sundries/apple-touch-icon.png"/>
15
+ <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.3/jquery.min.js"></script>
16
+ <script type="text/javascript" charset="utf-8">
17
+ document.domain = 'boingboing.net';
18
+ </script>
19
+
20
+
21
+ <!-- Begin DoubleClick For Publishers code -->
22
+ <script type='text/javascript'>
23
+ var googletag = googletag || {};
24
+ googletag.cmd = googletag.cmd || [];
25
+ (function() {
26
+ var gads = document.createElement('script');
27
+ gads.async = true;
28
+ gads.type = 'text/javascript';
29
+ var useSSL = 'https:' == document.location.protocol;
30
+ gads.src = (useSSL ? 'https:' : 'http:') +
31
+ '//www.googletagservices.com/tag/js/gpt.js';
32
+ var node = document.getElementsByTagName('script')[0];
33
+ node.parentNode.insertBefore(gads, node);
34
+ })();
35
+ </script>
36
+
37
+ <script type='text/javascript'>
38
+ googletag.cmd.push(function() {
39
+ googletag.defineSlot('/6203160/400x300_home_footer', [[400, 267], [300, 250]], 'div-gpt-ad-1348031780431-0').addService(googletag.pubads());
40
+ googletag.defineSlot('/6203160/300x250_temp_top_sidebar', [300, 250], 'div-gpt-ad-1388426870729-0').addService(googletag.pubads());
41
+ googletag.pubads().collapseEmptyDivs();
42
+ googletag.enableServices();
43
+ });
44
+ </script>
45
+
46
+ <script type='text/javascript'>
47
+ (function() {
48
+ var useSSL = 'https:' == document.location.protocol;
49
+ var src = (useSSL ? 'https:' : 'http:') +
50
+ '//www.googletagservices.com/tag/js/gpt_mobile.js';
51
+ document.write('<scr' + 'ipt src="' + src + '"></scr' + 'ipt>');
52
+ })();
53
+ </script>
54
+ <script type='text/javascript'>
55
+ googletag.cmd.push(function() {
56
+ googletag.defineSlot('/6203160/320x50', [320, 50], 'div-gpt-ad-1356214036289-0').addService(googletag.pubads());
57
+ googletag.enableServices();
58
+ });
59
+ </script>
60
+ <!-- End DoubleClick For Publishers Code -->
61
+
62
+
63
+
64
+ <link rel="stylesheet" href="http://media.boingboing.net/wp-content/themes/2012/style_single.css?v=21" type="text/css" charset="utf-8" />
65
+ <!--[if lt IE 9]> <link rel="stylesheet" href="http://media.boingboing.net/wp-content/themes/2012/style_IE_single.css?v=18" type="text/css" charset="utf-8" /><![endif]-->
66
+
67
+
68
+ <meta property="og:type" content="article" />
69
+ <meta property="og:title" content="Tick, tick, tick" />
70
+ <meta property="og:description" content="No idea who made this, but it&#039;s wonderful. If you know, post in the comments, please.
71
+
72
+
73
+ Update: It&#039;s from Bees and Bombs, to which I have just subscribed." />
74
+ <meta property="og:url" content="http://boingboing.net/2014/04/13/tick-tick-tick.html" />
75
+ <meta property="og:image" content="http://media.boingboing.net/wp-content/uploads/2014/04/tumblr_n3wstblgoN1socbkko1_5001.gif" />
76
+
77
+
78
+ <meta itemprop="name" content="Tick, tick, tick" />
79
+ <meta itemprop="headline" content="Tick, tick, tick" />
80
+ <meta itemprop="author" content="Cory Doctorow" />
81
+ <meta itemprop="description" content="No idea who made this, but it&#039;s wonderful. If you know, post in the comments, please.
82
+
83
+
84
+ Update: It&#039;s from Bees and Bombs, to which I have just subscribed." />
85
+ <link itemprop="url" href="http://boingboing.net/2014/04/13/tick-tick-tick.html" />
86
+ <link itemprop="thumbnailUrl" href="http://media.boingboing.net/wp-content/uploads/2014/04/tumblr_n3wstblgoN1socbkko1_5001.gif" />
87
+
88
+
89
+ <meta name="twitter:card" content="summary_large_image">
90
+ <meta name="twitter:site" content="@BoingBoing">
91
+ <meta name="twitter:creator" content="@doctorow">
92
+ <meta name="twitter:title" content="Tick, tick, tick">
93
+ <meta name="twitter:description" content="No idea who made this, but it&#039;s wonderful. If you know, post in the comments, please.
94
+
95
+
96
+ Update: It&#039;s from Bees and Bombs, to which I have just subscribed.">
97
+ <meta name="twitter:image:src" content="http://media.boingboing.net/wp-content/uploads/2014/04/tumblr_n3wstblgoN1socbkko1_5001.gif">
98
+
99
+
100
+ <link rel='stylesheet' id='discourse_comments-css' href='http://media.boingboing.net/wp-content/plugins/wp-discourse/css/style.css?ver=3.4.1' type='text/css' media='all' />
101
+ <link rel='stylesheet' id='kindle-style-css' href='http://media.boingboing.net/wp-content/plugins/sendtokindle/media/kindle.css?ver=3.4.1' type='text/css' media='all' />
102
+ <script type='text/javascript'>
103
+ /* <![CDATA[ */
104
+ (function k(){window.$SendToKindle&&window.$SendToKindle.Widget?$SendToKindle.Widget.init({"title":".entry-title","published":".entry-date","content":".post","exclude":".sharedaddy"}):setTimeout(k,500);})();
105
+ /* ]]> */
106
+ </script>
107
+ <script type='text/javascript' src='http://d1xnn692s7u6t6.cloudfront.net/widget.js'></script>
108
+ <link rel="EditURI" type="application/rsd+xml" title="RSD" href="http://boingboing.net/xmlrpc.php?rsd" />
109
+ <link rel="wlwmanifest" type="application/wlwmanifest+xml" href="http://media.boingboing.net/wp-includes/wlwmanifest.xml" />
110
+ <link rel='prev' title='This Day in Blogging History: Google&#039;s adds dead-man&#039;s switch; Hyperbolic Bronnerianism; Amex can&#039;t take a&nbsp;joke' href='http://boingboing.net/2014/04/13/this-day-in-blogging-history-195.html' />
111
+ <link rel='next' title='TV recap: Game Of Thrones &#039;The Lion And The Rose&#039; [season 4, episode&nbsp;2]' href='http://boingboing.net/2014/04/13/tv-recap-game-of-thrones-th.html' />
112
+ <meta name="generator" content="WordPress 3.4.1" />
113
+ <link rel='canonical' href='http://boingboing.net/2014/04/13/tick-tick-tick.html' />
114
+ <link rel='shortlink' href='http://boingboing.net/?p=297258' />
115
+ <link rel='stylesheet' type='text/css' href='http://media.boingboing.net/wp-content/plugins/embedly/css/embedly.css' />
116
+ <script type="text/javascript" src="http://media.boingboing.net/wp-content/plugins/oembed-manager/oembed-html-style-scripts.js?v=1"> </script><link rel="stylesheet" type="text/css" href="http://media.boingboing.net/wp-content/plugins/oembed-manager/oembed-html-style.css?v=1" /> </head>
117
+
118
+ <body class="single single-post postid-297258 single-format-standard" itemscope='' itemtype='http://schema.org/Blog'
119
+ >
120
+
121
+ <div id="adskin"></div>
122
+
123
+ <div id="dickbar2" style="">
124
+
125
+ <div id="dickbar2-inner">
126
+ <span style="float:left">
127
+ <a href="http://boingboing.net/suggest.html">Submit <span style="mobile-hide">a link</span></a>
128
+ </span>
129
+
130
+
131
+
132
+ <!-- Google search box. -->
133
+
134
+
135
+ <div id="cse-search-box" class="tablet-hide">
136
+ <form action="http://www.google.com/cse">
137
+ <input name="cx" value="partner-pub-2170174688585464:d58nno-rqp8" type="hidden">
138
+ <input name="ie" value="ISO-8859-1" type="hidden">
139
+ <input name="q" id="searchInputField" size="18" class="" value="" type="text" style="background-image:url('http://media.boingboing.net/wp-content/uploads/2013/07/searchback.png')!important;background-position:right center!important;background-repeat:no-repeat!important">
140
+ <input value="" name="siteurl" type="hidden">
141
+ </form>
142
+ </div>
143
+ <script type="text/javascript" src="http://www.google.com/coop/cse/brand?form=cse-search-box&amp;lang=en"></script>
144
+
145
+
146
+ <script>
147
+ function navdrop()
148
+ {
149
+ if (document.getElementById('drop').style.display=='none') { document.getElementById('drop').style.display='block'; }
150
+ else {document.getElementById('drop').style.display='none'}
151
+ }
152
+ </script>
153
+
154
+ <span style="float:right;margin-right:1em">
155
+ <a href="http://boingboing.net/category/feature/" style="color:#ff638c">Features</a>
156
+ <a href="http://boingboing.net/category/review/" style="color:#e761fd">Reviews</a>
157
+ <a href="http://boingboing.net/category/podcasts" style="color:#6b70ff">Podcasts</a>
158
+ <a href="http://boingboing.net/category/video/" style="color:#61f1fc">Video</a>
159
+ <a class="mobile-hide" href="http://bbs.boingboing.net/" style="color:#61fe99">Forums</a>
160
+ <a class="mobile-hide" href="javascript:void(0)" onClick="navdrop()" style="color:#80eb59">More &#9662;</a>
161
+ </span>
162
+
163
+
164
+ <div id="drop" style="border-left:15px solid white;border-right:15px solid white;border-bottom:15px solid white;position:absolute;top:54px;padding:0px 15px 15px 15px;right:87px;background-color:black;opacity:1;z-index:999;display:none;">
165
+ <a class="mobile-hide" href="http://shop.boingboing.net/" style="color:#fff">Shop</a>
166
+ <br><a class="mobile-hide" href="http://boingboing.net/about" style="color:#fff">About Us</a>
167
+ <br><a class="mobile-hide" href="http://boingboing.net/contact" style="color:#fff">Contact</a>
168
+ <br><a class="mobile-hide" href="mailto:inquiries@boingboing.net" style="color:#fff">Advertise</a>
169
+ <br><a class="mobile-hide" href="http://boingboing.net/privacy" style="color:#fff">Privacy</a>
170
+ <br><a class="mobile-hide" href="http://boingboing.net/tos" style="color:#fff">TOS</a>
171
+ <br><br><span style="font-size:13px;color:gray;">Follow Us</span>
172
+ <br><a href="http://facebook.com/boingboing" style="color:#fff">Facebook</a>
173
+ <br><a href="http://twitter.com/boingboing" style="color:#fff">Twitter</a>
174
+ <br><a href="http://feeds.boingboing.net/boingboing/iBag" style="color:#fff">RSS</a>
175
+ <br><a href="http://boingboing.us2.list-manage.com/subscribe?u=0e91f8e7df61da4bff2bd9b1f&id=fa324756a4" style="color:#fff">Email</a>
176
+ </div>
177
+ </div>
178
+ </div>
179
+
180
+
181
+ <h2 id="JKAnchor"><img src="http://media.boingboing.net/wp-content/themes/2012/sundries/boingboing.jpg"></h2> <!-- top anchor for j/k navigation -->
182
+
183
+ <div id="container">
184
+
185
+
186
+ <div id="mobile_includes">
187
+ <noscript id="mobile_includes_noscript">
188
+ <style type="text/css">
189
+ @media screen and (max-width:400px){
190
+ body{
191
+ overflow-x:hidden;
192
+ background:#ffffff !important;
193
+ }
194
+ #posts-loop *{
195
+ max-width:100% !important;
196
+ }
197
+ *{
198
+ max-width:320px;
199
+ }
200
+ #mobile_includes{
201
+ width:320px;
202
+ margin-left:-16px;
203
+ }
204
+ #container{
205
+ padding-top:0px;
206
+ }
207
+ #cse-search-box {
208
+ margin-right: 5px !important;
209
+ }
210
+ #dickbar {
211
+ width:310px;
212
+ }
213
+ #mobile-logo {
214
+ padding:20px 0px 10px 0px;
215
+ }
216
+ #metadataBox {
217
+ overflow-x:hidden;
218
+ }
219
+ #ad_500 {
220
+ max-height:400px;
221
+ overflow:hidden;
222
+ }
223
+ }
224
+ </style>
225
+
226
+ <!-- 320x50-Mobile-Leaderboard -->
227
+ <div id='div-gpt-ad-1356214036289-0'>
228
+ <script type='text/javascript'>
229
+ googletag.cmd.push(function() { googletag.display('div-gpt-ad-1356214036289-0')});
230
+ </script>
231
+ </div>
232
+ <!-- end 320x50-Mobile-Leaderboard -->
233
+ </noscript>
234
+
235
+ <script type="text/javascript">
236
+ function isMobile(){
237
+ return (function(a){
238
+ if(/android.+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|e\-|e\/|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(di|rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|xda(\-|2|g)|yas\-|your|zeto|zte\-/i.test(a.substr(0,4))){
239
+ return true;
240
+ }
241
+ else {
242
+ return false;
243
+ }
244
+ })(navigator.userAgent||navigator.vendor||window.opera);
245
+ }
246
+
247
+ if(isMobile()){
248
+ console.log('Mobile or tablet detected for mobile ad');
249
+ if($('#mobile_includes') && $('#mobile_includes_noscript')) {
250
+ console.log('Populating mobile-specific styles');
251
+ document.write($('#mobile_includes_noscript').text());
252
+ }
253
+ }
254
+ </script>
255
+ </div>
256
+
257
+
258
+ <div id="mobile-logo"><a href="http://boingboing.net"><img src="http://media.boingboing.net/wp-content/themes/2012/sundries/logo1.png"></a></div>
259
+
260
+
261
+
262
+
263
+
264
+ <!-- The main content area of the site -->
265
+
266
+ <div id="mainbar" style="">
267
+
268
+ <!-- Masthead and Leaderboard ad -->
269
+ <div id="masthead">
270
+ <div id="logobox" style="">
271
+ <a href="http://boingboing.net">
272
+ <img id="logo" src="http://media.boingboing.net/wp-content/themes/2012/sundries/logo_bounce2012_static.gif" name="MyImage" alt="Jill" onmouseover="document.MyImage.src='http://media.boingboing.net/wp-content/themes/2012/sundries/logo_bounce2012.gif';" onmouseout="document.MyImage.src='http://media.boingboing.net/wp-content/themes/2012/sundries/logo_bounce2012_static.gif';">
273
+ </a>
274
+ </div>
275
+
276
+ <div id="ad_leaderboard">
277
+ <!--[if !IE]> -->
278
+ <noscript id="ad_leaderboard_noscript">
279
+ <!-- <![endif]-->
280
+ <center>
281
+ <iframe src="http://boingboing.net/wp-content/themes/2012/ads/ad_leaderboard.html?v=1&fm_url=http://boingboing.net/2014/04/13/tick-tick-tick.html&fm_custom_kvs=category%3Dpost" frameborder="0" scrolling="no" marginheight="0" marginwidth="0" topmargin="0" leftmargin="0" allowtransparency="true" width="100%" onload="console.log('ad_leaderboard iframe loaded');"></iframe>
282
+ </center>
283
+ <!--[if !IE]> -->
284
+ </noscript>
285
+ <!-- <![endif]-->
286
+ </div>
287
+
288
+ </div>
289
+
290
+
291
+ <!-- IF IT'S AN AD, DISCLOSE IT-->
292
+
293
+
294
+ <!-- A LARGE HEADLINE AND THE BYLINE -->
295
+
296
+ <div id="headline-297258" class="headlineBox">
297
+
298
+
299
+
300
+ <h1 class="bigHeadline" id="theHeadline">Tick, tick,&nbsp;tick</h1>
301
+
302
+
303
+ <div id="share_post_small">
304
+
305
+ <span class="emailDiv">
306
+ <a href="mailto:type%20email%20address%20here?subject=Shared%20from%20Boing Boing&body=Tick, tick,&nbsp;tick - http://boingboing.net/2014/04/13/tick-tick-tick.html" title="Email to a friend/colleague" target="_blank">
307
+ <img src="http://media.boingboing.net/wp-content/themes/2012/sundries/share.png" style="margin-left:-60px;">
308
+ </a>
309
+ </span>
310
+
311
+ <span class="fbDiv">
312
+ <a href="http://www.facebook.com/sharer.php?u=http://boingboing.net/2014/04/13/tick-tick-tick.html" target='_blank'>
313
+ <img src="http://media.boingboing.net/wp-content/themes/2012/sundries/share.png" style="margin-left:-42px;">
314
+ </a>
315
+ </span>
316
+
317
+ <span class="twitterDiv">
318
+ <a href="http://twitter.com/home?status=Tick%2C+tick%2C%26nbsp%3Btick: http://boingboing.net/2014/04/13/tick-tick-tick.html" target='_blank' title='Click to Tweet this page'>
319
+ <img src="http://media.boingboing.net/wp-content/themes/2012/sundries/share.png" style="margin-left:-27px;">
320
+ </a>
321
+ </span>
322
+
323
+ </div>
324
+ <p class="byline permalink"><a href="http://boingboing.net/author/cory_doctorow_1" title="Posts by Cory Doctorow" rel="author">Cory Doctorow</a> at 8:00 pm Sun, Apr 13, 2014 </p>
325
+
326
+
327
+ </div>
328
+
329
+ <!-- RIGHT HAND ADS -->
330
+
331
+ <div id="sidebar">
332
+ <div class="sidebar_item">
333
+ <!-- 300x250_temp_top_sidebar -->
334
+ <div id='div-gpt-ad-1388426870729-0' style='width:300px; height:250px;'>
335
+ <script type='text/javascript'>
336
+ googletag.cmd.push(function() { googletag.display('div-gpt-ad-1388426870729-0'); });
337
+ </script>
338
+ </div>
339
+ </div>
340
+
341
+ <div id="wrap300">
342
+ <p id="featuretitle">&mdash; FEATURED &mdash;
343
+
344
+ <div id="features" >
345
+
346
+
347
+ <div class="features-item">
348
+
349
+ <a href="http://boingboing.net/2014/04/14/a-vindication-for-the-public.html"><img class="sidebarThumb" style="margin-top:2px;" src="http://media.boingboing.net/wp-content/uploads/2014/04/snow1.jpg"></a>
350
+
351
+ <p style="margin:0px 0px 3px 0px;text-transform:uppercase;font-size:12px;font-weight:bold;"><a href="http://boingboing.net/2014/04/14/a-vindication-for-the-public.html" style="color:#C00">THE LATEST</a></p>
352
+ <p style="margin: 0px;font-size:13px;line-height:1"><a href="http://boingboing.net/2014/04/14/a-vindication-for-the-public.html">A Vindication for the Public: Guardian and Washington Post Win Pulitzer Prize (A statement from Edward&nbsp;Snowden)</a>
353
+
354
+
355
+ </div>
356
+
357
+
358
+
359
+
360
+
361
+ <div class="features-item">
362
+
363
+ <a href="http://boingboing.net/2014/04/14/77-fun-ways-to-play-fast-movin.html"><img class="sidebarThumb" style="margin-top:2px;" src="http://media.boingboing.net/wp-content/uploads/2014/04/tenzi-pattern.jpg"></a>
364
+
365
+ <p style="margin:0px 0px 3px 0px;text-transform:uppercase;font-size:12px;font-weight:bold;"><a href="http://boingboing.net/2014/04/14/77-fun-ways-to-play-fast-movin.html" style="color:#C00">Family</a></p>
366
+ <p style="margin: 0px;font-size:13px;line-height:1"><a href="http://boingboing.net/2014/04/14/77-fun-ways-to-play-fast-movin.html">77 fun ways to play fast-moving Tenzi dice&nbsp;game</a>
367
+
368
+
369
+ </div>
370
+
371
+ <div class="features-item">
372
+
373
+ <a href="http://boingboing.net/2014/04/14/diableries-stereoscopic-adven.html"><img class="sidebarThumb" style="margin-top:2px;" src="http://media.boingboing.net/wp-content/uploads/2014/04/Screen-Shot-2014-04-13-at-7.41.53-PM.jpg"></a>
374
+
375
+ <p style="margin:0px 0px 3px 0px;text-transform:uppercase;font-size:12px;font-weight:bold;"><a href="http://boingboing.net/2014/04/14/diableries-stereoscopic-adven.html" style="color:#C00">Book Review</a></p>
376
+ <p style="margin: 0px;font-size:13px;line-height:1"><a href="http://boingboing.net/2014/04/14/diableries-stereoscopic-adven.html">Diableries: Stereoscopic Adventures in Hell (book&nbsp;review)</a>
377
+
378
+
379
+ </div>
380
+
381
+ <div class="features-item">
382
+
383
+ <a href="http://boingboing.net/2014/04/13/tv-recap-game-of-thrones-th.html"><img class="sidebarThumb" style="margin-top:2px;" src="http://media.boingboing.net/wp-content/uploads/2014/04/gotth1.jpg"></a>
384
+
385
+ <p style="margin:0px 0px 3px 0px;text-transform:uppercase;font-size:12px;font-weight:bold;"><a href="http://boingboing.net/2014/04/13/tv-recap-game-of-thrones-th.html" style="color:#C00">Recap</a></p>
386
+ <p style="margin: 0px;font-size:13px;line-height:1"><a href="http://boingboing.net/2014/04/13/tv-recap-game-of-thrones-th.html">TV recap: Game Of Thrones 'The Lion And The Rose' [season 4, episode&nbsp;2]</a>
387
+
388
+
389
+ </div>
390
+
391
+
392
+ </div>
393
+
394
+ <div id="sidebar_adblock">
395
+
396
+ <!--[if !IE]> -->
397
+ <noscript id="adblock_noscript">
398
+ <p style="text-align:center;margin-top:0px"><small><a href="mailto:inquiries@boingboing.net">ADVERTISE AT BOING BOING!</a></small>
399
+ <!-- <![endif]-->
400
+
401
+ <div class="sidebar_item">
402
+ <iframe id="ad_squares_frame" class="ad" src="http://boingboing.net/wp-content/themes/2012/ads/ad_squares.html?v=11&fm_url=http://boingboing.net/2014/04/13/tick-tick-tick.html" frameborder="0" scrolling="no" marginheight="0" marginwidth="0" topmargin="0" leftmargin="0" allowtransparency="true" width="300px" height="300px"> </iframe>
403
+ </div>
404
+
405
+ <div class="sidebar_item">
406
+
407
+ <iframe id="ad_300_frame" src="http://boingboing.net/wp-content/themes/2012/ads/ad_300.html?fm_url=http://boingboing.net/2014/04/13/tick-tick-tick.html&fm_custom_kvs=category%3Dpost&v=0" frameborder="0" scrolling="no" marginheight="0" marginwidth="0" topmargin="0" leftmargin="0" allowtransparency="true" width="300px"> </iframe>
408
+
409
+ </div>
410
+
411
+
412
+
413
+
414
+
415
+ <p id="featuretitle">&mdash; COMICS &mdash;
416
+ <div id="features" >
417
+
418
+ <div class="features-item">
419
+
420
+ <a href="http://boingboing.net/2014/04/09/tom-the-dancing-bug-learning.html"><img class="sidebarThumb" src="http://media.boingboing.net/wp-content/uploads/2014/04/1183cbTHUMB-twitter-events.jpg"></a>
421
+
422
+ <p style="margin:0px 0px 3px 0px;text-transform:uppercase;font-size:12px;font-weight:bold;"><a href="http://boingboing.net/2014/04/09/tom-the-dancing-bug-learning.html" style="color:#C00">Tom the Dancing Bug</a></p>
423
+ <p style="margin: 0px;font-size:13px;line-height:1"><a href="http://boingboing.net/2014/04/09/tom-the-dancing-bug-learning.html">TOM THE DANCING BUG: Learning Big News on Twitter, Through the&nbsp;Ages</a>
424
+
425
+ </div>
426
+
427
+ <div class="features-item">
428
+
429
+ <a href="http://boingboing.net/2014/04/08/brain-rot-hip-hop-family-tree-97.html"><img class="sidebarThumb" src="http://media.boingboing.net/wp-content/uploads/2014/04/hip-hop-strip-99-thumb.jpg"></a>
430
+
431
+ <p style="margin:0px 0px 3px 0px;text-transform:uppercase;font-size:12px;font-weight:bold;"><a href="http://boingboing.net/2014/04/08/brain-rot-hip-hop-family-tree-97.html" style="color:#C00">Brain Rot</a></p>
432
+ <p style="margin: 0px;font-size:13px;line-height:1"><a href="http://boingboing.net/2014/04/08/brain-rot-hip-hop-family-tree-97.html">Brain Rot: Hip Hop Family Tree, The Infamous Style Wars Film&nbsp;Screening</a>
433
+
434
+ </div>
435
+
436
+ <div class="features-item">
437
+
438
+ <a href="http://boingboing.net/2014/04/02/tom-the-dancing-bug-hobby-lob.html"><img class="sidebarThumb" src="http://media.boingboing.net/wp-content/uploads/2014/04/1182cbTHUMB-news-hobby-lobby.jpg"></a>
439
+
440
+ <p style="margin:0px 0px 3px 0px;text-transform:uppercase;font-size:12px;font-weight:bold;"><a href="http://boingboing.net/2014/04/02/tom-the-dancing-bug-hobby-lob.html" style="color:#C00">Tom the Dancing Bug</a></p>
441
+ <p style="margin: 0px;font-size:13px;line-height:1"><a href="http://boingboing.net/2014/04/02/tom-the-dancing-bug-hobby-lob.html">TOM THE DANCING BUG: Hobby Lobby, Inc., Changes Its&nbsp;Religion</a>
442
+
443
+ </div>
444
+
445
+ </div>
446
+
447
+
448
+ <p id="featuretitle">&mdash; RECENTLY &mdash;
449
+
450
+ <div id="features" >
451
+ <div class="features-item">
452
+
453
+ <a href="http://boingboing.net/2014/04/10/a-canticle-for-leibowitz-vene.html"><img class="sidebarThumb" style="margin-top:2px;" src="http://media.boingboing.net/wp-content/uploads/2014/04/Screen-Shot-2014-04-10-at-8.49.13-AM.png"></a>
454
+
455
+ <p style="margin:0px 0px 3px 0px;text-transform:uppercase;font-size:12px;font-weight:bold;"><a href="http://boingboing.net/2014/04/10/a-canticle-for-leibowitz-vene.html" style="color:#C00">Book Review</a></p>
456
+ <p style="margin: 0px;font-size:13px;line-height:1"><a href="http://boingboing.net/2014/04/10/a-canticle-for-leibowitz-vene.html">A Canticle for Leibowitz, venerated science fiction&nbsp;masterpiece</a>
457
+
458
+
459
+ </div>
460
+
461
+ <div class="features-item">
462
+
463
+ <a href="http://boingboing.net/2014/04/08/the-adjacent-by-christopher-p.html"><img class="sidebarThumb" style="margin-top:2px;" src="http://media.boingboing.net/wp-content/uploads/2014/04/christpherpreist.jpg"></a>
464
+
465
+ <p style="margin:0px 0px 3px 0px;text-transform:uppercase;font-size:12px;font-weight:bold;"><a href="http://boingboing.net/2014/04/08/the-adjacent-by-christopher-p.html" style="color:#C00">Review</a></p>
466
+ <p style="margin: 0px;font-size:13px;line-height:1"><a href="http://boingboing.net/2014/04/08/the-adjacent-by-christopher-p.html">The Adjacent, by Christopher Priest [exclusive&nbsp;excerpt]</a>
467
+
468
+
469
+ </div>
470
+
471
+ <div class="features-item">
472
+
473
+ <a href="http://boingboing.net/2014/04/08/the-unthinkable-blooms-on-hann.html"><img class="sidebarThumb" style="margin-top:2px;" src="http://media.boingboing.net/wp-content/uploads/2014/04/hanth.jpg"></a>
474
+
475
+ <p style="margin:0px 0px 3px 0px;text-transform:uppercase;font-size:12px;font-weight:bold;"><a href="http://boingboing.net/2014/04/08/the-unthinkable-blooms-on-hann.html" style="color:#C00">Recap</a></p>
476
+ <p style="margin: 0px;font-size:13px;line-height:1"><a href="http://boingboing.net/2014/04/08/the-unthinkable-blooms-on-hann.html">The unthinkable blooms on Hannibal "Futomono"&nbsp;[s2,e6]</a>
477
+
478
+
479
+ </div>
480
+
481
+ <div class="features-item">
482
+
483
+ <a href="http://boingboing.net/2014/04/08/doubleclicks-celebrate-the-pap.html"><img class="sidebarThumb" style="margin-top:2px;" src="http://media.boingboing.net/wp-content/uploads/2014/04/mqdefault6.jpg"></a>
484
+
485
+ <p style="margin:0px 0px 3px 0px;text-transform:uppercase;font-size:12px;font-weight:bold;"><a href="http://boingboing.net/2014/04/08/doubleclicks-celebrate-the-pap.html" style="color:#C00">Science</a></p>
486
+ <p style="margin: 0px;font-size:13px;line-height:1"><a href="http://boingboing.net/2014/04/08/doubleclicks-celebrate-the-pap.html">Doubleclicks celebrate the paperback of Scatter, Adapt, and Remember with a new&nbsp;song</a>
487
+
488
+
489
+ </div>
490
+
491
+ <div class="features-item">
492
+
493
+ <a href="http://boingboing.net/2014/04/07/restoring-cc-attribution-to-fl.html"><img class="sidebarThumb" style="margin-top:2px;" src="http://media.boingboing.net/wp-content/uploads/2014/04/nohotlinking63.jpg"></a>
494
+
495
+ <p style="margin:0px 0px 3px 0px;text-transform:uppercase;font-size:12px;font-weight:bold;"><a href="http://boingboing.net/2014/04/07/restoring-cc-attribution-to-fl.html" style="color:#C00">Feature</a></p>
496
+ <p style="margin: 0px;font-size:13px;line-height:1"><a href="http://boingboing.net/2014/04/07/restoring-cc-attribution-to-fl.html">Restoring CC attribution to Flickr, because Yahoo broke&nbsp;it</a>
497
+
498
+
499
+ </div>
500
+
501
+
502
+ </div>
503
+
504
+ <div class="sidebar_item">
505
+
506
+ <iframe id="ad_t-shirts_frame" src="http://media.boingboing.net/wp-content/themes/2012/ads/ad_t-shirts.html?v=1" frameborder="0" scrolling="no" marginheight="0" marginwidth="0" topmargin="0" leftmargin="0" allowtransparency="true" width="300px" height="300px"> </iframe>
507
+
508
+ </div>
509
+
510
+
511
+
512
+
513
+
514
+
515
+ <div id="ad_skyscraper" style="">
516
+ <div class="sidebar_item">
517
+ <!-- FM Wide Skyscraper 1 Zone -->
518
+ <iframe src="http://boingboing.net/wp-content/themes/2012/ads/ad_skyscraper.html?fm_url=http://boingboing.net/2014/04/13/tick-tick-tick.html&fm_custom_kvs=category%3Dpost" frameborder="0" scrolling="no" marginheight="0" marginwidth="0" topmargin="0" leftmargin="0" allowtransparency="true" width="160px" height="600px"> </iframe>
519
+ <!-- FM Wide Skyscraper 1 Zone -->
520
+ </div>
521
+ </div>
522
+ </div>
523
+
524
+ <p id="featuretitle">&mdash; FOLLOW US &mdash;
525
+ <p style="text-align:center;"><small>Find us on <a href="http://twitter.com/boingboing">Twitter</a>, <a href="https://plus.google.com/+BoingBoing" rel="publisher">Google+</a>, <a href="irc://irc.freenode.net/boingboing">IRC</a>, and <a href="http://facebook.com/boingboing">Facebook</a>. Subscribe to our <a href="http://feeds.boingboing.net/boingboing/iBag">RSS feed</a> or <a href="http://boingboing.us2.list-manage.com/subscribe?u=0e91f8e7df61da4bff2bd9b1f&id=fa324756a4">daily email</a>.</small>
526
+ <p>&nbsp;
527
+
528
+ <p id="featuretitle">&mdash; POLICIES &mdash;
529
+ <p style="text-align:center;"><small>Please read our <a href="http://boingboing.net/tos">Terms of Service</a>, <a href="http://boingboing.net/privacy">Privacy Policy</a>, and <a href="http://boingboing.net/community">Community Guidelines</a>. Except where indicated, Boing Boing is licensed under a Creative&nbsp;Commons License permitting <a href="http://creativecommons.org/licenses/by-nc/2.5/">non-commercial sharing with attribution</a></small>
530
+
531
+ <p>&nbsp;
532
+ <p id="featuretitle">&mdash; FONTS &mdash;
533
+ <p style="text-align:center;"><a href="https://typekit.com"><img src="http://media.boingboing.net/wp-content/uploads/2013/04/typekit-logo.jpg"></a>
534
+
535
+ <!--[if !IE]> -->
536
+ </noscript>
537
+ <!-- <![endif]-->
538
+ </div>
539
+ </div>
540
+
541
+
542
+ </div>
543
+
544
+
545
+ <!-- MAIN POST -->
546
+
547
+ <div id="posts-loop">
548
+
549
+ <div id="post-297258" class="post">
550
+
551
+
552
+
553
+
554
+
555
+ <!-- SHARING BUTTONS -->
556
+ <div id="sidebarPinPoint" style="height:0px;">
557
+ </div>
558
+ <div id="sidebarsticky">
559
+ <div style="" id="newShareBox">
560
+ <div class="sharebutton">
561
+ <div id="fb-root"></div>
562
+ <script>(function(d, s, id) {
563
+ var js, fjs = d.getElementsByTagName(s)[0];
564
+ if (d.getElementById(id)) return;
565
+ js = d.createElement(s); js.id = id;
566
+ js.src = "//connect.facebook.net/en_US/all.js#xfbml=1&appId=403820626333734";
567
+ fjs.parentNode.insertBefore(js, fjs);
568
+ }(document, 'script', 'facebook-jssdk'));</script>
569
+ <div class="fb-like" data-href="http://boingboing.net/2014/04/13/tick-tick-tick.html" data-send="false" data-layout="box_count" data-width="90" data-show-faces="false"></div>
570
+ </div>
571
+
572
+ <div class="sharebutton">
573
+ <a href="https://twitter.com/share" class="twitter-share-button" data-via="BoingBoing" data-count="vertical">Tweet</a>
574
+ <script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
575
+ </div>
576
+
577
+ <div class="sharebutton">
578
+ <!-- Place this tag where you want the su badge to render -->
579
+ <su:badge layout="5"></su:badge>
580
+
581
+ <!-- Place this snippet wherever appropriate -->
582
+ <script type="text/javascript">
583
+ (function() {
584
+ var li = document.createElement('script'); li.type = 'text/javascript'; li.async = true;
585
+ li.src = ('https:' == document.location.protocol ? 'https:' : 'http:') + '//platform.stumbleupon.com/1/widgets.js';
586
+ var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(li, s);
587
+ })();
588
+ </script>
589
+ </div>
590
+
591
+ <div class="sharebutton">
592
+ <!-- Place this tag where you want the +1 button to render. -->
593
+ <div class="g-plusone" data-size="tall"></div>
594
+
595
+ <!-- Place this tag after the last +1 button tag. -->
596
+ <script type="text/javascript">
597
+ (function() {
598
+ var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;
599
+ po.src = 'https://apis.google.com/js/plusone.js';
600
+ var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);
601
+ })();
602
+ </script>
603
+ </div>
604
+
605
+ <div class="sharebutton">
606
+ <div class='kindleWidget kindleLight' style='font-family: sans-serif;'><img src="http://media.boingboing.net/wp-content/plugins/sendtokindle/media/white-15.png" /><span>Kindle</span></div> </div>
607
+ </div>
608
+ </div>
609
+ <div class="post-content sharebuttons">
610
+
611
+ <!-- CONTENT OF THE POST -->
612
+
613
+ <p>
614
+ <img src="http://media.boingboing.net/wp-content/uploads/2014/04/tumblr_n3wstblgoN1socbkko1_5001-300x300.gif" original="http://media.boingboing.net/wp-content/uploads/2014/04/tumblr_n3wstblgoN1socbkko1_5001.gif" mobile="http://media.boingboing.net/wp-content/uploads/2014/04/tumblr_n3wstblgoN1socbkko1_5001-300x300.gif" class="bordered"><br />
615
+ No idea who made this, but it's wonderful. If you know, post in the comments, please.
616
+
617
+ <p>
618
+ <b>Update:</b> It's from <a href="http://beesandbombs.tumblr.com/post/82429759407/this-is-a-bees-bombs-original-accept-no">Bees and Bombs</a>, to which I have just subscribed.
619
+
620
+ <!-- METADATA AND COMMENTS -->
621
+ <div id="metadataBox">
622
+
623
+ <!-- PODCAST EMBEDS/LINKS, IF APPLICABLE -->
624
+
625
+
626
+
627
+
628
+
629
+
630
+ <!-- AUTHOR INFORMATION -->
631
+
632
+ <div id="authorbox">
633
+ <p><a href="http://craphound.com/homeland/buy"> <img src="http://craphound.com/images/homelandbio.jpg" class="bordered" align="left"></a>I write books. My latest is a YA science fiction novel called <a href="http://craphound.com/homeland">Homeland</a> (it's the sequel to <a href="http://craphound.com/littlebrother">Little Brother</a>). More books: <a href="http://craphound.com/rotn">Rapture of the Nerds</a> (a novel, with Charlie Stross); <a href="http://craphound.com/walh">With a Little Help</a> (short stories); and <a href="http://craphound.com/gbbt">The Great Big Beautiful Tomorrow</a> (novella and nonfic). I <a href="https://craphound.com/?page_id=4667">speak all over the place</a> and I <a href="https://twitter.com/doctorow">tweet</a> and <a href="http://mostlysignssomeportents.tumblr.com/">tumble</a>, too. </div>
634
+
635
+ <!-- TAGS -->
636
+
637
+ <div id="tagbox">
638
+ <p>MORE:&nbsp; <a href="http://boingboing.net/tag/animation" rel="tag">animation</a></p>
639
+ </div>
640
+
641
+
642
+
643
+
644
+ <!-- MORE AT BOING BOING from FEATURES -->
645
+
646
+ <div id="moreatboingboing">
647
+
648
+ <h3>More at Boing Boing</h3>
649
+
650
+
651
+
652
+ <div class="moreitem">
653
+ <p><a href="http://boingboing.net/2014/04/13/tv-recap-game-of-thrones-th.html?utm_campaign=moreatbbmetadata&utm_medium=referral&utm_source=boingboing.net" rel="bookmark"><img class="bordered" src="http://media.boingboing.net/wp-content/uploads/2014/04/gotth1.jpg"></a>
654
+
655
+ <p><a href="http://boingboing.net/2014/04/13/tv-recap-game-of-thrones-th.html?utm_campaign=moreatbbmetadata&utm_medium=referral&utm_source=boingboing.net" rel="bookmark">TV recap: Game Of Thrones 'The Lion And The Rose' [season 4, episode&nbsp;2]</a></p>
656
+ </div>
657
+
658
+
659
+
660
+ <div class="moreitem">
661
+ <p><a href="http://boingboing.net/2014/04/08/the-unthinkable-blooms-on-hann.html?utm_campaign=moreatbbmetadata&utm_medium=referral&utm_source=boingboing.net" rel="bookmark"><img class="bordered" src="http://media.boingboing.net/wp-content/uploads/2014/04/hanth.jpg"></a>
662
+
663
+ <p><a href="http://boingboing.net/2014/04/08/the-unthinkable-blooms-on-hann.html?utm_campaign=moreatbbmetadata&utm_medium=referral&utm_source=boingboing.net" rel="bookmark">The unthinkable blooms on Hannibal "Futomono"&nbsp;[s2,e6]</a></p>
664
+ </div>
665
+
666
+
667
+ </div>
668
+
669
+ <div id="ad_500">
670
+ <noscript id="ad_500_noscript">
671
+ <script type="text/javascript">
672
+ function convosuiteLabeling(){
673
+ console.log('convosuiteLabeling');
674
+ google_ad_500_code = "<center><iframe src='http://media.boingboing.net/wp-content/themes/2012/ads/ad_google_rect.html' width='410' height='290' scrolling='no' frameborder='no' style='margin:0;'></iframe><center>";
675
+
676
+ $('#ad_500').css('border-top', '1px solid #CCC');
677
+ $('#ad_500').css('border-bottom', '1px solid #CCC');
678
+ $('#ad_500').css('margin-bottom', '20px');
679
+ $('#ad_500').css('margin-top', '40px');
680
+ $('#ad_500_label').show();
681
+
682
+ if($('#ad_500').height() < 50){
683
+ $('#convosuite_ad').hide();
684
+ $('#google_ad_500').append(google_ad_500_code);
685
+ console.log('Appending google ad code: '+google_ad_500_code);
686
+ }
687
+ }
688
+ $(document).ready(function(){
689
+ // convosuiteLabeling();
690
+ setTimeout('convosuiteLabeling();', 3000);
691
+ });
692
+ </script>
693
+ <style type="text/css">
694
+ .fm-cs-ad {
695
+ margin:18px 0px 18px 0px !important;
696
+ max-width:514px;
697
+ }
698
+ </style>
699
+ <div id="ad_500_label" style="display:none;margin-top:-22px;text-align:center;font-family: 'proxima-nova-condensed', 'Helvetica Neue', Arial, sans-serif;color: #666;">ADVERTISEMENT</div>
700
+ <div id="convosuite_ad">
701
+ <!-- FM Convosuite 650x300 Zone -->
702
+ <script type='text/javascript' src='http://static.fmpub.net/zone/7234'></script>
703
+ <!-- FM Convosuite 650x300 Zone -->
704
+ </div>
705
+ <div id="google_ad_500"></div>
706
+ </noscript>
707
+ <script type="text/javascript">
708
+ if($('#ad_500').is(':visible')) {
709
+ console.debug('Populating desktop 500 spot with document.write');
710
+ document.write($('#ad_500_noscript').text());
711
+ }
712
+ </script>
713
+ </div>
714
+
715
+
716
+
717
+ </div>
718
+
719
+ <div id="comments-container">
720
+
721
+ <div id="comments">
722
+
723
+ <div class="respond">
724
+ <h3 class="reply-title"><a href="http://bbs.boingboing.net/t/tick-tick-tick/28470">Continue the discussion</a> at bbs.boingboing.net</h3>
725
+ <p class='more-replies'>22 replies</p>
726
+ <p>
727
+ <img alt="" src="//www.gravatar.com/avatar/bdd2b71f7e0f6b5e4e2fdf809cd8e3dc.png?s=25&r=pg&d=identicon" class="avatar avatar-25 photo avatar-default" height="25" width="25">
728
+ <img alt="" src="//scdn-discourse.r.worldssl.net/uploads/boingboing/avatars/ce6/573/7c77555a28/25.JPG" class="avatar avatar-25 photo avatar-default" height="25" width="25">
729
+ <img alt="" src="//scdn-discourse.r.worldssl.net/uploads/boingboing/avatars/d13/c17/ebaa887f16/25.jpg" class="avatar avatar-25 photo avatar-default" height="25" width="25">
730
+ <img alt="" src="//www.gravatar.com/avatar/dd477586d6b8bb0b5e25838985ed24cb.png?s=25&r=pg&d=identicon" class="avatar avatar-25 photo avatar-default" height="25" width="25">
731
+ <img alt="" src="//scdn-discourse.r.worldssl.net/uploads/boingboing/avatars/bfe/e7a/10ea6f18f4/25.jpg" class="avatar avatar-25 photo avatar-default" height="25" width="25">
732
+ <img alt="" src="//scdn-discourse.r.worldssl.net/uploads/boingboing/avatars/859/95b/fef8e18140/25.jpg" class="avatar avatar-25 photo avatar-default" height="25" width="25">
733
+ <img alt="" src="//scdn-discourse.r.worldssl.net/uploads/boingboing/avatars/9c9/c8d/983343ab8b/25.jpg" class="avatar avatar-25 photo avatar-default" height="25" width="25">
734
+ <img alt="" src="//scdn-discourse.r.worldssl.net/uploads/boingboing/avatars/dbd/003/583512792e/25.jpg" class="avatar avatar-25 photo avatar-default" height="25" width="25">
735
+ <img alt="" src="//www.gravatar.com/avatar/54052b273cc682b884d2f6151faf8207.png?s=25&r=pg&d=identicon" class="avatar avatar-25 photo avatar-default" height="25" width="25">
736
+ <img alt="" src="//www.gravatar.com/avatar/297418cf750e0c88035cf26cb430111a.png?s=25&r=pg&d=identicon" class="avatar avatar-25 photo avatar-default" height="25" width="25">
737
+ <img alt="" src="//www.gravatar.com/avatar/c1c83f628971c4bd7fc0be6e92ebdc42.png?s=25&r=pg&d=identicon" class="avatar avatar-25 photo avatar-default" height="25" width="25">
738
+ <img alt="" src="//www.gravatar.com/avatar/90ab94a6731be923785e4229028c1a86.png?s=25&r=pg&d=identicon" class="avatar avatar-25 photo avatar-default" height="25" width="25">
739
+ <img alt="" src="//www.gravatar.com/avatar/98bbaa880662d351e021d2f5fb5e40fe.png?s=25&r=pg&d=identicon" class="avatar avatar-25 photo avatar-default" height="25" width="25">
740
+ <img alt="" src="//www.gravatar.com/avatar/b82895a8423e72e133b679d4911045a7.png?s=25&r=pg&d=identicon" class="avatar avatar-25 photo avatar-default" height="25" width="25">
741
+ <img alt="" src="//www.gravatar.com/avatar/899a8a98c0788669af2ca0faba0d12d1.png?s=25&r=pg&d=identicon" class="avatar avatar-25 photo avatar-default" height="25" width="25">
742
+ <img alt="" src="//www.gravatar.com/avatar/f56c317566802c0d69809e2147507d38.png?s=25&r=pg&d=identicon" class="avatar avatar-25 photo avatar-default" height="25" width="25">
743
+ <img alt="" src="//scdn-discourse.r.worldssl.net/uploads/boingboing/avatars/88a/a82/211f2d102d/25.jpg" class="avatar avatar-25 photo avatar-default" height="25" width="25">
744
+ <img alt="" src="//www.gravatar.com/avatar/78d185ccd8b98d3b38f1e4a2ca88796c.png?s=25&r=pg&d=identicon" class="avatar avatar-25 photo avatar-default" height="25" width="25">
745
+ <img alt="" src="//www.gravatar.com/avatar/749e54555e08d2831cdfc817bbcd99dd.png?s=25&r=pg&d=identicon" class="avatar avatar-25 photo avatar-default" height="25" width="25">
746
+ </p>
747
+ </div><!-- #respond -->
748
+
749
+ </div>
750
+ </div>
751
+ </div>
752
+
753
+ </div>
754
+ </div>
755
+
756
+
757
+ <div style="text-align:center;margin-top:25px;">
758
+
759
+ </div>
760
+ <div style="clear:both;"></div>
761
+ </div>
762
+
763
+
764
+
765
+ <p style="clear:both;">
766
+ </div>
767
+
768
+
769
+
770
+ <div id="debugger"></div>
771
+
772
+ <!-- Sitewide javascript -->
773
+ <script type="text/javascript" src="http://media.boingboing.net/wp-content/themes/2012/boingboing.js?v=7"></script>
774
+ <!-- JK Nav by Yu-Jie Lin -->
775
+ <script src="http://media.boingboing.net/wp-content/themes/2012/jquery.jknav.min.js?v=1"></script>
776
+ <!-- Infinite Scroll -->
777
+ <script type="text/javascript" src="http://media.boingboing.net/wp-content/themes/2012/infinitescroll.init.js?v=9"> </script>
778
+
779
+ <!-- Google Plus -->
780
+ <script type="text/javascript">
781
+ (function() {
782
+ var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;
783
+ po.src = 'https://apis.google.com/js/plusone.js';
784
+ var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);
785
+ })();
786
+ </script>
787
+
788
+
789
+ <!-- Disqus javascript -->
790
+ <script type="text/javascript">
791
+ var disqus_shortname = 'boingboing'; // required: replace example with your forum shortname
792
+ /* * * DON'T EDIT BELOW THIS LINE * * */
793
+ (function () {
794
+ var s = document.createElement('script'); s.async = true;
795
+ s.type = 'text/javascript';
796
+ s.src = 'http://' + disqus_shortname + '.disqus.com/count.js';
797
+ (document.getElementsByTagName('HEAD')[0] || document.getElementsByTagName('BODY')[0]).appendChild(s);
798
+ }());
799
+ </script>
800
+
801
+ <!-- Day We Fight Back campaign -->
802
+ <!--[if !(lte IE 8)]><!-->
803
+ <script type="text/javascript">
804
+ (function(){var e=document.createElement("script");e.type="text/javascript";e.async=true;e.src=document.location.protocol+"//d1agz031tafz8n.cloudfront.net/thedaywefightback.js/widget.min.js";var t=document.getElementsByTagName("script")[0];t.parentNode.insertBefore(e,t)})()
805
+ </script>
806
+ <!--<![endif]-->
807
+
808
+ <!-- Analytics-->
809
+ <!-- FM Tracking Pixel -->
810
+ <script type='text/javascript' src='http://static-cf.fmpub.net/site/boingboing'></script>
811
+ <!-- FM Tracking Pixel -->
812
+
813
+ <!-- Mint internal analytics include -->
814
+ <script src="http://mint.boingboing.net/?js" type="text/javascript"></script>
815
+
816
+ <!-- Google Analytics include -->
817
+ <script type="text/javascript">
818
+
819
+ var _gaq = _gaq || [];
820
+ _gaq.push(['_setAccount', 'UA-3839311-1']);
821
+ <!-- Categories -->
822
+ _gaq.push(['_trackEvent', 'Permalink View', 'Category', 'Post']);
823
+
824
+ <!-- Tags -->
825
+ _gaq.push(['_trackEvent', 'Permalink View', 'Tag', 'animation']);
826
+
827
+ _gaq.push(['_setCustomVar', 1, 'MTAuthor', 'Cory Doctorow', 3]);
828
+ _gaq.push(['_trackEvent', 'Permalink View', 'Author', 'Cory Doctorow']);
829
+ _gaq.push(['_trackPageview']);
830
+
831
+ (function() {
832
+ var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
833
+ ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
834
+ var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
835
+ })();
836
+
837
+ </script>
838
+ <!-- end Google Analytics include -->
839
+
840
+ <!-- Blockmetrics include -->
841
+ <script type="text/javascript">
842
+ (function() {
843
+ function async_load(){
844
+ var protocol = ('https:' == document.location.protocol ? 'https://' : 'http://');
845
+ var s = document.createElement('script');
846
+ s.src = protocol + 'blockmetrics.com/static/adblock_detection/js/d.min.js';
847
+ var x = document.getElementsByTagName('script')[0]; x.parentNode.insertBefore(s, x);
848
+ }
849
+ bm_website_code = 'D3D06F828B4511E2';
850
+ jQuery(document).ready(async_load);
851
+ })();
852
+ </script>
853
+ <!-- end Blockmetrics include -->
854
+ <!-- Ads -->
855
+ <div id="ads">
856
+
857
+ <!-- FM AD SKIN Zone -->
858
+ <script type='text/javascript' src='http://static-cf.fmpub.net/zone/3992'></script>
859
+ <!-- FM AD SKIN Zone -->
860
+
861
+ </div>
862
+
863
+
864
+
865
+ </body>
866
+ </html>
867
+
868
+ <div style="clear:both;"></div>
869
+
870
+ </div> <!-- Ends container DIV -->
871
+
872
+
873
+
874
+ <!-- Dynamic page generated in 0.281 seconds. -->
875
+ <!-- Cached page generated by WP-Super-Cache on 2014-04-14 16:47:33 -->
876
+ <!-- super cache -->