mirror of
https://github.com/lavafroth/lavafroth.github.io.git
synced 2026-06-09 12:11:21 -03:00
deploy: 4392446af0
This commit is contained in:
@@ -23,15 +23,16 @@
|
||||
|
||||
|
||||
|
||||
⧉ Copy
|
||||
|
||||
|
||||
|
||||
|
||||
'><meta name=author content><link rel="preload stylesheet" as=style href=https://lavafroth.is-a.dev/app.min.css><link rel=preload as=image href=../header.svg><link as=font href=https://lavafroth.is-a.dev/latinmodern-math.otf><link rel=preload as=image href=https://lavafroth.is-a.dev/github.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/about.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/art.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/rss.svg><link rel=icon href=https://lavafroth.is-a.dev/favicon.png><link rel=blog-icon href=https://lavafroth.is-a.dev/icon.png></head><body><header><a class=site-name href=https://lavafroth.is-a.dev/><svg viewBox="0 0 8790 2080"><path d="M80 1935V465h216v1270h286v2e2zm853 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm1025 528L2014 465h210l108 868 8 142h12l8-142 108-868h210l-224 1470zm813 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm851 528V465h514v222h-298v386h2e2v222h-2e2v640zm910 0V465h216q194 0 286 108 92 107 92 316 0 124-43 215-44 90-106 132l147 699h-216l-122-620h-38v620zm216-820q60 0 95-26 35-27 50-76t15-116q0-105-34-161-35-57-126-57zm1084 836q-90 0-154-42-65-42-99-114-35-72-35-162V767q0-91 35-162 34-72 99-114 64-42 154-42t155 42q64 42 99 114 34 72 34 162v866q0 90-34 162-35 72-99 114-65 42-155 42zm0-210q40 0 56-33 16-34 16-75V767q0-41-17-74-17-34-55-34-37 0-54 34-18 33-18 74v866q0 41 17 75 17 33 55 33zm890 194V687h-204V465h624v222h-204v1248zm828 0V465h216v608h168V465h216v1470h-216v-640h-168v640z"/></svg></a><nav><a style=--url:url(./github.svg) href=https://github.com/lavafroth aria-label=github target=_blank></a><a href=../about/ aria-label=about style=--url:url(./about.svg)></a><a href=../art/ aria-label=art style=--url:url(./art.svg)></a><a href=../index.xml aria-label=rss style=--url:url(./rss.svg)></a><nav></header><main><hgroup data-pagefind-body><p data-pagefind-ignore><time>Jan 1, 1 | 1 minute read</time></p><h1 data-pagefind-meta=title></h1></hgroup><section class=post-content data-pagefind-body><!doctype html><html lang=en><head><meta charset=UTF-8><title>Easy SSH tunnel</title><meta name=viewport content="width=device-width,initial-scale=1"><meta name=description content><style>*{font-family:monospace}body{background:oklch(29.3% .136 325.661)}input{outline:none;color:#eee;border:none;background:oklch(29.3% .136 325.661);&:invalid { background:oklch(40.8% 0.153 2.432); }}.post-content>div{margin:1rem auto;label:not([for=direction]) { padding:.5rem; background:lab(78.5378% 39.3533 -32.9615); color:oklch(29.3% 0.136 325.661); }}.grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));grid-template-rows:repeat(3,minmax(0,1fr));justify-content:space-between;align-items:center; *{ text-align: center; } label[for=direction] { user-select: none; grid-row: span 2 / span 2; grid-column-start: 2; color: #eee; &::after { display: block; content: '<'; } } input[type="checkbox"] { opacity: 0; position: absolute; pointer-events: none; } &:has(input:checked) { label[for=direction]::after { content: '>'; } }}#remotehost{grid-column:span 2/span 2}.post-content:has(input:invalid){ #command { display: none; }}#command{background:oklch(45.2% .211 324.591);margin-top:1rem;padding:.5rem;color:#eee}</style></head><body><div class=grid><label for=localport>Local port</label>
|
||||
'><meta name=author content><link rel="preload stylesheet" as=style href=https://lavafroth.is-a.dev/app.min.css><link rel=preload as=image href=../header.svg><link as=font href=https://lavafroth.is-a.dev/latinmodern-math.otf><link rel=preload as=image href=https://lavafroth.is-a.dev/github.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/about.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/art.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/rss.svg><link rel=icon href=https://lavafroth.is-a.dev/favicon.png><link rel=blog-icon href=https://lavafroth.is-a.dev/icon.png></head><body><header><a class=site-name href=https://lavafroth.is-a.dev/><svg viewBox="0 0 8790 2080"><path d="M80 1935V465h216v1270h286v2e2zm853 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm1025 528L2014 465h210l108 868 8 142h12l8-142 108-868h210l-224 1470zm813 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm851 528V465h514v222h-298v386h2e2v222h-2e2v640zm910 0V465h216q194 0 286 108 92 107 92 316 0 124-43 215-44 90-106 132l147 699h-216l-122-620h-38v620zm216-820q60 0 95-26 35-27 50-76t15-116q0-105-34-161-35-57-126-57zm1084 836q-90 0-154-42-65-42-99-114-35-72-35-162V767q0-91 35-162 34-72 99-114 64-42 154-42t155 42q64 42 99 114 34 72 34 162v866q0 90-34 162-35 72-99 114-65 42-155 42zm0-210q40 0 56-33 16-34 16-75V767q0-41-17-74-17-34-55-34-37 0-54 34-18 33-18 74v866q0 41 17 75 17 33 55 33zm890 194V687h-204V465h624v222h-204v1248zm828 0V465h216v608h168V465h216v1470h-216v-640h-168v640z"/></svg></a><nav><a style=--url:url(./github.svg) href=https://github.com/lavafroth aria-label=github target=_blank></a><a href=../about/ aria-label=about style=--url:url(./about.svg)></a><a href=../art/ aria-label=art style=--url:url(./art.svg)></a><a href=../index.xml aria-label=rss style=--url:url(./rss.svg)></a><nav></header><main><hgroup data-pagefind-body><p data-pagefind-ignore><time>Jan 1, 1 | 1 minute read</time></p><h1 data-pagefind-meta=title></h1></hgroup><section class=post-content data-pagefind-body><!doctype html><html lang=en><head><meta charset=UTF-8><title>Easy SSH tunnel</title><meta name=viewport content="width=device-width,initial-scale=1"><meta name=description content><style>*{font-family:monospace}body{--purple-dark:oklch(29.3% 0.136 325.661);--purple-light:lab(78.5378% 39.3533 -32.9615);background:var(--purple-dark)}input{outline:none;color:#eee;border:none;background:var(--purple-dark)}.post-content>div{margin:1rem auto;label:not([for=direction]) { padding:.5rem; background:var(--purple-light); color:var(--purple-dark); }}.grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));grid-template-rows:repeat(3,minmax(0,1fr)); *{ text-align: center; } label[for=direction] { user-select: none; grid-row: span 2 / span 2; grid-column-start: 2; color: #eee; &::after { display: block; content: '<'; } } input[type="checkbox"] { opacity: 0; position: absolute; pointer-events: none; } &:has(input:checked) { label[for=direction]::after { content: '>'; } }}#remotehost{grid-column:span 2/span 2}#command{background:oklch(45.2% .211 324.591);margin-top:1rem;padding-inline:1rem;color:#eee}#copy{background:var(--purple-light);color:var(--purple-dark);padding-inline:1rem;float:right;&:active { background:oklch(45.2% 0.211 324.591); color:#eee; }}</style></head><body><div class=grid><label for=localport>Local port</label>
|
||||
<label for=direction>Traffic direction</label>
|
||||
<label for=remoteport>Remote port</label>
|
||||
<input id=localport type=number min=0 max=65535 step=1 value=8888>
|
||||
<input id=localport type=number min=0 max=65535 step=1 placeholder=8888>
|
||||
<input type=checkbox id=direction>
|
||||
<input id=remoteport type=number min=0 max=65535 step=1 value=8888>
|
||||
<input id=remoteport type=number min=0 max=65535 step=1 placeholder=8888>
|
||||
<label for=remotehost>Connect to</label>
|
||||
<input id=remotehost type=text placeholder=user@remote.host></div><div id=command></div></div></body><script>const localPort=document.querySelector("#localport"),remotePort=document.querySelector("#remoteport"),remoteHost=document.querySelector("#remotehost"),direction=document.querySelector("#direction"),command=document.querySelector("#command");function updateCommand(){const e=localPort.value,t=remotePort.value,n=direction.checked?"R":"L",s=remoteHost.value||remoteHost.placeholder;command.textContent=`ssh -f -N -${n} ${e}:localhost:${t} ${s}`}localPort.addEventListener("input",updateCommand),direction.addEventListener("change",updateCommand),remotePort.addEventListener("input",updateCommand),remoteHost.addEventListener("input",updateCommand),updateCommand()</script></html></section><footer class=post-tags data-pagefind-meta=tags></footer></main><footer class=footer><p>© 2026 <a href=https://lavafroth.is-a.dev/>lavafroth</a></p><p><a href=https://github.com/lavafroth/lavafroth.github.io/issues/new/choose>Report an issue</a></p><p><a href=https://github.com/lavafroth/lavafroth.github.io/discussions/>Discuss</a></p><p><a href=https://lavafroth.is-a.dev/privacy>Privacy</a></p><p><a href=https://creativecommons.org/licenses/by-sa/4.0/legalcode>License</a></p></footer></body></html>
|
||||
<input id=remotehost type=text placeholder=user@remote.host></div><div id=command></div><button id=copy>⧉ Copy</button></div></body><script>const localPort=document.querySelector("#localport"),remotePort=document.querySelector("#remoteport"),remoteHost=document.querySelector("#remotehost"),direction=document.querySelector("#direction"),command=document.querySelector("#command"),copy=document.querySelector("#copy"),valueOrPlaceholder=e=>e.value||e.placeholder;function updateCommand(){const e=direction.checked?"R":"L";command.textContent=`ssh -f -N -${e} ${valueOrPlaceholder(localPort)}:localhost:${valueOrPlaceholder(remotePort)} ${valueOrPlaceholder(remoteHost)}`}function validatePort(e){const t=e.keyCode;(t<48||t>57||e.target.value*10+(t-48)>65535)&&e.preventDefault()}for(const e of[localPort,direction,remoteHost,remotePort])e.addEventListener("input",updateCommand);for(const e of[localPort,remotePort])e.addEventListener("keypress",validatePort);copy.addEventListener("click",e=>navigator.clipboard.writeText(command.textContent)),updateCommand()</script></html></section><footer class=post-tags data-pagefind-meta=tags></footer></main><footer class=footer><p>© 2026 <a href=https://lavafroth.is-a.dev/>lavafroth</a></p><p><a href=https://github.com/lavafroth/lavafroth.github.io/issues/new/choose>Report an issue</a></p><p><a href=https://github.com/lavafroth/lavafroth.github.io/discussions/>Discuss</a></p><p><a href=https://lavafroth.is-a.dev/privacy>Privacy</a></p><p><a href=https://creativecommons.org/licenses/by-sa/4.0/legalcode>License</a></p></footer></body></html>
|
||||
70
index.xml
70
index.xml
@@ -1023,17 +1023,16 @@ injection wherein he mentions a way to &ldquo;gadget&rdquo; our way out
|
||||
<style>
|
||||
* { font-family: monospace; }
|
||||
body {
|
||||
background: oklch(29.3% 0.136 325.661);
|
||||
--purple-dark: oklch(29.3% 0.136 325.661);
|
||||
--purple-light: lab(78.5378% 39.3533 -32.9615);
|
||||
background: var(--purple-dark);
|
||||
}
|
||||
|
||||
input {
|
||||
outline: none;
|
||||
color: #eee;
|
||||
border: none;
|
||||
background: oklch(29.3% 0.136 325.661);
|
||||
&:invalid {
|
||||
background: oklch(40.8% 0.153 2.432);
|
||||
}
|
||||
background: var(--purple-dark);
|
||||
}
|
||||
|
||||
.post-content > div {
|
||||
@@ -1041,20 +1040,15 @@ injection wherein he mentions a way to &ldquo;gadget&rdquo; our way out
|
||||
|
||||
label:not([for=direction]) {
|
||||
padding: .5rem;
|
||||
background: lab(78.5378% 39.3533 -32.9615);
|
||||
color: oklch(29.3% 0.136 325.661);
|
||||
background: var(--purple-light);
|
||||
color: var(--purple-dark);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
grid-template-rows: repeat(3, minmax(0, 1fr));
|
||||
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
* { text-align: center; }
|
||||
|
||||
label[for=direction] {
|
||||
@@ -1085,18 +1079,23 @@ injection wherein he mentions a way to &ldquo;gadget&rdquo; our way out
|
||||
grid-column: span 2 / span 2;
|
||||
}
|
||||
|
||||
.post-content:has(input:invalid) {
|
||||
#command {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
#command {
|
||||
background: oklch(45.2% 0.211 324.591);
|
||||
margin-top: 1rem;
|
||||
padding: 0.5rem;
|
||||
padding-inline: 1rem;
|
||||
color: #eee;
|
||||
}
|
||||
|
||||
#copy {
|
||||
background: var(--purple-light);
|
||||
color: var(--purple-dark);
|
||||
padding-inline: 1rem;
|
||||
float: right;
|
||||
&:active {
|
||||
background: oklch(45.2% 0.211 324.591);
|
||||
color: #eee;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@@ -1107,14 +1106,15 @@ injection wherein he mentions a way to &ldquo;gadget&rdquo; our way out
|
||||
<label for="direction">Traffic direction</label>
|
||||
<label for="remoteport">Remote port</label>
|
||||
|
||||
<input id="localport" type="number" min="0" max="65535" step=1 value=8888>
|
||||
<input id="localport" type="number" min="0" max="65535" step=1 placeholder=8888>
|
||||
<input type=checkbox id="direction">
|
||||
<input id="remoteport" type="number" min="0" max="65535" step=1 value=8888>
|
||||
<input id="remoteport" type="number" min="0" max="65535" step=1 placeholder=8888>
|
||||
<label for="remotehost">Connect to</label>
|
||||
<input id="remotehost" type="text" placeholder="user@remote.host">
|
||||
</div>
|
||||
|
||||
<div id='command'></div>
|
||||
<button id='copy'>⧉ Copy</button>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
@@ -1124,19 +1124,31 @@ injection wherein he mentions a way to &ldquo;gadget&rdquo; our way out
|
||||
const remoteHost = document.querySelector('#remotehost');
|
||||
const direction = document.querySelector('#direction');
|
||||
const command = document.querySelector('#command');
|
||||
const copy = document.querySelector('#copy');
|
||||
const valueOrPlaceholder = (v) => v.value || v.placeholder;
|
||||
|
||||
function updateCommand() {
|
||||
const localPortValue = localPort.value;
|
||||
const remotePortValue = remotePort.value;
|
||||
const directionString = direction.checked ? "R" : "L";
|
||||
const remoteHostValue = remoteHost.value || remoteHost.placeholder;
|
||||
command.textContent = `ssh -f -N -${directionString} ${localPortValue}:localhost:${remotePortValue} ${remoteHostValue}`;
|
||||
command.textContent = `ssh -f -N -${directionString} ${valueOrPlaceholder(localPort)}:localhost:${valueOrPlaceholder(remotePort)} ${valueOrPlaceholder(remoteHost)}`;
|
||||
}
|
||||
|
||||
localPort.addEventListener('input', updateCommand);
|
||||
direction.addEventListener('change', updateCommand);
|
||||
remotePort.addEventListener('input', updateCommand);
|
||||
remoteHost.addEventListener('input', updateCommand);
|
||||
function validatePort(e) {
|
||||
const code = e.keyCode;
|
||||
if (code < 48 || code > 57 || e.target.value * 10 + (code - 48) > 65535) {
|
||||
e.preventDefault()
|
||||
}
|
||||
}
|
||||
|
||||
for (const variable of [localPort, direction, remoteHost, remotePort]) {
|
||||
variable.addEventListener('input', updateCommand);
|
||||
}
|
||||
|
||||
for (const portVariable of [localPort, remotePort]) {
|
||||
portVariable.addEventListener('keypress', validatePort);
|
||||
}
|
||||
|
||||
copy.addEventListener('click', (_) => navigator.clipboard.writeText(command.textContent))
|
||||
|
||||
|
||||
updateCommand()
|
||||
</script>
|
||||
|
||||
BIN
pagefind/fragment/en_8557af7.pf_fragment
Normal file
BIN
pagefind/fragment/en_8557af7.pf_fragment
Normal file
Binary file not shown.
BIN
pagefind/index/en_199f7bd.pf_index
Normal file
BIN
pagefind/index/en_199f7bd.pf_index
Normal file
Binary file not shown.
@@ -1 +1 @@
|
||||
{"version":"1.0.3","languages":{"en-us":{"hash":"en-us_e3ed9fd3f8c16","wasm":"en-us","page_count":56}}}
|
||||
{"version":"1.0.3","languages":{"en":{"hash":"en_f524472d1d","wasm":"en","page_count":1},"en-us":{"hash":"en-us_e3ed9fd3f8c16","wasm":"en-us","page_count":56}}}
|
||||
BIN
pagefind/pagefind.en_f524472d1d.pf_meta
Normal file
BIN
pagefind/pagefind.en_f524472d1d.pf_meta
Normal file
Binary file not shown.
BIN
pagefind/wasm.en.pagefind
Normal file
BIN
pagefind/wasm.en.pagefind
Normal file
Binary file not shown.
Reference in New Issue
Block a user