clwiki 2.4.0 → 3.0.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 (239) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +19 -9
  3. data/app/controllers/cl_wiki/application_controller.rb +29 -1
  4. data/app/controllers/cl_wiki/page_controller.rb +52 -38
  5. data/app/controllers/cl_wiki/sessions_controller.rb +30 -0
  6. data/app/helpers/cl_wiki/application_helper.rb +3 -1
  7. data/app/models/cl_wiki/user.rb +89 -0
  8. data/app/views/cl_wiki/page/edit.html.erb +5 -1
  9. data/app/views/cl_wiki/page/recent.html.erb +1 -1
  10. data/app/views/cl_wiki/page/recent.rss.builder +10 -8
  11. data/app/views/cl_wiki/sessions/new.html.erb +10 -0
  12. data/config/clwiki.yml +16 -30
  13. data/config/initializers/clwiki.rb +4 -3
  14. data/config/routes.rb +9 -0
  15. data/lib/cl_wiki.rb +5 -1
  16. data/lib/cl_wiki/configuration.rb +28 -137
  17. data/lib/cl_wiki/engine.rb +3 -1
  18. data/lib/cl_wiki/file.rb +140 -117
  19. data/lib/cl_wiki/format/format.blockquote.rb +8 -6
  20. data/lib/cl_wiki/format/format.graphviz.digraph.rb +8 -7
  21. data/lib/cl_wiki/format/format.opml.rb +11 -9
  22. data/lib/cl_wiki/format/format.pre.blockquote.rb +8 -6
  23. data/lib/cl_wiki/format/format.simpletable.rb +10 -8
  24. data/lib/cl_wiki/memory_index.rb +102 -0
  25. data/lib/cl_wiki/page.rb +129 -257
  26. data/lib/cl_wiki/public_user.rb +9 -0
  27. data/lib/cl_wiki/user_base.rb +25 -0
  28. data/lib/cl_wiki/version.rb +3 -1
  29. data/lib/cl_wiki_lib.rb +9 -0
  30. data/lib/tasks/index.rake +4 -4
  31. data/test/dummy/app/assets/config/manifest.js +3 -0
  32. data/test/dummy/config/application.rb +1 -0
  33. data/test/dummy/config/environments/development.rb +2 -0
  34. data/test/dummy/config/initializers/clwiki.rb +3 -0
  35. data/test/dummy/config/routes.rb +3 -0
  36. data/test/dummy/log/development.log +5909 -0
  37. data/test/dummy/log/test.log +33349 -0
  38. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/-8/-8X-3n5w3EAS5uiBS2GQxjMlqD43Qout1GsSJUU6e4k.cache +1 -0
  39. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/-P/-Pa1BPD1Ps1OvnKPyrGE4MiUEnlzMEccXN8CzzxSRjM.cache +1 -0
  40. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/0k/0ktSefuSiZXp-1v5uXwST57lRoAF2HvHzclO4Gtftgo.cache +0 -0
  41. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/1V/1VmPI9-8O9Y8OP-JxSXl7-yNRMZHqapeh2drmkXiRGE.cache +1 -0
  42. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/2W/2WKPDryRtGzZO6Uedw4RNjnI5M9YVH-IbFg5GvLvTTQ.cache +0 -0
  43. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/3G/3GuA3P7RM10Vv7NgdH65pwfAH7gMHlJ_xBUO74i-ZjM.cache +0 -0
  44. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/3S/3SzCkB81tc9XbtFdEYxCeR3If141gvhEnHchU_C6hHs.cache +1 -0
  45. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/41/41dY2GtQJAt3CmkQn8IDa9B3clQaUT6XymanCfFZR2o.cache +0 -0
  46. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/46/46WEPovJzlkEgsdG0aV08HiNsRkf0L8Txt1SWLi4atg.cache +1 -0
  47. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/4I/4Ir0PJhTRUd9iGlSu6n2AREP-_amedFe4-1fKwB2wvg.cache +1 -0
  48. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/5L/5LXSsjTcB5Un8FHlrhi6AOjxwgzWoXeWBhU_hi1gdcg.cache +1 -0
  49. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/67/67V_0cxwrU68Onen7N2Lb9bTd1jLulH06F9zh1VgZ0U.cache +1 -0
  50. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/6A/6AXD3XLczHK8MPb5e10-7sLcS45ZrP7Iwgyo9xle0nU.cache +0 -0
  51. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/6D/6D8TdXG6KyMkGDvPbv87qUCDz9_6gRZbNAohojB484w.cache +1 -0
  52. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/7L/7LVfTxjfHpOSp2FeG-uhloqIUqIZ7uE3nT40dqhoqY8.cache +2 -0
  53. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/7b/7bceaEE3qsyoVjeou6RR-V9w2Wgzraq0OI2erU4s9ew.cache +1 -0
  54. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/7h/7hRfgp9EsoD33qh0aNXeyg9qdGapPlUT6FmcL8xztY4.cache +0 -0
  55. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/8c/8cq-JtJ9Zwg4F0bFdkqaGHjdB7a9JBmfDO_sczTWycI.cache +1 -0
  56. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/8h/8hO7EIQ5iOa2rL6ZlP318Lrk0unB2CfhHCI0TrUr-Oo.cache +0 -0
  57. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/8x/8x0PXM3vatUzVGk-vKi80S7LXrGb6bE-3EzEj54VNak.cache +1 -0
  58. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/9v/9vfh8eoLcnq3s_rolIXPs15SPTQWGxJrrjpJ3PoABek.cache +1 -0
  59. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/9w/9w-0hdVYmxONDHQlpGn7DFzlRA3oXqpW4x3t9LBUU6M.cache +1 -0
  60. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/B3/B385Es3x0hpGSQNWzSjiDcExPuEV9m1dUZWlEp5zGbw.cache +0 -0
  61. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/BR/BRBOvy22uVEx9Z5Aal_0BfPilVYEQl6AYXG2u8yBqBg.cache +0 -0
  62. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/BX/BXdNycvZI2UN7cgqvk6P4MQCc1PH2bTwa9i9vP-s-jk.cache +0 -0
  63. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/CO/CO-z80mMyQGRy-BwknxOV5bI2IFbcMMNc05j7v8Nqso.cache +0 -0
  64. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Cg/CgPqTXtSkCxEox0z95JfY89MndA2GhTTQK39fjKk6QU.cache +1 -0
  65. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Ct/CtQeoxqXfctXd_NvChnCVaJ_cCjNuXJMv3LBXhswU6A.cache +0 -0
  66. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Dc/DcZ_YfpX7rLYFw-u7jSJCRp_z0iIyB7XKOcwm1cQexk.cache +0 -0
  67. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Ex/Exqg59Ton1SZt_QH4hMa7wUFOAuIQnCan8B9578NzIg.cache +0 -0
  68. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/F5/F5c-QANC5X3kApAecuyiMZEme0NT_UUB6SjxKvb0ALg.cache +1 -0
  69. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Fd/FdwPBPhLtL4s8RSPhJ53YoYoFdRkNxANV_zQYw-KsVc.cache +1 -0
  70. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/GK/GKrbCoxDofzkQCmA17lE84OT6RW_6NKm7jwyZ4n2T6s.cache +0 -0
  71. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Gh/GhVuWwPtbWpQY_Ny4MyilnH9iUqCPxTDzOonAXM4od8.cache +1 -0
  72. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Gv/GvQrSgGYXiR-rgsPHFZq1oJ5zCkDK54muqIw6KW2GyA.cache +0 -0
  73. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Gw/Gwhhfk9vS7QWmHsW90WtAt0_Rp_7AIM-ZcHmEqLf_Rg.cache +1 -0
  74. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/H5/H5Yxi2VJxpyMb-cbgwBNua8O2zZ03Jk4ByV6yhIzAsQ.cache +0 -0
  75. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/I0/I0OpFIfCc595P02GZa3LUD1uD-Payl41dWaW3oZSK7g.cache +1 -0
  76. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/IQ/IQoDS19BmJjvixXd16O_7P6DB-GRUEZgdNJexJ88fIc.cache +1 -0
  77. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/I_/I_zDBUxxL4b2Wk9_qqVs56Abw1jGccc4FgvKwuscswQ.cache +1 -0
  78. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Ig/IgcuJMmmdeYrq2F3D721tC7ficyRm92HIrLkim5DCxQ.cache +1 -0
  79. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/JI/JITjXC3hXUPgOQhDYsVjhPNjtTISt0j5uz2bjfoiSHI.cache +1 -0
  80. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/KL/KL75rsyvMJSIkYkXRijxh8cs7V1wtfLPjuodISQK5vc.cache +0 -0
  81. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Kw/KwqVMeMNxvnaSP-a-H5nkYyxloW_xoqR5JhEnqJ9puQ.cache +1 -0
  82. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/L1/L1KghIbeezpqVDyhAbCDc4pG11ElC5JpUl319-ZlZn8.cache +0 -0
  83. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Lh/LhI7QMLwiVavmyvwYzdc_t_V9OATXaBO8aCB2swJFCk.cache +1 -0
  84. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Lh/LhqYyoCtzXpfZq6UOhmZuZLSaAwZRX44sHfwPvPqezc.cache +2 -0
  85. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Lo/Lovn2yBpV04WnAQwZeM3hLL015H5syYBH2ufgIc6qCM.cache +1 -0
  86. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Lz/LznMZWa43whMHpqnPRsbUfREY3y_fiXQKaiKVEYW4fw.cache +0 -0
  87. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/MC/MC7GYdrSShtV64GB3hoINaYL3vCRZKq9KvwcwrJAdQo.cache +1 -0
  88. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/MU/MU6iF1YPAQqpVK_kVAtiJPtbHaYpYdOcO0g5bJ9exj8.cache +0 -0
  89. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Md/MdIg3XLcnbFsMXC-6xslVtmBvWH7Q21BSt9l5pm305o.cache +0 -0
  90. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Mw/Mwfi5Xeky61jhIuc6ooo4439CHOyz1hS48_taMRSlKM.cache +1 -0
  91. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Ni/Ni5yuK9FFnhLe5HciROve12UIYstBdESWm0LfdcuVVs.cache +1 -0
  92. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Nz/Nz3hkLq4WlqgoHg_ChdHSXbP7fVmCWCTw0lH0jkMmDg.cache +0 -0
  93. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/O3/O38OvSNrhXKbxauuC8GOBBnKrt2-rPaDmfyrXScgHcA.cache +1 -0
  94. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/OS/OSm-zAlxXS63lBjvzJeSWfqq5d3D9fu-_nBVFWyQ4j0.cache +0 -0
  95. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Oa/Oazc9AJ4e_67dU0aArJeCNEeWJKMIFPtAJtxTJoUKcs.cache +1 -0
  96. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/PV/PVDpEMY_ha4kHETTb3QvjOBoBUP4PMjNDNcIAgmDy2I.cache +1 -0
  97. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Pl/PldDxSvU1o_UFPYTE0GJmUS9mHQXH88zEw5HN6GtlRE.cache +1 -0
  98. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Pu/PuU5S_LPnhAX43U1VVN3qP_sv0ph4stXSGo7I0e_jOw.cache +1 -0
  99. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/QJ/QJ6RPZNUkui_k3wTkb62zo8wczYY7q0B174GfSJjjWE.cache +2 -0
  100. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/QX/QXCyCL-Eeb3uHm9iOvs4anspZqeFbQnNyzDfIsXgzC8.cache +0 -0
  101. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/R1/R1F4Qf-kXTMH0fTLahalFTHtNBvgDfkOkrPyW8zeN_E.cache +0 -0
  102. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/R1/R1__Y-gz4zkDYrXWyCf6YTkvXO0RZlrpK6ynGGVuvnM.cache +0 -0
  103. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/R2/R2Xqb6eAeUW2xTaTaTjlkyUCirkb1qfYgW2CyY80VjM.cache +1 -0
  104. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/RM/RMXouh7GkRuhy8S6jnpxFD27HRVT0LEHj9iR53ps4o4.cache +1 -0
  105. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/RV/RVmt1mCn0tykR8xyBylvh-Hvi-Am87neA2IEkYHjg-g.cache +1 -0
  106. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Tg/TgTXCuKAEg1DI5zjHO8tGMGuQGC9BRt9vgDZj2FdSa8.cache +1 -0
  107. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/UI/UIyRfqj_T27DnyWJiZK9BdUGTIDTQ9M953ArtrYz5fM.cache +1 -0
  108. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/U_/U_F-o3fo7oUYyn0O5KBlt3jOF53X_-4UuZb-_alPZPk.cache +1 -0
  109. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/U_/U_KCsVrX_QoGJ_FpUpCNU3XMT36CThwu8_0HYj_2k4w.cache +1 -0
  110. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/U_/U_ie5WwVJPItNZrqfbIrnZpaRokYT5klrYU92QSugd8.cache +0 -0
  111. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Ub/Ub-oUCoAiliSW8ohVsmtsflc4nPeiBvcjzgNbPLYQRc.cache +0 -0
  112. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Ud/UdvIJcVNQ_08Vaoyx4KuRGNjazpB9-qjOtDMTud8R0Y.cache +1 -0
  113. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Uz/UzEG5I_EszWbaSVnk497D0KfuIzsgHoPLVQd7e3mlQg.cache +1 -0
  114. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/V-/V-F9X0mrPgfTELxk9xdYnb27trOmB6nBDL973YWeOfU.cache +0 -0
  115. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/VA/VAOOXmbiiPy1jqpQQCDVrhkByG3pdeJoZCOvVkp-XVY.cache +1 -0
  116. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/VV/VVIuIm_HUOaEdZfXt-CmFQZb3ycoiXeeI-FV7nwkr0Y.cache +1 -0
  117. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/VX/VXHQHhwOUBuWlKPY6smpXG1xjASw927lyjUKBXBh3e0.cache +0 -0
  118. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Vn/VnMqvZo9nqGF_5tt3gNbMyoG8jJVm0K0r1fANEBjfkw.cache +0 -0
  119. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/W1/W1YuEAoPMZTXfbxg_xWV9o2RP60SAKs5bhk7teKdL2g.cache +1 -0
  120. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/W2/W2ZyYMlYmyA7_1WcpiWhYUJa6wfPCZ5kZj_-Nuw31yM.cache +0 -0
  121. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Wg/WgwI9C5-mh_smtsTGVmH4y76T5ifM4M_hKL1fn-K8iw.cache +2 -0
  122. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/X5/X5GHIj6tnz-w7d-60OaYcbzJczzkTBtm24BOxzoSDdo.cache +1 -0
  123. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/X6/X6jU4SPOD_b1ks9tCApsvWRa7q8cBYCjw3gI6Dwvr34.cache +2 -0
  124. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/X8/X88lT-cwuuj8gqiNY83uVqXFgeLcaHMc9Xh2X4Iux6k.cache +0 -0
  125. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/XQ/XQ0aFc1cceisG4P8qUPhW8z1H3I71pMguVRRMgJ66cs.cache +5 -0
  126. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Xh/XhXLVYOEEwpzOBAWDdiCEpTMz7vC8wnlBHYHJkySh-0.cache +1 -0
  127. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/YB/YBJNyX7HNPq78obeHYRGnJKSVl9EtRPbcGD253-ia34.cache +0 -0
  128. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Yu/YupDX89OAJ6u3BHBW-UJgO3nDfi7hwlpf_JHlnM8b6k.cache +1 -0
  129. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/ZH/ZHN5sHdNMxUCl3Ese5T5_AzQbD9WHqpgBL4PBOrgXJY.cache +1 -0
  130. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/ZP/ZPRvYWthjzuQ0tqk5AdgQbeTUqhDboF8bvTtdrmg4Jo.cache +1 -0
  131. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/ZV/ZVu2Ed9wpdsPLKStP971oLEJBwgJQHLInXIiQkIWC04.cache +0 -0
  132. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Zb/ZbnyIl6znMAVquD2ZD5OYA9SPXmQJYWU7V8F2Hgp3Uc.cache +0 -0
  133. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Zj/ZjALwFkjfG3uebsyy_CeJp5VQMJLE03zxPxkNp-sZDA.cache +0 -0
  134. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/_F/_Fu404i1O4mKpjPluBsq-3FZQnyQvla_6jDnH03Lpw8.cache +2 -0
  135. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/a-/a-t90hz_PZnc6ImKhk-cIh_WBB9vi_rChKzLv4hMBqw.cache +1 -0
  136. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/a5/a5cnzGcRAu4dPakq4_DHH9GanK42Ov5O1F62oeJR4Zo.cache +1 -0
  137. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/aJ/aJK2kxoM9CsnZpxiFvP6RoP0sxHBiix9X1P6Mhy9Dcg.cache +2 -0
  138. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/aO/aOU10S2QEOBHcdKwGRfXqqHdYshmYD20LYiJIGMzIa0.cache +1 -0
  139. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/aZ/aZEdK7dgijyjIs26V_QbKsDgO5JxeYXiT0Sl28M0e-U.cache +0 -0
  140. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/aq/aqBnFJWuQ-xmdUL8_asWtElNRrMr0W60LVdDqpt43L8.cache +1 -0
  141. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/b5/b5KTv2Hrf5faN7X4XahT1s8L5t-EANtcFKrMEsGm3lw.cache +1 -0
  142. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/bF/bFemYCjG73k2_Ys77S7qNyW7CYcyw4bngyc0OGneI-s.cache +1 -0
  143. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/bG/bGdy8gJL8acOmxK8AbkYbxNuakf4LlMZ-zPBkyL0E-0.cache +1 -0
  144. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/bK/bKm8sxC3i0ycUMXr6pnD61MdwytUWfpNOJlBY6qJaWg.cache +1 -0
  145. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/dA/dA1M22RMQvVwb74tbFg-_237SferZuCI10s4R0zx8NI.cache +0 -0
  146. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/dF/dFOzXjFeRtB5bukRI9wGrh2O_GkOeBPnrJRMiv8_ZbM.cache +0 -0
  147. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/dw/dwbXKkD4yllXOeD4T7BKoGvLS26j9lxMkjMiIxfyt6E.cache +0 -0
  148. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/eT/eTgN8O1TgsFV61pclFzCmmJ9qT7MgyGvtQrmRtJoNeg.cache +0 -0
  149. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/eu/eu6Xg0psMCuHIWG0WjCo9wwNOlWs-Z5OH4SyGEmdTNQ.cache +1 -0
  150. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/fC/fC-TBNdh4rVupPn2ObyZeIx6OSlpBSBQZfIzywI6xx0.cache +0 -0
  151. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/fR/fRIbNtGTaNqdwIDyusrUmllglSGMNnqnw7VOLvf5D_k.cache +1 -0
  152. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/fq/fq7SFxQSEFZCuS7jQj0n-BQfbJ5mpLpmJQsd9mJVq68.cache +1 -0
  153. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/gG/gGBN3yxvq8azMjDv3hsSw_zLUj9KLuqHPDXZK8x8pFc.cache +0 -0
  154. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/gd/gd3J0EmNeiTh2GzxcAKItmtUnUay9NG4Sm2vkiLKvmA.cache +1 -0
  155. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/gj/gjXteWe57D8FaBOQUw29N_mwHCeTQW8oLjyv8fu3wNw.cache +3 -0
  156. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/gt/gtFeEhjHn0G9WhgiMKaNtXVgNYW9s_wBLE0VGegeAN8.cache +1 -0
  157. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/hA/hA4-M5cp310ZkSe59_BWszdgXy7mmYagSRCfelGBA9o.cache +1 -0
  158. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/iC/iC3FCadetljjEIeMWfeqqDoMxhJi6rI20BpiVxtvgS4.cache +1 -0
  159. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/iV/iV16_jyEayI_vLgHw3HFhtJAiVOCIlzFho0Yt7a4v_Y.cache +0 -0
  160. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/j6/j62KRIr4T81zq1Ujpg7AJRQdI0ry9HGKPt4nK6fRt1g.cache +1 -0
  161. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/jR/jRg0Zbr59-UMtrWO5t2VWNI3GqU7XWOUsE44dX5cPyk.cache +0 -0
  162. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/jj/jj9HUpCSrLEyONEZNLLkgJ8hJmxOCLpcVJeiBa0KDsE.cache +1 -0
  163. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/jq/jqnMk9arxuef2cdSQuxj3WOQuAfGKup3H2pjO7x1DOg.cache +0 -0
  164. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/k1/k14rvggyKI9dk-yVjn-Lk0p8qU360H_JuVG9aZ4q0OM.cache +1 -0
  165. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/kb/Kb8Z49kajAX1vyy5d4-gA8StHhQp5yOUs0wtdZ7m8Hc.cache +1 -0
  166. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/kb/kbEMkrgp2k0pezn_gFfMqA142QwoJYBKMj7cEkE-Hag.cache +1 -0
  167. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/lD/lDpZHp5gBhRdNHdj1TwWq1_LZ_a56lxeksxqaEs2efA.cache +1 -0
  168. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/mE/mEfGHxLvdPQrcbpjLw4q_wOPirMzrR4z58KgozQ1zNY.cache +1 -0
  169. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/mM/mMZ3DR5b7kx70JtEg-ImWOa_V1jnHcWgHqNqapxIMXk.cache +0 -0
  170. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/mX/mXCT6vriuTtwLaKGnTa5hwXSrwGtAmP6pV5lmjbHaYM.cache +0 -0
  171. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/mZ/mZjIy4zRS4hbS4vWHpdKd7jeZgLatEx_nlFqv_KSCrs.cache +0 -0
  172. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/mg/mge36-9r2gGuKcPoghbLDM72AV4gIVTl6gQDbk7hrkg.cache +1 -0
  173. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/nK/nKZaLuUqTl9pf5Nb1oVuabxd74q4oN8YTBeo6bNd-Vk.cache +0 -0
  174. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/nP/nPbHGaYfJSLZ2K3YTROe7T1RPqKoBQJwawQtZ_FN1-I.cache +0 -0
  175. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/o9/o9KyTznHG0ZIHDI7kTg1Jp78qaga7gJqouXSKdocEjA.cache +1 -0
  176. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/oB/oBupyQ9cW436mBji6Rp7TtHE6CX_r8iq2sCBo0LNbc8.cache +1 -0
  177. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/oN/oN3TypgxDDLqcxy0Funa4RVCYXS-7qn6D56wgBiUT2Q.cache +1 -0
  178. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/om/omGcA_eTFAFIH3RJaPOpEW3yz0074cob3hozQFLOAxk.cache +1 -0
  179. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/p0/p0WHrZZBaXbPaNj5XmQGTli4mi08Rv8DidQfwj28a6w.cache +0 -0
  180. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/pA/pAvUFBt71eJx7E7oQbIxrEZ8YcMo9kboyGxjk73ZWrI.cache +1 -0
  181. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/pB/pBwzUQUu-GcmLiQwn6KnbbDP0ipnVHzVaeArqdpqi98.cache +0 -0
  182. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/pC/pCePfKbmTQ6s2Tl7ki3oBput2ruhpCzpa6Vvejbb5xg.cache +1 -0
  183. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/q6/q6BYa32YJF11eGVapO4ouNl6gayPIsARgMavlzZmoi0.cache +0 -0
  184. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/qY/qY78GTTnufmP1eP2CE16x833zGfQ0F5EVCFtUTMQ7Mw.cache +1 -0
  185. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/qm/qmZZzCnL9PLIyZ0iBu6Alr69AUfHHI1fKdNRRgG04yg.cache +1 -0
  186. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/s5/s5yv3jYvjyKZJ8SMzpj94eMKEuX46lAWV1ApHF-6bsM.cache +1 -0
  187. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/sO/sOBPF_p4Te56V9vdLV0Ywn6djNbmdPSIzvgYNPnAXYc.cache +0 -0
  188. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/sv/sv0a_JAC4GSc_cK-2OUAzhFwm_K3qzSfDefwpcqOCk4.cache +1 -0
  189. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/sw/sw2EAksRkslJNoJJCTS2FPOfHWCYvsS86AxmRMPjens.cache +1 -0
  190. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/t1/t1cv6bP9cTAIs82lyIsnXGeAwB1KNVY5_5rgUvelr04.cache +0 -0
  191. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/tO/To1SPyNegqysLIqhSzrNQPh1VKKj19MespjJediCde4.cache +1 -0
  192. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/tO/tOPkZNrO9FRDhSlCf7VWOexxRq2CE2X4_6KjyxJkq2A.cache +0 -0
  193. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/tR/tRoxwnX8bACHK5pW9tIi4ILY4XuYTIpueH0fGr2t0rc.cache +1 -0
  194. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/t_/t_bP70PmOB70862dwKmCTkmZuzTqCreOzNYW4Yn2n6A.cache +1 -0
  195. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/uj/ujdE_ewC5UIxr6uw5F7YRfKKWiu8-15wzBlOjYHsnkQ.cache +1 -0
  196. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/ut/ut8uBMdgxX8_wfU0l6kGew6H8TLXAj74kFnaI252F3k.cache +1 -0
  197. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/ut/utQEOZtBKQK_bUUDeZX4Mgk00L4AOMVyq6zrKAoo1Xw.cache +0 -0
  198. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/vm/vmjBl9ZCF5hj4sG4e2nid94GcRQYmsOsu-_Q3Zlud5c.cache +0 -0
  199. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/vz/vzBoVc4GQWi4UFp-4dBJnzrhyUuokPV8SCOxsdpOht8.cache +0 -0
  200. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/wM/wMWxmf8BN_NAJRCyardukpfDMwts44Bz2a8doi-49Rg.cache +1 -0
  201. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/x7/x7KkTV3ibfIEysLB_ug5bfmnn2VLV_BldukPR3EoPBk.cache +0 -0
  202. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/x7/x7iSOdqAIVmVpn9ujTwJ_C7EqUgmMSri5vjjHdRIX10.cache +1 -0
  203. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/xY/xYdD9O1JRIfpVj9Kw_b3JTUBQZLI_dcy-bf9uXEp-jg.cache +0 -0
  204. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/xx/xxkulLgT-tkVeDC50gUXRGGMou47BUdlYOwgs0j5muY.cache +1 -0
  205. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/yn/yn_3aZZwyjcI0O6fwisZ7zvcu4Gq5bV31g3tHFxfQNg.cache +1 -0
  206. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/yq/yqwjyepbYY4ctoMOySWiOIWUYwzl_BczAmXqJ5DPvb0.cache +0 -0
  207. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/z9/z9HQmzff5j_6CFyk6eQ52nYt9cPLXsxDQY0Yep1Hz-0.cache +1 -0
  208. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/zM/zMvcc87IG1SRbqwUNtWQfHgeWr5XN36OU8vg-v3rUus.cache +0 -0
  209. data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/zn/znjQpjNzh1iUAe9DljeFghnStRvqNIr1GuOTibVcEJQ.cache +0 -0
  210. data/test/dummy/tmp/testrep/BazQuux.txt +5 -0
  211. data/test/dummy/tmp/testrep/FooBar.txt +5 -0
  212. data/test/dummy/tmp/testrep/NewPage.txt +5 -0
  213. data/test/dummy/tmp/testrep/users/testy.json +1 -0
  214. data/test/dummy/tmp/wikirep/FrontPage.txt +5 -0
  215. data/test/dummy/tmp/wikirep/users/chrismo.json +1 -0
  216. data/test/dummy/wikirep/EncryptedPage.txt +0 -0
  217. data/test/dummy/wikirep/FrontPage.txt +11 -4
  218. data/test/dummy/wikirep/users/chrismo.json +1 -0
  219. data/test/helpers/wiki_helper_test.rb +2 -0
  220. data/test/lib/clwiki/clwiki_test_helper.rb +19 -2
  221. data/test/lib/clwiki/file_owner_test.rb +58 -0
  222. data/test/lib/clwiki/file_test.rb +85 -56
  223. data/test/lib/clwiki/memory_index_test.rb +61 -0
  224. data/test/lib/clwiki/page_test.rb +71 -148
  225. data/test/lib/clwiki/test_base.rb +19 -19
  226. data/test/test_helper.rb +7 -5
  227. metadata +398 -23
  228. data/lib/cl_wiki/find_in_file.rb +0 -33
  229. data/lib/cl_wiki/index.rb +0 -458
  230. data/lib/cl_wiki/tools/cron.reminders.rb +0 -241
  231. data/lib/cl_wiki/tools/movepages.rb +0 -27
  232. data/lib/cl_wiki/tools/pagestomove.txt +0 -56
  233. data/lib/cl_wiki/tools/rublog/clWiki.rb +0 -62
  234. data/lib/cl_wiki/tools/rublog/readme.txt +0 -2
  235. data/lib/cl_wiki/tools/singlepage.rb +0 -58
  236. data/lib/cl_wiki/tools/test/singlepagetest.rb +0 -9
  237. data/lib/cl_wiki/tools/thunderbird.rb +0 -23
  238. data/test/lib/clwiki/find_in_file_test.rb +0 -111
  239. data/test/lib/clwiki/index_test.rb +0 -32
@@ -1,12 +1,14 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class FormatBlockquote < ClWiki::CustomFormatter
2
- def FormatBlockquote.match_re
3
- /\[\].*\[\/\]/m
4
+ def self.match_re
5
+ %r{\[\].*\[/\]}m
4
6
  end
5
-
6
- def FormatBlockquote.format_content(content, page)
7
+
8
+ def self.format_content(content, page)
7
9
  if content
8
- content.gsub!(/\[\]/, "<blockquote>")
9
- content.gsub!(/\[\/\]/, "</blockquote>")
10
+ content.gsub!(/\[\]/, '<blockquote>')
11
+ content.gsub!(%r{\[/\]}, '</blockquote>')
10
12
  content
11
13
  end
12
14
  end
@@ -1,14 +1,15 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class FormatGraphVizDiGraph < ClWiki::CustomFormatter
2
- def FormatGraphVizDiGraph.match_re
4
+ def self.match_re
3
5
  /digraph.*\}/m
4
6
  end
5
-
6
- def FormatGraphVizDiGraph.format_content(content, page)
7
+
8
+ def self.format_content(content, page)
7
9
  content.sub!(/digraph.*\}/m,
8
- '<a href="dot.rb?fn=' + page.fileFullPathAndName + '">' +
9
- '<img src="dot.rb?fn=' + page.fileFullPathAndName + '">' +
10
- '</a>'
11
- )
10
+ "<a href=\"dot.rb?fn=#{page.file_full_path_and_name}\">
11
+ <img src=\"dot.rb?fn=#{page.file_full_path_and_name}\">
12
+ </a>")
12
13
  content
13
14
  end
14
15
  end
@@ -1,16 +1,18 @@
1
- if __FILE__ == $0
2
- $LOAD_PATH << ".."
1
+ # frozen_string_literal: true
2
+
3
+ if $PROGRAM_NAME == __FILE__
4
+ $LOAD_PATH << '..'
3
5
  require 'clwikipage'
4
6
  end
5
-
7
+
6
8
  class FormatOPML < ClWiki::CustomFormatter
7
- def FormatOPML.match_re
8
- /<opml.*?>.*?<\/opml>/m
9
+ def self.match_re
10
+ %r{<opml.*?>.*?</opml>}m
9
11
  end
10
-
11
- def FormatOPML.format_content(content, page)
12
+
13
+ def self.format_content(content, page)
12
14
  out = ['<NoWikiLinks>']
13
- content.grep(/<outline.*?>|<\/outline>/).each do |ln|
15
+ content.grep(%r{<outline.*?>|</outline>}).each do |ln|
14
16
  title = ln.scan(/title=\"(.*?)\"/).compact
15
17
  html = ln.scan(/htmlUrl=\"(.*?)\"/).compact
16
18
  xml = ln.scan(/xmlUrl=\"(.*?)\"/).compact
@@ -31,7 +33,7 @@ end
31
33
 
32
34
  ClWiki::CustomFormatters.instance.register(FormatOPML)
33
35
 
34
- if __FILE__ == $0
36
+ if $PROGRAM_NAME == __FILE__
35
37
  sample_opml = <<-OPMLTEXT
36
38
  <opml xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
37
39
  <head>
@@ -1,14 +1,16 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'cgi'
2
4
 
3
5
  class FormatPreBlockquote < ClWiki::CustomFormatter
4
- def FormatPreBlockquote.match_re
5
- /\[p\].*?\[\/p\]/mi
6
+ def self.match_re
7
+ %r{\[p\].*?\[/p\]}mi
6
8
  end
7
-
8
- def FormatPreBlockquote.format_content(content, page)
9
+
10
+ def self.format_content(content, page)
9
11
  content = CGI.escapeHTML(content)
10
- content.gsub!(/\[p\]/i, "<blockquote><pre>")
11
- content.gsub!(/\[\/p\]/i, "</pre></blockquote>")
12
+ content.gsub!(/\[p\]/i, '<blockquote><pre>')
13
+ content.gsub!(%r{\[/p\]}i, '</pre></blockquote>')
12
14
  end
13
15
  end
14
16
 
@@ -1,24 +1,26 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class FormatSimpleTable < ClWiki::CustomFormatter
2
- def FormatSimpleTable.match_re
3
- /<simpletable.*?>.*?<\/simpletable>/m
4
+ def self.match_re
5
+ %r{<simpletable.*?>.*?</simpletable>}m
4
6
  end
5
-
6
- def FormatSimpleTable.format_content(content, page=nil)
7
+
8
+ def self.format_content(content, page = nil)
7
9
  table_attr = content.scan(/<simpletable(.*?)>/m).to_s.strip
8
10
  table_attr = 'border="1"' if table_attr.empty?
9
11
  content.gsub!(/<simpletable.*?>/m, '')
10
- content.gsub!(/<\/simpletable>/m, '')
12
+ content.gsub!(%r{</simpletable>}m, '')
11
13
  content.strip!
12
14
  lines = content.split("\n")
13
15
  lines.collect! do |ln|
14
16
  ln.gsub!(/\t/, ' ')
15
17
  '<tr><td>' + ln.gsub(/ +/, '</td><td>') + '</td></tr>'
16
18
  end
17
- lines.collect! do |ln| ln.gsub(/<td>\s*?<\/td>/, '<td>&nbsp;</td>') end
19
+ lines.collect! { |ln| ln.gsub(%r{<td>\s*?</td>}, '<td>&nbsp;</td>') }
18
20
 
19
21
  # if you do a .join("\n"), then the \n will be converted to <br>
20
- # ... so don't do that
21
- "<table #{table_attr}>\n" + lines.join("") + "</table>"
22
+ # ... so don't do that
23
+ "<table #{table_attr}>\n#{lines.join('')}</table>"
22
24
  end
23
25
  end
24
26
 
@@ -0,0 +1,102 @@
1
+ # frozen_string_literal: true
2
+
3
+ gem 'clindex'
4
+ require 'index'
5
+
6
+ module ClWiki
7
+ class MemoryIndexer
8
+ attr_reader :index, :pages
9
+
10
+ WAIT = true
11
+
12
+ def self.instance(page_owner: PublicUser.new)
13
+ @instance ||= self.new(page_owner: page_owner)
14
+ end
15
+
16
+ def initialize(page_owner: PublicUser.new)
17
+ @page_owner = page_owner
18
+
19
+ @wiki_conf = $wiki_conf
20
+ @root_dir = @wiki_conf.wiki_path
21
+
22
+ @index = ClIndex.new
23
+ @recent = ClIndex.new
24
+ @pages = ClIndex.new
25
+
26
+ build
27
+ end
28
+
29
+ def recent(top = -1, text: '')
30
+ pages_desc_mtime = @recent.do_read(WAIT) do
31
+ hash = @recent.index
32
+ hash.sort { |a, b| b[0] <=> a[0] }
33
+ end.map { |_, page_names| page_names }.flatten
34
+
35
+ if text && !text.empty?
36
+ hit_page_names = search(text)
37
+ pages_desc_mtime &= hit_page_names
38
+ end
39
+
40
+ pages_desc_mtime[0..top]
41
+ end
42
+
43
+ def search(text, titles_only: false)
44
+ terms = text.split(' ')
45
+ all_hits = []
46
+ terms.each do |term|
47
+ term_hits = []
48
+ @index.search(term, term_hits, WAIT)
49
+ term_hits.flatten!
50
+ all_hits = all_hits.empty? ? term_hits : all_hits & term_hits
51
+ end
52
+ all_hits.flatten!
53
+ all_hits.uniq!
54
+ all_hits.sort!
55
+ all_hits.delete_if { |name| name !~ /#{text}/i } if titles_only
56
+ all_hits
57
+ end
58
+
59
+ def page_exists?(full_name)
60
+ @pages.term_exists?(full_name, WAIT)
61
+ end
62
+
63
+ def reindex_page(page_name)
64
+ remove_page_from_index(page_name)
65
+ index_page(page_name)
66
+ end
67
+
68
+ private
69
+
70
+ def build
71
+ files = Dir[::File.join(@root_dir, '**/*' + ClWiki::FILE_EXT)]
72
+ files.each do |fn|
73
+ next unless ::File.file?(fn)
74
+
75
+ page_name = ::File.basename(fn, ClWiki::FILE_EXT)
76
+ index_page(page_name)
77
+ end
78
+ end
79
+
80
+ def index_page(page_name)
81
+ pg = ClWiki::Page.new(page_name, wiki_path: @root_dir, owner: @page_owner)
82
+ pg.read_raw_content
83
+ formatter = ClWiki::PageFormatter.new(pg.raw_content, page_name)
84
+ formatter.format_links { |word| @index.add(word.downcase, page_name, WAIT) }
85
+
86
+ add_to_indexes(pg)
87
+ end
88
+
89
+ def add_to_indexes(page)
90
+ @index.add(page.page_name, page.page_name, WAIT)
91
+ @pages.add(page.page_name, nil, WAIT)
92
+
93
+ @recent.remove(page.page_name, WAIT)
94
+ @recent.add(page.mtime.strftime('%Y-%m-%dT%H:%M:%S'), page.page_name, WAIT)
95
+ end
96
+
97
+ def remove_page_from_index(page_name)
98
+ @index.remove(page_name, WAIT)
99
+ @recent.remove(page_name, WAIT)
100
+ end
101
+ end
102
+ end
@@ -1,99 +1,80 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'cgi'
2
4
  require 'singleton'
3
5
 
4
- require File.dirname(__FILE__) + '/file'
5
- require File.dirname(__FILE__) + '/find_in_file'
6
-
7
- $FIND_PAGE_NAME = "Find"
8
- $FIND_RESULTS_NAME = "Find Results"
9
-
10
6
  module ClWiki
11
7
  class Page
12
- attr_reader :content, :mtime, :name, :full_name, :pagePath, :raw_content,
13
- :fileFullPathAndName
14
-
15
- @@wikiIndexClient = nil
8
+ attr_reader :content, :mtime, :name, :page_name, :raw_content,
9
+ :file_full_path_and_name
16
10
 
17
- #Refactor clwikifile out of here into a storage class that will
18
- # require in the appropriate storage file clwikifile, clwikisql
11
+ def initialize(page_name, wiki_path: $wiki_conf.wiki_path, owner: PublicUser.new)
12
+ raise "Fix this - no slashes! #{page_name}" if %r{/}.match?(page_name)
19
13
 
20
- # refactor away wikiPath ... should be taken care of elsewhere, otherwise
21
- # ClWiki must know it, and it should be storage independent
22
- def initialize(fullName, wiki_path=$wiki_path)
23
- @full_name = fullName
14
+ @page_name = page_name
24
15
  @wiki_path = wiki_path
25
- @wikiFile = ClWiki::File.new(@full_name, @wiki_path)
26
- @pagePath = @wikiFile.pagePath
27
- @name = @wikiFile.name
16
+ @owner = owner
17
+ @wiki_file = ClWiki::File.new(@page_name, @wiki_path, owner: @owner)
18
+ @name = @wiki_file.name
28
19
  end
29
20
 
30
- # <pre> text in 1.13.2 had extra line feeds, because the \n were xformed to
31
- # <br>\n, which results in two line feeds when rendered by Mozilla.
32
- # The change a few versions ago inside convert_newline_to_br which started
33
- # converting \n to <br>\n is the culprit here. I did this for more readable
34
- # html, but that does screw up <pre> sections, so it's put back now.
35
21
  def convert_newline_to_br
36
- new_content = ""
37
- insideHtmlTags = false
22
+ new_content = ''
23
+ inside_html_tags = false
38
24
  @content.each_line do |substr|
39
- insideHtmlTags = true if (substr =~ /#{'<html>'}/)
40
- insideHtmlTags = false if (substr =~ /#{'</html>'}/)
41
- if ((!ClWiki::PageFormatter.only_html(substr)) or (substr == "\n")) and !insideHtmlTags
42
- new_content = new_content + substr.gsub(/\n/, "<br>")
43
- else
44
- new_content = new_content + substr
45
- end
25
+ inside_html_tags = true if /<html>/.match?(substr)
26
+ inside_html_tags = false if /<\/html>/.match?(substr)
27
+ new_content += if (!ClWiki::PageFormatter.only_html(substr) || (substr == "\n")) && !inside_html_tags
28
+ substr.gsub(/\n/, '<br>')
29
+ else
30
+ substr
31
+ end
46
32
  end
47
33
  @content = new_content
48
34
  end
49
35
 
50
- def self.wikiIndexClient
51
- @@wikiIndexClient = ClWikiIndexClient.new if !@@wikiIndexClient
52
- @@wikiIndexClient
36
+ def is_new?
37
+ @wiki_file.has_default_content?
53
38
  end
54
39
 
55
40
  def read_raw_content
56
- @raw_content = @wikiFile.content.join.gsub(/\r\n/, "\n")
41
+ @raw_content = @wiki_file.content
57
42
  read_page_attributes
58
- ClWiki::Page.wikiIndexClient.add_hit(@full_name) if $wiki_conf.access_log_index
59
- end
60
-
61
- def content_never_edited?
62
- @wikiFile.content_is_default?
63
43
  end
64
44
 
65
45
  def delete
66
- @wikiFile.delete
46
+ @wiki_file.delete
67
47
  end
68
48
 
69
- def self.read_file_full_path_and_name(full_name, wiki_path=$wiki_path)
70
- wiki_file = ClWikiFile.new(full_name, wiki_path, $wikiPageExt, false)
71
- wiki_file.fullPathAndName
49
+ def read_page_attributes
50
+ wiki_file = @wiki_file
51
+ @mtime = wiki_file.mod_time_at_last_read
52
+
53
+ # TODO: kill this - not needed except in graphviz renderer?
54
+ @file_full_path_and_name = wiki_file.full_path_and_name
72
55
  end
73
56
 
74
- def read_page_attributes
75
- wikiFile = @wikiFile # ClWikiFile.new(@fullName, @wikiPath)
76
- @mtime = wikiFile.modTimeAtLastRead
77
- @fileFullPathAndName = wikiFile.fullPathAndName
57
+ def content_encrypted?
58
+ @wiki_file.content_encrypted?
78
59
  end
79
60
 
80
61
  def read_raw_content_with_forwarding(full_page_name)
81
62
  stack = []
82
63
  history = []
83
- content = ''
64
+ content = String.new
84
65
  final_page_name = full_page_name
85
66
  stack.push(full_page_name)
86
- while !stack.empty?
67
+ until stack.empty?
87
68
  this_pg_name = stack.pop
88
69
  if history.index(this_pg_name)
89
70
  pg_content = '-= CIRCULAR FORWARDING DETECTED =-'
90
71
  else
91
- pg = ClWiki::Page.new(this_pg_name)
72
+ pg = ClWiki::Page.new(this_pg_name, owner: @owner)
92
73
  pg.read_raw_content
93
74
  pg_content = pg.raw_content
94
75
  fwd_full_page_name = get_forward_ref(pg_content)
95
76
  if fwd_full_page_name
96
- pg_content = "Auto forwarded from #{this_pg_name.strip_slash_prefix}<br><br>#{fwd_full_page_name}<br><br>"
77
+ pg_content = "Auto forwarded from #{this_pg_name}<br><br>#{fwd_full_page_name}<br><br>"
97
78
  stack.push fwd_full_page_name
98
79
  else
99
80
  final_page_name = this_pg_name
@@ -105,24 +86,22 @@ module ClWiki
105
86
  [content, final_page_name]
106
87
  end
107
88
 
108
- def read_content(include_header_and_footer=true, include_diff=false)
89
+ def read_content(include_header_and_footer = true, include_diff = false)
109
90
  read_page_attributes
110
- @content, final_page_name = read_raw_content_with_forwarding(@full_name)
91
+ @content, final_page_name = read_raw_content_with_forwarding(@page_name)
111
92
  process_custom_renderers
112
93
  convert_newline_to_br
113
94
  f = ClWiki::PageFormatter.new(@content, final_page_name)
114
- @content = "<div class='wikiBody'>#{f.formatLinks}</div>"
115
- if include_header_and_footer
116
- @content = get_header + @content + get_footer
117
- end
118
- @content = CLabs::WikiDiffFormatter.format_diff(@wikiFile.diff) + @content if include_diff
95
+ @content = "<div class='wikiBody'>#{f.format_links}</div>"
96
+ @content = get_header + @content + get_footer if include_header_and_footer
97
+ @content = CLabs::WikiDiffFormatter.format_diff(@wiki_file.diff) + @content if include_diff
119
98
  @content
120
99
  end
121
100
 
122
101
  def process_custom_renderers
123
102
  root_dirs = [::File.join(::File.dirname(__FILE__), 'format')] + $wiki_conf.custom_formatter_load_path
124
103
  root_dirs.each do |root_dir|
125
- Dir[::File.join(root_dir, 'format.*')].each do |fn|
104
+ Dir[::File.join(root_dir, 'format.*')].sort.each do |fn|
126
105
  require fn
127
106
  end
128
107
  end
@@ -131,91 +110,77 @@ module ClWiki
131
110
  end
132
111
 
133
112
  def get_header
134
- f = ClWiki::PageFormatter.new(nil, @full_name)
135
- f.header(@full_name, self)
113
+ ClWiki::PageFormatter.new(nil, @page_name).header(@page_name, self)
136
114
  end
137
115
 
138
116
  def get_footer
139
- f = ClWiki::PageFormatter.new(nil, @full_name)
140
- f.footer(self)
117
+ ClWiki::PageFormatter.new(nil, @page_name).footer(self)
141
118
  end
142
119
 
143
120
  def get_forward_ref(content)
144
121
  content_ary = content.split("\n")
145
122
  res = (content_ary.collect { |ln| ln.strip.empty? ? nil : ln }.compact.length == 1)
146
- if res
147
- res = content_ary[0] =~ /^see (.*)/i
148
- end
123
+ res = content_ary[0] =~ /^see (.*)/i if res
149
124
 
150
125
  if res
151
- page_name = $1
152
- f = ClWiki::PageFormatter.new(content, @full_name)
126
+ page_name = Regexp.last_match(1)
127
+ f = ClWiki::PageFormatter.new(content, @page_name)
153
128
  res = f.is_wiki_name?(page_name)
154
- if res
155
- res = ClWiki::Page.page_exists?(page_name)
156
- end
157
- end
158
- if res
159
- page_name
160
- else
161
- nil
129
+ res = ClWiki::Page.page_exists?(page_name) if res
162
130
  end
131
+ page_name if res
163
132
  end
164
133
 
165
- def update_content(newcontent, mtime)
166
- wikiFile = @wikiFile # ClWikiFile.new(@fullName, @wikiPath)
167
- wikiFile.clientLastReadModTime = mtime
168
- wikiFile.content = newcontent
169
- if $wiki_conf.useIndex != ClWiki::Configuration::USE_INDEX_NO
170
- wikiIndexClient = ClWiki::IndexClient.new
171
- wikiIndexClient.reindex_page_and_save_async(@full_name)
172
- end
134
+ def update_content(new_content, mtime, encrypt = false)
135
+ @wiki_file.client_last_read_mod_time = mtime
136
+ encrypt ? @wiki_file.encrypt_content! : @wiki_file.do_not_encrypt_content!
137
+ @wiki_file.content = new_content
138
+ ClWiki::MemoryIndexer.instance(page_owner: @owner).reindex_page(@page_name)
173
139
  end
174
140
 
141
+ # TODO: if this is the 1st time the index is instantiated, it won't have owner.
142
+ # and this will blow up waaay down the stack as it tries to do all of the indexing
143
+ # without an owner.
144
+ #
145
+ # For this query, however, it doesn't need owner, since it's just looking for
146
+ # existence. Hmmm. The index could be lazy-loaded, with names and metadata
147
+ # first, and not content if owner doesn't match. But ... I dunno.
175
148
  def self.page_exists?(page_name)
176
- if ($wiki_conf.useIndex != ClWiki::Configuration::USE_INDEX_NO) &&
177
- ($wiki_conf.useIndexForPageExists)
178
- res = ClWiki::Page.wikiIndexClient.page_exists?(page_name)
179
- else
180
- wiki_file = ClWiki::File.new(page_name, $wiki_path, $wikiPageExt, false)
181
- res = wiki_file.file_exists?
182
- end
183
- res
149
+ ClWiki::MemoryIndexer.instance.page_exists?(page_name)
184
150
  end
185
151
  end
186
152
 
187
153
  class PageFormatter
154
+ FIND_PAGE_NAME = 'Find'
155
+ FIND_RESULTS_NAME = 'Find Results'
156
+
157
+ attr_reader :full_name
188
158
  attr_accessor :content
189
159
 
190
- def initialize(content=nil, aFullName=nil)
160
+ def initialize(content = nil, full_name = nil)
191
161
  @content = content
192
- self.fullName = aFullName
193
- @wikiIndex = nil
162
+ self.full_name = full_name
163
+ @wiki_index = nil
194
164
  end
195
165
 
196
- def fullName=(value)
166
+ def full_name=(value)
197
167
  @full_name = value
198
168
  if @full_name
199
169
  @full_name = @full_name[1..-1] if @full_name[0..1] == '//'
200
170
  end
201
171
  end
202
172
 
203
- def fullName
204
- @full_name
205
- end
206
-
207
173
  def header(full_page_name, page = nil)
208
174
  search_text = ::File.basename(full_page_name)
209
175
  page_path, page_name = ::File.split(full_page_name)
210
176
  page_path = '/' if page_path == '.'
211
177
  dirs = page_path.split('/')
212
178
  dirs = dirs[1..-1] if !dirs.empty? && dirs[0].empty?
213
- full_dirs = (0..dirs.length-1).each { |i| full_dirs[i] = ('/' + dirs[0..i].join('/')) }
214
- head = '<div class=\'wikiHeader\'>'
215
- if (full_page_name != $FIND_PAGE_NAME) and
216
- (full_page_name != $FIND_RESULTS_NAME) and
217
- (full_page_name != $wiki_conf.recent_changes_name) and
218
- (full_page_name != $wiki_conf.stats_name)
179
+ full_dirs = (0..dirs.length - 1).each { |i| full_dirs[i] = ('/' + dirs[0..i].join('/')) }
180
+ head = String.new('<div class=\'wikiHeader\'>')
181
+ if [FIND_PAGE_NAME, FIND_RESULTS_NAME].include?(full_page_name)
182
+ head << "<span class='pageName'>#{full_page_name}</span>"
183
+ else
219
184
  head << "<span class='pageName'><a href='find?search_text=#{search_text}'>#{page_name}</a></span><br/>"
220
185
  full_dirs.each do |dir|
221
186
  head << '<span class=\'pageTag\'>'
@@ -223,8 +188,6 @@ module ClWiki
223
188
  end
224
189
  head << '<br/>'
225
190
  head << "<span class='wikiPageData'>#{page_update_time(page)}</span><br/>" if page
226
- else
227
- head << '<span class=\'pageName\'>' + full_page_name + '</span>'
228
191
  end
229
192
  head << '</div>'
230
193
  end
@@ -240,7 +203,7 @@ module ClWiki
240
203
  end
241
204
 
242
205
  def process_custom_footers(page)
243
- Dir[::File.dirname(__FILE__) + '/footer/footer.*'].each do |fn|
206
+ Dir["#{::File.dirname(__FILE__)}/footer/footer.*"].sort.each do |fn|
244
207
  require fn
245
208
  end
246
209
 
@@ -248,102 +211,70 @@ module ClWiki
248
211
  end
249
212
 
250
213
  def footer(page)
251
- return '' if !page.is_a? ClWiki::Page # blogki does this
214
+ return String.new unless page.is_a? ClWiki::Page
252
215
 
253
216
  custom_footer = process_custom_footers(page)
254
217
 
255
- wiki_name = page.full_name
218
+ wiki_name = page.page_name
256
219
 
257
220
  # refactor string constants
258
- footer = "<div class='wikiFooter'>"
259
- footer << "<ul>"
260
- if (wiki_name != $FIND_PAGE_NAME) and
261
- (wiki_name != $FIND_RESULTS_NAME) and
262
- (wiki_name != $wiki_conf.recent_changes_name) and
263
- (wiki_name != $wiki_conf.stats_name)
264
- if $wiki_conf.editable
265
- footer << ("<li><span class='wikiAction'><a href='" + wiki_name.strip_slash_prefix + "/edit'>Edit</a></span></li>")
221
+ footer = String.new("<div class='wikiFooter'>")
222
+ footer << '<ul>'
223
+ if $wiki_conf.editable
224
+ unless [FIND_PAGE_NAME, FIND_RESULTS_NAME].include?(wiki_name)
225
+ footer << "<li><span class='wikiAction'><a href='#{wiki_name}/edit'>Edit</a></span></li>"
266
226
  end
267
227
  end
268
228
  footer << "<li><span class='wikiAction'><a href='find'>Find</a></span></li>"
269
229
  footer << "<li><span class='wikiAction'><a href='recent'>Recent</a></span></li>"
270
- # footer << "<li><span class='wikiAction'><a href=#{cgifn}?about=true>About</a></span></li>" if wiki_name == "/FrontPage"
271
- footer << "</ul></div>"
272
- return custom_footer << footer
230
+ footer << '</ul></div>'
231
+ custom_footer << footer
273
232
  end
274
233
 
275
234
  def src_url
276
235
  "file://#{ClWiki::Page.read_file_full_path_and_name(@full_name)}"
277
236
  end
278
237
 
279
- def reload_url(with_global_edit_links=false)
238
+ def reload_url(with_global_edit_links = false)
280
239
  result = "#{full_url}?page=#{@full_name}"
281
- if with_global_edit_links
282
- result << "&globaledits=true"
283
- else
284
- result << "&globaledits=false"
285
- end
240
+ result << (with_global_edit_links ? '&globaledits=true' : '&globaledits=false')
286
241
  end
287
242
 
288
243
  def mailto_url
289
244
  "mailto:?Subject=wikifyi:%20#{@full_name}&Body=#{reload_url}"
290
245
  end
291
246
 
292
- def gsubWords
293
- @content.gsub(/<.+?>|<\/.+?>|\w+/) { |word| yield word }
294
- end
295
-
296
- def convert_relative_wikinames_to_absolute
297
- # do not go ahead without testing here
298
- #formatLinks do |word|
299
- # if isWikiName?(word)
300
- #end
301
-
302
- # problem here is we should obey the NoWikiLinks and Html tag rules,
303
- # and those variables aren't being yielded right now. If we change
304
- # how the yield works, it affects the indexer. And we can't just
305
- # tack on additional yield params and have existing code that only
306
- # pays attention to the first keep working:
307
- #
308
- # irb(main):001:0> def test
309
- # irb(main):002:1> yield 1,2,3
310
- # irb(main):003:1> end
311
- # nil
312
- # irb(main):004:0> test do |a|
313
- # irb(main):005:1* puts a
314
- # irb(main):006:1> end
315
- # 1
316
- # 2
317
- # 3
247
+ def gsub_words
248
+ @content.gsub(%r{<.+?>|</.+?>|\w+}) { |word| yield word }
318
249
  end
319
250
 
320
- def formatLinks
251
+ def format_links
321
252
  no_wiki_link_in_effect = false
322
253
  inside_html_tags = false
323
254
 
324
- gsubWords do |word|
325
- if (word[0, 1] == '<') and (word[-1, 1] == '>')
255
+ gsub_words do |word|
256
+ if (word[0, 1] == '<') && (word[-1, 1] == '>')
326
257
  # refactor to class,local constant, instead of global
327
- if word =~ /#{'<NoWikiLinks>'}/i
258
+ if /<NoWikiLinks>/i.match?(word)
328
259
  no_wiki_link_in_effect = true
329
260
  word = ''
330
261
  # refactor to class,local constant, instead of global
331
- elsif word =~ /#{'</NoWikiLinks>'}/i
262
+ elsif /<\/NoWikiLinks>/i.match?(word)
332
263
  no_wiki_link_in_effect = false
333
264
  word = ''
334
265
  end
335
266
 
336
- if word =~ /#{'<html>'}/i
267
+ if /<html>/i.match?(word)
337
268
  inside_html_tags = true
338
269
  word = ''
339
- elsif word =~ /#{'</html>'}/i
270
+ elsif /<\/html>/i.match?(word)
340
271
  inside_html_tags = false
341
272
  word = ''
342
273
  end
343
274
  elsif is_wiki_name?(word)
344
- if !no_wiki_link_in_effect and !inside_html_tags
275
+ if !no_wiki_link_in_effect && !inside_html_tags
345
276
  # code smell here y'all
346
- word = convertToLink(word) if !block_given?
277
+ word = convert_to_link(word) unless block_given?
347
278
  end
348
279
  end
349
280
  if block_given?
@@ -355,9 +286,9 @@ module ClWiki
355
286
  end
356
287
 
357
288
  def self.only_html(str)
358
- onlyOneTag = /\A[^<]*<[^<>]*>[^>]*\z/
359
- headerTagLine = /\A\s*<h.>.*<\/h.>\s*\z/
360
- (str =~ onlyOneTag) || (str =~ headerTagLine)
289
+ only_one_tag = /\A[^<]*<[^<>]*>[^>]*\z/
290
+ header_tag_line = %r{\A\s*<h.>.*</h.>\s*\z}
291
+ (str =~ only_one_tag) || (str =~ header_tag_line)
361
292
  # str.scan(/<.*>/).to_s == str.chomp
362
293
  end
363
294
 
@@ -366,38 +297,30 @@ module ClWiki
366
297
  end
367
298
 
368
299
  def cgifn
369
- $wiki_conf.cgifn if $wiki_conf
300
+ $wiki_conf&.cgifn
370
301
  end
371
302
 
372
303
  def full_url
373
304
  ($wiki_conf.url_prefix + cgifn) if $wiki_conf
374
305
  end
375
306
 
376
- def convertToLink(page_name)
307
+ def convert_to_link(page_name)
377
308
  if ClWiki::Page.page_exists?(page_name)
378
- "<a href='#{page_name.strip_slash_prefix}'>#{page_name.strip_slash_prefix}</a>"
309
+ "<a href='#{page_name}'>#{page_name}</a>"
379
310
  else
380
- if $wiki_conf.useIndex == ClWiki::Configuration::USE_INDEX_NO
381
- finder = FindInFile.new($wiki_path)
382
- finder.find(page_name, FindInFile::FILE_NAME_ONLY)
383
- hits = finder.files.collect { |f| f.sub($wikiPageExt, '') }
384
- else
385
- @wikiIndex = ClWiki::IndexClient.new if @wikiIndex.nil?
386
- titles_only = true
387
- hits = @wikiIndex.search(page_name, titles_only)
388
- hits = GlobalHitReducer.reduce_to_exact_if_exists(page_name, hits)
389
- end
390
-
391
- case hits.length
392
- when 0
393
- result = page_name
394
- when 1
395
- result = "<a href='#{hits[0]}'>#{page_name}</a>"
396
- else
397
- result = "<a href='find?search_text=#{page_name}'>#{page_name}</a>"
398
- end
399
-
400
- if ($wiki_conf.editable) && ((hits.length == 0) || ($wiki_conf.global_edits))
311
+ @wiki_index ||= ClWiki::MemoryIndexer.instance
312
+ hits = @wiki_index.search(page_name, titles_only: true)
313
+
314
+ result = case hits.length
315
+ when 0
316
+ page_name
317
+ when 1
318
+ "<a href='#{hits[0]}'>#{page_name}</a>"
319
+ else
320
+ "<a href='find?search_text=#{page_name}'>#{page_name}</a>"
321
+ end
322
+
323
+ if $wiki_conf.editable && (hits.empty? || $wiki_conf.global_edits)
401
324
  result << "<a href='#{page_name}/edit'>?</a>"
402
325
  end
403
326
  result
@@ -405,36 +328,12 @@ module ClWiki
405
328
  end
406
329
 
407
330
  def is_wiki_name?(string)
408
- all_wiki_names = true
409
- names = string.split(/[\\\/]/)
410
-
411
- # if first character is a slash, then split puts an empty string into names[0]
412
- names.delete_if { |name| name.empty? }
413
- all_wiki_names = false if names.empty?
414
- names.each do |name|
415
- all_wiki_names =
416
- (
417
- all_wiki_names and
418
-
419
- # the number of all capitals followed by a lowercase is greater than 1
420
- (name.scan(/[A-Z][a-z]/).length > 1) and
421
-
422
- # the first letter is capitalized or slash
423
- (
424
- (name[0, 1] == name[0, 1].capitalize) or (name[0, 1] == '/') or (name[0, 1] == "\\")
425
- ) and
426
-
427
- # there are no non-word characters in the string (count is 0)
428
- # ^[\w|\\|\/] is read:
429
- # _____________[_____ _^_ ____\w_________ _| __\\______ _| ___\/________]
430
- # characters that are not word characters or back-slash or forward-slash
431
- # (the not negates the *whole* character set (stuff in brackets))
432
- (name.scan(/[^\w\\\/]/).length == 0)
433
- )
434
- end
435
- return all_wiki_names
331
+ return false if string.empty?
332
+
333
+ /\A[A-Z][a-z]\w*?[A-Z][a-z]\w*\z/.match?(string)
436
334
  end
437
335
  end
336
+
438
337
  class CustomFooters
439
338
  include Singleton
440
339
 
@@ -444,11 +343,11 @@ module ClWiki
444
343
  end
445
344
 
446
345
  def process_footers(page)
447
- content = ''
448
- @footers.each do |f|
449
- content << f.footer_html(page)
450
- end if @footers
451
- return content
346
+ String.new.tap do |content|
347
+ @footers&.each do |f|
348
+ content << f.footer_html(page)
349
+ end
350
+ end
452
351
  end
453
352
  end
454
353
 
@@ -470,11 +369,11 @@ module ClWiki
470
369
  end
471
370
 
472
371
  def process_formatters(content, page)
473
- @formatters.each do |f|
474
- if content =~ f.match_re
372
+ @formatters&.each do |f|
373
+ if content&.match?(f.match_re)
475
374
  content.gsub!(f.match_re) { |match| f.format_content(match, page) }
476
375
  end
477
- end if @formatters
376
+ end
478
377
  end
479
378
  end
480
379
 
@@ -482,39 +381,12 @@ module ClWiki
482
381
  # directory and imitate.
483
382
  class CustomFormatter
484
383
  end
485
-
486
- class GlobalHitReducer
487
- def GlobalHitReducer.reduce_to_exact_if_exists(term, hits)
488
- reduced = hits.dup
489
- reduced.delete_if do |hit|
490
- parts = hit.split('/')
491
- exact = (parts[-1] =~ /^#{term}$/i)
492
- !exact
493
- end
494
-
495
- if !reduced.empty?
496
- reduced
497
- else
498
- hits
499
- end
500
- end
501
- end
502
384
  end
503
385
 
504
386
  module CLabs
505
387
  class WikiDiffFormatter
506
- def WikiDiffFormatter.format_diff(diff)
388
+ def self.format_diff(diff)
507
389
  "<b>Diff</b><br><pre>\n#{CGI.escapeHTML(diff)}\n</pre><br><hr=width\"50%\">"
508
390
  end
509
391
  end
510
392
  end
511
-
512
- class String
513
- def ensure_slash_prefix
514
- self[0..0] != '/' ? "/#{self}" : self
515
- end
516
-
517
- def strip_slash_prefix
518
- self.gsub(/^\//, '')
519
- end
520
- end