docgenerator 0.1.1 → 1.0.2

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 (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__