Compare commits
4 Commits
887de0a311
...
e79cd00a06
Author | SHA1 | Date | |
---|---|---|---|
e79cd00a06 | |||
ae81d8467c | |||
01c8eb3b27 | |||
a8c5adaeea |
BIN
assets/desktop_screenshots/1.png
Normal file
BIN
assets/desktop_screenshots/1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.2 MiB |
BIN
assets/desktop_screenshots/2.png
Normal file
BIN
assets/desktop_screenshots/2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 134 KiB |
BIN
assets/desktop_screenshots/3.png
Normal file
BIN
assets/desktop_screenshots/3.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 72 KiB |
@ -22,11 +22,18 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#container {
|
#container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
text-align: center;
|
text-align: center;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
align-content: center;
|
#container > * {
|
||||||
|
width: 50%;
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-tooltip] {
|
[data-tooltip] {
|
||||||
@ -67,16 +74,34 @@ input {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#result {
|
#result {
|
||||||
white-space: preserve;
|
|
||||||
|
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
|
white-space: preserve;
|
||||||
color: var(--color);
|
color: var(--color);
|
||||||
|
|
||||||
padding: 2em;
|
max-height: 100%;
|
||||||
margin: 2em;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
#switch_theme {
|
#switch_theme, #help {
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-grid {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-grid > * {
|
||||||
|
max-width: 50%;
|
||||||
|
max-height: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 798px) {
|
||||||
|
#container {
|
||||||
|
flex-direction: column !important;
|
||||||
|
}
|
||||||
}
|
}
|
17
index.html
17
index.html
@ -14,14 +14,15 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="container">
|
<div id="container">
|
||||||
<h1>welcome to my website</h1>
|
<div>
|
||||||
<h2 id="switch_theme">switch theme</h2>
|
<h1>welcome to my website</h1>
|
||||||
|
<h2 id="switch_theme">switch theme</h2>
|
||||||
<p>press <kbd>Enter</kbd> to run command</p>
|
|
||||||
<p>use 'help' to list all commands</p>
|
<p>press <kbd>Enter</kbd> to run command</p>
|
||||||
|
<p>use <span id="help">'help'</span> to list all commands</p>
|
||||||
<span>[guest@website ~]$ </span>
|
<span>[guest@website ~]$ </span>
|
||||||
<input type="text" id="command" value="help">
|
<input type="text" id="command">
|
||||||
|
</div>
|
||||||
<div id="result">
|
<div id="result">
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
@ -96,7 +96,6 @@ const COMMANDS = [
|
|||||||
'',
|
'',
|
||||||
'bitwarden (self-hosted)',
|
'bitwarden (self-hosted)',
|
||||||
'libreoffice'
|
'libreoffice'
|
||||||
|
|
||||||
].join('\n')
|
].join('\n')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -130,7 +129,7 @@ const COMMANDS = [
|
|||||||
name: 'curl',
|
name: 'curl',
|
||||||
description: 'open website in new tab',
|
description: 'open website in new tab',
|
||||||
usage: '<website>',
|
usage: '<website>',
|
||||||
usage_examples: ['curl google.com'],
|
usage_examples: ['curl https://google.com'],
|
||||||
arguments: [
|
arguments: [
|
||||||
{
|
{
|
||||||
name: 'url',
|
name: 'url',
|
||||||
@ -139,7 +138,7 @@ const COMMANDS = [
|
|||||||
multiword: true,
|
multiword: true,
|
||||||
check: (url) => URL_REGEX.test(url)
|
check: (url) => URL_REGEX.test(url)
|
||||||
? null
|
? null
|
||||||
: "invalid URL"
|
: "invalid URL or missing protocol"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
output: (url) => {
|
output: (url) => {
|
||||||
@ -151,6 +150,26 @@ const COMMANDS = [
|
|||||||
|
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'desktop',
|
||||||
|
description: 'Show some desktop screenshots',
|
||||||
|
usage: '',
|
||||||
|
usage_examples: [],
|
||||||
|
arguments: [],
|
||||||
|
output: () => {
|
||||||
|
let result = [];
|
||||||
|
|
||||||
|
for (let i = 0; i < 3;) {
|
||||||
|
result.push(`<img src="assets/desktop_screenshots/${++i}.png" alt="Desktop screenshot"/>`)
|
||||||
|
}
|
||||||
|
|
||||||
|
return `
|
||||||
|
<div class="image-grid">
|
||||||
|
${result.join('\n')}
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
const URL_REGEX = /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/g;
|
const URL_REGEX = /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/g;
|
||||||
|
|
||||||
const LINKS = {
|
const LINKS = {
|
||||||
'gitea': 'https://git.sador.me',
|
'gitea': 'https://git.sador.me/sadorowo',
|
||||||
'instagram': 'https://instagram.com/sadorowo',
|
'instagram': 'https://instagram.com/sadorowo',
|
||||||
'immich': 'https://photos.sador.me/',
|
'immich': 'https://photos.sador.me/',
|
||||||
'email': 'mailto:contact@sador.me'
|
'email': 'mailto:contact@sador.me'
|
||||||
@ -26,11 +27,17 @@ const MUSIC_METADATA = {
|
|||||||
'black metal': [
|
'black metal': [
|
||||||
'Behemoth',
|
'Behemoth',
|
||||||
'Venom',
|
'Venom',
|
||||||
|
'Mgła',
|
||||||
|
'Watain',
|
||||||
|
'Bathory',
|
||||||
'Carpathian Forest',
|
'Carpathian Forest',
|
||||||
'Darkthrone'
|
'Darkthrone'
|
||||||
],
|
],
|
||||||
'nu metal': [
|
'nu metal': [
|
||||||
'Slipknot',
|
'Slipknot',
|
||||||
'Evanescence'
|
'Evanescence'
|
||||||
|
],
|
||||||
|
'other genres': [
|
||||||
|
'Rammstein'
|
||||||
]
|
]
|
||||||
}
|
}
|
67
js/script.js
67
js/script.js
@ -4,6 +4,36 @@ function updateAge() {
|
|||||||
age.textContent = difference.toFixed(4);
|
age.textContent = difference.toFixed(4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// process command function
|
||||||
|
function processCommand() {
|
||||||
|
const [commandName, ...args] = command.value.split(' ') || [command.value]
|
||||||
|
const suppliedCommand = COMMANDS.find(c => c.name === commandName)
|
||||||
|
|
||||||
|
if (!suppliedCommand) {
|
||||||
|
result.textContent = 'invalid command';
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const { arguments, output } = suppliedCommand;
|
||||||
|
for (const i in arguments) {
|
||||||
|
const argument = arguments[i]
|
||||||
|
|
||||||
|
if (argument.required && !args[i]) {
|
||||||
|
result.textContent = `argument ${argument.name} is missing`;
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const errorMessage = argument.check(argument.multiword ? args.join(' ') : args[i])
|
||||||
|
|
||||||
|
if (typeof errorMessage === 'string') {
|
||||||
|
result.textContent = `error while executing ${suppliedCommand.name}: ${errorMessage}`;
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result.innerHTML = output(...args).replaceAll(TAB, '')
|
||||||
|
}
|
||||||
|
|
||||||
// wrapper for setInterval
|
// wrapper for setInterval
|
||||||
const runEvery = (task, ms) => {
|
const runEvery = (task, ms) => {
|
||||||
task()
|
task()
|
||||||
@ -37,34 +67,7 @@ command?.addEventListener('focusout', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
command?.addEventListener('keydown', e => {
|
command?.addEventListener('keydown', e => {
|
||||||
if (e.key === 'Enter') {
|
if (e.key === 'Enter') processCommand()
|
||||||
const [commandName, ...args] = e.target.value.split(' ') || [e.target.value]
|
|
||||||
const command = COMMANDS.find(c => c.name === commandName)
|
|
||||||
|
|
||||||
if (!command) {
|
|
||||||
result.textContent = 'invalid command';
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const { arguments, output } = command;
|
|
||||||
for (const i in arguments) {
|
|
||||||
const argument = arguments[i]
|
|
||||||
|
|
||||||
if (argument.required && !args[i]) {
|
|
||||||
result.textContent = `argument ${argument.name} is missing`;
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const errorMessage = argument.check(argument.multiword ? args.join(' ') : args[i])
|
|
||||||
|
|
||||||
if (typeof errorMessage === 'string') {
|
|
||||||
result.textContent = `error while executing ${command.name}: ${errorMessage}`;
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
result.innerHTML = output(...args).replaceAll(TAB, '')
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// run all tasks
|
// run all tasks
|
||||||
@ -74,4 +77,10 @@ command?.focus()
|
|||||||
// initial theme configuration
|
// initial theme configuration
|
||||||
const theme = localStorage.getItem('theme');
|
const theme = localStorage.getItem('theme');
|
||||||
if (theme === 'dark')
|
if (theme === 'dark')
|
||||||
document.body.classList.add('dark')
|
document.body.classList.add('dark')
|
||||||
|
|
||||||
|
// listen to help tooltip
|
||||||
|
help.addEventListener('click', () => {
|
||||||
|
command.value = 'help';
|
||||||
|
processCommand();
|
||||||
|
})
|
Loading…
Reference in New Issue
Block a user