isodoc 3.1.11 → 3.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8160c3e32a52cffb4ec08452c22872631c0a55dfd3ae81b3bb5dfdf6269769c6
4
- data.tar.gz: bb0f4a1a46099a5315d97991b6bff04a4f08a5364f8b5d4a3ae74bc4c2a2ea6c
3
+ metadata.gz: a3b8a9f7427b4df55cade247b1f292beb41b47d1ae684c9e1d3a7afe547c303f
4
+ data.tar.gz: e7bd73e5b3a1078f67c9b4f959e0a0255d524a600757d064353ddd941c8165c7
5
5
  SHA512:
6
- metadata.gz: 221dafa4fa11246d7b0e61c5553c6199e2a4a58bc409d6389a889a5cb4bee761c6e5a7a8d2936acefd41083cb86436845a6719519d50a675774149fd5a2c92ad
7
- data.tar.gz: de02f2a399990422f41dd6380bd337462b3a90609e1e6caefb7266d117a24b29b17a1b69015188cd087373eeb00ba097678aeed669d8bf7b2a1c73037c7e306b
6
+ metadata.gz: 241e2e7855b90c61d4d17955125f3f2025a8b4bd986bc32192355e9eee1af51a931d039b07520bb1403ae0dac1b6b14d6969c62815be3d502935198efc9fb124
7
+ data.tar.gz: f8a77cad3f2a0b46679c0cc980180911574b6e4d7649979c58bb29c7024c26c0a8b2ea380d60b97de62a29f85a71e2441291f0e00907789f7c999d0f1f67dc46
data/isodoc.gemspec CHANGED
@@ -30,7 +30,7 @@ Gem::Specification.new do |spec|
30
30
 
31
31
  spec.add_dependency "base64"
32
32
  spec.add_dependency "bigdecimal"
33
- spec.add_dependency "html2doc", "~> 1.9.0"
33
+ spec.add_dependency "html2doc", "~> 1.10.0"
34
34
  # spec.add_dependency "isodoc-i18n", "~> 1.1.0" # already in relaton-render and mn-requirements
35
35
  # spec.add_dependency "relaton-cli"
36
36
  # spec.add_dependency "metanorma-utils", "~> 1.5.0" # already in isodoc-i18n
@@ -311,9 +311,15 @@ h6:hover > a.anchor,
311
311
  padding: 0;
312
312
  }
313
313
 
314
+ .svg-container {
315
+ width: 100%; /* or any desired width */
316
+ display: block; /* ← removes unwanted inline spacing */
317
+ }
318
+
314
319
  svg {
315
320
  width: 100%;
316
- overflow: visible;
321
+ height: auto; /* ← key to maintaining aspect ratio */
322
+ display: block; /* ← removes unwanted inline spacing */
317
323
  }
318
324
 
319
325
  #standard-band {
@@ -311,7 +311,13 @@ h6:hover > a.anchor,
311
311
  padding: 0;
312
312
  }
313
313
 
314
+ .svg-container {
315
+ width: 100%; /* or any desired width */
316
+ display: block; /* ← removes unwanted inline spacing */
317
+ }
318
+
314
319
  svg {
315
320
  width: 100%;
316
- overflow: visible;
321
+ height: auto; /* ← key to maintaining aspect ratio */
322
+ display: block; /* ← removes unwanted inline spacing */
317
323
  }
@@ -277,6 +277,13 @@ visibility:visible;
277
277
  padding: 0;
278
278
  }
279
279
 
280
+ .svg-container {
281
+ width: 100%; /* or any desired width */
282
+ display: block; /* ← removes unwanted inline spacing */
283
+ }
284
+
280
285
  svg {
281
- width: 100%; overflow: visible;
286
+ width: 100%;
287
+ height: auto; /* ← key to maintaining aspect ratio */
288
+ display: block; /* ← removes unwanted inline spacing */
282
289
  }
@@ -58,7 +58,7 @@ module IsoDoc
58
58
  end
59
59
  end
60
60
 
61
- def fmt_review_body_parse(node, out); end
61
+ def fmt_annotation_body_parse(node, out); end
62
62
  end
63
63
  end
64
64
  end
@@ -200,33 +200,14 @@ module IsoDoc
200
200
  node&.children&.each { |n| parse(n, out) }
201
201
  end
202
202
 
203
- def location_parse(node, out); end
204
- def author_parse(node, out); end
205
- def xref_label_parse(node, out); end
206
- def name_parse(node, out); end
207
- def semx_definition_parse(node, out); end
208
- def semx_xref_parse(node, out); end
209
- def semx_eref_parse(node, out); end
210
- def semx_link_parse(node, out); end
211
- def semx_origin_parse(node, out); end
212
- def date_parse(node, out); end
213
- def semx_stem_parse(node, out); end
214
- def floating_title_parse(node, out); end
215
- def identifier_parse(node, out); end
216
- def concept_parse(node, out); end
217
- def erefstack_parse(node, out); end
218
- def svgmap_parse(node, out); end
219
- def amend_parse(node, out); end
220
- def semx_sourcecode_parse(node, out); end
221
- def review_note_parse(node, out); end
222
- def semx_source_parse(node, out); end
223
-
224
203
  def fmt_name_parse(node, out)
225
204
  children_parse(node, out)
226
205
  end
227
206
 
228
207
  def fmt_identifier_parse(node, out)
229
- children_parse(node, out)
208
+ out.span style: "white-space: nowrap;" do |s|
209
+ children_parse(node, s)
210
+ end
230
211
  end
231
212
 
232
213
  def fmt_concept_parse(node, out)
@@ -245,11 +226,11 @@ module IsoDoc
245
226
  children_parse(node, out)
246
227
  end
247
228
 
248
- def fmt_review_start_parse(node, out)
229
+ def fmt_annotation_start_parse(node, out)
249
230
  children_parse(node, out)
250
231
  end
251
232
 
252
- def fmt_review_end_parse(node, out)
233
+ def fmt_annotation_end_parse(node, out)
253
234
  children_parse(node, out)
254
235
  end
255
236
  end
@@ -77,6 +77,27 @@ module IsoDoc
77
77
  children_parse(node, e)
78
78
  end
79
79
  end
80
+
81
+ def location_parse(node, out); end
82
+ def author_parse(node, out); end
83
+ def xref_label_parse(node, out); end
84
+ def name_parse(node, out); end
85
+ def semx_definition_parse(node, out); end
86
+ def semx_xref_parse(node, out); end
87
+ def semx_eref_parse(node, out); end
88
+ def semx_link_parse(node, out); end
89
+ def semx_origin_parse(node, out); end
90
+ def date_parse(node, out); end
91
+ def semx_stem_parse(node, out); end
92
+ def floating_title_parse(node, out); end
93
+ def identifier_parse(node, out); end
94
+ def concept_parse(node, out); end
95
+ def erefstack_parse(node, out); end
96
+ def svgmap_parse(node, out); end
97
+ def amend_parse(node, out); end
98
+ def semx_sourcecode_parse(node, out); end
99
+ def annotation_note_parse(node, out); end
100
+ def semx_source_parse(node, out); end
80
101
  end
81
102
  end
82
103
  end
@@ -37,6 +37,7 @@ module IsoDoc
37
37
  def ol_attrs(node)
38
38
  { # type: node["type"] ? ol_style(node["type"].to_sym) : ol_depth(node),
39
39
  type: ol_style(node["type"]&.to_sym),
40
+ start: node["start"],
40
41
  id: node["id"], style: keep_style(node) }
41
42
  end
42
43
 
@@ -45,17 +45,15 @@ module IsoDoc
45
45
  c = node["class"]
46
46
  bordered = "border-width:1px;border-spacing:0;"
47
47
  (%w(modspec).include?(c) || !c) or bordered = ""
48
- attr_code(
49
- id: node["id"],
50
- class: c || "MsoISOTable",
51
- style: "#{bordered}#{width}#{keep_style(node)}",
52
- title: node["alt"],
53
- )
48
+ style = node["style"] ? "" : "#{bordered}#{width}"
49
+ attr_code(id: node["id"],
50
+ class: c || "MsoISOTable",
51
+ style: "#{style}#{keep_style(node)}",
52
+ title: node["alt"])
54
53
  end
55
54
 
56
55
  def tcaption(node, table)
57
- return unless node["summary"]
58
-
56
+ node["summary"] or return
59
57
  table.caption do |c|
60
58
  c.span style: "display:none" do |s|
61
59
  s << node["summary"]
@@ -157,7 +157,7 @@ module IsoDoc
157
157
  when "fmt-source" then source_parse(node, out)
158
158
  when "tr" then tr_parse(node, out)
159
159
  when "note" then note_parse(node, out)
160
- when "review" then review_note_parse(node, out)
160
+ when "annotation" then annotation_note_parse(node, out)
161
161
  when "admonition" then admonition_parse(node, out)
162
162
  when "formula" then formula_parse(node, out)
163
163
  when "table" then table_parse(node, out)
@@ -237,9 +237,9 @@ module IsoDoc
237
237
  when "fmt-fn-body" then fmt_fn_body_parse(node, out)
238
238
  when "fmt-fn-label" then fmt_fn_label_parse(node, out)
239
239
  when "fmt-footnote-container" then fmt_footnote_container_parse(node, out)
240
- when "fmt-review-start" then fmt_review_start_parse(node, out)
241
- when "fmt-review-end" then fmt_review_end_parse(node, out)
242
- when "fmt-review-body" then fmt_review_body_parse(node, out)
240
+ when "fmt-annotation-start" then fmt_annotation_start_parse(node, out)
241
+ when "fmt-annotation-end" then fmt_annotation_end_parse(node, out)
242
+ when "fmt-annotation-body" then fmt_annotation_body_parse(node, out)
243
243
  else error_parse(node, out)
244
244
  end
245
245
  end
@@ -100,12 +100,21 @@ module IsoDoc
100
100
  ret
101
101
  end
102
102
 
103
+ def svg_supply_viewbox(svg)
104
+ svg["viewbox"] and return
105
+ svg["height"] && svg["width"] or return
106
+ h = svg["height"].sub(/[^0-9]+$/, "")
107
+ w = svg["width"].sub(/[^0-9]+$/, "")
108
+ h.to_i.positive? && w.to_i.positive? or return
109
+ svg["viewbox"] = "0 0 #{w} #{h}"
110
+ end
111
+
103
112
  def image_body_parse(node, attrs, out)
104
113
  if svg = node.at("./m:svg", "m" => "http://www.w3.org/2000/svg")
105
- svg.delete("width")
106
- svg["height"] = "1px"
107
- svg["padding-bottom"] = "calc(100% * 3 / 4);"
108
- out.parent.add_child(svg)
114
+ svg_supply_viewbox(svg)
115
+ out.div class: "svg-container" do |div|
116
+ div.parent.add_child(svg)
117
+ end
109
118
  else super
110
119
  end
111
120
  end
@@ -83,7 +83,11 @@ module IsoDoc
83
83
  end
84
84
 
85
85
  def status_print(status)
86
- status.split(/[- ]/).map(&:capitalize).join(" ")
86
+ status.split(/[- ]/).map do |w|
87
+ letters = w.chars
88
+ letters.first.upcase!
89
+ letters.join
90
+ end.join(" ")
87
91
  end
88
92
 
89
93
  def docid(isoxml, _out)
@@ -102,9 +102,30 @@ module IsoDoc
102
102
  set(:agency, agency)
103
103
  set(:publisher, connectives_strip(@i18n.boolean_conj(publisher, "and")))
104
104
  set(:copublisher_logos, logos)
105
+ set(:copublisher_logo_attrs, copublisher_logo_attrs(xml))
105
106
  agency_addr(xml)
106
107
  end
107
108
 
109
+ def copublisher_logo_attrs(xml)
110
+ xml.xpath(ns("//metanorma-extension/presentation-metadata/*"))
111
+ .each_with_object([]) do |x, m|
112
+ copublisher_logo_attr?(x) or next
113
+ p = x.name.split(/[_-]/)
114
+ idx = (p[4] || "1").to_i - 1
115
+ m[idx] ||= {}
116
+ m[idx][p[2]] ||= {}
117
+ m[idx][p[2]][p[3]] = x.text
118
+ end
119
+ end
120
+
121
+ def copublisher_logo_attr?(elem)
122
+ elem.name.start_with?("logo-publisher-") or return false
123
+ p = elem.name.split(/[_-]/)
124
+ %w(doc html).include?(p[2]) &&
125
+ %w(height width).include?(p[3]) &&
126
+ (!p[4] || /^\d+/.match?(p[4]))
127
+ end
128
+
108
129
  def agency_addr(xml)
109
130
  a = xml.at(ns("//bibdata/contributor[xmlns:role/@type = 'publisher'][1]/" \
110
131
  "organization")) or return
@@ -1,7 +1,7 @@
1
1
  module IsoDoc
2
2
  class PresentationXMLConvert < ::IsoDoc::Convert
3
3
  def prefix_name(node, delims, label, elem)
4
- label, delims = prefix_name_defaults(node, delims, label)
4
+ label, delims = prefix_name_defaults(node, delims, label, elem)
5
5
  name, ins, ids, number = prefix_name_prep(node, elem)
6
6
  ins.next = fmt_xref_label(label, number, ids)
7
7
  # autonum can be empty, e.g single note in clause: "NOTE []"
@@ -11,8 +11,11 @@ module IsoDoc
11
11
  prefix_name_postprocess(node, elem)
12
12
  end
13
13
 
14
- def prefix_name_defaults(_node, delims, label)
14
+ def prefix_name_defaults(node, delims, label, elem)
15
15
  label&.empty? and label = nil
16
+ node["unnumbered"] == "true" && !node.at(ns("./#{elem}")) &&
17
+ node.name != "admonition" and label = nil
18
+ # do not caption unnumbered uncaptioned blocks, other than admonitions
16
19
  delims.nil? and delims = {}
17
20
  [label, delims]
18
21
  end
@@ -6,6 +6,7 @@ module IsoDoc
6
6
  a = bibdata_current(docxml) or return
7
7
  address_precompose(a)
8
8
  bibdata_i18n(a)
9
+ @xrefs.klass.info docxml, nil
9
10
  end
10
11
 
11
12
  def address_precompose(bib)
@@ -38,17 +39,23 @@ module IsoDoc
38
39
  end
39
40
 
40
41
  def bibdata_i18n(bib)
41
- hash_translate(bib, @i18n.get["doctype_dict"], "./ext/doctype")
42
- hash_translate(bib, @i18n.get["stage_dict"], "./status/stage")
43
- hash_translate(bib, @i18n.get["substage_dict"], "./status/substage")
42
+ hash_translate(bib, @i18n.get["doctype_dict"], "./ext/doctype",
43
+ "//presentation-metadata/doctype-alias", @lang)
44
+ hash_translate(bib, @i18n.get["stage_dict"], "./status/stage", nil, @lang)
45
+ hash_translate(bib, @i18n.get["substage_dict"], "./status/substage", nil,
46
+ @lang)
44
47
  edition_translate(bib)
45
48
  end
46
49
 
47
- def hash_translate(bibdata, hash, xpath, lang = @lang)
48
- x = bibdata.at(ns(xpath)) or return
50
+ # translate dest_xpath in bibdata using lookup in hash
51
+ # source text is dest_xpath by default, can be alt_source_xpath if given
52
+ def hash_translate(bibdata, hash, dest_xpath, alt_source_xpath, lang)
53
+ x = bibdata.at(ns(dest_xpath)) or return
54
+ alt_source_xpath and doctype = bibdata.at(ns(alt_source_xpath))
55
+ doctype ||= x
49
56
  hash.is_a? Hash or return
50
- hash[x.text] or return
51
- tag_translate(x, lang, hash[x.text])
57
+ hash[doctype.text] or return
58
+ tag_translate(x, lang, hash[doctype.text])
52
59
  end
53
60
 
54
61
  # does not allow %Spellout and %Ordinal in the ordinal expression
@@ -112,7 +112,7 @@ module IsoDoc
112
112
 
113
113
  def table_css(elem)
114
114
  parser = IsoDoc::CssBorderParser::BorderParser.new
115
- elem.xpath(ns(".//tr | .//th | .//td")).each do |n|
115
+ elem.xpath(ns(".//tr | .//th | .//td | .//table")).each do |n|
116
116
  n["style"] or next
117
117
  parsed_properties = parser.parse_declaration(n["style"])
118
118
  new_style = parser.to_css_string(parsed_properties)
@@ -0,0 +1,23 @@
1
+ module IsoDoc
2
+ class PresentationXMLConvert < ::IsoDoc::Convert
3
+ def cleanup(docxml)
4
+ docxml["type"] = "presentation"
5
+ empty_elements_remove(docxml)
6
+ end
7
+
8
+ # allow fmt-link to be empty
9
+ def empty_elements_remove(docxml)
10
+ %w(fmt-name fmt-xref-label fmt-source fmt-xref fmt-eref fmt-origin
11
+ fmt-concept fmt-related fmt-preferred fmt-deprecates
12
+ fmt-admitted fmt-termsource fmt-definition fmt-footnote-container
13
+ fmt-fn-body fmt-fn-label fmt-annotation-body fmt-provision
14
+ fmt-identifier fmt-date).each do |e|
15
+ docxml.xpath(ns("//#{e}")).each do |n|
16
+ n.text.strip.empty? or next
17
+ n.elements.empty? or next
18
+ n.remove
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -193,8 +193,7 @@ module IsoDoc
193
193
  out = desgn.parent.at(ns("./fmt-#{desgn.name}"))
194
194
  d1 = semx_fmt_dup(desgn)
195
195
  s = d1.at(ns("./source"))
196
- s0 = desgn.at(ns("./source"))
197
- modification_dup_align(s0, s)
196
+ modification_dup_align(desgn.at(ns("./source")), s)
198
197
  name = d1.at(ns("./expression/name | ./letter-symbol/name | " \
199
198
  "./graphical-symbol")) or return
200
199
  designation_annotate(d1, name, desgn)
@@ -227,9 +226,8 @@ module IsoDoc
227
226
 
228
227
  def designation_grammar(desgn, name)
229
228
  g = desgn.at(ns("./expression/grammar")) or return
230
- ret = []
231
- g.xpath(ns("./gender | ./number")).each do |x|
232
- ret << @i18n.grammar_abbrevs[x.text]
229
+ ret = g.xpath(ns("./gender | ./number")).each_with_object([]) do |x, m|
230
+ m << @i18n.grammar_abbrevs[x.text]
233
231
  end
234
232
  %w(isPreposition isParticiple isAdjective isVerb isAdverb isNoun)
235
233
  .each do |x|
@@ -252,9 +250,7 @@ module IsoDoc
252
250
  end
253
251
 
254
252
  def designation_bookmarks(desgn, name)
255
- desgn.xpath(ns(".//bookmark")).each do |b|
256
- name << b.remove
257
- end
253
+ desgn.xpath(ns(".//bookmark")).each { |b| name << b.remove }
258
254
  end
259
255
  end
260
256
  end
@@ -139,14 +139,22 @@ module IsoDoc
139
139
  end
140
140
 
141
141
  def comments(docxml)
142
- docxml.xpath(ns("//review")).each do |c|
142
+ global_display = display_comments_global?(docxml)
143
+ docxml.xpath(ns("//annotation")).each do |c|
144
+ global_display || display_comment_override?(c) or next
143
145
  c1 = comment_body(c)
144
146
  comment_bookmarks(c1)
145
147
  end
146
148
  end
147
149
 
150
+ # if false, then decision on displaying comment is only dependent on
151
+ # display_comments_global? . display_comment_override? overrides that
152
+ def display_comment_override?(_comment)
153
+ false
154
+ end
155
+
148
156
  def comment_body(elem)
149
- c1 = elem.after("<fmt-review-body/>").next
157
+ c1 = elem.after("<fmt-annotation-body/>").next
150
158
  elem.attributes.each_key { |k| k == "id" or c1[k] = elem[k] }
151
159
  add_id(c1)
152
160
  c1 << semx_fmt_dup(elem)
@@ -162,7 +170,7 @@ module IsoDoc
162
170
 
163
171
  # Do not insert a comment bookmark inside another comment bookmark
164
172
  AVOID_COMMENT_BOOKMARKS = <<~XPATH.freeze
165
- [not(ancestor::xmlns:fmt-review-start)][not(ancestor::xmlns:fmt-review-end)]
173
+ [not(ancestor::xmlns:fmt-annotation-start)][not(ancestor::xmlns:fmt-annotation-end)]
166
174
  XPATH
167
175
 
168
176
  def comment_bookmarks_locate(elem)
@@ -181,7 +189,7 @@ module IsoDoc
181
189
  end
182
190
 
183
191
  def comment_bookmark_start(from, elem)
184
- ret = from.before("<fmt-review-start/>").previous
192
+ ret = from.before("<fmt-annotation-start/>").previous
185
193
  add_id(ret)
186
194
  ret["source"] = elem["from"]
187
195
  comment_to_bookmark_attrs(elem, ret, start: true)
@@ -190,7 +198,7 @@ module IsoDoc
190
198
  end
191
199
 
192
200
  def comment_bookmark_end(to, elem)
193
- ret = to.after("<fmt-review-end/>").next
201
+ ret = to.after("<fmt-annotation-end/>").next
194
202
  add_id(ret)
195
203
  ret["source"] = elem["to"]
196
204
  comment_to_bookmark_attrs(elem, ret, start: false)
@@ -205,5 +213,11 @@ module IsoDoc
205
213
  def comment_bookmark_end_label(_elem)
206
214
  ""
207
215
  end
216
+
217
+ def display_comments_global?(docxml)
218
+ m = docxml.at(ns("//presentation-metadata/render-document-annotations"))
219
+ m&.text and return m.text != "false"
220
+ @meta.get[:unpublished]
221
+ end
208
222
  end
209
223
  end
@@ -100,7 +100,7 @@ module IsoDoc
100
100
 
101
101
  def add_missing_id(docxml)
102
102
  docxml.xpath(ns("//source | //modification | //erefstack | //fn | " \
103
- "//review | //floating-title | //li | //executivesummary | " \
103
+ "//annotation | //floating-title | //li | //executivesummary | " \
104
104
  "//preface/abstract | //foreword | //introduction | //annex | " \
105
105
  "//acknowledgements | //clause | //references | //terms | " \
106
106
  "//preferred | //deprecates | //admitted | //related")).each do |s|
@@ -219,7 +219,7 @@ module IsoDoc
219
219
  end
220
220
 
221
221
  def ruby1(elem)
222
- v = elem.at(ns("./pronunciation | ./annotation")).remove
222
+ v = elem.at(ns("./ruby-pronunciation | ./ruby-annotation")).remove
223
223
  elem.xpath(ns("./ruby")).each do |r|
224
224
  ruby1(r)
225
225
  end
@@ -1,14 +1,41 @@
1
1
  module IsoDoc
2
2
  class PresentationXMLConvert < ::IsoDoc::Convert
3
3
  def metadata(docxml)
4
+ preprocess_metadata(docxml)
4
5
  toc_metadata(docxml)
5
6
  fonts_metadata(docxml)
6
7
  attachments_extract(docxml)
7
- localized_strings(docxml)
8
8
  a = docxml.at(ns("//metanorma-extension")) or return
9
9
  a.elements.empty? and a.remove
10
10
  end
11
11
 
12
+ def preprocess_metadata(docxml)
13
+ localized_strings(docxml)
14
+ logo_expand_pres_metadata(docxml)
15
+ end
16
+
17
+ # logo-{role}-{format}-{height/width}-{number}
18
+ def logo_expand_pres_metadata(docxml)
19
+ docxml.xpath(ns("//metanorma-extension/presentation-metadata/*"))
20
+ .each do |x|
21
+ logo_size_pres_metadata_incomplete?(x) or next
22
+ parts = x.name.split("-")
23
+ @output_formats.each_key do |f|
24
+ tagname = "logo-#{parts[1]}-#{f}-#{parts[2..].join('-')}"
25
+ x.parent.next = <<~XML
26
+ <presentation-metadata><#{tagname}>#{x.text}</#{tagname}></presentation-metadata>
27
+ XML
28
+ end
29
+ end
30
+ end
31
+
32
+ def logo_size_pres_metadata_incomplete?(elem)
33
+ parts = elem.name.split("-")
34
+ elem.name.start_with?("logo-") &&
35
+ %w(author editor publisher authorizer distrbutor).include?(parts[1]) &&
36
+ %w(height width).include?(parts[2])
37
+ end
38
+
12
39
  def localized_strings(docxml)
13
40
  a = docxml.at(ns("//bibdata")) or return
14
41
  a.next =
@@ -68,9 +68,9 @@ module IsoDoc
68
68
  end
69
69
 
70
70
  def annotations(elem, fmt_elem)
71
- elem.at(ns("./annotation")) or return
71
+ elem.at(ns("./callout-annotation")) or return
72
72
  ret = ""
73
- elem.xpath(ns("./annotation")).each do |a|
73
+ elem.xpath(ns("./callout-annotation")).each do |a|
74
74
  id = a["original-id"]
75
75
  dd = semx_fmt_dup(a)
76
76
  dd["source"] = a["id"]
@@ -79,7 +79,7 @@ module IsoDoc
79
79
  <dd>#{to_xml dd}</dd>
80
80
  OUT
81
81
  end
82
- fmt_elem.xpath(ns("./annotation")).each(&:remove)
82
+ fmt_elem.xpath(ns("./callout-annotation")).each(&:remove)
83
83
  fmt_elem << "<dl><name>#{@i18n.key}</name>#{ret}</dl>"
84
84
  end
85
85
 
@@ -104,7 +104,7 @@ module IsoDoc
104
104
  end
105
105
 
106
106
  def source_remove_annotations(ret, elem)
107
- ret[:ann] = elem.xpath(ns("./annotation")).each(&:remove)
107
+ ret[:ann] = elem.xpath(ns("./callout-annotation")).each(&:remove)
108
108
  ret[:call] = elem.xpath(ns("./callout")).each_with_object([]) do |c, m|
109
109
  m << { xml: c.remove, line: c.line - elem.line }
110
110
  end
@@ -13,6 +13,7 @@ require_relative "presentation_function/bibdata"
13
13
  require_relative "presentation_function/metadata"
14
14
  require_relative "presentation_function/footnotes"
15
15
  require_relative "presentation_function/ids"
16
+ require_relative "presentation_function/cleanup"
16
17
 
17
18
  module IsoDoc
18
19
  class PresentationXMLConvert < ::IsoDoc::Convert
@@ -25,8 +26,8 @@ module IsoDoc
25
26
  def convert1(docxml, filename, dir)
26
27
  presxml_convert_init(docxml, filename, dir)
27
28
  conversions(docxml)
28
- docxml.root["type"] = "presentation"
29
- id_validate(docxml.root)
29
+ cleanup(docxml.root)
30
+ validate(docxml.root)
30
31
  docxml.to_xml.gsub("&lt;", "&#x3c;").gsub("&gt;", "&#x3e;")
31
32
  end
32
33
 
@@ -41,10 +42,13 @@ module IsoDoc
41
42
  provide_ids docxml # feeds @xrefs.parse
42
43
  @xrefs.parse docxml
43
44
  @xrefs.klass.meta = @meta
44
- @xrefs.klass.info docxml, nil
45
45
  counter_init
46
46
  end
47
47
 
48
+ def validate(docxml)
49
+ id_validate(docxml)
50
+ end
51
+
48
52
  def bibitem_lookup(docxml)
49
53
  @bibitem_lookup ||= docxml.xpath(ns("//references/bibitem"))
50
54
  .each_with_object({}) do |b, m|
@@ -1,3 +1,3 @@
1
1
  module IsoDoc
2
- VERSION = "3.1.11".freeze
2
+ VERSION = "3.2.0".freeze
3
3
  end
@@ -2,7 +2,7 @@ module IsoDoc
2
2
  module WordFunction
3
3
  module Comments
4
4
  def comments(docxml, out)
5
- c = docxml.xpath(ns("//fmt-review-body"))
5
+ c = docxml.xpath(ns("//fmt-annotation-body"))
6
6
  c.empty? and return
7
7
  out.div style: "mso-element:comment-list" do |div|
8
8
  @in_comment = true
@@ -17,7 +17,7 @@ module IsoDoc
17
17
  to: node["end"] }
18
18
  end
19
19
 
20
- def fmt_review_start_parse(node, out)
20
+ def fmt_annotation_start_parse(node, out)
21
21
  make_comment_link(out, node["target"], node)
22
22
  end
23
23
 
@@ -42,7 +42,7 @@ module IsoDoc
42
42
  end
43
43
  end
44
44
 
45
- def fmt_review_body_parse(node, out)
45
+ def fmt_annotation_body_parse(node, out)
46
46
  out.div style: "mso-element:comment", id: node["id"] do |div|
47
47
  div.span style: %{mso-comment-author:"#{node['reviewer']}"}
48
48
  make_comment_target(div)
@@ -61,10 +61,15 @@ module IsoDoc
61
61
  ddef.children[1..].each { |n| parse(n, out) }
62
62
  end
63
63
 
64
+ def dl_table_attrs(node)
65
+ { id: node["id"],
66
+ align: node["class"] == "formula_dl" ? "left" : nil,
67
+ class: node["class"] || "dl" }
68
+ end
69
+
64
70
  def dl_parse_table(node, out)
65
71
  list_title_parse(node, out)
66
- out.table **attr_code(id: node["id"],
67
- class: node["class"] || "dl") do |v|
72
+ out.table **attr_code(dl_table_attrs(node)) do |v|
68
73
  node.elements.select { |n| dt_dd?(n) }
69
74
  .each_slice(2) do |dt, dd|
70
75
  dl_parse_table1(v, dt, dd)
@@ -49,6 +49,7 @@ module IsoDoc
49
49
  word_preface(docxml)
50
50
  word_sourcecode_annotations(docxml)
51
51
  word_sourcecode_table(docxml)
52
+ word_nonbreaking_spans(docxml)
52
53
  word_nested_tables(docxml)
53
54
  word_colgroup(docxml)
54
55
  word_table_align(docxml)
@@ -185,6 +186,17 @@ module IsoDoc
185
186
  out[-1].previous = b.remove
186
187
  end
187
188
  end
189
+
190
+ def word_nonbreaking_spans(docxml)
191
+ docxml.xpath("//span[@style = 'white-space: nowrap;']").each do |s|
192
+ s.delete("style")
193
+ s.traverse do |n|
194
+ n.text? or next
195
+ n.replace(n.text.gsub(" ", "\u00a0").gsub("-", "\u2011")
196
+ .gsub(/\.(?=.)/, ".\u2060"))
197
+ end
198
+ end
199
+ end
188
200
  end
189
201
  end
190
202
  end
@@ -39,7 +39,7 @@ module IsoDoc
39
39
  border-top:#{top}mso-border-top-alt:#{top}
40
40
  border-bottom:#{bottom}mso-border-bottom-alt:#{bottom}
41
41
  STYLE
42
- opt[:bordered] or ret = ""
42
+ opt[:bordered] && !cell["style"] or ret = ""
43
43
  pb = keep_rows_together(cell, rowmax, totalrows, opt) ? "avoid" : "auto"
44
44
  "#{ret}page-break-after:#{pb};"
45
45
  end
@@ -72,15 +72,14 @@ module IsoDoc
72
72
 
73
73
  def table_attrs(node)
74
74
  c = node["class"]
75
- bordered = "border-spacing:0;border-width:1px;"
76
- (%w(modspec).include?(c) || !c) or bordered = nil
77
- ret = {
78
- summary: node["summary"], width: node["width"],
79
- style: "mso-table-anchor-horizontal:column;mso-table-overlap:never;" \
80
- "#{bordered}#{keep_style(node)}",
81
- class: (node.text.length > 4000 ? "MsoISOTableBig" : "MsoISOTable")
82
- }
83
- bordered or ret.delete(:class)
75
+ style = node["style"] ? '' : "border-spacing:0;border-width:1px;"
76
+ (%w(modspec).include?(c) || !c) or style = nil
77
+ ret =
78
+ { summary: node["summary"], width: node["width"],
79
+ style: "mso-table-anchor-horizontal:column;mso-table-overlap:never;" \
80
+ "#{style}#{keep_style(node)}",
81
+ class: (node.text.length > 4000 ? "MsoISOTableBig" : "MsoISOTable") }
82
+ style or ret.delete(:class)
84
83
  super.merge(attr_code(ret))
85
84
  end
86
85
 
@@ -59,7 +59,7 @@ module IsoDoc
59
59
  ret = ret.merge(@pdf_cmd_options)
60
60
  %w(--xsl-file --xsl-file-override).each do |x|
61
61
  ret[x] &&= Pathname.new(File.expand_path(ret[x])).to_s
62
- #.relative_path_from(File.dirname(@xsl)).to_s
62
+ # .relative_path_from(File.dirname(@xsl)).to_s
63
63
  end
64
64
  if ret["--xsl-file"]
65
65
  @xsl = ret["--xsl-file"]
@@ -100,15 +100,15 @@ module IsoDoc
100
100
 
101
101
  def input_xml_path(input_filename, xml_file, debug)
102
102
  docxml, filename, dir = convert_init(xml_file, input_filename, debug)
103
- input_filename = Tempfile.open([File.basename(filename), ".xml"],
104
- mode: File::BINARY | File::SHARE_DELETE,
105
- encoding: "utf-8") do |f|
106
- f.write docxml
107
- f
108
- end
103
+ temp_file = Tempfile.open([File.basename(filename), ".xml"],
104
+ mode: File::BINARY | File::SHARE_DELETE,
105
+ encoding: "utf-8")
106
+ temp_file.write docxml
107
+ temp_file.flush
108
+ @tempfile_cache << temp_file # Add to cache to prevent garbage collection
109
109
  FileUtils.rm_rf dir
110
110
 
111
- [input_filename, docxml, input_filename.path]
111
+ [temp_file, docxml, temp_file.path]
112
112
  end
113
113
  end
114
114
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: isodoc
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.11
4
+ version: 3.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-06-09 00:00:00.000000000 Z
11
+ date: 2025-07-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: base64
@@ -44,14 +44,14 @@ dependencies:
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: 1.9.0
47
+ version: 1.10.0
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: 1.9.0
54
+ version: 1.10.0
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: mn2pdf
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -438,6 +438,7 @@ files:
438
438
  - lib/isodoc/presentation_function/autonum.rb
439
439
  - lib/isodoc/presentation_function/bibdata.rb
440
440
  - lib/isodoc/presentation_function/block.rb
441
+ - lib/isodoc/presentation_function/cleanup.rb
441
442
  - lib/isodoc/presentation_function/concepts.rb
442
443
  - lib/isodoc/presentation_function/docid.rb
443
444
  - lib/isodoc/presentation_function/erefs.rb