camdict 1.0.3 → 2.0.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 +4 -4
- data/README.md +28 -33
- data/lib/camdict/array_ext.rb +37 -0
- data/lib/camdict/client.rb +133 -97
- data/lib/camdict/common.rb +25 -143
- data/lib/camdict/definition.rb +65 -596
- data/lib/camdict/entry.rb +76 -0
- data/lib/camdict/exception.rb +5 -0
- data/lib/camdict/explanation.rb +29 -66
- data/lib/camdict/http_client.rb +14 -10
- data/lib/camdict/ipa.rb +52 -0
- data/lib/camdict/pronunciation.rb +53 -0
- data/lib/camdict/sentence.rb +38 -0
- data/lib/camdict/string_ext.rb +141 -0
- data/lib/camdict/word.rb +83 -17
- data/test/debug.rb +60 -0
- data/test/helper.rb +2 -0
- data/test/itest_client.rb +39 -8
- data/test/itest_definition.rb +24 -75
- data/test/itest_entry.rb +37 -0
- data/test/itest_explanation.rb +41 -20
- data/test/itest_ipa.rb +105 -0
- data/test/itest_pronunciation.rb +74 -0
- data/test/itest_word.rb +49 -0
- data/test/test_array_ext.rb +23 -0
- data/test/test_client.rb +35 -42
- data/test/test_common.rb +22 -78
- data/test/test_explanation.rb +21 -25
- data/test/test_http_client.rb +27 -13
- data/test/test_string_ext.rb +95 -0
- metadata +42 -7
- data/test/test_definition.rb +0 -345
data/test/itest_ipa.rb
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require_relative 'helper'
|
3
|
+
|
4
|
+
module Camdict
|
5
|
+
class IPAiTest < Minitest::Test
|
6
|
+
def test_imaginary
|
7
|
+
ipa_test(imaginary)
|
8
|
+
end
|
9
|
+
|
10
|
+
# derived word
|
11
|
+
def test_plagiarism
|
12
|
+
ipa_test(plagiarism)
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_aluminum
|
16
|
+
skip 'words are both in British & American dictionary, and on two pages'
|
17
|
+
ipa_test(aluminum)
|
18
|
+
end
|
19
|
+
|
20
|
+
# two .headword
|
21
|
+
def test_sled
|
22
|
+
ipa_test(sled)
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_no_us_ipa
|
26
|
+
ipa_test(match)
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def ipa_assert(e, a)
|
32
|
+
uk, us, actk, acts = a
|
33
|
+
assert_equal e[:uk_utf8], uk, "#{e[:word]} uk ipa got a problem"
|
34
|
+
assert_equal e[:us_utf8], us, "#{e[:word]} us ipa got a problem"
|
35
|
+
assert_equal e[:uk_inx], actk, "#{e[:word]} uk superscript index issue"
|
36
|
+
assert_equal e[:us_inx], acts, "#{e[:word]} us superscript index issue"
|
37
|
+
end
|
38
|
+
|
39
|
+
def ipa_test(d)
|
40
|
+
defi = definition(d)
|
41
|
+
uk = ipa_hexes(defi, :uk)
|
42
|
+
us = ipa_hexes(defi, :us)
|
43
|
+
actual = [uk, us, defi.ipa.k, defi.ipa.s]
|
44
|
+
ipa_assert(d, actual)
|
45
|
+
end
|
46
|
+
|
47
|
+
def definition(d)
|
48
|
+
Camdict::Word.new(d[:word]).definition
|
49
|
+
end
|
50
|
+
|
51
|
+
def ipa_hexes(defi, region)
|
52
|
+
defi.ipa.send(region)&.unpack('U*')&.map { |n| n.to_s 16 }
|
53
|
+
end
|
54
|
+
|
55
|
+
def match
|
56
|
+
{
|
57
|
+
word: 'match',
|
58
|
+
uk_utf8: %w(6d e6 74 283),
|
59
|
+
us_utf8: nil,
|
60
|
+
uk_inx: nil,
|
61
|
+
us_inx: nil
|
62
|
+
}
|
63
|
+
end
|
64
|
+
|
65
|
+
def imaginary
|
66
|
+
{
|
67
|
+
word: 'imaginary',
|
68
|
+
uk_utf8: %w(26a 2c8 6d e6 64 292 2e 26a 2e 6e 259 72 2e 69),
|
69
|
+
us_utf8: %w(26a 2c8 6d e6 64 292 2e 259 2e 6e 65 72 2e 69),
|
70
|
+
uk_inx: [10, 1],
|
71
|
+
us_inx: nil
|
72
|
+
}
|
73
|
+
end
|
74
|
+
|
75
|
+
def plagiarism
|
76
|
+
{
|
77
|
+
word: 'plagiarism',
|
78
|
+
uk_utf8: %w(2c8 70 6c 65 26a 2e 64 292 259 72 2e 26a 2e 7a 259 6d),
|
79
|
+
us_utf8: %w(2c8 70 6c 65 26a 2e 64 292 25a 2e 26a 2e 7a 259 6d),
|
80
|
+
uk_inx: [8, 1, 14, 1],
|
81
|
+
us_inx: [13, 1]
|
82
|
+
}
|
83
|
+
end
|
84
|
+
|
85
|
+
def aluminum
|
86
|
+
{
|
87
|
+
word: 'aluminum',
|
88
|
+
uk_utf8: %w(259 2c8 6c 75 2d0 2e 6d 26a 2e 6e 259 6d),
|
89
|
+
us_utf8: %w(259 2c8 6c 75 2d0 2e 6d 26a 2e 6e 259 6d),
|
90
|
+
uk_inx: nil,
|
91
|
+
us_inx: nil
|
92
|
+
}
|
93
|
+
end
|
94
|
+
|
95
|
+
def sled
|
96
|
+
{
|
97
|
+
word: 'sled',
|
98
|
+
uk_utf8: %w(73 6c 65 64),
|
99
|
+
us_utf8: %w(73 6c 65 64),
|
100
|
+
uk_inx: nil,
|
101
|
+
us_inx: nil
|
102
|
+
}
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require_relative 'helper'
|
3
|
+
|
4
|
+
module Camdict
|
5
|
+
class PronunciationiTest < Minitest::Test
|
6
|
+
def test_uk_pronunciation
|
7
|
+
pron = get_pron('understand')
|
8
|
+
assert_equal uk_mp3, pron.uk.mp3
|
9
|
+
assert_equal uk_ogg, pron.uk.ogg
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_us_pronunciation
|
13
|
+
pron = get_pron('understand')
|
14
|
+
assert_equal us_mp3, pron.us.mp3
|
15
|
+
assert_equal us_ogg, pron.us.ogg
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_derived_uk
|
19
|
+
pron = get_pron('harmfully')
|
20
|
+
assert_equal harm_uk_mp3, pron.uk.mp3
|
21
|
+
assert_equal harm_uk_ogg, pron.uk.ogg
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_derived_us
|
25
|
+
pron = get_pron('harmfully')
|
26
|
+
assert_equal harm_us_mp3, pron.us.mp3
|
27
|
+
assert_equal harm_us_ogg, pron.us.ogg
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def get_pron(word)
|
33
|
+
defs = Camdict::Client.new.html_definition(word)
|
34
|
+
d = Camdict::Definition.new(word)
|
35
|
+
d.send :get_pronunciation, defs
|
36
|
+
end
|
37
|
+
|
38
|
+
def media
|
39
|
+
'http://dictionary.cambridge.org/media/english/'
|
40
|
+
end
|
41
|
+
|
42
|
+
def uk_mp3
|
43
|
+
media + 'uk_pron/u/uku/ukund/ukunder112.mp3'
|
44
|
+
end
|
45
|
+
|
46
|
+
def uk_ogg
|
47
|
+
media + 'uk_pron_ogg/u/uku/ukund/ukunder112.ogg'
|
48
|
+
end
|
49
|
+
|
50
|
+
def us_mp3
|
51
|
+
media + 'us_pron/u/und/under/understand.mp3'
|
52
|
+
end
|
53
|
+
|
54
|
+
def us_ogg
|
55
|
+
media + 'us_pron_ogg/u/und/under/understand.ogg'
|
56
|
+
end
|
57
|
+
|
58
|
+
def harm_uk_mp3
|
59
|
+
media + 'uk_pron/u/ukh/ukhar/ukhardw017.mp3'
|
60
|
+
end
|
61
|
+
|
62
|
+
def harm_uk_ogg
|
63
|
+
media + 'uk_pron_ogg/u/ukh/ukhar/ukhardw017.ogg'
|
64
|
+
end
|
65
|
+
|
66
|
+
def harm_us_mp3
|
67
|
+
media + 'us_pron/u/ush/ushan/ushangd027.mp3'
|
68
|
+
end
|
69
|
+
|
70
|
+
def harm_us_ogg
|
71
|
+
media + 'us_pron_ogg/u/ush/ushan/ushangd027.ogg'
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
data/test/itest_word.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require_relative 'helper'
|
3
|
+
|
4
|
+
module Camdict
|
5
|
+
class WordiTest < Minitest::Test
|
6
|
+
def setup
|
7
|
+
@film = Camdict::Word.new('film')
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_definitions
|
11
|
+
assert @film.definitions
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_raw_definition
|
15
|
+
refute @film.raw_definition.empty?
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_ipa
|
19
|
+
assert_equal 'fɪlm', @film.ipa
|
20
|
+
assert_equal 'fɪlm', @film.ipa(:us)
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_meaning
|
24
|
+
m = 'a series of moving pictures, usually shown in a cinema or on' \
|
25
|
+
' television and often telling a story: '
|
26
|
+
assert_equal m, @film.meaning
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_meanings
|
30
|
+
m = 'to record moving pictures with a camera, usually to make a film' \
|
31
|
+
' for television or the cinema: '
|
32
|
+
assert_equal m, @film.meanings.last
|
33
|
+
assert_equal 4, @film.meanings.size
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_pronunciation
|
37
|
+
uk_mp3 = 'http://dictionary.cambridge.org/media/english/uk_pron/u/ukf/' \
|
38
|
+
'ukfil/ukfill_007.mp3'
|
39
|
+
us_mp3 = 'http://dictionary.cambridge.org/media/english/us_pron/f/fil/' \
|
40
|
+
'film_/film.mp3'
|
41
|
+
assert_equal uk_mp3, @film.pronunciation
|
42
|
+
assert_equal us_mp3, @film.pronunciation(:us)
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_part_of_speech
|
46
|
+
assert_equal %w(noun verb), @film.part_of_speech
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require_relative 'helper'
|
3
|
+
require 'camdict/array_ext'
|
4
|
+
|
5
|
+
module Camdict
|
6
|
+
class ArrayExtTest < Minitest::Test
|
7
|
+
using Camdict::ArrayExt
|
8
|
+
|
9
|
+
def test_expand
|
10
|
+
phra = ['blow your nose', 'blow a kiss to/at sb']
|
11
|
+
expected = ['blow your nose', 'blow a kiss to sb', 'blow a kiss at sb']
|
12
|
+
assert_equal expected, phra.expand
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_has?
|
16
|
+
phra = ['blow your nose', 'blow a kiss to/at sb']
|
17
|
+
assert phra.has? 'blow your nose'
|
18
|
+
assert phra.has? 'blow a kiss to sb'
|
19
|
+
assert phra.has? 'a kiss to sb'
|
20
|
+
assert phra.has? 'kiss at sb'
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/test/test_client.rb
CHANGED
@@ -1,72 +1,65 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require 'minitest/autorun'
|
2
3
|
require 'camdict'
|
3
4
|
|
4
5
|
module Camdict
|
5
6
|
RESULTLIST = <<EoHTM
|
6
|
-
<ul class="
|
7
|
-
<li><a href="http://dictionary.cambridge.org/dictionary/
|
8
|
-
<li><a href="http://dictionary.cambridge.org/dictionary/
|
9
|
-
<li><a href="http://dictionary.cambridge.org/dictionary/british/stress-related" title="Definition of stress-related adjective in British English"><span class='arl2'><span class="base"><b class="hw">stress-related</b></span> <span title="A word that describes a noun or pronoun." class="pos">adjective</span></span></a></li>
|
7
|
+
<ul class="prefix-block">
|
8
|
+
<li><a href="http://dictionary.cambridge.org/dictionary/english/related" title="related definition in English"><span class='arl1'><span class="base"><b class="hw">related</b></span></a></li>
|
9
|
+
<li><a href="http://dictionary.cambridge.org/dictionary/english/relate" title="relate definition in English"><span class='arl1'><span class="base"><b class="hw">relate</b></span></a></li>
|
10
10
|
</ul>
|
11
11
|
EoHTM
|
12
12
|
|
13
13
|
class ClientTest < MiniTest::Test
|
14
|
+
def setup
|
15
|
+
@client = Camdict::Client.new
|
16
|
+
end
|
14
17
|
|
15
18
|
def test_new
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
assert c.instance_eval { @dictionary == "american-english" }
|
19
|
+
assert @client.instance_eval { @dictionary == 'english' }
|
20
|
+
c = Camdict::Client.new('english-chinese-simplified')
|
21
|
+
assert_equal 'english-chinese-simplified', c.dictionary
|
20
22
|
end
|
21
23
|
|
22
24
|
def test_single_def?
|
23
|
-
c = Camdict::Client.new
|
24
25
|
html = '<div class="di-head"> <div class="di-title"> <h1 class="hw">'
|
25
|
-
assert
|
26
|
-
assert
|
26
|
+
assert @client.send :single_def?, Nokogiri::HTML(html)
|
27
|
+
assert @client.send :definition_page?, Nokogiri::HTML(html)
|
27
28
|
end
|
28
|
-
|
29
|
+
|
29
30
|
def test_entry_id
|
30
|
-
|
31
|
-
|
32
|
-
assert_equal "related_1", c.send( :entry_id, url)
|
31
|
+
url = 'http://dictionary.cambridge.org/british/related'
|
32
|
+
assert_equal 'related', @client.send(:entry_id, url)
|
33
33
|
end
|
34
34
|
|
35
35
|
def test_matched_word?
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
assert
|
41
|
-
assert
|
42
|
-
assert
|
43
|
-
assert (c.send :matched_word?, "knock about", Nokogiri::HTML(html2))
|
36
|
+
html = '<li><span class="base"><b class="hw">related</b></span></li>'
|
37
|
+
html1 = '<li><span class="base"><b class="hw">stress-related'
|
38
|
+
html2 = '<span class="base">knock around/about'
|
39
|
+
assert @client.send :matched_word?, 'related', Nokogiri::HTML(html)
|
40
|
+
assert !(@client.send :matched_word?, 'related', Nokogiri::HTML(html1))
|
41
|
+
assert @client.send :matched_word?, 'knock around', Nokogiri::HTML(html2)
|
42
|
+
assert @client.send :matched_word?, 'knock about', Nokogiri::HTML(html2)
|
44
43
|
end
|
45
44
|
|
46
45
|
def test_mentry_links
|
47
|
-
|
48
|
-
|
49
|
-
expected_result = %w(related_1 related_2).map { |r|
|
50
|
-
rurl + r
|
51
|
-
}
|
46
|
+
rurl = 'http://dictionary.cambridge.org/dictionary/english'
|
47
|
+
expected_result = "#{rurl}/related"
|
52
48
|
result_list = Nokogiri::HTML(RESULTLIST)
|
53
|
-
links =
|
54
|
-
|
49
|
+
links = @client.send(:mentry_links, 'related', result_list).first
|
50
|
+
assert_equal expected_result, links
|
55
51
|
end
|
56
52
|
|
57
|
-
def
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
c = Camdict::Client.new
|
63
|
-
htmla = %q(<div class="di-head">)
|
64
|
-
htmlb = '<h2 class="di-title cdo-section-title-hw">aluminium</h2>' +
|
65
|
-
'<span class="di-info"><span class="pos">noun</span></span>'
|
66
|
-
result = c.send :di_head, Nokogiri::HTML(htmla+htmlb)
|
67
|
-
assert_equal(htmlb, result)
|
53
|
+
def test_di_body
|
54
|
+
html = '<div data-tab="ds-british">' \
|
55
|
+
'<div class="di-body"><div class="pos-header"/><div class="pos-body">'\
|
56
|
+
'</div></div>'
|
57
|
+
assert @client.send :di_body, Nokogiri::HTML(html)
|
68
58
|
end
|
69
59
|
|
60
|
+
def test_encode
|
61
|
+
assert_equal 'time-zone', @client.send(:encode, 'time zone')
|
62
|
+
assert_equal 'time-s-up', @client.send(:encode, "time's up")
|
63
|
+
end
|
70
64
|
end
|
71
|
-
|
72
65
|
end
|
data/test/test_common.rb
CHANGED
@@ -1,93 +1,37 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require_relative 'helper'
|
3
3
|
|
4
4
|
module Camdict
|
5
5
|
class CommonTest < Minitest::Test
|
6
6
|
include Camdict::Common
|
7
7
|
|
8
|
-
def test_flatten
|
9
|
-
str = "blow a kiss to/at sb"
|
10
|
-
expected = ['blow a kiss to sb', 'blow a kiss at sb']
|
11
|
-
assert_equal expected, str.flatten
|
12
|
-
str = "blow/blew a kiss"
|
13
|
-
expected = ['blow a kiss', 'blew a kiss']
|
14
|
-
assert_equal expected, str.flatten
|
15
|
-
str = "knock around/about"
|
16
|
-
expected = ['knock around', 'knock about']
|
17
|
-
assert_equal expected, str.flatten
|
18
|
-
str = "not give/budge/move an inch"
|
19
|
-
expected = ['not give an inch', 'not budge an inch', 'not move an inch']
|
20
|
-
assert_equal expected, str.flatten
|
21
|
-
str = "fall into the/sb's trap"
|
22
|
-
expected = ['fall into the trap', 'fall into sb\'s trap']
|
23
|
-
assert_equal expected, str.flatten
|
24
|
-
str = "what is sb/sth?"
|
25
|
-
expected = ['what is sb?', 'what is sth?']
|
26
|
-
assert_equal expected, str.flatten
|
27
|
-
str = "look lively/sharp!"
|
28
|
-
expected = ['look lively!', 'look sharp!']
|
29
|
-
assert_equal expected, str.flatten
|
30
|
-
str = "the like of sb/sth; sb's/sth's like"
|
31
|
-
expected = ['the like of sb', 'the like of sth',
|
32
|
-
"sb's like", "sth's like"]
|
33
|
-
assert_equal expected, str.flatten
|
34
|
-
str = "go (like/down) a bomb"
|
35
|
-
expected = ['go a bomb', 'go like a bomb', 'go down a bomb']
|
36
|
-
assert_equal expected, str.flatten
|
37
|
-
str = "the other side/end (of sth)"
|
38
|
-
expected = ['the other side', 'the other end', 'the other side of sth',
|
39
|
-
'the other end of sth']
|
40
|
-
assert_equal expected, str.flatten
|
41
|
-
strs = ["20/20 vision", "public enemy number one/no. 1"]
|
42
|
-
# todo:
|
43
|
-
# "20/20 vision".flatten => "20/20 vision" no change expected
|
44
|
-
# public enemy number one/no. 1 =>
|
45
|
-
# public enemy number one
|
46
|
-
# public enemy no. 1
|
47
|
-
str = "the more...the more/less"
|
48
|
-
expected = ['the more...the more', 'the more...the less']
|
49
|
-
assert_equal expected, str.flatten
|
50
|
-
# need more examples to support complex 'or' separators
|
51
|
-
# sound like/as if/as though
|
52
|
-
# look on/upon sb/sth as sth
|
53
|
-
# look at/see sth through rose-coloured/tinted glasses
|
54
|
-
# give /quote sth/sb chapter and verse
|
55
|
-
end
|
56
|
-
|
57
|
-
def test_expand
|
58
|
-
phra = ['blow your nose', 'blow a kiss to/at sb']
|
59
|
-
expected = ['blow your nose', 'blow a kiss to sb', 'blow a kiss at sb']
|
60
|
-
assert_equal expected, phra.expand
|
61
|
-
end
|
62
|
-
|
63
|
-
def test_has?
|
64
|
-
phra = ['blow your nose', 'blow a kiss to/at sb']
|
65
|
-
assert phra.has? "blow your nose"
|
66
|
-
assert phra.has? "blow a kiss to sb"
|
67
|
-
assert phra.has? "a kiss to sb"
|
68
|
-
assert phra.has? "kiss at sb"
|
69
|
-
assert "blow your nose".has?('nose')
|
70
|
-
assert ! phra[1].flatten.has?(phra[0])
|
71
|
-
end
|
72
|
-
|
73
8
|
def test_phrase_css
|
74
|
-
meaning = 'to have problems or be in difficult situation:'
|
75
|
-
sentence = 'a ship is in difficluties off the coast of Ireland.'
|
76
|
-
html = '<span class="phrase-block">' +
|
77
|
-
'<span class="phrase">be in difficulties</span>' +
|
78
|
-
'<span class="v" title="Variant form">be in difficulty</span>' +
|
79
|
-
'<span class="phrase-body">' +
|
80
|
-
"<span class='def-block'><span class='def'>#{meaning}</span>" +
|
81
|
-
"<span class='examp'><span class='eg'>#{sentence}</span></span>"
|
82
|
-
@html = Nokogiri::HTML html
|
83
9
|
@word = 'be in difficulty'
|
84
10
|
ret = ''
|
85
|
-
phrase_css(
|
11
|
+
phrase_css(Nokogiri::HTML(html), '.def-block') do |node|
|
86
12
|
ret = Camdict::Explanation.new(node)
|
87
|
-
|
13
|
+
end
|
88
14
|
assert_equal sentence, ret.examples.first.sentence
|
89
15
|
assert_equal meaning, ret.meaning
|
90
16
|
end
|
91
17
|
|
18
|
+
private
|
19
|
+
|
20
|
+
def meaning
|
21
|
+
'to have problems or be in difficult situation:'
|
22
|
+
end
|
23
|
+
|
24
|
+
def sentence
|
25
|
+
'a ship is in difficluties off the coast of Ireland.'
|
26
|
+
end
|
27
|
+
|
28
|
+
def html
|
29
|
+
'<span class="phrase-block">' \
|
30
|
+
'<span class="phrase">be in difficulties</span>' \
|
31
|
+
'<span class="v" title="Variant form">be in difficulty</span>' \
|
32
|
+
'<span class="phrase-body">' \
|
33
|
+
"<span class='def-block'><span class='def'>#{meaning}</span>" \
|
34
|
+
"<span class='examp'><span class='eg'>#{sentence}</span></span>"
|
35
|
+
end
|
92
36
|
end
|
93
37
|
end
|