metanorma-standoc 1.7.3 → 1.8.1

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.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/lib/asciidoctor/standoc/base.rb +31 -44
  3. data/lib/asciidoctor/standoc/basicdoc.rng +5 -3
  4. data/lib/asciidoctor/standoc/blocks.rb +7 -7
  5. data/lib/asciidoctor/standoc/blocks_notes.rb +2 -2
  6. data/lib/asciidoctor/standoc/cleanup.rb +5 -6
  7. data/lib/asciidoctor/standoc/cleanup_block.rb +3 -3
  8. data/lib/asciidoctor/standoc/cleanup_boilerplate.rb +56 -0
  9. data/lib/asciidoctor/standoc/cleanup_inline.rb +22 -26
  10. data/lib/asciidoctor/standoc/cleanup_ref.rb +0 -85
  11. data/lib/asciidoctor/standoc/cleanup_ref_dl.rb +94 -0
  12. data/lib/asciidoctor/standoc/converter.rb +0 -1
  13. data/lib/asciidoctor/standoc/front.rb +2 -2
  14. data/lib/asciidoctor/standoc/inline.rb +1 -1
  15. data/lib/asciidoctor/standoc/isodoc.rng +3 -0
  16. data/lib/asciidoctor/standoc/lists.rb +2 -2
  17. data/lib/asciidoctor/standoc/macros_plantuml.rb +1 -1
  18. data/lib/asciidoctor/standoc/ref_sect.rb +2 -2
  19. data/lib/asciidoctor/standoc/reqt.rb +6 -1
  20. data/lib/asciidoctor/standoc/section.rb +3 -80
  21. data/lib/asciidoctor/standoc/table.rb +1 -1
  22. data/lib/asciidoctor/standoc/terms.rb +125 -0
  23. data/lib/asciidoctor/standoc/utils.rb +2 -96
  24. data/lib/metanorma/standoc/version.rb +1 -1
  25. data/metanorma-standoc.gemspec +2 -2
  26. data/spec/asciidoctor-standoc/base_spec.rb +30 -1
  27. data/spec/asciidoctor-standoc/cleanup_spec.rb +111 -2
  28. data/spec/asciidoctor-standoc/isobib_cache_spec.rb +4 -4
  29. data/spec/asciidoctor-standoc/refs_dl_spec.rb +13 -1
  30. data/spec/asciidoctor-standoc/refs_spec.rb +12 -12
  31. data/spec/asciidoctor-standoc/section_spec.rb +5 -3
  32. data/spec/vcr_cassettes/dated_iso_ref_joint_iso_iec.yml +47 -47
  33. data/spec/vcr_cassettes/isobib_get_123.yml +11 -11
  34. data/spec/vcr_cassettes/isobib_get_123_1.yml +26 -26
  35. data/spec/vcr_cassettes/isobib_get_123_1_fr.yml +36 -36
  36. data/spec/vcr_cassettes/isobib_get_123_2001.yml +14 -14
  37. data/spec/vcr_cassettes/isobib_get_124.yml +14 -14
  38. data/spec/vcr_cassettes/rfcbib_get_rfc8341.yml +8 -8
  39. data/spec/vcr_cassettes/separates_iev_citations_by_top_level_clause.yml +45 -45
  40. metadata +19 -18
  41. data/lib/asciidoctor/standoc/log.rb +0 -59
@@ -120,91 +120,6 @@ module Asciidoctor
120
120
  end
121
121
  end
122
122
 
123
- def ref_dl_cleanup(xmldoc)
124
- xmldoc.xpath("//clause[@bibitem = 'true']").each do |c|
125
- bib = dl_bib_extract(c) or next
126
- validate_ref_dl(bib, c)
127
- bibitemxml = RelatonBib::BibliographicItem.new(RelatonBib::HashConverter::hash_to_bib(bib)).to_xml or next
128
- bibitem = Nokogiri::XML(bibitemxml)
129
- bibitem.root["id"] = c["id"] if c["id"] && !/^_/.match(c["id"])
130
- c.replace(bibitem.root)
131
- end
132
- end
133
-
134
- def validate_ref_dl(bib, c)
135
- id = bib["id"]
136
- id ||= c["id"] unless /^_/.match(c["id"]) # do not accept implicit id
137
- unless id
138
- @log.add("Anchors", c, "The following reference is missing an anchor:\n" + c.to_xml)
139
- return
140
- end
141
- bib["title"] or @log.add("Bibliography", c, "Reference #{id} is missing a title")
142
- bib["docid"] or @log.add("Bibliography", c, "Reference #{id} is missing a document identifier (docid)")
143
- end
144
-
145
- def extract_from_p(tag, bib, key)
146
- return unless bib[tag]
147
- "<#{key}>#{bib[tag].at('p').children}</#{key}>"
148
- end
149
-
150
- # if the content is a single paragraph, replace it with its children
151
- # single links replaced with uri
152
- def p_unwrap(p)
153
- elems = p.elements
154
- if elems.size == 1 && elems[0].name == "p"
155
- link_unwrap(elems[0]).children.to_xml.strip
156
- else
157
- p.to_xml.strip
158
- end
159
- end
160
-
161
- def link_unwrap(p)
162
- elems = p.elements
163
- if elems.size == 1 && elems[0].name == "link"
164
- p.at("./link").replace(elems[0]["target"].strip)
165
- end
166
- p
167
- end
168
-
169
- def dd_bib_extract(dtd)
170
- return nil if dtd.children.empty?
171
- dtd.at("./dl") and return dl_bib_extract(dtd)
172
- elems = dtd.remove.elements
173
- return p_unwrap(dtd) unless elems.size == 1 && %w(ol ul).include?(elems[0].name)
174
- ret = []
175
- elems[0].xpath("./li").each do |li|
176
- ret << p_unwrap(li)
177
- end
178
- ret
179
- end
180
-
181
- def add_to_hash(bib, key, val)
182
- Utils::set_nested_value(bib, key.split(/\./), val)
183
- end
184
-
185
- # definition list, with at most one level of unordered lists
186
- def dl_bib_extract(c, nested = false)
187
- dl = c.at("./dl") or return
188
- bib = {}
189
- key = ""
190
- dl.xpath("./dt | ./dd").each do |dtd|
191
- dtd.name == "dt" and key = dtd.text.sub(/:+$/, "") or add_to_hash(bib, key, dd_bib_extract(dtd))
192
- end
193
- c.xpath("./clause").each do |c1|
194
- key = c1&.at("./title")&.text&.downcase&.strip
195
- next unless %w(contributor relation series).include? key
196
- add_to_hash(bib, key, dl_bib_extract(c1, true))
197
- end
198
- if !nested and c.at("./title")
199
- title = c.at("./title").remove.children.to_xml
200
- bib["title"] = [bib["title"]] if bib["title"].is_a? Hash
201
- bib["title"] = [bib["title"]] if bib["title"].is_a? String
202
- bib["title"] = [] unless bib["title"]
203
- bib["title"] << title if !title.empty?
204
- end
205
- bib
206
- end
207
-
208
123
  def fetch_termbase(termbase, id)
209
124
  ""
210
125
  end
@@ -0,0 +1,94 @@
1
+ require "set"
2
+ require "relaton_bib"
3
+
4
+ module Asciidoctor
5
+ module Standoc
6
+ module Cleanup
7
+ def ref_dl_cleanup(xmldoc)
8
+ xmldoc.xpath("//clause[@bibitem = 'true']").each do |c|
9
+ bib = dl_bib_extract(c) or next
10
+ validate_ref_dl(bib, c)
11
+ bibitemxml = RelatonBib::BibliographicItem.new(RelatonBib::HashConverter::hash_to_bib(bib)).to_xml or next
12
+ bibitem = Nokogiri::XML(bibitemxml)
13
+ bibitem.root["id"] = c["id"] if c["id"] && !/^_/.match(c["id"])
14
+ c.replace(bibitem.root)
15
+ end
16
+ end
17
+
18
+ def validate_ref_dl(bib, c)
19
+ id = bib["id"]
20
+ id ||= c["id"] unless /^_/.match(c["id"]) # do not accept implicit id
21
+ unless id
22
+ @log.add("Anchors", c, "The following reference is missing an anchor:\n" + c.to_xml)
23
+ return
24
+ end
25
+ @refids << id
26
+ bib["title"] or @log.add("Bibliography", c, "Reference #{id} is missing a title")
27
+ bib["docid"] or @log.add("Bibliography", c, "Reference #{id} is missing a document identifier (docid)")
28
+ end
29
+
30
+ def extract_from_p(tag, bib, key)
31
+ return unless bib[tag]
32
+ "<#{key}>#{bib[tag].at('p').children}</#{key}>"
33
+ end
34
+
35
+ # if the content is a single paragraph, replace it with its children
36
+ # single links replaced with uri
37
+ def p_unwrap(p)
38
+ elems = p.elements
39
+ if elems.size == 1 && elems[0].name == "p"
40
+ link_unwrap(elems[0]).children.to_xml.strip
41
+ else
42
+ p.to_xml.strip
43
+ end
44
+ end
45
+
46
+ def link_unwrap(p)
47
+ elems = p.elements
48
+ if elems.size == 1 && elems[0].name == "link"
49
+ p.at("./link").replace(elems[0]["target"].strip)
50
+ end
51
+ p
52
+ end
53
+
54
+ def dd_bib_extract(dtd)
55
+ return nil if dtd.children.empty?
56
+ dtd.at("./dl") and return dl_bib_extract(dtd)
57
+ elems = dtd.remove.elements
58
+ return p_unwrap(dtd) unless elems.size == 1 && %w(ol ul).include?(elems[0].name)
59
+ ret = []
60
+ elems[0].xpath("./li").each do |li|
61
+ ret << p_unwrap(li)
62
+ end
63
+ ret
64
+ end
65
+
66
+ def add_to_hash(bib, key, val)
67
+ Metanorma::Utils::set_nested_value(bib, key.split(/\./), val)
68
+ end
69
+
70
+ # definition list, with at most one level of unordered lists
71
+ def dl_bib_extract(c, nested = false)
72
+ dl = c.at("./dl") or return
73
+ bib = {}
74
+ key = ""
75
+ dl.xpath("./dt | ./dd").each do |dtd|
76
+ dtd.name == "dt" and key = dtd.text.sub(/:+$/, "") or add_to_hash(bib, key, dd_bib_extract(dtd))
77
+ end
78
+ c.xpath("./clause").each do |c1|
79
+ key = c1&.at("./title")&.text&.downcase&.strip
80
+ next unless %w(contributor relation series).include? key
81
+ add_to_hash(bib, key, dl_bib_extract(c1, true))
82
+ end
83
+ if !nested and c.at("./title")
84
+ title = c.at("./title").remove.children.to_xml
85
+ bib["title"] = [bib["title"]] if bib["title"].is_a? Hash
86
+ bib["title"] = [bib["title"]] if bib["title"].is_a? String
87
+ bib["title"] = [] unless bib["title"]
88
+ bib["title"] << title if !title.empty?
89
+ end
90
+ bib
91
+ end
92
+ end
93
+ end
94
+ end
@@ -14,7 +14,6 @@ require "asciidoctor/standoc/utils"
14
14
  require "asciidoctor/standoc/cleanup"
15
15
  require "asciidoctor/standoc/reqt"
16
16
  require_relative "./macros.rb"
17
- require_relative "./log.rb"
18
17
 
19
18
  module Asciidoctor
20
19
  module Standoc
@@ -93,7 +93,7 @@ module Asciidoctor
93
93
  end
94
94
 
95
95
  def metadata_script(node, xml)
96
- xml.script (node.attr("script") || "Latn")
96
+ xml.script (node.attr("script") || default_script(node.attr("language")))
97
97
  end
98
98
 
99
99
  def relaton_relations
@@ -186,7 +186,7 @@ module Asciidoctor
186
186
  ["en"].each do |lang|
187
187
  at = { language: lang, format: "text/plain" }
188
188
  xml.title **attr_code(at) do |t|
189
- t << (Utils::asciidoc_sub(node.attr("title") ||
189
+ t << (Metanorma::Utils::asciidoc_sub(node.attr("title") ||
190
190
  node.attr("title-en")) || node.title)
191
191
  end
192
192
  end
@@ -194,7 +194,7 @@ module Asciidoctor
194
194
  type = types.first.to_s
195
195
  uri = uri.sub(%r{^data:image/\*;}, "data:#{type};")
196
196
  attr_code(src: uri, #@datauriimage ? datauri(uri) : uri,
197
- id: Utils::anchor_or_uuid,
197
+ id: Metanorma::Utils::anchor_or_uuid,
198
198
  mimetype: type,
199
199
  height: node.attr("height") || "auto",
200
200
  width: node.attr("width") || "auto" ,
@@ -789,6 +789,9 @@
789
789
  <attribute name="width"/>
790
790
  </element>
791
791
  </define>
792
+ <define name="BibItemType" combine="choice">
793
+ <value>internal</value>
794
+ </define>
792
795
  <define name="TextElement" combine="choice">
793
796
  <ref name="concept"/>
794
797
  </define>
@@ -54,7 +54,7 @@ module Asciidoctor
54
54
  end
55
55
 
56
56
  def ol_attrs(node)
57
- attr_code(keep_attrs(node).merge(id: Utils::anchor_or_uuid(node),
57
+ attr_code(keep_attrs(node).merge(id: Metanorma::Utils::anchor_or_uuid(node),
58
58
  type: olist_style(node.style)))
59
59
  end
60
60
 
@@ -88,7 +88,7 @@ module Asciidoctor
88
88
 
89
89
  def dl_attrs(node)
90
90
  attr_code(keep_attrs(node).
91
- merge(id: Utils::anchor_or_uuid(node),
91
+ merge(id: Metanorma::Utils::anchor_or_uuid(node),
92
92
  key: node.option?("key") ? "true" : nil))
93
93
  end
94
94
 
@@ -30,7 +30,7 @@ module Asciidoctor
30
30
  # plantuml process may finish earlier then dot, as result png file
31
31
  # maybe not created yet after plantuml finish
32
32
  def self.generate_file parent, reader
33
- localdir = Utils::localdir(parent.document)
33
+ localdir = Metanorma::Utils::localdir(parent.document)
34
34
  imagesdir = parent.document.attr('imagesdir')
35
35
  umlfile, outfile = save_plantuml parent, reader, localdir
36
36
  run(umlfile, outfile) or raise "No image output from PlantUML (#{umlfile}, #{outfile})!"
@@ -96,9 +96,9 @@ module Asciidoctor
96
96
  xstr = x.to_xml(lang: opts[:lang])
97
97
  xml = Nokogiri::XML(xstr)
98
98
  emend_biblio(xml, code, opts[:title], opts[:usrlbl])
99
- xml.xpath("//date").each { |d| Utils::endash_date(d) }
99
+ xml.xpath("//date").each { |d| Metanorma::Utils::endash_date(d) }
100
100
  xml.traverse do |n|
101
- n.text? and n.replace(Utils::smartformat(n.text))
101
+ n.text? and n.replace(Metanorma::Utils::smartformat(n.text))
102
102
  end
103
103
  xml.to_xml.sub(/<\?[^>]+>/, "")
104
104
  end
@@ -6,6 +6,11 @@ require "base64"
6
6
  module Asciidoctor
7
7
  module Standoc
8
8
  module Blocks
9
+ def reqt_subpart(x)
10
+ %w(specification measurement-target verification import label
11
+ subject inherit classification title).include? x
12
+ end
13
+
9
14
  def reqt_subpart_attrs(node)
10
15
  attr_code(keep_attrs(node).merge(exclude: node.option?("exclude"),
11
16
  type: node.attr("type")))
@@ -41,7 +46,7 @@ module Asciidoctor
41
46
 
42
47
  def reqt_attrs(node)
43
48
  attr_code(keep_attrs(node).merge(id_unnum_attrs(node)).merge(
44
- id: Utils::anchor_or_uuid(node),
49
+ id: Metanorma::Utils::anchor_or_uuid(node),
45
50
  unnumbered: node.option?("unnumbered") ? "true" : nil,
46
51
  number: node.attr("number"),
47
52
  subsequence: node.attr("subsequence"),
@@ -1,6 +1,6 @@
1
- require "htmlentities"
2
1
  require "uri"
3
2
  require_relative "ref_sect"
3
+ require_relative "terms"
4
4
 
5
5
  module Asciidoctor
6
6
  module Standoc
@@ -9,10 +9,6 @@ module Asciidoctor
9
9
  @term_def = false
10
10
  @norm_ref = false
11
11
 
12
- def in_terms?
13
- @term_def
14
- end
15
-
16
12
  def sectiontype1(node)
17
13
  node&.attr("heading")&.downcase || node.title.gsub(/<[^>]+>/, "").downcase
18
14
  end
@@ -45,10 +41,11 @@ module Asciidoctor
45
41
  end
46
42
 
47
43
  def section_attributes(node)
48
- ret = { id: Utils::anchor_or_uuid(node),
44
+ ret = { id: Metanorma::Utils::anchor_or_uuid(node),
49
45
  language: node.attributes["language"],
50
46
  script: node.attributes["script"],
51
47
  number: node.attributes["number"],
48
+ type: node.attributes["type"],
52
49
  annex: ( ((node.attr("style") == "appendix" || node.role == "appendix") &&
53
50
  node.level == 1) ? true : nil),
54
51
  preface: (
@@ -147,80 +144,6 @@ module Asciidoctor
147
144
  end
148
145
  end
149
146
 
150
- def nonterm_symbols_parse(attrs, xml, node)
151
- defs = @definitions
152
- @definitions = false
153
- clause_parse(attrs, xml, node)
154
- @definitions = defs
155
- end
156
-
157
- def symbols_attrs(node, a)
158
- case sectiontype1(node)
159
- when "symbols" then a.merge(type: "symbols")
160
- when "abbreviated terms", "abbreviations" then a.merge(type: "abbreviated_terms")
161
- else
162
- a
163
- end
164
- end
165
-
166
- def symbols_parse(attr, xml, node)
167
- node.role == "nonterm" and return nonterm_symbols_parse(attr, xml, node)
168
- xml.definitions **attr_code(attr) do |xml_section|
169
- xml_section.title { |t| t << node.title }
170
- defs = @definitions
171
- termdefs = @term_def
172
- @definitions = true
173
- @term_def = false
174
- xml_section << node.content
175
- @definitions = defs
176
- @term_def = termdefs
177
- end
178
- end
179
-
180
- def nonterm_term_def_subclause_parse(attrs, xml, node)
181
- defs = @term_def
182
- @term_def = false
183
- clause_parse(attrs, xml, node)
184
- @term_def = defs
185
- end
186
-
187
- def terms_boilerplate_parse(attrs, xml, node)
188
- defs = @term_def
189
- @term_def = false
190
- clause_parse(attrs.merge(type: "boilerplate"), xml, node)
191
- @term_def = defs
192
- end
193
-
194
- # subclause contains subclauses
195
- def term_def_subclause_parse(attrs, xml, node)
196
- node.role == "nonterm" and return nonterm_term_def_subclause_parse(attrs, xml, node)
197
- node.role == "boilerplate" and return terms_boilerplate_parse(attrs, xml, node)
198
- st = sectiontype(node, false)
199
- return symbols_parse(attrs, xml, node) if @definitions
200
- sub = node.find_by(context: :section) { |s| s.level == node.level + 1 }
201
- sub.empty? || (return term_def_parse(attrs, xml, node, false))
202
- st == "symbols and abbreviated terms" and (return symbols_parse(attrs, xml, node))
203
- st == "terms and definitions" and return clause_parse(attrs, xml, node)
204
- term_def_subclause_parse1(attrs, xml, node)
205
- end
206
-
207
- def term_def_subclause_parse1(attrs, xml, node)
208
- xml.term **attr_code(attrs) do |xml_section|
209
- xml_section.preferred { |name| name << node.title }
210
- xml_section << node.content
211
- end
212
- end
213
-
214
- def term_def_parse(attrs, xml, node, toplevel)
215
- xml.terms **attr_code(attrs) do |section|
216
- section.title { |t| t << node.title }
217
- (s = node.attr("source")) && s.split(/,/).each do |s1|
218
- section.termdocsource(nil, **attr_code(bibitemid: s1))
219
- end
220
- section << node.content
221
- end
222
- end
223
-
224
147
  def introduction_parse(attrs, xml, node)
225
148
  xml.introduction **attr_code(attrs) do |xml_section|
226
149
  xml_section.title { |t| t << @i18n.introduction }
@@ -2,7 +2,7 @@ module Asciidoctor
2
2
  module Standoc
3
3
  module Table
4
4
  def table_attrs(node)
5
- keep_attrs(node).merge( id: Utils::anchor_or_uuid(node),
5
+ keep_attrs(node).merge( id: Metanorma::Utils::anchor_or_uuid(node),
6
6
  headerrows: node.attr("headerrows"),
7
7
  unnumbered: node.option?("unnumbered") ? "true" : nil,
8
8
  number: node.attr("number"),
@@ -0,0 +1,125 @@
1
+ module Asciidoctor
2
+ module Standoc
3
+ module Section
4
+ def in_terms?
5
+ @term_def
6
+ end
7
+
8
+ def nonterm_symbols_parse(attrs, xml, node)
9
+ defs = @definitions
10
+ @definitions = false
11
+ clause_parse(attrs, xml, node)
12
+ @definitions = defs
13
+ end
14
+
15
+ def symbols_attrs(node, a)
16
+ case sectiontype1(node)
17
+ when "symbols" then a.merge(type: "symbols")
18
+ when "abbreviated terms", "abbreviations" then a.merge(type: "abbreviated_terms")
19
+ else
20
+ a
21
+ end
22
+ end
23
+
24
+ def symbols_parse(attr, xml, node)
25
+ node.role == "nonterm" and return nonterm_symbols_parse(attr, xml, node)
26
+ xml.definitions **attr_code(attr) do |xml_section|
27
+ xml_section.title { |t| t << node.title }
28
+ defs = @definitions
29
+ termdefs = @term_def
30
+ @definitions = true
31
+ @term_def = false
32
+ xml_section << node.content
33
+ @definitions = defs
34
+ @term_def = termdefs
35
+ end
36
+ end
37
+
38
+ def nonterm_term_def_subclause_parse(attrs, xml, node)
39
+ defs = @term_def
40
+ @term_def = false
41
+ clause_parse(attrs, xml, node)
42
+ @term_def = defs
43
+ end
44
+
45
+ def terms_boilerplate_parse(attrs, xml, node)
46
+ defs = @term_def
47
+ @term_def = false
48
+ clause_parse(attrs.merge(type: "boilerplate"), xml, node)
49
+ @term_def = defs
50
+ end
51
+
52
+ # subclause contains subclauses
53
+ def term_def_subclause_parse(attrs, xml, node)
54
+ node.role == "nonterm" and return nonterm_term_def_subclause_parse(attrs, xml, node)
55
+ node.role == "boilerplate" and return terms_boilerplate_parse(attrs, xml, node)
56
+ st = sectiontype(node, false)
57
+ return symbols_parse(attrs, xml, node) if @definitions
58
+ sub = node.find_by(context: :section) { |s| s.level == node.level + 1 }
59
+ sub.empty? || (return term_def_parse(attrs, xml, node, false))
60
+ st == "symbols and abbreviated terms" and (return symbols_parse(attrs, xml, node))
61
+ st == "terms and definitions" and return clause_parse(attrs, xml, node)
62
+ term_def_subclause_parse1(attrs, xml, node)
63
+ end
64
+
65
+ def term_def_subclause_parse1(attrs, xml, node)
66
+ xml.term **attr_code(attrs) do |xml_section|
67
+ xml_section.preferred { |name| name << node.title }
68
+ xml_section << node.content
69
+ end
70
+ end
71
+
72
+ def term_def_parse(attrs, xml, node, toplevel)
73
+ xml.terms **attr_code(attrs) do |section|
74
+ section.title { |t| t << node.title }
75
+ (s = node.attr("source")) && s.split(/,/).each do |s1|
76
+ section.termdocsource(nil, **attr_code(bibitemid: s1))
77
+ end
78
+ section << node.content
79
+ end
80
+ end
81
+
82
+ def term_source_attrs(seen_xref)
83
+ { bibitemid: seen_xref.children[0]["target"],
84
+ format: seen_xref.children[0]["format"], type: "inline" }
85
+ end
86
+
87
+ def add_term_source(xml_t, seen_xref, m)
88
+ if seen_xref.children[0].name == "concept"
89
+ xml_t.origin { |o| o << seen_xref.children[0].to_xml }
90
+ else
91
+ xml_t.origin seen_xref.children[0].content, **attr_code(term_source_attrs(seen_xref))
92
+ end
93
+ m[:text] && xml_t.modification do |mod|
94
+ mod.p { |p| p << m[:text].sub(/^\s+/, "") }
95
+ end
96
+ end
97
+
98
+ TERM_REFERENCE_RE_STR = <<~REGEXP.freeze
99
+ ^(?<xref><(xref|concept)[^>]+>([^<]*</(xref|concept)>)?)
100
+ (,\s(?<text>.*))?
101
+ $
102
+ REGEXP
103
+ TERM_REFERENCE_RE =
104
+ Regexp.new(TERM_REFERENCE_RE_STR.gsub(/\s/, "").gsub(/_/, "\\s"),
105
+ Regexp::IGNORECASE | Regexp::MULTILINE)
106
+
107
+ def extract_termsource_refs(text, node)
108
+ matched = TERM_REFERENCE_RE.match text
109
+ matched.nil? and @log.add("AsciiDoc Input", node, "term reference not in expected format: #{text}")
110
+ matched
111
+ end
112
+
113
+ def termsource(node)
114
+ matched = extract_termsource_refs(node.content, node) || return
115
+ noko do |xml|
116
+ attrs = { status: matched[:text] ? "modified" : "identical" }
117
+ xml.termsource **attrs do |xml_t|
118
+ seen_xref = Nokogiri::XML.fragment(matched[:xref])
119
+ add_term_source(xml_t, seen_xref, matched)
120
+ end
121
+ end.join("\n")
122
+ end
123
+ end
124
+ end
125
+ end