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.
- data/AUTHORS.TXT +3 -0
- data/CHANGES.TXT +248 -175
- data/LICENSE.TXT +0 -0
- data/NEWS.TXT +28 -24
- data/README.TXT +0 -0
- data/TODO.TXT +174 -88
- data/VERSION.TXT +1 -1
- data/bin/deplate +0 -0
- data/bin/deplate.bat +0 -0
- data/etc/deplate.ini +91 -3
- data/lib/action_view/helpers/deplate.rb +45 -0
- data/lib/deplate.rb +6 -1
- data/lib/deplate/abstract-class.rb +0 -0
- data/lib/deplate/bib.rb +576 -0
- data/lib/deplate/builtin.rb +0 -0
- data/lib/deplate/cache.rb +55 -5
- data/lib/deplate/commands.rb +346 -183
- data/lib/deplate/common.rb +209 -48
- data/lib/deplate/converter.rb +12 -6
- data/lib/deplate/core.rb +777 -378
- data/lib/deplate/counters.rb +254 -0
- data/lib/deplate/css/article.css +4 -3
- data/lib/deplate/css/deplate.css +121 -5
- data/lib/deplate/css/heading-navbar.css +0 -0
- data/lib/deplate/css/layout-deplate-print.css +0 -0
- data/lib/deplate/css/layout-deplate.css +0 -0
- data/lib/deplate/css/sans-serif.css +0 -0
- data/lib/deplate/css/serif-e.css +0 -0
- data/lib/deplate/css/serif-rel.css +0 -0
- data/lib/deplate/css/serif.css +9 -3
- data/lib/deplate/css/slides.css +0 -0
- data/lib/deplate/css/tabbar-left.css +0 -0
- data/lib/deplate/css/tabbar-right-ie.css +3 -9
- data/lib/deplate/css/tabbar-right.css +51 -18
- data/lib/deplate/css/tabbar-top.css +7 -1
- data/lib/deplate/css/tabbar.css +0 -0
- data/lib/deplate/css/text-sans-serif.css +0 -0
- data/lib/deplate/css/text-serif.css +0 -0
- data/lib/deplate/define.rb +183 -177
- data/lib/deplate/deplate-string.rb +82 -0
- data/lib/deplate/docbook.rb +236 -128
- data/lib/deplate/elements.rb +584 -417
- data/lib/deplate/etc.rb +163 -101
- data/lib/deplate/external.rb +42 -11
- data/lib/deplate/fmt/dbk-article-4.1.2.rb +0 -0
- data/lib/deplate/fmt/dbk-article.rb +0 -0
- data/lib/deplate/fmt/dbk-book.rb +0 -0
- data/lib/deplate/fmt/dbk-ref.rb +3 -3
- data/lib/deplate/fmt/dbk-slides.rb +0 -0
- data/lib/deplate/fmt/dbk-snippet.rb +0 -0
- data/lib/deplate/fmt/html-snippet.rb +0 -0
- data/lib/deplate/fmt/html.rb +783 -550
- data/lib/deplate/fmt/htmlsite.rb +192 -199
- data/lib/deplate/fmt/htmlslides.rb +0 -0
- data/lib/deplate/fmt/htmlwebsite.rb +3 -3
- data/lib/deplate/fmt/latex-snippet.rb +0 -0
- data/lib/deplate/fmt/latex.rb +242 -83
- data/lib/deplate/fmt/null.rb +32 -0
- data/lib/deplate/fmt/php.rb +4 -4
- data/lib/deplate/fmt/phpsite.rb +6 -5
- data/lib/deplate/fmt/plain.rb +160 -106
- data/lib/deplate/fmt/template.rb +0 -0
- data/lib/deplate/fmt/xhtml10t.rb +0 -0
- data/lib/deplate/formatter-snippet.rb +0 -0
- data/lib/deplate/formatter.rb +613 -301
- data/lib/deplate/input.rb +202 -142
- data/lib/deplate/input/deplate-headings.rb +4 -6
- data/lib/deplate/input/deplate-restricted.rb +15 -9
- data/lib/deplate/input/deplate.rb +2 -4
- data/lib/deplate/input/rdoc.rb +39 -38
- data/lib/deplate/input/template.rb +0 -0
- data/lib/deplate/lib/Makefile.config +29 -0
- data/lib/deplate/lib/latex/deplate.sty +54 -0
- data/lib/deplate/lib/latex/highlight-extra.sty +0 -0
- data/lib/deplate/lib/latex/highlight-typical.sty +0 -0
- data/lib/deplate/lib/php/page-comment.inc.php +216 -0
- data/lib/deplate/lib/tabmenu.js +0 -0
- data/lib/deplate/locale/de.latin1 +155 -17
- data/lib/deplate/locale/ru.koi8-r +0 -0
- data/lib/deplate/locale/zh_cn.gb2312 +0 -0
- data/lib/deplate/macros.rb +133 -82
- data/lib/deplate/messages.rb +6 -4
- data/lib/deplate/metadata.rb +0 -0
- data/lib/deplate/metadata/marshal.rb +0 -0
- data/lib/deplate/metadata/xml.rb +0 -0
- data/lib/deplate/metadata/yaml.rb +0 -0
- data/lib/deplate/mod/anyword.rb +3 -3
- data/lib/deplate/mod/babelfish.rb +4 -4
- data/lib/deplate/mod/code-gvim.rb +8 -4
- data/lib/deplate/mod/code-highlight.rb +3 -3
- data/lib/deplate/mod/colored-log.rb +0 -0
- data/lib/deplate/mod/de.rb +2 -2
- data/lib/deplate/mod/en.rb +0 -0
- data/lib/deplate/mod/endnotes.rb +0 -0
- data/lib/deplate/mod/fr.rb +0 -0
- data/lib/deplate/mod/html-asciimath.rb +0 -0
- data/lib/deplate/mod/html-deplate-button.rb +0 -0
- data/lib/deplate/mod/html-headings-navbar.rb +5 -13
- data/lib/deplate/mod/html-jsmath.rb +39 -0
- data/lib/deplate/mod/html-obfuscate-email.rb +3 -3
- data/lib/deplate/mod/html-sidebar.rb +0 -0
- data/lib/deplate/mod/htmlslides-navbar-fh.rb +3 -3
- data/lib/deplate/mod/iconv.rb +0 -0
- data/lib/deplate/mod/imgurl.rb +4 -4
- data/lib/deplate/mod/inlatex-compound.rb +7 -10
- data/lib/deplate/mod/koma.rb +0 -0
- data/lib/deplate/mod/latex-emph-table-head.rb +0 -0
- data/lib/deplate/mod/latex-styles.rb +7 -4
- data/lib/deplate/mod/latex-verbatim-small.rb +0 -0
- data/lib/deplate/mod/makefile.rb +23 -7
- data/lib/deplate/mod/mark-external-urls.rb +3 -3
- data/lib/deplate/mod/markup-1-warn.rb +10 -10
- data/lib/deplate/mod/markup-1.rb +0 -0
- data/lib/deplate/mod/navbar-png.rb +24 -8
- data/lib/deplate/mod/noindent.rb +0 -0
- data/lib/deplate/mod/numpara.rb +0 -0
- data/lib/deplate/mod/particle-math.rb +4 -4
- data/lib/deplate/mod/php-extra.rb +46 -6
- data/lib/deplate/mod/pstoedit.rb +0 -0
- data/lib/deplate/mod/recode.rb +0 -0
- data/lib/deplate/mod/ru_koi8-r.rb +0 -0
- data/lib/deplate/mod/smart-dash.rb +26 -0
- data/lib/deplate/mod/smiley.rb +69 -7
- data/lib/deplate/mod/soffice.rb +0 -0
- data/lib/deplate/mod/symbols-latin1.rb +14 -23
- data/lib/deplate/mod/symbols-od-utf-8.rb +5 -3
- data/lib/deplate/mod/symbols-plain.rb +5 -35
- data/lib/deplate/mod/symbols-sgml.rb +8 -9
- data/lib/deplate/mod/symbols-utf-8.rb +8 -9
- data/lib/deplate/mod/symbols-xml.rb +5 -9
- data/lib/deplate/mod/syntax-region-alt.rb +5 -5
- data/lib/deplate/mod/utf8.rb +0 -0
- data/lib/deplate/mod/validate-html.rb +0 -0
- data/lib/deplate/mod/xmlrpc.rb +0 -0
- data/lib/deplate/mod/zh-cn-autospace.rb +18 -20
- data/lib/deplate/mod/zh-cn.rb +4 -6
- data/lib/deplate/nukumi2.rb +71 -0
- data/lib/deplate/once-method.rb +0 -0
- data/lib/deplate/output.rb +19 -21
- data/lib/deplate/particles.rb +178 -116
- data/lib/deplate/regions.rb +99 -58
- data/lib/deplate/skeletons.rb +122 -0
- data/lib/deplate/structured.rb +164 -106
- data/lib/deplate/template.rb +67 -43
- data/lib/deplate/templates/html-doc.html +0 -0
- data/lib/deplate/templates/html-left-tabbar-js.html +0 -0
- data/lib/deplate/templates/html-left-tabbar.html +0 -0
- data/lib/deplate/templates/html-tabbar-right-pcomments.php +22 -0
- data/lib/deplate/templates/html-tabbar-right-step.html +24 -0
- data/lib/deplate/templates/html-tabbar-right-table.html +0 -0
- data/lib/deplate/templates/html-tabbar-right.html +2 -4
- data/lib/deplate/templates/html-tabbar-top.html +0 -9
- data/lib/deplate/templates/html-tabbar.html +0 -0
- data/lib/deplate/variables.rb +127 -0
- data/lib/deplate/wiki-markup.rb +99 -33
- data/lib/deplate/xml.rb +18 -18
- data/lib/deplate/zh-cn.rb +0 -0
- data/lib/ps2ppm.rb +0 -0
- data/man/man1/deplate.1 +564 -474
- metadata +201 -186
data/lib/deplate/fmt/template.rb
CHANGED
|
File without changes
|
data/lib/deplate/fmt/xhtml10t.rb
CHANGED
|
File without changes
|
|
File without changes
|
data/lib/deplate/formatter.rb
CHANGED
|
@@ -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:
|
|
7
|
-
# @Revision: 0.
|
|
6
|
+
# @Last Change: 05-Jun-2006.
|
|
7
|
+
# @Revision: 0.1443
|
|
8
8
|
|
|
9
|
-
require
|
|
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
|
-
|
|
57
|
+
def hook_post_myname=(name)
|
|
58
|
+
klass = self
|
|
59
|
+
Deplate::Core.class_eval {declare_formatter(klass)}
|
|
60
|
+
end
|
|
32
61
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
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
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
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
|
|
81
|
-
attr_reader
|
|
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
|
|
86
|
-
@variables
|
|
87
|
-
@
|
|
88
|
-
@
|
|
89
|
-
@
|
|
90
|
-
@
|
|
91
|
-
@
|
|
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,
|
|
180
|
-
join_inline(format_particle(agent,
|
|
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,
|
|
190
|
-
format_element(agent,
|
|
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 =
|
|
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
|
-
|
|
386
|
-
|
|
387
|
-
|
|
517
|
+
args = invoker.args
|
|
518
|
+
begin
|
|
519
|
+
if respond_to?(meth)
|
|
388
520
|
acc << send(meth, invoker)
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
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
|
-
|
|
394
|
-
|
|
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
|
|
445
|
-
|
|
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
|
-
|
|
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 ?
|
|
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
|
-
|
|
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[
|
|
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
|
|
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
|
-
|
|
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([
|
|
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
|
|
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[
|
|
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(
|
|
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
|
-
|
|
1200
|
+
strings = {}
|
|
1201
|
+
acc = acc.join("\n")
|
|
894
1202
|
loop do
|
|
895
|
-
m = /^\s
|
|
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[
|
|
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 << [
|
|
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
|
-
|
|
940
|
-
|
|
941
|
-
|
|
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
|
-
|
|
1264
|
+
text = bib_styler.bib_format(bibdef)
|
|
971
1265
|
end
|
|
972
|
-
|
|
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
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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([
|
|
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
|
|
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
|
|
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(
|
|
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
|
|
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
|
-
|
|
1377
|
+
def last_level(list_tags)
|
|
1378
|
+
list_tags[:levels].last
|
|
1119
1379
|
end
|
|
1120
1380
|
|
|
1121
|
-
def last_listtype
|
|
1122
|
-
|
|
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 "
|
|
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
|
-
|
|
1151
|
-
when "Description"
|
|
1152
|
-
|
|
1153
|
-
when
|
|
1154
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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 =
|
|
1171
|
-
tp, sp =
|
|
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
|
-
|
|
1184
|
-
|
|
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 =
|
|
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
|
|
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
|
|