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,34 @@
|
|
|
1
|
+
# template.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: 25-M�r-2005.
|
|
6
|
+
# @Last Change: 23-Okt-2005.
|
|
7
|
+
# @Revision: 0.21
|
|
8
|
+
#
|
|
9
|
+
# = Description
|
|
10
|
+
# The formatter for templates
|
|
11
|
+
|
|
12
|
+
# A pseudo-formatter used for templates.
|
|
13
|
+
class Deplate::Formatter::Template < Deplate::Formatter
|
|
14
|
+
self.myname = "template"
|
|
15
|
+
self.rx = /template/i
|
|
16
|
+
self.suffix = ".out"
|
|
17
|
+
|
|
18
|
+
self.label_mode = :delegate
|
|
19
|
+
self.label_delegate = []
|
|
20
|
+
self.label_once = []
|
|
21
|
+
|
|
22
|
+
def plain_text(text, escaped=false)
|
|
23
|
+
return text
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def format_unknown(invoker)
|
|
27
|
+
invoker.elt
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def format_paragraph(invoker)
|
|
31
|
+
invoker.elt
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# fmt-xhtml.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: 03-Aug-2004.
|
|
6
|
+
# @Last Change: 23-Okt-2005.
|
|
7
|
+
# @Revision: 0.35
|
|
8
|
+
|
|
9
|
+
require "deplate/fmt/html"
|
|
10
|
+
|
|
11
|
+
class Deplate::Formatter::XHTML10transitional < Deplate::Formatter::HTML
|
|
12
|
+
self.myname = "xhtml10t"
|
|
13
|
+
self.rx = /x?html?/i
|
|
14
|
+
self.suffix = ".xhtml"
|
|
15
|
+
|
|
16
|
+
def head_doctype
|
|
17
|
+
return %Q{<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
|
18
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">}
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def html_lang(stripped=false)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def html_def
|
|
25
|
+
acc = [%{xmlns="http://www.w3.org/1999/xhtml"}]
|
|
26
|
+
lang = @deplate.options.messages.prop('lang', self)
|
|
27
|
+
if lang
|
|
28
|
+
acc << %{lang="#{lang}"} << %{xml:lang="#{lang}"}
|
|
29
|
+
end
|
|
30
|
+
"<html #{acc.join(" ")}>"
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def head_meta_tag(text)
|
|
34
|
+
return %Q{<meta #{text} />}
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def head_link_tag(text)
|
|
38
|
+
return %Q{<link #{text} />}
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# formatter-snippet.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: 11-Aug-2005.
|
|
6
|
+
# @Last Change: 23-Okt-2005.
|
|
7
|
+
# @Revision: 0.3
|
|
8
|
+
|
|
9
|
+
module Deplate::Snippet
|
|
10
|
+
def formatter_initialize_snippet
|
|
11
|
+
unless @deplate.options.included
|
|
12
|
+
log(['Not run in included mode'], :error)
|
|
13
|
+
log(['Set included mode'], :error)
|
|
14
|
+
@deplate.options.included = true
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,1210 @@
|
|
|
1
|
+
# formatter.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: 31-Okt-2004.
|
|
6
|
+
# @Last Change: 02-Nov-2005.
|
|
7
|
+
# @Revision: 0.923
|
|
8
|
+
|
|
9
|
+
require "deplate/abstract-class"
|
|
10
|
+
|
|
11
|
+
# Description:
|
|
12
|
+
# An abstract formatter class
|
|
13
|
+
#
|
|
14
|
+
# Usage:
|
|
15
|
+
#
|
|
16
|
+
# TODO:
|
|
17
|
+
#
|
|
18
|
+
# CHANGES:
|
|
19
|
+
#
|
|
20
|
+
|
|
21
|
+
class Deplate::Formatter
|
|
22
|
+
class << self
|
|
23
|
+
def noop(context, name)
|
|
24
|
+
context.module_eval %{
|
|
25
|
+
def #{name}(*args)
|
|
26
|
+
return ""
|
|
27
|
+
end
|
|
28
|
+
}
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
attr_writer :suffix, :myname, :rx, :label_mode, :label_delegate, :label_once
|
|
32
|
+
|
|
33
|
+
def get_class_attrib(name, default=nil)
|
|
34
|
+
if self == Deplate::Formatter
|
|
35
|
+
return default
|
|
36
|
+
end
|
|
37
|
+
iv = "@#{name}"
|
|
38
|
+
if self.instance_variables.include?(iv)
|
|
39
|
+
val = self.instance_variable_get(iv)
|
|
40
|
+
if val
|
|
41
|
+
return val
|
|
42
|
+
end
|
|
43
|
+
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
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
@@custom_particles = {}
|
|
79
|
+
|
|
80
|
+
attr_reader :deplate
|
|
81
|
+
attr_reader :advices
|
|
82
|
+
attr_accessor :special_symbols
|
|
83
|
+
|
|
84
|
+
def initialize(deplate, args={})
|
|
85
|
+
@deplate = deplate
|
|
86
|
+
@variables = deplate.variables
|
|
87
|
+
@bibentries = {}
|
|
88
|
+
@open_labels = []
|
|
89
|
+
@advices = args[:advices] || {}
|
|
90
|
+
@inlatex_idx = 0
|
|
91
|
+
@encodings = {}
|
|
92
|
+
@consumed_labels = []
|
|
93
|
+
@consumed_ids = []
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def retrieve_particle(id, body=nil, specific=false)
|
|
97
|
+
fmt = specific ? formatter_name : '_'
|
|
98
|
+
particles = @@custom_particles[fmt] ||= {}
|
|
99
|
+
particle = particles[id]
|
|
100
|
+
if particle
|
|
101
|
+
if body.nil? or particle[:body] == body
|
|
102
|
+
return particle[:class]
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
return nil
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def store_particle(id, body, particle, specific=false)
|
|
109
|
+
fmt = specific ? formatter_name : '_'
|
|
110
|
+
particles = @@custom_particles[fmt] ||= {}
|
|
111
|
+
particles[id] = {:body => body, :class => particle}
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def def_advice(applicant, agent, args)
|
|
115
|
+
this = @advices[agent] ||= {}
|
|
116
|
+
for type in [:wrap]
|
|
117
|
+
thistype = []
|
|
118
|
+
prc = args[type]
|
|
119
|
+
if prc
|
|
120
|
+
if prc.kind_of?(Proc)
|
|
121
|
+
thistype << {:applicant => applicant, :prc => prc}
|
|
122
|
+
else
|
|
123
|
+
raise "Not a Proc: %s" % prc
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
unless thistype.empty?
|
|
127
|
+
if this[type]
|
|
128
|
+
this[type] += thistype
|
|
129
|
+
else
|
|
130
|
+
this[type] = thistype
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
for type in [:before, :around, :after]
|
|
135
|
+
prc = args[type]
|
|
136
|
+
if prc
|
|
137
|
+
log(["Unsupported advice type", type, applicant, prc], :error)
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def log(*args)
|
|
143
|
+
Deplate::Core.log(*args)
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def canonic_enc_name(enc, table=@encodings)
|
|
147
|
+
case enc.downcase
|
|
148
|
+
when 'latin-1', 'latin1', 'l1', 'isolat1', 'iso-8859-1'
|
|
149
|
+
cen = 'latin1'
|
|
150
|
+
when 'latin-9', 'latin9', 'l9', 'isolat9', 'iso-8859-15'
|
|
151
|
+
cen = 'latin9'
|
|
152
|
+
when 'gb2312', 'gbk'
|
|
153
|
+
cen = 'gb2312'
|
|
154
|
+
when 'koi8-r'
|
|
155
|
+
cen = 'koi8-r'
|
|
156
|
+
when 'utf8', 'utf-8'
|
|
157
|
+
cen = 'utf-8'
|
|
158
|
+
else
|
|
159
|
+
log(['Unsupported encoding', enc], :anyway)
|
|
160
|
+
cen = enc
|
|
161
|
+
end
|
|
162
|
+
return table[cen] || cen
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def join_blocks(blocks)
|
|
166
|
+
blocks.flatten.compact.join("\n")
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
def join_inline(strings)
|
|
170
|
+
strings.flatten.compact.join
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
def format_particle(agent, invoker, *args)
|
|
174
|
+
# rv = with_agent(agent, Array, invoker, *args)
|
|
175
|
+
# rv.empty? ? format_unknown_particle(invoker) : rv.join
|
|
176
|
+
with_agent(agent, Array, invoker, *args)
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
def format_particle_as_string(agent, object, *args)
|
|
180
|
+
join_inline(format_particle(agent, object, *args))
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
def format_element(agent, invoker, *args)
|
|
184
|
+
# rv = with_agent(agent, Array, invoker, *args)
|
|
185
|
+
# rv.empty? ? format_unknown(invoker) : join_blocks(rv)
|
|
186
|
+
with_agent(agent, Array, invoker, *args)
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
def format_element_as_string(agent, object, *args)
|
|
190
|
+
format_element(agent, object, *args)
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
def with_agent(agent, prototype, invoker, *args)
|
|
194
|
+
log(["Call with agent", agent, invoker.class, args], :debug)
|
|
195
|
+
if respond_to?(agent)
|
|
196
|
+
before = []
|
|
197
|
+
inner = nil
|
|
198
|
+
after = []
|
|
199
|
+
stylish = @advices[agent]
|
|
200
|
+
if stylish
|
|
201
|
+
# pre = stylish[:before]
|
|
202
|
+
# if pre
|
|
203
|
+
# for advice in pre
|
|
204
|
+
# before << advice[:prc].call(invoker, *args)
|
|
205
|
+
# end
|
|
206
|
+
# end
|
|
207
|
+
|
|
208
|
+
inner = self.send(agent, invoker, *args)
|
|
209
|
+
prototype ||= inner.class
|
|
210
|
+
around = stylish[:wrap]
|
|
211
|
+
if around
|
|
212
|
+
inner = around.inject(inner) do |acc, advice|
|
|
213
|
+
advice[:prc].call(agent, acc, invoker, *args)
|
|
214
|
+
end
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
# post = stylish[:after]
|
|
218
|
+
# if post
|
|
219
|
+
# for advice in post
|
|
220
|
+
# after << advice[:prc].call(invoker, *args)
|
|
221
|
+
# end
|
|
222
|
+
# end
|
|
223
|
+
else
|
|
224
|
+
args = args.unshift(invoker)
|
|
225
|
+
begin
|
|
226
|
+
inner = self.send(agent, *args)
|
|
227
|
+
rescue Exception => e
|
|
228
|
+
puts "DBG: #{agent}"
|
|
229
|
+
puts e.backtrace[0..10].join("\n")
|
|
230
|
+
raise e
|
|
231
|
+
end
|
|
232
|
+
prototype ||= inner.class
|
|
233
|
+
end
|
|
234
|
+
# if prototype == String
|
|
235
|
+
# rv = [before, inner, after].join
|
|
236
|
+
# elsif prototype == Integer
|
|
237
|
+
# rv = [before, inner, after].join.to_i
|
|
238
|
+
# elsif inner.kind_of?(Array)
|
|
239
|
+
# rv = before + inner + after
|
|
240
|
+
# else
|
|
241
|
+
# rv = before + [inner] + after
|
|
242
|
+
# end
|
|
243
|
+
# return rv
|
|
244
|
+
return inner
|
|
245
|
+
else
|
|
246
|
+
invoker.log(["Unknown formatting agent", agent], :error)
|
|
247
|
+
return nil
|
|
248
|
+
end
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
def output(invoker, *body)
|
|
252
|
+
output_at(invoker.doc_type, invoker.doc_slot, *body)
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
def output_preferably_at(invoker, type, slot, *body)
|
|
256
|
+
type = defined?(invoker.doc_type) ? invoker.doc_type(type) : type
|
|
257
|
+
slot = defined?(invoker.doc_slot) ? invoker.doc_slot(slot) : slot
|
|
258
|
+
output_at(type, slot, *body)
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
def output_empty_at?(type, slot)
|
|
262
|
+
@deplate.output.empty_at?(type, slot)
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
# def_delegator(:@deplate, :add_at, :output_at)
|
|
266
|
+
def output_at(type, slot, *body)
|
|
267
|
+
log(["Output at", "#{type}@#{slot}", body], :debug)
|
|
268
|
+
@deplate.output.add_at(type, slot, *body)
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
# def_delegator(:@deplate, :union_at)
|
|
272
|
+
def union_at(type, slot, *body)
|
|
273
|
+
@deplate.output.union_at(type, slot, *body)
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
# def_delegator(:@deplate, :set_at)
|
|
277
|
+
def set_at(type, slot, *body)
|
|
278
|
+
@deplate.output.set_at(type, slot, *body)
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
# push *options to variables['classOptions']
|
|
282
|
+
def push_class_option(*options)
|
|
283
|
+
acc = [@deplate.variables["classOptions"]]
|
|
284
|
+
acc += options
|
|
285
|
+
acc.compact!
|
|
286
|
+
@deplate.variables["classOptions"] = acc.join(' ')
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
# Properly format +text+ as formatter-valid plain text.
|
|
290
|
+
#
|
|
291
|
+
# If +escaped+ is true, +text+ appears in a special context and was
|
|
292
|
+
# escaped by a backslash or similar.
|
|
293
|
+
#
|
|
294
|
+
# If a block is given, convert normal text using this block.
|
|
295
|
+
#
|
|
296
|
+
# Special characters are translated on the basis of @special_symbols.
|
|
297
|
+
def plain_text(text, escaped=false)
|
|
298
|
+
if defined?(@plain_text_rx)
|
|
299
|
+
acc = []
|
|
300
|
+
text.split(@plain_text_rx).each_with_index do |e, i|
|
|
301
|
+
if i.modulo(2) == 0
|
|
302
|
+
acc << plain_text_recode(e) unless e.empty?
|
|
303
|
+
else
|
|
304
|
+
r = @special_symbols[e]
|
|
305
|
+
case r
|
|
306
|
+
when String
|
|
307
|
+
acc << r
|
|
308
|
+
when Proc
|
|
309
|
+
acc << r.call(escaped)
|
|
310
|
+
else
|
|
311
|
+
raise "Internal error: Strange symbol replacement for '#{e}'"
|
|
312
|
+
end
|
|
313
|
+
end
|
|
314
|
+
end
|
|
315
|
+
acc.join
|
|
316
|
+
else
|
|
317
|
+
plain_text_recode(text)
|
|
318
|
+
end
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
# Recode normal text for #plain_text
|
|
322
|
+
def plain_text_recode(text)
|
|
323
|
+
text
|
|
324
|
+
end
|
|
325
|
+
|
|
326
|
+
def encode_id(id)
|
|
327
|
+
id ? Deplate::Core.clean_file_name(id, "__") : id
|
|
328
|
+
end
|
|
329
|
+
|
|
330
|
+
def label_mode
|
|
331
|
+
self.class.label_mode
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
def label_once
|
|
335
|
+
self.class.label_once
|
|
336
|
+
end
|
|
337
|
+
|
|
338
|
+
def label_delegate
|
|
339
|
+
self.class.label_delegate
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
def suffix
|
|
343
|
+
self.class.suffix
|
|
344
|
+
end
|
|
345
|
+
|
|
346
|
+
def formatter_name
|
|
347
|
+
self.class.myname
|
|
348
|
+
end
|
|
349
|
+
|
|
350
|
+
def formatter_rx
|
|
351
|
+
self.class.rx
|
|
352
|
+
end
|
|
353
|
+
|
|
354
|
+
def setup
|
|
355
|
+
end
|
|
356
|
+
|
|
357
|
+
def pre_process
|
|
358
|
+
end
|
|
359
|
+
|
|
360
|
+
def prepare
|
|
361
|
+
end
|
|
362
|
+
|
|
363
|
+
def matches?(text)
|
|
364
|
+
if text[0..0] == "~"
|
|
365
|
+
rv = (formatter_name =~ Regexp.new(text[1..-1]))
|
|
366
|
+
else
|
|
367
|
+
rv = (text =~ formatter_rx)
|
|
368
|
+
end
|
|
369
|
+
return rv ? true : false
|
|
370
|
+
end
|
|
371
|
+
|
|
372
|
+
def format_GET(invoker)
|
|
373
|
+
elt = invoker.elt
|
|
374
|
+
if elt
|
|
375
|
+
elt.format_clip(invoker, Deplate::Element)
|
|
376
|
+
else
|
|
377
|
+
invoker.log("Dropped!", :error)
|
|
378
|
+
end
|
|
379
|
+
end
|
|
380
|
+
|
|
381
|
+
def format_LIST(invoker)
|
|
382
|
+
acc = []
|
|
383
|
+
elt = invoker.elt
|
|
384
|
+
meth = "format_list_of_" + elt
|
|
385
|
+
if respond_to?(meth)
|
|
386
|
+
args = invoker.args
|
|
387
|
+
begin
|
|
388
|
+
acc << send(meth, invoker)
|
|
389
|
+
acc << format_pagebreak(invoker) if args["page"]
|
|
390
|
+
rescue StandardError => e
|
|
391
|
+
log(["Formatting on LIST failed", elt.inspect, e, e.backtrace[0..10]], :error)
|
|
392
|
+
end
|
|
393
|
+
else
|
|
394
|
+
log(["Unknown LIST type", elt.inspect], :error)
|
|
395
|
+
end
|
|
396
|
+
join_blocks(acc)
|
|
397
|
+
end
|
|
398
|
+
|
|
399
|
+
def format_PAGEBREAK(invoker)
|
|
400
|
+
format_pagebreak(invoker, nil, true)
|
|
401
|
+
end
|
|
402
|
+
|
|
403
|
+
def fill_in_template(invoker)
|
|
404
|
+
invoker.elt
|
|
405
|
+
end
|
|
406
|
+
|
|
407
|
+
def read_bib(bibfiles)
|
|
408
|
+
end
|
|
409
|
+
|
|
410
|
+
def format_unknown(invoker)
|
|
411
|
+
log(["Unknown element", invoker.class], :error, invoker.source)
|
|
412
|
+
elt = invoker.elt
|
|
413
|
+
if elt.kind_of?(Array)
|
|
414
|
+
elt = elt.join("\n")
|
|
415
|
+
end
|
|
416
|
+
format_verbatim(invoker, elt)
|
|
417
|
+
end
|
|
418
|
+
|
|
419
|
+
def format_unknown_particle(invoker)
|
|
420
|
+
return plain_text(invoker.args[:match][0])
|
|
421
|
+
end
|
|
422
|
+
|
|
423
|
+
def format_unknown_macro(invoker)
|
|
424
|
+
return %{#{plain_text("{")}#{invoker.elt}#{plain_text("}")}}
|
|
425
|
+
end
|
|
426
|
+
|
|
427
|
+
|
|
428
|
+
### General
|
|
429
|
+
def_abstract :format_label, :format_figure, :include_image
|
|
430
|
+
|
|
431
|
+
### Elements
|
|
432
|
+
def_abstract :format_note, :format_table, :format_heading, :format_list,
|
|
433
|
+
:format_break, :format_anchor, :format_paragraph
|
|
434
|
+
|
|
435
|
+
### Regions
|
|
436
|
+
def_abstract :format_verbatim, :format_abstract, :format_quote,
|
|
437
|
+
:format_header, :format_footer
|
|
438
|
+
|
|
439
|
+
### Commands
|
|
440
|
+
def_abstract :format_title, :format_MAKEBIB, :format_IDX,
|
|
441
|
+
:format_pagebreak
|
|
442
|
+
|
|
443
|
+
### Particles
|
|
444
|
+
def_abstract :format_emphasize, :format_code, :format_url, :format_wiki, :format_symbol,
|
|
445
|
+
:doublequote_open, :doublequote_close, :singlequote_open, :singlequote_close
|
|
446
|
+
|
|
447
|
+
### Macros
|
|
448
|
+
def_abstract :format_index, :format_footnote, :format_ref,
|
|
449
|
+
:format_linebreak, :format_subscript, :format_superscript, :format_stacked,
|
|
450
|
+
:format_pagenumber
|
|
451
|
+
|
|
452
|
+
def format_cite(invoker)
|
|
453
|
+
container = invoker.container
|
|
454
|
+
args = invoker.args
|
|
455
|
+
n = args['n']
|
|
456
|
+
p = args['p']
|
|
457
|
+
np = args['np']
|
|
458
|
+
y = args['y']
|
|
459
|
+
acc = []
|
|
460
|
+
pmsg = @deplate.msg('p.\\ ')
|
|
461
|
+
for c in invoker.elt
|
|
462
|
+
cc = bib_entry(c)
|
|
463
|
+
if cc
|
|
464
|
+
yr = cc.assoc('year')
|
|
465
|
+
yr = if yr then yr[1] else '' end
|
|
466
|
+
if p
|
|
467
|
+
p = @deplate.parse_and_format_without_wikinames(container, "#{pmsg}#{p}")
|
|
468
|
+
yr += ": #{p}"
|
|
469
|
+
# yr += ": " + p if p
|
|
470
|
+
end
|
|
471
|
+
if y
|
|
472
|
+
acc << referenced_bib_entry(invoker, c, yr)
|
|
473
|
+
else
|
|
474
|
+
nm = cc.assoc('author') || cc.assoc('editor') || cc.assoc('howpublished')
|
|
475
|
+
if nm
|
|
476
|
+
nm = nm[1]
|
|
477
|
+
nm = nm.gsub(/\s+/, ' ').split(' and ').collect do |a|
|
|
478
|
+
a.scan(/\w+$/)
|
|
479
|
+
end
|
|
480
|
+
nm = nm.join(', ')
|
|
481
|
+
acc << referenced_bib_entry(invoker, c, [nm, yr].join(' '))
|
|
482
|
+
else
|
|
483
|
+
acc << referenced_bib_entry(invoker, c, c)
|
|
484
|
+
end
|
|
485
|
+
end
|
|
486
|
+
end
|
|
487
|
+
end
|
|
488
|
+
n &&= n + plain_text(' ', true)
|
|
489
|
+
acc = acc.join('; ')
|
|
490
|
+
if np
|
|
491
|
+
return %{#{plain_text(' ', true)}#{n}#{acc}}
|
|
492
|
+
else
|
|
493
|
+
return %{#{plain_text(' ', true)}(#{n}#{acc})}
|
|
494
|
+
end
|
|
495
|
+
end
|
|
496
|
+
|
|
497
|
+
# Check if ch (a number representing a character) is a multi-byte leader.
|
|
498
|
+
# This method always returns false unless it is overwritten by some module.
|
|
499
|
+
def multibyte_leader?(ch)
|
|
500
|
+
false
|
|
501
|
+
end
|
|
502
|
+
|
|
503
|
+
# Return the first character of string while taking care whether string
|
|
504
|
+
# starts with a multi-byte sequence. Return the character in upper case if
|
|
505
|
+
# upcase is true (this usually doesn't work for multi-byte characters.
|
|
506
|
+
def get_first_char(string, upcase=false)
|
|
507
|
+
ch = string[0..0]
|
|
508
|
+
upcase and ch ? ch.upcase : ch
|
|
509
|
+
end
|
|
510
|
+
|
|
511
|
+
# Return the alphabethically sorted index data.
|
|
512
|
+
# def sort_index_entries(data)
|
|
513
|
+
# return data.sort do |a,b|
|
|
514
|
+
# aa = get_first_char(a, true)
|
|
515
|
+
# bb = get_first_char(b, true)
|
|
516
|
+
# aa <=> bb
|
|
517
|
+
# end
|
|
518
|
+
# end
|
|
519
|
+
def sort_index_entries(data)
|
|
520
|
+
return data.sort {|a,b| a[0].upcase <=> b[0].upcase}
|
|
521
|
+
end
|
|
522
|
+
|
|
523
|
+
# Return the maximum row size for the table data in elt.
|
|
524
|
+
def table_row_size(elt)
|
|
525
|
+
max = 0
|
|
526
|
+
for row in elt
|
|
527
|
+
i = row.cols.size
|
|
528
|
+
if i > max
|
|
529
|
+
max = i
|
|
530
|
+
end
|
|
531
|
+
end
|
|
532
|
+
max
|
|
533
|
+
end
|
|
534
|
+
|
|
535
|
+
# Takes an optional block that takes a string as argument and returns
|
|
536
|
+
# true if we shouldn't wrap the text at this position
|
|
537
|
+
def wrap_text(text, args={})
|
|
538
|
+
moreIndent = args[:indent] || ""
|
|
539
|
+
innerMargin = args[:margin] || 66
|
|
540
|
+
outerMargin = args[:maxmargin] || 72
|
|
541
|
+
hanging = args[:hanging] || nil
|
|
542
|
+
hang_idt = hanging ? " " * hanging : nil
|
|
543
|
+
acc = []
|
|
544
|
+
block = args[:check]
|
|
545
|
+
break_at = args[:break_at]
|
|
546
|
+
if break_at
|
|
547
|
+
rx = /(\s+|([#{break_at}]+))/
|
|
548
|
+
else
|
|
549
|
+
rx = /\s+/
|
|
550
|
+
end
|
|
551
|
+
text.each do |text|
|
|
552
|
+
m = /^(\s*)(.*)$/.match(text)
|
|
553
|
+
idt = m[1] + moreIndent
|
|
554
|
+
accum = [m[1]]
|
|
555
|
+
idtx = idt.size
|
|
556
|
+
imx = innerMargin - idtx
|
|
557
|
+
rest = m[2]
|
|
558
|
+
while rest
|
|
559
|
+
this, rest = break_line(rest, rx, imx, block)
|
|
560
|
+
accum << this
|
|
561
|
+
if rest
|
|
562
|
+
accum << "\n"
|
|
563
|
+
accum << idt
|
|
564
|
+
accum << hang_idt if hang_idt
|
|
565
|
+
end
|
|
566
|
+
end
|
|
567
|
+
acc << accum.join
|
|
568
|
+
end
|
|
569
|
+
return acc.join("\n")
|
|
570
|
+
end
|
|
571
|
+
|
|
572
|
+
def break_line(line, rx, inner_margin, block=nil, delta=-1)
|
|
573
|
+
max = line.size
|
|
574
|
+
if inner_margin >= max
|
|
575
|
+
return line, nil
|
|
576
|
+
else
|
|
577
|
+
m = rx.match(line[inner_margin..-1])
|
|
578
|
+
if m
|
|
579
|
+
pre = m.pre_match
|
|
580
|
+
tt = line[0..inner_margin-1] + pre
|
|
581
|
+
if block and block.call(tt)
|
|
582
|
+
return break_line(line, rx, inner_margin + delta, block, delta)
|
|
583
|
+
else
|
|
584
|
+
if m[1]
|
|
585
|
+
x = m[1].size + 1
|
|
586
|
+
return tt[0..-x], m[1] + m.post_match
|
|
587
|
+
else
|
|
588
|
+
return tt, m.post_match
|
|
589
|
+
end
|
|
590
|
+
end
|
|
591
|
+
else
|
|
592
|
+
return break_line(line, rx, inner_margin + 1, block, 1)
|
|
593
|
+
end
|
|
594
|
+
end
|
|
595
|
+
end
|
|
596
|
+
|
|
597
|
+
def prelude(name)
|
|
598
|
+
@deplate.variables[name]
|
|
599
|
+
end
|
|
600
|
+
|
|
601
|
+
# Format the Inlatex region
|
|
602
|
+
def format_inlatex(invoker)
|
|
603
|
+
args = invoker.args
|
|
604
|
+
inline = args["inline"]
|
|
605
|
+
args["h"] ||= (args["inlineLatexHeight"] || args["inlatexHeight"]) if inline
|
|
606
|
+
acc = []
|
|
607
|
+
elt = invoker.elt
|
|
608
|
+
if elt
|
|
609
|
+
for i in elt
|
|
610
|
+
acc << format_element(:format_figure, invoker, inline, i)
|
|
611
|
+
end
|
|
612
|
+
else
|
|
613
|
+
invoker.log(['Empty element', 'inlatex'], :error)
|
|
614
|
+
end
|
|
615
|
+
join_blocks(acc)
|
|
616
|
+
end
|
|
617
|
+
|
|
618
|
+
# Format the ltx macro
|
|
619
|
+
def format_ltx(invoker, other_args={})
|
|
620
|
+
args = invoker.args
|
|
621
|
+
acc = []
|
|
622
|
+
args["h"] ||= (args["inlineLatexHeight"] || other_args["h"])
|
|
623
|
+
args["alt"] ||= invoker.text
|
|
624
|
+
args["style"] = "latex"
|
|
625
|
+
inlatex = invoker.elt
|
|
626
|
+
if !inlatex or inlatex.empty?
|
|
627
|
+
acc << invoker.text
|
|
628
|
+
else
|
|
629
|
+
for i in inlatex
|
|
630
|
+
# acc << @deplate.formatter.include_image(i, args, true)
|
|
631
|
+
acc << format_element(:format_figure, invoker, true, i)
|
|
632
|
+
end
|
|
633
|
+
end
|
|
634
|
+
return acc.flatten.join("\n")
|
|
635
|
+
end
|
|
636
|
+
|
|
637
|
+
# Format the math macro
|
|
638
|
+
alias :format_math :format_ltx
|
|
639
|
+
|
|
640
|
+
# Process inline latex. The file names of the output are saved as an
|
|
641
|
+
# array in <tt>invoker.elt</tt>.
|
|
642
|
+
def inlatex(invoker)
|
|
643
|
+
pkgs, body = inlatex_split(invoker.accum)
|
|
644
|
+
id = inlatex_id(invoker)
|
|
645
|
+
sfx = invoker.args["sfx"] || @deplate.variables['ltxSfx'] || inlatex_sfx
|
|
646
|
+
currDir = Dir.pwd
|
|
647
|
+
@deplate.in_working_dir do
|
|
648
|
+
ftex = id + ".tex"
|
|
649
|
+
flog = id + ".log"
|
|
650
|
+
faux = id + ".aux"
|
|
651
|
+
fdvi = id + ".dvi"
|
|
652
|
+
fps = id + ".ps"
|
|
653
|
+
checkOW = true
|
|
654
|
+
|
|
655
|
+
case sfx
|
|
656
|
+
when "ps"
|
|
657
|
+
device = nil
|
|
658
|
+
fout = fps
|
|
659
|
+
checkOW = false
|
|
660
|
+
when "pdf"
|
|
661
|
+
device = "pdfwrite"
|
|
662
|
+
fout = id + ".*.pdf"
|
|
663
|
+
when "jpeg", "jpg"
|
|
664
|
+
device = "jpeg"
|
|
665
|
+
fout = id + ".*.jpeg"
|
|
666
|
+
else
|
|
667
|
+
raise "Unknown device/suffix: #{sfx}"
|
|
668
|
+
end
|
|
669
|
+
|
|
670
|
+
acc = [
|
|
671
|
+
"\\documentclass[12pt,a4paper,notitlepage]{article}",
|
|
672
|
+
"\\usepackage{amsmath}",
|
|
673
|
+
"\\usepackage{amsfonts}",
|
|
674
|
+
]
|
|
675
|
+
acc += pkgs
|
|
676
|
+
acc << "\\begin{document}" << "\\pagestyle{empty}"
|
|
677
|
+
acc += body
|
|
678
|
+
acc << "\\end{document}"
|
|
679
|
+
|
|
680
|
+
if Deplate::Region.check_file(invoker, fout, ftex, acc)
|
|
681
|
+
invoker.log(["Files exist! Using", fout], :anyway)
|
|
682
|
+
else
|
|
683
|
+
if checkOW and !@deplate.options.force
|
|
684
|
+
for f in [ftex, flog, faux, fdvi, fout]
|
|
685
|
+
if !Dir[f].empty?
|
|
686
|
+
raise "Please delete '#{f}' or change the id before proceeding:\n#{invoker.accum.join("\n")}"
|
|
687
|
+
end
|
|
688
|
+
end
|
|
689
|
+
end
|
|
690
|
+
|
|
691
|
+
acc = acc.join("\n")
|
|
692
|
+
|
|
693
|
+
Deplate::External.write_file(invoker, ftex) {|io| io.puts(acc)}
|
|
694
|
+
inlatex_process_latex(invoker, ftex, faux, flog)
|
|
695
|
+
if block_given?
|
|
696
|
+
yield(invoker, device, fdvi, fps, fout)
|
|
697
|
+
else
|
|
698
|
+
inlatex_process_dvi(invoker, fdvi, fps) if File.exist?(fdvi)
|
|
699
|
+
if device
|
|
700
|
+
inlatex_process_ps(invoker, device, fps, fout, invoker.args)
|
|
701
|
+
elsif fps != fout
|
|
702
|
+
File.rename(fps, fout)
|
|
703
|
+
end
|
|
704
|
+
end
|
|
705
|
+
end
|
|
706
|
+
|
|
707
|
+
invoker.elt = Dir[fout]
|
|
708
|
+
if invoker.elt.empty?
|
|
709
|
+
code = invoker.accum.join("\n")
|
|
710
|
+
invoker.log(["Conversion if Inline LaTeX failed", code], :error)
|
|
711
|
+
end
|
|
712
|
+
end
|
|
713
|
+
end
|
|
714
|
+
|
|
715
|
+
def inlatex_id(invoker, last=false)
|
|
716
|
+
id = invoker.args["id"]
|
|
717
|
+
unless id
|
|
718
|
+
unless last
|
|
719
|
+
@inlatex_idx += 1
|
|
720
|
+
end
|
|
721
|
+
id = @deplate.auxiliary_auto_filename('ltx', @inlatex_idx, invoker.accum)
|
|
722
|
+
invoker.log(["No id given", invoker.accum])
|
|
723
|
+
end
|
|
724
|
+
id
|
|
725
|
+
end
|
|
726
|
+
|
|
727
|
+
def inlatex_process_latex(invoker, ftex, faux, flog)
|
|
728
|
+
latex2dvi(invoker, ftex, faux, flog)
|
|
729
|
+
end
|
|
730
|
+
|
|
731
|
+
def inlatex_process_dvi(invoker, fdvi, fps)
|
|
732
|
+
dvi2ps(invoker, fdvi, fps)
|
|
733
|
+
end
|
|
734
|
+
|
|
735
|
+
def inlatex_process_ps(invoker, device, fps, fout, args)
|
|
736
|
+
ps2img(invoker, device, fps, fout, args) if File.exist?(fps)
|
|
737
|
+
end
|
|
738
|
+
|
|
739
|
+
# Divert lines in invoker#accum to the preamble or the body.
|
|
740
|
+
def inlatex_split(accum)
|
|
741
|
+
pkgs = []
|
|
742
|
+
body = []
|
|
743
|
+
for l in accum.join("\n")
|
|
744
|
+
if l =~ /^\s*\\(usepackage|input)\s*(\[.*?\])?\s*\{.+?\}\s*$/
|
|
745
|
+
pkgs << l.chomp
|
|
746
|
+
elsif l =~ /%%%\s*$/
|
|
747
|
+
pkgs << l.chomp
|
|
748
|
+
else
|
|
749
|
+
body << l.chomp
|
|
750
|
+
end
|
|
751
|
+
end
|
|
752
|
+
return pkgs.uniq, body
|
|
753
|
+
end
|
|
754
|
+
|
|
755
|
+
# The default suffix/device to be used for inlatex output.
|
|
756
|
+
def inlatex_sfx
|
|
757
|
+
"jpeg"
|
|
758
|
+
end
|
|
759
|
+
|
|
760
|
+
def latex2dvi(invoker, ftex, faux, flog)
|
|
761
|
+
if Deplate::External.latex(invoker, ftex) and @deplate.options.clean
|
|
762
|
+
for i in [faux, flog]
|
|
763
|
+
if File.exist?(i)
|
|
764
|
+
File.delete(i)
|
|
765
|
+
invoker.log(["Deleting", i])
|
|
766
|
+
end
|
|
767
|
+
end
|
|
768
|
+
end
|
|
769
|
+
end
|
|
770
|
+
|
|
771
|
+
def dvi2ps(invoker, fdvi, fps, other_options=nil)
|
|
772
|
+
# -Pwww
|
|
773
|
+
if Deplate::External.dvi2ps(invoker, fdvi, fps, other_options) and @deplate.options.clean
|
|
774
|
+
File.delete(fdvi) if @deplate.options.clean
|
|
775
|
+
invoker.log(["Deleting", fdvi])
|
|
776
|
+
end
|
|
777
|
+
end
|
|
778
|
+
|
|
779
|
+
def ps2img(invoker, device, fps, fout, args)
|
|
780
|
+
if Deplate::External.ps2img(invoker, device, fps, fout, args) and @deplate.options.clean
|
|
781
|
+
File.delete(fps)
|
|
782
|
+
invoker.log(["Deleting", fps])
|
|
783
|
+
end
|
|
784
|
+
end
|
|
785
|
+
|
|
786
|
+
|
|
787
|
+
private
|
|
788
|
+
def referenced_bib_entry(invoker, key, text)
|
|
789
|
+
text
|
|
790
|
+
end
|
|
791
|
+
|
|
792
|
+
def formatted_block(env, text, opts=nil, args=nil, no_id=false, no_indent=false)
|
|
793
|
+
text = indent_text(text) unless no_indent
|
|
794
|
+
return join_blocks([get_open(env, opts, args, :no_id => no_id), text, get_close(env, args)])
|
|
795
|
+
end
|
|
796
|
+
|
|
797
|
+
def_abstract :get_open, :get_close
|
|
798
|
+
|
|
799
|
+
def formatted_inline(env, text, opts=nil, args=nil, no_id=false)
|
|
800
|
+
return join_inline([get_open(env, opts, args, :no_id => no_id), text, get_close(env, args)])
|
|
801
|
+
end
|
|
802
|
+
|
|
803
|
+
def formatted_single(env, opts=nil, args=nil, no_id=false)
|
|
804
|
+
return get_open(env, opts, args, :single => true, :no_id => no_id)
|
|
805
|
+
end
|
|
806
|
+
|
|
807
|
+
def use_id(args, opts={}, set=true)
|
|
808
|
+
if args
|
|
809
|
+
set &&= !args[:id]
|
|
810
|
+
else
|
|
811
|
+
args = {}
|
|
812
|
+
end
|
|
813
|
+
id = opts['id'] || args[:id] || args['id']
|
|
814
|
+
# || args['label']
|
|
815
|
+
args[:id] = id if set
|
|
816
|
+
id
|
|
817
|
+
end
|
|
818
|
+
|
|
819
|
+
def use_labels(args, labels, opts={})
|
|
820
|
+
args ||= {}
|
|
821
|
+
labels = labels ? labels.dup : []
|
|
822
|
+
id = use_id(args, opts)
|
|
823
|
+
l = args["label"]
|
|
824
|
+
labels << l if l
|
|
825
|
+
# i = opts[:invoker]
|
|
826
|
+
# if i
|
|
827
|
+
# labels += i.label
|
|
828
|
+
# end
|
|
829
|
+
if opts[:with_id]
|
|
830
|
+
labels << id
|
|
831
|
+
elsif id
|
|
832
|
+
labels.delete(id)
|
|
833
|
+
end
|
|
834
|
+
labels.delete_if {|e| @consumed_labels.include?(e)}
|
|
835
|
+
labels.flatten!
|
|
836
|
+
labels.compact!
|
|
837
|
+
labels.uniq!
|
|
838
|
+
@consumed_labels += labels unless labels.empty?
|
|
839
|
+
return labels
|
|
840
|
+
end
|
|
841
|
+
|
|
842
|
+
def format_indent(level, shift=false)
|
|
843
|
+
if level < 0
|
|
844
|
+
log(["Negative indentation level", level], :error)
|
|
845
|
+
return ""
|
|
846
|
+
else
|
|
847
|
+
l = level * 2
|
|
848
|
+
# l += 1 if shift
|
|
849
|
+
return " " * l
|
|
850
|
+
end
|
|
851
|
+
end
|
|
852
|
+
|
|
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
|
+
def keywords
|
|
861
|
+
kw = @deplate.variables["keywords"]
|
|
862
|
+
if kw.kind_of?(Array)
|
|
863
|
+
kw
|
|
864
|
+
elsif kw.kind_of?(String)
|
|
865
|
+
kw.split(/\s*[,;]\s*/)
|
|
866
|
+
elsif kw
|
|
867
|
+
log(["Shouldn't be here", kw, kw.class], :error)
|
|
868
|
+
else
|
|
869
|
+
nil
|
|
870
|
+
end
|
|
871
|
+
end
|
|
872
|
+
|
|
873
|
+
# Create @plain_text_rx, which contains the keys of @special_symbols
|
|
874
|
+
# in a group. This rx will be used by #plain_text.
|
|
875
|
+
def build_plain_text_rx
|
|
876
|
+
@plain_text_rx = Regexp.new("(%s)" % @special_symbols.keys.collect {|x| Regexp.escape(x)}.join("|"))
|
|
877
|
+
end
|
|
878
|
+
|
|
879
|
+
|
|
880
|
+
################################################ Bibliography {{{1
|
|
881
|
+
def simple_bibtex_reader(bibfiles)
|
|
882
|
+
acc = []
|
|
883
|
+
for b in bibfiles
|
|
884
|
+
b = File.expand_path(b)
|
|
885
|
+
unless File.exist?(b)
|
|
886
|
+
b = Deplate::External.kpsewhich(self, b)
|
|
887
|
+
if b.empty?
|
|
888
|
+
next
|
|
889
|
+
end
|
|
890
|
+
end
|
|
891
|
+
File.open(b) {|io| acc << io.read}
|
|
892
|
+
end
|
|
893
|
+
acc = acc.join("\n")
|
|
894
|
+
loop do
|
|
895
|
+
m = /^\s*(@\w+\{\s*(\S+?)\s*,.*?)(?=(^@|\z))/m.match(acc)
|
|
896
|
+
if m
|
|
897
|
+
id = m[2]
|
|
898
|
+
e = m[1]
|
|
899
|
+
arr = e.scan(/^\s*(\w+)\s*=\s*(\{.*?\}|\d+)\s*[,}]\s*$/m)
|
|
900
|
+
arr.collect! do |var, val, rest|
|
|
901
|
+
n = /^\s*\{(.*?)\}\s*($|\}\s*\z)/m.match(val)
|
|
902
|
+
if n
|
|
903
|
+
val = n[1]
|
|
904
|
+
end
|
|
905
|
+
[var, val]
|
|
906
|
+
end
|
|
907
|
+
arr << ["type", m[2]]
|
|
908
|
+
@bibentries[id] = arr
|
|
909
|
+
acc = m.post_match
|
|
910
|
+
else
|
|
911
|
+
break
|
|
912
|
+
end
|
|
913
|
+
end
|
|
914
|
+
end
|
|
915
|
+
|
|
916
|
+
def cited_keys
|
|
917
|
+
@deplate.options.citations.collect {|c| c.elt}.flatten.uniq
|
|
918
|
+
end
|
|
919
|
+
|
|
920
|
+
def format_bibliography(invoker)
|
|
921
|
+
acc = []
|
|
922
|
+
for k in cited_keys
|
|
923
|
+
b = bib_entry(k)
|
|
924
|
+
bb = format_bib_entry(invoker, b)
|
|
925
|
+
i = encode_id(k)
|
|
926
|
+
l = format_label(invoker, :string, [i])
|
|
927
|
+
if block_given?
|
|
928
|
+
acc << [yield(i, l, bb), bb]
|
|
929
|
+
else
|
|
930
|
+
acc << [bb, bb]
|
|
931
|
+
end
|
|
932
|
+
end
|
|
933
|
+
acc = acc.sort {|a,b| a[1] <=> b[1]}
|
|
934
|
+
acc.collect! {|e| e[0]}
|
|
935
|
+
join_blocks(acc)
|
|
936
|
+
end
|
|
937
|
+
|
|
938
|
+
def format_bib_entry(invoker, bibdef)
|
|
939
|
+
key, author = bibdef.assoc("author")
|
|
940
|
+
key, editor = bibdef.assoc("editor")
|
|
941
|
+
key, how = bibdef.assoc("howpublished")
|
|
942
|
+
author = reformat_authors(author)
|
|
943
|
+
editor = reformat_authors(editor)
|
|
944
|
+
au = [nil, author || editor || how || "???"]
|
|
945
|
+
yr = bibdef.assoc("year")
|
|
946
|
+
au[1] = "%s (%s)" % [au, yr[1]] if yr
|
|
947
|
+
ti = bibdef.assoc("title")
|
|
948
|
+
bt = bibdef.assoc("booktitle")
|
|
949
|
+
pu = bibdef.assoc("publisher")
|
|
950
|
+
i = bibdef.assoc("journal")
|
|
951
|
+
if i
|
|
952
|
+
vol = bibdef.assoc("volume")
|
|
953
|
+
vol &&= vol[1]
|
|
954
|
+
nr = bibdef.assoc("number")
|
|
955
|
+
nr &&= "(" + nr[1] +")"
|
|
956
|
+
i[1] += [" ", vol, nr].join if vol or nr
|
|
957
|
+
elsif author and editor
|
|
958
|
+
i = [nil, editor]
|
|
959
|
+
t = bt || ti
|
|
960
|
+
if t
|
|
961
|
+
i << ": " << t[1]
|
|
962
|
+
end
|
|
963
|
+
end
|
|
964
|
+
p = bibdef.assoc("pages")
|
|
965
|
+
if i
|
|
966
|
+
hi = "journal"
|
|
967
|
+
elsif bt
|
|
968
|
+
hi = "booktitle"
|
|
969
|
+
else
|
|
970
|
+
hi = "title"
|
|
971
|
+
end
|
|
972
|
+
bb = [au, ti, bt, pu, i, p].compact.collect do |key, val|
|
|
973
|
+
val = simple_latex_reformat(val)
|
|
974
|
+
val = %{__#{val}__} if key == hi
|
|
975
|
+
val
|
|
976
|
+
end
|
|
977
|
+
return @deplate.parse_and_format_without_wikinames(invoker, bb.join(". ") + ".")
|
|
978
|
+
end
|
|
979
|
+
|
|
980
|
+
def simple_latex_reformat(text)
|
|
981
|
+
text.gsub!(/^\{(.*)\}$/, "\\1")
|
|
982
|
+
text.gsub!(/\s+/m, " ")
|
|
983
|
+
text.gsub!(/``/, %{"})
|
|
984
|
+
text.gsub!(/''/, %{"})
|
|
985
|
+
text.gsub!(/`/, %{'})
|
|
986
|
+
text.gsub!(/'/, %{'})
|
|
987
|
+
# text.gsub!(/--/, %{--})
|
|
988
|
+
text.gsub!(/\\([$&%#_{}^~|])(\{\})?/, "\\1")
|
|
989
|
+
return text
|
|
990
|
+
end
|
|
991
|
+
|
|
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
|
+
# this is the general function used for formatting lists of any kind; it
|
|
1023
|
+
# relies on #format_list, #format_indent and #format_list_item to
|
|
1024
|
+
# do the actual output
|
|
1025
|
+
def printable_list(invoker, list=nil)
|
|
1026
|
+
list ||= invoker.elt
|
|
1027
|
+
unless list.nil? or list.empty?
|
|
1028
|
+
@levels = []
|
|
1029
|
+
@types = []
|
|
1030
|
+
@endTags = []
|
|
1031
|
+
accum = []
|
|
1032
|
+
# level0 = list.sort {|a,b| a.level <=> b.level}[0].level
|
|
1033
|
+
level0 = list.min {|a,b| a.level <=> b.level}.level
|
|
1034
|
+
ind = 0
|
|
1035
|
+
max = list.size - 1
|
|
1036
|
+
|
|
1037
|
+
list.each_with_index do |i, idx|
|
|
1038
|
+
# :listtype, :type, :level, :item, :body
|
|
1039
|
+
t = i.type
|
|
1040
|
+
s = list_subtype(t, i.item)
|
|
1041
|
+
c = [i.listtype, s]
|
|
1042
|
+
l = i.level
|
|
1043
|
+
if last_listtype
|
|
1044
|
+
# 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
|
|
1047
|
+
# close a nested list
|
|
1048
|
+
ind = printable_close_lists_until(invoker, accum, ind, l)
|
|
1049
|
+
elsif l > last_level and t != "Paragraph"
|
|
1050
|
+
# open a new nested list
|
|
1051
|
+
# p "DBG --- 1054: #{c} != #{last_listtype}"
|
|
1052
|
+
ind = printable_open_list(invoker, accum, c, ind, l, s)
|
|
1053
|
+
@endTags << nil
|
|
1054
|
+
end
|
|
1055
|
+
end
|
|
1056
|
+
if last_level and last_listtype and c != last_listtype and t != "Paragraph"
|
|
1057
|
+
if l <= last_level
|
|
1058
|
+
# close the previous list and start a new one
|
|
1059
|
+
ind = printable_list_close_endtag(invoker, accum, ind)
|
|
1060
|
+
# p "DBG ---- #{last_listtype} #{t}"
|
|
1061
|
+
end
|
|
1062
|
+
if c != last_listtype and l <= last_level
|
|
1063
|
+
# p "DBG --- 1067: #{c} != #{last_listtype}"
|
|
1064
|
+
ind = printable_close_list(invoker, accum, ind)
|
|
1065
|
+
ind = printable_open_list(invoker, accum, c, ind, l, s)
|
|
1066
|
+
@endTags << nil
|
|
1067
|
+
end
|
|
1068
|
+
end
|
|
1069
|
+
else
|
|
1070
|
+
# start a new list
|
|
1071
|
+
ind = printable_open_list(invoker, accum, c, ind, l, s)
|
|
1072
|
+
end
|
|
1073
|
+
if @levels.empty? and idx < max
|
|
1074
|
+
# something weired happened (e.g. the previous list item was
|
|
1075
|
+
# deeper nested, but this item doesn't continue anything --
|
|
1076
|
+
# which should probably considered as a syntax error anyway)
|
|
1077
|
+
invoker.log(["Malformed list hierarchy", last_listtype, idx], :error)
|
|
1078
|
+
ind = printable_open_list(invoker, accum, c, ind, l, s)
|
|
1079
|
+
end
|
|
1080
|
+
if t == "Paragraph"
|
|
1081
|
+
acc, etag = format_list_item(invoker, t, ind, i)
|
|
1082
|
+
accum << acc
|
|
1083
|
+
else
|
|
1084
|
+
ind = printable_list_close_endtag(invoker, accum, ind)
|
|
1085
|
+
# p "DBG #{' ' * l} Item (#{@types} #{@levels})"
|
|
1086
|
+
acc, etag = format_list_item(invoker, t, ind, i)
|
|
1087
|
+
@endTags << [etag, l, ind]
|
|
1088
|
+
accum << acc
|
|
1089
|
+
ind += 1
|
|
1090
|
+
end
|
|
1091
|
+
if i.label and !i.label.empty?
|
|
1092
|
+
lab = format_label(invoker, :string, i.label)
|
|
1093
|
+
if lab
|
|
1094
|
+
accum[-1] += lab
|
|
1095
|
+
end
|
|
1096
|
+
end
|
|
1097
|
+
end
|
|
1098
|
+
|
|
1099
|
+
# close all open tags & lists
|
|
1100
|
+
while !@endTags.empty?
|
|
1101
|
+
ind = printable_list_close_endtag(invoker, accum, ind)
|
|
1102
|
+
end
|
|
1103
|
+
while !@levels.empty?
|
|
1104
|
+
ind = printable_close_list(invoker, accum, ind)
|
|
1105
|
+
end
|
|
1106
|
+
if ind < 0
|
|
1107
|
+
invoker.log("Malformed list or internal error", :error)
|
|
1108
|
+
end
|
|
1109
|
+
|
|
1110
|
+
accum.delete_if {|e| e == :empty}
|
|
1111
|
+
return accum.join("\n")
|
|
1112
|
+
else
|
|
1113
|
+
return ""
|
|
1114
|
+
end
|
|
1115
|
+
end
|
|
1116
|
+
|
|
1117
|
+
def last_level
|
|
1118
|
+
@levels.last
|
|
1119
|
+
end
|
|
1120
|
+
|
|
1121
|
+
def last_listtype
|
|
1122
|
+
@types.last
|
|
1123
|
+
end
|
|
1124
|
+
|
|
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
|
+
def list_subtype(type, item)
|
|
1140
|
+
case type
|
|
1141
|
+
when "Numbered"
|
|
1142
|
+
if item =~ /^[A-Z]\.?$/
|
|
1143
|
+
return "A"
|
|
1144
|
+
elsif item =~ /^[a-z?@]\.?$/
|
|
1145
|
+
return "a"
|
|
1146
|
+
else
|
|
1147
|
+
return "1"
|
|
1148
|
+
end
|
|
1149
|
+
when "Itemize"
|
|
1150
|
+
return nil
|
|
1151
|
+
when "Description"
|
|
1152
|
+
return nil
|
|
1153
|
+
when "Paragraph"
|
|
1154
|
+
return nil
|
|
1155
|
+
else
|
|
1156
|
+
raise "Unknown list type: #{type}"
|
|
1157
|
+
end
|
|
1158
|
+
end
|
|
1159
|
+
|
|
1160
|
+
def printable_close_lists_until(invoker, accum, ind, level)
|
|
1161
|
+
begin
|
|
1162
|
+
ind = printable_list_close_endtag(invoker, accum, ind)
|
|
1163
|
+
ind = printable_close_list(invoker, accum, ind)
|
|
1164
|
+
end until @levels.empty? or @levels.last <= level
|
|
1165
|
+
ind
|
|
1166
|
+
end
|
|
1167
|
+
|
|
1168
|
+
def printable_close_list(invoker, accum, ind)
|
|
1169
|
+
ind -= 1
|
|
1170
|
+
lev = @levels.pop
|
|
1171
|
+
tp, sp = @types.pop
|
|
1172
|
+
# p "DBG #{' ' * (lev || 1)}>close #{lev} #{tp} #{sp} #{caller[0]}"
|
|
1173
|
+
le = format_list_env(invoker, tp, ind, :close, sp)
|
|
1174
|
+
accum << le if le
|
|
1175
|
+
ind
|
|
1176
|
+
end
|
|
1177
|
+
|
|
1178
|
+
def printable_open_list(invoker, accum, type, ind, level, subtype=nil)
|
|
1179
|
+
t, s = type
|
|
1180
|
+
le = format_list_env(invoker, t, ind, :open, subtype)
|
|
1181
|
+
accum << le if le
|
|
1182
|
+
ind += 1
|
|
1183
|
+
@levels << level
|
|
1184
|
+
@types << type
|
|
1185
|
+
# p "DBG #{' ' * (level || 1)}<open #{level} #{type} #{subtype} #{caller[0]}"
|
|
1186
|
+
ind
|
|
1187
|
+
end
|
|
1188
|
+
|
|
1189
|
+
def printable_list_close_endtag(invoker, accum, ind)
|
|
1190
|
+
tag, level, ind0 = @endTags.pop
|
|
1191
|
+
if tag
|
|
1192
|
+
while @levels.last and @levels.last > level
|
|
1193
|
+
ind = printable_close_list(invoker, accum, ind)
|
|
1194
|
+
end
|
|
1195
|
+
accum << tag unless tag == :none
|
|
1196
|
+
end
|
|
1197
|
+
return ind0 || ind
|
|
1198
|
+
end
|
|
1199
|
+
|
|
1200
|
+
def list_item_explicit_value(item, explicit=false)
|
|
1201
|
+
if @deplate.variables['noExplicitNumbering']
|
|
1202
|
+
nil
|
|
1203
|
+
elsif explicit or item.explicit and item.item and !item.item.empty?
|
|
1204
|
+
item.item
|
|
1205
|
+
else
|
|
1206
|
+
nil
|
|
1207
|
+
end
|
|
1208
|
+
end
|
|
1209
|
+
end
|
|
1210
|
+
|