deplate 0.7.3 → 0.8

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 (160) hide show
  1. data/AUTHORS.TXT +3 -0
  2. data/CHANGES.TXT +248 -175
  3. data/LICENSE.TXT +0 -0
  4. data/NEWS.TXT +28 -24
  5. data/README.TXT +0 -0
  6. data/TODO.TXT +174 -88
  7. data/VERSION.TXT +1 -1
  8. data/bin/deplate +0 -0
  9. data/bin/deplate.bat +0 -0
  10. data/etc/deplate.ini +91 -3
  11. data/lib/action_view/helpers/deplate.rb +45 -0
  12. data/lib/deplate.rb +6 -1
  13. data/lib/deplate/abstract-class.rb +0 -0
  14. data/lib/deplate/bib.rb +576 -0
  15. data/lib/deplate/builtin.rb +0 -0
  16. data/lib/deplate/cache.rb +55 -5
  17. data/lib/deplate/commands.rb +346 -183
  18. data/lib/deplate/common.rb +209 -48
  19. data/lib/deplate/converter.rb +12 -6
  20. data/lib/deplate/core.rb +777 -378
  21. data/lib/deplate/counters.rb +254 -0
  22. data/lib/deplate/css/article.css +4 -3
  23. data/lib/deplate/css/deplate.css +121 -5
  24. data/lib/deplate/css/heading-navbar.css +0 -0
  25. data/lib/deplate/css/layout-deplate-print.css +0 -0
  26. data/lib/deplate/css/layout-deplate.css +0 -0
  27. data/lib/deplate/css/sans-serif.css +0 -0
  28. data/lib/deplate/css/serif-e.css +0 -0
  29. data/lib/deplate/css/serif-rel.css +0 -0
  30. data/lib/deplate/css/serif.css +9 -3
  31. data/lib/deplate/css/slides.css +0 -0
  32. data/lib/deplate/css/tabbar-left.css +0 -0
  33. data/lib/deplate/css/tabbar-right-ie.css +3 -9
  34. data/lib/deplate/css/tabbar-right.css +51 -18
  35. data/lib/deplate/css/tabbar-top.css +7 -1
  36. data/lib/deplate/css/tabbar.css +0 -0
  37. data/lib/deplate/css/text-sans-serif.css +0 -0
  38. data/lib/deplate/css/text-serif.css +0 -0
  39. data/lib/deplate/define.rb +183 -177
  40. data/lib/deplate/deplate-string.rb +82 -0
  41. data/lib/deplate/docbook.rb +236 -128
  42. data/lib/deplate/elements.rb +584 -417
  43. data/lib/deplate/etc.rb +163 -101
  44. data/lib/deplate/external.rb +42 -11
  45. data/lib/deplate/fmt/dbk-article-4.1.2.rb +0 -0
  46. data/lib/deplate/fmt/dbk-article.rb +0 -0
  47. data/lib/deplate/fmt/dbk-book.rb +0 -0
  48. data/lib/deplate/fmt/dbk-ref.rb +3 -3
  49. data/lib/deplate/fmt/dbk-slides.rb +0 -0
  50. data/lib/deplate/fmt/dbk-snippet.rb +0 -0
  51. data/lib/deplate/fmt/html-snippet.rb +0 -0
  52. data/lib/deplate/fmt/html.rb +783 -550
  53. data/lib/deplate/fmt/htmlsite.rb +192 -199
  54. data/lib/deplate/fmt/htmlslides.rb +0 -0
  55. data/lib/deplate/fmt/htmlwebsite.rb +3 -3
  56. data/lib/deplate/fmt/latex-snippet.rb +0 -0
  57. data/lib/deplate/fmt/latex.rb +242 -83
  58. data/lib/deplate/fmt/null.rb +32 -0
  59. data/lib/deplate/fmt/php.rb +4 -4
  60. data/lib/deplate/fmt/phpsite.rb +6 -5
  61. data/lib/deplate/fmt/plain.rb +160 -106
  62. data/lib/deplate/fmt/template.rb +0 -0
  63. data/lib/deplate/fmt/xhtml10t.rb +0 -0
  64. data/lib/deplate/formatter-snippet.rb +0 -0
  65. data/lib/deplate/formatter.rb +613 -301
  66. data/lib/deplate/input.rb +202 -142
  67. data/lib/deplate/input/deplate-headings.rb +4 -6
  68. data/lib/deplate/input/deplate-restricted.rb +15 -9
  69. data/lib/deplate/input/deplate.rb +2 -4
  70. data/lib/deplate/input/rdoc.rb +39 -38
  71. data/lib/deplate/input/template.rb +0 -0
  72. data/lib/deplate/lib/Makefile.config +29 -0
  73. data/lib/deplate/lib/latex/deplate.sty +54 -0
  74. data/lib/deplate/lib/latex/highlight-extra.sty +0 -0
  75. data/lib/deplate/lib/latex/highlight-typical.sty +0 -0
  76. data/lib/deplate/lib/php/page-comment.inc.php +216 -0
  77. data/lib/deplate/lib/tabmenu.js +0 -0
  78. data/lib/deplate/locale/de.latin1 +155 -17
  79. data/lib/deplate/locale/ru.koi8-r +0 -0
  80. data/lib/deplate/locale/zh_cn.gb2312 +0 -0
  81. data/lib/deplate/macros.rb +133 -82
  82. data/lib/deplate/messages.rb +6 -4
  83. data/lib/deplate/metadata.rb +0 -0
  84. data/lib/deplate/metadata/marshal.rb +0 -0
  85. data/lib/deplate/metadata/xml.rb +0 -0
  86. data/lib/deplate/metadata/yaml.rb +0 -0
  87. data/lib/deplate/mod/anyword.rb +3 -3
  88. data/lib/deplate/mod/babelfish.rb +4 -4
  89. data/lib/deplate/mod/code-gvim.rb +8 -4
  90. data/lib/deplate/mod/code-highlight.rb +3 -3
  91. data/lib/deplate/mod/colored-log.rb +0 -0
  92. data/lib/deplate/mod/de.rb +2 -2
  93. data/lib/deplate/mod/en.rb +0 -0
  94. data/lib/deplate/mod/endnotes.rb +0 -0
  95. data/lib/deplate/mod/fr.rb +0 -0
  96. data/lib/deplate/mod/html-asciimath.rb +0 -0
  97. data/lib/deplate/mod/html-deplate-button.rb +0 -0
  98. data/lib/deplate/mod/html-headings-navbar.rb +5 -13
  99. data/lib/deplate/mod/html-jsmath.rb +39 -0
  100. data/lib/deplate/mod/html-obfuscate-email.rb +3 -3
  101. data/lib/deplate/mod/html-sidebar.rb +0 -0
  102. data/lib/deplate/mod/htmlslides-navbar-fh.rb +3 -3
  103. data/lib/deplate/mod/iconv.rb +0 -0
  104. data/lib/deplate/mod/imgurl.rb +4 -4
  105. data/lib/deplate/mod/inlatex-compound.rb +7 -10
  106. data/lib/deplate/mod/koma.rb +0 -0
  107. data/lib/deplate/mod/latex-emph-table-head.rb +0 -0
  108. data/lib/deplate/mod/latex-styles.rb +7 -4
  109. data/lib/deplate/mod/latex-verbatim-small.rb +0 -0
  110. data/lib/deplate/mod/makefile.rb +23 -7
  111. data/lib/deplate/mod/mark-external-urls.rb +3 -3
  112. data/lib/deplate/mod/markup-1-warn.rb +10 -10
  113. data/lib/deplate/mod/markup-1.rb +0 -0
  114. data/lib/deplate/mod/navbar-png.rb +24 -8
  115. data/lib/deplate/mod/noindent.rb +0 -0
  116. data/lib/deplate/mod/numpara.rb +0 -0
  117. data/lib/deplate/mod/particle-math.rb +4 -4
  118. data/lib/deplate/mod/php-extra.rb +46 -6
  119. data/lib/deplate/mod/pstoedit.rb +0 -0
  120. data/lib/deplate/mod/recode.rb +0 -0
  121. data/lib/deplate/mod/ru_koi8-r.rb +0 -0
  122. data/lib/deplate/mod/smart-dash.rb +26 -0
  123. data/lib/deplate/mod/smiley.rb +69 -7
  124. data/lib/deplate/mod/soffice.rb +0 -0
  125. data/lib/deplate/mod/symbols-latin1.rb +14 -23
  126. data/lib/deplate/mod/symbols-od-utf-8.rb +5 -3
  127. data/lib/deplate/mod/symbols-plain.rb +5 -35
  128. data/lib/deplate/mod/symbols-sgml.rb +8 -9
  129. data/lib/deplate/mod/symbols-utf-8.rb +8 -9
  130. data/lib/deplate/mod/symbols-xml.rb +5 -9
  131. data/lib/deplate/mod/syntax-region-alt.rb +5 -5
  132. data/lib/deplate/mod/utf8.rb +0 -0
  133. data/lib/deplate/mod/validate-html.rb +0 -0
  134. data/lib/deplate/mod/xmlrpc.rb +0 -0
  135. data/lib/deplate/mod/zh-cn-autospace.rb +18 -20
  136. data/lib/deplate/mod/zh-cn.rb +4 -6
  137. data/lib/deplate/nukumi2.rb +71 -0
  138. data/lib/deplate/once-method.rb +0 -0
  139. data/lib/deplate/output.rb +19 -21
  140. data/lib/deplate/particles.rb +178 -116
  141. data/lib/deplate/regions.rb +99 -58
  142. data/lib/deplate/skeletons.rb +122 -0
  143. data/lib/deplate/structured.rb +164 -106
  144. data/lib/deplate/template.rb +67 -43
  145. data/lib/deplate/templates/html-doc.html +0 -0
  146. data/lib/deplate/templates/html-left-tabbar-js.html +0 -0
  147. data/lib/deplate/templates/html-left-tabbar.html +0 -0
  148. data/lib/deplate/templates/html-tabbar-right-pcomments.php +22 -0
  149. data/lib/deplate/templates/html-tabbar-right-step.html +24 -0
  150. data/lib/deplate/templates/html-tabbar-right-table.html +0 -0
  151. data/lib/deplate/templates/html-tabbar-right.html +2 -4
  152. data/lib/deplate/templates/html-tabbar-top.html +0 -9
  153. data/lib/deplate/templates/html-tabbar.html +0 -0
  154. data/lib/deplate/variables.rb +127 -0
  155. data/lib/deplate/wiki-markup.rb +99 -33
  156. data/lib/deplate/xml.rb +18 -18
  157. data/lib/deplate/zh-cn.rb +0 -0
  158. data/lib/ps2ppm.rb +0 -0
  159. data/man/man1/deplate.1 +564 -474
  160. metadata +201 -186
File without changes
File without changes
File without changes
@@ -3,10 +3,11 @@
3
3
  # @Website: http://deplate.sf.net/
4
4
  # @License: GPL (see http://www.gnu.org/licenses/gpl.txt)
5
5
  # @Created: 31-Okt-2004.
6
- # @Last Change: 02-Nov-2005.
7
- # @Revision: 0.923
6
+ # @Last Change: 05-Jun-2006.
7
+ # @Revision: 0.1443
8
8
 
9
- require "deplate/abstract-class"
9
+ require 'deplate/abstract-class'
10
+ require 'deplate/common'
10
11
 
11
12
  # Description:
12
13
  # An abstract formatter class
@@ -18,7 +19,32 @@ require "deplate/abstract-class"
18
19
  # CHANGES:
19
20
  #
20
21
 
21
- class Deplate::Formatter
22
+ class Deplate::Formatter < Deplate::CommonObject
23
+ class_attribute :formatter
24
+
25
+ class_attribute :suffix
26
+ class_attribute :myname
27
+ class_attribute :related, []
28
+ class_attribute :rx
29
+ class_attribute :label_mode, :enclose
30
+ class_attribute :label_delegate, []
31
+ class_attribute :label_once, []
32
+
33
+ class_attribute :naked_agents, [
34
+ :format_label,
35
+ :format_index,
36
+ ]
37
+
38
+ class_attribute :blacklist_latex, [
39
+ 'include', 'def', 'command', 'loop', 'repeat',
40
+ 'open', 'toks', 'output', 'input', 'catcode', 'name', '^^',
41
+ '\\every', '\\errhelp', '\\errorstopmode', '\\scrollmode',
42
+ '\\nonstopmode', '\\batchmode', '\\read', '\\write', 'csname',
43
+ '\\newhelp', '\\uppercase', '\\lowercase', '\\relax',
44
+ '\\aftergroup', '\\afterassignment', '\\expandafter',
45
+ '\\noexpand', '\\special', '\\usepackage'
46
+ ]
47
+
22
48
  class << self
23
49
  def noop(context, name)
24
50
  context.module_eval %{
@@ -28,67 +54,54 @@ class Deplate::Formatter
28
54
  }
29
55
  end
30
56
 
31
- attr_writer :suffix, :myname, :rx, :label_mode, :label_delegate, :label_once
57
+ def hook_post_myname=(name)
58
+ klass = self
59
+ Deplate::Core.class_eval {declare_formatter(klass)}
60
+ end
32
61
 
33
- def get_class_attrib(name, default=nil)
34
- if self == Deplate::Formatter
35
- return default
62
+ # <+TBD+>Shouldn't services belong to the formatter?
63
+ def def_service(name, &block)
64
+ # prefix = @formatter.class.myname.gsub('\W', '__')
65
+ # method = ['svc', prefix, name].join('_')
66
+ method = ['svc', name].join('_')
67
+ self.class_eval do
68
+ define_method(method, &block)
36
69
  end
37
- iv = "@#{name}"
38
- if self.instance_variables.include?(iv)
39
- val = self.instance_variable_get(iv)
40
- if val
41
- return val
70
+ init = ['formatter_initialize', method].join('_')
71
+ sname = name.gsub(/_(.)/) {$1.capitalize}
72
+ self.class_eval do
73
+ define_method(init) do
74
+ @doc_services[name] = method
75
+ @doc_services[sname] = method
42
76
  end
43
77
  end
44
- return self.superclass.get_class_attrib(name, default)
45
- end
46
-
47
- def suffix
48
- get_class_attrib('suffix')
49
- end
50
-
51
- def myname
52
- get_class_attrib('myname')
53
- end
54
-
55
- def myname=(name)
56
- @myname = name
57
- klass = self
58
- Deplate::Core.class_eval {declare_formatter(klass)}
59
- end
60
-
61
- def rx
62
- get_class_attrib('rx')
63
- end
64
-
65
- def label_mode
66
- get_class_attrib('label_mode', :enclose)
67
- end
68
-
69
- def label_delegate
70
- get_class_attrib('label_delegate', [])
71
- end
72
-
73
- def label_once
74
- get_class_attrib('label_once', [])
75
78
  end
76
79
  end
77
80
 
78
81
  @@custom_particles = {}
79
82
 
80
- attr_reader :deplate
81
- attr_reader :advices
83
+ attr_reader :deplate
84
+ attr_reader :advices
85
+ attr_reader :expander
82
86
  attr_accessor :special_symbols
87
+ attr_accessor :bibentries
88
+ # A hash holding all known document services (names => method).
89
+ attr_accessor :doc_services
83
90
 
84
91
  def initialize(deplate, args={})
85
- @deplate = deplate
86
- @variables = deplate.variables
87
- @bibentries = {}
88
- @open_labels = []
89
- @advices = args[:advices] || {}
90
- @inlatex_idx = 0
91
- @encodings = {}
92
+ @deplate = deplate
93
+ @variables = deplate.variables
94
+ @advices = args[:advices] || {}
95
+ @doc_services = args[:doc_services] || initialize_services
96
+ @inlatex_idx = 0
97
+ @encodings = {}
98
+ @symbol_proxy = nil
99
+ reset!
100
+ end
101
+
102
+ def reset!
103
+ @bibentries = {}
104
+ @open_labels = []
92
105
  @consumed_labels = []
93
106
  @consumed_ids = []
94
107
  end
@@ -139,6 +152,24 @@ class Deplate::Formatter
139
152
  end
140
153
  end
141
154
 
155
+ # Run a "service", i.e., a small, mostly autonomous function/method that
156
+ # usually yields some formatted output.
157
+ def invoke_service(name, args={}, text='')
158
+ method = @doc_services[name]
159
+ if method
160
+ begin
161
+ return send(method, args || {}, text || '')
162
+ rescue Exception => e
163
+ puts e.backtrace[0..10].join("\n")
164
+ log(['Calling service failed', name, e], :error)
165
+ end
166
+ else
167
+ p "DBG"
168
+ puts @doc_services.keys.sort.join("\n")
169
+ log(['Unknown service', name], :error)
170
+ end
171
+ end
172
+
142
173
  def log(*args)
143
174
  Deplate::Core.log(*args)
144
175
  end
@@ -162,6 +193,10 @@ class Deplate::Formatter
162
193
  return table[cen] || cen
163
194
  end
164
195
 
196
+ def output_destination
197
+ @deplate.output.top_heading.destination || @deplate.options.out
198
+ end
199
+
165
200
  def join_blocks(blocks)
166
201
  blocks.flatten.compact.join("\n")
167
202
  end
@@ -173,23 +208,37 @@ class Deplate::Formatter
173
208
  def format_particle(agent, invoker, *args)
174
209
  # rv = with_agent(agent, Array, invoker, *args)
175
210
  # rv.empty? ? format_unknown_particle(invoker) : rv.join
176
- with_agent(agent, Array, invoker, *args)
211
+ rv = with_agent(agent, Array, invoker, *args)
212
+ if rv and !rv.empty? and !self.class.naked_agents.include?(agent)
213
+ wa = {}
214
+ wa[:styles] = invoker.styles if invoker.respond_to?(:styles)
215
+ rv = methods.find_all {|m| m =~ /^wrap_formatted_particle_/ }.
216
+ inject(rv) {|rv, m| send(m, invoker, rv, wa)}
217
+ end
218
+ rv
177
219
  end
178
220
 
179
- def format_particle_as_string(agent, object, *args)
180
- join_inline(format_particle(agent, object, *args))
221
+ def format_particle_as_string(agent, invoker, *args)
222
+ join_inline(format_particle(agent, invoker, *args))
181
223
  end
182
-
224
+
183
225
  def format_element(agent, invoker, *args)
184
226
  # rv = with_agent(agent, Array, invoker, *args)
185
227
  # rv.empty? ? format_unknown(invoker) : join_blocks(rv)
186
- with_agent(agent, Array, invoker, *args)
228
+ rv = with_agent(agent, Array, invoker, *args)
229
+ if rv and !rv.empty? and !self.class.naked_agents.include?(agent)
230
+ wa = {}
231
+ wa[:styles] = invoker.styles if invoker.respond_to?(:styles)
232
+ rv = methods.find_all {|m| m =~ /^wrap_formatted_element_/ }.
233
+ inject(rv) {|rv, m| send(m, invoker, rv, wa)}
234
+ end
235
+ rv
187
236
  end
188
237
 
189
- def format_element_as_string(agent, object, *args)
190
- format_element(agent, object, *args)
238
+ def format_element_as_string(agent, invoker, *args)
239
+ format_element(agent, invoker, *args)
191
240
  end
192
-
241
+
193
242
  def with_agent(agent, prototype, invoker, *args)
194
243
  log(["Call with agent", agent, invoker.class, args], :debug)
195
244
  if respond_to?(agent)
@@ -209,7 +258,7 @@ class Deplate::Formatter
209
258
  prototype ||= inner.class
210
259
  around = stylish[:wrap]
211
260
  if around
212
- inner = around.inject(inner) do |acc, advice|
261
+ inner = around.inject(inner) do |acc, advice|
213
262
  advice[:prc].call(agent, acc, invoker, *args)
214
263
  end
215
264
  end
@@ -247,7 +296,11 @@ class Deplate::Formatter
247
296
  return nil
248
297
  end
249
298
  end
250
-
299
+
300
+ def dummy(invoker, *args)
301
+ args
302
+ end
303
+
251
304
  def output(invoker, *body)
252
305
  output_at(invoker.doc_type, invoker.doc_slot, *body)
253
306
  end
@@ -318,6 +371,77 @@ class Deplate::Formatter
318
371
  end
319
372
  end
320
373
 
374
+ def check_symbol_proxy
375
+ unless @symbol_proxy
376
+ pre_process
377
+ end
378
+ end
379
+
380
+ def symbol_quote(invoker)
381
+ check_symbol_proxy
382
+ @symbol_proxy.symbol_quote(invoker)
383
+ end
384
+
385
+ def symbol_gt(invoker)
386
+ check_symbol_proxy
387
+ @symbol_proxy.symbol_gt(invoker)
388
+ end
389
+
390
+ def symbol_lt(invoker)
391
+ check_symbol_proxy
392
+ @symbol_proxy.symbol_lt(invoker)
393
+ end
394
+
395
+ def symbol_amp(invoker)
396
+ check_symbol_proxy
397
+ @symbol_proxy.symbol_amp(invoker)
398
+ end
399
+
400
+ def doublequote_open(invoker)
401
+ check_symbol_proxy
402
+ @symbol_proxy.doublequote_open(invoker)
403
+ end
404
+
405
+ def doublequote_close(invoker)
406
+ check_symbol_proxy
407
+ @symbol_proxy.doublequote_close(invoker)
408
+ end
409
+
410
+ def singlequote_open(invoker)
411
+ check_symbol_proxy
412
+ @symbol_proxy.singlequote_open(invoker)
413
+ end
414
+
415
+ def singlequote_close(invoker)
416
+ check_symbol_proxy
417
+ @symbol_proxy.singlequote_close(invoker)
418
+ end
419
+
420
+ def nonbreakingspace(invoker)
421
+ check_symbol_proxy
422
+ @symbol_proxy.nonbreakingspace(invoker)
423
+ end
424
+
425
+ def symbol_paragraph(invoker)
426
+ check_symbol_proxy
427
+ @symbol_proxy.symbol_paragraph(invoker)
428
+ end
429
+
430
+ def format_symbol(invoker, sym)
431
+ check_symbol_proxy
432
+ @symbol_proxy.format_symbol(invoker, sym)
433
+ end
434
+
435
+ def format_plain_text(invoker, text=nil, escaped=false)
436
+ text ||= invoker.match
437
+ # <+TBD+> escaped
438
+ plain_text(text, escaped)
439
+ end
440
+
441
+ def format_void(invoker, text=nil)
442
+ text || invoker.elt
443
+ end
444
+
321
445
  # Recode normal text for #plain_text
322
446
  def plain_text_recode(text)
323
447
  text
@@ -381,17 +505,27 @@ class Deplate::Formatter
381
505
  def format_LIST(invoker)
382
506
  acc = []
383
507
  elt = invoker.elt
508
+ case elt
509
+ when 'contents'
510
+ elt = 'toc'
511
+ when 'tables'
512
+ elt = 'lot'
513
+ when 'figures'
514
+ elt = 'lof'
515
+ end
384
516
  meth = "format_list_of_" + elt
385
- if respond_to?(meth)
386
- args = invoker.args
387
- begin
517
+ args = invoker.args
518
+ begin
519
+ if respond_to?(meth)
388
520
  acc << send(meth, invoker)
389
- acc << format_pagebreak(invoker) if args["page"]
390
- rescue StandardError => e
391
- log(["Formatting on LIST failed", elt.inspect, e, e.backtrace[0..10]], :error)
521
+ elsif @deplate.options.listings.is_defined?(elt)
522
+ acc << format_custom_list(invoker, elt)
523
+ else
524
+ log(["Unknown list type", elt.inspect], :error)
392
525
  end
393
- else
394
- log(["Unknown LIST type", elt.inspect], :error)
526
+ acc << format_pagebreak(invoker) if args["page"]
527
+ rescue StandardError => e
528
+ log(["Formatting on LIST failed", elt.inspect, e, e.backtrace[0..10]], :error)
395
529
  end
396
530
  join_blocks(acc)
397
531
  end
@@ -407,6 +541,20 @@ class Deplate::Formatter
407
541
  def read_bib(bibfiles)
408
542
  end
409
543
 
544
+ def bib_entry(key)
545
+ b = @bibentries[key] || []
546
+ crossref = b.assoc('crossref')
547
+ if crossref
548
+ cb = @bibentries[crossref[1]]
549
+ b += cb if cb
550
+ end
551
+ return b
552
+ end
553
+
554
+ def referenced_bib_entry(invoker, key, text)
555
+ text
556
+ end
557
+
410
558
  def format_unknown(invoker)
411
559
  log(["Unknown element", invoker.class], :error, invoker.source)
412
560
  elt = invoker.elt
@@ -426,7 +574,7 @@ class Deplate::Formatter
426
574
 
427
575
 
428
576
  ### General
429
- def_abstract :format_label, :format_figure, :include_image
577
+ def_abstract :format_label, :format_figure, :include_image, :image_suffixes
430
578
 
431
579
  ### Elements
432
580
  def_abstract :format_note, :format_table, :format_heading, :format_list,
@@ -441,8 +589,9 @@ class Deplate::Formatter
441
589
  :format_pagebreak
442
590
 
443
591
  ### Particles
444
- def_abstract :format_emphasize, :format_code, :format_url, :format_wiki, :format_symbol,
445
- :doublequote_open, :doublequote_close, :singlequote_open, :singlequote_close
592
+ def_abstract :format_emphasize, :format_code, :format_url, :format_wiki
593
+ # def_abstract :format_symbol, :doublequote_open, :doublequote_close,
594
+ # :singlequote_open, :singlequote_close
446
595
 
447
596
  ### Macros
448
597
  def_abstract :format_index, :format_footnote, :format_ref,
@@ -450,48 +599,7 @@ class Deplate::Formatter
450
599
  :format_pagenumber
451
600
 
452
601
  def format_cite(invoker)
453
- container = invoker.container
454
- args = invoker.args
455
- n = args['n']
456
- p = args['p']
457
- np = args['np']
458
- y = args['y']
459
- acc = []
460
- pmsg = @deplate.msg('p.\\ ')
461
- for c in invoker.elt
462
- cc = bib_entry(c)
463
- if cc
464
- yr = cc.assoc('year')
465
- yr = if yr then yr[1] else '' end
466
- if p
467
- p = @deplate.parse_and_format_without_wikinames(container, "#{pmsg}#{p}")
468
- yr += ": #{p}"
469
- # yr += ": " + p if p
470
- end
471
- if y
472
- acc << referenced_bib_entry(invoker, c, yr)
473
- else
474
- nm = cc.assoc('author') || cc.assoc('editor') || cc.assoc('howpublished')
475
- if nm
476
- nm = nm[1]
477
- nm = nm.gsub(/\s+/, ' ').split(' and ').collect do |a|
478
- a.scan(/\w+$/)
479
- end
480
- nm = nm.join(', ')
481
- acc << referenced_bib_entry(invoker, c, [nm, yr].join(' '))
482
- else
483
- acc << referenced_bib_entry(invoker, c, c)
484
- end
485
- end
486
- end
487
- end
488
- n &&= n + plain_text(' ', true)
489
- acc = acc.join('; ')
490
- if np
491
- return %{#{plain_text(' ', true)}#{n}#{acc}}
492
- else
493
- return %{#{plain_text(' ', true)}(#{n}#{acc})}
494
- end
602
+ bib_styler.bib_cite(invoker)
495
603
  end
496
604
 
497
605
  # Check if ch (a number representing a character) is a multi-byte leader.
@@ -532,14 +640,18 @@ class Deplate::Formatter
532
640
  max
533
641
  end
534
642
 
643
+ def table_empty_cell
644
+ ''
645
+ end
646
+
535
647
  # Takes an optional block that takes a string as argument and returns
536
648
  # true if we shouldn't wrap the text at this position
537
649
  def wrap_text(text, args={})
538
- moreIndent = args[:indent] || ""
650
+ moreIndent = args[:indent] || ''
539
651
  innerMargin = args[:margin] || 66
540
652
  outerMargin = args[:maxmargin] || 72
541
653
  hanging = args[:hanging] || nil
542
- hang_idt = hanging ? " " * hanging : nil
654
+ hang_idt = hanging ? ' ' * hanging : nil
543
655
  acc = []
544
656
  block = args[:check]
545
657
  break_at = args[:break_at]
@@ -571,6 +683,7 @@ class Deplate::Formatter
571
683
 
572
684
  def break_line(line, rx, inner_margin, block=nil, delta=-1)
573
685
  max = line.size
686
+ # p "DBG #{max} -- #{inner_margin}: #{line}"
574
687
  if inner_margin >= max
575
688
  return line, nil
576
689
  else
@@ -606,7 +719,7 @@ class Deplate::Formatter
606
719
  acc = []
607
720
  elt = invoker.elt
608
721
  if elt
609
- for i in elt
722
+ elt.each do |i|
610
723
  acc << format_element(:format_figure, invoker, inline, i)
611
724
  end
612
725
  else
@@ -627,7 +740,7 @@ class Deplate::Formatter
627
740
  acc << invoker.text
628
741
  else
629
742
  for i in inlatex
630
- # acc << @deplate.formatter.include_image(i, args, true)
743
+ # acc << @deplate.formatter.include_image(invoker, i, args, true)
631
744
  acc << format_element(:format_figure, invoker, true, i)
632
745
  end
633
746
  end
@@ -667,10 +780,13 @@ class Deplate::Formatter
667
780
  raise "Unknown device/suffix: #{sfx}"
668
781
  end
669
782
 
783
+ pointsize = invoker.args['pointsize'] ||
784
+ @deplate.variables['latexPointsize'] || '10'
670
785
  acc = [
671
- "\\documentclass[12pt,a4paper,notitlepage]{article}",
786
+ "\\documentclass[#{pointsize}pt,a4paper,notitlepage]{article}",
672
787
  "\\usepackage{amsmath}",
673
788
  "\\usepackage{amsfonts}",
789
+ "\\usepackage{amssymb}",
674
790
  ]
675
791
  acc += pkgs
676
792
  acc << "\\begin{document}" << "\\pagestyle{empty}"
@@ -719,7 +835,7 @@ class Deplate::Formatter
719
835
  @inlatex_idx += 1
720
836
  end
721
837
  id = @deplate.auxiliary_auto_filename('ltx', @inlatex_idx, invoker.accum)
722
- invoker.log(["No id given", invoker.accum])
838
+ invoker.log(["No ID given", invoker.accum])
723
839
  end
724
840
  id
725
841
  end
@@ -741,6 +857,7 @@ class Deplate::Formatter
741
857
  pkgs = []
742
858
  body = []
743
859
  for l in accum.join("\n")
860
+ l = inlatex_clean(l)
744
861
  if l =~ /^\s*\\(usepackage|input)\s*(\[.*?\])?\s*\{.+?\}\s*$/
745
862
  pkgs << l.chomp
746
863
  elsif l =~ /%%%\s*$/
@@ -751,10 +868,30 @@ class Deplate::Formatter
751
868
  end
752
869
  return pkgs.uniq, body
753
870
  end
871
+
872
+ rx = self.blacklist_latex.collect! do |c|
873
+ if c =~ /^\\(.+)$/
874
+ "\\\\\\s*#$1\\b"
875
+ elsif c =~ /\w$/
876
+ # "(\\\\\\s*)?\\b#{Regexp.escape(c)}\\b"
877
+ "\\\\\\s*#{Regexp.escape(c)}\\b"
878
+ else
879
+ Regexp.escape(c)
880
+ end
881
+ end
882
+ INLATEX_RX = Regexp.new(rx.join('|'))
754
883
 
884
+ def inlatex_clean(line)
885
+ line = line.chomp
886
+ unless @deplate.options.allow.include?('t')
887
+ line.gsub!(INLATEX_RX, '+++disabled+++')
888
+ end
889
+ line
890
+ end
891
+
755
892
  # The default suffix/device to be used for inlatex output.
756
893
  def inlatex_sfx
757
- "jpeg"
894
+ 'jpeg'
758
895
  end
759
896
 
760
897
  def latex2dvi(invoker, ftex, faux, flog)
@@ -783,12 +920,6 @@ class Deplate::Formatter
783
920
  end
784
921
  end
785
922
 
786
-
787
- private
788
- def referenced_bib_entry(invoker, key, text)
789
- text
790
- end
791
-
792
923
  def formatted_block(env, text, opts=nil, args=nil, no_id=false, no_indent=false)
793
924
  text = indent_text(text) unless no_indent
794
925
  return join_blocks([get_open(env, opts, args, :no_id => no_id), text, get_close(env, args)])
@@ -804,6 +935,184 @@ class Deplate::Formatter
804
935
  return get_open(env, opts, args, :single => true, :no_id => no_id)
805
936
  end
806
937
 
938
+ def indent_text(text, args={})
939
+ if text
940
+ mult = args[:mult] || 1
941
+ shift = args[:shift]
942
+ hanging = args[:hanging]
943
+ indent = args[:indent] || format_indent(mult, shift)
944
+ return text.collect do |l|
945
+ rv = '%s%s' % [indent, l.chomp]
946
+ if hanging
947
+ indent = args[:indenttail] || \
948
+ if args[:indent]
949
+ args[:indent] +
950
+ case hanging
951
+ when Integer
952
+ ' ' * hanging
953
+ else
954
+ ' '
955
+ end
956
+ else
957
+ format_indent(mult + 1, shift)
958
+ end
959
+ hanging = false
960
+ end
961
+ rv
962
+ end.join("\n")
963
+ end
964
+ end
965
+
966
+ def_service('object') do |args, text|
967
+ id = args['id']
968
+ if id
969
+ return @deplate.object_by_id(id)
970
+ elsif args['array']
971
+ text = args['array']
972
+ sep = args['sep']
973
+ if sep
974
+ sep = sep ? Regexp.escape(sep) : '\\s+'
975
+ else
976
+ sep = args['rx']
977
+ end
978
+ if sep
979
+ return text.split(Regexp.new(sep))
980
+ else
981
+ log('No separator', :error)
982
+ end
983
+ end
984
+ end
985
+
986
+ def_service('output_filename') do |args, text|
987
+ output_destination
988
+ end
989
+
990
+ def_service('output_basename') do |args, text|
991
+ sfx = args['sfx']
992
+ if sfx
993
+ File.basename(output_destination, sfx)
994
+ else
995
+ File.basename(output_destination)
996
+ end
997
+ end
998
+
999
+ # <+TBD+>
1000
+ # def_service('format') do |args, text|
1001
+ # id = args['id'] || text
1002
+ # # o = @variables[id]
1003
+ # o = object_by_id(id)
1004
+ # if o
1005
+ # o.format_as_string
1006
+ # end
1007
+ # end
1008
+
1009
+
1010
+ private
1011
+ def initialize_services
1012
+ services = {}
1013
+ return services
1014
+ end
1015
+
1016
+ def format_custom_list(invoker, elt)
1017
+ listing = @deplate.options.listings.get(elt, true)
1018
+ props = listing[:props]
1019
+ format_list_of(invoker,
1020
+ :title => props['title'],
1021
+ :prefix => props['prefix'] || elt,
1022
+ :data => listing[:value],
1023
+ :flat => props['flat'],
1024
+ :style => (props['style'] || props['prefix'])
1025
+ )
1026
+ end
1027
+
1028
+ def format_list_of(invoker, other_args)
1029
+ args = invoker.args
1030
+ name = other_args[:title]
1031
+ prefix = other_args[:prefix]
1032
+ data = other_args[:data]
1033
+ unless data
1034
+ list = other_args[:listing]
1035
+ data = invoker.deplate.options.listings.get(list)
1036
+ unless data
1037
+ invoker.log(['Unknown list', list], :error)
1038
+ end
1039
+ end
1040
+ name = args['title'] || name
1041
+ id = (name || prefix).gsub(/\W/, '_')
1042
+
1043
+ acc = []
1044
+ consume_label(id, true)
1045
+ consume_label("#{id}Block", true)
1046
+ acc << listing_prematter(invoker, other_args, id)
1047
+ unless args['plain'] || args['noTitle']
1048
+ acc << listing_title(invoker, other_args, name)
1049
+ end
1050
+
1051
+ ll = 1
1052
+ levels = args['levels']
1053
+ if levels
1054
+ range_from, range_to, rest = levels.split(/\.\./)
1055
+ if rest
1056
+ log(['Malformed range', levels], :error)
1057
+ end
1058
+ end
1059
+ range_from ||= args['min']
1060
+ if range_from
1061
+ range_from = range_from.to_i
1062
+ end
1063
+ range_to ||= args['max']
1064
+ if range_to
1065
+ range_to = range_to.to_i
1066
+ end
1067
+ top = args['top']
1068
+ if top
1069
+ top = /^#{Regexp.escape(top)}/
1070
+ end
1071
+ sub = args['sub']
1072
+ if sub
1073
+ sub = /^#{Regexp.escape(invoker.level_as_string)}\./
1074
+ end
1075
+ accData = []
1076
+ for elt in data
1077
+ if elt.nil? or elt.args['noList']
1078
+ next
1079
+ end
1080
+ if range_from and elt.level < range_from
1081
+ next
1082
+ end
1083
+ if range_to and elt.level > range_to
1084
+ next
1085
+ end
1086
+ if top and elt.level_as_string !~ top
1087
+ next
1088
+ end
1089
+ if sub and elt.level_as_string !~ sub
1090
+ next
1091
+ end
1092
+ title = block_given? ? yield(elt) : elt.element_caption
1093
+ level = other_args[:flat] ? 1 : elt.level
1094
+ accData << listing_item(invoker, args, prefix, title, elt, level, other_args)
1095
+ end
1096
+ acc << printable_list(invoker, accData)
1097
+ acc << listing_postmatter(invoker, other_args)
1098
+ join_blocks(acc)
1099
+ end
1100
+
1101
+ def_abstract :listing_prematter, :listing_postmatter, :listing_title, \
1102
+ :listing_item
1103
+
1104
+ def consume_label(label, warn=false)
1105
+ if !label
1106
+ return false
1107
+ elsif @consumed_labels.include?(label)
1108
+ log(['Duplicate label'], label, :error) if warn
1109
+ return false
1110
+ else
1111
+ @consumed_labels << label
1112
+ return true
1113
+ end
1114
+ end
1115
+
807
1116
  def use_id(args, opts={}, set=true)
808
1117
  if args
809
1118
  set &&= !args[:id]
@@ -841,24 +1150,17 @@ class Deplate::Formatter
841
1150
 
842
1151
  def format_indent(level, shift=false)
843
1152
  if level < 0
844
- log(["Negative indentation level", level], :error)
845
- return ""
1153
+ log(['Negative indentation level', level], :error)
1154
+ return ''
846
1155
  else
847
1156
  l = level * 2
848
1157
  # l += 1 if shift
849
- return " " * l
1158
+ return ' ' * l
850
1159
  end
851
1160
  end
852
1161
 
853
- def indent_text(text, mult=1, shift=false)
854
- if text
855
- indent = format_indent(mult)
856
- return text.collect {|l| "%s%s" % [indent, l.chomp]}.join("\n")
857
- end
858
- end
859
-
860
1162
  def keywords
861
- kw = @deplate.variables["keywords"]
1163
+ kw = @deplate.variables['keywords']
862
1164
  if kw.kind_of?(Array)
863
1165
  kw
864
1166
  elsif kw.kind_of?(String)
@@ -873,11 +1175,16 @@ class Deplate::Formatter
873
1175
  # Create @plain_text_rx, which contains the keys of @special_symbols
874
1176
  # in a group. This rx will be used by #plain_text.
875
1177
  def build_plain_text_rx
876
- @plain_text_rx = Regexp.new("(%s)" % @special_symbols.keys.collect {|x| Regexp.escape(x)}.join("|"))
1178
+ @plain_text_rx = Regexp.new('(%s)' % @special_symbols.keys.collect {|x| Regexp.escape(x)}.join('|'))
877
1179
  end
878
1180
 
879
1181
 
880
1182
  ################################################ Bibliography {{{1
1183
+ def bib_styler
1184
+ style = @deplate.variables['bibStyle']
1185
+ @deplate.bib_styler(style)
1186
+ end
1187
+
881
1188
  def simple_bibtex_reader(bibfiles)
882
1189
  acc = []
883
1190
  for b in bibfiles
@@ -890,11 +1197,22 @@ class Deplate::Formatter
890
1197
  end
891
1198
  File.open(b) {|io| acc << io.read}
892
1199
  end
893
- acc = acc.join("\n")
1200
+ strings = {}
1201
+ acc = acc.join("\n")
894
1202
  loop do
895
- m = /^\s*(@\w+\{\s*(\S+?)\s*,.*?)(?=(^@|\z))/m.match(acc)
1203
+ m = /^\s*@string\{\s*(\S+?)\s*=\s*(.+?)\s*\}/m.match(acc)
1204
+ if m
1205
+ r = m[2]
1206
+ if r =~ /^(".*?"|'.*?'|\{.*?\})$/
1207
+ r = r[1..-2]
1208
+ end
1209
+ strings[m[1]] = r
1210
+ acc = m.post_match
1211
+ next
1212
+ end
1213
+ m = /^\s*(@(\w+)\{\s*(\S+?)\s*,.*?)(?=(^@|\z))/m.match(acc)
896
1214
  if m
897
- id = m[2]
1215
+ id = m[3]
898
1216
  e = m[1]
899
1217
  arr = e.scan(/^\s*(\w+)\s*=\s*(\{.*?\}|\d+)\s*[,}]\s*$/m)
900
1218
  arr.collect! do |var, val, rest|
@@ -902,9 +1220,12 @@ class Deplate::Formatter
902
1220
  if n
903
1221
  val = n[1]
904
1222
  end
1223
+ if strings[val]
1224
+ val = strings[val]
1225
+ end
905
1226
  [var, val]
906
1227
  end
907
- arr << ["type", m[2]]
1228
+ arr << ['@type', m[2]] << ['@id', id]
908
1229
  @bibentries[id] = arr
909
1230
  acc = m.post_match
910
1231
  else
@@ -921,7 +1242,7 @@ class Deplate::Formatter
921
1242
  acc = []
922
1243
  for k in cited_keys
923
1244
  b = bib_entry(k)
924
- bb = format_bib_entry(invoker, b)
1245
+ bb = format_bib_entry(invoker, k, b)
925
1246
  i = encode_id(k)
926
1247
  l = format_label(invoker, :string, [i])
927
1248
  if block_given?
@@ -934,47 +1255,15 @@ class Deplate::Formatter
934
1255
  acc.collect! {|e| e[0]}
935
1256
  join_blocks(acc)
936
1257
  end
937
-
938
- def format_bib_entry(invoker, bibdef)
939
- key, author = bibdef.assoc("author")
940
- key, editor = bibdef.assoc("editor")
941
- key, how = bibdef.assoc("howpublished")
942
- author = reformat_authors(author)
943
- editor = reformat_authors(editor)
944
- au = [nil, author || editor || how || "???"]
945
- yr = bibdef.assoc("year")
946
- au[1] = "%s (%s)" % [au, yr[1]] if yr
947
- ti = bibdef.assoc("title")
948
- bt = bibdef.assoc("booktitle")
949
- pu = bibdef.assoc("publisher")
950
- i = bibdef.assoc("journal")
951
- if i
952
- vol = bibdef.assoc("volume")
953
- vol &&= vol[1]
954
- nr = bibdef.assoc("number")
955
- nr &&= "(" + nr[1] +")"
956
- i[1] += [" ", vol, nr].join if vol or nr
957
- elsif author and editor
958
- i = [nil, editor]
959
- t = bt || ti
960
- if t
961
- i << ": " << t[1]
962
- end
963
- end
964
- p = bibdef.assoc("pages")
965
- if i
966
- hi = "journal"
967
- elsif bt
968
- hi = "booktitle"
1258
+
1259
+ def format_bib_entry(invoker, key, bibdef)
1260
+ if bibdef.empty?
1261
+ # text = "#{key}??? (#{@deplate.msg('Unknown bib entry')})"
1262
+ text = "#{key}???"
969
1263
  else
970
- hi = "title"
1264
+ text = bib_styler.bib_format(bibdef)
971
1265
  end
972
- bb = [au, ti, bt, pu, i, p].compact.collect do |key, val|
973
- val = simple_latex_reformat(val)
974
- val = %{__#{val}__} if key == hi
975
- val
976
- end
977
- return @deplate.parse_and_format_without_wikinames(invoker, bb.join(". ") + ".")
1266
+ return @deplate.parse_and_format_without_wikinames(invoker, text)
978
1267
  end
979
1268
 
980
1269
  def simple_latex_reformat(text)
@@ -989,105 +1278,76 @@ class Deplate::Formatter
989
1278
  return text
990
1279
  end
991
1280
 
992
- def bib_entry(key)
993
- b = @bibentries[key] || []
994
- crossref = b.assoc("crossref")
995
- if crossref
996
- cb = @bibentries[crossref[1]]
997
- b += cb if cb
998
- end
999
- return b
1000
- end
1001
-
1002
- def reformat_authors(text)
1003
- if text
1004
- au = []
1005
- for a in text.split(/ and /)
1006
- m = /^((.+?)?\s+)?(\S+)$/.match(a.strip)
1007
- if m[2]
1008
- au << m[3] + ", " + m[2]
1009
- else
1010
- au << a
1011
- end
1012
- end
1013
- return au.join("; ")
1014
- end
1015
- end
1016
-
1017
- def authors_split(text)
1018
- text.split(/ and /) if text
1019
- end
1020
-
1021
-
1022
1281
  # this is the general function used for formatting lists of any kind; it
1023
1282
  # relies on #format_list, #format_indent and #format_list_item to
1024
1283
  # do the actual output
1025
1284
  def printable_list(invoker, list=nil)
1026
1285
  list ||= invoker.elt
1027
1286
  unless list.nil? or list.empty?
1028
- @levels = []
1029
- @types = []
1030
- @endTags = []
1287
+ list_tags = {
1288
+ :levels => [],
1289
+ :types => [],
1290
+ :end_tags => []
1291
+ }
1031
1292
  accum = []
1032
1293
  # level0 = list.sort {|a,b| a.level <=> b.level}[0].level
1033
- level0 = list.min {|a,b| a.level <=> b.level}.level
1294
+ level0 = list.min do |a,b|
1295
+ if a.level and b.level
1296
+ a.level <=> b.level
1297
+ elsif a
1298
+ 1
1299
+ else
1300
+ -1
1301
+ end
1302
+ end.level
1034
1303
  ind = 0
1035
1304
  max = list.size - 1
1036
1305
 
1037
1306
  list.each_with_index do |i, idx|
1038
1307
  # :listtype, :type, :level, :item, :body
1039
1308
  t = i.type
1040
- s = list_subtype(t, i.item)
1309
+ s = list_subtype(t, i)
1041
1310
  c = [i.listtype, s]
1042
1311
  l = i.level
1043
- if last_listtype
1312
+ if last_listtype(list_tags)
1313
+ special = ['Paragraph', 'Container'].include?(t)
1044
1314
  # there is a list environment, so this isn't the first item
1045
- if last_level and l != last_level
1046
- if l < last_level
1315
+ if last_level(list_tags) and l != last_level(list_tags)
1316
+ if l < last_level(list_tags)
1047
1317
  # close a nested list
1048
- ind = printable_close_lists_until(invoker, accum, ind, l)
1049
- elsif l > last_level and t != "Paragraph"
1318
+ ind = printable_close_lists_until(invoker, list_tags, accum, ind, l)
1319
+ elsif l > last_level(list_tags) and !special
1050
1320
  # open a new nested list
1051
- # p "DBG --- 1054: #{c} != #{last_listtype}"
1052
- ind = printable_open_list(invoker, accum, c, ind, l, s)
1053
- @endTags << nil
1321
+ # p "DBG --- 1054: #{c} != #{last_listtype(list_tags)}"
1322
+ ind = printable_open_list(invoker, list_tags, accum, c, ind, l, s)
1323
+ list_tags[:end_tags] << nil
1054
1324
  end
1055
1325
  end
1056
- if last_level and last_listtype and c != last_listtype and t != "Paragraph"
1057
- if l <= last_level
1326
+ if last_level(list_tags) and last_listtype(list_tags) and c != last_listtype(list_tags) and !special
1327
+ if l <= last_level(list_tags)
1058
1328
  # close the previous list and start a new one
1059
- ind = printable_list_close_endtag(invoker, accum, ind)
1060
- # p "DBG ---- #{last_listtype} #{t}"
1329
+ ind = printable_list_close_endtag(invoker, list_tags, accum, ind)
1330
+ # p "DBG ---- #{last_listtype(list_tags)} #{t}"
1061
1331
  end
1062
- if c != last_listtype and l <= last_level
1063
- # p "DBG --- 1067: #{c} != #{last_listtype}"
1064
- ind = printable_close_list(invoker, accum, ind)
1065
- ind = printable_open_list(invoker, accum, c, ind, l, s)
1066
- @endTags << nil
1332
+ if c != last_listtype(list_tags) and l <= last_level(list_tags)
1333
+ # p "DBG --- 1067: #{c} != #{last_listtype(list_tags)}"
1334
+ ind = printable_close_list(invoker, list_tags, accum, ind)
1335
+ ind = printable_open_list(invoker, list_tags, accum, c, ind, l, s)
1336
+ list_tags[:end_tags] << nil
1067
1337
  end
1068
1338
  end
1069
1339
  else
1070
1340
  # start a new list
1071
- ind = printable_open_list(invoker, accum, c, ind, l, s)
1341
+ ind = printable_open_list(invoker, list_tags, accum, c, ind, l, s)
1072
1342
  end
1073
- if @levels.empty? and idx < max
1343
+ if list_tags[:levels].empty? and idx < max
1074
1344
  # something weired happened (e.g. the previous list item was
1075
1345
  # deeper nested, but this item doesn't continue anything --
1076
1346
  # which should probably considered as a syntax error anyway)
1077
- invoker.log(["Malformed list hierarchy", last_listtype, idx], :error)
1078
- ind = printable_open_list(invoker, accum, c, ind, l, s)
1079
- end
1080
- if t == "Paragraph"
1081
- acc, etag = format_list_item(invoker, t, ind, i)
1082
- accum << acc
1083
- else
1084
- ind = printable_list_close_endtag(invoker, accum, ind)
1085
- # p "DBG #{' ' * l} Item (#{@types} #{@levels})"
1086
- acc, etag = format_list_item(invoker, t, ind, i)
1087
- @endTags << [etag, l, ind]
1088
- accum << acc
1089
- ind += 1
1347
+ invoker.log(['Malformed list hierarchy', last_listtype(list_tags), idx], :error)
1348
+ ind = printable_open_list(invoker, list_tags, accum, c, ind, l, s)
1090
1349
  end
1350
+ ind = printable_list_item(invoker, list_tags, accum, t, ind, l, i)
1091
1351
  if i.label and !i.label.empty?
1092
1352
  lab = format_label(invoker, :string, i.label)
1093
1353
  if lab
@@ -1097,100 +1357,135 @@ class Deplate::Formatter
1097
1357
  end
1098
1358
 
1099
1359
  # close all open tags & lists
1100
- while !@endTags.empty?
1101
- ind = printable_list_close_endtag(invoker, accum, ind)
1360
+ while !list_tags[:end_tags].empty?
1361
+ ind = printable_list_close_endtag(invoker, list_tags, accum, ind)
1102
1362
  end
1103
- while !@levels.empty?
1104
- ind = printable_close_list(invoker, accum, ind)
1363
+ while !list_tags[:levels].empty?
1364
+ ind = printable_close_list(invoker, list_tags, accum, ind)
1105
1365
  end
1106
1366
  if ind < 0
1107
- invoker.log("Malformed list or internal error", :error)
1367
+ invoker.log(['Malformed list or internal error', invoker.class], :error)
1108
1368
  end
1109
1369
 
1110
1370
  accum.delete_if {|e| e == :empty}
1111
- return accum.join("\n")
1371
+ return join_blocks(accum)
1112
1372
  else
1113
- return ""
1373
+ return ''
1114
1374
  end
1115
1375
  end
1116
1376
 
1117
- def last_level
1118
- @levels.last
1377
+ def last_level(list_tags)
1378
+ list_tags[:levels].last
1119
1379
  end
1120
1380
 
1121
- def last_listtype
1122
- @types.last
1381
+ def last_listtype(list_tags)
1382
+ list_tags[:types].last
1123
1383
  end
1124
1384
 
1125
- # def last_type
1126
- # @types.last
1127
- # end
1128
-
1129
- # def last_listtype
1130
- # c, s = last_type
1131
- # c
1132
- # end
1133
-
1134
- # def last_subtype
1135
- # c, s = last_type
1136
- # s
1137
- # end
1138
-
1139
1385
  def list_subtype(type, item)
1140
1386
  case type
1141
- when "Numbered"
1142
- if item =~ /^[A-Z]\.?$/
1387
+ when "Ordered"
1388
+ if item.item =~ /^[A-Z]\.?$/
1143
1389
  return "A"
1144
- elsif item =~ /^[a-z?@]\.?$/
1390
+ elsif item.item =~ /^[a-z?@]\.?$/
1145
1391
  return "a"
1146
1392
  else
1147
1393
  return "1"
1148
1394
  end
1149
- when "Itemize"
1150
- return nil
1151
- when "Description"
1152
- return nil
1153
- when "Paragraph"
1154
- return nil
1395
+ # when "Itemize"
1396
+ # return nil
1397
+ # when "Description"
1398
+ # return nil
1399
+ # when 'Task'
1400
+ # return nil
1401
+ # when "Paragraph"
1402
+ # return nil
1403
+ # when 'Container'
1404
+ # return nil
1155
1405
  else
1156
- raise "Unknown list type: #{type}"
1406
+ if item.opts and item.opts[:subtype]
1407
+ return item.opts[:subtype]
1408
+ else
1409
+ return nil
1410
+ end
1411
+ # raise "Unknown list type: #{type}"
1157
1412
  end
1158
1413
  end
1159
1414
 
1160
- def printable_close_lists_until(invoker, accum, ind, level)
1415
+ def printable_list_item(invoker, list_tags, accum, type, indentation, level, item)
1416
+ case type
1417
+ when 'Paragraph'
1418
+ args = {}
1419
+ if @list_last_type == 'Container'
1420
+ args[:follow_container] = true
1421
+ end
1422
+ acc, etag = format_list_item(invoker, type, indentation, item, args)
1423
+ accum << acc
1424
+ when 'Container'
1425
+ item_copy = item.dup
1426
+ # idt = item_copy.body.indentation
1427
+ # idt_level = item_copy.body.indentation_level
1428
+ idt_mode = invoker.args['indentation']
1429
+ if item_copy.body
1430
+ idt_mode ||= item_copy.body.class.indentation_mode.to_s
1431
+ item_copy.body = item_copy.body.format_current
1432
+ end
1433
+ case idt_mode
1434
+ when 'auto'
1435
+ item_copy.body = indent_text(item_copy.body, :mult => indentation)
1436
+ when 'none'
1437
+ else
1438
+ invoker.log(['Unknown indentation mode', idt_mode], :error)
1439
+ end
1440
+ # p "DBG #{' ' * level} Container (#{list_tags[:types]} #{@list_levels})"
1441
+ acc, etag = format_list_item(invoker, type, indentation, item_copy)
1442
+ accum << acc
1443
+ else
1444
+ indentation = printable_list_close_endtag(invoker, list_tags, accum, indentation)
1445
+ # p "DBG #{' ' * level} Item (#{list_tags[:types]} #{@list_levels})"
1446
+ acc, etag = format_list_item(invoker, type, indentation, item)
1447
+ list_tags[:end_tags] << [etag, level, indentation]
1448
+ accum << acc
1449
+ indentation += 1
1450
+ end
1451
+ @list_last_type = type
1452
+ indentation
1453
+ end
1454
+
1455
+ def printable_close_lists_until(invoker, list_tags, accum, ind, level)
1161
1456
  begin
1162
- ind = printable_list_close_endtag(invoker, accum, ind)
1163
- ind = printable_close_list(invoker, accum, ind)
1164
- end until @levels.empty? or @levels.last <= level
1457
+ ind = printable_list_close_endtag(invoker, list_tags, accum, ind)
1458
+ ind = printable_close_list(invoker, list_tags, accum, ind)
1459
+ end until list_tags[:levels].empty? or list_tags[:levels].last <= level
1165
1460
  ind
1166
1461
  end
1167
1462
 
1168
- def printable_close_list(invoker, accum, ind)
1463
+ def printable_close_list(invoker, list_tags, accum, ind)
1169
1464
  ind -= 1
1170
- lev = @levels.pop
1171
- tp, sp = @types.pop
1465
+ lev = list_tags[:levels].pop
1466
+ tp, sp = list_tags[:types].pop
1172
1467
  # p "DBG #{' ' * (lev || 1)}>close #{lev} #{tp} #{sp} #{caller[0]}"
1173
1468
  le = format_list_env(invoker, tp, ind, :close, sp)
1174
1469
  accum << le if le
1175
1470
  ind
1176
1471
  end
1177
1472
 
1178
- def printable_open_list(invoker, accum, type, ind, level, subtype=nil)
1473
+ def printable_open_list(invoker, list_tags, accum, type, ind, level, subtype=nil)
1179
1474
  t, s = type
1180
1475
  le = format_list_env(invoker, t, ind, :open, subtype)
1181
1476
  accum << le if le
1182
1477
  ind += 1
1183
- @levels << level
1184
- @types << type
1478
+ list_tags[:levels] << level
1479
+ list_tags[:types] << type
1185
1480
  # p "DBG #{' ' * (level || 1)}<open #{level} #{type} #{subtype} #{caller[0]}"
1186
1481
  ind
1187
1482
  end
1188
1483
 
1189
- def printable_list_close_endtag(invoker, accum, ind)
1190
- tag, level, ind0 = @endTags.pop
1484
+ def printable_list_close_endtag(invoker, list_tags, accum, ind)
1485
+ tag, level, ind0 = list_tags[:end_tags].pop
1191
1486
  if tag
1192
- while @levels.last and @levels.last > level
1193
- ind = printable_close_list(invoker, accum, ind)
1487
+ while list_tags[:levels].last and list_tags[:levels].last > level
1488
+ ind = printable_close_list(invoker, list_tags, accum, ind)
1194
1489
  end
1195
1490
  accum << tag unless tag == :none
1196
1491
  end
@@ -1206,5 +1501,22 @@ class Deplate::Formatter
1206
1501
  nil
1207
1502
  end
1208
1503
  end
1504
+
1505
+ def use_image_filename(filename, args={})
1506
+ unless args['noGuess'] or args[:raw]
1507
+ fext = File.extname(filename)
1508
+ fname = fext.empty? ? filename : filename[0..(-1 - fext.size)]
1509
+ for sfx in image_suffixes
1510
+ fs = [fname, sfx].join
1511
+ ff = @deplate.auxiliary_filename(fs)
1512
+ fff = @deplate.auxiliary_filename(fs, true)
1513
+ if File.exist?(fff)
1514
+ return ff
1515
+ end
1516
+ end
1517
+ end
1518
+ return filename
1519
+ end
1520
+
1209
1521
  end
1210
1522