asciidoctor-pdf-mathjax 0.2.0 → 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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ca91538264bb33f7f1396cd2a572e8aab9b025d8ad0aad41f2218f382ea4580b
4
- data.tar.gz: fa2bd399de8b1f2b8b496d4502d97440b17fdeac71a70d1615aade5a778a635f
3
+ metadata.gz: 4129aed907ee9beb5d7a2c523a0ed1ffb783502aed7184f687305a051ec60afe
4
+ data.tar.gz: 5dcf3ee6fb448dd253b3fbafbc0ecdf879035744d490e192779f3cb0c0180015
5
5
  SHA512:
6
- metadata.gz: 3196f3580bf60ddce0ceae5b7abd339019571bce0a05d5b4e2f2ab2e25fa88fa6cd085cfe567aa5be7fc54227dcabe3ea5d9ba616c628ea754d88c4098c82b7e
7
- data.tar.gz: d22d84c24ce7317cf9ef93b297917e4d3c3a1ba259a2e0f762e41b62b1be80b9c71ab26759d6f89d4f1f40e05981443ce9344818f9f9a56bbb74389db1d0414e
6
+ metadata.gz: 208a3e49a730fabb7eddce46b1ab711abd1765716c5647bfce354865b89e5553289d9b00c610f952daefbd9b6152b3718ceb94f90055aa44517867e948c6c09e
7
+ data.tar.gz: e018fbd87bd4e13675aaef9803c6e41505abdb80c952d07185d1a26d78a4cc56d59016a343836c4d437783fea07a299653de9a3d999c22652a95cb0e8d62b707
data/bin/render.js CHANGED
@@ -1,9 +1,17 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  const mj = require('mathjax-node');
4
+
5
+ const latex = process.argv[2];
6
+ const format = process.argv[3];
7
+ const pixels_per_ex = parseInt(process.argv[4]);
8
+ const font = process.argv[5];
9
+
4
10
  mj.config({
5
11
  MathJax: {
6
- // MathJax configuration
12
+ SVG: {
13
+ font: font
14
+ }
7
15
  }
8
16
  });
9
17
  mj.start();
@@ -18,9 +26,6 @@ async function convertToSvg(latex, format, pixels_per_ex) {
18
26
  return data.svg;
19
27
  }
20
28
 
21
- const latex = process.argv[2];
22
- const format = process.argv[3];
23
- const pixels_per_ex = parseInt(process.argv[4]);
24
29
  convertToSvg(latex, format, pixels_per_ex).then(svg => {
25
30
  console.log(svg);
26
31
  }).catch(err => console.error(err));
@@ -7,6 +7,7 @@ require 'asciimath'
7
7
 
8
8
  POINTS_PER_EX = 6
9
9
  MATHJAX_DEFAULT_COLOR_STRING = "currentColor"
10
+ MATHJAX_DEFAULT_FONT_FAMILY = "TeX"
10
11
 
11
12
  FALLBACK_FONT_SIZE = 12
12
13
  FALLBACK_FONT_STYLE = 'normal'
@@ -21,17 +22,20 @@ class AsciidoctorPDFExtensions < (Asciidoctor::Converter.for 'pdf')
21
22
  attr_reader :tempfiles
22
23
  end
23
24
 
24
- def convert_stem node
25
+ def convert_stem(node)
25
26
  arrange_block node do |_|
26
27
  add_dest_for_block node if node.id
27
28
 
28
29
  latex_content = extract_latex_content(node.content, node.style.to_sym)
30
+ math_font = node.document.attributes['math-font'] || MATHJAX_DEFAULT_FONT_FAMILY
29
31
 
30
- svg_output, error = stem_to_svg(latex_content, false)
32
+ svg_output, error = stem_to_svg(latex_content, false, math_font)
31
33
 
34
+ # noinspection RubyResolve
35
+ code_padding = @theme.code_padding
32
36
  if svg_output.nil? || svg_output.empty?
33
37
  logger.warn "Failed to convert STEM to SVG: #{error} (Fallback to code block)"
34
- pad_box @theme.code_padding, node do
38
+ pad_box code_padding, node do
35
39
  theme_font :code do
36
40
  typeset_formatted_text [{ text: (guard_indentation latex_content), color: @font_color }],
37
41
  (calc_line_metrics @base_line_height),
@@ -48,12 +52,12 @@ class AsciidoctorPDFExtensions < (Asciidoctor::Converter.for 'pdf')
48
52
  scaling_factor = @font_size.to_f / svg_default_font_size
49
53
  svg_width = svg_width * scaling_factor
50
54
 
51
- svg_file = Tempfile.new(['stem', '.svg'])
55
+ svg_file = Tempfile.new(%w[stem .svg])
52
56
  begin
53
57
  svg_file.write(svg_output)
54
58
  svg_file.close
55
59
 
56
- pad_box @theme.code_padding, node do
60
+ pad_box code_padding, node do
57
61
  begin
58
62
  image_obj = image svg_file.path, position: :center, width: svg_width, height: nil
59
63
  logger.debug "Successfully embedded stem block (as latex) #{latex_content} as SVG image" if image_obj
@@ -71,25 +75,26 @@ class AsciidoctorPDFExtensions < (Asciidoctor::Converter.for 'pdf')
71
75
  theme_margin :block, :bottom, (next_enclosed_block node)
72
76
  end
73
77
 
74
- def convert_inline_quoted node
78
+ def convert_inline_quoted(node)
75
79
  latex_content = extract_latex_content(node.text, node.type)
76
80
  return super if latex_content.nil?
77
81
 
78
82
  theme = (load_theme node.document)
83
+ math_font = node.document.attributes['math-font'] || MATHJAX_DEFAULT_FONT_FAMILY
79
84
 
80
- svg_output, error = stem_to_svg(latex_content, true)
85
+ svg_output, error = stem_to_svg(latex_content, true, math_font)
81
86
  if svg_output.nil? || svg_output.empty?
82
87
  logger.warn "Error processing stem: #{error || 'No SVG output'}"
83
88
  return super
84
89
  end
85
90
  adjusted_svg, svg_width = adjust_svg_to_match_text(svg_output, node, theme)
86
- tmp_svg = Tempfile.new(['stem-', '.svg'])
91
+ tmp_svg = Tempfile.new(%w[stem- .svg])
87
92
  self.class.tempfiles << tmp_svg
88
93
  begin
89
94
  tmp_svg.write(adjusted_svg)
90
95
  tmp_svg.close
91
96
 
92
- logger.debug "Successfully embedded stem inline #{node.text} as SVG image"
97
+ logger.debug "Successfully embedded stem inline #{node.text} with font #{math_font} as SVG image"
93
98
  quoted_text = "<img src=\"#{tmp_svg.path}\" format=\"svg\" width=\"#{svg_width}\" alt=\"#{node.text}\">"
94
99
  node.id ? %(<a id="#{node.id}">#{DummyText}</a>#{quoted_text}) : quoted_text
95
100
  rescue => e
@@ -116,13 +121,18 @@ class AsciidoctorPDFExtensions < (Asciidoctor::Converter.for 'pdf')
116
121
  svg_output.gsub(MATHJAX_DEFAULT_COLOR_STRING, "##{font_color}")
117
122
  end
118
123
 
119
- def stem_to_svg(latex_content, is_inline)
124
+ def stem_to_svg(latex_content, is_inline, math_font)
120
125
  js_script = File.join(File.dirname(__FILE__), '../bin/render.js')
121
126
  svg_output, error = nil, nil
122
127
  format = is_inline ? 'inline-TeX' : 'TeX'
123
- Open3.popen3('node', js_script, latex_content, format, POINTS_PER_EX.to_s) do |_, stdout, stderr, wait_thr|
124
- svg_output = stdout.read
125
- error = stderr.read unless wait_thr.value.success?
128
+ begin
129
+ Open3.popen3('node', js_script, latex_content, format, POINTS_PER_EX.to_s, math_font) do |_, stdout, stderr, wait_thr|
130
+ svg_output = stdout.read
131
+ error = stderr.read unless wait_thr.value.success?
132
+ end
133
+ rescue Errno::ENOENT => e
134
+ error = "Node.js executable 'node' was not found. Please install Node.js and ensure 'node' is available on your PATH. Original error: #{e.message}"
135
+ svg_output = nil
126
136
  end
127
137
  [svg_output, error]
128
138
  end
@@ -142,7 +152,7 @@ class AsciidoctorPDFExtensions < (Asciidoctor::Converter.for 'pdf')
142
152
  font_style = theme["#{theme_key}_font_style"] || theme['heading_font_style'] || theme['base_font_style'] || FALLBACK_FONT_STYLE
143
153
  font_size = theme["#{theme_key}_font_size"] || theme['heading_font_size'] || theme['base_font_size'] || FALLBACK_FONT_SIZE
144
154
  font_color = theme["#{theme_key}_font_color"] || theme['heading_font_color'] || theme['base_font_color'] || FALLBACK_FONT_COLOR
145
- else
155
+ elsif node_context
146
156
  if node_context.parent.is_a?(Asciidoctor::Section) && node_context.parent.sectname == 'abstract'
147
157
  theme_key = :abstract
148
158
  else
@@ -154,20 +164,48 @@ class AsciidoctorPDFExtensions < (Asciidoctor::Converter.for 'pdf')
154
164
  font_size = nil
155
165
  font_color = nil
156
166
  converter = node_context.converter
157
- converter.theme_font theme_key do
167
+ converter&.theme_font theme_key do
158
168
  font_family = converter.font_family || FALLBACK_FONT_FAMILY
159
169
  font_style = converter.font_style || FALLBACK_FONT_STYLE
160
170
  font_size = converter.font_size || FALLBACK_FONT_SIZE
161
171
  font_color = converter.font_color || FALLBACK_FONT_COLOR
162
172
  end
173
+ else
174
+ raise "No font context found for node #{node}"
163
175
  end
164
176
 
177
+ # noinspection RubyResolve
165
178
  font_catalog = theme.font_catalog
166
179
  font_file = font_catalog[font_family][font_style.to_s]
167
180
 
181
+ if font_file && !font_file.include?(File::SEPARATOR)
182
+ font_file = File.join(node.document.attributes['pdf-fontsdir'], font_file)
183
+ end
184
+
168
185
  font = TTFunk::File.open(font_file)
186
+ unless font
187
+ raise "Failed opening font file: #{font_file}"
188
+ end
189
+
169
190
  descender_height = font.horizontal_header.descent.abs
170
191
  ascender_height = font.horizontal_header.ascent.abs
192
+ x_height = font.os2.x_height
193
+
194
+ unless x_height
195
+ logger.debug "'OS/2' table not found, falling back to estimating font x-height (ex) from glyph"
196
+
197
+ cmap_table = font.cmap.tables.find { |table| table.format == 4 && table.platform_id == 3 && table.encoding_id == 1 || table.encoding_id == 10 }
198
+ raise 'No suitable Unicode cmap table found' unless cmap_table
199
+
200
+ glyph_id = cmap_table.code_map['x'.ord]
201
+ raise "Glyph for 'x' not found" if glyph_id.nil? || glyph_id == 0
202
+
203
+ glyph = font.glyph_outlines.for(glyph_id)
204
+ raise 'Glyph data not available' unless glyph
205
+
206
+ x_height = glyph.y_max - glyph.y_min
207
+ end
208
+ logger.debug "Embedding Font: #{font_family} #{font_style}, x-height: #{x_height}, ascender: #{ascender_height}, descender: #{descender_height}"
171
209
 
172
210
  units_per_em = font.header.units_per_em.to_f
173
211
  total_height = (descender_height.to_f + ascender_height.to_f)
@@ -230,7 +268,7 @@ class AsciidoctorPDFExtensions < (Asciidoctor::Converter.for 'pdf')
230
268
  [svg_output, svg_width]
231
269
  rescue => e
232
270
  logger.warn "Failed to adjust SVG baseline: #{e.full_message}"
233
- nil # Fallback to original if adjustment fails
271
+ nil # Fallback to the original if adjustment fails
234
272
  end
235
273
 
236
274
  def find_font_context(node)
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: asciidoctor-pdf-mathjax
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Crown0815
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-03-14 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: asciidoctor
@@ -186,7 +186,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
186
186
  - !ruby/object:Gem::Version
187
187
  version: '0'
188
188
  requirements: []
189
- rubygems_version: 3.6.2
189
+ rubygems_version: 3.6.9
190
190
  specification_version: 4
191
191
  summary: AsciiDoctor extension to render STEM fields using MathJax SVG
192
192
  test_files: []