govuk_frontend_toolkit 3.1.0 → 3.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/app/assets/CHANGELOG.md +4 -0
- data/app/assets/Gruntfile.js +4 -1
- data/app/assets/LICENCE +1 -1
- data/app/assets/README.md +29 -834
- data/app/assets/VERSION.txt +1 -1
- data/app/assets/docs/analytics.md +158 -0
- data/app/assets/docs/javascript.md +206 -0
- data/app/assets/docs/mixins.md +624 -0
- data/app/assets/javascripts/govuk/analytics/error-tracking.js +22 -0
- data/app/assets/javascripts/govuk/analytics/google-analytics-classic-tracker.js +111 -0
- data/app/assets/javascripts/govuk/analytics/google-analytics-universal-tracker.js +104 -0
- data/app/assets/javascripts/govuk/analytics/print-intent.js +31 -0
- data/app/assets/javascripts/govuk/analytics/tracker.js +61 -0
- data/app/assets/package.json +1 -1
- data/app/assets/spec/unit/MultivariateTestSpec.js +11 -11
- data/app/assets/spec/unit/SelectionButtonSpec.js +4 -4
- data/app/assets/spec/unit/analytics/GoogleAnalyticsClassicTrackerSpec.js +124 -0
- data/app/assets/spec/unit/analytics/GoogleAnalyticsUniversalTrackerSpec.js +122 -0
- data/app/assets/spec/unit/analytics/TrackerSpec.js +74 -0
- metadata +46 -15
@@ -0,0 +1,124 @@
|
|
1
|
+
describe("GOVUK.GoogleAnalyticsClassicTracker", function() {
|
2
|
+
var classic;
|
3
|
+
|
4
|
+
beforeEach(function() {
|
5
|
+
window._gaq = [];
|
6
|
+
classic = new GOVUK.GoogleAnalyticsClassicTracker('id', 'cookie-domain.com');
|
7
|
+
});
|
8
|
+
|
9
|
+
it('can load the libraries needed to run classic Google Analytics', function() {
|
10
|
+
delete window._gaq;
|
11
|
+
$('[src*="google-analytics.com/ga.js"]').remove();
|
12
|
+
|
13
|
+
GOVUK.GoogleAnalyticsClassicTracker.load();
|
14
|
+
expect($('script[async][src*="google-analytics.com/ga.js"]').length).toBe(1);
|
15
|
+
});
|
16
|
+
|
17
|
+
describe('when created', function() {
|
18
|
+
it('configures a Google tracker using the provided profile ID and cookie domain', function() {
|
19
|
+
expect(window._gaq[0]).toEqual(['_setAccount', 'id']);
|
20
|
+
expect(window._gaq[1]).toEqual(['_setDomainName', 'cookie-domain.com']);
|
21
|
+
});
|
22
|
+
|
23
|
+
it('allows cross site linking', function() {
|
24
|
+
expect(window._gaq[2]).toEqual(['_setAllowLinker', true]);
|
25
|
+
});
|
26
|
+
|
27
|
+
it('anonymises the IP', function() {
|
28
|
+
expect(window._gaq[3]).toEqual(['_gat._anonymizeIp']);
|
29
|
+
});
|
30
|
+
});
|
31
|
+
|
32
|
+
describe('when pageviews are tracked', function() {
|
33
|
+
beforeEach(function() {
|
34
|
+
// reset queue after setup
|
35
|
+
window._gaq = [];
|
36
|
+
});
|
37
|
+
|
38
|
+
it('sends them to Google Analytics', function() {
|
39
|
+
classic.trackPageview();
|
40
|
+
expect(window._gaq[0]).toEqual(['_trackPageview']);
|
41
|
+
});
|
42
|
+
|
43
|
+
it('can track a virtual pageview', function() {
|
44
|
+
classic.trackPageview('/nicholas-page');
|
45
|
+
expect(window._gaq[0]).toEqual(['_trackPageview', '/nicholas-page']);
|
46
|
+
});
|
47
|
+
});
|
48
|
+
|
49
|
+
describe('when events are tracked', function() {
|
50
|
+
beforeEach(function() {
|
51
|
+
// reset queue after setup
|
52
|
+
window._gaq = [];
|
53
|
+
});
|
54
|
+
|
55
|
+
it('sends them to Google Analytics', function() {
|
56
|
+
classic.trackEvent('category', 'action', {label: 'label'});
|
57
|
+
expect(window._gaq[0]).toEqual(['_trackEvent', 'category', 'action', 'label']);
|
58
|
+
});
|
59
|
+
|
60
|
+
it('the label is optional', function() {
|
61
|
+
classic.trackEvent('category', 'action');
|
62
|
+
expect(window._gaq[0]).toEqual(['_trackEvent', 'category', 'action']);
|
63
|
+
});
|
64
|
+
|
65
|
+
it('a value can be tracked if the label is omitted', function() {
|
66
|
+
classic.trackEvent('category', 'action', {value: 10});
|
67
|
+
expect(window._gaq[0]).toEqual(['_trackEvent', 'category', 'action', '', 10]);
|
68
|
+
});
|
69
|
+
|
70
|
+
it('only sends values if they are parseable as numbers', function() {
|
71
|
+
classic.trackEvent('category', 'action', {label: 'label', value: '10'});
|
72
|
+
expect(window._gaq[0]).toEqual(['_trackEvent', 'category', 'action', 'label', 10]);
|
73
|
+
|
74
|
+
classic.trackEvent('category', 'action', {label: 'label', value: 10});
|
75
|
+
expect(window._gaq[1]).toEqual(['_trackEvent', 'category', 'action', 'label', 10]);
|
76
|
+
|
77
|
+
classic.trackEvent('category', 'action', {label: 'label', value: 'not a number'});
|
78
|
+
expect(window._gaq[2]).toEqual(['_trackEvent', 'category', 'action', 'label']);
|
79
|
+
});
|
80
|
+
|
81
|
+
it('can mark an event as non interactive', function() {
|
82
|
+
classic.trackEvent('category', 'action', {label: 'label', value: 1, nonInteraction: true});
|
83
|
+
expect(window._gaq[0]).toEqual(['_trackEvent', 'category', 'action', 'label', 1, true]);
|
84
|
+
});
|
85
|
+
|
86
|
+
it('can mark an event as non interactive without a value', function() {
|
87
|
+
classic.trackEvent('category', 'action', {label: 'label', nonInteraction: true});
|
88
|
+
expect(window._gaq[0]).toEqual(['_trackEvent', 'category', 'action', 'label', 0, true]);
|
89
|
+
});
|
90
|
+
|
91
|
+
it('can mark an event as non interactive without a label or value', function() {
|
92
|
+
classic.trackEvent('category', 'action', {nonInteraction: true});
|
93
|
+
expect(window._gaq[0]).toEqual(['_trackEvent', 'category', 'action', '', 0, true]);
|
94
|
+
});
|
95
|
+
});
|
96
|
+
|
97
|
+
describe('when social events are tracked', function() {
|
98
|
+
beforeEach(function() {
|
99
|
+
window._gaq = [];
|
100
|
+
});
|
101
|
+
|
102
|
+
it('sends them to Google Analytics', function() {
|
103
|
+
classic.trackSocial('network', 'action', 'target');
|
104
|
+
expect(window._gaq[0]).toEqual(['_trackSocial', 'network', 'action', 'target']);
|
105
|
+
});
|
106
|
+
});
|
107
|
+
|
108
|
+
describe('when setting a custom variable', function() {
|
109
|
+
beforeEach(function() {
|
110
|
+
// reset queue after setup
|
111
|
+
window._gaq = [];
|
112
|
+
});
|
113
|
+
|
114
|
+
it('sends the variable to Google Analytics', function() {
|
115
|
+
classic.setCustomVariable(1, 'value', 'name', 10);
|
116
|
+
expect(window._gaq[0]).toEqual(['_setCustomVar', 1, 'name', 'value', 10]);
|
117
|
+
});
|
118
|
+
|
119
|
+
it('coerces the value to a string', function() {
|
120
|
+
classic.setCustomVariable(1, 100, 'name', 10);
|
121
|
+
expect(window._gaq[0]).toEqual(['_setCustomVar', 1, 'name', '100', 10]);
|
122
|
+
});
|
123
|
+
});
|
124
|
+
});
|
@@ -0,0 +1,122 @@
|
|
1
|
+
describe("GOVUK.GoogleAnalyticsUniversalTracker", function() {
|
2
|
+
var universal;
|
3
|
+
|
4
|
+
beforeEach(function() {
|
5
|
+
window.ga = function() {};
|
6
|
+
spyOn(window, 'ga');
|
7
|
+
universal = new GOVUK.GoogleAnalyticsUniversalTracker('id', 'cookie-domain.com');
|
8
|
+
});
|
9
|
+
|
10
|
+
it('can load the libraries needed to run universal Google Analytics', function() {
|
11
|
+
delete window.ga;
|
12
|
+
$('[src="//www.google-analytics.com/analytics.js"]').remove();
|
13
|
+
GOVUK.GoogleAnalyticsUniversalTracker.load();
|
14
|
+
expect($('script[async][src="//www.google-analytics.com/analytics.js"]').length).toBe(1);
|
15
|
+
expect(typeof window.ga).toBe('function');
|
16
|
+
|
17
|
+
window.ga('send message');
|
18
|
+
expect(window.ga.q[0]).toEqual(jasmine.any(Object));
|
19
|
+
});
|
20
|
+
|
21
|
+
describe('when created', function() {
|
22
|
+
var setupArguments;
|
23
|
+
|
24
|
+
beforeEach(function() {
|
25
|
+
setupArguments = window.ga.calls.allArgs();
|
26
|
+
});
|
27
|
+
|
28
|
+
it('configures a Google tracker using the provided profile ID and cookie domain', function() {
|
29
|
+
expect(setupArguments[0]).toEqual(['create', 'id', {'cookieDomain': 'cookie-domain.com'}]);
|
30
|
+
});
|
31
|
+
|
32
|
+
it('anonymises the IP', function() {
|
33
|
+
expect(setupArguments[1]).toEqual(['set', 'anonymizeIp', true]);
|
34
|
+
});
|
35
|
+
});
|
36
|
+
|
37
|
+
describe('when pageviews are tracked', function() {
|
38
|
+
it('sends them to Google Analytics', function() {
|
39
|
+
universal.trackPageview();
|
40
|
+
expect(window.ga.calls.mostRecent().args).toEqual(['send', 'pageview']);
|
41
|
+
});
|
42
|
+
|
43
|
+
it('can track a virtual pageview', function() {
|
44
|
+
universal.trackPageview('/nicholas-page');
|
45
|
+
expect(window.ga.calls.mostRecent().args).toEqual(['send', 'pageview', {page: '/nicholas-page'}]);
|
46
|
+
});
|
47
|
+
|
48
|
+
it('can track a virtual pageview with a custom title', function() {
|
49
|
+
universal.trackPageview('/nicholas-page', 'Nicholas Page');
|
50
|
+
expect(window.ga.calls.mostRecent().args).toEqual(['send', 'pageview', {page: '/nicholas-page', title: 'Nicholas Page'}]);
|
51
|
+
});
|
52
|
+
});
|
53
|
+
|
54
|
+
describe('when events are tracked', function() {
|
55
|
+
function eventObjectFromSpy() {
|
56
|
+
return window.ga.calls.mostRecent().args[1];
|
57
|
+
}
|
58
|
+
|
59
|
+
it('sends them to Google Analytics', function() {
|
60
|
+
universal.trackEvent('category', 'action', {label: 'label'});
|
61
|
+
expect(window.ga.calls.mostRecent().args).toEqual(
|
62
|
+
['send', {hitType: 'event', eventCategory: 'category', eventAction: 'action', eventLabel: 'label'}]
|
63
|
+
);
|
64
|
+
});
|
65
|
+
|
66
|
+
it('the label is optional', function() {
|
67
|
+
universal.trackEvent('category', 'action');
|
68
|
+
expect(window.ga.calls.mostRecent().args).toEqual(
|
69
|
+
['send', {hitType: 'event', eventCategory: 'category', eventAction: 'action'}]
|
70
|
+
);
|
71
|
+
});
|
72
|
+
|
73
|
+
it('only sends values if they are parseable as numbers', function() {
|
74
|
+
universal.trackEvent('category', 'action', {label: 'label', value: '10'});
|
75
|
+
expect(eventObjectFromSpy()['eventValue']).toEqual(10);
|
76
|
+
|
77
|
+
universal.trackEvent('category', 'action', {label: 'label', value: 10});
|
78
|
+
expect(eventObjectFromSpy()['eventValue']).toEqual(10);
|
79
|
+
|
80
|
+
universal.trackEvent('category', 'action', {label: 'label', value: 'not a number'});
|
81
|
+
expect(eventObjectFromSpy()['eventValue']).toEqual(undefined);
|
82
|
+
});
|
83
|
+
|
84
|
+
it('can mark an event as non interactive', function() {
|
85
|
+
universal.trackEvent('category', 'action', {label: 'label', value: 0, nonInteraction: true});
|
86
|
+
expect(window.ga.calls.mostRecent().args).toEqual(
|
87
|
+
['send', {
|
88
|
+
hitType: 'event',
|
89
|
+
eventCategory: 'category',
|
90
|
+
eventAction: 'action',
|
91
|
+
eventLabel: 'label',
|
92
|
+
eventValue: 0,
|
93
|
+
nonInteraction: 1
|
94
|
+
}]
|
95
|
+
);
|
96
|
+
});
|
97
|
+
});
|
98
|
+
|
99
|
+
describe('when social events are tracked', function() {
|
100
|
+
it('sends them to Google Analytics', function() {
|
101
|
+
universal.trackSocial('network', 'action', 'target');
|
102
|
+
expect(window.ga.calls.mostRecent().args).toEqual(['send', {
|
103
|
+
'hitType': 'social',
|
104
|
+
'socialNetwork': 'network',
|
105
|
+
'socialAction': 'action',
|
106
|
+
'socialTarget': 'target'
|
107
|
+
}]);
|
108
|
+
});
|
109
|
+
});
|
110
|
+
|
111
|
+
describe('when setting a custom dimension', function() {
|
112
|
+
it('sends the dimension to Google Analytics with the specified index and value', function() {
|
113
|
+
universal.setDimension(1, 'value');
|
114
|
+
expect(window.ga.calls.mostRecent().args).toEqual(['set', 'dimension1', 'value']);
|
115
|
+
});
|
116
|
+
|
117
|
+
it('coerces the value to a string', function() {
|
118
|
+
universal.setDimension(1, 10);
|
119
|
+
expect(window.ga.calls.mostRecent().args).toEqual(['set', 'dimension1', '10']);
|
120
|
+
});
|
121
|
+
});
|
122
|
+
});
|
@@ -0,0 +1,74 @@
|
|
1
|
+
describe("GOVUK.Tracker", function() {
|
2
|
+
var tracker;
|
3
|
+
|
4
|
+
beforeEach(function() {
|
5
|
+
window._gaq = [];
|
6
|
+
window.ga = function() {};
|
7
|
+
spyOn(window, 'ga');
|
8
|
+
this.config = {
|
9
|
+
universalId: 'universal-id',
|
10
|
+
classicId: 'classic-id',
|
11
|
+
cookieDomain: '.www.gov.uk'
|
12
|
+
};
|
13
|
+
});
|
14
|
+
|
15
|
+
describe('when created', function() {
|
16
|
+
var universalSetupArguments;
|
17
|
+
|
18
|
+
beforeEach(function () {
|
19
|
+
tracker = new GOVUK.Tracker(this.config);
|
20
|
+
universalSetupArguments = window.ga.calls.allArgs();
|
21
|
+
});
|
22
|
+
|
23
|
+
it('configures classic and universal trackers', function () {
|
24
|
+
expect(window._gaq[0]).toEqual(['_setAccount', 'classic-id']);
|
25
|
+
expect(window._gaq[1]).toEqual(['_setDomainName', '.www.gov.uk']);
|
26
|
+
expect(universalSetupArguments[0]).toEqual(['create', 'universal-id', {'cookieDomain': '.www.gov.uk'}]);
|
27
|
+
});
|
28
|
+
});
|
29
|
+
|
30
|
+
describe('when tracking pageviews, events and custom dimensions', function() {
|
31
|
+
|
32
|
+
beforeEach(function() {
|
33
|
+
tracker = new GOVUK.Tracker(this.config);
|
34
|
+
});
|
35
|
+
|
36
|
+
it('tracks in both classic and universal', function() {
|
37
|
+
window._gaq = [];
|
38
|
+
tracker.trackPageview('/path', 'Title');
|
39
|
+
expect(window._gaq[0]).toEqual(['_trackPageview', '/path']);
|
40
|
+
expect(window.ga.calls.mostRecent().args).toEqual(['send', 'pageview', {page: '/path', title: 'Title'}]);
|
41
|
+
|
42
|
+
window._gaq = [];
|
43
|
+
tracker.trackEvent('category', 'action');
|
44
|
+
expect(window._gaq[0]).toEqual(['_trackEvent', 'category', 'action']);
|
45
|
+
expect(window.ga.calls.mostRecent().args).toEqual(['send', {hitType: 'event', eventCategory: 'category', eventAction: 'action'}]);
|
46
|
+
|
47
|
+
window._gaq = [];
|
48
|
+
tracker.setDimension(1, 'value', 'name');
|
49
|
+
expect(window._gaq[0]).toEqual(['_setCustomVar', 1, 'name', 'value', 3]);
|
50
|
+
expect(window.ga.calls.mostRecent().args).toEqual(['set', 'dimension1', 'value']);
|
51
|
+
});
|
52
|
+
});
|
53
|
+
|
54
|
+
describe('when tracking social media shares', function() {
|
55
|
+
|
56
|
+
beforeEach(function() {
|
57
|
+
tracker = new GOVUK.Tracker(this.config);
|
58
|
+
});
|
59
|
+
|
60
|
+
it('tracks in both classic and universal', function() {
|
61
|
+
window._gaq = [];
|
62
|
+
tracker.trackShare('network');
|
63
|
+
|
64
|
+
expect(window._gaq[0]).toEqual(['_trackSocial', 'network', 'share', jasmine.any(String)]);
|
65
|
+
expect(window.ga.calls.mostRecent().args).toEqual(['send', {
|
66
|
+
hitType: 'social',
|
67
|
+
socialNetwork: 'network',
|
68
|
+
socialAction: 'share',
|
69
|
+
socialTarget: jasmine.any(String)
|
70
|
+
}]);
|
71
|
+
});
|
72
|
+
});
|
73
|
+
|
74
|
+
});
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: govuk_frontend_toolkit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.2.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2015-03-11 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rails
|
16
|
-
requirement:
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,15 @@ dependencies:
|
|
21
21
|
version: 3.1.0
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements:
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 3.1.0
|
25
30
|
- !ruby/object:Gem::Dependency
|
26
31
|
name: sass
|
27
|
-
requirement:
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
28
33
|
none: false
|
29
34
|
requirements:
|
30
35
|
- - ! '>='
|
@@ -32,29 +37,44 @@ dependencies:
|
|
32
37
|
version: 3.2.0
|
33
38
|
type: :runtime
|
34
39
|
prerelease: false
|
35
|
-
version_requirements:
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 3.2.0
|
36
46
|
- !ruby/object:Gem::Dependency
|
37
47
|
name: gem_publisher
|
38
|
-
requirement:
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
39
49
|
none: false
|
40
50
|
requirements:
|
41
|
-
- - =
|
51
|
+
- - '='
|
42
52
|
- !ruby/object:Gem::Version
|
43
53
|
version: 1.3.1
|
44
54
|
type: :development
|
45
55
|
prerelease: false
|
46
|
-
version_requirements:
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - '='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 1.3.1
|
47
62
|
- !ruby/object:Gem::Dependency
|
48
63
|
name: rake
|
49
|
-
requirement:
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
50
65
|
none: false
|
51
66
|
requirements:
|
52
|
-
- - =
|
67
|
+
- - '='
|
53
68
|
- !ruby/object:Gem::Version
|
54
69
|
version: 0.9.2.2
|
55
70
|
type: :development
|
56
71
|
prerelease: false
|
57
|
-
version_requirements:
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - '='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: 0.9.2.2
|
58
78
|
description:
|
59
79
|
email: bradley.wright@digital.cabinet-office.gov.uk
|
60
80
|
executables: []
|
@@ -84,6 +104,9 @@ files:
|
|
84
104
|
- app/assets/LICENCE
|
85
105
|
- app/assets/README.md
|
86
106
|
- app/assets/VERSION.txt
|
107
|
+
- app/assets/docs/analytics.md
|
108
|
+
- app/assets/docs/javascript.md
|
109
|
+
- app/assets/docs/mixins.md
|
87
110
|
- app/assets/images/accordian-arrow-2x.png
|
88
111
|
- app/assets/images/accordian-arrow.png
|
89
112
|
- app/assets/images/arrow-sprite.png
|
@@ -207,6 +230,11 @@ files:
|
|
207
230
|
- app/assets/images/player-icon-play.png
|
208
231
|
- app/assets/images/player-icon-rewind.png
|
209
232
|
- app/assets/images/player-icon-volume.png
|
233
|
+
- app/assets/javascripts/govuk/analytics/error-tracking.js
|
234
|
+
- app/assets/javascripts/govuk/analytics/google-analytics-classic-tracker.js
|
235
|
+
- app/assets/javascripts/govuk/analytics/google-analytics-universal-tracker.js
|
236
|
+
- app/assets/javascripts/govuk/analytics/print-intent.js
|
237
|
+
- app/assets/javascripts/govuk/analytics/tracker.js
|
210
238
|
- app/assets/javascripts/govuk/multivariate-test.js
|
211
239
|
- app/assets/javascripts/govuk/primary-links.js
|
212
240
|
- app/assets/javascripts/govuk/selection-buttons.js
|
@@ -227,6 +255,9 @@ files:
|
|
227
255
|
- app/assets/spec/unit/PrimaryLinksSpec.js
|
228
256
|
- app/assets/spec/unit/SelectionButtonSpec.js
|
229
257
|
- app/assets/spec/unit/StickAtTopWhenScrollingSpec.js
|
258
|
+
- app/assets/spec/unit/analytics/GoogleAnalyticsClassicTrackerSpec.js
|
259
|
+
- app/assets/spec/unit/analytics/GoogleAnalyticsUniversalTrackerSpec.js
|
260
|
+
- app/assets/spec/unit/analytics/TrackerSpec.js
|
230
261
|
- app/assets/stylesheets/.gitkeep
|
231
262
|
- app/assets/stylesheets/_colours.scss
|
232
263
|
- app/assets/stylesheets/_conditionals.scss
|
@@ -257,7 +288,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
257
288
|
version: '0'
|
258
289
|
segments:
|
259
290
|
- 0
|
260
|
-
hash: -
|
291
|
+
hash: -1949845834061421958
|
261
292
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
262
293
|
none: false
|
263
294
|
requirements:
|
@@ -266,10 +297,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
266
297
|
version: '0'
|
267
298
|
segments:
|
268
299
|
- 0
|
269
|
-
hash: -
|
300
|
+
hash: -1949845834061421958
|
270
301
|
requirements: []
|
271
302
|
rubyforge_project:
|
272
|
-
rubygems_version: 1.8.
|
303
|
+
rubygems_version: 1.8.23
|
273
304
|
signing_key:
|
274
305
|
specification_version: 3
|
275
306
|
summary: Tools for building frontend applications
|