Greasy Fork

Greasy Fork is available in English.

帕秋莉

pixiv 搜寻/浏览 工具

当前为 2018-05-12 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name              Patchouli
// @name:en           Patchouli
// @name:ja           パチュリー
// @name:zh-CN        帕秋莉
// @name:zh-TW        帕秋莉
// @namespace         https://github.com/FlandreDaisuki
// @description       An image searching/browsing tool on pixiv
// @description:en    An image searching/browsing tool on pixiv
// @description:ja    pixiv 検索機能強化
// @description:zh-CN pixiv 搜寻/浏览 工具
// @description:zh-TW pixiv 搜尋/瀏覽 工具
// @include           *://www.pixiv.net/*
// @require           https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.min.js
// @require           https://cdnjs.cloudflare.com/ajax/libs/vuex/3.0.1/vuex.min.js
// @require           https://cdnjs.cloudflare.com/ajax/libs/vue-i18n/7.4.2/vue-i18n.min.js
// @require           https://cdnjs.cloudflare.com/ajax/libs/axios/0.17.1/axios.min.js
// @icon              http://i.imgur.com/VwoYc5w.png
// @noframes
// @author            FlandreDaisuki
// @license           The MIT License (MIT) Copyright (c) 2016-2018 FlandreDaisuki
// @compatible        firefox >=52
// @compatible        chrome >=55
// @version           4.0.9
// @grant             none
// ==/UserScript==

(function (Vue,Vuex,VueI18n) {
  'use strict';

  function __$styleInject( css ) {
      if(!css) return ;

      if(typeof(window) == 'undefined') return ;
      let style = document.createElement('style');

      style.innerHTML = css;
      document.head.appendChild(style);
      return css;
  }

  Vue = Vue && Vue.hasOwnProperty('default') ? Vue['default'] : Vue;
  Vuex = Vuex && Vuex.hasOwnProperty('default') ? Vuex['default'] : Vuex;
  VueI18n = VueI18n && VueI18n.hasOwnProperty('default') ? VueI18n['default'] : VueI18n;

  __$styleInject("._global-header {\n  /* FIXME: Chrome will show #koakuma on top of header */\n  z-index: 4;\n  transform: translate(0);\n}\n._global-header.koakuma-placeholder {\n  /* I don't know why #koakuma just 32px\n     but it should preserve 42px to keep all spacing correct */\n  margin-bottom: 42px;\n}\n.ω {\n  display: -webkit-box;\n  display: -ms-flexbox;\n  display: flex;\n  -webkit-box-orient: horizontal;\n  -webkit-box-direction: normal;\n      -ms-flex-flow: row wrap;\n          flex-flow: row wrap;\n  -webkit-box-pack: center;\n      -ms-flex-pack: center;\n          justify-content: center;\n}\n.ω,\n.ω .layout-a,\n.ω .layout-body {\n  -webkit-transition: width 0.2s;\n  transition: width 0.2s;\n}\n.ω.↔,\n.ω.↔ .layout-a,\n.ω.↔ .layout-body {\n  width: 100% !important;\n}\n.ω.↔ .layout-a {\n  display: -webkit-box;\n  display: -ms-flexbox;\n  display: flex;\n  -webkit-box-orient: horizontal;\n  -webkit-box-direction: reverse;\n  -ms-flex-direction: row-reverse;\n  flex-direction: row-reverse;\n}\n.ω.↔ .layout-column-2 {\n  -webkit-box-flex: 1;\n  -ms-flex: 1;\n  flex: 1;\n  margin-left: 20px;\n}\n.ω.↔ .layout-body,\n.ω.↔ .layout-a {\n  margin: 10px 20px;\n}\n");

  function $(selector) {
    return document.querySelector(selector);
  }
  function $$(selector) {
    return [...document.querySelectorAll(selector)];
  }
  function $$find(doc, selector) {
    return [...doc.querySelectorAll(selector)];
  }
  function $el(tag, attr = {}, cb = () => {}) {
    const el = document.createElement(tag);
    Object.assign(el, attr);
    cb(el);
    return el;
  }
  function $error(...args) {
    console.error.apply(console, args);
  }
  (() => {
    Math.clamp = (val, min, max) => Math.min(Math.max(min, val), max);
    Number.toInt = (s) => (isNaN(~~s) ? 0 : ~~s);
    (function(arr) {
      arr.forEach(function(item) {
        if (item.hasOwnProperty('after')) {
          return;
        }
        Object.defineProperty(item, 'after', {
          configurable: true,
          enumerable: true,
          writable: true,
          value: function after() {
            const argArr = Array.prototype.slice.call(arguments);
            const docFrag = document.createDocumentFragment();
            argArr.forEach(function(argItem) {
              const isNode = argItem instanceof Node;
              docFrag.appendChild(isNode ? argItem : document.createTextNode(String(argItem)));
            });
            this.parentNode.insertBefore(docFrag, this.nextSibling);
          }
        });
      });
    })([Element.prototype, CharacterData.prototype, DocumentType.prototype]);
  })();
  class Pixiv {
    constructor() {
      this.tt = $('input[name="tt"]').value;
    }
    async fetch(url) {
      try {
        if (url) {
          const res = await axios.get(url);
          if (res.status !== 200) {
            throw new Error(`${res.status} ${res.statusText}`);
          } else {
            return res.data;
          }
        } else {
          $error('Pixiv#fetch has no url');
        }
      } catch (error) {
        $error('Pixiv#fetch: error:', error);
      }
    }
    async getLegacyPageHTMLIllustIds(url, { needBookmarkId } = { needBookmarkId: false }) {
      try {
        const html = await this.fetch(url);
        const nextTag = html.match(/class="next"[^/]*/);
        let nextUrl = '';
        if (nextTag) {
          const nextHref = nextTag[0].match(/href="([^"]+)"/);
          if (nextHref) {
            const query = nextHref[1].replace(/&/g, '&');
            if (query) {
              nextUrl = `${location.pathname}${query}`;
            }
          }
        }
        const iidHTMLs = html.match(/;illust_id=\d+"\s*class="work/g) || [];
        const illustIds = [];
        for (const dataid of iidHTMLs) {
          const iid = dataid.replace(/\D+(\d+).*/, '$1');
          if (!illustIds.includes(iid) && iid !== '0') {
            illustIds.push(iid);
          }
        }
        const ret = {
          nextUrl,
          illustIds
        };
        if (needBookmarkId) {
          ret.bookmarkIds = {};
          const bimHTMLs = html.match(/name="book_id[^;]+;illust_id=\d+/g) || [];
          for (const bim of bimHTMLs) {
            const [illustId, bookmarkId] = bim.replace(/\D+(\d+)\D+(\d+)/, '$2 $1').split(' ');
            if (illustIds.includes(illustId)) {
              ret.bookmarkIds[illustId] = { illustId, bookmarkId };
            }
          }
        }
        return ret;
      } catch (error) {
        $error('Pixiv#getLegacyPageHTMLIllustIds: error:', error);
      }
    }
    async getPageHTMLIllustIds(url) {
      try {
        const html = await this.fetch(url);
        const nextTag = html.match(/class="next"[^/]*/);
        let nextUrl = '';
        if (nextTag) {
          const nextHref = nextTag[0].match(/href="([^"]+)"/);
          if (nextHref) {
            const query = nextHref[1].replace(/&/g, '&');
            if (query) {
              nextUrl = `${location.pathname}${query}`;
            }
          }
        }
        const iidHTMLs = html.match(/illustId":"(\d+)"/g) || [];
        const illustIds = [];
        for (const dataid of iidHTMLs) {
          const iid = dataid.replace(/\D+(\d+).*/, '$1');
          if (!illustIds.includes(iid) && iid !== '0') {
            illustIds.push(iid);
          }
        }
        const ret = {
          nextUrl,
          illustIds
        };
        return ret;
      } catch (error) {
        $error('Pixiv#getPageHTMLIllustIds: error:', error);
      }
    }
    async getBookmarkHTMLDetails(illustIds) {
      const bookmarkHTMLDetails = illustIds.map(id => this.getBookmarkHTMLDetail(id));
      const bookmarkDetails = await Promise.all(bookmarkHTMLDetails);
      const detail = {};
      for (const d of bookmarkDetails) {
        detail[d.illustId] = d;
      }
      return detail;
    }
    async getBookmarkHTMLDetail(illustId) {
      const url = `/bookmark_detail.php?illust_id=${illustId}`;
      try {
        const html = await this.fetch(url);
        const bkMatches = html.match(/<i class="_icon _bookmark-icon-inline"><\/i>(\d+)/);
        const bookmarkCount = bkMatches ? parseInt(bkMatches[1]) : 0;
        const tagsListHTML = html.match(/<ul class="tags[^>]+>.*?(?=<\/ul>)/);
        const tagHTMLs = tagsListHTML ? tagsListHTML[0].match(/>[^<]+?(?=<\/a>)/g) : [];
        const tags = tagHTMLs ? tagHTMLs.map(x => x.slice(1)) : [];
        return {
          bookmarkCount,
          illustId,
          tags
        };
      } catch (error) {
        $error('Pixiv#getBookmarkHTMLDetail: error:', error);
      }
    }
    async getIllustsAPIDetail(illustIds) {
      const iids = illustIds.join(',');
      const url = `/rpc/index.php?mode=get_illust_detail_by_ids&illust_ids=${iids}&tt=${this.tt}`;
      try {
        const json = await this.fetch(url);
        if (json.error) {
          throw new Error(json.message);
        }
        const details = json.body;
        for (const [key, detail] of Object.entries(details)) {
          if (detail.error) {
            delete details[key];
          }
        }
        return details;
      } catch (error) {
        $error('Pixiv#getIllustsAPIDetail: error:', error);
      }
    }
    async getUsersAPIDetail(userIds) {
      const uids = [...new Set(userIds)].join(',');
      const url = `/rpc/get_profile.php?user_ids=${uids}&tt=${this.tt}`;
      try {
        const json = await this.fetch(url);
        if (json.error) {
          throw new Error(json.message);
        }
        const details = {};
        for (const u of json.body) {
          details[u.user_id] = {
            userId: u.user_id,
            isFollow: u.is_follow
          };
        }
        return details;
      } catch (error) {
        $error('Pixiv#getUsersAPIDetail: error:', error);
      }
    }
    async getRecommendationsAPIDetails(illustIds = 'auto', numRecommendations = 500) {
      const searchParams = {
        type: 'illust',
        sample_illusts: illustIds,
        num_recommendations: numRecommendations,
        tt: this.tt
      };
      const url = `/rpc/recommender.php?${searchParams.entries.map(p => p.join('=')).join('&')}`;
      try {
        const data = await this.fetch(url);
        return data.recommendations.map(x => `${x}`);
      } catch (error) {
        $error('Pixiv#getRecommendationsAPIDetails: error:', error);
      }
    }
    async postBookmarkAdd(illustId) {
      const searchParams = {
        mode: 'save_illust_bookmark',
        illust_id: illustId,
        restrict: 0,
        comment: '',
        tags: '',
        tt: this.tt
      };
      const data = searchParams.entries.map(p => p.join('=')).join('&');
      const config = {
        'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
      };
      try {
        const res = await axios.post('/rpc/index.php', data, config);
        if (res.statusText === 'OK') {
          return !res.data.error;
        } else {
          throw new Error(res.statusText);
        }
      } catch (error) {
        $error('Pixiv#postBookmarkAdd: error:', error);
      }
    }
  }
  function removeAnnoyings(doc = document) {
    const annoyings = [
      'iframe',
      '.ad',
      '.ads_area',
      '.ad-footer',
      '.ads_anchor',
      '.ads-top-info',
      '.comic-hot-works',
      '.user-ad-container',
      '.ads_area_no_margin',
      '.hover-item',
      '.ad-printservice',
      '.bookmark-ranges',
      '.require-premium',
      '.showcase-reminder',
      '.sample-user-search',
      '.popular-introduction',
      '._premium-lead-tag-search-bar',
      '._premium-lead-popular-d-body'
    ];
    for (const selector of annoyings) {
      for (const el of $$find(doc, selector)) {
        el.remove();
      }
    }
  }
  const PixivAPI = new Pixiv();
  function makeLibraryData({ pageType, illustAPIDetails, bookmarkHTMLDetails, userAPIDetails }) {
    if (!illustAPIDetails || !Object.keys(illustAPIDetails).length) {
      throw new Error('makeLibraryData: illustAPIDetails is falsy.');
    }
    const vLibrary = [];
    for (const [illustId, illustDetail] of Object.entries(illustAPIDetails)) {
      const d = {
        illustId,
        bookmarkCount: bookmarkHTMLDetails[illustId].bookmarkCount,
        tags: bookmarkHTMLDetails[illustId].tags.join(', '),
        illustTitle: illustDetail.illust_title,
        illustPageCount: Number.toInt(illustDetail.illust_page_count),
        userId: illustDetail.user_id,
        userName: illustDetail.user_name,
        isFollow: userAPIDetails[illustDetail.user_id].isFollow,
        isBookmarked: illustDetail.is_bookmarked,
        isUgoira: !!illustDetail.ugoira_meta,
        profileImg: illustDetail.profile_img,
        url: {
          big: illustDetail.url.big,
          sq240: illustDetail.url['240mw'].replace('240x480', '240x240')
        }
      };
      if (pageType === 'MY_BOOKMARK') {
        d.bookmarkId = illustDetail.bookmarkId;
      }
      vLibrary.push(d);
    }
    return vLibrary;
  }
  var pixiv = {
    state: {
      imgLibrary: [],
      isPaused: true,
      isEnded: false,
      nextUrl: location.href
    },
    mutations: {
      pause(state) {
        state.isPaused = true;
      },
      stop(state) {
        state.isPaused = true;
        state.isEnded = true;
      },
    },
    actions: {
      async start({ state, dispatch, rootState }, { times } = {}) {
        times = times || Infinity;
        if (state.isEnded || times <= 0) {
          return;
        }
        switch (rootState.pageType) {
        case 'SEARCH':
        case 'NEW_ILLUST':
        case 'MY_BOOKMARK':
        case 'MEMBER_ILLIST':
        case 'MEMBER_BOOKMARK':
        case 'ANCIENT_NEW_ILLUST':
          await dispatch('startNextUrlBased', { times });
          break;
        default:
          break;
        }
      },
      async startNextUrlBased({ state, commit, rootState }, { times } = {}) {
        state.isPaused = false;
        while (!state.isPaused && !state.isEnded && times) {
          let page = null;
          if (['SEARCH', 'NEW_ILLUST'].includes(rootState.pageType)) {
            page = await PixivAPI.getPageHTMLIllustIds(state.nextUrl);
          } else {
            page = await PixivAPI.getLegacyPageHTMLIllustIds(state.nextUrl, {
              needBookmarkId: rootState.pageType === 'MY_BOOKMARK'
            });
          }
          state.nextUrl = page.nextUrl;
          const illustAPIDetails = await PixivAPI.getIllustsAPIDetail(page.illustIds);
          if (rootState.pageType === 'MY_BOOKMARK') {
            const myBookmarkAPIDetails = page.bookmarkIds;
            for (const [illustId, illustDetail] of Object.entries(illustAPIDetails)) {
              const bookmarkId = myBookmarkAPIDetails[illustId].bookmarkId;
              if (bookmarkId) {
                illustDetail.bookmarkId = bookmarkId;
              }
            }
          }
          const bookmarkHTMLDetails = await PixivAPI.getBookmarkHTMLDetails(Object.keys(illustAPIDetails));
          const userIds = Object.values(illustAPIDetails).map(d => d.user_id);
          const userAPIDetails = await PixivAPI.getUsersAPIDetail(userIds);
          const libraryData = makeLibraryData({ pageType: rootState.pageType, illustAPIDetails, bookmarkHTMLDetails, userAPIDetails });
          for (const d of libraryData) {
            if (!state.imgLibrary.find(x => x.illustId === d.illustId)) {
              state.imgLibrary.push(d);
            }
          }
          times -= 1;
          if (!times) {
            commit('pause');
          }
          if (!state.nextUrl) {
            commit('stop');
          }
        }
      }
    },
    getters: {
      filteredLibrary(state, getters, rootState) {
        const cloneLibrary = state.imgLibrary.slice();
        return cloneLibrary
          .filter(el => el.bookmarkCount >= rootState.filters.limit)
          .filter(el => el.tags.match(rootState.filters.tag))
          .sort(
            (a, b) =>
              Number.toInt(b[rootState.filters.orderBy]) -
              Number.toInt(a[rootState.filters.orderBy])
          );
      }
    }
  };
  Vue.use(Vuex);
  const pageType = (() => {
    const path = location.pathname;
    const searchParam = new URLSearchParams(location.search);
    const spId = searchParam.get('id');
    const spType = searchParam.get('type');
    switch (path) {
    case '/search.php':
      return 'SEARCH';
    case '/bookmark_new_illust_r18.php':
    case '/bookmark_new_illust.php':
      return 'NEW_ILLUST';
    case '/new_illust.php':
    case '/mypixiv_new_illust.php':
    case '/new_illust_r18.php':
      return 'ANCIENT_NEW_ILLUST';
    case '/member_illust.php':
      return spId ? 'MEMBER_ILLIST' : 'NO_SUPPORT';
    case '/bookmark.php': {
      if (spId && spType !== 'user') {
        return 'MEMBER_BOOKMARK';
      } else if (!spType || spType === 'illust_all') {
        return 'MY_BOOKMARK';
      } else {
        return 'NO_SUPPORT';
      }
    }
    default:
      return 'NO_SUPPORT';
    }
  })();
  var store = new Vuex.Store({
    modules: { pixiv },
    state: {
      locale: document.documentElement.lang,
      pageType,
      koakumaMountPoint: null,
      patchouliMountPoint: null,
      VERSION: GM_info.script.version,
      NAME: GM_info.script.name,
      filters: {
        limit: 0,
        tag: new RegExp('', 'i'),
        orderBy: 'illustId'
      },
      config: {
        fitwidth: 1,
        sort: 0
      }
    },
    mutations: {
      prepareMountPoint(state) {
        if (pageType !== 'NO_SUPPORT') {
          $('#wrapper').classList.add('ω');
          state.koakumaMountPoint = $el('div', { className: 'koakumaMountPoint' }, (el) => {
            $('header._global-header').after(el);
          });
          if (pageType === 'SEARCH') {
            state.patchouliMountPoint = $('#js-react-search-mid');
          } else if (pageType === 'NEW_ILLUST') {
            state.patchouliMountPoint = $('#js-mount-point-latest-following');
          } else {
            const li = $('li.image-item');
            const ul = $('ul._image-items');
            state.patchouliMountPoint = li ? li.parentElement : ul;
          }
        }
      },
      applyConfig(state) {
        if (state.pageType !== 'NO_SUPPORT') {
          if (state.config.fitwidth) {
            $('.ω').classList.add('↔');
          } else {
            $('.ω').classList.remove('↔');
          }
          if (state.config.sort) {
            state.filters.orderBy = 'bookmarkCount';
          } else {
            state.filters.orderBy = 'illustId';
          }
          if (state.pageType === 'MY_BOOKMARK') {
            for (const marker of $$('.js-legacy-mark-all, .js-legacy-unmark-all')) {
              marker.addEventListener('click', () => {
                $$('input[name="book_id[]"]').forEach(el => {
                  el.checked = marker.classList.contains('js-legacy-mark-all');
                });
              });
            }
          }
        }
      },
      saveConfig(state) {
        const storable = JSON.stringify(state.config);
        localStorage.setItem(state.NAME, storable);
      },
      loadConfig(state) {
        const config = JSON.parse(localStorage.getItem(state.NAME) || '{}');
        Object.assign(state.config, config);
      }
    }
  });
  var script = {
    data() {
      return {
        debounceId0: null,
        debounceId1: null,
        usualSwitchOn: false,
        usualList: [100, 500, 1000, 3000, 5000, 10000]
      };
    },
    computed: {
      status() {
        return this.$store.state.pixiv;
      },
      config() {
        return this.$store.state.config;
      },
      statusClass() {
        return {
          end: this.status.isEnded,
          paused: !this.status.isPaused && !this.status.isEnded,
          go: this.status.isPaused && !this.status.isEnded
        };
      },
      filters() {
        return this.$store.state.filters;
      },
      buttonMsg() {
        if (this.status.isEnded) {
          return this.$t("koakuma.buttonEnd");
        } else if (this.status.isPaused) {
          return this.$t("koakuma.buttonGo");
        } else {
          return this.$t("koakuma.buttonPause");
        }
      },
      usualSwitchMsg() {
        return this.usualSwitchOn ? "⏶" : "⏷";
      }
    },
    methods: {
      clickMainButton() {
        if (this.status.isPaused) {
          this.$store.dispatch("start");
        } else {
          this.$store.commit("pause");
        }
      },
      sortInputWheel(event) {
        if (event.deltaY < 0) {
          this.filters.limit = Number.toInt(event.target.value) + 20;
        } else {
          this.filters.limit = Math.max(0, Number.toInt(event.target.value) - 20);
        }
      },
      sortInputInput(event) {
        if (this.debounceId0) {
          clearTimeout(this.debounceId0);
        }
        this.debounceId0 = setTimeout(() => {
          this.debounceId0 = null;
          this.filters.limit = Math.max(0, Number.toInt(event.target.value));
        }, 500);
      },
      optionsChange(event) {
        if (event.target.id === "koakuma-options-fit-browser-width-checkbox") {
          this.config.fitwidth = event.target.checked;
        } else if (
          event.target.id === "koakuma-options-sort-by-bookmark-count-checkbox"
        ) {
          this.config.sort = Number.toInt(event.target.checked);
        }
        this.$store.commit("saveConfig");
        this.$store.commit("applyConfig");
      },
      tagsFilterInput(event) {
        if (this.debounceId1) {
          clearTimeout(this.debounceId1);
        }
        this.debounceId1 = setTimeout(() => {
          this.debounceId1 = null;
          this.filters.tag = new RegExp(event.target.value, "ig");
        }, 1500);
      }
    }
  };
  const __vue_script__ = script;
  var __vue_render__ = function() {
    var _vm = this;
    var _h = _vm.$createElement;
    var _c = _vm._self._c || _h;
    return _c("div", { attrs: { id: "koakuma" } }, [
      _c("div", { staticClass: "processed" }, [
        _vm._v(
          _vm._s(
            _vm.$t("koakuma.processed", {
              count: _vm.$store.state.pixiv.imgLibrary.length
            })
          )
        )
      ]),
      _vm._v(" "),
      _c("div", { attrs: { id: "koakuma-bookmark-sort-block" } }, [
        _c(
          "label",
          {
            staticClass: "bookmark-count",
            attrs: { for: "koakuma-bookmark-sort-input" }
          },
          [
            _c("i", { staticClass: "_icon _bookmark-icon-inline" }),
            _vm._v(" "),
            _c("input", {
              attrs: {
                id: "koakuma-bookmark-sort-input",
                type: "number",
                min: "0",
                step: "1"
              },
              domProps: { value: _vm.filters.limit },
              on: {
                wheel: function($event) {
                  $event.stopPropagation();
                  $event.preventDefault();
                  return _vm.sortInputWheel($event)
                },
                input: _vm.sortInputInput
              }
            })
          ]
        ),
        _vm._v(" "),
        _c(
          "a",
          {
            class: _vm.usualSwitchOn ? "switch-on" : "switch-off",
            attrs: { id: "koakuma-bookmark-input-usual-switch", role: "button" },
            on: {
              click: function($event) {
                _vm.usualSwitchOn = !_vm.usualSwitchOn;
              }
            }
          },
          [_vm._v(_vm._s(_vm.usualSwitchMsg))]
        ),
        _vm._v(" "),
        _c(
          "ul",
          {
            directives: [
              {
                name: "show",
                rawName: "v-show",
                value: _vm.usualSwitchOn,
                expression: "usualSwitchOn"
              }
            ],
            attrs: { id: "koakuma-bookmark-input-usual-list" }
          },
          _vm._l(_vm.usualList, function(usual) {
            return _c("li", { key: usual }, [
              _c(
                "a",
                {
                  staticClass: "usual-list-link",
                  attrs: { role: "button" },
                  on: {
                    click: function($event) {
                      _vm.filters.limit = usual;
                      _vm.usualSwitchOn = false;
                    }
                  }
                },
                [_vm._v(_vm._s(usual))]
              )
            ])
          })
        )
      ]),
      _vm._v(" "),
      _c("div", [
        _c("input", {
          attrs: {
            id: "koakuma-bookmark-tags-filter-input",
            placeholder: _vm.$t("koakuma.tagsPlaceholder"),
            type: "text"
          },
          on: { input: _vm.tagsFilterInput }
        })
      ]),
      _vm._v(" "),
      _c("div", [
        _c(
          "button",
          {
            staticClass: "main-button",
            class: _vm.statusClass,
            attrs: { disabled: _vm.status.isEnded },
            on: { mouseup: _vm.clickMainButton }
          },
          [_vm._v("\n      " + _vm._s(_vm.buttonMsg) + "\n    ")]
        )
      ]),
      _vm._v(" "),
      _c("div", { attrs: { id: "koakuma-options-block" } }, [
        _c("div", [
          _c("input", {
            attrs: {
              id: "koakuma-options-fit-browser-width-checkbox",
              type: "checkbox"
            },
            domProps: { checked: _vm.config.fitwidth },
            on: { change: _vm.optionsChange }
          }),
          _vm._v(" "),
          _c(
            "label",
            { attrs: { for: "koakuma-options-fit-browser-width-checkbox" } },
            [_vm._v(_vm._s(_vm.$t("koakuma.fitWidth")))]
          )
        ]),
        _vm._v(" "),
        _c("div", [
          _c("input", {
            attrs: {
              id: "koakuma-options-sort-by-bookmark-count-checkbox",
              type: "checkbox"
            },
            domProps: { checked: _vm.config.sort },
            on: { change: _vm.optionsChange }
          }),
          _vm._v(" "),
          _c(
            "label",
            { attrs: { for: "koakuma-options-sort-by-bookmark-count-checkbox" } },
            [_vm._v(_vm._s(_vm.$t("koakuma.sortByBookmarkCount")))]
          )
        ])
      ])
    ])
  };
  var __vue_staticRenderFns__ = [];
  __vue_render__._withStripped = true;
  const __vue_template__ = typeof __vue_render__ !== 'undefined'
    ? { render: __vue_render__, staticRenderFns: __vue_staticRenderFns__ }
    : {};
  const __vue_inject_styles__ = function (inject) {
    if (!inject) return
    inject("data-v-462a1626_0", { source: "\n@-webkit-keyframes slidedown-data-v-462a1626 {\nfrom {\n    -webkit-transform: translateY(-100%);\n    transform: translateY(-100%);\n}\nto {\n    -webkit-transform: translateY(0);\n    transform: translateY(0);\n}\n}\n@keyframes slidedown-data-v-462a1626 {\nfrom {\n    -webkit-transform: translateY(-100%);\n    transform: translateY(-100%);\n}\nto {\n    -webkit-transform: translateY(0);\n    transform: translateY(0);\n}\n}\na[role=\"button\"][data-v-462a1626] {\n  text-decoration: none;\n}\n#koakuma[data-v-462a1626] {\n  display: -webkit-box;\n  display: -ms-flexbox;\n  display: flex;\n  -webkit-box-pack: center;\n  -ms-flex-pack: center;\n  justify-content: center;\n  -webkit-box-align: center;\n  -ms-flex-align: center;\n  align-items: center;\n  position: -webkit-sticky;\n  position: sticky;\n  top: 0;\n  z-index: 3;\n  background-color: #e5e4ff;\n  -webkit-box-shadow: 0 2px 2px #777;\n  box-shadow: 0 2px 2px #777;\n  padding: 4px;\n  color: #00186c;\n  font-size: 16px;\n  -webkit-animation: slidedown-data-v-462a1626 0.7s linear;\n  animation: slidedown-data-v-462a1626 0.7s linear;\n}\n#koakuma > div[data-v-462a1626] {\n  margin: 0 10px;\n  display: -webkit-inline-box;\n  display: -ms-inline-flexbox;\n  display: inline-flex;\n}\n.bookmark-count[data-v-462a1626] {\n  display: -webkit-inline-box !important;\n  display: -ms-inline-flexbox !important;\n  display: inline-flex !important;\n  -webkit-box-align: center;\n  -ms-flex-align: center;\n  align-items: center;\n  margin-right: 0;\n  border-radius: 3px 0 0 3px;\n}\n#koakuma-bookmark-sort-block[data-v-462a1626] {\n  position: relative;\n  height: 20px;\n  -webkit-box-shadow: 0 0 1px #069;\n  box-shadow: 0 0 1px #069;\n  border-radius: 4px;\n}\n#koakuma-bookmark-sort-input[data-v-462a1626] {\n  -moz-appearance: textfield;\n  border: none;\n  background-color: transparent;\n  padding: 0;\n  color: inherit;\n  font-size: 16px;\n  display: inline-block;\n  cursor: ns-resize;\n  text-align: center;\n  max-width: 50px;\n}\n#koakuma-bookmark-sort-input[data-v-462a1626]::-webkit-inner-spin-button,\n#koakuma-bookmark-sort-input[data-v-462a1626]::-webkit-outer-spin-button {\n  /* https://css-tricks.com/numeric-inputs-a-comparison-of-browser-defaults/ */\n  -webkit-appearance: none;\n  margin: 0;\n}\n#koakuma-bookmark-tags-filter-input[data-v-462a1626] {\n  min-width: 300px;\n}\n#koakuma-bookmark-input-usual-switch[data-v-462a1626] {\n  background-color: #cef;\n  padding: 1px;\n  border-left: 1px solid #888;\n  border-radius: 0 3px 3px 0;\n  cursor: pointer;\n  display: -webkit-inline-box;\n  display: -ms-inline-flexbox;\n  display: inline-flex;\n  -webkit-box-align: center;\n  -ms-flex-align: center;\n  align-items: center;\n}\n#koakuma-bookmark-input-usual-list[data-v-462a1626] {\n  border-radius: 3px;\n  border-top: 1px solid #888;\n  background-color: #cef;\n  -webkit-box-shadow: 0 0 1px #069;\n  box-shadow: 0 0 1px #069;\n  position: absolute;\n  top: 100%;\n  width: 100%;\n}\n#koakuma-bookmark-input-usual-list > li[data-v-462a1626]::after {\n  content: \"\";\n  -webkit-box-shadow: 0 0 0 1px #89d8ff;\n  box-shadow: 0 0 0 1px #89d8ff;\n  display: inline-block;\n  margin: 0;\n  height: 0;\n  line-height: 0;\n  font-size: 0;\n  position: absolute;\n  width: 100%;\n  -webkit-transform: scaleX(0.8);\n  transform: scaleX(0.8);\n}\n#koakuma-bookmark-input-usual-list > li[data-v-462a1626]:last-child::after {\n  -webkit-box-shadow: none;\n  box-shadow: none;\n}\n.usual-list-link[data-v-462a1626]:hover::before {\n  content: \"⮬\";\n  position: absolute;\n  left: 6px;\n  font-weight: bolder;\n}\n.usual-list-link[data-v-462a1626] {\n  display: block;\n  cursor: pointer;\n  text-align: center;\n}\n#koakuma-options-block > *[data-v-462a1626] {\n  margin: 0 5px;\n}\n.main-button[data-v-462a1626] {\n  border: none;\n  padding: 2px 14px;\n  border-radius: 3px;\n  font-size: 16px;\n}\n.main-button[data-v-462a1626]:enabled {\n  -webkit-transform: translate(-1px, -1px);\n  transform: translate(-1px, -1px);\n  -webkit-box-shadow: 1px 1px 1px hsl(60, 0%, 30%);\n  box-shadow: 1px 1px 1px hsl(60, 0%, 30%);\n  cursor: pointer;\n}\n.main-button[data-v-462a1626]:enabled:hover {\n  -webkit-transform: translate(0);\n  transform: translate(0);\n  -webkit-box-shadow: none;\n  box-shadow: none;\n}\n.main-button[data-v-462a1626]:enabled:active {\n  -webkit-transform: translate(1px, 1px);\n  transform: translate(1px, 1px);\n  -webkit-box-shadow: -1px -1px 1px hsl(60, 0%, 30%);\n  box-shadow: -1px -1px 1px hsl(60, 0%, 30%);\n}\n.main-button.go[data-v-462a1626] {\n  background-color: hsl(141, 100%, 50%);\n}\n.main-button.paused[data-v-462a1626] {\n  background-color: hsl(60, 100%, 50%);\n}\n.main-button.end[data-v-462a1626] {\n  background-color: #878787;\n  color: #fff;\n  opacity: 0.87;\n}\n", map: undefined, media: undefined });
  };
  const __vue_scope_id__ = "data-v-462a1626";
  const __vue_module_identifier__ = undefined;
  const __vue_is_functional_template__ = false;
  function __vue_normalize__(
    template, style, script$$1,
    scope, functional, moduleIdentifier,
    createInjector, createInjectorSSR
  ) {
    const component = script$$1 || {};
    {
      component.__file = "/home/flandre/dev/Patchouli/src/components/Koakuma.vue";
    }
    if (!component.render) {
      component.render = template.render;
      component.staticRenderFns = template.staticRenderFns;
      component._compiled = true;
      if (functional) component.functional = true;
    }
    component._scopeId = scope;
    {
      let hook;
      if (style) {
        hook = function(context) {
          style.call(this, createInjector(context));
        };
      }
      if (hook !== undefined) {
        if (component.functional) {
          const originalRender = component.render;
          component.render = function renderWithStyleInjection(h, context) {
            hook.call(context);
            return originalRender(h, context)
          };
        } else {
          const existing = component.beforeCreate;
          component.beforeCreate = existing ? [].concat(existing, hook) : [hook];
        }
      }
    }
    return component
  }
  function __vue_create_injector__() {
    const head = document.head || document.getElementsByTagName('head')[0];
    const styles = {};
    const isOldIE =
      typeof navigator !== 'undefined' &&
      /msie [6-9]\\b/.test(navigator.userAgent.toLowerCase());
    return function addStyle(id, css) {
      if (document.querySelector('style[data-vue-ssr-id~="' + id + '"]')) return
      const group = isOldIE ? css.media || 'default' : id;
      const style = styles[group] || (styles[group] = { ids: [], parts: [], element: undefined });
      if (!style.ids.includes(id)) {
        let code = css.source;
        let index = style.ids.length;
        style.ids.push(id);
        if (isOldIE) {
          style.element = style.element || document.querySelector('style[data-group=' + group + ']');
        }
        if (!style.element) {
          const el = style.element = document.createElement('style');
          el.type = 'text/css';
          if (css.media) el.setAttribute('media', css.media);
          if (isOldIE) {
            el.setAttribute('data-group', group);
            el.setAttribute('data-next-index', '0');
          }
          head.appendChild(el);
        }
        if (isOldIE) {
          index = parseInt(style.element.getAttribute('data-next-index'));
          style.element.setAttribute('data-next-index', index + 1);
        }
        if (style.element.styleSheet) {
          style.parts.push(code);
          style.element.styleSheet.cssText = style.parts
            .filter(Boolean)
            .join('\n');
        } else {
          const textNode = document.createTextNode(code);
          const nodes = style.element.childNodes;
          if (nodes[index]) style.element.removeChild(nodes[index]);
          if (nodes.length) style.element.insertBefore(textNode, nodes[index]);
          else style.element.appendChild(textNode);
        }
      }
    }
  }
  var koakuma = __vue_normalize__(
    __vue_template__,
    __vue_inject_styles__,
    typeof __vue_script__ === 'undefined' ? {} : __vue_script__,
    __vue_scope_id__,
    __vue_is_functional_template__,
    __vue_module_identifier__,
    typeof __vue_create_injector__ !== 'undefined' ? __vue_create_injector__ : function () {},
    typeof __vue_create_injector_ssr__ !== 'undefined' ? __vue_create_injector_ssr__ : function () {}
  );
  var script$1 = {
    props: {
      imgUrl: {
        type: String,
        default: ""
      },
      illustId: {
        type: String,
        default: ""
      },
      illustPageCount: {
        type: Number,
        default: 1
      },
      isUgoira: {
        type: Boolean,
        default: false
      },
      isBookmarked: {
        type: Boolean,
        default: false
      },
      bookmarkId: {
        type: String,
        default: ""
      }
    },
    data() {
      return {
        selfIsBookmarked: this.isBookmarked
      };
    },
    computed: {
      illustPageUrl() {
        return `/member_illust.php?mode=medium&illust_id=${this.illustId}`;
      }
    },
    methods: {
      oneClickBookmarkAdd() {
        if (!this.selfIsBookmarked) {
          this.selfIsBookmarked = true;
        }
      }
    }
  };
  const __vue_script__$1 = script$1;
  var __vue_render__$1 = function() {
    var _vm = this;
    var _h = _vm.$createElement;
    var _c = _vm._self._c || _h;
    return _c("div", { staticClass: "image-item-image" }, [
      _c(
        "a",
        {
          staticClass: "image-flexbox",
          attrs: { href: _vm.illustPageUrl, rel: "noopener" }
        },
        [
          _vm.illustPageCount > 1
            ? _c("div", { staticClass: "top-right-slot" }, [
                _c("span", [
                  _c("span", { staticClass: "multiple-icon" }),
                  _vm._v("\n        " + _vm._s(_vm.illustPageCount))
                ])
              ])
            : _vm._e(),
          _vm._v(" "),
          _c("img", { attrs: { "data-src": _vm.imgUrl, src: _vm.imgUrl } }),
          _vm._v(" "),
          _vm.isUgoira ? _c("div", { staticClass: "ugoira-icon" }) : _vm._e()
        ]
      ),
      _vm._v(" "),
      _c("div", {
        staticClass: "_one-click-bookmark",
        class: { on: _vm.selfIsBookmarked },
        attrs: {
          "data-click-label": _vm.illustId,
          "data-id": _vm.illustId,
          title: _vm.selfIsBookmarked,
          "data-type": "illust",
          "data-click-action": "illust"
        },
        on: { click: _vm.oneClickBookmarkAdd }
      }),
      _vm._v(" "),
      _vm.bookmarkId
        ? _c("div", { staticClass: "bookmark-input-container" }, [
            _c("input", {
              attrs: { type: "checkbox", name: "book_id[]" },
              domProps: { value: _vm.bookmarkId }
            })
          ])
        : _vm._e()
    ])
  };
  var __vue_staticRenderFns__$1 = [];
  __vue_render__$1._withStripped = true;
  const __vue_template__$1 = typeof __vue_render__$1 !== 'undefined'
    ? { render: __vue_render__$1, staticRenderFns: __vue_staticRenderFns__$1 }
    : {};
  const __vue_inject_styles__$1 = function (inject) {
    if (!inject) return
    inject("data-v-53b1aa38_0", { source: "\n.image-item-image[data-v-53b1aa38] {\n  display: -webkit-box;\n  display: -ms-flexbox;\n  display: flex;\n  -webkit-box-align: center;\n  -ms-flex-align: center;\n  align-items: center;\n  -webkit-box-pack: center;\n  -ms-flex-pack: center;\n  justify-content: center;\n  position: relative;\n}\n.image-flexbox[data-v-53b1aa38] {\n  display: -webkit-box;\n  display: -ms-flexbox;\n  display: flex;\n  -webkit-box-orient: vertical;\n  -webkit-box-direction: normal;\n  -ms-flex-flow: column;\n  flex-flow: column;\n  -webkit-box-pack: center;\n  -ms-flex-pack: center;\n  justify-content: center;\n  -webkit-box-align: center;\n  -ms-flex-align: center;\n  align-items: center;\n  z-index: 0;\n  border: 1px solid rgba(0, 0, 0, 0.04);\n  position: relative;\n  height: 200px;\n}\n.top-right-slot[data-v-53b1aa38] {\n  -webkit-box-flex: 0;\n  -ms-flex: none;\n  flex: none;\n  display: -webkit-box;\n  display: -ms-flexbox;\n  display: flex;\n  -webkit-box-align: center;\n  -ms-flex-align: center;\n  align-items: center;\n  z-index: 1;\n  -webkit-box-sizing: border-box;\n  box-sizing: border-box;\n  margin: 0 0 -24px auto;\n  padding: 6px;\n  height: 24px;\n  background: #000;\n  background: rgba(0, 0, 0, 0.4);\n  border-radius: 0 0 0 4px;\n  color: #fff;\n  font-size: 12px;\n  line-height: 1;\n  font-weight: 700;\n}\n.multiple-icon[data-v-53b1aa38] {\n  display: inline-block;\n  margin-right: 4px;\n  width: 10px;\n  height: 10px;\n  background: url(https://source.pixiv.net/www/js/bundle/3b9b0b9e331e13c46aeadaea83132203.svg);\n}\n.ugoira-icon[data-v-53b1aa38] {\n  position: absolute;\n  -webkit-box-flex: 0;\n  -ms-flex: none;\n  flex: none;\n  width: 40px;\n  height: 40px;\n  background: url(https://source.pixiv.net/www/js/bundle/f608d897f389e8161e230b817068526d.svg)\n    50% no-repeat;\n  top: 50%;\n  left: 50%;\n  margin: -20px 0 0 -20px;\n}\nimg[data-v-53b1aa38] {\n  max-height: 100%;\n  max-width: 100%;\n}\n._one-click-bookmark[data-v-53b1aa38] {\n  right: 0;\n  width: 24px;\n  height: 24px;\n  line-height: 24px;\n  z-index: 2;\n  text-align: center;\n  cursor: pointer;\n  background: url(https://source.pixiv.net/www/images/bookmark-heart-off.svg)\n    center transparent;\n  background-repeat: no-repeat;\n  background-size: cover;\n  opacity: 0.8;\n  filter: alpha(opacity=80);\n  -webkit-transition: opacity 0.2s ease-in-out;\n  transition: opacity 0.2s ease-in-out;\n}\n._one-click-bookmark.on[data-v-53b1aa38] {\n  background-image: url(https://source.pixiv.net/www/images/bookmark-heart-on.svg);\n}\n.bookmark-input-container[data-v-53b1aa38] {\n  position: absolute;\n  left: 0;\n  top: 0;\n  background: rgba(0, 0, 0, 0.4);\n  padding: 6px;\n  border-radius: 0 0 4px 0;\n}\n", map: undefined, media: undefined });
  };
  const __vue_scope_id__$1 = "data-v-53b1aa38";
  const __vue_module_identifier__$1 = undefined;
  const __vue_is_functional_template__$1 = false;
  function __vue_normalize__$1(
    template, style, script,
    scope, functional, moduleIdentifier,
    createInjector, createInjectorSSR
  ) {
    const component = script || {};
    {
      component.__file = "/home/flandre/dev/Patchouli/src/components/DefaultImageItemImage.vue";
    }
    if (!component.render) {
      component.render = template.render;
      component.staticRenderFns = template.staticRenderFns;
      component._compiled = true;
      if (functional) component.functional = true;
    }
    component._scopeId = scope;
    {
      let hook;
      if (style) {
        hook = function(context) {
          style.call(this, createInjector(context));
        };
      }
      if (hook !== undefined) {
        if (component.functional) {
          const originalRender = component.render;
          component.render = function renderWithStyleInjection(h, context) {
            hook.call(context);
            return originalRender(h, context)
          };
        } else {
          const existing = component.beforeCreate;
          component.beforeCreate = existing ? [].concat(existing, hook) : [hook];
        }
      }
    }
    return component
  }
  function __vue_create_injector__$1() {
    const head = document.head || document.getElementsByTagName('head')[0];
    const styles = {};
    const isOldIE =
      typeof navigator !== 'undefined' &&
      /msie [6-9]\\b/.test(navigator.userAgent.toLowerCase());
    return function addStyle(id, css) {
      if (document.querySelector('style[data-vue-ssr-id~="' + id + '"]')) return
      const group = isOldIE ? css.media || 'default' : id;
      const style = styles[group] || (styles[group] = { ids: [], parts: [], element: undefined });
      if (!style.ids.includes(id)) {
        let code = css.source;
        let index = style.ids.length;
        style.ids.push(id);
        if (isOldIE) {
          style.element = style.element || document.querySelector('style[data-group=' + group + ']');
        }
        if (!style.element) {
          const el = style.element = document.createElement('style');
          el.type = 'text/css';
          if (css.media) el.setAttribute('media', css.media);
          if (isOldIE) {
            el.setAttribute('data-group', group);
            el.setAttribute('data-next-index', '0');
          }
          head.appendChild(el);
        }
        if (isOldIE) {
          index = parseInt(style.element.getAttribute('data-next-index'));
          style.element.setAttribute('data-next-index', index + 1);
        }
        if (style.element.styleSheet) {
          style.parts.push(code);
          style.element.styleSheet.cssText = style.parts
            .filter(Boolean)
            .join('\n');
        } else {
          const textNode = document.createTextNode(code);
          const nodes = style.element.childNodes;
          if (nodes[index]) style.element.removeChild(nodes[index]);
          if (nodes.length) style.element.insertBefore(textNode, nodes[index]);
          else style.element.appendChild(textNode);
        }
      }
    }
  }
  var DefaultImageItemImage = __vue_normalize__$1(
    __vue_template__$1,
    __vue_inject_styles__$1,
    typeof __vue_script__$1 === 'undefined' ? {} : __vue_script__$1,
    __vue_scope_id__$1,
    __vue_is_functional_template__$1,
    __vue_module_identifier__$1,
    typeof __vue_create_injector__$1 !== 'undefined' ? __vue_create_injector__$1 : function () {},
    typeof __vue_create_injector_ssr__ !== 'undefined' ? __vue_create_injector_ssr__ : function () {}
  );
  var script$2 = {
    props: {
      illustId: {
        type: String,
        default: ""
      },
      illustTitle: {
        type: String,
        default: ""
      },
      userName: {
        type: String,
        default: ""
      },
      userId: {
        type: String,
        default: ""
      },
      profileImgUrl: {
        type: String,
        default: ""
      },
      bookmarkCount: {
        type: Number,
        default: 0
      },
      isFollow: {
        type: Boolean,
        default: false
      }
    },
    computed: {
      illustPageUrl() {
        return `/member_illust.php?mode=medium&illust_id=${this.illustId}`;
      },
      userPageUrl() {
        return `/member_illust.php?id=${this.userId}`;
      },
      bookmarkDetailUrl() {
        return `/bookmark_detail.php?illust_id=${this.illustId}`;
      },
      bookmarkTooltipMsg() {
        return this.$t("patchouli.bookmarkTooltip", {
          count: this.bookmarkCount
        });
      },
      profileImgStyle() {
        return {
          backgroundImage: `url(${this.profileImgUrl})`
        };
      },
      isMemberIllistPage() {
        return this.$store.state.pageType === "MEMBER_ILLIST";
      }
    }
  };
  const __vue_script__$2 = script$2;
  var __vue_render__$2 = function() {
    var _vm = this;
    var _h = _vm.$createElement;
    var _c = _vm._self._c || _h;
    return _c("figcaption", { staticClass: "image-item-title" }, [
      _c("ul", [
        _c("li", { staticClass: "title-text" }, [
          _c(
            "a",
            { attrs: { href: _vm.illustPageUrl, title: _vm.illustTitle } },
            [_vm._v(_vm._s(_vm.illustTitle))]
          )
        ]),
        _vm._v(" "),
        !_vm.isMemberIllistPage
          ? _c("li", { staticClass: "user-info" }, [
              _c(
                "a",
                {
                  staticClass: "user-link ui-profile-popup",
                  attrs: {
                    href: _vm.userPageUrl,
                    title: _vm.userName,
                    "data-user_id": _vm.userId,
                    "data-user_name": _vm.userName,
                    target: "_blank"
                  }
                },
                [
                  _c("span", {
                    staticClass: "user-img",
                    style: _vm.profileImgStyle
                  }),
                  _vm._v(" "),
                  _c("span", [_vm._v(_vm._s(_vm.userName))])
                ]
              ),
              _vm._v(" "),
              _vm.isFollow ? _c("i", { staticClass: "follow-icon" }) : _vm._e()
            ])
          : _vm._e(),
        _vm._v(" "),
        _vm.bookmarkCount > 0
          ? _c("li", [
              _c("ul", { staticClass: "count-list" }, [
                _c("li", [
                  _c(
                    "a",
                    {
                      staticClass: "_ui-tooltip bookmark-count",
                      attrs: {
                        href: _vm.bookmarkDetailUrl,
                        "data-tooltip": _vm.$t("patchouli.bookmarkTooltip", {
                          count: _vm.bookmarkCount
                        })
                      }
                    },
                    [
                      _c("i", { staticClass: "_icon _bookmark-icon-inline" }),
                      _vm._v(
                        "\n            " +
                          _vm._s(_vm.bookmarkCount) +
                          "\n          "
                      )
                    ]
                  )
                ])
              ])
            ])
          : _vm._e()
      ])
    ])
  };
  var __vue_staticRenderFns__$2 = [];
  __vue_render__$2._withStripped = true;
  const __vue_template__$2 = typeof __vue_render__$2 !== 'undefined'
    ? { render: __vue_render__$2, staticRenderFns: __vue_staticRenderFns__$2 }
    : {};
  const __vue_inject_styles__$2 = function (inject) {
    if (!inject) return
    inject("data-v-2d61f7ae_0", { source: "\n.image-item-title[data-v-2d61f7ae] {\n  max-width: 100%;\n  margin: 8px auto;\n  text-align: center;\n  color: #333;\n  font-size: 12px;\n  line-height: 1;\n}\n.title-text[data-v-2d61f7ae] {\n  margin: 4px 0;\n  overflow: hidden;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n  font-weight: 700;\n}\n.user-info[data-v-2d61f7ae] {\n  display: -webkit-inline-box;\n  display: -ms-inline-flexbox;\n  display: inline-flex;\n  -webkit-box-align: center;\n  -ms-flex-align: center;\n  align-items: center;\n}\n.user-link[data-v-2d61f7ae] {\n  font-size: 12px;\n  display: -webkit-inline-box;\n  display: -ms-inline-flexbox;\n  display: inline-flex;\n  -webkit-box-align: center;\n  -ms-flex-align: center;\n  align-items: center;\n}\n.user-img[data-v-2d61f7ae] {\n  width: 20px;\n  height: 20px;\n  display: inline-block;\n  background-size: cover;\n  border-radius: 50%;\n  margin-right: 4px;\n}\n.follow-icon[data-v-2d61f7ae] {\n  display: inline-block;\n  margin-left: 4px;\n  width: 14px;\n  height: 14px;\n  background-color: dodgerblue;\n  -webkit-mask-image: url(https://cdnjs.cloudflare.com/ajax/libs/simple-icons/3.0.1/rss.svg);\n  mask-image: url(https://cdnjs.cloudflare.com/ajax/libs/simple-icons/3.0.1/rss.svg);\n}\n", map: undefined, media: undefined });
  };
  const __vue_scope_id__$2 = "data-v-2d61f7ae";
  const __vue_module_identifier__$2 = undefined;
  const __vue_is_functional_template__$2 = false;
  function __vue_normalize__$2(
    template, style, script,
    scope, functional, moduleIdentifier,
    createInjector, createInjectorSSR
  ) {
    const component = script || {};
    {
      component.__file = "/home/flandre/dev/Patchouli/src/components/DefaultImageItemTitle.vue";
    }
    if (!component.render) {
      component.render = template.render;
      component.staticRenderFns = template.staticRenderFns;
      component._compiled = true;
      if (functional) component.functional = true;
    }
    component._scopeId = scope;
    {
      let hook;
      if (style) {
        hook = function(context) {
          style.call(this, createInjector(context));
        };
      }
      if (hook !== undefined) {
        if (component.functional) {
          const originalRender = component.render;
          component.render = function renderWithStyleInjection(h, context) {
            hook.call(context);
            return originalRender(h, context)
          };
        } else {
          const existing = component.beforeCreate;
          component.beforeCreate = existing ? [].concat(existing, hook) : [hook];
        }
      }
    }
    return component
  }
  function __vue_create_injector__$2() {
    const head = document.head || document.getElementsByTagName('head')[0];
    const styles = {};
    const isOldIE =
      typeof navigator !== 'undefined' &&
      /msie [6-9]\\b/.test(navigator.userAgent.toLowerCase());
    return function addStyle(id, css) {
      if (document.querySelector('style[data-vue-ssr-id~="' + id + '"]')) return
      const group = isOldIE ? css.media || 'default' : id;
      const style = styles[group] || (styles[group] = { ids: [], parts: [], element: undefined });
      if (!style.ids.includes(id)) {
        let code = css.source;
        let index = style.ids.length;
        style.ids.push(id);
        if (isOldIE) {
          style.element = style.element || document.querySelector('style[data-group=' + group + ']');
        }
        if (!style.element) {
          const el = style.element = document.createElement('style');
          el.type = 'text/css';
          if (css.media) el.setAttribute('media', css.media);
          if (isOldIE) {
            el.setAttribute('data-group', group);
            el.setAttribute('data-next-index', '0');
          }
          head.appendChild(el);
        }
        if (isOldIE) {
          index = parseInt(style.element.getAttribute('data-next-index'));
          style.element.setAttribute('data-next-index', index + 1);
        }
        if (style.element.styleSheet) {
          style.parts.push(code);
          style.element.styleSheet.cssText = style.parts
            .filter(Boolean)
            .join('\n');
        } else {
          const textNode = document.createTextNode(code);
          const nodes = style.element.childNodes;
          if (nodes[index]) style.element.removeChild(nodes[index]);
          if (nodes.length) style.element.insertBefore(textNode, nodes[index]);
          else style.element.appendChild(textNode);
        }
      }
    }
  }
  var DefaultImageItemTitle = __vue_normalize__$2(
    __vue_template__$2,
    __vue_inject_styles__$2,
    typeof __vue_script__$2 === 'undefined' ? {} : __vue_script__$2,
    __vue_scope_id__$2,
    __vue_is_functional_template__$2,
    __vue_module_identifier__$2,
    typeof __vue_create_injector__$2 !== 'undefined' ? __vue_create_injector__$2 : function () {},
    typeof __vue_create_injector_ssr__ !== 'undefined' ? __vue_create_injector_ssr__ : function () {}
  );
  var script$3 = {
    components: { DefaultImageItemImage, DefaultImageItemTitle },
    props: {
      imgUrl: {
        type: String,
        default: ""
      },
      illustId: {
        type: String,
        default: ""
      },
      illustTitle: {
        type: String,
        default: ""
      },
      illustPageCount: {
        type: Number,
        default: 1
      },
      userName: {
        type: String,
        default: ""
      },
      userId: {
        type: String,
        default: ""
      },
      profileImgUrl: {
        type: String,
        default: ""
      },
      isUgoira: {
        type: Boolean,
        default: false
      },
      isBookmarked: {
        type: Boolean,
        default: false
      },
      isFollow: {
        type: Boolean,
        default: false
      },
      bookmarkId: {
        type: String,
        default: ""
      },
      bookmarkCount: {
        type: Number,
        default: 0
      }
    },
    computed: {
      pageType() {
        return this.$store.state.pageType;
      }
    }
  };
  const __vue_script__$3 = script$3;
  var __vue_render__$3 = function() {
    var _vm = this;
    var _h = _vm.$createElement;
    var _c = _vm._self._c || _h;
    return _c("div", { staticClass: "image-item" }, [
      _c(
        "figure",
        { staticClass: "image-item-inner" },
        [
          _c("DefaultImageItemImage", {
            attrs: {
              "img-url": _vm.imgUrl,
              "illust-id": _vm.illustId,
              "illust-page-count": _vm.illustPageCount,
              "is-ugoira": _vm.isUgoira,
              "is-bookmarked": _vm.isBookmarked,
              "bookmark-id": _vm.bookmarkId
            }
          }),
          _vm._v(" "),
          _c("DefaultImageItemTitle", {
            attrs: {
              "illust-id": _vm.illustId,
              "illust-title": _vm.illustTitle,
              "user-name": _vm.userName,
              "user-id": _vm.userId,
              "is-follow": _vm.isFollow,
              "profile-img-url": _vm.profileImgUrl,
              "bookmark-count": _vm.bookmarkCount,
              "page-type": _vm.pageType
            }
          })
        ],
        1
      )
    ])
  };
  var __vue_staticRenderFns__$3 = [];
  __vue_render__$3._withStripped = true;
  const __vue_template__$3 = typeof __vue_render__$3 !== 'undefined'
    ? { render: __vue_render__$3, staticRenderFns: __vue_staticRenderFns__$3 }
    : {};
  const __vue_inject_styles__$3 = function (inject) {
    if (!inject) return
    inject("data-v-7736ae16_0", { source: "\n.image-item[data-v-7736ae16] {\n  display: -webkit-box;\n  display: -ms-flexbox;\n  display: flex;\n  -webkit-box-pack: center;\n  -ms-flex-pack: center;\n  justify-content: center;\n  margin: 0 0 30px 0;\n  padding: 10px;\n  height: auto;\n  width: 200px;\n}\n.image-item-inner[data-v-7736ae16] {\n  display: -webkit-box;\n  display: -ms-flexbox;\n  display: flex;\n  -webkit-box-orient: vertical;\n  -webkit-box-direction: normal;\n  -ms-flex-flow: column;\n  flex-flow: column;\n  max-width: 100%;\n  max-height: 300px;\n}\n", map: undefined, media: undefined });
  };
  const __vue_scope_id__$3 = "data-v-7736ae16";
  const __vue_module_identifier__$3 = undefined;
  const __vue_is_functional_template__$3 = false;
  function __vue_normalize__$3(
    template, style, script,
    scope, functional, moduleIdentifier,
    createInjector, createInjectorSSR
  ) {
    const component = script || {};
    {
      component.__file = "/home/flandre/dev/Patchouli/src/components/DefaultImageItem.vue";
    }
    if (!component.render) {
      component.render = template.render;
      component.staticRenderFns = template.staticRenderFns;
      component._compiled = true;
      if (functional) component.functional = true;
    }
    component._scopeId = scope;
    {
      let hook;
      if (style) {
        hook = function(context) {
          style.call(this, createInjector(context));
        };
      }
      if (hook !== undefined) {
        if (component.functional) {
          const originalRender = component.render;
          component.render = function renderWithStyleInjection(h, context) {
            hook.call(context);
            return originalRender(h, context)
          };
        } else {
          const existing = component.beforeCreate;
          component.beforeCreate = existing ? [].concat(existing, hook) : [hook];
        }
      }
    }
    return component
  }
  function __vue_create_injector__$3() {
    const head = document.head || document.getElementsByTagName('head')[0];
    const styles = {};
    const isOldIE =
      typeof navigator !== 'undefined' &&
      /msie [6-9]\\b/.test(navigator.userAgent.toLowerCase());
    return function addStyle(id, css) {
      if (document.querySelector('style[data-vue-ssr-id~="' + id + '"]')) return
      const group = isOldIE ? css.media || 'default' : id;
      const style = styles[group] || (styles[group] = { ids: [], parts: [], element: undefined });
      if (!style.ids.includes(id)) {
        let code = css.source;
        let index = style.ids.length;
        style.ids.push(id);
        if (isOldIE) {
          style.element = style.element || document.querySelector('style[data-group=' + group + ']');
        }
        if (!style.element) {
          const el = style.element = document.createElement('style');
          el.type = 'text/css';
          if (css.media) el.setAttribute('media', css.media);
          if (isOldIE) {
            el.setAttribute('data-group', group);
            el.setAttribute('data-next-index', '0');
          }
          head.appendChild(el);
        }
        if (isOldIE) {
          index = parseInt(style.element.getAttribute('data-next-index'));
          style.element.setAttribute('data-next-index', index + 1);
        }
        if (style.element.styleSheet) {
          style.parts.push(code);
          style.element.styleSheet.cssText = style.parts
            .filter(Boolean)
            .join('\n');
        } else {
          const textNode = document.createTextNode(code);
          const nodes = style.element.childNodes;
          if (nodes[index]) style.element.removeChild(nodes[index]);
          if (nodes.length) style.element.insertBefore(textNode, nodes[index]);
          else style.element.appendChild(textNode);
        }
      }
    }
  }
  var DefaultImageItem = __vue_normalize__$3(
    __vue_template__$3,
    __vue_inject_styles__$3,
    typeof __vue_script__$3 === 'undefined' ? {} : __vue_script__$3,
    __vue_scope_id__$3,
    __vue_is_functional_template__$3,
    __vue_module_identifier__$3,
    typeof __vue_create_injector__$3 !== 'undefined' ? __vue_create_injector__$3 : function () {},
    typeof __vue_create_injector_ssr__ !== 'undefined' ? __vue_create_injector_ssr__ : function () {}
  );
  var script$4 = {
    components: { DefaultImageItem },
    computed: {
      filteredLibrary() {
        return this.$store.getters.filteredLibrary;
      }
    }
  };
  const __vue_script__$4 = script$4;
  var __vue_render__$4 = function() {
    var _vm = this;
    var _h = _vm.$createElement;
    var _c = _vm._self._c || _h;
    return _c(
      "div",
      { attrs: { id: "patchouli" } },
      _vm._l(_vm.filteredLibrary, function(d) {
        return _c("DefaultImageItem", {
          key: d.illustId,
          attrs: {
            "img-url": d.url.sq240,
            "illust-id": d.illustId,
            "illust-title": d.illustTitle,
            "illust-page-count": d.illustPageCount,
            "is-ugoira": d.isUgoira,
            "user-name": d.userName,
            "user-id": d.userId,
            "profile-img-url": d.profileImg,
            "bookmark-count": d.bookmarkCount,
            "is-bookmarked": d.isBookmarked,
            "is-follow": d.isFollow,
            "bookmark-id": d.bookmarkId
          }
        })
      })
    )
  };
  var __vue_staticRenderFns__$4 = [];
  __vue_render__$4._withStripped = true;
  const __vue_template__$4 = typeof __vue_render__$4 !== 'undefined'
    ? { render: __vue_render__$4, staticRenderFns: __vue_staticRenderFns__$4 }
    : {};
  const __vue_inject_styles__$4 = function (inject) {
    if (!inject) return
    inject("data-v-ac856c12_0", { source: "\n#patchouli[data-v-ac856c12] {\n  display: -webkit-box;\n  display: -ms-flexbox;\n  display: flex;\n  -ms-flex-flow: wrap;\n  flex-flow: wrap;\n  -ms-flex-pack: distribute;\n  justify-content: space-around;\n}\n", map: undefined, media: undefined });
  };
  const __vue_scope_id__$4 = "data-v-ac856c12";
  const __vue_module_identifier__$4 = undefined;
  const __vue_is_functional_template__$4 = false;
  function __vue_normalize__$4(
    template, style, script,
    scope, functional, moduleIdentifier,
    createInjector, createInjectorSSR
  ) {
    const component = script || {};
    {
      component.__file = "/home/flandre/dev/Patchouli/src/components/Patchouli.vue";
    }
    if (!component.render) {
      component.render = template.render;
      component.staticRenderFns = template.staticRenderFns;
      component._compiled = true;
      if (functional) component.functional = true;
    }
    component._scopeId = scope;
    {
      let hook;
      if (style) {
        hook = function(context) {
          style.call(this, createInjector(context));
        };
      }
      if (hook !== undefined) {
        if (component.functional) {
          const originalRender = component.render;
          component.render = function renderWithStyleInjection(h, context) {
            hook.call(context);
            return originalRender(h, context)
          };
        } else {
          const existing = component.beforeCreate;
          component.beforeCreate = existing ? [].concat(existing, hook) : [hook];
        }
      }
    }
    return component
  }
  function __vue_create_injector__$4() {
    const head = document.head || document.getElementsByTagName('head')[0];
    const styles = {};
    const isOldIE =
      typeof navigator !== 'undefined' &&
      /msie [6-9]\\b/.test(navigator.userAgent.toLowerCase());
    return function addStyle(id, css) {
      if (document.querySelector('style[data-vue-ssr-id~="' + id + '"]')) return
      const group = isOldIE ? css.media || 'default' : id;
      const style = styles[group] || (styles[group] = { ids: [], parts: [], element: undefined });
      if (!style.ids.includes(id)) {
        let code = css.source;
        let index = style.ids.length;
        style.ids.push(id);
        if (isOldIE) {
          style.element = style.element || document.querySelector('style[data-group=' + group + ']');
        }
        if (!style.element) {
          const el = style.element = document.createElement('style');
          el.type = 'text/css';
          if (css.media) el.setAttribute('media', css.media);
          if (isOldIE) {
            el.setAttribute('data-group', group);
            el.setAttribute('data-next-index', '0');
          }
          head.appendChild(el);
        }
        if (isOldIE) {
          index = parseInt(style.element.getAttribute('data-next-index'));
          style.element.setAttribute('data-next-index', index + 1);
        }
        if (style.element.styleSheet) {
          style.parts.push(code);
          style.element.styleSheet.cssText = style.parts
            .filter(Boolean)
            .join('\n');
        } else {
          const textNode = document.createTextNode(code);
          const nodes = style.element.childNodes;
          if (nodes[index]) style.element.removeChild(nodes[index]);
          if (nodes.length) style.element.insertBefore(textNode, nodes[index]);
          else style.element.appendChild(textNode);
        }
      }
    }
  }
  var patchouli = __vue_normalize__$4(
    __vue_template__$4,
    __vue_inject_styles__$4,
    typeof __vue_script__$4 === 'undefined' ? {} : __vue_script__$4,
    __vue_scope_id__$4,
    __vue_is_functional_template__$4,
    __vue_module_identifier__$4,
    typeof __vue_create_injector__$4 !== 'undefined' ? __vue_create_injector__$4 : function () {},
    typeof __vue_create_injector_ssr__ !== 'undefined' ? __vue_create_injector_ssr__ : function () {}
  );
  Vue.use(VueI18n);
  var i18n = new VueI18n({
    locale: document.documentElement.lang,
    fallbackLocale: 'ja',
    messages: {
      'en': {
        patchouli: {
          bookmarkTooltip: '{count} bookmarks'
        },
        koakuma: {
          processed: '{count} imgs processed',
          tagsPlaceholder: 'tags filter example: flandre|sister',
          buttonGo: 'Go',
          buttonPause: 'Pause',
          buttonEnd: 'End',
          fitWidth: 'fit browser width',
          sortByBookmarkCount: 'sort by bookmark count'
        }
      },
      'ja': {
        patchouli: {
          bookmarkTooltip: '{count} 件のブックマーク'
        },
        koakuma: {
          processed: '{count} 件が処理された',
          tagsPlaceholder: 'タグフィルター 例: フランドール|妹様',
          buttonGo: '捜す',
          buttonPause: '中断',
          buttonEnd: '終了',
          fitWidth: '全幅',
          sortByBookmarkCount: 'ブックマーク数順'
        }
      },
      'zh': {
        patchouli: {
          bookmarkTooltip: '{count} 个收藏'
        },
        koakuma: {
          processed: '已处理 {count} 张',
          tagsPlaceholder: '标签过滤 例: 芙兰朵露|二小姐',
          buttonGo: '找',
          buttonPause: '停',
          buttonEnd: '完',
          fitWidth: '自适应浏览器宽度',
          sortByBookmarkCount: '书签数排序'
        }
      },
      'zh-tw': {
        patchouli: {
          bookmarkTooltip: '{count} 個收藏'
        },
        koakuma: {
          processed: '已處理 {count} 張',
          tagsPlaceholder: '標籤過濾 例: 芙蘭朵露|二小姐',
          buttonGo: '找',
          buttonPause: '停',
          buttonEnd: '完',
          fitWidth: '自適應瀏覽器寬度',
          sortByBookmarkCount: '書籤數排序'
        }
      }
    }
  });
  store.commit('prepareMountPoint');
  store.commit('loadConfig');
  store.commit('applyConfig');
  if (store.state.pageType !== 'NO_SUPPORT') {
    removeAnnoyings();
    document.querySelector('._global-header').classList.add('koakuma-placeholder');
    const Patchouli = new Vue({
      i18n,
      store,
      computed: {
        currentLocale() {
          return this.$store.state.locale;
        }
      },
      watch: {
        currentLocale(newValue) {
          this.$i18n.locale = newValue;
        }
      },
      render: h => h(patchouli)
    });
    const Koakuma = new Vue({
      i18n,
      store,
      computed: {
        currentLocale() {
          return this.$store.state.locale;
        }
      },
      watch: {
        currentLocale(newValue) {
          this.$i18n.locale = newValue;
        }
      },
      render: h => h(koakuma)
    });
    store.dispatch('start', { times: 1 }).then(() => {
      Patchouli.$mount(store.state.patchouliMountPoint);
      Koakuma.$mount(store.state.koakumaMountPoint);
      document.querySelector('._global-header').classList.remove('koakuma-placeholder');
    }).catch(error => {
      $error('Fail to first mount', error);
    });
    document.body.addEventListener('click', (event) => {
      if (event.target.id !== 'koakuma-bookmark-input-usual-switch') {
        Koakuma.$children[0].usualSwitchOn = false;
      }
    });
    window.Patchouli = Patchouli;
    window.Koakuma = Koakuma;
  }

}(Vue,Vuex,VueI18n));