metanorma-standoc 2.0.2 → 2.0.5

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 (57) hide show
  1. checksums.yaml +4 -4
  2. data/lib/metanorma/standoc/base.rb +73 -23
  3. data/lib/metanorma/standoc/basicdoc.rng +5 -3
  4. data/lib/metanorma/standoc/biblio.rng +5 -3
  5. data/lib/metanorma/standoc/blocks.rb +4 -4
  6. data/lib/metanorma/standoc/cleanup_amend.rb +33 -30
  7. data/lib/metanorma/standoc/cleanup_boilerplate.rb +29 -5
  8. data/lib/metanorma/standoc/cleanup_image.rb +117 -3
  9. data/lib/metanorma/standoc/cleanup_ref.rb +32 -3
  10. data/lib/metanorma/standoc/cleanup_ref_dl.rb +25 -16
  11. data/lib/metanorma/standoc/cleanup_section.rb +2 -2
  12. data/lib/metanorma/standoc/cleanup_terms_designations.rb +4 -2
  13. data/lib/metanorma/standoc/cleanup_text.rb +39 -17
  14. data/lib/metanorma/standoc/cleanup_xref.rb +82 -13
  15. data/lib/metanorma/standoc/converter.rb +2 -1
  16. data/lib/metanorma/standoc/inline.rb +21 -12
  17. data/lib/metanorma/standoc/isodoc.rng +73 -3
  18. data/lib/metanorma/standoc/macros.rb +14 -2
  19. data/lib/metanorma/standoc/macros_embed.rb +35 -14
  20. data/lib/metanorma/standoc/macros_note.rb +4 -3
  21. data/lib/metanorma/standoc/processor.rb +6 -1
  22. data/lib/metanorma/standoc/ref.rb +20 -16
  23. data/lib/metanorma/standoc/ref_utility.rb +8 -6
  24. data/lib/metanorma/standoc/render.rb +7 -3
  25. data/lib/metanorma/standoc/table.rb +8 -10
  26. data/lib/metanorma/standoc/term_lookup_cleanup.rb +16 -10
  27. data/lib/metanorma/standoc/terms.rb +10 -7
  28. data/lib/metanorma/standoc/utils.rb +3 -1
  29. data/lib/metanorma/standoc/validate.rb +81 -7
  30. data/lib/metanorma/standoc/version.rb +1 -1
  31. data/metanorma-standoc.gemspec +2 -2
  32. data/spec/assets/a2.adoc +4 -2
  33. data/spec/assets/a3.adoc +2 -2
  34. data/spec/assets/a3a.adoc +7 -0
  35. data/spec/metanorma/base_spec.rb +1 -1
  36. data/spec/metanorma/cleanup_blocks_spec.rb +136 -0
  37. data/spec/metanorma/cleanup_spec.rb +34 -23
  38. data/spec/metanorma/cleanup_terms_spec.rb +16 -4
  39. data/spec/metanorma/inline_spec.rb +31 -0
  40. data/spec/metanorma/isobib_cache_spec.rb +2 -2
  41. data/spec/metanorma/macros_plantuml_spec.rb +41 -42
  42. data/spec/metanorma/macros_spec.rb +267 -4
  43. data/spec/metanorma/processor_spec.rb +17 -13
  44. data/spec/metanorma/refs_spec.rb +632 -460
  45. data/spec/metanorma/section_spec.rb +1 -1
  46. data/spec/metanorma/validate_spec.rb +108 -0
  47. data/spec/vcr_cassettes/dated_iso_ref_joint_iso_iec.yml +48 -48
  48. data/spec/vcr_cassettes/dated_iso_ref_joint_iso_iec1.yml +13 -13
  49. data/spec/vcr_cassettes/hide_refs.yml +100 -100
  50. data/spec/vcr_cassettes/isobib_get_123.yml +12 -12
  51. data/spec/vcr_cassettes/isobib_get_123_1.yml +25 -25
  52. data/spec/vcr_cassettes/isobib_get_123_1_fr.yml +35 -35
  53. data/spec/vcr_cassettes/isobib_get_123_2001.yml +11 -11
  54. data/spec/vcr_cassettes/isobib_get_124.yml +13 -13
  55. data/spec/vcr_cassettes/rfcbib_get_rfc8341.yml +18 -18
  56. data/spec/vcr_cassettes/separates_iev_citations_by_top_level_clause.yml +86 -66
  57. metadata +10 -9
@@ -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
@@ -9,12 +9,6 @@ module Metanorma
9
9
  </passthrough>}mx) { HTMLEntities.new.decode($1) }
10
10
  end
11
11
 
12
- IGNORE_DUMBQUOTES =
13
- "//pre | //pre//* | //tt | //tt//* | "\
14
- "//sourcecode | //sourcecode//* | //bibdata//* | //stem | "\
15
- "//stem//* | //figure[@class = 'pseudocode'] | "\
16
- "//figure[@class = 'pseudocode']//*".freeze
17
-
18
12
  def smartquotes_cleanup(xmldoc)
19
13
  xmldoc.xpath("//date").each { |d| Metanorma::Utils::endash_date(d) }
20
14
  if @smartquotes then smartquotes_cleanup1(xmldoc)
@@ -31,14 +25,21 @@ module Metanorma
31
25
  def uninterrupt_quotes_around_xml(xmldoc)
32
26
  xmldoc.traverse do |n|
33
27
  next unless n.text? && n&.previous&.element?
34
- next unless /^['"]/.match?(n.text)
35
- next unless n.previous.ancestors("pre, tt, sourcecode, stem, figure")
36
- .empty?
28
+ next if uninterrupt_quotes_around_xml_skip(n)
37
29
 
38
30
  uninterrupt_quotes_around_xml1(n.previous)
39
31
  end
40
32
  end
41
33
 
34
+ def uninterrupt_quotes_around_xml_skip(elem)
35
+ !(/^['"]/.match?(elem.text) &&
36
+ elem.previous.ancestors("pre, tt, sourcecode, stem, figure, bibdata")
37
+ .empty? &&
38
+ ((elem.previous.text.strip.empty? &&
39
+ !empty_tag_with_text_content?(elem.previous)) ||
40
+ elem.previous.name == "index"))
41
+ end
42
+
42
43
  def uninterrupt_quotes_around_xml1(elem)
43
44
  prev = elem.at(".//preceding::text()[1]") or return
44
45
  /\S$/.match?(prev.text) or return
@@ -49,19 +50,40 @@ module Metanorma
49
50
  prev.content = "#{prev.text}#{m[1]}"
50
51
  end
51
52
 
52
- def dumb2smart_quotes(xmldoc)
53
- (xmldoc.xpath("//*[child::text()]") - xmldoc.xpath(IGNORE_DUMBQUOTES))
54
- .each do |x|
55
- x.children.each do |n|
56
- next unless n.text?
53
+ def block?(elem)
54
+ %w(title name variant-title clause figure annex example introduction
55
+ foreword acknowledgements note li th td dt dd p quote label
56
+ abstract preferred admitted related deprecates field-of-application
57
+ usage-info expression pronunciation grammar-value domain
58
+ definition termnote termexample modification description
59
+ newcontent floating-title).include? elem.name
60
+ end
57
61
 
58
- /[-'"(<>]|\.\.|\dx/.match(n) or next
62
+ def empty_tag_with_text_content?(elem)
63
+ %w(eref xref termref link).include? elem.name
64
+ end
59
65
 
60
- n.replace(Metanorma::Utils::smartformat(n.text))
61
- end
66
+ def dumb2smart_quotes(xmldoc)
67
+ prev = ""
68
+ xmldoc.traverse do |x|
69
+ block?(x) and prev = ""
70
+ empty_tag_with_text_content?(x) and prev = "dummy"
71
+ next unless x.text?
72
+
73
+ x.ancestors("pre, tt, sourcecode, stem, figure, bibdata").empty? and
74
+ dumb2smart_quotes1(x, prev)
75
+ prev = x.text if x.ancestors("index").empty?
62
76
  end
63
77
  end
64
78
 
79
+ def dumb2smart_quotes1(curr, prev)
80
+ /[-'"(<>]|\.\.|\dx/.match?(curr.text) or return
81
+
82
+ /^["']/.match?(curr.text) && prev.match?(/\S$/) and
83
+ curr.content = curr.text.sub(/^"/, "”").sub(/"’"/, "‘")
84
+ curr.replace(Metanorma::Utils::smartformat(curr.text))
85
+ end
86
+
65
87
  def dumbquote_cleanup(xmldoc)
66
88
  xmldoc.traverse do |n|
67
89
  next unless n.text?
@@ -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
@@ -47,19 +69,66 @@ module Metanorma
47
69
 
48
70
  def xref_to_eref(elem)
49
71
  elem["bibitemid"] = elem["target"]
50
- unless elem["citeas"] = @anchors&.dig(elem["target"], :xref)
51
- @internal_eref_namespaces.include?(elem["type"]) or
52
- @log.add("Crossreferences", elem,
53
- "#{elem['target']} does not have a corresponding "\
54
- "anchor ID in the bibliography!")
72
+ if ref = @anchors&.dig(elem["target"], :xref)
73
+ elem["citeas"] = HTMLEntities.new.encode(ref, :hexadecimal)
74
+ else
75
+ elem["citeas"] = ""
76
+ xref_to_eref1(elem)
55
77
  end
56
78
  elem.delete("target")
57
79
  extract_localities(elem) unless elem.children.empty?
58
80
  end
59
81
 
82
+ def xref_to_eref1(elem)
83
+ @internal_eref_namespaces.include?(elem["type"]) or
84
+ @log.add("Crossreferences", elem,
85
+ "#{elem['target']} does not have a corresponding "\
86
+ "anchor ID in the bibliography!")
87
+ end
88
+
60
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)
61
130
  xmldoc.xpath("//xref").each do |x|
62
- /:/.match(x["target"]) and xref_to_internal_eref(x)
131
+ /:/.match?(x["target"]) and xref_to_internal_eref(x)
63
132
  next unless x.name == "xref"
64
133
 
65
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
@@ -91,7 +92,7 @@ module Metanorma
91
92
  end
92
93
 
93
94
  class << self
94
- attr_accessor :_file
95
+ attr_accessor :_file, :embed_hdr
95
96
  end
96
97
 
97
98
  def self.inherited(konv) # rubocop:disable Lint/MissingSuper
@@ -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">
@@ -1098,6 +1132,16 @@
1098
1132
  </define>
1099
1133
  </include>
1100
1134
  <!-- end overrides -->
1135
+ <define name="image" combine="choice">
1136
+ <element name="svg">
1137
+ <oneOrMore>
1138
+ <choice>
1139
+ <text/>
1140
+ <ref name="AnyElement"/>
1141
+ </choice>
1142
+ </oneOrMore>
1143
+ </element>
1144
+ </define>
1101
1145
  <define name="MultilingualRenderingType">
1102
1146
  <choice>
1103
1147
  <value>common</value>
@@ -2631,4 +2675,30 @@
2631
2675
  </zeroOrMore>
2632
2676
  </element>
2633
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>
2634
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
@@ -140,7 +140,7 @@ module Metanorma
140
140
  parse_content_as :text
141
141
 
142
142
  def process(parent, target, attrs)
143
- /^(?<lang>[^-]*)(-(?<script>.*))?$/ =~ target
143
+ /^(?<lang>[^-]*)(?:-(?<script>.*))?$/ =~ target
144
144
  out = Asciidoctor::Inline.new(parent, :quoted, attrs["text"]).convert
145
145
  if script
146
146
  %{<variant lang=#{lang} script=#{script}>#{out}</variant>}
@@ -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
@@ -5,13 +5,24 @@ module Metanorma
5
5
  return reader if reader.eof?
6
6
 
7
7
  lines = reader.readlines
8
- while !lines.grep(/^embed::/).empty?
9
- headings = lines.grep(/^== /).map(&:strip)
10
- lines = lines.map do |line|
11
- /^embed::/.match?(line) ? embed(line, doc, reader, headings) : line
12
- end.flatten
8
+ headings = lines.grep(/^== /).map(&:strip)
9
+ ret = lines.each_with_object({ lines: [], hdr: [] }) do |line, m|
10
+ process1(line, m, doc, reader, headings)
13
11
  end
14
- ::Asciidoctor::Reader.new lines
12
+ #doc.converter.embed_hdr = ret[:hdr]
13
+ doc.attributes["embed_hdr"] = ret[:hdr]
14
+ ::Asciidoctor::Reader.new ret[:lines].flatten
15
+ end
16
+
17
+ def process1(line, acc, doc, reader, headings)
18
+ if /^embed::/.match?(line)
19
+ e = embed(line, doc, reader, headings)
20
+ acc[:lines] << e[:lines]
21
+ acc[:hdr] << e[:hdr]
22
+ else
23
+ acc[:lines] << line
24
+ end
25
+ acc
15
26
  end
16
27
 
17
28
  def filename(line, doc, reader)
@@ -27,26 +38,36 @@ module Metanorma
27
38
  end
28
39
  end
29
40
 
41
+ def read(inc_path)
42
+ ::File.open inc_path, "r" do |fd|
43
+ readlines_safe(fd).map(&:chomp)
44
+ end
45
+ end
46
+
30
47
  def embed(line, doc, reader, headings)
31
48
  inc_path = filename(line, doc, reader) or return line
32
49
  lines = filter_sections(read(inc_path), headings)
33
50
  doc = Asciidoctor::Document.new [], { safe: :safe }
34
51
  reader = ::Asciidoctor::PreprocessorReader.new doc, lines
35
- strip_header(reader.read_lines)
52
+ ret = strip_header(reader.read_lines)
53
+ embed_recurse(ret, doc, reader, headings)
36
54
  end
37
55
 
38
- def read(inc_path)
39
- ::File.open inc_path, "r" do |fd|
40
- readlines_safe(fd).map(&:chomp)
56
+ def embed_recurse(ret, doc, reader, headings)
57
+ ret1 = ret[:lines].each_with_object({ lines: [], hdr: [] }) do |line, m|
58
+ process1(line, m, doc, reader, headings)
41
59
  end
60
+ { lines: ret1[:lines],
61
+ hdr: { text: ret[:hdr].join("\n"), child: ret1[:hdr] } }
42
62
  end
43
63
 
44
64
  def strip_header(lines)
45
- return lines unless !lines.empty? && lines.first.start_with?("= ")
65
+ return { lines: lines, hdr: nil } unless !lines.empty? &&
66
+ lines.first.start_with?("= ")
46
67
 
47
68
  skip = true
48
- lines.each_with_object([]) do |l, m|
49
- m << l unless skip
69
+ lines.each_with_object({ hdr: [], lines: [] }) do |l, m|
70
+ m[skip ? :hdr : :lines] << l
50
71
  skip = false if !/\S/.match?(l)
51
72
  end
52
73
  end
@@ -56,7 +77,7 @@ module Metanorma
56
77
  lines.each_with_index.with_object([]) do |(l, i), m|
57
78
  if headings.include?(l.strip)
58
79
  skip = true
59
- m.unshift while !m.empty? && /^\S/.match?(m[-1])
80
+ m.pop while !m.empty? && /^\S/.match?(m[-1])
60
81
  elsif skip && /^== |^embed::|^include::/.match?(l)
61
82
  skip = false
62
83
  j = i
@@ -22,9 +22,10 @@ module Metanorma
22
22
  para.set_attr("name", "todo")
23
23
  para.set_attr("caption", "TODO")
24
24
  para.lines[0].sub!(/^TODO: /, "")
25
- todo = Asciidoctor::Block.new(parent, :admonition, attributes: para.attributes,
26
- source: para.lines,
27
- content_model: :compound)
25
+ todo = Asciidoctor::Block
26
+ .new(parent, :admonition, attributes: para.attributes,
27
+ source: para.lines,
28
+ content_model: :compound)
28
29
  parent.blocks[parent.blocks.index(para)] = todo
29
30
  end
30
31
  end
@@ -3,6 +3,10 @@ require "metanorma/processor"
3
3
  module Metanorma
4
4
  module Standoc
5
5
  class Processor < Metanorma::Processor
6
+ class << self
7
+ attr_reader :asciidoctor_backend
8
+ end
9
+
6
10
  def initialize # rubocop:disable Lint/MissingSuper
7
11
  @short = :standoc
8
12
  @input_format = :asciidoc
@@ -22,7 +26,8 @@ module Metanorma
22
26
  end
23
27
 
24
28
  def html_path(file)
25
- File.join(File.dirname(__FILE__), "..", "..", "isodoc", "html", file)
29
+ File.join(File.dirname(__FILE__), "..", "..", "isodoc", "html",
30
+ file)
26
31
  end
27
32
 
28
33
  def output(isodoc_node, inname, outname, format, options = {})
@@ -121,7 +121,7 @@ module Metanorma
121
121
  t.formattedref **{ format: "application/x-isodoc+xml" } do |i|
122
122
  i << ref_normalise_no_format(match[:text])
123
123
  end
124
- yr_match = /[:-](?<year>(19|20)[0-9][0-9])\b/.match(code[:id])
124
+ yr_match = /[:-](?<year>(?:19|20)[0-9][0-9])\b/.match(code[:id])
125
125
  refitem_render1(match, code, t)
126
126
  docnumber(t, code[:id]) unless /^\d+$|^\(.+\)$/.match?(code[:id])
127
127
  conditional_date(t, yr_match || match, false)
@@ -131,6 +131,7 @@ module Metanorma
131
131
  # TODO: alternative where only title is available
132
132
  def refitemcode(item, node)
133
133
  m = NON_ISO_REF.match(item) and return refitem1code(item, m).compact
134
+ m = NON_ISO_REF1.match(item) and return refitem1code(item, m).compact
134
135
  @log.add("AsciiDoc Input", node, "#{MALFORMED_REF}: #{item}")
135
136
  {}
136
137
  end
@@ -148,7 +149,7 @@ module Metanorma
148
149
  end
149
150
 
150
151
  def refitem1yr(code)
151
- yr_match = /[:-](?<year>(19|20)[0-9][0-9])\b/.match(code)
152
+ yr_match = /[:-](?<year>(?:19|20)[0-9][0-9])\b/.match(code)
152
153
  yr_match ? yr_match[:year] : nil
153
154
  end
154
155
 
@@ -162,25 +163,29 @@ module Metanorma
162
163
 
163
164
  ISO_REF =
164
165
  %r{^<ref\sid="(?<anchor>[^"]+)">
165
- \[(?<usrlbl>\([^)]+\))?(?<code>(ISO|IEC)[^0-9]*\s[0-9-]+|IEV)
166
- (:(?<year>[0-9][0-9-]+))?\]</ref>,?\s*(?<text>.*)$}xm.freeze
166
+ \[(?<usrlbl>\([^)]+\))?(?<code>(?:ISO|IEC)[^0-9]*\s[0-9-]+|IEV)
167
+ (?::(?<year>[0-9][0-9-]+))?\]</ref>,?\s*(?<text>.*)$}xm.freeze
167
168
 
168
169
  ISO_REF_NO_YEAR =
169
170
  %r{^<ref\sid="(?<anchor>[^"]+)">
170
- \[(?<usrlbl>\([^)]+\))?(?<code>(ISO|IEC)[^0-9]*\s[0-9-]+):
171
- (--|&\#821[12];)\]</ref>,?\s*
172
- (<fn[^>]*>\s*<p>(?<fn>[^\]]+)</p>\s*</fn>)?,?\s?(?<text>.*)$}xm
171
+ \[(?<usrlbl>\([^)]+\))?(?<code>(?:ISO|IEC)[^0-9]*\s[0-9-]+):
172
+ (?:--|&\#821[12];)\]</ref>,?\s*
173
+ (?:<fn[^>]*>\s*<p>(?<fn>[^\]]+)</p>\s*</fn>)?,?\s?(?<text>.*)$}xm
173
174
  .freeze
174
175
 
175
176
  ISO_REF_ALL_PARTS =
176
177
  %r{^<ref\sid="(?<anchor>[^"]+)">
177
- \[(?<usrlbl>\([^)]+\))?(?<code>(ISO|IEC)[^0-9]*\s[0-9]+)
178
- (:(?<year>--|&\#821[12];|[0-9][0-9-]+))?\s
178
+ \[(?<usrlbl>\([^)]+\))?(?<code>(?:ISO|IEC)[^0-9]*\s[0-9]+)
179
+ (?::(?<year>--|&\#821[12];|[0-9][0-9-]+))?\s
179
180
  \(all\sparts\)\]</ref>,?\s*
180
181
  (<fn[^>]*>\s*<p>(?<fn>[^\]]+)</p>\s*</fn>,?\s?)?(?<text>.*)$}xm.freeze
181
182
 
182
183
  NON_ISO_REF = %r{^<ref\sid="(?<anchor>[^"]+)">
183
- \[(?<usrlbl>\([^)]+\))?(?<code>[^\]]+?)\]</ref>,?\s*(?<text>.*)$}xm
184
+ \[(?<usrlbl>\([^)]+\))?(?<code>.+?)\]</ref>,?\s*(?<text>.*)$}xm
185
+ .freeze
186
+
187
+ NON_ISO_REF1 = %r{^<ref\sid="(?<anchor>[^"]+)">
188
+ (?<usrlbl>\([^)]+\))?(?<code>.+?)</ref>,?\s*(?<text>.*)$}xm
184
189
  .freeze
185
190
 
186
191
  def reference1_matches(item)
@@ -209,18 +214,17 @@ module Metanorma
209
214
  end
210
215
  end
211
216
 
212
- def reference_preproc(node)
217
+ def reference(node)
213
218
  refs = node.items.each_with_object([]) do |b, m|
214
219
  m << reference1code(b.text, node)
215
220
  end
221
+ reference_populate(refs)
222
+ end
223
+
224
+ def reference_populate(refs)
216
225
  results = refs.each_with_index.with_object(Queue.new) do |(ref, i), res|
217
226
  fetch_ref_async(ref.merge(ord: i), i, res)
218
227
  end
219
- [refs, results]
220
- end
221
-
222
- def reference(node)
223
- refs, results = reference_preproc(node)
224
228
  ret = reference_queue(refs, results)
225
229
  noko do |xml|
226
230
  ret.each { |b| reference1out(b, xml) }