add
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
**.DS_Store
|
||||
.jekyll*
|
||||
_site
|
520
css/terminal.css
Normal file
@ -0,0 +1,520 @@
|
||||
html {
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-font-smoothing: antialiased;
|
||||
-ms-font-smoothing: antialiased;
|
||||
-o-font-smoothing: antialiased;
|
||||
}
|
||||
body {
|
||||
background-attachment: fixed;
|
||||
-webkit-background-size: cover;
|
||||
background-size: cover;
|
||||
color: #444;
|
||||
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
}
|
||||
|
||||
#window {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
background: #343434;
|
||||
border-radius: 7px;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
height: 400px;
|
||||
}
|
||||
|
||||
#topbar {
|
||||
width: 100%;
|
||||
height: 21px;
|
||||
font-size: 16px;
|
||||
font-family: "Myriad Pro", sans-serif;
|
||||
text-shadow: 0px 1px 0px rgba(255, 255, 255, 0.25);
|
||||
-webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.5);
|
||||
-moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
#topbar ul li {
|
||||
float: left;
|
||||
padding: 0 10px;
|
||||
height: 21px;
|
||||
line-height: 24px;
|
||||
}
|
||||
#topbar ul li:first-child {
|
||||
font-size: 20px;
|
||||
line-height: 26px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
#topbar ul li:nth-child(2) {
|
||||
font-family: "Myriad-Semi", sans-serif;
|
||||
}
|
||||
#topbar ul li:active {
|
||||
background-image: -webkit-gradient(linear, left bottom, left top, color-stop(1, #4a82ff), color-stop(0, #0052fc));
|
||||
color: #fff;
|
||||
text-shadow: none;
|
||||
}
|
||||
#toolbar {
|
||||
width: 100%;
|
||||
height: 25px;
|
||||
background: #ccc;
|
||||
}
|
||||
#toolbar .top {
|
||||
float: left;
|
||||
width: 100%;
|
||||
height: 23px;
|
||||
}
|
||||
#toolbar .bottom {
|
||||
float: left;
|
||||
width: 100%;
|
||||
height: 30px;
|
||||
}
|
||||
#toolbar #lights {
|
||||
float: left;
|
||||
position: relative;
|
||||
top: 6px;
|
||||
left: 7px;
|
||||
}
|
||||
.light {
|
||||
float: left;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
border-radius: 14px;
|
||||
-webkit-box-shadow: 0px 1px 0px rgba(255, 255, 255, 0.5), 0px 0px 3px #000 inset;
|
||||
-moz-box-shadow: 0px 1px 0px rgba(255, 255, 255, 0.5), 0px 0px 3px #000 inset;
|
||||
box-shadow: 0px 1px 0px rgba(255, 255, 255, 0.5), 0px 0px 3px #000 inset;
|
||||
overflow: hidden;
|
||||
}
|
||||
#lights:hover .glyph {
|
||||
opacity: 1;
|
||||
cursor: default;
|
||||
}
|
||||
.light .shine {
|
||||
width: 4px;
|
||||
height: 3px;
|
||||
border-radius: 10px;
|
||||
background: -moz-radial-gradient(center, ellipse cover, rgba(255, 255, 255, 1) 0%, rgba(255, 255, 255, 0) 100%);
|
||||
background-image: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%, rgba(255, 255, 255, 1)), color-stop(100%, rgba(255, 255, 255, 0)));
|
||||
background: -webkit-radial-gradient(center, ellipse cover, rgba(255, 255, 255, 1) 0%, rgba(255, 255, 255, 0) 100%);
|
||||
background: -o-radial-gradient(center, ellipse cover, rgba(255, 255, 255, 1) 0%, rgba(255, 255, 255, 0) 100%);
|
||||
background: -ms-radial-gradient(center, ellipse cover, rgba(255, 255, 255, 1) 0%, rgba(255, 255, 255, 0) 100%);
|
||||
background: radial-gradient(center, ellipse cover, rgba(255, 255, 255, 1) 0%, rgba(255, 255, 255, 0) 100%);
|
||||
}
|
||||
.light .glow {
|
||||
width: 14px;
|
||||
height: 8px;
|
||||
background-image: -webkit-gradient(radial, center bottom, 0, center center, 5, from(rgba(255, 255, 255, 0.75)), to(rgba(255, 255, 255, 0)));
|
||||
background: 0px 0px -moz-radial-gradient(bottom, cover, rgba(255, 255, 255, 0.70) 0%, rgba(255, 255, 255, 0) 80%);
|
||||
}
|
||||
.red {
|
||||
background: #f41b16;
|
||||
background: -moz-linear-gradient(top, #f41b16 0%, #fc7471 100%);
|
||||
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #f41b16), color-stop(100%, #fc7471));
|
||||
background: -webkit-linear-gradient(top, #f41b16 0%, #fc7471 100%);
|
||||
background: -o-linear-gradient(top, #f41b16 0%, #fc7471 100%);
|
||||
background: -ms-linear-gradient(top, #f41b16 0%, #fc7471 100%);
|
||||
background: linear-gradient(top, #f41b16 0%, #fc7471 100%);
|
||||
}
|
||||
.red:active {
|
||||
background: #972f2e;
|
||||
background: -moz-linear-gradient(top, #972f2e 0%, #fc7471 100%);
|
||||
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #972f2e), color-stop(100%, #fc7471));
|
||||
background: -webkit-linear-gradient(top, #972f2e 0%, #fc7471 100%);
|
||||
background: -o-linear-gradient(top, #972f2e 0%, #fc7471 100%);
|
||||
background: -ms-linear-gradient(top, #972f2e 0%, #fc7471 100%);
|
||||
background: linear-gradient(top, #972f2e 0%, #fc7471 100%);
|
||||
}
|
||||
.red .shine {
|
||||
position: relative;
|
||||
top: -21px;
|
||||
left: 5px;
|
||||
}
|
||||
.red .glow {
|
||||
position: relative;
|
||||
top: -20px;
|
||||
}
|
||||
.red .glyph {
|
||||
position: relative;
|
||||
top: -5px;
|
||||
left: 3px;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: #9b3a36;
|
||||
z-index: 50;
|
||||
opacity: 0;
|
||||
}
|
||||
.yellow {
|
||||
background: #f4a316;
|
||||
background: -moz-linear-gradient(left, #f4a316 0%, #fcc371 100%);
|
||||
background: -webkit-gradient(linear, left top, right top, color-stop(0%, #f4a316), color-stop(100%, #fcc371));
|
||||
background: -webkit-linear-gradient(left, #f4a316 0%, #fcc371 100%);
|
||||
background: -o-linear-gradient(left, #f4a316 0%, #fcc371 100%);
|
||||
background: -ms-linear-gradient(left, #f4a316 0%, #fcc371 100%);
|
||||
background: linear-gradient(left, #f4a316 0%, #fcc371 100%);
|
||||
margin: 0px 7px;
|
||||
}
|
||||
.yellow:active {
|
||||
background: #ae4f1e;
|
||||
background: -moz-linear-gradient(top, #ae4f1e 0%, #fcc371 100%);
|
||||
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #ae4f1e), color-stop(100%, #fcc371));
|
||||
background: -webkit-linear-gradient(top, #ae4f1e 0%, #fcc371 100%);
|
||||
background: -o-linear-gradient(top, #ae4f1e 0%, #fcc371 100%);
|
||||
background: -ms-linear-gradient(top, #ae4f1e 0%, #fcc371 100%);
|
||||
background: linear-gradient(top, #ae4f1e 0%, #fcc371 100%);
|
||||
}
|
||||
.yellow .shine {
|
||||
position: relative;
|
||||
top: -21px;
|
||||
left: 5px;
|
||||
}
|
||||
.yellow .glow {
|
||||
position: relative;
|
||||
top: -20px;
|
||||
}
|
||||
.yellow .glyph {
|
||||
position: relative;
|
||||
top: -5px;
|
||||
left: 3px;
|
||||
font-size: 24px;
|
||||
color: #854322;
|
||||
z-index: 50;
|
||||
opacity: 0;
|
||||
-webkit-transform: scaleY(1.5) scaleX(1.3);
|
||||
}
|
||||
.green {
|
||||
background: #4cae2e;
|
||||
background: -moz-linear-gradient(top, #4cae2e 0%, #dafc71 100%);
|
||||
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #4cae2e), color-stop(100%, #dafc71));
|
||||
background: -webkit-linear-gradient(top, #4cae2e 0%, #dafc71 100%);
|
||||
background: -o-linear-gradient(top, #4cae2e 0%, #dafc71 100%);
|
||||
background: -ms-linear-gradient(top, #4cae2e 0%, #dafc71 100%);
|
||||
background: linear-gradient(top, #4cae2e 0%, #dafc71 100%);
|
||||
}
|
||||
.green:active {
|
||||
background: #48752b;
|
||||
background: -moz-linear-gradient(top, #48752b 0%, #dafc71 100%);
|
||||
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #48752b), color-stop(100%, #dafc71));
|
||||
background: -webkit-linear-gradient(top, #48752b 0%, #dafc71 100%);
|
||||
background: -o-linear-gradient(top, #48752b 0%, #dafc71 100%);
|
||||
background: -ms-linear-gradient(top, #48752b 0%, #dafc71 100%);
|
||||
background: linear-gradient(top, #48752b 0%, #dafc71 100%);
|
||||
}
|
||||
.green .shine {
|
||||
position: relative;
|
||||
top: -20px;
|
||||
left: 5px;
|
||||
}
|
||||
.green .glow {
|
||||
position: relative;
|
||||
top: -20px;
|
||||
}
|
||||
.green .glyph {
|
||||
position: relative;
|
||||
top: -5px;
|
||||
left: 3px;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
color: #25571d;
|
||||
z-index: 50;
|
||||
opacity: 0;
|
||||
}
|
||||
@-moz-document url-prefix() {
|
||||
.red .glyph {
|
||||
position: relative;
|
||||
top: -5px;
|
||||
}
|
||||
.yellow .glyph {
|
||||
top: -4px;
|
||||
left: 3px;
|
||||
}
|
||||
.green .glyph {
|
||||
position: relative;
|
||||
top: -4px;
|
||||
}
|
||||
}
|
||||
#title {
|
||||
float: left;
|
||||
position: relative;
|
||||
top: 6px;
|
||||
width: 40%;
|
||||
left: 45%;
|
||||
font-family: "Myriad Pro", sans-serif;
|
||||
font-size: 16px;
|
||||
line-height: 14px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.folder {
|
||||
float: left;
|
||||
margin-right: 5px;
|
||||
}
|
||||
.folder .tab {
|
||||
width: 4px;
|
||||
height: 2px;
|
||||
background: #a4c5da;
|
||||
border: 1px solid #728ea3;
|
||||
border-bottom: none;
|
||||
border-radius: 2px 2px 0px 0px;
|
||||
-webkit-box-shadow: 0px -1px 0px #99b5c7 inset;
|
||||
margin-left: 1px;
|
||||
z-index: 5000;
|
||||
margin-bottom: -1px;
|
||||
}
|
||||
.folder .body {
|
||||
width: 14px;
|
||||
height: 10px;
|
||||
border: 1px solid #6e8ba1;
|
||||
background: #b8cfe0;
|
||||
background: -moz-linear-gradient(top, #b8cfe0 0%, #86adc8 100%);
|
||||
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #b8cfe0), color-stop(100%, #86adc8));
|
||||
background: -webkit-linear-gradient(top, #b8cfe0 0%, #86adc8 100%);
|
||||
background: -o-linear-gradient(top, #b8cfe0 0%, #86adc8 100%);
|
||||
background: -ms-linear-gradient(top, #b8cfe0 0%, #86adc8 100%);
|
||||
background: linear-gradient(top, #b8cfe0 0%, #86adc8 100%);
|
||||
z-index: -50;
|
||||
-webkit-box-shadow: 0px 1px 0px rgba(255, 255, 255, 0.25) inset, 0px 1px 0px rgba(0, 0, 0, 0.2);
|
||||
-moz-box-shadow: 0px 1px 0px rgba(255, 255, 255, 0.25) inset, 0px 1px 0px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
#nav {
|
||||
margin: 1px 8px;
|
||||
float: left;
|
||||
}
|
||||
#view {
|
||||
margin: 2px 0 0 110px;
|
||||
display: inline-block;
|
||||
}
|
||||
.control_box {
|
||||
height: 20px;
|
||||
border-radius: 3px;
|
||||
border: 1px solid #555;
|
||||
background-image: -webkit-gradient(linear, left bottom, left top, color-stop(1, #fefefe), color-stop(0, #b8b8b8));
|
||||
box-shadow: 0px 1px 0px rgba(255, 255, 255, 0.25);
|
||||
}
|
||||
.control_box .control {
|
||||
height: 20px;
|
||||
border-right: 1px solid #2e2e2e;
|
||||
float: left;
|
||||
text-align: center;
|
||||
width: 27px;
|
||||
}
|
||||
.control:last-child {
|
||||
border-right: 0px solid !important;
|
||||
}
|
||||
.control:active {
|
||||
background: #b0afb0;
|
||||
-webkit-box-shadow: 0px 0px 4px #000 inset;
|
||||
}
|
||||
.active {
|
||||
background: #707070 !important;
|
||||
-webkit-box-shadow: 0px 3px 4px rgba(0, 0, 0, 0.6) inset !important;
|
||||
}
|
||||
#body {
|
||||
font-family: Andale Mono, monospace;
|
||||
line-height: 1em;
|
||||
font-size: 13px;
|
||||
float: left;
|
||||
width: 100%;
|
||||
background: #002b36;
|
||||
padding: 10px;
|
||||
line-height: 1.5em;
|
||||
}
|
||||
#body p {
|
||||
color: #63de00!important;
|
||||
}
|
||||
@keyframes blink {
|
||||
0% {
|
||||
background: rgba(99, 222, 0, 100);
|
||||
}
|
||||
100% {
|
||||
background: rgba(99, 222, 0, 0);
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes blink {
|
||||
0% {
|
||||
background: rgba(99, 222, 0, 100);
|
||||
}
|
||||
100% {
|
||||
background: rgba(99, 222, 0, 0);
|
||||
}
|
||||
}
|
||||
@-moz-keyframes blink {
|
||||
0% {
|
||||
background: rgba(99, 222, 0, 100);
|
||||
}
|
||||
100% {
|
||||
background: rgba(99, 222, 0, 0);
|
||||
}
|
||||
}
|
||||
.cursor {
|
||||
width: 10px;
|
||||
margin-left: 0px;
|
||||
color: #fff;
|
||||
}
|
||||
#body p::-webkit-selection {
|
||||
background: #0b209e;
|
||||
}
|
||||
#body p::selection {
|
||||
background: #0b209e;
|
||||
}
|
||||
#body p::-moz-selection {
|
||||
background: #0b209e;
|
||||
}
|
||||
#body p {
|
||||
margin-top: 5px;
|
||||
margin-bottom: 5px;
|
||||
font-size: 13px;
|
||||
}
|
||||
#content {
|
||||
float: left;
|
||||
margin-top: 1px;
|
||||
}
|
||||
#foot {
|
||||
height: 23px;
|
||||
width: 100%;
|
||||
float: left;
|
||||
background-image: -webkit-gradient(linear, left bottom, left top, color-stop(1, #cbcbcb), color-stop(0, #a7a7a7));
|
||||
border-top: 1px solid #515151;
|
||||
border-radius: 0 0 5px 5px;
|
||||
}
|
||||
#foot .handle {
|
||||
width: 11px;
|
||||
height: 11px;
|
||||
float: right;
|
||||
margin: 6px;
|
||||
overflow: hidden;
|
||||
}
|
||||
.handle .grip {
|
||||
-webkit-transform: rotate(45deg) scaley(3);
|
||||
margin: 2px 0 0 2px;
|
||||
color: #646464;
|
||||
text-shadow: 1px 1px 0 #c6c6c6;
|
||||
font-size: 14px;
|
||||
}
|
||||
.icon .frame {
|
||||
width: 82px;
|
||||
height: 82px;
|
||||
border-radius: 5px;
|
||||
border: 2px solid transparent;
|
||||
}
|
||||
.icon .name {
|
||||
color: #000;
|
||||
padding-top: 3px;
|
||||
border-radius: 15px;
|
||||
width: 55px;
|
||||
margin: 5px 0 0 15px;
|
||||
}
|
||||
.icon .folder {
|
||||
margin: 15px 0 0 6px;
|
||||
}
|
||||
#icon-github {
|
||||
text-align: -999px;
|
||||
font-size: 1px;
|
||||
display: block;
|
||||
width: 156px;
|
||||
height: 133px;
|
||||
background-image: url(../img/sprite.png);
|
||||
background-position: 0 133px;
|
||||
}
|
||||
#icon-github:hover {
|
||||
background-position: 0 0px;
|
||||
}
|
||||
#icon-rubygems {
|
||||
text-align: -999px;
|
||||
font-size: 1px;
|
||||
display: block;
|
||||
width: 156px;
|
||||
height: 133px;
|
||||
background-image: url(../img/sprite.png);
|
||||
background-position: 158px 133px;
|
||||
}
|
||||
#icon-rubygems:hover {
|
||||
background-position: 158px 0px;
|
||||
}
|
||||
.source-urls {
|
||||
margin-top: 40px;
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
.no-margin-bot {
|
||||
color: #337AB7;
|
||||
}
|
||||
span {
|
||||
font-size: 15px;
|
||||
}
|
||||
#particles-js {
|
||||
position: absolute;
|
||||
width: 98%;
|
||||
}
|
||||
#particles-js-no {
|
||||
position: absolute;
|
||||
width: 98%;
|
||||
}
|
||||
|
||||
#icon-github:hover,
|
||||
i.icon.ion-close-circled:hover,
|
||||
i.icon.ion-minus-circled:hover,
|
||||
i.icon.ion-plus-circled:hover {
|
||||
color: rgba(0, 0, 0, .5);
|
||||
}
|
||||
i.icon.ion-close-circled {
|
||||
color: rgba(212, 42, 38, 0.83);
|
||||
text-shadow: 0 0 1px rgba(187, 187, 187, 0.56);
|
||||
padding-top: 3px;
|
||||
}
|
||||
i.icon.ion-minus-circled {
|
||||
color: rgb(160, 165, 34);
|
||||
text-shadow: 0 0 1px rgba(187, 187, 187, 0.56);
|
||||
padding-top: 3px;
|
||||
}
|
||||
i.icon.ion-plus-circled {
|
||||
color: rgb(82, 183, 51);
|
||||
text-shadow: 0 0 1px rgba(187, 187, 187, 0.56);
|
||||
padding-top: 3px;
|
||||
}
|
||||
.icon {
|
||||
margin: 7px;
|
||||
float: left;
|
||||
font-size: 20px;
|
||||
}
|
||||
#title-left {
|
||||
position: relative;
|
||||
top: -8px;
|
||||
font-family: "Myriad Pro", sans-serif;
|
||||
font-size: 14px;
|
||||
left: 49%;
|
||||
}
|
||||
#terminal-origin {
|
||||
font-family: monospace;
|
||||
}
|
||||
@media all and (-webkit-min-device-pixel-ratio: 0) and (min-resolution: .001dpcm) {
|
||||
#title-left {
|
||||
top: -13px;
|
||||
}
|
||||
}
|
||||
|
||||
home-layout {
|
||||
background-color: #f1f1f1;
|
||||
}
|
||||
|
||||
.terminal, .cmd {
|
||||
background-color: #343434;
|
||||
}
|
||||
|
||||
@media screen and (max-width:1000px){i.icon.ion-minus-circled{display:none}
|
||||
#window{width:100%;}
|
||||
}
|
||||
@media screen and (max-width:800px){body{padding-top:0px;}
|
||||
#title-left{left:50%;}
|
||||
#window{width:100%;}
|
||||
.container{padding:0px;}
|
||||
/*article{padding:10px 20px;}*/
|
||||
i.icon.ion-minus-circled{display:none}
|
||||
}
|
||||
@media screen and (max-width:800px){#title-left{left:48%;}
|
||||
}
|
||||
@media screen and (max-width:500px){#title-left{left:40%;}
|
||||
}
|
||||
@media screen and (max-width:400px){body{padding-top:0px;width:auto;}
|
||||
#title-left{left:50%;}
|
||||
/*article{padding:10px 10px;}*/
|
||||
#particles-js{width:auto;}
|
||||
#particles-js-no{width:auto;}
|
||||
i.icon.ion-minus-circled{display:none}
|
||||
i.icon.ion-plus-circled{display:none}
|
||||
}
|
||||
|
1
css/terminal.mobile.css
Normal file
@ -0,0 +1 @@
|
||||
|
BIN
favicon.ico
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
icon/ai.png
Normal file
After Width: | Height: | Size: 89 KiB |
1882
icon/ai.svg
Normal file
After Width: | Height: | Size: 50 KiB |
BIN
icon/apple-touch-icon.png
Normal file
After Width: | Height: | Size: 89 KiB |
BIN
icon/avatar.png
Normal file
After Width: | Height: | Size: 557 KiB |
BIN
icon/player.png
Normal file
After Width: | Height: | Size: 54 KiB |
79
icon/player.svg
Normal file
@ -0,0 +1,79 @@
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
|
||||
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
||||
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
|
||||
width="645.000000pt" height="645.000000pt" viewBox="0 0 645.000000 645.000000"
|
||||
preserveAspectRatio="xMidYMid meet">
|
||||
|
||||
<g transform="translate(0.000000,645.000000) scale(0.100000,-0.100000)"
|
||||
fill="#000000" stroke="none">
|
||||
<path d="M2926 6399 c-400 -40 -754 -142 -1111 -319 -370 -183 -627 -373 -927
|
||||
-688 -334 -350 -608 -843 -740 -1332 -21 -78 -26 -96 -51 -220 -79 -384 -78
|
||||
-865 2 -1255 194 -948 827 -1772 1698 -2209 291 -145 607 -246 943 -301 122
|
||||
-20 533 -38 670 -30 657 40 1280 281 1805 699 128 101 378 352 482 481 306
|
||||
382 518 817 625 1280 57 249 78 434 78 715 0 315 -24 511 -100 806 -111 432
|
||||
-311 832 -598 1194 -98 123 -370 395 -492 491 -437 345 -923 564 -1457 655
|
||||
-81 14 -184 27 -228 30 -152 10 -510 12 -599 3z m624 -130 c408 -46 840 -185
|
||||
1170 -376 281 -163 463 -303 688 -531 158 -161 350 -411 456 -595 107 -187
|
||||
239 -493 286 -662 95 -343 122 -541 122 -880 -1 -286 -19 -452 -82 -725 -74
|
||||
-321 -246 -710 -441 -995 -496 -726 -1261 -1198 -2134 -1316 -204 -27 -592
|
||||
-27 -790 0 -569 80 -1070 293 -1512 643 -174 138 -366 331 -498 502 -16 22
|
||||
-39 51 -51 65 -71 88 -233 356 -293 486 -82 174 -99 218 -152 378 -107 326
|
||||
-153 616 -153 967 0 324 28 524 124 875 82 304 286 701 507 989 86 112 249
|
||||
291 342 374 47 42 88 79 91 82 20 22 172 139 250 192 380 262 816 437 1260
|
||||
507 36 5 85 13 110 17 67 11 379 21 500 17 58 -2 148 -8 200 -14z"/>
|
||||
<path d="M2685 5968 c-335 -80 -520 -146 -748 -266 -203 -107 -416 -252 -561
|
||||
-381 -115 -101 -291 -289 -363 -387 -91 -123 -121 -168 -186 -276 -119 -200
|
||||
-193 -363 -272 -603 -96 -291 -144 -724 -116 -1050 14 -158 24 -208 53 -247
|
||||
17 -24 26 -28 70 -28 29 0 65 4 82 9 38 12 156 42 281 73 98 23 91 14 -50 -60
|
||||
-134 -70 -236 -130 -302 -177 -20 -14 -23 -25 -23 -83 0 -75 8 -109 52 -232
|
||||
278 -770 926 -1405 1708 -1672 353 -120 734 -174 1067 -149 166 12 205 17 373
|
||||
48 492 90 1002 349 1364 693 277 262 443 485 605 811 133 267 180 426 157 529
|
||||
-12 52 -16 57 -77 98 -35 23 -118 72 -184 108 -66 36 -124 70 -130 76 -13 13
|
||||
49 6 135 -16 36 -9 83 -21 105 -27 22 -6 54 -14 70 -20 17 -5 52 -9 78 -10 50
|
||||
-2 78 18 99 71 35 90 47 471 23 700 -22 205 -37 284 -104 535 -5 17 -22 68
|
||||
-39 115 -95 268 -228 518 -390 735 -279 372 -577 626 -967 825 -234 120 -460
|
||||
200 -706 250 -102 21 -109 21 -163 6 -64 -19 -63 -17 -132 -206 -20 -52 -49
|
||||
-131 -66 -175 -16 -44 -39 -104 -49 -132 -10 -29 -28 -77 -38 -105 -11 -29
|
||||
-41 -113 -68 -187 -26 -74 -53 -136 -59 -138 -6 -2 -22 31 -37 74 -14 43 -40
|
||||
116 -57 163 -18 47 -36 96 -40 110 -5 14 -24 68 -43 120 -155 422 -157 427
|
||||
-217 468 -35 23 -69 26 -135 10z m-630 -2381 c147 -128 374 -251 533 -290 l92
|
||||
-22 0 -111 c0 -257 -69 -594 -184 -895 -73 -194 -68 -186 -137 -194 -59 -7
|
||||
-60 -7 -102 32 -29 27 -56 42 -83 46 -34 6 -52 20 -129 103 -50 53 -102 110
|
||||
-117 127 -16 16 -28 31 -28 34 0 3 14 21 31 41 82 94 103 232 54 367 -14 39
|
||||
-39 97 -55 130 -47 98 -180 266 -247 313 -33 23 -43 42 -22 42 6 0 23 -8 37
|
||||
-19 142 -100 442 -189 497 -148 20 15 20 16 -6 44 -93 103 -304 490 -285 522
|
||||
3 5 23 -7 43 -26 21 -19 69 -62 108 -96z m1006 -800 c236 -425 273 -488 343
|
||||
-572 117 -141 217 -197 376 -211 57 -5 100 -15 131 -30 38 -19 63 -24 128 -24
|
||||
45 0 81 -4 81 -9 0 -19 -90 -130 -110 -136 -29 -9 -112 3 -190 28 -61 20 -136
|
||||
24 -264 14 -25 -2 -31 3 -37 28 -5 16 -16 36 -26 42 -25 19 -102 16 -169 -8
|
||||
-32 -11 -66 -22 -75 -25 -12 -4 -25 10 -47 49 -70 124 -117 152 -206 122 -26
|
||||
-9 -50 -14 -53 -11 -3 3 2 38 11 78 30 129 40 323 29 558 -5 118 -7 218 -5
|
||||
223 7 15 21 -5 83 -116z m561 -275 c154 -140 331 -284 465 -380 68 -48 123
|
||||
-92 123 -98 0 -5 -13 -23 -30 -39 l-29 -28 -78 22 c-85 25 -157 61 -187 95
|
||||
-136 153 -359 476 -328 476 6 0 34 -22 64 -48z m818 -585 c182 -77 348 -75
|
||||
493 6 l38 21 23 -25 c33 -33 118 -185 157 -278 17 -42 39 -115 47 -164 l16
|
||||
-88 -85 -85 c-327 -332 -761 -584 -1214 -704 -371 -98 -793 -116 -1160 -50
|
||||
-33 6 -75 14 -93 17 -65 12 -53 29 58 84 261 128 315 151 495 211 227 74 392
|
||||
116 584 149 57 10 83 20 108 42 18 16 33 33 33 38 0 31 -298 -18 -520 -86
|
||||
-239 -72 -367 -119 -500 -181 -55 -26 -103 -44 -107 -40 -14 14 95 397 154
|
||||
541 76 186 79 190 130 223 80 51 283 149 365 176 154 50 250 53 367 11 54 -19
|
||||
221 -20 308 -1 67 14 128 45 122 61 -2 6 -32 9 -66 8 -37 0 -63 3 -63 9 0 6
|
||||
14 26 30 45 17 18 44 61 60 93 l30 60 78 -39 c42 -22 93 -46 112 -54z m-1357
|
||||
38 c14 -14 36 -49 50 -78 40 -86 52 -89 177 -53 30 9 72 16 93 16 73 0 42 -30
|
||||
-109 -105 -78 -38 -171 -90 -207 -114 -62 -40 -70 -50 -124 -150 -31 -58 -64
|
||||
-119 -73 -136 -9 -16 -27 -68 -39 -115 -25 -98 -43 -130 -72 -130 -32 0 -140
|
||||
-59 -177 -97 -47 -49 -84 -135 -80 -187 5 -63 26 -51 80 44 47 83 97 138 150
|
||||
166 15 8 29 10 32 5 3 -4 -16 -77 -42 -162 l-47 -153 -83 -48 c-46 -26 -94
|
||||
-48 -107 -48 -27 0 -164 45 -177 58 -5 5 15 45 50 98 74 112 188 316 291 522
|
||||
136 272 156 321 216 534 l28 98 60 30 c33 16 66 30 72 30 7 0 24 -11 38 -25z
|
||||
m-791 -197 c2 -6 -17 -75 -44 -152 -41 -123 -66 -214 -99 -371 -8 -40 -52
|
||||
-319 -64 -407 -5 -38 -10 -48 -25 -48 -20 0 -145 68 -197 106 -39 29 -49 78
|
||||
-36 176 l8 66 109 101 c60 56 115 101 122 101 17 0 48 46 39 59 -3 6 -20 14
|
||||
-38 19 -27 7 -33 13 -35 42 -2 18 -1 48 3 66 5 30 10 33 50 39 58 9 80 35 78
|
||||
90 -2 47 22 78 82 109 36 19 42 20 47 4z"/>
|
||||
<path d="M2350 2864 c-83 -62 -149 -98 -197 -108 -42 -9 -60 -31 -43 -51 7 -8
|
||||
23 -15 36 -15 25 0 33 -27 15 -45 -6 -6 -13 -29 -17 -52 -12 -75 24 -47 79 63
|
||||
19 38 38 59 73 79 89 52 176 148 159 175 -11 18 -29 10 -105 -46z"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 5.3 KiB |
BIN
icon/term.png
Normal file
After Width: | Height: | Size: 74 KiB |
30
icon/term.svg
Normal file
@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
|
||||
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
||||
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
|
||||
width="1417.000000pt" height="1417.000000pt" viewBox="0 0 1417.000000 1417.000000"
|
||||
preserveAspectRatio="xMidYMid meet">
|
||||
|
||||
<g transform="translate(0.000000,1417.000000) scale(0.100000,-0.100000)"
|
||||
fill="#000000" stroke="none">
|
||||
<path d="M0 7085 l0 -7085 7085 0 7085 0 0 7085 0 7085 -7085 0 -7085 0 0
|
||||
-7085z m2783 4626 c102 -58 632 -354 675 -376 18 -10 40 -8 115 8 78 17 129
|
||||
21 327 21 209 1 247 -2 345 -22 470 -100 868 -365 1128 -754 76 -115 153 -267
|
||||
197 -394 l32 -91 180 -113 c213 -133 528 -325 580 -354 43 -24 47 -40 16 -59
|
||||
-13 -8 -75 -46 -138 -84 -63 -39 -233 -143 -376 -232 l-261 -161 -33 -91
|
||||
c-145 -406 -431 -747 -799 -953 -202 -114 -430 -189 -651 -216 -173 -21 -479
|
||||
-5 -599 31 -37 11 -41 9 -257 -111 -120 -67 -266 -148 -324 -180 -58 -32 -141
|
||||
-78 -185 -103 -44 -25 -83 -43 -86 -39 -4 4 -16 219 -29 477 -12 259 -25 475
|
||||
-28 480 -3 6 -27 35 -53 65 -26 30 -77 100 -114 155 -347 520 -390 1212 -111
|
||||
1783 50 102 176 292 242 365 24 27 44 57 44 66 -1 47 42 918 45 929 3 6 7 12
|
||||
10 12 3 0 52 -26 108 -59z m6466 -3618 c31 -84 68 -239 82 -340 17 -128 7
|
||||
-403 -20 -526 -23 -106 -75 -273 -93 -294 -8 -11 -292 -13 -1484 -13 l-1473 0
|
||||
-12 21 c-23 43 -68 192 -91 297 -19 92 -23 136 -22 312 0 174 3 220 22 308 25
|
||||
115 69 261 84 280 8 9 320 12 1498 12 l1488 0 21 -57z"/>
|
||||
<path d="M3799 10649 c-156 -16 -335 -83 -479 -177 -72 -48 -215 -191 -267
|
||||
-267 -123 -182 -183 -381 -183 -606 0 -403 219 -761 576 -942 69 -35 214 -82
|
||||
299 -98 87 -16 269 -16 355 0 344 64 637 285 776 586 74 160 97 265 98 450 0
|
||||
191 -30 326 -109 485 -79 158 -202 296 -352 397 -146 97 -298 153 -475 172
|
||||
-107 12 -128 12 -239 0z"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.7 KiB |
BIN
icon/terminal.png
Normal file
After Width: | Height: | Size: 107 KiB |
32
icon/terminal.svg
Normal file
@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
|
||||
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
||||
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
|
||||
width="1417.000000pt" height="1417.000000pt" viewBox="0 0 1417.000000 1417.000000"
|
||||
preserveAspectRatio="xMidYMid meet">
|
||||
|
||||
<g transform="translate(0.000000,1417.000000) scale(0.100000,-0.100000)"
|
||||
fill="#000000" stroke="none">
|
||||
<path d="M0 7085 l0 -7085 7085 0 7085 0 0 7085 0 7085 -7085 0 -7085 0 0
|
||||
-7085z m2759 3496 c25 -16 134 -77 241 -137 234 -129 545 -302 732 -407 85
|
||||
-48 147 -77 166 -77 16 0 72 9 123 19 164 34 288 44 509 44 233 0 375 -14 565
|
||||
-58 474 -107 899 -337 1249 -675 308 -298 520 -635 673 -1074 l28 -79 95 -60
|
||||
c52 -33 133 -83 180 -112 47 -29 180 -111 295 -182 116 -71 242 -148 280 -171
|
||||
245 -147 340 -209 340 -222 0 -8 -13 -23 -30 -33 -16 -10 -77 -48 -135 -83
|
||||
-117 -71 -127 -77 -395 -241 -171 -104 -502 -309 -597 -369 -30 -19 -40 -35
|
||||
-58 -91 -129 -390 -331 -727 -608 -1015 -358 -371 -803 -625 -1295 -739 -206
|
||||
-48 -338 -62 -582 -63 -229 -1 -355 10 -525 46 -52 11 -104 20 -115 20 -17 0
|
||||
-194 -96 -750 -407 -27 -15 -125 -70 -218 -121 -92 -51 -177 -100 -189 -109
|
||||
-13 -8 -32 -15 -44 -15 -20 0 -21 6 -28 128 -12 245 -26 520 -41 852 -20 444
|
||||
-18 430 -66 488 -353 428 -535 822 -626 1352 -26 154 -26 650 0 800 57 320
|
||||
133 555 261 807 95 187 210 359 365 545 48 58 46 43 67 493 8 187 19 419 24
|
||||
515 5 96 12 239 16 318 8 163 10 165 93 113z m9685 -5373 c15 -24 64 -165 89
|
||||
-258 93 -344 103 -763 27 -1115 -39 -177 -117 -410 -144 -427 -15 -10 -4378
|
||||
-10 -4393 0 -39 25 -138 367 -175 602 -17 113 -17 536 0 650 32 207 124 543
|
||||
154 562 7 4 1006 8 2220 8 l2208 0 14 -22z"/>
|
||||
<path d="M4361 8949 c-96 -9 -252 -44 -351 -80 -520 -188 -897 -628 -1006
|
||||
-1174 -35 -176 -34 -434 1 -610 151 -747 782 -1265 1540 -1265 130 0 337 25
|
||||
405 49 14 5 57 19 95 31 452 140 839 526 991 988 61 186 68 239 68 502 0 265
|
||||
-8 325 -70 510 -88 261 -279 539 -479 699 -349 279 -731 391 -1194 350z"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.9 KiB |
22
index.html
Normal file
@ -0,0 +1,22 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>ai/term</title>
|
||||
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
|
||||
<meta name="author" content="syui" />
|
||||
<meta name="copyright" content="© syui" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
|
||||
<link rel="icon" href="/icon/term.png" />
|
||||
<link rel="shortcut icon" href="/icon/term.png" />
|
||||
<link rel="stylesheet" href="/pkg/jquery.terminal/css/jquery.terminal.css" />
|
||||
<link rel="stylesheet" href="/css/terminal.css" />
|
||||
<script src="/pkg/jquery.ajax/jquery.min.js"></script>
|
||||
<script src="/pkg/axios/dist/axios.min.js"></script>
|
||||
<script src="/pkg/jquery.terminal/js/jquery.terminal.min.js"></script>
|
||||
<script src="/pkg/jquery.terminal/js/jquery.mousewheel-min.js"></script>
|
||||
<script src="/js/terminal.quick.js"></script>
|
||||
<script src="/js/terminal.js"></script>
|
||||
<app></app>
|
||||
<script src="/js/bundle.js"></script>
|
||||
<script src="/js/terminal-open.js"></script>
|
||||
</head>
|
5241
js/bundle.js
Normal file
0
js/router.min.js.map
Normal file
2
js/terminal-open.js
Normal file
@ -0,0 +1,2 @@
|
||||
let e = document.querySelector('home-layout');
|
||||
e.style.display = "block";
|
275
js/terminal.js
Executable file
@ -0,0 +1,275 @@
|
||||
$(function() {
|
||||
var prompt = "[[b;#87cefa;]ai][[b;#FFFF00;]@aios] ~$ ";
|
||||
let url = new URL(window.location.href);
|
||||
let user = url.searchParams.get('user');
|
||||
let id = url.searchParams.get('id');
|
||||
if (id == null) { id = 2 };
|
||||
let did = url.searchParams.get('did');
|
||||
if (did == null) { did = "did:plc:4hqjfn7m6n5hno3doamuhgef" };
|
||||
if (user) { prompt = "[[b;#87cefa;]" + user + "][[b;#FFFF00;]@aios] ~$ " };
|
||||
var tab = "[[b;#87cefa;]<tab>]";
|
||||
var command_all = ["ai","ls","ai.json"];
|
||||
var handle = "yui.syui.ai";
|
||||
|
||||
var file_all = "ai.json";
|
||||
var ai_help = "\n\
|
||||
\nCommands:\
|
||||
\n ai\
|
||||
\n\
|
||||
\nFlags:\
|
||||
\n\t\t-h, --help\
|
||||
\n\
|
||||
\nOptions:\
|
||||
\n\ta\t\t\t\t: logo\
|
||||
\n\tv\t\t\t\t: pds version\
|
||||
\n\tp\t\t\t\t: ai profile\
|
||||
\n\tdid\t<handle> : did\
|
||||
\n\tplc\t<handle> : plc\
|
||||
\n\trecord <handle> : timeline\
|
||||
\n\
|
||||
\nex:\
|
||||
\n\t$ ai v\t: {\"version\":\"0.0.1\"}\
|
||||
\n\t\
|
||||
\nhttps://git.syui.ai/ai/bot\
|
||||
\n\t\
|
||||
";
|
||||
|
||||
var ascii_logo = '\n\ \n⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀\⠀ \n⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣿⣧⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀\⠀ \n⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣰⣿⣿⣿⣧⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀\⠀ \n⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣰⣿⣿⣿⣿⣿⣷⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀\⠀ \n⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⣿⣿⣿⣿⣿⣿⣿⣿⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀\⠀ \n⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣆⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀\⠀ \n⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣠⣴⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣶⣤⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀\⠀ \n⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣶⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀\⠀ \n⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣴⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣶⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀\⠀ \n⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣦⡀⠀⠀⠀⠀⠀⠀⠀⠀\⠀ \n⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣴⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠟⠋⠉⠀⠀⠀⠀⠀⠈⠉⠛⠿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⡄⠀⠀⠀⠀⠀⠀⠀\⠀ \n⠀⠀⠀⠀⠀⠀⠀⠀⠀⣼⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠟⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠙⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡄⠀⠀⠀⠀⠀⠀\⠀ \n⠀⠀⠀⠀⠀⠀⠀⠀⣸⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠹⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡀⠀⠀⠀⠀⠀\⠀ \n⠀⠀⠀⠀⠀⠀⠀⢀⣿⣿⣿⣿⣿⣿⣿⣿⣿⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⣿⣿⣿⣿⣿⣿⣿⣿⣿⣇⠀⠀⠀⠀⠀\⠀ \n⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢹⣿⣿⣿⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀⠀\⠀ \n⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⠀⠀\⠀ \n⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⠀⠀\⠀ \n⠀⠀⠀⠀⠀⠀⠀⢹⣿⣿⣿⣿⣿⣿⣿⣿⣷⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⣿⣿⣿⣿⣿⣿⣿⣿⣿⠁⠀⠀⠀⠀\⠀ \n⠀⠀⠀⠀⠀⠀⠀⠸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣾⣿⣿⣿⣿⣿⣿⣿⣿⡿⠀⠀⠀⠀⠀\⠀ \n⠀⠀⠀⠀⠀⠀⠀⣰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⡀⠀⠀⠀⠀\⠀ \n⠀⠀⠀⠀⠀⠀⢰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣧⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⠀⠀⠀⠀\⠀ \n⠀⠀⠀⠀⠀⢠⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣴⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣧⠀⠀⠀\⠀ \n⠀⠀⠀⠀⢠⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣶⣦⣤⣤⣤⣤⣶⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣇⠀⠀\⠀ \n⠀⠀⠀⢀⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣆⠀\⠀ \n⠀⠀⠀⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡆\⠀ \n⠀⠀⠘⠛⠛⠛⠛⠉⠉⠉⠉⠁⠀⠀⠀⠀⠈⠛⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠟⠋⠀⠀⠀⠀⠀⠉⠉⠉⠉⠙⠛⠛⠛⠛\⠀ \n⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠙⠛⠿⠿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠿⠟⠋⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀\⠀ \n⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠉⠉⠉⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀\⠀ \n\n';
|
||||
|
||||
var ascii_ai = "\n\
|
||||
\n⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠟⠉⣁⠉⠻⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\
|
||||
\n⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠿⠟⠛⠋⣉⣉⠡⠤⠤⠤⠤⠤⠤⠤⠤⠬⠤⣁⣉⡉⠛⠻⠿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\
|
||||
\n⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⢉⣤⡖⠚⣉⣡⣤⣦⣶⣶⣶⣶⣶⣶⣶⣶⣶⣶⣶⣴⣤⣤⠉⠑⣦⣌⠙⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\
|
||||
\n⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠀⣾⣿⣦⣄⣅⣌⣄⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣤⣶⣾⣿⣿⣁⣘⡙⠻⠿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\
|
||||
\n⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠿⢃⣤⣨⣿⡿⡿⠟⠟⠛⠻⠚⠛⠛⠛⠛⠛⠛⠋⡋⡋⠛⠛⠉⠉⠼⠿⠿⠿⠿⠿⠷⢶⢤⣈⠙⠿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\
|
||||
\n⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠿⢋⡡⠞⠛⣉⣉⣤⣤⣶⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣶⣶⣶⣶⣶⣶⣶⣦⣦⣦⣦⣶⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\
|
||||
\n⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣟⢁⣀⣤⣴⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\
|
||||
\n⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\
|
||||
\n⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠿⠟⠛⠋⡉⣉⣉⣁⣨⣀⣅⣉⣉⢉⠛⠛⠿⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\
|
||||
\n⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠟⠋⣁⡤⣴⣲⢯⢯⡯⣗⡯⣞⡾⣺⣺⢵⢯⢯⣟⢶⢦⣤⣀⡉⠛⠿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\
|
||||
\n⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠟⠉⣠⣔⡯⣗⡯⣗⡯⡯⣟⣞⣗⡯⣗⡯⣗⡯⡯⣟⣽⣺⢽⢽⣺⣳⢯⣟⡦⣌⡙⠻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\
|
||||
\n⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠟⠁⣠⣻⣺⣺⢽⣳⢯⣗⡯⡯⣗⡯⡾⣝⣗⡯⣗⡯⡯⣗⣗⡯⣟⣽⣺⣺⢽⣺⢽⣳⣻⢦⣈⠛⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\
|
||||
\n⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠋⢠⣺⣳⢽⣺⣺⢽⣺⢽⣺⢽⣫⣗⡯⡯⣗⣗⡯⣗⡯⡯⣗⣗⡯⣗⣗⡯⡾⣽⣺⢽⡽⣾⣽⣺⢵⡀⠻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\
|
||||
\n⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡟⠁⣔⣟⣞⡾⣽⣺⣺⢽⣺⢽⣺⢽⣺⣺⢽⣫⣗⣗⡯⣗⡯⡯⣗⣗⡯⣗⣗⡯⡯⣗⡯⣟⣞⣗⡿⣾⣽⢽⢦⠈⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\
|
||||
\n⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡟⢀⡮⣗⡯⡾⣝⡷⣽⣺⢽⣺⢽⣺⢽⣺⣺⢽⣺⣺⢵⢯⣗⡯⡯⣗⣗⡯⣗⣗⡯⡯⣗⡯⣗⣟⡾⣽⣻⣿⣯⣟⢷⡀⢻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\
|
||||
\n⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⢀⡾⣝⣗⡯⡯⣗⡯⣗⡯⣟⡾⣽⣺⢽⣺⣺⢽⣺⣺⢽⢽⣺⢽⣫⣗⣗⡯⣗⣗⡯⡯⣗⡯⣗⡷⣻⣗⡷⣿⣟⣿⣽⣳⠈⣻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\
|
||||
\n⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠁⣼⢽⣳⢗⡯⡯⣗⡯⣗⡯⣗⡯⣗⡯⠛⣞⡾⣽⣺⣺⢽⢽⣺⢽⣺⣺⢵⢯⣗⣗⡏⠙⣗⡯⣗⣯⢯⣷⢿⣽⣿⣿⡾⡽⣇⠘⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\
|
||||
\n⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠇⢸⣳⢽⣺⢽⢽⣫⣗⡯⣗⡯⣗⣯⡓⢡⡂⢵⢯⣗⡯⡾⣽⢽⣺⢽⣺⣺⢽⢽⣺⡞⢀⢇⠸⣽⣳⢽⣯⢿⣿⣿⣽⣷⣿⢯⢿⠀⣻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\
|
||||
\n⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠀⣞⡾⣽⣺⢽⢽⣺⣺⢽⣳⢯⣗⠇⢠⣿⠆⢸⢽⣺⢽⢽⣳⣻⣺⢽⣺⣺⢽⢽⡺⠁⡬⣿⡀⢳⡽⡽⣾⡯⢿⣯⣿⣽⣿⣻⢽⡃⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\
|
||||
\n⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡏⠠⣗⡯⣗⡯⣟⣽⣺⣺⢽⣺⢽⡺⢀⣿⣿⢅⠈⣟⡾⣽⢽⣺⢵⢯⣻⣺⣺⢽⢽⠃⡰⣽⣿⡇⢸⡽⡽⣿⢝⣽⣿⣿⣺⣿⡯⣯⡇⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\
|
||||
\n⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⢸⣳⢯⣗⡯⣗⣗⡯⡾⣽⣺⢽⠂⣸⣿⣾⡕⡀⢗⡯⣗⣟⡾⡽⣽⣺⣳⢽⢽⠃⢰⣱⣿⣷⡇⢸⡯⣟⠟⠀⣿⡿⣞⣾⣻⣽⡳⡇⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\
|
||||
\n⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⢸⣺⢽⣺⢽⣳⢗⡯⡯⣗⡯⡏⢀⣿⢿⣾⣗⠆⠸⣽⡳⣗⡯⡯⣗⣗⡯⣯⠏⢠⢣⣿⣿⣾⡇⢸⢯⠏⣰⠀⣿⣻⣳⣳⣿⣺⢽⠅⣸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\
|
||||
\n⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⠸⣺⢽⣺⢽⣺⢽⢽⣫⢷⠉⡇⠰⣿⣿⣻⣽⣎⠀⢗⡯⡗⢙⣽⡳⣗⡯⡏⢀⣗⣿⣿⣷⣿⠂⣺⠋⣠⣿⠀⣿⣺⢵⣫⣿⣺⢽⠀⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\
|
||||
\n⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⠈⣗⣟⡾⣽⣺⢽⢽⣺⠍⠀⡇⠘⣉⣤⣬⣈⣑⣅⠘⣽⠂⠘⣮⢯⣗⠏⢠⡟⣉⣡⠤⢤⠄⢠⠃⢴⡟⣯⠀⣗⡯⠟⡾⣗⡯⡇⢰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\
|
||||
\n⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡀⢸⣳⢯⣗⡯⣟⣽⡺⢀⠃⠀⠸⠋⢡⢡⡉⠻⣷⡄⠸⢀⡆⢹⣳⠃⣴⣿⣿⠋⣠⠐⡔⠀⠂⢳⡄⢰⣟⠀⠉⣠⣦⠘⣷⡻⠀⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\
|
||||
\n⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⢡⡀⢯⣗⣗⡯⣗⣷⡃⠀⣼⠀⠀⠓⠀⠓⢽⠄⢹⣿⡄⢐⣧⠘⢁⣾⣿⣯⡯⢐⢌⠀⠁⣜⠆⢸⣿⡀⢟⠀⢨⣄⠙⡇⢹⠃⣼⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\
|
||||
\n⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣌⠣⡈⢾⢵⢯⣗⢷⡃⢰⣿⡧⠈⣟⡀⠀⡸⡅⢸⡿⣿⣦⣹⣶⣻⣿⣷⣿⣇⠨⣫⢀⢀⢎⠃⣼⡿⣇⡾⠀⡢⠘⣨⠇⠈⣰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\
|
||||
\n⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣧⡐⠈⢫⣟⢾⢽⡂⢹⣿⣿⡄⠱⢕⢵⠝⢀⣾⣿⣿⣻⣿⣻⣿⣻⣾⣟⣿⣆⠑⡕⠗⣁⣴⣿⡿⣿⠃⠄⣾⣵⡟⠀⢰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\
|
||||
\n⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣄⠫⣟⡽⡃⢸⣿⣾⣿⡷⣾⣴⣻⡿⣯⣷⣿⣿⣻⣿⣽⣿⣟⣿⣻⣿⣟⣷⡿⣿⣽⣾⣿⡏⢠⠴⠟⠁⠄⣰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\
|
||||
\n⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⡈⢯⢧⠈⢿⣿⣾⣿⣿⣾⣿⢿⣿⣟⣿⣾⣿⣼⣿⣾⢿⣻⣿⣽⣿⣻⣿⣿⣻⣯⡿⠀⡄⡔⡔⠅⣴⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\
|
||||
\n⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡄⠙⢆⠈⠻⣾⣿⣾⢿⣾⣿⣿⣽⠻⢷⣿⣻⣾⠿⠟⢿⣻⣽⣾⣿⢿⣾⡿⠋⡁⡜⠌⠈⣠⠪⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\
|
||||
\n⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⢸⡂⠀⣤⡈⠻⣾⣿⢿⣷⡿⣯⣷⣤⣤⣤⣤⣶⣾⣿⣿⢿⣻⠽⠛⢉⢠⠸⠈⡠⣰⠀⣿⡀⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\
|
||||
\n⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⢸⠀⢨⣗⡯⣖⡄⢈⠉⠓⠻⠿⢿⣟⣿⣻⣿⠽⠟⠞⠋⢉⢠⠀⡰⠑⢁⢰⠀⡯⣪⠀⣳⣇⠸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\
|
||||
\n⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡗⠨⠀⣻⢮⡯⢺⠀⢜⠈⡊⢐⢶⢔⡤⡤⣤⢤⢖⣖⢷⠅⢸⠀⠐⢁⡴⡇⡘⢠⡫⡎⡇⢸⣺⡄⢻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\
|
||||
\n⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⡯⣗⠇⡪⠀⡃⠠⡃⠨⣿⣷⣯⣿⣾⣽⣷⣯⣿⠂⠀⡠⠀⣻⣺⡇⠀⢸⡂⢝⢦⠐⣗⣧⠈⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\
|
||||
\n⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠁⣜⠀⡯⡿⠀⠆⢐⠁⢜⠌⢨⣿⣾⣿⣽⣯⣿⣷⣿⢿⡁⢌⠐⠀⣳⣳⡃⠀⡪⡇⢸⢕⠄⢳⢽⡆⠸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\
|
||||
\n⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡟⠁⡰⢱⠀⡯⡏⠨⠂⢀⡈⢈⡄⢸⣷⣿⣷⢿⣯⣷⣿⣾⣿⣆⠙⠅⠀⣞⣾⠀⢀⢯⡢⠘⣎⢇⠘⡽⣽⡀⢻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\
|
||||
\n⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠏⠀⠀⣰⡹⠀⢯⠇⢘⠀⠍⣴⣿⣤⣿⡿⣷⣿⢿⣻⣽⣷⣿⡿⣿⣷⡂⢀⣗⣿⠀⠰⠣⢯⡀⢗⡝⡄⠹⣳⢧⠈⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\
|
||||
\n⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡟⢁⠔⢁⠞⣈⣴⠀⣫⠃⡐⢀⢞⣿⡿⣾⣟⣿⣿⣽⣿⡿⣟⣿⣾⡿⣿⣽⡂⢐⣗⡗⢀⣶⣦⣦⣤⣄⣉⠘⠀⠹⡽⣆⠘⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\
|
||||
\n⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠋⡠⠃⡔⢁⣼⣿⡿⠀⢸⠀⡂⢸⢸⣿⡿⣟⣿⢿⣞⡿⣾⣿⢿⣟⣷⢿⣿⣷⠁⢰⢯⡇⢰⣿⣯⣿⣟⣿⡿⣿⣷⣤⣈⠛⢆⠘⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\
|
||||
\n⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠟⢠⠊⡠⢊⣰⣿⣿⠟⣰⠀⢸⠀⠀⡎⣾⠿⠟⠛⣉⢉⠚⢮⢿⣾⢿⣝⠮⢋⣠⣈⠂⣸⢽⠀⢼⣟⣯⣷⣿⣟⣿⣿⣽⣿⣿⡷⡌⢣⡈⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\
|
||||
\n⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡟⠁⡔⢁⡔⢡⣾⣿⣿⣧⡐⢿⠀⣞⠀⠀⣏⢦⡶⣞⣿⣽⣳⣳⣽⣿⢿⣻⣾⣴⣳⣷⣿⠀⣺⡝⠀⣽⣿⢿⣻⣽⣿⣽⣾⡿⣯⣿⣿⣿⡀⢳⡀⠻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\
|
||||
\n⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠋⢀⠎⢠⠎⣠⣿⣿⣿⣿⣿⣿⣦⠀⡯⠀⠐⠧⠻⠛⠛⢋⢋⠋⠙⠛⠿⣿⢿⣷⡿⣿⣽⡿⠀⣷⠃⠀⣿⡿⣿⡿⣿⣽⣯⣷⣿⣿⡿⣿⣻⡇⢀⠹⣆⠘⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿\
|
||||
";
|
||||
|
||||
let list = 'https://bsky.social/xrpc/com.atproto.repo.listRecords?repo=';
|
||||
function bsky_record() {
|
||||
var u;
|
||||
u = axios.get(list + did + '&collection=app.bsky.feed.post&limit=1')
|
||||
.then(function (response) {
|
||||
return JSON.stringify(response.data.records[0].value,null,"\t");
|
||||
})
|
||||
return u;
|
||||
}
|
||||
|
||||
function bsky_ver() {
|
||||
var u;
|
||||
u = axios.get('https://bsky.social/xrpc/_health')
|
||||
.then(function (response) {
|
||||
return JSON.stringify(response.data,null,"\t");
|
||||
})
|
||||
return u;
|
||||
}
|
||||
|
||||
let plc_server = "https://plc.directory/"
|
||||
function bsky_plc() {
|
||||
var u;
|
||||
u = axios.get(plc_server + did + '/log')
|
||||
.then(function (response) {
|
||||
return JSON.stringify(response.data,null,"\t");
|
||||
})
|
||||
return u;
|
||||
}
|
||||
|
||||
let desc = 'https://bsky.social/xrpc/com.atproto.repo.describeRepo?repo=';
|
||||
function bsky_desc() {
|
||||
var u;
|
||||
u = axios.get(desc + did + '&collection=app.bsky.actor.profile')
|
||||
.then(function (response) {
|
||||
return JSON.stringify(response.data,null,"\t");
|
||||
})
|
||||
return u;
|
||||
}
|
||||
|
||||
function bsky_did() {
|
||||
var u;
|
||||
u = axios.get(desc + handle + '&collection=app.bsky.actor.profile')
|
||||
.then(function (response) {
|
||||
return JSON.stringify(response.data.did,null,"\t").replaceAll('"', '');
|
||||
})
|
||||
return u;
|
||||
}
|
||||
|
||||
function test_json() {
|
||||
var u;
|
||||
u = axios.get('/json/ai.json')
|
||||
.then(function (response) {
|
||||
return JSON.stringify(response.data,null,"\t");
|
||||
})
|
||||
return u;
|
||||
}
|
||||
|
||||
function print_slowly(term, paragraph, callback) {
|
||||
var foo, i, lines;
|
||||
lines = paragraph.split("\n");
|
||||
term.pause();
|
||||
i = 0;
|
||||
foo = function(lines) {
|
||||
return setTimeout((function() {
|
||||
if (i < lines.length - 1) {
|
||||
term.echo(lines[i]);
|
||||
i++;
|
||||
return foo(lines);
|
||||
} else {
|
||||
term.resume();
|
||||
return callback();
|
||||
}
|
||||
}), 100);
|
||||
};
|
||||
return foo(lines);
|
||||
}
|
||||
|
||||
function require_command(command_regex, terminal_history) {
|
||||
var executed = true;
|
||||
$.each(terminal_history, function(index, value) {
|
||||
if (command_regex.test(value)) {
|
||||
executed = true
|
||||
}
|
||||
});
|
||||
return executed;
|
||||
}
|
||||
|
||||
function interpreter(input, term) {
|
||||
var command, inputs;
|
||||
inputs = input.split(/ +/)
|
||||
command = inputs[0];
|
||||
option = inputs[1];
|
||||
if (did == null) { did = "did:plc:4hqjfn7m6n5hno3doamuhgef" };
|
||||
if (handle == null) { handle = "did:plc:4hqjfn7m6n5hno3doamuhgef" };
|
||||
if (command === 'ai' && inputs[1] === undefined) {
|
||||
term.echo(ai_help);
|
||||
} else if (command === 'ls') {
|
||||
term.echo(file_all);
|
||||
} else if (command === 'cat') {
|
||||
if (option === 'ai.json') {
|
||||
term.echo(test_json());
|
||||
} else {
|
||||
term.echo(file_all);
|
||||
}
|
||||
} else if (command === 'ai' && option === 'a') {
|
||||
print_slowly(term, ascii_logo);
|
||||
} else if (command === 'ai' && option === 'p') {
|
||||
term.echo(ascii_ai);
|
||||
term.echo(test_json());
|
||||
} else if (command === 'ai' && option === 'plc') {
|
||||
if (inputs[2] != undefined) { did = inputs[2]; }
|
||||
url = desc + did + '&collection=app.bsky.actor.profile';
|
||||
$.ajaxSetup({async: false});
|
||||
$.getJSON(url, function(data) {
|
||||
did = JSON.stringify(data.did,null,"\t").replaceAll('"', '')
|
||||
url = plc_server + did + '/log';
|
||||
$.ajaxSetup({async: false});
|
||||
$.getJSON(url, function(data) {
|
||||
term.echo(JSON.stringify(data,null,"\t"));
|
||||
});$.ajaxSetup({async: true});
|
||||
});$.ajaxSetup({async: true});
|
||||
} else if (command === 'ai' && option === 'record') {
|
||||
if (inputs[2] != undefined) { did = inputs[2]; }
|
||||
url = list + did + '&collection=app.bsky.feed.post&limit=1';
|
||||
$.ajaxSetup({async: false});
|
||||
$.getJSON(url, function(data) {
|
||||
term.echo(JSON.stringify(data,null,"\t"));
|
||||
});$.ajaxSetup({async: true});
|
||||
} else if (command === 'ai' && option === 'did') {
|
||||
if (inputs[2] != undefined) { handle = inputs[2]; }
|
||||
url = desc + handle + '&collection=app.bsky.actor.profile';
|
||||
$.ajaxSetup({async: false});
|
||||
$.getJSON(url, function(data) {
|
||||
term.echo(JSON.stringify(data.did,null,"\t").replaceAll('"', ''));
|
||||
});$.ajaxSetup({async: true});
|
||||
} else if (command === 'ai' && option === 'handle') {
|
||||
if (inputs[2] != undefined) { did = inputs[2]; }
|
||||
url = desc + did + '&collection=app.bsky.actor.profile';
|
||||
$.ajaxSetup({async: false});
|
||||
$.getJSON(url, function(data) {
|
||||
term.echo(JSON.stringify(data,null,"\t"));
|
||||
});$.ajaxSetup({async: true});
|
||||
} else if (command === 'ai' && option === 'v') {
|
||||
url = 'https://bsky.social/xrpc/_health';
|
||||
$.ajaxSetup({async: false});
|
||||
$.getJSON(url, function(data) {
|
||||
term.echo(JSON.stringify(data,null,"\t"));
|
||||
});$.ajaxSetup({async: true});
|
||||
} else {
|
||||
term.echo(ai_help);
|
||||
}
|
||||
}
|
||||
|
||||
function bash(inputs, term) {
|
||||
var argument, echo, insert;
|
||||
echo = term.echo;
|
||||
insert = term.insert;
|
||||
if (!inputs[1]) {
|
||||
//return console.log("none");
|
||||
} else {
|
||||
argument = inputs[1];
|
||||
if (/^\.\./.test(argument)) {
|
||||
return echo("-bash: cd: " + argument + ": Permission denied");
|
||||
} else {
|
||||
return echo("-bash: cd: " + argument + ": No such file or directory");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$('#terminal').terminal(interpreter, {
|
||||
prompt: prompt,
|
||||
name: 'test',
|
||||
greetings: "",
|
||||
exit: false,
|
||||
height: 450,
|
||||
onInit: function(term) {
|
||||
//term.insert("ai");
|
||||
//print_slowly(term, ascii_ai);
|
||||
},
|
||||
completion: function(term, string, callback) {
|
||||
var t = $(term[0]).text();
|
||||
if (t.match(/none/)) {
|
||||
term.clear();
|
||||
} else {
|
||||
callback(command_all);
|
||||
term.history().clear();
|
||||
}
|
||||
},
|
||||
tabcompletion: true
|
||||
});
|
||||
});
|
11
js/terminal.quick.js
Normal file
@ -0,0 +1,11 @@
|
||||
$(function(){
|
||||
$("#mainTitle").click(function(){
|
||||
$("home-layout").toggle();
|
||||
});
|
||||
$("#mainTitleA").click(function(){
|
||||
$("home-layout").toggle();
|
||||
});
|
||||
$("#mainTitleB").click(function(){
|
||||
$("home-layout").toggle();
|
||||
});
|
||||
});
|
6
json/ai.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"handle": "yui.syui.ai",
|
||||
"displayName": "ai",
|
||||
"day": "01/23",
|
||||
"size": "123cm"
|
||||
}
|
131
pkg/axios/bin/GithubAPI.js
Normal file
@ -0,0 +1,131 @@
|
||||
import util from "util";
|
||||
import cp from "child_process";
|
||||
import {parseVersion} from "./helpers/parser.js";
|
||||
import githubAxios from "./githubAxios.js";
|
||||
import memoize from 'memoizee';
|
||||
|
||||
const exec = util.promisify(cp.exec);
|
||||
|
||||
export default class GithubAPI {
|
||||
constructor(owner, repo) {
|
||||
if (!owner) {
|
||||
throw new Error('repo owner must be specified');
|
||||
}
|
||||
|
||||
if (!repo) {
|
||||
throw new Error('repo must be specified');
|
||||
}
|
||||
|
||||
this.repo = repo;
|
||||
this.owner = owner;
|
||||
this.axios = githubAxios.create({
|
||||
baseURL: `https://api.github.com/repos/${this.owner}/${this.repo}/`,
|
||||
})
|
||||
}
|
||||
|
||||
async createComment(issue, body) {
|
||||
return (await this.axios.post(`/issues/${issue}/comments`, {body})).data;
|
||||
}
|
||||
|
||||
async getComments(issue, {desc = false, per_page= 100, page = 1} = {}) {
|
||||
return (await this.axios.get(`/issues/${issue}/comments`, {params: {direction: desc ? 'desc' : 'asc', per_page, page}})).data;
|
||||
}
|
||||
|
||||
async getComment(id) {
|
||||
return (await this.axios.get(`/issues/comments/${id}`)).data;
|
||||
}
|
||||
|
||||
async updateComment(id, body) {
|
||||
return (await this.axios.patch(`/issues/comments/${id}`, {body})).data;
|
||||
}
|
||||
|
||||
async appendLabels(issue, labels) {
|
||||
return (await this.axios.post(`/issues/${issue}/labels`, {labels})).data;
|
||||
}
|
||||
|
||||
async getUser(user) {
|
||||
return (await githubAxios.get(`/users/${user}`)).data;
|
||||
}
|
||||
|
||||
async isCollaborator(user) {
|
||||
try {
|
||||
return (await this.axios.get(`/collaborators/${user}`)).status === 204;
|
||||
} catch (e) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
async deleteLabel(issue, label) {
|
||||
return (await this.axios.delete(`/issues/${issue}/labels/${label}`)).data;
|
||||
}
|
||||
|
||||
async getIssue(issue) {
|
||||
return (await this.axios.get(`/issues/${issue}`)).data;
|
||||
}
|
||||
|
||||
async getPR(issue) {
|
||||
return (await this.axios.get(`/pulls/${issue}`)).data;
|
||||
}
|
||||
|
||||
async getIssues({state= 'open', labels, sort = 'created', desc = false, per_page = 100, page = 1}) {
|
||||
return (await this.axios.get(`/issues`, {params: {state, labels, sort, direction: desc ? 'desc' : 'asc', per_page, page}})).data;
|
||||
}
|
||||
|
||||
async updateIssue(issue, data) {
|
||||
return (await this.axios.patch(`/issues/${issue}`, data)).data;
|
||||
}
|
||||
|
||||
async closeIssue(issue) {
|
||||
return this.updateIssue(issue, {
|
||||
state: "closed"
|
||||
})
|
||||
}
|
||||
|
||||
async getReleases({per_page = 30, page= 1} = {}) {
|
||||
return (await this.axios.get(`/releases`, {params: {per_page, page}})).data;
|
||||
}
|
||||
|
||||
async getRelease(release = 'latest') {
|
||||
return (await this.axios.get(parseVersion(release) ? `/releases/tags/${release}` : `/releases/${release}`)).data;
|
||||
}
|
||||
|
||||
async getTags({per_page = 30, page= 1} = {}) {
|
||||
return (await this.axios.get(`/tags`, {params: {per_page, page}})).data;
|
||||
}
|
||||
|
||||
async reopenIssue(issue) {
|
||||
return this.updateIssue(issue, {
|
||||
state: "open"
|
||||
})
|
||||
}
|
||||
|
||||
static async getTagRef(tag) {
|
||||
try {
|
||||
return (await exec(`git show-ref --tags "refs/tags/${tag}"`)).stdout.split(' ')[0];
|
||||
} catch (e) {
|
||||
}
|
||||
}
|
||||
|
||||
static async getLatestTag() {
|
||||
try{
|
||||
const {stdout} = await exec(`git for-each-ref refs/tags --sort=-taggerdate --format='%(refname)' --count=1`);
|
||||
|
||||
return stdout.split('/').pop();
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
static normalizeTag(tag){
|
||||
return tag ? 'v' + tag.replace(/^v/, '') : '';
|
||||
}
|
||||
}
|
||||
|
||||
const {prototype} = GithubAPI;
|
||||
|
||||
['getUser', 'isCollaborator'].forEach(methodName => {
|
||||
prototype[methodName] = memoize(prototype[methodName], { promise: true })
|
||||
});
|
||||
|
||||
['get', 'post', 'put', 'delete', 'isAxiosError'].forEach((method) => prototype[method] = function(...args){
|
||||
return this.axios[method](...args);
|
||||
});
|
||||
|
128
pkg/axios/bin/RepoBot.js
Normal file
@ -0,0 +1,128 @@
|
||||
import GithubAPI from "./GithubAPI.js";
|
||||
import api from './api.js';
|
||||
import Handlebars from "handlebars";
|
||||
import fs from "fs/promises";
|
||||
import {colorize} from "./helpers/colorize.js";
|
||||
import {getReleaseInfo} from "./contributors.js";
|
||||
import path from "path";
|
||||
import {fileURLToPath} from "url";
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
|
||||
const NOTIFY_PR_TEMPLATE = path.resolve(__dirname, '../templates/pr_published.hbs');
|
||||
|
||||
const normalizeTag = (tag) => tag ? 'v' + tag.replace(/^v/, '') : '';
|
||||
|
||||
const GITHUB_BOT_LOGIN = 'github-actions[bot]';
|
||||
|
||||
const skipCollaboratorPRs = true;
|
||||
|
||||
class RepoBot {
|
||||
constructor(options) {
|
||||
const {
|
||||
owner, repo,
|
||||
templates
|
||||
} = options || {};
|
||||
|
||||
this.templates = Object.assign({
|
||||
published: NOTIFY_PR_TEMPLATE
|
||||
}, templates);
|
||||
|
||||
this.github = api || new GithubAPI(owner, repo);
|
||||
|
||||
this.owner = this.github.owner;
|
||||
this.repo = this.github.repo;
|
||||
}
|
||||
|
||||
async addComment(targetId, message) {
|
||||
return this.github.createComment(targetId, message);
|
||||
}
|
||||
|
||||
async notifyPRPublished(id, tag) {
|
||||
let pr;
|
||||
|
||||
try {
|
||||
pr = await this.github.getPR(id);
|
||||
} catch (err) {
|
||||
if(err.response?.status === 404) {
|
||||
throw new Error(`PR #${id} not found (404)`);
|
||||
}
|
||||
|
||||
throw err;
|
||||
}
|
||||
|
||||
tag = normalizeTag(tag);
|
||||
|
||||
const {merged, labels, user: {login, type}} = pr;
|
||||
|
||||
const isBot = type === 'Bot';
|
||||
|
||||
if (!merged) {
|
||||
return false
|
||||
}
|
||||
|
||||
await this.github.appendLabels(id, [tag]);
|
||||
|
||||
if (isBot || labels.find(({name}) => name === 'automated pr') || (skipCollaboratorPRs && await this.github.isCollaborator(login))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const comments = await this.github.getComments(id, {desc: true});
|
||||
|
||||
const comment = comments.find(
|
||||
({body, user}) => user.login === GITHUB_BOT_LOGIN && body.indexOf('published in') >= 0
|
||||
)
|
||||
|
||||
if (comment) {
|
||||
console.log(colorize()`Release comment [${comment.html_url}] already exists in #${pr.id}`);
|
||||
return false;
|
||||
}
|
||||
|
||||
const author = await this.github.getUser(login);
|
||||
|
||||
author.isBot = isBot;
|
||||
|
||||
const message = await this.constructor.renderTemplate(this.templates.published, {
|
||||
id,
|
||||
author,
|
||||
release: {
|
||||
tag,
|
||||
url: `https://github.com/${this.owner}/${this.repo}/releases/tag/${tag}`
|
||||
}
|
||||
});
|
||||
|
||||
return await this.addComment(id, message);
|
||||
}
|
||||
|
||||
async notifyPublishedPRs(tag) {
|
||||
tag = normalizeTag(tag);
|
||||
|
||||
const release = await getReleaseInfo(tag);
|
||||
|
||||
if (!release) {
|
||||
throw Error(colorize()`Can't get release info for ${tag}`);
|
||||
}
|
||||
|
||||
const {merges} = release;
|
||||
|
||||
console.log(colorize()`Found ${merges.length} PRs in ${tag}:`);
|
||||
|
||||
let i = 0;
|
||||
|
||||
for (const pr of merges) {
|
||||
try {
|
||||
console.log(colorize()`${i++}) Notify PR #${pr.id}`)
|
||||
const result = await this.notifyPRPublished(pr.id, tag);
|
||||
console.log('✔️', result ? 'Label, comment' : 'Label');
|
||||
} catch (err) {
|
||||
console.warn(colorize('green', 'red')`❌ Failed notify PR ${pr.id}: ${err.message}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static async renderTemplate(template, data) {
|
||||
return Handlebars.compile(String(await fs.readFile(template)))(data);
|
||||
}
|
||||
}
|
||||
|
||||
export default RepoBot;
|
28
pkg/axios/bin/actions/notify_published.js
Normal file
@ -0,0 +1,28 @@
|
||||
import minimist from "minimist";
|
||||
import RepoBot from '../RepoBot.js';
|
||||
import fs from 'fs/promises';
|
||||
|
||||
const argv = minimist(process.argv.slice(2));
|
||||
console.log(argv);
|
||||
|
||||
let {tag} = argv;
|
||||
|
||||
(async() => {
|
||||
if (!tag || tag === true) {
|
||||
const {version} = JSON.parse((await fs.readFile('./package.json')).toString());
|
||||
|
||||
tag = 'v' + version;
|
||||
} else if (typeof tag !== 'string') {
|
||||
|
||||
throw new Error('tag must be a string');
|
||||
}
|
||||
|
||||
const bot = new RepoBot();
|
||||
|
||||
try {
|
||||
await bot.notifyPublishedPRs(tag);
|
||||
} catch (err) {
|
||||
console.warn('Error:', err.message);
|
||||
}
|
||||
})();
|
||||
|
3
pkg/axios/bin/api.js
Normal file
@ -0,0 +1,3 @@
|
||||
import GithubAPI from "./GithubAPI.js";
|
||||
|
||||
export default new GithubAPI('axios', 'axios');
|
29
pkg/axios/bin/check-build-version.js
Normal file
@ -0,0 +1,29 @@
|
||||
import fs from 'fs';
|
||||
import assert from 'assert';
|
||||
import axios from '../index.js';
|
||||
import axiosBuild from '../dist/node/axios.cjs';
|
||||
|
||||
const {version} = JSON.parse(fs.readFileSync('./package.json'));
|
||||
|
||||
console.log('Checking versions...\n----------------------------')
|
||||
|
||||
console.log(`Package version: v${version}`);
|
||||
console.log(`Axios version: v${axios.VERSION}`);
|
||||
console.log(`Axios build version: v${axiosBuild.VERSION}`);
|
||||
console.log(`----------------------------`);
|
||||
|
||||
assert.strictEqual(
|
||||
version,
|
||||
axios.VERSION,
|
||||
`Version mismatch between package and Axios ${version} != ${axios.VERSION}`
|
||||
);
|
||||
|
||||
assert.strictEqual(
|
||||
version,
|
||||
axiosBuild.VERSION,
|
||||
`Version mismatch between package and build ${version} != ${axiosBuild.VERSION}`
|
||||
);
|
||||
|
||||
console.log('✔️ PASSED\n');
|
||||
|
||||
|
241
pkg/axios/bin/contributors.js
Normal file
@ -0,0 +1,241 @@
|
||||
import axios from "./githubAxios.js";
|
||||
import util from "util";
|
||||
import cp from "child_process";
|
||||
import Handlebars from "handlebars";
|
||||
import fs from "fs/promises";
|
||||
import {colorize} from "./helpers/colorize.js";
|
||||
|
||||
const exec = util.promisify(cp.exec);
|
||||
|
||||
const ONE_MB = 1024 * 1024;
|
||||
|
||||
const removeExtraLineBreaks = (str) => str.replace(/(?:\r\n|\r|\n){3,}/gm, '\r\n\r\n');
|
||||
|
||||
const cleanTemplate = template => template
|
||||
.replace(/\n +/g, '\n')
|
||||
.replace(/^ +/, '')
|
||||
.replace(/\n\n\n+/g, '\n\n')
|
||||
.replace(/\n\n$/, '\n');
|
||||
|
||||
const getUserFromCommit = ((commitCache) => async (sha) => {
|
||||
try {
|
||||
if(commitCache[sha] !== undefined) {
|
||||
return commitCache[sha];
|
||||
}
|
||||
|
||||
console.log(colorize()`fetch github commit info (${sha})`);
|
||||
|
||||
const {data} = await axios.get(`https://api.github.com/repos/axios/axios/commits/${sha}`);
|
||||
|
||||
return commitCache[sha] = {
|
||||
...data.commit.author,
|
||||
...data.author,
|
||||
avatar_url_sm: data.author.avatar_url ? data.author.avatar_url + '&s=18' : '',
|
||||
};
|
||||
} catch (err) {
|
||||
return commitCache[sha] = null;
|
||||
}
|
||||
})({});
|
||||
|
||||
const getIssueById = ((cache) => async (id) => {
|
||||
if(cache[id] !== undefined) {
|
||||
return cache[id];
|
||||
}
|
||||
|
||||
try {
|
||||
const {data} = await axios.get(`https://api.github.com/repos/axios/axios/issues/${id}`);
|
||||
|
||||
return cache[id] = data;
|
||||
} catch (err) {
|
||||
return null;
|
||||
}
|
||||
})({});
|
||||
|
||||
const getUserInfo = ((userCache) => async (userEntry) => {
|
||||
const {email, commits} = userEntry;
|
||||
|
||||
if (userCache[email] !== undefined) {
|
||||
return userCache[email];
|
||||
}
|
||||
|
||||
console.log(colorize()`fetch github user info [${userEntry.name}]`);
|
||||
|
||||
return userCache[email] = {
|
||||
...userEntry,
|
||||
...await getUserFromCommit(commits[0].hash)
|
||||
}
|
||||
})({});
|
||||
|
||||
const deduplicate = (authors) => {
|
||||
const loginsMap = {};
|
||||
const combined= {};
|
||||
|
||||
const assign = (a, b) => {
|
||||
const {insertions, deletions, points, ...rest} = b;
|
||||
|
||||
Object.assign(a, rest);
|
||||
|
||||
a.insertions += insertions;
|
||||
a.deletions += insertions;
|
||||
a.insertions += insertions;
|
||||
}
|
||||
|
||||
for(const [email, user] of Object.entries(authors)) {
|
||||
const {login} = user;
|
||||
let entry;
|
||||
|
||||
if(login && (entry = loginsMap[login])) {
|
||||
assign(entry, user);
|
||||
} else {
|
||||
login && (loginsMap[login] = user);
|
||||
combined[email] = user;
|
||||
}
|
||||
}
|
||||
|
||||
return combined;
|
||||
}
|
||||
|
||||
const getReleaseInfo = ((releaseCache) => async (tag) => {
|
||||
if(releaseCache[tag] !== undefined) {
|
||||
return releaseCache[tag];
|
||||
}
|
||||
|
||||
const isUnreleasedTag = !tag;
|
||||
|
||||
const version = 'v' + tag.replace(/^v/, '');
|
||||
|
||||
const command = isUnreleasedTag ?
|
||||
`npx auto-changelog --unreleased-only --stdout --commit-limit false --template json` :
|
||||
`npx auto-changelog ${
|
||||
version ? '--starting-version ' + version + ' --ending-version ' + version : ''
|
||||
} --stdout --commit-limit false --template json`;
|
||||
|
||||
console.log(command);
|
||||
|
||||
const {stdout} = await exec(command, {maxBuffer: 10 * ONE_MB});
|
||||
|
||||
const release = JSON.parse(stdout)[0];
|
||||
|
||||
if(release) {
|
||||
const authors = {};
|
||||
|
||||
const commits = [
|
||||
...release.commits,
|
||||
...release.fixes.map(fix => fix.commit),
|
||||
...release.merges.map(fix => fix.commit)
|
||||
].filter(Boolean);
|
||||
|
||||
const commitMergeMap = {};
|
||||
|
||||
for(const merge of release.merges) {
|
||||
commitMergeMap[merge.commit.hash] = merge.id;
|
||||
}
|
||||
|
||||
for (const {hash, author, email, insertions, deletions} of commits) {
|
||||
const entry = authors[email] = (authors[email] || {
|
||||
name: author,
|
||||
prs: [],
|
||||
email,
|
||||
commits: [],
|
||||
insertions: 0, deletions: 0
|
||||
});
|
||||
|
||||
entry.commits.push({hash});
|
||||
|
||||
let pr;
|
||||
|
||||
if((pr = commitMergeMap[hash])) {
|
||||
entry.prs.push(pr);
|
||||
}
|
||||
|
||||
console.log(colorize()`Found commit [${hash}]`);
|
||||
|
||||
entry.displayName = entry.name || author || entry.login;
|
||||
|
||||
entry.github = entry.login ? `https://github.com/${encodeURIComponent(entry.login)}` : '';
|
||||
|
||||
entry.insertions += insertions;
|
||||
entry.deletions += deletions;
|
||||
entry.points = entry.insertions + entry.deletions;
|
||||
}
|
||||
|
||||
for (const [email, author] of Object.entries(authors)) {
|
||||
const entry = authors[email] = await getUserInfo(author);
|
||||
|
||||
entry.isBot = entry.type === "Bot";
|
||||
}
|
||||
|
||||
release.authors = Object.values(deduplicate(authors))
|
||||
.sort((a, b) => b.points - a.points);
|
||||
|
||||
release.allCommits = commits;
|
||||
}
|
||||
|
||||
releaseCache[tag] = release;
|
||||
|
||||
return release;
|
||||
})({});
|
||||
|
||||
const renderContributorsList = async (tag, template) => {
|
||||
const release = await getReleaseInfo(tag);
|
||||
|
||||
const compile = Handlebars.compile(String(await fs.readFile(template)))
|
||||
|
||||
const content = compile(release);
|
||||
|
||||
return removeExtraLineBreaks(cleanTemplate(content));
|
||||
}
|
||||
|
||||
const renderPRsList = async (tag, template, {comments_threshold= 5, awesome_threshold= 5, label = 'add_to_changelog'} = {}) => {
|
||||
const release = await getReleaseInfo(tag);
|
||||
|
||||
const prs = {};
|
||||
|
||||
for(const merge of release.merges) {
|
||||
const pr = await getIssueById(merge.id);
|
||||
|
||||
if (pr && pr.labels.find(({name})=> name === label)) {
|
||||
const {reactions, body} = pr;
|
||||
prs[pr.number] = pr;
|
||||
pr.isHot = pr.comments > comments_threshold;
|
||||
const points = reactions['+1'] +
|
||||
reactions['hooray'] + reactions['rocket'] + reactions['heart'] + reactions['laugh'] - reactions['-1'];
|
||||
|
||||
pr.isAwesome = points > awesome_threshold;
|
||||
|
||||
let match;
|
||||
|
||||
pr.messages = [];
|
||||
|
||||
if (body) {
|
||||
const reg = /```+changelog\n*(.+?)?\n*```/gms;
|
||||
|
||||
while((match = reg.exec(body))) {
|
||||
match[1] && pr.messages.push(match[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
release.prs = Object.values(prs);
|
||||
|
||||
const compile = Handlebars.compile(String(await fs.readFile(template)))
|
||||
|
||||
const content = compile(release);
|
||||
|
||||
return removeExtraLineBreaks(cleanTemplate(content));
|
||||
}
|
||||
|
||||
const getTagRef = async (tag) => {
|
||||
try {
|
||||
return (await exec(`git show-ref --tags "refs/tags/${tag}"`)).stdout.split(' ')[0];
|
||||
} catch(e) {
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
renderContributorsList,
|
||||
getReleaseInfo,
|
||||
renderPRsList,
|
||||
getTagRef
|
||||
}
|
19
pkg/axios/bin/githubAxios.js
Normal file
@ -0,0 +1,19 @@
|
||||
import axios from '../index.js';
|
||||
import {colorize} from "./helpers/colorize.js";
|
||||
|
||||
const {GITHUB_TOKEN} = process.env;
|
||||
|
||||
GITHUB_TOKEN ? console.log(`[GITHUB_TOKEN OK]`) : console.warn(`[GITHUB_TOKEN is not defined]`);
|
||||
|
||||
const defaultTransform = axios.defaults.transformRequest;
|
||||
|
||||
export default axios.create({
|
||||
transformRequest: [defaultTransform[0], function (data) {
|
||||
console.log(colorize()`[${this.method.toUpperCase()}] Request [${new URL(axios.getUri(this)).pathname}]`);
|
||||
return data;
|
||||
}],
|
||||
baseURL: 'https://api.github.com/',
|
||||
headers: {
|
||||
Authorization: GITHUB_TOKEN ? `token ${GITHUB_TOKEN}` : null
|
||||
}
|
||||
});
|
14
pkg/axios/bin/helpers/colorize.js
Normal file
@ -0,0 +1,14 @@
|
||||
import chalk from 'chalk';
|
||||
|
||||
export const colorize = (...colors)=> {
|
||||
if(!colors.length) {
|
||||
colors = ['green', 'cyan', 'magenta', 'blue', 'yellow', 'red'];
|
||||
}
|
||||
|
||||
const colorsCount = colors.length;
|
||||
|
||||
return (strings, ...values) => {
|
||||
const {length} = values;
|
||||
return strings.map((str, i) => i < length ? str + chalk[colors[i%colorsCount]].bold(values[i]) : str).join('');
|
||||
}
|
||||
}
|
12
pkg/axios/bin/helpers/parser.js
Normal file
@ -0,0 +1,12 @@
|
||||
export const matchAll = (text, regexp, cb) => {
|
||||
let match;
|
||||
while((match = regexp.exec(text))) {
|
||||
cb(match);
|
||||
}
|
||||
}
|
||||
|
||||
export const parseSection = (body, name, cb) => {
|
||||
matchAll(body, new RegExp(`^(#+)\\s+${name}?(.*?)^\\1\\s+\\w+`, 'gims'), cb);
|
||||
}
|
||||
|
||||
export const parseVersion = (rawVersion) => /^v?(\d+).(\d+).(\d+)/.exec(rawVersion);
|
78
pkg/axios/bin/injectContributorsList.js
Normal file
@ -0,0 +1,78 @@
|
||||
import fs from 'fs/promises';
|
||||
import path from 'path';
|
||||
import {renderContributorsList, getTagRef, renderPRsList} from './contributors.js';
|
||||
import asyncReplace from 'string-replace-async';
|
||||
import {fileURLToPath} from "url";
|
||||
import {colorize} from "./helpers/colorize.js";
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
|
||||
const CONTRIBUTORS_TEMPLATE = path.resolve(__dirname, '../templates/contributors.hbs');
|
||||
const PRS_TEMPLATE = path.resolve(__dirname, '../templates/prs.hbs');
|
||||
|
||||
const injectSection = async (name, contributorsRE, injector, infile = '../CHANGELOG.md') => {
|
||||
console.log(colorize()`Checking ${name} sections in ${infile}`);
|
||||
|
||||
infile = path.resolve(__dirname, infile);
|
||||
|
||||
const content = String(await fs.readFile(infile));
|
||||
const headerRE = /^#+\s+\[([-_\d.\w]+)].+?$/mig;
|
||||
|
||||
let tag;
|
||||
let index = 0;
|
||||
let isFirstTag = true;
|
||||
|
||||
const newContent = await asyncReplace(content, headerRE, async (match, nextTag, offset) => {
|
||||
const releaseContent = content.slice(index, offset);
|
||||
|
||||
const hasSection = contributorsRE.test(releaseContent);
|
||||
|
||||
const currentTag = tag;
|
||||
|
||||
tag = nextTag;
|
||||
index = offset + match.length;
|
||||
|
||||
if(currentTag) {
|
||||
if (hasSection) {
|
||||
console.log(colorize()`[${currentTag}]: ✓ OK`);
|
||||
} else {
|
||||
const target = isFirstTag && (!await getTagRef(currentTag)) ? '' : currentTag;
|
||||
|
||||
console.log(colorize()`[${currentTag}]: ❌ MISSED` + (!target ? ' (UNRELEASED)' : ''));
|
||||
|
||||
isFirstTag = false;
|
||||
|
||||
console.log(`Generating section...`);
|
||||
|
||||
const section = await injector(target);
|
||||
|
||||
if (!section) {
|
||||
return match;
|
||||
}
|
||||
|
||||
console.log(colorize()`\nRENDERED SECTION [${name}] for [${currentTag}]:`);
|
||||
console.log('-------------BEGIN--------------\n');
|
||||
console.log(section);
|
||||
console.log('--------------END---------------\n');
|
||||
|
||||
return section + '\n' + match;
|
||||
}
|
||||
}
|
||||
|
||||
return match;
|
||||
});
|
||||
|
||||
await fs.writeFile(infile, newContent);
|
||||
}
|
||||
|
||||
await injectSection(
|
||||
'PRs',
|
||||
/^\s*### PRs/mi,
|
||||
(tag) => tag ? '' : renderPRsList(tag, PRS_TEMPLATE, {awesome_threshold: 5, comments_threshold: 7}),
|
||||
);
|
||||
|
||||
await injectSection(
|
||||
'contributors',
|
||||
/^\s*### Contributors/mi,
|
||||
(tag) => renderContributorsList(tag, CONTRIBUTORS_TEMPLATE)
|
||||
);
|
75
pkg/axios/bin/pr.js
Normal file
@ -0,0 +1,75 @@
|
||||
import util from "util";
|
||||
import cp from "child_process";
|
||||
import Handlebars from "handlebars";
|
||||
import fs from "fs/promises";
|
||||
import prettyBytes from 'pretty-bytes';
|
||||
import {gzipSize} from 'gzip-size';
|
||||
|
||||
const exec = util.promisify(cp.exec);
|
||||
|
||||
const getBlobHistory = async (filepath, maxCount= 5) => {
|
||||
const log = (await exec(
|
||||
`git log --max-count=${maxCount} --no-walk --tags=v* --oneline --format=%H%d -- ${filepath}`
|
||||
)).stdout;
|
||||
|
||||
const commits = [];
|
||||
|
||||
let match;
|
||||
|
||||
const regexp = /^(\w+) \(tag: (v?[.\d]+)\)$/gm;
|
||||
|
||||
while((match = regexp.exec(log))) {
|
||||
commits.push({
|
||||
sha: match[1],
|
||||
tag: match[2],
|
||||
size: await getBlobSize(filepath, match[1])
|
||||
})
|
||||
}
|
||||
|
||||
return commits;
|
||||
}
|
||||
|
||||
const getBlobSize = async (filepath, sha ='HEAD') => {
|
||||
const size = (await exec(
|
||||
`git cat-file -s ${sha}:${filepath}`
|
||||
)).stdout;
|
||||
|
||||
return size ? +size : 0;
|
||||
}
|
||||
|
||||
const generateFileReport = async (files) => {
|
||||
const stat = {};
|
||||
|
||||
for(const [name, file] of Object.entries(files)) {
|
||||
const commits = await getBlobHistory(file);
|
||||
|
||||
stat[file] = {
|
||||
name,
|
||||
size: (await fs.stat(file)).size,
|
||||
path: file,
|
||||
gzip: await gzipSize(String(await fs.readFile(file))),
|
||||
commits,
|
||||
history: commits.map(({tag, size}) => `${prettyBytes(size)} (${tag})`).join(' ← ')
|
||||
}
|
||||
}
|
||||
|
||||
return stat;
|
||||
}
|
||||
|
||||
const generateBody = async ({files, template = './templates/pr.hbs'} = {}) => {
|
||||
const data = {
|
||||
files: await generateFileReport(files)
|
||||
};
|
||||
|
||||
Handlebars.registerHelper('filesize', (bytes)=> prettyBytes(bytes));
|
||||
|
||||
return Handlebars.compile(String(await fs.readFile(template)))(data);
|
||||
}
|
||||
|
||||
console.log(await generateBody({
|
||||
files: {
|
||||
'Browser build (UMD)' : './dist/axios.min.js',
|
||||
'Browser build (ESM)' : './dist/esm/axios.min.js',
|
||||
}
|
||||
}));
|
||||
|
22
pkg/axios/bin/ssl_hotfix.js
Normal file
@ -0,0 +1,22 @@
|
||||
import {spawn} from 'child_process';
|
||||
|
||||
const args = process.argv.slice(2);
|
||||
|
||||
console.log(`Running ${args.join(' ')} on ${process.version}\n`);
|
||||
|
||||
const match = /v(\d+)/.exec(process.version);
|
||||
|
||||
const isHotfixNeeded = match && match[1] > 16;
|
||||
|
||||
isHotfixNeeded && console.warn('Setting --openssl-legacy-provider as ssl hotfix');
|
||||
|
||||
const test = spawn('cross-env',
|
||||
isHotfixNeeded ? ['NODE_OPTIONS=--openssl-legacy-provider', ...args] : args, {
|
||||
shell: true,
|
||||
stdio: 'inherit'
|
||||
}
|
||||
);
|
||||
|
||||
test.on('exit', function (code) {
|
||||
process.exit(code)
|
||||
})
|
3061
pkg/axios/dist/axios.js
vendored
Normal file
1
pkg/axios/dist/axios.js.map
vendored
Normal file
2
pkg/axios/dist/axios.min.js
vendored
Normal file
1
pkg/axios/dist/axios.min.js.map
vendored
Normal file
3234
pkg/axios/dist/browser/axios.cjs
vendored
Normal file
1
pkg/axios/dist/browser/axios.cjs.map
vendored
Normal file
3257
pkg/axios/dist/esm/axios.js
vendored
Normal file
1
pkg/axios/dist/esm/axios.js.map
vendored
Normal file
2
pkg/axios/dist/esm/axios.min.js
vendored
Normal file
1
pkg/axios/dist/esm/axios.min.js.map
vendored
Normal file
4327
pkg/axios/dist/node/axios.cjs
vendored
Normal file
1
pkg/axios/dist/node/axios.cjs.map
vendored
Normal file
221
pkg/jquery-mousewheel/jquery.mousewheel.js
Executable file
@ -0,0 +1,221 @@
|
||||
/*!
|
||||
* jQuery Mousewheel 3.1.13
|
||||
*
|
||||
* Copyright jQuery Foundation and other contributors
|
||||
* Released under the MIT license
|
||||
* http://jquery.org/license
|
||||
*/
|
||||
|
||||
(function (factory) {
|
||||
if ( typeof define === 'function' && define.amd ) {
|
||||
// AMD. Register as an anonymous module.
|
||||
define(['jquery'], factory);
|
||||
} else if (typeof exports === 'object') {
|
||||
// Node/CommonJS style for Browserify
|
||||
module.exports = factory;
|
||||
} else {
|
||||
// Browser globals
|
||||
factory(jQuery);
|
||||
}
|
||||
}(function ($) {
|
||||
|
||||
var toFix = ['wheel', 'mousewheel', 'DOMMouseScroll', 'MozMousePixelScroll'],
|
||||
toBind = ( 'onwheel' in document || document.documentMode >= 9 ) ?
|
||||
['wheel'] : ['mousewheel', 'DomMouseScroll', 'MozMousePixelScroll'],
|
||||
slice = Array.prototype.slice,
|
||||
nullLowestDeltaTimeout, lowestDelta;
|
||||
|
||||
if ( $.event.fixHooks ) {
|
||||
for ( var i = toFix.length; i; ) {
|
||||
$.event.fixHooks[ toFix[--i] ] = $.event.mouseHooks;
|
||||
}
|
||||
}
|
||||
|
||||
var special = $.event.special.mousewheel = {
|
||||
version: '3.1.12',
|
||||
|
||||
setup: function() {
|
||||
if ( this.addEventListener ) {
|
||||
for ( var i = toBind.length; i; ) {
|
||||
this.addEventListener( toBind[--i], handler, false );
|
||||
}
|
||||
} else {
|
||||
this.onmousewheel = handler;
|
||||
}
|
||||
// Store the line height and page height for this particular element
|
||||
$.data(this, 'mousewheel-line-height', special.getLineHeight(this));
|
||||
$.data(this, 'mousewheel-page-height', special.getPageHeight(this));
|
||||
},
|
||||
|
||||
teardown: function() {
|
||||
if ( this.removeEventListener ) {
|
||||
for ( var i = toBind.length; i; ) {
|
||||
this.removeEventListener( toBind[--i], handler, false );
|
||||
}
|
||||
} else {
|
||||
this.onmousewheel = null;
|
||||
}
|
||||
// Clean up the data we added to the element
|
||||
$.removeData(this, 'mousewheel-line-height');
|
||||
$.removeData(this, 'mousewheel-page-height');
|
||||
},
|
||||
|
||||
getLineHeight: function(elem) {
|
||||
var $elem = $(elem),
|
||||
$parent = $elem['offsetParent' in $.fn ? 'offsetParent' : 'parent']();
|
||||
if (!$parent.length) {
|
||||
$parent = $('body');
|
||||
}
|
||||
return parseInt($parent.css('fontSize'), 10) || parseInt($elem.css('fontSize'), 10) || 16;
|
||||
},
|
||||
|
||||
getPageHeight: function(elem) {
|
||||
return $(elem).height();
|
||||
},
|
||||
|
||||
settings: {
|
||||
adjustOldDeltas: true, // see shouldAdjustOldDeltas() below
|
||||
normalizeOffset: true // calls getBoundingClientRect for each event
|
||||
}
|
||||
};
|
||||
|
||||
$.fn.extend({
|
||||
mousewheel: function(fn) {
|
||||
return fn ? this.bind('mousewheel', fn) : this.trigger('mousewheel');
|
||||
},
|
||||
|
||||
unmousewheel: function(fn) {
|
||||
return this.unbind('mousewheel', fn);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
function handler(event) {
|
||||
var orgEvent = event || window.event,
|
||||
args = slice.call(arguments, 1),
|
||||
delta = 0,
|
||||
deltaX = 0,
|
||||
deltaY = 0,
|
||||
absDelta = 0,
|
||||
offsetX = 0,
|
||||
offsetY = 0;
|
||||
event = $.event.fix(orgEvent);
|
||||
event.type = 'mousewheel';
|
||||
|
||||
// Old school scrollwheel delta
|
||||
if ( 'detail' in orgEvent ) { deltaY = orgEvent.detail * -1; }
|
||||
if ( 'wheelDelta' in orgEvent ) { deltaY = orgEvent.wheelDelta; }
|
||||
if ( 'wheelDeltaY' in orgEvent ) { deltaY = orgEvent.wheelDeltaY; }
|
||||
if ( 'wheelDeltaX' in orgEvent ) { deltaX = orgEvent.wheelDeltaX * -1; }
|
||||
|
||||
// Firefox < 17 horizontal scrolling related to DOMMouseScroll event
|
||||
if ( 'axis' in orgEvent && orgEvent.axis === orgEvent.HORIZONTAL_AXIS ) {
|
||||
deltaX = deltaY * -1;
|
||||
deltaY = 0;
|
||||
}
|
||||
|
||||
// Set delta to be deltaY or deltaX if deltaY is 0 for backwards compatabilitiy
|
||||
delta = deltaY === 0 ? deltaX : deltaY;
|
||||
|
||||
// New school wheel delta (wheel event)
|
||||
if ( 'deltaY' in orgEvent ) {
|
||||
deltaY = orgEvent.deltaY * -1;
|
||||
delta = deltaY;
|
||||
}
|
||||
if ( 'deltaX' in orgEvent ) {
|
||||
deltaX = orgEvent.deltaX;
|
||||
if ( deltaY === 0 ) { delta = deltaX * -1; }
|
||||
}
|
||||
|
||||
// No change actually happened, no reason to go any further
|
||||
if ( deltaY === 0 && deltaX === 0 ) { return; }
|
||||
|
||||
// Need to convert lines and pages to pixels if we aren't already in pixels
|
||||
// There are three delta modes:
|
||||
// * deltaMode 0 is by pixels, nothing to do
|
||||
// * deltaMode 1 is by lines
|
||||
// * deltaMode 2 is by pages
|
||||
if ( orgEvent.deltaMode === 1 ) {
|
||||
var lineHeight = $.data(this, 'mousewheel-line-height');
|
||||
delta *= lineHeight;
|
||||
deltaY *= lineHeight;
|
||||
deltaX *= lineHeight;
|
||||
} else if ( orgEvent.deltaMode === 2 ) {
|
||||
var pageHeight = $.data(this, 'mousewheel-page-height');
|
||||
delta *= pageHeight;
|
||||
deltaY *= pageHeight;
|
||||
deltaX *= pageHeight;
|
||||
}
|
||||
|
||||
// Store lowest absolute delta to normalize the delta values
|
||||
absDelta = Math.max( Math.abs(deltaY), Math.abs(deltaX) );
|
||||
|
||||
if ( !lowestDelta || absDelta < lowestDelta ) {
|
||||
lowestDelta = absDelta;
|
||||
|
||||
// Adjust older deltas if necessary
|
||||
if ( shouldAdjustOldDeltas(orgEvent, absDelta) ) {
|
||||
lowestDelta /= 40;
|
||||
}
|
||||
}
|
||||
|
||||
// Adjust older deltas if necessary
|
||||
if ( shouldAdjustOldDeltas(orgEvent, absDelta) ) {
|
||||
// Divide all the things by 40!
|
||||
delta /= 40;
|
||||
deltaX /= 40;
|
||||
deltaY /= 40;
|
||||
}
|
||||
|
||||
// Get a whole, normalized value for the deltas
|
||||
delta = Math[ delta >= 1 ? 'floor' : 'ceil' ](delta / lowestDelta);
|
||||
deltaX = Math[ deltaX >= 1 ? 'floor' : 'ceil' ](deltaX / lowestDelta);
|
||||
deltaY = Math[ deltaY >= 1 ? 'floor' : 'ceil' ](deltaY / lowestDelta);
|
||||
|
||||
// Normalise offsetX and offsetY properties
|
||||
if ( special.settings.normalizeOffset && this.getBoundingClientRect ) {
|
||||
var boundingRect = this.getBoundingClientRect();
|
||||
offsetX = event.clientX - boundingRect.left;
|
||||
offsetY = event.clientY - boundingRect.top;
|
||||
}
|
||||
|
||||
// Add information to the event object
|
||||
event.deltaX = deltaX;
|
||||
event.deltaY = deltaY;
|
||||
event.deltaFactor = lowestDelta;
|
||||
event.offsetX = offsetX;
|
||||
event.offsetY = offsetY;
|
||||
// Go ahead and set deltaMode to 0 since we converted to pixels
|
||||
// Although this is a little odd since we overwrite the deltaX/Y
|
||||
// properties with normalized deltas.
|
||||
event.deltaMode = 0;
|
||||
|
||||
// Add event and delta to the front of the arguments
|
||||
args.unshift(event, delta, deltaX, deltaY);
|
||||
|
||||
// Clearout lowestDelta after sometime to better
|
||||
// handle multiple device types that give different
|
||||
// a different lowestDelta
|
||||
// Ex: trackpad = 3 and mouse wheel = 120
|
||||
if (nullLowestDeltaTimeout) { clearTimeout(nullLowestDeltaTimeout); }
|
||||
nullLowestDeltaTimeout = setTimeout(nullLowestDelta, 200);
|
||||
|
||||
return ($.event.dispatch || $.event.handle).apply(this, args);
|
||||
}
|
||||
|
||||
function nullLowestDelta() {
|
||||
lowestDelta = null;
|
||||
}
|
||||
|
||||
function shouldAdjustOldDeltas(orgEvent, absDelta) {
|
||||
// If this is an older event and the delta is divisable by 120,
|
||||
// then we are assuming that the browser is treating this as an
|
||||
// older mouse wheel event and that we should divide the deltas
|
||||
// by 40 to try and get a more usable deltaFactor.
|
||||
// Side note, this actually impacts the reported scroll distance
|
||||
// in older browsers and can cause scrolling to be slower than native.
|
||||
// Turn this off by setting $.event.special.mousewheel.settings.adjustOldDeltas to false.
|
||||
return special.settings.adjustOldDeltas && orgEvent.type === 'mousewheel' && absDelta % 120 === 0;
|
||||
}
|
||||
|
||||
}));
|
8
pkg/jquery-mousewheel/jquery.mousewheel.min.js
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
/*!
|
||||
* jQuery Mousewheel 3.1.13
|
||||
*
|
||||
* Copyright 2015 jQuery Foundation and other contributors
|
||||
* Released under the MIT license.
|
||||
* http://jquery.org/license
|
||||
*/
|
||||
!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):"object"==typeof exports?module.exports=a:a(jQuery)}(function(a){function b(b){var g=b||window.event,h=i.call(arguments,1),j=0,l=0,m=0,n=0,o=0,p=0;if(b=a.event.fix(g),b.type="mousewheel","detail"in g&&(m=-1*g.detail),"wheelDelta"in g&&(m=g.wheelDelta),"wheelDeltaY"in g&&(m=g.wheelDeltaY),"wheelDeltaX"in g&&(l=-1*g.wheelDeltaX),"axis"in g&&g.axis===g.HORIZONTAL_AXIS&&(l=-1*m,m=0),j=0===m?l:m,"deltaY"in g&&(m=-1*g.deltaY,j=m),"deltaX"in g&&(l=g.deltaX,0===m&&(j=-1*l)),0!==m||0!==l){if(1===g.deltaMode){var q=a.data(this,"mousewheel-line-height");j*=q,m*=q,l*=q}else if(2===g.deltaMode){var r=a.data(this,"mousewheel-page-height");j*=r,m*=r,l*=r}if(n=Math.max(Math.abs(m),Math.abs(l)),(!f||f>n)&&(f=n,d(g,n)&&(f/=40)),d(g,n)&&(j/=40,l/=40,m/=40),j=Math[j>=1?"floor":"ceil"](j/f),l=Math[l>=1?"floor":"ceil"](l/f),m=Math[m>=1?"floor":"ceil"](m/f),k.settings.normalizeOffset&&this.getBoundingClientRect){var s=this.getBoundingClientRect();o=b.clientX-s.left,p=b.clientY-s.top}return b.deltaX=l,b.deltaY=m,b.deltaFactor=f,b.offsetX=o,b.offsetY=p,b.deltaMode=0,h.unshift(b,j,l,m),e&&clearTimeout(e),e=setTimeout(c,200),(a.event.dispatch||a.event.handle).apply(this,h)}}function c(){f=null}function d(a,b){return k.settings.adjustOldDeltas&&"mousewheel"===a.type&&b%120===0}var e,f,g=["wheel","mousewheel","DOMMouseScroll","MozMousePixelScroll"],h="onwheel"in document||document.documentMode>=9?["wheel"]:["mousewheel","DomMouseScroll","MozMousePixelScroll"],i=Array.prototype.slice;if(a.event.fixHooks)for(var j=g.length;j;)a.event.fixHooks[g[--j]]=a.event.mouseHooks;var k=a.event.special.mousewheel={version:"3.1.12",setup:function(){if(this.addEventListener)for(var c=h.length;c;)this.addEventListener(h[--c],b,!1);else this.onmousewheel=b;a.data(this,"mousewheel-line-height",k.getLineHeight(this)),a.data(this,"mousewheel-page-height",k.getPageHeight(this))},teardown:function(){if(this.removeEventListener)for(var c=h.length;c;)this.removeEventListener(h[--c],b,!1);else this.onmousewheel=null;a.removeData(this,"mousewheel-line-height"),a.removeData(this,"mousewheel-page-height")},getLineHeight:function(b){var c=a(b),d=c["offsetParent"in a.fn?"offsetParent":"parent"]();return d.length||(d=a("body")),parseInt(d.css("fontSize"),10)||parseInt(c.css("fontSize"),10)||16},getPageHeight:function(b){return a(b).height()},settings:{adjustOldDeltas:!0,normalizeOffset:!0}};a.fn.extend({mousewheel:function(a){return a?this.bind("mousewheel",a):this.trigger("mousewheel")},unmousewheel:function(a){return this.unbind("mousewheel",a)}})});
|
2
pkg/jquery.ajax/jquery.min.js
vendored
Normal file
19
pkg/jquery.hotkeys/hotkeys-blog.js
Normal file
@ -0,0 +1,19 @@
|
||||
$(function(){
|
||||
|
||||
$(document).bind('keydown','ctrl+return',
|
||||
function(){
|
||||
window.location.href = '/blog';
|
||||
}
|
||||
)
|
||||
|
||||
$(document).bind('keydown', 'Shift+j',
|
||||
function(){
|
||||
if (document.activeElement !== document.body){
|
||||
$(".article-nav-link-wrap:focus").closest("li").next().find("a.lmove").focus();
|
||||
} else {
|
||||
$('#article-nav-older').focus();
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
});
|
16
pkg/jquery.hotkeys/hotkeys.js
Normal file
@ -0,0 +1,16 @@
|
||||
$(function(){
|
||||
$(document).bind('keydown','ctrl+return',
|
||||
function(){
|
||||
$("home-layout").toggle();
|
||||
$('#terminal').click();
|
||||
var element=document.getElementById("window");
|
||||
var rect=element.getBoundingClientRect();
|
||||
var positionX=rect.left+window.pageXOffset;
|
||||
var positionY=rect.top+window.pageYOffset;
|
||||
window.scrollTo(positionX,positionY);
|
||||
})
|
||||
$('.move').click(
|
||||
function(){
|
||||
this.focus();
|
||||
});
|
||||
});
|
1
pkg/jquery.hotkeys/jquery.hotkeys.js
Normal file
@ -0,0 +1 @@
|
||||
(function(jQuery){jQuery.hotkeys={version:"0.2.0",specialKeys:{8:"backspace",9:"tab",10:"return",13:"return",16:"shift",17:"ctrl",18:"alt",19:"pause",20:"capslock",27:"esc",32:"space",33:"pageup",34:"pagedown",35:"end",36:"home",37:"left",38:"up",39:"right",40:"down",45:"insert",46:"del",59:";",61:"=",96:"0",97:"1",98:"2",99:"3",100:"4",101:"5",102:"6",103:"7",104:"8",105:"9",106:"*",107:"+",109:"-",110:".",111:"/",112:"f1",113:"f2",114:"f3",115:"f4",116:"f5",117:"f6",118:"f7",119:"f8",120:"f9",121:"f10",122:"f11",123:"f12",144:"numlock",145:"scroll",173:"-",186:";",187:"=",188:",",189:"-",190:".",191:"/",192:"`",219:"[",220:"\\",221:"]",222:"'"},shiftNums:{"`":"~","1":"!","2":"@","3":"#","4":"$","5":"%","6":"^","7":"&","8":"*","9":"(","0":")","-":"_","=":"+",";":": ","'":"\"",",":"<",".":">","/":"?","\\":"|"},textAcceptingInputTypes:["text","password","number","email","url","range","date","month","week","time","datetime","datetime-local","search","color","tel"],textInputTypes:/textarea|input|select/i,options:{filterInputAcceptingElements:true,filterTextInputs:true,filterContentEditable:true}};function keyHandler(handleObj){if(typeof handleObj.data==="string"){handleObj.data={keys:handleObj.data};}if(!handleObj.data||!handleObj.data.keys||typeof handleObj.data.keys!=="string"){return;}var origHandler=handleObj.handler,keys=handleObj.data.keys.toLowerCase().split(" ");handleObj.handler=function(event){if(this!==event.target&&(jQuery.hotkeys.options.filterInputAcceptingElements&&jQuery.hotkeys.textInputTypes.test(event.target.nodeName)||(jQuery.hotkeys.options.filterContentEditable&&jQuery(event.target).attr('contenteditable'))||(jQuery.hotkeys.options.filterTextInputs&&jQuery.inArray(event.target.type,jQuery.hotkeys.textAcceptingInputTypes)>-1))){return;}var special=event.type!=="keypress"&&jQuery.hotkeys.specialKeys[event.which],character=String.fromCharCode(event.which).toLowerCase(),modif="",possible={};jQuery.each(["alt","ctrl","shift"],function(index,specialKey){if(event[specialKey+'Key']&&special!==specialKey){modif+=specialKey+'+';}});if(event.metaKey&&!event.ctrlKey&&special!=="meta"){modif+="meta+";}if(event.metaKey&&special!=="meta"&&modif.indexOf("alt+ctrl+shift+")>-1){modif=modif.replace("alt+ctrl+shift+","hyper+");}if(special){possible[modif+special]=true;}else{possible[modif+character]=true;possible[modif+jQuery.hotkeys.shiftNums[character]]=true;if(modif==="shift+"){possible[jQuery.hotkeys.shiftNums[character]]=true;}}for(var i=0,l=keys.length;i<l;i++){if(possible[keys[i]]){return origHandler.apply(this,arguments);}}};}jQuery.each(["keydown","keyup","keypress"],function(){jQuery.event.special[this]={add:keyHandler};});})(jQuery||this.jQuery||window.jQuery);
|
BIN
pkg/jquery.terminal/bin/yuicompressor-2.4.8.jar
Normal file
249
pkg/jquery.terminal/css/jquery.terminal.css
Normal file
@ -0,0 +1,249 @@
|
||||
/*!
|
||||
* __ _____ ________ __
|
||||
* / // _ /__ __ _____ ___ __ _/__ ___/__ ___ ______ __ __ __ ___ / /
|
||||
* __ / // // // // // _ // _// // / / // _ // _// // // \/ // _ \/ /
|
||||
* / / // // // // // ___// / / // / / // ___// / / / / // // /\ // // / /__
|
||||
* \___//____ \\___//____//_/ _\_ / /_//____//_/ /_/ /_//_//_/ /_/ \__\_\___/
|
||||
* \/ /____/ version 0.10.8
|
||||
* http://terminal.jcubic.pl
|
||||
*
|
||||
* This file is part of jQuery Terminal.
|
||||
*
|
||||
* Copyright (c) 2011-2016 Jakub Jankiewicz <http://jcubic.pl>
|
||||
* Released under the MIT license
|
||||
*
|
||||
* Date: Tue, 17 May 2016 09:01:55 +0000
|
||||
*/
|
||||
.terminal .terminal-output .format, .cmd .format,
|
||||
.cmd .prompt, .cmd .prompt div, .terminal .terminal-output div div{
|
||||
display: inline-block;
|
||||
}
|
||||
.terminal h1, .terminal h2, .terminal h3, .terminal h4, .terminal h5, .terminal h6, .terminal pre, .cmd {
|
||||
margin: 0;
|
||||
}
|
||||
.terminal h1, .terminal h2, .terminal h3, .terminal h4, .terminal h5, .terminal h6 {
|
||||
line-height: 1.2em;
|
||||
}
|
||||
/*
|
||||
.cmd .mask {
|
||||
width: 10px;
|
||||
height: 11px;
|
||||
background: black;
|
||||
z-index: 100;
|
||||
}
|
||||
*/
|
||||
.cmd .clipboard {
|
||||
position: absolute;
|
||||
height: 16px;
|
||||
left: -6px;
|
||||
/* this seems to work after all on Android */
|
||||
/*left: -99999px;
|
||||
clip: rect(1px,1px,1px,1px);
|
||||
/* on desktop textarea appear when paste */
|
||||
/*
|
||||
opacity: 0.01;
|
||||
filter: alpha(opacity = 0.01);
|
||||
filter: progid:DXImageTransform.Microsoft.Alpha(opacity=0.01);
|
||||
*/
|
||||
width: 5px; /* textarea need to have width or it will not work on Android */
|
||||
background: transparent;
|
||||
border: none;
|
||||
color: transparent;
|
||||
outline: none;
|
||||
padding: 0;
|
||||
resize: none;
|
||||
z-index: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
.terminal .error {
|
||||
color: #f00;
|
||||
}
|
||||
.terminal {
|
||||
padding: 10px;
|
||||
position: relative;
|
||||
/*overflow: hidden;*/
|
||||
overflow: auto;
|
||||
}
|
||||
.cmd {
|
||||
padding: 0;
|
||||
height: 1.3em;
|
||||
position: relative;
|
||||
/*margin-top: 3px; */
|
||||
}
|
||||
.terminal .inverted, .cmd .inverted, .cmd .cursor.blink {
|
||||
background-color: #aaa;
|
||||
color: #000;
|
||||
}
|
||||
.cmd .cursor.blink {
|
||||
-webkit-animation: terminal-blink 1s infinite steps(1, start);
|
||||
-moz-animation: terminal-blink 1s infinite steps(1, start);
|
||||
-ms-animation: terminal-blink 1s infinite steps(1, start);
|
||||
animation: terminal-blink 1s infinite steps(1, start);
|
||||
}
|
||||
@-webkit-keyframes terminal-blink {
|
||||
0%, 100% {
|
||||
background-color: #000;
|
||||
color: #aaa;
|
||||
}
|
||||
50% {
|
||||
background-color: #bbb;
|
||||
color: #000;
|
||||
}
|
||||
}
|
||||
|
||||
@-ms-keyframes terminal-blink {
|
||||
0%, 100% {
|
||||
background-color: #000;
|
||||
color: #aaa;
|
||||
}
|
||||
50% {
|
||||
background-color: #bbb;
|
||||
color: #000;
|
||||
}
|
||||
}
|
||||
|
||||
@-moz-keyframes terminal-blink {
|
||||
0%, 100% {
|
||||
background-color: #000;
|
||||
color: #aaa;
|
||||
}
|
||||
50% {
|
||||
background-color: #bbb;
|
||||
color: #000;
|
||||
}
|
||||
}
|
||||
@keyframes terminal-blink {
|
||||
0%, 100% {
|
||||
background-color: #000;
|
||||
color: #aaa;
|
||||
}
|
||||
50% {
|
||||
background-color: #bbb; /* not #aaa because it's seems there is Google Chrome bug */
|
||||
color: #000;
|
||||
}
|
||||
}
|
||||
|
||||
.terminal .terminal-output div div, .cmd .prompt {
|
||||
display: block;
|
||||
line-height: 14px;
|
||||
height: auto;
|
||||
}
|
||||
.cmd .prompt {
|
||||
float: left;
|
||||
}
|
||||
.terminal, .cmd {
|
||||
font-family: SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace;
|
||||
color: #aaa;
|
||||
background-color: #000;
|
||||
font-size: 14px;
|
||||
line-height: 16px;
|
||||
padding-bottom:3px;
|
||||
}
|
||||
.terminal-output > div {
|
||||
/*padding-top: 3px;*/
|
||||
min-height: 14px;
|
||||
}
|
||||
.terminal .terminal-output div span {
|
||||
display: inline-block;
|
||||
}
|
||||
.cmd span {
|
||||
float: left;
|
||||
/*display: inline-block; */
|
||||
}
|
||||
/* fix double style of selecting text in terminal */
|
||||
.terminal-output span, .terminal-output a, .cmd div, .cmd span, .terminal td,
|
||||
.terminal pre, .terminal h1, .terminal h2, .terminal h3, .terminal h4,
|
||||
.terminal h5, .terminal h6 {
|
||||
-webkit-touch-callout: initial;
|
||||
-webkit-user-select: initial;
|
||||
-khtml-user-select: initial;
|
||||
-moz-user-select: initial;
|
||||
-ms-user-select: initial;
|
||||
user-select: initial;
|
||||
}
|
||||
.terminal, .terminal-output, .terminal-output div {
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
/* firefox hack */
|
||||
@-moz-document url-prefix() {
|
||||
.terminal, .terminal-output, .terminal-output div {
|
||||
-webkit-touch-callout: initial;
|
||||
-webkit-user-select: initial;
|
||||
-khtml-user-select: initial;
|
||||
-moz-user-select: initial;
|
||||
-ms-user-select: initial;
|
||||
user-select: initial;
|
||||
}
|
||||
}
|
||||
.terminal table {
|
||||
border-collapse: collapse;
|
||||
}
|
||||
.terminal td {
|
||||
border: 1px solid #aaa;
|
||||
}
|
||||
.terminal h1::-moz-selection,
|
||||
.terminal h2::-moz-selection,
|
||||
.terminal h3::-moz-selection,
|
||||
.terminal h4::-moz-selection,
|
||||
.terminal h5::-moz-selection,
|
||||
.terminal h6::-moz-selection,
|
||||
.terminal pre::-moz-selection,
|
||||
.terminal td::-moz-selection,
|
||||
.terminal .terminal-output div div::-moz-selection,
|
||||
.terminal .terminal-output div span::-moz-selection,
|
||||
.terminal .terminal-output div div a::-moz-selection,
|
||||
.cmd div::-moz-selection,
|
||||
.cmd > span::-moz-selection,
|
||||
.cmd .prompt span::-moz-selection {
|
||||
background-color: #aaa;
|
||||
color: #000;
|
||||
}
|
||||
/* this don't work in Chrome
|
||||
.terminal tr td::-moz-selection {
|
||||
border-color: #000;
|
||||
}
|
||||
.terminal tr td::selection {
|
||||
border-color: #000;
|
||||
}
|
||||
*/
|
||||
.terminal h1::selection,
|
||||
.terminal h2::selection,
|
||||
.terminal h3::selection,
|
||||
.terminal h4::selection,
|
||||
.terminal h5::selection,
|
||||
.terminal h6::selection,
|
||||
.terminal pre::selection,
|
||||
.terminal td::selection,
|
||||
.terminal .terminal-output div div::selection,
|
||||
.terminal .terminal-output div div a::selection,
|
||||
.terminal .terminal-output div span::selection,
|
||||
.cmd div::selection,
|
||||
.cmd > span::selection,
|
||||
.cmd .prompt span::selection {
|
||||
background-color: #aaa;
|
||||
color: #000;
|
||||
}
|
||||
.terminal .terminal-output div.error, .terminal .terminal-output div.error div {
|
||||
color: red;
|
||||
}
|
||||
.tilda {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
z-index: 1100;
|
||||
}
|
||||
.clear {
|
||||
clear: both;
|
||||
}
|
||||
.terminal a {
|
||||
color: #0F60FF;
|
||||
}
|
||||
.terminal a:hover {
|
||||
color: red;
|
||||
}
|
1
pkg/jquery.terminal/css/jquery.terminal.min.css
vendored
Normal file
@ -0,0 +1 @@
|
||||
.terminal .terminal-output .format,.cmd .format,.cmd .prompt,.cmd .prompt div,.terminal .terminal-output div div{display:inline-block}.terminal h1,.terminal h2,.terminal h3,.terminal h4,.terminal h5,.terminal h6,.terminal pre,.cmd{margin:0}.terminal h1,.terminal h2,.terminal h3,.terminal h4,.terminal h5,.terminal h6{line-height:1.2em}.cmd .clipboard{position:absolute;height:16px;left:-6px;width:5px;background:transparent;border:0;color:transparent;outline:0;padding:0;resize:none;z-index:0;overflow:hidden}.terminal .error{color:red}.terminal{padding:10px;position:relative;overflow:auto}.cmd{padding:0;height:1.3em;position:relative}.terminal .inverted,.cmd .inverted,.cmd .cursor.blink{background-color:#aaa;color:#000}.cmd .cursor.blink{-webkit-animation:terminal-blink 1s infinite steps(1,start);-moz-animation:terminal-blink 1s infinite steps(1,start);-ms-animation:terminal-blink 1s infinite steps(1,start);animation:terminal-blink 1s infinite steps(1,start)}@-webkit-keyframes terminal-blink{0,100%{background-color:#000;color:#aaa}50%{background-color:#bbb;color:#000}}@-ms-keyframes terminal-blink{0,100%{background-color:#000;color:#aaa}50%{background-color:#bbb;color:#000}}@-moz-keyframes terminal-blink{0,100%{background-color:#000;color:#aaa}50%{background-color:#bbb;color:#000}}@keyframes terminal-blink{0,100%{background-color:#000;color:#aaa}50%{background-color:#bbb;color:#000}}.terminal .terminal-output div div,.cmd .prompt{display:block;line-height:14px;height:auto}.cmd .prompt{float:left}.terminal,.cmd{font-family:monospace;color:#aaa;background-color:#000;font-size:12px;line-height:14px}.terminal-output>div{min-height:14px}.terminal .terminal-output div span{display:inline-block}.cmd span{float:left}.terminal-output span,.terminal-output a,.cmd div,.cmd span,.terminal td,.terminal pre,.terminal h1,.terminal h2,.terminal h3,.terminal h4,.terminal h5,.terminal h6{-webkit-touch-callout:initial;-webkit-user-select:initial;-khtml-user-select:initial;-moz-user-select:initial;-ms-user-select:initial;user-select:initial}.terminal,.terminal-output,.terminal-output div{-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}@-moz-document url-prefix(){.terminal,.terminal-output,.terminal-output div{-webkit-touch-callout:initial;-webkit-user-select:initial;-khtml-user-select:initial;-moz-user-select:initial;-ms-user-select:initial;user-select:initial}}.terminal table{border-collapse:collapse}.terminal td{border:1px solid #aaa}.terminal h1::-moz-selection,.terminal h2::-moz-selection,.terminal h3::-moz-selection,.terminal h4::-moz-selection,.terminal h5::-moz-selection,.terminal h6::-moz-selection,.terminal pre::-moz-selection,.terminal td::-moz-selection,.terminal .terminal-output div div::-moz-selection,.terminal .terminal-output div span::-moz-selection,.terminal .terminal-output div div a::-moz-selection,.cmd div::-moz-selection,.cmd>span::-moz-selection,.cmd .prompt span::-moz-selection{background-color:#aaa;color:#000}.terminal h1::selection,.terminal h2::selection,.terminal h3::selection,.terminal h4::selection,.terminal h5::selection,.terminal h6::selection,.terminal pre::selection,.terminal td::selection,.terminal .terminal-output div div::selection,.terminal .terminal-output div div a::selection,.terminal .terminal-output div span::selection,.cmd div::selection,.cmd>span::selection,.cmd .prompt span::selection{background-color:#aaa;color:#000}.terminal .terminal-output div.error,.terminal .terminal-output div.error div{color:red}.tilda{position:fixed;top:0;left:0;width:100%;z-index:1100}.clear{clear:both}.terminal a{color:#0f60ff}.terminal a:hover{color:red}
|
113
pkg/jquery.terminal/js/ascii_table.js
Normal file
@ -0,0 +1,113 @@
|
||||
/**@license
|
||||
* __ _____ ________ __
|
||||
* / // _ /__ __ _____ ___ __ _/__ ___/__ ___ ______ __ __ __ ___ / /
|
||||
* __ / // // // // // _ // _// // / / // _ // _// // // \/ // _ \/ /
|
||||
* / / // // // // // ___// / / // / / // ___// / / / / // // /\ // // / /__
|
||||
* \___//____ \\___//____//_/ _\_ / /_//____//_/ /_/ /_//_//_/ /_/ \__\_\___/
|
||||
* \/ /____/
|
||||
* http://terminal.jcubic.pl
|
||||
*
|
||||
* utility that renders simple ascii table, like the one from mysql cli tool
|
||||
* it was first created for leash shell https://leash.jcubic.pl
|
||||
*
|
||||
* usage:
|
||||
*
|
||||
* var arr = [[1,2,3,4,5], ["lorem", "ipsum", "dolor", "sit", "amet"]];
|
||||
* term.echo(ascii_table(arr));
|
||||
* // or
|
||||
* term.echo(ascii_table(arr, true)); // this will render first row as header
|
||||
*
|
||||
* Copyright (c) 2018-2019 Jakub Jankiewicz <https://jcubic.pl/me>
|
||||
* Released under the MIT license
|
||||
*
|
||||
*/
|
||||
/* global define, module, global, wcwidth, require */
|
||||
(function(factory) {
|
||||
var root = typeof window !== 'undefined' ? window : global;
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
// AMD. Register as an anonymous module.
|
||||
define(['wcwidth'], function(wcwidth) {
|
||||
return (root.ascii_table = factory(wcwidth));
|
||||
});
|
||||
} else if (typeof module === 'object' && module.exports) {
|
||||
// Node/CommonJS
|
||||
module.exports = factory(require('wcwidth'));
|
||||
} else {
|
||||
root.ascii_table = factory(root.wcwidth);
|
||||
}
|
||||
})(function(wcwidth, undefined) {
|
||||
var strlen = (function() {
|
||||
if (typeof wcwidth === 'undefined') {
|
||||
return function(string) {
|
||||
return string.length;
|
||||
};
|
||||
} else {
|
||||
return wcwidth;
|
||||
}
|
||||
})();
|
||||
function ascii_table(array, header) {
|
||||
if (!array.length) {
|
||||
return '';
|
||||
}
|
||||
for (var i = array.length - 1; i >= 0; i--) {
|
||||
var row = array[i];
|
||||
var stacks = [];
|
||||
for (var j = 0; j < row.length; j++) {
|
||||
var new_lines = row[j].toString().replace(/\r/g).split("\n");
|
||||
row[j] = new_lines.shift();
|
||||
stacks.push(new_lines);
|
||||
}
|
||||
var stack_lengths = stacks.map(function(column) {
|
||||
return column.length;
|
||||
});
|
||||
var new_rows_count = Math.max.apply(Math, stack_lengths);
|
||||
for (var k = new_rows_count - 1; k >= 0; k--) {
|
||||
array.splice(i + 1, 0, stacks.map(function(column) {
|
||||
return column[k] || "";
|
||||
}));
|
||||
}
|
||||
}
|
||||
var lengths = array[0].map(function(_, i) {
|
||||
var col = array.map(function(row) {
|
||||
if (row[i] != undefined) {
|
||||
var len = strlen(row[i]);
|
||||
if (row[i].match(/\t/g)) {
|
||||
// tab is 4 spaces
|
||||
len += row[i].match(/\t/g).length*3;
|
||||
}
|
||||
return len;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
return Math.max.apply(Math, col);
|
||||
});
|
||||
// column padding
|
||||
array = array.map(function(row) {
|
||||
return '| ' + row.map(function(item, i) {
|
||||
var size = strlen(item);
|
||||
if (item.match(/\t/g)) {
|
||||
// tab is 4 spaces
|
||||
size += item.match(/\t/g).length*3;
|
||||
}
|
||||
if (size < lengths[i]) {
|
||||
item += new Array(lengths[i] - size + 1).join(' ');
|
||||
}
|
||||
return item;
|
||||
}).join(' | ') + ' |';
|
||||
});
|
||||
array = array.map(function(line) {
|
||||
return line.replace(/&(?![^;]+;)/g, '&');
|
||||
});
|
||||
var sep = '+' + lengths.map(function(length) {
|
||||
return new Array(length + 3).join('-');
|
||||
}).join('+') + '+';
|
||||
if (header) {
|
||||
return sep + '\n' + array[0] + '\n' + sep + '\n' +
|
||||
array.slice(1).join('\n') + '\n' + sep;
|
||||
} else {
|
||||
return sep + '\n' + array.join('\n') + '\n' + sep;
|
||||
}
|
||||
}
|
||||
return ascii_table;
|
||||
});
|
69
pkg/jquery.terminal/js/dterm.js
Normal file
@ -0,0 +1,69 @@
|
||||
/*!
|
||||
* Example plugin using JQuery Terminal Emulator
|
||||
* Copyright (C) 2010-2016 Jakub Jankiewicz <http://jcubic.pl>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*/
|
||||
(function($) {
|
||||
$.extend_if_has = function(desc, source, array) {
|
||||
for (var i=array.length;i--;) {
|
||||
if (typeof source[array[i]] != 'undefined') {
|
||||
desc[array[i]] = source[array[i]];
|
||||
}
|
||||
}
|
||||
return desc;
|
||||
};
|
||||
$.fn.dterm = function(interpreter, options) {
|
||||
var op = $.extend_if_has({}, options,
|
||||
['greetings', 'prompt', 'onInit',
|
||||
'onExit', 'clear',
|
||||
'login', 'name', 'exit']);
|
||||
op.enabled = false;
|
||||
var terminal = this.terminal(interpreter, op).css('overflow', 'hidden');
|
||||
if (!options.title) {
|
||||
options.title = 'JQuery Terminal Emulator';
|
||||
}
|
||||
if (options.logoutOnClose) {
|
||||
options.close = function(e, ui) {
|
||||
terminal.logout();
|
||||
terminal.clear();
|
||||
};
|
||||
} else {
|
||||
options.close = function(e, ui) {
|
||||
terminal.disable();
|
||||
};
|
||||
}
|
||||
var self = this;
|
||||
this.dialog($.extend(options, {
|
||||
resizeStop: function(e, ui) {
|
||||
var content = self.find('.ui-dialog-content');
|
||||
terminal.resize(content.width(), content.height());
|
||||
},
|
||||
open: function(e, ui) {
|
||||
terminal.focus();
|
||||
terminal.resize();
|
||||
},
|
||||
show: 'fade',
|
||||
closeOnEscape: false
|
||||
}));
|
||||
self.terminal = terminal;
|
||||
return self;
|
||||
};
|
||||
})(jQuery);
|
2
pkg/jquery.terminal/js/jquery.mousewheel-min.js
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
(function(c){function g(a){var b=a||window.event,i=[].slice.call(arguments,1),e=0,h=0,f=0;a=c.event.fix(b);a.type="mousewheel";if(b.wheelDelta)e=b.wheelDelta/120;if(b.detail)e=-b.detail/3;f=e;if(b.axis!==undefined&&b.axis===b.HORIZONTAL_AXIS){f=0;h=-1*e}if(b.wheelDeltaY!==undefined)f=b.wheelDeltaY/120;if(b.wheelDeltaX!==undefined)h=-1*b.wheelDeltaX/120;i.unshift(a,e,h,f);return(c.event.dispatch||c.event.handle).apply(this,i)}var d=["DOMMouseScroll","mousewheel"];if(c.event.fixHooks)for(var j=d.length;j;)c.event.fixHooks[d[--j]]=
|
||||
c.event.mouseHooks;c.event.special.mousewheel={setup:function(){if(this.addEventListener)for(var a=d.length;a;)this.addEventListener(d[--a],g,false);else this.onmousewheel=g},teardown:function(){if(this.removeEventListener)for(var a=d.length;a;)this.removeEventListener(d[--a],g,false);else this.onmousewheel=null}};c.fn.extend({mousewheel:function(a){return a?this.bind("mousewheel",a):this.trigger("mousewheel")},unmousewheel:function(a){return this.unbind("mousewheel",a)}})})(jQuery);
|
37
pkg/jquery.terminal/js/jquery.terminal.min.js
vendored
Normal file
317
pkg/jquery.terminal/js/unix_formatting.js
Normal file
@ -0,0 +1,317 @@
|
||||
/**@license
|
||||
* __ _____ ________ __
|
||||
* / // _ /__ __ _____ ___ __ _/__ ___/__ ___ ______ __ __ __ ___ / /
|
||||
* __ / // // // // // _ // _// // / / // _ // _// // // \/ // _ \/ /
|
||||
* / / // // // // // ___// / / // / / // ___// / / / / // // /\ // // / /__
|
||||
* \___//____ \\___//____//_/ _\_ / /_//____//_/ /_/ /_//_//_/ /_/ \__\_\___/
|
||||
* \/ /____/
|
||||
* http://terminal.jcubic.pl
|
||||
*
|
||||
* This is example of how to create custom formatter for jQuery Terminal
|
||||
*
|
||||
* Copyright (c) 2014-2016 Jakub Jankiewicz <http://jcubic.pl>
|
||||
* Released under the MIT license
|
||||
*
|
||||
*/
|
||||
(function($) {
|
||||
if (!$.terminal) {
|
||||
throw new Error('$.terminal is not defined');
|
||||
}
|
||||
// ---------------------------------------------------------------------
|
||||
// :: Replace overtyping (from man) formatting with terminal formatting
|
||||
// ---------------------------------------------------------------------
|
||||
$.terminal.overtyping = function(string) {
|
||||
return string.replace(/((?:_\x08.|.\x08_)+)/g, function(full, g) {
|
||||
var striped = full.replace(/_x08|\x08_|_\u0008|\u0008_/g, '');
|
||||
return '[[u;;]' + striped + ']';
|
||||
}).replace(/((?:.\x08.)+)/g, function(full, g) {
|
||||
return '[[b;#fff;]' + full.replace(/(.)(?:\x08|\u0008)(.)/g,
|
||||
function(full, g1, g2) {
|
||||
return g2;
|
||||
}) + ']';
|
||||
});
|
||||
};
|
||||
// ---------------------------------------------------------------------
|
||||
// :: Html colors taken from ANSI formatting in Linux Terminal
|
||||
// ---------------------------------------------------------------------
|
||||
$.terminal.ansi_colors = {
|
||||
normal: {
|
||||
black: '#000',
|
||||
red: '#A00',
|
||||
green: '#008400',
|
||||
yellow: '#A50',
|
||||
blue: '#00A',
|
||||
magenta: '#A0A',
|
||||
cyan: '#0AA',
|
||||
white: '#AAA'
|
||||
},
|
||||
faited: {
|
||||
black: '#000',
|
||||
red: '#640000',
|
||||
green: '#006100',
|
||||
yellow: '#737300',
|
||||
blue: '#000087',
|
||||
magenta: '#650065',
|
||||
cyan: '#008787',
|
||||
white: '#818181'
|
||||
},
|
||||
bold: {
|
||||
black: '#000',
|
||||
red: '#F55',
|
||||
green: '#44D544',
|
||||
yellow: '#FF5',
|
||||
blue: '#55F',
|
||||
magenta: '#F5F',
|
||||
cyan: '#5FF',
|
||||
white: '#FFF'
|
||||
},
|
||||
// XTerm 8-bit pallete
|
||||
palette: [
|
||||
'#000000', '#AA0000', '#00AA00', '#AA5500', '#0000AA', '#AA00AA',
|
||||
'#00AAAA', '#AAAAAA', '#555555', '#FF5555', '#55FF55', '#FFFF55',
|
||||
'#5555FF', '#FF55FF', '#55FFFF', '#FFFFFF', '#000000', '#00005F',
|
||||
'#000087', '#0000AF', '#0000D7', '#0000FF', '#005F00', '#005F5F',
|
||||
'#005F87', '#005FAF', '#005FD7', '#005FFF', '#008700', '#00875F',
|
||||
'#008787', '#0087AF', '#0087D7', '#0087FF', '#00AF00', '#00AF5F',
|
||||
'#00AF87', '#00AFAF', '#00AFD7', '#00AFFF', '#00D700', '#00D75F',
|
||||
'#00D787', '#00D7AF', '#00D7D7', '#00D7FF', '#00FF00', '#00FF5F',
|
||||
'#00FF87', '#00FFAF', '#00FFD7', '#00FFFF', '#5F0000', '#5F005F',
|
||||
'#5F0087', '#5F00AF', '#5F00D7', '#5F00FF', '#5F5F00', '#5F5F5F',
|
||||
'#5F5F87', '#5F5FAF', '#5F5FD7', '#5F5FFF', '#5F8700', '#5F875F',
|
||||
'#5F8787', '#5F87AF', '#5F87D7', '#5F87FF', '#5FAF00', '#5FAF5F',
|
||||
'#5FAF87', '#5FAFAF', '#5FAFD7', '#5FAFFF', '#5FD700', '#5FD75F',
|
||||
'#5FD787', '#5FD7AF', '#5FD7D7', '#5FD7FF', '#5FFF00', '#5FFF5F',
|
||||
'#5FFF87', '#5FFFAF', '#5FFFD7', '#5FFFFF', '#870000', '#87005F',
|
||||
'#870087', '#8700AF', '#8700D7', '#8700FF', '#875F00', '#875F5F',
|
||||
'#875F87', '#875FAF', '#875FD7', '#875FFF', '#878700', '#87875F',
|
||||
'#878787', '#8787AF', '#8787D7', '#8787FF', '#87AF00', '#87AF5F',
|
||||
'#87AF87', '#87AFAF', '#87AFD7', '#87AFFF', '#87D700', '#87D75F',
|
||||
'#87D787', '#87D7AF', '#87D7D7', '#87D7FF', '#87FF00', '#87FF5F',
|
||||
'#87FF87', '#87FFAF', '#87FFD7', '#87FFFF', '#AF0000', '#AF005F',
|
||||
'#AF0087', '#AF00AF', '#AF00D7', '#AF00FF', '#AF5F00', '#AF5F5F',
|
||||
'#AF5F87', '#AF5FAF', '#AF5FD7', '#AF5FFF', '#AF8700', '#AF875F',
|
||||
'#AF8787', '#AF87AF', '#AF87D7', '#AF87FF', '#AFAF00', '#AFAF5F',
|
||||
'#AFAF87', '#AFAFAF', '#AFAFD7', '#AFAFFF', '#AFD700', '#AFD75F',
|
||||
'#AFD787', '#AFD7AF', '#AFD7D7', '#AFD7FF', '#AFFF00', '#AFFF5F',
|
||||
'#AFFF87', '#AFFFAF', '#AFFFD7', '#AFFFFF', '#D70000', '#D7005F',
|
||||
'#D70087', '#D700AF', '#D700D7', '#D700FF', '#D75F00', '#D75F5F',
|
||||
'#D75F87', '#D75FAF', '#D75FD7', '#D75FFF', '#D78700', '#D7875F',
|
||||
'#D78787', '#D787AF', '#D787D7', '#D787FF', '#D7AF00', '#D7AF5F',
|
||||
'#D7AF87', '#D7AFAF', '#D7AFD7', '#D7AFFF', '#D7D700', '#D7D75F',
|
||||
'#D7D787', '#D7D7AF', '#D7D7D7', '#D7D7FF', '#D7FF00', '#D7FF5F',
|
||||
'#D7FF87', '#D7FFAF', '#D7FFD7', '#D7FFFF', '#FF0000', '#FF005F',
|
||||
'#FF0087', '#FF00AF', '#FF00D7', '#FF00FF', '#FF5F00', '#FF5F5F',
|
||||
'#FF5F87', '#FF5FAF', '#FF5FD7', '#FF5FFF', '#FF8700', '#FF875F',
|
||||
'#FF8787', '#FF87AF', '#FF87D7', '#FF87FF', '#FFAF00', '#FFAF5F',
|
||||
'#FFAF87', '#FFAFAF', '#FFAFD7', '#FFAFFF', '#FFD700', '#FFD75F',
|
||||
'#FFD787', '#FFD7AF', '#FFD7D7', '#FFD7FF', '#FFFF00', '#FFFF5F',
|
||||
'#FFFF87', '#FFFFAF', '#FFFFD7', '#FFFFFF', '#080808', '#121212',
|
||||
'#1C1C1C', '#262626', '#303030', '#3A3A3A', '#444444', '#4E4E4E',
|
||||
'#585858', '#626262', '#6C6C6C', '#767676', '#808080', '#8A8A8A',
|
||||
'#949494', '#9E9E9E', '#A8A8A8', '#B2B2B2', '#BCBCBC', '#C6C6C6',
|
||||
'#D0D0D0', '#DADADA', '#E4E4E4', '#EEEEEE'
|
||||
]
|
||||
};
|
||||
// ---------------------------------------------------------------------
|
||||
// :: Replace ANSI formatting with terminal formatting
|
||||
// ---------------------------------------------------------------------
|
||||
$.terminal.from_ansi = (function() {
|
||||
var color_list = {
|
||||
30: 'black',
|
||||
31: 'red',
|
||||
32: 'green',
|
||||
33: 'yellow',
|
||||
34: 'blue',
|
||||
35: 'magenta',
|
||||
36: 'cyan',
|
||||
37: 'white',
|
||||
|
||||
39: 'inherit' // default color
|
||||
};
|
||||
var background_list = {
|
||||
40: 'black',
|
||||
41: 'red',
|
||||
42: 'green',
|
||||
43: 'yellow',
|
||||
44: 'blue',
|
||||
45: 'magenta',
|
||||
46: 'cyan',
|
||||
47: 'white',
|
||||
|
||||
49: 'transparent' // default background
|
||||
};
|
||||
function format_ansi(code) {
|
||||
var controls = code.split(';');
|
||||
var num;
|
||||
var faited = false;
|
||||
var reverse = false;
|
||||
var bold = false;
|
||||
var styles = [];
|
||||
var output_color = '';
|
||||
var output_background = '';
|
||||
var _8bit_color = false;
|
||||
var _8bit_background = false;
|
||||
var process_8bit = false;
|
||||
var palette = $.terminal.ansi_colors.palette;
|
||||
for(var i in controls) {
|
||||
if (controls.hasOwnProperty(i)) {
|
||||
num = parseInt(controls[i], 10);
|
||||
if (process_8bit && (_8bit_background || _8bit_color)) {
|
||||
if (_8bit_color && palette[num]) {
|
||||
output_color = palette[num];
|
||||
}
|
||||
if (_8bit_background && palette[num]) {
|
||||
output_background = palette[num];
|
||||
}
|
||||
} else {
|
||||
switch(num) {
|
||||
case 1:
|
||||
styles.push('b');
|
||||
bold = true;
|
||||
faited = false;
|
||||
break;
|
||||
case 4:
|
||||
styles.push('u');
|
||||
break;
|
||||
case 3:
|
||||
styles.push('i');
|
||||
break;
|
||||
case 5:
|
||||
process_8bit = true;
|
||||
break;
|
||||
case 38:
|
||||
_8bit_color = true;
|
||||
break;
|
||||
case 48:
|
||||
_8bit_background = true;
|
||||
break;
|
||||
case 2:
|
||||
faited = true;
|
||||
bold = false;
|
||||
break;
|
||||
case 7:
|
||||
reverse = true;
|
||||
break;
|
||||
default:
|
||||
if (controls.indexOf('5') == -1) {
|
||||
if (color_list[num]) {
|
||||
output_color = color_list[num];
|
||||
}
|
||||
if (background_list[num]) {
|
||||
output_background = background_list[num];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (reverse) {
|
||||
if (output_color || output_background) {
|
||||
var tmp = output_background;
|
||||
output_background = output_color;
|
||||
output_color = tmp;
|
||||
} else {
|
||||
output_color = 'black';
|
||||
output_background = 'white';
|
||||
}
|
||||
}
|
||||
var colors, color, background, backgrounds;
|
||||
if (bold) {
|
||||
colors = backgrounds = $.terminal.ansi_colors.bold;
|
||||
} else if (faited) {
|
||||
colors = backgrounds = $.terminal.ansi_colors.faited;
|
||||
} else {
|
||||
colors = backgrounds = $.terminal.ansi_colors.normal;
|
||||
}
|
||||
if (_8bit_color) {
|
||||
color = output_color;
|
||||
} else if (output_color == 'inherit') {
|
||||
color = output_color;
|
||||
} else {
|
||||
color = colors[output_color];
|
||||
}
|
||||
if (_8bit_background) {
|
||||
background = output_background;
|
||||
} else if (output_background == 'transparent') {
|
||||
background = output_background;
|
||||
} else {
|
||||
background = backgrounds[output_background];
|
||||
}
|
||||
return [styles.join(''), color, background];
|
||||
}
|
||||
return function(input) {
|
||||
//merge multiple codes
|
||||
/*input = input.replace(/((?:\x1B\[[0-9;]*[A-Za-z])*)/g, function(group) {
|
||||
return group.replace(/m\x1B\[/g, ';');
|
||||
});*/
|
||||
var splitted = input.split(/(\x1B\[[0-9;]*[A-Za-z])/g);
|
||||
if (splitted.length == 1) {
|
||||
return input;
|
||||
}
|
||||
var output = [];
|
||||
//skip closing at the begining
|
||||
if (splitted.length > 3) {
|
||||
var str = splitted.slice(0,3).join('');
|
||||
if (str == '[0m' || str == '[m') {
|
||||
splitted = splitted.slice(3);
|
||||
}
|
||||
}
|
||||
var next, prev_color, prev_background, code, match;
|
||||
var inside = false;
|
||||
for (var i=0; i<splitted.length; ++i) {
|
||||
match = splitted[i].match(/^\x1B\[([0-9;]*)([A-Za-z])$/);
|
||||
if (match) {
|
||||
switch (match[2]) {
|
||||
case 'm':
|
||||
if (match[1] !== '0') {
|
||||
code = format_ansi(match[1]);
|
||||
}
|
||||
if (inside) {
|
||||
output.push(']');
|
||||
if (match[1] === '0' || match[1] === '') {
|
||||
//just closing
|
||||
inside = false;
|
||||
prev_color = prev_background = '';
|
||||
} else {
|
||||
// someone forget to close - move to next
|
||||
code[1] = code[1] || prev_color;
|
||||
code[2] = code[2] || prev_background;
|
||||
output.push('[[' + code.join(';') + ']');
|
||||
// store colors to next use
|
||||
if (code[1]) {
|
||||
prev_color = code[1];
|
||||
}
|
||||
if (code[2]) {
|
||||
prev_background = code[2];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (match[1] != '0') {
|
||||
inside = true;
|
||||
code[1] = code[1] || prev_color;
|
||||
code[2] = code[2] || prev_background;
|
||||
output.push('[[' + code.join(';') + ']');
|
||||
// store colors to next use
|
||||
if (code[1]) {
|
||||
prev_color = code[1];
|
||||
}
|
||||
if (code[2]) {
|
||||
prev_background = code[2];
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
output.push(splitted[i]);
|
||||
}
|
||||
}
|
||||
if (inside) {
|
||||
output.push(']');
|
||||
}
|
||||
return output.join(''); //.replace(/\[\[[^\]]+\]\]/g, '');
|
||||
};
|
||||
})();
|
||||
$.terminal.defaults.formatters.push($.terminal.overtyping);
|
||||
$.terminal.defaults.formatters.push($.terminal.from_ansi);
|
||||
})(jQuery);
|
48
pkg/jquery.terminal/js/xml_formatting.js
Normal file
@ -0,0 +1,48 @@
|
||||
/**@license
|
||||
* __ _____ ________ __
|
||||
* / // _ /__ __ _____ ___ __ _/__ ___/__ ___ ______ __ __ __ ___ / /
|
||||
* __ / // // // // // _ // _// // / / // _ // _// // // \/ // _ \/ /
|
||||
* / / // // // // // ___// / / // / / // ___// / / / / // // /\ // // / /__
|
||||
* \___//____ \\___//____//_/ _\_ / /_//____//_/ /_/ /_//_//_/ /_/ \__\_\___/
|
||||
* \/ /____/
|
||||
* http://terminal.jcubic.pl
|
||||
*
|
||||
* This is example of how to create custom formatter for jQuery Terminal
|
||||
*
|
||||
* Copyright (c) 2014-2016 Jakub Jankiewicz <http://jcubic.pl>
|
||||
* Released under the MIT license
|
||||
*
|
||||
*/
|
||||
(function($) {
|
||||
if (!$.terminal) {
|
||||
throw new Error('$.terminal is not defined');
|
||||
}
|
||||
// this formatter allow to echo xml where tags are colors like:
|
||||
// <red>hello <navy>blue</navy> world</red>
|
||||
$.terminal.defaults.formatters.push(function(string) {
|
||||
var stack = [];
|
||||
var output = [];
|
||||
var parts = string.split(/(<\/?[a-zA-Z]+>)/);
|
||||
for (var i=0; i<parts.length; ++i) {
|
||||
if (parts[i][0] == '<') {
|
||||
if (parts[i][1] == '/') {
|
||||
if (stack.length) {
|
||||
stack.pop();
|
||||
}
|
||||
} else {
|
||||
stack.push(parts[i].replace(/^<|>$/g, ''));
|
||||
}
|
||||
} else {
|
||||
if (stack.length) {
|
||||
// top of the stack
|
||||
output.push('[[;' + stack[stack.length-1] + ';]');
|
||||
}
|
||||
output.push(parts[i]);
|
||||
if (stack.length) {
|
||||
output.push(']');
|
||||
}
|
||||
}
|
||||
}
|
||||
return output.join('');
|
||||
});
|
||||
})(jQuery);
|
688
pkg/jquery.terminal/spec/terminalSpec.js
Normal file
@ -0,0 +1,688 @@
|
||||
if (typeof window === 'undefined') {
|
||||
var node = true;
|
||||
var jsdom = require("jsdom");
|
||||
global.document = jsdom.jsdom();
|
||||
global.window = global.document.parentWindow;
|
||||
var navigator = {userAgent: "node-js", platform: "Linux i686"};
|
||||
global.window.navigator = global.navigator = navigator;
|
||||
global.jQuery = global.$ = require("jquery");
|
||||
require('../js/jquery.terminal-src');
|
||||
require('../js/unix_formatting');
|
||||
}
|
||||
describe('Terminal utils', function() {
|
||||
var command = 'test "foo bar" baz /^asd [x]/ str\\ str 10 1e10';
|
||||
var args = '"foo bar" baz /^asd [x]/ str\\ str 10 1e10';
|
||||
describe('$.terminal.split_arguments', function() {
|
||||
it('should create array of arguments', function() {
|
||||
expect($.terminal.split_arguments(args)).toEqual([
|
||||
'foo bar',
|
||||
'baz',
|
||||
'/^asd [x]/',
|
||||
'str str',
|
||||
'10',
|
||||
'1e10'
|
||||
]);
|
||||
});
|
||||
});
|
||||
describe('$.terminal.parse_arguments', function() {
|
||||
it('should create array of arguments and convert types', function() {
|
||||
expect($.terminal.parse_arguments(args)).toEqual([
|
||||
'foo bar',
|
||||
'baz',
|
||||
/^asd [x]/,
|
||||
'str str',
|
||||
10,
|
||||
1e10
|
||||
]);
|
||||
});
|
||||
});
|
||||
describe('$.terminal.split_command', function() {
|
||||
it('Should split command', function() {
|
||||
var cmd = jQuery.terminal.split_command(command);
|
||||
expect(cmd).toEqual({
|
||||
command: command,
|
||||
name: 'test',
|
||||
args: [
|
||||
'foo bar',
|
||||
'baz',
|
||||
'/^asd [x]/',
|
||||
'str str',
|
||||
'10',
|
||||
'1e10'
|
||||
],
|
||||
rest: '"foo bar" baz /^asd [x]/ str\\ str 10 1e10'
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('$.terminal.parse_command', function() {
|
||||
it('should split and parse command', function() {
|
||||
var cmd = jQuery.terminal.parse_command(command);
|
||||
expect(cmd).toEqual({
|
||||
command: command,
|
||||
name: 'test',
|
||||
args: [
|
||||
'foo bar',
|
||||
'baz',
|
||||
/^asd [x]/,
|
||||
'str str',
|
||||
10,
|
||||
1e10
|
||||
],
|
||||
rest: '"foo bar" baz /^asd [x]/ str\\ str 10 1e10'
|
||||
});
|
||||
});
|
||||
});
|
||||
var ansi_string = '\x1b[2;31;46mFoo\x1b[1;3;4;32;45mBar\x1b[0m\x1b[7mBaz';
|
||||
describe('$.terminal.from_ansi', function() {
|
||||
it('should convert ansi to terminal formatting', function() {
|
||||
var string = $.terminal.from_ansi(ansi_string);
|
||||
expect(string).toEqual('[[;#640000;#008787]Foo][[biu;#44D544;#F5F]'+
|
||||
'Bar][[;#000;#AAA]Baz]');
|
||||
});
|
||||
});
|
||||
describe('$.terminal.overtyping', function() {
|
||||
var string = 'HELLO TERMINAL'.replace(/./g, function(chr) {
|
||||
return chr == ' ' ? chr : chr + '\x08' + chr;
|
||||
});
|
||||
var result = '[[b;#fff;]HELLO] [[b;#fff;]TERMINAL]';
|
||||
it('should convert to terminal formatting', function() {
|
||||
expect($.terminal.overtyping(string)).toEqual(result);
|
||||
});
|
||||
});
|
||||
describe('$.terminal.escape_brackets', function() {
|
||||
var string = '[[jQuery]] [[Terminal]]';
|
||||
var result = '[[jQuery]] [[Terminal]]';
|
||||
it('should replace [ and ] with html entities', function() {
|
||||
expect($.terminal.escape_brackets(string)).toEqual(result);
|
||||
});
|
||||
});
|
||||
describe('$.terminal.encode', function() {
|
||||
var tags = '<hello> </hello>\t<world> </world>';
|
||||
var tags_result = '<hello> </hello> '+
|
||||
' <world> </world>';
|
||||
it('should convert < > space and tabs', function() {
|
||||
expect($.terminal.encode(tags)).toEqual(tags_result);
|
||||
});
|
||||
var entites = '& & & &64; = [';
|
||||
//'& & & &64; = ['
|
||||
var ent_result = '& & & &64; ='+
|
||||
' &#91';
|
||||
it('it should convert & but not when used with entities', function() {
|
||||
expect($.terminal.encode(entites)).toEqual(ent_result);
|
||||
});
|
||||
});
|
||||
describe('$.terminal.format_split', function() {
|
||||
});
|
||||
describe('$.terminal.is_formatting', function() {
|
||||
|
||||
it('should detect terminal formatting', function() {
|
||||
var formattings = [
|
||||
'[[;;]Te[xt]',
|
||||
'[[;;]Te\\]xt]',
|
||||
'[[;;]]',
|
||||
'[[gui;;;class]Text]',
|
||||
'[[b;#fff;]Text]',
|
||||
'[[b;red;blue]Text]'];
|
||||
var not_formattings = [
|
||||
'[[;;]Text[',
|
||||
'[[Text]]',
|
||||
'[[Text[[',
|
||||
'[[;]Text]',
|
||||
'Text]',
|
||||
'[[Text',
|
||||
'[;;]Text]'];
|
||||
formattings.forEach(function(formatting) {
|
||||
expect($.terminal.is_formatting(formatting)).toEqual(true);
|
||||
});
|
||||
not_formattings.forEach(function(formatting) {
|
||||
expect($.terminal.is_formatting(formatting)).toEqual(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('$.terminal.escape_regex', function() {
|
||||
it('should escape regex special characters', function() {
|
||||
var safe = "\\\\\\^\\*\\+\\?\\.\\$\\[\\]\\{\\}\\(\\)";
|
||||
expect($.terminal.escape_regex('\\^*+?.$[]{}()')).toEqual(safe);
|
||||
});
|
||||
});
|
||||
describe('$.terminal.have_formatting', function() {
|
||||
var formattings = [
|
||||
'some text [[;;]Te[xt] and formatting',
|
||||
'some text [[;;]Te\\]xt] and formatting',
|
||||
'some text [[;;]] and formatting',
|
||||
'some text [[gui;;;class]Text] and formatting',
|
||||
'some text [[b;#fff;]Text] and formatting',
|
||||
'some text [[b;red;blue]Text] and formatting'];
|
||||
var not_formattings = [
|
||||
'some text [[;;]Text[ and formatting',
|
||||
'some text [[Text]] and formatting',
|
||||
'some text [[Text[[ and formatting',
|
||||
'some text [[;]Text] and formatting',
|
||||
'some text Text] and formatting',
|
||||
'some text [[Text and formatting',
|
||||
'some text [;;]Text] and formatting'];
|
||||
it('should detect terminal formatting', function() {
|
||||
formattings.forEach(function(formatting) {
|
||||
expect($.terminal.have_formatting(formatting)).toEqual(true);
|
||||
});
|
||||
not_formattings.forEach(function(formatting) {
|
||||
expect($.terminal.have_formatting(formatting)).toEqual(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('$.terminal.valid_color', function() {
|
||||
it('should mark hex color as valid', function() {
|
||||
var valid_colors = ['#fff', '#fab', '#ffaacc', 'red', 'blue'];
|
||||
valid_colors.forEach(function(color) {
|
||||
expect($.terminal.valid_color(color)).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('$.terminal.format', function() {
|
||||
var format = '[[biugs;#fff;#000]Foo][[i;;;foo]Bar][[ous;;]Baz]';
|
||||
it('should create html span tags with style and classes', function() {
|
||||
var string = $.terminal.format(format);
|
||||
expect(string).toEqual('<span style="font-weight:bold;text-decorat'+
|
||||
'ion:underline line-through;font-style:ital'+
|
||||
'ic;color:#fff;text-shadow:0 0 5px #fff;bac'+
|
||||
'kground-color:#000" data-text="Foo">Foo</s'+
|
||||
'pan><span style="font-style:italic;" class'+
|
||||
'="foo" data-text="Bar">Bar</span><span sty'+
|
||||
'le="text-decoration:underline line-through'+
|
||||
' overline;" data-text="Baz">Baz</span>');
|
||||
});
|
||||
});
|
||||
describe('$.terminal.strip', function() {
|
||||
var formatting = '-_-[[biugs;#fff;#000]Foo]-_-[[i;;;foo]Bar]-_-[[ous;;'+
|
||||
']Baz]-_-';
|
||||
var result = '-_-Foo-_-Bar-_-Baz-_-';
|
||||
it('should remove formatting', function() {
|
||||
expect($.terminal.strip(formatting)).toEqual(result);
|
||||
});
|
||||
});
|
||||
describe('$.terminal.split_equal', function() {
|
||||
var text = ['[[bui;#fff;]Lorem ipsum dolor sit amet, consectetur adipi',
|
||||
'scing elit. Nulla sed dolor nisl, in suscipit justo. Donec a enim',
|
||||
' et est porttitor semper at vitae augue. Proin at nulla at dui ma',
|
||||
'ttis mattis. Nam a volutpat ante. Aliquam consequat dui eu sem co',
|
||||
'nvallis ullamcorper. Nulla suscipit, massa vitae suscipit ornare,',
|
||||
' tellus] est [[b;;#f00]consequat nunc, quis blandit elit odio eu ',
|
||||
'arcu. Nam a urna nec nisl varius sodales. Mauris iaculis tincidun',
|
||||
't orci id commodo. Aliquam] non magna quis [[i;;]tortor malesuada',
|
||||
' aliquam] eget ut lacus. Nam ut vestibulum est. Praesent volutpat',
|
||||
' tellus in eros dapibus elementum. Nam laoreet risus non nulla mo',
|
||||
'llis ac luctus [[ub;#fff;]felis dapibus. Pellentesque mattis elem',
|
||||
'entum augue non sollicitudin. Nullam lobortis fermentum elit ac m',
|
||||
'ollis. Nam ac varius risus. Cras faucibus euismod nulla, ac aucto',
|
||||
'r diam rutrum sit amet. Nulla vel odio erat], ac mattis enim.'
|
||||
].join('');
|
||||
it('should split text that into equal length chunks', function() {
|
||||
var cols = [10, 40, 60, 400];
|
||||
for (var i=cols.length; i--;) {
|
||||
var lines = $.terminal.split_equal(text, cols[i]);
|
||||
var success = true;
|
||||
for (var j=0; j<lines.length; ++j) {
|
||||
if ($.terminal.strip(lines[j]).length > cols[i]) {
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
expect(success).toEqual(true);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
function support_animations() {
|
||||
var animation = false,
|
||||
animationstring = 'animation',
|
||||
keyframeprefix = '',
|
||||
domPrefixes = 'Webkit Moz O ms Khtml'.split(' '),
|
||||
pfx = '',
|
||||
elm = document.createElement('div');
|
||||
if (elm.style.animationName) { animation = true; }
|
||||
if (animation === false) {
|
||||
for (var i = 0; i < domPrefixes.length; i++) {
|
||||
var name = domPrefixes[i] + 'AnimationName';
|
||||
if (elm.style[ name ] !== undefined) {
|
||||
pfx = domPrefixes[i];
|
||||
animationstring = pfx + 'Animation';
|
||||
keyframeprefix = '-' + pfx.toLowerCase() + '-';
|
||||
animation = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return animation;
|
||||
}
|
||||
function enter_text(text) {
|
||||
var e;
|
||||
var $root = $(document.documentElement || window);
|
||||
for (var i=0; i<text.length; ++i) {
|
||||
e = $.Event("keypress");
|
||||
e.which = e.keyCode = text.charCodeAt(i);
|
||||
e.ctrlKey = false;
|
||||
e.altKey = false;
|
||||
$root.trigger(e);
|
||||
}
|
||||
}
|
||||
function shortcut(ctrl, alt, shift, which) {
|
||||
var e = $.Event("keydown");
|
||||
e.ctrlKey = ctrl;
|
||||
e.altKey = alt;
|
||||
e.shiftKey = shift;
|
||||
e.which = e.keyCode = which;
|
||||
$(document.documentElement || window).trigger(e);
|
||||
}
|
||||
function enter_key() {
|
||||
shortcut(false, false, false, 13);
|
||||
}
|
||||
|
||||
function tests_on_ready() {
|
||||
describe('Terminal plugin', function() {
|
||||
describe('terminal create / terminal destroy', function() {
|
||||
var term = $('<div></div>').appendTo('body').terminal();
|
||||
it('should create terminal', function() {
|
||||
expect(term.length).toBe(1);
|
||||
});
|
||||
it('should have proper elements', function() {
|
||||
expect(term.hasClass('terminal')).toBe(true);
|
||||
expect(term.find('.terminal-output').length).toBe(1);
|
||||
expect(term.find('.cmd').length).toBe(1);
|
||||
var prompt = term.find('.prompt');
|
||||
expect(prompt.length).toBe(1);
|
||||
expect(prompt.is('span')).toBe(true);
|
||||
expect(prompt.children().length).toBe(1);
|
||||
var cursor = term.find('.cursor');
|
||||
expect(cursor.length).toBe(1);
|
||||
expect(cursor.is('span')).toBe(true);
|
||||
expect(cursor.prev().is('span')).toBe(true);
|
||||
expect(cursor.next().is('span')).toBe(true);
|
||||
term.focus(true);
|
||||
if (support_animations()) {
|
||||
expect(cursor.hasClass('blink')).toBe(true);
|
||||
}
|
||||
expect(term.find('.clipboard').length).toBe(1);
|
||||
});
|
||||
it('should have signature', function() {
|
||||
var sig = term.find('.terminal-output div div').map(function() { return $(this).text(); }).get().join('\n');
|
||||
expect(term.signature().replace(/ /g, '\xA0')).toEqual(sig);
|
||||
});
|
||||
it('should have default prompt', function() {
|
||||
var prompt = term.find('.prompt');
|
||||
expect(prompt.html()).toEqual("<span>> </span>");
|
||||
expect(prompt.text()).toEqual('>\xA0');
|
||||
});
|
||||
it('should destroy terminal', function() {
|
||||
term.destroy();
|
||||
expect(term.children().length).toBe(0);
|
||||
term.remove();
|
||||
});
|
||||
});
|
||||
describe('exec', function() {
|
||||
var interpreter = {
|
||||
foo: function() {
|
||||
}
|
||||
};
|
||||
|
||||
var term = $('<div></div>').appendTo('body').terminal(interpreter);
|
||||
|
||||
it('should execute function', function() {
|
||||
var spy = spyOn(interpreter, 'foo');
|
||||
if (spy.andCallThrough) {
|
||||
spy.andCallThrough();
|
||||
} else {
|
||||
spy.and.callThrough();
|
||||
}
|
||||
term.exec('foo').then(function() {
|
||||
expect(interpreter.foo).toHaveBeenCalled();
|
||||
term.destroy().remove();
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('enter text', function() {
|
||||
var interpreter = {
|
||||
foo: function() {
|
||||
}
|
||||
};
|
||||
var term = $('<div></div>').appendTo('body').terminal(interpreter);
|
||||
it('text should appear and interpreter function should be called', function() {
|
||||
term.focus(true);
|
||||
var spy = spyOn(interpreter, 'foo');
|
||||
if (spy.andCallThrough) {
|
||||
spy.andCallThrough();
|
||||
} else {
|
||||
spy.and.callThrough();
|
||||
}
|
||||
enter_text('foo');
|
||||
enter_key();
|
||||
expect(interpreter.foo).toHaveBeenCalled();
|
||||
var last_div = term.find('.terminal-output > div:last-child');
|
||||
expect(last_div.hasClass('command')).toBe(true);
|
||||
expect(last_div.children().html()).toEqual('<span>> foo</span>');
|
||||
term.destroy().remove();
|
||||
});
|
||||
});
|
||||
describe('prompt', function() {
|
||||
var term = $('<div></div>').appendTo('body').terminal($.noop, {
|
||||
prompt: '>>> '
|
||||
});
|
||||
it('should return prompt', function() {
|
||||
expect(term.get_prompt()).toEqual('>>> ');
|
||||
expect(term.find('.prompt').html()).toEqual('<span>>>> </span>');
|
||||
});
|
||||
it('should set prompt', function() {
|
||||
term.set_prompt('||| ');
|
||||
expect(term.get_prompt()).toEqual('||| ');
|
||||
expect(term.find('.prompt').html()).toEqual('<span>||| </span>');
|
||||
function prompt(callback) {
|
||||
callback('>>> ');
|
||||
}
|
||||
term.set_prompt(prompt);
|
||||
expect(term.get_prompt()).toEqual(prompt);
|
||||
expect(term.find('.prompt').html()).toEqual('<span>>>> </span>');
|
||||
});
|
||||
it('should format prompt', function() {
|
||||
var prompt = '<span style="font-weight:bold;text-decoration:underline;color:#fff;" data-text=">>>">>>></span><span> </span>';
|
||||
term.set_prompt('[[ub;#fff;]>>>] ');
|
||||
expect(term.find('.prompt').html()).toEqual(prompt);
|
||||
term.set_prompt(function(callback) {
|
||||
callback('[[ub;#fff;]>>>] ');
|
||||
});
|
||||
expect(term.find('.prompt').html()).toEqual(prompt);
|
||||
term.destroy().remove();
|
||||
});
|
||||
});
|
||||
describe('cmd plugin', function() {
|
||||
var term = $('<div></div>').appendTo('body').css('overflow-y', 'scroll').terminal($.noop, {
|
||||
name: 'cmd',
|
||||
numChars: 150,
|
||||
numRows: 20
|
||||
});
|
||||
var string = '';
|
||||
for (var i=term.cols(); i--;) {
|
||||
term.insert('M');
|
||||
}
|
||||
var cmd = term.cmd();
|
||||
var line = cmd.find('.prompt').next();
|
||||
it('text should have 2 lines', function() {
|
||||
expect(line.is('div')).toBe(true);
|
||||
expect(line.text().length).toBe(term.cols()-2);
|
||||
});
|
||||
it('cmd plugin moving cursor', function() {
|
||||
cmd.position(-8, true);
|
||||
var before = cmd.find('.prompt').next();
|
||||
var cursor = cmd.find('.cursor');
|
||||
var after = cursor.next();
|
||||
expect(before.is('span')).toBe(true);
|
||||
expect(before.text().length).toBe(term.cols()-8);
|
||||
expect(after.next().text().length).toBe(2);
|
||||
expect(after.text().length).toBe(5);
|
||||
expect(cursor.text()).toBe('M');
|
||||
});
|
||||
it('should remove characters', function() {
|
||||
cmd['delete'](-10);
|
||||
var before = cmd.find('.prompt').next();
|
||||
var cursor = cmd.find('.cursor');
|
||||
var after = cursor.next();
|
||||
expect(before.text().length).toEqual(term.cols()-8-10);
|
||||
cmd['delete'](8);
|
||||
expect(cursor.text()).toEqual('\xA0');
|
||||
expect(after.text().length).toEqual(0);
|
||||
});
|
||||
var history = cmd.history()
|
||||
it('should have one entry in history', function() {
|
||||
cmd.purge();
|
||||
term.set_command('something').focus(true);
|
||||
enter_key();
|
||||
expect(history.data()).toEqual(['something']);
|
||||
});
|
||||
it('should not add item to history if history is disabled', function() {
|
||||
history.disable();
|
||||
term.set_command('something else');
|
||||
enter_key();
|
||||
expect(history.data()).toEqual(['something']);
|
||||
});
|
||||
it('should remove commands from history', function() {
|
||||
var spy = spyOn(history, 'purge');
|
||||
if (spy.andCallThrough) {
|
||||
spy.andCallThrough();
|
||||
} else {
|
||||
spy.and.callThrough();
|
||||
}
|
||||
cmd.purge();
|
||||
expect(history.purge).toHaveBeenCalled();
|
||||
expect(history.data()).toEqual([]);
|
||||
});
|
||||
it('should have name', function() {
|
||||
expect(cmd.name()).toEqual('cmd_4');
|
||||
});
|
||||
it('should return command', function() {
|
||||
cmd.set('foo');
|
||||
expect(cmd.get()).toEqual('foo');
|
||||
});
|
||||
it('should not move position', function() {
|
||||
var pos = cmd.position();
|
||||
cmd.insert('bar', true);
|
||||
expect(cmd.position()).toEqual(pos);
|
||||
});
|
||||
it('should return $.noop for commands', function() {
|
||||
expect($.terminal.active().commands()).toEqual($.noop);
|
||||
});
|
||||
it('should set position', function() {
|
||||
cmd.position(0);
|
||||
expect(cmd.position()).toEqual(0);
|
||||
});
|
||||
it('should set and remove mask', function() {
|
||||
cmd.mask('•');
|
||||
cmd.position(6);
|
||||
var before = cmd.find('.prompt').next();
|
||||
expect(before.text()).toEqual('••••••');
|
||||
expect(cmd.get()).toEqual('foobar');
|
||||
cmd.mask(false);
|
||||
expect(before.text()).toEqual('foobar');
|
||||
});
|
||||
it('should execute functions on shortcuts', function() {
|
||||
var spy;
|
||||
spy = spyOn(cmd, 'position');
|
||||
if (spy.andCallThrough) {
|
||||
spy.andCallThrough();
|
||||
} else {
|
||||
spy.and.callThrough();
|
||||
}
|
||||
shortcut(true, false, false, 65); // CTRL+A
|
||||
expect(cmd.position).toHaveBeenCalled();
|
||||
spy = spyOn(cmd, 'delete');
|
||||
if (spy.andCallThrough) {
|
||||
spy.andCallThrough();
|
||||
} else {
|
||||
spy.and.callThrough();
|
||||
}
|
||||
shortcut(true, false, false, 75); // CTRL+K
|
||||
expect(cmd['delete']).toHaveBeenCalled();
|
||||
spy = spyOn(cmd, 'insert');
|
||||
if (spy.andCallThrough) {
|
||||
spy.andCallThrough();
|
||||
} else {
|
||||
spy.and.callThrough();
|
||||
}
|
||||
shortcut(true, false, false, 89); // CTRL+Y
|
||||
expect(cmd.insert).toHaveBeenCalled();
|
||||
shortcut(true, false, false, 85); // CTRL+U
|
||||
expect(cmd.kill_text()).toEqual('foobar');
|
||||
shortcut(true, false, true, 13);
|
||||
expect(cmd.find('.prompt').next().text()).toEqual('\xA0');
|
||||
expect(cmd.get()).toEqual('\n');
|
||||
cmd.set('');
|
||||
shortcut(false, false, false, 9); // TAB
|
||||
expect(cmd.get()).toEqual('\t');
|
||||
history.enable();
|
||||
cmd.set('foo bar');
|
||||
enter_key();
|
||||
shortcut(false, false, false, 38); // UP ARROW
|
||||
expect(cmd.get()).toEqual('foo bar');
|
||||
shortcut(false, false, false, 40); // DOWN ARROW
|
||||
expect(cmd.get()).toEqual('');
|
||||
cmd.insert('hello');
|
||||
shortcut(false, false, false, 38);
|
||||
shortcut(false, false, false, 40);
|
||||
expect(cmd.get()).toEqual('hello');
|
||||
shortcut(true, false, false, 80); // CTRL+P
|
||||
expect(cmd.get()).toEqual('foo bar');
|
||||
shortcut(true, false, false, 78); // CTRL+N
|
||||
expect(cmd.get()).toEqual('hello');
|
||||
cmd.set('foo bar baz');
|
||||
shortcut(false, false, false, 37); // LEFT ARROW
|
||||
expect(cmd.position()).toEqual(10);
|
||||
shortcut(true, false, false, 37); // moving by words
|
||||
expect(cmd.position()).toEqual(8);
|
||||
shortcut(true, false, false, 37);
|
||||
expect(cmd.position()).toEqual(4);
|
||||
shortcut(true, false, false, 37);
|
||||
expect(cmd.position()).toEqual(0);
|
||||
shortcut(false, false, false, 39); // RIGHT ARROW
|
||||
expect(cmd.position()).toEqual(1);
|
||||
shortcut(true, false, false, 39);
|
||||
expect(cmd.position()).toEqual(3);
|
||||
shortcut(true, false, false, 39);
|
||||
expect(cmd.position()).toEqual(7);
|
||||
shortcut(true, false, false, 39);
|
||||
expect(cmd.position()).toEqual(11);
|
||||
shortcut(false, false, false, 36); // HOME
|
||||
expect(cmd.position()).toEqual(0);
|
||||
shortcut(false, false, false, 35); // END
|
||||
expect(cmd.position()).toEqual(cmd.get().length);
|
||||
shortcut(true, false, false, 82); // CTRL+R
|
||||
expect(cmd.prompt()).toEqual("(reverse-i-search)`': ");
|
||||
enter_text('foo');
|
||||
expect(cmd.get()).toEqual('foo bar');
|
||||
shortcut(true, false, false, 71); // CTRL+G
|
||||
expect(cmd.get()).toEqual('foo bar baz');
|
||||
cmd.purge();
|
||||
term.destroy();
|
||||
});
|
||||
});
|
||||
function JSONRPCMock(url, object) {
|
||||
var ajax = $.ajax;
|
||||
var system = {
|
||||
'sdversion': '1.0',
|
||||
'name': 'DemoService',
|
||||
'address': url,
|
||||
// md5('JSONRPCMock')
|
||||
'id': 'urn:md5:e1a975ac782ce4ed0a504ceb909abf44',
|
||||
'procs': []
|
||||
};
|
||||
for (var key in object) {
|
||||
var proc = {
|
||||
name: key
|
||||
};
|
||||
if ($.isFunction(object[key])) {
|
||||
var re = /function[^\(]+\(([^\)]+)\)/;
|
||||
var m = object[key].toString().match(re);
|
||||
if (m) {
|
||||
proc.params = m[1].split(/\s*,\s*/);
|
||||
}
|
||||
}
|
||||
system.procs.push(proc);
|
||||
}
|
||||
$.ajax = function(obj) {
|
||||
if (obj.url == url) {
|
||||
var defer = $.Deferred();
|
||||
try {
|
||||
var req = JSON.parse(obj.data);
|
||||
var resp;
|
||||
if (req.method == 'system.describe') {
|
||||
resp = system;
|
||||
} else {
|
||||
var error = null;
|
||||
var ret = null
|
||||
try {
|
||||
ret = object[req.method].apply(null, req.params);
|
||||
} catch (e) {
|
||||
error = {message: e.message};
|
||||
}
|
||||
resp = {
|
||||
id: req.id,
|
||||
jsonrpc: '1.1',
|
||||
result: ret,
|
||||
error: error
|
||||
};
|
||||
}
|
||||
resp = JSON.stringify(resp);
|
||||
if ($.isFunction(obj.success)) {
|
||||
obj.success(resp, 'OK', {
|
||||
getResponseHeader: function(header) {
|
||||
if (header == 'Content-Type') {
|
||||
return 'application/json';
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
defer.resolve(resp);
|
||||
} catch (e) {
|
||||
throw new Error(e.message);
|
||||
}
|
||||
return defer.promise();
|
||||
} else {
|
||||
return ajax.apply($, arguments);
|
||||
}
|
||||
}
|
||||
}
|
||||
var object = {
|
||||
echo: function(token, str) {
|
||||
return str;
|
||||
},
|
||||
login: function(user, password) {
|
||||
if (user == 'demo' && password == 'demo') {
|
||||
return 'TOKEN';
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
};
|
||||
JSONRPCMock('/test', object);
|
||||
describe('JSON-RPC', function() {
|
||||
var term = $('<div></div>').appendTo('body').terminal('/test', {
|
||||
login: true
|
||||
});
|
||||
it('should call login', function() {
|
||||
term.focus();
|
||||
var spy = spyOn(object, 'login');
|
||||
if (spy.andCallThrough) {
|
||||
spy.andCallThrough();
|
||||
} else {
|
||||
spy.and.callThrough();
|
||||
}
|
||||
term.insert('test');
|
||||
enter_key();
|
||||
term.insert('test');
|
||||
enter_key();
|
||||
var last_div = term.find('.terminal-output > div:last-child');
|
||||
expect(last_div.text()).toEqual('Wrong password try again!');
|
||||
expect(object.login).toHaveBeenCalledWith('test', 'test');
|
||||
term.insert('demo');
|
||||
enter_key();
|
||||
term.insert('demo');
|
||||
enter_key();
|
||||
expect(object.login).toHaveBeenCalledWith('demo', 'demo');
|
||||
});
|
||||
it('should call a function', function() {
|
||||
term.focus();
|
||||
var spy = spyOn(object, 'echo');
|
||||
if (spy.andCallThrough) {
|
||||
spy.andCallThrough();
|
||||
} else {
|
||||
spy.and.callThrough();
|
||||
}
|
||||
term.insert('echo hello');
|
||||
enter_key();
|
||||
expect(object.echo).toHaveBeenCalledWith('TOKEN', 'hello');
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
if (node) {
|
||||
tests_on_ready();
|
||||
} else {
|
||||
$(tests_on_ready);
|
||||
}
|
||||
|