deplate 0.7.3
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.
- data/AUTHORS.TXT +26 -0
- data/CHANGES.TXT +177 -0
- data/LICENSE.TXT +340 -0
- data/NEWS.TXT +29 -0
- data/README.TXT +86 -0
- data/TODO.TXT +202 -0
- data/VERSION.TXT +1 -0
- data/bin/deplate +3 -0
- data/bin/deplate.bat +2 -0
- data/etc/deplate.ini +361 -0
- data/lib/deplate.rb +31 -0
- data/lib/deplate/abstract-class.rb +30 -0
- data/lib/deplate/builtin.rb +11 -0
- data/lib/deplate/cache.rb +59 -0
- data/lib/deplate/commands.rb +693 -0
- data/lib/deplate/common.rb +335 -0
- data/lib/deplate/converter.rb +99 -0
- data/lib/deplate/core.rb +2705 -0
- data/lib/deplate/css/article.css +545 -0
- data/lib/deplate/css/deplate.css +699 -0
- data/lib/deplate/css/heading-navbar.css +29 -0
- data/lib/deplate/css/layout-deplate-print.css +540 -0
- data/lib/deplate/css/layout-deplate.css +764 -0
- data/lib/deplate/css/sans-serif.css +160 -0
- data/lib/deplate/css/serif-e.css +170 -0
- data/lib/deplate/css/serif-rel.css +121 -0
- data/lib/deplate/css/serif.css +190 -0
- data/lib/deplate/css/slides.css +11 -0
- data/lib/deplate/css/tabbar-left.css +91 -0
- data/lib/deplate/css/tabbar-right-ie.css +14 -0
- data/lib/deplate/css/tabbar-right.css +118 -0
- data/lib/deplate/css/tabbar-top.css +64 -0
- data/lib/deplate/css/tabbar.css +81 -0
- data/lib/deplate/css/text-sans-serif.css +154 -0
- data/lib/deplate/css/text-serif.css +175 -0
- data/lib/deplate/define.rb +439 -0
- data/lib/deplate/docbook.rb +738 -0
- data/lib/deplate/elements.rb +1355 -0
- data/lib/deplate/etc.rb +199 -0
- data/lib/deplate/external.rb +135 -0
- data/lib/deplate/fmt/dbk-article-4.1.2.rb +21 -0
- data/lib/deplate/fmt/dbk-article.rb +46 -0
- data/lib/deplate/fmt/dbk-book.rb +46 -0
- data/lib/deplate/fmt/dbk-ref.rb +105 -0
- data/lib/deplate/fmt/dbk-slides.rb +47 -0
- data/lib/deplate/fmt/dbk-snippet.rb +21 -0
- data/lib/deplate/fmt/html-snippet.rb +21 -0
- data/lib/deplate/fmt/html.rb +1696 -0
- data/lib/deplate/fmt/htmlsite.rb +419 -0
- data/lib/deplate/fmt/htmlslides.rb +21 -0
- data/lib/deplate/fmt/htmlwebsite.rb +70 -0
- data/lib/deplate/fmt/latex-snippet.rb +22 -0
- data/lib/deplate/fmt/latex.rb +1242 -0
- data/lib/deplate/fmt/php.rb +19 -0
- data/lib/deplate/fmt/phpsite.rb +19 -0
- data/lib/deplate/fmt/plain.rb +598 -0
- data/lib/deplate/fmt/template.rb +34 -0
- data/lib/deplate/fmt/xhtml10t.rb +41 -0
- data/lib/deplate/formatter-snippet.rb +17 -0
- data/lib/deplate/formatter.rb +1210 -0
- data/lib/deplate/input.rb +492 -0
- data/lib/deplate/input/deplate-headings.rb +48 -0
- data/lib/deplate/input/deplate-restricted.rb +70 -0
- data/lib/deplate/input/deplate.rb +28 -0
- data/lib/deplate/input/rdoc.rb +277 -0
- data/lib/deplate/input/template.rb +29 -0
- data/lib/deplate/lib/latex/highlight-extra.sty +15 -0
- data/lib/deplate/lib/latex/highlight-typical.sty +15 -0
- data/lib/deplate/lib/tabmenu.js +146 -0
- data/lib/deplate/locale/de.latin1 +708 -0
- data/lib/deplate/locale/ru.koi8-r +48 -0
- data/lib/deplate/locale/zh_cn.gb2312 +35 -0
- data/lib/deplate/macros.rb +639 -0
- data/lib/deplate/messages.rb +120 -0
- data/lib/deplate/metadata.rb +77 -0
- data/lib/deplate/metadata/marshal.rb +24 -0
- data/lib/deplate/metadata/xml.rb +42 -0
- data/lib/deplate/metadata/yaml.rb +26 -0
- data/lib/deplate/mod/anyword.rb +56 -0
- data/lib/deplate/mod/babelfish.rb +27 -0
- data/lib/deplate/mod/code-gvim.rb +52 -0
- data/lib/deplate/mod/code-highlight.rb +91 -0
- data/lib/deplate/mod/colored-log.rb +17 -0
- data/lib/deplate/mod/de.rb +19 -0
- data/lib/deplate/mod/en.rb +17 -0
- data/lib/deplate/mod/endnotes.rb +60 -0
- data/lib/deplate/mod/fr.rb +46 -0
- data/lib/deplate/mod/html-asciimath.rb +40 -0
- data/lib/deplate/mod/html-deplate-button.rb +15 -0
- data/lib/deplate/mod/html-headings-navbar.rb +39 -0
- data/lib/deplate/mod/html-obfuscate-email.rb +47 -0
- data/lib/deplate/mod/html-sidebar.rb +232 -0
- data/lib/deplate/mod/htmlslides-navbar-fh.rb +32 -0
- data/lib/deplate/mod/iconv.rb +35 -0
- data/lib/deplate/mod/imgurl.rb +30 -0
- data/lib/deplate/mod/inlatex-compound.rb +69 -0
- data/lib/deplate/mod/koma.rb +109 -0
- data/lib/deplate/mod/latex-emph-table-head.rb +38 -0
- data/lib/deplate/mod/latex-styles.rb +461 -0
- data/lib/deplate/mod/latex-verbatim-small.rb +29 -0
- data/lib/deplate/mod/makefile.rb +194 -0
- data/lib/deplate/mod/mark-external-urls.rb +38 -0
- data/lib/deplate/mod/markup-1-warn.rb +37 -0
- data/lib/deplate/mod/markup-1.rb +41 -0
- data/lib/deplate/mod/navbar-png.rb +33 -0
- data/lib/deplate/mod/noindent.rb +32 -0
- data/lib/deplate/mod/numpara.rb +40 -0
- data/lib/deplate/mod/particle-math.rb +34 -0
- data/lib/deplate/mod/php-extra.rb +44 -0
- data/lib/deplate/mod/pstoedit.rb +71 -0
- data/lib/deplate/mod/recode.rb +57 -0
- data/lib/deplate/mod/ru_koi8-r.rb +20 -0
- data/lib/deplate/mod/smiley.rb +50 -0
- data/lib/deplate/mod/soffice.rb +23 -0
- data/lib/deplate/mod/symbols-latin1.rb +58 -0
- data/lib/deplate/mod/symbols-od-utf-8.rb +16 -0
- data/lib/deplate/mod/symbols-plain.rb +58 -0
- data/lib/deplate/mod/symbols-sgml.rb +97 -0
- data/lib/deplate/mod/symbols-utf-8.rb +81 -0
- data/lib/deplate/mod/symbols-xml.rb +34 -0
- data/lib/deplate/mod/syntax-region-alt.rb +37 -0
- data/lib/deplate/mod/utf8.rb +49 -0
- data/lib/deplate/mod/validate-html.rb +35 -0
- data/lib/deplate/mod/xmlrpc.rb +233 -0
- data/lib/deplate/mod/zh-cn-autospace.rb +108 -0
- data/lib/deplate/mod/zh-cn.rb +59 -0
- data/lib/deplate/once-method.rb +44 -0
- data/lib/deplate/output.rb +249 -0
- data/lib/deplate/particles.rb +815 -0
- data/lib/deplate/regions.rb +1076 -0
- data/lib/deplate/structured.rb +763 -0
- data/lib/deplate/template.rb +430 -0
- data/lib/deplate/templates/html-doc.html +28 -0
- data/lib/deplate/templates/html-left-tabbar-js.html +37 -0
- data/lib/deplate/templates/html-left-tabbar.html +31 -0
- data/lib/deplate/templates/html-tabbar-right-table.html +43 -0
- data/lib/deplate/templates/html-tabbar-right.html +23 -0
- data/lib/deplate/templates/html-tabbar-top.html +43 -0
- data/lib/deplate/templates/html-tabbar.html +31 -0
- data/lib/deplate/wiki-markup.rb +117 -0
- data/lib/deplate/xml.rb +109 -0
- data/lib/deplate/zh-cn.rb +59 -0
- data/lib/ps2ppm.rb +239 -0
- data/man/man1/deplate.1 +692 -0
- metadata +210 -0
|
@@ -0,0 +1,1355 @@
|
|
|
1
|
+
# elements.rb
|
|
2
|
+
# @Author: Thomas Link (samul AT web.de)
|
|
3
|
+
# @Website: http://deplate.sf.net/
|
|
4
|
+
# @License: GPL (see http://www.gnu.org/licenses/gpl.txt)
|
|
5
|
+
# @Created: 26-M�r-2004.
|
|
6
|
+
# @Last Change: 02-Nov-2005.
|
|
7
|
+
# @Revision: 0.3718
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class Deplate::DontFormatException < Exception
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
Deplate::CaptionDef = Struct.new('DeplateCaptionDef', :elt, :args)
|
|
14
|
+
|
|
15
|
+
# Deplate::Elements are text entities at line or paragraph level.
|
|
16
|
+
class Deplate::Element < Deplate::BaseElement
|
|
17
|
+
@@elements = []
|
|
18
|
+
|
|
19
|
+
@@accumulate_pre = {}
|
|
20
|
+
@@accumulate_post = {}
|
|
21
|
+
|
|
22
|
+
#### attached labels
|
|
23
|
+
attr_accessor :label
|
|
24
|
+
#### an attached caption (for Table etc.)
|
|
25
|
+
attr_accessor :caption, :captionOptions
|
|
26
|
+
#### is this element in one-line format?
|
|
27
|
+
attr_accessor :multiliner
|
|
28
|
+
#### end pattern
|
|
29
|
+
attr_reader :endRx
|
|
30
|
+
#### the element's level of indentation or whatever
|
|
31
|
+
attr_accessor :level_heading, :top_heading_idx
|
|
32
|
+
#### an array of deferred formatting blocks
|
|
33
|
+
attr_accessor :postponed_format, :postponed_preformat
|
|
34
|
+
#### whether we can collapse this element with another one
|
|
35
|
+
attr_accessor :collapse
|
|
36
|
+
#### postponed registration of metadata
|
|
37
|
+
attr_accessor :registered_metadata
|
|
38
|
+
|
|
39
|
+
attr_reader :line_cont
|
|
40
|
+
|
|
41
|
+
# class methods & variables
|
|
42
|
+
class << self
|
|
43
|
+
# the regular expression for this class
|
|
44
|
+
attr_reader :rx
|
|
45
|
+
attr_reader :labelling
|
|
46
|
+
|
|
47
|
+
def match(text)
|
|
48
|
+
return @rx.match(text)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def elements
|
|
52
|
+
return @@elements
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def is_volatile?(match)
|
|
56
|
+
false
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def register_element(c=self)
|
|
60
|
+
@@elements << c
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def set_labelling(val=true)
|
|
64
|
+
@labelling = val
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def set_name(name)
|
|
68
|
+
@name=name
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def accumulate(src, array, deplate, text, match, *args)
|
|
72
|
+
Deplate::Core.log(["New element", self.name, text], :debug)
|
|
73
|
+
e = self.new(deplate, src, text, match, *args)
|
|
74
|
+
if e
|
|
75
|
+
array << e
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def accumulate_pre(klass, format, &block)
|
|
80
|
+
hooks = @@accumulate_pre[klass] || {}
|
|
81
|
+
pre = hooks[format] || []
|
|
82
|
+
hooks[format] = pre << block
|
|
83
|
+
@@accumulate_pre[klass] = hooks
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def accumulate_post(klass, format, &block)
|
|
87
|
+
hooks = @@accumulate_post[klass] || {}
|
|
88
|
+
post = hooks[format] || []
|
|
89
|
+
hooks[format] = post << block
|
|
90
|
+
@@accumulate_post[klass] = hooks
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def do_accumulate(src, array, deplate, *args)
|
|
94
|
+
run_accumulation_hooks(@@accumulate_pre[self], src, array, deplate, *args)
|
|
95
|
+
accumulate(src, array, deplate, *args)
|
|
96
|
+
run_accumulation_hooks(@@accumulate_post[self], src, array, deplate, *args)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def run_accumulation_hooks(all_hooks, src, array, deplate, *args)
|
|
100
|
+
if all_hooks
|
|
101
|
+
klass = deplate.formatter.class
|
|
102
|
+
begin
|
|
103
|
+
hooks = all_hooks[klass]
|
|
104
|
+
if hooks
|
|
105
|
+
for block in hooks
|
|
106
|
+
block.call(src, array, deplate, *args)
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
klass = klass.superclass
|
|
110
|
+
end until klass === Module
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def get_date(arg, args)
|
|
115
|
+
case arg
|
|
116
|
+
when "now"
|
|
117
|
+
return Time.new.asctime
|
|
118
|
+
when "time"
|
|
119
|
+
return Time.new.strftime("%X")
|
|
120
|
+
when "today"
|
|
121
|
+
return Time.new.strftime("%d. %b %Y")
|
|
122
|
+
when "month"
|
|
123
|
+
return Time.new.strftime("%B %Y")
|
|
124
|
+
when "year"
|
|
125
|
+
return Time.new.strftime("%Y")
|
|
126
|
+
when "", nil
|
|
127
|
+
return ""
|
|
128
|
+
else
|
|
129
|
+
return Time.new.strftime(arg)
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def initialize(deplate, src, text, match, *args)
|
|
135
|
+
super(deplate)
|
|
136
|
+
@source = src
|
|
137
|
+
@text = text
|
|
138
|
+
@match = match
|
|
139
|
+
@endRx = nil
|
|
140
|
+
@fmx = nil
|
|
141
|
+
@label = []
|
|
142
|
+
@collapse = nil
|
|
143
|
+
@caption = nil
|
|
144
|
+
@container = nil
|
|
145
|
+
@line_cont = true
|
|
146
|
+
@postponed_format = []
|
|
147
|
+
@postponed_preformat = []
|
|
148
|
+
@registered_metadata = []
|
|
149
|
+
|
|
150
|
+
set_instance_top
|
|
151
|
+
|
|
152
|
+
@deplate.call_methods_matching(self, /^hook_pre_setup_/)
|
|
153
|
+
setup(*args)
|
|
154
|
+
@deplate.call_methods_matching(self, /^hook_post_setup_/)
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def set_instance_top
|
|
158
|
+
@top_heading_idx = @deplate.top_heading_idx
|
|
159
|
+
@top_heading = @deplate.top_heading_by_idx(@top_heading_idx)
|
|
160
|
+
@level_heading = @deplate.current_heading.dup
|
|
161
|
+
self.level_as_string = @deplate.get_current_heading
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def setup
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def level_as_string
|
|
168
|
+
@level_as_string
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def level_as_string=(val)
|
|
172
|
+
@args[:level_as_string] = val
|
|
173
|
+
@level_as_string = val
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
def put_label(lab, anyway=false)
|
|
177
|
+
if lab
|
|
178
|
+
for l in lab.compact
|
|
179
|
+
# or @deplate.label_aliases.include?(l)
|
|
180
|
+
unless @label.include?(l)
|
|
181
|
+
@label << l
|
|
182
|
+
@deplate.add_label(self, l, @level_as_string, :anyway => anyway)
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
def collapsable?(other)
|
|
189
|
+
return @collapse && other.collapse && self.class == other.class
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
def drop?
|
|
193
|
+
return @collapse == :drop
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
def unify(other)
|
|
197
|
+
if other.drop?
|
|
198
|
+
other.container = self
|
|
199
|
+
return true
|
|
200
|
+
elsif collapsable?(other)
|
|
201
|
+
unify_now(other)
|
|
202
|
+
other.container = self
|
|
203
|
+
return true
|
|
204
|
+
else
|
|
205
|
+
return false
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
def <<(line)
|
|
210
|
+
@accum << line
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
def to_be_continued?(line)
|
|
214
|
+
return @multiliner
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
# compile the accumulated lines in @accum & put the result into @elt
|
|
218
|
+
def finish
|
|
219
|
+
elt = join_lines(@accum)
|
|
220
|
+
@elt = [ @deplate.parse(self, elt) ]
|
|
221
|
+
return self
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
def finished?
|
|
225
|
+
return defined?(@elt) && @elt != nil
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
def join_lines(accum)
|
|
229
|
+
if @deplate.options.keep_whitespace
|
|
230
|
+
return accum.join("\n")
|
|
231
|
+
else
|
|
232
|
+
return accum.join(" ")
|
|
233
|
+
end
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
def process
|
|
237
|
+
process_etc
|
|
238
|
+
process_particles do |e|
|
|
239
|
+
if e.kind_of?(String)
|
|
240
|
+
### <+TBD+> This actually is more of an error and shouldn't be
|
|
241
|
+
e
|
|
242
|
+
else
|
|
243
|
+
rv = e.collect do |p|
|
|
244
|
+
# <+TBD+> begin
|
|
245
|
+
# p.container = self
|
|
246
|
+
p.process
|
|
247
|
+
# rescue Exception => e
|
|
248
|
+
# puts e.backtrace.join("\n")
|
|
249
|
+
# raise
|
|
250
|
+
# end
|
|
251
|
+
p.elt
|
|
252
|
+
end
|
|
253
|
+
@deplate.join_particles(rv)
|
|
254
|
+
end
|
|
255
|
+
end
|
|
256
|
+
return self
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
def print
|
|
260
|
+
unless @args['swallow']
|
|
261
|
+
for block in @postponed_preformat
|
|
262
|
+
block.call(self)
|
|
263
|
+
end
|
|
264
|
+
output(format_current)
|
|
265
|
+
for block in @postponed_format
|
|
266
|
+
block.call(self)
|
|
267
|
+
end
|
|
268
|
+
end
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
def format_current(formatting_method=nil)
|
|
272
|
+
formatting_method ||= self.class.formatter
|
|
273
|
+
if formatting_method
|
|
274
|
+
elt = format_element(formatting_method, self)
|
|
275
|
+
elsif self.respond_to?(:format_special)
|
|
276
|
+
elt = format_special
|
|
277
|
+
else
|
|
278
|
+
elt = @deplate.formatter.format_unknown(self)
|
|
279
|
+
end
|
|
280
|
+
if elt
|
|
281
|
+
acc = []
|
|
282
|
+
acc << format_prologue
|
|
283
|
+
acc << elt
|
|
284
|
+
acc << format_epilogue
|
|
285
|
+
label_accum(acc, formatting_method) if doc_type == :body
|
|
286
|
+
rv = @deplate.formatter.join_blocks(acc.compact)
|
|
287
|
+
else
|
|
288
|
+
rv = nil
|
|
289
|
+
end
|
|
290
|
+
register_metadata
|
|
291
|
+
return rv
|
|
292
|
+
# rescue Exception => e
|
|
293
|
+
# log(["Formatting failed", self.class.name, e], :error)
|
|
294
|
+
# format_element(:format_unknown, self)
|
|
295
|
+
# end
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
def register_metadata
|
|
299
|
+
@deplate.output.merge_metadata(@registered_metadata)
|
|
300
|
+
for l in @label
|
|
301
|
+
m = @deplate.get_metadata(@source,
|
|
302
|
+
'type' => 'label',
|
|
303
|
+
'name' => l
|
|
304
|
+
)
|
|
305
|
+
@deplate.output.push_metadata(m)
|
|
306
|
+
end
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
def label_accum(out, formatting_method)
|
|
310
|
+
fmt = @deplate.formatter
|
|
311
|
+
if fmt.label_once.include?(formatting_method)
|
|
312
|
+
l = format_element(:format_label, self, :once)
|
|
313
|
+
out.unshift(l) unless l.empty?
|
|
314
|
+
elsif fmt.label_delegate.include?(formatting_method)
|
|
315
|
+
else
|
|
316
|
+
case label_mode || fmt.label_mode
|
|
317
|
+
when :once
|
|
318
|
+
l = format_element(:format_label, self, :once)
|
|
319
|
+
out.unshift(l) unless l.empty?
|
|
320
|
+
when :before
|
|
321
|
+
l = format_element(:format_label, self, :before)
|
|
322
|
+
out.unshift(l) unless l.empty?
|
|
323
|
+
when :after
|
|
324
|
+
l = format_element(:format_label, self, :after)
|
|
325
|
+
out.push(l) unless l.empty?
|
|
326
|
+
when :delegate, :self
|
|
327
|
+
else
|
|
328
|
+
lb = format_element(:format_label, self, :before)
|
|
329
|
+
la = format_element(:format_label, self, :after)
|
|
330
|
+
out.unshift(lb) unless lb.empty?
|
|
331
|
+
out.push(la) unless la.empty?
|
|
332
|
+
end
|
|
333
|
+
end
|
|
334
|
+
end
|
|
335
|
+
|
|
336
|
+
def format_prologue
|
|
337
|
+
@prologue.empty? ? nil : @prologue
|
|
338
|
+
end
|
|
339
|
+
|
|
340
|
+
def format_epilogue
|
|
341
|
+
@epilogue.empty? ? nil : @epilogue
|
|
342
|
+
end
|
|
343
|
+
|
|
344
|
+
def destination
|
|
345
|
+
if @top_heading and @top_heading != self
|
|
346
|
+
@top_heading.destination
|
|
347
|
+
else
|
|
348
|
+
@destination
|
|
349
|
+
end
|
|
350
|
+
end
|
|
351
|
+
|
|
352
|
+
def register_caption
|
|
353
|
+
log(["Can't attach caption to", self.class.name], :error)
|
|
354
|
+
end
|
|
355
|
+
|
|
356
|
+
def to_plain_text
|
|
357
|
+
@accum.join("\n")
|
|
358
|
+
end
|
|
359
|
+
|
|
360
|
+
protected
|
|
361
|
+
def process_etc
|
|
362
|
+
if !@caption and @args["caption"]
|
|
363
|
+
caption = @deplate.parse(self, @args["caption"])
|
|
364
|
+
@caption = Deplate::CaptionDef.new(caption, @args)
|
|
365
|
+
end
|
|
366
|
+
if defined?(@caption) && @caption
|
|
367
|
+
elt = @caption.elt.collect {|p| p.process; p.elt}
|
|
368
|
+
@caption.elt = @deplate.join_particles(elt)
|
|
369
|
+
end
|
|
370
|
+
end
|
|
371
|
+
alias process_options process_etc
|
|
372
|
+
|
|
373
|
+
def unify_now(other)
|
|
374
|
+
unify_elt(other)
|
|
375
|
+
unify_props(other)
|
|
376
|
+
end
|
|
377
|
+
|
|
378
|
+
def unify_props(other)
|
|
379
|
+
put_label(other.label, true)
|
|
380
|
+
@args.update(other.args)
|
|
381
|
+
@level ||= other.level
|
|
382
|
+
@caption ||= other.caption
|
|
383
|
+
@captionOptions ||= other.captionOptions
|
|
384
|
+
@source.begin ||= other.source.begin
|
|
385
|
+
@source.end = other.source.end if other.source.end
|
|
386
|
+
if other.styles
|
|
387
|
+
update_styles(other.styles)
|
|
388
|
+
end
|
|
389
|
+
if !level_as_string and other.level_as_string
|
|
390
|
+
self.level_as_string = other.level_as_string
|
|
391
|
+
end
|
|
392
|
+
end
|
|
393
|
+
|
|
394
|
+
def unify_elt(other)
|
|
395
|
+
if @elt.nil?
|
|
396
|
+
@elt = other.elt
|
|
397
|
+
elsif !other.elt.nil?
|
|
398
|
+
@elt += other.elt
|
|
399
|
+
end
|
|
400
|
+
end
|
|
401
|
+
|
|
402
|
+
def container=(element)
|
|
403
|
+
@container = element
|
|
404
|
+
@args = element.args
|
|
405
|
+
@postponed_format = element.postponed_format
|
|
406
|
+
@postponed_preformat = element.postponed_preformat
|
|
407
|
+
end
|
|
408
|
+
|
|
409
|
+
def get_indent(text)
|
|
410
|
+
text = expand_tab(text)
|
|
411
|
+
/^\s*/.match(text)[0]
|
|
412
|
+
end
|
|
413
|
+
|
|
414
|
+
def expand_tab(text)
|
|
415
|
+
tabwidth = @deplate.variables['tabwidth'] || 4
|
|
416
|
+
accum = []
|
|
417
|
+
loop do
|
|
418
|
+
m = /\t/.match(text)
|
|
419
|
+
if m
|
|
420
|
+
pre = m.pre_match
|
|
421
|
+
text = m.post_match
|
|
422
|
+
add = tabwidth - pre.size % tabwidth
|
|
423
|
+
accum << pre + (" " * add)
|
|
424
|
+
else
|
|
425
|
+
return accum.join + text
|
|
426
|
+
end
|
|
427
|
+
end
|
|
428
|
+
return text
|
|
429
|
+
end
|
|
430
|
+
|
|
431
|
+
# call block on all text particles in the current element
|
|
432
|
+
def process_particles(&block)
|
|
433
|
+
if @elt
|
|
434
|
+
@elt = (@elt.collect(&block)).join
|
|
435
|
+
else
|
|
436
|
+
log(["Internal error: no @elt", self.class], :error)
|
|
437
|
+
@elt = ""
|
|
438
|
+
end
|
|
439
|
+
end
|
|
440
|
+
alias process_elements process_particles
|
|
441
|
+
|
|
442
|
+
def register_figure
|
|
443
|
+
@deplate.table_of_figures << self
|
|
444
|
+
@deplate.current_figure += 1
|
|
445
|
+
@level_as_string = [@deplate.current_heading[0], @deplate.current_figure].join(".")
|
|
446
|
+
@label << @deplate.elt_label("fig", @level_as_string)
|
|
447
|
+
end
|
|
448
|
+
|
|
449
|
+
def register_table
|
|
450
|
+
@deplate.table_of_tables << self
|
|
451
|
+
@deplate.current_table += 1
|
|
452
|
+
@level_as_string = [@deplate.current_heading[0], @deplate.current_table].join(".")
|
|
453
|
+
@label << @deplate.elt_label("tab", @level_as_string)
|
|
454
|
+
end
|
|
455
|
+
end
|
|
456
|
+
|
|
457
|
+
class Deplate::Element::Comment < Deplate::Element
|
|
458
|
+
register_element
|
|
459
|
+
set_rx(/^\s*(%+)[ \t]*(.*)$/)
|
|
460
|
+
|
|
461
|
+
# disappear
|
|
462
|
+
def self.accumulate(src, array, deplate, text, match)
|
|
463
|
+
Deplate::Core.log(["Hide comment", text], :debug)
|
|
464
|
+
end
|
|
465
|
+
|
|
466
|
+
def setup
|
|
467
|
+
@multiliner = false
|
|
468
|
+
@collapse = true
|
|
469
|
+
@level = get_level
|
|
470
|
+
@accum = [get_text]
|
|
471
|
+
end
|
|
472
|
+
|
|
473
|
+
def get_level
|
|
474
|
+
@match[1].size
|
|
475
|
+
end
|
|
476
|
+
|
|
477
|
+
def get_text
|
|
478
|
+
@match[2]
|
|
479
|
+
end
|
|
480
|
+
end
|
|
481
|
+
|
|
482
|
+
class Deplate::Element::Region < Deplate::Element
|
|
483
|
+
register_element
|
|
484
|
+
set_rx(/^(\s*)#([A-Z]([a-z][A-Za-z]*)?)\b(.*)(\<\<(.+)|:)\s*$/)
|
|
485
|
+
@rxi_name = 2
|
|
486
|
+
@rxi_args = 4
|
|
487
|
+
@rxi_endrx = 6
|
|
488
|
+
@rxi_indent = 1
|
|
489
|
+
|
|
490
|
+
attr_reader :specified, :regNote, :name
|
|
491
|
+
|
|
492
|
+
class << self
|
|
493
|
+
attr_reader :rxi_name, :rxi_args, :rxi_endrx, :rxi_indent
|
|
494
|
+
|
|
495
|
+
def pseudo_match(args)
|
|
496
|
+
[
|
|
497
|
+
nil,
|
|
498
|
+
args[:indent], #1
|
|
499
|
+
args[:name], #2
|
|
500
|
+
nil, #3
|
|
501
|
+
args[:args], #4
|
|
502
|
+
nil, #5
|
|
503
|
+
args[:endrx], #6
|
|
504
|
+
]
|
|
505
|
+
end
|
|
506
|
+
end
|
|
507
|
+
|
|
508
|
+
def setup(name=nil)
|
|
509
|
+
@multiliner = true
|
|
510
|
+
@endRx = get_endrx
|
|
511
|
+
@accum = []
|
|
512
|
+
@name = name || get_name
|
|
513
|
+
begin
|
|
514
|
+
@args, @regNote = @deplate.input.parse_args(get_args)
|
|
515
|
+
@collapse = false
|
|
516
|
+
region = @deplate.input.regions[@name]
|
|
517
|
+
unless region
|
|
518
|
+
if @deplate.formatter.matches?(@name)
|
|
519
|
+
Deplate::Core.log(["Obsolete use of native regions. Please use", "#Native fmt=#{@deplate.formatter.formatter_name}"], :error, @source)
|
|
520
|
+
else
|
|
521
|
+
# We put a message to notify the user of an ignored class
|
|
522
|
+
# This should be a native class for an unused formatter
|
|
523
|
+
Deplate::Core.log(["Unknown region class", @name], :error, @source)
|
|
524
|
+
end
|
|
525
|
+
region = Deplate::Regions::UNKNOWN
|
|
526
|
+
end
|
|
527
|
+
rescue Deplate::DontFormatException
|
|
528
|
+
Deplate::Core.log(["Dropping", @match[0]], nil, @source)
|
|
529
|
+
region = Deplate::Regions::UNKNOWN
|
|
530
|
+
end
|
|
531
|
+
@specified = region.new(@deplate, @source, @text, @match, self)
|
|
532
|
+
@specified.indent = get_indent
|
|
533
|
+
@line_cont = region.line_cont
|
|
534
|
+
# @deplate.register_id(@args, @specified)
|
|
535
|
+
@deplate.register_id(@args, self)
|
|
536
|
+
end
|
|
537
|
+
|
|
538
|
+
def get_name
|
|
539
|
+
@match[self.class.rxi_name]
|
|
540
|
+
end
|
|
541
|
+
|
|
542
|
+
def get_args
|
|
543
|
+
@match[self.class.rxi_args]
|
|
544
|
+
end
|
|
545
|
+
|
|
546
|
+
def get_endrx
|
|
547
|
+
i = self.class.rxi_endrx
|
|
548
|
+
if @match[i - 1] == ":"
|
|
549
|
+
/^(#{get_indent})?#End\s*$/
|
|
550
|
+
else
|
|
551
|
+
erx = @match[i]
|
|
552
|
+
if erx
|
|
553
|
+
/^(#{get_indent})?#{Regexp.escape(erx)}\s*$/
|
|
554
|
+
end
|
|
555
|
+
end
|
|
556
|
+
end
|
|
557
|
+
|
|
558
|
+
def get_indent
|
|
559
|
+
@match[self.class.rxi_indent]
|
|
560
|
+
end
|
|
561
|
+
|
|
562
|
+
def finish
|
|
563
|
+
return @specified.finish
|
|
564
|
+
end
|
|
565
|
+
end
|
|
566
|
+
|
|
567
|
+
class Deplate::Element::Clip < Deplate::BaseElement
|
|
568
|
+
attr_reader :is_template
|
|
569
|
+
# attr_accessor :prototype
|
|
570
|
+
|
|
571
|
+
def initialize(acc, deplate, source)
|
|
572
|
+
super(deplate)
|
|
573
|
+
@acc = acc
|
|
574
|
+
@elt = nil
|
|
575
|
+
@source = source
|
|
576
|
+
@invoker = nil
|
|
577
|
+
@is_template = false
|
|
578
|
+
@prototype = nil
|
|
579
|
+
end
|
|
580
|
+
|
|
581
|
+
def process
|
|
582
|
+
unless @prototype
|
|
583
|
+
@prototype = @acc.first
|
|
584
|
+
@prototype.args.update(@args) if @prototype
|
|
585
|
+
end
|
|
586
|
+
unless @elt
|
|
587
|
+
@elt = @acc.collect{|p| p.process; p.elt}
|
|
588
|
+
@elt = @deplate.join_particles(@elt)
|
|
589
|
+
end
|
|
590
|
+
return self
|
|
591
|
+
end
|
|
592
|
+
|
|
593
|
+
def format_clip(invoker, expected)
|
|
594
|
+
unless @elt
|
|
595
|
+
log("We shouldn't be here. If you can track down when this happens, please send an example to the author.", :anyway)
|
|
596
|
+
process
|
|
597
|
+
end
|
|
598
|
+
if @elt
|
|
599
|
+
@prototype.match_expected(expected, invoker)
|
|
600
|
+
else
|
|
601
|
+
log("Clip is nil, which is quite strange and most likely deplate's error but as I haven't had the time yet to track this down this error still occurs.", :error)
|
|
602
|
+
end
|
|
603
|
+
@elt
|
|
604
|
+
end
|
|
605
|
+
|
|
606
|
+
def print
|
|
607
|
+
output(@elt)
|
|
608
|
+
end
|
|
609
|
+
end
|
|
610
|
+
|
|
611
|
+
class Deplate::Element::Command < Deplate::Element
|
|
612
|
+
register_element
|
|
613
|
+
set_rx /^\s*#([A-Z]+)((\s[^:]+)?(:\s*(.+?)\s*)?)$/
|
|
614
|
+
attr :name
|
|
615
|
+
|
|
616
|
+
class << self
|
|
617
|
+
def is_volatile?(match)
|
|
618
|
+
case match[1]
|
|
619
|
+
when "IDX", "NOIDX", "DONTIDX", "AUTOIDX", "DOC", "OPT", "AUTHOR",
|
|
620
|
+
"TITLE", "DATE", "ABBREV"
|
|
621
|
+
true
|
|
622
|
+
else
|
|
623
|
+
false
|
|
624
|
+
end
|
|
625
|
+
end
|
|
626
|
+
|
|
627
|
+
def accumulate(src, array, deplate, text, match)
|
|
628
|
+
cmd = match[1]
|
|
629
|
+
Deplate::Core.log(["Command", cmd, text], :debug)
|
|
630
|
+
begin
|
|
631
|
+
args, text = deplate.input.parse_args(match[2])
|
|
632
|
+
case cmd
|
|
633
|
+
when "IF"
|
|
634
|
+
deplate.switches << !check_switch(deplate, text)
|
|
635
|
+
when "ELSEIF"
|
|
636
|
+
if deplate.switches.empty?
|
|
637
|
+
Deplate::Core.log(["ELSEIF without IF", cmd, match[0]], :error, src)
|
|
638
|
+
else
|
|
639
|
+
case deplate.switches.last
|
|
640
|
+
when :skip
|
|
641
|
+
when true
|
|
642
|
+
deplate.switches.pop
|
|
643
|
+
deplate.switches << !check_switch(deplate, text)
|
|
644
|
+
else
|
|
645
|
+
deplate.switches.pop
|
|
646
|
+
deplate.switches << :skip
|
|
647
|
+
end
|
|
648
|
+
end
|
|
649
|
+
when "ELSE"
|
|
650
|
+
if deplate.switches.empty?
|
|
651
|
+
Deplate::Core.log(["ELSE without IF", cmd, match[0]], :error, src)
|
|
652
|
+
else
|
|
653
|
+
case deplate.switches.last
|
|
654
|
+
when :skip
|
|
655
|
+
when true
|
|
656
|
+
deplate.switches << !deplate.switches.pop
|
|
657
|
+
else
|
|
658
|
+
deplate.switches.pop
|
|
659
|
+
deplate.switches << :skip
|
|
660
|
+
end
|
|
661
|
+
end
|
|
662
|
+
when "ENDIF"
|
|
663
|
+
if deplate.switches.empty?
|
|
664
|
+
Deplate::Core.log(["ENDIF without IF", cmd, match[0]], :error, src)
|
|
665
|
+
else
|
|
666
|
+
deplate.switches.pop
|
|
667
|
+
end
|
|
668
|
+
else
|
|
669
|
+
if !deplate.switches.last
|
|
670
|
+
cc = deplate.input.commands[cmd]
|
|
671
|
+
if cc
|
|
672
|
+
cc.do_accumulate(src, array, deplate, text, match, args, cmd)
|
|
673
|
+
else
|
|
674
|
+
Deplate::Core.log(["Unknown command", cmd, match[0]], :error, src)
|
|
675
|
+
end
|
|
676
|
+
end
|
|
677
|
+
end
|
|
678
|
+
rescue Deplate::DontFormatException
|
|
679
|
+
Deplate::Core.log(["Dropping", match[0]], nil, src)
|
|
680
|
+
end
|
|
681
|
+
end
|
|
682
|
+
|
|
683
|
+
# return true if the test succeeds
|
|
684
|
+
def check_switch(deplate, text)
|
|
685
|
+
if text =~ /^\(.*\)$/
|
|
686
|
+
text = text[1..-2]
|
|
687
|
+
end
|
|
688
|
+
m = /^\s*([:]?\w+)\s*((!=~|=~|==|!=)\s*(.+)\s*|!)$/.match(text)
|
|
689
|
+
if m
|
|
690
|
+
var = m[1]
|
|
691
|
+
negate = /^no([A-Z].*)$/.match(var)
|
|
692
|
+
if negate
|
|
693
|
+
var = negate[1][0..0].downcase + negate[1][1..-1]
|
|
694
|
+
end
|
|
695
|
+
val = m[4]
|
|
696
|
+
op = val ? m[3] : m[2]
|
|
697
|
+
if op == "!"
|
|
698
|
+
return get_var_or_option(deplate, var)
|
|
699
|
+
else
|
|
700
|
+
case op
|
|
701
|
+
when "==", "!="
|
|
702
|
+
compare = Proc.new {|a, b| a == b}
|
|
703
|
+
when "=~", "!=~"
|
|
704
|
+
compare = Proc.new {|a, b| a =~ Regexp.new(b)}
|
|
705
|
+
else
|
|
706
|
+
raise "Internal error"
|
|
707
|
+
end
|
|
708
|
+
case var
|
|
709
|
+
when "fmt"
|
|
710
|
+
switch = compare.call(deplate.formatter.formatter_name, val)
|
|
711
|
+
else
|
|
712
|
+
switch = compare.call(get_var_or_option(deplate, var), val)
|
|
713
|
+
end
|
|
714
|
+
if op[0..0] == "!" or negate
|
|
715
|
+
return !switch
|
|
716
|
+
else
|
|
717
|
+
return switch
|
|
718
|
+
end
|
|
719
|
+
end
|
|
720
|
+
elsif text =~ /^\w+$/
|
|
721
|
+
return get_var_or_option(deplate, text)
|
|
722
|
+
else
|
|
723
|
+
Deplate::Core.log(["Malformed condition", text], :error)
|
|
724
|
+
return true
|
|
725
|
+
end
|
|
726
|
+
end
|
|
727
|
+
|
|
728
|
+
def get_var_or_option(deplate, key)
|
|
729
|
+
if deplate.variables.has_key?(key)
|
|
730
|
+
return deplate.variables[key]
|
|
731
|
+
elsif deplate.options.allow.include?(':') && key =~ /^:(.*)$/
|
|
732
|
+
return deplate.options.send($1)
|
|
733
|
+
end
|
|
734
|
+
Deplate::Core.log(["Unknown variable or option", key])
|
|
735
|
+
return nil
|
|
736
|
+
end
|
|
737
|
+
end
|
|
738
|
+
end
|
|
739
|
+
|
|
740
|
+
class Deplate::Element::Note < Deplate::Element
|
|
741
|
+
register_element
|
|
742
|
+
set_formatter :format_note
|
|
743
|
+
set_rx /^([ \t]+)([#!?+]{3,3})\s+(.*)$/
|
|
744
|
+
|
|
745
|
+
attr_reader :marker
|
|
746
|
+
|
|
747
|
+
def setup
|
|
748
|
+
@multiliner = true
|
|
749
|
+
@collapse = false
|
|
750
|
+
@level = get_level
|
|
751
|
+
@marker = get_marker
|
|
752
|
+
@accum = [get_text]
|
|
753
|
+
end
|
|
754
|
+
|
|
755
|
+
def to_be_continued?(line)
|
|
756
|
+
indent = get_indent(line).size
|
|
757
|
+
return indent >= @level
|
|
758
|
+
end
|
|
759
|
+
|
|
760
|
+
def get_level
|
|
761
|
+
expand_tab(@match[1]).size
|
|
762
|
+
end
|
|
763
|
+
|
|
764
|
+
def get_marker
|
|
765
|
+
@match[2][0..0]
|
|
766
|
+
end
|
|
767
|
+
|
|
768
|
+
def get_text
|
|
769
|
+
@match[3]
|
|
770
|
+
end
|
|
771
|
+
end
|
|
772
|
+
|
|
773
|
+
Deplate::ListItem = Struct.new("DeplateListItem", :item, :body, :listtype, :type,
|
|
774
|
+
:level, :max, :explicit, :label, :style)
|
|
775
|
+
|
|
776
|
+
class Deplate::List < Deplate::Element
|
|
777
|
+
set_formatter :format_list
|
|
778
|
+
set_labelling
|
|
779
|
+
|
|
780
|
+
attr_reader :levelRange, :item, :oitem
|
|
781
|
+
|
|
782
|
+
class << self
|
|
783
|
+
attr :name
|
|
784
|
+
end
|
|
785
|
+
|
|
786
|
+
def setup
|
|
787
|
+
@multiliner = true
|
|
788
|
+
@collapse = true
|
|
789
|
+
@level = get_level
|
|
790
|
+
if self.instance_of?(Deplate::List::Description)
|
|
791
|
+
@levelMax = @level + (@deplate.variables["tabwidth"] || 4)
|
|
792
|
+
else
|
|
793
|
+
@levelMax = get_level_max
|
|
794
|
+
end
|
|
795
|
+
@oitem = @item = get_item
|
|
796
|
+
@accum = [get_text]
|
|
797
|
+
end
|
|
798
|
+
|
|
799
|
+
def get_level
|
|
800
|
+
expand_tab(@match[2]).size
|
|
801
|
+
end
|
|
802
|
+
|
|
803
|
+
def get_level_max
|
|
804
|
+
expand_tab(@match[1]).size
|
|
805
|
+
end
|
|
806
|
+
|
|
807
|
+
def get_item
|
|
808
|
+
@match[3]
|
|
809
|
+
end
|
|
810
|
+
|
|
811
|
+
def get_text
|
|
812
|
+
@match[4]
|
|
813
|
+
end
|
|
814
|
+
|
|
815
|
+
def collapsable?(other)
|
|
816
|
+
if other.kind_of?(Deplate::List)
|
|
817
|
+
return true
|
|
818
|
+
elsif other.kind_of?(Deplate::Element::Paragraph)
|
|
819
|
+
return @elt.find do |i|
|
|
820
|
+
continuation_level_ok?(other.level, i.level, i.max)
|
|
821
|
+
end
|
|
822
|
+
elsif other.kind_of?(Deplate::Element::Whitespace)
|
|
823
|
+
return true
|
|
824
|
+
else
|
|
825
|
+
return false
|
|
826
|
+
end
|
|
827
|
+
end
|
|
828
|
+
|
|
829
|
+
def unify_now(other)
|
|
830
|
+
if other.kind_of?(Deplate::Element::Paragraph)
|
|
831
|
+
@elt << Deplate::ListItem.new([], other.elt.flatten, @elt.last.listtype,
|
|
832
|
+
"Paragraph", other.level, other.level,
|
|
833
|
+
other.is_explicit?, other.label)
|
|
834
|
+
other.label = []
|
|
835
|
+
unify_props(other)
|
|
836
|
+
elsif other.kind_of?(Deplate::Element::Whitespace)
|
|
837
|
+
else
|
|
838
|
+
super
|
|
839
|
+
end
|
|
840
|
+
end
|
|
841
|
+
|
|
842
|
+
def to_be_continued?(line)
|
|
843
|
+
linelevel = get_indent(line).size
|
|
844
|
+
return continuation_level_ok?(linelevel, @level, @levelMax)
|
|
845
|
+
end
|
|
846
|
+
|
|
847
|
+
def continuation_level_ok?(otherLevel, thisLevel, thisMaxLevel)
|
|
848
|
+
# return thisLevel <= otherLevel && otherLevel <= thisMaxLevel
|
|
849
|
+
return thisLevel <= otherLevel
|
|
850
|
+
end
|
|
851
|
+
|
|
852
|
+
def finish
|
|
853
|
+
@item = @deplate.parse(self, @item)
|
|
854
|
+
accum = @deplate.parse(self, @accum.join(" "))
|
|
855
|
+
name = self.class.name
|
|
856
|
+
@elt = [Deplate::ListItem.new(@item, accum, name, name, @level,
|
|
857
|
+
@levelMax, is_explicit?, @label)]
|
|
858
|
+
@label = []
|
|
859
|
+
return self
|
|
860
|
+
end
|
|
861
|
+
|
|
862
|
+
def process_particles(&block)
|
|
863
|
+
@elt.each do |e|
|
|
864
|
+
e.item = block.call(e.item)
|
|
865
|
+
e.body = block.call(e.body)
|
|
866
|
+
end
|
|
867
|
+
end
|
|
868
|
+
end
|
|
869
|
+
|
|
870
|
+
class Deplate::List::Numbered < Deplate::List
|
|
871
|
+
register_element
|
|
872
|
+
set_formatter :format_list
|
|
873
|
+
set_rx /^(([ \t]+)([0-9]+\.|[#\@?]\.?|[a-zA-Z?]\.)[ \t]+)(.+)$/
|
|
874
|
+
set_name "Numbered"
|
|
875
|
+
|
|
876
|
+
def is_explicit?
|
|
877
|
+
if @oitem =~ /^[0-9a-zA-Z]+\.$/
|
|
878
|
+
return true
|
|
879
|
+
else
|
|
880
|
+
return false
|
|
881
|
+
end
|
|
882
|
+
end
|
|
883
|
+
end
|
|
884
|
+
|
|
885
|
+
class Deplate::List::Itemize < Deplate::List
|
|
886
|
+
register_element
|
|
887
|
+
set_formatter :format_list
|
|
888
|
+
set_rx /^(([ \t]+)([-�+*])[ \t]+)(.+)$/
|
|
889
|
+
set_name "Itemize"
|
|
890
|
+
end
|
|
891
|
+
|
|
892
|
+
class Deplate::List::Description < Deplate::List
|
|
893
|
+
register_element
|
|
894
|
+
set_formatter :format_list
|
|
895
|
+
set_rx /^(([ \t]+)(.+?)[ \t]+::[ \t])(.*)$/
|
|
896
|
+
set_name "Description"
|
|
897
|
+
end
|
|
898
|
+
|
|
899
|
+
|
|
900
|
+
|
|
901
|
+
class Deplate::Element::Table < Deplate::Element
|
|
902
|
+
register_element
|
|
903
|
+
set_formatter :format_table
|
|
904
|
+
set_rx /^(\|\|?)([ \t]+.+[ \t]+)\1$/
|
|
905
|
+
|
|
906
|
+
TableRow = Struct.new("DeplateTableRow", :high, :cols, :head, :foot, :is_ruler,
|
|
907
|
+
:from_top, :from_bottom)
|
|
908
|
+
TableCell = Struct.new("DeplateTableCell", :cell,
|
|
909
|
+
:x, :y, :from_right, :from_bottom,
|
|
910
|
+
:high, :head, :foot,
|
|
911
|
+
:span_x, :span_y, :row)
|
|
912
|
+
|
|
913
|
+
attr_accessor :preNote, :postNote, :coordinates,
|
|
914
|
+
:contains_footnotes, :printed_header
|
|
915
|
+
|
|
916
|
+
def setup
|
|
917
|
+
@multiliner = false
|
|
918
|
+
@collapse = true
|
|
919
|
+
high = get_highlight
|
|
920
|
+
cols = get_cols
|
|
921
|
+
cols.collect! {|t| t.strip}
|
|
922
|
+
@accum = [ TableRow.new(high, cols) ]
|
|
923
|
+
@preNote = nil
|
|
924
|
+
@postNote = nil
|
|
925
|
+
@contains_footnotes = false
|
|
926
|
+
end
|
|
927
|
+
|
|
928
|
+
def get_highlight
|
|
929
|
+
@match[1].size == 2
|
|
930
|
+
end
|
|
931
|
+
|
|
932
|
+
def get_cols
|
|
933
|
+
@match[2].split(/[ \t]\|\|?[ \t]/)
|
|
934
|
+
end
|
|
935
|
+
|
|
936
|
+
def unify_now(other)
|
|
937
|
+
super
|
|
938
|
+
@contains_footnotes ||= other.contains_footnotes
|
|
939
|
+
end
|
|
940
|
+
|
|
941
|
+
def collapsable?(other)
|
|
942
|
+
return @collapse && other.collapse && self.class == other.class
|
|
943
|
+
end
|
|
944
|
+
|
|
945
|
+
def finish
|
|
946
|
+
@accum.each do |row|
|
|
947
|
+
row.is_ruler = false
|
|
948
|
+
row.cols.collect! do |c|
|
|
949
|
+
case c
|
|
950
|
+
when /^-+$/
|
|
951
|
+
row.is_ruler = true
|
|
952
|
+
:ruler
|
|
953
|
+
when "<"
|
|
954
|
+
log(["Malformed ruler definition (<)", col.cols], :error) if row.is_ruler
|
|
955
|
+
:join_left
|
|
956
|
+
when "^"
|
|
957
|
+
log(["Malformed ruler definition (^)", col.cols], :error) if row.is_ruler
|
|
958
|
+
:join_above
|
|
959
|
+
when /^\s*$/
|
|
960
|
+
if row.is_ruler
|
|
961
|
+
:noruler
|
|
962
|
+
else
|
|
963
|
+
@deplate.parse(self, c)
|
|
964
|
+
end
|
|
965
|
+
else
|
|
966
|
+
log(["Malformed ruler definition", c, col.cols], :error) if row.is_ruler
|
|
967
|
+
@deplate.parse(self, c)
|
|
968
|
+
end
|
|
969
|
+
end
|
|
970
|
+
end
|
|
971
|
+
@elt = @accum
|
|
972
|
+
return self
|
|
973
|
+
end
|
|
974
|
+
|
|
975
|
+
def process_particles(&block)
|
|
976
|
+
hiCol = get_table_args("hiCol")
|
|
977
|
+
hiRow = get_table_args("hiRow")
|
|
978
|
+
head = @args["head"]
|
|
979
|
+
head = head ? head.to_i : 0
|
|
980
|
+
foot = @args["foot"]
|
|
981
|
+
foot = foot ? foot.to_i : 0
|
|
982
|
+
rowmax = @elt.size
|
|
983
|
+
@coordinates = {}
|
|
984
|
+
y = 0
|
|
985
|
+
rown = @elt.size
|
|
986
|
+
for row in @elt
|
|
987
|
+
y += 1
|
|
988
|
+
x = 0
|
|
989
|
+
coln = row.cols.size
|
|
990
|
+
row.cols.collect! do |cell|
|
|
991
|
+
x += 1
|
|
992
|
+
case cell
|
|
993
|
+
when :join_left
|
|
994
|
+
parent = find_parent_cell(x, y, 1, 0)
|
|
995
|
+
if parent.kind_of?(Symbol)
|
|
996
|
+
elsif parent
|
|
997
|
+
parent.span_x += 1
|
|
998
|
+
else
|
|
999
|
+
log(["Table: Can't join with left cell", x, y], :error)
|
|
1000
|
+
end
|
|
1001
|
+
when :join_above
|
|
1002
|
+
parent = find_parent_cell(x, y, 0, 1)
|
|
1003
|
+
if parent.kind_of?(Symbol)
|
|
1004
|
+
elsif parent
|
|
1005
|
+
parent.span_y += 1
|
|
1006
|
+
else
|
|
1007
|
+
log(["Table: Can't join with above cell", x, y], :error)
|
|
1008
|
+
end
|
|
1009
|
+
when :ruler, :noruler
|
|
1010
|
+
row.is_ruler = true
|
|
1011
|
+
else
|
|
1012
|
+
cell = TableCell.new(block.call(cell), x, y)
|
|
1013
|
+
cell.from_bottom = rown - y
|
|
1014
|
+
cell.from_right = coln - x
|
|
1015
|
+
cell.span_x = 1
|
|
1016
|
+
cell.span_y = 1
|
|
1017
|
+
cell.row = row
|
|
1018
|
+
cell.high = check_table_opts(hiCol, x, coln)
|
|
1019
|
+
end
|
|
1020
|
+
@coordinates[[x,y]] = cell
|
|
1021
|
+
cell
|
|
1022
|
+
end
|
|
1023
|
+
if y <= head
|
|
1024
|
+
row.head = true
|
|
1025
|
+
elsif (rowmax - y + 1) <= foot
|
|
1026
|
+
row.foot = true
|
|
1027
|
+
elsif check_table_opts(hiRow, y, rowmax)
|
|
1028
|
+
row.high = true
|
|
1029
|
+
end
|
|
1030
|
+
row.from_top = y
|
|
1031
|
+
row.from_bottom = rowmax - y
|
|
1032
|
+
end
|
|
1033
|
+
for row in @elt
|
|
1034
|
+
if row.high
|
|
1035
|
+
row.head = true
|
|
1036
|
+
else
|
|
1037
|
+
break
|
|
1038
|
+
end
|
|
1039
|
+
end
|
|
1040
|
+
for row in @elt.reverse
|
|
1041
|
+
if row.high and !row.head
|
|
1042
|
+
row.foot = true
|
|
1043
|
+
else
|
|
1044
|
+
break
|
|
1045
|
+
end
|
|
1046
|
+
end
|
|
1047
|
+
end
|
|
1048
|
+
|
|
1049
|
+
def check_table_opts(args, nth, max)
|
|
1050
|
+
(nth == 1 and args.include?("first")) or
|
|
1051
|
+
(nth == max and args.include?("last")) or
|
|
1052
|
+
args.include?("%d" % nth)
|
|
1053
|
+
end
|
|
1054
|
+
|
|
1055
|
+
def get_table_args(name)
|
|
1056
|
+
args = @args[name]
|
|
1057
|
+
args ? args.split(/\s*,\s*/) : []
|
|
1058
|
+
end
|
|
1059
|
+
|
|
1060
|
+
def find_parent_cell(x, y, delta_x, delta_y)
|
|
1061
|
+
i = 1
|
|
1062
|
+
loop do
|
|
1063
|
+
xx = x - (delta_x * i)
|
|
1064
|
+
yy = y - (delta_y * i)
|
|
1065
|
+
c = @coordinates[[xx, yy]]
|
|
1066
|
+
case c
|
|
1067
|
+
when :join_left
|
|
1068
|
+
return c if delta_x == 0
|
|
1069
|
+
when :join_above
|
|
1070
|
+
return c if delta_y == 0
|
|
1071
|
+
when :ruler, :noruler
|
|
1072
|
+
when nil
|
|
1073
|
+
return nil
|
|
1074
|
+
else
|
|
1075
|
+
return c
|
|
1076
|
+
end
|
|
1077
|
+
i += 1
|
|
1078
|
+
end
|
|
1079
|
+
end
|
|
1080
|
+
|
|
1081
|
+
def register_caption
|
|
1082
|
+
register_table
|
|
1083
|
+
end
|
|
1084
|
+
end
|
|
1085
|
+
|
|
1086
|
+
class Deplate::Element::Heading < Deplate::Element
|
|
1087
|
+
attr_accessor :first_top, :last_top, :top_index, :abstract
|
|
1088
|
+
attr_writer :destination
|
|
1089
|
+
|
|
1090
|
+
register_element
|
|
1091
|
+
set_formatter :format_heading
|
|
1092
|
+
set_rx /^(\*+)[ \t]+(.*?)$/
|
|
1093
|
+
|
|
1094
|
+
class << self
|
|
1095
|
+
def accumulate(src, array, deplate, text, match)
|
|
1096
|
+
Deplate::Element::PotentialPageBreak.accumulate(src, array, deplate, text, match)
|
|
1097
|
+
ppb = array[-1]
|
|
1098
|
+
super
|
|
1099
|
+
hd = array[-1]
|
|
1100
|
+
if hd.is_top_heading?
|
|
1101
|
+
ppb.enabled = true
|
|
1102
|
+
end
|
|
1103
|
+
end
|
|
1104
|
+
|
|
1105
|
+
# Programmatically markup text as heading.
|
|
1106
|
+
def markup(text, level=1)
|
|
1107
|
+
['*' * level, text].join(' ')
|
|
1108
|
+
end
|
|
1109
|
+
end
|
|
1110
|
+
|
|
1111
|
+
def set_instance_top
|
|
1112
|
+
@level = get_level
|
|
1113
|
+
ls = @deplate.variables["levelshift"]
|
|
1114
|
+
if ls
|
|
1115
|
+
@level += ls.to_i
|
|
1116
|
+
end
|
|
1117
|
+
if is_top_heading?
|
|
1118
|
+
@deplate.current_table = 0
|
|
1119
|
+
@deplate.current_figure = 0
|
|
1120
|
+
end
|
|
1121
|
+
@deplate.increase_current_heading(@level)
|
|
1122
|
+
super
|
|
1123
|
+
end
|
|
1124
|
+
|
|
1125
|
+
def setup
|
|
1126
|
+
@first_top = false
|
|
1127
|
+
@last_top = false
|
|
1128
|
+
@multiliner = false
|
|
1129
|
+
@collapse = false
|
|
1130
|
+
@abstract = nil
|
|
1131
|
+
@accum = [get_text]
|
|
1132
|
+
@args[:id] = @deplate.elt_label("hd", @level_as_string)
|
|
1133
|
+
@destination = @deplate.output.destination
|
|
1134
|
+
@top_index = [0, 0]
|
|
1135
|
+
@deplate.table_of_contents << self
|
|
1136
|
+
@deplate.headings[@level_heading] = self
|
|
1137
|
+
update_args
|
|
1138
|
+
end
|
|
1139
|
+
|
|
1140
|
+
def get_level
|
|
1141
|
+
@match[1].size
|
|
1142
|
+
end
|
|
1143
|
+
|
|
1144
|
+
def get_text
|
|
1145
|
+
@match[2]
|
|
1146
|
+
end
|
|
1147
|
+
|
|
1148
|
+
def is_top_heading?
|
|
1149
|
+
@level == 1
|
|
1150
|
+
end
|
|
1151
|
+
|
|
1152
|
+
def update_options(args)
|
|
1153
|
+
@args.update(args)
|
|
1154
|
+
update_args
|
|
1155
|
+
end
|
|
1156
|
+
|
|
1157
|
+
def update_args
|
|
1158
|
+
super
|
|
1159
|
+
register_heading
|
|
1160
|
+
end
|
|
1161
|
+
|
|
1162
|
+
def register_heading
|
|
1163
|
+
sc = @args['id'] || @args['shortcaption']
|
|
1164
|
+
log(['Register heading', level_as_string, sc], :debug)
|
|
1165
|
+
@deplate.set_top_heading(self, sc)
|
|
1166
|
+
end
|
|
1167
|
+
|
|
1168
|
+
def process
|
|
1169
|
+
rv = super
|
|
1170
|
+
if rv.is_top_heading?
|
|
1171
|
+
@deplate.options.heading_names[@top_heading_idx] = rv.elt
|
|
1172
|
+
if @deplate.variables['subToC']
|
|
1173
|
+
args = {'sub' => true, 'plain' => true}
|
|
1174
|
+
match = []
|
|
1175
|
+
toc = Deplate::Command::LIST.new(@deplate, @source, 'toc', match, args, 'LIST')
|
|
1176
|
+
toc.level = @level
|
|
1177
|
+
toc.level_as_string = @level_as_string
|
|
1178
|
+
rv = [rv, toc.finish.process].compact.flatten
|
|
1179
|
+
end
|
|
1180
|
+
end
|
|
1181
|
+
rv
|
|
1182
|
+
end
|
|
1183
|
+
|
|
1184
|
+
def register_metadata
|
|
1185
|
+
stats = @source.stats
|
|
1186
|
+
mtime = stats ? stats.mtime : nil
|
|
1187
|
+
args = {
|
|
1188
|
+
'type' => 'heading',
|
|
1189
|
+
'name' => description,
|
|
1190
|
+
'id' => get_id
|
|
1191
|
+
}
|
|
1192
|
+
if @abstract
|
|
1193
|
+
args['abstract'] = @abstract.to_plain_text
|
|
1194
|
+
end
|
|
1195
|
+
@registered_metadata << @deplate.get_metadata(@source, args)
|
|
1196
|
+
super
|
|
1197
|
+
end
|
|
1198
|
+
|
|
1199
|
+
def description
|
|
1200
|
+
if @args['shortcaption']
|
|
1201
|
+
@args['shortcaption']
|
|
1202
|
+
elsif @caption
|
|
1203
|
+
@caption.elt
|
|
1204
|
+
else
|
|
1205
|
+
@elt
|
|
1206
|
+
end
|
|
1207
|
+
end
|
|
1208
|
+
|
|
1209
|
+
def register_caption
|
|
1210
|
+
@deplate.table_of_contents << self
|
|
1211
|
+
@label << @deplate.elt_label('hd', @level_as_string)
|
|
1212
|
+
end
|
|
1213
|
+
end
|
|
1214
|
+
|
|
1215
|
+
class Deplate::Element::Break < Deplate::Element
|
|
1216
|
+
register_element
|
|
1217
|
+
set_formatter :format_break
|
|
1218
|
+
set_rx /^\s*-{2,}8\<-{2,}\s*$/
|
|
1219
|
+
|
|
1220
|
+
def setup
|
|
1221
|
+
@multiliner = false
|
|
1222
|
+
@collapse = false
|
|
1223
|
+
@accum = []
|
|
1224
|
+
end
|
|
1225
|
+
end
|
|
1226
|
+
|
|
1227
|
+
# An anchor is not a proper element, but is attached to the preceding one
|
|
1228
|
+
class Deplate::Element::Anchor < Deplate::Element
|
|
1229
|
+
register_element
|
|
1230
|
+
set_formatter :format_anchor
|
|
1231
|
+
set_rx /^\s*%?#([a-z][a-zA-Z0-9:_-]+).*$/
|
|
1232
|
+
|
|
1233
|
+
class << self
|
|
1234
|
+
def accumulate(src, array, deplate, text, match)
|
|
1235
|
+
i = 0
|
|
1236
|
+
l = get_text(match)
|
|
1237
|
+
Deplate::Core.log(['New anchor', l], :debug)
|
|
1238
|
+
last = array.last
|
|
1239
|
+
if last and last.can_be_labelled
|
|
1240
|
+
last.put_label([l])
|
|
1241
|
+
# last.args["label"] ||= l
|
|
1242
|
+
deplate.labels_named << l
|
|
1243
|
+
else
|
|
1244
|
+
Deplate::Core.log(["Defer label", l], nil, src)
|
|
1245
|
+
deplate.labels_floating << l
|
|
1246
|
+
end
|
|
1247
|
+
end
|
|
1248
|
+
|
|
1249
|
+
def get_text(match)
|
|
1250
|
+
match[1]
|
|
1251
|
+
end
|
|
1252
|
+
|
|
1253
|
+
def is_volatile?(match)
|
|
1254
|
+
true
|
|
1255
|
+
end
|
|
1256
|
+
end
|
|
1257
|
+
|
|
1258
|
+
def setup
|
|
1259
|
+
put_label([@text])
|
|
1260
|
+
end
|
|
1261
|
+
|
|
1262
|
+
def process
|
|
1263
|
+
return self
|
|
1264
|
+
end
|
|
1265
|
+
end
|
|
1266
|
+
|
|
1267
|
+
# just disappear
|
|
1268
|
+
class Deplate::Element::Whitespace < Deplate::Element
|
|
1269
|
+
register_element
|
|
1270
|
+
set_rx /^\s*$/
|
|
1271
|
+
|
|
1272
|
+
class << self
|
|
1273
|
+
def accumulate(src, array, deplate, text, match)
|
|
1274
|
+
Deplate::Core.log(["Whitespace", text], :debug)
|
|
1275
|
+
le = array.last
|
|
1276
|
+
kw = deplate.options.keep_whitespace
|
|
1277
|
+
if le.kind_of?(Deplate::Element::Table) or (kw and !(le and le.collapse))
|
|
1278
|
+
e = self.new(deplate, src, text, match, kw)
|
|
1279
|
+
if e
|
|
1280
|
+
array << e
|
|
1281
|
+
end
|
|
1282
|
+
end
|
|
1283
|
+
end
|
|
1284
|
+
end
|
|
1285
|
+
|
|
1286
|
+
def setup(kw)
|
|
1287
|
+
@multiliner = false
|
|
1288
|
+
@collapse = true
|
|
1289
|
+
@accum = [@text]
|
|
1290
|
+
@can_be_labelled = false
|
|
1291
|
+
@keep_whitespace = kw
|
|
1292
|
+
end
|
|
1293
|
+
|
|
1294
|
+
def process
|
|
1295
|
+
return @keep_whitespace ? self : nil
|
|
1296
|
+
end
|
|
1297
|
+
|
|
1298
|
+
def print
|
|
1299
|
+
if @keep_whitespace
|
|
1300
|
+
output(@accum.join)
|
|
1301
|
+
end
|
|
1302
|
+
end
|
|
1303
|
+
alias :format_special :print
|
|
1304
|
+
end
|
|
1305
|
+
|
|
1306
|
+
|
|
1307
|
+
class Deplate::Element::PotentialPageBreak < Deplate::Element
|
|
1308
|
+
set_formatter :format_PAGEBREAK
|
|
1309
|
+
attr_accessor :enabled
|
|
1310
|
+
|
|
1311
|
+
def initialize(*args)
|
|
1312
|
+
@enabled = false
|
|
1313
|
+
super
|
|
1314
|
+
end
|
|
1315
|
+
|
|
1316
|
+
def process
|
|
1317
|
+
if @enabled and @deplate.options.multi_file_output
|
|
1318
|
+
self
|
|
1319
|
+
else
|
|
1320
|
+
nil
|
|
1321
|
+
end
|
|
1322
|
+
end
|
|
1323
|
+
end
|
|
1324
|
+
|
|
1325
|
+
|
|
1326
|
+
# Don't register Paragraph in @@elements -- it's assigned if nothing else
|
|
1327
|
+
# matches
|
|
1328
|
+
class Deplate::Element::Paragraph < Deplate::Element
|
|
1329
|
+
set_formatter :format_paragraph
|
|
1330
|
+
set_rx /^([ \t]*)(.+)[ \t]*$/
|
|
1331
|
+
|
|
1332
|
+
class << self
|
|
1333
|
+
def from_text(deplate, src, text)
|
|
1334
|
+
m = @rx.match(text)
|
|
1335
|
+
self.new(deplate, src, text, m)
|
|
1336
|
+
end
|
|
1337
|
+
end
|
|
1338
|
+
|
|
1339
|
+
def setup
|
|
1340
|
+
@multiliner = true
|
|
1341
|
+
@collapse = false
|
|
1342
|
+
@level = get_level
|
|
1343
|
+
@accum = [get_text]
|
|
1344
|
+
end
|
|
1345
|
+
|
|
1346
|
+
def get_level
|
|
1347
|
+
get_indent(@match[1]).size
|
|
1348
|
+
end
|
|
1349
|
+
|
|
1350
|
+
def get_text
|
|
1351
|
+
@deplate.options.keep_whitespace ? @match[0] : @match[2]
|
|
1352
|
+
end
|
|
1353
|
+
end
|
|
1354
|
+
|
|
1355
|
+
# vim: ff=unix
|