isodoc 1.1.0 → 1.1.3.pre.alpha3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/macos.yml +6 -12
- data/.github/workflows/ubuntu.yml +18 -20
- data/.github/workflows/windows.yml +6 -12
- data/Rakefile +3 -1
- data/isodoc.gemspec +1 -1
- data/lib/isodoc/base_style/all.css +207 -0
- data/lib/isodoc/base_style/blocks.css +0 -0
- data/lib/isodoc/base_style/coverpage.css +0 -0
- data/lib/isodoc/base_style/defaults.css +0 -0
- data/lib/isodoc/base_style/metanorma_word.css +34 -0
- data/lib/isodoc/base_style/metanorma_word.scss +0 -1
- data/lib/isodoc/base_style/nav.css +0 -0
- data/lib/isodoc/base_style/reset.css +105 -0
- data/lib/isodoc/base_style/reset.scss +3 -3
- data/lib/isodoc/base_style/typography.css +0 -0
- data/lib/isodoc/convert.rb +106 -53
- data/lib/isodoc/function/references.rb +28 -17
- data/lib/isodoc/function/to_word_html.rb +2 -2
- data/lib/isodoc/function/utils.rb +57 -51
- data/lib/isodoc/gem_tasks.rb +133 -0
- data/lib/isodoc/metadata.rb +69 -63
- data/lib/isodoc/sassc_importer.rb +11 -0
- data/lib/isodoc/version.rb +1 -1
- data/lib/isodoc/xref/xref_sect_gen.rb +3 -7
- data/spec/assets/{html.css → html.scss} +0 -0
- data/spec/isodoc/footnotes_spec.rb +2 -2
- data/spec/isodoc/postproc_spec.rb +1319 -1345
- data/spec/isodoc/ref_spec.rb +1 -1
- data/spec/isodoc/section_spec.rb +52 -0
- metadata +28 -18
@@ -49,9 +49,9 @@ time, mark, audio, video {
|
|
49
49
|
}
|
50
50
|
|
51
51
|
html, body, div, span, applet, object, iframe,
|
52
|
-
p, blockquote,
|
53
|
-
a, abbr, acronym, address, big, cite,
|
54
|
-
del, dfn, em, img, ins, q, s,
|
52
|
+
p, blockquote,
|
53
|
+
a, abbr, acronym, address, big, cite,
|
54
|
+
del, dfn, em, img, ins, q, s,
|
55
55
|
small, strike, strong, sub, sup, var,
|
56
56
|
b, u, i, center,
|
57
57
|
dl, dt, dd, ol, ul, li,
|
File without changes
|
data/lib/isodoc/convert.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'isodoc/common'
|
4
|
+
require 'fileutils'
|
5
|
+
require 'tempfile'
|
5
6
|
|
6
7
|
module IsoDoc
|
7
8
|
class Convert < ::IsoDoc::Common
|
@@ -27,15 +28,25 @@ module IsoDoc
|
|
27
28
|
# scripts_pdf: Scripts file for PDF
|
28
29
|
# datauriimage: Encode images in HTML output as data URIs
|
29
30
|
def initialize(options)
|
30
|
-
@libdir
|
31
|
-
options.merge!(default_fonts(options))
|
32
|
-
|
31
|
+
@libdir ||= File.dirname(__FILE__)
|
32
|
+
options.merge!(default_fonts(options)) do |_, old, new|
|
33
|
+
old || new
|
34
|
+
end
|
35
|
+
.merge!(default_file_locations(options)) do |_, old, new|
|
36
|
+
old || new
|
37
|
+
end
|
33
38
|
@options = options
|
34
39
|
@files_to_delete = []
|
35
40
|
@tempfile_cache = []
|
36
|
-
@htmlstylesheet_name =
|
37
|
-
|
38
|
-
|
41
|
+
@htmlstylesheet_name = precompiled_style_or_original(
|
42
|
+
options[:htmlstylesheet]
|
43
|
+
)
|
44
|
+
@wordstylesheet_name = precompiled_style_or_original(
|
45
|
+
options[:wordstylesheet]
|
46
|
+
)
|
47
|
+
@standardstylesheet_name = precompiled_style_or_original(
|
48
|
+
options[:standardstylesheet]
|
49
|
+
)
|
39
50
|
@header = options[:header]
|
40
51
|
@htmlcoverpage = options[:htmlcoverpage]
|
41
52
|
@wordcoverpage = options[:wordcoverpage]
|
@@ -48,8 +59,8 @@ module IsoDoc
|
|
48
59
|
@olstyle = options[:olstyle]
|
49
60
|
@datauriimage = options[:datauriimage]
|
50
61
|
@suppressheadingnumbers = options[:suppressheadingnumbers]
|
51
|
-
@break_up_urls_in_tables = options[:break_up_urls_in_tables] ==
|
52
|
-
@termdomain =
|
62
|
+
@break_up_urls_in_tables = options[:break_up_urls_in_tables] == 'true'
|
63
|
+
@termdomain = ''
|
53
64
|
@termexample = false
|
54
65
|
@note = false
|
55
66
|
@sourcecode = false
|
@@ -61,40 +72,57 @@ module IsoDoc
|
|
61
72
|
@in_figure = false
|
62
73
|
@seen_footnote = Set.new
|
63
74
|
@c = HTMLEntities.new
|
64
|
-
@openmathdelim =
|
65
|
-
@closemathdelim =
|
66
|
-
@lang =
|
67
|
-
@script =
|
75
|
+
@openmathdelim = '`'
|
76
|
+
@closemathdelim = '`'
|
77
|
+
@lang = 'en'
|
78
|
+
@script = 'Latn'
|
68
79
|
@maxwidth = 1200
|
69
80
|
@maxheight = 800
|
70
81
|
@wordToClevels = options[:doctoclevels].to_i
|
71
|
-
@wordToClevels = 2 if @wordToClevels
|
82
|
+
@wordToClevels = 2 if @wordToClevels.zero?
|
72
83
|
@htmlToClevels = options[:htmltoclevels].to_i
|
73
|
-
@htmlToClevels = 2 if @htmlToClevels
|
74
|
-
@bookmarks_allocated = {
|
84
|
+
@htmlToClevels = 2 if @htmlToClevels.zero?
|
85
|
+
@bookmarks_allocated = { 'X' => true }
|
75
86
|
@fn_bookmarks = {}
|
76
87
|
end
|
77
88
|
|
89
|
+
# Check if already compiled version(.css) exists,
|
90
|
+
# if not, return original scss file. During release
|
91
|
+
# we compile scss into css files in order to not depend on scss
|
92
|
+
def precompiled_style_or_original(stylesheet_path)
|
93
|
+
# Already have compiled stylesheet, use it
|
94
|
+
return stylesheet_path if stylesheet_path.nil? ||
|
95
|
+
File.extname(stylesheet_path) == '.css'
|
96
|
+
|
97
|
+
basename = File.basename(stylesheet_path, '.*')
|
98
|
+
compiled_path = File.join(File.dirname(stylesheet_path),
|
99
|
+
"#{basename}.css")
|
100
|
+
return stylesheet_path unless File.file?(compiled_path)
|
101
|
+
|
102
|
+
compiled_path
|
103
|
+
end
|
104
|
+
|
78
105
|
# run this after @meta is populated
|
79
106
|
def populate_css
|
80
|
-
@htmlstylesheet = generate_css(@htmlstylesheet_name, true
|
81
|
-
@wordstylesheet = generate_css(@wordstylesheet_name, false
|
82
|
-
@standardstylesheet = generate_css(@standardstylesheet_name, false
|
107
|
+
@htmlstylesheet = generate_css(@htmlstylesheet_name, true)
|
108
|
+
@wordstylesheet = generate_css(@wordstylesheet_name, false)
|
109
|
+
@standardstylesheet = generate_css(@standardstylesheet_name, false)
|
83
110
|
end
|
84
111
|
|
85
112
|
def tmpimagedir_suffix
|
86
|
-
|
113
|
+
'_images'
|
87
114
|
end
|
88
115
|
|
89
116
|
def default_fonts(_options)
|
90
117
|
{
|
91
|
-
bodyfont:
|
92
|
-
headerfont:
|
93
|
-
monospacefont:
|
118
|
+
bodyfont: 'Arial',
|
119
|
+
headerfont: 'Arial',
|
120
|
+
monospacefont: 'Courier'
|
94
121
|
}
|
95
122
|
end
|
96
123
|
|
97
|
-
# none for this parent gem, but will be populated in child
|
124
|
+
# none for this parent gem, but will be populated in child
|
125
|
+
# gems which have access to stylesheets &c; e.g.
|
98
126
|
# {
|
99
127
|
# htmlstylesheet: html_doc_path("htmlstyle.scss"),
|
100
128
|
# htmlcoverpage: html_doc_path("html_rsd_titlepage.html"),
|
@@ -112,30 +140,51 @@ module IsoDoc
|
|
112
140
|
{}
|
113
141
|
end
|
114
142
|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
143
|
+
def fonts_options
|
144
|
+
{
|
145
|
+
'bodyfont' => options[:bodyfont] || 'Arial',
|
146
|
+
'headerfont' => options[:headerfont] || 'Arial',
|
147
|
+
'monospacefont' => options[:monospacefont] || 'Courier'
|
148
|
+
}
|
149
|
+
end
|
150
|
+
|
151
|
+
def scss_fontheader
|
152
|
+
b = options[:bodyfont] || 'Arial'
|
153
|
+
h = options[:headerfont] || 'Arial'
|
154
|
+
m = options[:monospacefont] || 'Courier'
|
120
155
|
"$bodyfont: #{b};\n$headerfont: #{h};\n$monospacefont: #{m};\n"
|
121
156
|
end
|
122
157
|
|
123
158
|
def html_doc_path(file)
|
124
|
-
File.join(@libdir, File.join(
|
159
|
+
File.join(@libdir, File.join('html', file))
|
160
|
+
end
|
161
|
+
|
162
|
+
def convert_scss(filename, stylesheet)
|
163
|
+
require 'sassc'
|
164
|
+
require 'isodoc/sassc_importer'
|
165
|
+
|
166
|
+
[File.join(Gem.loaded_specs['isodoc'].full_gem_path,
|
167
|
+
'lib', 'isodoc'),
|
168
|
+
File.dirname(filename)].each do |name|
|
169
|
+
SassC.load_paths << name
|
170
|
+
end
|
171
|
+
SassC::Engine.new(scss_fontheader + stylesheet, syntax: :scss,
|
172
|
+
importer: SasscImporter)
|
173
|
+
.render
|
125
174
|
end
|
126
175
|
|
127
|
-
def generate_css(filename, stripwordcss
|
128
|
-
return nil
|
129
|
-
|
176
|
+
def generate_css(filename, stripwordcss)
|
177
|
+
return nil if filename.nil?
|
178
|
+
|
179
|
+
stylesheet = File.read(filename, encoding: 'UTF-8')
|
130
180
|
stylesheet = populate_template(stylesheet, :word)
|
131
|
-
stylesheet.gsub!(/(\s|\{)mso-[^:]+:[^;]+;/m,
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
f.write(engine.render)
|
181
|
+
stylesheet.gsub!(/(\s|\{)mso-[^:]+:[^;]+;/m, '\\1') if stripwordcss
|
182
|
+
if File.extname(filename) == '.scss'
|
183
|
+
stylesheet = convert_scss(filename, stylesheet)
|
184
|
+
end
|
185
|
+
Tempfile.open([File.basename(filename, '.*'), 'css'],
|
186
|
+
encoding: 'utf-8') do |f|
|
187
|
+
f.write(stylesheet)
|
139
188
|
f
|
140
189
|
end
|
141
190
|
end
|
@@ -143,10 +192,10 @@ module IsoDoc
|
|
143
192
|
def convert1(docxml, filename, dir)
|
144
193
|
@xrefs.parse docxml
|
145
194
|
noko do |xml|
|
146
|
-
xml.html **{ lang:
|
147
|
-
html.parent.add_namespace(
|
195
|
+
xml.html **{ lang: @lang.to_s } do |html|
|
196
|
+
html.parent.add_namespace('epub', 'http://www.idpf.org/2007/ops')
|
148
197
|
info docxml, nil
|
149
|
-
populate_css
|
198
|
+
populate_css
|
150
199
|
html.head { |head| define_head head, filename, dir }
|
151
200
|
make_body(html, docxml)
|
152
201
|
end
|
@@ -164,17 +213,21 @@ module IsoDoc
|
|
164
213
|
def convert_init(file, input_filename, debug)
|
165
214
|
docxml = Nokogiri::XML(file)
|
166
215
|
filename, dir = init_file(input_filename, debug)
|
167
|
-
docxml.root.default_namespace =
|
168
|
-
lang = docxml&.at(ns(
|
169
|
-
script = docxml&.at(ns(
|
216
|
+
docxml.root.default_namespace = ''
|
217
|
+
lang = docxml&.at(ns('//bibdata/language'))&.text || @lang
|
218
|
+
script = docxml&.at(ns('//bibdata/script'))&.text || @script
|
170
219
|
i18n_init(lang, script)
|
171
220
|
metadata_init(lang, script, @labels)
|
221
|
+
@meta.fonts_options = fonts_options
|
172
222
|
xref_init(lang, script, self, @labels, {})
|
173
223
|
[docxml, filename, dir]
|
174
224
|
end
|
175
225
|
|
176
|
-
def convert(input_filename,
|
177
|
-
|
226
|
+
def convert(input_filename,
|
227
|
+
file = nil,
|
228
|
+
debug = false,
|
229
|
+
output_filename = nil)
|
230
|
+
file = File.read(input_filename, encoding: 'utf-8') if file.nil?
|
178
231
|
@openmathdelim, @closemathdelim = extract_delims(file)
|
179
232
|
docxml, filename, dir = convert_init(file, input_filename, debug)
|
180
233
|
result = convert1(docxml, filename, dir)
|
@@ -186,7 +239,7 @@ module IsoDoc
|
|
186
239
|
|
187
240
|
def middle_clause
|
188
241
|
"//clause[parent::sections][not(xmlns:title = 'Scope')]"\
|
189
|
-
|
242
|
+
'[not(descendant::terms)]'
|
190
243
|
end
|
191
244
|
end
|
192
245
|
end
|
@@ -16,22 +16,24 @@ module IsoDoc::Function
|
|
16
16
|
identifiers = render_identifier(ids)
|
17
17
|
if biblio then ref_entry_code(ref, ordinal, identifiers, ids)
|
18
18
|
else
|
19
|
-
ref << "#{identifiers[0] || identifiers[1]}
|
20
|
-
ref << "#{identifiers[1]}
|
19
|
+
ref << "#{identifiers[0] || identifiers[1]}"
|
20
|
+
ref << ", #{identifiers[1]}" if identifiers[0] && identifiers[1]
|
21
21
|
end
|
22
|
+
ref << ", " unless biblio && !identifiers[1]
|
22
23
|
reference_format(b, ref)
|
23
24
|
end
|
24
25
|
end
|
25
26
|
|
26
27
|
def std_bibitem_entry(list, b, ordinal, biblio)
|
27
28
|
list.p **attr_code(iso_bibitem_entry_attrs(b, biblio)) do |ref|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
29
|
+
identifiers = render_identifier(bibitem_ref_code(b))
|
30
|
+
if biblio then ref_entry_code(ref, ordinal, identifiers, nil)
|
31
|
+
else
|
32
|
+
ref << "#{identifiers[0] || identifiers[1]}"
|
33
|
+
ref << ", #{identifiers[1]}" if identifiers[0] && identifiers[1]
|
34
|
+
end
|
33
35
|
date_note_process(b, ref)
|
34
|
-
ref << ", "
|
36
|
+
ref << ", " unless biblio && !identifiers[1]
|
35
37
|
reference_format(b, ref)
|
36
38
|
end
|
37
39
|
end
|
@@ -40,9 +42,7 @@ module IsoDoc::Function
|
|
40
42
|
# else, use both ordinal, as prefix, and t
|
41
43
|
def ref_entry_code(r, ordinal, t, id)
|
42
44
|
prefix_bracketed_ref(r, t[0] || "[#{ordinal}]")
|
43
|
-
|
44
|
-
r << "#{t[1]}, "
|
45
|
-
end
|
45
|
+
t[1] and r << "#{t[1]}"
|
46
46
|
end
|
47
47
|
|
48
48
|
def pref_ref_code(b)
|
@@ -153,22 +153,33 @@ module IsoDoc::Function
|
|
153
153
|
end
|
154
154
|
end
|
155
155
|
|
156
|
+
def norm_ref_xpath
|
157
|
+
"//bibliography/references[@normative = 'true'] | "\
|
158
|
+
"//bibliography/clause[.//references[@normative = 'true']]"
|
159
|
+
end
|
160
|
+
|
156
161
|
def norm_ref(isoxml, out, num)
|
157
|
-
|
158
|
-
f = isoxml.at(ns(q)) or return num
|
162
|
+
f = isoxml.at(ns(norm_ref_xpath)) or return num
|
159
163
|
out.div do |div|
|
160
164
|
num = num + 1
|
161
165
|
clause_name(num, @normref_lbl, div, nil)
|
162
|
-
|
166
|
+
if f.name == "clause"
|
167
|
+
f.elements.each { |e| parse(e, div) unless e.name == "title" }
|
168
|
+
else
|
169
|
+
biblio_list(f, div, false)
|
170
|
+
end
|
163
171
|
end
|
164
172
|
num
|
165
173
|
end
|
166
174
|
|
167
|
-
|
168
|
-
"//bibliography/references
|
175
|
+
def bibliography_xpath
|
176
|
+
"//bibliography/clause[.//references]"\
|
177
|
+
"[not(.//references[@normative = 'true'])] | "\
|
178
|
+
"//bibliography/references[@normative = 'false']"
|
179
|
+
end
|
169
180
|
|
170
181
|
def bibliography(isoxml, out)
|
171
|
-
f = isoxml.at(ns(
|
182
|
+
f = isoxml.at(ns(bibliography_xpath)) || return
|
172
183
|
page_break(out)
|
173
184
|
out.div do |div|
|
174
185
|
div.h1 @bibliography_lbl, **{ class: "Section3" }
|
@@ -18,7 +18,7 @@ module IsoDoc::Function
|
|
18
18
|
|
19
19
|
def init_file(filename, debug)
|
20
20
|
filepath = Pathname.new(filename)
|
21
|
-
filename = filepath.sub_ext('').to_s
|
21
|
+
filename = filepath.sub_ext('').sub(/\.presentation$/, "").to_s
|
22
22
|
dir = "#{filename}_files"
|
23
23
|
unless debug
|
24
24
|
Dir.mkdir(dir, 0777) unless File.exists?(dir)
|
@@ -45,7 +45,7 @@ module IsoDoc::Function
|
|
45
45
|
head.style do |style|
|
46
46
|
@standardstylesheet.open
|
47
47
|
stylesheet = @standardstylesheet.read.
|
48
|
-
gsub("FILENAME", File.basename(filename))
|
48
|
+
gsub("FILENAME", File.basename(filename).sub(/\.presentation$/, ""))
|
49
49
|
style.comment "\n#{stylesheet}\n"
|
50
50
|
end
|
51
51
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module IsoDoc::Function
|
2
4
|
module Utils
|
3
5
|
def date_range(date)
|
@@ -9,50 +11,50 @@ module IsoDoc::Function
|
|
9
11
|
end
|
10
12
|
|
11
13
|
def insert_tab(out, n)
|
12
|
-
[1..n].each { out <<
|
14
|
+
[1..n].each { out << ' ' }
|
13
15
|
end
|
14
16
|
|
15
17
|
# add namespaces for Word fragments
|
16
|
-
NOKOHEAD = <<~HERE
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
18
|
+
NOKOHEAD = <<~HERE
|
19
|
+
<!DOCTYPE html SYSTEM
|
20
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
21
|
+
<html xmlns="http://www.w3.org/1999/xhtml">
|
22
|
+
<head> <title></title> <meta charset="UTF-8" /> </head>
|
23
|
+
<body> </body> </html>
|
22
24
|
HERE
|
23
25
|
|
24
26
|
# block for processing XML document fragments as XHTML,
|
25
27
|
# to allow for HTMLentities
|
26
28
|
def noko(&block)
|
27
29
|
doc = ::Nokogiri::XML.parse(NOKOHEAD)
|
28
|
-
fragment = doc.fragment(
|
30
|
+
fragment = doc.fragment('')
|
29
31
|
::Nokogiri::XML::Builder.with fragment, &block
|
30
|
-
fragment.to_xml(encoding:
|
31
|
-
l.gsub(/\s*\n/,
|
32
|
+
fragment.to_xml(encoding: 'US-ASCII').lines.map do |l|
|
33
|
+
l.gsub(/\s*\n/, '')
|
32
34
|
end
|
33
35
|
end
|
34
36
|
|
35
37
|
def attr_code(attributes)
|
36
38
|
attributes = attributes.reject { |_, val| val.nil? }.map
|
37
39
|
attributes.map do |k, v|
|
38
|
-
[k,
|
40
|
+
[k, v.is_a?(String) ? HTMLEntities.new.decode(v) : v]
|
39
41
|
end.to_h
|
40
42
|
end
|
41
43
|
|
42
44
|
DOCTYPE_HDR = '<!DOCTYPE html SYSTEM '\
|
43
|
-
'"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'
|
45
|
+
'"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'
|
44
46
|
|
45
47
|
def to_xhtml(xml)
|
46
|
-
xml.gsub!(/<\?xml[^>]*>/,
|
47
|
-
/<!DOCTYPE /.match
|
48
|
+
xml.gsub!(/<\?xml[^>]*>/, '')
|
49
|
+
/<!DOCTYPE /.match(xml) || (xml = DOCTYPE_HDR + xml)
|
48
50
|
xml = xml.split(/(\&[^ \r\n\t#;]+;)/).map do |t|
|
49
|
-
/^(\&[^ \t\r\n#;]+;)/.match(t) ?
|
51
|
+
/^(\&[^ \t\r\n#;]+;)/.match?(t) ?
|
50
52
|
HTMLEntities.new.encode(HTMLEntities.new.decode(t), :hexadecimal) : t
|
51
|
-
end.join(
|
53
|
+
end.join('')
|
52
54
|
begin
|
53
|
-
Nokogiri::XML.parse(xml
|
55
|
+
Nokogiri::XML.parse(xml, &:strict)
|
54
56
|
rescue Nokogiri::XML::SyntaxError => e
|
55
|
-
File.open("#{@filename}.#{@format}.err",
|
57
|
+
File.open("#{@filename}.#{@format}.err", 'w:UTF-8') { |f| f.write xml }
|
56
58
|
abort "Malformed Output XML for #{@format}: #{e} (see #{@filename}.#{@format}.err)"
|
57
59
|
end
|
58
60
|
end
|
@@ -64,7 +66,7 @@ module IsoDoc::Function
|
|
64
66
|
end
|
65
67
|
|
66
68
|
def from_xhtml(xml)
|
67
|
-
xml.to_xml.sub(%r{ xmlns="http://www.w3.org/1999/xhtml"},
|
69
|
+
xml.to_xml.sub(%r{ xmlns="http://www.w3.org/1999/xhtml"}, '')
|
68
70
|
end
|
69
71
|
|
70
72
|
CLAUSE_ANCESTOR =
|
@@ -72,7 +74,7 @@ module IsoDoc::Function
|
|
72
74
|
"local-name() = 'acknowledgements' or local-name() = 'term' or "\
|
73
75
|
"local-name() = 'appendix' or local-name() = 'foreword' or "\
|
74
76
|
"local-name() = 'introduction' or local-name() = 'terms' or "\
|
75
|
-
"local-name() = 'clause' or local-name() = 'references']/@id"
|
77
|
+
"local-name() = 'clause' or local-name() = 'references']/@id"
|
76
78
|
|
77
79
|
def get_clause_id(node)
|
78
80
|
clause = node.xpath(CLAUSE_ANCESTOR)
|
@@ -86,7 +88,7 @@ module IsoDoc::Function
|
|
86
88
|
"local-name() = 'acknowledgements' or local-name() = 'term' or "\
|
87
89
|
"local-name() = 'clause' or local-name() = 'references' or "\
|
88
90
|
"local-name() = 'figure' or local-name() = 'formula' or "\
|
89
|
-
"local-name() = 'table' or local-name() = 'example']/@id"
|
91
|
+
"local-name() = 'table' or local-name() = 'example']/@id"
|
90
92
|
|
91
93
|
def get_note_container_id(node)
|
92
94
|
container = node.xpath(NOTE_CONTAINER_ANCESTOR)
|
@@ -94,7 +96,7 @@ module IsoDoc::Function
|
|
94
96
|
end
|
95
97
|
|
96
98
|
def sentence_join(array)
|
97
|
-
return
|
99
|
+
return '' if array.nil? || array.empty?
|
98
100
|
if array.length == 1 then array[0]
|
99
101
|
else
|
100
102
|
IsoDoc::Function::I18n::l10n("#{array[0..-2].join(', ')} "\
|
@@ -105,25 +107,25 @@ module IsoDoc::Function
|
|
105
107
|
|
106
108
|
# avoid `; avoid {{ (Liquid Templates); avoid [[ (Javascript)
|
107
109
|
def extract_delims(text)
|
108
|
-
@openmathdelim =
|
109
|
-
@closemathdelim =
|
110
|
+
@openmathdelim = '(#('
|
111
|
+
@closemathdelim = ')#)'
|
110
112
|
while text.include?(@openmathdelim) || text.include?(@closemathdelim)
|
111
|
-
@openmathdelim +=
|
112
|
-
@closemathdelim +=
|
113
|
+
@openmathdelim += '('
|
114
|
+
@closemathdelim += ')'
|
113
115
|
end
|
114
116
|
[@openmathdelim, @closemathdelim]
|
115
117
|
end
|
116
118
|
|
117
119
|
def header_strip(h)
|
118
|
-
h = h.to_s.gsub(%r{<br\s*/>},
|
119
|
-
|
120
|
+
h = h.to_s.gsub(%r{<br\s*/>}, ' ').gsub(/<\/?h[123456][^>]*>/, '')
|
121
|
+
.gsub(/<\/?b[^>]*>/, '')
|
120
122
|
h1 = to_xhtml_fragment(h.dup)
|
121
123
|
h1.traverse do |x|
|
122
|
-
x.replace(
|
123
|
-
x.remove if x.name ==
|
124
|
-
x.remove if x.name ==
|
125
|
-
x.remove if x.name ==
|
126
|
-
x.replace(x.children) if x.name ==
|
124
|
+
x.replace(' ') if x.name == 'span' && /mso-tab-count/.match(x['style'])
|
125
|
+
x.remove if x.name == 'span' && x['class'] == 'MsoCommentReference'
|
126
|
+
x.remove if x.name == 'a' && x['class'] == 'FootnoteRef'
|
127
|
+
x.remove if x.name == 'span' && /mso-bookmark/.match(x['style'])
|
128
|
+
x.replace(x.children) if x.name == 'a'
|
127
129
|
end
|
128
130
|
from_xhtml(h1)
|
129
131
|
end
|
@@ -135,9 +137,9 @@ module IsoDoc::Function
|
|
135
137
|
def liquid(doc)
|
136
138
|
# unescape HTML escapes in doc
|
137
139
|
doc = doc.split(%r<(\{%|%\})>).each_slice(4).map do |a|
|
138
|
-
a[2] = a[2].gsub(/\</,
|
139
|
-
a.join(
|
140
|
-
end.join(
|
140
|
+
a[2] = a[2].gsub(/\</, '<').gsub(/\>/, '>') if a.size > 2
|
141
|
+
a.join('')
|
142
|
+
end.join('')
|
141
143
|
Liquid::Template.parse(doc)
|
142
144
|
end
|
143
145
|
|
@@ -147,37 +149,41 @@ module IsoDoc::Function
|
|
147
149
|
end
|
148
150
|
|
149
151
|
def populate_template(docxml, _format = nil)
|
150
|
-
meta = @meta
|
152
|
+
meta = @meta
|
153
|
+
.get
|
154
|
+
.merge(@labels || {})
|
155
|
+
.merge(@meta.labels || {})
|
156
|
+
.merge(@meta.fonts_options || {})
|
151
157
|
template = liquid(docxml)
|
152
|
-
template.render(meta.map { |k, v| [k.to_s, empty2nil(v)] }.to_h)
|
153
|
-
|
158
|
+
template.render(meta.map { |k, v| [k.to_s, empty2nil(v)] }.to_h)
|
159
|
+
.gsub('<', '<').gsub('>', '>').gsub('&', '&')
|
154
160
|
end
|
155
161
|
|
156
|
-
def save_dataimage(uri,
|
162
|
+
def save_dataimage(uri, _relative_dir = true)
|
157
163
|
%r{^data:image/(?<imgtype>[^;]+);base64,(?<imgdata>.+)$} =~ uri
|
158
|
-
imgtype.sub!(/\+[a-z0-9]+$/,
|
159
|
-
imgtype =
|
160
|
-
Tempfile.open([
|
164
|
+
imgtype.sub!(/\+[a-z0-9]+$/, '') # svg+xml
|
165
|
+
imgtype = 'png' unless /^[a-z0-9]+$/.match imgtype
|
166
|
+
Tempfile.open(['image', ".#{imgtype}"]) do |f|
|
161
167
|
f.binmode
|
162
168
|
f.write(Base64.strict_decode64(imgdata))
|
163
|
-
@tempfile_cache << f #persist to the end
|
169
|
+
@tempfile_cache << f # persist to the end
|
164
170
|
f.path
|
165
171
|
end
|
166
172
|
end
|
167
173
|
|
168
174
|
def image_localfile(i)
|
169
|
-
if /^data:image/.match i[
|
170
|
-
save_dataimage(i[
|
171
|
-
elsif %r{^([A-Z]:)?/}.match i[
|
172
|
-
i[
|
175
|
+
if /^data:image/.match? i['src']
|
176
|
+
save_dataimage(i['src'], false)
|
177
|
+
elsif %r{^([A-Z]:)?/}.match? i['src']
|
178
|
+
i['src']
|
173
179
|
else
|
174
|
-
File.join(@localdir, i[
|
180
|
+
File.join(@localdir, i['src'])
|
175
181
|
end
|
176
182
|
end
|
177
183
|
|
178
184
|
def labelled_ancestor(node)
|
179
|
-
|
180
|
-
|
185
|
+
!node.ancestors('example, requirement, recommendation, permission, '\
|
186
|
+
'table, figure, sourcecode').empty?
|
181
187
|
end
|
182
188
|
end
|
183
189
|
end
|