isodoc 1.6.7 → 1.7.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/isodoc.gemspec +1 -1
  3. data/lib/isodoc-yaml/i18n-ar.yaml +19 -25
  4. data/lib/isodoc-yaml/i18n-de.yaml +1 -0
  5. data/lib/isodoc-yaml/i18n-en.yaml +1 -0
  6. data/lib/isodoc-yaml/i18n-es.yaml +1 -0
  7. data/lib/isodoc-yaml/i18n-fr.yaml +1 -0
  8. data/lib/isodoc-yaml/i18n-ru.yaml +1 -0
  9. data/lib/isodoc-yaml/i18n-zh-Hans.yaml +1 -0
  10. data/lib/isodoc.rb +1 -0
  11. data/lib/isodoc/convert.rb +1 -1
  12. data/lib/isodoc/function/blocks.rb +180 -168
  13. data/lib/isodoc/function/form.rb +39 -36
  14. data/lib/isodoc/function/inline.rb +5 -1
  15. data/lib/isodoc/function/references.rb +1 -1
  16. data/lib/isodoc/function/to_word_html.rb +206 -204
  17. data/lib/isodoc/html_convert.rb +0 -4
  18. data/lib/isodoc/html_function/form.rb +48 -45
  19. data/lib/isodoc/html_function/html.rb +2 -0
  20. data/lib/isodoc/html_function/postprocess.rb +9 -4
  21. data/lib/isodoc/presentation_function/block.rb +7 -4
  22. data/lib/isodoc/presentation_function/inline.rb +29 -12
  23. data/lib/isodoc/presentation_function/section.rb +1 -2
  24. data/lib/isodoc/presentation_xml_convert.rb +2 -2
  25. data/lib/isodoc/version.rb +1 -1
  26. data/lib/isodoc/xref.rb +8 -7
  27. data/lib/isodoc/xref/xref_anchor.rb +45 -44
  28. data/lib/isodoc/xref/xref_counter.rb +113 -103
  29. data/lib/isodoc/xref/xref_gen.rb +39 -11
  30. data/lib/metanorma/output.rb +7 -0
  31. data/lib/metanorma/output/base.rb +13 -0
  32. data/lib/metanorma/output/utils.rb +17 -0
  33. data/lib/metanorma/output/xslfo.rb +21 -0
  34. data/spec/assets/outputtest/a.xml +66 -0
  35. data/spec/assets/outputtest/iso.international-standard.xsl +3011 -0
  36. data/spec/isodoc/blocks_spec.rb +327 -243
  37. data/spec/isodoc/form_spec.rb +94 -90
  38. data/spec/isodoc/inline_spec.rb +431 -234
  39. data/spec/isodoc/postproc_spec.rb +68 -25
  40. data/spec/isodoc/terms_spec.rb +2 -2
  41. data/spec/isodoc/xref_spec.rb +274 -652
  42. metadata +8 -18
  43. data/lib/isodoc/html_function/sectionsplit.rb +0 -230
  44. data/spec/isodoc/sectionsplit_spec.rb +0 -190
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: isodoc
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.6.7
4
+ version: 1.7.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-06-21 00:00:00.000000000 Z
11
+ date: 2021-08-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: asciimath
@@ -66,20 +66,6 @@ dependencies:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: '4'
69
- - !ruby/object:Gem::Dependency
70
- name: metanorma
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - ">="
74
- - !ruby/object:Gem::Version
75
- version: 1.2.0
76
- type: :runtime
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - ">="
81
- - !ruby/object:Gem::Version
82
- version: 1.2.0
83
69
  - !ruby/object:Gem::Dependency
84
70
  name: nokogiri
85
71
  requirement: !ruby/object:Gem::Requirement
@@ -410,7 +396,6 @@ files:
410
396
  - lib/isodoc/html_function/mathvariant_to_plain.rb
411
397
  - lib/isodoc/html_function/postprocess.rb
412
398
  - lib/isodoc/html_function/postprocess_footnotes.rb
413
- - lib/isodoc/html_function/sectionsplit.rb
414
399
  - lib/isodoc/i18n.rb
415
400
  - lib/isodoc/metadata.rb
416
401
  - lib/isodoc/metadata_contributor.rb
@@ -440,6 +425,10 @@ files:
440
425
  - lib/isodoc/xref/xref_gen_seq.rb
441
426
  - lib/isodoc/xref/xref_sect_gen.rb
442
427
  - lib/isodoc/xslfo_convert.rb
428
+ - lib/metanorma/output.rb
429
+ - lib/metanorma/output/base.rb
430
+ - lib/metanorma/output/utils.rb
431
+ - lib/metanorma/output/xslfo.rb
443
432
  - spec/assets/header.html
444
433
  - spec/assets/html.scss
445
434
  - spec/assets/html_override.css
@@ -450,6 +439,8 @@ files:
450
439
  - spec/assets/odf.emf
451
440
  - spec/assets/odf.svg
452
441
  - spec/assets/odf1.svg
442
+ - spec/assets/outputtest/a.xml
443
+ - spec/assets/outputtest/iso.international-standard.xsl
453
444
  - spec/assets/rice_image1
454
445
  - spec/assets/rice_image1.png
455
446
  - spec/assets/scripts.html
@@ -471,7 +462,6 @@ files:
471
462
  - spec/isodoc/presentation_xml_spec.rb
472
463
  - spec/isodoc/ref_spec.rb
473
464
  - spec/isodoc/section_spec.rb
474
- - spec/isodoc/sectionsplit_spec.rb
475
465
  - spec/isodoc/table_spec.rb
476
466
  - spec/isodoc/terms_spec.rb
477
467
  - spec/isodoc/xref_spec.rb
@@ -1,230 +0,0 @@
1
- require "metanorma"
2
- require "yaml"
3
-
4
- module IsoDoc::HtmlFunction
5
- module Html
6
- # assume we pass in Presentation XML, but we want to recover Semantic XML
7
- def sectionsplit_convert(input_filename, file, debug, output_filename = nil)
8
- input_filename += ".xml" unless input_filename.match?(/\.xml$/)
9
- File.exist?(input_filename) or
10
- File.open(input_filename, "w:UTF-8") { |f| f.write(file) }
11
- presxml = File.read(input_filename, encoding: "utf-8")
12
- @openmathdelim, @closemathdelim = extract_delims(presxml)
13
- xml, filename, dir = convert_init(presxml, input_filename, debug)
14
- build_collection(xml, presxml, output_filename || filename, dir)
15
- end
16
-
17
- def build_collection(xml, presxml, filename, dir)
18
- base = File.basename(filename)
19
- collection_setup(base, dir)
20
- files = sectionsplit(xml, base, dir)
21
- collection_manifest(base, files, xml, presxml, dir).render(
22
- format: %i(html), output_folder: "#{filename}_collection",
23
- coverpage: File.join(dir, "cover.html")
24
- )
25
- end
26
-
27
- def collection_manifest(filename, files, origxml, _presxml, dir)
28
- File.open(File.join(dir, "#{filename}.html.yaml"), "w:UTF-8") do |f|
29
- f.write(collectionyaml(files, origxml))
30
- end
31
- Metanorma::Collection.parse File.join(dir, "#{filename}.html.yaml")
32
- end
33
-
34
- def collection_setup(filename, dir)
35
- FileUtils.mkdir_p "#{filename}_collection"
36
- FileUtils.mkdir_p dir
37
- File.open(File.join(dir, "cover.html"), "w:UTF-8") do |f|
38
- f.write(coll_cover)
39
- end
40
- end
41
-
42
- def coll_cover
43
- <<~COVER
44
- <html>
45
- <head/>
46
- <body>
47
- <h1>{{ doctitle }}</h1>
48
- <h2>{{ docnumber }}</h2>
49
- <nav>{{ labels["navigation"] }}</nav>
50
- </body>
51
- </html>
52
- COVER
53
- end
54
-
55
- def sectionsplit(xml, filename, dir)
56
- xref_preprocess(xml)
57
- out = emptydoc(xml)
58
- [["//preface/*", "preface"], ["//sections/*", "sections"],
59
- ["//annex", nil],
60
- ["//bibliography/*[not(@hidden = 'true')]", "bibliography"],
61
- ["//indexsect", nil]].each_with_object([]) do |n, ret|
62
- xml.xpath(ns(n[0])).each do |s|
63
- ret << sectionfile(out, dir, "#{filename}.#{ret.size}", s, n[1])
64
- end
65
- end
66
- end
67
-
68
- def emptydoc(xml)
69
- out = xml.dup
70
- out.xpath(
71
- ns("//preface | //sections | //annex | //bibliography/clause | "\
72
- "//bibliography/references[not(@hidden = 'true')] | //indexsect"),
73
- ).each(&:remove)
74
- out
75
- end
76
-
77
- def sectionfile(xml, dir, file, chunk, parentnode)
78
- fname = create_sectionfile(xml.dup, dir, file, chunk, parentnode)
79
- { order: chunk["displayorder"].to_i, url: fname,
80
- title: titlerender(chunk) }
81
- end
82
-
83
- def create_sectionfile(out, dir, file, chunk, parentnode)
84
- ins = out.at(ns("//misccontainer")) || out.at(ns("//bibdata"))
85
- if parentnode
86
- ins.next = "<#{parentnode}/>"
87
- ins.next.add_child(chunk.dup)
88
- else
89
- ins.next = chunk.dup
90
- end
91
- outname = "#{file}.xml"
92
- File.open(File.join(dir, outname), "w:UTF-8") { |f| f.write(out) }
93
- outname
94
- end
95
-
96
- def xref_preprocess(xml)
97
- svg_preprocess(xml)
98
- key = (0...8).map { rand(65..90).chr }.join # random string
99
- refs = eref_to_internal_eref(xml, key)
100
- refs += xref_to_internal_eref(xml, key)
101
- xml.root["type"] = key # to force recognition of internal refs
102
- insert_indirect_biblio(xml, refs, key)
103
- end
104
-
105
- def svg_preprocess(xml)
106
- xml.xpath("//m:svg", "m" => "http://www.w3.org/2000/svg").each do |s|
107
- m = svgmap_wrap(s)
108
- s.xpath(".//m:a", "m" => "http://www.w3.org/2000/svg").each do |a|
109
- next unless /^#/.match? a["href"]
110
-
111
- a["href"] = a["href"].sub(/^#/, "")
112
- m << "<target href='#{a['href']}'>"\
113
- "<xref target='#{a['href']}'/></target>"
114
- end
115
- end
116
- end
117
-
118
- def svgmap_wrap(svg)
119
- ret = svg.at("./ancestor::xmlns:svgmap") and return ret
120
- ret = svg.at("./ancestor::xmlns:figure")
121
- ret.wrap("<svgmap/>")
122
- svg.at("./ancestor::xmlns:svgmap")
123
- end
124
-
125
- def make_anchor(anchor)
126
- "<localityStack><locality type='anchor'><referenceFrom>"\
127
- "#{anchor}</referenceFrom></locality></localityStack>"
128
- end
129
-
130
- def xref_to_internal_eref(xml, key)
131
- xml.xpath(ns("//xref")).each_with_object({}) do |x, m|
132
- x["bibitemid"] = "#{key}_#{x['target']}"
133
- x << make_anchor(x["target"])
134
- m[x["bibitemid"]] = true
135
- x.delete("target")
136
- x["type"] = key
137
- x.name = "eref"
138
- end.keys
139
- end
140
-
141
- def eref_to_internal_eref(xml, key)
142
- eref_to_internal_eref_select(xml).each_with_object([]) do |x, m|
143
- url = xml.at(ns("//bibitem[@id = '#{x}']/url[@type = 'citation']"))
144
- xml.xpath(("//*[@bibitemid = '#{x}']")).each do |e|
145
- id = eref_to_internal_eref1(e, key, url)
146
- id and m << id
147
- end
148
- end
149
- end
150
-
151
- def eref_to_internal_eref1(elem, key, url)
152
- if url
153
- elem.name = "link"
154
- elem["target"] = url
155
- nil
156
- else
157
- elem["bibitemid"] = "#{key}_#{elem['bibitemid']}"
158
- elem << make_anchor(elem["bibitemid"])
159
- elem["type"] = key
160
- elem["bibitemid"]
161
- end
162
- end
163
-
164
- def eref_to_internal_eref_select(xml)
165
- refs = xml.xpath(("//*/@bibitemid")).map { |x| x.text } # rubocop:disable Style/SymbolProc
166
- refs.uniq.reject do |x|
167
- xml.at(ns("//bibitem[@id = '#{x}'][@type = 'internal']"))
168
- end
169
- end
170
-
171
- # from standoc
172
- def insert_indirect_biblio(xmldoc, refs, prefix)
173
- ins = xmldoc.at("bibliography") or
174
- xmldoc.root << "<bibliography/>" and ins = xmldoc.at("bibliography")
175
- ins = ins.add_child("<references hidden='true' normative='false'/>").first
176
- refs.each do |x|
177
- ins << <<~BIBENTRY
178
- <bibitem id="#{x}" type="internal">
179
- <docidentifier type="repository">#{x.sub(/^#{prefix}_/, "#{prefix}/")}</docidentifier>
180
- </bibitem>
181
- BIBENTRY
182
- end
183
- end
184
-
185
- def recursive_string_keys(hash)
186
- case hash
187
- when Hash then Hash[
188
- hash.map { |k, v| [k.to_s, recursive_string_keys(v)] }
189
- ]
190
- when Enumerable then hash.map { |v| recursive_string_keys(v) }
191
- else
192
- hash
193
- end
194
- end
195
-
196
- def titlerender(section)
197
- title = section.at(ns("./title")) or return "[Untitled]"
198
- t = title.dup
199
- t.xpath(ns(".//tab | .//br")).each { |x| x.replace(" ") }
200
- t.xpath(ns(".//strong")).each { |x| x.replace(x.children) }
201
- t.children.to_xml
202
- end
203
-
204
- def collectionyaml(files, xml)
205
- ret = {
206
- directives: ["presentation-xml", "bare-after-first"],
207
- bibdata: {
208
- title: {
209
- type: "title-main",
210
- language: @lang,
211
- content: xml.at(ns("//bibdata/title")).text,
212
- },
213
- type: "collection",
214
- docid: {
215
- type: xml.at(ns("//bibdata/docidentifier/@type")).text,
216
- id: xml.at(ns("//bibdata/docidentifier")).text,
217
- },
218
- },
219
- manifest: {
220
- level: "collection",
221
- title: "Collection",
222
- docref: files.sort_by { |f| f[:order] }.each.map do |f|
223
- { fileref: f[:url], identifier: f[:title] }
224
- end,
225
- },
226
- }
227
- recursive_string_keys(ret).to_yaml
228
- end
229
- end
230
- end
@@ -1,190 +0,0 @@
1
- require "spec_helper"
2
-
3
- RSpec.describe IsoDoc do
4
- it "processes section split HTML" do
5
- FileUtils.rm_f "test.xml"
6
- FileUtils.rm_f "test.html.yaml"
7
- FileUtils.rm_rf "test_collection"
8
- FileUtils.rm_rf "test_files"
9
- input = <<~INPUT
10
- <iso-standard xmlns="http://riboseinc.com/isoxml">
11
- <bibdata>
12
- <title>ISO Title</title>
13
- <docidentifier type="ISO">ISO 1</docidentifier>
14
- </bibdata>
15
- <preface>
16
- <abstract id="A" displayorder='1'><title>abstract</title></abstract>
17
- <introduction id="B" displayorder='2'><title>introduction</title></introduction>
18
- </preface>
19
- <sections>
20
- <clause id="M" inline-header="false" obligation="normative" displayorder='4'>
21
- <title>Clause 4</title>
22
- <clause id="N" inline-header="false" obligation="normative">
23
- <title>Introduction</title>
24
- <p><xref target="A">HE</xref></p>
25
- <p><eref bibitemid="R1">SHE</xref></p>
26
- <svgmap>
27
- <figure>
28
- <svg xmlns="http://www.w3.org/2000/svg">
29
- <a href="#A">A</a>
30
- <a href="#B">B</a>
31
- </svg>
32
- <target href="B"><eref bibitemid="R1"/></target>
33
- </figure>
34
- </svgmap>
35
- <figure>
36
- <svg xmlns="http://www.w3.org/2000/svg">
37
- <a href="#P">P</a>
38
- </svg>
39
- </figure>
40
- </clause>
41
- <clause id="O" inline-header="true" obligation="normative">
42
- <title>Clause 4.2</title>
43
- </clause></clause>
44
- <admonition id="L" type="caution"><p>admonition</p></admonition>
45
- </sections>
46
- <annex id="P" inline-header="false" obligation="normative" displayorder='5'>
47
- <title><strong>Annex</strong><br/>(informative)</title>
48
- <clause id="Q" inline-header="false" obligation="normative">
49
- <title>Annex A.1</title>
50
- <clause id="Q1" inline-header="false" obligation="normative">
51
- <title>Annex A.1a</title>
52
- </clause>
53
- <references id="Q2" normative="false">
54
- <title>Annex Bibliography</title>
55
- </references>
56
- </clause>
57
- </annex>
58
- <annex id="P1" inline-header="false" obligation="normative" displayorder='6'>
59
- </annex>
60
- <bibliography><references id="R" obligation="informative" normative="true" displayorder='3'>
61
- <title>Normative References</title>
62
- <bibitem id="R1"><docidentifier>R1</docidentifier><title>Hello</title></bibitem>
63
- </references><clause id="S" obligation="informative" displayorder='7'>
64
- <title>Bibliography</title>
65
- <references id="T" obligation="informative" normative="false">
66
- <title>Bibliography Subsection</title>
67
- </references>
68
- </clause>
69
- </bibliography>
70
- </iso-standard>
71
- INPUT
72
- mock_render
73
- IsoDoc::HtmlConvert.new({ sectionsplit: "true" })
74
- .convert("test", input, true)
75
- expect(File.exist?("test_collection/index.html")).to be true
76
- expect(File.exist?("test_collection/test.0.html")).to be true
77
- expect(File.exist?("test_collection/test.1.html")).to be true
78
- expect(File.exist?("test_collection/test.2.html")).to be true
79
- expect(File.exist?("test_collection/test.3.html")).to be false
80
- expect(File.exist?("test_collection/test.4.html")).to be true
81
- expect(File.exist?("test_collection/test.5.html")).to be true
82
- expect(File.exist?("test_collection/test.6.html")).to be true
83
- expect(File.exist?("test_collection/test.7.html")).to be true
84
- expect(File.exist?("test_collection/test.8.html")).to be false
85
- expect(File.exist?("test_files/cover.html")).to be true
86
- expect(File.exist?("test_files/test.0.xml")).to be true
87
- expect(File.exist?("test_files/test.1.xml")).to be true
88
- expect(File.exist?("test_files/test.2.xml")).to be true
89
- expect(File.exist?("test_files/test.3.xml")).to be true
90
- expect(File.exist?("test_files/test.4.xml")).to be true
91
- expect(File.exist?("test_files/test.5.xml")).to be true
92
- expect(File.exist?("test_files/test.6.xml")).to be true
93
- expect(File.exist?("test_files/test.7.xml")).to be true
94
- expect(File.exist?("test_files/test.8.xml")).to be false
95
- expect(File.exist?("test_files/test.html.yaml")).to be true
96
- m = /type="([^"]+)"/.match(File.read("test_files/test.0.xml"))
97
- file2 = Nokogiri::XML(File.read("test_files/test.2.xml"))
98
- expect(xmlpp(file2
99
- .at("//xmlns:eref[@bibitemid = '#{m[1]}_A']").to_xml))
100
- .to be_equivalent_to xmlpp(<<~OUTPUT)
101
- <eref bibitemid="#{m[1]}_A" type="#{m[1]}">HE<localityStack><locality type="anchor"><referenceFrom>A</referenceFrom></locality></localityStack></eref>
102
- OUTPUT
103
- expect(xmlpp(file2
104
- .at("//xmlns:eref[@bibitemid = '#{m[1]}_R1']").to_xml))
105
- .to be_equivalent_to xmlpp(<<~OUTPUT)
106
- <eref bibitemid="#{m[1]}_R1" type="#{m[1]}">SHE<localityStack><locality type="anchor"><referenceFrom>#{m[1]}_R1</referenceFrom></locality></localityStack></eref>
107
- OUTPUT
108
- expect(xmlpp(file2
109
- .at("//xmlns:bibitem[@id = '#{m[1]}_R1']").to_xml))
110
- .to be_equivalent_to xmlpp(<<~OUTPUT)
111
- <bibitem id="#{m[1]}_R1" type="internal">
112
- <docidentifier type="repository">#{m[1]}/R1</docidentifier>
113
- </bibitem>
114
- OUTPUT
115
- expect(xmlpp(file2
116
- .at("//xmlns:bibitem[@id = '#{m[1]}_A']").to_xml))
117
- .to be_equivalent_to xmlpp(<<~OUTPUT)
118
- <bibitem id="#{m[1]}_A" type="internal">
119
- <docidentifier type="repository">#{m[1]}/A</docidentifier>
120
- </bibitem>
121
- OUTPUT
122
- expect(xmlpp(file2
123
- .at("//xmlns:svgmap[1]").to_xml))
124
- .to be_equivalent_to xmlpp(<<~OUTPUT)
125
- <svgmap>
126
- <figure>
127
- <svg xmlns="http://www.w3.org/2000/svg">
128
- <a href="A">A</a>
129
- <a href="B">B</a>
130
- </svg>
131
- <target href="B"><eref bibitemid="#{m[1]}_R1" type="#{m[1]}"><localityStack><locality type="anchor"><referenceFrom>#{m[1]}_R1</referenceFrom></locality></localityStack></eref></target>
132
- </figure>
133
- <target href="A"><eref bibitemid="#{m[1]}_A" type="#{m[1]}"><localityStack><locality type="anchor"><referenceFrom>A</referenceFrom></locality></localityStack></eref></target><target href="B"><eref bibitemid="#{m[1]}_B" type="#{m[1]}"><localityStack><locality type="anchor"><referenceFrom>B</referenceFrom></locality></localityStack></eref></target></svgmap>
134
- OUTPUT
135
- expect(xmlpp(file2
136
- .at("//xmlns:svgmap[2]").to_xml))
137
- .to be_equivalent_to xmlpp(<<~OUTPUT)
138
- <svgmap><figure>
139
- <svg xmlns="http://www.w3.org/2000/svg">
140
- <a href="P">P</a>
141
- </svg>
142
- </figure><target href="P"><eref bibitemid="#{m[1]}_P" type="#{m[1]}"><localityStack><locality type="anchor"><referenceFrom>P</referenceFrom></locality></localityStack></eref></target></svgmap>
143
- OUTPUT
144
- expect(File.read("test_files/test.html.yaml")).to be_equivalent_to <<~OUTPUT
145
- ---
146
- directives:
147
- - presentation-xml
148
- - bare-after-first
149
- bibdata:
150
- title:
151
- type: title-main
152
- language: en
153
- content: ISO Title
154
- type: collection
155
- docid:
156
- type: ISO
157
- id: ISO 1
158
- manifest:
159
- level: collection
160
- title: Collection
161
- docref:
162
- - fileref: test.3.xml
163
- identifier: "[Untitled]"
164
- - fileref: test.0.xml
165
- identifier: abstract
166
- - fileref: test.1.xml
167
- identifier: introduction
168
- - fileref: test.6.xml
169
- identifier: Normative References
170
- - fileref: test.2.xml
171
- identifier: Clause 4
172
- - fileref: test.4.xml
173
- identifier: Annex (informative)
174
- - fileref: test.5.xml
175
- identifier: "[Untitled]"
176
- - fileref: test.7.xml
177
- identifier: Bibliography
178
- OUTPUT
179
- end
180
-
181
- private
182
-
183
- def mock_render
184
- original_add = ::Metanorma::CollectionRenderer.method(:render)
185
- allow(::Metanorma::CollectionRenderer)
186
- .to receive(:render) do |col, opts|
187
- original_add.call(col, opts.merge(compile: { no_install_fonts: true }))
188
- end
189
- end
190
- end