[
  {
    "path": ".editorconfig",
    "content": "# 编辑器插件 EditorConfig 的配置文件\n\nroot = true\n\n[*]\ncharset = utf-8                 # 字符集\nindent_style = space            # 缩进样式\nindent_size = 2                 # 缩进尺寸\ntrim_trailing_whitespace = true # 清理行尾空白\nend_of_line = lf                # 换行符\ninsert_final_newline = true     # 文末插入空白行\n"
  },
  {
    "path": ".gitignore",
    "content": "node_modules\nyarn-error.log\n.DS_Store\n"
  },
  {
    "path": ".vscode/custom.code-snippets",
    "content": "{\n  \"/* 单行注释 */\": {\n    \"scope\": \"javascript,typescript,css\",\n    \"prefix\": \"ll\",\n    \"body\": [\"/* ${1:comments} */\"],\n    \"description\": \"创建单行注释\",\n  },\n  \"/* 多行注释 */\": {\n    \"scope\": \"javascript,typescript\",\n    \"prefix\": \"lll\",\n    \"body\": [\"/**\", \" * ${1:comments}\", \" */\"],\n    \"description\": \"创建多行注释\",\n  },\n  \"console.log()\": {\n\t\t\"scope\": \"javascript,typescript\",\n\t\t\"prefix\": \"con\",\n\t\t\"body\": [\"console.log($1)\", \"\"],\n  },\n  \"导入模块\": {\n\t\t\"scope\": \"javascript,typescript\",\n\t\t\"prefix\": \"imp\",\n\t\t\"body\": [\"import $1 from '$1'\", \"\"],\n  },\n}\n"
  },
  {
    "path": "bundle/index.js",
    "content": "// ==UserScript==\n// @name         Yande.re 简体中文\n// @namespace    com.coderzhaoziwei.yandere\n// @version      2.1.47\n// @author       Coder Zhao coderzhaoziwei@outlook.com\n// @description  中文标签 | 界面优化 | 高清大图 | 键盘翻页 | 流体布局\n// @homepage     https://greasyfork.org/scripts/421970\n// @license      MIT\n// @match        https://yande.re/*\n// @exclude      https://yande.re/forum/*\n// @match        https://konachan.com/*\n// @exclude      https://konachan.com/forum/*\n// @match        https://konachan.net/*\n// @exclude      https://konachan.net/forum/*\n// @supportURL   https://github.com/coderzhaoziwei/yande-re-chinese-patch/issues\n// @grant        GM_download\n// ==/UserScript==\n\n/* eslint-env es2022 */\n/* global jQuery:readonly */\n/* global Vue:readonly */\n/* global Vuetify:readonly */\n/* global VueMasonry:readonly */\n\n(function () {\n  'use strict';\n\n  const initStyle = function() {\n    document.head.insertAdjacentHTML(\"beforeend\", `<style>[{ path: \"source/style/fix.css\" }]</style>`);\n  };\n\n  const initHotKey = function() {\n    window.addEventListener(\"keyup\", function(event) {\n      console.log('keyup:', event.key);\n      if (/^(TEXTAREA|INPUT|SELECT|BUTTON)$/.test(document.activeElement.tagName)) return\n      const prev = document.querySelector(\".pagination>.previous_page\") || jQuery(\"li:contains('Previous') a[href]\")[0];\n      if (prev && (event.key == \"ArrowLeft\" || event.key == \"a\" || event.key == \"A\")) {\n        prev.click();\n        return event.preventDefault()\n      }\n      const next = document.querySelector(\".pagination>.next_page\") || jQuery(\"li:contains('Next') a[href]\")[0];\n      if (next && (event.key == \"ArrowRight\" || event.key === \"d\" || event.key == \"D\")) {\n        next.click();\n        return event.preventDefault()\n      }\n      const show = document.querySelector(\"#png\") || document.querySelector(\"#highres\");\n      if (show && (event.key === \"s\" || event.key === \"S\")) {\n        show.click();\n        return event.preventDefault()\n      }\n      const where = jQuery(\"li:contains('Source:') a\")[0];\n      if (where && (event.key === \"w\" || event.key === \"W\")) {\n        where.click();\n        return event.preventDefault()\n      }\n    });\n    const sidebar = document.querySelector(\"#post-list > div.sidebar\") || document.querySelector(\"#post-view > div.sidebar\");\n    if (sidebar) {\n      sidebar.insertAdjacentHTML(\"beforeend\", \"<div>\" +\n        \"<h5>快捷键说明</h5>\" +\n        \"<div style='color: #ee8888'>上一页：A / ←</div>\" +\n        \"<div style='color: #ee8888'>下一页：D / →</div>\" +\n        \"<div style='color: #ee8888'>显示当前作品原图：S</div>\" +\n        \"<div style='color: #ee8888'>显示当前作品来源：W</div>\" +\n      \"</div>\");\n    }\n  };\n\n  class Post {\n    constructor(data) {\n      if (typeof data !== \"object\") data = {};\n      this.id = data.id || 0;\n      this.score = data.score || 0;\n      this.tags = data.tags || \"\";\n      this.source = data.source || \"\";\n      this.author = data.author || \"\";\n      this.creatorId = data.creator_id || 0;\n      this.createdAt = data.created_at || 0;\n      this.updatedAt = data.updated_at || 0;\n      this.rating = data.rating || \"s\";\n      this.fileUrl = data.file_url || \"\";\n      this.fileExt = data.file_ext || \"\";\n      this.fileSize = data.file_size || 0;\n      this.width = data.width || 0;\n      this.height = data.height || 0;\n      this.jpegUrl = data.jpeg_url || \"\";\n      this.jpegSize = data.jpeg_file_size || 0;\n      this.jpegWidth = data.jpeg_width || 0;\n      this.jpegHeight = data.jpeg_height || 0;\n      this.sampleUrl = data.sample_url;\n      this.sampleSize = data.sample_file_size || 0;\n      this.sampleWidth = data.sample_width || 0;\n      this.sampleHeight = data.sample_height || 0;\n      this.previewUrl = data.preview_url;\n      this.previewWidth = data.actual_preview_width || 0;\n      this.previewHeight = data.actual_preview_height || 0;\n      this.favorite = false;\n    }\n    get isRatingS() {\n      return this.rating === \"s\"\n    }\n    get isRatingQ() {\n      return this.rating === \"q\"\n    }\n    get isRatingE() {\n      return this.rating === \"e\"\n    }\n    get aspectRatio() {\n      return this.width / this.height\n    }\n    getSizeText(size) {\n      if (size > 1024 * 1024) {\n        return (size / (1024 * 1024)).toFixed(2) + \"MB\"\n      }\n      if (size > 1024) {\n        return (size / 1024).toFixed(2) + \"KB\"\n      }\n      return (size).toFixed(2) + \"B\"\n    }\n    get sampleSizeText() {\n      return this.getSizeText(this.sampleSize)\n    }\n    get sampleDownloadText() {\n      return `下载缩略图 ${this.sampleWidth}×${this.sampleHeight} [${this.sampleSizeText}]`\n    }\n    get sampleDownloadName() {\n      return `${location.hostname}.${this.id}.${this.sampleWidth}x${this.sampleHeight}`.replace(/\\./g, \"_\")\n    }\n    get jpegSizeText() {\n      return this.getSizeText(this.jpegSize)\n    }\n    get jpegDownloadText() {\n      return `下载高清图 ${this.jpegWidth}×${this.jpegHeight} [${this.jpegSizeText}]`\n    }\n    get jpegDownloadName() {\n      return `${location.hostname}.${this.id}.${this.jpegWidth}x${this.jpegHeight}`.replace(/\\./g, \"_\")\n    }\n    get fileSizeText() {\n      return this.getSizeText(this.fileSize)\n    }\n    get fileDownloadText() {\n      return `下载原文件 ${this.width}×${this.height} [${this.fileSizeText}] ${this.fileExt.toUpperCase()}`\n    }\n    get fileDownloadName() {\n      return `${location.hostname}.${this.id}.${this.width}x${this.height}`.replace(/\\./g, \"_\")\n    }\n    get createdTime() {\n      const date = new Date(this.createdAt * 1000);\n      return `${date.toLocaleDateString()} ${date.toLocaleTimeString(\"en-DE\")}`\n    }\n    get updatedTime() {\n      const date = new Date(this.updatedAt * 1000);\n      return `${date.toLocaleDateString()} ${date.toLocaleTimeString(\"en-DE\")}`\n    }\n    get sourceUrl() {\n      if (/^https:\\/\\/i\\.pximg\\.net\\/img-original\\/img\\/[\\d\\/]{19}\\/([\\d]{1,})_p[\\d]{1,}\\.(jpg|png)$/.test(this.source)) {\n        const pid = RegExp.$1;\n        return `https://pixiv.net/artworks/${pid}`\n      }\n      return this.source\n    }\n  }\n\n  const App = {\n    template: \"#app-template\",\n    data() {\n      return {\n        showDrawer: false,\n        showImageSelected: false,\n        showImageInfo: true,\n        showRatingQ: JSON.parse(localStorage.getItem(\"showRatingQ\") || \"true\"),\n        showRatingE: JSON.parse(localStorage.getItem(\"showRatingE\") || \"false\"),\n        imageList: [],\n        imageSelectedIndex: 0,\n        imageSelectedDetail: {},\n        params: new URLSearchParams(location.search),\n        requestState: false,\n        requestStop: false,\n        innerWidth: window.innerWidth,\n        innerHeight: window.innerHeight,\n        imageCountInRow: JSON.parse(localStorage.getItem(\"imageCountInRow\") || \"3\"),\n        imageQualityHigh: JSON.parse(localStorage.getItem(\"imageQualityHigh\") || \"false\"),\n        showFavoriteSuccess: false,\n      }\n    },\n    computed: {\n      isMobile() {\n        try {\n          return this.$vuetify.breakpoint.mobile\n        } catch(error) {\n          return false\n        }\n      },\n      title() {\n        return `${this.imageList.length} Posts`\n      },\n      version() {\n        return GM_info.script.version\n      },\n      imageSelected() {\n        return this.imageList[this.imageSelectedIndex] || new Post()\n      },\n      imageSelectedWidth() {\n        const width = parseInt(Math.min(this.innerWidth * 0.9, this.imageSelected.sampleWidth));\n        const height = Math.min(this.innerHeight * 0.9, this.imageSelected.sampleHeight);\n        const width2 = parseInt(height * this.imageSelected.aspectRatio);\n        return Math.min(width, width2)\n      },\n      imageSelectedHeight() {\n        const width = Math.min(this.innerWidth * 0.9, this.imageSelected.sampleWidth);\n        const height = parseInt(Math.min(this.innerHeight * 0.9, this.imageSelected.sampleHeight));\n        const height2 = parseInt(width / this.imageSelected.aspectRatio);\n        return Math.min(height, height2)\n      },\n    },\n    watch: {\n      showRatingQ(value) {\n        localStorage.setItem(\"showRatingQ\", JSON.stringify(value));\n      },\n      showRatingE(value) {\n        localStorage.setItem(\"showRatingE\", JSON.stringify(value));\n      },\n      imageCountInRow(value) {\n        localStorage.setItem(\"imageCountInRow\", JSON.stringify(value));\n      },\n      imageQualityHigh(value) {\n        localStorage.setItem(\"imageQualityHigh\", JSON.stringify(value));\n      },\n      showFavoriteSuccess(value) {\n        console.log('showFavoriteSuccess: ', value);\n      },\n      showImageSelected(value) {\n        if (!value) {\n          this.imageSelectedDetail = {};\n          return\n        }\n        this.getPostDetail(this.imageSelected.id).then(res => {\n          if (!res) return\n          this.imageSelectedDetail = res;\n        });\n      }\n    },\n    methods: {\n      async request() {\n        this.requestState = true;\n        const url = location.origin + location.pathname + \".json?\" + this.params.toString();\n        const response = await new Promise(resolve => {\n          console.log(url);\n          jQuery.get(url, data => resolve(data));\n        });\n        if (response instanceof Array && response.length > 0) {\n          window.history.pushState(\"\", \"\", location.pathname + \"?\" + this.params.toString());\n          response.forEach(item => this.imageList.push(new Post(item)));\n          const page = Number(this.params.get(\"page\")) || 1;\n          this.params.set(\"page\", page + 1);\n          setTimeout(() => (this.requestState = false), 1000);\n        } else {\n          this.requestStop = true;\n        }\n      },\n      download(src, filename) {\n        const match = src.match(/[.](?<extension>png|jpg|jpeg)$/);\n        if (match) {\n          const extension = match.groups.extension;\n          GM_download(src, filename + \".\" + extension);\n        } else {\n          GM_download(src, filename);\n        }\n      },\n      onFavorite(id) {\n        $.ajax({\n          method: 'POST',\n          url: \"https://yande.re/post/vote.json\",\n          beforeSend: xhr => xhr.setRequestHeader('x-csrf-token', window.csrfToken),\n          data: { id, score: 3 },\n          success: data => {\n            if (data.success === true) {\n              this.imageList[this.imageSelectedIndex].favorite = true;\n              this.imageSelectedDetail.favorite = true;\n            }\n          },\n        });\n      },\n      async getPostDetail(id) {\n        try {\n          if (!id) return\n          const response = await fetch(`/post.json?api_version=2&tags=id:${id}&include_tags=1&include_votes=1`);\n          const result = await response.json();\n          return {\n            favorite: result.votes[id] == 3,\n            artist: Object.keys(result.tags).find(k => result.tags[k] == 'artist')\n          }\n        } catch (error) {\n          console.log('getPostDetail error:', error);\n        }\n      }\n    },\n    mounted() {\n      const timeInterval = setInterval(() => {\n        if (this.requestStop === true) {\n          clearInterval(timeInterval);\n          return\n        }\n        const scrollTop = document.documentElement.scrollTop;\n        const scrollHeight = document.documentElement.scrollHeight;\n        const height = window.innerHeight;\n        if (scrollTop + height >= scrollHeight * 0.75) {\n          if (this.requestState === false) {\n            this.request();\n          }\n        }\n      }, 1000);\n      window.addEventListener(\"resize\", () => {\n        this.innerWidth = window.innerWidth;\n        this.innerHeight = window.innerHeight;\n      });\n    },\n  };\n\n  async function enterBrowseMode() {\n    function getScript(url) {\n      return new Promise(resolve => jQuery.getScript(url, () => resolve()))\n    }\n    await getScript(\"https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.min.js\");\n    await getScript(\"https://cdn.jsdelivr.net/npm/vuetify@2.5.0/dist/vuetify.min.js\");\n    await getScript(\"https://cdn.jsdelivr.net/npm/vue-masonry-css@1.0.3/dist/vue-masonry.min.js\");\n    await getScript(\"https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js\");\n    window.csrfToken = jQuery('[name=\"csrf-token\"]').attr('content');\n    document.head.innerHTML = `[{ path: \"source/html/head.html\" }]`;\n    document.body.innerHTML = `[{ path: \"source/html/body.html\" }]`;\n    Vue.use(VueMasonry);\n    new Vue({\n      vuetify: new Vuetify({\n        theme: { dark: true },\n      }),\n      render: h => h(App)\n    }).$mount(\"#app\");\n  }\n\n  const onChangeLeftBar = function() {\n    const value = Boolean(document.getElementById(\"showLeftBar\").selectedIndex);\n    localStorage.setItem(\"showLeftBar\", JSON.stringify(value));\n    const element = document.querySelector(\"#post-list > .sidebar\");\n    element.setAttribute(\"show-left-bar\", value);\n    console.log(\"showLeftBar\", value);\n  };\n  const onChangeRatingE = function() {\n    const value = Boolean(document.getElementById(\"showRatingE\").selectedIndex);\n    localStorage.setItem(\"showRatingE\", JSON.stringify(value));\n    const elementList = document.querySelectorAll(\".javascript-hide\");\n    elementList.forEach(element => element.setAttribute(\"show-rating-e\", value));\n    console.log(\"showRatingE\", value);\n  };\n  const onChangeImageHD = function() {\n    const index = document.getElementById(\"showImageHD\").selectedIndex;\n    const elementList = document.querySelectorAll(\"#post-list-posts > li > .inner\");\n    elementList.forEach(element => element.setAttribute(\"show-image-hd\", index));\n    localStorage.setItem(\"showImageHD\", JSON.stringify(index));\n    console.log(\"showImageHD\", index);\n  };\n  let taskArray = [];\n  let maxLoadingSampleNum = 4;\n  let doLoadSampleUrl = () => {\n    let loadingNum = 0;\n    let loadSampleUrl = () => {\n      if (taskArray.length == 0) return\n      loadingNum++;\n      let { element, sampleUrl } = taskArray.shift();\n      element.onerror = () => {\n        element.src = sampleUrl;\n      };\n      element.onload = () => {\n        loadingNum--;\n      };\n      element.src = sampleUrl;\n    };\n    setInterval(() => {\n      if (taskArray.length == 0) return\n      let needloadNum = maxLoadingSampleNum - loadingNum;\n      while (needloadNum--) {\n        loadSampleUrl();\n      }\n    }, 1000);\n  };\n  const initOptions = function() {\n    if (/^\\/user\\/show\\/[\\d]{1,}/.test(location.pathname)) return\n    if (document.getElementById(\"post-list-posts\") === null) return\n    document.getElementById(\"post-list-posts\").insertAdjacentHTML(\"beforebegin\", `[{ path: \"source/html/options.html\" }]`);\n    const imageList = document.querySelectorAll(\"img.preview\");\n    const samples = JSON.parse(localStorage.getItem(\"sample_urls\"));\n    imageList.forEach(element => {\n      if (/\\/post\\/show\\/([\\d]{1,})/.test(element.nextElementSibling.innerText)) {\n        const id = RegExp.$1;\n        const sampleUrl = samples[id];\n        if (sampleUrl !== undefined) {\n          element.src = sampleUrl;\n        }\n      }\n    });\n    doLoadSampleUrl();\n    document.getElementById(\"showLeftBar\").addEventListener(\"change\", onChangeLeftBar);\n    document.getElementById(\"showRatingE\").addEventListener(\"change\", onChangeRatingE);\n    document.getElementById(\"showImageHD\").addEventListener(\"change\", onChangeImageHD);\n    const showLeftBar = JSON.parse(localStorage.getItem(\"showLeftBar\") || \"true\");\n    const showRatingE = JSON.parse(localStorage.getItem(\"showRatingE\") || \"true\");\n    const showImageHD = JSON.parse(localStorage.getItem(\"showImageHD\") || \"0\");\n    document.getElementById(\"showLeftBar\").selectedIndex = showLeftBar;\n    document.getElementById(\"showRatingE\").selectedIndex = showRatingE;\n    document.getElementById(\"showImageHD\").selectedIndex = showImageHD;\n    onChangeLeftBar();\n    onChangeRatingE();\n    onChangeImageHD();\n    document.getElementById(\"enterBrowseMode\").addEventListener(\"click\", enterBrowseMode);\n  };\n\n  const tags = [{ path: \"source/data/tags.json\" }];\n  const menus = [{ path: \"source/data/menus.json\" }];\n  const footers = [{ path: \"source/data/footers.json\" }];\n  const translateTags = function() {\n    const elementList = Array.from(document.getElementsByTagName(\"a\"));\n    elementList.forEach(element => {\n      const href = element.getAttribute(\"href\");\n      if (typeof href === \"string\" && /^\\/post\\?tags=(\\S+)$/.test(href)) {\n        const en = RegExp.$1;\n        const cn = tags[en];\n        if (cn) {\n          element.innerText = `[${cn}]${en.replace(/_/g, \" \")}`;\n        }\n      }\n    });\n  };\n  const translateMenus = function() {\n    const mainMenuList = Array.from(document.querySelectorAll(\"#main-menu>ul>li>a\"));\n    const subMenuList = Array.from(document.querySelectorAll(\"ul.submenu>li>a\"));\n    const elementList = [...mainMenuList, ...subMenuList];\n    elementList.forEach(element => {\n      if (element.getAttribute(\"href\") === \"#\") return\n      const en = element.innerText;\n      const cn = menus[en];\n      if (cn) {\n        element.innerText = cn;\n      }\n    });\n  };\n  const translateNotice = function() {\n    const elementList = Array.from(document.querySelectorAll(\".status-notice\"));\n    elementList.forEach(element => {\n      console.log(element.innerHTML);\n      element.innerHTML = element.innerHTML\n        .replace(/^[\\s]+This image has been resized. Click on the /, \"这张图片已经被压缩，单击侧边栏中的\")\n        .replace(/View larger version/, \"显示高清图\")\n        .replace(/ link in the sidebar for a high-quality version./, \"可以获取更高质量的版本。\")\n        .replace(/Hide this message<\\/a>\\./, \"不再提醒</a>\")\n        .replace(/This post belongs to a /, \"这张图片从属于一个\")\n        .replace(/parent post<\\/a>\\./, \"相关父作品</a>。\")\n        .replace(/This post has /, \"这张图片从属于一个\")\n        .replace(/child posts<\\/a>\\. \\(post #/, \"作品集</a>。相关子作品：\")\n        .replace(/a child post<\\/a>\\. \\(post #/, \"作品集</a>。相关子作品：\")\n        .replace(/<\\/a>, <a /, \"</a> | <a \")\n        .replace(/<\\/a>\\)/, \"</a>\");\n    });\n  };\n  const translateButtons = function() {\n    [\n      ['#highres-show', 'View larger version', '显示高清图'],\n      ['#highres', 'Download larger version', '下载高清图'],\n      ['#png', 'Download PNG', '下载 PNG 图'],\n      ['li#add-to-favs>a', 'Add to favorites', '添加收藏'],\n      ['li#set-avatar>a', 'Set avatar', '设置头像'],\n      ['h4>a.js-posts-show-edit-tab', 'Edit', '编辑'],\n      ['h4>a.js-posts-show-comments-tab', 'Respond', '评论'],\n      ['.pagination>.previous_page', '← Previous', '上一页'],\n      ['.pagination>.next_page', 'Next →', '下一页'],\n    ].forEach(data => {\n      const [selector, en, cn] = data;\n      const element = document.querySelector(selector);\n      if (element) {\n        element.innerText = element.innerText.replace(en, cn);\n      }\n    });\n  };\n  const translateFooters = function() {\n    const elementList = Array.from(document.querySelectorAll('#subnavbar>li>a'));\n    elementList.forEach(element => {\n      const en = element.innerText;\n      const cn = footers[en];\n      if (cn) {\n        element.innerText = cn;\n      }\n    });\n  };\n  const initTranslate = function() {\n    translateTags();\n    translateMenus();\n    translateNotice();\n    translateButtons();\n    translateFooters();\n  };\n\n  jQuery(document).ready(function() {\n    initStyle();\n    initHotKey();\n    initOptions();\n    initTranslate();\n    if (document.cookie.includes('locale=zh_CN') === false) {\n      document.cookie = \"locale=zh_CN\";\n      location.href = location.href;\n    }\n  });\n\n}());\n"
  },
  {
    "path": "bundle/index.user.js",
    "content": "// ==UserScript==\n// @name         Yande.re 简体中文\n// @namespace    com.coderzhaoziwei.yandere\n// @version      2.1.47\n// @author       Coder Zhao coderzhaoziwei@outlook.com\n// @description  中文标签 | 界面优化 | 高清大图 | 键盘翻页 | 流体布局\n// @homepage     https://greasyfork.org/scripts/421970\n// @license      MIT\n// @match        https://yande.re/*\n// @exclude      https://yande.re/forum/*\n// @match        https://konachan.com/*\n// @exclude      https://konachan.com/forum/*\n// @match        https://konachan.net/*\n// @exclude      https://konachan.net/forum/*\n// @supportURL   https://github.com/coderzhaoziwei/yande-re-chinese-patch/issues\n// @grant        GM_download\n// ==/UserScript==\n\n/* eslint-env es2022 */\n/* global jQuery:readonly */\n/* global Vue:readonly */\n/* global Vuetify:readonly */\n/* global VueMasonry:readonly */\n\n(function () {\n  'use strict';\n\n  const initStyle = function() {\n    document.head.insertAdjacentHTML(\"beforeend\", `<style>\nbody {\n  font-size: 12px;\n  padding: 0 0.5rem;\n}\nbody::-webkit-scrollbar {\n  display: none;\n  width: 0px !important;\n}\n/* 标题居中 */\ndiv#header {\n  margin: 0;\n}\ndiv#header > div#title {\n  display: flex;\n  place-content: center;\n  margin: 0 !important;\n  height: fit-content;\n}\ndiv#header > div#title > h2#site-title {\n  display: flex !important;\n  flex-direction: column;\n}\ndiv#header > div#title > h2#site-title > span {\n  font-size: 12px;\n  font-weight: normal;\n  text-align: right;\n}\ndiv#header > div#main-menu {\n  padding: 0 !important;\n  margin: 0 !important;\n  display: flex !important;\n  justify-content: center;\n  font-size: 14px;\n  line-height: 2rem;\n  height: 2rem;\n}\ndiv#header > div#main-menu > ul {\n  margin: 0;\n}\n/* 通知 */\n.status-notice {\n  text-align: center;\n}\n/* 标签前缀 */\nli.tag-type-artist a[href^=\"/post\"]:not(.no-browser-link)::before {\n  content: \"[画师]\";\n}\nli.tag-type-copyright a[href^=\"/post\"]:not(.no-browser-link)::before {\n  content: \"[原作]\";\n}\nli.tag-type-character a[href^=\"/post\"]:not(.no-browser-link)::before {\n  content: \"[角色]\";\n}\nli.tag-type-circle a[href^=\"/post\"]:not(.no-browser-link)::before {\n  content: \"[公司]\";\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: 1 1 auto;\n}\n#post-list > div.lsidebar {\n  display: none;\n}\nul#post-list-posts {\n  display: flex;\n  flex-wrap: wrap;\n  gap: 0.5rem;\n  place-content: center;\n  place-items: center;\n}\nul#post-list-posts > li {\n  width: fit-content !important;\n  height: 100%;\n  margin: 0 !important;\n  border: none;\n}\nul#post-list-posts > li > div.inner {\n  width: auto !important;\n  height: fit-content !important;\n}\nul#post-list-posts > li > a.directlink {\n  font-size: 12px;\n  height: 12px;\n  line-height: 12px;\n  margin: 0;\n  padding: 0;\n  overflow: hidden;\n  background: rgb(16, 16, 16);\n}\nul#post-list-posts > li > a.directlink > span.directlink-res {\n  display: inline;\n}\nul#post-list-posts > li > a.directlink > span.directlink-info {\n  display: none;\n}\nul#post-list-posts > li > div.inner > a.thumb {\n  height: auto;\n}\nul#post-list-posts > li > div.inner > a.thumb > img.preview {\n  margin: 0 !important; /* @konachan */\n  border: none;\n}\n/* 分页器 */\ndiv#paginator {\n  padding: 0;\n}\ndiv#paginator > div.pagination {\n  line-height: 2rem;\n}\n/* 页脚 */\n#content > div:nth-child(2) > div.sidebar {\n  display: none;\n}\n#content div.footer {\n  font-size: 14px;\n  margin: 1rem;\n}\n\n/* show-left-bar */\n.sidebar[show-left-bar=false] {\n  display: none !important;\n}\n/* show-rating-e */\n.javascript-hide[show-rating-e=true] {\n  display: block !important;\n  position: relative;\n}\n.javascript-hide[show-rating-e=true]::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/* show-image-hd */\n#post-list-posts > li > .inner[show-image-hd=\"1\"] {\n  zoom: 2;\n}\n#post-list-posts > li > .inner[show-image-hd=\"2\"] {\n  zoom: 3;\n}\n#post-list-posts > li > .inner[show-image-hd=\"3\"] {\n  zoom: 4;\n}\n</style>`);\n  };\n\n  const initHotKey = function() {\n    window.addEventListener(\"keyup\", function(event) {\n      console.log('keyup:', event.key);\n      if (/^(TEXTAREA|INPUT|SELECT|BUTTON)$/.test(document.activeElement.tagName)) return\n      const prev = document.querySelector(\".pagination>.previous_page\") || jQuery(\"li:contains('Previous') a[href]\")[0];\n      if (prev && (event.key == \"ArrowLeft\" || event.key == \"a\" || event.key == \"A\")) {\n        prev.click();\n        return event.preventDefault()\n      }\n      const next = document.querySelector(\".pagination>.next_page\") || jQuery(\"li:contains('Next') a[href]\")[0];\n      if (next && (event.key == \"ArrowRight\" || event.key === \"d\" || event.key == \"D\")) {\n        next.click();\n        return event.preventDefault()\n      }\n      const show = document.querySelector(\"#png\") || document.querySelector(\"#highres\");\n      if (show && (event.key === \"s\" || event.key === \"S\")) {\n        show.click();\n        return event.preventDefault()\n      }\n      const where = jQuery(\"li:contains('Source:') a\")[0];\n      if (where && (event.key === \"w\" || event.key === \"W\")) {\n        where.click();\n        return event.preventDefault()\n      }\n    });\n    const sidebar = document.querySelector(\"#post-list > div.sidebar\") || document.querySelector(\"#post-view > div.sidebar\");\n    if (sidebar) {\n      sidebar.insertAdjacentHTML(\"beforeend\", \"<div>\" +\n        \"<h5>快捷键说明</h5>\" +\n        \"<div style='color: #ee8888'>上一页：A / ←</div>\" +\n        \"<div style='color: #ee8888'>下一页：D / →</div>\" +\n        \"<div style='color: #ee8888'>显示当前作品原图：S</div>\" +\n        \"<div style='color: #ee8888'>显示当前作品来源：W</div>\" +\n      \"</div>\");\n    }\n  };\n\n  class Post {\n    constructor(data) {\n      if (typeof data !== \"object\") data = {};\n      this.id = data.id || 0;\n      this.score = data.score || 0;\n      this.tags = data.tags || \"\";\n      this.source = data.source || \"\";\n      this.author = data.author || \"\";\n      this.creatorId = data.creator_id || 0;\n      this.createdAt = data.created_at || 0;\n      this.updatedAt = data.updated_at || 0;\n      this.rating = data.rating || \"s\";\n      this.fileUrl = data.file_url || \"\";\n      this.fileExt = data.file_ext || \"\";\n      this.fileSize = data.file_size || 0;\n      this.width = data.width || 0;\n      this.height = data.height || 0;\n      this.jpegUrl = data.jpeg_url || \"\";\n      this.jpegSize = data.jpeg_file_size || 0;\n      this.jpegWidth = data.jpeg_width || 0;\n      this.jpegHeight = data.jpeg_height || 0;\n      this.sampleUrl = data.sample_url;\n      this.sampleSize = data.sample_file_size || 0;\n      this.sampleWidth = data.sample_width || 0;\n      this.sampleHeight = data.sample_height || 0;\n      this.previewUrl = data.preview_url;\n      this.previewWidth = data.actual_preview_width || 0;\n      this.previewHeight = data.actual_preview_height || 0;\n      this.favorite = false;\n    }\n    get isRatingS() {\n      return this.rating === \"s\"\n    }\n    get isRatingQ() {\n      return this.rating === \"q\"\n    }\n    get isRatingE() {\n      return this.rating === \"e\"\n    }\n    get aspectRatio() {\n      return this.width / this.height\n    }\n    getSizeText(size) {\n      if (size > 1024 * 1024) {\n        return (size / (1024 * 1024)).toFixed(2) + \"MB\"\n      }\n      if (size > 1024) {\n        return (size / 1024).toFixed(2) + \"KB\"\n      }\n      return (size).toFixed(2) + \"B\"\n    }\n    get sampleSizeText() {\n      return this.getSizeText(this.sampleSize)\n    }\n    get sampleDownloadText() {\n      return `下载缩略图 ${this.sampleWidth}×${this.sampleHeight} [${this.sampleSizeText}]`\n    }\n    get sampleDownloadName() {\n      return `${location.hostname}.${this.id}.${this.sampleWidth}x${this.sampleHeight}`.replace(/\\./g, \"_\")\n    }\n    get jpegSizeText() {\n      return this.getSizeText(this.jpegSize)\n    }\n    get jpegDownloadText() {\n      return `下载高清图 ${this.jpegWidth}×${this.jpegHeight} [${this.jpegSizeText}]`\n    }\n    get jpegDownloadName() {\n      return `${location.hostname}.${this.id}.${this.jpegWidth}x${this.jpegHeight}`.replace(/\\./g, \"_\")\n    }\n    get fileSizeText() {\n      return this.getSizeText(this.fileSize)\n    }\n    get fileDownloadText() {\n      return `下载原文件 ${this.width}×${this.height} [${this.fileSizeText}] ${this.fileExt.toUpperCase()}`\n    }\n    get fileDownloadName() {\n      return `${location.hostname}.${this.id}.${this.width}x${this.height}`.replace(/\\./g, \"_\")\n    }\n    get createdTime() {\n      const date = new Date(this.createdAt * 1000);\n      return `${date.toLocaleDateString()} ${date.toLocaleTimeString(\"en-DE\")}`\n    }\n    get updatedTime() {\n      const date = new Date(this.updatedAt * 1000);\n      return `${date.toLocaleDateString()} ${date.toLocaleTimeString(\"en-DE\")}`\n    }\n    get sourceUrl() {\n      if (/^https:\\/\\/i\\.pximg\\.net\\/img-original\\/img\\/[\\d\\/]{19}\\/([\\d]{1,})_p[\\d]{1,}\\.(jpg|png)$/.test(this.source)) {\n        const pid = RegExp.$1;\n        return `https://pixiv.net/artworks/${pid}`\n      }\n      return this.source\n    }\n  }\n\n  const App = {\n    template: \"#app-template\",\n    data() {\n      return {\n        showDrawer: false,\n        showImageSelected: false,\n        showImageInfo: true,\n        showRatingQ: JSON.parse(localStorage.getItem(\"showRatingQ\") || \"true\"),\n        showRatingE: JSON.parse(localStorage.getItem(\"showRatingE\") || \"false\"),\n        imageList: [],\n        imageSelectedIndex: 0,\n        imageSelectedDetail: {},\n        params: new URLSearchParams(location.search),\n        requestState: false,\n        requestStop: false,\n        innerWidth: window.innerWidth,\n        innerHeight: window.innerHeight,\n        imageCountInRow: JSON.parse(localStorage.getItem(\"imageCountInRow\") || \"3\"),\n        imageQualityHigh: JSON.parse(localStorage.getItem(\"imageQualityHigh\") || \"false\"),\n        showFavoriteSuccess: false,\n      }\n    },\n    computed: {\n      isMobile() {\n        try {\n          return this.$vuetify.breakpoint.mobile\n        } catch(error) {\n          return false\n        }\n      },\n      title() {\n        return `${this.imageList.length} Posts`\n      },\n      version() {\n        return GM_info.script.version\n      },\n      imageSelected() {\n        return this.imageList[this.imageSelectedIndex] || new Post()\n      },\n      imageSelectedWidth() {\n        const width = parseInt(Math.min(this.innerWidth * 0.9, this.imageSelected.sampleWidth));\n        const height = Math.min(this.innerHeight * 0.9, this.imageSelected.sampleHeight);\n        const width2 = parseInt(height * this.imageSelected.aspectRatio);\n        return Math.min(width, width2)\n      },\n      imageSelectedHeight() {\n        const width = Math.min(this.innerWidth * 0.9, this.imageSelected.sampleWidth);\n        const height = parseInt(Math.min(this.innerHeight * 0.9, this.imageSelected.sampleHeight));\n        const height2 = parseInt(width / this.imageSelected.aspectRatio);\n        return Math.min(height, height2)\n      },\n    },\n    watch: {\n      showRatingQ(value) {\n        localStorage.setItem(\"showRatingQ\", JSON.stringify(value));\n      },\n      showRatingE(value) {\n        localStorage.setItem(\"showRatingE\", JSON.stringify(value));\n      },\n      imageCountInRow(value) {\n        localStorage.setItem(\"imageCountInRow\", JSON.stringify(value));\n      },\n      imageQualityHigh(value) {\n        localStorage.setItem(\"imageQualityHigh\", JSON.stringify(value));\n      },\n      showFavoriteSuccess(value) {\n        console.log('showFavoriteSuccess: ', value);\n      },\n      showImageSelected(value) {\n        if (!value) {\n          this.imageSelectedDetail = {};\n          return\n        }\n        this.getPostDetail(this.imageSelected.id).then(res => {\n          if (!res) return\n          this.imageSelectedDetail = res;\n        });\n      }\n    },\n    methods: {\n      async request() {\n        this.requestState = true;\n        const url = location.origin + location.pathname + \".json?\" + this.params.toString();\n        const response = await new Promise(resolve => {\n          console.log(url);\n          jQuery.get(url, data => resolve(data));\n        });\n        if (response instanceof Array && response.length > 0) {\n          window.history.pushState(\"\", \"\", location.pathname + \"?\" + this.params.toString());\n          response.forEach(item => this.imageList.push(new Post(item)));\n          const page = Number(this.params.get(\"page\")) || 1;\n          this.params.set(\"page\", page + 1);\n          setTimeout(() => (this.requestState = false), 1000);\n        } else {\n          this.requestStop = true;\n        }\n      },\n      download(src, filename) {\n        const match = src.match(/[.](?<extension>png|jpg|jpeg)$/);\n        if (match) {\n          const extension = match.groups.extension;\n          GM_download(src, filename + \".\" + extension);\n        } else {\n          GM_download(src, filename);\n        }\n      },\n      onFavorite(id) {\n        $.ajax({\n          method: 'POST',\n          url: \"https://yande.re/post/vote.json\",\n          beforeSend: xhr => xhr.setRequestHeader('x-csrf-token', window.csrfToken),\n          data: { id, score: 3 },\n          success: data => {\n            if (data.success === true) {\n              this.imageList[this.imageSelectedIndex].favorite = true;\n              this.imageSelectedDetail.favorite = true;\n            }\n          },\n        });\n      },\n      async getPostDetail(id) {\n        try {\n          if (!id) return\n          const response = await fetch(`/post.json?api_version=2&tags=id:${id}&include_tags=1&include_votes=1`);\n          const result = await response.json();\n          return {\n            favorite: result.votes[id] == 3,\n            artist: Object.keys(result.tags).find(k => result.tags[k] == 'artist')\n          }\n        } catch (error) {\n          console.log('getPostDetail error:', error);\n        }\n      }\n    },\n    mounted() {\n      const timeInterval = setInterval(() => {\n        if (this.requestStop === true) {\n          clearInterval(timeInterval);\n          return\n        }\n        const scrollTop = document.documentElement.scrollTop;\n        const scrollHeight = document.documentElement.scrollHeight;\n        const height = window.innerHeight;\n        if (scrollTop + height >= scrollHeight * 0.75) {\n          if (this.requestState === false) {\n            this.request();\n          }\n        }\n      }, 1000);\n      window.addEventListener(\"resize\", () => {\n        this.innerWidth = window.innerWidth;\n        this.innerHeight = window.innerHeight;\n      });\n    },\n  };\n\n  async function enterBrowseMode() {\n    function getScript(url) {\n      return new Promise(resolve => jQuery.getScript(url, () => resolve()))\n    }\n    await getScript(\"https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.min.js\");\n    await getScript(\"https://cdn.jsdelivr.net/npm/vuetify@2.5.0/dist/vuetify.min.js\");\n    await getScript(\"https://cdn.jsdelivr.net/npm/vue-masonry-css@1.0.3/dist/vue-masonry.min.js\");\n    await getScript(\"https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js\");\n    window.csrfToken = jQuery('[name=\"csrf-token\"]').attr('content');\n    document.head.innerHTML = `\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui\">\n<title>Yande.re 简体中文</title>\n<link rel=\"stylesheet\" href=\"https://cdn.jsdelivr.net/gh/necolas/normalize.css/normalize.css\">\n<link rel=\"stylesheet\" href=\"https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900\">\n<link rel=\"stylesheet\" href=\"https://cdn.jsdelivr.net/npm/@mdi/font@5.9.55/css/materialdesignicons.css\">\n<link rel=\"stylesheet\" href=\"https://cdn.jsdelivr.net/npm/vuetify@2.5.0/dist/vuetify.min.css\">\n<style>\n::-webkit-scrollbar {\n  display: none;\n  width: 0px !important;\n}\n</style>\n`;\n    document.body.innerHTML = `\n<div id=\"app\"></div>\n\n<script type=\"text/template\" id=\"app-template\">\n<v-app>\n\n  <v-app-bar app dense>\n    <v-app-bar-nav-icon :x-small=\"isMobile\" @click=\"showDrawer=!showDrawer\"></v-app-bar-nav-icon>\n    <v-toolbar-title :style=\"isMobile ? 'font-size: 12px;' : ''\" v-text=\"title\"></v-toolbar-title>\n    <!-- 设置分级制度 -->\n    <v-menu offset-y>\n      <template v-slot:activator=\"{ on, attrs }\">\n        <v-btn :x-small=\"isMobile\" class=\"white--text ml-2\" dark v-bind=\"attrs\" v-on=\"on\">\n          S{{ showRatingQ ? 'Q' : '' }}{{ showRatingE ? 'E' : '' }}\n        </v-btn>\n      </template>\n      <v-list dense>\n        <v-list-item dense>\n          <v-list-item-title style=\"cursor: pointer;\" @click=\"showRatingQ = !showRatingQ;\">\n            {{ showRatingQ ? '隐藏 Q 级内容' : '显示 Q 级内容' }}\n          </v-list-item-title>\n        </v-list-item>\n        <v-list-item dense>\n          <v-list-item-title style=\"cursor: pointer;\" @click=\"showRatingE = !showRatingE;\">\n            {{ showRatingE ? '隐藏 E 级内容' : '显示 E 级内容' }}\n          </v-list-item-title>\n        </v-list-item>\n      </v-list>\n    </v-menu>\n    <!-- 设置图片质量 -->\n    <v-menu offset-y>\n      <template v-slot:activator=\"{ on, attrs }\">\n        <v-btn :x-small=\"isMobile\" class=\"white--text ml-2\" dark v-bind=\"attrs\" v-on=\"on\">{{ imageQualityHigh ? 'HD' : '速' }}</v-btn>\n      </template>\n      <v-list dense>\n        <v-list-item dense>\n          <v-list-item-title style=\"cursor: pointer;\" @click=\"imageQualityHigh = false;\">\n            图片质量：速览\n          </v-list-item-title>\n        </v-list-item>\n        <v-list-item dense>\n          <v-list-item-title style=\"cursor: pointer;\" @click=\"imageQualityHigh = true;\">\n            图片质量：高清\n          </v-list-item-title>\n        </v-list-item>\n      </v-list>\n    </v-menu>\n    <!-- 设置每行几张 -->\n    <v-menu offset-y>\n      <template v-slot:activator=\"{ on, attrs }\">\n        <v-btn :x-small=\"isMobile\" class=\"white--text ml-2\" dark v-bind=\"attrs\" v-on=\"on\">{{imageCountInRow}}列</v-btn>\n      </template>\n      <v-list dense>\n        <v-list-item dense v-for=\"number in [1, 2, 3, 4, 5, 6, 8, 10, 12, 14, 16, 20]\" :key=\"number\">\n          <v-list-item-title style=\"cursor: pointer;\" @click=\"imageCountInRow = number;\">\n            {{ number }}列\n          </v-list-item-title>\n        </v-list-item>\n      </v-list>\n    </v-menu>\n\n    <v-spacer></v-spacer>\n    <v-btn\n      :style=\"isMobile ? 'flex: 0 1 auto; overflow: hidden;' : ''\" :x-small=\"isMobile\"\n      text v-text=\"'v' + version\" color=\"#ffffff\" disabled>\n    </v-btn>\n  </v-app-bar>\n\n  <v-navigation-drawer v-model=\"showDrawer\" app temporary>\n    <v-list-item>\n      <v-list-item-content>\n        <v-list-item-title class=\"title\">Yande.re 简体中文</v-list-item-title>\n        <v-list-item-subtitle>浏览器脚本程序</v-list-item-subtitle>\n      </v-list-item-content>\n    </v-list-item>\n\n    <v-divider></v-divider>\n\n    <v-list dense nav>\n      <v-list-item-content>\n        <v-list-item-title class=\"title\">设置</v-list-item-title>\n        <v-list-item-subtitle></v-list-item-subtitle>\n      </v-list-item-content>\n      <!-- s -->\n      <v-list-item link>\n        <v-list-item-icon class=\"mr-2\">\n          <v-icon>mdi-check</v-icon>\n        </v-list-item-icon>\n        <v-list-item-content>\n          <v-list-item-title>显示 S 分级内容</v-list-item-title>\n          <v-list-item-subtitle>S(safe) 安全的全年龄内容</v-list-item-subtitle>\n        </v-list-item-content>\n      </v-list-item>\n      <!-- q -->\n      <v-list-item link @click=\"showRatingQ=!showRatingQ;\">\n        <v-list-item-icon class=\"mr-2\">\n          <v-icon v-text=\"showRatingQ ? 'mdi-check' : 'mdi-close'\"></v-icon>\n        </v-list-item-icon>\n        <v-list-item-content>\n          <v-list-item-title v-text=\"showRatingQ ? '显示 Q 分级内容' : '隐藏 Q 分级内容'\"></v-list-item-title>\n          <v-list-item-subtitle>Q(questionable) 疑似的成人内容</v-list-item-subtitle>\n        </v-list-item-content>\n      </v-list-item>\n      <!-- e -->\n      <v-list-item link @click=\"showRatingE=!showRatingE;\">\n        <v-list-item-icon class=\"mr-2\">\n          <v-icon v-text=\"showRatingE ? 'mdi-check' : 'mdi-close'\"></v-icon>\n        </v-list-item-icon>\n        <v-list-item-content>\n          <v-list-item-title v-text=\"showRatingE ? '显示 E 分级内容' : '隐藏 E 分级内容'\"></v-list-item-title>\n          <v-list-item-subtitle>E(explicit) 明确的成人内容</v-list-item-subtitle>\n        </v-list-item-content>\n      </v-list-item>\n    </v-list>\n\n    <v-divider></v-divider>\n\n    <v-list dense nav>\n      <v-list-item-content>\n        <v-list-item-title class=\"title\">关于</v-list-item-title>\n        <v-list-item-subtitle></v-list-item-subtitle>\n      </v-list-item-content>\n      <v-list-item link @click=\"window.open('https://github.com/coderzhaoziwei/yande-re-chinese-patch/blob/main/readme.md')\">\n        <v-list-item-icon class=\"mr-2\"><v-icon>mdi-file-document-outline</v-icon></v-list-item-icon>\n        <v-list-item-content>\n          <v-list-item-title>简介</v-list-item-title>\n          <v-list-item-subtitle>说明文档 / 功能介绍</v-list-item-subtitle>\n        </v-list-item-content>\n      </v-list-item>\n      <v-list-item link @click=\"window.open('https://github.com/coderzhaoziwei/yande-re-chinese-patch/issues')\">\n        <v-list-item-icon class=\"mr-2\"><v-icon>mdi-github</v-icon></v-list-item-icon>\n        <v-list-item-content>\n          <v-list-item-title>反馈</v-list-item-title>\n          <v-list-item-subtitle>发现错误 / 提出建议</v-list-item-subtitle>\n        </v-list-item-content>\n      </v-list-item>\n      <v-list-item link @click=\"window.open('https://github.com/coderzhaoziwei/yande-re-chinese-patch')\">\n        <v-list-item-icon class=\"mr-2\"><v-icon>mdi-star</v-icon></v-list-item-icon>\n        <v-list-item-content>\n          <v-list-item-title>Github</v-list-item-title>\n          <v-list-item-subtitle>觉得好用就 Star 支持一下</v-list-item-subtitle>\n        </v-list-item-content>\n      </v-list-item>\n      <v-list-item link>\n        <v-list-item-icon class=\"mr-2\"><v-icon>mdi-google-controller</v-icon></v-list-item-icon>\n        <v-list-item-content>\n          <v-list-item-title>QQ</v-list-item-title>\n          <v-list-item-subtitle>3158492760</v-list-item-subtitle>\n        </v-list-item-content>\n      </v-list-item>\n      <v-list-item link>\n        <v-list-item-icon class=\"mr-2\"><v-icon>mdi-email</v-icon></v-list-item-icon>\n        <v-list-item-content>\n          <v-list-item-title>邮箱</v-list-item-title>\n          <v-list-item-subtitle>coderzhaoziwei@outlook.com</v-list-item-subtitle>\n        </v-list-item-content>\n      </v-list-item>\n    </v-list>\n  </v-navigation-drawer>\n\n  <v-main app>\n    <v-container class=\"pa-2\" fluid>\n      <masonry ref=\"masonry\" :cols=\"imageCountInRow\" gutter=\"8px\" :key=\"imageCountInRow\">\n        <v-card class=\"mb-2\" v-for=\"(image, index) in imageList\" :key=\"index\">\n          <v-img\n            :src=\"\n              image.isRatingS || (image.isRatingQ && showRatingQ) || (image.isRatingE && showRatingE)\n                ? (imageQualityHigh ? image.sampleUrl : image.previewUrl) : ''\n            \"\n            :aspect-ratio=\"image.aspectRatio\"\n            @click=\"if(image.isRatingS||(image.isRatingQ && showRatingQ)||(image.isRatingE && showRatingE)){imageSelectedIndex=index;showImageSelected=true;}\"\n            @click.middle=\"imageSelectedIndex = index; window.open('/post/show/' + imageSelected.id)\"\n          >\n            <template v-slot:placeholder>\n              <v-row v-if=\"image.isRatingS||(image.isRatingQ && showRatingQ)||(image.isRatingE && showRatingE)\"\n                class=\"fill-height ma-0\" align=\"center\" justify=\"center\"\n              >\n                <v-progress-circular indeterminate color=\"#ee8888\"></v-progress-circular>\n              </v-row>\n            </template>\n            <v-row\n              v-if=\"(image.isRatingS||(image.isRatingQ && showRatingQ)||(image.isRatingE && showRatingE))===false\"\n              class=\"fill-height ma-0 text-h5\" align=\"center\" justify=\"center\"\n              style=\"color:#ee8888;\"\n              v-text=\"image.rating.toUpperCase()\"\n            ></v-row>\n          </v-img>\n        </v-card>\n      </masonry>\n\n      <div class=\"d-flex justify-center\">\n        <v-btn\n          :disabled=\"requestState===false\"\n          color=\"#ee8888\" text\n          v-text=\"requestStop ? '下面没有了...' : requestState ? '正在加载中...' : ''\"\n        ></v-btn>\n      </div>\n\n      <v-dialog v-model=\"showImageSelected\" :width=\"imageSelectedWidth\" :height=\"imageSelectedHeight\">\n        <v-img\n          :src=\"imageSelected.sampleUrl\"\n          :lazy-src=\"imageSelected.previewUrl\"\n          @click=\"showImageInfo = !showImageInfo;\"\n        >\n          <div\n            :style=\"showImageInfo\n              ? 'display: flex; flex-direction: column; height: 100%; padding: 4px; grid-gap: 4px;'\n              : 'display: none !important;'\"\n          >\n            <div style=\"height: 100%; flex: 1 1 auto;\"></div>\n\n            <div style=\"display: flex; flex-direction: column; grid-gap: 4px;\">\n              <v-chip style=\"width: fit-content;\" color=\"#009ff088\" text-color=\"#ffffff\" small\n                v-text=\"imageSelected.sampleDownloadText\"\n                @click.stop=\"download(imageSelected.sampleUrl, imageSelected.sampleDownloadName)\"\n              ></v-chip>\n              <v-chip style=\"width: fit-content;\" color=\"#009ff088\" text-color=\"#ffffff\" small\n                v-if=\"imageSelected.jpegSize !== 0\"\n                v-text=\"imageSelected.jpegDownloadText\"\n                @click.stop=\"download(imageSelected.jpegUrl, imageSelected.jpegDownloadName)\"\n              ></v-chip>\n              <v-chip style=\"width: fit-content;\" color=\"#009ff088\" text-color=\"#ffffff\" small\n                v-text=\"imageSelected.fileDownloadText\"\n                @click.stop=\"download(imageSelected.fileUrl, imageSelected.fileDownloadName)\"\n              ></v-chip>\n            </div>\n            <div style=\"display: flex; grid-gap: 4px; flex-wrap: wrap;\">\n              <v-chip\n                style=\"width: fit-content;\" color=\"#ee888888\" text-color=\"#ffffff\" small\n                v-text=\"imageSelected.id + ' ' + imageSelected.rating.toUpperCase()\" @click.stop\n              ></v-chip>\n              <v-chip class=\"mr-1\" style=\"width: fit-content;\" color=\"#009ff088\" text-color=\"#ffffff\" small\n                v-if=\"imageSelectedDetail.artist\"\n                @click.stop=\"window.open('/post?tags='+imageSelectedDetail.artist)\"\n              >画师 {{imageSelectedDetail.artist}}</v-chip>\n              <v-chip class=\"mr-1\" style=\"width: fit-content;\" color=\"#009ff088\" text-color=\"#ffffff\" small\n                v-if=\"imageSelected.sourceUrl !== ''\"\n                v-text=\"'来源链接'\"\n                @click.stop=\"window.open(imageSelected.sourceUrl)\"\n              ></v-chip>\n              <v-chip class=\"mr-1\" style=\"width: fit-content;\" color=\"#009ff088\" text-color=\"#ffffff\" small\n                v-text=\"'本站链接'\"\n                @click.stop=\"window.open('/post/show/' + imageSelected.id)\"\n              ></v-chip>\n              <v-chip class=\"mr-1\" style=\"width: fit-content;\" text-color=\"#ffffff\" small\n                :color=\"imageSelectedDetail.favorite ? '#00900088' : '#009ff088'\"\n                v-text=\"imageSelectedDetail.favorite ? '已收藏' : '添加收藏'\"\n                @click.stop=\"imageSelectedDetail.favorite ? (void 0) : onFavorite(imageSelected.id)\"\n              ></v-chip>\n            </div>\n          </div>\n        </v-img>\n      </v-dialog>\n    </v-container>\n  </v-main>\n</v-app>\n</script>\n`;\n    Vue.use(VueMasonry);\n    new Vue({\n      vuetify: new Vuetify({\n        theme: { dark: true },\n      }),\n      render: h => h(App)\n    }).$mount(\"#app\");\n  }\n\n  const onChangeLeftBar = function() {\n    const value = Boolean(document.getElementById(\"showLeftBar\").selectedIndex);\n    localStorage.setItem(\"showLeftBar\", JSON.stringify(value));\n    const element = document.querySelector(\"#post-list > .sidebar\");\n    element.setAttribute(\"show-left-bar\", value);\n    console.log(\"showLeftBar\", value);\n  };\n  const onChangeRatingE = function() {\n    const value = Boolean(document.getElementById(\"showRatingE\").selectedIndex);\n    localStorage.setItem(\"showRatingE\", JSON.stringify(value));\n    const elementList = document.querySelectorAll(\".javascript-hide\");\n    elementList.forEach(element => element.setAttribute(\"show-rating-e\", value));\n    console.log(\"showRatingE\", value);\n  };\n  const onChangeImageHD = function() {\n    const index = document.getElementById(\"showImageHD\").selectedIndex;\n    const elementList = document.querySelectorAll(\"#post-list-posts > li > .inner\");\n    elementList.forEach(element => element.setAttribute(\"show-image-hd\", index));\n    localStorage.setItem(\"showImageHD\", JSON.stringify(index));\n    console.log(\"showImageHD\", index);\n  };\n  let taskArray = [];\n  let maxLoadingSampleNum = 4;\n  let doLoadSampleUrl = () => {\n    let loadingNum = 0;\n    let loadSampleUrl = () => {\n      if (taskArray.length == 0) return\n      loadingNum++;\n      let { element, sampleUrl } = taskArray.shift();\n      element.onerror = () => {\n        element.src = sampleUrl;\n      };\n      element.onload = () => {\n        loadingNum--;\n      };\n      element.src = sampleUrl;\n    };\n    setInterval(() => {\n      if (taskArray.length == 0) return\n      let needloadNum = maxLoadingSampleNum - loadingNum;\n      while (needloadNum--) {\n        loadSampleUrl();\n      }\n    }, 1000);\n  };\n  const initOptions = function() {\n    if (/^\\/user\\/show\\/[\\d]{1,}/.test(location.pathname)) return\n    if (document.getElementById(\"post-list-posts\") === null) return\n    document.getElementById(\"post-list-posts\").insertAdjacentHTML(\"beforebegin\", `\n<div style=\"padding: 1rem; user-select: none; text-align: center;\">\n  <select id=\"showLeftBar\" style=\"height: 1.5rem; line-height: 1.5rem;\">\n    <option>隐藏左栏</option>\n    <option>显示左栏</option>\n  </select>\n  <select id=\"showRatingE\" style=\"height: 1.5rem; line-height: 1.5rem; margin-left: 0.25rem;\">\n    <option>隐藏默认</option>\n    <option>显示全部</option>\n  </select>\n  <select id=\"showImageHD\" style=\"height: 1.5rem; line-height: 1.5rem; margin-left: 0.25rem;\">\n    <option>默认尺寸</option>\n    <option>二倍尺寸</option>\n    <option>三倍尺寸</option>\n    <option>四倍尺寸</option>\n  </select>\n  <button id=\"enterBrowseMode\" style=\"margin-left: 0.25rem;\">进入浏览模式</button>\n</div>\n`);\n    const imageList = document.querySelectorAll(\"img.preview\");\n    const samples = JSON.parse(localStorage.getItem(\"sample_urls\"));\n    imageList.forEach(element => {\n      if (/\\/post\\/show\\/([\\d]{1,})/.test(element.nextElementSibling.innerText)) {\n        const id = RegExp.$1;\n        const sampleUrl = samples[id];\n        if (sampleUrl !== undefined) {\n          element.src = sampleUrl;\n        }\n      }\n    });\n    doLoadSampleUrl();\n    document.getElementById(\"showLeftBar\").addEventListener(\"change\", onChangeLeftBar);\n    document.getElementById(\"showRatingE\").addEventListener(\"change\", onChangeRatingE);\n    document.getElementById(\"showImageHD\").addEventListener(\"change\", onChangeImageHD);\n    const showLeftBar = JSON.parse(localStorage.getItem(\"showLeftBar\") || \"true\");\n    const showRatingE = JSON.parse(localStorage.getItem(\"showRatingE\") || \"true\");\n    const showImageHD = JSON.parse(localStorage.getItem(\"showImageHD\") || \"0\");\n    document.getElementById(\"showLeftBar\").selectedIndex = showLeftBar;\n    document.getElementById(\"showRatingE\").selectedIndex = showRatingE;\n    document.getElementById(\"showImageHD\").selectedIndex = showImageHD;\n    onChangeLeftBar();\n    onChangeRatingE();\n    onChangeImageHD();\n    document.getElementById(\"enterBrowseMode\").addEventListener(\"click\", enterBrowseMode);\n  };\n\n  const tags = {\n  \"4koma\": \"四格漫画\",\n  \"5-toubun_no_hanayome\": \"五等分的新娘\",\n  \"anal\": \"肛交\",\n  \"angel\": \"天使\",\n  \"angel_beats!\": \"Angel Beats!\",\n  \"animal_ears\": \"兽耳\",\n  \"anthropomorphization\": \"拟人化\",\n  \"anus\": \"肛门露出\",\n  \"areola\": \"乳晕\",\n  \"arknights\": \"明日方舟\",\n  \"armor\": \"盔甲/装甲\",\n  \"artist_revision\": \"画师修改\",\n  \"ass\": \"臀部\",\n  \"ass_grab\": \"持股/捏臀\",\n  \"atelier\": \"炼金工房系列\",\n  \"autographed\": \"亲笔签名\",\n  \"azur_lane\": \"碧蓝航线\",\n  \"bakemonogatari\": \"化物语\",\n  \"bandages\": \"绷带\",\n  \"bandaid\": \"创可贴/绷带\",\n  \"bang_dream!\": \"BanG Dream!\",\n  \"baseball\": \"棒球\",\n  \"basketball\": \"篮球\",\n  \"bathing\": \"沐浴\",\n  \"benghuai_xueyuan\": \"崩坏学园\",\n  \"bike_shorts\": \"自行车短裤\",\n  \"bikini\": \"比基尼\",\n  \"bikini_armor\": \"比基尼装甲/轻薄盔甲\",\n  \"bikini_top\": \"比基尼乳罩\",\n  \"black_rock_shooter\": \"黑岩射手\",\n  \"blood\": \"血腥\",\n  \"bloomers\": \"灯笼裤/宽松短裤\",\n  \"blue_archive\": \"碧蓝档案\",\n  \"bodysuit\": \"紧身衣裤\",\n  \"boku_wa_tomodachi_ga_sukunai\": \"我的朋友很少\",\n  \"bondage\": \"束缚\",\n  \"bottomless\": \"下身露出\",\n  \"bra\": \"乳罩\",\n  \"breast_grab\": \"握乳\",\n  \"breast_hold\": \"托乳\",\n  \"breasts\": \"乳\",\n  \"bukkake\": \"颜射\",\n  \"bunny_ears\": \"兔耳\",\n  \"bunny_girl\": \"兔女郎\",\n  \"buruma\": \"运动短裤\",\n  \"business_suit\": \"西装/职业服\",\n  \"calendar\": \"日历\",\n  \"cameltoe\": \"阴户凸显\",\n  \"card\": \"卡牌\",\n  \"card_captor_sakura\": \"魔卡少女樱\",\n  \"censored\": \"有码\",\n  \"cg\": \"CG/计算机动画\",\n  \"chainsaw\": \"电锯\",\n  \"character_design\": \"角色设计\",\n  \"cheerleader\": \"啦啦队队员\",\n  \"chibi\": \"Q版\",\n  \"chinadress\": \"旗袍\",\n  \"choujigen_game_neptune\": \"超次元游戏海王星\",\n  \"christmas\": \"圣诞\",\n  \"cleavage\": \"乳沟\",\n  \"code_geass\": \"反叛的鲁路修\",\n  \"condom\": \"避孕套\",\n  \"corset\": \"(束腰)紧身内衣\",\n  \"cosplay\": \"角色扮演\",\n  \"cream\": \"奶油\",\n  \"cropped\": \"裁剪图\",\n  \"crossdress\": \"变装\",\n  \"crossover\": \"作品联动/混合同人\",\n  \"cum\": \"精液\",\n  \"cunnilingus\": \"品玉/舔阴\",\n  \"dakimakura\": \"抱枕\",\n  \"darling_in_the_franxx\": \"DARLING in the FRANXX\",\n  \"date_a_live\": \"约会大作战\",\n  \"detexted\": \"去字图片\",\n  \"devil\": \"魔鬼/恶魔\",\n  \"digital_version\": \"数字版\",\n  \"dildo\": \"假阳具\",\n  \"disc_cover\": \"光盘封面\",\n  \"dress\": \"连衣裙\",\n  \"dress_shirt\": \"衬衫\",\n  \"duplicate\": \"重复图片\",\n  \"elf\": \"精灵\",\n  \"endcard\": \"片尾插图\",\n  \"erect_nipples\": \"乳尖\",\n  \"expression\": \"角色展示/立绘\",\n  \"extreme_content\": \"极端\",\n  \"eyepatch\": \"眼罩\",\n  \"fairy\": \"精灵/小精灵\",\n  \"fate/kaleid_liner_prisma_illya\": \"Fate/kaleid liner 魔法少女☆伊莉雅\",\n  \"feet\": \"足\",\n  \"fellatio\": \"口交\",\n  \"final_fantasy\": \"最终幻想\",\n  \"final_fantasy_vii\": \"最终幻想 VII\",\n  \"final_fantasy_xiv\": \"最终幻想 14\",\n  \"fingering\": \"指交\",\n  \"fire_emblem\": \"火焰纹章\",\n  \"fire_emblem_heroes\": \"火焰之纹章：英雄云集\",\n  \"fire_emblem_kakusei\": \"火焰之纹章：觉醒\",\n  \"fire_emblem_three_houses\": \"火焰之纹章：风花雪月\",\n  \"fishnets\": \"鱼网袜\",\n  \"fixed\": \"修改\",\n  \"footjob\": \"足交\",\n  \"fundoshi\": \"褌/兜裆布\",\n  \"futanari\": \"扶她\",\n  \"game_cg\": \"游戏CG\",\n  \"gangbang\": \"乱交\",\n  \"garter\": \"袜带\",\n  \"garter_belt\": \"吊袜腰带\",\n  \"genderswap\": \"性转\",\n  \"genshin_impact\": \"原神\",\n  \"girls_frontline\": \"少女前线\",\n  \"girls_und_panzer\": \"少女与战车\",\n  \"gochuumon_wa_usagi_desu_ka?\": \"请问您今天要来点兔子吗？\",\n  \"gothic_lolita\": \"哥特式洛丽塔\",\n  \"granblue_fantasy\": \"碧蓝幻想\",\n  \"guitar\": \"吉他\",\n  \"gun\": \"枪炮\",\n  \"gundam\": \"高达\",\n  \"guro\": \"猎奇\",\n  \"halloween\": \"万圣节前夜\",\n  \"handjob\": \"打手枪\",\n  \"headphones\": \"耳机\",\n  \"heels\": \"高跟鞋\",\n  \"heterochromia\": \"虹膜异色\",\n  \"hibike!_euphonium\": \"吹响吧！上低音号\",\n  \"highschool_dxd\": \"恶魔高校D×D\",\n  \"honkai_impact\": \"崩坏 3\",\n  \"horns\": \"角\",\n  \"index_page\": \"索引页面\",\n  \"infinite_stratos\": \"IS/无限斯特拉托斯\",\n  \"inumimi\": \"犬耳\",\n  \"japanese_clothes\": \"日式服装\",\n  \"k-on!\": \"轻音少女\",\n  \"kaguya-sama_wa_kokurasetai_~tensai-tachi_no_renai_zunousen~\": \"辉夜大小姐想让我告白～天才们的恋爱头脑战～\",\n  \"kantai_collection\": \"舰队 Collection\",\n  \"kemono_friends\": \"兽娘动物园\",\n  \"kimetsu_no_yaiba\": \"鬼灭之刃\",\n  \"kimono\": \"和服\",\n  \"kitsune\": \"狐狸\",\n  \"kobayashi-san_chi_no_maid_dragon\": \"小林家的龙女仆\",\n  \"kono_subarashii_sekai_ni_shukufuku_wo!\": \"为美好的世界献上祝福！\",\n  \"lactation\": \"泌乳\",\n  \"landscape\": \"风景画\",\n  \"league_of_legends\": \"英雄联盟\",\n  \"leotard\": \"紧身连衣裤\",\n  \"line_art\": \"线条画\",\n  \"lingerie\": \"贴身内衣\",\n  \"little_busters!\": \"Little Busters!\",\n  \"loli\": \"萝莉\",\n  \"lolita_fashion\": \"洛丽塔\",\n  \"love_live!_nijigasaki_high_school_idol_club\": \"Love Live! 虹咲学园学园偶像同好会\",\n  \"lucky_star\": \"幸运星\",\n  \"maebari\": \"前貼り/遮盖私处\",\n  \"mahou_shoujo_lyrical_nanoha\": \"魔法少女奈叶\",\n  \"mahou_shoujo_lyrical_nanoha_strikers\": \"魔法少女奈叶 StrikerS\",\n  \"maid\": \"女仆\",\n  \"male\": \"男性\",\n  \"masturbation\": \"自摸/手淫\",\n  \"mecha\": \"机甲\",\n  \"mecha_musume\": \"机甲娘\",\n  \"megane\": \"眼镜\",\n  \"megaten\": \"女神转生系列\",\n  \"mermaid\": \"美人鱼\",\n  \"miko\": \"巫女\",\n  \"monochrome\": \"单色\",\n  \"monster\": \"怪物\",\n  \"monster_girl\": \"怪物女孩\",\n  \"monster_musume_no_iru_nichijou\": \"魔物娘的相伴日常\",\n  \"naked\": \"裸体\",\n  \"naked_apron\": \"裸体围裙\",\n  \"naked_cape\": \"裸体披风\",\n  \"naked_ribbon\": \"裸体丝带\",\n  \"neko\": \"猫\",\n  \"nekomimi\": \"猫耳\",\n  \"neon_genesis_evangelion\": \"新世纪福音战士\",\n  \"nier_automata\": \"尼尔：自动人形\",\n  \"nijisanji\": \"彩虹社\",\n  \"ninja\": \"忍者\",\n  \"nipple_slip\": \"露点\",\n  \"nipples\": \"乳头\",\n  \"no_bra\": \"无乳罩\",\n  \"nopan\": \"无胖次\",\n  \"nun\": \"修女\",\n  \"nurse\": \"护士\",\n  \"official_watermark\": \"官方水印\",\n  \"onsen\": \"温泉\",\n  \"open_shirt\": \"衬衫敞开\",\n  \"ore_no_imouto_ga_konnani_kawaii_wake_ga_nai\": \"我的妹妹哪有这么可爱！\",\n  \"overalls\": \"工装连衣裤\",\n  \"overwatch\": \"守望先锋\",\n  \"paizuri\": \"乳交\",\n  \"pajama\": \"睡衣\",\n  \"panties\": \"内裤\",\n  \"pantsu\": \"胖次\",\n  \"panty_pull\": \"胖次脱下\",\n  \"pantyhose\": \"吊带袜\",\n  \"parody\": \"仿拟/谐拟\",\n  \"partial_scan\": \"局部扫描\",\n  \"pasties\": \"乳贴\",\n  \"pee\": \"尿尿\",\n  \"penguin\": \"企鹅\",\n  \"penis\": \"阴茎\",\n  \"photo\": \"照片/现实背景\",\n  \"photoshop\": \"PS 改图\",\n  \"pirate\": \"海盗\",\n  \"pointy_ears\": \"尖耳朵\",\n  \"pokemon\": \"精灵宝可梦\",\n  \"possible_duplicate\": \"可能重复\",\n  \"pregnant\": \"孕妇\",\n  \"pretty_cure\": \"光之美少女\",\n  \"princess_connect\": \"公主连结\",\n  \"princess_connect!_re:dive\": \"公主连结 Re:Dive\",\n  \"profile_page\": \"角色资料页\",\n  \"pubic_hair\": \"阴毛\",\n  \"puella_magi_madoka_magica\": \"魔法少女小圆\",\n  \"pussy\": \"阴户\",\n  \"pussy_juice\": \"妹汁\",\n  \"queen's_blade\": \"女王之刃\",\n  \"raw_scan\": \"扫描原图\",\n  \"re_zero_kara_hajimeru_isekai_seikatsu\": \"Re:从零开始的异世界生活\",\n  \"robe\": \"长袍/礼服/睡袍\",\n  \"saenai_heroine_no_sodatekata\": \"路人女主的养成方法\",\n  \"sailor_moon\": \"美少女战士\",\n  \"sake\": \"日本清酒\",\n  \"sample\": \"样品图\",\n  \"sarashi\": \"晒し/缠胸布\",\n  \"school_swimsuit\": \"学校泳衣\",\n  \"see_through\": \"透视\",\n  \"seifuku\": \"制服\",\n  \"selfie\": \"自拍\",\n  \"senran_kagura\": \"闪乱神乐\",\n  \"sex\": \"性交\",\n  \"sheets\": \"床单\",\n  \"shimapan\": \"条纹胖次\",\n  \"shirt_lift\": \"衬衫掀起\",\n  \"shota\": \"正太\",\n  \"silhouette\": \"剪影/暗色轮廓/体形\",\n  \"sketch\": \"素描\",\n  \"skirt_lift\": \"裙摆掀起\",\n  \"sling_bikini\": \"吊带比基尼\",\n  \"smoking\": \"吸烟\",\n  \"soccer\": \"足球\",\n  \"sono_bisque_doll_wa_koi_wo_suru\": \"更衣人偶坠入爱河\",\n  \"spy_x_family\": \"间谍过家家\",\n  \"ssss.gridman\": \"SSSS.古立特\",\n  \"stick_poster\": \"海报\",\n  \"stockings\": \"长筒袜\",\n  \"strike_witches\": \"强袭魔女\",\n  \"string_panties\": \"细绳胖次\",\n  \"summer_dress\": \"夏装\",\n  \"suzumiya_haruhi_no_yuuutsu\": \"凉宫春日的忧郁\",\n  \"sweater\": \"毛衣\",\n  \"swimsuits\": \"泳衣\",\n  \"sword\": \"刀剑\",\n  \"sword_art_online\": \"刀剑神域\",\n  \"symmetrical_docking\": \"乳乳相接\",\n  \"tagme\": \"标签\",\n  \"tail\": \"兽尾\",\n  \"tan_lines\": \"日晒线\",\n  \"tattoo\": \"文身\",\n  \"tennis\": \"网球\",\n  \"tentacles\": \"触手\",\n  \"text\": \"文本\",\n  \"the_idolm@ster\": \"偶像大师\",\n  \"the_idolm@ster_cinderella_girls\": \"偶像大师灰姑娘女孩\",\n  \"the_idolm@ster_million_live!\": \"偶像大师百万现场\",\n  \"the_idolm@ster_shiny_colors\": \"偶像大师闪耀色彩\",\n  \"thighhighs\": \"过膝袜\",\n  \"thong\": \"丁字裤\",\n  \"to_aru_kagaku_no_railgun\": \"某科学的超电磁炮\",\n  \"to_aru_majutsu_no_index\": \"魔法禁书目录\",\n  \"to_heart_(series)\": \"To Heart 系列\",\n  \"to_heart_2\": \"To Heart 2\",\n  \"to_love_ru\": \"出包王女\",\n  \"to_love_ru_darkness\": \"出包王女 Darkness\",\n  \"topless\": \"上身露出\",\n  \"torn_clothes\": \"破衣\",\n  \"touhou\": \"东方\",\n  \"towel\": \"浴巾\",\n  \"translated\": \"文字已翻译(英文)\",\n  \"transparent_png\": \"背景透明\",\n  \"trap\": \"伪娘\",\n  \"tribadism\": \"磨豆腐/交叉体位\",\n  \"tutorial\": \"教程\",\n  \"uma_musume_pretty_derby\": \"赛马娘\",\n  \"umbrella\": \"伞\",\n  \"uncensored\": \"无码\",\n  \"underboob\": \"南半球\",\n  \"underwear\": \"内衣\",\n  \"undressing\": \"脱衣\",\n  \"uniform\": \"制服\",\n  \"valentine\": \"情人节\",\n  \"vibrator\": \"跳蛋\",\n  \"wa_maid\": \"和风女仆\",\n  \"waitress\": \"女侍\",\n  \"wallpaper\": \"壁纸\",\n  \"wardrobe_malfunction\": \"走光\",\n  \"weapon\": \"武器\",\n  \"wedding_dress\": \"婚纱\",\n  \"wet\": \"湿身\",\n  \"wet_clothes\": \"湿衣\",\n  \"wings\": \"翅膀\",\n  \"witch\": \"女巫\",\n  \"xenoblade\": \"异度神剑\",\n  \"xenoblade_chronicles_2\": \"异度神剑 2\",\n  \"yahari_ore_no_seishun_lovecome_wa_machigatteiru.\": \"我的青春恋爱喜剧果然有问题\",\n  \"yaoi\": \"蔷薇/男同\",\n  \"yukata\": \"浴衣\",\n  \"yuri\": \"百合\",\n  \"zhanjianshaonv\": \"战舰少女\"\n};\n  const menus = \n{\n  \"My Account\": \"账户\",\n  \"Posts\": \"作品\",\n  \"Comments\": \"评论\",\n  \"Notes\": \"笔记\",\n  \"Artists\": \"画师\",\n  \"Tags\": \"标签\",\n  \"Forum\": \"论坛\",\n  \"Help\": \"帮助\",\n  \"More »\": \"更多>>\",\n  \"New Mail\": \"新消息\",\n  \"My Profile\": \"我的资料\",\n  \"My Mail\": \"我的消息\",\n  \"My Favorites\": \"我的收藏\",\n  \"Settings\": \"设置\",\n  \"Change Password\": \"修改密码\",\n  \"Logout\": \"退出登录\",\n  \"View Posts\": \"浏览作品\",\n  \"Search Posts\": \"搜索作品\",\n  \"Upload\": \"上传\",\n  \"Random\": \"随机浏览\",\n  \"Popular\": \"热门\",\n  \"Image Search\": \"搜索图片\",\n  \"History\": \"历史\",\n  \"View Comments\": \"浏览评论\",\n  \"Search Comments\": \"搜索评论\",\n  \"View Notes\": \"浏览笔记\",\n  \"Search Notes\": \"搜索笔记\",\n  \"View Artists\": \"浏览画师\",\n  \"Search Artists\": \"搜索画师\",\n  \"Create\": \"创建\",\n  \"View Tags\": \"浏览标签\",\n  \"Search Tags\": \"搜索标签\",\n  \"Aliases\": \"别名\",\n  \"Implications\": \"含义\",\n  \"View Pools\": \"浏览 Pools\",\n  \"Search Pools\": \"搜索 Pools\",\n  \"Create New Pool\": \"创建 Pool\",\n  \"View Wiki Index\": \"浏览 Wiki 主页\",\n  \"Search Wiki\": \"搜索 Wiki\",\n  \"Create New Page\": \"创建新页面\",\n  \"Mark All Read\": \"全部标记已读\"\n}\n;\n  const footers = \n{\n  \"List\": \"首页\",\n  \"Browse\": \"翻阅\",\n  \"Upload\": \"上传\",\n  \"Random\": \"随机\",\n  \"Popular\": \"热门\",\n  \"Image Search\": \"寻图\",\n  \"History\": \"历史\",\n  \"Help\": \"帮助\"\n}\n;\n  const translateTags = function() {\n    const elementList = Array.from(document.getElementsByTagName(\"a\"));\n    elementList.forEach(element => {\n      const href = element.getAttribute(\"href\");\n      if (typeof href === \"string\" && /^\\/post\\?tags=(\\S+)$/.test(href)) {\n        const en = RegExp.$1;\n        const cn = tags[en];\n        if (cn) {\n          element.innerText = `[${cn}]${en.replace(/_/g, \" \")}`;\n        }\n      }\n    });\n  };\n  const translateMenus = function() {\n    const mainMenuList = Array.from(document.querySelectorAll(\"#main-menu>ul>li>a\"));\n    const subMenuList = Array.from(document.querySelectorAll(\"ul.submenu>li>a\"));\n    const elementList = [...mainMenuList, ...subMenuList];\n    elementList.forEach(element => {\n      if (element.getAttribute(\"href\") === \"#\") return\n      const en = element.innerText;\n      const cn = menus[en];\n      if (cn) {\n        element.innerText = cn;\n      }\n    });\n  };\n  const translateNotice = function() {\n    const elementList = Array.from(document.querySelectorAll(\".status-notice\"));\n    elementList.forEach(element => {\n      console.log(element.innerHTML);\n      element.innerHTML = element.innerHTML\n        .replace(/^[\\s]+This image has been resized. Click on the /, \"这张图片已经被压缩，单击侧边栏中的\")\n        .replace(/View larger version/, \"显示高清图\")\n        .replace(/ link in the sidebar for a high-quality version./, \"可以获取更高质量的版本。\")\n        .replace(/Hide this message<\\/a>\\./, \"不再提醒</a>\")\n        .replace(/This post belongs to a /, \"这张图片从属于一个\")\n        .replace(/parent post<\\/a>\\./, \"相关父作品</a>。\")\n        .replace(/This post has /, \"这张图片从属于一个\")\n        .replace(/child posts<\\/a>\\. \\(post #/, \"作品集</a>。相关子作品：\")\n        .replace(/a child post<\\/a>\\. \\(post #/, \"作品集</a>。相关子作品：\")\n        .replace(/<\\/a>, <a /, \"</a> | <a \")\n        .replace(/<\\/a>\\)/, \"</a>\");\n    });\n  };\n  const translateButtons = function() {\n    [\n      ['#highres-show', 'View larger version', '显示高清图'],\n      ['#highres', 'Download larger version', '下载高清图'],\n      ['#png', 'Download PNG', '下载 PNG 图'],\n      ['li#add-to-favs>a', 'Add to favorites', '添加收藏'],\n      ['li#set-avatar>a', 'Set avatar', '设置头像'],\n      ['h4>a.js-posts-show-edit-tab', 'Edit', '编辑'],\n      ['h4>a.js-posts-show-comments-tab', 'Respond', '评论'],\n      ['.pagination>.previous_page', '← Previous', '上一页'],\n      ['.pagination>.next_page', 'Next →', '下一页'],\n    ].forEach(data => {\n      const [selector, en, cn] = data;\n      const element = document.querySelector(selector);\n      if (element) {\n        element.innerText = element.innerText.replace(en, cn);\n      }\n    });\n  };\n  const translateFooters = function() {\n    const elementList = Array.from(document.querySelectorAll('#subnavbar>li>a'));\n    elementList.forEach(element => {\n      const en = element.innerText;\n      const cn = footers[en];\n      if (cn) {\n        element.innerText = cn;\n      }\n    });\n  };\n  const initTranslate = function() {\n    translateTags();\n    translateMenus();\n    translateNotice();\n    translateButtons();\n    translateFooters();\n  };\n\n  jQuery(document).ready(function() {\n    initStyle();\n    initHotKey();\n    initOptions();\n    initTranslate();\n    if (document.cookie.includes('locale=zh_CN') === false) {\n      document.cookie = \"locale=zh_CN\";\n      location.href = location.href;\n    }\n  });\n\n}());\n"
  },
  {
    "path": "config/rollup.config.js",
    "content": "import { version } from \"../package.json\"\nimport cleanup from \"rollup-plugin-cleanup\"\nimport json from \"@rollup/plugin-json\"\n\nconst banner = `// ==UserScript==\n// @name         Yande.re 简体中文\n// @namespace    com.coderzhaoziwei.yandere\n// @version      ${ version }\n// @author       Coder Zhao coderzhaoziwei@outlook.com\n// @description  中文标签 | 界面优化 | 高清大图 | 键盘翻页 | 流体布局\n// @homepage     https://greasyfork.org/scripts/421970\n// @license      MIT\n// @match        https://yande.re/*\n// @exclude      https://yande.re/forum/*\n// @match        https://konachan.com/*\n// @exclude      https://konachan.com/forum/*\n// @match        https://konachan.net/*\n// @exclude      https://konachan.net/forum/*\n// @supportURL   https://github.com/coderzhaoziwei/yande-re-chinese-patch/issues\n// @grant        GM_download\n// ==/UserScript==\n\n/* eslint-env es2022 */\n/* global jQuery:readonly */\n/* global Vue:readonly */\n/* global Vuetify:readonly */\n/* global VueMasonry:readonly */\n`\n\nexport default {\n  input: \"source/index.js\",\n  output: {\n    file: \"bundle/index.js\",\n    format: \"iife\",\n    banner,\n  },\n  plugins: [ cleanup(), json() ],\n}\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"yande-re-chinese-patch\",\n  \"version\": \"2.1.47\",\n  \"author\": \"Coder Zhao\",\n  \"description\": \"Yande.re Chinese Patch | Y 站简体中文补丁\",\n  \"repository\": \"https://github.com/coderzhaoziwei/yande.re-chinese-patch.git\",\n  \"license\": \"MIT\",\n  \"scripts\": {\n    \"bundle\": \"sh script/bundle.sh\"\n  },\n  \"devDependencies\": {\n    \"@rollup/plugin-json\": \"^4.1.0\",\n    \"rollup\": \"^2.47.0\",\n    \"rollup-plugin-cleanup\": \"^3.2.1\"\n  }\n}\n"
  },
  {
    "path": "readme.md",
    "content": "![version][img-version]\n![license][img-license]\n![stars][img-stars]\n![cover][img-cover]\n\n<!-- omit in toc -->\n# 目录\n\n- [前言](#前言)\n- [预览](#预览)\n- [功能](#功能)\n  - [标签翻译](#标签翻译)\n  - [操作优化](#操作优化)\n  - [浏览模式](#浏览模式)\n- [安装](#安装)\n  - [安装浏览器插件](#安装浏览器插件)\n  - [安装脚本程序](#安装脚本程序)\n- [常见问题](#常见问题)\n  - [Q: 安卓手机如何安装 Tampermonkey？](#q-安卓手机如何安装-tampermonkey)\n- [相关链接](#相关链接)\n- [开源许可](#开源许可)\n- [附：标签翻译表](#附标签翻译表)\n\n# 前言\n\n最初，我在浏览 [yande.re 站](https://yande.re)（以下简称 Y 站）的时候，遇到了一些难懂的标签名。在使用搜索引擎多方查询之后，我才终于明白个别晦涩单词的含义，可是过了一段时间再次遇到，又忘记了。然后我就敲了一个脚本程序，自动遍历页面中的标签名，添加中文翻译。为了让与我有同样困扰的其他朋友节约时间，我将脚本程序发布到了脚本网站 [Greasy Fork](https://greasyfork.org/) 上。\n\n后来，有朋友提议添加更优化的操作方式，于是陆续增加了显示大图、键盘翻页等功能。再后来有一天，我躺在床上用手机登陆了 Y 站，网站无法适配移动端屏幕实在是太特么难受了，于是我就敲了响应式布局的浏览模式，手机可以自动加载图片资源，单屏一滑到底。\n\n终于，舒服了。\n\n- https://yande.re\n- ~~https://oreno.imouto.us （Y 站镜像，无需魔法上网）~~（已失效）\n- https://konachan.com （K 站已兼容）\n- https://konachan.net （K 站安全模式，.net 域名下默认隐藏成人内容）\n\n# 预览\n\n- 样式优化，高清图源，尺寸自选。\n\n![1](https://cdn.jsdelivr.net/gh/coderzhaoziwei/yande-re-chinese-patch/source/img/1.png)\n\n- 流体布局，自动加载，一屏到底。\n\n![2](https://cdn.jsdelivr.net/gh/coderzhaoziwei/yande-re-chinese-patch/source/img/2.png)\n\n- 单图预览，聚合详情，一键下载。\n\n![3](https://cdn.jsdelivr.net/gh/coderzhaoziwei/yande-re-chinese-patch/source/img/3.png)\n\n- 显隐自如，更多功能，欢迎体验。\n\n![4](https://cdn.jsdelivr.net/gh/coderzhaoziwei/yande-re-chinese-patch/source/img/4.png)\n\n# 功能\n\n## 标签翻译\n\n翻译了 Y 站出现频率较高的 100 多个标签，详细内容请查看最下方的标签翻译表。欢迎校正或补充。\n\n## 操作优化\n\n- 对于 Y 站默认隐藏的成人内容，提供了显示或者隐藏的选项。\n- 网页左侧的边栏，提供了显示或者隐藏的选项。\n- 图源默认自动替换为高清资源，并提供了 1 ~ 4 倍尺寸的选项。\n- 快捷键\n  - 上一页：A / ←\n  - 下一页：D / →\n  - 显示当前作品原图：S\n  - 显示当前作品来源：W\n\n## 浏览模式\n\n浏览任意图片列表时，可以进入浏览模式。\n\n# 安装\n\n## 安装浏览器插件\n\n首先你需要为你的浏览器安装一个用户脚本管理器，推荐使用插件 [Tampermonkey](https://www.tampermonkey.net/)。\n\n> 主流浏览器有 Chrome、Microsoft Edge、Firefox、Safari 等，如果你的浏览器无法安装 Tampermonkey，那么也就无法安装此脚本程序。\n\n## 安装脚本程序\n\n使用浏览器直接访问 [Greasy Fork - Yande.re 简体中文 - 主页](https://greasyfork.org/scripts/421970)，点击安装即可。\n\n如果你没有 Greasy Fork 的账号，访问以上链接可能会提示你：`此脚本不再在本网站上匿名可用。请登录并检查您的 Greasy Fork 账号设置。`\n\n因为此脚本程序涉及成人内容，所以在 Greasy Fork 站点必须登录才可以浏览或安装。如果你不想注册成为 Greasy Fork 的用户，可以访问成人脚本站点 [Sleasy Fork](https://sleazyfork.org/scripts/421970) 直接安装，或者直接获取[仓库文件](https://github.com/coderzhaoziwei/yande-re-chinese-patch/raw/main/index.user.js)来安装。\n\n# 常见问题\n\n## Q: 安卓手机如何安装 Tampermonkey？\n\n我推荐安卓 Yandex 浏览器，可以直接安装 Chrome 插件。当你发现谷歌市场的 Tampermonkey 显示不兼容时，点击 Yandex 菜单栏，切换为桌面模式即可。\n\n其他安卓浏览器也可以的，Firefox、Kiwi、Iceraven 等自行尝试。\n\n# 相关链接\n\n[Github 仓库](https://github.com/coderzhaoziwei/yande-re-chinese-patch) |\n[Greasy Fork 脚本主页](https://greasyfork.org/scripts/421970) |\n[封面原图 Yande#388833](https://yande.re/post/show/388833)\n\n# 开源许可\n\nMIT\n\n# 附：标签翻译表\n\n||English|简体中文|\n|:-:|:-|:-|\n|1|4koma|四格漫画|\n|2|5-toubun no hanayome|五等分的新娘|\n|3|anal|肛交|\n|4|angel|天使|\n|5|angel beats!|Angel Beats!|\n|6|animal ears|兽耳|\n|7|anthropomorphization|拟人化|\n|8|anus|肛门露出|\n|9|areola|乳晕|\n|10|arknights|明日方舟|\n|11|armor|盔甲/装甲|\n|12|artist revision|画师修改|\n|13|ass|臀部|\n|14|ass grab|持股/捏臀|\n|15|atelier|炼金工房系列|\n|16|autographed|亲笔签名|\n|17|azur lane|碧蓝航线|\n|18|bakemonogatari|化物语|\n|19|bandages|绷带|\n|20|bandaid|创可贴/绷带|\n|21|bang dream!|BanG Dream!|\n|22|baseball|棒球|\n|23|basketball|篮球|\n|24|bathing|沐浴|\n|25|benghuai xueyuan|崩坏学园|\n|26|bike shorts|自行车短裤|\n|27|bikini|比基尼|\n|28|bikini armor|比基尼装甲/轻薄盔甲|\n|29|bikini top|比基尼乳罩|\n|30|black rock shooter|黑岩射手|\n|31|blood|血腥|\n|32|bloomers|灯笼裤/宽松短裤|\n|33|blue archive|碧蓝档案|\n|34|bodysuit|紧身衣裤|\n|35|boku wa tomodachi ga sukunai|我的朋友很少|\n|36|bondage|束缚|\n|37|bottomless|下身露出|\n|38|bra|乳罩|\n|39|breast grab|握乳|\n|40|breast hold|托乳|\n|41|breasts|乳|\n|42|bukkake|颜射|\n|43|bunny ears|兔耳|\n|44|bunny girl|兔女郎|\n|45|buruma|运动短裤|\n|46|business suit|西装/职业服|\n|47|calendar|日历|\n|48|cameltoe|阴户凸显|\n|49|card|卡牌|\n|50|card captor sakura|魔卡少女樱|\n|51|censored|有码|\n|52|cg|CG/计算机动画|\n|53|chainsaw|电锯|\n|54|character design|角色设计|\n|55|cheerleader|啦啦队队员|\n|56|chibi|Q版|\n|57|chinadress|旗袍|\n|58|choujigen game neptune|超次元游戏海王星|\n|59|christmas|圣诞|\n|60|cleavage|乳沟|\n|61|code geass|反叛的鲁路修|\n|62|condom|避孕套|\n|63|corset|(束腰)紧身内衣|\n|64|cosplay|角色扮演|\n|65|cream|奶油|\n|66|cropped|裁剪图|\n|67|crossdress|变装|\n|68|crossover|作品联动/混合同人|\n|69|cum|精液|\n|70|cunnilingus|品玉/舔阴|\n|71|dakimakura|抱枕|\n|72|darling in the franxx|DARLING in the FRANXX|\n|73|date a live|约会大作战|\n|74|detexted|去字图片|\n|75|devil|魔鬼/恶魔|\n|76|digital version|数字版|\n|77|dildo|假阳具|\n|78|disc cover|光盘封面|\n|79|dress|连衣裙|\n|80|dress shirt|衬衫|\n|81|duplicate|重复图片|\n|82|elf|精灵|\n|83|endcard|片尾插图|\n|84|erect nipples|乳尖|\n|85|expression|角色展示/立绘|\n|86|extreme content|极端|\n|87|eyepatch|眼罩|\n|88|fairy|精灵/小精灵|\n|89|fate/kaleid liner prisma illya|Fate/kaleid liner 魔法少女☆伊莉雅|\n|90|feet|足|\n|91|fellatio|口交|\n|92|final fantasy|最终幻想|\n|93|final fantasy vii|最终幻想 VII|\n|94|final fantasy xiv|最终幻想 14|\n|95|fingering|指交|\n|96|fire emblem|火焰纹章|\n|97|fire emblem heroes|火焰之纹章：英雄云集|\n|98|fire emblem kakusei|火焰之纹章：觉醒|\n|99|fire emblem three houses|火焰之纹章：风花雪月|\n|100|fishnets|鱼网袜|\n|101|fixed|修改|\n|102|footjob|足交|\n|103|fundoshi|褌/兜裆布|\n|104|futanari|扶她|\n|105|game cg|游戏CG|\n|106|gangbang|乱交|\n|107|garter|袜带|\n|108|garter belt|吊袜腰带|\n|109|genderswap|性转|\n|110|genshin impact|原神|\n|111|girls frontline|少女前线|\n|112|girls und panzer|少女与战车|\n|113|gochuumon wa usagi desu ka?|请问您今天要来点兔子吗？|\n|114|gothic lolita|哥特式洛丽塔|\n|115|granblue fantasy|碧蓝幻想|\n|116|guitar|吉他|\n|117|gun|枪炮|\n|118|gundam|高达|\n|119|guro|猎奇|\n|120|halloween|万圣节前夜|\n|121|handjob|打手枪|\n|122|headphones|耳机|\n|123|heels|高跟鞋|\n|124|heterochromia|虹膜异色|\n|125|hibike! euphonium|吹响吧！上低音号|\n|126|highschool dxd|恶魔高校D×D|\n|127|honkai impact|崩坏 3|\n|128|horns|角|\n|129|index page|索引页面|\n|130|infinite stratos|IS/无限斯特拉托斯|\n|131|inumimi|犬耳|\n|132|japanese clothes|日式服装|\n|133|k-on!|轻音少女|\n|134|kaguya-sama wa kokurasetai ~tensai-tachi no renai zunousen~|辉夜大小姐想让我告白～天才们的恋爱头脑战～|\n|135|kantai collection|舰队 Collection|\n|136|kemono friends|兽娘动物园|\n|137|kimetsu no yaiba|鬼灭之刃|\n|138|kimono|和服|\n|139|kitsune|狐狸|\n|140|kobayashi-san chi no maid dragon|小林家的龙女仆|\n|141|kono subarashii sekai ni shukufuku wo!|为美好的世界献上祝福！|\n|142|lactation|泌乳|\n|143|landscape|风景画|\n|144|league of legends|英雄联盟|\n|145|leotard|紧身连衣裤|\n|146|line art|线条画|\n|147|lingerie|贴身内衣|\n|148|little busters!|Little Busters!|\n|149|loli|萝莉|\n|150|lolita fashion|洛丽塔|\n|151|love live! nijigasaki high school idol club|Love Live! 虹咲学园学园偶像同好会|\n|152|lucky star|幸运星|\n|153|maebari|前貼り/遮盖私处|\n|154|mahou shoujo lyrical nanoha|魔法少女奈叶|\n|155|mahou shoujo lyrical nanoha strikers|魔法少女奈叶 StrikerS|\n|156|maid|女仆|\n|157|male|男性|\n|158|masturbation|自摸/手淫|\n|159|mecha|机甲|\n|160|mecha musume|机甲娘|\n|161|megane|眼镜|\n|162|megaten|女神转生系列|\n|163|mermaid|美人鱼|\n|164|miko|巫女|\n|165|monochrome|单色|\n|166|monster|怪物|\n|167|monster girl|怪物女孩|\n|168|monster musume no iru nichijou|魔物娘的相伴日常|\n|169|naked|裸体|\n|170|naked apron|裸体围裙|\n|171|naked cape|裸体披风|\n|172|naked ribbon|裸体丝带|\n|173|neko|猫|\n|174|nekomimi|猫耳|\n|175|neon genesis evangelion|新世纪福音战士|\n|176|nier automata|尼尔：自动人形|\n|177|nijisanji|彩虹社|\n|178|ninja|忍者|\n|179|nipple slip|露点|\n|180|nipples|乳头|\n|181|no bra|无乳罩|\n|182|nopan|无胖次|\n|183|nun|修女|\n|184|nurse|护士|\n|185|official watermark|官方水印|\n|186|onsen|温泉|\n|187|open shirt|衬衫敞开|\n|188|ore no imouto ga konnani kawaii wake ga nai|我的妹妹哪有这么可爱！|\n|189|overalls|工装连衣裤|\n|190|overwatch|守望先锋|\n|191|paizuri|乳交|\n|192|pajama|睡衣|\n|193|panties|内裤|\n|194|pantsu|胖次|\n|195|panty pull|胖次脱下|\n|196|pantyhose|吊带袜|\n|197|parody|仿拟/谐拟|\n|198|partial scan|局部扫描|\n|199|pasties|乳贴|\n|200|pee|尿尿|\n|201|penguin|企鹅|\n|202|penis|阴茎|\n|203|photo|照片/现实背景|\n|204|photoshop|PS 改图|\n|205|pirate|海盗|\n|206|pointy ears|尖耳朵|\n|207|pokemon|精灵宝可梦|\n|208|possible duplicate|可能重复|\n|209|pregnant|孕妇|\n|210|pretty cure|光之美少女|\n|211|princess connect|公主连结|\n|212|princess connect! re:dive|公主连结 Re:Dive|\n|213|profile page|角色资料页|\n|214|pubic hair|阴毛|\n|215|puella magi madoka magica|魔法少女小圆|\n|216|pussy|阴户|\n|217|pussy juice|妹汁|\n|218|queen's blade|女王之刃|\n|219|raw scan|扫描原图|\n|220|re zero kara hajimeru isekai seikatsu|Re:从零开始的异世界生活|\n|221|robe|长袍/礼服/睡袍|\n|222|saenai heroine no sodatekata|路人女主的养成方法|\n|223|sailor moon|美少女战士|\n|224|sake|日本清酒|\n|225|sample|样品图|\n|226|sarashi|晒し/缠胸布|\n|227|school swimsuit|学校泳衣|\n|228|see through|透视|\n|229|seifuku|制服|\n|230|selfie|自拍|\n|231|senran kagura|闪乱神乐|\n|232|sex|性交|\n|233|sheets|床单|\n|234|shimapan|条纹胖次|\n|235|shirt lift|衬衫掀起|\n|236|shota|正太|\n|237|silhouette|剪影/暗色轮廓/体形|\n|238|sketch|素描|\n|239|skirt lift|裙摆掀起|\n|240|sling bikini|吊带比基尼|\n|241|smoking|吸烟|\n|242|soccer|足球|\n|243|sono bisque doll wa koi wo suru|更衣人偶坠入爱河|\n|244|spy x family|间谍过家家|\n|245|ssss.gridman|SSSS.古立特|\n|246|stick poster|海报|\n|247|stockings|长筒袜|\n|248|strike witches|强袭魔女|\n|249|string panties|细绳胖次|\n|250|summer dress|夏装|\n|251|suzumiya haruhi no yuuutsu|凉宫春日的忧郁|\n|252|sweater|毛衣|\n|253|swimsuits|泳衣|\n|254|sword|刀剑|\n|255|sword art online|刀剑神域|\n|256|symmetrical docking|乳乳相接|\n|257|tagme|标签|\n|258|tail|兽尾|\n|259|tan lines|日晒线|\n|260|tattoo|文身|\n|261|tennis|网球|\n|262|tentacles|触手|\n|263|text|文本|\n|264|the idolm@ster|偶像大师|\n|265|the idolm@ster cinderella girls|偶像大师灰姑娘女孩|\n|266|the idolm@ster million live!|偶像大师百万现场|\n|267|the idolm@ster shiny colors|偶像大师闪耀色彩|\n|268|thighhighs|过膝袜|\n|269|thong|丁字裤|\n|270|to aru kagaku no railgun|某科学的超电磁炮|\n|271|to aru majutsu no index|魔法禁书目录|\n|272|to heart (series)|To Heart 系列|\n|273|to heart 2|To Heart 2|\n|274|to love ru|出包王女|\n|275|to love ru darkness|出包王女 Darkness|\n|276|topless|上身露出|\n|277|torn clothes|破衣|\n|278|touhou|东方|\n|279|towel|浴巾|\n|280|translated|文字已翻译(英文)|\n|281|transparent png|背景透明|\n|282|trap|伪娘|\n|283|tribadism|磨豆腐/交叉体位|\n|284|tutorial|教程|\n|285|uma musume pretty derby|赛马娘|\n|286|umbrella|伞|\n|287|uncensored|无码|\n|288|underboob|南半球|\n|289|underwear|内衣|\n|290|undressing|脱衣|\n|291|uniform|制服|\n|292|valentine|情人节|\n|293|vibrator|跳蛋|\n|294|wa maid|和风女仆|\n|295|waitress|女侍|\n|296|wallpaper|壁纸|\n|297|wardrobe malfunction|走光|\n|298|weapon|武器|\n|299|wedding dress|婚纱|\n|300|wet|湿身|\n|301|wet clothes|湿衣|\n|302|wings|翅膀|\n|303|witch|女巫|\n|304|xenoblade|异度神剑|\n|305|xenoblade chronicles 2|异度神剑 2|\n|306|yahari ore no seishun lovecome wa machigatteiru.|我的青春恋爱喜剧果然有问题|\n|307|yaoi|蔷薇/男同|\n|308|yukata|浴衣|\n|309|yuri|百合|\n|310|zhanjianshaonv|战舰少女|\n\n[img-version]: https://img.shields.io/github/package-json/v/coderzhaoziwei/yande-re-chinese-patch?style=flat-square\n[img-license]: https://shields.io/badge/license-MIT-blue?style=flat-square\n[img-stars]: https://img.shields.io/github/stars/coderzhaoziwei/yande-re-chinese-patch?label=star&style=social\n[img-cover]: https://cdn.jsdelivr.net/gh/coderzhaoziwei/yande-re-chinese-patch/preview.png\n"
  },
  {
    "path": "readme_main.md",
    "content": "![version][img-version]\n![license][img-license]\n![stars][img-stars]\n![cover][img-cover]\n\n<!-- omit in toc -->\n# 目录\n\n- [前言](#前言)\n- [预览](#预览)\n- [功能](#功能)\n  - [标签翻译](#标签翻译)\n  - [操作优化](#操作优化)\n  - [浏览模式](#浏览模式)\n- [安装](#安装)\n  - [安装浏览器插件](#安装浏览器插件)\n  - [安装脚本程序](#安装脚本程序)\n- [常见问题](#常见问题)\n  - [Q: 安卓手机如何安装 Tampermonkey？](#q-安卓手机如何安装-tampermonkey)\n- [相关链接](#相关链接)\n- [开源许可](#开源许可)\n- [附：标签翻译表](#附标签翻译表)\n\n# 前言\n\n最初，我在浏览 [yande.re 站](https://yande.re)（以下简称 Y 站）的时候，遇到了一些难懂的标签名。在使用搜索引擎多方查询之后，我才终于明白个别晦涩单词的含义，可是过了一段时间再次遇到，又忘记了。然后我就敲了一个脚本程序，自动遍历页面中的标签名，添加中文翻译。为了让与我有同样困扰的其他朋友节约时间，我将脚本程序发布到了脚本网站 [Greasy Fork](https://greasyfork.org/) 上。\n\n后来，有朋友提议添加更优化的操作方式，于是陆续增加了显示大图、键盘翻页等功能。再后来有一天，我躺在床上用手机登陆了 Y 站，网站无法适配移动端屏幕实在是太特么难受了，于是我就敲了响应式布局的浏览模式，手机可以自动加载图片资源，单屏一滑到底。\n\n终于，舒服了。\n\n- https://yande.re\n- ~~https://oreno.imouto.us （Y 站镜像，无需魔法上网）~~（已失效）\n- https://konachan.com （K 站已兼容）\n- https://konachan.net （K 站安全模式，.net 域名下默认隐藏成人内容）\n\n# 预览\n\n- 样式优化，高清图源，尺寸自选。\n\n![1](https://cdn.jsdelivr.net/gh/coderzhaoziwei/yande-re-chinese-patch/source/img/1.png)\n\n- 流体布局，自动加载，一屏到底。\n\n![2](https://cdn.jsdelivr.net/gh/coderzhaoziwei/yande-re-chinese-patch/source/img/2.png)\n\n- 单图预览，聚合详情，一键下载。\n\n![3](https://cdn.jsdelivr.net/gh/coderzhaoziwei/yande-re-chinese-patch/source/img/3.png)\n\n- 显隐自如，更多功能，欢迎体验。\n\n![4](https://cdn.jsdelivr.net/gh/coderzhaoziwei/yande-re-chinese-patch/source/img/4.png)\n\n# 功能\n\n## 标签翻译\n\n翻译了 Y 站出现频率较高的 100 多个标签，详细内容请查看最下方的标签翻译表。欢迎校正或补充。\n\n## 操作优化\n\n- 对于 Y 站默认隐藏的成人内容，提供了显示或者隐藏的选项。\n- 网页左侧的边栏，提供了显示或者隐藏的选项。\n- 图源默认自动替换为高清资源，并提供了 1 ~ 4 倍尺寸的选项。\n- 快捷键\n  - 上一页：A / ←\n  - 下一页：D / →\n  - 显示当前作品原图：S\n  - 显示当前作品来源：W\n\n## 浏览模式\n\n浏览任意图片列表时，可以进入浏览模式。\n\n# 安装\n\n## 安装浏览器插件\n\n首先你需要为你的浏览器安装一个用户脚本管理器，推荐使用插件 [Tampermonkey](https://www.tampermonkey.net/)。\n\n> 主流浏览器有 Chrome、Microsoft Edge、Firefox、Safari 等，如果你的浏览器无法安装 Tampermonkey，那么也就无法安装此脚本程序。\n\n## 安装脚本程序\n\n使用浏览器直接访问 [Greasy Fork - Yande.re 简体中文 - 主页](https://greasyfork.org/scripts/421970)，点击安装即可。\n\n如果你没有 Greasy Fork 的账号，访问以上链接可能会提示你：`此脚本不再在本网站上匿名可用。请登录并检查您的 Greasy Fork 账号设置。`\n\n因为此脚本程序涉及成人内容，所以在 Greasy Fork 站点必须登录才可以浏览或安装。如果你不想注册成为 Greasy Fork 的用户，可以访问成人脚本站点 [Sleasy Fork](https://sleazyfork.org/scripts/421970) 直接安装，或者直接获取[仓库文件](https://github.com/coderzhaoziwei/yande-re-chinese-patch/raw/main/index.user.js)来安装。\n\n# 常见问题\n\n## Q: 安卓手机如何安装 Tampermonkey？\n\n我推荐安卓 Yandex 浏览器，可以直接安装 Chrome 插件。当你发现谷歌市场的 Tampermonkey 显示不兼容时，点击 Yandex 菜单栏，切换为桌面模式即可。\n\n其他安卓浏览器也可以的，Firefox、Kiwi、Iceraven 等自行尝试。\n\n# 相关链接\n\n[Github 仓库](https://github.com/coderzhaoziwei/yande-re-chinese-patch) |\n[Greasy Fork 脚本主页](https://greasyfork.org/scripts/421970) |\n[封面原图 Yande#388833](https://yande.re/post/show/388833)\n\n# 开源许可\n\nMIT\n\n# 附：标签翻译表\n\n[[ TAGS ]]\n\n[img-version]: https://img.shields.io/github/package-json/v/coderzhaoziwei/yande-re-chinese-patch?style=flat-square\n[img-license]: https://shields.io/badge/license-MIT-blue?style=flat-square\n[img-stars]: https://img.shields.io/github/stars/coderzhaoziwei/yande-re-chinese-patch?label=star&style=social\n[img-cover]: https://cdn.jsdelivr.net/gh/coderzhaoziwei/yande-re-chinese-patch/preview.png\n"
  },
  {
    "path": "script/action.js",
    "content": "#!/usr/bin/env node\n\nconst fs = require('fs')\nconst path = require('path')\nconst tagsData = Object()\nconst version = process.env['npm_package_version'] || ''\n\nformatTagsFile()\ngenerateReadMeFile()\n\nfunction formatTagsFile() {\n  info('正在格式化标签数据')\n  const tagsPath = path.resolve(__dirname, '../source/data/tags.json')\n  const data = JSON.parse(fs.readFileSync(tagsPath))\n  Object.keys(data).sort().forEach(key => tagsData[key.replace(/ /g, '_')] = data[key])\n  fs.writeFileSync(tagsPath, JSON.stringify(tagsData, null, 2))\n}\n\nfunction generateReadMeFile() {\n  info('正在生成说明文档')\n  const main = fs.readFileSync(path.resolve(__dirname, '../readme_main.md'), 'utf8')\n  const tags = Object.keys(tagsData).reduce((data, key, index) => {\n    const en = key.replace(/_/g, ' ')\n    const cn = tagsData[key]\n    return `${ data }\\n|${ index + 1 }|${en}|${cn}|`\n  }, '||English|简体中文|\\n|:-:|:-|:-|')\n\n  fs.writeFileSync(path.resolve(__dirname, '../readme.md'), main.replace('[[ TAGS ]]', tags))\n}\n\nfunction info(log) {\n  console.log(`\\u001b[35m[${version}] \\u001b[34m${log}`)\n}\n"
  },
  {
    "path": "script/bundle.sh",
    "content": "# clear\necho \"\\033[2J\"\n\n# version\nyarn version --no-git-tag-version --patch\n\nnode script/action.js\n\n# rollup\nyarn rollup --config config/rollup.config.js\n\nnode script/replace.js\n\n# copy\nif (type pbcopy >/dev/null 2>&1) then\n  pbcopy < bundle/index.user.js\n  echo \"\\033[32mcopied \\033[1;36mbundle/valkyrie.user.js \\033[0;32mto clipboard.\\033[0m\"\nfi\n# end\necho \"\"\n"
  },
  {
    "path": "script/replace.js",
    "content": "#!/usr/bin/env node\n\nconst fs = require(\"fs\")\n\nconst origin = fs.readFileSync(\"bundle/index.js\", \"utf8\")\nconst result = handler(origin)\n\nfs.writeFile(\"bundle/index.user.js\", result, error => {\n  if (error) console.log(error)\n})\n\n\n\nfunction handler(content) {\n  // [{ path: \"source/body.html\" }]\n  const regexp = /\\[{ path: ([\\S]+) }\\]/i\n  while (regexp.test(content)) {\n    const path = JSON.parse(RegExp.$1)\n    console.log(path)\n    const replacement = fs.readFileSync(path, \"utf8\")\n    content = content.replace(regexp, replacement)\n  }\n  return content\n}\n"
  },
  {
    "path": "source/app.js",
    "content": "import Post from \"./post\"\n\nconst App = {\n  template: \"#app-template\",\n  data() {\n    return {\n      showDrawer: false,\n      showImageSelected: false,\n      showImageInfo: true,\n\n      showRatingQ: JSON.parse(localStorage.getItem(\"showRatingQ\") || \"true\"),\n      showRatingE: JSON.parse(localStorage.getItem(\"showRatingE\") || \"false\"),\n\n      imageList: [],\n      imageSelectedIndex: 0,\n      imageSelectedDetail: {},\n\n      params: new URLSearchParams(location.search),\n      requestState: false,\n      requestStop: false,\n\n      innerWidth: window.innerWidth,\n      innerHeight: window.innerHeight,\n\n      imageCountInRow: JSON.parse(localStorage.getItem(\"imageCountInRow\") || \"3\"),\n      imageQualityHigh: JSON.parse(localStorage.getItem(\"imageQualityHigh\") || \"false\"),\n\n      showFavoriteSuccess: false,\n    }\n  },\n  computed: {\n    isMobile() {\n      try {\n        return this.$vuetify.breakpoint.mobile\n      } catch(error) {\n        return false\n      }\n    },\n    title() {\n      return `${this.imageList.length} Posts`\n    },\n    version() {\n      return GM_info.script.version\n    },\n    imageSelected() {\n      return this.imageList[this.imageSelectedIndex] || new Post()\n    },\n    imageSelectedWidth() {\n      const width = parseInt(Math.min(this.innerWidth * 0.9, this.imageSelected.sampleWidth))\n      const height = Math.min(this.innerHeight * 0.9, this.imageSelected.sampleHeight)\n      const width2 = parseInt(height * this.imageSelected.aspectRatio)\n      return Math.min(width, width2)\n    },\n    imageSelectedHeight() {\n      const width = Math.min(this.innerWidth * 0.9, this.imageSelected.sampleWidth)\n      const height = parseInt(Math.min(this.innerHeight * 0.9, this.imageSelected.sampleHeight))\n      const height2 = parseInt(width / this.imageSelected.aspectRatio)\n      return Math.min(height, height2)\n    },\n  },\n  watch: {\n    showRatingQ(value) {\n      localStorage.setItem(\"showRatingQ\", JSON.stringify(value))\n    },\n    showRatingE(value) {\n      localStorage.setItem(\"showRatingE\", JSON.stringify(value))\n    },\n    imageCountInRow(value) {\n      localStorage.setItem(\"imageCountInRow\", JSON.stringify(value))\n    },\n    imageQualityHigh(value) {\n      localStorage.setItem(\"imageQualityHigh\", JSON.stringify(value))\n    },\n    showFavoriteSuccess(value) {\n      console.log('showFavoriteSuccess: ', value)\n    },\n    showImageSelected(value) {\n      if (!value) {\n        this.imageSelectedDetail = {}\n        return\n      }\n      this.getPostDetail(this.imageSelected.id).then(res => {\n        if (!res) return\n        this.imageSelectedDetail = res\n      })\n    }\n  },\n  methods: {\n    async request() {\n      this.requestState = true\n      const url = location.origin + location.pathname + \".json?\" + this.params.toString()\n      const response = await new Promise(resolve => {\n        console.log(url)\n        jQuery.get(url, data => resolve(data))\n      })\n      if (response instanceof Array && response.length > 0) {\n        window.history.pushState(\"\", \"\", location.pathname + \"?\" + this.params.toString())\n        response.forEach(item => this.imageList.push(new Post(item)))\n        const page = Number(this.params.get(\"page\")) || 1\n        this.params.set(\"page\", page + 1)\n        // 延迟\n        setTimeout(() => (this.requestState = false), 1000)\n      } else {\n        this.requestStop = true\n      }\n    },\n    download(src, filename) {\n      // 添加文件后缀\n      const match = src.match(/[.](?<extension>png|jpg|jpeg)$/)\n      if (match) {\n        const extension = match.groups.extension\n        GM_download(src, filename + \".\" + extension)\n      } else {\n        GM_download(src, filename)\n      }\n    },\n    // 添加收藏\n    onFavorite(id) {\n      $.ajax({\n        method: 'POST',\n        url: \"https://yande.re/post/vote.json\",\n        beforeSend: xhr => xhr.setRequestHeader('x-csrf-token', window.csrfToken),\n        data: { id, score: 3 },\n        success: data => {\n          if (data.success === true) {\n            this.imageList[this.imageSelectedIndex].favorite = true // 更新收藏状态\n            this.imageSelectedDetail.favorite = true\n          }\n        },\n      })\n    },\n    async getPostDetail(id) {\n      try {\n        if (!id) return\n        const response = await fetch(`/post.json?api_version=2&tags=id:${id}&include_tags=1&include_votes=1`)\n        const result = await response.json()\n        return {\n          favorite: result.votes[id] == 3,\n          artist: Object.keys(result.tags).find(k => result.tags[k] == 'artist')\n        }\n      } catch (error) {\n        console.log('getPostDetail error:', error)\n      }\n    }\n  },\n  mounted() {\n    // 自动加载数据\n    const timeInterval = setInterval(() => {\n      if (this.requestStop === true) {\n        clearInterval(timeInterval)\n        return\n      }\n      const scrollTop = document.documentElement.scrollTop\n      const scrollHeight = document.documentElement.scrollHeight\n      const height = window.innerHeight\n      if (scrollTop + height >= scrollHeight * 0.75) {\n        if (this.requestState === false) {\n          this.request()\n        }\n      }\n    }, 1000)\n    // 记录窗口尺寸\n    window.addEventListener(\"resize\", () => {\n      this.innerWidth = window.innerWidth\n      this.innerHeight = window.innerHeight\n    })\n  },\n}\n\nexport default App\n"
  },
  {
    "path": "source/browse.js",
    "content": "import app from \"./app\"\n\nexport async function enterBrowseMode() {\n  function getScript(url) {\n    return new Promise(resolve => jQuery.getScript(url, () => resolve()))\n  }\n\n  await getScript(\"https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.min.js\")\n  await getScript(\"https://cdn.jsdelivr.net/npm/vuetify@2.5.0/dist/vuetify.min.js\")\n  await getScript(\"https://cdn.jsdelivr.net/npm/vue-masonry-css@1.0.3/dist/vue-masonry.min.js\")\n  await getScript(\"https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js\")\n\n  window.csrfToken = jQuery('[name=\"csrf-token\"]').attr('content')\n\n  document.head.innerHTML = `[{ path: \"source/html/head.html\" }]`\n  document.body.innerHTML = `[{ path: \"source/html/body.html\" }]`\n\n  Vue.use(VueMasonry)\n\n  new Vue({\n    vuetify: new Vuetify({\n      theme: { dark: true },\n    }),\n    render: h => h(app)\n  }).$mount(\"#app\")\n}\n"
  },
  {
    "path": "source/data/footers.json",
    "content": "\n{\n  \"List\": \"首页\",\n  \"Browse\": \"翻阅\",\n  \"Upload\": \"上传\",\n  \"Random\": \"随机\",\n  \"Popular\": \"热门\",\n  \"Image Search\": \"寻图\",\n  \"History\": \"历史\",\n  \"Help\": \"帮助\"\n}\n"
  },
  {
    "path": "source/data/menus.json",
    "content": "\n{\n  \"My Account\": \"账户\",\n  \"Posts\": \"作品\",\n  \"Comments\": \"评论\",\n  \"Notes\": \"笔记\",\n  \"Artists\": \"画师\",\n  \"Tags\": \"标签\",\n  \"Forum\": \"论坛\",\n  \"Help\": \"帮助\",\n  \"More »\": \"更多>>\",\n  \"New Mail\": \"新消息\",\n  \"My Profile\": \"我的资料\",\n  \"My Mail\": \"我的消息\",\n  \"My Favorites\": \"我的收藏\",\n  \"Settings\": \"设置\",\n  \"Change Password\": \"修改密码\",\n  \"Logout\": \"退出登录\",\n  \"View Posts\": \"浏览作品\",\n  \"Search Posts\": \"搜索作品\",\n  \"Upload\": \"上传\",\n  \"Random\": \"随机浏览\",\n  \"Popular\": \"热门\",\n  \"Image Search\": \"搜索图片\",\n  \"History\": \"历史\",\n  \"View Comments\": \"浏览评论\",\n  \"Search Comments\": \"搜索评论\",\n  \"View Notes\": \"浏览笔记\",\n  \"Search Notes\": \"搜索笔记\",\n  \"View Artists\": \"浏览画师\",\n  \"Search Artists\": \"搜索画师\",\n  \"Create\": \"创建\",\n  \"View Tags\": \"浏览标签\",\n  \"Search Tags\": \"搜索标签\",\n  \"Aliases\": \"别名\",\n  \"Implications\": \"含义\",\n  \"View Pools\": \"浏览 Pools\",\n  \"Search Pools\": \"搜索 Pools\",\n  \"Create New Pool\": \"创建 Pool\",\n  \"View Wiki Index\": \"浏览 Wiki 主页\",\n  \"Search Wiki\": \"搜索 Wiki\",\n  \"Create New Page\": \"创建新页面\",\n  \"Mark All Read\": \"全部标记已读\"\n}\n"
  },
  {
    "path": "source/data/tags.json",
    "content": "{\n  \"4koma\": \"四格漫画\",\n  \"5-toubun_no_hanayome\": \"五等分的新娘\",\n  \"anal\": \"肛交\",\n  \"angel\": \"天使\",\n  \"angel_beats!\": \"Angel Beats!\",\n  \"animal_ears\": \"兽耳\",\n  \"anthropomorphization\": \"拟人化\",\n  \"anus\": \"肛门露出\",\n  \"areola\": \"乳晕\",\n  \"arknights\": \"明日方舟\",\n  \"armor\": \"盔甲/装甲\",\n  \"artist_revision\": \"画师修改\",\n  \"ass\": \"臀部\",\n  \"ass_grab\": \"持股/捏臀\",\n  \"atelier\": \"炼金工房系列\",\n  \"autographed\": \"亲笔签名\",\n  \"azur_lane\": \"碧蓝航线\",\n  \"bakemonogatari\": \"化物语\",\n  \"bandages\": \"绷带\",\n  \"bandaid\": \"创可贴/绷带\",\n  \"bang_dream!\": \"BanG Dream!\",\n  \"baseball\": \"棒球\",\n  \"basketball\": \"篮球\",\n  \"bathing\": \"沐浴\",\n  \"benghuai_xueyuan\": \"崩坏学园\",\n  \"bike_shorts\": \"自行车短裤\",\n  \"bikini\": \"比基尼\",\n  \"bikini_armor\": \"比基尼装甲/轻薄盔甲\",\n  \"bikini_top\": \"比基尼乳罩\",\n  \"black_rock_shooter\": \"黑岩射手\",\n  \"blood\": \"血腥\",\n  \"bloomers\": \"灯笼裤/宽松短裤\",\n  \"blue_archive\": \"碧蓝档案\",\n  \"bodysuit\": \"紧身衣裤\",\n  \"boku_wa_tomodachi_ga_sukunai\": \"我的朋友很少\",\n  \"bondage\": \"束缚\",\n  \"bottomless\": \"下身露出\",\n  \"bra\": \"乳罩\",\n  \"breast_grab\": \"握乳\",\n  \"breast_hold\": \"托乳\",\n  \"breasts\": \"乳\",\n  \"bukkake\": \"颜射\",\n  \"bunny_ears\": \"兔耳\",\n  \"bunny_girl\": \"兔女郎\",\n  \"buruma\": \"运动短裤\",\n  \"business_suit\": \"西装/职业服\",\n  \"calendar\": \"日历\",\n  \"cameltoe\": \"阴户凸显\",\n  \"card\": \"卡牌\",\n  \"card_captor_sakura\": \"魔卡少女樱\",\n  \"censored\": \"有码\",\n  \"cg\": \"CG/计算机动画\",\n  \"chainsaw\": \"电锯\",\n  \"character_design\": \"角色设计\",\n  \"cheerleader\": \"啦啦队队员\",\n  \"chibi\": \"Q版\",\n  \"chinadress\": \"旗袍\",\n  \"choujigen_game_neptune\": \"超次元游戏海王星\",\n  \"christmas\": \"圣诞\",\n  \"cleavage\": \"乳沟\",\n  \"code_geass\": \"反叛的鲁路修\",\n  \"condom\": \"避孕套\",\n  \"corset\": \"(束腰)紧身内衣\",\n  \"cosplay\": \"角色扮演\",\n  \"cream\": \"奶油\",\n  \"cropped\": \"裁剪图\",\n  \"crossdress\": \"变装\",\n  \"crossover\": \"作品联动/混合同人\",\n  \"cum\": \"精液\",\n  \"cunnilingus\": \"品玉/舔阴\",\n  \"dakimakura\": \"抱枕\",\n  \"darling_in_the_franxx\": \"DARLING in the FRANXX\",\n  \"date_a_live\": \"约会大作战\",\n  \"detexted\": \"去字图片\",\n  \"devil\": \"魔鬼/恶魔\",\n  \"digital_version\": \"数字版\",\n  \"dildo\": \"假阳具\",\n  \"disc_cover\": \"光盘封面\",\n  \"dress\": \"连衣裙\",\n  \"dress_shirt\": \"衬衫\",\n  \"duplicate\": \"重复图片\",\n  \"elf\": \"精灵\",\n  \"endcard\": \"片尾插图\",\n  \"erect_nipples\": \"乳尖\",\n  \"expression\": \"角色展示/立绘\",\n  \"extreme_content\": \"极端\",\n  \"eyepatch\": \"眼罩\",\n  \"fairy\": \"精灵/小精灵\",\n  \"fate/kaleid_liner_prisma_illya\": \"Fate/kaleid liner 魔法少女☆伊莉雅\",\n  \"feet\": \"足\",\n  \"fellatio\": \"口交\",\n  \"final_fantasy\": \"最终幻想\",\n  \"final_fantasy_vii\": \"最终幻想 VII\",\n  \"final_fantasy_xiv\": \"最终幻想 14\",\n  \"fingering\": \"指交\",\n  \"fire_emblem\": \"火焰纹章\",\n  \"fire_emblem_heroes\": \"火焰之纹章：英雄云集\",\n  \"fire_emblem_kakusei\": \"火焰之纹章：觉醒\",\n  \"fire_emblem_three_houses\": \"火焰之纹章：风花雪月\",\n  \"fishnets\": \"鱼网袜\",\n  \"fixed\": \"修改\",\n  \"footjob\": \"足交\",\n  \"fundoshi\": \"褌/兜裆布\",\n  \"futanari\": \"扶她\",\n  \"game_cg\": \"游戏CG\",\n  \"gangbang\": \"乱交\",\n  \"garter\": \"袜带\",\n  \"garter_belt\": \"吊袜腰带\",\n  \"genderswap\": \"性转\",\n  \"genshin_impact\": \"原神\",\n  \"girls_frontline\": \"少女前线\",\n  \"girls_und_panzer\": \"少女与战车\",\n  \"gochuumon_wa_usagi_desu_ka?\": \"请问您今天要来点兔子吗？\",\n  \"gothic_lolita\": \"哥特式洛丽塔\",\n  \"granblue_fantasy\": \"碧蓝幻想\",\n  \"guitar\": \"吉他\",\n  \"gun\": \"枪炮\",\n  \"gundam\": \"高达\",\n  \"guro\": \"猎奇\",\n  \"halloween\": \"万圣节前夜\",\n  \"handjob\": \"打手枪\",\n  \"headphones\": \"耳机\",\n  \"heels\": \"高跟鞋\",\n  \"heterochromia\": \"虹膜异色\",\n  \"hibike!_euphonium\": \"吹响吧！上低音号\",\n  \"highschool_dxd\": \"恶魔高校D×D\",\n  \"honkai_impact\": \"崩坏 3\",\n  \"horns\": \"角\",\n  \"index_page\": \"索引页面\",\n  \"infinite_stratos\": \"IS/无限斯特拉托斯\",\n  \"inumimi\": \"犬耳\",\n  \"japanese_clothes\": \"日式服装\",\n  \"k-on!\": \"轻音少女\",\n  \"kaguya-sama_wa_kokurasetai_~tensai-tachi_no_renai_zunousen~\": \"辉夜大小姐想让我告白～天才们的恋爱头脑战～\",\n  \"kantai_collection\": \"舰队 Collection\",\n  \"kemono_friends\": \"兽娘动物园\",\n  \"kimetsu_no_yaiba\": \"鬼灭之刃\",\n  \"kimono\": \"和服\",\n  \"kitsune\": \"狐狸\",\n  \"kobayashi-san_chi_no_maid_dragon\": \"小林家的龙女仆\",\n  \"kono_subarashii_sekai_ni_shukufuku_wo!\": \"为美好的世界献上祝福！\",\n  \"lactation\": \"泌乳\",\n  \"landscape\": \"风景画\",\n  \"league_of_legends\": \"英雄联盟\",\n  \"leotard\": \"紧身连衣裤\",\n  \"line_art\": \"线条画\",\n  \"lingerie\": \"贴身内衣\",\n  \"little_busters!\": \"Little Busters!\",\n  \"loli\": \"萝莉\",\n  \"lolita_fashion\": \"洛丽塔\",\n  \"love_live!_nijigasaki_high_school_idol_club\": \"Love Live! 虹咲学园学园偶像同好会\",\n  \"lucky_star\": \"幸运星\",\n  \"maebari\": \"前貼り/遮盖私处\",\n  \"mahou_shoujo_lyrical_nanoha\": \"魔法少女奈叶\",\n  \"mahou_shoujo_lyrical_nanoha_strikers\": \"魔法少女奈叶 StrikerS\",\n  \"maid\": \"女仆\",\n  \"male\": \"男性\",\n  \"masturbation\": \"自摸/手淫\",\n  \"mecha\": \"机甲\",\n  \"mecha_musume\": \"机甲娘\",\n  \"megane\": \"眼镜\",\n  \"megaten\": \"女神转生系列\",\n  \"mermaid\": \"美人鱼\",\n  \"miko\": \"巫女\",\n  \"monochrome\": \"单色\",\n  \"monster\": \"怪物\",\n  \"monster_girl\": \"怪物女孩\",\n  \"monster_musume_no_iru_nichijou\": \"魔物娘的相伴日常\",\n  \"naked\": \"裸体\",\n  \"naked_apron\": \"裸体围裙\",\n  \"naked_cape\": \"裸体披风\",\n  \"naked_ribbon\": \"裸体丝带\",\n  \"neko\": \"猫\",\n  \"nekomimi\": \"猫耳\",\n  \"neon_genesis_evangelion\": \"新世纪福音战士\",\n  \"nier_automata\": \"尼尔：自动人形\",\n  \"nijisanji\": \"彩虹社\",\n  \"ninja\": \"忍者\",\n  \"nipple_slip\": \"露点\",\n  \"nipples\": \"乳头\",\n  \"no_bra\": \"无乳罩\",\n  \"nopan\": \"无胖次\",\n  \"nun\": \"修女\",\n  \"nurse\": \"护士\",\n  \"official_watermark\": \"官方水印\",\n  \"onsen\": \"温泉\",\n  \"open_shirt\": \"衬衫敞开\",\n  \"ore_no_imouto_ga_konnani_kawaii_wake_ga_nai\": \"我的妹妹哪有这么可爱！\",\n  \"overalls\": \"工装连衣裤\",\n  \"overwatch\": \"守望先锋\",\n  \"paizuri\": \"乳交\",\n  \"pajama\": \"睡衣\",\n  \"panties\": \"内裤\",\n  \"pantsu\": \"胖次\",\n  \"panty_pull\": \"胖次脱下\",\n  \"pantyhose\": \"吊带袜\",\n  \"parody\": \"仿拟/谐拟\",\n  \"partial_scan\": \"局部扫描\",\n  \"pasties\": \"乳贴\",\n  \"pee\": \"尿尿\",\n  \"penguin\": \"企鹅\",\n  \"penis\": \"阴茎\",\n  \"photo\": \"照片/现实背景\",\n  \"photoshop\": \"PS 改图\",\n  \"pirate\": \"海盗\",\n  \"pointy_ears\": \"尖耳朵\",\n  \"pokemon\": \"精灵宝可梦\",\n  \"possible_duplicate\": \"可能重复\",\n  \"pregnant\": \"孕妇\",\n  \"pretty_cure\": \"光之美少女\",\n  \"princess_connect\": \"公主连结\",\n  \"princess_connect!_re:dive\": \"公主连结 Re:Dive\",\n  \"profile_page\": \"角色资料页\",\n  \"pubic_hair\": \"阴毛\",\n  \"puella_magi_madoka_magica\": \"魔法少女小圆\",\n  \"pussy\": \"阴户\",\n  \"pussy_juice\": \"妹汁\",\n  \"queen's_blade\": \"女王之刃\",\n  \"raw_scan\": \"扫描原图\",\n  \"re_zero_kara_hajimeru_isekai_seikatsu\": \"Re:从零开始的异世界生活\",\n  \"robe\": \"长袍/礼服/睡袍\",\n  \"saenai_heroine_no_sodatekata\": \"路人女主的养成方法\",\n  \"sailor_moon\": \"美少女战士\",\n  \"sake\": \"日本清酒\",\n  \"sample\": \"样品图\",\n  \"sarashi\": \"晒し/缠胸布\",\n  \"school_swimsuit\": \"学校泳衣\",\n  \"see_through\": \"透视\",\n  \"seifuku\": \"制服\",\n  \"selfie\": \"自拍\",\n  \"senran_kagura\": \"闪乱神乐\",\n  \"sex\": \"性交\",\n  \"sheets\": \"床单\",\n  \"shimapan\": \"条纹胖次\",\n  \"shirt_lift\": \"衬衫掀起\",\n  \"shota\": \"正太\",\n  \"silhouette\": \"剪影/暗色轮廓/体形\",\n  \"sketch\": \"素描\",\n  \"skirt_lift\": \"裙摆掀起\",\n  \"sling_bikini\": \"吊带比基尼\",\n  \"smoking\": \"吸烟\",\n  \"soccer\": \"足球\",\n  \"sono_bisque_doll_wa_koi_wo_suru\": \"更衣人偶坠入爱河\",\n  \"spy_x_family\": \"间谍过家家\",\n  \"ssss.gridman\": \"SSSS.古立特\",\n  \"stick_poster\": \"海报\",\n  \"stockings\": \"长筒袜\",\n  \"strike_witches\": \"强袭魔女\",\n  \"string_panties\": \"细绳胖次\",\n  \"summer_dress\": \"夏装\",\n  \"suzumiya_haruhi_no_yuuutsu\": \"凉宫春日的忧郁\",\n  \"sweater\": \"毛衣\",\n  \"swimsuits\": \"泳衣\",\n  \"sword\": \"刀剑\",\n  \"sword_art_online\": \"刀剑神域\",\n  \"symmetrical_docking\": \"乳乳相接\",\n  \"tagme\": \"标签\",\n  \"tail\": \"兽尾\",\n  \"tan_lines\": \"日晒线\",\n  \"tattoo\": \"文身\",\n  \"tennis\": \"网球\",\n  \"tentacles\": \"触手\",\n  \"text\": \"文本\",\n  \"the_idolm@ster\": \"偶像大师\",\n  \"the_idolm@ster_cinderella_girls\": \"偶像大师灰姑娘女孩\",\n  \"the_idolm@ster_million_live!\": \"偶像大师百万现场\",\n  \"the_idolm@ster_shiny_colors\": \"偶像大师闪耀色彩\",\n  \"thighhighs\": \"过膝袜\",\n  \"thong\": \"丁字裤\",\n  \"to_aru_kagaku_no_railgun\": \"某科学的超电磁炮\",\n  \"to_aru_majutsu_no_index\": \"魔法禁书目录\",\n  \"to_heart_(series)\": \"To Heart 系列\",\n  \"to_heart_2\": \"To Heart 2\",\n  \"to_love_ru\": \"出包王女\",\n  \"to_love_ru_darkness\": \"出包王女 Darkness\",\n  \"topless\": \"上身露出\",\n  \"torn_clothes\": \"破衣\",\n  \"touhou\": \"东方\",\n  \"towel\": \"浴巾\",\n  \"translated\": \"文字已翻译(英文)\",\n  \"transparent_png\": \"背景透明\",\n  \"trap\": \"伪娘\",\n  \"tribadism\": \"磨豆腐/交叉体位\",\n  \"tutorial\": \"教程\",\n  \"uma_musume_pretty_derby\": \"赛马娘\",\n  \"umbrella\": \"伞\",\n  \"uncensored\": \"无码\",\n  \"underboob\": \"南半球\",\n  \"underwear\": \"内衣\",\n  \"undressing\": \"脱衣\",\n  \"uniform\": \"制服\",\n  \"valentine\": \"情人节\",\n  \"vibrator\": \"跳蛋\",\n  \"wa_maid\": \"和风女仆\",\n  \"waitress\": \"女侍\",\n  \"wallpaper\": \"壁纸\",\n  \"wardrobe_malfunction\": \"走光\",\n  \"weapon\": \"武器\",\n  \"wedding_dress\": \"婚纱\",\n  \"wet\": \"湿身\",\n  \"wet_clothes\": \"湿衣\",\n  \"wings\": \"翅膀\",\n  \"witch\": \"女巫\",\n  \"xenoblade\": \"异度神剑\",\n  \"xenoblade_chronicles_2\": \"异度神剑 2\",\n  \"yahari_ore_no_seishun_lovecome_wa_machigatteiru.\": \"我的青春恋爱喜剧果然有问题\",\n  \"yaoi\": \"蔷薇/男同\",\n  \"yukata\": \"浴衣\",\n  \"yuri\": \"百合\",\n  \"zhanjianshaonv\": \"战舰少女\"\n}"
  },
  {
    "path": "source/hotkey.js",
    "content": "export const initHotKey = function() {\n\n  window.addEventListener(\"keyup\", function(event) {\n    console.log('keyup:', event.key)\n    // 有输入框被激活时，禁止触发方向键。\n    if (/^(TEXTAREA|INPUT|SELECT|BUTTON)$/.test(document.activeElement.tagName)) return\n\n    // 上一页 ← a A\n    const prev = document.querySelector(\".pagination>.previous_page\") || jQuery(\"li:contains('Previous') a[href]\")[0]\n    if (prev && (event.key == \"ArrowLeft\" || event.key == \"a\" || event.key == \"A\")) {\n      prev.click()\n      return event.preventDefault()\n    }\n    // 下一页 → d D\n    const next = document.querySelector(\".pagination>.next_page\") || jQuery(\"li:contains('Next') a[href]\")[0]\n    if (next && (event.key == \"ArrowRight\" || event.key === \"d\" || event.key == \"D\")) {\n      next.click()\n      return event.preventDefault()\n    }\n    // 显示 s S\n    const show = document.querySelector(\"#png\") || document.querySelector(\"#highres\")\n    if (show && (event.key === \"s\" || event.key === \"S\")) {\n      show.click()\n      return event.preventDefault()\n    }\n    // 来源 w W\n    const where = jQuery(\"li:contains('Source:') a\")[0]\n    if (where && (event.key === \"w\" || event.key === \"W\")) {\n      where.click()\n      return event.preventDefault()\n    }\n  })\n\n  const sidebar = document.querySelector(\"#post-list > div.sidebar\") || document.querySelector(\"#post-view > div.sidebar\")\n  if (sidebar) {\n    sidebar.insertAdjacentHTML(\"beforeend\", \"<div>\" +\n      \"<h5>快捷键说明</h5>\" +\n      \"<div style='color: #ee8888'>上一页：A / ←</div>\" +\n      \"<div style='color: #ee8888'>下一页：D / →</div>\" +\n      \"<div style='color: #ee8888'>显示当前作品原图：S</div>\" +\n      \"<div style='color: #ee8888'>显示当前作品来源：W</div>\" +\n    \"</div>\")\n  }\n\n}\n"
  },
  {
    "path": "source/html/body.html",
    "content": "\n<div id=\"app\"></div>\n\n<script type=\"text/template\" id=\"app-template\">\n<v-app>\n\n  <v-app-bar app dense>\n    <v-app-bar-nav-icon :x-small=\"isMobile\" @click=\"showDrawer=!showDrawer\"></v-app-bar-nav-icon>\n    <v-toolbar-title :style=\"isMobile ? 'font-size: 12px;' : ''\" v-text=\"title\"></v-toolbar-title>\n    <!-- 设置分级制度 -->\n    <v-menu offset-y>\n      <template v-slot:activator=\"{ on, attrs }\">\n        <v-btn :x-small=\"isMobile\" class=\"white--text ml-2\" dark v-bind=\"attrs\" v-on=\"on\">\n          S{{ showRatingQ ? 'Q' : '' }}{{ showRatingE ? 'E' : '' }}\n        </v-btn>\n      </template>\n      <v-list dense>\n        <v-list-item dense>\n          <v-list-item-title style=\"cursor: pointer;\" @click=\"showRatingQ = !showRatingQ;\">\n            {{ showRatingQ ? '隐藏 Q 级内容' : '显示 Q 级内容' }}\n          </v-list-item-title>\n        </v-list-item>\n        <v-list-item dense>\n          <v-list-item-title style=\"cursor: pointer;\" @click=\"showRatingE = !showRatingE;\">\n            {{ showRatingE ? '隐藏 E 级内容' : '显示 E 级内容' }}\n          </v-list-item-title>\n        </v-list-item>\n      </v-list>\n    </v-menu>\n    <!-- 设置图片质量 -->\n    <v-menu offset-y>\n      <template v-slot:activator=\"{ on, attrs }\">\n        <v-btn :x-small=\"isMobile\" class=\"white--text ml-2\" dark v-bind=\"attrs\" v-on=\"on\">{{ imageQualityHigh ? 'HD' : '速' }}</v-btn>\n      </template>\n      <v-list dense>\n        <v-list-item dense>\n          <v-list-item-title style=\"cursor: pointer;\" @click=\"imageQualityHigh = false;\">\n            图片质量：速览\n          </v-list-item-title>\n        </v-list-item>\n        <v-list-item dense>\n          <v-list-item-title style=\"cursor: pointer;\" @click=\"imageQualityHigh = true;\">\n            图片质量：高清\n          </v-list-item-title>\n        </v-list-item>\n      </v-list>\n    </v-menu>\n    <!-- 设置每行几张 -->\n    <v-menu offset-y>\n      <template v-slot:activator=\"{ on, attrs }\">\n        <v-btn :x-small=\"isMobile\" class=\"white--text ml-2\" dark v-bind=\"attrs\" v-on=\"on\">{{imageCountInRow}}列</v-btn>\n      </template>\n      <v-list dense>\n        <v-list-item dense v-for=\"number in [1, 2, 3, 4, 5, 6, 8, 10, 12, 14, 16, 20]\" :key=\"number\">\n          <v-list-item-title style=\"cursor: pointer;\" @click=\"imageCountInRow = number;\">\n            {{ number }}列\n          </v-list-item-title>\n        </v-list-item>\n      </v-list>\n    </v-menu>\n\n    <v-spacer></v-spacer>\n    <v-btn\n      :style=\"isMobile ? 'flex: 0 1 auto; overflow: hidden;' : ''\" :x-small=\"isMobile\"\n      text v-text=\"'v' + version\" color=\"#ffffff\" disabled>\n    </v-btn>\n  </v-app-bar>\n\n  <v-navigation-drawer v-model=\"showDrawer\" app temporary>\n    <v-list-item>\n      <v-list-item-content>\n        <v-list-item-title class=\"title\">Yande.re 简体中文</v-list-item-title>\n        <v-list-item-subtitle>浏览器脚本程序</v-list-item-subtitle>\n      </v-list-item-content>\n    </v-list-item>\n\n    <v-divider></v-divider>\n\n    <v-list dense nav>\n      <v-list-item-content>\n        <v-list-item-title class=\"title\">设置</v-list-item-title>\n        <v-list-item-subtitle></v-list-item-subtitle>\n      </v-list-item-content>\n      <!-- s -->\n      <v-list-item link>\n        <v-list-item-icon class=\"mr-2\">\n          <v-icon>mdi-check</v-icon>\n        </v-list-item-icon>\n        <v-list-item-content>\n          <v-list-item-title>显示 S 分级内容</v-list-item-title>\n          <v-list-item-subtitle>S(safe) 安全的全年龄内容</v-list-item-subtitle>\n        </v-list-item-content>\n      </v-list-item>\n      <!-- q -->\n      <v-list-item link @click=\"showRatingQ=!showRatingQ;\">\n        <v-list-item-icon class=\"mr-2\">\n          <v-icon v-text=\"showRatingQ ? 'mdi-check' : 'mdi-close'\"></v-icon>\n        </v-list-item-icon>\n        <v-list-item-content>\n          <v-list-item-title v-text=\"showRatingQ ? '显示 Q 分级内容' : '隐藏 Q 分级内容'\"></v-list-item-title>\n          <v-list-item-subtitle>Q(questionable) 疑似的成人内容</v-list-item-subtitle>\n        </v-list-item-content>\n      </v-list-item>\n      <!-- e -->\n      <v-list-item link @click=\"showRatingE=!showRatingE;\">\n        <v-list-item-icon class=\"mr-2\">\n          <v-icon v-text=\"showRatingE ? 'mdi-check' : 'mdi-close'\"></v-icon>\n        </v-list-item-icon>\n        <v-list-item-content>\n          <v-list-item-title v-text=\"showRatingE ? '显示 E 分级内容' : '隐藏 E 分级内容'\"></v-list-item-title>\n          <v-list-item-subtitle>E(explicit) 明确的成人内容</v-list-item-subtitle>\n        </v-list-item-content>\n      </v-list-item>\n    </v-list>\n\n    <v-divider></v-divider>\n\n    <v-list dense nav>\n      <v-list-item-content>\n        <v-list-item-title class=\"title\">关于</v-list-item-title>\n        <v-list-item-subtitle></v-list-item-subtitle>\n      </v-list-item-content>\n      <v-list-item link @click=\"window.open('https://github.com/coderzhaoziwei/yande-re-chinese-patch/blob/main/readme.md')\">\n        <v-list-item-icon class=\"mr-2\"><v-icon>mdi-file-document-outline</v-icon></v-list-item-icon>\n        <v-list-item-content>\n          <v-list-item-title>简介</v-list-item-title>\n          <v-list-item-subtitle>说明文档 / 功能介绍</v-list-item-subtitle>\n        </v-list-item-content>\n      </v-list-item>\n      <v-list-item link @click=\"window.open('https://github.com/coderzhaoziwei/yande-re-chinese-patch/issues')\">\n        <v-list-item-icon class=\"mr-2\"><v-icon>mdi-github</v-icon></v-list-item-icon>\n        <v-list-item-content>\n          <v-list-item-title>反馈</v-list-item-title>\n          <v-list-item-subtitle>发现错误 / 提出建议</v-list-item-subtitle>\n        </v-list-item-content>\n      </v-list-item>\n      <v-list-item link @click=\"window.open('https://github.com/coderzhaoziwei/yande-re-chinese-patch')\">\n        <v-list-item-icon class=\"mr-2\"><v-icon>mdi-star</v-icon></v-list-item-icon>\n        <v-list-item-content>\n          <v-list-item-title>Github</v-list-item-title>\n          <v-list-item-subtitle>觉得好用就 Star 支持一下</v-list-item-subtitle>\n        </v-list-item-content>\n      </v-list-item>\n      <v-list-item link>\n        <v-list-item-icon class=\"mr-2\"><v-icon>mdi-google-controller</v-icon></v-list-item-icon>\n        <v-list-item-content>\n          <v-list-item-title>QQ</v-list-item-title>\n          <v-list-item-subtitle>3158492760</v-list-item-subtitle>\n        </v-list-item-content>\n      </v-list-item>\n      <v-list-item link>\n        <v-list-item-icon class=\"mr-2\"><v-icon>mdi-email</v-icon></v-list-item-icon>\n        <v-list-item-content>\n          <v-list-item-title>邮箱</v-list-item-title>\n          <v-list-item-subtitle>coderzhaoziwei@outlook.com</v-list-item-subtitle>\n        </v-list-item-content>\n      </v-list-item>\n    </v-list>\n  </v-navigation-drawer>\n\n  <v-main app>\n    <v-container class=\"pa-2\" fluid>\n      <masonry ref=\"masonry\" :cols=\"imageCountInRow\" gutter=\"8px\" :key=\"imageCountInRow\">\n        <v-card class=\"mb-2\" v-for=\"(image, index) in imageList\" :key=\"index\">\n          <v-img\n            :src=\"\n              image.isRatingS || (image.isRatingQ && showRatingQ) || (image.isRatingE && showRatingE)\n                ? (imageQualityHigh ? image.sampleUrl : image.previewUrl) : ''\n            \"\n            :aspect-ratio=\"image.aspectRatio\"\n            @click=\"if(image.isRatingS||(image.isRatingQ && showRatingQ)||(image.isRatingE && showRatingE)){imageSelectedIndex=index;showImageSelected=true;}\"\n            @click.middle=\"imageSelectedIndex = index; window.open('/post/show/' + imageSelected.id)\"\n          >\n            <template v-slot:placeholder>\n              <v-row v-if=\"image.isRatingS||(image.isRatingQ && showRatingQ)||(image.isRatingE && showRatingE)\"\n                class=\"fill-height ma-0\" align=\"center\" justify=\"center\"\n              >\n                <v-progress-circular indeterminate color=\"#ee8888\"></v-progress-circular>\n              </v-row>\n            </template>\n            <v-row\n              v-if=\"(image.isRatingS||(image.isRatingQ && showRatingQ)||(image.isRatingE && showRatingE))===false\"\n              class=\"fill-height ma-0 text-h5\" align=\"center\" justify=\"center\"\n              style=\"color:#ee8888;\"\n              v-text=\"image.rating.toUpperCase()\"\n            ></v-row>\n          </v-img>\n        </v-card>\n      </masonry>\n\n      <div class=\"d-flex justify-center\">\n        <v-btn\n          :disabled=\"requestState===false\"\n          color=\"#ee8888\" text\n          v-text=\"requestStop ? '下面没有了...' : requestState ? '正在加载中...' : ''\"\n        ></v-btn>\n      </div>\n\n      <v-dialog v-model=\"showImageSelected\" :width=\"imageSelectedWidth\" :height=\"imageSelectedHeight\">\n        <v-img\n          :src=\"imageSelected.sampleUrl\"\n          :lazy-src=\"imageSelected.previewUrl\"\n          @click=\"showImageInfo = !showImageInfo;\"\n        >\n          <div\n            :style=\"showImageInfo\n              ? 'display: flex; flex-direction: column; height: 100%; padding: 4px; grid-gap: 4px;'\n              : 'display: none !important;'\"\n          >\n            <div style=\"height: 100%; flex: 1 1 auto;\"></div>\n\n            <div style=\"display: flex; flex-direction: column; grid-gap: 4px;\">\n              <v-chip style=\"width: fit-content;\" color=\"#009ff088\" text-color=\"#ffffff\" small\n                v-text=\"imageSelected.sampleDownloadText\"\n                @click.stop=\"download(imageSelected.sampleUrl, imageSelected.sampleDownloadName)\"\n              ></v-chip>\n              <v-chip style=\"width: fit-content;\" color=\"#009ff088\" text-color=\"#ffffff\" small\n                v-if=\"imageSelected.jpegSize !== 0\"\n                v-text=\"imageSelected.jpegDownloadText\"\n                @click.stop=\"download(imageSelected.jpegUrl, imageSelected.jpegDownloadName)\"\n              ></v-chip>\n              <v-chip style=\"width: fit-content;\" color=\"#009ff088\" text-color=\"#ffffff\" small\n                v-text=\"imageSelected.fileDownloadText\"\n                @click.stop=\"download(imageSelected.fileUrl, imageSelected.fileDownloadName)\"\n              ></v-chip>\n            </div>\n            <div style=\"display: flex; grid-gap: 4px; flex-wrap: wrap;\">\n              <v-chip\n                style=\"width: fit-content;\" color=\"#ee888888\" text-color=\"#ffffff\" small\n                v-text=\"imageSelected.id + ' ' + imageSelected.rating.toUpperCase()\" @click.stop\n              ></v-chip>\n              <v-chip class=\"mr-1\" style=\"width: fit-content;\" color=\"#009ff088\" text-color=\"#ffffff\" small\n                v-if=\"imageSelectedDetail.artist\"\n                @click.stop=\"window.open('/post?tags='+imageSelectedDetail.artist)\"\n              >画师 {{imageSelectedDetail.artist}}</v-chip>\n              <v-chip class=\"mr-1\" style=\"width: fit-content;\" color=\"#009ff088\" text-color=\"#ffffff\" small\n                v-if=\"imageSelected.sourceUrl !== ''\"\n                v-text=\"'来源链接'\"\n                @click.stop=\"window.open(imageSelected.sourceUrl)\"\n              ></v-chip>\n              <v-chip class=\"mr-1\" style=\"width: fit-content;\" color=\"#009ff088\" text-color=\"#ffffff\" small\n                v-text=\"'本站链接'\"\n                @click.stop=\"window.open('/post/show/' + imageSelected.id)\"\n              ></v-chip>\n              <v-chip class=\"mr-1\" style=\"width: fit-content;\" text-color=\"#ffffff\" small\n                :color=\"imageSelectedDetail.favorite ? '#00900088' : '#009ff088'\"\n                v-text=\"imageSelectedDetail.favorite ? '已收藏' : '添加收藏'\"\n                @click.stop=\"imageSelectedDetail.favorite ? (void 0) : onFavorite(imageSelected.id)\"\n              ></v-chip>\n            </div>\n          </div>\n        </v-img>\n      </v-dialog>\n    </v-container>\n  </v-main>\n</v-app>\n</script>\n"
  },
  {
    "path": "source/html/head.html",
    "content": "\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui\">\n<title>Yande.re 简体中文</title>\n<link rel=\"stylesheet\" href=\"https://cdn.jsdelivr.net/gh/necolas/normalize.css/normalize.css\">\n<link rel=\"stylesheet\" href=\"https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900\">\n<link rel=\"stylesheet\" href=\"https://cdn.jsdelivr.net/npm/@mdi/font@5.9.55/css/materialdesignicons.css\">\n<link rel=\"stylesheet\" href=\"https://cdn.jsdelivr.net/npm/vuetify@2.5.0/dist/vuetify.min.css\">\n<style>\n::-webkit-scrollbar {\n  display: none;\n  width: 0px !important;\n}\n</style>\n"
  },
  {
    "path": "source/html/options.html",
    "content": "\n<div style=\"padding: 1rem; user-select: none; text-align: center;\">\n  <select id=\"showLeftBar\" style=\"height: 1.5rem; line-height: 1.5rem;\">\n    <option>隐藏左栏</option>\n    <option>显示左栏</option>\n  </select>\n  <select id=\"showRatingE\" style=\"height: 1.5rem; line-height: 1.5rem; margin-left: 0.25rem;\">\n    <option>隐藏默认</option>\n    <option>显示全部</option>\n  </select>\n  <select id=\"showImageHD\" style=\"height: 1.5rem; line-height: 1.5rem; margin-left: 0.25rem;\">\n    <option>默认尺寸</option>\n    <option>二倍尺寸</option>\n    <option>三倍尺寸</option>\n    <option>四倍尺寸</option>\n  </select>\n  <button id=\"enterBrowseMode\" style=\"margin-left: 0.25rem;\">进入浏览模式</button>\n</div>\n"
  },
  {
    "path": "source/index.js",
    "content": "import { initStyle } from \"./style\"\nimport { initHotKey } from \"./hotkey\"\nimport { initOptions } from \"./options\"\nimport { initTranslate } from \"./translate\"\n\n\njQuery(document).ready(function() {\n  initStyle()\n  initHotKey()\n  initOptions()\n  initTranslate()\n\n  if (document.cookie.includes('locale=zh_CN') === false) {\n    document.cookie = \"locale=zh_CN\"\n    location.href = location.href\n  }\n\n})\n"
  },
  {
    "path": "source/options.js",
    "content": "import { enterBrowseMode } from \"./browse\"\n\nexport const onChangeLeftBar = function() {\n  const value = Boolean(document.getElementById(\"showLeftBar\").selectedIndex)\n  localStorage.setItem(\"showLeftBar\", JSON.stringify(value))\n  const element = document.querySelector(\"#post-list > .sidebar\")\n  element.setAttribute(\"show-left-bar\", value)\n\n  console.log(\"showLeftBar\", value)\n}\nexport const onChangeRatingE = function() {\n  const value = Boolean(document.getElementById(\"showRatingE\").selectedIndex)\n  localStorage.setItem(\"showRatingE\", JSON.stringify(value))\n  const elementList = document.querySelectorAll(\".javascript-hide\")\n  elementList.forEach(element => element.setAttribute(\"show-rating-e\", value))\n\n  console.log(\"showRatingE\", value)\n}\nexport const onChangeImageHD = function() {\n  // 获取 index 值\n  const index = document.getElementById(\"showImageHD\").selectedIndex\n  // 修改属性 show-image-hd\n  const elementList = document.querySelectorAll(\"#post-list-posts > li > .inner\")\n  elementList.forEach(element => element.setAttribute(\"show-image-hd\", index))\n  // 缓存 index 值\n  localStorage.setItem(\"showImageHD\", JSON.stringify(index))\n  console.log(\"showImageHD\", index)\n  // 设置网格布局宽\n  // document.querySelector(\"#post-list-posts\").style.gridTemplateColumns = `repeat(auto-fill, ${(index + 1) * 150}px)`\n}\n// 网站域名 例如'https://oreno.imouto.us'\nconst origin = window.location.origin\nlet taskArray = []\n// 'https://oreno.imouto.us'域名下每秒钟尝试加载的Sample图片数\nlet maxLoadingSampleNum = 4\nlet doLoadSampleUrl = () => {\n  let loadingNum = 0\n  let loadSampleUrl = () => {\n    if (taskArray.length == 0) return\n    loadingNum++\n    let { element, sampleUrl } = taskArray.shift()\n    element.onerror = () => {\n      element.src = sampleUrl\n    }\n    element.onload = () => {\n      loadingNum--\n    }\n    element.src = sampleUrl\n  }\n  setInterval(() => {\n    if (taskArray.length == 0) return\n    let needloadNum = maxLoadingSampleNum - loadingNum\n    while (needloadNum--) {\n      loadSampleUrl()\n    }\n  }, 1000)\n}\nexport const initOptions = function() {\n  // https://yande.re/user/show/507475\n  if (/^\\/user\\/show\\/[\\d]{1,}/.test(location.pathname)) return\n  if (document.getElementById(\"post-list-posts\") === null) return\n  // 插入文档元素\n  document.getElementById(\"post-list-posts\").insertAdjacentHTML(\"beforebegin\", `[{ path: \"source/html/options.html\" }]`)\n  // 替换图片元素\n  const imageList = document.querySelectorAll(\"img.preview\")\n  const samples = JSON.parse(localStorage.getItem(\"sample_urls\"))\n  imageList.forEach(element => {\n    if (/\\/post\\/show\\/([\\d]{1,})/.test(element.nextElementSibling.innerText)) {\n      const id = RegExp.$1\n      const sampleUrl = samples[id]\n      if (sampleUrl !== undefined) {\n        element.src = sampleUrl\n      }\n    }\n  })\n  doLoadSampleUrl()\n\n  // 监听\n  document.getElementById(\"showLeftBar\").addEventListener(\"change\", onChangeLeftBar)\n  document.getElementById(\"showRatingE\").addEventListener(\"change\", onChangeRatingE)\n  document.getElementById(\"showImageHD\").addEventListener(\"change\", onChangeImageHD)\n\n  // 获取本地记录\n  const showLeftBar = JSON.parse(localStorage.getItem(\"showLeftBar\") || \"true\")\n  const showRatingE = JSON.parse(localStorage.getItem(\"showRatingE\") || \"true\")\n  const showImageHD = JSON.parse(localStorage.getItem(\"showImageHD\") || \"0\")\n  document.getElementById(\"showLeftBar\").selectedIndex = showLeftBar\n  document.getElementById(\"showRatingE\").selectedIndex = showRatingE\n  document.getElementById(\"showImageHD\").selectedIndex = showImageHD\n  onChangeLeftBar()\n  onChangeRatingE()\n  onChangeImageHD()\n\n  // 浏览模式\n  document.getElementById(\"enterBrowseMode\").addEventListener(\"click\", enterBrowseMode)\n}\n"
  },
  {
    "path": "source/post.js",
    "content": "/*\napprover_id: null\nchange: 4106973\nframes: []\nframes_pending: []\nframes_pending_string: \"\"\nframes_string: \"\"\nhas_children: false\nis_held: false\nis_note_locked: false\nis_pending: false\nis_rating_locked: false\nis_shown_in_index: true\nlast_commented_at: 0\nlast_noted_at: 0\nparent_id: null\nstatus: \"active\"\n*/\n\nexport default class Post {\n  constructor(data) {\n    if (typeof data !== \"object\") data = {}\n    this.id = data.id || 0\n    this.score = data.score || 0\n    this.tags = data.tags || \"\"\n    this.source = data.source || \"\"\n\n    this.author = data.author || \"\"\n    this.creatorId = data.creator_id || 0\n    this.createdAt = data.created_at || 0\n    this.updatedAt = data.updated_at || 0\n\n    this.rating = data.rating || \"s\"\n    // 文件\n    this.fileUrl = data.file_url || \"\"\n    this.fileExt = data.file_ext || \"\"\n    this.fileSize = data.file_size || 0\n    this.width = data.width || 0\n    this.height = data.height || 0\n    // 高清图\n    this.jpegUrl = data.jpeg_url || \"\"\n    this.jpegSize = data.jpeg_file_size || 0\n    this.jpegWidth = data.jpeg_width || 0\n    this.jpegHeight = data.jpeg_height || 0\n    // 缩略图\n    this.sampleUrl = data.sample_url\n    this.sampleSize = data.sample_file_size || 0\n    this.sampleWidth = data.sample_width || 0\n    this.sampleHeight = data.sample_height || 0\n    // 预览图 用作懒加载的占位图\n    this.previewUrl = data.preview_url\n    this.previewWidth = data.actual_preview_width || 0\n    this.previewHeight = data.actual_preview_height || 0\n\n    this.favorite = false\n  }\n  // 全年龄 safe\n  get isRatingS() {\n    return this.rating === \"s\"\n  }\n  // 擦边球 questionable\n  get isRatingQ() {\n    return this.rating === \"q\"\n  }\n  // 成人向 explicit\n  get isRatingE() {\n    return this.rating === \"e\"\n  }\n  // 长宽比\n  get aspectRatio() {\n    return this.width / this.height\n  }\n\n  getSizeText(size) {\n    if (size > 1024 * 1024) {\n      return (size / (1024 * 1024)).toFixed(2) + \"MB\"\n    }\n    if (size > 1024) {\n      return (size / 1024).toFixed(2) + \"KB\"\n    }\n    return (size).toFixed(2) + \"B\"\n  }\n\n  get sampleSizeText() {\n    return this.getSizeText(this.sampleSize)\n  }\n  get sampleDownloadText() {\n    return `下载缩略图 ${this.sampleWidth}×${this.sampleHeight} [${this.sampleSizeText}]`\n  }\n  get sampleDownloadName() {\n    return `${location.hostname}.${this.id}.${this.sampleWidth}x${this.sampleHeight}`.replace(/\\./g, \"_\")\n  }\n\n  get jpegSizeText() {\n    return this.getSizeText(this.jpegSize)\n  }\n  get jpegDownloadText() {\n    return `下载高清图 ${this.jpegWidth}×${this.jpegHeight} [${this.jpegSizeText}]`\n  }\n  get jpegDownloadName() {\n    return `${location.hostname}.${this.id}.${this.jpegWidth}x${this.jpegHeight}`.replace(/\\./g, \"_\")\n  }\n\n  get fileSizeText() {\n    return this.getSizeText(this.fileSize)\n  }\n  get fileDownloadText() {\n    return `下载原文件 ${this.width}×${this.height} [${this.fileSizeText}] ${this.fileExt.toUpperCase()}`\n  }\n  get fileDownloadName() {\n    return `${location.hostname}.${this.id}.${this.width}x${this.height}`.replace(/\\./g, \"_\")\n  }\n\n  get createdTime() {\n    const date = new Date(this.createdAt * 1000)\n    return `${date.toLocaleDateString()} ${date.toLocaleTimeString(\"en-DE\")}`\n  }\n  get updatedTime() {\n    const date = new Date(this.updatedAt * 1000)\n    return `${date.toLocaleDateString()} ${date.toLocaleTimeString(\"en-DE\")}`\n  }\n\n  // 解析图源 i.pximg.net => pixiv.net\n  // https://i.pximg.net/img-original/img/2021/05/15/09/41/42/89846615_p0.jpg\n  // https://www.pixiv.net/artworks/89846615\n  get sourceUrl() {\n    if (/^https:\\/\\/i\\.pximg\\.net\\/img-original\\/img\\/[\\d\\/]{19}\\/([\\d]{1,})_p[\\d]{1,}\\.(jpg|png)$/.test(this.source)) {\n      const pid = RegExp.$1\n      return `https://pixiv.net/artworks/${pid}`\n    }\n    return this.source\n  }\n}\n"
  },
  {
    "path": "source/style/fix.css",
    "content": "\nbody {\n  font-size: 12px;\n  padding: 0 0.5rem;\n}\nbody::-webkit-scrollbar {\n  display: none;\n  width: 0px !important;\n}\n/* 标题居中 */\ndiv#header {\n  margin: 0;\n}\ndiv#header > div#title {\n  display: flex;\n  place-content: center;\n  margin: 0 !important;\n  height: fit-content;\n}\ndiv#header > div#title > h2#site-title {\n  display: flex !important;\n  flex-direction: column;\n}\ndiv#header > div#title > h2#site-title > span {\n  font-size: 12px;\n  font-weight: normal;\n  text-align: right;\n}\ndiv#header > div#main-menu {\n  padding: 0 !important;\n  margin: 0 !important;\n  display: flex !important;\n  justify-content: center;\n  font-size: 14px;\n  line-height: 2rem;\n  height: 2rem;\n}\ndiv#header > div#main-menu > ul {\n  margin: 0;\n}\n/* 通知 */\n.status-notice {\n  text-align: center;\n}\n/* 标签前缀 */\nli.tag-type-artist a[href^=\"/post\"]:not(.no-browser-link)::before {\n  content: \"[画师]\";\n}\nli.tag-type-copyright a[href^=\"/post\"]:not(.no-browser-link)::before {\n  content: \"[原作]\";\n}\nli.tag-type-character a[href^=\"/post\"]:not(.no-browser-link)::before {\n  content: \"[角色]\";\n}\nli.tag-type-circle a[href^=\"/post\"]:not(.no-browser-link)::before {\n  content: \"[公司]\";\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: 1 1 auto;\n}\n#post-list > div.lsidebar {\n  display: none;\n}\nul#post-list-posts {\n  display: flex;\n  flex-wrap: wrap;\n  gap: 0.5rem;\n  place-content: center;\n  place-items: center;\n}\nul#post-list-posts > li {\n  width: fit-content !important;\n  height: 100%;\n  margin: 0 !important;\n  border: none;\n}\nul#post-list-posts > li > div.inner {\n  width: auto !important;\n  height: fit-content !important;\n}\nul#post-list-posts > li > a.directlink {\n  font-size: 12px;\n  height: 12px;\n  line-height: 12px;\n  margin: 0;\n  padding: 0;\n  overflow: hidden;\n  background: rgb(16, 16, 16);\n}\nul#post-list-posts > li > a.directlink > span.directlink-res {\n  display: inline;\n}\nul#post-list-posts > li > a.directlink > span.directlink-info {\n  display: none;\n}\nul#post-list-posts > li > div.inner > a.thumb {\n  height: auto;\n}\nul#post-list-posts > li > div.inner > a.thumb > img.preview {\n  margin: 0 !important; /* @konachan */\n  border: none;\n}\n/* 分页器 */\ndiv#paginator {\n  padding: 0;\n}\ndiv#paginator > div.pagination {\n  line-height: 2rem;\n}\n/* 页脚 */\n#content > div:nth-child(2) > div.sidebar {\n  display: none;\n}\n#content div.footer {\n  font-size: 14px;\n  margin: 1rem;\n}\n\n/* show-left-bar */\n.sidebar[show-left-bar=false] {\n  display: none !important;\n}\n/* show-rating-e */\n.javascript-hide[show-rating-e=true] {\n  display: block !important;\n  position: relative;\n}\n.javascript-hide[show-rating-e=true]::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/* show-image-hd */\n#post-list-posts > li > .inner[show-image-hd=\"1\"] {\n  zoom: 2;\n}\n#post-list-posts > li > .inner[show-image-hd=\"2\"] {\n  zoom: 3;\n}\n#post-list-posts > li > .inner[show-image-hd=\"3\"] {\n  zoom: 4;\n}\n"
  },
  {
    "path": "source/style.js",
    "content": "export const initStyle = function() {\n  document.head.insertAdjacentHTML(\"beforeend\", `<style>[{ path: \"source/style/fix.css\" }]</style>`)\n}\n"
  },
  {
    "path": "source/translate.js",
    "content": "const tags = [{ path: \"source/data/tags.json\" }]\nconst menus = [{ path: \"source/data/menus.json\" }]\nconst footers = [{ path: \"source/data/footers.json\" }]\n\n// 翻译标签\nexport const translateTags = function() {\n  const elementList = Array.from(document.getElementsByTagName(\"a\"))\n  elementList.forEach(element => {\n    const href = element.getAttribute(\"href\")\n    if (typeof href === \"string\" && /^\\/post\\?tags=(\\S+)$/.test(href)) {\n      const en = RegExp.$1\n      const cn = tags[en]\n      if (cn) {\n        element.innerText = `[${cn}]${en.replace(/_/g, \" \")}`\n      }\n    }\n  })\n}\n\n// 翻译菜单\nexport const translateMenus = function() {\n  const mainMenuList = Array.from(document.querySelectorAll(\"#main-menu>ul>li>a\"))\n  const subMenuList = Array.from(document.querySelectorAll(\"ul.submenu>li>a\"))\n  const elementList = [...mainMenuList, ...subMenuList]\n  elementList.forEach(element => {\n    if (element.getAttribute(\"href\") === \"#\") return\n    const en = element.innerText\n    const cn = menus[en]\n    if (cn) {\n      element.innerText = cn\n    }\n  })\n}\n\n// 翻译提示\nexport const translateNotice = function() {\n  // EN: This image has been resized. Click on the `View larger version` link in the sidebar\n  //     for a high-quality version. Hide this message\n  // CN: 这张图片已经被压缩，单击侧边栏中的 `显示高清图` 可以获取更高质量的版本。不再提醒\n  // EN: This post belongs to a parent post.\n  // EN: This post has child posts. (post #728160, 746235)\n  // EN: This post has a child post. (post #383703)\n  const elementList = Array.from(document.querySelectorAll(\".status-notice\"))\n  elementList.forEach(element => {\n    console.log(element.innerHTML)\n    element.innerHTML = element.innerHTML\n      .replace(/^[\\s]+This image has been resized. Click on the /, \"这张图片已经被压缩，单击侧边栏中的\")\n      .replace(/View larger version/, \"显示高清图\")\n      .replace(/ link in the sidebar for a high-quality version./, \"可以获取更高质量的版本。\")\n      .replace(/Hide this message<\\/a>\\./, \"不再提醒</a>\")\n      /* 相关父作品 */\n      .replace(/This post belongs to a /, \"这张图片从属于一个\")\n      .replace(/parent post<\\/a>\\./, \"相关父作品</a>。\")\n      /* 相关子作品 */\n      .replace(/This post has /, \"这张图片从属于一个\")\n      .replace(/child posts<\\/a>\\. \\(post #/, \"作品集</a>。相关子作品：\")\n      .replace(/a child post<\\/a>\\. \\(post #/, \"作品集</a>。相关子作品：\")\n      .replace(/<\\/a>, <a /, \"</a> | <a \")\n      .replace(/<\\/a>\\)/, \"</a>\")\n  })\n}\n\n// 翻译点击\nexport const translateButtons = function() {\n  [\n    ['#highres-show', 'View larger version', '显示高清图'],\n    ['#highres', 'Download larger version', '下载高清图'],\n    ['#png', 'Download PNG', '下载 PNG 图'],\n    ['li#add-to-favs>a', 'Add to favorites', '添加收藏'],\n    ['li#set-avatar>a', 'Set avatar', '设置头像'],\n    ['h4>a.js-posts-show-edit-tab', 'Edit', '编辑'],\n    ['h4>a.js-posts-show-comments-tab', 'Respond', '评论'],\n    ['.pagination>.previous_page', '← Previous', '上一页'],\n    ['.pagination>.next_page', 'Next →', '下一页'],\n  ].forEach(data => {\n    const [selector, en, cn] = data\n    const element = document.querySelector(selector)\n    if (element) {\n      element.innerText = element.innerText.replace(en, cn)\n    }\n  })\n}\n\n// 翻译页脚\nexport const translateFooters = function() {\n  const elementList = Array.from(document.querySelectorAll('#subnavbar>li>a'))\n  elementList.forEach(element => {\n    const en = element.innerText\n    const cn = footers[en]\n    if (cn) {\n      element.innerText = cn\n    }\n  })\n}\n\n// 合并\nexport const initTranslate = function() {\n  translateTags()\n  translateMenus()\n  translateNotice()\n  translateButtons()\n  translateFooters()\n}\n"
  },
  {
    "path": "temp/css_text_loader.js",
    "content": "module.exports = function(source) {\n  return 'export default ' + JSON.stringify(source)\n}\n"
  },
  {
    "path": "temp/index.js",
    "content": "/**\n * 默认显示隐藏的作品，并提供可开关的选项。\n */\n;(function() {\n  const SET_JS_HIDE = 'set-javascript-hide'\n  const INPUT_HTML = `<input type=\"checkbox\" id=\"${SET_JS_HIDE}\"> <label for=\"${SET_JS_HIDE}\">显示隐藏的作品</label>`\n\n  const target = document.getElementById('post-list-posts')\n  if (target && target.parentNode) {\n    const div = document.createElement('div')\n    target.parentNode.insertBefore(div, target)\n    div.innerHTML = INPUT_HTML\n    // div.setAttribute('style', 'user-select: none; text-align: left;')\n    div.setAttribute('id', 'script-addition')\n  } else return\n\n  const checkbox = document.getElementById(SET_JS_HIDE)\n  checkbox.checked = JSON.parse(localStorage.getItem(SET_JS_HIDE))\n  update()\n  checkbox.addEventListener('change', update)\n\n  function update() {\n    Array.from(document.querySelectorAll('.javascript-hide')).forEach(element => {\n      if (checkbox.checked) element.removeClassName(SET_JS_HIDE)\n      else element.addClassName(SET_JS_HIDE)\n    })\n    localStorage.setItem(SET_JS_HIDE, checkbox.checked)\n  }\n})()\n\n/**\n * 默认尺寸 h=150px\n * 大图模式 h=300px\n * 高清模式 显示高清大图 parent\n */\n;(function() {\n  const target = document.getElementById(`script-addition`)\n\n  if (target) {\n    // const SET_POST_HD = `set-post-hd`\n    // const isHD = Boolean(JSON.parse(localStorage.getItem(SET_POST_HD)))\n\n    const SET_POST_SIZE = `set-post-size`\n    if (getHDValue() === false) {\n      target.insertAdjacentHTML(`beforeend`, `<input type=\"checkbox\" id=\"${SET_POST_SIZE}1\">`)\n      target.insertAdjacentHTML(`beforeend`, `<label for=\"${SET_POST_SIZE}1\">默认尺寸</label>`)\n      target.insertAdjacentHTML(`beforeend`, `<input type=\"checkbox\" id=\"${SET_POST_SIZE}2\">`)\n      target.insertAdjacentHTML(`beforeend`, `<label for=\"${SET_POST_SIZE}2\">大图模式</label>`)\n    }\n    target.insertAdjacentHTML(`beforeend`, `<input type=\"checkbox\" id=\"${SET_POST_SIZE}3\">`)\n    target.insertAdjacentHTML(`beforeend`, `<label for=\"${SET_POST_SIZE}2\">高清模式</label>`)\n\n    const checkbox1 = document.getElementById(`${SET_POST_SIZE}1`)\n    const checkbox2 = document.getElementById(`${SET_POST_SIZE}2`)\n    const checkbox3 = document.getElementById(`${SET_POST_SIZE}3`)\n    update()\n\n    checkbox1 && checkbox1.addEventListener(`change`, changeValue)\n    checkbox2 && checkbox2.addEventListener(`change`, changeValue)\n    checkbox3.addEventListener(`change`, changeHDValue)\n\n    function getValue() {\n      return Boolean(JSON.parse(localStorage.getItem(SET_POST_SIZE)))\n    }\n    function changeValue() {\n      const value = getValue()\n      localStorage.setItem(SET_POST_SIZE, JSON.stringify(!value))\n      location.reload() // 刷新页面\n    }\n    function getHDValue() {\n      return Boolean(JSON.parse(localStorage.getItem(`set-post-hd`)))\n    }\n    function changeHDValue() {\n      const value = getHDValue()\n      localStorage.setItem(`set-post-hd`, JSON.stringify(!value))\n      location.reload() // 刷新页面\n    }\n    function update() {\n      if (getHDValue() === true) {\n        checkbox3.checked = true\n        target.insertAdjacentHTML(`beforeend`, `<div id=\"script-notice-hd\">高清模式加载缓慢，可能需要等待一段时间。</div>`)\n        // setTimeout(() => document.getElementById(`script-notice-hd`).remove(), 10000)\n        const imageList = document.querySelectorAll(`img.preview`)\n        imageList.forEach(x => x.src = x.parentNode.parentNode.nextElementSibling.href)\n        document.head.insertAdjacentHTML(`beforeend`, `<style>#post-list-posts>li>.inner{zoom:2.5;}</style>`)\n      } else if (getValue() === false) {\n        checkbox1.checked = true\n        checkbox2.checked = false\n        checkbox3.checked = false\n      } else {\n        checkbox1.checked = false\n        checkbox2.checked = true\n        checkbox3.checked = false\n        document.head.insertAdjacentHTML(`beforeend`, `<style>img.preview{width:auto;height:auto;}</style>`)\n        document.head.insertAdjacentHTML(`beforeend`, `<style>#post-list-posts>li>.inner{height:auto !important;}</style>`)\n      }\n    }\n  }\n})()\n"
  },
  {
    "path": "temp/index.user.js",
    "content": "// ==UserScript==\n// @name         Yande.re 简体中文\n// @namespace    com.coderzhaoziwei.yandere\n// @version      1.0.10\n// @author       Coder Zhao\n// @description  Y 站简体中文补丁| 显示隐藏作品 | 高清大图模式 | 界面布局优化 | 方向键翻页 | Simplified Chinese patch for Yande.re\n// @modified     2021/5/7 01:12:31\n// @license      MIT\n// @homepage     https://greasyfork.org/zh-CN/scripts/421970\n// @match        https://yande.re/*\n// @exclude      https://yande.re/forum/*\n// @match        https://yande.in/*\n// @match        https://oreno.imouto.us/*\n// @match        https://konachan.com/*\n// @supportURL   https://github.com/coderzhaoziwei/yande-re-chinese-patch/issues\n// @grant        none\n// ==/UserScript==\n\n/******/ (() => { // webpackBootstrap\n/******/ \t\"use strict\";\n/******/ \tvar __webpack_modules__ = ({\n\n/***/ 798:\n/***/ (() => {\n\n\n;// CONCATENATED MODULE: ./tags.json\nconst 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\":\"百合\"}');\n;// CONCATENATED MODULE: ./style.css\n/* 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\");\n;// CONCATENATED MODULE: ./index.js\n\n(function() {\n  const list = Array.from(document.getElementsByTagName('a'))\n  list.forEach(a => {\n    const href = a.getAttribute('href')\n    if (typeof href === 'string' && /^\\/post\\?tags=(\\S+)$/.test(href)) {\n      const en = RegExp.$1\n      const cn = tags_namespaceObject[en]\n      if (cn) a.innerText = `[${cn}]${en.replace(/_/g, ' ')}`\n    }\n  })\n})()\n\n/**\n * 创建 <style> 标签，导入 style.css 的内容。\n */\n;(function() {\n  const element = document.createElement('style')\n  element.innerHTML = style\n  document.head.appendChild(element)\n})()\n\n/**\n * 导航栏，替换主菜单和子菜单的部分文本内容。\n */\n;(function() {\n  const list1 = Array.from(document.querySelectorAll('#main-menu>ul>li>a'))\n  const list2 = Array.from(document.querySelectorAll('ul.submenu>li>a'))\n  const list  = [...list1, ...list2]\n\n  list.forEach(menu => {\n    if (menu.getAttribute('href') === '#') return\n    const en = menu.innerText\n    const cn = {\n      /* 主菜单 */\n      'My Account': '账户',\n      'Posts':      '作品',\n      'Comments':   '评论',\n      'Notes':      '笔记',\n      'Artists':    '画师',\n      'Tags':       '标签',\n      'Forum':      '论坛',\n      'Help':       '帮助',\n      'More »':     '更多>>',\n      'New Mail':   '新消息',\n      /* 子菜单 */\n      'My Profile':      '我的资料',\n      'My Mail':         '我的消息',\n      'My Favorites':    '我的收藏',\n      'Settings':        '设置',\n      'Change Password': '修改密码',\n      'Logout':          '退出登录',\n      'View Posts':      '浏览作品',\n      'Search Posts':    '搜索作品',\n      'Upload':          '上传',\n      'Random':          '随机浏览',\n      'Popular':         '热门',\n      'Image Search':    '搜索图片',\n      'History':         '历史',\n      'View Comments':   '浏览评论',\n      'Search Comments': '搜索评论',\n      'View Notes':      '浏览笔记',\n      'Search Notes':    '搜索笔记',\n      'View Artists':    '浏览画师',\n      'Search Artists':  '搜索画师',\n      'Create':          '创建',\n      'View Tags':       '浏览标签',\n      'Search Tags':     '搜索标签',\n      'Aliases':         '别名',\n      'Implications':    '含义',\n      'View Pools':      '浏览 Pools',\n      'Search Pools':    '搜索 Pools',\n      'Create New Pool': '创建 Pool',\n      'View Wiki Index': '浏览 Wiki 主页',\n      'Search Wiki':     '搜索 Wiki',\n      'Create New Page': '创建新页面',\n      'Mark All Read':   '全部标记已读',\n    }[en]\n    if (typeof cn === 'string') menu.innerText = cn\n  })\n})()\n\n/**\n * 提示信息\n * EN: This image has been resized. Click on the `View larger version` link in the sidebar\n *     for a high-quality version. Hide this message\n * CN: 这张图片已经被压缩，单击侧边栏中的 `显示高清图` 可以获取更高质量的版本。不再提醒\n *\n * EN: This post belongs to a parent post.\n * EN: This post has child posts. (post #728160, 746235)\n * EN: This post has a child post. (post #383703)\n  </div>\n */\n;(function() {\n  Array.from(document.querySelectorAll('.status-notice')).forEach(element => {\n    console.log(element.innerHTML)\n    element.innerHTML = element.innerHTML\n      .replace(/^[\\s]+This image has been resized. Click on the /, '这张图片已经被压缩，单击侧边栏中的')\n      .replace(/View larger version/, '显示高清图')\n      .replace(/ link in the sidebar for a high-quality version./, '可以获取更高质量的版本。')\n      .replace(/Hide this message<\\/a>\\./, '不再提醒</a>')\n      /* 相关父作品 */\n      .replace(/This post belongs to a /, '这张图片从属于一个').replace(/parent post<\\/a>\\./, '相关父作品</a>。')\n      /* 相关子作品 */\n      .replace(/This post has /, '这张图片从属于一个')\n      .replace(/child posts<\\/a>\\. \\(post #/, '作品集</a>。相关子作品：')\n      .replace(/a child post<\\/a>\\. \\(post #/, '作品集</a>。相关子作品：')\n      .replace(/<\\/a>, <a /, '</a> | <a ').replace(/<\\/a>\\)/, '</a>')\n  })\n})()\n\n/**\n * 快捷操作，替换指定的元素的文本内容。\n */\n;(function() {\n  const translate = function(selector, en, cn) {\n    const element = document.querySelector(selector)\n    if (element) element.innerText = element.innerText.replace(en, cn)\n  }\n  const list = [\n    ['#highres-show',                   'View larger version',     '显示高清图'],\n    ['#highres',                        'Download larger version', '下载高清图'],\n    ['#png',                            'Download PNG',            '下载 PNG 图'],\n    ['li#add-to-favs>a',                'Add to favorites',        '添加收藏'],\n    ['li#set-avatar>a',                 'Set avatar',              '设置头像'],\n    ['h4>a.js-posts-show-edit-tab',     'Edit',                    '编辑'],\n    ['h4>a.js-posts-show-comments-tab', 'Respond',                 '评论'],\n    ['.pagination>.previous_page',      '← Previous',              '上一页'],\n    ['.pagination>.next_page',          'Next →',                  '下一页'],\n  ]\n  list.forEach(item => translate(...item))\n  /* 页脚 */\n  Array.from(document.querySelectorAll('#subnavbar>li>a')).forEach(a => {\n    const en = a.innerText\n    const cn = {\n      'List': '首页',\n      'Browse': '翻阅',\n      'Upload': '上传',\n      'Random': '随机',\n      'Popular': '热门',\n      'Image Search': '寻图',\n      'History': '历史',\n      'Help': '帮助',\n    }[en]\n    if (cn) a.innerText = cn\n  })\n})()\n\n/**\n * 翻页功能，使用键盘左右方向键控制。\n */\n;(function() {\n  window.addEventListener('keyup', function(event) {\n    /* 在输入的情况下，方向键禁止触发翻页。 */\n    if (/^(TEXTAREA|INPUT|SELECT|BUTTON)$/.test(document.activeElement.tagName)) return\n\n    const prev = document.querySelector('.pagination>.previous_page')\n    const next = document.querySelector('.pagination>.next_page')\n    if (event.key == 'ArrowLeft'  && prev) {\n      prev.click()\n      return event.preventDefault()\n    }\n    if (event.key == 'ArrowRight' && next) {\n      next.click()\n      return event.preventDefault()\n    }\n  })\n})()\n\n/**\n * 默认显示隐藏的作品，并提供可开关的选项。\n */\n;(function() {\n  const SET_JS_HIDE = 'set-javascript-hide'\n  const INPUT_HTML = `<input type=\"checkbox\" id=\"${SET_JS_HIDE}\"> <label for=\"${SET_JS_HIDE}\">显示隐藏的作品</label>`\n\n  const target = document.getElementById('post-list-posts')\n  if (target && target.parentNode) {\n    const div = document.createElement('div')\n    target.parentNode.insertBefore(div, target)\n    div.innerHTML = INPUT_HTML\n    // div.setAttribute('style', 'user-select: none; text-align: left;')\n    div.setAttribute('id', 'script-addition')\n  } else return\n\n  const checkbox = document.getElementById(SET_JS_HIDE)\n  checkbox.checked = JSON.parse(localStorage.getItem(SET_JS_HIDE))\n  update()\n  checkbox.addEventListener('change', update)\n\n  function update() {\n    Array.from(document.querySelectorAll('.javascript-hide')).forEach(element => {\n      if (checkbox.checked) element.removeClassName(SET_JS_HIDE)\n      else element.addClassName(SET_JS_HIDE)\n    })\n    localStorage.setItem(SET_JS_HIDE, checkbox.checked)\n  }\n})()\n\n/**\n * 默认尺寸 h=150px\n * 大图模式 h=300px\n * 高清模式 显示高清大图\n */\n;(function() {\n  const target = document.getElementById(`script-addition`)\n\n  if (target) {\n    // const SET_POST_HD = `set-post-hd`\n    // const isHD = Boolean(JSON.parse(localStorage.getItem(SET_POST_HD)))\n\n    const SET_POST_SIZE = `set-post-size`\n    if (getHDValue() === false) {\n      target.insertAdjacentHTML(`beforeend`, `<input type=\"checkbox\" id=\"${SET_POST_SIZE}1\">`)\n      target.insertAdjacentHTML(`beforeend`, `<label for=\"${SET_POST_SIZE}1\">默认尺寸</label>`)\n      target.insertAdjacentHTML(`beforeend`, `<input type=\"checkbox\" id=\"${SET_POST_SIZE}2\">`)\n      target.insertAdjacentHTML(`beforeend`, `<label for=\"${SET_POST_SIZE}2\">大图模式</label>`)\n    }\n    target.insertAdjacentHTML(`beforeend`, `<input type=\"checkbox\" id=\"${SET_POST_SIZE}3\">`)\n    target.insertAdjacentHTML(`beforeend`, `<label for=\"${SET_POST_SIZE}2\">高清模式</label>`)\n\n    const checkbox1 = document.getElementById(`${SET_POST_SIZE}1`)\n    const checkbox2 = document.getElementById(`${SET_POST_SIZE}2`)\n    const checkbox3 = document.getElementById(`${SET_POST_SIZE}3`)\n    update()\n\n    checkbox1 && checkbox1.addEventListener(`change`, changeValue)\n    checkbox2 && checkbox2.addEventListener(`change`, changeValue)\n    checkbox3.addEventListener(`change`, changeHDValue)\n\n    function getValue() {\n      return Boolean(JSON.parse(localStorage.getItem(SET_POST_SIZE)))\n    }\n    function changeValue() {\n      const value = getValue()\n      localStorage.setItem(SET_POST_SIZE, JSON.stringify(!value))\n      location.reload() // 刷新页面\n    }\n    function getHDValue() {\n      return Boolean(JSON.parse(localStorage.getItem(`set-post-hd`)))\n    }\n    function changeHDValue() {\n      const value = getHDValue()\n      localStorage.setItem(`set-post-hd`, JSON.stringify(!value))\n      location.reload() // 刷新页面\n    }\n    function update() {\n      if (getHDValue() === true) {\n        checkbox3.checked = true\n        target.insertAdjacentHTML(`beforeend`, `<div id=\"script-notice-hd\">高清模式加载缓慢，可能需要等待一段时间。</div>`)\n        // setTimeout(() => document.getElementById(`script-notice-hd`).remove(), 10000)\n        const imageList = document.querySelectorAll(`img.preview`)\n        imageList.forEach(x => x.src = x.parentNode.parentNode.nextElementSibling.href)\n        document.head.insertAdjacentHTML(`beforeend`, `<style>#post-list-posts>li>.inner{zoom:2.5;}</style>`)\n      } else if (getValue() === false) {\n        checkbox1.checked = true\n        checkbox2.checked = false\n        checkbox3.checked = false\n      } else {\n        checkbox1.checked = false\n        checkbox2.checked = true\n        checkbox3.checked = false\n        document.head.insertAdjacentHTML(`beforeend`, `<style>img.preview{width:auto;height:auto;}</style>`)\n        document.head.insertAdjacentHTML(`beforeend`, `<style>#post-list-posts>li>.inner{height:auto !important;}</style>`)\n      }\n    }\n  }\n})()\n\n\n/***/ })\n\n/******/ \t});\n/************************************************************************/\n/******/ \t\n/******/ \t// startup\n/******/ \t// Load entry module and return exports\n/******/ \t// This entry module doesn't tell about it's top-level declarations so it can't be inlined\n/******/ \tvar __webpack_exports__ = {};\n/******/ \t__webpack_modules__[798]();\n/******/ \t\n/******/ })()\n;"
  },
  {
    "path": "temp/webpack.config.js",
    "content": "const path = require('path')\nconst config = require('./package.json')\nconst { BannerPlugin } = require('webpack')\n\nconst banner = `\n`\n\nmodule.exports = {\n  mode: 'production',\n  entry: './index.js',\n  output: {\n    path: path.resolve(__dirname, ''),\n    filename: `index.user.js`,\n  },\n  module: {\n    rules: [\n      { test: /\\.css$/, use: './css_text_loader.js' },\n    ],\n  },\n  plugins: [\n    new BannerPlugin({ banner, raw: true, entryOnly: true }),\n  ],\n  optimization: {\n    minimize: true,\n    minimizer: [],\n  },\n}\n"
  }
]