metanorma-standoc 1.10.0 → 1.10.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/lib/asciidoctor/standoc/base.rb +0 -1
  3. data/lib/asciidoctor/standoc/blocks.rb +1 -1
  4. data/lib/asciidoctor/standoc/cleanup.rb +62 -2
  5. data/lib/asciidoctor/standoc/cleanup_block.rb +0 -1
  6. data/lib/asciidoctor/standoc/cleanup_boilerplate.rb +2 -2
  7. data/lib/asciidoctor/standoc/cleanup_footnotes.rb +0 -1
  8. data/lib/asciidoctor/standoc/cleanup_maths.rb +0 -1
  9. data/lib/asciidoctor/standoc/cleanup_section.rb +0 -1
  10. data/lib/asciidoctor/standoc/converter.rb +3 -0
  11. data/lib/asciidoctor/standoc/datamodel/diagram_preprocessor.rb +22 -21
  12. data/lib/asciidoctor/standoc/front.rb +0 -1
  13. data/lib/asciidoctor/standoc/front_contributor.rb +0 -1
  14. data/lib/asciidoctor/standoc/isodoc.rng +44 -7
  15. data/lib/asciidoctor/standoc/macros.rb +25 -5
  16. data/lib/asciidoctor/standoc/macros_plantuml.rb +3 -3
  17. data/lib/asciidoctor/standoc/macros_terms.rb +34 -7
  18. data/lib/asciidoctor/standoc/ref.rb +60 -56
  19. data/lib/asciidoctor/standoc/section.rb +19 -12
  20. data/lib/asciidoctor/standoc/term_lookup_cleanup.rb +59 -18
  21. data/lib/asciidoctor/standoc/utils.rb +0 -1
  22. data/lib/asciidoctor/standoc/validate.rb +4 -3
  23. data/lib/isodoc/html/html_titlepage.html +81 -0
  24. data/lib/isodoc/html/htmlstyle.css +983 -0
  25. data/lib/isodoc/html/htmlstyle.scss +714 -0
  26. data/lib/isodoc/html/scripts.html +71 -0
  27. data/lib/metanorma/standoc/processor.rb +16 -7
  28. data/lib/metanorma/standoc/version.rb +1 -1
  29. data/metanorma-standoc.gemspec +1 -1
  30. data/spec/asciidoctor/blocks_spec.rb +2 -2
  31. data/spec/asciidoctor/cleanup_sections_spec.rb +899 -864
  32. data/spec/asciidoctor/cleanup_spec.rb +64 -14
  33. data/spec/asciidoctor/macros_json2text_spec.rb +1 -1
  34. data/spec/asciidoctor/macros_plantuml_spec.rb +165 -104
  35. data/spec/asciidoctor/macros_spec.rb +396 -75
  36. data/spec/asciidoctor/validate_spec.rb +12 -2
  37. data/spec/support/shared_examples/structured_data_2_text_preprocessor.rb +34 -34
  38. data/spec/vcr_cassettes/dated_iso_ref_joint_iso_iec.yml +50 -50
  39. data/spec/vcr_cassettes/isobib_get_123.yml +12 -12
  40. data/spec/vcr_cassettes/isobib_get_123_1.yml +23 -23
  41. data/spec/vcr_cassettes/isobib_get_123_1_fr.yml +34 -34
  42. data/spec/vcr_cassettes/isobib_get_123_2001.yml +13 -13
  43. data/spec/vcr_cassettes/isobib_get_124.yml +12 -12
  44. data/spec/vcr_cassettes/rfcbib_get_rfc8341.yml +14 -14
  45. data/spec/vcr_cassettes/separates_iev_citations_by_top_level_clause.yml +46 -46
  46. metadata +8 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f802ef3bf91b1b1af85aa22ca72569b6a6d74b29ed4389373e6b42e7d364b016
4
- data.tar.gz: 55bd7031c2f7a2623955c9d1778b48a5a1666d15a0fe160a8058b544ffe60f92
3
+ metadata.gz: 9189fd92cd1faa176828d42a9f0e7b7b58dc995eeb945fad0d13214d41c54c0d
4
+ data.tar.gz: a6fa58d732b182153c56c04b9e83df2788abd01a497d12ed9746e990662ecec1
5
5
  SHA512:
6
- metadata.gz: 59462520c525758884fdeac23103756b75908daf58707c25ed1420c3e7184e6c3cfaaa7ecd3770619cb3f5d7d9eedc9778b96980b5a33fcdedbea015da9e2684
7
- data.tar.gz: ad562abbf62b1217ab40c933a1f32fe7dbbc474561c47ff0ed91c7de9e9262e3b0612393d8354eccacf30b034316635f5c84aa80f24cc2d5e6e5650bd918e485
6
+ metadata.gz: 4c5ae33422d77c5ce51e88c2d8006a61795542949687f7ceaec0e253298f15398d1e1a3bb65314e834952cb370d44d03b3af759f8be9e51487709e5d926ac6ae
7
+ data.tar.gz: 341c38c603a0f7b0f7913605309f633e5b76e8051ea41a6205342ec5b54fb3e4fb8799198c2deb12871251e2956ef2d09cb842ca1106baea042a56094b0c891f
@@ -3,7 +3,6 @@ require "nokogiri"
3
3
  require "htmlentities"
4
4
  require "json"
5
5
  require "pathname"
6
- require "open-uri"
7
6
  require "isodoc"
8
7
  require "relaton"
9
8
  require "fileutils"
@@ -41,7 +41,7 @@ module Asciidoctor
41
41
  def form(node)
42
42
  noko do |xml|
43
43
  xml.form **attr_code(
44
- id: Metanorma::Utils::anchor_or_uuid,
44
+ id: Metanorma::Utils::anchor_or_uuid, class: node.attr("class"),
45
45
  name: node.attr("name"), action: node.attr("action")
46
46
  ) do |f|
47
47
  f << node.content
@@ -1,6 +1,5 @@
1
1
  require "nokogiri"
2
2
  require "pathname"
3
- require "open-uri"
4
3
  require "html2doc"
5
4
  require_relative "./cleanup_block"
6
5
  require_relative "./cleanup_footnotes"
@@ -48,6 +47,7 @@ module Asciidoctor
48
47
  xref_cleanup(xmldoc)
49
48
  concept_cleanup(xmldoc)
50
49
  origin_cleanup(xmldoc)
50
+ bookmark_cleanup(xmldoc)
51
51
  termdef_cleanup(xmldoc)
52
52
  RelatonIev::iev_cleanup(xmldoc, @bibdb)
53
53
  element_name_cleanup(xmldoc)
@@ -58,11 +58,11 @@ module Asciidoctor
58
58
  mathml_cleanup(xmldoc)
59
59
  script_cleanup(xmldoc)
60
60
  docidentifier_cleanup(xmldoc)
61
- bookmark_cleanup(xmldoc)
62
61
  requirement_cleanup(xmldoc)
63
62
  bibdata_cleanup(xmldoc)
64
63
  svgmap_cleanup(xmldoc)
65
64
  boilerplate_cleanup(xmldoc)
65
+ toc_cleanup(xmldoc)
66
66
  smartquotes_cleanup(xmldoc)
67
67
  variant_cleanup(xmldoc)
68
68
  para_cleanup(xmldoc)
@@ -85,6 +85,30 @@ module Asciidoctor
85
85
  end
86
86
 
87
87
  def smartquotes_cleanup1(xmldoc)
88
+ uninterrupt_quotes_around_xml(xmldoc)
89
+ dumb2smart_quotes(xmldoc)
90
+ end
91
+
92
+ # "abc<tag/>", def => "abc",<tag/> def
93
+ def uninterrupt_quotes_around_xml(xmldoc)
94
+ xmldoc.xpath("//*[following::text()[1]"\
95
+ "[starts-with(., '\"') or starts-with(., \"'\")]]")
96
+ .each do |x|
97
+ next if !x.ancestors("pre, tt, sourcecode, stem, figure").empty?
98
+ uninterrupt_quotes_around_xml1(x)
99
+ end
100
+ end
101
+
102
+ def uninterrupt_quotes_around_xml1(elem)
103
+ prev = elem.at(".//preceding::text()[1]") or return
104
+ /\S$/.match?(prev.text) or return
105
+ foll = elem.at(".//following::text()[1]")
106
+ m = /^(["'][[:punct:]]*)(\s|$)/.match(HTMLEntities.new.decode(foll&.text)) or return
107
+ foll.content = foll.text.sub(/^(["'][[:punct:]]*)/, "")
108
+ prev.content = "#{prev.text}#{m[1]}"
109
+ end
110
+
111
+ def dumb2smart_quotes(xmldoc)
88
112
  (xmldoc.xpath("//*[child::text()]") - xmldoc.xpath(IGNORE_DUMBQUOTES))
89
113
  .each do |x|
90
114
  x.children.each do |n|
@@ -167,6 +191,42 @@ module Asciidoctor
167
191
  end
168
192
  end
169
193
  end
194
+
195
+ def toc_cleanup(xmldoc)
196
+ xmldoc.xpath("//p[toc]").each do |x|
197
+ x.xpath("./toc").reverse.each do |t|
198
+ x.next = t
199
+ end
200
+ x.remove if x.text.strip.empty?
201
+ end
202
+ xmldoc.xpath("//toc").each { |t| toc_cleanup1(t, xmldoc) }
203
+ end
204
+
205
+ def toc_index(toc, xmldoc)
206
+ depths = toc.xpath("./toc-xpath").each_with_object({}) do |x, m|
207
+ m[x.text] = x["depth"]
208
+ end
209
+ depths.keys.each_with_object([]) do |key, arr|
210
+ xmldoc.xpath(key).each do |x|
211
+ arr << { text: x.children.to_xml, depth: depths[key].to_i,
212
+ target: x.xpath("(./ancestor-or-self::*/@id)[last()]")[0].text,
213
+ line: x.line }
214
+ end
215
+ end.sort_by { |a| a[:line] }
216
+ end
217
+
218
+ def toc_cleanup1(toc, xmldoc)
219
+ depth = 1
220
+ ret = ""
221
+ toc_index(toc, xmldoc).each do |x|
222
+ if depth > x[:depth] then ret += "</ul></li>" * (depth - x[:depth])
223
+ elsif depth < x[:depth] then ret += "<li><ul>" * (x[:depth] - depth)
224
+ end
225
+ ret += "<li><xref target='#{x[:target]}'>#{x[:text]}</xref></li>"
226
+ depth = x[:depth]
227
+ end
228
+ toc.children = "<ul>#{ret}</ul>"
229
+ end
170
230
  end
171
231
  end
172
232
  end
@@ -1,6 +1,5 @@
1
1
  require "date"
2
2
  require "htmlentities"
3
- require "open-uri"
4
3
 
5
4
  module Asciidoctor
6
5
  module Standoc
@@ -158,11 +158,11 @@ module Asciidoctor
158
158
  xmldoc.root << "<bibliography/>" and ins = xmldoc.at("bibliography")
159
159
  ins = ins.add_child("<references hidden='true' normative='false'/>").first
160
160
  refs.each do |x|
161
- ins << <<~END
161
+ ins << <<~BIB
162
162
  <bibitem id="#{x}" type="internal">
163
163
  <docidentifier type="repository">#{x.sub(/^#{prefix}_/, "#{prefix}/")}</docidentifier>
164
164
  </bibitem>
165
- END
165
+ BIB
166
166
  end
167
167
  end
168
168
 
@@ -1,7 +1,6 @@
1
1
  require "date"
2
2
  require "htmlentities"
3
3
  require "json"
4
- require "open-uri"
5
4
 
6
5
  module Asciidoctor
7
6
  module Standoc
@@ -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"
@@ -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
 
@@ -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
@@ -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>
@@ -954,6 +966,16 @@
954
966
  </define>
955
967
  <define name="concept">
956
968
  <element name="concept">
969
+ <optional>
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>
957
979
  <optional>
958
980
  <element name="refterm">
959
981
  <zeroOrMore>
@@ -989,8 +1011,14 @@
989
1011
  <ref name="imagemap"/>
990
1012
  <ref name="svgmap"/>
991
1013
  <ref name="inputform"/>
1014
+ <ref name="toc"/>
992
1015
  </choice>
993
1016
  </define>
1017
+ <define name="toc">
1018
+ <element name="toc">
1019
+ <ref name="ul"/>
1020
+ </element>
1021
+ </define>
994
1022
  <define name="inputform">
995
1023
  <element name="form">
996
1024
  <attribute name="id">
@@ -998,6 +1026,9 @@
998
1026
  </attribute>
999
1027
  <attribute name="name"/>
1000
1028
  <attribute name="action"/>
1029
+ <optional>
1030
+ <attribute name="class"/>
1031
+ </optional>
1001
1032
  <zeroOrMore>
1002
1033
  <choice>
1003
1034
  <ref name="TextElement"/>
@@ -1229,6 +1260,12 @@
1229
1260
  <optional>
1230
1261
  <attribute name="type"/>
1231
1262
  </optional>
1263
+ <optional>
1264
+ <attribute name="identifier"/>
1265
+ </optional>
1266
+ <optional>
1267
+ <attribute name="prefix"/>
1268
+ </optional>
1232
1269
  <text/>
1233
1270
  </define>
1234
1271
  <define name="ics">
@@ -1490,26 +1527,26 @@
1490
1527
  <optional>
1491
1528
  <ref name="section-title"/>
1492
1529
  </optional>
1493
- <group>
1530
+ <choice>
1494
1531
  <choice>
1495
1532
  <group>
1496
- <zeroOrMore>
1533
+ <oneOrMore>
1497
1534
  <ref name="BasicBlock"/>
1498
- </zeroOrMore>
1535
+ </oneOrMore>
1499
1536
  <zeroOrMore>
1500
1537
  <ref name="note"/>
1501
1538
  </zeroOrMore>
1502
1539
  </group>
1503
1540
  <ref name="amend"/>
1504
1541
  </choice>
1505
- <zeroOrMore>
1542
+ <oneOrMore>
1506
1543
  <choice>
1507
1544
  <ref name="clause-subsection"/>
1508
1545
  <ref name="terms"/>
1509
1546
  <ref name="definitions"/>
1510
1547
  </choice>
1511
- </zeroOrMore>
1512
- </group>
1548
+ </oneOrMore>
1549
+ </choice>
1513
1550
  </define>
1514
1551
  <define name="Annex-Section">
1515
1552
  <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