bastion 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (278) hide show
  1. checksums.yaml +15 -0
  2. data/.jshintrc +35 -0
  3. data/Gruntfile.js +24 -0
  4. data/LICENSE +339 -0
  5. data/README.md +8 -0
  6. data/Rakefile +53 -0
  7. data/app/assets/javascripts/bastion/auth/auth.module.js +87 -0
  8. data/app/assets/javascripts/bastion/auth/authorization.service.js +48 -0
  9. data/app/assets/javascripts/bastion/bastion-bootstrap.js +32 -0
  10. data/app/assets/javascripts/bastion/bastion-resource.factory.js +39 -0
  11. data/app/assets/javascripts/bastion/bastion.js +52 -0
  12. data/app/assets/javascripts/bastion/bastion.module.js +213 -0
  13. data/app/assets/javascripts/bastion/i18n/README +9 -0
  14. data/app/assets/javascripts/bastion/i18n/i18n.module.js +24 -0
  15. data/app/assets/javascripts/bastion/i18n/katello.pot +968 -0
  16. data/app/assets/javascripts/bastion/i18n/locale/README +1 -0
  17. data/app/assets/javascripts/bastion/i18n/translate.service.js +14 -0
  18. data/app/assets/javascripts/bastion/i18n/translations.js +3 -0
  19. data/app/assets/javascripts/bastion/i18n/zanata.xml +28 -0
  20. data/app/assets/javascripts/bastion/incubator/alch-alert.directive.js +67 -0
  21. data/app/assets/javascripts/bastion/incubator/alch-container-scroll.directive.js +44 -0
  22. data/app/assets/javascripts/bastion/incubator/alch-dropdown.directive.js +28 -0
  23. data/app/assets/javascripts/bastion/incubator/alch-edit.directive.js +361 -0
  24. data/app/assets/javascripts/bastion/incubator/alch-flyout.directive.js +19 -0
  25. data/app/assets/javascripts/bastion/incubator/alch-form-buttons.directive.js +60 -0
  26. data/app/assets/javascripts/bastion/incubator/alch-form-group.directive.js +87 -0
  27. data/app/assets/javascripts/bastion/incubator/alch-infinite-scroll.directive.js +84 -0
  28. data/app/assets/javascripts/bastion/incubator/alch-menu.directive.js +56 -0
  29. data/app/assets/javascripts/bastion/incubator/alch-modal.directive.js +80 -0
  30. data/app/assets/javascripts/bastion/incubator/alch-save-control.directive.js +42 -0
  31. data/app/assets/javascripts/bastion/incubator/alch-table.directive.js +295 -0
  32. data/app/assets/javascripts/bastion/incubator/format/alch-format.module.js +21 -0
  33. data/app/assets/javascripts/bastion/incubator/format/array-to-string.filter.js +30 -0
  34. data/app/assets/javascripts/bastion/incubator/format/boolean-to-yes-no.filter.js +34 -0
  35. data/app/assets/javascripts/bastion/incubator/format/capitalize.filter.js +32 -0
  36. data/app/assets/javascripts/bastion/incubator/format/key-value-to-string.filter.js +40 -0
  37. data/app/assets/javascripts/bastion/incubator/format/unlimitedFilter.filter.js +35 -0
  38. data/app/assets/javascripts/bastion/incubator/stylesheets/alch-edit.scss +34 -0
  39. data/app/assets/javascripts/bastion/incubator/stylesheets/header.scss +207 -0
  40. data/app/assets/javascripts/bastion/incubator/views/alch-alert.html +6 -0
  41. data/app/assets/javascripts/bastion/incubator/views/alch-dropdown.html +19 -0
  42. data/app/assets/javascripts/bastion/incubator/views/alch-edit-add-item.html +21 -0
  43. data/app/assets/javascripts/bastion/incubator/views/alch-edit-add-remove-cancel.html +28 -0
  44. data/app/assets/javascripts/bastion/incubator/views/alch-edit-checkbox.html +6 -0
  45. data/app/assets/javascripts/bastion/incubator/views/alch-edit-custom.html +8 -0
  46. data/app/assets/javascripts/bastion/incubator/views/alch-edit-multiselect.html +17 -0
  47. data/app/assets/javascripts/bastion/incubator/views/alch-edit-save-cancel.html +20 -0
  48. data/app/assets/javascripts/bastion/incubator/views/alch-edit-select.html +10 -0
  49. data/app/assets/javascripts/bastion/incubator/views/alch-edit-text.html +6 -0
  50. data/app/assets/javascripts/bastion/incubator/views/alch-edit-textarea.html +6 -0
  51. data/app/assets/javascripts/bastion/incubator/views/alch-edit.html +18 -0
  52. data/app/assets/javascripts/bastion/incubator/views/alch-flyout.html +10 -0
  53. data/app/assets/javascripts/bastion/incubator/views/alch-form-buttons.html +10 -0
  54. data/app/assets/javascripts/bastion/incubator/views/alch-form-group.html +9 -0
  55. data/app/assets/javascripts/bastion/incubator/views/alch-menu.html +18 -0
  56. data/app/assets/javascripts/bastion/incubator/views/alch-modal-remove.html +13 -0
  57. data/app/assets/javascripts/bastion/incubator/views/alch-save-control.html +18 -0
  58. data/app/assets/javascripts/bastion/layouts/details-nutupane.html +73 -0
  59. data/app/assets/javascripts/bastion/layouts/nutupane.html +63 -0
  60. data/app/assets/javascripts/bastion/layouts/select-all-results.html +9 -0
  61. data/app/assets/javascripts/bastion/menu/menu-expander.service.js +51 -0
  62. data/app/assets/javascripts/bastion/menu/menu.module.js +26 -0
  63. data/app/assets/javascripts/bastion/utils/as.filter.js +33 -0
  64. data/app/assets/javascripts/bastion/utils/form-utils.service.js +53 -0
  65. data/app/assets/javascripts/bastion/utils/utils.module.js +21 -0
  66. data/app/assets/javascripts/bastion/widgets/current-tasks.directive.js +67 -0
  67. data/app/assets/javascripts/bastion/widgets/nutupane-table.directive.js +59 -0
  68. data/app/assets/javascripts/bastion/widgets/nutupane.factory.js +316 -0
  69. data/app/assets/javascripts/bastion/widgets/page-title.directive.js +61 -0
  70. data/app/assets/javascripts/bastion/widgets/page-title.service.js +42 -0
  71. data/app/assets/javascripts/bastion/widgets/path-selector.directive.js +109 -0
  72. data/app/assets/javascripts/bastion/widgets/views/current-tasks.html +23 -0
  73. data/app/assets/javascripts/bastion/widgets/views/path-selector.html +11 -0
  74. data/app/assets/javascripts/bastion/widgets/widgets.module.js +24 -0
  75. data/app/assets/stylesheets/bastion/animations.less +15 -0
  76. data/app/assets/stylesheets/bastion/bastion.less +160 -0
  77. data/app/assets/stylesheets/bastion/forms.less +41 -0
  78. data/app/assets/stylesheets/bastion/gpg-keys.less +36 -0
  79. data/app/assets/stylesheets/bastion/helpers.less +6 -0
  80. data/app/assets/stylesheets/bastion/mixins.less +15 -0
  81. data/app/assets/stylesheets/bastion/nutupane.less +382 -0
  82. data/app/assets/stylesheets/bastion/overrides.less +54 -0
  83. data/app/assets/stylesheets/bastion/path-selector.less +123 -0
  84. data/app/assets/stylesheets/bastion/systems.less +35 -0
  85. data/app/assets/stylesheets/bastion/tasks.less +23 -0
  86. data/app/assets/stylesheets/bastion/typography.less +31 -0
  87. data/app/assets/stylesheets/bastion/variables.less +3 -0
  88. data/app/controllers/bastion/bastion_controller.rb +24 -0
  89. data/app/views/bastion/layouts/application.html.erb +32 -0
  90. data/app/views/bastion/layouts/application_ie.html.erb +5 -0
  91. data/bastion.js +26 -0
  92. data/bower.json +94 -0
  93. data/config/routes.rb +25 -0
  94. data/config/routes/mount_engine.rb +3 -0
  95. data/grunt/bower.js +20 -0
  96. data/grunt/htmlhint.js +15 -0
  97. data/grunt/jshint.js +9 -0
  98. data/grunt/karma.js +83 -0
  99. data/lib/bastion.rb +17 -0
  100. data/lib/bastion/engine.rb +37 -0
  101. data/lib/bastion/version.rb +3 -0
  102. data/package.json +29 -0
  103. data/test/auth/authorization.service.test.js +63 -0
  104. data/test/bastion/bastion-resource.factory.test.js +31 -0
  105. data/test/bastion/test-constants.js +30 -0
  106. data/test/i18n/translate.service.test.js +31 -0
  107. data/test/incubator/alch-alert.directive.test.js +84 -0
  108. data/test/incubator/alch-container-scroll.directive.test.js +68 -0
  109. data/test/incubator/alch-dropdown.directive.test.js +113 -0
  110. data/test/incubator/alch-edit.directive.test.js +320 -0
  111. data/test/incubator/alch-flyout.directive.test.js +73 -0
  112. data/test/incubator/alch-form-buttons.directive.test.js +55 -0
  113. data/test/incubator/alch-form-group.directive.test.js +76 -0
  114. data/test/incubator/alch-infinite-scroll.directive.test.js +123 -0
  115. data/test/incubator/alch-menu.directive.test.js +94 -0
  116. data/test/incubator/alch-modal.directive.test.js +81 -0
  117. data/test/incubator/alch-table.directive.test.js +270 -0
  118. data/test/incubator/format/array-to-string.filter.test.js +38 -0
  119. data/test/incubator/format/boolean-to-yes-no.filter.test.js +41 -0
  120. data/test/incubator/format/capitalize.filter.test.js +35 -0
  121. data/test/incubator/format/key-value-to-string.filter.test.js +60 -0
  122. data/test/incubator/format/unlimited-filter.filter.test.js +31 -0
  123. data/test/incubator/nutupane-table.directive.test.js +69 -0
  124. data/test/incubator/nutupane.factory.test.js +307 -0
  125. data/test/menu/menu-expander.service.test.js +74 -0
  126. data/test/test-mocks.module.js +268 -0
  127. data/test/utils/as.filter.test.js +33 -0
  128. data/test/utils/form-utils.service.test.js +52 -0
  129. data/test/widgets/page-title.directive.test.js +54 -0
  130. data/test/widgets/page-title.service.test.js +51 -0
  131. data/test/widgets/path-selector.directive.test.js +136 -0
  132. data/vendor/assets/fonts/bastion/bootstrap/glyphicons-halflings-regular.eot +0 -0
  133. data/vendor/assets/fonts/bastion/bootstrap/glyphicons-halflings-regular.svg +229 -0
  134. data/vendor/assets/fonts/bastion/bootstrap/glyphicons-halflings-regular.ttf +0 -0
  135. data/vendor/assets/fonts/bastion/bootstrap/glyphicons-halflings-regular.woff +0 -0
  136. data/vendor/assets/fonts/bastion/font-awesome/FontAwesome.otf +0 -0
  137. data/vendor/assets/fonts/bastion/font-awesome/fontawesome-webfont.eot +0 -0
  138. data/vendor/assets/fonts/bastion/font-awesome/fontawesome-webfont.svg +399 -0
  139. data/vendor/assets/fonts/bastion/font-awesome/fontawesome-webfont.ttf +0 -0
  140. data/vendor/assets/fonts/bastion/font-awesome/fontawesome-webfont.woff +0 -0
  141. data/vendor/assets/fonts/bastion/rcue/OpenSans-Bold-webfont.eot +0 -0
  142. data/vendor/assets/fonts/bastion/rcue/OpenSans-Bold-webfont.svg +146 -0
  143. data/vendor/assets/fonts/bastion/rcue/OpenSans-Bold-webfont.ttf +0 -0
  144. data/vendor/assets/fonts/bastion/rcue/OpenSans-Bold-webfont.woff +0 -0
  145. data/vendor/assets/fonts/bastion/rcue/OpenSans-BoldItalic-webfont.eot +0 -0
  146. data/vendor/assets/fonts/bastion/rcue/OpenSans-BoldItalic-webfont.svg +146 -0
  147. data/vendor/assets/fonts/bastion/rcue/OpenSans-BoldItalic-webfont.ttf +0 -0
  148. data/vendor/assets/fonts/bastion/rcue/OpenSans-BoldItalic-webfont.woff +0 -0
  149. data/vendor/assets/fonts/bastion/rcue/OpenSans-ExtraBold-webfont.eot +0 -0
  150. data/vendor/assets/fonts/bastion/rcue/OpenSans-ExtraBold-webfont.svg +146 -0
  151. data/vendor/assets/fonts/bastion/rcue/OpenSans-ExtraBold-webfont.ttf +0 -0
  152. data/vendor/assets/fonts/bastion/rcue/OpenSans-ExtraBold-webfont.woff +0 -0
  153. data/vendor/assets/fonts/bastion/rcue/OpenSans-ExtraBoldItalic-webfont.eot +0 -0
  154. data/vendor/assets/fonts/bastion/rcue/OpenSans-ExtraBoldItalic-webfont.svg +146 -0
  155. data/vendor/assets/fonts/bastion/rcue/OpenSans-ExtraBoldItalic-webfont.ttf +0 -0
  156. data/vendor/assets/fonts/bastion/rcue/OpenSans-ExtraBoldItalic-webfont.woff +0 -0
  157. data/vendor/assets/fonts/bastion/rcue/OpenSans-Italic-webfont.eot +0 -0
  158. data/vendor/assets/fonts/bastion/rcue/OpenSans-Italic-webfont.svg +146 -0
  159. data/vendor/assets/fonts/bastion/rcue/OpenSans-Italic-webfont.ttf +0 -0
  160. data/vendor/assets/fonts/bastion/rcue/OpenSans-Italic-webfont.woff +0 -0
  161. data/vendor/assets/fonts/bastion/rcue/OpenSans-Light-webfont.eot +0 -0
  162. data/vendor/assets/fonts/bastion/rcue/OpenSans-Light-webfont.svg +146 -0
  163. data/vendor/assets/fonts/bastion/rcue/OpenSans-Light-webfont.ttf +0 -0
  164. data/vendor/assets/fonts/bastion/rcue/OpenSans-Light-webfont.woff +0 -0
  165. data/vendor/assets/fonts/bastion/rcue/OpenSans-LightItalic-webfont.eot +0 -0
  166. data/vendor/assets/fonts/bastion/rcue/OpenSans-LightItalic-webfont.svg +146 -0
  167. data/vendor/assets/fonts/bastion/rcue/OpenSans-LightItalic-webfont.ttf +0 -0
  168. data/vendor/assets/fonts/bastion/rcue/OpenSans-LightItalic-webfont.woff +0 -0
  169. data/vendor/assets/fonts/bastion/rcue/OpenSans-Regular-webfont.eot +0 -0
  170. data/vendor/assets/fonts/bastion/rcue/OpenSans-Regular-webfont.svg +146 -0
  171. data/vendor/assets/fonts/bastion/rcue/OpenSans-Regular-webfont.ttf +0 -0
  172. data/vendor/assets/fonts/bastion/rcue/OpenSans-Regular-webfont.woff +0 -0
  173. data/vendor/assets/fonts/bastion/rcue/OpenSans-Semibold-webfont.eot +0 -0
  174. data/vendor/assets/fonts/bastion/rcue/OpenSans-Semibold-webfont.svg +146 -0
  175. data/vendor/assets/fonts/bastion/rcue/OpenSans-Semibold-webfont.ttf +0 -0
  176. data/vendor/assets/fonts/bastion/rcue/OpenSans-Semibold-webfont.woff +0 -0
  177. data/vendor/assets/fonts/bastion/rcue/OpenSans-SemiboldItalic-webfont.eot +0 -0
  178. data/vendor/assets/fonts/bastion/rcue/OpenSans-SemiboldItalic-webfont.svg +146 -0
  179. data/vendor/assets/fonts/bastion/rcue/OpenSans-SemiboldItalic-webfont.ttf +0 -0
  180. data/vendor/assets/fonts/bastion/rcue/OpenSans-SemiboldItalic-webfont.woff +0 -0
  181. data/vendor/assets/fonts/bastion/rcue/Overpass-Bold-webfont.eot +0 -0
  182. data/vendor/assets/fonts/bastion/rcue/Overpass-Bold-webfont.svg +454 -0
  183. data/vendor/assets/fonts/bastion/rcue/Overpass-Bold-webfont.ttf +0 -0
  184. data/vendor/assets/fonts/bastion/rcue/Overpass-Bold-webfont.woff +0 -0
  185. data/vendor/assets/fonts/bastion/rcue/Overpass-Regular-webfont.eot +0 -0
  186. data/vendor/assets/fonts/bastion/rcue/Overpass-Regular-webfont.svg +454 -0
  187. data/vendor/assets/fonts/bastion/rcue/Overpass-Regular-webfont.ttf +0 -0
  188. data/vendor/assets/fonts/bastion/rcue/Overpass-Regular-webfont.woff +0 -0
  189. data/vendor/assets/javascripts/bastion/alchemy/alchemy.js +20 -0
  190. data/vendor/assets/javascripts/bastion/angular-animate/angular-animate.js +1226 -0
  191. data/vendor/assets/javascripts/bastion/angular-blocks/angular-blocks.js +79 -0
  192. data/vendor/assets/javascripts/bastion/angular-bootstrap/ui-bootstrap-tpls.js +3677 -0
  193. data/vendor/assets/javascripts/bastion/angular-bootstrap/ui-bootstrap.js +3427 -0
  194. data/vendor/assets/javascripts/bastion/angular-gettext/angular-gettext.js +345 -0
  195. data/vendor/assets/javascripts/bastion/angular-resource/angular-resource.js +594 -0
  196. data/vendor/assets/javascripts/bastion/angular-route/angular-route.js +920 -0
  197. data/vendor/assets/javascripts/bastion/angular-sanitize/angular-sanitize.js +622 -0
  198. data/vendor/assets/javascripts/bastion/angular-ui-bootstrap/datepicker.js +447 -0
  199. data/vendor/assets/javascripts/bastion/angular-ui-bootstrap/timepicker.js +232 -0
  200. data/vendor/assets/javascripts/bastion/angular-ui-router/angular-ui-router.js +3223 -0
  201. data/vendor/assets/javascripts/bastion/angular-uuid4/angular-uuid4.js +21 -0
  202. data/vendor/assets/javascripts/bastion/angular/angular.js +20560 -0
  203. data/vendor/assets/javascripts/bastion/es5-shim/es5-shim.js +1216 -0
  204. data/vendor/assets/javascripts/bastion/json3/json3.js +861 -0
  205. data/vendor/assets/javascripts/bastion/ngUpload/ng-upload.js +205 -0
  206. data/vendor/assets/javascripts/bastion/underscore/underscore.js +1276 -0
  207. data/vendor/assets/stylesheets/bastion/alchemy/_colors.scss +99 -0
  208. data/vendor/assets/stylesheets/bastion/alchemy/_media_object.scss +22 -0
  209. data/vendor/assets/stylesheets/bastion/alchemy/_mixins.scss +24 -0
  210. data/vendor/assets/stylesheets/bastion/alchemy/_normalize.scss +396 -0
  211. data/vendor/assets/stylesheets/bastion/alchemy/_vars.scss +31 -0
  212. data/vendor/assets/stylesheets/bastion/alchemy/alchemy.scss +8 -0
  213. data/vendor/assets/stylesheets/bastion/bootstrap/alerts.less +67 -0
  214. data/vendor/assets/stylesheets/bastion/bootstrap/badges.less +51 -0
  215. data/vendor/assets/stylesheets/bastion/bootstrap/bootstrap.less +49 -0
  216. data/vendor/assets/stylesheets/bastion/bootstrap/breadcrumbs.less +23 -0
  217. data/vendor/assets/stylesheets/bastion/bootstrap/button-groups.less +227 -0
  218. data/vendor/assets/stylesheets/bastion/bootstrap/buttons.less +155 -0
  219. data/vendor/assets/stylesheets/bastion/bootstrap/carousel.less +232 -0
  220. data/vendor/assets/stylesheets/bastion/bootstrap/close.less +33 -0
  221. data/vendor/assets/stylesheets/bastion/bootstrap/code.less +53 -0
  222. data/vendor/assets/stylesheets/bastion/bootstrap/component-animations.less +29 -0
  223. data/vendor/assets/stylesheets/bastion/bootstrap/dropdowns.less +187 -0
  224. data/vendor/assets/stylesheets/bastion/bootstrap/forms.less +375 -0
  225. data/vendor/assets/stylesheets/bastion/bootstrap/glyphicons.less +237 -0
  226. data/vendor/assets/stylesheets/bastion/bootstrap/grid.less +79 -0
  227. data/vendor/assets/stylesheets/bastion/bootstrap/input-groups.less +136 -0
  228. data/vendor/assets/stylesheets/bastion/bootstrap/jumbotron.less +46 -0
  229. data/vendor/assets/stylesheets/bastion/bootstrap/labels.less +64 -0
  230. data/vendor/assets/stylesheets/bastion/bootstrap/list-group.less +88 -0
  231. data/vendor/assets/stylesheets/bastion/bootstrap/media.less +56 -0
  232. data/vendor/assets/stylesheets/bastion/bootstrap/mixins.less +845 -0
  233. data/vendor/assets/stylesheets/bastion/bootstrap/modals.less +129 -0
  234. data/vendor/assets/stylesheets/bastion/bootstrap/navbar.less +612 -0
  235. data/vendor/assets/stylesheets/bastion/bootstrap/navs.less +242 -0
  236. data/vendor/assets/stylesheets/bastion/bootstrap/normalize.less +406 -0
  237. data/vendor/assets/stylesheets/bastion/bootstrap/pager.less +55 -0
  238. data/vendor/assets/stylesheets/bastion/bootstrap/pagination.less +85 -0
  239. data/vendor/assets/stylesheets/bastion/bootstrap/panels.less +182 -0
  240. data/vendor/assets/stylesheets/bastion/bootstrap/popovers.less +133 -0
  241. data/vendor/assets/stylesheets/bastion/bootstrap/print.less +105 -0
  242. data/vendor/assets/stylesheets/bastion/bootstrap/progress-bars.less +80 -0
  243. data/vendor/assets/stylesheets/bastion/bootstrap/responsive-utilities.less +209 -0
  244. data/vendor/assets/stylesheets/bastion/bootstrap/scaffolding.less +119 -0
  245. data/vendor/assets/stylesheets/bastion/bootstrap/tables.less +231 -0
  246. data/vendor/assets/stylesheets/bastion/bootstrap/theme.less +247 -0
  247. data/vendor/assets/stylesheets/bastion/bootstrap/thumbnails.less +36 -0
  248. data/vendor/assets/stylesheets/bastion/bootstrap/tooltip.less +95 -0
  249. data/vendor/assets/stylesheets/bastion/bootstrap/type.less +281 -0
  250. data/vendor/assets/stylesheets/bastion/bootstrap/utilities.less +56 -0
  251. data/vendor/assets/stylesheets/bastion/bootstrap/variables.less +642 -0
  252. data/vendor/assets/stylesheets/bastion/bootstrap/wells.less +29 -0
  253. data/vendor/assets/stylesheets/bastion/font-awesome/less/bootstrap.less +84 -0
  254. data/vendor/assets/stylesheets/bastion/font-awesome/less/core.less +129 -0
  255. data/vendor/assets/stylesheets/bastion/font-awesome/less/extras.less +93 -0
  256. data/vendor/assets/stylesheets/bastion/font-awesome/less/font-awesome-ie7.less +1953 -0
  257. data/vendor/assets/stylesheets/bastion/font-awesome/less/font-awesome.less +33 -0
  258. data/vendor/assets/stylesheets/bastion/font-awesome/less/icons.less +381 -0
  259. data/vendor/assets/stylesheets/bastion/font-awesome/less/mixins.less +48 -0
  260. data/vendor/assets/stylesheets/bastion/font-awesome/less/path.less +14 -0
  261. data/vendor/assets/stylesheets/bastion/font-awesome/less/variables.less +735 -0
  262. data/vendor/assets/stylesheets/bastion/font-awesome/scss/_bootstrap.scss +84 -0
  263. data/vendor/assets/stylesheets/bastion/font-awesome/scss/_core.scss +129 -0
  264. data/vendor/assets/stylesheets/bastion/font-awesome/scss/_extras.scss +93 -0
  265. data/vendor/assets/stylesheets/bastion/font-awesome/scss/_icons.scss +381 -0
  266. data/vendor/assets/stylesheets/bastion/font-awesome/scss/_mixins.scss +48 -0
  267. data/vendor/assets/stylesheets/bastion/font-awesome/scss/_path.scss +14 -0
  268. data/vendor/assets/stylesheets/bastion/font-awesome/scss/_variables.scss +734 -0
  269. data/vendor/assets/stylesheets/bastion/font-awesome/scss/font-awesome-ie7.scss +1953 -0
  270. data/vendor/assets/stylesheets/bastion/font-awesome/scss/font-awesome.scss +33 -0
  271. data/vendor/assets/stylesheets/bastion/rcue/buttons.less +44 -0
  272. data/vendor/assets/stylesheets/bastion/rcue/fonts.less +52 -0
  273. data/vendor/assets/stylesheets/bastion/rcue/forms.less +19 -0
  274. data/vendor/assets/stylesheets/bastion/rcue/mixins.less +50 -0
  275. data/vendor/assets/stylesheets/bastion/rcue/navbar.less +481 -0
  276. data/vendor/assets/stylesheets/bastion/rcue/rcue.less +15 -0
  277. data/vendor/assets/stylesheets/bastion/rcue/variables.less +47 -0
  278. metadata +376 -0
@@ -0,0 +1,622 @@
1
+ /**
2
+ * @license AngularJS v1.2.9
3
+ * (c) 2010-2014 Google, Inc. http://angularjs.org
4
+ * License: MIT
5
+ */
6
+ (function(window, angular, undefined) {'use strict';
7
+
8
+ var $sanitizeMinErr = angular.$$minErr('$sanitize');
9
+
10
+ /**
11
+ * @ngdoc overview
12
+ * @name ngSanitize
13
+ * @description
14
+ *
15
+ * # ngSanitize
16
+ *
17
+ * The `ngSanitize` module provides functionality to sanitize HTML.
18
+ *
19
+ * {@installModule sanitize}
20
+ *
21
+ * <div doc-module-components="ngSanitize"></div>
22
+ *
23
+ * See {@link ngSanitize.$sanitize `$sanitize`} for usage.
24
+ */
25
+
26
+ /*
27
+ * HTML Parser By Misko Hevery (misko@hevery.com)
28
+ * based on: HTML Parser By John Resig (ejohn.org)
29
+ * Original code by Erik Arvidsson, Mozilla Public License
30
+ * http://erik.eae.net/simplehtmlparser/simplehtmlparser.js
31
+ *
32
+ * // Use like so:
33
+ * htmlParser(htmlString, {
34
+ * start: function(tag, attrs, unary) {},
35
+ * end: function(tag) {},
36
+ * chars: function(text) {},
37
+ * comment: function(text) {}
38
+ * });
39
+ *
40
+ */
41
+
42
+
43
+ /**
44
+ * @ngdoc service
45
+ * @name ngSanitize.$sanitize
46
+ * @function
47
+ *
48
+ * @description
49
+ * The input is sanitized by parsing the html into tokens. All safe tokens (from a whitelist) are
50
+ * then serialized back to properly escaped html string. This means that no unsafe input can make
51
+ * it into the returned string, however, since our parser is more strict than a typical browser
52
+ * parser, it's possible that some obscure input, which would be recognized as valid HTML by a
53
+ * browser, won't make it through the sanitizer.
54
+ * The whitelist is configured using the functions `aHrefSanitizationWhitelist` and
55
+ * `imgSrcSanitizationWhitelist` of {@link ng.$compileProvider `$compileProvider`}.
56
+ *
57
+ * @param {string} html Html input.
58
+ * @returns {string} Sanitized html.
59
+ *
60
+ * @example
61
+ <doc:example module="ngSanitize">
62
+ <doc:source>
63
+ <script>
64
+ function Ctrl($scope, $sce) {
65
+ $scope.snippet =
66
+ '<p style="color:blue">an html\n' +
67
+ '<em onmouseover="this.textContent=\'PWN3D!\'">click here</em>\n' +
68
+ 'snippet</p>';
69
+ $scope.deliberatelyTrustDangerousSnippet = function() {
70
+ return $sce.trustAsHtml($scope.snippet);
71
+ };
72
+ }
73
+ </script>
74
+ <div ng-controller="Ctrl">
75
+ Snippet: <textarea ng-model="snippet" cols="60" rows="3"></textarea>
76
+ <table>
77
+ <tr>
78
+ <td>Directive</td>
79
+ <td>How</td>
80
+ <td>Source</td>
81
+ <td>Rendered</td>
82
+ </tr>
83
+ <tr id="bind-html-with-sanitize">
84
+ <td>ng-bind-html</td>
85
+ <td>Automatically uses $sanitize</td>
86
+ <td><pre>&lt;div ng-bind-html="snippet"&gt;<br/>&lt;/div&gt;</pre></td>
87
+ <td><div ng-bind-html="snippet"></div></td>
88
+ </tr>
89
+ <tr id="bind-html-with-trust">
90
+ <td>ng-bind-html</td>
91
+ <td>Bypass $sanitize by explicitly trusting the dangerous value</td>
92
+ <td>
93
+ <pre>&lt;div ng-bind-html="deliberatelyTrustDangerousSnippet()"&gt;
94
+ &lt;/div&gt;</pre>
95
+ </td>
96
+ <td><div ng-bind-html="deliberatelyTrustDangerousSnippet()"></div></td>
97
+ </tr>
98
+ <tr id="bind-default">
99
+ <td>ng-bind</td>
100
+ <td>Automatically escapes</td>
101
+ <td><pre>&lt;div ng-bind="snippet"&gt;<br/>&lt;/div&gt;</pre></td>
102
+ <td><div ng-bind="snippet"></div></td>
103
+ </tr>
104
+ </table>
105
+ </div>
106
+ </doc:source>
107
+ <doc:scenario>
108
+ it('should sanitize the html snippet by default', function() {
109
+ expect(using('#bind-html-with-sanitize').element('div').html()).
110
+ toBe('<p>an html\n<em>click here</em>\nsnippet</p>');
111
+ });
112
+
113
+ it('should inline raw snippet if bound to a trusted value', function() {
114
+ expect(using('#bind-html-with-trust').element("div").html()).
115
+ toBe("<p style=\"color:blue\">an html\n" +
116
+ "<em onmouseover=\"this.textContent='PWN3D!'\">click here</em>\n" +
117
+ "snippet</p>");
118
+ });
119
+
120
+ it('should escape snippet without any filter', function() {
121
+ expect(using('#bind-default').element('div').html()).
122
+ toBe("&lt;p style=\"color:blue\"&gt;an html\n" +
123
+ "&lt;em onmouseover=\"this.textContent='PWN3D!'\"&gt;click here&lt;/em&gt;\n" +
124
+ "snippet&lt;/p&gt;");
125
+ });
126
+
127
+ it('should update', function() {
128
+ input('snippet').enter('new <b onclick="alert(1)">text</b>');
129
+ expect(using('#bind-html-with-sanitize').element('div').html()).toBe('new <b>text</b>');
130
+ expect(using('#bind-html-with-trust').element('div').html()).toBe(
131
+ 'new <b onclick="alert(1)">text</b>');
132
+ expect(using('#bind-default').element('div').html()).toBe(
133
+ "new &lt;b onclick=\"alert(1)\"&gt;text&lt;/b&gt;");
134
+ });
135
+ </doc:scenario>
136
+ </doc:example>
137
+ */
138
+ function $SanitizeProvider() {
139
+ this.$get = ['$$sanitizeUri', function($$sanitizeUri) {
140
+ return function(html) {
141
+ var buf = [];
142
+ htmlParser(html, htmlSanitizeWriter(buf, function(uri, isImage) {
143
+ return !/^unsafe/.test($$sanitizeUri(uri, isImage));
144
+ }));
145
+ return buf.join('');
146
+ };
147
+ }];
148
+ }
149
+
150
+ function sanitizeText(chars) {
151
+ var buf = [];
152
+ var writer = htmlSanitizeWriter(buf, angular.noop);
153
+ writer.chars(chars);
154
+ return buf.join('');
155
+ }
156
+
157
+
158
+ // Regular Expressions for parsing tags and attributes
159
+ var START_TAG_REGEXP =
160
+ /^<\s*([\w:-]+)((?:\s+[\w:-]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)\s*>/,
161
+ END_TAG_REGEXP = /^<\s*\/\s*([\w:-]+)[^>]*>/,
162
+ ATTR_REGEXP = /([\w:-]+)(?:\s*=\s*(?:(?:"((?:[^"])*)")|(?:'((?:[^'])*)')|([^>\s]+)))?/g,
163
+ BEGIN_TAG_REGEXP = /^</,
164
+ BEGING_END_TAGE_REGEXP = /^<\s*\//,
165
+ COMMENT_REGEXP = /<!--(.*?)-->/g,
166
+ DOCTYPE_REGEXP = /<!DOCTYPE([^>]*?)>/i,
167
+ CDATA_REGEXP = /<!\[CDATA\[(.*?)]]>/g,
168
+ // Match everything outside of normal chars and " (quote character)
169
+ NON_ALPHANUMERIC_REGEXP = /([^\#-~| |!])/g;
170
+
171
+
172
+ // Good source of info about elements and attributes
173
+ // http://dev.w3.org/html5/spec/Overview.html#semantics
174
+ // http://simon.html5.org/html-elements
175
+
176
+ // Safe Void Elements - HTML5
177
+ // http://dev.w3.org/html5/spec/Overview.html#void-elements
178
+ var voidElements = makeMap("area,br,col,hr,img,wbr");
179
+
180
+ // Elements that you can, intentionally, leave open (and which close themselves)
181
+ // http://dev.w3.org/html5/spec/Overview.html#optional-tags
182
+ var optionalEndTagBlockElements = makeMap("colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr"),
183
+ optionalEndTagInlineElements = makeMap("rp,rt"),
184
+ optionalEndTagElements = angular.extend({},
185
+ optionalEndTagInlineElements,
186
+ optionalEndTagBlockElements);
187
+
188
+ // Safe Block Elements - HTML5
189
+ var blockElements = angular.extend({}, optionalEndTagBlockElements, makeMap("address,article," +
190
+ "aside,blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5," +
191
+ "h6,header,hgroup,hr,ins,map,menu,nav,ol,pre,script,section,table,ul"));
192
+
193
+ // Inline Elements - HTML5
194
+ var inlineElements = angular.extend({}, optionalEndTagInlineElements, makeMap("a,abbr,acronym,b," +
195
+ "bdi,bdo,big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s," +
196
+ "samp,small,span,strike,strong,sub,sup,time,tt,u,var"));
197
+
198
+
199
+ // Special Elements (can contain anything)
200
+ var specialElements = makeMap("script,style");
201
+
202
+ var validElements = angular.extend({},
203
+ voidElements,
204
+ blockElements,
205
+ inlineElements,
206
+ optionalEndTagElements);
207
+
208
+ //Attributes that have href and hence need to be sanitized
209
+ var uriAttrs = makeMap("background,cite,href,longdesc,src,usemap");
210
+ var validAttrs = angular.extend({}, uriAttrs, makeMap(
211
+ 'abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,'+
212
+ 'color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,'+
213
+ 'ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,'+
214
+ 'scope,scrolling,shape,size,span,start,summary,target,title,type,'+
215
+ 'valign,value,vspace,width'));
216
+
217
+ function makeMap(str) {
218
+ var obj = {}, items = str.split(','), i;
219
+ for (i = 0; i < items.length; i++) obj[items[i]] = true;
220
+ return obj;
221
+ }
222
+
223
+
224
+ /**
225
+ * @example
226
+ * htmlParser(htmlString, {
227
+ * start: function(tag, attrs, unary) {},
228
+ * end: function(tag) {},
229
+ * chars: function(text) {},
230
+ * comment: function(text) {}
231
+ * });
232
+ *
233
+ * @param {string} html string
234
+ * @param {object} handler
235
+ */
236
+ function htmlParser( html, handler ) {
237
+ var index, chars, match, stack = [], last = html;
238
+ stack.last = function() { return stack[ stack.length - 1 ]; };
239
+
240
+ while ( html ) {
241
+ chars = true;
242
+
243
+ // Make sure we're not in a script or style element
244
+ if ( !stack.last() || !specialElements[ stack.last() ] ) {
245
+
246
+ // Comment
247
+ if ( html.indexOf("<!--") === 0 ) {
248
+ // comments containing -- are not allowed unless they terminate the comment
249
+ index = html.indexOf("--", 4);
250
+
251
+ if ( index >= 0 && html.lastIndexOf("-->", index) === index) {
252
+ if (handler.comment) handler.comment( html.substring( 4, index ) );
253
+ html = html.substring( index + 3 );
254
+ chars = false;
255
+ }
256
+ // DOCTYPE
257
+ } else if ( DOCTYPE_REGEXP.test(html) ) {
258
+ match = html.match( DOCTYPE_REGEXP );
259
+
260
+ if ( match ) {
261
+ html = html.replace( match[0] , '');
262
+ chars = false;
263
+ }
264
+ // end tag
265
+ } else if ( BEGING_END_TAGE_REGEXP.test(html) ) {
266
+ match = html.match( END_TAG_REGEXP );
267
+
268
+ if ( match ) {
269
+ html = html.substring( match[0].length );
270
+ match[0].replace( END_TAG_REGEXP, parseEndTag );
271
+ chars = false;
272
+ }
273
+
274
+ // start tag
275
+ } else if ( BEGIN_TAG_REGEXP.test(html) ) {
276
+ match = html.match( START_TAG_REGEXP );
277
+
278
+ if ( match ) {
279
+ html = html.substring( match[0].length );
280
+ match[0].replace( START_TAG_REGEXP, parseStartTag );
281
+ chars = false;
282
+ }
283
+ }
284
+
285
+ if ( chars ) {
286
+ index = html.indexOf("<");
287
+
288
+ var text = index < 0 ? html : html.substring( 0, index );
289
+ html = index < 0 ? "" : html.substring( index );
290
+
291
+ if (handler.chars) handler.chars( decodeEntities(text) );
292
+ }
293
+
294
+ } else {
295
+ html = html.replace(new RegExp("(.*)<\\s*\\/\\s*" + stack.last() + "[^>]*>", 'i'),
296
+ function(all, text){
297
+ text = text.replace(COMMENT_REGEXP, "$1").replace(CDATA_REGEXP, "$1");
298
+
299
+ if (handler.chars) handler.chars( decodeEntities(text) );
300
+
301
+ return "";
302
+ });
303
+
304
+ parseEndTag( "", stack.last() );
305
+ }
306
+
307
+ if ( html == last ) {
308
+ throw $sanitizeMinErr('badparse', "The sanitizer was unable to parse the following block " +
309
+ "of html: {0}", html);
310
+ }
311
+ last = html;
312
+ }
313
+
314
+ // Clean up any remaining tags
315
+ parseEndTag();
316
+
317
+ function parseStartTag( tag, tagName, rest, unary ) {
318
+ tagName = angular.lowercase(tagName);
319
+ if ( blockElements[ tagName ] ) {
320
+ while ( stack.last() && inlineElements[ stack.last() ] ) {
321
+ parseEndTag( "", stack.last() );
322
+ }
323
+ }
324
+
325
+ if ( optionalEndTagElements[ tagName ] && stack.last() == tagName ) {
326
+ parseEndTag( "", tagName );
327
+ }
328
+
329
+ unary = voidElements[ tagName ] || !!unary;
330
+
331
+ if ( !unary )
332
+ stack.push( tagName );
333
+
334
+ var attrs = {};
335
+
336
+ rest.replace(ATTR_REGEXP,
337
+ function(match, name, doubleQuotedValue, singleQuotedValue, unquotedValue) {
338
+ var value = doubleQuotedValue
339
+ || singleQuotedValue
340
+ || unquotedValue
341
+ || '';
342
+
343
+ attrs[name] = decodeEntities(value);
344
+ });
345
+ if (handler.start) handler.start( tagName, attrs, unary );
346
+ }
347
+
348
+ function parseEndTag( tag, tagName ) {
349
+ var pos = 0, i;
350
+ tagName = angular.lowercase(tagName);
351
+ if ( tagName )
352
+ // Find the closest opened tag of the same type
353
+ for ( pos = stack.length - 1; pos >= 0; pos-- )
354
+ if ( stack[ pos ] == tagName )
355
+ break;
356
+
357
+ if ( pos >= 0 ) {
358
+ // Close all the open elements, up the stack
359
+ for ( i = stack.length - 1; i >= pos; i-- )
360
+ if (handler.end) handler.end( stack[ i ] );
361
+
362
+ // Remove the open elements from the stack
363
+ stack.length = pos;
364
+ }
365
+ }
366
+ }
367
+
368
+ var hiddenPre=document.createElement("pre");
369
+ var spaceRe = /^(\s*)([\s\S]*?)(\s*)$/;
370
+ /**
371
+ * decodes all entities into regular string
372
+ * @param value
373
+ * @returns {string} A string with decoded entities.
374
+ */
375
+ function decodeEntities(value) {
376
+ if (!value) { return ''; }
377
+
378
+ // Note: IE8 does not preserve spaces at the start/end of innerHTML
379
+ // so we must capture them and reattach them afterward
380
+ var parts = spaceRe.exec(value);
381
+ var spaceBefore = parts[1];
382
+ var spaceAfter = parts[3];
383
+ var content = parts[2];
384
+ if (content) {
385
+ hiddenPre.innerHTML=content.replace(/</g,"&lt;");
386
+ // innerText depends on styling as it doesn't display hidden elements.
387
+ // Therefore, it's better to use textContent not to cause unnecessary
388
+ // reflows. However, IE<9 don't support textContent so the innerText
389
+ // fallback is necessary.
390
+ content = 'textContent' in hiddenPre ?
391
+ hiddenPre.textContent : hiddenPre.innerText;
392
+ }
393
+ return spaceBefore + content + spaceAfter;
394
+ }
395
+
396
+ /**
397
+ * Escapes all potentially dangerous characters, so that the
398
+ * resulting string can be safely inserted into attribute or
399
+ * element text.
400
+ * @param value
401
+ * @returns escaped text
402
+ */
403
+ function encodeEntities(value) {
404
+ return value.
405
+ replace(/&/g, '&amp;').
406
+ replace(NON_ALPHANUMERIC_REGEXP, function(value){
407
+ return '&#' + value.charCodeAt(0) + ';';
408
+ }).
409
+ replace(/</g, '&lt;').
410
+ replace(/>/g, '&gt;');
411
+ }
412
+
413
+ /**
414
+ * create an HTML/XML writer which writes to buffer
415
+ * @param {Array} buf use buf.jain('') to get out sanitized html string
416
+ * @returns {object} in the form of {
417
+ * start: function(tag, attrs, unary) {},
418
+ * end: function(tag) {},
419
+ * chars: function(text) {},
420
+ * comment: function(text) {}
421
+ * }
422
+ */
423
+ function htmlSanitizeWriter(buf, uriValidator){
424
+ var ignore = false;
425
+ var out = angular.bind(buf, buf.push);
426
+ return {
427
+ start: function(tag, attrs, unary){
428
+ tag = angular.lowercase(tag);
429
+ if (!ignore && specialElements[tag]) {
430
+ ignore = tag;
431
+ }
432
+ if (!ignore && validElements[tag] === true) {
433
+ out('<');
434
+ out(tag);
435
+ angular.forEach(attrs, function(value, key){
436
+ var lkey=angular.lowercase(key);
437
+ var isImage = (tag === 'img' && lkey === 'src') || (lkey === 'background');
438
+ if (validAttrs[lkey] === true &&
439
+ (uriAttrs[lkey] !== true || uriValidator(value, isImage))) {
440
+ out(' ');
441
+ out(key);
442
+ out('="');
443
+ out(encodeEntities(value));
444
+ out('"');
445
+ }
446
+ });
447
+ out(unary ? '/>' : '>');
448
+ }
449
+ },
450
+ end: function(tag){
451
+ tag = angular.lowercase(tag);
452
+ if (!ignore && validElements[tag] === true) {
453
+ out('</');
454
+ out(tag);
455
+ out('>');
456
+ }
457
+ if (tag == ignore) {
458
+ ignore = false;
459
+ }
460
+ },
461
+ chars: function(chars){
462
+ if (!ignore) {
463
+ out(encodeEntities(chars));
464
+ }
465
+ }
466
+ };
467
+ }
468
+
469
+
470
+ // define ngSanitize module and register $sanitize service
471
+ angular.module('ngSanitize', []).provider('$sanitize', $SanitizeProvider);
472
+
473
+ /* global sanitizeText: false */
474
+
475
+ /**
476
+ * @ngdoc filter
477
+ * @name ngSanitize.filter:linky
478
+ * @function
479
+ *
480
+ * @description
481
+ * Finds links in text input and turns them into html links. Supports http/https/ftp/mailto and
482
+ * plain email address links.
483
+ *
484
+ * Requires the {@link ngSanitize `ngSanitize`} module to be installed.
485
+ *
486
+ * @param {string} text Input text.
487
+ * @param {string} target Window (_blank|_self|_parent|_top) or named frame to open links in.
488
+ * @returns {string} Html-linkified text.
489
+ *
490
+ * @usage
491
+ <span ng-bind-html="linky_expression | linky"></span>
492
+ *
493
+ * @example
494
+ <doc:example module="ngSanitize">
495
+ <doc:source>
496
+ <script>
497
+ function Ctrl($scope) {
498
+ $scope.snippet =
499
+ 'Pretty text with some links:\n'+
500
+ 'http://angularjs.org/,\n'+
501
+ 'mailto:us@somewhere.org,\n'+
502
+ 'another@somewhere.org,\n'+
503
+ 'and one more: ftp://127.0.0.1/.';
504
+ $scope.snippetWithTarget = 'http://angularjs.org/';
505
+ }
506
+ </script>
507
+ <div ng-controller="Ctrl">
508
+ Snippet: <textarea ng-model="snippet" cols="60" rows="3"></textarea>
509
+ <table>
510
+ <tr>
511
+ <td>Filter</td>
512
+ <td>Source</td>
513
+ <td>Rendered</td>
514
+ </tr>
515
+ <tr id="linky-filter">
516
+ <td>linky filter</td>
517
+ <td>
518
+ <pre>&lt;div ng-bind-html="snippet | linky"&gt;<br>&lt;/div&gt;</pre>
519
+ </td>
520
+ <td>
521
+ <div ng-bind-html="snippet | linky"></div>
522
+ </td>
523
+ </tr>
524
+ <tr id="linky-target">
525
+ <td>linky target</td>
526
+ <td>
527
+ <pre>&lt;div ng-bind-html="snippetWithTarget | linky:'_blank'"&gt;<br>&lt;/div&gt;</pre>
528
+ </td>
529
+ <td>
530
+ <div ng-bind-html="snippetWithTarget | linky:'_blank'"></div>
531
+ </td>
532
+ </tr>
533
+ <tr id="escaped-html">
534
+ <td>no filter</td>
535
+ <td><pre>&lt;div ng-bind="snippet"&gt;<br>&lt;/div&gt;</pre></td>
536
+ <td><div ng-bind="snippet"></div></td>
537
+ </tr>
538
+ </table>
539
+ </doc:source>
540
+ <doc:scenario>
541
+ it('should linkify the snippet with urls', function() {
542
+ expect(using('#linky-filter').binding('snippet | linky')).
543
+ toBe('Pretty text with some links:&#10;' +
544
+ '<a href="http://angularjs.org/">http://angularjs.org/</a>,&#10;' +
545
+ '<a href="mailto:us@somewhere.org">us@somewhere.org</a>,&#10;' +
546
+ '<a href="mailto:another@somewhere.org">another@somewhere.org</a>,&#10;' +
547
+ 'and one more: <a href="ftp://127.0.0.1/">ftp://127.0.0.1/</a>.');
548
+ });
549
+
550
+ it ('should not linkify snippet without the linky filter', function() {
551
+ expect(using('#escaped-html').binding('snippet')).
552
+ toBe("Pretty text with some links:\n" +
553
+ "http://angularjs.org/,\n" +
554
+ "mailto:us@somewhere.org,\n" +
555
+ "another@somewhere.org,\n" +
556
+ "and one more: ftp://127.0.0.1/.");
557
+ });
558
+
559
+ it('should update', function() {
560
+ input('snippet').enter('new http://link.');
561
+ expect(using('#linky-filter').binding('snippet | linky')).
562
+ toBe('new <a href="http://link">http://link</a>.');
563
+ expect(using('#escaped-html').binding('snippet')).toBe('new http://link.');
564
+ });
565
+
566
+ it('should work with the target property', function() {
567
+ expect(using('#linky-target').binding("snippetWithTarget | linky:'_blank'")).
568
+ toBe('<a target="_blank" href="http://angularjs.org/">http://angularjs.org/</a>');
569
+ });
570
+ </doc:scenario>
571
+ </doc:example>
572
+ */
573
+ angular.module('ngSanitize').filter('linky', ['$sanitize', function($sanitize) {
574
+ var LINKY_URL_REGEXP =
575
+ /((ftp|https?):\/\/|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s.;,(){}<>]/,
576
+ MAILTO_REGEXP = /^mailto:/;
577
+
578
+ return function(text, target) {
579
+ if (!text) return text;
580
+ var match;
581
+ var raw = text;
582
+ var html = [];
583
+ var url;
584
+ var i;
585
+ while ((match = raw.match(LINKY_URL_REGEXP))) {
586
+ // We can not end in these as they are sometimes found at the end of the sentence
587
+ url = match[0];
588
+ // if we did not match ftp/http/mailto then assume mailto
589
+ if (match[2] == match[3]) url = 'mailto:' + url;
590
+ i = match.index;
591
+ addText(raw.substr(0, i));
592
+ addLink(url, match[0].replace(MAILTO_REGEXP, ''));
593
+ raw = raw.substring(i + match[0].length);
594
+ }
595
+ addText(raw);
596
+ return $sanitize(html.join(''));
597
+
598
+ function addText(text) {
599
+ if (!text) {
600
+ return;
601
+ }
602
+ html.push(sanitizeText(text));
603
+ }
604
+
605
+ function addLink(url, text) {
606
+ html.push('<a ');
607
+ if (angular.isDefined(target)) {
608
+ html.push('target="');
609
+ html.push(target);
610
+ html.push('" ');
611
+ }
612
+ html.push('href="');
613
+ html.push(url);
614
+ html.push('">');
615
+ addText(text);
616
+ html.push('</a>');
617
+ }
618
+ };
619
+ }]);
620
+
621
+
622
+ })(window, window.angular);