asciidoctor-mathematical 0.0.5 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/asciidoctor-mathematical.rb +2 -3
- data/lib/asciidoctor-mathematical/extension.rb +95 -112
- metadata +6 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c60e640244d19ad2679b5117d86aa6b71ea3068d
|
4
|
+
data.tar.gz: a872640167565771f597fdd7868db7103a626a82
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b13a97f6910f9936f965eddc9eec2764bff84d15f81f27dfa1dfa2c8abe7c67c15a47072bdc620d10bd10a14ab82e761df2acc78cbba2695cb922401fa45b081
|
7
|
+
data.tar.gz: 8a1e50165d18cb99a763b8ca769fe970c5b1fdd683350cedc2d2b7c08abc881983d436be412bc07829868d743fdd5995ebf1da660f33e7adba1ae6db48447254
|
@@ -1,6 +1,5 @@
|
|
1
|
-
|
1
|
+
require_relative 'asciidoctor-mathematical/extension'
|
2
2
|
|
3
|
-
Extensions.register do
|
4
|
-
preprocessor MathematicalPreprocessor
|
3
|
+
Asciidoctor::Extensions.register do
|
5
4
|
treeprocessor MathematicalTreeprocessor
|
6
5
|
end
|
@@ -1,43 +1,35 @@
|
|
1
|
-
require '
|
1
|
+
require 'pathname'
|
2
2
|
require 'asciidoctor/extensions'
|
3
|
-
require 'mathematical'
|
4
3
|
|
5
4
|
autoload :Digest, 'digest'
|
5
|
+
autoload :Mathematical, 'mathematical'
|
6
6
|
|
7
|
-
|
7
|
+
class MathematicalTreeprocessor < Asciidoctor::Extensions::Treeprocessor
|
8
|
+
LineFeed = %(\n)
|
9
|
+
StemInlineMacroRx = /\\?(?:stem|latexmath):([a-z,]*)\[(.*?[^\\])\]/m
|
10
|
+
LatexmathInlineMacroRx = /\\?latexmath:([a-z,]*)\[(.*?[^\\])\]/m
|
8
11
|
|
9
|
-
class MathematicalTreeprocessor < Extensions::Treeprocessor
|
10
12
|
def process document
|
11
|
-
|
13
|
+
to_html = document.basebackend? 'html'
|
14
|
+
format = ((document.attr 'mathematical-format') || 'png').to_sym
|
15
|
+
if format != :png and format != :svg
|
16
|
+
warn %(Unknown format '#{format}', retreat to 'png')
|
12
17
|
format = :png
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
if format == :png
|
24
|
-
scale = 72.0/300.0
|
25
|
-
end
|
26
|
-
ppi = 72.0
|
27
|
-
if format == :png
|
28
|
-
ppi = 300.0
|
29
|
-
end
|
30
|
-
# The no-args constructor defaults to SVG and standard delimiters ($..$ for inline, $$..$$ for block)
|
31
|
-
mathematical = ::Mathematical.new({ :format => format, :ppi => ppi })
|
32
|
-
image_output_dir = resolve_image_output_dir document
|
33
|
-
image_target_dir = document.attr 'imagesoutdir', (document.attr 'imagesdir')
|
34
|
-
image_target_dir = '.' if image_target_dir.nil_or_empty?
|
35
|
-
::FileUtils.mkdir_p image_output_dir unless ::File.directory? image_output_dir
|
18
|
+
end
|
19
|
+
image_ext = %(.#{format})
|
20
|
+
ppi = ((document.attr 'mathematical-ppi') || '300.0').to_f
|
21
|
+
ppi = format == :png ? ppi : 72.0
|
22
|
+
# The no-args constructor defaults to SVG and standard delimiters ($..$ for inline, $$..$$ for block)
|
23
|
+
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?
|
27
|
+
::Asciidoctor::Helpers.mkdir_p image_output_dir unless ::File.directory? image_output_dir
|
36
28
|
|
37
29
|
stem_blocks.each do |stem|
|
38
|
-
equation_data = %($$#{stem.content}$$)
|
39
30
|
equation_type = stem.style.to_sym
|
40
31
|
next unless equation_type == :latexmath
|
32
|
+
equation_data = %($$#{stem.content}$$)
|
41
33
|
|
42
34
|
# FIXME auto-generate id if one is not provided
|
43
35
|
unless (stem_id = stem.id)
|
@@ -46,7 +38,7 @@ class MathematicalTreeprocessor < Extensions::Treeprocessor
|
|
46
38
|
|
47
39
|
alt_text = stem.attr 'alt', equation_data
|
48
40
|
|
49
|
-
image_target = %(#{stem_id}#{
|
41
|
+
image_target = %(#{stem_id}#{image_ext})
|
50
42
|
image_file = ::File.join image_output_dir, image_target
|
51
43
|
image_target = ::File.join image_target_dir, image_target unless image_target_dir == '.'
|
52
44
|
|
@@ -56,8 +48,8 @@ class MathematicalTreeprocessor < Extensions::Treeprocessor
|
|
56
48
|
|
57
49
|
attrs = { 'target' => image_target, 'alt' => alt_text, 'align' => 'center' }
|
58
50
|
if format == :png
|
59
|
-
attrs['width'] =
|
60
|
-
attrs['height'] =
|
51
|
+
attrs['width'] = %(#{result[:width]})
|
52
|
+
attrs['height'] = %(#{result[:height]})
|
61
53
|
end
|
62
54
|
parent = stem.parent
|
63
55
|
stem_image = create_image_block parent, attrs
|
@@ -68,94 +60,85 @@ class MathematicalTreeprocessor < Extensions::Treeprocessor
|
|
68
60
|
parent.blocks[parent.blocks.index stem] = stem_image
|
69
61
|
end
|
70
62
|
end
|
71
|
-
nil
|
72
|
-
end
|
73
|
-
|
74
|
-
def resolve_image_output_dir doc
|
75
|
-
if (images_dir = doc.attr 'imagesoutdir')
|
76
|
-
base_dir = nil
|
77
|
-
else
|
78
|
-
base_dir = (doc.attr 'outdir') || ((doc.respond_to? :options) && doc.options[:to_dir])
|
79
|
-
images_dir = doc.attr 'imagesdir'
|
80
|
-
end
|
81
|
-
|
82
|
-
doc.normalize_system_path images_dir, base_dir
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
class MathematicalPreprocessor < Extensions::Preprocessor
|
87
|
-
LATEXMATH_PTN = /latexmath:\[([^\]]+)\]/
|
88
63
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
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
|
79
|
+
|
80
|
+
if (eq_data = m[2].rstrip).empty?
|
81
|
+
next
|
82
|
+
else
|
83
|
+
source_modified = true
|
84
|
+
end
|
85
|
+
|
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?
|
89
|
+
|
90
|
+
eq_id = %(stem-#{::Digest::MD5.hexdigest eq_data})
|
91
|
+
eq_input = %($#{eq_data}$)
|
92
|
+
|
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 == '.'
|
96
|
+
|
97
|
+
eq_result = mathematical.parse eq_input
|
98
|
+
|
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:'))
|
102
|
+
|
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
|
109
|
+
end
|
113
110
|
end
|
114
111
|
end
|
115
|
-
image_postfix = ".#{format}"
|
116
|
-
scale = 1.0
|
117
|
-
if format == :png
|
118
|
-
scale = 72.0/300.0
|
119
|
-
end
|
120
|
-
ppi = 72.0
|
121
|
-
if format == :png
|
122
|
-
ppi = 300.0
|
123
|
-
end
|
124
112
|
|
125
|
-
|
126
|
-
|
127
|
-
image_output_dir = './images'
|
128
|
-
image_target_dir = './images'
|
129
|
-
::FileUtils.mkdir_p image_output_dir unless ::File.directory? image_output_dir
|
130
|
-
|
131
|
-
mathematical = ::Mathematical.new({ :format => format, :ppi => ppi })
|
132
|
-
|
133
|
-
lines = reader.readlines
|
134
|
-
lines.each do |line|
|
135
|
-
md = LATEXMATH_PTN.match line
|
136
|
-
while md
|
137
|
-
stem_content = md[1]
|
138
|
-
# NOTE: It seems that we need to escape '<>&' to make mathematical
|
139
|
-
# work. This is weired but verified. So we escape them here.
|
140
|
-
stem_content = sub_specialchars stem_content
|
141
|
-
equation_data = %($#{stem_content}$)
|
142
|
-
stem_id = %(stem-#{::Digest::MD5.hexdigest stem_content})
|
143
|
-
|
144
|
-
image_target = %(#{stem_id}#{image_postfix})
|
145
|
-
image_file = ::File.join image_output_dir, image_target
|
146
|
-
image_target = ::File.join image_target_dir, image_target unless image_target_dir == '.'
|
113
|
+
nil
|
114
|
+
end
|
147
115
|
|
148
|
-
|
149
|
-
|
150
|
-
::IO.write image_file, result[:data]
|
116
|
+
def image_output_and_target_dir(parent)
|
117
|
+
document = parent.document
|
151
118
|
|
152
|
-
|
153
|
-
|
154
|
-
|
119
|
+
output_dir = parent.attr('imagesoutdir')
|
120
|
+
if output_dir
|
121
|
+
base_dir = nil
|
122
|
+
if parent.attr('imagesdir').nil_or_empty?
|
123
|
+
target_dir = output_dir
|
124
|
+
else
|
125
|
+
# 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
|
155
132
|
end
|
133
|
+
else
|
134
|
+
base_dir = parent.attr('outdir') || (document.respond_to?(:options) && document.options[:to_dir])
|
135
|
+
output_dir = parent.attr('imagesdir')
|
136
|
+
# since we store images directly to imagesdir, target dir shall be NULL and asciidoctor converters will prefix imagesdir.
|
137
|
+
target_dir = "."
|
156
138
|
end
|
157
139
|
|
158
|
-
|
159
|
-
|
140
|
+
output_dir = parent.normalize_system_path(output_dir, base_dir)
|
141
|
+
return [output_dir, target_dir]
|
160
142
|
end
|
143
|
+
|
161
144
|
end
|
metadata
CHANGED
@@ -1,15 +1,16 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: asciidoctor-mathematical
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tobias Stumm
|
8
8
|
- Zhang Yang
|
9
|
+
- Dan Allen
|
9
10
|
autorequire:
|
10
11
|
bindir: bin
|
11
12
|
cert_chain: []
|
12
|
-
date:
|
13
|
+
date: 2016-08-21 00:00:00.000000000 Z
|
13
14
|
dependencies:
|
14
15
|
- !ruby/object:Gem::Dependency
|
15
16
|
name: ruby-enum
|
@@ -65,7 +66,7 @@ dependencies:
|
|
65
66
|
- - ">="
|
66
67
|
- !ruby/object:Gem::Version
|
67
68
|
version: 1.5.0
|
68
|
-
description:
|
69
|
+
description: An Asciidoctor extension to converts latexmath equations to SVG or PNGs
|
69
70
|
email: tstumm@users.noreply.github.com
|
70
71
|
executables: []
|
71
72
|
extensions: []
|
@@ -93,8 +94,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
93
94
|
version: '0'
|
94
95
|
requirements: []
|
95
96
|
rubyforge_project:
|
96
|
-
rubygems_version: 2.
|
97
|
+
rubygems_version: 2.5.1
|
97
98
|
signing_key:
|
98
99
|
specification_version: 4
|
99
|
-
summary:
|
100
|
+
summary: Asciidoctor STEM processor based on Mathematical
|
100
101
|
test_files: []
|