texml 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. data/bin/texml +12 -0
  2. data/lib/texml.rb +200 -0
  3. metadata +68 -0
data/bin/texml ADDED
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rubygems'
3
+ require 'texml'
4
+
5
+ xml = ARGF.read
6
+ begin
7
+ print TeXML.convert(xml)
8
+ rescue XMLParserError
9
+ puts "#{$0}: #{$!}"
10
+ exit 1
11
+ end
12
+
data/lib/texml.rb ADDED
@@ -0,0 +1,200 @@
1
+ ########################################
2
+ # texml.rb
3
+ # Author: Pierre-Charles David (pcdavid@gmail.com)
4
+ # Version: 0.4
5
+ # Web page: http://github.com/pcdavid/ruby-texml
6
+ # Depends on: xmlparser (available on RAA)
7
+ # License: WTFPL: http://sam.zoy.org/wtfpl/COPYING
8
+
9
+ # Based of Douglas Lovell's paper:
10
+ # "TeXML: Typesetting with TeX", Douglas Lovell, IBM Research
11
+ # in TUGboat, Volume 20 (1999), No. 3
12
+ #
13
+ # Original implementation in Java by D. Lovell, available on IBM
14
+ # alphaWorks: http://www.alphaworks.ibm.com/tech/texml
15
+ #
16
+ # Usage: % texml.rb < input.xml > output.tex
17
+
18
+ require "xmltreebuilder"
19
+
20
+ module TeXML
21
+
22
+ # Escaping sequences for LaTeX special characters
23
+ SPECIAL_CHAR_ESCAPES = {
24
+ '%'[0] => '\%{}',
25
+ '{'[0] => '\{',
26
+ '}'[0] => '\}',
27
+ '|'[0] => '$|${}',
28
+ '#'[0] => '\#{}',
29
+ '_'[0] => '\_{}',
30
+ '^'[0] => '\\char`\\^{}',
31
+ '~'[0] => '\\char`\\~{}',
32
+ '&'[0] => '\&{}',
33
+ '$'[0] => '\${}', #'
34
+ '<'[0] => '$<${}', #'
35
+ '>'[0] => '$>${}', #'
36
+ '\\'[0] => '$\\backslash${}'#'
37
+ }
38
+
39
+ # Converts a TeXML document, passed as a raw XML string, into the
40
+ # corresponding (La)TeX document.
41
+ def TeXML.convert(xml)
42
+ builder = XML::SimpleTreeBuilder.new
43
+ tree = builder.parse(xml)
44
+ TeXML::Node.create(tree.documentElement).to_tex
45
+ end
46
+
47
+ # Given a raw string, returns a copy with all (La)TeX special
48
+ # characters properly quoted.
49
+ def TeXML.quote(str)
50
+ tex = ''
51
+ str.each_byte do |char|
52
+ tex << (SPECIAL_CHAR_ESCAPES[char] or char)
53
+ end
54
+ return tex
55
+ end
56
+
57
+ # Keeps track of which classes can handle which type of nodes
58
+ NODE_HANDLERS = Hash.new
59
+
60
+ # Common node superclass (also node factory, see Node#create)
61
+ class Node
62
+
63
+ # Creates a node handler object appropriate for the specified XML
64
+ # node, based on the name of the node (uses information from
65
+ # NODE_HANDLERS).
66
+ def Node.create(domNode)
67
+ handlerClass = NODE_HANDLERS[domNode.nodeName]
68
+ if !handlerClass.nil?
69
+ handlerClass.new(domNode)
70
+ else
71
+ nil
72
+ end
73
+ end
74
+
75
+ def initialize(node)
76
+ @node = node
77
+ end
78
+
79
+ # Aggregates the values of all the children of this Node whose
80
+ # node name is included in the parameters, in the document order
81
+ # of the children.
82
+ def childrenValue(*childTypes)
83
+ tex = ''
84
+ @node.childNodes do |kid|
85
+ if childTypes.include?(kid.nodeName)
86
+ node = Node.create(kid)
87
+ tex << node.to_tex unless node.nil?
88
+ end
89
+ end
90
+ return tex
91
+ end
92
+ end
93
+
94
+ class TexmlNode < Node
95
+ NODE_HANDLERS['TeXML'] = TexmlNode
96
+
97
+ def to_tex
98
+ return childrenValue('cmd', 'env', 'ctrl', 'spec', '#text')
99
+ end
100
+ end
101
+
102
+ class CmdNode < Node
103
+ NODE_HANDLERS['cmd'] = CmdNode
104
+
105
+ def to_tex
106
+ name = @node.getAttribute('name')
107
+ nl_before = (@node.getAttribute('nl1') == '1') ? "\n" : ''
108
+ nl_after = (@node.getAttribute('nl2') == '1') ? "\n" : ''
109
+ return nl_before + "\\#{name}" + childrenValue('opt') + childrenValue('parm') + ' ' + nl_after
110
+ end
111
+ end
112
+
113
+ class EnvNode < Node
114
+ NODE_HANDLERS['env'] = EnvNode
115
+
116
+ def to_tex
117
+ name = @node.getAttribute('name')
118
+ start = @node.getAttribute('begin')
119
+ start = 'begin' if start == ''
120
+ stop = @node.getAttribute('end')
121
+ stop = 'end' if stop == ''
122
+ return "\\#{start}{#{name}}\n" +
123
+ childrenValue('cmd', 'env', 'ctrl', 'spec', '#text') +
124
+ "\\#{stop}{#{name}}\n"
125
+ end
126
+ end
127
+
128
+ class OptNode < Node
129
+ NODE_HANDLERS['opt'] = OptNode
130
+
131
+ def to_tex
132
+ return "[" + childrenValue('cmd', 'ctrl', 'spec', '#text') + "]"
133
+ end
134
+ end
135
+
136
+ class ParmNode < Node
137
+ NODE_HANDLERS['parm'] = ParmNode
138
+
139
+ def to_tex
140
+ return "{" + childrenValue('cmd', 'ctrl', 'spec', '#text') + "}"
141
+ end
142
+ end
143
+
144
+ class CtrlNode < Node
145
+ NODE_HANDLERS['ctrl'] = CtrlNode
146
+
147
+ def to_tex
148
+ ch = @node.getAttribute('ch')
149
+ unless ch.nil?
150
+ return ch & 0x9F # Control version of ch
151
+ else
152
+ nil
153
+ end
154
+ end
155
+ end
156
+
157
+ class GroupNode < Node
158
+ NODE_HANDLERS['group'] = GroupNode
159
+
160
+ def to_tex
161
+ return "{" + childrenValue('cmd', 'env', 'ctrl', 'spec', '#text') + "}"
162
+ end
163
+ end
164
+
165
+ class SpecNode < Node
166
+ NODE_HANDLERS['spec'] = SpecNode
167
+
168
+ SPECIAL_MAP = {
169
+ 'esc' => "\\",
170
+ 'bg' => '{',
171
+ 'eg' => '}',
172
+ 'mshift' => '$', # '
173
+ 'align' => '&',
174
+ 'parm' => '#',
175
+ 'sup' => '^',
176
+ 'sub' => '_',
177
+ 'tilde' => '~',
178
+ 'comment' => '%'
179
+ }
180
+
181
+ def to_tex
182
+ cat = @node.getAttribute('cat')
183
+ return (SPECIAL_MAP[cat] or '')
184
+ end
185
+ end
186
+
187
+ class TextNode < Node
188
+ NODE_HANDLERS['#text'] = TextNode
189
+
190
+ def to_tex
191
+ parent = @node.parentNode
192
+ if parent.nodeName == 'env' && parent.getAttribute('name') == 'verbatim'
193
+ return @node.nodeValue # TODO: is there /some/ quoting to do?
194
+ else
195
+ return TeXML.quote(@node.nodeValue)
196
+ end
197
+ end
198
+ end
199
+
200
+ end
metadata ADDED
@@ -0,0 +1,68 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: texml
3
+ version: !ruby/object:Gem::Version
4
+ hash: 15
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 4
9
+ - 0
10
+ version: 0.4.0
11
+ platform: ruby
12
+ authors:
13
+ - Pierre-Charles David
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-11-21 00:00:00 +01:00
19
+ default_executable:
20
+ dependencies: []
21
+
22
+ description: "This program converts an XML document conforming to the TeXML syntax into the corresponding (La)TeX document, ready to be typeset. It is based on Douglas Lovell's paper: \"TeXML: Typesetting with TeX\", Douglas Lovell, IBM Research in TUGboat, Volume 20 (1999), No. 3"
23
+ email: pcdavid@gmail.com
24
+ executables:
25
+ - texml
26
+ extensions: []
27
+
28
+ extra_rdoc_files: []
29
+
30
+ files:
31
+ - lib/texml.rb
32
+ - bin/texml
33
+ has_rdoc: true
34
+ homepage: http://github.com/pcdavid/ruby-texml
35
+ licenses: []
36
+
37
+ post_install_message:
38
+ rdoc_options: []
39
+
40
+ require_paths:
41
+ - lib
42
+ required_ruby_version: !ruby/object:Gem::Requirement
43
+ none: false
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ hash: 3
48
+ segments:
49
+ - 0
50
+ version: "0"
51
+ required_rubygems_version: !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ hash: 3
57
+ segments:
58
+ - 0
59
+ version: "0"
60
+ requirements: []
61
+
62
+ rubyforge_project:
63
+ rubygems_version: 1.3.7
64
+ signing_key:
65
+ specification_version: 3
66
+ summary: A TeXML to LaTeX converter.
67
+ test_files: []
68
+