agt 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE.md +7 -0
- data/README.md +5 -0
- data/app/assets/javascripts/agt/config.coffee +9 -0
- data/app/assets/javascripts/agt/dom.coffee +12 -0
- data/app/assets/javascripts/agt/function.coffee +317 -0
- data/app/assets/javascripts/agt/geom/circle.coffee +338 -0
- data/app/assets/javascripts/agt/geom/cubic_bezier.coffee +37 -0
- data/app/assets/javascripts/agt/geom/diamond.coffee +241 -0
- data/app/assets/javascripts/agt/geom/ellipsis.coffee +141 -0
- data/app/assets/javascripts/agt/geom/linear_spline.coffee +56 -0
- data/app/assets/javascripts/agt/geom/matrix.coffee +240 -0
- data/app/assets/javascripts/agt/geom/mixins/geometry.coffee +171 -0
- data/app/assets/javascripts/agt/geom/mixins/intersections.coffee +150 -0
- data/app/assets/javascripts/agt/geom/mixins/path.coffee +145 -0
- data/app/assets/javascripts/agt/geom/mixins/proxyable.coffee +9 -0
- data/app/assets/javascripts/agt/geom/mixins/spline.coffee +329 -0
- data/app/assets/javascripts/agt/geom/mixins/surface.coffee +55 -0
- data/app/assets/javascripts/agt/geom/mixins/triangulable.coffee +112 -0
- data/app/assets/javascripts/agt/geom/point.coffee +454 -0
- data/app/assets/javascripts/agt/geom/polygon.coffee +119 -0
- data/app/assets/javascripts/agt/geom/quad_bezier.coffee +43 -0
- data/app/assets/javascripts/agt/geom/quint_bezier.coffee +42 -0
- data/app/assets/javascripts/agt/geom/rectangle.coffee +599 -0
- data/app/assets/javascripts/agt/geom/spiral.coffee +90 -0
- data/app/assets/javascripts/agt/geom/transformation_proxy.coffee +43 -0
- data/app/assets/javascripts/agt/geom/triangle.coffee +442 -0
- data/app/assets/javascripts/agt/impulse.coffee +105 -0
- data/app/assets/javascripts/agt/index.coffee +56 -0
- data/app/assets/javascripts/agt/inflector/inflection.coffee +21 -0
- data/app/assets/javascripts/agt/inflector/inflections.coffee +75 -0
- data/app/assets/javascripts/agt/inflector/inflector.coffee +235 -0
- data/app/assets/javascripts/agt/inheritance.coffee +132 -0
- data/app/assets/javascripts/agt/math.coffee +45 -0
- data/app/assets/javascripts/agt/mixins/activable.coffee +31 -0
- data/app/assets/javascripts/agt/mixins/aliasable.coffee +25 -0
- data/app/assets/javascripts/agt/mixins/alternate_case.coffee +72 -0
- data/app/assets/javascripts/agt/mixins/cloneable.coffee +71 -0
- data/app/assets/javascripts/agt/mixins/delegation.coffee +90 -0
- data/app/assets/javascripts/agt/mixins/disposable.coffee +7 -0
- data/app/assets/javascripts/agt/mixins/equatable.coffee +37 -0
- data/app/assets/javascripts/agt/mixins/formattable.coffee +52 -0
- data/app/assets/javascripts/agt/mixins/globalizable.coffee +175 -0
- data/app/assets/javascripts/agt/mixins/has_ancestors.coffee +47 -0
- data/app/assets/javascripts/agt/mixins/has_collection.coffee +107 -0
- data/app/assets/javascripts/agt/mixins/has_nested_collection.coffee +51 -0
- data/app/assets/javascripts/agt/mixins/memoizable.coffee +64 -0
- data/app/assets/javascripts/agt/mixins/parameterizable.coffee +101 -0
- data/app/assets/javascripts/agt/mixins/poolable.coffee +62 -0
- data/app/assets/javascripts/agt/mixins/sourcable.coffee +45 -0
- data/app/assets/javascripts/agt/mixins/state_machine.coffee +47 -0
- data/app/assets/javascripts/agt/net/router.coffee +165 -0
- data/app/assets/javascripts/agt/object.coffee +9 -0
- data/app/assets/javascripts/agt/particles/actions/base_action.coffee +7 -0
- data/app/assets/javascripts/agt/particles/actions/die_on_surface.coffee +14 -0
- data/app/assets/javascripts/agt/particles/actions/force.coffee +11 -0
- data/app/assets/javascripts/agt/particles/actions/friction.coffee +14 -0
- data/app/assets/javascripts/agt/particles/actions/live.coffee +9 -0
- data/app/assets/javascripts/agt/particles/actions/macro_action.coffee +13 -0
- data/app/assets/javascripts/agt/particles/actions/move.coffee +11 -0
- data/app/assets/javascripts/agt/particles/actions/null_action.coffee +9 -0
- data/app/assets/javascripts/agt/particles/counters/by_rate.coffee +17 -0
- data/app/assets/javascripts/agt/particles/counters/fixed.coffee +9 -0
- data/app/assets/javascripts/agt/particles/counters/null_counter.coffee +9 -0
- data/app/assets/javascripts/agt/particles/emission.coffee +35 -0
- data/app/assets/javascripts/agt/particles/emitters/null_emitter.coffee +7 -0
- data/app/assets/javascripts/agt/particles/emitters/path.coffee +10 -0
- data/app/assets/javascripts/agt/particles/emitters/ponctual.coffee +9 -0
- data/app/assets/javascripts/agt/particles/emitters/surface.coffee +10 -0
- data/app/assets/javascripts/agt/particles/initializers/explosion.coffee +19 -0
- data/app/assets/javascripts/agt/particles/initializers/life.coffee +16 -0
- data/app/assets/javascripts/agt/particles/initializers/macro_initializer.coffee +10 -0
- data/app/assets/javascripts/agt/particles/initializers/null_initializer.coffee +7 -0
- data/app/assets/javascripts/agt/particles/initializers/particle_sub_system.coffee +12 -0
- data/app/assets/javascripts/agt/particles/initializers/stream.coffee +20 -0
- data/app/assets/javascripts/agt/particles/mixins/randomizable.coffee +10 -0
- data/app/assets/javascripts/agt/particles/particle.coffee +32 -0
- data/app/assets/javascripts/agt/particles/sub_system.coffee +11 -0
- data/app/assets/javascripts/agt/particles/system.coffee +103 -0
- data/app/assets/javascripts/agt/particles/timers/instant.coffee +11 -0
- data/app/assets/javascripts/agt/particles/timers/limited.coffee +19 -0
- data/app/assets/javascripts/agt/particles/timers/null_timer.coffee +11 -0
- data/app/assets/javascripts/agt/particles/timers/unlimited.coffee +9 -0
- data/app/assets/javascripts/agt/particles/timers/until_death.coffee +11 -0
- data/app/assets/javascripts/agt/promise.coffee +214 -0
- data/app/assets/javascripts/agt/random/random.coffee +100 -0
- data/app/assets/javascripts/agt/random/seeds/lagged_fibonnacci.coffee +53 -0
- data/app/assets/javascripts/agt/random/seeds/linear.coffee +16 -0
- data/app/assets/javascripts/agt/random/seeds/linear_congruential.coffee +23 -0
- data/app/assets/javascripts/agt/random/seeds/math_random.coffee +9 -0
- data/app/assets/javascripts/agt/random/seeds/mersenne_twister.coffee +42 -0
- data/app/assets/javascripts/agt/random/seeds/no_random.coffee +12 -0
- data/app/assets/javascripts/agt/random/seeds/paul_houle.coffee +19 -0
- data/app/assets/javascripts/agt/signal.coffee +272 -0
- data/app/assets/javascripts/agt/sprites/animation.coffee +13 -0
- data/app/assets/javascripts/agt/sprites/sprite.coffee +30 -0
- data/app/assets/javascripts/agt/widgets/hash.coffee +36 -0
- data/app/assets/javascripts/agt/widgets/widgets.coffee +194 -0
- data/app/assets/javascripts/agt/widgets/widgets/checked_input.coffee +7 -0
- data/app/assets/javascripts/agt/widgets/widgets/focus_bubbling.coffee +15 -0
- data/lib/agt.rb +8 -0
- data/lib/agt/version.rb +5 -0
- metadata +173 -0
@@ -0,0 +1,105 @@
|
|
1
|
+
|
2
|
+
# Defines a local `requestAnimationFrame` function using the snippets
|
3
|
+
# from [Paul Irish](http://paulirish.com/2011/requestanimationframe-for-smart-animating/).
|
4
|
+
g = global ? window
|
5
|
+
requestAnimFrame = g.requestAnimationFrame or
|
6
|
+
g.webkitRequestAnimationFrame or
|
7
|
+
g.mozRequestAnimationFrame or
|
8
|
+
g.oRequestAnimationFrame or
|
9
|
+
g.msRequestAnimationFrame or
|
10
|
+
-> g.setTimeout callback, 1000 / 60
|
11
|
+
|
12
|
+
# Public: Impulse is a custom signal whose purpose is to handle
|
13
|
+
# animations within an application.
|
14
|
+
#
|
15
|
+
# The `Impulse` signal has its own messages to dispatch.
|
16
|
+
#
|
17
|
+
# Impulse dispatch its messages on a regular basis, based
|
18
|
+
# on the `requestAnimationFrame` function.
|
19
|
+
class agt.Impulse extends agt.Signal
|
20
|
+
### Public ###
|
21
|
+
|
22
|
+
# Returns a global unique instance to use as reference
|
23
|
+
# in a typical application
|
24
|
+
#
|
25
|
+
# Returns an {agt.Impulse}
|
26
|
+
@instance: -> @__instance__ ||= new Impulse
|
27
|
+
|
28
|
+
# Initialize the `Impulse` signal with a specific time scale.
|
29
|
+
# By default the `timeScale` is `1`, which means there's no scaling.
|
30
|
+
constructor:(@timeScale=1)->
|
31
|
+
super()
|
32
|
+
|
33
|
+
@running = false
|
34
|
+
|
35
|
+
# Impulse listeners are registered as any other signal listeners.
|
36
|
+
#
|
37
|
+
# ```coffeescript
|
38
|
+
# impulse.add (bias, biasInSeconds, time) ->
|
39
|
+
# ```
|
40
|
+
#
|
41
|
+
# listener - The listener {Function} to register, with the following
|
42
|
+
# signature:
|
43
|
+
# :bias - The duration {Number} of the last animation
|
44
|
+
# frame in milliseconds.
|
45
|
+
# :biasInSeconds - The duration {Number} of the last
|
46
|
+
# animation frame in seconds.
|
47
|
+
# :time - The current time {Number} at the moment of the call.
|
48
|
+
# context - The this {Object} for the listener.
|
49
|
+
# priority - The priority {Number}, the greater the priority, the sooner
|
50
|
+
# the listener will be called.
|
51
|
+
add:(listener, context, priority=0)->
|
52
|
+
super listener, context, priority
|
53
|
+
|
54
|
+
# By convention, the `Impulse` signal start running when the
|
55
|
+
# first listener is added.
|
56
|
+
@start() if @hasListeners() and not @running
|
57
|
+
|
58
|
+
# Impulse listeners are unregistered as any other signal listeners.
|
59
|
+
#
|
60
|
+
# listener - The {Function} to remove from this signal.
|
61
|
+
# context - The `this` {Object} that was registered with the listener.
|
62
|
+
remove:(listener, context)->
|
63
|
+
super listener, context
|
64
|
+
|
65
|
+
# The `Impulse` object automatically stop itself when it doesn't
|
66
|
+
# have a listener anymore.
|
67
|
+
@stop() if @running and not @hasListeners()
|
68
|
+
|
69
|
+
# {Delegates to: agt.Signal.hasListeners}
|
70
|
+
hasListeners:->
|
71
|
+
@listeners.length > 0
|
72
|
+
|
73
|
+
# Starts, or restarts the `Impulse`.
|
74
|
+
start:->
|
75
|
+
@running = true
|
76
|
+
@initRun()
|
77
|
+
|
78
|
+
# Stops the `Impulse`.
|
79
|
+
stop:->
|
80
|
+
@running = false
|
81
|
+
|
82
|
+
# Internal: Initializes the run of the `Impulse`. A request
|
83
|
+
# is made to the `requestAnimationFrame` that will
|
84
|
+
# call the `run` method each time.
|
85
|
+
initRun:->
|
86
|
+
@time = @getTime()
|
87
|
+
requestAnimFrame =>
|
88
|
+
@run()
|
89
|
+
|
90
|
+
# A running `Impulse` will dispatch various informations
|
91
|
+
# to its listeners each time the `run` method is called.
|
92
|
+
#
|
93
|
+
# The `initRun` is called at the end of the function if the impulse
|
94
|
+
# is always running in order to continue the animation.
|
95
|
+
run:->
|
96
|
+
if @running
|
97
|
+
t = @getTime()
|
98
|
+
s = ( t - @time ) * @timeScale
|
99
|
+
|
100
|
+
@dispatch s, s / 1000, t
|
101
|
+
@initRun()
|
102
|
+
|
103
|
+
# Internal: Helper method that return the current time.
|
104
|
+
getTime:->
|
105
|
+
new Date().getTime()
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# The module bootstrap.
|
2
|
+
isCommonJS = typeof module isnt "undefined"
|
3
|
+
|
4
|
+
__namespaces__ = {}
|
5
|
+
|
6
|
+
if isCommonJS
|
7
|
+
module.exports = agt = {}
|
8
|
+
else
|
9
|
+
window.agt = agt = {}
|
10
|
+
|
11
|
+
namespace = (path) ->
|
12
|
+
return if __namespaces__[path]
|
13
|
+
|
14
|
+
__namespaces__[path] = true
|
15
|
+
|
16
|
+
originalPath = path
|
17
|
+
path = path.split('.')
|
18
|
+
root = path.shift()
|
19
|
+
|
20
|
+
obj = if isCommonJS
|
21
|
+
module.exports
|
22
|
+
else
|
23
|
+
window[root] ||= {}
|
24
|
+
|
25
|
+
for p in path
|
26
|
+
obj = obj[p] = obj[p] or {}
|
27
|
+
|
28
|
+
window.namespace if window?
|
29
|
+
|
30
|
+
agt.deprecated = (message) ->
|
31
|
+
parseLine = (line) ->
|
32
|
+
if line.indexOf('@') > 0
|
33
|
+
if line.indexOf('</') > 0
|
34
|
+
[m, o, f] = /<\/([^@]+)@(.)+$/.exec line
|
35
|
+
else
|
36
|
+
[m, f] = /@(.)+$/.exec line
|
37
|
+
else
|
38
|
+
if line.indexOf('(') > 0
|
39
|
+
[m, o, f] = /at\s+([^\s]+)\s*\(([^\)])+/.exec line
|
40
|
+
else
|
41
|
+
[m, f] = /at\s+([^\s]+)/.exec line
|
42
|
+
|
43
|
+
[o,f]
|
44
|
+
|
45
|
+
e = new Error()
|
46
|
+
caller = ''
|
47
|
+
if e.stack?
|
48
|
+
s = e.stack.split('\n')
|
49
|
+
[deprecatedMethodCallerName, deprecatedMethodCallerFile] = parseLine s[3]
|
50
|
+
|
51
|
+
caller = if deprecatedMethodCallerName
|
52
|
+
" (called from #{deprecatedMethodCallerName} at #{deprecatedMethodCallerFile})"
|
53
|
+
else
|
54
|
+
"(called from #{deprecatedMethodCallerFile})"
|
55
|
+
|
56
|
+
console.log "DEPRECATION WARNING: #{message}#{caller}"
|
@@ -0,0 +1,21 @@
|
|
1
|
+
namespace('agt.inflector')
|
2
|
+
|
3
|
+
# Public: The `Inflection` class represent a single inflection for the general
|
4
|
+
# case of pluralization, singularization and conversion to the past tense.
|
5
|
+
class agt.inflector.Inflection
|
6
|
+
### Public ###
|
7
|
+
|
8
|
+
# Creates a new instance.
|
9
|
+
#
|
10
|
+
# match - The {RegExp} or {String} to match.
|
11
|
+
# replace - The replacement {String}.
|
12
|
+
constructor: (@match, @replace) ->
|
13
|
+
@match = ///^#{@match}$///i if typeof @match is 'string'
|
14
|
+
|
15
|
+
# Converts the passed-in {String} if it matches the inflection's {RegExp}.
|
16
|
+
#
|
17
|
+
# string - The {String} to convert.
|
18
|
+
#
|
19
|
+
# Returns a {String}.
|
20
|
+
inflect: (string) ->
|
21
|
+
string.replace(@match, @replace) if @match.test(string)
|
@@ -0,0 +1,75 @@
|
|
1
|
+
|
2
|
+
agt.inflector.config 'en', ->
|
3
|
+
@plural(/$/, 's')
|
4
|
+
@plural(/s$/i, 's')
|
5
|
+
@plural(/^(ax|test)is$/i, '$1es')
|
6
|
+
@plural(/(octop|vir)us$/i, '$1i')
|
7
|
+
@plural(/(octop|vir)i$/i, '$1i')
|
8
|
+
@plural(/(alias|status)$/i, '$1es')
|
9
|
+
@plural(/(bu)s$/i, '$1ses')
|
10
|
+
@plural(/(buffal|tomat)o$/i, '$1oes')
|
11
|
+
@plural(/([ti])um$/i, '$1a')
|
12
|
+
@plural(/([ti])a$/i, '$1a')
|
13
|
+
@plural(/sis$/i, 'ses')
|
14
|
+
@plural(/(?:([^f])fe|([lr])f)$/i, '$1$2ves')
|
15
|
+
@plural(/(hive)$/i, '$1s')
|
16
|
+
@plural(/([^aeiouy]|qu)y$/i, '$1ies')
|
17
|
+
@plural(/(x|ch|ss|sh)$/i, '$1es')
|
18
|
+
@plural(/(matr|vert|ind)(?:ix|ex)$/i, '$1ices')
|
19
|
+
@plural(/^(m|l)ouse$/i, '$1ice')
|
20
|
+
@plural(/^(m|l)ice$/i, '$1ice')
|
21
|
+
@plural(/^(ox)$/i, '$1en')
|
22
|
+
@plural(/^(oxen)$/i, '$1')
|
23
|
+
@plural(/(quiz)$/i, '$1zes')
|
24
|
+
|
25
|
+
@singular(/s$/i, '')
|
26
|
+
@singular(/(ss)$/i, '$1')
|
27
|
+
@singular(/(n)ews$/i, '$1ews')
|
28
|
+
@singular(/([ti])a$/i, '$1um')
|
29
|
+
@singular(/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)(sis|ses)$/i, '$1sis')
|
30
|
+
@singular(/(^analy)(sis|ses)$/i, '$1sis')
|
31
|
+
@singular(/([^f])ves$/i, '$1fe')
|
32
|
+
@singular(/(hive)s$/i, '$1')
|
33
|
+
@singular(/(tive)s$/i, '$1')
|
34
|
+
@singular(/([lr])ves$/i, '$1f')
|
35
|
+
@singular(/([^aeiouy]|qu)ies$/i, '$1y')
|
36
|
+
@singular(/(s)eries$/i, '$1eries')
|
37
|
+
@singular(/(m)ovies$/i, '$1ovie')
|
38
|
+
@singular(/(x|ch|ss|sh)es$/i, '$1')
|
39
|
+
@singular(/^(m|l)ice$/i, '$1ouse')
|
40
|
+
@singular(/(bus)(es)?$/i, '$1')
|
41
|
+
@singular(/(o)es$/i, '$1')
|
42
|
+
@singular(/(shoe)s$/i, '$1')
|
43
|
+
@singular(/(cris|test)(is|es)$/i, '$1is')
|
44
|
+
@singular(/^(a)x[ie]s$/i, '$1xis')
|
45
|
+
@singular(/(octop|vir)(us|i)$/i, '$1us')
|
46
|
+
@singular(/(alias|status)(es)?$/i, '$1')
|
47
|
+
@singular(/^(ox)en/i, '$1')
|
48
|
+
@singular(/(vert|ind)ices$/i, '$1ex')
|
49
|
+
@singular(/(matr)ices$/i, '$1ix')
|
50
|
+
@singular(/(quiz)zes$/i, '$1')
|
51
|
+
@singular(/(database)s$/i, '$1')
|
52
|
+
|
53
|
+
@irregular('person', 'people')
|
54
|
+
@irregular('man', 'men')
|
55
|
+
@irregular('child', 'children')
|
56
|
+
@irregular('sex', 'sexes')
|
57
|
+
@irregular('move', 'moves')
|
58
|
+
@irregular('zombie', 'zombies')
|
59
|
+
|
60
|
+
@uncountable('equipment', 'information', 'rice', 'money', 'species', 'series', 'fish', 'sheep', 'jeans ', 'police')
|
61
|
+
|
62
|
+
@pastTense /^(.*)$/,'$1ed'
|
63
|
+
@pastTense /e$/,'ed'
|
64
|
+
@pastTense /t$/,'ted'
|
65
|
+
@pastTense /g$/,'gged'
|
66
|
+
@pastTense /ight$/,'ought'
|
67
|
+
@pastTense "buy",'bought'
|
68
|
+
@pastTense "has",'had'
|
69
|
+
@pastTense "sell",'sold'
|
70
|
+
@pastTense "is",'was'
|
71
|
+
@pastTense "are",'were'
|
72
|
+
@pastTense "teach",'taught'
|
73
|
+
@pastTense "feel",'felt'
|
74
|
+
@pastTense "light",'lit'
|
75
|
+
@pastTense "find",'found'
|
@@ -0,0 +1,235 @@
|
|
1
|
+
namespace('agt.inflector')
|
2
|
+
# Public: The `Inflector` transform words from singular to plural
|
3
|
+
# and verbs from present to past. The `agt.inflector` package is an instance
|
4
|
+
# of the `Inflector` class with default inflections for english words and verbs.
|
5
|
+
#
|
6
|
+
# ```coffeescript
|
7
|
+
# agt.inflector.config 'fr', ->
|
8
|
+
# @plural /$/, 's'
|
9
|
+
# @plural /^(bij|caill|ch|gen|hib|jouj|p)ou$/i, '$1oux'
|
10
|
+
# @plural /^(b|cor|ém|gemm|soupir|trav|vant|vitr)ail$/i, 'aux'
|
11
|
+
#
|
12
|
+
# @singular /s$/i, ''
|
13
|
+
# @singular /oux$/i, 'ou'
|
14
|
+
# @singular /aux$/i, 'ail'
|
15
|
+
#
|
16
|
+
# @uncountable 'discours', 'secours', 'souris'
|
17
|
+
#
|
18
|
+
# @pastTense /^a$/i, 'eu'
|
19
|
+
# @pastTense /^est$/i, 'fut'
|
20
|
+
#
|
21
|
+
# agt.inflector.pluralize('fr', 'coup') # 'coups'
|
22
|
+
# agt.inflector.pluralize('fr', 'hibou') # 'hiboux'
|
23
|
+
# agt.inflector.pluralize('fr', 'discours') # 'discours'
|
24
|
+
#
|
25
|
+
# agt.inflector.singularize('fr', 'hiboux') # 'hibou'
|
26
|
+
# agt.inflector.singularize('fr', 'coups') # 'coup'
|
27
|
+
# ```
|
28
|
+
class agt.inflector.Inflector
|
29
|
+
|
30
|
+
### Public ###
|
31
|
+
|
32
|
+
# Extends or defines the inflections for a given language.
|
33
|
+
#
|
34
|
+
# ```coffee
|
35
|
+
# inflector.config 'en', ->
|
36
|
+
# # ...
|
37
|
+
#
|
38
|
+
# inflector.config 'fr', ->
|
39
|
+
# # ...
|
40
|
+
#
|
41
|
+
# inflector.config 'de', ->
|
42
|
+
# # ...
|
43
|
+
# ```
|
44
|
+
#
|
45
|
+
# As the language is passed to the `config` function, the methods available
|
46
|
+
# inside the block doesn't require the `lang` argument as the `Inflector`
|
47
|
+
# methods does.
|
48
|
+
#
|
49
|
+
# lang - The language {String} to configurate.
|
50
|
+
# block - The configuration {Function} to call. The function is called
|
51
|
+
# with the inflector as the `this` object as well as the sole
|
52
|
+
# argument.
|
53
|
+
config: (lang, block) ->
|
54
|
+
scope =
|
55
|
+
plural: (m,r) => @plural(lang,m,r)
|
56
|
+
singular: (m,r) => @singular(lang,m,r)
|
57
|
+
irregular: (p,s) => @irregular(lang,p,s)
|
58
|
+
uncountable: (a...) => @uncountable(lang,a)
|
59
|
+
pastTense: (m,r) => @pastTense(lang,m,r)
|
60
|
+
|
61
|
+
block.call(scope, scope)
|
62
|
+
|
63
|
+
# Defines a pluralization inflection for the specified language.
|
64
|
+
#
|
65
|
+
# ```coffee
|
66
|
+
# inflector.plural 'fr', /$/, 's'
|
67
|
+
#
|
68
|
+
# inflector.plural 'fr', /(eu|eau|au)$/i, '$1x'
|
69
|
+
#
|
70
|
+
# inflector.plural 'fr', /^(bij|caill|ch|gen|hib|jouj|p)ou$/i, '$1oux'
|
71
|
+
# ```
|
72
|
+
#
|
73
|
+
# lang - The language {String} to configurate. Note that when inside
|
74
|
+
# a configuration block this parameter is automatically set.
|
75
|
+
# match - The {RegExp} or the {String} that match words. When a string
|
76
|
+
# is passed, the created regex is equivalent to `///^#{word}$///`.
|
77
|
+
# replace - The replacement {String}. Groups defined in the regex can be
|
78
|
+
# freely used.
|
79
|
+
plural: (lang, match, replace) ->
|
80
|
+
@default(lang, 'plural')
|
81
|
+
|
82
|
+
inflection = new agt.inflector.Inflection(match, replace)
|
83
|
+
@inflections[lang].plural.push(inflection)
|
84
|
+
|
85
|
+
|
86
|
+
# Defines a singularization inflection for the specified language.
|
87
|
+
#
|
88
|
+
# ```coffee
|
89
|
+
# inflector.singlular 'fr', /s$/, ''
|
90
|
+
#
|
91
|
+
# inflector.singlular 'fr', /^(eu|eau|au)x$/i, '$1'
|
92
|
+
#
|
93
|
+
# inflector.singlular 'fr', /oux$/i, 'ou'
|
94
|
+
# ```
|
95
|
+
#
|
96
|
+
# lang - The language {String} to configurate. Note that when inside
|
97
|
+
# a configuration block this parameter is automatically set.
|
98
|
+
# match - The {RegExp} or the {String} that match words. When a string
|
99
|
+
# is passed, the created regex is equivalent to `///^#{word}$///`.
|
100
|
+
# replace - The replacement {String}. Groups defined in the regex can be
|
101
|
+
# freely used.
|
102
|
+
singular: (lang, match, replace) ->
|
103
|
+
@default(lang, 'singular')
|
104
|
+
|
105
|
+
inflection = new agt.inflector.Inflection(match, replace)
|
106
|
+
@inflections[lang].singular.push(inflection)
|
107
|
+
|
108
|
+
# Defines an inflection for an irregular word which pluralization doesn't
|
109
|
+
# follow the general rules such as person and people in english.
|
110
|
+
#
|
111
|
+
# ```coffee
|
112
|
+
# inflector.irregular 'fr', 'ail', 'aulx'
|
113
|
+
# inflector.irregular 'fr', 'œuil', 'yeux'
|
114
|
+
# ```
|
115
|
+
#
|
116
|
+
# lang - The language {String} to configurate. Note that when inside
|
117
|
+
# a configuration block this parameter is automatically set.
|
118
|
+
# singular - The singular {String} for the irregular word.
|
119
|
+
# plural - The plural {String} for the irregular word.
|
120
|
+
irregular: (lang, singular, plural) ->
|
121
|
+
@default(lang, 'plural')
|
122
|
+
@default(lang, 'singular')
|
123
|
+
|
124
|
+
pluralInflection = new agt.inflector.Inflection(singular, plural)
|
125
|
+
singularInflection = new agt.inflector.Inflection(plural, singular)
|
126
|
+
@inflections[lang].singular.push(singularInflection)
|
127
|
+
@inflections[lang].plural.push(pluralInflection)
|
128
|
+
|
129
|
+
# Defines one or many uncountable words. Uncountable words have a single
|
130
|
+
# form and are always returned as is in both {::pluralize} and {::singularize}
|
131
|
+
# methods.
|
132
|
+
#
|
133
|
+
# ```coffee
|
134
|
+
# inflector.uncountable 'fr', ['discours', 'secours']
|
135
|
+
#
|
136
|
+
# inflector.config 'fr', ->
|
137
|
+
# @uncountable 'discours', 'secours'
|
138
|
+
# ```
|
139
|
+
#
|
140
|
+
# lang - The language {String} to configurate. Note that when inside
|
141
|
+
# a configuration block this parameter is automatically set.
|
142
|
+
# uncountables - The {Array} of uncountable {String}. When inside
|
143
|
+
# a configuration block, the uncountable words must be passed
|
144
|
+
# as a list of {String}.
|
145
|
+
uncountable: (lang, uncountables) ->
|
146
|
+
@default(lang, 'uncountable')
|
147
|
+
|
148
|
+
@inflections[lang].uncountable = @inflections[lang].uncountable.concat(uncountables)
|
149
|
+
|
150
|
+
# Defines an inflection to convert a verb from its present form to its past
|
151
|
+
# form.
|
152
|
+
#
|
153
|
+
# ```coffee
|
154
|
+
# inflector.pastTense 'fr', /e/i, 'é'
|
155
|
+
# inflector.pastTense 'fr', /est/i, 'était'
|
156
|
+
# ```
|
157
|
+
#
|
158
|
+
# lang - The language {String} to configurate. Note that when inside
|
159
|
+
# a configuration block this parameter is automatically set.
|
160
|
+
# match - The {RegExp} or the {String} that match words. When a string
|
161
|
+
# is passed, the created regex is equivalent to `///^#{word}$///`.
|
162
|
+
# replace - The replacement {String}. Groups defined in the regex can be
|
163
|
+
# freely used.
|
164
|
+
pastTense: (lang, match, replace) ->
|
165
|
+
@default(lang, 'past')
|
166
|
+
|
167
|
+
inflection = new agt.inflector.Inflection(match, replace)
|
168
|
+
@inflections[lang].past.push(inflection)
|
169
|
+
|
170
|
+
# Conversion Methods
|
171
|
+
|
172
|
+
# Returns the passed-in {String} in its pluralized form.
|
173
|
+
#
|
174
|
+
# string - The {String} to pluralize.
|
175
|
+
# lang - The language {String} to use.
|
176
|
+
#
|
177
|
+
# Returns a {String}.
|
178
|
+
pluralize: (string, lang='en') -> @inflect('plural', string, lang)
|
179
|
+
|
180
|
+
# Returns the passed-in {String} in its singularized form.
|
181
|
+
#
|
182
|
+
# string - The {String} to singularize.
|
183
|
+
# lang - The language {String} to use.
|
184
|
+
#
|
185
|
+
# Returns a {String}.
|
186
|
+
singularize: (string, lang='en') -> @inflect('singular', string, lang)
|
187
|
+
|
188
|
+
# Returns the passed-in {String} in its past form.
|
189
|
+
#
|
190
|
+
# string - The {String} to conjugate to the past.
|
191
|
+
# lang - The language {String} to use.
|
192
|
+
#
|
193
|
+
# Returns a {String}.
|
194
|
+
toPast: (string, lang='en') -> @inflect('past', string, lang)
|
195
|
+
|
196
|
+
### Internal ###
|
197
|
+
|
198
|
+
# Realizes the inflection for the passed-in string based on the specified
|
199
|
+
# conversion mode.
|
200
|
+
#
|
201
|
+
# conversion - The {String} kind of conversion to apply.
|
202
|
+
# string - The {String} to convert.
|
203
|
+
# lang - The language {String} to use.
|
204
|
+
#
|
205
|
+
# Returns a {String}.
|
206
|
+
inflect: (conversion, string, lang='en') ->
|
207
|
+
result = string
|
208
|
+
return result if string is '' or string in @inflections[lang].uncountable
|
209
|
+
|
210
|
+
inflections = @inflections[lang][conversion]
|
211
|
+
|
212
|
+
return result if not inflections? or inflections.length is 0
|
213
|
+
|
214
|
+
reversed = []
|
215
|
+
reversed.unshift(o) for o in inflections
|
216
|
+
|
217
|
+
reversed.some (inflection) ->
|
218
|
+
res = inflection.inflect(string)
|
219
|
+
result = res if res?
|
220
|
+
res
|
221
|
+
|
222
|
+
result
|
223
|
+
|
224
|
+
# Defines a new collection on the `inflections` object for the specified
|
225
|
+
# `lang`.
|
226
|
+
#
|
227
|
+
# lang - The target language {String}.
|
228
|
+
# collection - The {String} name of the collection to create.
|
229
|
+
default: (lang, collection)->
|
230
|
+
@inflections ||= {}
|
231
|
+
@inflections[lang] ||= {}
|
232
|
+
@inflections[lang][collection] ||= []
|
233
|
+
|
234
|
+
agt.inflector = new agt.inflector.Inflector
|
235
|
+
agt.inflector.Inflector = agt.inflector.constructor
|