metanorma-standoc 1.9.4 → 1.10.3

Sign up to get free protection for your applications and to get access to all the features.
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