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 +2 -0
- data/Readme.md +22 -3
- data/fixtures/vcr_cassettes/html_page.yml +545 -0
- data/html2markdown.gemspec +1 -1
- data/lib/html2markdown/converter.rb +2 -0
- data/lib/html2markdown/html_page.rb +1 -1
- data/lib/html2markdown/version.rb +1 -1
- data/spec/cases/{converter_spec.rb → html_page_spec.rb} +18 -7
- data/spec/spec_helper.rb +10 -1
- metadata +7 -6
data/Gemfile
CHANGED
data/Readme.md
CHANGED
@@ -1,11 +1,30 @@
|
|
1
|
-
###
|
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
|
-
###
|
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 — 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"Install
|
73
|
+
this .app. Good job, you now have a working Rails install!"\"/>\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 >> 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"Install
|
81
|
+
this .app. Good job, you now have a working Rails install!"\"/>\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=\"✓\" /></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&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\"> </div>\n<span
|
235
|
+
class=\"text\"> </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&logged_in=false&p=0&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&backing[backer_reward_id]=477812&clicked_reward=true&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&backing[backer_reward_id]=477813&clicked_reward=true&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 "I'm
|
251
|
+
committed" 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&backing[backer_reward_id]=477814&clicked_reward=true&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&backing[backer_reward_id]=477815&clicked_reward=true&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• 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&backing[backer_reward_id]=550490&clicked_reward=true&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• 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 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&%20video?ref=footer\">Film & 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=\"✓\" /><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©\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
|
data/html2markdown.gemspec
CHANGED
@@ -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
|
|
@@ -4,12 +4,15 @@ require_relative '../../lib/html2markdown'
|
|
4
4
|
|
5
5
|
describe HTMLPage do
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
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
|
data/spec/spec_helper.rb
CHANGED
@@ -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
|
-
|
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.
|
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: &
|
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: *
|
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/
|
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/
|
70
|
+
- spec/cases/html_page_spec.rb
|
70
71
|
- spec/spec_helper.rb
|