spontaneous 0.2.0.alpha2 → 0.2.0.alpha3

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 (404) hide show
  1. data/Gemfile +3 -40
  2. data/Rakefile +29 -41
  3. data/Readme.markdown +21 -8
  4. data/application/css/add_alias_dialogue.css.scss +79 -0
  5. data/application/css/{v2.scss → core.css.scss} +537 -550
  6. data/application/css/{definitions.scss → definitions.css.scss} +121 -33
  7. data/application/css/dialogue.css.scss +409 -0
  8. data/application/css/{editing.scss → editing.css.scss} +25 -262
  9. data/application/css/font.css.scss +8 -0
  10. data/application/css/jquery-ui-1.8.21.custom/images/ui-bg_diagonals-thick_18_b81900_40x40.png +0 -0
  11. data/application/css/jquery-ui-1.8.21.custom/images/ui-bg_diagonals-thick_20_666666_40x40.png +0 -0
  12. data/application/css/jquery-ui-1.8.21.custom/images/ui-bg_flat_10_000000_40x100.png +0 -0
  13. data/application/css/jquery-ui-1.8.21.custom/images/ui-bg_glass_100_f6f6f6_1x400.png +0 -0
  14. data/application/css/jquery-ui-1.8.21.custom/images/ui-bg_glass_100_fdf5ce_1x400.png +0 -0
  15. data/application/css/jquery-ui-1.8.21.custom/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  16. data/application/css/jquery-ui-1.8.21.custom/images/ui-bg_gloss-wave_35_f6a828_500x100.png +0 -0
  17. data/application/css/jquery-ui-1.8.21.custom/images/ui-bg_highlight-soft_100_eeeeee_1x100.png +0 -0
  18. data/application/css/jquery-ui-1.8.21.custom/images/ui-bg_highlight-soft_75_ffe45c_1x100.png +0 -0
  19. data/application/css/jquery-ui-1.8.21.custom/images/ui-icons_222222_256x240.png +0 -0
  20. data/application/css/jquery-ui-1.8.21.custom/images/ui-icons_228ef1_256x240.png +0 -0
  21. data/application/css/jquery-ui-1.8.21.custom/images/ui-icons_ef8c08_256x240.png +0 -0
  22. data/application/css/jquery-ui-1.8.21.custom/images/ui-icons_ffd27a_256x240.png +0 -0
  23. data/application/css/jquery-ui-1.8.21.custom/images/ui-icons_ffffff_256x240.png +0 -0
  24. data/application/css/jquery-ui-1.8.21.custom/ui-lightness.css.scss +565 -0
  25. data/application/css/{login.scss → login.css.scss} +4 -4
  26. data/application/css/meta.css.scss +331 -0
  27. data/application/css/{popover.scss → popover.css.scss} +9 -8
  28. data/application/css/{schema_error.scss → schema_error.css.scss} +4 -4
  29. data/application/css/spontaneous.css +5 -0
  30. data/application/css/unsupported.css.scss +42 -0
  31. data/application/js/add_alias_dialogue.js +72 -10
  32. data/application/js/ajax.js +50 -16
  33. data/application/js/compatibility.js +19 -15
  34. data/application/js/content.js +39 -36
  35. data/application/js/content_area.js +53 -5
  36. data/application/js/dialogue.js +17 -0
  37. data/application/js/dom.js +1 -1
  38. data/application/js/edit_panel.js +23 -8
  39. data/application/js/extensions.js +7 -2
  40. data/application/js/field_preview.js +2 -1
  41. data/application/js/field_types/date_field.js +11 -8
  42. data/application/js/field_types/file_field.js +188 -9
  43. data/application/js/field_types/image_field.js +46 -29
  44. data/application/js/field_types/markdown_field.js +57 -14
  45. data/application/js/field_types/select_field.js +72 -0
  46. data/application/js/field_types/string_field.js +8 -0
  47. data/application/js/field_types/webvideo_field.js +8 -0
  48. data/application/js/init.js +1 -7
  49. data/application/js/location.js +41 -13
  50. data/application/js/login.js +3 -0
  51. data/application/js/meta_view/user_admin.js +543 -0
  52. data/application/js/meta_view.js +1 -0
  53. data/application/js/metadata.js +20 -0
  54. data/application/js/page.js +17 -3
  55. data/application/js/page_browser.js +40 -30
  56. data/application/js/page_entry.js +4 -0
  57. data/application/js/panel/root_menu.js +66 -0
  58. data/application/js/popover.js +2 -2
  59. data/application/js/preview.js +1 -1
  60. data/application/js/publish.js +138 -30
  61. data/application/js/services.js +43 -0
  62. data/application/js/sharded_upload.js +2 -2
  63. data/application/js/spontaneous.js +64 -5
  64. data/application/js/state.js +20 -9
  65. data/application/js/top_bar.js +273 -150
  66. data/application/js/types.js +20 -15
  67. data/application/js/upload.js +1 -2
  68. data/application/js/user.js +18 -4
  69. data/application/js/vendor/date.js +104 -0
  70. data/application/js/vendor/jquery-ui-1.8.18.custom.min.js +356 -0
  71. data/application/js/views/box_view.js +15 -8
  72. data/application/js/views/page_piece_view.js +11 -8
  73. data/application/js/views/page_view.js +21 -3
  74. data/application/js/views/piece_view.js +19 -10
  75. data/application/js/views.js +3 -0
  76. data/application/static/chromelogo-200x52-45c7cbc93be080bea342df5fcda2ef8b.png +0 -0
  77. data/application/static/dot-texture-9eea29e4ac7ad9a772285252078ec127.png +0 -0
  78. data/application/static/editing-textarea-resize-s-b5af62365eb7e19ea4beccf7242d508e.png +0 -0
  79. data/application/static/editing-texture-1-42b06a3439752490988f30f2a06d5e7c.png +0 -0
  80. data/application/static/font/fontawesome-webfont-5c5c21100a346972a82c34c5e96ffcfe.ttf +0 -0
  81. data/application/static/loop_alt1-white-7894b458528e92216196cae26b4c2c96.svg +12 -0
  82. data/application/static/spontaneous-states-e91ec89db525c62da0105b97cdd781ce.png +0 -0
  83. data/application/views/index.erb +2 -2
  84. data/application/views/login.erb +4 -8
  85. data/application/views/schema_modification_error.html.erb +1 -4
  86. data/application/views/unsupported.erb +9 -7
  87. data/bin/spot +1 -1
  88. data/db/migrations/20110209152710_users_and_groups.rb +10 -10
  89. data/db/migrations/20120305112647_site_modification_time.rb +11 -0
  90. data/db/migrations/20120418153903_add_ownership_of_content.rb +14 -0
  91. data/db/migrations/20120423175416_add_pending_modifications.rb +21 -0
  92. data/db/migrations/20120525164947_add_field_versions.rb +27 -0
  93. data/lib/sequel/plugins/scoped_table_name.rb +10 -1
  94. data/lib/spontaneous/asset/file.rb +25 -0
  95. data/lib/spontaneous/asset/source.rb +28 -0
  96. data/lib/spontaneous/asset.rb +75 -0
  97. data/lib/spontaneous/box.rb +6 -4
  98. data/lib/spontaneous/capistrano/deploy.rb +47 -0
  99. data/lib/spontaneous/capistrano/sync.rb +81 -0
  100. data/lib/spontaneous/capistrano.rb +13 -0
  101. data/lib/spontaneous/change.rb +60 -68
  102. data/lib/spontaneous/cli/assets.rb +29 -0
  103. data/lib/spontaneous/cli/base.rb +0 -48
  104. data/lib/spontaneous/cli/console.rb +1 -1
  105. data/lib/spontaneous/cli/server.rb +6 -4
  106. data/lib/spontaneous/cli/site.rb +28 -17
  107. data/lib/spontaneous/cli/user.rb +107 -0
  108. data/lib/spontaneous/cli.rb +100 -4
  109. data/lib/spontaneous/collections/entry_set.rb +2 -2
  110. data/lib/spontaneous/collections/field_set.rb +48 -22
  111. data/lib/spontaneous/collections/prototype_set.rb +20 -13
  112. data/lib/spontaneous/constants.rb +3 -0
  113. data/lib/spontaneous/content.rb +22 -5
  114. data/lib/spontaneous/errors.rb +3 -3
  115. data/lib/spontaneous/extensions/array.rb +12 -0
  116. data/lib/spontaneous/extensions/enumerable.rb +30 -0
  117. data/lib/spontaneous/extensions/nil.rb +3 -1
  118. data/lib/spontaneous/extensions/string.rb +16 -0
  119. data/lib/spontaneous/field_types/date_field.rb +45 -2
  120. data/lib/spontaneous/field_types/field.rb +42 -9
  121. data/lib/spontaneous/field_types/file_field.rb +68 -0
  122. data/lib/spontaneous/field_types/image_field.rb +63 -0
  123. data/lib/spontaneous/field_types/select_field.rb +109 -0
  124. data/lib/spontaneous/field_types/string_field.rb +6 -1
  125. data/lib/spontaneous/field_types/webvideo_field.rb +85 -27
  126. data/lib/spontaneous/field_types.rb +1 -1
  127. data/lib/spontaneous/field_version.rb +8 -0
  128. data/lib/spontaneous/generators/page.rb +1 -1
  129. data/lib/spontaneous/generators/site/Capfile.tt +1 -4
  130. data/lib/spontaneous/generators/site/Gemfile.tt +13 -6
  131. data/lib/spontaneous/generators/site/config/deploy.rb.tt +28 -0
  132. data/lib/spontaneous/generators/site/config/environments/production.rb.tt +7 -2
  133. data/lib/spontaneous/generators/site.rb +1 -0
  134. data/lib/spontaneous/json.rb +34 -11
  135. data/lib/spontaneous/layout.rb +22 -0
  136. data/lib/spontaneous/media/file.rb +4 -0
  137. data/lib/spontaneous/output/assets/compression.rb +58 -0
  138. data/lib/spontaneous/output/assets.rb +32 -0
  139. data/lib/spontaneous/output/context.rb +179 -0
  140. data/lib/spontaneous/output/format/html.rb +5 -0
  141. data/lib/spontaneous/output/format/plain.rb +5 -0
  142. data/lib/spontaneous/output/format.rb +180 -0
  143. data/lib/spontaneous/output/helpers/classes_helper.rb +18 -0
  144. data/lib/spontaneous/{render/helpers/html_helper.rb → output/helpers/conditional_comment_helper.rb} +3 -12
  145. data/lib/spontaneous/output/helpers/script_helper.rb +73 -0
  146. data/lib/spontaneous/output/helpers/stylesheet_helper.rb +61 -0
  147. data/lib/spontaneous/output/helpers.rb +28 -0
  148. data/lib/spontaneous/output/template/engine.rb +59 -0
  149. data/lib/spontaneous/output/template/renderer.rb +153 -0
  150. data/lib/spontaneous/output/template.rb +21 -0
  151. data/lib/spontaneous/output.rb +163 -0
  152. data/lib/spontaneous/page.rb +2 -1
  153. data/lib/spontaneous/paths.rb +6 -1
  154. data/lib/spontaneous/permissions/access_key.rb +5 -5
  155. data/lib/spontaneous/permissions/user.rb +81 -35
  156. data/lib/spontaneous/permissions/user_level.rb +26 -22
  157. data/lib/spontaneous/plugins/aliases.rb +76 -12
  158. data/lib/spontaneous/plugins/allowed_types.rb +60 -18
  159. data/lib/spontaneous/plugins/application/paths.rb +0 -28
  160. data/lib/spontaneous/plugins/application/system.rb +35 -0
  161. data/lib/spontaneous/plugins/boxes.rb +4 -0
  162. data/lib/spontaneous/plugins/content_groups.rb +16 -0
  163. data/lib/spontaneous/plugins/entries.rb +50 -30
  164. data/lib/spontaneous/plugins/fields.rb +15 -0
  165. data/lib/spontaneous/plugins/layouts.rb +8 -2
  166. data/lib/spontaneous/plugins/modifications.rb +228 -0
  167. data/lib/spontaneous/plugins/page/formats.rb +67 -42
  168. data/lib/spontaneous/plugins/page/request.rb +10 -0
  169. data/lib/spontaneous/plugins/page/site_timestamps.rb +28 -0
  170. data/lib/spontaneous/plugins/paths.rb +15 -3
  171. data/lib/spontaneous/plugins/publishing.rb +124 -45
  172. data/lib/spontaneous/plugins/render.rb +13 -8
  173. data/lib/spontaneous/plugins/schema_hierarchy.rb +18 -6
  174. data/lib/spontaneous/plugins/site/helpers.rb +53 -0
  175. data/lib/spontaneous/plugins/site/hooks.rb +50 -0
  176. data/lib/spontaneous/plugins/site/map.rb +1 -1
  177. data/lib/spontaneous/plugins/site/paths.rb +13 -0
  178. data/lib/spontaneous/plugins/site/publishing.rb +6 -2
  179. data/lib/spontaneous/plugins/site/{revisions.rb → state.rb} +5 -1
  180. data/lib/spontaneous/plugins/site/storage.rb +4 -0
  181. data/lib/spontaneous/plugins/site/url.rb +15 -0
  182. data/lib/spontaneous/plugins/site_map.rb +13 -3
  183. data/lib/spontaneous/plugins/styles.rb +5 -1
  184. data/lib/spontaneous/plugins/visibility.rb +39 -12
  185. data/lib/spontaneous/prototypes/box_prototype.rb +4 -0
  186. data/lib/spontaneous/prototypes/field_prototype.rb +15 -10
  187. data/lib/spontaneous/publishing/event_client.rb +46 -0
  188. data/lib/spontaneous/publishing/immediate.rb +81 -44
  189. data/lib/spontaneous/publishing/simultaneous.rb +23 -6
  190. data/lib/spontaneous/publishing.rb +4 -3
  191. data/lib/spontaneous/rack/around_back.rb +1 -5
  192. data/lib/spontaneous/rack/around_front.rb +4 -4
  193. data/lib/spontaneous/rack/around_preview.rb +4 -3
  194. data/lib/spontaneous/rack/assets.rb +81 -54
  195. data/lib/spontaneous/rack/authentication.rb +0 -1
  196. data/lib/spontaneous/rack/back.rb +160 -72
  197. data/lib/spontaneous/rack/cookie_authentication.rb +2 -2
  198. data/lib/spontaneous/rack/css.rb +18 -15
  199. data/lib/spontaneous/rack/event_source.rb +9 -21
  200. data/lib/spontaneous/rack/fiber_pool.rb +26 -0
  201. data/lib/spontaneous/rack/front.rb +12 -4
  202. data/lib/spontaneous/rack/helpers.rb +35 -13
  203. data/lib/spontaneous/rack/js.rb +41 -0
  204. data/lib/spontaneous/rack/public.rb +34 -44
  205. data/lib/spontaneous/rack/sse.rb +18 -0
  206. data/lib/spontaneous/rack/static.rb +3 -0
  207. data/lib/spontaneous/rack/user_admin.rb +100 -0
  208. data/lib/spontaneous/rack/user_helpers.rb +1 -1
  209. data/lib/spontaneous/rack.rb +6 -2
  210. data/lib/spontaneous/schema.rb +31 -4
  211. data/lib/spontaneous/search/index.rb +19 -3
  212. data/lib/spontaneous/search/results.rb +1 -1
  213. data/lib/spontaneous/sequel.rb +17 -0
  214. data/lib/spontaneous/site.rb +11 -4
  215. data/lib/spontaneous/state.rb +11 -0
  216. data/lib/spontaneous/storage/cloud.rb +4 -0
  217. data/lib/spontaneous/storage/local.rb +11 -0
  218. data/lib/spontaneous/style.rb +2 -2
  219. data/lib/spontaneous/tasks/database.rake +21 -22
  220. data/lib/spontaneous/utils/database/mysql_dumper.rb +4 -0
  221. data/lib/spontaneous/utils/database/postgres_dumper.rb +78 -0
  222. data/lib/spontaneous/utils/database.rb +6 -3
  223. data/lib/spontaneous/utils/smart_quotes.rb +499 -0
  224. data/lib/spontaneous/utils/smush_it.rb +66 -0
  225. data/lib/spontaneous/utils.rb +3 -1
  226. data/lib/spontaneous/version.rb +2 -2
  227. data/lib/spontaneous.rb +25 -29
  228. data/spontaneous.gemspec +186 -106
  229. data/test/experimental/test_features.rb +1 -1
  230. data/test/fixtures/asset_pipeline/application/css/basic.css.scss +4 -0
  231. data/test/fixtures/asset_pipeline/application/css/complex.css.scss.erb +6 -0
  232. data/test/fixtures/asset_pipeline/application/css/simple.css +3 -0
  233. data/test/fixtures/asset_pipeline/application/css/spontaneous.css +7 -0
  234. data/test/fixtures/asset_pipeline/application/css/subdir/complex.css.scss.erb +6 -0
  235. data/test/fixtures/asset_pipeline/application/css/subdir/library.css.scss +1 -0
  236. data/test/fixtures/asset_pipeline/application/css/subdir/simple.css +3 -0
  237. data/test/fixtures/asset_pipeline/application/js/basic.js.coffee +1 -0
  238. data/test/fixtures/asset_pipeline/application/js/complex.js.coffee.erb +1 -0
  239. data/test/fixtures/asset_pipeline/application/js/login.js +1 -0
  240. data/test/fixtures/asset_pipeline/application/js/require.js +1 -0
  241. data/test/fixtures/asset_pipeline/application/js/simple.js +1 -0
  242. data/test/fixtures/asset_pipeline/application/js/spontaneous.js +5 -0
  243. data/test/fixtures/asset_pipeline/application/js/subdir/complex.js.coffee.erb +1 -0
  244. data/test/fixtures/asset_pipeline/application/js/subdir/library.js.coffee +1 -0
  245. data/test/fixtures/asset_pipeline/application/js/subdir/simple.js +1 -0
  246. data/test/fixtures/asset_pipeline/application/js/vendor/jquery.js +1 -0
  247. data/test/fixtures/asset_pipeline/application/static/dot-texture.png +0 -0
  248. data/test/fixtures/asset_pipeline/application/static/subdir/px.gif +0 -0
  249. data/test/fixtures/assets/public1/css/a.scss +1 -0
  250. data/test/fixtures/assets/public1/js/a.js +1 -0
  251. data/test/fixtures/assets/public1/js/m.coffee +1 -0
  252. data/test/fixtures/assets/public2/css/b.scss +1 -0
  253. data/test/fixtures/assets/public2/css/c.css +1 -0
  254. data/test/fixtures/assets/public2/js/b.js +1 -0
  255. data/test/fixtures/assets/public2/js/c.js +1 -0
  256. data/test/fixtures/assets/public2/js/n.coffee +1 -0
  257. data/test/fixtures/back/config/user_levels.yml +3 -0
  258. data/test/fixtures/back/public/js/coffeescript.coffee +1 -0
  259. data/test/fixtures/back/templates/layouts/standard.css.cut +1 -0
  260. data/test/fixtures/back/templates/layouts/standard.js.cut +1 -0
  261. data/test/fixtures/example_application/config/database.yml +4 -4
  262. data/test/fixtures/helpers/templates/layouts/standard.html.cut +1 -0
  263. data/test/fixtures/helpers/templates/layouts/standard.mobile.cut +1 -0
  264. data/test/fixtures/images/vimlogo.pdf +0 -0
  265. data/test/fixtures/outputs/templates/layouts/standard.atom.cut +1 -0
  266. data/test/fixtures/permissions/config/user_levels.yml +6 -3
  267. data/test/fixtures/serialisation/class_hash.yaml.erb +1 -0
  268. data/test/fixtures/serialisation/root_hash.yaml.erb +2 -2
  269. data/test/fixtures/templates/extended/grandparent.html.cut +7 -7
  270. data/test/fixtures/templates/extended/main.html.cut +5 -5
  271. data/test/fixtures/templates/extended/parent.html.cut +8 -8
  272. data/test/fixtures/templates/extended/partial_with_locals.html.cut +1 -1
  273. data/test/fixtures/templates/extended/with_includes.html.cut +6 -6
  274. data/test/fixtures/templates/extended/with_includes_and_locals.html.cut +6 -7
  275. data/test/fixtures/templates/layouts/entries.html.cut +4 -4
  276. data/test/fixtures/templates/layouts/standard.html.cut +1 -0
  277. data/test/fixtures/templates/layouts/variables.html.cut +1 -1
  278. data/test/fixtures/templates/publishing/templates/layouts/static.html.cut +1 -1
  279. data/test/fixtures/templates/publishing/templates/layouts/static.rtf.cut +1 -0
  280. data/test/fixtures/templates/template_class/complex_template.html.cut +2 -2
  281. data/test/fixtures/templates/template_class/complex_template.pdf.cut +2 -2
  282. data/test/fixtures/templates/template_class/default_template_style.html.cut +1 -1
  283. data/test/fixtures/templates/template_class/images_with_template.html.cut +2 -2
  284. data/test/fixtures/templates/template_class/slots_template.html.cut +2 -2
  285. data/test/fixtures/templates/template_class/slots_template.pdf.cut +2 -2
  286. data/test/fixtures/user_manager/config/user_levels.yml +9 -0
  287. data/test/functional/test_application.rb +7 -7
  288. data/test/functional/test_back.rb +352 -97
  289. data/test/functional/test_front.rb +71 -20
  290. data/test/functional/test_user_manager.rb +284 -0
  291. data/test/javascript/env.js +13505 -0
  292. data/test/javascript/test_markdown.rb +43 -3
  293. data/test/support/custom_matchers.rb +3 -2
  294. data/test/test_helper.rb +50 -9
  295. data/test/test_javascript.rb +13 -13
  296. data/test/ui_helper.rb +1 -1
  297. data/test/unit/test_alias.rb +79 -8
  298. data/test/unit/test_asset_bundler.rb +220 -0
  299. data/test/unit/test_assets.rb +213 -0
  300. data/test/unit/test_async.rb +55 -0
  301. data/test/unit/test_authentication.rb +52 -39
  302. data/test/unit/test_boxes.rb +20 -15
  303. data/test/unit/test_changesets.rb +261 -0
  304. data/test/unit/test_content.rb +73 -33
  305. data/test/unit/test_content_inheritance.rb +18 -18
  306. data/test/unit/test_extensions.rb +26 -0
  307. data/test/unit/test_fields.rb +303 -16
  308. data/test/unit/test_formats.rb +267 -34
  309. data/test/unit/test_helpers.rb +79 -2
  310. data/test/unit/test_images.rb +10 -0
  311. data/test/unit/test_layouts.rb +21 -13
  312. data/test/unit/test_modifications.rb +648 -0
  313. data/test/unit/test_page.rb +6 -2
  314. data/test/unit/test_permissions.rb +101 -27
  315. data/test/unit/test_piece.rb +4 -4
  316. data/test/unit/test_plugins.rb +3 -2
  317. data/test/unit/test_publishing.rb +332 -0
  318. data/test/unit/test_render.rb +118 -67
  319. data/test/unit/test_revisions.rb +546 -0
  320. data/test/unit/test_schema.rb +83 -1
  321. data/test/unit/test_search.rb +59 -0
  322. data/test/unit/test_serialisation.rb +2 -47
  323. data/test/unit/test_site.rb +217 -108
  324. data/test/unit/test_storage.rb +26 -0
  325. data/test/unit/test_structure.rb +2 -2
  326. data/test/unit/test_styles.rb +90 -75
  327. data/test/unit/test_table_scoping.rb +21 -17
  328. data/test/unit/test_templates.rb +75 -69
  329. data/test/{slow → unit}/test_visibility.rb +78 -22
  330. metadata +528 -221
  331. data/application/css/add_alias_dialogue.scss +0 -27
  332. data/application/css/min/14c2a35812c443001b15d8b12a4780f88c678035.css +0 -1
  333. data/application/css/min/565d4c25e82148acb01c45c8d675b37a08676d77.css +0 -1
  334. data/application/css/min/84dbe894ea96eafd321c30823d630817bfc4b03b.css +0 -1
  335. data/application/css/spontaneous.scss +0 -111
  336. data/application/css/unsupported.scss +0 -16
  337. data/application/css/variables.scss +0 -80
  338. data/application/js/min/2a0c2962537a3181fedfff5c92596ba6d3122dc9.js +0 -3
  339. data/application/js/min/4cf1c493d3379ecba5287758c61238034c0893f9.js +0 -2
  340. data/application/js/min/78ac6b99d96750bb6b9f9aad4cb9cd91cd03f391.js +0 -3
  341. data/application/js/min/b8abf302a824c35385ff517b34111e1710ff3b37.js +0 -2
  342. data/application/js/min/c8efb9b9f7c3f6613fcebc6be60f605b6570a382.js +0 -90
  343. data/application/static/diagonal-texture.png +0 -0
  344. data/application/static/editing-0-noise.png +0 -0
  345. data/application/static/editing-1-noise.png +0 -0
  346. data/application/static/editing-texture-1.png +0 -0
  347. data/application/static/editing-texture.png +0 -0
  348. data/application/static/editing-toolbar-shadow-bottom.png +0 -0
  349. data/application/static/editing-toolbar-shadow-top.png +0 -0
  350. data/application/static/inner-glow.png +0 -0
  351. data/application/static/item-buttons-highlight.png +0 -0
  352. data/application/static/item-buttons.png +0 -0
  353. data/application/static/paper-texture-dark.png +0 -0
  354. data/application/static/plus_alt.svg +0 -8
  355. data/application/static/select-arrow-root.png +0 -0
  356. data/application/static/slot-up-arrow.png +0 -0
  357. data/application/static/spontaneous.png +0 -0
  358. data/lib/cutaneous/context_helper.rb +0 -187
  359. data/lib/cutaneous/preview_context.rb +0 -32
  360. data/lib/cutaneous/preview_renderer.rb +0 -10
  361. data/lib/cutaneous/publish_context.rb +0 -10
  362. data/lib/cutaneous/publish_renderer.rb +0 -14
  363. data/lib/cutaneous/publish_template.rb +0 -62
  364. data/lib/cutaneous/publish_token_parser.rb +0 -8
  365. data/lib/cutaneous/renderer.rb +0 -124
  366. data/lib/cutaneous/request_context.rb +0 -9
  367. data/lib/cutaneous/request_renderer.rb +0 -15
  368. data/lib/cutaneous/request_template.rb +0 -11
  369. data/lib/cutaneous/request_token_parser.rb +0 -9
  370. data/lib/cutaneous/token_parser.rb +0 -125
  371. data/lib/cutaneous.rb +0 -48
  372. data/lib/spontaneous/render/context_base.rb +0 -143
  373. data/lib/spontaneous/render/development_renderer.rb +0 -14
  374. data/lib/spontaneous/render/engine.rb +0 -19
  375. data/lib/spontaneous/render/format/html.rb +0 -5
  376. data/lib/spontaneous/render/format.rb +0 -75
  377. data/lib/spontaneous/render/helpers/script_helper.rb +0 -17
  378. data/lib/spontaneous/render/helpers/stylesheet_helper.rb +0 -16
  379. data/lib/spontaneous/render/helpers.rb +0 -14
  380. data/lib/spontaneous/render/preview_context.rb +0 -8
  381. data/lib/spontaneous/render/preview_renderer.rb +0 -24
  382. data/lib/spontaneous/render/publish_context.rb +0 -22
  383. data/lib/spontaneous/render/published_renderer.rb +0 -53
  384. data/lib/spontaneous/render/publishing_renderer.rb +0 -16
  385. data/lib/spontaneous/render/render_cache.rb +0 -26
  386. data/lib/spontaneous/render/renderer.rb +0 -50
  387. data/lib/spontaneous/render/request_context.rb +0 -8
  388. data/lib/spontaneous/render.rb +0 -214
  389. data/test/experimental/test_cutaneous.rb +0 -309
  390. data/test/fixtures/application/css/test.less +0 -5
  391. data/test/slow/test_publishing.rb +0 -1006
  392. /data/application/css/{developer.scss → developer.css.scss} +0 -0
  393. /data/application/js/vendor/{jquery-1.7.1.min.js → jquery.js} +0 -0
  394. /data/application/static/{location-arrow.png → location-arrow-c1c1d3ca472481c61a0a5f8cb289d743.png} +0 -0
  395. /data/application/static/{missing.png → missing-911ce6dbd9f4602e0f3fbcd7e78846a2.png} +0 -0
  396. /data/application/static/{orange-down-arrow.png → orange-down-arrow-395ae1929e8662b2ff0977daf12c35bb.png} +0 -0
  397. /data/application/static/{page-browser-next.png → page-browser-next-ce781a242c23b980b99b9db7abc20b05.png} +0 -0
  398. /data/application/static/{plus-box.png → plus-box-dcde74a1e496f68298c9b443caa1c5d5.png} +0 -0
  399. /data/application/static/{select-arrow.png → select-arrow-6e7dd3745b00e934b0d7a3250c46558b.png} +0 -0
  400. /data/application/static/{slot-down-arrow.png → slot-down-arrow-59ad5f5ee5b52a7ebd00bca4b3104194.png} +0 -0
  401. /data/application/static/{splash.png → splash-65b493a714df9b8b3ab170103401b53d.png} +0 -0
  402. /data/application/static/{spot.png → spot-71fab1d2f065034f5fc15e7bea2ad36c.png} +0 -0
  403. /data/application/static/{spot.svg → spot-8505041082d8d3bbe8d34c29dddb3b7d.svg} +0 -0
  404. /data/application/static/{texture.png → texture-03f7627e8264b1d607113ab32c593a58.png} +0 -0
@@ -6,31 +6,30 @@ namespace :spot do
6
6
  Sequel.extension :migration
7
7
  Sequel::Migrator.apply(Spontaneous.database, Spontaneous.gem_dir('db/migrations'))
8
8
  end
9
+ end
9
10
 
10
-
11
- namespace :database do
12
- desc "Make a dump of the current database"
13
- task :dump do
14
- dumpfilename = ENV['dumpfile']
15
- if dumpfilename.nil?
16
- dumpfilename = "#{Time.now.to_i}.mysql.gz"
17
- end
18
- dump_file = "tmp/#{dumpfilename}"
19
- dumper = Spontaneous::Utils::Database.dumper_for_database
20
- # Spontaneous::Cli::Site::MySQL.new(Spontaneous.database)
21
- dumper.dump(dump_file)
11
+ namespace :db do
12
+ desc "Make a dump of the current database"
13
+ task :dump do
14
+ dumpfilename = ENV['dumpfile']
15
+ if dumpfilename.nil?
16
+ dumpfilename = "#{Time.now.to_i}.mysql.gz"
22
17
  end
18
+ dump_file = "tmp/#{dumpfilename}"
19
+ dumper = Spontaneous::Utils::Database.dumper_for_database
20
+ # Spontaneous::Cli::Site::MySQL.new(Spontaneous.database)
21
+ dumper.dump(dump_file)
22
+ end
23
23
 
24
- desc "Load a database dump into the local database"
25
- task :load do
26
- dumpfile = ENV['dumpfile']
27
- if dumpfile.nil?
28
- $stderr.puts "Usage: rake spot:database:load dumpfile=/path/to/dump.mysql.gz"
29
- exit 1
30
- end
31
- dumper = Spontaneous::Utils::Database.dumper_for_database
32
- # dumper = Spontaneous::Cli::Site::MySQL.new(Spontaneous.database)
33
- dumper.load(dumpfile)
24
+ desc "Load a database dump into the local database"
25
+ task :load do
26
+ dumpfile = ENV['dumpfile']
27
+ if dumpfile.nil?
28
+ $stderr.puts "Usage: rake spot:database:load dumpfile=/path/to/dump.mysql.gz"
29
+ exit 1
34
30
  end
31
+ dumper = Spontaneous::Utils::Database.dumper_for_database
32
+ # dumper = Spontaneous::Cli::Site::MySQL.new(Spontaneous.database)
33
+ dumper.load(dumpfile)
35
34
  end
36
35
  end
@@ -7,6 +7,10 @@ module Spontaneous
7
7
  @database = database
8
8
  end
9
9
 
10
+ def name
11
+ "mysql"
12
+ end
13
+
10
14
  def load(path)
11
15
  system(load_command(path))
12
16
  end
@@ -0,0 +1,78 @@
1
+ module Spontaneous
2
+ module Utils
3
+ module Database
4
+ class PostgresDumper < MySQLDumper
5
+ def initialize(database)
6
+ @database = database
7
+ end
8
+
9
+ def name
10
+ "pgsql"
11
+ end
12
+
13
+ def load(path)
14
+ system(load_command(path))
15
+ end
16
+
17
+ def load_command(path)
18
+ options = [
19
+ "psql",
20
+ "--quiet",
21
+ option(:password),
22
+ option(:username),
23
+ database_name
24
+ ]
25
+ if path =~ /\.gz$/
26
+ options = ["gunzip", "<", path, "|"].concat(options)
27
+ else
28
+ options.concat [ "<", path ]
29
+ end
30
+
31
+ options.concat [ ">/dev/null" ]
32
+
33
+ command = options.join(" ")
34
+ end
35
+
36
+ def dump(path, tables = nil)
37
+ system(dump_command(path, tables))
38
+ end
39
+
40
+ def dump_command(path, tables = nil)
41
+ options = [
42
+ "--clean",
43
+ "--no-owner",
44
+ "--no-privileges",
45
+ option(:password),
46
+ option(:username),
47
+ option(:encoding),
48
+ database_name
49
+ ]
50
+ unless tables.nil?
51
+ options.push(tables.join(" "))
52
+ end
53
+
54
+ options.push( "| gzip") if path =~ /\.gz$/
55
+
56
+ command = %(pg_dump #{options.join(" ")} > #{path} )
57
+ end
58
+
59
+ def database_name
60
+ @database.opts[:database]
61
+ end
62
+
63
+ def username
64
+ @database.opts[:user]
65
+ end
66
+
67
+ def password
68
+ @database.opts[:password]
69
+ end
70
+
71
+ def encoding
72
+ "UTF8"
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
78
+
@@ -4,15 +4,18 @@ module Spontaneous
4
4
  module Database
5
5
 
6
6
  def self.dumper_for_database(database = Spontaneous.database)
7
- case database
8
- when ::Sequel::Mysql2::Database
7
+ case database.class.to_s
8
+ when "Sequel::Mysql2::Database"
9
9
  Spontaneous::Utils::Database::MySQLDumper
10
+ when "Sequel::Postgres::Database"
11
+ Spontaneous::Utils::Database::PostgresDumper
10
12
  else
11
13
  raise "Unsupported adapter #{database.class}"
12
14
  end.new(database)
13
15
  end
14
16
 
15
- autoload :MySQLDumper, 'spontaneous/utils/database/mysql_dumper'
17
+ autoload :MySQLDumper, 'spontaneous/utils/database/mysql_dumper'
18
+ autoload :PostgresDumper, 'spontaneous/utils/database/postgres_dumper'
16
19
  end
17
20
  end
18
21
  end
@@ -0,0 +1,499 @@
1
+ # encoding: UTF-8
2
+ #
3
+ # = RubyPants -- SmartyPants ported to Ruby
4
+ #
5
+ # Ported by Christian Neukirchen <mailto:chneukirchen@gmail.com>
6
+ # Copyright (C) 2004 Christian Neukirchen
7
+ #
8
+ # Incooporates ideas, comments and documentation by Chad Miller
9
+ # Copyright (C) 2004 Chad Miller
10
+ #
11
+ # Original SmartyPants by John Gruber
12
+ # Copyright (C) 2003 John Gruber
13
+ #
14
+
15
+ #
16
+ # = RubyPants -- SmartyPants ported to Ruby
17
+ #
18
+ # == Synopsis
19
+ #
20
+ # RubyPants is a Ruby port of the smart-quotes library SmartyPants.
21
+ #
22
+ # The original "SmartyPants" is a free web publishing plug-in for
23
+ # Movable Type, Blosxom, and BBEdit that easily translates plain ASCII
24
+ # punctuation characters into "smart" typographic punctuation HTML
25
+ # entities.
26
+ #
27
+ #
28
+ # == Description
29
+ #
30
+ # RubyPants can perform the following transformations:
31
+ #
32
+ # * Straight quotes (<tt>"</tt> and <tt>'</tt>) into "curly" quote
33
+ # HTML entities
34
+ # * Backticks-style quotes (<tt>``like this''</tt>) into "curly" quote
35
+ # HTML entities
36
+ # * Dashes (<tt>--</tt> and <tt>---</tt>) into en- and em-dash
37
+ # entities
38
+ # * Three consecutive dots (<tt>...</tt> or <tt>. . .</tt>) into an
39
+ # ellipsis entity
40
+ #
41
+ # This means you can write, edit, and save your posts using plain old
42
+ # ASCII straight quotes, plain dashes, and plain dots, but your
43
+ # published posts (and final HTML output) will appear with smart
44
+ # quotes, em-dashes, and proper ellipses.
45
+ #
46
+ # RubyPants does not modify characters within <tt><pre></tt>,
47
+ # <tt><code></tt>, <tt><kbd></tt>, <tt><math></tt> or
48
+ # <tt><script></tt> tag blocks. Typically, these tags are used to
49
+ # display text where smart quotes and other "smart punctuation" would
50
+ # not be appropriate, such as source code or example markup.
51
+ #
52
+ #
53
+ # == Backslash Escapes
54
+ #
55
+ # If you need to use literal straight quotes (or plain hyphens and
56
+ # periods), RubyPants accepts the following backslash escape sequences
57
+ # to force non-smart punctuation. It does so by transforming the
58
+ # escape sequence into a decimal-encoded HTML entity:
59
+ #
60
+ # \\ \" \' \. \- \`
61
+ #
62
+ # This is useful, for example, when you want to use straight quotes as
63
+ # foot and inch marks: 6'2" tall; a 17" iMac. (Use <tt>6\'2\"</tt>
64
+ # resp. <tt>17\"</tt>.)
65
+ #
66
+ #
67
+ # == Algorithmic Shortcomings
68
+ #
69
+ # One situation in which quotes will get curled the wrong way is when
70
+ # apostrophes are used at the start of leading contractions. For
71
+ # example:
72
+ #
73
+ # 'Twas the night before Christmas.
74
+ #
75
+ # In the case above, RubyPants will turn the apostrophe into an
76
+ # opening single-quote, when in fact it should be a closing one. I
77
+ # don't think this problem can be solved in the general case--every
78
+ # word processor I've tried gets this wrong as well. In such cases,
79
+ # it's best to use the proper HTML entity for closing single-quotes
80
+ # ("<tt>&#8217;</tt>") by hand.
81
+ #
82
+ #
83
+ # == Bugs
84
+ #
85
+ # To file bug reports or feature requests (except see above) please
86
+ # send email to: mailto:chneukirchen@gmail.com
87
+ #
88
+ # If the bug involves quotes being curled the wrong way, please send
89
+ # example text to illustrate.
90
+ #
91
+ #
92
+ # == Authors
93
+ #
94
+ # John Gruber did all of the hard work of writing this software in
95
+ # Perl for Movable Type and almost all of this useful documentation.
96
+ # Chad Miller ported it to Python to use with Pyblosxom.
97
+ #
98
+ # Christian Neukirchen provided the Ruby port, as a general-purpose
99
+ # library that follows the *Cloth API.
100
+ #
101
+ #
102
+ # == Copyright and License
103
+ #
104
+ # === SmartyPants license:
105
+ #
106
+ # Copyright (c) 2003 John Gruber
107
+ # (http://daringfireball.net)
108
+ # All rights reserved.
109
+ #
110
+ # Redistribution and use in source and binary forms, with or without
111
+ # modification, are permitted provided that the following conditions
112
+ # are met:
113
+ #
114
+ # * Redistributions of source code must retain the above copyright
115
+ # notice, this list of conditions and the following disclaimer.
116
+ #
117
+ # * Redistributions in binary form must reproduce the above copyright
118
+ # notice, this list of conditions and the following disclaimer in
119
+ # the documentation and/or other materials provided with the
120
+ # distribution.
121
+ #
122
+ # * Neither the name "SmartyPants" nor the names of its contributors
123
+ # may be used to endorse or promote products derived from this
124
+ # software without specific prior written permission.
125
+ #
126
+ # This software is provided by the copyright holders and contributors
127
+ # "as is" and any express or implied warranties, including, but not
128
+ # limited to, the implied warranties of merchantability and fitness
129
+ # for a particular purpose are disclaimed. In no event shall the
130
+ # copyright owner or contributors be liable for any direct, indirect,
131
+ # incidental, special, exemplary, or consequential damages (including,
132
+ # but not limited to, procurement of substitute goods or services;
133
+ # loss of use, data, or profits; or business interruption) however
134
+ # caused and on any theory of liability, whether in contract, strict
135
+ # liability, or tort (including negligence or otherwise) arising in
136
+ # any way out of the use of this software, even if advised of the
137
+ # possibility of such damage.
138
+ #
139
+ # === RubyPants license
140
+ #
141
+ # RubyPants is a derivative work of SmartyPants and smartypants.py.
142
+ #
143
+ # Redistribution and use in source and binary forms, with or without
144
+ # modification, are permitted provided that the following conditions
145
+ # are met:
146
+ #
147
+ # * Redistributions of source code must retain the above copyright
148
+ # notice, this list of conditions and the following disclaimer.
149
+ #
150
+ # * Redistributions in binary form must reproduce the above copyright
151
+ # notice, this list of conditions and the following disclaimer in
152
+ # the documentation and/or other materials provided with the
153
+ # distribution.
154
+ #
155
+ # This software is provided by the copyright holders and contributors
156
+ # "as is" and any express or implied warranties, including, but not
157
+ # limited to, the implied warranties of merchantability and fitness
158
+ # for a particular purpose are disclaimed. In no event shall the
159
+ # copyright owner or contributors be liable for any direct, indirect,
160
+ # incidental, special, exemplary, or consequential damages (including,
161
+ # but not limited to, procurement of substitute goods or services;
162
+ # loss of use, data, or profits; or business interruption) however
163
+ # caused and on any theory of liability, whether in contract, strict
164
+ # liability, or tort (including negligence or otherwise) arising in
165
+ # any way out of the use of this software, even if advised of the
166
+ # possibility of such damage.
167
+ #
168
+ #
169
+ # == Links
170
+ #
171
+ # John Gruber:: http://daringfireball.net
172
+ # SmartyPants:: http://daringfireball.net/projects/smartypants
173
+ #
174
+ # Chad Miller:: http://web.chad.org
175
+ #
176
+ # Christian Neukirchen:: http://kronavita.de/chris
177
+ #
178
+
179
+ module Spontaneous::Utils
180
+ module SmartQuotes
181
+ extend self
182
+
183
+ VERSION = "0.2"
184
+
185
+ OPEN_SGL_QUOTE = "‘"
186
+ CLOSE_SGL_QUOTE = "’"
187
+
188
+ OPEN_DBL_QUOTE = "“"
189
+ CLOSE_DBL_QUOTE = "”"
190
+
191
+ ELLIPSIS = "…"
192
+ EM_DASH = "—"
193
+ EN_DASH = "–"
194
+
195
+ # Create a new RubyPants instance with the text in +string+.
196
+ #
197
+ # Allowed elements in the options array:
198
+ #
199
+ # 0 :: do nothing
200
+ # 1 :: enable all, using only em-dash shortcuts
201
+ # 2 :: enable all, using old school en- and em-dash shortcuts (*default*)
202
+ # 3 :: enable all, using inverted old school en and em-dash shortcuts
203
+ # -1 :: stupefy (translate HTML entities to their ASCII-counterparts)
204
+ #
205
+ # If you don't like any of these defaults, you can pass symbols to change
206
+ # RubyPants' behavior:
207
+ #
208
+ # <tt>:quotes</tt> :: quotes
209
+ # <tt>:backticks</tt> :: backtick quotes (``double'' only)
210
+ # <tt>:allbackticks</tt> :: backtick quotes (``double'' and `single')
211
+ # <tt>:dashes</tt> :: dashes
212
+ # <tt>:oldschool</tt> :: old school dashes
213
+ # <tt>:inverted</tt> :: inverted old school dashes
214
+ # <tt>:ellipses</tt> :: ellipses
215
+ # <tt>:convertquotes</tt> :: convert <tt>&quot;</tt> entities to
216
+ # <tt>"</tt> for Dreamweaver users
217
+ # <tt>:stupefy</tt> :: translate RubyPants HTML entities
218
+ # to their ASCII counterparts.
219
+ #
220
+
221
+ # Apply SmartyPants transformations.
222
+ def smarten(string, options=[2])
223
+ do_quotes = do_backticks = do_dashes = do_ellipses = do_stupify = nil
224
+ convert_quotes = false
225
+
226
+ if options.include? 0
227
+ # Do nothing.
228
+ return string
229
+ elsif options.include? 1
230
+ # Do everything, turn all options on.
231
+ do_quotes = do_backticks = do_ellipses = true
232
+ do_dashes = :normal
233
+ elsif options.include? 2
234
+ # Do everything, turn all options on, use old school dash shorthand.
235
+ do_quotes = do_backticks = do_ellipses = true
236
+ do_dashes = :oldschool
237
+ elsif options.include? 3
238
+ # Do everything, turn all options on, use inverted old school
239
+ # dash shorthand.
240
+ do_quotes = do_backticks = do_ellipses = true
241
+ do_dashes = :inverted
242
+ elsif options.include?(-1)
243
+ do_stupefy = true
244
+ else
245
+ do_quotes = options.include? :quotes
246
+ do_backticks = options.include? :backticks
247
+ do_backticks = :both if options.include? :allbackticks
248
+ do_dashes = :normal if options.include? :dashes
249
+ do_dashes = :oldschool if options.include? :oldschool
250
+ do_dashes = :inverted if options.include? :inverted
251
+ do_ellipses = options.include? :ellipses
252
+ convert_quotes = options.include? :convertquotes
253
+ do_stupefy = options.include? :stupefy
254
+ end
255
+
256
+ # Parse the HTML
257
+ tokens = tokenize(string)
258
+
259
+ # Keep track of when we're inside <pre> or <code> tags.
260
+ in_pre = false
261
+
262
+ # Here is the result stored in.
263
+ result = ""
264
+
265
+ # This is a cheat, used to get some context for one-character
266
+ # tokens that consist of just a quote char. What we do is remember
267
+ # the last character of the previous text token, to use as context
268
+ # to curl single- character quote tokens correctly.
269
+ prev_token_last_char = nil
270
+
271
+ tokens.each { |token|
272
+ if token.first == :tag
273
+ result << token[1]
274
+ if token[1] =~ %r!<(/?)(?:pre|code|kbd|script|math)[\s>]!
275
+ in_pre = ($1 != "/") # Opening or closing tag?
276
+ end
277
+ else
278
+ t = token[1]
279
+
280
+ # Remember last char of this token before processing.
281
+ last_char = t[-1].chr
282
+
283
+ unless in_pre
284
+ t = process_escapes t
285
+
286
+ t.gsub!(/&quot;/, '"') if convert_quotes
287
+
288
+ if do_dashes
289
+ t = educate_dashes t if do_dashes == :normal
290
+ t = educate_dashes_oldschool t if do_dashes == :oldschool
291
+ t = educate_dashes_inverted t if do_dashes == :inverted
292
+ end
293
+
294
+ t = educate_ellipses t if do_ellipses
295
+
296
+ # Note: backticks need to be processed before quotes.
297
+ if do_backticks
298
+ t = educate_backticks t
299
+ t = educate_single_backticks t if do_backticks == :both
300
+ end
301
+
302
+ if do_quotes
303
+ if t == "'"
304
+ # Special case: single-character ' token
305
+ if prev_token_last_char =~ /\S/
306
+ t = CLOSE_SGL_QUOTE
307
+ else
308
+ t = OPEN_SGL_QUOTE
309
+ end
310
+ elsif t == '"'
311
+ # Special case: single-character " token
312
+ if prev_token_last_char =~ /\S/
313
+ t = CLOSE_DBL_QUOTE
314
+ else
315
+ t = OPEN_DBL_QUOTE
316
+ end
317
+ else
318
+ # Normal case:
319
+ t = educate_quotes t
320
+ end
321
+ end
322
+
323
+ t = stupefy_entities t if do_stupefy
324
+ end
325
+
326
+ prev_token_last_char = last_char
327
+ result << t
328
+ end
329
+ }
330
+
331
+ # Done
332
+ result
333
+ end
334
+
335
+ protected
336
+
337
+ # Return the string, with after processing the following backslash
338
+ # escape sequences. This is useful if you want to force a "dumb" quote
339
+ # or other character to appear.
340
+ #
341
+ # Escaped are:
342
+ # \\ \" \' \. \- \`
343
+ #
344
+ def process_escapes(str)
345
+ str.gsub('\\\\', '\\').
346
+ gsub('\"', '"').
347
+ gsub("\\\'", "'").
348
+ gsub('\.', '.').
349
+ gsub('\-', '-').
350
+ gsub('\`', '`')
351
+ end
352
+
353
+ # The string, with each instance of "<tt>--</tt>" translated to an
354
+ # em-dash HTML entity.
355
+ #
356
+ def educate_dashes(str)
357
+ str.gsub(/--/, EM_DASH)
358
+ end
359
+
360
+ # The string, with each instance of "<tt>--</tt>" translated to an
361
+ # en-dash HTML entity, and each "<tt>---</tt>" translated to an
362
+ # em-dash HTML entity.
363
+ #
364
+ def educate_dashes_oldschool(str)
365
+ str.gsub(/---/, EM_DASH).gsub(/--/, EN_DASH)
366
+ end
367
+
368
+ # Return the string, with each instance of "<tt>--</tt>" translated
369
+ # to an em-dash HTML entity, and each "<tt>---</tt>" translated to
370
+ # an en-dash HTML entity. Two reasons why: First, unlike the en- and
371
+ # em-dash syntax supported by +educate_dashes_oldschool+, it's
372
+ # compatible with existing entries written before SmartyPants 1.1,
373
+ # back when "<tt>--</tt>" was only used for em-dashes. Second,
374
+ # em-dashes are more common than en-dashes, and so it sort of makes
375
+ # sense that the shortcut should be shorter to type. (Thanks to
376
+ # Aaron Swartz for the idea.)
377
+ #
378
+ def educate_dashes_inverted(str)
379
+ str.gsub(/---/, EN_DASH).gsub(/--/, EM_DASH)
380
+ end
381
+
382
+ # Return the string, with each instance of "<tt>...</tt>" translated
383
+ # to an ellipsis HTML entity. Also converts the case where there are
384
+ # spaces between the dots.
385
+ #
386
+ def educate_ellipses(str)
387
+ str.gsub('...', ELLIPSIS).gsub('. . .', ELLIPSIS)
388
+ end
389
+
390
+ # Return the string, with "<tt>``backticks''</tt>"-style single quotes
391
+ # translated into HTML curly quote entities.
392
+ #
393
+ def educate_backticks(str)
394
+ str.gsub("``", OPEN_DBL_QUOTE).gsub("''", CLOSE_DBL_QUOTE)
395
+ end
396
+
397
+ # Return the string, with "<tt>`backticks'</tt>"-style single quotes
398
+ # translated into HTML curly quote entities.
399
+ #
400
+ def educate_single_backticks(str)
401
+ str.gsub("`", OPEN_SGL_QUOTE).gsub("'", CLOSE_SGL_QUOTE)
402
+ end
403
+
404
+ # Return the string, with "educated" curly quote HTML entities.
405
+ #
406
+ def educate_quotes(str)
407
+ punct_class = '[!"#\$\%\'()*+,\-.\/:;<=>?\@\[\\\\\]\^_`{|}~]'
408
+
409
+ str = str.dup
410
+
411
+ # Special case if the very first character is a quote followed by
412
+ # punctuation at a non-word-break. Close the quotes by brute
413
+ # force:
414
+ str.gsub!(/^'(?=#{punct_class}\B)/, CLOSE_SGL_QUOTE)
415
+ str.gsub!(/^"(?=#{punct_class}\B)/, CLOSE_DBL_QUOTE)
416
+
417
+ # Special case for double sets of quotes, e.g.:
418
+ # <p>He said, "'Quoted' words in a larger quote."</p>
419
+ str.gsub!(/"'(?=\w)/, "#{OPEN_DBL_QUOTE}#{OPEN_SGL_QUOTE}")
420
+ str.gsub!(/'"(?=\w)/, "#{OPEN_SGL_QUOTE}#{OPEN_DBL_QUOTE}")
421
+
422
+ # Special case for decade abbreviations (the '80s):
423
+ str.gsub!(/'(?=\d\ds)/, CLOSE_SGL_QUOTE)
424
+
425
+ close_class = %![^\ \t\r\n\\[\{\(\-]!
426
+ dec_dashes = "#{EN_DASH}|#{EM_DASH}"#'&#8211;|&#8212;'
427
+
428
+ # Get most opening single quotes:
429
+ str.gsub!(/(\s|&nbsp;|--|&[mn]dash;|#{dec_dashes}|&#x201[34];)'(?=\w)/, '\1'+OPEN_SGL_QUOTE)
430
+ # Single closing quotes:
431
+ str.gsub!(/(#{close_class})'/, '\1'+CLOSE_SGL_QUOTE)
432
+ str.gsub!(/'(\s|s\b|$)/, CLOSE_SGL_QUOTE+'\1')
433
+ # Any remaining single quotes should be opening ones:
434
+ str.gsub!(/'/, OPEN_SGL_QUOTE)
435
+
436
+ # Get most opening double quotes:
437
+ str.gsub!(/(\s|&nbsp;|--|&[mn]dash;|#{dec_dashes}|&#x201[34];)"(?=\w)/,
438
+ '\1'+OPEN_DBL_QUOTE)
439
+ # Double closing quotes:
440
+ str.gsub!(/(#{close_class})"/, '\1'+CLOSE_DBL_QUOTE)
441
+ str.gsub!(/"(\s|s\b|$)/, CLOSE_DBL_QUOTE+'\1')
442
+ # Any remaining quotes should be opening ones:
443
+ str.gsub!(/"/, OPEN_DBL_QUOTE)
444
+
445
+ str
446
+ end
447
+
448
+ # Return the string, with each RubyPants HTML entity translated to
449
+ # its ASCII counterpart.
450
+ #
451
+ # Note: This is not reversible (but exactly the same as in SmartyPants)
452
+ #
453
+ def stupefy_entities(str)
454
+ str.
455
+ gsub(%r(#{EN_DASH}), "-"). # en-dash
456
+ gsub(%r(#{EM_DASH}), "--"). # em-dash
457
+
458
+ gsub(%r(#{OPEN_SGL_QUOTE}), "'"). # open single quote
459
+ gsub(%r(#{CLOSE_SGL_QUOTE}), "'"). # close single quote
460
+
461
+ gsub(%r(#{OPEN_DBL_QUOTE}), '"'). # open double quote
462
+ gsub(%r(#{CLOSE_DBL_QUOTE}), '"'). # close double quote
463
+
464
+ gsub(/&#8230;/, '...') # ellipsis
465
+ end
466
+
467
+ # Return an array of the tokens comprising the string. Each token is
468
+ # either a tag (possibly with nested, tags contained therein, such
469
+ # as <tt><a href="<MTFoo>"></tt>, or a run of text between
470
+ # tags. Each element of the array is a two-element array; the first
471
+ # is either :tag or :text; the second is the actual value.
472
+ #
473
+ # Based on the <tt>_tokenize()</tt> subroutine from Brad Choate's
474
+ # MTRegex plugin. <http://www.bradchoate.com/past/mtregex.php>
475
+ #
476
+ # This is actually the easier variant using tag_soup, as used by
477
+ # Chad Miller in the Python port of SmartyPants.
478
+ #
479
+ def tokenize(string)
480
+ tag_soup = /([^<]*)(<[^>]*>)/o
481
+
482
+ tokens = []
483
+
484
+ prev_end = 0
485
+ string.scan(tag_soup) {
486
+ tokens << [:text, $1] if $1 != ""
487
+ tokens << [:tag, $2]
488
+
489
+ prev_end = $~.end(0)
490
+ }
491
+
492
+ if prev_end < string.size
493
+ tokens << [:text, string[prev_end..-1]]
494
+ end
495
+
496
+ tokens
497
+ end
498
+ end
499
+ end