ruby_speech 2.1.2 → 2.2.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.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -2
  3. data/CHANGELOG.md +8 -0
  4. data/README.md +23 -0
  5. data/ext/ruby_speech/extconf.rb +3 -1
  6. data/ext/ruby_speech/ruby_speech.c +4 -1
  7. data/lib/ruby_speech.rb +6 -19
  8. data/lib/ruby_speech/generic_element.rb +141 -29
  9. data/lib/ruby_speech/grxml.rb +16 -22
  10. data/lib/ruby_speech/grxml/element.rb +6 -6
  11. data/lib/ruby_speech/grxml/grammar.rb +29 -12
  12. data/lib/ruby_speech/grxml/item.rb +13 -0
  13. data/lib/ruby_speech/grxml/matcher.rb +5 -1
  14. data/lib/ruby_speech/grxml/one_of.rb +4 -0
  15. data/lib/ruby_speech/grxml/rule.rb +10 -0
  16. data/lib/ruby_speech/grxml/token.rb +3 -0
  17. data/lib/ruby_speech/nlsml.rb +3 -9
  18. data/lib/ruby_speech/ssml.rb +20 -22
  19. data/lib/ruby_speech/ssml/audio.rb +17 -0
  20. data/lib/ruby_speech/ssml/desc.rb +4 -0
  21. data/lib/ruby_speech/ssml/element.rb +5 -3
  22. data/lib/ruby_speech/ssml/emphasis.rb +17 -0
  23. data/lib/ruby_speech/ssml/mark.rb +2 -0
  24. data/lib/ruby_speech/ssml/p.rb +21 -0
  25. data/lib/ruby_speech/ssml/phoneme.rb +2 -0
  26. data/lib/ruby_speech/ssml/prosody.rb +15 -0
  27. data/lib/ruby_speech/ssml/s.rb +20 -0
  28. data/lib/ruby_speech/ssml/say_as.rb +2 -0
  29. data/lib/ruby_speech/ssml/speak.rb +19 -1
  30. data/lib/ruby_speech/ssml/sub.rb +2 -0
  31. data/lib/ruby_speech/ssml/voice.rb +19 -0
  32. data/lib/ruby_speech/version.rb +1 -1
  33. data/ruby_speech.gemspec +2 -3
  34. data/spec/ruby_speech/grxml/grammar_spec.rb +35 -30
  35. data/spec/ruby_speech/grxml/item_spec.rb +8 -6
  36. data/spec/ruby_speech/grxml/one_of_spec.rb +7 -3
  37. data/spec/ruby_speech/grxml/rule_spec.rb +14 -12
  38. data/spec/ruby_speech/grxml/ruleref_spec.rb +5 -3
  39. data/spec/ruby_speech/grxml/tag_spec.rb +6 -2
  40. data/spec/ruby_speech/grxml/token_spec.rb +6 -2
  41. data/spec/ruby_speech/grxml_spec.rb +57 -69
  42. data/spec/ruby_speech/ssml/audio_spec.rb +20 -16
  43. data/spec/ruby_speech/ssml/break_spec.rb +14 -10
  44. data/spec/ruby_speech/ssml/desc_spec.rb +9 -5
  45. data/spec/ruby_speech/ssml/emphasis_spec.rb +17 -13
  46. data/spec/ruby_speech/ssml/mark_spec.rb +7 -3
  47. data/spec/ruby_speech/ssml/p_spec.rb +18 -14
  48. data/spec/ruby_speech/ssml/phoneme_spec.rb +10 -6
  49. data/spec/ruby_speech/ssml/prosody_spec.rb +29 -25
  50. data/spec/ruby_speech/ssml/s_spec.rb +17 -13
  51. data/spec/ruby_speech/ssml/say_as_spec.rb +11 -7
  52. data/spec/ruby_speech/ssml/speak_spec.rb +48 -32
  53. data/spec/ruby_speech/ssml/sub_spec.rb +9 -5
  54. data/spec/ruby_speech/ssml/voice_spec.rb +23 -19
  55. data/spec/ruby_speech/ssml_spec.rb +64 -63
  56. data/spec/spec_helper.rb +0 -3
  57. metadata +10 -31
  58. data/lib/ruby_speech/xml.rb +0 -11
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: caf6dc66fd5b216e0825c25c2df9c16324e955e1
4
- data.tar.gz: ecd61a61b6a362521b6915d7eac46b47556f55c0
3
+ metadata.gz: ec0d77b52aa0d3a5f6984d3a966592337bf744b8
4
+ data.tar.gz: dd2535eab8d121f262017bd29cb881021652b1ea
5
5
  SHA512:
6
- metadata.gz: 1a08ac02e15a99aaf0f4ec753cb22fbf63304d4d42df34215dffe15255d344cf2d06bc23ab448f2152069e1c074d3d47b9a4978a4e04a1a746124a5658ce8a1e
7
- data.tar.gz: 4a96f1f2fb4a56a08f6328bd6caa89ec4b47ee8638ee1c0d2e7bd3e2a867274b1d19d43039b423144e7e195140380e474c1533109e5ca0d165fc919e3b63fc69
6
+ metadata.gz: 23a82e611e67b400e6fd06560e5ae7bcec8a68df565ac6c82378dcb2d86378ac75696b5f6399f39d275c8c98ec9cc0126209b60f1b78bf262bc2b97b65f7f453
7
+ data.tar.gz: 9816cb0183ec5138a976417b27beae562590eba32d205076294855a8160f763828bfc84a548fa603e5758970cc73affe65838e84dc541c4abf3054b5bd71ee2c
data/.travis.yml CHANGED
@@ -1,7 +1,6 @@
1
1
  language: ruby
2
2
 
3
3
  rvm:
4
- - 1.9.2
5
4
  - 1.9.3
6
5
  - 2.0.0
7
6
  - jruby-19mode
@@ -9,7 +8,7 @@ rvm:
9
8
  - ruby-head
10
9
  matrix:
11
10
  allow_failures:
12
- # - rvm: jruby-19mode
11
+ - rvm: ruby-head
13
12
  before_install:
14
13
  - sudo apt-get install libpcre3 libpcre3-dev
15
14
 
data/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # [develop](https://github.com/benlangfeld/ruby_speech)
2
2
 
3
+ # [2.2.0](https://github.com/benlangfeld/ruby_speech/compare/v2.1.2...v2.2.0) - [2013-06-26](https://rubygems.org/gems/ruby_speech/versions/2.2.0)
4
+ * Bugfix: Constant autoload in rbx C extensions doesn't work properly
5
+ * Bugfix: No longer subclass or copy nodes, use delegation instead
6
+ * Bugfix: Java 1.6 compatability
7
+ * CS: Remove niceogiri dependency
8
+ * CS: Remove autoloading
9
+ * CS: Depend on activesupport less
10
+
3
11
  # [2.1.2](https://github.com/benlangfeld/ruby_speech/compare/v2.1.1...v2.1.2) - [2013-06-05](https://rubygems.org/gems/ruby_speech/versions/2.1.2)
4
12
  * Bugfix: Allow wrapping a pre-parsed XML node nested arbitrary deeply as an NLSML document
5
13
 
data/README.md CHANGED
@@ -1,9 +1,32 @@
1
1
  # RubySpeech
2
2
  RubySpeech is a library for constructing and parsing Text to Speech (TTS) and Automatic Speech Recognition (ASR) documents such as [SSML](http://www.w3.org/TR/speech-synthesis), [GRXML](http://www.w3.org/TR/speech-grammar/) and [NLSML](http://www.w3.org/TR/nl-spec/). Such documents can be constructed to be processed by TTS and ASR engines, parsed as the result from such, or used in the implementation of such engines.
3
3
 
4
+ ## Dependencies
5
+
6
+ ### pcre (except on JRuby)
7
+
8
+ #### On OSX with Homebrew
9
+ ```
10
+ brew install pcre
11
+ ```
12
+
13
+ #### On Ubuntu/Debian
14
+ ```
15
+ sudo apt-get install libpcre3 libpcre3-dev
16
+ ```
17
+
18
+ #### On CentOS
19
+ ```
20
+ sudo yum install pcre-devel
21
+ ```
22
+
4
23
  ## Installation
5
24
  gem install ruby_speech
6
25
 
26
+ ## Ruby Version Compatability
27
+ * CRuby 1.9.3+ (1.9.2 is unofficially supported, but not regularly tested)
28
+ * JRuby 1.7+
29
+
7
30
  ## Library
8
31
 
9
32
  ### SSML
@@ -2,6 +2,8 @@ require 'mkmf'
2
2
 
3
3
  $LIBS << " -lpcre"
4
4
 
5
- abort "-----\n#{lib} is missing.\n-----" unless find_header('pcre.h')
5
+ unless find_header('pcre.h')
6
+ abort "-----\nPCRE is missing. You must install it as per the README @ https://github.com/benlangfeld/ruby_speech\n-----"
7
+ end
6
8
 
7
9
  create_makefile 'ruby_speech/ruby_speech'
@@ -33,12 +33,15 @@ static int is_match_end(pcre *compiled_regex, const char *input)
33
33
  char search_input[MAX_INPUT_SIZE + 2];
34
34
  const char *search_set = "0123456789#*ABCD";
35
35
  const char *search = strchr(search_set, input[input_size - 1]); /* start with last digit in input */
36
+ int i;
36
37
 
37
38
  /* For each digit in search_set, check if input + search_set digit is a potential match.
38
39
  If so, then this is not a match end.
39
40
  */
41
+ if (strlen(input) > MAX_INPUT_SIZE) {
42
+ return 0;
43
+ }
40
44
  sprintf(search_input, "%sZ", input);
41
- int i;
42
45
  for (i = 0; i < 16; i++) {
43
46
  int result;
44
47
  if (!*search) {
data/lib/ruby_speech.rb CHANGED
@@ -1,24 +1,13 @@
1
1
  %w{
2
- active_support/dependencies/autoload
3
- active_support/core_ext/object/blank
4
- active_support/core_ext/numeric/time
5
- active_support/core_ext/enumerable
6
- niceogiri
2
+ nokogiri
3
+
4
+ ruby_speech/version
5
+ ruby_speech/ssml
6
+ ruby_speech/grxml
7
+ ruby_speech/nlsml
7
8
  }.each { |f| require f }
8
9
 
9
10
  module RubySpeech
10
- extend ActiveSupport::Autoload
11
-
12
- autoload :Version
13
-
14
- eager_autoload do
15
- autoload :GenericElement
16
- autoload :SSML
17
- autoload :GRXML
18
- autoload :NLSML
19
- autoload :XML
20
- end
21
-
22
11
  def self.parse(string)
23
12
  document = Nokogiri::XML.parse string, nil, nil, Nokogiri::XML::ParseOptions::NOBLANKS
24
13
  namespace = document.root.namespace
@@ -32,5 +21,3 @@ module RubySpeech
32
21
  end
33
22
  end
34
23
  end
35
-
36
- ActiveSupport::Autoload.eager_autoload!
@@ -41,34 +41,42 @@ module RubySpeech
41
41
  # @param [XML::Node] node the node to import
42
42
  # @return the appropriate object based on the node name and namespace
43
43
  def import(node)
44
- node = Nokogiri::XML.parse(node, nil, nil, Nokogiri::XML::ParseOptions::NOBLANKS).root unless node.is_a?(Nokogiri::XML::Node)
44
+ node = Nokogiri::XML.parse(node, nil, nil, Nokogiri::XML::ParseOptions::NOBLANKS).root unless node.is_a?(Nokogiri::XML::Node) || node.is_a?(GenericElement)
45
45
  return node.content if node.is_a?(Nokogiri::XML::Text)
46
46
  klass = class_from_registration node.node_name
47
47
  if klass && klass != self
48
48
  klass.import node
49
49
  else
50
- new.inherit node
50
+ new(node.document).inherit node
51
51
  end
52
52
  end
53
+ end
53
54
 
54
- def new(atts = {}, &block)
55
- super(self.registered_name, nil, self.namespace) do |new_node|
56
- (self.defaults || {}).merge(atts).each_pair { |k, v| new_node.send :"#{k}=", v }
57
- block_return = new_node.eval_dsl_block &block
58
- new_node.string block_return if block_return.is_a?(String) && block_return.present?
59
- end
60
- end
55
+ def initialize(doc, atts = nil, &block)
56
+ @doc = doc
57
+ build atts, &block if atts || block_given?
61
58
  end
62
59
 
63
60
  attr_writer :parent
64
61
 
62
+ def node
63
+ @node || create_node
64
+ end
65
+
65
66
  def parent
66
67
  @parent || super
67
68
  end
68
69
 
69
70
  def inherit(node)
70
71
  self.parent = node.parent
71
- super
72
+ @node = node
73
+ self
74
+ end
75
+
76
+ def build(atts, &block)
77
+ mass_assign atts
78
+ block_return = eval_dsl_block &block
79
+ string block_return if block_return.is_a?(String) && !block_return.length.zero?
72
80
  end
73
81
 
74
82
  def version
@@ -94,9 +102,16 @@ module RubySpeech
94
102
  end
95
103
 
96
104
  def +(other)
97
- self.class.new(:base_uri => base_uri).tap do |new_element|
98
- (self.children + other.children).each do |child|
99
- new_element << child
105
+ new_doc = Nokogiri::XML::Document.new
106
+ self.class.new(new_doc).tap do |new_element|
107
+ new_doc.root = new_element.node
108
+ if Nokogiri.jruby?
109
+ new_element.add_child self.nokogiri_children
110
+ new_element.add_child other.nokogiri_children
111
+ else
112
+ # TODO: This is yucky because it requires serialization
113
+ new_element.add_child self.nokogiri_children.to_xml
114
+ new_element.add_child other.nokogiri_children.to_xml
100
115
  end
101
116
  end
102
117
  end
@@ -113,15 +128,30 @@ module RubySpeech
113
128
  expression << type.to_s
114
129
 
115
130
  expression << '[' << attributes.inject([]) do |h, (key, value)|
116
- h << "@#{namespace_href && Nokogiri.jruby? ? 'ns:' : ''}#{key}='#{value}'"
131
+ h << "@#{key}='#{value}'"
117
132
  end.join(',') << ']' if attributes
118
133
 
119
- xpath expression, :ns => namespace_href
134
+ xpath expression, :ns => self.class.namespace
120
135
  else
121
136
  super()
122
137
  end.map { |c| self.class.import c }
123
138
  end
124
139
 
140
+ def nokogiri_children
141
+ node.children
142
+ end
143
+
144
+ def <<(other)
145
+ case other
146
+ when GenericElement
147
+ super other.node
148
+ when String
149
+ string other
150
+ else
151
+ super other
152
+ end
153
+ end
154
+
125
155
  def embed(other)
126
156
  case other
127
157
  when String
@@ -141,18 +171,6 @@ module RubySpeech
141
171
  self << Nokogiri::XML::Text.new(other, document)
142
172
  end
143
173
 
144
- def method_missing(method_name, *args, &block)
145
- const_name = method_name.to_s.sub('ssml', '').titleize.gsub(' ', '')
146
- if self.class.module.const_defined?(const_name)
147
- const = self.class.module.const_get const_name
148
- embed const.new(*args, &block)
149
- elsif @block_binding && @block_binding.respond_to?(method_name)
150
- @block_binding.send method_name, *args, &block
151
- else
152
- super
153
- end
154
- end
155
-
156
174
  def clone
157
175
  GRXML.import to_xml
158
176
  end
@@ -162,8 +180,102 @@ module RubySpeech
162
180
  block.call self
163
181
  end
164
182
 
165
- def eql?(o, *args)
166
- super o, :content, :children, *args
183
+ # Helper method to read an attribute
184
+ #
185
+ # @param [#to_sym] attr_name the name of the attribute
186
+ # @param [String, Symbol, nil] to_call the name of the method to call on
187
+ # the returned value
188
+ # @return nil or the value
189
+ def read_attr(attr_name, to_call = nil)
190
+ val = self[attr_name]
191
+ val && to_call ? val.__send__(to_call) : val
192
+ end
193
+
194
+ # Helper method to write a value to an attribute
195
+ #
196
+ # @param [#to_sym] attr_name the name of the attribute
197
+ # @param [#to_s] value the value to set the attribute to
198
+ def write_attr(attr_name, value, to_call = nil)
199
+ self[attr_name] = value && to_call ? value.__send__(to_call) : value
200
+ end
201
+
202
+ # Attach a namespace to the node
203
+ #
204
+ # @overload namespace=(ns)
205
+ # Attach an already created XML::Namespace
206
+ # @param [XML::Namespace] ns the namespace object
207
+ # @overload namespace=(ns)
208
+ # Create a new namespace and attach it
209
+ # @param [String] ns the namespace uri
210
+ def namespace=(namespaces)
211
+ case namespaces
212
+ when Nokogiri::XML::Namespace
213
+ super namespaces
214
+ when String
215
+ ns = self.add_namespace nil, namespaces
216
+ super ns
217
+ end
218
+ end
219
+
220
+ # Helper method to get the node's namespace
221
+ #
222
+ # @return [XML::Namespace, nil] The node's namespace object if it exists
223
+ def namespace_href
224
+ namespace.href if namespace
225
+ end
226
+
227
+ # The node as XML
228
+ #
229
+ # @return [String] XML representation of the node
230
+ def inspect
231
+ self.to_xml
232
+ end
233
+
234
+ def to_s
235
+ to_xml
236
+ end
237
+
238
+ # Check that a set of fields are equal between nodes
239
+ #
240
+ # @param [Node] other the other node to compare against
241
+ # @param [*#to_s] fields the set of fields to compare
242
+ # @return [Fixnum<-1,0,1>]
243
+ def eql?(o, *fields)
244
+ o.is_a?(self.class) && ([:content, :children] + fields).all? { |f| self.__send__(f) == o.__send__(f) }
245
+ end
246
+
247
+ # @private
248
+ def ==(o)
249
+ eql?(o)
250
+ end
251
+
252
+ def create_node
253
+ @node = Nokogiri::XML::Node.new self.class.registered_name, @doc
254
+ mass_assign self.class.defaults
255
+ @node
256
+ end
257
+
258
+ def mass_assign(attrs)
259
+ attrs.each_pair { |k, v| send :"#{k}=", v } if attrs
260
+ end
261
+
262
+ def method_missing(method_name, *args, &block)
263
+ if node.respond_to?(method_name)
264
+ return node.send method_name, *args, &block
265
+ end
266
+
267
+ const_name = method_name.to_s.sub('ssml_', '').gsub('_', '-')
268
+ if const = self.class.class_from_registration(const_name)
269
+ embed const.new(self.document, *args, &block)
270
+ elsif @block_binding && @block_binding.respond_to?(method_name)
271
+ @block_binding.send method_name, *args, &block
272
+ else
273
+ super
274
+ end
275
+ end
276
+
277
+ def respond_to_missing?(method_name, include_private = false)
278
+ node.respond_to?(method_name, include_private) || super
167
279
  end
168
280
  end # Element
169
281
  end # RubySpeech
@@ -1,30 +1,26 @@
1
+ require 'ruby_speech/grxml/matcher'
2
+ require 'ruby_speech/grxml/element'
3
+
1
4
  module RubySpeech
2
5
  module GRXML
3
- extend ActiveSupport::Autoload
4
-
5
- eager_autoload do
6
- autoload :Element
7
- autoload :Grammar
8
- autoload :Rule
9
- autoload :Item
10
- autoload :OneOf
11
- autoload :Ruleref
12
- autoload :Tag
13
- autoload :Token
14
- end
15
-
16
- autoload :Match
17
- autoload :Matcher
18
- autoload :MaxMatch
19
- autoload :NoMatch
20
- autoload :PotentialMatch
21
-
22
6
  InvalidChildError = Class.new StandardError
23
7
 
24
8
  GRXML_NAMESPACE = 'http://www.w3.org/2001/06/grammar'
25
9
 
10
+ %w{
11
+ grammar
12
+ rule
13
+ item
14
+ one_of
15
+ ruleref
16
+ tag
17
+ token
18
+ }.each { |f| require "ruby_speech/grxml/#{f}" }
19
+
26
20
  def self.draw(attributes = {}, &block)
27
- Grammar.new(attributes).tap do |grammar|
21
+ document = Nokogiri::XML::Document.new
22
+ Grammar.new(document, attributes).tap do |grammar|
23
+ document.root = grammar.node
28
24
  block_return = grammar.eval_dsl_block &block
29
25
  grammar << block_return if block_return.is_a?(String)
30
26
  end.assert_has_matching_root_rule
@@ -35,5 +31,3 @@ module RubySpeech
35
31
  end
36
32
  end # GRXML
37
33
  end # RubySpeech
38
-
39
- ActiveSupport::Autoload.eager_autoload!
@@ -1,8 +1,8 @@
1
- require 'active_support/core_ext/class/attribute'
1
+ require 'ruby_speech/generic_element'
2
2
 
3
3
  module RubySpeech
4
4
  module GRXML
5
- class Element < Niceogiri::XML::Node
5
+ class Element
6
6
  def self.namespace
7
7
  GRXML_NAMESPACE
8
8
  end
@@ -15,12 +15,12 @@ module RubySpeech
15
15
  GRXML
16
16
  end
17
17
 
18
- alias_method :nokogiri_children, :children
19
-
20
- alias :to_doc :document
21
-
22
18
  include GenericElement
23
19
 
20
+ def to_doc
21
+ document
22
+ end
23
+
24
24
  def regexp_content # :nodoc:
25
25
  "(#{children.map(&:regexp_content).join})"
26
26
  end