docgenerator 1.1.1 → 1.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (179) hide show
  1. data/examples/docgenerator_example.rb +34 -17
  2. data/examples/docgenerator_example_footnote.rb +82 -61
  3. data/examples/docgenerator_example_list.rb +24 -18
  4. data/examples/docgenerator_example_restrictions.rb +17 -27
  5. data/examples/docgenerator_example_tabular.rb +20 -20
  6. data/examples/docgenerator_example_tripfalls.rb +28 -20
  7. data/examples/results/readme +1 -0
  8. data/examples/results_expected/docgenerator_example.html +39 -0
  9. data/examples/results_expected/docgenerator_example.pdf +0 -0
  10. data/examples/results_expected/docgenerator_example.tex +56 -0
  11. data/examples/results_expected/docgenerator_example_footnote.html +40 -0
  12. data/examples/results_expected/docgenerator_example_footnote.pdf +0 -0
  13. data/examples/results_expected/docgenerator_example_footnote.tex +50 -0
  14. data/examples/results_expected/docgenerator_example_list.html +18 -0
  15. data/examples/results_expected/docgenerator_example_list.pdf +0 -0
  16. data/examples/results_expected/docgenerator_example_list.tex +46 -0
  17. data/examples/results_expected/docgenerator_example_restrictions.html +22 -0
  18. data/examples/results_expected/docgenerator_example_restrictions.pdf +0 -0
  19. data/examples/results_expected/docgenerator_example_restrictions.tex +31 -0
  20. data/examples/results_expected/docgenerator_example_tabular.html +37 -0
  21. data/examples/results_expected/docgenerator_example_tabular.pdf +0 -0
  22. data/examples/results_expected/docgenerator_example_tabular.tex +41 -0
  23. data/examples/results_expected/docgenerator_example_tripfalls.html +27 -0
  24. data/examples/results_expected/docgenerator_example_tripfalls.pdf +0 -0
  25. data/examples/results_expected/docgenerator_example_tripfalls.tex +31 -0
  26. data/lib/creole/creole2doc.rb +291 -140
  27. data/lib/creole/creole_inclusion_and_plugins.rb +142 -39
  28. data/lib/creole/creole_placeholder.rb +92 -30
  29. data/lib/creole/creole_tabular.rb +119 -20
  30. data/lib/docgenerator.rb +209 -118
  31. data/lib/{docgenerator_attribute.rb → docgenerator/attribute.rb} +2 -1
  32. data/lib/{docgenerator_characters.rb → docgenerator/characters.rb} +75 -6
  33. data/lib/{docgenerator_css.rb → docgenerator/css.rb} +0 -0
  34. data/lib/docgenerator/document.rb +588 -0
  35. data/lib/{docgenerator_element.rb → docgenerator/element.rb} +52 -80
  36. data/lib/{docgenerator_elements.rb → docgenerator/elements.rb} +43 -17
  37. data/lib/{docgenerator_environments.rb → docgenerator/environments.rb} +20 -6
  38. data/lib/{docgenerator_footnote.rb → docgenerator/footnote.rb} +22 -18
  39. data/lib/{docgenerator_lists.rb → docgenerator/lists.rb} +17 -1
  40. data/lib/{docgenerator_sections.rb → docgenerator/sections.rb} +9 -1
  41. data/lib/docgenerator/standard.rb +81 -0
  42. data/lib/{docgenerator_tabular.rb → docgenerator/tabular.rb} +9 -5
  43. data/lib/packages/docgenerator_listings.rb +9 -5
  44. data/lib/packages/docgenerator_pdfpages.rb +17 -11
  45. data/lib/packages/docgenerator_url.rb +0 -2
  46. data/lib/templates/docgenerator_template.rb +66 -29
  47. data/lib/templates/docgenerator_template.yaml +18 -0
  48. data/lib/wiki2doc/wiki2docgenerator.rb +6 -2
  49. data/readme.rd +132 -0
  50. data/unittest/expected/test_document_usepackage_undefined.log +2 -0
  51. data/unittest/expected/test_enumerate.context +4 -0
  52. data/unittest/expected/test_footnote.html +4 -4
  53. data/unittest/expected/test_footnote.latex +4 -4
  54. data/unittest/expected/test_footnote_group.html +6 -6
  55. data/unittest/expected/test_footnote_group.latex +6 -6
  56. data/unittest/expected/test_href.html +2 -2
  57. data/unittest/expected/test_href.latex +2 -2
  58. data/unittest/expected/test_href.text +2 -2
  59. data/unittest/expected/test_itemize.context +4 -0
  60. data/unittest/expected/test_runtex.stdout +3 -0
  61. data/unittest/expected/test_runtex_2.stdout +3 -0
  62. data/unittest/expected/test_section.context +20 -0
  63. data/unittest/expected/test_tabular.html +2 -2
  64. data/unittest/expected/test_verbatim.html +3 -0
  65. data/unittest/expected/test_verbatim.latex +4 -0
  66. data/unittest/expected/test_verbatim_array.html +1 -0
  67. data/unittest/expected/test_verbatim_array.latex +2 -0
  68. data/unittest/expected_creole/test_creole_characters_all.html +12 -5
  69. data/unittest/expected_creole/test_creole_characters_all.latex +20 -6
  70. data/unittest/expected_creole/test_creole_comment.context +11 -0
  71. data/unittest/expected_creole/test_creole_comment.creole +12 -0
  72. data/unittest/expected_creole/test_creole_comment.html +9 -0
  73. data/unittest/expected_creole/test_creole_comment.latex +11 -0
  74. data/unittest/expected_creole/test_creole_creole1.0test.html +3 -3
  75. data/unittest/expected_creole/test_creole_creole1.0test.latex +3 -3
  76. data/unittest/expected_creole/test_creole_creole1.0test.text +4 -4
  77. data/unittest/expected_creole/test_creole_ignore.html +3 -0
  78. data/unittest/expected_creole/test_creole_ignore.latex +4 -0
  79. data/unittest/expected_creole/test_creole_ignore.text +2 -0
  80. data/unittest/expected_creole/test_creole_input.normsource +12 -12
  81. data/unittest/expected_creole/test_creole_input_file_simple.html +15 -0
  82. data/unittest/expected_creole/test_creole_input_file_simple_readlines.html +15 -0
  83. data/unittest/expected_creole/test_creole_links_external_implicit.html +2 -2
  84. data/unittest/expected_creole/test_creole_links_external_implicit.latex +2 -2
  85. data/unittest/expected_creole/test_creole_links_external_implicit.text +2 -2
  86. data/unittest/expected_creole/test_creole_links_implicit_end.creole +4 -0
  87. data/unittest/expected_creole/test_creole_links_implicit_end.html +3 -0
  88. data/unittest/expected_creole/test_creole_links_implicit_end.latex +4 -0
  89. data/unittest/expected_creole/test_creole_list_ul.normsource +42 -42
  90. data/unittest/expected_creole/test_creole_mix_titles_list.html +10 -0
  91. data/unittest/expected_creole/test_creole_mix_titles_list.latex +18 -0
  92. data/unittest/expected_creole/test_creole_mix_titles_list.text +12 -0
  93. data/unittest/expected_creole/test_creole_paragraphs.normsource +15 -15
  94. data/unittest/expected_creole/test_creole_pictures_css.html +4 -1
  95. data/unittest/expected_creole/test_creole_pictures_css.latex +5 -1
  96. data/unittest/expected_creole/test_creole_pictures_longdesc.html +3 -0
  97. data/unittest/expected_creole/test_creole_pictures_width.html +3 -0
  98. data/unittest/expected_creole/test_creole_pictures_width.latex +4 -0
  99. data/unittest/expected_creole/test_creole_short_html.html +3 -0
  100. data/unittest/expected_creole/test_creole_short_html.latex +4 -0
  101. data/unittest/expected_creole/test_creole_short_html.text +2 -0
  102. data/unittest/expected_creole/test_creole_shy.creole +6 -0
  103. data/unittest/expected_creole/test_creole_shy.html +6 -0
  104. data/unittest/expected_creole/test_creole_shy.latex +8 -0
  105. data/unittest/expected_creole/test_creole_shy.text +4 -0
  106. data/unittest/expected_creole/test_creole_tabular_with_cell_option.html +20 -0
  107. data/unittest/expected_creole/test_creole_toc.html +3 -1
  108. data/unittest/expected_creole/test_creole_toc.latex +1 -1
  109. data/unittest/expected_creole/test_creole_toc.text +1 -1
  110. data/unittest/expected_creole/test_creole_toc_level.html +7 -0
  111. data/unittest/expected_creole/test_creole_toc_level.latex +10 -0
  112. data/unittest/expected_creole/test_creole_toc_level.text +3 -0
  113. data/unittest/expected_creole/test_creole_toc_level_text.html +8 -0
  114. data/unittest/expected_creole/test_creole_toc_level_text.latex +9 -0
  115. data/unittest/expected_creole/test_creole_verbatim.html +1 -1
  116. data/unittest/expected_creole/test_creole_verbatim.latex +1 -1
  117. data/unittest/expected_creole/test_creole_verbatim.text +1 -1
  118. data/unittest/expected_creole/test_creole_verbatim_inline.html +1 -1
  119. data/unittest/expected_creole/test_creole_verbatim_inline.latex +1 -1
  120. data/unittest/expected_wiki/test_wiki_description.html +5 -5
  121. data/unittest/expected_wiki/test_wiki_description.latex +5 -5
  122. data/unittest/expected_wiki/test_wiki_description.text +5 -5
  123. data/unittest/expected_wiki/test_wiki_description.wiki +5 -5
  124. data/unittest/test_rakefile_docgenerator.rb +43 -0
  125. data/unittest/unittest_creole2doc.rb +415 -27
  126. data/unittest/unittest_docgenerator.rb +256 -23
  127. data/unittest/unittest_docgenerator_runtex.rb +83 -0
  128. data/unittest/unittest_versions.rb +44 -0
  129. data/unittest/unittest_wiki2doc.rb +28 -27
  130. metadata +473 -106
  131. data/lib/docgenerator_document.rb +0 -525
  132. data/lib/packages/docgenerator_beamer.rb +0 -253
  133. data/lib/yaml2presentation/yaml2presentation.rb +0 -1091
  134. data/unittest/expected/beamer_01_article.tex +0 -13
  135. data/unittest/expected/beamer_01_attachment.tex +0 -15
  136. data/unittest/expected/beamer_01_doc.html +0 -13
  137. data/unittest/expected/beamer_01_doc.tex +0 -18
  138. data/unittest/expected/beamer_01_notes_only.tex +0 -13
  139. data/unittest/expected/beamer_01_notes_onlyslideswithnotes.tex +0 -13
  140. data/unittest/expected/beamer_01_notes_show.tex +0 -13
  141. data/unittest/expected/beamer_01_presentation.tex +0 -13
  142. data/unittest/expected/beamer_02_doc.html +0 -29
  143. data/unittest/expected/beamer_02_doc.tex +0 -34
  144. data/unittest/expected/beamer_block.html +0 -1
  145. data/unittest/expected/beamer_block.latex +0 -1
  146. data/unittest/expected/beamer_doc_fragile_doc.tex +0 -33
  147. data/unittest/expected/beamer_doc_html_overview_with_detailpic_and_text_doc.html +0 -34
  148. data/unittest/expected/beamer_doc_html_overview_with_detailpic_doc.html +0 -34
  149. data/unittest/expected/beamer_doc_key_doc.html +0 -20
  150. data/unittest/expected/beamer_doc_key_doc.tex +0 -29
  151. data/unittest/expected/beamer_doc_note_doc.html +0 -30
  152. data/unittest/expected/beamer_doc_note_doc.tex +0 -37
  153. data/unittest/expected/beamer_doc_pic_bottom_doc.html +0 -24
  154. data/unittest/expected/beamer_doc_pic_doc.html +0 -24
  155. data/unittest/expected/beamer_doc_pic_doc.tex +0 -28
  156. data/unittest/expected/beamer_doc_pic_left_doc.html +0 -24
  157. data/unittest/expected/beamer_doc_pic_left_doc.tex +0 -28
  158. data/unittest/expected/beamer_doc_pic_ratio_doc.tex +0 -29
  159. data/unittest/expected/beamer_doc_pic_right_doc.html +0 -24
  160. data/unittest/expected/beamer_doc_pic_right_doc.tex +0 -28
  161. data/unittest/expected/beamer_doc_pic_top_doc.html +0 -24
  162. data/unittest/expected/beamer_frame.html +0 -5
  163. data/unittest/expected/beamer_frame.tex +0 -11
  164. data/unittest/expected/beamer_frame_fragile.tex +0 -7
  165. data/unittest/expected/beamer_frame_id.html +0 -1
  166. data/unittest/expected/beamer_frame_id.tex +0 -4
  167. data/unittest/expected/beamer_framepic.html +0 -5
  168. data/unittest/expected/beamer_framepic.latex +0 -1
  169. data/unittest/expected/beamer_framepic_link.html +0 -5
  170. data/unittest/expected/beamer_framepic_link.latex +0 -1
  171. data/unittest/expected/beamer_frametitle.html +0 -1
  172. data/unittest/expected/beamer_frametitle.latex +0 -1
  173. data/unittest/expected/beamer_note.html +0 -1
  174. data/unittest/expected/beamer_note.latex +0 -1
  175. data/unittest/expected_privat/test_creole_test_document.html +0 -6
  176. data/unittest/expected_wiki/test_wiki_amazon.html +0 -10
  177. data/unittest/expected_wiki/test_wiki_link.log +0 -3
  178. data/unittest/test_docgenerator.rb +0 -107
  179. data/unittest/unittest_yaml2pres.rb +0 -336
File without changes
@@ -0,0 +1,588 @@
1
+ #encoding: utf-8
2
+ =begin rdoc
3
+ Container for a document.
4
+
5
+ Each document contains a header and a body. Both are special Element classes.
6
+ =end
7
+ class Document
8
+ include Docgenerator #get VERSION
9
+
10
+ #Valid meta tags, used for HTML
11
+ #
12
+ #This meta-tags are used by sitegenerator
13
+ VALID_META_TAGS = %w{
14
+ keywords
15
+ description
16
+ id
17
+ altlang
18
+ toc
19
+ pdf
20
+ odp
21
+ amazon
22
+ forum
23
+ feed
24
+ }
25
+ class << VALID_META_TAGS
26
+ # Return true if self is part of the given parameter.
27
+ def ===(o)
28
+ return self.include?(o)
29
+ end
30
+ end
31
+
32
+ #Create a new document.
33
+ #There are different document templates supported.
34
+ #The templates refer to the corresponding TeX-classes.
35
+ #- article
36
+ #- report
37
+ #- book
38
+ def initialize( settings = {} )
39
+ #Set template defaults
40
+ @template = {
41
+ :html => DocumentTemplate[:html],
42
+ :latex => DocumentTemplate[:article],
43
+ :text => DocumentTemplate[:text],
44
+ :wiki => DocumentTemplate[:wiki],
45
+ }
46
+ @language = 'ngerman' #default
47
+ @date = nil
48
+
49
+ ##>>>>temporary check, old interface
50
+ #~ puts settings.inspect
51
+ if ! settings.is_a?(Hash)
52
+ #Make an exception to correct data
53
+ raise "Old interface for Document#new, use :template => "
54
+ settings = { :template => settings }
55
+ end
56
+ ##<<<<temporary check, old interface
57
+
58
+ @log = settings[:log]
59
+ if ! @log
60
+ @log = Log4r::Logger.new( 'Doc', Log4r::WARN )
61
+ @log.outputters = Log4r::StdoutOutputter.new('log_xxx')
62
+ end
63
+ @meta = {} #some meta-Tags for HTML
64
+ @body = element( :body, { :log => @log } )
65
+ @head = element( :head, { :log => @log } )
66
+ #~ @body.part_of << self
67
+ #~ @head.part_of << self
68
+ @options = []
69
+ #Flag to avoid double definition of docinfo()
70
+ @docinfo_called = false
71
+ @creator = nil
72
+
73
+ settings.each{|key, value|
74
+ case key
75
+ when :title, :shorttitle, :author, :date, :keywords, :description, :creator, :language
76
+ self.send("#{key}=".to_sym, value)
77
+ #~ when :odp, :pdf, :amazon #VALID_META_TAGS
78
+ when *VALID_META_TAGS.map{|mkey|mkey.to_sym}
79
+ self.meta( key, value )
80
+ when :template
81
+ [value].flatten.each{|template|
82
+ case template
83
+ when DocumentTemplate
84
+ @template[template.target] = template
85
+ when Symbol
86
+ templ = DocumentTemplate[template]
87
+ if ! templ.is_a?( DocumentTemplate )
88
+ @log.fatal("Unknown template #{template}, valid:\n\t#{DocumentTemplate.keys.join("\n\t")}") if @log.fatal?
89
+ else
90
+ @template[templ.target] = templ
91
+ end
92
+ end
93
+ } #templates
94
+ when :css
95
+ if ! File.exist?(value)
96
+ @log.warn("CSS-Reference not found (#{value})") if @log.warn?
97
+ end
98
+ #~ @head << element(:htmlonly,{}, <<css
99
+ #~ <meta http-equiv="Content-Style-Type" content="text/css">
100
+ #~ css
101
+ #~ <link rel="stylesheet" type="text/css" href="#{value}">
102
+ #~ ).cr
103
+ @head << element( :link, {
104
+ :href => value,
105
+ :rel => 'stylesheet',
106
+ :type => "text/css" } ).cr. restrict_to(:html)
107
+ when :maketitle
108
+ #:maketitle is defined, but we have also to check, if it is true
109
+ @body << element(:maketitle ).cr if settings[key]
110
+ when :log
111
+ else
112
+ @log.warn("Document.new: Unknown setting #{key.inspect} (=#{value.inspect})") if @log.warn?
113
+ end
114
+ } #settings
115
+
116
+ end
117
+ #body and head are lists, containing elements.
118
+ attr_reader :body, :head
119
+ attr_reader :template
120
+ #Logger for the document
121
+ attr_reader :log
122
+ #Document title
123
+ attr_accessor :title, :shorttitle
124
+ #Set document description
125
+ attr_writer :author, :date, :keywords, :description, :creator
126
+ attr_writer :language
127
+ #Flag, if tex should be started immediate after document creation.
128
+ attr_writer :runtex
129
+ #Add more keywords
130
+ def keyword_add( keyword )
131
+ @keywords << ", #{keyword}"
132
+ end
133
+
134
+ #Constant to detect the generated header
135
+ PREFIX_ENDFLAG = 'Generation-Info-End'
136
+ #
137
+ #Define, if there should be a message in case of:
138
+ #-:change Document changed
139
+ #-:nochange Document existed, but is unchanged
140
+ #Give an array with the wanted values.
141
+ def Document.givemessage=( value = [:change, :nochange] )
142
+ @@givemessage = value
143
+ end
144
+ @@givemessage = [:change, :nochange]
145
+ def Document.givemessage(); @@givemessage; end
146
+ #Add a meta-tag-information for the HTML-Output.
147
+ def meta( key, content )
148
+ key = key.to_s
149
+
150
+ if ! VALID_META_TAGS.include?(key)
151
+ @log.warn("Unknown meta-tag #{key} (#{content})") if @log.warn?
152
+ @log.info("\tAllowed meta-tags: #{VALID_META_TAGS.join(', ')}") if @log.info?
153
+ end
154
+ if @meta[key]
155
+ @log.warn("Double definition meta-tag #{key} (old: #{@meta[key]}, new: #{content})") if @log.warn? and @meta[key] != content
156
+ end
157
+
158
+ @meta[key] = content
159
+ end
160
+ #Prepare the docinfo.
161
+ #May be called only once.
162
+ #
163
+ #If the title should change (e.g. when you save the document twice in different versions)
164
+ #you can do it via the parameter.
165
+ def docinfo()
166
+ #If this method is called twice (e.g. with save to tex and html),
167
+ #then the title is doubled in the second output.
168
+ #(Elements are added to @head)
169
+ return nil if @docinfo_called
170
+ @docinfo_called = true
171
+
172
+ #Build docinfo.
173
+ result = []
174
+ result << element( :title, {:short => shorttitle }, @title).CR if @title
175
+ result << element( :author, {}, @author).cr if @author
176
+ result << element( :date, {}, @date).cr if @date
177
+ result << element( :keywords, {}, @keywords).cr if @keywords
178
+ result << element( :metadescription, {}, @description).cr if @description
179
+ result << element( :creator, {}, @creator).cr if @creator
180
+ @meta.each{ |key, content|
181
+ result << element( :meta, { :name => key, :content => content } ).cr
182
+ }
183
+ return result
184
+ end
185
+ def add_option( option)
186
+ @options << option
187
+ end
188
+ #Prepare a table of content.
189
+ #
190
+ #There is no sense to use it with LaTeX, better you use \tableofcontents
191
+ #
192
+ #Options:
193
+ #- id: Id of div, needed for CSS-formatting
194
+ #- tocfilename: Added as prefix to link.
195
+ # can be used to make toc for in another file (cross-referencing)
196
+ #- level: Depth of toc
197
+ #The document should be filled before you add the toc.
198
+ #You an use Element#insertbefore:
199
+ # doc.body.insertbefore(start, doc.toc)
200
+ def toc( options = {} )
201
+ opt = {
202
+ :id => 'toc',
203
+ :tocfilename => nil, #Can be used to build cross references
204
+ :level => 3,
205
+ :log => @log
206
+ }.update(options)
207
+
208
+ opt[:level] = 3 unless opt[:level]
209
+ opt[:log].info("Prepare Table of contents, options: #{options.keys.inspect}") if opt[:log].info?
210
+ opt[:log].debug("Options: #{[:id, :level, :tocfilename].map{|k| "#{k}: #{opt[k].inspect}"}.join(',')}") if opt[:log].debug?
211
+
212
+ toc = element(:div, { :id => opt[:id] }).cR
213
+ opt[:pre].is_a?(String) ? toc << element(:p, {}, opt[:pre] ).cr : toc << opt[:pre]
214
+
215
+ toc_uls = [ toc ]
216
+
217
+ #fixme
218
+ #It would be nicer to get something like 1-1-1 instead of a counter.
219
+ toccnt = 0
220
+ toc_ids = [ :chapter, :section,:subsection, :subsubsection, :paragraph, :subparagraph,:minisec]
221
+ @body.content.flatten.each{|el|
222
+ if ! el.respond_to?(:ids)
223
+ #e.g. Wikitext. Has a to_doc, but doesn't react on flatten.
224
+ opt[:log].error("Toc: Element ohne :ids #{el.class}") if opt[:log].error?
225
+ next
226
+ end
227
+ depth = toc_ids.index((el.ids & toc_ids)[0])
228
+ next if ! depth #Element is no header
229
+
230
+ opt[:log].debug("Toc: Found entry on level #{depth}: <#{el.content}>") if opt[:log].debug?
231
+ #Create an id if not already defined
232
+ if el[:id].content.empty?
233
+ el[:id] << "toc#{toccnt += 1}"
234
+ end
235
+ if depth > opt[:level]
236
+ opt[:log].debug("Toc: Reject by level #{el.content}") if opt[:log].debug?
237
+ next
238
+ end
239
+
240
+ #Check missing levels
241
+ (depth - toc_uls.size).times{|i|
242
+ opt[:log].warn("Toc: Jump over section level #{depth-1+i} (#{opt[:tocfilename]})") if opt[:log].warn?
243
+ toc_uls << element(:ul, {}, element(:li ).cr ).cR
244
+ if toc_uls.size == 2 #First entry
245
+ toc_uls.first << toc_uls.last
246
+ else
247
+ toc_uls[-2].content.last << toc_uls.last
248
+ end
249
+ }
250
+
251
+ #Build new toc-list and deletet bigger ones
252
+ if ! toc_uls[depth]
253
+ opt[:log].debug("Toc: Start new level #{depth}") if opt[:log].debug?
254
+ toc_uls << element(:ul).cR
255
+ if depth == 1
256
+ toc << toc_uls[depth]
257
+ else
258
+ toc_uls[depth -1 ].content.last << toc_uls[depth]
259
+ end
260
+ else #delete levels under actual level
261
+ if toc_uls.slice!(depth+1..toc_uls.size+1)
262
+ opt[:log].debug("Toc: Stop level > #{depth}") if opt[:log].debug?
263
+ end
264
+ end
265
+ toc_uls[depth] << element(:li, {}, element(:a, {:href => "#{opt[:tocfilename]}##{el[:id]}" }, el.content ) ).cr
266
+ }
267
+ opt[:post].is_a?(String) ? toc << element(:p, {}, opt[:post] ).cr : toc << opt[:post]
268
+
269
+ return toc
270
+ end #toc
271
+ =begin rdoc
272
+ Save the file.
273
+ The type of the document is determined by the file extensison.
274
+ Supported document types are:
275
+ - tex
276
+ - html
277
+ - (wiki)
278
+ - (text)
279
+ Depending on a template, different results are created.
280
+
281
+ There is a comparison between an already existing file and the new one.
282
+ To write a new version, the document must change and overwrite must be true.
283
+
284
+ Valid options:
285
+ - :replacements
286
+ It is possible to give pairs of RegExp (pattern) and replacements to the result.
287
+ - overwrite [true]
288
+ allows to overwrite
289
+ - target
290
+ In most cases this is defined by the extension.
291
+ Main usage will be for ConTeXt (shares the extension with LaTeX)
292
+ - :additional_options
293
+ List of options.
294
+ If you want to give parameters to specific 'Element'-objects you can define the keys here.
295
+ If you don't make it, you get warnings about undefined options.
296
+ =end
297
+ def save( filename, options = {} )
298
+ #check old interface before 1.1.0
299
+ case options
300
+ when true, false
301
+ @log.warn( "Old interface for Document.save, use :overwrite => true/false" ) if @log.error?
302
+ options = { :overwrite => options }
303
+ end
304
+
305
+ options = {
306
+ :overwrite => true,
307
+ :replacements => {} ,
308
+ :additional_options => [],
309
+ :target => nil, #Will be set by extension
310
+ :runtex => @runtex,
311
+ }.update(options)
312
+
313
+ #Check valid options
314
+ options.each{|key,value|
315
+ case key
316
+ when :overwrite, :replacements, :target
317
+ when :additional_options
318
+ else
319
+ if options[:additional_options].include?(key)
320
+ @log.warn( "unknown option #{key.inspect} for Document.save" ) if @log.warn?
321
+ else
322
+ @log.debug( "Save-Specific option #{key.inspect} in Document.save" ) if @log.debug?
323
+ end
324
+ end
325
+ }
326
+
327
+ if ! @template
328
+ @log.error( "No template available to create #{filename}" ) if @log.error?
329
+ return false
330
+ end
331
+
332
+ prefix = [ nil,
333
+ "Build by\t#{__FILE__}",
334
+ "Dir:\t\t#{Dir.pwd}",
335
+ "Creator:\t#{$0}",
336
+ "Target:\t\t#{filename}",
337
+ "#{Time.now.strftime('%Y/%m/%d %H:%M:%S')}",
338
+ nil,
339
+ "#{PREFIX_ENDFLAG}"
340
+ ].join("\n\t")
341
+
342
+ #Determine the target document type, depending on extension.
343
+ extension = File.basename( filename ).split( /\./).last
344
+ case extension
345
+ when /tex/i
346
+ target = :latex
347
+ #Take context if requested.
348
+ target = :context if options[:target] == :context
349
+ when /miv/i #Mark IV
350
+ target = :context
351
+ when /htm[l]?/i
352
+ target = :html
353
+ when /txt/
354
+ target = :text
355
+ when /wiki/
356
+ target = :wiki
357
+ target = :creole if options[:target] == :creole
358
+ when /creole/
359
+ target = :creole
360
+ else
361
+ @log.fatal( "Unknown Extension #{extension} for #{File.basename( filename )}" ) if @log.fatal?
362
+ raise "Unknown Extension #{extension}"
363
+ end
364
+
365
+ #Check if the wanted target makes sense
366
+ case options[:target]
367
+ when nil #nothing predefined -> no check necessary
368
+ when target #Same as determined by extension -> no check necessary
369
+ else #Requested target is another one.
370
+ @log.warn( "Target #{options[:target]} doesn't match extension. Recommended: #{target}" ) if @log.warn?
371
+ target = options[:target]
372
+ end
373
+
374
+ #Create new version.
375
+ new = to_doc( target, {
376
+ :template=> @template[target],
377
+ :filename => filename,
378
+ :replacements => options[:replacements],
379
+ :log => @log
380
+ })
381
+ #Get previous content if available
382
+ old = nil
383
+ if File.exist?( filename )
384
+ #read the file. We expect to have the same encoding.
385
+ File.open(filename, 'r', :external_encoding => new.encoding){|f| old = f.read }
386
+ old = File.read(filename) unless old.valid_encoding? #
387
+ end
388
+ prefix.encode!(new.encoding) #for later sub...
389
+ case target
390
+ when :latex, :context
391
+ prefix.gsub!( /^/, '%' )
392
+ old.sub!(/\A.*#{PREFIX_ENDFLAG}/m, '<<prefix>>' ) if old
393
+ when :html
394
+ #Delete prefix (with generation time) for later compare.
395
+ old.sub!(/\A.*#{PREFIX_ENDFLAG}/m, "<!--\n<<prefix>>" ) if old
396
+ when :text
397
+ when :wiki
398
+ when :creole
399
+ #~ new.squeeze!("\n")
400
+ else
401
+ @log.fatal( "Unknown target #{target} for #{File.basename( filename )}" ) if @log.fatal?
402
+ raise "Unknown target #{target}"
403
+ end
404
+ #Make it a bit more compact.
405
+ #TeX requires at least 2 \n for paragraph changes
406
+ new.gsub!(/\n+\n\n/, "\n\n")
407
+
408
+ if ! new.kind_of?( String )
409
+ @log.error( "New is wrong type: #{new.inspect}" ) if @log.error?
410
+ end
411
+
412
+ if new != old
413
+ new.sub!( '<<prefix>>', prefix)
414
+ if ( File.exist?( filename ) and ! options[:overwrite] )
415
+ puts "Datei #{filename} exist already \nContinue [yn]?"
416
+ answer = $stdin.gets() if $stdin.tty? #only when called in a shell
417
+ if ! ( answer =~ /[YyjJ].*/ )
418
+ puts "Bye"
419
+ @log.info( "Overwrite #{filename} after confirmation" ) if @log.info?
420
+ return false
421
+ end
422
+ end
423
+ File.open( filename, 'w', :external_encoding => new.encoding ){|f|
424
+ f << new
425
+ }
426
+ @log.info( "Save changed\t#{filename}") if @log.info?
427
+ puts "Save changed\t#{filename}" if @@givemessage.include?(:change)
428
+ #Save copy of old version (attention, *.bak makes no control on tex or html)
429
+ #~ f = File.new( filename.sub( extension, 'bak'), 'w' )
430
+ #~ f << old
431
+ #~ f.close
432
+ Document.runtex( filename, options[:runtex] ) if options[:runtex] and [:latex, :context].include?(target)
433
+ return true
434
+ elsif old
435
+ @log.info("Unchanged\t#{filename}") if @log.info?
436
+ puts "Unchanged\t#{filename}" if @@givemessage.include?(:nochange)
437
+ return false
438
+ end
439
+ end #Document#save
440
+ =begin rdoc
441
+ Build the content for the target format.
442
+ Supported target formats are:
443
+ - :latex
444
+ - :html
445
+ - :text
446
+ If the standard templates are used, there is a <<prefix>> left
447
+ (used from Document#save to include some additional information).
448
+
449
+ If the method is called directly to prepare document snipplets, you can use:
450
+ puts Document#to_doc( :latex, '<<body>>')
451
+
452
+ It is possible to give pairs of RegExp (pattern) and a replacement to the result.
453
+ =end
454
+ def to_doc( target, options )
455
+ #~ o = Docgenerator_logger.set_option_defaults(options)
456
+ options[:log].info( "Build document for #{target.inspect}" ) if options[:log].info?
457
+ template = options[:template]
458
+ if ! template
459
+ options[:log].error( "No template available to create #{target.inspect} #{self.class}" ) if options[:log].error?
460
+ return ''
461
+ end
462
+ replacements = options[:replacements] || {}
463
+ options[:log].warn( "No filename given " ) if options[:log].warn? and ! options[:filename]
464
+
465
+ new = template.template
466
+ encoding = template.template.encoding
467
+ case target
468
+ when :latex
469
+ add_option( @language )
470
+ when :context
471
+ options[:log].warn( "Support for #{target} under development" ) if options[:log].warn?
472
+ when :html
473
+ when :text
474
+ when :wiki
475
+ when :creole
476
+ options[:log].warn( "Support for #{target} under development" ) if options[:log].warn?
477
+ else
478
+ options[:log].fatal( "Unknown target #{target} for #{options[:filename]}" ) if options[:log].fatal?
479
+ return ''
480
+ end
481
+ if ! new.kind_of?( String )
482
+ options[:log].error( "New is wrong type: #{new.inspect}") if options[:log].error?
483
+ end
484
+
485
+ options[:document] = self
486
+ @head << self.docinfo()
487
+ options[:log].debug( "Build header data") if options[:log].debug?
488
+ new.sub!( '<<head>>', @head.to_doc(target, options ).encode(encoding))
489
+ options[:log].debug( "Build body") if options[:log].debug?
490
+ new.sub!( '<<body>>', @body.to_doc(target, options).encode(encoding))
491
+ new.sub!( '<<classoptions>>', @options.uniq.join(',').encode(encoding))
492
+
493
+
494
+ replacements.each{|pattern, replace |
495
+ options[:log].info("Replace text #{pattern.source} with #{replace}" ) if options[:log].info?
496
+ new.gsub!( pattern, replace ) if replace
497
+ }
498
+ return new
499
+ end #Document#to_doc
500
+ #Return the actual target type.
501
+ #Needed by Element#to_s to decide which method is used to prepare the output.
502
+ #
503
+ #The usage of this technic makes similar processing unposibble.
504
+ #Set in Document#save.
505
+ attr_reader :target
506
+ =begin rdoc
507
+ Call rake4latex to translate the file.
508
+ =end
509
+ def Document.runtex( filename, options = [:touch, :statistic, :clean])
510
+ if ! defined? Rake4LaTeX
511
+ puts <<warning
512
+ Rake4LaTeX not loaded!
513
+ Please use one of the following commands:
514
+ require 'rake4latex'
515
+ require 'rake4latex_latex'
516
+ require 'rake4latex_pdflatex'
517
+ require 'rake4latex_xelatex'
518
+ ...
519
+ Document.save(
520
+ :runtex => [:statistic, :clean]
521
+ #or with more options:
522
+ #:runtex => [:touch, :texerrors_allowed, :statistic, :clean]
523
+ )
524
+ warning
525
+ begin
526
+ #interprete old interface before 1.2.0
527
+ gem 'rake4latex', '>= 0.1.2'
528
+ case options
529
+ when :latex; require 'rake4latex_latex'
530
+ when :pdflatex; require 'rake4latex_pdflatex'
531
+ when :xelatex; require 'rake4latex_xelatex'
532
+ else; require 'rake4latex'
533
+ end #format
534
+ options = [:touch, :statistic, :clean]
535
+ rescue LoadError
536
+ puts "Sorry, I didn't find the rake4latex to translate #{filename}"
537
+ puts "I try to use the old 'RunTeX'"
538
+ runtex_old( filename, options[:format] )
539
+ return false
540
+ end unless defined? Rake4LaTeX
541
+ end # ! defined? Rake4LaTeX
542
+
543
+ case options
544
+ when Array #ok
545
+ when true; options = [:touch, :statistic, :clean]
546
+ else
547
+ options = [:touch, :statistic, :clean]
548
+ puts "Please change runtex-options to: #{options.inspect}"
549
+ end
550
+ #Taskname must be uniq for this file.
551
+ runtex = "Define TeX-task #{filename.ext('pdf')}"
552
+ rake4latex = Rake4LaTeX::Basefile.set(filename)#needed for clean...
553
+ rake4latex [:texerrors_allowed] = true if options.delete(:texerrors_allowed)
554
+ rake4latex[:loglevel] = Log4r::WARN
555
+
556
+ if options.delete(:touch)
557
+ task :touch => filename.ext('tex')
558
+ task runtex => :touch
559
+ end #if options.delete(:touch)
560
+ task runtex => filename.ext('pdf')
561
+ task runtex => options
562
+
563
+ Rake.application[runtex].invoke
564
+ options.each{|option| Rake.application[option].reenable }
565
+ end
566
+ =begin rdoc
567
+ Make some basic replacements for TeX.
568
+ There is no sense to use it with HTML.
569
+
570
+ Better solution: Puts String into \path, \verb or similar.
571
+ =end
572
+ def Document.texify( input )
573
+ out = input.strip
574
+ #~ out.gsub!( /&/, '\\\&') #geht schief. erzeugt <<body>>...
575
+ #~ out.gsub!( /\\/, '\\\\')
576
+ out.gsub!( /%/, '\%')
577
+ out.gsub!( /\$/, '\$')
578
+ out.gsub!( /&/, '\\\\&')
579
+ out.gsub!( /_/, '\_')
580
+ out.gsub!( /#/, '\#')
581
+ out.gsub!( /€/, '\euro ')
582
+ return out
583
+ end
584
+ def inspect()
585
+ return "#<Document '#{@title}'>"
586
+ #~ return "#<Document '#{@title} #{@body.inspect}>'"
587
+ end
588
+ end #Document