asciidoctor-mathematical 0.1.0 → 0.3.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/lib/asciidoctor-mathematical/extension.rb +175 -85
- metadata +41 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: e817ca8a177571fe61d368e26b09d8b35e1560b38ac8f971e14281f403b88344
|
4
|
+
data.tar.gz: 96d5d392cdf0ff18fd2d4bb3972247230f2c00b552b345ef42202f3327eede11
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0a50106271975fa4975ff5511f969106e088de7e0a94d4fd64b65eff1c29d97c1131bdad2547732a90ca30555dd28c5fc2b31a2e74fc86b460764ace24dde8a1
|
7
|
+
data.tar.gz: ec3da1e35a5d0ab1ef4ff6005b0aa81802e477400b87078564b0a9d32e85e92a6a1c288b02c048ef1a17ddd44e002e00030ff8ef4f7a304915200258068ea4e7
|
@@ -1,143 +1,233 @@
|
|
1
1
|
require 'pathname'
|
2
2
|
require 'asciidoctor/extensions'
|
3
|
+
require 'asciimath'
|
3
4
|
|
4
5
|
autoload :Digest, 'digest'
|
5
6
|
autoload :Mathematical, 'mathematical'
|
6
7
|
|
7
8
|
class MathematicalTreeprocessor < Asciidoctor::Extensions::Treeprocessor
|
8
9
|
LineFeed = %(\n)
|
9
|
-
StemInlineMacroRx = /\\?(?:stem|latexmath):([a-z,]*)\[(.*?[^\\])\]/m
|
10
|
+
StemInlineMacroRx = /\\?(?:stem|latexmath|asciimath):([a-z,]*)\[(.*?[^\\])\]/m
|
10
11
|
LatexmathInlineMacroRx = /\\?latexmath:([a-z,]*)\[(.*?[^\\])\]/m
|
12
|
+
AsciiMathInlineMacroRx = /\\?asciimath:([a-z,]*)\[(.*?[^\\])\]/m
|
11
13
|
|
12
14
|
def process document
|
13
|
-
to_html = document.basebackend? 'html'
|
14
15
|
format = ((document.attr 'mathematical-format') || 'png').to_sym
|
15
16
|
if format != :png and format != :svg
|
16
17
|
warn %(Unknown format '#{format}', retreat to 'png')
|
17
18
|
format = :png
|
18
19
|
end
|
19
|
-
image_ext = %(.#{format})
|
20
20
|
ppi = ((document.attr 'mathematical-ppi') || '300.0').to_f
|
21
21
|
ppi = format == :png ? ppi : 72.0
|
22
|
+
inline = document.attr 'mathematical-inline'
|
23
|
+
if inline and format == :png
|
24
|
+
warn 'Can\'t use mathematical-inline together with mathematical-format=png'
|
25
|
+
end
|
22
26
|
# The no-args constructor defaults to SVG and standard delimiters ($..$ for inline, $$..$$ for block)
|
23
27
|
mathematical = ::Mathematical.new format: format, ppi: ppi
|
24
|
-
|
25
|
-
|
26
|
-
unless (stem_blocks = document.find_by context: :stem).nil_or_empty?
|
28
|
+
unless inline
|
29
|
+
image_output_dir, image_target_dir = image_output_and_target_dir document
|
27
30
|
::Asciidoctor::Helpers.mkdir_p image_output_dir unless ::File.directory? image_output_dir
|
31
|
+
end
|
28
32
|
|
33
|
+
unless (stem_blocks = document.find_by context: :stem).nil_or_empty?
|
29
34
|
stem_blocks.each do |stem|
|
30
|
-
|
31
|
-
|
32
|
-
|
35
|
+
handle_stem_block stem, mathematical, image_output_dir, image_target_dir, format, inline
|
36
|
+
end
|
37
|
+
end
|
33
38
|
|
34
|
-
|
35
|
-
|
36
|
-
|
39
|
+
unless (prose_blocks = document.find_by {|b|
|
40
|
+
(b.content_model == :simple && (b.subs.include? :macros)) || b.context == :list_item
|
41
|
+
}).nil_or_empty?
|
42
|
+
prose_blocks.each do |prose|
|
43
|
+
handle_prose_block prose, mathematical, image_output_dir, image_target_dir, format, inline
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# handle table cells of the "asciidoc" type, as suggested by mojavelinux
|
48
|
+
# at asciidoctor/asciidoctor-mathematical#20.
|
49
|
+
unless (table_blocks = document.find_by context: :table).nil_or_empty?
|
50
|
+
table_blocks.each do |table|
|
51
|
+
(table.rows[:body] + table.rows[:foot]).each do |row|
|
52
|
+
row.each do |cell|
|
53
|
+
if cell.style == :asciidoc
|
54
|
+
process cell.inner_document
|
55
|
+
elsif cell.style != :literal
|
56
|
+
handle_nonasciidoc_table_cell cell, mathematical, image_output_dir, image_target_dir, format, inline
|
57
|
+
end
|
58
|
+
end
|
37
59
|
end
|
60
|
+
end
|
61
|
+
end
|
38
62
|
|
39
|
-
|
63
|
+
unless (sect_blocks = document.find_by content: :section).nil_or_empty?
|
64
|
+
sect_blocks.each do |sect|
|
65
|
+
handle_section_title sect, mathematical, image_output_dir, image_target_dir, format, inline
|
66
|
+
end
|
67
|
+
end
|
40
68
|
|
41
|
-
|
42
|
-
|
43
|
-
image_target = ::File.join image_target_dir, image_target unless image_target_dir == '.'
|
69
|
+
nil
|
70
|
+
end
|
44
71
|
|
45
|
-
|
46
|
-
|
47
|
-
::IO.write image_file, result[:data]
|
72
|
+
def handle_stem_block(stem, mathematical, image_output_dir, image_target_dir, format, inline)
|
73
|
+
equation_type = stem.style.to_sym
|
48
74
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
75
|
+
case equation_type
|
76
|
+
when :latexmath
|
77
|
+
content = stem.content
|
78
|
+
when :asciimath
|
79
|
+
content = AsciiMath.parse(stem.content).to_latex
|
80
|
+
else
|
81
|
+
return
|
82
|
+
end
|
83
|
+
|
84
|
+
img_target, img_width, img_height = make_equ_image content, stem.id, false, mathematical, image_output_dir, image_target_dir, format, inline
|
85
|
+
|
86
|
+
parent = stem.parent
|
87
|
+
if inline
|
88
|
+
stem_image = create_pass_block parent, %{<div class="stemblock"> #{img_target} </div>}, {}
|
89
|
+
parent.blocks[parent.blocks.index stem] = stem_image
|
90
|
+
else
|
91
|
+
alt_text = stem.attr 'alt', (equation_type == :latexmath ? %($$#{content}$$) : %(`#{content}`))
|
92
|
+
attrs = {'target' => img_target, 'alt' => alt_text, 'align' => 'center'}
|
93
|
+
# NOTE: The following setups the *intended width and height in pixel* for png images, which can be different that that of the generated image when PPIs larger than 72.0 is used.
|
94
|
+
if format == :png
|
95
|
+
attrs['width'] = %(#{img_width})
|
96
|
+
attrs['height'] = %(#{img_height})
|
97
|
+
end
|
98
|
+
parent = stem.parent
|
99
|
+
stem_image = create_image_block parent, attrs
|
100
|
+
stem_image.id = stem.id if stem.id
|
101
|
+
if (title = stem.attributes['title'])
|
102
|
+
stem_image.title = title
|
61
103
|
end
|
104
|
+
parent.blocks[parent.blocks.index stem] = stem_image
|
62
105
|
end
|
106
|
+
end
|
63
107
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
source.gsub!(stem_rx) {
|
76
|
-
if (m = $~)[0].start_with? '\\'
|
77
|
-
next m[0][1..-1]
|
78
|
-
end
|
108
|
+
def handle_prose_block(prose, mathematical, image_output_dir, image_target_dir, format, inline)
|
109
|
+
text = prose.context == :list_item ? (prose.instance_variable_get :@text) : (prose.lines * LineFeed)
|
110
|
+
text, source_modified = handle_inline_stem prose, text, mathematical, image_output_dir, image_target_dir, format, inline
|
111
|
+
if source_modified
|
112
|
+
if prose.context == :list_item
|
113
|
+
prose.instance_variable_set :@text, text
|
114
|
+
else
|
115
|
+
prose.lines = text.split LineFeed
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
79
119
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
120
|
+
def handle_nonasciidoc_table_cell(cell, mathematical, image_output_dir, image_target_dir, format, inline)
|
121
|
+
text = cell.instance_variable_get :@text
|
122
|
+
text, source_modified = handle_inline_stem cell, text, mathematical, image_output_dir, image_target_dir, format, inline
|
123
|
+
if source_modified
|
124
|
+
cell.instance_variable_set :@text, text
|
125
|
+
end
|
126
|
+
end
|
85
127
|
|
86
|
-
|
87
|
-
|
88
|
-
|
128
|
+
def handle_section_title(sect, mathematical, image_output_dir, image_target_dir, format, inline)
|
129
|
+
text = sect.instance_variable_get :@title
|
130
|
+
text, source_modified = handle_inline_stem sect, text, mathematical, image_output_dir, image_target_dir, format, inline
|
131
|
+
if source_modified
|
132
|
+
sect.instance_variable_set :@title, text
|
133
|
+
sect.remove_instance_variable :@subbed_title
|
134
|
+
end
|
135
|
+
end
|
89
136
|
|
90
|
-
|
91
|
-
|
137
|
+
def handle_inline_stem(node, text, mathematical, image_output_dir, image_target_dir, format, inline)
|
138
|
+
document = node.document
|
139
|
+
to_html = document.basebackend? 'html'
|
92
140
|
|
93
|
-
|
94
|
-
|
95
|
-
|
141
|
+
case document.attr 'stem'
|
142
|
+
when 'latexmath'
|
143
|
+
support_stem_prefix = true
|
144
|
+
stem_rx = LatexmathInlineMacroRx
|
145
|
+
when 'asciimath'
|
146
|
+
support_stem_prefix = true
|
147
|
+
stem_rx = AsciiMathInlineMacroRx
|
148
|
+
else
|
149
|
+
support_stem_prefix = false
|
150
|
+
stem_rx = StemInlineMacroRx
|
151
|
+
end
|
96
152
|
|
97
|
-
|
153
|
+
source_modified = false
|
98
154
|
|
99
|
-
|
100
|
-
|
101
|
-
|
155
|
+
# TODO skip passthroughs in the source (e.g., +stem:[x^2]+)
|
156
|
+
if text != nil && text.include? ':'
|
157
|
+
text = text.gsub(stem_rx) {
|
158
|
+
if (m = $~)[0].start_with? '\\'
|
159
|
+
next m[0][1..-1]
|
160
|
+
end
|
102
161
|
|
103
|
-
if
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
block.lines = source.split LineFeed
|
108
|
-
end
|
162
|
+
if (eq_data = m[2].rstrip).empty?
|
163
|
+
next
|
164
|
+
else
|
165
|
+
source_modified = true
|
109
166
|
end
|
110
|
-
|
167
|
+
|
168
|
+
if text.include? 'asciimath:'
|
169
|
+
eq_data = AsciiMath.parse(eq_data).to_latex
|
170
|
+
else if (support_stem_prefix && (text.include? 'stem:')) || (text.include? 'latexmath:')
|
171
|
+
eq_data.gsub! '\]', ']'
|
172
|
+
subs = m[1].nil_or_empty? ? (to_html ? [:specialcharacters] : []) : (node.resolve_pass_subs m[1])
|
173
|
+
eq_data = node.apply_subs eq_data, subs unless subs.empty?
|
174
|
+
else
|
175
|
+
source_modified = false
|
176
|
+
return text
|
177
|
+
end
|
178
|
+
|
179
|
+
img_target, img_width, img_height = make_equ_image eq_data, nil, true, mathematical, image_output_dir, image_target_dir, format, inline
|
180
|
+
if inline
|
181
|
+
%(pass:[<span class="steminline"> #{img_target} </span>])
|
182
|
+
else
|
183
|
+
%(image:#{img_target}[width=#{img_width},height=#{img_height}])
|
184
|
+
end
|
185
|
+
}
|
111
186
|
end
|
112
187
|
|
113
|
-
|
188
|
+
[text, source_modified]
|
114
189
|
end
|
115
190
|
|
116
|
-
def
|
117
|
-
|
191
|
+
def make_equ_image(equ_data, equ_id, equ_inline, mathematical, image_output_dir, image_target_dir, format, inline)
|
192
|
+
input = equ_inline ? %($#{equ_data}$) : %($$#{equ_data}$$)
|
193
|
+
|
194
|
+
# TODO: Handle exceptions.
|
195
|
+
result = mathematical.parse input
|
196
|
+
if inline
|
197
|
+
result[:data]
|
198
|
+
else
|
199
|
+
unless equ_id
|
200
|
+
equ_id = %(stem-#{::Digest::MD5.hexdigest input})
|
201
|
+
end
|
202
|
+
image_ext = %(.#{format})
|
203
|
+
img_target = %(#{equ_id}#{image_ext})
|
204
|
+
img_file = ::File.join image_output_dir, img_target
|
205
|
+
|
206
|
+
::IO.write img_file, result[:data]
|
207
|
+
|
208
|
+
img_target = ::File.join image_target_dir, img_target unless image_target_dir == '.'
|
209
|
+
[img_target, result[:width], result[:height]]
|
210
|
+
end
|
211
|
+
end
|
118
212
|
|
119
|
-
|
213
|
+
def image_output_and_target_dir(doc)
|
214
|
+
output_dir = doc.attr('imagesoutdir')
|
120
215
|
if output_dir
|
121
|
-
|
122
|
-
if parent.attr('imagesdir').nil_or_empty?
|
216
|
+
if doc.attr('imagesdir').nil_or_empty?
|
123
217
|
target_dir = output_dir
|
124
218
|
else
|
125
219
|
# When imagesdir attribute is set, every relative path is prefixed with it. So the real target dir shall then be relative to the imagesdir, instead of being relative to document root.
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
p1 = ::Pathname.new abs_outdir
|
130
|
-
p2 = ::Pathname.new abs_imagesdir
|
131
|
-
target_dir = p1.relative_path_from(p2).to_s
|
220
|
+
abs_imagesdir = ::Pathname.new doc.normalize_system_path(doc.attr('imagesdir'))
|
221
|
+
abs_outdir = ::Pathname.new doc.normalize_system_path(output_dir)
|
222
|
+
target_dir = abs_outdir.relative_path_from(abs_imagesdir).to_s
|
132
223
|
end
|
133
224
|
else
|
134
|
-
|
135
|
-
output_dir = parent.attr('imagesdir')
|
225
|
+
output_dir = doc.attr('imagesdir')
|
136
226
|
# since we store images directly to imagesdir, target dir shall be NULL and asciidoctor converters will prefix imagesdir.
|
137
227
|
target_dir = "."
|
138
228
|
end
|
139
229
|
|
140
|
-
output_dir =
|
230
|
+
output_dir = doc.normalize_system_path(output_dir, doc.attr('docdir'))
|
141
231
|
return [output_dir, target_dir]
|
142
232
|
end
|
143
233
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: asciidoctor-mathematical
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tobias Stumm
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date:
|
13
|
+
date: 2017-01-09 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: ruby-enum
|
@@ -52,20 +52,54 @@ dependencies:
|
|
52
52
|
requirements:
|
53
53
|
- - "~>"
|
54
54
|
- !ruby/object:Gem::Version
|
55
|
-
version: '
|
55
|
+
version: '2.0'
|
56
56
|
- - ">="
|
57
57
|
- !ruby/object:Gem::Version
|
58
|
-
version:
|
58
|
+
version: 2.0.0
|
59
59
|
type: :runtime
|
60
60
|
prerelease: false
|
61
61
|
version_requirements: !ruby/object:Gem::Requirement
|
62
62
|
requirements:
|
63
63
|
- - "~>"
|
64
64
|
- !ruby/object:Gem::Version
|
65
|
-
version: '
|
65
|
+
version: '2.0'
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 2.0.0
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: asciimath
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 2.0.0
|
66
76
|
- - ">="
|
67
77
|
- !ruby/object:Gem::Version
|
68
|
-
version:
|
78
|
+
version: 2.0.0
|
79
|
+
type: :runtime
|
80
|
+
prerelease: false
|
81
|
+
version_requirements: !ruby/object:Gem::Requirement
|
82
|
+
requirements:
|
83
|
+
- - "~>"
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: 2.0.0
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: 2.0.0
|
89
|
+
- !ruby/object:Gem::Dependency
|
90
|
+
name: rake
|
91
|
+
requirement: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - "~>"
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: 12.3.0
|
96
|
+
type: :development
|
97
|
+
prerelease: false
|
98
|
+
version_requirements: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - "~>"
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: 12.3.0
|
69
103
|
description: An Asciidoctor extension to converts latexmath equations to SVG or PNGs
|
70
104
|
email: tstumm@users.noreply.github.com
|
71
105
|
executables: []
|
@@ -93,8 +127,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
93
127
|
- !ruby/object:Gem::Version
|
94
128
|
version: '0'
|
95
129
|
requirements: []
|
96
|
-
|
97
|
-
rubygems_version: 2.5.1
|
130
|
+
rubygems_version: 3.1.4
|
98
131
|
signing_key:
|
99
132
|
specification_version: 4
|
100
133
|
summary: Asciidoctor STEM processor based on Mathematical
|