metanorma-standoc 2.6.0 → 2.6.2

Sign up to get free protection for your applications and to get access to all the features.
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