metanorma-standoc 1.9.4 → 1.10.3

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 (56) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/rake.yml +1 -1
  3. data/.rubocop.yml +1 -1
  4. data/lib/asciidoctor/standoc/base.rb +0 -1
  5. data/lib/asciidoctor/standoc/blocks.rb +1 -1
  6. data/lib/asciidoctor/standoc/cleanup.rb +61 -2
  7. data/lib/asciidoctor/standoc/cleanup_block.rb +0 -1
  8. data/lib/asciidoctor/standoc/cleanup_boilerplate.rb +2 -2
  9. data/lib/asciidoctor/standoc/cleanup_footnotes.rb +0 -1
  10. data/lib/asciidoctor/standoc/cleanup_inline.rb +117 -77
  11. data/lib/asciidoctor/standoc/cleanup_maths.rb +0 -1
  12. data/lib/asciidoctor/standoc/cleanup_ref.rb +7 -0
  13. data/lib/asciidoctor/standoc/cleanup_section.rb +0 -1
  14. data/lib/asciidoctor/standoc/cleanup_terms.rb +19 -18
  15. data/lib/asciidoctor/standoc/converter.rb +3 -0
  16. data/lib/asciidoctor/standoc/datamodel/diagram_preprocessor.rb +22 -21
  17. data/lib/asciidoctor/standoc/front.rb +0 -1
  18. data/lib/asciidoctor/standoc/front_contributor.rb +0 -1
  19. data/lib/asciidoctor/standoc/inline.rb +20 -17
  20. data/lib/asciidoctor/standoc/isodoc.rng +56 -8
  21. data/lib/asciidoctor/standoc/macros.rb +25 -5
  22. data/lib/asciidoctor/standoc/macros_plantuml.rb +21 -23
  23. data/lib/asciidoctor/standoc/macros_terms.rb +60 -23
  24. data/lib/asciidoctor/standoc/ref.rb +60 -56
  25. data/lib/asciidoctor/standoc/section.rb +19 -12
  26. data/lib/asciidoctor/standoc/term_lookup_cleanup.rb +69 -30
  27. data/lib/asciidoctor/standoc/terms.rb +1 -1
  28. data/lib/asciidoctor/standoc/utils.rb +0 -1
  29. data/lib/asciidoctor/standoc/validate.rb +22 -8
  30. data/lib/isodoc/html/html_titlepage.html +81 -0
  31. data/lib/isodoc/html/htmlstyle.css +983 -0
  32. data/lib/isodoc/html/htmlstyle.scss +714 -0
  33. data/lib/isodoc/html/scripts.html +71 -0
  34. data/lib/metanorma/standoc/processor.rb +16 -7
  35. data/lib/metanorma/standoc/version.rb +1 -1
  36. data/metanorma-standoc.gemspec +3 -3
  37. data/spec/asciidoctor/blocks_spec.rb +8 -8
  38. data/spec/asciidoctor/cleanup_sections_spec.rb +899 -864
  39. data/spec/asciidoctor/cleanup_spec.rb +85 -20
  40. data/spec/asciidoctor/isobib_cache_spec.rb +4 -6
  41. data/spec/asciidoctor/lists_spec.rb +147 -135
  42. data/spec/asciidoctor/macros_json2text_spec.rb +1 -1
  43. data/spec/asciidoctor/macros_plantuml_spec.rb +165 -104
  44. data/spec/asciidoctor/macros_spec.rb +813 -168
  45. data/spec/asciidoctor/refs_spec.rb +12 -12
  46. data/spec/asciidoctor/validate_spec.rb +76 -20
  47. data/spec/support/shared_examples/structured_data_2_text_preprocessor.rb +34 -34
  48. data/spec/vcr_cassettes/dated_iso_ref_joint_iso_iec.yml +50 -50
  49. data/spec/vcr_cassettes/isobib_get_123.yml +13 -13
  50. data/spec/vcr_cassettes/isobib_get_123_1.yml +26 -26
  51. data/spec/vcr_cassettes/isobib_get_123_1_fr.yml +34 -34
  52. data/spec/vcr_cassettes/isobib_get_123_2001.yml +14 -14
  53. data/spec/vcr_cassettes/isobib_get_124.yml +11 -11
  54. data/spec/vcr_cassettes/rfcbib_get_rfc8341.yml +14 -14
  55. data/spec/vcr_cassettes/separates_iev_citations_by_top_level_clause.yml +51 -61
  56. metadata +11 -7
@@ -1,6 +1,5 @@
1
1
  require "nokogiri"
2
2
  require "pathname"
3
- require "open-uri"
4
3
  require "html2doc"
5
4
  require "asciimath2unitsml"
6
5
  require_relative "./cleanup_block"
@@ -149,7 +149,14 @@ module Asciidoctor
149
149
  end
150
150
  end
151
151
 
152
+ def bibitem_nested_id(xmldoc)
153
+ xmldoc.xpath("//bibitem//bibitem").each do |b|
154
+ b.delete("id")
155
+ end
156
+ end
157
+
152
158
  def bibitem_cleanup(xmldoc)
159
+ bibitem_nested_id(xmldoc)
153
160
  ref_dl_cleanup(xmldoc)
154
161
  fetch_local_bibitem(xmldoc)
155
162
  end
@@ -1,7 +1,6 @@
1
1
  require "date"
2
2
  require "htmlentities"
3
3
  require "json"
4
- require "open-uri"
5
4
  require "mathml2asciimath"
6
5
  require_relative "cleanup_section_names"
7
6
 
@@ -60,15 +60,15 @@ module Asciidoctor
60
60
 
61
61
  def term_children_cleanup(xmldoc)
62
62
  xmldoc.xpath("//term").each do |t|
63
- t.xpath("./termnote").each { |n| t << n.remove }
64
- t.xpath("./termexample").each { |n| t << n.remove }
65
- t.xpath("./termsource").each { |n| t << n.remove }
63
+ %w(termnote termexample termsource).each do |w|
64
+ t.xpath("./#{w}").each { |n| t << n.remove }
65
+ end
66
66
  end
67
- end
67
+ end
68
68
 
69
69
  def termdef_from_termbase(xmldoc)
70
70
  xmldoc.xpath("//term").each do |x|
71
- if c = x.at("./origin/termref") and !x.at("./definition")
71
+ if (c = x.at("./origin/termref")) && !x.at("./definition")
72
72
  x.at("./origin").previous = fetch_termbase(c["base"], c.text)
73
73
  end
74
74
  end
@@ -93,33 +93,34 @@ module Asciidoctor
93
93
  termdomain1_cleanup(xmldoc)
94
94
  termnote_example_cleanup(xmldoc)
95
95
  termdef_subclause_cleanup(xmldoc)
96
- term_children_cleanup(xmldoc)
96
+ term_children_cleanup(xmldoc)
97
97
  termdocsource_cleanup(xmldoc)
98
- end
98
+ end
99
99
 
100
100
  # Indices sort after letter but before any following
101
101
  # letter (x, x_m, x_1, xa); we use colon to force that sort order.
102
102
  # Numbers sort *after* letters; we use thorn to force that sort order.
103
- def symbol_key(x)
104
- key = x.dup
103
+ def symbol_key(sym)
104
+ key = sym.dup
105
105
  key.traverse do |n|
106
106
  next unless n.name == "math"
107
+
107
108
  n.replace(grkletters(MathML2AsciiMath.m2a(n.to_xml)))
108
109
  end
109
110
  ret = Nokogiri::XML(key.to_xml)
110
- HTMLEntities.new.decode(ret.text.downcase).
111
- gsub(/[\[\]\{\}<>\(\)]/, "").gsub(/\s/m, "").
112
- gsub(/[[:punct:]]|[_^]/, ":\\0").gsub(/`/, "").
113
- gsub(/[0-9]+/, "þ\\0")
111
+ HTMLEntities.new.decode(ret.text.downcase)
112
+ .gsub(/[\[\]{}<>()]/, "").gsub(/\s/m, "")
113
+ .gsub(/[[:punct:]]|[_^]/, ":\\0").gsub(/`/, "")
114
+ .gsub(/[0-9]+/, "þ\\0")
114
115
  end
115
-
116
+
116
117
  def grkletters(x)
117
118
  x.gsub(/\b(alpha|beta|gamma|delta|epsilon|zeta|eta|theta|iota|kappa|lambda|mu|nu|xi|omicron|pi|rho|sigma|tau|upsilon|phi|chi|psi|omega)\b/i, "&\\1;")
118
119
  end
119
120
 
120
- def extract_symbols_list(dl)
121
+ def extract_symbols_list(dlist)
121
122
  dl_out = []
122
- dl.xpath("./dt | ./dd").each do |dtd|
123
+ dlist.xpath("./dt | ./dd").each do |dtd|
123
124
  if dtd.name == "dt"
124
125
  dl_out << { dt: dtd.remove, key: symbol_key(dtd) }
125
126
  else
@@ -128,7 +129,7 @@ module Asciidoctor
128
129
  end
129
130
  dl_out
130
131
  end
131
-
132
+
132
133
  def symbols_cleanup(docxml)
133
134
  docxml.xpath("//definitions/dl").each do |dl|
134
135
  dl_out = extract_symbols_list(dl)
@@ -136,7 +137,7 @@ module Asciidoctor
136
137
  dl.children = dl_out.map { |d| d[:dt].to_s + d[:dd].to_s }.join("\n")
137
138
  end
138
139
  docxml
139
- end
140
+ end
140
141
  end
141
142
  end
142
143
  end
@@ -37,6 +37,7 @@ module Asciidoctor
37
37
  inline_macro Asciidoctor::Standoc::VariantInlineMacro
38
38
  inline_macro Asciidoctor::Standoc::FootnoteBlockInlineMacro
39
39
  inline_macro Asciidoctor::Standoc::TermRefInlineMacro
40
+ inline_macro Asciidoctor::Standoc::SymbolRefInlineMacro
40
41
  inline_macro Asciidoctor::Standoc::IndexXrefInlineMacro
41
42
  inline_macro Asciidoctor::Standoc::IndexRangeInlineMacro
42
43
  inline_macro Asciidoctor::Standoc::AddMacro
@@ -46,6 +47,8 @@ module Asciidoctor
46
47
  inline_macro Asciidoctor::Standoc::FormTextareaMacro
47
48
  inline_macro Asciidoctor::Standoc::FormSelectMacro
48
49
  inline_macro Asciidoctor::Standoc::FormOptionMacro
50
+ inline_macro Asciidoctor::Standoc::ToCInlineMacro
51
+ block_macro Metanorma::Plugin::Lutaml::LutamlDiagramBlockMacro
49
52
  block Asciidoctor::Standoc::ToDoAdmonitionBlock
50
53
  treeprocessor Asciidoctor::Standoc::ToDoInlineAdmonitionBlock
51
54
  block Asciidoctor::Standoc::PlantUMLBlockMacro
@@ -1,16 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'erb'
4
- require 'asciidoctor/standoc/datamodel/plantuml_renderer'
3
+ require "erb"
4
+ require "asciidoctor/standoc/datamodel/plantuml_renderer"
5
5
 
6
6
  module Asciidoctor
7
7
  module Standoc
8
8
  module Datamodel
9
9
  class DiagramPreprocessor < Asciidoctor::Extensions::Preprocessor
10
- BLOCK_START_REGEXP = /\{(.+?)\.\*,(.+),(.+)\}/
11
- BLOCK_END_REGEXP = /\A\{[A-Z]+\}\z/
12
- MARCO_REGEXP = /\[datamodel_diagram,([^,]+),?(.+)?\]/
13
- TEMPLATES_PATH = File.expand_path('../views/datamodel', __dir__).freeze
10
+ BLOCK_START_REGEXP = /\{(.+?)\.\*,(.+),(.+)\}/.freeze
11
+ BLOCK_END_REGEXP = /\A\{[A-Z]+\}\z/.freeze
12
+ MARCO_REGEXP = /\[datamodel_diagram,([^,]+),?(.+)?\]/.freeze
13
+ TEMPLATES_PATH = File.expand_path("../views/datamodel", __dir__).freeze
14
14
  # search document for block `datamodel_diagram`
15
15
  # read include derectives that goes after that in block and transform
16
16
  # into plantuml block
@@ -33,7 +33,7 @@ module Asciidoctor
33
33
  end
34
34
 
35
35
  def parse_datamodel_marco(yaml_path, include_path, document)
36
- include_path ||= File.join(File.dirname(yaml_path), '..', 'models')
36
+ include_path ||= File.join(File.dirname(yaml_path), "..", "models")
37
37
  include_path = yaml_relative_path(include_path, document)
38
38
  yaml_relative_to_doc_path = yaml_relative_path(yaml_path, document)
39
39
  view_hash = YAML.safe_load(File.read(yaml_relative_to_doc_path))
@@ -43,7 +43,7 @@ module Asciidoctor
43
43
  end
44
44
 
45
45
  def yaml_relative_path(file_path, document)
46
- docfile = document.attributes['docfile'] || '.'
46
+ docfile = document.attributes["docfile"] || "."
47
47
  docfile_directory = File.dirname(docfile)
48
48
  document.path_resolver.system_path(file_path, docfile_directory)
49
49
  end
@@ -51,11 +51,11 @@ module Asciidoctor
51
51
  def import_format(include_path, import_name, values)
52
52
  include_content = File.read(File.join(
53
53
  include_path,
54
- "#{import_name}.yml"
55
- ))
54
+ "#{import_name}.yml",
55
+ ))
56
56
  content = YAML.safe_load(include_content)
57
57
  if values
58
- content['skipSection'] = values['skipSection']
58
+ content["skipSection"] = values["skipSection"]
59
59
  end
60
60
  content
61
61
  end
@@ -63,36 +63,37 @@ module Asciidoctor
63
63
  def format_import_directives(imports, include_path)
64
64
  imports
65
65
  .each_with_object({}) do |(import_name, values), res|
66
- full_model_name = import_name.split('/').join
66
+ full_model_name = import_name.split("/").join
67
67
  content = import_format(include_path, import_name, values)
68
- res[content['name'] || full_model_name] = content
68
+ res[content["name"] || full_model_name] = content
69
69
  end.compact
70
70
  end
71
71
 
72
72
  def prepare_view_hash(view_hash, all_imports)
73
73
  view_hash.merge!(
74
- 'classes' => model_type(all_imports, 'class'),
75
- 'enums' => model_type(all_imports, 'enum'),
76
- 'relations' => view_hash['relations'] || [],
77
- 'fidelity' => (view_hash['fidelity'] || {})
78
- .merge!('classes' => model_type(all_imports, 'class'))
74
+ "classes" => model_type(all_imports, "class"),
75
+ "enums" => model_type(all_imports, "enum"),
76
+ "relations" => view_hash["relations"] || [],
77
+ "fidelity" => (view_hash["fidelity"] || {})
78
+ .merge!("classes" => model_type(all_imports,
79
+ "class")),
79
80
  )
80
81
  end
81
82
 
82
83
  def model_type(imports, type)
83
84
  imports
84
85
  .select do |_name, elem|
85
- elem['modelType'] == type
86
+ elem["modelType"] == type
86
87
  end
87
88
  end
88
89
 
89
90
  def plantuml_representations(view_hash, view_path, include_path)
90
91
  yaml_directory = File.dirname(view_path)
91
- all_imports = format_import_directives(view_hash['imports'],
92
+ all_imports = format_import_directives(view_hash["imports"],
92
93
  include_path)
93
94
  prepare_view_hash(view_hash, all_imports)
94
95
  Asciidoctor::Datamodel::PlantumlRenderer
95
- .new(view_hash, File.join(yaml_directory, '..'))
96
+ .new(view_hash, File.join(yaml_directory, ".."))
96
97
  .render
97
98
  .split("\n")
98
99
  end
@@ -2,7 +2,6 @@ require "date"
2
2
  require "nokogiri"
3
3
  require "htmlentities"
4
4
  require "pathname"
5
- require "open-uri"
6
5
  require_relative "./front_contributor"
7
6
 
8
7
  module Asciidoctor
@@ -2,7 +2,6 @@ require "date"
2
2
  require "nokogiri"
3
3
  require "htmlentities"
4
4
  require "pathname"
5
- require "open-uri"
6
5
  require "csv"
7
6
 
8
7
  module Asciidoctor
@@ -46,13 +46,13 @@ module Asciidoctor
46
46
  def inline_anchor_xref_attrs(node)
47
47
  m = /^(?<drop>droploc%)?(?<case>capital%|lowercase%)?(?<drop2>droploc%)?
48
48
  (?<fn>fn:?\s*)?(?<text>.*)$/x.match node.text
49
- casing = m.nil? ? nil : m[:case]&.sub(/%$/, "")
50
- droploc = m.nil? ? nil : ((m[:drop].nil? && m[:drop2].nil?) ? nil: true)
51
- f = (m.nil? || m[:fn].nil?) ? "inline" : "footnote"
52
- c = (!m.nil? && (%i[case fn drop drop2].any? { |x| !m[x].nil? })) ?
53
- m[:text] : node.text
54
49
  t = node.target.gsub(/^#/, "").gsub(%r{(\.xml|\.adoc)(#.*$)}, "\\2")
55
- { target: t, type: f, case: casing, droploc: droploc, text: c }
50
+ m.nil? and return { target: t, type: "inline", text: node.text }
51
+ droploc = m[:drop].nil? && m[:drop2].nil? ? nil : true
52
+ f = m[:fn].nil? ? "inline" : "footnote"
53
+ c = %i[case fn drop drop2].any? { |x| !m[x].nil? } ? m[:text] : node.text
54
+ { target: t, type: f, case: m[:case]&.sub(/%$/, ""), droploc: droploc,
55
+ text: c }
56
56
  end
57
57
 
58
58
  def inline_anchor_link(node)
@@ -115,12 +115,12 @@ module Asciidoctor
115
115
 
116
116
  def xml_encode(text)
117
117
  HTMLEntities.new.encode(text, :basic, :hexadecimal)
118
- .gsub(/&amp;gt;/, ">").gsub(/\&amp;lt;/, "<").gsub(/&amp;amp;/, "&")
118
+ .gsub(/&amp;gt;/, ">").gsub(/&amp;lt;/, "<").gsub(/&amp;amp;/, "&")
119
119
  .gsub(/&gt;/, ">").gsub(/&lt;/, "<").gsub(/&amp;/, "&")
120
120
  .gsub(/&quot;/, '"').gsub(/&#xa;/, "\n").gsub(/&amp;#/, "&#")
121
121
  end
122
122
 
123
- def latex_parse(text)
123
+ def latex_parse1(text)
124
124
  lxm_input = Unicode2LaTeX.unicode2latex(HTMLEntities.new.decode(text))
125
125
  results = Latexmath.parse(lxm_input).to_mathml
126
126
  results.nil? and
@@ -134,16 +134,19 @@ module Asciidoctor
134
134
  <([^:>&]+:)?math(\s+[^>&]+)?>/x.match? text
135
135
  math = xml_encode(text)
136
136
  xml.stem math, **{ type: "MathML" }
137
- elsif style == :latexmath
138
- latex = latex_parse(text) or return xml.stem **{ type: "MathML" }
139
- xml.stem **{ type: "MathML" } do |s|
140
- math = Nokogiri::XML.fragment(latex.sub(/<\?[^>]+>/, ""))
141
- .elements[0]
142
- math.delete("alttext")
143
- s.parent.children = math
144
- end
137
+ elsif style == :latexmath then latex_parse(text, xml)
145
138
  else
146
- xml.stem text&.gsub(/\&amp;#/, "&#"), **{ type: "AsciiMath" }
139
+ xml.stem text&.gsub(/&amp;#/, "&#"), **{ type: "AsciiMath" }
140
+ end
141
+ end
142
+
143
+ def latex_parse(text, xml)
144
+ latex = latex_parse1(text) or return xml.stem **{ type: "MathML" }
145
+ xml.stem **{ type: "MathML" } do |s|
146
+ math = Nokogiri::XML.fragment(latex.sub(/<\?[^>]+>/, ""))
147
+ .elements[0]
148
+ math.delete("alttext")
149
+ s.parent.children = math
147
150
  end
148
151
  end
149
152
 
@@ -204,6 +204,18 @@
204
204
  </zeroOrMore>
205
205
  </element>
206
206
  </define>
207
+ <define name="dt">
208
+ <element name="dt">
209
+ <optional>
210
+ <attribute name="id">
211
+ <data type="ID"/>
212
+ </attribute>
213
+ </optional>
214
+ <zeroOrMore>
215
+ <ref name="TextElement"/>
216
+ </zeroOrMore>
217
+ </element>
218
+ </define>
207
219
  <define name="example">
208
220
  <element name="example">
209
221
  <attribute name="id">
@@ -899,7 +911,7 @@
899
911
  </include>
900
912
  <!-- end overrides -->
901
913
  <define name="docsubtype">
902
- <element name="docsubtype">
914
+ <element name="subdoctype">
903
915
  <ref name="DocumentSubtype"/>
904
916
  </element>
905
917
  </define>
@@ -955,7 +967,34 @@
955
967
  <define name="concept">
956
968
  <element name="concept">
957
969
  <optional>
958
- <attribute name="term"/>
970
+ <attribute name="ital">
971
+ <data type="boolean"/>
972
+ </attribute>
973
+ </optional>
974
+ <optional>
975
+ <attribute name="ref">
976
+ <data type="boolean"/>
977
+ </attribute>
978
+ </optional>
979
+ <optional>
980
+ <element name="refterm">
981
+ <zeroOrMore>
982
+ <choice>
983
+ <ref name="PureTextElement"/>
984
+ <ref name="stem"/>
985
+ </choice>
986
+ </zeroOrMore>
987
+ </element>
988
+ </optional>
989
+ <optional>
990
+ <element name="renderterm">
991
+ <zeroOrMore>
992
+ <choice>
993
+ <ref name="PureTextElement"/>
994
+ <ref name="stem"/>
995
+ </choice>
996
+ </zeroOrMore>
997
+ </element>
959
998
  </optional>
960
999
  <choice>
961
1000
  <ref name="eref"/>
@@ -981,6 +1020,9 @@
981
1020
  </attribute>
982
1021
  <attribute name="name"/>
983
1022
  <attribute name="action"/>
1023
+ <optional>
1024
+ <attribute name="class"/>
1025
+ </optional>
984
1026
  <zeroOrMore>
985
1027
  <choice>
986
1028
  <ref name="TextElement"/>
@@ -1212,6 +1254,12 @@
1212
1254
  <optional>
1213
1255
  <attribute name="type"/>
1214
1256
  </optional>
1257
+ <optional>
1258
+ <attribute name="identifier"/>
1259
+ </optional>
1260
+ <optional>
1261
+ <attribute name="prefix"/>
1262
+ </optional>
1215
1263
  <text/>
1216
1264
  </define>
1217
1265
  <define name="ics">
@@ -1473,26 +1521,26 @@
1473
1521
  <optional>
1474
1522
  <ref name="section-title"/>
1475
1523
  </optional>
1476
- <group>
1524
+ <choice>
1477
1525
  <choice>
1478
1526
  <group>
1479
- <zeroOrMore>
1527
+ <oneOrMore>
1480
1528
  <ref name="BasicBlock"/>
1481
- </zeroOrMore>
1529
+ </oneOrMore>
1482
1530
  <zeroOrMore>
1483
1531
  <ref name="note"/>
1484
1532
  </zeroOrMore>
1485
1533
  </group>
1486
1534
  <ref name="amend"/>
1487
1535
  </choice>
1488
- <zeroOrMore>
1536
+ <oneOrMore>
1489
1537
  <choice>
1490
1538
  <ref name="clause-subsection"/>
1491
1539
  <ref name="terms"/>
1492
1540
  <ref name="definitions"/>
1493
1541
  </choice>
1494
- </zeroOrMore>
1495
- </group>
1542
+ </oneOrMore>
1543
+ </choice>
1496
1544
  </define>
1497
1545
  <define name="Annex-Section">
1498
1546
  <optional>
@@ -2,6 +2,7 @@ require "asciidoctor/extensions"
2
2
  require "fileutils"
3
3
  require "uuidtools"
4
4
  require "yaml"
5
+ require "csv"
5
6
  require_relative "./macros_plantuml"
6
7
  require_relative "./macros_terms"
7
8
  require_relative "./macros_form"
@@ -75,7 +76,7 @@ module Asciidoctor
75
76
  def supply_br(lines)
76
77
  ignore = false
77
78
  lines.each_with_index do |l, i|
78
- /^(--+|====+|\|===|\.\.\.\.+|\*\*\*\*+|\+\+\+\++|\`\`\`\`+|____\+)$/
79
+ /^(--+|====+|\|===|\.\.\.\.+|\*\*\*\*+|\+\+\+\++|````+|____\+)$/
79
80
  .match(l) && (ignore = !ignore)
80
81
  next if l.empty? || l.match(/ \+$/) || /^\[.*\]$/.match?(l) || ignore
81
82
  next if i == lines.size - 1 ||
@@ -107,7 +108,7 @@ module Asciidoctor
107
108
  if (attributes.size == 1) && attributes.key?("text")
108
109
  rt = attributes["text"]
109
110
  elsif (attributes.size == 2) && attributes.key?(1) &&
110
- attributes.key?("rpbegin")
111
+ attributes.key?("rpbegin")
111
112
  rt = attributes[1] || ""
112
113
  else
113
114
  rpbegin = attributes["rpbegin"]
@@ -143,7 +144,7 @@ module Asciidoctor
143
144
  para.set_attr("caption", "TODO")
144
145
  para.lines[0].sub!(/^TODO: /, "")
145
146
  todo = Block.new(parent, :admonition, attributes: para.attributes,
146
- source: para.lines, content_model: :compound)
147
+ source: para.lines, content_model: :compound)
147
148
  parent.blocks[parent.blocks.index(para)] = todo
148
149
  end
149
150
  end
@@ -168,9 +169,11 @@ module Asciidoctor
168
169
  def process(parent, target, attrs)
169
170
  /^(?<lang>[^-]*)(-(?<script>.*))?$/ =~ target
170
171
  out = Asciidoctor::Inline.new(parent, :quoted, attrs["text"]).convert
171
- script ?
172
- %{<variant lang=#{lang} script=#{script}>#{out}</variant>} :
172
+ if script
173
+ %{<variant lang=#{lang} script=#{script}>#{out}</variant>}
174
+ else
173
175
  %{<variant lang=#{lang}>#{out}</variant>}
176
+ end
174
177
  end
175
178
  end
176
179
 
@@ -209,5 +212,22 @@ module Asciidoctor
209
212
  %{<del>#{out}</del>}
210
213
  end
211
214
  end
215
+
216
+ class ToCInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
217
+ use_dsl
218
+ named :toc
219
+ parse_content_as :text
220
+ using_format :short
221
+
222
+ def process(parent, _target, attrs)
223
+ out = Asciidoctor::Inline.new(parent, :quoted, attrs["text"]).convert
224
+ content = CSV.parse_line(out).map do |x|
225
+ x.sub!(/^(["'])(.+)\1/, "\\2")
226
+ m = /^(.*?)(:\d+)?$/.match(x)
227
+ %{<toc-xpath depth='#{m[2]&.sub(/:/, '') || 1}'>#{m[1]}</toc-xpath>}
228
+ end.join
229
+ "<toc>#{content}</toc>"
230
+ end
231
+ end
212
232
  end
213
233
  end