my_wiki_generator 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (103) hide show
  1. data/my_wiki/grep.txt +238 -0
  2. data/my_wiki/my_wiki_generator.rb +248 -0
  3. data/my_wiki/templates/POST_GENERATION_REMINDER +1 -0
  4. data/my_wiki/templates/app/controllers/application.rb +75 -0
  5. data/my_wiki/templates/app/controllers/content_history_controller.rb +49 -0
  6. data/my_wiki/templates/app/controllers/login_controller.rb +93 -0
  7. data/my_wiki/templates/app/controllers/my_wiki_admin_controller.rb +26 -0
  8. data/my_wiki/templates/app/controllers/my_wiki_controller.rb +250 -0
  9. data/my_wiki/templates/app/controllers/page_admin_controller.rb +51 -0
  10. data/my_wiki/templates/app/controllers/user_admin_controller.rb +34 -0
  11. data/my_wiki/templates/app/helpers/application_helper.rb +3 -0
  12. data/my_wiki/templates/app/helpers/content_history_helper.rb +2 -0
  13. data/my_wiki/templates/app/helpers/login_helper.rb +2 -0
  14. data/my_wiki/templates/app/helpers/my_wiki_admin_helper.rb +2 -0
  15. data/my_wiki/templates/app/helpers/my_wiki_helper.rb +94 -0
  16. data/my_wiki/templates/app/helpers/page_admin_helper.rb +2 -0
  17. data/my_wiki/templates/app/helpers/user_admin_helper.rb +2 -0
  18. data/my_wiki/templates/app/models/attachment.rb +55 -0
  19. data/my_wiki/templates/app/models/content.rb +32 -0
  20. data/my_wiki/templates/app/models/content_history.rb +49 -0
  21. data/my_wiki/templates/app/models/content_sweeper.rb +7 -0
  22. data/my_wiki/templates/app/models/my_wiki_mailer.rb +29 -0
  23. data/my_wiki/templates/app/models/role.rb +18 -0
  24. data/my_wiki/templates/app/models/setting.rb +7 -0
  25. data/my_wiki/templates/app/models/user.rb +60 -0
  26. data/my_wiki/templates/app/views/content_history/_form.rhtml +19 -0
  27. data/my_wiki/templates/app/views/content_history/edit.rhtml +9 -0
  28. data/my_wiki/templates/app/views/content_history/list.rhtml +27 -0
  29. data/my_wiki/templates/app/views/content_history/new.rhtml +8 -0
  30. data/my_wiki/templates/app/views/content_history/show.rhtml +21 -0
  31. data/my_wiki/templates/app/views/layouts/my_wiki.rhtml +105 -0
  32. data/my_wiki/templates/app/views/login/edit.rhtml +25 -0
  33. data/my_wiki/templates/app/views/login/login.rhtml +23 -0
  34. data/my_wiki/templates/app/views/login/logout.rhtml +10 -0
  35. data/my_wiki/templates/app/views/login/signup.rhtml +23 -0
  36. data/my_wiki/templates/app/views/login/welcome.rhtml +13 -0
  37. data/my_wiki/templates/app/views/my_wiki/_form.rhtml +11 -0
  38. data/my_wiki/templates/app/views/my_wiki/css.rhtml +224 -0
  39. data/my_wiki/templates/app/views/my_wiki/diff.rhtml +4 -0
  40. data/my_wiki/templates/app/views/my_wiki/edit.rhtml +34 -0
  41. data/my_wiki/templates/app/views/my_wiki/fileinfo.rhtml +22 -0
  42. data/my_wiki/templates/app/views/my_wiki/list.rhtml +1 -0
  43. data/my_wiki/templates/app/views/my_wiki/mails.rhtml +1 -0
  44. data/my_wiki/templates/app/views/my_wiki/new.rhtml +6 -0
  45. data/my_wiki/templates/app/views/my_wiki/recent.rhtml +3 -0
  46. data/my_wiki/templates/app/views/my_wiki/search.rhtml +5 -0
  47. data/my_wiki/templates/app/views/my_wiki/search_result.rhtml +10 -0
  48. data/my_wiki/templates/app/views/my_wiki/show.rhtml +31 -0
  49. data/my_wiki/templates/app/views/my_wiki_admin/index.rhtml +5 -0
  50. data/my_wiki/templates/app/views/my_wiki_admin/setting.rhtml +64 -0
  51. data/my_wiki/templates/app/views/my_wiki_mailer/inform.rhtml +3 -0
  52. data/my_wiki/templates/app/views/page_admin/_form.rhtml +22 -0
  53. data/my_wiki/templates/app/views/page_admin/edit.rhtml +9 -0
  54. data/my_wiki/templates/app/views/page_admin/list.rhtml +55 -0
  55. data/my_wiki/templates/app/views/page_admin/new.rhtml +8 -0
  56. data/my_wiki/templates/app/views/page_admin/show.rhtml +8 -0
  57. data/my_wiki/templates/app/views/user_admin/_form.rhtml +10 -0
  58. data/my_wiki/templates/app/views/user_admin/change_password.rhtml +9 -0
  59. data/my_wiki/templates/app/views/user_admin/list.rhtml +25 -0
  60. data/my_wiki/templates/app/views/user_admin/signup.rhtml +20 -0
  61. data/my_wiki/templates/components/admin/menu/menu.rhtml +5 -0
  62. data/my_wiki/templates/components/admin/menu_controller.rb +3 -0
  63. data/my_wiki/templates/components/list/list/list.rhtml +11 -0
  64. data/my_wiki/templates/components/list/list_controller.rb +11 -0
  65. data/my_wiki/templates/components/sidebar/sidebar/show.rhtml +7 -0
  66. data/my_wiki/templates/components/sidebar/sidebar_controller.rb +9 -0
  67. data/my_wiki/templates/config/routes.rb +35 -0
  68. data/my_wiki/templates/db/migrate/001_my_wiki_migration.rb +75 -0
  69. data/my_wiki/templates/lib/diff/lcs.rb +1105 -0
  70. data/my_wiki/templates/lib/diff/lcs/array.rb +21 -0
  71. data/my_wiki/templates/lib/diff/lcs/block.rb +51 -0
  72. data/my_wiki/templates/lib/diff/lcs/callbacks.rb +322 -0
  73. data/my_wiki/templates/lib/diff/lcs/change.rb +169 -0
  74. data/my_wiki/templates/lib/diff/lcs/hunk.rb +257 -0
  75. data/my_wiki/templates/lib/diff/lcs/ldiff.rb +226 -0
  76. data/my_wiki/templates/lib/diff/lcs/string.rb +19 -0
  77. data/my_wiki/templates/lib/login_system.rb +87 -0
  78. data/my_wiki/templates/lib/markup/simple_markup.rb +489 -0
  79. data/my_wiki/templates/lib/markup/simple_markup/fragments.rb +329 -0
  80. data/my_wiki/templates/lib/markup/simple_markup/inline.rb +338 -0
  81. data/my_wiki/templates/lib/markup/simple_markup/lines.rb +151 -0
  82. data/my_wiki/templates/lib/markup/simple_markup/preprocess.rb +68 -0
  83. data/my_wiki/templates/lib/markup/simple_markup/to_flow.rb +188 -0
  84. data/my_wiki/templates/lib/markup/simple_markup/to_html.rb +302 -0
  85. data/my_wiki/templates/lib/markup/simple_markup/to_latex.rb +333 -0
  86. data/my_wiki/templates/lib/my_wiki_plugin.rb +60 -0
  87. data/my_wiki/templates/lib/my_wiki_plugins/christel.rb +5 -0
  88. data/my_wiki/templates/lib/my_wiki_plugins/join.rb +3 -0
  89. data/my_wiki/templates/lib/my_wiki_plugins/link_to_attach.rb +17 -0
  90. data/my_wiki/templates/lib/my_wiki_plugins/recent.rb +8 -0
  91. data/my_wiki/templates/public/javascripts/my_wiki.js +8 -0
  92. data/my_wiki/templates/public/stylesheets/my_wiki/back.jpg +0 -0
  93. data/my_wiki/templates/public/stylesheets/my_wiki/back1.jpg +0 -0
  94. data/my_wiki/templates/public/stylesheets/my_wiki/back2.jpg +0 -0
  95. data/my_wiki/templates/public/stylesheets/my_wiki/foot.jpg +0 -0
  96. data/my_wiki/templates/public/stylesheets/my_wiki/h1.gif +0 -0
  97. data/my_wiki/templates/public/stylesheets/my_wiki/h1.jpg +0 -0
  98. data/my_wiki/templates/public/stylesheets/my_wiki/menu.jpg +0 -0
  99. data/my_wiki/templates/public/stylesheets/my_wiki/menu2.jpg +0 -0
  100. data/my_wiki/templates/public/stylesheets/my_wiki/menu_c.jpg +0 -0
  101. data/my_wiki/templates/public/stylesheets/my_wiki/my_wiki.css +336 -0
  102. data/my_wiki/templates/public/stylesheets/my_wiki/title.jpg +0 -0
  103. metadata +181 -0
@@ -0,0 +1,151 @@
1
+ ##########################################################################
2
+ #
3
+ # We store the lines we're working on as objects of class Line.
4
+ # These contain the text of the line, along with a flag indicating the
5
+ # line type, and an indentation level
6
+
7
+ module SM
8
+
9
+ class Line
10
+ INFINITY = 9999
11
+
12
+ BLANK = :BLANK
13
+ HEADING = :HEADING
14
+ LIST = :LIST
15
+ RULE = :RULE
16
+ PARAGRAPH = :PARAGRAPH
17
+ VERBATIM = :VERBATIM
18
+
19
+ # line type
20
+ attr_accessor :type
21
+
22
+ # The indentation nesting level
23
+ attr_accessor :level
24
+
25
+ # The contents
26
+ attr_accessor :text
27
+
28
+ # A prefix or parameter. For LIST lines, this is
29
+ # the text that introduced the list item (the label)
30
+ attr_accessor :param
31
+
32
+ # A flag. For list lines, this is the type of the list
33
+ attr_accessor :flag
34
+
35
+ # the number of leading spaces
36
+ attr_accessor :leading_spaces
37
+
38
+ # true if this line has been deleted from the list of lines
39
+ attr_accessor :deleted
40
+
41
+
42
+ def initialize(text)
43
+ @text = text.dup
44
+ @deleted = false
45
+
46
+ # expand tabs
47
+ 1 while @text.gsub!(/\t+/) { ' ' * (8*$&.length - $`.length % 8)} && $~ #`
48
+
49
+ # Strip trailing whitespace
50
+ @text.sub!(/\s+$/, '')
51
+
52
+ # and look for leading whitespace
53
+ if @text.length > 0
54
+ @text =~ /^(\s*)/
55
+ @leading_spaces = $1.length
56
+ else
57
+ @leading_spaces = INFINITY
58
+ end
59
+ end
60
+
61
+ # Return true if this line is blank
62
+ def isBlank?
63
+ @text.length.zero?
64
+ end
65
+
66
+ # stamp a line with a type, a level, a prefix, and a flag
67
+ def stamp(type, level, param="", flag=nil)
68
+ @type, @level, @param, @flag = type, level, param, flag
69
+ end
70
+
71
+ ##
72
+ # Strip off the leading margin
73
+ #
74
+
75
+ def strip_leading(size)
76
+ if @text.size > size
77
+ @text[0,size] = ""
78
+ else
79
+ @text = ""
80
+ end
81
+ end
82
+
83
+ def to_s
84
+ "#@type#@level: #@text"
85
+ end
86
+ end
87
+
88
+ ###############################################################################
89
+ #
90
+ # A container for all the lines
91
+ #
92
+
93
+ class Lines
94
+ include Enumerable
95
+
96
+ attr_reader :lines # for debugging
97
+
98
+ def initialize(lines)
99
+ @lines = lines
100
+ rewind
101
+ end
102
+
103
+ def empty?
104
+ @lines.size.zero?
105
+ end
106
+
107
+ def each
108
+ @lines.each do |line|
109
+ yield line unless line.deleted
110
+ end
111
+ end
112
+
113
+ # def [](index)
114
+ # @lines[index]
115
+ # end
116
+
117
+ def rewind
118
+ @nextline = 0
119
+ end
120
+
121
+ def next
122
+ begin
123
+ res = @lines[@nextline]
124
+ @nextline += 1 if @nextline < @lines.size
125
+ end while res and res.deleted and @nextline < @lines.size
126
+ res
127
+ end
128
+
129
+ def unget
130
+ @nextline -= 1
131
+ end
132
+
133
+ def delete(a_line)
134
+ a_line.deleted = true
135
+ end
136
+
137
+ def normalize
138
+ margin = @lines.collect{|l| l.leading_spaces}.min
139
+ margin = 0 if margin == Line::INFINITY
140
+ @lines.each {|line| line.strip_leading(margin) } if margin > 0
141
+ end
142
+
143
+ def as_text
144
+ @lines.map {|l| l.text}.join("\n")
145
+ end
146
+
147
+ def line_types
148
+ @lines.map {|l| l.type }
149
+ end
150
+ end
151
+ end
@@ -0,0 +1,68 @@
1
+ module SM
2
+
3
+ ##
4
+ # Handle common directives that can occur in a block of text:
5
+ #
6
+ # : include : filename
7
+ #
8
+
9
+ class PreProcess
10
+
11
+ def initialize(input_file_name, include_path)
12
+ @input_file_name = input_file_name
13
+ @include_path = include_path
14
+ end
15
+
16
+ # Look for common options in a chunk of text. Options that
17
+ # we don't handle are passed back to our caller
18
+ # as |directive, param|
19
+
20
+ def handle(text)
21
+ text.gsub!(/^([ \t#]*):(\w+):\s*(.+)?\n/) do
22
+ prefix = $1
23
+ directive = $2.downcase
24
+ param = $3
25
+
26
+ case directive
27
+ when "include"
28
+ filename = param.split[0]
29
+ include_file(filename, prefix)
30
+
31
+ else
32
+ yield(directive, param)
33
+ end
34
+ end
35
+ end
36
+
37
+ #######
38
+ private
39
+ #######
40
+
41
+ # Include a file, indenting it correctly
42
+
43
+ def include_file(name, indent)
44
+ if (full_name = find_include_file(name))
45
+ content = File.open(full_name) {|f| f.read}
46
+ res = content.gsub(/^#?/, indent)
47
+ else
48
+ $stderr.puts "Couldn't find file to include: '#{name}'"
49
+ ''
50
+ end
51
+ end
52
+
53
+ # Look for the given file in the directory containing the current
54
+ # file, and then in each of the directories specified in the
55
+ # RDOC_INCLUDE path
56
+
57
+ def find_include_file(name)
58
+ to_search = [ File.dirname(@input_file_name) ].concat @include_path
59
+ to_search.each do |dir|
60
+ full_name = File.join(dir, name)
61
+ stat = File.stat(full_name) rescue next
62
+ return full_name if stat.readable?
63
+ end
64
+ nil
65
+ end
66
+
67
+ end
68
+ end
@@ -0,0 +1,188 @@
1
+ require 'markup/simple_markup/fragments'
2
+ require 'markup/simple_markup/inline'
3
+ require 'cgi'
4
+
5
+ module SM
6
+
7
+ module Flow
8
+ P = Struct.new(:body)
9
+ VERB = Struct.new(:body)
10
+ RULE = Struct.new(:width)
11
+ class LIST
12
+ attr_reader :type, :contents
13
+ def initialize(type)
14
+ @type = type
15
+ @contents = []
16
+ end
17
+ def <<(stuff)
18
+ @contents << stuff
19
+ end
20
+ end
21
+ LI = Struct.new(:label, :body)
22
+ H = Struct.new(:level, :text)
23
+ end
24
+
25
+ class ToFlow
26
+ LIST_TYPE_TO_HTML = {
27
+ SM::ListBase::BULLET => [ "<ul>", "</ul>" ],
28
+ SM::ListBase::NUMBER => [ "<ol>", "</ol>" ],
29
+ SM::ListBase::UPPERALPHA => [ "<ol>", "</ol>" ],
30
+ SM::ListBase::LOWERALPHA => [ "<ol>", "</ol>" ],
31
+ SM::ListBase::LABELED => [ "<dl>", "</dl>" ],
32
+ SM::ListBase::NOTE => [ "<table>", "</table>" ],
33
+ }
34
+
35
+ InlineTag = Struct.new(:bit, :on, :off)
36
+
37
+ def initialize
38
+ init_tags
39
+ end
40
+
41
+ ##
42
+ # Set up the standard mapping of attributes to HTML tags
43
+ #
44
+ def init_tags
45
+ @attr_tags = [
46
+ InlineTag.new(SM::Attribute.bitmap_for(:BOLD), "<b>", "</b>"),
47
+ InlineTag.new(SM::Attribute.bitmap_for(:TT), "<tt>", "</tt>"),
48
+ InlineTag.new(SM::Attribute.bitmap_for(:EM), "<em>", "</em>"),
49
+ ]
50
+ end
51
+
52
+ ##
53
+ # Add a new set of HTML tags for an attribute. We allow
54
+ # separate start and end tags for flexibility
55
+ #
56
+ def add_tag(name, start, stop)
57
+ @attr_tags << InlineTag.new(SM::Attribute.bitmap_for(name), start, stop)
58
+ end
59
+
60
+ ##
61
+ # Given an HTML tag, decorate it with class information
62
+ # and the like if required. This is a no-op in the base
63
+ # class, but is overridden in HTML output classes that
64
+ # implement style sheets
65
+
66
+ def annotate(tag)
67
+ tag
68
+ end
69
+
70
+ ##
71
+ # Here's the client side of the visitor pattern
72
+
73
+ def start_accepting
74
+ @res = []
75
+ @list_stack = []
76
+ end
77
+
78
+ def end_accepting
79
+ @res
80
+ end
81
+
82
+ def accept_paragraph(am, fragment)
83
+ @res << Flow::P.new((convert_flow(am.flow(fragment.txt))))
84
+ end
85
+
86
+ def accept_verbatim(am, fragment)
87
+ @res << Flow::VERB.new((convert_flow(am.flow(fragment.txt))))
88
+ end
89
+
90
+ def accept_rule(am, fragment)
91
+ size = fragment.param
92
+ size = 10 if size > 10
93
+ @res << Flow::RULE.new(size)
94
+ end
95
+
96
+ def accept_list_start(am, fragment)
97
+ @list_stack.push(@res)
98
+ list = Flow::LIST.new(fragment.type)
99
+ @res << list
100
+ @res = list
101
+ end
102
+
103
+ def accept_list_end(am, fragment)
104
+ @res = @list_stack.pop
105
+ end
106
+
107
+ def accept_list_item(am, fragment)
108
+ @res << Flow::LI.new(fragment.param, convert_flow(am.flow(fragment.txt)))
109
+ end
110
+
111
+ def accept_blank_line(am, fragment)
112
+ # @res << annotate("<p />") << "\n"
113
+ end
114
+
115
+ def accept_heading(am, fragment)
116
+ @res << Flow::H.new(fragment.head_level, convert_flow(am.flow(fragment.txt)))
117
+ end
118
+
119
+
120
+ #######################################################################
121
+
122
+ private
123
+
124
+ #######################################################################
125
+
126
+ def on_tags(res, item)
127
+ attr_mask = item.turn_on
128
+ return if attr_mask.zero?
129
+
130
+ @attr_tags.each do |tag|
131
+ if attr_mask & tag.bit != 0
132
+ res << annotate(tag.on)
133
+ end
134
+ end
135
+ end
136
+
137
+ def off_tags(res, item)
138
+ attr_mask = item.turn_off
139
+ return if attr_mask.zero?
140
+
141
+ @attr_tags.reverse_each do |tag|
142
+ if attr_mask & tag.bit != 0
143
+ res << annotate(tag.off)
144
+ end
145
+ end
146
+ end
147
+
148
+ def convert_flow(flow)
149
+ res = ""
150
+ flow.each do |item|
151
+ case item
152
+ when String
153
+ res << convert_string(item)
154
+ when AttrChanger
155
+ off_tags(res, item)
156
+ on_tags(res, item)
157
+ when Special
158
+ res << convert_special(item)
159
+ else
160
+ raise "Unknown flow element: #{item.inspect}"
161
+ end
162
+ end
163
+ res
164
+ end
165
+
166
+ # some of these patterns are taken from SmartyPants...
167
+
168
+ def convert_string(item)
169
+ CGI.escapeHTML(item)
170
+ end
171
+
172
+ def convert_special(special)
173
+ handled = false
174
+ Attribute.each_name_of(special.type) do |name|
175
+ method_name = "handle_special_#{name}"
176
+ if self.respond_to? method_name
177
+ special.text = send(method_name, special)
178
+ handled = true
179
+ end
180
+ end
181
+ raise "Unhandled special: #{special}" unless handled
182
+ special.text
183
+ end
184
+
185
+
186
+ end
187
+
188
+ end
@@ -0,0 +1,302 @@
1
+ require 'markup/simple_markup/fragments'
2
+ require 'markup/simple_markup/inline'
3
+
4
+ require 'cgi'
5
+
6
+ module SM
7
+
8
+ class ToHtml
9
+
10
+ LIST_TYPE_TO_HTML = {
11
+ ListBase::BULLET => [ "<ul>", "</ul>" ],
12
+ ListBase::NUMBER => [ "<ol>", "</ol>" ],
13
+ ListBase::UPPERALPHA => [ "<ol>", "</ol>" ],
14
+ ListBase::LOWERALPHA => [ "<ol>", "</ol>" ],
15
+ ListBase::LABELED => [ "<dl>", "</dl>" ],
16
+ ListBase::NOTE => [ "<table>", "</table>" ],
17
+ ListBase::TABLE => [ '<table class="table" cellspacing="1" border="0">', "</table>" ], # added by ando
18
+ }
19
+
20
+ InlineTag = Struct.new(:bit, :on, :off)
21
+
22
+ def initialize
23
+ init_tags
24
+ end
25
+
26
+ ##
27
+ # Set up the standard mapping of attributes to HTML tags
28
+ #
29
+ def init_tags
30
+ @attr_tags = [
31
+ InlineTag.new(SM::Attribute.bitmap_for(:BOLD), "<b>", "</b>"),
32
+ InlineTag.new(SM::Attribute.bitmap_for(:TT), "<tt>", "</tt>"),
33
+ InlineTag.new(SM::Attribute.bitmap_for(:EM), "<em>", "</em>"),
34
+ ]
35
+ end
36
+
37
+ ##
38
+ # Add a new set of HTML tags for an attribute. We allow
39
+ # separate start and end tags for flexibility
40
+ #
41
+ def add_tag(name, start, stop)
42
+ @attr_tags << InlineTag.new(SM::Attribute.bitmap_for(name), start, stop)
43
+ end
44
+
45
+ ##
46
+ # Given an HTML tag, decorate it with class information
47
+ # and the like if required. This is a no-op in the base
48
+ # class, but is overridden in HTML output classes that
49
+ # implement style sheets
50
+
51
+ def annotate(tag)
52
+ tag
53
+ end
54
+
55
+ ##
56
+ # Here's the client side of the visitor pattern
57
+
58
+ def start_accepting
59
+ @res = ""
60
+ @in_list_entry = []
61
+ end
62
+
63
+ def end_accepting
64
+ @res
65
+ end
66
+
67
+ def accept_paragraph(am, fragment)
68
+ @res << annotate("<p>") + "\n"
69
+ @res << wrap(convert_flow(am.flow(fragment.txt)))
70
+ @res << annotate("</p>") + "\n"
71
+ end
72
+
73
+ def accept_verbatim(am, fragment)
74
+ @res << annotate("<pre>") + "\n"
75
+ @res << CGI.escapeHTML(fragment.txt)
76
+ @res << annotate("</pre>") << "\n"
77
+ end
78
+
79
+ def accept_rule(am, fragment)
80
+ size = fragment.param
81
+ size = 10 if size > 10
82
+ @res << "<hr size=\"#{size}\"></hr>"
83
+ end
84
+
85
+ def accept_list_start(am, fragment)
86
+ @res << html_list_name(fragment.type, true) <<"\n"
87
+ @in_list_entry.push false
88
+ end
89
+
90
+ def accept_list_end(am, fragment)
91
+ if tag = @in_list_entry.pop
92
+ @res << annotate(tag) << "\n"
93
+ end
94
+ @res << html_list_name(fragment.type, false) <<"\n"
95
+ end
96
+
97
+ def accept_list_item(am, fragment)
98
+ if tag = @in_list_entry.last
99
+ @res << annotate(tag) << "\n"
100
+ end
101
+ @res << list_item_start(am, fragment)
102
+ @res << wrap(convert_flow(am.flow(fragment.txt))) << "\n"
103
+ @in_list_entry[-1] = list_end_for(fragment.type)
104
+ end
105
+
106
+ def accept_blank_line(am, fragment)
107
+ # @res << annotate("<p />") << "\n"
108
+ end
109
+
110
+ def accept_heading(am, fragment)
111
+ @res << convert_heading(fragment.head_level, am.flow(fragment.txt))
112
+ end
113
+
114
+ # This is a higher speed (if messier) version of wrap
115
+
116
+ def wrap(txt, line_len = 76)
117
+ res = ""
118
+ sp = 0
119
+ ep = txt.length
120
+ while sp < ep
121
+ # scan back for a space
122
+ p = sp + line_len - 1
123
+ if p >= ep
124
+ p = ep
125
+ else
126
+ while p > sp and txt[p] != ?\s
127
+ p -= 1
128
+ end
129
+ if p <= sp
130
+ p = sp + line_len
131
+ while p < ep and txt[p] != ?\s
132
+ p += 1
133
+ end
134
+ end
135
+ end
136
+ res << txt[sp...p] << "\n"
137
+ sp = p
138
+ sp += 1 while sp < ep and txt[sp] == ?\s
139
+ end
140
+ res
141
+ end
142
+
143
+ #######################################################################
144
+
145
+ private
146
+
147
+ #######################################################################
148
+
149
+ def on_tags(res, item)
150
+ attr_mask = item.turn_on
151
+ return if attr_mask.zero?
152
+
153
+ @attr_tags.each do |tag|
154
+ if attr_mask & tag.bit != 0
155
+ res << annotate(tag.on)
156
+ end
157
+ end
158
+ end
159
+
160
+ def off_tags(res, item)
161
+ attr_mask = item.turn_off
162
+ return if attr_mask.zero?
163
+
164
+ @attr_tags.reverse_each do |tag|
165
+ if attr_mask & tag.bit != 0
166
+ res << annotate(tag.off)
167
+ end
168
+ end
169
+ end
170
+
171
+ def convert_flow(flow)
172
+ res = ""
173
+ flow.each do |item|
174
+ case item
175
+ when String
176
+ res << convert_string(item)
177
+ when AttrChanger
178
+ off_tags(res, item)
179
+ on_tags(res, item)
180
+ when Special
181
+ res << convert_special(item)
182
+ else
183
+ raise "Unknown flow element: #{item.inspect}"
184
+ end
185
+ end
186
+ res
187
+ end
188
+
189
+ # some of these patterns are taken from SmartyPants...
190
+
191
+ def convert_string(item)
192
+ item = CGI.escapeHTML(item).
193
+
194
+ # convert -- to em-dash, (-- to en-dash)
195
+ gsub(/---?/, '&#8212;'). #gsub(/--/, '&#8211;').
196
+
197
+ # convert ... to elipsis (and make sure .... becomes .<elipsis>)
198
+ gsub(/\.\.\.\./, '.&#8230;').gsub(/\.\.\./, '&#8230;').
199
+
200
+ # convert single closing quote
201
+ gsub(%r{([^ \t\r\n\[\{\(])\'}) { "#$1&#8217;" }.
202
+ gsub(%r{\'(?=\W|s\b)}) { "&#8217;" }.
203
+
204
+ # convert single opening quote
205
+ gsub(/'/, '&#8216;').
206
+
207
+ # convert double closing quote
208
+ gsub(%r{([^ \t\r\n\[\{\(])\'(?=\W)}) { "#$1&#8221;" }.
209
+
210
+ # convert double opening quote
211
+ gsub(/'/, '&#8220;').
212
+
213
+ # convert copyright
214
+ gsub(/\(c\)/, '&#169;').
215
+
216
+ # convert and registered trademark
217
+ gsub(/\(r\)/, '&#174;')
218
+
219
+ # convert column separator (by ando)
220
+ if item =~ /^\|\|(.*)/
221
+ #item = item.sub(/^\|\|/, '').gsub('||', '</td><td>')
222
+ item = $1.gsub('||', '</td><td>')
223
+ end
224
+
225
+ item
226
+ end
227
+
228
+ def convert_special(special)
229
+ handled = false
230
+ Attribute.each_name_of(special.type) do |name|
231
+ method_name = "handle_special_#{name}"
232
+ if self.respond_to? method_name
233
+ special.text = send(method_name, special)
234
+ handled = true
235
+ end
236
+ end
237
+ raise "Unhandled special: #{special}" unless handled
238
+ special.text
239
+ end
240
+
241
+ def convert_heading(level, flow)
242
+ res =
243
+ annotate("<h#{level}>") +
244
+ convert_flow(flow) +
245
+ annotate("</h#{level}>\n")
246
+ end
247
+
248
+ def html_list_name(list_type, is_open_tag)
249
+ tags = LIST_TYPE_TO_HTML[list_type] || raise("Invalid list type: #{list_type.inspect}")
250
+ annotate(tags[ is_open_tag ? 0 : 1])
251
+ end
252
+
253
+ def list_item_start(am, fragment)
254
+ case fragment.type
255
+ when ListBase::BULLET, ListBase::NUMBER
256
+ annotate("<li>")
257
+
258
+ when ListBase::UPPERALPHA
259
+ annotate("<li type=\"A\">")
260
+
261
+ when ListBase::LOWERALPHA
262
+ annotate("<li type=\"a\">")
263
+
264
+ when ListBase::LABELED
265
+ annotate("<dt>") +
266
+ convert_flow(am.flow(fragment.param)) +
267
+ annotate("</dt>") +
268
+ annotate("<dd>")
269
+
270
+ when ListBase::NOTE
271
+ annotate("<tr>") +
272
+ annotate("<td valign=\"top\">") +
273
+ convert_flow(am.flow(fragment.param)) +
274
+ annotate("</td>") +
275
+ annotate("<td>")
276
+
277
+ when ListBase::TABLE # added by ando
278
+ annotate("<tr><td>")
279
+
280
+ else
281
+ raise "Invalid list type"
282
+ end
283
+ end
284
+
285
+ def list_end_for(fragment_type)
286
+ case fragment_type
287
+ when ListBase::BULLET, ListBase::NUMBER, ListBase::UPPERALPHA, ListBase::LOWERALPHA
288
+ "</li>"
289
+ when ListBase::LABELED
290
+ "</dd>"
291
+ when ListBase::NOTE
292
+ "</td></tr>"
293
+ when ListBase::TABLE # added by ando
294
+ "</td></tr>"
295
+ else
296
+ raise "Invalid list type"
297
+ end
298
+ end
299
+
300
+ end
301
+
302
+ end