Compare commits

..

35 Commits

Author SHA1 Message Date
roffy3051
e614d279c1 Update README.md 2024-11-02 21:47:27 +08:00
roffy3051
1b4e98af4a feat: Improve performance
feat: Add `prefix` param
feat: Theme supports `_start` and `_end` as padding image
2024-11-02 21:44:48 +08:00
roffy3051
dbf98b4735 chore: Add themes 2024-11-02 21:39:14 +08:00
Jad
84b8111fd3
Update README.md 2024-11-01 01:05:05 +08:00
journey-ad
09fb0186d0 feat: Strictly limit parameter types 2024-10-31 16:54:37 +08:00
Jad
5ae1921530
Update README.md 2024-10-31 14:21:03 +08:00
journey-ad
6f90c7a062 fix(web): wrong template ga_id 2024-10-31 14:11:39 +08:00
journey-ad
16948c7038 feat: Add GA_ID and LOG_LEVEL environment variables 2024-10-31 13:58:21 +08:00
Jad
f16899d51e
Update README.md 2024-10-31 11:54:06 +08:00
journey-ad
005f736f44 feat: Add align param 2024-10-30 16:06:09 +08:00
roffy3051
e4132e0ef1 feat: use .env instead of config.yml as configuration file #66 2024-10-29 00:24:12 +08:00
roffy3051
f4bc3cfc33 chore: Add theme ai-1 2024-10-25 23:26:36 +08:00
journey-ad
bdc1cb0794 refactor: Add cors middleware 2024-10-25 13:36:32 +08:00
journey-ad
1dce9e93aa feat: Add num param 2024-10-25 12:53:34 +08:00
journey-ad
c0b421125c chore: Add theme booru-lewd 2024-10-25 10:14:06 +08:00
roffy3051
74cad48f28 refactor(web): Improve performance 2024-10-23 03:59:07 +08:00
journey-ad
2922452f9d chore: Add theme love-and-deepspace #65 2024-10-22 11:33:45 +08:00
journey-ad
fa1b537da1 Update contribute-theme.yml 2024-10-22 11:32:39 +08:00
roffy3051
de3ade4086 chore: Add some themes 2024-10-22 01:31:38 +08:00
journey-ad
d4ad5fad3d feat(web): Add lazyload 2024-10-21 12:22:51 +08:00
roffy3051
440c6e9f72 docs: Add contribute theme template 2024-10-21 02:06:51 +08:00
roffy3051
97c529e540 feat(web): show message on error 2024-10-21 00:58:30 +08:00
roffy3051
41bf6caeb8 refactor: Improve performance 2024-10-21 00:19:35 +08:00
roffy3051
14c5e0c86c Update README.md 2024-10-20 16:40:27 +08:00
roffy3051
fa8500fac7 chore: Add some themes 2024-10-20 16:23:18 +08:00
roffy3051
56dbf9bf08 chore: Add some themes
from https://forgejo.sny.sh/sun/MCGo
2024-10-20 08:56:56 +08:00
roffy3051
77cac2c504 feat: Add params validate 2024-10-20 08:53:07 +08:00
roffy3051
cc1881cc4f Several updates
feat: New website UI
feat: Add few params
feat: Improve performance
2024-10-20 05:11:14 +08:00
Jad
81936a9883
Merge pull request #50 from HChenZi/feat-homePageUrl
feat: Get url from req for index page
2023-04-04 15:03:08 +08:00
journey-ad
8e3a196dc3 perf: Use more precise variable naming and support configuration. 2023-04-04 15:01:50 +08:00
Jad
4fcc0a05db
Merge pull request #49 from HChenZi/master
feat: add docker deploy
2023-04-04 14:43:16 +08:00
HChenZi
5d5045de54 feat: Get url from req for index page 2023-04-04 12:22:37 +08:00
HChenZi
a3eb1409c4 feat: add docker deploy 2023-04-04 10:10:55 +08:00
Jad
6b4d7a010a
Merge pull request #46 from eggplants/fix-typo
Fix typo
2023-03-09 14:41:48 +08:00
eggplants
65097d982d
fix: typo 2023-03-09 15:34:29 +09:00
519 changed files with 2584 additions and 4116 deletions

20
.env.example Normal file
View 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

View 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
View File

@ -16,6 +16,7 @@ count.db
# misc # misc
.DS_Store .DS_Store
.env
.env.local .env.local
.env.development.local .env.development.local
.env.test.local .env.test.local

77
.replit
View File

@ -1,77 +0,0 @@
hidden = [".config", "package-lock.json"]
run = "npm run start"
[[hints]]
regex = "Error \\[ERR_REQUIRE_ESM\\]"
message = "We see that you are using require(...) inside your code. We currently do not support this syntax. Please use 'import' instead when using external modules. (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import)"
[nix]
channel = "stable-22_11"
[env]
XDG_CONFIG_HOME = "/home/runner/.config"
PATH = "/home/runner/$REPL_SLUG/.config/npm/node_global/bin:/home/runner/$REPL_SLUG/node_modules/.bin"
npm_config_prefix = "/home/runner/$REPL_SLUG/.config/npm/node_global"
[gitHubImport]
requiredFiles = [".replit", "replit.nix", ".config", "package.json", "package-lock.json"]
[packager]
language = "nodejs"
[packager.features]
packageSearch = true
guessImports = true
enabledForHosting = false
[unitTest]
language = "nodejs"
[debugger]
support = true
[debugger.interactive]
transport = "localhost:0"
startCommand = [ "dap-node" ]
[debugger.interactive.initializeMessage]
command = "initialize"
type = "request"
[debugger.interactive.initializeMessage.arguments]
clientID = "replit"
clientName = "replit.com"
columnsStartAt1 = true
linesStartAt1 = true
locale = "en-us"
pathFormat = "path"
supportsInvalidatedEvent = true
supportsProgressReporting = true
supportsRunInTerminalRequest = true
supportsVariablePaging = true
supportsVariableType = true
[debugger.interactive.launchMessage]
command = "launch"
type = "request"
[debugger.interactive.launchMessage.arguments]
args = []
console = "externalTerminal"
cwd = "."
environment = []
pauseForSourceMap = false
program = "./index.js"
request = "launch"
sourceMaps = true
stopOnEntry = false
type = "pwa-node"
[languages]
[languages.javascript]
pattern = "**/{*.js,*.jsx,*.ts,*.tsx}"
[languages.javascript.languageServer]
start = "typescript-language-server --stdio"

11
Dockerfile Normal file
View File

@ -0,0 +1,11 @@
FROM node:14
WORKDIR /app
COPY . .
RUN yarn install
EXPOSE 3000
CMD ["yarn", "start"]

307
README.md Normal file
View File

@ -0,0 +1,307 @@
# *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="FeaturedHelloGitHub" 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
#### 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
$ pnpm install
$ pnpm run start
```
### Configuration
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
* [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>

View File

@ -1,81 +0,0 @@
# Moe-Counter
多种风格可选的萌萌计数器
![Moe-Counter](https://count.getloli.com/get/@Moe-counter.github)
<details>
<summary>More theme</summary>
##### asoul
![asoul](https://count.getloli.com/get/@demo?theme=asoul)
##### moebooru
![moebooru](https://count.getloli.com/get/@demo?theme=moebooru)
##### rule34
![Rule34](https://count.getloli.com/get/@demo?theme=rule34)
##### gelbooru
![Gelbooru](https://count.getloli.com/get/@demo?theme=gelbooru)</details>
## Demo
[https://count.getloli.com](https://count.getloli.com)
## Usage
### Install
#### Run on Replit
- Open the url [https://replit.com/@journeyad/Moe-Counter](https://replit.com/@journeyad/Moe-Counter)
- Just hit the **Fork** button
- And hit the **Run** button
#### Deploying on your own server
```shell
$ git clone https://github.com/journey-ad/Moe-Counter.git
$ cd Moe-Counter
$ yarn install
$ yarn start
```
### Confignation
`config.yml`
```yaml
app:
port: 3000
db:
type: sqlite # sqlite or mongodb
```
If you use mongodb, you need to specify the environment variable `DB_URL`
```shell
# eg:
export DB_URL=mongodb+srv://account:passwd@***.***.***.mongodb.net/db_count
```
replit can use Secrets, [documentation](https://docs.replit.com/programming-ide/storing-sensitive-information-environment-variables)
```
DB_URL="mongodb+srv://account:passwd@***.***.***.mongodb.net/db_count"
```
## Credits
* [replit](https://replit.com/)
* [A-SOUL_Official](https://space.bilibili.com/703007996)
* [moebooru](https://github.com/moebooru/moebooru)
* rule34.xxx NSFW
* gelbooru.com NSFW
* [Icons8](https://icons8.com/icons/set/star)
## 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)

BIN
assets/img/back-to-top.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

1
assets/img/failed.svg Normal file
View 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
View 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
View 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());
})();

View File

@ -1,5 +0,0 @@
@media screen and (max-width: 900px) {
iframe {
display: none;
}
}

243
assets/style.less Normal file
View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
assets/theme/3d-num/1.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
assets/theme/3d-num/2.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
assets/theme/3d-num/3.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
assets/theme/3d-num/4.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
assets/theme/3d-num/5.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
assets/theme/3d-num/6.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
assets/theme/3d-num/7.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
assets/theme/3d-num/8.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
assets/theme/3d-num/9.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
assets/theme/ai-1/0.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

BIN
assets/theme/ai-1/1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

BIN
assets/theme/ai-1/2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

BIN
assets/theme/ai-1/3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

BIN
assets/theme/ai-1/4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

BIN
assets/theme/ai-1/5.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

BIN
assets/theme/ai-1/6.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

BIN
assets/theme/ai-1/7.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

BIN
assets/theme/ai-1/8.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

BIN
assets/theme/ai-1/9.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Some files were not shown because too many files have changed in this diff Show More