Add GUI editor

This commit is contained in:
Lorem Ipsum 2021-01-07 13:47:43 +00:00
parent 18fcbc5056
commit f729785019
10 changed files with 2073 additions and 156 deletions

View file

@ -6,6 +6,6 @@ This can be used for bot embed commands commands, although I understand that not
You can look into the [project boards](https://github.com/Glitchii/embedbuilder/projects/3) if you want to see what is being worked on or want to contribute.
<br>
<br>
![Layout image](https://raw.githubusercontent.com/Glitchii/embedbuilder/master/assets/media/layout.png)
![GUI image](https://raw.githubusercontent.com/Glitchii/embedbuilder/master/assets/media/gui.png) ![JSON image](https://raw.githubusercontent.com/Glitchii/embedbuilder/master/assets/media/json.png)
[To Do](https://github.com/Glitchii/embedbuilder/projects/3) | [Discussions](https://github.com/Glitchii/embedbuilder/discussions/1)

View file

@ -89,21 +89,20 @@ body {
overflow: auto;
}
.bottom {
height: 30%;
display: none;
}
.side1 .item.top {
background-color: #292b2f;
width: 100%;
height: 100%;
height: 94%;
border-radius: 5px;
margin: auto;
transform: translateY(10px);
}
.item~.item {
margin-top: 15px;
body.gui .side1 .item.top {
transform: translateY(20px);
}
.top, .bottom {
margin: auto;
}
.main .side2 {
@ -218,12 +217,16 @@ img[alt] {
.msgEmbed {
min-height: 2.75rem;
padding: 0.125rem 0 20px 72px;
position: absolute;
overflow-wrap: break-word;
user-select: text;
width: 96%;
margin: 10px 20px 0 20px;
width: 100%;
margin: 10px 0 0 0;
padding: calc(0.125rem + 10px) 20px 20px 92px;
}
.msgEmbed:hover {
background-color: #04040512;
}
.embedTitle>* {
@ -239,7 +242,7 @@ img[alt] {
.avatar {
position: absolute;
left: 16px;
left: 36px;
margin-top: calc(4px - 0.125rem);
width: 40px;
height: 40px;
@ -685,7 +688,7 @@ u {
color: #f45711;
font-size: 20px;
position: relative;
left: -2px;
left: 10px;
top: -3px;
}
@ -715,6 +718,19 @@ u {
.CodeMirror-gutters {
background: #292b2f!important;
display: none;
}
.CodeMirror pre.CodeMirror-line, .CodeMirror pre.CodeMirror-line-like {
padding: 0 12px;
}
.CodeMirror-lint-marker.CodeMirror-lint-marker-error {
left: 15px!important;
}
.CodeMirror pre.CodeMirror-line, .CodeMirror pre.CodeMirror-line-like {
padding: 0 15px!important;
}
.CodeMirror-foldmarker {
@ -797,17 +813,798 @@ u {
z-index: 5;
}
@media screen and (max-width: 1015px) {
.main {
display: flex;
flex-direction: column;
.col.cm-string.cm-property::before {
content: url("data:image/svg+xml,%3Csvg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 512 512' xml:space='preserve'%3E%3Cpath style='fill:%23D8D8DA;' d='M256,0C114.615,0,0,114.615,0,256s114.615,256,256,256s256-114.615,256-256S397.385,0,256,0z M256,336.842c-44.648,0-80.842-36.194-80.842-80.842s36.194-80.842,80.842-80.842s80.842,36.194,80.842,80.842 S300.648,336.842,256,336.842z'/%3E%3Cpath style='fill:%23D4B6E6;' d='M282.947,188.632h220.076C485.09,122.726,441.507,67.394,383.64,34.044L229.053,188.632H282.947z'/%3E%3Cpath style='fill:%23EBAFD1;/*! fill: %23e592bf; */' d='M229.053,188.632L383.639,34.044C346.068,12.39,302.482,0,256,0c-23.319,0-45.899,3.135-67.368,8.978 v220.075L229.053,188.632z'/%3E%3Cpath style='fill:%23E07188;' d='M188.632,229.053V8.978C122.726,26.91,67.394,70.493,34.045,128.36l154.586,154.588V229.053z'/%3E%3Cg%3E%3Cpolygon style='fill:%23D8D8DA;' points='188.632,229.053 229.053,188.633 282.947,188.633 282.947,188.632 229.053,188.632 '/%3E%3Cpolygon style='fill:%23D8D8DA;' points='229.053,323.367 188.632,282.947 229.053,323.368 282.947,323.368 323.368,282.947 282.947,323.367 '/%3E%3C/g%3E%3Cpath style='fill:%23B4D8F1;' d='M503.024,188.632H282.947v0.001h0.958l39.463,40.42L477.955,383.64 C499.611,346.068,512,302.482,512,256C512,232.681,508.865,210.099,503.024,188.632z'/%3E%3Cpath style='fill:%23ACFFF4;' d='M323.368,282.947v220.075c65.905-17.932,121.238-61.517,154.586-119.382L323.368,229.053V282.947z'/%3E%3Cpath style='fill:%2395D5A7;' d='M282.947,323.368L128.361,477.956C165.932,499.61,209.518,512,256,512 c23.319,0,45.899-3.135,67.368-8.977V282.947L282.947,323.368z'/%3E%3Cpath style='fill:%23F8E99B;' d='M229.053,323.368H8.976C26.91,389.274,70.493,444.606,128.36,477.956l154.588-154.588H229.053z'/%3E%3Cpath style='fill:%23EFC27B;' d='M188.632,282.947L34.045,128.36C12.389,165.932,0,209.518,0,256c0,23.319,3.135,45.901,8.976,67.368 h220.076L188.632,282.947z'/%3E%3Cpolygon style='fill:%23E3E3E3;' points='283.905,188.633 282.947,188.633 323.368,229.053 '/%3E%3Cpath style='fill:%23B681D5;' d='M503.024,188.632C485.09,122.726,441.507,67.394,383.64,34.044L256,161.684v26.947h26.947H503.024z'/%3E%3Cpath style='fill:%23E592BF;' d='M383.639,34.044C346.068,12.39,302.482,0,256,0v161.684L383.639,34.044z'/%3E%3Cpath style='fill:%2380CB93;' d='M256,350.316V512c23.319,0,45.899-3.135,67.368-8.977V282.947l-40.421,40.421L256,350.316z'/%3E%3Cpolygon style='fill:%23F6E27D;' points='282.947,323.368 256,323.368 256,350.316 '/%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3Cg%3E%3C/g%3E%3C/svg%3E");
width: 15px;
height: 100px;
display: block;
background-repeat: no-repeat;
position: absolute;
top: 0;
left: 40px;
cursor: pointer;
opacity: .5;
transition: 1s ease;
}
.CodeMirror:hover .col.cm-string.cm-property::before {
opacity: 1;
}
body.gui .side1 .item.top {
max-width: 90%;
height: 70%;
border-radius: 15px;
}
body.gui .top>.CodeMirror {
display: none;
}
.top>.gui {
height: 100px;
height: 100%;
width: 100%;
background: #292b2f;
border-radius: 5px;
overflow-y: scroll;
overflow-x: hidden;
scrollbar-color: #202225 #292b2f;
scrollbar-width: thin;
}
body:not(.gui) .top>.gui, body:not(.gui) .bottom, body:not(.gui) .pickerToggle {
display: none;
}
.chooser {
display: flex;
height: 40px;
width: 100px;
border-radius: 5px;
margin-bottom: 10px;
padding: 7px;
background: #1b1c2061;
box-shadow: -2px -2px 10px 0px #0000;
}
.chooser>.opt {
width: 50px;
cursor: pointer;
background: #292b2f;
border-radius: 4px;
}
body.gui .chooser>.gui {
background: #41444a;
}
body:not(.gui) .chooser>.json {
background: #41444a;
}
.chooser>.back {
position: absolute;
height: 26px;
width: 43px;
border-radius: 4px;
background: #41444a;
transition: .5s ease-out;
pointer-events: none;
}
body:not(.gui) .chooser>.back {
transform: translateX(43px);
}
.chooser>.opt p {
display: flex;
justify-content: center;
font-size: 10px;
position: relative;
top: 50%;
transform: translateY(-50%);
pointer-events: none;
}
.bottom {
height: 40%;
margin: 40px auto auto auto!important;
max-width: 90%;
}
@keyframes colrsAn {
0% {
transform: translateX(-200px);
opacity: 0;
}
.side1 .item.top {
height: 100%;
}
.bottom .colrs {
animation: colrsAn .5s ease-out;
background: #212226;
border-radius: 10px;
width: 250px;
height: 130px;
position: absolute;
bottom: 20px;
box-shadow: -3px 3px 5px 0px #00000029;
display: grid;
grid-template-columns: 27% 73%;
grid-template-columns: 5% 27.5% 67.5%;
}
.bottom .colrs .colr {
background: #41f097;
}
.bottom .colrs.display {
display: grid;
}
.colLeft {
border-radius: 15px;
}
.colLeft .picker {
background: #292b2f;
border: 1px solid #ffffff24;
}
.colLeft .picker>svg {
top: 7px;
right: 10px;
width: 16px;
height: 16px;
position: absolute;
}
.col.colLeft>* {
border-radius: 8px;
cursor: pointer;
}
.colRight {
margin: 0 10px;
}
.cTop {
width: 100%;
}
.cTop>h2 {
font-weight: 900;
margin-top: 10px;
}
.cTop .desc {
font-size: 12px;
opacity: .6;
margin-top: 5px;
}
.col {
display: grid;
grid-template-rows: 45% 45%;
gap: 10px;
height: 80%;
transform: translateY(-50%);
top: 50%;
position: relative;
}
.pallets {
width: 100%;
display: grid;
/* grid-template-columns: repeat(8, 1fr); */
grid-template-columns: repeat(6, minmax(25px, 1fr));
gap: 5px 0px;
/* opacity: .7; */
transition: .5s;
}
.colrs:hover .pallets {
opacity: 1;
}
.pallets>* {
background: black;
width: 17px;
height: 17px;
margin-left: 5px;
border-radius: 2px;
cursor: pointer;
}
.color-picker {
transform: none;
width: 100%;
height: 100%;
top: 0!important;
left: 0!important;
border-radius: 10px;
overflow: hidden;
}
.color-picker>div {
height: 100%!important;
}
.colRight.picking .cTop>*:not(.color-picker), .colRight.picking .pallets, .colRight:not(.picking) .colBack {
display: none;
}
.color-picker\:a {
display: none!important;
}
@keyframes colBackAn {
from {
right: 50px;
}
.notification .inline {
display: block;
margin-top: 5px;
}
.colBack {
animation: colBackAn .2s ease-out;
position: absolute;
right: 0;
transform: translateX(40px);
z-index: 1000;
cursor: pointer;
}
.colBack svg {
width: 20px;
height: 20px;
opacity: .6;
}
.top {
scrollbar-color: #202225 #292b2f;
scrollbar-width: thin;
overflow: hidden;
}
.top>.gui>.item {
cursor: pointer;
background: #212226;
height: 40px;
width: 90%;
margin: 8px auto;
border-radius: 7px;
background: linear-gradient(90deg, #212226, #21222600);
position: relative;
z-index: 2;
}
.top>.gui>.item.active .ttle::after {
transform: scale(.8) rotate(180deg);
}
.top>.gui>.item.active .ttle::after {
transform: scale(.8) rotate(180deg);
}
.top>.gui>.item.inlineField.active .ttle, .top>.gui>.item:not(.active) .ttle~input {
display: none;
}
.ttle, .ttle~input {
font-size: 12px;
font-weight: 900;
text-transform: uppercase;
position: relative;
top: 50%;
transform: translateY(-50%);
margin-left: 15px;
}
.top>.gui>.item.active .ttle~input:not(:placeholder-shown) {
font-weight: normal;
text-transform: none;
font-size: 12px;
}
input, textarea {
background: transparent;
border: none;
color: inherit;
}
.ttle~input {
width: 100%;
}
.ttle::after {
content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='30' viewBox='0 0 24 24' height='30'%3E%3Cpath clip-rule='evenodd' fill='%23fff' d='M16.59 8.59004L12 13.17L7.41 8.59004L6 10L12 16L18 10L16.59 8.59004Z'%3E%3C/path%3E%3C/svg%3E");
position: absolute;
right: 0;
top: -12px;
transform: scale(.8);
opacity: .1;
pointer-events: none;
transition: .2s ease;
}
@keyframes editAn {
from {
opacity: 0;
transform: translateY(-40px);
}
}
.top>.gui>.item~.edit {
animation: editAn .3s ease;
height: 40px;
width: 90%;
margin: 8px auto;
position: relative;
border-bottom-left-radius: 7px;
border-bottom-right-radius: 7px;
margin-top: 0;
background: #212226;
}
.top>.gui>.item~.edit input {
align-self: start;
font-size: 13px;
position: relative;
margin-left: 15px;
transform: translateY(4px);
}
.top>.gui>.item:not(.active)+.edit {
display: none;
}
.top>.gui>.item:not(.inlineField).active {
margin-bottom: 0;
background: #212226;
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}
.edit {
padding-left: 15px;
}
.item:not(.rows2)+.edit {
display: flex;
}
.editIcon {
display: flex;
}
.editIcon, .editName, .editIcon input, .editName input {
width: 100%;
overflow: hidden;
}
.editIcon .imgParent {
width: 24px;
height: 24px;
object-fit: contain;
border-radius: 50%;
}
.editIcon>* {
display: inline-flex;
}
.pickerToggle {
display: none;
bottom: 15px;
left: 15px;
position: absolute;
cursor: pointer;
z-index: 5;
}
.pickerToggle>svg {
width: 20px;
height: 100%;
}
textarea {
font-size: 13px;
min-width: 100%;
max-width: 100%!important;
height: 75px;
max-height: 200px;
}
.top>.gui>.item.description+.edit, .top>.gui>.item.content+.edit {
height: auto;
}
.top>.gui>.item.content+.edit textarea {
height: 80px;
}
.browse {
margin-top: 25px;
font-size: 13px;
display: flex;
cursor: pointer;
position: absolute;
opacity: .5;
}
.browse:hover {
opacity: 1;
}
.browse>svg {
width: 20px;
position: relative;
z-index: 6;
height: 20px;
transform: translateY(-5px);
margin-right: 5px;
}
.browse>p::after {
content: "Browse";
}
.browse.loading>svg:first-of-type, .browse:not(.loading)>svg:last-of-type, .browse.error>svg {
display: none;
}
.browse.loading>p::after {
content: "Loading...";
}
.browse.error>p::after {
color: #ee9191;
content: "Request failed. (Check dev-tools)";
}
.linkName {
display: flex;
}
.linkName, .linkName .txtCol, .linkName .txtCol>input[type="text"] {
width: 100%;
text-overflow: ellipsis;
}
.txtCol>input[type="text"] {
overflow: auto;
}
.top>.gui>.item.rows2+.edit {
height: 80px;
}
input[type="file"], button[type="submit"] {
display: none;
}
.largeImg+.edit .editIcon .imgParent {
width: 80px;
height: 80px;
border-radius: 4px;
object-fit: fill;
margin-top: 0;
margin-bottom: 15px;
}
.top>.gui>.largeImg+.edit input {
transform: none;
}
.largeImg+.edit .browse {
margin-top: 40px;
font-size: 13px;
display: flex;
cursor: pointer;
position: relative;
opacity: .5;
margin-left: 15px;
}
.largeImg.image+.edit .browse {
margin-top: 35px;
}
.largeImg+.edit .editIcon>* {
display: block;
}
.largeImg+.edit {
height: auto!important;
}
.largeImg.image+.edit .editIcon .imgParent {
width: 130px;
object-fit: contain;
border-radius: 4px;
object-fit: cover;
}
.top>.gui>.item.fields+.edit input {
margin-left: 0;
}
.top>.gui>.item.fields+.edit input[type="text"] {
width: 100%;
}
.top>.gui>.item.fields+.edit {
height: auto;
padding-bottom: 15px;
}
.top>.gui>.item.fields.active+.edit {
display: block;
}
.designerFieldName {
width: 95%;
min-height: 30px;
border-radius: 5px;
}
.designerFieldValue textarea {
padding: 5px 10px;
}
.designerFieldName {
width: 100%;
min-height: 30px;
padding: 5px 10px;
margin-bottom: 2px;
}
.designerFieldName>input[type="text"] {
font-weight: 700;
}
.field~.field {
margin-top: 10px;
}
.field .fieldInner {
width: 95%;
height: 100%;
border-radius: 4px;
background: #292b2f;
border-radius: 5px;
margin-bottom: 2px;
transition: .3s ease;
}
@keyframes lastFieldSlide {
from {
opacity: 0;
transform: translateY(100px);
}
}
.gui>.item.fields+.edit>.field {
animation: lastFieldSlide .5s ease;
}
.fields+.edit .fieldInner .designerFieldName {
background: #2d2e33;
}
body {
counter-reset: fieldCount;
}
.fieldNumber {
position: absolute;
}
.fields+.edit {
z-index: 2;
}
@keyframes fieldNumberFadeInAn {
from {
opacity: 0;
transition: opacity 1s ease;
}
}
.fieldNumber::before {
animation: fieldNumberFadeInAn .2s ease-in;
counter-increment: fieldCount;
content: counter(fieldCount);
position: relative;
font-size: 20px;
right: 41px;
top: 22px;
z-index: -2;
opacity: .15;
}
.inlineCheck, .removeBtn {
font-size: 11px;
font-weight: bold;
text-transform: uppercase;
cursor: pointer;
display: inline-block;
margin-top: 3px;
}
#inlineCheck, [for="inlineCheck"] {
cursor: pointer;
}
.removeBtn {
margin-left: 20PX;
}
.removeBtn>svg {
width: 10px;
height: 10px;
transition: .5s ease;
}
.removeBtn>span {
margin-left: 3px;
position: relative;
top: -1px;
transition: .5s ease;
}
.removeBtn:hover>span, .removeBtn:hover>svg path {
color: #ff9191;
fill: #ff9191;
}
.inlineCheck input[type="checkbox"] {
scale: .8;
cursor: pointer;
}
.inlineCheck input[type="checkbox"]+span {
cursor: pointer;
}
.sep {
width: 100%;
height: 2px;
background: linear-gradient(to right, #2f313600, #2f3136, #2f313600);
}
.imgParent {
border-radius: 4px;
object-fit: fill;
margin-top: 0;
content: url("data:image/svg+xml,%3Csvg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0' y='0' width='1400' height='780' viewBox='0, 0, 1400, 780'%3E%3Cg id='Background'%3E%3Crect x='0' y='0' width='1400' height='780' style='fill: %23212226;' fill='%23363A3E'/%3E%3C/g%3E%3Cg id='Background'/%3E%3Cg id='Background'%3E%3Cg%3E%3Cpath d='M463.326,212.495 L936.674,212.495 L936.674,567.505 L463.326,567.505 z' fill-opacity='0' stroke='%2343474B' stroke-width='30' stroke-miterlimit='10' style='stroke: %23888789;fill: %23888789;'/%3E%3Cpath d='M605.33,309.136 C605.33,328.961 589.259,345.032 569.435,345.032 C549.61,345.032 533.539,328.961 533.539,309.136 C533.539,289.312 549.61,273.241 569.435,273.241 C589.259,273.241 605.33,289.312 605.33,309.136 z' fill='%2343474B' style='fill: %23888789;'/%3E%3Cpath d='M878.689,507.548 L523.284,507.548 L570.618,406.173 L600.597,450.352 L700.789,298.092 L772.58,405.778 L806.503,368.699 z' fill='%2343474B' style='fill: %23888789;'/%3E%3C/g%3E%3C/g%3E%3Cstyle xmlns='http://www.w3.org/1999/xhtml' type='text/css'%3E%3C/style%3E%3C/svg%3E");
}
.largeImg+.edit .imgParent {
margin-bottom: 15px;
}
.item:not(.largeImg)+.edit .imgParent[style*="content"] {
transform: scale(1);
}
.item:not(.largeImg)+.edit .imgParent {
transform: scale(2);
}
@keyframes addFieldFade {
from {
opacity: 0;
}
}
.addField {
animation: addFieldFade .5s ease;
font-size: 13px;
display: flex;
cursor: pointer;
opacity: .5;
padding-top: 15px;
transition: .5s ease;
}
.field+.addField {
margin-top: 5px;
}
.addField>svg {
width: 16px;
position: relative;
z-index: 6;
height: 100%;
transform: translateY(-3px);
margin-left: 5px;
opacity: .8;
}
.addField:hover, .addField:hover>svg {
opacity: 1;
}
.clear {
left: 140px;
position: absolute;
cursor: pointer;
z-index: 5;
transform: translate(0, -5px);
padding: 8.5px;
border-radius: 100%;
background: #27282e;
width: 35px;
height: 35px;
transition: .5s ease;
}
@keyframes emptyTxtAn {
from {
opacity: 0;
}
}
.emptyTxt {
animation: emptyTxtAn 1s ease;
font-weight: 600;
text-transform: uppercase;
font-size: 30px;
line-height: 16px;
color: #41444a;
font-family: var(--font2);
padding: 10px 0;
top: 50%;
position: absolute;
left: 50%;
transform: translate(-50%, -50%);
pointer-events: none;
}
@keyframes clearAn {
0% {
transform: rotate(10deg);
}
25% {
transform: rotate(-10deg);
}
50% {
transform: rotate(10deg);
}
75% {
transform: rotate(-13deg);
}
}
.clear:hover>svg {
animation: clearAn 1s ease-in-out forwards;
transform-origin: top right;
}
.side2:not(.empty) .emptyTxt {
display: none;
}
.clear>svg {
width: 20px;
height: 100%;
position: relative;
left: -2.5px;
top: -2px;
}
::-webkit-scrollbar {
width: 7px;
background: #292b2f00;
}
::-webkit-scrollbar-thumb {
background: #202225;
}
@media screen and (max-width: 1270px) {
.fieldNumber::before {
right: 300%;
}
}
@ -822,4 +1619,79 @@ u {
.main .side1 {
padding: 10px;
}
}
@media screen and (max-height: 760px) {
.bottom .colrs {
bottom: 10px;
}
body.gui .side1 .item.top {
height: 65%;
max-width: 100%;
width: 100%;
}
.bottom {
margin: 40px 0 0 0 !important;
}
}
@media screen and (max-width: 1015px) {
.clear {
position: absolute;
cursor: pointer;
z-index: 5;
left: 135px;
}
.main {
display: flex;
flex-direction: column;
}
.side1 .item.top {
height: 100%;
}
.notification .inline {
display: block;
margin-top: 5px;
}
.bottom .colrs {
bottom: 40px;
left: 200px;
display: none;
top: 0;
animation: colrsAn .1s ease-out;
box-shadow: 0px 5px 15px 0px #0000004f;
}
body.gui .side1 .item.top {
height: 85%;
max-width: 100%;
width: 100%;
}
.bottom {
margin: 40px 0 0 0 !important;
}
.pickerToggle {
display: block;
position: absolute;
cursor: pointer;
z-index: 5;
left: 170px;
border-left: 2px solid #4c5057;
padding-left: 15px;
bottom: auto;
margin-left: 15px;
}
.pickerToggle>svg {
width: 17px;
}
.side1 .item.top {
padding-top: 10px;
transform: translateY(10px);
}
}
@media screen and (max-width: 460px) {
.bottom .colrs {
top: 70px;
left: 10px;
}
}

View file

@ -2910,6 +2910,7 @@ var emojis = {
"sob": "😭",
"smiling_imp": "😈",
"slight_smile": "🙂",
"pensive": "😔",
"angry": "😠",
"blush": "😊",
"confused": "😕",

View file

@ -2,23 +2,86 @@
// Want to use or contribute to this? https://github.com/Glitchii/embedbuilder
// If you found an issue, please report it, make a P.R, or use the discussion page. Thanks
var colNum = 1, num = 0;
var activeFields, colNum = 1, num = 0,
toRGB = (hex, reversed, integer) => {
if (reversed) return '#' + hex.match(/[\d]+/g).map(x => parseInt(x).toString(16).padStart(2, '0')).join('');
if (integer) return parseInt(hex.match(/[\d]+/g).map(x => parseInt(x).toString(16).padStart(2, '0')).join(''), 16);
if (hex.includes(',')) return hex.match(/[\d]+/g);
hex = hex.replace('#', '').match(/.{1,2}/g)
return [parseInt(hex[0], 16), parseInt(hex[1], 16), parseInt(hex[2], 16), 1];
}, json = {
content: "You can~~not~~ do `this`.```py\nAnd this.\nprint('Hi')```\n*italics* or _italics_ __*underline italics*__\n**bold** __**underline bold**__\n***bold italics*** __***underline bold italics***__\n__underline__ ~~Strikethrough~~",
embed: {
title: "Hello ~~people~~ world :wave:",
description: "You can use [links](https://discord.com) or emojis :smile: 😎\n```\nAnd also code blocks\n```",
color: 4321431,
timestamp: "2020-12-08T13:37:35.401Z",
url: "https://discord.com",
author: {
name: "Author name",
url: "https://discord.com",
icon_url: "https://unsplash.it/100"
},
thumbnail: {
url: "https://unsplash.it/200"
},
image: {
url: "https://unsplash.it/380/200"
},
footer: {
text: "Footer text",
icon_url: "https://unsplash.it/100"
},
fields: [
{
name: "Field 1, *lorem* **ipsum**, ~~dolor~~",
value: "Field value"
},
{
name: "Field 2",
value: "You can use custom emojis <:Kekwlaugh:722088222766923847>. <:GangstaBlob:742256196295065661>",
inline: false
},
{
name: "Inline field",
value: "Fields can be inline",
inline: true
},
{
name: "Inline field",
value: "*Lorem ipsum*",
inline: true
},
{
name: "Inline field",
value: "value",
inline: true
},
{
name: "Another field",
value: "> Nope, didn't forget about code blocks",
inline: false
}
]
}
};
window.onload = () => {
document.querySelectorAll('img.clickable')
.forEach(e => e.addEventListener('click', el => window.open(el.target.src)));
let textarea = document.querySelector('textarea');
window.editor = CodeMirror(elt => textarea.parentNode.replaceChild(elt, textarea), {
value: textarea.value,
theme: 'material-darker',
let editorHolder = document.querySelector('.editorHolder'),
guiParent = document.querySelector('.top'),
gui = guiParent.querySelector('.gui:first-of-type');
window.editor = CodeMirror(elt => editorHolder.parentNode.replaceChild(elt, editorHolder), {
value: JSON.stringify(json, null, 4),
extraKeys: { Tab: cm => cm.replaceSelection(" ", "end") },
gutters: ["CodeMirror-foldgutter", "CodeMirror-lint-markers"],
scrollbarStyle: "overlay",
mode: "application/json",
foldGutter: true,
gutters: ["CodeMirror-foldgutter", "CodeMirror-lint-markers"],
theme: 'material-darker',
matchBrackets: true,
foldGutter: true,
lint: true,
extraKeys: {
"Tab": cm => cm.replaceSelection(" ", "end")
}
});
editor.focus();
@ -57,7 +120,7 @@ window.onload = () => {
.replace(/\n/g, '<br>');
return txt;
},
content = document.querySelector('.messageContent'),
embedContent = document.querySelector('.messageContent'),
embed = document.querySelector('.embedGrid'),
msgEmbed = document.querySelector('.msgEmbed'),
embedTitle = document.querySelector('.embedTitle'),
@ -66,7 +129,7 @@ window.onload = () => {
embedFooter = document.querySelector('.embedFooter'),
embedImage = document.querySelector('.embedImage'),
embedThumbnail = document.querySelector('.embedThumbnail'),
fields = embed.querySelector('.embedFields'),
embedFields = embed.querySelector('.embedFields'),
tstamp = stringISO => {
let date = stringISO ? new Date(stringISO) : new Date(),
dateArray = date.toLocaleString('en-US', { hour: 'numeric', hour12: true, minute: 'numeric' }),
@ -79,84 +142,516 @@ window.onload = () => {
if (data) el.innerHTML = data;
el.style.display = displayType || "unset";
}, hide = el => el.style.removeProperty('display'),
toObj = jsonString => JSON.parse(jsonString.replace(/\\"|"(?:\\"|[^"])*"|(\/\/.*|\/\*[\s\S]*?\*\/)/g, (x, y) => y ? "" : x)),
update = data => {
try {
content.innerHTML = data.content ? markup(data.content, { replaceEmojis: true }) : '';
if (data.embed) {
let e = data.embed;
if (!allGood(e)) return;
if (e.title) display(embedTitle, markup(`${e.url ? '<a class="anchor" target="_blank" href="' + url(e.url) + '">' + e.title + '</a>' : e.title}`, { replaceEmojis: true, inlineBlock: true }));
else hide(embedTitle);
if (e.description) display(embedDescription, markup(e.description, { inEmbed: true, replaceEmojis: true }));
else hide(embedDescription);
if (e.color) embed.closest('.embed').style.borderColor = (typeof e.color === 'number' ? '#' + e.color.toString(16) : e.color);
else embed.closest('.embed').style.removeProperty('border-color');
if (e.author && e.author.name) display(embedAuthor, `
${e.author.icon_url ? '<img class="embedAuthorIcon" src="' + url(e.author.icon_url) + '">' : ''}
${e.author.url ? '<a class="embedAuthorNameLink embedLink embedAuthorName" href="' + url(e.author.url) + '" target="_blank">' + e.author.name + '</a>' : '<span class="embedAuthorName">' + e.author.name + '</span>'}`, 'flex');
else hide(embedAuthor);
if (e.thumbnail && e.thumbnail.url) embedThumbnail.src = e.thumbnail.url, embedThumbnail.style.display = 'block';
else hide(embedThumbnail);
if (e.image && e.image.url) embedImage.src = e.image.url, embedImage.style.display = 'block';
else hide(embedImage);
if (e.footer && e.footer.text) display(embedFooter, `
${e.footer.icon_url ? '<img class="embedFooterIcon" src="' + url(e.footer.icon_url) + '">' : ''}<span class="embedFooterText">
${e.footer.text}
${e.timestamp ? '<span class="embedFooterSeparator">•</span>' + tstamp(e.timestamp) : ''}</span></div>`, 'flex');
else if (e.timestamp) display(embedFooter, `<span class="embedFooterText">${tstamp(e.timestamp)}</span></div>`, 'flex');
else hide(embedFooter);
if (e.fields) {
fields.innerHTML = '';
e.fields.forEach(f => {
imgSrc = (elm, src, remove) => remove ? elm.style.removeProperty('content') : elm.style.content = `url(${src})`,
toObj = jsonString => JSON.parse(jsonString.replace(/\\"|"(?:\\"|[^"])*"|(\/\/.*|\/\*[\s\S]*?\*\/)/g, (x, y) => y ? "" : x));
buildGui = (object, opts) => {
gui.innerHTML = `
<div class="item content"><p class="ttle">Message content</p></div>
<div class="edit">
<textarea class="editContent" placeholder="Message content" autocomplete="off">${object.content || ''}</textarea>
</div>
<div class="item author rows2"><p class="ttle">Author</p></div>
<div class="edit">
<div class="linkName">
<div class="editIcon">
<span class="imgParent" ${object.embed?.author?.icon_url ? 'style="content: url(' + object.embed.author.icon_url + ')"' : ''}></span>
<input class="editAuthorLink" type="text" value="${object.embed?.author?.icon_url || ''}" placeholder="Icon URL" autocomplete="off"/>
</div>
<div class="editName">
<input class="editAuthorName" type="text" value="${object.embed?.author?.name || ''}" placeholder="Author name" autocomplete="off" />
</div>
</div>
<form method="post" enctype="multipart/form-data">
<input class="browserAuthorLink" type="file" name="file" id="file2" accept="image/png,image/gif,image/jpeg,image/webp" autocomplete="off" />
<button type="submit"></button>
<label for="file2">
<div class="browse">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svgjs="http://svgjs.com/svgjs" version="1.1" width="512" height="512" x="0" y="0" viewBox="0 0 64 64" xml:space="preserve">
<g>
<path xmlns="http://www.w3.org/2000/svg" d="m23.414 21.414 6.586-6.586v29.172c0 1.104.896 2 2 2s2-.896 2-2v-29.172l6.586 6.586c.39.391.902.586 1.414.586s1.024-.195 1.414-.586c.781-.781.781-2.047 0-2.828l-10-10c-.78-.781-2.048-.781-2.828 0l-10 10c-.781.781-.781 2.047 0 2.828.78.781 2.048.781 2.828 0z" fill="#ffffff" data-original="#000000"></path>
<path xmlns="http://www.w3.org/2000/svg" d="m50 40c-1.104 0-2 .896-2 2v8c0 1.103-.897 2-2 2h-28c-1.103 0-2-.897-2-2v-8c0-1.104-.896-2-2-2s-2 .896-2 2v8c0 3.309 2.691 6 6 6h28c3.309 0 6-2.691 6-6v-8c0-1.104-.896-2-2-2z" fill="#ffffff" data-original="#000000"></path>
</g>
</svg>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 100 100" enable-background="new 0 0 0 0" xml:space="preserve">
<circle fill="#fff" stroke="none" cx="6" cy="50" r="6">
<animateTransform attributeName="transform" dur="1s" type="translate" values="0 15 ; 0 -15; 0 15" repeatCount="indefinite" begin="0.1"></animateTransform>
</circle>
<circle fill="#fff" stroke="none" cx="30" cy="50" r="6">
<animateTransform attributeName="transform" dur="1s" type="translate" values="0 10 ; 0 -10; 0 10" repeatCount="indefinite" begin="0.2"></animateTransform>
</circle>
<circle fill="#fff" stroke="none" cx="54" cy="50" r="6">
<animateTransform attributeName="transform" dur="1s" type="translate" values="0 5 ; 0 -5; 0 5" repeatCount="indefinite" begin="0.3"></animateTransform>
</circle>
</svg>
<p></p>
</div>
</label>
</form>
</div>
<div class="item title inlineField">
<p class="ttle">Title</p>
<input class="editTitle" type="text" placeholder="Title" autocomplete="off" value="${object.embed?.title || ''}">
</div>
<div class="item description"><p class="ttle">Description</p></div>
<div class="edit">
<textarea class="editDescription" placeholder="Embed description" autocomplete="off">${object.embed?.description || ''}</textarea>
</div>
<div class="item fields"><p class="ttle">Fields</p></div>
<div class="edit"></div>
<div class="item thumbnail largeImg"><p class="ttle">Thumbnail</p></div>
<div class="edit">
<div class="linkName">
<div class="editIcon">
<span class="imgParent" ${object.embed?.thumbnail?.url ? 'style="content: url(' + object.embed.thumbnail.url + ')"' : ''}></span>
<div class="txtCol">
<input class="editThumbnailLink" type="text" value="${object.embed?.thumbnail?.url || ''}" placeholder="Thumbnail URL" autocomplete="off" />
<form method="post" enctype="multipart/form-data">
<input class="browseThumbLink" type="file" name="file" id="file3" accept="image/png,image/gif,image/jpeg,image/webp" autocomplete="off" />
<button type="submit"></button>
<label for="file3">
<div class="browse">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svgjs="http://svgjs.com/svgjs" version="1.1" width="512" height="512" x="0" y="0" viewBox="0 0 64 64" xml:space="preserve">
<g>
<path xmlns="http://www.w3.org/2000/svg" d="m23.414 21.414 6.586-6.586v29.172c0 1.104.896 2 2 2s2-.896 2-2v-29.172l6.586 6.586c.39.391.902.586 1.414.586s1.024-.195 1.414-.586c.781-.781.781-2.047 0-2.828l-10-10c-.78-.781-2.048-.781-2.828 0l-10 10c-.781.781-.781 2.047 0 2.828.78.781 2.048.781 2.828 0z" fill="#ffffff" data-original="#000000"></path>
<path xmlns="http://www.w3.org/2000/svg" d="m50 40c-1.104 0-2 .896-2 2v8c0 1.103-.897 2-2 2h-28c-1.103 0-2-.897-2-2v-8c0-1.104-.896-2-2-2s-2 .896-2 2v8c0 3.309 2.691 6 6 6h28c3.309 0 6-2.691 6-6v-8c0-1.104-.896-2-2-2z" fill="#ffffff" data-original="#000000"></path>
</g>
</svg>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 100 100" enable-background="new 0 0 0 0" xml:space="preserve">
<circle fill="#fff" stroke="none" cx="6" cy="50" r="6">
<animateTransform attributeName="transform" dur="1s" type="translate" values="0 15 ; 0 -15; 0 15" repeatCount="indefinite" begin="0.1"></animateTransform>
</circle>
<circle fill="#fff" stroke="none" cx="30" cy="50" r="6">
<animateTransform attributeName="transform" dur="1s" type="translate" values="0 10 ; 0 -10; 0 10" repeatCount="indefinite" begin="0.2"></animateTransform>
</circle>
<circle fill="#fff" stroke="none" cx="54" cy="50" r="6">
<animateTransform attributeName="transform" dur="1s" type="translate" values="0 5 ; 0 -5; 0 5" repeatCount="indefinite" begin="0.3"></animateTransform>
</circle>
</svg>
<p></p>
</div>
</label>
</form>
</div>
</div>
</div>
</div>
<div class="item image largeImg"><p class="ttle">Image</p></div>
<div class="edit">
<div class="linkName">
<div class="editIcon">
<span class="imgParent" ${object.embed?.image?.url ? 'style="content: url(' + object.embed.image.url + ')"' : ''}></span>
<div class="txtCol">
<input class="editImageLink" type="text" value="${object.embed?.image?.url || ''}" placeholder="Image URL" autocomplete="off" />
<form method="post" enctype="multipart/form-data">
<input class="browseImageLink" type="file" name="file" id="file4" accept="image/png,image/gif,image/jpeg,image/webp" autocomplete="off" />
<button type="submit"></button>
<label for="file4">
<div class="browse">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svgjs="http://svgjs.com/svgjs" version="1.1" width="512" height="512" x="0" y="0" viewBox="0 0 64 64" xml:space="preserve">
<g>
<path xmlns="http://www.w3.org/2000/svg" d="m23.414 21.414 6.586-6.586v29.172c0 1.104.896 2 2 2s2-.896 2-2v-29.172l6.586 6.586c.39.391.902.586 1.414.586s1.024-.195 1.414-.586c.781-.781.781-2.047 0-2.828l-10-10c-.78-.781-2.048-.781-2.828 0l-10 10c-.781.781-.781 2.047 0 2.828.78.781 2.048.781 2.828 0z" fill="#ffffff" data-original="#000000"></path>
<path xmlns="http://www.w3.org/2000/svg" d="m50 40c-1.104 0-2 .896-2 2v8c0 1.103-.897 2-2 2h-28c-1.103 0-2-.897-2-2v-8c0-1.104-.896-2-2-2s-2 .896-2 2v8c0 3.309 2.691 6 6 6h28c3.309 0 6-2.691 6-6v-8c0-1.104-.896-2-2-2z" fill="#ffffff" data-original="#000000"></path>
</g>
</svg>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 100 100" enable-background="new 0 0 0 0" xml:space="preserve">
<circle fill="#fff" stroke="none" cx="6" cy="50" r="6">
<animateTransform attributeName="transform" dur="1s" type="translate" values="0 15 ; 0 -15; 0 15" repeatCount="indefinite" begin="0.1"></animateTransform>
</circle>
<circle fill="#fff" stroke="none" cx="30" cy="50" r="6">
<animateTransform attributeName="transform" dur="1s" type="translate" values="0 10 ; 0 -10; 0 10" repeatCount="indefinite" begin="0.2"></animateTransform>
</circle>
<circle fill="#fff" stroke="none" cx="54" cy="50" r="6">
<animateTransform attributeName="transform" dur="1s" type="translate" values="0 5 ; 0 -5; 0 5" repeatCount="indefinite" begin="0.3"></animateTransform>
</circle>
</svg>
<p></p>
</div>
</label>
</form>
</div>
</div>
</div>
</div>
<div class="item footer rows2"><p class="ttle">Footer</p></div>
<div class="edit">
<div class="linkName">
<div class="editIcon">
<span class="imgParent" ${object.embed?.footer?.icon_url ? 'style="content: url(' + object.embed.footer.icon_url + ')"' : ''}></span>
<input class="editFooterLink" type="text" value="${object.embed?.footer?.icon_url || ''}" placeholder="Icon URL" autocomplete="off"/>
</div>
<div class="editName">
<input class="editFooterText" type="text" value="${object.embed?.footer?.text || ''}" placeholder="Footer text" autocomplete="off" />
</div>
</div>
<form method="post" enctype="multipart/form-data">
<input class="browserFooterLink" type="file" name="file" id="file" accept="image/png,image/gif,image/jpeg,image/webp" autocomplete="off" />
<button type="submit"></button>
<label for="file">
<div class="browse">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svgjs="http://svgjs.com/svgjs" version="1.1" width="512" height="512" x="0" y="0" viewBox="0 0 64 64" xml:space="preserve">
<g>
<path xmlns="http://www.w3.org/2000/svg" d="m23.414 21.414 6.586-6.586v29.172c0 1.104.896 2 2 2s2-.896 2-2v-29.172l6.586 6.586c.39.391.902.586 1.414.586s1.024-.195 1.414-.586c.781-.781.781-2.047 0-2.828l-10-10c-.78-.781-2.048-.781-2.828 0l-10 10c-.781.781-.781 2.047 0 2.828.78.781 2.048.781 2.828 0z" fill="#ffffff" data-original="#000000"></path>
<path xmlns="http://www.w3.org/2000/svg" d="m50 40c-1.104 0-2 .896-2 2v8c0 1.103-.897 2-2 2h-28c-1.103 0-2-.897-2-2v-8c0-1.104-.896-2-2-2s-2 .896-2 2v8c0 3.309 2.691 6 6 6h28c3.309 0 6-2.691 6-6v-8c0-1.104-.896-2-2-2z" fill="#ffffff" data-original="#000000"></path>
</g>
</svg>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 100 100" enable-background="new 0 0 0 0" xml:space="preserve">
<circle fill="#fff" stroke="none" cx="6" cy="50" r="6">
<animateTransform attributeName="transform" dur="1s" type="translate" values="0 15 ; 0 -15; 0 15" repeatCount="indefinite" begin="0.1"></animateTransform>
</circle>
<circle fill="#fff" stroke="none" cx="30" cy="50" r="6">
<animateTransform attributeName="transform" dur="1s" type="translate" values="0 10 ; 0 -10; 0 10" repeatCount="indefinite" begin="0.2"></animateTransform>
</circle>
<circle fill="#fff" stroke="none" cx="54" cy="50" r="6">
<animateTransform attributeName="transform" dur="1s" type="translate" values="0 5 ; 0 -5; 0 5" repeatCount="indefinite" begin="0.3"></animateTransform>
</circle>
</svg>
<p></p>
</div>
</label>
</form>
</div>`;
let fieldsEditor = gui.querySelector('.fields ~ .edit'), addField = `
<div class="addField">
<p>New Field</p>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svgjs="http://svgjs.com/svgjs" version="1.1" x="0" y="0" viewBox="0 0 477.867 477.867" xml:space="preserve">
<g>
<g xmlns="http://www.w3.org/2000/svg">
<g>
<path d="M392.533,0h-307.2C38.228,0.056,0.056,38.228,0,85.333v307.2c0.056,47.105,38.228,85.277,85.333,85.333h307.2 c47.105-0.056,85.277-38.228,85.333-85.333v-307.2C477.81,38.228,439.638,0.056,392.533,0z M443.733,392.533 c0,28.277-22.923,51.2-51.2,51.2h-307.2c-28.277,0-51.2-22.923-51.2-51.2v-307.2c0-28.277,22.923-51.2,51.2-51.2h307.2 c28.277,0,51.2,22.923,51.2,51.2V392.533z" fill="#ffffff" data-original="#000000"
></path>
</g>
</g>
<g xmlns="http://www.w3.org/2000/svg">
<g>
<path d="M324.267,221.867H256V153.6c0-9.426-7.641-17.067-17.067-17.067s-17.067,7.641-17.067,17.067v68.267H153.6 c-9.426,0-17.067,7.641-17.067,17.067S144.174,256,153.6,256h68.267v68.267c0,9.426,7.641,17.067,17.067,17.067 S256,333.692,256,324.267V256h68.267c9.426,0,17.067-7.641,17.067-17.067S333.692,221.867,324.267,221.867z" fill="#ffffff" data-original="#000000"></path>
</g>
</g>
<g xmlns="http://www.w3.org/2000/svg"></g>
<g xmlns="http://www.w3.org/2000/svg"></g>
<g xmlns="http://www.w3.org/2000/svg"></g>
<g xmlns="http://www.w3.org/2000/svg"></g>
<g xmlns="http://www.w3.org/2000/svg"></g>
<g xmlns="http://www.w3.org/2000/svg"></g>
<g xmlns="http://www.w3.org/2000/svg"></g>
<g xmlns="http://www.w3.org/2000/svg"></g>
<g xmlns="http://www.w3.org/2000/svg"></g>
<g xmlns="http://www.w3.org/2000/svg"></g>
<g xmlns="http://www.w3.org/2000/svg"></g>
<g xmlns="http://www.w3.org/2000/svg"></g>
<g xmlns="http://www.w3.org/2000/svg"></g>
<g xmlns="http://www.w3.org/2000/svg"></g>
<g xmlns="http://www.w3.org/2000/svg"></g>
</g>
</svg>
</div>`;
if (object.embed?.fields) fieldsEditor.innerHTML = object.embed.fields.filter(f => f && typeof f === 'object').map(f => `
<div class="field">
<div class="fieldNumber"></div>
<div class="fieldInner">
<div class="designerFieldName">
<input type="text" placeholder="Field name" autocomplete="off" value="${f.name}">
</div>
<div class="designerFieldValue">
<textarea placeholder="Field value" autocomplete="off">${f.value}</textarea>
</div>
</div>
<div class="inlineCheck">
<label>
<input type="checkbox" autocomplete="off" ${f.inline ? 'checked' : ''}>
<span>Inline</span>
</label>
</div>
<div class="removeBtn">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svgjs="http://svgjs.com/svgjs" version="1.1" width="512" height="512" x="0" y="0" viewBox="0 0 329.26933 329" xml:space="preserve">
<g>
<path xmlns="http://www.w3.org/2000/svg" d="m194.800781 164.769531 128.210938-128.214843c8.34375-8.339844 8.34375-21.824219 0-30.164063-8.339844-8.339844-21.824219-8.339844-30.164063 0l-128.214844 128.214844-128.210937-128.214844c-8.34375-8.339844-21.824219-8.339844-30.164063 0-8.34375 8.339844-8.34375 21.824219 0 30.164063l128.210938 128.214843-128.210938 128.214844c-8.34375 8.339844-8.34375 21.824219 0 30.164063 4.15625 4.160156 9.621094 6.25 15.082032 6.25 5.460937 0 10.921875-2.089844 15.082031-6.25l128.210937-128.214844 128.214844 128.214844c4.160156 4.160156 9.621094 6.25 15.082032 6.25 5.460937 0 10.921874-2.089844 15.082031-6.25 8.34375-8.339844 8.34375-21.824219 0-30.164063zm0 0" fill="#ffffff" data-original="#000000"/>
</g>
</svg>
<span>Remove</span>
</div>
</div>`).join('\n') + addField;
else fieldsEditor.innerHTML = addField;
gui.querySelectorAll('.removeBtn').forEach(e => {
e.addEventListener('click', el => {
fields = gui.querySelector('.fields ~ .edit');
let field = el.target.closest('.field');
if (field) {
let i = Array.from(fields.children).indexOf(field), jsonField = object.embed.fields[i];
if (jsonField) {
object.embed.fields.splice(i, 1);
field.remove();
update(object);
}
}
})
})
document.querySelectorAll('.gui > .item').forEach(e => {
e.addEventListener('click', el => {
let elm = (el.target.closest('.top>.gui>.item') || el.target);
if (elm.classList.contains('active')) window.getSelection().anchorNode !== elm && elm.classList.remove('active');
else {
let inlineField = elm.closest('.inlineField'),
input = elm.nextElementSibling.querySelector('input[type="text"]'),
txt = elm.nextElementSibling.querySelector('textarea');
elm.classList.add('active');
if (inlineField) inlineField.querySelector('.ttle~input').focus();
else if (input) {
input.focus();
input.selectionStart = input.selectionEnd = input.value.length;
} else if (txt) txt.focus();
elm.classList.contains('fields') && elm.scrollIntoView({ behavior: "smooth", block: "center" });
}
})
})
content = gui.querySelector('.editContent');
title = gui.querySelector('.editTitle');
authorName = gui.querySelector('.editAuthorName');
authorLink = gui.querySelector('.editAuthorLink');
desc = gui.querySelector('.editDescription');
thumbLink = gui.querySelector('.editThumbnailLink');
imgLink = gui.querySelector('.editImageLink');
footerText = gui.querySelector('.editFooterText');
footerLink = gui.querySelector('.editFooterLink');
fields = gui.querySelector('.fields ~ .edit');
document.querySelector('.addField').addEventListener('click', () => {
!json.embed && (json.embed = {});
let arr = json.embed.fields || [];
arr.push({ name: "Field name", value: "Field value", inline: false });
json.embed.fields = arr;
update(json);
buildGui(json, { newField: true, activate: document.querySelectorAll('.gui > .item.active') });
})
gui.querySelectorAll('textarea, input').forEach(e => e.addEventListener('input', el => {
let v = el.target.value, field = el.target.closest('.field');
if (field) {
let jsonField = json.embed.fields[Array.from(fields.children).indexOf(field)];
if (jsonField) {
if (el.target.type === 'text') jsonField.name = v;
else if (el.target.type === 'textarea') jsonField.value = v;
else jsonField.inline = el.target.checked;
} else {
let obj = {}
if (el.target.type === 'text') obj.name = v;
else if (el.target.type === 'textarea') obj.value = v;
else obj.inline = el.target.checked;
json.embed.fields.push(obj);
}
} else {
json.embed ??= {};
switch (el.target) {
case content: json.content = v; break;
case title: json.embed.title = v; break;
case authorName: json.embed.author ??= {}, json.embed.author.name = v; break;
case authorLink: json.embed.author ??= {}, json.embed.author.icon_url = v, imgSrc(el.target.previousElementSibling, v); break;
case desc: json.embed.description = v; break;
case thumbLink: json.embed.thumbnail ??= {}, json.embed.thumbnail.url = v, imgSrc(el.target.closest('.editIcon').querySelector('.imgParent'), v); break;
case imgLink: json.embed.image ??= {}, json.embed.image.url = v, imgSrc(el.target.closest('.editIcon').querySelector('.imgParent'), v); break;
case footerText: json.embed.footer ??= {}, json.embed.footer.text = v; break;
case footerLink: json.embed.footer ??= {}, json.embed.footer.icon_url = v, imgSrc(el.target.previousElementSibling, v); break;
}
}
update(json);
}))
if (opts?.activate) {
let elements = opts.activate;
Array.from(elements).map(el => el.className).map(clss => '.' + clss.split(' ').slice(0, 2).join('.'))
.forEach(clss => document.querySelectorAll(clss)
.forEach(e => e.classList.add('active')))
} else['.item.author', '.item.description'].forEach(clss => document.querySelector(clss).classList.add('active'));
if (opts?.newField) {
let last = fields.children[fields.childElementCount - 2], el = last.querySelector('.designerFieldName > input');
el.setSelectionRange(el.value.length, el.value.length); el.focus();
last.scrollIntoView({ behavior: "smooth", block: "center" });
// setTimeout(() => last.animate([
// { opacity: '.2', offset: .25 },
// { opacity: '1', offset: .5 },
// { opacity: '.2', offset: .75 },
// { opacity: '1', offset: 1 }
// ], { easing: 'ease', duration: 1500 }), 250);
}
let files = document.querySelectorAll('input[type="file"]');
files.forEach(f => f.addEventListener('change', e => {
if (f.files) {
e.target.nextElementSibling.click();
e.target.closest('.edit').querySelector('.browse').classList.add('loading');
}
}))
document.querySelectorAll('form').forEach(form => form.addEventListener('submit', e => {
e.preventDefault();
let formData = new FormData(e.target);
formData.append('file', files.files);
formData.append('datetime', '10m');
fetch('https://tempfile.site/api/files', {
method: 'POST',
body: formData,
})
.then(res => res.json())
.then(res => {
let browse = e.target.closest('.edit').querySelector('.browse');
browse.classList.remove('loading');
if (!res.ok) {
console.log(res.error);
browse.classList.add('error');
return setTimeout(() => browse.classList.remove('error'), 5000)
}
imgSrc(e.target.previousElementSibling.querySelector('.editIcon > .imgParent') || e.target.closest('.editIcon').querySelector('.imgParent'), res.link);
let input = e.target.previousElementSibling.querySelector('.editIcon > input') || e.target.previousElementSibling;
input.value = res.link;
if (input === authorLink) json.embed.author.icon_url = res.link;
else if (input === thumbLink) json.embed.thumbnail.url = res.link;
else if (input === imgLink) json.embed.image.url = res.link;
else json.embed.footer.icon_url = res.link;
update(json);
console.info(`Image (${res.link}) will be deleted in 5 minutes. To delete it now got to ${res.link.replace('/files', '/del')} and enter this code: ${res.authkey}`);
}).catch(err => `Request to tempfile.site failed with error: ${err}`)
}))
}
buildGui(json);
fields = gui.querySelector('.fields ~ .edit');
update = data => {
try {
embedContent.innerHTML = data.content ? markup(data.content, { replaceEmojis: true }) : '';
if (data.embed && Object.keys(data.embed).length) {
let e = data.embed;
if (!allGood(e)) return;
if (e.title) display(embedTitle, markup(`${e.url ? '<a class="anchor" target="_blank" href="' + url(e.url) + '">' + e.title + '</a>' : e.title}`, { replaceEmojis: true, inlineBlock: true }));
else hide(embedTitle);
if (e.description) display(embedDescription, markup(e.description, { inEmbed: true, replaceEmojis: true }));
else hide(embedDescription);
if (e.color) embed.closest('.embed').style.borderColor = (typeof e.color === 'number' ? '#' + e.color.toString(16).padStart(6, "0") : e.color);
else embed.closest('.embed').style.removeProperty('border-color');
if (e.author && e.author.name) display(embedAuthor, `
${e.author.icon_url ? '<img class="embedAuthorIcon" src="' + url(e.author.icon_url) + '">' : ''}
${e.author.url ? '<a class="embedAuthorNameLink embedLink embedAuthorName" href="' + url(e.author.url) + '" target="_blank">' + e.author.name + '</a>' : '<span class="embedAuthorName">' + e.author.name + '</span>'}`, 'flex');
else hide(embedAuthor);
if (e.thumbnail && e.thumbnail.url) embedThumbnail.src = e.thumbnail.url, embedThumbnail.style.display = 'block';
else hide(embedThumbnail);
if (e.image && e.image.url) embedImage.src = e.image.url, embedImage.style.display = 'block';
else hide(embedImage);
if (e.footer && e.footer.text) display(embedFooter, `
${e.footer.icon_url ? '<img class="embedFooterIcon" src="' + url(e.footer.icon_url) + '">' : ''}<span class="embedFooterText">
${e.footer.text}
${e.timestamp ? '<span class="embedFooterSeparator">•</span>' + tstamp(e.timestamp) : ''}</span></div>`, 'flex');
else if (e.timestamp) display(embedFooter, `<span class="embedFooterText">${tstamp(e.timestamp)}</span></div>`, 'flex');
else hide(embedFooter);
if (e.fields) {
embedFields.innerHTML = '';
e.fields.forEach(f => {
if (f.name && f.value) {
if (!f.inline) {
let el = fields.insertBefore(document.createElement('div'), null);
let el = embedFields.insertBefore(document.createElement('div'), null);
el.outerHTML = `
<div class="embedField" style="grid-column: 1 / 13;">
<div class="embedFieldName">${markup(f.name, { inEmbed: true, replaceEmojis: true, inlineBlock: true })}</div>
<div class="embedFieldValue">${markup(f.value, { inEmbed: true, replaceEmojis: true })}</div>
</div>`;
<div class="embedField" style="grid-column: 1 / 13;">
<div class="embedFieldName">${markup(f.name, { inEmbed: true, replaceEmojis: true, inlineBlock: true })}</div>
<div class="embedFieldValue">${markup(f.value, { inEmbed: true, replaceEmojis: true })}</div>
</div>`;
} else {
el = fields.insertBefore(document.createElement('div'), null);
el = embedFields.insertBefore(document.createElement('div'), null);
el.outerHTML = `
<div class="embedField ${num}" style="grid-column: ${colNum} / ${colNum + 4};">
<div class="embedFieldName">${markup(f.name, { inEmbed: true, replaceEmojis: true, inlineBlock: true })}</div>
<div class="embedFieldValue">${markup(f.value, { inEmbed: true, replaceEmojis: true })}</div>
</div>`;
<div class="embedField ${num}" style="grid-column: ${colNum} / ${colNum + 4};">
<div class="embedFieldName">${markup(f.name, { inEmbed: true, replaceEmojis: true, inlineBlock: true })}</div>
<div class="embedFieldValue">${markup(f.value, { inEmbed: true, replaceEmojis: true })}</div>
</div>`;
colNum = (colNum === 9 ? 1 : colNum + 4);
num++;
}
});
colNum = 1;
let len = e.fields.filter(f => f.inline).length;
if (len === 2 || (len > 3 && len % 2 !== 0)) {
let children = Array.from(fields.children), arr = children.filter(x => x === children[len] || x === children[len - 1]);
arr[0].style.gridColumn = '1 / 7', arr[1].style.gridColumn = '7 / 13';
}
display(fields, undefined, 'grid');
} else hide(fields);
embed.classList.remove('empty');
notif.animate({ opacity: '0', bottom: '-50px', offset: 1 }, { easing: 'ease', duration: 500 }).onfinish = () => notif.style.removeProperty('display');
twemoji.parse(msgEmbed);
} else embed.classList.add('empty');
} catch (e) {
error(e);
}
});
colNum = 1;
let len = e.fields.filter(f => f.inline).length;
if (len === 2 || (len > 3 && len % 2 !== 0)) {
let children = Array.from(embedFields.children), arr = children.filter(x => x === children[len] || x === children[len - 1]);
arr[0] && (arr[0].style.gridColumn = '1 / 7');
arr[1] && (arr[1].style.gridColumn = '7 / 13');
}
display(embedFields, undefined, 'grid');
} else hide(embedFields);
embed.classList.remove('empty');
document.querySelectorAll('.markup pre > code').forEach((block) => hljs.highlightBlock(block));
notif.animate({ opacity: '0', bottom: '-50px', offset: 1 }, { easing: 'ease', duration: 500 }).onfinish = () => notif.style.removeProperty('display');
twemoji.parse(msgEmbed);
} else embed.classList.add('empty');
} catch (e) {
error(e);
}
}
editor.on('change', editor => {
try { update(toObj(editor.getValue())); }
catch (e) {
if (editor.getValue()) return;
embed.classList.add('empty');
content.innerHTML = '';
embedContent.innerHTML = '';
}
document.querySelectorAll('.markup pre > code').forEach((block) => hljs.highlightBlock(block));
});
update(toObj(editor.getValue()));
let picker = new CP(document.querySelector('.picker'), state = { parent: document.querySelector('.cTop') });
picker.fire('change', toRGB('#41f097'));
let colRight = document.querySelector('.colRight'), removePicker = () => colRight.classList.remove('picking');
document.querySelector('.colBack').addEventListener('click', e => {
picker.self.remove(); removePicker();
})
picker.on('enter', () => colRight.classList.add('picking'))
picker.on('exit', removePicker);
document.querySelectorAll('.colr').forEach(e => e.addEventListener('click', el => {
el = el.target.closest('.colr') || el.target;
embed.closest('.embed').style.borderColor = el.style.backgroundColor;
json.embed.color = toRGB(el.style.backgroundColor, false, true);
picker.source.style.removeProperty('background');
}))
setTimeout(() => {
picker.on('change', function (r, g, b, a) {
embed.closest('.embed').style.borderColor = this.color(r, g, b);
json.embed.color = parseInt(this.color(r, g, b).slice(1), 16);
picker.source.style.background = this.color(r, g, b);
})
}, 1000)
document.querySelector('.timeText').innerText = tstamp();
document.querySelectorAll('.markup pre > code').forEach((block) => hljs.highlightBlock(block));
!window.navigator.userAgent.match(/Firefox\/[\d\.]+$/g) && // Firefox pushes the text up a little
document.querySelector('.botText').style.removeProperty('top');
document.querySelector('.opt.gui').addEventListener('click', () => {
json = toObj(editor.getValue() || '{}');
buildGui(json, { activate: activeFields });
document.body.classList.add('gui');
activeFields = null;
})
document.querySelector('.opt.json').addEventListener('click', () => {
editor.setValue(JSON.stringify(json, null, 4));
editor.refresh();
document.body.classList.remove('gui');
editor.focus();
activeFields = document.querySelectorAll('.gui > .item.active');
})
document.querySelector('.clear').addEventListener('click', () => {
json = {}
embed.style.removeProperty('border-color');
picker.source.style.removeProperty('background');
update(json); buildGui(json); editor.setValue('{}');
document.querySelectorAll('.gui>.item').forEach(e => e.classList.add('active'));
content.focus();
})
let colrs = document.querySelector('.colrs');
document.querySelector('.pickerToggle').addEventListener('click', () => colrs.classList.toggle('display'));
update(json);
};

View file

@ -0,0 +1,23 @@
The MIT License (MIT)
Copyright (c) 2020 Taufik Nurrohman
<https://github.com/taufik-nurrohman/color-picker>
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.

View file

@ -0,0 +1,129 @@
.color-picker,
.color-picker *,
.color-picker ::after,
.color-picker ::before,
.color-picker::after,
.color-picker::before {
box-sizing: border-box;
}
.color-picker {
position: absolute;
top: 0;
left: 0;
z-index: 9999;
box-shadow: 1px 3px 6px rgba(0, 0, 0, 0.5);
}
.color-picker > div {
display: flex;
height: 10em;
border: 1px solid #000;
color: #000;
}
.color-picker > div * {
border-color: inherit;
color: inherit;
}
.color-picker i {
font: inherit;
font-size: 12px;
}
.color-picker\:a,
.color-picker\:h,
.color-picker\:sv {
background-size: 100% 100%;
position: relative;
}
.color-picker\:a,
.color-picker\:h {
width: 1.5em;
border-left: 1px solid;
cursor: ns-resize;
overflow: hidden;
}
.color-picker\:a div,
.color-picker\:h div,
.color-picker\:sv div {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
.color-picker\:a i,
.color-picker\:h i {
display: block;
height: 0.5em;
position: absolute;
top: -0.25em;
right: 0;
left: 0;
z-index: 2;
}
.color-picker\:a i::before,
.color-picker\:h i::before {
display: block;
content: "";
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
border: 0.25em solid;
border-top-color: transparent;
border-bottom-color: transparent;
}
.color-picker\:sv {
width: 10em;
cursor: crosshair;
overflow: hidden;
}
.color-picker\:sv i {
display: block;
width: 0.75em;
height: 0.75em;
position: absolute;
top: -0.375em;
right: -0.375em;
z-index: 2;
}
.color-picker\:sv i::before {
display: block;
content: "";
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
border: 1px solid #fff;
border-radius: 100%;
box-shadow: 0 0 2px #000;
}
.color-picker\:a div {
z-index: 2;
}
.color-picker\:a div + div {
background-image: linear-gradient(45deg, #ddd 25%, transparent 25%, transparent 75%, #ddd 75%, #ddd 100%), linear-gradient(45deg, #ddd 25%, #fff 25%, #fff 75%, #ddd 75%, #ddd 100%);
background-size: 0.5em 0.5em;
background-position: 0 0, 0.25em 0.25em;
z-index: 1;
}
.color-picker\:h div {
background-image: linear-gradient(to top, red 0, #ff0 17%, #0f0 33%, #0ff 50%, #00f 67%, #f0f 83%, red 100%);
}
.color-picker\:sv div + div {
background-image: linear-gradient(to right, #fff, rgba(255, 255, 255, 0));
}
.color-picker\:sv div + div + div {
background-image: linear-gradient(to top, #000, rgba(0, 0, 0, 0));
}
.color-picker\:a,
.color-picker\:h,
.color-picker\:sv {
-webkit-touch-callout: none;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
-webkit-tap-highlight-color: transparent;
-webkit-tap-highlight-color: transparent;
}

View file

@ -0,0 +1,323 @@
/*!
* ==============================================================
* COLOR PICKER 2.1.6
* ==============================================================
* Author: Taufik Nurrohman <https://github.com/taufik-nurrohman>
* License: MIT
* --------------------------------------------------------------
*/
((e, t, n) => {
let r = t.documentElement,
i = "HEX",
o = "top",
u = "right",
c = "left",
l = "px",
f = e.setTimeout,
s = ["touchstart", "mousedown"],
a = ["touchmove", "mousemove"],
d = ["orientationchange", "resize"],
h = ["touchend", "mouseup"];
function p(e) {
let t,
n,
r,
i,
o,
u,
c,
l,
f = +e[0],
s = +e[1],
a = +e[2];
switch (((u = a * (1 - s)), (c = a * (1 - (o = 6 * f - (i = Math.floor(6 * f))) * s)), (l = a * (1 - (1 - o) * s)), (i = i || 0), (c = c || 0), (l = l || 0), i % 6)) {
case 0:
(t = a), (n = l), (r = u);
break;
case 1:
(t = c), (n = a), (r = u);
break;
case 2:
(t = u), (n = a), (r = l);
break;
case 3:
(t = u), (n = c), (r = a);
break;
case 4:
(t = l), (n = u), (r = a);
break;
case 5:
(t = a), (n = u), (r = c);
}
return [L(255 * t), L(255 * n), L(255 * r), w(e[3]) ? +e[3] : 1];
}
function g(e) {
let t,
n,
r = +e[0] / 255,
i = +e[1] / 255,
o = +e[2] / 255,
u = Math.max(r, i, o),
c = Math.min(r, i, o),
l = u,
f = u - c;
if (((n = 0 === u ? 0 : f / u), u === c)) t = 0;
else {
switch (u) {
case r:
t = (i - o) / f + (i < o ? 6 : 0);
break;
case i:
t = (o - r) / f + 2;
break;
case o:
t = (r - i) / f + 4;
}
t /= 6;
}
return [t, n, l, w(e[3]) ? +e[3] : 1];
}
function v(e, t) {
let n = t.touches ? t.touches[0].clientX : t.clientX,
r = t.touches ? t.touches[0].clientY : t.clientY,
i = E(e);
return [n - i[0], r - i[1]];
}
function b(e, t) {
if (e === t) return e;
for (; (e = e.parentElement) && e !== t; );
return e;
}
function m(e) {
e && e.preventDefault();
}
function C(e, t, n) {
for (let r = 0, i = t.length; r < i; ++r) e.removeEventListener(t[r], n, !1);
}
function k(e, t, n) {
for (let r = 0, i = t.length; r < i; ++r) e.addEventListener(t[r], n, !1);
}
function y(e) {
return "function" == typeof e;
}
function w(e) {
return void 0 !== e && null !== e;
}
function x(e) {
return "string" == typeof e;
}
function E(t) {
let n, i, o;
return t === e ? ((n = e.pageXOffset || r.scrollLeft), (i = e.pageYOffset || r.scrollTop)) : ((n = (o = t.getBoundingClientRect()).left), (i = o.top)), [n, i];
}
function P(t) {
return t === e ? [e.innerWidth, e.innerHeight] : [t.offsetWidth, t.offsetHeight];
}
function H(e, t, n) {
e.style[t] = n;
}
function M(e, t) {
return e < t[0] ? t[0] : e > t[1] ? t[1] : e;
}
function O(e, t) {
return parseInt(e, t || 10);
}
function X(e, n, r) {
return (e = t.createElement(e)), n && n.appendChild(e), r && (e.className = r), e;
}
function L(e) {
return Math.round(e);
}
function Y(e, t) {
return e.toString(t);
}
((e) => {
(e[i] = (e) => {
if (x(e)) {
let t = (e = e.trim()).length;
if ((4 !== t && 7 !== t) || "#" !== e[0]) {
if ((5 === t || 9 === t) && "#" === e[0] && /^#([a-f\d]{3,4}){1,2}$/i.test(e))
return 5 === t ? [O(e[1] + e[1], 16), O(e[2] + e[2], 16), O(e[3] + e[3], 16), O(e[4] + e[4], 16) / 255] : [O(e[1] + e[2], 16), O(e[3] + e[4], 16), O(e[5] + e[6], 16), O(e[7] + e[8], 16) / 255];
} else if (/^#([a-f\d]{3}){1,2}$/i.test(e)) return 4 === t ? [O(e[1] + e[1], 16), O(e[2] + e[2], 16), O(e[3] + e[3], 16), 1] : [O(e[1] + e[2], 16), O(e[3] + e[4], 16), O(e[5] + e[6], 16), 1];
return [0, 0, 0, 1];
}
return "#" + ("000000" + Y(+e[2] | (+e[1] << 8) | (+e[0] << 16), 16)).slice(-6) + (w(e[3]) && e[3] < 1 ? Y(L(255 * e[3]) + 65536, 16).substr(-2) : "");
}),
(e.instances = {}),
(e.state = { class: "color-picker", color: i, parent: null }),
(e.version = "2.1.6");
})(
(e.CP = function (n, O) {
if (!n) return;
let L = this,
Y = e.CP,
I = {},
N = Object.assign({}, Y.state, x(O) ? { color: O } : O || {}),
T = N.class,
W = X("div", 0, T);
if (n.CP) return L;
if (!(L instanceof Y)) return new Y(n, O);
(Y.instances[n.id || n.name || Object.keys(Y.instances).length] = L), (n.CP = 1), (L.visible = !1);
let $,
z,
B,
D,
R = t.body,
S = le(),
q = g(S),
A = X("div", W),
F = X("div", A, T + ":sv"),
G = X("div", A, T + ":h"),
J = X("div", A, T + ":a"),
K = X("div", F),
Q = (X("div", F), X("div", F), X("i", F)),
U = (X("div", G), X("i", G)),
V = X("div", J),
Z = (X("div", J), X("i", J)),
_ = 0,
ee = 0,
te = 0,
ne = 0,
re = 0,
ie = 0;
function oe(e) {
if (I.focus) ue("focus", S);
else {
let t = e.target;
n === b(t, n) ? !ce() && $(N.parent) : z();
}
}
function ue(e, t) {
if (!w(I[e])) return L;
for (let n = 0, r = I[e].length; n < r; ++n) I[e][n].apply(L, t);
return L;
}
function ce() {
return W.parentNode;
}
function le(e) {
let t,
r = Y[y(Y[N.color]) ? N.color : i];
return (t = n.dataset.color) ? (w(e) ? (n.dataset.color = r(t)) : r(t)) : (t = n.value) ? (w(e) ? (n.value = r(t)) : r(t)) : (t = n.textContent) ? (w(e) ? (n.textContent = r(t)) : r(t)) : w(e) ? void 0 : [0, 0, 0, 1];
}
!(function i(y, x) {
(q = g((S = le()))),
y || ((x || N.parent || R).appendChild(W), (L.visible = !0)),
($ = (e) => (i(0, e), ue("enter", S), L)),
(z = () => {
let n = ce();
return n && (n.removeChild(W), (L.current = null), (L.visible = !1)), C(F, s, ge), C(G, s, ve), C(J, s, be), C(t, a, he), C(t, h, pe), C(e, d, D), ue("exit", S), L;
}),
(B = (t) => {
let i = P(e),
u = P(r),
f = i[0] - u[0],
s = i[1] - r.clientHeight,
a = E(e),
d = E(n),
h = P(W),
p = h[0],
g = h[1],
v = d[0] + a[0],
b = d[1] + a[1] + P(n)[1];
if ("object" == typeof t) w(t[0]) && (v = t[0]), w(t[1]) && (b = t[1]);
else {
let e = a[0],
t = a[1],
n = a[0] + i[0] - p - f,
r = a[1] + i[1] - g - s;
(v = M(v, [e, n]) >> 0), (b = M(b, [t, r]) >> 0);
}
return H(W, c, v + l), H(W, o, b + l), ue("fit", S), L;
}),
(D = () => B());
let j = P(F),
O = j[0],
X = j[1],
Y = P(Q),
T = Y[0],
A = Y[1],
fe = P(G)[1],
se = P(U)[1],
ae = P(J)[1],
de = P(Z)[1];
function he(e) {
ne &&
(function (e) {
let t = v(F, e),
n = M(t[0], [0, O]),
r = M(t[1], [0, X]);
(q[1] = 1 - (O - n) / O), (q[2] = (X - r) / X), me();
})(e),
re &&
(function (e) {
(q[0] = (fe - M(v(G, e)[1], [0, fe])) / fe), me();
})(e),
ie &&
(function (e) {
(q[3] = (ae - M(v(J, e)[1], [0, ae])) / ae), me();
})(e),
(S = p(q)),
(ne || re || ie) && (ue(_ || ee || te ? "start" : "drag", S), ue("change", S)),
(_ = ee = te = 0);
}
function pe(e) {
S = p(q);
let t = e.target,
r = n === b(t, n),
i = W === b(t, W);
(L.current = null), r || i ? i && (ne || re || ie) && ue("stop", S) : I.blur ? ue("blur", S) : ce() && z(), (ne = re = ie = 0);
}
function ge(e) {
(L.current = F), (_ = ne = 1), he(e), m(e);
}
function ve(e) {
(L.current = G), (ee = re = 1), he(e), m(e);
}
function be(e) {
(L.current = J), (te = ie = 1), he(e), m(e);
}
function me() {
var e;
w((e = q)[1]) && H(Q, u, O - T / 2 - O * +e[1] + l), w(e[2]) && H(Q, o, X - A / 2 - X * +e[2] + l), w(e[0]) && H(U, o, fe - se / 2 - fe * +e[0] + l), w(e[3]) && H(Z, o, ae - de / 2 - ae * +e[3] + l);
let t = p(q),
n = p([q[0], 1, 1]);
H(K, "backgroundColor", "rgb(" + n[0] + "," + n[1] + "," + n[2] + ")"), H(V, "backgroundImage", "linear-gradient(rgb(" + t[0] + "," + t[1] + "," + t[2] + "),transparent)");
}
y
? (k(n, s, oe),
f(() => {
ue("change", S);
}, 1))
: (k(F, s, ge), k(G, s, ve), k(J, s, be), k(t, a, he), k(t, h, pe), k(e, d, D), B()),
(L.get = () => le()),
(L.set = (e, t, n, r) => ((q = g([e, t, n, r])), me(), L)),
me();
})(1),
(L.color = (e, t, n, r) => Y[y(Y[N.color]) ? N.color : i]([e, t, n, r])),
(L.current = null),
(L.enter = $),
(L.exit = z),
(L.fire = ue),
(L.fit = B),
(L.hooks = I),
(L.off = function (e, t) {
if (!w(e)) return (I = {}), L;
if (w(I[e]))
if (w(t)) {
for (let n = 0, r = I[e].length; n < r; ++n) t === I[e][n] && I[e].splice(n, 1);
0 === j && delete I[e];
} else delete I[e];
return L;
}),
(L.on = function (e, t) {
return w(I[e]) || (I[e] = []), w(t) && I[e].push(t), L;
}),
(L.pop = () => (n.CP ? (delete n.CP, C(n, s, oe), z(), ue("pop", S)) : L)),
(L.self = W),
(L.source = n),
(L.state = N),
(L.value = (e, t, n, r) => (L.set(e, t, n, r), ue("change", [e, t, n, r])));
})
);
})(window, document);

BIN
assets/media/gui.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 324 KiB

BIN
assets/media/json.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 366 KiB

View file

@ -23,73 +23,146 @@
<script src="https://unpkg.com/jsonlint@1.6.3/web/jsonlint.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.58.3/addon/lint/lint.min.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.58.3/addon/lint/lint.min.js"></script>
<script src="https://glitchii.github.io/embedbuilder/assets/js/components.js"></script>
<script src="./assets/libs/color-picker/color-picker.min.js"></script>
<link rel="stylesheet" href="./assets/libs/color-picker/color-picker.min.css">
<script src="./assets/js/components.js"></script>
<script src="./assets/js/index.js"></script>
</head>
<body>
<body class="gui">
<div class="main">
<section class="side1">
<div class="top item">
<textarea style="display: none;">
{
"content": "You can~~not~~ do `this`.```py\nAnd this.\nprint('Hi')```\n*italics* or _italics_ __*underline italics*__\n**bold** __**underline bold**__\n***bold italics*** __***underline bold italics***__\n__underline__ ~~Strikethrough~~",
"embed": {
"title": "Hello ~~people~~ world :wave:",
"description": "You can use [links](https://discord.com) or emojis :smile: 😎\n```\nAnd also code blocks```",
"color": 4321431,
"timestamp": "2020-12-08T13:37:35.401Z",
"url": "https://discord.com",
"author": {
"name": "Name",
"url": "https://discord.com",
"icon_url": "https://unsplash.it/100"
},
"thumbnail": {
"url": "https://unsplash.it/200"
},
"image": {
"url": "https://unsplash.it/380/200"
},
"footer": {
"text": "Footer text",
"icon_url": "https://unsplash.it/100"
},
"fields": [
{
"name": "Field 1, *lorem* **ipsum**, ~~dolor~~",
"value": "Field value"
},
{
"name": "Field 2",
"value": "You can use custom emojis &lt;:Kekwlaugh:722088222766923847&gt;. &lt;:GangstaBlob:742256196295065661&gt;",
"inline": false
},
{
"name": "Inline field",
"value": "Fields can be inline",
"inline": true
},
{
"name": "Inline field",
"value": "*Lorem ipsum*",
"inline": true
},
{
"name": "Inline field",
"value": "value",
"inline": true
},
{
"name": "Another field",
"value": "> Nope, didn't forget about code blocks",
"inline": false
}
]
}
}
</textarea>
<div class="chooser">
<div class="back"></div>
<div class="gui opt">
<p>GUI</p>
</div>
<div class="json opt">
<p>JSON</p>
</div>
<div class="clear">
<svg title="clear everything" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 1000 1000" xml:space="preserve">
<g>
<path d="M740.4,401.4c-46-25.4-92.5-49.9-139.1-74.2c-36.3-18.9-73.3-19.2-110-0.9c-22,11-38.8,27.5-50.4,49.9c116.5,62,232.2,123.6,348.7,185.6c2.2-5.1,4.4-9.3,6-13.7C816.7,491.3,794.5,431.2,740.4,401.4z" style="fill: #fff;"></path>
<path d="M875.6,35.1c-9.2-12.8-21.9-20.4-37.2-23.8c-16.7-3.7-26.1,0.2-35,14.3c-53,84.6-106,169.2-159,253.8c-1.7,2.7-3.2,5.4-4.8,8.1c1,1.1,1.5,2,2.3,2.4c36.2,19.3,72.4,38.6,109.1,58.2c1.3-2.1,2-3.1,2.6-4.2c41.6-93.9,83.1-187.8,124.8-281.6C882.7,52.3,881.7,43.5,875.6,35.1z" style="fill: #fff;"></path>
<path d="M754.3,597.7c7.1-18.1-1.8-38.5-19.9-45.6c-18-7.2-38.5,1.7-45.6,19.8c-3.7,9.4-80.7,208.2-18.2,347.6c-29.6-0.3-76.3-7.1-141.9-31.8c-12.2-38-20.9-97.3,5.7-166.9c0,0-63.7,72.8-74.3,137.5c-13.7-6.6-28-13.8-43-21.8c-15-8.1-28.9-16-42-23.8c48.1-44.6,73.5-137.9,73.5-137.9c-43.3,60.6-97.5,86.2-135.9,97c-57.1-41.1-88.6-76.3-105.1-100.6c150.8-25,273.9-199.1,279.7-207.4c11.1-15.9,7.2-37.9-8.7-48.9c-15.9-11.2-37.8-7.2-49,8.7c-1.4,1.9-137.8,193.7-271.7,179.5c-10.4-1.1-21,2.5-28.6,10c-7.5,7.5-11.3,17.9-10.2,28.5c1.3,12.4,19.5,125.3,264.8,256.9C522.1,972.6,615.5,990,672.6,990c44.3,0,66.9-10.4,71.7-13c9.4-4.9,16-13.8,18.1-24.3c2.1-10.4-0.7-21.2-7.5-29.4C668.7,819.5,753.5,599.9,754.3,597.7z" style="fill: #fff;"></path>
</g>
</svg>
</div>
<div class="pickerToggle">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 512 512" xml:space="preserve">
<path style="fill:#D8D8DA;" d="M256,0C114.615,0,0,114.615,0,256s114.615,256,256,256s256-114.615,256-256S397.385,0,256,0z M256,336.842c-44.648,0-80.842-36.194-80.842-80.842s36.194-80.842,80.842-80.842s80.842,36.194,80.842,80.842 S300.648,336.842,256,336.842z"></path>
<path style="fill:#D4B6E6;" d="M282.947,188.632h220.076C485.09,122.726,441.507,67.394,383.64,34.044L229.053,188.632H282.947z"></path>
<path style="fill:#EBAFD1;" d="M229.053,188.632L383.639,34.044C346.068,12.39,302.482,0,256,0c-23.319,0-45.899,3.135-67.368,8.978 v220.075L229.053,188.632z"></path>
<path style="fill:#E07188;" d="M188.632,229.053V8.978C122.726,26.91,67.394,70.493,34.045,128.36l154.586,154.588V229.053z"></path>
<g>
<polygon style="fill:#D8D8DA;" points="188.632,229.053 229.053,188.633 282.947,188.633 282.947,188.632 229.053,188.632 "></polygon>
<polygon style="fill:#D8D8DA;" points="229.053,323.367 188.632,282.947 229.053,323.368 282.947,323.368 323.368,282.947 282.947,323.367 "></polygon>
</g>
<path style="fill:#B4D8F1;" d="M503.024,188.632H282.947v0.001h0.958l39.463,40.42L477.955,383.64 C499.611,346.068,512,302.482,512,256C512,232.681,508.865,210.099,503.024,188.632z"></path>
<path style="fill:#ACFFF4;" d="M323.368,282.947v220.075c65.905-17.932,121.238-61.517,154.586-119.382L323.368,229.053V282.947z"></path>
<path style="fill:#95D5A7;" d="M282.947,323.368L128.361,477.956C165.932,499.61,209.518,512,256,512 c23.319,0,45.899-3.135,67.368-8.977V282.947L282.947,323.368z"></path>
<path style="fill:#F8E99B;" d="M229.053,323.368H8.976C26.91,389.274,70.493,444.606,128.36,477.956l154.588-154.588H229.053z"></path>
<path style="fill:#EFC27B;" d="M188.632,282.947L34.045,128.36C12.389,165.932,0,209.518,0,256c0,23.319,3.135,45.901,8.976,67.368 h220.076L188.632,282.947z"></path>
<polygon style="fill:#D8D8DA;" points="283.905,188.633 282.947,188.633 323.368,229.053 "></polygon>
<path style="fill:#B681D5;" d="M503.024,188.632C485.09,122.726,441.507,67.394,383.64,34.044L256,161.684v26.947h26.947H503.024z"></path>
<path style="fill:#E592BF;" d="M383.639,34.044C346.068,12.39,302.482,0,256,0v161.684L383.639,34.044z"></path>
<path style="fill:#80CB93;" d="M256,350.316V512c23.319,0,45.899-3.135,67.368-8.977V282.947l-40.421,40.421L256,350.316z"></path>
<polygon style="fill:#F6E27D;" points="282.947,323.368 256,323.368 256,350.316 "></polygon>
<g></g>
<g></g>
<g></g>
<g></g>
<g></g>
<g></g>
<g></g>
<g></g>
<g></g>
<g></g>
<g></g>
<g></g>
<g></g>
<g></g>
<g></g>
</svg>
</div>
</div>
<div class="top item">
<div class="gui"></div>
<div class="editorHolder"></div>
</div>
<div class="bottom item">
<div class="colrs">
<div></div>
<div class="col colLeft">
<div class="picker">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svgjs="http://svgjs.com/svgjs" version="1.1" x="0" y="0" viewBox="0 0 390.954 390.955" xml:space="preserve">
<g>
<g xmlns="http://www.w3.org/2000/svg">
<g>
<path d="M377.314,27.704C360.761,0.494,325.283-8.145,298.076,8.41l-52.561,31.977l-3.607-5.932 c-10.484-17.229-32.947-22.7-50.179-12.218C174.5,32.72,169.032,55.184,179.512,72.415l7.162,11.771L60.314,161.652 c-11.612,7.065-30.483,32.364-35.989,39.95c-2.97,4.09-3.191,9.563-0.565,13.881l24.784,40.738 c2.627,4.317,7.591,6.637,12.587,5.88c9.269-1.402,40.41-6.529,52.024-13.596l126.357-77.467l7.161,11.771 c10.481,17.229,32.946,22.7,50.178,12.217c17.229-10.481,22.699-32.946,12.217-50.177l-3.607-5.93l52.561-31.978 C385.229,90.389,393.868,54.912,377.314,27.704z M100.124,227.084l-0.694-59.882l85.469-52.59 c0.715,8.641,3.392,17.25,8.204,25.161c4.812,7.911,11.229,14.245,18.571,18.853L100.124,227.084z" fill="#ffffff" data-original="#000000"></path>
<path d="M52.666,276.584c-1.823-1.458-4.413-1.459-6.238-0.003C44.745,277.922,5.23,309.82,5.23,343.554 c0,27.909,18.223,47.4,44.314,47.4c26.836,0,46.314-19.936,46.314-47.4C95.859,311.472,54.43,277.995,52.666,276.584z M55.582,378.402c-0.414,0.104-0.829,0.155-1.237,0.155c-2.231,0-4.266-1.506-4.842-3.769c-0.68-2.672,0.931-5.389,3.6-6.075 c0.915-0.241,20.916-5.754,20.913-25.823c0-2.762,2.237-5,4.999-5.001c2.762,0,5.001,2.238,5.001,4.999 C84.02,365.254,65.417,375.898,55.582,378.402z" fill="#ffffff" data-original="#000000"></path>
</g>
</g>
<g xmlns="http://www.w3.org/2000/svg">
</g>
<g xmlns="http://www.w3.org/2000/svg">
</g>
<g xmlns="http://www.w3.org/2000/svg">
</g>
<g xmlns="http://www.w3.org/2000/svg">
</g>
<g xmlns="http://www.w3.org/2000/svg">
</g>
<g xmlns="http://www.w3.org/2000/svg">
</g>
<g xmlns="http://www.w3.org/2000/svg">
</g>
<g xmlns="http://www.w3.org/2000/svg">
</g>
<g xmlns="http://www.w3.org/2000/svg">
</g>
<g xmlns="http://www.w3.org/2000/svg">
</g>
<g xmlns="http://www.w3.org/2000/svg">
</g>
<g xmlns="http://www.w3.org/2000/svg">
</g>
<g xmlns="http://www.w3.org/2000/svg">
</g>
<g xmlns="http://www.w3.org/2000/svg">
</g>
<g xmlns="http://www.w3.org/2000/svg">
</g>
</g>
</svg>
</div>
<div class="colr" style="background: #41f097"></div>
</div>
<div class="col colRight">
<div class="colBack">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svgjs="http://svgjs.com/svgjs" version="1.1" width="512" height="512" x="0" y="0" viewBox="0 0 512 512" xml:space="preserve"><g><g xmlns="http://www.w3.org/2000/svg"><path d="m377 91h-362c-8.291 0-15 6.709-15 15v30c0 8.291 6.709 15 15 15h362c41.353 0 75 33.647 75 75s-33.647 75-75 75h-121v-45c0-5.742-3.281-10.986-8.452-13.491s-11.323-1.846-15.85 1.714l-94.995 75c-3.604 2.842-5.698 7.192-5.698 11.777s2.095 8.936 5.698 11.777l94.995 75c4.554 3.569 10.688 4.222 15.85 1.714 5.171-2.504 8.452-7.749 8.452-13.491v-45h121c74.443 0 135-60.557 135-135s-60.557-135-135-135z" fill="#ffffff" data-original="#000000"></path></g></g></svg>
</div>
<div class="cTop">
<h2>Embed Colour</h2>
<p class="desc">Pick the embed colour</p>
</div>
<div class="pallets">
<div class="colr" class="colr" style="background: #00bb9c"></div>
<div class="colr" style="background: #00cb74"></div>
<div class="colr" style="background: #0098d9"></div>
<div class="colr" style="background: #a05bb4"></div>
<div class="colr" style="background: #f52565"></div>
<div class="colr" style="background: #f6c42f"></div>
<div class="colr" style="background: #ef7f31"></div>
<div class="colr" style="background: #f24e43"></div>
<div class="colr" style="background: #93a5a6"></div>
<div class="colr" style="background: #5c7d8a"></div>
<div class="colr" style="background: #00806a"></div>
<div class="colr" style="background: #008a4e"></div>
</div>
</div>
</div>
</div>
<div class="bottom item"></div>
</section>
<section class="side2">
<div class="msgEmbed">
@ -118,6 +191,7 @@
<div class="bottomSide">
<div class="notification">There is an error</div>
</div>
<div class="emptyTxt">Nothing here</div>
</section>
</div>
</body>