metanorma-standoc 1.4.2 → 1.5.2

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 (53) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/macos.yml +0 -7
  3. data/.github/workflows/ubuntu.yml +6 -11
  4. data/.github/workflows/windows.yml +0 -8
  5. data/.rubocop.yml +1 -1
  6. data/Rakefile +2 -0
  7. data/lib/asciidoctor/standoc/base.rb +15 -21
  8. data/lib/asciidoctor/standoc/cleanup.rb +1 -0
  9. data/lib/asciidoctor/standoc/cleanup_boilerplate.rb +11 -24
  10. data/lib/asciidoctor/standoc/cleanup_inline.rb +57 -1
  11. data/lib/asciidoctor/standoc/cleanup_ref.rb +13 -8
  12. data/lib/asciidoctor/standoc/cleanup_section.rb +90 -6
  13. data/lib/asciidoctor/standoc/cleanup_terms.rb +12 -2
  14. data/lib/asciidoctor/standoc/converter.rb +16 -2
  15. data/lib/asciidoctor/standoc/front.rb +0 -12
  16. data/lib/asciidoctor/standoc/front_contributor.rb +28 -3
  17. data/lib/asciidoctor/standoc/inline.rb +1 -1
  18. data/lib/asciidoctor/standoc/isodoc.rng +16 -7
  19. data/lib/asciidoctor/standoc/log.rb +10 -1
  20. data/lib/asciidoctor/standoc/ref.rb +24 -25
  21. data/lib/asciidoctor/standoc/section.rb +31 -27
  22. data/lib/asciidoctor/standoc/utils.rb +18 -1
  23. data/lib/asciidoctor/standoc/validate.rb +30 -18
  24. data/lib/asciidoctor/standoc/validate_section.rb +1 -1
  25. data/lib/metanorma/standoc/processor.rb +0 -4
  26. data/lib/metanorma/standoc/version.rb +1 -1
  27. data/metanorma-standoc.gemspec +3 -2
  28. data/spec/asciidoctor-standoc/base_spec.rb +21 -6
  29. data/spec/asciidoctor-standoc/blocks_spec.rb +21 -7
  30. data/spec/asciidoctor-standoc/cleanup_spec.rb +1337 -23
  31. data/spec/asciidoctor-standoc/inline_spec.rb +7 -4
  32. data/spec/asciidoctor-standoc/macros_spec.rb +41 -23
  33. data/spec/asciidoctor-standoc/refs_dl_spec.rb +9 -7
  34. data/spec/asciidoctor-standoc/refs_spec.rb +16 -16
  35. data/spec/asciidoctor-standoc/section_spec.rb +42 -38
  36. data/spec/asciidoctor-standoc/table_spec.rb +7 -1
  37. data/spec/asciidoctor-standoc/validate_spec.rb +40 -0
  38. data/spec/assets/{html.css → html.scss} +0 -0
  39. data/spec/assets/i18n.yaml +17 -2
  40. data/spec/assets/{word.css → word.scss} +0 -0
  41. data/spec/metanorma/processor_spec.rb +1 -2
  42. data/spec/vcr_cassettes/dated_iso_ref_joint_iso_iec.yml +66 -66
  43. data/spec/vcr_cassettes/isobib_get_123.yml +16 -16
  44. data/spec/vcr_cassettes/isobib_get_123_1.yml +33 -33
  45. data/spec/vcr_cassettes/isobib_get_123_2001.yml +19 -19
  46. data/spec/vcr_cassettes/isobib_get_124.yml +19 -19
  47. data/spec/vcr_cassettes/rfcbib_get_rfc8341.yml +8 -8
  48. data/spec/vcr_cassettes/separates_iev_citations_by_top_level_clause.yml +28 -28
  49. metadata +22 -12
  50. data/lib/asciidoctor-yaml/i18n-en.yaml +0 -20
  51. data/lib/asciidoctor-yaml/i18n-fr.yaml +0 -13
  52. data/lib/asciidoctor-yaml/i18n-zh-Hans.yaml +0 -15
  53. data/lib/asciidoctor/standoc/i18n.rb +0 -39
@@ -76,6 +76,15 @@ module Asciidoctor
76
76
  end
77
77
  end
78
78
 
79
+ def termnote_example_cleanup(xmldoc)
80
+ xmldoc.xpath("//termnote[not(ancestor::term)]").each do |x|
81
+ x.name = "note"
82
+ end
83
+ xmldoc.xpath("//termexample[not(ancestor::term)]").each do |x|
84
+ x.name = "note"
85
+ end
86
+ end
87
+
79
88
  def termdef_cleanup(xmldoc)
80
89
  termdef_from_termbase(xmldoc)
81
90
  termdef_unnest_cleanup(xmldoc)
@@ -83,6 +92,7 @@ module Asciidoctor
83
92
  termdomain_cleanup(xmldoc)
84
93
  termdefinition_cleanup(xmldoc)
85
94
  termdomain1_cleanup(xmldoc)
95
+ termnote_example_cleanup(xmldoc)
86
96
  termdef_boilerplate_cleanup(xmldoc)
87
97
  termdef_subclause_cleanup(xmldoc)
88
98
  term_children_cleanup(xmldoc)
@@ -100,8 +110,8 @@ module Asciidoctor
100
110
  end
101
111
  ret = Nokogiri::XML(key.to_xml)
102
112
  HTMLEntities.new.decode(ret.text).
103
- gsub(/[\[\]\{\}<>\(\)]/, "").strip.
104
- gsub(/[[:punct]]|[_^]/, ":\\0").gsub(/`/, "").
113
+ gsub(/[\[\]\{\}<>\(\)]/, "").gsub(/\s/m, "").
114
+ gsub(/[[:punct:]]|[_^]/, ":\\0").gsub(/`/, "").
105
115
  gsub(/[0-9]+/, "þ\\0")
106
116
  end
107
117
 
@@ -11,7 +11,6 @@ require "asciidoctor/standoc/table"
11
11
  require "asciidoctor/standoc/validate"
12
12
  require "asciidoctor/standoc/utils"
13
13
  require "asciidoctor/standoc/cleanup"
14
- require "asciidoctor/standoc/i18n"
15
14
  require "asciidoctor/standoc/reqt"
16
15
  require_relative "./macros.rb"
17
16
  require_relative "./log.rb"
@@ -21,6 +20,22 @@ module Asciidoctor
21
20
  # A {Converter} implementation that generates Standoc output, and a document
22
21
  # schema encapsulation of the document for validation
23
22
  class Converter
23
+ Asciidoctor::Extensions.register do
24
+ preprocessor Asciidoctor::Standoc::Datamodel::AttributesTablePreprocessor
25
+ preprocessor Asciidoctor::Standoc::Datamodel::DiagramPreprocessor
26
+ preprocessor Asciidoctor::Standoc::Yaml2TextPreprocessor
27
+ inline_macro Asciidoctor::Standoc::AltTermInlineMacro
28
+ inline_macro Asciidoctor::Standoc::DeprecatedTermInlineMacro
29
+ inline_macro Asciidoctor::Standoc::DomainTermInlineMacro
30
+ inline_macro Asciidoctor::Standoc::InheritInlineMacro
31
+ inline_macro Asciidoctor::Standoc::HTML5RubyMacro
32
+ inline_macro Asciidoctor::Standoc::ConceptInlineMacro
33
+ block Asciidoctor::Standoc::ToDoAdmonitionBlock
34
+ treeprocessor Asciidoctor::Standoc::ToDoInlineAdmonitionBlock
35
+ block Asciidoctor::Standoc::PlantUMLBlockMacro
36
+ block Asciidoctor::Standoc::PseudocodeBlockMacro
37
+ end
38
+
24
39
  include ::Asciidoctor::Converter
25
40
  include ::Asciidoctor::Writer
26
41
 
@@ -32,7 +47,6 @@ module Asciidoctor
32
47
  include ::Asciidoctor::Standoc::Section
33
48
  include ::Asciidoctor::Standoc::Table
34
49
  include ::Asciidoctor::Standoc::Utils
35
- include ::Asciidoctor::Standoc::I18n
36
50
  include ::Asciidoctor::Standoc::Cleanup
37
51
  include ::Asciidoctor::Standoc::Validate
38
52
 
@@ -25,18 +25,6 @@ module Asciidoctor
25
25
  end
26
26
  end
27
27
 
28
- def metadata_copyright(node, xml)
29
- publishers = node.attr("publisher") || " "
30
- publishers.split(/,[ ]?/).each do |p|
31
- xml.copyright do |c|
32
- c.from (node.attr("copyright-year") || Date.today.year)
33
- p.match(/[A-Za-z]/).nil? or c.owner do |owner|
34
- owner.organization { |o| organization(o, p) }
35
- end
36
- end
37
- end
38
- end
39
-
40
28
  def metadata_status(node, xml)
41
29
  xml.status do |s|
42
30
  s.stage ( node.attr("status") || node.attr("docstage") || "published" )
@@ -3,6 +3,7 @@ require "nokogiri"
3
3
  require "htmlentities"
4
4
  require "pathname"
5
5
  require "open-uri"
6
+ require "csv"
6
7
 
7
8
  module Asciidoctor
8
9
  module Standoc
@@ -24,8 +25,15 @@ module Asciidoctor
24
25
  org.name orgname
25
26
  end
26
27
 
28
+ # , " => ," : CSV definition does not deal with space followed by quote
29
+ # at start of field
30
+ def csv_split(s, delim = ",")
31
+ CSV.parse_line(s&.gsub(/, "(?!")/, ',"'), liberal_parsing: true,
32
+ col_sep: delim)&.map { |x| x.strip }
33
+ end
34
+
27
35
  def metadata_author(node, xml)
28
- (node.attr("publisher") || "").split(/,[ ]?/).each do |p|
36
+ csv_split(node.attr("publisher") || default_publisher || "")&.each do |p|
29
37
  xml.contributor do |c|
30
38
  c.role **{ type: "author" }
31
39
  c.organization { |a| organization(a, p) }
@@ -85,15 +93,32 @@ module Asciidoctor
85
93
  end
86
94
  end
87
95
 
96
+ def default_publisher
97
+ nil
98
+ end
99
+
88
100
  def metadata_publisher(node, xml)
89
- publishers = node.attr("publisher") || return
90
- publishers.split(/,[ ]?/).each do |p|
101
+ publishers = node.attr("publisher") || default_publisher || return
102
+ csv_split(publishers)&.each do |p|
91
103
  xml.contributor do |c|
92
104
  c.role **{ type: "publisher" }
93
105
  c.organization { |a| organization(a, p) }
94
106
  end
95
107
  end
96
108
  end
109
+
110
+ def metadata_copyright(node, xml)
111
+ publishers = node.attr("copyright-holder") || node.attr("publisher") ||
112
+ default_publisher || "-"
113
+ csv_split(publishers)&.each do |p|
114
+ xml.copyright do |c|
115
+ c.from (node.attr("copyright-year") || Date.today.year)
116
+ p.match(/[A-Za-z]/).nil? or c.owner do |owner|
117
+ owner.organization { |o| organization(o, p) }
118
+ end
119
+ end
120
+ end
121
+ end
97
122
  end
98
123
  end
99
124
  end
@@ -135,7 +135,7 @@ module Asciidoctor
135
135
  results.nil? and
136
136
  @log.add('Math', nil,
137
137
  "latexmlmath failed to process equation:\n#{lxm_input}")
138
- results
138
+ results&.sub(%r{<math ([^>]+ )?display="block"}, "<math \\1")
139
139
  end
140
140
 
141
141
  def stem_parse(text, xml, style)
@@ -42,8 +42,11 @@
42
42
  </define>
43
43
  <define name="xref">
44
44
  <element name="xref">
45
+ <!-- attribute target { xsd:IDREF }, -->
45
46
  <attribute name="target">
46
- <data type="IDREF"/>
47
+ <data type="string">
48
+ <param name="pattern">\i\c*|\c+#\c+</param>
49
+ </data>
47
50
  </attribute>
48
51
  <optional>
49
52
  <attribute name="type">
@@ -922,6 +925,9 @@
922
925
  <optional>
923
926
  <attribute name="script"/>
924
927
  </optional>
928
+ <optional>
929
+ <attribute name="type"/>
930
+ </optional>
925
931
  <optional>
926
932
  <attribute name="obligation">
927
933
  <choice>
@@ -961,9 +967,6 @@
961
967
  </define>
962
968
  <define name="content-subsection">
963
969
  <element name="clause">
964
- <optional>
965
- <attribute name="type"/>
966
- </optional>
967
970
  <ref name="Content-Section"/>
968
971
  </element>
969
972
  </define>
@@ -992,6 +995,9 @@
992
995
  </choice>
993
996
  </attribute>
994
997
  </optional>
998
+ <optional>
999
+ <attribute name="type"/>
1000
+ </optional>
995
1001
  <optional>
996
1002
  <ref name="section-title"/>
997
1003
  </optional>
@@ -1011,9 +1017,6 @@
1011
1017
  </define>
1012
1018
  <define name="clause">
1013
1019
  <element name="clause">
1014
- <optional>
1015
- <attribute name="type"/>
1016
- </optional>
1017
1020
  <ref name="Clause-Section"/>
1018
1021
  </element>
1019
1022
  </define>
@@ -1042,6 +1045,9 @@
1042
1045
  </choice>
1043
1046
  </attribute>
1044
1047
  </optional>
1048
+ <optional>
1049
+ <attribute name="type"/>
1050
+ </optional>
1045
1051
  <optional>
1046
1052
  <ref name="section-title"/>
1047
1053
  </optional>
@@ -1180,6 +1186,9 @@
1180
1186
  <optional>
1181
1187
  <attribute name="script"/>
1182
1188
  </optional>
1189
+ <optional>
1190
+ <attribute name="type"/>
1191
+ </optional>
1183
1192
  <optional>
1184
1193
  <attribute name="obligation">
1185
1194
  <choice>
@@ -8,7 +8,8 @@ module Asciidoctor
8
8
  def add(category, loc, msg)
9
9
  return if @novalid
10
10
  @log[category] = [] unless @log[category]
11
- @log[category] << { location: current_location(loc), message: msg }
11
+ @log[category] << { location: current_location(loc), message: msg,
12
+ context: context(loc) }
12
13
  loc = loc.nil? ? "" : "(#{current_location(loc)}): "
13
14
  warn "#{category}: #{loc}#{msg}"
14
15
  end
@@ -31,6 +32,13 @@ module Asciidoctor
31
32
  "??"
32
33
  end
33
34
 
35
+ def context(n)
36
+ return nil if n.is_a? String
37
+ n.respond_to?(:to_xml) and return n.to_xml
38
+ n.respond_to?(:to_s) and return n.to_s
39
+ nil
40
+ end
41
+
34
42
  def write(file)
35
43
  File.open(file, "w:UTF-8") do |f|
36
44
  f.puts "#{file} errors"
@@ -41,6 +49,7 @@ module Asciidoctor
41
49
  end.each do |n|
42
50
  loc = n[:location] ? "(#{n[:location]}): " : ""
43
51
  f.puts "#{loc}#{n[:message]}"
52
+ n[:context]&.split(/\n/)&.first(5)&.each { |l| f.puts "\t#{l}" }
44
53
  end
45
54
  end
46
55
  end
@@ -61,10 +61,10 @@ module Asciidoctor
61
61
  end
62
62
 
63
63
  def isorefrender1(t, m, yr, allp = "")
64
- t.title(**plaintxt) { |i| i << ref_normalise(m[:text]) }
65
- docid(t, m[:usrlbl]) if m[:usrlbl]
66
- docid(t, id_and_year(m[:code], yr) + allp)
67
- docnumber(t, m[:code])
64
+ t.title(**plaintxt) { |i| i << ref_normalise(m[:text]) }
65
+ docid(t, m[:usrlbl]) if m[:usrlbl]
66
+ docid(t, id_and_year(m[:code], yr) + allp)
67
+ docnumber(t, m[:code])
68
68
  end
69
69
 
70
70
  def isorefmatches(xml, m)
@@ -106,15 +106,16 @@ module Asciidoctor
106
106
 
107
107
  def isorefmatches3(xml, m)
108
108
  yr = norm_year(m[:year])
109
- hasyr = m.names.include?("year") && yr != "--"
110
- noyr = m.names.include?("year") && yr == "--"
111
- ref = fetch_ref xml, m[:code], hasyr ? yr : nil,
112
- all_parts: true, no_year: noyr, text: m[:text], usrlbl: m[:usrlbl]
109
+ #hasyr = m.names.include?("year") && yr != "--"
110
+ hasyr = !yr.nil? && yr != "--"
111
+ #noyr = m.names.include?("year") && yr == "--"
112
+ ref = fetch_ref xml, m[:code], hasyr ? yr : nil, all_parts: true,
113
+ no_year: yr == "--", text: m[:text], usrlbl: m[:usrlbl]
113
114
  return use_my_anchor(ref, m[:anchor]) if ref
114
115
 
115
116
  xml.bibitem(**attr_code(ref_attributes(m))) do |t|
116
117
  isorefrender1(t, m, yr, " (all parts)")
117
- conditional_date(t, m, noyr)
118
+ conditional_date(t, m, yr == "--")
118
119
  iso_publisher(t, m[:code])
119
120
  m.names.include?("fn") && m[:fn] and
120
121
  t.note(**plaintxt.merge(type: "ISO DATE")) { |p| p << "#{m[:fn]}" }
@@ -150,32 +151,30 @@ module Asciidoctor
150
151
  "https://www.metanorma.com/author/iso/topics/markup/#bibliographies".freeze
151
152
 
152
153
  def analyse_ref_nofetch(ret)
153
- if m = /^nofetch\((?<id>.+)\)$/.match(ret[:id])
154
- ret[:id] = m[:id]
155
- ret[:nofetch] = true
156
- end
154
+ return ret unless m = /^nofetch\((?<id>.+)\)$/.match(ret[:id])
155
+ ret[:id] = m[:id]
156
+ ret[:nofetch] = true
157
157
  ret
158
158
  end
159
-
159
+
160
160
  def analyse_ref_repo_path(ret)
161
- if m = /^(?<type>repo|path):\((?<key>[^,]+),(?<id>.+)\)$/.match(ret[:id])
162
- ret[:id] = m[:id]
163
- ret[:type] = m[:type]
164
- ret[:key] = m[:key]
165
- ret[:nofetch] = true
166
- end
167
- ret
161
+ return ret unless m =
162
+ /^(?<type>repo|path):\((?<key>[^,]+),(?<id>.+)\)$/.match(ret[:id])
163
+ ret[:id] = m[:id]
164
+ ret[:type] = m[:type]
165
+ ret[:key] = m[:key]
166
+ ret[:nofetch] = true
167
+ ret
168
168
  end
169
169
 
170
170
  def analyse_ref_numeric(ret)
171
- if /^\d+$/.match(ret[:id])
172
- ret[:numeric] = true
173
- end
171
+ return ret unless /^\d+$/.match(ret[:id])
172
+ ret[:numeric] = true
174
173
  ret
175
174
  end
176
175
 
177
176
  # ref id = (usrlbl)code[:-]year
178
- # code = nofetch(code) | (repo|path):(key,code) | \[? number \]? | identifier
177
+ # code = nofetch(code) | (repo|path):(key,code) | \[? number \]? | ident
179
178
  def analyse_ref_code(code)
180
179
  ret = {id: code}
181
180
  return ret if code.nil? || code.empty?
@@ -13,9 +13,13 @@ module Asciidoctor
13
13
  @term_def
14
14
  end
15
15
 
16
- def sectiontype(node, level = true)
17
- ret = node&.attr("heading")&.downcase ||
16
+ def sectiontype1(node)
17
+ node&.attr("heading")&.downcase ||
18
18
  node.title.gsub(/<[^>]+>/, "").downcase
19
+ end
20
+
21
+ def sectiontype(node, level = true)
22
+ ret = sectiontype1(node)
19
23
  ret1 = sectiontype_streamline(ret)
20
24
  return ret1 if "symbols and abbreviated terms" == ret1
21
25
  return nil unless !level || node.level == 1
@@ -61,16 +65,18 @@ module Asciidoctor
61
65
  case sectiontype(node)
62
66
  when "introduction" then introduction_parse(a, xml, node)
63
67
  when "foreword" then foreword_parse(a, xml, node)
68
+ when "scope" then scope_parse(a, xml, node)
64
69
  when "normative references" then norm_ref_parse(a, xml, node)
65
70
  when "terms and definitions"
66
71
  @term_def = true
67
72
  term_def_parse(a, xml, node, true)
68
73
  @term_def = false
69
74
  when "symbols and abbreviated terms"
70
- symbols_parse(a, xml, node)
75
+ symbols_parse(symbols_attrs(node, a), xml, node)
71
76
  when "acknowledgements"
72
77
  acknowledgements_parse(a, xml, node)
73
- when "bibliography" then bibliography_parse(a, xml, node)
78
+ when "bibliography"
79
+ bibliography_parse(a, xml, node)
74
80
  else
75
81
  if @term_def then term_def_subclause_parse(a, xml, node)
76
82
  elsif @definitions then symbols_parse(a, xml, node)
@@ -106,7 +112,7 @@ module Asciidoctor
106
112
  def preamble(node)
107
113
  noko do |xml|
108
114
  xml.foreword **attr_code(section_attributes(node)) do |xml_abstract|
109
- xml_abstract.title { |t| t << (node.blocks[0].title || "Foreword") }
115
+ xml_abstract.title { |t| t << (node.blocks[0].title || @i18n.foreword) }
110
116
  content = node.content
111
117
  xml_abstract << content
112
118
  end
@@ -119,6 +125,10 @@ module Asciidoctor
119
125
  end
120
126
  end
121
127
 
128
+ def scope_parse(attrs, xml, node)
129
+ clause_parse(attrs.merge(type: "scope"), xml, node)
130
+ end
131
+
122
132
  def clause_parse(attrs, xml, node)
123
133
  attrs["inline-header".to_sym] = node.option? "inline-header"
124
134
  attrs[:bibitem] = true if node.option? "bibitem"
@@ -140,9 +150,19 @@ module Asciidoctor
140
150
  end
141
151
 
142
152
  def nonterm_symbols_parse(attrs, xml, node)
153
+ defs = @definitions
143
154
  @definitions = false
144
155
  clause_parse(attrs, xml, node)
145
- @definitions = true
156
+ @definitions = defs
157
+ end
158
+
159
+ def symbols_attrs(node, a)
160
+ case sectiontype1(node)
161
+ when "symbols" then a.merge(type: "symbols")
162
+ when "abbreviated terms", "abbreviations" then a.merge(type: "abbreviated_terms")
163
+ else
164
+ a
165
+ end
146
166
  end
147
167
 
148
168
  def symbols_parse(attr, xml, node)
@@ -159,13 +179,11 @@ module Asciidoctor
159
179
  end
160
180
  end
161
181
 
162
- SYMBOLS_TITLES = ["symbols and abbreviated terms", "symbols",
163
- "abbreviated terms"].freeze
164
-
165
182
  def nonterm_term_def_subclause_parse(attrs, xml, node)
183
+ defs = @term_def
166
184
  @term_def = false
167
185
  clause_parse(attrs, xml, node)
168
- @term_def = true
186
+ @term_def = defs
169
187
  end
170
188
 
171
189
  # subclause contains subclauses
@@ -190,23 +208,9 @@ module Asciidoctor
190
208
  end
191
209
  end
192
210
 
193
- def term_def_title(toplevel, node)
194
- return node.title unless toplevel
195
- sub = node.find_by(context: :section) do |s|
196
- SYMBOLS_TITLES.include? s.title.downcase
197
- end
198
- return "Terms and definitions" if sub.empty?
199
- sym = /symbol/i.match(node.title)
200
- abbrev = /abbreviat/i.match(node.title)
201
- sym && abbrev and return "Terms, definitions, symbols and abbreviated terms"
202
- sym and return "Terms, definitions and symbols"
203
- abbrev and return "Terms, definitions and abbreviated terms"
204
- "Terms, definitions, symbols and abbreviated terms"
205
- end
206
-
207
211
  def term_def_parse(attrs, xml, node, toplevel)
208
212
  xml.terms **attr_code(attrs) do |section|
209
- section.title { |t| t << term_def_title(toplevel, node) }
213
+ section.title { |t| t << node.title }
210
214
  (s = node.attr("source")) && s.split(/,/).each do |s1|
211
215
  section.termdocsource(nil, **attr_code(bibitemid: s1))
212
216
  end
@@ -216,7 +220,7 @@ module Asciidoctor
216
220
 
217
221
  def introduction_parse(attrs, xml, node)
218
222
  xml.introduction **attr_code(attrs) do |xml_section|
219
- xml_section.title { |t| t << "Introduction" }
223
+ xml_section.title { |t| t << @i18n.introduction }
220
224
  content = node.content
221
225
  xml_section << content
222
226
  end
@@ -232,7 +236,7 @@ module Asciidoctor
232
236
 
233
237
  def acknowledgements_parse(attrs, xml, node)
234
238
  xml.acknowledgements **attr_code(attrs) do |xml_section|
235
- xml_section.title { |t| t << node.title || "Acknowledgements" }
239
+ xml_section.title { |t| t << node.title || @i18n.acknowledgements }
236
240
  content = node.content
237
241
  xml_section << content
238
242
  end