sw2at-ui 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (387) hide show
  1. checksums.yaml +7 -0
  2. data/.document +5 -0
  3. data/Gemfile +21 -0
  4. data/LICENSE.txt +20 -0
  5. data/README.rdoc +19 -0
  6. data/Rakefile +51 -0
  7. data/VERSION +1 -0
  8. data/app/assets/images/swat/loading-green.gif +0 -0
  9. data/app/assets/javascripts/swat/.bowerrc +3 -0
  10. data/app/assets/javascripts/swat/app/app.coffee +38 -0
  11. data/app/assets/javascripts/swat/app/controllers/revision.coffee +25 -0
  12. data/app/assets/javascripts/swat/app/controllers/revisions.coffee +10 -0
  13. data/app/assets/javascripts/swat/app/controllers/root.coffee +8 -0
  14. data/app/assets/javascripts/swat/app/factories/response.coffee +9 -0
  15. data/app/assets/javascripts/swat/app/factories/revision_model.coffee +20 -0
  16. data/app/assets/javascripts/swat/app/services/revision.coffee +16 -0
  17. data/app/assets/javascripts/swat/app/services/test_case.coffee +8 -0
  18. data/app/assets/javascripts/swat/application.coffee +5 -0
  19. data/app/assets/javascripts/swat/bower.json +16 -0
  20. data/app/assets/javascripts/swat/bower_components/angular/angular-csp.css +21 -0
  21. data/app/assets/javascripts/swat/bower_components/angular/angular.js +28133 -0
  22. data/app/assets/javascripts/swat/bower_components/angular/angular.min.js +289 -0
  23. data/app/assets/javascripts/swat/bower_components/angular/index.js +2 -0
  24. data/app/assets/javascripts/swat/bower_components/angular-animate/angular-animate.js +2137 -0
  25. data/app/assets/javascripts/swat/bower_components/angular-animate/angular-animate.min.js +33 -0
  26. data/app/assets/javascripts/swat/bower_components/angular-aria/angular-aria.js +339 -0
  27. data/app/assets/javascripts/swat/bower_components/angular-aria/angular-aria.min.js +12 -0
  28. data/app/assets/javascripts/swat/bower_components/angular-bootstrap/ui-bootstrap-csp.css +6 -0
  29. data/app/assets/javascripts/swat/bower_components/angular-bootstrap/ui-bootstrap-tpls.js +4840 -0
  30. data/app/assets/javascripts/swat/bower_components/angular-bootstrap/ui-bootstrap-tpls.min.js +10 -0
  31. data/app/assets/javascripts/swat/bower_components/angular-bootstrap/ui-bootstrap.js +4461 -0
  32. data/app/assets/javascripts/swat/bower_components/angular-bootstrap/ui-bootstrap.min.js +9 -0
  33. data/app/assets/javascripts/swat/bower_components/angular-material/LICENSE.txt +21 -0
  34. data/app/assets/javascripts/swat/bower_components/angular-material/angular-material.css +6228 -0
  35. data/app/assets/javascripts/swat/bower_components/angular-material/angular-material.js +8602 -0
  36. data/app/assets/javascripts/swat/bower_components/angular-material/angular-material.min.css +6 -0
  37. data/app/assets/javascripts/swat/bower_components/angular-material/angular-material.min.js +277 -0
  38. data/app/assets/javascripts/swat/bower_components/angular-material/default-theme.css +394 -0
  39. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/backdrop/backdrop-default-theme.css +8 -0
  40. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/backdrop/backdrop.css +54 -0
  41. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/backdrop/backdrop.js +40 -0
  42. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/bottomSheet/bottomSheet-default-theme.css +15 -0
  43. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/bottomSheet/bottomSheet.css +161 -0
  44. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/bottomSheet/bottomSheet.js +263 -0
  45. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/button/button-default-theme.css +49 -0
  46. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/button/button.css +134 -0
  47. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/button/button.js +101 -0
  48. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/card/card-default-theme.css +10 -0
  49. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/card/card.css +26 -0
  50. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/card/card.js +60 -0
  51. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/checkbox/checkbox-default-theme.css +38 -0
  52. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/checkbox/checkbox.css +78 -0
  53. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/checkbox/checkbox.js +135 -0
  54. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/content/content-default-theme.css +8 -0
  55. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/content/content.css +24 -0
  56. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/content/content.js +87 -0
  57. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/core/core.css +2736 -0
  58. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/core/core.js +3090 -0
  59. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/core/default-theme.js +1 -0
  60. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/dialog/dialog-default-theme.css +11 -0
  61. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/dialog/dialog.css +75 -0
  62. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/dialog/dialog.js +500 -0
  63. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/divider/divider-default-theme.css +8 -0
  64. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/divider/divider.css +12 -0
  65. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/divider/divider.js +50 -0
  66. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/icon/icon.css +24 -0
  67. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/icon/icon.js +52 -0
  68. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/input/input-default-theme.css +39 -0
  69. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/input/input.css +113 -0
  70. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/input/input.js +355 -0
  71. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/list/list.css +56 -0
  72. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/list/list.js +96 -0
  73. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/menu/menu.css +6 -0
  74. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/menu/menu.js +29 -0
  75. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/progressCircular/progressCircular-default-theme.css +35 -0
  76. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/progressCircular/progressCircular.css +1395 -0
  77. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/progressCircular/progressCircular.js +129 -0
  78. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/progressLinear/progressLinear-default-theme.css +26 -0
  79. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/progressLinear/progressLinear.css +366 -0
  80. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/progressLinear/progressLinear.js +130 -0
  81. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/radioButton/radioButton-default-theme.css +39 -0
  82. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/radioButton/radioButton.css +66 -0
  83. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/radioButton/radioButton.js +302 -0
  84. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/sidenav/sidenav-default-theme.css +8 -0
  85. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/sidenav/sidenav.css +86 -0
  86. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/sidenav/sidenav.js +320 -0
  87. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/slider/slider-default-theme.css +55 -0
  88. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/slider/slider.css +210 -0
  89. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/slider/slider.js +391 -0
  90. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/sticky/sticky.css +20 -0
  91. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/sticky/sticky.js +314 -0
  92. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/subheader/subheader-default-theme.css +15 -0
  93. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/subheader/subheader.css +62 -0
  94. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/subheader/subheader.js +89 -0
  95. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/swipe/swipe.js +79 -0
  96. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/switch/switch-default-theme.css +29 -0
  97. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/switch/switch.css +81 -0
  98. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/switch/switch.js +171 -0
  99. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/tabs/tabs-default-theme.css +34 -0
  100. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/tabs/tabs.css +171 -0
  101. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/tabs/tabs.js +1009 -0
  102. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/textField/textField-default-theme.css +29 -0
  103. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/textField/textField.css +72 -0
  104. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/textField/textField.js +145 -0
  105. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/toast/toast-default-theme.css +17 -0
  106. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/toast/toast.css +110 -0
  107. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/toast/toast.js +236 -0
  108. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/toolbar/toolbar-default-theme.css +17 -0
  109. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/toolbar/toolbar.css +69 -0
  110. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/toolbar/toolbar.js +161 -0
  111. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/tooltip/tooltip-default-theme.css +10 -0
  112. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/tooltip/tooltip.css +133 -0
  113. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/tooltip/tooltip.js +199 -0
  114. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/whiteframe/whiteframe.css +20 -0
  115. data/app/assets/javascripts/swat/bower_components/angular-material/modules/closure/whiteframe/whiteframe.js +17 -0
  116. data/app/assets/javascripts/swat/bower_components/angular-material/modules/css/angular-material-layout.css +2582 -0
  117. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/backdrop/backdrop-default-theme.css +8 -0
  118. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/backdrop/backdrop-default-theme.min.css +6 -0
  119. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/backdrop/backdrop.css +54 -0
  120. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/backdrop/backdrop.js +38 -0
  121. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/backdrop/backdrop.min.css +6 -0
  122. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/backdrop/backdrop.min.js +7 -0
  123. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/backdrop/bower.json +7 -0
  124. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/bottomSheet/bottomSheet-default-theme.css +15 -0
  125. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/bottomSheet/bottomSheet-default-theme.min.css +6 -0
  126. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/bottomSheet/bottomSheet.css +188 -0
  127. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/bottomSheet/bottomSheet.js +293 -0
  128. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/bottomSheet/bottomSheet.min.css +6 -0
  129. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/bottomSheet/bottomSheet.min.js +7 -0
  130. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/bottomSheet/bower.json +8 -0
  131. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/button/bower.json +7 -0
  132. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/button/button-default-theme.css +42 -0
  133. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/button/button-default-theme.min.css +6 -0
  134. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/button/button.css +132 -0
  135. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/button/button.js +94 -0
  136. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/button/button.min.css +6 -0
  137. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/button/button.min.js +7 -0
  138. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/card/bower.json +7 -0
  139. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/card/card-default-theme.css +10 -0
  140. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/card/card-default-theme.min.css +6 -0
  141. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/card/card.css +31 -0
  142. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/card/card.js +58 -0
  143. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/card/card.min.css +6 -0
  144. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/card/card.min.js +7 -0
  145. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/checkbox/bower.json +7 -0
  146. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/checkbox/checkbox-default-theme.css +38 -0
  147. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/checkbox/checkbox-default-theme.min.css +6 -0
  148. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/checkbox/checkbox.css +79 -0
  149. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/checkbox/checkbox.js +133 -0
  150. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/checkbox/checkbox.min.css +6 -0
  151. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/checkbox/checkbox.min.js +7 -0
  152. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/content/bower.json +7 -0
  153. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/content/content-default-theme.css +8 -0
  154. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/content/content-default-theme.min.css +6 -0
  155. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/content/content.css +24 -0
  156. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/content/content.js +60 -0
  157. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/content/content.min.css +6 -0
  158. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/content/content.min.js +7 -0
  159. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/core/bower.json +7 -0
  160. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/core/core.css +3067 -0
  161. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/core/core.js +2780 -0
  162. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/core/core.min.css +6 -0
  163. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/core/core.min.js +7 -0
  164. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/core/default-theme.js +1 -0
  165. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/dialog/bower.json +8 -0
  166. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/dialog/dialog-default-theme.css +11 -0
  167. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/dialog/dialog-default-theme.min.css +6 -0
  168. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/dialog/dialog.css +88 -0
  169. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/dialog/dialog.js +495 -0
  170. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/dialog/dialog.min.css +6 -0
  171. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/dialog/dialog.min.js +7 -0
  172. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/divider/bower.json +7 -0
  173. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/divider/divider-default-theme.css +8 -0
  174. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/divider/divider-default-theme.min.css +6 -0
  175. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/divider/divider.css +12 -0
  176. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/divider/divider.js +48 -0
  177. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/divider/divider.min.css +6 -0
  178. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/divider/divider.min.js +7 -0
  179. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/icon/bower.json +7 -0
  180. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/icon/icon.css +24 -0
  181. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/icon/icon.js +50 -0
  182. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/icon/icon.min.css +6 -0
  183. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/icon/icon.min.js +7 -0
  184. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/input/bower.json +7 -0
  185. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/input/input-default-theme.css +40 -0
  186. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/input/input-default-theme.min.css +6 -0
  187. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/input/input.css +102 -0
  188. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/input/input.js +333 -0
  189. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/input/input.min.css +6 -0
  190. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/input/input.min.js +7 -0
  191. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/list/bower.json +7 -0
  192. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/list/list.css +61 -0
  193. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/list/list.js +94 -0
  194. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/list/list.min.css +6 -0
  195. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/list/list.min.js +7 -0
  196. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/menu/bower.json +5 -0
  197. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/menu/menu.css +6 -0
  198. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/menu/menu.js +27 -0
  199. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/menu/menu.min.css +6 -0
  200. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/menu/menu.min.js +7 -0
  201. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/progressCircular/bower.json +7 -0
  202. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/progressCircular/progressCircular-default-theme.css +35 -0
  203. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/progressCircular/progressCircular-default-theme.min.css +6 -0
  204. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/progressCircular/progressCircular.css +1445 -0
  205. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/progressCircular/progressCircular.js +127 -0
  206. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/progressCircular/progressCircular.min.css +6 -0
  207. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/progressCircular/progressCircular.min.js +7 -0
  208. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/progressLinear/bower.json +7 -0
  209. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/progressLinear/progressLinear-default-theme.css +28 -0
  210. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/progressLinear/progressLinear-default-theme.min.css +6 -0
  211. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/progressLinear/progressLinear.css +368 -0
  212. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/progressLinear/progressLinear.js +128 -0
  213. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/progressLinear/progressLinear.min.css +6 -0
  214. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/progressLinear/progressLinear.min.js +7 -0
  215. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/radioButton/bower.json +7 -0
  216. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/radioButton/radioButton-default-theme.css +39 -0
  217. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/radioButton/radioButton-default-theme.min.css +6 -0
  218. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/radioButton/radioButton.css +67 -0
  219. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/radioButton/radioButton.js +296 -0
  220. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/radioButton/radioButton.min.css +6 -0
  221. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/radioButton/radioButton.min.js +7 -0
  222. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/sidenav/bower.json +8 -0
  223. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/sidenav/sidenav-default-theme.css +8 -0
  224. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/sidenav/sidenav-default-theme.min.css +6 -0
  225. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/sidenav/sidenav.css +90 -0
  226. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/sidenav/sidenav.js +302 -0
  227. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/sidenav/sidenav.min.css +6 -0
  228. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/sidenav/sidenav.min.js +7 -0
  229. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/slider/bower.json +7 -0
  230. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/slider/slider-default-theme.css +55 -0
  231. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/slider/slider-default-theme.min.css +6 -0
  232. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/slider/slider.css +218 -0
  233. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/slider/slider.js +411 -0
  234. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/slider/slider.min.css +6 -0
  235. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/slider/slider.min.js +7 -0
  236. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/sticky/bower.json +8 -0
  237. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/sticky/sticky.css +20 -0
  238. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/sticky/sticky.js +309 -0
  239. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/sticky/sticky.min.css +6 -0
  240. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/sticky/sticky.min.js +7 -0
  241. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/subheader/bower.json +8 -0
  242. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/subheader/subheader-default-theme.css +15 -0
  243. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/subheader/subheader-default-theme.min.css +6 -0
  244. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/subheader/subheader.css +61 -0
  245. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/subheader/subheader.js +86 -0
  246. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/subheader/subheader.min.css +6 -0
  247. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/subheader/subheader.min.js +7 -0
  248. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/swipe/bower.json +5 -0
  249. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/swipe/swipe.js +213 -0
  250. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/swipe/swipe.min.js +7 -0
  251. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/switch/bower.json +8 -0
  252. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/switch/switch-default-theme.css +29 -0
  253. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/switch/switch-default-theme.min.css +6 -0
  254. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/switch/switch.css +77 -0
  255. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/switch/switch.js +144 -0
  256. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/switch/switch.min.css +6 -0
  257. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/switch/switch.min.js +7 -0
  258. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/tabs/bower.json +7 -0
  259. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/tabs/tabs-default-theme.css +34 -0
  260. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/tabs/tabs-default-theme.min.css +6 -0
  261. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/tabs/tabs.css +181 -0
  262. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/tabs/tabs.js +992 -0
  263. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/tabs/tabs.min.css +6 -0
  264. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/tabs/tabs.min.js +7 -0
  265. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/textField/bower.json +7 -0
  266. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/textField/textField-default-theme.css +29 -0
  267. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/textField/textField-default-theme.min.css +6 -0
  268. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/textField/textField.css +76 -0
  269. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/textField/textField.js +143 -0
  270. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/textField/textField.min.css +6 -0
  271. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/textField/textField.min.js +7 -0
  272. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/toast/bower.json +9 -0
  273. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/toast/toast-default-theme.css +17 -0
  274. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/toast/toast-default-theme.min.css +6 -0
  275. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/toast/toast.css +115 -0
  276. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/toast/toast.js +235 -0
  277. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/toast/toast.min.css +6 -0
  278. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/toast/toast.min.js +7 -0
  279. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/toolbar/bower.json +8 -0
  280. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/toolbar/toolbar-default-theme.css +17 -0
  281. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/toolbar/toolbar-default-theme.min.css +6 -0
  282. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/toolbar/toolbar.css +78 -0
  283. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/toolbar/toolbar.js +158 -0
  284. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/toolbar/toolbar.min.css +6 -0
  285. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/toolbar/toolbar.min.js +7 -0
  286. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/tooltip/bower.json +7 -0
  287. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/tooltip/tooltip-default-theme.css +10 -0
  288. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/tooltip/tooltip-default-theme.min.css +6 -0
  289. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/tooltip/tooltip.css +136 -0
  290. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/tooltip/tooltip.js +197 -0
  291. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/tooltip/tooltip.min.css +6 -0
  292. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/tooltip/tooltip.min.js +7 -0
  293. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/whiteframe/bower.json +5 -0
  294. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/whiteframe/whiteframe.css +20 -0
  295. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/whiteframe/whiteframe.js +15 -0
  296. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/whiteframe/whiteframe.min.css +6 -0
  297. data/app/assets/javascripts/swat/bower_components/angular-material/modules/js/whiteframe/whiteframe.min.js +7 -0
  298. data/app/assets/javascripts/swat/bower_components/angular-resource/angular-resource.js +668 -0
  299. data/app/assets/javascripts/swat/bower_components/angular-resource/angular-resource.min.js +13 -0
  300. data/app/assets/javascripts/swat/bower_components/angular-resource/index.js +2 -0
  301. data/app/assets/javascripts/swat/bower_components/angular-route/angular-route.js +991 -0
  302. data/app/assets/javascripts/swat/bower_components/angular-route/angular-route.min.js +15 -0
  303. data/app/assets/javascripts/swat/bower_components/angular-route/index.js +2 -0
  304. data/app/assets/javascripts/swat/bower_components/angular-ui-router/LICENSE.txt +21 -0
  305. data/app/assets/javascripts/swat/bower_components/angular-ui-router/api/angular-ui-router.d.ts +126 -0
  306. data/app/assets/javascripts/swat/bower_components/angular-ui-router/release/angular-ui-router.js +4370 -0
  307. data/app/assets/javascripts/swat/bower_components/angular-ui-router/release/angular-ui-router.min.js +7 -0
  308. data/app/assets/javascripts/swat/bower_components/angular-ui-router/src/common.js +292 -0
  309. data/app/assets/javascripts/swat/bower_components/angular-ui-router/src/resolve.js +252 -0
  310. data/app/assets/javascripts/swat/bower_components/angular-ui-router/src/state.js +1465 -0
  311. data/app/assets/javascripts/swat/bower_components/angular-ui-router/src/stateDirectives.js +285 -0
  312. data/app/assets/javascripts/swat/bower_components/angular-ui-router/src/stateFilters.js +39 -0
  313. data/app/assets/javascripts/swat/bower_components/angular-ui-router/src/templateFactory.js +110 -0
  314. data/app/assets/javascripts/swat/bower_components/angular-ui-router/src/urlMatcherFactory.js +1050 -0
  315. data/app/assets/javascripts/swat/bower_components/angular-ui-router/src/urlRouter.js +427 -0
  316. data/app/assets/javascripts/swat/bower_components/angular-ui-router/src/view.js +71 -0
  317. data/app/assets/javascripts/swat/bower_components/angular-ui-router/src/viewDirective.js +303 -0
  318. data/app/assets/javascripts/swat/bower_components/angular-ui-router/src/viewScroll.js +52 -0
  319. data/app/assets/javascripts/swat/bower_components/lodash/lodash.js +12235 -0
  320. data/app/assets/javascripts/swat/bower_components/lodash/lodash.min.js +98 -0
  321. data/app/assets/javascripts/swat/bower_components/ng-clip/.editorconfig +10 -0
  322. data/app/assets/javascripts/swat/bower_components/ng-clip/.gitignore +3 -0
  323. data/app/assets/javascripts/swat/bower_components/ng-clip/Gruntfile.js +96 -0
  324. data/app/assets/javascripts/swat/bower_components/ng-clip/dest/ng-clip.min.js +2 -0
  325. data/app/assets/javascripts/swat/bower_components/ng-clip/example/bootstrap-tooltip.html +49 -0
  326. data/app/assets/javascripts/swat/bower_components/ng-clip/example/index.html +68 -0
  327. data/app/assets/javascripts/swat/bower_components/ng-clip/example/ng-repeat.html +44 -0
  328. data/app/assets/javascripts/swat/bower_components/ng-clip/npm-debug.log +145 -0
  329. data/app/assets/javascripts/swat/bower_components/ng-clip/src/ngClip.js +84 -0
  330. data/app/assets/javascripts/swat/bower_components/zeroclipboard/dist/.jshintrc +70 -0
  331. data/app/assets/javascripts/swat/bower_components/zeroclipboard/dist/ZeroClipboard.Core.js +2017 -0
  332. data/app/assets/javascripts/swat/bower_components/zeroclipboard/dist/ZeroClipboard.Core.min.js +10 -0
  333. data/app/assets/javascripts/swat/bower_components/zeroclipboard/dist/ZeroClipboard.js +2581 -0
  334. data/app/assets/javascripts/swat/bower_components/zeroclipboard/dist/ZeroClipboard.min.js +10 -0
  335. data/app/assets/javascripts/swat/bower_components/zeroclipboard/dist/ZeroClipboard.swf +0 -0
  336. data/app/assets/javascripts/swat/bower_components.coffee +12 -0
  337. data/app/assets/stylesheets/swat/application.sass +59 -0
  338. data/app/assets/stylesheets/swat/default-theme.css +394 -0
  339. data/app/assets/stylesheets/swat/font-awesome.css +1801 -0
  340. data/app/assets/stylesheets/swat/fonts/FontAwesome.otf +0 -0
  341. data/app/assets/stylesheets/swat/fonts/fontawesome-webfont.eot +0 -0
  342. data/app/assets/stylesheets/swat/fonts/fontawesome-webfont.svg +565 -0
  343. data/app/assets/stylesheets/swat/fonts/fontawesome-webfont.ttf +0 -0
  344. data/app/assets/stylesheets/swat/fonts/fontawesome-webfont.woff +0 -0
  345. data/app/assets/stylesheets/swat/fonts/fontawesome-webfont.woff2 +0 -0
  346. data/app/assets/stylesheets/swat/swat_theme.sass +177 -0
  347. data/app/controllers/swat/api/revisions_controller.rb +27 -0
  348. data/app/controllers/swat/api/test_cases_controller.rb +20 -0
  349. data/app/controllers/swat/application_controller.rb +4 -0
  350. data/app/controllers/swat/info/states_controller.rb +12 -0
  351. data/app/controllers/swat/pages/base_pages_controller.rb +7 -0
  352. data/app/controllers/swat/pages/revisions_controller.rb +8 -0
  353. data/app/controllers/swat/revisions_controller.rb +4 -0
  354. data/app/helpers/swat/application_helper.rb +4 -0
  355. data/app/models/concerns/root_revision_ext.rb +14 -0
  356. data/app/models/full_revision.rb +88 -0
  357. data/app/models/revision.rb +84 -0
  358. data/app/models/revision_status_calculator.rb +98 -0
  359. data/app/models/test_case.rb +25 -0
  360. data/app/views/layouts/swat/application.slim +36 -0
  361. data/app/views/layouts/swat/page.slim +2 -0
  362. data/app/views/swat/application/index.slim +0 -0
  363. data/app/views/swat/pages/revisions/index.slim +25 -0
  364. data/app/views/swat/pages/revisions/show.slim +43 -0
  365. data/app/views/swat/shared/_footer.slim +5 -0
  366. data/app/views/swat/shared/_header.slim +9 -0
  367. data/bin/rails +12 -0
  368. data/config/routes.rb +38 -0
  369. data/fixtures/firebase_collection.rb +97 -0
  370. data/lib/sw2at-ui.rb +19 -0
  371. data/lib/swat/engine.rb +5 -0
  372. data/lib/swat/ui/config.rb +28 -0
  373. data/lib/swat/ui/rspec_commands.rb +191 -0
  374. data/lib/swat/ui/rspec_setup.rb +42 -0
  375. data/lib/swat/ui/stats_collector.rb +90 -0
  376. data/lib/swat/ui/version.rb +5 -0
  377. data/lib/tasks/swat_tasks.rake +36 -0
  378. data/spec/lib/commands_spec.rb +88 -0
  379. data/spec/models/calculator_spec.rb +130 -0
  380. data/spec/models/full_revision_spec.rb +263 -0
  381. data/spec/models/revision_spec.rb +59 -0
  382. data/spec/models/testcase_spec.rb +94 -0
  383. data/spec/spec_helper.rb +45 -0
  384. data/sw2at-ui.gemspec +465 -0
  385. data/test/helper.rb +34 -0
  386. data/test/test_sw2at-ui.rb +7 -0
  387. metadata +628 -0
@@ -0,0 +1,1050 @@
1
+ var $$UMFP; // reference to $UrlMatcherFactoryProvider
2
+
3
+ /**
4
+ * @ngdoc object
5
+ * @name ui.router.util.type:UrlMatcher
6
+ *
7
+ * @description
8
+ * Matches URLs against patterns and extracts named parameters from the path or the search
9
+ * part of the URL. A URL pattern consists of a path pattern, optionally followed by '?' and a list
10
+ * of search parameters. Multiple search parameter names are separated by '&'. Search parameters
11
+ * do not influence whether or not a URL is matched, but their values are passed through into
12
+ * the matched parameters returned by {@link ui.router.util.type:UrlMatcher#methods_exec exec}.
13
+ *
14
+ * Path parameter placeholders can be specified using simple colon/catch-all syntax or curly brace
15
+ * syntax, which optionally allows a regular expression for the parameter to be specified:
16
+ *
17
+ * * `':'` name - colon placeholder
18
+ * * `'*'` name - catch-all placeholder
19
+ * * `'{' name '}'` - curly placeholder
20
+ * * `'{' name ':' regexp|type '}'` - curly placeholder with regexp or type name. Should the
21
+ * regexp itself contain curly braces, they must be in matched pairs or escaped with a backslash.
22
+ *
23
+ * Parameter names may contain only word characters (latin letters, digits, and underscore) and
24
+ * must be unique within the pattern (across both path and search parameters). For colon
25
+ * placeholders or curly placeholders without an explicit regexp, a path parameter matches any
26
+ * number of characters other than '/'. For catch-all placeholders the path parameter matches
27
+ * any number of characters.
28
+ *
29
+ * Examples:
30
+ *
31
+ * * `'/hello/'` - Matches only if the path is exactly '/hello/'. There is no special treatment for
32
+ * trailing slashes, and patterns have to match the entire path, not just a prefix.
33
+ * * `'/user/:id'` - Matches '/user/bob' or '/user/1234!!!' or even '/user/' but not '/user' or
34
+ * '/user/bob/details'. The second path segment will be captured as the parameter 'id'.
35
+ * * `'/user/{id}'` - Same as the previous example, but using curly brace syntax.
36
+ * * `'/user/{id:[^/]*}'` - Same as the previous example.
37
+ * * `'/user/{id:[0-9a-fA-F]{1,8}}'` - Similar to the previous example, but only matches if the id
38
+ * parameter consists of 1 to 8 hex digits.
39
+ * * `'/files/{path:.*}'` - Matches any URL starting with '/files/' and captures the rest of the
40
+ * path into the parameter 'path'.
41
+ * * `'/files/*path'` - ditto.
42
+ * * `'/calendar/{start:date}'` - Matches "/calendar/2014-11-12" (because the pattern defined
43
+ * in the built-in `date` Type matches `2014-11-12`) and provides a Date object in $stateParams.start
44
+ *
45
+ * @param {string} pattern The pattern to compile into a matcher.
46
+ * @param {Object} config A configuration object hash:
47
+ * @param {Object=} parentMatcher Used to concatenate the pattern/config onto
48
+ * an existing UrlMatcher
49
+ *
50
+ * * `caseInsensitive` - `true` if URL matching should be case insensitive, otherwise `false`, the default value (for backward compatibility) is `false`.
51
+ * * `strict` - `false` if matching against a URL with a trailing slash should be treated as equivalent to a URL without a trailing slash, the default value is `true`.
52
+ *
53
+ * @property {string} prefix A static prefix of this pattern. The matcher guarantees that any
54
+ * URL matching this matcher (i.e. any string for which {@link ui.router.util.type:UrlMatcher#methods_exec exec()} returns
55
+ * non-null) will start with this prefix.
56
+ *
57
+ * @property {string} source The pattern that was passed into the constructor
58
+ *
59
+ * @property {string} sourcePath The path portion of the source property
60
+ *
61
+ * @property {string} sourceSearch The search portion of the source property
62
+ *
63
+ * @property {string} regex The constructed regex that will be used to match against the url when
64
+ * it is time to determine which url will match.
65
+ *
66
+ * @returns {Object} New `UrlMatcher` object
67
+ */
68
+ function UrlMatcher(pattern, config, parentMatcher) {
69
+ config = extend({ params: {} }, isObject(config) ? config : {});
70
+
71
+ // Find all placeholders and create a compiled pattern, using either classic or curly syntax:
72
+ // '*' name
73
+ // ':' name
74
+ // '{' name '}'
75
+ // '{' name ':' regexp '}'
76
+ // The regular expression is somewhat complicated due to the need to allow curly braces
77
+ // inside the regular expression. The placeholder regexp breaks down as follows:
78
+ // ([:*])([\w\[\]]+) - classic placeholder ($1 / $2) (search version has - for snake-case)
79
+ // \{([\w\[\]]+)(?:\:( ... ))?\} - curly brace placeholder ($3) with optional regexp/type ... ($4) (search version has - for snake-case
80
+ // (?: ... | ... | ... )+ - the regexp consists of any number of atoms, an atom being either
81
+ // [^{}\\]+ - anything other than curly braces or backslash
82
+ // \\. - a backslash escape
83
+ // \{(?:[^{}\\]+|\\.)*\} - a matched set of curly braces containing other atoms
84
+ var placeholder = /([:*])([\w\[\]]+)|\{([\w\[\]]+)(?:\:((?:[^{}\\]+|\\.|\{(?:[^{}\\]+|\\.)*\})+))?\}/g,
85
+ searchPlaceholder = /([:]?)([\w\[\]-]+)|\{([\w\[\]-]+)(?:\:((?:[^{}\\]+|\\.|\{(?:[^{}\\]+|\\.)*\})+))?\}/g,
86
+ compiled = '^', last = 0, m,
87
+ segments = this.segments = [],
88
+ parentParams = parentMatcher ? parentMatcher.params : {},
89
+ params = this.params = parentMatcher ? parentMatcher.params.$$new() : new $$UMFP.ParamSet(),
90
+ paramNames = [];
91
+
92
+ function addParameter(id, type, config, location) {
93
+ paramNames.push(id);
94
+ if (parentParams[id]) return parentParams[id];
95
+ if (!/^\w+(-+\w+)*(?:\[\])?$/.test(id)) throw new Error("Invalid parameter name '" + id + "' in pattern '" + pattern + "'");
96
+ if (params[id]) throw new Error("Duplicate parameter name '" + id + "' in pattern '" + pattern + "'");
97
+ params[id] = new $$UMFP.Param(id, type, config, location);
98
+ return params[id];
99
+ }
100
+
101
+ function quoteRegExp(string, pattern, squash, optional) {
102
+ var surroundPattern = ['',''], result = string.replace(/[\\\[\]\^$*+?.()|{}]/g, "\\$&");
103
+ if (!pattern) return result;
104
+ switch(squash) {
105
+ case false: surroundPattern = ['(', ')' + (optional ? "?" : "")]; break;
106
+ case true: surroundPattern = ['?(', ')?']; break;
107
+ default: surroundPattern = ['(' + squash + "|", ')?']; break;
108
+ }
109
+ return result + surroundPattern[0] + pattern + surroundPattern[1];
110
+ }
111
+
112
+ this.source = pattern;
113
+
114
+ // Split into static segments separated by path parameter placeholders.
115
+ // The number of segments is always 1 more than the number of parameters.
116
+ function matchDetails(m, isSearch) {
117
+ var id, regexp, segment, type, cfg, arrayMode;
118
+ id = m[2] || m[3]; // IE[78] returns '' for unmatched groups instead of null
119
+ cfg = config.params[id];
120
+ segment = pattern.substring(last, m.index);
121
+ regexp = isSearch ? m[4] : m[4] || (m[1] == '*' ? '.*' : null);
122
+ type = $$UMFP.type(regexp || "string") || inherit($$UMFP.type("string"), { pattern: new RegExp(regexp, config.caseInsensitive ? 'i' : undefined) });
123
+ return {
124
+ id: id, regexp: regexp, segment: segment, type: type, cfg: cfg
125
+ };
126
+ }
127
+
128
+ var p, param, segment;
129
+ while ((m = placeholder.exec(pattern))) {
130
+ p = matchDetails(m, false);
131
+ if (p.segment.indexOf('?') >= 0) break; // we're into the search part
132
+
133
+ param = addParameter(p.id, p.type, p.cfg, "path");
134
+ compiled += quoteRegExp(p.segment, param.type.pattern.source, param.squash, param.isOptional);
135
+ segments.push(p.segment);
136
+ last = placeholder.lastIndex;
137
+ }
138
+ segment = pattern.substring(last);
139
+
140
+ // Find any search parameter names and remove them from the last segment
141
+ var i = segment.indexOf('?');
142
+
143
+ if (i >= 0) {
144
+ var search = this.sourceSearch = segment.substring(i);
145
+ segment = segment.substring(0, i);
146
+ this.sourcePath = pattern.substring(0, last + i);
147
+
148
+ if (search.length > 0) {
149
+ last = 0;
150
+ while ((m = searchPlaceholder.exec(search))) {
151
+ p = matchDetails(m, true);
152
+ param = addParameter(p.id, p.type, p.cfg, "search");
153
+ last = placeholder.lastIndex;
154
+ // check if ?&
155
+ }
156
+ }
157
+ } else {
158
+ this.sourcePath = pattern;
159
+ this.sourceSearch = '';
160
+ }
161
+
162
+ compiled += quoteRegExp(segment) + (config.strict === false ? '\/?' : '') + '$';
163
+ segments.push(segment);
164
+
165
+ this.regexp = new RegExp(compiled, config.caseInsensitive ? 'i' : undefined);
166
+ this.prefix = segments[0];
167
+ this.$$paramNames = paramNames;
168
+ }
169
+
170
+ /**
171
+ * @ngdoc function
172
+ * @name ui.router.util.type:UrlMatcher#concat
173
+ * @methodOf ui.router.util.type:UrlMatcher
174
+ *
175
+ * @description
176
+ * Returns a new matcher for a pattern constructed by appending the path part and adding the
177
+ * search parameters of the specified pattern to this pattern. The current pattern is not
178
+ * modified. This can be understood as creating a pattern for URLs that are relative to (or
179
+ * suffixes of) the current pattern.
180
+ *
181
+ * @example
182
+ * The following two matchers are equivalent:
183
+ * <pre>
184
+ * new UrlMatcher('/user/{id}?q').concat('/details?date');
185
+ * new UrlMatcher('/user/{id}/details?q&date');
186
+ * </pre>
187
+ *
188
+ * @param {string} pattern The pattern to append.
189
+ * @param {Object} config An object hash of the configuration for the matcher.
190
+ * @returns {UrlMatcher} A matcher for the concatenated pattern.
191
+ */
192
+ UrlMatcher.prototype.concat = function (pattern, config) {
193
+ // Because order of search parameters is irrelevant, we can add our own search
194
+ // parameters to the end of the new pattern. Parse the new pattern by itself
195
+ // and then join the bits together, but it's much easier to do this on a string level.
196
+ var defaultConfig = {
197
+ caseInsensitive: $$UMFP.caseInsensitive(),
198
+ strict: $$UMFP.strictMode(),
199
+ squash: $$UMFP.defaultSquashPolicy()
200
+ };
201
+ return new UrlMatcher(this.sourcePath + pattern + this.sourceSearch, extend(defaultConfig, config), this);
202
+ };
203
+
204
+ UrlMatcher.prototype.toString = function () {
205
+ return this.source;
206
+ };
207
+
208
+ /**
209
+ * @ngdoc function
210
+ * @name ui.router.util.type:UrlMatcher#exec
211
+ * @methodOf ui.router.util.type:UrlMatcher
212
+ *
213
+ * @description
214
+ * Tests the specified path against this matcher, and returns an object containing the captured
215
+ * parameter values, or null if the path does not match. The returned object contains the values
216
+ * of any search parameters that are mentioned in the pattern, but their value may be null if
217
+ * they are not present in `searchParams`. This means that search parameters are always treated
218
+ * as optional.
219
+ *
220
+ * @example
221
+ * <pre>
222
+ * new UrlMatcher('/user/{id}?q&r').exec('/user/bob', {
223
+ * x: '1', q: 'hello'
224
+ * });
225
+ * // returns { id: 'bob', q: 'hello', r: null }
226
+ * </pre>
227
+ *
228
+ * @param {string} path The URL path to match, e.g. `$location.path()`.
229
+ * @param {Object} searchParams URL search parameters, e.g. `$location.search()`.
230
+ * @returns {Object} The captured parameter values.
231
+ */
232
+ UrlMatcher.prototype.exec = function (path, searchParams) {
233
+ var m = this.regexp.exec(path);
234
+ if (!m) return null;
235
+ searchParams = searchParams || {};
236
+
237
+ var paramNames = this.parameters(), nTotal = paramNames.length,
238
+ nPath = this.segments.length - 1,
239
+ values = {}, i, j, cfg, paramName;
240
+
241
+ if (nPath !== m.length - 1) throw new Error("Unbalanced capture group in route '" + this.source + "'");
242
+
243
+ function decodePathArray(string) {
244
+ function reverseString(str) { return str.split("").reverse().join(""); }
245
+ function unquoteDashes(str) { return str.replace(/\\-/g, "-"); }
246
+
247
+ var split = reverseString(string).split(/-(?!\\)/);
248
+ var allReversed = map(split, reverseString);
249
+ return map(allReversed, unquoteDashes).reverse();
250
+ }
251
+
252
+ for (i = 0; i < nPath; i++) {
253
+ paramName = paramNames[i];
254
+ var param = this.params[paramName];
255
+ var paramVal = m[i+1];
256
+ // if the param value matches a pre-replace pair, replace the value before decoding.
257
+ for (j = 0; j < param.replace; j++) {
258
+ if (param.replace[j].from === paramVal) paramVal = param.replace[j].to;
259
+ }
260
+ if (paramVal && param.array === true) paramVal = decodePathArray(paramVal);
261
+ values[paramName] = param.value(paramVal);
262
+ }
263
+ for (/**/; i < nTotal; i++) {
264
+ paramName = paramNames[i];
265
+ values[paramName] = this.params[paramName].value(searchParams[paramName]);
266
+ }
267
+
268
+ return values;
269
+ };
270
+
271
+ /**
272
+ * @ngdoc function
273
+ * @name ui.router.util.type:UrlMatcher#parameters
274
+ * @methodOf ui.router.util.type:UrlMatcher
275
+ *
276
+ * @description
277
+ * Returns the names of all path and search parameters of this pattern in an unspecified order.
278
+ *
279
+ * @returns {Array.<string>} An array of parameter names. Must be treated as read-only. If the
280
+ * pattern has no parameters, an empty array is returned.
281
+ */
282
+ UrlMatcher.prototype.parameters = function (param) {
283
+ if (!isDefined(param)) return this.$$paramNames;
284
+ return this.params[param] || null;
285
+ };
286
+
287
+ /**
288
+ * @ngdoc function
289
+ * @name ui.router.util.type:UrlMatcher#validate
290
+ * @methodOf ui.router.util.type:UrlMatcher
291
+ *
292
+ * @description
293
+ * Checks an object hash of parameters to validate their correctness according to the parameter
294
+ * types of this `UrlMatcher`.
295
+ *
296
+ * @param {Object} params The object hash of parameters to validate.
297
+ * @returns {boolean} Returns `true` if `params` validates, otherwise `false`.
298
+ */
299
+ UrlMatcher.prototype.validates = function (params) {
300
+ return this.params.$$validates(params);
301
+ };
302
+
303
+ /**
304
+ * @ngdoc function
305
+ * @name ui.router.util.type:UrlMatcher#format
306
+ * @methodOf ui.router.util.type:UrlMatcher
307
+ *
308
+ * @description
309
+ * Creates a URL that matches this pattern by substituting the specified values
310
+ * for the path and search parameters. Null values for path parameters are
311
+ * treated as empty strings.
312
+ *
313
+ * @example
314
+ * <pre>
315
+ * new UrlMatcher('/user/{id}?q').format({ id:'bob', q:'yes' });
316
+ * // returns '/user/bob?q=yes'
317
+ * </pre>
318
+ *
319
+ * @param {Object} values the values to substitute for the parameters in this pattern.
320
+ * @returns {string} the formatted URL (path and optionally search part).
321
+ */
322
+ UrlMatcher.prototype.format = function (values) {
323
+ values = values || {};
324
+ var segments = this.segments, params = this.parameters(), paramset = this.params;
325
+ if (!this.validates(values)) return null;
326
+
327
+ var i, search = false, nPath = segments.length - 1, nTotal = params.length, result = segments[0];
328
+
329
+ function encodeDashes(str) { // Replace dashes with encoded "\-"
330
+ return encodeURIComponent(str).replace(/-/g, function(c) { return '%5C%' + c.charCodeAt(0).toString(16).toUpperCase(); });
331
+ }
332
+
333
+ for (i = 0; i < nTotal; i++) {
334
+ var isPathParam = i < nPath;
335
+ var name = params[i], param = paramset[name], value = param.value(values[name]);
336
+ var isDefaultValue = param.isOptional && param.type.equals(param.value(), value);
337
+ var squash = isDefaultValue ? param.squash : false;
338
+ var encoded = param.type.encode(value);
339
+
340
+ if (isPathParam) {
341
+ var nextSegment = segments[i + 1];
342
+ if (squash === false) {
343
+ if (encoded != null) {
344
+ if (isArray(encoded)) {
345
+ result += map(encoded, encodeDashes).join("-");
346
+ } else {
347
+ result += encodeURIComponent(encoded);
348
+ }
349
+ }
350
+ result += nextSegment;
351
+ } else if (squash === true) {
352
+ var capture = result.match(/\/$/) ? /\/?(.*)/ : /(.*)/;
353
+ result += nextSegment.match(capture)[1];
354
+ } else if (isString(squash)) {
355
+ result += squash + nextSegment;
356
+ }
357
+ } else {
358
+ if (encoded == null || (isDefaultValue && squash !== false)) continue;
359
+ if (!isArray(encoded)) encoded = [ encoded ];
360
+ encoded = map(encoded, encodeURIComponent).join('&' + name + '=');
361
+ result += (search ? '&' : '?') + (name + '=' + encoded);
362
+ search = true;
363
+ }
364
+ }
365
+
366
+ return result;
367
+ };
368
+
369
+ /**
370
+ * @ngdoc object
371
+ * @name ui.router.util.type:Type
372
+ *
373
+ * @description
374
+ * Implements an interface to define custom parameter types that can be decoded from and encoded to
375
+ * string parameters matched in a URL. Used by {@link ui.router.util.type:UrlMatcher `UrlMatcher`}
376
+ * objects when matching or formatting URLs, or comparing or validating parameter values.
377
+ *
378
+ * See {@link ui.router.util.$urlMatcherFactory#methods_type `$urlMatcherFactory#type()`} for more
379
+ * information on registering custom types.
380
+ *
381
+ * @param {Object} config A configuration object which contains the custom type definition. The object's
382
+ * properties will override the default methods and/or pattern in `Type`'s public interface.
383
+ * @example
384
+ * <pre>
385
+ * {
386
+ * decode: function(val) { return parseInt(val, 10); },
387
+ * encode: function(val) { return val && val.toString(); },
388
+ * equals: function(a, b) { return this.is(a) && a === b; },
389
+ * is: function(val) { return angular.isNumber(val) isFinite(val) && val % 1 === 0; },
390
+ * pattern: /\d+/
391
+ * }
392
+ * </pre>
393
+ *
394
+ * @property {RegExp} pattern The regular expression pattern used to match values of this type when
395
+ * coming from a substring of a URL.
396
+ *
397
+ * @returns {Object} Returns a new `Type` object.
398
+ */
399
+ function Type(config) {
400
+ extend(this, config);
401
+ }
402
+
403
+ /**
404
+ * @ngdoc function
405
+ * @name ui.router.util.type:Type#is
406
+ * @methodOf ui.router.util.type:Type
407
+ *
408
+ * @description
409
+ * Detects whether a value is of a particular type. Accepts a native (decoded) value
410
+ * and determines whether it matches the current `Type` object.
411
+ *
412
+ * @param {*} val The value to check.
413
+ * @param {string} key Optional. If the type check is happening in the context of a specific
414
+ * {@link ui.router.util.type:UrlMatcher `UrlMatcher`} object, this is the name of the
415
+ * parameter in which `val` is stored. Can be used for meta-programming of `Type` objects.
416
+ * @returns {Boolean} Returns `true` if the value matches the type, otherwise `false`.
417
+ */
418
+ Type.prototype.is = function(val, key) {
419
+ return true;
420
+ };
421
+
422
+ /**
423
+ * @ngdoc function
424
+ * @name ui.router.util.type:Type#encode
425
+ * @methodOf ui.router.util.type:Type
426
+ *
427
+ * @description
428
+ * Encodes a custom/native type value to a string that can be embedded in a URL. Note that the
429
+ * return value does *not* need to be URL-safe (i.e. passed through `encodeURIComponent()`), it
430
+ * only needs to be a representation of `val` that has been coerced to a string.
431
+ *
432
+ * @param {*} val The value to encode.
433
+ * @param {string} key The name of the parameter in which `val` is stored. Can be used for
434
+ * meta-programming of `Type` objects.
435
+ * @returns {string} Returns a string representation of `val` that can be encoded in a URL.
436
+ */
437
+ Type.prototype.encode = function(val, key) {
438
+ return val;
439
+ };
440
+
441
+ /**
442
+ * @ngdoc function
443
+ * @name ui.router.util.type:Type#decode
444
+ * @methodOf ui.router.util.type:Type
445
+ *
446
+ * @description
447
+ * Converts a parameter value (from URL string or transition param) to a custom/native value.
448
+ *
449
+ * @param {string} val The URL parameter value to decode.
450
+ * @param {string} key The name of the parameter in which `val` is stored. Can be used for
451
+ * meta-programming of `Type` objects.
452
+ * @returns {*} Returns a custom representation of the URL parameter value.
453
+ */
454
+ Type.prototype.decode = function(val, key) {
455
+ return val;
456
+ };
457
+
458
+ /**
459
+ * @ngdoc function
460
+ * @name ui.router.util.type:Type#equals
461
+ * @methodOf ui.router.util.type:Type
462
+ *
463
+ * @description
464
+ * Determines whether two decoded values are equivalent.
465
+ *
466
+ * @param {*} a A value to compare against.
467
+ * @param {*} b A value to compare against.
468
+ * @returns {Boolean} Returns `true` if the values are equivalent/equal, otherwise `false`.
469
+ */
470
+ Type.prototype.equals = function(a, b) {
471
+ return a == b;
472
+ };
473
+
474
+ Type.prototype.$subPattern = function() {
475
+ var sub = this.pattern.toString();
476
+ return sub.substr(1, sub.length - 2);
477
+ };
478
+
479
+ Type.prototype.pattern = /.*/;
480
+
481
+ Type.prototype.toString = function() { return "{Type:" + this.name + "}"; };
482
+
483
+ /** Given an encoded string, or a decoded object, returns a decoded object */
484
+ Type.prototype.$normalize = function(val) {
485
+ return this.is(val) ? val : this.decode(val);
486
+ };
487
+
488
+ /*
489
+ * Wraps an existing custom Type as an array of Type, depending on 'mode'.
490
+ * e.g.:
491
+ * - urlmatcher pattern "/path?{queryParam[]:int}"
492
+ * - url: "/path?queryParam=1&queryParam=2
493
+ * - $stateParams.queryParam will be [1, 2]
494
+ * if `mode` is "auto", then
495
+ * - url: "/path?queryParam=1 will create $stateParams.queryParam: 1
496
+ * - url: "/path?queryParam=1&queryParam=2 will create $stateParams.queryParam: [1, 2]
497
+ */
498
+ Type.prototype.$asArray = function(mode, isSearch) {
499
+ if (!mode) return this;
500
+ if (mode === "auto" && !isSearch) throw new Error("'auto' array mode is for query parameters only");
501
+
502
+ function ArrayType(type, mode) {
503
+ function bindTo(type, callbackName) {
504
+ return function() {
505
+ return type[callbackName].apply(type, arguments);
506
+ };
507
+ }
508
+
509
+ // Wrap non-array value as array
510
+ function arrayWrap(val) { return isArray(val) ? val : (isDefined(val) ? [ val ] : []); }
511
+ // Unwrap array value for "auto" mode. Return undefined for empty array.
512
+ function arrayUnwrap(val) {
513
+ switch(val.length) {
514
+ case 0: return undefined;
515
+ case 1: return mode === "auto" ? val[0] : val;
516
+ default: return val;
517
+ }
518
+ }
519
+ function falsey(val) { return !val; }
520
+
521
+ // Wraps type (.is/.encode/.decode) functions to operate on each value of an array
522
+ function arrayHandler(callback, allTruthyMode) {
523
+ return function handleArray(val) {
524
+ val = arrayWrap(val);
525
+ var result = map(val, callback);
526
+ if (allTruthyMode === true)
527
+ return filter(result, falsey).length === 0;
528
+ return arrayUnwrap(result);
529
+ };
530
+ }
531
+
532
+ // Wraps type (.equals) functions to operate on each value of an array
533
+ function arrayEqualsHandler(callback) {
534
+ return function handleArray(val1, val2) {
535
+ var left = arrayWrap(val1), right = arrayWrap(val2);
536
+ if (left.length !== right.length) return false;
537
+ for (var i = 0; i < left.length; i++) {
538
+ if (!callback(left[i], right[i])) return false;
539
+ }
540
+ return true;
541
+ };
542
+ }
543
+
544
+ this.encode = arrayHandler(bindTo(type, 'encode'));
545
+ this.decode = arrayHandler(bindTo(type, 'decode'));
546
+ this.is = arrayHandler(bindTo(type, 'is'), true);
547
+ this.equals = arrayEqualsHandler(bindTo(type, 'equals'));
548
+ this.pattern = type.pattern;
549
+ this.$normalize = arrayHandler(bindTo(type, '$normalize'));
550
+ this.name = type.name;
551
+ this.$arrayMode = mode;
552
+ }
553
+
554
+ return new ArrayType(this, mode);
555
+ };
556
+
557
+
558
+
559
+ /**
560
+ * @ngdoc object
561
+ * @name ui.router.util.$urlMatcherFactory
562
+ *
563
+ * @description
564
+ * Factory for {@link ui.router.util.type:UrlMatcher `UrlMatcher`} instances. The factory
565
+ * is also available to providers under the name `$urlMatcherFactoryProvider`.
566
+ */
567
+ function $UrlMatcherFactory() {
568
+ $$UMFP = this;
569
+
570
+ var isCaseInsensitive = false, isStrictMode = true, defaultSquashPolicy = false;
571
+
572
+ function valToString(val) { return val != null ? val.toString().replace(/\//g, "%2F") : val; }
573
+ function valFromString(val) { return val != null ? val.toString().replace(/%2F/g, "/") : val; }
574
+
575
+ var $types = {}, enqueue = true, typeQueue = [], injector, defaultTypes = {
576
+ string: {
577
+ encode: valToString,
578
+ decode: valFromString,
579
+ // TODO: in 1.0, make string .is() return false if value is undefined/null by default.
580
+ // In 0.2.x, string params are optional by default for backwards compat
581
+ is: function(val) { return val == null || !isDefined(val) || typeof val === "string"; },
582
+ pattern: /[^/]*/
583
+ },
584
+ int: {
585
+ encode: valToString,
586
+ decode: function(val) { return parseInt(val, 10); },
587
+ is: function(val) { return isDefined(val) && this.decode(val.toString()) === val; },
588
+ pattern: /\d+/
589
+ },
590
+ bool: {
591
+ encode: function(val) { return val ? 1 : 0; },
592
+ decode: function(val) { return parseInt(val, 10) !== 0; },
593
+ is: function(val) { return val === true || val === false; },
594
+ pattern: /0|1/
595
+ },
596
+ date: {
597
+ encode: function (val) {
598
+ if (!this.is(val))
599
+ return undefined;
600
+ return [ val.getFullYear(),
601
+ ('0' + (val.getMonth() + 1)).slice(-2),
602
+ ('0' + val.getDate()).slice(-2)
603
+ ].join("-");
604
+ },
605
+ decode: function (val) {
606
+ if (this.is(val)) return val;
607
+ var match = this.capture.exec(val);
608
+ return match ? new Date(match[1], match[2] - 1, match[3]) : undefined;
609
+ },
610
+ is: function(val) { return val instanceof Date && !isNaN(val.valueOf()); },
611
+ equals: function (a, b) { return this.is(a) && this.is(b) && a.toISOString() === b.toISOString(); },
612
+ pattern: /[0-9]{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[1-2][0-9]|3[0-1])/,
613
+ capture: /([0-9]{4})-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])/
614
+ },
615
+ json: {
616
+ encode: angular.toJson,
617
+ decode: angular.fromJson,
618
+ is: angular.isObject,
619
+ equals: angular.equals,
620
+ pattern: /[^/]*/
621
+ },
622
+ any: { // does not encode/decode
623
+ encode: angular.identity,
624
+ decode: angular.identity,
625
+ equals: angular.equals,
626
+ pattern: /.*/
627
+ }
628
+ };
629
+
630
+ function getDefaultConfig() {
631
+ return {
632
+ strict: isStrictMode,
633
+ caseInsensitive: isCaseInsensitive
634
+ };
635
+ }
636
+
637
+ function isInjectable(value) {
638
+ return (isFunction(value) || (isArray(value) && isFunction(value[value.length - 1])));
639
+ }
640
+
641
+ /**
642
+ * [Internal] Get the default value of a parameter, which may be an injectable function.
643
+ */
644
+ $UrlMatcherFactory.$$getDefaultValue = function(config) {
645
+ if (!isInjectable(config.value)) return config.value;
646
+ if (!injector) throw new Error("Injectable functions cannot be called at configuration time");
647
+ return injector.invoke(config.value);
648
+ };
649
+
650
+ /**
651
+ * @ngdoc function
652
+ * @name ui.router.util.$urlMatcherFactory#caseInsensitive
653
+ * @methodOf ui.router.util.$urlMatcherFactory
654
+ *
655
+ * @description
656
+ * Defines whether URL matching should be case sensitive (the default behavior), or not.
657
+ *
658
+ * @param {boolean} value `false` to match URL in a case sensitive manner; otherwise `true`;
659
+ * @returns {boolean} the current value of caseInsensitive
660
+ */
661
+ this.caseInsensitive = function(value) {
662
+ if (isDefined(value))
663
+ isCaseInsensitive = value;
664
+ return isCaseInsensitive;
665
+ };
666
+
667
+ /**
668
+ * @ngdoc function
669
+ * @name ui.router.util.$urlMatcherFactory#strictMode
670
+ * @methodOf ui.router.util.$urlMatcherFactory
671
+ *
672
+ * @description
673
+ * Defines whether URLs should match trailing slashes, or not (the default behavior).
674
+ *
675
+ * @param {boolean=} value `false` to match trailing slashes in URLs, otherwise `true`.
676
+ * @returns {boolean} the current value of strictMode
677
+ */
678
+ this.strictMode = function(value) {
679
+ if (isDefined(value))
680
+ isStrictMode = value;
681
+ return isStrictMode;
682
+ };
683
+
684
+ /**
685
+ * @ngdoc function
686
+ * @name ui.router.util.$urlMatcherFactory#defaultSquashPolicy
687
+ * @methodOf ui.router.util.$urlMatcherFactory
688
+ *
689
+ * @description
690
+ * Sets the default behavior when generating or matching URLs with default parameter values.
691
+ *
692
+ * @param {string} value A string that defines the default parameter URL squashing behavior.
693
+ * `nosquash`: When generating an href with a default parameter value, do not squash the parameter value from the URL
694
+ * `slash`: When generating an href with a default parameter value, squash (remove) the parameter value, and, if the
695
+ * parameter is surrounded by slashes, squash (remove) one slash from the URL
696
+ * any other string, e.g. "~": When generating an href with a default parameter value, squash (remove)
697
+ * the parameter value from the URL and replace it with this string.
698
+ */
699
+ this.defaultSquashPolicy = function(value) {
700
+ if (!isDefined(value)) return defaultSquashPolicy;
701
+ if (value !== true && value !== false && !isString(value))
702
+ throw new Error("Invalid squash policy: " + value + ". Valid policies: false, true, arbitrary-string");
703
+ defaultSquashPolicy = value;
704
+ return value;
705
+ };
706
+
707
+ /**
708
+ * @ngdoc function
709
+ * @name ui.router.util.$urlMatcherFactory#compile
710
+ * @methodOf ui.router.util.$urlMatcherFactory
711
+ *
712
+ * @description
713
+ * Creates a {@link ui.router.util.type:UrlMatcher `UrlMatcher`} for the specified pattern.
714
+ *
715
+ * @param {string} pattern The URL pattern.
716
+ * @param {Object} config The config object hash.
717
+ * @returns {UrlMatcher} The UrlMatcher.
718
+ */
719
+ this.compile = function (pattern, config) {
720
+ return new UrlMatcher(pattern, extend(getDefaultConfig(), config));
721
+ };
722
+
723
+ /**
724
+ * @ngdoc function
725
+ * @name ui.router.util.$urlMatcherFactory#isMatcher
726
+ * @methodOf ui.router.util.$urlMatcherFactory
727
+ *
728
+ * @description
729
+ * Returns true if the specified object is a `UrlMatcher`, or false otherwise.
730
+ *
731
+ * @param {Object} object The object to perform the type check against.
732
+ * @returns {Boolean} Returns `true` if the object matches the `UrlMatcher` interface, by
733
+ * implementing all the same methods.
734
+ */
735
+ this.isMatcher = function (o) {
736
+ if (!isObject(o)) return false;
737
+ var result = true;
738
+
739
+ forEach(UrlMatcher.prototype, function(val, name) {
740
+ if (isFunction(val)) {
741
+ result = result && (isDefined(o[name]) && isFunction(o[name]));
742
+ }
743
+ });
744
+ return result;
745
+ };
746
+
747
+ /**
748
+ * @ngdoc function
749
+ * @name ui.router.util.$urlMatcherFactory#type
750
+ * @methodOf ui.router.util.$urlMatcherFactory
751
+ *
752
+ * @description
753
+ * Registers a custom {@link ui.router.util.type:Type `Type`} object that can be used to
754
+ * generate URLs with typed parameters.
755
+ *
756
+ * @param {string} name The type name.
757
+ * @param {Object|Function} definition The type definition. See
758
+ * {@link ui.router.util.type:Type `Type`} for information on the values accepted.
759
+ * @param {Object|Function} definitionFn (optional) A function that is injected before the app
760
+ * runtime starts. The result of this function is merged into the existing `definition`.
761
+ * See {@link ui.router.util.type:Type `Type`} for information on the values accepted.
762
+ *
763
+ * @returns {Object} Returns `$urlMatcherFactoryProvider`.
764
+ *
765
+ * @example
766
+ * This is a simple example of a custom type that encodes and decodes items from an
767
+ * array, using the array index as the URL-encoded value:
768
+ *
769
+ * <pre>
770
+ * var list = ['John', 'Paul', 'George', 'Ringo'];
771
+ *
772
+ * $urlMatcherFactoryProvider.type('listItem', {
773
+ * encode: function(item) {
774
+ * // Represent the list item in the URL using its corresponding index
775
+ * return list.indexOf(item);
776
+ * },
777
+ * decode: function(item) {
778
+ * // Look up the list item by index
779
+ * return list[parseInt(item, 10)];
780
+ * },
781
+ * is: function(item) {
782
+ * // Ensure the item is valid by checking to see that it appears
783
+ * // in the list
784
+ * return list.indexOf(item) > -1;
785
+ * }
786
+ * });
787
+ *
788
+ * $stateProvider.state('list', {
789
+ * url: "/list/{item:listItem}",
790
+ * controller: function($scope, $stateParams) {
791
+ * console.log($stateParams.item);
792
+ * }
793
+ * });
794
+ *
795
+ * // ...
796
+ *
797
+ * // Changes URL to '/list/3', logs "Ringo" to the console
798
+ * $state.go('list', { item: "Ringo" });
799
+ * </pre>
800
+ *
801
+ * This is a more complex example of a type that relies on dependency injection to
802
+ * interact with services, and uses the parameter name from the URL to infer how to
803
+ * handle encoding and decoding parameter values:
804
+ *
805
+ * <pre>
806
+ * // Defines a custom type that gets a value from a service,
807
+ * // where each service gets different types of values from
808
+ * // a backend API:
809
+ * $urlMatcherFactoryProvider.type('dbObject', {}, function(Users, Posts) {
810
+ *
811
+ * // Matches up services to URL parameter names
812
+ * var services = {
813
+ * user: Users,
814
+ * post: Posts
815
+ * };
816
+ *
817
+ * return {
818
+ * encode: function(object) {
819
+ * // Represent the object in the URL using its unique ID
820
+ * return object.id;
821
+ * },
822
+ * decode: function(value, key) {
823
+ * // Look up the object by ID, using the parameter
824
+ * // name (key) to call the correct service
825
+ * return services[key].findById(value);
826
+ * },
827
+ * is: function(object, key) {
828
+ * // Check that object is a valid dbObject
829
+ * return angular.isObject(object) && object.id && services[key];
830
+ * }
831
+ * equals: function(a, b) {
832
+ * // Check the equality of decoded objects by comparing
833
+ * // their unique IDs
834
+ * return a.id === b.id;
835
+ * }
836
+ * };
837
+ * });
838
+ *
839
+ * // In a config() block, you can then attach URLs with
840
+ * // type-annotated parameters:
841
+ * $stateProvider.state('users', {
842
+ * url: "/users",
843
+ * // ...
844
+ * }).state('users.item', {
845
+ * url: "/{user:dbObject}",
846
+ * controller: function($scope, $stateParams) {
847
+ * // $stateParams.user will now be an object returned from
848
+ * // the Users service
849
+ * },
850
+ * // ...
851
+ * });
852
+ * </pre>
853
+ */
854
+ this.type = function (name, definition, definitionFn) {
855
+ if (!isDefined(definition)) return $types[name];
856
+ if ($types.hasOwnProperty(name)) throw new Error("A type named '" + name + "' has already been defined.");
857
+
858
+ $types[name] = new Type(extend({ name: name }, definition));
859
+ if (definitionFn) {
860
+ typeQueue.push({ name: name, def: definitionFn });
861
+ if (!enqueue) flushTypeQueue();
862
+ }
863
+ return this;
864
+ };
865
+
866
+ // `flushTypeQueue()` waits until `$urlMatcherFactory` is injected before invoking the queued `definitionFn`s
867
+ function flushTypeQueue() {
868
+ while(typeQueue.length) {
869
+ var type = typeQueue.shift();
870
+ if (type.pattern) throw new Error("You cannot override a type's .pattern at runtime.");
871
+ angular.extend($types[type.name], injector.invoke(type.def));
872
+ }
873
+ }
874
+
875
+ // Register default types. Store them in the prototype of $types.
876
+ forEach(defaultTypes, function(type, name) { $types[name] = new Type(extend({name: name}, type)); });
877
+ $types = inherit($types, {});
878
+
879
+ /* No need to document $get, since it returns this */
880
+ this.$get = ['$injector', function ($injector) {
881
+ injector = $injector;
882
+ enqueue = false;
883
+ flushTypeQueue();
884
+
885
+ forEach(defaultTypes, function(type, name) {
886
+ if (!$types[name]) $types[name] = new Type(type);
887
+ });
888
+ return this;
889
+ }];
890
+
891
+ this.Param = function Param(id, type, config, location) {
892
+ var self = this;
893
+ config = unwrapShorthand(config);
894
+ type = getType(config, type, location);
895
+ var arrayMode = getArrayMode();
896
+ type = arrayMode ? type.$asArray(arrayMode, location === "search") : type;
897
+ if (type.name === "string" && !arrayMode && location === "path" && config.value === undefined)
898
+ config.value = ""; // for 0.2.x; in 0.3.0+ do not automatically default to ""
899
+ var isOptional = config.value !== undefined;
900
+ var squash = getSquashPolicy(config, isOptional);
901
+ var replace = getReplace(config, arrayMode, isOptional, squash);
902
+
903
+ function unwrapShorthand(config) {
904
+ var keys = isObject(config) ? objectKeys(config) : [];
905
+ var isShorthand = indexOf(keys, "value") === -1 && indexOf(keys, "type") === -1 &&
906
+ indexOf(keys, "squash") === -1 && indexOf(keys, "array") === -1;
907
+ if (isShorthand) config = { value: config };
908
+ config.$$fn = isInjectable(config.value) ? config.value : function () { return config.value; };
909
+ return config;
910
+ }
911
+
912
+ function getType(config, urlType, location) {
913
+ if (config.type && urlType) throw new Error("Param '"+id+"' has two type configurations.");
914
+ if (urlType) return urlType;
915
+ if (!config.type) return (location === "config" ? $types.any : $types.string);
916
+ return config.type instanceof Type ? config.type : new Type(config.type);
917
+ }
918
+
919
+ // array config: param name (param[]) overrides default settings. explicit config overrides param name.
920
+ function getArrayMode() {
921
+ var arrayDefaults = { array: (location === "search" ? "auto" : false) };
922
+ var arrayParamNomenclature = id.match(/\[\]$/) ? { array: true } : {};
923
+ return extend(arrayDefaults, arrayParamNomenclature, config).array;
924
+ }
925
+
926
+ /**
927
+ * returns false, true, or the squash value to indicate the "default parameter url squash policy".
928
+ */
929
+ function getSquashPolicy(config, isOptional) {
930
+ var squash = config.squash;
931
+ if (!isOptional || squash === false) return false;
932
+ if (!isDefined(squash) || squash == null) return defaultSquashPolicy;
933
+ if (squash === true || isString(squash)) return squash;
934
+ throw new Error("Invalid squash policy: '" + squash + "'. Valid policies: false, true, or arbitrary string");
935
+ }
936
+
937
+ function getReplace(config, arrayMode, isOptional, squash) {
938
+ var replace, configuredKeys, defaultPolicy = [
939
+ { from: "", to: (isOptional || arrayMode ? undefined : "") },
940
+ { from: null, to: (isOptional || arrayMode ? undefined : "") }
941
+ ];
942
+ replace = isArray(config.replace) ? config.replace : [];
943
+ if (isString(squash))
944
+ replace.push({ from: squash, to: undefined });
945
+ configuredKeys = map(replace, function(item) { return item.from; } );
946
+ return filter(defaultPolicy, function(item) { return indexOf(configuredKeys, item.from) === -1; }).concat(replace);
947
+ }
948
+
949
+ /**
950
+ * [Internal] Get the default value of a parameter, which may be an injectable function.
951
+ */
952
+ function $$getDefaultValue() {
953
+ if (!injector) throw new Error("Injectable functions cannot be called at configuration time");
954
+ var defaultValue = injector.invoke(config.$$fn);
955
+ if (defaultValue !== null && defaultValue !== undefined && !self.type.is(defaultValue))
956
+ throw new Error("Default value (" + defaultValue + ") for parameter '" + self.id + "' is not an instance of Type (" + self.type.name + ")");
957
+ return defaultValue;
958
+ }
959
+
960
+ /**
961
+ * [Internal] Gets the decoded representation of a value if the value is defined, otherwise, returns the
962
+ * default value, which may be the result of an injectable function.
963
+ */
964
+ function $value(value) {
965
+ function hasReplaceVal(val) { return function(obj) { return obj.from === val; }; }
966
+ function $replace(value) {
967
+ var replacement = map(filter(self.replace, hasReplaceVal(value)), function(obj) { return obj.to; });
968
+ return replacement.length ? replacement[0] : value;
969
+ }
970
+ value = $replace(value);
971
+ return !isDefined(value) ? $$getDefaultValue() : self.type.$normalize(value);
972
+ }
973
+
974
+ function toString() { return "{Param:" + id + " " + type + " squash: '" + squash + "' optional: " + isOptional + "}"; }
975
+
976
+ extend(this, {
977
+ id: id,
978
+ type: type,
979
+ location: location,
980
+ array: arrayMode,
981
+ squash: squash,
982
+ replace: replace,
983
+ isOptional: isOptional,
984
+ value: $value,
985
+ dynamic: undefined,
986
+ config: config,
987
+ toString: toString
988
+ });
989
+ };
990
+
991
+ function ParamSet(params) {
992
+ extend(this, params || {});
993
+ }
994
+
995
+ ParamSet.prototype = {
996
+ $$new: function() {
997
+ return inherit(this, extend(new ParamSet(), { $$parent: this}));
998
+ },
999
+ $$keys: function () {
1000
+ var keys = [], chain = [], parent = this,
1001
+ ignore = objectKeys(ParamSet.prototype);
1002
+ while (parent) { chain.push(parent); parent = parent.$$parent; }
1003
+ chain.reverse();
1004
+ forEach(chain, function(paramset) {
1005
+ forEach(objectKeys(paramset), function(key) {
1006
+ if (indexOf(keys, key) === -1 && indexOf(ignore, key) === -1) keys.push(key);
1007
+ });
1008
+ });
1009
+ return keys;
1010
+ },
1011
+ $$values: function(paramValues) {
1012
+ var values = {}, self = this;
1013
+ forEach(self.$$keys(), function(key) {
1014
+ values[key] = self[key].value(paramValues && paramValues[key]);
1015
+ });
1016
+ return values;
1017
+ },
1018
+ $$equals: function(paramValues1, paramValues2) {
1019
+ var equal = true, self = this;
1020
+ forEach(self.$$keys(), function(key) {
1021
+ var left = paramValues1 && paramValues1[key], right = paramValues2 && paramValues2[key];
1022
+ if (!self[key].type.equals(left, right)) equal = false;
1023
+ });
1024
+ return equal;
1025
+ },
1026
+ $$validates: function $$validate(paramValues) {
1027
+ var keys = this.$$keys(), i, param, rawVal, normalized, encoded;
1028
+ for (i = 0; i < keys.length; i++) {
1029
+ param = this[keys[i]];
1030
+ rawVal = paramValues[keys[i]];
1031
+ if ((rawVal === undefined || rawVal === null) && param.isOptional)
1032
+ break; // There was no parameter value, but the param is optional
1033
+ normalized = param.type.$normalize(rawVal);
1034
+ if (!param.type.is(normalized))
1035
+ return false; // The value was not of the correct Type, and could not be decoded to the correct Type
1036
+ encoded = param.type.encode(normalized);
1037
+ if (angular.isString(encoded) && !param.type.pattern.exec(encoded))
1038
+ return false; // The value was of the correct type, but when encoded, did not match the Type's regexp
1039
+ }
1040
+ return true;
1041
+ },
1042
+ $$parent: undefined
1043
+ };
1044
+
1045
+ this.ParamSet = ParamSet;
1046
+ }
1047
+
1048
+ // Register as a provider so it's available to other providers
1049
+ angular.module('ui.router.util').provider('$urlMatcherFactory', $UrlMatcherFactory);
1050
+ angular.module('ui.router.util').run(['$urlMatcherFactory', function($urlMatcherFactory) { }]);