isodoc 1.5.5 → 1.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +2 -2
- data/isodoc.gemspec +10 -10
- data/lib/isodoc/base_style/all.css +7 -0
- data/lib/isodoc/base_style/metanorma_word.css +7 -0
- data/lib/isodoc/base_style/metanorma_word.scss +8 -0
- data/lib/isodoc/base_style/reset.css +7 -0
- data/lib/isodoc/base_style/reset.scss +9 -0
- data/lib/isodoc/base_style/scripts.html +187 -0
- data/lib/isodoc/class_utils.rb +6 -5
- data/lib/isodoc/convert.rb +24 -15
- data/lib/isodoc/css.rb +14 -9
- data/lib/isodoc/function/inline.rb +31 -10
- data/lib/isodoc/function/to_word_html.rb +19 -9
- data/lib/isodoc/function/utils.rb +1 -0
- data/lib/isodoc/pdf_convert.rb +1 -3
- data/lib/isodoc/presentation_function/inline.rb +31 -19
- data/lib/isodoc/presentation_xml_convert.rb +1 -1
- data/lib/isodoc/version.rb +1 -1
- data/lib/isodoc/xslfo_convert.rb +36 -27
- data/spec/isodoc/footnotes_spec.rb +1 -16
- data/spec/isodoc/inline_spec.rb +34 -0
- data/spec/isodoc/postproc_spec.rb +36 -12
- data/spec/isodoc/presentation_xml_spec.rb +345 -342
- data/spec/isodoc/section_spec.rb +910 -902
- data/spec/isodoc/table_spec.rb +566 -556
- data/spec/isodoc/terms_spec.rb +252 -256
- data/spec/isodoc/xref_spec.rb +2991 -2994
- data/spec/isodoc/xslfo_convert_spec.rb +39 -0
- data/spec/spec_helper.rb +30 -29
- metadata +67 -65
data/lib/isodoc/css.rb
CHANGED
@@ -14,17 +14,22 @@ module IsoDoc
|
|
14
14
|
compiled_path
|
15
15
|
end
|
16
16
|
|
17
|
+
def localpath(path)
|
18
|
+
return path if %r{^[A-Z]:|^/|^file:/}.match(path)
|
19
|
+
return path unless (@sourcedir || @localdir) && path
|
20
|
+
File.expand_path(File.join((@sourcedir || @localdir), path))
|
21
|
+
end
|
22
|
+
|
17
23
|
# run this after @meta is populated
|
18
24
|
def populate_css
|
19
|
-
@htmlstylesheet = generate_css(@htmlstylesheet_name, true)
|
20
|
-
@wordstylesheet = generate_css(@wordstylesheet_name, false)
|
21
|
-
@standardstylesheet =
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
end
|
25
|
+
@htmlstylesheet = generate_css(localpath(@htmlstylesheet_name), true)
|
26
|
+
@wordstylesheet = generate_css(localpath(@wordstylesheet_name), false)
|
27
|
+
@standardstylesheet =
|
28
|
+
generate_css(localpath(@standardstylesheet_name), false)
|
29
|
+
@htmlstylesheet_override_name and @htmlstylesheet_override =
|
30
|
+
File.open(localpath(@htmlstylesheet_override_name))
|
31
|
+
@wordstylesheet_override_name and @wordstylesheet_override =
|
32
|
+
File.open(localpath(@wordstylesheet_override_name))
|
28
33
|
end
|
29
34
|
|
30
35
|
def default_fonts(_options)
|
@@ -23,21 +23,26 @@ module IsoDoc::Function
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def xref_parse(node, out)
|
26
|
-
target = /#/.match(node["target"])
|
27
|
-
|
28
|
-
|
26
|
+
target = if /#/.match?(node["target"])
|
27
|
+
node["target"].sub(/#/, ".html#")
|
28
|
+
else
|
29
|
+
"##{node['target']}"
|
30
|
+
end
|
31
|
+
out.a(**{ "href": target }) { |l| no_locality_parse(node, l) }
|
29
32
|
end
|
30
33
|
|
31
34
|
def suffix_url(url)
|
32
|
-
return url if %r{^
|
35
|
+
return url if %r{^https?://}.match?(url)
|
36
|
+
|
33
37
|
url.sub(/#{File.extname(url)}$/, ".html")
|
34
38
|
end
|
35
39
|
|
36
40
|
def eref_target(node)
|
37
|
-
href = "
|
41
|
+
href = "##{node['bibitemid']}"
|
38
42
|
url = node.at(ns("//bibitem[@id = '#{node['bibitemid']}']/"\
|
39
43
|
"uri[@type = 'citation']"))
|
40
44
|
return href unless url
|
45
|
+
|
41
46
|
href = suffix_url(url.text)
|
42
47
|
anchor = node&.at(ns(".//locality[@type = 'anchor']"))&.text&.strip
|
43
48
|
anchor and href += "##{anchor}"
|
@@ -68,10 +73,11 @@ module IsoDoc::Function
|
|
68
73
|
end
|
69
74
|
|
70
75
|
def stem_parse(node, out)
|
71
|
-
ooml =
|
76
|
+
ooml = case node["type"]
|
77
|
+
when "AsciiMath"
|
72
78
|
"#{@openmathdelim}#{HTMLEntities.new.encode(node.text)}"\
|
73
79
|
"#{@closemathdelim}"
|
74
|
-
|
80
|
+
when "MathML" then node.first_element_child.to_s
|
75
81
|
else
|
76
82
|
HTMLEntities.new.encode(node.text)
|
77
83
|
end
|
@@ -93,7 +99,7 @@ module IsoDoc::Function
|
|
93
99
|
height: node["height"] || "auto",
|
94
100
|
width: node["width"] || "auto",
|
95
101
|
title: node["title"],
|
96
|
-
alt: node["alt"]
|
102
|
+
alt: node["alt"] }
|
97
103
|
out.img **attr_code(attrs)
|
98
104
|
image_title_parse(out, caption)
|
99
105
|
end
|
@@ -106,12 +112,27 @@ module IsoDoc::Function
|
|
106
112
|
|
107
113
|
def text_parse(node, out)
|
108
114
|
return if node.nil? || node.text.nil?
|
115
|
+
|
109
116
|
text = node.to_s
|
110
|
-
|
111
|
-
gsub(
|
117
|
+
if in_sourcecode
|
118
|
+
text = text.gsub("\n", "<br/>").gsub("<br/> ", "<br/> ")
|
119
|
+
.gsub(/ (?= )/, " ")
|
120
|
+
end
|
112
121
|
out << text
|
113
122
|
end
|
114
123
|
|
124
|
+
def add_parse(node, out)
|
125
|
+
out.span **{class: "addition"} do |e|
|
126
|
+
node.children.each { |n| parse(n, e) }
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def del_parse(node, out)
|
131
|
+
out.span **{class: "deletion"} do |e|
|
132
|
+
node.children.each { |n| parse(n, e) }
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
115
136
|
def error_parse(node, out)
|
116
137
|
text = node.to_xml.gsub(/</, "<").gsub(/>/, ">")
|
117
138
|
out.para do |p|
|
@@ -19,14 +19,21 @@ module IsoDoc::Function
|
|
19
19
|
def init_file(filename, debug)
|
20
20
|
filepath = Pathname.new(filename)
|
21
21
|
filename = filepath.sub_ext('').sub(/\.presentation$/, "").to_s
|
22
|
+
dir = init_dir(filename, debug)
|
23
|
+
@filename = filename
|
24
|
+
@localdir = filepath.parent.to_s + '/'
|
25
|
+
@sourcedir = @localdir
|
26
|
+
@sourcefilename and @sourcedir = Pathname.new(@sourcefilename).parent.to_s + '/'
|
27
|
+
[filename, dir]
|
28
|
+
end
|
29
|
+
|
30
|
+
def init_dir(filename, debug)
|
22
31
|
dir = "#{filename}_files"
|
23
32
|
unless debug
|
24
33
|
Dir.mkdir(dir, 0777) unless File.exists?(dir)
|
25
34
|
FileUtils.rm_rf "#{dir}/*"
|
26
35
|
end
|
27
|
-
|
28
|
-
@localdir = filepath.parent.to_s + '/'
|
29
|
-
[filename, dir]
|
36
|
+
dir
|
30
37
|
end
|
31
38
|
|
32
39
|
# tmp image dir is same directory as @filename
|
@@ -44,15 +51,16 @@ module IsoDoc::Function
|
|
44
51
|
if @standardstylesheet
|
45
52
|
head.style do |style|
|
46
53
|
@standardstylesheet.open
|
47
|
-
stylesheet = @standardstylesheet.read.
|
48
|
-
|
54
|
+
stylesheet = @standardstylesheet.read.gsub(
|
55
|
+
"FILENAME", File.basename(filename).sub(/\.presentation$/, "")
|
56
|
+
)
|
49
57
|
style.comment "\n#{stylesheet}\n"
|
50
58
|
end
|
51
59
|
end
|
52
60
|
end
|
53
61
|
|
54
62
|
def body_attr
|
55
|
-
{ lang:
|
63
|
+
{ lang: @lang.to_s }
|
56
64
|
end
|
57
65
|
|
58
66
|
def make_body(xml, docxml)
|
@@ -125,7 +133,7 @@ module IsoDoc::Function
|
|
125
133
|
i = scope isoxml, out, 0
|
126
134
|
i = norm_ref isoxml, out, i
|
127
135
|
i = terms_defs isoxml, out, i
|
128
|
-
|
136
|
+
symbols_abbrevs isoxml, out, i
|
129
137
|
clause isoxml, out
|
130
138
|
annex isoxml, out
|
131
139
|
bibliography isoxml, out
|
@@ -133,7 +141,7 @@ module IsoDoc::Function
|
|
133
141
|
|
134
142
|
def boilerplate(node, out)
|
135
143
|
boilerplate = node.at(ns("//boilerplate")) or return
|
136
|
-
out.div **{class: "authority"} do |s|
|
144
|
+
out.div **{ class: "authority" } do |s|
|
137
145
|
boilerplate.children.each do |n|
|
138
146
|
if n.name == "title"
|
139
147
|
s.h1 do |h|
|
@@ -225,7 +233,9 @@ module IsoDoc::Function
|
|
225
233
|
when "passthrough" then passthrough_parse(node, out)
|
226
234
|
when "amend" then amend_parse(node, out)
|
227
235
|
when "tab" then clausedelimspace(out) # in Presentation XML only
|
228
|
-
when "svg" then svg_parse(node, out) #
|
236
|
+
when "svg" then svg_parse(node, out) # in Presentation XML only
|
237
|
+
when "add" then add_parse(node, out)
|
238
|
+
when "del" then del_parse(node, out)
|
229
239
|
else
|
230
240
|
error_parse(node, out)
|
231
241
|
end
|
@@ -123,6 +123,7 @@ module IsoDoc::Function
|
|
123
123
|
h1 = to_xhtml_fragment(h.dup)
|
124
124
|
h1.traverse do |x|
|
125
125
|
x.replace(' ') if x.name == 'span' && /mso-tab-count/.match(x['style'])
|
126
|
+
x.remove if x.name == 'img'
|
126
127
|
x.remove if x.name == 'span' && x['class'] == 'MsoCommentReference'
|
127
128
|
x.remove if x.name == 'a' && x['class'] == 'FootnoteRef'
|
128
129
|
x.remove if x.name == 'span' && /mso-bookmark/.match(x['style'])
|
data/lib/isodoc/pdf_convert.rb
CHANGED
@@ -42,9 +42,7 @@ module IsoDoc
|
|
42
42
|
end
|
43
43
|
|
44
44
|
def xref_parse(node, out)
|
45
|
-
|
46
|
-
"##{node["target"]}"
|
47
|
-
out.a(**{ "href": target }) { |l| l << get_linkend(node) }
|
45
|
+
out.a(**{ "href": target_pdf(node) }) { |l| l << get_linkend(node) }
|
48
46
|
end
|
49
47
|
end
|
50
48
|
end
|
@@ -50,67 +50,79 @@ module IsoDoc
|
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
53
|
-
def get_linkend(
|
54
|
-
contents = non_locality_elems(
|
53
|
+
def get_linkend(node)
|
54
|
+
contents = non_locality_elems(node).select { |c| !c.text? || /\S/.match(c) }
|
55
55
|
return unless contents.empty?
|
56
|
-
link = anchor_linkend(
|
57
|
-
link += eref_localities(
|
58
|
-
non_locality_elems(
|
59
|
-
|
56
|
+
link = anchor_linkend(node, docid_l10n(node["target"] || node["citeas"]))
|
57
|
+
link += eref_localities(node.xpath(ns("./locality | ./localityStack")), link, node)
|
58
|
+
non_locality_elems(node).each { |n| n.remove }
|
59
|
+
node.add_child(link)
|
60
60
|
end
|
61
61
|
# so not <origin bibitemid="ISO7301" citeas="ISO 7301">
|
62
62
|
# <locality type="section"><reference>3.1</reference></locality></origin>
|
63
63
|
|
64
|
-
def eref_localities(refs, target)
|
64
|
+
def eref_localities(refs, target, n)
|
65
65
|
ret = ""
|
66
66
|
refs.each_with_index do |r, i|
|
67
67
|
delim = ","
|
68
68
|
delim = ";" if r.name == "localityStack" && i>0
|
69
|
-
ret = eref_locality_stack(r, i, target, delim, ret)
|
69
|
+
ret = eref_locality_stack(r, i, target, delim, ret, n)
|
70
70
|
end
|
71
71
|
ret
|
72
72
|
end
|
73
73
|
|
74
|
-
def eref_locality_stack(r, i, target, delim, ret)
|
74
|
+
def eref_locality_stack(r, i, target, delim, ret, n)
|
75
75
|
if r.name == "localityStack"
|
76
76
|
r.elements.each_with_index do |rr, j|
|
77
|
-
ret += eref_localities0(rr, j, target, delim)
|
77
|
+
ret += eref_localities0(rr, j, target, delim, n)
|
78
78
|
delim = ","
|
79
79
|
end
|
80
80
|
else
|
81
|
-
ret += eref_localities0(r, i, target, delim)
|
81
|
+
ret += eref_localities0(r, i, target, delim, n)
|
82
82
|
end
|
83
83
|
ret
|
84
84
|
end
|
85
85
|
|
86
|
-
def eref_localities0(r, i, target, delim)
|
86
|
+
def eref_localities0(r, i, target, delim, n)
|
87
87
|
if r["type"] == "whole" then l10n("#{delim} #{@i18n.wholeoftext}")
|
88
88
|
else
|
89
|
-
eref_localities1(target, r["type"], r.at(ns("./referenceFrom")),
|
89
|
+
eref_localities1(target, r["type"], r.at(ns("./referenceFrom")),
|
90
|
+
r.at(ns("./referenceTo")), delim, n, @lang)
|
90
91
|
end
|
91
92
|
end
|
92
93
|
|
93
94
|
# TODO: move to localization file
|
94
|
-
def eref_localities1_zh(target, type, from, to, delim)
|
95
|
+
def eref_localities1_zh(target, type, from, to, n, delim)
|
95
96
|
ret = "#{delim} 第#{from.text}" if from
|
96
97
|
ret += "–#{to.text}" if to
|
97
98
|
loc = (@i18n.locality[type] || type.sub(/^locality:/, "").capitalize )
|
98
|
-
ret += " #{loc}"
|
99
|
+
ret += " #{loc}" unless n["droploc"] == "true"
|
99
100
|
ret
|
100
101
|
end
|
101
102
|
|
102
103
|
# TODO: move to localization file
|
103
|
-
def eref_localities1(target, type, from, to, delim, lang = "en")
|
104
|
+
def eref_localities1(target, type, from, to, delim, n, lang = "en")
|
104
105
|
return "" if type == "anchor"
|
105
|
-
lang == "zh" and return l10n(eref_localities1_zh(target, type, from, to, delim))
|
106
|
+
lang == "zh" and return l10n(eref_localities1_zh(target, type, from, to, n, delim))
|
106
107
|
ret = delim
|
107
|
-
|
108
|
-
ret += " #{loc}"
|
108
|
+
ret += eref_locality_populate(type, n)
|
109
109
|
ret += " #{from.text}" if from
|
110
110
|
ret += "–#{to.text}" if to
|
111
111
|
l10n(ret)
|
112
112
|
end
|
113
113
|
|
114
|
+
def eref_locality_populate(type, n)
|
115
|
+
return "" if n["droploc"] == "true"
|
116
|
+
loc = @i18n.locality[type] || type.sub(/^locality:/, "")
|
117
|
+
loc = case n["case"]
|
118
|
+
when "capital" then loc.capitalize
|
119
|
+
when "lowercase" then loc.downcase
|
120
|
+
else
|
121
|
+
loc.capitalize
|
122
|
+
end
|
123
|
+
" #{loc}"
|
124
|
+
end
|
125
|
+
|
114
126
|
def xref(docxml)
|
115
127
|
docxml.xpath(ns("//xref")).each { |f| xref1(f) }
|
116
128
|
end
|
data/lib/isodoc/version.rb
CHANGED
data/lib/isodoc/xslfo_convert.rb
CHANGED
@@ -2,52 +2,61 @@ require "metanorma"
|
|
2
2
|
|
3
3
|
module IsoDoc
|
4
4
|
class XslfoPdfConvert < ::IsoDoc::Convert
|
5
|
+
MN2PDF_OPTIONS = :mn2pdf
|
6
|
+
MN2PDF_FONT_MANIFEST = :font_manifest_file
|
5
7
|
|
6
8
|
def initialize(options)
|
9
|
+
@format = :pdf
|
10
|
+
@suffix = "pdf"
|
7
11
|
super
|
8
|
-
@maxwidth = 500
|
9
|
-
@maxheight = 800
|
10
12
|
end
|
11
13
|
|
12
14
|
def tmpimagedir_suffix
|
13
15
|
"_pdfimages"
|
14
16
|
end
|
15
17
|
|
16
|
-
def
|
17
|
-
@format = :pdf
|
18
|
-
@suffix = "pdf"
|
19
|
-
super
|
20
|
-
end
|
21
|
-
|
22
|
-
def pdf_stylesheet(docxml)
|
18
|
+
def pdf_stylesheet(_docxml)
|
23
19
|
nil
|
24
20
|
end
|
25
21
|
|
26
|
-
def pdf_options(
|
27
|
-
font_manifest_file = @options.dig(
|
28
|
-
|
29
|
-
|
22
|
+
def pdf_options(_docxml)
|
23
|
+
if font_manifest_file = @options.dig(MN2PDF_OPTIONS,
|
24
|
+
MN2PDF_FONT_MANIFEST)
|
25
|
+
"--font-manifest #{font_manifest_file}"
|
26
|
+
else
|
27
|
+
""
|
28
|
+
end
|
30
29
|
end
|
31
30
|
|
32
|
-
def convert(input_filename, file = nil, debug = false,
|
31
|
+
def convert(input_filename, file = nil, debug = false,
|
32
|
+
output_filename = nil)
|
33
33
|
file = File.read(input_filename, encoding: "utf-8") if file.nil?
|
34
|
-
docxml, filename
|
35
|
-
|
36
|
-
|
37
|
-
|
34
|
+
input_filename, docxml, filename = input_xml_path(input_filename,
|
35
|
+
file, debug)
|
36
|
+
::Metanorma::Output::XslfoPdf.new.convert(
|
37
|
+
input_filename,
|
38
|
+
output_filename || "#{filename}.#{@suffix}",
|
39
|
+
File.join(@libdir, pdf_stylesheet(docxml)),
|
40
|
+
pdf_options(docxml)
|
41
|
+
)
|
42
|
+
end
|
43
|
+
|
44
|
+
def xref_parse(node, out)
|
45
|
+
out.a(**{ "href": target_pdf(node) }) { |l| l << get_linkend(node) }
|
46
|
+
end
|
47
|
+
|
48
|
+
def input_xml_path(input_filename, xml_file, debug)
|
49
|
+
docxml, filename, dir = convert_init(xml_file, input_filename, debug)
|
50
|
+
unless /\.xml$/.match?(input_filename)
|
51
|
+
input_filename = Tempfile.open([filename, ".xml"],
|
52
|
+
encoding: "utf-8") do |f|
|
53
|
+
f.write xml_file
|
38
54
|
f.path
|
39
55
|
end
|
56
|
+
end
|
40
57
|
FileUtils.rm_rf dir
|
41
|
-
::Metanorma::Output::XslfoPdf.new.convert(input_filename,
|
42
|
-
output_filename || "#{filename}.#{@suffix}",
|
43
|
-
File.join(@libdir, pdf_stylesheet(docxml)),
|
44
|
-
pdf_options(docxml))
|
45
|
-
end
|
46
58
|
|
47
|
-
|
48
|
-
target = /#/.match(node["target"]) ? node["target"].sub(/#/, ".pdf#") :
|
49
|
-
"##{node["target"]}"
|
50
|
-
out.a(**{ "href": target }) { |l| l << get_linkend(node) }
|
59
|
+
[input_filename, docxml, filename]
|
51
60
|
end
|
52
61
|
end
|
53
62
|
end
|
@@ -155,17 +155,8 @@ RSpec.describe IsoDoc do
|
|
155
155
|
</preface>
|
156
156
|
</iso-standard>
|
157
157
|
INPUT
|
158
|
-
html = File.read("test.html").sub(/^.*<
|
158
|
+
html = File.read("test.html").sub(/^.*<main/m, "<main").sub(%r{</main>.*$}m, "</main>")
|
159
159
|
expect(xmlpp(html)).to be_equivalent_to xmlpp(<<~"OUTPUT")
|
160
|
-
<body lang="en" xml:lang="en">
|
161
|
-
<div class="title-section">
|
162
|
-
<p> </p>
|
163
|
-
</div>
|
164
|
-
<br />
|
165
|
-
<div class="prefatory-section">
|
166
|
-
<p> </p>
|
167
|
-
</div>
|
168
|
-
<br />
|
169
160
|
<main class="main-section"><button onclick="topFunction()" id="myBtn" title="Go to top">Top</button>
|
170
161
|
<br />
|
171
162
|
<div>
|
@@ -180,12 +171,6 @@ RSpec.describe IsoDoc do
|
|
180
171
|
</div>
|
181
172
|
<p class="zzSTDTitle1"></p>
|
182
173
|
</main>
|
183
|
-
<script type='text/x-mathjax-config'>
|
184
|
-
MathJax.Hub.Config({ "HTML-CSS": { preferredFont: "STIX" }, asciimath2jax:
|
185
|
-
{ delimiters: [['(#(', ')#)']] } });
|
186
|
-
</script>
|
187
|
-
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/latest.js?config=MML_HTMLorMML-full" async="async"></script>
|
188
|
-
<script src="https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js"></script></body>
|
189
174
|
OUTPUT
|
190
175
|
end
|
191
176
|
|