texml 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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
+