metanorma-standoc 1.11.3 → 2.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (150) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/rake.yml +3 -31
  3. data/.gitignore +23 -0
  4. data/Gemfile +0 -1
  5. data/lib/asciidoctor/standoc/base.rb +2 -145
  6. data/lib/asciidoctor/standoc/blocks.rb +2 -238
  7. data/lib/asciidoctor/standoc/blocks_notes.rb +2 -100
  8. data/lib/asciidoctor/standoc/cleanup.rb +2 -208
  9. data/lib/asciidoctor/standoc/cleanup_amend.rb +2 -53
  10. data/lib/asciidoctor/standoc/cleanup_block.rb +2 -172
  11. data/lib/asciidoctor/standoc/cleanup_boilerplate.rb +2 -212
  12. data/lib/asciidoctor/standoc/cleanup_footnotes.rb +2 -108
  13. data/lib/asciidoctor/standoc/cleanup_image.rb +2 -69
  14. data/lib/asciidoctor/standoc/cleanup_inline.rb +2 -189
  15. data/lib/asciidoctor/standoc/cleanup_maths.rb +2 -221
  16. data/lib/asciidoctor/standoc/cleanup_ref.rb +2 -169
  17. data/lib/asciidoctor/standoc/cleanup_ref_dl.rb +2 -103
  18. data/lib/asciidoctor/standoc/cleanup_reqt.rb +2 -110
  19. data/lib/asciidoctor/standoc/cleanup_section.rb +2 -184
  20. data/lib/asciidoctor/standoc/cleanup_section_names.rb +2 -91
  21. data/lib/asciidoctor/standoc/cleanup_symbols.rb +2 -47
  22. data/lib/asciidoctor/standoc/cleanup_table.rb +2 -67
  23. data/lib/asciidoctor/standoc/cleanup_terms.rb +2 -139
  24. data/lib/asciidoctor/standoc/cleanup_terms_designations.rb +2 -192
  25. data/lib/asciidoctor/standoc/cleanup_text.rb +2 -95
  26. data/lib/asciidoctor/standoc/cleanup_toc.rb +3 -0
  27. data/lib/asciidoctor/standoc/cleanup_xref.rb +2 -106
  28. data/lib/asciidoctor/standoc/converter.rb +2 -123
  29. data/lib/asciidoctor/standoc/datamodel/attributes_table_preprocessor.rb +2 -56
  30. data/lib/asciidoctor/standoc/datamodel/diagram_preprocessor.rb +2 -102
  31. data/lib/asciidoctor/standoc/datamodel/plantuml_renderer.rb +3 -404
  32. data/lib/asciidoctor/standoc/deprecated.rb +5 -0
  33. data/lib/asciidoctor/standoc/front.rb +2 -219
  34. data/lib/asciidoctor/standoc/front_contributor.rb +2 -191
  35. data/lib/asciidoctor/standoc/inline.rb +2 -231
  36. data/lib/asciidoctor/standoc/lists.rb +2 -119
  37. data/lib/asciidoctor/standoc/macros.rb +2 -203
  38. data/lib/asciidoctor/standoc/macros_form.rb +2 -62
  39. data/lib/asciidoctor/standoc/macros_note.rb +2 -44
  40. data/lib/asciidoctor/standoc/macros_plantuml.rb +2 -112
  41. data/lib/asciidoctor/standoc/macros_terms.rb +2 -180
  42. data/lib/asciidoctor/standoc/ref.rb +2 -251
  43. data/lib/asciidoctor/standoc/ref_sect.rb +2 -153
  44. data/lib/asciidoctor/standoc/ref_utility.rb +2 -0
  45. data/lib/asciidoctor/standoc/render.rb +2 -116
  46. data/lib/asciidoctor/standoc/reqt.rb +2 -89
  47. data/lib/asciidoctor/standoc/section.rb +2 -194
  48. data/lib/asciidoctor/standoc/table.rb +2 -84
  49. data/lib/asciidoctor/standoc/term_lookup_cleanup.rb +2 -178
  50. data/lib/asciidoctor/standoc/terms.rb +2 -153
  51. data/lib/asciidoctor/standoc/utils.rb +2 -100
  52. data/lib/asciidoctor/standoc/validate.rb +2 -157
  53. data/lib/asciidoctor/standoc/validate_section.rb +2 -54
  54. data/lib/isodoc/html/htmlstyle.css +44 -29
  55. data/lib/isodoc/html/htmlstyle.scss +17 -12
  56. data/lib/metanorma/standoc/base.rb +163 -0
  57. data/lib/{asciidoctor → metanorma}/standoc/basicdoc.rng +0 -0
  58. data/lib/{asciidoctor → metanorma}/standoc/biblio.rng +2 -2
  59. data/lib/metanorma/standoc/blocks.rb +239 -0
  60. data/lib/metanorma/standoc/blocks_notes.rb +101 -0
  61. data/lib/metanorma/standoc/cleanup.rb +157 -0
  62. data/lib/metanorma/standoc/cleanup_amend.rb +54 -0
  63. data/lib/metanorma/standoc/cleanup_block.rb +173 -0
  64. data/lib/metanorma/standoc/cleanup_boilerplate.rb +213 -0
  65. data/lib/metanorma/standoc/cleanup_footnotes.rb +109 -0
  66. data/lib/metanorma/standoc/cleanup_image.rb +70 -0
  67. data/lib/metanorma/standoc/cleanup_inline.rb +190 -0
  68. data/lib/metanorma/standoc/cleanup_maths.rb +222 -0
  69. data/lib/metanorma/standoc/cleanup_ref.rb +170 -0
  70. data/lib/metanorma/standoc/cleanup_ref_dl.rb +104 -0
  71. data/lib/metanorma/standoc/cleanup_reqt.rb +111 -0
  72. data/lib/metanorma/standoc/cleanup_section.rb +212 -0
  73. data/lib/metanorma/standoc/cleanup_section_names.rb +92 -0
  74. data/lib/metanorma/standoc/cleanup_symbols.rb +48 -0
  75. data/lib/metanorma/standoc/cleanup_table.rb +68 -0
  76. data/lib/metanorma/standoc/cleanup_terms.rb +140 -0
  77. data/lib/metanorma/standoc/cleanup_terms_designations.rb +199 -0
  78. data/lib/metanorma/standoc/cleanup_text.rb +74 -0
  79. data/lib/metanorma/standoc/cleanup_toc.rb +98 -0
  80. data/lib/metanorma/standoc/cleanup_xref.rb +107 -0
  81. data/lib/metanorma/standoc/converter.rb +126 -0
  82. data/lib/metanorma/standoc/datamodel/attributes_table_preprocessor.rb +57 -0
  83. data/lib/metanorma/standoc/datamodel/diagram_preprocessor.rb +103 -0
  84. data/lib/metanorma/standoc/datamodel/plantuml_renderer.rb +409 -0
  85. data/lib/metanorma/standoc/front.rb +224 -0
  86. data/lib/metanorma/standoc/front_contributor.rb +192 -0
  87. data/lib/metanorma/standoc/inline.rb +232 -0
  88. data/lib/{asciidoctor → metanorma}/standoc/isodoc.rng +104 -3
  89. data/lib/metanorma/standoc/lists.rb +120 -0
  90. data/lib/metanorma/standoc/macros.rb +205 -0
  91. data/lib/metanorma/standoc/macros_embed.rb +72 -0
  92. data/lib/metanorma/standoc/macros_form.rb +63 -0
  93. data/lib/metanorma/standoc/macros_note.rb +45 -0
  94. data/lib/metanorma/standoc/macros_plantuml.rb +113 -0
  95. data/lib/metanorma/standoc/macros_terms.rb +194 -0
  96. data/lib/metanorma/standoc/ref.rb +243 -0
  97. data/lib/metanorma/standoc/ref_sect.rb +153 -0
  98. data/lib/{asciidoctor/standoc/ref_date_id.rb → metanorma/standoc/ref_utility.rb} +43 -5
  99. data/lib/metanorma/standoc/render.rb +115 -0
  100. data/lib/metanorma/standoc/reqt.rb +90 -0
  101. data/lib/{asciidoctor → metanorma}/standoc/reqt.rng +0 -0
  102. data/lib/metanorma/standoc/section.rb +209 -0
  103. data/lib/metanorma/standoc/table.rb +85 -0
  104. data/lib/metanorma/standoc/term_lookup_cleanup.rb +179 -0
  105. data/lib/metanorma/standoc/terms.rb +160 -0
  106. data/lib/metanorma/standoc/utils.rb +101 -0
  107. data/lib/metanorma/standoc/validate.rb +158 -0
  108. data/lib/metanorma/standoc/validate_section.rb +55 -0
  109. data/lib/metanorma/standoc/version.rb +1 -1
  110. data/lib/{asciidoctor → metanorma}/standoc/views/datamodel/model_representation.adoc.erb +0 -0
  111. data/lib/{asciidoctor → metanorma}/standoc/views/datamodel/plantuml_representation.adoc.erb +0 -0
  112. data/lib/metanorma-standoc.rb +1 -1
  113. data/metanorma-standoc.gemspec +1 -1
  114. data/spec/assets/a1.adoc +8 -0
  115. data/spec/assets/a2.adoc +8 -0
  116. data/spec/assets/a3.adoc +9 -0
  117. data/spec/assets/a4.adoc +4 -0
  118. data/spec/{asciidoctor → metanorma}/base_spec.rb +499 -407
  119. data/spec/{asciidoctor → metanorma}/blank_spec.rb +1 -1
  120. data/spec/{asciidoctor → metanorma}/blocks_spec.rb +1 -1
  121. data/spec/{asciidoctor → metanorma}/cleanup_blocks_spec.rb +1 -1
  122. data/spec/{asciidoctor → metanorma}/cleanup_sections_spec.rb +1 -1
  123. data/spec/{asciidoctor → metanorma}/cleanup_spec.rb +5 -5
  124. data/spec/{asciidoctor → metanorma}/cleanup_terms_spec.rb +227 -119
  125. data/spec/{asciidoctor → metanorma}/datamodel/attributes_table_preprocessor_spec.rb +1 -1
  126. data/spec/{asciidoctor → metanorma}/datamodel/diagram_preprocessor_spec.rb +1 -1
  127. data/spec/{asciidoctor → metanorma}/inline_spec.rb +170 -1
  128. data/spec/{asciidoctor → metanorma}/isobib_cache_spec.rb +1 -1
  129. data/spec/{asciidoctor → metanorma}/lists_spec.rb +1 -1
  130. data/spec/{asciidoctor → metanorma}/macros_json2text_spec.rb +0 -0
  131. data/spec/{asciidoctor → metanorma}/macros_plantuml_spec.rb +3 -3
  132. data/spec/{asciidoctor → metanorma}/macros_spec.rb +97 -6
  133. data/spec/{asciidoctor → metanorma}/macros_yaml2text_spec.rb +0 -0
  134. data/spec/metanorma/refs_dl_spec.rb +863 -0
  135. data/spec/{asciidoctor → metanorma}/refs_spec.rb +522 -15
  136. data/spec/{asciidoctor → metanorma}/section_spec.rb +59 -1
  137. data/spec/{asciidoctor → metanorma}/table_spec.rb +1 -1
  138. data/spec/{asciidoctor → metanorma}/validate_spec.rb +2 -2
  139. data/spec/vcr_cassettes/dated_iso_ref_joint_iso_iec.yml +46 -46
  140. data/spec/vcr_cassettes/dated_iso_ref_joint_iso_iec1.yml +12 -12
  141. data/spec/vcr_cassettes/hide_refs.yml +599 -0
  142. data/spec/vcr_cassettes/isobib_get_123.yml +12 -12
  143. data/spec/vcr_cassettes/isobib_get_123_1.yml +24 -24
  144. data/spec/vcr_cassettes/isobib_get_123_1_fr.yml +35 -35
  145. data/spec/vcr_cassettes/isobib_get_123_2001.yml +13 -13
  146. data/spec/vcr_cassettes/isobib_get_124.yml +10 -10
  147. data/spec/vcr_cassettes/rfcbib_get_rfc8341.yml +18 -18
  148. data/spec/vcr_cassettes/separates_iev_citations_by_top_level_clause.yml +46 -46
  149. metadata +88 -32
  150. data/spec/asciidoctor/refs_dl_spec.rb +0 -864
@@ -0,0 +1,157 @@
1
+ require "nokogiri"
2
+ require "pathname"
3
+ require "html2doc"
4
+ require_relative "./cleanup_block"
5
+ require_relative "./cleanup_table"
6
+ require_relative "./cleanup_footnotes"
7
+ require_relative "./cleanup_ref"
8
+ require_relative "./cleanup_ref_dl"
9
+ require_relative "./cleanup_boilerplate"
10
+ require_relative "./cleanup_section"
11
+ require_relative "./cleanup_terms"
12
+ require_relative "./cleanup_symbols"
13
+ require_relative "./cleanup_xref"
14
+ require_relative "./cleanup_inline"
15
+ require_relative "./cleanup_amend"
16
+ require_relative "./cleanup_maths"
17
+ require_relative "./cleanup_image"
18
+ require_relative "./cleanup_reqt"
19
+ require_relative "./cleanup_text"
20
+ require_relative "./cleanup_toc"
21
+ require "relaton_iev"
22
+
23
+ module Metanorma
24
+ module Standoc
25
+ module Cleanup
26
+ def cleanup(xmldoc)
27
+ element_name_cleanup(xmldoc)
28
+ sections_cleanup(xmldoc)
29
+ obligations_cleanup(xmldoc)
30
+ table_cleanup(xmldoc)
31
+ formula_cleanup(xmldoc)
32
+ form_cleanup(xmldoc)
33
+ sourcecode_cleanup(xmldoc)
34
+ figure_cleanup(xmldoc)
35
+ element_name_cleanup(xmldoc)
36
+ ref_cleanup(xmldoc)
37
+ note_cleanup(xmldoc)
38
+ clausebefore_cleanup(xmldoc)
39
+ floatingtitle_cleanup(xmldoc)
40
+ bibitem_cleanup(xmldoc)
41
+ normref_cleanup(xmldoc)
42
+ biblio_cleanup(xmldoc)
43
+ reference_names(xmldoc)
44
+ symbols_cleanup(xmldoc)
45
+ xref_cleanup(xmldoc)
46
+ concept_cleanup(xmldoc)
47
+ related_cleanup(xmldoc)
48
+ origin_cleanup(xmldoc)
49
+ bookmark_cleanup(xmldoc)
50
+ termdef_cleanup(xmldoc)
51
+ RelatonIev::iev_cleanup(xmldoc, @bibdb)
52
+ element_name_cleanup(xmldoc)
53
+ index_cleanup(xmldoc)
54
+ bpart_cleanup(xmldoc)
55
+ quotesource_cleanup(xmldoc)
56
+ callout_cleanup(xmldoc)
57
+ footnote_cleanup(xmldoc)
58
+ mathml_cleanup(xmldoc)
59
+ script_cleanup(xmldoc)
60
+ docidentifier_cleanup(xmldoc)
61
+ requirement_cleanup(xmldoc)
62
+ bibdata_cleanup(xmldoc)
63
+ svgmap_cleanup(xmldoc)
64
+ boilerplate_cleanup(xmldoc)
65
+ toc_cleanup(xmldoc)
66
+ metadata_cleanup(xmldoc)
67
+ smartquotes_cleanup(xmldoc)
68
+ variant_cleanup(xmldoc)
69
+ para_cleanup(xmldoc)
70
+ empty_element_cleanup(xmldoc)
71
+ img_cleanup(xmldoc)
72
+ anchor_cleanup(xmldoc)
73
+ xmldoc
74
+ end
75
+
76
+ def docidentifier_cleanup(xmldoc); end
77
+
78
+ TEXT_ELEMS =
79
+ %w{status language script version author name callout phone email
80
+ street city state country postcode identifier referenceFrom surname
81
+ referenceTo docidentifier docnumber prefix initial addition forename
82
+ title draft secretariat title-main title-intro title-part
83
+ verbal-definition non-verbal-representation}.freeze
84
+
85
+ # it seems Nokogiri::XML is treating the content of <script> as cdata,
86
+ # because of its use in HTML. Bad nokogiri. Undoing that, since we use
87
+ # script as a normal tag
88
+ def script_cleanup(xmldoc)
89
+ xmldoc.xpath("//script").each { |x| x.content = x.to_str }
90
+ end
91
+
92
+ def empty_element_cleanup(xmldoc)
93
+ xmldoc.xpath("//#{TEXT_ELEMS.join(' | //')}").each do |x|
94
+ next if x.name == "name" && x.parent.name == "expression"
95
+
96
+ x.remove if x.children.empty?
97
+ end
98
+ end
99
+
100
+ def element_name_cleanup(xmldoc)
101
+ xmldoc.traverse { |n| n.name = n.name.gsub(/_/, "-") }
102
+ end
103
+
104
+ # allows us to deal with doc relation localities,
105
+ # temporarily stashed to "bpart"
106
+ def bpart_cleanup(xmldoc)
107
+ xmldoc.xpath("//relation/bpart").each do |x|
108
+ extract_localities(x)
109
+ x.replace(x.children)
110
+ end
111
+ end
112
+
113
+ def variant_cleanup(xmldoc)
114
+ variant_space_cleanup(xmldoc)
115
+ xmldoc.xpath("//*[variant]").each do |c|
116
+ next unless c.children.any? do |n|
117
+ n.name != "variant" && (!n.text? || !n.text.gsub(/\s/, "").empty?)
118
+ end
119
+
120
+ variant_cleanup1(c)
121
+ end
122
+ xmldoc.xpath("//variantwrap").each { |n| n.name = "variant" }
123
+ end
124
+
125
+ def variant_cleanup1(elem)
126
+ elem.xpath("./variant").each do |n|
127
+ if n.at_xpath("preceding-sibling::node()"\
128
+ "[not(self::text()[not(normalize-space())])][1]"\
129
+ "[self::variantwrap]")
130
+ n.previous_element << n
131
+ else
132
+ n.replace("<variantwrap/>").first << n
133
+ end
134
+ end
135
+ end
136
+
137
+ def variant_space_cleanup(xmldoc)
138
+ xmldoc.xpath("//*[variant]").each do |c|
139
+ next if c.next.nil? || c.next.next.nil?
140
+
141
+ if c.next.text? && c.next.next.name == "variant"
142
+ c.next.text.gsub(/\s/, "").empty? and
143
+ c.next.remove
144
+ end
145
+ end
146
+ end
147
+
148
+ def metadata_cleanup(xmldoc)
149
+ return if @metadata_attrs.nil? || @metadata_attrs.empty?
150
+
151
+ ins = xmldoc.at("//misc-container") ||
152
+ xmldoc.at("//bibdata").after("<misc-container/>").next_element
153
+ ins << @metadata_attrs
154
+ end
155
+ end
156
+ end
157
+ end
@@ -0,0 +1,54 @@
1
+ module Metanorma
2
+ module Standoc
3
+ module Cleanup
4
+ def change_clauses(x)
5
+ x.xpath("//clause[@change]").each do |c|
6
+ a = create_amend(c)
7
+ end
8
+ end
9
+
10
+ def create_amend(c)
11
+ a = c.add_child("<amend id='_#{UUIDTools::UUID.random_create}'/>").first
12
+ c.elements.each do |e|
13
+ e.parent = a unless %w(amend title).include? e.name
14
+ end
15
+ create_amend1(c, a)
16
+ end
17
+
18
+ def create_amend1(c, a)
19
+ create_amend2(c, a)
20
+ d = a.at("./description")
21
+ d.xpath(".//autonumber").each { |e| d.previous = e }
22
+ d.xpath(".//p[normalize-space(.)='']").each { |e| e.remove }
23
+ move_attrs_to_amend(c, a)
24
+ a
25
+ end
26
+
27
+ def create_amend2(c, a)
28
+ q = a.at("./quote") and q.name = "newcontent"
29
+ if q.nil?
30
+ a.children = "<description>#{a.children.to_xml}</description>"
31
+ else
32
+ pre = q&.xpath("./preceding-sibling::*")&.remove
33
+ post = q&.xpath("./following-sibling::*")&.remove
34
+ pre.empty? or a << "<description>#{pre.to_xml}</description>"
35
+ a << q.remove
36
+ post.empty? or a << "<description>#{post.to_xml}</description>"
37
+ end
38
+ end
39
+
40
+ def move_attrs_to_amend(c, a)
41
+ %w(change path path_end title).each do |e|
42
+ next unless c[e]
43
+ a[e] = c[e]
44
+ c.delete(e)
45
+ end
46
+ return unless a["locality"]
47
+ loc = a.children.add_previous_sibling("<location/>")
48
+ extract_localities1(loc, a["locality"])
49
+ loc1 = loc.at("./localityStack") and loc.replace(loc1.elements)
50
+ a.delete("locality")
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,173 @@
1
+ require "date"
2
+ require "htmlentities"
3
+
4
+ module Metanorma
5
+ module Standoc
6
+ module Cleanup
7
+ def para_cleanup(xmldoc)
8
+ ["//p[not(ancestor::bibdata)]", "//ol[not(ancestor::bibdata)]",
9
+ "//ul[not(ancestor::bibdata)]", "//quote[not(ancestor::bibdata)]",
10
+ "//note[not(ancestor::bibitem or "\
11
+ "ancestor::table or ancestor::bibdata)]"].each do |w|
12
+ inject_id(xmldoc, w)
13
+ end
14
+ end
15
+
16
+ def inject_id(xmldoc, path)
17
+ xmldoc.xpath(path).each do |x|
18
+ x["id"] ||= Metanorma::Utils::anchor_or_uuid
19
+ end
20
+ end
21
+
22
+ # include where definition list inside stem block
23
+ def formula_cleanup(formula)
24
+ formula_cleanup_where1(formula)
25
+ formula_cleanup_where2(formula)
26
+ end
27
+
28
+ def formula_cleanup_where1(formula)
29
+ q = "//formula/following-sibling::*[1][self::dl]"
30
+ formula.xpath(q).each do |s|
31
+ s["key"] == "true" and s.previous_element << s.remove
32
+ end
33
+ end
34
+
35
+ def formula_cleanup_where2(formula)
36
+ q = "//formula/following-sibling::*[1][self::p]"
37
+ formula.xpath(q).each do |s|
38
+ if s.text =~ /^\s*where[^a-z]*$/i && s&.next_element&.name == "dl"
39
+ s.next_element["key"] = "true"
40
+ s.previous_element << s.next_element.remove
41
+ s.remove
42
+ end
43
+ end
44
+ end
45
+
46
+ def figure_dl_cleanup1(xmldoc)
47
+ q = "//figure/following-sibling::*[self::dl]"
48
+ xmldoc.xpath(q).each do |s|
49
+ s["key"] == "true" and s.previous_element << s.remove
50
+ end
51
+ end
52
+
53
+ # include key definition list inside figure
54
+ def figure_dl_cleanup2(xmldoc)
55
+ q = "//figure/following-sibling::*[self::p]"
56
+ xmldoc.xpath(q).each do |s|
57
+ if s.text =~ /^\s*key[^a-z]*$/i && s&.next_element&.name == "dl"
58
+ s.next_element["key"] = "true"
59
+ s.previous_element << s.next_element.remove
60
+ s.remove
61
+ end
62
+ end
63
+ end
64
+
65
+ # examples containing only figures become subfigures of figures
66
+ def subfigure_cleanup(xmldoc)
67
+ xmldoc.xpath("//example[figure]").each do |e|
68
+ next unless e.elements.map(&:name).reject do |m|
69
+ %w(name figure).include? m
70
+ end.empty?
71
+
72
+ e.name = "figure"
73
+ end
74
+ end
75
+
76
+ def figure_cleanup(xmldoc)
77
+ figure_footnote_cleanup(xmldoc)
78
+ figure_dl_cleanup1(xmldoc)
79
+ figure_dl_cleanup2(xmldoc)
80
+ subfigure_cleanup(xmldoc)
81
+ end
82
+
83
+ ELEMS_ALLOW_NOTES = %w[p formula ul ol dl figure].freeze
84
+
85
+ # if a note is at the end of a section, it is left alone
86
+ # if a note is followed by a non-note block,
87
+ # it is moved inside its preceding block if it is not delimited
88
+ # (so there was no way of making that block include the note)
89
+ def note_cleanup(xmldoc)
90
+ q = "//note[following-sibling::*[not(local-name() = 'note')]]"
91
+ xmldoc.xpath(q).each do |n|
92
+ next if n["keep-separate"] == "true" || !n.ancestors("table").empty?
93
+
94
+ prev = n.previous_element || next
95
+ n.parent = prev if ELEMS_ALLOW_NOTES.include? prev.name
96
+ end
97
+ xmldoc.xpath("//note[@keep-separate] | "\
98
+ "//termnote[@keep-separate]").each do |n|
99
+ n.delete("keep-separate")
100
+ end
101
+ end
102
+
103
+ def link_callouts_to_annotations(callouts, annotations)
104
+ callouts.each_with_index do |c, i|
105
+ c["target"] = "_#{UUIDTools::UUID.random_create}"
106
+ annotations[i]["id"] = c["target"]
107
+ end
108
+ end
109
+
110
+ def align_callouts_to_annotations(xmldoc)
111
+ xmldoc.xpath("//sourcecode").each do |x|
112
+ callouts = x.elements.select { |e| e.name == "callout" }
113
+ annotations = x.elements.select { |e| e.name == "annotation" }
114
+ callouts.size == annotations.size and
115
+ link_callouts_to_annotations(callouts, annotations)
116
+ end
117
+ end
118
+
119
+ def merge_annotations_into_sourcecode(xmldoc)
120
+ xmldoc.xpath("//sourcecode").each do |x|
121
+ while x&.next_element&.name == "annotation"
122
+ x.next_element.parent = x
123
+ end
124
+ end
125
+ end
126
+
127
+ def callout_cleanup(xmldoc)
128
+ merge_annotations_into_sourcecode(xmldoc)
129
+ align_callouts_to_annotations(xmldoc)
130
+ end
131
+
132
+ def sourcecode_cleanup(xmldoc)
133
+ xmldoc.xpath("//sourcecode").each do |x|
134
+ x.traverse do |n|
135
+ next unless n.text?
136
+ next unless /#{Regexp.escape(@sourcecode_markup_start)}/
137
+ .match?(n.text)
138
+
139
+ n.replace(sourcecode_markup(n))
140
+ end
141
+ end
142
+ end
143
+
144
+ def safe_noko(text, doc)
145
+ Nokogiri::XML::Text.new(text, doc).to_xml(
146
+ encoding: "US-ASCII",
147
+ save_with: Nokogiri::XML::Node::SaveOptions::NO_DECLARATION,
148
+ )
149
+ end
150
+
151
+ def sourcecode_markup(node)
152
+ node.text.split(/(#{Regexp.escape(@sourcecode_markup_start)}|
153
+ #{Regexp.escape(@sourcecode_markup_end)})/x)
154
+ .each_slice(4).map.with_object([]) do |a, acc|
155
+ acc << safe_noko(a[0], node.document)
156
+ next unless a.size == 4
157
+
158
+ acc << Asciidoctor.convert(
159
+ a[2], doctype: :inline, backend: (self&.backend&.to_sym || :standoc)
160
+ )
161
+ end.join
162
+ end
163
+
164
+ def form_cleanup(xmldoc)
165
+ xmldoc.xpath("//select").each do |s|
166
+ while s&.next_element&.name == "option"
167
+ s << s.next_element
168
+ end
169
+ end
170
+ end
171
+ end
172
+ end
173
+ end
@@ -0,0 +1,213 @@
1
+ module Metanorma
2
+ module Standoc
3
+ module Cleanup
4
+ def external_terms_boilerplate(sources)
5
+ @i18n.l10n(
6
+ @i18n.external_terms_boilerplate.gsub(/%/, sources || "???"),
7
+ @lang, @script
8
+ )
9
+ end
10
+
11
+ def internal_external_terms_boilerplate(sources)
12
+ @i18n.l10n(
13
+ @i18n.internal_external_terms_boilerplate.gsub(/%/, sources || "??"),
14
+ @lang, @script
15
+ )
16
+ end
17
+
18
+ def term_defs_boilerplate(div, source, term, _preface, isodoc)
19
+ a = @i18n.term_def_boilerplate and div.next = a
20
+ source.each do |s|
21
+ @anchors[s["bibitemid"]] or
22
+ @log.add("Crossreferences", nil,
23
+ "term source #{s['bibitemid']} not referenced")
24
+ end
25
+ a = if source.empty? && term.nil?
26
+ @i18n.no_terms_boilerplate
27
+ else
28
+ term_defs_boilerplate_cont(source, term, isodoc)
29
+ end
30
+ a and div.next = a
31
+ end
32
+
33
+ def term_defs_boilerplate_cont(src, term, isodoc)
34
+ sources = isodoc.sentence_join(src.map do |s|
35
+ %{<eref bibitemid="#{s['bibitemid']}"/>}
36
+ end)
37
+ if src.empty? then @i18n.internal_terms_boilerplate
38
+ elsif term.nil? then external_terms_boilerplate(sources)
39
+ else
40
+ internal_external_terms_boilerplate(sources)
41
+ end
42
+ end
43
+
44
+ def norm_ref_preface(ref)
45
+ if ref.at("./note[@type = 'boilerplate']")
46
+ unwrap_boilerplate_clauses(ref, ".")
47
+ else
48
+ refs = ref.elements.select do |e|
49
+ %w(references bibitem).include? e.name
50
+ end
51
+ pref = refs.empty? ? @i18n.norm_empty_pref : @i18n.norm_with_refs_pref
52
+ ref.at("./title").next = "<p>#{pref}</p>"
53
+ end
54
+ end
55
+
56
+ TERM_CLAUSE = "//sections/terms | "\
57
+ "//sections/clause[descendant::terms]".freeze
58
+
59
+ NORM_REF = "//bibliography/references[@normative = 'true'] | "\
60
+ "//bibliography/clause[.//references[@normative = 'true']]"
61
+ .freeze
62
+
63
+ def boilerplate_isodoc(xmldoc)
64
+ x = xmldoc.dup
65
+ x.root.add_namespace(nil, self.class::XML_NAMESPACE)
66
+ xml = Nokogiri::XML(x.to_xml)
67
+ @isodoc ||= isodoc(@lang, @script)
68
+ @isodoc.info(xml, nil)
69
+ @isodoc
70
+ end
71
+
72
+ def termdef_boilerplate_cleanup(xmldoc)
73
+ # termdef_remove_initial_paras(xmldoc)
74
+ end
75
+
76
+ def termdef_remove_initial_paras(xmldoc)
77
+ xmldoc.xpath("//terms/p | //terms/ul").each(&:remove)
78
+ end
79
+
80
+ def unwrap_boilerplate_clauses(xmldoc, xpath)
81
+ xmldoc.xpath(xpath).each do |f|
82
+ f.xpath(".//clause[@type = 'boilerplate'] | "\
83
+ ".//note[@type = 'boilerplate']").each do |c|
84
+ c&.at("./title")&.remove
85
+ c.replace(c.children)
86
+ end
87
+ end
88
+ end
89
+
90
+ def termdef_boilerplate_insert(xmldoc, isodoc, once = false)
91
+ xmldoc.xpath(self.class::TERM_CLAUSE).each do |f|
92
+ next if f.at("./clause[@type = 'boilerplate']")
93
+
94
+ term_defs_boilerplate(f.at("./title"),
95
+ xmldoc.xpath(".//termdocsource"),
96
+ f.at(".//term"), f.at(".//p"), isodoc)
97
+ break if once
98
+ end
99
+ end
100
+
101
+ def boilerplate_cleanup(xmldoc)
102
+ isodoc = boilerplate_isodoc(xmldoc)
103
+ termdef_boilerplate_cleanup(xmldoc)
104
+ termdef_boilerplate_insert(xmldoc, isodoc)
105
+ unwrap_boilerplate_clauses(xmldoc, self.class::TERM_CLAUSE)
106
+ f = xmldoc.at(self.class::NORM_REF) and norm_ref_preface(f)
107
+ initial_boilerplate(xmldoc, isodoc)
108
+ end
109
+
110
+ def initial_boilerplate(xml, isodoc)
111
+ return if xml.at("//boilerplate")
112
+
113
+ preface = xml.at("//preface") || xml.at("//sections") ||
114
+ xml.at("//annex") || xml.at("//references") || return
115
+ b = boilerplate(xml, isodoc) or return
116
+ preface.previous = b
117
+ end
118
+
119
+ def boilerplate_file(_xmldoc)
120
+ File.join(@libdir, "boilerplate.xml")
121
+ end
122
+
123
+ def boilerplate(xml, conv)
124
+ file = boilerplate_file(xml)
125
+ if @boilerplateauthority
126
+ file = File.join(@localdir,
127
+ @boilerplateauthority)
128
+ end
129
+ (!file.nil? and File.exists?(file)) or return
130
+ conv.populate_template(File.read(file, encoding: "UTF-8"), nil)
131
+ end
132
+
133
+ def bibdata_cleanup(xmldoc)
134
+ bibdata_anchor_cleanup(xmldoc)
135
+ bibdata_docidentifier_cleanup(xmldoc)
136
+ biblio_indirect_erefs(xmldoc, @internal_eref_namespaces&.uniq)
137
+ end
138
+
139
+ def bibdata_anchor_cleanup(xmldoc)
140
+ xmldoc.xpath("//bibdata//bibitem | //bibdata//note").each do |b|
141
+ b.delete("id")
142
+ end
143
+ end
144
+
145
+ def bibdata_docidentifier_cleanup(xmldoc)
146
+ ins = xmldoc.at("//bibdata/docidentifier")
147
+ xmldoc.xpath("//bibdata/docidentifier").each_with_index do |b, i|
148
+ next if i.zero?
149
+
150
+ ins.next = b.remove
151
+ ins = ins.next
152
+ end
153
+ end
154
+
155
+ def gather_indirect_erefs(xmldoc, prefix)
156
+ xmldoc.xpath("//eref[@type = '#{prefix}']")
157
+ .each_with_object({}) do |e, m|
158
+ e.delete("type")
159
+ m[e["bibitemid"]] = true
160
+ end.keys
161
+ end
162
+
163
+ def insert_indirect_biblio(xmldoc, refs, prefix)
164
+ ins = xmldoc.at("bibliography") or
165
+ xmldoc.root << "<bibliography/>" and ins = xmldoc.at("bibliography")
166
+ ins = ins.add_child("<references hidden='true' normative='false'/>").first
167
+ refs.each do |x|
168
+ ins << <<~BIB
169
+ <bibitem id="#{x}" type="internal">
170
+ <docidentifier type="repository">#{x.sub(/^#{prefix}_/, "#{prefix}/")}</docidentifier>
171
+ </bibitem>
172
+ BIB
173
+ end
174
+ end
175
+
176
+ def indirect_eref_to_xref(eref, ident)
177
+ loc = eref&.at("./localityStack[locality[@type = 'anchor']]")
178
+ &.remove&.text ||
179
+ eref&.at("./locality[@type = 'anchor']")&.remove&.text || ident
180
+ eref.name = "xref"
181
+ eref.delete("bibitemid")
182
+ eref.delete("citeas")
183
+ eref["target"] = loc
184
+ unless eref.document.at("//*[@id = '#{loc}']")
185
+ eref.children = %(** Missing target #{loc})
186
+ eref["target"] = ident
187
+ end
188
+ end
189
+
190
+ def resolve_local_indirect_erefs(xmldoc, refs, prefix)
191
+ refs.each_with_object([]) do |r, m|
192
+ id = r.sub(/^#{prefix}_/, "")
193
+ if n = xmldoc.at("//*[@id = '#{id}']") and
194
+ n.at("./ancestor-or-self::*[@type = '#{prefix}']")
195
+ xmldoc.xpath("//eref[@bibitemid = '#{r}']").each do |e|
196
+ indirect_eref_to_xref(e, id)
197
+ end
198
+ else m << r
199
+ end
200
+ end
201
+ end
202
+
203
+ def biblio_indirect_erefs(xmldoc, prefixes)
204
+ prefixes&.each do |prefix|
205
+ refs = gather_indirect_erefs(xmldoc, prefix)
206
+ refs = resolve_local_indirect_erefs(xmldoc, refs, prefix)
207
+ refs.empty? and next
208
+ insert_indirect_biblio(xmldoc, refs, prefix)
209
+ end
210
+ end
211
+ end
212
+ end
213
+ end