asciidoctor-pdf-mathjax 0.3.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 +4 -4
- data/bin/render.js +9 -4
- data/lib/asciidoctor-pdf-mathjax.rb +50 -16
- metadata +3 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4129aed907ee9beb5d7a2c523a0ed1ffb783502aed7184f687305a051ec60afe
|
|
4
|
+
data.tar.gz: 5dcf3ee6fb448dd253b3fbafbc0ecdf879035744d490e192779f3cb0c0180015
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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
|
-
|
|
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
|
|
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
|
|
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([
|
|
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
|
|
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
|
|
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([
|
|
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
|
-
|
|
124
|
-
|
|
125
|
-
|
|
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
|
-
|
|
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,14 +164,17 @@ class AsciidoctorPDFExtensions < (Asciidoctor::Converter.for 'pdf')
|
|
|
154
164
|
font_size = nil
|
|
155
165
|
font_color = nil
|
|
156
166
|
converter = node_context.converter
|
|
157
|
-
converter
|
|
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
|
|
|
@@ -170,8 +183,29 @@ class AsciidoctorPDFExtensions < (Asciidoctor::Converter.for 'pdf')
|
|
|
170
183
|
end
|
|
171
184
|
|
|
172
185
|
font = TTFunk::File.open(font_file)
|
|
186
|
+
unless font
|
|
187
|
+
raise "Failed opening font file: #{font_file}"
|
|
188
|
+
end
|
|
189
|
+
|
|
173
190
|
descender_height = font.horizontal_header.descent.abs
|
|
174
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}"
|
|
175
209
|
|
|
176
210
|
units_per_em = font.header.units_per_em.to_f
|
|
177
211
|
total_height = (descender_height.to_f + ascender_height.to_f)
|
|
@@ -234,7 +268,7 @@ class AsciidoctorPDFExtensions < (Asciidoctor::Converter.for 'pdf')
|
|
|
234
268
|
[svg_output, svg_width]
|
|
235
269
|
rescue => e
|
|
236
270
|
logger.warn "Failed to adjust SVG baseline: #{e.full_message}"
|
|
237
|
-
nil # Fallback to original if adjustment fails
|
|
271
|
+
nil # Fallback to the original if adjustment fails
|
|
238
272
|
end
|
|
239
273
|
|
|
240
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.
|
|
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:
|
|
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.
|
|
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: []
|