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
@@ -1,7 +1,9 @@
1
- require 'sidebar_field'
1
+ # frozen_string_literal: true
2
+
3
+ require "sidebar_field"
2
4
 
3
5
  # This class cannot be autoloaded since other sidebar classes depend on it.
4
- class Sidebar < ActiveRecord::Base
6
+ class Sidebar < ApplicationRecord
5
7
  serialize :config, Hash
6
8
 
7
9
  belongs_to :blog
@@ -24,7 +26,7 @@ class Sidebar < ActiveRecord::Base
24
26
  end
25
27
 
26
28
  def self.purge
27
- delete_all('active_position is null and staged_position is null')
29
+ delete_all("active_position is null and staged_position is null")
28
30
  end
29
31
 
30
32
  def self.setting(key, default = nil, options = {})
@@ -55,7 +57,7 @@ class Sidebar < ActiveRecord::Base
55
57
  if desc
56
58
  @description = desc
57
59
  else
58
- @description || ''
60
+ @description || ""
59
61
  end
60
62
  end
61
63
 
@@ -90,7 +92,7 @@ class Sidebar < ActiveRecord::Base
90
92
  end
91
93
 
92
94
  def html_id
93
- short_name + '-' + id.to_s
95
+ "#{short_name}-#{id}"
94
96
  end
95
97
 
96
98
  def parse_request(_contents, _params); end
@@ -130,8 +132,11 @@ class Sidebar < ActiveRecord::Base
130
132
  end
131
133
 
132
134
  def admin_state
133
- return :active if active_position && (staged_position == active_position || staged_position.nil?)
135
+ if active_position && (staged_position == active_position || staged_position.nil?)
136
+ return :active
137
+ end
134
138
  return :will_change_position if active_position != staged_position
139
+
135
140
  raise "Unknown admin_state: active: #{active_position}, staged: #{staged_position}"
136
141
  end
137
142
  end
@@ -1,20 +1,21 @@
1
- # coding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
3
  class StaticSidebar < Sidebar
4
- DEFAULT_TEXT = '
5
- <ul>
6
- <li><a href="http://www.publify.co/" title="Publify">Publify</a></li>
7
- <li><a href="http://t37.net/" title="Le Rayon UX">Frédéric</a></li>
8
- <li><a href="http://www.matijs.net/" title="Matijs">Matijs</a></li>
9
- <li><a href="http://elsif.fr/" title="Yannick">Yannick</a></li>
10
- <li><a href="http://blog.ookook.fr/" title="Thomas">Thomas</a></li>
11
- <li><a href="/admin">Admin</a></li>
12
- </ul>
4
+ DEFAULT_TEXT = <<~TEXT
5
+ <ul>
6
+ <li><a href="https://publify.github.io/" title="Publify">Publify</a></li>
7
+ <li><a href="http://t37.net/" title="Le Rayon UX">Frédéric</a></li>
8
+ <li><a href="http://www.matijs.net/" title="Matijs">Matijs</a></li>
9
+ <li><a href="http://elsif.fr/" title="Yannick">Yannick</a></li>
10
+ <li><a href="http://blog.ookook.fr/" title="Thomas">Thomas</a></li>
11
+ <li><a href="/admin">Admin</a></li>
12
+ </ul>
13
+ TEXT
13
14
 
14
- '.freeze
15
- description 'Static content, like links to other sites, advertisements, or blog meta-information'
15
+ description "Static content, like links to other sites, advertisements," \
16
+ " or blog meta-information"
16
17
 
17
- setting :title, 'Links'
18
+ setting :title, "Links"
18
19
  setting :body, DEFAULT_TEXT, input_type: :text_area
19
20
  end
20
21
 
data/app/models/tag.rb CHANGED
@@ -1,6 +1,8 @@
1
- class Tag < ActiveRecord::Base
1
+ # frozen_string_literal: true
2
+
3
+ class Tag < ApplicationRecord
2
4
  belongs_to :blog
3
- has_and_belongs_to_many :contents, order: 'created_at DESC'
5
+ has_and_belongs_to_many :contents, order: "created_at DESC"
4
6
 
5
7
  validates :name, uniqueness: { scope: :blog_id }
6
8
  validates :blog, presence: true
@@ -12,10 +14,11 @@ class Tag < ActiveRecord::Base
12
14
 
13
15
  def self.create_from_article!(article)
14
16
  return if article.keywords.nil?
17
+
15
18
  tags = []
16
19
  Tag.transaction do
17
- tagwords = article.keywords.to_s.scan(/((['"]).*?\2|[\.:[[:alnum:]]]+)/).map do |x|
18
- x.first.tr("\"'", '')
20
+ tagwords = article.keywords.to_s.scan(/((['"]).*?\2|[.:[[:alnum:]]]+)/).map do |x|
21
+ x.first.tr("\"'", "")
19
22
  end
20
23
  tagwords.uniq.each do |tagword|
21
24
  tagname = tagword.to_url
@@ -35,18 +38,19 @@ class Tag < ActiveRecord::Base
35
38
 
36
39
  def self.find_all_with_content_counters
37
40
  Tag.joins(:contents).
38
- where(contents: { state: 'published' }).
39
- select(*Tag.column_names, 'COUNT(contents_tags.content_id) as content_counter').
41
+ where(contents: { state: "published" }).
42
+ select(*Tag.column_names, "COUNT(contents_tags.content_id) as content_counter").
40
43
  group(*Tag.column_names).
41
- order('content_counter DESC').limit(1000)
44
+ order("content_counter DESC").limit(1000)
42
45
  end
43
46
 
44
47
  def self.find_with_char(char)
45
- where('name LIKE ? ', "%#{char}%").order('name ASC')
48
+ where("name LIKE ? ", "%#{char}%").order("name ASC")
46
49
  end
47
50
 
48
51
  def self.collection_to_string(tags)
49
- tags.map(&:display_name).sort.map { |name| name =~ / / ? "\"#{name}\"" : name }.join ', '
52
+ tags.map(&:display_name).sort.
53
+ map { |name| / /.match?(name) ? "\"#{name}\"" : name }.join ", "
50
54
  end
51
55
 
52
56
  def published_contents
@@ -58,10 +62,10 @@ class Tag < ActiveRecord::Base
58
62
  end
59
63
 
60
64
  def feed_url(format)
61
- "#{permalink_url}.#{format.gsub(/\d/, '')}"
65
+ "#{permalink_url}.#{format.gsub(/\d/, "")}"
62
66
  end
63
67
 
64
68
  def permalink_url(_anchor = nil, only_path = false)
65
- blog.url_for(controller: 'tags', action: 'show', id: permalink, only_path: only_path)
69
+ blog.url_for(controller: "tags", action: "show", id: permalink, only_path: only_path)
66
70
  end
67
71
  end
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class TagSidebar < Sidebar
2
- display_name 'Tags'
3
- description 'Show most popular tags for this blog'
4
+ display_name "Tags"
5
+ description "Show most popular tags for this blog"
4
6
 
5
7
  setting :maximum_tags, 20
6
8
 
@@ -11,8 +13,9 @@ class TagSidebar < Sidebar
11
13
 
12
14
  def sizes
13
15
  return @sizes if @sizes
16
+
14
17
  total = tags.reduce(0) { |sum, tag| sum + tag.content_counter }
15
- average = total.to_f / @tags.size.to_f
18
+ average = total.to_f / @tags.size
16
19
  @sizes = tags.reduce({}) do |h, tag|
17
20
  size = tag.content_counter.to_f / average
18
21
  h.merge tag => [[2.0 / 3.0, size].max, 2].min * 100
@@ -1,15 +1,28 @@
1
- require 'net/http'
1
+ # frozen_string_literal: true
2
2
 
3
- class TextFilter < ActiveRecord::Base
4
- serialize :filters, Array
5
- serialize :params, Hash
3
+ require "net/http"
4
+
5
+ class TextFilter
6
+ attr_accessor :description, :filters, :markup, :name, :params
7
+
8
+ def initialize(name: nil,
9
+ description: nil,
10
+ markup: nil,
11
+ filters: [],
12
+ params: nil)
13
+ @name = name
14
+ @description = description
15
+ @markup = markup
16
+ @filters = filters
17
+ @params = params
18
+ end
6
19
 
7
20
  def sanitize(*args, &blk)
8
21
  self.class.sanitize(*args, &blk)
9
22
  end
10
23
 
11
24
  def self.find_or_default(name)
12
- find_by(name: name) || find_by(name: 'none')
25
+ make_filter(name) || none
13
26
  end
14
27
 
15
28
  def self.filter_text(text, filters)
@@ -17,8 +30,10 @@ class TextFilter < ActiveRecord::Base
17
30
 
18
31
  filters.each do |filter|
19
32
  next if filter.nil?
33
+
20
34
  filter_class = map[filter.to_s]
21
35
  next unless filter_class
36
+
22
37
  text = filter_class.filtertext(text)
23
38
  end
24
39
 
@@ -35,12 +50,16 @@ class TextFilter < ActiveRecord::Base
35
50
 
36
51
  help = []
37
52
  help.push(filter_map[markup])
38
- filter_types['macropre'].sort_by(&:short_name).each { |f| help.push f }
39
- filter_types['macropost'].sort_by(&:short_name).each { |f| help.push f }
53
+ filter_types["macropre"].sort_by(&:short_name).each { |f| help.push f }
54
+ filter_types["macropost"].sort_by(&:short_name).each { |f| help.push f }
40
55
  filters.each { |f| help.push(filter_map[f.to_s]) }
41
56
 
42
57
  help_text = help.map do |f|
43
- f.help_text.blank? ? '' : "<h3>#{f.display_name}</h3>\n#{BlueCloth.new(f.help_text).to_html}\n"
58
+ if f.help_text.blank?
59
+ ""
60
+ else
61
+ "<h3>#{f.display_name}</h3>\n#{BlueCloth.new(f.help_text).to_html}\n"
62
+ end
44
63
  end
45
64
 
46
65
  help_text.join("\n")
@@ -52,10 +71,65 @@ class TextFilter < ActiveRecord::Base
52
71
  help = [filter_map[markup]]
53
72
  filters.each { |f| help.push(filter_map[f.to_s]) }
54
73
 
55
- help_text = help.map do |f|
56
- f.help_text.blank? ? '' : "#{BlueCloth.new(f.help_text).to_html}\n"
74
+ help.map do |f|
75
+ f.help_text.blank? ? "" : "#{BlueCloth.new(f.help_text).to_html}\n"
57
76
  end.join("\n")
77
+ end
78
+
79
+ def self.all
80
+ [
81
+ markdown,
82
+ smartypants,
83
+ markdown_smartypants,
84
+ textile,
85
+ none,
86
+ ]
87
+ end
88
+
89
+ def self.make_filter(name)
90
+ case name
91
+ when "markdown"
92
+ markdown
93
+ when "smartypants"
94
+ smartypants
95
+ when "markdown smartypants"
96
+ markdown_smartypants
97
+ when "textile"
98
+ textile
99
+ when "none"
100
+ none
101
+ end
102
+ end
103
+
104
+ def self.markdown
105
+ new(name: "markdown",
106
+ description: "Markdown",
107
+ markup: "markdown")
108
+ end
109
+
110
+ def self.smartypants
111
+ new(name: "smartypants",
112
+ description: "SmartyPants",
113
+ markup: "none",
114
+ filters: [:smartypants])
115
+ end
116
+
117
+ def self.markdown_smartypants
118
+ new(name: "markdown smartypants",
119
+ description: "Markdown with SmartyPants",
120
+ markup: "markdown",
121
+ filters: [:smartypants])
122
+ end
123
+
124
+ def self.textile
125
+ new(name: "textile",
126
+ description: "Textile",
127
+ markup: "textile")
128
+ end
58
129
 
59
- help_text
130
+ def self.none
131
+ new(name: "none",
132
+ description: "None",
133
+ markup: "none")
60
134
  end
61
135
  end
@@ -1,34 +1,30 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Legacy class to support old feedback sent as trackbacks.
2
4
  class Trackback < Feedback
3
5
  content_fields :excerpt
4
6
  validates :title, :excerpt, :url, presence: true
5
7
 
6
- # attr_accessible :url, :blog_name, :title, :excerpt, :ip, :published, :article_id
7
-
8
- def initialize(*args, &block)
9
- super(*args, &block)
10
- self.title ||= url
11
- self.blog_name ||= ''
12
- end
13
-
14
8
  before_create :process_trackback
15
9
 
16
10
  def process_trackback
17
11
  if excerpt.length >= 251
18
12
  # this limits excerpt to 250 chars, including the trailing "..."
19
- self.excerpt = excerpt[0..246] << '...'
13
+ self.excerpt = excerpt[0..246] << "..."
20
14
  end
21
15
  end
22
16
 
23
17
  def article_allows_feedback?
24
18
  return true if article.allow_pings?
25
- errors.add(:article, 'Article is not pingable')
19
+
20
+ errors.add(:article, "Article is not pingable")
26
21
  false
27
22
  end
28
23
 
29
24
  def blog_allows_feedback?
30
25
  return true unless blog.global_pings_disable
31
- errors.add(:article, 'Pings are disabled')
26
+
27
+ errors.add(:article, "Pings are disabled")
32
28
  false
33
29
  end
34
30
 
@@ -1,20 +1,23 @@
1
- class Trigger < ActiveRecord::Base
1
+ # frozen_string_literal: true
2
+
3
+ class Trigger < ApplicationRecord
2
4
  belongs_to :pending_item, polymorphic: true
3
5
 
4
6
  class << self
5
- def post_action(due_at, item, method = 'came_due')
7
+ def post_action(due_at, item, method = "came_due")
6
8
  create!(due_at: due_at, pending_item: item,
7
9
  trigger_method: method)
8
10
  fire
9
11
  end
10
12
 
11
13
  def fire
12
- where('due_at <= ?', Time.now).destroy_all
14
+ where("due_at <= ?", Time.zone.now).destroy_all
13
15
  true
14
16
  end
15
17
 
16
18
  def remove(pending_item, conditions = {})
17
19
  return if pending_item.new_record?
20
+
18
21
  conditions = conditions.merge(pending_item_id: pending_item.id,
19
22
  pending_item_type: pending_item.class.to_s)
20
23
  where(conditions).delete_all
@@ -25,7 +28,7 @@ class Trigger < ActiveRecord::Base
25
28
  before_destroy :trigger_pending_item
26
29
 
27
30
  def trigger_pending_item
28
- pending_item.send(trigger_method) if pending_item
31
+ pending_item&.send(trigger_method)
29
32
  true
30
33
  end
31
34
  end
data/app/models/user.rb CHANGED
@@ -1,11 +1,13 @@
1
- require 'digest/sha1'
1
+ # frozen_string_literal: true
2
+
3
+ require "digest/sha1"
2
4
 
3
5
  # Publify user.
4
6
  # TODO: Should belong to a blog
5
- class User < ActiveRecord::Base
6
- ADMIN = 'admin'.freeze
7
- PUBLISHER = 'publisher'.freeze
8
- CONTRIBUTOR = 'contributor'.freeze
7
+ class User < ApplicationRecord
8
+ ADMIN = "admin"
9
+ PUBLISHER = "publisher"
10
+ CONTRIBUTOR = "contributor"
9
11
 
10
12
  # Include default devise modules. Others available are:
11
13
  # :confirmable, :lockable, :timeoutable and :omniauthable
@@ -13,14 +15,17 @@ class User < ActiveRecord::Base
13
15
  :recoverable, :rememberable, :trackable, :validatable
14
16
  include ConfigManager
15
17
 
16
- belongs_to :text_filter
17
- belongs_to :resource, optional: true
18
+ before_validation :set_default_profile
18
19
 
19
- delegate :name, to: :text_filter, prefix: true
20
+ validates :login, uniqueness: true, on: :create
21
+ validates :email, uniqueness: true, on: :create
22
+ validates :email, :login, presence: true
23
+ validates :login, length: { in: 3..40 }
20
24
 
21
- has_many :notifications, foreign_key: 'notify_user_id'
25
+ belongs_to :resource, optional: true
26
+ has_many :notifications, foreign_key: "notify_user_id"
22
27
  has_many :notify_contents, -> { uniq }, through: :notifications,
23
- source: 'notify_content'
28
+ source: "notify_content"
24
29
 
25
30
  has_many :articles
26
31
 
@@ -32,36 +37,38 @@ class User < ActiveRecord::Base
32
37
 
33
38
  # Settings
34
39
  setting :notify_watch_my_articles, :boolean, true
35
- setting :firstname, :string, ''
36
- setting :lastname, :string, ''
37
- setting :nickname, :string, ''
38
- setting :description, :string, ''
39
- setting :url, :string, ''
40
- setting :msn, :string, ''
41
- setting :aim, :string, ''
42
- setting :yahoo, :string, ''
43
- setting :twitter, :string, ''
44
- setting :jabber, :string, ''
45
- setting :admin_theme, :string, 'blue'
46
- setting :twitter_account, :string, ''
47
- setting :twitter_oauth_token, :string, ''
48
- setting :twitter_oauth_token_secret, :string, ''
49
- setting :twitter_profile_image, :string, ''
40
+ setting :firstname, :string, ""
41
+ setting :lastname, :string, ""
42
+ setting :nickname, :string, ""
43
+ setting :description, :string, ""
44
+ setting :url, :string, ""
45
+ setting :msn, :string, ""
46
+ setting :aim, :string, ""
47
+ setting :yahoo, :string, ""
48
+ setting :twitter, :string, ""
49
+ setting :jabber, :string, ""
50
+ setting :admin_theme, :string, "blue"
51
+ setting :twitter_account, :string, ""
52
+ setting :twitter_oauth_token, :string, ""
53
+ setting :twitter_oauth_token_secret, :string, ""
54
+ setting :twitter_profile_image, :string, ""
50
55
 
51
56
  # echo "publify" | sha1sum -
52
57
  class_attribute :salt
53
58
 
54
59
  def self.salt
55
- '20ac4d290c2293702c64b3b287ae5ea79b26a5c1'
60
+ "20ac4d290c2293702c64b3b287ae5ea79b26a5c1"
56
61
  end
57
62
 
58
63
  def first_and_last_name
59
- return '' unless firstname.present? && lastname.present?
64
+ return "" unless firstname.present? && lastname.present?
65
+
60
66
  "#{firstname} #{lastname}"
61
67
  end
62
68
 
63
69
  def display_names
64
- [:login, :nickname, :firstname, :lastname, :first_and_last_name].map { |f| send(f) }.delete_if(&:empty?)
70
+ [:login, :nickname, :firstname, :lastname, :first_and_last_name].
71
+ map { |f| send(f) }.delete_if(&:empty?)
65
72
  end
66
73
 
67
74
  # Authenticate users with old password hashes
@@ -75,23 +82,23 @@ class User < ActiveRecord::Base
75
82
  # Update old SHA1 password with new Devise ByCrypt password
76
83
  self.encrypted_password = password_digest(password)
77
84
  save
78
- return true
85
+ true
79
86
  else
80
87
  # If not BCrypt password and not old SHA1 password deny access
81
- return false
88
+ false
82
89
  end
83
90
  end
84
91
 
85
92
  def active_for_authentication?
86
- super && state == 'active'
93
+ super && state == "active"
87
94
  end
88
95
 
89
- def default_text_filter
90
- text_filter
96
+ def text_filter
97
+ TextFilter.make_filter(text_filter_name)
91
98
  end
92
99
 
93
100
  def self.to_prefix
94
- 'author'
101
+ "author"
95
102
  end
96
103
 
97
104
  def article_counter
@@ -118,6 +125,7 @@ class User < ActiveRecord::Base
118
125
 
119
126
  def update_twitter_profile_image(img)
120
127
  return if twitter_profile_image == img
128
+
121
129
  self.twitter_profile_image = img
122
130
  save
123
131
  end
@@ -126,16 +134,9 @@ class User < ActiveRecord::Base
126
134
  twitter_oauth_token.present? && twitter_oauth_token_secret.present?
127
135
  end
128
136
 
129
- protected
130
-
131
- before_validation :set_default_profile
137
+ private
132
138
 
133
139
  def set_default_profile
134
- self.profile ||= User.count.zero? ? 'admin' : 'contributor'
140
+ self.profile ||= User.count.zero? ? "admin" : "contributor"
135
141
  end
136
-
137
- validates :login, uniqueness: true, on: :create
138
- validates :email, uniqueness: true, on: :create
139
- validates :email, :login, presence: true
140
- validates :login, length: { in: 3..40 }
141
142
  end