isodoc 3.7.1 → 3.7.3
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/.rubocop.yml +9 -0
- data/isodoc.gemspec +1 -1
- data/lib/isodoc/convert.rb +1 -1
- data/lib/isodoc/function/section_titles.rb +12 -1
- data/lib/isodoc/function/table.rb +5 -1
- data/lib/isodoc/init.rb +4 -0
- data/lib/isodoc/presentation_function/annex.rb +1 -1
- data/lib/isodoc/presentation_function/block.rb +7 -5
- data/lib/isodoc/presentation_function/concepts.rb +3 -0
- data/lib/isodoc/presentation_function/designations.rb +5 -0
- data/lib/isodoc/presentation_function/docid_semantic.rb +52 -4
- data/lib/isodoc/presentation_function/image.rb +2 -3
- data/lib/isodoc/presentation_function/index.rb +68 -24
- data/lib/isodoc/presentation_function/list.rb +3 -0
- data/lib/isodoc/presentation_function/section.rb +1 -1
- data/lib/isodoc/presentation_function/sourcecode.rb +19 -1
- data/lib/isodoc/presentation_function/terms.rb +1 -1
- data/lib/isodoc/version.rb +1 -1
- data/lib/isodoc/xref/xref_gen_seq.rb +3 -0
- data/lib/isodoc-yaml/i18n-en.yaml +4 -0
- data/lib/isodoc-yaml/i18n-fr.yaml +4 -0
- metadata +14 -14
- data/lib/isodoc/base_style/all.css +0 -459
- data/lib/isodoc/base_style/bands.css +0 -135
- 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 +0 -72
- data/lib/isodoc/base_style/nav.css +0 -0
- data/lib/isodoc/base_style/reset.css +0 -327
- data/lib/isodoc/base_style/typography.css +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 05f87f0cc3f6c9af1a762da02c747652b67ad51a40c98d85658f69be692e36d1
|
|
4
|
+
data.tar.gz: ef06f84692f35bad821ed4a52993ece6ed7705e582a4a46a9df0d53584e3f97d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 538c670f229942b89c25779e75fd48bc7ac7b3b5df70d34025eb13e20c0801e875ac1a841f612772ae1f2bde378e776228e31f69c54676e049fd2f1fe5e45ee8
|
|
7
|
+
data.tar.gz: 351d66c6b1d2a9abb29a530ea8fa973b1c7f810d1fe1b24c57df97b05d1c2ab62ac97fda7b45725c2935c6b494d88fed93a4f11040f655ea3b8ebaa8b3542abc
|
data/.rubocop.yml
CHANGED
|
@@ -2,6 +2,15 @@
|
|
|
2
2
|
# See https://github.com/metanorma/cimas
|
|
3
3
|
inherit_from:
|
|
4
4
|
- https://raw.githubusercontent.com/riboseinc/oss-guides/main/ci/rubocop.yml
|
|
5
|
+
# .rubocop_todo.yml MUST be the last entry. inherit_from is last-wins:
|
|
6
|
+
# if listed before oss-guides, the shared config's stricter Metrics/
|
|
7
|
+
# (MethodLength, BlockLength, etc.) rules override the todo's per-file
|
|
8
|
+
# grandfathering, and the todo becomes inert on those cops. Empirically
|
|
9
|
+
# verified on suma 2026-07-06: with todo listed first, 34 Metrics/* offenses
|
|
10
|
+
# remained; moved last, cleared. Every gem in the metanorma-org fleet
|
|
11
|
+
# already ships a `.rubocop_todo.yml` on its live tree (audited 2026-07-06,
|
|
12
|
+
# 54/54 have it), so this reference is safe to emit unconditionally.
|
|
13
|
+
- .rubocop_todo.yml
|
|
5
14
|
|
|
6
15
|
# Rubocop plugins enabled centrally so every metanorma-org gem picks them up
|
|
7
16
|
# on cimas sync — best practice belongs at the shared-template layer, not
|
data/isodoc.gemspec
CHANGED
|
@@ -32,7 +32,7 @@ Gem::Specification.new do |spec|
|
|
|
32
32
|
spec.add_dependency "bigdecimal"
|
|
33
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", "< 3.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"
|
data/lib/isodoc/convert.rb
CHANGED
|
@@ -44,7 +44,7 @@ module IsoDoc
|
|
|
44
44
|
# bare: do not insert any prefatory material (coverpage, boilerplate)
|
|
45
45
|
# tocfigures: add ToC for figures
|
|
46
46
|
# toctables: add ToC for tables
|
|
47
|
-
# tocrecommendations: add ToC for
|
|
47
|
+
# tocrecommendations: add ToC for recommendations
|
|
48
48
|
# tocexamples: add ToC for examples
|
|
49
49
|
# fonts: fontist fonts to install
|
|
50
50
|
# fontlicenseagreement: fontist font license agreement
|
|
@@ -1,8 +1,19 @@
|
|
|
1
1
|
module IsoDoc
|
|
2
2
|
module Function
|
|
3
3
|
module Section
|
|
4
|
+
# Optional per-caption-type delimiter override from i18n: a
|
|
5
|
+
# +<type>_delimiter+ key, falling back to a shared +caption_delimiter+
|
|
6
|
+
# key, falling back to the hardcoded default. Uses +@i18n.get+ (hash
|
|
7
|
+
# lookup, nil for absent keys) rather than +@i18n.<key>+ (which is only
|
|
8
|
+
# defined for present keys). The keys are absent from the base i18n YAML,
|
|
9
|
+
# so default behaviour is unchanged unless a flavour or document sets them.
|
|
10
|
+
def i18n_delim(type, default)
|
|
11
|
+
@i18n&.get&.dig("#{type}_delimiter") ||
|
|
12
|
+
@i18n&.get&.dig("caption_delimiter") || default
|
|
13
|
+
end
|
|
14
|
+
|
|
4
15
|
def clausedelim
|
|
5
|
-
"."
|
|
16
|
+
i18n_delim("clause", ".")
|
|
6
17
|
end
|
|
7
18
|
|
|
8
19
|
def clausedelimspace(_node, out)
|
|
@@ -173,7 +173,11 @@ module IsoDoc
|
|
|
173
173
|
true
|
|
174
174
|
end
|
|
175
175
|
|
|
176
|
-
|
|
176
|
+
# Defaults cover the bare-tr dispatch in ToWordHtml#parse, which had
|
|
177
|
+
# called this with two arguments (unsatisfiable) since 2018: a tr
|
|
178
|
+
# outside tbody/thead context renders as an unbordered plain row
|
|
179
|
+
# instead of crashing (metanorma-pdfa#84)
|
|
180
|
+
def tr_parse(node, out, ord = 0, totalrows = 1, header = false)
|
|
177
181
|
out.tr(**attr_code(style: node["style"])) do |r|
|
|
178
182
|
node.elements.each do |td|
|
|
179
183
|
attrs = make_tr_attr(td, ord, totalrows - 1, header,
|
data/lib/isodoc/init.rb
CHANGED
|
@@ -7,6 +7,7 @@ module IsoDoc
|
|
|
7
7
|
def xref_init(lang, script, _klass, i18n, options)
|
|
8
8
|
html = HtmlConvert.new(language: @lang, script: @script)
|
|
9
9
|
@xrefs = Xref.new(lang, script, html, i18n, options)
|
|
10
|
+
@xrefs
|
|
10
11
|
end
|
|
11
12
|
|
|
12
13
|
def i18n_init(lang, script, locale, i18nyaml = nil)
|
|
@@ -35,6 +36,9 @@ module IsoDoc
|
|
|
35
36
|
toc_init(xml)
|
|
36
37
|
@details_open = xml.at(ns("//metanorma-extension/presentation-metadata/" \
|
|
37
38
|
"html-details-open"))&.text != "false"
|
|
39
|
+
@index_fold_case =
|
|
40
|
+
xml.at(ns("//metanorma-extension/presentation-metadata/" \
|
|
41
|
+
"index-case-sensitive"))&.text != "true"
|
|
38
42
|
end
|
|
39
43
|
|
|
40
44
|
def doctype_init(docxml)
|
|
@@ -46,7 +46,8 @@ module IsoDoc
|
|
|
46
46
|
n = @xrefs.get[elem["id"]] || @xrefs.get[elem["original-id"]]
|
|
47
47
|
lbl = labelled_autonum(@i18n.example, elem["id"] || elem["original-id"],
|
|
48
48
|
n&.dig(:label))
|
|
49
|
-
prefix_name(elem, { caption: block_delim }, lbl,
|
|
49
|
+
prefix_name(elem, { caption: i18n_delim("example", block_delim) }, lbl,
|
|
50
|
+
"name")
|
|
50
51
|
end
|
|
51
52
|
|
|
52
53
|
def note(docxml)
|
|
@@ -54,7 +55,7 @@ module IsoDoc
|
|
|
54
55
|
end
|
|
55
56
|
|
|
56
57
|
def note_delim(_elem)
|
|
57
|
-
"<tab/>"
|
|
58
|
+
i18n_delim("note", "<tab/>")
|
|
58
59
|
end
|
|
59
60
|
|
|
60
61
|
def note1(elem)
|
|
@@ -88,7 +89,8 @@ module IsoDoc
|
|
|
88
89
|
|
|
89
90
|
def admonition_options(elem)
|
|
90
91
|
options = { label: admonition_delim(elem) }
|
|
91
|
-
elem["type"] == "box" and
|
|
92
|
+
elem["type"] == "box" and
|
|
93
|
+
options = { caption: i18n_delim("admonition", block_delim) }
|
|
92
94
|
options
|
|
93
95
|
end
|
|
94
96
|
|
|
@@ -119,7 +121,7 @@ module IsoDoc
|
|
|
119
121
|
|
|
120
122
|
def admonition_delim(elem)
|
|
121
123
|
if elem["type"] == "box"
|
|
122
|
-
block_delim
|
|
124
|
+
i18n_delim("admonition", block_delim)
|
|
123
125
|
else
|
|
124
126
|
""
|
|
125
127
|
end
|
|
@@ -157,7 +159,7 @@ module IsoDoc
|
|
|
157
159
|
end
|
|
158
160
|
|
|
159
161
|
def table_delim
|
|
160
|
-
block_delim
|
|
162
|
+
i18n_delim("table", block_delim)
|
|
161
163
|
end
|
|
162
164
|
|
|
163
165
|
def table_long_strings_cleanup(docxml)
|
|
@@ -21,6 +21,9 @@ module IsoDoc
|
|
|
21
21
|
|
|
22
22
|
def concept_render(node, defaults)
|
|
23
23
|
opts, render, ref, ret = concept_render_init(node, defaults)
|
|
24
|
+
# generator-emitted term-resolution failure reports
|
|
25
|
+
# (metanorma-model-iso#144) render in boldface
|
|
26
|
+
ret&.xpath(ns(".//errormsg"))&.each { |e| e.name = "strong" }
|
|
24
27
|
ret&.at(ns("./refterm"))&.remove
|
|
25
28
|
ref && opts[:ref] != "false" and render&.next = " "
|
|
26
29
|
concept1_linkmention(ref, render, opts)
|
|
@@ -8,12 +8,17 @@ module IsoDoc
|
|
|
8
8
|
def related1(node)
|
|
9
9
|
p, ref, orig = related1_prep(node)
|
|
10
10
|
label = @i18n.relatedterms[orig["type"]].upcase
|
|
11
|
+
err = node.at(ns("./errormsg"))
|
|
11
12
|
ret = if p && ref
|
|
12
13
|
if p.text == ref.text
|
|
13
14
|
"<em>#{Common::to_xml(ref)}</em>"
|
|
14
15
|
else
|
|
15
16
|
"<em>#{to_xml(p)}</em> (#{Common::to_xml(ref)})"
|
|
16
17
|
end
|
|
18
|
+
elsif err
|
|
19
|
+
# generator-emitted term-resolution failure reports
|
|
20
|
+
# (metanorma-model-iso#144) render in boldface
|
|
21
|
+
"<strong>#{to_xml(err.children)}</strong>"
|
|
17
22
|
else "<strong>**RELATED TERM NOT FOUND**</strong>"
|
|
18
23
|
end
|
|
19
24
|
node.children = (l10n("<p><strong>#{label}:</strong> #{ret}</p>"))
|
|
@@ -16,18 +16,66 @@ module IsoDoc
|
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
def std_docid_semantic_parse(id)
|
|
19
|
-
|
|
19
|
+
result = pubid_parse(id)
|
|
20
20
|
# Pubid::Ieee in particular happily parses any "letters+digits" token
|
|
21
21
|
# as an IEEE Std identifier and synthesises an "IEEE Std" prefix that
|
|
22
22
|
# wasn't in the input (e.g. "REF4" -> "IEEE Std REF4"). Refuse to
|
|
23
23
|
# annotate when the parser has invented structure not present in the
|
|
24
24
|
# input -- detected by a non-identity round-trip.
|
|
25
|
-
return id if
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
return std_docid_semantic_full(id) if result.nil?
|
|
26
|
+
|
|
27
|
+
result
|
|
28
|
+
rescue StandardError
|
|
28
29
|
std_docid_semantic_full(id)
|
|
29
30
|
end
|
|
30
31
|
|
|
32
|
+
# pubid 2 has no universal Pubid::Registry.parse: try each registered
|
|
33
|
+
# flavor. Outcomes:
|
|
34
|
+
# 1. A flavor round-trips the input AND renders annotation markup —
|
|
35
|
+
# return it (some flavors' renderers ignore annotated: and
|
|
36
|
+
# return plain text; those need the regex fallback below).
|
|
37
|
+
# 2. A flavor parses but synthesizes structure the input lacks
|
|
38
|
+
# (e.g. "REF4" -> "IEEE Std REF4") — return the input unchanged
|
|
39
|
+
# (1.x's round-trip guard).
|
|
40
|
+
# 3. Nothing parses, a round-tripper renders plain, or the parse
|
|
41
|
+
# only canonicalizes FORM (e.g. em-dash year -> "--") — nil, so
|
|
42
|
+
# the caller uses the regex fallback, which preserves the
|
|
43
|
+
# original string (1.x's ParseError path).
|
|
44
|
+
def pubid_parse(string)
|
|
45
|
+
Pubid.eager_load_flavors!
|
|
46
|
+
parsed_any = false
|
|
47
|
+
plain_roundtrip = false
|
|
48
|
+
canonicalized = false
|
|
49
|
+
Pubid::Registry.flavors.each_value do |flavor|
|
|
50
|
+
next unless flavor.respond_to?(:parse)
|
|
51
|
+
|
|
52
|
+
begin
|
|
53
|
+
parsed = flavor.parse(string)
|
|
54
|
+
parsed_any = true
|
|
55
|
+
if parsed.to_s == string
|
|
56
|
+
annotated = parsed.to_s(annotated: true)
|
|
57
|
+
return annotated if annotated != parsed.to_s
|
|
58
|
+
|
|
59
|
+
plain_roundtrip = true
|
|
60
|
+
elsif dash_normalize(parsed.to_s) == dash_normalize(string)
|
|
61
|
+
canonicalized = true
|
|
62
|
+
end
|
|
63
|
+
rescue StandardError
|
|
64
|
+
next
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
return string if parsed_any && !plain_roundtrip && !canonicalized
|
|
68
|
+
|
|
69
|
+
nil
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Compare strings ignoring dash FORM (em-dash / double dash / single
|
|
73
|
+
# dash), so a parse that only canonicalizes punctuation is not
|
|
74
|
+
# mistaken for structure synthesis.
|
|
75
|
+
def dash_normalize(string)
|
|
76
|
+
string.tr("—", "-").gsub("--", "-")
|
|
77
|
+
end
|
|
78
|
+
|
|
31
79
|
# Regex-based fallback when Pubid::Registry cannot parse the id. Emits
|
|
32
80
|
# the same generic class names that Pubid uses (publisher, docnumber,
|
|
33
81
|
# part, year) so that flavors' `std_docid_span_classes` remaps work
|
|
@@ -54,12 +54,11 @@ module IsoDoc
|
|
|
54
54
|
end
|
|
55
55
|
|
|
56
56
|
def subfigure_delim
|
|
57
|
-
""
|
|
58
|
-
# "<span class='fmt-label-delim'>)</span>"
|
|
57
|
+
i18n_delim("subfigure", "")
|
|
59
58
|
end
|
|
60
59
|
|
|
61
60
|
def figure_delim(_elem)
|
|
62
|
-
block_delim
|
|
61
|
+
i18n_delim("figure", block_delim)
|
|
63
62
|
end
|
|
64
63
|
|
|
65
64
|
def figure_name(elem)
|
|
@@ -22,16 +22,24 @@ module IsoDoc
|
|
|
22
22
|
def index1(docxml, indexsect, index)
|
|
23
23
|
c = indexsect.add_child("<ul></ul>").first
|
|
24
24
|
index.keys.sort.each do |k|
|
|
25
|
-
words = index[k].keys
|
|
26
|
-
v[sortable(w).downcase] = w
|
|
27
|
-
end
|
|
25
|
+
words = index_sort_buckets(index[k].keys)
|
|
28
26
|
words.keys.localize(@lang.to_sym).sort.to_a.each do |w|
|
|
29
|
-
c.add_child index_entries(
|
|
27
|
+
words[w].each { |w1| c.add_child index_entries(w1, index[k]) }
|
|
30
28
|
end
|
|
31
29
|
end
|
|
32
30
|
index1_cleanup(docxml)
|
|
33
31
|
end
|
|
34
32
|
|
|
33
|
+
# Sorting is case-insensitive, so entries differing only in case (or
|
|
34
|
+
# only in markup, which the sort key strips) share a sort key; they
|
|
35
|
+
# are kept as distinct entries in a bucket per key, sorted adjacently
|
|
36
|
+
# (metanorma/metanorma#298: overwriting them lost all but one entry)
|
|
37
|
+
def index_sort_buckets(keys)
|
|
38
|
+
keys.compact.each_with_object({}) do |w, v|
|
|
39
|
+
(v[sortable(w).downcase] ||= []) << w
|
|
40
|
+
end.transform_values(&:sort)
|
|
41
|
+
end
|
|
42
|
+
|
|
35
43
|
def index1_cleanup(docxml)
|
|
36
44
|
docxml.xpath(ns("//indexsect//xref")).each do |x|
|
|
37
45
|
x.children.remove
|
|
@@ -48,34 +56,31 @@ module IsoDoc
|
|
|
48
56
|
{ xref_lbl: ", ", see_lbl: ", #{see_lbl}", also_lbl: ", #{also_lbl}" }
|
|
49
57
|
end
|
|
50
58
|
|
|
51
|
-
def index_entries(
|
|
52
|
-
ret = index_entries_head(
|
|
53
|
-
index.dig(words[primary], nil, nil),
|
|
59
|
+
def index_entries(primary, index)
|
|
60
|
+
ret = index_entries_head(primary, index.dig(primary, nil, nil),
|
|
54
61
|
index_entries_opt)
|
|
55
|
-
words2 = index[
|
|
56
|
-
&.each_with_object({}) { |w, v| v[w.downcase] = w }
|
|
62
|
+
words2 = index_sort_buckets(index[primary].keys)
|
|
57
63
|
unless words2.empty?
|
|
58
64
|
ret += "<ul>"
|
|
59
65
|
words2.keys.localize(@lang.to_sym).sort.to_a.each do |w|
|
|
60
|
-
ret += index_entries2(
|
|
66
|
+
words2[w].each { |w1| ret += index_entries2(w1, index[primary]) }
|
|
61
67
|
end
|
|
62
68
|
ret += "</ul>"
|
|
63
69
|
end
|
|
64
70
|
"#{ret}</li>"
|
|
65
71
|
end
|
|
66
72
|
|
|
67
|
-
def index_entries2(
|
|
68
|
-
ret = index_entries_head(
|
|
69
|
-
index.dig(words[secondary], nil),
|
|
73
|
+
def index_entries2(secondary, index)
|
|
74
|
+
ret = index_entries_head(secondary, index.dig(secondary, nil),
|
|
70
75
|
index_entries_opt)
|
|
71
|
-
words3 = index[
|
|
72
|
-
&.each_with_object({}) { |w, v| v[w.downcase] = w }
|
|
76
|
+
words3 = index_sort_buckets(index[secondary].keys)
|
|
73
77
|
unless words3.empty?
|
|
74
78
|
ret += "<ul>"
|
|
75
79
|
words3.keys.localize(@lang.to_sym).sort.to_a.each do |w|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
80
|
+
words3[w].each do |w1|
|
|
81
|
+
ret += "#{index_entries_head(w1, index[secondary][w1],
|
|
82
|
+
index_entries_opt)}</li>"
|
|
83
|
+
end
|
|
79
84
|
end
|
|
80
85
|
ret += "</ul>"
|
|
81
86
|
end
|
|
@@ -95,12 +100,9 @@ module IsoDoc
|
|
|
95
100
|
|
|
96
101
|
def index_entries_see(entries, label)
|
|
97
102
|
see_sort = entries&.dig(label) or return nil
|
|
98
|
-
x = see_sort
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
x.keys.localize(@lang.to_sym).sort.to_a.map do |k|
|
|
102
|
-
# see_sort[k]
|
|
103
|
-
x[k]
|
|
103
|
+
x = index_sort_buckets(see_sort)
|
|
104
|
+
x.keys.localize(@lang.to_sym).sort.to_a.flat_map do |k|
|
|
105
|
+
@index_fold_case ? [index_fold_head(x[k])] : x[k].uniq
|
|
104
106
|
end.join(", ")
|
|
105
107
|
end
|
|
106
108
|
|
|
@@ -116,12 +118,54 @@ module IsoDoc
|
|
|
116
118
|
index = extract_indexterms(terms)
|
|
117
119
|
index = extract_indexsee(index, see, :see)
|
|
118
120
|
index = extract_indexsee(index, also, :also)
|
|
121
|
+
@index_fold_case and index_fold_case(index)
|
|
119
122
|
index.keys.sort.each_with_object({}) do |k, v|
|
|
120
123
|
v[sortable(k)[0].upcase.transliterate] ||= {}
|
|
121
124
|
v[sortable(k)[0].upcase.transliterate][k] = index[k]
|
|
122
125
|
end
|
|
123
126
|
end
|
|
124
127
|
|
|
128
|
+
# Entries differing only in case merge into a single headword, the
|
|
129
|
+
# lowercase spelling, with the union of their subentries and locators:
|
|
130
|
+
# ((activity)) mid-sentence and ((Activity)) sentence-initially are
|
|
131
|
+
# the same entry. Suppressed by the :index-case-sensitive: document
|
|
132
|
+
# attribute for identifier-heavy documents, where Activity and
|
|
133
|
+
# activity are distinct case-bearing names (metanorma/metanorma#298).
|
|
134
|
+
# Applied per level: primaries, then secondaries, then tertiaries.
|
|
135
|
+
def index_fold_case(index)
|
|
136
|
+
index_fold_level(index)
|
|
137
|
+
index.each_value do |sec|
|
|
138
|
+
index_fold_level(sec)
|
|
139
|
+
sec.each_value { |ter| index_fold_level(ter) }
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def index_fold_level(hash)
|
|
144
|
+
hash.keys.grep(String).group_by { |w| sortable(w).downcase }
|
|
145
|
+
.each_value { |ws| ws.size > 1 and index_fold_bucket(hash, ws) }
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def index_fold_bucket(hash, words)
|
|
149
|
+
head = index_fold_head(words)
|
|
150
|
+
(words - [head]).each do |w|
|
|
151
|
+
index_merge(hash[head], hash[w])
|
|
152
|
+
hash.delete(w)
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def index_fold_head(words)
|
|
157
|
+
words.find { |w| sortable(w) == sortable(w).downcase } || words.min
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def index_merge(target, other)
|
|
161
|
+
other.each do |k, v|
|
|
162
|
+
if !target.key?(k) then target[k] = v
|
|
163
|
+
elsif v.is_a?(Array) then target[k].concat(v)
|
|
164
|
+
else index_merge(target[k], v)
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
|
|
125
169
|
def extract_indexsee(val, terms, label)
|
|
126
170
|
terms.each_with_object(val) do |t, v|
|
|
127
171
|
term, term2, term3 = extract_indexterms_init(t)
|
|
@@ -68,6 +68,9 @@ module IsoDoc
|
|
|
68
68
|
|
|
69
69
|
def ol_label_format(semx, elem)
|
|
70
70
|
template = ol_label_template(elem)[elem.parent["type"].to_sym]
|
|
71
|
+
# types outside the template set are not decorated, e.g. xml2rfc v2
|
|
72
|
+
# format strings passed through as ol/@type by metanorma-ietf
|
|
73
|
+
template or return semx
|
|
71
74
|
template.sub("%", semx)
|
|
72
75
|
end
|
|
73
76
|
|
|
@@ -175,17 +175,35 @@ module IsoDoc
|
|
|
175
175
|
lexer = Rouge::Lexer.find(lang || "plaintext") ||
|
|
176
176
|
Rouge::Lexer.find("plaintext")
|
|
177
177
|
l = Rouge::Lexers::Escape.new(start: "{^^{", end: "}^^}", lang: lexer)
|
|
178
|
+
source_collapse_markup_newlines(elem)
|
|
178
179
|
source = to_xml(elem.children).gsub("<", "{^^{<").gsub(">", ">}^^}")
|
|
179
180
|
l.lang.reset!
|
|
180
181
|
l.lex(@c.decode(source))
|
|
181
182
|
end
|
|
182
183
|
|
|
184
|
+
# Embedded markup serialised across multiple lines (e.g. pretty-printed
|
|
185
|
+
# MathML from stem) would be split across line cells by the line-table
|
|
186
|
+
# formatter, leaving each cell with unbalanced tags: the string reparse
|
|
187
|
+
# of the table then cascades mis-nested rows, and rendering crashes on
|
|
188
|
+
# the orphaned rows (metanorma-pdfa#84). Collapse whitespace inside
|
|
189
|
+
# embedded elements so each occupies a single code line; code text
|
|
190
|
+
# outside the elements is untouched.
|
|
191
|
+
def source_collapse_markup_newlines(elem)
|
|
192
|
+
elem.elements.each do |e|
|
|
193
|
+
e.xpath(".//text()").each do |t|
|
|
194
|
+
/[\n\r]/.match?(t.content) and
|
|
195
|
+
t.content = t.content.gsub(/\s*[\n\r]+\s*/, " ")
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
end
|
|
199
|
+
|
|
183
200
|
def source_label(elem)
|
|
184
201
|
if !labelled_ancestor(elem) && # do not number if labelled_ancestor
|
|
185
202
|
lbl = @xrefs.anchor(elem["id"], :label, false)
|
|
186
203
|
s = labelled_autonum(lower2cap(@i18n.figure), elem["id"], lbl)&.strip
|
|
187
204
|
end
|
|
188
|
-
prefix_name(elem, { caption: block_delim }, s,
|
|
205
|
+
prefix_name(elem, { caption: i18n_delim("sourcecode", block_delim) }, s,
|
|
206
|
+
"name")
|
|
189
207
|
end
|
|
190
208
|
end
|
|
191
209
|
end
|
data/lib/isodoc/version.rb
CHANGED
|
@@ -105,6 +105,7 @@ module IsoDoc
|
|
|
105
105
|
end
|
|
106
106
|
|
|
107
107
|
def sequential_permission_names(clause, container: true)
|
|
108
|
+
@reqt_models or (warn "reqt_models not set, skipping permission numbering" and return)
|
|
108
109
|
clause.xpath(ns(first_lvl_req)).noblank
|
|
109
110
|
.each_with_object(ReqCounter.new) do |t, c|
|
|
110
111
|
m = @reqt_models.model(t["model"])
|
|
@@ -117,6 +118,7 @@ module IsoDoc
|
|
|
117
118
|
end
|
|
118
119
|
|
|
119
120
|
def sequential_permission_children(elem, lbl, klass, container: false)
|
|
121
|
+
@reqt_models or (warn "reqt_models not set, skipping permission children numbering" and return)
|
|
120
122
|
elem.xpath(ns(req_children)).noblank
|
|
121
123
|
.each_with_object(ReqCounter.new) do |t, c|
|
|
122
124
|
m = @reqt_models.model(t["model"])
|
|
@@ -229,6 +231,7 @@ container: false)
|
|
|
229
231
|
end
|
|
230
232
|
|
|
231
233
|
def hierarchical_permission_names(clauses, num)
|
|
234
|
+
@reqt_models or (warn "reqt_models not set, skipping hierarchical permission numbering" and return)
|
|
232
235
|
nodeSet(clauses).each_with_object(ReqCounter.new) do |clause, c|
|
|
233
236
|
clause.xpath(ns(first_lvl_req)).noblank.each do |t|
|
|
234
237
|
m = @reqt_models.model(t["model"])
|
|
@@ -135,6 +135,7 @@ title_prefixes:
|
|
|
135
135
|
locality: {
|
|
136
136
|
section: Section,
|
|
137
137
|
clause: Clause,
|
|
138
|
+
definition: Definition,
|
|
138
139
|
part: Part,
|
|
139
140
|
paragraph: Paragraph,
|
|
140
141
|
chapter: Chapter,
|
|
@@ -174,6 +175,9 @@ inflection:
|
|
|
174
175
|
Clause:
|
|
175
176
|
sg: Clause
|
|
176
177
|
pl: Clauses
|
|
178
|
+
Definition:
|
|
179
|
+
sg: Definition
|
|
180
|
+
pl: Definitions
|
|
177
181
|
Annex:
|
|
178
182
|
sg: Annex
|
|
179
183
|
pl: Annexes
|
|
@@ -131,6 +131,7 @@ title_prefixes:
|
|
|
131
131
|
locality: {
|
|
132
132
|
section: Section,
|
|
133
133
|
clause: Article,
|
|
134
|
+
definition: Définition,
|
|
134
135
|
part: Partie,
|
|
135
136
|
paragraph: Alinéa,
|
|
136
137
|
chapter: Chapitre,
|
|
@@ -170,6 +171,9 @@ inflection:
|
|
|
170
171
|
Clause:
|
|
171
172
|
sg: Article
|
|
172
173
|
pl: Articles
|
|
174
|
+
Definition:
|
|
175
|
+
sg: Définition
|
|
176
|
+
pl: Définitions
|
|
173
177
|
Annex:
|
|
174
178
|
sg: Annexe
|
|
175
179
|
pl: Annexes
|
metadata
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: isodoc
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.7.
|
|
4
|
+
version: 3.7.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose Inc.
|
|
8
|
+
autorequire:
|
|
8
9
|
bindir: bin
|
|
9
10
|
cert_chain: []
|
|
10
|
-
date:
|
|
11
|
+
date: 2026-09-08 00:00:00.000000000 Z
|
|
11
12
|
dependencies:
|
|
12
13
|
- !ruby/object:Gem::Dependency
|
|
13
14
|
name: base64
|
|
@@ -55,16 +56,22 @@ dependencies:
|
|
|
55
56
|
name: relaton-cli
|
|
56
57
|
requirement: !ruby/object:Gem::Requirement
|
|
57
58
|
requirements:
|
|
58
|
-
- - "
|
|
59
|
+
- - ">="
|
|
59
60
|
- !ruby/object:Gem::Version
|
|
60
61
|
version: 2.1.0
|
|
62
|
+
- - "<"
|
|
63
|
+
- !ruby/object:Gem::Version
|
|
64
|
+
version: 3.1.0
|
|
61
65
|
type: :runtime
|
|
62
66
|
prerelease: false
|
|
63
67
|
version_requirements: !ruby/object:Gem::Requirement
|
|
64
68
|
requirements:
|
|
65
|
-
- - "
|
|
69
|
+
- - ">="
|
|
66
70
|
- !ruby/object:Gem::Version
|
|
67
71
|
version: 2.1.0
|
|
72
|
+
- - "<"
|
|
73
|
+
- !ruby/object:Gem::Version
|
|
74
|
+
version: 3.1.0
|
|
68
75
|
- !ruby/object:Gem::Dependency
|
|
69
76
|
name: mn2pdf
|
|
70
77
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -207,25 +214,16 @@ files:
|
|
|
207
214
|
- lib/isodoc-yaml/i18n-zh-Hans.yaml
|
|
208
215
|
- lib/isodoc-yaml/i18n-zh-Hant.yaml
|
|
209
216
|
- lib/isodoc.rb
|
|
210
|
-
- lib/isodoc/base_style/all.css
|
|
211
217
|
- lib/isodoc/base_style/all.scss
|
|
212
|
-
- lib/isodoc/base_style/bands.css
|
|
213
218
|
- lib/isodoc/base_style/bands.scss
|
|
214
|
-
- lib/isodoc/base_style/blocks.css
|
|
215
219
|
- lib/isodoc/base_style/blocks.scss
|
|
216
|
-
- lib/isodoc/base_style/coverpage.css
|
|
217
220
|
- lib/isodoc/base_style/coverpage.scss
|
|
218
|
-
- lib/isodoc/base_style/defaults.css
|
|
219
221
|
- lib/isodoc/base_style/defaults.scss
|
|
220
|
-
- lib/isodoc/base_style/metanorma_word.css
|
|
221
222
|
- lib/isodoc/base_style/metanorma_word.scss
|
|
222
|
-
- lib/isodoc/base_style/nav.css
|
|
223
223
|
- lib/isodoc/base_style/nav.scss
|
|
224
|
-
- lib/isodoc/base_style/reset.css
|
|
225
224
|
- lib/isodoc/base_style/reset.scss
|
|
226
225
|
- lib/isodoc/base_style/rouge.css
|
|
227
226
|
- lib/isodoc/base_style/scripts.html
|
|
228
|
-
- lib/isodoc/base_style/typography.css
|
|
229
227
|
- lib/isodoc/base_style/typography.scss
|
|
230
228
|
- lib/isodoc/class_utils.rb
|
|
231
229
|
- lib/isodoc/common.rb
|
|
@@ -337,6 +335,7 @@ homepage: https://github.com/metanorma/isodoc
|
|
|
337
335
|
licenses:
|
|
338
336
|
- BSD-2-Clause
|
|
339
337
|
metadata: {}
|
|
338
|
+
post_install_message:
|
|
340
339
|
rdoc_options: []
|
|
341
340
|
require_paths:
|
|
342
341
|
- lib
|
|
@@ -351,7 +350,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
351
350
|
- !ruby/object:Gem::Version
|
|
352
351
|
version: '0'
|
|
353
352
|
requirements: []
|
|
354
|
-
rubygems_version:
|
|
353
|
+
rubygems_version: 3.5.22
|
|
354
|
+
signing_key:
|
|
355
355
|
specification_version: 4
|
|
356
356
|
summary: Convert documents in IsoDoc into Word and HTML in AsciiDoc.
|
|
357
357
|
test_files: []
|