clwiki 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (134) hide show
  1. data/LICENSE +31 -0
  2. data/Rakefile +53 -0
  3. data/app/assets/javascripts/cl_wiki/application.js +29 -0
  4. data/app/assets/stylesheets/cl_wiki/application.css +103 -0
  5. data/app/controllers/cl_wiki/application_controller.rb +4 -0
  6. data/app/controllers/cl_wiki/page_controller.rb +106 -0
  7. data/app/helpers/cl_wiki/application_helper.rb +4 -0
  8. data/app/views/cl_wiki/page/edit.html.erb +8 -0
  9. data/app/views/cl_wiki/page/find.html.erb +27 -0
  10. data/app/views/cl_wiki/page/recent.html.erb +4 -0
  11. data/app/views/cl_wiki/page/recent.rss.builder +18 -0
  12. data/app/views/cl_wiki/page/show.html.erb +1 -0
  13. data/app/views/layouts/cl_wiki/application.html.erb +14 -0
  14. data/config/clwiki.yml +73 -0
  15. data/config/initializers/clwiki.rb +9 -0
  16. data/config/routes.rb +15 -0
  17. data/lib/cl_wiki.rb +12 -0
  18. data/lib/cl_wiki/configuration.rb +171 -0
  19. data/lib/cl_wiki/engine.rb +5 -0
  20. data/lib/cl_wiki/file.rb +171 -0
  21. data/lib/cl_wiki/find_in_file.rb +33 -0
  22. data/lib/cl_wiki/format/format.blockquote.rb +15 -0
  23. data/lib/cl_wiki/format/format.graphviz.digraph.rb +16 -0
  24. data/lib/cl_wiki/format/format.opml.rb +105 -0
  25. data/lib/cl_wiki/format/format.pre.blockquote.rb +15 -0
  26. data/lib/cl_wiki/format/format.simpletable.rb +25 -0
  27. data/lib/cl_wiki/index.rb +455 -0
  28. data/lib/cl_wiki/page.rb +516 -0
  29. data/lib/cl_wiki/tools/cron.reminders.rb +241 -0
  30. data/lib/cl_wiki/tools/movepages.rb +27 -0
  31. data/lib/cl_wiki/tools/pagestomove.txt +56 -0
  32. data/lib/cl_wiki/tools/rublog/clWiki.rb +62 -0
  33. data/lib/cl_wiki/tools/rublog/readme.txt +2 -0
  34. data/lib/cl_wiki/tools/singlepage.rb +58 -0
  35. data/lib/cl_wiki/tools/test/singlepagetest.rb +9 -0
  36. data/lib/cl_wiki/tools/thunderbird.rb +23 -0
  37. data/lib/cl_wiki/version.rb +3 -0
  38. data/test/dummy/README.rdoc +259 -0
  39. data/test/dummy/Rakefile +6 -0
  40. data/test/dummy/app/assets/javascripts/application.js +16 -0
  41. data/test/dummy/app/assets/stylesheets/application.css +13 -0
  42. data/test/dummy/app/controllers/application_controller.rb +5 -0
  43. data/test/dummy/app/helpers/application_helper.rb +2 -0
  44. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  45. data/test/dummy/config.ru +4 -0
  46. data/test/dummy/config/application.rb +37 -0
  47. data/test/dummy/config/boot.rb +9 -0
  48. data/test/dummy/config/database.yml +25 -0
  49. data/test/dummy/config/environment.rb +5 -0
  50. data/test/dummy/config/environments/development.rb +34 -0
  51. data/test/dummy/config/environments/production.rb +81 -0
  52. data/test/dummy/config/environments/test.rb +36 -0
  53. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  54. data/test/dummy/config/initializers/inflections.rb +16 -0
  55. data/test/dummy/config/initializers/locale.rb +7 -0
  56. data/test/dummy/config/initializers/mime_types.rb +5 -0
  57. data/test/dummy/config/initializers/secret_token.rb +12 -0
  58. data/test/dummy/config/initializers/session_store.rb +3 -0
  59. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  60. data/test/dummy/config/locales/en.yml +23 -0
  61. data/test/dummy/config/routes.rb +5 -0
  62. data/test/dummy/db/development.sqlite3 +0 -0
  63. data/test/dummy/log/development.log +1963 -0
  64. data/test/dummy/log/test.log +1340 -0
  65. data/test/dummy/public/404.html +27 -0
  66. data/test/dummy/public/422.html +26 -0
  67. data/test/dummy/public/500.html +26 -0
  68. data/test/dummy/public/favicon.ico +0 -0
  69. data/test/dummy/script/rails +6 -0
  70. data/test/dummy/tmp/cache/assets/development/sprockets/13fe41fee1fe35b49d145bcc06610705 +0 -0
  71. data/test/dummy/tmp/cache/assets/development/sprockets/17ea26cbf693e610505bdc24be534847 +0 -0
  72. data/test/dummy/tmp/cache/assets/development/sprockets/1883f3d938430da389005555d27c0bad +0 -0
  73. data/test/dummy/tmp/cache/assets/development/sprockets/1b9132b83b822937e80ef987f7da1760 +0 -0
  74. data/test/dummy/tmp/cache/assets/development/sprockets/259fb44b87b29348087957b4937a1953 +0 -0
  75. data/test/dummy/tmp/cache/assets/development/sprockets/37f8e4f0491b6401433af823dfb471d9 +0 -0
  76. data/test/dummy/tmp/cache/assets/development/sprockets/48d7a2c40083020f9e7d97d4d73f26fa +0 -0
  77. data/test/dummy/tmp/cache/assets/development/sprockets/4b0bfb6eb9d6983eb9defa58dd96dae4 +0 -0
  78. data/test/dummy/tmp/cache/assets/development/sprockets/4da11f1195532cd7b80f2dde7cf843d5 +0 -0
  79. data/test/dummy/tmp/cache/assets/development/sprockets/57347ee373d74c87e1515a059c701085 +0 -0
  80. data/test/dummy/tmp/cache/assets/development/sprockets/61b40e54192bf61d97ce2aef71e7d694 +0 -0
  81. data/test/dummy/tmp/cache/assets/development/sprockets/633b01c5a65fcd6457baf30d1cc94148 +0 -0
  82. data/test/dummy/tmp/cache/assets/development/sprockets/6ad8bb345cc43acfca78c043b7bfefae +0 -0
  83. data/test/dummy/tmp/cache/assets/development/sprockets/87a335a43cb68a253dea2b6c0269a4d6 +0 -0
  84. data/test/dummy/tmp/cache/assets/development/sprockets/8a38b2f4390e68175dae4b4b1c144e2e +0 -0
  85. data/test/dummy/tmp/cache/assets/development/sprockets/8ddc1a668acec35c2707ebc47768f59c +0 -0
  86. data/test/dummy/tmp/cache/assets/development/sprockets/8f5ab7b6f73a1e9f16421b299134e39a +0 -0
  87. data/test/dummy/tmp/cache/assets/development/sprockets/9835aec4bc0277b8f02d0e86c977fdba +0 -0
  88. data/test/dummy/tmp/cache/assets/development/sprockets/ae4f771558859f9c120a0f22328e8521 +0 -0
  89. data/test/dummy/tmp/cache/assets/development/sprockets/afed0eaa6fcf7a263498a08a5cc02cf0 +0 -0
  90. data/test/dummy/tmp/cache/assets/development/sprockets/be786e5567855cdc6817603725fd1b8d +0 -0
  91. data/test/dummy/tmp/cache/assets/development/sprockets/bf9b02df32690fb2a936818715d611f3 +0 -0
  92. data/test/dummy/tmp/cache/assets/development/sprockets/c2bf9d91a6a2786263b9912b948f435d +0 -0
  93. data/test/dummy/tmp/cache/assets/development/sprockets/ce4c918439a53cb89d02313ed990d5de +0 -0
  94. data/test/dummy/tmp/cache/assets/development/sprockets/d771ace226fc8215a3572e0aa35bb0d6 +0 -0
  95. data/test/dummy/tmp/cache/assets/development/sprockets/d9c791f08c547f30854ad746a89b0bb5 +0 -0
  96. data/test/dummy/tmp/cache/assets/development/sprockets/ddc3a7b5173ff5c911a53004b56e4305 +0 -0
  97. data/test/dummy/tmp/cache/assets/development/sprockets/dfed1391742203d15f08cb07173bccba +0 -0
  98. data/test/dummy/tmp/cache/assets/development/sprockets/e282b6bdaa0e070754f8558b9de5e417 +0 -0
  99. data/test/dummy/tmp/cache/assets/development/sprockets/f0e957c30443ade693f73ff470f0f894 +0 -0
  100. data/test/dummy/tmp/cache/assets/development/sprockets/f6b3cbb9c04d5af74d780464c9a34ee5 +0 -0
  101. data/test/dummy/tmp/cache/assets/development/sprockets/fb41fedee86fd2d10ddd938bf5d68eb7 +0 -0
  102. data/test/dummy/tmp/cache/assets/test/sprockets/1883f3d938430da389005555d27c0bad +0 -0
  103. data/test/dummy/tmp/cache/assets/test/sprockets/48d7a2c40083020f9e7d97d4d73f26fa +0 -0
  104. data/test/dummy/tmp/cache/assets/test/sprockets/61b40e54192bf61d97ce2aef71e7d694 +0 -0
  105. data/test/dummy/tmp/cache/assets/test/sprockets/8f5ab7b6f73a1e9f16421b299134e39a +0 -0
  106. data/test/dummy/tmp/cache/assets/test/sprockets/9835aec4bc0277b8f02d0e86c977fdba +0 -0
  107. data/test/dummy/tmp/cache/assets/test/sprockets/ae4f771558859f9c120a0f22328e8521 +0 -0
  108. data/test/dummy/tmp/cache/assets/test/sprockets/be786e5567855cdc6817603725fd1b8d +0 -0
  109. data/test/dummy/tmp/cache/assets/test/sprockets/c2bf9d91a6a2786263b9912b948f435d +0 -0
  110. data/test/dummy/tmp/cache/assets/test/sprockets/ce4c918439a53cb89d02313ed990d5de +0 -0
  111. data/test/dummy/tmp/cache/assets/test/sprockets/e282b6bdaa0e070754f8558b9de5e417 +0 -0
  112. data/test/dummy/tmp/cache/assets/test/sprockets/f0e957c30443ade693f73ff470f0f894 +0 -0
  113. data/test/dummy/tmp/cache/assets/test/sprockets/f6b3cbb9c04d5af74d780464c9a34ee5 +0 -0
  114. data/test/dummy/tmp/testrep/FooBar.txt +1 -0
  115. data/test/dummy/tmp/testrep/FrontPage.txt +1 -0
  116. data/test/dummy/tmp/testrep/QuuxBaz.txt +1 -0
  117. data/test/dummy/wikirep/AboutClWiki.txt +31 -0
  118. data/test/dummy/wikirep/ChrisMorris.txt +4 -0
  119. data/test/dummy/wikirep/DotTest.txt +6 -0
  120. data/test/dummy/wikirep/FooBar.txt +4 -0
  121. data/test/dummy/wikirep/FooBarQuux.txt +4 -0
  122. data/test/dummy/wikirep/FrontPage.txt +14 -0
  123. data/test/dummy/wikirep/HtmlAreaTest.txt +4 -0
  124. data/test/dummy/wikirep/PreTagsTest.txt +27 -0
  125. data/test/dummy/wikirep/TheMan.txt +4 -0
  126. data/test/helpers/wiki_helper_test.rb +4 -0
  127. data/test/lib/clwiki/clwiki_test_helper.rb +3 -0
  128. data/test/lib/clwiki/file_test.rb +93 -0
  129. data/test/lib/clwiki/find_in_file_test.rb +111 -0
  130. data/test/lib/clwiki/index_test.rb +32 -0
  131. data/test/lib/clwiki/page_test.rb +239 -0
  132. data/test/lib/clwiki/test_base.rb +25 -0
  133. data/test/test_helper.rb +15 -0
  134. metadata +312 -0
@@ -0,0 +1,105 @@
1
+ if __FILE__ == $0
2
+ $LOAD_PATH << ".."
3
+ require 'clwikipage'
4
+ end
5
+
6
+ class FormatOPML < ClWiki::CustomFormatter
7
+ def FormatOPML.match_re
8
+ /<opml.*?>.*?<\/opml>/m
9
+ end
10
+
11
+ def FormatOPML.format_content(content, page)
12
+ out = ['<NoWikiLinks>']
13
+ content.grep(/<outline.*?>|<\/outline>/).each do |ln|
14
+ title = ln.scan(/title=\"(.*?)\"/).compact
15
+ html = ln.scan(/htmlUrl=\"(.*?)\"/).compact
16
+ xml = ln.scan(/xmlUrl=\"(.*?)\"/).compact
17
+ if html.empty? && xml.empty?
18
+ if !title.empty?
19
+ out << "<h4>#{title}</h4>"
20
+ out << '<blockquote>'
21
+ else
22
+ out << '</blockquote>'
23
+ end
24
+ else
25
+ out << "<a href='#{xml}'>[xml]</a> <a href='#{html}'>#{title}</a>"
26
+ end
27
+ end
28
+ out.join("\n") + content
29
+ end
30
+ end
31
+
32
+ ClWiki::CustomFormatters.instance.register(FormatOPML)
33
+
34
+ if __FILE__ == $0
35
+ sample_opml = <<-OPMLTEXT
36
+ <opml xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
37
+ <head>
38
+ <title>Generated by SharpReader - http://www.sharpreader.net</title>
39
+ </head>
40
+ <body>
41
+ <outline type="rss" title="{ | one, step, back | }" description="Jim Weirich's Blog" xmlUrl="http://onestepback.org/index.cgi/index.rss" htmlUrl="http://onestepback.org/index.cgi" />
42
+ <outline type="rss" title="A Few Comments (Bill Caputo)" description="" xmlUrl="http://www.williamcaputo.com/index.rdf" htmlUrl="http://www.williamcaputo.com/" />
43
+ <outline type="rss" title="Allen Bauer's blog..." description="Borland Delphi and C#Builder IDE Architect.&#xA;Just jumping on the blogging bandwagon... oh look a cliff.." xmlUrl="http://homepages.borland.com/abauer/rss.xml" htmlUrl="http://homepages.borland.com/abauer" />
44
+ <outline type="rss" title="Artima Weblogs" description="Artima Weblogs is a community of bloggers posting on a wide range of topics of interest to software developers." xmlUrl="http://www.artima.com/weblogs/feeds/weblogs.rss" htmlUrl="http://www.artima.com/weblogs/" />
45
+ <outline type="rss" title="Bit Banger" description="The definitive source of everything Adam Keys." xmlUrl="http://www.trmk.org/~adam/blog/index.rdf" htmlUrl="http://trmk.org/~adam/blog/" />
46
+ <outline type="rss" title="bt.etree.org" description="etree.org BitTorrent Tracker" xmlUrl="http://bt.etree.org/rss/bt_etree_org.rdf" htmlUrl="http://bt.etree.org/" />
47
+ <outline type="rss" title="Cem Kaner's blog" description="Cem Kaner's weblog&#xA;Software testing, software safety, software law." xmlUrl="http://blackbox.cs.fit.edu/blog/kaner/index.rdf" htmlUrl="http://blackbox.cs.fit.edu/blog/kaner/" />
48
+ <outline type="rss" title="ChadFowler.com" description="Chad Fowler's Random Posts on Computing, Language, and Travel" xmlUrl="http://www.chadfowler.com/?rss " htmlUrl="http://www.chadfowler.com/index.cgi" />
49
+ <outline type="rss" title="cLabs Blogki" description="cLabs Blogki" xmlUrl="http://www.clabs.org/blogki/blogki.rss.cgi " htmlUrl="http://www.clabs.org/blogki" />
50
+ <outline type="rss" title="Clay Shirky's Essays" description="Clay Shirky's Essays" xmlUrl="http://www.shirky.com/writings/rss.cgi" htmlUrl="http://www.shirky.com/writings/rss.cgi" />
51
+ <outline type="rss" title="Collaborative Software Testing (Jonathan Kohl)" description="Jonathan Kohl's blog. Exploring tester and developer collaboration." xmlUrl="http://www.kohl.ca/blog/index.rdf" htmlUrl="http://www.kohl.ca/blog/" />
52
+ <outline type="rss" title="Common Content: Newest Items" description="Common Content's latest posted items." xmlUrl="http://www.commoncontent.org/rss/newest.cgi" htmlUrl="http://www.commoncontent.org/" />
53
+ <outline type="rss" title="Conversations with Dale" description="Dale H. Emery's Journal" xmlUrl="http://www.dhemery.com/journal/index.rdf " htmlUrl="http://www.dhemery.com/journal/" />
54
+ <outline type="rss" title="Creative Commons: weblog" description="Creative Commons: weblog" xmlUrl="http://www.creativecommons.org/weblog/rss " htmlUrl="http://creativecommons.org/weblog/" />
55
+ <outline type="rss" title="Dan Bricklin's Log" description="VisiCalc co-creator Dan Bricklin chronicles his life in the computer world with pictures, text, and commentary." xmlUrl="http://danbricklin.com/log_rss.xml" htmlUrl="http://danbricklin.com/log" />
56
+ <outline type="rss" title="Don Box's Spoutlet" description="Rants from the SOAP box" xmlUrl="http://www.gotdotnet.com/team/dbox/rss.aspx" htmlUrl="http://www.gotdotnet.com/team/dbox/default.aspx" />
57
+ <outline type="rss" title="Eric.Weblog()" description="Thoughts about software from yet another person who invented the Internet" xmlUrl="http://biztech.ericsink.com/rss.xml" htmlUrl="http://software.ericsink.com/" />
58
+ <outline type="rss" title="Exploration Through Example (Brian Marick)" description="Exploration Through Example - Brian Marick" xmlUrl="http://www.testing.com/cgi-bin/blog/index.rss " htmlUrl="http://www.testing.com/cgi-bin/blog" />
59
+ <outline title="Fluffy">
60
+ <outline type="rss" title="/\ndy's Weblog" description="" xmlUrl="http://www.toolshed.com/blog/index.rss " htmlUrl="http://www.toolshed.com/blog" />
61
+ <outline type="rss" title="Bill Dudney's Weblog" description="Bill Dudney's Weblog" xmlUrl="http://bill.dudney.net/roller/rss/bill" htmlUrl="http://bill.dudney.net/roller/page/bill" />
62
+ <outline type="rss" title="Duncan's Blog" description="Personal website for James Duncan Davidson" xmlUrl="http://x180.net/Blog/index.rss " htmlUrl="http://x180.net" />
63
+ <outline type="rss" title="Glenn Vanderburg: Weblog" description="Glenn Vanderburg's personal weblog." xmlUrl="http://www.vanderburg.org/cgi-bin/glv/blosxom?flav=rss " htmlUrl="http://www.vanderburg.org/cgi-bin/glv/blosxom" />
64
+ <outline type="rss" title="Mike Clark" description="Mike's soapbox of life in the trenches" xmlUrl="http://www.clarkware.com/cgi/blosxom/index.rss" htmlUrl="http://www.clarkware.com/cgi/blosxom" />
65
+ <outline type="rss" title="Ockham's Flashlight (Stuart Halloway)" description="Stuart Halloway on software development, technology, and the future." xmlUrl="http://www.relevancellc.com/halloway/weblog/rss.xml" htmlUrl="http://www.relevancellc.com/halloway/weblog/" />
66
+ <outline type="rss" title="Potential Differences (Greg Vaughn)" description="Greg Vaughn on Java, Agile methodologies, OS X, whatever piques my interest!" xmlUrl="http://gigavolt.net/blog/index.rss" htmlUrl="http://gigavolt.net/blog" />
67
+ <outline type="rss" title="PragDave" description="Dave's Weblog: Pragmatic Programming." xmlUrl="http://pragprog.com/pragdave/index.rss " htmlUrl="http://pragprog.com/pragdave" />
68
+ <outline type="rss" title="Servlets.com Weblog (Jason Hunter)" description="Java, Open Source, XML, Web Services, and (gasp) .NET" xmlUrl="http://www.servlets.com/blog/index-all.xml" htmlUrl="http://www.servlets.com/blog/" />
69
+ </outline>
70
+ <outline type="rss" title="Joel on Software" description="Painless Software Management" xmlUrl="http://www.joelonsoftware.com/rss.xml " htmlUrl="http://www.joelonsoftware.com" />
71
+ <outline type="rss" title="Luke Hutteman's Weblog" description="Luke Hutteman on Java, C#, J2EE, RSS and whatever else comes to mind..." xmlUrl="http://www.hutteman.com/weblog/rss.xml" htmlUrl="http://www.hutteman.com/weblog/" />
72
+ <outline type="rss" title="Managing Product Development" description="Management, especially good management, is hard to do. This blog is for people who want to think about how they manage people, projects, and risk." xmlUrl="http://www.jrothman.com/weblog/RSS/mpdblogger_rss.xml" htmlUrl="http://www.jrothman.com/weblog/blogger.html" />
73
+ <outline type="rss" title="Martin Fowler's Bliki" description="A cross between a blog and wiki of my partly-formed ideas on software development" xmlUrl="http://martinfowler.com/bliki/bliki.rss" htmlUrl="http://martinfowler.com/bliki" />
74
+ <outline type="rss" title="mezzoblue" description="" xmlUrl="http://www.mezzoblue.com/rss/index.xml" htmlUrl="http://www.mezzoblue.com/" />
75
+ <outline type="rss" title="Michael Feathers' Weblog" description="Let's Reconsider That" xmlUrl="http://www.artima.com/weblogs/feeds/bloggers/mfeathers.rss" htmlUrl="http://www.artima.com/weblogs/index.jsp?blogger=mfeathers" />
76
+ <outline type="rss" title="OK/Cancel" description="OK/Cancel is a comic strip written for a very specific audience, but much of what we talk about is quite universal. Most everybody can relate to things in the world which don't work like they should. You needn't be a usability specialist, interaction designer, industrial designer or any sort of designer to appreciate that frustration. But if you ARE any of those aforementioned people or have had the pleasure and pain of working with one or more of this rare breed, this strip is for you." xmlUrl="http://www.ok-cancel.com/index.rdf" htmlUrl="http://www.ok-cancel.com/" />
77
+ <outline type="rss" title="open.neurosaudio.com" description="" xmlUrl="http://open.neurosaudio.com/index.rdf" htmlUrl="http://open.neurosaudio.com/" />
78
+ <outline title="Ruby">
79
+ <outline type="rss" title="Ruby Application Archive" description="Summary for Ruby Application Archive, provided by Bulknews." xmlUrl="http://bulknews.net/rss/rdf.cgi?RAA" htmlUrl="http://www.ruby-lang.org/en/raa.html" />
80
+ <outline type="rss" title="Ruby Garden Wiki" description="Recent Changes to the Ruby Garden" xmlUrl="http://www.rubygarden.com/rdf/cached/rubygarden-wiki.rdf" htmlUrl="http://www.rubygarden.org/ruby" />
81
+ <outline type="rss" title="Ruby Weekly News" description="Recent news about Ruby" xmlUrl="http://www.rubygarden.com//rdf/cached/rurl.rdf" htmlUrl="http://www.rubygarden.org/rurl/html/index.html" />
82
+ <outline type="rss" title="Ruby XML" description="" xmlUrl="http://www.rubyxml.com/rss0.91.xml" htmlUrl="" />
83
+ <outline type="rss" title="ruby-doc" description="Recent postings to the Ruby Documentation Project web site." xmlUrl="http://www.ruby-doc.org/index.rb/rss0.91.xml" htmlUrl="http://www.ruby-doc.org/index.rb" />
84
+ </outline>
85
+ <outline type="rss" title="Ruminations" description="" xmlUrl="http://www.mcmains.net/ruminations/rss " htmlUrl="http://www.mcmains.net/ruminations" />
86
+ <outline type="rss" title="SATN" description="Bob, David, and Dan's comments" xmlUrl="http://www.satn.org/satn_rss.xml" htmlUrl="http://www.satn.org" />
87
+ <outline type="rss" title="Secure Programming News" description="News &amp; information related to secure programming topics" xmlUrl="http://www.secureprogramming.com/?action=rss&amp;feature=weblog" htmlUrl="http://www.secureprogramming.com/" />
88
+ <outline type="rss" title="Secure Programming Recipes" description="Cookbook-style recipes for tackling programming problems securely." xmlUrl="http://www.secureprogramming.com/website.py?action=rss&amp;feature=recipes" htmlUrl="http://www.secureprogramming.com/?action=browse&amp;feature=recipes" />
89
+ <outline type="rss" title="simplegeek (Chris Anderson - MS Architect)" description="" xmlUrl="http://www.simplegeek.com/blogxbrowsing.asmx/GetRss?" htmlUrl="http://www.simplegeek.com" />
90
+ <outline type="rss" title="Slashdot" description="News for nerds, stuff that matters" xmlUrl="http://slashdot.org/slashdot.rss" htmlUrl="http://slashdot.org/" />
91
+ <outline type="rss" title="Software (Management) Process Improvement" description="&quot;Poor management can increase software costs more rapidly than any other factor.&quot; (Barry Boehm)" xmlUrl="http://www.estherderby.com/weblog/RSS/blogger_rss.xml" htmlUrl="http://www.estherderby.com/weblog/blogger.html" />
92
+ <outline type="rss" title="SourceForge.net: Project File Releases: Neuros Database Manipulator" description="SF.net File Releases: Neuros Database Manipulator (neurosdbm project) - Neuros Database Manipulator - Browse and modify the database of your Neuros Audio Computer. Neuros Database Manipulator is written in Java for cross platform support." xmlUrl="http://sourceforge.net/export/rss2_projfiles.php?group_id=83367" htmlUrl="http://sourceforge.net/projects/neurosdbm/" />
93
+ <outline type="rss" title="SQLServerCentral.Com - Articles" description="Articles posted on the SQLServercentral.com site." xmlUrl="http://www.sqlservercentral.com/sscrss.xml" htmlUrl="http://www.sqlservercentral.com" />
94
+ <outline type="rss" title="Testing Hotlist Update" description="Bret Pettichord's Weblog. Observations of a Software Tester." xmlUrl="http://www.io.com/~wazmo/blog/index.rdf" htmlUrl="http://www.io.com/~wazmo/blog/" />
95
+ <outline type="rss" title="The Idea Ether" description="Rich Kilmer's place to express the ideas that bounce around in his head." xmlUrl="http://richkilmer.blogs.com/ether/index.rdf" htmlUrl="http://richkilmer.blogs.com/ether/" />
96
+ <outline type="rss" title="The Old New Thing" description="" xmlUrl="http://blogs.gotdotnet.com/raymondc/blogxbrowsing.asmx/GetRss?" htmlUrl="http://blogs.gotdotnet.com/raymondc/" />
97
+ <outline type="rss" title="Thinking About Computing (Bruce Eckel)" description="Bruce Eckel's Web Log" xmlUrl="http://mindview.net/WebLog/RSS.xml" htmlUrl="http://www.MindView.net/WebLog/" />
98
+ <outline type="rss" title="Ward Cunningham's Weblog" description="Ward Says, Don't Try This at Home" xmlUrl="http://www.artima.com/weblogs/feeds/bloggers/ward.rss " htmlUrl="http://www.artima.com/weblogs/index.jsp?blogger=ward" />
99
+ <outline type="rss" title="Web Testing with Ruby" description="Web Testing with Ruby" xmlUrl="http://www.clabs.org/wtr/blogki.rss.cgi" htmlUrl="http://www.clabs.org//wtr/index.cgi" />
100
+ <outline type="rss" title="whytheluckystiff.net" description="we've all got our ways of dealing with it." xmlUrl="http://whytheluckystiff.net/why.xml" htmlUrl="http://www.whytheluckystiff.net/" />
101
+ </body>
102
+ </opml>
103
+ OPMLTEXT
104
+ puts FormatOPML.format_content(sample_opml, nil)
105
+ end
@@ -0,0 +1,15 @@
1
+ require 'cgi'
2
+
3
+ class FormatPreBlockquote < ClWiki::CustomFormatter
4
+ def FormatPreBlockquote.match_re
5
+ /\[p\].*?\[\/p\]/mi
6
+ end
7
+
8
+ def FormatPreBlockquote.format_content(content, page)
9
+ content = CGI.escapeHTML(content)
10
+ content.gsub!(/\[p\]/i, "<blockquote><pre>")
11
+ content.gsub!(/\[\/p\]/i, "</pre></blockquote>")
12
+ end
13
+ end
14
+
15
+ ClWiki::CustomFormatters.instance.register(FormatPreBlockquote)
@@ -0,0 +1,25 @@
1
+ class FormatSimpleTable < ClWiki::CustomFormatter
2
+ def FormatSimpleTable.match_re
3
+ /<simpletable.*?>.*?<\/simpletable>/m
4
+ end
5
+
6
+ def FormatSimpleTable.format_content(content, page=nil)
7
+ table_attr = content.scan(/<simpletable(.*?)>/m).to_s.strip
8
+ table_attr = 'border="1"' if table_attr.empty?
9
+ content.gsub!(/<simpletable.*?>/m, '')
10
+ content.gsub!(/<\/simpletable>/m, '')
11
+ content.strip!
12
+ lines = content.split("\n")
13
+ lines.collect! do |ln|
14
+ ln.gsub!(/\t/, ' ')
15
+ '<tr><td>' + ln.gsub(/ +/, '</td><td>') + '</td></tr>'
16
+ end
17
+ lines.collect! do |ln| ln.gsub(/<td>\s*?<\/td>/, '<td>&nbsp;</td>') end
18
+
19
+ # 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
+ end
23
+ end
24
+
25
+ ClWiki::CustomFormatters.instance.register(FormatSimpleTable)
@@ -0,0 +1,455 @@
1
+ require 'rubygems'
2
+
3
+ require File.dirname(__FILE__) + '/page'
4
+ require File.dirname(__FILE__) + '/configuration'
5
+ require 'cl/util/progress'
6
+ require 'cl/util/console'
7
+
8
+ gem 'clindex'
9
+ require 'index'
10
+
11
+ require 'drb'
12
+
13
+ module ClWiki
14
+ class Indexer
15
+ attr_reader :index
16
+
17
+ WAIT = true
18
+
19
+ def self.defaultPort
20
+ '9111'
21
+ end
22
+
23
+ def initialize(wiki_conf=$wiki_conf, fn=nil)
24
+ @wiki_conf = wiki_conf
25
+
26
+ @index = ClIndex.new
27
+ @recent = ClIndex.new
28
+ @pages = ClIndex.new
29
+ @hits = ClIndex.new if @wiki_conf.access_log_index
30
+ @rootDir = @wiki_conf.wiki_path
31
+ @fn = fn
32
+ @record_hits = true
33
+ load
34
+ end
35
+
36
+ def do_puts(text)
37
+ if @fn
38
+ File.open(@fn, 'a+') do |f|
39
+ f.puts text
40
+ end
41
+ else
42
+ puts text
43
+ end
44
+ end
45
+
46
+ def build(limit=-1, purge=false)
47
+ @record_hits = false
48
+ begin
49
+ fileCount = 0
50
+ raise '$wikiPageExt not set' if $wikiPageExt.empty? # for debugging only, really
51
+ files = Dir[::File.join(@rootDir, '**/*' + $wikiPageExt)]
52
+ if limit == -1
53
+ p = Progress.new(files.length)
54
+ else
55
+ p = Progress.new(limit)
56
+ end
57
+ p.start
58
+ files.each do |fn|
59
+ next if !::File.file?(fn)
60
+ break if (limit > -1) && (fileCount >= limit)
61
+ fileCount += 1
62
+ fullName = fn.sub(@rootDir, '')
63
+ fullName = fullName.sub(/#{$wikiPageExt}/, '')
64
+ index_page(fullName, purge)
65
+ do_puts p.progress(true)
66
+ end
67
+ ensure
68
+ @record_hits = true
69
+ end
70
+ end
71
+
72
+ def index_page(fullName, purge=false)
73
+ put_status "indexing #{fullName}" do
74
+ pg = ClWiki::Page.new(fullName, @rootDir)
75
+ pg.read_raw_content
76
+ if purge && pg.content_never_edited?
77
+ put_status("purging #{fullName}")
78
+ pg.delete
79
+ remove_page_from_index(fullName)
80
+ else
81
+ formatter = ClWiki::PageFormatter.new(pg.raw_content, fullName)
82
+ formatter.formatLinks do |word|
83
+ if formatter.is_wiki_name?(word)
84
+ word = formatter.expand_path(word, fullName)
85
+ else
86
+ word.downcase!
87
+ end
88
+ add_to_index(word, fullName)
89
+ end
90
+ add_to_index(fullName, fullName)
91
+ add_to_pages(fullName)
92
+
93
+ add_to_recent(pg.mtime, fullName)
94
+ end
95
+ end
96
+ end
97
+
98
+ def add_to_index(term, fullPageName)
99
+ @index.add(term, fullPageName, WAIT)
100
+ end
101
+
102
+ def add_to_recent(modTime, fullPageName)
103
+ # remove all other instances of this page, we only need the current modTime
104
+ @recent.remove(fullPageName, WAIT)
105
+ @recent.add(modTime, fullPageName, WAIT)
106
+ end
107
+
108
+ def add_to_pages(fullPageName)
109
+ @pages.add(fullPageName, nil, WAIT)
110
+ end
111
+
112
+ def hits_filename
113
+ ::File.join(::File.expand_path('.'), 'hits.dat')
114
+ end
115
+
116
+ def index_filename
117
+ ::File.join(::File.expand_path('.'), 'index.dat')
118
+ end
119
+
120
+ def recent_filename
121
+ ::File.join(::File.expand_path('.'), 'recent.dat')
122
+ end
123
+
124
+ def pages_filename
125
+ ::File.join(::File.expand_path('.'), 'pages.dat')
126
+ end
127
+
128
+ def remove_page_from_index(fullPageName)
129
+ @index.remove(fullPageName, WAIT)
130
+ @recent.remove(fullPageName, WAIT)
131
+ end
132
+
133
+ def put_status(status)
134
+ if block_given?
135
+ do_puts Time.now.strftime("%I:%M:%S") + ' ' + status + '... '
136
+ yield
137
+ do_puts Time.now.strftime("%I:%M:%S") + ' ' + status + ' done '
138
+ else
139
+ do_puts Time.now.strftime("%I:%M:%S") + ' ' + status
140
+ end
141
+ end
142
+
143
+ def reindex_and_save_async(fullPageName)
144
+ thread = Thread.new do
145
+ reindex_page(fullPageName)
146
+ save
147
+ end
148
+ @wiki_conf.wait_on_thread(thread)
149
+ end
150
+
151
+ def reindex_page(fullPageName)
152
+ put_status 'Reindexing ' + fullPageName do
153
+ remove_page_from_index(fullPageName)
154
+ index_page(fullPageName)
155
+ end
156
+ end
157
+
158
+ def save
159
+ put_status 'Saving' do
160
+ put_status 'Saving Main' do
161
+ @index.save(index_filename, WAIT)
162
+ end
163
+ put_status 'Saving Recent' do
164
+ @recent.save(recent_filename, WAIT)
165
+ end
166
+ put_status 'Saving Pages' do
167
+ @pages.save(pages_filename, WAIT)
168
+ end
169
+ put_status 'Saving Hits' do
170
+ @hits.save(hits_filename, WAIT) if @wiki_conf.access_log_index
171
+ end
172
+ end
173
+ end
174
+
175
+ def load
176
+ put_status 'Loading' do
177
+ put_status 'Loading Main' do
178
+ @index.load(index_filename, WAIT) if ::File.exists?(index_filename)
179
+ end
180
+ put_status 'Loading Recent' do
181
+ @recent.load(recent_filename, WAIT) if ::File.exists?(recent_filename)
182
+ end
183
+ put_status 'Loading Pages' do
184
+ @pages.load(pages_filename, WAIT) if ::File.exists?(pages_filename)
185
+ end
186
+ if @wiki_conf.access_log_index
187
+ put_status 'Loading Hits' do
188
+ @hits.load(hits_filename, WAIT) if ::File.exists?(hits_filename)
189
+ end
190
+ end
191
+ end
192
+ end
193
+
194
+ def dump_clindex(aindex, fn_prefix)
195
+ put_status "Dumping #{fn_prefix}..." do
196
+ hash = aindex.index
197
+ ::File.open(fn_prefix + '.keys.dump.txt', 'w+') do |f|
198
+ keys = hash.keys
199
+ keys.sort.each do |key|
200
+ f.puts key
201
+ end
202
+ end
203
+ File.open(fn_prefix + '.full.dump.txt', 'w+') do |f|
204
+ fullary = hash.to_a
205
+ fullary.sort!
206
+ fullary.each do |keyValueAry|
207
+ f.puts keyValueAry[0].inspect + " => " + keyValueAry[1].inspect
208
+ end
209
+ end
210
+ end
211
+ end
212
+
213
+ def dump
214
+ dump_clindex(@index, 'index')
215
+ dump_clindex(@recent, 'recent')
216
+ dump_clindex(@pages, 'pages')
217
+ dump_clindex(@hits, 'hits') if @wiki_conf.access_log_index
218
+ end
219
+
220
+ def search(text)
221
+ terms = text.split(' ')
222
+ allhits = nil
223
+ terms.each do |term|
224
+ termhits = []
225
+ @index.search(term, termhits, WAIT)
226
+ termhits.flatten!
227
+ if !allhits
228
+ allhits = termhits
229
+ else
230
+ allhits = allhits & termhits
231
+ end
232
+ end
233
+ allhits = [] if !allhits # shouldn't ever happen I'd wager
234
+ p allhits if $debug
235
+ allhits.flatten!
236
+ allhits.uniq!
237
+ allhits.sort!
238
+ p allhits if $debug
239
+ allhits
240
+ end
241
+
242
+ def sort_hits_by_recent(hits, top=-1)
243
+ hits_by_date = {}
244
+ # don't send top into this call to recent, we need all recent, then
245
+ # we filter that down to all matches, /then/ we take the topmost
246
+ # of that matching list
247
+ recent.each do |date, page_name_array|
248
+ hits_at_this_time = page_name_array & hits
249
+ hits_by_date[date] = hits_at_this_time if !hits_at_this_time.empty?
250
+ end
251
+ hits_by_date.sort { |a, b| b[0] <=> a[0] }[0..top]
252
+ end
253
+
254
+ def recent(top=-1)
255
+ @recent.do_read(WAIT) do
256
+ hash = @recent.index
257
+ hash.sort { |a, b| b[0] <=> a[0] }[0..top]
258
+ end
259
+ end
260
+
261
+ def pages_out(rootPage)
262
+ all = @index.all_terms(rootPage, WAIT)
263
+ #all.delete_if do |term|
264
+ # term[0..0] != '/' || !ClWikiPage.page_exists?(term.dup)
265
+ #end
266
+ all.delete_if do |term|
267
+ (term[0..0] != '/') || (term == '/') || (term == '//')
268
+ end
269
+ all.delete_if do |term|
270
+ !ClWikiPage.page_exists?(term.dup)
271
+ end
272
+ all
273
+ end
274
+
275
+ def page_exists?(fullPageName)
276
+ exists = false
277
+ exists = @pages.term_exists?(fullPageName, WAIT)
278
+ exists
279
+ end
280
+
281
+ def add_hit(fullPageName)
282
+ if @record_hits && @wiki_conf.access_log_index
283
+ put_status('Hit on ' + fullPageName)
284
+ @hits.add(fullPageName, Time.now, WAIT)
285
+ thread = Thread.new do
286
+ @hits.save(hits_filename, WAIT)
287
+ end
288
+ @wiki_conf.wait_on_thread(thread)
289
+ end
290
+ end
291
+
292
+ def hit_summary(start_index=0, end_index=-1)
293
+ if @wiki_conf.access_log_index
294
+ hit_index = nil
295
+ @hits.do_read(WAIT) do
296
+ hit_index = @hits.index.dup
297
+ end
298
+ hit_index.sort { |a, b| b[1].length <=> a[1].length }[start_index..end_index]
299
+ end
300
+ end
301
+ end
302
+
303
+ class IndexClient
304
+ def initialize(wiki_conf=$wiki_conf)
305
+ case wiki_conf.useIndex
306
+ when ClWiki::Configuration::USE_INDEX_NO
307
+ raise 'wikiConf.useIndex says to not use an index'
308
+ when ClWiki::Configuration::USE_INDEX_DRB
309
+ DRb.start_service()
310
+ @indexer = DRbObject.new(nil, "druby://localhost:#{wiki_conf.indexPort}")
311
+ when ClWiki::Configuration::USE_INDEX_LOCAL
312
+ $indexer ||= ClWiki::Indexer.new(wiki_conf, wiki_conf.index_log_fn)
313
+ @indexer = $indexer
314
+ end
315
+ end
316
+
317
+ def reindex_page(fullPageName)
318
+ @indexer.reindex_and_save_async(fullPageName)
319
+ end
320
+
321
+ def search(term, titles_only=false)
322
+ hits = @indexer.search(term).flatten
323
+ if titles_only
324
+ hits.delete_if do |fullName|
325
+ !(fullName =~ /#{term}/i)
326
+ end
327
+ end
328
+ hits
329
+ end
330
+
331
+ def page_exists?(fullPageName)
332
+ @indexer.page_exists?(fullPageName)
333
+ end
334
+
335
+ def sort_hits_by_recent(hits, top=-1)
336
+ @indexer.sort_hits_by_recent(hits, top)
337
+ end
338
+
339
+ def recent(top=-1)
340
+ @indexer.recent(top)
341
+ end
342
+
343
+ def add_hit(fullPageName)
344
+ @indexer.add_hit(fullPageName)
345
+ end
346
+
347
+ def hit_summary(start_index=0, end_index=-1)
348
+ @indexer.hit_summary(start_index, end_index)
349
+ end
350
+ end
351
+ end
352
+
353
+
354
+ def launch_server(port=nil, fn=nil)
355
+ port = ClWiki::Indexer.defaultPort if !port
356
+ idxServer = ClWiki::Indexer.new(fn)
357
+ puts "ClWikiIndexer launching on localhost:#{port}..."
358
+ DRb.start_service("druby://localhost:#{port}", idxServer)
359
+ DRb.thread.join
360
+ end
361
+
362
+ if __FILE__ == $0
363
+ def do_page_exists(fullPageName)
364
+ if @i.page_exists?(fullPageName)
365
+ puts fullPageName + ' exists'
366
+ else
367
+ puts fullPageName + ' does not exist'
368
+ end
369
+ end
370
+
371
+ def do_search(search)
372
+ puts @i.search(search).join("\n")
373
+ puts
374
+ end
375
+
376
+ def do_index_dump
377
+ puts 'Dumping...'
378
+ @i.dump
379
+ end
380
+
381
+ def do_recent
382
+ puts @i.recent
383
+ puts
384
+ end
385
+
386
+ def do_hits
387
+ puts @i.hit_summary.inspect
388
+ puts
389
+ end
390
+
391
+ def show_help
392
+ puts 'ClWikiIndexer'
393
+ puts
394
+ puts '-h Show this help'
395
+ puts
396
+ puts '-s Launch drb server'
397
+ puts "-p Drb port. Default is #{ClWiki::Indexer.defaultPort}"
398
+ puts '-f [fn] File to route output to. stdout used if not specified'
399
+ puts '-b Do a full re-build of the index'
400
+ puts '-bp Do a full re-build, purging unused pages. An unused page'
401
+ puts ' is one where the contents are the default content after'
402
+ puts ' creation, but has never been edited.'
403
+ puts '-l [x] If -b, limit number of pages built to x'
404
+ puts '<none> load index to search for terms entered in stdin'
405
+ puts '-q [term] load index and search for term'
406
+ puts '-r [page] load index and see if page exists'
407
+ puts '-x [page] load index and re-index the specified page'
408
+ puts '-d debug'
409
+ puts '-dump dumps full index to text file'
410
+ puts '-recent show 1st recent hits'
411
+ puts '-hits show 1st hit count'
412
+ end
413
+
414
+ $debug = if_switch('-d')
415
+
416
+ if if_switch('-h')
417
+ show_help
418
+ elsif if_switch('-s')
419
+ launch_server(get_switch('-p'), get_switch('-f'))
420
+ elsif if_switch('-b') || if_switch('-bp')
421
+ limit = -1
422
+ limit = get_switch('-l').to_i if get_switch('-l')
423
+ @i = ClWiki::Indexer.new
424
+ $wiki_conf.access_log_index = false
425
+ @i.build(limit, if_switch('-bp'))
426
+ @i.save
427
+ else
428
+ puts 'loading index...'
429
+ @i = ClWiki::Indexer.new
430
+ $wiki_conf.access_log_index = false
431
+ #@i.load
432
+ if get_switch('-q')
433
+ do_search(get_switch('-q'))
434
+ elsif if_switch('-recent')
435
+ do_recent
436
+ elsif if_switch('-hits')
437
+ do_hits
438
+ elsif get_switch('-r')
439
+ do_page_exists(get_switch('-r'))
440
+ elsif if_switch('-dump')
441
+ do_index_dump
442
+ elsif if_switch('-x')
443
+ @i.index_page(get_switch('-x'))
444
+ @i.save
445
+ else
446
+ begin
447
+ print 'input search term (empty to quit): '
448
+ search = gets.chomp
449
+ break if search.empty?
450
+ do_search(search)
451
+ end while true
452
+ end
453
+ end
454
+ end
455
+