docgenerator 0.1.1 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (152) hide show
  1. data/examples/docgenerator_example.rb +76 -160
  2. data/examples/docgenerator_example_footnote.rb +98 -0
  3. data/examples/docgenerator_example_list.rb +62 -0
  4. data/examples/docgenerator_example_restrictions.rb +59 -0
  5. data/examples/docgenerator_example_tabular.rb +68 -0
  6. data/examples/docgenerator_example_tripfalls.rb +57 -0
  7. data/examples/wiki2docgenerator_example.rb +270 -0
  8. data/lib/docgenerator.rb +159 -0
  9. data/{docgenerator_attribute.rb → lib/docgenerator_attribute.rb} +32 -7
  10. data/{docgenerator_characters.rb → lib/docgenerator_characters.rb} +15 -0
  11. data/{docgenerator_css.rb → lib/docgenerator_css.rb} +6 -1
  12. data/{docgenerator_document.rb → lib/docgenerator_document.rb} +92 -93
  13. data/{docgenerator_element.rb → lib/docgenerator_element.rb} +125 -51
  14. data/{docgenerator_elements.rb → lib/docgenerator_elements.rb} +40 -56
  15. data/{docgenerator_environments.rb → lib/docgenerator_environments.rb} +16 -10
  16. data/{docgenerator_footnote.rb → lib/docgenerator_footnote.rb} +44 -22
  17. data/{docgenerator_lists.rb → lib/docgenerator_lists.rb} +44 -39
  18. data/{docgenerator_sections.rb → lib/docgenerator_sections.rb} +2 -2
  19. data/{docgenerator_tabular.rb → lib/docgenerator_tabular.rb} +71 -39
  20. data/{packages → lib/packages}/docgenerator_attachfile.rb +0 -0
  21. data/{packages → lib/packages}/docgenerator_caption.rb +0 -0
  22. data/{packages → lib/packages}/docgenerator_hyperref.rb +0 -0
  23. data/{packages → lib/packages}/docgenerator_listings.rb +1 -2
  24. data/{packages → lib/packages}/docgenerator_pdfpages.rb +0 -0
  25. data/{packages → lib/packages}/docgenerator_scrlettr2.rb +2 -2
  26. data/{packages → lib/packages}/docgenerator_scrpage2.rb +0 -0
  27. data/{packages → lib/packages}/docgenerator_url.rb +0 -0
  28. data/lib/templates/docgenerator_template.rb +176 -0
  29. data/lib/templates/docgenerator_template.yaml +105 -0
  30. data/lib/wiki2doc/wiki2docgenerator.rb +1161 -0
  31. data/self_docgenerator.rb +161 -0
  32. data/unittest/expected/test_beamer_note.html +1 -0
  33. data/unittest/expected/test_beamer_note.latex +1 -0
  34. data/unittest/expected/test_beamer_note.text +1 -0
  35. data/unittest/expected/test_beamer_note.wiki +1 -0
  36. data/unittest/expected/test_block.html +1 -0
  37. data/unittest/expected/test_block.latex +1 -0
  38. data/unittest/expected/test_block.text +1 -0
  39. data/unittest/expected/test_block.wiki +2 -0
  40. data/unittest/expected/test_css.css +1 -0
  41. data/unittest/expected/test_css2.css +1 -0
  42. data/unittest/expected/test_description.html +1 -0
  43. data/unittest/expected/test_description.latex +3 -0
  44. data/unittest/expected/test_description.text +3 -0
  45. data/unittest/expected/test_description.wiki +3 -0
  46. data/unittest/expected/test_document_article.latex +23 -0
  47. data/unittest/expected/test_document_html.html +14 -0
  48. data/unittest/expected/test_document_replacement_article.latex +23 -0
  49. data/unittest/expected/test_document_replacement_html.html +14 -0
  50. data/unittest/expected/test_document_replacement_text.text +5 -0
  51. data/unittest/expected/test_document_replacement_wiki.wiki +5 -0
  52. data/unittest/expected/test_document_text.text +5 -0
  53. data/unittest/expected/test_document_wiki.wiki +5 -0
  54. data/unittest/expected/test_enumerate.html +1 -0
  55. data/unittest/expected/test_enumerate.latex +3 -0
  56. data/unittest/expected/test_enumerate.text +1 -0
  57. data/unittest/expected/test_enumerate.wiki +2 -0
  58. data/unittest/expected/test_footnote.html +5 -0
  59. data/unittest/expected/test_footnote.latex +11 -0
  60. data/unittest/expected/test_footnote.text +13 -0
  61. data/unittest/expected/test_footnote.wiki +11 -0
  62. data/unittest/expected/test_footnote_group.html +8 -0
  63. data/unittest/expected/test_footnote_group.latex +17 -0
  64. data/unittest/expected/test_footnote_group.wiki +17 -0
  65. data/unittest/expected/test_href.html +2 -0
  66. data/unittest/expected/test_href.latex +8 -0
  67. data/unittest/expected/test_href.text +4 -0
  68. data/unittest/expected/test_html_css.html +1 -0
  69. data/unittest/expected/test_itemize.html +1 -0
  70. data/unittest/expected/test_itemize.latex +3 -0
  71. data/unittest/expected/test_itemize.text +1 -0
  72. data/unittest/expected/test_itemize.wiki +2 -0
  73. data/unittest/expected/test_section.html +8 -0
  74. data/unittest/expected/test_section.latex +20 -0
  75. data/unittest/expected/test_section.text +24 -0
  76. data/unittest/expected/test_section.wiki +20 -0
  77. data/unittest/expected/test_tabular.html +10 -0
  78. data/unittest/expected/test_tabular.latex +10 -0
  79. data/unittest/expected/test_tabular.wiki +31 -0
  80. data/unittest/expected/test_tabular_doc.latex +22 -0
  81. data/unittest/expected/test_wiki.html +6 -0
  82. data/unittest/expected/test_wiki.latex +12 -0
  83. data/unittest/expected/test_wiki.text +14 -0
  84. data/unittest/expected/test_wiki.wiki +12 -0
  85. data/unittest/expected/test_wiki_amazon.html +10 -0
  86. data/unittest/expected/test_wiki_description.html +7 -0
  87. data/unittest/expected/test_wiki_description.latex +11 -0
  88. data/unittest/expected/test_wiki_description.text +6 -0
  89. data/unittest/expected/test_wiki_description.wiki +6 -0
  90. data/unittest/expected/test_wiki_footnote.html +8 -0
  91. data/unittest/expected/test_wiki_footnote.latex +15 -0
  92. data/unittest/expected/test_wiki_footnote.text +12 -0
  93. data/unittest/expected/test_wiki_footnote.wiki +12 -0
  94. data/unittest/expected/test_wiki_footnote_groupid.html +21 -0
  95. data/unittest/expected/test_wiki_html_code.html +7 -0
  96. data/unittest/expected/test_wiki_html_code.latex +10 -0
  97. data/unittest/expected/test_wiki_html_code.text +6 -0
  98. data/unittest/expected/test_wiki_html_code.wiki +6 -0
  99. data/unittest/expected/test_wiki_inline.html +6 -0
  100. data/unittest/expected/test_wiki_inline.latex +12 -0
  101. data/unittest/expected/test_wiki_inline.text +8 -0
  102. data/unittest/expected/test_wiki_inline.wiki +8 -0
  103. data/unittest/expected/test_wiki_label.html +6 -0
  104. data/unittest/expected/test_wiki_link.html +8 -0
  105. data/unittest/expected/test_wiki_link.latex +14 -0
  106. data/unittest/expected/test_wiki_link.log +3 -0
  107. data/unittest/expected/test_wiki_link.wiki +6 -0
  108. data/unittest/expected/test_wiki_list_ol.html +24 -0
  109. data/unittest/expected/test_wiki_list_ol.latex +30 -0
  110. data/unittest/expected/test_wiki_list_ol.text +10 -0
  111. data/unittest/expected/test_wiki_list_ol.wiki +12 -0
  112. data/unittest/expected/test_wiki_list_ol_after_ul.html +16 -0
  113. data/unittest/expected/test_wiki_list_ol_after_ul.latex +24 -0
  114. data/unittest/expected/test_wiki_list_ol_after_ul.text +8 -0
  115. data/unittest/expected/test_wiki_list_ol_after_ul.wiki +10 -0
  116. data/unittest/expected/test_wiki_list_ol_ul.html +24 -0
  117. data/unittest/expected/test_wiki_list_ol_ul.latex +30 -0
  118. data/unittest/expected/test_wiki_list_ol_ul.text +10 -0
  119. data/unittest/expected/test_wiki_list_ol_ul.wiki +12 -0
  120. data/unittest/expected/test_wiki_list_ul.html +24 -0
  121. data/unittest/expected/test_wiki_list_ul.latex +30 -0
  122. data/unittest/expected/test_wiki_list_ul.text +10 -0
  123. data/unittest/expected/test_wiki_list_ul.wiki +12 -0
  124. data/unittest/expected/test_wiki_list_ul_too_much.html +39 -0
  125. data/unittest/expected/test_wiki_list_ul_too_much.latex +51 -0
  126. data/unittest/expected/test_wiki_list_ul_too_much.text +11 -0
  127. data/unittest/expected/test_wiki_list_ul_too_much.wiki +15 -0
  128. data/unittest/expected/test_wiki_picture.html +55 -0
  129. data/unittest/expected/test_wiki_picture.latex +76 -0
  130. data/unittest/expected/test_wiki_picture_thumb.html +5 -0
  131. data/unittest/expected/test_wiki_tab1.html +30 -0
  132. data/unittest/expected/test_wiki_tab1.latex +30 -0
  133. data/unittest/expected/test_wiki_tab1.wiki +29 -0
  134. data/unittest/expected/test_wiki_textformatting.html +7 -0
  135. data/unittest/expected/test_wiki_textformatting.latex +16 -0
  136. data/unittest/expected/test_wiki_textformatting.text +11 -0
  137. data/unittest/expected/test_wiki_textformatting.wiki +9 -0
  138. data/unittest/expected/test_wiki_toc.html +9 -0
  139. data/unittest/expected/test_wiki_toc.latex +18 -0
  140. data/unittest/expected/test_wiki_toc.text +21 -0
  141. data/unittest/expected/test_wiki_toc.wiki +18 -0
  142. data/unittest/expected/test_wiki_ul_multiple_line.html +18 -0
  143. data/unittest/expected/test_wiki_ul_multiple_line.latex +19 -0
  144. data/unittest/expected/test_wiki_ul_multiple_line.text +6 -0
  145. data/unittest/expected/test_wiki_ul_multiple_line.wiki +7 -0
  146. data/unittest/test_docgenerator.rb +85 -0
  147. data/unittest/unittest_docgenerator.rb +454 -0
  148. data/unittest/unittest_wiki2doc.rb +451 -0
  149. metadata +155 -31
  150. data/docgenerator.rb +0 -137
  151. data/docgenerator_template.rb +0 -103
  152. data/packages/docgenerator_beamer.rb +0 -250
@@ -0,0 +1,105 @@
1
+ :text:
2
+ :target: :text
3
+ :source: |
4
+
5
+ <<body>>
6
+
7
+ :xhtml_strict:
8
+ :target: :html
9
+ :source: |
10
+ <!--
11
+ <<prefix>>
12
+ -->
13
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
14
+ <html>
15
+
16
+ <<head>>
17
+
18
+ <<body>>
19
+ </html>
20
+
21
+ :wiki:
22
+ :target: :wiki
23
+ :source: |
24
+
25
+ <<body>>
26
+
27
+ :xhtml_trans:
28
+ :target: :html
29
+ :source: |
30
+ <!--
31
+ <<prefix>>
32
+ -->
33
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
34
+ <html>
35
+
36
+ <<head>>
37
+
38
+ <<body>>
39
+ </html>
40
+
41
+ :html401_strict:
42
+ :target: :html
43
+ :source: |
44
+ <!--
45
+ <<prefix>>
46
+ -->
47
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
48
+ <html>
49
+
50
+ <<head>>
51
+
52
+ <<body>>
53
+ </html>
54
+
55
+ :html:
56
+ :target: :html
57
+ :source: |
58
+ <!--
59
+ <<prefix>>
60
+ -->
61
+ <!doctype html public "-//W3C//DTD HTML 4.01 Transitional//EN">
62
+ <html>
63
+ <<head>>
64
+ <<body>>
65
+ </html>
66
+
67
+ :html401_trans:
68
+ :target: :html
69
+ :source: |
70
+ <!--
71
+ <<prefix>>
72
+ -->
73
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
74
+ <html>
75
+
76
+ <<head>>
77
+
78
+ <<body>>
79
+ </html>
80
+
81
+ :include:
82
+ :target: :latex
83
+ :source: |
84
+ <<prefix>>
85
+ % ----------------------------------------------------------------
86
+ <<head>>
87
+ % ----------------------------------------------------------------
88
+ <<body>>
89
+ % ----------------------------------------------------------------
90
+
91
+ :article:
92
+ :target: :latex
93
+ :source: |
94
+ <<prefix>>
95
+ \documentclass[<<classoptions>>]{scrartcl}
96
+ \usepackage{babel}
97
+ \usepackage[ansinew]{inputenc}
98
+ \usepackage{hyperref}
99
+ % ----------------------------------------------------------------
100
+ <<head>>
101
+ % ----------------------------------------------------------------
102
+ \begin{document}
103
+ <<body>>
104
+ \end{document}
105
+ % ----------------------------------------------------------------
@@ -0,0 +1,1161 @@
1
+ #
2
+ #This small programm reads a text in Wiki-format and
3
+ #transform it to a "docgenerator"-object.
4
+ #
5
+ #This object can be saved as HTML or TeX (or Wiki again - in preparation).
6
+ #
7
+ #http://de.wikipedia.org/wiki/WikiSyntax
8
+ #http://de.wikipedia.org/wiki/Hilfe:Textgestaltung
9
+ #
10
+ #For usage: Check test.wiki.rb
11
+
12
+ #
13
+ #fixme:
14
+ #-
15
+ #- Textbaustein {{...}}
16
+ #Standard: [[ legt Textbaustein an, {{ nutzt diesen
17
+ # http://de.wikipedia.org/wiki/Wikipedia:Textbausteine/Schwesterprojekte
18
+ #- http://de.wikipedia.org/wiki/Wikipedia:Textbausteine
19
+
20
+ require 'C:/usr/Script/MyScripts' if File.exist?('C:/usr/Script/MyScripts.rb')
21
+ require 'docgenerator'
22
+ require 'log4r'
23
+ begin
24
+ require 'privat/docgenerator_affiliate'
25
+ rescue LoadError
26
+ end
27
+
28
+ #Struct for wiki-replacements.
29
+ #The proc contains three block-parameter: The match-element, the Wikitext-object and the logger-object.
30
+ Wikireg = Struct.new( 'WikiReg', :rule, :regex, :proc )
31
+ class Wikireg
32
+ @@give_message = true
33
+ def self.give_message=(val); @@give_message = val; end
34
+ def self.give_message?(); return @@give_message; end
35
+ end
36
+
37
+ #Constant with all Standard-replacemnts of Wikis.
38
+ #Each replacement should also convert the part before and after the match.
39
+ WIKI_INLINE_REPLACEMENTS = [
40
+ #[[Bild:Dateiname|Zusatzinfos|Beschreibung]]
41
+ #Zusatzinfos:
42
+ # -left
43
+ # -right
44
+ Wikireg.new(:bild, /\[\[Bild:(.*?)\]\]/,
45
+ Proc.new{|m, oo, log|
46
+ parameter = m[1].split('|')
47
+ [ oo.inline(m.pre_match, log),
48
+ oo.wiki_bild( parameter.first, parameter[1..-1], log),
49
+ oo.inline(m.post_match, log),
50
+ ]
51
+ } ),
52
+ Wikireg.new(:file, /\[\[File:(.*)\]\]/,
53
+ Proc.new{|m, oo, log|
54
+ parameter = m[1].split('|')
55
+ filename = parameter[0]
56
+ if parameter.size > 1
57
+ txt = "#{parameter.last}"
58
+ else
59
+ txt = File.basename(filename)
60
+ end
61
+ if Wikireg.give_message? and ! File.exist?(filename)
62
+ log.warn( "Link to unexisting local file #{filename} (from #{Dir.pwd})" ) if log.warn?
63
+ end
64
+
65
+ css = CSS.new()
66
+ parameter[1..-2].each{|p|
67
+ case p
68
+ when 'size'
69
+ txt << " (#{File.size(filename)/1024}KB)" if File.exist?(filename)
70
+ when /(.*)=>(.*)/
71
+ css[$1] = $2
72
+ else
73
+ log.warn( "Wiki-File with unknown setting #{p}" ) if log.warn?
74
+ end
75
+ }
76
+ #Result:
77
+ [
78
+ oo.inline(m.pre_match, log),
79
+ element(:a, { :href => filename, :alt => txt, :style => css }, oo.inline(txt, log) ),
80
+ oo.inline(m.post_match,log)
81
+ ]} ),
82
+ Wikireg.new(:label, %r{\[\[label:(.*)\]\]},
83
+ Proc.new{|m, oo, log|
84
+ [ oo.inline(m.pre_match, log),
85
+ element(:label, { :name => m[1]} ),
86
+ oo.inline(m.post_match, log)
87
+ ]
88
+ } ),
89
+ Wikireg.new(:ref, %r{<ref>(.*)</ref>},
90
+ Proc.new{|m, oo, log|
91
+ puts "<ref> is obsolete, use {{footnote}}. To get footnotes set {{footnotes|ref}}"
92
+ [ oo.inline(m.pre_match, log),
93
+ element(:footnote, { :groupid => 'ref' }, oo.inline(m[1],log) ),
94
+ oo.inline(m.post_match, log)
95
+ ]
96
+ } ),
97
+ Wikireg.new(:bf_it, /''''(.*?)''''/,
98
+ Proc.new{|m, oo, log| [ oo.inline(m.pre_match, log),
99
+ element(:textbf, {}, element(:emph, {}, oo.inline(m[1], log) )),
100
+ oo.inline(m.post_match, log)
101
+ ]} ),
102
+ Wikireg.new(:bf, /'''(.*?)'''/,
103
+ Proc.new{|m, oo, log| [ oo.inline(m.pre_match, log),
104
+ element(:textbf, {}, oo.inline(m[1], log)),
105
+ oo.inline(m.post_match, log)
106
+ ]} ),
107
+ Wikireg.new(:it, /''(.*?)''/,
108
+ Proc.new{|m, oo, log| [ oo.inline(m.pre_match, log),
109
+ element(:emph, {}, oo.inline(m[1], log)),
110
+ oo.inline(m.post_match, log)
111
+ ]} ),
112
+ #Soll in Wikipedia-Artikeln nicht verwendet werden.
113
+ Wikireg.new(:small, %r{<small>(.*)</small>},
114
+ Proc.new{|m, oo, log|
115
+ [ oo.inline(m.pre_match, log),
116
+ element(:small, {}, oo.inline(m[1], log )),
117
+ oo.inline(m.post_match, log)
118
+ ]
119
+ } ),
120
+ Wikireg.new(:stroke, %r{<s>(.*)</s>},
121
+ Proc.new{|m, oo, log|
122
+ [ oo.inline(m.pre_match, log),
123
+ element(:stroke, {}, oo.inline(m[1], log )),
124
+ oo.inline(m.post_match, log)
125
+ ]
126
+ } ),
127
+ #- Textbaustein {{...}}
128
+ #Standard: [[ legt Textbaustein an, {{ nutzt diesen
129
+ # http://de.wikipedia.org/wiki/Wikipedia:Textbausteine/Schwesterprojekte
130
+ #- http://de.wikipedia.org/wiki/Wikipedia:Textbausteine
131
+ Wikireg.new(:wikidef, /\[\[(.+?):(.*?)\]\]/,
132
+ Proc.new{|m, oo, log|
133
+ puts "wikidef #{m[1].inspect} obsolete, please use macro {{..|"
134
+ [ oo.inline(m.pre_match, log),
135
+ oo.wikidef(m[1], m[2] ),
136
+ oo.inline(m.post_match, log)
137
+ ]}
138
+ ),
139
+ Wikireg.new(:wiki_macro, /\{\{(.+?)(\|(.*?))?\}\}/,
140
+ Proc.new{|m, oo, log|
141
+ [ oo.inline(m.pre_match, log),
142
+ oo.wiki_macro(m[1], m[3] ),
143
+ oo.inline(m.post_match, log)
144
+ ].delete_if{|e| ! e or e.respond_to?(:to_str) and /\A\s*\Z/m =~ e}
145
+ #[].delete(nil) may return nil -> use delete_if
146
+ }
147
+ ),
148
+ #Problem: detect end of url without a end-character
149
+ #[uri text]
150
+ Wikireg.new(:url1, %r{\[\s*((?:https?://|\.|C:\\|C:\/|ftp:|mailto:|webcal://).*?)\s+(.*?)\s*\]},
151
+ Proc.new{|m, oo, log|
152
+ #Check local files, but without anchor
153
+ if /\A\./ =~ m[1] #local file
154
+ filename = oo.inputsource + m[1].split(/#/).first
155
+ else
156
+ filename = m[1].split(/#/).first
157
+ end
158
+ if Wikireg.give_message? and /\A(\.|\w:)/ =~ m[1] and ! File.exist?(filename)
159
+ log.warn( "Link to unexisting local file #{filename} (from #{Dir.pwd})" ) if log.warn?
160
+ end
161
+ link_url = m[1]
162
+ if /^\w:/ =~ link_url #local file with absolut path
163
+ link_url = 'file://' + link_url
164
+ end
165
+ if m[2].size > 0
166
+ linktext = m[2]
167
+ else
168
+ linktext = m[1].sub(/http:\/\//, '').sub(/\/$/, '')
169
+ end
170
+ [ oo.inline(m.pre_match, log),
171
+ element(:a, {:href=> link_url }, oo.inline(linktext, log) ).Cr,
172
+ oo.inline(m.post_match, log)
173
+ ]
174
+ }
175
+ ),
176
+ #uri http...
177
+ Wikireg.new(:url2, %r{(https?://.*?)(\s|\Z)},
178
+ Proc.new{|m, oo, log|
179
+ [ oo.inline(m.pre_match, log),
180
+ #~ element(:a, {:href=> m[1]}, m[1] ), #hier kein oo.inline
181
+ element(:url, {}, m[1] ), #hier kein oo.inline
182
+ m[2], #Space/CR
183
+ oo.inline(m.post_match, log)
184
+ ]} ),
185
+ Wikireg.new(:wikilink, /\[\[(.+?)(\|(.*?))?\]\]/,
186
+ #~ Wikireg.new(:wikilink, /\[\[(.+?)\]\]/,
187
+ Proc.new{|m, oo, log|
188
+ linktext = m[1]
189
+ #m[2] includes the |
190
+ if m[3]
191
+ linktext = m[3]
192
+ end
193
+ [ oo.inline(m.pre_match, log),
194
+ element(:a, {:href=> m[1]},
195
+ oo.inline(linktext, log)
196
+ ),
197
+ oo.inline(m.post_match, log)
198
+ ]
199
+ } ),
200
+ ]
201
+
202
+ #require 'LotusNotes.rb'
203
+ WIKI_INLINE_REPLACEMENT_NOTES =
204
+ Wikireg.new(:notes, /(Notes:.*?)(\s|\Z)/, Proc.new{|m, oo, log|
205
+ [
206
+ oo.inline( m.pre_match, log),
207
+ LN_Link.new( m[1] ).to_element,
208
+ m[2],
209
+ oo.inline( m.post_match, log ),
210
+ ]})
211
+
212
+ WIKI_INLINE_REPLACEMENTS_SYMBOLS = [
213
+ #Problem: Native LaTeX with beamer and \only...
214
+ Wikireg.new(:arrow, /->/,
215
+ Proc.new{|m, oo, log|
216
+ [ oo.inline(m.pre_match, log),
217
+ element(:rightarrow),
218
+ oo.inline(m.post_match, log),
219
+ ]
220
+ } ),
221
+ Wikireg.new(:Arrow, /=>/,
222
+ Proc.new{|m, oo, log|
223
+ [ oo.inline(m.pre_match, log),
224
+ element(:Rightarrow),
225
+ oo.inline(m.post_match, log),
226
+ ]
227
+ } ),
228
+ ]
229
+
230
+ WIKI_INLINE_REPLACEMENTS_UNDERSCORE = Wikireg.new(:underscore, /_/,
231
+ Proc.new{|m, oo, log|
232
+ [ oo.inline(m.pre_match, log),
233
+ "\\_",
234
+ oo.inline(m.post_match, log),
235
+ ]
236
+ } )
237
+
238
+ #require 'LotusNotes.rb'
239
+ if defined? LN_Link
240
+ WIKI_INLINE_REPLACEMENTS << WIKI_INLINE_REPLACEMENT_NOTES
241
+ end
242
+
243
+ module Wiki_helper
244
+ #Transfer the input to a list.
245
+ #input can be
246
+ #-String
247
+ #-List
248
+ #-File (if .rb, then the part after __END__ is taken)
249
+ #The method returns a list with lines, but no \n
250
+ def get_input( input, lineoffset, close_it = false )
251
+ inputlist = []
252
+ if input.is_a?(String)
253
+ #~ inputlist = input.split("\n")
254
+ #Convert to Array, but keep the \n
255
+ inputlist = input.split("\n")
256
+ elsif input.is_a?(Array)
257
+ inputlist = input.flatten.map{|l| l.chomp()}
258
+ elsif input.is_a?(File)
259
+ #If file is a ruby scriot, then the wiki-code in after __END__
260
+ if /\.rb\Z/ =~ input.path and $0 != input.path
261
+ line = input.readline while line != "__END__\n"
262
+ end
263
+ lineoffset = input.lineno
264
+ inputlist << input.readlines.map{|l| l.chomp}
265
+ input.close if close_it
266
+ end
267
+ return inputlist, lineoffset
268
+ end
269
+ end
270
+ #
271
+ #Struct for wiki elements.
272
+ class Wikielements < Struct.new('Wikielements', :first, :l1,:l2,:l3,:l4, :tab, :row )
273
+ #Clear all precesssors.
274
+ def clear( element )
275
+ if element.is_a?(Integer)
276
+ element = self.members[element]
277
+ end
278
+ self.members.reverse.each{|i|
279
+ break if i == element.to_s
280
+ self[i] = nil
281
+ }
282
+ end
283
+ end
284
+
285
+
286
+ class Wikitext
287
+ #Read text and convert it to a Document.
288
+ def initialize(
289
+ options = {}
290
+ )
291
+ #convert from old interface
292
+ options = {
293
+ :wiki_inline_replacements => options
294
+ } if options.is_a?(Array)
295
+ @options = {
296
+ :wiki_inline_replacements => WIKI_INLINE_REPLACEMENTS + WIKI_INLINE_REPLACEMENTS_SYMBOLS,
297
+ :log => Log4r::Logger.new('Wikitext', Log4r::INFO),
298
+ :inputsource => './',
299
+ :parsetest => false #Make an immediate test for parsing
300
+ }.update(options)
301
+ @source = []
302
+ #This rules can be extended via the accessors.
303
+ @wiki_inline_replacements = @options[:wiki_inline_replacements]
304
+ @lineoffset = 0 #for better debugging
305
+ @inputsource = @options[:inputsource]
306
+ @log = @options[:log]
307
+ @log.outputters = Log4r::StdoutOutputter.new('log_stdout') if @log.outputters.empty?
308
+ self << @options[:content] if @options[:content]
309
+ @parent = self
310
+ end
311
+ #Line offset.
312
+ #Is used as initial value in <<
313
+ attr_writer :lineoffset
314
+ #Used for relative filecheck
315
+ attr_accessor :inputsource
316
+ #Array with the rules for the inline elements (like text formatting...)
317
+ #Can be extended/replaces by this accessor
318
+ #
319
+ #Don't include arrays. elements must be 'Wikireg'.
320
+ attr_reader :wiki_inline_replacements
321
+ #Logger
322
+ attr_reader :log
323
+ #Element, where the wiki test belongs to.
324
+ #Can be used in the procs insiede a wikirule.
325
+ attr_accessor :parent
326
+ #Wiki-Code, which is translated to to_element.
327
+ #Source is an array
328
+ attr_accessor :source
329
+
330
+ include Wiki_helper
331
+ #Add contents to Wiki-Text
332
+ def <<( input )
333
+ inputlist, lineoffset = get_input( input, @lineoffset )
334
+ #The immediate parsing may help, when an error occurs.
335
+ #The immediat parsing returns error messages with correct lineoffsets.
336
+ #(On the other side, it may helt to see the @source itself)
337
+ wiki2doc( inputlist.join("\n"), lineoffset ) if @options[:parsetest] == true
338
+ @source.concat(inputlist)
339
+ return self
340
+ end
341
+ #Prepare output for docgenerator.
342
+ #
343
+ #Attention! to_doc uses another logger then the wiki.
344
+ #If it should be the same, it must be added at definition of the wiki.
345
+ def to_doc( target, options = {} )
346
+ o = Docgenerator_logger.set_option_defaults(options)
347
+ o[:log].debug("enter to_doc for Wikitext #{self.inspect}") if o[:log].debug?
348
+ Footnotegroup.clear()
349
+ doc = wiki2doc( @source.join("\n") ) #return lists of element
350
+ doc.to_doc(target, options )
351
+ end
352
+
353
+ #
354
+ #Method is called for wiki-structures like
355
+ # [[key:value]]
356
+ #This can be used to adapt the wiki for special usages.
357
+ #
358
+ #This is a inline replacement.
359
+ #The return code is added at the location, where it is defined
360
+ def wikidef( key, value )
361
+ @log.warn("#{self.class}#wikidef #{key}: #{value} in line #{@lineno}" ) if log.warn?
362
+ return value
363
+ end
364
+ #Include a picture
365
+ # [[Bild:Dateiname|Zusatzinfos|Beschreibung]]
366
+ #Zusatzinfos:
367
+ # -left/right
368
+ # -___px scale the pic. When used in combination with thumb, a pic "widht-picname) is searched.
369
+ # -thumb (usefull in combination with href or width=50%)
370
+ #figure_type:
371
+ #The picture is framed by this value.
372
+ #When you use :div, you can't make inline-Pics.
373
+ #:span can be used also as float (HTML)
374
+ #Correct LaTeX: figure (or not?
375
+ def wiki_bild( picname, parameter, log, figure_type = :span)
376
+ thumb = false #Use thumb instead
377
+ href = false #make pic clickabe
378
+ figure = element(figure_type, { :style => css_fig = CSS.new() }).cR
379
+ css_img = CSS.new()
380
+ option = { :src => picname, :style => css_img } #Options for img
381
+ before_img = []
382
+ after_img = []
383
+
384
+ parameter.each{|p|
385
+ case p
386
+ when /href=(.*)/; href = $1
387
+ when /alt=(.*)/; option[:alt] = $1
388
+ when /imgclass=(.*)/; option[:class] = $1
389
+ when /figureclass=(.*)/; figure[:class] << $1
390
+ when /^class=(.*)/; option[:class] = $1 #old
391
+ when 'left', 'right'
392
+ css_fig[:float] = p
393
+ when /aftertitle(=(.*))*/
394
+ after_img << element(:br, { :clear => 'all' } ).cr
395
+ after_img << $2
396
+ when /beforetitle(=(.*))*/
397
+ before_img << $2
398
+ after_img << element(:br, { :clear => 'all' } ).cr
399
+ when /thumb(=(.*))*/
400
+ #Add a thumb in the text and link to picture
401
+ thumb = true #look later for width-picname
402
+ thumb = $2 if $2
403
+ if File.exist?( @inputsource + picname ) and !href
404
+ href = picname
405
+ end
406
+ when /\A\d*px\Z/ #size
407
+ option[:width] = p
408
+ when /(width)=(.*)/
409
+ css_img[$1] = $2
410
+ w = $2 #store it, $2 is replaced in next regex.
411
+ case w
412
+ when /100%/
413
+ option[:width] = "\\textwidth"
414
+ when /\A(\d+)%/
415
+ option[:width] = "0.#{$1}\\textwidth"
416
+ else
417
+ option[:width] = w
418
+ end
419
+ when /(.*)=(.*)/
420
+ css_img[$1] = $2
421
+ else
422
+ log.warn( "Wiki-Picture with unknown setting #{p}" ) if log.warn?
423
+ end
424
+ }
425
+
426
+ bild = []
427
+ bild = element(:a, {:href=>href }).cr if href
428
+
429
+ figure << before_img if ! before_img.empty?
430
+ figure << bild
431
+ figure << after_img if ! after_img.empty?
432
+
433
+ if thumb == true
434
+ if File.exist?( "#{option[:width]}-#{option[:src]}" )
435
+ thumb = "#{option[:width]}-#{option[:src]}"
436
+ else
437
+ thumb = picname
438
+ end
439
+ end
440
+ option[:src] = thumb if thumb
441
+
442
+ if /^(http|file|.:\/|\/)/ =~ option[:src]
443
+ src = option[:src]
444
+ else
445
+ src = @inputsource + option[:src]
446
+ end
447
+ if /^http/ !~ src and ! File.exist?( (src).sub(%r{file:\/\/}, '') )
448
+ log.warn( "Wikireg:bild: Picture #{option[:src]} not found (check from #{Dir.pwd} #{inputsource})" ) if log.warn?
449
+ end
450
+ if thumb and ! File.exist?( @inputsource + thumb )
451
+ log.warn( "Wikireg:bild: Thumb #{thumb} not found (check from #{Dir.pwd} #{inputsource})" ) if log.warn?
452
+ end
453
+ if href and /^http:/!~ href and ! File.exist?( @inputsource + href )
454
+ log.warn("Wikireg:bild: reference #{href} not found (check from #{Dir.pwd} #{inputsource})" ) if log.warn?
455
+ #~ puts Dir.pwd
456
+ #~ puts @inputsource.inspect
457
+ #~ puts href
458
+ #~ puts option[:src]
459
+ #~ puts '-'*10
460
+ end
461
+
462
+ bild << element(:img, option )
463
+ figure
464
+ end #wiki_bild
465
+
466
+ #
467
+ #Analyses {{-Textmacros.
468
+ #If it is redefined, but want to keep the standard method,
469
+ #then you can call it via super in the else-branch of your case-command.
470
+ def wiki_macro( key, value, log = @log )
471
+ if value
472
+ val = value.split('|')
473
+ else
474
+ val = []
475
+ end
476
+ case key
477
+ when 'maketitle', 'author', 'title', 'date'
478
+ val = val[0]
479
+ return [
480
+ element( key.to_sym,{},val ).cr,
481
+ ]
482
+ when 'Commons'
483
+ return [
484
+ element(:a, { :href => "http://commons.wikimedia.org/wiki/#{val[0]}" }, "Commons: #{val[0]}" ).cr,
485
+ ]
486
+ #~ when 'Wikibooks'
487
+ #~ #fixme language?
488
+ #~ return [
489
+ #~ element(:a, { :href => "http://en.wikibooks.org/wiki/#{val[0]}" }, "Commons: #{val[0]}" ).cr,
490
+ #~ ]
491
+ when 'newline'
492
+ if val.include?('clear')
493
+ return element(:br, {:clear=>'all'})
494
+ else
495
+ return element(:br)
496
+ end
497
+ when 'dmoz'
498
+ def dmoz_analyse(val)
499
+ if val[1]
500
+ catname = val[1]
501
+ else
502
+ catname = val[0].split(/\//).last.gsub(/_/, ' ')
503
+ end
504
+ cat = val[0].sub(%r{http://(www|editors)*.dmoz.org/}, '')
505
+ cat << '/' if cat[-1,1] != '/'
506
+ return cat, catname
507
+ end
508
+ cat, catname = dmoz_analyse(val)
509
+ return [
510
+ 'Weitere Links zum Thema ',
511
+ element(:a, { :href => "http://dmoz.org/#{cat}" }, catname ),
512
+ ' im Open Directory Project'
513
+ ]
514
+ when 'dmozed'
515
+ #fixme: Umlaute
516
+ cat, catname = dmoz_analyse(val)
517
+ return [
518
+ element(:a, { :href => "http://dmoz.org/#{cat}" }, catname ),
519
+ ' ',
520
+ element(:a, { :href => "http://editors.dmoz.org/editors/editcat.cgi?cat=#{cat}" },
521
+ [ '(Edit)'])
522
+ ]
523
+ #footnotes|groupid
524
+ when 'footnotes'
525
+ #~ value = self.object_id if ! value
526
+ value = nil if ! value
527
+ return Footnotegroup.get( value )
528
+ #footnote[groupid]
529
+ when /footnote(\[(.*)\])*/
530
+ #fixme footnotegroup?
531
+ #~ $2 ? groupid = $2 : groupid = self.object_id
532
+ $2 ? groupid = $2 : groupid = nil
533
+ return [
534
+ element(:footnote, { :groupid =>groupid }, self.inline(value, log) ),
535
+ ]
536
+ when 'html'
537
+ return element(:htmlonly, {}, value )
538
+ when 'rubycode', 'rubyvar' ##Pfui, eval
539
+ log.warn( "#{self.class}#wiki_macro: eval in line #{@lineno} ('#{value}')" ) if log.warn?
540
+ #~ return eval(value)
541
+ return eval(value, binding, 'Wiki', @lineno)
542
+ when 'verbatimfile'
543
+ if File.exist?( val.first )
544
+ return element(:verbatim,
545
+ Hash[*val[1..-1].map{|v| kv = v.split(/=/); [kv[0].to_sym, kv[1]]}.flatten],
546
+ File.read(val.first) )
547
+ else
548
+ log.warn( "#{self.class}#wiki_macro: File #{value} missing for verbatimfile in line #{@lineno}" ) if log.warn?
549
+ end
550
+ when 'filecontent'
551
+ if File.exist?( val.first )
552
+ return element(:div,
553
+ Hash[*val[1..-1].map{|v| kv = v.split(/=/); [kv[0].to_sym, kv[1]]}.flatten],
554
+ File.read(val.first) )
555
+ else
556
+ log.error( "#{self.class}#wiki_macro: File #{value} missing for filecontent in line #{@lineno}" ) if log.error?
557
+ end
558
+ #A symbol. The corresponding element must be defined.
559
+ when 'symbol'; return element(value.to_sym)
560
+ when 'backslash'; return element(:backslash )
561
+ when '^'; return element(:ensuremath, {}, element(:'^' ) )
562
+ when '>'; return element(:gt)
563
+ when '<'; return element(:lt)
564
+ when 'percent', '%'; return element(:percent )
565
+ when 'rbrace'; return element(:rbrace )
566
+ when '_'; return element(:underscore )
567
+ when ' '; return element(:relax )
568
+ when 'lbrace'; return element(:lbrace )
569
+ when 'tilde', 'sim'; return element(:sim )
570
+ when 'math'; return element(:ensuremath,{}, value )
571
+ #>>>requires privat/affiliate.rb
572
+ when 'asin'
573
+ return Amazon.new.asin_in_iframe( value )
574
+ when 'amazon' #~ {{amazon|produktlinie|keywords}}
575
+ return Amazon.make_link(val)
576
+ when 'jpc' #~ {{amazon|produktlinie|keywords}}
577
+ return JPC.make_link(val)
578
+ #<<<requires privat/affiliate.rb
579
+ when 'fixme'
580
+ log.info( "Fixme: #{value}" ) if log.info?
581
+ return element(:comment, {}, [ 'Fixme: ', value ] )
582
+ else
583
+ log.error( "#{self.class}#wiki_macro Key '#{key}' unknown in line #{@lineno} ('#{value}')" ) if log.error?
584
+ return value
585
+ end
586
+ end
587
+
588
+
589
+ #Little structure for use in wiki2doc.
590
+ Wiki_line = Struct.new('Wiki_line', :type, :content, :lineno, :indent, :add_info)
591
+ #
592
+ #Parse the text and creates the elements of it.
593
+ #
594
+ def wiki2doc( txt, lineoffset = 0, log = @log )
595
+ (@wiki_inline_replacements ).each{|rule|
596
+ if ! rule.is_a?(Wikireg)
597
+ log.fatal( "Wikitext.wiki2doc: rule is no Wikireg #{rule.inspect}" ) if log.fatal?
598
+ end
599
+ }
600
+
601
+ lines = []
602
+ @lineno = lineoffset
603
+ collector = nil #collect content for other application
604
+ collectorline = nil #collect content for other application
605
+
606
+ txt.each{|line|
607
+ if line.gsub!( /#~.*/, '') #delete comments
608
+ #skip processing, if the line is now empty.
609
+ #Without this, empty paragraphs can be created.
610
+ next if line == "\n"
611
+ end
612
+ @lineno += 1
613
+
614
+ #if the content should be turned into new variant, do it here.
615
+ if collector
616
+ if /^<<</ =~ line #close the collector
617
+ lines << Wiki_line.new(:collector, collector, collectorline )
618
+ collector = nil
619
+ else
620
+ collector << line.chomp #collect content to collector
621
+ end
622
+ next
623
+ end
624
+ #Preparse. Detect line type and assign it
625
+ case line.chomp
626
+ #Example:
627
+ #>>>structogramm{title;width;height}
628
+ when /^>>>(.*)\{(.*)\}/
629
+ args = []
630
+ ctype = $1
631
+ args = $2.split(/[;]/) if $2
632
+ collector = WikiCollector.create(ctype, args )
633
+ collectorline = @lineno
634
+ if ! collector
635
+ log.error( "#{__FILE__}##{__LINE__}: Undefined Collector #{ctype.inspect} used. Take Array instead (line #{@lineno})" ) if log.error?
636
+ collector = []
637
+ end
638
+ #===[key]Titel===
639
+ when /\A(=+)(?:\[(.*?)\])?(.+?)(=+)\s*/ #:h1, :h2, :h3, :h4, :h5, :h6
640
+ #~ puts $1, $2, $3
641
+ if $1.size != $4.size
642
+ log.warn("#{__FILE__}: Heading problem #{$1} doesn't match <#{$3}> #{line.inspect}" ) if log.warn?
643
+ end
644
+ #Level starts with ==
645
+ # =title= is not supported.
646
+ h_level = "h#{$1.size - 1}".to_sym
647
+ lines << Wiki_line.new(h_level, self.inline($3, log), @lineno, nil, $2)
648
+ when /^\s*$/ #empty line
649
+ lines << Wiki_line.new(:p,nil, @lineno)
650
+ when /^((?:\*|\#)+)(\s*)/ #:li
651
+ lines << Wiki_line.new(:li, self.inline($~.post_match, log), @lineno, $2.size, $1)
652
+ #Experiment f�r items in description
653
+ #~ when /^(:)?((?:\*|\#)+)(\s*)/ #:li
654
+ #~ puts '>' * 15
655
+ #~ puts line.inspect
656
+ #~ puts $1.inspect
657
+ #~ puts $2.inspect
658
+ #~ puts $3.inspect
659
+ #~ puts '<' * 15
660
+ #~ lines << Wiki_line.new(:li, self.inline($~.post_match, log), @lineno, $3.size, $2)
661
+ when /^;(\s*)/ #:dt
662
+ lines << Wiki_line.new(:dt, self.inline($~.post_match, log), @lineno, $1.size)
663
+ when /^:(\s*)/ #:dd
664
+ lastline = lines.last
665
+ if ! lastline
666
+ log.warn( "#{__FILE__}: Use ':' at start of wiki text. #{@lineno}" ) if log.warn?
667
+ lastline = Wiki_line.new() #Avoid error with method type
668
+ end
669
+ #If there was already an indent before, loo back.
670
+ if lastline.type == :indent
671
+ #find first line before indent
672
+ lines.reverse.each{|line|
673
+ lastline = line
674
+ break if lastline.type != :indent
675
+ }
676
+ end
677
+ if [:dt,:dd].include?(lastline.type)
678
+ lines << Wiki_line.new(:dd, self.inline($~.post_match, log), @lineno, $1.size)
679
+ else #-> quote
680
+ lines << Wiki_line.new(:quote, self.inline($~.post_match, log), @lineno, $1.size)
681
+ end
682
+ when /^----$/ #:hr #line
683
+ lines << Wiki_line.new(:hr,nil,@lineno)
684
+ when /^(\s+)/ #:indent #can be: continuation of a list or a verbatim
685
+ lines << Wiki_line.new(:indent, $~.post_match, @lineno, $1.size)
686
+ when /^\{\|/ #:tab
687
+ lines << Wiki_line.new(:tabular,$~.post_match,@lineno)
688
+ when /^\|\}/ #:tabend
689
+ lines << Wiki_line.new(:tabular_end,$~.post_match,@lineno)
690
+ when /^\|-/ #:tabrow
691
+ lines << Wiki_line.new(:tabular_row,$~.post_match,@lineno)
692
+ when /^\|(.*\|)*(.*?)\s*$/ #:tabcell
693
+ par = $1
694
+ txt = $2
695
+ #if the text contains macros with | there is a bit confusion,
696
+ #what is a parameter of the cell and whats part of the macro.
697
+ #
698
+ #Solution:
699
+ #Define the end of cell parameters with ||
700
+ if par and par =~ /\|\|/
701
+ par = $~.pre_match #parameters only before ||
702
+ txt = $~.post_match + txt #txt all after ||
703
+ end
704
+ lines << Wiki_line.new(:tabular_cell ,self.inline(txt, log),@lineno,nil,par)
705
+ else
706
+ #~ puts "??\tUnknown line (#{__FILE__} line #{__LINE__})"
707
+ #~ puts "??\tUnknown line: #{line.inspect}"
708
+ #lines << Wiki_line.new(:text, self.inline(line, log), @lineno)
709
+ #Insert space at end of line, but before \n.
710
+ #Without, a line break results in HTML-Text without space between flow text
711
+ lines << Wiki_line.new(:text, self.inline("#{line.chomp} \n", log), @lineno)
712
+ end
713
+ } #txt.each |line|
714
+
715
+ if collector
716
+ log.error( "#{__FILE__}##{__LINE__}: Content Collector not closed (start in line #{collectorline}" ) if log.error?
717
+ end
718
+
719
+ elements = [] #main container
720
+ lists ={} #lists.
721
+ lines.each{|line|
722
+ case line.type
723
+ when :h1, :h2, :h3, :h4, :h5, :h6
724
+ elements << element( line.type,{},line.content).cr
725
+ if line.add_info
726
+ elements.last[:id] << line.add_info
727
+ end
728
+ #~ elements << element( line.type,{},self.inline(line.content, log)).cr
729
+ when :p #new paragraph
730
+ #fixme: how to detect new paragraph or continuation of item/pre/verbatim
731
+ if ! elements.last #Start wiki
732
+ elements << element( :p ).cr
733
+ elsif elements.last.is_a?(:p) and ! elements.last.content?
734
+ #There is already an empty new par, we can use it.
735
+ elsif elements.last.is_a?(ListEnvironment)
736
+ #The next indent decides, if we need a new paragraph or continue in the last item.
737
+ elements.last.content.last << nil #Add neutral flag for new paragraph
738
+ else
739
+ elements << element( :p ).cr
740
+ end
741
+ when :hr
742
+ elements << element( :hr ).cr
743
+ when :text
744
+ if ! elements.last or ! elements.last.is_a?(:p)
745
+ elements << element( :p ).cr
746
+ end
747
+ elements.last << line.content
748
+ when :li
749
+ if ! elements.last.is_a?(ListEnvironment) #ListEnvironment can be also a :dl
750
+ lists = {} #delete all lists to start fresh
751
+ end
752
+ #~ puts "-----#{line.add_info}\t#{line.content.inspect}\t#{lists.keys.inspect}"
753
+ listtype = ''
754
+ loclist = {} #temporary list of lists. will be stored in 'lists'
755
+ 1.upto(line.add_info.size){|level|
756
+ leveltyp = line.add_info[0..level-1] #typ of listhirarchie
757
+ if lists[leveltyp] #list already defined
758
+ loclist[leveltyp] = lists[leveltyp]
759
+ loclist[leveltyp] << element(:li,{}, line.content).cR if leveltyp == line.add_info
760
+ else #create new list
761
+ case line.add_info[-1,1]
762
+ when '*'
763
+ list_type = :ul
764
+ when '#'
765
+ list_type = :ol
766
+ else
767
+ log.error( "#{self.class}#wiki2doc: Unknown list type #{v}" ) if log.error?
768
+ end
769
+ loclist[leveltyp] = element( list_type ).CR
770
+ #include first item in list
771
+ loclist[leveltyp] << li = element(:li,{}).cR #add first item line
772
+ li << line.content if leveltyp == line.add_info #add content to item line
773
+ #Include list
774
+ if level == 1 #Add first list to element-list
775
+ elements << loclist[leveltyp]
776
+ elsif leveltyp == line.add_info #add new list to previous list
777
+ loclist[line.add_info[0,level-1]].content.last << loclist[leveltyp]
778
+ end
779
+ end
780
+ }
781
+ #copy lists and delete all other lists (so we get level changes)
782
+ lists = loclist
783
+ when :dt
784
+ #~ lists = {} #mixture dl and ul/ol not possible actual
785
+ if ! elements.last.is_a?(:dl)
786
+ elements << element(:dl).cR
787
+ lists[':'] = elements.last
788
+ end
789
+ elements.last << element(:dt,{},line.content ).cr
790
+ when :dd
791
+ if ! elements.last.is_a?(:dl)
792
+ log.warn( "#{self.class}#wiki2doc(#{line.lineno}: :dl without :dt (#{line.content.strip})" ) if log.warn?
793
+ elements << element(:dl).cr
794
+ end
795
+ elements.last << element(:dd,{},line.content).cr
796
+ when :quote
797
+ if ! elements.last.is_a?(:quote)
798
+ elements << element(:quote).cR
799
+ end
800
+ if line.content =~ /^\s*$/ #Empty line
801
+ elements.last << element(:newline).cR
802
+ else
803
+ elements.last << line.content
804
+ elements.last << ' '
805
+ end
806
+ when :indent
807
+ #~ puts "#{self.class}#wiki2doc(#{line.lineno}: indent: #{line.indent}\t#{line.add_info}\t#{line.content}"
808
+ #Check if the indent is part of a list item
809
+ if elements.last.is_a?(ListEnvironment)
810
+ lastlist = lists[lists.keys.max] #Get last (deepest) list
811
+ lastitem = lastlist.content.last
812
+
813
+ case lastitem.content.last
814
+ when nil #new paragraph
815
+ lastitem << element(:p, {}, self.inline(line.content, log)).cr
816
+ when Element #add content to last element
817
+ lastitem.content.last << self.inline(line.content, log)
818
+ else #add content to item line
819
+ lastitem << ' '
820
+ lastitem << self.inline(line.content, log)
821
+ end
822
+ elsif elements.last.is_a?(:dl)
823
+ lastitem << self.inline(line.content, log)
824
+ elsif ! elements.last.is_a?(:pre)
825
+ elements << element(:pre).cR
826
+ end
827
+ if elements.last.is_a?(:pre)
828
+ elements.last << (' ' * (line.indent - 1 )) + line.content + "\n"
829
+ end
830
+ when :tabular
831
+ if /longtable/ =~ line.content
832
+ elements << tab = element(:longtable, {:style=>CSS.new()}).CR
833
+ else
834
+ elements << tab = element(:tabular, {:style=>CSS.new()}).CR
835
+ end
836
+ if line.content #options
837
+ options = line.content.split('|')
838
+ options.each{|opt|
839
+ case opt
840
+ when /columndescription\s*=\s*(.*)/
841
+ tab[:columndescription] << $1 #TeX-Format
842
+ when /columns\s*=\s*(.*)/
843
+ tab[:columns] << $1.to_i
844
+ when /border\s*=\s*(.*)/
845
+ tab[:border] << $1.to_i
846
+ when /(.*)\s*=\s*(.*)/
847
+ #~ puts "#{__FILE__}##{__LINE__}: #{opt}" if ! tab[:style].content.first
848
+ tab[:style].content.first[$1] = $2
849
+ else
850
+ log.warn( "#{self.class}#wiki2doc(#{line.lineno}: options for table unknown: #{opt}" ) if log.warn?
851
+ end
852
+ }
853
+ end
854
+ #Add first row
855
+ elements.last << element(:tr, {} ).cr
856
+ when :tabular_end
857
+ elements << nil
858
+ when :tabular_row
859
+ if ! elements.last.is_a?(:tabular)
860
+ log.warn( "#{self.class}#wiki2doc(#{line.lineno}: Add row to non-tabular" ) if log.warn?
861
+ end
862
+ prev_row = elements.last.content.last
863
+ rowcss = CSS.new()
864
+ elements.last << element(:tr, { :style => rowcss } ).cr
865
+ if line.content #options
866
+ options = line.content.split('|')
867
+ #~ puts options.inspect
868
+ options.each{|opt|
869
+ case opt
870
+ when 'toprule'; prev_row.toprule
871
+ when 'midrule'; prev_row.midrule
872
+ when 'hline'; prev_row.hline
873
+ when /(.+)=(.+)/ #CSS?
874
+ rowcss[$1] = $2
875
+ when /\A\s*\Z/ #empty option
876
+ else
877
+ log.warn( "#{self.class}#wiki2doc(#{line.lineno}): Unknown line option #{opt.inspect}" ) if log.warn?
878
+ end
879
+ }
880
+ end
881
+ when :tabular_cell
882
+ cellcss = CSS.new()
883
+ colspan = 1
884
+ pos = 'c'
885
+ if line.add_info #options
886
+ #fixme: Tabelle mit verschiedenen Optionen??
887
+ options = line.add_info.split('|')
888
+ options.each{|opt|
889
+ case opt
890
+ when /colspan\s*=\s*(.*)/
891
+ colspan = $1.to_i
892
+ when /pos\s*=\s*(.*)/
893
+ pos = $1
894
+ when /(.*?)\s*=\s*(.*)/
895
+ cellcss[$1] = $2
896
+ else
897
+ log.warn( "options for table cell unknown: #{opt} (line #{line.lineno})" ) if log.warn?
898
+ end
899
+ }
900
+ end
901
+ row = elements.last.content.last
902
+ if colspan > 1
903
+ row << element(:multicolumn, { :colspan => colspan, :style => cellcss, :pos => pos }, line.content).cr
904
+ else
905
+ row << element(:td, { :style => cellcss }, line.content).cr
906
+ end
907
+ when :collector
908
+ #~ if line.content.respond_to? :to_doc
909
+ #~ elements << line.content.to_element
910
+ #~ else
911
+ elements << line.content
912
+ #~ end
913
+ else
914
+ log.error("#{self.class}#wiki2doc(#{line.lineno}): New line type #{line.type.inspect} (#{line.content.inspect})" ) if log.error?
915
+ elements << element( line.type,{},self.inline(line.content, log)).cr
916
+ end
917
+ }
918
+ return elements
919
+ end #wiki2doc
920
+ #Translate text for inline tags.
921
+ def inline( intext, log, subs = @wiki_inline_replacements )
922
+ return Wikitext.inline( intext, log, subs, self )
923
+ end
924
+ #Translate text for inline tags.
925
+ #
926
+ #This can also be used from "outside" to translate single lines.
927
+ #To keep the same environment if called via an object, the object is given in oo.
928
+ def self.inline( intext, log, subs = WIKI_INLINE_REPLACEMENTS,
929
+ oo = self)
930
+ subs.each{|rule|
931
+ if rule.regex =~ intext
932
+ if rule.proc.is_a?( Proc )
933
+ return rule.proc.call($~, oo, log)
934
+ else
935
+ return rule.proc
936
+ end
937
+ end
938
+ }
939
+ return intext
940
+ end
941
+ def toccss()
942
+ return <<wikitoc
943
+ <style type="text/css">
944
+ div.toc {
945
+ float: right;
946
+ width: 45%;
947
+ background: lightgray;
948
+ border: 2px solid;
949
+ }
950
+ div.toc ul li a {
951
+ font-size: xx-small;
952
+ font-weight: normal;
953
+ }
954
+ </style>
955
+ wikitoc
956
+ end
957
+ #Make a table of contents
958
+ #
959
+ #Options:
960
+ #- listtype: :ul or :ol
961
+ #- addlinks: Set label for each header.
962
+ def toc( i_options = {} )
963
+ options = {
964
+ :listtype => :ul,
965
+ :level => 4,
966
+ :startlevel => 1,
967
+ :addlinks => true
968
+ }.update(i_options)
969
+ uls = {}
970
+ uls[options[:startlevel]] = element(options[:listtype])
971
+ @source.flatten.each{|line|
972
+ if /\A(=+)(?:\[(.*?)\])?(.+?)(=+)\s*\z/ =~ line #:h1, :h2, :h3, :h4, :h5, :h6
973
+ level = $1.size.to_i - 1
974
+ anker = $2
975
+ titletext = $3
976
+ #Entfernen von Wiki-Links im Titel.
977
+ titletext.sub!(/\[\..*\s+(.*)\]/, '\1')
978
+
979
+ next if level > options[:level]
980
+ if level < options[:startlevel]
981
+ log.warn( "#{self.class}#toc: TOC starts at #{options[:startlevel]}, but level #{level} defined at #{line}" ) if log.warn?
982
+ next
983
+ end
984
+ if anker
985
+ titel = element(:a, {:href=>"##{anker}"}, titletext)
986
+ elsif options[:addlinks]
987
+ #Build label for toc
988
+ toclabel = []
989
+ 1.upto(level){|i|
990
+ if uls[i]
991
+ if i == level #same level - add one for actual element
992
+ toclabel << uls[i].content.size + 1
993
+ else #Previous level - use size
994
+ toclabel << uls[i].content.size
995
+ end
996
+ else #First element on this level
997
+ toclabel << 1
998
+ end
999
+ }
1000
+ #~ puts "toclabel <#{$3}>\t#{toclabel.inspect}\t#{toclabel.join('-')}"
1001
+ titel = element(:a, {:href=>"##{toclabel.join('-')}"}, titletext)
1002
+ line.sub!(/^(=+)/, "\\1[#{toclabel.join('-')}]")
1003
+ else
1004
+ titel = titletext
1005
+ end
1006
+ options[:startlevel].upto(6){|i|
1007
+ #Create 'higher' sections (indicates a problem in the text)
1008
+ if i < level
1009
+ if ! uls[i]
1010
+ log.warn( "#{self.class}#toc: Sectioning jumps over level #{i} at #{line}" ) if log.warn?
1011
+ uls[i-1].content.last << uls[i] = element(options[:listtype] ).Cr if uls[i-1]
1012
+ end
1013
+ if ! uls[i].content.last
1014
+ uls[i] << element(:li,{}, '' ).cr
1015
+ end
1016
+ elsif i == level
1017
+ #Create new level if necessary
1018
+ if ! uls[level]
1019
+ uls[level-1].content.last << uls[level] = element(options[:listtype] ).Cr
1020
+ end
1021
+ #Add section title
1022
+ uls[level] << element(:li,{}, titel ).cr
1023
+ else
1024
+ #delete lower levels of previous topic
1025
+ uls[i] = nil
1026
+ end
1027
+ }
1028
+ end
1029
+ }
1030
+ return element(:div, { :class => 'toc' }, uls[options[:startlevel]] ).CR
1031
+ end
1032
+ def footnotes()
1033
+ footnotes = Footnotegroup.get( self.object_id)
1034
+ return footnotes
1035
+ end
1036
+ end
1037
+
1038
+ #Wiki-Collector is a hash with collectors.
1039
+ #
1040
+ #A WikiCollector give you the possibility to define
1041
+ #'customized exits' in the wiki code.
1042
+ #
1043
+ #Usage example: see code2structogramm
1044
+ class WikiCollector
1045
+ @@variants = {}
1046
+ #Add a new collector type.
1047
+ #
1048
+ #Each collector must implement the following methods:
1049
+ #-new without parameters.
1050
+ #-<< get lines of wiki-source
1051
+ #-to_doc return the result
1052
+ #See the two examples
1053
+ #- WikiCollectorHTML
1054
+ #- WikiCollectorFilecontent
1055
+ #
1056
+ def self.add(key, classtype)
1057
+ if @@variants[key]
1058
+ puts "WikiCollector: Double assignment #{key.inspect}, #{classtype}"
1059
+ end
1060
+ if ! classtype.method_defined?(:'<<')
1061
+ puts "WikiCollector: Collector <#{key.inspect}> doesn't support <<"
1062
+ return false
1063
+ end
1064
+ if ! classtype.method_defined?(:to_doc)
1065
+ puts "WikiCollector: Collector <#{key.inspect}> doesn't support to_doc"
1066
+ return false
1067
+ end
1068
+ @@variants[key] = classtype
1069
+ end
1070
+ #Get an instance of the requested collector.
1071
+ def self.create(key, arguments = [] )
1072
+ #~ puts "WikiCollector: request #{key.inspect}"
1073
+ if @@variants[key.to_sym]
1074
+ begin
1075
+ return @@variants[key.to_sym].new(*arguments)
1076
+ rescue ArgumentError
1077
+ puts "WikiCollector: Collector <#{key.inspect}> get wrong parameters"
1078
+ return false
1079
+ end
1080
+ else
1081
+ puts "WikiCollector: Collector <#{key}> not found (available: #{@@variants.keys.inspect})"
1082
+ return nil
1083
+ end
1084
+ end
1085
+ end #WikiCollector
1086
+ #
1087
+ #A little collector of "Plain-HTML".
1088
+ #
1089
+ class WikiCollectorHTML < Element
1090
+ Element.add( [:wikicollectorhtml], WikiCollectorHTML)
1091
+ #Start without parameters.
1092
+ #Can be called in a Wiki with:
1093
+ # >>>html{}
1094
+ # here you can add plain HTML
1095
+ # <<<
1096
+ def initialize()
1097
+ @htmlcode = []
1098
+ end
1099
+ #Add another line from Wiki
1100
+ def <<(content)
1101
+ @htmlcode << content
1102
+ end
1103
+ #
1104
+ #Return the content 'as is', but only for HTML
1105
+ def to_doc( target, options = {} )
1106
+ case target
1107
+ when :html
1108
+ @htmlcode.join("\n")
1109
+ else
1110
+ ''
1111
+ end
1112
+ #~ return element(:onlyhtml,{},@htmlcode).restrict_to(:html).to_doc(target)
1113
+ end
1114
+ #~ def to_html()
1115
+ #~ return @htmlcode
1116
+ #~ end
1117
+ #~ def to_latex(); ''; end
1118
+ #~ def to_wiki(); ''; end
1119
+ #~ def to_text(); ''; end
1120
+ end
1121
+ WikiCollector.add(:html, WikiCollectorHTML )
1122
+
1123
+ if __FILE__ == $0
1124
+ puts 'Use the unit test for complete test'
1125
+
1126
+ wiki = Wikitext.new(:content => <<wiki
1127
+ There are normal footnotes{{footnote|Like this one}}. But:
1128
+ Here is a footnote in group 1{{footnote[group1]some remarks}}, and
1129
+ a second footnote{{footnote[group1]more remarks}}.
1130
+ In another group{{footnote[group2]Each group gets a name}}, we can define further remarks.
1131
+
1132
+ ----
1133
+ Normal Footnotes:
1134
+ {{footnotes}}
1135
+ ----
1136
+ Footnote group 1:
1137
+ {{footnotes|group1}}
1138
+ ----
1139
+ Footnote group 2:
1140
+ {{footnotes|group2}}
1141
+ wiki
1142
+ )
1143
+ puts '---------------------'
1144
+
1145
+ #~ puts wiki.toc.inspect
1146
+ #~ puts wiki.toc.to_html
1147
+ #~ puts wiki.toc.to_wiki
1148
+ #~ puts '--------HTML-------------'
1149
+ #~ puts wiki.to_html
1150
+ #~ puts '--------HTML-------------'
1151
+ #~ puts wiki.to_html
1152
+ #~ puts '--------LaTeX-------------'
1153
+ #~ puts wiki.to_latex
1154
+ #~ puts '--------Wiki-------------'
1155
+ #~ puts wiki.to_wiki
1156
+ #~ puts '--------Text-------------'
1157
+ #~ puts wiki.to_text
1158
+ end
1159
+
1160
+
1161
+ __END__