-
Notifications
You must be signed in to change notification settings - Fork 2
/
index.html
202 lines (196 loc) · 9.08 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
<title>URL Shortener</title>
<meta property="og:type" content="website" />
<meta property="og:image" content="https://slight.gq/favicon.png">
<link rel="icon" type="image/png" href="/favicon.png" />
<link rel="icon" type="image/png" href="https://slight.gq/favicon.png" />
<meta property="og:title" content="Slight.gq – The best URL shortener" />
<meta property="og:url" content="https://slight.gq" />
<meta property="twitter:card" content="summary_small_image" />
<meta name="theme-color" content="#10B981" />
<meta property="og:description" content="
Slight.gq is a super easy to use, quick, no tracking URL shortener. It supports:
- ✨ Custom ID's (https://slight.gq/anything)
- ✏️ Editing links (by setting a password when creating them)
- 🚫 No tracking
- ⏩ Speed - super fast
- 💸 Free: It's totally free.
- 👨💻 Open source: Just go to https://slight.gq/__repl to see the code.
">
<noscript>
<center style="height: 100vh; width: 100vw; background: white; z-index: 10000; display: flex; justify-content: center; align-items: center; flex-direction: column;">
<h1 class="text-center text-gray-700 text-5xl block">Idiot</h1>
<i class="block">
<p>Turn on JavaScript >=(</p>
</i>
</center>
</noscript>
<link type="application/json+oembed" href="https://slight.gq/embed.json" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script src="https://code.iconify.design/1/1.0.7/iconify.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/node-snackbar/0.1.16/snackbar.min.js" integrity="sha512-iILlngu0qmiyIkOH6MV1RWSya+DL2uzo0cb/nKR4hqwz9H+Xnop1++f8TMw1j5CdbutXGkBUyfRUfg/hmNBfZg==" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/node-snackbar/0.1.16/snackbar.css" integrity="sha512-mMqvQEYxSHpo1H5EeRLrfMxwcRH8DKeZWchEYj6QX7Lu9xngntPbcXXrQ7Ls2gEsyNlh1UwT+thZUcSIpG45Wg==" crossorigin="anonymous" />
<link href="https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css" rel="stylesheet" />
<style>
@import url('https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap');
* {
font-family: "Montserrat", sans-serif;
transition-property: background-color, color, box-shadow !important;
transition-duration: .4s !important;
}
</style>
<script src="https://bijou.js.org/bijou.js" type="module"></script>
<html>
<style>
#message-box * {
display: inline !important;
}
#message-box .iconify {
cursor: pointer !important;
transition: color .3s ease;
}
#message-box .iconify:hover {
color: #555;
}
</style>
<body style="visibility: hidden;" onload="display()">
<div id="app" class="inset-center h-full flex flex-col justify-center items-center" style="max-width: 600px; width: 60vw;">
<h1 class="text-center text-gray-600 text-2xl font-extrabold m-3"> URL Shortener </h1>
<span id="message-box" v-if="shortened" class="p-2 bg-green-100 ring-2 ring-green-500 text-gray-500 my-3 break-all w-full h-auto italic inline-block rounded text-md text-center">
<span v-html="shortened"></span>
<span class="inline" v-if="realUrl" v-on:click="copy">
<span class="iconify" data-icon="akar-icons:copy"></span>
</span>
</span>
<div class="input flex flex-col sm:flex-row items-center justify-center" style="min-width: 100%;">
<input v-on:change="changeUrl" v-on:blur="changeUrl" v-on:keyup="changeUrl" class="w-full focus:ring-4 focus:outline-none focus:ring-green-500 rounded focus:ring-opacity-50 border-2 border-green-500 transition-shadow transition-colors p-2 text-gray-600 shadow-xl text-sm hover:shadow-2xl flex my-2" type="url" name="url" id="url" style="flex: 10" placeholder="Shorten a url!" autofocus spellcheck="false" />
<button id="button" v-on:click="shortenurl" class="my-2 flex-1 w-full bg-green-500 focus:outline-none focus:ring-4 focus:ring-green-500 focus:ring-opacity-50 hover:bg-green-700 text-white font-bold py-2 px-4 md:px-6 lg:px-8 rounded transition-colors transition-shadow flex text-center ml-1">
<span v-if='status==="loading"'><svg style="margin: 0 auto;" class="inline-block animate-spin h-3 w-3 text-white text-center w-full" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg></span>
<span v-else class="text-center w-full"> Go </span>
</button>
</div>
<span v-if="newurl.replace(/[^a-z]/g, '').length && re.test(newurl)" class="w-full sm:w-6/12 text-center text-sm mt-6 text-gray-400 font-light">The new URL will be <span class="bg-green-400 rounded inline-block text-white">https://slight.gq/{{id}}</span><br><a class="underline inline text-green-600 hover:text-green-700" href="javascript:void(0)" v-on:click="newId">Change ID</a>
<a class="underline inline text-green-600 hover:text-green-700" v-if="password" v-on:click="setPassword" href="javascript:void(0)">Change password</a>
<a class="underline inline text-green-600 hover:text-green-700" v-else v-on:click="setPassword" href="javascript:void(0)">Set password</a></span>
<span v-else-if="newurl" class="w-full sm:w-6/12 text-center italic text-sm text-gray-400 mt-6 font-light">Invalid URL format</span>
<span v-else class="w-full sm:w-6/12 text-center italic text-sm mt-6 text-gray-400 font-light">Type something into the URL box!</span>
</div>
<span class="text-gray-500 text-sm" style="position: absolute; bottom: 5px; left: 5px;">Bookmarklet: <a class="italic text-sm text-green-600 hover:text-green-700 cursor-pointer" href='javascript:(async()=>{var e=await fetch("https://slight.gq/shorten",{method:"POST",body:JSON.stringify({url:window.location.href,id:prompt("ID",function(){var t=46656*Math.random()|0,e=46656*Math.random()|0;return t=("000"+t.toString(36)).slice(-3),e=("000"+e.toString(36)).slice(-3),t+e}())})}).then(t=>t.json());e.url?(t=document.createElement("textarea"),document.body.appendChild(t),t.value=e.url,t.select(),document.execCommand("copy"),t.remove()):alert(e.error||e.message)})();'>Shorten</a></span>
</body>
</html>
<script>
function display() {
document.body.style.visibility = 'visible';
}
// display();
var app = new Vue({
el: "#app",
data: {
newurl: "",
shortened: "",
realUrl: "",
status: "normal",
id: genId(),
password: "",
re: /^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&\/=]*)$/
},
methods: {
changeUrl: (e) => {
app.newurl = document.querySelector("input").value;
if (e.keyCode === 13) {
app.shortenurl();
}
},
copy: () => {
let txt = document.createElement("textarea");
txt.value = app.realUrl;
document.body.appendChild(txt);
txt.select();
document.execCommand("copy");
txt.remove();
Snackbar.show({
text: "Copied to clipboard",
actionText: 'ok',
});
},
shortenurl: async () => {
app.status = 'loading';
var data = {
url: document.querySelector("input").value,
id: app.id
}
if (app.password) {
data.password = app.password;
}
let j = await fetch("/shorten", {
method: "POST",
body: JSON.stringify(data),
}).then((res) => res.json());
app.shortened = j.error || j.message;
if (j.url) {
app.realUrl = j.url;
console.log(app.realUrl)
let txt = document.createElement("textarea");
txt.value = j.url;
document.body.appendChild(txt);
txt.select();
document.execCommand("copy");
txt.remove();
Snackbar.show({
text: "Copied to clipboard",
actionText: 'ok',
});
}
app.status = 'normal'
app.id = genId();
},
setPassword: () => {
app.password = prompt("What password would you like? (This password can be used to update your shortened URL)", app.password || "");
},
newId: () => {
let p = prompt("New ID? (https://slight.gq/[id])", genId())
if (!p) return;
while (!/[a-zA-Z0-9]/gi.test(p)) {
p = prompt("Invalid ID, please only use alphanumeric characters.", ">=(")
if (!p) return;
}
app.id = p;
document.querySelector("input").focus();
}
},
});
function genId() {
var firstPart = (Math.random() * 46656) | 0;
var secondPart = (Math.random() * 46656) | 0;
firstPart = ("000" + firstPart.toString(36)).slice(-3);
secondPart = ("000" + secondPart.toString(36)).slice(-3);
return firstPart + secondPart;
}
</script>
<style>
.inset-center {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.snackbar-container {
transition: all .3s ease !important;
background: white !important;
border: 1px solid #ccc;
color: #333 !important;
}
.snackbar-container * {
color: #333 !important;
transition: all .3s ease !important;
}
.snackbar-container button.action {
background: rgba(0, 182, 112, 0.795);
padding: 4px;
color: white;
border-radius: 3px;
}
</style>