metanorma-standoc 1.11.4 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (141) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/rake.yml +3 -31
  3. data/.gitignore +23 -0
  4. data/lib/asciidoctor/standoc/base.rb +2 -145
  5. data/lib/asciidoctor/standoc/blocks.rb +2 -238
  6. data/lib/asciidoctor/standoc/blocks_notes.rb +2 -100
  7. data/lib/asciidoctor/standoc/cleanup.rb +2 -208
  8. data/lib/asciidoctor/standoc/cleanup_amend.rb +2 -53
  9. data/lib/asciidoctor/standoc/cleanup_block.rb +2 -172
  10. data/lib/asciidoctor/standoc/cleanup_boilerplate.rb +2 -212
  11. data/lib/asciidoctor/standoc/cleanup_footnotes.rb +2 -108
  12. data/lib/asciidoctor/standoc/cleanup_image.rb +2 -69
  13. data/lib/asciidoctor/standoc/cleanup_inline.rb +2 -189
  14. data/lib/asciidoctor/standoc/cleanup_maths.rb +2 -221
  15. data/lib/asciidoctor/standoc/cleanup_ref.rb +2 -169
  16. data/lib/asciidoctor/standoc/cleanup_ref_dl.rb +2 -103
  17. data/lib/asciidoctor/standoc/cleanup_reqt.rb +2 -110
  18. data/lib/asciidoctor/standoc/cleanup_section.rb +2 -184
  19. data/lib/asciidoctor/standoc/cleanup_section_names.rb +2 -91
  20. data/lib/asciidoctor/standoc/cleanup_symbols.rb +2 -47
  21. data/lib/asciidoctor/standoc/cleanup_table.rb +2 -67
  22. data/lib/asciidoctor/standoc/cleanup_terms.rb +2 -139
  23. data/lib/asciidoctor/standoc/cleanup_terms_designations.rb +2 -198
  24. data/lib/asciidoctor/standoc/cleanup_text.rb +2 -95
  25. data/lib/asciidoctor/standoc/cleanup_toc.rb +3 -0
  26. data/lib/asciidoctor/standoc/cleanup_xref.rb +2 -106
  27. data/lib/asciidoctor/standoc/converter.rb +2 -123
  28. data/lib/asciidoctor/standoc/datamodel/attributes_table_preprocessor.rb +2 -56
  29. data/lib/asciidoctor/standoc/datamodel/diagram_preprocessor.rb +2 -102
  30. data/lib/asciidoctor/standoc/datamodel/plantuml_renderer.rb +3 -404
  31. data/lib/asciidoctor/standoc/deprecated.rb +5 -0
  32. data/lib/asciidoctor/standoc/front.rb +2 -223
  33. data/lib/asciidoctor/standoc/front_contributor.rb +2 -191
  34. data/lib/asciidoctor/standoc/inline.rb +2 -231
  35. data/lib/asciidoctor/standoc/lists.rb +2 -119
  36. data/lib/asciidoctor/standoc/macros.rb +2 -203
  37. data/lib/asciidoctor/standoc/macros_form.rb +2 -62
  38. data/lib/asciidoctor/standoc/macros_note.rb +2 -44
  39. data/lib/asciidoctor/standoc/macros_plantuml.rb +2 -112
  40. data/lib/asciidoctor/standoc/macros_terms.rb +2 -180
  41. data/lib/asciidoctor/standoc/ref.rb +2 -251
  42. data/lib/asciidoctor/standoc/ref_sect.rb +2 -153
  43. data/lib/asciidoctor/standoc/ref_utility.rb +2 -0
  44. data/lib/asciidoctor/standoc/render.rb +2 -114
  45. data/lib/asciidoctor/standoc/reqt.rb +2 -89
  46. data/lib/asciidoctor/standoc/section.rb +2 -207
  47. data/lib/asciidoctor/standoc/table.rb +2 -84
  48. data/lib/asciidoctor/standoc/term_lookup_cleanup.rb +2 -178
  49. data/lib/asciidoctor/standoc/terms.rb +2 -159
  50. data/lib/asciidoctor/standoc/utils.rb +2 -100
  51. data/lib/asciidoctor/standoc/validate.rb +2 -157
  52. data/lib/asciidoctor/standoc/validate_section.rb +2 -54
  53. data/lib/metanorma/standoc/base.rb +149 -0
  54. data/lib/{asciidoctor → metanorma}/standoc/basicdoc.rng +0 -0
  55. data/lib/{asciidoctor → metanorma}/standoc/biblio.rng +0 -0
  56. data/lib/metanorma/standoc/blocks.rb +239 -0
  57. data/lib/metanorma/standoc/blocks_notes.rb +101 -0
  58. data/lib/metanorma/standoc/cleanup.rb +146 -0
  59. data/lib/metanorma/standoc/cleanup_amend.rb +54 -0
  60. data/lib/metanorma/standoc/cleanup_block.rb +173 -0
  61. data/lib/metanorma/standoc/cleanup_boilerplate.rb +213 -0
  62. data/lib/metanorma/standoc/cleanup_footnotes.rb +109 -0
  63. data/lib/metanorma/standoc/cleanup_image.rb +70 -0
  64. data/lib/metanorma/standoc/cleanup_inline.rb +190 -0
  65. data/lib/metanorma/standoc/cleanup_maths.rb +222 -0
  66. data/lib/metanorma/standoc/cleanup_ref.rb +170 -0
  67. data/lib/metanorma/standoc/cleanup_ref_dl.rb +104 -0
  68. data/lib/metanorma/standoc/cleanup_reqt.rb +111 -0
  69. data/lib/metanorma/standoc/cleanup_section.rb +212 -0
  70. data/lib/metanorma/standoc/cleanup_section_names.rb +92 -0
  71. data/lib/metanorma/standoc/cleanup_symbols.rb +48 -0
  72. data/lib/metanorma/standoc/cleanup_table.rb +68 -0
  73. data/lib/metanorma/standoc/cleanup_terms.rb +140 -0
  74. data/lib/metanorma/standoc/cleanup_terms_designations.rb +199 -0
  75. data/lib/metanorma/standoc/cleanup_text.rb +96 -0
  76. data/lib/metanorma/standoc/cleanup_toc.rb +98 -0
  77. data/lib/metanorma/standoc/cleanup_xref.rb +107 -0
  78. data/lib/metanorma/standoc/converter.rb +124 -0
  79. data/lib/metanorma/standoc/datamodel/attributes_table_preprocessor.rb +57 -0
  80. data/lib/metanorma/standoc/datamodel/diagram_preprocessor.rb +103 -0
  81. data/lib/metanorma/standoc/datamodel/plantuml_renderer.rb +409 -0
  82. data/lib/metanorma/standoc/front.rb +224 -0
  83. data/lib/metanorma/standoc/front_contributor.rb +192 -0
  84. data/lib/metanorma/standoc/inline.rb +232 -0
  85. data/lib/{asciidoctor → metanorma}/standoc/isodoc.rng +29 -0
  86. data/lib/metanorma/standoc/lists.rb +120 -0
  87. data/lib/metanorma/standoc/macros.rb +204 -0
  88. data/lib/metanorma/standoc/macros_form.rb +63 -0
  89. data/lib/metanorma/standoc/macros_note.rb +45 -0
  90. data/lib/metanorma/standoc/macros_plantuml.rb +113 -0
  91. data/lib/metanorma/standoc/macros_terms.rb +181 -0
  92. data/lib/metanorma/standoc/ref.rb +243 -0
  93. data/lib/metanorma/standoc/ref_sect.rb +153 -0
  94. data/lib/{asciidoctor/standoc/ref_date_id.rb → metanorma/standoc/ref_utility.rb} +43 -5
  95. data/lib/metanorma/standoc/render.rb +115 -0
  96. data/lib/metanorma/standoc/reqt.rb +90 -0
  97. data/lib/{asciidoctor → metanorma}/standoc/reqt.rng +0 -0
  98. data/lib/metanorma/standoc/section.rb +209 -0
  99. data/lib/metanorma/standoc/table.rb +85 -0
  100. data/lib/metanorma/standoc/term_lookup_cleanup.rb +179 -0
  101. data/lib/metanorma/standoc/terms.rb +160 -0
  102. data/lib/metanorma/standoc/utils.rb +101 -0
  103. data/lib/metanorma/standoc/validate.rb +158 -0
  104. data/lib/metanorma/standoc/validate_section.rb +55 -0
  105. data/lib/metanorma/standoc/version.rb +1 -1
  106. data/lib/{asciidoctor → metanorma}/standoc/views/datamodel/model_representation.adoc.erb +0 -0
  107. data/lib/{asciidoctor → metanorma}/standoc/views/datamodel/plantuml_representation.adoc.erb +0 -0
  108. data/lib/metanorma-standoc.rb +1 -1
  109. data/metanorma-standoc.gemspec +1 -1
  110. data/spec/{asciidoctor → metanorma}/base_spec.rb +27 -10
  111. data/spec/{asciidoctor → metanorma}/blank_spec.rb +1 -1
  112. data/spec/{asciidoctor → metanorma}/blocks_spec.rb +1 -1
  113. data/spec/{asciidoctor → metanorma}/cleanup_blocks_spec.rb +1 -1
  114. data/spec/{asciidoctor → metanorma}/cleanup_sections_spec.rb +1 -1
  115. data/spec/{asciidoctor → metanorma}/cleanup_spec.rb +5 -5
  116. data/spec/{asciidoctor → metanorma}/cleanup_terms_spec.rb +2 -2
  117. data/spec/{asciidoctor → metanorma}/datamodel/attributes_table_preprocessor_spec.rb +1 -1
  118. data/spec/{asciidoctor → metanorma}/datamodel/diagram_preprocessor_spec.rb +1 -1
  119. data/spec/{asciidoctor → metanorma}/inline_spec.rb +1 -1
  120. data/spec/{asciidoctor → metanorma}/isobib_cache_spec.rb +1 -1
  121. data/spec/{asciidoctor → metanorma}/lists_spec.rb +1 -1
  122. data/spec/{asciidoctor → metanorma}/macros_json2text_spec.rb +0 -0
  123. data/spec/{asciidoctor → metanorma}/macros_plantuml_spec.rb +3 -3
  124. data/spec/{asciidoctor → metanorma}/macros_spec.rb +6 -6
  125. data/spec/{asciidoctor → metanorma}/macros_yaml2text_spec.rb +0 -0
  126. data/spec/metanorma/refs_dl_spec.rb +863 -0
  127. data/spec/{asciidoctor → metanorma}/refs_spec.rb +399 -25
  128. data/spec/{asciidoctor → metanorma}/section_spec.rb +42 -17
  129. data/spec/{asciidoctor → metanorma}/table_spec.rb +1 -1
  130. data/spec/{asciidoctor → metanorma}/validate_spec.rb +2 -2
  131. data/spec/vcr_cassettes/dated_iso_ref_joint_iso_iec.yml +42 -42
  132. data/spec/vcr_cassettes/dated_iso_ref_joint_iso_iec1.yml +11 -11
  133. data/spec/vcr_cassettes/isobib_get_123.yml +12 -12
  134. data/spec/vcr_cassettes/isobib_get_123_1.yml +21 -21
  135. data/spec/vcr_cassettes/isobib_get_123_1_fr.yml +81 -81
  136. data/spec/vcr_cassettes/isobib_get_123_2001.yml +10 -10
  137. data/spec/vcr_cassettes/isobib_get_124.yml +11 -11
  138. data/spec/vcr_cassettes/rfcbib_get_rfc8341.yml +13 -13
  139. data/spec/vcr_cassettes/separates_iev_citations_by_top_level_clause.yml +46 -46
  140. metadata +82 -32
  141. data/spec/asciidoctor/refs_dl_spec.rb +0 -864
@@ -32,6 +32,19 @@
32
32
  <ref name="DocumentType"/>
33
33
  </element>
34
34
  </define>
35
+ <define name="bibitem">
36
+ <element name="bibitem">
37
+ <attribute name="id">
38
+ <data type="ID"/>
39
+ </attribute>
40
+ <optional>
41
+ <attribute name="hidden">
42
+ <data type="boolean"/>
43
+ </attribute>
44
+ </optional>
45
+ <ref name="BibliographicItem"/>
46
+ </element>
47
+ </define>
35
48
  <define name="section-title">
36
49
  <element name="title">
37
50
  <zeroOrMore>
@@ -690,6 +703,7 @@
690
703
  <ref name="terms"/>
691
704
  <ref name="term-clause"/>
692
705
  <ref name="definitions"/>
706
+ <ref name="floating-title"/>
693
707
  </choice>
694
708
  </oneOrMore>
695
709
  </element>
@@ -1680,6 +1694,7 @@
1680
1694
  <ref name="clause-subsection"/>
1681
1695
  <ref name="terms"/>
1682
1696
  <ref name="definitions"/>
1697
+ <ref name="floating-title"/>
1683
1698
  </choice>
1684
1699
  </oneOrMore>
1685
1700
  </choice>
@@ -1722,6 +1737,7 @@
1722
1737
  <ref name="terms"/>
1723
1738
  <ref name="definitions"/>
1724
1739
  <ref name="references"/>
1740
+ <ref name="floating-title"/>
1725
1741
  </choice>
1726
1742
  </zeroOrMore>
1727
1743
  </group>
@@ -2534,4 +2550,17 @@
2534
2550
  </oneOrMore>
2535
2551
  </element>
2536
2552
  </define>
2553
+ <define name="floating-title">
2554
+ <element name="floating-title">
2555
+ <attribute name="id">
2556
+ <data type="ID"/>
2557
+ </attribute>
2558
+ <attribute name="depth">
2559
+ <data type="int"/>
2560
+ </attribute>
2561
+ <zeroOrMore>
2562
+ <ref name="TextElement"/>
2563
+ </zeroOrMore>
2564
+ </element>
2565
+ </define>
2537
2566
  </grammar>
@@ -0,0 +1,120 @@
1
+ module Metanorma
2
+ module Standoc
3
+ module Lists
4
+ def li(xml_ul, item)
5
+ xml_ul.li do |xml_li|
6
+ if item.blocks?
7
+ xml_li.p(**attr_code(id_attr(item))) { |t| t << item.text }
8
+ xml_li << item.content
9
+ else
10
+ xml_li.p(**attr_code(id_attr(item))) { |p| p << item.text }
11
+ end
12
+ end
13
+ end
14
+
15
+ def ul_li(xml_ul, item)
16
+ xml_ul.li **ul_li_attrs(item) do |xml_li|
17
+ xml_li.p(**attr_code(id_attr(item))) { |t| t << item.text }
18
+ if item.blocks?
19
+ xml_li << item.content
20
+ end
21
+ end
22
+ end
23
+
24
+ def ul_attrs(node)
25
+ attr_code(id_attr(node).merge(keep_attrs(node)))
26
+ end
27
+
28
+ def ul_li_attrs(node)
29
+ c = node.attr?("checked")
30
+ attr_code(
31
+ uncheckedcheckbox: node.attr?("checkbox") ? !c : nil,
32
+ checkedcheckbox: node.attr?("checkbox") ? c : nil,
33
+ )
34
+ end
35
+
36
+ def ulist(node)
37
+ return reference(node) if in_norm_ref? || in_biblio?
38
+
39
+ noko do |xml|
40
+ xml.ul **ul_attrs(node) do |xml_ul|
41
+ node.items.each do |item|
42
+ ul_li(xml_ul, item)
43
+ end
44
+ end
45
+ end.join("\n")
46
+ end
47
+
48
+ def olist_style(style)
49
+ return "alphabet" if style == "loweralpha"
50
+ return "roman" if style == "lowerroman"
51
+ return "roman_upper" if style == "upperroman"
52
+ return "alphabet_upper" if style == "upperalpha"
53
+
54
+ style
55
+ end
56
+
57
+ def ol_attrs(node)
58
+ attr_code(id_attr(node).merge(keep_attrs(node)
59
+ .merge(type: olist_style(node.style))))
60
+ end
61
+
62
+ def olist(node)
63
+ noko do |xml|
64
+ xml.ol **ol_attrs(node) do |xml_ol|
65
+ node.items.each { |item| li(xml_ol, item) }
66
+ end
67
+ end.join("\n")
68
+ end
69
+
70
+ def dt(terms, xml_dl)
71
+ terms.each_with_index do |dt, idx|
72
+ xml_dl.dt { |xml_dt| xml_dt << dt.text }
73
+ if idx < terms.size - 1
74
+ xml_dl.dd
75
+ end
76
+ end
77
+ end
78
+
79
+ def dd(ddefn, xml_dl)
80
+ if ddefn.nil?
81
+ xml_dl.dd
82
+ return
83
+ end
84
+ xml_dl.dd do |xml_dd|
85
+ xml_dd.p { |t| t << ddefn.text } if ddefn.text?
86
+ xml_dd << ddefn.content if ddefn.blocks?
87
+ end
88
+ end
89
+
90
+ def dl_attrs(node)
91
+ attr_code(id_attr(node).merge(keep_attrs(node)
92
+ .merge(
93
+ metadata: node.option?("metadata") ? "true" : nil,
94
+ key: node.option?("key") ? "true" : nil,
95
+ )))
96
+ end
97
+
98
+ def dlist(node)
99
+ noko do |xml|
100
+ xml.dl **dl_attrs(node) do |xml_dl|
101
+ node.items.each do |terms, dd|
102
+ dt(terms, xml_dl)
103
+ dd(dd, xml_dl)
104
+ end
105
+ end
106
+ end.join("\n")
107
+ end
108
+
109
+ def colist(node)
110
+ noko do |xml|
111
+ node.items.each_with_index do |item, i|
112
+ xml.annotation **attr_code(id: i + 1) do |xml_li|
113
+ xml_li.p { |p| p << item.text }
114
+ end
115
+ end
116
+ end.join("\n")
117
+ end
118
+ end
119
+ end
120
+ end
@@ -0,0 +1,204 @@
1
+ require "asciidoctor/extensions"
2
+ require "fileutils"
3
+ require "uuidtools"
4
+ require "yaml"
5
+ require "csv"
6
+ require_relative "./macros_plantuml"
7
+ require_relative "./macros_terms"
8
+ require_relative "./macros_form"
9
+ require_relative "./macros_note"
10
+ require_relative "./datamodel/attributes_table_preprocessor"
11
+ require_relative "./datamodel/diagram_preprocessor"
12
+ require "metanorma-plugin-datastruct"
13
+ require "metanorma-plugin-lutaml"
14
+
15
+ module Metanorma
16
+ module Standoc
17
+ class InheritInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
18
+ use_dsl
19
+ named :inherit
20
+ parse_content_as :text
21
+ using_format :short
22
+
23
+ def process(parent, _target, attrs)
24
+ out = Asciidoctor::Inline.new(parent, :quoted, attrs["text"]).convert
25
+ %{<inherit>#{out}</inherit>}
26
+ end
27
+ end
28
+
29
+ class IndexXrefInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
30
+ use_dsl
31
+ named :index
32
+
33
+ def preprocess_attrs(attrs)
34
+ return unless attrs.size > 1 && attrs.size < 5
35
+
36
+ ret = { primary: attrs[1], target: attrs[attrs.size] }
37
+ ret[:secondary] = attrs[2] if attrs.size > 2
38
+ ret[:tertiary] = attrs[3] if attrs.size > 3
39
+ ret
40
+ end
41
+
42
+ def process(_parent, target, attr)
43
+ args = preprocess_attrs(attr) or return
44
+ ret = "<index-xref also='#{target == 'also'}'>"\
45
+ "<primary>#{args[:primary]}</primary>"
46
+ ret += "<secondary>#{args[:secondary]}</secondary>" if args[:secondary]
47
+ ret += "<tertiary>#{args[:tertiary]}</tertiary>" if args[:tertiary]
48
+ ret + "<target>#{args[:target]}</target></index-xref>"
49
+ end
50
+ end
51
+
52
+ class IndexRangeInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
53
+ use_dsl
54
+ named :"index-range"
55
+ parse_content_as :text
56
+
57
+ def process(parent, target, attr)
58
+ text = attr["text"]
59
+ text = "((#{text}))" unless /^\(\(.+\)\)$/.match?(text)
60
+ out = parent.sub_macros(text)
61
+ out.sub(/<index>/, "<index to='#{target}'>")
62
+ end
63
+ end
64
+
65
+ class PseudocodeBlockMacro < Asciidoctor::Extensions::BlockProcessor
66
+ use_dsl
67
+ named :pseudocode
68
+ on_context :example, :sourcecode
69
+
70
+ def init_indent(line)
71
+ /^(?<prefix>[ \t]*)(?<suffix>.*)$/ =~ line
72
+ prefix = prefix.gsub(/\t/, "\u00a0\u00a0\u00a0\u00a0")
73
+ .gsub(/ /, "\u00a0")
74
+ prefix + suffix
75
+ end
76
+
77
+ def supply_br(lines)
78
+ ignore = false
79
+ lines.each_with_index do |l, i|
80
+ /^(--+|====+|\|===|\.\.\.\.+|\*\*\*\*+|\+\+\+\++|````+|____\+)$/
81
+ .match(l) && (ignore = !ignore)
82
+ next if l.empty? || l.match(/ \+$/) || /^\[.*\]$/.match?(l) || ignore
83
+ next if i == lines.size - 1 ||
84
+ i < lines.size - 1 && lines[i + 1].empty?
85
+
86
+ lines[i] += " +"
87
+ end
88
+ lines
89
+ end
90
+
91
+ def process(parent, reader, attrs)
92
+ attrs["role"] = "pseudocode"
93
+ lines = reader.lines.map { |m| init_indent(m) }
94
+ create_block(parent, :example, supply_br(lines),
95
+ attrs, content_model: :compound)
96
+ end
97
+ end
98
+
99
+ class HTML5RubyMacro < Asciidoctor::Extensions::InlineMacroProcessor
100
+ use_dsl
101
+ named :ruby
102
+ parse_content_as :text
103
+ option :pos_attrs, %w(rpbegin rt rpend)
104
+
105
+ # for example, html5ruby:楽聖少女[がくせいしょうじょ]
106
+ def process(_parent, target, attributes)
107
+ rpbegin = "("
108
+ rpend = ")"
109
+ if (attributes.size == 1) && attributes.key?("text")
110
+ rt = attributes["text"]
111
+ elsif (attributes.size == 2) && attributes.key?(1) &&
112
+ attributes.key?("rpbegin")
113
+ rt = attributes[1] || ""
114
+ else
115
+ rpbegin = attributes["rpbegin"]
116
+ rt = attributes["rt"]
117
+ rpend = attributes["rpend"]
118
+ end
119
+
120
+ "<ruby>#{target}<rp>#{rpbegin}</rp><rt>#{rt}</rt>"\
121
+ "<rp>#{rpend}</rp></ruby>"
122
+ end
123
+ end
124
+
125
+ class AutonumberInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
126
+ use_dsl
127
+ named :autonumber
128
+ parse_content_as :text
129
+
130
+ def process(parent, target, attrs)
131
+ out = Asciidoctor::Inline.new(parent, :quoted, attrs["text"]).convert
132
+ %{<autonumber type=#{target}>#{out}</autonumber>}
133
+ end
134
+ end
135
+
136
+ class VariantInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
137
+ use_dsl
138
+ named :lang
139
+ parse_content_as :text
140
+
141
+ def process(parent, target, attrs)
142
+ /^(?<lang>[^-]*)(-(?<script>.*))?$/ =~ target
143
+ out = Asciidoctor::Inline.new(parent, :quoted, attrs["text"]).convert
144
+ if script
145
+ %{<variant lang=#{lang} script=#{script}>#{out}</variant>}
146
+ else
147
+ %{<variant lang=#{lang}>#{out}</variant>}
148
+ end
149
+ end
150
+ end
151
+
152
+ class AddMacro < Asciidoctor::Extensions::InlineMacroProcessor
153
+ use_dsl
154
+ named :add
155
+ parse_content_as :text
156
+ using_format :short
157
+
158
+ def process(parent, _target, attrs)
159
+ out = Asciidoctor::Inline.new(parent, :quoted, attrs["text"]).convert
160
+ %{<add>#{out}</add>}
161
+ end
162
+ end
163
+
164
+ class DelMacro < Asciidoctor::Extensions::InlineMacroProcessor
165
+ use_dsl
166
+ named :del
167
+ parse_content_as :text
168
+ using_format :short
169
+
170
+ def process(parent, _target, attrs)
171
+ out = Asciidoctor::Inline.new(parent, :quoted, attrs["text"]).convert
172
+ %{<del>#{out}</del>}
173
+ end
174
+ end
175
+
176
+ class ToCInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
177
+ use_dsl
178
+ named :toc
179
+ parse_content_as :text
180
+ using_format :short
181
+
182
+ def process(parent, _target, attrs)
183
+ out = Asciidoctor::Inline.new(parent, :quoted, attrs["text"]).convert
184
+ content = CSV.parse_line(out).map do |x|
185
+ x.sub!(/^(["'])(.+)\1/, "\\2")
186
+ m = /^(.*?)(:\d+)?$/.match(x)
187
+ %{<toc-xpath depth='#{m[2]&.sub(/:/, '') || 1}'>#{m[1]}</toc-xpath>}
188
+ end.join
189
+ "<toc>#{content}</toc>"
190
+ end
191
+ end
192
+
193
+ class PassInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
194
+ use_dsl
195
+ named :"pass-format"
196
+
197
+ def process(parent, target, attrs)
198
+ format = target || "metanorma"
199
+ out = Asciidoctor::Inline.new(parent, :quoted, attrs[1]).convert
200
+ %{<passthrough formats="#{format}">#{out}</passthrough>}
201
+ end
202
+ end
203
+ end
204
+ end
@@ -0,0 +1,63 @@
1
+ module Metanorma
2
+ module Standoc
3
+ class FormInputMacro < Asciidoctor::Extensions::InlineMacroProcessor
4
+ use_dsl
5
+ named :input
6
+
7
+ def process(_parent, target, attr)
8
+ m = %w(id name value disabled readonly checked maxlength minlength)
9
+ .map { |a| attr[a] ? " #{a}='#{attr[a]}'" : nil }.compact
10
+ %{<input type='#{target}' #{m.join}/>}
11
+ end
12
+ end
13
+
14
+ class FormLabelMacro < Asciidoctor::Extensions::InlineMacroProcessor
15
+ use_dsl
16
+ named :label
17
+ parse_content_as :text
18
+
19
+ def process(parent, target, attr)
20
+ out = Asciidoctor::Inline.new(parent, :quoted, attr["text"]).convert
21
+ %{<label for="#{target}">#{out}</label>}
22
+ end
23
+ end
24
+
25
+ class FormTextareaMacro < Asciidoctor::Extensions::InlineMacroProcessor
26
+ use_dsl
27
+ named :textarea
28
+ using_format :short
29
+
30
+ def process(_parent, _target, attr)
31
+ m = %w(id name rows cols value)
32
+ .map { |a| attr[a] ? " #{a}='#{attr[a]}'" : nil }.compact
33
+ %{<textarea #{m.join}/>}
34
+ end
35
+ end
36
+
37
+ class FormSelectMacro < Asciidoctor::Extensions::InlineMacroProcessor
38
+ use_dsl
39
+ named :select
40
+ using_format :short
41
+
42
+ def process(parent, _target, attr)
43
+ m = %w(id name size disabled multiple value)
44
+ .map { |a| attr[a] ? " #{a}='#{attr[a]}'" : nil }.compact
45
+ out = Asciidoctor::Inline.new(parent, :quoted, attr["text"]).convert
46
+ %{<select #{m.join}>#{out}</select>}
47
+ end
48
+ end
49
+
50
+ class FormOptionMacro < Asciidoctor::Extensions::InlineMacroProcessor
51
+ use_dsl
52
+ named :option
53
+ using_format :short
54
+
55
+ def process(parent, _target, attr)
56
+ m = %w(disabled value)
57
+ .map { |a| attr[a] ? " #{a}='#{attr[a]}'" : nil }.compact
58
+ out = Asciidoctor::Inline.new(parent, :quoted, attr["text"]).convert
59
+ %{<option #{m.join}">#{out}</option>}
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,45 @@
1
+ module Metanorma
2
+ module Standoc
3
+ class ToDoAdmonitionBlock < Asciidoctor::Extensions::BlockProcessor
4
+ use_dsl
5
+ named :TODO
6
+ on_contexts :example, :paragraph
7
+
8
+ def process(parent, reader, attrs)
9
+ attrs["name"] = "todo"
10
+ attrs["caption"] = "TODO"
11
+ create_block(parent, :admonition, reader.lines, attrs,
12
+ content_model: :compound)
13
+ end
14
+ end
15
+
16
+ class ToDoInlineAdmonitionBlock < Asciidoctor::Extensions::Treeprocessor
17
+ def process(document)
18
+ (document.find_by context: :paragraph).each do |para|
19
+ next unless /^TODO: /.match? para.lines[0]
20
+
21
+ parent = para.parent
22
+ para.set_attr("name", "todo")
23
+ para.set_attr("caption", "TODO")
24
+ para.lines[0].sub!(/^TODO: /, "")
25
+ todo = Asciidoctor::Block.new(parent, :admonition, attributes: para.attributes,
26
+ source: para.lines,
27
+ content_model: :compound)
28
+ parent.blocks[parent.blocks.index(para)] = todo
29
+ end
30
+ end
31
+ end
32
+
33
+ class FootnoteBlockInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor
34
+ use_dsl
35
+ named :footnoteblock
36
+ parse_content_as :text
37
+ using_format :short
38
+
39
+ def process(parent, _target, attrs)
40
+ out = Asciidoctor::Inline.new(parent, :quoted, attrs["text"]).convert
41
+ %{<footnoteblock>#{out}</footnoteblock>}
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,113 @@
1
+ module Metanorma
2
+ module Standoc
3
+ class PlantUMLBlockMacroBackend
4
+ # https://stackoverflow.com/questions/2108727/which-in-ruby-checking-if-program-exists-in-path-from-ruby
5
+ def self.plantuml_installed?
6
+ cmd = "plantuml"
7
+ exts = ENV["PATHEXT"] ? ENV["PATHEXT"].split(";") : [""]
8
+ ENV["PATH"].split(File::PATH_SEPARATOR).each do |path|
9
+ exts.each do |ext|
10
+ exe = File.join(path, "#{cmd}#{ext}")
11
+ return exe if File.executable?(exe) && !File.directory?(exe)
12
+ end
13
+ end
14
+ raise "PlantUML not installed"
15
+ end
16
+
17
+ def self.run(umlfile, outfile)
18
+ system "plantuml #{umlfile.path}" or (warn $? and return false)
19
+ i = 0
20
+ until !Gem.win_platform? || File.exist?(outfile) || i == 15
21
+ sleep(1)
22
+ i += 1
23
+ end
24
+ File.exist?(outfile)
25
+ end
26
+
27
+ # if no :imagesdir: leave image file in plantuml
28
+ # sleep need for windows because dot works in separate process and
29
+ # plantuml process may finish earlier then dot, as result png file
30
+ # maybe not created yet after plantuml finish
31
+ #
32
+ # # Warning: metanorma/metanorma-standoc#187
33
+ # Windows Ruby 2.4 will crash if a Tempfile is "mv"ed.
34
+ # This is why we need to copy and then unlink.
35
+ def self.generate_file(parent, reader)
36
+ localdir = Metanorma::Utils::localdir(parent.document)
37
+ imagesdir = parent.document.attr("imagesdir")
38
+ umlfile, outfile = save_plantuml parent, reader, localdir
39
+ run(umlfile, outfile) or
40
+ raise "No image output from PlantUML (#{umlfile}, #{outfile})!"
41
+ umlfile.unlink
42
+
43
+ path = path_prep(localdir, imagesdir)
44
+ filename = File.basename(outfile.to_s)
45
+ FileUtils.cp(outfile, path) and outfile.unlink
46
+
47
+ imagesdir ? filename : File.join(path, filename)
48
+ end
49
+
50
+ def self.path_prep(localdir, imagesdir)
51
+ path = Pathname.new(localdir) + (imagesdir || "plantuml")
52
+ File.writable?(localdir) or
53
+ raise "Destination path #{path} not writable for PlantUML!"
54
+ path.mkpath
55
+ File.writable?(path) or
56
+ raise "Destination path #{path} not writable for PlantUML!"
57
+ # File.exist?(path) or raise "Destination path #{path} already exists for PlantUML!"
58
+ path
59
+ end
60
+
61
+ def self.save_plantuml(_parent, reader, _localdir)
62
+ src = prep_source(reader)
63
+ /^@startuml (?<fn>[^\n]+)\n/ =~ src
64
+ Tempfile.open(["plantuml", ".pml"], encoding: "utf-8") do |f|
65
+ f.write(src)
66
+ [f, File.join(File.dirname(f.path),
67
+ "#{fn || File.basename(f.path, '.pml')}.png")]
68
+ end
69
+ end
70
+
71
+ def self.prep_source(reader)
72
+ src = reader.source
73
+ reader.lines.first.sub(/\s+$/, "").match /^@startuml($| )/ or
74
+ src = "@startuml\n#{src}\n@enduml\n"
75
+ %r{@enduml\s*$}m.match?(src) or
76
+ raise "@startuml without matching @enduml in PlantUML!"
77
+ src
78
+ end
79
+
80
+ def self.generate_attrs(attrs)
81
+ %w(id align float title role width height alt)
82
+ .inject({}) do |memo, key|
83
+ memo[key] = attrs[key] if attrs.has_key? key
84
+ memo
85
+ end
86
+ end
87
+ end
88
+
89
+ class PlantUMLBlockMacro < Asciidoctor::Extensions::BlockProcessor
90
+ use_dsl
91
+ named :plantuml
92
+ on_context :literal
93
+ parse_content_as :raw
94
+
95
+ def abort(parent, reader, attrs, msg)
96
+ warn msg
97
+ attrs["language"] = "plantuml"
98
+ create_listing_block parent, reader.source,
99
+ (attrs.reject { |k, _v| k == 1 })
100
+ end
101
+
102
+ def process(parent, reader, attrs)
103
+ PlantUMLBlockMacroBackend.plantuml_installed?
104
+ filename = PlantUMLBlockMacroBackend.generate_file(parent, reader)
105
+ through_attrs = PlantUMLBlockMacroBackend.generate_attrs attrs
106
+ through_attrs["target"] = filename
107
+ create_image_block parent, through_attrs
108
+ rescue StandardError => e
109
+ abort(parent, reader, attrs, e.message)
110
+ end
111
+ end
112
+ end
113
+ end