isodoc 3.6.6 → 3.6.7

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: 7afaca0661a1ca0321fb479d3f1d1db9b2687bf63d668c69778cb13ac8caaec9
4
- data.tar.gz: 822fe85bb3ffd7966aac0ff7f6bbbc5cc8e79759664f81c1df804767e2b1ce86
3
+ metadata.gz: eb5eaaa62e081fd25bff232ebc2a38ef74f3d73c4207da35cde420169fbfe0b1
4
+ data.tar.gz: baa0b652f47d32440c93e1f0f823ef2ef734ec78bd351f3112d3e2fc14906c2c
5
5
  SHA512:
6
- metadata.gz: 4840fd50ec5c71c4bf7202bc9ffcc87bdd1f756ae2c58212b627f78633e87333c935926f921b0c276a83fd4c1ab279ed9d3a3b3b34605ac215261506f59dc600
7
- data.tar.gz: 9afda013dcdfb71c8ee962cfe787b2b24e997613b2b1fd644e0e751cf521290aad51ec1c0859254c0c27ba087abe2839ad9419b846c33ae287f5784bb4e6b319
6
+ metadata.gz: 711a67de087b11beb0fc089d21e9fe62694fbe5e0d8d1bbd6a37a7fb2b0546c7ba43a95da22cb5073ee4263bee4127e57b5455d7cf3c40c7a020f4a490936947
7
+ data.tar.gz: 64d9a08ecd6e2355a738702b843d8873fcf66e191f359b1ef84eac09c57e9f136535f3edc685a96289339c021c743349d6550e9eac92d3417cb42d18d99851a4
data/.rubocop.yml CHANGED
@@ -3,8 +3,20 @@
3
3
  inherit_from:
4
4
  - https://raw.githubusercontent.com/riboseinc/oss-guides/main/ci/rubocop.yml
5
5
 
6
+ # Rubocop plugins enabled centrally so every metanorma-org gem picks them up
7
+ # on cimas sync — best practice belongs at the shared-template layer, not
8
+ # per-repo. Per ronaldtse feedback on metanorma/ci#332.
9
+ plugins:
10
+ - rubocop-rspec
11
+ - rubocop-performance
12
+ - rubocop-rake
13
+
6
14
  # local repo-specific modifications
7
15
  # ...
8
16
 
9
17
  AllCops:
10
- TargetRubyVersion: 3.4
18
+ # 3.3 matches the org-wide minimum being pushed via #274 (Raise minimum
19
+ # Ruby version to 3.3 due to EOL of 3.2 on 2026-03-31). Was 3.4 before
20
+ # this commit — 3.4 was above the org's stated minimum and would have
21
+ # applied Rubocop rules that fail-close on gems still targeting 3.3.
22
+ TargetRubyVersion: 3.3
data/isodoc.gemspec CHANGED
@@ -26,7 +26,7 @@ Gem::Specification.new do |spec|
26
26
  f.match(%r{^(test|spec|features|bin|.github)/}) \
27
27
  || f.match(%r{Rakefile|bin/rspec})
28
28
  end
29
- spec.required_ruby_version = Gem::Requirement.new(">= 3.1.0")
29
+ spec.required_ruby_version = Gem::Requirement.new(">= 3.3.0")
30
30
 
31
31
  spec.add_dependency "base64"
32
32
  spec.add_dependency "bigdecimal"
@@ -11,11 +11,16 @@ module IsoDoc
11
11
  end
12
12
 
13
13
  def figure_attrs(node)
14
- attr_code(id: node["id"], class: "figure", style: keep_style(node))
14
+ attr_code(id: node["id"], class: merge_html_class("figure", node),
15
+ style: keep_style(node))
15
16
  end
16
17
 
17
18
  def figure_parse(node, out)
18
- node["class"] == "pseudocode" || node["type"] == "pseudocode" and
19
+ # metanorma/metanorma-standoc#1197: "pseudocode" may be one of several
20
+ # space-separated classes; dispatch on its presence, not equality, so a
21
+ # custom class alongside it is preserved.
22
+ node["class"]&.split&.include?("pseudocode") ||
23
+ node["type"] == "pseudocode" and
19
24
  return pseudocode_parse(node, out)
20
25
  @in_figure = true
21
26
  figure_parse1(node, out)
@@ -32,7 +37,10 @@ module IsoDoc
32
37
  end
33
38
 
34
39
  def pseudocode_attrs(node)
35
- attr_code(id: node["id"], class: "pseudocode", style: keep_style(node))
40
+ classes = node["class"]&.split || []
41
+ classes.include?("pseudocode") or classes.unshift("pseudocode")
42
+ attr_code(id: node["id"], class: classes.join(" "),
43
+ style: keep_style(node))
36
44
  end
37
45
 
38
46
  def pseudocode_tag
@@ -58,7 +66,8 @@ module IsoDoc
58
66
  end
59
67
 
60
68
  def sourcecode_attrs(node)
61
- attr_code(id: node["id"], class: "Sourcecode", style: keep_style(node))
69
+ attr_code(id: node["id"], class: merge_html_class("Sourcecode", node),
70
+ style: keep_style(node))
62
71
  end
63
72
 
64
73
  def sourcecode_parse(node, out)
@@ -151,8 +160,7 @@ module IsoDoc
151
160
  classtype = "MsoCommentText" if in_comment
152
161
  node["type"] == "floating-title" and
153
162
  classtype = "h#{node['depth'] || '1'}"
154
- classtype ||= node["class"]
155
- classtype
163
+ merge_html_class(classtype, node)
156
164
  end
157
165
 
158
166
  def para_attrs(node)
@@ -187,7 +195,7 @@ module IsoDoc
187
195
  end
188
196
 
189
197
  def quote_attrs(node)
190
- ret = para_attrs(node).merge(class: "Quote")
198
+ ret = para_attrs(node).merge(class: merge_html_class("Quote", node))
191
199
  node["type"] == "newcontent" and
192
200
  ret[:class] += " AmendNewcontent"
193
201
  ret
@@ -13,7 +13,8 @@ module IsoDoc
13
13
  margin-left:0pt;vertical-align:top;" }.freeze
14
14
 
15
15
  def example_div_attr(node)
16
- attr_code(id: node["id"], class: "example", style: keep_style(node))
16
+ attr_code(id: node["id"], class: merge_html_class("example", node),
17
+ style: keep_style(node))
17
18
  end
18
19
 
19
20
  # used if we are boxing examples
@@ -130,6 +131,7 @@ module IsoDoc
130
131
  def note_attrs(node)
131
132
  classes = node["type"]&.split(",") || []
132
133
  classes << "Note"
134
+ node["class"] and classes << node["class"]
133
135
  attr_code(id: node["id"], class: classes.join(" "),
134
136
  style: keep_style(node), coverpage: node["coverpage"])
135
137
  end
@@ -154,7 +156,11 @@ module IsoDoc
154
156
  end
155
157
 
156
158
  def admonition_class(node)
157
- "Admonition #{admonition_subclass(node)}".strip
159
+ # metanorma/metanorma-standoc#1197: admonition @class is unused by the
160
+ # type-driven labelling/numbering, so it is repurposed for additive
161
+ # custom HTML classes appended after the built-in Admonition classes.
162
+ ["Admonition", admonition_subclass(node), node["class"]]
163
+ .compact.join(" ").strip
158
164
  end
159
165
 
160
166
  def admonition_subclass(node)
@@ -9,7 +9,7 @@ module IsoDoc
9
9
  end
10
10
 
11
11
  def ul_attrs(node)
12
- { id: node["id"], style: keep_style(node) }
12
+ { id: node["id"], class: node["class"], style: keep_style(node) }
13
13
  end
14
14
 
15
15
  def ul_parse(node, out)
@@ -46,7 +46,7 @@ module IsoDoc
46
46
  { # type: node["type"] ? ol_style(node["type"].to_sym) : ol_depth(node),
47
47
  type: ol_style(node["type"]&.to_sym),
48
48
  start: node["start"],
49
- id: node["id"], style: keep_style(node)
49
+ id: node["id"], class: node["class"], style: keep_style(node)
50
50
  }
51
51
  end
52
52
 
@@ -46,21 +46,37 @@ module IsoDoc
46
46
  end
47
47
  end
48
48
 
49
- def bordered_table_style(node, klass)
50
- bordered = "border-width:1px;border-spacing:0;"
51
- (node["plain"] != "true" && (%w(modspec).include?(klass) || !klass)) or
52
- bordered = ""
53
- bordered
49
+ # Bordering is governed by %plain only, NOT by the presence of a custom
50
+ # @class (metanorma/metanorma-pdfa#33). A non-plain table -- including one
51
+ # carrying a custom class, or the internal modspec variant -- keeps the
52
+ # ISO borders. The internal `rouge-line-table` (sourcecode line numbering)
53
+ # is the exception: like %plain it is mutually exclusive with MsoISOTable
54
+ # and takes no ISO border additions.
55
+ def bordered_table_style(node, klass = nil)
56
+ node["plain"] == "true" and return ""
57
+ klass == "rouge-line-table" and return ""
58
+ "border-width:1px;border-spacing:0;"
54
59
  end
55
60
 
56
61
  def table_attrs(node)
57
62
  c = node["class"]
58
63
  style = table_attrs_style(node, c)
59
64
  attr_code(id: node["id"],
60
- class: node["plain"] == "true" ? "plain" : (c || "MsoISOTable"),
65
+ class: table_html_class(node, c),
61
66
  style: style, title: node["alt"])
62
67
  end
63
68
 
69
+ # metanorma/metanorma-pdfa#33: a custom @class is ADDITIVE -- it augments
70
+ # the computed base class (MsoISOTable, or "plain" under %plain) rather
71
+ # than replacing it, and is orthogonal to bordering. `modspec` and the
72
+ # sourcecode line-numbering `rouge-line-table` stay grandfathered internal
73
+ # values with replace semantics (mutually exclusive with MsoISOTable).
74
+ def table_html_class(node, custom)
75
+ node["plain"] == "true" and return ["plain", custom].compact.join(" ")
76
+ %w(modspec rouge-line-table).include?(custom) and return custom
77
+ ["MsoISOTable", custom].compact.join(" ")
78
+ end
79
+
64
80
  def table_attrs_style(node, klass)
65
81
  width = node["width"] ? "width:#{node['width']};" : nil
66
82
  bordered = bordered_table_style(node, klass)
@@ -146,10 +162,14 @@ module IsoDoc
146
162
  STYLE
147
163
  end
148
164
 
165
+ # Cell bordering follows %plain only, not the custom @class, with
166
+ # `rouge-line-table` excluded like %plain (see bordered_table_style).
167
+ # metanorma/metanorma-pdfa#33
149
168
  def table_bordered?(node)
150
- node.parent.parent["plain"] == "true" and return false
151
- c = node.parent.parent["class"]
152
- %w(modspec).include?(c) || !c
169
+ table = node.parent.parent
170
+ table["plain"] == "true" and return false
171
+ table["class"] == "rouge-line-table" and return false
172
+ true
153
173
  end
154
174
 
155
175
  def tr_parse(node, out, ord, totalrows, header)
@@ -38,6 +38,17 @@ module IsoDoc
38
38
  end
39
39
  end
40
40
 
41
+ # metanorma/metanorma-standoc#1197: render an author's custom @class
42
+ # additively, augmenting a block's built-in HTML class rather than
43
+ # replacing it. `base` is the block's hardcoded class ("figure",
44
+ # "Sourcecode", ...) or nil for blocks with no built-in class; the author
45
+ # class (if any) is appended. Returns nil when the result is empty, so a
46
+ # class-less block does not gain an empty class attribute.
47
+ def merge_html_class(base, node)
48
+ ret = [base, node["class"]].compact.join(" ")
49
+ ret.empty? ? nil : ret
50
+ end
51
+
41
52
  DOCTYPE_HDR = "<!DOCTYPE html SYSTEM " \
42
53
  '"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'.freeze
43
54
 
@@ -73,7 +73,8 @@ module IsoDoc
73
73
  def sourcecode_parse(node, out)
74
74
  tag, child_tag = sourcecode_tag(node)
75
75
  s = node.at(ns("./fmt-sourcecode")) || node
76
- attr = sourcecode_attrs(node).merge(class: "sourcecode")
76
+ attr = sourcecode_attrs(node)
77
+ .merge(class: merge_html_class("sourcecode", node))
77
78
  out.send tag, **attr do |div|
78
79
  sourcecode_pre_wrap(child_tag, s, div)
79
80
  annotation_parse(s, div)
@@ -50,21 +50,46 @@ module IsoDoc
50
50
  precision: num_precision(num.text))
51
51
  end
52
52
 
53
+ # The `data-metanorma-numberformat` options metanorma types, by target
54
+ # type. The single source of truth lives here in isodoc (metanorma's
55
+ # concern), not in plurimath.
56
+ NUMBERFORMAT_INTEGER = %i(precision significant digit_count group_digits
57
+ fraction_group_digits base).freeze
58
+ NUMBERFORMAT_SYMBOL = %i(notation exponent_sign number_sign locale
59
+ hex_capital).freeze
60
+ NUMBERFORMAT_NULLABLE = %i(base_prefix base_suffix).freeze
61
+ # plurimath options metanorma deliberately passes through unchanged (string)
62
+ NUMBERFORMAT_PASSTHROUGH = %i(fraction_group decimal group times e).freeze
63
+ NUMBERFORMAT_KNOWN = (NUMBERFORMAT_INTEGER + NUMBERFORMAT_SYMBOL +
64
+ NUMBERFORMAT_NULLABLE + NUMBERFORMAT_PASSTHROUGH).freeze
65
+
53
66
  def numberformat_type(ret)
54
- %i(precision significant digit_count group_digits fraction_group_digits
55
- base)
56
- .each do |i|
57
- ret[i] &&= ret[i].to_i
58
- end
59
- %i(notation exponent_sign number_sign locale hex_capital).each do |i|
60
- ret[i] &&= ret[i].to_sym
61
- end
62
- %i(base_prefix base_suffix).each do |i|
67
+ numberformat_unclassified_warn
68
+ NUMBERFORMAT_INTEGER.each { |i| ret[i] &&= ret[i].to_i }
69
+ NUMBERFORMAT_SYMBOL.each { |i| ret[i] &&= ret[i].to_sym }
70
+ NUMBERFORMAT_NULLABLE.each do |i|
63
71
  ["", "nil"].include?(ret[i]) and ret[i] = nil
64
72
  end
65
73
  ret
66
74
  end
67
75
 
76
+ # Union plurimath's option defaults against metanorma's known lists, and
77
+ # warn (once) on anything plurimath exposes that metanorma has not
78
+ # classified -- e.g. a passthrough option added upstream (potentially via a
79
+ # direct Peter Wyatt request) that we would otherwise be none the wiser of.
80
+ # DEFAULT_OPTIONS is the passthrough watch-point, not plurimath's entire
81
+ # option surface. See metanorma/basicdoc-models#35.
82
+ def numberformat_unclassified_warn
83
+ @numberformat_warned and return
84
+ @numberformat_warned = true
85
+ unknown = Plurimath::Formatter::Standard::DEFAULT_OPTIONS.keys -
86
+ NUMBERFORMAT_KNOWN
87
+ unknown.empty? and return
88
+ warn "[isodoc] plurimath number-format options not classified by " \
89
+ "metanorma (treated as string passthrough): #{unknown.join(', ')}. " \
90
+ "Classify them in IsoDoc numberformat_type."
91
+ end
92
+
68
93
  def explicit_number_formatter(num, locale, options)
69
94
  ret = numberformat_type(csv_attribute_extract(options))
70
95
  l = ret[:locale] || locale
@@ -1,3 +1,3 @@
1
1
  module IsoDoc
2
- VERSION = "3.6.6".freeze
2
+ VERSION = "3.6.7".freeze
3
3
  end
@@ -84,12 +84,18 @@ module IsoDoc
84
84
  super.merge(attr_code(ret))
85
85
  end
86
86
 
87
+ # %plain or an explicit @style still suppresses the default border; a
88
+ # custom @class no longer nulls it. The class is HTML-only and is not
89
+ # emitted to Word output (Word CSS is too inflexible), but a custom-class
90
+ # table must still render as a normal bordered ISO table.
91
+ # Exception: the internal `rouge-line-table` (sourcecode line numbering)
92
+ # takes no ISO border and keeps its own class -- returning nil drops the
93
+ # Word MsoISOTable override (see table_attrs) so the HTML super class
94
+ # survives. metanorma/metanorma-pdfa#33
87
95
  def table_border_css(node)
88
- c = node["class"]
89
96
  style = "border-spacing:0;border-width:1px;"
90
97
  node["style"] || node["plain"] == "true" and style = ""
91
- (%w(modspec).include?(c) || !c) or style = nil
92
- node["plain"] == "true" and style = ""
98
+ node["class"] == "rouge-line-table" and style = nil
93
99
  style
94
100
  end
95
101
 
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.6
4
+ version: 3.6.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
@@ -330,7 +330,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
330
330
  requirements:
331
331
  - - ">="
332
332
  - !ruby/object:Gem::Version
333
- version: 3.1.0
333
+ version: 3.3.0
334
334
  required_rubygems_version: !ruby/object:Gem::Requirement
335
335
  requirements:
336
336
  - - ">="