isodoc 3.6.11 → 3.7.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: 82d4992cdf6cebe7c3abf1b624847dc08586213fa57c7ce01e98d86d721cafbf
4
- data.tar.gz: 0025b823e97539b471833bef1de6424d56d6b569343b6fd414de20b575f46e11
3
+ metadata.gz: 1704124a224846f711e07140b38b352fe8d9548465654168467b0d892c29867d
4
+ data.tar.gz: eedf867e52f1ff13d2c7166a4bd9361ac432da5afc688c4d7bfa50f0f91bada5
5
5
  SHA512:
6
- metadata.gz: 1da939aa2ae8858bd2731a1fdbe0ddaf77cdc7d170655502d4b110ecb1e149ce5e6e9dc8c2cbed77389f2cc8c05977f72e445d8aa28b43276b89080c3a23b8ec
7
- data.tar.gz: c59cfc4210201281df2a282b7822b5aa76371855db0840defb57f2afd50b617127be738d41b10a1c0512267cf4946ba9b0180eff2437b14b63b334b6d4b93c6d
6
+ metadata.gz: 20ce7106f1eb73784cf58ef1ed0bf7bfc7f5bcd6c1a8495f4bec0b19326b70f7228fc2b0886abe4c98df19d2f42cc0456be55c6eba6d90c7806bbbff56bd5cd7
7
+ data.tar.gz: ca9607aceeafd8d263a6cc779f6311d709b1c35c6be218ec6b0dee2193e86eb1cdc1725b0457d79c8967bcb27e6c4df4b062ca972960e96690e309ab7c9e9503
data/isodoc.gemspec CHANGED
@@ -30,9 +30,9 @@ 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.11.0"
33
+ spec.add_dependency "html2doc", "~> 1.12"
34
34
  # spec.add_dependency "isodoc-i18n", "~> 1.1.0" # already in relaton-render and mn-requirements
35
- # spec.add_dependency "relaton-cli"
35
+ spec.add_dependency "relaton-cli", "~> 2.1.0"
36
36
  # spec.add_dependency "metanorma-utils", "~> 1.5.0" # already in isodoc-i18n
37
37
  spec.add_dependency "mn2pdf", ">= 2.13"
38
38
  spec.add_dependency "mn-requirements", "~> 0.5.0"
@@ -143,6 +143,11 @@ a.FootnoteRef, span.FootnoteRef {
143
143
  vertical-align: super;
144
144
  }
145
145
 
146
+ a.TableFootnoteRef, a.FootnoteRef, a.footnote-number,
147
+ sup a, a:has(> sup) {
148
+ vertical-align: baseline;
149
+ }
150
+
146
151
  .addition {
147
152
  color: blue;
148
153
  }
@@ -145,9 +145,21 @@ div.document-stage-band, div.document-type-band {
145
145
  background-color: #333333;
146
146
  }
147
147
 
148
- a.TableFootnoteRef, span.TableFootnoteRef,
148
+ a.TableFootnoteRef, span.TableFootnoteRef,
149
149
  a.FootnoteRef, span.FootnoteRef {
150
- vertical-align: super;
150
+ vertical-align: super;
151
+ }
152
+
153
+ // A footnote-style link superscripts its content through an inner <sup>, but the
154
+ // link's underline rides up with the anchor's own `vertical-align: super`,
155
+ // leaving a raised underline that reads as a stray dash. Keep the *anchor* on
156
+ // the baseline (so the underline stays at the bottom of the line) and let the
157
+ // inner <sup> alone raise the glyph. The anchor classes are named explicitly
158
+ // because the generic `a:has(> sup)` has lower specificity than the rule above;
159
+ // `sup a` covers the inverse nesting. https://github.com/metanorma/iso-10303/issues/717
160
+ a.TableFootnoteRef, a.FootnoteRef, a.footnote-number,
161
+ sup a, a:has(> sup) {
162
+ vertical-align: baseline;
151
163
  }
152
164
 
153
165
  .addition {
@@ -61,10 +61,9 @@ module IsoDoc
61
61
 
62
62
  # HTML5 collapsible example: label in <summary>, body in the example div
63
63
  def example_collapsible_parse(node, out)
64
- out.details(open: "open") do |det|
65
- name = node.at(ns("./fmt-name"))
64
+ out.details(**example_collapsible_parse_attr) do |det|
66
65
  det.summary do |s|
67
- name and children_parse(name, s)
66
+ name = node.at(ns("./fmt-name")) and children_parse(name, s)
68
67
  end
69
68
  det.div(**example_div_attr(node)) do |div|
70
69
  node.children.each do |n|
@@ -74,6 +73,10 @@ module IsoDoc
74
73
  end
75
74
  end
76
75
 
76
+ def example_collapsible_parse_attr
77
+ @details_open ? { open: "open" } : {}
78
+ end
79
+
77
80
  def block_body_first_elem(node)
78
81
  node.elements.each do |n|
79
82
  %w(title fmt-title fmt-xref-label fmt-name name)
@@ -43,6 +43,7 @@ module IsoDoc
43
43
  def info(isoxml, out)
44
44
  @meta.localdir = @localdir
45
45
  @meta.presentation isoxml, out
46
+ @meta.bibdata isoxml, out
46
47
  @meta.code_css isoxml, out
47
48
  @meta.title isoxml, out
48
49
  @meta.subtitle isoxml, out
data/lib/isodoc/init.rb CHANGED
@@ -30,9 +30,11 @@ module IsoDoc
30
30
  .new(language: @lang, script: @script)
31
31
  end
32
32
 
33
- def docxml_var_init(docxml)
34
- doctype_init(docxml)
35
- toc_init(docxml)
33
+ def docxml_var_init(xml)
34
+ doctype_init(xml)
35
+ toc_init(xml)
36
+ @details_open = xml.at(ns("//metanorma-extension/presentation-metadata/" \
37
+ "html-details-open"))&.text != "false"
36
38
  end
37
39
 
38
40
  def doctype_init(docxml)
@@ -1,5 +1,6 @@
1
1
  require_relative "metadata_date"
2
2
  require_relative "metadata_contributor"
3
+ require_relative "metadata_bibdata"
3
4
 
4
5
  module IsoDoc
5
6
  class Metadata
@@ -72,15 +73,29 @@ module IsoDoc
72
73
  set(:substage_display, i1)
73
74
  (i2 = xml.at(ns("//bibdata/status/iteration"))&.text) and
74
75
  set(:iteration, i2)
75
- !published && set(:stageabbr, stage_abbr(s.text))
76
+ # @abbreviation is authoritative (e.g. supplied by a taste through
77
+ # :docstage-abbrev:); read here rather than in stage_abbr, so that
78
+ # flavour stage_abbr overrides do not mask it
79
+ published or
80
+ set(:stageabbr, s["abbreviation"] || stage_abbr(s.text))
76
81
  end
77
82
 
78
83
  def published_default(xml)
79
84
  override = xml.at(ns("//semantic-metadata/stage-published"))&.text
80
- default = override || "true"
81
- ret = default == "false"
82
- set(:unpublished, ret)
83
- default == "true"
85
+ if override.nil?
86
+ stage = xml.at(ns("//bibdata/status/stage#{NOLANG}"))&.text
87
+ override = draft_stage?(stage) ? "false" : "true"
88
+ end
89
+ set(:unpublished, override == "false")
90
+ override == "true"
91
+ end
92
+
93
+ # Is the stage a draft (unpublished) stage? Overridable seam for
94
+ # documents whose XML does not carry semantic-metadata/
95
+ # stage-published (which is authoritative when present). Base
96
+ # default preserves historical behaviour: absent flag => published.
97
+ def draft_stage?(_stage)
98
+ false
84
99
  end
85
100
 
86
101
  def stage_abbr(docstatus)
@@ -0,0 +1,73 @@
1
+ require "relaton-cli"
2
+
3
+ module IsoDoc
4
+ class BibdataConfig < ::Lutaml::Model::Serializable
5
+ class Bibdata < ::Lutaml::Model::Serializable
6
+ model ::Relaton::Bib::ItemData
7
+ end
8
+
9
+ attribute :bibdata, Bibdata
10
+
11
+ xml do
12
+ root "metanorma"
13
+ map_element "bibdata", to: :bibdata, with: { from: :bibdata_from_xml,
14
+ to: :bibdata_to_xml }
15
+ end
16
+
17
+ def bibdata_from_xml(model, node)
18
+ node or return
19
+ model.bibdata = Relaton::Cli.parse_xml(node.adapter_node.native)
20
+ end
21
+
22
+ def bibdata_to_xml(model, parent, doc); end
23
+ end
24
+
25
+ class Metadata
26
+ def bibdata(isoxml, _out)
27
+ set(:bibdata, bibdata_hash(isoxml))
28
+ end
29
+
30
+ private
31
+
32
+ def bibdata_hash(isoxml)
33
+ b = isoxml.at("//bibdata") || isoxml.at("//xmlns:bibdata") or return
34
+ key = b.to_xml
35
+ # memoised by content, not unconditionally: after
36
+ # docidentifier_boilerplate_isodoc resolves Liquid docidentifiers,
37
+ # refresh_isodoc_bibdata re-runs this walker on the same Metadata
38
+ # instance and must re-parse the changed bibdata
39
+ @bibdata_hash_cache ||= {}
40
+ @bibdata_hash_cache.key?(key) or
41
+ @bibdata_hash_cache[key] = bibdata_hash_parse(key)
42
+ @bibdata_hash_cache[key]
43
+ end
44
+
45
+ def bibdata_hash_parse(bibdata_xml)
46
+ stripped = Nokogiri::XML(bibdata_xml)
47
+ stripped.remove_namespaces!
48
+ # Drop @boilerplate="true" docidentifiers before handing the
49
+ # bibdata to Relaton::Cli.parse_xml: their content is an
50
+ # unresolved Liquid template, and recent relaton-iho /
51
+ # relaton-cc / etc. eagerly call pubid in their docidentifier
52
+ # content= setter, which crashes on raw Liquid syntax. The
53
+ # template variables for substitution come from other bibdata
54
+ # fields (seriesabbr, docnumeric, …), not from the
55
+ # docidentifier itself, so dropping it here does not affect
56
+ # what we feed back into isodoc.meta. Substitution still runs
57
+ # on the original xmldoc via standoc's
58
+ # docidentifier_boilerplate_isodoc; afterwards
59
+ # refresh_isodoc_bibdata re-runs this walker to seed
60
+ # meta[:bibdata] with the resolved docidentifier.
61
+ # See https://github.com/metanorma/metanorma/issues/558.
62
+ stripped.xpath("//docidentifier[@boilerplate = 'true']").each(&:remove)
63
+ bib = BibdataConfig.from_xml(
64
+ "<metanorma>#{stripped.root.to_xml}</metanorma>",
65
+ ).bibdata or return nil
66
+ YAML.safe_load(bib.to_yaml, permitted_classes: [Date, Symbol],
67
+ symbolize_names: true)
68
+ rescue StandardError => e
69
+ warn "Failed to parse bibdata for Liquid template use: #{e.message}"
70
+ nil
71
+ end
72
+ end
73
+ end
@@ -101,9 +101,18 @@ module IsoDoc
101
101
  labelled_autonum(lbl, elem["id"] || elem["original-id"], num)
102
102
  end
103
103
 
104
+ # The presentation-metadata element is named from the document
105
+ # attribute :presentation-metadata-admonition-icon-{type}:, whose name
106
+ # cannot contain spaces; so spaced admonition types ("safety
107
+ # precautions") address it with spaces replaced by underscores --
108
+ # underscore, not hyphen, to avoid collision with genuinely hyphenated
109
+ # type names. Interpolating the raw type made the XPath invalid and
110
+ # fatal (#760). The i18n lookup keeps the raw type: i18n keys may
111
+ # legitimately contain spaces.
104
112
  def admonition_icon(elem)
113
+ type = elem["type"]&.tr(" ", "_")
105
114
  icon = elem.document
106
- .at(ns("//presentation-metadata/admonition-icon-#{elem['type']}"))&.text
115
+ .at(ns("//presentation-metadata/admonition-icon-#{type}"))&.text
107
116
  icon ||= @i18n.labels.dig("admonition-icon", elem["type"])
108
117
  icon and return "<span class='fmt-admonition-icon'>#{icon}</span>"
109
118
  end
@@ -41,9 +41,14 @@ module IsoDoc
41
41
  ins = body.at(ns(".//p")) ||
42
42
  body.at(ns("./semx")).children.first.before("<p> </p>").previous
43
43
  lbl = fn_body_label(fnote)
44
- ins.children.first.previous = <<~FNOTE.strip
44
+ fnote = <<~FNOTE.strip
45
45
  <fmt-fn-label><span class='fmt-caption-label'>#{lbl}</span><span class="fmt-caption-delim"><tab/></fmt-fn-label>
46
46
  FNOTE
47
+ if ins.children.first
48
+ ins.children.first.previous = fnote
49
+ else
50
+ ins << fnote
51
+ end
47
52
  end
48
53
 
49
54
  def fn_ref_label(fnote)
@@ -9,7 +9,7 @@ module IsoDoc
9
9
  i = xml.at(ns("//indexsect")) ||
10
10
  xml.root.add_child(
11
11
  "<indexsect #{add_id_text}>" \
12
- "<fmt-title #{add_id_text}>#{@i18n.index}</fmt-title></indexsect>",
12
+ "<fmt-title #{add_id_text}>#{@i18n.index}</fmt-title></indexsect>",
13
13
  ).first
14
14
  index = sort_indexterms(xml.xpath(ns("//index")),
15
15
  xml.xpath(ns("//index-xref[@also = 'false']")),
@@ -59,7 +59,8 @@ module IsoDoc
59
59
  hex_capital).freeze
60
60
  NUMBERFORMAT_NULLABLE = %i(base_prefix base_suffix).freeze
61
61
  # plurimath options metanorma deliberately passes through unchanged (string)
62
- NUMBERFORMAT_PASSTHROUGH = %i(fraction_group decimal group times e).freeze
62
+ NUMBERFORMAT_PASSTHROUGH = %i(fraction_group decimal group times e
63
+ padding).freeze
63
64
  NUMBERFORMAT_KNOWN = (NUMBERFORMAT_INTEGER + NUMBERFORMAT_SYMBOL +
64
65
  NUMBERFORMAT_NULLABLE + NUMBERFORMAT_PASSTHROUGH).freeze
65
66
 
@@ -18,14 +18,14 @@ module IsoDoc
18
18
  def logo_expand_pres_metadata(docxml)
19
19
  docxml.xpath(ns("//metanorma-extension/presentation-metadata/*"))
20
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
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
29
  end
30
30
  end
31
31
 
@@ -71,7 +71,7 @@ module IsoDoc
71
71
  def save_attachment(attachment, dir)
72
72
  n = File.join(dir, File.basename(attachment["name"]))
73
73
  c = attachment.text.sub(%r{^data:[^;]+;(?:charset=[^;]+;)?base64,}, "")
74
- File.open(n, "wb") { |f| f.write(Base64.decode64(c)) }
74
+ File.binwrite(n, Base64.decode64(c))
75
75
  end
76
76
 
77
77
  def extension_insert(xml, path = [])
@@ -94,14 +94,14 @@ module IsoDoc
94
94
 
95
95
  def toc_metadata(docxml)
96
96
  @tocfigures || @toctables || @tocrecommendations || @tocexamples or return
97
- ins = extension_insert(docxml)
97
+ ins = presmeta_insert_pt(docxml)
98
98
  @tocfigures and
99
99
  ins.add_child "<toc type='figure'><title>#{@i18n.toc_figures}</title></toc>"
100
100
  @toctables and
101
101
  ins << "<toc type='table'><title>#{@i18n.toc_tables}</title></toc>"
102
102
  @tocrecommendations and
103
103
  ins << "<toc type='recommendation'><title>#{@i18n.toc_recommendations}" \
104
- "</title></toc>"
104
+ "</title></toc>"
105
105
  @tocexamples and
106
106
  ins << "<toc type='example'><title>#{@i18n.toc_examples}</title></toc>"
107
107
  end
@@ -158,7 +158,7 @@ module IsoDoc
158
158
  i18n_name(v1, "#{i18n_safe(k)}.#{i}", lang).each { |x| g << x }
159
159
  end
160
160
  else
161
- g << i18n_tag("#{pref}#{pref.empty? ? '' : '.'}#{i18n_safe(k)}", v,
161
+ g << i18n_tag("#{pref}#{'.' unless pref.empty?}#{i18n_safe(k)}", v,
162
162
  lang)
163
163
  end
164
164
  end
@@ -1,3 +1,3 @@
1
1
  module IsoDoc
2
- VERSION = "3.6.11".freeze
2
+ VERSION = "3.7.0".freeze
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: isodoc
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.6.11
4
+ version: 3.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
@@ -43,14 +43,28 @@ dependencies:
43
43
  requirements:
44
44
  - - "~>"
45
45
  - !ruby/object:Gem::Version
46
- version: 1.11.0
46
+ version: '1.12'
47
47
  type: :runtime
48
48
  prerelease: false
49
49
  version_requirements: !ruby/object:Gem::Requirement
50
50
  requirements:
51
51
  - - "~>"
52
52
  - !ruby/object:Gem::Version
53
- version: 1.11.0
53
+ version: '1.12'
54
+ - !ruby/object:Gem::Dependency
55
+ name: relaton-cli
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: 2.1.0
61
+ type: :runtime
62
+ prerelease: false
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: 2.1.0
54
68
  - !ruby/object:Gem::Dependency
55
69
  name: mn2pdf
56
70
  requirement: !ruby/object:Gem::Requirement
@@ -175,7 +189,6 @@ extensions: []
175
189
  extra_rdoc_files: []
176
190
  files:
177
191
  - ".gitignore"
178
- - ".hound.yml"
179
192
  - ".oss-guides.rubocop.yml"
180
193
  - ".rubocop.yml"
181
194
  - CODE_OF_CONDUCT.md
@@ -252,6 +265,7 @@ files:
252
265
  - lib/isodoc/i18n.rb
253
266
  - lib/isodoc/init.rb
254
267
  - lib/isodoc/metadata.rb
268
+ - lib/isodoc/metadata_bibdata.rb
255
269
  - lib/isodoc/metadata_contributor.rb
256
270
  - lib/isodoc/metadata_date.rb
257
271
  - lib/isodoc/pdf_convert.rb
data/.hound.yml DELETED
@@ -1,5 +0,0 @@
1
- # Auto-generated by Cimas: Do not edit it manually!
2
- # See https://github.com/metanorma/cimas
3
- ruby:
4
- enabled: true
5
- config_file: .rubocop.yml