isodoc 1.5.5 → 1.6.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/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
|
|