ui_alchemy-rails 1.0.5 → 1.0.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -108,3 +108,7 @@ $spritePath: image-url("alchemy/icons/action-icons.png");
108
108
  .left_arrow_icon-grey { background-position: -656px 0; }
109
109
  .selector_icon-grey { background-position: -672px 0; }
110
110
  .validation_icon-grey { background-position: -688px 0; }
111
+
112
+ //White Icons
113
+ .validation_icon-white { background-position: -704px -16px; }
114
+ .arrow_icon-white { background-position: -719px -16px; }
@@ -1,5 +1,5 @@
1
1
  module UIAlchemy
2
2
  module Rails
3
- VERSION = "1.0.5"
3
+ VERSION = "1.0.6"
4
4
  end
5
5
  end
@@ -0,0 +1,275 @@
1
+ /* Will be compiled down to a single stylesheet with your sass files */
2
+ /* line 9, ../../component/styles/header.scss */
3
+ .left {
4
+ float: left;
5
+ }
6
+
7
+ /* line 10, ../../component/styles/header.scss */
8
+ .right {
9
+ float: right;
10
+ }
11
+
12
+ /* line 12, ../../component/styles/header.scss */
13
+ .logo-header {
14
+ height: 25px;
15
+ background-color: #cc8400;
16
+ z-index: 100;
17
+ line-height: 25px;
18
+ }
19
+ /* line 20, ../../component/styles/header.scss */
20
+ .logo-header .logo {
21
+ margin-left: 30px;
22
+ }
23
+ /* line 24, ../../component/styles/header.scss */
24
+ .logo-header .menu-container {
25
+ line-height: 25px;
26
+ }
27
+ /* line 27, ../../component/styles/header.scss */
28
+ .logo-header .menu-container .menu-item {
29
+ line-height: 25px;
30
+ }
31
+ /* line 30, ../../component/styles/header.scss */
32
+ .logo-header .menu-container .menu-item .menu-item-link {
33
+ white-space: nowrap;
34
+ text-overflow: ellipsis;
35
+ -webkit-transition: all 0.15s ease-in;
36
+ -moz-transition: all 0.15s ease-in;
37
+ -o-transition: all 0.15s ease-in;
38
+ transition: all 0.15s ease-in;
39
+ text-align: center;
40
+ text-transform: capitalize;
41
+ font-family: overpass, sans-serif, sans;
42
+ text-decoration: none;
43
+ margin: 0 auto;
44
+ }
45
+ /* line 40, ../../component/styles/header.scss */
46
+ .logo-header .menu-container .menu-item .menu-item-link:hover {
47
+ -webkit-transition: all 0.3s ease-in-out;
48
+ -moz-transition: all 0.3s ease-in-out;
49
+ -o-transition: all 0.3s ease-in-out;
50
+ transition: all 0.3s ease-in-out;
51
+ color: #e6e6e6;
52
+ background: #996300;
53
+ }
54
+ /* line 47, ../../component/styles/header.scss */
55
+ .logo-header .menu-container .menu-item .menu-item-link.active-item {
56
+ color: #e6e6e6;
57
+ background: #996300;
58
+ }
59
+ /* line 55, ../../component/styles/header.scss */
60
+ .logo-header .dropdown-active {
61
+ box-shadow: none;
62
+ }
63
+
64
+ /* line 60, ../../component/styles/header.scss */
65
+ .nav-header {
66
+ min-height: 40px;
67
+ background: orange;
68
+ border-top: 1px solid #ffb733;
69
+ }
70
+ /* line 65, ../../component/styles/header.scss */
71
+ .nav-header .menu-item {
72
+ font-family: Overpass;
73
+ line-height: 37px;
74
+ vertical-align: baseline;
75
+ font-size: 14px;
76
+ position: relative;
77
+ }
78
+ /* line 72, ../../component/styles/header.scss */
79
+ .nav-header .menu-item .menu-item-link {
80
+ -webkit-transition: all 0.15s ease-in;
81
+ -moz-transition: all 0.15s ease-in;
82
+ -o-transition: all 0.15s ease-in;
83
+ transition: all 0.15s ease-in;
84
+ white-space: nowrap;
85
+ text-overflow: ellipsis;
86
+ text-align: center;
87
+ text-transform: capitalize;
88
+ font-family: overpass, sans-serif, sans;
89
+ text-decoration: none;
90
+ margin: 0 auto;
91
+ color: black;
92
+ }
93
+ /* line 83, ../../component/styles/header.scss */
94
+ .nav-header .menu-item .menu-item-link:hover {
95
+ -webkit-transition: all 0.15s ease-in-out;
96
+ -moz-transition: all 0.15s ease-in-out;
97
+ -o-transition: all 0.15s ease-in-out;
98
+ transition: all 0.15s ease-in-out;
99
+ border-bottom: 3px solid #ffdb99;
100
+ color: #e6e6e6;
101
+ background: #cc8400;
102
+ box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);
103
+ }
104
+ /* line 91, ../../component/styles/header.scss */
105
+ .nav-header .menu-item .menu-item-link.active-item {
106
+ box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);
107
+ color: #e6e6e6;
108
+ border-bottom: 3px solid #ffdb99;
109
+ background: #cc8400;
110
+ }
111
+
112
+ /* line 101, ../../component/styles/header.scss */
113
+ .menu-container {
114
+ position: relative;
115
+ left: 0;
116
+ display: block;
117
+ float: left;
118
+ margin: 0;
119
+ list-style: none;
120
+ line-height: 40px;
121
+ }
122
+ /* line 110, ../../component/styles/header.scss */
123
+ .menu-container .menu-item {
124
+ line-height: 37px;
125
+ position: relative;
126
+ margin: 0;
127
+ float: left;
128
+ }
129
+ /* line 116, ../../component/styles/header.scss */
130
+ .menu-container .menu-item .menu-item-link {
131
+ float: none;
132
+ padding: 0 20px;
133
+ text-decoration: none;
134
+ display: block;
135
+ cursor: default;
136
+ -webkit-box-sizing: border-box;
137
+ -moz-box-sizing: border-box;
138
+ box-sizing: border-box;
139
+ }
140
+
141
+ /* line 127, ../../component/styles/header.scss */
142
+ .menu-dropdown {
143
+ background: white;
144
+ position: absolute;
145
+ z-index: 1;
146
+ }
147
+
148
+ /* line 133, ../../component/styles/header.scss */
149
+ .compact {
150
+ position: fixed;
151
+ vertical-align: middle;
152
+ top: 0;
153
+ padding: 0;
154
+ margin: 0;
155
+ width: 100%;
156
+ z-index: 100;
157
+ }
158
+
159
+ /* line 143, ../../component/styles/header.scss */
160
+ .right .menu-item .dropdown {
161
+ right: -1px;
162
+ }
163
+
164
+ /* line 148, ../../component/styles/header.scss */
165
+ .dropdown {
166
+ position: absolute;
167
+ top: 100%;
168
+ left: -1px;
169
+ float: left;
170
+ min-width: 200px;
171
+ display: none;
172
+ list-style: none;
173
+ border-radius: 0 0 5px 5px;
174
+ padding: 0;
175
+ z-index: 3;
176
+ -webkit-box-sizing: border-box;
177
+ -moz-box-sizing: border-box;
178
+ box-sizing: border-box;
179
+ border: 1px solid #C8C8C8;
180
+ border-top: none;
181
+ box-shadow: 0px 1px 5px #C8C8C8;
182
+ background: white;
183
+ opacity: 1;
184
+ font-family: "Liberation-sans";
185
+ }
186
+ /* line 171, ../../component/styles/header.scss */
187
+ .dropdown li {
188
+ text-align: left;
189
+ line-height: 35px;
190
+ position: relative;
191
+ display: block;
192
+ clear: both;
193
+ }
194
+ /* line 178, ../../component/styles/header.scss */
195
+ .dropdown li a, .dropdown li a:visited, .dropdown li a:active, .dropdown li a:link {
196
+ color: #000;
197
+ text-decoration: none;
198
+ display: block;
199
+ padding: 5px 0px 5px 20px;
200
+ }
201
+ /* line 185, ../../component/styles/header.scss */
202
+ .dropdown li:hover {
203
+ background: black;
204
+ }
205
+ /* line 188, ../../component/styles/header.scss */
206
+ .dropdown li:hover .dropdown-menu-item-link {
207
+ text-decoration: none;
208
+ color: #e6e6e6;
209
+ }
210
+
211
+ /* line 196, ../../component/styles/header.scss */
212
+ .dropdown-left {
213
+ left: 0;
214
+ }
215
+
216
+ /* line 200, ../../component/styles/header.scss */
217
+ .dropdown-right {
218
+ right: 0;
219
+ left: auto;
220
+ }
221
+
222
+ /* line 205, ../../component/styles/header.scss */
223
+ .dropdown-active {
224
+ -webkit-transition: all 0.4s ease-in;
225
+ -moz-transition: all 0.4s ease-in;
226
+ -o-transition: all 0.4s ease-in;
227
+ transition: all 0.4s ease-in;
228
+ display: block;
229
+ }
230
+
231
+ /* line 210, ../../component/styles/header.scss */
232
+ .flyout-indicator {
233
+ margin-top: 10px;
234
+ float: right;
235
+ margin-right: 5px;
236
+ }
237
+
238
+ /* line 216, ../../component/styles/header.scss */
239
+ .flyout {
240
+ padding: 0;
241
+ list-style: none;
242
+ position: absolute;
243
+ top: -1px;
244
+ left: 100%;
245
+ min-width: 180px;
246
+ border: 1px solid #C8C8C8;
247
+ border-radius: 0 3px 3px 3px;
248
+ box-shadow: 1px 0px 5px #C8C8C8;
249
+ z-index: 2;
250
+ background: white;
251
+ }
252
+ /* line 229, ../../component/styles/header.scss */
253
+ .flyout li {
254
+ text-align: left;
255
+ line-height: 35px;
256
+ position: relative;
257
+ display: block;
258
+ clear: both;
259
+ }
260
+ /* line 236, ../../component/styles/header.scss */
261
+ .flyout li a, .flyout li a:visited, .flyout li a:active, .flyout li a:link {
262
+ color: #000;
263
+ text-decoration: none;
264
+ display: block;
265
+ padding: 5px 0px 5px 20px;
266
+ }
267
+ /* line 243, ../../component/styles/header.scss */
268
+ .flyout li:hover {
269
+ background: black;
270
+ }
271
+ /* line 246, ../../component/styles/header.scss */
272
+ .flyout li:hover a, .flyout li:hover a:visited, .flyout li:hover a:active, .flyout li:hover a:link {
273
+ text-decoration: none;
274
+ color: #e6e6e6;
275
+ }
@@ -0,0 +1,160 @@
1
+ angular.module("alch-templates").run(function($templateCache) {
2
+ $templateCache.put("component/templates/dropdown.html",
3
+ "<ul class=\"dropdown\" " +
4
+ " ng-class=\"{ 'dropdown-right' : isRight(dropdown.direction), 'dropdown-active' : dropdown.show }\">" +
5
+ " <li ng-repeat=\"item in dropdown\"" +
6
+ " ng-mouseenter=\"set_hover(item, true)\"" +
7
+ " ng-mouseleave=\"set_hover(item, false)\">" +
8
+ " " +
9
+ " <a class=\"dropdown-menu-item-link\" href=\"{{ item.url }}\">" +
10
+ " {{ item.display }}" +
11
+ " <i class=\"right_arrow_icon-grey flyout-indicator\" ng-show=\"item.type=='flyout'\"></i>" +
12
+ " </a>" +
13
+ " <ul alch-flyout=\"item.items\" ng-show=\"flyout.show\" ng-class=\"{ 'dropdown-active' : dropdown.show }\"></ul>" +
14
+ " </li>" +
15
+ "</ul>" +
16
+ "");
17
+ });
18
+
19
+ angular.module("alch-templates").run(function($templateCache) {
20
+ $templateCache.put("component/templates/flyout.html",
21
+ "<ul class=\"flyout\">" +
22
+ " <li ng-repeat=\"item in flyout\"" +
23
+ " ng-class=\"{ 'dropdown-highlight' : item.active }\"" +
24
+ " ng-mouseenter=\"set_hover(item, true)\"" +
25
+ " ng-mouseleave=\"set_hover(item, false)\">" +
26
+ " " +
27
+ " <a href=\"{{ item.url }}\">{{ item.display }}</a>" +
28
+ " </li>" +
29
+ "</ul>" +
30
+ "");
31
+ });
32
+
33
+ angular.module("alch-templates").run(function($templateCache) {
34
+ $templateCache.put("component/templates/menu.html",
35
+ "<nav ng-class=\"menu.location\">" +
36
+ " <ul class=\"menu-container\">" +
37
+ " <li class=\"menu-item\"" +
38
+ " ng-repeat=\"item in menu.items\"" +
39
+ " ng-mouseenter=\"handle_hover(item, true)\"" +
40
+ " ng-mouseleave=\"handle_hover(item, false)\">" +
41
+ " " +
42
+ " <a href=\"{{ item.url }}\" " +
43
+ " ng-class=\"{ 'active-item' : item.active }\"" +
44
+ " class=\"menu-item-link\">" +
45
+ " " +
46
+ " {{ item.display }}" +
47
+ " <i class=\"down_arrow_icon-grey\" ng-show=\"item.type == 'dropdown'\"></i>" +
48
+ " </a>" +
49
+ " <ul alch-dropdown=\"item.items\"></ul>" +
50
+ " </li>" +
51
+ " </ul>" +
52
+ "</nav>" +
53
+ "");
54
+ });
55
+
56
+ 'use strict';
57
+
58
+ angular.module('alchemy').directive('alchMenu', function($window){
59
+ return {
60
+ restrict: 'EA',
61
+ transclude: true,
62
+ replace: true,
63
+ scope: {
64
+ 'menu': '=alchMenu',
65
+ 'compact' : '@'
66
+ },
67
+ templateUrl: 'component/templates/menu.html',
68
+
69
+ controller: function($scope) {
70
+ $scope.dropdown = {};
71
+
72
+ $scope.handle_hover = function(item, mousein){
73
+ if( item.type === 'dropdown' && mousein ){
74
+ item.active = true;
75
+ $scope.dropdown = item.items;
76
+ $scope.dropdown.show = true;
77
+ $scope.dropdown.direction = $scope.menu.location;
78
+ } else {
79
+ $scope.dropdown.show = false;
80
+
81
+ if( item !== $scope.menu.active_item ){
82
+ item.active = false;
83
+ }
84
+ }
85
+ };
86
+
87
+ },
88
+
89
+ link: function(scope, element, attrs){
90
+ if( attrs.compact !== undefined ){
91
+ angular.element($window).bind('scroll', function(){
92
+ var h = $('body').height();
93
+ var y = $($window).scrollTop();
94
+
95
+ if( y > (h*0.03) ){
96
+ element.parent().addClass('compact');
97
+ } else {
98
+ element.parent().removeClass('compact');
99
+ }
100
+ });
101
+ }
102
+ }
103
+ };
104
+ });
105
+
106
+ angular.module('alchemy').directive('alchDropdown', function(){
107
+ return {
108
+ restrict: 'EA',
109
+ transclude: true,
110
+ replace: true,
111
+ scope: {
112
+ 'dropdown' : '=alchDropdown'
113
+ },
114
+ templateUrl: 'component/templates/dropdown.html',
115
+
116
+ controller: function($scope){
117
+ $scope.set_hover = function(item, mousein){
118
+ if( mousein ){
119
+ item.active = true;
120
+
121
+ if( item.type === 'flyout' ){
122
+ $scope.flyout = item.items;
123
+ $scope.flyout.show = true;
124
+ }
125
+ } else {
126
+ if( $scope.flyout ){
127
+ $scope.flyout.show = false;
128
+ }
129
+ item.active = false;
130
+ }
131
+ };
132
+
133
+ $scope.isRight = function(direction){
134
+ return direction === 'right';
135
+ };
136
+ }
137
+ };
138
+ });
139
+
140
+ angular.module('alchemy').directive('alchFlyout', function(){
141
+ return {
142
+ restrict: 'EA',
143
+ transclude: true,
144
+ replace: true,
145
+ scope: {
146
+ 'flyout' : '=alchFlyout'
147
+ },
148
+ templateUrl: 'component/templates/flyout.html',
149
+
150
+ controller: function($scope){
151
+ $scope.set_hover = function(item, mousein){
152
+ if( mousein ){
153
+ item.active = true;
154
+ } else {
155
+ item.active = false;
156
+ }
157
+ };
158
+ }
159
+ };
160
+ });
@@ -0,0 +1,26 @@
1
+ {
2
+ "name": "alchemy-header",
3
+ "version": "0.0.4",
4
+ "main": [
5
+ "./*.js",
6
+ "./*.scss",
7
+ "./*.css"
8
+ ],
9
+ "dependencies": {
10
+ "angular": "~1.0.5",
11
+ "jquery": "~1.9.1",
12
+ "alchemy": ">=0.0.1"
13
+ },
14
+ "devDependencies": {
15
+ "angular-mocks": "~1.0.5",
16
+ "angular-scenario": "~1.0.5"
17
+ },
18
+ "gitHead": "35c50677e2c0c3afed09a77caf11580bc3d691d0",
19
+ "_id": "alchemy-header@0.0.4",
20
+ "readme": "ERROR: No README.md file found!",
21
+ "description": "ERROR: No README.md file found!",
22
+ "repository": {
23
+ "type": "git",
24
+ "url": "git://github.com/ui-alchemy/alchemy-header.git"
25
+ }
26
+ }
@@ -0,0 +1,252 @@
1
+ $nav-header_background: orange !default;
2
+ $logo-header_background: darken($nav-header_background, 10%) !default;
3
+ $menu-item_hover: darken($nav-header_background, 10%) !default;
4
+ $link_color: #000 !default;
5
+ $link-hover_color: lighten($link_color, 90%) !default;
6
+ $link-border_color: lighten(orange, 30%) !default;
7
+ $dropdown-link-hover_background: #000 !default;
8
+
9
+ .left { float: left; }
10
+ .right { float: right; }
11
+
12
+ .logo-header {
13
+ $logo-header_line_height: 25px;
14
+
15
+ height: $logo-header_line_height;
16
+ background-color: $logo-header_background;
17
+ z-index: 100;
18
+ line-height: $logo-header_line_height;
19
+
20
+ .logo {
21
+ margin-left: 30px;
22
+ }
23
+
24
+ .menu-container {
25
+ line-height: $logo-header_line_height;
26
+
27
+ .menu-item {
28
+ line-height: $logo-header_line_height;
29
+
30
+ .menu-item-link {
31
+ white-space: nowrap;
32
+ text-overflow: ellipsis;
33
+ @include transition( all .15s ease-in);
34
+ text-align: center;
35
+ text-transform: capitalize;
36
+ font-family: overpass, sans-serif, sans;
37
+ text-decoration: none;
38
+ margin: 0 auto;
39
+
40
+ &:hover {
41
+ @include transition( all 0.3s ease-in-out);
42
+
43
+ color: $link-hover_color;
44
+ background: darken($logo-header_background, 10%);
45
+ }
46
+
47
+ &.active-item {
48
+ color: $link-hover_color;
49
+ background: darken($logo-header_background, 10%);
50
+ }
51
+ }
52
+ }
53
+ }
54
+
55
+ .dropdown-active {
56
+ box-shadow: none;
57
+ }
58
+ }
59
+
60
+ .nav-header {
61
+ min-height: 40px;
62
+ background: $nav-header_background;
63
+ border-top: 1px solid lighten($nav-header_background, 10%);
64
+
65
+ .menu-item {
66
+ font-family: Overpass;
67
+ line-height: 37px;
68
+ vertical-align: baseline;
69
+ font-size: 14px;
70
+ position: relative;
71
+
72
+ .menu-item-link {
73
+ @include transition( all .15s ease-in);
74
+ white-space: nowrap;
75
+ text-overflow: ellipsis;
76
+ text-align: center;
77
+ text-transform: capitalize;
78
+ font-family: overpass, sans-serif, sans;
79
+ text-decoration: none;
80
+ margin: 0 auto;
81
+ color: $link_color;
82
+
83
+ &:hover {
84
+ @include transition( all 0.15s ease-in-out);
85
+ border-bottom: 3px solid $link-border_color;
86
+ color: $link-hover_color;
87
+ background: darken($nav-header_background, 10%);
88
+ box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);
89
+ }
90
+
91
+ &.active-item {
92
+ box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.125);
93
+ color: $link-hover_color;
94
+ border-bottom: 3px solid $link-border_color;
95
+ background: darken($nav-header_background, 10%);
96
+ }
97
+ }
98
+ }
99
+ }
100
+
101
+ .menu-container {
102
+ position: relative;
103
+ left: 0;
104
+ display: block;
105
+ float: left;
106
+ margin: 0;
107
+ list-style: none;
108
+ line-height: 40px;
109
+
110
+ .menu-item {
111
+ line-height: 37px;
112
+ position: relative;
113
+ margin: 0;
114
+ float: left;
115
+
116
+ .menu-item-link {
117
+ float: none;
118
+ padding: 0 20px;
119
+ text-decoration: none;
120
+ display: block;
121
+ cursor: default;
122
+ @include box-sizing(border-box);
123
+ }
124
+ }
125
+ }
126
+
127
+ .menu-dropdown {
128
+ background: white;
129
+ position: absolute;
130
+ z-index: 1;
131
+ }
132
+
133
+ .compact{
134
+ position:fixed;
135
+ vertical-align:middle;
136
+ top: 0;
137
+ padding:0;
138
+ margin: 0;
139
+ width: 100%;
140
+ z-index: 100;
141
+ }
142
+
143
+ .right .menu-item .dropdown {
144
+ right: -1px;
145
+
146
+ }
147
+
148
+ .dropdown {
149
+ position: absolute;
150
+ top: 100%;
151
+ left: -1px;
152
+ float: left;
153
+ min-width: 200px;
154
+ display: none;
155
+ list-style: none;
156
+ border-radius: 0 0 5px 5px;
157
+ padding: 0;
158
+ z-index: 3;
159
+ @include box-sizing(border-box);
160
+
161
+ border: 1px solid #C8C8C8;
162
+ border-top: none;
163
+ box-shadow: 0px 1px 5px #C8C8C8;
164
+ background: white;
165
+ opacity: 1;
166
+ font-family: "Liberation-sans";
167
+
168
+ .dropdown-highlight {
169
+ }
170
+
171
+ li {
172
+ text-align: left;
173
+ line-height: 35px;
174
+ position: relative;
175
+ display: block;
176
+ clear: both;
177
+
178
+ a, a:visited, a:active, a:link {
179
+ color: #000;
180
+ text-decoration: none;
181
+ display: block;
182
+ padding: 5px 0px 5px 20px;
183
+ }
184
+
185
+ &:hover {
186
+ background: $dropdown-link-hover_background;
187
+
188
+ .dropdown-menu-item-link {
189
+ text-decoration: none;
190
+ color: $link-hover_color;
191
+ }
192
+ }
193
+ }
194
+ }
195
+
196
+ .dropdown-left {
197
+ left: 0;
198
+ }
199
+
200
+ .dropdown-right {
201
+ right: 0;
202
+ left: auto;
203
+ }
204
+
205
+ .dropdown-active {
206
+ @include transition(all 0.4s ease-in);
207
+ display: block;
208
+ }
209
+
210
+ .flyout-indicator {
211
+ margin-top: 10px;
212
+ float: right;
213
+ margin-right: 5px;
214
+ }
215
+
216
+ .flyout {
217
+ padding: 0;
218
+ list-style: none;
219
+ position: absolute;
220
+ top: -1px;
221
+ left: 100%;
222
+ min-width: 180px;
223
+ border: 1px solid #C8C8C8;
224
+ border-radius: 0 3px 3px 3px;
225
+ box-shadow: 1px 0px 5px #C8C8C8;
226
+ z-index: 2;
227
+ background: white;
228
+
229
+ li {
230
+ text-align: left;
231
+ line-height: 35px;
232
+ position: relative;
233
+ display: block;
234
+ clear: both;
235
+
236
+ a, a:visited, a:active, a:link {
237
+ color: #000;
238
+ text-decoration: none;
239
+ display: block;
240
+ padding: 5px 0px 5px 20px;
241
+ }
242
+
243
+ &:hover {
244
+ background: $dropdown-link-hover_background;
245
+
246
+ a, a:visited, a:active, a:link {
247
+ text-decoration: none;
248
+ color: $link-hover_color;
249
+ }
250
+ }
251
+ }
252
+ }
@@ -0,0 +1,4 @@
1
+ bower-angular-sanitize
2
+ ======================
3
+
4
+ angular-sanitize bower repo
@@ -0,0 +1,537 @@
1
+ /**
2
+ * @license AngularJS v1.0.6
3
+ * (c) 2010-2012 Google, Inc. http://angularjs.org
4
+ * License: MIT
5
+ */
6
+ (function(window, angular, undefined) {
7
+ 'use strict';
8
+
9
+ /**
10
+ * @ngdoc overview
11
+ * @name ngSanitize
12
+ * @description
13
+ */
14
+
15
+ /*
16
+ * HTML Parser By Misko Hevery (misko@hevery.com)
17
+ * based on: HTML Parser By John Resig (ejohn.org)
18
+ * Original code by Erik Arvidsson, Mozilla Public License
19
+ * http://erik.eae.net/simplehtmlparser/simplehtmlparser.js
20
+ *
21
+ * // Use like so:
22
+ * htmlParser(htmlString, {
23
+ * start: function(tag, attrs, unary) {},
24
+ * end: function(tag) {},
25
+ * chars: function(text) {},
26
+ * comment: function(text) {}
27
+ * });
28
+ *
29
+ */
30
+
31
+
32
+ /**
33
+ * @ngdoc service
34
+ * @name ngSanitize.$sanitize
35
+ * @function
36
+ *
37
+ * @description
38
+ * The input is sanitized by parsing the html into tokens. All safe tokens (from a whitelist) are
39
+ * then serialized back to properly escaped html string. This means that no unsafe input can make
40
+ * it into the returned string, however, since our parser is more strict than a typical browser
41
+ * parser, it's possible that some obscure input, which would be recognized as valid HTML by a
42
+ * browser, won't make it through the sanitizer.
43
+ *
44
+ * @param {string} html Html input.
45
+ * @returns {string} Sanitized html.
46
+ *
47
+ * @example
48
+ <doc:example module="ngSanitize">
49
+ <doc:source>
50
+ <script>
51
+ function Ctrl($scope) {
52
+ $scope.snippet =
53
+ '<p style="color:blue">an html\n' +
54
+ '<em onmouseover="this.textContent=\'PWN3D!\'">click here</em>\n' +
55
+ 'snippet</p>';
56
+ }
57
+ </script>
58
+ <div ng-controller="Ctrl">
59
+ Snippet: <textarea ng-model="snippet" cols="60" rows="3"></textarea>
60
+ <table>
61
+ <tr>
62
+ <td>Filter</td>
63
+ <td>Source</td>
64
+ <td>Rendered</td>
65
+ </tr>
66
+ <tr id="html-filter">
67
+ <td>html filter</td>
68
+ <td>
69
+ <pre>&lt;div ng-bind-html="snippet"&gt;<br/>&lt;/div&gt;</pre>
70
+ </td>
71
+ <td>
72
+ <div ng-bind-html="snippet"></div>
73
+ </td>
74
+ </tr>
75
+ <tr id="escaped-html">
76
+ <td>no filter</td>
77
+ <td><pre>&lt;div ng-bind="snippet"&gt;<br/>&lt;/div&gt;</pre></td>
78
+ <td><div ng-bind="snippet"></div></td>
79
+ </tr>
80
+ <tr id="html-unsafe-filter">
81
+ <td>unsafe html filter</td>
82
+ <td><pre>&lt;div ng-bind-html-unsafe="snippet"&gt;<br/>&lt;/div&gt;</pre></td>
83
+ <td><div ng-bind-html-unsafe="snippet"></div></td>
84
+ </tr>
85
+ </table>
86
+ </div>
87
+ </doc:source>
88
+ <doc:scenario>
89
+ it('should sanitize the html snippet ', function() {
90
+ expect(using('#html-filter').element('div').html()).
91
+ toBe('<p>an html\n<em>click here</em>\nsnippet</p>');
92
+ });
93
+
94
+ it('should escape snippet without any filter', function() {
95
+ expect(using('#escaped-html').element('div').html()).
96
+ toBe("&lt;p style=\"color:blue\"&gt;an html\n" +
97
+ "&lt;em onmouseover=\"this.textContent='PWN3D!'\"&gt;click here&lt;/em&gt;\n" +
98
+ "snippet&lt;/p&gt;");
99
+ });
100
+
101
+ it('should inline raw snippet if filtered as unsafe', function() {
102
+ expect(using('#html-unsafe-filter').element("div").html()).
103
+ toBe("<p style=\"color:blue\">an html\n" +
104
+ "<em onmouseover=\"this.textContent='PWN3D!'\">click here</em>\n" +
105
+ "snippet</p>");
106
+ });
107
+
108
+ it('should update', function() {
109
+ input('snippet').enter('new <b>text</b>');
110
+ expect(using('#html-filter').binding('snippet')).toBe('new <b>text</b>');
111
+ expect(using('#escaped-html').element('div').html()).toBe("new &lt;b&gt;text&lt;/b&gt;");
112
+ expect(using('#html-unsafe-filter').binding("snippet")).toBe('new <b>text</b>');
113
+ });
114
+ </doc:scenario>
115
+ </doc:example>
116
+ */
117
+ var $sanitize = function(html) {
118
+ var buf = [];
119
+ htmlParser(html, htmlSanitizeWriter(buf));
120
+ return buf.join('');
121
+ };
122
+
123
+
124
+ // Regular Expressions for parsing tags and attributes
125
+ var START_TAG_REGEXP = /^<\s*([\w:-]+)((?:\s+[\w:-]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)\s*>/,
126
+ END_TAG_REGEXP = /^<\s*\/\s*([\w:-]+)[^>]*>/,
127
+ ATTR_REGEXP = /([\w:-]+)(?:\s*=\s*(?:(?:"((?:[^"])*)")|(?:'((?:[^'])*)')|([^>\s]+)))?/g,
128
+ BEGIN_TAG_REGEXP = /^</,
129
+ BEGING_END_TAGE_REGEXP = /^<\s*\//,
130
+ COMMENT_REGEXP = /<!--(.*?)-->/g,
131
+ CDATA_REGEXP = /<!\[CDATA\[(.*?)]]>/g,
132
+ URI_REGEXP = /^((ftp|https?):\/\/|mailto:|#)/,
133
+ NON_ALPHANUMERIC_REGEXP = /([^\#-~| |!])/g; // Match everything outside of normal chars and " (quote character)
134
+
135
+
136
+ // Good source of info about elements and attributes
137
+ // http://dev.w3.org/html5/spec/Overview.html#semantics
138
+ // http://simon.html5.org/html-elements
139
+
140
+ // Safe Void Elements - HTML5
141
+ // http://dev.w3.org/html5/spec/Overview.html#void-elements
142
+ var voidElements = makeMap("area,br,col,hr,img,wbr");
143
+
144
+ // Elements that you can, intentionally, leave open (and which close themselves)
145
+ // http://dev.w3.org/html5/spec/Overview.html#optional-tags
146
+ var optionalEndTagBlockElements = makeMap("colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr"),
147
+ optionalEndTagInlineElements = makeMap("rp,rt"),
148
+ optionalEndTagElements = angular.extend({}, optionalEndTagInlineElements, optionalEndTagBlockElements);
149
+
150
+ // Safe Block Elements - HTML5
151
+ var blockElements = angular.extend({}, optionalEndTagBlockElements, makeMap("address,article,aside," +
152
+ "blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5,h6," +
153
+ "header,hgroup,hr,ins,map,menu,nav,ol,pre,script,section,table,ul"));
154
+
155
+ // Inline Elements - HTML5
156
+ var inlineElements = angular.extend({}, optionalEndTagInlineElements, makeMap("a,abbr,acronym,b,bdi,bdo," +
157
+ "big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s,samp,small," +
158
+ "span,strike,strong,sub,sup,time,tt,u,var"));
159
+
160
+
161
+ // Special Elements (can contain anything)
162
+ var specialElements = makeMap("script,style");
163
+
164
+ var validElements = angular.extend({}, voidElements, blockElements, inlineElements, optionalEndTagElements);
165
+
166
+ //Attributes that have href and hence need to be sanitized
167
+ var uriAttrs = makeMap("background,cite,href,longdesc,src,usemap");
168
+ var validAttrs = angular.extend({}, uriAttrs, makeMap(
169
+ 'abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,'+
170
+ 'color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,'+
171
+ 'ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,'+
172
+ 'scope,scrolling,shape,span,start,summary,target,title,type,'+
173
+ 'valign,value,vspace,width'));
174
+
175
+ function makeMap(str) {
176
+ var obj = {}, items = str.split(','), i;
177
+ for (i = 0; i < items.length; i++) obj[items[i]] = true;
178
+ return obj;
179
+ }
180
+
181
+
182
+ /**
183
+ * @example
184
+ * htmlParser(htmlString, {
185
+ * start: function(tag, attrs, unary) {},
186
+ * end: function(tag) {},
187
+ * chars: function(text) {},
188
+ * comment: function(text) {}
189
+ * });
190
+ *
191
+ * @param {string} html string
192
+ * @param {object} handler
193
+ */
194
+ function htmlParser( html, handler ) {
195
+ var index, chars, match, stack = [], last = html;
196
+ stack.last = function() { return stack[ stack.length - 1 ]; };
197
+
198
+ while ( html ) {
199
+ chars = true;
200
+
201
+ // Make sure we're not in a script or style element
202
+ if ( !stack.last() || !specialElements[ stack.last() ] ) {
203
+
204
+ // Comment
205
+ if ( html.indexOf("<!--") === 0 ) {
206
+ index = html.indexOf("-->");
207
+
208
+ if ( index >= 0 ) {
209
+ if (handler.comment) handler.comment( html.substring( 4, index ) );
210
+ html = html.substring( index + 3 );
211
+ chars = false;
212
+ }
213
+
214
+ // end tag
215
+ } else if ( BEGING_END_TAGE_REGEXP.test(html) ) {
216
+ match = html.match( END_TAG_REGEXP );
217
+
218
+ if ( match ) {
219
+ html = html.substring( match[0].length );
220
+ match[0].replace( END_TAG_REGEXP, parseEndTag );
221
+ chars = false;
222
+ }
223
+
224
+ // start tag
225
+ } else if ( BEGIN_TAG_REGEXP.test(html) ) {
226
+ match = html.match( START_TAG_REGEXP );
227
+
228
+ if ( match ) {
229
+ html = html.substring( match[0].length );
230
+ match[0].replace( START_TAG_REGEXP, parseStartTag );
231
+ chars = false;
232
+ }
233
+ }
234
+
235
+ if ( chars ) {
236
+ index = html.indexOf("<");
237
+
238
+ var text = index < 0 ? html : html.substring( 0, index );
239
+ html = index < 0 ? "" : html.substring( index );
240
+
241
+ if (handler.chars) handler.chars( decodeEntities(text) );
242
+ }
243
+
244
+ } else {
245
+ html = html.replace(new RegExp("(.*)<\\s*\\/\\s*" + stack.last() + "[^>]*>", 'i'), function(all, text){
246
+ text = text.
247
+ replace(COMMENT_REGEXP, "$1").
248
+ replace(CDATA_REGEXP, "$1");
249
+
250
+ if (handler.chars) handler.chars( decodeEntities(text) );
251
+
252
+ return "";
253
+ });
254
+
255
+ parseEndTag( "", stack.last() );
256
+ }
257
+
258
+ if ( html == last ) {
259
+ throw "Parse Error: " + html;
260
+ }
261
+ last = html;
262
+ }
263
+
264
+ // Clean up any remaining tags
265
+ parseEndTag();
266
+
267
+ function parseStartTag( tag, tagName, rest, unary ) {
268
+ tagName = angular.lowercase(tagName);
269
+ if ( blockElements[ tagName ] ) {
270
+ while ( stack.last() && inlineElements[ stack.last() ] ) {
271
+ parseEndTag( "", stack.last() );
272
+ }
273
+ }
274
+
275
+ if ( optionalEndTagElements[ tagName ] && stack.last() == tagName ) {
276
+ parseEndTag( "", tagName );
277
+ }
278
+
279
+ unary = voidElements[ tagName ] || !!unary;
280
+
281
+ if ( !unary )
282
+ stack.push( tagName );
283
+
284
+ var attrs = {};
285
+
286
+ rest.replace(ATTR_REGEXP, function(match, name, doubleQuotedValue, singleQoutedValue, unqoutedValue) {
287
+ var value = doubleQuotedValue
288
+ || singleQoutedValue
289
+ || unqoutedValue
290
+ || '';
291
+
292
+ attrs[name] = decodeEntities(value);
293
+ });
294
+ if (handler.start) handler.start( tagName, attrs, unary );
295
+ }
296
+
297
+ function parseEndTag( tag, tagName ) {
298
+ var pos = 0, i;
299
+ tagName = angular.lowercase(tagName);
300
+ if ( tagName )
301
+ // Find the closest opened tag of the same type
302
+ for ( pos = stack.length - 1; pos >= 0; pos-- )
303
+ if ( stack[ pos ] == tagName )
304
+ break;
305
+
306
+ if ( pos >= 0 ) {
307
+ // Close all the open elements, up the stack
308
+ for ( i = stack.length - 1; i >= pos; i-- )
309
+ if (handler.end) handler.end( stack[ i ] );
310
+
311
+ // Remove the open elements from the stack
312
+ stack.length = pos;
313
+ }
314
+ }
315
+ }
316
+
317
+ /**
318
+ * decodes all entities into regular string
319
+ * @param value
320
+ * @returns {string} A string with decoded entities.
321
+ */
322
+ var hiddenPre=document.createElement("pre");
323
+ function decodeEntities(value) {
324
+ hiddenPre.innerHTML=value.replace(/</g,"&lt;");
325
+ return hiddenPre.innerText || hiddenPre.textContent || '';
326
+ }
327
+
328
+ /**
329
+ * Escapes all potentially dangerous characters, so that the
330
+ * resulting string can be safely inserted into attribute or
331
+ * element text.
332
+ * @param value
333
+ * @returns escaped text
334
+ */
335
+ function encodeEntities(value) {
336
+ return value.
337
+ replace(/&/g, '&amp;').
338
+ replace(NON_ALPHANUMERIC_REGEXP, function(value){
339
+ return '&#' + value.charCodeAt(0) + ';';
340
+ }).
341
+ replace(/</g, '&lt;').
342
+ replace(/>/g, '&gt;');
343
+ }
344
+
345
+ /**
346
+ * create an HTML/XML writer which writes to buffer
347
+ * @param {Array} buf use buf.jain('') to get out sanitized html string
348
+ * @returns {object} in the form of {
349
+ * start: function(tag, attrs, unary) {},
350
+ * end: function(tag) {},
351
+ * chars: function(text) {},
352
+ * comment: function(text) {}
353
+ * }
354
+ */
355
+ function htmlSanitizeWriter(buf){
356
+ var ignore = false;
357
+ var out = angular.bind(buf, buf.push);
358
+ return {
359
+ start: function(tag, attrs, unary){
360
+ tag = angular.lowercase(tag);
361
+ if (!ignore && specialElements[tag]) {
362
+ ignore = tag;
363
+ }
364
+ if (!ignore && validElements[tag] == true) {
365
+ out('<');
366
+ out(tag);
367
+ angular.forEach(attrs, function(value, key){
368
+ var lkey=angular.lowercase(key);
369
+ if (validAttrs[lkey]==true && (uriAttrs[lkey]!==true || value.match(URI_REGEXP))) {
370
+ out(' ');
371
+ out(key);
372
+ out('="');
373
+ out(encodeEntities(value));
374
+ out('"');
375
+ }
376
+ });
377
+ out(unary ? '/>' : '>');
378
+ }
379
+ },
380
+ end: function(tag){
381
+ tag = angular.lowercase(tag);
382
+ if (!ignore && validElements[tag] == true) {
383
+ out('</');
384
+ out(tag);
385
+ out('>');
386
+ }
387
+ if (tag == ignore) {
388
+ ignore = false;
389
+ }
390
+ },
391
+ chars: function(chars){
392
+ if (!ignore) {
393
+ out(encodeEntities(chars));
394
+ }
395
+ }
396
+ };
397
+ }
398
+
399
+
400
+ // define ngSanitize module and register $sanitize service
401
+ angular.module('ngSanitize', []).value('$sanitize', $sanitize);
402
+
403
+ /**
404
+ * @ngdoc directive
405
+ * @name ngSanitize.directive:ngBindHtml
406
+ *
407
+ * @description
408
+ * Creates a binding that will sanitize the result of evaluating the `expression` with the
409
+ * {@link ngSanitize.$sanitize $sanitize} service and innerHTML the result into the current element.
410
+ *
411
+ * See {@link ngSanitize.$sanitize $sanitize} docs for examples.
412
+ *
413
+ * @element ANY
414
+ * @param {expression} ngBindHtml {@link guide/expression Expression} to evaluate.
415
+ */
416
+ angular.module('ngSanitize').directive('ngBindHtml', ['$sanitize', function($sanitize) {
417
+ return function(scope, element, attr) {
418
+ element.addClass('ng-binding').data('$binding', attr.ngBindHtml);
419
+ scope.$watch(attr.ngBindHtml, function ngBindHtmlWatchAction(value) {
420
+ value = $sanitize(value);
421
+ element.html(value || '');
422
+ });
423
+ };
424
+ }]);
425
+
426
+ /**
427
+ * @ngdoc filter
428
+ * @name ngSanitize.filter:linky
429
+ * @function
430
+ *
431
+ * @description
432
+ * Finds links in text input and turns them into html links. Supports http/https/ftp/mailto and
433
+ * plain email address links.
434
+ *
435
+ * @param {string} text Input text.
436
+ * @returns {string} Html-linkified text.
437
+ *
438
+ * @usage
439
+ <span ng-bind-html="linky_expression | linky"></span>
440
+ *
441
+ * @example
442
+ <doc:example module="ngSanitize">
443
+ <doc:source>
444
+ <script>
445
+ function Ctrl($scope) {
446
+ $scope.snippet =
447
+ 'Pretty text with some links:\n'+
448
+ 'http://angularjs.org/,\n'+
449
+ 'mailto:us@somewhere.org,\n'+
450
+ 'another@somewhere.org,\n'+
451
+ 'and one more: ftp://127.0.0.1/.';
452
+ }
453
+ </script>
454
+ <div ng-controller="Ctrl">
455
+ Snippet: <textarea ng-model="snippet" cols="60" rows="3"></textarea>
456
+ <table>
457
+ <tr>
458
+ <td>Filter</td>
459
+ <td>Source</td>
460
+ <td>Rendered</td>
461
+ </tr>
462
+ <tr id="linky-filter">
463
+ <td>linky filter</td>
464
+ <td>
465
+ <pre>&lt;div ng-bind-html="snippet | linky"&gt;<br>&lt;/div&gt;</pre>
466
+ </td>
467
+ <td>
468
+ <div ng-bind-html="snippet | linky"></div>
469
+ </td>
470
+ </tr>
471
+ <tr id="escaped-html">
472
+ <td>no filter</td>
473
+ <td><pre>&lt;div ng-bind="snippet"&gt;<br>&lt;/div&gt;</pre></td>
474
+ <td><div ng-bind="snippet"></div></td>
475
+ </tr>
476
+ </table>
477
+ </doc:source>
478
+ <doc:scenario>
479
+ it('should linkify the snippet with urls', function() {
480
+ expect(using('#linky-filter').binding('snippet | linky')).
481
+ toBe('Pretty text with some links:&#10;' +
482
+ '<a href="http://angularjs.org/">http://angularjs.org/</a>,&#10;' +
483
+ '<a href="mailto:us@somewhere.org">us@somewhere.org</a>,&#10;' +
484
+ '<a href="mailto:another@somewhere.org">another@somewhere.org</a>,&#10;' +
485
+ 'and one more: <a href="ftp://127.0.0.1/">ftp://127.0.0.1/</a>.');
486
+ });
487
+
488
+ it ('should not linkify snippet without the linky filter', function() {
489
+ expect(using('#escaped-html').binding('snippet')).
490
+ toBe("Pretty text with some links:\n" +
491
+ "http://angularjs.org/,\n" +
492
+ "mailto:us@somewhere.org,\n" +
493
+ "another@somewhere.org,\n" +
494
+ "and one more: ftp://127.0.0.1/.");
495
+ });
496
+
497
+ it('should update', function() {
498
+ input('snippet').enter('new http://link.');
499
+ expect(using('#linky-filter').binding('snippet | linky')).
500
+ toBe('new <a href="http://link">http://link</a>.');
501
+ expect(using('#escaped-html').binding('snippet')).toBe('new http://link.');
502
+ });
503
+ </doc:scenario>
504
+ </doc:example>
505
+ */
506
+ angular.module('ngSanitize').filter('linky', function() {
507
+ var LINKY_URL_REGEXP = /((ftp|https?):\/\/|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s\.\;\,\(\)\{\}\<\>]/,
508
+ MAILTO_REGEXP = /^mailto:/;
509
+
510
+ return function(text) {
511
+ if (!text) return text;
512
+ var match;
513
+ var raw = text;
514
+ var html = [];
515
+ // TODO(vojta): use $sanitize instead
516
+ var writer = htmlSanitizeWriter(html);
517
+ var url;
518
+ var i;
519
+ while ((match = raw.match(LINKY_URL_REGEXP))) {
520
+ // We can not end in these as they are sometimes found at the end of the sentence
521
+ url = match[0];
522
+ // if we did not match ftp/http/mailto then assume mailto
523
+ if (match[2] == match[3]) url = 'mailto:' + url;
524
+ i = match.index;
525
+ writer.chars(raw.substr(0, i));
526
+ writer.start('a', {href:url});
527
+ writer.chars(match[0].replace(MAILTO_REGEXP, ''));
528
+ writer.end('a');
529
+ raw = raw.substring(i + match[0].length);
530
+ }
531
+ writer.chars(raw);
532
+ return html.join('');
533
+ };
534
+ });
535
+
536
+
537
+ })(window, window.angular);
@@ -0,0 +1,13 @@
1
+ /*
2
+ AngularJS v1.0.6
3
+ (c) 2010-2012 Google, Inc. http://angularjs.org
4
+ License: MIT
5
+ */
6
+ (function(I,g){'use strict';function i(a){var d={},a=a.split(","),b;for(b=0;b<a.length;b++)d[a[b]]=!0;return d}function z(a,d){function b(a,b,c,h){b=g.lowercase(b);if(m[b])for(;f.last()&&n[f.last()];)e("",f.last());o[b]&&f.last()==b&&e("",b);(h=p[b]||!!h)||f.push(b);var j={};c.replace(A,function(a,b,d,e,c){j[b]=k(d||e||c||"")});d.start&&d.start(b,j,h)}function e(a,b){var e=0,c;if(b=g.lowercase(b))for(e=f.length-1;e>=0;e--)if(f[e]==b)break;if(e>=0){for(c=f.length-1;c>=e;c--)d.end&&d.end(f[c]);f.length=
7
+ e}}var c,h,f=[],j=a;for(f.last=function(){return f[f.length-1]};a;){h=!0;if(!f.last()||!q[f.last()]){if(a.indexOf("<\!--")===0)c=a.indexOf("--\>"),c>=0&&(d.comment&&d.comment(a.substring(4,c)),a=a.substring(c+3),h=!1);else if(B.test(a)){if(c=a.match(r))a=a.substring(c[0].length),c[0].replace(r,e),h=!1}else if(C.test(a)&&(c=a.match(s)))a=a.substring(c[0].length),c[0].replace(s,b),h=!1;h&&(c=a.indexOf("<"),h=c<0?a:a.substring(0,c),a=c<0?"":a.substring(c),d.chars&&d.chars(k(h)))}else a=a.replace(RegExp("(.*)<\\s*\\/\\s*"+
8
+ f.last()+"[^>]*>","i"),function(b,a){a=a.replace(D,"$1").replace(E,"$1");d.chars&&d.chars(k(a));return""}),e("",f.last());if(a==j)throw"Parse Error: "+a;j=a}e()}function k(a){l.innerHTML=a.replace(/</g,"&lt;");return l.innerText||l.textContent||""}function t(a){return a.replace(/&/g,"&amp;").replace(F,function(a){return"&#"+a.charCodeAt(0)+";"}).replace(/</g,"&lt;").replace(/>/g,"&gt;")}function u(a){var d=!1,b=g.bind(a,a.push);return{start:function(a,c,h){a=g.lowercase(a);!d&&q[a]&&(d=a);!d&&v[a]==
9
+ !0&&(b("<"),b(a),g.forEach(c,function(a,c){var e=g.lowercase(c);if(G[e]==!0&&(w[e]!==!0||a.match(H)))b(" "),b(c),b('="'),b(t(a)),b('"')}),b(h?"/>":">"))},end:function(a){a=g.lowercase(a);!d&&v[a]==!0&&(b("</"),b(a),b(">"));a==d&&(d=!1)},chars:function(a){d||b(t(a))}}}var s=/^<\s*([\w:-]+)((?:\s+[\w:-]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)\s*>/,r=/^<\s*\/\s*([\w:-]+)[^>]*>/,A=/([\w:-]+)(?:\s*=\s*(?:(?:"((?:[^"])*)")|(?:'((?:[^'])*)')|([^>\s]+)))?/g,C=/^</,B=/^<\s*\//,D=/<\!--(.*?)--\>/g,
10
+ E=/<!\[CDATA\[(.*?)]]\>/g,H=/^((ftp|https?):\/\/|mailto:|#)/,F=/([^\#-~| |!])/g,p=i("area,br,col,hr,img,wbr"),x=i("colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr"),y=i("rp,rt"),o=g.extend({},y,x),m=g.extend({},x,i("address,article,aside,blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5,h6,header,hgroup,hr,ins,map,menu,nav,ol,pre,script,section,table,ul")),n=g.extend({},y,i("a,abbr,acronym,b,bdi,bdo,big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s,samp,small,span,strike,strong,sub,sup,time,tt,u,var")),
11
+ q=i("script,style"),v=g.extend({},p,m,n,o),w=i("background,cite,href,longdesc,src,usemap"),G=g.extend({},w,i("abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,scope,scrolling,shape,span,start,summary,target,title,type,valign,value,vspace,width")),l=document.createElement("pre");g.module("ngSanitize",[]).value("$sanitize",function(a){var d=[];
12
+ z(a,u(d));return d.join("")});g.module("ngSanitize").directive("ngBindHtml",["$sanitize",function(a){return function(d,b,e){b.addClass("ng-binding").data("$binding",e.ngBindHtml);d.$watch(e.ngBindHtml,function(c){c=a(c);b.html(c||"")})}}]);g.module("ngSanitize").filter("linky",function(){var a=/((ftp|https?):\/\/|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s\.\;\,\(\)\{\}\<\>]/,d=/^mailto:/;return function(b){if(!b)return b;for(var e=b,c=[],h=u(c),f,g;b=e.match(a);)f=b[0],b[2]==b[3]&&(f="mailto:"+f),g=b.index,
13
+ h.chars(e.substr(0,g)),h.start("a",{href:f}),h.chars(b[0].replace(d,"")),h.end("a"),e=e.substring(g+b[0].length);h.chars(e);return c.join("")}})})(window,window.angular);
@@ -0,0 +1,17 @@
1
+ {
2
+ "name": "angular-sanitize",
3
+ "version": "1.0.6",
4
+ "main": "./angular-sanitize.js",
5
+ "dependencies": {
6
+ "angular": "1.0.6"
7
+ },
8
+ "gitHead": "44fa1f93ff18a826caf00c9a726aa20b330e9577",
9
+ "readme": "bower-angular-sanitize\n======================\n\nangular-sanitize bower repo",
10
+ "readmeFilename": "README.md",
11
+ "_id": "angular-sanitize@1.0.6",
12
+ "description": "bower-angular-sanitize ======================",
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "git://github.com/angular/bower-angular-sanitize.git"
16
+ }
17
+ }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ui_alchemy-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.5
4
+ version: 1.0.6
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-04-11 00:00:00.000000000 Z
12
+ date: 2013-04-15 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
@@ -217,6 +217,10 @@ files:
217
217
  - vendor/assets/ui_alchemy/alchemy-tables/alchemy-tables.js
218
218
  - vendor/assets/ui_alchemy/alchemy-tables/component.json
219
219
  - vendor/assets/ui_alchemy/alchemy-tables/alchemy-tables.css
220
+ - vendor/assets/ui_alchemy/angular-sanitize/angular-sanitize.js
221
+ - vendor/assets/ui_alchemy/angular-sanitize/component.json
222
+ - vendor/assets/ui_alchemy/angular-sanitize/angular-sanitize.min.js
223
+ - vendor/assets/ui_alchemy/angular-sanitize/README.md
220
224
  - vendor/assets/ui_alchemy/alchemy-forms/_forms_ie.scss
221
225
  - vendor/assets/ui_alchemy/alchemy-forms/_forms_responsive.scss
222
226
  - vendor/assets/ui_alchemy/alchemy-forms/_forms_mixins.scss
@@ -237,6 +241,10 @@ files:
237
241
  - vendor/assets/ui_alchemy/alchemy/component.json
238
242
  - vendor/assets/ui_alchemy/alchemy/alchemy.css
239
243
  - vendor/assets/ui_alchemy/alchemy/alchemy.scss
244
+ - vendor/assets/ui_alchemy/alchemy-header/component.json
245
+ - vendor/assets/ui_alchemy/alchemy-header/header.scss
246
+ - vendor/assets/ui_alchemy/alchemy-header/alchemy-header.js
247
+ - vendor/assets/ui_alchemy/alchemy-header/alchemy-header.css
240
248
  - vendor/assets/ui_alchemy/alchemy-buttons/buttons.scss
241
249
  - vendor/assets/ui_alchemy/alchemy-buttons/component.json
242
250
  - vendor/assets/ui_alchemy/alchemy-buttons/alchemy-buttons.css