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.
- checksums.yaml +4 -4
- data/Rakefile +19 -9
- data/app/controllers/cl_wiki/application_controller.rb +29 -1
- data/app/controllers/cl_wiki/page_controller.rb +52 -38
- data/app/controllers/cl_wiki/sessions_controller.rb +30 -0
- data/app/helpers/cl_wiki/application_helper.rb +3 -1
- data/app/models/cl_wiki/user.rb +89 -0
- data/app/views/cl_wiki/page/edit.html.erb +5 -1
- data/app/views/cl_wiki/page/recent.html.erb +1 -1
- data/app/views/cl_wiki/page/recent.rss.builder +10 -8
- data/app/views/cl_wiki/sessions/new.html.erb +10 -0
- data/config/clwiki.yml +16 -30
- data/config/initializers/clwiki.rb +4 -3
- data/config/routes.rb +9 -0
- data/lib/cl_wiki.rb +5 -1
- data/lib/cl_wiki/configuration.rb +28 -137
- data/lib/cl_wiki/engine.rb +3 -1
- data/lib/cl_wiki/file.rb +140 -117
- data/lib/cl_wiki/format/format.blockquote.rb +8 -6
- data/lib/cl_wiki/format/format.graphviz.digraph.rb +8 -7
- data/lib/cl_wiki/format/format.opml.rb +11 -9
- data/lib/cl_wiki/format/format.pre.blockquote.rb +8 -6
- data/lib/cl_wiki/format/format.simpletable.rb +10 -8
- data/lib/cl_wiki/memory_index.rb +102 -0
- data/lib/cl_wiki/page.rb +129 -257
- data/lib/cl_wiki/public_user.rb +9 -0
- data/lib/cl_wiki/user_base.rb +25 -0
- data/lib/cl_wiki/version.rb +3 -1
- data/lib/cl_wiki_lib.rb +9 -0
- data/lib/tasks/index.rake +4 -4
- data/test/dummy/app/assets/config/manifest.js +3 -0
- data/test/dummy/config/application.rb +1 -0
- data/test/dummy/config/environments/development.rb +2 -0
- data/test/dummy/config/initializers/clwiki.rb +3 -0
- data/test/dummy/config/routes.rb +3 -0
- data/test/dummy/log/development.log +5909 -0
- data/test/dummy/log/test.log +33349 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/-8/-8X-3n5w3EAS5uiBS2GQxjMlqD43Qout1GsSJUU6e4k.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/-P/-Pa1BPD1Ps1OvnKPyrGE4MiUEnlzMEccXN8CzzxSRjM.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/0k/0ktSefuSiZXp-1v5uXwST57lRoAF2HvHzclO4Gtftgo.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/1V/1VmPI9-8O9Y8OP-JxSXl7-yNRMZHqapeh2drmkXiRGE.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/2W/2WKPDryRtGzZO6Uedw4RNjnI5M9YVH-IbFg5GvLvTTQ.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/3G/3GuA3P7RM10Vv7NgdH65pwfAH7gMHlJ_xBUO74i-ZjM.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/3S/3SzCkB81tc9XbtFdEYxCeR3If141gvhEnHchU_C6hHs.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/41/41dY2GtQJAt3CmkQn8IDa9B3clQaUT6XymanCfFZR2o.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/46/46WEPovJzlkEgsdG0aV08HiNsRkf0L8Txt1SWLi4atg.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/4I/4Ir0PJhTRUd9iGlSu6n2AREP-_amedFe4-1fKwB2wvg.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/5L/5LXSsjTcB5Un8FHlrhi6AOjxwgzWoXeWBhU_hi1gdcg.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/67/67V_0cxwrU68Onen7N2Lb9bTd1jLulH06F9zh1VgZ0U.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/6A/6AXD3XLczHK8MPb5e10-7sLcS45ZrP7Iwgyo9xle0nU.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/6D/6D8TdXG6KyMkGDvPbv87qUCDz9_6gRZbNAohojB484w.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/7L/7LVfTxjfHpOSp2FeG-uhloqIUqIZ7uE3nT40dqhoqY8.cache +2 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/7b/7bceaEE3qsyoVjeou6RR-V9w2Wgzraq0OI2erU4s9ew.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/7h/7hRfgp9EsoD33qh0aNXeyg9qdGapPlUT6FmcL8xztY4.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/8c/8cq-JtJ9Zwg4F0bFdkqaGHjdB7a9JBmfDO_sczTWycI.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/8h/8hO7EIQ5iOa2rL6ZlP318Lrk0unB2CfhHCI0TrUr-Oo.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/8x/8x0PXM3vatUzVGk-vKi80S7LXrGb6bE-3EzEj54VNak.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/9v/9vfh8eoLcnq3s_rolIXPs15SPTQWGxJrrjpJ3PoABek.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/9w/9w-0hdVYmxONDHQlpGn7DFzlRA3oXqpW4x3t9LBUU6M.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/B3/B385Es3x0hpGSQNWzSjiDcExPuEV9m1dUZWlEp5zGbw.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/BR/BRBOvy22uVEx9Z5Aal_0BfPilVYEQl6AYXG2u8yBqBg.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/BX/BXdNycvZI2UN7cgqvk6P4MQCc1PH2bTwa9i9vP-s-jk.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/CO/CO-z80mMyQGRy-BwknxOV5bI2IFbcMMNc05j7v8Nqso.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Cg/CgPqTXtSkCxEox0z95JfY89MndA2GhTTQK39fjKk6QU.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Ct/CtQeoxqXfctXd_NvChnCVaJ_cCjNuXJMv3LBXhswU6A.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Dc/DcZ_YfpX7rLYFw-u7jSJCRp_z0iIyB7XKOcwm1cQexk.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Ex/Exqg59Ton1SZt_QH4hMa7wUFOAuIQnCan8B9578NzIg.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/F5/F5c-QANC5X3kApAecuyiMZEme0NT_UUB6SjxKvb0ALg.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Fd/FdwPBPhLtL4s8RSPhJ53YoYoFdRkNxANV_zQYw-KsVc.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/GK/GKrbCoxDofzkQCmA17lE84OT6RW_6NKm7jwyZ4n2T6s.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Gh/GhVuWwPtbWpQY_Ny4MyilnH9iUqCPxTDzOonAXM4od8.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Gv/GvQrSgGYXiR-rgsPHFZq1oJ5zCkDK54muqIw6KW2GyA.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Gw/Gwhhfk9vS7QWmHsW90WtAt0_Rp_7AIM-ZcHmEqLf_Rg.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/H5/H5Yxi2VJxpyMb-cbgwBNua8O2zZ03Jk4ByV6yhIzAsQ.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/I0/I0OpFIfCc595P02GZa3LUD1uD-Payl41dWaW3oZSK7g.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/IQ/IQoDS19BmJjvixXd16O_7P6DB-GRUEZgdNJexJ88fIc.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/I_/I_zDBUxxL4b2Wk9_qqVs56Abw1jGccc4FgvKwuscswQ.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Ig/IgcuJMmmdeYrq2F3D721tC7ficyRm92HIrLkim5DCxQ.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/JI/JITjXC3hXUPgOQhDYsVjhPNjtTISt0j5uz2bjfoiSHI.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/KL/KL75rsyvMJSIkYkXRijxh8cs7V1wtfLPjuodISQK5vc.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Kw/KwqVMeMNxvnaSP-a-H5nkYyxloW_xoqR5JhEnqJ9puQ.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/L1/L1KghIbeezpqVDyhAbCDc4pG11ElC5JpUl319-ZlZn8.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Lh/LhI7QMLwiVavmyvwYzdc_t_V9OATXaBO8aCB2swJFCk.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Lh/LhqYyoCtzXpfZq6UOhmZuZLSaAwZRX44sHfwPvPqezc.cache +2 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Lo/Lovn2yBpV04WnAQwZeM3hLL015H5syYBH2ufgIc6qCM.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Lz/LznMZWa43whMHpqnPRsbUfREY3y_fiXQKaiKVEYW4fw.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/MC/MC7GYdrSShtV64GB3hoINaYL3vCRZKq9KvwcwrJAdQo.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/MU/MU6iF1YPAQqpVK_kVAtiJPtbHaYpYdOcO0g5bJ9exj8.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Md/MdIg3XLcnbFsMXC-6xslVtmBvWH7Q21BSt9l5pm305o.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Mw/Mwfi5Xeky61jhIuc6ooo4439CHOyz1hS48_taMRSlKM.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Ni/Ni5yuK9FFnhLe5HciROve12UIYstBdESWm0LfdcuVVs.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Nz/Nz3hkLq4WlqgoHg_ChdHSXbP7fVmCWCTw0lH0jkMmDg.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/O3/O38OvSNrhXKbxauuC8GOBBnKrt2-rPaDmfyrXScgHcA.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/OS/OSm-zAlxXS63lBjvzJeSWfqq5d3D9fu-_nBVFWyQ4j0.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Oa/Oazc9AJ4e_67dU0aArJeCNEeWJKMIFPtAJtxTJoUKcs.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/PV/PVDpEMY_ha4kHETTb3QvjOBoBUP4PMjNDNcIAgmDy2I.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Pl/PldDxSvU1o_UFPYTE0GJmUS9mHQXH88zEw5HN6GtlRE.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Pu/PuU5S_LPnhAX43U1VVN3qP_sv0ph4stXSGo7I0e_jOw.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/QJ/QJ6RPZNUkui_k3wTkb62zo8wczYY7q0B174GfSJjjWE.cache +2 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/QX/QXCyCL-Eeb3uHm9iOvs4anspZqeFbQnNyzDfIsXgzC8.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/R1/R1F4Qf-kXTMH0fTLahalFTHtNBvgDfkOkrPyW8zeN_E.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/R1/R1__Y-gz4zkDYrXWyCf6YTkvXO0RZlrpK6ynGGVuvnM.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/R2/R2Xqb6eAeUW2xTaTaTjlkyUCirkb1qfYgW2CyY80VjM.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/RM/RMXouh7GkRuhy8S6jnpxFD27HRVT0LEHj9iR53ps4o4.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/RV/RVmt1mCn0tykR8xyBylvh-Hvi-Am87neA2IEkYHjg-g.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Tg/TgTXCuKAEg1DI5zjHO8tGMGuQGC9BRt9vgDZj2FdSa8.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/UI/UIyRfqj_T27DnyWJiZK9BdUGTIDTQ9M953ArtrYz5fM.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/U_/U_F-o3fo7oUYyn0O5KBlt3jOF53X_-4UuZb-_alPZPk.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/U_/U_KCsVrX_QoGJ_FpUpCNU3XMT36CThwu8_0HYj_2k4w.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/U_/U_ie5WwVJPItNZrqfbIrnZpaRokYT5klrYU92QSugd8.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Ub/Ub-oUCoAiliSW8ohVsmtsflc4nPeiBvcjzgNbPLYQRc.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Ud/UdvIJcVNQ_08Vaoyx4KuRGNjazpB9-qjOtDMTud8R0Y.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Uz/UzEG5I_EszWbaSVnk497D0KfuIzsgHoPLVQd7e3mlQg.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/V-/V-F9X0mrPgfTELxk9xdYnb27trOmB6nBDL973YWeOfU.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/VA/VAOOXmbiiPy1jqpQQCDVrhkByG3pdeJoZCOvVkp-XVY.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/VV/VVIuIm_HUOaEdZfXt-CmFQZb3ycoiXeeI-FV7nwkr0Y.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/VX/VXHQHhwOUBuWlKPY6smpXG1xjASw927lyjUKBXBh3e0.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Vn/VnMqvZo9nqGF_5tt3gNbMyoG8jJVm0K0r1fANEBjfkw.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/W1/W1YuEAoPMZTXfbxg_xWV9o2RP60SAKs5bhk7teKdL2g.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/W2/W2ZyYMlYmyA7_1WcpiWhYUJa6wfPCZ5kZj_-Nuw31yM.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Wg/WgwI9C5-mh_smtsTGVmH4y76T5ifM4M_hKL1fn-K8iw.cache +2 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/X5/X5GHIj6tnz-w7d-60OaYcbzJczzkTBtm24BOxzoSDdo.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/X6/X6jU4SPOD_b1ks9tCApsvWRa7q8cBYCjw3gI6Dwvr34.cache +2 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/X8/X88lT-cwuuj8gqiNY83uVqXFgeLcaHMc9Xh2X4Iux6k.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/XQ/XQ0aFc1cceisG4P8qUPhW8z1H3I71pMguVRRMgJ66cs.cache +5 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Xh/XhXLVYOEEwpzOBAWDdiCEpTMz7vC8wnlBHYHJkySh-0.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/YB/YBJNyX7HNPq78obeHYRGnJKSVl9EtRPbcGD253-ia34.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Yu/YupDX89OAJ6u3BHBW-UJgO3nDfi7hwlpf_JHlnM8b6k.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/ZH/ZHN5sHdNMxUCl3Ese5T5_AzQbD9WHqpgBL4PBOrgXJY.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/ZP/ZPRvYWthjzuQ0tqk5AdgQbeTUqhDboF8bvTtdrmg4Jo.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/ZV/ZVu2Ed9wpdsPLKStP971oLEJBwgJQHLInXIiQkIWC04.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Zb/ZbnyIl6znMAVquD2ZD5OYA9SPXmQJYWU7V8F2Hgp3Uc.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/Zj/ZjALwFkjfG3uebsyy_CeJp5VQMJLE03zxPxkNp-sZDA.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/_F/_Fu404i1O4mKpjPluBsq-3FZQnyQvla_6jDnH03Lpw8.cache +2 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/a-/a-t90hz_PZnc6ImKhk-cIh_WBB9vi_rChKzLv4hMBqw.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/a5/a5cnzGcRAu4dPakq4_DHH9GanK42Ov5O1F62oeJR4Zo.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/aJ/aJK2kxoM9CsnZpxiFvP6RoP0sxHBiix9X1P6Mhy9Dcg.cache +2 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/aO/aOU10S2QEOBHcdKwGRfXqqHdYshmYD20LYiJIGMzIa0.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/aZ/aZEdK7dgijyjIs26V_QbKsDgO5JxeYXiT0Sl28M0e-U.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/aq/aqBnFJWuQ-xmdUL8_asWtElNRrMr0W60LVdDqpt43L8.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/b5/b5KTv2Hrf5faN7X4XahT1s8L5t-EANtcFKrMEsGm3lw.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/bF/bFemYCjG73k2_Ys77S7qNyW7CYcyw4bngyc0OGneI-s.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/bG/bGdy8gJL8acOmxK8AbkYbxNuakf4LlMZ-zPBkyL0E-0.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/bK/bKm8sxC3i0ycUMXr6pnD61MdwytUWfpNOJlBY6qJaWg.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/dA/dA1M22RMQvVwb74tbFg-_237SferZuCI10s4R0zx8NI.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/dF/dFOzXjFeRtB5bukRI9wGrh2O_GkOeBPnrJRMiv8_ZbM.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/dw/dwbXKkD4yllXOeD4T7BKoGvLS26j9lxMkjMiIxfyt6E.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/eT/eTgN8O1TgsFV61pclFzCmmJ9qT7MgyGvtQrmRtJoNeg.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/eu/eu6Xg0psMCuHIWG0WjCo9wwNOlWs-Z5OH4SyGEmdTNQ.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/fC/fC-TBNdh4rVupPn2ObyZeIx6OSlpBSBQZfIzywI6xx0.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/fR/fRIbNtGTaNqdwIDyusrUmllglSGMNnqnw7VOLvf5D_k.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/fq/fq7SFxQSEFZCuS7jQj0n-BQfbJ5mpLpmJQsd9mJVq68.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/gG/gGBN3yxvq8azMjDv3hsSw_zLUj9KLuqHPDXZK8x8pFc.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/gd/gd3J0EmNeiTh2GzxcAKItmtUnUay9NG4Sm2vkiLKvmA.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/gj/gjXteWe57D8FaBOQUw29N_mwHCeTQW8oLjyv8fu3wNw.cache +3 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/gt/gtFeEhjHn0G9WhgiMKaNtXVgNYW9s_wBLE0VGegeAN8.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/hA/hA4-M5cp310ZkSe59_BWszdgXy7mmYagSRCfelGBA9o.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/iC/iC3FCadetljjEIeMWfeqqDoMxhJi6rI20BpiVxtvgS4.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/iV/iV16_jyEayI_vLgHw3HFhtJAiVOCIlzFho0Yt7a4v_Y.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/j6/j62KRIr4T81zq1Ujpg7AJRQdI0ry9HGKPt4nK6fRt1g.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/jR/jRg0Zbr59-UMtrWO5t2VWNI3GqU7XWOUsE44dX5cPyk.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/jj/jj9HUpCSrLEyONEZNLLkgJ8hJmxOCLpcVJeiBa0KDsE.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/jq/jqnMk9arxuef2cdSQuxj3WOQuAfGKup3H2pjO7x1DOg.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/k1/k14rvggyKI9dk-yVjn-Lk0p8qU360H_JuVG9aZ4q0OM.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/kb/Kb8Z49kajAX1vyy5d4-gA8StHhQp5yOUs0wtdZ7m8Hc.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/kb/kbEMkrgp2k0pezn_gFfMqA142QwoJYBKMj7cEkE-Hag.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/lD/lDpZHp5gBhRdNHdj1TwWq1_LZ_a56lxeksxqaEs2efA.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/mE/mEfGHxLvdPQrcbpjLw4q_wOPirMzrR4z58KgozQ1zNY.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/mM/mMZ3DR5b7kx70JtEg-ImWOa_V1jnHcWgHqNqapxIMXk.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/mX/mXCT6vriuTtwLaKGnTa5hwXSrwGtAmP6pV5lmjbHaYM.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/mZ/mZjIy4zRS4hbS4vWHpdKd7jeZgLatEx_nlFqv_KSCrs.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/mg/mge36-9r2gGuKcPoghbLDM72AV4gIVTl6gQDbk7hrkg.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/nK/nKZaLuUqTl9pf5Nb1oVuabxd74q4oN8YTBeo6bNd-Vk.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/nP/nPbHGaYfJSLZ2K3YTROe7T1RPqKoBQJwawQtZ_FN1-I.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/o9/o9KyTznHG0ZIHDI7kTg1Jp78qaga7gJqouXSKdocEjA.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/oB/oBupyQ9cW436mBji6Rp7TtHE6CX_r8iq2sCBo0LNbc8.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/oN/oN3TypgxDDLqcxy0Funa4RVCYXS-7qn6D56wgBiUT2Q.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/om/omGcA_eTFAFIH3RJaPOpEW3yz0074cob3hozQFLOAxk.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/p0/p0WHrZZBaXbPaNj5XmQGTli4mi08Rv8DidQfwj28a6w.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/pA/pAvUFBt71eJx7E7oQbIxrEZ8YcMo9kboyGxjk73ZWrI.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/pB/pBwzUQUu-GcmLiQwn6KnbbDP0ipnVHzVaeArqdpqi98.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/pC/pCePfKbmTQ6s2Tl7ki3oBput2ruhpCzpa6Vvejbb5xg.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/q6/q6BYa32YJF11eGVapO4ouNl6gayPIsARgMavlzZmoi0.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/qY/qY78GTTnufmP1eP2CE16x833zGfQ0F5EVCFtUTMQ7Mw.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/qm/qmZZzCnL9PLIyZ0iBu6Alr69AUfHHI1fKdNRRgG04yg.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/s5/s5yv3jYvjyKZJ8SMzpj94eMKEuX46lAWV1ApHF-6bsM.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/sO/sOBPF_p4Te56V9vdLV0Ywn6djNbmdPSIzvgYNPnAXYc.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/sv/sv0a_JAC4GSc_cK-2OUAzhFwm_K3qzSfDefwpcqOCk4.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/sw/sw2EAksRkslJNoJJCTS2FPOfHWCYvsS86AxmRMPjens.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/t1/t1cv6bP9cTAIs82lyIsnXGeAwB1KNVY5_5rgUvelr04.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/tO/To1SPyNegqysLIqhSzrNQPh1VKKj19MespjJediCde4.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/tO/tOPkZNrO9FRDhSlCf7VWOexxRq2CE2X4_6KjyxJkq2A.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/tR/tRoxwnX8bACHK5pW9tIi4ILY4XuYTIpueH0fGr2t0rc.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/t_/t_bP70PmOB70862dwKmCTkmZuzTqCreOzNYW4Yn2n6A.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/uj/ujdE_ewC5UIxr6uw5F7YRfKKWiu8-15wzBlOjYHsnkQ.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/ut/ut8uBMdgxX8_wfU0l6kGew6H8TLXAj74kFnaI252F3k.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/ut/utQEOZtBKQK_bUUDeZX4Mgk00L4AOMVyq6zrKAoo1Xw.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/vm/vmjBl9ZCF5hj4sG4e2nid94GcRQYmsOsu-_Q3Zlud5c.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/vz/vzBoVc4GQWi4UFp-4dBJnzrhyUuokPV8SCOxsdpOht8.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/wM/wMWxmf8BN_NAJRCyardukpfDMwts44Bz2a8doi-49Rg.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/x7/x7KkTV3ibfIEysLB_ug5bfmnn2VLV_BldukPR3EoPBk.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/x7/x7iSOdqAIVmVpn9ujTwJ_C7EqUgmMSri5vjjHdRIX10.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/xY/xYdD9O1JRIfpVj9Kw_b3JTUBQZLI_dcy-bf9uXEp-jg.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/xx/xxkulLgT-tkVeDC50gUXRGGMou47BUdlYOwgs0j5muY.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/yn/yn_3aZZwyjcI0O6fwisZ7zvcu4Gq5bV31g3tHFxfQNg.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/yq/yqwjyepbYY4ctoMOySWiOIWUYwzl_BczAmXqJ5DPvb0.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/z9/z9HQmzff5j_6CFyk6eQ52nYt9cPLXsxDQY0Yep1Hz-0.cache +1 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/zM/zMvcc87IG1SRbqwUNtWQfHgeWr5XN36OU8vg-v3rUus.cache +0 -0
- data/test/dummy/tmp/cache/assets/sprockets/v4.0.0/zn/znjQpjNzh1iUAe9DljeFghnStRvqNIr1GuOTibVcEJQ.cache +0 -0
- data/test/dummy/tmp/testrep/BazQuux.txt +5 -0
- data/test/dummy/tmp/testrep/FooBar.txt +5 -0
- data/test/dummy/tmp/testrep/NewPage.txt +5 -0
- data/test/dummy/tmp/testrep/users/testy.json +1 -0
- data/test/dummy/tmp/wikirep/FrontPage.txt +5 -0
- data/test/dummy/tmp/wikirep/users/chrismo.json +1 -0
- data/test/dummy/wikirep/EncryptedPage.txt +0 -0
- data/test/dummy/wikirep/FrontPage.txt +11 -4
- data/test/dummy/wikirep/users/chrismo.json +1 -0
- data/test/helpers/wiki_helper_test.rb +2 -0
- data/test/lib/clwiki/clwiki_test_helper.rb +19 -2
- data/test/lib/clwiki/file_owner_test.rb +58 -0
- data/test/lib/clwiki/file_test.rb +85 -56
- data/test/lib/clwiki/memory_index_test.rb +61 -0
- data/test/lib/clwiki/page_test.rb +71 -148
- data/test/lib/clwiki/test_base.rb +19 -19
- data/test/test_helper.rb +7 -5
- metadata +398 -23
- data/lib/cl_wiki/find_in_file.rb +0 -33
- data/lib/cl_wiki/index.rb +0 -458
- data/lib/cl_wiki/tools/cron.reminders.rb +0 -241
- data/lib/cl_wiki/tools/movepages.rb +0 -27
- data/lib/cl_wiki/tools/pagestomove.txt +0 -56
- data/lib/cl_wiki/tools/rublog/clWiki.rb +0 -62
- data/lib/cl_wiki/tools/rublog/readme.txt +0 -2
- data/lib/cl_wiki/tools/singlepage.rb +0 -58
- data/lib/cl_wiki/tools/test/singlepagetest.rb +0 -9
- data/lib/cl_wiki/tools/thunderbird.rb +0 -23
- data/test/lib/clwiki/find_in_file_test.rb +0 -111
- data/test/lib/clwiki/index_test.rb +0 -32
@@ -1,8 +1,9 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_dependency 'cl_wiki/configuration'
|
2
4
|
|
3
5
|
filename = File.join(File.dirname(__FILE__), '..', '..', 'config', 'clwiki.yml')
|
4
6
|
|
5
|
-
conf_hash = YAML
|
7
|
+
conf_hash = YAML.safe_load(::File.open(filename))[Rails.env]
|
6
8
|
conf_hash['wiki_path'] = ::File.expand_path(conf_hash['wiki_path'], Rails.root)
|
7
9
|
$wiki_conf = ClWiki::Configuration.new(conf_hash)
|
8
|
-
$wiki_path = $wiki_conf.wiki_path
|
data/config/routes.rb
CHANGED
@@ -1,14 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
ClWiki::Engine.routes.draw do
|
2
4
|
root to: 'page#show'
|
3
5
|
|
4
6
|
# legacy CGI
|
5
7
|
match '/clwikicgi.rb', to: 'page#show', via: [:get], as: 'legacy'
|
6
8
|
|
9
|
+
# Ordering of routes matters! Anything specific, like `find` needs to be
|
10
|
+
# _before_ the `/:page_name` route, otherwise it matches on `/:page_name`
|
11
|
+
# before matching on the specific route.
|
12
|
+
|
7
13
|
get '/find' => 'page#find', as: 'page_find'
|
8
14
|
post '/find' => 'page#find'
|
9
15
|
|
10
16
|
get '/recent' => 'page#recent', as: 'recent'
|
11
17
|
|
18
|
+
get '/login', to: 'sessions#new'
|
19
|
+
post '/login', to: 'sessions#create'
|
20
|
+
|
12
21
|
get '/:page_name' => 'page#show', as: 'page_show'
|
13
22
|
get '/:page_name/edit' => 'page#edit', as: 'page_edit'
|
14
23
|
post '/:page_name' => 'page#update'
|
data/lib/cl_wiki.rb
CHANGED
@@ -1,5 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'cl_wiki/engine'
|
2
4
|
|
5
|
+
require_relative 'cl_wiki_lib'
|
6
|
+
|
3
7
|
module ClWiki
|
4
8
|
=begin
|
5
9
|
http://edgeguides.rubyonrails.org/engines.html#inside-an-engine
|
@@ -9,4 +13,4 @@ module ClWiki
|
|
9
13
|
options, the file where your engine's module is defined is perfect for that. Place
|
10
14
|
the methods inside the module and you'll be good to go.
|
11
15
|
=end
|
12
|
-
end
|
16
|
+
end
|
@@ -1,83 +1,43 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require 'yaml'
|
3
4
|
|
4
5
|
$defaultConfFile = 'clwiki.yml'
|
5
6
|
|
6
7
|
module ClWiki
|
8
|
+
# noinspection RubyTooManyInstanceVariablesInspection
|
7
9
|
class Configuration
|
10
|
+
attr_accessor :wiki_path, :cssHref, :template, :publishTag, :url_prefix,
|
11
|
+
:global_edits, :page_update_format, :use_authentication,
|
12
|
+
:owner, :encryption_default
|
13
|
+
attr_reader :custom_formatter_load_path, :edit_rows, :edit_cols, :editable
|
8
14
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
attr_accessor :wiki_path, :cgifn, :indexPort, :cssHref, :template, :useGmt,
|
14
|
-
:publishTag, :url_prefix, :global_edits, :cgifn_from_rss, :stats_name,
|
15
|
-
:index_log_fn, :page_update_format
|
16
|
-
attr_reader :custom_formatter_load_path
|
17
|
-
|
18
|
-
def wait_on_threads
|
19
|
-
# Ruby kills any threads as soon as the main process is done. Any
|
20
|
-
# threads created should be registered here. The last
|
21
|
-
# line of the CGI script should call out to wait_on_threads to make
|
22
|
-
# sure nothing running async in the background is terminated too early
|
23
|
-
@threads.each do |thread|
|
24
|
-
thread.join
|
25
|
-
end if !@threads.nil?
|
26
|
-
end
|
27
|
-
|
28
|
-
def wait_on_thread(thread)
|
29
|
-
@threads = [] if !@threads
|
30
|
-
@threads << thread
|
31
|
-
end
|
32
|
-
|
33
|
-
def useIndex
|
34
|
-
@useIndex
|
35
|
-
end
|
36
|
-
|
37
|
-
def useIndex=(value)
|
38
|
-
@useIndex = value.to_i
|
15
|
+
def initialize(hash = {})
|
16
|
+
default_hash.merge(hash).each do |k, v|
|
17
|
+
instance_variable_set(:"@#{k}", v)
|
18
|
+
end
|
39
19
|
end
|
40
20
|
|
41
|
-
def
|
42
|
-
|
21
|
+
def default_hash
|
22
|
+
{
|
23
|
+
url_prefix: '/',
|
24
|
+
publishTag: nil,
|
25
|
+
useIndexForPageExists: false,
|
26
|
+
edit_rows: 25,
|
27
|
+
edit_cols: 80,
|
28
|
+
custom_formatter_load_path: [],
|
29
|
+
use_authentication: false
|
30
|
+
}
|
43
31
|
end
|
44
32
|
|
45
33
|
def edit_rows=(value)
|
46
34
|
@edit_rows = value.to_i
|
47
35
|
end
|
48
36
|
|
49
|
-
def edit_cols
|
50
|
-
@edit_cols
|
51
|
-
end
|
52
|
-
|
53
37
|
def edit_cols=(value)
|
54
38
|
@edit_cols = value.to_i
|
55
39
|
end
|
56
40
|
|
57
|
-
def useIndexForPageExists
|
58
|
-
@useIndexForPageExists
|
59
|
-
end
|
60
|
-
|
61
|
-
def useIndexForPageExists=(value)
|
62
|
-
if value.class == String
|
63
|
-
@useIndexForPageExists = (value =~ /true/i)
|
64
|
-
else
|
65
|
-
@useIndexForPageExists = value
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
def access_log_index
|
70
|
-
@access_log_index
|
71
|
-
end
|
72
|
-
|
73
|
-
def access_log_index=(value)
|
74
|
-
if value.class == String
|
75
|
-
@access_log_index = (value =~ /true/i)
|
76
|
-
else
|
77
|
-
@access_log_index = value
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
41
|
def override_access_log_index
|
82
42
|
@orig_access_log_index_value = @access_log_index
|
83
43
|
@access_log_index = false
|
@@ -87,85 +47,16 @@ module ClWiki
|
|
87
47
|
@access_log_index = @orig_access_log_index_value if @orig_access_log_index_value
|
88
48
|
end
|
89
49
|
|
90
|
-
def editable
|
91
|
-
@editable
|
92
|
-
end
|
93
|
-
|
94
50
|
def editable=(value)
|
95
|
-
if value.class == String
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
end
|
101
|
-
|
102
|
-
def showSourceLink
|
103
|
-
@showSourceLink
|
104
|
-
end
|
105
|
-
|
106
|
-
def showSourceLink=(value)
|
107
|
-
if value.class == String
|
108
|
-
@showSourceLink = (value =~ /true/i)
|
109
|
-
else
|
110
|
-
@showSourceLink = value
|
111
|
-
end
|
51
|
+
@editable = if value.class == String
|
52
|
+
(value =~ /true/i)
|
53
|
+
else
|
54
|
+
value
|
55
|
+
end
|
112
56
|
end
|
113
57
|
|
114
|
-
def self.load(filename
|
115
|
-
$wiki_conf = self.new(YAML
|
116
|
-
$wiki_path = $wiki_conf.wiki_path
|
117
|
-
$wiki_conf
|
58
|
+
def self.load(filename = $defaultConfFile)
|
59
|
+
$wiki_conf = self.new(YAML.safe_load(::File.open(filename)))
|
118
60
|
end
|
119
|
-
|
120
|
-
def initialize(hash={})
|
121
|
-
default_hash.merge(hash).each do |k, v|
|
122
|
-
instance_variable_set(:"@#{k.to_s}", v)
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
|
-
def default_hash
|
127
|
-
{
|
128
|
-
:url_prefix => '/',
|
129
|
-
:indexPort => ClWiki::Indexer.defaultPort,
|
130
|
-
:cgifn => 'clwikicgi.rb',
|
131
|
-
:default_recent_changes_name => "Recent Changes",
|
132
|
-
:recent_changes_name => "Recent Changes",
|
133
|
-
:stats_name => "Hit Counts",
|
134
|
-
:useGmt => false,
|
135
|
-
:publishTag => nil,
|
136
|
-
:useIndexForPageExists => false,
|
137
|
-
:showSourceLink => false,
|
138
|
-
:cgifn_from_rss => 'blogki.rb',
|
139
|
-
:edit_rows => 25,
|
140
|
-
:edit_cols => 80,
|
141
|
-
:access_log_index => false,
|
142
|
-
:index_log_fn => nil,
|
143
|
-
:custom_formatter_load_path => []
|
144
|
-
}
|
145
|
-
end
|
146
|
-
|
147
|
-
def default_recent_changes_name=(value)
|
148
|
-
if @recent_changes_name == @default_recent_changes_name
|
149
|
-
@recent_changes_name = value
|
150
|
-
end
|
151
|
-
@default_recent_changes_name = default_recent_changes_name
|
152
|
-
end
|
153
|
-
|
154
|
-
def default_recent_changes_name
|
155
|
-
@default_recent_changes_name
|
156
|
-
end
|
157
|
-
|
158
|
-
def recentChangesName=(value)
|
159
|
-
@recent_changes_name = value
|
160
|
-
@recent_changes_name = @default_recent_changes_name if @recent_changes_name.empty?
|
161
|
-
end
|
162
|
-
|
163
|
-
alias recent_changes_name= recentChangesName=
|
164
|
-
|
165
|
-
def recentChangesName
|
166
|
-
@recent_changes_name
|
167
|
-
end
|
168
|
-
|
169
|
-
alias recent_changes_name recentChangesName
|
170
61
|
end
|
171
62
|
end
|
data/lib/cl_wiki/engine.rb
CHANGED
@@ -1,9 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ClWiki
|
2
4
|
class Engine < ::Rails::Engine
|
3
5
|
isolate_namespace ClWiki
|
4
6
|
|
5
7
|
initializer 'cl_wiki.assets.precompile' do |app|
|
6
|
-
app.config.assets.precompile += %w
|
8
|
+
app.config.assets.precompile += %w[application.css application.js]
|
7
9
|
end
|
8
10
|
end
|
9
11
|
end
|
data/lib/cl_wiki/file.rb
CHANGED
@@ -1,168 +1,196 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'fileutils'
|
2
4
|
require 'time'
|
3
5
|
|
4
|
-
require_relative 'page'
|
5
|
-
|
6
|
-
$wikiPageExt = '.txt'
|
7
|
-
|
8
6
|
module ClWiki
|
7
|
+
FILE_EXT = '.txt'
|
8
|
+
|
9
9
|
class File
|
10
|
-
attr_reader :name, :
|
11
|
-
attr_accessor :
|
12
|
-
|
13
|
-
def initialize(
|
14
|
-
|
15
|
-
@
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
@fileExt = fileExt
|
21
|
-
@metadata = {}
|
22
|
-
@metadata_keys = ['mtime']
|
23
|
-
if autocreate
|
24
|
-
if file_exists?
|
25
|
-
readFile
|
26
|
-
else
|
27
|
-
writeToFile(default_content, false)
|
28
|
-
end
|
10
|
+
attr_reader :name, :mod_time_at_last_read, :metadata, :owner
|
11
|
+
attr_accessor :client_last_read_mod_time
|
12
|
+
|
13
|
+
def initialize(page_name, wiki_root_path, auto_create: true, owner: PublicUser.new)
|
14
|
+
@wiki_root_path = wiki_root_path
|
15
|
+
@owner = owner
|
16
|
+
@name = ::File.basename(ClWiki::Util.convert_to_native_path(page_name))
|
17
|
+
@metadata = Metadata.new
|
18
|
+
if auto_create
|
19
|
+
file_exists? ? read_file : write_to_file(default_content, false)
|
29
20
|
end
|
30
21
|
end
|
31
22
|
|
32
|
-
def
|
23
|
+
def has_default_content?
|
33
24
|
@contents.to_s == default_content
|
34
25
|
end
|
35
26
|
|
36
|
-
def
|
37
|
-
|
27
|
+
def default_content
|
28
|
+
"Describe #{@name} here."
|
38
29
|
end
|
39
30
|
|
40
|
-
def
|
41
|
-
|
31
|
+
def delete
|
32
|
+
::File.delete(full_path_and_name) if file_exists?
|
42
33
|
end
|
43
34
|
|
44
35
|
def file_exists?
|
45
|
-
FileTest.exist?(
|
36
|
+
FileTest.exist?(full_path_and_name)
|
46
37
|
end
|
47
38
|
|
48
|
-
def
|
49
|
-
|
50
|
-
raise 'no dirs in fullPath' if res.split('/').empty?
|
51
|
-
res
|
39
|
+
def full_path_and_name
|
40
|
+
::File.expand_path(@name + FILE_EXT, @wiki_root_path)
|
52
41
|
end
|
53
42
|
|
54
|
-
def
|
55
|
-
|
43
|
+
def content
|
44
|
+
@contents
|
56
45
|
end
|
57
46
|
|
58
|
-
def
|
59
|
-
|
60
|
-
# fullPathAndName
|
47
|
+
def content=(new_content)
|
48
|
+
write_to_file(new_content)
|
61
49
|
end
|
62
50
|
|
63
|
-
def content
|
64
|
-
|
51
|
+
def write_to_file(content, check_mod_time = true)
|
52
|
+
do_mod_time_check if check_mod_time
|
53
|
+
|
54
|
+
update_metadata
|
55
|
+
file_contents = String.new.tap do |s|
|
56
|
+
s << @metadata.to_s
|
57
|
+
s << (content_encrypted? ? @owner.lockbox.encrypt(content) : content)
|
58
|
+
end
|
59
|
+
::File.binwrite(full_path_and_name, file_contents)
|
60
|
+
::File.utime(@metadata['mtime'], @metadata['mtime'], full_path_and_name)
|
61
|
+
read_file
|
65
62
|
end
|
66
63
|
|
67
|
-
def
|
68
|
-
|
64
|
+
def read_file
|
65
|
+
@mod_time_at_last_read = ::File.mtime(full_path_and_name)
|
66
|
+
|
67
|
+
# positive lookbehind regex is used here to retain the end of line
|
68
|
+
# newline, because this used to just be `File.readlines` which also keeps
|
69
|
+
# the newline characters.
|
70
|
+
raw_lines = ::File.binread(full_path_and_name).split(/(?<=\n)/)
|
71
|
+
@metadata, raw_content = Metadata.split_file_contents(raw_lines)
|
72
|
+
raw_content = raw_content.join
|
73
|
+
|
74
|
+
apply_metadata
|
75
|
+
|
76
|
+
@contents = content_encrypted? ? @owner.lockbox.decrypt_str(raw_content) : raw_content
|
69
77
|
end
|
70
78
|
|
71
|
-
def
|
72
|
-
|
73
|
-
|
74
|
-
ClWiki::Util.raiseIfMTimeNotEqual(@modTimeAtLastRead, fullPathAndName)
|
75
|
-
unless @clientLastReadModTime.nil?
|
76
|
-
ClWiki::Util.raiseIfMTimeNotEqual(@clientLastReadModTime, fullPathAndName)
|
77
|
-
end
|
78
|
-
end
|
79
|
+
def read_metadata(lines)
|
80
|
+
@metadata = Metadata.new(lines)
|
81
|
+
end
|
79
82
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
f.print(metadata_to_write)
|
84
|
-
f.print(content)
|
85
|
-
end
|
86
|
-
::File.utime(@metadata['mtime'], @metadata['mtime'], fullPathAndName)
|
87
|
-
readFile
|
83
|
+
def apply_metadata
|
84
|
+
@mod_time_at_last_read = Time.parse(@metadata['mtime']) if @metadata.has? 'mtime'
|
85
|
+
ensure_same_owner!
|
88
86
|
end
|
89
87
|
|
90
|
-
def
|
91
|
-
@metadata['
|
88
|
+
def content_encrypted?
|
89
|
+
@metadata['encrypted'] == 'true'
|
92
90
|
end
|
93
91
|
|
94
|
-
def
|
95
|
-
|
92
|
+
def encrypt_content!
|
93
|
+
raise "Owner <#{@owner.name}> cannot encrypt" unless @owner.can_encrypt?
|
94
|
+
|
95
|
+
@metadata['encrypted'] = 'true'
|
96
96
|
end
|
97
97
|
|
98
|
-
def
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
98
|
+
def do_not_encrypt_content!
|
99
|
+
@metadata['encrypted'] = 'false'
|
100
|
+
end
|
101
|
+
|
102
|
+
private
|
103
|
+
|
104
|
+
def do_mod_time_check
|
105
|
+
ClWiki::Util.raise_if_mtime_not_equal(@mod_time_at_last_read, full_path_and_name)
|
106
|
+
unless @client_last_read_mod_time.nil?
|
107
|
+
ClWiki::Util.raise_if_mtime_not_equal(@client_last_read_mod_time, full_path_and_name)
|
106
108
|
end
|
107
109
|
end
|
108
110
|
|
109
|
-
def
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
111
|
+
def update_metadata
|
112
|
+
@metadata['mtime'] = Time.now
|
113
|
+
@metadata['owner'] = @owner.name
|
114
|
+
end
|
115
|
+
|
116
|
+
def ensure_same_owner!
|
117
|
+
meta_owner = @metadata['owner']
|
118
|
+
is_legacy_file = meta_owner.to_s.empty?
|
119
|
+
unless is_legacy_file || meta_owner == @owner.name
|
120
|
+
raise "Owner must match: <#{meta_owner}> - <#{@owner.name}>"
|
117
121
|
end
|
118
122
|
end
|
123
|
+
end
|
119
124
|
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
end
|
125
|
+
class Metadata
|
126
|
+
def self.split_file_contents(lines)
|
127
|
+
st_idx = 0
|
128
|
+
lines.each_with_index do |ln, index|
|
129
|
+
next unless ln.chomp.empty?
|
130
|
+
|
131
|
+
next_line = lines[index + 1]
|
132
|
+
if next_line.nil? || next_line.chomp.empty?
|
133
|
+
st_idx = index + 2 if all_lines_are_metadata_lines(lines[0..index - 1])
|
134
|
+
break
|
131
135
|
end
|
132
136
|
end
|
133
137
|
|
134
|
-
|
135
|
-
|
136
|
-
else
|
137
|
-
[[], raw_lines]
|
138
|
-
end
|
138
|
+
m, c = st_idx > 0 ? [lines[0..st_idx - 3], lines[st_idx..-1]] : [[], lines]
|
139
|
+
[self.new(m), c]
|
139
140
|
end
|
140
141
|
|
141
|
-
def all_lines_are_metadata_lines(lines)
|
142
|
+
def self.all_lines_are_metadata_lines(lines)
|
142
143
|
lines.map { |ln| ln.scan(/\A(\w+):?/) }.flatten.
|
143
|
-
map { |k|
|
144
|
+
map { |k| supported_keys.include?(k) }.uniq == [true]
|
144
145
|
end
|
145
146
|
|
146
|
-
def
|
147
|
-
|
147
|
+
def self.supported_keys
|
148
|
+
%w[mtime encrypted owner]
|
149
|
+
end
|
150
|
+
|
151
|
+
def initialize(lines = [])
|
152
|
+
@hash = {}
|
153
|
+
@keys = Metadata.supported_keys
|
154
|
+
parse_lines(lines)
|
155
|
+
end
|
156
|
+
|
157
|
+
def [](key)
|
158
|
+
@hash[key]
|
159
|
+
end
|
160
|
+
|
161
|
+
def []=(key, value)
|
162
|
+
raise "Unexpected key: #{key}" unless @keys.include?(key)
|
163
|
+
|
164
|
+
@hash[key] = value
|
165
|
+
end
|
166
|
+
|
167
|
+
def has?(key)
|
168
|
+
@hash.key?(key)
|
169
|
+
end
|
170
|
+
|
171
|
+
def to_s
|
172
|
+
@hash.collect { |k, v| "#{k}: #{v}" }.join("\n") + "\n\n\n"
|
173
|
+
end
|
174
|
+
|
175
|
+
def to_h
|
176
|
+
@hash
|
177
|
+
end
|
178
|
+
|
179
|
+
private
|
180
|
+
|
181
|
+
def parse_lines(lines)
|
148
182
|
lines.each do |ln|
|
149
183
|
key, value = ln.split(': ')
|
150
|
-
@
|
184
|
+
@hash[key] = value.chomp if @keys.include?(key)
|
151
185
|
end
|
152
186
|
end
|
153
|
-
|
154
|
-
def apply_metadata
|
155
|
-
@modTimeAtLastRead = Time.parse(@metadata['mtime']) if @metadata.keys.include? 'mtime'
|
156
|
-
end
|
157
187
|
end
|
158
188
|
|
159
189
|
class Util
|
160
|
-
def self.
|
190
|
+
def self.raise_if_mtime_not_equal(mtime_to_compare, file_name)
|
161
191
|
# reading the instance .mtime appears to take Windows DST into account,
|
162
192
|
# whereas the static File.mtime(filename) method does not
|
163
|
-
current_mtime = ::File.open(file_name)
|
164
|
-
f.mtime
|
165
|
-
end
|
193
|
+
current_mtime = ::File.open(file_name, &:mtime)
|
166
194
|
compare_read_times!(mtime_to_compare, current_mtime)
|
167
195
|
end
|
168
196
|
|
@@ -176,25 +204,20 @@ module ClWiki
|
|
176
204
|
end
|
177
205
|
|
178
206
|
def self.dump_time(time)
|
179
|
-
|
180
|
-
s <<
|
207
|
+
String.new.tap do |s|
|
208
|
+
s << time.to_s
|
181
209
|
s << ".#{time.usec}" if time.respond_to?(:usec)
|
182
210
|
end
|
183
211
|
end
|
184
212
|
|
185
|
-
def self.
|
186
|
-
|
187
|
-
newpath = newpath.gsub(/\\/, ::File::SEPARATOR)
|
188
|
-
return newpath
|
213
|
+
def self.convert_to_native_path(path)
|
214
|
+
path.gsub(%r{/}, ::File::SEPARATOR).gsub(/\\/, ::File::SEPARATOR)
|
189
215
|
end
|
190
216
|
end
|
191
217
|
|
192
|
-
class FileError <
|
218
|
+
class FileError < RuntimeError
|
193
219
|
end
|
194
220
|
|
195
221
|
class FileModifiedSinceRead < FileError
|
196
222
|
end
|
197
|
-
|
198
|
-
class FileMustUseWriteNewContent < FileError
|
199
|
-
end
|
200
223
|
end
|