html2markdown 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -5,6 +5,8 @@ group :development, :test do
5
5
  # Testing infrastructure
6
6
  gem 'guard'
7
7
  gem 'guard-rspec'
8
+ gem 'vcr'
9
+ gem 'webmock'
8
10
 
9
11
  end
10
12
 
data/Readme.md CHANGED
@@ -1,11 +1,30 @@
1
- ### Yet Another Html to Markdown ruby lib
1
+ ### Simple html to Markdown ruby gem
2
2
  We love markdown, cause it is friendly to edit.
3
- So we want everything to be markdown
3
+ So we want everything to be **markdown**
4
4
 
5
- ### spec is our promise
5
+ ### RSpec is our promise
6
6
  ```ruby
7
7
  p = HTMLPage.new :contents => '<strong>haha</strong>'
8
8
  p.markdown.should == '**haha**'
9
9
  p.contents = '<strong>hehe</strong>'
10
10
  p.markdown!.should == '**hehe**'
11
+
12
+ # you can also define your own node parse
13
+ p.strong do |node,contents|
14
+ "strong text : **#{contents}**"
15
+ end
16
+ p.markdown!.should be_include('strong text')
17
+ ```
18
+
19
+ ### Installation
20
+ * gem
21
+
22
+ ```ruby
23
+ gem install html2markdown
24
+ ```
25
+
26
+ * Rails Gemfile
27
+
28
+ ```ruby
29
+ gem 'html2markdown'
11
30
  ```
@@ -0,0 +1,545 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: http://www.kickstarter.com/projects/1397300529/railsapp
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ Accept:
11
+ - ! '*/*'
12
+ User-Agent:
13
+ - Ruby
14
+ response:
15
+ status:
16
+ code: 200
17
+ message: OK
18
+ headers:
19
+ Server:
20
+ - nginx/1.0.11
21
+ Date:
22
+ - Wed, 28 Mar 2012 23:06:46 GMT
23
+ Content-Type:
24
+ - text/html; charset=utf-8
25
+ Connection:
26
+ - keep-alive
27
+ Status:
28
+ - 200 OK
29
+ Etag:
30
+ - ! '"75da5432903c1b163d600fcf81fa65b1"'
31
+ Set-Cookie:
32
+ - _ksr_session=BAh7ByIPc2Vzc2lvbl9pZCIlNjhlZGU3NGE3NDQxMWNlMmY4ZDc2NTgyYjk4M2Q1N2QiEF9jc3JmX3Rva2VuIjFLSnV1a1c0RWhLbG12cmQwaVpKVjl1b1VLNHdoSW4rSmJ1Y2J3RmpIMUFjPQ%3D%3D--31eac2c89ed04e369b81ef4dd247fbae2098517e;
33
+ path=/
34
+ - abid=BAgiFTk5NDA2OWM4OTY1Y2NhZjI%3D--512e3e9f12894311c8dc10fcb05d3e14f539265c;
35
+ path=/; expires=Sun, 28-Mar-2032 23:06:46 GMT
36
+ - last_page=http%3A%2F%2Fwww.kickstarter.com%2Fprojects%2F1397300529%2Frailsapp;
37
+ path=/; expires=Wed, 28-Mar-2012 23:36:46 GMT
38
+ - request_time=Wed%2C+28+Mar+2012+23%3A06%3A46+-0000; path=/
39
+ Content-Length:
40
+ - '42056'
41
+ Cache-Control:
42
+ - max-age=0, private, must-revalidate
43
+ X-Runtime:
44
+ - '0.139642'
45
+ X-Ua-Compatible:
46
+ - IE=Edge,chrome=1
47
+ body:
48
+ encoding: ASCII-8BIT
49
+ string: ! "<!DOCTYPE html>\n<html class=\"projects_show no-js fontface \" lang=\"en\"
50
+ xml:lang=\"en\" xmlns:fb=\"http://www.facebook.com/2008/fbml\" xmlns=\"http://www.w3.org/1999/xhtml\">\n<head><script
51
+ type=\"text/javascript\">var NREUMQ=NREUMQ||[];NREUMQ.push([\"mark\",\"firstbyte\",new
52
+ Date().getTime()]);</script><title>rails.app by Yehuda Katz &mdash; Kickstarter</title><!--[if
53
+ lt IE 9]>\n <script src=\"http://html5shim.googlecode.com/svn/trunk/html5.js\"
54
+ type=\"text/javascript\"></script>\n<![endif]-->\n\n\n<meta content=\"text/html;
55
+ charset=utf-8\" http-equiv=\"Content-Type\">\n<meta content=\"telephone=no\"
56
+ name=\"format-detection\">\n<link href=\"/fonts/fonts.css\" media=\"screen\"
57
+ rel=\"stylesheet\" type=\"text/css\">\n<link href=\"http://d297h9he240fqh.cloudfront.net/cache-e1f3b9f54/assets/project_page.css\"
58
+ media=\"screen\" rel=\"stylesheet\" type=\"text/css\" />\n<!--[if lte IE 7]>\n
59
+ \ <link href=\"http://d297h9he240fqh.cloudfront.net/cache-e1f3b9f54/stylesheets/compass/library/ie.css\"
60
+ media=\"screen\" rel=\"stylesheet\" type=\"text/css\" />\n<![endif]-->\n\n<link
61
+ href=\"http://d297h9he240fqh.cloudfront.net/cache-e1f3b9f54/favicon.png\"
62
+ rel=\"icon\" type=\"image/png\">\n<link href=\"http://d297h9he240fqh.cloudfront.net/cache-e1f3b9f54/apple-touch-icon-precomposed.png\"
63
+ rel=\"apple-touch-icon-precomposed\" type=\"image/png\">\n<link href=\"http://d297h9he240fqh.cloudfront.net/cache-e1f3b9f54/apple-touch-icon-ipad-precomposed.png\"
64
+ rel=\"apple-touch-icon-precomposed\" sizes=\"72x72\" type=\"image/png\">\n<link
65
+ href=\"http://d297h9he240fqh.cloudfront.net/cache-e1f3b9f54/apple-touch-icon-iphone4-precomposed.png\"
66
+ rel=\"apple-touch-icon-precomposed\" sizes=\"114x114\" type=\"image/png\">\n<link
67
+ href=\"http://www.kickstarter.com/services/oembed?url=http%3A%2F%2Fwww.kickstarter.com%2Fprojects%2F1397300529%2Frailsapp\"
68
+ rel=\"alternate\" title=\"rails.app Script Tag oEmbed\" type=\"application/json+oembed\">\n<link
69
+ rel=\"alternate\" type=\"application/atom+xml\" title=\"rails.app : Kickstarter\"
70
+ href=\"http://www.kickstarter.com/projects/1397300529/railsapp/posts.atom\"
71
+ />\n<meta name=\"description\" content=\"Yehuda Katz is raising funds for
72
+ rails.app on Kickstarter! \n\n Let's make Rails on OS X easy again!\n\n&quot;Install
73
+ this .app. Good job, you now have a working Rails install!&quot;\"/>\n<meta
74
+ property=\"fb:app_id\" content=\"69103156693\"/>\n<meta property=\"og:type\"
75
+ content=\"kickstarter:project\"/>\n<meta property=\"kickstarter:location:longitude\"
76
+ content=\"-122.419\"/>\n<meta property=\"og:image\" content=\"http://s3.amazonaws.com/ksr/projects/82738/photo-full.jpg?1331014996\"/>\n<meta
77
+ property=\"og:site_name\" content=\"Kickstarter\"/>\n<meta name=\"title\"
78
+ content=\"Kickstarter &gt;&gt; rails.app by Yehuda Katz\"/>\n<meta property=\"kickstarter:location:latitude\"
79
+ content=\"37.7749\"/>\n<meta property=\"og:title\" content=\"rails.app\"/>\n<meta
80
+ property=\"og:description\" content=\"Let's make Rails on OS X easy again!\n\n&quot;Install
81
+ this .app. Good job, you now have a working Rails install!&quot;\"/>\n<meta
82
+ property=\"og:url\" content=\"http://www.kickstarter.com/projects/1397300529/railsapp\"/>\n<meta
83
+ name=\"csrf-param\" content=\"authenticity_token\"/>\n<meta name=\"csrf-token\"
84
+ content=\"KJuukW4EhKlmvrd0iZJV9uoUK4whIn+JbucbwFjH1Ac=\"/>\n<link href=\"http://kck.st/HfUVql\"
85
+ rel=\"shorturl\">\n<link href=\"http://www.kickstarter.com/projects/1397300529/railsapp\"
86
+ rel=\"canonical\">\n<link href=\"http://s3.amazonaws.com/ksr/projects/82738/photo-med.jpg?1331014996\"
87
+ rel=\"image_src\">\n\n<script>\n //<![CDATA[\n var _sf_startpt=(new Date()).getTime();\n
88
+ \ docElement = this.document.documentElement;\n docElement.className=docElement.className.replace(/\\bno-js\\b/,'')
89
+ + 'js';\n //]]>\n</script>\n<script>\n //<![CDATA[\n function timeRemaining(epochTime){\n
90
+ \ \n var diff = epochTime - ((new Date()).getTime() / 1000);\n var
91
+ num_unit = (diff < 60 && [Math.max(diff, 0), 'seconds']) ||\n ((diff/=60)
92
+ < 60 && [diff, 'minutes']) ||\n ((diff/=60) < 72 && [diff, 'hours'])
93
+ ||\n [diff/=24, 'days'];\n \n // Round down\n num_unit[0]
94
+ = Math.floor(num_unit[0]);\n // Singularize unit\n if (num_unit[0]
95
+ == 1) { num_unit[1] = num_unit[1].replace(/s$/,\"\"); }\n \n return
96
+ num_unit;\n };\n //]]>\n</script>\n</head>\n\n<body class=\"project projects\"
97
+ id=\"projects_show\">\n<div class=\"jGrowl center\" id=\"growl_section\"></div>\n<div
98
+ id=\"learn-more-wrap\">\n<div class=\"container\" id=\"learn-more\">\n<p>\n<span
99
+ class=\"icon-whaaat\"></span>\n<strong>What is Kickstarter?</strong>\nWe’re
100
+ the world's largest funding platform for creative projects.\n<a href=\"#\"
101
+ class=\"link_to_learn-more-dialog\">Learn more!</a>\n</p>\n</div>\n</div>\n<div
102
+ id=\"header-wrap\">\n<div class=\"container\" id=\"header\">\n<h1 id=\"logo\"><a
103
+ href=\"/\"><span>Kickstarter</span></a></h1>\n<ul id=\"menu-main\">\n<li id=\"menu-main-discover\"><a
104
+ href=\"/discover\"><strong>Discover</strong> <span>great projects</span></a></li>\n<li
105
+ id=\"menu-main-fund\"><a href=\"/start\"><strong>Start</strong> <span>your
106
+ project</span></a></li>\n</ul>\n<form accept-charset=\"UTF-8\" action=\"/projects/search\"
107
+ class=\"search\" method=\"get\"><div style=\"margin:0;padding:0;display:inline\"><input
108
+ name=\"utf8\" type=\"hidden\" value=\"&#x2713;\" /></div>\n<div class=\"field
109
+ search\">\n<span class=\"icon-search\"></span>\n<span class=\"icon-search-clear\"></span>\n<input
110
+ class=\"input-search header text\" data-tracker-name=\"Header Live Search\"
111
+ id=\"term\" name=\"term\" type=\"text\" />\n<span class=\"icon-search-nipple\"></span>\n</div>\n</form>\n\n<ul
112
+ id=\"menu-sub\">\n<li id=\"menu-sub-blog\"><a href=\"/blog\">Blog</a></li>\n<li
113
+ id=\"menu-sub-help\"><a href=\"/help\">Help</a></li>\n<li><a href=\"https://www.kickstarter.com/signup\">Sign
114
+ up</a></li>\n<li><a href=\"https://www.kickstarter.com/login\">Log in</a></li>\n</ul>\n</div>\n</div>\n<div
115
+ id=\"search_results-wrap\">\n<div id=\"search_results-shadow\">\n<div id=\"search_results-inner_wrap\">\n<div
116
+ class=\"container\" id=\"search_results\">\n<a class=\"close\"><span class=\"icon-x\"></span>\nClose</a>\n<h2
117
+ class=\"header\"></h2>\n<div id=\"search_results_panel\"></div>\n<p class=\"footer\"></p>\n<a
118
+ class=\"prev arrow\">\n<span class=\"icon-search-left\"></span>\n<strong>Previous</strong>\n</a>\n<a
119
+ class=\"next arrow\">\n<span class=\"icon-search-right\"></span>\n<strong>Next</strong>\n</a>\n</div>\n</div>\n</div>\n</div>\n\n\n\n\n\n<div
120
+ id=\"running-board-wrap\">\n<div class=\"container\" id=\"running-board\">\n<div
121
+ id=\"project-header\">\n<div class=\"NS-project_-running_board\">\n<div id=\"headrow\">\n<h1
122
+ id=\"name\"><a href=\"/projects/1397300529/railsapp\">rails.app</a></h1>\n<p>\n<span
123
+ data-project-category=\"Technology\" id=\"project_category\">\nAn\n<a href=\"/discover/categories/Open%20Software?ref=project\">Open
124
+ Software</a>\n</span>\nproject\nin\n<a href=\"/discover/cities/san-francisco-ca?ref=project\">San
125
+ Francisco, CA</a>\nby\n<a href=\"/profile/1397300529\" id=\"byline\">Yehuda
126
+ Katz</a>\n·\n<a href=\"/projects/1397300529/railsapp/messages/new?message[to]=1397300529\"
127
+ class=\"send-message remote_modal_dialog\" data-modal-title=\"Send a Message
128
+ to Yehuda Katz\">send message</a>\n</p>\n</div>\n\n<ul id=\"widgets\">\n<li
129
+ class=\"ajax-container\" id=\"following-widget\">\n<div id=\"follow-tip\">\n<p>Don't
130
+ want to forget? We'll remind you by email 48 hours before funding ends.</p>\n<span
131
+ class=\"nipple\"></span>\n</div>\n<div id=\"follow\">\n<a href=\"/projects/1397300529/railsapp/follow\"
132
+ class=\"button-remind-me\" data-ksrjson=\"true\">Remind Me</a>\n</div>\n\n</li>\n</ul>\n<ul
133
+ class=\"menu-tabs\" id=\"running-board-nav\">\n<li>\n<a href=\"/projects/1397300529/railsapp\"
134
+ class=\"current\" id=\"home\">Project Home</a>\n</li>\n<li>\n<a href=\"/projects/1397300529/railsapp/posts\"
135
+ id=\"updates\">Updates <span class='count'>0</span></a>\n</li>\n<li>\n<a href=\"/projects/1397300529/railsapp/backers\"
136
+ id=\"backers\">Backers <span class='count'>147</span></a>\n</li>\n<li>\n<a
137
+ href=\"/projects/1397300529/railsapp/comments\" id=\"comments\">Comments <span
138
+ class='count'>3</span></a>\n</li>\n</ul>\n</div>\n\n</div>\n</div>\n</div>\n<div
139
+ id=\"content-wrap\">\n<div class=\"container\" id=\"content\">\n\n<div class=\"NS-projects-content\">\n<div
140
+ id=\"leftcol\">\n\n<div id=\"video-section\">\n<img alt=\"Photo-full\" src=\"http://s3.amazonaws.com/ksr/projects/82738/photo-full.jpg?1331014996\"
141
+ />\n</div>\n<div class=\"share-box-wrap\">\n<table class=\"share-box\">\n<tbody>\n<tr>\n<td
142
+ class=\"facebook first\">\n<fb:like data-tracker-name=\"Facebook\" font=\"lucida
143
+ grande\" href=\"http://www.kickstarter.com/projects/1397300529/railsapp\"
144
+ show_faces=\"false\" width=\"251\"></fb:like>\n</td>\n<td class=\"twitter\">\n<a
145
+ class=\"twitter-share-button\" data-count=\"none\" data-tracker-name=\"Twitter\"
146
+ data-url=\"http://kck.st/HfUVql\" data-via=\"kickstarter\" href=\"http://twitter.com/share\"></a>\n</td>\n<td
147
+ class=\"embed\">\n<a href=\"/projects/1397300529/railsapp/widget\" class=\"button-action
148
+ remote_modal_dialog\" data-modal-title=\"Embed a widget on your site\" data-tracker-name=\"Embed\"><span
149
+ class='icon-embed'></span>Embed</a>\n</td>\n<td class=\"short-link\">\n<input
150
+ class=\"text\" id=\"share_a_link\" name=\"share_a_link\" type=\"text\" value=\"http://kck.st/HfUVql\"
151
+ />\n<div class=\"copy_button\">\n<a href=\"\" class=\"copy-button zeroclipboard\"
152
+ data-text=\"http://kck.st/HfUVql\" data-tracker-name=\"Copy Link\">Copy</a>\n</div>\n</td>\n</tr>\n</tbody>\n</table>\n</div>\n\n<div
153
+ data-project-state=\"live\" id=\"about\">\n<h3 class=\"dotty\">About this
154
+ project<div class=\"clear\"></div></h3><p><b>Let's make Rails on OS X easy
155
+ again!</b></p><p>Getting started with Rails on OS X has gotten hard. When
156
+ I started working with Rails in 2005, a beginner could get up and running
157
+ by downloading and running Locomotive. Locomotive made good on the implicit
158
+ promise of the original <a href=\"http://media.rubyonrails.org/video/rails-0-5.mov\"
159
+ target=\"_blank\">Get Excited screencast</a>: within minutes, you too can
160
+ feel the power of Ruby on Rails.</p><p>By the time I became a member of the
161
+ Rails core team and began work on Rails 3, Locomotive was abandonware. Since
162
+ OS X shipped with Ruby 1.8, it seemed like a simple `gem install` would do
163
+ the trick. And for many people, it did.</p><p>Since then, the Ruby ecosystem
164
+ has become increasingly sophisticated, making tools like bundler and rvm (or
165
+ rbenv, if that's your thing) a part of the standard workflow. And as those
166
+ tools increasingly became part of the toolchain for experienced developers,
167
+ we lost track of the complexity of setting up the standard Ruby toolchain.</p><p>Even
168
+ more frustrating, every piece of the toolchain has multiple options, meaning
169
+ that new developers are faced with needing to choose between rvm and rbenv,
170
+ Ruby 1.8 and Ruby 1.9, etc.</p><p>For experienced developers, these hurdles
171
+ may not seem particularly large, but they frequently chase away enthusiastic
172
+ newcomers at exactly the wrong time.</p><p><b>Enough is enough. </b>We need
173
+ a way to get up and running with Rails that is as conventional and pleasant
174
+ as Rails itself.</p><p><b>I have a track record of delivering OSS projects.
175
+ </b>For the past five years, I have worked on a number of popular open source
176
+ projects. I am probably most well-known for my work on Rails following its
177
+ merge with Merb, where I was the maintainer.</p><p>My goals for Rails 3 were
178
+ to bring Merb's ethic of modularity and extensibility to Rails, and Rails
179
+ 3 shipped with a stable plugin API that has paved the way for a richer extension
180
+ ecosystem. Jose Valim's book, <a href=\"http://pragprog.com/book/jvrails/crafting-rails-applications\"
181
+ target=\"_blank\">Crafting Rails Applications</a>, illustrates the power of
182
+ many of these extensions.</p><p>When I began work on Rails 3, the Rails ecosystem
183
+ desperately needed a stable foundation for long-term extensions. Today, the
184
+ Rails ecosystem desperately needs to get back to basics and make the experience
185
+ of starting fresh exciting again.</p><p>I have the track record and skills
186
+ to deliver a polished, maintainable solution that can become part of the Rails
187
+ project. Please help me get this done.</p><h1>Deliverables</h1><p>Many of
188
+ the necessary components for rails.app already exist in some form. <b>I do
189
+ not want to duplicate existing efforts</b>, where those efforts already solve
190
+ some part of the larger problem. I will deliver a project that lives in the
191
+ `rails` organization on GitHub, can be maintained by the Rails team and shipped
192
+ as part of the official releases.</p><p>My plan is to deliver a `.app` that
193
+ can be downloaded and dragged to the user's `/Applications` folder. At first,
194
+ the application will have two facilities:</p><ul>\n<li>Install Rails into
195
+ the system: This will install a working copy of Ruby, Rubygems, Rails and
196
+ all necessary gems into the user's system, available from the Terminal. It
197
+ may also install rvm and other common system tools, depending on the feedback
198
+ I get from the community as I develop this project.</li>\n<li>Open a Terminal
199
+ with a working Rails environment: This will leave all necessary resources
200
+ in the `.app` file or `Application Support`, but open a terminal window with
201
+ the `$PATH` and other variables set up.</li>\n</ul><p>The second option will
202
+ be the preferred option for new users, as it will be a more controlled environment
203
+ with fewer opportunities for something to go wrong. This will not be a toy
204
+ Ruby. It will be a full-fledged Ruby environment running in an isolated sandbox. <b>My
205
+ goal is for this mode to be something I personally would use</b>.</p><p>Over
206
+ time, I imagine that the community would add additional features, such as
207
+ the ability to start and stop the server, generate files, run migrations,
208
+ etc. but these are not part of the initial release goals.</p><p>The finished
209
+ project will also include several facilities to help with long-term maintenance:</p><ul>\n<li>It
210
+ will prompt the user to accept patch-level updates to Ruby or Rails without
211
+ requiring a new download of the entire package.</li>\n<li>Each `.app` will
212
+ be a self-contained environment for a given version of Ruby and Rails, so
213
+ multiple copies can live side-by-side for users who want to work with, for
214
+ example, Rails 3.1 and Rails 3.2 for different projects.</li>\n<li>The release
215
+ of a new version of the `.app` will be fully scripted, working off of release
216
+ tags of the Rails repository. At the very *most* a single rake task will build
217
+ and deploy new versions and make those versions available to the `.app`'s
218
+ updater.</li>\n<li>It will be easy to build a nightly build server for people
219
+ who want to live on the edge.</li>\n</ul><p>If time permits, I also would
220
+ like the framework for building this self-contained `.app` to be useful for
221
+ other projects (such as Compass/Sass) that have a desire to ship self-contained
222
+ environments for working with Ruby-based tools.</p>\n</div>\n<div class=\"NS-projects-faqs\"
223
+ id=\"project-faqs\">\n<h3 class=\"dotty hidden\">\nFAQ\n</h3>\n<ul class=\"faqs\">\n\n</ul>\n<div
224
+ class=\"faq-ask-box\">\n<a href=\"/projects/1397300529/railsapp/messages/new?message[to]=1397300529&amp;mode=FAQ\"
225
+ class=\"remote_modal_dialog button-neutral\" data-modal-title=\"Ask a question
226
+ about rails.app\">Ask a question</a>\n<p>\n<strong>Have a question?</strong>\nIf
227
+ the info above doesn't help, you can ask the project creator directly.\n</p>\n</div>\n</div>\n\n<div
228
+ id=\"report-issue-wrap\">\n<a href=\"/projects/1397300529/railsapp/report/new\"
229
+ class=\"remote_modal_dialog\" data-modal-title=\"Report this project to Kickstarter\"
230
+ id=\"report-issue-link\">Report this project to Kickstarter</a>\n</div>\n</div>\n<div
231
+ class=\"NS-projects-rightcol\" id=\"rightcol\">\n<div class=\"NS-projects-ecom\"
232
+ id=\"moneyraised\">\n<h5>\n<div class=\"num\">147</div>\nBackers\n</h5>\n<h5>\n<div
233
+ class=\"num\">$4,580</div>\npledged of $25,000 goal\n</h5>\n<h5 class=\"ksr_page_timer\"
234
+ data-end_time=\"Sat, 12 May 2012 16:53:15 -0400\">\n<div class=\"num\">&nbsp;</div>\n<span
235
+ class=\"text\">&nbsp;</span>\n</h5>\n<div id=\"banner\">\nThis project will
236
+ only be funded if at least $25,000 is pledged by Saturday May 12, 4:53pm
237
+ EDT.\n</div>\n<div id=\"pledge-wrap\">\n<a href=\"/projects/1397300529/railsapp/pledge/new?clicked_reward=false&amp;logged_in=false&amp;p=0&amp;v=n\"
238
+ class=\"button roundsmall\" id=\"button-back-this-proj\" title=\"Back This
239
+ Project\">Back This Project <small>$1 minimum pledge</small></a>\n</div>\n</div>\n\n<div
240
+ class=\"NS-projects-rightcol-rewards clickable\" id=\"what-you-get\">\n<div
241
+ class=\"NS-projects-reward clickable\">\n<h3>\n<a href=\"/projects/1397300529/railsapp/pledge/new?backing[amount]=10.0&amp;backing[backer_reward_id]=477812&amp;clicked_reward=true&amp;logged_in=false\">Pledge
242
+ $10 or more</a>\n<span>Pledge $10 or more</span>\n</h3>\n<div class=\"backers-limits\">\n<span
243
+ class=\"icon-backer-tag\"></span>\n<span class=\"num-backers\">\n29 Backers\n</span>\n</div>\n<div
244
+ class=\"desc\">\n<p>Receive a handwritten thank you for sponsoring this project.</p>\n</div>\n<div
245
+ class=\"delivery-date\">\n<strong>Estimated Delivery:</strong>\nJun 2012\n</div>\n</div>\n<div
246
+ class=\"NS-projects-reward clickable\">\n<h3>\n<a href=\"/projects/1397300529/railsapp/pledge/new?backing[amount]=25.0&amp;backing[backer_reward_id]=477813&amp;clicked_reward=true&amp;logged_in=false\">Pledge
247
+ $25 or more</a>\n<span>Pledge $25 or more</span>\n</h3>\n<div class=\"backers-limits\">\n<span
248
+ class=\"icon-backer-tag\"></span>\n<span class=\"num-backers\">\n61 Backers\n</span>\n</div>\n<div
249
+ class=\"desc\">\n<p>The previous rewards, plus receive a first-edition backers-only
250
+ sticker so you can show your support. My laptop is graced with an &quot;I'm
251
+ committed&quot; sticker that the Rubinius project gave me for my early contributions--this
252
+ is your chance to spruce up any of your belongings in desperate need of a
253
+ stickering.</p>\n</div>\n<div class=\"delivery-date\">\n<strong>Estimated
254
+ Delivery:</strong>\nJul 2012\n</div>\n</div>\n<div class=\"NS-projects-reward
255
+ clickable\">\n<h3>\n<a href=\"/projects/1397300529/railsapp/pledge/new?backing[amount]=100.0&amp;backing[backer_reward_id]=477814&amp;clicked_reward=true&amp;logged_in=false\">Pledge
256
+ $100 or more</a>\n<span>Pledge $100 or more</span>\n</h3>\n<div class=\"backers-limits\">\n<span
257
+ class=\"icon-backer-tag\"></span>\n<span class=\"num-backers\">\n21 Backers\n</span>\n</div>\n<div
258
+ class=\"desc\">\n<p>The previous rewards, plus access to the internal list
259
+ for the project, where I'll be soliciting feedback about how to nail this.
260
+ Great open source projects rarely come from the ideas of just one person,
261
+ and your input will guarantee that Rails 4 is as great for beginners as it
262
+ is for experienced developers.</p>\n</div>\n<div class=\"delivery-date\">\n<strong>Estimated
263
+ Delivery:</strong>\nMay 2012\n</div>\n</div>\n<div class=\"NS-projects-reward
264
+ clickable\">\n<h3>\n<a href=\"/projects/1397300529/railsapp/pledge/new?backing[amount]=1000.0&amp;backing[backer_reward_id]=477815&amp;clicked_reward=true&amp;logged_in=false\">Pledge
265
+ $1,000 or more</a>\n<span>Pledge $1,000 or more</span>\n</h3>\n<div class=\"backers-limits\">\n<span
266
+ class=\"icon-backer-tag\"></span>\n<span class=\"num-backers\">\n0 Backers\n</span>\n<span
267
+ class=\"limited\">\n&bull; Limited Reward\n(10 of 10 remaining)\n</span>\n</div>\n<div
268
+ class=\"desc\">\n<p>The previous rewards, plus recognition on the project's
269
+ website as a backer. If the price is a bit too steep personally, this is a
270
+ good opportunity to ask your company to contribute to a good cause.</p>\n</div>\n<div
271
+ class=\"delivery-date\">\n<strong>Estimated Delivery:</strong>\nJul 2012\n</div>\n</div>\n<div
272
+ class=\"NS-projects-reward clickable\">\n<h3>\n<a href=\"/projects/1397300529/railsapp/pledge/new?backing[amount]=10000.0&amp;backing[backer_reward_id]=550490&amp;clicked_reward=true&amp;logged_in=false\">Pledge
273
+ $10,000 or more</a>\n<span>Pledge $10,000 or more</span>\n</h3>\n<div class=\"backers-limits\">\n<span
274
+ class=\"icon-backer-tag\"></span>\n<span class=\"num-backers\">\n0 Backers\n</span>\n<span
275
+ class=\"limited\">\n&bull; Limited Reward\n(2 of 2 remaining)\n</span>\n</div>\n<div
276
+ class=\"desc\">\n<p>The previous rewards, plus recognition on the project's
277
+ website as a sponsor. This recognition will appear above the fold on the front
278
+ page for at least one year. If you or your company is building a product that
279
+ appeals to new developers, this is a great way to get some visibility, and
280
+ give back to the community :D\n\nPing me. Let's talk about how we can both
281
+ get the most out of this.</p>\n</div>\n<div class=\"delivery-date\">\n<strong>Estimated
282
+ Delivery:</strong>\nJul 2012\n</div>\n</div>\n\n</div>\n\n<div class=\"NS-projects-rightcol-projectby\"
283
+ id=\"project-by\">\n<h3 class=\"dotty\">Project By<div class=\"clear\"></div></h3><div
284
+ id=\"avatar\">\n<a href=\"/profile/1397300529\"><img alt=\"Fb_profile_picture.large\"
285
+ class=\"avatar-large\" height=\"220\" src=\"http://s3.amazonaws.com/ksr/avatars/441663/fb_profile_picture.large.jpg?1301941659\"
286
+ width=\"220\" /></a>\n</div>\n<div id=\"creator-details\">\n<h3><a href=\"/profile/1397300529\">Yehuda
287
+ Katz</a></h3>\n<p class=\"last-login\">\nLast Login\n03/28/12\n</p>\n<ul>\n<li
288
+ class=\"location\">\n<a href=\"/discover/cities/san-francisco-ca\"><span class='icon'></span>San
289
+ Francisco, CA</a>\n</li>\n<li class=\"backed\">\n<a href=\"/profiles/1397300529/projects/backed\"
290
+ class=\"more-button remote_modal_dialog\" data-modal-title=\"Projects backed
291
+ by Yehuda Katz\"><span class='icon'></span>Backed 2 projects</a>\n</li>\n<li
292
+ class=\"contactme\">\n<a href=\"/projects/1397300529/railsapp/messages/new?message[to]=1397300529\"
293
+ class=\"remote_modal_dialog\" data-modal-title=\"Send A Message to Yehuda
294
+ Katz\"><span class='icon'></span>Send Message</a>\n</li>\n</ul>\n</div>\n<div
295
+ id=\"facebook-connect\">\n<div class=\"icon\"></div>\n<p>Connected\nas\n<a
296
+ href=\"http://facebook.com/16200017\" class=\"popup\" target=\"_blank\">Yehuda
297
+ Katz</a>\n(400&nbsp;friends)\n</p>\n</div>\n<div id=\"biography\">\n<p>I have
298
+ a history of working on hard open source projects and delivering on them.</p>\n\n<p>Since
299
+ 2008, I worked on the Merb project, helped lead the Rails 3 effort, and am
300
+ currently bringing convention over configuration to the browser with Ember.js.</p>\n</div>\n<ol
301
+ id=\"sites\">\n<li>\n<a href=\"http://www.yehudakatz.com\" class=\"popup\"
302
+ rel=\"nofollow\" target=\"_blank\">yehudakatz.com</a>\n</li>\n<li>\n<a href=\"http://github.com/wycats\"
303
+ class=\"popup\" rel=\"nofollow\" target=\"_blank\">github.com</a>\n</li>\n<li>\n<a
304
+ href=\"http://twitter.com/wycats\" class=\"popup\" rel=\"nofollow\" target=\"_blank\">twitter.com</a>\n</li>\n</ol>\n</div>\n\n</div>\n\n</div>\n\n\n</div>\n</div>\n<div
305
+ id=\"project_bar\">\n<div class=\"this_project_id\" style=\"display: none;\">82738</div>\n<div
306
+ class=\"container\">\n<img alt=\"Project_bar_shadow\" class=\"shadow\" src=\"http://d297h9he240fqh.cloudfront.net/cache-e1f3b9f54/images/projects/project_bar_shadow.png\"
307
+ />\n<div class=\"window\">\n<ol class=\"projects\">\n<li class=\"page\">\n<ol></ol>\n</li>\n</ol>\n</div>\n<a
308
+ href=\"#\" class=\"prev arrow enabled\"><div class=\"icon-project-bar-left\"></div>\n</a><a
309
+ href=\"#\" class=\"next arrow enabled\"><div class=\"icon-project-bar-right\"></div>\n</a></div>\n</div>\n\n\n\n\n<div
310
+ id=\"mega-footer-wrap\">\n<div id=\"mega-footer-shadow\">\n<div class=\"container\"
311
+ id=\"mega-footer\">\n<div id=\"mega-discover\">\n<h5>Browse Categories</h5>\n<ul
312
+ class=\"list-footer-categories list-0\">\n<li><a href=\"/discover/categories/art?ref=footer\">Art</a></li>\n<li><a
313
+ href=\"/discover/categories/comics?ref=footer\">Comics</a></li>\n<li><a href=\"/discover/categories/dance?ref=footer\">Dance</a></li>\n<li><a
314
+ href=\"/discover/categories/design?ref=footer\">Design</a></li>\n<li><a href=\"/discover/categories/fashion?ref=footer\">Fashion</a></li>\n<li><a
315
+ href=\"/discover/categories/film%20&amp;%20video?ref=footer\">Film &amp; Video</a></li>\n<li><a
316
+ href=\"/discover/categories/food?ref=footer\">Food</a></li>\n</ul>\n<ul class=\"list-footer-categories
317
+ list-1\">\n<li><a href=\"/discover/categories/games?ref=footer\">Games</a></li>\n<li><a
318
+ href=\"/discover/categories/music?ref=footer\">Music</a></li>\n<li><a href=\"/discover/categories/photography?ref=footer\">Photography</a></li>\n<li><a
319
+ href=\"/discover/categories/publishing?ref=footer\">Publishing</a></li>\n<li><a
320
+ href=\"/discover/categories/technology?ref=footer\">Technology</a></li>\n<li><a
321
+ href=\"/discover/categories/theater?ref=footer\">Theater</a></li>\n</ul>\n</div>\n<div
322
+ id=\"mega-join-like\">\n<form accept-charset=\"UTF-8\" action=\"/newsletters/signup\"
323
+ class=\"overlabels\" method=\"post\"><div style=\"margin:0;padding:0;display:inline\"><input
324
+ name=\"utf8\" type=\"hidden\" value=\"&#x2713;\" /><input name=\"authenticity_token\"
325
+ type=\"hidden\" value=\"KJuukW4EhKlmvrd0iZJV9uoUK4whIn+JbucbwFjH1Ac=\" /></div>\n<h5>Kickstarter's
326
+ weekly newsletter</h5>\n<p>Get awesome projects delivered to your inbox each
327
+ week.</p>\n<textarea class=\"hide textarea\" id=\"comment\" name=\"comment\"></textarea>\n<div
328
+ class=\"field newsletter\">\n<label class=\"overlabel overlabel-newsletter\">Your
329
+ email address...</label>\n<input class=\"text\" id=\"email\" name=\"email\"
330
+ type=\"text\" />\n</div>\n<input class=\"button-positive submit\" id=\"user_submit\"
331
+ name=\"commit\" type=\"submit\" value=\"Join newsletter\" />\n</form>\n\n<h5>Kickstarter
332
+ on Facebook</h5>\n<fb:like href=\"http://facebook.com/kickstarter\" show_faces=\"true\"
333
+ width=\"330\"></fb:like>\n</div>\n<div id=\"mega-connect\">\n<h5>Connect with
334
+ Kickstarter</h5>\n<ul id=\"list-footer-connect\">\n<li><a href=\"http://twitter.com/kickstarter\"
335
+ id=\"footer-twitter\"><span class='icon-footer-twitter'></span>Follow on Twitter</a></li>\n<li><a
336
+ href=\"/blog\" id=\"footer-blog\"><span class='icon-footer-blog'></span>Read
337
+ our blog</a></li>\n<li><a href=\"/team?ref=footer\" id=\"footer-team\"><span
338
+ class='icon-footer-team'></span>Meet the team</a></li>\n<li><a href=\"/jobs?ref=footer\"
339
+ id=\"footer-jobs\"><span class='icon-footer-jobs'></span>Work with us</a></li>\n</ul>\n<span
340
+ class=\"scissors icon-scissors-1\"></span>\n</div>\n</div>\n</div>\n</div>\n<div
341
+ id=\"footer-wrap\">\n<div class=\"container\" id=\"footer\">\n<div id=\"etc\">\n<ul>\n<li><a
342
+ href=\"/help?ref=footer\">Help</a></li>\n<li><a href=\"/help/guidelines?ref=footer\">Guidelines</a></li>\n<li><a
343
+ href=\"/terms-of-use?ref=footer\">Terms of Use</a></li>\n<li><a href=\"/privacy?ref=footer\">Privacy
344
+ Policy</a></li>\n<li class=\"last\"><a href=\"http://kickstarter.zendesk.com/home\"
345
+ id=\"\" onclick=\"Zenbox.render(); return false;\">Contact</a></li>\n</ul>\n</div>\n<div
346
+ id=\"legal\">\n&copy;\n2012\nKickstarter, Inc.\n</div>\n</div>\n</div>\n\n<script>\n
347
+ \ //<![CDATA[\n var gaJsHost = ((\"https:\" == document.location.protocol)
348
+ ? \"https://ssl.\" : \"http://www.\");\n document.write(unescape(\"%3Cscript
349
+ src='\" + gaJsHost + \"google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E\"));\n
350
+ \ var analytics_vars = { google_analytics_id : \"UA-7621056-1\", logged_in
351
+ : \"false\", verifying_backing : \"false\" }\n //]]>\n</script>\n\n\n<script>\n
352
+ \ //<![CDATA[\n _qoptions={qacct:\"p-34IbSpw2K94Sg\"};\n //]]>\n</script>\n<script
353
+ src=\"http://edge.quantserve.com/quant.js\" type=\"text/javascript\"></script>\n<noscript><img
354
+ alt=\"Quantcast\" border=\"0\" height=\"1\" src=\"http://pixel.quantserve.com/pixel/p-34IbSpw2K94Sg.gif\"
355
+ style=\"display:none\" width=\"1\" /></noscript>\n\n<script>\n //<![CDATA[\n
356
+ \ var _sf_async_config={uid:5536,domain:\"kickstarter.com\"};\n (function(){\n
357
+ \ function loadChartbeat() {\n window._sf_endpt=(new Date()).getTime();\n
358
+ \ var e = document.createElement('script');\n e.setAttribute('language',
359
+ 'javascript');\n e.setAttribute('type', 'text/javascript');\n e.setAttribute('src',\n
360
+ \ ((\"https:\" == document.location.protocol) ? \"https://a248.e.akamai.net/chartbeat.download.akamai.com/102508/\"
361
+ : \"http://static.chartbeat.com/\") +\n \"js/chartbeat.js\");\n
362
+ \ document.body.appendChild(e);\n }\n var oldonload = window.onload;\n
363
+ \ window.onload = (typeof window.onload != 'function') ?\n loadChartbeat
364
+ : function() { oldonload(); loadChartbeat(); };\n })();\n //]]>\n</script>\n\n<div
365
+ class=\"modal_dialog\" id=\"learn-more-dialog\" style=\"display: none;\">\n<div
366
+ class=\"modal_dialog_ie6_background\"></div>\n<div class=\"modal_dialog_outer\">\n<div
367
+ class=\"modal_dialog_sizer\">\n<div class=\"modal_dialog_inner\">\n<div class=\"modal_dialog_content\">\n<div
368
+ class=\"modal_dialog_head\"><h4><span>What is Kickstarter?</span></h4><a class=\"modal_dialog_close\"
369
+ href=\"#\"><span class=\"icon-x\">Close</span></a></div>\n<div class=\"modal_dialog_body\">\n<div
370
+ id=\"learn-more\">\n<p><strong>Kickstarter is the world's largest funding
371
+ platform for creative projects.</strong> Every week, tens of thousands of
372
+ amazing people pledge millions of dollars to projects from the worlds of <span
373
+ class='category-1'>music</span>, <span class='category-2'>film</span>, <span
374
+ class='category-3'>art</span>, <span class='category-4'>technology</span>,
375
+ <span class='category-5'>design</span>, <span class='category-6'>food</span>,
376
+ <span class='category-7'>publishing</span> and other creative fields.</p>\n<p>\n<strong>A
377
+ new form of commerce and patronage.</strong>\nThis is not about investment
378
+ or lending. Project creators keep 100% ownership and control over their work.
379
+ Instead, they offer products and experiences that are unique to each project.\n</p>\n<p>\n<strong>All
380
+ or nothing funding.</strong>\nOn Kickstarter, a project must reach its funding
381
+ goal before time runs out or no money changes hands. Why? It protects everyone
382
+ involved. Creators aren’t expected to develop their project without necessary
383
+ funds, and it allows anyone to test concepts without risk.\n</p>\n<p>\n<strong>Each
384
+ and every project is the independent creation of someone like you.</strong>\nProjects
385
+ are big and small, serious and whimsical, traditional and experimental. They’re
386
+ inspiring, entertaining and unbelievably diverse. We hope you agree... Welcome
387
+ to Kickstarter!\n</p>\n<p><a href=\"#\" class=\"modal_dialog_close\">Thanks!
388
+ All done.</a></p>\n</div>\n\n</div>\n</div>\n</div>\n<span class=\"modal_dialog_ie_hack\"></span>\n</div>\n</div>\n</div>\n\n<script
389
+ src=\"http://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js\" type=\"text/javascript\"></script>\n<script>\n
390
+ \ //<![CDATA[\n (function () {\n function PageClock(settings){\n this.local_start_time
391
+ = new Date();\n this.settings = {\n cookie_name : 'request_time'\n
392
+ \ };\n for (var k in settings) {\n this.settings[k]
393
+ = settings[k];\n }\n this.get_remote_offset();\n }\n \n
394
+ \ PageClock.prototype.get_remote_offset = function () {\n // try
395
+ to get remote time from cookie\n this.cookie_value = this.read_cookie();\n
396
+ \ var remote_start_time = new Date( this.cookie_value );\n \n if
397
+ (!this.cookie_value || remote_start_time.toString() === 'Invalid Date') {\n
398
+ \ // try to get the offset from the local_offset cookie, if present\n
399
+ \ // this situation arises when the back button is clicked\n this.remote_offset
400
+ = this.read_cookie('local_offset');\n if (this.remote_offset) {\n
401
+ \ this.remote_offset = parseInt(this.remote_offset, 10);\n }\n
402
+ \ } else {\n this.remote_offset = remote_start_time - this.local_start_time;\n
403
+ \ }\n \n if (typeof this.remote_offset !== 'undefined') {\n
404
+ \ document.cookie = 'local_offset=' + this.remote_offset + '; path=/';\n
405
+ \ this.is_set = true;\n } else {\n this.is_set = false;\n
406
+ \ }\n };\n \n PageClock.prototype.time_units = [\n ['milliseconds',
407
+ 1],\n ['seconds', 1000],\n ['minutes', 1000 * 60],\n ['hours',
408
+ \ 1000 * 60 * 60],\n ['days', 1000 * 60 * 60 * 24]\n ];\n
409
+ \ \n PageClock.prototype.get_units_in_interval = function(unit_name,
410
+ time) {\n var method_name = unit_name.replace(/^\\w/, function(l) {\n
411
+ \ return 'get' + l.toUpperCase();\n });\n return time[method_name]();\n
412
+ \ };\n \n PageClock.prototype.milliseconds_in_day = function(time)
413
+ {\n if (typeof time === 'undefined') {\n time = new Date();\n
414
+ \ }\n var milliseconds = 0;\n for (var i=this.time_units.length
415
+ - 2; i >= 0; i--) {\n milliseconds += this.get_units_in_interval(this.time_units[i][0],
416
+ time) * this.time_units[i][1];\n }\n return milliseconds;\n
417
+ \ };\n \n PageClock.prototype.milliseconds_in_interval = function(unit_length,
418
+ time) {\n return this.milliseconds_in_day(time) % unit_length;\n };\n
419
+ \ \n PageClock.prototype.milliseconds_to_next_interval = function(unit_length,
420
+ time) {\n return unit_length - this.milliseconds_in_interval(unit_length,
421
+ time);\n };\n \n PageClock.prototype.pluralize = function(unit,
422
+ num) {\n if (num === 1) {\n unit = unit.replace(/s$/, '');\n
423
+ \ }\n return unit;\n };\n \n \n PageClock.prototype.read_cookie
424
+ = function(cookie_name){\n var\n ca = window.document.cookie.split(';'),\n
425
+ \ cookie_string = (cookie_name || this.settings.cookie_name) + '=';\n
426
+ \ for (var i=0;i < ca.length;i++) {\n var c = ca[i];\n while
427
+ (c.charAt(0)==' ') {\n c = c.substring(1,c.length);\n }\n
428
+ \ if (c.indexOf(cookie_string) == 0) {\n var encoded_string
429
+ = c.substring(cookie_string.length,c.length);\n return decodeURIComponent(encoded_string).replace(/\\+/g,
430
+ ' ');\n }\n }\n return null;\n };\n \n PageClock.prototype.destroy_cookie
431
+ = function() {\n var expires = new Date();\n expires.setTime(expires.getTime()
432
+ - 1 * 24 * 60 * 60 * 1000);\n window.document.cookie = this.settings.cookie_name
433
+ + \"=; expires=\" + expires.toGMTString() + \"; path=/\";\n };\n \n
434
+ \ PageClock.prototype.get_remote_time = function() {\n var\n time
435
+ = new Date(),\n remote_milliseconds = time.getTime() + this.remote_offset;\n
436
+ \ time = time.setTime(remote_milliseconds);\n return time;\n
437
+ \ };\n \n window.ksr_page_clock = new PageClock();\n })();\n
438
+ \ \n (function(){\n // simple_find( selector [, context_element]
439
+ )\n // selector: a string in the form [tag_name].class_name : must include
440
+ a dot-prefixed css class\n var simple_find = function(selector, context)
441
+ {\n var\n root = context || window.document.body,\n parts
442
+ = selector.split('.'),\n class_name = parts[parts.length - 1],\n
443
+ \ tag_name = (parts.length > 1 && parts[0]) ? parts[0] : '*';\n \n
444
+ \ if (window.document.getElementsByClassName) {\n return root.getElementsByClassName(class_name);\n
445
+ \ }\n \n if (root.querySelectorAll) {\n tag_name
446
+ = tag_name || '';\n return root.querySelectorAll(selector);\n }\n
447
+ \ \n // lame, fall back\n var\n much_elements = root.getElementsByTagName(tag_name),\n
448
+ \ elements = [];\n for (var i = 0, much_element; much_element
449
+ = much_elements[i]; i++) {\n if (this.hasClass(much_element, class_name))
450
+ {\n elements.push(much_element);\n }\n }\n return
451
+ elements;\n }\n \n // TODO: decouple this class from the DOM\n
452
+ \ function ProjectTimer(element, clock, options) {\n this.options
453
+ = {\n unit_base : {\n 'seconds' : 119,\n 'minutes'
454
+ : 119,\n 'hours' : 72,\n 'days' : 0\n },\n
455
+ \ end_phrase : (element.getAttribute('data-word') || 'to go'),\n count_down
456
+ : false\n };\n for (k in options) {\n this.options[k]
457
+ = options[k];\n }\n this.clock = clock;\n this.time_units
458
+ = this.clock.time_units.slice(1);\n this.element = element;\n if
459
+ (this.clock.is_set) {\n this.attach();\n }\n };\n \n
460
+ \ ProjectTimer.prototype.get_remaining_time = function() {\n var
461
+ time = this.remote_end_time - this.clock.get_remote_time();\n if (time
462
+ < 0) {\n time = 0;\n }\n return time;\n };\n \n
463
+ \ ProjectTimer.prototype.get_current_unit = function() {\n var
464
+ unit;\n for (var i=0; i < this.time_units.length; i++) {\n unit
465
+ = this.time_units[i];\n if (this.get_remaining_time() <= this.options.unit_base[unit[0]]
466
+ * unit[1]) {\n break;\n }\n }\n return unit;\n
467
+ \ };\n \n ProjectTimer.prototype.update_element = function() {\n
468
+ \ var\n unit = this.get_current_unit(),\n number_of_units
469
+ = Math.floor(this.get_remaining_time() / unit[1]);\n if (isNaN(number_of_units))
470
+ { return; }\n this.number_element.innerHTML = number_of_units;\n this.text_element.innerHTML
471
+ = this.clock.pluralize(unit[0], number_of_units) + ' ' + this.options.end_phrase;\n
472
+ \ };\n \n ProjectTimer.prototype.valid = function() {\n return
473
+ !!(this.number_element && this.text_element);\n };\n \n ProjectTimer.prototype.attach
474
+ = function() {\n function count() {\n timer.update_element();\n
475
+ \ if (timer.options.count_down && timer.get_remaining_time() > 0)
476
+ {\n var unit = timer.get_current_unit();\n this.timeout
477
+ = window.setTimeout(count, timer.clock.milliseconds_to_next_interval(unit[1]));\n
478
+ \ }\n }\n var timer = this;\n this.remote_end_time_string
479
+ = this.element.getAttribute('data-end_time');\n this.remote_end_time
480
+ = new Date(this.remote_end_time_string);\n this.number_element = simple_find('.num',
481
+ this.element)[0],\n this.text_element = simple_find('.text', this.element)[0],\n
482
+ \ this.element.ksr_page_timer = true;\n if (this.valid()) {\n
483
+ \ count();\n }\n };\n \n ProjectTimer.prototype.cancel
484
+ = function () {\n if (this.timeout) {\n clearTimeout(this.timeout);\n
485
+ \ }\n };\n \n function TimerFinder() {\n this.elements
486
+ = [];\n this.attach();\n }\n \n TimerFinder.prototype.loading
487
+ = true;\n \n TimerFinder.prototype.stop_finding = function() {\n this.attach_timers();\n
488
+ \ this.loading = false;\n \n if ( document.addEventListener
489
+ ) {\n document.removeEventListener( \"DOMContentLoaded\", this.stop_finding,
490
+ false );\n } else if ( document.attachEvent ) {\n if ( document.readyState
491
+ === \"complete\" ) {\n document.detachEvent( \"onreadystatechange\",
492
+ this.stop_finding );\n }\n }\n };\n \n TimerFinder.prototype.bind_ready
493
+ = function() {\n var\n that = this,\n stop_finding
494
+ = function () {\n that.stop_finding.call(that);\n };\n
495
+ \ \n // lifted from jQuery's .ready() method:\n // Mozilla,
496
+ Opera and webkit nightlies currently support this event\n if ( document.addEventListener
497
+ ) {\n // Use the handy event callback\n document.addEventListener(
498
+ \"DOMContentLoaded\", stop_finding, false );\n \n // A fallback
499
+ to window.onload, that will always work\n window.addEventListener(
500
+ \"load\", stop_finding, false );\n \n // If IE event model is used\n
501
+ \ } else if ( document.attachEvent ) {\n // ensure firing before
502
+ onload,\n // maybe late but safe also for iframes\n document.attachEvent(
503
+ \"onreadystatechange\", stop_finding );\n \n // A fallback to
504
+ window.onload, that will always work\n window.attachEvent( \"onload\",
505
+ stop_finding );\n }\n };\n \n TimerFinder.prototype.attach_timers
506
+ = function () {\n var elements = simple_find('div.ksr_page_timer');\n
507
+ \ for (var i=0; i < elements.length; i++) {\n if (!elements[i].ksr_page_timer)
508
+ {\n new ProjectTimer(elements[i], window.ksr_page_clock);\n this.elements.push(elements[i]);\n
509
+ \ }\n }\n };\n \n TimerFinder.prototype.attach
510
+ = function() {\n var that = this;\n function poll_for_timers()
511
+ {\n that.attach_timers();\n if (that.loading) {\n window.setTimeout(that.attach_timers,
512
+ 200);\n }\n }\n this.bind_ready();\n poll_for_timers();\n
513
+ \ };\n \n window.ProjectTimer = ProjectTimer;\n \n new
514
+ TimerFinder();\n })();\n //]]>\n</script>\n\n<script src=\"http://d297h9he240fqh.cloudfront.net/cache-e1f3b9f54/assets/jwplayer.js\"
515
+ type=\"text/javascript\"></script>\n<script src=\"http://d297h9he240fqh.cloudfront.net/cache-e1f3b9f54/assets/project_page.js\"
516
+ type=\"text/javascript\"></script>\n<style type=\"text/css\" media=\"screen,
517
+ projection\">@import url(http://asset0.zendesk.com/external/zenbox/v2.1/zenbox.css);</style><script
518
+ type=\"text/javascript\" src=\"http://asset0.zendesk.com/external/zenbox/v2.1/zenbox.js\"></script><script
519
+ type=\"text/javascript\">\n//<![CDATA[\n if (typeof(Zenbox) !== \"undefined\")
520
+ {\n Zenbox.init({\n dropboxID: \"20012797\",\n tabID:
521
+ \"support\",\n hide_tab: true,\n url: \"kickstarter.zendesk.com\"\n
522
+ \ });\n }\n\n//]]>\n</script>\n<script src=\"http://platform.twitter.com/widgets.js\"
523
+ type=\"text/javascript\"></script>\n\n\n\n<div id=\"fb-root\"></div>\n<script>\n
524
+ \ //<![CDATA[\n var channelUrl = window.location.protocol + \"//\" + window.location.host
525
+ + \"/channel.html\";\n \n window.fbAsyncInit = function() {\n FB.init({\n
526
+ \ appId: '69103156693',\n channelUrl: channelUrl,\n status:
527
+ true, // check login status\n cookie: true, // enable cookies
528
+ to allow the server to access the session\n xfbml: true, // parse
529
+ XFBML\n logging: false // turn off logging\n });\n \n $(document).trigger('fb:loaded');\n
530
+ \ \n var logout_from_fb = false;\n \n FB.Event.subscribe('auth.statusChange',
531
+ function(response) {\n if (logout_from_fb) {\n FB.logout(function()
532
+ {\n logout_from_fb = false;\n });\n } else if (response.authResponse
533
+ && true && true && true && !FB.usingButton) {\n $.get(\"http://www.kickstarter.com/fb/connect/verify?then=http%3A%2F%2Fwww.kickstarter.com%2Fprojects%2F1397300529%2Frailsapp\",
534
+ {'fbsr': response.authResponse.signedRequest}, function() {});\n }\n
535
+ \ });\n \n };\n \n \n // Load the SDK Asynchronously\n
536
+ \ (function(d){\n var js, id = 'facebook-jssdk'; if (d.getElementById(id))
537
+ {return;}\n js = d.createElement('script'); js.id = id; js.async = true;\n
538
+ \ js.src = \"//connect.facebook.net/en_US/all.js\";\n d.getElementsByTagName('head')[0].appendChild(js);\n
539
+ \ }(document));\n //]]>\n</script>\n\n\n<script type=\"text/javascript\">if
540
+ (!NREUMQ.f) { NREUMQ.f=function() {\nNREUMQ.push([\"load\",new Date().getTime()]);\nvar
541
+ e=document.createElement(\"script\");\ne.type=\"text/javascript\";e.async=true;e.src=\"https://d1ros97qkrwjf5.cloudfront.net/30/eum/rum.js\";\ndocument.body.appendChild(e);\nif(NREUMQ.a)NREUMQ.a();\n};\nNREUMQ.a=window.onload;window.onload=NREUMQ.f;\n};\nNREUMQ.push([\"nrfj\",\"beacon-1.newrelic.com\",\"b04b883ad2\",11086,\"cFteRUULX1wHFhtIEFxeVVJDFxxDCgtD\",0.0,120,new
542
+ Date().getTime(),\"\",\"\",\"\",\"\",\"\"])</script></body>\n</html>\n"
543
+ http_version: !!null
544
+ recorded_at: Wed, 28 Mar 2012 23:06:47 GMT
545
+ recorded_with: VCR 2.0.0
@@ -6,7 +6,7 @@ Gem::Specification.new do |gem|
6
6
  gem.email = ["mike.d.1984@gmail.com"]
7
7
  gem.description = %q{simple and flexible html to markdown converter}
8
8
  gem.summary = %q{simple and flexible html to markdown converter}
9
- gem.homepage = ""
9
+ gem.homepage = "https://github.com/29decibel/html2markdown"
10
10
 
11
11
  gem.add_dependency 'nokogiri'
12
12
 
@@ -38,6 +38,8 @@ module HTML2Markdown
38
38
  # default parse
39
39
  case node.name.downcase
40
40
  when 'i'
41
+ when 'script'
42
+ when 'style'
41
43
  when 'li'
42
44
  result << "*#{contents}\n"
43
45
  when 'blockquote'
@@ -20,7 +20,7 @@ class HTMLPage
20
20
  end
21
21
 
22
22
  def markdown!
23
- to_markdown(contents)
23
+ @markdown = to_markdown(contents)
24
24
  end
25
25
 
26
26
  end
@@ -1,3 +1,3 @@
1
1
  module HTML2Markdown
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
@@ -4,12 +4,15 @@ require_relative '../../lib/html2markdown'
4
4
 
5
5
  describe HTMLPage do
6
6
 
7
- # it "should have url and contents property" do
8
- # url = 'http://bbs.qyer.com/viewthread.php?tid=503325&extra=page%3D1'
9
- # page = HTMLPage.new :url => url
10
- # page.contents.should_not be_nil
11
- # page.url.should == url
12
- # end
7
+ it "should fetch contents of url" do
8
+ url = 'http://www.kickstarter.com/projects/1397300529/railsapp'
9
+ VCR.use_cassette 'html_page' do
10
+ page = HTMLPage.new :url => url
11
+ page.contents.should_not be_nil
12
+ page.url.should == url
13
+ page.markdown.length.should > 0
14
+ end
15
+ end
13
16
 
14
17
  it "can convert to markdow format" do
15
18
  contents = <<-CON
@@ -72,7 +75,6 @@ NEXT!<br>
72
75
  end
73
76
  markdown = page.to_markdown page.contents
74
77
  markdown.length.should > 0
75
- puts markdown
76
78
  end
77
79
 
78
80
  it "should have markdown method" do
@@ -81,4 +83,13 @@ NEXT!<br>
81
83
  p.contents = '<strong>hehe</strong>'
82
84
  p.markdown!.should == '**hehe**'
83
85
  end
86
+
87
+ it "can have custom node parse block" do
88
+ p = HTMLPage.new :contents => '<strong>haha</strong>'
89
+ p.strong do |node,contents|
90
+ "strong text : **#{contents}**"
91
+ end
92
+ p.markdown!.should be_include('strong text')
93
+ end
94
+
84
95
  end
@@ -4,6 +4,9 @@ rescue LoadError
4
4
  puts 'Although not required, bundler is recommended for running the tests.'
5
5
  end
6
6
 
7
+ require 'vcr'
8
+
9
+ # configuration for rspec
7
10
  RSpec.configure do |config|
8
11
  config.mock_with :rspec
9
12
  config.color_enabled = true
@@ -19,4 +22,10 @@ RSpec.configure do |config|
19
22
  end
20
23
  end
21
24
 
22
- require 'html2markdown'
25
+ # configuration for vcr
26
+ VCR.configure do |c|
27
+ c.cassette_library_dir = 'fixtures/vcr_cassettes'
28
+ c.hook_into :webmock # or :fakeweb
29
+ end
30
+
31
+ require_relative '../lib/html2markdown'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: html2markdown
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -13,7 +13,7 @@ date: 2012-03-28 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: nokogiri
16
- requirement: &2158826900 !ruby/object:Gem::Requirement
16
+ requirement: &2155739160 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,7 +21,7 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *2158826900
24
+ version_requirements: *2155739160
25
25
  description: simple and flexible html to markdown converter
26
26
  email:
27
27
  - mike.d.1984@gmail.com
@@ -33,15 +33,16 @@ files:
33
33
  - Gemfile
34
34
  - Rakefile
35
35
  - Readme.md
36
+ - fixtures/vcr_cassettes/html_page.yml
36
37
  - html2markdown.gemspec
37
38
  - lib/html2markdown.rb
38
39
  - lib/html2markdown/converter.rb
39
40
  - lib/html2markdown/exceptions.rb
40
41
  - lib/html2markdown/html_page.rb
41
42
  - lib/html2markdown/version.rb
42
- - spec/cases/converter_spec.rb
43
+ - spec/cases/html_page_spec.rb
43
44
  - spec/spec_helper.rb
44
- homepage: ''
45
+ homepage: https://github.com/29decibel/html2markdown
45
46
  licenses: []
46
47
  post_install_message:
47
48
  rdoc_options: []
@@ -66,5 +67,5 @@ signing_key:
66
67
  specification_version: 3
67
68
  summary: simple and flexible html to markdown converter
68
69
  test_files:
69
- - spec/cases/converter_spec.rb
70
+ - spec/cases/html_page_spec.rb
70
71
  - spec/spec_helper.rb