ruwiki 0.9.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 (96) hide show
  1. data/Readme.rubygems +86 -0
  2. data/Readme.tarfile +65 -0
  3. data/bin/ruwiki +58 -0
  4. data/bin/ruwiki.cgi +87 -0
  5. data/bin/ruwiki_convert +56 -0
  6. data/bin/ruwiki_service.rb +82 -0
  7. data/bin/ruwiki_servlet +53 -0
  8. data/contrib/enscript-token.rb +55 -0
  9. data/contrib/rublog_integrator.rb +68 -0
  10. data/data/Default/ProjectIndex.ruwiki +49 -0
  11. data/data/Ruwiki/Antispam.ruwiki +65 -0
  12. data/data/Ruwiki/BugTracking.ruwiki +33 -0
  13. data/data/Ruwiki/ChangeLog.ruwiki +102 -0
  14. data/data/Ruwiki/Configuring_Ruwiki.ruwiki +151 -0
  15. data/data/Ruwiki/Extending_Ruwiki.ruwiki +317 -0
  16. data/data/Ruwiki/LicenseAndAuthorInfo.ruwiki +30 -0
  17. data/data/Ruwiki/ProjectIndex.ruwiki +84 -0
  18. data/data/Ruwiki/Roadmap.ruwiki +225 -0
  19. data/data/Ruwiki/RuwikiTemplatingLibrary.ruwiki +156 -0
  20. data/data/Ruwiki/RuwikiUtilities.ruwiki +157 -0
  21. data/data/Ruwiki/SandBox.ruwiki +9 -0
  22. data/data/Ruwiki/To_Do.ruwiki +51 -0
  23. data/data/Ruwiki/TroubleShooting.ruwiki +33 -0
  24. data/data/Ruwiki/WikiFeatures.ruwiki +17 -0
  25. data/data/Ruwiki/WikiMarkup.ruwiki +261 -0
  26. data/data/Tutorial/AddingPages.ruwiki +16 -0
  27. data/data/Tutorial/AddingProjects.ruwiki +16 -0
  28. data/data/Tutorial/ProjectIndex.ruwiki +11 -0
  29. data/data/Tutorial/SandBox.ruwiki +9 -0
  30. data/data/agents.banned +60 -0
  31. data/data/agents.readonly +321 -0
  32. data/data/hostip.banned +30 -0
  33. data/data/hostip.readonly +28 -0
  34. data/lib/ruwiki.rb +622 -0
  35. data/lib/ruwiki/auth.rb +56 -0
  36. data/lib/ruwiki/auth/gforge.rb +73 -0
  37. data/lib/ruwiki/backend.rb +318 -0
  38. data/lib/ruwiki/backend/flatfiles.rb +217 -0
  39. data/lib/ruwiki/config.rb +244 -0
  40. data/lib/ruwiki/exportable.rb +192 -0
  41. data/lib/ruwiki/handler.rb +342 -0
  42. data/lib/ruwiki/lang/de.rb +339 -0
  43. data/lib/ruwiki/lang/en.rb +334 -0
  44. data/lib/ruwiki/lang/es.rb +339 -0
  45. data/lib/ruwiki/page.rb +262 -0
  46. data/lib/ruwiki/servlet.rb +38 -0
  47. data/lib/ruwiki/template.rb +553 -0
  48. data/lib/ruwiki/utils.rb +24 -0
  49. data/lib/ruwiki/utils/command.rb +102 -0
  50. data/lib/ruwiki/utils/converter.rb +297 -0
  51. data/lib/ruwiki/utils/manager.rb +639 -0
  52. data/lib/ruwiki/utils/servletrunner.rb +295 -0
  53. data/lib/ruwiki/wiki.rb +147 -0
  54. data/lib/ruwiki/wiki/tokens.rb +136 -0
  55. data/lib/ruwiki/wiki/tokens/00default.rb +211 -0
  56. data/lib/ruwiki/wiki/tokens/01wikilinks.rb +166 -0
  57. data/lib/ruwiki/wiki/tokens/02actions.rb +63 -0
  58. data/lib/ruwiki/wiki/tokens/abbreviations.rb +40 -0
  59. data/lib/ruwiki/wiki/tokens/calendar.rb +147 -0
  60. data/lib/ruwiki/wiki/tokens/headings.rb +43 -0
  61. data/lib/ruwiki/wiki/tokens/lists.rb +112 -0
  62. data/lib/ruwiki/wiki/tokens/rubylists.rb +48 -0
  63. data/ruwiki.conf +22 -0
  64. data/ruwiki.pkg +0 -0
  65. data/templates/default/body.tmpl +19 -0
  66. data/templates/default/content.tmpl +7 -0
  67. data/templates/default/controls.tmpl +23 -0
  68. data/templates/default/edit.tmpl +27 -0
  69. data/templates/default/error.tmpl +14 -0
  70. data/templates/default/footer.tmpl +23 -0
  71. data/templates/default/ruwiki.css +297 -0
  72. data/templates/default/save.tmpl +8 -0
  73. data/templates/sidebar/body.tmpl +19 -0
  74. data/templates/sidebar/content.tmpl +8 -0
  75. data/templates/sidebar/controls.tmpl +8 -0
  76. data/templates/sidebar/edit.tmpl +27 -0
  77. data/templates/sidebar/error.tmpl +13 -0
  78. data/templates/sidebar/footer.tmpl +22 -0
  79. data/templates/sidebar/ruwiki.css +347 -0
  80. data/templates/sidebar/save.tmpl +10 -0
  81. data/templates/simple/body.tmpl +13 -0
  82. data/templates/simple/content.tmpl +7 -0
  83. data/templates/simple/controls.tmpl +8 -0
  84. data/templates/simple/edit.tmpl +25 -0
  85. data/templates/simple/error.tmpl +10 -0
  86. data/templates/simple/footer.tmpl +10 -0
  87. data/templates/simple/ruwiki.css +192 -0
  88. data/templates/simple/save.tmpl +8 -0
  89. data/tests/harness.rb +52 -0
  90. data/tests/tc_backend_flatfile.rb +103 -0
  91. data/tests/tc_bugs.rb +74 -0
  92. data/tests/tc_exportable.rb +64 -0
  93. data/tests/tc_template.rb +145 -0
  94. data/tests/tc_tokens.rb +335 -0
  95. data/tests/testall.rb +20 -0
  96. metadata +182 -0
@@ -0,0 +1,8 @@
1
+ <!-- header -->!INCLUDE!<!-- /header -->
2
+ <!-- content --><div class="rw_content" id="rw_saved_page_announcement">
3
+ #label_saved_page# <a href="%cgi_url%/%page_project%/%page_raw_topic%">%page_project%::%page_topic_name%</a>
4
+ </div>
5
+ <div class="rw_content">
6
+ %content%
7
+ </div><!-- /content -->
8
+ <!-- footer -->!INCLUDE!<!-- /footer -->
@@ -0,0 +1,52 @@
1
+ #!/usr/bin/env ruby
2
+ #--
3
+ # Ruwiki
4
+ # Copyright � 2002 - 2004, Digikata and HaloStatue
5
+ # Alan Chen (alan@digikata.com)
6
+ # Austin Ziegler (ruwiki@halostatue.ca)
7
+ #
8
+ # Licensed under the same terms as Ruby.
9
+ #
10
+ # $Id: harness.rb,v 1.9 2004/11/22 04:53:41 austin Exp $
11
+ #++
12
+ ENV["REQUEST_METHOD"] = "HEAD"
13
+
14
+ require 'ruwiki'
15
+
16
+ # This is the CGI version of Ruwiki. Therefore, when we create the Ruwiki
17
+ # instance, we specify that the request and response handlers are to be
18
+ # generated from a new CGI object.
19
+ $wiki = Ruwiki.new(Ruwiki::Handler.from_cgi(CGI.new))
20
+
21
+ # Configuration defaults to certain values. This overrides the defaults.
22
+ # The webmaster.
23
+ $wiki.config.webmaster = "webmaster@domain.com"
24
+ $wiki.config.storage_type = 'flatfiles'
25
+
26
+ dp = nil
27
+ dp = "../data" if File.exists?("../data")
28
+ dp = "./data" if File.exists?("./data")
29
+ raise "Cannot find either ./data or ../data for tests. Aborting." if dp.nil?
30
+
31
+ $wiki.config.storage_options['flatfiles']['data-path'] = dp
32
+ $wiki.config.storage_options['flatfiles']['format'] = "exportable"
33
+ $wiki.config.storage_options['flatfiles']['extension'] = "ruwiki"
34
+
35
+ tp = nil
36
+ tp = "../templates" if File.exists?("../templates")
37
+ tp = "./templates" if File.exists?("./templates")
38
+ raise "Cannot find either ./templates or ../templates for tests. Aborting." if tp.nil?
39
+
40
+ $wiki.config.template_path = tp
41
+ $wiki.config.verify
42
+ $wiki.set_backend
43
+
44
+ # $wiki.config.debug = false
45
+ # $wiki.config.title = "Ruwiki"
46
+ # $wiki.config.default_page = "ProjectIndex"
47
+ # $wiki.config.default_project = "Default"
48
+ # $wiki.config.storage_type = :flatfiles
49
+ # $wiki.config.storage_options[:flatfiles][:data_path] = "./data/"
50
+ # $wiki.config.template_path = "./templates/"
51
+ # $wiki.config.template_set = "default"
52
+ # $wiki.config.css = "ruwiki.css"
@@ -0,0 +1,103 @@
1
+ #!/usr/bin/env ruby
2
+ #--
3
+ # Ruwiki
4
+ # Copyright � 2002 - 2004, Digikata and HaloStatue
5
+ # Alan Chen (alan@digikata.com)
6
+ # Austin Ziegler (ruwiki@halostatue.ca)
7
+ #
8
+ # Licensed under the same terms as Ruby.
9
+ #
10
+ # $Id: tc_backend_flatfile.rb,v 1.6 2004/09/27 04:48:28 austin Exp $
11
+ #++
12
+
13
+ $LOAD_PATH.unshift("#{File.dirname(__FILE__)}/../lib") if __FILE__ == $0
14
+
15
+ require 'harness'
16
+ require 'ruwiki/backend/flatfiles'
17
+ require 'ostruct'
18
+ require 'test/unit'
19
+ require 'fileutils'
20
+
21
+ class TestBackendFlatfiles < Test::Unit::TestCase
22
+ def setup
23
+ @ffopts = { 'data-path' => "./test/data", 'extension' => nil }
24
+
25
+ # generate a database
26
+ raise "Setup Error: #{@ffopts['data-path']} exists" if File.exists?(@ffopts['data-path'])
27
+
28
+ @flatbase = {
29
+ 'Proj1' => ['ProjectIndex:all projects must have this',
30
+ 'P1TopicOne:this is the content',
31
+ 'P1TopicTwo:more content'],
32
+ 'Proj2' => ['ProjectIndex:all projects must have this',
33
+ 'P2TopicOne:this is the content',
34
+ 'P2TopicTwo:more content',
35
+ 'P2TopicThree:even more more content']
36
+ }
37
+
38
+ @flatbase.each do |key, val|
39
+ prjdir = "#{@ffopts['data-path']}/#{key}"
40
+ FileUtils.mkdir_p(prjdir) rescue nil
41
+ val.each do |topcon|
42
+ topic, content = topcon.split(":")
43
+ File.open("#{prjdir}/#{topic}", "w") do |fh|
44
+ fh.puts "page!content:\x09#{content}"
45
+ end
46
+ end
47
+ end
48
+
49
+ @backend = nil
50
+ @pg = nil
51
+ end
52
+
53
+ def teardown
54
+ # remove testing flatabase
55
+ FileUtils.rm_rf(@ffopts['data-path'])
56
+ Dir.rmdir("./test") # ugly but it works
57
+ end
58
+
59
+ def test_list_projects
60
+ assert_nothing_raised { @backend = Ruwiki::Backend::Flatfiles.new(@ffopts) }
61
+
62
+ # should be ['Proj1', 'Proj2']
63
+ assert_equal(@flatbase.keys, @backend.list_projects)
64
+ end
65
+
66
+ def test_list_topics
67
+ assert_nothing_raised { @backend = Ruwiki::Backend::Flatfiles.new(@ffopts) }
68
+
69
+ @flatbase.keys.sort.each do |proj|
70
+ got_topics = @backend.list_topics(proj)
71
+ exp_topics = @flatbase[proj].map { |ent| ent.split(':')[0] }
72
+ assert_equal(exp_topics.sort, got_topics.sort)
73
+ end
74
+ end
75
+
76
+ # test simple one word lookups
77
+ # need to add more complex search strings
78
+ def test_search_project
79
+ assert_nothing_raised { @backend = Ruwiki::Backend::Flatfiles.new(@ffopts) }
80
+
81
+ assert_equal({'ProjectIndex' => 1,
82
+ 'P1TopicOne' => 1,
83
+ 'P1TopicTwo' => 0 }.to_a.sort,
84
+ @backend.search_project('Proj1', 'this').to_a.sort)
85
+ assert_equal({'ProjectIndex' => 0,
86
+ 'P1TopicOne' => 0,
87
+ 'P1TopicTwo' => 1 }.to_a.sort,
88
+ @backend.search_project('Proj1', 'more').to_a.sort)
89
+ assert_equal({'ProjectIndex' => 0,
90
+ 'P1TopicOne' => 1,
91
+ 'P1TopicTwo' => 1 }.to_a.sort,
92
+ @backend.search_project('Proj1', 'topic').to_a.sort)
93
+ assert_equal({'ProjectIndex' => 0,
94
+ 'P1TopicOne' => 1,
95
+ 'P1TopicTwo' => 1 }.to_a.sort,
96
+ @backend.search_project('Proj1', 'content').to_a.sort)
97
+ assert_equal({'ProjectIndex' => 0,
98
+ 'P2TopicOne' => 0,
99
+ 'P2TopicTwo' => 1,
100
+ 'P2TopicThree' => 2 }.to_a.sort,
101
+ @backend.search_project('Proj2', 'more').to_a.sort)
102
+ end
103
+ end
@@ -0,0 +1,74 @@
1
+ #!/usr/bin/env ruby
2
+ #--
3
+ # Ruwiki
4
+ # Copyright � 2002 - 2004, Digikata and HaloStatue
5
+ # Alan Chen (alan@digikata.com)
6
+ # Austin Ziegler (ruwiki@halostatue.ca)
7
+ #
8
+ # Licensed under the same terms as Ruby.
9
+ #
10
+ # $Id: tc_bugs.rb,v 1.8 2004/11/22 04:53:41 austin Exp $
11
+ #++
12
+
13
+ $LOAD_PATH.unshift("#{File.dirname(__FILE__)}/../lib") if __FILE__ == $0
14
+
15
+ require 'harness'
16
+ require 'ruwiki/backend/flatfiles'
17
+ require 'ostruct'
18
+ require 'test/unit'
19
+
20
+ # see if we can reproduce the LicenseandAuthor hang
21
+ # described in bug id 147 on rubyforge
22
+ class TC_LicenseAndAuthorHang < Test::Unit::TestCase
23
+ def setup
24
+ @ffopts = { }
25
+ dp = nil
26
+ dp = "../data" if File.exists?("../data")
27
+ dp = "./data" if File.exists?("./data")
28
+ raise "Cannot find either ./data or ../data for tests. Aborting." if dp.nil?
29
+
30
+ @ffopts['data-path'] = dp
31
+ @ffopts['format'] = 'exportable'
32
+
33
+ @backend = nil
34
+ @pg = nil
35
+ end
36
+
37
+ # load "to the metal"
38
+ def test_ffload
39
+ assert_nothing_raised do
40
+ @backend = ::Ruwiki::Backend::Flatfiles.new(@ffopts)
41
+ end
42
+ assert_not_nil(@backend)
43
+ assert_nothing_raised do
44
+ @pg = @backend.load('LicenseAndAuthorInfo.ruwiki', 'Ruwiki')
45
+ end
46
+ assert_not_nil(@pg)
47
+ end
48
+
49
+ # abstract backend retreive
50
+ def test_beload
51
+ @backend = nil
52
+ assert_nothing_raised do
53
+ mock_ruwiki = OpenStruct.new
54
+ mock_ruwiki.config = OpenStruct.new
55
+ mock_ruwiki.config.message = {}
56
+ mock_ruwiki.config.storage_options = { 'flatfiles' => @ffopts }
57
+
58
+ @backend = ::Ruwiki::BackendDelegator.new(mock_ruwiki, 'flatfiles')
59
+ end
60
+ assert_not_nil(@backend)
61
+ assert_nothing_raised do
62
+ @pg = @backend.retrieve('LicenseAndAuthorInfo', 'Ruwiki')
63
+ end
64
+ assert_not_nil(@pg)
65
+ end
66
+ end
67
+
68
+ # if __FILE__ == $0
69
+ # ObjectSpace.each_object { |o| tests << o if o.kind_of?(Class) }
70
+ # tests.delete_if { |o| !o.ancestors.include?(Test::Unit::TestCase) }
71
+ # tests.delete_if { |o| o == Test::Unit::TestCase }
72
+
73
+ # tests.each { |test| Test::Unit::UI::Console::TestRunner.run(test) }
74
+ # end
@@ -0,0 +1,64 @@
1
+ #!/usr/bin/env ruby
2
+ #--
3
+ # Ruwiki
4
+ # Copyright � 2002 - 2004, Digikata and HaloStatue
5
+ # Alan Chen (alan@digikata.com)
6
+ # Austin Ziegler (ruwiki@halostatue.ca)
7
+ #
8
+ # Licensed under the same terms as Ruby.
9
+ #
10
+ # $Id: tc_exportable.rb,v 1.4 2004/09/27 04:48:28 austin Exp $
11
+ #++
12
+
13
+ $LOAD_PATH.unshift("#{File.dirname(__FILE__)}/../lib") if __FILE__ == $0
14
+ class Ruwiki; end if __FILE__ == $0
15
+
16
+ require 'ruwiki/exportable'
17
+ require 'test/unit'
18
+
19
+ class TCExportable < Test::Unit::TestCase
20
+ class Exportable
21
+ include Ruwiki::Exportable
22
+
23
+ attr_accessor :a, :b, :long_name, :altname, :xform, :group2
24
+ exportable :a
25
+ exportable :long_name
26
+ exportable :altname, :name => 'alt-name'
27
+ exportable :group2, :group => 'group2'
28
+ end
29
+
30
+ def test_exportable
31
+ __exportables = {
32
+ 'default' => {
33
+ 'a' => '@a'.intern,
34
+ 'long-name' => '@long_name'.intern,
35
+ 'alt-name' => '@altname'.intern,
36
+ },
37
+ 'group2' => {
38
+ 'group2' => '@group2'.intern
39
+ }
40
+ }
41
+ __values = {
42
+ 'default' => {
43
+ 'a' => 'a',
44
+ 'long-name' => 'c',
45
+ 'alt-name' => 'd',
46
+ },
47
+ 'group2' => { 'group2' => 'e' }
48
+ }
49
+ xx = nil
50
+ ss = nil
51
+ assert_nothing_raised do
52
+ xx = Exportable.new
53
+ xx.a = "a"
54
+ xx.b = "b"
55
+ xx.long_name = "c"
56
+ xx.altname = "d"
57
+ xx.xform = 22/7
58
+ xx.group2 = "e"
59
+ ss = xx.export
60
+ end
61
+ assert_equal(__exportables, xx.class.__exportables)
62
+ assert_equal(__values, ss)
63
+ end
64
+ end
@@ -0,0 +1,145 @@
1
+ #!/usr/bin/env ruby
2
+ #--
3
+ # Ruwiki
4
+ # Copyright � 2002 - 2003, Digikata and HaloStatue
5
+ # Alan Chen (alan@digikata.com)
6
+ # Austin Ziegler (ruwiki@halostatue.ca)
7
+ #
8
+ # Licensed under the same terms as Ruby.
9
+ #
10
+ # $Id: tc_template.rb,v 1.5 2004/09/27 04:48:28 austin Exp $
11
+ #++
12
+
13
+ $LOAD_PATH.unshift("#{File.dirname(__FILE__)}/../lib") if __FILE__ == $0
14
+
15
+ require 'test/unit'
16
+ require 'harness'
17
+
18
+ class TestTemplates < Test::Unit::TestCase
19
+ def test_include
20
+ a = "a!INCLUDE!c"
21
+ b = "b"
22
+ t = Ruwiki::TemplatePage.new(a, b)
23
+ assert_equal(["abc"], t.lines.lines)
24
+ end
25
+
26
+ def test_variables
27
+ a = "a%b%c"
28
+ v = { "b" => "b" }
29
+ t = Ruwiki::TemplatePage.new(a)
30
+ assert_equal("abc", t.write_plain_on("", v))
31
+ end
32
+
33
+ def test_optional_variables
34
+ a = "a%b%%?c%d"
35
+ v = { "b" => "b" }
36
+ t = Ruwiki::TemplatePage.new(a)
37
+ assert_equal("abd", t.write_plain_on("", v))
38
+
39
+ v["c"] = "c"
40
+ assert_equal("abcd", t.write_plain_on("", v))
41
+ end
42
+
43
+ def test_labels
44
+ a = "a#b#c"
45
+ v = {}
46
+ m = { :b => "b" }
47
+ t = Ruwiki::TemplatePage.new(a)
48
+ assert_equal("abc", t.write_plain_on("", v, m))
49
+ end
50
+
51
+ def test_optional_labels
52
+ a = "a#b##?c#d"
53
+ v = {}
54
+ m = { :b => "b" }
55
+ t = Ruwiki::TemplatePage.new(a)
56
+ assert_equal("abd", t.write_plain_on("", v, m))
57
+
58
+ m[:c] = "c"
59
+ assert_equal("abcd", t.write_plain_on("", v, m))
60
+ end
61
+
62
+ def test_hrefs
63
+ a = "HREF:a:b:"
64
+ t = Ruwiki::TemplatePage.new(a)
65
+ v = { "b" => "b" }
66
+
67
+ assert_equal("b", t.write_plain_on("", v))
68
+
69
+ s = ""
70
+ v["a"] = "link"
71
+ assert_equal(%Q(<a href="link">b</a>), t.write_plain_on("", v))
72
+ end
73
+
74
+ def test_repeat_subst
75
+ v1 = { "a" => 3 }
76
+ v2 = { "a" => 2...4 }
77
+ v3 = { "a" => -4...-2 }
78
+ v4 = { "a" => [3, 1, 4, 1, 5, 9] }
79
+ v5 = { "a" => [{ "a" => 3 }, { "a" => 1 }, { "a" => 4 }, { "a" => 1 }, { "a" => 5 }, { "a" => 9 }] }
80
+
81
+ a = "[:a|xy:]"
82
+ t = Ruwiki::TemplatePage.new(a)
83
+ assert_equal("xyxyxy", t.write_plain_on("", v1))
84
+ assert_equal("xyxy", t.write_plain_on("", v2))
85
+ assert_equal("xyxy", t.write_plain_on("", v3))
86
+ assert_equal("xyxyxyxyxyxy", t.write_plain_on("", v4))
87
+ assert_equal("xyxyxyxyxyxy", t.write_plain_on("", v5))
88
+
89
+ a = "[:a|%a%:]"
90
+ t = Ruwiki::TemplatePage.new(a)
91
+ assert_equal("123", t.write_plain_on("", v1))
92
+ assert_equal("23", t.write_plain_on("", v2))
93
+ assert_equal("-4-3", t.write_plain_on("", v3))
94
+ assert_equal("314159", t.write_plain_on("", v4))
95
+ assert_equal("314159", t.write_plain_on("", v5))
96
+ end
97
+
98
+ def test_optional_subst
99
+ v1 = { "a" => "a" }
100
+ v2 = { "a" => nil }
101
+ a1 = "[?a|xy?]"
102
+ a2 = "[!a|xy?]"
103
+ t1 = Ruwiki::TemplatePage.new(a1)
104
+ t2 = Ruwiki::TemplatePage.new(a2)
105
+
106
+ assert_equal("xy", t1.write_plain_on("", v1))
107
+ assert_equal("", t1.write_plain_on("", v2))
108
+ assert_equal("", t2.write_plain_on("", v1))
109
+ assert_equal("xy", t2.write_plain_on("", v2))
110
+ end
111
+
112
+ def test_repeat_block
113
+ a1 = "START:a\nxy\nEND:a"
114
+ a2 = "START:a\nx%b%y\nEND:a"
115
+ a3 = "START:\nEND:"
116
+ t1 = Ruwiki::TemplatePage.new(a1)
117
+ t2 = Ruwiki::TemplatePage.new(a2)
118
+ t3 = Ruwiki::TemplatePage.new(a3)
119
+ v = { "a" => [{ "b" => 3 }, { "b" => 1 }, { "b" => 4 }, { "b" => 1 }, { "b" => 5 }, { "b" => 9 }] }
120
+
121
+ assert_equal("xy\nxy\nxy\nxy\nxy\nxy\n", t1.write_plain_on("", v))
122
+ assert_equal("x3y\nx1y\nx4y\nx1y\nx5y\nx9y\n", t2.write_plain_on("", v))
123
+ assert_raises(RuntimeError) { t3.write_plain_on("", v) }
124
+ end
125
+
126
+ def test_optional_block
127
+ a1 = "IF:a\nxy\nENDIF:a"
128
+ a2 = "IF:\nxy\nEND:"
129
+ a3 = "IFNOT:a\nxy\nENDIF:a"
130
+ a4 = "IFNOT:\nxy\nEND:"
131
+ t1 = Ruwiki::TemplatePage.new(a1)
132
+ t2 = Ruwiki::TemplatePage.new(a2)
133
+ t3 = Ruwiki::TemplatePage.new(a3)
134
+ t4 = Ruwiki::TemplatePage.new(a4)
135
+ v1 = { "a" => true }
136
+ v2 = { "a" => nil }
137
+
138
+ assert_equal("xy", t1.write_plain_on("", v1))
139
+ assert_equal("", t1.write_plain_on("", v2))
140
+ assert_raises(RuntimeError) { t2.write_plain_on("", v1) }
141
+ assert_equal("", t3.write_plain_on("", v1))
142
+ assert_equal("xy", t3.write_plain_on("", v2))
143
+ assert_raises(RuntimeError) { t4.write_plain_on("", v1) }
144
+ end
145
+ end