Repository: coderzhaoziwei/yande-re-chinese-patch
Branch: main
Commit: 4b5c888921b3
Files: 31
Total size: 141.2 KB
Directory structure:
gitextract_unlq4rb5/
├── .editorconfig
├── .gitignore
├── .vscode/
│ └── custom.code-snippets
├── bundle/
│ ├── index.js
│ └── index.user.js
├── config/
│ └── rollup.config.js
├── package.json
├── readme.md
├── readme_main.md
├── script/
│ ├── action.js
│ ├── bundle.sh
│ └── replace.js
├── source/
│ ├── app.js
│ ├── browse.js
│ ├── data/
│ │ ├── footers.json
│ │ ├── menus.json
│ │ └── tags.json
│ ├── hotkey.js
│ ├── html/
│ │ ├── body.html
│ │ ├── head.html
│ │ └── options.html
│ ├── index.js
│ ├── options.js
│ ├── post.js
│ ├── style/
│ │ └── fix.css
│ ├── style.js
│ └── translate.js
└── temp/
├── css_text_loader.js
├── index.js
├── index.user.js
└── webpack.config.js
================================================
FILE CONTENTS
================================================
================================================
FILE: .editorconfig
================================================
# 编辑器插件 EditorConfig 的配置文件
root = true
[*]
charset = utf-8 # 字符集
indent_style = space # 缩进样式
indent_size = 2 # 缩进尺寸
trim_trailing_whitespace = true # 清理行尾空白
end_of_line = lf # 换行符
insert_final_newline = true # 文末插入空白行
================================================
FILE: .gitignore
================================================
node_modules
yarn-error.log
.DS_Store
================================================
FILE: .vscode/custom.code-snippets
================================================
{
"/* 单行注释 */": {
"scope": "javascript,typescript,css",
"prefix": "ll",
"body": ["/* ${1:comments} */"],
"description": "创建单行注释",
},
"/* 多行注释 */": {
"scope": "javascript,typescript",
"prefix": "lll",
"body": ["/**", " * ${1:comments}", " */"],
"description": "创建多行注释",
},
"console.log()": {
"scope": "javascript,typescript",
"prefix": "con",
"body": ["console.log($1)", ""],
},
"导入模块": {
"scope": "javascript,typescript",
"prefix": "imp",
"body": ["import $1 from '$1'", ""],
},
}
================================================
FILE: bundle/index.js
================================================
// ==UserScript==
// @name Yande.re 简体中文
// @namespace com.coderzhaoziwei.yandere
// @version 2.1.47
// @author Coder Zhao coderzhaoziwei@outlook.com
// @description 中文标签 | 界面优化 | 高清大图 | 键盘翻页 | 流体布局
// @homepage https://greasyfork.org/scripts/421970
// @license MIT
// @match https://yande.re/*
// @exclude https://yande.re/forum/*
// @match https://konachan.com/*
// @exclude https://konachan.com/forum/*
// @match https://konachan.net/*
// @exclude https://konachan.net/forum/*
// @supportURL https://github.com/coderzhaoziwei/yande-re-chinese-patch/issues
// @grant GM_download
// ==/UserScript==
/* eslint-env es2022 */
/* global jQuery:readonly */
/* global Vue:readonly */
/* global Vuetify:readonly */
/* global VueMasonry:readonly */
(function () {
'use strict';
const initStyle = function() {
document.head.insertAdjacentHTML("beforeend", ``);
};
const initHotKey = function() {
window.addEventListener("keyup", function(event) {
console.log('keyup:', event.key);
if (/^(TEXTAREA|INPUT|SELECT|BUTTON)$/.test(document.activeElement.tagName)) return
const prev = document.querySelector(".pagination>.previous_page") || jQuery("li:contains('Previous') a[href]")[0];
if (prev && (event.key == "ArrowLeft" || event.key == "a" || event.key == "A")) {
prev.click();
return event.preventDefault()
}
const next = document.querySelector(".pagination>.next_page") || jQuery("li:contains('Next') a[href]")[0];
if (next && (event.key == "ArrowRight" || event.key === "d" || event.key == "D")) {
next.click();
return event.preventDefault()
}
const show = document.querySelector("#png") || document.querySelector("#highres");
if (show && (event.key === "s" || event.key === "S")) {
show.click();
return event.preventDefault()
}
const where = jQuery("li:contains('Source:') a")[0];
if (where && (event.key === "w" || event.key === "W")) {
where.click();
return event.preventDefault()
}
});
const sidebar = document.querySelector("#post-list > div.sidebar") || document.querySelector("#post-view > div.sidebar");
if (sidebar) {
sidebar.insertAdjacentHTML("beforeend", "
" +
"
快捷键说明
" +
"
上一页:A / ←
" +
"
下一页:D / →
" +
"
显示当前作品原图:S
" +
"
显示当前作品来源:W
" +
"
");
}
};
class Post {
constructor(data) {
if (typeof data !== "object") data = {};
this.id = data.id || 0;
this.score = data.score || 0;
this.tags = data.tags || "";
this.source = data.source || "";
this.author = data.author || "";
this.creatorId = data.creator_id || 0;
this.createdAt = data.created_at || 0;
this.updatedAt = data.updated_at || 0;
this.rating = data.rating || "s";
this.fileUrl = data.file_url || "";
this.fileExt = data.file_ext || "";
this.fileSize = data.file_size || 0;
this.width = data.width || 0;
this.height = data.height || 0;
this.jpegUrl = data.jpeg_url || "";
this.jpegSize = data.jpeg_file_size || 0;
this.jpegWidth = data.jpeg_width || 0;
this.jpegHeight = data.jpeg_height || 0;
this.sampleUrl = data.sample_url;
this.sampleSize = data.sample_file_size || 0;
this.sampleWidth = data.sample_width || 0;
this.sampleHeight = data.sample_height || 0;
this.previewUrl = data.preview_url;
this.previewWidth = data.actual_preview_width || 0;
this.previewHeight = data.actual_preview_height || 0;
this.favorite = false;
}
get isRatingS() {
return this.rating === "s"
}
get isRatingQ() {
return this.rating === "q"
}
get isRatingE() {
return this.rating === "e"
}
get aspectRatio() {
return this.width / this.height
}
getSizeText(size) {
if (size > 1024 * 1024) {
return (size / (1024 * 1024)).toFixed(2) + "MB"
}
if (size > 1024) {
return (size / 1024).toFixed(2) + "KB"
}
return (size).toFixed(2) + "B"
}
get sampleSizeText() {
return this.getSizeText(this.sampleSize)
}
get sampleDownloadText() {
return `下载缩略图 ${this.sampleWidth}×${this.sampleHeight} [${this.sampleSizeText}]`
}
get sampleDownloadName() {
return `${location.hostname}.${this.id}.${this.sampleWidth}x${this.sampleHeight}`.replace(/\./g, "_")
}
get jpegSizeText() {
return this.getSizeText(this.jpegSize)
}
get jpegDownloadText() {
return `下载高清图 ${this.jpegWidth}×${this.jpegHeight} [${this.jpegSizeText}]`
}
get jpegDownloadName() {
return `${location.hostname}.${this.id}.${this.jpegWidth}x${this.jpegHeight}`.replace(/\./g, "_")
}
get fileSizeText() {
return this.getSizeText(this.fileSize)
}
get fileDownloadText() {
return `下载原文件 ${this.width}×${this.height} [${this.fileSizeText}] ${this.fileExt.toUpperCase()}`
}
get fileDownloadName() {
return `${location.hostname}.${this.id}.${this.width}x${this.height}`.replace(/\./g, "_")
}
get createdTime() {
const date = new Date(this.createdAt * 1000);
return `${date.toLocaleDateString()} ${date.toLocaleTimeString("en-DE")}`
}
get updatedTime() {
const date = new Date(this.updatedAt * 1000);
return `${date.toLocaleDateString()} ${date.toLocaleTimeString("en-DE")}`
}
get sourceUrl() {
if (/^https:\/\/i\.pximg\.net\/img-original\/img\/[\d\/]{19}\/([\d]{1,})_p[\d]{1,}\.(jpg|png)$/.test(this.source)) {
const pid = RegExp.$1;
return `https://pixiv.net/artworks/${pid}`
}
return this.source
}
}
const App = {
template: "#app-template",
data() {
return {
showDrawer: false,
showImageSelected: false,
showImageInfo: true,
showRatingQ: JSON.parse(localStorage.getItem("showRatingQ") || "true"),
showRatingE: JSON.parse(localStorage.getItem("showRatingE") || "false"),
imageList: [],
imageSelectedIndex: 0,
imageSelectedDetail: {},
params: new URLSearchParams(location.search),
requestState: false,
requestStop: false,
innerWidth: window.innerWidth,
innerHeight: window.innerHeight,
imageCountInRow: JSON.parse(localStorage.getItem("imageCountInRow") || "3"),
imageQualityHigh: JSON.parse(localStorage.getItem("imageQualityHigh") || "false"),
showFavoriteSuccess: false,
}
},
computed: {
isMobile() {
try {
return this.$vuetify.breakpoint.mobile
} catch(error) {
return false
}
},
title() {
return `${this.imageList.length} Posts`
},
version() {
return GM_info.script.version
},
imageSelected() {
return this.imageList[this.imageSelectedIndex] || new Post()
},
imageSelectedWidth() {
const width = parseInt(Math.min(this.innerWidth * 0.9, this.imageSelected.sampleWidth));
const height = Math.min(this.innerHeight * 0.9, this.imageSelected.sampleHeight);
const width2 = parseInt(height * this.imageSelected.aspectRatio);
return Math.min(width, width2)
},
imageSelectedHeight() {
const width = Math.min(this.innerWidth * 0.9, this.imageSelected.sampleWidth);
const height = parseInt(Math.min(this.innerHeight * 0.9, this.imageSelected.sampleHeight));
const height2 = parseInt(width / this.imageSelected.aspectRatio);
return Math.min(height, height2)
},
},
watch: {
showRatingQ(value) {
localStorage.setItem("showRatingQ", JSON.stringify(value));
},
showRatingE(value) {
localStorage.setItem("showRatingE", JSON.stringify(value));
},
imageCountInRow(value) {
localStorage.setItem("imageCountInRow", JSON.stringify(value));
},
imageQualityHigh(value) {
localStorage.setItem("imageQualityHigh", JSON.stringify(value));
},
showFavoriteSuccess(value) {
console.log('showFavoriteSuccess: ', value);
},
showImageSelected(value) {
if (!value) {
this.imageSelectedDetail = {};
return
}
this.getPostDetail(this.imageSelected.id).then(res => {
if (!res) return
this.imageSelectedDetail = res;
});
}
},
methods: {
async request() {
this.requestState = true;
const url = location.origin + location.pathname + ".json?" + this.params.toString();
const response = await new Promise(resolve => {
console.log(url);
jQuery.get(url, data => resolve(data));
});
if (response instanceof Array && response.length > 0) {
window.history.pushState("", "", location.pathname + "?" + this.params.toString());
response.forEach(item => this.imageList.push(new Post(item)));
const page = Number(this.params.get("page")) || 1;
this.params.set("page", page + 1);
setTimeout(() => (this.requestState = false), 1000);
} else {
this.requestStop = true;
}
},
download(src, filename) {
const match = src.match(/[.](?png|jpg|jpeg)$/);
if (match) {
const extension = match.groups.extension;
GM_download(src, filename + "." + extension);
} else {
GM_download(src, filename);
}
},
onFavorite(id) {
$.ajax({
method: 'POST',
url: "https://yande.re/post/vote.json",
beforeSend: xhr => xhr.setRequestHeader('x-csrf-token', window.csrfToken),
data: { id, score: 3 },
success: data => {
if (data.success === true) {
this.imageList[this.imageSelectedIndex].favorite = true;
this.imageSelectedDetail.favorite = true;
}
},
});
},
async getPostDetail(id) {
try {
if (!id) return
const response = await fetch(`/post.json?api_version=2&tags=id:${id}&include_tags=1&include_votes=1`);
const result = await response.json();
return {
favorite: result.votes[id] == 3,
artist: Object.keys(result.tags).find(k => result.tags[k] == 'artist')
}
} catch (error) {
console.log('getPostDetail error:', error);
}
}
},
mounted() {
const timeInterval = setInterval(() => {
if (this.requestStop === true) {
clearInterval(timeInterval);
return
}
const scrollTop = document.documentElement.scrollTop;
const scrollHeight = document.documentElement.scrollHeight;
const height = window.innerHeight;
if (scrollTop + height >= scrollHeight * 0.75) {
if (this.requestState === false) {
this.request();
}
}
}, 1000);
window.addEventListener("resize", () => {
this.innerWidth = window.innerWidth;
this.innerHeight = window.innerHeight;
});
},
};
async function enterBrowseMode() {
function getScript(url) {
return new Promise(resolve => jQuery.getScript(url, () => resolve()))
}
await getScript("https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.min.js");
await getScript("https://cdn.jsdelivr.net/npm/vuetify@2.5.0/dist/vuetify.min.js");
await getScript("https://cdn.jsdelivr.net/npm/vue-masonry-css@1.0.3/dist/vue-masonry.min.js");
await getScript("https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js");
window.csrfToken = jQuery('[name="csrf-token"]').attr('content');
document.head.innerHTML = `[{ path: "source/html/head.html" }]`;
document.body.innerHTML = `[{ path: "source/html/body.html" }]`;
Vue.use(VueMasonry);
new Vue({
vuetify: new Vuetify({
theme: { dark: true },
}),
render: h => h(App)
}).$mount("#app");
}
const onChangeLeftBar = function() {
const value = Boolean(document.getElementById("showLeftBar").selectedIndex);
localStorage.setItem("showLeftBar", JSON.stringify(value));
const element = document.querySelector("#post-list > .sidebar");
element.setAttribute("show-left-bar", value);
console.log("showLeftBar", value);
};
const onChangeRatingE = function() {
const value = Boolean(document.getElementById("showRatingE").selectedIndex);
localStorage.setItem("showRatingE", JSON.stringify(value));
const elementList = document.querySelectorAll(".javascript-hide");
elementList.forEach(element => element.setAttribute("show-rating-e", value));
console.log("showRatingE", value);
};
const onChangeImageHD = function() {
const index = document.getElementById("showImageHD").selectedIndex;
const elementList = document.querySelectorAll("#post-list-posts > li > .inner");
elementList.forEach(element => element.setAttribute("show-image-hd", index));
localStorage.setItem("showImageHD", JSON.stringify(index));
console.log("showImageHD", index);
};
let taskArray = [];
let maxLoadingSampleNum = 4;
let doLoadSampleUrl = () => {
let loadingNum = 0;
let loadSampleUrl = () => {
if (taskArray.length == 0) return
loadingNum++;
let { element, sampleUrl } = taskArray.shift();
element.onerror = () => {
element.src = sampleUrl;
};
element.onload = () => {
loadingNum--;
};
element.src = sampleUrl;
};
setInterval(() => {
if (taskArray.length == 0) return
let needloadNum = maxLoadingSampleNum - loadingNum;
while (needloadNum--) {
loadSampleUrl();
}
}, 1000);
};
const initOptions = function() {
if (/^\/user\/show\/[\d]{1,}/.test(location.pathname)) return
if (document.getElementById("post-list-posts") === null) return
document.getElementById("post-list-posts").insertAdjacentHTML("beforebegin", `[{ path: "source/html/options.html" }]`);
const imageList = document.querySelectorAll("img.preview");
const samples = JSON.parse(localStorage.getItem("sample_urls"));
imageList.forEach(element => {
if (/\/post\/show\/([\d]{1,})/.test(element.nextElementSibling.innerText)) {
const id = RegExp.$1;
const sampleUrl = samples[id];
if (sampleUrl !== undefined) {
element.src = sampleUrl;
}
}
});
doLoadSampleUrl();
document.getElementById("showLeftBar").addEventListener("change", onChangeLeftBar);
document.getElementById("showRatingE").addEventListener("change", onChangeRatingE);
document.getElementById("showImageHD").addEventListener("change", onChangeImageHD);
const showLeftBar = JSON.parse(localStorage.getItem("showLeftBar") || "true");
const showRatingE = JSON.parse(localStorage.getItem("showRatingE") || "true");
const showImageHD = JSON.parse(localStorage.getItem("showImageHD") || "0");
document.getElementById("showLeftBar").selectedIndex = showLeftBar;
document.getElementById("showRatingE").selectedIndex = showRatingE;
document.getElementById("showImageHD").selectedIndex = showImageHD;
onChangeLeftBar();
onChangeRatingE();
onChangeImageHD();
document.getElementById("enterBrowseMode").addEventListener("click", enterBrowseMode);
};
const tags = [{ path: "source/data/tags.json" }];
const menus = [{ path: "source/data/menus.json" }];
const footers = [{ path: "source/data/footers.json" }];
const translateTags = function() {
const elementList = Array.from(document.getElementsByTagName("a"));
elementList.forEach(element => {
const href = element.getAttribute("href");
if (typeof href === "string" && /^\/post\?tags=(\S+)$/.test(href)) {
const en = RegExp.$1;
const cn = tags[en];
if (cn) {
element.innerText = `[${cn}]${en.replace(/_/g, " ")}`;
}
}
});
};
const translateMenus = function() {
const mainMenuList = Array.from(document.querySelectorAll("#main-menu>ul>li>a"));
const subMenuList = Array.from(document.querySelectorAll("ul.submenu>li>a"));
const elementList = [...mainMenuList, ...subMenuList];
elementList.forEach(element => {
if (element.getAttribute("href") === "#") return
const en = element.innerText;
const cn = menus[en];
if (cn) {
element.innerText = cn;
}
});
};
const translateNotice = function() {
const elementList = Array.from(document.querySelectorAll(".status-notice"));
elementList.forEach(element => {
console.log(element.innerHTML);
element.innerHTML = element.innerHTML
.replace(/^[\s]+This image has been resized. Click on the /, "这张图片已经被压缩,单击侧边栏中的")
.replace(/View larger version/, "显示高清图")
.replace(/ link in the sidebar for a high-quality version./, "可以获取更高质量的版本。")
.replace(/Hide this message<\/a>\./, "不再提醒")
.replace(/This post belongs to a /, "这张图片从属于一个")
.replace(/parent post<\/a>\./, "相关父作品。")
.replace(/This post has /, "这张图片从属于一个")
.replace(/child posts<\/a>\. \(post #/, "作品集。相关子作品:")
.replace(/a child post<\/a>\. \(post #/, "作品集。相关子作品:")
.replace(/<\/a>, | \)/, "");
});
};
const translateButtons = function() {
[
['#highres-show', 'View larger version', '显示高清图'],
['#highres', 'Download larger version', '下载高清图'],
['#png', 'Download PNG', '下载 PNG 图'],
['li#add-to-favs>a', 'Add to favorites', '添加收藏'],
['li#set-avatar>a', 'Set avatar', '设置头像'],
['h4>a.js-posts-show-edit-tab', 'Edit', '编辑'],
['h4>a.js-posts-show-comments-tab', 'Respond', '评论'],
['.pagination>.previous_page', '← Previous', '上一页'],
['.pagination>.next_page', 'Next →', '下一页'],
].forEach(data => {
const [selector, en, cn] = data;
const element = document.querySelector(selector);
if (element) {
element.innerText = element.innerText.replace(en, cn);
}
});
};
const translateFooters = function() {
const elementList = Array.from(document.querySelectorAll('#subnavbar>li>a'));
elementList.forEach(element => {
const en = element.innerText;
const cn = footers[en];
if (cn) {
element.innerText = cn;
}
});
};
const initTranslate = function() {
translateTags();
translateMenus();
translateNotice();
translateButtons();
translateFooters();
};
jQuery(document).ready(function() {
initStyle();
initHotKey();
initOptions();
initTranslate();
if (document.cookie.includes('locale=zh_CN') === false) {
document.cookie = "locale=zh_CN";
location.href = location.href;
}
});
}());
================================================
FILE: bundle/index.user.js
================================================
// ==UserScript==
// @name Yande.re 简体中文
// @namespace com.coderzhaoziwei.yandere
// @version 2.1.47
// @author Coder Zhao coderzhaoziwei@outlook.com
// @description 中文标签 | 界面优化 | 高清大图 | 键盘翻页 | 流体布局
// @homepage https://greasyfork.org/scripts/421970
// @license MIT
// @match https://yande.re/*
// @exclude https://yande.re/forum/*
// @match https://konachan.com/*
// @exclude https://konachan.com/forum/*
// @match https://konachan.net/*
// @exclude https://konachan.net/forum/*
// @supportURL https://github.com/coderzhaoziwei/yande-re-chinese-patch/issues
// @grant GM_download
// ==/UserScript==
/* eslint-env es2022 */
/* global jQuery:readonly */
/* global Vue:readonly */
/* global Vuetify:readonly */
/* global VueMasonry:readonly */
(function () {
'use strict';
const initStyle = function() {
document.head.insertAdjacentHTML("beforeend", ``);
};
const initHotKey = function() {
window.addEventListener("keyup", function(event) {
console.log('keyup:', event.key);
if (/^(TEXTAREA|INPUT|SELECT|BUTTON)$/.test(document.activeElement.tagName)) return
const prev = document.querySelector(".pagination>.previous_page") || jQuery("li:contains('Previous') a[href]")[0];
if (prev && (event.key == "ArrowLeft" || event.key == "a" || event.key == "A")) {
prev.click();
return event.preventDefault()
}
const next = document.querySelector(".pagination>.next_page") || jQuery("li:contains('Next') a[href]")[0];
if (next && (event.key == "ArrowRight" || event.key === "d" || event.key == "D")) {
next.click();
return event.preventDefault()
}
const show = document.querySelector("#png") || document.querySelector("#highres");
if (show && (event.key === "s" || event.key === "S")) {
show.click();
return event.preventDefault()
}
const where = jQuery("li:contains('Source:') a")[0];
if (where && (event.key === "w" || event.key === "W")) {
where.click();
return event.preventDefault()
}
});
const sidebar = document.querySelector("#post-list > div.sidebar") || document.querySelector("#post-view > div.sidebar");
if (sidebar) {
sidebar.insertAdjacentHTML("beforeend", "" +
"
快捷键说明
" +
"
上一页:A / ←
" +
"
下一页:D / →
" +
"
显示当前作品原图:S
" +
"
显示当前作品来源:W
" +
"
");
}
};
class Post {
constructor(data) {
if (typeof data !== "object") data = {};
this.id = data.id || 0;
this.score = data.score || 0;
this.tags = data.tags || "";
this.source = data.source || "";
this.author = data.author || "";
this.creatorId = data.creator_id || 0;
this.createdAt = data.created_at || 0;
this.updatedAt = data.updated_at || 0;
this.rating = data.rating || "s";
this.fileUrl = data.file_url || "";
this.fileExt = data.file_ext || "";
this.fileSize = data.file_size || 0;
this.width = data.width || 0;
this.height = data.height || 0;
this.jpegUrl = data.jpeg_url || "";
this.jpegSize = data.jpeg_file_size || 0;
this.jpegWidth = data.jpeg_width || 0;
this.jpegHeight = data.jpeg_height || 0;
this.sampleUrl = data.sample_url;
this.sampleSize = data.sample_file_size || 0;
this.sampleWidth = data.sample_width || 0;
this.sampleHeight = data.sample_height || 0;
this.previewUrl = data.preview_url;
this.previewWidth = data.actual_preview_width || 0;
this.previewHeight = data.actual_preview_height || 0;
this.favorite = false;
}
get isRatingS() {
return this.rating === "s"
}
get isRatingQ() {
return this.rating === "q"
}
get isRatingE() {
return this.rating === "e"
}
get aspectRatio() {
return this.width / this.height
}
getSizeText(size) {
if (size > 1024 * 1024) {
return (size / (1024 * 1024)).toFixed(2) + "MB"
}
if (size > 1024) {
return (size / 1024).toFixed(2) + "KB"
}
return (size).toFixed(2) + "B"
}
get sampleSizeText() {
return this.getSizeText(this.sampleSize)
}
get sampleDownloadText() {
return `下载缩略图 ${this.sampleWidth}×${this.sampleHeight} [${this.sampleSizeText}]`
}
get sampleDownloadName() {
return `${location.hostname}.${this.id}.${this.sampleWidth}x${this.sampleHeight}`.replace(/\./g, "_")
}
get jpegSizeText() {
return this.getSizeText(this.jpegSize)
}
get jpegDownloadText() {
return `下载高清图 ${this.jpegWidth}×${this.jpegHeight} [${this.jpegSizeText}]`
}
get jpegDownloadName() {
return `${location.hostname}.${this.id}.${this.jpegWidth}x${this.jpegHeight}`.replace(/\./g, "_")
}
get fileSizeText() {
return this.getSizeText(this.fileSize)
}
get fileDownloadText() {
return `下载原文件 ${this.width}×${this.height} [${this.fileSizeText}] ${this.fileExt.toUpperCase()}`
}
get fileDownloadName() {
return `${location.hostname}.${this.id}.${this.width}x${this.height}`.replace(/\./g, "_")
}
get createdTime() {
const date = new Date(this.createdAt * 1000);
return `${date.toLocaleDateString()} ${date.toLocaleTimeString("en-DE")}`
}
get updatedTime() {
const date = new Date(this.updatedAt * 1000);
return `${date.toLocaleDateString()} ${date.toLocaleTimeString("en-DE")}`
}
get sourceUrl() {
if (/^https:\/\/i\.pximg\.net\/img-original\/img\/[\d\/]{19}\/([\d]{1,})_p[\d]{1,}\.(jpg|png)$/.test(this.source)) {
const pid = RegExp.$1;
return `https://pixiv.net/artworks/${pid}`
}
return this.source
}
}
const App = {
template: "#app-template",
data() {
return {
showDrawer: false,
showImageSelected: false,
showImageInfo: true,
showRatingQ: JSON.parse(localStorage.getItem("showRatingQ") || "true"),
showRatingE: JSON.parse(localStorage.getItem("showRatingE") || "false"),
imageList: [],
imageSelectedIndex: 0,
imageSelectedDetail: {},
params: new URLSearchParams(location.search),
requestState: false,
requestStop: false,
innerWidth: window.innerWidth,
innerHeight: window.innerHeight,
imageCountInRow: JSON.parse(localStorage.getItem("imageCountInRow") || "3"),
imageQualityHigh: JSON.parse(localStorage.getItem("imageQualityHigh") || "false"),
showFavoriteSuccess: false,
}
},
computed: {
isMobile() {
try {
return this.$vuetify.breakpoint.mobile
} catch(error) {
return false
}
},
title() {
return `${this.imageList.length} Posts`
},
version() {
return GM_info.script.version
},
imageSelected() {
return this.imageList[this.imageSelectedIndex] || new Post()
},
imageSelectedWidth() {
const width = parseInt(Math.min(this.innerWidth * 0.9, this.imageSelected.sampleWidth));
const height = Math.min(this.innerHeight * 0.9, this.imageSelected.sampleHeight);
const width2 = parseInt(height * this.imageSelected.aspectRatio);
return Math.min(width, width2)
},
imageSelectedHeight() {
const width = Math.min(this.innerWidth * 0.9, this.imageSelected.sampleWidth);
const height = parseInt(Math.min(this.innerHeight * 0.9, this.imageSelected.sampleHeight));
const height2 = parseInt(width / this.imageSelected.aspectRatio);
return Math.min(height, height2)
},
},
watch: {
showRatingQ(value) {
localStorage.setItem("showRatingQ", JSON.stringify(value));
},
showRatingE(value) {
localStorage.setItem("showRatingE", JSON.stringify(value));
},
imageCountInRow(value) {
localStorage.setItem("imageCountInRow", JSON.stringify(value));
},
imageQualityHigh(value) {
localStorage.setItem("imageQualityHigh", JSON.stringify(value));
},
showFavoriteSuccess(value) {
console.log('showFavoriteSuccess: ', value);
},
showImageSelected(value) {
if (!value) {
this.imageSelectedDetail = {};
return
}
this.getPostDetail(this.imageSelected.id).then(res => {
if (!res) return
this.imageSelectedDetail = res;
});
}
},
methods: {
async request() {
this.requestState = true;
const url = location.origin + location.pathname + ".json?" + this.params.toString();
const response = await new Promise(resolve => {
console.log(url);
jQuery.get(url, data => resolve(data));
});
if (response instanceof Array && response.length > 0) {
window.history.pushState("", "", location.pathname + "?" + this.params.toString());
response.forEach(item => this.imageList.push(new Post(item)));
const page = Number(this.params.get("page")) || 1;
this.params.set("page", page + 1);
setTimeout(() => (this.requestState = false), 1000);
} else {
this.requestStop = true;
}
},
download(src, filename) {
const match = src.match(/[.](?png|jpg|jpeg)$/);
if (match) {
const extension = match.groups.extension;
GM_download(src, filename + "." + extension);
} else {
GM_download(src, filename);
}
},
onFavorite(id) {
$.ajax({
method: 'POST',
url: "https://yande.re/post/vote.json",
beforeSend: xhr => xhr.setRequestHeader('x-csrf-token', window.csrfToken),
data: { id, score: 3 },
success: data => {
if (data.success === true) {
this.imageList[this.imageSelectedIndex].favorite = true;
this.imageSelectedDetail.favorite = true;
}
},
});
},
async getPostDetail(id) {
try {
if (!id) return
const response = await fetch(`/post.json?api_version=2&tags=id:${id}&include_tags=1&include_votes=1`);
const result = await response.json();
return {
favorite: result.votes[id] == 3,
artist: Object.keys(result.tags).find(k => result.tags[k] == 'artist')
}
} catch (error) {
console.log('getPostDetail error:', error);
}
}
},
mounted() {
const timeInterval = setInterval(() => {
if (this.requestStop === true) {
clearInterval(timeInterval);
return
}
const scrollTop = document.documentElement.scrollTop;
const scrollHeight = document.documentElement.scrollHeight;
const height = window.innerHeight;
if (scrollTop + height >= scrollHeight * 0.75) {
if (this.requestState === false) {
this.request();
}
}
}, 1000);
window.addEventListener("resize", () => {
this.innerWidth = window.innerWidth;
this.innerHeight = window.innerHeight;
});
},
};
async function enterBrowseMode() {
function getScript(url) {
return new Promise(resolve => jQuery.getScript(url, () => resolve()))
}
await getScript("https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.min.js");
await getScript("https://cdn.jsdelivr.net/npm/vuetify@2.5.0/dist/vuetify.min.js");
await getScript("https://cdn.jsdelivr.net/npm/vue-masonry-css@1.0.3/dist/vue-masonry.min.js");
await getScript("https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js");
window.csrfToken = jQuery('[name="csrf-token"]').attr('content');
document.head.innerHTML = `
Yande.re 简体中文
`;
document.body.innerHTML = `
`;
Vue.use(VueMasonry);
new Vue({
vuetify: new Vuetify({
theme: { dark: true },
}),
render: h => h(App)
}).$mount("#app");
}
const onChangeLeftBar = function() {
const value = Boolean(document.getElementById("showLeftBar").selectedIndex);
localStorage.setItem("showLeftBar", JSON.stringify(value));
const element = document.querySelector("#post-list > .sidebar");
element.setAttribute("show-left-bar", value);
console.log("showLeftBar", value);
};
const onChangeRatingE = function() {
const value = Boolean(document.getElementById("showRatingE").selectedIndex);
localStorage.setItem("showRatingE", JSON.stringify(value));
const elementList = document.querySelectorAll(".javascript-hide");
elementList.forEach(element => element.setAttribute("show-rating-e", value));
console.log("showRatingE", value);
};
const onChangeImageHD = function() {
const index = document.getElementById("showImageHD").selectedIndex;
const elementList = document.querySelectorAll("#post-list-posts > li > .inner");
elementList.forEach(element => element.setAttribute("show-image-hd", index));
localStorage.setItem("showImageHD", JSON.stringify(index));
console.log("showImageHD", index);
};
let taskArray = [];
let maxLoadingSampleNum = 4;
let doLoadSampleUrl = () => {
let loadingNum = 0;
let loadSampleUrl = () => {
if (taskArray.length == 0) return
loadingNum++;
let { element, sampleUrl } = taskArray.shift();
element.onerror = () => {
element.src = sampleUrl;
};
element.onload = () => {
loadingNum--;
};
element.src = sampleUrl;
};
setInterval(() => {
if (taskArray.length == 0) return
let needloadNum = maxLoadingSampleNum - loadingNum;
while (needloadNum--) {
loadSampleUrl();
}
}, 1000);
};
const initOptions = function() {
if (/^\/user\/show\/[\d]{1,}/.test(location.pathname)) return
if (document.getElementById("post-list-posts") === null) return
document.getElementById("post-list-posts").insertAdjacentHTML("beforebegin", `
`);
const imageList = document.querySelectorAll("img.preview");
const samples = JSON.parse(localStorage.getItem("sample_urls"));
imageList.forEach(element => {
if (/\/post\/show\/([\d]{1,})/.test(element.nextElementSibling.innerText)) {
const id = RegExp.$1;
const sampleUrl = samples[id];
if (sampleUrl !== undefined) {
element.src = sampleUrl;
}
}
});
doLoadSampleUrl();
document.getElementById("showLeftBar").addEventListener("change", onChangeLeftBar);
document.getElementById("showRatingE").addEventListener("change", onChangeRatingE);
document.getElementById("showImageHD").addEventListener("change", onChangeImageHD);
const showLeftBar = JSON.parse(localStorage.getItem("showLeftBar") || "true");
const showRatingE = JSON.parse(localStorage.getItem("showRatingE") || "true");
const showImageHD = JSON.parse(localStorage.getItem("showImageHD") || "0");
document.getElementById("showLeftBar").selectedIndex = showLeftBar;
document.getElementById("showRatingE").selectedIndex = showRatingE;
document.getElementById("showImageHD").selectedIndex = showImageHD;
onChangeLeftBar();
onChangeRatingE();
onChangeImageHD();
document.getElementById("enterBrowseMode").addEventListener("click", enterBrowseMode);
};
const tags = {
"4koma": "四格漫画",
"5-toubun_no_hanayome": "五等分的新娘",
"anal": "肛交",
"angel": "天使",
"angel_beats!": "Angel Beats!",
"animal_ears": "兽耳",
"anthropomorphization": "拟人化",
"anus": "肛门露出",
"areola": "乳晕",
"arknights": "明日方舟",
"armor": "盔甲/装甲",
"artist_revision": "画师修改",
"ass": "臀部",
"ass_grab": "持股/捏臀",
"atelier": "炼金工房系列",
"autographed": "亲笔签名",
"azur_lane": "碧蓝航线",
"bakemonogatari": "化物语",
"bandages": "绷带",
"bandaid": "创可贴/绷带",
"bang_dream!": "BanG Dream!",
"baseball": "棒球",
"basketball": "篮球",
"bathing": "沐浴",
"benghuai_xueyuan": "崩坏学园",
"bike_shorts": "自行车短裤",
"bikini": "比基尼",
"bikini_armor": "比基尼装甲/轻薄盔甲",
"bikini_top": "比基尼乳罩",
"black_rock_shooter": "黑岩射手",
"blood": "血腥",
"bloomers": "灯笼裤/宽松短裤",
"blue_archive": "碧蓝档案",
"bodysuit": "紧身衣裤",
"boku_wa_tomodachi_ga_sukunai": "我的朋友很少",
"bondage": "束缚",
"bottomless": "下身露出",
"bra": "乳罩",
"breast_grab": "握乳",
"breast_hold": "托乳",
"breasts": "乳",
"bukkake": "颜射",
"bunny_ears": "兔耳",
"bunny_girl": "兔女郎",
"buruma": "运动短裤",
"business_suit": "西装/职业服",
"calendar": "日历",
"cameltoe": "阴户凸显",
"card": "卡牌",
"card_captor_sakura": "魔卡少女樱",
"censored": "有码",
"cg": "CG/计算机动画",
"chainsaw": "电锯",
"character_design": "角色设计",
"cheerleader": "啦啦队队员",
"chibi": "Q版",
"chinadress": "旗袍",
"choujigen_game_neptune": "超次元游戏海王星",
"christmas": "圣诞",
"cleavage": "乳沟",
"code_geass": "反叛的鲁路修",
"condom": "避孕套",
"corset": "(束腰)紧身内衣",
"cosplay": "角色扮演",
"cream": "奶油",
"cropped": "裁剪图",
"crossdress": "变装",
"crossover": "作品联动/混合同人",
"cum": "精液",
"cunnilingus": "品玉/舔阴",
"dakimakura": "抱枕",
"darling_in_the_franxx": "DARLING in the FRANXX",
"date_a_live": "约会大作战",
"detexted": "去字图片",
"devil": "魔鬼/恶魔",
"digital_version": "数字版",
"dildo": "假阳具",
"disc_cover": "光盘封面",
"dress": "连衣裙",
"dress_shirt": "衬衫",
"duplicate": "重复图片",
"elf": "精灵",
"endcard": "片尾插图",
"erect_nipples": "乳尖",
"expression": "角色展示/立绘",
"extreme_content": "极端",
"eyepatch": "眼罩",
"fairy": "精灵/小精灵",
"fate/kaleid_liner_prisma_illya": "Fate/kaleid liner 魔法少女☆伊莉雅",
"feet": "足",
"fellatio": "口交",
"final_fantasy": "最终幻想",
"final_fantasy_vii": "最终幻想 VII",
"final_fantasy_xiv": "最终幻想 14",
"fingering": "指交",
"fire_emblem": "火焰纹章",
"fire_emblem_heroes": "火焰之纹章:英雄云集",
"fire_emblem_kakusei": "火焰之纹章:觉醒",
"fire_emblem_three_houses": "火焰之纹章:风花雪月",
"fishnets": "鱼网袜",
"fixed": "修改",
"footjob": "足交",
"fundoshi": "褌/兜裆布",
"futanari": "扶她",
"game_cg": "游戏CG",
"gangbang": "乱交",
"garter": "袜带",
"garter_belt": "吊袜腰带",
"genderswap": "性转",
"genshin_impact": "原神",
"girls_frontline": "少女前线",
"girls_und_panzer": "少女与战车",
"gochuumon_wa_usagi_desu_ka?": "请问您今天要来点兔子吗?",
"gothic_lolita": "哥特式洛丽塔",
"granblue_fantasy": "碧蓝幻想",
"guitar": "吉他",
"gun": "枪炮",
"gundam": "高达",
"guro": "猎奇",
"halloween": "万圣节前夜",
"handjob": "打手枪",
"headphones": "耳机",
"heels": "高跟鞋",
"heterochromia": "虹膜异色",
"hibike!_euphonium": "吹响吧!上低音号",
"highschool_dxd": "恶魔高校D×D",
"honkai_impact": "崩坏 3",
"horns": "角",
"index_page": "索引页面",
"infinite_stratos": "IS/无限斯特拉托斯",
"inumimi": "犬耳",
"japanese_clothes": "日式服装",
"k-on!": "轻音少女",
"kaguya-sama_wa_kokurasetai_~tensai-tachi_no_renai_zunousen~": "辉夜大小姐想让我告白~天才们的恋爱头脑战~",
"kantai_collection": "舰队 Collection",
"kemono_friends": "兽娘动物园",
"kimetsu_no_yaiba": "鬼灭之刃",
"kimono": "和服",
"kitsune": "狐狸",
"kobayashi-san_chi_no_maid_dragon": "小林家的龙女仆",
"kono_subarashii_sekai_ni_shukufuku_wo!": "为美好的世界献上祝福!",
"lactation": "泌乳",
"landscape": "风景画",
"league_of_legends": "英雄联盟",
"leotard": "紧身连衣裤",
"line_art": "线条画",
"lingerie": "贴身内衣",
"little_busters!": "Little Busters!",
"loli": "萝莉",
"lolita_fashion": "洛丽塔",
"love_live!_nijigasaki_high_school_idol_club": "Love Live! 虹咲学园学园偶像同好会",
"lucky_star": "幸运星",
"maebari": "前貼り/遮盖私处",
"mahou_shoujo_lyrical_nanoha": "魔法少女奈叶",
"mahou_shoujo_lyrical_nanoha_strikers": "魔法少女奈叶 StrikerS",
"maid": "女仆",
"male": "男性",
"masturbation": "自摸/手淫",
"mecha": "机甲",
"mecha_musume": "机甲娘",
"megane": "眼镜",
"megaten": "女神转生系列",
"mermaid": "美人鱼",
"miko": "巫女",
"monochrome": "单色",
"monster": "怪物",
"monster_girl": "怪物女孩",
"monster_musume_no_iru_nichijou": "魔物娘的相伴日常",
"naked": "裸体",
"naked_apron": "裸体围裙",
"naked_cape": "裸体披风",
"naked_ribbon": "裸体丝带",
"neko": "猫",
"nekomimi": "猫耳",
"neon_genesis_evangelion": "新世纪福音战士",
"nier_automata": "尼尔:自动人形",
"nijisanji": "彩虹社",
"ninja": "忍者",
"nipple_slip": "露点",
"nipples": "乳头",
"no_bra": "无乳罩",
"nopan": "无胖次",
"nun": "修女",
"nurse": "护士",
"official_watermark": "官方水印",
"onsen": "温泉",
"open_shirt": "衬衫敞开",
"ore_no_imouto_ga_konnani_kawaii_wake_ga_nai": "我的妹妹哪有这么可爱!",
"overalls": "工装连衣裤",
"overwatch": "守望先锋",
"paizuri": "乳交",
"pajama": "睡衣",
"panties": "内裤",
"pantsu": "胖次",
"panty_pull": "胖次脱下",
"pantyhose": "吊带袜",
"parody": "仿拟/谐拟",
"partial_scan": "局部扫描",
"pasties": "乳贴",
"pee": "尿尿",
"penguin": "企鹅",
"penis": "阴茎",
"photo": "照片/现实背景",
"photoshop": "PS 改图",
"pirate": "海盗",
"pointy_ears": "尖耳朵",
"pokemon": "精灵宝可梦",
"possible_duplicate": "可能重复",
"pregnant": "孕妇",
"pretty_cure": "光之美少女",
"princess_connect": "公主连结",
"princess_connect!_re:dive": "公主连结 Re:Dive",
"profile_page": "角色资料页",
"pubic_hair": "阴毛",
"puella_magi_madoka_magica": "魔法少女小圆",
"pussy": "阴户",
"pussy_juice": "妹汁",
"queen's_blade": "女王之刃",
"raw_scan": "扫描原图",
"re_zero_kara_hajimeru_isekai_seikatsu": "Re:从零开始的异世界生活",
"robe": "长袍/礼服/睡袍",
"saenai_heroine_no_sodatekata": "路人女主的养成方法",
"sailor_moon": "美少女战士",
"sake": "日本清酒",
"sample": "样品图",
"sarashi": "晒し/缠胸布",
"school_swimsuit": "学校泳衣",
"see_through": "透视",
"seifuku": "制服",
"selfie": "自拍",
"senran_kagura": "闪乱神乐",
"sex": "性交",
"sheets": "床单",
"shimapan": "条纹胖次",
"shirt_lift": "衬衫掀起",
"shota": "正太",
"silhouette": "剪影/暗色轮廓/体形",
"sketch": "素描",
"skirt_lift": "裙摆掀起",
"sling_bikini": "吊带比基尼",
"smoking": "吸烟",
"soccer": "足球",
"sono_bisque_doll_wa_koi_wo_suru": "更衣人偶坠入爱河",
"spy_x_family": "间谍过家家",
"ssss.gridman": "SSSS.古立特",
"stick_poster": "海报",
"stockings": "长筒袜",
"strike_witches": "强袭魔女",
"string_panties": "细绳胖次",
"summer_dress": "夏装",
"suzumiya_haruhi_no_yuuutsu": "凉宫春日的忧郁",
"sweater": "毛衣",
"swimsuits": "泳衣",
"sword": "刀剑",
"sword_art_online": "刀剑神域",
"symmetrical_docking": "乳乳相接",
"tagme": "标签",
"tail": "兽尾",
"tan_lines": "日晒线",
"tattoo": "文身",
"tennis": "网球",
"tentacles": "触手",
"text": "文本",
"the_idolm@ster": "偶像大师",
"the_idolm@ster_cinderella_girls": "偶像大师灰姑娘女孩",
"the_idolm@ster_million_live!": "偶像大师百万现场",
"the_idolm@ster_shiny_colors": "偶像大师闪耀色彩",
"thighhighs": "过膝袜",
"thong": "丁字裤",
"to_aru_kagaku_no_railgun": "某科学的超电磁炮",
"to_aru_majutsu_no_index": "魔法禁书目录",
"to_heart_(series)": "To Heart 系列",
"to_heart_2": "To Heart 2",
"to_love_ru": "出包王女",
"to_love_ru_darkness": "出包王女 Darkness",
"topless": "上身露出",
"torn_clothes": "破衣",
"touhou": "东方",
"towel": "浴巾",
"translated": "文字已翻译(英文)",
"transparent_png": "背景透明",
"trap": "伪娘",
"tribadism": "磨豆腐/交叉体位",
"tutorial": "教程",
"uma_musume_pretty_derby": "赛马娘",
"umbrella": "伞",
"uncensored": "无码",
"underboob": "南半球",
"underwear": "内衣",
"undressing": "脱衣",
"uniform": "制服",
"valentine": "情人节",
"vibrator": "跳蛋",
"wa_maid": "和风女仆",
"waitress": "女侍",
"wallpaper": "壁纸",
"wardrobe_malfunction": "走光",
"weapon": "武器",
"wedding_dress": "婚纱",
"wet": "湿身",
"wet_clothes": "湿衣",
"wings": "翅膀",
"witch": "女巫",
"xenoblade": "异度神剑",
"xenoblade_chronicles_2": "异度神剑 2",
"yahari_ore_no_seishun_lovecome_wa_machigatteiru.": "我的青春恋爱喜剧果然有问题",
"yaoi": "蔷薇/男同",
"yukata": "浴衣",
"yuri": "百合",
"zhanjianshaonv": "战舰少女"
};
const menus =
{
"My Account": "账户",
"Posts": "作品",
"Comments": "评论",
"Notes": "笔记",
"Artists": "画师",
"Tags": "标签",
"Forum": "论坛",
"Help": "帮助",
"More »": "更多>>",
"New Mail": "新消息",
"My Profile": "我的资料",
"My Mail": "我的消息",
"My Favorites": "我的收藏",
"Settings": "设置",
"Change Password": "修改密码",
"Logout": "退出登录",
"View Posts": "浏览作品",
"Search Posts": "搜索作品",
"Upload": "上传",
"Random": "随机浏览",
"Popular": "热门",
"Image Search": "搜索图片",
"History": "历史",
"View Comments": "浏览评论",
"Search Comments": "搜索评论",
"View Notes": "浏览笔记",
"Search Notes": "搜索笔记",
"View Artists": "浏览画师",
"Search Artists": "搜索画师",
"Create": "创建",
"View Tags": "浏览标签",
"Search Tags": "搜索标签",
"Aliases": "别名",
"Implications": "含义",
"View Pools": "浏览 Pools",
"Search Pools": "搜索 Pools",
"Create New Pool": "创建 Pool",
"View Wiki Index": "浏览 Wiki 主页",
"Search Wiki": "搜索 Wiki",
"Create New Page": "创建新页面",
"Mark All Read": "全部标记已读"
}
;
const footers =
{
"List": "首页",
"Browse": "翻阅",
"Upload": "上传",
"Random": "随机",
"Popular": "热门",
"Image Search": "寻图",
"History": "历史",
"Help": "帮助"
}
;
const translateTags = function() {
const elementList = Array.from(document.getElementsByTagName("a"));
elementList.forEach(element => {
const href = element.getAttribute("href");
if (typeof href === "string" && /^\/post\?tags=(\S+)$/.test(href)) {
const en = RegExp.$1;
const cn = tags[en];
if (cn) {
element.innerText = `[${cn}]${en.replace(/_/g, " ")}`;
}
}
});
};
const translateMenus = function() {
const mainMenuList = Array.from(document.querySelectorAll("#main-menu>ul>li>a"));
const subMenuList = Array.from(document.querySelectorAll("ul.submenu>li>a"));
const elementList = [...mainMenuList, ...subMenuList];
elementList.forEach(element => {
if (element.getAttribute("href") === "#") return
const en = element.innerText;
const cn = menus[en];
if (cn) {
element.innerText = cn;
}
});
};
const translateNotice = function() {
const elementList = Array.from(document.querySelectorAll(".status-notice"));
elementList.forEach(element => {
console.log(element.innerHTML);
element.innerHTML = element.innerHTML
.replace(/^[\s]+This image has been resized. Click on the /, "这张图片已经被压缩,单击侧边栏中的")
.replace(/View larger version/, "显示高清图")
.replace(/ link in the sidebar for a high-quality version./, "可以获取更高质量的版本。")
.replace(/Hide this message<\/a>\./, "不再提醒")
.replace(/This post belongs to a /, "这张图片从属于一个")
.replace(/parent post<\/a>\./, "相关父作品。")
.replace(/This post has /, "这张图片从属于一个")
.replace(/child posts<\/a>\. \(post #/, "作品集。相关子作品:")
.replace(/a child post<\/a>\. \(post #/, "作品集。相关子作品:")
.replace(/<\/a>, | \)/, "");
});
};
const translateButtons = function() {
[
['#highres-show', 'View larger version', '显示高清图'],
['#highres', 'Download larger version', '下载高清图'],
['#png', 'Download PNG', '下载 PNG 图'],
['li#add-to-favs>a', 'Add to favorites', '添加收藏'],
['li#set-avatar>a', 'Set avatar', '设置头像'],
['h4>a.js-posts-show-edit-tab', 'Edit', '编辑'],
['h4>a.js-posts-show-comments-tab', 'Respond', '评论'],
['.pagination>.previous_page', '← Previous', '上一页'],
['.pagination>.next_page', 'Next →', '下一页'],
].forEach(data => {
const [selector, en, cn] = data;
const element = document.querySelector(selector);
if (element) {
element.innerText = element.innerText.replace(en, cn);
}
});
};
const translateFooters = function() {
const elementList = Array.from(document.querySelectorAll('#subnavbar>li>a'));
elementList.forEach(element => {
const en = element.innerText;
const cn = footers[en];
if (cn) {
element.innerText = cn;
}
});
};
const initTranslate = function() {
translateTags();
translateMenus();
translateNotice();
translateButtons();
translateFooters();
};
jQuery(document).ready(function() {
initStyle();
initHotKey();
initOptions();
initTranslate();
if (document.cookie.includes('locale=zh_CN') === false) {
document.cookie = "locale=zh_CN";
location.href = location.href;
}
});
}());
================================================
FILE: config/rollup.config.js
================================================
import { version } from "../package.json"
import cleanup from "rollup-plugin-cleanup"
import json from "@rollup/plugin-json"
const banner = `// ==UserScript==
// @name Yande.re 简体中文
// @namespace com.coderzhaoziwei.yandere
// @version ${ version }
// @author Coder Zhao coderzhaoziwei@outlook.com
// @description 中文标签 | 界面优化 | 高清大图 | 键盘翻页 | 流体布局
// @homepage https://greasyfork.org/scripts/421970
// @license MIT
// @match https://yande.re/*
// @exclude https://yande.re/forum/*
// @match https://konachan.com/*
// @exclude https://konachan.com/forum/*
// @match https://konachan.net/*
// @exclude https://konachan.net/forum/*
// @supportURL https://github.com/coderzhaoziwei/yande-re-chinese-patch/issues
// @grant GM_download
// ==/UserScript==
/* eslint-env es2022 */
/* global jQuery:readonly */
/* global Vue:readonly */
/* global Vuetify:readonly */
/* global VueMasonry:readonly */
`
export default {
input: "source/index.js",
output: {
file: "bundle/index.js",
format: "iife",
banner,
},
plugins: [ cleanup(), json() ],
}
================================================
FILE: package.json
================================================
{
"name": "yande-re-chinese-patch",
"version": "2.1.47",
"author": "Coder Zhao",
"description": "Yande.re Chinese Patch | Y 站简体中文补丁",
"repository": "https://github.com/coderzhaoziwei/yande.re-chinese-patch.git",
"license": "MIT",
"scripts": {
"bundle": "sh script/bundle.sh"
},
"devDependencies": {
"@rollup/plugin-json": "^4.1.0",
"rollup": "^2.47.0",
"rollup-plugin-cleanup": "^3.2.1"
}
}
================================================
FILE: readme.md
================================================
![version][img-version]
![license][img-license]
![stars][img-stars]
![cover][img-cover]
# 目录
- [前言](#前言)
- [预览](#预览)
- [功能](#功能)
- [标签翻译](#标签翻译)
- [操作优化](#操作优化)
- [浏览模式](#浏览模式)
- [安装](#安装)
- [安装浏览器插件](#安装浏览器插件)
- [安装脚本程序](#安装脚本程序)
- [常见问题](#常见问题)
- [Q: 安卓手机如何安装 Tampermonkey?](#q-安卓手机如何安装-tampermonkey)
- [相关链接](#相关链接)
- [开源许可](#开源许可)
- [附:标签翻译表](#附标签翻译表)
# 前言
最初,我在浏览 [yande.re 站](https://yande.re)(以下简称 Y 站)的时候,遇到了一些难懂的标签名。在使用搜索引擎多方查询之后,我才终于明白个别晦涩单词的含义,可是过了一段时间再次遇到,又忘记了。然后我就敲了一个脚本程序,自动遍历页面中的标签名,添加中文翻译。为了让与我有同样困扰的其他朋友节约时间,我将脚本程序发布到了脚本网站 [Greasy Fork](https://greasyfork.org/) 上。
后来,有朋友提议添加更优化的操作方式,于是陆续增加了显示大图、键盘翻页等功能。再后来有一天,我躺在床上用手机登陆了 Y 站,网站无法适配移动端屏幕实在是太特么难受了,于是我就敲了响应式布局的浏览模式,手机可以自动加载图片资源,单屏一滑到底。
终于,舒服了。
- https://yande.re
- ~~https://oreno.imouto.us (Y 站镜像,无需魔法上网)~~(已失效)
- https://konachan.com (K 站已兼容)
- https://konachan.net (K 站安全模式,.net 域名下默认隐藏成人内容)
# 预览
- 样式优化,高清图源,尺寸自选。

- 流体布局,自动加载,一屏到底。

- 单图预览,聚合详情,一键下载。

- 显隐自如,更多功能,欢迎体验。

# 功能
## 标签翻译
翻译了 Y 站出现频率较高的 100 多个标签,详细内容请查看最下方的标签翻译表。欢迎校正或补充。
## 操作优化
- 对于 Y 站默认隐藏的成人内容,提供了显示或者隐藏的选项。
- 网页左侧的边栏,提供了显示或者隐藏的选项。
- 图源默认自动替换为高清资源,并提供了 1 ~ 4 倍尺寸的选项。
- 快捷键
- 上一页:A / ←
- 下一页:D / →
- 显示当前作品原图:S
- 显示当前作品来源:W
## 浏览模式
浏览任意图片列表时,可以进入浏览模式。
# 安装
## 安装浏览器插件
首先你需要为你的浏览器安装一个用户脚本管理器,推荐使用插件 [Tampermonkey](https://www.tampermonkey.net/)。
> 主流浏览器有 Chrome、Microsoft Edge、Firefox、Safari 等,如果你的浏览器无法安装 Tampermonkey,那么也就无法安装此脚本程序。
## 安装脚本程序
使用浏览器直接访问 [Greasy Fork - Yande.re 简体中文 - 主页](https://greasyfork.org/scripts/421970),点击安装即可。
如果你没有 Greasy Fork 的账号,访问以上链接可能会提示你:`此脚本不再在本网站上匿名可用。请登录并检查您的 Greasy Fork 账号设置。`
因为此脚本程序涉及成人内容,所以在 Greasy Fork 站点必须登录才可以浏览或安装。如果你不想注册成为 Greasy Fork 的用户,可以访问成人脚本站点 [Sleasy Fork](https://sleazyfork.org/scripts/421970) 直接安装,或者直接获取[仓库文件](https://github.com/coderzhaoziwei/yande-re-chinese-patch/raw/main/index.user.js)来安装。
# 常见问题
## Q: 安卓手机如何安装 Tampermonkey?
我推荐安卓 Yandex 浏览器,可以直接安装 Chrome 插件。当你发现谷歌市场的 Tampermonkey 显示不兼容时,点击 Yandex 菜单栏,切换为桌面模式即可。
其他安卓浏览器也可以的,Firefox、Kiwi、Iceraven 等自行尝试。
# 相关链接
[Github 仓库](https://github.com/coderzhaoziwei/yande-re-chinese-patch) |
[Greasy Fork 脚本主页](https://greasyfork.org/scripts/421970) |
[封面原图 Yande#388833](https://yande.re/post/show/388833)
# 开源许可
MIT
# 附:标签翻译表
||English|简体中文|
|:-:|:-|:-|
|1|4koma|四格漫画|
|2|5-toubun no hanayome|五等分的新娘|
|3|anal|肛交|
|4|angel|天使|
|5|angel beats!|Angel Beats!|
|6|animal ears|兽耳|
|7|anthropomorphization|拟人化|
|8|anus|肛门露出|
|9|areola|乳晕|
|10|arknights|明日方舟|
|11|armor|盔甲/装甲|
|12|artist revision|画师修改|
|13|ass|臀部|
|14|ass grab|持股/捏臀|
|15|atelier|炼金工房系列|
|16|autographed|亲笔签名|
|17|azur lane|碧蓝航线|
|18|bakemonogatari|化物语|
|19|bandages|绷带|
|20|bandaid|创可贴/绷带|
|21|bang dream!|BanG Dream!|
|22|baseball|棒球|
|23|basketball|篮球|
|24|bathing|沐浴|
|25|benghuai xueyuan|崩坏学园|
|26|bike shorts|自行车短裤|
|27|bikini|比基尼|
|28|bikini armor|比基尼装甲/轻薄盔甲|
|29|bikini top|比基尼乳罩|
|30|black rock shooter|黑岩射手|
|31|blood|血腥|
|32|bloomers|灯笼裤/宽松短裤|
|33|blue archive|碧蓝档案|
|34|bodysuit|紧身衣裤|
|35|boku wa tomodachi ga sukunai|我的朋友很少|
|36|bondage|束缚|
|37|bottomless|下身露出|
|38|bra|乳罩|
|39|breast grab|握乳|
|40|breast hold|托乳|
|41|breasts|乳|
|42|bukkake|颜射|
|43|bunny ears|兔耳|
|44|bunny girl|兔女郎|
|45|buruma|运动短裤|
|46|business suit|西装/职业服|
|47|calendar|日历|
|48|cameltoe|阴户凸显|
|49|card|卡牌|
|50|card captor sakura|魔卡少女樱|
|51|censored|有码|
|52|cg|CG/计算机动画|
|53|chainsaw|电锯|
|54|character design|角色设计|
|55|cheerleader|啦啦队队员|
|56|chibi|Q版|
|57|chinadress|旗袍|
|58|choujigen game neptune|超次元游戏海王星|
|59|christmas|圣诞|
|60|cleavage|乳沟|
|61|code geass|反叛的鲁路修|
|62|condom|避孕套|
|63|corset|(束腰)紧身内衣|
|64|cosplay|角色扮演|
|65|cream|奶油|
|66|cropped|裁剪图|
|67|crossdress|变装|
|68|crossover|作品联动/混合同人|
|69|cum|精液|
|70|cunnilingus|品玉/舔阴|
|71|dakimakura|抱枕|
|72|darling in the franxx|DARLING in the FRANXX|
|73|date a live|约会大作战|
|74|detexted|去字图片|
|75|devil|魔鬼/恶魔|
|76|digital version|数字版|
|77|dildo|假阳具|
|78|disc cover|光盘封面|
|79|dress|连衣裙|
|80|dress shirt|衬衫|
|81|duplicate|重复图片|
|82|elf|精灵|
|83|endcard|片尾插图|
|84|erect nipples|乳尖|
|85|expression|角色展示/立绘|
|86|extreme content|极端|
|87|eyepatch|眼罩|
|88|fairy|精灵/小精灵|
|89|fate/kaleid liner prisma illya|Fate/kaleid liner 魔法少女☆伊莉雅|
|90|feet|足|
|91|fellatio|口交|
|92|final fantasy|最终幻想|
|93|final fantasy vii|最终幻想 VII|
|94|final fantasy xiv|最终幻想 14|
|95|fingering|指交|
|96|fire emblem|火焰纹章|
|97|fire emblem heroes|火焰之纹章:英雄云集|
|98|fire emblem kakusei|火焰之纹章:觉醒|
|99|fire emblem three houses|火焰之纹章:风花雪月|
|100|fishnets|鱼网袜|
|101|fixed|修改|
|102|footjob|足交|
|103|fundoshi|褌/兜裆布|
|104|futanari|扶她|
|105|game cg|游戏CG|
|106|gangbang|乱交|
|107|garter|袜带|
|108|garter belt|吊袜腰带|
|109|genderswap|性转|
|110|genshin impact|原神|
|111|girls frontline|少女前线|
|112|girls und panzer|少女与战车|
|113|gochuumon wa usagi desu ka?|请问您今天要来点兔子吗?|
|114|gothic lolita|哥特式洛丽塔|
|115|granblue fantasy|碧蓝幻想|
|116|guitar|吉他|
|117|gun|枪炮|
|118|gundam|高达|
|119|guro|猎奇|
|120|halloween|万圣节前夜|
|121|handjob|打手枪|
|122|headphones|耳机|
|123|heels|高跟鞋|
|124|heterochromia|虹膜异色|
|125|hibike! euphonium|吹响吧!上低音号|
|126|highschool dxd|恶魔高校D×D|
|127|honkai impact|崩坏 3|
|128|horns|角|
|129|index page|索引页面|
|130|infinite stratos|IS/无限斯特拉托斯|
|131|inumimi|犬耳|
|132|japanese clothes|日式服装|
|133|k-on!|轻音少女|
|134|kaguya-sama wa kokurasetai ~tensai-tachi no renai zunousen~|辉夜大小姐想让我告白~天才们的恋爱头脑战~|
|135|kantai collection|舰队 Collection|
|136|kemono friends|兽娘动物园|
|137|kimetsu no yaiba|鬼灭之刃|
|138|kimono|和服|
|139|kitsune|狐狸|
|140|kobayashi-san chi no maid dragon|小林家的龙女仆|
|141|kono subarashii sekai ni shukufuku wo!|为美好的世界献上祝福!|
|142|lactation|泌乳|
|143|landscape|风景画|
|144|league of legends|英雄联盟|
|145|leotard|紧身连衣裤|
|146|line art|线条画|
|147|lingerie|贴身内衣|
|148|little busters!|Little Busters!|
|149|loli|萝莉|
|150|lolita fashion|洛丽塔|
|151|love live! nijigasaki high school idol club|Love Live! 虹咲学园学园偶像同好会|
|152|lucky star|幸运星|
|153|maebari|前貼り/遮盖私处|
|154|mahou shoujo lyrical nanoha|魔法少女奈叶|
|155|mahou shoujo lyrical nanoha strikers|魔法少女奈叶 StrikerS|
|156|maid|女仆|
|157|male|男性|
|158|masturbation|自摸/手淫|
|159|mecha|机甲|
|160|mecha musume|机甲娘|
|161|megane|眼镜|
|162|megaten|女神转生系列|
|163|mermaid|美人鱼|
|164|miko|巫女|
|165|monochrome|单色|
|166|monster|怪物|
|167|monster girl|怪物女孩|
|168|monster musume no iru nichijou|魔物娘的相伴日常|
|169|naked|裸体|
|170|naked apron|裸体围裙|
|171|naked cape|裸体披风|
|172|naked ribbon|裸体丝带|
|173|neko|猫|
|174|nekomimi|猫耳|
|175|neon genesis evangelion|新世纪福音战士|
|176|nier automata|尼尔:自动人形|
|177|nijisanji|彩虹社|
|178|ninja|忍者|
|179|nipple slip|露点|
|180|nipples|乳头|
|181|no bra|无乳罩|
|182|nopan|无胖次|
|183|nun|修女|
|184|nurse|护士|
|185|official watermark|官方水印|
|186|onsen|温泉|
|187|open shirt|衬衫敞开|
|188|ore no imouto ga konnani kawaii wake ga nai|我的妹妹哪有这么可爱!|
|189|overalls|工装连衣裤|
|190|overwatch|守望先锋|
|191|paizuri|乳交|
|192|pajama|睡衣|
|193|panties|内裤|
|194|pantsu|胖次|
|195|panty pull|胖次脱下|
|196|pantyhose|吊带袜|
|197|parody|仿拟/谐拟|
|198|partial scan|局部扫描|
|199|pasties|乳贴|
|200|pee|尿尿|
|201|penguin|企鹅|
|202|penis|阴茎|
|203|photo|照片/现实背景|
|204|photoshop|PS 改图|
|205|pirate|海盗|
|206|pointy ears|尖耳朵|
|207|pokemon|精灵宝可梦|
|208|possible duplicate|可能重复|
|209|pregnant|孕妇|
|210|pretty cure|光之美少女|
|211|princess connect|公主连结|
|212|princess connect! re:dive|公主连结 Re:Dive|
|213|profile page|角色资料页|
|214|pubic hair|阴毛|
|215|puella magi madoka magica|魔法少女小圆|
|216|pussy|阴户|
|217|pussy juice|妹汁|
|218|queen's blade|女王之刃|
|219|raw scan|扫描原图|
|220|re zero kara hajimeru isekai seikatsu|Re:从零开始的异世界生活|
|221|robe|长袍/礼服/睡袍|
|222|saenai heroine no sodatekata|路人女主的养成方法|
|223|sailor moon|美少女战士|
|224|sake|日本清酒|
|225|sample|样品图|
|226|sarashi|晒し/缠胸布|
|227|school swimsuit|学校泳衣|
|228|see through|透视|
|229|seifuku|制服|
|230|selfie|自拍|
|231|senran kagura|闪乱神乐|
|232|sex|性交|
|233|sheets|床单|
|234|shimapan|条纹胖次|
|235|shirt lift|衬衫掀起|
|236|shota|正太|
|237|silhouette|剪影/暗色轮廓/体形|
|238|sketch|素描|
|239|skirt lift|裙摆掀起|
|240|sling bikini|吊带比基尼|
|241|smoking|吸烟|
|242|soccer|足球|
|243|sono bisque doll wa koi wo suru|更衣人偶坠入爱河|
|244|spy x family|间谍过家家|
|245|ssss.gridman|SSSS.古立特|
|246|stick poster|海报|
|247|stockings|长筒袜|
|248|strike witches|强袭魔女|
|249|string panties|细绳胖次|
|250|summer dress|夏装|
|251|suzumiya haruhi no yuuutsu|凉宫春日的忧郁|
|252|sweater|毛衣|
|253|swimsuits|泳衣|
|254|sword|刀剑|
|255|sword art online|刀剑神域|
|256|symmetrical docking|乳乳相接|
|257|tagme|标签|
|258|tail|兽尾|
|259|tan lines|日晒线|
|260|tattoo|文身|
|261|tennis|网球|
|262|tentacles|触手|
|263|text|文本|
|264|the idolm@ster|偶像大师|
|265|the idolm@ster cinderella girls|偶像大师灰姑娘女孩|
|266|the idolm@ster million live!|偶像大师百万现场|
|267|the idolm@ster shiny colors|偶像大师闪耀色彩|
|268|thighhighs|过膝袜|
|269|thong|丁字裤|
|270|to aru kagaku no railgun|某科学的超电磁炮|
|271|to aru majutsu no index|魔法禁书目录|
|272|to heart (series)|To Heart 系列|
|273|to heart 2|To Heart 2|
|274|to love ru|出包王女|
|275|to love ru darkness|出包王女 Darkness|
|276|topless|上身露出|
|277|torn clothes|破衣|
|278|touhou|东方|
|279|towel|浴巾|
|280|translated|文字已翻译(英文)|
|281|transparent png|背景透明|
|282|trap|伪娘|
|283|tribadism|磨豆腐/交叉体位|
|284|tutorial|教程|
|285|uma musume pretty derby|赛马娘|
|286|umbrella|伞|
|287|uncensored|无码|
|288|underboob|南半球|
|289|underwear|内衣|
|290|undressing|脱衣|
|291|uniform|制服|
|292|valentine|情人节|
|293|vibrator|跳蛋|
|294|wa maid|和风女仆|
|295|waitress|女侍|
|296|wallpaper|壁纸|
|297|wardrobe malfunction|走光|
|298|weapon|武器|
|299|wedding dress|婚纱|
|300|wet|湿身|
|301|wet clothes|湿衣|
|302|wings|翅膀|
|303|witch|女巫|
|304|xenoblade|异度神剑|
|305|xenoblade chronicles 2|异度神剑 2|
|306|yahari ore no seishun lovecome wa machigatteiru.|我的青春恋爱喜剧果然有问题|
|307|yaoi|蔷薇/男同|
|308|yukata|浴衣|
|309|yuri|百合|
|310|zhanjianshaonv|战舰少女|
[img-version]: https://img.shields.io/github/package-json/v/coderzhaoziwei/yande-re-chinese-patch?style=flat-square
[img-license]: https://shields.io/badge/license-MIT-blue?style=flat-square
[img-stars]: https://img.shields.io/github/stars/coderzhaoziwei/yande-re-chinese-patch?label=star&style=social
[img-cover]: https://cdn.jsdelivr.net/gh/coderzhaoziwei/yande-re-chinese-patch/preview.png
================================================
FILE: readme_main.md
================================================
![version][img-version]
![license][img-license]
![stars][img-stars]
![cover][img-cover]
# 目录
- [前言](#前言)
- [预览](#预览)
- [功能](#功能)
- [标签翻译](#标签翻译)
- [操作优化](#操作优化)
- [浏览模式](#浏览模式)
- [安装](#安装)
- [安装浏览器插件](#安装浏览器插件)
- [安装脚本程序](#安装脚本程序)
- [常见问题](#常见问题)
- [Q: 安卓手机如何安装 Tampermonkey?](#q-安卓手机如何安装-tampermonkey)
- [相关链接](#相关链接)
- [开源许可](#开源许可)
- [附:标签翻译表](#附标签翻译表)
# 前言
最初,我在浏览 [yande.re 站](https://yande.re)(以下简称 Y 站)的时候,遇到了一些难懂的标签名。在使用搜索引擎多方查询之后,我才终于明白个别晦涩单词的含义,可是过了一段时间再次遇到,又忘记了。然后我就敲了一个脚本程序,自动遍历页面中的标签名,添加中文翻译。为了让与我有同样困扰的其他朋友节约时间,我将脚本程序发布到了脚本网站 [Greasy Fork](https://greasyfork.org/) 上。
后来,有朋友提议添加更优化的操作方式,于是陆续增加了显示大图、键盘翻页等功能。再后来有一天,我躺在床上用手机登陆了 Y 站,网站无法适配移动端屏幕实在是太特么难受了,于是我就敲了响应式布局的浏览模式,手机可以自动加载图片资源,单屏一滑到底。
终于,舒服了。
- https://yande.re
- ~~https://oreno.imouto.us (Y 站镜像,无需魔法上网)~~(已失效)
- https://konachan.com (K 站已兼容)
- https://konachan.net (K 站安全模式,.net 域名下默认隐藏成人内容)
# 预览
- 样式优化,高清图源,尺寸自选。

- 流体布局,自动加载,一屏到底。

- 单图预览,聚合详情,一键下载。

- 显隐自如,更多功能,欢迎体验。

# 功能
## 标签翻译
翻译了 Y 站出现频率较高的 100 多个标签,详细内容请查看最下方的标签翻译表。欢迎校正或补充。
## 操作优化
- 对于 Y 站默认隐藏的成人内容,提供了显示或者隐藏的选项。
- 网页左侧的边栏,提供了显示或者隐藏的选项。
- 图源默认自动替换为高清资源,并提供了 1 ~ 4 倍尺寸的选项。
- 快捷键
- 上一页:A / ←
- 下一页:D / →
- 显示当前作品原图:S
- 显示当前作品来源:W
## 浏览模式
浏览任意图片列表时,可以进入浏览模式。
# 安装
## 安装浏览器插件
首先你需要为你的浏览器安装一个用户脚本管理器,推荐使用插件 [Tampermonkey](https://www.tampermonkey.net/)。
> 主流浏览器有 Chrome、Microsoft Edge、Firefox、Safari 等,如果你的浏览器无法安装 Tampermonkey,那么也就无法安装此脚本程序。
## 安装脚本程序
使用浏览器直接访问 [Greasy Fork - Yande.re 简体中文 - 主页](https://greasyfork.org/scripts/421970),点击安装即可。
如果你没有 Greasy Fork 的账号,访问以上链接可能会提示你:`此脚本不再在本网站上匿名可用。请登录并检查您的 Greasy Fork 账号设置。`
因为此脚本程序涉及成人内容,所以在 Greasy Fork 站点必须登录才可以浏览或安装。如果你不想注册成为 Greasy Fork 的用户,可以访问成人脚本站点 [Sleasy Fork](https://sleazyfork.org/scripts/421970) 直接安装,或者直接获取[仓库文件](https://github.com/coderzhaoziwei/yande-re-chinese-patch/raw/main/index.user.js)来安装。
# 常见问题
## Q: 安卓手机如何安装 Tampermonkey?
我推荐安卓 Yandex 浏览器,可以直接安装 Chrome 插件。当你发现谷歌市场的 Tampermonkey 显示不兼容时,点击 Yandex 菜单栏,切换为桌面模式即可。
其他安卓浏览器也可以的,Firefox、Kiwi、Iceraven 等自行尝试。
# 相关链接
[Github 仓库](https://github.com/coderzhaoziwei/yande-re-chinese-patch) |
[Greasy Fork 脚本主页](https://greasyfork.org/scripts/421970) |
[封面原图 Yande#388833](https://yande.re/post/show/388833)
# 开源许可
MIT
# 附:标签翻译表
[[ TAGS ]]
[img-version]: https://img.shields.io/github/package-json/v/coderzhaoziwei/yande-re-chinese-patch?style=flat-square
[img-license]: https://shields.io/badge/license-MIT-blue?style=flat-square
[img-stars]: https://img.shields.io/github/stars/coderzhaoziwei/yande-re-chinese-patch?label=star&style=social
[img-cover]: https://cdn.jsdelivr.net/gh/coderzhaoziwei/yande-re-chinese-patch/preview.png
================================================
FILE: script/action.js
================================================
#!/usr/bin/env node
const fs = require('fs')
const path = require('path')
const tagsData = Object()
const version = process.env['npm_package_version'] || ''
formatTagsFile()
generateReadMeFile()
function formatTagsFile() {
info('正在格式化标签数据')
const tagsPath = path.resolve(__dirname, '../source/data/tags.json')
const data = JSON.parse(fs.readFileSync(tagsPath))
Object.keys(data).sort().forEach(key => tagsData[key.replace(/ /g, '_')] = data[key])
fs.writeFileSync(tagsPath, JSON.stringify(tagsData, null, 2))
}
function generateReadMeFile() {
info('正在生成说明文档')
const main = fs.readFileSync(path.resolve(__dirname, '../readme_main.md'), 'utf8')
const tags = Object.keys(tagsData).reduce((data, key, index) => {
const en = key.replace(/_/g, ' ')
const cn = tagsData[key]
return `${ data }\n|${ index + 1 }|${en}|${cn}|`
}, '||English|简体中文|\n|:-:|:-|:-|')
fs.writeFileSync(path.resolve(__dirname, '../readme.md'), main.replace('[[ TAGS ]]', tags))
}
function info(log) {
console.log(`\u001b[35m[${version}] \u001b[34m${log}`)
}
================================================
FILE: script/bundle.sh
================================================
# clear
echo "\033[2J"
# version
yarn version --no-git-tag-version --patch
node script/action.js
# rollup
yarn rollup --config config/rollup.config.js
node script/replace.js
# copy
if (type pbcopy >/dev/null 2>&1) then
pbcopy < bundle/index.user.js
echo "\033[32mcopied \033[1;36mbundle/valkyrie.user.js \033[0;32mto clipboard.\033[0m"
fi
# end
echo ""
================================================
FILE: script/replace.js
================================================
#!/usr/bin/env node
const fs = require("fs")
const origin = fs.readFileSync("bundle/index.js", "utf8")
const result = handler(origin)
fs.writeFile("bundle/index.user.js", result, error => {
if (error) console.log(error)
})
function handler(content) {
// [{ path: "source/body.html" }]
const regexp = /\[{ path: ([\S]+) }\]/i
while (regexp.test(content)) {
const path = JSON.parse(RegExp.$1)
console.log(path)
const replacement = fs.readFileSync(path, "utf8")
content = content.replace(regexp, replacement)
}
return content
}
================================================
FILE: source/app.js
================================================
import Post from "./post"
const App = {
template: "#app-template",
data() {
return {
showDrawer: false,
showImageSelected: false,
showImageInfo: true,
showRatingQ: JSON.parse(localStorage.getItem("showRatingQ") || "true"),
showRatingE: JSON.parse(localStorage.getItem("showRatingE") || "false"),
imageList: [],
imageSelectedIndex: 0,
imageSelectedDetail: {},
params: new URLSearchParams(location.search),
requestState: false,
requestStop: false,
innerWidth: window.innerWidth,
innerHeight: window.innerHeight,
imageCountInRow: JSON.parse(localStorage.getItem("imageCountInRow") || "3"),
imageQualityHigh: JSON.parse(localStorage.getItem("imageQualityHigh") || "false"),
showFavoriteSuccess: false,
}
},
computed: {
isMobile() {
try {
return this.$vuetify.breakpoint.mobile
} catch(error) {
return false
}
},
title() {
return `${this.imageList.length} Posts`
},
version() {
return GM_info.script.version
},
imageSelected() {
return this.imageList[this.imageSelectedIndex] || new Post()
},
imageSelectedWidth() {
const width = parseInt(Math.min(this.innerWidth * 0.9, this.imageSelected.sampleWidth))
const height = Math.min(this.innerHeight * 0.9, this.imageSelected.sampleHeight)
const width2 = parseInt(height * this.imageSelected.aspectRatio)
return Math.min(width, width2)
},
imageSelectedHeight() {
const width = Math.min(this.innerWidth * 0.9, this.imageSelected.sampleWidth)
const height = parseInt(Math.min(this.innerHeight * 0.9, this.imageSelected.sampleHeight))
const height2 = parseInt(width / this.imageSelected.aspectRatio)
return Math.min(height, height2)
},
},
watch: {
showRatingQ(value) {
localStorage.setItem("showRatingQ", JSON.stringify(value))
},
showRatingE(value) {
localStorage.setItem("showRatingE", JSON.stringify(value))
},
imageCountInRow(value) {
localStorage.setItem("imageCountInRow", JSON.stringify(value))
},
imageQualityHigh(value) {
localStorage.setItem("imageQualityHigh", JSON.stringify(value))
},
showFavoriteSuccess(value) {
console.log('showFavoriteSuccess: ', value)
},
showImageSelected(value) {
if (!value) {
this.imageSelectedDetail = {}
return
}
this.getPostDetail(this.imageSelected.id).then(res => {
if (!res) return
this.imageSelectedDetail = res
})
}
},
methods: {
async request() {
this.requestState = true
const url = location.origin + location.pathname + ".json?" + this.params.toString()
const response = await new Promise(resolve => {
console.log(url)
jQuery.get(url, data => resolve(data))
})
if (response instanceof Array && response.length > 0) {
window.history.pushState("", "", location.pathname + "?" + this.params.toString())
response.forEach(item => this.imageList.push(new Post(item)))
const page = Number(this.params.get("page")) || 1
this.params.set("page", page + 1)
// 延迟
setTimeout(() => (this.requestState = false), 1000)
} else {
this.requestStop = true
}
},
download(src, filename) {
// 添加文件后缀
const match = src.match(/[.](?png|jpg|jpeg)$/)
if (match) {
const extension = match.groups.extension
GM_download(src, filename + "." + extension)
} else {
GM_download(src, filename)
}
},
// 添加收藏
onFavorite(id) {
$.ajax({
method: 'POST',
url: "https://yande.re/post/vote.json",
beforeSend: xhr => xhr.setRequestHeader('x-csrf-token', window.csrfToken),
data: { id, score: 3 },
success: data => {
if (data.success === true) {
this.imageList[this.imageSelectedIndex].favorite = true // 更新收藏状态
this.imageSelectedDetail.favorite = true
}
},
})
},
async getPostDetail(id) {
try {
if (!id) return
const response = await fetch(`/post.json?api_version=2&tags=id:${id}&include_tags=1&include_votes=1`)
const result = await response.json()
return {
favorite: result.votes[id] == 3,
artist: Object.keys(result.tags).find(k => result.tags[k] == 'artist')
}
} catch (error) {
console.log('getPostDetail error:', error)
}
}
},
mounted() {
// 自动加载数据
const timeInterval = setInterval(() => {
if (this.requestStop === true) {
clearInterval(timeInterval)
return
}
const scrollTop = document.documentElement.scrollTop
const scrollHeight = document.documentElement.scrollHeight
const height = window.innerHeight
if (scrollTop + height >= scrollHeight * 0.75) {
if (this.requestState === false) {
this.request()
}
}
}, 1000)
// 记录窗口尺寸
window.addEventListener("resize", () => {
this.innerWidth = window.innerWidth
this.innerHeight = window.innerHeight
})
},
}
export default App
================================================
FILE: source/browse.js
================================================
import app from "./app"
export async function enterBrowseMode() {
function getScript(url) {
return new Promise(resolve => jQuery.getScript(url, () => resolve()))
}
await getScript("https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.min.js")
await getScript("https://cdn.jsdelivr.net/npm/vuetify@2.5.0/dist/vuetify.min.js")
await getScript("https://cdn.jsdelivr.net/npm/vue-masonry-css@1.0.3/dist/vue-masonry.min.js")
await getScript("https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js")
window.csrfToken = jQuery('[name="csrf-token"]').attr('content')
document.head.innerHTML = `[{ path: "source/html/head.html" }]`
document.body.innerHTML = `[{ path: "source/html/body.html" }]`
Vue.use(VueMasonry)
new Vue({
vuetify: new Vuetify({
theme: { dark: true },
}),
render: h => h(app)
}).$mount("#app")
}
================================================
FILE: source/data/footers.json
================================================
{
"List": "首页",
"Browse": "翻阅",
"Upload": "上传",
"Random": "随机",
"Popular": "热门",
"Image Search": "寻图",
"History": "历史",
"Help": "帮助"
}
================================================
FILE: source/data/menus.json
================================================
{
"My Account": "账户",
"Posts": "作品",
"Comments": "评论",
"Notes": "笔记",
"Artists": "画师",
"Tags": "标签",
"Forum": "论坛",
"Help": "帮助",
"More »": "更多>>",
"New Mail": "新消息",
"My Profile": "我的资料",
"My Mail": "我的消息",
"My Favorites": "我的收藏",
"Settings": "设置",
"Change Password": "修改密码",
"Logout": "退出登录",
"View Posts": "浏览作品",
"Search Posts": "搜索作品",
"Upload": "上传",
"Random": "随机浏览",
"Popular": "热门",
"Image Search": "搜索图片",
"History": "历史",
"View Comments": "浏览评论",
"Search Comments": "搜索评论",
"View Notes": "浏览笔记",
"Search Notes": "搜索笔记",
"View Artists": "浏览画师",
"Search Artists": "搜索画师",
"Create": "创建",
"View Tags": "浏览标签",
"Search Tags": "搜索标签",
"Aliases": "别名",
"Implications": "含义",
"View Pools": "浏览 Pools",
"Search Pools": "搜索 Pools",
"Create New Pool": "创建 Pool",
"View Wiki Index": "浏览 Wiki 主页",
"Search Wiki": "搜索 Wiki",
"Create New Page": "创建新页面",
"Mark All Read": "全部标记已读"
}
================================================
FILE: source/data/tags.json
================================================
{
"4koma": "四格漫画",
"5-toubun_no_hanayome": "五等分的新娘",
"anal": "肛交",
"angel": "天使",
"angel_beats!": "Angel Beats!",
"animal_ears": "兽耳",
"anthropomorphization": "拟人化",
"anus": "肛门露出",
"areola": "乳晕",
"arknights": "明日方舟",
"armor": "盔甲/装甲",
"artist_revision": "画师修改",
"ass": "臀部",
"ass_grab": "持股/捏臀",
"atelier": "炼金工房系列",
"autographed": "亲笔签名",
"azur_lane": "碧蓝航线",
"bakemonogatari": "化物语",
"bandages": "绷带",
"bandaid": "创可贴/绷带",
"bang_dream!": "BanG Dream!",
"baseball": "棒球",
"basketball": "篮球",
"bathing": "沐浴",
"benghuai_xueyuan": "崩坏学园",
"bike_shorts": "自行车短裤",
"bikini": "比基尼",
"bikini_armor": "比基尼装甲/轻薄盔甲",
"bikini_top": "比基尼乳罩",
"black_rock_shooter": "黑岩射手",
"blood": "血腥",
"bloomers": "灯笼裤/宽松短裤",
"blue_archive": "碧蓝档案",
"bodysuit": "紧身衣裤",
"boku_wa_tomodachi_ga_sukunai": "我的朋友很少",
"bondage": "束缚",
"bottomless": "下身露出",
"bra": "乳罩",
"breast_grab": "握乳",
"breast_hold": "托乳",
"breasts": "乳",
"bukkake": "颜射",
"bunny_ears": "兔耳",
"bunny_girl": "兔女郎",
"buruma": "运动短裤",
"business_suit": "西装/职业服",
"calendar": "日历",
"cameltoe": "阴户凸显",
"card": "卡牌",
"card_captor_sakura": "魔卡少女樱",
"censored": "有码",
"cg": "CG/计算机动画",
"chainsaw": "电锯",
"character_design": "角色设计",
"cheerleader": "啦啦队队员",
"chibi": "Q版",
"chinadress": "旗袍",
"choujigen_game_neptune": "超次元游戏海王星",
"christmas": "圣诞",
"cleavage": "乳沟",
"code_geass": "反叛的鲁路修",
"condom": "避孕套",
"corset": "(束腰)紧身内衣",
"cosplay": "角色扮演",
"cream": "奶油",
"cropped": "裁剪图",
"crossdress": "变装",
"crossover": "作品联动/混合同人",
"cum": "精液",
"cunnilingus": "品玉/舔阴",
"dakimakura": "抱枕",
"darling_in_the_franxx": "DARLING in the FRANXX",
"date_a_live": "约会大作战",
"detexted": "去字图片",
"devil": "魔鬼/恶魔",
"digital_version": "数字版",
"dildo": "假阳具",
"disc_cover": "光盘封面",
"dress": "连衣裙",
"dress_shirt": "衬衫",
"duplicate": "重复图片",
"elf": "精灵",
"endcard": "片尾插图",
"erect_nipples": "乳尖",
"expression": "角色展示/立绘",
"extreme_content": "极端",
"eyepatch": "眼罩",
"fairy": "精灵/小精灵",
"fate/kaleid_liner_prisma_illya": "Fate/kaleid liner 魔法少女☆伊莉雅",
"feet": "足",
"fellatio": "口交",
"final_fantasy": "最终幻想",
"final_fantasy_vii": "最终幻想 VII",
"final_fantasy_xiv": "最终幻想 14",
"fingering": "指交",
"fire_emblem": "火焰纹章",
"fire_emblem_heroes": "火焰之纹章:英雄云集",
"fire_emblem_kakusei": "火焰之纹章:觉醒",
"fire_emblem_three_houses": "火焰之纹章:风花雪月",
"fishnets": "鱼网袜",
"fixed": "修改",
"footjob": "足交",
"fundoshi": "褌/兜裆布",
"futanari": "扶她",
"game_cg": "游戏CG",
"gangbang": "乱交",
"garter": "袜带",
"garter_belt": "吊袜腰带",
"genderswap": "性转",
"genshin_impact": "原神",
"girls_frontline": "少女前线",
"girls_und_panzer": "少女与战车",
"gochuumon_wa_usagi_desu_ka?": "请问您今天要来点兔子吗?",
"gothic_lolita": "哥特式洛丽塔",
"granblue_fantasy": "碧蓝幻想",
"guitar": "吉他",
"gun": "枪炮",
"gundam": "高达",
"guro": "猎奇",
"halloween": "万圣节前夜",
"handjob": "打手枪",
"headphones": "耳机",
"heels": "高跟鞋",
"heterochromia": "虹膜异色",
"hibike!_euphonium": "吹响吧!上低音号",
"highschool_dxd": "恶魔高校D×D",
"honkai_impact": "崩坏 3",
"horns": "角",
"index_page": "索引页面",
"infinite_stratos": "IS/无限斯特拉托斯",
"inumimi": "犬耳",
"japanese_clothes": "日式服装",
"k-on!": "轻音少女",
"kaguya-sama_wa_kokurasetai_~tensai-tachi_no_renai_zunousen~": "辉夜大小姐想让我告白~天才们的恋爱头脑战~",
"kantai_collection": "舰队 Collection",
"kemono_friends": "兽娘动物园",
"kimetsu_no_yaiba": "鬼灭之刃",
"kimono": "和服",
"kitsune": "狐狸",
"kobayashi-san_chi_no_maid_dragon": "小林家的龙女仆",
"kono_subarashii_sekai_ni_shukufuku_wo!": "为美好的世界献上祝福!",
"lactation": "泌乳",
"landscape": "风景画",
"league_of_legends": "英雄联盟",
"leotard": "紧身连衣裤",
"line_art": "线条画",
"lingerie": "贴身内衣",
"little_busters!": "Little Busters!",
"loli": "萝莉",
"lolita_fashion": "洛丽塔",
"love_live!_nijigasaki_high_school_idol_club": "Love Live! 虹咲学园学园偶像同好会",
"lucky_star": "幸运星",
"maebari": "前貼り/遮盖私处",
"mahou_shoujo_lyrical_nanoha": "魔法少女奈叶",
"mahou_shoujo_lyrical_nanoha_strikers": "魔法少女奈叶 StrikerS",
"maid": "女仆",
"male": "男性",
"masturbation": "自摸/手淫",
"mecha": "机甲",
"mecha_musume": "机甲娘",
"megane": "眼镜",
"megaten": "女神转生系列",
"mermaid": "美人鱼",
"miko": "巫女",
"monochrome": "单色",
"monster": "怪物",
"monster_girl": "怪物女孩",
"monster_musume_no_iru_nichijou": "魔物娘的相伴日常",
"naked": "裸体",
"naked_apron": "裸体围裙",
"naked_cape": "裸体披风",
"naked_ribbon": "裸体丝带",
"neko": "猫",
"nekomimi": "猫耳",
"neon_genesis_evangelion": "新世纪福音战士",
"nier_automata": "尼尔:自动人形",
"nijisanji": "彩虹社",
"ninja": "忍者",
"nipple_slip": "露点",
"nipples": "乳头",
"no_bra": "无乳罩",
"nopan": "无胖次",
"nun": "修女",
"nurse": "护士",
"official_watermark": "官方水印",
"onsen": "温泉",
"open_shirt": "衬衫敞开",
"ore_no_imouto_ga_konnani_kawaii_wake_ga_nai": "我的妹妹哪有这么可爱!",
"overalls": "工装连衣裤",
"overwatch": "守望先锋",
"paizuri": "乳交",
"pajama": "睡衣",
"panties": "内裤",
"pantsu": "胖次",
"panty_pull": "胖次脱下",
"pantyhose": "吊带袜",
"parody": "仿拟/谐拟",
"partial_scan": "局部扫描",
"pasties": "乳贴",
"pee": "尿尿",
"penguin": "企鹅",
"penis": "阴茎",
"photo": "照片/现实背景",
"photoshop": "PS 改图",
"pirate": "海盗",
"pointy_ears": "尖耳朵",
"pokemon": "精灵宝可梦",
"possible_duplicate": "可能重复",
"pregnant": "孕妇",
"pretty_cure": "光之美少女",
"princess_connect": "公主连结",
"princess_connect!_re:dive": "公主连结 Re:Dive",
"profile_page": "角色资料页",
"pubic_hair": "阴毛",
"puella_magi_madoka_magica": "魔法少女小圆",
"pussy": "阴户",
"pussy_juice": "妹汁",
"queen's_blade": "女王之刃",
"raw_scan": "扫描原图",
"re_zero_kara_hajimeru_isekai_seikatsu": "Re:从零开始的异世界生活",
"robe": "长袍/礼服/睡袍",
"saenai_heroine_no_sodatekata": "路人女主的养成方法",
"sailor_moon": "美少女战士",
"sake": "日本清酒",
"sample": "样品图",
"sarashi": "晒し/缠胸布",
"school_swimsuit": "学校泳衣",
"see_through": "透视",
"seifuku": "制服",
"selfie": "自拍",
"senran_kagura": "闪乱神乐",
"sex": "性交",
"sheets": "床单",
"shimapan": "条纹胖次",
"shirt_lift": "衬衫掀起",
"shota": "正太",
"silhouette": "剪影/暗色轮廓/体形",
"sketch": "素描",
"skirt_lift": "裙摆掀起",
"sling_bikini": "吊带比基尼",
"smoking": "吸烟",
"soccer": "足球",
"sono_bisque_doll_wa_koi_wo_suru": "更衣人偶坠入爱河",
"spy_x_family": "间谍过家家",
"ssss.gridman": "SSSS.古立特",
"stick_poster": "海报",
"stockings": "长筒袜",
"strike_witches": "强袭魔女",
"string_panties": "细绳胖次",
"summer_dress": "夏装",
"suzumiya_haruhi_no_yuuutsu": "凉宫春日的忧郁",
"sweater": "毛衣",
"swimsuits": "泳衣",
"sword": "刀剑",
"sword_art_online": "刀剑神域",
"symmetrical_docking": "乳乳相接",
"tagme": "标签",
"tail": "兽尾",
"tan_lines": "日晒线",
"tattoo": "文身",
"tennis": "网球",
"tentacles": "触手",
"text": "文本",
"the_idolm@ster": "偶像大师",
"the_idolm@ster_cinderella_girls": "偶像大师灰姑娘女孩",
"the_idolm@ster_million_live!": "偶像大师百万现场",
"the_idolm@ster_shiny_colors": "偶像大师闪耀色彩",
"thighhighs": "过膝袜",
"thong": "丁字裤",
"to_aru_kagaku_no_railgun": "某科学的超电磁炮",
"to_aru_majutsu_no_index": "魔法禁书目录",
"to_heart_(series)": "To Heart 系列",
"to_heart_2": "To Heart 2",
"to_love_ru": "出包王女",
"to_love_ru_darkness": "出包王女 Darkness",
"topless": "上身露出",
"torn_clothes": "破衣",
"touhou": "东方",
"towel": "浴巾",
"translated": "文字已翻译(英文)",
"transparent_png": "背景透明",
"trap": "伪娘",
"tribadism": "磨豆腐/交叉体位",
"tutorial": "教程",
"uma_musume_pretty_derby": "赛马娘",
"umbrella": "伞",
"uncensored": "无码",
"underboob": "南半球",
"underwear": "内衣",
"undressing": "脱衣",
"uniform": "制服",
"valentine": "情人节",
"vibrator": "跳蛋",
"wa_maid": "和风女仆",
"waitress": "女侍",
"wallpaper": "壁纸",
"wardrobe_malfunction": "走光",
"weapon": "武器",
"wedding_dress": "婚纱",
"wet": "湿身",
"wet_clothes": "湿衣",
"wings": "翅膀",
"witch": "女巫",
"xenoblade": "异度神剑",
"xenoblade_chronicles_2": "异度神剑 2",
"yahari_ore_no_seishun_lovecome_wa_machigatteiru.": "我的青春恋爱喜剧果然有问题",
"yaoi": "蔷薇/男同",
"yukata": "浴衣",
"yuri": "百合",
"zhanjianshaonv": "战舰少女"
}
================================================
FILE: source/hotkey.js
================================================
export const initHotKey = function() {
window.addEventListener("keyup", function(event) {
console.log('keyup:', event.key)
// 有输入框被激活时,禁止触发方向键。
if (/^(TEXTAREA|INPUT|SELECT|BUTTON)$/.test(document.activeElement.tagName)) return
// 上一页 ← a A
const prev = document.querySelector(".pagination>.previous_page") || jQuery("li:contains('Previous') a[href]")[0]
if (prev && (event.key == "ArrowLeft" || event.key == "a" || event.key == "A")) {
prev.click()
return event.preventDefault()
}
// 下一页 → d D
const next = document.querySelector(".pagination>.next_page") || jQuery("li:contains('Next') a[href]")[0]
if (next && (event.key == "ArrowRight" || event.key === "d" || event.key == "D")) {
next.click()
return event.preventDefault()
}
// 显示 s S
const show = document.querySelector("#png") || document.querySelector("#highres")
if (show && (event.key === "s" || event.key === "S")) {
show.click()
return event.preventDefault()
}
// 来源 w W
const where = jQuery("li:contains('Source:') a")[0]
if (where && (event.key === "w" || event.key === "W")) {
where.click()
return event.preventDefault()
}
})
const sidebar = document.querySelector("#post-list > div.sidebar") || document.querySelector("#post-view > div.sidebar")
if (sidebar) {
sidebar.insertAdjacentHTML("beforeend", "" +
"
快捷键说明
" +
"
上一页:A / ←
" +
"
下一页:D / →
" +
"
显示当前作品原图:S
" +
"
显示当前作品来源:W
" +
"
")
}
}
================================================
FILE: source/html/body.html
================================================
================================================
FILE: source/html/head.html
================================================
Yande.re 简体中文
================================================
FILE: source/html/options.html
================================================
================================================
FILE: source/index.js
================================================
import { initStyle } from "./style"
import { initHotKey } from "./hotkey"
import { initOptions } from "./options"
import { initTranslate } from "./translate"
jQuery(document).ready(function() {
initStyle()
initHotKey()
initOptions()
initTranslate()
if (document.cookie.includes('locale=zh_CN') === false) {
document.cookie = "locale=zh_CN"
location.href = location.href
}
})
================================================
FILE: source/options.js
================================================
import { enterBrowseMode } from "./browse"
export const onChangeLeftBar = function() {
const value = Boolean(document.getElementById("showLeftBar").selectedIndex)
localStorage.setItem("showLeftBar", JSON.stringify(value))
const element = document.querySelector("#post-list > .sidebar")
element.setAttribute("show-left-bar", value)
console.log("showLeftBar", value)
}
export const onChangeRatingE = function() {
const value = Boolean(document.getElementById("showRatingE").selectedIndex)
localStorage.setItem("showRatingE", JSON.stringify(value))
const elementList = document.querySelectorAll(".javascript-hide")
elementList.forEach(element => element.setAttribute("show-rating-e", value))
console.log("showRatingE", value)
}
export const onChangeImageHD = function() {
// 获取 index 值
const index = document.getElementById("showImageHD").selectedIndex
// 修改属性 show-image-hd
const elementList = document.querySelectorAll("#post-list-posts > li > .inner")
elementList.forEach(element => element.setAttribute("show-image-hd", index))
// 缓存 index 值
localStorage.setItem("showImageHD", JSON.stringify(index))
console.log("showImageHD", index)
// 设置网格布局宽
// document.querySelector("#post-list-posts").style.gridTemplateColumns = `repeat(auto-fill, ${(index + 1) * 150}px)`
}
// 网站域名 例如'https://oreno.imouto.us'
const origin = window.location.origin
let taskArray = []
// 'https://oreno.imouto.us'域名下每秒钟尝试加载的Sample图片数
let maxLoadingSampleNum = 4
let doLoadSampleUrl = () => {
let loadingNum = 0
let loadSampleUrl = () => {
if (taskArray.length == 0) return
loadingNum++
let { element, sampleUrl } = taskArray.shift()
element.onerror = () => {
element.src = sampleUrl
}
element.onload = () => {
loadingNum--
}
element.src = sampleUrl
}
setInterval(() => {
if (taskArray.length == 0) return
let needloadNum = maxLoadingSampleNum - loadingNum
while (needloadNum--) {
loadSampleUrl()
}
}, 1000)
}
export const initOptions = function() {
// https://yande.re/user/show/507475
if (/^\/user\/show\/[\d]{1,}/.test(location.pathname)) return
if (document.getElementById("post-list-posts") === null) return
// 插入文档元素
document.getElementById("post-list-posts").insertAdjacentHTML("beforebegin", `[{ path: "source/html/options.html" }]`)
// 替换图片元素
const imageList = document.querySelectorAll("img.preview")
const samples = JSON.parse(localStorage.getItem("sample_urls"))
imageList.forEach(element => {
if (/\/post\/show\/([\d]{1,})/.test(element.nextElementSibling.innerText)) {
const id = RegExp.$1
const sampleUrl = samples[id]
if (sampleUrl !== undefined) {
element.src = sampleUrl
}
}
})
doLoadSampleUrl()
// 监听
document.getElementById("showLeftBar").addEventListener("change", onChangeLeftBar)
document.getElementById("showRatingE").addEventListener("change", onChangeRatingE)
document.getElementById("showImageHD").addEventListener("change", onChangeImageHD)
// 获取本地记录
const showLeftBar = JSON.parse(localStorage.getItem("showLeftBar") || "true")
const showRatingE = JSON.parse(localStorage.getItem("showRatingE") || "true")
const showImageHD = JSON.parse(localStorage.getItem("showImageHD") || "0")
document.getElementById("showLeftBar").selectedIndex = showLeftBar
document.getElementById("showRatingE").selectedIndex = showRatingE
document.getElementById("showImageHD").selectedIndex = showImageHD
onChangeLeftBar()
onChangeRatingE()
onChangeImageHD()
// 浏览模式
document.getElementById("enterBrowseMode").addEventListener("click", enterBrowseMode)
}
================================================
FILE: source/post.js
================================================
/*
approver_id: null
change: 4106973
frames: []
frames_pending: []
frames_pending_string: ""
frames_string: ""
has_children: false
is_held: false
is_note_locked: false
is_pending: false
is_rating_locked: false
is_shown_in_index: true
last_commented_at: 0
last_noted_at: 0
parent_id: null
status: "active"
*/
export default class Post {
constructor(data) {
if (typeof data !== "object") data = {}
this.id = data.id || 0
this.score = data.score || 0
this.tags = data.tags || ""
this.source = data.source || ""
this.author = data.author || ""
this.creatorId = data.creator_id || 0
this.createdAt = data.created_at || 0
this.updatedAt = data.updated_at || 0
this.rating = data.rating || "s"
// 文件
this.fileUrl = data.file_url || ""
this.fileExt = data.file_ext || ""
this.fileSize = data.file_size || 0
this.width = data.width || 0
this.height = data.height || 0
// 高清图
this.jpegUrl = data.jpeg_url || ""
this.jpegSize = data.jpeg_file_size || 0
this.jpegWidth = data.jpeg_width || 0
this.jpegHeight = data.jpeg_height || 0
// 缩略图
this.sampleUrl = data.sample_url
this.sampleSize = data.sample_file_size || 0
this.sampleWidth = data.sample_width || 0
this.sampleHeight = data.sample_height || 0
// 预览图 用作懒加载的占位图
this.previewUrl = data.preview_url
this.previewWidth = data.actual_preview_width || 0
this.previewHeight = data.actual_preview_height || 0
this.favorite = false
}
// 全年龄 safe
get isRatingS() {
return this.rating === "s"
}
// 擦边球 questionable
get isRatingQ() {
return this.rating === "q"
}
// 成人向 explicit
get isRatingE() {
return this.rating === "e"
}
// 长宽比
get aspectRatio() {
return this.width / this.height
}
getSizeText(size) {
if (size > 1024 * 1024) {
return (size / (1024 * 1024)).toFixed(2) + "MB"
}
if (size > 1024) {
return (size / 1024).toFixed(2) + "KB"
}
return (size).toFixed(2) + "B"
}
get sampleSizeText() {
return this.getSizeText(this.sampleSize)
}
get sampleDownloadText() {
return `下载缩略图 ${this.sampleWidth}×${this.sampleHeight} [${this.sampleSizeText}]`
}
get sampleDownloadName() {
return `${location.hostname}.${this.id}.${this.sampleWidth}x${this.sampleHeight}`.replace(/\./g, "_")
}
get jpegSizeText() {
return this.getSizeText(this.jpegSize)
}
get jpegDownloadText() {
return `下载高清图 ${this.jpegWidth}×${this.jpegHeight} [${this.jpegSizeText}]`
}
get jpegDownloadName() {
return `${location.hostname}.${this.id}.${this.jpegWidth}x${this.jpegHeight}`.replace(/\./g, "_")
}
get fileSizeText() {
return this.getSizeText(this.fileSize)
}
get fileDownloadText() {
return `下载原文件 ${this.width}×${this.height} [${this.fileSizeText}] ${this.fileExt.toUpperCase()}`
}
get fileDownloadName() {
return `${location.hostname}.${this.id}.${this.width}x${this.height}`.replace(/\./g, "_")
}
get createdTime() {
const date = new Date(this.createdAt * 1000)
return `${date.toLocaleDateString()} ${date.toLocaleTimeString("en-DE")}`
}
get updatedTime() {
const date = new Date(this.updatedAt * 1000)
return `${date.toLocaleDateString()} ${date.toLocaleTimeString("en-DE")}`
}
// 解析图源 i.pximg.net => pixiv.net
// https://i.pximg.net/img-original/img/2021/05/15/09/41/42/89846615_p0.jpg
// https://www.pixiv.net/artworks/89846615
get sourceUrl() {
if (/^https:\/\/i\.pximg\.net\/img-original\/img\/[\d\/]{19}\/([\d]{1,})_p[\d]{1,}\.(jpg|png)$/.test(this.source)) {
const pid = RegExp.$1
return `https://pixiv.net/artworks/${pid}`
}
return this.source
}
}
================================================
FILE: source/style/fix.css
================================================
body {
font-size: 12px;
padding: 0 0.5rem;
}
body::-webkit-scrollbar {
display: none;
width: 0px !important;
}
/* 标题居中 */
div#header {
margin: 0;
}
div#header > div#title {
display: flex;
place-content: center;
margin: 0 !important;
height: fit-content;
}
div#header > div#title > h2#site-title {
display: flex !important;
flex-direction: column;
}
div#header > div#title > h2#site-title > span {
font-size: 12px;
font-weight: normal;
text-align: right;
}
div#header > div#main-menu {
padding: 0 !important;
margin: 0 !important;
display: flex !important;
justify-content: center;
font-size: 14px;
line-height: 2rem;
height: 2rem;
}
div#header > div#main-menu > ul {
margin: 0;
}
/* 通知 */
.status-notice {
text-align: center;
}
/* 标签前缀 */
li.tag-type-artist a[href^="/post"]:not(.no-browser-link)::before {
content: "[画师]";
}
li.tag-type-copyright a[href^="/post"]:not(.no-browser-link)::before {
content: "[原作]";
}
li.tag-type-character a[href^="/post"]:not(.no-browser-link)::before {
content: "[角色]";
}
li.tag-type-circle a[href^="/post"]:not(.no-browser-link)::before {
content: "[公司]";
}
/* 图区 */
#post-list {
display: flex;
flex-direction: row;
}
#post-list > .sidebar {
width: auto;
max-width: 200px;
flex: 0 0 auto;
}
#post-list > .content {
width: auto;
flex: 1 1 auto;
}
#post-list > div.lsidebar {
display: none;
}
ul#post-list-posts {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
place-content: center;
place-items: center;
}
ul#post-list-posts > li {
width: fit-content !important;
height: 100%;
margin: 0 !important;
border: none;
}
ul#post-list-posts > li > div.inner {
width: auto !important;
height: fit-content !important;
}
ul#post-list-posts > li > a.directlink {
font-size: 12px;
height: 12px;
line-height: 12px;
margin: 0;
padding: 0;
overflow: hidden;
background: rgb(16, 16, 16);
}
ul#post-list-posts > li > a.directlink > span.directlink-res {
display: inline;
}
ul#post-list-posts > li > a.directlink > span.directlink-info {
display: none;
}
ul#post-list-posts > li > div.inner > a.thumb {
height: auto;
}
ul#post-list-posts > li > div.inner > a.thumb > img.preview {
margin: 0 !important; /* @konachan */
border: none;
}
/* 分页器 */
div#paginator {
padding: 0;
}
div#paginator > div.pagination {
line-height: 2rem;
}
/* 页脚 */
#content > div:nth-child(2) > div.sidebar {
display: none;
}
#content div.footer {
font-size: 14px;
margin: 1rem;
}
/* show-left-bar */
.sidebar[show-left-bar=false] {
display: none !important;
}
/* show-rating-e */
.javascript-hide[show-rating-e=true] {
display: block !important;
position: relative;
}
.javascript-hide[show-rating-e=true]::after {
content: "";
position: absolute;
width: 100%;
height: 100%;
top: 0;
box-shadow: 0px 0px 12px rgb(255, 0, 0) inset;
pointer-events: none;
}
/* show-image-hd */
#post-list-posts > li > .inner[show-image-hd="1"] {
zoom: 2;
}
#post-list-posts > li > .inner[show-image-hd="2"] {
zoom: 3;
}
#post-list-posts > li > .inner[show-image-hd="3"] {
zoom: 4;
}
================================================
FILE: source/style.js
================================================
export const initStyle = function() {
document.head.insertAdjacentHTML("beforeend", ``)
}
================================================
FILE: source/translate.js
================================================
const tags = [{ path: "source/data/tags.json" }]
const menus = [{ path: "source/data/menus.json" }]
const footers = [{ path: "source/data/footers.json" }]
// 翻译标签
export const translateTags = function() {
const elementList = Array.from(document.getElementsByTagName("a"))
elementList.forEach(element => {
const href = element.getAttribute("href")
if (typeof href === "string" && /^\/post\?tags=(\S+)$/.test(href)) {
const en = RegExp.$1
const cn = tags[en]
if (cn) {
element.innerText = `[${cn}]${en.replace(/_/g, " ")}`
}
}
})
}
// 翻译菜单
export const translateMenus = function() {
const mainMenuList = Array.from(document.querySelectorAll("#main-menu>ul>li>a"))
const subMenuList = Array.from(document.querySelectorAll("ul.submenu>li>a"))
const elementList = [...mainMenuList, ...subMenuList]
elementList.forEach(element => {
if (element.getAttribute("href") === "#") return
const en = element.innerText
const cn = menus[en]
if (cn) {
element.innerText = cn
}
})
}
// 翻译提示
export const translateNotice = function() {
// EN: This image has been resized. Click on the `View larger version` link in the sidebar
// for a high-quality version. Hide this message
// CN: 这张图片已经被压缩,单击侧边栏中的 `显示高清图` 可以获取更高质量的版本。不再提醒
// EN: This post belongs to a parent post.
// EN: This post has child posts. (post #728160, 746235)
// EN: This post has a child post. (post #383703)
const elementList = Array.from(document.querySelectorAll(".status-notice"))
elementList.forEach(element => {
console.log(element.innerHTML)
element.innerHTML = element.innerHTML
.replace(/^[\s]+This image has been resized. Click on the /, "这张图片已经被压缩,单击侧边栏中的")
.replace(/View larger version/, "显示高清图")
.replace(/ link in the sidebar for a high-quality version./, "可以获取更高质量的版本。")
.replace(/Hide this message<\/a>\./, "不再提醒")
/* 相关父作品 */
.replace(/This post belongs to a /, "这张图片从属于一个")
.replace(/parent post<\/a>\./, "相关父作品。")
/* 相关子作品 */
.replace(/This post has /, "这张图片从属于一个")
.replace(/child posts<\/a>\. \(post #/, "作品集。相关子作品:")
.replace(/a child post<\/a>\. \(post #/, "作品集。相关子作品:")
.replace(/<\/a>, | \)/, "")
})
}
// 翻译点击
export const translateButtons = function() {
[
['#highres-show', 'View larger version', '显示高清图'],
['#highres', 'Download larger version', '下载高清图'],
['#png', 'Download PNG', '下载 PNG 图'],
['li#add-to-favs>a', 'Add to favorites', '添加收藏'],
['li#set-avatar>a', 'Set avatar', '设置头像'],
['h4>a.js-posts-show-edit-tab', 'Edit', '编辑'],
['h4>a.js-posts-show-comments-tab', 'Respond', '评论'],
['.pagination>.previous_page', '← Previous', '上一页'],
['.pagination>.next_page', 'Next →', '下一页'],
].forEach(data => {
const [selector, en, cn] = data
const element = document.querySelector(selector)
if (element) {
element.innerText = element.innerText.replace(en, cn)
}
})
}
// 翻译页脚
export const translateFooters = function() {
const elementList = Array.from(document.querySelectorAll('#subnavbar>li>a'))
elementList.forEach(element => {
const en = element.innerText
const cn = footers[en]
if (cn) {
element.innerText = cn
}
})
}
// 合并
export const initTranslate = function() {
translateTags()
translateMenus()
translateNotice()
translateButtons()
translateFooters()
}
================================================
FILE: temp/css_text_loader.js
================================================
module.exports = function(source) {
return 'export default ' + JSON.stringify(source)
}
================================================
FILE: temp/index.js
================================================
/**
* 默认显示隐藏的作品,并提供可开关的选项。
*/
;(function() {
const SET_JS_HIDE = 'set-javascript-hide'
const INPUT_HTML = ` `
const target = document.getElementById('post-list-posts')
if (target && target.parentNode) {
const div = document.createElement('div')
target.parentNode.insertBefore(div, target)
div.innerHTML = INPUT_HTML
// div.setAttribute('style', 'user-select: none; text-align: left;')
div.setAttribute('id', 'script-addition')
} else return
const checkbox = document.getElementById(SET_JS_HIDE)
checkbox.checked = JSON.parse(localStorage.getItem(SET_JS_HIDE))
update()
checkbox.addEventListener('change', update)
function update() {
Array.from(document.querySelectorAll('.javascript-hide')).forEach(element => {
if (checkbox.checked) element.removeClassName(SET_JS_HIDE)
else element.addClassName(SET_JS_HIDE)
})
localStorage.setItem(SET_JS_HIDE, checkbox.checked)
}
})()
/**
* 默认尺寸 h=150px
* 大图模式 h=300px
* 高清模式 显示高清大图 parent
*/
;(function() {
const target = document.getElementById(`script-addition`)
if (target) {
// const SET_POST_HD = `set-post-hd`
// const isHD = Boolean(JSON.parse(localStorage.getItem(SET_POST_HD)))
const SET_POST_SIZE = `set-post-size`
if (getHDValue() === false) {
target.insertAdjacentHTML(`beforeend`, ``)
target.insertAdjacentHTML(`beforeend`, ``)
target.insertAdjacentHTML(`beforeend`, ``)
target.insertAdjacentHTML(`beforeend`, ``)
}
target.insertAdjacentHTML(`beforeend`, ``)
target.insertAdjacentHTML(`beforeend`, ``)
const checkbox1 = document.getElementById(`${SET_POST_SIZE}1`)
const checkbox2 = document.getElementById(`${SET_POST_SIZE}2`)
const checkbox3 = document.getElementById(`${SET_POST_SIZE}3`)
update()
checkbox1 && checkbox1.addEventListener(`change`, changeValue)
checkbox2 && checkbox2.addEventListener(`change`, changeValue)
checkbox3.addEventListener(`change`, changeHDValue)
function getValue() {
return Boolean(JSON.parse(localStorage.getItem(SET_POST_SIZE)))
}
function changeValue() {
const value = getValue()
localStorage.setItem(SET_POST_SIZE, JSON.stringify(!value))
location.reload() // 刷新页面
}
function getHDValue() {
return Boolean(JSON.parse(localStorage.getItem(`set-post-hd`)))
}
function changeHDValue() {
const value = getHDValue()
localStorage.setItem(`set-post-hd`, JSON.stringify(!value))
location.reload() // 刷新页面
}
function update() {
if (getHDValue() === true) {
checkbox3.checked = true
target.insertAdjacentHTML(`beforeend`, `高清模式加载缓慢,可能需要等待一段时间。
`)
// setTimeout(() => document.getElementById(`script-notice-hd`).remove(), 10000)
const imageList = document.querySelectorAll(`img.preview`)
imageList.forEach(x => x.src = x.parentNode.parentNode.nextElementSibling.href)
document.head.insertAdjacentHTML(`beforeend`, ``)
} else if (getValue() === false) {
checkbox1.checked = true
checkbox2.checked = false
checkbox3.checked = false
} else {
checkbox1.checked = false
checkbox2.checked = true
checkbox3.checked = false
document.head.insertAdjacentHTML(`beforeend`, ``)
document.head.insertAdjacentHTML(`beforeend`, ``)
}
}
}
})()
================================================
FILE: temp/index.user.js
================================================
// ==UserScript==
// @name Yande.re 简体中文
// @namespace com.coderzhaoziwei.yandere
// @version 1.0.10
// @author Coder Zhao
// @description Y 站简体中文补丁| 显示隐藏作品 | 高清大图模式 | 界面布局优化 | 方向键翻页 | Simplified Chinese patch for Yande.re
// @modified 2021/5/7 01:12:31
// @license MIT
// @homepage https://greasyfork.org/zh-CN/scripts/421970
// @match https://yande.re/*
// @exclude https://yande.re/forum/*
// @match https://yande.in/*
// @match https://oreno.imouto.us/*
// @match https://konachan.com/*
// @supportURL https://github.com/coderzhaoziwei/yande-re-chinese-patch/issues
// @grant none
// ==/UserScript==
/******/ (() => { // webpackBootstrap
/******/ "use strict";
/******/ var __webpack_modules__ = ({
/***/ 798:
/***/ (() => {
;// CONCATENATED MODULE: ./tags.json
const tags_namespaceObject = JSON.parse('{"anal":"肛交","angel":"天使","animal_ears":"兽耳","anus":"肛门露出","areola":"乳晕","armor":"盔甲/装甲","artist_revision":"画师修改","ass":"臀部","ass_grab":"持股/捏臀","bandages":"绷带","bathing":"沐浴","bikini":"比基尼","bikini_armor":"比基尼装甲/轻薄盔甲","bikini_top":"比基尼乳罩","blood":"血腥","bloomers":"灯笼裤/宽松短裤","bodysuit":"紧身衣裤","bondage":"束缚","bottomless":"下身露出","bra":"乳罩","breast_grab":"握乳","breast_hold":"托乳","breasts":"乳","bunny_ears":"兔耳","bunny_girl":"兔女郎","buruma":"运动短裤","calendar":"日历","cameltoe":"阴户凸显","censored":"有码","cheerleader":"啦啦队队员","chibi":"Q版","chinadress":"旗袍","christmas":"圣诞","cleavage":"乳沟","cream":"奶油","crossdress":"变装","cum":"精液","dakimakura":"抱枕","digital_version":"数字版","dildo":"假阳具","disc_cover":"光盘封面","dress":"连衣裙","dress_shirt":"衬衫","elf":"精灵","erect_nipples":"乳尖","extreme_content":"极端","eyepatch":"眼罩","feet":"足","fellatio":"口交","fishnets":"鱼网袜","fixed":"修改","footjob":"足交","futanari":"扶她","game_cg":"游戏CG","gangbang":"乱交","garter":"袜带","garter_belt":"吊袜腰带","guitar":"吉他","gun":"枪炮","guro":"猎奇","halloween":"万圣节前夜","handjob":"打手枪","headphones":"耳机","heels":"高跟鞋","heterochromia":"虹膜异色","horns":"角","japanese_clothes":"日式服装","kimono":"和服","kitsune":"狐狸","landscape":"风景画","leotard":"紧身连衣裤","lingerie":"贴身内衣","loli":"萝莉","lolita_fashion":"洛丽塔","maid":"女仆","male":"男性","masturbation":"自摸/手淫","mecha":"机甲","megane":"眼镜","miko":"巫女","monochrome":"单色","naked":"裸体","naked_apron":"裸体围裙","naked_cape":"裸体披风","neko":"猫","nekomimi":"猫耳","nipples":"乳头","no_bra":"无乳罩","nopan":"无胖次","nurse":"护士","onsen":"温泉","open_shirt":"衬衫敞开","paizuri":"乳交","pajama":"睡衣","pantsu":"胖次","panty_pull":"胖次脱下","pantyhose":"吊带袜","partial_scan":"局部扫描","penis":"阴茎","pointy_ears":"尖耳朵","pubic_hair":"阴毛","pussy":"阴户","pussy_juice":"妹汁","school_swimsuit":"学校泳衣","see_through":"透视","seifuku":"制服","sex":"性交","sheets":"床单","shimapan":"条纹胖次","shirt_lift":"衬衫掀起","shota":"正太","sketch":"素描","skirt_lift":"裙摆掀起","stockings":"长筒袜","string_panties":"细绳胖次","sweater":"毛衣","swimsuits":"泳衣","sword":"刀剑","symmetrical_docking":"乳乳相接","tagme":"标签","tail":"兽尾","tan_lines":"日晒线","tattoo":"文身","tentacles":"触手","text":"文本","thighhighs":"过膝袜","thong":"丁字裤","topless":"上身露出","torn_clothes":"破衣","towel":"浴巾","transparent_png":"背景透明","trap":"伪娘","umbrella":"伞","uncensored":"无码","underboob":"南半球/下乳露出","undressing":"脱衣","uniform":"制服","vibrator":"跳蛋","waitress":"女侍","wallpaper":"壁纸","weapon":"武器","wedding_dress":"婚纱","wet":"湿身","wet_clothes":"湿衣","wings":"翅膀","witch":"女巫","yaoi":"蔷薇/男同","yukata":"浴衣","yuri":"百合"}');
;// CONCATENATED MODULE: ./style.css
/* harmony default export */ const style = ("/* 标签前缀 */\nli.tag-type-artist a:nth-child(4)::before {\n content: '[画师]';\n}\nli.tag-type-copyright a:nth-child(4)::before {\n content: '[原作]';\n}\nli.tag-type-character a:nth-child(4)::before {\n content: '[角色]';\n}\nli.tag-type-circle a:nth-child(4)::before {\n content: '[公司]';\n}\n\n/* 字体大小 */\nbody {\n font-size: 12px;\n padding: 12px 4px;\n}\n\n/* 标题居中 */\n#title {\n display: flex;\n justify-content: center;\n margin: 0 0 0 0 !important;\n}\n#site-title {\n display: flex !important;\n}\n#main-menu {\n padding: 0 !important;\n margin: 0 !important;\n display: flex !important;\n justify-content: center;\n}\n\n/* 通知居中 */\n.status-notice {\n text-align: center;\n}\n\n/* 图片区域 */\n#post-list {\n display: flex;\n flex-direction: row;\n}\n#post-list > .sidebar {\n width: auto;\n max-width: 200px;\n flex: 0 0 auto;\n}\n#post-list > .content {\n width: auto;\n flex: 0 1 auto;\n}\n\n#post-list-posts {\n display: flex !important;\n flex-wrap: wrap;\n justify-content: center;\n}\n#post-list-posts > li {\n width: auto !important;\n height: auto !important;\n margin: 0 8px 8px 0 !important; /* 图片区域间距 */\n border: 1px solid rgba(0, 0, 0, 0);\n}\n#post-list-posts > li.javascript-hide:not(.set-javascript-hide) {\n display: block !important;\n position: relative;\n}\n#post-list-posts > li.javascript-hide::after {\n content: \"\";\n position: absolute;\n width: 100%;\n height: 100%;\n top: 0;\n box-shadow: 0px 0px 12px rgb(255, 0, 0) inset;\n pointer-events: none;\n}\n#post-list-posts > li > .inner {\n width: auto !important;\n height: 150px !important;\n display: flex;\n align-items: center;\n}\n#post-list-posts > li > .inner > .thumb {\n height: auto;\n}\n#post-list-posts > li > .largeimg.directlink {\n height: 12px;\n font-size: 12px;\n line-height: 12px;\n padding: 0;\n margin: 2px 0 0 0;\n overflow: hidden;\n}\n\n/* 脚本添加的内容 */\n#script-addition {\n user-select: none;\n /* text-align: right; */\n /* font-weight: 100; */\n padding: 8px 12px;\n display: flex;\n}\n#script-addition > input {\n margin-left: 1em;\n}\n#script-notice-hd {\n margin-left: 0.5em;\n font-weight: bold;\n color: #ee8887;\n}\n\n/* 隐藏浏览器默认显示的滚动条 */\nbody::-webkit-scrollbar {\n display: none;\n width: 0px !important;\n}\n");
;// CONCATENATED MODULE: ./index.js
(function() {
const list = Array.from(document.getElementsByTagName('a'))
list.forEach(a => {
const href = a.getAttribute('href')
if (typeof href === 'string' && /^\/post\?tags=(\S+)$/.test(href)) {
const en = RegExp.$1
const cn = tags_namespaceObject[en]
if (cn) a.innerText = `[${cn}]${en.replace(/_/g, ' ')}`
}
})
})()
/**
* 创建 `)
} else if (getValue() === false) {
checkbox1.checked = true
checkbox2.checked = false
checkbox3.checked = false
} else {
checkbox1.checked = false
checkbox2.checked = true
checkbox3.checked = false
document.head.insertAdjacentHTML(`beforeend`, ``)
document.head.insertAdjacentHTML(`beforeend`, ``)
}
}
}
})()
/***/ })
/******/ });
/************************************************************************/
/******/
/******/ // startup
/******/ // Load entry module and return exports
/******/ // This entry module doesn't tell about it's top-level declarations so it can't be inlined
/******/ var __webpack_exports__ = {};
/******/ __webpack_modules__[798]();
/******/
/******/ })()
;
================================================
FILE: temp/webpack.config.js
================================================
const path = require('path')
const config = require('./package.json')
const { BannerPlugin } = require('webpack')
const banner = `
`
module.exports = {
mode: 'production',
entry: './index.js',
output: {
path: path.resolve(__dirname, ''),
filename: `index.user.js`,
},
module: {
rules: [
{ test: /\.css$/, use: './css_text_loader.js' },
],
},
plugins: [
new BannerPlugin({ banner, raw: true, entryOnly: true }),
],
optimization: {
minimize: true,
minimizer: [],
},
}