initial commit
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
misctils.xpi
|
25
Makefile
Normal file
25
Makefile
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
MOZ_NATIVE=$(HOME)/.mozilla/native-messaging-hosts
|
||||||
|
|
||||||
|
release: xpi
|
||||||
|
|
||||||
|
xpi:
|
||||||
|
zip -r misctils.xpi *.js manifest.json icons/ startpage/
|
||||||
|
|
||||||
|
startpage:
|
||||||
|
./genfs.sh
|
||||||
|
|
||||||
|
install:
|
||||||
|
mkdir -p $(MOZ_NATIVE)
|
||||||
|
cp nativemsg/bg.py $(MOZ_NATIVE)
|
||||||
|
|
||||||
|
# make the home directory work for all users
|
||||||
|
sed "s@HOME@$(HOME)@" nativemsg/bg_app.json > $(MOZ_NATIVE)/bg_app.json
|
||||||
|
chmod +x $(MOZ_NATIVE)/bg.py
|
||||||
|
|
||||||
|
uninstall:
|
||||||
|
rm $(MOZ_NATIVE)/bg_app.json $(MOZ_NATIVE)/bg.py
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm misctils.xpi
|
||||||
|
|
||||||
|
.PHONY: startpage
|
96
background.js
Normal file
96
background.js
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
/* add a context menu for setting the background */
|
||||||
|
browser.menus.create({
|
||||||
|
id: "set-background",
|
||||||
|
title: "Set Background Image",
|
||||||
|
contexts: [ "image" ],
|
||||||
|
icons: {
|
||||||
|
"16": "icons/background.png",
|
||||||
|
"32": "icons/background.png",
|
||||||
|
"64": "icons/background.png",
|
||||||
|
"128": "icons/background.png",
|
||||||
|
"256": "icons/background.png"
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
/* add a context menu for accessing repo on github */
|
||||||
|
browser.menus.create({
|
||||||
|
id: "search-github",
|
||||||
|
title: "Open in Github",
|
||||||
|
contexts: [ "selection" ]
|
||||||
|
})
|
||||||
|
|
||||||
|
browser.menus.onClicked.addListener(info => {
|
||||||
|
if (info.menuItemId == "set-background") {
|
||||||
|
browser.runtime.sendNativeMessage("bg_app", info.srcUrl);
|
||||||
|
} else if (info.menuItemId == "search-github" && info.selectionText) {
|
||||||
|
const trimmedText = info.selectionText.trim();
|
||||||
|
const githubUrl = `https://github.com/${trimmedText}`;
|
||||||
|
chrome.tabs.create({ url: githubUrl })
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/* add functionality to commands defined in manifest.json */
|
||||||
|
chrome.commands.onCommand.addListener(function(action) {
|
||||||
|
action.preventDefault();
|
||||||
|
switch (action) {
|
||||||
|
case "toggle-pin-tab": /* toggle current tab pinning */
|
||||||
|
chrome.tabs.query({ currentWindow: true, active: true }, function(found_tab) {
|
||||||
|
const currentTab = found_tab[0]
|
||||||
|
const toggledValue = !currentTab.pinned;
|
||||||
|
|
||||||
|
chrome.tabs.update(currentTab.id, { pinned: toggledValue });
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* switch between tabs */
|
||||||
|
case "tab-up":
|
||||||
|
chrome.tabs.query({ currentWindow: true, active: true }, function(found_tab) {
|
||||||
|
switch_tab(found_tab[0].index - 1);
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case "tab-down":
|
||||||
|
chrome.tabs.query({ currentWindow: true, active: true }, function(found_tab) {
|
||||||
|
switch_tab(found_tab[0].index + 1);
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* close tab */
|
||||||
|
case "tab-close":
|
||||||
|
chrome.tabs.query({ currentWindow: true, active: true }, function(found_tab) {
|
||||||
|
browser.tabs.remove(found_tab[0].id);
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case "scroll-half-down":
|
||||||
|
window.scrollBy(0, window.innerHeight / 2, "smooth");
|
||||||
|
console.log(window)
|
||||||
|
console.log("hello world")
|
||||||
|
break;
|
||||||
|
case "scroll-half-up":
|
||||||
|
window.scrollBy(0, -(window.innerHeight / 2), "smooth");
|
||||||
|
console.log(window)
|
||||||
|
console.log("hello world")
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function switch_tab(tab_number) {
|
||||||
|
/* I don't want it to cycle around */
|
||||||
|
if (tab_number < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
chrome.tabs.query({ currentWindow: true, active: true }, function(found_tabs) {
|
||||||
|
const currentTab = found_tabs[0];
|
||||||
|
if (currentTab.index == tab_number) {
|
||||||
|
/* we're already on the current tab */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* change the selected tab to active */
|
||||||
|
browser.tabs.query({ currentWindow: true }, function(window_tabs) {
|
||||||
|
if (typeof window_tabs.at(tab_number) != "undefined") {
|
||||||
|
chrome.tabs.update(window_tabs.at(tab_number).id, { active: true });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
15
genfs.sh
Executable file
15
genfs.sh
Executable file
@@ -0,0 +1,15 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# generate fs files because we can't do directory traversal from js within a
|
||||||
|
# browser.
|
||||||
|
|
||||||
|
for d in ./startpage/root/*; do
|
||||||
|
if [ ! -d "$d" ]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
s=""
|
||||||
|
for f in "$d"/*; do
|
||||||
|
s=${s:+$s\\n}$(echo "$f" | cut -d '/' -f 5-)
|
||||||
|
done
|
||||||
|
echo "$s" > ./startpage/root/."$(echo "$d" | cut -d '/' -f 4-)"
|
||||||
|
done
|
BIN
icons/background.png
Normal file
BIN
icons/background.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 257 KiB |
BIN
icons/misc.png
Normal file
BIN
icons/misc.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 257 KiB |
59
manifest.json
Normal file
59
manifest.json
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
{
|
||||||
|
"name": "misctils",
|
||||||
|
"version": "1.0",
|
||||||
|
"description": "Miscelanious Utils for Firefox",
|
||||||
|
"icons": {
|
||||||
|
"16": "icons/misc.png",
|
||||||
|
"32": "icons/misc.png",
|
||||||
|
"64": "icons/misc.png",
|
||||||
|
"128": "icons/misc.png",
|
||||||
|
"256": "icons/misc.png"
|
||||||
|
},
|
||||||
|
"manifest_version": 2,
|
||||||
|
"permissions": [ "menus", "activeTab", "tabs", "nativeMessaging", "storage" ],
|
||||||
|
|
||||||
|
"browser_specific_settings": {
|
||||||
|
"gecko": {
|
||||||
|
"id": "misc@tils",
|
||||||
|
"strict_min_version": "58.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"background": {
|
||||||
|
"scripts": [ "background.js" ],
|
||||||
|
"persistent": false
|
||||||
|
},
|
||||||
|
"chrome_settings_overrides" : {
|
||||||
|
"homepage": "startpage/index.html"
|
||||||
|
},
|
||||||
|
"chrome_url_overrides" : {
|
||||||
|
"newtab": "startpage/index.html"
|
||||||
|
},
|
||||||
|
|
||||||
|
"commands": {
|
||||||
|
"toggle-pin-tab": {
|
||||||
|
"suggested_key": { "default": "Alt+P" },
|
||||||
|
"description": "Pin the currently active tab."
|
||||||
|
},
|
||||||
|
"tab-up": {
|
||||||
|
"suggested_key": { "default": "Alt+K" },
|
||||||
|
"description": "Switch tab focus to one up."
|
||||||
|
},
|
||||||
|
"tab-down": {
|
||||||
|
"suggested_key": { "default": "Alt+J" },
|
||||||
|
"description": "Switch tab focus to one down."
|
||||||
|
},
|
||||||
|
"tab-close": {
|
||||||
|
"suggested_key": { "default": "Alt+C" },
|
||||||
|
"description": "Close the current tab."
|
||||||
|
},
|
||||||
|
"scroll-half-down": {
|
||||||
|
"suggested_key": { "default": "Alt+D" },
|
||||||
|
"description": "Scroll down half a page."
|
||||||
|
},
|
||||||
|
"scroll-half-up": {
|
||||||
|
"suggested_key": { "default": "Alt+U" },
|
||||||
|
"description": "Scroll up half a page."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
18
nativemsg/bg.py
Normal file
18
nativemsg/bg.py
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
#!/usr/bin/env -S python3
|
||||||
|
import sys
|
||||||
|
import struct
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
# Read a message from stdin and decode it.
|
||||||
|
rawLength = sys.stdin.buffer.read(4)
|
||||||
|
if len(rawLength) == 0:
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
# Read the length of the message
|
||||||
|
messageLength: int = struct.unpack("@I", rawLength)[0]
|
||||||
|
|
||||||
|
# Decode the message
|
||||||
|
message = sys.stdin.buffer.read(messageLength).decode("utf-8")
|
||||||
|
|
||||||
|
# Run the background setting with a link to the image
|
||||||
|
_ = subprocess.run(["setbg", "-tw", message.replace('"', "")])
|
7
nativemsg/bg_app.json
Normal file
7
nativemsg/bg_app.json
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"name": "bg_app",
|
||||||
|
"description": "set background via native script",
|
||||||
|
"path": "HOME/.mozilla/native-messaging-hosts/bg.py",
|
||||||
|
"type": "stdio",
|
||||||
|
"allowed_extensions": [ "misc@tils" ]
|
||||||
|
}
|
28
startpage/index.html
Normal file
28
startpage/index.html
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8"/>
|
||||||
|
<link rel="stylesheet" href="style.css">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||||
|
<link rel="icon" type="image/png" href="../icons/misc.png">
|
||||||
|
<title>Startpage</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<header>
|
||||||
|
<h1 id="clock" style="margin-bottom:0;"></h1>
|
||||||
|
<p id="date" style="margin-top:0;"></p>
|
||||||
|
</header>
|
||||||
|
<p id="search-results">
|
||||||
|
<div id="search">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
id="search-bar"
|
||||||
|
value="fetch"
|
||||||
|
placeholder="run man for more info"
|
||||||
|
autofocus
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</p>
|
||||||
|
</body>
|
||||||
|
<script type="module" src="./index.js"></script>
|
||||||
|
</html>
|
134
startpage/index.js
Normal file
134
startpage/index.js
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
let clock = document.getElementById("clock");
|
||||||
|
let date = document.getElementById("date");
|
||||||
|
let input = document.getElementById("search-bar");
|
||||||
|
let result = document.getElementById("search-results");
|
||||||
|
|
||||||
|
/* Allow toggling between military and 12 hr time */
|
||||||
|
let military_time = false
|
||||||
|
clock.onclick = function() {
|
||||||
|
military_time = !military_time;
|
||||||
|
time();
|
||||||
|
}
|
||||||
|
|
||||||
|
function time(timeout) {
|
||||||
|
let d = new Date();
|
||||||
|
let m = d.getMinutes();
|
||||||
|
let h = d.getHours();
|
||||||
|
|
||||||
|
/* if it hasn't been set then set it here */
|
||||||
|
if (military_time) {
|
||||||
|
clock.textContent = `${("0" + h).substr(-2)}:${("0" + m).substr(-2)}`;
|
||||||
|
} else {
|
||||||
|
let hours = h % 12;
|
||||||
|
let minutes = ("0" + m).substr(-2);
|
||||||
|
hours = hours ? hours : 12;
|
||||||
|
|
||||||
|
clock.textContent = `${hours}:${minutes} ${(h >= 12 ? "PM" : "AM")}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set the time every second */
|
||||||
|
timeout && setTimeout(() => time(true), (60 - d.getSeconds()) * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
let last_date;
|
||||||
|
/* Sun 31st, May */
|
||||||
|
function cal(force) {
|
||||||
|
const days = [ "Sun", "Mon", "Tue", "Wed", "Thur", "Fri", "Sat" ];
|
||||||
|
const months = [ "January", "Febuary", "March", "April", "May", "June",
|
||||||
|
"July", "August", "September", "November", "December", ];
|
||||||
|
|
||||||
|
let d = new Date();
|
||||||
|
let day = days[d.getDay()];
|
||||||
|
let day_of_month = d.getDate();
|
||||||
|
let month = months[d.getMonth()];
|
||||||
|
let day_suffix
|
||||||
|
|
||||||
|
/* get a suffix for the day of the month */
|
||||||
|
if (day_of_month > 3 && day_of_month < 21) {
|
||||||
|
day_suffix = "th";
|
||||||
|
} else if ((day_of_month / 1) % 10 == 1) {
|
||||||
|
day_suffix = "st";
|
||||||
|
} else if ((day_of_month / 1) % 10 == 2) {
|
||||||
|
day_suffix = "nd";
|
||||||
|
} else if ((day_of_month / 1) % 10 == 3) {
|
||||||
|
day_suffix = "rd";
|
||||||
|
} else {
|
||||||
|
day_suffix = "th";
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check if this date has already been set before */
|
||||||
|
if (!force && last_date == `${d.getDay()}${d.getMonth()}`) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
date.textContent = `${day} ${day_of_month}${day_suffix}, ${month}`;
|
||||||
|
|
||||||
|
/* store the last date that was set */
|
||||||
|
last_date = `${d.getDay()}${d.getMonth()}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* show the time on the page */
|
||||||
|
time(true);
|
||||||
|
|
||||||
|
/* just incase something dumb happens the time should update when the user
|
||||||
|
* focus's the page */
|
||||||
|
window.addEventListener('focus', time);
|
||||||
|
|
||||||
|
cal();
|
||||||
|
setInterval(cal, 1000);
|
||||||
|
|
||||||
|
function shell(event) {
|
||||||
|
var env = {
|
||||||
|
path: "/startpage/root/bin/",
|
||||||
|
};
|
||||||
|
|
||||||
|
/* convert a directory such as /startpage/root/bin/ to /startpage/root/.bin
|
||||||
|
* to read static fs data.
|
||||||
|
*/
|
||||||
|
function convertPath(path) {
|
||||||
|
if (path.endsWith('/')) {
|
||||||
|
path = path.slice(0, -1);
|
||||||
|
}
|
||||||
|
const parts = path.split('/');
|
||||||
|
const hidden = '.' + parts.pop();
|
||||||
|
return parts.concat(hidden).join('/');
|
||||||
|
}
|
||||||
|
|
||||||
|
async function run(path) {
|
||||||
|
try {
|
||||||
|
const response = await fetch(convertPath(env.path));
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`Failed to load file: ${response.status}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const text = await response.text();
|
||||||
|
const lines = text.split(/\r?\n/);
|
||||||
|
const matchedLine = lines.find(line => line.split(".")[0] == path);
|
||||||
|
if (!matchedLine) {
|
||||||
|
throw new Error(`${path} cannot be found in path.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const file = env.path + matchedLine;
|
||||||
|
const { cmd } = await import(file);
|
||||||
|
return await cmd(input.value, event.key);
|
||||||
|
} catch (err) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input.value == "") {
|
||||||
|
input.style.color = "white";
|
||||||
|
} else {
|
||||||
|
run(input.value.substring(0, input.value.indexOf(" ")) || input.value)
|
||||||
|
.then(res => {
|
||||||
|
result.innerHTML = res;
|
||||||
|
input.style.color = "var(--blue)";
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
input.style.color = "white";
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
input.addEventListener('keyup', shell);
|
||||||
|
shell({ key: "" });
|
4
startpage/root/.bin
Normal file
4
startpage/root/.bin
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
clear.js
|
||||||
|
fetch.js
|
||||||
|
gpt.js
|
||||||
|
man.js
|
12
startpage/root/bin/clear.js
Normal file
12
startpage/root/bin/clear.js
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
export async function cmd() {
|
||||||
|
return ``;
|
||||||
|
}
|
||||||
|
|
||||||
|
export let man = `
|
||||||
|
<pre>
|
||||||
|
CLEAR(1)
|
||||||
|
|
||||||
|
NAME
|
||||||
|
\tclear - clear the screen
|
||||||
|
</pre>
|
||||||
|
`
|
29
startpage/root/bin/fetch.js
Normal file
29
startpage/root/bin/fetch.js
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
export async function cmd(_) {
|
||||||
|
return `
|
||||||
|
<pre>
|
||||||
|
_____\t\t\tOS: ${navigator.platform}
|
||||||
|
.-"" ""-.\t\tLang: ${navigator.language}
|
||||||
|
/(/ _ }\`;\`.\t\tTimezone: ${Intl.DateTimeFormat().resolvedOptions().timeZone}
|
||||||
|
|\`---'/ \` \`;\\\t\tAgent: ${navigator.userAgent}
|
||||||
|
.' (\`._ ; \`:
|
||||||
|
: \--' '|\`;,;
|
||||||
|
| .---' ; | |
|
||||||
|
: ' \`.__.-. / ; ;
|
||||||
|
: .----' .' / :
|
||||||
|
\`. \`----' .' /
|
||||||
|
\`.\`--. __ .- .'
|
||||||
|
\`-._ _.-' fsc
|
||||||
|
\`""""
|
||||||
|
</pre>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export let man = `
|
||||||
|
<pre>
|
||||||
|
FETCH(1)
|
||||||
|
|
||||||
|
NAME
|
||||||
|
\tfetch – Get information about the browser. This is specific to firefox because
|
||||||
|
\tthis addon is specific to firefox.
|
||||||
|
</pre>
|
||||||
|
`
|
26
startpage/root/bin/gpt.js
Normal file
26
startpage/root/bin/gpt.js
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
export async function cmd(inp, k) {
|
||||||
|
var search = ""
|
||||||
|
if (inp.indexOf(" ") > 0) {
|
||||||
|
search = inp.substring(inp.indexOf(" ") + 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (k == 'Enter') {
|
||||||
|
window.open(`https://chatgpt.com/?q=${search}`, '_self');
|
||||||
|
}
|
||||||
|
|
||||||
|
return `
|
||||||
|
<pre>
|
||||||
|
press Enter to search chat.openai.com for: '${search}'
|
||||||
|
</pre>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export let man = `
|
||||||
|
<pre>
|
||||||
|
GPT(1)
|
||||||
|
|
||||||
|
NAME
|
||||||
|
\tgpt - search chat.openai.com for something. You'll probably only get slop
|
||||||
|
\tbut it may have a chance of helping.
|
||||||
|
</pre>
|
||||||
|
`
|
53
startpage/root/bin/man.js
Normal file
53
startpage/root/bin/man.js
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
var getmanval;
|
||||||
|
async function getman(path) {
|
||||||
|
try {
|
||||||
|
const module = await import("/startpage/" + path);
|
||||||
|
return module.man;
|
||||||
|
} catch (error) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: update to use the path in the env this can be done once we first
|
||||||
|
* make the env available to the programs running in the shell
|
||||||
|
*/
|
||||||
|
export async function cmd(inp) {
|
||||||
|
var search = ""
|
||||||
|
if (inp.indexOf(" ") > 0) {
|
||||||
|
search = inp.substring(inp.indexOf(" ") + 1)
|
||||||
|
}
|
||||||
|
switch (search) {
|
||||||
|
case "fetch": return getman('/root/bin/fetch.js');
|
||||||
|
case "gpt": return getman('/root/bin/gpt.js');
|
||||||
|
case "clear": return getman('/root/bin/clear.js');
|
||||||
|
case "shell": return manshell;
|
||||||
|
case "man": default: return man;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export let man = `
|
||||||
|
<pre>
|
||||||
|
MAN(1)
|
||||||
|
|
||||||
|
NAME
|
||||||
|
\tman – display manual pages
|
||||||
|
|
||||||
|
SEE ALSO
|
||||||
|
\tfetch(1), gpt(1), shell(1), clear(1)
|
||||||
|
</pre>
|
||||||
|
`;
|
||||||
|
|
||||||
|
export let manshell = `
|
||||||
|
<pre>
|
||||||
|
SHELL(1)
|
||||||
|
|
||||||
|
NAME
|
||||||
|
\tshell – command interpreter
|
||||||
|
|
||||||
|
DESCRIPTION
|
||||||
|
\tshell is a shell for my startpage. It's not POSIX nor will it ever be. It's
|
||||||
|
\tsole job it to interpret text and run a command if a valid one is found.
|
||||||
|
\tWhile this is quite unintuitive in a standard UNIX shell in my opinion this
|
||||||
|
\tmakes sense here because of such a limited number of commands.
|
||||||
|
</pre>
|
||||||
|
`;
|
103
startpage/style.css
Normal file
103
startpage/style.css
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
:root {
|
||||||
|
--bg: #161617;
|
||||||
|
--fg: #c9c7cd;
|
||||||
|
--bg-dark: #131314;
|
||||||
|
|
||||||
|
/* Normal */
|
||||||
|
--black: #27272a;
|
||||||
|
--red: #f5a191;
|
||||||
|
--green: #90b99f;
|
||||||
|
--yellow: #e6b99d;
|
||||||
|
--blue: #aca1cf;
|
||||||
|
--magenta: #e29eca;
|
||||||
|
--cyan: #ea83a5;
|
||||||
|
--white: #c1c0d4;
|
||||||
|
/* Bright */
|
||||||
|
--bright-black: #353539;
|
||||||
|
--bright-red: #ffae9f;
|
||||||
|
--bright-green: #9dc6ac;
|
||||||
|
--bright-yellow: #f0c5a9;
|
||||||
|
--bright-blue: #b9aeda;
|
||||||
|
--bright-magenta: #ecaad6;
|
||||||
|
--bright-cyan: #f591b2;
|
||||||
|
--bright-white: #cac9dd;
|
||||||
|
/* Grays */
|
||||||
|
--gray01: #1b1b1d;
|
||||||
|
--gray02: #2a2a2d;
|
||||||
|
--gray03: #3e3e43;
|
||||||
|
--gray04: #57575f;
|
||||||
|
--gray05: #757581;
|
||||||
|
--gray06: #9998a8;
|
||||||
|
--gray07: var(--white);
|
||||||
|
}
|
||||||
|
|
||||||
|
html, body {
|
||||||
|
background-color: var(--bg-dark);
|
||||||
|
max-width: 80ch;
|
||||||
|
max-height: 100%;
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (orientation: portrait) {
|
||||||
|
html, body {
|
||||||
|
max-width: 100% !important;
|
||||||
|
padding: 5px !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#font, p, ul, ol, h1, h2, h3, h4, h5, table {
|
||||||
|
font-family: sans-serif;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
pre {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
h1 {
|
||||||
|
font-size: 3em;
|
||||||
|
}
|
||||||
|
a {
|
||||||
|
font-family: sans-serif;
|
||||||
|
text-decoration: none;
|
||||||
|
color: var(--cyan);
|
||||||
|
}
|
||||||
|
a:hover, a:active {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
#search {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
#search-bar, #search-btn {
|
||||||
|
height: 2.25em;
|
||||||
|
background-color: var(--bg);
|
||||||
|
color: white;
|
||||||
|
padding: 0 15px;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
#search-bar {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
#search-bar:focus {
|
||||||
|
outline: none;
|
||||||
|
background-color: var(--gray01);
|
||||||
|
}
|
||||||
|
#search-btn {
|
||||||
|
background-color: var(--yellow);
|
||||||
|
color: var(--bg);
|
||||||
|
font-weight: bold;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
#search-btn:focus {
|
||||||
|
outline: none;
|
||||||
|
background-color: var(--bright-yellow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#search-results {
|
||||||
|
height: 15lh;
|
||||||
|
margin-top: 0px;
|
||||||
|
margin-bottom: 0px;
|
||||||
|
padding: 15px;
|
||||||
|
overflow: scroll;
|
||||||
|
background-color: #111112;
|
||||||
|
}
|
Reference in New Issue
Block a user