typo 3.99.0

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 (742) hide show
  1. data/.DS_Store +0 -0
  2. data/CHANGELOG +718 -0
  3. data/MAINTAINERS +30 -0
  4. data/MIT-LICENSE +21 -0
  5. data/README +92 -0
  6. data/Rakefile +10 -0
  7. data/app/apis/blogger_service.rb +94 -0
  8. data/app/apis/meta_weblog_service.rb +197 -0
  9. data/app/apis/movable_type_service.rb +150 -0
  10. data/app/apis/typo_web_service.rb +26 -0
  11. data/app/controllers/accounts_controller.rb +52 -0
  12. data/app/controllers/admin/base_controller.rb +21 -0
  13. data/app/controllers/admin/blacklist_controller.rb +50 -0
  14. data/app/controllers/admin/cache_controller.rb +31 -0
  15. data/app/controllers/admin/categories_controller.rb +64 -0
  16. data/app/controllers/admin/comments_controller.rb +57 -0
  17. data/app/controllers/admin/content_controller.rb +147 -0
  18. data/app/controllers/admin/general_controller.rb +42 -0
  19. data/app/controllers/admin/pages_controller.rb +50 -0
  20. data/app/controllers/admin/resources_controller.rb +98 -0
  21. data/app/controllers/admin/sidebar_controller.rb +74 -0
  22. data/app/controllers/admin/textfilters_controller.rb +104 -0
  23. data/app/controllers/admin/themes_controller.rb +20 -0
  24. data/app/controllers/admin/trackbacks_controller.rb +54 -0
  25. data/app/controllers/admin/users_controller.rb +41 -0
  26. data/app/controllers/application.rb +66 -0
  27. data/app/controllers/articles_controller.rb +218 -0
  28. data/app/controllers/backend_controller.rb +11 -0
  29. data/app/controllers/content_controller.rb +98 -0
  30. data/app/controllers/live_controller.rb +10 -0
  31. data/app/controllers/redirect_controller.rb +16 -0
  32. data/app/controllers/sidebar_controller.rb +50 -0
  33. data/app/controllers/textfilter_controller.rb +22 -0
  34. data/app/controllers/theme_controller.rb +52 -0
  35. data/app/controllers/xml_controller.rb +111 -0
  36. data/app/helpers/accounts_helper.rb +2 -0
  37. data/app/helpers/admin/base_helper.rb +124 -0
  38. data/app/helpers/admin/blacklist_helper.rb +2 -0
  39. data/app/helpers/admin/cache_helper.rb +2 -0
  40. data/app/helpers/admin/comments_helper.rb +2 -0
  41. data/app/helpers/admin/content_helper.rb +2 -0
  42. data/app/helpers/admin/general_helper.rb +2 -0
  43. data/app/helpers/admin/pages_helper.rb +2 -0
  44. data/app/helpers/admin/resources_helper.rb +2 -0
  45. data/app/helpers/admin/sidebar_helper.rb +2 -0
  46. data/app/helpers/admin/textfilters_helper.rb +2 -0
  47. data/app/helpers/admin/themes_helper.rb +2 -0
  48. data/app/helpers/admin/trackbacks_helper.rb +2 -0
  49. data/app/helpers/admin/users_helper.rb +2 -0
  50. data/app/helpers/application_helper.rb +92 -0
  51. data/app/helpers/articles_helper.rb +163 -0
  52. data/app/helpers/backend_helper.rb +2 -0
  53. data/app/helpers/content_helper.rb +3 -0
  54. data/app/helpers/mail_helper.rb +6 -0
  55. data/app/helpers/redirect_helper.rb +2 -0
  56. data/app/helpers/sidebar_helper.rb +22 -0
  57. data/app/helpers/sidebars/plugin_helper.rb +2 -0
  58. data/app/helpers/text_filter_plugin_helper.rb +2 -0
  59. data/app/helpers/textfilter_helper.rb +2 -0
  60. data/app/helpers/theme_helper.rb +23 -0
  61. data/app/helpers/xml_helper.rb +21 -0
  62. data/app/models/aggregations/audioscrobbler.rb +54 -0
  63. data/app/models/aggregations/backpack.rb +57 -0
  64. data/app/models/aggregations/delicious.rb +57 -0
  65. data/app/models/aggregations/flickr.rb +89 -0
  66. data/app/models/aggregations/fortythree.rb +62 -0
  67. data/app/models/aggregations/magnolia.rb +81 -0
  68. data/app/models/aggregations/tada.rb +75 -0
  69. data/app/models/aggregations/technorati.rb +51 -0
  70. data/app/models/aggregations/upcoming.rb +74 -0
  71. data/app/models/article.rb +211 -0
  72. data/app/models/blacklist_pattern.rb +22 -0
  73. data/app/models/blog.rb +162 -0
  74. data/app/models/blog_sweeper.rb +23 -0
  75. data/app/models/category.rb +62 -0
  76. data/app/models/comment.rb +76 -0
  77. data/app/models/config_manager.rb +80 -0
  78. data/app/models/content.rb +222 -0
  79. data/app/models/content_observer.rb +5 -0
  80. data/app/models/content_state/base.rb +51 -0
  81. data/app/models/content_state/draft.rb +40 -0
  82. data/app/models/content_state/factory.rb +16 -0
  83. data/app/models/content_state/just_published.rb +47 -0
  84. data/app/models/content_state/new.rb +45 -0
  85. data/app/models/content_state/publication_pending.rb +43 -0
  86. data/app/models/content_state/published.rb +35 -0
  87. data/app/models/email_notifier.rb +9 -0
  88. data/app/models/notification_mailer.rb +34 -0
  89. data/app/models/page.rb +20 -0
  90. data/app/models/page_cache.rb +29 -0
  91. data/app/models/ping.rb +129 -0
  92. data/app/models/redirect.rb +3 -0
  93. data/app/models/resource.rb +76 -0
  94. data/app/models/sidebar.rb +32 -0
  95. data/app/models/simple_cache.rb +37 -0
  96. data/app/models/tag.rb +63 -0
  97. data/app/models/text_filter.rb +111 -0
  98. data/app/models/theme.rb +44 -0
  99. data/app/models/trackback.rb +51 -0
  100. data/app/models/trigger.rb +31 -0
  101. data/app/models/user.rb +113 -0
  102. data/app/models/web_notifier.rb +7 -0
  103. data/app/views/accounts/login.rhtml +24 -0
  104. data/app/views/accounts/logout.rhtml +12 -0
  105. data/app/views/accounts/signup.rhtml +26 -0
  106. data/app/views/accounts/welcome.rhtml +13 -0
  107. data/app/views/admin/base/_recent_comments.rhtml +10 -0
  108. data/app/views/admin/base/_recent_trackbacks.rhtml +10 -0
  109. data/app/views/admin/blacklist/_blacklist_patterns.rhtml +16 -0
  110. data/app/views/admin/blacklist/_form.rhtml +15 -0
  111. data/app/views/admin/blacklist/_quick_post.rhtml +16 -0
  112. data/app/views/admin/blacklist/destroy.rhtml +10 -0
  113. data/app/views/admin/blacklist/edit.rhtml +14 -0
  114. data/app/views/admin/blacklist/list.rhtml +13 -0
  115. data/app/views/admin/cache/list.rhtml +8 -0
  116. data/app/views/admin/categories/_categories.rhtml +14 -0
  117. data/app/views/admin/categories/_form.rhtml +7 -0
  118. data/app/views/admin/categories/_quick_post.rhtml +11 -0
  119. data/app/views/admin/categories/destroy.rhtml +10 -0
  120. data/app/views/admin/categories/edit.rhtml +13 -0
  121. data/app/views/admin/categories/list.rhtml +15 -0
  122. data/app/views/admin/categories/reorder.rhtml +9 -0
  123. data/app/views/admin/categories/show.rhtml +18 -0
  124. data/app/views/admin/comments/_form.rhtml +19 -0
  125. data/app/views/admin/comments/comments.rhtml +4 -0
  126. data/app/views/admin/comments/destroy.rhtml +11 -0
  127. data/app/views/admin/comments/edit.rhtml +18 -0
  128. data/app/views/admin/comments/list.rhtml +31 -0
  129. data/app/views/admin/comments/new.rhtml +15 -0
  130. data/app/views/admin/comments/show.rhtml +10 -0
  131. data/app/views/admin/content/_articles.rhtml +20 -0
  132. data/app/views/admin/content/_attachment.rhtml +17 -0
  133. data/app/views/admin/content/_form.rhtml +51 -0
  134. data/app/views/admin/content/_pages.rhtml +3 -0
  135. data/app/views/admin/content/_quick_post.rhtml +20 -0
  136. data/app/views/admin/content/_show_categories.rhtml +9 -0
  137. data/app/views/admin/content/_show_resources.rhtml +9 -0
  138. data/app/views/admin/content/destroy.rhtml +11 -0
  139. data/app/views/admin/content/edit.rhtml +28 -0
  140. data/app/views/admin/content/list.rhtml +20 -0
  141. data/app/views/admin/content/new.rhtml +27 -0
  142. data/app/views/admin/content/preview.rhtml +3 -0
  143. data/app/views/admin/content/show.rhtml +25 -0
  144. data/app/views/admin/general/index.rhtml +216 -0
  145. data/app/views/admin/general/update_database.rhtml +44 -0
  146. data/app/views/admin/pages/_form.rhtml +19 -0
  147. data/app/views/admin/pages/_pages.rhtml +18 -0
  148. data/app/views/admin/pages/_quick_post.rhtml +21 -0
  149. data/app/views/admin/pages/destroy.rhtml +11 -0
  150. data/app/views/admin/pages/edit.rhtml +28 -0
  151. data/app/views/admin/pages/list.rhtml +13 -0
  152. data/app/views/admin/pages/new.rhtml +24 -0
  153. data/app/views/admin/pages/preview.rhtml +1 -0
  154. data/app/views/admin/pages/show.rhtml +14 -0
  155. data/app/views/admin/resources/_itunes_category_add.rhtml +11 -0
  156. data/app/views/admin/resources/_itunes_category_edit.rhtml +32 -0
  157. data/app/views/admin/resources/_metadata_add.rhtml +22 -0
  158. data/app/views/admin/resources/_metadata_edit.rhtml +22 -0
  159. data/app/views/admin/resources/_mime_edit.rhtml +8 -0
  160. data/app/views/admin/resources/_pages.rhtml +3 -0
  161. data/app/views/admin/resources/_resources.rhtml +40 -0
  162. data/app/views/admin/resources/destroy.rhtml +11 -0
  163. data/app/views/admin/resources/list.rhtml +9 -0
  164. data/app/views/admin/resources/new.rhtml +12 -0
  165. data/app/views/admin/sidebar/_active.rhtml +14 -0
  166. data/app/views/admin/sidebar/_actives.rhtml +9 -0
  167. data/app/views/admin/sidebar/_available.rhtml +5 -0
  168. data/app/views/admin/sidebar/_availables.rhtml +5 -0
  169. data/app/views/admin/sidebar/_publish.rhtml +2 -0
  170. data/app/views/admin/sidebar/_target.rhtml +1 -0
  171. data/app/views/admin/sidebar/index.rhtml +34 -0
  172. data/app/views/admin/sidebar/publish.rjs +6 -0
  173. data/app/views/admin/sidebar/remove.rjs +5 -0
  174. data/app/views/admin/sidebar/set_active.rjs +10 -0
  175. data/app/views/admin/textfilters/_form.rhtml +45 -0
  176. data/app/views/admin/textfilters/_macros.rhtml +16 -0
  177. data/app/views/admin/textfilters/_textfilters.rhtml +20 -0
  178. data/app/views/admin/textfilters/destroy.rhtml +10 -0
  179. data/app/views/admin/textfilters/edit.rhtml +17 -0
  180. data/app/views/admin/textfilters/list.rhtml +15 -0
  181. data/app/views/admin/textfilters/macro_help.rhtml +3 -0
  182. data/app/views/admin/textfilters/new.rhtml +15 -0
  183. data/app/views/admin/textfilters/preview.rhtml +3 -0
  184. data/app/views/admin/textfilters/show.rhtml +34 -0
  185. data/app/views/admin/textfilters/show_help.rhtml +8 -0
  186. data/app/views/admin/themes/index.rhtml +12 -0
  187. data/app/views/admin/trackbacks/_form.rhtml +19 -0
  188. data/app/views/admin/trackbacks/destroy.rhtml +6 -0
  189. data/app/views/admin/trackbacks/edit.rhtml +14 -0
  190. data/app/views/admin/trackbacks/list.rhtml +31 -0
  191. data/app/views/admin/trackbacks/new.rhtml +15 -0
  192. data/app/views/admin/trackbacks/show.rhtml +14 -0
  193. data/app/views/admin/users/_form.rhtml +48 -0
  194. data/app/views/admin/users/_user.rhtml +9 -0
  195. data/app/views/admin/users/destroy.rhtml +14 -0
  196. data/app/views/admin/users/edit.rhtml +14 -0
  197. data/app/views/admin/users/list.rhtml +9 -0
  198. data/app/views/admin/users/new.rhtml +15 -0
  199. data/app/views/admin/users/show.rhtml +18 -0
  200. data/app/views/articles/_article.rhtml +4 -0
  201. data/app/views/articles/_comment.rhtml +7 -0
  202. data/app/views/articles/_comment_box.rhtml +43 -0
  203. data/app/views/articles/_comment_error.rhtml +1 -0
  204. data/app/views/articles/_trackback.rhtml +7 -0
  205. data/app/views/articles/archives.rhtml +22 -0
  206. data/app/views/articles/comment_preview.rhtml +3 -0
  207. data/app/views/articles/error.rhtml +3 -0
  208. data/app/views/articles/groupings.rhtml +14 -0
  209. data/app/views/articles/index.rhtml +11 -0
  210. data/app/views/articles/read.rhtml +70 -0
  211. data/app/views/articles/trackback.rxml +5 -0
  212. data/app/views/articles/view_page.rhtml +3 -0
  213. data/app/views/layouts/accounts.rhtml +22 -0
  214. data/app/views/layouts/administration.rhtml +75 -0
  215. data/app/views/layouts/sidebar.rhtml +40 -0
  216. data/app/views/live/search.rhtml +10 -0
  217. data/app/views/notification_mailer/_mail_footer.rhtml +7 -0
  218. data/app/views/notification_mailer/_mail_header.rhtml +1 -0
  219. data/app/views/notification_mailer/article.rhtml +6 -0
  220. data/app/views/notification_mailer/comment.rhtml +11 -0
  221. data/app/views/notification_mailer/trackback.rhtml +3 -0
  222. data/app/views/settings/done.rhtml +2 -0
  223. data/app/views/settings/install.rhtml +12 -0
  224. data/app/views/shared/_search.rhtml +10 -0
  225. data/app/views/sidebar/_row.rhtml +1 -0
  226. data/app/views/sidebar/_sidebar.rhtml +5 -0
  227. data/app/views/sidebar/display_plugins.rhtml +5 -0
  228. data/app/views/sidebar/show.rhtml +1 -0
  229. data/app/views/theme/static_view_test.rhtml +1 -0
  230. data/app/views/xml/_atom10_item_article.rxml +39 -0
  231. data/app/views/xml/_atom10_item_comment.rxml +13 -0
  232. data/app/views/xml/_atom10_item_trackback.rxml +16 -0
  233. data/app/views/xml/_itunes_item_resource.rxml +30 -0
  234. data/app/views/xml/_rss20_item_article.rxml +35 -0
  235. data/app/views/xml/_rss20_item_comment.rxml +7 -0
  236. data/app/views/xml/_rss20_item_trackback.rxml +7 -0
  237. data/app/views/xml/atom10_feed.rxml +18 -0
  238. data/app/views/xml/itunes_feed.rxml +29 -0
  239. data/app/views/xml/rsd.rxml +19 -0
  240. data/app/views/xml/rss20_feed.rxml +18 -0
  241. data/bin/typo +12 -0
  242. data/cache/META/DATA/ACTION_PARAM/localhost.3000/articles/index/.cache +540 -0
  243. data/cache/META/DATA/ACTION_PARAM/localhost.3000/articles/permalink/day=09&month=09&title=i-need-a-new-keyboard-and-mouse&year=2005.cache +414 -0
  244. data/cache/META/META/ACTION_PARAM/localhost.3000/articles/index/.cache +3 -0
  245. data/cache/META/META/ACTION_PARAM/localhost.3000/articles/permalink/day=09&month=09&title=i-need-a-new-keyboard-and-mouse&year=2005.cache +3 -0
  246. data/components/plugins/sidebars/aimpresence/content.rhtml +4 -0
  247. data/components/plugins/sidebars/aimpresence_controller.rb +10 -0
  248. data/components/plugins/sidebars/amazon/content.rhtml +4 -0
  249. data/components/plugins/sidebars/amazon_controller.rb +17 -0
  250. data/components/plugins/sidebars/archives/content.rhtml +11 -0
  251. data/components/plugins/sidebars/archives_controller.rb +24 -0
  252. data/components/plugins/sidebars/audioscrobbler/content.rhtml +10 -0
  253. data/components/plugins/sidebars/audioscrobbler_controller.rb +10 -0
  254. data/components/plugins/sidebars/backpack/content.rhtml +12 -0
  255. data/components/plugins/sidebars/backpack_controller.rb +17 -0
  256. data/components/plugins/sidebars/category/content.rhtml +10 -0
  257. data/components/plugins/sidebars/category_controller.rb +13 -0
  258. data/components/plugins/sidebars/delicious/content.rhtml +20 -0
  259. data/components/plugins/sidebars/delicious_controller.rb +29 -0
  260. data/components/plugins/sidebars/flickr/content.rhtml +15 -0
  261. data/components/plugins/sidebars/flickr_controller.rb +16 -0
  262. data/components/plugins/sidebars/fortythree/content.rhtml +8 -0
  263. data/components/plugins/sidebars/fortythree_controller.rb +12 -0
  264. data/components/plugins/sidebars/fortythreeplaces/content.rhtml +8 -0
  265. data/components/plugins/sidebars/fortythreeplaces_controller.rb +12 -0
  266. data/components/plugins/sidebars/magnolia/content.rhtml +12 -0
  267. data/components/plugins/sidebars/magnolia_controller.rb +17 -0
  268. data/components/plugins/sidebars/recent_comments/content.rhtml +12 -0
  269. data/components/plugins/sidebars/recent_comments_controller.rb +23 -0
  270. data/components/plugins/sidebars/static/content.rhtml +2 -0
  271. data/components/plugins/sidebars/static_controller.rb +23 -0
  272. data/components/plugins/sidebars/tada/content.rhtml +12 -0
  273. data/components/plugins/sidebars/tada_controller.rb +12 -0
  274. data/components/plugins/sidebars/tag/content.rhtml +8 -0
  275. data/components/plugins/sidebars/tag_controller.rb +18 -0
  276. data/components/plugins/sidebars/technorati/content.rhtml +8 -0
  277. data/components/plugins/sidebars/technorati_controller.rb +12 -0
  278. data/components/plugins/sidebars/upcoming/content.rhtml +8 -0
  279. data/components/plugins/sidebars/upcoming_controller.rb +11 -0
  280. data/components/plugins/sidebars/xbox/content.rhtml +2 -0
  281. data/components/plugins/sidebars/xbox_controller.rb +6 -0
  282. data/components/plugins/sidebars/xml/content.rhtml +12 -0
  283. data/components/plugins/sidebars/xml_controller.rb +11 -0
  284. data/components/plugins/textfilters/amazon_controller.rb +39 -0
  285. data/components/plugins/textfilters/code_controller.rb +59 -0
  286. data/components/plugins/textfilters/flickr_controller.rb +75 -0
  287. data/components/plugins/textfilters/htmlfilter_controller.rb +8 -0
  288. data/components/plugins/textfilters/lightbox_controller.rb +122 -0
  289. data/components/plugins/textfilters/macropost_controller.rb +14 -0
  290. data/components/plugins/textfilters/macropre_controller.rb +14 -0
  291. data/components/plugins/textfilters/markdown_controller.rb +32 -0
  292. data/components/plugins/textfilters/none_controller.rb +8 -0
  293. data/components/plugins/textfilters/smartypants_controller.rb +8 -0
  294. data/components/plugins/textfilters/sparkline_controller.rb +87 -0
  295. data/components/plugins/textfilters/textile_controller.rb +8 -0
  296. data/components/sidebars/README +36 -0
  297. data/config/boot.rb +44 -0
  298. data/config/database.yml +17 -0
  299. data/config/database.yml-pgsql +17 -0
  300. data/config/database.yml.example +18 -0
  301. data/config/environment.rb +145 -0
  302. data/config/environments/development.rb +17 -0
  303. data/config/environments/production.rb +19 -0
  304. data/config/environments/test.rb +26 -0
  305. data/config/iTunes.yml +72 -0
  306. data/config/lighttpd.conf +46 -0
  307. data/config/mail.yml +8 -0
  308. data/config/mail.yml.example +8 -0
  309. data/config/routes.rb +92 -0
  310. data/db/DB +0 -0
  311. data/db/DB.test +0 -0
  312. data/db/converters/README +14 -0
  313. data/db/converters/feed.rb +68 -0
  314. data/db/converters/mt-import.rb +72 -0
  315. data/db/converters/mt3.rb +172 -0
  316. data/db/converters/rss.rb +67 -0
  317. data/db/converters/s9y.rb +182 -0
  318. data/db/converters/textpattern.rb +137 -0
  319. data/db/converters/wordpress.rb +187 -0
  320. data/db/development_structure.sql +691 -0
  321. data/db/migrate/001_initial_schema.rb +127 -0
  322. data/db/migrate/002_add_user_email.rb +17 -0
  323. data/db/migrate/003_add_article_user_id.rb +20 -0
  324. data/db/migrate/004_add_sidebars.rb +31 -0
  325. data/db/migrate/005_add_cache_table.rb +20 -0
  326. data/db/migrate/006_add_pages.rb +17 -0
  327. data/db/migrate/007_add_permalink.rb +36 -0
  328. data/db/migrate/008_add_page_title.rb +9 -0
  329. data/db/migrate/009_add_article_guid.rb +10 -0
  330. data/db/migrate/010_add_tags.rb +19 -0
  331. data/db/migrate/011_add_article_id.rb +17 -0
  332. data/db/migrate/012_enlarge_settings.rb +11 -0
  333. data/db/migrate/013_add_textfilters.rb +33 -0
  334. data/db/migrate/014_move_text_filter_to_text_filter_id.rb +43 -0
  335. data/db/migrate/015_convert_mysql_to_innodb.rb +19 -0
  336. data/db/migrate/016_fix_is_primary_postgres.rb +19 -0
  337. data/db/migrate/017_add_comment_user_id.rb +23 -0
  338. data/db/migrate/018_add_guids.rb +13 -0
  339. data/db/migrate/019_add_whiteboards_to_content.rb +15 -0
  340. data/db/migrate/020_superclass_articles.rb +167 -0
  341. data/db/migrate/021_superclass_comments.rb +94 -0
  342. data/db/migrate/022_superclass_trackbacks.rb +71 -0
  343. data/db/migrate/023_superclass_pages.rb +64 -0
  344. data/db/migrate/024_cleanup_contents.rb +54 -0
  345. data/db/migrate/025_add_itunes_metadata.rb +29 -0
  346. data/db/migrate/026_add_redirect_table.rb +13 -0
  347. data/db/migrate/027_set_comment_published_flag.rb +19 -0
  348. data/db/migrate/028_rename_redirect_to.rb +12 -0
  349. data/db/migrate/029_add_user_notification.rb +29 -0
  350. data/db/migrate/030_index_sessions.rb +9 -0
  351. data/db/migrate/031_add_notifications_table.rb +14 -0
  352. data/db/migrate/032_add_jabber_notification.rb +11 -0
  353. data/db/migrate/033_add_count_caching.rb +34 -0
  354. data/db/migrate/034_boolify_published.rb +36 -0
  355. data/db/migrate/035_boolify_content_allow_foo.rb +36 -0
  356. data/db/migrate/036_add_tag_display_name.rb +53 -0
  357. data/db/migrate/037_enlarge_ip_field.rb +9 -0
  358. data/db/migrate/038_add_blog_object.rb +52 -0
  359. data/db/migrate/039_serialize_blog_attributes.rb +160 -0
  360. data/db/migrate/040_attach_content_to_blog.rb +28 -0
  361. data/db/migrate/041_fixup_default_sidebars.rb +18 -0
  362. data/db/migrate/042_remove_sidebar_staged_config.rb +22 -0
  363. data/db/migrate/043_create_triggers.rb +14 -0
  364. data/db/migrate/044_add_published_at_to_content.rb +18 -0
  365. data/db/migrate/045_fix_contents_published_default.rb +9 -0
  366. data/db/migrate/046_fixup_forthcoming_publications.rb +40 -0
  367. data/db/schema.mysql-v3.sql +218 -0
  368. data/db/schema.mysql.sql +218 -0
  369. data/db/schema.postgresql.sql +218 -0
  370. data/db/schema.rb +169 -0
  371. data/db/schema.sqlite.sql +218 -0
  372. data/db/schema.sqlserver.sql +232 -0
  373. data/db/schema_version +1 -0
  374. data/db/scripts/fix_permalinks.rb +5 -0
  375. data/db/updates/update.168.to.200.mysql.sql +33 -0
  376. data/db/updates/update.168.to.200.psql.sql +30 -0
  377. data/doc/Installer.txt +55 -0
  378. data/doc/README_FOR_APP +2 -0
  379. data/installer/rails-installer.rb +488 -0
  380. data/installer/rails_installer_defaults.yml +4 -0
  381. data/installer/typo-installer.rb +35 -0
  382. data/lib/backpack_api.rb +202 -0
  383. data/lib/bare_migration.rb +142 -0
  384. data/lib/email_notify.rb +32 -0
  385. data/lib/format.rb +19 -0
  386. data/lib/generators/sidebar/sidebar_generator.rb +13 -0
  387. data/lib/generators/sidebar/templates/components/plugins/sidebars/controller_template.rb +20 -0
  388. data/lib/generators/sidebar/templates/components/plugins/sidebars/views/content_template.rhtml +4 -0
  389. data/lib/jabber_notify.rb +32 -0
  390. data/lib/login_system.rb +85 -0
  391. data/lib/migrator.rb +28 -0
  392. data/lib/rails_patch/active_record.rb +36 -0
  393. data/lib/rails_patch/components.rb +14 -0
  394. data/lib/sidebars/component_plugin.rb +5 -0
  395. data/lib/sidebars/plugin.rb +241 -0
  396. data/lib/spam_protection.rb +126 -0
  397. data/lib/tasks/release.rake +171 -0
  398. data/lib/tasks/schemas.rake +6 -0
  399. data/lib/tasks/sweep_cache.rake +6 -0
  400. data/lib/text_filter_plugin.rb +97 -0
  401. data/lib/transforms.rb +26 -0
  402. data/lib/typo_guid.rb +10 -0
  403. data/lib/typo_plugins.rb +19 -0
  404. data/lib/typo_version.rb +1 -0
  405. data/lib/xmlrpc_fix.rb +13 -0
  406. data/public/.htaccess +34 -0
  407. data/public/404.html +8 -0
  408. data/public/500.html +8 -0
  409. data/public/dispatch.cgi +10 -0
  410. data/public/dispatch.fcgi +24 -0
  411. data/public/dispatch.rb +10 -0
  412. data/public/favicon.ico +0 -0
  413. data/public/images/admin/dot-vertical.gif +0 -0
  414. data/public/images/admin/h-tile.gif +0 -0
  415. data/public/images/admin/hdr-tile.gif +0 -0
  416. data/public/images/admin/toggle.gif +0 -0
  417. data/public/images/bg.jpg +0 -0
  418. data/public/images/bgcolor.jpg +0 -0
  419. data/public/images/body_bg.png +0 -0
  420. data/public/images/branding_bg.png +0 -0
  421. data/public/images/branding_logo.png +0 -0
  422. data/public/images/checked.gif +0 -0
  423. data/public/images/content_bg.png +0 -0
  424. data/public/images/delete.png +0 -0
  425. data/public/images/footer.jpg +0 -0
  426. data/public/images/footer.png +0 -0
  427. data/public/images/global_bg.png +0 -0
  428. data/public/images/global_logo.png +0 -0
  429. data/public/images/go.png +0 -0
  430. data/public/images/header.jpg +0 -0
  431. data/public/images/loading.gif +0 -0
  432. data/public/images/not-checked copy.gif +0 -0
  433. data/public/images/not-checked.gif +0 -0
  434. data/public/images/overlay.png +0 -0
  435. data/public/images/powered.gif +0 -0
  436. data/public/images/section_bg.png +0 -0
  437. data/public/images/sections_bg.png +0 -0
  438. data/public/images/sections_hilite.png +0 -0
  439. data/public/images/sections_hover.png +0 -0
  440. data/public/images/spinner-blue.gif +0 -0
  441. data/public/images/spinner.gif +0 -0
  442. data/public/images/spot-header.gif +0 -0
  443. data/public/images/spot-title.gif +0 -0
  444. data/public/images/x-ed.gif +0 -0
  445. data/public/javascripts/application.js +2 -0
  446. data/public/javascripts/controls.js +815 -0
  447. data/public/javascripts/cookies.js +60 -0
  448. data/public/javascripts/dragdrop.js +724 -0
  449. data/public/javascripts/effects.js +953 -0
  450. data/public/javascripts/lightbox.js +348 -0
  451. data/public/javascripts/prototype.js +1985 -0
  452. data/public/javascripts/scriptaculous.js +47 -0
  453. data/public/javascripts/slider.js +258 -0
  454. data/public/javascripts/typo.js +85 -0
  455. data/public/robots.txt +2 -0
  456. data/public/stylesheets/administration.css +585 -0
  457. data/public/stylesheets/lightbox.css +22 -0
  458. data/public/stylesheets/rss.css +54 -0
  459. data/public/stylesheets/user-styles.css +0 -0
  460. data/script/about +3 -0
  461. data/script/benchmarker +19 -0
  462. data/script/breakpointer +3 -0
  463. data/script/console +3 -0
  464. data/script/destroy +3 -0
  465. data/script/generate +3 -0
  466. data/script/lighttpd +2 -0
  467. data/script/logreport +79 -0
  468. data/script/migrate +31 -0
  469. data/script/performance/benchmarker +3 -0
  470. data/script/performance/profiler +3 -0
  471. data/script/plugin +3 -0
  472. data/script/process/reaper +3 -0
  473. data/script/process/spawner +3 -0
  474. data/script/process/spinner +3 -0
  475. data/script/profiler +34 -0
  476. data/script/runner +3 -0
  477. data/script/server +3 -0
  478. data/script/spacecheck +40 -0
  479. data/test/fixtures/articles_categories.yml +31 -0
  480. data/test/fixtures/articles_tags.yml +19 -0
  481. data/test/fixtures/blacklist_patterns.yml +10 -0
  482. data/test/fixtures/blogs.yml +74 -0
  483. data/test/fixtures/categories.yml +35 -0
  484. data/test/fixtures/contents.yml +297 -0
  485. data/test/fixtures/notification_mailer/article +3 -0
  486. data/test/fixtures/notification_mailer/comment +3 -0
  487. data/test/fixtures/notification_mailer/trackback +3 -0
  488. data/test/fixtures/notifications.yml +0 -0
  489. data/test/fixtures/page_caches.yml +7 -0
  490. data/test/fixtures/redirects.yml +13 -0
  491. data/test/fixtures/resources.yml +24 -0
  492. data/test/fixtures/sidebars.yml +5 -0
  493. data/test/fixtures/tags.yml +13 -0
  494. data/test/fixtures/text_filters.yml +42 -0
  495. data/test/fixtures/triggers.yml +1 -0
  496. data/test/fixtures/users.yml +56 -0
  497. data/test/functional/accounts_controller_test.rb +82 -0
  498. data/test/functional/admin/article_preview_test.rb +67 -0
  499. data/test/functional/admin/blacklist_controller_test.rb +63 -0
  500. data/test/functional/admin/categories_controller_test.rb +112 -0
  501. data/test/functional/admin/comments_controller_test.rb +78 -0
  502. data/test/functional/admin/content_controller_test.rb +234 -0
  503. data/test/functional/admin/general_controller_test.rb +26 -0
  504. data/test/functional/admin/pages_controller_test.rb +103 -0
  505. data/test/functional/admin/resources_controller_test.rb +49 -0
  506. data/test/functional/admin/textfilters_controller_test.rb +29 -0
  507. data/test/functional/admin/themes_controller_test.rb +34 -0
  508. data/test/functional/admin/trackbacks_controller_test.rb +76 -0
  509. data/test/functional/admin/users_controller_test.rb +72 -0
  510. data/test/functional/articles_controller_test.rb +525 -0
  511. data/test/functional/backend_controller_test.rb +273 -0
  512. data/test/functional/redirect_controller_test.rb +40 -0
  513. data/test/functional/textfilter_controller_test.rb +275 -0
  514. data/test/functional/theme_controller_test.rb +45 -0
  515. data/test/functional/xml_controller_test.rb +353 -0
  516. data/test/mocks/test/dns_mock.rb +13 -0
  517. data/test/mocks/test/flickr_mock.rb +30 -0
  518. data/test/mocks/test/http_mock.rb +38 -0
  519. data/test/mocks/test/theme_mock.rb +5 -0
  520. data/test/mocks/test/xmlrpc_mock.rb +27 -0
  521. data/test/mocks/themes/123-numbers-in-path/about.markdown +0 -0
  522. data/test/mocks/themes/CamelCaseDirectory/about.markdown +0 -0
  523. data/test/mocks/themes/azure/about.markdown +5 -0
  524. data/test/mocks/themes/azure/layouts/default.rhtml +50 -0
  525. data/test/mocks/themes/azure/preview.png +0 -0
  526. data/test/mocks/themes/azure/views/theme/static_view_test.rhtml +1 -0
  527. data/test/mocks/themes/i-have-special-chars/about.markdown +0 -0
  528. data/test/test_helper.rb +95 -0
  529. data/test/unit/article_test.rb +245 -0
  530. data/test/unit/assumptions_tests.rb +54 -0
  531. data/test/unit/audioscrobbler_test.rb +132 -0
  532. data/test/unit/blacklist_pattern_test.rb +14 -0
  533. data/test/unit/blog_test.rb +83 -0
  534. data/test/unit/category_test.rb +37 -0
  535. data/test/unit/comment_test.rb +117 -0
  536. data/test/unit/configuration_test.rb +21 -0
  537. data/test/unit/content_state/factory_test.rb +84 -0
  538. data/test/unit/delicious_test.rb +96 -0
  539. data/test/unit/flickr_test.rb +134 -0
  540. data/test/unit/fortythree_test.rb +66 -0
  541. data/test/unit/magnolia_test.rb +87 -0
  542. data/test/unit/metafragment_test.rb +63 -0
  543. data/test/unit/notification_mailer_test.rb +55 -0
  544. data/test/unit/observer_test.rb +40 -0
  545. data/test/unit/page_cache_test.rb +34 -0
  546. data/test/unit/page_test.rb +25 -0
  547. data/test/unit/ping_test.rb +111 -0
  548. data/test/unit/redirect_test.rb +19 -0
  549. data/test/unit/resource_test.rb +71 -0
  550. data/test/unit/sidebar_test.rb +14 -0
  551. data/test/unit/tag_test.rb +66 -0
  552. data/test/unit/text_filter_test.rb +126 -0
  553. data/test/unit/theme_test.rb +44 -0
  554. data/test/unit/trackback_test.rb +45 -0
  555. data/test/unit/trigger_test.rb +40 -0
  556. data/test/unit/user_test.rb +111 -0
  557. data/themes/azure/about.markdown +5 -0
  558. data/themes/azure/images/bg-tile.gif +0 -0
  559. data/themes/azure/images/bracket.gif +0 -0
  560. data/themes/azure/images/bullet.gif +0 -0
  561. data/themes/azure/images/hdr.gif +0 -0
  562. data/themes/azure/images/q-close.gif +0 -0
  563. data/themes/azure/images/q-open.gif +0 -0
  564. data/themes/azure/images/sbar-tile.gif +0 -0
  565. data/themes/azure/images/spinner.gif +0 -0
  566. data/themes/azure/images/xlink.gif +0 -0
  567. data/themes/azure/layouts/default.rhtml +50 -0
  568. data/themes/azure/preview.png +0 -0
  569. data/themes/azure/stylesheets/azure.css +436 -0
  570. data/themes/azure/stylesheets/print.css +30 -0
  571. data/themes/azure/views/theme/static_view_test.rhtml +1 -0
  572. data/vendor/akismet/Akismet.rb +140 -0
  573. data/vendor/bluecloth/CHANGES +366 -0
  574. data/vendor/bluecloth/LICENSE +340 -0
  575. data/vendor/bluecloth/README +99 -0
  576. data/vendor/bluecloth/bin/bluecloth +83 -0
  577. data/vendor/bluecloth/install.rb +150 -0
  578. data/vendor/bluecloth/lib/bluecloth.rb +1144 -0
  579. data/vendor/bluecloth/test.rb +117 -0
  580. data/vendor/bluecloth/tests/00_Class.tests.rb +71 -0
  581. data/vendor/bluecloth/tests/05_Markdown.tests.rb +1527 -0
  582. data/vendor/bluecloth/tests/10_Bug.tests.rb +57 -0
  583. data/vendor/bluecloth/tests/15_Contrib.tests.rb +132 -0
  584. data/vendor/bluecloth/tests/bctestcase.rb +274 -0
  585. data/vendor/bluecloth/tests/data/antsugar.txt +34 -0
  586. data/vendor/bluecloth/tests/data/ml-announce.txt +17 -0
  587. data/vendor/bluecloth/tests/data/re-overflow.txt +67 -0
  588. data/vendor/bluecloth/tests/data/re-overflow2.txt +281 -0
  589. data/vendor/bluecloth/utils.rb +553 -0
  590. data/vendor/flickr/Rakefile +36 -0
  591. data/vendor/flickr/flickr.rb +490 -0
  592. data/vendor/flickr/index.html +129 -0
  593. data/vendor/flickr/test_flickr.rb +173 -0
  594. data/vendor/jabber4r/CHANGES +8 -0
  595. data/vendor/jabber4r/LICENSE.txt +12 -0
  596. data/vendor/jabber4r/README +180 -0
  597. data/vendor/jabber4r/Rakefile.rb +143 -0
  598. data/vendor/jabber4r/lib/jabber4r/jabber4r.rb +22 -0
  599. data/vendor/jabber4r/lib/jabber4r/jid.rb +93 -0
  600. data/vendor/jabber4r/lib/jabber4r/protocol.rb +1384 -0
  601. data/vendor/jabber4r/lib/jabber4r/rexml_1.8_patch.rb +16 -0
  602. data/vendor/jabber4r/lib/jabber4r/roster.rb +322 -0
  603. data/vendor/jabber4r/lib/jabber4r/session.rb +615 -0
  604. data/vendor/jabber4r/lib/jabber4r/vcard.rb +42 -0
  605. data/vendor/plugins/expiring_action_cache/init.rb +2 -0
  606. data/vendor/plugins/expiring_action_cache/lib/actionparamcache.rb +113 -0
  607. data/vendor/plugins/expiring_action_cache/lib/metafragment.rb +46 -0
  608. data/vendor/plugins/upload_progress/CHANGELOG +3 -0
  609. data/vendor/plugins/upload_progress/MIT-LICENSE +20 -0
  610. data/vendor/plugins/upload_progress/README +45 -0
  611. data/vendor/plugins/upload_progress/Rakefile +23 -0
  612. data/vendor/plugins/upload_progress/init.rb +7 -0
  613. data/vendor/plugins/upload_progress/lib/multipart_progress.rb +169 -0
  614. data/vendor/plugins/upload_progress/lib/progress.rb +145 -0
  615. data/vendor/plugins/upload_progress/lib/upload_progress.rb +303 -0
  616. data/vendor/plugins/upload_progress/lib/upload_progress_helper.rb +424 -0
  617. data/vendor/plugins/upload_progress/public/stylesheets/upload_progress.css +21 -0
  618. data/vendor/plugins/upload_progress/test/multipart_progress_testx.rb +364 -0
  619. data/vendor/plugins/upload_progress/test/upload_progress_helper_testx.rb +134 -0
  620. data/vendor/plugins/upload_progress/test/upload_progress_testx.rb +88 -0
  621. data/vendor/redcloth/RedCloth.gemspec +52 -0
  622. data/vendor/redcloth/bin/redcloth +3 -0
  623. data/vendor/redcloth/doc/CHANGELOG +160 -0
  624. data/vendor/redcloth/doc/COPYING +25 -0
  625. data/vendor/redcloth/doc/README +106 -0
  626. data/vendor/redcloth/doc/REFERENCE +216 -0
  627. data/vendor/redcloth/doc/make.rb +359 -0
  628. data/vendor/redcloth/install.rb +1032 -0
  629. data/vendor/redcloth/lib/redcloth.rb +1130 -0
  630. data/vendor/redcloth/run-tests.rb +28 -0
  631. data/vendor/redcloth/setup.rb +1376 -0
  632. data/vendor/redcloth/tests/code.yml +105 -0
  633. data/vendor/redcloth/tests/hard_breaks.yml +26 -0
  634. data/vendor/redcloth/tests/images.yml +171 -0
  635. data/vendor/redcloth/tests/instiki.yml +39 -0
  636. data/vendor/redcloth/tests/links.yml +155 -0
  637. data/vendor/redcloth/tests/lists.yml +77 -0
  638. data/vendor/redcloth/tests/markdown.yml +218 -0
  639. data/vendor/redcloth/tests/poignant.yml +64 -0
  640. data/vendor/redcloth/tests/table.yml +198 -0
  641. data/vendor/redcloth/tests/textism.yml +406 -0
  642. data/vendor/ruby-mp3info/lib/mp3info.rb +720 -0
  643. data/vendor/rubypants/README +114 -0
  644. data/vendor/rubypants/Rakefile +55 -0
  645. data/vendor/rubypants/html/classes/RubyPants.html +924 -0
  646. data/vendor/rubypants/html/created.rid +1 -0
  647. data/vendor/rubypants/html/files/README.html +248 -0
  648. data/vendor/rubypants/html/files/rubypants_rb.html +125 -0
  649. data/vendor/rubypants/html/fr_class_index.html +27 -0
  650. data/vendor/rubypants/html/fr_file_index.html +28 -0
  651. data/vendor/rubypants/html/fr_method_index.html +38 -0
  652. data/vendor/rubypants/html/index.html +24 -0
  653. data/vendor/rubypants/html/rdoc-style.css +172 -0
  654. data/vendor/rubypants/install.rb +9 -0
  655. data/vendor/rubypants/rubypants.rb +490 -0
  656. data/vendor/rubypants/test_rubypants.rb +162 -0
  657. data/vendor/sparklines/README.txt +47 -0
  658. data/vendor/sparklines/USAGE +14 -0
  659. data/vendor/sparklines/lib/sparklines.rb +435 -0
  660. data/vendor/sparklines/samples/sparklinestest.rb +26 -0
  661. data/vendor/sparklines/sparklines_generator.rb +9 -0
  662. data/vendor/sparklines/templates/sparklines_controller.rb +30 -0
  663. data/vendor/sparklines/templates/sparklines_helper.rb +30 -0
  664. data/vendor/syntax/LICENSE +27 -0
  665. data/vendor/syntax/NEWS +16 -0
  666. data/vendor/syntax/README +38 -0
  667. data/vendor/syntax/Rakefile +194 -0
  668. data/vendor/syntax/api/classes/Syntax.html +173 -0
  669. data/vendor/syntax/api/classes/Syntax/Convertors.html +91 -0
  670. data/vendor/syntax/api/classes/Syntax/Convertors/Abstract.html +159 -0
  671. data/vendor/syntax/api/classes/Syntax/Convertors/HTML.html +149 -0
  672. data/vendor/syntax/api/classes/Syntax/Default.html +123 -0
  673. data/vendor/syntax/api/classes/Syntax/Ruby.html +319 -0
  674. data/vendor/syntax/api/classes/Syntax/Token.html +151 -0
  675. data/vendor/syntax/api/classes/Syntax/Tokenizer.html +324 -0
  676. data/vendor/syntax/api/classes/Syntax/Version.html +109 -0
  677. data/vendor/syntax/api/classes/Syntax/XML.html +205 -0
  678. data/vendor/syntax/api/classes/Syntax/YAML.html +189 -0
  679. data/vendor/syntax/api/created.rid +1 -0
  680. data/vendor/syntax/api/files/README.html +155 -0
  681. data/vendor/syntax/api/files/lib/syntax/common_rb.html +96 -0
  682. data/vendor/syntax/api/files/lib/syntax/convertors/abstract_rb.html +96 -0
  683. data/vendor/syntax/api/files/lib/syntax/convertors/html_rb.html +96 -0
  684. data/vendor/syntax/api/files/lib/syntax/lang/ruby_rb.html +96 -0
  685. data/vendor/syntax/api/files/lib/syntax/lang/xml_rb.html +96 -0
  686. data/vendor/syntax/api/files/lib/syntax/lang/yaml_rb.html +96 -0
  687. data/vendor/syntax/api/files/lib/syntax/version_rb.html +92 -0
  688. data/vendor/syntax/api/files/lib/syntax_rb.html +96 -0
  689. data/vendor/syntax/api/fr_class_index.html +56 -0
  690. data/vendor/syntax/api/fr_file_index.html +54 -0
  691. data/vendor/syntax/api/fr_method_index.html +65 -0
  692. data/vendor/syntax/api/index.html +26 -0
  693. data/vendor/syntax/api/rdoc-style.css +175 -0
  694. data/vendor/syntax/doc/manual-html/chapter-1.html +198 -0
  695. data/vendor/syntax/doc/manual-html/chapter-2.html +262 -0
  696. data/vendor/syntax/doc/manual-html/chapter-3.html +266 -0
  697. data/vendor/syntax/doc/manual-html/chapter-4.html +267 -0
  698. data/vendor/syntax/doc/manual-html/index.html +152 -0
  699. data/vendor/syntax/doc/manual-html/stylesheets/manual.css +270 -0
  700. data/vendor/syntax/doc/manual-html/stylesheets/ruby.css +17 -0
  701. data/vendor/syntax/doc/manual/chapter.erb +38 -0
  702. data/vendor/syntax/doc/manual/example.erb +18 -0
  703. data/vendor/syntax/doc/manual/index.erb +29 -0
  704. data/vendor/syntax/doc/manual/manual.rb +311 -0
  705. data/vendor/syntax/doc/manual/manual.yml +43 -0
  706. data/vendor/syntax/doc/manual/page.erb +87 -0
  707. data/vendor/syntax/doc/manual/parts/0000.txt +5 -0
  708. data/vendor/syntax/doc/manual/parts/0001.txt +16 -0
  709. data/vendor/syntax/doc/manual/parts/0002.txt +24 -0
  710. data/vendor/syntax/doc/manual/parts/0003.txt +6 -0
  711. data/vendor/syntax/doc/manual/parts/0004.txt +32 -0
  712. data/vendor/syntax/doc/manual/parts/0005.txt +18 -0
  713. data/vendor/syntax/doc/manual/parts/0006.txt +62 -0
  714. data/vendor/syntax/doc/manual/parts/0007.txt +3 -0
  715. data/vendor/syntax/doc/manual/parts/0008.txt +5 -0
  716. data/vendor/syntax/doc/manual/parts/0009.txt +29 -0
  717. data/vendor/syntax/doc/manual/parts/0010.txt +21 -0
  718. data/vendor/syntax/doc/manual/stylesheets/manual.css +270 -0
  719. data/vendor/syntax/doc/manual/stylesheets/ruby.css +17 -0
  720. data/vendor/syntax/doc/manual/tutorial.erb +30 -0
  721. data/vendor/syntax/lib/syntax.rb +38 -0
  722. data/vendor/syntax/lib/syntax/common.rb +163 -0
  723. data/vendor/syntax/lib/syntax/convertors/abstract.rb +27 -0
  724. data/vendor/syntax/lib/syntax/convertors/html.rb +51 -0
  725. data/vendor/syntax/lib/syntax/lang/ruby.rb +317 -0
  726. data/vendor/syntax/lib/syntax/lang/xml.rb +108 -0
  727. data/vendor/syntax/lib/syntax/lang/yaml.rb +105 -0
  728. data/vendor/syntax/lib/syntax/version.rb +9 -0
  729. data/vendor/syntax/setup.rb +1331 -0
  730. data/vendor/syntax/syntax.gemspec +24 -0
  731. data/vendor/syntax/test/ALL-TESTS.rb +5 -0
  732. data/vendor/syntax/test/syntax/tc_ruby.rb +871 -0
  733. data/vendor/syntax/test/syntax/tc_xml.rb +202 -0
  734. data/vendor/syntax/test/syntax/tc_yaml.rb +228 -0
  735. data/vendor/syntax/test/syntax/tokenizer_testcase.rb +40 -0
  736. data/vendor/syntax/test/tc_syntax.rb +22 -0
  737. data/vendor/uuidtools/CHANGELOG +4 -0
  738. data/vendor/uuidtools/README +13 -0
  739. data/vendor/uuidtools/install.rb +30 -0
  740. data/vendor/uuidtools/lib/uuidtools.rb +555 -0
  741. data/vendor/uuidtools/rakefile +112 -0
  742. metadata +1022 -0
@@ -0,0 +1,162 @@
1
+ require 'test/unit'
2
+ require './rubypants'
3
+
4
+ # Test EVERYTHING against SmartyPants.pl output!
5
+
6
+
7
+ class TestRubyPants < Test::Unit::TestCase
8
+ def assert_rp_equal(str, orig, options=[2])
9
+ assert_equal orig, RubyPants.new(str, options).to_html
10
+ end
11
+
12
+ def assert_verbatim(str)
13
+ assert_rp_equal str, str
14
+ end
15
+
16
+ def test_verbatim
17
+ assert_verbatim "foo!"
18
+ assert_verbatim "<div>This is HTML</div>"
19
+ assert_verbatim "<div>This is HTML with <crap </div> tags>"
20
+ assert_verbatim <<EOF
21
+ multiline
22
+
23
+ <b>html</b>
24
+
25
+ code
26
+
27
+ EOF
28
+ end
29
+
30
+ def test_quotes
31
+ assert_rp_equal '"A first example"', '&#8220;A first example&#8221;'
32
+ assert_rp_equal '"A first "nested" example"',
33
+ '&#8220;A first &#8220;nested&#8221; example&#8221;'
34
+
35
+ assert_rp_equal '".', '&#8221;.'
36
+ assert_rp_equal '"a', '&#8220;a'
37
+
38
+ assert_rp_equal "'.", '&#8217;.'
39
+ assert_rp_equal "'a", '&#8216;a'
40
+
41
+ assert_rp_equal %{<p>He said, "'Quoted' words in a larger quote."</p>},
42
+ "<p>He said, &#8220;&#8216;Quoted&#8217; words in a larger quote.&#8221;</p>"
43
+
44
+ assert_rp_equal %{"I like the 70's"}, '&#8220;I like the 70&#8217;s&#8221;'
45
+ assert_rp_equal %{"I like the '70s"}, '&#8220;I like the &#8217;70s&#8221;'
46
+ assert_rp_equal %{"I like the '70!"}, '&#8220;I like the &#8216;70!&#8221;'
47
+
48
+ assert_rp_equal 'pre"post', 'pre&#8221;post'
49
+ assert_rp_equal 'pre "post', 'pre &#8220;post'
50
+ assert_rp_equal 'pre&nbsp;"post', 'pre&nbsp;&#8220;post'
51
+ assert_rp_equal 'pre--"post', 'pre&#8211;&#8220;post'
52
+ assert_rp_equal 'pre--"!', 'pre&#8211;&#8221;!'
53
+
54
+ assert_rp_equal "pre'post", 'pre&#8217;post'
55
+ assert_rp_equal "pre 'post", 'pre &#8216;post'
56
+ assert_rp_equal "pre&nbsp;'post", 'pre&nbsp;&#8216;post'
57
+ assert_rp_equal "pre--'post", 'pre&#8211;&#8216;post'
58
+ assert_rp_equal "pre--'!", 'pre&#8211;&#8217;!'
59
+
60
+ assert_rp_equal "<b>'</b>", "<b>&#8216;</b>"
61
+ assert_rp_equal "foo<b>'</b>", "foo<b>&#8217;</b>"
62
+
63
+ assert_rp_equal '<b>"</b>', "<b>&#8220;</b>"
64
+ assert_rp_equal 'foo<b>"</b>', "foo<b>&#8221;</b>"
65
+ end
66
+
67
+ def test_dashes
68
+ assert_rp_equal "foo--bar", 'foo&#8212;bar', 1
69
+ assert_rp_equal "foo---bar", 'foo&#8212;-bar', 1
70
+ assert_rp_equal "foo----bar", 'foo&#8212;&#8212;bar', 1
71
+ assert_rp_equal "foo-----bar", 'foo&#8212;&#8212;-bar', 1
72
+ assert_rp_equal "--foo--bar--quux--",
73
+ '&#8212;foo&#8212;bar&#8212;quux&#8212;', 1
74
+
75
+ assert_rp_equal "foo--bar", 'foo&#8211;bar', 2
76
+ assert_rp_equal "foo---bar", 'foo&#8212;bar', 2
77
+ assert_rp_equal "foo----bar", 'foo&#8212;-bar', 2
78
+ assert_rp_equal "foo-----bar", 'foo&#8212;&#8211;bar', 2
79
+ assert_rp_equal "--foo--bar--quux--",
80
+ '&#8211;foo&#8211;bar&#8211;quux&#8211;', 2
81
+
82
+ assert_rp_equal "foo--bar", 'foo&#8212;bar', 3
83
+ assert_rp_equal "foo---bar", 'foo&#8211;bar', 3
84
+ assert_rp_equal "foo----bar", 'foo&#8211;-bar', 3
85
+ assert_rp_equal "foo-----bar", 'foo&#8211;&#8212;bar', 3
86
+ assert_rp_equal "--foo--bar--quux--",
87
+ '&#8212;foo&#8212;bar&#8212;quux&#8212;', 3
88
+ end
89
+
90
+ def test_ellipses
91
+ assert_rp_equal "foo..bar", 'foo..bar'
92
+ assert_rp_equal "foo...bar", 'foo&#8230;bar'
93
+ assert_rp_equal "foo....bar", 'foo&#8230;.bar'
94
+
95
+ # Nasty ones
96
+ assert_rp_equal "foo. . ..bar", 'foo&#8230;.bar'
97
+ assert_rp_equal "foo. . ...bar", 'foo. . &#8230;bar'
98
+ assert_rp_equal "foo. . ....bar", 'foo. . &#8230;.bar'
99
+ end
100
+
101
+ def test_backticks
102
+ assert_rp_equal "pre``post", 'pre&#8220;post'
103
+ assert_rp_equal "pre ``post", 'pre &#8220;post'
104
+ assert_rp_equal "pre&nbsp;``post", 'pre&nbsp;&#8220;post'
105
+ assert_rp_equal "pre--``post", 'pre&#8211;&#8220;post'
106
+ assert_rp_equal "pre--``!", 'pre&#8211;&#8220;!'
107
+
108
+ assert_rp_equal "pre''post", 'pre&#8221;post'
109
+ assert_rp_equal "pre ''post", 'pre &#8221;post'
110
+ assert_rp_equal "pre&nbsp;''post", 'pre&nbsp;&#8221;post'
111
+ assert_rp_equal "pre--''post", 'pre&#8211;&#8221;post'
112
+ assert_rp_equal "pre--''!", 'pre&#8211;&#8221;!'
113
+ end
114
+
115
+ def test_single_backticks
116
+ o = [:oldschool, :allbackticks]
117
+
118
+ assert_rp_equal "`foo'", "&#8216;foo&#8217;", o
119
+
120
+ assert_rp_equal "pre`post", 'pre&#8216;post', o
121
+ assert_rp_equal "pre `post", 'pre &#8216;post', o
122
+ assert_rp_equal "pre&nbsp;`post", 'pre&nbsp;&#8216;post', o
123
+ assert_rp_equal "pre--`post", 'pre&#8211;&#8216;post', o
124
+ assert_rp_equal "pre--`!", 'pre&#8211;&#8216;!', o
125
+
126
+ assert_rp_equal "pre'post", 'pre&#8217;post', o
127
+ assert_rp_equal "pre 'post", 'pre &#8217;post', o
128
+ assert_rp_equal "pre&nbsp;'post", 'pre&nbsp;&#8217;post', o
129
+ assert_rp_equal "pre--'post", 'pre&#8211;&#8217;post', o
130
+ assert_rp_equal "pre--'!", 'pre&#8211;&#8217;!', o
131
+ end
132
+
133
+ def test_stupefy
134
+ o = [:stupefy]
135
+
136
+ assert_rp_equal "<p>He said, &#8220;&#8216;Quoted&#8217; words " +
137
+ "in a larger quote.&#8221;</p>",
138
+ %{<p>He said, "'Quoted' words in a larger quote."</p>}, o
139
+
140
+ assert_rp_equal "&#8211; &#8212; &#8216;&#8217; &#8220;&#8221; &#8230;",
141
+ %{- -- '' "" ...}, o
142
+
143
+ assert_rp_equal %{- -- '' "" ...}, %{- -- '' "" ...}, o
144
+ end
145
+
146
+ def test_process_escapes
147
+ assert_rp_equal %q{foo\bar}, "foo\\bar"
148
+ assert_rp_equal %q{foo\\\bar}, "foo&#92;bar"
149
+ assert_rp_equal %q{foo\\\\\bar}, "foo&#92;\\bar"
150
+ assert_rp_equal %q{foo\...bar}, "foo&#46;..bar"
151
+ assert_rp_equal %q{foo\.\.\.bar}, "foo&#46;&#46;&#46;bar"
152
+
153
+ assert_rp_equal %q{foo\'bar}, "foo&#39;bar"
154
+ assert_rp_equal %q{foo\"bar}, "foo&#34;bar"
155
+ assert_rp_equal %q{foo\-bar}, "foo&#45;bar"
156
+ assert_rp_equal %q{foo\`bar}, "foo&#96;bar"
157
+
158
+ assert_rp_equal %q{foo\#bar}, "foo\\#bar"
159
+ assert_rp_equal %q{foo\*bar}, "foo\\*bar"
160
+ assert_rp_equal %q{foo\&bar}, "foo\\&bar"
161
+ end
162
+ end
@@ -0,0 +1,47 @@
1
+ **********************************
2
+ ** Spark Graph Library for Ruby **
3
+ **********************************
4
+
5
+ Geoffrey Grosenbach
6
+ boss@topfunky.com
7
+ http://nubyonrails.topfunky.com
8
+
9
+ Daniel Nugent
10
+ nugend@gmail.com
11
+
12
+
13
+ *** What is it? ***
14
+
15
+ A library for generating small sparkline graphs from Ruby. Use it in desktop apps or Rails apps. See the samples in the 'samples' directory.
16
+
17
+
18
+ *** How do I use it? ***
19
+
20
+ Read the meager documentation in the enclosed 'docs' folder.
21
+
22
+ In Rails, copy the included files (sparklines_controller.rb, sparklines_helper.rb, sparklines.rb) into your controller, helper, and lib directories, respectively.
23
+
24
+ In your custom controller, do
25
+ require_dependency 'sparklines'
26
+ and
27
+ helper :sparklines
28
+
29
+ In your view, call it like this:
30
+
31
+ <%= sparklines_tag [1,2,3,4,5,6] %> <!-- Gives you a smooth graph -->
32
+
33
+ Or specify details:
34
+
35
+ <%= sparklines_tag [1,2,3,4,5,6], :type => 'discrete', :height => 10, :upper => 80, :above_color => 'green', :below_color => 'blue' %>
36
+
37
+
38
+ **********************************
39
+ CHANGES
40
+ **********************************
41
+
42
+ 0.2.1
43
+
44
+ * Added line_color option for smooth graphs
45
+ * Now available as a gem ('gem install sparklines') and as a rails generator ('gem install sparklines_generator')
46
+
47
+
@@ -0,0 +1,14 @@
1
+ Description:
2
+ Generates a controller and helper for making sparklines graphs from a view.
3
+
4
+ No arguments are needed.
5
+
6
+ The generator creates a controller class in app/controllers and
7
+ a helper in app/helpers.
8
+
9
+ Example:
10
+ ./script/generate sparklines
11
+
12
+ This will create:
13
+ Controller: app/controllers/sparklines_controller.rb
14
+ Helper: app/helpers/sparklines_helper.rb
@@ -0,0 +1,435 @@
1
+ require 'RMagick'
2
+ require 'mathn'
3
+
4
+ =begin rdoc
5
+
6
+ A library (in Ruby!) for generating sparklines.
7
+
8
+ Can be used to write to a file or make a web service with Rails or other Ruby CGI apps.
9
+
10
+ Idea and much of the outline for the source lifted directly from {Joe Gregorio's Python Sparklines web service script}[http://bitworking.org/projects/sparklines].
11
+
12
+ Requires the RMagick image library.
13
+
14
+ ==Authors
15
+
16
+ {Dan Nugent}[mailto:nugend@gmail.com]
17
+ Original port from Python Sparklines library.
18
+
19
+
20
+ {Geoffrey Grosenbach}[mailto:boss@topfunky.com] -- http://nubyonrails.topfunky.com
21
+ -- Conversion to module and addition of functions for using with Rails. Also changed functions to use Rails-style option hashes for parameters.
22
+
23
+ ===Tangent regarding RMagick
24
+
25
+ I had a heck of a time getting RMagick to work on my system so in the interests of saving other people the trouble here's a little set of instructions on how to get RMagick working properly and with the right image formats.
26
+
27
+ 1. Install the zlib[http://www.libpng.org/pub/png/libpng.html] library
28
+ 2. With zlib in the same directory as the libpng[http://www.libpng.org/pub/png/libpng.html] library, install libpng
29
+ 3. Option step: Install the {jpeg library}[ftp://ftp.uu.net/graphics/jpeg/jpegsrc.v6b.tar.gz] (You need it to use jpegs and you might want to have it)
30
+ 4. Install ImageMagick from *source*[http://www.imagemagick.org/script/install-source.php]. RMagick requires the ImageMagick headers, so this is important.
31
+ 5. Install RMagick from source[http://rubyforge.org/projects/rmagick/]. The gem is not reliable.
32
+ 6. Edit Magick-conf if necessary. I had to remove -lcms and -ltiff since I didn't want those to be built and the libraries weren't on my system.
33
+
34
+ Please keep in mind that these were only the steps that made RMagick work on my machine. This is a tricky library to get working.
35
+ Consider using Joe Gregorio's version for Python if the installation proves to be too cumbersome.
36
+
37
+ ==General Usage and Defaults
38
+
39
+ To use in a script:
40
+
41
+ require 'rubygems'
42
+ require 'sparklines'
43
+ Sparklines.plot([1,25,33,46,89,90,85,77,42], :type => 'discrete', :height => 20)
44
+
45
+ An image blob will be returned which you can print, write to STDOUT, etc.
46
+
47
+ In Rails,
48
+
49
+ * Install the 'sparklines_generator' gem ('gem install sparklines_generator')
50
+ * Call 'ruby script/generate sparklines'. This will copy the Sparklines controller and helper to your rails directories
51
+ * Add "require 'sparklines'" to the bottom of your config/environment.rb
52
+ * Restart your fcgi's or your WEBrick if necessary
53
+
54
+ And finally, add this to the controller whose view will be using sparklines:
55
+
56
+ helper :sparklines
57
+
58
+ In your view, call it like this:
59
+
60
+ <%= sparkline_tag [1,2,3,4,5,6] %> <!-- Gives you a smooth graph -->
61
+
62
+ Or specify details:
63
+
64
+ <%= sparkline_tag [1,2,3,4,5,6], :type => 'discrete', :height => 10, :upper => 80, :above_color => 'green', :below_color => 'blue' %>
65
+
66
+
67
+ Graph types:
68
+
69
+ area
70
+ discrete
71
+ pie
72
+ smooth
73
+
74
+ General Defaults:
75
+
76
+ :type => 'smooth'
77
+ :height => 14px
78
+ :upper => 50
79
+ :above_color => 'red'
80
+ :below_color => 'grey'
81
+ :background_color => 'white'
82
+ :line_color => 'lightgrey'
83
+
84
+ ==License
85
+
86
+ Licensed under the MIT license.
87
+
88
+ =end
89
+
90
+ module Sparklines
91
+ $VERSION = '0.2.2'
92
+
93
+ # Does the actually plotting of the graph. Calls the appropriate function based on the :type value passed. Defaults to 'smooth.'
94
+ def Sparklines.plot(results=[], options={})
95
+ defaults = { :type => 'smooth',
96
+ :height => 14,
97
+ :upper => 50,
98
+ :diameter => 20,
99
+ :step => 2,
100
+ :line_color => 'lightgrey',
101
+
102
+ :above_color => 'red',
103
+ :below_color => 'grey',
104
+ :background_color => 'white',
105
+ :share_color => 'blue',
106
+ :remain_color => 'lightgrey',
107
+ :min_color => 'blue',
108
+ :max_color => 'green',
109
+ :last_color => 'red',
110
+
111
+ :has_min => false,
112
+ :has_max => false,
113
+ :has_last => false
114
+ }
115
+
116
+ # This symbol->string->symbol is kind of awkward. Is there a more elegant way?
117
+
118
+ # Convert all symbol keys to strings
119
+ defaults.keys.reverse.each do |key|
120
+ defaults[key.to_s] = defaults[key]
121
+ end
122
+ options.keys.reverse.each do |key|
123
+ options[key.to_s] = options[key]
124
+ end
125
+
126
+ options = defaults.merge(options)
127
+
128
+ # Convert options string keys back to symbols
129
+ options.keys.reverse.each do |key|
130
+ options[key.to_sym] = options[key]
131
+ end
132
+
133
+
134
+ # Call the appropriate function for actual plotting
135
+ #self.send('smooth', results, options)
136
+ self.send(options[:type], results, options)
137
+ end
138
+
139
+ # Writes a graph to disk with the specified filename, or "Sparklines.png"
140
+ def Sparklines.plot_to_file(filename="sparklines.png", results=[], options={})
141
+ File.open( filename, 'wb' ) do |png|
142
+ png << self.plot( results, options)
143
+ end
144
+ end
145
+
146
+ # Creates a pie-chart sparkline
147
+ #
148
+ # * results - an array of integer values between 0 and 100 inclusive. Only the first integer will be accepted. It will be used to determine the percentage of the pie that is filled by the share_color
149
+ #
150
+ # * options - a hash that takes parameters:
151
+ #
152
+ # :diameter - An integer that determines what the size of the sparkline will be. Defaults to 20
153
+ #
154
+ # :share_color - A string or color code representing the color to draw the share of the pie represented by percent. Defaults to blue.
155
+ #
156
+ # :remain_color - A string or color code representing the color to draw the pie not taken by the share color. Defaults to lightgrey.
157
+ def self.pie(results=[],options={})
158
+
159
+ diameter = options[:diameter].to_i
160
+ share_color = options[:share_color]
161
+ remain_color = options[:remain_color]
162
+ percent = results[0]
163
+
164
+ img = Magick::Image.new(diameter , diameter) {self.background_color = options[:background_color]}
165
+ img.format = "PNG"
166
+ draw = Magick::Draw.new
167
+
168
+ #Adjust the radius so there's some edge left n the pie
169
+ r = diameter/2.0 - 2
170
+ draw.fill(remain_color)
171
+ draw.ellipse(r + 2, r + 2, r , r , 0, 360)
172
+ draw.fill(share_color)
173
+
174
+ #Okay, this part is as confusing as hell, so pay attention:
175
+ #This line determines the horizontal portion of the point on the circle where the X-Axis
176
+ #should end. It's caculated by taking the center of the on-image circle and adding that
177
+ #to the radius multiplied by the formula for determinig the point on a unit circle that a
178
+ #angle corresponds to. 3.6 * percent gives us that angle, but it's in degrees, so we need to
179
+ #convert, hence the muliplication by Pi over 180
180
+ arc_end_x = r + 2 + (r * Math.cos((3.6 * percent)*(Math::PI/180)))
181
+
182
+ #The same goes for here, except it's the vertical point instead of the horizontal one
183
+ arc_end_y = r + 2 + (r * Math.sin((3.6 * percent)*(Math::PI/180)))
184
+
185
+ #Because the SVG path format is seriously screwy, we need to set the large-arc-flag to 1
186
+ #if the angle of an arc is greater than 180 degrees. I have no idea why this is, but it is.
187
+ percent > 50? large_arc_flag = 1: large_arc_flag = 0
188
+
189
+ #This is also confusing
190
+ #M tells us to move to an absolute point on the image. We're moving to the center of the pie
191
+ #h tells us to move to a relative point. We're moving to the right edge of the circle.
192
+ #A tells us to start an absolute elliptical arc. The first two values are the radii of the ellipse
193
+ #the third value is the x-axis-rotation (how to rotate the ellipse if we wanted to [could have some fun
194
+ #with randomizing that maybe), the fourth value is our large-arc-flag, the fifth is the sweep-flag,
195
+ #(again, confusing), the sixth and seventh values are the end point of the arc which we calculated previously
196
+ #More info on the SVG path string format at: http://www.w3.org/TR/SVG/paths.html
197
+ path = "M#{r + 2},#{r + 2} h#{r} A#{r},#{r} 0 #{large_arc_flag},1 #{arc_end_x},#{arc_end_y} z"
198
+ draw.path(path)
199
+
200
+ draw.draw(img)
201
+ img.to_blob
202
+ end
203
+
204
+ # Creates a discretized sparkline
205
+ #
206
+ # * results is an array of integer values between 0 and 100 inclusive
207
+ #
208
+ # * options is a hash that takes 4 parameters:
209
+ #
210
+ # :height - An integer that determines what the height of the sparkline will be. Defaults to 14
211
+ #
212
+ # :upper - An integer that determines the threshold for colorization purposes. Any value less than upper will be colored using below_color, anything above and equal to upper will use above_color. Defaults to 50.
213
+ #
214
+ # :above_color - A string or color code representing the color to draw values above or equal the upper value. Defaults to red.
215
+ #
216
+ # :below_color - A string or color code representing the color to draw values below the upper value. Defaults to gray.
217
+ def self.discrete(results=[], options = {})
218
+
219
+ height = options[:height].to_i
220
+ upper = options[:upper].to_i
221
+ below_color = options[:below_color]
222
+ above_color = options[:above_color]
223
+
224
+ img = Magick::Image.new(results.size * 2 - 1, height) {self.background_color = options[:background_color]}
225
+ img.format = "PNG"
226
+ draw = Magick::Draw.new
227
+
228
+ i=0
229
+ results.each do |r|
230
+ color = (r >= upper) && above_color || below_color
231
+ draw.stroke(color)
232
+ draw.line(i, (img.rows - r/(101.0/(height-4))-4).to_i,i,(img.rows - r/(101.0/(height-4))).to_i)
233
+ i+=2
234
+ end
235
+
236
+ draw.draw(img)
237
+ img.to_blob
238
+ end
239
+
240
+ # Creates a continuous area sparkline
241
+ #
242
+ # * results is an array of integer values between 0 and 100 inclusive
243
+ #
244
+ # * options is a hash that takes 4 parameters:
245
+ #
246
+ # :step - An integer that determines the distance between each point on the sparkline. Defaults to 2.
247
+ #
248
+ # :height - An integer that determines what the height of the sparkline will be. Defaults to 14
249
+ #
250
+ # :upper - An ineger that determines the threshold for colorization purposes. Any value less than upper will be colored using below_color, anything above and equal to upper will use above_color. Defaults to 50.
251
+ #
252
+ # :has_min - Determines whether a dot will be drawn at the lowest value or not. Defaulst to false.
253
+ #
254
+ # :has_max - Determines whether a dot will be drawn at the highest value or not. Defaulst to false.
255
+ #
256
+ # :has_last - Determines whether a dot will be drawn at the last value or not. Defaulst to false.
257
+ #
258
+ # :min_color - A string or color code representing the color that the dot drawn at the smallest value will be displayed as. Defaults to blue.
259
+ #
260
+ # :max_color - A string or color code representing the color that the dot drawn at the largest value will be displayed as. Defaults to green.
261
+ #
262
+ # :last_color - A string or color code representing the color that the dot drawn at the last value will be displayed as. Defaults to red.
263
+ #
264
+ # :above_color - A string or color code representing the color to draw values above or equal the upper value. Defaults to red.
265
+ #
266
+ # :below_color - A string or color code representing the color to draw values below the upper value. Defaults to gray.
267
+ def self.area(results=[], options={})
268
+
269
+ step = options[:step].to_i
270
+ height = options[:height].to_i
271
+ upper = options[:upper].to_i
272
+
273
+ has_min = options[:has_min]
274
+ has_max = options[:has_max]
275
+ has_last = options[:has_last]
276
+
277
+ min_color = options[:min_color]
278
+ max_color = options[:max_color]
279
+ last_color = options[:last_color]
280
+ below_color = options[:below_color]
281
+ above_color = options[:above_color]
282
+
283
+ img = Magick::Image.new((results.size - 1) * step + 4, height) {self.background_color = options[:background_color]}
284
+ img.format = "PNG"
285
+ draw = Magick::Draw.new
286
+
287
+ coords = [[0,(height - 3 - upper/(101.0/(height-4)))]]
288
+ i=0
289
+ results.each do |r|
290
+ coords.push [(2 + i), (height - 3 - r/(101.0/(height-4)))]
291
+ i += step
292
+ end
293
+ coords.push [(results.size - 1) * step + 4, (height - 3 - upper/(101.0/(height-4)))]
294
+
295
+ #Block off the bottom half of the image and draw the sparkline
296
+ draw.fill(above_color)
297
+ draw.define_clip_path('top') do
298
+ draw.rectangle(0,0,(results.size - 1) * step + 4,(height - 3 - upper/(101.0/(height-4))))
299
+ end
300
+ draw.clip_path('top')
301
+ draw.polygon *coords.flatten
302
+
303
+ #Block off the top half of the image and draw the sparkline
304
+ draw.fill(below_color)
305
+ draw.define_clip_path('bottom') do
306
+ draw.rectangle(0,(height - 3 - upper/(101.0/(height-4))),(results.size - 1) * step + 4,height)
307
+ end
308
+ draw.clip_path('bottom')
309
+ draw.polygon *coords.flatten
310
+
311
+ #The sparkline looks kinda nasty if either the above_color or below_color gets the center line
312
+ draw.fill('black')
313
+ draw.line(0,(height - 3 - upper/(101.0/(height-4))),(results.size - 1) * step + 4,(height - 3 - upper/(101.0/(height-4))))
314
+
315
+ #After the parts have been masked, we need to let the whole canvas be drawable again
316
+ #so a max dot can be displayed
317
+ draw.define_clip_path('all') do
318
+ draw.rectangle(0,0,img.columns,img.rows)
319
+ end
320
+ draw.clip_path('all')
321
+ if has_min == 'true'
322
+ min_pt = coords[results.index(results.min)+1]
323
+ draw.fill(min_color)
324
+ draw.rectangle(min_pt[0]-1, min_pt[1]-1, min_pt[0]+1, min_pt[1]+1)
325
+ end
326
+ if has_max == 'true'
327
+ max_pt = coords[results.index(results.max)+1]
328
+ draw.fill(max_color)
329
+ draw.rectangle(max_pt[0]-1, max_pt[1]-1, max_pt[0]+1, max_pt[1]+1)
330
+ end
331
+ if has_last == 'true'
332
+ last_pt = coords[-2]
333
+ draw.fill(last_color)
334
+ draw.rectangle(last_pt[0]-1, last_pt[1]-1, last_pt[0]+1, last_pt[1]+1)
335
+ end
336
+
337
+ draw.draw(img)
338
+ img.to_blob
339
+ end
340
+
341
+ # Creates a smooth sparkline
342
+ #
343
+ # * results - an array of integer values between 0 and 100 inclusive
344
+ #
345
+ # * options - a hash that takes these optional parameters:
346
+ #
347
+ # :step - An integer that determines the distance between each point on the sparkline. Defaults to 2.
348
+ #
349
+ # :height - An integer that determines what the height of the sparkline will be. Defaults to 14
350
+ #
351
+ # :has_min - Determines whether a dot will be drawn at the lowest value or not. Defaulst to false.
352
+ #
353
+ # :has_max - Determines whether a dot will be drawn at the highest value or not. Defaulst to false.
354
+ #
355
+ # :has_last - Determines whether a dot will be drawn at the last value or not. Defaulst to false.
356
+ #
357
+ # :min_color - A string or color code representing the color that the dot drawn at the smallest value will be displayed as. Defaults to blue.
358
+ #
359
+ # :max_color - A string or color code representing the color that the dot drawn at the largest value will be displayed as. Defaults to green.
360
+ #
361
+ # :last_color - A string or color code representing the color that the dot drawn at the last value will be displayed as. Defaults to red.
362
+ def self.smooth(results, options)
363
+
364
+ step = options[:step].to_i
365
+ height = options[:height].to_i
366
+ min_color = options[:min_color]
367
+ max_color = options[:max_color]
368
+ last_color = options[:last_color]
369
+ has_min = options[:has_min]
370
+ has_max = options[:has_max]
371
+ has_last = options[:has_last]
372
+ line_color = options[:line_color]
373
+
374
+ img = Magick::Image.new((results.size - 1) * step + 4, height.to_i) {self.background_color = options[:background_color]}
375
+ img.format = "PNG"
376
+ draw = Magick::Draw.new
377
+
378
+ draw.stroke(line_color)
379
+ coords = []
380
+ i=0
381
+ results.each do |r|
382
+ coords.push [ 2 + i, (height - 3 - r/(101.0/(height-4))) ]
383
+ i += step
384
+ end
385
+
386
+ my_polyline(draw, coords)
387
+
388
+ if has_min == true
389
+ min_pt = coords[results.index(results.min)]
390
+ draw.fill(min_color)
391
+ draw.rectangle(min_pt[0]-2, min_pt[1]-2, min_pt[0]+2, min_pt[1]+2)
392
+ end
393
+ if has_max == true
394
+ max_pt = coords[results.index(results.max)]
395
+ draw.fill(max_color)
396
+ draw.rectangle(max_pt[0]-2, max_pt[1]-2, max_pt[0]+2, max_pt[1]+2)
397
+ end
398
+ if has_last == true
399
+ last_pt = coords[-1]
400
+ draw.fill(last_color)
401
+ draw.rectangle(last_pt[0]-2, last_pt[1]-2, last_pt[0]+2, last_pt[1]+2)
402
+ end
403
+
404
+ draw.draw(img)
405
+ img.to_blob
406
+ end
407
+
408
+
409
+ # This is a function to replace the RMagick polyline function because it doesn't seem to work properly.
410
+ #
411
+ # * draw - a RMagick::Draw object.
412
+ #
413
+ # * arr - an array of points (represented as two element arrays)
414
+ def self.my_polyline (draw, arr)
415
+ i = 0
416
+ while i < arr.size - 1
417
+ draw.line(arr[i][0], arr[i][1], arr[i+1][0], arr[i+1][1])
418
+ i += 1
419
+ end
420
+ end
421
+
422
+ # Draw the error Sparkline. Not implemented yet.
423
+ def self.plot_error(options={})
424
+ img = Magick::Image.new(40,15) {self.background_color = options[:background_color]}
425
+ img.format = "PNG"
426
+ draw = Magick::Draw.new
427
+ draw.fill('red')
428
+ draw.line(0,0,40,15)
429
+ draw.line(0,15,40,0)
430
+ draw.draw(img)
431
+
432
+ img.to_blob
433
+ end
434
+
435
+ end