metanorma-iso 1.7.2 → 1.8.2
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/.github/workflows/rake.yml +11 -41
- data/.gitignore +2 -0
- data/.rubocop.yml +7 -1
- data/lib/asciidoctor/iso/base.rb +14 -11
- data/lib/asciidoctor/iso/biblio.rng +4 -6
- data/lib/asciidoctor/iso/cleanup.rb +40 -24
- data/lib/asciidoctor/iso/front.rb +29 -17
- data/lib/asciidoctor/iso/front_id.rb +81 -60
- data/lib/asciidoctor/iso/isodoc.rng +327 -2
- data/lib/asciidoctor/iso/isostandard.rng +12 -97
- data/lib/asciidoctor/iso/section.rb +2 -1
- data/lib/asciidoctor/iso/validate.rb +22 -109
- data/lib/asciidoctor/iso/validate_image.rb +97 -0
- data/lib/asciidoctor/iso/validate_requirements.rb +26 -20
- data/lib/asciidoctor/iso/validate_section.rb +39 -20
- data/lib/asciidoctor/iso/validate_style.rb +36 -24
- data/lib/asciidoctor/iso/validate_title.rb +23 -17
- data/lib/isodoc/iso/base_convert.rb +19 -2
- data/lib/isodoc/iso/html/style-human.css +7 -0
- data/lib/isodoc/iso/html/style-iso.css +7 -0
- data/lib/isodoc/iso/html_convert.rb +0 -1
- data/lib/isodoc/iso/i18n-en.yaml +4 -0
- data/lib/isodoc/iso/i18n-fr.yaml +4 -0
- data/lib/isodoc/iso/i18n-zh-Hans.yaml +4 -0
- data/lib/isodoc/iso/index.rb +140 -0
- data/lib/isodoc/iso/iso.amendment.xsl +1157 -208
- data/lib/isodoc/iso/iso.international-standard.xsl +1157 -208
- data/lib/isodoc/iso/metadata.rb +1 -0
- data/lib/isodoc/iso/presentation_xml_convert.rb +45 -37
- data/lib/isodoc/iso/sts_convert.rb +10 -13
- data/lib/isodoc/iso/word_convert.rb +0 -1
- data/lib/isodoc/iso/xref.rb +46 -25
- data/lib/metanorma/iso/processor.rb +1 -0
- data/lib/metanorma/iso/version.rb +1 -1
- data/metanorma-iso.gemspec +8 -8
- data/spec/{asciidoctor-iso → asciidoctor}/amd_spec.rb +5 -5
- data/spec/asciidoctor/base_spec.rb +825 -0
- data/spec/{asciidoctor-iso → asciidoctor}/blocks_spec.rb +0 -0
- data/spec/{asciidoctor-iso → asciidoctor}/cleanup_spec.rb +383 -25
- data/spec/{asciidoctor-iso → asciidoctor}/inline_spec.rb +0 -0
- data/spec/{asciidoctor-iso → asciidoctor}/lists_spec.rb +0 -0
- data/spec/{asciidoctor-iso → asciidoctor}/refs_spec.rb +0 -0
- data/spec/{asciidoctor-iso → asciidoctor}/section_spec.rb +0 -14
- data/spec/{asciidoctor-iso → asciidoctor}/table_spec.rb +0 -0
- data/spec/{asciidoctor-iso → asciidoctor}/validate_spec.rb +188 -83
- data/spec/isodoc/postproc_spec.rb +481 -438
- data/spec/isodoc/section_spec.rb +219 -0
- data/spec/spec_helper.rb +2 -0
- metadata +65 -64
- data/lib/isodoc/iso/html/scripts.html +0 -178
- data/spec/asciidoctor-iso/base_spec.rb +0 -704
@@ -7,28 +7,32 @@ module Asciidoctor
|
|
7
7
|
class Converter < Standoc::Converter
|
8
8
|
def extract_text(node)
|
9
9
|
return "" if node.nil?
|
10
|
+
|
10
11
|
node1 = Nokogiri::XML.fragment(node.to_s)
|
11
12
|
node1.xpath("//link | //locality | //localityStack").each(&:remove)
|
12
13
|
ret = ""
|
13
14
|
node1.traverse { |x| ret += x.text if x.text? }
|
14
|
-
ret
|
15
|
+
HTMLEntities.new.decode(ret)
|
15
16
|
end
|
16
17
|
|
17
18
|
# ISO/IEC DIR 2, 12.2
|
18
19
|
def foreword_style(node)
|
19
20
|
return if @novalid
|
21
|
+
|
20
22
|
style_no_guidance(node, extract_text(node), "Foreword")
|
21
23
|
end
|
22
24
|
|
23
25
|
# ISO/IEC DIR 2, 14.2
|
24
26
|
def scope_style(node)
|
25
27
|
return if @novalid
|
28
|
+
|
26
29
|
style_no_guidance(node, extract_text(node), "Scope")
|
27
30
|
end
|
28
31
|
|
29
32
|
# ISO/IEC DIR 2, 13.2
|
30
33
|
def introduction_style(node)
|
31
34
|
return if @novalid
|
35
|
+
|
32
36
|
r = requirement_check(extract_text(node))
|
33
37
|
style_warning(node, "Introduction may contain requirement", r) if r
|
34
38
|
end
|
@@ -36,6 +40,7 @@ module Asciidoctor
|
|
36
40
|
# ISO/IEC DIR 2, 16.5.6
|
37
41
|
def definition_style(node)
|
38
42
|
return if @novalid
|
43
|
+
|
39
44
|
r = requirement_check(extract_text(node))
|
40
45
|
style_warning(node, "Definition may contain requirement", r) if r
|
41
46
|
end
|
@@ -44,6 +49,7 @@ module Asciidoctor
|
|
44
49
|
# ISO/IEC DIR 2, 25.5
|
45
50
|
def example_style(node)
|
46
51
|
return if @novalid
|
52
|
+
|
47
53
|
style_no_guidance(node, extract_text(node), "Example")
|
48
54
|
style(node, extract_text(node))
|
49
55
|
end
|
@@ -51,6 +57,7 @@ module Asciidoctor
|
|
51
57
|
# ISO/IEC DIR 2, 24.5
|
52
58
|
def note_style(node)
|
53
59
|
return if @novalid
|
60
|
+
|
54
61
|
style_no_guidance(node, extract_text(node), "Note")
|
55
62
|
style(node, extract_text(node))
|
56
63
|
end
|
@@ -58,6 +65,7 @@ module Asciidoctor
|
|
58
65
|
# ISO/IEC DIR 2, 26.5
|
59
66
|
def footnote_style(node)
|
60
67
|
return if @novalid
|
68
|
+
|
61
69
|
style_no_guidance(node, extract_text(node), "Footnote")
|
62
70
|
style(node, extract_text(node))
|
63
71
|
end
|
@@ -70,6 +78,7 @@ module Asciidoctor
|
|
70
78
|
# and a negative match on its preceding token
|
71
79
|
def style_two_regex_not_prev(n, text, re, re_prev, warning)
|
72
80
|
return if text.nil?
|
81
|
+
|
73
82
|
arr = Tokenizer::WhitespaceTokenizer.new.tokenize(text)
|
74
83
|
arr.each_index do |i|
|
75
84
|
m = re.match arr[i]
|
@@ -80,43 +89,45 @@ module Asciidoctor
|
|
80
89
|
end
|
81
90
|
end
|
82
91
|
|
83
|
-
def style(
|
92
|
+
def style(node, text)
|
84
93
|
return if @novalid
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
94
|
+
|
95
|
+
style_number(node, text)
|
96
|
+
style_percent(node, text)
|
97
|
+
style_abbrev(node, text)
|
98
|
+
style_units(node, text)
|
89
99
|
end
|
90
100
|
|
91
101
|
# ISO/IEC DIR 2, 9.1
|
92
102
|
# ISO/IEC DIR 2, Table B.1
|
93
|
-
def style_number(
|
103
|
+
def style_number(node, text)
|
94
104
|
style_two_regex_not_prev(
|
95
|
-
|
105
|
+
node, text, /^(?<num>-?[0-9]{4,}[,0-9]*)$/,
|
96
106
|
%r{\b(ISO|IEC|IEEE/|(in|January|February|March|April|May|June|August|September|October|November|December)\b)$},
|
97
|
-
"number not broken up in threes"
|
107
|
+
"number not broken up in threes"
|
108
|
+
)
|
98
109
|
style_regex(/\b(?<num>[0-9]+\.[0-9]+)/i,
|
99
|
-
"possible decimal point",
|
100
|
-
style_regex(/\b(?<num>
|
101
|
-
"ambiguous number",
|
110
|
+
"possible decimal point", node, text)
|
111
|
+
style_regex(/\b(?<num>billions?)\b/i,
|
112
|
+
"ambiguous number", node, text)
|
102
113
|
end
|
103
114
|
|
104
115
|
# ISO/IEC DIR 2, 9.2.1
|
105
|
-
def style_percent(
|
116
|
+
def style_percent(node, text)
|
106
117
|
style_regex(/\b(?<num>[0-9.,]+%)/,
|
107
|
-
"no space before percent sign",
|
118
|
+
"no space before percent sign", node, text)
|
108
119
|
style_regex(/\b(?<num>[0-9.,]+ \u00b1 [0-9,.]+ %)/,
|
109
|
-
"unbracketed tolerance before percent sign",
|
120
|
+
"unbracketed tolerance before percent sign", node, text)
|
110
121
|
end
|
111
122
|
|
112
123
|
# ISO/IEC DIR 2, 8.4
|
113
124
|
# ISO/IEC DIR 2, 9.3
|
114
|
-
def style_abbrev(
|
125
|
+
def style_abbrev(node, text)
|
115
126
|
style_regex(/(^|\s)(?!e\.g\.|i\.e\.)
|
116
127
|
(?<num>[a-z]{1,2}\.([a-z]{1,2}|\.))\b/ix,
|
117
|
-
|
128
|
+
"no dots in abbreviations", node, text)
|
118
129
|
style_regex(/\b(?<num>ppm)\b/i,
|
119
|
-
"language-specific abbreviation",
|
130
|
+
"language-specific abbreviation", node, text)
|
120
131
|
end
|
121
132
|
|
122
133
|
# leaving out as problematic: N J K C S T H h d B o E
|
@@ -125,12 +136,13 @@ module Asciidoctor
|
|
125
136
|
"bit|kB|MB|Hart|nat|Sh|var)".freeze
|
126
137
|
|
127
138
|
# ISO/IEC DIR 2, 9.3
|
128
|
-
def style_units(
|
139
|
+
def style_units(node, text)
|
129
140
|
style_regex(/\b(?<num>[0-9][0-9,]*\s+[\u00b0\u2032\u2033])/,
|
130
|
-
"space between number and degrees/minutes/seconds",
|
141
|
+
"space between number and degrees/minutes/seconds",
|
142
|
+
node, text)
|
131
143
|
style_regex(/\b(?<num>[0-9][0-9,]*#{SI_UNIT})\b/,
|
132
|
-
"no space between number and SI unit",
|
133
|
-
style_non_std_units(
|
144
|
+
"no space between number and SI unit", node, text)
|
145
|
+
style_non_std_units(node, text)
|
134
146
|
end
|
135
147
|
|
136
148
|
NONSTD_UNITS = {
|
@@ -139,10 +151,10 @@ module Asciidoctor
|
|
139
151
|
}.freeze
|
140
152
|
|
141
153
|
# ISO/IEC DIR 2, 9.3
|
142
|
-
def style_non_std_units(
|
154
|
+
def style_non_std_units(node, text)
|
143
155
|
NONSTD_UNITS.each do |k, v|
|
144
156
|
style_regex(/\b(?<num>[0-9][0-9,]*\s+#{k})\b/,
|
145
|
-
"non-standard unit (should be #{v})",
|
157
|
+
"non-standard unit (should be #{v})", node, text)
|
146
158
|
end
|
147
159
|
end
|
148
160
|
end
|
@@ -3,9 +3,13 @@ require "metanorma-standoc"
|
|
3
3
|
module Asciidoctor
|
4
4
|
module ISO
|
5
5
|
class Converter < Standoc::Converter
|
6
|
+
def title_lang_part(doc, part, lang)
|
7
|
+
doc.at("//bibdata/title[@type='title-#{part}' and @language='#{lang}']")
|
8
|
+
end
|
9
|
+
|
6
10
|
def title_intro_validate(root)
|
7
|
-
title_intro_en = root
|
8
|
-
title_intro_fr = root
|
11
|
+
title_intro_en = title_lang_part(root, "intro", "en")
|
12
|
+
title_intro_fr = title_lang_part(root, "intro", "fr")
|
9
13
|
if title_intro_en.nil? && !title_intro_fr.nil?
|
10
14
|
@log.add("Style", title_intro_fr, "No English Title Intro!")
|
11
15
|
end
|
@@ -15,8 +19,8 @@ module Asciidoctor
|
|
15
19
|
end
|
16
20
|
|
17
21
|
def title_main_validate(root)
|
18
|
-
title_main_en = root
|
19
|
-
title_main_fr = root
|
22
|
+
title_main_en = title_lang_part(root, "main", "en")
|
23
|
+
title_main_fr = title_lang_part(root, "main", "fr")
|
20
24
|
if title_main_en.nil? && !title_main_fr.nil?
|
21
25
|
@log.add("Style", title_main_fr, "No English Title!")
|
22
26
|
end
|
@@ -26,8 +30,8 @@ module Asciidoctor
|
|
26
30
|
end
|
27
31
|
|
28
32
|
def title_part_validate(root)
|
29
|
-
title_part_en = root
|
30
|
-
title_part_fr = root
|
33
|
+
title_part_en = title_lang_part(root, "part", "en")
|
34
|
+
title_part_fr = title_lang_part(root, "part", "fr")
|
31
35
|
(title_part_en.nil? && !title_part_fr.nil?) &&
|
32
36
|
@log.add("Style", title_part_fr, "No English Title Part!")
|
33
37
|
(!title_part_en.nil? && title_part_fr.nil?) &&
|
@@ -41,21 +45,21 @@ module Asciidoctor
|
|
41
45
|
iec = root.at("//bibdata/contributor[role/@type = 'publisher']/"\
|
42
46
|
"organization[abbreviation = 'IEC' or "\
|
43
47
|
"name = 'International Electrotechnical Commission']")
|
44
|
-
|
48
|
+
subpart && !iec and
|
49
|
+
@log.add("Style", docid, "Subpart defined on non-IEC document!")
|
45
50
|
end
|
46
51
|
|
47
52
|
# ISO/IEC DIR 2, 11.5.2
|
48
53
|
def title_names_type_validate(root)
|
49
54
|
doctypes = /International\sStandard | Technical\sSpecification |
|
50
55
|
Publicly\sAvailable\sSpecification | Technical\sReport | Guide /xi
|
51
|
-
title_main_en = root
|
52
|
-
|
56
|
+
title_main_en = title_lang_part(root, "main", "en")
|
57
|
+
!title_main_en.nil? && doctypes.match(title_main_en.text) and
|
53
58
|
@log.add("Style", title_main_en, "Main Title may name document type")
|
54
|
-
|
55
|
-
title_intro_en
|
56
|
-
|
57
|
-
|
58
|
-
end
|
59
|
+
title_intro_en = title_lang_part(root, "intro", "en")
|
60
|
+
!title_intro_en.nil? && doctypes.match(title_intro_en.text) and
|
61
|
+
@log.add("Style", title_intro_en,
|
62
|
+
"Title Intro may name document type")
|
59
63
|
end
|
60
64
|
|
61
65
|
# ISO/IEC DIR 2, 22.2
|
@@ -64,8 +68,9 @@ module Asciidoctor
|
|
64
68
|
title = s&.at("./title")&.text || s.name
|
65
69
|
s.xpath("./clause | ./terms | ./references").each do |ss|
|
66
70
|
subtitle = ss.at("./title")
|
67
|
-
!subtitle.nil? && !subtitle&.text&.empty?
|
68
|
-
@log.add("Style", ss,
|
71
|
+
!subtitle.nil? && !subtitle&.text&.empty? or
|
72
|
+
@log.add("Style", ss,
|
73
|
+
"#{title}: each first-level subclause must have a title")
|
69
74
|
end
|
70
75
|
end
|
71
76
|
end
|
@@ -82,7 +87,8 @@ module Asciidoctor
|
|
82
87
|
withtitle = withtitle || (subtitle && !subtitle.text.empty?)
|
83
88
|
end
|
84
89
|
notitle && withtitle &&
|
85
|
-
@log.add("Style", nil,
|
90
|
+
@log.add("Style", nil,
|
91
|
+
"#{label}: all subclauses must have a title, or none")
|
86
92
|
end
|
87
93
|
|
88
94
|
def title_validate(root)
|
@@ -15,6 +15,7 @@ module IsoDoc
|
|
15
15
|
|
16
16
|
def implicit_reference(b)
|
17
17
|
return true if b&.at(ns("./docidentifier"))&.text == "IEV"
|
18
|
+
|
18
19
|
super
|
19
20
|
end
|
20
21
|
|
@@ -27,8 +28,9 @@ module IsoDoc
|
|
27
28
|
end
|
28
29
|
end
|
29
30
|
|
30
|
-
def example_span_label(
|
31
|
+
def example_span_label(_node, div, name)
|
31
32
|
return if name.nil?
|
33
|
+
|
32
34
|
div.span **{ class: "example_label" } do |p|
|
33
35
|
name.children.each { |n| parse(n, div) }
|
34
36
|
end
|
@@ -56,6 +58,7 @@ module IsoDoc
|
|
56
58
|
node.elements.each do |e|
|
57
59
|
next if e.name == "name"
|
58
60
|
return true if e.name == "p"
|
61
|
+
|
59
62
|
return false
|
60
63
|
end
|
61
64
|
false
|
@@ -74,6 +77,7 @@ module IsoDoc
|
|
74
77
|
def insertall_after_here(node, insert, name)
|
75
78
|
node.children.each do |n|
|
76
79
|
next unless n.name == name
|
80
|
+
|
77
81
|
insert.next = n.remove
|
78
82
|
insert = n
|
79
83
|
end
|
@@ -83,6 +87,7 @@ module IsoDoc
|
|
83
87
|
def termexamples_before_termnotes(node)
|
84
88
|
return unless node.at(ns("./termnote")) && node.at(ns("./termexample"))
|
85
89
|
return unless insert = node.at(ns("./definition"))
|
90
|
+
|
86
91
|
insert = insertall_after_here(node, insert, "termexample")
|
87
92
|
insert = insertall_after_here(node, insert, "termnote")
|
88
93
|
end
|
@@ -110,6 +115,7 @@ module IsoDoc
|
|
110
115
|
return super unless (dl&.xpath(ns("./dt"))&.size == 1 &&
|
111
116
|
dl&.at(ns("./dd"))&.elements&.size == 1 &&
|
112
117
|
dl&.at(ns("./dd/p")))
|
118
|
+
|
113
119
|
out.span **{ class: "zzMoveToFollowing" } do |s|
|
114
120
|
s << "#{@i18n.where} "
|
115
121
|
dl.at(ns("./dt")).children.each { |n| parse(n, s) }
|
@@ -149,7 +155,18 @@ module IsoDoc
|
|
149
155
|
|
150
156
|
def figure_name_parse(node, div, name)
|
151
157
|
div.p **{ class: "FigureTitle", style: "text-align:center;" } do |p|
|
152
|
-
name
|
158
|
+
name&.children&.each { |n| parse(n, div) }
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def middle(isoxml, out)
|
163
|
+
super
|
164
|
+
indexsect isoxml, out
|
165
|
+
end
|
166
|
+
|
167
|
+
def indexsect(isoxml, out)
|
168
|
+
isoxml.xpath(ns("//indexsect")).each do |i|
|
169
|
+
clause_parse(i, out)
|
153
170
|
end
|
154
171
|
end
|
155
172
|
end
|
@@ -115,6 +115,13 @@ a.FootnoteRef + a.FootnoteRef:before {
|
|
115
115
|
content: ", ";
|
116
116
|
vertical-align: super; }
|
117
117
|
|
118
|
+
.addition {
|
119
|
+
color: blue; }
|
120
|
+
|
121
|
+
.deletion {
|
122
|
+
color: red;
|
123
|
+
text-decoration: line-through; }
|
124
|
+
|
118
125
|
#standard-band {
|
119
126
|
background-color: #0AC442; }
|
120
127
|
|
@@ -115,6 +115,13 @@ a.FootnoteRef + a.FootnoteRef:before {
|
|
115
115
|
content: ", ";
|
116
116
|
vertical-align: super; }
|
117
117
|
|
118
|
+
.addition {
|
119
|
+
color: blue; }
|
120
|
+
|
121
|
+
.deletion {
|
122
|
+
color: red;
|
123
|
+
text-decoration: line-through; }
|
124
|
+
|
118
125
|
#standard-band {
|
119
126
|
background-color: #0AC442; }
|
120
127
|
|
data/lib/isodoc/iso/i18n-en.yaml
CHANGED
data/lib/isodoc/iso/i18n-fr.yaml
CHANGED
@@ -0,0 +1,140 @@
|
|
1
|
+
module IsoDoc
|
2
|
+
module Iso
|
3
|
+
class PresentationXMLConvert < IsoDoc::PresentationXMLConvert
|
4
|
+
def add_id
|
5
|
+
%(id="_#{UUIDTools::UUID.random_create}")
|
6
|
+
end
|
7
|
+
|
8
|
+
def index(docxml)
|
9
|
+
unless docxml.at(ns("//index"))
|
10
|
+
docxml.xpath(ns("//indexsect")).each { |i| i.remove }
|
11
|
+
return
|
12
|
+
end
|
13
|
+
i = docxml.at(ns("//indexsect")) ||
|
14
|
+
docxml.root.add_child("<indexsect #{add_id}><title>#{@i18n.index}</title></indexsect>").first
|
15
|
+
index = sort_indexterms(docxml.xpath(ns("//index")), docxml.xpath(ns("//index-xref[@also = 'false']")),
|
16
|
+
docxml.xpath(ns("//index-xref[@also = 'true']")))
|
17
|
+
index1(docxml, i, index)
|
18
|
+
end
|
19
|
+
|
20
|
+
def index1(docxml, i, index)
|
21
|
+
c = i.add_child("<ul></ul>").first
|
22
|
+
index.keys.sort.each do |k|
|
23
|
+
#c = i.add_child "<clause #{add_id}><title>#{k}</title><ul></ul></clause>"
|
24
|
+
words = index[k].keys.each_with_object({}) { |w, v| v[sortable(w).downcase] = w }
|
25
|
+
words.keys.localize(@lang.to_sym).sort.to_a.each do |w|
|
26
|
+
#c.first.at(ns("./ul")).add_child index_entries(words, index[k], w)
|
27
|
+
c.add_child index_entries(words, index[k], w)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
docxml.xpath(ns("//indexsect//xref")).each { |x| x.children.remove }
|
31
|
+
@xrefs.bookmark_anchor_names(docxml)
|
32
|
+
end
|
33
|
+
|
34
|
+
def sortable(s)
|
35
|
+
HTMLEntities.new.decode(Nokogiri::XML.fragment(s).text)
|
36
|
+
end
|
37
|
+
|
38
|
+
def index_entries_opt
|
39
|
+
{ xref_lbl: ", ", see_lbl: ", #{see_lbl}", also_lbl: ", #{also_lbl}" }
|
40
|
+
end
|
41
|
+
|
42
|
+
def index_entries(words, index, primary)
|
43
|
+
ret = index_entries_head(words[primary], index.dig(words[primary], nil, nil), index_entries_opt)
|
44
|
+
words2 = index[words[primary]]&.keys&.reject { |k| k.nil?}&.each_with_object({}) { |w, v| v[w.downcase] = w }
|
45
|
+
unless words2.empty?
|
46
|
+
ret += "<ul>"
|
47
|
+
words2.keys.localize(@lang.to_sym).sort.to_a.each do |w|
|
48
|
+
ret += index_entries2(words2, index[words[primary]], w)
|
49
|
+
end
|
50
|
+
ret += "</ul>"
|
51
|
+
end
|
52
|
+
ret + "</li>"
|
53
|
+
end
|
54
|
+
|
55
|
+
def index_entries2(words, index, secondary)
|
56
|
+
ret = index_entries_head(words[secondary], index.dig(words[secondary], nil), index_entries_opt)
|
57
|
+
words3 = index[words[secondary]]&.keys&.reject { |k| k.nil?}&.each_with_object({}) { |w, v| v[w.downcase] = w }
|
58
|
+
unless words3.empty?
|
59
|
+
ret += "<ul>"
|
60
|
+
words3.keys.localize(@lang.to_sym).sort.to_a.each do |w|
|
61
|
+
ret += (index_entries_head(words3[w], index[words[secondary]][words3[w]], index_entries_opt) + "</li>")
|
62
|
+
end
|
63
|
+
ret += "</ul>"
|
64
|
+
end
|
65
|
+
ret + "</li>"
|
66
|
+
end
|
67
|
+
|
68
|
+
def index_entries_head(head, entries, opt)
|
69
|
+
ret = "<li>#{head}"
|
70
|
+
xref = entries&.dig(:xref)&.join(", ")
|
71
|
+
see_sort = entries&.dig(:see)&.each_with_object({}) { |w, v| v[sortable(w).downcase] = w }
|
72
|
+
see = see_sort&.keys&.localize(@lang.to_sym)&.sort&.to_a&.map { |k| see_sort[k] }&.join(", ")
|
73
|
+
also_sort = entries&.dig(:also)&.each_with_object({}) { |w, v| v[sortable(w).downcase] = w }
|
74
|
+
also = also_sort&.keys&.localize(@lang.to_sym)&.sort&.to_a&.map { |k| also_sort[k] }&.join(", ")
|
75
|
+
ret += "#{opt[:xref_lbl]} #{xref}" if xref
|
76
|
+
ret += "#{opt[:see_lbl]} #{see}" if see
|
77
|
+
ret += "#{opt[:also_lbl]} #{also}" if also
|
78
|
+
ret
|
79
|
+
end
|
80
|
+
|
81
|
+
def see_lbl
|
82
|
+
@lang == "en" ? @i18n.see : "<em>#{@i18n.see}</em>"
|
83
|
+
end
|
84
|
+
|
85
|
+
def also_lbl
|
86
|
+
@lang == "en" ? @i18n.see_also : "<em>#{@i18n.see_also}</em>"
|
87
|
+
end
|
88
|
+
|
89
|
+
def sort_indexterms(terms, see, also)
|
90
|
+
index = extract_indexterms(terms)
|
91
|
+
index = extract_indexsee(index, see, :see)
|
92
|
+
index = extract_indexsee(index, also, :also)
|
93
|
+
index.keys.sort.each_with_object({}) do |k, v|
|
94
|
+
v[sortable(k)[0].upcase.transliterate] ||= {}
|
95
|
+
v[sortable(k)[0].upcase.transliterate][k] = index[k]
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def extract_indexsee(v, terms, label)
|
100
|
+
terms.each_with_object(v) do |t, v|
|
101
|
+
term = t&.at(ns("./primary"))&.children&.to_xml
|
102
|
+
term2 = t&.at(ns("./secondary"))&.children&.to_xml
|
103
|
+
term3 = t&.at(ns("./tertiary"))&.children&.to_xml
|
104
|
+
v[term] ||= {}
|
105
|
+
v[term][term2] ||= {}
|
106
|
+
v[term][term2][term3] ||= {}
|
107
|
+
v[term][term2][term3][label] ||= []
|
108
|
+
v[term][term2][term3][label] << t&.at(ns("./target"))&.children&.to_xml
|
109
|
+
t.remove
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def xml_encode_attr(s)
|
114
|
+
HTMLEntities.new.encode(s, :basic, :hexadecimal).gsub(/\&#x([^;]+);/) { |x| "&#x#{$1.upcase};" }
|
115
|
+
end
|
116
|
+
|
117
|
+
# attributes are decoded into UTF-8, elements in extract_indexsee are still in entities
|
118
|
+
def extract_indexterms(terms)
|
119
|
+
terms.each_with_object({}) do |t, v|
|
120
|
+
term = t&.at(ns("./primary"))&.children&.to_xml
|
121
|
+
term2 = t&.at(ns("./secondary"))&.children&.to_xml
|
122
|
+
term3 = t&.at(ns("./tertiary"))&.children&.to_xml
|
123
|
+
index2bookmark(t)
|
124
|
+
v[term] ||= {}
|
125
|
+
v[term][term2] ||= {}
|
126
|
+
v[term][term2][term3] ||= {}
|
127
|
+
v[term][term2][term3][:xref] ||= []
|
128
|
+
to = t["to"] ? "to='#{t['to']}' " : ""
|
129
|
+
v[term][term2][term3][:xref] << "<xref target='#{t['id']}' #{to}pagenumber='true'/>"
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def index2bookmark(t)
|
134
|
+
t.name = "bookmark"
|
135
|
+
t.children.each { |x| x.remove }
|
136
|
+
t["id"] = "_#{UUIDTools::UUID.random_create}"
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|