metanorma-standoc 2.6.0 → 2.6.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6a9ee49a9aa313dae428fb537106a5da2c369f24da90074725e9e9a11bf4e75b
4
- data.tar.gz: 6439d160874d60c6c7d41d5ed5bcc5480a842479b3b9e203db314360abf2063f
3
+ metadata.gz: bd044342634fd4dd1a67955a5f07785ae4762a0f63520e8254efe6e016853b1a
4
+ data.tar.gz: 89625dee3748cca3301727fc88650b0f916b8d2f60a258a9731ac09783c2465a
5
5
  SHA512:
6
- metadata.gz: e7cfd27c5a9c81fbe673f9041b209ad691286a7ce217a647bde009eb1981b4cead8c89972bb7738f666bdd2c874db284d030329f9c64e952f176952ce62d44bc
7
- data.tar.gz: 72e727e0016b53616c39dd22a66508b08d6f5a36044e7690670b05574a4632187c1e69ddd6ea09aa6238a8b934352ddfc653c1e79c026b62249369de51ec2be0
6
+ metadata.gz: 9958565ebd72f63b2a17af3f6cc89d5055d36f77ba15f4b80763ca64f3d45368b084e321ef05b0f49655943df029556a1ddd1c9cf27a7466299977b48aee57cc
7
+ data.tar.gz: 3979efde78ee18714f49a321ce89c51aa2039cc153863d118ddc788d610fae7788134688454bff075a9c95ace5bb097e5b24b169df9877f17a4321632b230b14
@@ -178,7 +178,7 @@ module Metanorma
178
178
  end
179
179
 
180
180
  def clean_exit
181
- @novalid or @log.write("#{@output_dir}#{@filename}.err")
181
+ @novalid or @log.write("#{@output_dir}#{@filename}.err.html")
182
182
  @files_to_delete.each { |f| FileUtils.rm f }
183
183
  end
184
184
 
@@ -346,6 +346,8 @@
346
346
  <ref name="keyword"/>
347
347
  <ref name="xref"/>
348
348
  <ref name="hyperlink"/>
349
+ <ref name="index"/>
350
+ <ref name="index-xref"/>
349
351
  </choice>
350
352
  </oneOrMore>
351
353
  </element>
@@ -623,6 +625,8 @@
623
625
  <ref name="eref"/>
624
626
  <ref name="xref"/>
625
627
  <ref name="hyperlink"/>
628
+ <ref name="index"/>
629
+ <ref name="index-xref"/>
626
630
  </choice>
627
631
  </zeroOrMore>
628
632
  </element>
@@ -636,6 +640,8 @@
636
640
  <ref name="eref"/>
637
641
  <ref name="xref"/>
638
642
  <ref name="hyperlink"/>
643
+ <ref name="index"/>
644
+ <ref name="index-xref"/>
639
645
  </choice>
640
646
  </zeroOrMore>
641
647
  </element>
@@ -648,6 +654,8 @@
648
654
  <ref name="eref"/>
649
655
  <ref name="xref"/>
650
656
  <ref name="hyperlink"/>
657
+ <ref name="index"/>
658
+ <ref name="index-xref"/>
651
659
  </choice>
652
660
  </zeroOrMore>
653
661
  </element>
@@ -655,7 +663,11 @@
655
663
  <define name="keyword">
656
664
  <element name="keyword">
657
665
  <zeroOrMore>
658
- <ref name="PureTextElement"/>
666
+ <choice>
667
+ <ref name="PureTextElement"/>
668
+ <ref name="index"/>
669
+ <ref name="index-xref"/>
670
+ </choice>
659
671
  </zeroOrMore>
660
672
  </element>
661
673
  </define>
@@ -676,7 +688,11 @@
676
688
  <define name="strike">
677
689
  <element name="strike">
678
690
  <zeroOrMore>
679
- <ref name="PureTextElement"/>
691
+ <choice>
692
+ <ref name="PureTextElement"/>
693
+ <ref name="index"/>
694
+ <ref name="index-xref"/>
695
+ </choice>
680
696
  </zeroOrMore>
681
697
  </element>
682
698
  </define>
@@ -1283,7 +1283,7 @@
1283
1283
  <value>mergedInto</value>
1284
1284
  <value>splits</value>
1285
1285
  <value>splitInto</value>
1286
- <value>instance</value>
1286
+ <value>instanceOf</value>
1287
1287
  <value>hasInstance</value>
1288
1288
  <value>exemplarOf</value>
1289
1289
  <value>hasExemplar</value>
@@ -45,7 +45,7 @@ module Metanorma
45
45
  element_name_cleanup(xmldoc)
46
46
  ref_cleanup(xmldoc) # feeds: bibitem_cleanup
47
47
  note_cleanup(xmldoc)
48
- clausebefore_cleanup(xmldoc)
48
+ clausebefore_cleanup(xmldoc) # feeeds: floatingtitle_cleanup
49
49
  floatingtitle_cleanup(xmldoc)
50
50
  bibitem_cleanup(xmldoc) # feeds: normref_cleanup, biblio_cleanup,
51
51
  # reference_names, bpart_cleanup
@@ -86,16 +86,33 @@ module Metanorma
86
86
  end
87
87
 
88
88
  def termdef_boilerplate_insert(xmldoc, isodoc, once = false)
89
- xmldoc.xpath(self.class::TERM_CLAUSE).each do |f|
90
- f.at("./clause[@type = 'boilerplate'] | " \
91
- "./note[@type = 'boilerplate']") and next
92
- term_defs_boilerplate(f.at("./title"),
93
- xmldoc.xpath(".//termdocsource"),
94
- f.at(".//term"), f.at(".//p"), isodoc)
95
- once and break
89
+ if once
90
+ f = termdef_boilerplate_insert_location(xmldoc) and
91
+ termdef_boilerplate_insert1(f, xmldoc, isodoc)
92
+ else
93
+ xmldoc.xpath(self.class::TERM_CLAUSE).each do |f|
94
+ termdef_boilerplate_insert1(f, xmldoc, isodoc)
95
+ end
96
96
  end
97
97
  end
98
98
 
99
+ def termdef_boilerplate_insert_location(xmldoc)
100
+ f = xmldoc.at(self.class::TERM_CLAUSE)
101
+ root = xmldoc.at("//sections/terms | //sections/clause[.//terms]")
102
+ !f || !root and return f || root
103
+ f.at("./following::terms") and return root
104
+ f.at("./preceding-sibling::clause") and return root
105
+ f
106
+ end
107
+
108
+ def termdef_boilerplate_insert1(sect, xmldoc, isodoc)
109
+ sect.at("./clause[@type = 'boilerplate'] | " \
110
+ "./note[@type = 'boilerplate']") and return
111
+ term_defs_boilerplate(sect.at("./title"),
112
+ xmldoc.xpath(".//termdocsource"),
113
+ sect.at(".//term"), sect.at(".//p"), isodoc)
114
+ end
115
+
99
116
  def boilerplate_cleanup(xmldoc)
100
117
  isodoc = boilerplate_isodoc(xmldoc)
101
118
  termdef_boilerplate_cleanup(xmldoc)
@@ -178,8 +178,8 @@ module Metanorma
178
178
  end
179
179
 
180
180
  def clausebefore_cleanup(xmldoc)
181
- preface_clausebefore_cleanup(xmldoc)
182
181
  sections_clausebefore_cleanup(xmldoc)
182
+ preface_clausebefore_cleanup(xmldoc)
183
183
  end
184
184
 
185
185
  def preface_clausebefore_cleanup(xmldoc)
@@ -196,10 +196,20 @@ module Metanorma
196
196
  end
197
197
 
198
198
  def sections_clausebefore_cleanup(xmldoc)
199
- return unless xmldoc.at("//sections")
200
-
199
+ xmldoc.at("//sections") or return
201
200
  ins = insert_before(xmldoc, "//sections")
202
- xmldoc.xpath("//sections//*[@beforeclauses = 'true']").each do |x|
201
+ xmldoc.xpath("//sections//*[@beforeclauses = 'true']").reverse.each do |x|
202
+ x.delete("beforeclauses")
203
+ ins.previous = x.remove
204
+ end
205
+ endofpreface_clausebefore(xmldoc, ins)
206
+ end
207
+
208
+ # only move clausebefore notes at the very end of preface
209
+ def endofpreface_clausebefore(xmldoc, ins)
210
+ xmldoc.xpath("//preface//*[@beforeclauses = 'true']").reverse.each do |x|
211
+ textafternote = xmldoc.xpath("//preface//*") & x.xpath("./following::*")
212
+ textafternote.text.strip.empty? or break
203
213
  x.delete("beforeclauses")
204
214
  ins.previous = x.remove
205
215
  end
@@ -214,6 +224,7 @@ module Metanorma
214
224
  end
215
225
 
216
226
  def floatingtitle_cleanup(xmldoc)
227
+ pop_floating_title(xmldoc) # done again, after endofpreface_clausebefore
217
228
  floating_title_preface2sections(xmldoc)
218
229
  end
219
230
 
@@ -50,10 +50,30 @@ module Metanorma
50
50
  "[not(.//definitions[@type = 'symbols'])]".freeze
51
51
 
52
52
  def section_names_terms_cleanup(xml)
53
- replace_title(xml, "//definitions[@type = 'symbols']", @i18n&.symbols)
53
+ section_names_definitions(xml)
54
+ section_names_terms1_cleanup(xml)
55
+ end
56
+
57
+ def section_names_definitions(xml)
58
+ auto_name_definitions(xml) or return
59
+ replace_title(xml, "//definitions[@type = 'symbols']",
60
+ @i18n&.symbols)
54
61
  replace_title(xml, "//definitions[@type = 'abbreviated_terms']",
55
62
  @i18n&.abbrev)
56
- replace_title(xml, "//definitions[not(@type)]", @i18n&.symbolsabbrev)
63
+ replace_title(xml, "//definitions[not(@type)]",
64
+ @i18n&.symbolsabbrev)
65
+ end
66
+
67
+ def auto_name_definitions(xml)
68
+ xml.xpath("//definitions[@type = 'symbols']").size > 1 and return false
69
+ xml.xpath("//definitions[@type = 'abbreviated_terms']").size > 1 and
70
+ return false
71
+ xml.xpath("//definitions[not(@type)]").size > 1 and return false
72
+ true
73
+ end
74
+
75
+ def section_names_terms1_cleanup(xml)
76
+ auto_name_terms(xml) or return
57
77
  replace_title(xml, "//terms#{SYMnoABBR} | //clause[.//terms]#{SYMnoABBR}",
58
78
  @i18n&.termsdefsymbols, true)
59
79
  replace_title(xml, "//terms#{ABBRnoSYM} | //clause[.//terms]#{ABBRnoSYM}",
@@ -69,6 +89,54 @@ module Metanorma
69
89
  )
70
90
  end
71
91
 
92
+ # do not auto-name terms sections if there are terms subclauses
93
+ # not covered by the auto titles,
94
+ # or if more than one title is covered by an auto title
95
+ def auto_name_terms(xml)
96
+ n = xml.at("//terms | //clause[.//terms]")
97
+ out = terms_subclauses(n)
98
+ .each_with_object({ term: 0, sna: 0, ans: 0, sa: 0, nsa: 0,
99
+ tsna: 0, tans: 0, tsa: 0, tnsa: 0,
100
+ termdef: 0, other: 0 }) do |x, m|
101
+ terms_subclause_type_tally(x, m, n)
102
+ end
103
+ out.delete(:parent)
104
+ !out.values.detect { |x| x > 1 } && out[:other].zero?
105
+ end
106
+
107
+ def terms_subclauses(node)
108
+ legal = %w(terms definitions clause)
109
+ [node, node&.elements].compact.flatten
110
+ .select do |x|
111
+ legal.include?(x.name) &&
112
+ !(x.name == "clause" && x["type"] == "boilerplate")
113
+ end
114
+ end
115
+
116
+ def terms_subclause_type_tally(node, m, parent)
117
+ sym = if (node.at(".//term") && !node.at(".//definitions")) ||
118
+ (node.name == "terms" && !node.at(".//term"))
119
+ unless m[:parent] == :term # don't count Term > Term twice
120
+ :term
121
+ end
122
+ elsif node.at(".//term") && node.at("./self::*#{SYMnoABBR}") then :tsna
123
+ elsif node.at(".//term") && node.at("./self::*#{ABBRnoSYM}") then :tans
124
+ elsif node.at(".//term") && node.at("./self::*#{SYMABBR}") then :tsa
125
+ elsif node.at(".//term") && node.at("./self::*#{NO_SYMABBR}") then :tnsa
126
+ elsif node.at("./self::*#{SYMnoABBR}") then :sna
127
+ elsif node.at("./self::*#{ABBRnoSYM}") then :ans
128
+ elsif node.at("./self::*#{SYMABBR}") then :sa
129
+ elsif node.at("./self::*#{NO_SYMABBR}") then :nsa
130
+ elsif node.name == "definitions" # ignore
131
+ elsif node == parent && node.at(".//term") &&
132
+ node.at(".//definitions")
133
+ :termdef
134
+ else :other
135
+ end
136
+ node == parent and m[:parent] = sym
137
+ sym and m[sym] += 1
138
+ end
139
+
72
140
  SECTION_CONTAINERS = %w(foreword introduction acknowledgements abstract
73
141
  clause clause references terms definitions annex
74
142
  appendix).freeze
@@ -63,6 +63,7 @@ module Metanorma
63
63
  treeprocessor Metanorma::Standoc::ToDoInlineAdmonitionBlock
64
64
  block Metanorma::Standoc::PlantUMLBlockMacro
65
65
  block Metanorma::Standoc::PseudocodeBlockMacro
66
+ block_macro Metanorma::Standoc::ColumnBreakBlockMacro
66
67
  end
67
68
 
68
69
  include ::Asciidoctor::Converter
@@ -17,7 +17,7 @@
17
17
  these elements; we just want one namespace for any child grammars
18
18
  of this.
19
19
  -->
20
- <!-- VERSION v1.2.4 -->
20
+ <!-- VERSION v1.2.6 -->
21
21
  <grammar xmlns:a="http://relaxng.org/ns/compatibility/annotations/1.0" xmlns="http://relaxng.org/ns/structure/1.0" datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
22
22
  <include href="reqt.rng"/>
23
23
  <include href="basicdoc.rng">
@@ -485,6 +485,8 @@
485
485
  <choice>
486
486
  <text/>
487
487
  <ref name="callout"/>
488
+ <ref name="xref"/>
489
+ <ref name="eref"/>
488
490
  </choice>
489
491
  </oneOrMore>
490
492
  <zeroOrMore>
@@ -865,6 +867,7 @@
865
867
  <ref name="PureTextElement"/>
866
868
  <ref name="stem"/>
867
869
  <ref name="index"/>
870
+ <ref name="index-xref"/>
868
871
  <ref name="eref"/>
869
872
  <ref name="erefstack"/>
870
873
  <ref name="xref"/>
@@ -880,6 +883,7 @@
880
883
  <ref name="PureTextElement"/>
881
884
  <ref name="stem"/>
882
885
  <ref name="index"/>
886
+ <ref name="index-xref"/>
883
887
  <ref name="eref"/>
884
888
  <ref name="erefstack"/>
885
889
  <ref name="xref"/>
@@ -894,6 +898,7 @@
894
898
  <choice>
895
899
  <ref name="PureTextElement"/>
896
900
  <ref name="index"/>
901
+ <ref name="index-xref"/>
897
902
  <ref name="eref"/>
898
903
  <ref name="erefstack"/>
899
904
  <ref name="xref"/>
@@ -908,6 +913,7 @@
908
913
  <choice>
909
914
  <ref name="PureTextElement"/>
910
915
  <ref name="index"/>
916
+ <ref name="index-xref"/>
911
917
  </choice>
912
918
  </zeroOrMore>
913
919
  </element>
@@ -918,6 +924,7 @@
918
924
  <choice>
919
925
  <ref name="PureTextElement"/>
920
926
  <ref name="index"/>
927
+ <ref name="index-xref"/>
921
928
  </choice>
922
929
  </zeroOrMore>
923
930
  </element>
@@ -928,6 +935,7 @@
928
935
  <choice>
929
936
  <ref name="PureTextElement"/>
930
937
  <ref name="index"/>
938
+ <ref name="index-xref"/>
931
939
  </choice>
932
940
  </zeroOrMore>
933
941
  </element>
@@ -938,6 +946,7 @@
938
946
  <choice>
939
947
  <ref name="PureTextElement"/>
940
948
  <ref name="index"/>
949
+ <ref name="index-xref"/>
941
950
  </choice>
942
951
  </zeroOrMore>
943
952
  </element>
@@ -1004,6 +1013,14 @@
1004
1013
  </oneOrMore>
1005
1014
  </element>
1006
1015
  </define>
1016
+ <define name="BasicBlock" combine="choice">
1017
+ <ref name="columnbreak"/>
1018
+ </define>
1019
+ <define name="columnbreak">
1020
+ <element name="columnbreak">
1021
+ <empty/>
1022
+ </element>
1023
+ </define>
1007
1024
  <define name="MultilingualRenderingType">
1008
1025
  <choice>
1009
1026
  <value>common</value>
@@ -1047,6 +1064,8 @@
1047
1064
  <ref name="keyword"/>
1048
1065
  <ref name="xref"/>
1049
1066
  <ref name="hyperlink"/>
1067
+ <ref name="index"/>
1068
+ <ref name="index-xref"/>
1050
1069
  </choice>
1051
1070
  </element>
1052
1071
  </define>
@@ -1060,6 +1079,8 @@
1060
1079
  <ref name="keyword"/>
1061
1080
  <ref name="xref"/>
1062
1081
  <ref name="hyperlink"/>
1082
+ <ref name="index"/>
1083
+ <ref name="index-xref"/>
1063
1084
  </choice>
1064
1085
  </element>
1065
1086
  </define>
@@ -1126,6 +1147,8 @@
1126
1147
  <choice>
1127
1148
  <ref name="PureTextElement"/>
1128
1149
  <ref name="stem"/>
1150
+ <ref name="index"/>
1151
+ <ref name="index-xref"/>
1129
1152
  </choice>
1130
1153
  </zeroOrMore>
1131
1154
  </element>
@@ -1136,6 +1159,8 @@
1136
1159
  <choice>
1137
1160
  <ref name="PureTextElement"/>
1138
1161
  <ref name="stem"/>
1162
+ <ref name="index"/>
1163
+ <ref name="index-xref"/>
1139
1164
  </choice>
1140
1165
  </zeroOrMore>
1141
1166
  </element>
@@ -61,6 +61,15 @@ module Metanorma
61
61
  end
62
62
  end
63
63
 
64
+ class ColumnBreakBlockMacro < Asciidoctor::Extensions::BlockMacroProcessor
65
+ use_dsl
66
+ named :columnbreak
67
+
68
+ def process(parent, _reader, _attrs)
69
+ create_pass_block parent, "<columnbreak/>", {}, subs: nil
70
+ end
71
+ end
72
+
64
73
  # refer https://github.com/asciidoctor/asciidoctor/blob/main/lib/asciidoctor/substitutors.rb
65
74
  # Not using TreeProcessor because that is still too close to
66
75
  # inline expressions being processed on access (e.g. titles)
@@ -47,7 +47,7 @@ module Metanorma
47
47
  end
48
48
 
49
49
  def merge_simple(old, new, field)
50
- new[field].blank? and return
50
+ (new[field].nil? || new[field].empty?) and return
51
51
  old[field] = new[field]
52
52
  end
53
53
 
@@ -77,12 +77,10 @@ module Metanorma
77
77
  # @old.field is an array, overwrite only those array elements
78
78
  # where @old.field[attribute] = @new.field[attribute]
79
79
  def merge_by_type(old, new, field, attributes, opt = {})
80
- new.nil? || new[field].blank? and return
80
+ new.nil? || new[field].nil? || new[field].empty? and return
81
81
  old.nil? and return new[field]
82
- if !old[field].is_a?(::Array) || old[field].empty?
82
+ !old[field].is_a?(::Array) || old[field].empty? and
83
83
  return old[field] = new[field]
84
- end
85
-
86
84
  old[field] = merge_by_type1(old, new, field, attributes, opt)
87
85
  end
88
86
 
@@ -32,6 +32,7 @@ module Metanorma
32
32
  end
33
33
 
34
34
  def output(isodoc_node, inname, outname, format, options = {})
35
+ options_preprocess(options)
35
36
  case format
36
37
  when :html
37
38
  options = options
@@ -1,4 +1,5 @@
1
1
  require_relative "ref_utility"
2
+ require_relative "ref_queue"
2
3
 
3
4
  module Metanorma
4
5
  module Standoc
@@ -226,42 +227,6 @@ module Metanorma
226
227
  when 3 then isorefmatches3out(item, xml)
227
228
  end
228
229
  end
229
-
230
- def reference(node)
231
- refs = node.items.each_with_object([]) do |b, m|
232
- m << reference1code(b.text, node)
233
- end
234
- reference_populate(reference_normalise(refs))
235
- end
236
-
237
- def reference_normalise(refs)
238
- refs.each do |r|
239
- r[:code] = @c.decode(r[:code])
240
- .gsub("\u2009\u2014\u2009", " -- ").strip
241
- end
242
- end
243
-
244
- def reference_populate(refs)
245
- results = refs.each_with_index.with_object(Queue.new) do |(ref, i), res|
246
- fetch_ref_async(ref.merge(ord: i), i, res)
247
- end
248
- ret = reference_queue(refs, results)
249
- noko do |xml|
250
- ret.each { |b| reference1out(b, xml) }
251
- end.join
252
- end
253
-
254
- def reference_queue(refs, results)
255
- refs.each.with_object([]) do |_, m|
256
- ref, i, doc = results.pop
257
- m[i.to_i] = { ref: ref }
258
- if doc.is_a?(RelatonBib::RequestError)
259
- @log.add("Bibliography", nil, "Could not retrieve #{ref[:code]}: " \
260
- "no access to online site")
261
- else m[i.to_i][:doc] = doc
262
- end
263
- end
264
- end
265
230
  end
266
231
  end
267
232
  end
@@ -0,0 +1,243 @@
1
+ module Metanorma
2
+ module Standoc
3
+ module Refs
4
+ def reference(node)
5
+ refs = node.items.each_with_object([]) do |b, m|
6
+ m << reference1code(b.text, node)
7
+ end
8
+ reference_populate(reference_normalise(refs))
9
+ end
10
+
11
+ def reference_normalise(refs)
12
+ refs.each do |r|
13
+ r[:code] = @c.decode(r[:code])
14
+ .gsub("\u2009\u2014\u2009", " -- ").strip
15
+ end
16
+ end
17
+
18
+ def reference_populate(refs)
19
+ ret = reference_queue(*references_fetch(refs))
20
+ joint_prep = joint_entries_prep(ret)
21
+ out = references2xml(ret)
22
+ joint_entries(out, joint_prep).compact.map { |x| to_xml(x) }.join
23
+ end
24
+
25
+ def references2xml(ret)
26
+ out = ret.map do |b|
27
+ b.nil? ? nil : noko { |xml| reference1out(b, xml) }.join
28
+ end
29
+ out.map { |x| x.nil? ? nil : Nokogiri::XML(x).root }
30
+ end
31
+
32
+ def references_fetch(refs)
33
+ i = 0
34
+ ret = refs.each_with_object(Queue.new) do |ref, res|
35
+ i = fetch_ref_async(ref.merge(ord: i), i, res)
36
+ end
37
+ [ret, i]
38
+ end
39
+
40
+ def reference_queue(results, size)
41
+ (1..size).each.with_object([]) do |_, m|
42
+ ref, i, doc = results.pop
43
+ m[i.to_i] = { ref: ref }
44
+ if doc.is_a?(RelatonBib::RequestError)
45
+ @log.add("Bibliography", nil, "Could not retrieve #{ref[:code]}: " \
46
+ "no access to online site")
47
+ else m[i.to_i][:doc] = doc end
48
+ end
49
+ end
50
+
51
+ def joint_entries(out, joint_prep)
52
+ joint_prep.each do |k, v|
53
+ v[:merge]&.each do |i|
54
+ merge_entries(out[k], out[i]) and out[i] = nil
55
+ end
56
+ v[:dual]&.each do |i|
57
+ dual_entries(out[k], out[i]) and out[i] = nil
58
+ end
59
+ end
60
+ out
61
+ end
62
+
63
+ # append publishers docids of add to base
64
+ def merge_entries(base, add)
65
+ merge_publishers(base, add)
66
+ merge_docids(base, add)
67
+ merge_urls(base, add)
68
+ end
69
+
70
+ def merge_publishers(base, add)
71
+ ins = base.at("//contributor[last()]") || base.children[-1]
72
+ add.xpath("//contributor[role/@type = 'publisher']").reverse.each do |p|
73
+ ins.next = p
74
+ end
75
+ end
76
+
77
+ def merge_docids(base, add)
78
+ ins = base.at("//docidentifier[last()]")
79
+ [ins, add].each do |v|
80
+ v.at("//docidentifier[@primary = 'true']") or
81
+ v.at("//docidentifier")["primary"] = true
82
+ end
83
+ add.xpath("//docidentifier").reverse.each do |p|
84
+ ins.next = p
85
+ end
86
+ end
87
+
88
+ def merge_urls(base, add)
89
+ ins = base.at("./uri[last()]") || base.at("./title[last()]")
90
+ add.xpath("./uri").reverse.each do |p|
91
+ ins.next = p
92
+ end
93
+ end
94
+
95
+ def dual_entries(base, add)
96
+ ins = docrelation_insert(base)
97
+ ins.next = "<relation type='hasReproduction'>#{to_xml(add)}</relation>"
98
+ end
99
+
100
+ def docrelation_insert(base)
101
+ %w(relation copyright status abstract locale language note version
102
+ edition contributor date docnumber docidentifier).each do |v|
103
+ r = base.at("//#{v}[last()]") and return r
104
+ end
105
+ end
106
+
107
+ JOINT_REFS = %i(merge dual).freeze
108
+
109
+ def joint_entries_prep(out)
110
+ out.each_with_object({}) do |r, m|
111
+ JOINT_REFS.each do |v|
112
+ if i = r&.dig(:ref, "#{v}_into".to_sym)
113
+ m[i] ||= { "#{v}": [] }
114
+ m[i][v][r[:ref][:merge_order]] = r[:ref][:ord]
115
+ end
116
+ end
117
+ end
118
+ end
119
+
120
+ def global_ievcache_name
121
+ "#{Dir.home}/.iev/cache"
122
+ end
123
+
124
+ def local_ievcache_name(cachename)
125
+ return nil if cachename.nil?
126
+
127
+ cachename += "_iev" unless cachename.empty?
128
+ cachename = "iev" if cachename.empty?
129
+ "#{cachename}/cache"
130
+ end
131
+
132
+ def fetch_ref(xml, code, year, **opts)
133
+ return nil if opts[:no_year]
134
+
135
+ code = code.sub(/^\([^)]+\)/, "")
136
+ hit = fetch_ref1(code, year, opts) or return nil
137
+ xml.parent.add_child(smart_render_xml(hit, code, opts))
138
+ xml
139
+ rescue RelatonBib::RequestError
140
+ @log.add("Bibliography", nil, "Could not retrieve #{code}: " \
141
+ "no access to online site")
142
+ nil
143
+ end
144
+
145
+ def supply_ref_prefix(ret)
146
+ ret
147
+ end
148
+
149
+ def fetch_ref1(code, year, opts)
150
+ code = supply_ref_prefix(code)
151
+ if opts[:localfile]
152
+ @local_bibdb.get(code, opts[:localfile])
153
+ else @bibdb&.fetch(code, year, opts)
154
+ end
155
+ end
156
+
157
+ def unfetchable_ref_code?(ref)
158
+ ref[:code].nil? || ref[:code].empty? || ref[:no_year] ||
159
+ /^\(.+\)$/.match?(ref[:code]) ||
160
+ (@bibdb.nil? && !ref[:localfile])
161
+ end
162
+
163
+ def fetch_ref_async(ref, idx, res)
164
+ ref[:code] &&= supply_ref_prefix(ref[:code])
165
+ if unfetchable_ref_code?(ref)
166
+ res << [ref, idx, nil]
167
+ idx += 1
168
+ elsif ref[:localfile]
169
+ res << [ref, idx, @local_bibdb.get(ref[:code], ref[:localfile])]
170
+ idx += 1
171
+ else idx = fetch_ref_async1(ref, idx, res)
172
+ end
173
+ idx
174
+ end
175
+
176
+ def fetch_ref_async1(ref, idx, res)
177
+ @bibdb.fetch_async(ref[:code], ref[:year], ref) do |doc|
178
+ res << [ref, idx, doc]
179
+ end
180
+ fetch_ref_async_dual(ref, idx, idx + 1, res)
181
+ end
182
+
183
+ def fetch_ref_async_dual(ref, orig, idx, res)
184
+ JOINT_REFS.each do |m|
185
+ ref.dig(:analyse_code, m)&.each_with_index do |code, i|
186
+ @bibdb.fetch_async(code, nil, ref.merge(ord: idx)) do |doc|
187
+ res << [ref.merge("#{m}_into": orig, merge_order: i, ord: idx),
188
+ idx, doc]
189
+ end
190
+ idx += 1
191
+ end
192
+ end
193
+ idx
194
+ end
195
+
196
+ def smart_render_xml(xml, code, opts)
197
+ xml.respond_to? :to_xml or return nil
198
+ xml = Nokogiri::XML(xml.to_xml(lang: opts[:lang]))
199
+ emend_biblio(xml, code, opts[:title], opts[:usrlbl])
200
+ xml.xpath("//date").each { |d| Metanorma::Utils::endash_date(d) }
201
+ xml.traverse do |n|
202
+ n.text? and n.replace(Metanorma::Utils::smartformat(n.text))
203
+ end
204
+ xml.to_xml.sub(/<\?[^>]+>/, "")
205
+ end
206
+
207
+ def use_retrieved_relaton(item, xml)
208
+ xml.parent.add_child(smart_render_xml(item[:doc], item[:ref][:code],
209
+ item[:ref]))
210
+ use_my_anchor(xml, item[:ref][:match][:anchor],
211
+ hidden: item.dig(:ref, :analyse_code, :hidden),
212
+ dropid: item.dig(:ref, :analyse_code, :dropid))
213
+ end
214
+
215
+ def init_bib_caches(node)
216
+ return if @no_isobib
217
+
218
+ global = !@no_isobib_cache && !node.attr("local-cache-only")
219
+ local = node.attr("local-cache") || node.attr("local-cache-only")
220
+ local = nil if @no_isobib_cache
221
+ @bibdb = Relaton::Db.init_bib_caches(
222
+ local_cache: local,
223
+ flush_caches: node.attr("flush-caches"),
224
+ global_cache: global,
225
+ )
226
+ end
227
+
228
+ def init_iev_caches(node)
229
+ unless @no_isobib_cache || @no_isobib
230
+ node.attr("local-cache-only") or
231
+ @iev_globalname = global_ievcache_name
232
+ @iev_localname = local_ievcache_name(node.attr("local-cache") ||
233
+ node.attr("local-cache-only"))
234
+ if node.attr("flush-caches")
235
+ FileUtils.rm_f @iev_globalname unless @iev_globalname.nil?
236
+ FileUtils.rm_f @iev_localname unless @iev_localname.nil?
237
+ end
238
+ end
239
+ # @iev = Iev::Db.new(globalname, localname) unless @no_isobib
240
+ end
241
+ end
242
+ end
243
+ end
@@ -53,59 +53,6 @@ module Metanorma
53
53
  end
54
54
  end
55
55
 
56
- def global_ievcache_name
57
- "#{Dir.home}/.iev/cache"
58
- end
59
-
60
- def local_ievcache_name(cachename)
61
- return nil if cachename.nil?
62
-
63
- cachename += "_iev" unless cachename.empty?
64
- cachename = "iev" if cachename.empty?
65
- "#{cachename}/cache"
66
- end
67
-
68
- def fetch_ref(xml, code, year, **opts)
69
- return nil if opts[:no_year]
70
-
71
- code = code.sub(/^\([^)]+\)/, "")
72
- hit = fetch_ref1(code, year, opts) or return nil
73
- xml.parent.add_child(smart_render_xml(hit, code, opts))
74
- xml
75
- rescue RelatonBib::RequestError
76
- @log.add("Bibliography", nil, "Could not retrieve #{code}: " \
77
- "no access to online site")
78
- nil
79
- end
80
-
81
- def fetch_ref1(code, year, opts)
82
- if opts[:localfile]
83
- @local_bibdb.get(code, opts[:localfile])
84
- else @bibdb&.fetch(code, year, opts)
85
- end
86
- end
87
-
88
- def unfetchable_ref_code?(ref)
89
- ref[:code].nil? || ref[:code].empty? || ref[:no_year] ||
90
- /^\(.+\)$/.match?(ref[:code]) ||
91
- (@bibdb.nil? && !ref[:localfile])
92
- end
93
-
94
- def fetch_ref_async(ref, idx, res)
95
- if unfetchable_ref_code?(ref)
96
- res << [ref, idx, nil]
97
- elsif ref[:localfile]
98
- res << [ref, idx, @local_bibdb.get(ref[:code], ref[:localfile])]
99
- else fetch_ref_async1(ref, idx, res)
100
- end
101
- end
102
-
103
- def fetch_ref_async1(ref, idx, res)
104
- @bibdb.fetch_async(ref[:code], ref[:year], ref) do |doc|
105
- res << [ref, idx, doc]
106
- end
107
- end
108
-
109
56
  def emend_biblio(xml, code, title, usrlbl)
110
57
  emend_biblio_id(xml, code)
111
58
  emend_biblio_title(xml, code, title)
@@ -138,52 +85,6 @@ module Metanorma
138
85
  xml.at("/bibitem/docidentifier").next =
139
86
  "<docidentifier type='metanorma'>#{mn_code(usrlbl)}</docidentifier>"
140
87
  end
141
-
142
- def smart_render_xml(xml, code, opts)
143
- xml.respond_to? :to_xml or return nil
144
- xml = Nokogiri::XML(xml.to_xml(lang: opts[:lang]))
145
- emend_biblio(xml, code, opts[:title], opts[:usrlbl])
146
- xml.xpath("//date").each { |d| Metanorma::Utils::endash_date(d) }
147
- xml.traverse do |n|
148
- n.text? and n.replace(Metanorma::Utils::smartformat(n.text))
149
- end
150
- xml.to_xml.sub(/<\?[^>]+>/, "")
151
- end
152
-
153
- def use_retrieved_relaton(item, xml)
154
- xml.parent.add_child(smart_render_xml(item[:doc], item[:ref][:code],
155
- item[:ref]))
156
- use_my_anchor(xml, item[:ref][:match][:anchor],
157
- hidden: item.dig(:ref, :analyse_code, :hidden),
158
- dropid: item.dig(:ref, :analyse_code, :dropid))
159
- end
160
-
161
- def init_bib_caches(node)
162
- return if @no_isobib
163
-
164
- global = !@no_isobib_cache && !node.attr("local-cache-only")
165
- local = node.attr("local-cache") || node.attr("local-cache-only")
166
- local = nil if @no_isobib_cache
167
- @bibdb = Relaton::Db.init_bib_caches(
168
- local_cache: local,
169
- flush_caches: node.attr("flush-caches"),
170
- global_cache: global,
171
- )
172
- end
173
-
174
- def init_iev_caches(node)
175
- unless @no_isobib_cache || @no_isobib
176
- node.attr("local-cache-only") or
177
- @iev_globalname = global_ievcache_name
178
- @iev_localname = local_ievcache_name(node.attr("local-cache") ||
179
- node.attr("local-cache-only"))
180
- if node.attr("flush-caches")
181
- FileUtils.rm_f @iev_globalname unless @iev_globalname.nil?
182
- FileUtils.rm_f @iev_localname unless @iev_localname.nil?
183
- end
184
- end
185
- # @iev = Iev::Db.new(globalname, localname) unless @no_isobib
186
- end
187
88
  end
188
89
  end
189
90
  end
@@ -69,43 +69,46 @@ module Metanorma
69
69
  def analyse_ref_localfile(ret)
70
70
  m = /^local-file\((?:(?<source>[^,]+),\s*)?(?<id>.+)\)$/.match(ret[:id])
71
71
  m or return ret
72
-
73
72
  ret.merge(id: m[:id], localfile: (m[:source] || "default"))
74
73
  end
75
74
 
76
75
  def analyse_ref_nofetch(ret)
77
- return ret unless m = /^nofetch\((?<id>.+)\)$/.match(ret[:id])
78
-
76
+ m = /^nofetch\((?<id>.+)\)$/.match(ret[:id]) or return ret
79
77
  ret.merge(id: m[:id], nofetch: true)
80
78
  end
81
79
 
82
80
  def analyse_ref_hidden(ret)
83
- return ret unless m = /^hidden\((?<id>.+)\)$/.match(ret[:id])
84
-
81
+ m = /^hidden\((?<id>.+)\)$/.match(ret[:id]) or return ret
85
82
  ret.merge(id: m[:id], hidden: true)
86
83
  end
87
84
 
88
85
  def analyse_ref_dropid(ret)
89
- return ret unless m = /^dropid\((?<id>.+)\)$/.match(ret[:id])
90
-
86
+ m = /^dropid\((?<id>.+)\)$/.match(ret[:id]) or return ret
91
87
  ret.merge(id: m[:id], dropid: true)
92
88
  end
93
89
 
94
90
  def analyse_ref_repo_path(ret)
95
- return ret unless m =
96
- /^(?<type>repo|path):\((?<key>[^,]+),?(?<id>.*)\)$/
97
- .match(ret[:id])
98
-
91
+ m = /^(?<type>repo|path):\((?<key>[^,]+),?(?<id>.*)\)$/
92
+ .match(ret[:id]) or return ret
99
93
  id = m[:id].empty? ? m[:key].sub(%r{^[^/]+/}, "") : m[:id]
100
94
  ret.merge(id: id, type: m[:type], key: m[:key], nofetch: true)
101
95
  end
102
96
 
103
97
  def analyse_ref_numeric(ret)
104
- return ret unless /^\d+$/.match?(ret[:id])
105
-
98
+ /^\d+$/.match?(ret[:id]) or return ret
106
99
  ret.merge(numeric: true)
107
100
  end
108
101
 
102
+ def analyse_ref_dual(ret)
103
+ m = /^(?<type>merge|dual)\((?<keys>.+)\)$/.match(ret[:id]) or
104
+ return ret
105
+ line = CSV.parse_line(m[:keys], liberal_parsing: true) or return ret
106
+ line.size > 1 or return ret
107
+ ret[:id] = line.first
108
+ ret[m[:type].to_sym] = line[1..-1].map(&:strip)
109
+ ret
110
+ end
111
+
109
112
  def analyse_ref_code(code)
110
113
  ret = { id: code }
111
114
  code.nil? || code.empty? and return ret
@@ -157,13 +160,16 @@ module Metanorma
157
160
 
158
161
  # ref id = (usrlbl)code[:-]year
159
162
  # code = \[? number \]? | ident | nofetch(code) | hidden(code) |
160
- # dropid(code) | # (repo|path):(key,code) | local-file(source,? key)
163
+ # dropid(code) | # (repo|path):(key,code) | local-file(source,? key) |
164
+ # merge(code, code) | dual(code, code)
161
165
  def analyse_ref_code_nested(ret)
162
- analyse_ref_numeric(
163
- analyse_ref_repo_path(
164
- analyse_ref_dropid(
165
- analyse_ref_hidden(
166
- analyse_ref_nofetch(analyse_ref_localfile(ret)),
166
+ analyse_ref_dual(
167
+ analyse_ref_numeric(
168
+ analyse_ref_repo_path(
169
+ analyse_ref_dropid(
170
+ analyse_ref_hidden(
171
+ analyse_ref_nofetch(analyse_ref_localfile(ret)),
172
+ ),
167
173
  ),
168
174
  ),
169
175
  ),
@@ -193,12 +199,12 @@ module Metanorma
193
199
  REF
194
200
 
195
201
  def ref_normalise(ref)
196
- ref.gsub(/&amp;amp;/, "&amp;").gsub(%r{^<em>(.*)</em>}, "\\1")
202
+ ref.gsub("&amp;amp;", "&amp;").gsub(%r{^<em>(.*)</em>}, "\\1")
197
203
  end
198
204
 
199
205
  def ref_normalise_no_format(ref)
200
- ref.gsub(/&amp;amp;/, "&amp;")
201
- .gsub(/>\n/, "> \n")
206
+ ref.gsub("&amp;amp;", "&amp;")
207
+ .gsub(">\n", "> \n")
202
208
  end
203
209
 
204
210
  def skip_docid
@@ -91,7 +91,7 @@ module Metanorma
91
91
  pdf-allow-print pdf-allow-print-hq
92
92
  pdf-allow-access-content pdf-encrypt-metadata fonts
93
93
  font-license-agreement).each_with_object({}) do |x, m|
94
- m[x.gsub(/-/, "").to_i] = node.attr(x)
94
+ m[x.gsub("-", "").to_i] = node.attr(x)
95
95
  end
96
96
 
97
97
  pdf_options.merge(fonts_manifest_option(node) || {})
@@ -102,7 +102,9 @@ module Metanorma
102
102
  end
103
103
 
104
104
  def presentation_xml_converter(node)
105
- IsoDoc::PresentationXMLConvert.new(html_extract_attributes(node))
105
+ IsoDoc::PresentationXMLConvert
106
+ .new(html_extract_attributes(node)
107
+ .merge(output_formats: ::Metanorma::Standoc::Processor.new.output_formats) )
106
108
  end
107
109
 
108
110
  def default_fonts(node)
@@ -19,6 +19,6 @@ module Metanorma
19
19
  end
20
20
 
21
21
  module Standoc
22
- VERSION = "2.6.0".freeze
22
+ VERSION = "2.6.2".freeze
23
23
  end
24
24
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: metanorma-standoc
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.6.0
4
+ version: 2.6.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-09-11 00:00:00.000000000 Z
11
+ date: 2023-10-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: addressable
@@ -514,6 +514,7 @@ files:
514
514
  - lib/metanorma/standoc/merge_bibitems.rb
515
515
  - lib/metanorma/standoc/processor.rb
516
516
  - lib/metanorma/standoc/ref.rb
517
+ - lib/metanorma/standoc/ref_queue.rb
517
518
  - lib/metanorma/standoc/ref_sect.rb
518
519
  - lib/metanorma/standoc/ref_utility.rb
519
520
  - lib/metanorma/standoc/render.rb