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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: c60e640244d19ad2679b5117d86aa6b71ea3068d
4
- data.tar.gz: a872640167565771f597fdd7868db7103a626a82
2
+ SHA256:
3
+ metadata.gz: e817ca8a177571fe61d368e26b09d8b35e1560b38ac8f971e14281f403b88344
4
+ data.tar.gz: 96d5d392cdf0ff18fd2d4bb3972247230f2c00b552b345ef42202f3327eede11
5
5
  SHA512:
6
- metadata.gz: b13a97f6910f9936f965eddc9eec2764bff84d15f81f27dfa1dfa2c8abe7c67c15a47072bdc620d10bd10a14ab82e761df2acc78cbba2695cb922401fa45b081
7
- data.tar.gz: 8a1e50165d18cb99a763b8ca769fe970c5b1fdd683350cedc2d2b7c08abc881983d436be412bc07829868d743fdd5995ebf1da660f33e7adba1ae6db48447254
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
- image_output_dir, image_target_dir = image_output_and_target_dir document
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
- equation_type = stem.style.to_sym
31
- next unless equation_type == :latexmath
32
- equation_data = %($$#{stem.content}$$)
35
+ handle_stem_block stem, mathematical, image_output_dir, image_target_dir, format, inline
36
+ end
37
+ end
33
38
 
34
- # FIXME auto-generate id if one is not provided
35
- unless (stem_id = stem.id)
36
- stem_id = %(stem-#{::Digest::MD5.hexdigest stem.content})
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
- alt_text = stem.attr 'alt', equation_data
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
- image_target = %(#{stem_id}#{image_ext})
42
- image_file = ::File.join image_output_dir, image_target
43
- image_target = ::File.join image_target_dir, image_target unless image_target_dir == '.'
69
+ nil
70
+ end
44
71
 
45
- # TODO check for error
46
- result = mathematical.parse equation_data
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
- attrs = { 'target' => image_target, 'alt' => alt_text, 'align' => 'center' }
50
- if format == :png
51
- attrs['width'] = %(#{result[:width]})
52
- attrs['height'] = %(#{result[:height]})
53
- end
54
- parent = stem.parent
55
- stem_image = create_image_block parent, attrs
56
- stem_image.id = stem.id if stem.id
57
- if (title = stem.attributes['title'])
58
- stem_image.title = title
59
- end
60
- parent.blocks[parent.blocks.index stem] = stem_image
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
- unless (prose_blocks = document.find_by {|b|
65
- (b.content_model == :simple && (b.subs.include? :macros)) || b.context == :list_item
66
- }).nil_or_empty?
67
- support_stem_prefix = document.attr? 'stem', 'latexmath'
68
- ::Asciidoctor::Helpers.mkdir_p image_output_dir unless ::File.directory? image_output_dir
69
- stem_rx = support_stem_prefix ? StemInlineMacroRx : LatexmathInlineMacroRx
70
-
71
- prose_blocks.each do |block|
72
- source_modified = false
73
- source = block.context == :list_item ? (block.instance_variable_get :@text) : (block.lines * LineFeed)
74
- # TODO skip passthroughs in the source (e.g., +stem:[x^2]+)
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
- if (eq_data = m[2].rstrip).empty?
81
- next
82
- else
83
- source_modified = true
84
- end
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
- eq_data.gsub! '\]', ']'
87
- subs = m[1].nil_or_empty? ? (to_html ? [:specialcharacters] : []) : (block.resolve_pass_subs m[1])
88
- eq_data = block.apply_subs eq_data, subs unless subs.empty?
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
- eq_id = %(stem-#{::Digest::MD5.hexdigest eq_data})
91
- eq_input = %($#{eq_data}$)
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
- img_target = %(#{eq_id}#{image_ext})
94
- img_file = ::File.join image_output_dir, img_target
95
- img_target = ::File.join image_target_dir, img_target unless image_target_dir == '.'
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
- eq_result = mathematical.parse eq_input
153
+ source_modified = false
98
154
 
99
- ::IO.write img_file, eq_result[:data]
100
- %(image:#{img_target}[width=#{eq_result[:width]},height=#{eq_result[:height]}])
101
- } if (source.include? ':') && ((support_stem_prefix && (source.include? 'stem:')) || (source.include? 'latexmath:'))
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 source_modified
104
- if block.context == :list_item
105
- block.instance_variable_set :@text, source
106
- else
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
- end
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
- nil
188
+ [text, source_modified]
114
189
  end
115
190
 
116
- def image_output_and_target_dir(parent)
117
- document = parent.document
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
- output_dir = parent.attr('imagesoutdir')
213
+ def image_output_and_target_dir(doc)
214
+ output_dir = doc.attr('imagesoutdir')
120
215
  if output_dir
121
- base_dir = nil
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
- doc_outdir = parent.attr('outdir') || (document.respond_to?(:options) && document.options[:to_dir])
127
- abs_imagesdir = parent.normalize_system_path(parent.attr('imagesdir'), doc_outdir)
128
- abs_outdir = parent.normalize_system_path(output_dir, base_dir)
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
- base_dir = parent.attr('outdir') || (document.respond_to?(:options) && document.options[:to_dir])
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 = parent.normalize_system_path(output_dir, base_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.1.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: 2016-08-21 00:00:00.000000000 Z
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: '1.5'
55
+ version: '2.0'
56
56
  - - ">="
57
57
  - !ruby/object:Gem::Version
58
- version: 1.5.0
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: '1.5'
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: 1.5.0
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
- rubyforge_project:
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