devcenter 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (192) hide show
  1. data/.gitignore +18 -0
  2. data/Gemfile +8 -0
  3. data/LICENSE.txt +22 -0
  4. data/README.md +39 -0
  5. data/Rakefile +2 -0
  6. data/bin/devcenter +7 -0
  7. data/devcenter.gemspec +30 -0
  8. data/lib/devcenter.rb +6 -0
  9. data/lib/devcenter/cli.rb +45 -0
  10. data/lib/devcenter/coderay_extensions.rb +70 -0
  11. data/lib/devcenter/commands.rb +4 -0
  12. data/lib/devcenter/commands/base.rb +47 -0
  13. data/lib/devcenter/commands/open.rb +34 -0
  14. data/lib/devcenter/commands/preview.rb +28 -0
  15. data/lib/devcenter/commands/pull.rb +37 -0
  16. data/lib/devcenter/helpers.rb +41 -0
  17. data/lib/devcenter/layout.html +299 -0
  18. data/lib/devcenter/md_parser.rb +87 -0
  19. data/lib/devcenter/previewer.rb +36 -0
  20. data/lib/devcenter/previewer/assets/images/public/article-icon-large.png +0 -0
  21. data/lib/devcenter/previewer/assets/images/public/article-icon.png +0 -0
  22. data/lib/devcenter/previewer/assets/images/public/aside_accordion_indicator_default.png +0 -0
  23. data/lib/devcenter/previewer/assets/images/public/aside_accordion_indicator_open.png +0 -0
  24. data/lib/devcenter/previewer/assets/images/public/body_bg.png +0 -0
  25. data/lib/devcenter/previewer/assets/images/public/callout_bg.png +0 -0
  26. data/lib/devcenter/previewer/assets/images/public/feed-icon-sprite.png +0 -0
  27. data/lib/devcenter/previewer/assets/images/public/heroku-header-logo-mobile.png +0 -0
  28. data/lib/devcenter/previewer/assets/images/public/heroku-header-logo.png +0 -0
  29. data/lib/devcenter/previewer/assets/images/public/heroku-logo.png +0 -0
  30. data/lib/devcenter/previewer/assets/images/public/icon_sprite_16.png +0 -0
  31. data/lib/devcenter/previewer/assets/images/public/index_li_bullet.png +0 -0
  32. data/lib/devcenter/previewer/assets/images/public/intro_bg.png +0 -0
  33. data/lib/devcenter/previewer/assets/images/public/jive_discussion_arrow.png +0 -0
  34. data/lib/devcenter/previewer/assets/images/public/jive_discussion_glyph.png +0 -0
  35. data/lib/devcenter/previewer/assets/images/public/line.png +0 -0
  36. data/lib/devcenter/previewer/assets/images/public/pre_code_background.png +0 -0
  37. data/lib/devcenter/previewer/assets/images/public/search-icon.png +0 -0
  38. data/lib/devcenter/previewer/assets/images/public/search_glyph.png +0 -0
  39. data/lib/devcenter/previewer/assets/images/public/search_return.png +0 -0
  40. data/lib/devcenter/previewer/assets/images/public/tag-icon-large.png +0 -0
  41. data/lib/devcenter/previewer/assets/images/public/toc-icon.png +0 -0
  42. data/lib/devcenter/previewer/assets/public.css +2125 -0
  43. data/lib/devcenter/previewer/assets/public/article-icon-large.png +0 -0
  44. data/lib/devcenter/previewer/assets/public/article-icon.png +0 -0
  45. data/lib/devcenter/previewer/assets/public/aside_accordion_indicator_default.png +0 -0
  46. data/lib/devcenter/previewer/assets/public/aside_accordion_indicator_open.png +0 -0
  47. data/lib/devcenter/previewer/assets/public/body_bg.png +0 -0
  48. data/lib/devcenter/previewer/assets/public/callout_bg.png +0 -0
  49. data/lib/devcenter/previewer/assets/public/feed-icon-sprite.png +0 -0
  50. data/lib/devcenter/previewer/assets/public/heroku-header-logo-mobile.png +0 -0
  51. data/lib/devcenter/previewer/assets/public/heroku-header-logo.png +0 -0
  52. data/lib/devcenter/previewer/assets/public/heroku-logo.png +0 -0
  53. data/lib/devcenter/previewer/assets/public/icon_sprite_16.png +0 -0
  54. data/lib/devcenter/previewer/assets/public/index_li_bullet.png +0 -0
  55. data/lib/devcenter/previewer/assets/public/intro_bg.png +0 -0
  56. data/lib/devcenter/previewer/assets/public/jive_discussion_arrow.png +0 -0
  57. data/lib/devcenter/previewer/assets/public/jive_discussion_glyph.png +0 -0
  58. data/lib/devcenter/previewer/assets/public/line.png +0 -0
  59. data/lib/devcenter/previewer/assets/public/pre_code_background.png +0 -0
  60. data/lib/devcenter/previewer/assets/public/public.css +2125 -0
  61. data/lib/devcenter/previewer/assets/public/search-icon.png +0 -0
  62. data/lib/devcenter/previewer/assets/public/search_glyph.png +0 -0
  63. data/lib/devcenter/previewer/assets/public/search_return.png +0 -0
  64. data/lib/devcenter/previewer/assets/public/tag-icon-large.png +0 -0
  65. data/lib/devcenter/previewer/assets/public/toc-icon.png +0 -0
  66. data/lib/devcenter/previewer/file_listener.rb +23 -0
  67. data/lib/devcenter/previewer/views/article.erb +345 -0
  68. data/lib/devcenter/previewer/web_app.rb +53 -0
  69. data/lib/devcenter/previewer/web_server.rb +29 -0
  70. data/lib/devcenter/version.rb +3 -0
  71. data/vendor/sinatra/.gitignore +6 -0
  72. data/vendor/sinatra/.travis.yml +16 -0
  73. data/vendor/sinatra/.yardopts +4 -0
  74. data/vendor/sinatra/AUTHORS +61 -0
  75. data/vendor/sinatra/Gemfile +91 -0
  76. data/vendor/sinatra/LICENSE +22 -0
  77. data/vendor/sinatra/README.de.rdoc +2116 -0
  78. data/vendor/sinatra/README.es.rdoc +2106 -0
  79. data/vendor/sinatra/README.fr.rdoc +2133 -0
  80. data/vendor/sinatra/README.hu.rdoc +608 -0
  81. data/vendor/sinatra/README.jp.rdoc +1056 -0
  82. data/vendor/sinatra/README.ko.rdoc +1932 -0
  83. data/vendor/sinatra/README.pt-br.rdoc +778 -0
  84. data/vendor/sinatra/README.pt-pt.rdoc +647 -0
  85. data/vendor/sinatra/README.rdoc +2049 -0
  86. data/vendor/sinatra/README.ru.rdoc +2033 -0
  87. data/vendor/sinatra/README.zh.rdoc +1816 -0
  88. data/vendor/sinatra/Rakefile +182 -0
  89. data/vendor/sinatra/examples/chat.rb +61 -0
  90. data/vendor/sinatra/examples/simple.rb +3 -0
  91. data/vendor/sinatra/examples/stream.ru +26 -0
  92. data/vendor/sinatra/lib/sinatra.rb +5 -0
  93. data/vendor/sinatra/lib/sinatra/base.rb +1820 -0
  94. data/vendor/sinatra/lib/sinatra/images/404.png +0 -0
  95. data/vendor/sinatra/lib/sinatra/images/500.png +0 -0
  96. data/vendor/sinatra/lib/sinatra/main.rb +30 -0
  97. data/vendor/sinatra/lib/sinatra/showexceptions.rb +345 -0
  98. data/vendor/sinatra/lib/sinatra/version.rb +3 -0
  99. data/vendor/sinatra/sinatra.gemspec +18 -0
  100. data/vendor/sinatra/test/base_test.rb +172 -0
  101. data/vendor/sinatra/test/builder_test.rb +91 -0
  102. data/vendor/sinatra/test/coffee_test.rb +90 -0
  103. data/vendor/sinatra/test/compile_test.rb +139 -0
  104. data/vendor/sinatra/test/contest.rb +98 -0
  105. data/vendor/sinatra/test/creole_test.rb +65 -0
  106. data/vendor/sinatra/test/delegator_test.rb +160 -0
  107. data/vendor/sinatra/test/encoding_test.rb +20 -0
  108. data/vendor/sinatra/test/erb_test.rb +98 -0
  109. data/vendor/sinatra/test/extensions_test.rb +98 -0
  110. data/vendor/sinatra/test/filter_test.rb +437 -0
  111. data/vendor/sinatra/test/haml_test.rb +91 -0
  112. data/vendor/sinatra/test/helper.rb +123 -0
  113. data/vendor/sinatra/test/helpers_test.rb +1768 -0
  114. data/vendor/sinatra/test/integration/app.rb +62 -0
  115. data/vendor/sinatra/test/integration_helper.rb +222 -0
  116. data/vendor/sinatra/test/integration_test.rb +87 -0
  117. data/vendor/sinatra/test/less_test.rb +69 -0
  118. data/vendor/sinatra/test/liquid_test.rb +59 -0
  119. data/vendor/sinatra/test/mapped_error_test.rb +305 -0
  120. data/vendor/sinatra/test/markaby_test.rb +80 -0
  121. data/vendor/sinatra/test/markdown_test.rb +82 -0
  122. data/vendor/sinatra/test/middleware_test.rb +68 -0
  123. data/vendor/sinatra/test/nokogiri_test.rb +67 -0
  124. data/vendor/sinatra/test/public/favicon.ico +0 -0
  125. data/vendor/sinatra/test/rabl_test.rb +89 -0
  126. data/vendor/sinatra/test/rack_test.rb +45 -0
  127. data/vendor/sinatra/test/radius_test.rb +59 -0
  128. data/vendor/sinatra/test/rdoc_test.rb +66 -0
  129. data/vendor/sinatra/test/readme_test.rb +120 -0
  130. data/vendor/sinatra/test/request_test.rb +45 -0
  131. data/vendor/sinatra/test/response_test.rb +64 -0
  132. data/vendor/sinatra/test/result_test.rb +76 -0
  133. data/vendor/sinatra/test/route_added_hook_test.rb +59 -0
  134. data/vendor/sinatra/test/routing_test.rb +1175 -0
  135. data/vendor/sinatra/test/sass_test.rb +116 -0
  136. data/vendor/sinatra/test/scss_test.rb +89 -0
  137. data/vendor/sinatra/test/server_test.rb +48 -0
  138. data/vendor/sinatra/test/settings_test.rb +561 -0
  139. data/vendor/sinatra/test/sinatra_test.rb +12 -0
  140. data/vendor/sinatra/test/slim_test.rb +84 -0
  141. data/vendor/sinatra/test/static_test.rb +219 -0
  142. data/vendor/sinatra/test/streaming_test.rb +149 -0
  143. data/vendor/sinatra/test/templates_test.rb +333 -0
  144. data/vendor/sinatra/test/textile_test.rb +65 -0
  145. data/vendor/sinatra/test/views/a/in_a.str +1 -0
  146. data/vendor/sinatra/test/views/ascii.erb +2 -0
  147. data/vendor/sinatra/test/views/b/in_b.str +1 -0
  148. data/vendor/sinatra/test/views/calc.html.erb +1 -0
  149. data/vendor/sinatra/test/views/error.builder +3 -0
  150. data/vendor/sinatra/test/views/error.erb +3 -0
  151. data/vendor/sinatra/test/views/error.haml +3 -0
  152. data/vendor/sinatra/test/views/error.sass +2 -0
  153. data/vendor/sinatra/test/views/explicitly_nested.str +1 -0
  154. data/vendor/sinatra/test/views/foo/hello.test +1 -0
  155. data/vendor/sinatra/test/views/hello.builder +1 -0
  156. data/vendor/sinatra/test/views/hello.coffee +1 -0
  157. data/vendor/sinatra/test/views/hello.creole +1 -0
  158. data/vendor/sinatra/test/views/hello.erb +1 -0
  159. data/vendor/sinatra/test/views/hello.haml +1 -0
  160. data/vendor/sinatra/test/views/hello.less +5 -0
  161. data/vendor/sinatra/test/views/hello.liquid +1 -0
  162. data/vendor/sinatra/test/views/hello.mab +1 -0
  163. data/vendor/sinatra/test/views/hello.md +1 -0
  164. data/vendor/sinatra/test/views/hello.nokogiri +1 -0
  165. data/vendor/sinatra/test/views/hello.rabl +2 -0
  166. data/vendor/sinatra/test/views/hello.radius +1 -0
  167. data/vendor/sinatra/test/views/hello.rdoc +1 -0
  168. data/vendor/sinatra/test/views/hello.sass +2 -0
  169. data/vendor/sinatra/test/views/hello.scss +3 -0
  170. data/vendor/sinatra/test/views/hello.slim +1 -0
  171. data/vendor/sinatra/test/views/hello.str +1 -0
  172. data/vendor/sinatra/test/views/hello.test +1 -0
  173. data/vendor/sinatra/test/views/hello.textile +1 -0
  174. data/vendor/sinatra/test/views/hello.wlang +1 -0
  175. data/vendor/sinatra/test/views/hello.yajl +1 -0
  176. data/vendor/sinatra/test/views/layout2.builder +3 -0
  177. data/vendor/sinatra/test/views/layout2.erb +2 -0
  178. data/vendor/sinatra/test/views/layout2.haml +2 -0
  179. data/vendor/sinatra/test/views/layout2.liquid +2 -0
  180. data/vendor/sinatra/test/views/layout2.mab +2 -0
  181. data/vendor/sinatra/test/views/layout2.nokogiri +3 -0
  182. data/vendor/sinatra/test/views/layout2.rabl +3 -0
  183. data/vendor/sinatra/test/views/layout2.radius +2 -0
  184. data/vendor/sinatra/test/views/layout2.slim +3 -0
  185. data/vendor/sinatra/test/views/layout2.str +2 -0
  186. data/vendor/sinatra/test/views/layout2.test +1 -0
  187. data/vendor/sinatra/test/views/layout2.wlang +2 -0
  188. data/vendor/sinatra/test/views/nested.str +1 -0
  189. data/vendor/sinatra/test/views/utf8.erb +2 -0
  190. data/vendor/sinatra/test/wlang_test.rb +70 -0
  191. data/vendor/sinatra/test/yajl_test.rb +86 -0
  192. metadata +414 -0
@@ -0,0 +1,23 @@
1
+ module Devcenter::Previewer
2
+
3
+ class FileListener
4
+ require 'listen'
5
+
6
+ def initialize(file_path, callback)
7
+ dir = File.dirname(file_path)
8
+ basename = File.basename(file_path)
9
+ @listener = Listen.to(dir)
10
+ @listener.filter(%r{#{basename}})
11
+ @listener.change(&callback)
12
+ end
13
+
14
+ def start
15
+ @listener.start(false) # non-blocking
16
+ end
17
+
18
+ def stop
19
+ @listener.stop
20
+ end
21
+ end
22
+
23
+ end
@@ -0,0 +1,345 @@
1
+ <!DOCTYPE html>
2
+ <html class="no-js" dir="ltr" lang="en">
3
+ <head>
4
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
5
+ <title>Preview: <%= @article.metadata.title %></title>
6
+ <meta charset="utf-8">
7
+ <meta name="viewport" content="width=device-width, initial-scale=0.5">
8
+ <meta content="IE=edge,chrome=1" http-equiv="X-UA-Compatible">
9
+ <meta content="authenticity_token" name="csrf-param">
10
+ <link href="/assets/public.css" media="screen" rel="stylesheet" type="text/css">
11
+ <!--[if IE 6]>
12
+ <link href="https://universal-ie6-css.googlecode.com/files/ie6.0.3.css" media="screen" rel="stylesheet" type="text/css" />
13
+ <![endif]-->
14
+ <style>
15
+ .parsing-error, .parsing-error h4 {
16
+ color: red;
17
+ line-height: 1.8em;
18
+ }
19
+ .save {
20
+ margin: 2em 0;
21
+ }
22
+ .save textarea {
23
+ display:none;
24
+ }
25
+ .save input {
26
+ padding: 1em 2em;
27
+ }
28
+ </style>
29
+ <script>
30
+ try {
31
+ var es = new EventSource('/stream');
32
+ es.onmessage = function(e) {
33
+ document.location.reload();
34
+ };
35
+ es.onerror = function(error) {
36
+ es.close();
37
+ }
38
+ } catch (error) {
39
+ console.log("ERROR:");
40
+ console.log(error);
41
+ }
42
+ </script>
43
+ </head>
44
+ <body>
45
+ <div id="heroku-header">
46
+ <div id="heroku-header-hgroup">
47
+ <h1><a href="https://heroku.com">Heroku</a></h1>
48
+ </div>
49
+ <div id="heroku-header-nav">
50
+ <ul>
51
+ <li><a href="https://heroku.com/how/">How It Works</a></li>
52
+ <li><a href="https://heroku.com/pricing/">Pricing</a></li>
53
+ <li class="last"><a href="https://addons.heroku.com/">Add-ons</a></li>
54
+ </ul>
55
+ <ul class="group" id="heroku-header-aid">
56
+ <li><a href="https://devcenter.heroku.com/">Dev Center</a></li>
57
+ <li class="last"><a href="https://help.heroku.com">Help</a></li>
58
+ </ul>
59
+ <ul class="last group" id="heroku-header-my-heroku">
60
+ <li class="last"><a href="/auth/login?back_to=%2Farticles%2Fcedar">Login</a></li>
61
+ </ul>
62
+ </div>
63
+
64
+ <div id="heroku-header-quicknav">
65
+ <select><optgroup label="About">
66
+ <option value="https://heroku.com/how/">How It Works</option>
67
+ <option value="https://heroku.com/pricing/">Pricing</option>
68
+ <option value="https://addons.heroku.com/">Add-ons</option>
69
+ </optgroup>
70
+ <optgroup label="Support">
71
+ <option selected value="https://devcenter.heroku.com/">Dev Center</option>
72
+ <option value="https://help.heroku.com">Help</option>
73
+ </optgroup>
74
+ <optgroup label="My Heroku"><option value="/auth/logout?back_to=%2Farticles%2Fcedar">Login</option></optgroup></select><a href="#" onclick="return false;">Dev Center</a>
75
+ </div>
76
+ </div>
77
+ <script type="text/javascript">
78
+ </script><div id="sheet">
79
+ <div class="wrapper">
80
+ <div class="pie-clearfix" id="article">
81
+ <aside id="sidebar">
82
+ <select id="quicknav" class="nocontent"><option value="/">Home</option>
83
+ <optgroup label="Overview">
84
+ <option value="/categories/getting-started">
85
+ Getting Started
86
+ </option>
87
+ <option value="/categories/platform-architecture">
88
+ Platform Architecture
89
+ </option>
90
+ <option value="/categories/application-architecture">
91
+ Application Architecture
92
+ </option>
93
+ </optgroup>
94
+ <optgroup label="Reference">
95
+ <option value="/categories/platform-features" selected>
96
+ Platform Features
97
+ </option>
98
+ <option value="/categories/language-support">
99
+ Languages
100
+ </option>
101
+ <option value="/categories/command-line">
102
+ Command Line
103
+ </option>
104
+ <option value="/categories/collaboration">
105
+ Collaboration
106
+ </option>
107
+ <option value="/categories/deployment">
108
+ Deployment
109
+ </option>
110
+ <option value="/categories/troubleshooting">
111
+ Troubleshooting
112
+ </option>
113
+ <option value="/categories/devcenter">
114
+ Dev Center
115
+ </option>
116
+ <option value="/categories/aspen-bamboo">
117
+ Bamboo
118
+ </option>
119
+ <option value="/categories/labs">
120
+ Heroku Labs
121
+ </option>
122
+ <option value="/categories/buildpacks">
123
+ Buildpacks
124
+ </option>
125
+ <option value="/changelog">
126
+ Changelog
127
+ </option>
128
+ </optgroup>
129
+ <optgroup label="Languages">
130
+ <option value="/categories/ruby">
131
+ Ruby
132
+ </option>
133
+ <option value="/categories/java">
134
+ Java
135
+ </option>
136
+ <option value="/categories/python">
137
+ Python
138
+ </option>
139
+ <option value="/categories/clojure">
140
+ Clojure
141
+ </option>
142
+ <option value="/categories/scala">
143
+ Scala
144
+ </option>
145
+ <option value="/categories/nodejs">
146
+ Node.js
147
+ </option>
148
+ </optgroup>
149
+ <optgroup label="Tutorials">
150
+ <option value="/categories/features">
151
+ Adding Features
152
+ </option>
153
+ <option value="/categories/facebook">
154
+ Facebook
155
+ </option>
156
+ <option value="/categories/mobile">
157
+ Mobile
158
+ </option>
159
+ <option value="/categories/database">
160
+ Database
161
+ </option>
162
+ </optgroup>
163
+ <optgroup label="Accounts &amp; Billing">
164
+ <option value="/categories/billing">
165
+ Accounts &amp; Billing
166
+ </option>
167
+ <option value="/categories/support">
168
+ Support
169
+ </option>
170
+ </optgroup>
171
+ <optgroup label="Add-ons">
172
+ <option value="/categories/heroku-postgres">
173
+ Heroku Postgres
174
+ </option>
175
+ <option value="/categories/addon-overview">
176
+ Overview
177
+ </option>
178
+ <option value="/categories/add-on-documentation">
179
+ All Add-ons
180
+ </option>
181
+ </optgroup></select><ul id="nav" class="nocontent">
182
+ <li class="category-group">
183
+ <a class="category" href="#">Overview</a>
184
+
185
+ <ul class="tags" style="display:none;">
186
+ <li>
187
+ <a href="/categories/getting-started">Getting Started</a>
188
+ </li>
189
+ <li>
190
+ <a href="/categories/platform-architecture">Platform Architecture</a>
191
+ </li>
192
+ <li>
193
+ <a href="/categories/application-architecture">Application Architecture</a>
194
+ </li>
195
+ </ul>
196
+ </li>
197
+ <li class="category-group">
198
+ <a class="category" href="#">Reference</a>
199
+
200
+ <ul class="tags" style="display:block;">
201
+ <li class="active">
202
+ <a href="/categories/platform-features">Platform Features</a>
203
+ </li>
204
+ <li>
205
+ <a href="/categories/language-support">Languages</a>
206
+ </li>
207
+ <li>
208
+ <a href="/categories/command-line">Command Line</a>
209
+ </li>
210
+ <li>
211
+ <a href="/categories/collaboration">Collaboration</a>
212
+ </li>
213
+ <li>
214
+ <a href="/categories/deployment">Deployment</a>
215
+ </li>
216
+ <li>
217
+ <a href="/categories/troubleshooting">Troubleshooting</a>
218
+ </li>
219
+ <li>
220
+ <a href="/categories/devcenter">Dev Center</a>
221
+ </li>
222
+ <li>
223
+ <a href="/categories/aspen-bamboo">Bamboo</a>
224
+ </li>
225
+ <li>
226
+ <a href="/categories/labs">Heroku Labs</a>
227
+ </li>
228
+ <li>
229
+ <a href="/categories/buildpacks">Buildpacks</a>
230
+ </li>
231
+ <li>
232
+ <a href="/changelog">Changelog</a>
233
+ </li>
234
+ </ul>
235
+ </li>
236
+ <li class="category-group">
237
+ <a class="category" href="#">Languages</a>
238
+
239
+ <ul class="tags" style="display:none;">
240
+ <li>
241
+ <a href="/categories/ruby">Ruby</a>
242
+ </li>
243
+ <li>
244
+ <a href="/categories/java">Java</a>
245
+ </li>
246
+ <li>
247
+ <a href="/categories/python">Python</a>
248
+ </li>
249
+ <li>
250
+ <a href="/categories/clojure">Clojure</a>
251
+ </li>
252
+ <li>
253
+ <a href="/categories/scala">Scala</a>
254
+ </li>
255
+ <li>
256
+ <a href="/categories/nodejs">Node.js</a>
257
+ </li>
258
+ </ul>
259
+ </li>
260
+ <li class="category-group">
261
+ <a class="category" href="#">Tutorials</a>
262
+
263
+ <ul class="tags" style="display:none;">
264
+ <li>
265
+ <a href="/categories/features">Adding Features</a>
266
+ </li>
267
+ <li>
268
+ <a href="/categories/facebook">Facebook</a>
269
+ </li>
270
+ <li>
271
+ <a href="/categories/mobile">Mobile</a>
272
+ </li>
273
+ <li>
274
+ <a href="/categories/database">Database</a>
275
+ </li>
276
+ </ul>
277
+ </li>
278
+ <li class="category-group">
279
+ <a class="category" href="#">Accounts &amp; Billing</a>
280
+
281
+ <ul class="tags" style="display:none;">
282
+ <li>
283
+ <a href="/categories/billing">Accounts &amp; Billing</a>
284
+ </li>
285
+ <li>
286
+ <a href="/categories/support">Support</a>
287
+ </li>
288
+ </ul>
289
+ </li>
290
+ <li class="category-group">
291
+ <a class="category" href="#">Add-ons</a>
292
+
293
+ <ul class="tags" style="display:none;">
294
+ <li>
295
+ <a href="/categories/heroku-postgres">Heroku Postgres</a>
296
+ </li>
297
+ <li>
298
+ <a href="/categories/addon-overview">Overview</a>
299
+ </li>
300
+ <li>
301
+ <a href="/categories/add-on-documentation">All Add-ons</a>
302
+ </li>
303
+ </ul>
304
+ </li>
305
+ </ul></aside><section id="main"><div id="admin-tabs"></div>
306
+
307
+
308
+
309
+ <article><hgroup><h1><%= @article.metadata.title %></h1>
310
+
311
+
312
+
313
+ <p class="meta">
314
+ Local preview.
315
+ </p>
316
+
317
+ </hgroup>
318
+
319
+ <% if !@article.html.to_s.empty? %>
320
+ <%= @article.html %>
321
+ <% elsif @article.error %>
322
+ <div class="parsing-error">
323
+ <h4>Parsing error:</h4>
324
+ <p>
325
+ <%= @article.error %>
326
+ </p>
327
+ </div>
328
+ <% end %>
329
+
330
+ <form class="save" action="<%= devcenter_base_url %>/admin/articles/update/<%= @article.metadata.id %>" method="POST">
331
+ <input name="_method" type="hidden" value="put">
332
+ <input type="hidden" name="article[title]" value="<%= @article.metadata.title %>">
333
+ <textarea style="display:none1" name="article[content]">
334
+ <%= @article.content.to_s.lstrip %>
335
+ </textarea>
336
+ <input type="submit" value="Save in Dev Center">
337
+ </form>
338
+
339
+ </article>
340
+ </section>
341
+ </div>
342
+
343
+
344
+ </body>
345
+ </html>
@@ -0,0 +1,53 @@
1
+ module Devcenter::Previewer
2
+
3
+ class WebApp < Sinatra::Base
4
+
5
+ set :logging, false
6
+ set connections: []
7
+ set :public_folder, File.dirname(__FILE__)
8
+ set :views, File.join(File.dirname(__FILE__), 'views')
9
+
10
+ helpers do
11
+ include Devcenter::Helpers
12
+ end
13
+
14
+ get '/favicon.ico' do
15
+ end
16
+
17
+ get '/stream', provides: 'text/event-stream' do
18
+ stream :keep_open do |conn|
19
+ settings.connections << conn
20
+ conn.callback { settings.connections.delete(conn) } # connection closed properly
21
+ conn.errback do # connection closed due to an error
22
+ conn.close
23
+ settings.connections.delete(conn)
24
+ end
25
+ end
26
+ end
27
+
28
+ get '/:slug' do
29
+ src_path = File.join(Dir.pwd, "#{params[:slug]}.md")
30
+ @article = parse_article(src_path)
31
+ erb :article
32
+ end
33
+
34
+ def parse_article(src_path)
35
+ article = OpenStruct.new
36
+ src = IO.read(src_path)
37
+ metadata_yaml, article.content = src.split(/\r*\n\r*\n/, 2)
38
+ article.metadata = OpenStruct.new YAML.load(metadata_yaml)
39
+ begin
40
+ article.html = ::Devcenter::MdParser.to_html(article.content)
41
+ rescue Exception => e
42
+ article.error = e.to_s
43
+ end
44
+ article
45
+ end
46
+
47
+ def self.send_server_event
48
+ settings.connections.each do |conn|
49
+ conn << "data: reload\n\n"
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,29 @@
1
+ module Devcenter::Previewer
2
+
3
+ class WebServer
4
+ require 'thin'
5
+
6
+ attr_reader :threaded
7
+
8
+ def initialize(host, port, app, threaded = false)
9
+ @host, @port = host, port
10
+ Thin::Logging.silent = true
11
+ @server = Thin::Server.new(@host, @port, app)
12
+ @threaded = false
13
+ end
14
+
15
+ def start
16
+ if threaded
17
+ @thread = Thread.new { @server.start }
18
+ else
19
+ @server.start
20
+ end
21
+ end
22
+
23
+ def stop
24
+ @server.stop
25
+ Thread.kill(@thread) if threaded
26
+ end
27
+ end
28
+
29
+ end