metanorma-standoc 1.8.8 → 1.9.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4c6a59c6f6a5cfd1b0f6515cf768e060cf846f239b2336a6db7bfb8fef1b75ec
4
- data.tar.gz: f88ef657e463750bdad1f01389f8fc9f30fb881ec4f517010a58ca8676c74e04
3
+ metadata.gz: 5cd6e66873fc1d0b703e0fee76f1ed3a56de06684135f142e3be3865bb7c21fa
4
+ data.tar.gz: ec666e930ce8ad73f39563050aaf052ddc0ed31a1778dec88cd1bf7308ddef12
5
5
  SHA512:
6
- metadata.gz: 21a8546de21b8a31a98dc6b2a48a7afed919e847c4e25d54094b60e9ac5fe6489a42b7b0a99b42577f505232b5d2cbd8099c27a3a811db092cb305dfeeb396fe
7
- data.tar.gz: 7bbe4985fcf8e3ffe2190552d16d3ece90cd462c4f5ab841241821ea527a00242cd1b17622f07cd6e9900b4875cbefbf0e84d21f7aae0a39ad7be571392ab007
6
+ metadata.gz: 65062d39f1c2bd1c33ceaf3bc0d55f5be7c34728c4b9027c7b7192c5ddf8a4b3cc3e37705070b471aac7c20117946a6dae150a5e31613d36afff59bb3ab5aa39
7
+ data.tar.gz: e1ca0ba1c31ad442c6359d30ca338fecb840dd86839d01cf697e314b365f72da424a6f93eecb1906eafdc34e2f489f2afd9f264ce1762cd1bc2e7524711ac653
data/Gemfile.devel ADDED
File without changes
@@ -8,6 +8,7 @@ require "isodoc"
8
8
  require "relaton"
9
9
  require "fileutils"
10
10
  require "metanorma-utils"
11
+ require "isodoc/xslfo_convert"
11
12
 
12
13
  module Asciidoctor
13
14
  module Standoc
@@ -52,6 +53,7 @@ module Asciidoctor
52
53
  htmltoclevels: node.attr("htmltoclevels") || node.attr("toclevels"),
53
54
  doctoclevels: node.attr("doctoclevels") || node.attr("toclevels"),
54
55
  break_up_urls_in_tables: node.attr("break-up-urls-in-tables"),
56
+ sectionsplit: node.attr("sectionsplit"),
55
57
  }
56
58
  end
57
59
 
@@ -60,7 +62,7 @@ module Asciidoctor
60
62
  end
61
63
 
62
64
  def doc_extract_attributes(node)
63
- {
65
+ attrs = {
64
66
  script: node.attr("script"),
65
67
  bodyfont: node.attr("body-font"),
66
68
  headerfont: node.attr("header-font"),
@@ -79,6 +81,14 @@ module Asciidoctor
79
81
  doctoclevels: node.attr("doctoclevels") || node.attr("toclevels"),
80
82
  break_up_urls_in_tables: node.attr("break-up-urls-in-tables"),
81
83
  }
84
+
85
+ if font_manifest_file = node.attr("mn2pdf-font-manifest-file")
86
+ attrs[IsoDoc::XslfoPdfConvert::MN2PDF_OPTIONS] = {
87
+ IsoDoc::XslfoPdfConvert::MN2PDF_FONT_MANIFEST => font_manifest_file,
88
+ }
89
+ end
90
+
91
+ attrs
82
92
  end
83
93
 
84
94
  def doc_converter(node)
@@ -3,21 +3,26 @@ module Asciidoctor
3
3
  module Cleanup
4
4
  def external_terms_boilerplate(sources)
5
5
  @i18n.l10n(
6
- @i18n.external_terms_boilerplate.gsub(/%/, sources || "???"), @lang, @script)
6
+ @i18n.external_terms_boilerplate.gsub(/%/, sources || "???"),
7
+ @lang, @script
8
+ )
7
9
  end
8
10
 
9
11
  def internal_external_terms_boilerplate(sources)
10
12
  @i18n.l10n(
11
- @i18n.internal_external_terms_boilerplate.gsub(/%/, sources || "??"), @lang, @script)
13
+ @i18n.internal_external_terms_boilerplate.gsub(/%/, sources || "??"),
14
+ @lang, @script
15
+ )
12
16
  end
13
17
 
14
18
  def term_defs_boilerplate(div, source, term, preface, isodoc)
15
19
  a = @i18n.term_def_boilerplate and div.next = a
16
20
  source.each do |s|
17
21
  @anchors[s["bibitemid"]] or
18
- @log.add("Crossreferences", nil, "term source #{s['bibitemid']} not referenced")
22
+ @log.add("Crossreferences", nil,
23
+ "term source #{s['bibitemid']} not referenced")
19
24
  end
20
- a = (source.empty? && term.nil?) ? @i18n.no_terms_boilerplate :
25
+ a = source.empty? && term.nil? ? @i18n.no_terms_boilerplate :
21
26
  term_defs_boilerplate_cont(source, term, isodoc)
22
27
  a and div.next = a
23
28
  end
@@ -55,7 +60,7 @@ module Asciidoctor
55
60
  end
56
61
 
57
62
  def termdef_boilerplate_cleanup(xmldoc)
58
- #termdef_remove_initial_paras(xmldoc)
63
+ # termdef_remove_initial_paras(xmldoc)
59
64
  end
60
65
 
61
66
  def termdef_remove_initial_paras(xmldoc)
@@ -76,6 +81,7 @@ module Asciidoctor
76
81
  termdef_boilerplate_cleanup(xmldoc)
77
82
  xmldoc.xpath(self.class::TERM_CLAUSE).each do |f|
78
83
  next if f.at("./clause[@type = 'boilerplate']")
84
+
79
85
  term_defs_boilerplate(f.at("./title"), xmldoc.xpath(".//termdocsource"),
80
86
  f.at(".//term"), f.at(".//p"), isodoc)
81
87
  end
@@ -84,15 +90,16 @@ module Asciidoctor
84
90
  initial_boilerplate(xmldoc, isodoc)
85
91
  end
86
92
 
87
- def initial_boilerplate(x, isodoc)
88
- return if x.at("//boilerplate")
89
- preface = x.at("//preface") || x.at("//sections") || x.at("//annex") ||
90
- x.at("//references") || return
91
- b = boilerplate(x, isodoc) or return
93
+ def initial_boilerplate(xml, isodoc)
94
+ return if xml.at("//boilerplate")
95
+
96
+ preface = xml.at("//preface") || xml.at("//sections") ||
97
+ xml.at("//annex") || xml.at("//references") || return
98
+ b = boilerplate(xml, isodoc) or return
92
99
  preface.previous = b
93
100
  end
94
101
 
95
- def boilerplate_file(xmldoc)
102
+ def boilerplate_file(_xmldoc)
96
103
  File.join(@libdir, "boilerplate.xml")
97
104
  end
98
105
 
@@ -100,7 +107,7 @@ module Asciidoctor
100
107
  file = boilerplate_file(xml)
101
108
  file = File.join(@localdir, @boilerplateauthority) if @boilerplateauthority
102
109
  !file.nil? and File.exists?(file) or return
103
- conv.populate_template((File.read(file, encoding: "UTF-8")), nil)
110
+ conv.populate_template(File.read(file, encoding: "UTF-8"), nil)
104
111
  end
105
112
 
106
113
  def bibdata_cleanup(xmldoc)
@@ -118,14 +125,16 @@ module Asciidoctor
118
125
  def bibdata_docidentifier_cleanup(xmldoc)
119
126
  ins = xmldoc.at("//bibdata/docidentifier")
120
127
  xmldoc.xpath("//bibdata/docidentifier").each_with_index do |b, i|
121
- next if i == 0
128
+ next if i.zero?
129
+
122
130
  ins.next = b.remove
123
131
  ins = ins.next
124
132
  end
125
133
  end
126
134
 
127
135
  def gather_indirect_erefs(xmldoc, prefix)
128
- xmldoc.xpath("//eref[@type = '#{prefix}']").each_with_object({}) do |e, m|
136
+ xmldoc.xpath("//eref[@type = '#{prefix}']")
137
+ .each_with_object({}) do |e, m|
129
138
  e.delete("type")
130
139
  m[e["bibitemid"]] = true
131
140
  end.keys
@@ -43,7 +43,7 @@ module Asciidoctor
43
43
  end
44
44
 
45
45
  def bibabstract_location(x)
46
- bibabstract = x.at("//bibdata/script") || x.at("//bibdata/language") ||
46
+ x.at("//bibdata/script") || x.at("//bibdata/language") ||
47
47
  x.at("//bibdata/contributor[not(following-sibling::contributor)]") ||
48
48
  x.at("//bibdata/date[not(following-sibling::date)]") ||
49
49
  x.at("//docnumber") ||
@@ -74,7 +74,6 @@ module Asciidoctor
74
74
  make_bibliography(x, s)
75
75
  x.xpath("//sections/annex").reverse_each { |r| s.next = r.remove }
76
76
  end
77
-
78
77
  def make_annexes(x)
79
78
  x.xpath("//*[@annex]").each do |y|
80
79
  y.delete("annex")
@@ -186,6 +185,7 @@ module Asciidoctor
186
185
 
187
186
  def replace_title(doc, xpath, text, first = false)
188
187
  return unless text
188
+
189
189
  doc.xpath(xpath).each_with_index do |node, i|
190
190
  next if first && !i.zero?
191
191
  title = get_or_make_title(node)
@@ -196,24 +196,24 @@ module Asciidoctor
196
196
  end
197
197
  end
198
198
 
199
- def sections_names_cleanup(x)
200
- replace_title(x, "//clause[@type = 'scope']", @i18n&.scope)
201
- replace_title(x, "//preface//abstract", @i18n&.abstract)
202
- replace_title(x, "//foreword", @i18n&.foreword)
203
- replace_title(x, "//introduction", @i18n&.introduction)
204
- replace_title(x, "//acknowledgements", @i18n&.acknowledgements)
205
- section_names_refs_cleanup(x)
206
- section_names_terms_cleanup(x)
199
+ def sections_names_cleanup(xml)
200
+ replace_title(xml, "//clause[@type = 'scope']", @i18n&.scope)
201
+ replace_title(xml, "//preface//abstract", @i18n&.abstract)
202
+ replace_title(xml, "//foreword", @i18n&.foreword)
203
+ replace_title(xml, "//introduction", @i18n&.introduction)
204
+ replace_title(xml, "//acknowledgements", @i18n&.acknowledgements)
205
+ section_names_refs_cleanup(xml)
206
+ section_names_terms_cleanup(xml)
207
207
  end
208
208
 
209
- def section_names_refs_cleanup(x)
210
- replace_title(x, "//references[@normative = 'true']",
209
+ def section_names_refs_cleanup(xml)
210
+ replace_title(xml, "//references[@normative = 'true']",
211
211
  @i18n&.normref, true)
212
- replace_title(x, "//references[@normative = 'false']",
212
+ replace_title(xml, "//references[@normative = 'false']",
213
213
  @i18n&.bibliography, true)
214
214
  end
215
215
 
216
- NO_SYMABBR = "[.//definitions[not(@type)]]"
216
+ NO_SYMABBR = "[.//definitions[not(@type)]]".freeze
217
217
  SYMABBR = "[.//definitions[@type = 'symbols']"\
218
218
  "[@type = 'abbreviated_terms']]".freeze
219
219
  SYMnoABBR = "[.//definitions[@type = 'symbols']"\
@@ -223,7 +223,8 @@ module Asciidoctor
223
223
 
224
224
  def section_names_terms_cleanup(x)
225
225
  replace_title(x, "//definitions[@type = 'symbols']", @i18n&.symbols)
226
- replace_title(x, "//definitions[@type = 'abbreviated_terms']", @i18n&.abbrev)
226
+ replace_title(x, "//definitions[@type = 'abbreviated_terms']",
227
+ @i18n&.abbrev)
227
228
  replace_title(x, "//definitions[not(@type)]", @i18n&.symbolsabbrev)
228
229
  replace_title(x, "//terms#{SYMnoABBR} | //clause[.//terms]#{SYMnoABBR}",
229
230
  @i18n&.termsdefsymbols, true)
@@ -13,7 +13,7 @@ require "asciidoctor/standoc/validate"
13
13
  require "asciidoctor/standoc/utils"
14
14
  require "asciidoctor/standoc/cleanup"
15
15
  require "asciidoctor/standoc/reqt"
16
- require_relative "./macros.rb"
16
+ require_relative "./macros"
17
17
 
18
18
  module Asciidoctor
19
19
  module Standoc
@@ -39,6 +39,8 @@ module Asciidoctor
39
39
  inline_macro Asciidoctor::Standoc::TermRefInlineMacro
40
40
  inline_macro Asciidoctor::Standoc::IndexXrefInlineMacro
41
41
  inline_macro Asciidoctor::Standoc::IndexRangeInlineMacro
42
+ inline_macro Asciidoctor::Standoc::AddMacro
43
+ inline_macro Asciidoctor::Standoc::DelMacro
42
44
  block Asciidoctor::Standoc::ToDoAdmonitionBlock
43
45
  treeprocessor Asciidoctor::Standoc::ToDoInlineAdmonitionBlock
44
46
  block Asciidoctor::Standoc::PlantUMLBlockMacro
@@ -45,7 +45,7 @@ module Asciidoctor
45
45
 
46
46
  def inline_anchor_xref_attrs(node)
47
47
  m = /^(?<drop>droploc%)?(?<case>capital%|lowercase%)?(?<drop2>droploc%)?
48
- (?<fn>fn(:\s*(?<text>.*))?)?$/x.match node.text
48
+ (?<fn>fn:?\s*)?(?<text>.*)$/x.match node.text
49
49
  casing = m.nil? ? nil : m[:case]&.sub(/%$/, "")
50
50
  droploc = m.nil? ? nil : ((m[:drop].nil? && m[:drop2].nil?) ? nil: true)
51
51
  f = (m.nil? || m[:fn].nil?) ? "inline" : "footnote"
@@ -86,6 +86,35 @@
86
86
  <text/>
87
87
  </element>
88
88
  </define>
89
+ <define name="erefType">
90
+ <optional>
91
+ <attribute name="normative">
92
+ <data type="boolean"/>
93
+ </attribute>
94
+ </optional>
95
+ <attribute name="citeas"/>
96
+ <attribute name="type">
97
+ <ref name="ReferenceFormat"/>
98
+ </attribute>
99
+ <optional>
100
+ <attribute name="alt"/>
101
+ </optional>
102
+ <optional>
103
+ <attribute name="case">
104
+ <choice>
105
+ <value>capital</value>
106
+ <value>lowercase</value>
107
+ </choice>
108
+ </attribute>
109
+ </optional>
110
+ <optional>
111
+ <attribute name="droploc">
112
+ <data type="boolean"/>
113
+ </attribute>
114
+ </optional>
115
+ <ref name="CitationType"/>
116
+ <text/>
117
+ </define>
89
118
  <define name="ul">
90
119
  <element name="ul">
91
120
  <attribute name="id">
@@ -775,6 +804,78 @@
775
804
  <ref name="paragraph"/>
776
805
  </element>
777
806
  </define>
807
+ <define name="em">
808
+ <element name="em">
809
+ <zeroOrMore>
810
+ <choice>
811
+ <ref name="PureTextElement"/>
812
+ <ref name="stem"/>
813
+ <ref name="index"/>
814
+ </choice>
815
+ </zeroOrMore>
816
+ </element>
817
+ </define>
818
+ <define name="strong">
819
+ <element name="strong">
820
+ <zeroOrMore>
821
+ <choice>
822
+ <ref name="PureTextElement"/>
823
+ <ref name="stem"/>
824
+ <ref name="index"/>
825
+ </choice>
826
+ </zeroOrMore>
827
+ </element>
828
+ </define>
829
+ <define name="tt">
830
+ <element name="tt">
831
+ <zeroOrMore>
832
+ <choice>
833
+ <ref name="PureTextElement"/>
834
+ <ref name="index"/>
835
+ </choice>
836
+ </zeroOrMore>
837
+ </element>
838
+ </define>
839
+ <define name="keyword">
840
+ <element name="keyword">
841
+ <zeroOrMore>
842
+ <choice>
843
+ <ref name="PureTextElement"/>
844
+ <ref name="index"/>
845
+ </choice>
846
+ </zeroOrMore>
847
+ </element>
848
+ </define>
849
+ <define name="strike">
850
+ <element name="strike">
851
+ <zeroOrMore>
852
+ <choice>
853
+ <ref name="PureTextElement"/>
854
+ <ref name="index"/>
855
+ </choice>
856
+ </zeroOrMore>
857
+ </element>
858
+ </define>
859
+ <define name="underline">
860
+ <element name="underline">
861
+ <zeroOrMore>
862
+ <choice>
863
+ <ref name="PureTextElement"/>
864
+ <ref name="index"/>
865
+ </choice>
866
+ </zeroOrMore>
867
+ </element>
868
+ </define>
869
+ <define name="smallcap">
870
+ <element name="smallcap">
871
+ <zeroOrMore>
872
+ <choice>
873
+ <ref name="PureTextElement"/>
874
+ <ref name="index"/>
875
+ </choice>
876
+ </zeroOrMore>
877
+ </element>
878
+ </define>
778
879
  </include>
779
880
  <!-- end overrides -->
780
881
  <define name="colgroup">
@@ -793,7 +894,35 @@
793
894
  <value>internal</value>
794
895
  </define>
795
896
  <define name="TextElement" combine="choice">
796
- <ref name="concept"/>
897
+ <choice>
898
+ <ref name="concept"/>
899
+ <ref name="add"/>
900
+ <ref name="del"/>
901
+ </choice>
902
+ </define>
903
+ <define name="add">
904
+ <element name="add">
905
+ <choice>
906
+ <ref name="PureTextElement"/>
907
+ <ref name="eref"/>
908
+ <ref name="stem"/>
909
+ <ref name="keyword"/>
910
+ <ref name="xref"/>
911
+ <ref name="hyperlink"/>
912
+ </choice>
913
+ </element>
914
+ </define>
915
+ <define name="del">
916
+ <element name="del">
917
+ <choice>
918
+ <ref name="PureTextElement"/>
919
+ <ref name="eref"/>
920
+ <ref name="stem"/>
921
+ <ref name="keyword"/>
922
+ <ref name="xref"/>
923
+ <ref name="hyperlink"/>
924
+ </choice>
925
+ </element>
797
926
  </define>
798
927
  <define name="concept">
799
928
  <element name="concept">
@@ -2,10 +2,10 @@ require "asciidoctor/extensions"
2
2
  require "fileutils"
3
3
  require "uuidtools"
4
4
  require "yaml"
5
- require_relative "./macros_plantuml.rb"
6
- require_relative "./macros_terms.rb"
7
- require_relative "./datamodel/attributes_table_preprocessor.rb"
8
- require_relative "./datamodel/diagram_preprocessor.rb"
5
+ require_relative "./macros_plantuml"
6
+ require_relative "./macros_terms"
7
+ require_relative "./datamodel/attributes_table_preprocessor"
8
+ require_relative "./datamodel/diagram_preprocessor"
9
9
  require "metanorma-plugin-datastruct"
10
10
  require "metanorma-plugin-lutaml"
11
11
 
@@ -29,6 +29,7 @@ module Asciidoctor
29
29
 
30
30
  def preprocess_attrs(attrs)
31
31
  return unless attrs.size > 1 && attrs.size < 5
32
+
32
33
  ret = { primary: attrs[1], target: attrs[attrs.size] }
33
34
  ret[:secondary] = attrs[2] if attrs.size > 2
34
35
  ret[:tertiary] = attrs[3] if attrs.size > 3
@@ -37,7 +38,8 @@ module Asciidoctor
37
38
 
38
39
  def process(_parent, target, attr)
39
40
  args = preprocess_attrs(attr) or return
40
- ret = "<index-xref also='#{target == 'also'}'><primary>#{args[:primary]}</primary>"
41
+ ret = "<index-xref also='#{target == 'also'}'>"\
42
+ "<primary>#{args[:primary]}</primary>"
41
43
  ret += "<secondary>#{args[:secondary]}</secondary>" if args[:secondary]
42
44
  ret += "<tertiary>#{args[:tertiary]}</tertiary>" if args[:tertiary]
43
45
  ret + "<target>#{args[:target]}</target></index-xref>"
@@ -51,7 +53,7 @@ module Asciidoctor
51
53
 
52
54
  def process(parent, target, attr)
53
55
  text = attr["text"]
54
- text = "((#{text}))" unless /^\(\(.+\)\)$/.match(text)
56
+ text = "((#{text}))" unless /^\(\(.+\)\)$/.match?(text)
55
57
  out = parent.sub_macros(text)
56
58
  out.sub(/<index>/, "<index to='#{target}'>")
57
59
  end
@@ -62,8 +64,8 @@ module Asciidoctor
62
64
  named :pseudocode
63
65
  on_context :example, :sourcecode
64
66
 
65
- def init_indent(s)
66
- /^(?<prefix>[ \t]*)(?<suffix>.*)$/ =~ s
67
+ def init_indent(line)
68
+ /^(?<prefix>[ \t]*)(?<suffix>.*)$/ =~ line
67
69
  prefix = prefix.gsub(/\t/, "\u00a0\u00a0\u00a0\u00a0")
68
70
  .gsub(/ /, "\u00a0")
69
71
  prefix + suffix
@@ -75,9 +77,10 @@ module Asciidoctor
75
77
  /^(--+|====+|\|===|\.\.\.\.+|\*\*\*\*+|\+\+\+\++|\`\`\`\`+|____\+)$/.match(l) &&
76
78
  (ignore = !ignore)
77
79
  next if l.empty? || l.match(/ \+$/)
78
- next if /^\[.*\]$/.match(l)
80
+ next if /^\[.*\]$/.match?(l)
79
81
  next if ignore
80
82
  next if i == lines.size - 1 || i < lines.size - 1 && lines[i + 1].empty?
83
+
81
84
  lines[i] += " +"
82
85
  end
83
86
  lines
@@ -86,9 +89,8 @@ module Asciidoctor
86
89
  def process(parent, reader, attrs)
87
90
  attrs["role"] = "pseudocode"
88
91
  lines = reader.lines.map { |m| init_indent(m) }
89
- ret = create_block(parent, :example, supply_br(lines),
90
- attrs, content_model: :compound)
91
- ret
92
+ create_block(parent, :example, supply_br(lines),
93
+ attrs, content_model: :compound)
92
94
  end
93
95
  end
94
96
 
@@ -98,6 +100,7 @@ module Asciidoctor
98
100
  parse_content_as :text
99
101
  option :pos_attrs, %w(rpbegin rt rpend)
100
102
 
103
+ # for example, html5ruby:楽聖少女[がくせいしょうじょ]
101
104
  def process(_parent, target, attributes)
102
105
  rpbegin = "("
103
106
  rpend = ")"
@@ -105,7 +108,6 @@ module Asciidoctor
105
108
  rt = attributes["text"]
106
109
  elsif (attributes.size == 2) && attributes.key?(1) &&
107
110
  attributes.key?("rpbegin")
108
- # for example, html5ruby:楽聖少女[がくせいしょうじょ]
109
111
  rt = attributes[1] || ""
110
112
  else
111
113
  rpbegin = attributes["rpbegin"]
@@ -135,6 +137,7 @@ module Asciidoctor
135
137
  def process(document)
136
138
  (document.find_by context: :paragraph).each do |para|
137
139
  next unless /^TODO: /.match para.lines[0]
140
+
138
141
  parent = para.parent
139
142
  para.set_attr("name", "todo")
140
143
  para.set_attr("caption", "TODO")
@@ -182,5 +185,29 @@ module Asciidoctor
182
185
  %{<footnoteblock>#{out}</footnoteblock>}
183
186
  end
184
187
  end
188
+
189
+ class AddMacro < Asciidoctor::Extensions::InlineMacroProcessor
190
+ use_dsl
191
+ named :add
192
+ parse_content_as :text
193
+ using_format :short
194
+
195
+ def process(parent, _target, attrs)
196
+ out = Asciidoctor::Inline.new(parent, :quoted, attrs["text"]).convert
197
+ %{<add>#{out}</add>}
198
+ end
199
+ end
200
+
201
+ class DelMacro < Asciidoctor::Extensions::InlineMacroProcessor
202
+ use_dsl
203
+ named :del
204
+ parse_content_as :text
205
+ using_format :short
206
+
207
+ def process(parent, _target, attrs)
208
+ out = Asciidoctor::Inline.new(parent, :quoted, attrs["text"]).convert
209
+ %{<del>#{out}</del>}
210
+ end
211
+ end
185
212
  end
186
213
  end