gmi-web/gmi.js

203 lines
5.9 KiB
JavaScript
Raw Normal View History

2020-12-11 23:22:09 +00:00
/* gmi.js is licensed under CC0 */
class Gemini {
constructor({modes} = {modes: false}) {
this.modes = modes
this.allThemes = {
default: {
icon: "🎨",
colors: [
getComputedStyle(document.documentElement).getPropertyValue(`--foreground`),
getComputedStyle(document.documentElement).getPropertyValue(`--background`)
],
},
}
if (this.modes) {
css(`#toggleMode {
font-size: 1rem;
cursor: pointer;
position: fixed;
top: 0.5rem;
right: 0.5rem;
padding: 0.3rem;
margin-top: 0.1rem;
border: none;
color: var(--background);
background-color: var(--foreground);
}`)
this.toggleMode = document.createElement("button")
this.toggleMode.id = "toggleMode"
this.toggleMode.textContent = this.mode
this.toggleMode.onclick = () => {
this.mode = this.mode === "light" ? "dark" : "light"
this.toggleMode.textContent = this.mode
}
}
window.addEventListener("load", () => {
this.mode = this.mode
document.body.append(this.toggleMode)
})
}
set foreground(value) { return this.set("foreground", value) }
get(property) { return document.documentElement.style.getPropertyValue(`--${property}`) }
set(property, value) { return document.documentElement.style.setProperty(`--${property}`, value) }
get foreground() { return this.get("foreground") }
get background() { return this.get("background") }
set background(value) { return this.set("background", value) }
get fontSize() { return this.get("font-size") }
set fontSize(value) { return this.set("font-size", value) }
get mono() { return this.get("mono") }
set mono(value) { return this.set("mono", value) }
get serif() { return this.get("serif") }
set serif(value) { return this.set("serif", value) }
get sansSerif() { return this.get("sans-serif") }
set sansSerif(value) { return this.set("sans-serif", value) }
get mode() { return localStorage.getItem("mode") || "light" }
set mode(value) {
if (!/^(light|dark)$/.test(value))
throw Error("Invalid mode: use either 'light' or 'dark'")
localStorage.setItem("mode", value)
this.colors()
}
get theme() {
const theme = localStorage.getItem("theme")
return !theme || !this.allThemes[theme] ? "default" : theme
}
set theme(theme) {
if (this.themeSwitcher) this.themeSwitcher.textContent = this.allThemes[theme].icon
localStorage.setItem("theme", theme)
this.colors()
}
colors() {
const theme = this.allThemes[this.theme]
const foreground = theme.colors[0]
const background = theme.colors[1]
if (this.mode == "dark") {
this.foreground = background
this.background = foreground
} else {
this.foreground = foreground
this.background = background
}
}
themes(themes, mode) {
this.mode = mode || this.mode
this.allThemes = Object.assign(themes, this.allThemes)
css(`#themeSwitcher {
font-size: 1.5rem;
position: fixed;
top: 0.5rem;
right: ${this.modes ? "3.3rem" : "1rem"};
cursor: pointer;
border: none;
background: none;"
}`)
this.themeSwitcher = document.createElement("button")
this.themeSwitcher.id = "themeSwitcher"
this.themeSwitcher.onclick = () => {
const names = Object.keys(this.allThemes)
let next = names.indexOf(this.theme) + 1
next = next <= names.length - 1 ? next : 0
this.theme = names[next]
}
document.body.append(this.themeSwitcher)
this.theme = this.theme
return this
}
clickToCopy() {
css(`pre:hover {
cursor: pointer;
}
pre:hover::before {
content: "click to copy";
color: var(--foreground);
background-color: var(--background);
float: right;
}`)
for (const pre of document.getElementsByTagName('pre')) {
pre.onclick = () => {
navigator.clipboard.writeText(pre.textContent)
}
}
return this
}
inline({images, audio, video} = {images: false, audio: false, video: false}) {
if(images) {
css(`img {
display: block;
max-width: 100%;
}`)
const IMAGE_EXTENSIONS = /\.(jpeg|jpg|png|gif|bmp|svg|ico|webp|tiff)$/
for (const link of document.getElementsByTagName('a')) {
if (IMAGE_EXTENSIONS.test(link.pathname)) {
const img = document.createElement("img")
img.src = link.href
img.title = link.textContent.replace(/\n$/, "")
link.append(img)
}
}
}
if (audio) {
css(`audio {
width: 100%;
display: block;
}`)
const AUDIO_EXTENSIONS = /\.(mp3|ogg)$/
for (const link of document.getElementsByTagName('a')) {
if (AUDIO_EXTENSIONS.test(link.pathname)) {
const audio = document.createElement("audio")
audio.src = link.href
audio.title = link.textContent.replace(/\n$/, "")
audio.controls = true
audio.currentTime = true
audio.preload = "none"
link.append(audio)
}
}
}
if (video) {
css(`video {
width: 100%;
display: block;
}`)
const VIDEO_EXTENSIONS = /\.(mp4|webm|ogv|mov)$/
for (const link of document.getElementsByTagName('a')) {
if (VIDEO_EXTENSIONS.test(link.pathname)) {
const video = document.createElement("video")
video.src = link.href
video.title = link.textContent.replace(/\n$/, "")
video.controls = true
video.currentTime = true
video.preload = "metadata"
link.append(video)
}
}
}
return this
}
}
function css(css) {
if (!this.style) {
this.style = document.createElement("style")
document.documentElement.append(this.style)
}
this.style.textContent = this.style.textContent + "\n" + css
return this
}