publify_core 9.1.0 → 9.2.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 (357) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +34 -1
  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 -5
  76. data/app/controllers/admin/content_controller.rb +37 -24
  77. data/app/controllers/admin/dashboard_controller.rb +16 -64
  78. data/app/controllers/admin/feedback_controller.rb +45 -38
  79. data/app/controllers/admin/notes_controller.rb +15 -9
  80. data/app/controllers/admin/pages_controller.rb +18 -15
  81. data/app/controllers/admin/post_types_controller.rb +7 -5
  82. data/app/controllers/admin/profiles_controller.rb +4 -2
  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 +14 -10
  86. data/app/controllers/admin/settings_controller.rb +7 -5
  87. data/app/controllers/admin/sidebar_controller.rb +7 -4
  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 +9 -6
  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 -5
  94. data/app/controllers/comments_controller.rb +12 -8
  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 +14 -10
  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 +14 -12
  103. data/app/controllers/xml_controller.rb +2 -0
  104. data/app/helpers/admin/base_helper.rb +28 -28
  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 +6 -3
  108. data/app/helpers/base_helper.rb +50 -34
  109. data/app/helpers/blog_helper.rb +4 -2
  110. data/app/helpers/xml_helper.rb +2 -0
  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 +44 -32
  116. data/app/models/article/factory.rb +14 -6
  117. data/app/models/blog.rb +85 -65
  118. data/app/models/comment.rb +10 -7
  119. data/app/models/config_manager.rb +4 -2
  120. data/app/models/content.rb +34 -40
  121. data/app/models/content_base.rb +9 -3
  122. data/app/models/feedback.rb +19 -16
  123. data/app/models/meta_sidebar.rb +5 -2
  124. data/app/models/note.rb +25 -23
  125. data/app/models/page.rb +8 -6
  126. data/app/models/page_sidebar.rb +4 -2
  127. data/app/models/ping.rb +2 -0
  128. data/app/models/post_type.rb +3 -1
  129. data/app/models/redirect.rb +11 -6
  130. data/app/models/redirection.rb +2 -0
  131. data/app/models/resource.rb +4 -2
  132. data/app/models/search_sidebar.rb +4 -2
  133. data/app/models/sidebar.rb +10 -5
  134. data/app/models/static_sidebar.rb +15 -12
  135. data/app/models/tag.rb +14 -10
  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 +6 -3
  140. data/app/models/user.rb +43 -42
  141. data/app/services/title_builder.rb +56 -45
  142. data/app/uploaders/resource_uploader.rb +7 -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/edit.html.erb +1 -1
  147. data/app/views/admin/content/index.html.erb +25 -15
  148. data/app/views/admin/content/new.html.erb +2 -2
  149. data/app/views/admin/dashboard/_comment.html.erb +5 -5
  150. data/app/views/admin/dashboard/_comments.html.erb +2 -2
  151. data/app/views/admin/dashboard/_drafts.html.erb +5 -5
  152. data/app/views/admin/dashboard/_overview.html.erb +7 -9
  153. data/app/views/admin/dashboard/_welcome.html.erb +11 -11
  154. data/app/views/admin/dashboard/index.html.erb +12 -7
  155. data/app/views/admin/feedback/_button.html.erb +6 -6
  156. data/app/views/admin/feedback/_feedback.html.erb +3 -3
  157. data/app/views/admin/feedback/_ham.html.erb +27 -9
  158. data/app/views/admin/feedback/_spam.html.erb +26 -16
  159. data/app/views/admin/feedback/article.html.erb +20 -21
  160. data/app/views/admin/feedback/edit.html.erb +14 -15
  161. data/app/views/admin/feedback/{ham.js → ham.js.erb} +0 -0
  162. data/app/views/admin/feedback/index.html.erb +25 -23
  163. data/app/views/admin/feedback/{spam.js → spam.js.erb} +0 -0
  164. data/app/views/admin/migrations/show.html.erb +10 -11
  165. data/app/views/admin/notes/_form.html.erb +13 -13
  166. data/app/views/admin/notes/_list.html.erb +19 -8
  167. data/app/views/admin/notes/_note.html.erb +12 -7
  168. data/app/views/admin/notes/edit.html.erb +6 -1
  169. data/app/views/admin/notes/index.html.erb +5 -1
  170. data/app/views/admin/notes/show.html.erb +2 -2
  171. data/app/views/admin/pages/_form.html.erb +86 -77
  172. data/app/views/admin/pages/_pages.html.erb +11 -4
  173. data/app/views/admin/pages/edit.html.erb +3 -1
  174. data/app/views/admin/pages/index.html.erb +10 -6
  175. data/app/views/admin/pages/new.html.erb +3 -1
  176. data/app/views/admin/post_types/_index_and_form.html.erb +15 -16
  177. data/app/views/admin/post_types/edit.html.erb +1 -1
  178. data/app/views/admin/post_types/index.html.erb +1 -1
  179. data/app/views/admin/profiles/index.html.erb +2 -3
  180. data/app/views/admin/redirects/_index_and_form.html.erb +10 -11
  181. data/app/views/admin/redirects/edit.html.erb +1 -1
  182. data/app/views/admin/redirects/index.html.erb +1 -1
  183. data/app/views/admin/resources/index.html.erb +19 -16
  184. data/app/views/admin/seo/_general.html.erb +23 -47
  185. data/app/views/admin/seo/_permalinks.html.erb +14 -14
  186. data/app/views/admin/seo/_titles.html.erb +63 -64
  187. data/app/views/admin/seo/show.html.erb +14 -19
  188. data/app/views/admin/settings/display.html.erb +22 -25
  189. data/app/views/admin/settings/feedback.html.erb +31 -32
  190. data/app/views/admin/settings/index.html.erb +23 -24
  191. data/app/views/admin/settings/write.html.erb +21 -22
  192. data/app/views/admin/shared/_edit.html.erb +3 -3
  193. data/app/views/admin/shared/_menu.html.erb +26 -26
  194. data/app/views/admin/shared/_twitter_alert.html.erb +1 -1
  195. data/app/views/admin/sidebar/_config.html.erb +5 -5
  196. data/app/views/admin/sidebar/_target_sidebar.html.erb +4 -4
  197. data/app/views/admin/sidebar/index.html.erb +7 -7
  198. data/app/views/admin/tags/_index_and_form.html.erb +11 -12
  199. data/app/views/admin/tags/edit.html.erb +1 -1
  200. data/app/views/admin/tags/index.html.erb +1 -1
  201. data/app/views/admin/themes/index.html.erb +5 -6
  202. data/app/views/admin/users/_form.html.erb +34 -34
  203. data/app/views/admin/users/edit.html.erb +2 -2
  204. data/app/views/admin/users/index.html.erb +10 -12
  205. data/app/views/admin/users/new.html.erb +2 -2
  206. data/app/views/archives_sidebar/_content.html.erb +2 -2
  207. data/app/views/articles/_archives_article.html.erb +3 -3
  208. data/app/views/articles/_article.html.erb +7 -9
  209. data/app/views/articles/_article_author.html.erb +4 -0
  210. data/app/views/articles/_article_content.html.erb +2 -2
  211. data/app/views/articles/_article_excerpt.html.erb +2 -2
  212. data/app/views/articles/_article_links.html.erb +1 -1
  213. data/app/views/articles/_comment_errors.html.erb +1 -1
  214. data/app/views/articles/_comment_form.html.erb +12 -12
  215. data/app/views/articles/_comment_preview.html.erb +3 -3
  216. data/app/views/articles/_password_form.html.erb +4 -4
  217. data/app/views/articles/_trackback.html.erb +2 -2
  218. data/app/views/articles/archives.html.erb +1 -1
  219. data/app/views/articles/feedback_atom_feed.atom.builder +3 -1
  220. data/app/views/articles/feedback_rss_feed.rss.builder +9 -7
  221. data/app/views/articles/index_atom_feed.atom.builder +5 -3
  222. data/app/views/articles/index_rss_feed.rss.builder +10 -8
  223. data/app/views/articles/live_search.html.erb +3 -3
  224. data/app/views/articles/read.html.erb +16 -8
  225. data/app/views/articles/search.html.erb +2 -2
  226. data/app/views/articles/trackback.xml.builder +3 -1
  227. data/app/views/articles/view_page.html.erb +1 -1
  228. data/app/views/authors/show.html.erb +9 -9
  229. data/app/views/authors/show_atom_feed.atom.builder +4 -2
  230. data/app/views/authors/show_rss_feed.rss.builder +10 -8
  231. data/app/views/comments/_comment.html.erb +3 -3
  232. data/app/views/devise/mailer/reset_password_instructions.html.erb +7 -9
  233. data/app/views/devise/passwords/edit.html.erb +4 -4
  234. data/app/views/devise/passwords/new.html.erb +1 -1
  235. data/app/views/devise/registrations/new.html.erb +5 -5
  236. data/app/views/devise/sessions/new.html.erb +3 -3
  237. data/app/views/errors/404.html.erb +2 -2
  238. data/app/views/feedback/index.atom.builder +3 -1
  239. data/app/views/feedback/index.rss.builder +9 -7
  240. data/app/views/layouts/accounts.html.erb +26 -26
  241. data/app/views/layouts/administration.html.erb +31 -31
  242. data/app/views/layouts/default.html.erb +3 -3
  243. data/app/views/layouts/editor.html.erb +5 -19
  244. data/app/views/meta_sidebar/_content.html.erb +2 -2
  245. data/app/views/notes/_note.html.erb +1 -1
  246. data/app/views/notes/index.html.erb +1 -1
  247. data/app/views/notes/show_in_reply.html.erb +1 -1
  248. data/app/views/notification_mailer/_mail_footer.html.erb +3 -3
  249. data/app/views/notification_mailer/article.html.erb +2 -2
  250. data/app/views/notification_mailer/comment.html.erb +5 -5
  251. data/app/views/notification_mailer/notif_user.html.erb +1 -1
  252. data/app/views/page_sidebar/_content.html.erb +1 -1
  253. data/app/views/search_sidebar/_content.html.erb +2 -2
  254. data/app/views/settings/install.html.erb +2 -2
  255. data/app/views/setup/index.html.erb +7 -7
  256. data/app/views/shared/_atom_header.atom.builder +4 -2
  257. data/app/views/shared/_atom_item_article.atom.builder +11 -6
  258. data/app/views/shared/_atom_item_comment.atom.builder +4 -2
  259. data/app/views/shared/_atom_item_trackback.atom.builder +4 -2
  260. data/app/views/shared/_page_header.html.erb +9 -12
  261. data/app/views/shared/_rss_item_article.rss.builder +6 -3
  262. data/app/views/shared/_rss_item_comment.rss.builder +3 -1
  263. data/app/views/shared/_rss_item_trackback.rss.builder +3 -1
  264. data/app/views/sidebar/display_plugins.html.erb +1 -1
  265. data/app/views/tag_sidebar/_content.html.erb +1 -1
  266. data/app/views/tags/index.html.erb +1 -1
  267. data/app/views/xml/_googlesitemap_item_article.googlesitemap.builder +2 -0
  268. data/app/views/xml/_googlesitemap_item_category.googlesitemap.builder +2 -0
  269. data/app/views/xml/_googlesitemap_item_page.googlesitemap.builder +2 -0
  270. data/app/views/xml/_googlesitemap_item_tag.googlesitemap.builder +2 -0
  271. data/app/views/xml/sitemap.googlesitemap.builder +4 -2
  272. data/config/i18n-tasks.yml +0 -5
  273. data/config/initializers/devise.rb +10 -4
  274. data/config/initializers/mime_types.rb +3 -1
  275. data/config/locales/da.yml +134 -71
  276. data/config/locales/de.yml +142 -75
  277. data/config/locales/en.yml +128 -66
  278. data/config/locales/es-MX.yml +135 -69
  279. data/config/locales/fr.yml +167 -86
  280. data/config/locales/he.yml +128 -70
  281. data/config/locales/it.yml +136 -72
  282. data/config/locales/ja.yml +110 -64
  283. data/config/locales/lt.yml +153 -74
  284. data/config/locales/nb-NO.yml +123 -65
  285. data/config/locales/nl.yml +140 -75
  286. data/config/locales/pl.yml +160 -69
  287. data/config/locales/pt-BR.yml +137 -70
  288. data/config/locales/ro.yml +148 -70
  289. data/config/locales/ru.yml +161 -69
  290. data/config/locales/zh-CN.yml +106 -59
  291. data/config/locales/zh-TW.yml +109 -61
  292. data/config/routes.rb +68 -63
  293. data/db/migrate/113_initial_schema.rb +192 -190
  294. data/db/migrate/114_fixes_buggy_articles_and_notes.rb +9 -6
  295. data/db/migrate/115_drops_categories_for_tags.rb +3 -1
  296. data/db/migrate/20150207131657_add_missing_indexes.rb +2 -0
  297. data/db/migrate/20150807134129_simplify_redirect_relations.rb +8 -1
  298. data/db/migrate/20150808052637_add_blog_ids.rb +4 -2
  299. data/db/migrate/20150808191127_add_blog_id_to_redirects.rb +2 -0
  300. data/db/migrate/20150810094754_add_blog_id_to_tags.rb +2 -0
  301. data/db/migrate/20160108111120_add_devise_to_users.rb +4 -2
  302. data/db/migrate/20160108184201_move_last_connection_to_last_sign_in_at.rb +2 -0
  303. data/db/migrate/20160110094906_remove_profiles_rights.rb +2 -0
  304. data/db/migrate/20160605103918_replace_profile_id_with_string.rb +2 -0
  305. data/db/migrate/20160605154632_remove_profiles.rb +10 -5
  306. data/db/migrate/20160701061851_demand_blog_id_on_contents.rb +2 -0
  307. data/db/migrate/20160701062604_add_blog_id_to_resources.rb +2 -0
  308. data/db/migrate/20170528093024_move_resources_to_content.rb +2 -0
  309. data/db/migrate/20170528094923_move_tags_to_content.rb +2 -0
  310. data/db/migrate/20170528201606_remove_separate_published_flag.rb +2 -0
  311. data/db/migrate/20170605071626_remove_extra_state_columns_from_feedback.rb +2 -0
  312. data/db/migrate/20170702105201_remove_published_at_from_feedback.rb +2 -0
  313. data/db/migrate/20190208151235_add_text_filter_name_fields.rb +9 -0
  314. data/db/migrate/20190208152646_move_text_filter_to_name.rb +97 -0
  315. data/db/migrate/20190209155717_remove_text_filter_ids.rb +19 -0
  316. data/db/migrate/20190209160610_remove_text_filters.rb +17 -0
  317. data/db/migrate/20200413140440_add_unique_indexes.rb +10 -0
  318. data/db/seeds.rb +9 -19
  319. data/lib/email_notify.rb +3 -1
  320. data/lib/format.rb +4 -2
  321. data/lib/publify_core.rb +36 -35
  322. data/lib/publify_core/engine.rb +8 -6
  323. data/lib/publify_core/lang.rb +5 -1
  324. data/lib/publify_core/testing_support/dns_mock.rb +15 -0
  325. data/lib/publify_core/testing_support/factories.rb +240 -0
  326. data/lib/publify_core/testing_support/feed_assertions.rb +48 -0
  327. data/lib/publify_core/testing_support/fixtures/exploit.svg +4 -0
  328. data/lib/publify_core/testing_support/fixtures/fakepng.png +1 -0
  329. data/lib/publify_core/testing_support/fixtures/otherfile.txt +1 -0
  330. data/lib/publify_core/testing_support/fixtures/testfile.png +0 -0
  331. data/lib/publify_core/testing_support/fixtures/testfile.txt +1 -0
  332. data/lib/publify_core/testing_support/upload_fixtures.rb +15 -0
  333. data/lib/publify_core/version.rb +3 -1
  334. data/lib/publify_guid.rb +3 -1
  335. data/lib/publify_plugins.rb +10 -5
  336. data/lib/publify_textfilter_markdown.rb +38 -25
  337. data/lib/publify_textfilter_none.rb +5 -3
  338. data/lib/publify_textfilter_smartypants.rb +5 -3
  339. data/lib/publify_textfilter_textile.rb +7 -4
  340. data/lib/publify_textfilter_twitterfilter.rb +13 -7
  341. data/lib/publify_time.rb +4 -0
  342. data/lib/sidebar_field.rb +15 -13
  343. data/lib/sidebar_registry.rb +5 -3
  344. data/lib/spam_protection.rb +16 -13
  345. data/lib/tasks/i18n.rake +9 -0
  346. data/lib/tasks/manifest.rake +30 -0
  347. data/lib/tasks/publify_core_tasks.rake +2 -0
  348. data/lib/text_filter_plugin.rb +27 -25
  349. data/lib/theme.rb +5 -3
  350. data/lib/transforms.rb +22 -19
  351. metadata +217 -87
  352. data/app/assets/javascripts/widearea.js +0 -486
  353. data/app/assets/stylesheets/widearea.css +0 -133
  354. data/app/controllers/admin/textfilters_controller.rb +0 -6
  355. data/app/views/admin/dashboard/_inbound.html.erb +0 -31
  356. data/app/views/admin/notes/_header.html.erb +0 -6
  357. data/app/views/articles/_protected_article_content.html.erb +0 -6
@@ -1,4 +1,6 @@
1
- require 'timeout'
1
+ # frozen_string_literal: true
2
+
3
+ require "timeout"
2
4
 
3
5
  class Comment < Feedback
4
6
  belongs_to :user, optional: true
@@ -7,14 +9,14 @@ class Comment < Feedback
7
9
 
8
10
  attr_accessor :referrer, :permalink
9
11
 
10
- scope :spam, -> { where(state: 'spam') }
12
+ scope :spam, -> { where(state: "spam") }
11
13
  scope :not_spam, -> { where("state != 'spam'") }
12
- scope :presumed_spam, -> { where(state: 'presumed_spam') }
13
- scope :presumed_ham, -> { where(state: 'presumed_ham') }
14
- scope :ham, -> { where(state: 'ham') }
14
+ scope :presumed_spam, -> { where(state: "presumed_spam") }
15
+ scope :presumed_ham, -> { where(state: "presumed_ham") }
16
+ scope :ham, -> { where(state: "ham") }
15
17
  scope :unconfirmed, -> { where(state: %w(presumed_spam presumed_ham)) }
16
18
 
17
- scope :last_published, -> { published.limit(5).order('created_at DESC') }
19
+ scope :last_published, -> { published.limit(5).order("created_at DESC") }
18
20
 
19
21
  def notify_user_via_email(user)
20
22
  EmailNotify.send_comment(self, user) if user.notify_via_email?
@@ -40,7 +42,8 @@ class Comment < Feedback
40
42
 
41
43
  def article_allows_feedback?
42
44
  return true if article.allow_comments?
43
- errors.add(:article, 'Article is not open to comments')
45
+
46
+ errors.add(:article, "Article is not open to comments")
44
47
  false
45
48
  end
46
49
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ConfigManager
2
4
  def self.append_features(base)
3
5
  super
@@ -35,7 +37,7 @@ module ConfigManager
35
37
  raw_value.nil? ? item.default : raw_value
36
38
  end
37
39
  if item.ruby_type == :boolean
38
- send(:define_method, item.name + '?') do
40
+ send(:define_method, "#{item.name}?") do
39
41
  raw_value = settings[item.name]
40
42
  raw_value.nil? ? item.default : raw_value
41
43
  end
@@ -62,7 +64,7 @@ module ConfigManager
62
64
  case ruby_type
63
65
  when :boolean
64
66
  case value
65
- when '0', 0, '', false, 'false', 'f', nil
67
+ when "0", 0, "", false, "false", "f", nil
66
68
  false
67
69
  else
68
70
  true
@@ -1,34 +1,40 @@
1
- require 'set'
2
- require 'uri'
1
+ # frozen_string_literal: true
2
+
3
+ require "set"
4
+ require "uri"
3
5
 
4
6
  class Content < ApplicationRecord
5
7
  include ContentBase
6
8
 
7
- belongs_to :text_filter, optional: true
8
9
  belongs_to :user, optional: true, touch: true
9
10
  belongs_to :blog
10
11
 
11
12
  validates :blog, presence: true
12
13
 
13
- has_one :redirect, dependent: :destroy, inverse_of: :contents
14
+ has_one :redirect, dependent: :destroy, inverse_of: :content
14
15
 
15
16
  has_many :triggers, as: :pending_item, dependent: :delete_all
16
17
  has_many :resources, inverse_of: :content, dependent: :nullify
17
18
  has_and_belongs_to_many :tags
18
19
 
19
- scope :user_id, ->(user_id) { where('user_id = ?', user_id) }
20
- scope :published, -> { where(state: 'published'). order(default_order) }
21
- scope :published_at, ->(time_params) { published.where(published_at: PublifyTime.delta(*time_params)) }
22
- scope :not_published, -> { where.not(state: 'published') }
23
- scope :drafts, -> { where(state: 'draft').order('created_at DESC') }
24
- scope :no_draft, -> { where.not(state: 'draft').order('published_at DESC') }
20
+ scope :user_id, ->(user_id) { where("user_id = ?", user_id) }
21
+ scope :published, -> { where(state: "published").order(default_order) }
22
+ scope :published_at, lambda { |time_params|
23
+ published.where(published_at: PublifyTime.delta(*time_params))
24
+ }
25
+ scope :not_published, -> { where.not(state: "published") }
26
+ scope :drafts, -> { where(state: "draft").order("created_at DESC") }
27
+ scope :no_draft, -> { where.not(state: "draft").order("published_at DESC") }
25
28
  scope :searchstring, lambda { |search_string|
26
- tokens = search_string.split(' ').map { |c| "%#{c.downcase}%" }
27
- where('state = ? AND ' + (['(LOWER(body) LIKE ? OR LOWER(extended) LIKE ? OR LOWER(title) LIKE ?)'] * tokens.size).join(' AND '),
28
- 'published', *tokens.map { |token| [token] * 3 }.flatten)
29
+ tokens = search_string.split(" ").map { |c| "%#{c.downcase}%" }
30
+ matcher = "(LOWER(body) LIKE ? OR LOWER(extended) LIKE ? OR LOWER(title) LIKE ?)"
31
+ template = "state = ? AND #{([matcher] * tokens.size).join(" AND ")}"
32
+ where(template, "published", *tokens.map { |token| [token] * 3 }.flatten)
29
33
  }
30
34
 
31
- scope :published_at_like, ->(date_at) { where(published_at: PublifyTime.delta_like(date_at)) }
35
+ scope :published_at_like, lambda { |date_at|
36
+ where(published_at: PublifyTime.delta_like(date_at))
37
+ }
32
38
 
33
39
  serialize :whiteboard
34
40
 
@@ -49,28 +55,12 @@ class Content < ApplicationRecord
49
55
  end
50
56
  end
51
57
 
52
- # Set the text filter for this object.
53
- # NOTE: Due to how Rails injects association methods, this cannot be put in ContentBase
54
- # TODO: Allowing assignment of a string here is not very clean.
55
- def text_filter=(filter)
56
- filter_object = case filter
57
- when TextFilter
58
- filter
59
- else
60
- TextFilter.find_or_default(filter)
61
- end
62
- self.text_filter_id = if filter_object
63
- filter_object.id
64
- else
65
- filter.to_i
66
- end
67
- end
68
-
69
58
  def shorten_url
70
59
  return unless published?
71
60
 
72
61
  if redirect.present?
73
62
  return if redirect.to_path == permalink_url
63
+
74
64
  redirect.to_path = permalink_url
75
65
  redirect.save
76
66
  else
@@ -91,13 +81,17 @@ class Content < ApplicationRecord
91
81
  scoped = unscoped
92
82
  scoped = scoped.searchstring(params[:searchstring]) if params[:searchstring].present?
93
83
 
94
- scoped = scoped.published_at_like(params[:published_at]) if params[:published_at].present? && /(\d\d\d\d)-(\d\d)/ =~ params[:published_at]
84
+ if params[:published_at].present? && /(\d\d\d\d)-(\d\d)/ =~ params[:published_at]
85
+ scoped = scoped.published_at_like(params[:published_at])
86
+ end
95
87
 
96
- scoped = scoped.user_id(params[:user_id]) if params[:user_id].present? && params[:user_id].to_i > 0
88
+ if params[:user_id].present? && params[:user_id].to_i > 0
89
+ scoped = scoped.user_id(params[:user_id])
90
+ end
97
91
 
98
92
  if params[:published].present?
99
- scoped = scoped.published if params[:published].to_s == '1'
100
- scoped = scoped.not_published if params[:published].to_s == '0'
93
+ scoped = scoped.published if params[:published].to_s == "1"
94
+ scoped = scoped.not_published if params[:published].to_s == "0"
101
95
  end
102
96
 
103
97
  scoped
@@ -108,13 +102,13 @@ class Content < ApplicationRecord
108
102
  end
109
103
 
110
104
  def rss_description
111
- return '' unless blog.rss_description
105
+ return "" unless blog.rss_description
112
106
 
113
107
  rss_desc = blog.rss_description_text
114
- rss_desc.gsub!('%author%', author_name)
115
- rss_desc.gsub!('%blog_url%', blog.base_url)
116
- rss_desc.gsub!('%blog_name%', blog.blog_name)
117
- rss_desc.gsub!('%permalink_url%', permalink_url)
108
+ rss_desc.gsub!("%author%", author_name)
109
+ rss_desc.gsub!("%blog_url%", blog.base_url)
110
+ rss_desc.gsub!("%blog_name%", blog.blog_name)
111
+ rss_desc.gsub!("%permalink_url%", permalink_url)
118
112
  rss_desc
119
113
  end
120
114
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ContentBase
2
4
  def self.included(base)
3
5
  base.extend ClassMethods
@@ -52,7 +54,7 @@ module ContentBase
52
54
  end
53
55
 
54
56
  def excerpt_text(length = 160)
55
- text = if respond_to?(:excerpt) && (excerpt || '') != ''
57
+ text = if respond_to?(:excerpt) && (excerpt || "") != ""
56
58
  generate_html(:excerpt, excerpt)
57
59
  else
58
60
  html(:all)
@@ -61,7 +63,11 @@ module ContentBase
61
63
  text = text.strip_html
62
64
 
63
65
  text.slice(0, length) +
64
- (text.length > length ? '...' : '')
66
+ (text.length > length ? "..." : "")
67
+ end
68
+
69
+ def text_filter
70
+ TextFilter.make_filter(text_filter_name)
65
71
  end
66
72
 
67
73
  # The default text filter. Generally, this is the filter specified by blog.text_filter,
@@ -76,7 +82,7 @@ module ContentBase
76
82
  end
77
83
 
78
84
  def default_order
79
- 'published_at DESC'
85
+ "published_at DESC"
80
86
  end
81
87
  end
82
88
  end
@@ -1,12 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'aasm'
4
- require 'akismet'
3
+ require "aasm"
4
+ require "akismet"
5
5
 
6
6
  class Feedback < ApplicationRecord
7
- self.table_name = 'feedback'
7
+ self.table_name = "feedback"
8
8
 
9
- belongs_to :text_filter, optional: true
10
9
  belongs_to :article, touch: true
11
10
 
12
11
  include PublifyGuid
@@ -21,17 +20,17 @@ class Feedback < ApplicationRecord
21
20
  validate :feedback_not_closed, on: :create
22
21
  validates :article, presence: true
23
22
 
24
- before_create :create_guid, :article_allows_this_feedback
25
23
  before_save :correct_url, :classify_content
24
+ before_create :create_guid, :article_allows_this_feedback
26
25
 
27
26
  # TODO: Rename so it doesn't sound like only approved ham
28
27
  scope :ham, -> { where(state: %w(presumed_ham ham)) }
29
28
 
30
- scope :spam, -> { where(state: 'spam') }
31
- scope :created_since, ->(time) { ham.where('created_at > ?', time) }
32
- scope :presumed_ham, -> { where(state: 'presumed_ham') }
33
- scope :presumed_spam, -> { where(state: 'presumed_spam') }
34
- scope :unapproved, -> { where(state: ['presumed_spam', 'presumed_ham']) }
29
+ scope :spam, -> { where(state: "spam") }
30
+ scope :created_since, ->(time) { ham.where("created_at > ?", time) }
31
+ scope :presumed_ham, -> { where(state: "presumed_ham") }
32
+ scope :presumed_spam, -> { where(state: "presumed_spam") }
33
+ scope :unapproved, -> { where(state: ["presumed_spam", "presumed_ham"]) }
35
34
 
36
35
  scope :published, -> { ham }
37
36
  scope :oldest_first, -> { order(:created_at) }
@@ -97,7 +96,8 @@ class Feedback < ApplicationRecord
97
96
 
98
97
  def correct_url
99
98
  return if url.blank?
100
- self.url = 'http://' + url.to_s unless url =~ %r{^https?://}
99
+
100
+ self.url = "http://#{url}" unless %r{^https?://}.match?(url)
101
101
  end
102
102
 
103
103
  def article_allows_this_feedback
@@ -157,13 +157,13 @@ class Feedback < ApplicationRecord
157
157
  end
158
158
 
159
159
  def change_state!
160
- result = ''
160
+ result = ""
161
161
  if spam? || presumed_spam?
162
162
  mark_as_ham!
163
- result = 'ham'
163
+ result = "ham"
164
164
  else
165
165
  mark_as_spam!
166
- result = 'spam'
166
+ result = "spam"
167
167
  end
168
168
  result
169
169
  end
@@ -183,6 +183,7 @@ class Feedback < ApplicationRecord
183
183
 
184
184
  def report_as_spam
185
185
  return if akismet.nil?
186
+
186
187
  begin
187
188
  Timeout.timeout(5) do
188
189
  akismet.submit_spam(ip, user_agent, akismet_options)
@@ -194,6 +195,7 @@ class Feedback < ApplicationRecord
194
195
 
195
196
  def report_as_ham
196
197
  return if akismet.nil?
198
+
197
199
  begin
198
200
  Timeout.timeout(5) do
199
201
  akismet.ham(ip, user_agent, akismet_options)
@@ -204,7 +206,7 @@ class Feedback < ApplicationRecord
204
206
  end
205
207
 
206
208
  def feedback_not_closed
207
- errors.add(:article_id, 'Comment are closed') if article.comments_closed?
209
+ errors.add(:article_id, "Comment are closed") if article.comments_closed?
208
210
  end
209
211
 
210
212
  def send_notifications
@@ -233,9 +235,10 @@ class Feedback < ApplicationRecord
233
235
 
234
236
  def akismet_client
235
237
  return nil if blog.sp_akismet_key.blank?
238
+
236
239
  client = Akismet::Client.new(blog.sp_akismet_key, blog.base_url)
237
240
  begin
238
- return client.verify_key ? client : nil
241
+ client.verify_key ? client : nil
239
242
  rescue SocketError
240
243
  nil
241
244
  end
@@ -1,7 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class MetaSidebar < Sidebar
2
- description "This widget just displays links to Publify main site, this blog's admin and RSS."
4
+ description "This widget just displays links to Publify main site," \
5
+ " this blog's admin and RSS."
3
6
 
4
- setting :title, 'Meta'
7
+ setting :title, "Meta"
5
8
  end
6
9
 
7
10
  SidebarRegistry.register_sidebar MetaSidebar
@@ -1,27 +1,29 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Note < Content
2
- require 'twitter'
3
- require 'json'
4
- require 'uri'
4
+ require "twitter"
5
+ require "json"
6
+ require "uri"
5
7
  include PublifyGuid
6
8
  include ConfigManager
7
9
 
8
10
  serialize :settings, Hash
9
11
 
10
- setting :twitter_id, :string, ''
11
- setting :in_reply_to_status_id, :string, ''
12
+ setting :twitter_id, :string, ""
13
+ setting :in_reply_to_status_id, :string, ""
12
14
  setting :in_reply_to_protected, :boolean, false
13
- setting :in_reply_to_message, :string, ''
15
+ setting :in_reply_to_message, :string, ""
14
16
 
15
17
  validates :body, presence: true
16
18
  validates :permalink, :guid, uniqueness: true
17
19
 
18
- after_create :set_permalink, :shorten_url
19
20
  before_create :create_guid
21
+ after_create :set_permalink, :shorten_url
20
22
 
21
23
  scope :published, lambda {
22
- where(state: 'published').where('published_at <= ?', Time.zone.now).order(default_order)
24
+ where(state: "published").where("published_at <= ?", Time.zone.now).order(default_order)
23
25
  }
24
- default_scope { order('published_at DESC') }
26
+ default_scope { order("published_at DESC") }
25
27
 
26
28
  TWITTER_FTP_URL_LENGTH = 19
27
29
  TWITTER_HTTP_URL_LENGTH = 20
@@ -46,10 +48,10 @@ class Note < Content
46
48
  end
47
49
 
48
50
  def truncate(message, length)
49
- if message[length + 1] == ' '
51
+ if message[length + 1] == " "
50
52
  message[0..length]
51
53
  else
52
- message[0..(message[0..length].rindex(' ') - 1)]
54
+ message[0..(message[0..length].rindex(" ") - 1)]
53
55
  end
54
56
  end
55
57
 
@@ -65,7 +67,7 @@ class Note < Content
65
67
 
66
68
  # FIXME: This breaks if the user changes or deletes their handle.
67
69
  def twitter_url
68
- File.join('https://twitter.com', user.twitter, 'status', twitter_id)
70
+ File.join("https://twitter.com", user.twitter, "status", twitter_id)
69
71
  end
70
72
 
71
73
  def send_to_twitter
@@ -81,7 +83,7 @@ class Note < Content
81
83
 
82
84
  begin
83
85
  options = {}
84
- if in_reply_to_status_id && in_reply_to_status_id != ''
86
+ if in_reply_to_status_id && in_reply_to_status_id != ""
85
87
  options = { in_reply_to_status_id: in_reply_to_status_id }
86
88
  self.in_reply_to_message = twitter.status(in_reply_to_status_id).to_json
87
89
  end
@@ -109,8 +111,8 @@ class Note < Content
109
111
 
110
112
  def permalink_url(anchor = nil, only_path = false)
111
113
  blog.url_for(
112
- controller: '/notes',
113
- action: 'show',
114
+ controller: "/notes",
115
+ action: "show",
114
116
  permalink: permalink,
115
117
  anchor: anchor,
116
118
  only_path: only_path)
@@ -122,11 +124,11 @@ class Note < Content
122
124
  end
123
125
 
124
126
  def prefix
125
- blog.shortener_url.sub(%r{^https?://}, '')
127
+ blog.shortener_url.sub(%r{^https?://}, "")
126
128
  end
127
129
 
128
130
  def published?
129
- state == 'published'
131
+ state == "published"
130
132
  end
131
133
 
132
134
  private
@@ -135,13 +137,13 @@ class Note < Content
135
137
  uris = URI.extract(message, %w(http https ftp))
136
138
  uris << prefix
137
139
  uris.each do |uri|
138
- payload = case uri.split(':')[0]
139
- when 'https'
140
- '-' * TWITTER_HTTPS_URL_LENGTH
141
- when 'ftp'
142
- '-' * TWITTER_FTP_URL_LENGTH
140
+ payload = case uri.split(":")[0]
141
+ when "https"
142
+ "-" * TWITTER_HTTPS_URL_LENGTH
143
+ when "ftp"
144
+ "-" * TWITTER_FTP_URL_LENGTH
143
145
  else
144
- '-' * TWITTER_HTTP_URL_LENGTH
146
+ "-" * TWITTER_HTTP_URL_LENGTH
145
147
  end
146
148
  message = message.gsub(uri, payload)
147
149
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Page < Content
2
4
  validates :title, :body, presence: true
3
5
  validates :name, uniqueness: true
@@ -5,7 +7,7 @@ class Page < Content
5
7
  include ConfigManager
6
8
 
7
9
  serialize :settings, Hash
8
- setting :password, :string, ''
10
+ setting :password, :string, ""
9
11
 
10
12
  before_save :set_permalink
11
13
  after_save :shorten_url
@@ -17,24 +19,24 @@ class Page < Content
17
19
  content_fields :body
18
20
 
19
21
  def self.default_order
20
- 'title ASC'
22
+ "title ASC"
21
23
  end
22
24
 
23
25
  def permalink_url(anchor = nil, only_path = false)
24
26
  blog.url_for(
25
- controller: '/articles',
26
- action: 'view_page',
27
+ controller: "/articles",
28
+ action: "view_page",
27
29
  name: name,
28
30
  anchor: anchor,
29
31
  only_path: only_path)
30
32
  end
31
33
 
32
34
  def publish!
33
- self.state = 'published'
35
+ self.state = "published"
34
36
  save!
35
37
  end
36
38
 
37
39
  def published?
38
- state == 'published'
40
+ state == "published"
39
41
  end
40
42
  end