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.
data/lib/camdict/word.rb CHANGED
@@ -1,36 +1,102 @@
1
+ # frozen_string_literal: true
1
2
  require 'camdict/client'
2
3
  require 'camdict/definition'
3
4
 
4
5
  module Camdict
5
- # Get all definitions data about a word or phrase including IPAs,
6
- # pronunciations, usage sentences, etc. from Camdict Client.
6
+ # Get all definitions data about a word or phrase including IPAs,
7
+ # pronunciations, usage sentences, etc. from Cambridge dictionary.
7
8
  class Word
8
-
9
9
  # New a +word+ or phrase, default +dictionary+ is british.
10
- def initialize(word, dictionary=nil)
11
- @word ||= word
10
+ def initialize(word, dictionary = nil)
11
+ @word = word
12
12
  @dictionary = dictionary
13
- @raw_definitions = [] # each element is a hash
14
- @definitions = [] # each element is a Definition object
13
+ end
14
+
15
+ def part_of_speech
16
+ s = definition.senses.map(&:part_of_speech).uniq
17
+ return s.first if s.count < 2
18
+ s
19
+ end
20
+
21
+ def pronunciation(region = :uk)
22
+ p = definition.pronunciation.send(region)
23
+ p.mp3 || p.ogg
24
+ end
25
+
26
+ def ipa(region = :uk)
27
+ definition.ipa.send(region)
28
+ end
29
+
30
+ def meaning
31
+ definition.senses.first.explanations.first.meaning
32
+ end
33
+
34
+ def meanings
35
+ definition.senses.map { |s| s.explanations.map(&:meaning) }.flatten
36
+ end
37
+
38
+ # show all important dictionary information, returns
39
+ # { meaning: [{ pos: '', category: '',
40
+ # sense: [{ meaning:, eg: [], level: '', code: '', synonym: '',
41
+ # opposite: '', usage: '', region: ''}] }]
42
+ # ipa: '' | { uk: , us: },
43
+ # pronunciation: { uk: mp3|ogg, us: mp3|ogg }
44
+ # }
45
+ def show
46
+ {
47
+ meaning: meanings_json,
48
+ ipa: ipa_json,
49
+ pronunciation: { uk: pronunciation, us: pronunciation(:us) }
50
+ }
51
+ end
52
+
53
+ def print
54
+ require 'pp'
55
+ pp show
15
56
  end
16
57
 
17
58
  # Get all definitions for this word from remote online dictionary
18
59
  def definitions
19
- client = Camdict::Client.new(@dictionary)
20
- @raw_definitions = client.html_definition(@word)
21
- if found?
22
- @definitions = @raw_definitions.map { |r|
23
- Camdict::Definition.new(@word, r)
60
+ @definitions ||= g_definitions
61
+ end
62
+
63
+ def raw_definition
64
+ @raw_definition ||= retrieve.to_html(save_with: 0)
65
+ end
66
+
67
+ alias pos part_of_speech
68
+ alias definition definitions
69
+
70
+ private
71
+
72
+ def retrieve
73
+ @retrieved ||= Camdict::Client.new(@dictionary).html_definition(@word)
74
+ end
75
+
76
+ def g_definitions
77
+ Camdict::Definition.new(@word).parse(retrieve)
78
+ end
79
+
80
+ def meanings_json
81
+ definition.senses.map do |s|
82
+ {
83
+ pos: s.part_of_speech, category: s.category,
84
+ sense: s.explanations.map do |e|
85
+ { meaning: e.meaning, eg: e.examples&.map(&:sentence) }
86
+ .merge(optional_meaning_items(e))
87
+ end
24
88
  }
25
89
  end
26
90
  end
27
91
 
28
- # Found in the diciontary? Return number of found entries
29
- def found?
30
- @raw_definitions.size
92
+ def ipa_json
93
+ ipa(:uk) == ipa(:us) ? ipa : { uk: ipa(:uk), us: ipa(:us) }
31
94
  end
32
95
 
33
- alias in? found?
34
-
96
+ def optional_meaning_items(exp)
97
+ %w(level code synonym opposite usage region).inject({}) do |ret, o|
98
+ exp.public_send(o) ? ret.merge({ o => exp.public_send(o) }) : ret
99
+ end
100
+ end
35
101
  end
36
102
  end
data/test/debug.rb ADDED
@@ -0,0 +1,60 @@
1
+ require_relative 'helper'
2
+
3
+ module Camdict
4
+ # test in a way that how camdict is working, so that remote changes can
5
+ # be found quickly, especially for css class changes.
6
+ class Debug < Minitest::Test
7
+ def setup
8
+ @word = ARGV[0]
9
+ check_input
10
+ @wordict = Camdict::Word.new(@word)
11
+ @client = Camdict::Client.new
12
+ $cache ||= {}
13
+ end
14
+
15
+ def test_search
16
+ assert @client.send :fetch, @word
17
+ end
18
+
19
+ def test_word_page
20
+ assert @client.send :single_def?, word_page
21
+ end
22
+
23
+ def test_british_tab
24
+ end
25
+
26
+ def test_where
27
+ where = definations.send(:where, word_content)
28
+ print 'where=', where
29
+ refute_equal 'unknown', where
30
+ end
31
+
32
+ def test_ipa
33
+ definations
34
+ end
35
+
36
+ def test_print
37
+ puts
38
+ @wordict.print
39
+ end
40
+
41
+ private
42
+
43
+ def check_input
44
+ @word || abort('please specify a word on command line')
45
+ end
46
+
47
+ def definations
48
+ $cache[:definitions] ||=
49
+ Camdict::Definition.new(@word).parse(word_content)
50
+ end
51
+
52
+ def word_content
53
+ $cache[:word_content] ||= @client.send(:di_extracted, word_page)
54
+ end
55
+
56
+ def word_page
57
+ $cache[:word_page] ||= @client.get_html(@client.word_url(@word))
58
+ end
59
+ end
60
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,2 @@
1
+ require 'minitest/autorun'
2
+ require 'camdict'
data/test/itest_client.rb CHANGED
@@ -1,20 +1,51 @@
1
+ # frozen_string_literal: true
1
2
  require 'minitest/autorun'
2
3
  require 'camdict'
3
4
 
4
5
  module Camdict
5
6
  class ClientiTest < Minitest::Test
7
+ def setup
8
+ @client = Camdict::Client.new
9
+ @imaginary = @client.word_url('imaginary')
10
+ end
11
+
6
12
  def test_fetch
7
- c = Camdict::Client.new
8
- result = c.send :fetch, "pppppp"
9
- assert ! result
13
+ assert !@client.send(:fetch, 'pppppp')
14
+ assert @client.send(:fetch, 'mind')
15
+ end
16
+
17
+ def test_single_def?
18
+ html = @client.get_html(@imaginary)
19
+ assert @client.send :single_def?, html
20
+ end
21
+
22
+ def test_mentry_links
23
+ related_html = @client.get_html(@client.search_url('related'))
24
+ related_links = @client.send :mentry_links, 'related', related_html
25
+ assert_equal 1, related_links.size
26
+ end
27
+
28
+ def test_matched_word?
29
+ mind_url = @client.search_url('mind')
30
+ mind_node = @client.get_html(mind_url).css('.prefix-item').first
31
+ assert @client.send :matched_word?, 'mind', mind_node
32
+ end
33
+
34
+ def test_di_extracted
35
+ html = @client.get_html(@imaginary)
36
+ r = @client.send :di_extracted, html
37
+ assert r.css('.cdo-section-title-hw')
38
+ assert r.css('.pron-info')
39
+ end
40
+
41
+ def test_di_body
42
+ html = @client.get_html(@imaginary)
43
+ assert @client.send :di_body, html
10
44
  end
11
45
 
12
46
  def test_html_definition
13
- c = Camdict::Client.new
14
- search_result = c.html_definition("related")
15
- r = search_result.collect {|r| r.keys}
16
- assert_equal ["related_1", "related_2"], r.flatten
47
+ search_result = @client.html_definition('related')
48
+ assert search_result.first
17
49
  end
18
50
  end
19
51
  end
20
-
@@ -1,90 +1,39 @@
1
- require 'minitest/autorun'
2
- require 'camdict'
1
+ # frozen_string_literal: true
2
+ require_relative 'helper'
3
3
 
4
4
  module Camdict
5
5
  class DefinitioniTest < Minitest::Test
6
-
7
6
  def test_part_of_speech
8
- data = {'aluminium' => 'noun', 'aluminum' => 'noun',
9
- 'look at sth' => 'phrasal verb', 'plagiarist' => 'noun',
10
- 'pass water' => 'idiom', 'ruby' => 'noun'}
11
- # adjective for ruby exists in British dictionary
12
- data.each_pair { |word, exp_result|
7
+ pos_data.each_pair do |word, exp_result|
13
8
  w = Camdict::Word.new(word)
14
- defa = w.definitions
15
- defo = defa.pop
16
- assert_equal exp_result, defo.part_of_speech
17
- }
9
+ assert_equal exp_result, w.part_of_speech
10
+ end
11
+ end
12
+
13
+ def test_pos
18
14
  w = Camdict::Word.new('correct')
19
- defa = w.definitions
20
- assert_equal 'adjective', defa[0].part_of_speech
21
- assert_equal 'verb', defa[1].part_of_speech
15
+ assert_equal %w(adjective verb), w.pos
22
16
  end
23
17
 
24
- def test_explanations
25
- w = Camdict::Word.new('pass water')
26
- defa = w.definitions
27
- expl = defa[0].explanations.first
28
- assert_equal "polite expression for urinate", expl.meaning
18
+ def test_region_in_block
19
+ skip 'word in block'
20
+ w = Camdict::Word.new('rubbers')
21
+ assert_equal 'US', w.region
29
22
  end
30
23
 
31
- def test_ipa
32
- imaginary = {
33
- :word => "imaginary",
34
- :uk_utf8 => %w(26a 2c8 6d e6 64 292 2e 26a 2e 6e 259 72 2e 69),
35
- :us_utf8 => %w(26a 2c8 6d e6 64 292 2e 259 2e 6e 65 72 2e 69),
36
- :uk_inx => [10,1],
37
- :us_inx => nil,
38
- :which => 0
39
- }
40
- plagiarism = {
41
- :word => "plagiarism",
42
- :uk_utf8 => %w(2c8 70 6c 65 26a 2e 64 292 259 72 2e 26a 2e 7a 259 6d),
43
- :us_utf8 => %w(2c8 70 6c 65 26a 2e 64 292 25a 2e 26a 2e 7a 259 6d),
44
- :uk_inx => [8,1,14,1],
45
- :us_inx => [13,1],
46
- :which => 0
47
- }
48
- aluminum = {
49
- :word => "aluminum",
50
- :uk_utf8 => %w(259 2c8 6c 75 2d0 2e 6d 26a 2e 6e 259 6d),
51
- :us_utf8 => %w(259 2c8 6c 75 2d0 2e 6d 26a 2e 6e 259 6d),
52
- :uk_inx => nil,
53
- :us_inx => nil,
54
- :which => 0
55
- }
56
- sled = {
57
- :word => "sled",
58
- :uk_utf8 => nil,
59
- :us_utf8 => nil,
60
- :uk_inx => nil,
61
- :us_inx => nil,
62
- :which => 1
63
- }
64
- data = [imaginary, plagiarism, aluminum, sled]
65
- data.each { |d|
66
- w = Camdict::Word.new(d[:word])
67
- defa = w.definitions
68
- defo = defa[d[:which]]
69
- uk = defo.ipa.uk
70
- us = defo.ipa.us
71
- uk = uk.unpack('U*').map { |n| n.to_s 16 } if uk
72
- us = us.unpack('U*').map { |n| n.to_s 16 } if us
73
- actk = defo.ipa.k
74
- acts = defo.ipa.s
75
- assert_equal d[:uk_utf8], uk, "#{d[:word]} uk ipa got a problem"
76
- assert_equal d[:us_utf8], us, "#{d[:word]} us ipa got a problem"
77
- assert_equal d[:uk_inx], actk, "#{d[:word]} uk superscript index issue"
78
- assert_equal d[:us_inx], acts, "#{d[:word]} us superscript index issue"
79
- }
24
+ def test_meaning
25
+ skip 'phrase'
26
+ w = Camdict::Word.new('pass water')
27
+ expl = w.definition.senses.first.explanations.first
28
+ assert_equal 'polite expression for urinate', expl.meaning
80
29
  end
81
30
 
82
- def test_region
83
- w = Camdict::Word.new('rubbers')
84
- defa = w.definitions
85
- actual = defa[0].region
86
- assert_equal "US", actual
31
+ def pos_data
32
+ # 'aluminum' => 'noun', US variant ought to be got from American tab
33
+ { 'aluminium' => 'noun',
34
+ 'plagiarist' => 'noun',
35
+ 'ruby' => 'noun' }
36
+ # adjective for ruby exists in British dictionary
87
37
  end
88
-
89
38
  end
90
39
  end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+ require_relative 'helper'
3
+
4
+ module Camdict
5
+ class EntryiTest < Minitest::Test
6
+ def setup
7
+ fly_e = Camdict::Client.new.html_definition('fly')
8
+ .css('.entry-body__el').first
9
+ @senses = Camdict::Definition.new('fly').send(:get_senses, fly_e)
10
+ end
11
+
12
+ def test_senses
13
+ assert_equal 4, @senses.size
14
+ end
15
+
16
+ def test_meaning
17
+ expect = 'When a bird, insect, or aircraft flies, it moves through ' \
18
+ 'the air: '
19
+ assert_equal expect, @senses.first.explanations.first.meaning
20
+ end
21
+
22
+ def test_part_of_speech
23
+ assert_equal 'verb', @senses.first.part_of_speech
24
+ end
25
+
26
+ def test_category
27
+ assert_equal 'TRAVEL', @senses.first.category
28
+ end
29
+
30
+ def test_derived_pos
31
+ html = Camdict::Client.new.html_definition('plagiarism')
32
+ .css('.entry-body__el')
33
+ senses = Camdict::Definition.new('plagiarism').send(:get_senses, html)
34
+ assert_equal 'noun', senses.first.part_of_speech
35
+ end
36
+ end
37
+ end
@@ -1,35 +1,56 @@
1
- require 'minitest/autorun'
2
- require 'camdict'
1
+ # frozen_string_literal: true
2
+ require_relative 'helper'
3
3
 
4
4
  module Camdict
5
5
  class ExplanationiTest < Minitest::Test
6
- def test_explanations
7
- w = Camdict::Word.new('correct')
8
- defa = w.definitions
9
- def1 = defa.first #first is adjective
10
- e1 = def1.explanations.first
11
- #todo: level info is not in english-chinese-simplied dictionary
12
- #assert_equal "A2", e1.level
13
- #assert_equal "B2", defa.last.explanations.first.level
14
- assert_equal "I've got thirty exam papers to correct.",
15
- defa.last.explanations.first.examples.last.sentence
16
- w = Camdict::Word.new('correctly')
17
- defa = w.definitions
18
- def1 = defa.first #first is adjective
19
- e1 = def1.explanations
20
- assert_equal "Have I pronounced your name correctly?",
21
- e1[2].examples[0].sentence
22
- #assert_equal "B1", e1[2].level
6
+ def test_level
7
+ assert_equal 'B2', sense(:last).explanations.first.level
8
+ end
9
+
10
+ def test_sentence
11
+ e = sense(:first).explanations.first
12
+ assert_equal 'A2', e.level
13
+ assert_equal %("Your name is Angela Black?" "That is correct."),
14
+ e.examples.last.sentence
15
+ end
16
+
17
+ def test_code
18
+ w = Camdict::Word.new('cause')
19
+ def1 = w.definitions
20
+ e1 = def1.senses.first.explanations.first
21
+ assert_equal ' C or U ', e1.code
22
+ end
23
+
24
+ def test_gc_usage
25
+ w = Camdict::Word.new('cause')
26
+ def1 = w.definition
27
+ e2 = def1.senses[2].explanations.first
28
+ assert_equal ' + two objects ', e2.examples.last.usage
29
+ end
30
+
31
+ def test_correctly
32
+ skip 'derived word - on the same page with its original'
33
+ w = Camdict::Word.new('correctly').definition
34
+ e1 = w.senses.first.explanations
35
+ assert_equal 'Have I pronounced your name correctly?',
36
+ e1[2].examples[0].sentence
37
+ assert_equal 'B1', e1[2].level
23
38
  end
24
39
 
25
40
  def test_phrase_meaning
41
+ skip 'phrase ought have its own class'
26
42
  w = Camdict::Word.new('blow your nose')
27
43
  defa = w.definitions
28
- def1 = defa.first
44
+ def1 = defa.first
29
45
  el = def1.explanations.last
30
46
  exped = 'to force air from your lungs and through your nose to clear it'
31
47
  assert_equal exped, el.meaning
32
48
  end
33
49
 
50
+ private
51
+
52
+ def sense(nth)
53
+ Camdict::Word.new('correct').definition.senses.send(nth)
54
+ end
34
55
  end
35
56
  end