0
Fork 0
mirror of https://github.com/verdaccio/verdaccio.git synced 2025-03-25 02:32:52 -05:00

add authentication to web interface

This commit is contained in:
Alex Kocharin 2014-11-04 17:47:03 +03:00
parent 7b34bb63c9
commit 67b4528643
11 changed files with 1298 additions and 298 deletions

View file

@ -1,10 +1,10 @@
/*!
* Bootstrap v3.2.0 (http://getbootstrap.com)
* Bootstrap v3.3.0 (http://getbootstrap.com)
* Copyright 2011-2014 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
*/
/*! normalize.css v3.0.1 | MIT License | git.io/normalize */
/*! normalize.css v3.0.2 | MIT License | git.io/normalize */
html {
font-family: sans-serif;
-webkit-text-size-adjust: 100%;
@ -22,6 +22,7 @@ footer,
header,
hgroup,
main,
menu,
nav,
section,
summary {
@ -43,7 +44,7 @@ template {
display: none;
}
a {
background: transparent;
background-color: transparent;
}
a:active,
a:hover {
@ -187,8 +188,11 @@ td,
th {
padding: 0;
}
/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */
@media print {
* {
*,
*:before,
*:after {
color: #000 !important;
text-shadow: none !important;
background: transparent !important;
@ -205,8 +209,8 @@ th {
abbr[title]:after {
content: " (" attr(title) ")";
}
a[href^="javascript:"]:after,
a[href^="#"]:after {
a[href^="#"]:after,
a[href^="javascript:"]:after {
content: "";
}
pre,
@ -241,10 +245,6 @@ th {
.navbar {
display: none;
}
.table td,
.table th {
background-color: #fff !important;
}
.btn > .caret,
.dropup > .btn > .caret {
border-top-color: #000 !important;
@ -255,6 +255,10 @@ th {
.table {
border-collapse: collapse !important;
}
.table td,
.table th {
background-color: #fff !important;
}
.table-bordered th,
.table-bordered td {
border: 1px solid #ddd !important;
@ -284,7 +288,8 @@ th {
.glyphicon-plus:before {
content: "\2b";
}
.glyphicon-euro:before {
.glyphicon-euro:before,
.glyphicon-eur:before {
content: "\20ac";
}
.glyphicon-minus:before {
@ -935,7 +940,6 @@ img {
.carousel-inner > .item > img,
.carousel-inner > .item > a > img {
display: block;
width: 100% \9;
max-width: 100%;
height: auto;
}
@ -944,7 +948,6 @@ img {
}
.img-thumbnail {
display: inline-block;
width: 100% \9;
max-width: 100%;
height: auto;
padding: 4px;
@ -1117,9 +1120,6 @@ small,
.small {
font-size: 85%;
}
cite {
font-style: normal;
}
mark,
.mark {
padding: .2em;
@ -1328,10 +1328,6 @@ blockquote.pull-right small:after,
blockquote.pull-right .small:after {
content: '\00A0 \2014';
}
blockquote:before,
blockquote:after {
content: "";
}
address {
margin-bottom: 20px;
font-style: normal;
@ -1362,6 +1358,7 @@ kbd {
kbd kbd {
padding: 0;
font-size: 100%;
font-weight: bold;
-webkit-box-shadow: none;
box-shadow: none;
}
@ -2060,6 +2057,12 @@ pre code {
table {
background-color: transparent;
}
caption {
padding-top: 8px;
padding-bottom: 8px;
color: #777;
text-align: left;
}
th {
text-align: left;
}
@ -2120,12 +2123,10 @@ th {
.table-bordered > thead > tr > td {
border-bottom-width: 2px;
}
.table-striped > tbody > tr:nth-child(odd) > td,
.table-striped > tbody > tr:nth-child(odd) > th {
.table-striped > tbody > tr:nth-child(odd) {
background-color: #f9f9f9;
}
.table-hover > tbody > tr:hover > td,
.table-hover > tbody > tr:hover > th {
.table-hover > tbody > tr:hover {
background-color: #f5f5f5;
}
table col[class*="col-"] {
@ -2244,13 +2245,15 @@ table th[class*="col-"] {
.table-hover > tbody > tr.danger:hover > th {
background-color: #ebcccc;
}
.table-responsive {
min-height: .01%;
overflow-x: auto;
}
@media screen and (max-width: 767px) {
.table-responsive {
width: 100%;
margin-bottom: 15px;
overflow-x: auto;
overflow-y: hidden;
-webkit-overflow-scrolling: touch;
-ms-overflow-style: -ms-autohiding-scrollbar;
border: 1px solid #ddd;
}
@ -2375,14 +2378,14 @@ output {
box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6);
}
.form-control::-moz-placeholder {
color: #777;
color: #999;
opacity: 1;
}
.form-control:-ms-input-placeholder {
color: #777;
color: #999;
}
.form-control::-webkit-input-placeholder {
color: #777;
color: #999;
}
.form-control[disabled],
.form-control[readonly],
@ -2409,12 +2412,44 @@ input[type="time"].input-sm,
input[type="datetime-local"].input-sm,
input[type="month"].input-sm {
line-height: 30px;
line-height: 1.5 \0;
}
input[type="date"].input-lg,
input[type="time"].input-lg,
input[type="datetime-local"].input-lg,
input[type="month"].input-lg {
line-height: 46px;
line-height: 1.33 \0;
}
_:-ms-fullscreen,
:root input[type="date"],
_:-ms-fullscreen,
:root input[type="time"],
_:-ms-fullscreen,
:root input[type="datetime-local"],
_:-ms-fullscreen,
:root input[type="month"] {
line-height: 1.42857143;
}
_:-ms-fullscreen.input-sm,
:root input[type="date"].input-sm,
_:-ms-fullscreen.input-sm,
:root input[type="time"].input-sm,
_:-ms-fullscreen.input-sm,
:root input[type="datetime-local"].input-sm,
_:-ms-fullscreen.input-sm,
:root input[type="month"].input-sm {
line-height: 1.5;
}
_:-ms-fullscreen.input-lg,
:root input[type="date"].input-lg,
_:-ms-fullscreen.input-lg,
:root input[type="time"].input-lg,
_:-ms-fullscreen.input-lg,
:root input[type="datetime-local"].input-lg,
_:-ms-fullscreen.input-lg,
:root input[type="month"].input-lg {
line-height: 1.33;
}
.form-group {
margin-bottom: 15px;
@ -2423,12 +2458,12 @@ input[type="month"].input-lg {
.checkbox {
position: relative;
display: block;
min-height: 20px;
margin-top: 10px;
margin-bottom: 10px;
}
.radio label,
.checkbox label {
min-height: 20px;
padding-left: 20px;
margin-bottom: 0;
font-weight: normal;
@ -2491,35 +2526,41 @@ fieldset[disabled] .checkbox label {
padding-left: 0;
}
.input-sm,
.form-horizontal .form-group-sm .form-control {
.form-group-sm .form-control {
height: 30px;
padding: 5px 10px;
font-size: 12px;
line-height: 1.5;
border-radius: 3px;
}
select.input-sm {
select.input-sm,
select.form-group-sm .form-control {
height: 30px;
line-height: 30px;
}
textarea.input-sm,
select[multiple].input-sm {
textarea.form-group-sm .form-control,
select[multiple].input-sm,
select[multiple].form-group-sm .form-control {
height: auto;
}
.input-lg,
.form-horizontal .form-group-lg .form-control {
.form-group-lg .form-control {
height: 46px;
padding: 10px 16px;
font-size: 18px;
line-height: 1.33;
border-radius: 6px;
}
select.input-lg {
select.input-lg,
select.form-group-lg .form-control {
height: 46px;
line-height: 46px;
}
textarea.input-lg,
select[multiple].input-lg {
textarea.form-group-lg .form-control,
select[multiple].input-lg,
select[multiple].form-group-lg .form-control {
height: auto;
}
.has-feedback {
@ -2530,7 +2571,7 @@ select[multiple].input-lg {
}
.form-control-feedback {
position: absolute;
top: 25px;
top: 0;
right: 0;
z-index: 2;
display: block;
@ -2538,6 +2579,7 @@ select[multiple].input-lg {
height: 34px;
line-height: 34px;
text-align: center;
pointer-events: none;
}
.input-lg + .form-control-feedback {
width: 46px;
@ -2554,7 +2596,11 @@ select[multiple].input-lg {
.has-success .radio,
.has-success .checkbox,
.has-success .radio-inline,
.has-success .checkbox-inline {
.has-success .checkbox-inline,
.has-success.radio label,
.has-success.checkbox label,
.has-success.radio-inline label,
.has-success.checkbox-inline label {
color: #3c763d;
}
.has-success .form-control {
@ -2580,7 +2626,11 @@ select[multiple].input-lg {
.has-warning .radio,
.has-warning .checkbox,
.has-warning .radio-inline,
.has-warning .checkbox-inline {
.has-warning .checkbox-inline,
.has-warning.radio label,
.has-warning.checkbox label,
.has-warning.radio-inline label,
.has-warning.checkbox-inline label {
color: #8a6d3b;
}
.has-warning .form-control {
@ -2606,7 +2656,11 @@ select[multiple].input-lg {
.has-error .radio,
.has-error .checkbox,
.has-error .radio-inline,
.has-error .checkbox-inline {
.has-error .checkbox-inline,
.has-error.radio label,
.has-error.checkbox label,
.has-error.radio-inline label,
.has-error.checkbox-inline label {
color: #a94442;
}
.has-error .form-control {
@ -2627,6 +2681,9 @@ select[multiple].input-lg {
.has-error .form-control-feedback {
color: #a94442;
}
.has-feedback label ~ .form-control-feedback {
top: 25px;
}
.has-feedback label.sr-only ~ .form-control-feedback {
top: 0;
}
@ -2647,6 +2704,9 @@ select[multiple].input-lg {
width: auto;
vertical-align: middle;
}
.form-inline .form-control-static {
display: inline-block;
}
.form-inline .input-group {
display: inline-table;
vertical-align: middle;
@ -2707,7 +2767,6 @@ select[multiple].input-lg {
}
}
.form-horizontal .has-feedback .form-control-feedback {
top: 0;
right: 15px;
}
@media (min-width: 768px) {
@ -2730,6 +2789,8 @@ select[multiple].input-lg {
text-align: center;
white-space: nowrap;
vertical-align: middle;
-ms-touch-action: manipulation;
touch-action: manipulation;
cursor: pointer;
-webkit-user-select: none;
-moz-user-select: none;
@ -2741,13 +2802,17 @@ select[multiple].input-lg {
}
.btn:focus,
.btn:active:focus,
.btn.active:focus {
.btn.active:focus,
.btn.focus,
.btn:active.focus,
.btn.active.focus {
outline: thin dotted;
outline: 5px auto -webkit-focus-ring-color;
outline-offset: -2px;
}
.btn:hover,
.btn:focus {
.btn:focus,
.btn.focus {
color: #333;
text-decoration: none;
}
@ -2775,6 +2840,7 @@ fieldset[disabled] .btn {
}
.btn-default:hover,
.btn-default:focus,
.btn-default.focus,
.btn-default:active,
.btn-default.active,
.open > .dropdown-toggle.btn-default {
@ -2796,6 +2862,9 @@ fieldset[disabled] .btn-default:hover,
.btn-default.disabled:focus,
.btn-default[disabled]:focus,
fieldset[disabled] .btn-default:focus,
.btn-default.disabled.focus,
.btn-default[disabled].focus,
fieldset[disabled] .btn-default.focus,
.btn-default.disabled:active,
.btn-default[disabled]:active,
fieldset[disabled] .btn-default:active,
@ -2816,6 +2885,7 @@ fieldset[disabled] .btn-default.active {
}
.btn-primary:hover,
.btn-primary:focus,
.btn-primary.focus,
.btn-primary:active,
.btn-primary.active,
.open > .dropdown-toggle.btn-primary {
@ -2837,6 +2907,9 @@ fieldset[disabled] .btn-primary:hover,
.btn-primary.disabled:focus,
.btn-primary[disabled]:focus,
fieldset[disabled] .btn-primary:focus,
.btn-primary.disabled.focus,
.btn-primary[disabled].focus,
fieldset[disabled] .btn-primary.focus,
.btn-primary.disabled:active,
.btn-primary[disabled]:active,
fieldset[disabled] .btn-primary:active,
@ -2857,6 +2930,7 @@ fieldset[disabled] .btn-primary.active {
}
.btn-success:hover,
.btn-success:focus,
.btn-success.focus,
.btn-success:active,
.btn-success.active,
.open > .dropdown-toggle.btn-success {
@ -2878,6 +2952,9 @@ fieldset[disabled] .btn-success:hover,
.btn-success.disabled:focus,
.btn-success[disabled]:focus,
fieldset[disabled] .btn-success:focus,
.btn-success.disabled.focus,
.btn-success[disabled].focus,
fieldset[disabled] .btn-success.focus,
.btn-success.disabled:active,
.btn-success[disabled]:active,
fieldset[disabled] .btn-success:active,
@ -2898,6 +2975,7 @@ fieldset[disabled] .btn-success.active {
}
.btn-info:hover,
.btn-info:focus,
.btn-info.focus,
.btn-info:active,
.btn-info.active,
.open > .dropdown-toggle.btn-info {
@ -2919,6 +2997,9 @@ fieldset[disabled] .btn-info:hover,
.btn-info.disabled:focus,
.btn-info[disabled]:focus,
fieldset[disabled] .btn-info:focus,
.btn-info.disabled.focus,
.btn-info[disabled].focus,
fieldset[disabled] .btn-info.focus,
.btn-info.disabled:active,
.btn-info[disabled]:active,
fieldset[disabled] .btn-info:active,
@ -2939,6 +3020,7 @@ fieldset[disabled] .btn-info.active {
}
.btn-warning:hover,
.btn-warning:focus,
.btn-warning.focus,
.btn-warning:active,
.btn-warning.active,
.open > .dropdown-toggle.btn-warning {
@ -2960,6 +3042,9 @@ fieldset[disabled] .btn-warning:hover,
.btn-warning.disabled:focus,
.btn-warning[disabled]:focus,
fieldset[disabled] .btn-warning:focus,
.btn-warning.disabled.focus,
.btn-warning[disabled].focus,
fieldset[disabled] .btn-warning.focus,
.btn-warning.disabled:active,
.btn-warning[disabled]:active,
fieldset[disabled] .btn-warning:active,
@ -2980,6 +3065,7 @@ fieldset[disabled] .btn-warning.active {
}
.btn-danger:hover,
.btn-danger:focus,
.btn-danger.focus,
.btn-danger:active,
.btn-danger.active,
.open > .dropdown-toggle.btn-danger {
@ -3001,6 +3087,9 @@ fieldset[disabled] .btn-danger:hover,
.btn-danger.disabled:focus,
.btn-danger[disabled]:focus,
fieldset[disabled] .btn-danger:focus,
.btn-danger.disabled.focus,
.btn-danger[disabled].focus,
fieldset[disabled] .btn-danger.focus,
.btn-danger.disabled:active,
.btn-danger[disabled]:active,
fieldset[disabled] .btn-danger:active,
@ -3017,11 +3106,11 @@ fieldset[disabled] .btn-danger.active {
.btn-link {
font-weight: normal;
color: #428bca;
cursor: pointer;
border-radius: 0;
}
.btn-link,
.btn-link:active,
.btn-link.active,
.btn-link[disabled],
fieldset[disabled] .btn-link {
background-color: transparent;
@ -3091,9 +3180,11 @@ input[type="button"].btn-block {
}
.collapse {
display: none;
visibility: hidden;
}
.collapse.in {
display: block;
visibility: visible;
}
tr.collapse.in {
display: table-row;
@ -3105,9 +3196,15 @@ tbody.collapse.in {
position: relative;
height: 0;
overflow: hidden;
-webkit-transition: height .35s ease;
-o-transition: height .35s ease;
transition: height .35s ease;
-webkit-transition-timing-function: ease;
-o-transition-timing-function: ease;
transition-timing-function: ease;
-webkit-transition-duration: .35s;
-o-transition-duration: .35s;
transition-duration: .35s;
-webkit-transition-property: height, visibility;
-o-transition-property: height, visibility;
transition-property: height, visibility;
}
.caret {
display: inline-block;
@ -3413,12 +3510,13 @@ tbody.collapse.in {
.btn-group-justified > .btn-group .dropdown-menu {
left: auto;
}
[data-toggle="buttons"] > .btn > input[type="radio"],
[data-toggle="buttons"] > .btn > input[type="checkbox"] {
[data-toggle="buttons"] > .btn input[type="radio"],
[data-toggle="buttons"] > .btn-group > .btn input[type="radio"],
[data-toggle="buttons"] > .btn input[type="checkbox"],
[data-toggle="buttons"] > .btn-group > .btn input[type="checkbox"] {
position: absolute;
z-index: -1;
filter: alpha(opacity=0);
opacity: 0;
clip: rect(0, 0, 0, 0);
pointer-events: none;
}
.input-group {
position: relative;
@ -3757,9 +3855,11 @@ select[multiple].input-group-sm > .input-group-btn > .btn {
}
.tab-content > .tab-pane {
display: none;
visibility: hidden;
}
.tab-content > .active {
display: block;
visibility: visible;
}
.nav-tabs .dropdown-menu {
margin-top: -1px;
@ -3806,6 +3906,7 @@ select[multiple].input-group-sm > .input-group-btn > .btn {
height: auto !important;
padding-bottom: 0;
overflow: visible !important;
visibility: visible !important;
}
.navbar-collapse.in {
overflow-y: visible;
@ -3821,7 +3922,7 @@ select[multiple].input-group-sm > .input-group-btn > .btn {
.navbar-fixed-bottom .navbar-collapse {
max-height: 340px;
}
@media (max-width: 480px) and (orientation: landscape) {
@media (max-device-width: 480px) and (orientation: landscape) {
.navbar-fixed-top .navbar-collapse,
.navbar-fixed-bottom .navbar-collapse {
max-height: 200px;
@ -3858,9 +3959,6 @@ select[multiple].input-group-sm > .input-group-btn > .btn {
right: 0;
left: 0;
z-index: 1030;
-webkit-transform: translate3d(0, 0, 0);
-o-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
@media (min-width: 768px) {
.navbar-fixed-top,
@ -3888,6 +3986,9 @@ select[multiple].input-group-sm > .input-group-btn > .btn {
.navbar-brand:focus {
text-decoration: none;
}
.navbar-brand > img {
display: block;
}
@media (min-width: 768px) {
.navbar > .container .navbar-brand,
.navbar > .container-fluid .navbar-brand {
@ -3966,17 +4067,6 @@ select[multiple].input-group-sm > .input-group-btn > .btn {
padding-top: 15px;
padding-bottom: 15px;
}
.navbar-nav.navbar-right:last-child {
margin-right: -15px;
}
}
@media (min-width: 768px) {
.navbar-left {
float: left !important;
}
.navbar-right {
float: right !important;
}
}
.navbar-form {
padding: 10px 15px;
@ -4000,6 +4090,9 @@ select[multiple].input-group-sm > .input-group-btn > .btn {
width: auto;
vertical-align: middle;
}
.navbar-form .form-control-static {
display: inline-block;
}
.navbar-form .input-group {
display: inline-table;
vertical-align: middle;
@ -4040,6 +4133,9 @@ select[multiple].input-group-sm > .input-group-btn > .btn {
.navbar-form .form-group {
margin-bottom: 5px;
}
.navbar-form .form-group:last-child {
margin-bottom: 0;
}
}
@media (min-width: 768px) {
.navbar-form {
@ -4052,9 +4148,6 @@ select[multiple].input-group-sm > .input-group-btn > .btn {
-webkit-box-shadow: none;
box-shadow: none;
}
.navbar-form.navbar-right:last-child {
margin-right: -15px;
}
}
.navbar-nav > li > .dropdown-menu {
margin-top: 0;
@ -4087,7 +4180,16 @@ select[multiple].input-group-sm > .input-group-btn > .btn {
margin-right: 15px;
margin-left: 15px;
}
.navbar-text.navbar-right:last-child {
}
@media (min-width: 768px) {
.navbar-left {
float: left !important;
}
.navbar-right {
float: right !important;
margin-right: -15px;
}
.navbar-right ~ .navbar-right {
margin-right: 0;
}
}
@ -4192,7 +4294,7 @@ fieldset[disabled] .navbar-default .btn-link:focus {
border-color: #080808;
}
.navbar-inverse .navbar-brand {
color: #777;
color: #9d9d9d;
}
.navbar-inverse .navbar-brand:hover,
.navbar-inverse .navbar-brand:focus {
@ -4200,10 +4302,10 @@ fieldset[disabled] .navbar-default .btn-link:focus {
background-color: transparent;
}
.navbar-inverse .navbar-text {
color: #777;
color: #9d9d9d;
}
.navbar-inverse .navbar-nav > li > a {
color: #777;
color: #9d9d9d;
}
.navbar-inverse .navbar-nav > li > a:hover,
.navbar-inverse .navbar-nav > li > a:focus {
@ -4250,7 +4352,7 @@ fieldset[disabled] .navbar-default .btn-link:focus {
background-color: #080808;
}
.navbar-inverse .navbar-nav .open .dropdown-menu > li > a {
color: #777;
color: #9d9d9d;
}
.navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover,
.navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus {
@ -4271,13 +4373,13 @@ fieldset[disabled] .navbar-default .btn-link:focus {
}
}
.navbar-inverse .navbar-link {
color: #777;
color: #9d9d9d;
}
.navbar-inverse .navbar-link:hover {
color: #fff;
}
.navbar-inverse .btn-link {
color: #777;
color: #9d9d9d;
}
.navbar-inverse .btn-link:hover,
.navbar-inverse .btn-link:focus {
@ -4545,7 +4647,7 @@ a.list-group-item.active > .badge,
margin-left: 3px;
}
.jumbotron {
padding: 30px;
padding: 30px 15px;
margin-bottom: 30px;
color: inherit;
background-color: #eee;
@ -4562,7 +4664,8 @@ a.list-group-item.active > .badge,
.jumbotron > hr {
border-top-color: #d5d5d5;
}
.container .jumbotron {
.container .jumbotron,
.container-fluid .jumbotron {
border-radius: 6px;
}
.jumbotron .container {
@ -4570,8 +4673,7 @@ a.list-group-item.active > .badge,
}
@media screen and (min-width: 768px) {
.jumbotron {
padding-top: 48px;
padding-bottom: 48px;
padding: 48px 0;
}
.container .jumbotron {
padding-right: 60px;
@ -4590,9 +4692,9 @@ a.list-group-item.active > .badge,
background-color: #fff;
border: 1px solid #ddd;
border-radius: 4px;
-webkit-transition: all .2s ease-in-out;
-o-transition: all .2s ease-in-out;
transition: all .2s ease-in-out;
-webkit-transition: border .2s ease-in-out;
-o-transition: border .2s ease-in-out;
transition: border .2s ease-in-out;
}
.thumbnail > img,
.thumbnail a > img {
@ -4745,18 +4847,6 @@ a.thumbnail.active {
-o-animation: progress-bar-stripes 2s linear infinite;
animation: progress-bar-stripes 2s linear infinite;
}
.progress-bar[aria-valuenow="1"],
.progress-bar[aria-valuenow="2"] {
min-width: 30px;
}
.progress-bar[aria-valuenow="0"] {
min-width: 30px;
color: #777;
background-color: transparent;
background-image: none;
-webkit-box-shadow: none;
box-shadow: none;
}
.progress-bar-success {
background-color: #5cb85c;
}
@ -4789,29 +4879,35 @@ a.thumbnail.active {
background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
}
.media,
.media-body {
overflow: hidden;
zoom: 1;
}
.media,
.media .media {
.media {
margin-top: 15px;
}
.media:first-child {
margin-top: 0;
}
.media-object {
display: block;
.media-right,
.media > .pull-right {
padding-left: 10px;
}
.media-left,
.media > .pull-left {
padding-right: 10px;
}
.media-left,
.media-right,
.media-body {
display: table-cell;
vertical-align: top;
}
.media-middle {
vertical-align: middle;
}
.media-bottom {
vertical-align: bottom;
}
.media-heading {
margin: 0 0 5px;
}
.media > .pull-left {
margin-right: 10px;
}
.media > .pull-right {
margin-left: 10px;
margin-top: 0;
margin-bottom: 5px;
}
.media-list {
padding-left: 0;
@ -4860,6 +4956,7 @@ a.list-group-item:focus {
.list-group-item.disabled:hover,
.list-group-item.disabled:focus {
color: #777;
cursor: not-allowed;
background-color: #eee;
}
.list-group-item.disabled .list-group-item-heading,
@ -5028,19 +5125,23 @@ a.list-group-item-danger.active:focus {
border-bottom-right-radius: 3px;
border-bottom-left-radius: 3px;
}
.panel > .list-group {
.panel > .list-group,
.panel > .panel-collapse > .list-group {
margin-bottom: 0;
}
.panel > .list-group .list-group-item {
.panel > .list-group .list-group-item,
.panel > .panel-collapse > .list-group .list-group-item {
border-width: 1px 0;
border-radius: 0;
}
.panel > .list-group:first-child .list-group-item:first-child {
.panel > .list-group:first-child .list-group-item:first-child,
.panel > .panel-collapse > .list-group:first-child .list-group-item:first-child {
border-top: 0;
border-top-left-radius: 3px;
border-top-right-radius: 3px;
}
.panel > .list-group:last-child .list-group-item:last-child {
.panel > .list-group:last-child .list-group-item:last-child,
.panel > .panel-collapse > .list-group:last-child .list-group-item:last-child {
border-bottom: 0;
border-bottom-right-radius: 3px;
border-bottom-left-radius: 3px;
@ -5056,11 +5157,24 @@ a.list-group-item-danger.active:focus {
.panel > .panel-collapse > .table {
margin-bottom: 0;
}
.panel > .table caption,
.panel > .table-responsive > .table caption,
.panel > .panel-collapse > .table caption {
padding-right: 15px;
padding-left: 15px;
}
.panel > .table:first-child,
.panel > .table-responsive:first-child > .table:first-child {
border-top-left-radius: 3px;
border-top-right-radius: 3px;
}
.panel > .table:first-child > thead:first-child > tr:first-child,
.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child,
.panel > .table:first-child > tbody:first-child > tr:first-child,
.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child {
border-top-left-radius: 3px;
border-top-right-radius: 3px;
}
.panel > .table:first-child > thead:first-child > tr:first-child td:first-child,
.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child,
.panel > .table:first-child > tbody:first-child > tr:first-child td:first-child,
@ -5086,6 +5200,13 @@ a.list-group-item-danger.active:focus {
border-bottom-right-radius: 3px;
border-bottom-left-radius: 3px;
}
.panel > .table:last-child > tbody:last-child > tr:last-child,
.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child,
.panel > .table:last-child > tfoot:last-child > tr:last-child,
.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child {
border-bottom-right-radius: 3px;
border-bottom-left-radius: 3px;
}
.panel > .table:last-child > tbody:last-child > tr:last-child td:first-child,
.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child,
.panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child,
@ -5107,7 +5228,9 @@ a.list-group-item-danger.active:focus {
border-bottom-right-radius: 3px;
}
.panel > .panel-body + .table,
.panel > .panel-body + .table-responsive {
.panel > .panel-body + .table-responsive,
.panel > .table + .panel-body,
.panel > .table-responsive + .panel-body {
border-top: 1px solid #ddd;
}
.panel > .table > tbody:first-child > tr:first-child th,
@ -5183,7 +5306,8 @@ a.list-group-item-danger.active:focus {
.panel-group .panel-heading {
border-bottom: 0;
}
.panel-group .panel-heading + .panel-collapse > .panel-body {
.panel-group .panel-heading + .panel-collapse > .panel-body,
.panel-group .panel-heading + .panel-collapse > .list-group {
border-top: 1px solid #ddd;
}
.panel-group .panel-footer {
@ -5310,7 +5434,8 @@ a.list-group-item-danger.active:focus {
.embed-responsive .embed-responsive-item,
.embed-responsive iframe,
.embed-responsive embed,
.embed-responsive object {
.embed-responsive object,
.embed-responsive video {
position: absolute;
top: 0;
bottom: 0;
@ -5381,7 +5506,7 @@ button.close {
right: 0;
bottom: 0;
left: 0;
z-index: 1050;
z-index: 1040;
display: none;
overflow: hidden;
-webkit-overflow-scrolling: touch;
@ -5391,14 +5516,16 @@ button.close {
-webkit-transition: -webkit-transform .3s ease-out;
-o-transition: -o-transform .3s ease-out;
transition: transform .3s ease-out;
-webkit-transform: translate3d(0, -25%, 0);
-o-transform: translate3d(0, -25%, 0);
transform: translate3d(0, -25%, 0);
-webkit-transform: translate(0, -25%);
-ms-transform: translate(0, -25%);
-o-transform: translate(0, -25%);
transform: translate(0, -25%);
}
.modal.in .modal-dialog {
-webkit-transform: translate3d(0, 0, 0);
-o-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
-webkit-transform: translate(0, 0);
-ms-transform: translate(0, 0);
-o-transform: translate(0, 0);
transform: translate(0, 0);
}
.modal-open .modal {
overflow-x: hidden;
@ -5427,7 +5554,6 @@ button.close {
right: 0;
bottom: 0;
left: 0;
z-index: 1040;
background-color: #000;
}
.modal-backdrop.fade {
@ -5600,6 +5726,9 @@ button.close {
display: none;
max-width: 276px;
padding: 1px;
font-size: 14px;
font-weight: normal;
line-height: 1.42857143;
text-align: left;
white-space: normal;
background-color: #fff;
@ -5627,8 +5756,6 @@ button.close {
padding: 8px 14px;
margin: 0;
font-size: 14px;
font-weight: normal;
line-height: 18px;
background-color: #f7f7f7;
border-bottom: 1px solid #ebebeb;
border-radius: 5px 5px 0 0;
@ -5731,6 +5858,37 @@ button.close {
.carousel-inner > .item > a > img {
line-height: 1;
}
@media all and (transform-3d), (-webkit-transform-3d) {
.carousel-inner > .item {
-webkit-transition: -webkit-transform .6s ease-in-out;
-o-transition: -o-transform .6s ease-in-out;
transition: transform .6s ease-in-out;
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
-webkit-perspective: 1000;
perspective: 1000;
}
.carousel-inner > .item.next,
.carousel-inner > .item.active.right {
left: 0;
-webkit-transform: translate3d(100%, 0, 0);
transform: translate3d(100%, 0, 0);
}
.carousel-inner > .item.prev,
.carousel-inner > .item.active.left {
left: 0;
-webkit-transform: translate3d(-100%, 0, 0);
transform: translate3d(-100%, 0, 0);
}
.carousel-inner > .item.next.left,
.carousel-inner > .item.prev.right,
.carousel-inner > .item.active {
left: 0;
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
}
.carousel-inner > .active,
.carousel-inner > .next,
.carousel-inner > .prev {
@ -5986,9 +6144,6 @@ button.close {
}
.affix {
position: fixed;
-webkit-transform: translate3d(0, 0, 0);
-o-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
@-ms-viewport {
width: device-width;

View file

@ -187,3 +187,8 @@
.center {
text-align: center;
}
.login-btn {
margin-left: 10px;
margin-top: 5px;
}

View file

@ -4,7 +4,7 @@
<meta charset="utf-8">
<title>{{ name }}</title>
<link rel="icon" type="image/ico" href="{{ baseUrl }}/-/static/favicon.ico"/>
<link rel="icon" type="image/ico" href="{{ baseUrl }}/-/static/favicon.png"/>
<link rel="stylesheet" type="text/css" href="{{ baseUrl }}/-/static/main.css">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
@ -15,6 +15,19 @@
<div class="npm-logo navbar-left">
<a href="{{ baseUrl }}"></a>
</div>
<div class="navbar-left login-btn">
{{#if username}}
You're {{username}}
<br>
<form action="{{ baseUrl }}/-/logout" method="post">
<a class="submit white no-bg" href="#">Logout</a>
</form>
{{else}}
&nbsp;
<br>
<a class="white no-bg" data-toggle="modal" data-target="#login-form" href="#">Login</a>
{{/if}}
</div>
<div class="navbar-right setup hidden-xs">
<code class="white no-bg">npm set registry {{ baseUrl }}</code><br>
@ -50,15 +63,42 @@
{{/each}}
{{#unless packages.length}}
<div class='no-results'>
<big>No Packages</big><br>
Use <code>npm publish</code>
</div>
<div class='no-results'>
<big>No Packages</big><br>
Use <code>npm publish</code>
</div>
{{/unless}}
</section>
<section class="content container pkg-search-container" id="search-results"></section>
<div class="modal fade" id="login-form" tabindex="-1" role="dialog" aria-labelledby="login-form-label" aria-hidden="true">
<div class="modal-dialog modal-sm">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
<h5 class="modal-title" id="login-form-label">Welcome back</h5>
</div>
<form role="form" action="{{ baseUrl }}/-/login" method="post" id="login-form" autocomplete="off">
<div class="modal-body">
<div class="form-group">
<label for="user" class="sr-only">Email</label>
<input name="user" id="user" class="form-control" placeholder="Username" type="text">
</div>
<div class="form-group">
<label for="pass" class="sr-only">Password</label>
<input name="pass" id="pass" class="form-control" placeholder="Password" type="password">
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="submit" class="btn btn-primary">Log in</button>
</div>
</form>
</div>
</div>
</div>
<script src="{{ baseUrl }}/-/static/jquery.min.js"></script>
<script type='text/javascript' src='{{ baseUrl }}/-/static/main.js'></script>
</body>

281
lib/GUI/js/bootstrap-modal.js vendored Normal file
View file

@ -0,0 +1,281 @@
/* ========================================================================
* Bootstrap: modal.js v3.3.0
* http://getbootstrap.com/javascript/#modals
* ========================================================================
* Copyright 2011-2014 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* ======================================================================== */
+function ($) {
'use strict';
// MODAL CLASS DEFINITION
// ======================
var Modal = function (element, options) {
this.options = options
this.$body = $(document.body)
this.$element = $(element)
this.$backdrop =
this.isShown = null
this.scrollbarWidth = 0
if (this.options.remote) {
this.$element
.find('.modal-content')
.load(this.options.remote, $.proxy(function () {
this.$element.trigger('loaded.bs.modal')
}, this))
}
}
Modal.VERSION = '3.3.0'
Modal.TRANSITION_DURATION = 300
Modal.BACKDROP_TRANSITION_DURATION = 150
Modal.DEFAULTS = {
backdrop: true,
keyboard: true,
show: true
}
Modal.prototype.toggle = function (_relatedTarget) {
return this.isShown ? this.hide() : this.show(_relatedTarget)
}
Modal.prototype.show = function (_relatedTarget) {
var that = this
var e = $.Event('show.bs.modal', { relatedTarget: _relatedTarget })
this.$element.trigger(e)
if (this.isShown || e.isDefaultPrevented()) return
this.isShown = true
this.checkScrollbar()
this.$body.addClass('modal-open')
this.setScrollbar()
this.escape()
this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this))
this.backdrop(function () {
var transition = $.support.transition && that.$element.hasClass('fade')
if (!that.$element.parent().length) {
that.$element.appendTo(that.$body) // don't move modals dom position
}
that.$element
.show()
.scrollTop(0)
if (transition) {
that.$element[0].offsetWidth // force reflow
}
that.$element
.addClass('in')
.attr('aria-hidden', false)
that.enforceFocus()
var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget })
transition ?
that.$element.find('.modal-dialog') // wait for modal to slide in
.one('bsTransitionEnd', function () {
that.$element.trigger('focus').trigger(e)
})
.emulateTransitionEnd(Modal.TRANSITION_DURATION) :
that.$element.trigger('focus').trigger(e)
})
}
Modal.prototype.hide = function (e) {
if (e) e.preventDefault()
e = $.Event('hide.bs.modal')
this.$element.trigger(e)
if (!this.isShown || e.isDefaultPrevented()) return
this.isShown = false
this.escape()
$(document).off('focusin.bs.modal')
this.$element
.removeClass('in')
.attr('aria-hidden', true)
.off('click.dismiss.bs.modal')
$.support.transition && this.$element.hasClass('fade') ?
this.$element
.one('bsTransitionEnd', $.proxy(this.hideModal, this))
.emulateTransitionEnd(Modal.TRANSITION_DURATION) :
this.hideModal()
}
Modal.prototype.enforceFocus = function () {
$(document)
.off('focusin.bs.modal') // guard against infinite focus loop
.on('focusin.bs.modal', $.proxy(function (e) {
if (this.$element[0] !== e.target && !this.$element.has(e.target).length) {
this.$element.trigger('focus')
}
}, this))
}
Modal.prototype.escape = function () {
if (this.isShown && this.options.keyboard) {
this.$element.on('keydown.dismiss.bs.modal', $.proxy(function (e) {
e.which == 27 && this.hide()
}, this))
} else if (!this.isShown) {
this.$element.off('keydown.dismiss.bs.modal')
}
}
Modal.prototype.hideModal = function () {
var that = this
this.$element.hide()
this.backdrop(function () {
that.$body.removeClass('modal-open')
that.resetScrollbar()
that.$element.trigger('hidden.bs.modal')
})
}
Modal.prototype.removeBackdrop = function () {
this.$backdrop && this.$backdrop.remove()
this.$backdrop = null
}
Modal.prototype.backdrop = function (callback) {
var that = this
var animate = this.$element.hasClass('fade') ? 'fade' : ''
if (this.isShown && this.options.backdrop) {
var doAnimate = $.support.transition && animate
this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />')
.prependTo(this.$element)
.on('click.dismiss.bs.modal', $.proxy(function (e) {
if (e.target !== e.currentTarget) return
this.options.backdrop == 'static'
? this.$element[0].focus.call(this.$element[0])
: this.hide.call(this)
}, this))
if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
this.$backdrop.addClass('in')
if (!callback) return
doAnimate ?
this.$backdrop
.one('bsTransitionEnd', callback)
.emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
callback()
} else if (!this.isShown && this.$backdrop) {
this.$backdrop.removeClass('in')
var callbackRemove = function () {
that.removeBackdrop()
callback && callback()
}
$.support.transition && this.$element.hasClass('fade') ?
this.$backdrop
.one('bsTransitionEnd', callbackRemove)
.emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
callbackRemove()
} else if (callback) {
callback()
}
}
Modal.prototype.checkScrollbar = function () {
this.scrollbarWidth = this.measureScrollbar()
}
Modal.prototype.setScrollbar = function () {
var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10)
if (this.scrollbarWidth) this.$body.css('padding-right', bodyPad + this.scrollbarWidth)
}
Modal.prototype.resetScrollbar = function () {
this.$body.css('padding-right', '')
}
Modal.prototype.measureScrollbar = function () { // thx walsh
if (document.body.clientWidth >= window.innerWidth) return 0
var scrollDiv = document.createElement('div')
scrollDiv.className = 'modal-scrollbar-measure'
this.$body.append(scrollDiv)
var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth
this.$body[0].removeChild(scrollDiv)
return scrollbarWidth
}
// MODAL PLUGIN DEFINITION
// =======================
function Plugin(option, _relatedTarget) {
return this.each(function () {
var $this = $(this)
var data = $this.data('bs.modal')
var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option)
if (!data) $this.data('bs.modal', (data = new Modal(this, options)))
if (typeof option == 'string') data[option](_relatedTarget)
else if (options.show) data.show(_relatedTarget)
})
}
var old = $.fn.modal
$.fn.modal = Plugin
$.fn.modal.Constructor = Modal
// MODAL NO CONFLICT
// =================
$.fn.modal.noConflict = function () {
$.fn.modal = old
return this
}
// MODAL DATA-API
// ==============
$(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) {
var $this = $(this)
var href = $this.attr('href')
var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) // strip for ie7
var option = $target.data('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data())
if ($this.is('a')) e.preventDefault()
$target.one('show.bs.modal', function (showEvent) {
if (showEvent.isDefaultPrevented()) return // only register focus restorer if modal will actually get shown
$target.one('hidden.bs.modal', function () {
$this.is(':visible') && $this.trigger('focus')
})
})
Plugin.call($target, option, this)
})
}(jQuery);

View file

@ -1,2 +1,12 @@
require('./search');
require('./entry');
// twitter bootstrap stuff;
// not in static 'cause I want it to be bundled with the rest of javascripts
require('./bootstrap-modal')
// our own files
require('./search')
require('./entry')
$(document).on('click', 'a.submit', function() {
$(this).parent('form').submit()
return false
})

View file

@ -115,7 +115,7 @@ Auth.prototype.add_user = function(user, password, cb) {
}()
}
Auth.prototype.middleware = function() {
Auth.prototype.auth_middleware = function() {
var self = this
return function(req, res, _next) {
req.pause()
@ -130,7 +130,7 @@ Auth.prototype.middleware = function() {
return _next()
}
if (req.remote_user != null) return next()
if (req.remote_user != null && req.remote_user.name !== undefined) return next()
req.remote_user = AnonymousUser()
var authorization = req.headers.authorization
@ -167,6 +167,39 @@ Auth.prototype.middleware = function() {
}
}
Auth.prototype.cookie_middleware = function() {
var self = this
return function(req, res, _next) {
req.pause()
function next(err) {
req.resume()
return _next()
}
if (req.remote_user != null && req.remote_user.name !== undefined) return next()
req.remote_user = AnonymousUser()
var cookie = req.cookies.get('token')
if (cookie == null) return next()
var credentials = new Buffer(cookie, 'base64').toString()
var index = credentials.indexOf(':')
var user = credentials.slice(0, index)
var pass = credentials.slice(index + 1)
self.authenticate(user, pass, function(err, groups) {
if (!err && groups != null && groups != false) {
req.remote_user = AuthenticatedUser(user, groups)
next()
} else {
req.remote_user = AnonymousUser()
next(err)
}
})
}
}
function AnonymousUser() {
return {
name: undefined,

View file

@ -3,21 +3,35 @@ var marked = require('marked')
var search = require('./search')
var Handlebars = require('handlebars')
var Error = require('http-errors')
var express = require('express')
var Cookies = require('cookies')
module.exports = function(config, auth, storage) {
var app = express()
app.use(Cookies.express())
app.use(express.urlencoded())
app.use(auth.cookie_middleware())
app.use(function(req, res, next) {
// disable loading in frames (clickjacking, etc.)
res.header('X-Frame-Options', 'deny')
next()
})
module.exports = function(app, config, storage) {
search.configureStorage(storage)
Handlebars.registerPartial('entry', fs.readFileSync(require.resolve('./GUI/entry.hbs'), 'utf8'));
var template = Handlebars.compile(fs.readFileSync(require.resolve('./GUI/index.hbs'), 'utf8'));
app.get('/', function(req, res, next) {
var base = config.url_prefix || req.protocol + '://' + req.get('host')
res.setHeader('Content-Type', 'text/html');
storage.get_local(function(err, packages) {
res.send(template({
name: config.web.title || "Sinopia",
packages: packages,
baseUrl: config.url_prefix || req.protocol + '://' + req.get('host')
baseUrl: base,
username: req.remote_user.name,
}));
});
});
@ -43,6 +57,18 @@ module.exports = function(app, config, storage) {
res.sendfile(config.web.logosm ? config.web.logosm : __dirname + "/static/logo-sm.png")
})
app.post('/-/login', function(req, res, next) {
var base = config.url_prefix || req.protocol + '://' + req.get('host')
res.cookies.set('token', Buffer(req.body.user + ':' + req.body.pass).toString('base64'))
res.redirect(base)
})
app.post('/-/logout', function(req, res, next) {
var base = config.url_prefix || req.protocol + '://' + req.get('host')
res.cookies.set('token', '')
res.redirect(base)
})
// Search
app.get('/-/search/:anything', function(req, res, next) {
var results = search.query(req.params.anything),
@ -82,4 +108,5 @@ module.exports = function(app, config, storage) {
res.send(marked(info.readme || 'ERROR: No README data found!'))
})
})
return app
}

View file

@ -84,7 +84,7 @@ module.exports = function(config_hash) {
next()
})
app.use(Cats.middleware)
app.use(auth.middleware())
app.use(auth.auth_middleware())
app.use(express.json({strict: false, limit: config.max_body_size || '10mb'}))
app.use(express.compress())
app.use(Middleware.anti_loop(config))
@ -421,12 +421,10 @@ module.exports = function(config_hash) {
})
if (config.web && config.web.enable) {
require('./index-web')(app, config, storage)
app.use(require('./index-web')(config, auth, storage))
} else {
app.get('/', function(req, res) {
res.send('Web interface is a work-in-progress right now, '
+ 'so it is disabled by default. If you want to play with it, '
+ 'you can enable it in the config file.')
res.send('Web interface is disabled in the config file')
})
}

BIN
lib/static/favicon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 315 B

File diff suppressed because one or more lines are too long

View file

@ -30,7 +30,290 @@ helpers = this.merge(helpers, Handlebars.helpers); data = data || {};
+ "</p>\n </div>\n </div>\n</div>\n";
return buffer;
});
},{"handlebars/runtime":11}],2:[function(require,module,exports){
},{"handlebars/runtime":12}],2:[function(require,module,exports){
/* ========================================================================
* Bootstrap: modal.js v3.3.0
* http://getbootstrap.com/javascript/#modals
* ========================================================================
* Copyright 2011-2014 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* ======================================================================== */
+function ($) {
'use strict';
// MODAL CLASS DEFINITION
// ======================
var Modal = function (element, options) {
this.options = options
this.$body = $(document.body)
this.$element = $(element)
this.$backdrop =
this.isShown = null
this.scrollbarWidth = 0
if (this.options.remote) {
this.$element
.find('.modal-content')
.load(this.options.remote, $.proxy(function () {
this.$element.trigger('loaded.bs.modal')
}, this))
}
}
Modal.VERSION = '3.3.0'
Modal.TRANSITION_DURATION = 300
Modal.BACKDROP_TRANSITION_DURATION = 150
Modal.DEFAULTS = {
backdrop: true,
keyboard: true,
show: true
}
Modal.prototype.toggle = function (_relatedTarget) {
return this.isShown ? this.hide() : this.show(_relatedTarget)
}
Modal.prototype.show = function (_relatedTarget) {
var that = this
var e = $.Event('show.bs.modal', { relatedTarget: _relatedTarget })
this.$element.trigger(e)
if (this.isShown || e.isDefaultPrevented()) return
this.isShown = true
this.checkScrollbar()
this.$body.addClass('modal-open')
this.setScrollbar()
this.escape()
this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this))
this.backdrop(function () {
var transition = $.support.transition && that.$element.hasClass('fade')
if (!that.$element.parent().length) {
that.$element.appendTo(that.$body) // don't move modals dom position
}
that.$element
.show()
.scrollTop(0)
if (transition) {
that.$element[0].offsetWidth // force reflow
}
that.$element
.addClass('in')
.attr('aria-hidden', false)
that.enforceFocus()
var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget })
transition ?
that.$element.find('.modal-dialog') // wait for modal to slide in
.one('bsTransitionEnd', function () {
that.$element.trigger('focus').trigger(e)
})
.emulateTransitionEnd(Modal.TRANSITION_DURATION) :
that.$element.trigger('focus').trigger(e)
})
}
Modal.prototype.hide = function (e) {
if (e) e.preventDefault()
e = $.Event('hide.bs.modal')
this.$element.trigger(e)
if (!this.isShown || e.isDefaultPrevented()) return
this.isShown = false
this.escape()
$(document).off('focusin.bs.modal')
this.$element
.removeClass('in')
.attr('aria-hidden', true)
.off('click.dismiss.bs.modal')
$.support.transition && this.$element.hasClass('fade') ?
this.$element
.one('bsTransitionEnd', $.proxy(this.hideModal, this))
.emulateTransitionEnd(Modal.TRANSITION_DURATION) :
this.hideModal()
}
Modal.prototype.enforceFocus = function () {
$(document)
.off('focusin.bs.modal') // guard against infinite focus loop
.on('focusin.bs.modal', $.proxy(function (e) {
if (this.$element[0] !== e.target && !this.$element.has(e.target).length) {
this.$element.trigger('focus')
}
}, this))
}
Modal.prototype.escape = function () {
if (this.isShown && this.options.keyboard) {
this.$element.on('keydown.dismiss.bs.modal', $.proxy(function (e) {
e.which == 27 && this.hide()
}, this))
} else if (!this.isShown) {
this.$element.off('keydown.dismiss.bs.modal')
}
}
Modal.prototype.hideModal = function () {
var that = this
this.$element.hide()
this.backdrop(function () {
that.$body.removeClass('modal-open')
that.resetScrollbar()
that.$element.trigger('hidden.bs.modal')
})
}
Modal.prototype.removeBackdrop = function () {
this.$backdrop && this.$backdrop.remove()
this.$backdrop = null
}
Modal.prototype.backdrop = function (callback) {
var that = this
var animate = this.$element.hasClass('fade') ? 'fade' : ''
if (this.isShown && this.options.backdrop) {
var doAnimate = $.support.transition && animate
this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />')
.prependTo(this.$element)
.on('click.dismiss.bs.modal', $.proxy(function (e) {
if (e.target !== e.currentTarget) return
this.options.backdrop == 'static'
? this.$element[0].focus.call(this.$element[0])
: this.hide.call(this)
}, this))
if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
this.$backdrop.addClass('in')
if (!callback) return
doAnimate ?
this.$backdrop
.one('bsTransitionEnd', callback)
.emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
callback()
} else if (!this.isShown && this.$backdrop) {
this.$backdrop.removeClass('in')
var callbackRemove = function () {
that.removeBackdrop()
callback && callback()
}
$.support.transition && this.$element.hasClass('fade') ?
this.$backdrop
.one('bsTransitionEnd', callbackRemove)
.emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
callbackRemove()
} else if (callback) {
callback()
}
}
Modal.prototype.checkScrollbar = function () {
this.scrollbarWidth = this.measureScrollbar()
}
Modal.prototype.setScrollbar = function () {
var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10)
if (this.scrollbarWidth) this.$body.css('padding-right', bodyPad + this.scrollbarWidth)
}
Modal.prototype.resetScrollbar = function () {
this.$body.css('padding-right', '')
}
Modal.prototype.measureScrollbar = function () { // thx walsh
if (document.body.clientWidth >= window.innerWidth) return 0
var scrollDiv = document.createElement('div')
scrollDiv.className = 'modal-scrollbar-measure'
this.$body.append(scrollDiv)
var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth
this.$body[0].removeChild(scrollDiv)
return scrollbarWidth
}
// MODAL PLUGIN DEFINITION
// =======================
function Plugin(option, _relatedTarget) {
return this.each(function () {
var $this = $(this)
var data = $this.data('bs.modal')
var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option)
if (!data) $this.data('bs.modal', (data = new Modal(this, options)))
if (typeof option == 'string') data[option](_relatedTarget)
else if (options.show) data.show(_relatedTarget)
})
}
var old = $.fn.modal
$.fn.modal = Plugin
$.fn.modal.Constructor = Modal
// MODAL NO CONFLICT
// =================
$.fn.modal.noConflict = function () {
$.fn.modal = old
return this
}
// MODAL DATA-API
// ==============
$(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) {
var $this = $(this)
var href = $this.attr('href')
var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) // strip for ie7
var option = $target.data('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data())
if ($this.is('a')) e.preventDefault()
$target.one('show.bs.modal', function (showEvent) {
if (showEvent.isDefaultPrevented()) return // only register focus restorer if modal will actually get shown
$target.one('hidden.bs.modal', function () {
$this.is(':visible') && $this.trigger('focus')
})
})
Plugin.call($target, option, this)
})
}(jQuery);
},{}],3:[function(require,module,exports){
var $ = require('unopinionate').selector,
onClick = require('onclick'),
transitionComplete = require('transition-complete');
@ -103,11 +386,21 @@ $(function() {
});
});
},{"onclick":12,"transition-complete":14,"unopinionate":15}],3:[function(require,module,exports){
require('./search');
require('./entry');
},{"onclick":13,"transition-complete":15,"unopinionate":16}],4:[function(require,module,exports){
// twitter bootstrap stuff;
// not in static 'cause I want it to be bundled with the rest of javascripts
require('./bootstrap-modal')
},{"./entry":2,"./search":4}],4:[function(require,module,exports){
// our own files
require('./search')
require('./entry')
$(document).on('click', 'a.submit', function() {
$(this).parent('form').submit()
return false
})
},{"./bootstrap-modal":2,"./entry":3,"./search":5}],5:[function(require,module,exports){
var $ = require('unopinionate').selector,
template = require('../entry.hbs'),
onScroll = require('onscroll');
@ -190,7 +483,7 @@ $(function() {
})( window, window.document );
});
},{"../entry.hbs":1,"onscroll":13,"unopinionate":15}],5:[function(require,module,exports){
},{"../entry.hbs":1,"onscroll":14,"unopinionate":16}],6:[function(require,module,exports){
"use strict";
/*globals Handlebars: true */
var base = require("./handlebars/base");
@ -223,7 +516,7 @@ var Handlebars = create();
Handlebars.create = create;
exports["default"] = Handlebars;
},{"./handlebars/base":6,"./handlebars/exception":7,"./handlebars/runtime":8,"./handlebars/safe-string":9,"./handlebars/utils":10}],6:[function(require,module,exports){
},{"./handlebars/base":7,"./handlebars/exception":8,"./handlebars/runtime":9,"./handlebars/safe-string":10,"./handlebars/utils":11}],7:[function(require,module,exports){
"use strict";
var Utils = require("./utils");
var Exception = require("./exception")["default"];
@ -404,7 +697,7 @@ exports.log = log;var createFrame = function(object) {
return obj;
};
exports.createFrame = createFrame;
},{"./exception":7,"./utils":10}],7:[function(require,module,exports){
},{"./exception":8,"./utils":11}],8:[function(require,module,exports){
"use strict";
var errorProps = ['description', 'fileName', 'lineNumber', 'message', 'name', 'number', 'stack'];
@ -433,7 +726,7 @@ function Exception(message, node) {
Exception.prototype = new Error();
exports["default"] = Exception;
},{}],8:[function(require,module,exports){
},{}],9:[function(require,module,exports){
"use strict";
var Utils = require("./utils");
var Exception = require("./exception")["default"];
@ -571,7 +864,7 @@ exports.program = program;function invokePartial(partial, name, context, helpers
exports.invokePartial = invokePartial;function noop() { return ""; }
exports.noop = noop;
},{"./base":6,"./exception":7,"./utils":10}],9:[function(require,module,exports){
},{"./base":7,"./exception":8,"./utils":11}],10:[function(require,module,exports){
"use strict";
// Build out our basic SafeString type
function SafeString(string) {
@ -583,7 +876,7 @@ SafeString.prototype.toString = function() {
};
exports["default"] = SafeString;
},{}],10:[function(require,module,exports){
},{}],11:[function(require,module,exports){
"use strict";
/*jshint -W004 */
var SafeString = require("./safe-string")["default"];
@ -660,12 +953,12 @@ exports.escapeExpression = escapeExpression;function isEmpty(value) {
}
exports.isEmpty = isEmpty;
},{"./safe-string":9}],11:[function(require,module,exports){
},{"./safe-string":10}],12:[function(require,module,exports){
// Create a simple path alias to allow browserify to resolve
// the runtime on a supported path.
module.exports = require('./dist/cjs/handlebars.runtime');
},{"./dist/cjs/handlebars.runtime":5}],12:[function(require,module,exports){
},{"./dist/cjs/handlebars.runtime":6}],13:[function(require,module,exports){
var $ = require('unopinionate').selector;
var $document = $(document),
@ -830,7 +1123,7 @@ $(document).bind('mousedown', click._doAnywheres);
module.exports = click;
},{"unopinionate":15}],13:[function(require,module,exports){
},{"unopinionate":16}],14:[function(require,module,exports){
var $ = require('unopinionate').selector;
var bodyScrollers = [];
@ -853,7 +1146,7 @@ var onScroll = function(callback) {
};
module.exports = onScroll;
},{"unopinionate":15}],14:[function(require,module,exports){
},{"unopinionate":16}],15:[function(require,module,exports){
(function(root) {
var callbacks = [];
@ -917,7 +1210,7 @@ module.exports = onScroll;
}
})(this);
},{}],15:[function(require,module,exports){
},{}],16:[function(require,module,exports){
(function (global){
(function(root) {
var unopinionate = {
@ -944,4 +1237,4 @@ module.exports = onScroll;
})(typeof window != 'undefined' ? window : global);
}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{}]},{},[3]);
},{}]},{},[4]);