Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
52a3339981 | ||
|
|
226519ed38 | ||
|
|
208abfe127 | ||
|
|
42a06296b7 | ||
|
|
2ac8bbf36d | ||
|
|
47abbfe35b | ||
|
|
620a3ee324 | ||
|
|
0453e7d2b6 | ||
|
|
c0682db621 | ||
|
|
b85f4a6e53 | ||
|
|
1656460b22 | ||
|
|
50686c8c3d | ||
|
|
b6c9e67fe4 | ||
|
|
cc4be07487 | ||
|
|
af4bcb85fe | ||
|
|
d10c238578 | ||
|
|
f1caf65d0c | ||
|
|
ada8600722 | ||
|
|
befb7a9366 | ||
|
|
d8731ac3ae | ||
|
|
945875e986 | ||
|
|
8299cfdecc | ||
|
|
01d56a6660 | ||
|
|
4eba5607b8 | ||
|
|
e22a04a21f | ||
|
|
e9067761dc | ||
|
|
918dff492f | ||
|
|
b9d3b8aa09 | ||
|
|
548f358813 | ||
|
|
29ac81c6b1 | ||
|
|
053e8d8043 | ||
|
|
ae10743fbd | ||
|
|
aa426e3331 | ||
|
|
7727589ee7 | ||
|
|
88102d56c9 | ||
|
|
fa2a105872 | ||
|
|
dc501074de | ||
|
|
619fd15c8c | ||
|
|
6947f61052 | ||
|
|
263f438e4b | ||
|
|
93bf6f4302 | ||
|
|
534533dc62 | ||
|
|
8bc2864eba | ||
|
|
b269b40a0a | ||
|
|
03f3963836 | ||
|
|
e6ab86d076 | ||
|
|
72bd25217c | ||
|
|
405d528db1 | ||
|
|
e6d26f0116 | ||
|
|
16adb6d032 | ||
|
|
969e962881 | ||
|
|
35e1f1509e | ||
|
|
5f547f7ba6 | ||
|
|
46bb61ac64 | ||
|
|
4e2e032819 | ||
|
|
6a240b46ac | ||
|
|
95922b1fce | ||
|
|
b7c6735975 | ||
|
|
b5d94ac8c0 | ||
|
|
124ee249ed | ||
|
|
dc0d9365c4 | ||
|
|
6c01418f01 | ||
|
|
3464957ce5 | ||
|
|
c4db4c8f0f | ||
|
|
66f16d78f0 | ||
|
|
f64a688df9 | ||
|
|
55b7dc4c9f | ||
|
|
d53b7d2562 | ||
|
|
566fb7099b | ||
|
|
adaa15c080 | ||
|
|
ce4ee6076c | ||
|
|
ed18adc962 | ||
|
|
8e2f36b349 | ||
|
|
add8351e8c | ||
|
|
3d51ebae45 | ||
|
|
e32ac91070 | ||
|
|
61a7bb6393 | ||
|
|
2a7e46c3cb | ||
|
|
ea1bc2e59a | ||
|
|
851234a5be | ||
|
|
30efdd605d | ||
|
|
805be867a5 | ||
|
|
404e44a4cf | ||
|
|
cf83d53ec6 | ||
|
|
89031e589e | ||
|
|
c7fcf8929e | ||
|
|
3f62af5c87 | ||
|
|
1f6707e99c | ||
|
|
b0e064bee7 | ||
|
|
9622a40eb0 | ||
|
|
7dac537a38 | ||
|
|
1092999502 | ||
|
|
2a2cbf7354 | ||
|
|
64c568a99d | ||
|
|
e8fb8e9fd3 | ||
|
|
cd2dd5cd93 | ||
|
|
fbf5309085 | ||
|
|
f51aa39ff8 | ||
|
|
b267d5b400 | ||
|
|
da8b3b9a7b | ||
|
|
1a8f1137b6 | ||
|
|
37e8598f0a | ||
|
|
534e25d049 | ||
|
|
8cdf6b08d0 | ||
|
|
5097d92d27 | ||
|
|
a092c782b4 | ||
|
|
e124d37ea6 | ||
|
|
e1b1867a39 | ||
|
|
981ee36cae | ||
|
|
e838f193ea | ||
|
|
5df9029686 | ||
|
|
504b7bf090 | ||
|
|
b266177ed1 | ||
|
|
78050cfe9f | ||
|
|
2d101708ec | ||
|
|
194012d87f | ||
|
|
19291e1f4f | ||
|
|
4e76e7fa30 | ||
|
|
d20a0c9963 | ||
|
|
f9a2f9bd11 | ||
|
|
4d67bbc76e | ||
|
|
e449dceda5 | ||
|
|
d78042824c | ||
|
|
5a7982fc8f | ||
|
|
ef4b6e319d | ||
|
|
4edf99aca3 | ||
|
|
e5edba7845 | ||
|
|
f070c110a8 | ||
|
|
c91bdd2ab5 | ||
|
|
a0ddaf2f34 | ||
|
|
c1c9a542be | ||
|
|
025b6302f4 | ||
|
|
857dd0ef26 | ||
|
|
7baccc44de | ||
|
|
a3a3212f85 | ||
|
|
4fc018aab9 | ||
|
|
a11013a09d | ||
|
|
2be5c025bf | ||
|
|
be750019d9 | ||
|
|
ecce969d1b | ||
|
|
0854226534 | ||
|
|
c775be1704 | ||
|
|
bfb65e9a11 | ||
|
|
4be49c6041 | ||
|
|
3aca4eca97 | ||
|
|
7bdcec1ea2 | ||
|
|
52c0b9e2e5 | ||
|
|
c4c7be3dec | ||
|
|
9b138cd0c4 | ||
|
|
92045ec23f | ||
|
|
8d368af8b0 | ||
|
|
4af39469e5 | ||
|
|
bc3b7e0d7a | ||
|
|
39c2652fae | ||
|
|
bfc8d76aed |
@@ -1 +1,6 @@
|
||||
.vscode/
|
||||
_site
|
||||
.bundle
|
||||
.sass-cache
|
||||
Gemfile.lock
|
||||
.DS_Store
|
||||
*.pem
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "pwa-chrome",
|
||||
"request": "launch",
|
||||
"name": "Launch Chrome against localhost",
|
||||
"url": "http://localhost:8000/hitomi-dev.html",
|
||||
"webRoot": "${workspaceFolder}"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
source 'https://rubygems.org'
|
||||
|
||||
gem 'github-pages', group: :jekyll_plugins
|
||||
@@ -1,3 +0,0 @@
|
||||
[Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0) except for `zh.json`
|
||||
|
||||
`zh.json`: [CC BY-NC-SA 3.0](https://github.com/EhTagTranslation/Database/blob/master/LICENSE.md) / Based on [EhTagTranslation/Database](https://github.com/EhTagTranslation/Database)
|
||||
@@ -1,48 +1,69 @@
|
||||
# Tag translation
|
||||
# Jekyll Cayman theme
|
||||
|
||||
Tags will be updated every day at 00:00 UTC
|
||||
This is a [Jekyll][1] theme for [@jasonlong][2]'s [Cayman theme][4] on [GitHub Pages][3].
|
||||
|
||||
## License
|
||||
Check [LICENSE](https://github.com/tom5079/Pupil/blob/tags/LICENSE.md)
|
||||
Cayman is a clean, responsive theme for [GitHub Pages](https://pages.github.com). This theme is available as an option if you use the [Automatic Page Generator](https://help.github.com/articles/creating-pages-with-the-automatic-generator/) or you can copy the template and styles to use on your own.
|
||||
|
||||
## Participating in tag translation
|
||||
You can preview the theme at https://jasonlong.github.io/cayman-theme or with real content at https://jasonlong.github.io/geo_pattern.
|
||||
|
||||
[한글 설명서](https://github.com/tom5079/Pupil/blob/tags/docs/README-ko.md)
|
||||

|
||||
|
||||
### Rules
|
||||
* Each translation file should be located in the root folder
|
||||
* Each translation file should be named in following format: [`<ISO 639-1 Code>.json`](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes)
|
||||
* Each translation file should be formatted as JSON file
|
||||
# How to use it?
|
||||
|
||||
### 1. Access Editor
|
||||
Download the theme @ https://github.com/pietromenna/jekyll-cayman-theme/archive/master.zip
|
||||
|
||||
### 1-1. (Optional) Add language file
|
||||
Unzip it and use it as a regular jekyll folder.
|
||||
|
||||
If the target language file doesn't exist, you have to create one.
|
||||
```
|
||||
$ unzip jekyll-cayman-theme-master.zip
|
||||
```
|
||||
|
||||
1) Click `Create New File` Button at the upper right corner
|
||||

|
||||
Get inside the newly extracted folder
|
||||
```
|
||||
$ cd jekyll-cayman-theme-master
|
||||
```
|
||||
|
||||
2) Name the file according to the naming rule
|
||||

|
||||
Get the required gems
|
||||
```
|
||||
$ bundle install
|
||||
```
|
||||
|
||||
3) Copy-paste all the content of [`template.json`](https://raw.githubusercontent.com/tom5079/Pupil/tags/template.json)
|
||||
Use it!
|
||||
|
||||
### 1-2. Edit Existing File
|
||||
```
|
||||
$ jekyll serve
|
||||
```
|
||||
|
||||
Click the file to edit and click Pen icon located at the upper right corner
|
||||

|
||||
For more details read about [Jekyll][1] on its web page.
|
||||
|
||||
### 2. Make Necessary Changes
|
||||
# Setup
|
||||
|
||||
Use text editor shown on screen to make changes
|
||||
Some important configuration can be done in the file `_config.yml`. Please, check the Setup section in that file.
|
||||
|
||||
### 3. Propose Changes
|
||||
|
||||
When you're done with your changes, Scroll down to the bottom of the page and click `Propose Changes`
|
||||
## baseurl
|
||||
|
||||
You don't have to provide any commit messages
|
||||
`baseurl` parameter is required in the case the site doesn't sit on the root of the domain. For example: https://pietromenna.github.io/jekyll-cayman-theme
|
||||
|
||||

|
||||
In the case above the baseurl should be set to "/jekyll-cayman-theme".
|
||||
|
||||
The changes will be applied after review
|
||||
In the case the site sits in the root, you can leave `baseurl` as empty "".
|
||||
|
||||
# Contributing
|
||||
|
||||
Bug reports and pull requests are welcome on GitHub at https://github.com/pietromenna/jekyll-cayman-theme.
|
||||
|
||||
# Development
|
||||
|
||||
To set up your environment to develop this theme, run `bundle install`.
|
||||
|
||||
Your theme is setup just like a normal Jekyll site! To test your theme, run `bundle exec jekyll serve` and open your browser at `http://localhost:4000`. This starts a Jekyll server using your theme. Add pages, documents, data, etc. like normal to test your theme's contents. As you make modifications to your theme and to your content, your site will regenerate and you should see the changes in the browser after a refresh, just like normal.
|
||||
|
||||
# License
|
||||
|
||||
This work is licensed under a [Creative Commons Attribution 4.0 International](https://creativecommons.org/licenses/by/4.0/) license.
|
||||
|
||||
[1]: https://jekyllrb.com/
|
||||
[2]: https://github.com/jasonlong
|
||||
[3]: https://pages.github.com/
|
||||
[4]: https://github.com/jasonlong/cayman-theme
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
theme: jekyll-theme-cayman
|
||||
|
||||
plugins:
|
||||
- jekyll-sitemap
|
||||
|
||||
title: Pupil
|
||||
description: Hitomi.la viewer for Android
|
||||
baseurl: "/Pupil"
|
||||
|
||||
google_analytics: UA-119938781-2
|
||||
|
||||
disqus_url: "https://pupil.disqus.com"
|
||||
discord_url: "https://discord.gg/Stj4b5v"
|
||||
|
||||
github_url: "https://github.com/tom5079/Pupil"
|
||||
|
||||
t:
|
||||
en:
|
||||
header:
|
||||
description: "Hitomi.la viewer for Android"
|
||||
download: "Download app"
|
||||
issue: "Having a problem?"
|
||||
or: "or…"
|
||||
email: "Send an E-mail"
|
||||
discord: "Join Discord server"
|
||||
ko:
|
||||
header:
|
||||
description: "안드로이드 Hitomi.la 뷰어"
|
||||
download: "앱 다운로드"
|
||||
issue: "문제가 있으세요?"
|
||||
or: "또는…"
|
||||
email: "이메일 보내기"
|
||||
discord: "디스코드"
|
||||
@@ -0,0 +1,10 @@
|
||||
---
|
||||
layout: default
|
||||
lang: ko
|
||||
title: 히토미를 여행하는 신사들을 위한 안내서
|
||||
---
|
||||
|
||||

|
||||
*히옷!*
|
||||
|
||||
안녕하십니까, 전국 방방곡곡의 신사 여러분들~!
|
||||
@@ -0,0 +1,95 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="{{ site.lang | default: " en-US " }}">
|
||||
|
||||
<head>
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
|
||||
<script src="https://kit.fontawesome.com/695c47bd28.js" crossorigin="anonymous"></script>
|
||||
|
||||
{% if site.google_analytics %}
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id={{ site.google_analytics }}"></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
|
||||
function gtag() {
|
||||
dataLayer.push(arguments);
|
||||
}
|
||||
gtag('js', new Date());
|
||||
gtag('config', '{{ site.google_analytics }}');
|
||||
</script>
|
||||
{% endif %}
|
||||
<meta charset="UTF-8">
|
||||
|
||||
{% seo %}
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="theme-color" content="#157878">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
|
||||
<link rel="stylesheet" href="{{ '/assets/css/style.css?v=' | append: site.github.build_revision | relative_url }}">
|
||||
<link rel="stylesheet" href="{{ '/assets/css/styles.css' | absolute_url }}">
|
||||
<link rel="shortcut icon" href="/Pupil/favicon.ico" type="image/x-icon" />
|
||||
|
||||
<script>
|
||||
/**
|
||||
* RECOMMENDED CONFIGURATION VARIABLES: EDIT AND UNCOMMENT THE SECTION BELOW TO INSERT DYNAMIC VALUES FROM YOUR PLATFORM OR CMS.
|
||||
* LEARN WHY DEFINING THESE VARIABLES IS IMPORTANT: https://disqus.com/admin/universalcode/#configuration-variables*/
|
||||
|
||||
var disqus_config = function() {
|
||||
this.page.url = '{{ site.url }}{{ page.url }}'; // Replace PAGE_URL with your page's canonical URL variable
|
||||
this.page.identifier = '{{ page.id }}'; // Replace PAGE_IDENTIFIER with your page's unique identifier variable
|
||||
this.page.language = '{{ page.lang }}';
|
||||
};
|
||||
|
||||
(function() { // DON'T EDIT BELOW THIS LINE
|
||||
var d = document,
|
||||
s = d.createElement('script');
|
||||
s.src = 'https://pupil.disqus.com/embed.js';
|
||||
s.setAttribute('data-timestamp', +new Date());
|
||||
(d.head || d.body).appendChild(s);
|
||||
})();
|
||||
</script>
|
||||
|
||||
<script type='text/javascript' src='/Pupil/assets/js/pupil.js'></script>
|
||||
<script>
|
||||
Promise.resolve()
|
||||
.then(getLatestRelease)
|
||||
.then(result => {
|
||||
let url = result["assets"][0]["browser_download_url"];
|
||||
|
||||
$("#download-btn").attr("href", url)
|
||||
})
|
||||
.catch(err => {
|
||||
console.log(err)
|
||||
})
|
||||
</script>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<header class="page-header" role="banner">
|
||||
<a href="https://tom5079.github.io/Pupil" style="text-decoration:none; color:inherit;"><h1 class="project-name">{{ page.title | default: site.title | default: site.github.repository_name }}</h1></a>
|
||||
<h2 class="project-tagline">{{ site.t[page.lang].header.description }}</h2>
|
||||
<a id="download-btn" class="btn">{{ site.t[page.lang].header.download }}</a>
|
||||
<p/>
|
||||
<div class="wrap">
|
||||
<a href="{{ site.github_url }}"><i class="fab fa-github"></i></a>
|
||||
<a href="mailto:pupil.hentai@gmail.com"><i class="fas fa-envelope"></i></a>
|
||||
<a href="{{ site.discord_url }}"><i class="fab fa-discord"></i></a>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main id="content" class="main-content" role="main">
|
||||
{{ content }}
|
||||
|
||||
<footer class="site-footer">
|
||||
|
||||
<div id="disqus_thread"></div>
|
||||
<noscript>Please enable JavaScript to view the <a href="https://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
|
||||
|
||||
{% if site.github.is_project_page %}
|
||||
<span class="site-footer-owner">{{ site.github.repository_name }} is maintained by <a href="{{ site.github.owner_url }}">{{ site.github.owner_name }}</a>.</span> {% endif %}
|
||||
<span class="site-footer-credits">This page was generated by <a href="https://pages.github.com">GitHub Pages</a>.</span>
|
||||
</footer>
|
||||
</main>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,40 @@
|
||||
---
|
||||
layout: default
|
||||
lang: ko
|
||||
title: 접속 불가 현상 해결법
|
||||
description: 히토미 뷰어 Pupil 접속 불가 현상 해결법
|
||||
date: 2020-10-01
|
||||
---
|
||||
|
||||
**현재 Intra/유니콘/Aspear 등으로 접속이 불가능합니다.**
|
||||
|
||||
**1줄요약: [PowerTunnel](https://github.com/krlvm/PowerTunnel-Android) / [1.1.1.1](https://play.google.com/store/apps/details?id=com.cloudflare.onedotonedotonedotone)쓰세요**
|
||||
|
||||

|
||||
*익숙한 `그` 화면*
|
||||
|
||||
현재 일부 통신사에서 https 차단이 시행되고 있는 관계로 우회접속을 해야합니다.
|
||||
|
||||
# 해결 방법
|
||||
|
||||
## 1. PowerTunnel(속도저하 없음, 무료)
|
||||
테스트해본 앱 중 유일하게 작동하는 앱입니다.
|
||||
SNI 파편화로 작동하며, 외부 서버를 경유하지 않아 속도가 가장 빠릅니다.
|
||||
|
||||
[Github](https://github.com/krlvm/PowerTunnel-Android)
|
||||
|
||||
## 2. 1.1.1.1(속도저하 거의 없음, 무료)
|
||||
Cloudflare에서 제공하는 검열 우회 앱입니다.
|
||||
가까운 Cloudflare 서버를 경유하여 일반 VPN보다는 빠른 속도가 특징입니다.
|
||||
|
||||
[플레이스토어 링크](https://play.google.com/store/apps/details?id=com.cloudflare.onedotonedotonedotone)
|
||||
|
||||
## 3. VPN
|
||||
확실한 해결 방법입니다.
|
||||
추천 VPN으로는
|
||||
* Tunnelbear(한 달 1.5GB 무료, 이후 유료)
|
||||
* Betternet(무료)
|
||||
* NordVPN(유료)
|
||||
|
||||
가 있습니다. 속도는 NordVPN>Tunnelbear>Betternet순입니다.
|
||||
개인적으로 Tunnelbear을 추천드립니다.
|
||||
@@ -0,0 +1,179 @@
|
||||
---
|
||||
layout: default
|
||||
lang: ko
|
||||
title: Pupil v4.0 사용 설명서
|
||||
description: 히토미 뷰어 Pupil 사용 설명서
|
||||
---
|
||||
|
||||
일단 읽어 보셔봐
|
||||
|
||||
**취소 버튼이 없는 알림창은 알림창 밖을 누르면 취소됩니다**
|
||||
**만화 내보내기 기본 위치는 `내장메모리/Pupil`폴더 입니다.**
|
||||
**결과 없음/연결 오류/썸네일 안 나오시는 분들은 [접속 불가 해결법](https://tom5079.github.io/Pupil/2019/05/30/https-block-kr.html)을 참조해 주세요!**
|
||||
|
||||
# 1. 메인 화면
|
||||
|
||||

|
||||
|
||||
1. <span style="color:rgb(34,177,76)">사이드 메뉴 열기</span>
|
||||
2. <span style="color:rgb(255,127,39)">검색창</span>
|
||||
3. <span style="color:rgb(0,162,232)">설정</span>
|
||||
4. <span style="color:rgb(255,174,201)">기타</span>
|
||||
- 정렬 설정 (시간순, 인기순)
|
||||
5. <span style="color:rgb(185,122,87)">다운로드 상태</span>
|
||||
- 녹색: 다운로드 완료
|
||||
- 적색: 다운로드 중
|
||||
- 없음: 다운로드 안 됨
|
||||
6. <span style="color:rgb(237,28,36)">태그</span>
|
||||
- 태그를 누르면 해당 태그로 검색됩니다
|
||||
7. <span style="color:rgb(163,73,164)">갤러리 번호</span>
|
||||
- 태그를 누르면 검색됩니다
|
||||
8. <span style="color:rgb(255,242,0)">즐겨찾기</span>
|
||||
9. <span style="color:rgb(181,230,29)">추가 기능</span>
|
||||
- 페이지 이동: 원하는 페이지로 바로 이동
|
||||
- 갤러리 번호로 열기: 갤러리 번호로 뷰어를 엽니다
|
||||
|
||||
## 1-1. 검색
|
||||
|
||||
검색창에 태그/검색어를 입력하면 검색이 됩니다
|
||||
|
||||

|
||||
|
||||
검색어를 덜 입력하면 추천 태그가 나옵니다.
|
||||
물론 즐겨찾기 된 태그가 제일 앞에 표시됩니다.
|
||||
|
||||
우측 별 아이콘을 누르면 즐겨찾기 태그로 등록할 수 있습니다.
|
||||
|
||||

|
||||
즐겨찾기 태그는 검색어를 입력하지 않은 상태에서 나타납니다.
|
||||
|
||||
## 1-2. 페이지 이동
|
||||
페이지 이동은 볼륨 버튼으로도 가능합니다
|
||||
```
|
||||
볼륨 상 -> 이전 페이지
|
||||
볼륨 하 -> 다음 페이지
|
||||
```
|
||||
|
||||
### 1-2.1. 다음 페이지
|
||||

|
||||
페이지 맨 아래에서 한 번 더 끌어주시면 됩니다
|
||||
|
||||
### 1-2.2. 이전 페이지
|
||||

|
||||
페이지 맨 위에서 한 번 더 끌어주시면 됩니다
|
||||
|
||||
## 1-3. 갤러리 상세 보기
|
||||
갤러리의 상세 정보를 볼 수 있습니다
|
||||
|
||||
해당하는 갤러리를 길게 눌러 주세요
|
||||
|
||||

|
||||
|
||||
* 갤러리 종류/작가/그룹/언어/태그를 볼 수 있습니다
|
||||
- 클릭 시 해당 태그로 검색됩니다
|
||||
* 썸네일 표시
|
||||
* 연관 갤러리 표시
|
||||
|
||||
# 2. 뷰어
|
||||
|
||||

|
||||
|
||||
1. <span style="color:rgb(0,0,0)">제목</span>
|
||||
2. <span style="color:rgb(34,177,76)">즐겨찾기</span>
|
||||
3. <span style="color:rgb(238,28,36)">hiyobi.me 사용 표시</span>
|
||||
- hiyobi에서 이미지를 불러올 때 표시됩니다
|
||||
4. <span style="color:rgb(163,73,164)">페이지 표시</span>
|
||||
- 클릭 시 페이지 이동
|
||||
5. <span style="color:rgb(255,127,39)">로딩 상태바</span>
|
||||
- 다운로드 완료 시 사라짐
|
||||
6. <span style="color:rgb(255,201,14)">백그라운드 다운로드 버튼</span>
|
||||
7. <span style="color:rgb(0,162,232)">전체 화면 버튼</span>
|
||||
|
||||
## 2-1. 스크롤 모드
|
||||
|
||||
세로 스크롤 방식과 가로 스크롤 방식을 모두 지원합니다
|
||||
|
||||

|
||||
|
||||
* 세로 스크롤
|
||||
* 기본 방식
|
||||
* 세로 전체화면 스크롤
|
||||
* 전체화면 버튼을 이용
|
||||
* 가로 전체화면 스크롤
|
||||
* 이미지를 한 번 클릭
|
||||
* 뒤로가기 버튼으로 나갈 수 있음
|
||||
|
||||
# 3. 설정
|
||||
|
||||
## 3-1. 검색 설정
|
||||
### 3-1.1. 한 번에 로드할 갤러리 수
|
||||
한 페이지당 갤러리 수를 설정합니다.
|
||||
기본 값은 `25`입니다.
|
||||
|
||||
### 3-1.2. 기본 검색어
|
||||

|
||||
|
||||
메인 화면에서 검색어를 지정하지 않아도 추가되는 검색어입니다.
|
||||
한국어만 보고 싶을 때나 *특정 태그*에 관심이 있을 때 아주 유용합니다.
|
||||
|
||||
## 3-2. 캐시
|
||||
|
||||
### 3-1.1 캐시 삭제
|
||||
캐시 된 갤러리를 삭제합니다.
|
||||
|
||||
### 3-1.2 다운로드 삭제
|
||||
다운로드 된 갤러리를 삭제합니다.
|
||||
다운로드 목록에서도 지워집니다.
|
||||
|
||||
### 3-1.3 기록 삭제
|
||||
히스토리를 삭제합니다. 캐시된 이미지는 지워지지 않습니다.
|
||||
|
||||
## 3-3. 앱 잠금
|
||||
시작 시 잠금을 지원합니다.
|
||||
|
||||
현재 패턴 잠금만 지원합니다.
|
||||
|
||||
패턴을 잊어버렸을 때는 앱을 재설치 해주시기 바랍니다.
|
||||
|
||||
## 3-4. 기타
|
||||
### 3-4.1. hiyobi.me 사용
|
||||
이미지 로딩 속도 향상을 위해 ***가급적이면*** 히요비에서 불러옵니다.
|
||||
요즘 히요비가 계속 죽어서 효과가 없는 것 같기도 하고...
|
||||
|
||||
### 3-4.2. 보안 모드
|
||||
최근 앱 목록 창에서 끄지 못한 히토미를 남이 보는 불상사를 아주 조금 방지합니다.
|
||||
|
||||

|
||||
*보안 모드 ON*
|
||||
|
||||

|
||||
*보안 모드 OFF*
|
||||
|
||||
혹시 모르니까 켜 놓는게 좋습니다. **진짜루요**
|
||||
|
||||
### 3-4.3. 다크 모드
|
||||
앱의 테마를 어두운 색깔로 바꿉니다.
|
||||
밤에 볼때 좋겠지요^^*
|
||||
|
||||

|
||||
*다크 모드 OFF*
|
||||
|
||||

|
||||
*다크 모드 ON*
|
||||
|
||||
## 3-4.4. 이미지 숨기기
|
||||
갤러리에서 다운로드한 이미지를 보이지 않게 합니다.
|
||||
|
||||
이런 곤란한 상황을 막아줍니다
|
||||
|
||||

|
||||
*곤란...*
|
||||
|
||||
# 4. 갤러리 다운로드
|
||||
갤러리를 다운로드 하시면 `내장메모리/Pupil/<갤러리ID>` 폴더에 저장됩니다.
|
||||
이미지는 `images` 폴더에 이미지 번호 순서대로 저장되어 있습니다.
|
||||
|
||||
---
|
||||
|
||||
일단 여기까지입니다.
|
||||
더 궁금하신 게 있으시면 이메일 주세요!
|
||||
@@ -0,0 +1,30 @@
|
||||
---
|
||||
---
|
||||
|
||||
/* for image caption */
|
||||
img + br + em {
|
||||
font-style: normal;
|
||||
display: inherit;
|
||||
text-align: center;
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
.center {
|
||||
display: block;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.wrap {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.wrap > * {
|
||||
margin: 0 1rem;
|
||||
}
|
||||
|
||||
.fab, .fas {
|
||||
font-size: 32px;
|
||||
color: white;
|
||||
}
|
||||
|
After Width: | Height: | Size: 87 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 917 KiB |
|
After Width: | Height: | Size: 357 KiB |
|
After Width: | Height: | Size: 129 KiB |
|
After Width: | Height: | Size: 127 KiB |
|
After Width: | Height: | Size: 332 KiB |
|
After Width: | Height: | Size: 365 KiB |
|
After Width: | Height: | Size: 681 KiB |
|
After Width: | Height: | Size: 3.8 MiB |
|
After Width: | Height: | Size: 526 KiB |
|
After Width: | Height: | Size: 812 KiB |
|
After Width: | Height: | Size: 1.1 MiB |
|
After Width: | Height: | Size: 1.4 MiB |
|
After Width: | Height: | Size: 202 KiB |
|
After Width: | Height: | Size: 218 KiB |
|
After Width: | Height: | Size: 141 KiB |
|
After Width: | Height: | Size: 14 MiB |
|
After Width: | Height: | Size: 583 KiB |
|
After Width: | Height: | Size: 564 KiB |
|
After Width: | Height: | Size: 821 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 132 KiB |
@@ -0,0 +1,170 @@
|
||||
"use strict";
|
||||
|
||||
var loading_timer;
|
||||
var domain = (/^dev\./.test(document.location.hostname.toString()) ? 'dev' : 'ltn')+'.hitomi.la';
|
||||
var galleryblockextension = '.html';
|
||||
var galleryblockdir = 'galleryblock';
|
||||
var nozomiextension = '.nozomi';
|
||||
|
||||
function subdomain_from_url(url, base) {
|
||||
var retval = 'b';
|
||||
if (base) {
|
||||
retval = base;
|
||||
}
|
||||
|
||||
var b = 16;
|
||||
|
||||
var r = /\/[0-9a-f]{61}([0-9a-f]{2})([0-9a-f])/;
|
||||
var m = r.exec(url);
|
||||
if (!m) {
|
||||
return 'a';
|
||||
}
|
||||
|
||||
var g = parseInt(m[2]+m[1], b);
|
||||
if (!isNaN(g)) {
|
||||
retval = String.fromCharCode(97 + gg.m(g)) + retval;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
function url_from_url(url, base) {
|
||||
return url.replace(/\/\/..?\.hitomi\.la\//, '//'+subdomain_from_url(url, base)+'.hitomi.la/');
|
||||
}
|
||||
|
||||
|
||||
function full_path_from_hash(hash) {
|
||||
return gg.b+gg.s(hash)+'/'+hash;
|
||||
}
|
||||
|
||||
function real_full_path_from_hash(hash) {
|
||||
return hash.replace(/^.*(..)(.)$/, '$2/$1/'+hash);
|
||||
}
|
||||
|
||||
|
||||
function url_from_hash(galleryid, image, dir, ext) {
|
||||
ext = ext || dir || image.name.split('.').pop();
|
||||
dir = dir || 'images';
|
||||
|
||||
return 'https://a.hitomi.la/'+dir+'/'+full_path_from_hash(image.hash)+'.'+ext;
|
||||
}
|
||||
|
||||
function url_from_url_from_hash(galleryid, image, dir, ext, base) {
|
||||
if ('tn' === base) {
|
||||
return url_from_url('https://a.hitomi.la/'+dir+'/'+real_full_path_from_hash(image.hash)+'.'+ext, base);
|
||||
}
|
||||
return url_from_url(url_from_hash(galleryid, image, dir, ext), base);
|
||||
}
|
||||
|
||||
function rewrite_tn_paths(html) {
|
||||
return html.replace(/\/\/tn\.hitomi\.la\/[^\/]+\/[0-9a-f]\/[0-9a-f]{2}\/[0-9a-f]{64}/g, function(url) {
|
||||
return url_from_url(url, 'tn');
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function show_loading() {
|
||||
return vate_loading(true);
|
||||
}
|
||||
|
||||
function hide_loading() {
|
||||
stop_loading_timer();
|
||||
return vate_loading(false);
|
||||
}
|
||||
|
||||
function vate_loading(bool) {
|
||||
var el = $('#loader-content');
|
||||
if (!el) return;
|
||||
|
||||
if (bool) {
|
||||
el.show();
|
||||
} else {
|
||||
el.hide();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function start_loading_timer() {
|
||||
hide_loading();
|
||||
loading_timer = setTimeout(show_loading, 500);
|
||||
}
|
||||
|
||||
function stop_loading_timer() {
|
||||
clearTimeout(loading_timer);
|
||||
}
|
||||
|
||||
|
||||
|
||||
function scroll_to_top() {
|
||||
document.body.scrollTop = document.documentElement.scrollTop = 0;
|
||||
}
|
||||
|
||||
|
||||
function localDates() {
|
||||
$(".date").each(function() {
|
||||
//2007-02-06 20:02:00-06
|
||||
//2016-03-27 13:37:33.612-05
|
||||
var r = /(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})(?:\.\d+)?([+-]\d{2})/;
|
||||
var m = r.exec($(this).html());
|
||||
if (!m) {
|
||||
return;
|
||||
}
|
||||
|
||||
//2007-02-06T20:02:00-06:00
|
||||
$(this).html(new Date(m[1]+'-'+m[2]+'-'+m[3]+'T'+m[4]+':'+m[5]+':'+m[6]+m[7]+':00').toLocaleString(undefined, { year: 'numeric', month: 'short', day: 'numeric', hour: 'numeric', minute: 'numeric' })); //Feb 6, 2007, 8:02 PM
|
||||
});
|
||||
}
|
||||
|
||||
//https://stackoverflow.com/a/51332115/272601
|
||||
function retry(fn, retries, err) {
|
||||
retries = typeof retries !== 'undefined' ? retries : 3;
|
||||
err = typeof err !== 'undefined' ? err : null;
|
||||
|
||||
if (!retries) {
|
||||
return Promise.reject(err);
|
||||
}
|
||||
return fn().catch(function(err) {
|
||||
//console.warn(`retry ${3 - retries}, err ${err}`);
|
||||
return retry(fn, (retries - 1), err);
|
||||
});
|
||||
}
|
||||
|
||||
function flip_lazy_images() {
|
||||
const sources = document.querySelectorAll('source.picturelazyload');
|
||||
sources.forEach(function(lazyEl) {
|
||||
lazyEl.setAttribute("srcset", lazyEl.getAttribute("data-srcset"));
|
||||
});
|
||||
|
||||
const imgs = document.querySelectorAll('img.lazyload');
|
||||
imgs.forEach(function(lazyEl) {
|
||||
lazyEl.setAttribute("src", lazyEl.getAttribute("data-src"));
|
||||
//lazyEl.setAttribute("srcset", lazyEl.getAttribute("data-srcset")); //can't do this because the webp shim can't handle it
|
||||
});
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
$("#lang").mouseenter(function() {
|
||||
$("#lang-drop").addClass("active");
|
||||
});
|
||||
$("#lang").mouseleave(function() {
|
||||
$("#lang-drop").removeClass("active");
|
||||
});
|
||||
$("#lang").click(function() {
|
||||
$("#lang-drop").toggleClass("active");
|
||||
});
|
||||
$(".drop-button").click(function() {
|
||||
$("nav").toggleClass("active");
|
||||
});
|
||||
localDates();
|
||||
});
|
||||
|
||||
if (typeof Cookies !== 'undefined' && Cookies && Cookies.get('observe_cls')) {
|
||||
let cls = 0;
|
||||
const po = new PerformanceObserver((list) => {
|
||||
for (const entry of list.getEntries()) {
|
||||
cls += entry.value;
|
||||
console.log(entry, 'total is now: '+cls);
|
||||
}
|
||||
});
|
||||
po.observe({type: 'layout-shift', buffered: true});
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
"use strict";
|
||||
|
||||
var loading_timer;
|
||||
var domain = (/^dev\./.test(document.location.hostname.toString()) ? 'dev' : 'ltn')+'.hitomi.la';
|
||||
var galleryblockextension = '.html';
|
||||
var galleryblockdir = 'galleryblock';
|
||||
var nozomiextension = '.nozomi';
|
||||
|
||||
function subdomain_from_url(url, base) {
|
||||
var retval = 'b';
|
||||
if (base) {
|
||||
retval = base;
|
||||
}
|
||||
|
||||
var b = 16;
|
||||
|
||||
var r = /\/[0-9a-f]{61}([0-9a-f]{2})([0-9a-f])/;
|
||||
var m = r.exec(url);
|
||||
if (!m) {
|
||||
return 'a';
|
||||
}
|
||||
|
||||
var g = parseInt(m[2]+m[1], b);
|
||||
if (!isNaN(g)) {
|
||||
retval = String.fromCharCode(97 + gg.m(g)) + retval;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
function url_from_url(url, base) {
|
||||
return url.replace(/\/\/..?\.hitomi\.la\//, '//'+subdomain_from_url(url, base)+'.hitomi.la/');
|
||||
}
|
||||
|
||||
|
||||
function full_path_from_hash(hash) {
|
||||
return gg.b+gg.s(hash)+'/'+hash;
|
||||
}
|
||||
|
||||
function real_full_path_from_hash(hash) {
|
||||
return hash.replace(/^.*(..)(.)$/, '$2/$1/'+hash);
|
||||
}
|
||||
|
||||
|
||||
function url_from_hash(galleryid, image, dir, ext) {
|
||||
ext = ext || dir || image.name.split('.').pop();
|
||||
dir = dir || 'images';
|
||||
|
||||
return 'https://a.hitomi.la/'+dir+'/'+full_path_from_hash(image.hash)+'.'+ext;
|
||||
}
|
||||
|
||||
function url_from_url_from_hash(galleryid, image, dir, ext, base) {
|
||||
if ('tn' === base) {
|
||||
return url_from_url('https://a.hitomi.la/'+dir+'/'+real_full_path_from_hash(image.hash)+'.'+ext, base);
|
||||
}
|
||||
return url_from_url(url_from_hash(galleryid, image, dir, ext), base);
|
||||
}
|
||||
|
||||
function rewrite_tn_paths(html) {
|
||||
return html.replace(/\/\/tn\.hitomi\.la\/[^\/]+\/[0-9a-f]\/[0-9a-f]{2}\/[0-9a-f]{64}/g, function(url) {
|
||||
return url_from_url(url, 'tn');
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function show_loading() {
|
||||
return vate_loading(true);
|
||||
}
|
||||
|
||||
function hide_loading() {
|
||||
stop_loading_timer();
|
||||
return vate_loading(false);
|
||||
}
|
||||
|
||||
function vate_loading(bool) {
|
||||
var el = $('#loader-content');
|
||||
if (!el) return;
|
||||
|
||||
if (bool) {
|
||||
el.show();
|
||||
} else {
|
||||
el.hide();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function start_loading_timer() {
|
||||
hide_loading();
|
||||
loading_timer = setTimeout(show_loading, 500);
|
||||
}
|
||||
|
||||
function stop_loading_timer() {
|
||||
clearTimeout(loading_timer);
|
||||
}
|
||||
|
||||
|
||||
|
||||
function scroll_to_top() {
|
||||
document.body.scrollTop = document.documentElement.scrollTop = 0;
|
||||
}
|
||||
|
||||
|
||||
function localDates() {
|
||||
$(".date").each(function() {
|
||||
//2007-02-06 20:02:00-06
|
||||
//2016-03-27 13:37:33.612-05
|
||||
var r = /(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})(?:\.\d+)?([+-]\d{2})/;
|
||||
var m = r.exec($(this).html());
|
||||
if (!m) {
|
||||
return;
|
||||
}
|
||||
|
||||
//2007-02-06T20:02:00-06:00
|
||||
$(this).html(new Date(m[1]+'-'+m[2]+'-'+m[3]+'T'+m[4]+':'+m[5]+':'+m[6]+m[7]+':00').toLocaleString(undefined, { year: 'numeric', month: 'short', day: 'numeric', hour: 'numeric', minute: 'numeric' })); //Feb 6, 2007, 8:02 PM
|
||||
});
|
||||
}
|
||||
|
||||
//https://stackoverflow.com/a/51332115/272601
|
||||
function retry(fn, retries, err) {
|
||||
retries = typeof retries !== 'undefined' ? retries : 3;
|
||||
err = typeof err !== 'undefined' ? err : null;
|
||||
|
||||
if (!retries) {
|
||||
return Promise.reject(err);
|
||||
}
|
||||
return fn().catch(function(err) {
|
||||
//console.warn(`retry ${3 - retries}, err ${err}`);
|
||||
return retry(fn, (retries - 1), err);
|
||||
});
|
||||
}
|
||||
|
||||
function flip_lazy_images() {
|
||||
const sources = document.querySelectorAll('source.picturelazyload');
|
||||
sources.forEach(function(lazyEl) {
|
||||
lazyEl.setAttribute("srcset", lazyEl.getAttribute("data-srcset"));
|
||||
});
|
||||
|
||||
const imgs = document.querySelectorAll('img.lazyload');
|
||||
imgs.forEach(function(lazyEl) {
|
||||
lazyEl.setAttribute("src", lazyEl.getAttribute("data-src"));
|
||||
//lazyEl.setAttribute("srcset", lazyEl.getAttribute("data-srcset")); //can't do this because the webp shim can't handle it
|
||||
});
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
$("#lang").mouseenter(function() {
|
||||
$("#lang-drop").addClass("active");
|
||||
});
|
||||
$("#lang").mouseleave(function() {
|
||||
$("#lang-drop").removeClass("active");
|
||||
});
|
||||
$("#lang").click(function() {
|
||||
$("#lang-drop").toggleClass("active");
|
||||
});
|
||||
$(".drop-button").click(function() {
|
||||
$("nav").toggleClass("active");
|
||||
});
|
||||
localDates();
|
||||
});
|
||||
|
||||
if (typeof Cookies !== 'undefined' && Cookies && Cookies.get('observe_cls')) {
|
||||
let cls = 0;
|
||||
const po = new PerformanceObserver((list) => {
|
||||
for (const entry of list.getEntries()) {
|
||||
cls += entry.value;
|
||||
console.log(entry, 'total is now: '+cls);
|
||||
}
|
||||
});
|
||||
po.observe({type: 'layout-shift', buffered: true});
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
async function get_gallery_url(galleryid) {
|
||||
const url = `https://hitomi.la/galleries/${galleryid}.html`;
|
||||
|
||||
const response = await fetch(url);
|
||||
const html = await response.text();
|
||||
|
||||
const doc = new DOMParser().parseFromString(html, 'text/html');
|
||||
|
||||
return doc.querySelector('link').getAttribute('href');
|
||||
}
|
||||
|
||||
async function get_gallery(galleryid) {
|
||||
const url = await get_gallery_url(galleryid);
|
||||
|
||||
const response = await fetch(url);
|
||||
const html = await response.text();
|
||||
|
||||
const doc = new DOMParser().parseFromString(rewrite_tn_paths(html), 'text/html');
|
||||
|
||||
//related
|
||||
eval(Array.from(doc.getElementsByTagName('script')).find(elm => elm.innerHTML.includes('var related')).innerHTML);
|
||||
|
||||
const lang_list = {};
|
||||
|
||||
Array.from(doc.querySelectorAll('#lang-list a')).forEach(elm => lang_list[elm.innerText] = elm.getAttribute('href').slice(11, -5));
|
||||
|
||||
const cover = replace_jpg_tn(doc.querySelector('.cover img').src);
|
||||
|
||||
const title = doc.querySelector('.gallery h1 a').innerText;
|
||||
const artists = Array.from(doc.querySelectorAll('.gallery h2 a'), elm => elm.innerText);
|
||||
const groups = Array.from(doc.querySelectorAll('.gallery-info a[href^="/group."]'), elm => elm.innerText);
|
||||
const type = doc.querySelector('.gallery-info a[href^="/type/"]').innerText.trim();
|
||||
|
||||
const language = doc.querySelector('.gallery-info a[href^="/index"][href$=".html"]').getAttribute('href').slice(7, -5);
|
||||
|
||||
const series = Array.from(doc.querySelectorAll('.gallery-info a[href^="/series/"]'), elm => elm.innerText);
|
||||
const characters = Array.from(doc.querySelectorAll('.gallery-info a[href^="/character/"]'), elm => elm.innerText);
|
||||
|
||||
const tags = Array.from(doc.querySelectorAll('.gallery-info a[href^="/tag/"]'), elm => decodeURIComponent(elm.getAttribute('href')).slice(5, -9));
|
||||
|
||||
const gallery_info = await get_gallery_info(galleryid);
|
||||
const thumbnails = gallery_info.files.map(file => url_from_url_from_hash(galleryid, file, 'webpsmallsmalltn', 'webp', 'tn'));
|
||||
|
||||
return {
|
||||
related: related,
|
||||
langList: lang_list,
|
||||
cover: cover,
|
||||
title: title,
|
||||
artists: artists,
|
||||
groups: groups,
|
||||
type: type,
|
||||
language: language,
|
||||
series: series,
|
||||
characters: characters,
|
||||
tags: tags,
|
||||
thumbnails: thumbnails
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
async function get_gallery_block(galleryid) {
|
||||
const uri = `//${domain}/${galleryblockdir}/${galleryid}${galleryblockextension}`;
|
||||
|
||||
const response = await fetch(uri);
|
||||
const html = await response.text();
|
||||
|
||||
const doc = new DOMParser().parseFromString(rewrite_tn_paths(html), 'text/html');
|
||||
|
||||
const title_elm = doc.querySelector('h1 > a');
|
||||
|
||||
const gallery_url = title_elm.href;
|
||||
const title = title_elm.textContent;
|
||||
|
||||
const thumbnails = Array.from(doc.querySelectorAll('.dj-img-cont img'), elm => replace_jpg_tn(elm.getAttribute('data-src')));
|
||||
|
||||
const artists = Array.from(doc.querySelectorAll('.artist-list a'), elm => elm.innerText);
|
||||
const series = Array.from(doc.querySelectorAll('a[href^="/series/"]'), elm => elm.innerText);
|
||||
const type = doc.querySelector('a[href^="/type/"]').innerText;
|
||||
|
||||
const language = doc.querySelector('a[href^="/index"][href$=".html"]')?.getAttribute('href').slice(7, -5);
|
||||
|
||||
const related_tags = Array.from(doc.querySelectorAll('.relatedtags a'), elm => decodeURIComponent(elm.getAttribute('href')).slice(5, -9));
|
||||
|
||||
return {
|
||||
id: galleryid,
|
||||
galleryUrl: gallery_url,
|
||||
thumbnails: thumbnails,
|
||||
title: title,
|
||||
artists: artists,
|
||||
series: series,
|
||||
type: type,
|
||||
language: language,
|
||||
relatedTags: related_tags
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
function get_gallery_info(galleryID) {
|
||||
return new Promise((resolve, reject) => {
|
||||
$.getScript(`https://ltn.hitomi.la/galleries/${galleryID}.js`, () => {
|
||||
resolve(galleryinfo);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function do_search(query) {
|
||||
let terms = query.toLowerCase().trim().split(/\s+/);
|
||||
let positive_terms = [], negative_terms = [];
|
||||
|
||||
$.each(terms, function (i, term) {
|
||||
term = term.replace(/_/g, ' ');
|
||||
if (term.match(/^-/)) {
|
||||
negative_terms.push(term.replace(/^-/, ''));
|
||||
} else {
|
||||
positive_terms.push(term);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
return new Promise((resolve, reject) => { //first results
|
||||
if (!positive_terms.length) {
|
||||
get_galleryids_from_nozomi(undefined, 'index', 'all').then(results => {
|
||||
resolve(results);
|
||||
});
|
||||
} else {
|
||||
const term = positive_terms.shift();
|
||||
get_galleryids_for_query(term).then(results => {
|
||||
resolve(results);
|
||||
});
|
||||
}
|
||||
}).then(() => { //positive results
|
||||
return Promise.all(positive_terms.map(term => {
|
||||
return new Promise((resolve, reject) => {
|
||||
get_galleryids_for_query(term).then(new_results => {
|
||||
const new_results_set = new Set(new_results);
|
||||
results = results.filter(galleryid => new_results_set.has(galleryid));
|
||||
resolve();
|
||||
})
|
||||
});
|
||||
}));
|
||||
}).then(() => { //negative results
|
||||
return Promise.all(negative_terms.map(term => {
|
||||
return new Promise((resolve, reject) => {
|
||||
get_galleryids_for_query(term).then(new_results => {
|
||||
const new_results_set = new Set(new_results);
|
||||
results = results.filter(galleryid => !new_results_set.has(galleryid));
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}));
|
||||
}).then(() => {
|
||||
const final_results_length = results.length;
|
||||
$('#number-of-results').html(final_results_length);
|
||||
if (!final_results_length) {
|
||||
hide_loading();
|
||||
$('.gallery-content').html($('#no-results-content').html());
|
||||
} else {
|
||||
put_results_on_page();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function replace_jpg_tn(tn) {
|
||||
if (!tn.startsWith('https')) tn = `https:${tn}`;
|
||||
if (tn.endsWith('jpg')) tn = tn.replace('bigtn', 'webpbigtn').replace(/jpg$/, 'webp');
|
||||
|
||||
return tn;
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
async function get_gallery_url(galleryid) {
|
||||
const url = `https://hitomi.la/galleries/${galleryid}.html`;
|
||||
|
||||
const response = await fetch(url);
|
||||
const html = await response.text();
|
||||
|
||||
const doc = new DOMParser().parseFromString(html, 'text/html');
|
||||
|
||||
return doc.querySelector('link').getAttribute('href');
|
||||
}
|
||||
|
||||
async function get_gallery(galleryid) {
|
||||
const url = await get_gallery_url(galleryid);
|
||||
|
||||
const response = await fetch(url);
|
||||
const html = await response.text();
|
||||
|
||||
const doc = new DOMParser().parseFromString(rewrite_tn_paths(html), 'text/html');
|
||||
|
||||
//related
|
||||
eval(Array.from(doc.getElementsByTagName('script')).find(elm => elm.innerHTML.includes('var related')).innerHTML);
|
||||
|
||||
const lang_list = {};
|
||||
|
||||
Array.from(doc.querySelectorAll('#lang-list a')).forEach(elm => lang_list[elm.innerText] = elm.getAttribute('href').slice(11, -5));
|
||||
|
||||
const cover = replace_jpg_tn(doc.querySelector('.cover img').src);
|
||||
|
||||
const title = doc.querySelector('.gallery h1 a').innerText;
|
||||
const artists = Array.from(doc.querySelectorAll('.gallery h2 a'), elm => elm.innerText);
|
||||
const groups = Array.from(doc.querySelectorAll('.gallery-info a[href^="/group."]'), elm => elm.innerText);
|
||||
const type = doc.querySelector('.gallery-info a[href^="/type/"]').innerText.trim();
|
||||
|
||||
const language = doc.querySelector('.gallery-info a[href^="/index"][href$=".html"]').getAttribute('href').slice(7, -5);
|
||||
|
||||
const series = Array.from(doc.querySelectorAll('.gallery-info a[href^="/series/"]'), elm => elm.innerText);
|
||||
const characters = Array.from(doc.querySelectorAll('.gallery-info a[href^="/character/"]'), elm => elm.innerText);
|
||||
|
||||
const tags = Array.from(doc.querySelectorAll('.gallery-info a[href^="/tag/"]'), elm => decodeURIComponent(elm.getAttribute('href')).slice(5, -9));
|
||||
|
||||
const gallery_info = await get_gallery_info(galleryid);
|
||||
const thumbnails = gallery_info.files.map(file => url_from_url_from_hash(galleryid, file, 'webpsmallsmalltn', 'webp', 'tn'));
|
||||
|
||||
return {
|
||||
related: related,
|
||||
langList: lang_list,
|
||||
cover: cover,
|
||||
title: title,
|
||||
artists: artists,
|
||||
groups: groups,
|
||||
type: type,
|
||||
language: language,
|
||||
series: series,
|
||||
characters: characters,
|
||||
tags: tags,
|
||||
thumbnails: thumbnails
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
async function get_gallery_block(galleryid) {
|
||||
const uri = `//${domain}/${galleryblockdir}/${galleryid}${galleryblockextension}`;
|
||||
|
||||
const response = await fetch(uri);
|
||||
const html = await response.text();
|
||||
|
||||
const doc = new DOMParser().parseFromString(rewrite_tn_paths(html), 'text/html');
|
||||
|
||||
const title_elm = doc.querySelector('h1 > a');
|
||||
|
||||
const gallery_url = title_elm.href;
|
||||
const title = title_elm.textContent;
|
||||
|
||||
const thumbnails = Array.from(doc.querySelectorAll('.dj-img-cont img'), elm => replace_jpg_tn(elm.getAttribute('data-src')));
|
||||
|
||||
const artists = Array.from(doc.querySelectorAll('.artist-list a'), elm => elm.innerText);
|
||||
const series = Array.from(doc.querySelectorAll('a[href^="/series/"]'), elm => elm.innerText);
|
||||
const type = doc.querySelector('a[href^="/type/"]').innerText;
|
||||
|
||||
const language = doc.querySelector('a[href^="/index"][href$=".html"]').getAttribute('href').slice(7, -5);
|
||||
|
||||
const related_tags = Array.from(doc.querySelectorAll('.relatedtags a'), elm => decodeURIComponent(elm.getAttribute('href')).slice(5, -9));
|
||||
|
||||
return {
|
||||
id: galleryid,
|
||||
galleryUrl: gallery_url,
|
||||
thumbnails: thumbnails,
|
||||
title: title,
|
||||
artists: artists,
|
||||
series: series,
|
||||
type: type,
|
||||
language: language,
|
||||
relatedTags: related_tags
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
function get_gallery_info(galleryID) {
|
||||
return new Promise((resolve, reject) => {
|
||||
$.getScript(`https://ltn.hitomi.la/galleries/${galleryID}.js`, () => {
|
||||
resolve(galleryinfo);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function do_search(query) {
|
||||
let terms = query.toLowerCase().trim().split(/\s+/);
|
||||
let positive_terms = [], negative_terms = [];
|
||||
|
||||
$.each(terms, function (i, term) {
|
||||
term = term.replace(/_/g, ' ');
|
||||
if (term.match(/^-/)) {
|
||||
negative_terms.push(term.replace(/^-/, ''));
|
||||
} else {
|
||||
positive_terms.push(term);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
return new Promise((resolve, reject) => { //first results
|
||||
if (!positive_terms.length) {
|
||||
get_galleryids_from_nozomi(undefined, 'index', 'all').then(results => {
|
||||
resolve(results);
|
||||
});
|
||||
} else {
|
||||
const term = positive_terms.shift();
|
||||
get_galleryids_for_query(term).then(results => {
|
||||
resolve(results);
|
||||
});
|
||||
}
|
||||
}).then(() => { //positive results
|
||||
return Promise.all(positive_terms.map(term => {
|
||||
return new Promise((resolve, reject) => {
|
||||
get_galleryids_for_query(term).then(new_results => {
|
||||
const new_results_set = new Set(new_results);
|
||||
results = results.filter(galleryid => new_results_set.has(galleryid));
|
||||
resolve();
|
||||
})
|
||||
});
|
||||
}));
|
||||
}).then(() => { //negative results
|
||||
return Promise.all(negative_terms.map(term => {
|
||||
return new Promise((resolve, reject) => {
|
||||
get_galleryids_for_query(term).then(new_results => {
|
||||
const new_results_set = new Set(new_results);
|
||||
results = results.filter(galleryid => !new_results_set.has(galleryid));
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}));
|
||||
}).then(() => {
|
||||
const final_results_length = results.length;
|
||||
$('#number-of-results').html(final_results_length);
|
||||
if (!final_results_length) {
|
||||
hide_loading();
|
||||
$('.gallery-content').html($('#no-results-content').html());
|
||||
} else {
|
||||
put_results_on_page();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function replace_jpg_tn(tn) {
|
||||
if (!tn.startsWith('https')) tn = `https:${tn}`;
|
||||
if (tn.endsWith('jpg')) tn = tn.replace('bigtn', 'webpbigtn').replace(/jpg$/, 'webp');
|
||||
|
||||
return tn;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
'use strict';
|
||||
|
||||
const LATEST_URL = "https://api.github.com/repos/tom5079/Pupil/releases/latest";
|
||||
|
||||
function getLatestRelease() {
|
||||
return new Promise(function(resolve, reject) {
|
||||
const xhr = new XMLHttpRequest();
|
||||
|
||||
xhr.open("GET", LATEST_URL)
|
||||
xhr.onreadystatechange = function() {
|
||||
if (xhr.readyState === 4) {
|
||||
if (xhr.status === 200) {
|
||||
resolve(JSON.parse(xhr.responseText))
|
||||
} else {
|
||||
reject(new Error('XHR failed on getLAtestRelease() with status ' + xhr.status))
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
xhr.send();
|
||||
})
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
# 태그 번역 데이터
|
||||
|
||||
태그 데이터는 매일 00:00 UTC에 업데이트 됩니다
|
||||
|
||||
## 태그 데이터 번역에 참여하기
|
||||
|
||||
### 규칙
|
||||
* 각 번역 파일은 최상단 폴더에 위치하여야 합니다
|
||||
* 각 번역 파일의 이름은 다음 형식을 따라야 합니다: [`<ISO 639-1 Code>.json`](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes)
|
||||
* 각 번역 파일은 JSON 파일 형식을 따라야 합니다
|
||||
|
||||
### 1. 에디터 열기
|
||||
|
||||
번역하려는 파일이 존재하지 않으면, 1-1을 참고하세요
|
||||
번역하려는 파일이 존재한다면, 1-2를 참고하세요
|
||||
|
||||
### 1-1. 번역 파일 추가
|
||||
|
||||
번역하려는 파일이 존재하지 않으면 새 파일을 추가해야 합니다
|
||||
|
||||
1) 우상단 `Create new file` 버튼을 클릭하세요
|
||||

|
||||
|
||||
2) 규칙에 따라 파일 이름을 지정하세요
|
||||

|
||||
|
||||
3) [`template.json`](https://raw.githubusercontent.com/tom5079/Pupil/tags/template.json)의 내용물을 전부 붙여넣으세요
|
||||
|
||||
### 1-2. 존재하는 파일 수정하기
|
||||
|
||||
수정하려는 파일을 열고 우상단 펜 아이콘을 클릭하세요
|
||||

|
||||
|
||||
### 2. 파일 수정하기
|
||||
|
||||
화면에 나타나는 파일 편집기에서 파일을 수정하세요
|
||||
|
||||
### 3. 파일 변경 요청하기
|
||||
|
||||
수정이 완료되었다면, 페이지 아래로 스크롤하여 `Propose changes` 버튼을 누르세요
|
||||
|
||||
별다른 커밋 메세지는 추가하지 않아도 됩니다
|
||||
|
||||

|
||||
|
||||
수정사항은 리뷰 후 적용됩니다
|
||||
|
Before Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 4.2 KiB |
@@ -0,0 +1,14 @@
|
||||
<script src="https://ltn.hitomi.la/jquery.min.js"></script>
|
||||
<script src="https://tom5079.github.io/Pupil/assets/js/dev/gg.js"></script>
|
||||
<script src="https://tom5079.github.io/Pupil/assets/js/dev/common.js"></script>
|
||||
<script src="https://tom5079.github.io/Pupil/assets/js/dev/misc.js"></script>
|
||||
<script src="https://tom5079.github.io/Pupil/assets/js/dev/galleryblock.js"></script>
|
||||
<script src="https://tom5079.github.io/Pupil/assets/js/dev/gallery.js"></script>
|
||||
<script src="https://ltn.hitomi.la/search.js"></script>
|
||||
<script src="https://ltn.hitomi.la/searchlib.js"></script>
|
||||
<script src="https://ltn.hitomi.la/results.js"></script>
|
||||
<script src="https://ltn.hitomi.la/galleryblock.js"></script>
|
||||
<script src="https://ltn.hitomi.la/limitlists.js"></script>
|
||||
<script src="https://ltn.hitomi.la/moveimage.js"></script>
|
||||
<script src="https://ltn.hitomi.la/paging.js"></script>
|
||||
<script src="https://ltn.hitomi.la/language_support.js"></script>
|
||||
@@ -0,0 +1 @@
|
||||
0.0.7-DEV10
|
||||
@@ -0,0 +1,14 @@
|
||||
<script src="https://ltn.hitomi.la/jquery.min.js"></script>
|
||||
<script src="https://tom5079.github.io/Pupil/assets/js/gg.js"></script>
|
||||
<script src="https://tom5079.github.io/Pupil/assets/js/common.js"></script>
|
||||
<script src="https://tom5079.github.io/Pupil/assets/js/misc.js"></script>
|
||||
<script src="https://tom5079.github.io/Pupil/assets/js/galleryblock.js"></script>
|
||||
<script src="https://tom5079.github.io/Pupil/assets/js/gallery.js"></script>
|
||||
<script src="https://ltn.hitomi.la/search.js"></script>
|
||||
<script src="https://ltn.hitomi.la/searchlib.js"></script>
|
||||
<script src="https://ltn.hitomi.la/results.js"></script>
|
||||
<script src="https://ltn.hitomi.la/galleryblock.js"></script>
|
||||
<script src="https://ltn.hitomi.la/limitlists.js"></script>
|
||||
<script src="https://ltn.hitomi.la/moveimage.js"></script>
|
||||
<script src="https://ltn.hitomi.la/paging.js"></script>
|
||||
<script src="https://ltn.hitomi.la/language_support.js"></script>
|
||||
@@ -0,0 +1 @@
|
||||
0.0.6
|
||||
@@ -0,0 +1,27 @@
|
||||
---
|
||||
layout: default
|
||||
lang: ko
|
||||
description: 히토미 뷰어 Pupil
|
||||
---
|
||||
|
||||
<div id="home">
|
||||
<h1>글 목록</h1>
|
||||
{% assign posts=site.posts | where:"lang", page.lang %}
|
||||
<ul class="posts">
|
||||
{% for post in posts %}
|
||||
<li>
|
||||
<span>
|
||||
{{ post.date | date_to_string }}
|
||||
</span>
|
||||
|
||||
»
|
||||
|
||||
<a href="{{ site.baseurl }}{{ post.url }}">
|
||||
{{ post.title }}
|
||||
</a>
|
||||
|
||||
{{ post.excerpt }}
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
@@ -1,2 +0,0 @@
|
||||
requests
|
||||
beautifulsoup4
|
||||
@@ -1,48 +0,0 @@
|
||||
# Returns a list of all tags sorted by the number of tags
|
||||
|
||||
import re
|
||||
import json
|
||||
|
||||
import sys
|
||||
|
||||
import requests
|
||||
from bs4 import BeautifulSoup
|
||||
|
||||
indices = ['123'] + [chr(ord('a')+i) for i in range(26)]
|
||||
tags = dict()
|
||||
|
||||
count_regex = re.compile(r".+\((\d+)\)$")
|
||||
|
||||
for index in indices:
|
||||
url = f'https://hitomi.la/alltags-{index}.html'
|
||||
|
||||
soup = BeautifulSoup(requests.get(url).text, 'html.parser')
|
||||
|
||||
for item in soup.select('.content li'):
|
||||
tag = item.a.text
|
||||
count = int(count_regex.match(item.text).group(1))
|
||||
|
||||
tags[tag] = count
|
||||
|
||||
tag_regex = re.compile(r".+:(.+)$")
|
||||
def clean(tag):
|
||||
match = tag_regex.match(tag)
|
||||
|
||||
if match:
|
||||
return match.group(1)
|
||||
else:
|
||||
return tag
|
||||
|
||||
temp = dict()
|
||||
for k, v in tags.items():
|
||||
tag = clean(k)
|
||||
|
||||
if tag in temp:
|
||||
if v > temp[tag]:
|
||||
temp[tag] = v
|
||||
else:
|
||||
temp[tag] = v
|
||||
|
||||
tags = sorted(temp, key=temp.get, reverse=True)
|
||||
|
||||
print(json.dumps(tags, indent=4))
|
||||
@@ -1,17 +0,0 @@
|
||||
import json
|
||||
import sys
|
||||
|
||||
tags = {tag: u'' for tag in json.loads(''.join(sys.stdin.readlines()))}
|
||||
|
||||
try:
|
||||
with open(sys.argv[1], encoding='utf-8') as f:
|
||||
lang = json.load(f)
|
||||
except:
|
||||
lang = dict()
|
||||
|
||||
for tag in tags:
|
||||
if tag in lang and lang[tag]:
|
||||
tags[tag] = lang[tag]
|
||||
|
||||
with open(sys.argv[1], 'w', encoding='utf-8') as f:
|
||||
json.dump(tags, f, indent=4, ensure_ascii=False)
|
||||
@@ -1,10 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
$TAGS_PYTHON -m pip install -r $TAGS_FOLDER/scripts/requirements.txt > /dev/null 2>&1
|
||||
|
||||
tags=$($TAGS_PYTHON $TAGS_FOLDER/scripts/tags.py)
|
||||
|
||||
for file in $TAGS_FOLDER/*.json
|
||||
do
|
||||
echo "$tags" | $TAGS_PYTHON $TAGS_FOLDER/scripts/update.py $file
|
||||
done
|
||||