Merge branch 'master' into master
20
.env.example
Normal file
@ -0,0 +1,20 @@
|
||||
# Specify your website URL
|
||||
# APP_SITE=https://count.getloli.com
|
||||
|
||||
# Application port
|
||||
APP_PORT=3000
|
||||
|
||||
# Database type: either 'sqlite' or 'mongodb'
|
||||
DB_TYPE=sqlite
|
||||
|
||||
# If using MongoDB, provide the connection string
|
||||
# DB_URL=mongodb://127.0.0.1:27017
|
||||
|
||||
# Database write interval in seconds (0 for real-time)
|
||||
DB_INTERVAL=60
|
||||
|
||||
# Log level: either 'debug' | 'info' | 'warn' | 'error' | 'none'
|
||||
LOG_LEVEL=debug
|
||||
|
||||
# Google Analytics `G-Tag` ID
|
||||
# GA_ID=G-XXXX
|
39
.github/ISSUE_TEMPLATE/contribute-theme.yml
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
name: Contribute Themes
|
||||
description: Contribute themes for everyone to use.
|
||||
title: "[Theme]: "
|
||||
labels: ["theme"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
### Contribute themes is welcome! Please read this brief tips to get started:
|
||||
|
||||
- Create images of numbers from *0-9*, file type can be *jpeg, png, gif, webp*,
|
||||
- Then named these images as *0.gif, 1.gif, ..., 9.gif* (or other extension).
|
||||
- Try to ensure that each image has an equal height, and that the image size is not too large.
|
||||
> Online image compressor: [TinyPNG](https://tinypng.com/) [Ezgif](https://ezgif.com/optimize)
|
||||
- Then pack these images into a ZIP file.
|
||||
|
||||
Additionally, please refrain from using political figures or controversial figures or characters.
|
||||
- type: checkboxes
|
||||
id: tips
|
||||
attributes:
|
||||
label: Tips
|
||||
options:
|
||||
- label: I have read and understood the tips above
|
||||
required: true
|
||||
- type: input
|
||||
id: name
|
||||
attributes:
|
||||
label: Theme Name
|
||||
description: Describe this theme with a short name that can include letters, numbers, and hyphens
|
||||
placeholder: ex. awesome
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: theme
|
||||
attributes:
|
||||
label: Preview and ZIP file
|
||||
description: Upload the theme preview, and ZIP file
|
||||
validations:
|
||||
required: true
|
1
.gitignore
vendored
@ -16,6 +16,7 @@ count.db
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
.env
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
|
291
README.md
@ -24,10 +24,245 @@ Multiple styles of Moe-Counters to choose from
|
||||
|
||||
##### gelbooru
|
||||
![Gelbooru](https://count.getloli.com/get/@demo?theme=gelbooru)</details>
|
||||
=======
|
||||
# *Moe Counter!*
|
||||
|
||||
多种风格可选的萌萌计数器
|
||||
|
||||
<p align="center">
|
||||
<a href="https://count.getloli.com" target="_blank">
|
||||
<img alt="Moe Counter!" src="https://count.getloli.com/@Moe-counter.github?name=Moe-counter.github&theme=booru-lewd&padding=7&offset=0&align=top&scale=1&pixelated=1&darkmode=auto">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://hellogithub.com/repository/ed741b376efe46789ce9bb140ac19a52" target="_blank">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://api.hellogithub.com/v1/widgets/recommend.svg?rid=ed741b376efe46789ce9bb140ac19a52&claim_uid=NyJh2Vejq3984f5&theme=dark" />
|
||||
<source media="(prefers-color-scheme: light)" srcset="https://api.hellogithub.com/v1/widgets/recommend.svg?rid=ed741b376efe46789ce9bb140ac19a52&claim_uid=NyJh2Vejq3984f5&theme=neutral" />
|
||||
<img src="https://api.hellogithub.com/v1/widgets/recommend.svg?rid=ed741b376efe46789ce9bb140ac19a52&claim_uid=NyJh2Vejq3984f5&theme=neutral" alt="Featured|HelloGitHub" style="width: 250px; height: 54px;" width="250" height="54" />
|
||||
</picture>
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<details>
|
||||
<summary><h2>More theme</h2></summary>
|
||||
|
||||
### *[Contribute themes is welcome!](https://github.com/journey-ad/Moe-Counter/issues/new?assignees=&labels=theme&projects=&template=contribute-theme.yml&title=%5BTheme%5D%3A+)*
|
||||
|
||||
##### 3d-num
|
||||
|
||||
![3d-num](https://count.getloli.com/@demo?theme=3d-num)
|
||||
|
||||
##### ai-1
|
||||
|
||||
![ai-1](https://count.getloli.com/@demo?theme=ai-1)
|
||||
|
||||
##### asoul
|
||||
|
||||
![asoul](https://count.getloli.com/@demo?theme=asoul)
|
||||
|
||||
##### booru-ffsr
|
||||
|
||||
![booru-ffsr](https://count.getloli.com/@demo?theme=booru-ffsr)
|
||||
|
||||
##### booru-helltaker
|
||||
|
||||
![booru-helltaker](https://count.getloli.com/@demo?theme=booru-helltaker)
|
||||
|
||||
##### booru-huggboo
|
||||
|
||||
![booru-huggboo](https://count.getloli.com/@demo?theme=booru-huggboo)
|
||||
|
||||
##### booru-jaypee
|
||||
|
||||
![booru-jaypee](https://count.getloli.com/@demo?theme=booru-jaypee)
|
||||
|
||||
##### booru-koe
|
||||
|
||||
![booru-koe](https://count.getloli.com/@demo?theme=booru-koe)
|
||||
|
||||
##### booru-lewd
|
||||
|
||||
![booru-lewd](https://count.getloli.com/@demo?theme=booru-lewd)
|
||||
|
||||
##### booru-lisu
|
||||
|
||||
![booru-lisu](https://count.getloli.com/@demo?theme=booru-lisu)
|
||||
|
||||
##### booru-mjg
|
||||
|
||||
![booru-mjg](https://count.getloli.com/@demo?theme=booru-mjg)
|
||||
|
||||
##### booru-mof
|
||||
|
||||
![booru-mof](https://count.getloli.com/@demo?theme=booru-mof)
|
||||
|
||||
##### booru-nandroid
|
||||
|
||||
![booru-nandroid](https://count.getloli.com/@demo?theme=booru-nandroid)
|
||||
|
||||
##### booru-qualityhentais
|
||||
|
||||
![booru-qualityhentais](https://count.getloli.com/@demo?theme=booru-qualityhentais)
|
||||
|
||||
##### booru-r6gdrawfriends
|
||||
|
||||
![booru-r6gdrawfriends](https://count.getloli.com/@demo?theme=booru-r6gdrawfriends)
|
||||
|
||||
##### booru-rfck
|
||||
|
||||
![booru-rfck](https://count.getloli.com/@demo?theme=booru-rfck)
|
||||
|
||||
##### booru-smtg
|
||||
|
||||
![booru-smtg](https://count.getloli.com/@demo?theme=booru-smtg)
|
||||
|
||||
##### booru-snyde
|
||||
|
||||
![booru-snyde](https://count.getloli.com/@demo?theme=booru-snyde)
|
||||
|
||||
##### booru-the-collection
|
||||
|
||||
![booru-the-collection](https://count.getloli.com/@demo?theme=booru-the-collection)
|
||||
|
||||
##### booru-touhoulat
|
||||
|
||||
![booru-touhoulat](https://count.getloli.com/@demo?theme=booru-touhoulat)
|
||||
|
||||
##### booru-townofgravityfalls
|
||||
|
||||
![booru-townofgravityfalls](https://count.getloli.com/@demo?theme=booru-townofgravityfalls)
|
||||
|
||||
##### booru-twifanartsfw
|
||||
|
||||
![booru-twifanartsfw](https://count.getloli.com/@demo?theme=booru-twifanartsfw)
|
||||
|
||||
##### booru-ve
|
||||
|
||||
![booru-ve](https://count.getloli.com/@demo?theme=booru-ve)
|
||||
|
||||
##### booru-vivi
|
||||
|
||||
![booru-vivi](https://count.getloli.com/@demo?theme=booru-vivi)
|
||||
|
||||
##### booru-vp
|
||||
|
||||
![booru-vp](https://count.getloli.com/@demo?theme=booru-vp)
|
||||
|
||||
##### booru-yuyuyui
|
||||
|
||||
![booru-yuyuyui](https://count.getloli.com/@demo?theme=booru-yuyuyui)
|
||||
|
||||
##### capoo-1
|
||||
|
||||
![capoo-1](https://count.getloli.com/@demo?theme=capoo-1)
|
||||
|
||||
##### capoo-2
|
||||
|
||||
![capoo-2](https://count.getloli.com/@demo?theme=capoo-2)
|
||||
|
||||
##### e621
|
||||
|
||||
![e621](https://count.getloli.com/@demo?theme=e621)
|
||||
|
||||
##### food
|
||||
|
||||
![food](https://count.getloli.com/@demo?theme=food)
|
||||
|
||||
##### gelbooru
|
||||
|
||||
![gelbooru](https://count.getloli.com/@demo?theme=gelbooru)
|
||||
|
||||
##### green
|
||||
|
||||
![green](https://count.getloli.com/@demo?theme=green)
|
||||
|
||||
##### kasuterura-1
|
||||
|
||||
![kasuterura-1](https://count.getloli.com/@demo?theme=kasuterura-1)
|
||||
|
||||
##### kasuterura-2
|
||||
|
||||
![kasuterura-2](https://count.getloli.com/@demo?theme=kasuterura-2)
|
||||
|
||||
##### kasuterura-3
|
||||
|
||||
![kasuterura-3](https://count.getloli.com/@demo?theme=kasuterura-3)
|
||||
|
||||
##### kasuterura-4
|
||||
|
||||
![kasuterura-4](https://count.getloli.com/@demo?theme=kasuterura-4)
|
||||
|
||||
##### kyun
|
||||
|
||||
![kyun](https://count.getloli.com/@demo?theme=kyun)
|
||||
|
||||
##### love-and-deepspace
|
||||
|
||||
![love-and-deepspace](https://count.getloli.com/@demo?theme=love-and-deepspace)
|
||||
|
||||
##### minecraft
|
||||
|
||||
![minecraft](https://count.getloli.com/@demo?theme=minecraft)
|
||||
|
||||
##### moebooru
|
||||
|
||||
![moebooru](https://count.getloli.com/@demo?theme=moebooru)
|
||||
|
||||
##### morden-num
|
||||
|
||||
![morden-num](https://count.getloli.com/@demo?theme=morden-num)
|
||||
|
||||
##### nixietube-1
|
||||
|
||||
![nixietube-1](https://count.getloli.com/@demo?theme=nixietube-1)
|
||||
|
||||
##### nixietube-2
|
||||
|
||||
![nixietube-2](https://count.getloli.com/@demo?theme=nixietube-2)
|
||||
|
||||
##### normal-1
|
||||
|
||||
![normal-1](https://count.getloli.com/@demo?theme=normal-1)
|
||||
|
||||
##### normal-2
|
||||
|
||||
![normal-2](https://count.getloli.com/@demo?theme=normal-2)
|
||||
|
||||
##### original-new
|
||||
|
||||
![original-new](https://count.getloli.com/@demo?theme=original-new)
|
||||
|
||||
##### original-old
|
||||
|
||||
![original-old](https://count.getloli.com/@demo?theme=original-old)
|
||||
|
||||
##### rule34
|
||||
|
||||
![rule34](https://count.getloli.com/@demo?theme=rule34)
|
||||
|
||||
##### shimmie2
|
||||
|
||||
![shimmie2](https://count.getloli.com/@demo?theme=shimmie2)
|
||||
|
||||
##### sketch-1
|
||||
|
||||
![sketch-1](https://count.getloli.com/@demo?theme=sketch-1)
|
||||
|
||||
##### sketch-2
|
||||
|
||||
![sketch-2](https://count.getloli.com/@demo?theme=sketch-2)
|
||||
|
||||
</details>
|
||||
|
||||
## Demo
|
||||
[https://count.getloli.com](https://count.getloli.com)
|
||||
|
||||
## How to use
|
||||
|
||||
For information on counter usage and configuration, refer to the [demo website](https://count.getloli.com).
|
||||
|
||||
## Usage
|
||||
|
||||
### Install
|
||||
@ -38,14 +273,25 @@ Multiple styles of Moe-Counters to choose from
|
||||
- Just hit the **Fork** button
|
||||
- And hit the **Run** button
|
||||
|
||||
#### Run on Glitch
|
||||
|
||||
- Open [Glitch project](https://glitch.com/~moe-counter-api)
|
||||
- Just hit the **Remix your own** button
|
||||
- That's it!
|
||||
|
||||
#### Deploying on your own server
|
||||
|
||||
```shell
|
||||
$ git clone https://github.com/journey-ad/Moe-Counter.git
|
||||
$ cd Moe-Counter
|
||||
|
||||
$ yarn install
|
||||
|
||||
$ yarn start
|
||||
|
||||
$ pnpm install
|
||||
|
||||
$ pnpm run start
|
||||
```
|
||||
|
||||
### Configuration
|
||||
@ -72,6 +318,30 @@ Replit can use Secrets, check [documentation](https://docs.replit.com/programmin
|
||||
|
||||
```
|
||||
DB_URL="mongodb+srv://account:passwd@***.***.***.mongodb.net/db_count"
|
||||
=======
|
||||
Set `.env` file to specify the environment variables. *[.env.example](./.env.example)*
|
||||
|
||||
```dosini
|
||||
# Specify your website URL
|
||||
# APP_SITE=https://count.getloli.com
|
||||
|
||||
# Application port
|
||||
APP_PORT=3000
|
||||
|
||||
# Database type: either 'sqlite' or 'mongodb'
|
||||
DB_TYPE=sqlite
|
||||
|
||||
# If using MongoDB, provide the connection string
|
||||
# DB_URL=mongodb://127.0.0.1:27017
|
||||
|
||||
# Database write interval in seconds (0 for real-time)
|
||||
DB_INTERVAL=60
|
||||
|
||||
# Log level: either 'debug' | 'info' | 'warn' | 'error' | 'none'
|
||||
LOG_LEVEL=debug
|
||||
|
||||
# Google Analytics `G-Tag` ID
|
||||
# GA_ID=G-XXXX
|
||||
```
|
||||
|
||||
## Credits
|
||||
@ -86,3 +356,24 @@ DB_URL="mongodb+srv://account:passwd@***.***.***.mongodb.net/db_count"
|
||||
## License
|
||||
|
||||
[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fjourney-ad%2FMoe-Counter.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2Fjourney-ad%2FMoe-Counter?ref=badge_large)
|
||||
=======
|
||||
* [Glitch](https://glitch.com/)
|
||||
* [A-SOUL_Official](https://space.bilibili.com/703007996)
|
||||
* [moebooru](https://github.com/moebooru/moebooru)
|
||||
* gelbooru.com NSFW
|
||||
* [Icons8](https://icons8.com/icon/80355/star)
|
||||
* *And all booru site...*
|
||||
|
||||
## License
|
||||
|
||||
[MIT License](./LICENSE), excluding all themes
|
||||
|
||||
---
|
||||
|
||||
<a href="https://star-history.com/?repos=journey-ad/Moe-Counter&type=Date#journey-ad/Moe-Counter&Date">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=journey-ad/Moe-Counter&type=Date&theme=dark" />
|
||||
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=journey-ad/Moe-Counter&type=Date" />
|
||||
<img alt="Star History Chart" src="https://api.star-history.com/svg?repos=journey-ad/Moe-Counter&type=Date" />
|
||||
</picture>
|
||||
</a>
|
||||
|
BIN
assets/img/back-to-top.png
Normal file
After Width: | Height: | Size: 37 KiB |
1
assets/img/failed.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg"><style>@media (prefers-color-scheme:dark){svg{filter:invert(1)}}</style><path d="M170.667 469.333c4.266 4.267 12.8 8.534 21.333 8.534s17.067 0 21.333-8.534l64-64 64 64c4.267 4.267 12.8 8.534 21.334 8.534s17.066 0 21.333-8.534c12.8-12.8 12.8-34.133 0-46.933l-59.733-59.733 59.733-64c12.8-12.8 12.8-29.867 0-42.667s-29.867-12.8-42.667 0l-64 59.733-64-59.733c-12.8-12.8-29.866-12.8-42.666 0s-12.8 29.867 0 42.667l64 64-64 64c-12.8 12.8-12.8 29.866 0 42.666z"/><path d="M917.333 85.333H106.667C46.933 85.333 0 132.267 0 192v640c0 59.733 46.933 106.667 106.667 106.667h810.666C977.067 938.667 1024 891.733 1024 832V192c0-59.733-46.933-106.667-106.667-106.667zm-810.666 85.334h810.666c12.8 0 21.334 8.533 21.334 21.333v477.867L686.933 435.2c-17.066-17.067-42.666-17.067-59.733 0L405.333 657.067l-102.4-102.4c-17.066-17.067-38.4-17.067-55.466-4.267L85.333 686.933V192c0-12.8 8.534-21.333 21.334-21.333zm810.666 682.666H106.667c-12.8 0-21.334-8.533-21.334-21.333v-34.133l187.734-149.334 102.4 102.4c17.066 17.067 42.666 17.067 59.733 0l221.867-221.866L934.4 789.333V832c4.267 12.8-4.267 21.333-17.067 21.333z"/></svg>
|
After Width: | Height: | Size: 1.1 KiB |
1
assets/img/loading.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><style>@keyframes _xe7Q{93.75%,to{r:3px}46.875%{r:.2px}}._b2T7{animation:_xe7Q .8s linear infinite}@media (prefers-color-scheme:dark){svg{filter:invert(1)}}</style><circle class="_b2T7" cx="4" cy="12" r="3"/><circle class="_b2T7" cx="12" cy="12" r="3" style="animation-delay:-.65s"/><circle class="_b2T7" cx="20" cy="12" r="3" style="animation-delay:-.5s"/></svg>
|
After Width: | Height: | Size: 446 B |
208
assets/script.js
Normal file
@ -0,0 +1,208 @@
|
||||
(function () {
|
||||
const btn = document.getElementById('get');
|
||||
const img = document.getElementById('result');
|
||||
const code = document.getElementById('code');
|
||||
|
||||
const elements = {
|
||||
name: document.getElementById('name'),
|
||||
theme: document.getElementById('theme'),
|
||||
padding: document.getElementById('padding'),
|
||||
offset: document.getElementById('offset'),
|
||||
align: document.getElementById('align'),
|
||||
scale: document.getElementById('scale'),
|
||||
pixelated: document.getElementById('pixelated'),
|
||||
darkmode: document.getElementById('darkmode'),
|
||||
num: document.getElementById('num'),
|
||||
prefix: document.getElementById('prefix')
|
||||
};
|
||||
|
||||
btn.addEventListener('click', throttle(handleButtonClick, 500));
|
||||
code.addEventListener('click', selectCodeText);
|
||||
|
||||
const mainTitle = document.querySelector('#main_title i');
|
||||
const themes = document.querySelector('#themes');
|
||||
const moreTheme = document.querySelector('#more_theme');
|
||||
|
||||
mainTitle.addEventListener('click', throttle(() => party.sparkles(document.documentElement, { count: party.variation.range(40, 100) }), 1000));
|
||||
moreTheme.addEventListener('click', scrollToThemes);
|
||||
|
||||
function handleButtonClick() {
|
||||
const { name, theme, padding, offset, scale, pixelated, darkmode, num } = elements;
|
||||
const nameValue = name.value.trim();
|
||||
|
||||
if (!nameValue) {
|
||||
alert('Please input counter name.');
|
||||
return;
|
||||
}
|
||||
|
||||
const params = {
|
||||
name: nameValue,
|
||||
theme: theme.value || 'moebooru',
|
||||
padding: padding.value || '7',
|
||||
offset: offset.value || '0',
|
||||
align: align.value || 'top',
|
||||
scale: scale.value || '1',
|
||||
pixelated: pixelated.checked ? '1' : '0',
|
||||
darkmode: darkmode.value || 'auto'
|
||||
};
|
||||
|
||||
if (num.value > 0) {
|
||||
params.num = num.value;
|
||||
}
|
||||
if (prefix.value !== '') {
|
||||
params.prefix = prefix.value;
|
||||
}
|
||||
|
||||
const query = new URLSearchParams(params).toString();
|
||||
const imgSrc = `${__global_data.site}/@${nameValue}?${query}`;
|
||||
|
||||
img.src = `${imgSrc}&_=${Math.random()}`;
|
||||
btn.setAttribute('disabled', '');
|
||||
|
||||
img.onload = () => {
|
||||
img.scrollIntoView({ block: 'start', behavior: 'smooth' });
|
||||
code.textContent = imgSrc;
|
||||
code.style.visibility = 'visible';
|
||||
party.confetti(btn, { count: party.variation.range(20, 40) });
|
||||
btn.removeAttribute('disabled');
|
||||
};
|
||||
|
||||
img.onerror = async () => {
|
||||
try {
|
||||
const res = await fetch(img.src);
|
||||
if (!res.ok) {
|
||||
const { message } = await res.json();
|
||||
alert(message);
|
||||
}
|
||||
} finally {
|
||||
btn.removeAttribute('disabled');
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function selectCodeText(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
const target = e.target;
|
||||
const range = document.createRange();
|
||||
const selection = window.getSelection();
|
||||
|
||||
range.selectNodeContents(target);
|
||||
selection.removeAllRanges();
|
||||
selection.addRange(range);
|
||||
}
|
||||
|
||||
function scrollToThemes() {
|
||||
if (!themes.hasAttribute('open')) {
|
||||
party.sparkles(moreTheme.querySelector('h3'), { count: party.variation.range(20, 40) });
|
||||
themes.scrollIntoView({ block: 'start', behavior: 'smooth' });
|
||||
}
|
||||
}
|
||||
|
||||
function throttle(fn, threshold = 250) {
|
||||
let last, deferTimer;
|
||||
return function (...args) {
|
||||
const now = Date.now();
|
||||
if (last && now < last + threshold) {
|
||||
clearTimeout(deferTimer);
|
||||
deferTimer = setTimeout(() => {
|
||||
last = now;
|
||||
fn.apply(this, args);
|
||||
}, threshold);
|
||||
} else {
|
||||
last = now;
|
||||
fn.apply(this, args);
|
||||
}
|
||||
};
|
||||
}
|
||||
})();
|
||||
|
||||
// Lazy Load
|
||||
(() => {
|
||||
function lazyLoad(options = {}) {
|
||||
const { selector = 'img[data-src]:not([src])', loading = '', failed = '', rootMargin = '200px', threshold = 0.01 } = options;
|
||||
|
||||
const images = document.querySelectorAll(selector);
|
||||
|
||||
const observer = new IntersectionObserver((entries, observer) => {
|
||||
entries.forEach(entry => {
|
||||
if (entry.isIntersecting) {
|
||||
const img = entry.target;
|
||||
observer.unobserve(img);
|
||||
|
||||
img.onerror = failed ? () => { img.src = failed; img.setAttribute('data-failed', ''); } : null;
|
||||
img.src = img.getAttribute('data-src');
|
||||
img.removeAttribute('data-loading');
|
||||
}
|
||||
});
|
||||
}, { rootMargin, threshold });
|
||||
|
||||
images.forEach(img => {
|
||||
if (loading) {
|
||||
img.src = loading;
|
||||
img.setAttribute('data-loading', '');
|
||||
}
|
||||
observer.observe(img);
|
||||
});
|
||||
}
|
||||
|
||||
const lazyLoadOptions = {
|
||||
selector: 'img[data-src]:not([src])',
|
||||
loading: `${__global_data.site}/img/loading.svg`,
|
||||
failed: `${__global_data.site}/img/failed.svg`,
|
||||
rootMargin: '200px',
|
||||
threshold: 0.01
|
||||
};
|
||||
|
||||
document.readyState === 'loading'
|
||||
? document.addEventListener("DOMContentLoaded", () => lazyLoad(lazyLoadOptions))
|
||||
: lazyLoad(lazyLoadOptions);
|
||||
})();
|
||||
|
||||
// Back to top
|
||||
(() => {
|
||||
let isShow = false, lock = false;
|
||||
const btn = document.querySelector('.back-to-top');
|
||||
|
||||
const handleScroll = () => {
|
||||
if (lock) return;
|
||||
if (document.body.scrollTop >= 1000) {
|
||||
if (!isShow) {
|
||||
btn.classList.add('load');
|
||||
isShow = true;
|
||||
}
|
||||
} else if (isShow) {
|
||||
btn.classList.remove('load');
|
||||
isShow = false;
|
||||
}
|
||||
};
|
||||
|
||||
const handleClick = () => {
|
||||
lock = true;
|
||||
btn.classList.add('ani-leave');
|
||||
window.scrollTo({ top: 0, behavior: 'smooth' });
|
||||
|
||||
setTimeout(() => {
|
||||
btn.classList.remove('ani-leave');
|
||||
btn.classList.add('leaved');
|
||||
}, 390);
|
||||
|
||||
setTimeout(() => btn.classList.add('ending'), 120);
|
||||
setTimeout(() => btn.classList.remove('load'), 1500);
|
||||
|
||||
setTimeout(() => {
|
||||
lock = false;
|
||||
isShow = false;
|
||||
btn.classList.remove('leaved', 'ending');
|
||||
}, 2000);
|
||||
};
|
||||
|
||||
window.addEventListener('scroll', handleScroll);
|
||||
btn.addEventListener('click', handleClick);
|
||||
})();
|
||||
|
||||
// Prevent safari gesture
|
||||
(() => {
|
||||
document.addEventListener('gesturestart', e => e.preventDefault());
|
||||
})();
|
@ -1,5 +0,0 @@
|
||||
@media screen and (max-width: 900px) {
|
||||
iframe {
|
||||
display: none;
|
||||
}
|
||||
}
|
243
assets/style.less
Normal file
@ -0,0 +1,243 @@
|
||||
html {
|
||||
scroll-padding: 50px 0;
|
||||
}
|
||||
|
||||
#main_title {
|
||||
margin-top: 0.5em;
|
||||
}
|
||||
|
||||
#themes {
|
||||
margin-top: 2em;
|
||||
|
||||
& > p {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
#more_theme h3 {
|
||||
display: inline-block;
|
||||
margin: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#get {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
#code {
|
||||
visibility: hidden;
|
||||
display: inline-block;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
#result {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.github {
|
||||
margin-top: 2em;
|
||||
}
|
||||
|
||||
code {
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
input[type="checkbox"][role="switch"] {
|
||||
height: 0;
|
||||
width: 0;
|
||||
visibility: hidden;
|
||||
|
||||
& + label {
|
||||
cursor: pointer;
|
||||
width: 3.6em;
|
||||
height: 1.8em;
|
||||
margin: 0;
|
||||
background: grey;
|
||||
display: block;
|
||||
border-radius: 1.8em;
|
||||
position: relative;
|
||||
transition: 0.3s;
|
||||
|
||||
&:active:after {
|
||||
width: 2.34em;
|
||||
}
|
||||
|
||||
&:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0.1em;
|
||||
left: 0.1em;
|
||||
width: 1.6em;
|
||||
height: 1.6em;
|
||||
background: #fff;
|
||||
border-radius: 1.6em;
|
||||
transition: 0.3s;
|
||||
}
|
||||
|
||||
span {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 0 12.5%;
|
||||
font-size: 10px;
|
||||
|
||||
&::before,
|
||||
&::after {
|
||||
display: block;
|
||||
color: #fff;
|
||||
font-weight: bold;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
&::before {
|
||||
content: "ON";
|
||||
}
|
||||
|
||||
&::after {
|
||||
content: "OFF";
|
||||
color: #ccc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:checked + label {
|
||||
background: var(--b-btn-bg);
|
||||
|
||||
&:after {
|
||||
left: calc(100% - 0.1em);
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
img[data-loading],
|
||||
img[data-failed] {
|
||||
width: 40px;
|
||||
}
|
||||
|
||||
details > summary {
|
||||
list-style: none;
|
||||
|
||||
&::-webkit-details-marker,
|
||||
&::marker {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
summary::before {
|
||||
border-bottom: 6px solid transparent;
|
||||
border-left: 10px solid var(--b-txt);
|
||||
border-top: 6px solid transparent;
|
||||
content: "";
|
||||
display: inline-block;
|
||||
height: 0;
|
||||
margin-right: 10px;
|
||||
position: relative;
|
||||
transition: 0.2s;
|
||||
width: 0;
|
||||
}
|
||||
|
||||
details[open] summary::before {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5 {
|
||||
margin: 1.5em 0 0.6em;
|
||||
}
|
||||
|
||||
table {
|
||||
tr {
|
||||
.caption {
|
||||
margin: 1em 0 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.back-to-top {
|
||||
position: fixed;
|
||||
z-index: 2;
|
||||
right: -108px;
|
||||
bottom: 0;
|
||||
width: 108px;
|
||||
height: 150px;
|
||||
background: url("./img/back-to-top.png?v=1") no-repeat 0 0;
|
||||
background-size: 108px 450px;
|
||||
opacity: 0.6;
|
||||
transition: opacity 0.3s, right 0.8s;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
background-position: 0 -150px;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
&::after {
|
||||
content: "";
|
||||
position: fixed;
|
||||
z-index: 2;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
width: 108px;
|
||||
height: 150px;
|
||||
background: url("./img/back-to-top.png?v=1") no-repeat 0 0;
|
||||
background-size: 108px 450px;
|
||||
background-position: 0 -300px;
|
||||
transition: opacity 0.3s;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
&.load {
|
||||
right: 0;
|
||||
}
|
||||
|
||||
&.ani-leave {
|
||||
background-position: 0 -150px;
|
||||
animation: ani-leave 390ms ease-in-out forwards;
|
||||
|
||||
@keyframes ani-leave {
|
||||
0% {
|
||||
transform: translateX(0);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translateX(108px);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.leaved,
|
||||
&.ending {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
&.leaved {
|
||||
background: none;
|
||||
transition: none;
|
||||
}
|
||||
|
||||
&.ending::after {
|
||||
opacity: 1;
|
||||
transition-delay: 0.35s;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 800px) {
|
||||
body {
|
||||
max-width: ~"min(90%, 800px)";
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 900px) {
|
||||
iframe {
|
||||
display: none;
|
||||
}
|
||||
}
|
BIN
assets/theme/3d-num/0.gif
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
assets/theme/3d-num/1.gif
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
assets/theme/3d-num/2.gif
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
assets/theme/3d-num/3.gif
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
assets/theme/3d-num/4.gif
Normal file
After Width: | Height: | Size: 1.8 KiB |
BIN
assets/theme/3d-num/5.gif
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
assets/theme/3d-num/6.gif
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
assets/theme/3d-num/7.gif
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
assets/theme/3d-num/8.gif
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
assets/theme/3d-num/9.gif
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
assets/theme/ai-1/0.png
Normal file
After Width: | Height: | Size: 5.4 KiB |
BIN
assets/theme/ai-1/1.png
Normal file
After Width: | Height: | Size: 6.6 KiB |
BIN
assets/theme/ai-1/2.png
Normal file
After Width: | Height: | Size: 4.9 KiB |
BIN
assets/theme/ai-1/3.png
Normal file
After Width: | Height: | Size: 5.7 KiB |
BIN
assets/theme/ai-1/4.png
Normal file
After Width: | Height: | Size: 6.2 KiB |
BIN
assets/theme/ai-1/5.png
Normal file
After Width: | Height: | Size: 6.8 KiB |
BIN
assets/theme/ai-1/6.png
Normal file
After Width: | Height: | Size: 6.1 KiB |
BIN
assets/theme/ai-1/7.png
Normal file
After Width: | Height: | Size: 4.9 KiB |
BIN
assets/theme/ai-1/8.png
Normal file
After Width: | Height: | Size: 5.3 KiB |
BIN
assets/theme/ai-1/9.png
Normal file
After Width: | Height: | Size: 4.9 KiB |
BIN
assets/theme/booru-ffsr/0.gif
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
assets/theme/booru-ffsr/1.gif
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
assets/theme/booru-ffsr/2.gif
Normal file
After Width: | Height: | Size: 2.3 KiB |
BIN
assets/theme/booru-ffsr/3.gif
Normal file
After Width: | Height: | Size: 3.0 KiB |
BIN
assets/theme/booru-ffsr/4.gif
Normal file
After Width: | Height: | Size: 2.0 KiB |
BIN
assets/theme/booru-ffsr/5.gif
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
assets/theme/booru-ffsr/6.gif
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
assets/theme/booru-ffsr/7.gif
Normal file
After Width: | Height: | Size: 3.0 KiB |
BIN
assets/theme/booru-ffsr/8.gif
Normal file
After Width: | Height: | Size: 2.6 KiB |
BIN
assets/theme/booru-ffsr/9.gif
Normal file
After Width: | Height: | Size: 3.3 KiB |
BIN
assets/theme/booru-helltaker/0.gif
Normal file
After Width: | Height: | Size: 6.6 KiB |
BIN
assets/theme/booru-helltaker/1.gif
Normal file
After Width: | Height: | Size: 6.1 KiB |
BIN
assets/theme/booru-helltaker/2.gif
Normal file
After Width: | Height: | Size: 5.6 KiB |
BIN
assets/theme/booru-helltaker/3.gif
Normal file
After Width: | Height: | Size: 5.1 KiB |
BIN
assets/theme/booru-helltaker/4.gif
Normal file
After Width: | Height: | Size: 5.0 KiB |
BIN
assets/theme/booru-helltaker/5.gif
Normal file
After Width: | Height: | Size: 5.5 KiB |
BIN
assets/theme/booru-helltaker/6.gif
Normal file
After Width: | Height: | Size: 5.8 KiB |
BIN
assets/theme/booru-helltaker/7.gif
Normal file
After Width: | Height: | Size: 6.9 KiB |
BIN
assets/theme/booru-helltaker/8.gif
Normal file
After Width: | Height: | Size: 5.6 KiB |
BIN
assets/theme/booru-helltaker/9.gif
Normal file
After Width: | Height: | Size: 9.2 KiB |
BIN
assets/theme/booru-huggboo/0.gif
Normal file
After Width: | Height: | Size: 3.3 KiB |
BIN
assets/theme/booru-huggboo/1.gif
Normal file
After Width: | Height: | Size: 2.8 KiB |
BIN
assets/theme/booru-huggboo/2.gif
Normal file
After Width: | Height: | Size: 3.4 KiB |
BIN
assets/theme/booru-huggboo/3.gif
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
assets/theme/booru-huggboo/4.gif
Normal file
After Width: | Height: | Size: 4.4 KiB |
BIN
assets/theme/booru-huggboo/5.gif
Normal file
After Width: | Height: | Size: 3.6 KiB |
BIN
assets/theme/booru-huggboo/6.gif
Normal file
After Width: | Height: | Size: 3.1 KiB |
BIN
assets/theme/booru-huggboo/7.gif
Normal file
After Width: | Height: | Size: 3.5 KiB |
BIN
assets/theme/booru-huggboo/8.gif
Normal file
After Width: | Height: | Size: 3.5 KiB |
BIN
assets/theme/booru-huggboo/9.gif
Normal file
After Width: | Height: | Size: 3.1 KiB |
BIN
assets/theme/booru-jaypee/0.gif
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
assets/theme/booru-jaypee/1.gif
Normal file
After Width: | Height: | Size: 2.3 KiB |
BIN
assets/theme/booru-jaypee/2.gif
Normal file
After Width: | Height: | Size: 3.8 KiB |
BIN
assets/theme/booru-jaypee/3.gif
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
assets/theme/booru-jaypee/4.gif
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
assets/theme/booru-jaypee/5.gif
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
assets/theme/booru-jaypee/6.gif
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
assets/theme/booru-jaypee/7.gif
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
assets/theme/booru-jaypee/8.gif
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
assets/theme/booru-jaypee/9.gif
Normal file
After Width: | Height: | Size: 3.8 KiB |
BIN
assets/theme/booru-koe/0.gif
Normal file
After Width: | Height: | Size: 3.8 KiB |
BIN
assets/theme/booru-koe/1.gif
Normal file
After Width: | Height: | Size: 4.0 KiB |
BIN
assets/theme/booru-koe/2.gif
Normal file
After Width: | Height: | Size: 4.2 KiB |
BIN
assets/theme/booru-koe/3.gif
Normal file
After Width: | Height: | Size: 3.6 KiB |
BIN
assets/theme/booru-koe/4.gif
Normal file
After Width: | Height: | Size: 4.7 KiB |
BIN
assets/theme/booru-koe/5.gif
Normal file
After Width: | Height: | Size: 3.4 KiB |
BIN
assets/theme/booru-koe/6.gif
Normal file
After Width: | Height: | Size: 3.1 KiB |
BIN
assets/theme/booru-koe/7.gif
Normal file
After Width: | Height: | Size: 3.7 KiB |
BIN
assets/theme/booru-koe/8.gif
Normal file
After Width: | Height: | Size: 4.0 KiB |
BIN
assets/theme/booru-koe/9.gif
Normal file
After Width: | Height: | Size: 4.3 KiB |
BIN
assets/theme/booru-lewd/0.gif
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
assets/theme/booru-lewd/1.gif
Normal file
After Width: | Height: | Size: 6.5 KiB |
BIN
assets/theme/booru-lewd/2.gif
Normal file
After Width: | Height: | Size: 6.9 KiB |
BIN
assets/theme/booru-lewd/3.gif
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
assets/theme/booru-lewd/4.gif
Normal file
After Width: | Height: | Size: 9.7 KiB |
BIN
assets/theme/booru-lewd/5.gif
Normal file
After Width: | Height: | Size: 9.3 KiB |
BIN
assets/theme/booru-lewd/6.gif
Normal file
After Width: | Height: | Size: 8.3 KiB |
BIN
assets/theme/booru-lewd/7.gif
Normal file
After Width: | Height: | Size: 8.1 KiB |
BIN
assets/theme/booru-lewd/8.gif
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
assets/theme/booru-lewd/9.gif
Normal file
After Width: | Height: | Size: 5.0 KiB |
BIN
assets/theme/booru-lisu/0.gif
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
assets/theme/booru-lisu/1.gif
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
assets/theme/booru-lisu/2.gif
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
assets/theme/booru-lisu/3.gif
Normal file
After Width: | Height: | Size: 2.0 KiB |
BIN
assets/theme/booru-lisu/4.gif
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
assets/theme/booru-lisu/5.gif
Normal file
After Width: | Height: | Size: 2.3 KiB |
BIN
assets/theme/booru-lisu/6.gif
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
assets/theme/booru-lisu/7.gif
Normal file
After Width: | Height: | Size: 2.3 KiB |
BIN
assets/theme/booru-lisu/8.gif
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
assets/theme/booru-lisu/9.gif
Normal file
After Width: | Height: | Size: 5.3 KiB |