metanorma-standoc 2.0.3 → 2.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/lib/metanorma/standoc/base.rb +61 -22
  3. data/lib/metanorma/standoc/blocks.rb +3 -3
  4. data/lib/metanorma/standoc/cleanup_boilerplate.rb +3 -3
  5. data/lib/metanorma/standoc/cleanup_ref.rb +31 -2
  6. data/lib/metanorma/standoc/cleanup_ref_dl.rb +20 -16
  7. data/lib/metanorma/standoc/cleanup_section.rb +1 -1
  8. data/lib/metanorma/standoc/cleanup_terms_designations.rb +4 -2
  9. data/lib/metanorma/standoc/cleanup_xref.rb +70 -8
  10. data/lib/metanorma/standoc/converter.rb +1 -0
  11. data/lib/metanorma/standoc/inline.rb +21 -12
  12. data/lib/metanorma/standoc/isodoc.rng +63 -3
  13. data/lib/metanorma/standoc/macros.rb +13 -1
  14. data/lib/metanorma/standoc/macros_embed.rb +1 -1
  15. data/lib/metanorma/standoc/ref.rb +5 -6
  16. data/lib/metanorma/standoc/render.rb +7 -3
  17. data/lib/metanorma/standoc/table.rb +8 -10
  18. data/lib/metanorma/standoc/term_lookup_cleanup.rb +2 -1
  19. data/lib/metanorma/standoc/utils.rb +3 -1
  20. data/lib/metanorma/standoc/version.rb +1 -1
  21. data/spec/metanorma/base_spec.rb +1 -1
  22. data/spec/metanorma/cleanup_spec.rb +10 -10
  23. data/spec/metanorma/cleanup_terms_spec.rb +1 -1
  24. data/spec/metanorma/inline_spec.rb +31 -0
  25. data/spec/metanorma/macros_plantuml_spec.rb +41 -42
  26. data/spec/metanorma/macros_spec.rb +138 -2
  27. data/spec/metanorma/processor_spec.rb +17 -13
  28. data/spec/metanorma/refs_spec.rb +129 -2
  29. data/spec/vcr_cassettes/dated_iso_ref_joint_iso_iec.yml +45 -45
  30. data/spec/vcr_cassettes/dated_iso_ref_joint_iso_iec1.yml +10 -10
  31. data/spec/vcr_cassettes/hide_refs.yml +39 -39
  32. data/spec/vcr_cassettes/isobib_get_123.yml +12 -12
  33. data/spec/vcr_cassettes/isobib_get_123_1.yml +23 -23
  34. data/spec/vcr_cassettes/isobib_get_123_1_fr.yml +28 -28
  35. data/spec/vcr_cassettes/isobib_get_123_2001.yml +11 -11
  36. data/spec/vcr_cassettes/isobib_get_124.yml +12 -12
  37. data/spec/vcr_cassettes/rfcbib_get_rfc8341.yml +18 -18
  38. data/spec/vcr_cassettes/separates_iev_citations_by_top_level_clause.yml +75 -65
  39. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cc4b55c7be36492191bd86bc19646a520c76e94bd2e2af9f96cf0d80d25fb05e
4
- data.tar.gz: 533fc5380552ab239528a559ee41a47c246203e17cb33df64cb5cdef5df21f34
3
+ metadata.gz: 48ca241528c217b9b563a2d3f6f2e13b52f2fa24e679ca2de431ebde8d10fb98
4
+ data.tar.gz: f6b70cd60a959376474a35ef4d364f69f9e15fd6582a53571a71cec995d90a01
5
5
  SHA512:
6
- metadata.gz: adc2d0b10dd30e5f59060b20574701dc6049b25a9d25eff06557ac51ca66645f62b553517690380009460f01fe135d26e83ab653b81c7746209e8f55221c3703
7
- data.tar.gz: 8bc78cf1ab42e80d93c8a22f0028e44e7ba735914fa43c2dcdd5eb53cb57b3a3ee52ea1677cae5033dbc738f8b444bc0dc2e5021ff08a443d991535c84c373b2
6
+ metadata.gz: f175a4b49b2aa24d8c8b566a6929401f1a61fb217cf2ee03b506d93482a086afb7b09c85e7c6d88c93d1ef57d41e5a79dc6122bf41624842118dfa75759823b4
7
+ data.tar.gz: c395e93a7f1d3c03c63f1063f1689beb3e1725b81d26b2b38769038d491e8fade8462ab1b2f3b6324eede90c7e03b1473ce40873b903fd3859852436d69e7a9a
@@ -31,48 +31,65 @@ module Metanorma
31
31
  @refids = Set.new
32
32
  @anchors = {}
33
33
  @internal_eref_namespaces = []
34
+ @seen_headers = []
34
35
  @draft = node.attributes.has_key?("draft")
35
36
  @novalid = node.attr("novalid")
36
37
  @smartquotes = node.attr("smartquotes") != "false"
37
38
  @keepasciimath = node.attr("mn-keep-asciimath") &&
38
39
  node.attr("mn-keep-asciimath") != "false"
39
- @fontheader = default_fonts(node)
40
- @files_to_delete = []
41
- @filename = if node.attr("docfile")
42
- File.basename(node.attr("docfile"))&.gsub(/\.adoc$/, "")
43
- else ""
44
- end
45
- @localdir = Metanorma::Utils::localdir(node)
46
- @output_dir = outputdir node
47
- @no_isobib_cache = node.attr("no-isobib-cache")
48
- @no_isobib = node.attr("no-isobib")
49
40
  @index_terms = node.attr("index-terms")
50
41
  @sourcecode_markup_start = node.attr("sourcecode-markup-start") || "{{{"
51
42
  @sourcecode_markup_end = node.attr("sourcecode-markup-end") || "}}}"
52
- @bibdb = nil
53
- @seen_headers = []
54
43
  @datauriimage = node.attr("data-uri-image") != "false"
55
44
  @boilerplateauthority = node.attr("boilerplate-authority")
56
45
  @sourcecode_markup_start = node.attr("sourcecode-markup-start") || "{{{"
57
46
  @sourcecode_markup_end = node.attr("sourcecode-markup-end") || "}}}"
47
+ init_toc(node)
48
+ init_output(node)
49
+ init_i18n(node)
50
+ init_biblio(node)
51
+ @metadata_attrs = metadata_attrs(node)
52
+ end
53
+
54
+ def init_toc(node)
55
+ @htmltoclevels = node.attr("htmltoclevels")
56
+ @doctoclevels = node.attr("doctoclevels")
57
+ @toclevels = node.attr("toclevels")
58
+ @tocfigures = node.attr("toc-figures")
59
+ @toctables = node.attr("toc-tables")
60
+ @tocrecommendations = node.attr("toc-recommendations")
61
+ end
62
+
63
+ def init_output(node)
64
+ @fontheader = default_fonts(node)
58
65
  @log = Metanorma::Utils::Log.new
59
- init_bib_caches(node)
60
- init_iev_caches(node)
66
+ @files_to_delete = []
67
+ @filename = if node.attr("docfile")
68
+ File.basename(node.attr("docfile"))&.gsub(/\.adoc$/, "")
69
+ else ""
70
+ end
71
+ @localdir = Metanorma::Utils::localdir(node)
72
+ @output_dir = outputdir node
73
+ end
74
+
75
+ def init_i18n(node)
61
76
  @lang = (node.attr("language") || "en")
62
77
  @script = (node.attr("script") ||
63
78
  Metanorma::Utils.default_script(node.attr("language")))
64
79
  @isodoc = isodoc(@lang, @script, node.attr("i18nyaml"))
65
80
  @i18n = @isodoc.i18n
66
- @htmltoclevels = node.attr("htmltoclevels")
67
- @doctoclevels = node.attr("doctoclevels")
68
- @toclevels = node.attr("toclevels")
69
- @metadata_attrs = metadata_attrs(node)
81
+ end
82
+
83
+ def init_biblio(node)
84
+ @no_isobib_cache = node.attr("no-isobib-cache")
85
+ @no_isobib = node.attr("no-isobib")
86
+ @bibdb = nil
87
+ init_bib_caches(node)
88
+ init_iev_caches(node)
70
89
  end
71
90
 
72
91
  def document(node)
73
- init(node)
74
- ret = makexml(node).to_xml(encoding: "UTF-8", indent: 2)
75
- outputs(node, ret) unless node.attr("nodoc") || !node.attr("docfile")
92
+ ret = document1(node)
76
93
  clean_exit
77
94
  ret
78
95
  rescue StandardError => e
@@ -81,6 +98,28 @@ module Metanorma
81
98
  raise e
82
99
  end
83
100
 
101
+ def document1(node)
102
+ init(node)
103
+ ret = makexml(node)
104
+ .to_xml(encoding: "UTF-8", indent: 2,
105
+ save_with: Nokogiri::XML::Node::SaveOptions::AS_XML)
106
+ outputs(node, ret) unless node.attr("nodoc") || !node.attr("docfile")
107
+ ret
108
+ end
109
+
110
+ def insert_xml_cr(doc)
111
+ doc
112
+ .gsub(%r{(</(clause|table|figure|p|bibitem|ul|ol|dl|dt|dd|li|example|
113
+ sourcecode|formula|quote|references|annex|appendix|title|
114
+ name|note|thead|tbody|tfoot|th|td|form|requirement|
115
+ recommendation|permission|imagemap|svgmap|preferred|
116
+ admitted|related|deprecates|letter-symbol|domain|
117
+ graphical-symbol|expression|abbreviation-type|subject|
118
+ pronunciation|grammar|term|terms|termnote|termexample|
119
+ termsource|origin|termref|modification)>)}x, "\\1\n")
120
+ .gsub(%r{(<(title|name))}x, "\n\\1")
121
+ end
122
+
84
123
  def version
85
124
  flavour = self.class.name.sub(/::Converter$/, "").sub(/^.+::/, "")
86
125
  Metanorma.versioned(Metanorma, flavour)[-1]::VERSION
@@ -110,7 +149,7 @@ module Metanorma
110
149
 
111
150
  def makexml(node)
112
151
  result = makexml1(node)
113
- ret1 = cleanup(Nokogiri::XML(result))
152
+ ret1 = cleanup(Nokogiri::XML(insert_xml_cr(result)))
114
153
  ret1.root.add_namespace(nil, xml_namespace)
115
154
  validate(ret1) unless @novalid
116
155
  ret1
@@ -174,11 +174,11 @@ module Metanorma
174
174
  def paragraph(node)
175
175
  return termsource(node) if node.role == "source"
176
176
 
177
- noko do |xml|
177
+ ret = noko do |xml|
178
178
  xml.p **para_attrs(node) do |xml_t|
179
179
  xml_t << node.content
180
180
  end
181
- end.join("\n")
181
+ end.join
182
182
  end
183
183
 
184
184
  def quote_attrs(node)
@@ -203,7 +203,7 @@ module Metanorma
203
203
  quote_attribution(node, q)
204
204
  wrap_in_para(node, q)
205
205
  end
206
- end.join("\n")
206
+ end.join
207
207
  end
208
208
 
209
209
  def listing_attrs(node)
@@ -56,9 +56,9 @@ module Metanorma
56
56
  TERM_CLAUSE = "//sections/terms | "\
57
57
  "//sections/clause[descendant::terms]".freeze
58
58
 
59
- NORM_REF = "//bibliography/references[@normative = 'true'] | "\
60
- "//bibliography/clause[.//references[@normative = 'true']]"
61
- .freeze
59
+ NORM_REF =
60
+ "//bibliography/references[@normative = 'true'][not(@hidden)] | "\
61
+ "//bibliography/clause[.//references[@normative = 'true']]".freeze
62
62
 
63
63
  def boilerplate_isodoc(xmldoc)
64
64
  x = xmldoc.dup
@@ -16,7 +16,7 @@ module Metanorma
16
16
  insert = refs&.at("./bibitem")&.previous_element
17
17
  refs.xpath("./bibitem").each(&:remove)
18
18
  bib.reverse.each do |b|
19
- insert and insert.next = b.to_xml or
19
+ (insert and insert.next = b.to_xml) or
20
20
  refs.children.first.add_previous_sibling b.to_xml
21
21
  end
22
22
  extract_notes_from_biblio(refs)
@@ -84,9 +84,39 @@ module Metanorma
84
84
  biblio_reorder(xmldoc)
85
85
  biblio_nested(xmldoc)
86
86
  biblio_renumber(xmldoc)
87
+ biblio_linkonly(xmldoc)
88
+ biblio_hidden_inherit(xmldoc)
87
89
  biblio_no_ext(xmldoc)
88
90
  end
89
91
 
92
+ def biblio_hidden_inherit(xmldoc)
93
+ xmldoc.xpath("//references[@hidden = 'true']").each do |r|
94
+ r.xpath("./bibitem").each do |b|
95
+ b["hidden"] = true
96
+ end
97
+ end
98
+ end
99
+
100
+ def biblio_linkonly(xmldoc)
101
+ return unless xmldoc.at("//xref[@hidden]")
102
+
103
+ ins = xmldoc.at("//bibliography")
104
+ .add_child("<references hidden='true' normative='true'/>").first
105
+ refs = xmldoc.xpath("//xref[@hidden]").each_with_object([]) do |x, m|
106
+ @refids << x["target"]
107
+ m << { id: x["target"], ref: x["hidden"] }
108
+ x.delete("hidden")
109
+ end
110
+ ins << insert_hidden_bibitems(refs)
111
+ end
112
+
113
+ def insert_hidden_bibitems(bib)
114
+ refs = bib.each_with_object([]) do |b, m|
115
+ m << reference1code(%(<ref id="#{b[:id]}">[#{b[:ref]}]</ref>), nil)
116
+ end
117
+ reference_populate(refs)
118
+ end
119
+
90
120
  def biblio_no_ext(xmldoc)
91
121
  xmldoc.xpath("//bibitem/ext").each(&:remove)
92
122
  end
@@ -114,7 +144,6 @@ module Metanorma
114
144
 
115
145
  def reference_names(xmldoc)
116
146
  xmldoc.xpath("//bibitem[not(ancestor::bibitem)]").each do |ref|
117
- # isopub = ref.at(ISO_PUBLISHER_XPATH)
118
147
  docid = ref.at("./docidentifier[@type = 'metanorma']") ||
119
148
  ref.at("./docidentifier[not(@type = 'DOI')]") or next
120
149
  reference = format_ref(docid.children.to_xml, docid["type"])
@@ -15,19 +15,20 @@ module Metanorma
15
15
  end
16
16
  end
17
17
 
18
- def validate_ref_dl(bib, c)
18
+ def validate_ref_dl(bib, clause)
19
19
  id = bib["id"]
20
- id ||= c["id"] unless /^_/.match?(c["id"]) # do not accept implicit id
20
+ # do not accept implicit id
21
+ id ||= clause["id"] unless /^_/.match?(clause["id"])
21
22
  unless id
22
- @log.add("Anchors", c,
23
- "The following reference is missing an anchor:\n" + c.to_xml)
23
+ @log.add("Anchors", clause,
24
+ "The following reference is missing an anchor:\n#{clause.to_xml}")
24
25
  return
25
26
  end
26
27
  @refids << id
27
28
  bib["title"] or
28
- @log.add("Bibliography", c, "Reference #{id} is missing a title")
29
+ @log.add("Bibliography", clause, "Reference #{id} is missing a title")
29
30
  bib["docid"] or
30
- @log.add("Bibliography", c,
31
+ @log.add("Bibliography", clause,
31
32
  "Reference #{id} is missing a document identifier (docid)")
32
33
  end
33
34
 
@@ -76,27 +77,30 @@ module Metanorma
76
77
  end
77
78
 
78
79
  # definition list, with at most one level of unordered lists
79
- def dl_bib_extract(c, nested = false)
80
- dl = c.at("./dl") or return
80
+ def dl_bib_extract(clause, nested = false)
81
+ dl = clause.at("./dl") or return
81
82
  bib = {}
82
83
  key = ""
83
84
  dl.xpath("./dt | ./dd").each do |dtd|
84
85
  (dtd.name == "dt" and key = dtd.text.sub(/:+$/, "")) or
85
86
  add_to_hash(bib, key, dd_bib_extract(dtd))
86
87
  end
87
- c.xpath("./clause").each do |c1|
88
+ clause.xpath("./clause").each do |c1|
88
89
  key = c1&.at("./title")&.text&.downcase&.strip
89
90
  next unless %w(contributor relation series).include? key
90
91
 
91
92
  add_to_hash(bib, key, dl_bib_extract(c1, true))
92
93
  end
93
- if !nested && c.at("./title")
94
- title = c.at("./title").remove.children.to_xml
95
- bib["title"] = [bib["title"]] if bib["title"].is_a? Hash
96
- bib["title"] = [bib["title"]] if bib["title"].is_a? String
97
- bib["title"] = [] unless bib["title"]
98
- bib["title"] << title if !title.empty?
99
- end
94
+ dl_bib_extract_title(bib, clause, nested)
95
+ end
96
+
97
+ def dl_bib_extract_title(bib, clause, nested)
98
+ (!nested && clause.at("./title")) or return bib
99
+ title = clause.at("./title").remove.children.to_xml
100
+ bib["title"] = [bib["title"]] if bib["title"].is_a?(Hash) ||
101
+ bib["title"].is_a?(String)
102
+ bib["title"] = [] unless bib["title"]
103
+ bib["title"] << title if !title.empty?
100
104
  bib
101
105
  end
102
106
  end
@@ -54,7 +54,7 @@ module Metanorma
54
54
  end
55
55
 
56
56
  def make_bibliography(xml, sect)
57
- if xml.at("//sections/references")
57
+ if xml.at("//sections/references | //xref[@hidden]")
58
58
  biblio = sect.add_next_sibling("<bibliography/>").first
59
59
  xml.xpath("//sections/references").each do |r|
60
60
  biblio.add_child r.remove
@@ -182,10 +182,12 @@ module Metanorma
182
182
 
183
183
  def term_designation_reorder(xmldoc)
184
184
  xmldoc.xpath("//term").each do |t|
185
- %w(preferred admitted deprecates related)
185
+ des = %w(preferred admitted deprecates related)
186
186
  .each_with_object([]) do |tag, m|
187
187
  t.xpath("./#{tag}").each { |x| m << x.remove }
188
- end.reverse.each do |x|
188
+ end.reverse
189
+ t << " "
190
+ des.each do |x|
189
191
  t.children.first.previous = x
190
192
  end
191
193
  end
@@ -3,11 +3,12 @@ module Metanorma
3
3
  module Cleanup
4
4
  # extending localities to cover ISO referencing
5
5
  LOCALITY_REGEX_STR = <<~REGEXP.freeze
6
- ^((?<locality>section|clause|part|paragraph|chapter|page|
6
+ ^(((?<conn>and|or|from|to)!)?
7
+ (?<locality>section|clause|part|paragraph|chapter|page|
7
8
  table|annex|figure|example|note|formula|list|time|anchor|
8
9
  locality:[^ \\t\\n\\r:,;=]+)(\\s+|=)
9
- (?<ref>[^"][^ \\t\\n,:-]*|"[^"]+")
10
- (-(?<to>[^"][^ \\t\\n,:-]*|"[^"]"))?|
10
+ (?<ref>[^"][^ \\t\\n,:;-]*|"[^"]+")
11
+ (-(?<to>[^"][^ \\t\\n,:;-]*|"[^"]"))?|
11
12
  (?<locality2>whole|locality:[^ \\t\\n\\r:,;=]+))(?<punct>[,:;]?)\\s*
12
13
  (?<text>.*)$
13
14
  REGEXP
@@ -30,16 +31,37 @@ module Metanorma
30
31
  def extract_localities1(elem, text)
31
32
  b = elem.add_child("<localityStack/>").first if LOCALITY_RE.match text
32
33
  while (m = LOCALITY_RE.match text)
33
- ref = m[:ref] ? "<referenceFrom>#{tq m[:ref]}</referenceFrom>" : ""
34
- refto = m[:to] ? "<referenceTo>#{tq m[:to]}</referenceTo>" : ""
35
- b.add_child("<locality type='#{locality_label(m)}'>#{ref}#{refto}"\
36
- "</locality>")
34
+ add_locality(b, m)
37
35
  text = m[:text]
38
36
  b = elem.add_child("<localityStack/>").first if m[:punct] == ";"
39
37
  end
38
+ fill_in_eref_connectives(elem)
40
39
  elem.add_child(text) if text
41
40
  end
42
41
 
42
+ def add_locality(stack, match)
43
+ stack.children.empty? && match[:conn] and
44
+ stack["connective"] = match[:conn]
45
+ ref =
46
+ match[:ref] ? "<referenceFrom>#{tq match[:ref]}</referenceFrom>" : ""
47
+ refto = match[:to] ? "<referenceTo>#{tq match[:to]}</referenceTo>" : ""
48
+ stack.add_child("<locality type='#{locality_label(match)}'>#{ref}"\
49
+ "#{refto}</locality>")
50
+ end
51
+
52
+ def fill_in_eref_connectives(elem)
53
+ return if elem.xpath("./localityStack").size < 2
54
+
55
+ elem.xpath("./localityStack[not(@connective)]").each do |l|
56
+ n = l.next_element
57
+ l["connective"] = if n && n.name == "localityStack" &&
58
+ n["connective"] == "to"
59
+ "from"
60
+ else "and"
61
+ end
62
+ end
63
+ end
64
+
43
65
  def locality_label(match)
44
66
  loc = match[:locality] || match[:locality2]
45
67
  /^locality:/.match?(loc) ? loc : loc&.downcase
@@ -65,8 +87,48 @@ module Metanorma
65
87
  end
66
88
 
67
89
  def xref_cleanup(xmldoc)
90
+ xref_compound_cleanup(xmldoc)
91
+ xref_cleanup1(xmldoc)
92
+ xref_compound_wrapup(xmldoc)
93
+ end
94
+
95
+ def xref_compound_cleanup(xmldoc)
96
+ xmldoc.xpath("//xref").each do |x|
97
+ /;/.match?(x["target"]) or next
98
+ locations = x["target"].split(";")
99
+ x["target"] = locations.first.sub(/^[^!]*!/, "")
100
+ xref_compound_cleanup1(x, locations)
101
+ end
102
+ end
103
+
104
+ def xref_compound_cleanup1(xref, locations)
105
+ xref.children.empty? and xref.children = "<sentinel/>"
106
+ xref_parse_compound_locations(locations).reverse.each do |y|
107
+ xref.children.first.previous =
108
+ "<xref target='#{y[1]}' connective='#{y[0]}'/>"
109
+ end
110
+ xref&.at("./sentinel")&.remove
111
+ end
112
+
113
+ def xref_parse_compound_locations(locations)
114
+ l = locations.map { |y| y.split("!", 2) }
115
+ l.map.with_index do |y, i|
116
+ if y.size == 1
117
+ y.unshift(l.dig(i + 1, 0) == "to" ? "from" : "and")
118
+ end
119
+ y
120
+ end
121
+ end
122
+
123
+ def xref_compound_wrapup(xmldoc)
124
+ xmldoc.xpath("//xref//xref").each do |x|
125
+ x.name = "location"
126
+ end
127
+ end
128
+
129
+ def xref_cleanup1(xmldoc)
68
130
  xmldoc.xpath("//xref").each do |x|
69
- /:/.match(x["target"]) and xref_to_internal_eref(x)
131
+ /:/.match?(x["target"]) and xref_to_internal_eref(x)
70
132
  next unless x.name == "xref"
71
133
 
72
134
  if refid? x["target"]
@@ -53,6 +53,7 @@ module Metanorma
53
53
  inline_macro Metanorma::Standoc::FormOptionMacro
54
54
  inline_macro Metanorma::Standoc::ToCInlineMacro
55
55
  inline_macro Metanorma::Standoc::PassInlineMacro
56
+ inline_macro Metanorma::Standoc::StdLinkInlineMacro
56
57
  inline_macro Metanorma::Plugin::Lutaml::LutamlFigureInlineMacro
57
58
  inline_macro Metanorma::Plugin::Lutaml::LutamlTableInlineMacro
58
59
  block_macro Metanorma::Plugin::Lutaml::LutamlDiagramBlockMacro
@@ -40,20 +40,29 @@ module Metanorma
40
40
  end
41
41
 
42
42
  def inline_anchor_xref_attrs(node)
43
- m = /^(?<drop>droploc%)?(?<case>capital%|lowercase%)?(?<drop2>droploc%)?
44
- (?<fn>fn:?\s*)?(?<text>.*)$/x.match node.text
43
+ m = inline_anchor_xref_match(node)
45
44
  t = node.target.gsub(/^#/, "").gsub(%r{(\.xml|\.adoc)(#.*$)}, "\\2")
46
45
  m.nil? and return { target: t, type: "inline", text: node.text }
47
- droploc = m[:drop].nil? && m[:drop2].nil? ? nil : true
48
- f = m[:fn].nil? ? "inline" : "footnote"
49
- c = if %i[case fn drop drop2].any? do |x|
50
- !m[x].nil?
51
- end
52
- m[:text]
53
- else node.text
54
- end
55
- { target: t, type: f, case: m[:case]&.sub(/%$/, ""), droploc: droploc,
56
- text: c }
46
+ { target: t, type: m[:fn].nil? ? "inline" : "footnote",
47
+ case: m[:case]&.sub(/%$/, ""),
48
+ droploc: m[:drop].nil? && m[:drop2].nil? ? nil : true,
49
+ text: inline_anchor_xref_text(m, node),
50
+ hidden: m[:hidden] }
51
+ end
52
+
53
+ def inline_anchor_xref_match(node)
54
+ /^(hidden%(?<hidden>[^,]+),?)?
55
+ (?<drop>droploc%)?(?<case>capital%|lowercase%)?(?<drop2>droploc%)?
56
+ (?<fn>fn:?\s*)?(?<text>.*)$/x.match node.text
57
+ end
58
+
59
+ def inline_anchor_xref_text(match, node)
60
+ if %i[case fn drop drop2 hidden].any? do |x|
61
+ !match[x].nil?
62
+ end
63
+ match[:text]
64
+ else node.text
65
+ end
57
66
  end
58
67
 
59
68
  def inline_anchor_link(node)
@@ -152,9 +152,7 @@
152
152
  <data type="boolean"/>
153
153
  </attribute>
154
154
  </optional>
155
- <oneOrMore>
156
- <ref name="PureTextElement"/>
157
- </oneOrMore>
155
+ <ref name="XrefBody"/>
158
156
  </element>
159
157
  </define>
160
158
  <define name="erefType">
@@ -188,6 +186,42 @@
188
186
  <ref name="PureTextElement"/>
189
187
  </oneOrMore>
190
188
  </define>
189
+ <define name="localityStack">
190
+ <element name="localityStack">
191
+ <optional>
192
+ <attribute name="connective">
193
+ <choice>
194
+ <value>and</value>
195
+ <value>or</value>
196
+ <value>from</value>
197
+ <value>to</value>
198
+ <value/>
199
+ </choice>
200
+ </attribute>
201
+ </optional>
202
+ <zeroOrMore>
203
+ <ref name="locality"/>
204
+ </zeroOrMore>
205
+ </element>
206
+ </define>
207
+ <define name="sourceLocalityStack">
208
+ <element name="sourceLocalityStack">
209
+ <optional>
210
+ <attribute name="connective">
211
+ <choice>
212
+ <value>and</value>
213
+ <value>or</value>
214
+ <value>from</value>
215
+ <value>to</value>
216
+ <value/>
217
+ </choice>
218
+ </attribute>
219
+ </optional>
220
+ <zeroOrMore>
221
+ <ref name="sourceLocality"/>
222
+ </zeroOrMore>
223
+ </element>
224
+ </define>
191
225
  <define name="ul">
192
226
  <element name="ul">
193
227
  <attribute name="id">
@@ -2641,4 +2675,30 @@
2641
2675
  </zeroOrMore>
2642
2676
  </element>
2643
2677
  </define>
2678
+ <define name="XrefBody">
2679
+ <zeroOrMore>
2680
+ <ref name="XrefTarget"/>
2681
+ </zeroOrMore>
2682
+ <oneOrMore>
2683
+ <ref name="PureTextElement"/>
2684
+ </oneOrMore>
2685
+ </define>
2686
+ <define name="XrefTarget">
2687
+ <element name="location">
2688
+ <attribute name="target">
2689
+ <data type="string">
2690
+ <param name="pattern">\i\c*|\c+#\c+</param>
2691
+ </data>
2692
+ </attribute>
2693
+ <attribute name="connective">
2694
+ <choice>
2695
+ <value>and</value>
2696
+ <value>or</value>
2697
+ <value>from</value>
2698
+ <value>to</value>
2699
+ <value/>
2700
+ </choice>
2701
+ </attribute>
2702
+ </element>
2703
+ </define>
2644
2704
  </grammar>
@@ -82,7 +82,7 @@ module Metanorma
82
82
  .match(l) && (ignore = !ignore)
83
83
  next if l.empty? || l.match(/ \+$/) || /^\[.*\]$/.match?(l) || ignore
84
84
  next if i == lines.size - 1 ||
85
- i < lines.size - 1 && lines[i + 1].empty?
85
+ (i < lines.size - 1 && lines[i + 1].empty?)
86
86
 
87
87
  lines[i] += " +"
88
88
  end
@@ -201,5 +201,17 @@ module Metanorma
201
201
  %{<passthrough formats="#{format}">#{out}</passthrough>}
202
202
  end
203
203
  end
204
+
205
+ class StdLinkInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
206
+ use_dsl
207
+ named :"std-link"
208
+ parse_content_as :text
209
+ using_format :short
210
+
211
+ def process(parent, _target, attrs)
212
+ create_anchor(parent, "hidden%#{attrs['text']}",
213
+ type: :xref, target: "_#{UUIDTools::UUID.random_create}")
214
+ end
215
+ end
204
216
  end
205
217
  end
@@ -56,7 +56,7 @@ module Metanorma
56
56
  lines.each_with_index.with_object([]) do |(l, i), m|
57
57
  if headings.include?(l.strip)
58
58
  skip = true
59
- m.unshift while !m.empty? && /^\S/.match?(m[-1])
59
+ m.pop while !m.empty? && /^\S/.match?(m[-1])
60
60
  elsif skip && /^== |^embed::|^include::/.match?(l)
61
61
  skip = false
62
62
  j = i
@@ -214,18 +214,17 @@ module Metanorma
214
214
  end
215
215
  end
216
216
 
217
- def reference_preproc(node)
217
+ def reference(node)
218
218
  refs = node.items.each_with_object([]) do |b, m|
219
219
  m << reference1code(b.text, node)
220
220
  end
221
+ reference_populate(refs)
222
+ end
223
+
224
+ def reference_populate(refs)
221
225
  results = refs.each_with_index.with_object(Queue.new) do |(ref, i), res|
222
226
  fetch_ref_async(ref.merge(ord: i), i, res)
223
227
  end
224
- [refs, results]
225
- end
226
-
227
- def reference(node)
228
- refs, results = reference_preproc(node)
229
228
  ret = reference_queue(refs, results)
230
229
  noko do |xml|
231
230
  ret.each { |b| reference1out(b, xml) }
@@ -25,6 +25,9 @@ module Metanorma
25
25
  sectionsplit: node.attr("sectionsplit"),
26
26
  baseassetpath: node.attr("base-asset-path"),
27
27
  aligncrosselements: node.attr("align-cross-elements"),
28
+ tocfigures: @tocfigures,
29
+ toctables: @toctables,
30
+ tocrecommendations: @tocrecommendations,
28
31
  }
29
32
  end
30
33
 
@@ -61,12 +64,13 @@ module Metanorma
61
64
  bare: node.attr("bare"),
62
65
  baseassetpath: node.attr("base-asset-path"),
63
66
  aligncrosselements: node.attr("align-cross-elements"),
67
+ tocfigures: @tocfigures,
68
+ toctables: @toctables,
69
+ tocrecommendations: @tocrecommendations,
64
70
  }
65
71
 
66
72
  if fonts_manifest = node.attr(FONTS_MANIFEST)
67
- attrs[IsoDoc::XslfoPdfConvert::MN2PDF_OPTIONS] = {
68
- IsoDoc::XslfoPdfConvert::MN2PDF_FONT_MANIFEST => fonts_manifest,
69
- }
73
+ attrs[IsoDoc::XslfoPdfConvert::MN2PDF_FONT_MANIFEST] = fonts_manifest
70
74
  end
71
75
 
72
76
  attrs