pinball_wizard 0.0.1.pre → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -13
- data/.gitignore +9 -0
- data/CHANGELOG.md +6 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +32 -0
- data/LICENSE +21 -0
- data/README.md +336 -0
- data/Rakefile +4 -0
- data/bower.json +14 -0
- data/dist/css_tagger.js +42 -0
- data/dist/css_tagger.min.js +3 -0
- data/dist/pinball_wizard.js +227 -0
- data/gulpfile.js +40 -0
- data/karma.conf.js +66 -0
- data/lib/pinball_wizard.rb +5 -0
- data/lib/pinball_wizard/configuration.rb +17 -0
- data/lib/pinball_wizard/dsl.rb +38 -0
- data/lib/pinball_wizard/feature.rb +52 -0
- data/lib/pinball_wizard/helpers/hash.rb +26 -0
- data/lib/pinball_wizard/null_feature.rb +7 -0
- data/lib/pinball_wizard/railtie.rb +9 -0
- data/lib/pinball_wizard/registry.rb +44 -0
- data/lib/pinball_wizard/version.rb +3 -0
- data/lib/pinball_wizard/view_helpers/rails.rb +13 -0
- data/lib/pinball_wizard/view_helpers/sinatra/slim.rb +15 -0
- data/package.json +45 -0
- data/pinball_wizard.gemspec +20 -0
- data/spec/pinball_wizard/dsl_spec.rb +73 -0
- data/spec/pinball_wizard/feature_spec.rb +89 -0
- data/spec/pinball_wizard/registry_spec.rb +56 -0
- data/src/css_tagger.coffee +44 -0
- data/src/pinball_wizard.coffee +157 -0
- data/test/spec/css_tagger_spec.coffee +50 -0
- data/test/spec/pinball_wizard_spec.coffee +268 -0
- data/test/test-main.coffee +25 -0
- metadata +47 -10
data/bower.json
ADDED
data/dist/css_tagger.js
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
(function() {
|
2
|
+
define(function() {
|
3
|
+
return function(ele, pinballQueue, searchQuery) {
|
4
|
+
var add, classNames, entry, feature, featureNames, matches, state, _i, _j, _len, _len1, _ref;
|
5
|
+
classNames = [];
|
6
|
+
add = function(name) {
|
7
|
+
return classNames.push('use-' + name.split('_').join('-'));
|
8
|
+
};
|
9
|
+
for (_i = 0, _len = pinballQueue.length; _i < _len; _i++) {
|
10
|
+
entry = pinballQueue[_i];
|
11
|
+
if (!entry.length) {
|
12
|
+
continue;
|
13
|
+
}
|
14
|
+
switch (entry[0]) {
|
15
|
+
case 'activate':
|
16
|
+
add(entry[1]);
|
17
|
+
break;
|
18
|
+
case 'add':
|
19
|
+
_ref = entry[1];
|
20
|
+
for (feature in _ref) {
|
21
|
+
state = _ref[feature];
|
22
|
+
if (state === 'active') {
|
23
|
+
add(feature);
|
24
|
+
}
|
25
|
+
}
|
26
|
+
}
|
27
|
+
}
|
28
|
+
matches = searchQuery.match(/pinball=([a-z-_,]+)/i);
|
29
|
+
if (matches && matches.length > 1) {
|
30
|
+
featureNames = (matches[1] + '').split(',');
|
31
|
+
for (_j = 0, _len1 = featureNames.length; _j < _len1; _j++) {
|
32
|
+
feature = featureNames[_j];
|
33
|
+
add(feature);
|
34
|
+
}
|
35
|
+
}
|
36
|
+
if (ele) {
|
37
|
+
ele.className += ' ' + classNames.join(' ');
|
38
|
+
}
|
39
|
+
};
|
40
|
+
});
|
41
|
+
|
42
|
+
}).call(this);
|
@@ -0,0 +1,3 @@
|
|
1
|
+
// Minified on http://closure-compiler.appspot.com/ using Advanced settings
|
2
|
+
|
3
|
+
(function(g,d,e){var f,h,b,a,c,l,k;h=[];f=function(a){h.push("use-"+a.split("_").join("-"))};c=0;for(l=d.length;c<l;c++)if(b=d[c],b.length)switch(b[0]){case "activate":f(b[1]);break;case "add":for(a in k=b[1],k)b=k[a],"active"===b&&f(a)}if((a=e.match(/pinball=([a-z-_,]+)/i))&&1<a.length)for(d=(a[1]+"").split(","),e=0,c=d.length;e<c;e++)a=d[e],f(a);g&&(g.className+=" "+h.join(" "))})(document.documentElement,window.pinball,window.location.search);
|
@@ -0,0 +1,227 @@
|
|
1
|
+
(function() {
|
2
|
+
'use strict';
|
3
|
+
var __slice = [].slice;
|
4
|
+
|
5
|
+
define(function() {
|
6
|
+
var activate, add, addCSSClassName, cssClassName, deactivate, debug, exports, features, get, isActive, logPrefix, push, removeCSSClassName, reset, showLog, state, subscribe, subscribers, update, urlValues, _buildSubscriber, _log, _notifySubscriberOnActivate, _notifySubscribersOnActivate, _notifySubscribersOnDeactivate, _urlValueMatches, _urlValues;
|
7
|
+
features = {};
|
8
|
+
subscribers = {};
|
9
|
+
showLog = false;
|
10
|
+
logPrefix = '[PinballWizard]';
|
11
|
+
_log = function() {
|
12
|
+
var args, message;
|
13
|
+
message = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
|
14
|
+
if (showLog && window.console && window.console.log) {
|
15
|
+
console.log.apply(console, ["" + logPrefix + " " + message].concat(__slice.call(args)));
|
16
|
+
}
|
17
|
+
};
|
18
|
+
_notifySubscribersOnActivate = function(name) {
|
19
|
+
var subscriber, _i, _len, _ref, _results;
|
20
|
+
if (subscribers[name] == null) {
|
21
|
+
subscribers[name] = [];
|
22
|
+
}
|
23
|
+
_ref = subscribers[name];
|
24
|
+
_results = [];
|
25
|
+
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
26
|
+
subscriber = _ref[_i];
|
27
|
+
_results.push(_notifySubscriberOnActivate(subscriber, name));
|
28
|
+
}
|
29
|
+
return _results;
|
30
|
+
};
|
31
|
+
_notifySubscriberOnActivate = function(subscriber, name) {
|
32
|
+
_log('Notify subscriber that %s is active', name);
|
33
|
+
return subscriber.onActivate();
|
34
|
+
};
|
35
|
+
_notifySubscribersOnDeactivate = function(name) {
|
36
|
+
var subscriber, _i, _len, _ref, _results;
|
37
|
+
if (subscribers[name] == null) {
|
38
|
+
subscribers[name] = [];
|
39
|
+
}
|
40
|
+
_ref = subscribers[name];
|
41
|
+
_results = [];
|
42
|
+
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
43
|
+
subscriber = _ref[_i];
|
44
|
+
_results.push(subscriber.onDeactivate());
|
45
|
+
}
|
46
|
+
return _results;
|
47
|
+
};
|
48
|
+
_urlValueMatches = function(value) {
|
49
|
+
var v, _i, _len, _ref;
|
50
|
+
_ref = _urlValues();
|
51
|
+
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
52
|
+
v = _ref[_i];
|
53
|
+
if (value === v) {
|
54
|
+
return true;
|
55
|
+
}
|
56
|
+
}
|
57
|
+
return false;
|
58
|
+
};
|
59
|
+
_urlValues = function(search) {
|
60
|
+
var key, pair, pairs, value, _i, _len, _ref;
|
61
|
+
if (search == null) {
|
62
|
+
search = window.location.search;
|
63
|
+
}
|
64
|
+
pairs = search.substr(1).split('&');
|
65
|
+
for (_i = 0, _len = pairs.length; _i < _len; _i++) {
|
66
|
+
pair = pairs[_i];
|
67
|
+
_ref = pair.split('='), key = _ref[0], value = _ref[1];
|
68
|
+
if (key === 'pinball' && (value != null)) {
|
69
|
+
return value.split(',');
|
70
|
+
}
|
71
|
+
}
|
72
|
+
return [];
|
73
|
+
};
|
74
|
+
urlValues = _urlValues();
|
75
|
+
cssClassName = function(name, prefix) {
|
76
|
+
if (prefix == null) {
|
77
|
+
prefix = 'use-';
|
78
|
+
}
|
79
|
+
return prefix + name.split('_').join('-');
|
80
|
+
};
|
81
|
+
addCSSClassName = function(name, ele) {
|
82
|
+
var cN;
|
83
|
+
if (ele == null) {
|
84
|
+
ele = document.documentElement;
|
85
|
+
}
|
86
|
+
cN = cssClassName(name);
|
87
|
+
if (ele.className.indexOf(cN) < 0) {
|
88
|
+
return ele.className += ' ' + cN;
|
89
|
+
}
|
90
|
+
};
|
91
|
+
removeCSSClassName = function(name, ele) {
|
92
|
+
var cN;
|
93
|
+
if (ele == null) {
|
94
|
+
ele = document.documentElement;
|
95
|
+
}
|
96
|
+
cN = cssClassName(name);
|
97
|
+
if (ele.className.indexOf(cN) >= 0) {
|
98
|
+
return ele.className = ele.className.replace(cN, '');
|
99
|
+
}
|
100
|
+
};
|
101
|
+
add = function(list) {
|
102
|
+
var name, state, _results;
|
103
|
+
_results = [];
|
104
|
+
for (name in list) {
|
105
|
+
state = list[name];
|
106
|
+
features[name] = state;
|
107
|
+
_log("Added %s: %s.", name, state);
|
108
|
+
if (isActive(name)) {
|
109
|
+
_results.push(activate(name, "automatic. added as '" + state + "'"));
|
110
|
+
} else if (_urlValueMatches(name, urlValues)) {
|
111
|
+
_results.push(activate(name, 'URL'));
|
112
|
+
} else {
|
113
|
+
_results.push(void 0);
|
114
|
+
}
|
115
|
+
}
|
116
|
+
return _results;
|
117
|
+
};
|
118
|
+
get = function(name) {
|
119
|
+
return features[name];
|
120
|
+
};
|
121
|
+
update = function(name, state) {
|
122
|
+
return features[name] = state;
|
123
|
+
};
|
124
|
+
activate = function(name, sourceName) {
|
125
|
+
var source, state;
|
126
|
+
if (sourceName == null) {
|
127
|
+
sourceName = null;
|
128
|
+
}
|
129
|
+
state = get(name);
|
130
|
+
source = sourceName != null ? " (source: " + sourceName + ")" : '';
|
131
|
+
switch (state) {
|
132
|
+
case void 0:
|
133
|
+
return _log("Attempted to activate %s, but it was not found%s.", name, source);
|
134
|
+
case 'inactive':
|
135
|
+
_log("Activate %s%s.", name, source);
|
136
|
+
update(name, 'active');
|
137
|
+
addCSSClassName(name);
|
138
|
+
return _notifySubscribersOnActivate(name);
|
139
|
+
case 'active':
|
140
|
+
return _log("Attempted to activate %s, but it is already active%s.", name, source);
|
141
|
+
default:
|
142
|
+
return _log("Attempted to activate %s, but it is %s%s.", name, state, source);
|
143
|
+
}
|
144
|
+
};
|
145
|
+
deactivate = function(name, source) {
|
146
|
+
var state;
|
147
|
+
if (source == null) {
|
148
|
+
source = null;
|
149
|
+
}
|
150
|
+
state = get(name);
|
151
|
+
source = typeof sourceName !== "undefined" && sourceName !== null ? " (source: " + sourceName + ")" : '';
|
152
|
+
switch (state) {
|
153
|
+
case void 0:
|
154
|
+
return _log("Attempted to deactivate %s, but it was not found%s.", name, source);
|
155
|
+
case 'active':
|
156
|
+
_log("Dectivate %s%s.", name, source);
|
157
|
+
update(name, 'inactive');
|
158
|
+
removeCSSClassName(name);
|
159
|
+
return _notifySubscribersOnDeactivate(name);
|
160
|
+
default:
|
161
|
+
return _log("Attempted to deactivate %s, but it is %s%s.", name, state, source);
|
162
|
+
}
|
163
|
+
};
|
164
|
+
isActive = function(name) {
|
165
|
+
return get(name) === 'active';
|
166
|
+
};
|
167
|
+
_buildSubscriber = function(onActivate, onDeactivate) {
|
168
|
+
return {
|
169
|
+
onActivate: onActivate != null ? onActivate : function() {},
|
170
|
+
onDeactivate: onDeactivate != null ? onDeactivate : function() {}
|
171
|
+
};
|
172
|
+
};
|
173
|
+
subscribe = function(name, onActivate, onDeactivate) {
|
174
|
+
var subscriber;
|
175
|
+
_log('Added subscriber to %s', name);
|
176
|
+
subscriber = _buildSubscriber(onActivate, onDeactivate);
|
177
|
+
if (subscribers[name] == null) {
|
178
|
+
subscribers[name] = [];
|
179
|
+
}
|
180
|
+
subscribers[name].push(subscriber);
|
181
|
+
if (isActive(name)) {
|
182
|
+
return _notifySubscriberOnActivate(subscriber, name);
|
183
|
+
}
|
184
|
+
};
|
185
|
+
push = function(params) {
|
186
|
+
var method;
|
187
|
+
method = params.shift();
|
188
|
+
return this[method].apply(this, params);
|
189
|
+
};
|
190
|
+
state = function() {
|
191
|
+
return features;
|
192
|
+
};
|
193
|
+
reset = function() {
|
194
|
+
return features = {};
|
195
|
+
};
|
196
|
+
debug = function() {
|
197
|
+
return showLog = true;
|
198
|
+
};
|
199
|
+
exports = {
|
200
|
+
add: add,
|
201
|
+
get: get,
|
202
|
+
activate: activate,
|
203
|
+
deactivate: deactivate,
|
204
|
+
isActive: isActive,
|
205
|
+
subscribe: subscribe,
|
206
|
+
push: push,
|
207
|
+
state: state,
|
208
|
+
reset: reset,
|
209
|
+
debug: debug,
|
210
|
+
cssClassName: cssClassName,
|
211
|
+
addCSSClassName: addCSSClassName,
|
212
|
+
removeCSSClassName: removeCSSClassName,
|
213
|
+
_urlValues: _urlValues
|
214
|
+
};
|
215
|
+
if (typeof window !== "undefined" && window !== null ? window.pinball : void 0) {
|
216
|
+
if (_urlValueMatches('debug')) {
|
217
|
+
debug();
|
218
|
+
}
|
219
|
+
while (window.pinball.length) {
|
220
|
+
exports.push(window.pinball.shift());
|
221
|
+
}
|
222
|
+
window.pinball = exports;
|
223
|
+
}
|
224
|
+
return exports;
|
225
|
+
});
|
226
|
+
|
227
|
+
}).call(this);
|
data/gulpfile.js
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
var gulp = require('gulp');
|
4
|
+
var coffee = require('gulp-coffee')
|
5
|
+
var gutil = require('gulp-util')
|
6
|
+
var sourcemaps = require('gulp-sourcemaps')
|
7
|
+
var del = require('del');
|
8
|
+
|
9
|
+
gulp.task('clean-dist', function (cb) {
|
10
|
+
del('dist/', cb);
|
11
|
+
});
|
12
|
+
|
13
|
+
gulp.task('dist', ['clean-dist'], function() {
|
14
|
+
gulp.src('src/**/*.coffee')
|
15
|
+
.pipe(coffee().on('error', gutil.log))
|
16
|
+
.pipe(gulp.dest('dist/'));
|
17
|
+
});
|
18
|
+
|
19
|
+
gulp.task('coffee', function() {
|
20
|
+
gulp.src('src/**/*.coffee')
|
21
|
+
.pipe(sourcemaps.init())
|
22
|
+
.pipe(coffee().on('error', gutil.log))
|
23
|
+
.pipe(sourcemaps.write())
|
24
|
+
.pipe(gulp.dest('.tmp/dist/'));
|
25
|
+
});
|
26
|
+
|
27
|
+
gulp.task('coffee-spec', function() {
|
28
|
+
gulp.src('test/**/*.coffee')
|
29
|
+
.pipe(sourcemaps.init())
|
30
|
+
.pipe(coffee().on('error', gutil.log))
|
31
|
+
.pipe(sourcemaps.write())
|
32
|
+
.pipe(gulp.dest('.tmp/test/'));
|
33
|
+
});
|
34
|
+
|
35
|
+
gulp.task('build', ['coffee','coffee-spec','dist']);
|
36
|
+
|
37
|
+
gulp.task('default', ['build'], function () {
|
38
|
+
gulp.watch('src/**/*.coffee', ['coffee','dist']);
|
39
|
+
gulp.watch('test/**/*.coffee', ['coffee-spec']);
|
40
|
+
});
|
data/karma.conf.js
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
// Karma configuration
|
2
|
+
// Generated on Tue Jan 13 2015 13:14:05 GMT-0500 (EST)
|
3
|
+
|
4
|
+
module.exports = function(config) {
|
5
|
+
config.set({
|
6
|
+
|
7
|
+
// base path that will be used to resolve all patterns (eg. files, exclude)
|
8
|
+
basePath: '.tmp/',
|
9
|
+
|
10
|
+
// frameworks to use
|
11
|
+
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
|
12
|
+
frameworks: ['jasmine','requirejs'],
|
13
|
+
|
14
|
+
|
15
|
+
// list of files / patterns to load in the browser
|
16
|
+
files: [
|
17
|
+
{pattern: 'dist/**/*.js', included: false},
|
18
|
+
{pattern: 'test/spec/**/*_spec.js', included: false},
|
19
|
+
|
20
|
+
'test/test-main.js'
|
21
|
+
],
|
22
|
+
|
23
|
+
// list of files to exclude
|
24
|
+
exclude: [
|
25
|
+
],
|
26
|
+
|
27
|
+
|
28
|
+
// preprocess matching files before serving them to the browser
|
29
|
+
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
|
30
|
+
preprocessors: {
|
31
|
+
},
|
32
|
+
|
33
|
+
|
34
|
+
// test results reporter to use
|
35
|
+
// possible values: 'dots', 'progress'
|
36
|
+
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
|
37
|
+
reporters: ['progress'],
|
38
|
+
|
39
|
+
|
40
|
+
// web server port
|
41
|
+
port: 9876,
|
42
|
+
|
43
|
+
|
44
|
+
// enable / disable colors in the output (reporters and logs)
|
45
|
+
colors: true,
|
46
|
+
|
47
|
+
|
48
|
+
// level of logging
|
49
|
+
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
|
50
|
+
logLevel: config.LOG_INFO,
|
51
|
+
|
52
|
+
|
53
|
+
// enable / disable watching file and executing tests whenever any file changes
|
54
|
+
autoWatch: true,
|
55
|
+
|
56
|
+
|
57
|
+
// start these browsers
|
58
|
+
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
|
59
|
+
browsers: ['Chrome'],
|
60
|
+
|
61
|
+
|
62
|
+
// Continuous Integration mode
|
63
|
+
// if true, Karma captures browsers, runs the tests and exits
|
64
|
+
singleRun: false
|
65
|
+
});
|
66
|
+
};
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module PinballWizard
|
2
|
+
def self.configuration
|
3
|
+
@configuration ||= Configuration.new
|
4
|
+
end
|
5
|
+
|
6
|
+
def self.configure
|
7
|
+
yield(configuration)
|
8
|
+
end
|
9
|
+
|
10
|
+
class Configuration
|
11
|
+
attr_accessor :class_patterns
|
12
|
+
|
13
|
+
def initialize(class_patterns = {})
|
14
|
+
@class_patterns = class_patterns
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'pinball_wizard/helpers/hash'
|
2
|
+
|
3
|
+
module PinballWizard
|
4
|
+
module DSL
|
5
|
+
def self.build(config = PinballWizard.configuration, &block)
|
6
|
+
builder = Builder.new(config)
|
7
|
+
builder.instance_eval(&block)
|
8
|
+
builder
|
9
|
+
end
|
10
|
+
|
11
|
+
class Builder
|
12
|
+
attr_reader :config
|
13
|
+
|
14
|
+
def initialize(config)
|
15
|
+
@config = config
|
16
|
+
end
|
17
|
+
|
18
|
+
def feature(name, *options)
|
19
|
+
options = Helpers::Hash.normalize_options(options)
|
20
|
+
feature = build_feature(name, options)
|
21
|
+
Registry.add(feature)
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def build_feature(name, options)
|
27
|
+
build_from_class_pattern(name, options) || Feature.new(name, options)
|
28
|
+
end
|
29
|
+
|
30
|
+
def build_from_class_pattern(name, options)
|
31
|
+
config.class_patterns.each_pair do |key, klass|
|
32
|
+
return klass.new(name, options) if options.keys.include?(key)
|
33
|
+
end
|
34
|
+
false
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|