diff --git a/.github/ISSUE_TEMPLATE/custom-rule-request.md b/.github/ISSUE_TEMPLATE/custom-rule-request.md index 9661eebebba..d012e0245f3 100644 --- a/.github/ISSUE_TEMPLATE/custom-rule-request.md +++ b/.github/ISSUE_TEMPLATE/custom-rule-request.md @@ -10,7 +10,7 @@ assignees: '' --- **The url of site** -The example urls of site. ⚠**Do not paste only domain without pathname**⚠. +The example urls of site. ⚠**Do not paste only domain without pathname, or I'll close the issue without explanation**⚠. **Is your request related to a problem? Please describe.** A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] diff --git a/.github/workflows/build-dist.yml b/.github/workflows/build-dist.yml new file mode 100644 index 00000000000..ef4f9880fb6 --- /dev/null +++ b/.github/workflows/build-dist.yml @@ -0,0 +1,33 @@ +name: Build Picviewer CE+ Dist + +on: + push: + branches: + - master + paths: + - 'Picviewer CE*/Picviewer CE*.user.js' + workflow_dispatch: + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Replace require paths, add timestamp, and create dist file + run: | + sed -E \ + -e "s#https://update.greasyfork.org/scripts/6158/([0-9]+)/GM_config%20CN.js#https://hoothin.github.io/UserScripts/Picviewer%20CE%2B/GM_config%20CN.js?v=\1#g" \ + -e "s#https://update.greasyfork.org/scripts/438080/([0-9]+)/pvcep_rules.js#https://hoothin.github.io/UserScripts/Picviewer%20CE%2B/pvcep_rules.js?v=\1#g" \ + -e "s#https://update.greasyfork.org/scripts/440698/([0-9]+)/pvcep_lang.js#https://hoothin.github.io/UserScripts/Picviewer%20CE%2B/pvcep_lang.js?v=\1#g" \ + "Picviewer CE+/Picviewer CE+.user.js" > "Picviewer CE+/dist.user.js" + + - name: Commit and push dist.user.js + run: | + git config --local user.email "rixixi@gmail.com" + git config --local user.name "hoothin-update" + git add "Picviewer CE+/dist.user.js" + git commit -m "chore(Picviewer CE+): Auto-generate dist.user.js" + git push https://${{ secrets.ACTION_SECRET }}@github.com/${{ github.repository }} diff --git a/.github/workflows/jekyll-gh-pages.yml b/.github/workflows/jekyll-gh-pages.yml index 00b864d6d2c..9bdd4e3eec5 100644 --- a/.github/workflows/jekyll-gh-pages.yml +++ b/.github/workflows/jekyll-gh-pages.yml @@ -8,6 +8,8 @@ on: paths-ignore: - 'Pagetual/items_all.json' - 'Pagetual/pagetualRules.json' + - '.github/*' + - '.github/*/*' workflow_run: workflows: ["Update Version on File Change"] types: diff --git a/.github/workflows/json-validator.yml b/.github/workflows/json-validator.yml index a726236d040..01911cc1730 100644 --- a/.github/workflows/json-validator.yml +++ b/.github/workflows/json-validator.yml @@ -13,9 +13,9 @@ jobs: - uses: actions/checkout@v4 - name: json-yaml-validate - uses: GrantBirki/json-yaml-validate@v3.0.0 + uses: GrantBirki/json-yaml-validate@v5 id: json-yaml-validate with: json_schema: Pagetual/pagetual.schema.json files: | - Pagetual/pagetualRules.json \ No newline at end of file + Pagetual/pagetualRules.json diff --git a/91wii/91wii.user.js b/91wii/91wii.user.js deleted file mode 100644 index b94c7d4fd79..00000000000 --- a/91wii/91wii.user.js +++ /dev/null @@ -1,50 +0,0 @@ -// ==UserScript== -// @name 91wii -// @namespace hoothin -// @version 0.6 -// @description 91wii签到 -// @author hoothin -// @match https://*.91wii.com/* -// @match https://*.91tvg.com/* -// @icon data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== -// @run-at document-idle -// @grant unsafeWindow -// ==/UserScript== - -(function() { - 'use strict'; - setTimeout(()=>{ - var formula = document.querySelector("b"),dcsignin = document.querySelector("#dcsignin_tips"); - if(formula && /^[\d\s\+-=?]+$/.test(formula.innerText.trim())){ - setTimeout(function(){ - document.querySelector("input[type=text]").value=eval(formula.innerText.match(/[\d\s\+-]+/)[0]); - document.querySelector("input[type=submit]").click(); - },10); - }else if(dcsignin){ - if(dcsignin.style.background.indexOf("signin_yes") != -1)return; - unsafeWindow.showWindow('sign', 'plugin.php?id=dc_signin:sign'); - var checkTimes=0; - let signInterval=setInterval(()=>{ - var signWin=document.querySelector("#fwin_sign"); - if(signWin){ - signWin.style.display="none"; - } - var dialogWin=document.querySelector("#fwin_dialog"); - if(dialogWin){ - dialogWin.style.display="none"; - } - let emotIndex=parseInt(Math.random() * 10) + 1; - if(document.querySelector("#emot_" + emotIndex)){ - clearInterval(signInterval); - document.querySelector("#emot_" + emotIndex).click(); - //document.querySelector('#content').value = '君子有四时,朝以听政,昼以访问,夕以修令,夜以安身。'; - document.querySelector("button[name=signpn]").click(); - unsafeWindow.hideWindow('sign'); - }else if(checkTimes++>15){ - clearInterval(signInterval); - unsafeWindow.hideWindow('sign'); - } - }, 100); - } - },2000); -})(); \ No newline at end of file diff --git a/91wii/README.md b/91wii/README.md deleted file mode 100644 index d7cb01b5315..00000000000 --- a/91wii/README.md +++ /dev/null @@ -1 +0,0 @@ -# 91wii 自动作答数学题,自动签到 diff --git a/BingBgForBaidu/BingBgForBaidu.user.js b/BingBgForBaidu/BingBgForBaidu.user.js index d4a0aa7e66e..ba0fa832396 100644 --- a/BingBgForBaidu/BingBgForBaidu.user.js +++ b/BingBgForBaidu/BingBgForBaidu.user.js @@ -2,7 +2,7 @@ // @name 百Bing图 // @name:en BingBgForBaidu // @namespace hoothin -// @version 2.3.39 +// @version 2.3.45 // @description 给百度首页换上Bing的背景图,并添加背景图链接与日历组件 // @description:en Just change the background image of baidu.com to bing.com // @author hoothin @@ -31,7 +31,7 @@ if(!head.classList.contains("s-skin-hasbg")){ head.classList.add("s-skin-hasbg"); head.classList.add("s-opacity-50"); - GM_addStyle(".s-opacity-50 .s-opacity-border1-top{border-top-color: rgba(233,233,233,0.5) !important;}.s-opacity-50 .s-opacity-border1-bottom{border-bottom-color: rgba(233,233,233,0.5) !important;}.s-opacity-50 .s-opacity-border1-left{border-left-color: rgba(233,233,233,0.5) !important;}.s-opacity-50 .s-opacity-border1-right{border-right-color: rgba(233,233,233,0.5) !important;}.s-opacity-50 .s-opacity-border2-top{border-top-color: rgba(234,234,234,0.5) !important;}.s-opacity-50 .s-opacity-border2-bottom{border-bottom-color: rgba(234,234,234,0.5) !important;}.s-opacity-50 .s-opacity-border2-left{border-left-color: rgba(234,234,234,0.5) !important;}.s-opacity-50 .s-opacity-border2-right{border-right-color: rgba(234,234,234,0.5) !important;}.s-opacity-50 .s-opacity-border3-top{border-top-color: rgba(238,238,238,0.5) !important;}.s-opacity-50 .s-opacity-border3-bottom{border-bottom-color: rgba(238,238,238,0.5) !important;}.s-opacity-50 .s-opacity-border3-left{border-left-color: rgba(238,238,238,0.5) !important;}.s-opacity-50 .s-opacity-border3-right{border-right-color: rgba(238,238,238,0.5) !important;}.s-opacity-50 .s-opacity-border4-top{border-top-color: rgba(240,240,240,0.5) !important;}.s-opacity-50 .s-opacity-border4-bottom{border-bottom-color: rgba(240,240,240,0.5) !important;}.s-opacity-50 .s-opacity-border4-left{border-left-color: rgba(240,240,240,0.5) !important;}.s-opacity-50 .s-opacity-border4-right{border-right-color: rgba(240,240,240,0.5) !important;}.s-opacity-50 .s-opacity-border5-top{border-top-color: rgba(243,243,243,0.5) !important;}.s-opacity-50 .s-opacity-border5-bottom{border-bottom-color: rgba(243,243,243,0.5) !important;}.s-opacity-50 .s-opacity-border5-left{border-left-color: rgba(243,243,243,0.5) !important;}.s-opacity-50 .s-opacity-border5-right{border-right-color: rgba(243,243,243,0.5) !important;}.s-opacity-50 .s-opacity-border6-top{border-top-color: rgba(218,218,218,0.5) !important;}.s-opacity-50 .s-opacity-border6-bottom{border-bottom-color: rgba(218,218,218,0.5) !important;}.s-opacity-50 .s-opacity-border6-left{border-left-color: rgba(218,218,218,0.5) !important;}.s-opacity-50 .s-opacity-border6-right{border-right-color: rgba(218,218,218,0.5) !important;}.s-opacity-50 .s-opacity-border7-top{border-top-color: rgba(226,226,226,0.5) !important;}.s-opacity-50 .s-opacity-border7-bottom{border-bottom-color: rgba(226,226,226,0.5) !important;}.s-opacity-50 .s-opacity-border7-left{border-left-color: rgba(226,226,226,0.5) !important;}.s-opacity-50 .s-opacity-border7-right{border-right-color: rgba(226,226,226,0.5) !important;}.s-opacity-50 .s-opacity-blank1{border-color: rgba(206,206,206,0.5) !important;}.s-opacity-50 .s-opacity-blank2{border-color: rgba(233,233,233,0.5) !important;}.s-opacity-50 .s-opacity-blank3{border-color: rgba(240,240,240,0.5) !important;}.s-opacity-50 .s-opacity-blank4{border-color: rgba(218,218,218,0.5) !important;}.s-opacity-50 .s-opacity-blank5{border-color: rgba(216,216,216,0.5) !important;}.s-opacity-50 .s-opacity-blank6{border-color: rgba(238,238,238,0.5) !important;}.s-opacity-50 .s-opacity-blank7{border-color: rgba(234,234,234,0.5) !important;}.s-opacity-50 .s-opacity-blank8{border-color: rgba(226,226,226,0.5) !important;}.s-opacity-50 .s-opacity-scroll{border-color: rgba(227,227,227,0.5) !important;}.s-opacity-50 .s-opacity-scroll{border-left-color: rgba(225,225,225,0.5) !important;}.s-opacity-50 .s-opacity-scroll{background: none !important;background-image: -webkit-gradient(linear,left top,left bottom,from(rgba(227,227,227,0.5)),to(rgba(227,227,227,0.5))) !important;background-image: -moz-linear-gradient(rgba(227,227,227,0.5) 0%,rgba(227,227,227,0.5) 100%) !important;background-image: -ms-linear-gradient(rgba(227,227,227,0.5) 0%,rgba(227,227,227,0.5) 100%) !important;background-image: -o-linear-gradient(rgba(227,227,227,0.5) 0%,rgba(227,227,227,0.5) 100%) !important;background-image: linear-gradient(rgba(227,227,227,0.5) 0%,rgba(227,227,227,0.5) 100%) !important;filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#7FE3E3E3,endColorstr=#7FE3E3E3) !important;}.s-opacity-50 .s-opacity-scroll-slider{border-color: rgba(225,225,225,0.5) !important;}.s-opacity-50 .s-opacity-scroll-slider{border-bottom-color: rgba(212,212,212,0.5) !important;}.s-opacity-50 .s-opacity-scroll-slider{background: none !important;background-image: -webkit-gradient(linear,left top,left bottom,from(rgba(255,255,255,0.5)),to(rgba(255,255,255,0.5))) !important;background-image: -moz-linear-gradient(rgba(255,255,255,0.5) 0%,rgba(255,255,255,0.5) 100%) !important;background-image: -ms-linear-gradient(rgba(255,255,255,0.5) 0%,rgba(255,255,255,0.5) 100%) !important;background-image: -o-linear-gradient(rgba(255,255,255,0.5) 0%,rgba(255,255,255,0.5) 100%) !important;background-image: linear-gradient(rgba(255,255,255,0.5) 0%,rgba(255,255,255,0.5) 100%) !important;filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#7FFFFFFF,endColorstr=#7FFFFFFF) !important;}.s-opacity-50 .s-opacity-background1{background: none !important;background-image: -webkit-gradient(linear,left top,left bottom,from(rgba(243,243,243,0.5)),to(rgba(243,243,243,0.5))) !important;background-image: -moz-linear-gradient(rgba(243,243,243,0.5) 0%,rgba(243,243,243,0.5) 100%) !important;background-image: -ms-linear-gradient(rgba(243,243,243,0.5) 0%,rgba(243,243,243,0.5) 100%) !important;background-image: -o-linear-gradient(rgba(243,243,243,0.5) 0%,rgba(243,243,243,0.5) 100%) !important;background-image: linear-gradient(rgba(243,243,243,0.5) 0%,rgba(243,243,243,0.5) 100%) !important;filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#7FF3F3F3,endColorstr=#7FF3F3F3) !important;}.s-opacity-50 .s-opacity-background2{background: none !important;background-image: -webkit-gradient(linear,left top,left bottom,from(rgba(248,248,248,0.5)),to(rgba(248,248,248,0.5))) !important;background-image: -moz-linear-gradient(rgba(248,248,248,0.5) 0%,rgba(248,248,248,0.5) 100%) !important;background-image: -ms-linear-gradient(rgba(248,248,248,0.5) 0%,rgba(248,248,248,0.5) 100%) !important;background-image: -o-linear-gradient(rgba(248,248,248,0.5) 0%,rgba(248,248,248,0.5) 100%) !important;background-image: linear-gradient(rgba(248,248,248,0.5) 0%,rgba(248,248,248,0.5) 100%) !important;filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#7FF8F8F8,endColorstr=#7FF8F8F8) !important;}.s-opacity-50 .s-opacity-white-background{background: none !important;background-image: -webkit-gradient(linear,left top,left bottom,from(rgba(255,255,255,0.5)),to(rgba(255,255,255,0.5))) !important;background-image: -moz-linear-gradient(rgba(255,255,255,0.5) 0%,rgba(255,255,255,0.5) 100%) !important;background-image: -ms-linear-gradient(rgba(255,255,255,0.5) 0%,rgba(255,255,255,0.5) 100%) !important;background-image: -o-linear-gradient(rgba(255,255,255,0.5) 0%,rgba(255,255,255,0.5) 100%) !important;background-image: linear-gradient(rgba(255,255,255,0.5) 0%,rgba(255,255,255,0.5) 100%) !important;filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#7FFFFFFF,endColorstr=#7FFFFFFF) !important;}.s-opacity-50 .s-opacity-menu1{background: none !important;background-image: -webkit-gradient(linear,left top,left bottom,from(rgba(0,0,0,0.4)),to(rgba(0,0,0,0.4))) !important;background-image: -moz-linear-gradient(rgba(0,0,0,0.4) 0%,rgba(0,0,0,0.4) 100%) !important;background-image: -ms-linear-gradient(rgba(0,0,0,0.4) 0%,rgba(0,0,0,0.4) 100%) !important;background-image: -o-linear-gradient(rgba(0,0,0,0.4) 0%,rgba(0,0,0,0.4) 100%) !important;background-image: linear-gradient(rgba(0,0,0,0.4) 0%,rgba(0,0,0,0.4) 100%) !important;filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#66000000,endColorstr=#66000000) !important;}.s-opacity-50 .s-opacity-foreground{opacity: 0.5;filter: alpha(opacity=50);}.s-opacity-50 .s-opacity-max{opacity: 0.4;filter: alpha(opacity=40);}.s-opacity-50 .s-opacity-bottommoremenu{background: none !important;background-image: -webkit-gradient(linear,left top,left bottom,from(rgba(0,0,0,0)),to(rgba(0,0,0,0.45))) !important;background-image: -moz-linear-gradient(rgba(0,0,0,0) 0%,rgba(0,0,0,0.45) 100%) !important;background-image: -ms-linear-gradient(rgba(0,0,0,0) 0%,rgba(0,0,0,0.45) 100%) !important;background-image: -o-linear-gradient(rgba(0,0,0,0) 0%,rgba(0,0,0,0.45) 100%) !important;background-image: linear-gradient(rgba(0,0,0,0) 0%,rgba(0,0,0,0.45) 100%) !important;filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#00000000,endColorstr=#72000000) !important;}.s-opacity-50 .s-opacity-topmoremenu{background: none !important;background-image: -webkit-gradient(linear,left top,left bottom,from(rgba(0,0,0,0.45)),to(rgba(0,0,0,0))) !important;background-image: -moz-linear-gradient(rgba(0,0,0,0.45) 0%,rgba(0,0,0,0) 100%) !important;background-image: -ms-linear-gradient(rgba(0,0,0,0.45) 0%,rgba(0,0,0,0) 100%) !important;background-image: -o-linear-gradient(rgba(0,0,0,0.45) 0%,rgba(0,0,0,0) 100%) !important;background-image: linear-gradient(rgba(0,0,0,0.45) 0%,rgba(0,0,0,0) 100%) !important;filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#72000000,endColorstr=#00000000) !important;}"); + GM_addStyle("[tpl='ai-tools-panel'],.fixed-skin-wrapper{display: none!important;}#bottom_layer{position:absolute!important;}.s-opacity-50 .s-opacity-border1-top{border-top-color: rgba(233,233,233,0.5) !important;}.s-opacity-50 .s-opacity-border1-bottom{border-bottom-color: rgba(233,233,233,0.5) !important;}.s-opacity-50 .s-opacity-border1-left{border-left-color: rgba(233,233,233,0.5) !important;}.s-opacity-50 .s-opacity-border1-right{border-right-color: rgba(233,233,233,0.5) !important;}.s-opacity-50 .s-opacity-border2-top{border-top-color: rgba(234,234,234,0.5) !important;}.s-opacity-50 .s-opacity-border2-bottom{border-bottom-color: rgba(234,234,234,0.5) !important;}.s-opacity-50 .s-opacity-border2-left{border-left-color: rgba(234,234,234,0.5) !important;}.s-opacity-50 .s-opacity-border2-right{border-right-color: rgba(234,234,234,0.5) !important;}.s-opacity-50 .s-opacity-border3-top{border-top-color: rgba(238,238,238,0.5) !important;}.s-opacity-50 .s-opacity-border3-bottom{border-bottom-color: rgba(238,238,238,0.5) !important;}.s-opacity-50 .s-opacity-border3-left{border-left-color: rgba(238,238,238,0.5) !important;}.s-opacity-50 .s-opacity-border3-right{border-right-color: rgba(238,238,238,0.5) !important;}.s-opacity-50 .s-opacity-border4-top{border-top-color: rgba(240,240,240,0.5) !important;}.s-opacity-50 .s-opacity-border4-bottom{border-bottom-color: rgba(240,240,240,0.5) !important;}.s-opacity-50 .s-opacity-border4-left{border-left-color: rgba(240,240,240,0.5) !important;}.s-opacity-50 .s-opacity-border4-right{border-right-color: rgba(240,240,240,0.5) !important;}.s-opacity-50 .s-opacity-border5-top{border-top-color: rgba(243,243,243,0.5) !important;}.s-opacity-50 .s-opacity-border5-bottom{border-bottom-color: rgba(243,243,243,0.5) !important;}.s-opacity-50 .s-opacity-border5-left{border-left-color: rgba(243,243,243,0.5) !important;}.s-opacity-50 .s-opacity-border5-right{border-right-color: rgba(243,243,243,0.5) !important;}.s-opacity-50 .s-opacity-border6-top{border-top-color: rgba(218,218,218,0.5) !important;}.s-opacity-50 .s-opacity-border6-bottom{border-bottom-color: rgba(218,218,218,0.5) !important;}.s-opacity-50 .s-opacity-border6-left{border-left-color: rgba(218,218,218,0.5) !important;}.s-opacity-50 .s-opacity-border6-right{border-right-color: rgba(218,218,218,0.5) !important;}.s-opacity-50 .s-opacity-border7-top{border-top-color: rgba(226,226,226,0.5) !important;}.s-opacity-50 .s-opacity-border7-bottom{border-bottom-color: rgba(226,226,226,0.5) !important;}.s-opacity-50 .s-opacity-border7-left{border-left-color: rgba(226,226,226,0.5) !important;}.s-opacity-50 .s-opacity-border7-right{border-right-color: rgba(226,226,226,0.5) !important;}.s-opacity-50 .s-opacity-blank1{border-color: rgba(206,206,206,0.5) !important;}.s-opacity-50 .s-opacity-blank2{border-color: rgba(233,233,233,0.5) !important;}.s-opacity-50 .s-opacity-blank3{border-color: rgba(240,240,240,0.5) !important;}.s-opacity-50 .s-opacity-blank4{border-color: rgba(218,218,218,0.5) !important;}.s-opacity-50 .s-opacity-blank5{border-color: rgba(216,216,216,0.5) !important;}.s-opacity-50 .s-opacity-blank6{border-color: rgba(238,238,238,0.5) !important;}.s-opacity-50 .s-opacity-blank7{border-color: rgba(234,234,234,0.5) !important;}.s-opacity-50 .s-opacity-blank8{border-color: rgba(226,226,226,0.5) !important;}.s-opacity-50 .s-opacity-scroll{border-color: rgba(227,227,227,0.5) !important;}.s-opacity-50 .s-opacity-scroll{border-left-color: rgba(225,225,225,0.5) !important;}.s-opacity-50 .s-opacity-scroll{background: none !important;background-image: -webkit-gradient(linear,left top,left bottom,from(rgba(227,227,227,0.5)),to(rgba(227,227,227,0.5))) !important;background-image: -moz-linear-gradient(rgba(227,227,227,0.5) 0%,rgba(227,227,227,0.5) 100%) !important;background-image: -ms-linear-gradient(rgba(227,227,227,0.5) 0%,rgba(227,227,227,0.5) 100%) !important;background-image: -o-linear-gradient(rgba(227,227,227,0.5) 0%,rgba(227,227,227,0.5) 100%) !important;background-image: linear-gradient(rgba(227,227,227,0.5) 0%,rgba(227,227,227,0.5) 100%) !important;filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#7FE3E3E3,endColorstr=#7FE3E3E3) !important;}.s-opacity-50 .s-opacity-scroll-slider{border-color: rgba(225,225,225,0.5) !important;}.s-opacity-50 .s-opacity-scroll-slider{border-bottom-color: rgba(212,212,212,0.5) !important;}.s-opacity-50 .s-opacity-scroll-slider{background: none !important;background-image: -webkit-gradient(linear,left top,left bottom,from(rgba(255,255,255,0.5)),to(rgba(255,255,255,0.5))) !important;background-image: -moz-linear-gradient(rgba(255,255,255,0.5) 0%,rgba(255,255,255,0.5) 100%) !important;background-image: -ms-linear-gradient(rgba(255,255,255,0.5) 0%,rgba(255,255,255,0.5) 100%) !important;background-image: -o-linear-gradient(rgba(255,255,255,0.5) 0%,rgba(255,255,255,0.5) 100%) !important;background-image: linear-gradient(rgba(255,255,255,0.5) 0%,rgba(255,255,255,0.5) 100%) !important;filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#7FFFFFFF,endColorstr=#7FFFFFFF) !important;}.s-opacity-50 .s-opacity-background1{background: none !important;background-image: -webkit-gradient(linear,left top,left bottom,from(rgba(243,243,243,0.5)),to(rgba(243,243,243,0.5))) !important;background-image: -moz-linear-gradient(rgba(243,243,243,0.5) 0%,rgba(243,243,243,0.5) 100%) !important;background-image: -ms-linear-gradient(rgba(243,243,243,0.5) 0%,rgba(243,243,243,0.5) 100%) !important;background-image: -o-linear-gradient(rgba(243,243,243,0.5) 0%,rgba(243,243,243,0.5) 100%) !important;background-image: linear-gradient(rgba(243,243,243,0.5) 0%,rgba(243,243,243,0.5) 100%) !important;filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#7FF3F3F3,endColorstr=#7FF3F3F3) !important;}.s-opacity-50 .s-opacity-background2{background: none !important;background-image: -webkit-gradient(linear,left top,left bottom,from(rgba(248,248,248,0.5)),to(rgba(248,248,248,0.5))) !important;background-image: -moz-linear-gradient(rgba(248,248,248,0.5) 0%,rgba(248,248,248,0.5) 100%) !important;background-image: -ms-linear-gradient(rgba(248,248,248,0.5) 0%,rgba(248,248,248,0.5) 100%) !important;background-image: -o-linear-gradient(rgba(248,248,248,0.5) 0%,rgba(248,248,248,0.5) 100%) !important;background-image: linear-gradient(rgba(248,248,248,0.5) 0%,rgba(248,248,248,0.5) 100%) !important;filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#7FF8F8F8,endColorstr=#7FF8F8F8) !important;}.s-opacity-50 .s-opacity-white-background{background: none !important;background-image: -webkit-gradient(linear,left top,left bottom,from(rgba(255,255,255,0.5)),to(rgba(255,255,255,0.5))) !important;background-image: -moz-linear-gradient(rgba(255,255,255,0.5) 0%,rgba(255,255,255,0.5) 100%) !important;background-image: -ms-linear-gradient(rgba(255,255,255,0.5) 0%,rgba(255,255,255,0.5) 100%) !important;background-image: -o-linear-gradient(rgba(255,255,255,0.5) 0%,rgba(255,255,255,0.5) 100%) !important;background-image: linear-gradient(rgba(255,255,255,0.5) 0%,rgba(255,255,255,0.5) 100%) !important;filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#7FFFFFFF,endColorstr=#7FFFFFFF) !important;}.s-opacity-50 .s-opacity-menu1{background: none !important;background-image: -webkit-gradient(linear,left top,left bottom,from(rgba(0,0,0,0.4)),to(rgba(0,0,0,0.4))) !important;background-image: -moz-linear-gradient(rgba(0,0,0,0.4) 0%,rgba(0,0,0,0.4) 100%) !important;background-image: -ms-linear-gradient(rgba(0,0,0,0.4) 0%,rgba(0,0,0,0.4) 100%) !important;background-image: -o-linear-gradient(rgba(0,0,0,0.4) 0%,rgba(0,0,0,0.4) 100%) !important;background-image: linear-gradient(rgba(0,0,0,0.4) 0%,rgba(0,0,0,0.4) 100%) !important;filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#66000000,endColorstr=#66000000) !important;}.s-opacity-50 .s-opacity-foreground{opacity: 0.5;filter: alpha(opacity=50);}.s-opacity-50 .s-opacity-max{opacity: 0.4;filter: alpha(opacity=40);}.s-opacity-50 .s-opacity-bottommoremenu{background: none !important;background-image: -webkit-gradient(linear,left top,left bottom,from(rgba(0,0,0,0)),to(rgba(0,0,0,0.45))) !important;background-image: -moz-linear-gradient(rgba(0,0,0,0) 0%,rgba(0,0,0,0.45) 100%) !important;background-image: -ms-linear-gradient(rgba(0,0,0,0) 0%,rgba(0,0,0,0.45) 100%) !important;background-image: -o-linear-gradient(rgba(0,0,0,0) 0%,rgba(0,0,0,0.45) 100%) !important;background-image: linear-gradient(rgba(0,0,0,0) 0%,rgba(0,0,0,0.45) 100%) !important;filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#00000000,endColorstr=#72000000) !important;}.s-opacity-50 .s-opacity-topmoremenu{background: none !important;background-image: -webkit-gradient(linear,left top,left bottom,from(rgba(0,0,0,0.45)),to(rgba(0,0,0,0))) !important;background-image: -moz-linear-gradient(rgba(0,0,0,0.45) 0%,rgba(0,0,0,0) 100%) !important;background-image: -ms-linear-gradient(rgba(0,0,0,0.45) 0%,rgba(0,0,0,0) 100%) !important;background-image: -o-linear-gradient(rgba(0,0,0,0.45) 0%,rgba(0,0,0,0) 100%) !important;background-image: linear-gradient(rgba(0,0,0,0.45) 0%,rgba(0,0,0,0) 100%) !important;filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#72000000,endColorstr=#00000000) !important;}"); } var bingBgLink=document.createElement("a"); bingBgLink.innerHTML="Bing图"; @@ -95,11 +95,11 @@ //riliLink.innerHTML=""+$(".op-calendar-new-right-date,.op-calendar-pc-right-date",iframe.contentDocument).html()+""; riliLink.onmouseenter=function(){ clearTimeout(t); - $(iframe).show(200); - iframeDoc.scrollTop(137); - iframeDoc.scrollLeft(150); - iframe.width=592; - iframe.height=702; + $(iframe).show(200); + iframeDoc.scrollTop(125); + iframeDoc.scrollLeft(145); + iframe.width=618; + iframe.height=630; }; riliLink.onmouseleave=function(){ clearTimeout(t); @@ -123,17 +123,17 @@ riliLink.title=title; } }; - var skinContainer=document.querySelector(".s-skin-container"); - if(!skinContainer){ - skinContainer=document.getElementsByTagName("body")[0]; - GM_addStyle(".s-top-right .ai-entry-right-nologin,.s-top-right .operate-wrapper-nologin{right:362px;}.hot-refresh{padding-bottom:7px;}.hot-title>div,.hot-refresh{background-color: #f0f8ff95; border-radius: 3px 3px 0 0}.s-hotsearch-content{position: absolute; background-color: #f0f8ff95; border-radius: 0 0 5px 5px;padding-right: 2px;}.s_ipt{margin:0!important;}.s_ipt_wr{border-radius: 10px 4px 4px 10px;border-radius: 10px 0 0 10px;background: #fff!important;}#qrcodeCon{display:none}body{position:fixed;_position:absolute;top:0;left:0;height:100%;width:100%;min-width:1000px;z-index:-10;background-position:center 0;background-repeat:no-repeat;background-size:cover;-webkit-background-size:cover;-o-background-size:cover;zoom:1;}"); - var inputsu=document.querySelector("input#su"); - var clickHandler=e=>{ - if(skinContainer)skinContainer.style.backgroundImage=""; - else inputsu.removeEventListener("click",clickHandler); - }; - inputsu.addEventListener("click",clickHandler); + var skinContainer=document.getElementsByTagName("body")[0]; + if (!document.querySelector(".aigc-skin-bg,#s_mancard_main")) { + GM_addStyle(".s-news-rank-content{max-height: 180px; width: 99%; overflow-y: auto; overflow-x: hidden;}.s-top-right .ai-entry-right-nologin,.s-top-right .operate-wrapper-nologin{right:362px;}.hot-refresh{padding-bottom:7px;}.hot-title>div,.hot-refresh{border-radius: 3px 3px 0 0}.s-hotsearch-title>a,.s-hotsearch-title>a>div{padding: 5px;background-color: #f0f8ff95;border-radius: 5px;}.s-hotsearch-content{position: absolute; background-color: #f0f8ff95; border-radius: 5px;padding: 5px;}"); } + GM_addStyle(".s_ipt{margin:0!important;}.s_ipt_wr{border-radius: 10px 4px 4px 10px;border-radius: 10px 0 0 10px;background: #fff!important;}#qrcodeCon{display:none}body{position:fixed;_position:absolute;top:0;left:0;height:100%;width:100%;min-width:1000px;z-index:-10;background-position:center 0;background-repeat:no-repeat;background-size:cover;-webkit-background-size:cover;-o-background-size:cover;zoom:1;}"); + var inputsu=document.querySelector("input#su"); + var clickHandler=e=>{ + if(skinContainer)skinContainer.style.backgroundImage=""; + else inputsu.removeEventListener("click",clickHandler); + }; + inputsu.addEventListener("click",clickHandler); var bingImgObj=GM_getValue("bingImgObj"); if(bingImgObj){ skinContainer.style.backgroundImage = "url(\""+bingImgObj.base64+"\")"; @@ -156,7 +156,7 @@ logo.style.display="initial"; } } - var input=document.querySelector("#kw"); + var input=document.querySelector("#kw,#chat-textarea"); var headWrapper=document.querySelector("#head_wrapper"); let inputHandler = e => { setTimeout(() => { @@ -168,6 +168,11 @@ }, 0); }; input.addEventListener('input', inputHandler); + var submit=document.querySelector("#chat-submit-button"); + submit.addEventListener('click', e => { + if(skinContainer)skinContainer.style.backgroundImage=""; + skinContainer=null; + }); GM_xmlhttpRequest({ method: 'GET', url: "https://global.bing.com/HPImageArchive.aspx?format=js&idx=0&pid=hp&video=1&n=1", diff --git a/BingBgForBaidu/BingBgForGoogle.user.js b/BingBgForBaidu/BingBgForGoogle.user.js new file mode 100644 index 00000000000..dba6149ffdb --- /dev/null +++ b/BingBgForBaidu/BingBgForGoogle.user.js @@ -0,0 +1,320 @@ +// ==UserScript== +// @name BingBgForGoogle +// @name:zh-CN 谷Bing图 +// @name:zh-TW 谷Bing圖 +// @namespace hoothin +// @version 0.3 +// @description Just change the background image of Google homepage to Bing +// @description:zh-CN 给谷歌首页换上 Bing 的背景图 +// @description:zh-TW 給 Google 首頁換上 Bing 的背景圖 +// @author hoothin +// @grant GM_xmlhttpRequest +// @grant GM_setValue +// @grant GM_getValue +// @grant GM_addStyle +// @grant GM_registerMenuCommand +// @grant unsafeWindow +// @connect global.bing.com +// @connect cn.bing.com +// @license MIT License +// @match *://www.google.com/* +// @match *://www.google.ad/* +// @match *://www.google.ae/* +// @match *://www.google.com.af/* +// @match *://www.google.com.ag/* +// @match *://www.google.al/* +// @match *://www.google.am/* +// @match *://www.google.co.ao/* +// @match *://www.google.com.ar/* +// @match *://www.google.as/* +// @match *://www.google.at/* +// @match *://www.google.com.au/* +// @match *://www.google.az/* +// @match *://www.google.ba/* +// @match *://www.google.com.bd/* +// @match *://www.google.be/* +// @match *://www.google.bf/* +// @match *://www.google.bg/* +// @match *://www.google.com.bh/* +// @match *://www.google.bi/* +// @match *://www.google.bj/* +// @match *://www.google.com.bn/* +// @match *://www.google.com.bo/* +// @match *://www.google.com.br/* +// @match *://www.google.bs/* +// @match *://www.google.bt/* +// @match *://www.google.co.bw/* +// @match *://www.google.by/* +// @match *://www.google.com.bz/* +// @match *://www.google.ca/* +// @match *://www.google.cd/* +// @match *://www.google.cf/* +// @match *://www.google.cg/* +// @match *://www.google.ch/* +// @match *://www.google.ci/* +// @match *://www.google.co.ck/* +// @match *://www.google.cl/* +// @match *://www.google.cm/* +// @match *://www.google.cn/* +// @match *://www.google.com.co/* +// @match *://www.google.co.cr/* +// @match *://www.google.com.cu/* +// @match *://www.google.cv/* +// @match *://www.google.com.cy/* +// @match *://www.google.cz/* +// @match *://www.google.de/* +// @match *://www.google.dj/* +// @match *://www.google.dk/* +// @match *://www.google.dm/* +// @match *://www.google.com.do/* +// @match *://www.google.dz/* +// @match *://www.google.com.ec/* +// @match *://www.google.ee/* +// @match *://www.google.com.eg/* +// @match *://www.google.es/* +// @match *://www.google.com.et/* +// @match *://www.google.fi/* +// @match *://www.google.com.fj/* +// @match *://www.google.fm/* +// @match *://www.google.fr/* +// @match *://www.google.ga/* +// @match *://www.google.ge/* +// @match *://www.google.gg/* +// @match *://www.google.com.gh/* +// @match *://www.google.com.gi/* +// @match *://www.google.gl/* +// @match *://www.google.gm/* +// @match *://www.google.gr/* +// @match *://www.google.com.gt/* +// @match *://www.google.gy/* +// @match *://www.google.com.hk/* +// @match *://www.google.hn/* +// @match *://www.google.hr/* +// @match *://www.google.ht/* +// @match *://www.google.hu/* +// @match *://www.google.co.id/* +// @match *://www.google.ie/* +// @match *://www.google.co.il/* +// @match *://www.google.im/* +// @match *://www.google.co.in/* +// @match *://www.google.iq/* +// @match *://www.google.is/* +// @match *://www.google.it/* +// @match *://www.google.je/* +// @match *://www.google.com.jm/* +// @match *://www.google.jo/* +// @match *://www.google.co.jp/* +// @match *://www.google.co.ke/* +// @match *://www.google.com.kh/* +// @match *://www.google.ki/* +// @match *://www.google.kg/* +// @match *://www.google.co.kr/* +// @match *://www.google.com.kw/* +// @match *://www.google.kz/* +// @match *://www.google.la/* +// @match *://www.google.com.lb/* +// @match *://www.google.li/* +// @match *://www.google.lk/* +// @match *://www.google.co.ls/* +// @match *://www.google.lt/* +// @match *://www.google.lu/* +// @match *://www.google.lv/* +// @match *://www.google.com.ly/* +// @match *://www.google.co.ma/* +// @match *://www.google.md/* +// @match *://www.google.me/* +// @match *://www.google.mg/* +// @match *://www.google.mk/* +// @match *://www.google.ml/* +// @match *://www.google.com.mm/* +// @match *://www.google.mn/* +// @match *://www.google.com.mt/* +// @match *://www.google.mu/* +// @match *://www.google.mv/* +// @match *://www.google.mw/* +// @match *://www.google.com.mx/* +// @match *://www.google.com.my/* +// @match *://www.google.co.mz/* +// @match *://www.google.com.na/* +// @match *://www.google.com.ng/* +// @match *://www.google.com.ni/* +// @match *://www.google.ne/* +// @match *://www.google.nl/* +// @match *://www.google.no/* +// @match *://www.google.com.np/* +// @match *://www.google.nr/* +// @match *://www.google.nu/* +// @match *://www.google.co.nz/* +// @match *://www.google.com.om/* +// @match *://www.google.com.pa/* +// @match *://www.google.com.pe/* +// @match *://www.google.com.pg/* +// @match *://www.google.com.ph/* +// @match *://www.google.com.pk/* +// @match *://www.google.pl/* +// @match *://www.google.pn/* +// @match *://www.google.com.pr/* +// @match *://www.google.ps/* +// @match *://www.google.pt/* +// @match *://www.google.com.py/* +// @match *://www.google.com.qa/* +// @match *://www.google.ro/* +// @match *://www.google.ru/* +// @match *://www.google.rw/* +// @match *://www.google.com.sa/* +// @match *://www.google.com.sb/* +// @match *://www.google.sc/* +// @match *://www.google.se/* +// @match *://www.google.com.sg/* +// @match *://www.google.sh/* +// @match *://www.google.si/* +// @match *://www.google.sk/* +// @match *://www.google.com.sl/* +// @match *://www.google.sn/* +// @match *://www.google.so/* +// @match *://www.google.sm/* +// @match *://www.google.sr/* +// @match *://www.google.st/* +// @match *://www.google.com.sv/* +// @match *://www.google.td/* +// @match *://www.google.tg/* +// @match *://www.google.co.th/* +// @match *://www.google.com.tj/* +// @match *://www.google.tl/* +// @match *://www.google.tm/* +// @match *://www.google.tn/* +// @match *://www.google.to/* +// @match *://www.google.com.tr/* +// @match *://www.google.tt/* +// @match *://www.google.com.tw/* +// @match *://www.google.co.tz/* +// @match *://www.google.com.ua/* +// @match *://www.google.co.ug/* +// @match *://www.google.co.uk/* +// @match *://www.google.com.uy/* +// @match *://www.google.co.uz/* +// @match *://www.google.com.vc/* +// @match *://www.google.co.ve/* +// @match *://www.google.co.vi/* +// @match *://www.google.com.vn/* +// @match *://www.google.vu/* +// @match *://www.google.ws/* +// @match *://www.google.rs/* +// @match *://www.google.co.za/* +// @match *://www.google.co.zm/* +// @match *://www.google.co.zw/* +// @match *://www.google.cat/* +// @downloadURL https://update.greasyfork.org/scripts/503741/BingBgForGoogle.user.js +// @updateURL https://update.greasyfork.org/scripts/503741/BingBgForGoogle.meta.js +// ==/UserScript== + +(function() { + 'use strict'; + if (/\?q=/.test(location.href)) return; + let LinkPa = document.querySelector("[data-ogbl]"); + if (!LinkPa) return; + let bingBgLink = document.createElement("a"); + bingBgLink.className = LinkPa.firstChild.firstChild.className; + bingBgLink.target = "_blank"; + bingBgLink.innerText = "Bing Bg"; + let linkDiv = document.createElement("div"); + linkDiv.className = LinkPa.firstChild.className; + linkDiv.appendChild(bingBgLink); + LinkPa.appendChild(linkDiv); + let skinContainer = document.body; + GM_addStyle(` + body{ + background-position: center 0; + background-repeat: no-repeat; + background-size: cover; + -webkit-background-size: cover; + -o-background-size: cover; + } + #gb{ + background-color: unset!important; + } + [role="navigation"],[role="contentinfo"]{ + background-color: rgb(32 33 36 / 50%)!important; + } + #gb *,[role="contentinfo"] *{ + color: white!important; + } + `); + + let btnK = document.querySelector("input[name='btnK']"); + let clickHandler = e => { + skinContainer.style.backgroundImage = ""; + }; + btnK.addEventListener("click",clickHandler); + let bingImgObj = GM_getValue("bingImgObj"); + if (bingImgObj) { + skinContainer.style.backgroundImage = "url(\"" + bingImgObj.base64 + "\")"; + } + + GM_xmlhttpRequest({ + method: 'GET', + url: "https://global.bing.com/HPImageArchive.aspx?format=js&idx=0&pid=hp&video=1&n=1", + onload: function(result) { + let jsonData = null; + try { + jsonData = JSON.parse(result.responseText); + let bgUrl = jsonData.images[0].url; + if (!/^https?:\/\//.test(bgUrl)) { + bgUrl = "https://global.bing.com" + bgUrl; + } + bingBgLink.title = jsonData.images[0].copyright; + bingBgLink.href = bgUrl; + if (bingImgObj && bingImgObj.url == bgUrl) return; + if (!bingImgObj) skinContainer.style.backgroundImage = "url(\"" + bgUrl + "\")"; + GM_xmlhttpRequest({ + method: 'GET', + url: bgUrl, + responseType: "blob", + onload: function(r) { + let blob = r.response; + let fr = new FileReader(); + fr.readAsDataURL(blob); + fr.onload = function (e) { + let base64ImgData = e.target.result; + GM_setValue("bingImgObj",{url: bgUrl, base64: base64ImgData}); + }; + } + }); + } catch (e) { + console.log(e); + } + } + }); + let blurStyle; + function createBlur() { + if (!blurStyle) { + blurStyle = document.createElement("style"); + blurStyle.innerText = ` + body::before{ + content: " "; + display: block; + position: absolute; + left: 0; + top: 0; + right: 0; + bottom: 0; + background: inherit; + filter: blur(5px); + z-index: -1; + }`; + } + document.head.appendChild(blurStyle); + } + if (GM_getValue("blur")) { + createBlur(); + } + GM_registerMenuCommand("Change blur", () => { + if (blurStyle && blurStyle.parentNode) { + GM_setValue("blur", false); + blurStyle.parentNode.removeChild(blurStyle); + } else { + GM_setValue("blur", true); + createBlur(); + } + }); +})(); \ No newline at end of file diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 00000000000..b6d486bd5e3 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,128 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, religion, or sexual identity +and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +* Focusing on what is best not just for us as individuals, but for the + overall community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or + advances of any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email + address, without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official e-mail address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement at +rixixi@gmail.com. +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series +of actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or +permanent ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within +the community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.0, available at +https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. + +Community Impact Guidelines were inspired by [Mozilla's code of conduct +enforcement ladder](https://github.com/mozilla/diversity). + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see the FAQ at +https://www.contributor-covenant.org/faq. Translations are available at +https://www.contributor-covenant.org/translations. diff --git a/DownloadAllContent/DownloadAllContent.user.js b/DownloadAllContent/DownloadAllContent.user.js index 560a73214e1..de600e6dc11 100644 --- a/DownloadAllContent/DownloadAllContent.user.js +++ b/DownloadAllContent/DownloadAllContent.user.js @@ -2,9 +2,9 @@ // @name DownloadAllContent // @name:zh-CN 怠惰小说下载器 // @name:zh-TW 怠惰小説下載器 -// @name:ja 怠惰者小説ダウンロードツール +// @name:ja 怠惰小説ダウンローダー // @namespace hoothin -// @version 2.8.3.10 +// @version 2.8.3.19 // @description Lightweight web scraping script. Fetch and download main textual content from the current page, provide special support for novels // @description:zh-CN 通用网站内容爬虫抓取工具,可批量抓取任意站点的小说、论坛内容等并保存为TXT文档 // @description:zh-TW 通用網站內容爬蟲抓取工具,可批量抓取任意站點的小說、論壇內容等並保存為TXT文檔 @@ -245,8 +245,12 @@ if (window.top != window.self) { abort:"跳过此章", save:"保存当前", saveAsMd:"存为 Markdown", + saveAsJSON: "存为 JSON", downThreadNum:"设置同时下载的线程数,负数为单线程下载间隔", + enableTouch:"在移动端按→↓←↑的方向滑动屏幕画正方形立即开始下载", customTitle:"自定义章节标题,输入内页文字对应选择器", + saveUrl: "储存 URL", + disableAutoStartSave: "禁用自动保存", maxDlPerMin:"每分钟最大下载数", reSortDefault:"默认按页面中位置排序章节", reverseOrder:"反转章节排序", @@ -267,10 +271,11 @@ if (window.top != window.self) { dacSaveAsZip:"下载为 zip", dacSetCustomRule:"修改规则", dacAddUrl:"添加章节", + prefix:"给章节名称添加前缀", dacStartDownload:"下载选中", - downloadShortcut:"下载章节", - downloadSingleShortcut:"下载单页", - downloadCustomShortcut:"自定义下载" + downloadShortcut:"下载章节快捷键", + downloadSingleShortcut:"下载单页快捷键", + downloadCustomShortcut:"自定义下载快捷键" }; break; case "zh": @@ -292,8 +297,12 @@ if (window.top != window.self) { abort:"跳過此章", save:"保存當前", saveAsMd:"存爲 Markdown", + saveAsJSON: "存爲 JSON", downThreadNum:"設置同時下載的綫程數,負數為單線程下載間隔", + enableTouch:"在行動端按→↓←↑的方向滑動螢幕畫方立即開始下載", customTitle:"自訂章節標題,輸入內頁文字對應選擇器", + saveUrl: "儲存 URL", + disableAutoStartSave: "禁用自動保存", maxDlPerMin:"每分鐘最大下載數", reSortDefault:"預設依頁面中位置排序章節", reverseOrder:"反轉章節排序", @@ -314,10 +323,11 @@ if (window.top != window.self) { dacSaveAsZip:"下載為 zip", dacSetCustomRule:"修改規則", dacAddUrl:"新增章節", + prefix:"為章節名稱加上前綴", dacStartDownload:"下載選取", - downloadShortcut:"下載章節", - downloadSingleShortcut:"下載單頁", - downloadCustomShortcut:"自設下載" + downloadShortcut:"下載章節快速鍵", + downloadSingleShortcut:"下載單頁快速鍵", + downloadCustomShortcut:"自設下載快速鍵" }; break; case "ar": @@ -338,47 +348,104 @@ if (window.top != window.self) { case "ar-TN": case "ar-YE": i18n={ - fetch: "تحميل", - info: "المصدر: #t#\nتم تنزيل الـ TXT بواسطة 'DownloadAllContent'", - error: "فشل في تحميل الفصل الحالي", - downloading: "......%s تحميل
صفحات متبقية %s صفحات تم تحميلها، هناك %s", - complete: "صفحات في المجموع %s اكتمل! حصلت على", - del: "لتجاهل CSS تعيين محددات", - custom: "تحميل مخصص", - customInfo: "لروابط الفصول sss إدخال الروابط أو محددات", - reSort: "إعادة الترتيب حسب العنوان", - reSortUrl: "إعادة الترتيب حسب الروابط", - setting: "فتح الإعدادات", - searchRule: "قاعدة البحث", - abort: "إيقاف", - save: "حفظ", - saveAsMd: "Markdown حفظ كـ", - downThreadNum: "تعيين عدد الخيوط للتحميل", - customTitle: "تخصيص عنوان الفصل، إدخال المحدد في الصفحة الداخلية", - maxDlPerMin:"الحد الأقصى لعدد التنزيلات في الدقيقة", - reSortDefault: "الترتيب الافتراضي حسب الموقع في الصفحة", - reverseOrder: "عكس ترتيب الفصول", - saveBtn: "حفظ الإعدادات", - saveOk: "تم الحفظ", - nextPage: "التحقق من الصفحة التالية في الفصل", - nextPageReg: "مخصص للصفحة التالية RegExp", - retainImage: "الاحتفاظ بعنوان الصورة إذا كانت هناك صور في النص", - minTxtLength: "المحاولة مرة أخرى عندما يكون طول المحتوى أقل من هذا", - showFilterList: "عرض نافذة التصفية والترتيب قبل التحميل", - ok: "موافق", - close: "إغلاق", - dacSortByPos: "الترتيب حسب الموقع", - dacSortByUrl: "الترتيب حسب الرابط", - dacSortByName: "الترتيب حسب الاسم", - reverse: "عكس الاختيار", - dacUseIframe: "لتحميل المحتوى (بطيء) iframe استخدام", - dacSaveAsZip: "zip حفظ كـ", - dacSetCustomRule: "تعديل القواعد", - dacAddUrl: "إضافة فصل", - dacStartDownload: "تحميل المحدد", - downloadShortcut: "تحميل الفصل", - downloadSingleShortcut: "تحميل صفحة واحدة", - downloadCustomShortcut: "تحميل مخصص" + encode: true, + fetch: "%D8%AA%D8%AD%D9%85%D9%8A%D9%84", + info: "%D8%A7%D9%84%D9%85%D8%B5%D8%AF%D8%B1:%20#t#%0A%D8%AA%D9%85%20%D8%AA%D9%86%D8%B2%D9%8A%D9%84%20%D8%A7%D9%84%D9%80%20TXT%20%D8%A8%D9%88%D8%A7%D8%B3%D8%B7%D8%A9%20'DownloadAllContent'", + error: "%D9%81%D8%B4%D9%84%20%D9%81%D9%8A%20%D8%AA%D8%AD%D9%85%D9%8A%D9%84%20%D8%A7%D9%84%D9%81%D8%B5%D9%84%20%D8%A7%D9%84%D8%AD%D8%A7%D9%84%D9%8A", + downloading: "......%25s%20%D8%AA%D8%AD%D9%85%D9%8A%D9%84%3Cbr%3E%D8%B5%D9%81%D8%AD%D8%A7%D8%AA%20%D9%85%D8%AA%D8%A8%D9%82%D9%8A%D8%A9%20%25s%20%D8%B5%D9%81%D8%AD%D8%A7%D8%AA%20%D8%AA%D9%85%20%D8%AA%D8%AD%D9%85%D9%8A%D9%84%D9%87%D8%A7%D8%8C%20%D9%87%D9%86%D8%A7%D9%83%20%25s", + complete: "%D8%B5%D9%81%D8%AD%D8%A7%D8%AA%20%D9%81%D9%8A%20%D8%A7%D9%84%D9%85%D8%AC%D9%85%D9%88%D8%B9%20%25s%20%D8%A7%D9%83%D8%AA%D9%85%D9%84!%20%D8%AD%D8%B5%D9%84%D8%AA%20%D8%B9%D9%84%D9%89", + del: "%D9%84%D8%AA%D8%AC%D8%A7%D9%87%D9%84%20CSS%20%D8%AA%D8%B9%D9%8A%D9%8A%D9%86%20%D9%85%D8%AD%D8%AF%D8%AF%D8%A7%D8%AA", + custom: "%D8%AA%D8%AD%D9%85%D9%8A%D9%84%20%D9%85%D8%AE%D8%B5%D8%B5", + customInfo: "%D9%84%D8%B1%D9%88%D8%A7%D8%A8%D8%B7%20%D8%A7%D9%84%D9%81%D8%B5%D9%88%D9%84%20sss%20%D8%A5%D8%AF%D8%AE%D8%A7%D9%84%20%D8%A7%D9%84%D8%B1%D9%88%D8%A7%D8%A8%D8%B7%20%D8%A3%D9%88%20%D9%85%D8%AD%D8%AF%D8%AF%D8%A7%D8%AA", + reSort: "%D8%A5%D8%B9%D8%A7%D8%AF%D8%A9%20%D8%A7%D9%84%D8%AA%D8%B1%D8%AA%D9%8A%D8%A8%20%D8%AD%D8%B3%D8%A8%20%D8%A7%D9%84%D8%B9%D9%86%D9%88%D8%A7%D9%86", + reSortUrl: "%D8%A5%D8%B9%D8%A7%D8%AF%D8%A9%20%D8%A7%D9%84%D8%AA%D8%B1%D8%AA%D9%8A%D8%A8%20%D8%AD%D8%B3%D8%A8%20%D8%A7%D9%84%D8%B1%D9%88%D8%A7%D8%A8%D8%B7", + setting: "%D9%81%D8%AA%D8%AD%20%D8%A7%D9%84%D8%A5%D8%B9%D8%AF%D8%A7%D8%AF%D8%A7%D8%AA", + searchRule: "%D9%82%D8%A7%D8%B9%D8%AF%D8%A9%20%D8%A7%D9%84%D8%A8%D8%AD%D8%AB", + abort: "%D8%A5%D9%8A%D9%82%D8%A7%D9%81", + save: "%D8%AD%D9%81%D8%B8", + saveAsMd: "Markdown%20%D8%AD%D9%81%D8%B8%20%D9%83%D9%80", + saveAsJSON: "JSON%20%D8%AD%D9%81%D8%B8%20%D9%83%D9%80", + downThreadNum: "%D8%AA%D8%B9%D9%8A%D9%8A%D9%86%20%D8%B9%D8%AF%D8%AF%20%D8%A7%D9%84%D8%AE%D9%8A%D9%88%D8%B7%20%D9%84%D9%84%D8%AA%D8%AD%D9%85%D9%8A%D9%84", + enableTouch: "On%20the%20mobile%20device,%20slide%20the%20screen%20in%20the%20direction%20of%20%E2%86%92%E2%86%93%E2%86%90%E2%86%91%20to%20draw%20a%20square%20will%20start%20downloading%20immediately", + customTitle: "%D8%AA%D8%AE%D8%B5%D9%8A%D8%B5%20%D8%B9%D9%86%D9%88%D8%A7%D9%86%20%D8%A7%D9%84%D9%81%D8%B5%D9%84%D8%8C%20%D8%A5%D8%AF%D8%AE%D8%A7%D9%84%20%D8%A7%D9%84%D9%85%D8%AD%D8%AF%D8%AF%20%D9%81%D9%8A%20%D8%A7%D9%84%D8%B5%D9%81%D8%AD%D8%A9%20%D8%A7%D9%84%D8%AF%D8%A7%D8%AE%D9%84%D9%8A%D8%A9", + saveUrl: "%D8%AD%D9%81%D8%B8%20URL", + disableAutoStartSave: "%D8%AA%D8%B9%D8%B7%D9%8A%D9%84%20%D8%A7%D9%84%D8%AD%D9%81%D8%B8%20%D8%A7%D9%84%D8%AA%D9%84%D9%82%D8%A7%D8%A6%D9%8A", + maxDlPerMin: "%D8%A7%D9%84%D8%AD%D8%AF%20%D8%A7%D9%84%D8%A3%D9%82%D8%B5%D9%89%20%D9%84%D8%B9%D8%AF%D8%AF%20%D8%A7%D9%84%D8%AA%D9%86%D8%B2%D9%8A%D9%84%D8%A7%D8%AA%20%D9%81%D9%8A%20%D8%A7%D9%84%D8%AF%D9%82%D9%8A%D9%82%D8%A9", + reSortDefault: "%D8%A7%D9%84%D8%AA%D8%B1%D8%AA%D9%8A%D8%A8%20%D8%A7%D9%84%D8%A7%D9%81%D8%AA%D8%B1%D8%A7%D8%B6%D9%8A%20%D8%AD%D8%B3%D8%A8%20%D8%A7%D9%84%D9%85%D9%88%D9%82%D8%B9%20%D9%81%D9%8A%20%D8%A7%D9%84%D8%B5%D9%81%D8%AD%D8%A9", + reverseOrder: "%D8%B9%D9%83%D8%B3%20%D8%AA%D8%B1%D8%AA%D9%8A%D8%A8%20%D8%A7%D9%84%D9%81%D8%B5%D9%88%D9%84", + saveBtn: "%D8%AD%D9%81%D8%B8%20%D8%A7%D9%84%D8%A5%D8%B9%D8%AF%D8%A7%D8%AF%D8%A7%D8%AA", + saveOk: "%D8%AA%D9%85%20%D8%A7%D9%84%D8%AD%D9%81%D8%B8", + nextPage: "%D8%A7%D9%84%D8%AA%D8%AD%D9%82%D9%82%20%D9%85%D9%86%20%D8%A7%D9%84%D8%B5%D9%81%D8%AD%D8%A9%20%D8%A7%D9%84%D8%AA%D8%A7%D9%84%D9%8A%D8%A9%20%D9%81%D9%8A%20%D8%A7%D9%84%D9%81%D8%B5%D9%84", + nextPageReg: "%D9%85%D8%AE%D8%B5%D8%B5%20%D9%84%D9%84%D8%B5%D9%81%D8%AD%D8%A9%20%D8%A7%D9%84%D8%AA%D8%A7%D9%84%D9%8A%D8%A9%20RegExp", + retainImage: "%D8%A7%D9%84%D8%A7%D8%AD%D8%AA%D9%81%D8%A7%D8%B8%20%D8%A8%D8%B9%D9%86%D9%88%D8%A7%D9%86%20%D8%A7%D9%84%D8%B5%D9%88%D8%B1%D8%A9%20%D8%A5%D8%B0%D8%A7%20%D9%83%D8%A7%D9%86%D8%AA%20%D9%87%D9%86%D8%A7%D9%83%20%D8%B5%D9%88%D8%B1%20%D9%81%D9%8A%20%D8%A7%D9%84%D9%86%D8%B5", + minTxtLength: "%D8%A7%D9%84%D9%85%D8%AD%D8%A7%D9%88%D9%84%D8%A9%20%D9%85%D8%B1%D8%A9%20%D8%A3%D8%AE%D8%B1%D9%89%20%D8%B9%D9%86%D8%AF%D9%85%D8%A7%20%D9%8A%D9%83%D9%88%D9%86%20%D8%B7%D9%88%D9%84%20%D8%A7%D9%84%D9%85%D8%AD%D8%AA%D9%88%D9%89%20%D8%A3%D9%82%D9%84%20%D9%85%D9%86%20%D9%87%D8%B0%D8%A7", + showFilterList: "%D8%B9%D8%B1%D8%B6%20%D9%86%D8%A7%D9%81%D8%B0%D8%A9%20%D8%A7%D9%84%D8%AA%D8%B5%D9%81%D9%8A%D8%A9%20%D9%88%D8%A7%D9%84%D8%AA%D8%B1%D8%AA%D9%8A%D8%A8%20%D9%82%D8%A8%D9%84%20%D8%A7%D9%84%D8%AA%D8%AD%D9%85%D9%8A%D9%84", + ok: "%D9%85%D9%88%D8%A7%D9%81%D9%82", + close: "%D8%A5%D8%BA%D9%84%D8%A7%D9%82", + dacSortByPos: "%D8%A7%D9%84%D8%AA%D8%B1%D8%AA%D9%8A%D8%A8%20%D8%AD%D8%B3%D8%A8%20%D8%A7%D9%84%D9%85%D9%88%D9%82%D8%B9", + dacSortByUrl: "%D8%A7%D9%84%D8%AA%D8%B1%D8%AA%D9%8A%D8%A8%20%D8%AD%D8%B3%D8%A8%20%D8%A7%D9%84%D8%B1%D8%A7%D8%A8%D8%B7", + dacSortByName: "%D8%A7%D9%84%D8%AA%D8%B1%D8%AA%D9%8A%D8%A8%20%D8%AD%D8%B3%D8%A8%20%D8%A7%D9%84%D8%A7%D8%B3%D9%85", + reverse: "%D8%B9%D9%83%D8%B3%20%D8%A7%D9%84%D8%A7%D8%AE%D8%AA%D9%8A%D8%A7%D8%B1", + dacUseIframe: "%D9%84%D8%AA%D8%AD%D9%85%D9%8A%D9%84%20%D8%A7%D9%84%D9%85%D8%AD%D8%AA%D9%88%D9%89%20(%D8%A8%D8%B7%D9%8A%D8%A1)%20iframe%20%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85", + dacSaveAsZip: "zip%20%D8%AD%D9%81%D8%B8%20%D9%83%D9%80", + dacSetCustomRule: "%D8%AA%D8%B9%D8%AF%D9%8A%D9%84%20%D8%A7%D9%84%D9%82%D9%88%D8%A7%D8%B9%D8%AF", + dacAddUrl: "%D8%A5%D8%B6%D8%A7%D9%81%D8%A9%20%D9%81%D8%B5%D9%84", + prefix:"Prefix%20of%20chapter%20name", + dacStartDownload: "%D8%AA%D8%AD%D9%85%D9%8A%D9%84%20%D8%A7%D9%84%D9%85%D8%AD%D8%AF%D8%AF", + downloadShortcut: "%D8%AA%D8%AD%D9%85%D9%8A%D9%84%20%D8%A7%D9%84%D9%81%D8%B5%D9%84", + downloadSingleShortcut: "%D8%AA%D8%AD%D9%85%D9%8A%D9%84%20%D8%B5%D9%81%D8%AD%D8%A9%20%D9%88%D8%A7%D8%AD%D8%AF%D8%A9", + downloadCustomShortcut: "%D8%AA%D8%AD%D9%85%D9%8A%D9%84%20%D9%85%D8%AE%D8%B5%D8%B5" + }; + break; + case "ja": + case "ja-JP": + i18n={ + fetch:"小説のダウンロードを開始", + info:"提供元:#t#\nこの作品は、怠惰小説ダウンローダー(DownloadAllContent)を使ってダウンロードされました。", + error:"このコンテンツの取得に失敗しました", + downloading:"%s/%sエピソードをダウンロード済み
%sをダウンロード中", + complete:"全%sエピソードのダウンロードが完了しました", + del:"テキストの乱れを削除するCSSセレクターを設定", + custom:"カスタムルールでダウンロード", + customInfo:"URLまたは章のCSSセレクターを入力してください", + reSort:"章をタイトル順で並べ替え", + reSortUrl:"章をURL順で並べ替え", + setting:"オプション設定", + searchRule:"サイトの検索ルール", + abort:"この章をスキップ", + save:"現在の設定を保存", + saveAsMd:"Markdown形式で保存", + saveAsJSON: "JSON形式で保存", + downThreadNum:"同時ダウンロードスレッド数を設定(負の値はシングルスレッドでのダウンロード間隔)", + enableTouch:"モバイルで画面をスライドして正方形を描くとダウンロードを開始", + customTitle:"カスタム章タイトル(ページ内のテキストに対応するセレクターを入力)", + saveUrl: "URLを保存", + disableAutoStartSave: "自動保存を無効にする", + maxDlPerMin:"1分あたりの最大ダウンロード数", + reSortDefault:"デフォルト(ページ内の位置)で章を並べ替え", + reverseOrder:"章の並び順を反転", + saveBtn:"設定を保存", + saveOk:"保存しました", + nextPage:"章内のページを検出", + nextPageReg:"カスタムページネーション正規表現", + retainImage:"本文中の画像のURLを保持", + minTxtLength:"検出された本文の文字数がこの数より少ない場合、再取得を試行", + showFilterList:"ダウンロード前に章のフィルタリング・並べ替えウィンドウを表示", + ok:"OK", + close:"閉じる", + dacSortByPos:"ページ内の位置で並べ替え", + dacSortByUrl:"URLで並べ替え", + dacSortByName:"章の名前で並べ替え", + reverse:"選択を反転", + dacUseIframe:"iframeを使ってコンテンツをバックグラウンドで読み込む(低速)", + dacSaveAsZip:"Zip形式でダウンロード", + dacSetCustomRule:"ルールを編集", + dacAddUrl:"章を追加", + prefix:"章のタイトルにプレフィックスを追加", + dacStartDownload:"選択した章をダウンロード", + downloadShortcut:"章ダウンロードのショートカット", + downloadSingleShortcut:"単一ページダウンロードのショートカット", + downloadCustomShortcut:"カスタムダウンロードのショートカット" }; break; default: @@ -398,8 +465,12 @@ if (window.top != window.self) { abort:"Abort", save:"Save", saveAsMd:"Save as Markdown", + saveAsJSON: "Save as JSON", downThreadNum:"Set threadNum for download, negative means interval of single thread", + enableTouch:"On the mobile device, slide the screen in the direction of →↓←↑ to draw a square will start downloading immediately", customTitle: "Customize the chapter title, enter the selector on inner page", + saveUrl: "Save URL", + disableAutoStartSave: "Disable auto save", maxDlPerMin:"Maximum number of downloads per minute", reSortDefault: "Default sort by position in the page", reverseOrder:"Reverse chapter ordering", @@ -420,13 +491,21 @@ if (window.top != window.self) { dacSaveAsZip: "Save as zip", dacSetCustomRule:"Modify rules", dacAddUrl:"Add Chapter", + prefix:"Prefix of chapter name", dacStartDownload:"Download selected", - downloadShortcut:"Download chapter", - downloadSingleShortcut:"Download single page", - downloadCustomShortcut:"Custom download" + downloadShortcut:"Download chapter Shortcut", + downloadSingleShortcut:"Download single page Shortcut", + downloadCustomShortcut:"Custom download Shortcut" }; break; } + if (i18n.encode) { + for (let k in i18n) { + if (k != "encode") { + i18n[k] = decodeURI(i18n[k]); + } + } + } var firefox=navigator.userAgent.toLowerCase().indexOf('firefox')!=-1,curRequests=[],useIframe=false,iframeSandbox=false,iframeInit=false; var filterListContainer,txtDownContent,txtDownWords,txtDownQuit,dacLinksCon,dacUseIframe,shadowContainer,downTxtShadowContainer; @@ -852,7 +931,7 @@ if (window.top != window.self) { height: 30px;line-height: 30px;display:block;color:#FFF;text-align:center;font-size: 12px;font-weight: bold;font-family: arial;background: initial; float: initial; } #txtDownQuit+div{ - position:absolute;right:0px;bottom:2px;cursor: pointer;max-width:85px; + position:absolute;right:0px;bottom:2px;cursor: pointer;display: flex; } #txtDownQuit+div>button{ background: #008aff;border: 0;padding: 5px;border-radius: 6px;color: white;float: right;margin: 1px;height: 25px;line-height: 16px;cursor: pointer;overflow: hidden; @@ -869,6 +948,7 @@ if (window.top != window.self) { + `); txtDownWords=txtDownContent.querySelector("#txtDownWords"); @@ -895,6 +975,8 @@ if (window.top != window.self) { var tempSavebtn = txtDownContent.querySelector('#tempSaveTxt'); var abortbtn = txtDownContent.querySelector('#abortRequest'); var saveAsMd = txtDownContent.querySelector('#saveAsMd'); + var saveAsJSON = txtDownContent.querySelector('#saveAsJSON'); + tempSavebtn.onclick = function(){ saveContent(); console.log(curRequests); @@ -912,6 +994,28 @@ if (window.top != window.self) { var blob = new Blob([txt], {type: "text/plain;charset=utf-8"}); saveAs(blob, document.title.replace(/[\*\/:<>\?\\\|\r\n,]/g, "_") + ".md"); } + saveAsJSON.onclick = function(){ + let txt = []; + rCats.forEach(cat => { + let catArr = cat.split("\r\n", 3); + let saveUrl = GM_getValue("saveUrl"); + let catJson = { + title: catArr[0].trim(), + content: catArr[1].trim() + }; + if (saveUrl){ + catJson = { + title: catArr[0].trim(), + url: catArr[1].trim(), + content: catArr[2].trim() + }; + } + txt.push(catJson); + }); + txt = JSON.stringify(txt, null, 2); + var blob = new Blob([txt], {type: "text/plain;charset=utf-8"}); + saveAs(blob, document.title.replace(/[\*\/:<>\?\\\|\r\n,]/g, "_") + ".json"); + } } let charset = (document.characterSet || document.charset || document.inputEncoding); @@ -924,6 +1028,7 @@ if (window.top != window.self) { charsetValid = false; } } else charsetValid = false; + var iframePool = []; function indexDownload(aEles, noSort){ if(aEles.length<1)return; initTxtDownDiv(); @@ -954,6 +1059,7 @@ if (window.top != window.self) { const minute=60000; var minTxtLength=GM_getValue("minTxtLength") || 100; var customTitle=GM_getValue("customTitle"); + var prefix=GM_getValue("prefix"); var disableNextPage=!!GM_getValue("disableNextPage"); var customNextPageReg=GM_getValue("nextPageReg"); var maxDlPerMin=GM_getValue("maxDlPerMin") || 0; @@ -965,6 +1071,28 @@ if (window.top != window.self) { console.warn(e); } } + function packLink(doc, item) { + if (customTitle) { + try { + let title = doc.querySelector(customTitle); + if (title && title.innerText) { + item.innerText = title.innerText; + } + } catch(e) { + console.warn(e); + } + } + } + function getIframe() { + if (iframePool && iframePool.length) return iframePool.shift(); + let iframe = document.createElement('iframe'); + iframe.name = 'pagetual-iframe'; + iframe.width = '100%'; + iframe.height = '1000'; + iframe.frameBorder = '0'; + iframe.style.cssText = 'margin:0!important;padding:0!important;visibility:hidden!important;flex:0;opacity:0!important;pointer-events:none!important;position:fixed;top:0px;left:0px;z-index:-2147483647;'; + return iframe; + } var insertSigns=[]; // var j=0,rCats=[]; var downIndex=0,downNum=0,downOnce=function(wait){ @@ -987,6 +1115,9 @@ if (window.top != window.self) { let curIndex=downIndex; let aTag=aEles[curIndex]; let request=(aTag, curIndex)=>{ + if (aTag && aTag.cloneNode) { + aTag = aTag.cloneNode(true); + } let tryTimes=0; let validTimes=0; function requestDoc(_charset) { @@ -1023,7 +1154,7 @@ if (window.top != window.self) { } } let base = doc.querySelector("base"); - let nextPages = !disableNextPage && !processFunc && await checkNextPage(doc, base ? base.href : aTag.href); + let nextPages = !disableNextPage && (!processFunc || nextPageFunc) && await checkNextPage(doc, base ? base.href : aTag.href); if (nextPages) { if (!nextPages.length) nextPages = [nextPages]; nextPages.forEach(nextPage => { @@ -1063,16 +1194,6 @@ if (window.top != window.self) { } else { console.log(result.status); } - if (customTitle) { - try { - let title = doc.querySelector(customTitle); - if (title && title.innerText) { - aTag.innerText = title.innerText; - } - } catch(e) { - console.warn(e); - } - } let validData = processDoc(curIndex, aTag, doc, (result.status>=400?` status: ${result.status} from: ${aTag.href} `:""), validTimes < 5); if (!validData && validTimes++ < 5) { downIndex--; @@ -1126,7 +1247,7 @@ if (window.top != window.self) { }); }; if (useIframe) { - let iframe = document.createElement('iframe'), inited = false, failedTimes = 0; + let iframe = getIframe(), inited = false, failedTimes = 0; let loadtimeout; let loadIframe = src => { iframe.src = src; @@ -1135,12 +1256,7 @@ if (window.top != window.self) { iframe.src = src; }, 20000); }; - iframe.name = 'pagetual-iframe'; - iframe.width = '100%'; - iframe.height = '1000'; - iframe.frameBorder = '0'; iframe.sandbox = iframeSandbox || "allow-same-origin allow-scripts allow-popups allow-forms"; - iframe.style.cssText = 'margin:0!important;padding:0!important;visibility:hidden!important;flex:0;opacity:0!important;pointer-events:none!important;position:fixed;top:0px;left:0px;z-index:-2147483647;'; iframe.addEventListener('load', e => { if (e.data != 'pagetual-iframe:DOMLoaded' && e.type != 'load') return; if (inited) return; @@ -1199,16 +1315,6 @@ if (window.top != window.self) { } }); } - if (customTitle) { - try { - let title = doc.querySelector(customTitle); - if (title && title.innerText) { - aTag.innerText = title.innerText; - } - } catch(e) { - console.warn(e); - } - } downIndex++; downNum++; let validData = processDoc(curIndex, aTag, doc, "", failedTimes < 2); @@ -1228,7 +1334,15 @@ if (window.top != window.self) { } catch(e) { console.debug("Stop as cors"); } - if (iframe && iframe.parentNode) iframe.parentNode.removeChild(iframe); + if (iframe && iframe.parentNode) { + try { + iframe.src = 'about:blank'; + } catch (e) { + console.error("Error clearing iframe src:", e); + } + iframe.parentNode.removeChild(iframe); + iframePool.push(iframe); + } } setTimeout(() => { checkIframe(); @@ -1307,11 +1421,22 @@ if (window.top != window.self) { } } rCats = rCats.filter(function(e){return e!=null}); + if (prefix) { + for(i=0;i{ - rCats[i]=(aTag.innerText.replace(/[\r\n\t]/g, "") + "\r\n" + (cause || '') + content.replace(/\s*$/, "")); + packLink(doc, aTag); + let isHref = ""; + let saveUrl = GM_getValue("saveUrl"); + if (saveUrl){ + isHref = aTag.href + '\r\n'; + } + rCats[i]=(aTag.innerText.replace(/[\r\n\t]/g, "") + "\r\n" + isHref + (cause || '') + content.replace(/\s*$/, "")); curRequests = curRequests.filter(function(e){return e[0]!=i}); txtDownContent.style.display="block"; txtDownWords.innerHTML=getI18n("downloading",[downNum,(aEles.length-downNum),aTag.innerText]); @@ -1321,7 +1446,10 @@ if (window.top != window.self) { if(downNum==aEles.length){ txtDownWords.innerHTML=getI18n("complete",[downNum]); sortInnerPage(); - saveContent(); + var disableAutoStartSave = GM_getValue("disableAutoStartSave"); + if(!disableAutoStartSave){ + saveContent(); + } } },3000); } @@ -1408,10 +1536,10 @@ if (window.top != window.self) { function getPageContent(doc, cb, url){ if(!doc)return i18n.error; - if(doc.body && !doc.body.children.length)return doc.body.innerText; if(processFunc){ return processFunc(doc, cb, url); } + if(doc.body && !doc.body.children.length)return doc.body.innerText; [].forEach.call(doc.querySelectorAll("span,div,ul"),function(item){ var thisStyle=doc.defaultView?doc.defaultView.getComputedStyle(item):item.style; if(thisStyle && (thisStyle.display=="none" || (item.nodeName=="SPAN" && thisStyle.fontSize=="0px"))){ @@ -1522,6 +1650,7 @@ if (window.top != window.self) { cStr+=content.replace(/[\uFEFF\xA0 ]+/g," ").replace(/([^\r]|^)\n([^\r]|$)/gi,"$1\r\n$2"); } if(childNode.nodeType!=3 && !/^(I|A|STRONG|B|FONT|IMG)$/.test(childNode.nodeName))cStr+="\r\n"; + else if(childNode.nextSibling && /^P$/.test(childNode.nextSibling.nodeName))cStr+="\r\n"; } if(hasText || noTextEnable || ele==largestContent)rStr+=cStr+"\r\n"; } @@ -1547,7 +1676,7 @@ if (window.top != window.self) { } getContentByLargest(); if (rStr.length < 100) { - let articles = pageData.querySelectorAll("article"); + let articles = pageData.querySelectorAll("article,.content,#content"); if (articles && articles.length == 1) { largestContent = articles[0]; largestNum = largestContent.innerText.length; @@ -1817,6 +1946,17 @@ if (window.top != window.self) { if(evalCode.indexOf("return ")==-1){ if(evalCode.indexOf("@")==0){ let content=""; + var selectors=GM_getValue("selectors"); + if(selectors){ + [].forEach.call(data.querySelectorAll(selectors),function(item){ + item.innerHTML=""; + }); + } + [].forEach.call(data.querySelectorAll("script,style,link,noscript,iframe"),function(item){ + if (item && item.parentNode) { + item.parentNode.removeChild(item); + } + }); if(retainImage){ [].forEach.call(data.querySelectorAll("img[src]"), img => { let imgTxt=`![img](${canonicalUri(img.getAttribute("src"), location.href)})`; @@ -1858,6 +1998,54 @@ if (window.top != window.self) { var downloadSingleShortcut = GM_getValue("downloadSingleShortcut") || {ctrlKey: true, shiftKey: true, altKey: false, metaKey: false, key: 'F9'}; var downloadCustomShortcut = GM_getValue("downloadCustomShortcut") || {ctrlKey: true, shiftKey: false, altKey: true, metaKey: false, key: 'F9'}; + var enableTouch = GM_getValue("enableTouch"); + if (enableTouch) { + const minLength = 256, tg = 0.5, atg = 2; + var lastX, lastY, signs, lastSign; + function tracer(e) { + let curX = e.changedTouches[0].clientX, curY = e.changedTouches[0].clientY; + let distanceX = curX - lastX, distanceY = curY - lastY; + let distance = distanceX * distanceX + distanceY * distanceY; + if (distance > minLength) { + lastX = curX; + lastY = curY; + let direction = ""; + let slope = Math.abs(distanceY / distanceX); + if (slope > atg) { + if (distanceY > 0) { + direction = "↓"; + } else { + direction = "↑"; + } + } else if (slope < tg) { + if (distanceX > 0) { + direction = "→"; + } else { + direction = "←"; + } + } + if (direction && lastSign != direction) { + signs += direction; + lastSign = direction; + } + } + } + document.addEventListener("touchstart", function(e) { + lastX = e.changedTouches[0].clientX; + lastY = e.changedTouches[0].clientY; + lastSign = signs = ""; + document.addEventListener("touchmove", tracer, false); + }, false); + document.addEventListener("touchend", function(e) { + document.removeEventListener("touchmove", tracer, false); + if (signs == "→↓←↑") { + e.stopPropagation(); + e.preventDefault(); + startCustom(); + } + }, false); + } + if (location.origin + location.pathname == configPage) { let exampleNode = document.getElementById("example"); if (!exampleNode) return; @@ -2032,12 +2220,15 @@ if (window.top != window.self) { downloadShortcutInput.addEventListener("keydown", keydonwHandler); downloadSingleShortcutInput.addEventListener("keydown", keydonwHandler); downloadCustomShortcutInput.addEventListener("keydown", keydonwHandler); + let enableTouchInput = createOption(i18n.enableTouch, !!enableTouch, "checkbox"); let delSelector = createOption(i18n.del, GM_getValue("selectors") || ""); delSelector.setAttribute("placeHolder", ".mask,.ksam"); let downThreadNum = createOption(i18n.downThreadNum, GM_getValue("downThreadNum") || "20", "number"); let maxDlPerMin = createOption(i18n.maxDlPerMin, GM_getValue("maxDlPerMin") || "0", "number"); let customTitle = createOption(i18n.customTitle, GM_getValue("customTitle") || ""); + let saveUrl = createOption(i18n.saveUrl, !!GM_getValue("saveUrl"), "checkbox"); + let disableAutoStartSave = createOption(i18n.disableAutoStartSave, !!GM_getValue("disableAutoStartSave"), "checkbox"); customTitle.setAttribute("placeHolder", "title"); let minTxtLength = createOption(i18n.minTxtLength, GM_getValue("minTxtLength") || "100", "number"); let contentSortUrlValue = GM_getValue("contentSortUrl") || false; @@ -2049,10 +2240,12 @@ if (window.top != window.self) { reSortUrl.name = "sort"; contentSort.name = "sort"; let reverse = createOption(i18n.reverseOrder, !!GM_getValue("reverse"), "checkbox"); + let prefix = createOption(i18n.prefix, GM_getValue("prefix") || ""); let disableNextPage = !!GM_getValue("disableNextPage"); let nextPage = createOption(i18n.nextPage, !disableNextPage, "checkbox"); let nextPageReg = createOption(i18n.nextPageReg, GM_getValue("nextPageReg") || ""); let retainImage = createOption(i18n.retainImage, !!GM_getValue("retainImage"), "checkbox"); + prefix.setAttribute("placeHolder", "第 $i 章:"); nextPageReg.setAttribute("placeHolder", "^\\s*(下一[页頁张張]|next\\s*page|次のページ)"); if (disableNextPage) { nextPageReg.parentNode.style.display = "none"; @@ -2070,6 +2263,8 @@ if (window.top != window.self) { GM_setValue("maxDlPerMin", parseInt(maxDlPerMin.value || 20)); GM_setValue("minTxtLength", parseInt(minTxtLength.value || 100)); GM_setValue("customTitle", customTitle.value || ""); + GM_setValue("disableAutoStartSave", disableAutoStartSave.checked); + GM_setValue("saveUrl", saveUrl.checked); if (reSortUrl.checked) { GM_setValue("contentSortUrl", true); GM_setValue("contentSort", false); @@ -2081,10 +2276,12 @@ if (window.top != window.self) { GM_setValue("contentSort", false); } GM_setValue("reverse", reverse.checked); + GM_setValue("enableTouch", enableTouchInput.checked); GM_setValue("retainImage", retainImage.checked); GM_setValue("showFilterList", showFilterList.checked); GM_setValue("disableNextPage", !nextPage.checked); GM_setValue("nextPageReg", nextPageReg.value || ""); + GM_setValue("prefix", prefix.value || ""); GM_setValue("downloadShortcut", geneShortcutData(downloadShortcutInput.value) || ""); GM_setValue("downloadSingleShortcut", geneShortcutData(downloadSingleShortcutInput.value) || ""); GM_setValue("downloadCustomShortcut", geneShortcutData(downloadCustomShortcutInput.value) || ""); @@ -2103,7 +2300,7 @@ if (window.top != window.self) { function startCustom() { var customRules = GM_getValue("DACrules_" + document.domain); - var urls = window.prompt(i18n.customInfo, customRules ? customRules : "https://xxx.xxx/book-[20-99].html, https://xxx.xxx/book-[01-10].html"); + var urls = window.prompt(i18n.customInfo + ":\nhttps://xxx.xxx/book-[20-99].html, https://xxx.xxx/book-[01-10].html", customRules || ""); if (urls) { customDown(urls); } diff --git a/DownloadAllContent/DownloadAllContentSavaAsZIP.user.js b/DownloadAllContent/DownloadAllContentSavaAsZIP.user.js index ceb8dcc0a09..73c8e6a5ad6 100644 --- a/DownloadAllContent/DownloadAllContentSavaAsZIP.user.js +++ b/DownloadAllContent/DownloadAllContentSavaAsZIP.user.js @@ -3,7 +3,7 @@ // @name:zh-CN 怠惰小说下载器 ZIP 扩展 // @name:zh-TW 怠惰小説下載器 ZIP 擴充 // @namespace hoothin -// @version 0.6 +// @version 0.6.1 // @description Save content as ZIP for DownloadAllContent // @description:zh-CN 下载时分章节保存 TXT 并打包为 ZIP // @description:zh-TW 下載時分章節儲存 TXT 並打包為 ZIP @@ -198,7 +198,7 @@ imgMatch = cat.match(mdImgReg); hasImg = true; } - zipTemp.push({title: (i + 1) + " - " + catTitle.replace(/[\*\/:<>\?\\\|\r\n]/g, "_").slice(0, 50), hasImg: hasImg, content: cat}); + zipTemp.push({title: catTitle.replace(/[\*\/:<>\?\\\|\r\n]/g, "_").slice(0, 50), hasImg: hasImg, content: cat}); } downloadImages(() => { zipTemp.forEach(d => { diff --git a/DownloadAllContent/README.md b/DownloadAllContent/README.md index c8b5c03d8b7..f5de4823ebd 100644 --- a/DownloadAllContent/README.md +++ b/DownloadAllContent/README.md @@ -1,30 +1,33 @@ -起點等都推薦用這個腳本[【小說】下載腳本](https://github.com/dodying/UserJs/tree/master/novel/novelDownloader),遇到沒人願意適配的小站再考慮我的腳本。 +起點等主流網站建議優先使用這個腳本[【小說】下載腳本](https://github.com/dodying/UserJs/tree/master/novel/novelDownloader),如果遇到沒有人願意支援的小網站,再考慮我的腳本。 -勿用于版權站,如造成侵權或對象站點損失,後果自負。 +請勿用於有版權的網站,如造成侵權或對目標網站造成損失,後果請自行負責。 -輕量級抓取腳本,用於下載網頁小説或其他文字內容,理論上通用於任何靜態寫入正文的小說網站、論壇、貼吧等而無需規則。 +輕量級抓取腳本,用於下載網路小說或其他文字內容。理論上,它通用於任何將內文靜態寫入網頁的小說網站、論壇、貼吧等,且無須另外設定規則。 -腳本會自動檢索頁面中的主要內容並下載(省得複製完gal攻略還要手動逐條刪除「某某某13級頭銜水龍王發表於X年X月X日來自XX客戶端」)。 -如果位於小說目錄頁會遍歷所有章節並排序拼接後存為TXT文檔。 +腳本會自動偵測並下載頁面中的主要內容(省得複製完gal攻略還要手動逐條刪除「某某某13級頭銜水龍王發表於X年X月X日來自XX客戶端」)。 +如果當前在小說目錄頁,腳本會遍歷所有章節,排序後串接成一個 TXT 文字檔。 [![img](https://img.shields.io/github/stars/hoothin/UserScripts?style=social)](https://github.com/hoothin/UserScripts#StarMe) ⭐[Star Me](https://github.com/hoothin/UserScripts#StarMe) +安裝: [Github📥](https://hoothin.github.io/UserScripts/DownloadAllContent/DownloadAllContent.user.js) / [Greasefork📥](https://greasyfork.org/scripts/25068). + --- # 操作說明 -+ 打開小說目錄頁、論壇或貼吧內容頁 -+ 按下 `CTRL+F9` 或點擊命令菜單 -+ 按下 `SHIFT+CTRL+F9` 忽略目錄,僅下載當前頁 ++ 開啟小說目錄頁、論壇或貼吧的內容頁面 ++ 按下 `CTRL+F9` 或點擊使用者腳本管理器中的指令選單 ++ 按下 `SHIFT+CTRL+F9` 可忽略目錄,僅下載當前頁面 ++ 建議開啟`下載前顯示章節篩選排序視窗`的選項 -若是遇到下載出錯的站點,可隨意提交 issue 至 [Github](https://github.com/hoothin/UserScripts/)。請幫我點亮 Star ! +如果遇到下載出錯的網站,歡迎到 [Github](https://github.com/hoothin/UserScripts/) 提交 issue。也請順手幫我點亮 Star! -*對你有幫助的話,可透過 [![i](https://static.afdiancdn.com/favicon.ico) 愛發電](https://afdian.net/a/hoothin) 或者 [![i](https://ko-fi.com/favicon-32x32.png) Ko-fi](https://ko-fi.com/hoothin) 請我喝一杯奶茶。歡迎加入 [💬Discord 群組](https://discord.com/invite/keqypXC6wD)。* +*對你有幫助的話,可透過 [![i](https://static.afdiancdn.com/favicon.ico) 愛發電](https://afdian.com/a/hoothin) 或者 [![i](https://ko-fi.com/favicon-32x32.png) Ko-fi](https://ko-fi.com/hoothin) 請我喝一杯奶茶。也歡迎加入 [💬Discord 群組](https://discord.com/invite/keqypXC6wD) 或者關注我的 [Twitter](https://twitter.com/intent/follow?screen_name=HoothinDev)。* ![donate](https://s2.loli.net/2023/02/06/afTMxeASm48z5vE.jpg) -[怠惰小説下載器 ZIP 擴充](https://greasyfork.org/scripts/476943) 下載時分章節保存 TXT 並打包為 ZIP +[怠惰小説下載器 ZIP 擴充](https://hoothin.github.io/UserScripts/DownloadAllContent/DownloadAllContentSavaAsZIP.user.js) 下載時將各章節分別存為 TXT,並打包成 ZIP 檔 -[圖片驗證碼辨識](https://github.com/hoothin/ImgCodeCheck) 開啟`保留內文圖片的網址`後配合 ZIP 擴充可自動轉換圖片文字,詳閱[愛發電](https://afdian.net/p/c7fc3abc8e8411ee9b1852540025c377) +[圖片驗證碼辨識](https://github.com/hoothin/ImgCodeCheck) 開啟`保留內文圖片的網址`後配合 ZIP 擴充可自動轉換圖片文字,詳閱[愛發電](https://afdian.com/p/c7fc3abc8e8411ee9b1852540025c377) ## 怠惰心法 名喚怠惰,實為勤勉 @@ -34,41 +37,43 @@ **CTRL+F9** 就完事了唄。 ### 第二層心法(超易) - 倘若章節連結沒有xx章、xx節、xx話之類的特徵字樣,可點擊**自定義下載**,輸入隨便一個章節名,例如 「眾神的風車」,即可標記所有同級連結為目錄章節並下載。假如頁面有兩套章節格式,也可標記多個,例如「眾神的風車,風車的眾神」。亦可標記排除項,例如「眾神的風車01!02!03,風車的眾神!鐵幕」,代表標記「眾神的風車01」同級連結並排除含有 02 的項和含有 03 的項,同時標記「風車的眾神」同級連結並排除含有「鐵幕」的項。 + 倘若章節連結沒有xx章、xx節、xx話之類的特徵字樣,可點擊**自訂下載**,輸入任意一個章節名稱,例如 「`眾神的風車`」,即可標記所有同級的連結為目錄章節並下載。假如頁面有兩種章節格式,也可以標記多個,例如「`眾神的風車,風車的眾神`」。亦可標記排除項,例如「`眾神的風車01!02!03,風車的眾神!鐵幕`」,這代表:標記「眾神的風車01」的同級連結,但排除其中含有「02」和「03」的項目;同時標記「風車的眾神」的同級連結,並排除含有「鐵幕」的項目。 ### 第三層心法(略易) - 如果內頁沒有正文,但章節連結與真實內容連結有關聯,可通過**自定義下載**,替換連結內容獲取真實內容。例如 【`眾神的風車@@articles@@articlescontent`】,即可替換章節 URL 中的 articles 為 articlescontent 並自動獲取內容。 + 如果內頁沒有正文,但章節連結與真實內容連結有關聯,可透過**自訂下載**,替換連結內容來獲取真實內容。例如輸入 「`眾神的風車@@articles@@articlescontent`」,即可替換章節 URL 中的 articles 為 articlescontent 並自動獲取內容。 ### 第四層心法(略難) - 如果連結無法由直接替換得到最終地址,可用正則替換,例如【`眾神的風車@@articles(\d+)@@articlescontent_$1b`】,即可替換章節 URL 中的 articles1、articles2 為 + 如果連結無法由直接替換得到最終網址,可用正規表示式替換,例如【`眾神的風車@@articles(\d+)@@articlescontent_$1b`】,即可替換章節 URL 中的 articles1、articles2 為 `articlescontent_1b、articlescontent_2b` ### 第五層心法(難) 輸入章節的 css 選擇器可以更精確地標記章節連結。例如`.l_chaptname>a`,代表 class 為 l_chaptname 的元素下的 a 連結。 - 下載內容可能含有幹擾碼,此時只需點擊**懶人小說下載設置**,輸入幹擾碼的 css 選擇器即可排除幹擾碼。例如 `.mask,.ksam,font.jammer`,代表刪除 class 為 mask 或者 ksam 的元素或者 class 為 jammer 的 font 元素。 + 如果有内分頁,且無法用正規表示式提取下一頁連結,可直接用選擇器來獲取,例如`.l_chaptname>a@@@@@@next:{.curr+a}`。 + 如果內文擷取錯誤,也可以使用選擇器來獲取,例如`.l_chaptname>a@@@@@@@div#content`或者`.l_chaptname>a@@@@@@next:{.curr+a}@div#content`。 + 下載內容可能含有幹擾碼,此時只需點擊**懶人小說下載設置**,輸入幹擾碼的 CSS 選擇器即可排除幹擾碼。例如 `.mask,.ksam,font.jammer`,代表刪除 class 為 mask 或者 ksam 的元素,或者 class 為 jammer 的 font 元素。 ### 第六層心法(超難) - 倘若正文不在內頁正文,是頁面加載後處理得到的,可點擊**自定義下載**,輸入自定義代碼對內頁進行分析獲取正確結果。例如 【`眾神的風車@@@@@@var noval=JSON.parse(doc.querySelector("#meta-preload-data").content).novel;noval[Object.keys(noval)[0]].content;`】,即可通過自定義代碼處理返回頁面獲取內容。代碼中使用 doc 可以獲得返回頁面的 document,最後一個表達式的值為最終寫入的內容。 + 倘若內文並非直接存在於頁面原始碼,而是在頁面載入後才處理生成的,可以點擊**自訂下載**,輸入自訂程式碼對內頁進行分析以獲取正確結果。例如 【`眾神的風車@@@@@@var noval=JSON.parse(doc.querySelector("#meta-preload-data").content).novel;noval[Object.keys(noval)[0]].content;`】,即可透過自訂程式碼處理返回的頁面來獲取內容。程式碼中的 `doc` 代表返回頁面的 document 物件,最後一個表達式的值就是最終寫入的內容。 - 如果返回 false,代表異步回調,可自行抓取內容並等待抓取成功後用 cb(content) 返回抓取到的 content。 + 如果返回 `false`,代表這是一個非同步回呼(asynchronous callback),可自行抓取內容並等待抓取成功後用 `cb(content)`` 回傳抓取到的 content。 - 倘若章節沒有連結,點擊後方纔生成連結跳轉,可通過 `>>` 管道處理抓取到的元素生成章節連結,詳情見下方例子。 + 倘若章節沒有連結,而是點擊後才生成連結並跳轉,可透過 `>>` 管道處理抓取到的元素生成章節連結,例如`a.link >> item.href = xxx; return item;`。詳情見下方範例。 ### 第七層心法(極難) - 倘若正文已經經過加密,需要解密才能獲取正確內容,可打開瀏覽器的控製臺,自定義 dacProcess 函數,調取頁面中網站自身的解密代碼處理抓取的加密數據。例如控製臺輸入`dacProcess=data=>{return decrypt(xxx);}` 代表調用網站的 decrypt 解密章節頁面返回的數據。然後再點擊**自定義下載**,需要注意自定義下載時標記章節是必需的。 + 倘若正文已經經過加密,需要解密才能獲取正確內容,可開啟瀏覽器的開發人員工具主控台,自訂 dacProcess 函數,調取頁面中網站自身的解密程式碼處理抓取的加密數據。例如主控台輸入`dacProcess=data=>{return decrypt(xxx);}` 代表調用網站的 decrypt 函數來解密章節頁面返回的資料。然後再點擊**自訂下載**,需要注意自訂下載時,標記章節是必要步驟。 -### 關於配置項 - **【以下功能需要通過 Tampermonkey 等管理器的命令菜單進入】** +### 關於設定選項 + **【以下功能需要透過 Tampermonkey 等腳本管理器的指令選單進入】** ![img](https://greasyfork.s3.us-east-2.amazonaws.com/grg0pe1t13eth8t012bd1absp9id) - - 自定義目錄:如`https://xxx.xxx/book-**[20-99]**.html,https://xxx.xxx/book-**[01-10]**.html`,意思為下載book-20.html到book-99.html,以及book-01.html到book-10.html,使用**[1-10]**則不補0。 - - 章節選擇器自定義:輸入章節連結的 css 選擇器即可,後面可以接上 url 替換碼、以及自定義處理代碼。 + - 自訂目錄:如`https://xxx.xxx/book-**[20-99]**.html,https://xxx.xxx/book-**[01-10]**.html`,意思為下載book-20.html到book-99.html,以及book-01.html到book-10.html,使用**[1-10]**則不補0。 + - 章節選擇器自訂:輸入章節連結的 css 選擇器即可,後面可以接上 url 替換碼、以及自定義處理代碼。 - 幹擾碼:填入幹擾碼的 css 選擇器,如`.mask,.ksam`,意為刪除 class 為 mask 或者 ksam 的元素。 - 按標題名重新排序:是則把目錄頁所有連結按標題名排序後存入txt,否則按頁面位置順序排列。 - - 下載線程數:同時下載的線程數,默認為20,遇到存在限製的站點(例如下載時總有章節獲取失敗)可調低。 + - 下載線程數:同時下載的執行緒數量,默認為20,遇到存在限製的站點(例如下載時總有章節獲取失敗)可調低。 ### 完整格式說明 -某個章節名 / CSS 選擇器【選擇器後可跟 >> 傳入 item 處理】 **@@** 抓取到 URL 的正則匹配 **@@** 正則替換 URL **@@** 根據爬取返回內容 data 處理並返回最終文本 +某個章節名 / CSS 選擇器【選擇器後可跟 >> 傳入 item 處理】 **@@** 抓取到 URL 的正規表示式匹配 **@@** 正規表示式替換 URL **@@** 根據爬取返回內容 data 進行處理並回傳最終文本 #### 内頁處理範例 假設章節元素為 `a.links` + 使用 iframe 處理内頁内容 @@ -77,16 +82,16 @@ `a.links@@@@@@iframe:sandbox:{allow-same-origin}` - iframe 添加初始化程式碼 `a.links@@@@@@iframe:init:{win.top=win.self}` -+ 自定義内頁中分頁抓取方式 ++ 自訂内頁中分頁抓取方式 - 透過選擇器抓取 `a.links@@@@@@next:{a.next}` - 透過程式碼生成 `a.links@@@@@@next:{return await getNextElement()}` 可以用多層 `{}` 來避免程式碼中出現大括號產生的問題 -### 自定義下載範例,打開目錄頁點擊【自定義下載】粘貼後使用,僅爲規則實例引導,有出入請自行修改 +### 自訂下載範例,打開目錄頁點擊【自訂下載】粘貼後使用,僅爲規則實例引導,有出入請自行修改 + [📕po18](https://www.po18.tw/books/755779/articles) -> 章節的選擇器為 `.l_chaptname>a` ,輸入並下載後發現通過 url 無法下載正文內容,正文是 ajax 通過 articlescontent 下載的。此時可後接 `@@articles@@articlescontent` (@@ 分隔) 將章節 url 中的 articles 替換為 articlescontent 。 `.l_chaptname>a@@articles@@articlescontent` 粘貼進命令菜單即可下載。其中第一個 articles 可使用正則,例如 `@@articles(\d+)@@$1content` 代表將連結中的「articles1」「articles2」等替換為「1content」「2content」。 +> 章節的選擇器為 `.l_chaptname>a` ,輸入並下載後發現通過 url 無法下載正文內容,正文是 ajax 通過 articlescontent 下載的。此時可後接 `@@articles@@articlescontent` (@@ 分隔) 將章節 url 中的 articles 替換為 articlescontent 。 `.l_chaptname>a@@articles@@articlescontent` 粘貼進命令菜單即可下載。其中第一個 articles 可使用正規表示式,例如 `@@articles(\d+)@@$1content` 代表將連結中的「articles1」「articles2」等替換為「1content」「2content」。 ``` css .l_chaptname>a@@articles@@articlescontent ``` @@ -99,6 +104,10 @@ ``` javascript main>section ul>li div>a@@@@@@var noval=JSON.parse(doc.querySelector("#meta-preload-data").content).novel;noval[Object.keys(noval)[0]].content; ``` + 新規則 + ``` javascript +main>section ul>li div>a@@novel/show\.php\?id=@@ajax/novel/@@data.json().body.content; + ``` + [📕紅薯中文網](https://g.hongshu.com/chapterlist/91735.do) > 這個站沒有目錄連結,此時可以遍歷標籤自己創建目錄連結下載 ``` javascript @@ -207,7 +216,7 @@ function decode(t) { + [📕愛發電](https://愛發電/album/afee5ce2462d11ee897e52540025c377) > 我也是愛發電用戶,拿人手短,就不欺負它了。只給個思路,用第四層心法取 album_id 與 章節 id 去 /api/post 請求數據即可。 + [📕頭文字小説](https://m.touwz.net/dushi/yinhezhuiluo/) -> 簡單的分頁,沒啥難點。惟一需要注意的是,分頁連結藏在 js 代碼裏,用正則取出完事。 +> 簡單的分頁,沒啥難點。惟一需要注意的是,分頁連結藏在 js 代碼裏,用正規表示式取出完事。 ``` javascript .chapter>li>a@@@@@@let content="\n";let checkContent=(doc,over)=>{word=doc.querySelector('.content-div');if(!word)content+='\n'+doc.body.innerText;else {let ps=[];[].forEach.call(word.children, p=>{if(p.className!='moreinfo')ps.push(p.innerText)});content+=ps.join('\n');}let next=doc.querySelector("#pt_next");if(next){fetch(location.href+ doc.body.innerHTML.match(/'([^\|']+)\|[^']+'\.split/)[1]+".html").then(r => r.text()).then(d => {let _doc = document.implementation.createHTMLDocument('');_doc.documentElement.innerHTML = d;checkContent(_doc,over);});}else over();};checkContent(data,()=>{cb(content.replace(/\s*「如章节缺失请退#出#阅#读#模#式」\s*|\s*本章未完,点下一页继续阅读。>>>\s*/g,''))});return false; ``` diff --git a/Easy offline/Easy offline pikpak.user.js b/Easy offline/Easy offline pikpak.user.js new file mode 100644 index 00000000000..8550d395dc0 --- /dev/null +++ b/Easy offline/Easy offline pikpak.user.js @@ -0,0 +1,249 @@ +// ==UserScript== +// @name Easy Offline pikpak addon +// @namespace hoothin +// @version 2024-08-16 +// @description Add pikpak support for Easy Offline +// @author hoothin +// @match *://*/* +// @grant GM_setValue +// @grant GM_getValue +// @grant GM_xmlhttpRequest +// @grant GM_notification +// @grant unsafeWindow +// @run-at document-start +// @require https://unpkg.com/crypto-js@4.2.0/crypto-js.js +// @connect user.mypikpak.com +// @connect api-drive.mypikpak.com +// ==/UserScript== + +(function() { + 'use strict'; + let info = GM_getValue("pikpakUserInfo"), device_id, user_id; + const CLIENT_ID = "YNxT9w7GMdWvEOKa"; + const CLIENT_SECRET = "dbw2OtmVEeuUvIptb1Coyg"; + const CLIENT_VERSION = "1.47.1"; + const PACKAG_ENAME = "com.pikcloud.pikpak"; + const SDK_VERSION = "2.0.4.204000"; + const APP_NAME = "com.pikcloud.pikpak"; + function captchaInit() { + return new Promise(resolve => { + let meta = {}; + if (/\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*/.test(info.userName)) { + meta.email = info.userName; + } else if (/\d{11,18}/.test(info.userName)) { + meta.phone_number = info.userName; + } else { + meta.username = info.userName; + } + let params = { + "client_id": CLIENT_ID, + "action": "POST:https://user.mypikpak.com/v1/auth/signin", + "device_id": device_id, + "meta": meta + } + GM_xmlhttpRequest({ + method: 'POST', + url: 'https://user.mypikpak.com/v1/shield/captcha/init', + data: JSON.stringify(params), + onload: (res) => { + if(res.status === 200) { + let data = JSON.parse(res.responseText); + resolve(data); + } else { + info.loginInfo = null; + GM_setValue("pikpakUserInfo", info); + const msg = JSON.parse(res.responseText).error_description; + alert(msg); + } + }, + onerror: (e) => { + GM_notification("Error: " + (e.statusText || e.error)); + }, + ontimeout: (e) => { + GM_notification("Error: " + (e.statusText || e.error)); + } + }); + }); + } + function buildCustomUserAgent() { + let signature_base = `${device_id}${PACKAG_ENAME}1appkey`; + let sha1_result = CryptoJS.SHA1(signature_base).toString(CryptoJS.enc.Hex); + let md5_result = CryptoJS.MD5(sha1_result).toString(CryptoJS.enc.Hex); + + let device_sign = `div101.${device_id}${md5_result}`; + + let user_agent_parts = [ + `ANDROID-${APP_NAME}/${CLIENT_VERSION}`, + "protocolVersion/200", + "accesstype/", + `clientid/${CLIENT_ID}`, + `clientversion/${CLIENT_VERSION}`, + "action_type/", + "networktype/WIFI", + "sessionid/", + `deviceid/${device_id}`, + "providername/NONE", + `devicesign/${device_sign}`, + "refresh_token/", + `sdkversion/${SDK_VERSION}`, + `datetime/${Date.now()}`, + `usrno/${user_id}`, + `appname/${APP_NAME}`, + "session_origin/", + "grant_type/", + "appid/", + "clientip/", + "devicename/Xiaomi_M2004j7ac", + "osversion/13", + "platformversion/10", + "accessmode/", + "devicemodel/M2004J7AC", + ] + + return user_agent_parts.join(" "); + } + document.addEventListener("click", function(e) { + if (e.target && e.target.getAttribute && e.target.getAttribute("name") === "pikpak" && e.target.parentNode.id === "icons") { + GM_setValue("pikpakUserInfo", ""); + alert("PikPak account has been cleared"); + } + }); + var _unsafeWindow = (typeof unsafeWindow === 'undefined') ? window : unsafeWindow; + if (!_unsafeWindow.eoAddons) _unsafeWindow.eoAddons = {}; + _unsafeWindow.eoAddons.pikpak = { + regex: /mypikpak\.com/, + url: "http://user.mypikpak.com/", + bgColor: "2265ff", + noTxt: true, + linkRegExp: /^magnet:\?xt|^PikPak:\/\/|\.(torrent|mp4|mp3|rar|7z|zip|rmvb|mkv|avi|iso)$/i, + directUrl: function(offUrl) { + if (!info) { + let userName = prompt("userName"); + if (!userName) return; + let userPass = prompt("userPass"); + if (!userPass) return; + info = {userName: userName, userPass: userPass}; + GM_setValue("pikpakUserInfo", info); + } + var postUrl = async () => { + let postData; + if (offUrl.indexOf('PikPak://') === 0) { + const urlData = offUrl.substring(9).split('|') + postData = { + kind: "drive#file", + name: urlData[0], + size: urlData[1], + hash: urlData[2], + upload_type: "UPLOAD_TYPE_RESUMABLE", + objProvider: { + provider: "UPLOAD_TYPE_UNKNOWN" + } + } + } else { + postData = { + kind: "drive#file", + name: "", + upload_type: "UPLOAD_TYPE_URL", + url: { + url: offUrl + }, + params: {"from":"file"}, + folder_type: "DOWNLOAD" + } + } + GM_xmlhttpRequest({ + method: 'POST', + url: 'https://api-drive.mypikpak.com/drive/v1/files', + data: JSON.stringify(postData), + headers: { + "Content-Type": "application/json; charset=utf-8", + authorization: info.loginInfo.token_type + ' ' + info.loginInfo.access_token, + "X-Captcha-Token": info.captchaData.captcha_token + }, + onload: (res) => { + if(res.status === 200) { + GM_notification("Task OK"); + } else if(res.status === 401) { + info.loginInfo=null; + GM_setValue("pikpakUserInfo", info); + const msg = JSON.parse(res.responseText).error_description; + alert(msg); + } else if(res.status === 400) { + const msg = JSON.parse(res.responseText).error_description; + alert(msg); + } else if(res.status === 403) { + const msg = JSON.parse(res.responseText).error_description; + alert(msg); + } + }, + onerror: (e) => { + GM_notification("Error: " + (e.statusText || e.error)); + }, + ontimeout: (e) => { + GM_notification("Error: " + (e.statusText || e.error)); + } + }) + }; + device_id = CryptoJS.MD5(`${info.userName}${info.userPass}`).toString(CryptoJS.enc.Hex); + (async () => { + if (!info.captchaData || info.captchaData.expires < new Date().getTime()) { + let captchaData = await captchaInit(); + info.captchaData = captchaData; + if (!info.captchaData.expires && info.captchaData.expires_in) { + info.captchaData.expires = new Date().getTime() + 1000 * info.captchaData.expires_in; + } + GM_setValue("pikpakUserInfo", info); + } + if (!info.loginInfo || info.loginInfo.expires < new Date().getTime()) { + let data = { + "client_id": CLIENT_ID, + "client_secret": CLIENT_SECRET, + "password": info.userPass, + "username": info.userName, + "captcha_token": info.captchaData.captcha_token, + } + GM_xmlhttpRequest({ + method: 'POST', + url: 'https://user.mypikpak.com/v1/auth/signin', + data: JSON.stringify(data), + headers: { + 'user-agent': 'accessmode/ devicename/Netease_Mumu appname/android-com.pikcloud.pikpak cmd/login appid/ action_type/ clientid/YNxT9w7GMdWvEOKa deviceid/56e000d71f4660700ca974f2305171c5 refresh_token/ grant_type/ networktype/WIFI devicemodel/MuMu accesstype/ sessionid/ osversion/6.0.1 datetime/1636364470779 sdkversion/1.0.1.101600 protocolversion/200 clientversion/ providername/NONE clientip/ session_origin/ devicesign/div101.56e000d71f4660700ca974f2305171c5b94c3d4196a9dd74e49d7710a7af873d platformversion/10 usrno/null' + }, + onload: (res) => { + if (res.status === 200) { + info.loginInfo = JSON.parse(res.responseText); + if (!info.loginInfo.expires && info.loginInfo.expires_in) { + info.loginInfo.expires = new Date().getTime() + 1000 * info.loginInfo.expires_in; + } + GM_setValue("pikpakUserInfo", info); + postUrl(); + } else if (res.status === 401) { + GM_setValue("pikpakUserInfo",""); + const msg = JSON.parse(res.responseText).error_description; + alert(msg); + } else if (res.status === 400) { + GM_setValue("pikpakUserInfo",""); + const msg = JSON.parse(res.responseText).error_description; + alert(msg); + } else if (res.status === 403) { + GM_setValue("pikpakUserInfo",""); + const msg = JSON.parse(res.responseText).error_description; + alert(msg); + } + }, + onerror: (e) => { + GM_notification("Error: " + (e.statusText || e.error)); + }, + ontimeout: (e) => { + GM_notification("Error: " + (e.statusText || e.error)); + } + }) + } else { + postUrl(); + } + })(); + return false; + }, + bgImg: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAYFBMVEUAAAArbP5MdNFMdNIrbP4sbP1QdctQdcwvbv////8dYf8sbP9smP/09/8qaf/V4f8iZf/u8/+lwP+duv+UtP+PsP9hkP92n/9nlP/K2v/F1v+7z/+Ytv9Wif9Aef91nv9e7pgKAAAACHRSTlMA+puT/PWHhQBB7XEAAACQSURBVBjTTY8JCsQwCEWdrjFm37p37n/LMdAJfSTgf4IoAPQf8fDpgek4N9NxnwQZJx0/w+UMNd/XV6nluqsBQbRp79Xqvd7ICBCuaHuElMJhdXEspMKGko/YA2LYXyKuiGt8Ca3rfwm052nbjILV1IyFBZFZck4xppwXQ8Srk2wQzXzcIBpDB8w0/vM4AfwACl4LKjajMX0AAAAASUVORK5CYII=" + }; +})(); \ No newline at end of file diff --git a/Easy offline/Easy offline.user.js b/Easy offline/Easy offline.user.js index fd26c8bc42e..a95eadbffb3 100644 --- a/Easy offline/Easy offline.user.js +++ b/Easy offline/Easy offline.user.js @@ -7,7 +7,7 @@ // @description:zh-TW 一鍵離綫下載 - 一鍵自動將磁鏈、bt種子或其他下載資源離綫下載至網盤 // @namespace https://github.com/hoothin/UserScripts/tree/master/Easy%20offline // @require http://code.jquery.com/jquery-1.7.2.min.js -// @version 1.9.39.3 +// @version 1.9.41 // @author Hoothin // @icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAAQlBMVEUAAAD///////////////////////////////////////////////////////////////////////////////////8IX9KGAAAAFXRSTlMAwT7hFahN0LZWJgqIavB7YJuRdDPJsaCPAAAA6ElEQVQ4y8WRW5aEIAxEDUGgAQUftf+tjgYOjcPMb3d96Im5pkIxfVgmOuY5mX/afkYVqb/6EXDGh+CNA7axvwOvZrUiDfalX6UY5y+AkZ687Ut9WNgw9SLYQ3cDYfNz4kIAq2Z/wYN0AiSRQN16iroMXnD3K2F+f1oBLK2ckeWpmjFEsc2Tfxn6ndUBLGgjNVgAX8oNa56AO8dKeAEccnW89ruB6bQVWGTL2IcmQJOTdXSdOAIRrMtxsekR8AQ5XyHARLTrAhi6xH0iYWfcOguQpeAtPJJXSvlqEdSl4XaGHb4HEE0f1w+Jcw2XCZjSwgAAAABJRU5ErkJggg== // @match *://*/* @@ -386,132 +386,6 @@ }, bgImg:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAA9lBMVEUAAACgoqOipKUAAAC4ubq1traXl5jX19g9PT4GBga2t7ixsrOur7Cmp6jMzM1+f39ZWVpnZ2eChIXMzc3BwcKvsrLGxsacnZ3f399zdHS9vr61trZZW1upq6vIysq7vb2nqKliZGTS09O6vLzg4OC2uLhQUVHi4uK+v79OTk4hISHT1NQZGRnf4OCPkpKsra3KysxmZ2d+f3/y8vOUlZW+vr+2tridnp/Z2dmAgYJ4enptbm5YWVn39/fv7/DDw8Td3d7U1dXU1NTOztC4ubuoqamlpaWcnJyYmJp6fHxwcXFTVVX29/bHyMnHx8e3t7qgoaGHiYm1AxJpAAAAL3RSTlMAHhgF4NbW2jQU4uDg3sybVDUkHhcF6Ojk5ODc2dfJycPDra17ezkuLiUlIRUREf6sWL0AAAC0SURBVBjTjY9HEoJAAAQXVwVzAMw5Z5YMgoBizv7/M7JwoLw5t+lD1wzAYVcEPaeXLAgyHvTazTpJtvrDCe5M1nUReiiK/ERZxgNEVLYdy1GFz1uuET54IfGucTq/5qIYRGIKEjcaJ3ggFsEgrp/tnSwZJi/EMSDSqqQeJeNmXk+pwLFHlrg9CPzl16H/7ygmQ0eyCACkMuGODAUBTORzHbJSKlcb3Vw+AfE9uJgWCiNq5rcvfNwgjdumYdQAAAAASUVORK5CYII=" }, - PikPak:{ - regex:/mypikpak\.com/, - url:"http://user.mypikpak.com/", - bgColor:"2265ff", - noTxt:true, - linkRegExp: /^magnet:\?xt|^PikPak:\/\/|\.(torrent|mp4|mp3|rar|7z|zip|rmvb|mkv|avi|iso)$/i, - directUrl:function(offUrl){ - //此段代码引用自 mumuchenchen 大佬的 PikPak 保存助手 https://greasyfork.org/scripts/435219 - //mumuchenchen 的第三方 Pikpak 网页客户端 推荐大家前往 fork https://github.com/mumuchenchen/pikpak - storage.getItem("pikpakUserInfo",info=>{ - if(!info){ - let userName=prompt(i18n("userName")); - if(!userName)return; - let userPass=prompt(i18n("userPass")); - if(!userPass)return; - info={userName:userName,userPass:userPass}; - storage.setItem("pikpakUserInfo",info); - } - var postUrl=()=>{ - let postData; - if(offUrl.indexOf('PikPak://') === 0) { - const urlData = offUrl.substring(9).split('|') - postData = { - kind: "drive#file", - name: urlData[0], - size: urlData[1], - hash: urlData[2], - upload_type: "UPLOAD_TYPE_RESUMABLE", - objProvider: { - provider: "UPLOAD_TYPE_UNKNOWN" - } - } - } else { - postData = { - kind: "drive#file", - name: "", - upload_type: "UPLOAD_TYPE_URL", - url: { - url: offUrl - }, - params: {"from":"file"}, - folder_type: "DOWNLOAD" - } - } - _GM_xmlhttpRequest({ - method: 'POST', - url: 'https://api-drive.mypikpak.com/drive/v1/files', - data: JSON.stringify(postData), - headers: { - authorization: info.loginInfo.token_type + ' ' + info.loginInfo.access_token - }, - onload: (res) => { - if(res.status === 200) { - _GM_notification("Task OK"); - } else if(res.status === 401) { - info.loginInfo=null; - storage.setItem("pikpakUserInfo",info); - const msg = JSON.parse(res.responseText).error_description; - alert(msg); - } else if(res.status === 400) { - const msg = JSON.parse(res.responseText).error_description; - alert(msg); - } else if(res.status === 403) { - const msg = JSON.parse(res.responseText).error_description; - alert(msg); - } - }, - onerror: (e) => { - _GM_notification(i18n("postError") + (e.statusText||e.error)); - }, - ontimeout: (e) => { - _GM_notification(i18n("postError") + (e.statusText||e.error)); - } - }) - }; - if(!info.loginInfo || info.loginInfo.expires < new Date().getTime()){ - _GM_xmlhttpRequest({ - method: 'POST', - url: 'https://user.mypikpak.com/v1/auth/token', - data: JSON.stringify({ - "grant_type": "password", - "client_id": "YNxT9w7GMdWvEOKa", - "client_secret": "dbw2OtmVEeuUvIptb1Coyg", - "password": info.userPass, - "username": info.userName - }), - headers: { - 'user-agent': 'accessmode/ devicename/Netease_Mumu appname/android-com.pikcloud.pikpak cmd/login appid/ action_type/ clientid/YNxT9w7GMdWvEOKa deviceid/56e000d71f4660700ca974f2305171c5 refresh_token/ grant_type/ networktype/WIFI devicemodel/MuMu accesstype/ sessionid/ osversion/6.0.1 datetime/1636364470779 sdkversion/1.0.1.101600 protocolversion/200 clientversion/ providername/NONE clientip/ session_origin/ devicesign/div101.56e000d71f4660700ca974f2305171c5b94c3d4196a9dd74e49d7710a7af873d platformversion/10 usrno/null' - }, - onload: (res) => { - if(res.status === 200) { - info.loginInfo=JSON.parse(res.responseText); - if(!info.loginInfo.expires && info.loginInfo.expires_in){ - info.loginInfo.expires = new Date().getTime() + 1000 * info.loginInfo.expires_in; - } - storage.setItem("pikpakUserInfo",info); - postUrl(); - } else if(res.status === 401) { - storage.setItem("pikpakUserInfo",""); - const msg = JSON.parse(res.responseText).error_description; - alert(msg); - } else if(res.status === 400) { - storage.setItem("pikpakUserInfo",""); - const msg = JSON.parse(res.responseText).error_description; - alert(msg); - } else if(res.status === 403) { - storage.setItem("pikpakUserInfo",""); - const msg = JSON.parse(res.responseText).error_description; - alert(msg); - } - }, - onerror: (e) => { - _GM_notification(i18n("postError") + (e.statusText||e.error)); - }, - ontimeout: (e) => { - _GM_notification(i18n("postError") + (e.statusText||e.error)); - } - }) - }else{ - postUrl(); - } - }); - return false; - }, - bgImg:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAYFBMVEUAAAArbP5MdNFMdNIrbP4sbP1QdctQdcwvbv////8dYf8sbP9smP/09/8qaf/V4f8iZf/u8/+lwP+duv+UtP+PsP9hkP92n/9nlP/K2v/F1v+7z/+Ytv9Wif9Aef91nv9e7pgKAAAACHRSTlMA+puT/PWHhQBB7XEAAACQSURBVBjTTY8JCsQwCEWdrjFm37p37n/LMdAJfSTgf4IoAPQf8fDpgek4N9NxnwQZJx0/w+UMNd/XV6nluqsBQbRp79Xqvd7ICBCuaHuElMJhdXEspMKGko/YA2LYXyKuiGt8Ca3rfwm052nbjILV1IyFBZFZck4xppwXQ8Srk2wQzXzcIBpDB8w0/vM4AfwACl4LKjajMX0AAAAASUVORK5CYII=" - }, putio:{ regex:/app\.put\.io/, url:"https://app.put.io/files", @@ -554,190 +428,190 @@ var disableUrl=[".torrentkitty.","bt.box.n0808.com"]; var manageLinksLang={}; var lang = navigator.appName=="Netscape"?navigator.language:navigator.userLanguage; + var config={}; + switch (lang){ + case "zh-CN": + case "zh-SG": + config={ + configure:"全载设置", + yyw:"115网盘", + baidu:"百度网盘", + furk:"Furk网盘", + seedr:"Seedr网盘", + pcloud:"Pcloud网盘", + xunlei:"迅雷离线", + xunleipan:"迅雷网盘", + xiaomi:"小米路由器", + weiyun:"腾讯微云", + bitqiu:"比特球", + apiv:"九秒云播", + torrent:"Itorrents种子下载", + btcache:"Btcache.me种子下载", + enable:"启用", + disable:"禁用", + addIcon:"添加站点", + settingTitle:"全载", + urlRegexpTips:"自定义需要启用一键下载的链接正则,一行一条", + disableOnSite:"已于此站点禁用,点击启用", + bdPathTips:"不需要加'我的网盘/全部文件'", + bdPathTitle:"度盘存储路径:", + settingMouseOver:"仅当鼠标经过时显示图标", + settingBtn:"设置", + allDisableError:"不能全部禁用!", + siteRuleSetOK:"设置成功,刷新生效", + setOK:"设置成功", + regExpError:"含有无效正则,请重新输入", + addSiteRuleTitle:"自定义新增图标规则,一行一条", + siteRulePlaceholder:"站点 @@ 站名 @@ 下载链接正则 @@ 图标base64 @@ 图标背景颜色 @@ 是否隐藏图标\n\n@@ 分隔,目标站点中用 $url 代替目标链接,$hash 代表目标磁链的 hash 值,${reg}用正则提取,$text代表链接文本,$title代表链接title\n\n可用//注释规则\n\n例如:http://192.168.2.1/d2r?u=$url@@路由器下载\nhttp://xxx.com/magnet/$hash@@磁链下载@@^magnet@@data:image/png;base64,AAA@@ffffff", + inputLink:"输入需要离线下载的链接:", + importOrNot:"是否导入规则?", + importCustomAlert:"点击确定追加规则,点击取消覆盖规则", + importOver:"规则导入完毕!", + postOver:"发送成功,返回消息:", + copyOver:"复制成功!", + postError:"发送失败,错误内容:", + importCustomSame:"存在同名规则,是否覆盖?", + copyLinks:"嗅探下载资源", + noLinks:"当前页面没有资源!", + userName:"请输入用户账号", + userPass:"请输入用户密码", + seekKey:"嗅探快捷键:" + }; + manageLinksLang={ + copyAll:"全部复制", + copySel:"复制选中", + addTips:"%i代表递增 %n代表文件名", + sortByName:"按文件名排序", + sortByUrl:"按网址排序", + sortByType:"按扩展名排序", + preHolder:"批量前缀", + nextHolder:"批量后缀", + closeBtn:"关闭", + typeHead:"类型:" + }; + break; + case "zh-TW": + case "zh-HK": + case "zh-MO": + config={ + configure:"全載設置", + yyw:"115網盤", + baidu:"百度網盤", + furk:"Furk網盤", + seedr:"Seedr網盤", + pcloud:"Pcloud網盤", + xunlei:"迅雷離線", + xunleipan:"迅雷網盤", + xiaomi:"小米路由器", + weiyun:"騰訊微雲", + bitqiu:"比特球", + apiv:"九秒雲播", + torrent:"Itorrents種子下載", + btcache:"Btcache.me種子下載", + enable:"啟用", + disable:"禁用", + addIcon:"添加站點", + settingTitle:"全載", + urlRegexpTips:"自定義需要啟用一鍵下載的連結正則,一行一條", + disableOnSite:"已於此站點禁用,點擊啟用", + bdPathTips:"不需要加'我的網盤/全部文件'", + bdPathTitle:"度盤存儲路徑:", + settingMouseOver:"僅當滑鼠經過時顯示圖標", + settingBtn:"設置", + allDisableError:"不能全部禁用!", + siteRuleSetOK:"設置成功,刷新生效", + setOK:"設置成功", + regExpError:"含有無效正則,請重新輸入", + addSiteRuleTitle:"自定義新增圖標規則,一行一條", + siteRulePlaceholder:"站點 @@ 站名 @@ 下載鏈接正則 @@ 圖標base64 @@ 圖標背景顏色 @@ 是否隱藏圖標\n\n@@ 分隔,目標站點中用 $url 代替目標連結,$hash 代表目標磁鏈的 hash 值,${reg}用正则提取,$text代表連結文本,$title代表連結title\n\n可用//注釋規則\n\n例如:http://192.168.2.1/d2r?u=$url@@路由器下載\nhttp://xxx.com/magnet/$hash@@磁鏈下載@@^magnet@@data:image/png;base64,AAA@@ffffff", + inputLink:"輸入需要離線下載的連結:", + importOrNot:"是否導入規則?", + importCustomAlert:"點擊確定追加規則,點擊取消覆蓋規則", + importOver:"規則導入完畢!", + postOver:"發送成功,返回消息:", + copyOver:"複製成功!", + postError:"發送失敗,錯誤内容:", + importCustomSame:"存在同名規則,是否覆蓋?", + copyLinks:"嗅探下載資源", + noLinks:"當前頁面沒有資源!", + userName:"請輸入用戶賬號", + userPass:"請輸入用戶密碼", + seekKey:"嗅探快捷鍵:" + }; + manageLinksLang={ + copyAll:"全部複製", + copySel:"複製選中", + addTips:"%i代表遞增 %n代表文件名", + sortByName:"按文件名排序", + sortByUrl:"按網址排序", + sortByType:"按擴展名排序", + preHolder:"批量前綴", + nextHolder:"批量後綴", + closeBtn:"關閉", + typeHead:"類型:" + }; + break; + default: + config={ + configure:"Easy-Offline Configure", + yyw:"115", + baidu:"BaiduPan", + furk:"Furk", + seedr:"Seedr", + pcloud:"Pcloud", + xunlei:"Xunlei", + xunleipan:"XunleiPan", + xiaomi:"MiWifi", + weiyun:"Weiyun", + bitqiu:"bitqiu", + apiv:"Apiv Online play", + torrent:"Torrent download in itorrent.org", + btcache:"Torrent download in btcache.me", + enable:"Enable ", + disable:"Disable ", + addIcon:"Add new site", + settingTitle: "Easy Offline", + urlRegexpTips: "Customize the Link Regexp, one per line", + disableOnSite: "Disabled currently, click to enable", + bdPathTips: "No need to add'/all files'", + bdPathTitle: "Path of BDpan:", + settingMouseOver: "Display the icon only when the mouse passes over", + settingBtn: "Save", + allDisableError: "Cannot disable all!", + siteRuleSetOK: "Set successfully, refresh takes effect", + setOK: "Set successfully", + regExpError: "Contains invalid regularity, please re-enter", + addSiteRuleTitle: "Customize new icon rules, one per line", + siteRulePlaceholder: "site @@ sitename @@ link regexp @@ icon base64 @@ icon background color @@ hide icon\n\nUse @@ to separated, use $url for the target Link, $hash for the hash of the target magnet link, ${reg} for regexp result on link, $text for link text, $title for link title\n\nUse // to comment rule\n\nFor example: http://192.168.2.1/d2r?u=$url@@MyRouter\nhttp://xxx.com/magnet/$hash@@MyMagnetLinkDownload@@^magnet@@data:image/png;base64,AAA@@ffffff", + inputLink: "Enter the link that needs to be downloaded with this:", + importOrNot:"Do you want to import rules?", + importCustomAlert:"Ok to add rule,Cancel to cover rule", + importOver:"Rules import over!", + postOver:"Post over, return: ", + copyOver:"Copy over!", + postError:"Fail in post, error: ", + importCustomSame:"Rule exists, overwritten?", + copyLinks:"Seek downloadable links", + noLinks:"No links!", + userName:"Input user name", + userPass:"Input user pass", + seekKey:"Seek key: " + }; + manageLinksLang={ + copyAll: "Copy all", + copySel: "Copy selected", + addTips: "%i means increment, %n means file name", + sortByName: "Sort by name", + sortByUrl: "Sort by URL", + sortByType: "Sort by type", + preHolder: "Batch Prefix", + nextHolder: "Batch Suffix", + closeBtn: "Close", + typeHead: "Type:" + }; + break; + } var i18n=(name)=>{ - var config={}; - switch (lang){ - case "zh-CN": - case "zh-SG": - config={ - configure:"全载设置", - yyw:"115网盘", - baidu:"百度网盘", - furk:"Furk网盘", - seedr:"Seedr网盘", - pcloud:"Pcloud网盘", - xunlei:"迅雷离线", - xunleipan:"迅雷网盘", - xiaomi:"小米路由器", - weiyun:"腾讯微云", - bitqiu:"比特球", - apiv:"九秒云播", - torrent:"Itorrents种子下载", - btcache:"Btcache.me种子下载", - enable:"启用", - disable:"禁用", - addIcon:"添加站点", - settingTitle:"全载", - urlRegexpTips:"自定义需要启用一键下载的链接正则,一行一条", - disableOnSite:"已于此站点禁用,点击启用", - bdPathTips:"不需要加'我的网盘/全部文件'", - bdPathTitle:"度盘存储路径:", - settingMouseOver:"仅当鼠标经过时显示图标", - settingBtn:"设置", - allDisableError:"不能全部禁用!", - siteRuleSetOK:"设置成功,刷新生效", - setOK:"设置成功", - regExpError:"含有无效正则,请重新输入", - addSiteRuleTitle:"自定义新增图标规则,一行一条", - siteRulePlaceholder:"站点 @@ 站名 @@ 下载链接正则 @@ 图标base64 @@ 图标背景颜色 @@ 是否隐藏图标\n\n@@ 分隔,目标站点中用 $url 代替目标链接,$hash 代表目标磁链的 hash 值,${reg}用正则提取,$text代表链接文本,$title代表链接title\n\n可用//注释规则\n\n例如:http://192.168.2.1/d2r?u=$url@@路由器下载\nhttp://xxx.com/magnet/$hash@@磁链下载@@^magnet@@data:image/png;base64,AAA@@ffffff", - inputLink:"输入需要离线下载的链接:", - importOrNot:"是否导入规则?", - importCustomAlert:"点击确定追加规则,点击取消覆盖规则", - importOver:"规则导入完毕!", - postOver:"发送成功,返回消息:", - copyOver:"复制成功!", - postError:"发送失败,错误内容:", - importCustomSame:"存在同名规则,是否覆盖?", - copyLinks:"嗅探下载资源", - noLinks:"当前页面没有资源!", - userName:"请输入用户账号", - userPass:"请输入用户密码", - seekKey:"嗅探快捷键:" - }; - manageLinksLang={ - copyAll:"全部复制", - copySel:"复制选中", - addTips:"%i代表递增 %n代表文件名", - sortByName:"按文件名排序", - sortByUrl:"按网址排序", - sortByType:"按扩展名排序", - preHolder:"批量前缀", - nextHolder:"批量后缀", - closeBtn:"关闭", - typeHead:"类型:" - }; - break; - case "zh-TW": - case "zh-HK": - case "zh-MO": - config={ - configure:"全載設置", - yyw:"115網盤", - baidu:"百度網盤", - furk:"Furk網盤", - seedr:"Seedr網盤", - pcloud:"Pcloud網盤", - xunlei:"迅雷離線", - xunleipan:"迅雷網盤", - xiaomi:"小米路由器", - weiyun:"騰訊微雲", - bitqiu:"比特球", - apiv:"九秒雲播", - torrent:"Itorrents種子下載", - btcache:"Btcache.me種子下載", - enable:"啟用", - disable:"禁用", - addIcon:"添加站點", - settingTitle:"全載", - urlRegexpTips:"自定義需要啟用一鍵下載的連結正則,一行一條", - disableOnSite:"已於此站點禁用,點擊啟用", - bdPathTips:"不需要加'我的網盤/全部文件'", - bdPathTitle:"度盤存儲路徑:", - settingMouseOver:"僅當滑鼠經過時顯示圖標", - settingBtn:"設置", - allDisableError:"不能全部禁用!", - siteRuleSetOK:"設置成功,刷新生效", - setOK:"設置成功", - regExpError:"含有無效正則,請重新輸入", - addSiteRuleTitle:"自定義新增圖標規則,一行一條", - siteRulePlaceholder:"站點 @@ 站名 @@ 下載鏈接正則 @@ 圖標base64 @@ 圖標背景顏色 @@ 是否隱藏圖標\n\n@@ 分隔,目標站點中用 $url 代替目標連結,$hash 代表目標磁鏈的 hash 值,${reg}用正则提取,$text代表連結文本,$title代表連結title\n\n可用//注釋規則\n\n例如:http://192.168.2.1/d2r?u=$url@@路由器下載\nhttp://xxx.com/magnet/$hash@@磁鏈下載@@^magnet@@data:image/png;base64,AAA@@ffffff", - inputLink:"輸入需要離線下載的連結:", - importOrNot:"是否導入規則?", - importCustomAlert:"點擊確定追加規則,點擊取消覆蓋規則", - importOver:"規則導入完畢!", - postOver:"發送成功,返回消息:", - copyOver:"複製成功!", - postError:"發送失敗,錯誤内容:", - importCustomSame:"存在同名規則,是否覆蓋?", - copyLinks:"嗅探下載資源", - noLinks:"當前頁面沒有資源!", - userName:"請輸入用戶賬號", - userPass:"請輸入用戶密碼", - seekKey:"嗅探快捷鍵:" - }; - manageLinksLang={ - copyAll:"全部複製", - copySel:"複製選中", - addTips:"%i代表遞增 %n代表文件名", - sortByName:"按文件名排序", - sortByUrl:"按網址排序", - sortByType:"按擴展名排序", - preHolder:"批量前綴", - nextHolder:"批量後綴", - closeBtn:"關閉", - typeHead:"類型:" - }; - break; - default: - config={ - configure:"Easy-Offline Configure", - yyw:"115", - baidu:"BaiduPan", - furk:"Furk", - seedr:"Seedr", - pcloud:"Pcloud", - xunlei:"Xunlei", - xunleipan:"XunleiPan", - xiaomi:"MiWifi", - weiyun:"Weiyun", - bitqiu:"bitqiu", - apiv:"Apiv Online play", - torrent:"Torrent download in itorrent.org", - btcache:"Torrent download in btcache.me", - enable:"Enable ", - disable:"Disable ", - addIcon:"Add new site", - settingTitle: "Easy Offline", - urlRegexpTips: "Customize the Link Regexp, one per line", - disableOnSite: "Disabled currently, click to enable", - bdPathTips: "No need to add'/all files'", - bdPathTitle: "Path of BDpan:", - settingMouseOver: "Display the icon only when the mouse passes over", - settingBtn: "Save", - allDisableError: "Cannot disable all!", - siteRuleSetOK: "Set successfully, refresh takes effect", - setOK: "Set successfully", - regExpError: "Contains invalid regularity, please re-enter", - addSiteRuleTitle: "Customize new icon rules, one per line", - siteRulePlaceholder: "site @@ sitename @@ link regexp @@ icon base64 @@ icon background color @@ hide icon\n\nUse @@ to separated, use $url for the target Link, $hash for the hash of the target magnet link, ${reg} for regexp result on link, $text for link text, $title for link title\n\nUse // to comment rule\n\nFor example: http://192.168.2.1/d2r?u=$url@@MyRouter\nhttp://xxx.com/magnet/$hash@@MyMagnetLinkDownload@@^magnet@@data:image/png;base64,AAA@@ffffff", - inputLink: "Enter the link that needs to be downloaded with this:", - importOrNot:"Do you want to import rules?", - importCustomAlert:"Ok to add rule,Cancel to cover rule", - importOver:"Rules import over!", - postOver:"Post over, return: ", - copyOver:"Copy over!", - postError:"Fail in post, error: ", - importCustomSame:"Rule exists, overwritten?", - copyLinks:"Seek downloadable links", - noLinks:"No links!", - userName:"Input user name", - userPass:"Input user pass", - seekKey:"Seek key: " - }; - manageLinksLang={ - copyAll: "Copy all", - copySel: "Copy selected", - addTips: "%i means increment, %n means file name", - sortByName: "Sort by name", - sortByUrl: "Sort by URL", - sortByType: "Sort by type", - preHolder: "Batch Prefix", - nextHolder: "Batch Suffix", - closeBtn: "Close", - typeHead: "Type:" - }; - break; - } return config[name]?config[name]:name; }; @@ -881,24 +755,29 @@ defaultReg=new RegExp(defaultReg, 'i'); addCustomSites(()=>{ storage.getItem("siteSort",v=>{ - siteSort=v; - if(!siteSort)siteSort=["baidu","yyw","furk","seedr"]; - siteSort.forEach(function(item) { - var siteConfig=sites[item]; - if(siteConfig){ - siteConfig.name=item; + setTimeout(() => { + if (_unsafeWindow.eoAddons) { + sites = Object.assign(sites, _unsafeWindow.eoAddons); + } + siteSort=v; + if(!siteSort)siteSort=["baidu","yyw","furk","seedr"]; + siteSort.forEach(function(item) { + var siteConfig=sites[item]; + if(siteConfig){ + siteConfig.name=item; + sitesArr.push(siteConfig); + } + }); + for(let siteName in sites){ + let hasSite=false; + siteSort.forEach(function(item){if(item==siteName)hasSite=true;}); + if(hasSite)continue; + var siteConfig=sites[siteName]; + siteConfig.name=siteName; sitesArr.push(siteConfig); } - }); - for(let siteName in sites){ - let hasSite=false; - siteSort.forEach(function(item){if(item==siteName)hasSite=true;}); - if(hasSite)continue; - var siteConfig=sites[siteName]; - siteConfig.name=siteName; - sitesArr.push(siteConfig); - } - pageRun(); + pageRun(); + }, 1); }); }); }); @@ -1330,12 +1209,13 @@ if(/^c:/.test(url)){ urlArr.push(url.replace(/^c:/i,"")); }else if(/^p:/.test(url)){ - url=url.match(/p:(.*?)\?(.*)/); + url=url.match(/p:(.*?)\?(.*?)(\$headers({.*}))?$/); if(!url)return; let postData=JSON.stringify(urlArgs(url[2])); + let headers = url[4] ? JSON.parse(url[4]) : null; url=url[1]; _GM_xmlhttpRequest({ - method: "POST", url: url, data: postData, + method: "POST", url: url, data: postData, headers: headers, onload: (d) => { _GM_notification(i18n("postOver")+d.statusText); }, @@ -1364,12 +1244,13 @@ _GM_setClipboard(url.replace(/^c:/i,"")); _GM_notification(i18n("copyOver")); }else if(/^p:/.test(url)){ - url=url.match(/p:(.*?)\?(.*)/); + url=url.match(/p:(.*?)\?(.*?)(\$headers({.*}))?$/); if(!url)return; let postData=JSON.stringify(urlArgs(url[2])); + let headers = url[4] ? JSON.parse(url[4]) : null; url=url[1]; _GM_xmlhttpRequest({ - method: "POST", url: url, data: postData, + method: "POST", url: url, data: postData, headers: headers, onload: (d) => { _GM_notification(i18n("postOver")+d.statusText); }, @@ -1541,7 +1422,7 @@ document.body.appendChild(configContent); configContent.innerHTML=`
- ${i18n("settingTitle")} +

${i18n("settingTitle")}

${i18n("urlRegexpTips")}
@@ -1622,9 +1503,6 @@ if(allHide){ alert(i18n("allDisableError")); return; - }else if(siteConfig.name==="PikPak"){ - storage.setItem("pikpakUserInfo",""); - alert("PikPak account has been cleared"); } } storage.setItem("eoHide"+siteConfig.name, !eoHide); @@ -1723,7 +1601,8 @@ if(!link){ if(targetA) link=targetA.href; else link=prompt(i18n("inputLink"),"magnet:?xt=urn:btih:"); - }else{ + } + if(link){ init(); showDiskIcons(link.trim(),mouseEve.pageY-10,mouseEve.pageX-10); } diff --git a/Easy offline/README.MD b/Easy offline/README.MD index 6a26351630d..a0e3ba53343 100644 --- a/Easy offline/README.MD +++ b/Easy offline/README.MD @@ -37,14 +37,14 @@ https://github.rc1844.workers.dev${https?://[^/]+(.*)}@@RC1844@@github\.com.*(re https://ghproxy.fsou.cc/$url@@Fsou@@github\.com.*(releases\/download|archive\/refs\/)@@@@ffff0f -### 自定義例子2 - Aria2下載 +### 自定義例子2 - Aria2 下載 同樣是點擊下方導入
 http://aria.hoothin.com/#!/new/$base64@@Aria2@@@@data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAABOFBMVEUAAADSVF7SVF7SVF7LVWDSVF7QVF/SVF7SVF7SVF7SVF7SVF7SVF7RVF7SVF7SVF7SVF7SVF7SVF7SVF7SVF7SVF7SVF5ma4Di4uLSVF7v7+9DQ0NvaX1+ZniUYXGtXGppan+cYG+TYXLs7OyyW2h4tsiVlJWxs7ylpaWgoKBwaX2JZHVRVFxNT1VNTU1KSkxGRkd0uMzKysp5tceHipjDV2JYWFrr5ufa2tvT09Pjycu9v8a5u8PCwsK+vr6rrbego6+Tp62pqamZnKmloaGjj5l5fY+MfY60gozDfIa3foJkaHzTX2hYW2i6UVluSEuK2/Pd3d7X0NLExcm1tbWRlKKbm5uohJCOjo6GhoqOeInPgIh0coV8fHx7e3vRbXbObXaNY3SgX25hYmRhYWHJVmGOTFGNTFENIl9FAAAAF3RSTlMAJNEM+vr1iQjpyFfr6pybmjLusJhyIzaw7jcAAAHlSURBVDjLfZNnU+NADIbXduyQBBLq2fK6JcQmF0gvtOOOztGv90Ln//8Ddm3txkNmeD54vNI7klYrkRFaYT6f0/Vcfr6gkXGUklH13HoQ1F2vapSUZ+6JbKbsmIzvR/zrlDPZibT/lerXTc4fuDJj6r6aCjKTq5gJZwDH+FvJzcj0U8to/A+M93hYnlIwv+qh6RhijkQMNakj66PhF8BBr3cAZwEa/GxcYMbB8284CT90whOZxMnwJKUyHvurG/thpxPub3wykXKR9c8QATZtu7YT9nZqlvVVhDA0Uqji4XDVtrdeM95a1uYhGqsFMi2usGfb9uJWrcb81toeGr1pknfxf8nmLFox79Do5smkKOFNWrAkipgkevCSINBRMJ5CCmSK7ZTg47ZMMSqyHwt+fOOCbl8WObrm0OKC4R0X7A5PxTVlo87pFy5oNrngLz0XjZKtXqH/uIBSLmjRhmw1KSaP1WIuIdiltCUfiyjJc7cp/bm2vt5qd7ufbylt43OPBoayqFEUNZtRZJ42KE0GBkeuwgUr7FIAl5cArHWNdjxyWmpomd+8AXh8ALjmNcuhTY/9AODiAsCXYy9RVN/hGRLuXVafWJz06nmAeLh6z5d3AMjAKCpkHG1hTp3V9Vl1biG1/k8fR16xKi9r1wAAAABJRU5ErkJggg==@@ff2a00
 
*之所以把Aria2做成自定義是因為每個人的Aria2UI網址都不一樣,用我的伺服器管理本地的Aria2服務需要允許Chrome訪問本地資源,訪問 chrome://flags/#block-insecure-private-network-requests 並關閉即可。不想關閉的話直接打開設置把上面的網址換成自己本地的即可,例如 127.0.0.1 -### 自定義例子3 - Post請求RPC遠程下載 +### 自定義例子3 - Post 請求 RPC 遠程下載
 p:http://192.168.32.1:6800/jsonrpc?id=$random&jsonrpc=2.0&method=aria2.addUri&params=["token:123456",["$url"]]@@Aria2RPC@@@@@@df2a00
 
@@ -68,6 +68,11 @@ https://translate.google.com/?client=gtx&dj=1&q=$text&sl=auto&tl=zh-CN&hl=zh-CN& $text{[^\w\-_\.~!\*'();:@&=\+\$,\/\?#\[\]%]}@@GetLink@@@@@@f9ff9f +### 自定義例子7 - Post 請求 OpenList(原AList)遠程下載 +
+p:https://alist.domain.com/api/fs/add_offline_download?path=/115网盘/OpList离线下载&tool=115%20Cloud&delete_policy=delete_on_upload_succeed&urls=["$url"]$headers{"Content-Type": "application/json","Authorization": "alist-50a563b4-and-more-token-chars", "Accept": "*/*", "Host": "alist.domain.com", "Connection": "keep-alive"}@@OpenList@@@@@@df2a11
+
+ ### Update - **`Alt + F9`** 自定義下載,選中文本超鏈則下載文本超鏈,鼠標指向鏈接則下載鏈接,沒有選中則彈框輸入鏈接下載 diff --git a/FlashViewer-HTML5 Video/README.md b/FlashViewer-HTML5 Video/README.md index f066f20599a..94771d645c5 100644 --- a/FlashViewer-HTML5 Video/README.md +++ b/FlashViewer-HTML5 Video/README.md @@ -1,4 +1,4 @@ -# [FlashViewer](https://github.com/hoothin/UserScripts/raw/master/FlashViewer-HTML5%20Video/flashViewer.user.js) +# [FlashViewer⬇️](https://hoothin.github.io/UserScripts/FlashViewer-HTML5%20Video/flashViewer.user.js) HTML5 視頻增強腳本 原作者 NLF diff --git a/FlashViewer-HTML5 Video/flashViewer.user.js b/FlashViewer-HTML5 Video/flashViewer.user.js index 36b2f4dd4e5..e3f508f5e90 100644 --- a/FlashViewer-HTML5 Video/flashViewer.user.js +++ b/FlashViewer-HTML5 Video/flashViewer.user.js @@ -2,9 +2,9 @@ // @name flashViewer // @author NLF & Hoothin // @description 围观Flash,增加 HTML5 视频速度与亮度调整 -// @version 1.2.1.8 +// @version 1.2.1.9 // @created 2013-12-27 -// @lastUpdated 2024-8-10 +// @lastUpdated 2025-9-24 // @grant none // @run-at document-start // @namespace http://userscripts.org/users/NLF @@ -1555,6 +1555,7 @@ minHeight: 150, scale: function (e) { + if (this.pinned || this.maximized) return; if (e.deltaY > 0) { this.zoomLevel += -0.1; if (this.zoomLevel > 3) this.zoomLevel = 1; @@ -1635,13 +1636,15 @@ var vNodeName = video.nodeName; // 如果是这些元素,那么pin的时候直接用fixed方式(这些元素随便调整position不会引发重载) - var fixedPin = /^(?:IFRAME|VIDEO|AUDIO)$/.test(vNodeName); + var fixedPin = /^(?:IFRAME|VIDEO|AUDIO|CANVAS)$/.test(vNodeName); this.fixedPin = fixedPin; video.fvPopVideo = true;// 标记弹出中。 this.zoomLevel = 1; video.addEventListener("wheel", this.scale.bind(this)); - video.addEventListener("mousedown", this.videoMouseDown.bind(this), true); + if (vNodeName === "VIDEO") { + video.addEventListener("mousedown", this.videoMouseDown.bind(this), true); + } // 很多网站加载flash为了兼容现代浏览器和ie,经常使用 object classid嵌套object或者embed的格式 var vPEIsObject; @@ -3091,7 +3094,7 @@ // 插入占位符 var pluginNS = plugin.nextSibling; - var pluginP = plugin.parentNode; + pluginP = plugin.parentNode; if (pluginNS) { pluginP.insertBefore(placeholder, pluginNS); } else { @@ -3620,7 +3623,7 @@ mouseDown = true; lastRate = target.playbackRate; speedUpTimer = setTimeout(() => { - target.playbackRate = 3; + target.playbackRate = 5; target.play(); }, 500); lastPos = e.clientX; @@ -3637,7 +3640,6 @@ mouseDown = false; }, true); target.addEventListener('mousemove', function (e) { - clearTimeout(speedUpTimer); if (!mouseDown) return; if (!mouseMoving) { if (Math.abs(e.clientX - lastPos) > 10) { @@ -3645,6 +3647,7 @@ } return; } + clearTimeout(speedUpTimer); target.playbackRate = lastRate; target.pause(); target.currentTime += (e.clientX - lastPos) / 5; @@ -3843,7 +3846,7 @@ } // 可弹出元素 - const availableNode = /^(?:OBJECT|EMBED|VIDEO|AUDIO|IFRAME)$/i; + const availableNode = /^(?:OBJECT|EMBED|VIDEO|AUDIO|IFRAME|CANVAS)$/i; if (!availableNode.test(tNName)) { target = null; if (document.elementsFromPoint) { @@ -3884,13 +3887,13 @@ }; }; }; + }; - // 如果flash太小,一般不是引用视频,不出现工具栏 - var cCRect = getContentClientRect(target); - if (!(cCRect.width >= prefs.floatBar.minSizeLimit.width && cCRect.height >= prefs.floatBar.minSizeLimit.height)) { - // console.log(cCRect); - return; - }; + // 如果flash太小,一般不是引用视频,不出现工具栏 + var cCRect = getContentClientRect(target); + if (!(cCRect.width >= prefs.floatBar.minSizeLimit.width && cCRect.height >= prefs.floatBar.minSizeLimit.height)) { + // console.log(cCRect); + return; }; diff --git a/Kill Baidu AD/Kill Baidu AD.user.js b/Kill Baidu AD/Kill Baidu AD.user.js index 22ae4c65596..565821eb870 100644 --- a/Kill Baidu AD/Kill Baidu AD.user.js +++ b/Kill Baidu AD/Kill Baidu AD.user.js @@ -4,7 +4,7 @@ // @name:zh-TW 百度廣告(首尾推廣及右側廣告)清理 // @name:en Kill Baidu AD // @namespace hoothin -// @version 1.23.10 +// @version 1.23.12 // @description 彻底清理百度搜索(www.baidu.com)结果首尾的推广广告、二次顽固广告、右侧广告,去除重定向,删除百家号 // @description:zh-CN 彻底清理百度搜索(www.baidu.com)结果首尾的推广广告、二次顽固广告、右侧广告,去除重定向,移除百家号 // @description:zh-TW 徹底清理百度搜索(www.baidu.com)結果首尾的推廣廣告、二次頑固廣告、右側廣告,去除重定向,刪除百家號 @@ -31,7 +31,11 @@ (function() { 'use strict'; - var MO = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver, killBaijiaType = 1, killRight, killRightStyle, killRightRegister, hidePicture, hidePictureStyle, hidePictureRegister, blackList; + var MO = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver, killBaijiaType = 1, killRight, killRightStyle, killRightRegister, hidePicture, keepBaijia, hidePictureStyle, hidePictureRegister, blackList; + killRight = !!GM_getValue("killRight"); + hidePicture = !!GM_getValue("hidePicture"); + keepBaijia = !!GM_getValue("keepBaijia"); + blackList = GM_getValue("blackList") || []; if (MO) { var observer = new MO(function(records) { records.map(function(record) { @@ -93,13 +97,13 @@ } if (!mu || mu === 'null') return; if (/^https:\/\/baijiahao\.baidu\.com/.test(mu)) { - item.remove(); + !keepBaijia && item.remove(); return; } else { let title = item.querySelector('[data-module="title"]'); let isBlack = checkBlackList(mu, title && title.innerText); if (isBlack) { - item.remove(); + item.classList.add("blocked"); return; } } @@ -107,19 +111,22 @@ function checkLeftItem(item) { let mu = item.getAttribute("mu"); - if (mu && mu !== 'null') { + if (mu && mu !== 'null' && mu.indexOf("http") == 0 && mu.indexOf("nourl") == -1 && item.getAttribute("tpl") != "short_video") { if (/^https:\/\/baijiahao\.baidu\.com/.test(mu)) { - item.remove(); + !keepBaijia && item.remove(); return; } else { let title = item.querySelector('h3'); let isBlack = checkBlackList(mu, title && title.innerText); if (isBlack) { - item.remove(); + item.classList.add("blocked"); return; } let link = item.querySelector("a[href*='www.baidu.com/link']"); - if (link) link.href = mu; + if (link) { + link.href = mu; + item.setAttribute("mu", ""); + } } } let s = item.getAttribute("style"); @@ -144,7 +151,7 @@ [].forEach.call(item.querySelectorAll("a>div>span+img"), function(img) { if (img && /^https?:\/\/pic\.rmb\.bdstatic\.com/.test(img.src)) { //checkBaijia(item); - item.remove(); + !keepBaijia && item.remove(); } }); } @@ -236,6 +243,14 @@ } function initCss() { killRightStyle && killRightStyle.parentNode && killRightStyle.parentNode.removeChild(killRightStyle); + GM_addStyle(` + body:not(.showBlocked) .blocked { + display: none!important; + } + body.showBlocked .blocked { + background: linen; + } + `); if (killRight) { killRightStyle = GM_addStyle(` #content_right,[tpl="recommend_list"],#rs_new { @@ -397,32 +412,34 @@ if (pattern === '') { return true; } - let match = pattern.match(/^(\*|[\w-]+):\/{2,3}(?:(\*|\*\.[^/*]+|[^/*]+)\/)?(.*)$/); - if (!match) return url.indexOf(pattern) !== -1; - const [, scheme, host, path] = match; - const urlScheme = url.split(':')[0]; - const urlParam = new URL(url); - if (scheme === '*' || urlScheme === scheme) { - if (host !== '*') { - const urlHost = urlParam.hostname; - if (host.startsWith('*')) { - const hostPattern = host.slice(2); - if (!urlHost.endsWith(hostPattern)) return false; - } else { - if (urlHost !== host) return false; + try { + let match = pattern.match(/^(\*|[\w-]+):\/{2,3}(?:(\*|\*\.[^/*]+|[^/*]+)\/)?(.*)$/); + if (!match) return url.indexOf(pattern) !== -1; + const [, scheme, host, path] = match; + const urlScheme = url.split(':')[0]; + const urlParam = new URL(url); + if (scheme === '*' || urlScheme === scheme) { + if (host !== '*') { + const urlHost = urlParam.hostname; + if (host.startsWith('*')) { + const hostPattern = host.slice(2); + if (!urlHost.endsWith(hostPattern)) return false; + } else { + if (urlHost !== host) return false; + } } + const urlPath = urlParam.pathname + urlParam.search; + const pathRegex = new RegExp(`^${path.replace(/([\.\?])/g, '\\$1').replace(/\*/g, '.*')}$`); + return pathRegex.test(urlPath); } - const urlPath = urlParam.pathname + urlParam.search; - const pathRegex = new RegExp(`^${path.replace(/([\.\?])/g, '\\$1').replace(/\*/g, '.*')}$`); - return pathRegex.test(urlPath); - } + } catch(e) {} return false; } function registerMenuCommand() { initCss(); if (window.top !== window.self) return; - hidePictureRegister = GM_registerMenuCommand(hidePicture ? "✅ 恢复图片与样式" : "❌ 隐藏图片并简化样式", () => { + hidePictureRegister = GM_registerMenuCommand(hidePicture ? "✅ 恢复图片视频与样式" : "❌ 隐藏图片视频并简化样式", () => { GM_unregisterMenuCommand(killRightRegister); GM_unregisterMenuCommand(hidePictureRegister); hidePicture = !hidePicture; @@ -440,9 +457,6 @@ function run() { try { - killRight = !!GM_getValue("killRight"); - hidePicture = !!GM_getValue("hidePicture"); - blackList = GM_getValue("blackList") || []; if (location.host === "greasyfork.org") { function initConfig() { let parent = document.querySelector('#additional-info'); @@ -467,6 +481,7 @@ }; let hidePictureInput = createCheckbox('隐藏图片并简化样式', hidePicture); let killRightInput = createCheckbox('隐藏右边栏并多列显示', killRight); + let keepBaijiaInput = createCheckbox('保留百家号', keepBaijia); let importInput = document.createElement('textarea'); importInput.placeholder = '订阅 uBlacklist 规则:如 https://git.io/ublacklist'; importInput.style.width = '100%'; @@ -491,8 +506,10 @@ saveBtn.addEventListener("click", function(e) { hidePicture = hidePictureInput.checked; killRight = killRightInput.checked; + keepBaijia = keepBaijiaInput.checked; GM_setValue("hidePicture", hidePicture); GM_setValue("killRight", killRight); + GM_setValue("keepBaijia", keepBaijia); if (importInput.value) { alert("读取规则中……"); let importUrls = importInput.value.trim().split("\n"); @@ -536,6 +553,10 @@ return; } registerMenuCommand(); + GM_registerMenuCommand("👁️ 检查屏蔽元素", () => { + alert(`屏蔽元素数量:${document.body.querySelectorAll(".blocked").length}`) + document.body.classList.toggle("showBlocked"); + }); GM_registerMenuCommand("🔧 打开设置页", () => { GM_openInTab("https://greasyfork.org/scripts/24192", {active: true}); }); diff --git a/Pagetual/README.md b/Pagetual/README.md index 5004a5955e2..40854710e73 100644 --- a/Pagetual/README.md +++ b/Pagetual/README.md @@ -1,8 +1,8 @@ -[☯️](https://greasyfork.org/scripts/438684 "Install from greasyfork")東方永頁機 [v.1.9.37.91](https://greasyfork.org/scripts/438684-pagetual/code/Pagetual.user.js "Latest version") +[☯️](https://greasyfork.org/scripts/438684 "Install from greasyfork")東方永頁機 [v.1.9.37.131](https://hoothin.github.io/UserScripts/Pagetual/pagetual.user.js "Latest version") == *Pagetual - Perpetual pages. Auto loading paginated web pages for 90% of all web sites !* -🔧CONFIGURATION PAGE🔧 +🔧CONFIGURATION PAGE

@@ -16,23 +16,21 @@ https://raw.githubusercontent.com/hoothin/UserScripts/master/Pagetual/pagetualRu
         Buy me a coffee if you get help💞
     
     
-        
PayPal
-
Ko-fi
-
愛發電
- donate - reward +
PayPal
+
Ko-fi
+
愛發電
- 💬Join our Discord + Join 💬Discord - 📧Send me an email + Follow 🕊️twitter - Made with ❤️ by Hoothin + Send 📧email - +
Made with ❤️ by Hoothin diff --git a/Pagetual/items_all.json b/Pagetual/items_all.json index 44e071ca04e..2b5769c0881 100644 --- a/Pagetual/items_all.json +++ b/Pagetual/items_all.json @@ -1,10 +1,39 @@ [ { - "resource_url": "http://wedata.net/items/86240", + "resource_url": "http://wedata.net/items/86244", + "data": { + "insertBefore": "", + "pageElement": "//div[starts-with(@id, 'zone-twilight')]//div[@class='zone__content']", + "nextLink": "//a[@rel='next']", + "url": "^https://www\\.huffpost\\.com/", + "exampleUrl": "https://www.huffpost.com/news/" + }, + "database_resource_url": "http://wedata.net/databases/AutoPagerize", + "created_by": "Griever3", + "name": "HuffPost", + "created_at": "2024-08-31T07:10:48+09:00", + "updated_at": "2024-08-31T07:10:48+09:00" +}, +{ + "resource_url": "http://wedata.net/items/86242", "data": { "insertBefore": "", + "pageElement": "//div[@class='sysItemList aa']/ul", + "nextLink": "//div[@class='sysPagination']/ul/li[last()]/a", + "url": "^https://mirai-dora-world-online\\.com/", + "exampleUrl": "https://mirai-dora-world-online.com/ic" + }, + "database_resource_url": "http://wedata.net/databases/AutoPagerize", + "created_by": "タックン君", + "name": "ドラえもん未来デパート オンライン", + "created_at": "2024-08-27T18:01:20+09:00", + "updated_at": "2024-08-27T18:01:20+09:00" +}, +{ + "resource_url": "http://wedata.net/items/86240", + "data": { "pageElement": "//div[@class='act-video-list']", - "nextLink": "//div[@class='pagination']/b/a[last()][@title='']\r\n", + "nextLink": "//div[@class='pagination']/b/a[text()='次へ']\r\n", "url": "^https://www.minnano-av\\.com/", "exampleUrl": "https://www.minnano-av.com/actress218689.html" }, @@ -12,7 +41,7 @@ "created_by": "blekai", "name": "みんなのAV.com", "created_at": "2024-08-04T09:53:36+09:00", - "updated_at": "2024-08-04T09:53:36+09:00" + "updated_at": "2024-08-18T14:37:33+09:00" }, { "resource_url": "http://wedata.net/items/86239", @@ -4060,33 +4089,32 @@ "updated_at": "2022-01-24T19:38:36+09:00" }, { + "resource_url": "http://wedata.net/items/85824", "data": { - "insertBefore": "", "pageElement": "//div[@class=\"p-body-pageContent\"]//article[contains(concat(\" \", normalize-space(@class), \" \"), \" message \")]", "nextLink": "//link[@rel=\"next\"]", - "url": "^https?://www\\.racedepartment\\.com/threads/?", + "url": "^https?://www\\.(racedepartment\\.com|overtake\\.gg)/threads/?", "exampleUrl": "https://www.racedepartment.com/threads/assetto-corsa-latest-news-discussion.44395/" }, "database_resource_url": "http://wedata.net/databases/AutoPagerize", "created_by": "awoifajwojfiawf", - "resource_url": "http://wedata.net/items/85824", - "name": "RaceDepartment Forums", + "name": "OverTake (Formerly RaceDepartment) Forums", "created_at": "2022-01-23T20:29:59+09:00", - "updated_at": "2022-01-23T20:29:59+09:00" + "updated_at": "2024-08-19T05:05:04+09:00" }, { "resource_url": "http://wedata.net/items/85823", "data": { "pageElement": "descendant::*[./*[@data-author]][1]/*[@data-author]", "nextLink": "//link[@rel=\"next\"]", - "url": "^https?://www\\.racedepartment\\.com/", + "url": "^https?://www\\.(racedepartment\\.com|overtake\\.gg)/", "exampleUrl": "https://www.racedepartment.com/downloads/categories/ac-tracks.8/\r\nhttps://www.racedepartment.com/search/15502838/?q=test&o=relevance\r\nhttps://www.racedepartment.com/\r\nhttps://www.racedepartment.com/whats-new/media/1019969/\r\nhttps://www.racedepartment.com/store/categories/fanatec.2/\r\n" }, "database_resource_url": "http://wedata.net/databases/AutoPagerize", "created_by": "awoifajwojfiawf", - "name": "RaceDepartment", + "name": "OverTake (Formerly RaceDepartment)", "created_at": "2022-01-23T20:15:46+09:00", - "updated_at": "2022-01-23T20:40:55+09:00" + "updated_at": "2024-08-19T05:04:54+09:00" }, { "resource_url": "http://wedata.net/items/85822", @@ -5801,17 +5829,17 @@ { "resource_url": "http://wedata.net/items/85609", "data": { - "insertBefore": "id('entry')/div[div[@class='pager']]", "pageElement": "id('entry')/div[(@class='block' and not(.//p[@class='hdg'])) or .//div[@class='thumb']]", + "insertBefore": "id('entry')/div[div[@class='pager']]", "nextLink": "//div[@class='pager']//a[@class='btn' and span/i[contains(concat(' ', @class, ' '), ' fa-arrow-right ')]]", - "url": "^https://www.chunichi.co.jp/article/.+?", - "exampleUrl": "" + "url": "^https://www\\.chunichi\\.co\\.jp/article/\\d+", + "exampleUrl": "https://www.chunichi.co.jp/article/947611/1" }, "database_resource_url": "http://wedata.net/databases/AutoPagerize", "created_by": "htsign00", "name": "中日新聞", "created_at": "2021-02-13T15:46:27+09:00", - "updated_at": "2021-02-13T15:46:27+09:00" + "updated_at": "2024-08-25T08:37:46+09:00" }, { "resource_url": "http://wedata.net/items/85606", @@ -12030,20 +12058,6 @@ }, "created_at": "2018-11-20T23:05:03+09:00" }, -{ - "name": "東京2020特集 - スポーツナビ", - "data": { - "url": "^https://2020\\.yahoo\\.co\\.jp/column/", - "pageElement": "//section[@class=\"article__body\"]", - "exampleUrl": "https://2020.yahoo.co.jp/column/detail/201810250001-spnavi/", - "nextLink": "//a[span/text()=\"次へ\"]" - }, - "database_resource_url": "http://wedata.net/databases/AutoPagerize", - "created_by": "jpmyke", - "resource_url": "http://wedata.net/items/82021", - "created_at": "2018-11-16T14:01:22+09:00", - "updated_at": "2020-04-04T12:21:03+09:00" -}, { "resource_url": "http://wedata.net/items/82020", "name": "Us Weekly", @@ -14470,16 +14484,16 @@ { "resource_url": "http://wedata.net/items/81579", "data": { - "pageElement": "//article/section/div[2]", + "pageElement": "//article/section/div[contains(@class, 'kijiwrap')]", "nextLink": "//link[@rel=\"next\"]", "url": "^https?://kinmaweb\\.jp/archives/", - "exampleUrl": "https://kinmaweb.jp/archives/70121" + "exampleUrl": "https://kinmaweb.jp/archives/70121 https://kinmaweb.jp/archives/70121/2" }, "database_resource_url": "http://wedata.net/databases/AutoPagerize", "created_by": "jigendaddy_be", "name": "キンマweb", "created_at": "2017-09-30T13:23:47+09:00", - "updated_at": "2022-01-01T17:05:39+09:00" + "updated_at": "2024-08-18T08:03:14+09:00" }, { "resource_url": "http://wedata.net/items/81578", @@ -16067,7 +16081,7 @@ "created_by": "hatenaZZZ", "name": "nikkansports", "created_at": "2017-02-21T19:35:57+09:00", - "updated_at": "2022-02-14T21:50:28+09:00" + "updated_at": "2024-08-27T07:13:41+09:00" }, { "resource_url": "http://wedata.net/items/81207", @@ -26220,14 +26234,14 @@ "pageElement": "//div[starts-with(@id, 'zone-twilight')]//div[@class='zone__content']", "comment": "記事の取りこぼし修正。記事に css: order があるため zone__content を取得。", "nextLink": "//a[@rel='next']", - "url": "^https?://www\\.huffingtonpost\\.jp/", - "exampleUrl": "https://www.huffingtonpost.jp/news/" + "url": "^https?://www\\.huffingtonpost(\\.co)?\\.\\w{2}/", + "exampleUrl": "https://www.huffingtonpost.jp/news/\r\nhttps://www.huffingtonpost.co.uk/news/" }, "database_resource_url": "http://wedata.net/databases/AutoPagerize", "created_by": "jigendaddy_be", "name": "ハフィントンポスト", "created_at": "2014-08-02T12:33:40+09:00", - "updated_at": "2023-08-08T20:47:56+09:00" + "updated_at": "2024-08-25T08:34:17+09:00" }, { "resource_url": "http://wedata.net/items/74999", @@ -33353,18 +33367,18 @@ "created_at": "2012-08-02T02:15:15+09:00" }, { + "resource_url": "http://wedata.net/items/62561", "data": { - "pageElement": "//main//div[@class=\"l-artlst001\"]|//main//*[./div[@class=\"wrp lv2\"]][.//div[@class=\"thumb\"] and not(.//ul)]", + "pageElement": "//main//div[@class=\"cmp-thmb001 pt-20 pb-20\" or @class=\"l-artlst001\"]", "nextLink": "descendant::li[contains(@class,\"is-active\")][1]/following-sibling::li[1]/a", - "url": "^https://(www\\.)?chunichi\\.co\\.jp/(chuspo|tags)/", - "exampleUrl": "https://www.chunichi.co.jp/tags/tag_shimenlink/ https://www.chunichi.co.jp/chuspo/dragons/draban/" + "url": "^https://www\\.chunichi\\.co\\.jp/", + "exampleUrl": "https://www.chunichi.co.jp/tags/tag_shimenlink/ https://www.chunichi.co.jp/chuspo/dragons/draban/\r\nhttps://www.chunichi.co.jp/tags/yourdigital/yourdigital_repo" }, "database_resource_url": "http://wedata.net/databases/AutoPagerize", "created_by": "jigendaddy_be", - "resource_url": "http://wedata.net/items/62561", "name": "中日スポーツ-日付別記事一覧系", "created_at": "2012-07-29T13:47:10+09:00", - "updated_at": "2021-02-18T10:42:29+09:00" + "updated_at": "2024-08-25T08:37:04+09:00" }, { "resource_url": "http://wedata.net/items/62559", @@ -48733,17 +48747,17 @@ }, { "resource_url": "http://wedata.net/items/26590", - "name": "写真素材 [フォトライブラリー]", - "created_by": "クリト", - "database_resource_url": "http://wedata.net/databases/AutoPagerize", - "updated_at": "2016-02-09T08:26:08+09:00", "data": { - "exampleUrl": "http://www.photolibrary.jp/search/?p=%B3%D8%B9%BB", - "url": "^https?://(?:www\\.)?photolibrary\\.jp/search/", - "pageElement": "//ul[@class='pList pListLarge']/li[.//@class='photo']", - "nextLink": "//span[@class='next']//a" + "pageElement": "//ul[@class='pList pListLarge']/li[.//*[contains(@class, 'photo')]]", + "nextLink": "//span[@class='next']//a", + "url": "^https?://(?:www\\.)?photolibrary\\.jp/", + "exampleUrl": "https://www.photolibrary.jp/search/?p=%B3%D8%B9%BB\r\nhttps://www.photolibrary.jp/newarrival/\r\nhttps://www.photolibrary.jp/cat/cooking_1.html" }, - "created_at": "2009-01-06T22:50:33+09:00" + "database_resource_url": "http://wedata.net/databases/AutoPagerize", + "created_by": "クリト", + "name": "写真素材 [フォトライブラリー]", + "created_at": "2009-01-06T22:50:33+09:00", + "updated_at": "2024-08-25T08:35:31+09:00" }, { "resource_url": "http://wedata.net/items/26587", diff --git a/Pagetual/pagetual.user.js b/Pagetual/pagetual.user.js index 3d17c09d098..ae4b3ad94f3 100644 --- a/Pagetual/pagetual.user.js +++ b/Pagetual/pagetual.user.js @@ -10,8 +10,28 @@ // @name:es Pagetual // @name:fr Pagetual // @name:it Pagetual +// @name:id Pagetual +// @name:th Pagetual +// @name:nb Pagetual +// @name:sv Pagetual +// @name:sr Pagetual +// @name:sk Pagetual +// @name:hu Pagetual +// @name:ro Pagetual +// @name:fi Pagetual +// @name:el Pagetual +// @name:eo Pagetual +// @name:bg Pagetual +// @name:cs Pagetual +// @name:vi Pagetual +// @name:pl Pagetual +// @name:uk Pagetual +// @name:tr Pagetual +// @name:nl Pagetual +// @name:da Pagetual +// @name:fr-CA Pagetual // @namespace hoothin -// @version 1.9.37.91 +// @version 1.9.37.132 // @description Perpetual pages - powerful auto-pager script. Auto fetching next paginated web pages and inserting into current page for infinite scroll. Support thousands of web sites without any rule. // @description:zh-CN 终极自动翻页 - 加载并拼接下一分页内容至当前页尾,智能适配任意网页 // @description:zh-TW 終極自動翻頁 - 加載並拼接下一分頁內容至當前頁尾,智能適配任意網頁 @@ -23,6 +43,26 @@ // @description:es Carga automática de las siguientes páginas web paginadas e inserción en la página actual. Admite miles de sitios web sin ninguna regla. // @description:fr Chargement automatique des pages Web paginées suivantes et insertion dans la page en cours. Prend en charge des milliers de sites Web sans aucune règle. // @description:it Caricamento automatico delle pagine Web impaginate successive e inserimento nella pagina corrente. Supporta migliaia di siti web senza alcuna regola. +// @description:id Pengambilan otomatis halaman web yang dipaginasi berikutnya dan penyisipan ke halaman saat ini untuk pengguliran tak terbatas. Mendukung ribuan situs web tanpa aturan apa pun. +// @description:th ดึงหน้าเว็บแบบแบ่งหน้าถัดไปโดยอัตโนมัติและแทรกลงในหน้าปัจจุบันเพื่อเลื่อนแบบไม่มีที่สิ้นสุด รองรับเว็บไซต์หลายพันแห่งโดยไม่มีกฎเกณฑ์ใดๆ +// @description:nb Henter automatisk neste paginerte nettsider og setter inn på gjeldende side for uendelig rulling. Støtt tusenvis av nettsider uten noen regel. +// @description:sv Hämtar automatiskt nästa paginerade webbsidor och infogar på aktuell sida för oändlig rullning. Stöd tusentals webbplatser utan några regler. +// @description:sr Аутоматско преузимање следећих пагинираних веб страница и уметање у тренутну страницу за бесконачно померање. Подржите хиљаде веб локација без икаквог правила. +// @description:sk Samodejno pridobivanje naslednjih paginiranih spletnih strani in vstavljanje v trenutno stran za neskončno drsenje. Podprite na tisoče spletnih mest brez pravil. +// @description:hu A következő oldalszámozott weboldalak automatikus lekérése és beszúrása az aktuális oldalra a végtelen görgetés érdekében. Több ezer webhely támogatása szabály nélkül. +// @description:ro Preluare automată a următoarelor pagini web paginate și inserare în pagina curentă pentru defilare infinită. Suportă mii de site-uri web fără nicio regulă. +// @description:fi Hakee automaattisesti seuraavat sivutetut verkkosivut ja lisäämällä nykyiselle sivulle loputonta vieritystä. Tukee tuhansia web-sivustoja ilman sääntöjä. +// @description:el Αυτόματη ανάκτηση επόμενων σελιδοποιημένων ιστοσελίδων και εισαγωγή στην τρέχουσα σελίδα για άπειρη κύλιση. Υποστηρίξτε χιλιάδες ιστοσελίδες χωρίς κανένα κανόνα. +// @description:eo Aŭtomate alportado de sekvaj paĝigitaj retpaĝoj kaj enmetado en nunan paĝon por senfina movo. Subtenu milojn da retejoj sen ajna regulo. +// @description:bg Автоматично извличане на следващите уеб страници с пагиниране и вмъкване в текущата страница за безкрайно превъртане. Поддържайте хиляди уеб сайтове без никакви правила. +// @description:cs Automatické načítání dalších stránkovaných webových stránek a vkládání do aktuální stránky pro nekonečné posouvání. Podporujte tisíce webových stránek bez jakýchkoli pravidel. +// @description:vi Tự động tìm các trang web được phân trang tiếp theo và chèn vào trang hiện tại để cuộn vô hạn. Hỗ trợ hàng ngàn trang web mà không cần bất kỳ quy tắc nào. +// @description:pl Automatyczne pobieranie kolejnych stron internetowych z podziałem na strony i wstawianie ich do bieżącej strony w celu nieskończonego przewijania. Obsługa tysięcy stron internetowych bez żadnej reguły. +// @description:uk Автоматичне отримання наступних веб-сторінок із розбивкою на сторінки та вставка на поточну сторінку для нескінченного прокручування. Підтримка тисяч веб-сайтів без будь-яких правил. +// @description:tr Sonraki sayfalı web sayfalarını otomatik olarak getirme ve sonsuz kaydırma için geçerli sayfaya ekleme. Hiçbir kural olmadan binlerce web sitesini destekleyin. +// @description:nl Automatisch ophalen van volgende gepagineerde webpagina's en invoegen in huidige pagina voor oneindig scrollen. Ondersteun duizenden websites zonder enige regel. +// @description:da Automatisk hentning af næste paginerede websider og indsættelse på nuværende side for uendelig rulning. Støt tusindvis af websteder uden nogen regler. +// @description:fr-CA Récupération automatique des pages Web paginées suivantes et insertion dans la page actuelle pour un défilement infini. Prise en charge de milliers de sites Web sans aucune règle. // @author hoothin // @license MPL-2.0 // @match *://*/* @@ -52,13 +92,12 @@ // @connect wedata.net // @connect githubusercontent.com // @connect ghproxy.com +// @connect ghp.ci // @connect hoothin.github.io // @run-at document-end // @connect * // @contributionURL https://ko-fi.com/hoothin // @contributionAmount 1 -// @downloadURL https://update.greasyfork.org/scripts/438684/Pagetual.user.js -// @updateURL https://update.greasyfork.org/scripts/438684/Pagetual.meta.js // ==/UserScript== (function() { @@ -68,6 +107,7 @@ [].forEach.call(document.querySelectorAll("video"), video => { video.removeAttribute && video.removeAttribute("autoplay"); video.pause && video.pause(); + video.muted = true; }); }, 1000); }; @@ -97,6 +137,9 @@ if (document.body && getComputedStyle(document.body).display === 'none') { document.body.style.display = 'block'; } + Element.prototype.scrollIntoView = function() { + console.log('ScrollIntoView blocked.'); + }; return; } @@ -113,20 +156,21 @@ } const noRuleTest = false; - const lang = navigator.appName === "Netscape" ? navigator.language : navigator.userLanguage; + var langName = navigator.appName === "Netscape" ? navigator.language : navigator.userLanguage; const langData = [ { // English translation update by github.com/https433, admin@abby0666.xyz. name: "English", match: ["en"], lang: { - enableDebug: "Enable debug output to console.", + enableDebug: "Enable debug output to console", updateNotification: "Notification after rules updated", - disable: "Temporarily disable.", - disableSite: "Toggle disabled state.", + disable: "Temporarily disable", + disableSite: "Toggle disabled state", disableSiteTips: "Disabled on this site.", enableSiteTips: "Enabled on this site.", - enable: "Enable automatic page turning.", + enable: "✅Enable automatic page turning", + tempActive: "Temporarily active", toTop: "Back to Top.", toBottom: "Go to Bottom.", current: "Current Page.", @@ -171,12 +215,12 @@ openInNewTab: "Open urls of additions in new tab", importSucc: "Import complete", import: "Import", - editCurrent: "Edit rule for current website.", + editCurrent: "Edit rule for current website", editBlacklist: "Edit the url blacklist, one entry per line, Supports [?,*] wildcarding.", upBtnImg: "Icon of back to top", downBtnImg: "Icon of go to footer", sideControllerIcon: "Icon of sidebar", - loadingTextTitle: "Loading.", + loadingTextTitle: "Loading", dbClick2StopCtrl: "Ctrl key", dbClick2StopAlt: "Alt key", dbClick2StopShift: "Shift key", @@ -185,7 +229,7 @@ pageElementCss: "Custom style for main page elements", customCss: "Custom complete css", firstAlert: "You have not imported the base rule, please select the appropriate rule to import", - picker: "Pagetual page element picker", + picker: "Pagetual element picker", closePicker: "Close Pagetual picker", pickerPlaceholder: "Element selector, (Advanced users only, leave blank otherwise)", pickerCheck: "Check selector and copy", @@ -219,8 +263,8 @@ errorWrongUrl: "Wrong url, Check again!", errorAlreadyExists: "A rule already exists!", settingsSaved: "The settings are saved, refresh to view", - iframe: "Forced split by iframe.", - dynamic: "Dynamic loading.", + iframe: "Forced split by iframe", + dynamic: "Dynamic loading", reloadPage: "Edit completed, reload now?", copied: "Copied", noValidContent: "No valid content detected, a Captcha may be present", @@ -239,10 +283,2738 @@ lastPageTips: "Show tips when reaching the last page" } }, + { + name: "한국어", + match: ["ko"], + lang: { + enableDebug: "콘솔에 디버그 출력 활성화", + updateNotification: "규칙 업데이트 후 알림", + disable: "일시적으로 비활성화", + disableSite: "비활성화 상태 전환", + disableSiteTips: "이 사이트에서 비활성화됨.", + enableSiteTips: "이 사이트에서 활성화됨.", + enable: "✅자동 페이지 넘김 활성화", + tempActive: "일시적으로 활성", + toTop: "맨 위로 이동.", + toBottom: "맨 아래로 이동.", + current: "현재 페이지.", + forceIframe: "다음 페이지 강제 결합", + cancelForceIframe: "강제 결합 취소", + configure: "Pagetual 설정", + firstUpdate: "기본 규칙 목록을 초기화하려면 여기를 클릭하세요", + update: "온라인 규칙 업데이트", + click2update: "URL에서 규칙을 지금 업데이트하려면 클릭하세요", + loadNow: "다음 페이지 자동 로드", + loadConfirm: "몇 페이지를 로드하시겠습니까? (0은 무한을 의미)", + noNext: "다음 링크를 찾을 수 없습니다. 새 규칙을 만들어 주세요", + passSec: "#t#초 전에 업데이트됨", + passMin: "#t#분 전에 업데이트됨", + passHour: "#t#시간 전에 업데이트됨", + passDay: "#t#일 전에 업데이트됨", + cantDel: "내장된 규칙은 삭제할 수 없습니다", + confirmDel: "이 규칙을 정말로 삭제하시겠습니까?", + updateSucc: "업데이트 성공", + beginUpdate: "업데이트를 시작합니다. 잠시만 기다려 주세요", + customUrls: "Pagetual 또는 AutoPagerize 규칙 URL 가져오기, 한 줄에 하나의 URL.", + customRules: "사용자 정의 규칙을 입력하세요. ✍️규칙 기여하기", + save: "저장", + loadingText: "로딩 중...", + opacity: "불투명도", + opacityPlaceholder: "0: 구분선 숨기기", + hideBar: "페이지 구분선 숨기기", + hideBarButNoStop: "숨기지만 중지하지 않음", + dbClick2Stop: "일시 중지하려면 빈 공간을 두 번 클릭하세요", + sortTitle: "정렬은 다음 규칙 업데이트 후에 적용됩니다", + autoRun: "자동 활성화 (블랙리스트 모드)", + autoLoadNum: "미리 로드할 페이지 수", + turnRate: "바닥글로부터 페이지 높이의 【X】배 미만일 때 다음 페이지로 넘기기", + inputPageNum: "이동할 페이지 번호를 입력하세요", + enableHistory: "페이지 넘김 후 방문 기록 저장", + enableHistoryAfterInsert: "페이지 결합 직후 방문 기록 저장, 그렇지 않으면 탐색 후 저장", + contentVisibility: "렌더링 성능 향상을 위해 content-visibility 자동 전환", + initRun: "페이지 열람 직후 자동 넘김 시작", + preload: "속도 향상을 위해 다음 페이지 미리 로드", + click2ImportRule: "기본 규칙 링크를 가져오려면 클릭하고 업데이트가 완료될 때까지 기다리세요: ", + forceAllBody: "페이지의 전체 본문을 결합하시겠습니까?", + openInNewTab: "추가된 URL을 새 탭에서 열기", + importSucc: "가져오기 완료", + import: "가져오기", + editCurrent: "현재 웹사이트 규칙 편집", + editBlacklist: "URL 블랙리스트 편집, 한 줄에 하나씩 입력, [?,*] 와일드카드 지원.", + upBtnImg: "맨 위로 가기 아이콘", + downBtnImg: "맨 아래로 가기 아이콘", + sideControllerIcon: "사이드바 아이콘", + loadingTextTitle: "로딩", + dbClick2StopCtrl: "Ctrl 키", + dbClick2StopAlt: "Alt 키", + dbClick2StopShift: "Shift 키", + dbClick2StopMeta: "Meta 키", + dbClick2StopKey: "단축키", + pageElementCss: "주요 페이지 요소에 대한 사용자 정의 스타일", + customCss: "사용자 정의 전체 CSS", + firstAlert: "기본 규칙을 가져오지 않았습니다. 가져올 적절한 규칙을 선택해주세요", + picker: "Pagetual 요소 선택기", + closePicker: "Pagetual 선택기 닫기", + pickerPlaceholder: "요소 선택기 (고급 사용자 전용, 그렇지 않으면 비워두세요)", + pickerCheck: "선택기 확인 및 복사", + switchSelector: "클릭하여 요소 전환", + gotoEdit: "현재 선택기로 규칙 편집하러 가기", + manualMode: "결합 비활성화, 오른쪽 화살표 키를 사용하여 수동으로 다음 페이지로 이동 (또는 'pagetual.next' 이벤트 전달)", + clickMode: "결합 비활성화, 페이지 끝까지 스크롤하면 다음 페이지 자동 클릭", + pageBarMenu: "페이지 바 중앙을 클릭하여 선택기 메뉴 열기", + nextSwitch: "다음 링크 전환", + arrowToScroll: "왼쪽 화살표를 눌러 뒤로 스크롤하고 오른쪽 화살표를 눌러 페이지 이동", + sideController: "사이드바에 페이징 제어 바 표시", + sideControllerScroll: "스크롤 시 표시/숨김", + sideControllerAlways: "항상 표시", + hideLoadingIcon: "로딩 애니메이션 숨기기", + hideBarArrow: "페이지 바 화살표 숨기기", + duplicate: "중복된 Pagetual이 설치되었습니다. 스크립트 관리자를 확인하세요!", + forceStateIframe: "전체 페이지를 iframe으로 삽입", + forceStateDynamic: "iframe을 통해 동적 콘텐츠 로드", + forceStateDisable: "이 사이트에서 페이지 넘김 비활성화", + autoScrollRate: "스크롤 속도 (1~1000)", + disableAutoScroll: "자동 스크롤 중지", + enableAutoScroll: "자동 스크롤 활성화", + toggleAutoScroll: "자동 스크롤 전환", + ruleRequest: "규칙 요청", + page: "페이지 ", + prevPage: "이전 페이지", + nextPage: "다음 페이지", + errorRulesMustBeArray: "규칙은 배열이어야 합니다!", + errorJson: "JSON 오류, 다시 확인해주세요!", + editSuccess: "성공적으로 편집되었습니다", + errorWrongUrl: "잘못된 URL, 다시 확인해주세요!", + errorAlreadyExists: "규칙이 이미 존재합니다!", + settingsSaved: "설정이 저장되었습니다. 확인하려면 새로고침하세요", + iframe: "iframe으로 강제 분할", + dynamic: "동적 로딩", + reloadPage: "편집 완료, 지금 새로고침하시겠습니까?", + copied: "복사됨", + noValidContent: "유효한 콘텐츠를 찾을 수 없습니다. 보안 문자(Captcha)가 있을 수 있습니다", + outOfDate: "스크립트가 오래되었습니다. 최신 버전으로 업데이트해주세요.", + hideBarTips: "페이지네이션 바 숨기기, 몰입형 경험 전환", + setConfigPage: "현재 페이지를 기본 설정 페이지로 지정", + wedata2github: "wedata 주소를 github 저장소의 미러 주소로 변경", + addOtherProp: "규칙 속성 추가", + addNextSelector: "선택기 콘텐츠를 nextLink로 추가", + addPageSelector: "선택기 콘텐츠를 pageElement로 추가", + propName: "규칙 속성 이름 입력", + propValue: "규칙 속성 값 입력", + customFirst: "로컬 사용자 정의 규칙 캐시 무시", + rulesExample: "규칙 예시", + lastPage: "마지막 페이지에 도달했습니다", + lastPageTips: "마지막 페이지 도달 시 팁 표시" + } + }, + { + name: "Deutsch", + match: ["de", "de-AT", "de-CH", "de-DE", "de-LI", "de-LU"], + lang: { + enableDebug: "Debug-Ausgabe in der Konsole aktivieren", + updateNotification: "Benachrichtigung nach Aktualisierung der Regeln", + disable: "Vorübergehend deaktivieren", + disableSite: "Deaktivierungszustand umschalten", + disableSiteTips: "Auf dieser Seite deaktiviert.", + enableSiteTips: "Auf dieser Seite aktiviert.", + enable: "✅Automatisches Blättern aktivieren", + tempActive: "Vorübergehend aktiv", + toTop: "Zurück nach oben.", + toBottom: "Nach unten gehen.", + current: "Aktuelle Seite.", + forceIframe: "Zwingen, die nächste Seite zu laden", + cancelForceIframe: "Zwangsöffnung abbrechen", + configure: "Pagetual konfigurieren", + firstUpdate: "Hier klicken, um die Standardregel-Liste zu initialisieren", + update: "Online-Regeln aktualisieren", + click2update: "Jetzt klicken, um Regeln von der URL zu aktualisieren", + loadNow: "Nächste Seite automatisch laden", + loadConfirm: "Wie viele Seiten möchten Sie laden? (0 bedeutet unendlich)", + noNext: "Keinen nächsten Link gefunden, bitte erstellen Sie eine neue Regel", + passSec: "Vor #t# Sekunden aktualisiert", + passMin: "Vor #t# Minuten aktualisiert", + passHour: "Vor #t# Stunden aktualisiert", + passDay: "Vor #t# Tagen aktualisiert", + cantDel: "Kann integrierte Regeln nicht löschen", + confirmDel: "Sind Sie sicher, dass Sie diese Regel löschen möchten?", + updateSucc: "Aktualisierung erfolgreich", + beginUpdate: "Aktualisierung beginnen, bitte einen Moment warten", + customUrls: "Pagetual oder AutoPagerize Regel-URL importieren, eine URL pro Zeile.", + customRules: "Benutzerdefinierte Regeln eingeben. ✍️Regeln beitragen", + save: "Speichern", + loadingText: "Shojo lädt jetzt...", + opacity: "Opazität", + opacityPlaceholder: "0: Platzhalter ausblenden", + hideBar: "Den Platzhalter für die Seitenanzahl ausblenden", + hideBarButNoStop: "Ausblenden, aber nicht stoppen", + dbClick2Stop: "Doppelklicken Sie auf den leeren Bereich, um zu pausieren", + sortTitle: "Die Sortierung wird nach der nächsten Regelaktualisierung wirksam", + autoRun: "Automatisch aktivieren (Blacklist-Modus)", + autoLoadNum: "Anzahl der vorzuladenden Seiten", + turnRate: "Blättern zur nächsten Seite, wenn sie weniger als 【X】 Mal die Seitenshöhe vom Fußbereich entfernt ist", + inputPageNum: "Seitenzahl eingeben, um zu springen", + enableHistory: "Browserverlauf nach dem Blättern aufzeichnen", + enableHistoryAfterInsert: "Browserverlauf sofort nach dem Einfügen aufzeichnen, andernfalls nach dem Browsen aufzeichnen", + contentVisibility: "Inhaltssichtbarkeit automatisch umschalten, um die Render-Leistung zu verbessern", + initRun: "Seiten sofort nach dem Öffnen blättern", + preload: "Nächste Seite vorladen, um zu beschleunigen", + click2ImportRule: "Klicken Sie, um den Basisregel-Link zu importieren, und warten Sie, bis die Aktualisierung abgeschlossen ist: ", + forceAllBody: "Gesamten Seiteninhalt als iframe einfügen?", + openInNewTab: "URLs der Ergänzungen in neuem Tab öffnen", + importSucc: "Import abgeschlossen", + import: "Importieren", + editCurrent: "Regel für die aktuelle Website bearbeiten", + editBlacklist: "Bearbeiten Sie die URL-Blacklist, ein Eintrag pro Zeile, unterstützt Wildcards [?,*].", + upBtnImg: "Symbol zum Zurück nach oben", + downBtnImg: "Symbol zum Gehen zum Fußbereich", + sideControllerIcon: "Symbol der Seitenleiste", + loadingTextTitle: "Laden", + dbClick2StopCtrl: "Strg-Taste", + dbClick2StopAlt: "Alt-Taste", + dbClick2StopShift: "Shift-Taste", + dbClick2StopMeta: "Meta-Taste", + dbClick2StopKey: "Kurzbefehl-Taste", + pageElementCss: "Benutzerdefinierter Stil für Hauptelemente der Seite", + customCss: "Benutzerdefiniertes vollständiges CSS", + firstAlert: "Sie haben die Basisregel nicht importiert, bitte wählen Sie die passende Regel zum Importieren aus", + picker: "Pagetual Elementauswahl", + closePicker: "Pagetual Picker schließen", + pickerPlaceholder: "Elementauswahl, (nur für Fortgeschrittene, andernfalls leer lassen)", + pickerCheck: "Wählen Sie den Selektor aus und kopieren", + switchSelector: "Klicken Sie, um das Element zu wechseln", + gotoEdit: "Gehe zur Regelbearbeitung mit dem aktuellen Selektor", + manualMode: "Splicing deaktivieren, manuell zur nächsten Seite mit der rechten Pfeiltaste weiterblättern (oder das Ereignis 'pagetual.next' auslösen)", + clickMode: "Splicing deaktivieren, automatisch zur nächsten Seite klicken, wenn das Ende der Seite erreicht ist", + pageBarMenu: "Klicken Sie auf die Mitte der Seitenleiste, um das Picker-Menü zu öffnen", + nextSwitch: "Nächsten Link wechseln", + arrowToScroll: "Drücken Sie die linke Pfeiltaste, um nach hinten zu scrollen, und die rechte Pfeiltaste, um zur nächsten Seite zu blättern", + sideController: "Die Steuerleiste für das Blättern in der Seitenleiste anzeigen", + sideControllerScroll: "Scroll-Umschaltung", + sideControllerAlways: "Immer anzeigen", + hideLoadingIcon: "Ladeanimation ausblenden", + hideBarArrow: "Pfeil für die Seitenleiste ausblenden", + duplicate: "Duplikat Pagetual wurde installiert, überprüfen Sie Ihren Skriptmanager!", + forceStateIframe: "Gesamte Seite als iframe einfügen", + forceStateDynamic: "Dynamische Inhalte über iframe laden", + forceStateDisable: "Blättern auf dieser Seite deaktivieren", + autoScrollRate: "Scrollgeschwindigkeit (1~1000)", + disableAutoScroll: "Auto-Scroll stoppen", + enableAutoScroll: "Auto-Scroll aktivieren", + toggleAutoScroll: "Auto-Scroll umschalten", + ruleRequest: "Regelanfrage", + page: "Seite ", + prevPage: "Vorherige Seite", + nextPage: "Nächste Seite", + errorRulesMustBeArray: "Regeln müssen ein Array sein!", + errorJson: "JSON-Fehler, bitte erneut überprüfen!", + editSuccess: "Erfolgreich bearbeitet", + errorWrongUrl: "Falsche URL, bitte erneut überprüfen!", + errorAlreadyExists: "Eine Regel existiert bereits!", + settingsSaved: "Die Einstellungen wurden gespeichert, bitte aktualisieren, um sie zu sehen", + iframe: "Zwangsaufteilung durch iframe", + dynamic: "Dynamisches Laden", + reloadPage: "Bearbeitung abgeschlossen, jetzt neu laden?", + copied: "Kopiert", + noValidContent: "Kein gültiger Inhalt erkannt, möglicherweise ist ein Captcha vorhanden", + outOfDate: "Das Skript ist veraltet, bitte auf die neueste Version aktualisieren.", + hideBarTips: "Die Seitenzahlenleiste ausblenden, um ein immersives Erlebnis zu ermöglichen", + setConfigPage: "Aktuelle Seite als Standardkonfigurationsseite festlegen", + wedata2github: "Die wedata-Adresse auf die Spiegeladresse im GitHub-Repository ändern", + addOtherProp: "Regelattribute hinzufügen", + addNextSelector: "Selector-Inhalt als nextLink hinzufügen", + addPageSelector: "Selector-Inhalt als pageElement hinzufügen", + propName: "Regelattributnamen eingeben", + propValue: "Regelattributwert eingeben", + customFirst: "Cache für lokale benutzerdefinierte Regeln ignorieren", + rulesExample: "Regeln Beispiel", + lastPage: "Letzte Seite erreicht", + lastPageTips: "Tipps anzeigen, wenn die letzte Seite erreicht ist" + } + }, + { + name: "ไทย", + match: ["th"], + lang: { + enableDebug: "เปิดใช้งานเอาต์พุตการดีบักไปยังคอนโซล", + updateNotification: "การแจ้งเตือนหลังจากอัปเดตกฎ", + disable: "ปิดใช้งานชั่วคราว", + disableSite: "สลับสถานะการปิดใช้งาน", + disableSiteTips: "ปิดใช้งานบนไซต์นี้", + enableSiteTips: "เปิดใช้งานบนไซต์นี้", + enable: "✅เปิดใช้งานการเปลี่ยนหน้าอัตโนมัติ", + tempActive: "ใช้งานชั่วคราว", + toTop: "กลับไปด้านบน", + toBottom: "ไปที่ด้านล่าง", + current: "หน้าปัจจุบัน", + forceIframe: "บังคับให้เข้าร่วมหน้าถัดไป", + cancelForceIframe: "ยกเลิกการเข้าร่วมบังคับ", + configure: "กำหนดค่า Pagetual", + firstUpdate: "คลิกที่นี่เพื่อเริ่มต้นรายการกฎเริ่มต้น", + update: "อัปเดตกฎออนไลน์", + click2update: "คลิกเพื่ออัปเดตกฎจาก url ทันที", + loadNow: "โหลดหน้าถัดไปโดยอัตโนมัติ", + loadConfirm: "คุณต้องการโหลดกี่หน้า (0 หมายถึงไม่สิ้นสุด)", + noNext: "ไม่พบลิงก์ถัดไป โปรดสร้างกฎใหม่", + passSec: "อัปเดตเมื่อ #t# วินาทีที่แล้ว", + passMin: "อัปเดตเมื่อ #t# นาทีที่แล้ว", + passHour: "อัปเดตเมื่อ #t# ชั่วโมงที่แล้ว", + passDay: "อัปเดตเมื่อ #t# วันที่แล้ว", + cantDel: "ไม่สามารถลบกฎในตัวได้", + confirmDel: "คุณแน่ใจหรือไม่ว่าต้องการลบกฎนี้", + updateSucc: "อัปเดตสำเร็จ", + beginUpdate: "เริ่มอัปเดต โปรดรอสักครู่", + customUrls: "นำเข้า URL กฎ Pagetual หรือ AutoPagerize หนึ่ง URL ต่อบรรทัด", + customRules: "ป้อนกฎที่กำหนดเอง ✍️มีส่วนร่วมในกฎ", + save: "บันทึก", + loadingText: "กำลังโหลด...", + opacity: "ความทึบ", + opacityPlaceholder: "0: ซ่อนตัวเว้นวรรค", + hideBar: "ซ่อนตัวเว้นวรรคของหน้า", + hideBarButNoStop: "ซ่อนแต่ไม่หยุด", + dbClick2Stop: "ดับเบิลคลิกที่พื้นที่ว่างเพื่อหยุดชั่วคราว", + sortTitle: "การเรียงลำดับจะมีผลหลังจากการอัปเดตกฎครั้งถัดไป", + autoRun: "เปิดใช้งานอัตโนมัติ (โหมดบัญชีดำ)", + autoLoadNum: "จำนวนหน้าที่โหลดล่วงหน้า", + turnRate: "เปลี่ยนหน้าถัดไปเมื่ออยู่ห่างจากส่วนท้ายน้อยกว่า【X】เท่าของความสูงของหน้า", + inputPageNum: "ป้อนหมายเลขหน้าเพื่อข้ามไป", + enableHistory: "เขียนประวัติการเข้าชมหลังจากการเปลี่ยนหน้า", + enableHistoryAfterInsert: "เขียนประวัติการเข้าชมทันทีหลังจากต่อเข้าด้วยกัน มิฉะนั้นจะเขียนหลังจากการเข้าชม", + contentVisibility: "สลับ content-visibility โดยอัตโนมัติเพื่อปรับปรุงประสิทธิภาพการเรนเดอร์", + initRun: "เปลี่ยนหน้าทันทีหลังจากเปิด", + preload: "โหลดหน้าถัดไปล่วงหน้าเพื่อเพิ่มความเร็ว", + click2ImportRule: "คลิกเพื่อนำเข้าลิงก์กฎพื้นฐาน แล้วรอจนกว่าการอัปเดตจะเสร็จสมบูรณ์: ", + forceAllBody: "เข้าร่วมเนื้อหาทั้งหมดของหน้าหรือไม่", + openInNewTab: "เปิด URL ของส่วนเพิ่มเติมในแท็บใหม่", + importSucc: "นำเข้าสำเร็จ", + import: "นำเข้า", + editCurrent: "แก้ไขกฎสำหรับเว็บไซต์ปัจจุบัน", + editBlacklist: "แก้ไขบัญชีดำของ URL หนึ่งรายการต่อบรรทัด รองรับ [?,*] wildcards", + upBtnImg: "ไอคอนกลับไปด้านบน", + downBtnImg: "ไอคอนไปที่ส่วนท้าย", + sideControllerIcon: "ไอคอนของแถบด้านข้าง", + loadingTextTitle: "กำลังโหลด", + dbClick2StopCtrl: "ปุ่ม Ctrl", + dbClick2StopAlt: "ปุ่ม Alt", + dbClick2StopShift: "ปุ่ม Shift", + dbClick2StopMeta: "ปุ่ม Meta", + dbClick2StopKey: "ปุ่มลัด", + pageElementCss: "สไตล์ที่กำหนดเองสำหรับองค์ประกอบหน้าหลัก", + customCss: "CSS ที่กำหนดเองทั้งหมด", + firstAlert: "คุณยังไม่ได้นำเข้ากฎพื้นฐาน โปรดเลือกกฎที่เหมาะสมเพื่อนำเข้า", + picker: "ตัวเลือกองค์ประกอบ Pagetual", + closePicker: "ปิดตัวเลือก Pagetual", + pickerPlaceholder: "ตัวเลือกองค์ประกอบ (สำหรับผู้ใช้ขั้นสูงเท่านั้น เว้นว่างไว้)", + pickerCheck: "ตรวจสอบตัวเลือกและคัดลอก", + switchSelector: "คลิกเพื่อสลับองค์ประกอบ", + gotoEdit: "ไปที่การแก้ไขกฎด้วยตัวเลือกปัจจุบัน", + manualMode: "ปิดใช้งานการต่อเข้าด้วยกัน เลื่อนหน้าถัดไปด้วยตนเองโดยใช้ปุ่มลูกศรขวา (หรือส่งเหตุการณ์ 'pagetual.next')", + clickMode: "ปิดใช้งานการต่อเข้าด้วยกัน คลิกหน้าถัดไปโดยอัตโนมัติเมื่อเลื่อนไปที่ท้ายหน้า", + pageBarMenu: "คลิกที่กึ่งกลางของแถบหน้าเพื่อเปิดเมนูตัวเลือก", + nextSwitch: "สลับลิงก์ถัดไป", + arrowToScroll: "กดลูกศรซ้ายเพื่อเลื่อนกลับและลูกศรขวาเพื่อเลื่อนหน้า", + sideController: "แสดงแถบควบคุมการแบ่งหน้าในแถบด้านข้าง", + sideControllerScroll: "สลับการเลื่อน", + sideControllerAlways: "แสดงเสมอ", + hideLoadingIcon: "ซ่อนภาพเคลื่อนไหวการโหลด", + hideBarArrow: "ซ่อนลูกศรสำหรับแถบหน้า", + duplicate: "มีการติดตั้ง Pagetual ที่ซ้ำกัน ตรวจสอบผู้จัดการสคริปต์ของคุณ!", + forceStateIframe: "ฝังหน้าเต็มเป็น iframe", + forceStateDynamic: "โหลดเนื้อหาแบบไดนามิกผ่าน iframe", + forceStateDisable: "ปิดใช้งานการเปลี่ยนหน้าบนไซต์นี้", + autoScrollRate: "ความเร็วในการเลื่อน (1~1000)", + disableAutoScroll: "หยุดการเลื่อนอัตโนมัติ", + enableAutoScroll: "เปิดใช้งานการเลื่อนอัตโนมัติ", + toggleAutoScroll: "สลับการเลื่อนอัตโนมัติ", + ruleRequest: "ขอกฎ", + page: "หน้า ", + prevPage: "หน้าก่อนหน้า", + nextPage: "หน้าถัดไป", + errorRulesMustBeArray: "กฎต้องเป็นอาร์เรย์!", + errorJson: "ข้อผิดพลาด JSON ตรวจสอบอีกครั้ง!", + editSuccess: "แก้ไขสำเร็จ", + errorWrongUrl: "URL ไม่ถูกต้อง ตรวจสอบอีกครั้ง!", + errorAlreadyExists: "มีกฎอยู่แล้ว!", + settingsSaved: "บันทึกการตั้งค่าแล้ว รีเฟรชเพื่อดู", + iframe: "บังคับแยกโดย iframe", + dynamic: "การโหลดแบบไดนามิก", + reloadPage: "แก้ไขเสร็จแล้ว โหลดใหม่ตอนนี้หรือไม่", + copied: "คัดลอกแล้ว", + noValidContent: "ไม่พบเนื้อหาที่ถูกต้อง อาจมี Captcha", + outOfDate: "สคริปต์ล้าสมัย โปรดอัปเดตเป็นเวอร์ชันล่าสุด", + hideBarTips: "ซ่อนแถบเลขหน้า สลับประสบการณ์ที่สมจริง", + setConfigPage: "ตั้งค่าหน้าปัจจุบันเป็นหน้าการกำหนดค่าเริ่มต้น", + wedata2github: "เปลี่ยนที่อยู่ wedata เป็นที่อยู่มิเรอร์ในที่เก็บ github", + addOtherProp: "เพิ่มคุณสมบัติของกฎ", + addNextSelector: "เพิ่มเนื้อหาตัวเลือกเป็น nextLink", + addPageSelector: "เพิ่มเนื้อหาตัวเลือกเป็น pageElement", + propName: "ป้อนชื่อคุณสมบัติของกฎ", + propValue: "ป้อนค่าคุณสมบัติของกฎ", + customFirst: "ไม่สนใจแคชสำหรับกฎที่กำหนดเองในเครื่อง", + rulesExample: "ตัวอย่างกฎ", + lastPage: "ถึงหน้าสุดท้ายแล้ว", + lastPageTips: "แสดงเคล็ดลับเมื่อถึงหน้าสุดท้าย" + } + }, + { + name: "Norsk (Bokmål)", + match: ["nb", "nb-NO"], + lang: { + enableDebug: "Aktiver feilsøkingsutdata til konsollen", + updateNotification: "Varsling etter at regler er oppdatert", + disable: "Deaktiver midlertidig", + disableSite: "Veksle deaktivert tilstand", + disableSiteTips: "Deaktivert på dette nettstedet.", + enableSiteTips: "Aktivert på dette nettstedet.", + enable: "✅Aktiver automatisk sidevending", + tempActive: "Midlertidig aktiv", + toTop: "Tilbake til toppen.", + toBottom: "Gå til bunnen.", + current: "Gjeldende side.", + forceIframe: "Tving til å koble til neste side", + cancelForceIframe: "Avbryt tvungen tilkobling", + configure: "Konfigurer Pagetual", + firstUpdate: "Klikk her for å initialisere standard regelliste", + update: "Oppdater nettbaserte regler", + click2update: "Klikk for å oppdatere regler fra url nå", + loadNow: "Last neste automatisk", + loadConfirm: "Hvor mange sider vil du laste? (0 betyr uendelig)", + noNext: "Ingen neste lenke funnet, vennligst opprett en ny regel", + passSec: "Oppdatert for #t# sekunder siden", + passMin: "Oppdatert for #t# minutter siden", + passHour: "Oppdatert for #t# timer siden", + passDay: "Oppdatert for #t# dager siden", + cantDel: "Kan ikke slette innebygde regler", + confirmDel: "Er du sikker på at du vil slette denne regelen?", + updateSucc: "Oppdatering vellykket", + beginUpdate: "Starter oppdatering, vent et øyeblikk", + customUrls: "Importer Pagetual eller AutoPagerize regel-url, én url per linje.", + customRules: "Skriv inn egendefinerte regler. ✍️Bidra med regler", + save: "Lagre", + loadingText: "Laster nå...", + opacity: "Opasitet", + opacityPlaceholder: "0: skjul avstandsstykke", + hideBar: "Skjul pagineringsavstandsstykket", + hideBarButNoStop: "Skjul, men ikke stopp", + dbClick2Stop: "Dobbeltklikk på det tomme området for å pause", + sortTitle: "Sortering trer i kraft etter neste regeloppdatering", + autoRun: "Auto-aktiver (svartelistemodus)", + autoLoadNum: "Antall for forhåndslastede sider", + turnRate: "Snu til neste side når det er mindre enn 【X】 ganger sidehøyden fra bunnteksten", + inputPageNum: "Skriv inn sidetall for å hoppe", + enableHistory: "Skriv nettleserlogg etter sidevending", + enableHistoryAfterInsert: "Skriv nettleserlogg umiddelbart etter spleising, ellers skriv etter surfing", + contentVisibility: "Bytt automatisk innholdssynlighet for å forbedre gjengivelsesytelsen", + initRun: "Snu sider umiddelbart etter åpning", + preload: "Forhåndslast neste side for å øke hastigheten", + click2ImportRule: "Klikk for å importere grunnregellenke, og vent deretter til oppdateringen er fullført: ", + forceAllBody: "Koble til hele sidens kropp?", + openInNewTab: "Åpne url-er for tillegg i ny fane", + importSucc: "Import fullført", + import: "Importer", + editCurrent: "Rediger regel for gjeldende nettsted", + editBlacklist: "Rediger url-svartelisten, én oppføring per linje, støtter [?,*] jokertegn.", + upBtnImg: "Ikon for tilbake til toppen", + downBtnImg: "Ikon for å gå til bunntekst", + sideControllerIcon: "Ikon for sidefelt", + loadingTextTitle: "Laster", + dbClick2StopCtrl: "Ctrl-tast", + dbClick2StopAlt: "Alt-tast", + dbClick2StopShift: "Shift-tast", + dbClick2StopMeta: "Meta-tast", + dbClick2StopKey: "Hurtigtast", + pageElementCss: "Egendefinert stil for hovedsideelementer", + customCss: "Egendefinert komplett css", + firstAlert: "Du har ikke importert grunnregelen, vennligst velg riktig regel å importere", + picker: "Pagetual elementvelger", + closePicker: "Lukk Pagetual-velger", + pickerPlaceholder: "Elementvelger, (Kun avanserte brukere, la stå tomt ellers)", + pickerCheck: "Sjekk velger og kopier", + switchSelector: "Klikk for å bytte element", + gotoEdit: "Gå til redigeringsregel med gjeldende velger", + manualMode: "Deaktiver spleising, gå manuelt frem til neste side med høyre piltast (eller send hendelsen 'pagetual.next')", + clickMode: "Deaktiver spleising, klikk automatisk på neste side når du ruller til slutten av siden", + pageBarMenu: "Klikk på midten av sidelinjen for å åpne velgermenyen", + nextSwitch: "Bytt neste lenke", + arrowToScroll: "Trykk venstre piltast for å rulle tilbake og høyre piltast for å gå frem en side", + sideController: "Vis pagineringskontrollinjen i sidefeltet", + sideControllerScroll: "Rulleveksling", + sideControllerAlways: "Vis alltid", + hideLoadingIcon: "Skjul lasteanimasjon", + hideBarArrow: "Skjul pil for sidelinje", + duplicate: "Duplikat Pagetual har blitt installert, sjekk skriptbehandleren din!", + forceStateIframe: "Bygg inn hele siden som iframe", + forceStateDynamic: "Last dynamisk innhold via iframe", + forceStateDisable: "Deaktiver sidevending på dette nettstedet", + autoScrollRate: "Rullehastighet (1~1000)", + disableAutoScroll: "Stopp automatisk rulling", + enableAutoScroll: "Aktiver automatisk rulling", + toggleAutoScroll: "Veksle automatisk rulling", + ruleRequest: "Regelforespørsel", + page: "Side ", + prevPage: "Forrige side", + nextPage: "Neste side", + errorRulesMustBeArray: "Regler må være en matrise!", + errorJson: "JSON-feil, sjekk igjen!", + editSuccess: "Redigering vellykket", + errorWrongUrl: "Feil url, sjekk igjen!", + errorAlreadyExists: "En regel eksisterer allerede!", + settingsSaved: "Innstillingene er lagret, oppdater for å se", + iframe: "Tvunget delt av iframe", + dynamic: "Dynamisk lasting", + reloadPage: "Redigering fullført, last på nytt nå?", + copied: "Kopiert", + noValidContent: "Ingen gyldig innhold funnet, en Captcha kan være til stede", + outOfDate: "Skriptet er utdatert, vennligst oppdater til den nyeste versjonen.", + hideBarTips: "Skjul pagineringslinjen, veksle mellom oppslukende opplevelse", + setConfigPage: "Angi gjeldende side som standard konfigurasjonsside", + wedata2github: "Endre wedata-adressen til speiladressen i github-depotet", + addOtherProp: "Legg til regelegenskaper", + addNextSelector: "Legg til velgerinnhold som nextLink", + addPageSelector: "Legg til velgerinnhold som pageElement", + propName: "Skriv inn regelegenskapsnavn", + propValue: "Skriv inn regelegenskapsverdi", + customFirst: "Ignorer hurtigbuffer for lokale egendefinerte regler", + rulesExample: "Regeleksempel", + lastPage: "Nådde den siste siden", + lastPageTips: "Vis tips når du når den siste siden" + } + }, + { + name: "Svenska", + match: ["sv"], + lang: { + enableDebug: "Aktivera felsökningsutdata till konsolen", + updateNotification: "Meddelande efter att regler har uppdaterats", + disable: "Inaktivera tillfälligt", + disableSite: "Växla inaktiverat läge", + disableSiteTips: "Inaktiverad på denna webbplats.", + enableSiteTips: "Aktiverad på denna webbplats.", + enable: "✅Aktivera automatisk sidvändning", + tempActive: "Tillfälligt aktiv", + toTop: "Tillbaka till toppen.", + toBottom: "Gå till botten.", + current: "Nuvarande sida.", + forceIframe: "Tvinga att ansluta till nästa sida", + cancelForceIframe: "Avbryt tvångsanslutning", + configure: "Konfigurera Pagetual", + firstUpdate: "Klicka här för att initiera standardregellistan", + update: "Uppdatera onlineregler", + click2update: "Klicka för att uppdatera regler från url nu", + loadNow: "Ladda nästa automatiskt", + loadConfirm: "Hur många sidor vill du ladda? (0 betyder oändligt)", + noNext: "Ingen nästa länk hittades, skapa en ny regel", + passSec: "Uppdaterad för #t# sekunder sedan", + passMin: "Uppdaterad för #t# minuter sedan", + passHour: "Uppdaterad för #t# timmar sedan", + passDay: "Uppdaterad för #t# dagar sedan", + cantDel: "Kan inte ta bort inbyggda regler", + confirmDel: "Är du säker på att du vill ta bort denna regel?", + updateSucc: "Uppdatering lyckades", + beginUpdate: "Påbörjar uppdatering, vänta ett ögonblick", + customUrls: "Importera Pagetual eller AutoPagerize regel-url, en url per rad.", + customRules: "Ange anpassade regler. ✍️Bidra med regler", + save: "Spara", + loadingText: "Laddar nu...", + opacity: "Opacitet", + opacityPlaceholder: "0: dölj mellanrum", + hideBar: "Dölj pagineringsmellanrummet", + hideBarButNoStop: "Dölj men stoppa inte", + dbClick2Stop: "Dubbelklicka på det tomma utrymmet för att pausa", + sortTitle: "Sortering träder i kraft efter nästa regeluppdatering", + autoRun: "Auto-aktivera (svartlistningsläge)", + autoLoadNum: "Antal för förinläsning av sidor", + turnRate: "Vänd till nästa sida när det är mindre än 【X】 gånger sidhöjden från sidfoten", + inputPageNum: "Ange sidnummer för att hoppa", + enableHistory: "Skriv webbhistorik efter sidvändning", + enableHistoryAfterInsert: "Skriv webbhistorik omedelbart efter sammanfogning, annars skriv efter surfning", + contentVisibility: "Växla automatiskt innehållssynlighet för att förbättra renderingsprestanda", + initRun: "Vänd sidor omedelbart efter öppning", + preload: "Förinläs nästa sida för att påskynda", + click2ImportRule: "Klicka för att importera grundregellänk, och vänta sedan tills uppdateringen är klar: ", + forceAllBody: "Anslut hela sidans kropp?", + openInNewTab: "Öppna webbadresser för tillägg i ny flik", + importSucc: "Importen är klar", + import: "Importera", + editCurrent: "Redigera regel för aktuell webbplats", + editBlacklist: "Redigera webbadress-svartlistan, en post per rad, stöder [?,*] jokertecken.", + upBtnImg: "Ikon för tillbaka till toppen", + downBtnImg: "Ikon för att gå till sidfot", + sideControllerIcon: "Ikon för sidofältet", + loadingTextTitle: "Laddar", + dbClick2StopCtrl: "Ctrl-tangent", + dbClick2StopAlt: "Alt-tangent", + dbClick2StopShift: "Shift-tangent", + dbClick2StopMeta: "Meta-tangent", + dbClick2StopKey: "Snabbtangent", + pageElementCss: "Anpassad stil för huvudsidaelement", + customCss: "Anpassad komplett css", + firstAlert: "Du har inte importerat grundregeln, välj lämplig regel att importera", + picker: "Pagetual elementväljare", + closePicker: "Stäng Pagetual-väljare", + pickerPlaceholder: "Elementväljare, (Endast avancerade användare, lämna tomt annars)", + pickerCheck: "Kontrollera väljare och kopiera", + switchSelector: "Klicka för att byta element", + gotoEdit: "Gå till redigera regel med aktuell väljare", + manualMode: "Inaktivera sammanfogning, gå manuellt framåt till nästa sida med höger piltangent (eller skicka händelsen 'pagetual.next')", + clickMode: "Inaktivera sammanfogning, klicka automatiskt på nästa sida när du rullar till slutet av sidan", + pageBarMenu: "Klicka på mitten av sidfältet för att öppna väljarmenyn", + nextSwitch: "Byt nästa länk", + arrowToScroll: "Tryck på vänster piltangent för att rulla tillbaka och höger piltangent för att gå fram en sida", + sideController: "Visa pagineringskontrollfältet i sidofältet", + sideControllerScroll: "Rullningsväxling", + sideControllerAlways: "Visa alltid", + hideLoadingIcon: "Dölj laddningsanimation", + hideBarArrow: "Dölj pil för sidfält", + duplicate: "Duplicerad Pagetual har installerats, kontrollera din skripthanterare!", + forceStateIframe: "Bädda in hela sidan som iframe", + forceStateDynamic: "Ladda dynamiskt innehåll via iframe", + forceStateDisable: "Inaktivera sidvändning på denna webbplats", + autoScrollRate: "Rullningshastighet (1~1000)", + disableAutoScroll: "Stoppa automatisk rullning", + enableAutoScroll: "Aktivera automatisk rullning", + toggleAutoScroll: "Växla automatisk rullning", + ruleRequest: "Regelförfrågan", + page: "Sida ", + prevPage: "Föregående sida", + nextPage: "Nästa sida", + errorRulesMustBeArray: "Regler måste vara en array!", + errorJson: "JSON-fel, kontrollera igen!", + editSuccess: "Redigering lyckades", + errorWrongUrl: "Fel webbadress, kontrollera igen!", + errorAlreadyExists: "En regel finns redan!", + settingsSaved: "Inställningarna har sparats, uppdatera för att se", + iframe: "Tvingad delning av iframe", + dynamic: "Dynamisk laddning", + reloadPage: "Redigering slutförd, ladda om nu?", + copied: "Kopierad", + noValidContent: "Inget giltigt innehåll hittades, en Captcha kan finnas", + outOfDate: "Skriptet är föråldrat, uppdatera till den senaste versionen.", + hideBarTips: "Dölj pagineringsfältet, växla till en uppslukande upplevelse", + setConfigPage: "Ange aktuell sida som standardkonfigurationssida", + wedata2github: "Ändra wedata-adressen till spegeladressen i github-förvaret", + addOtherProp: "Lägg till regelegenskaper", + addNextSelector: "Lägg till väljarinnehåll som nextLink", + addPageSelector: "Lägg till väljarinnehåll som pageElement", + propName: "Ange regelegenskapsnamn", + propValue: "Ange regelegenskapsvärde", + customFirst: "Ignorera cache för lokala anpassade regler", + rulesExample: "Regelexempel", + lastPage: "Nådde sista sidan", + lastPageTips: "Visa tips när du når sista sidan" + } + }, + { + name: "Српски", + match: ["sr"], + lang: { + enableDebug: "Омогући отклањање грешака на конзоли", + updateNotification: "Обавештење након ажурирања правила", + disable: "Привремено онемогући", + disableSite: "Промени стање онемогућености", + disableSiteTips: "Онемогућено на овом сајту.", + enableSiteTips: "Омогућено на овом сајту.", + enable: "✅Омогући аутоматско окретање страница", + tempActive: "Привремено активно", + toTop: "Назад на врх.", + toBottom: "Иди на дно.", + current: "Тренутна страница.", + forceIframe: "Присили спајање следеће странице", + cancelForceIframe: "Откажи присилно спајање", + configure: "Конфигуриши Pagetual", + firstUpdate: "Кликните овде да бисте покренули подразумевану листу правила", + update: "Ажурирај правила на мрежи", + click2update: "Кликните да бисте одмах ажурирали правила са УРЛ-а", + loadNow: "Учитај следеће аутоматски", + loadConfirm: "Колико страница желите да учитате? (0 значи бесконачно)", + noNext: "Није пронађена следећа веза, креирајте ново правило", + passSec: "Ажурирано пре #t# секунди", + passMin: "Ажурирано пре #t# минута", + passHour: "Ажурирано пре #t# сати", + passDay: "Ажурирано пре #t# дана", + cantDel: "Не могу се избрисати уграђена правила", + confirmDel: "Да ли сте сигурни да желите да избришете ово правило?", + updateSucc: "Ажурирање је успело", + beginUpdate: "Започни ажурирање, сачекајте тренутак", + customUrls: "Увезите Pagetual или AutoPagerize УРЛ правила, један УРЛ по линији.", + customRules: "Унесите прилагођена правила. ✍️Допринесите правилима", + save: "Сачувај", + loadingText: "Учитавање у току...", + opacity: "Провидност", + opacityPlaceholder: "0: сакриј размак", + hideBar: "Сакриј размак за пагинацију", + hideBarButNoStop: "Сакриј, али не заустављај", + dbClick2Stop: "Двапут кликните на празан простор да бисте паузирали", + sortTitle: "Сортирање ступа на снагу након следећег ажурирања правила", + autoRun: "Аутоматско омогућавање (режим црне листе)", + autoLoadNum: "Количина за унапред учитане странице", + turnRate: "Окрените следећу страницу када је мање од 【X】 пута висине странице од подножја", + inputPageNum: "Унесите број странице за скок", + enableHistory: "Упиши историју прегледања након окретања странице", + enableHistoryAfterInsert: "Упиши историју прегледања одмах након спајања, у супротном упиши након прегледања", + contentVisibility: "Аутоматски промени видљивост садржаја да би се побољшале перформансе приказивања", + initRun: "Окрени странице одмах након отварања", + preload: "Унапред учитај следећу страницу ради убрзања", + click2ImportRule: "Кликните да бисте увезли везу основних правила, а затим сачекајте док се ажурирање не заврши: ", + forceAllBody: "Спојити цело тело странице?", + openInNewTab: "Отвори УРЛ-ове додатака у новој картици", + importSucc: "Увоз је завршен", + import: "Увези", + editCurrent: "Уреди правило за тренутни веб-сајт", + editBlacklist: "Уредите УРЛ црну листу, један унос по линији, подржава џокере [?,*].", + upBtnImg: "Икона за повратак на врх", + downBtnImg: "Икона за одлазак на подножје", + sideControllerIcon: "Икона бочне траке", + loadingTextTitle: "Учитавање", + dbClick2StopCtrl: "Тастер Ctrl", + dbClick2StopAlt: "Тастер Alt", + dbClick2StopShift: "Тастер Shift", + dbClick2StopMeta: "Тастер Meta", + dbClick2StopKey: "Тастер пречице", + pageElementCss: "Прилагођени стил за главне елементе странице", + customCss: "Прилагођени комплетан ЦСС", + firstAlert: "Нисте увезли основно правило, изаберите одговарајуће правило за увоз", + picker: "Pagetual бирач елемената", + closePicker: "Затвори Pagetual бирач", + pickerPlaceholder: "Бирач елемената, (Само напредни корисници, иначе оставите празно)", + pickerCheck: "Провери бирач и копирај", + switchSelector: "Кликните да бисте променили елемент", + gotoEdit: "Иди на уређивање правила са тренутним бирачем", + manualMode: "Онемогући спајање, ручно пређи на следећу страницу помоћу десног тастера са стрелицом (или пошаљи догађај 'pagetual.next')", + clickMode: "Онемогући спајање, аутоматски кликни на следећу страницу приликом померања до краја странице", + pageBarMenu: "Кликните на центар траке странице да бисте отворили мени бирача", + nextSwitch: "Промени следећу везу", + arrowToScroll: "Притисните леви тастер са стрелицом за померање уназад и десни тастер са стрелицом за прелазак на страницу", + sideController: "Прикажи контролну траку за пагинацију у бочној траци", + sideControllerScroll: "Промена померања", + sideControllerAlways: "Увек прикажи", + hideLoadingIcon: "Сакриј анимацију учитавања", + hideBarArrow: "Сакриј стрелицу за траку странице", + duplicate: "Дупликат Pagetual је инсталиран, проверите свој менаџер скрипти!", + forceStateIframe: "Угради целу страницу као iframe", + forceStateDynamic: "Учитај динамички садржај путем iframe-a", + forceStateDisable: "Онемогући окретање страница на овом сајту", + autoScrollRate: "Брзина померања (1~1000)", + disableAutoScroll: "Заустави аутоматско померање", + enableAutoScroll: "Омогући аутоматско померање", + toggleAutoScroll: "Промени аутоматско померање", + ruleRequest: "Захтев за правило", + page: "Страница ", + prevPage: "Претходна страница", + nextPage: "Следећа страница", + errorRulesMustBeArray: "Правила морају бити низ!", + errorJson: "ЈСОН грешка, проверите поново!", + editSuccess: "Успешно уређено", + errorWrongUrl: "Погрешан УРЛ, проверите поново!", + errorAlreadyExists: "Правило већ постоји!", + settingsSaved: "Подешавања су сачувана, освежите да бисте видели", + iframe: "Присилно подељено iframe-ом", + dynamic: "Динамичко учитавање", + reloadPage: "Уређивање је завршено, поново учитати сада?", + copied: "Копирано", + noValidContent: "Није детектован важећи садржај, можда је присутан Цаптцха", + outOfDate: "Скрипта је застарела, ажурирајте на најновију верзију.", + hideBarTips: "Сакријте траку за пагинацију, промените имерзивно искуство", + setConfigPage: "Постави тренутну страницу као подразумевану страницу за конфигурацију", + wedata2github: "Промените wedata адресу на адресу огледала у гитхуб спремишту", + addOtherProp: "Додај својства правила", + addNextSelector: "Додај садржај бирача као nextLink", + addPageSelector: "Додај садржај бирача као pageElement", + propName: "Унесите назив својства правила", + propValue: "Унесите вредност својства правила", + customFirst: "Игнориши кеш за локална прилагођена правила", + rulesExample: "Пример правила", + lastPage: "Достигнута је последња страница", + lastPageTips: "Прикажи савете приликом достизања последње странице" + } + }, + { + name: "Slovenčina", + match: ["sk"], + lang: { + enableDebug: "Povoliť výstup ladenia do konzoly", + updateNotification: "Oznámenie po aktualizácii pravidiel", + disable: "Dočasne zakázať", + disableSite: "Prepnúť stav zakázania", + disableSiteTips: "Na tejto stránke zakázané.", + enableSiteTips: "Na tejto stránke povolené.", + enable: "✅Povoliť automatické otáčanie stránok", + tempActive: "Dočasne aktívne", + toTop: "Späť na začiatok.", + toBottom: "Ísť na koniec.", + current: "Aktuálna stránka.", + forceIframe: "Vynútiť pripojenie k ďalšej stránke", + cancelForceIframe: "Zrušiť vynútené pripojenie", + configure: "Konfigurovať Pagetual", + firstUpdate: "Kliknite sem pre inicializáciu predvoleného zoznamu pravidiel", + update: "Aktualizovať online pravidlá", + click2update: "Kliknite pre aktualizáciu pravidiel z URL teraz", + loadNow: "Načítať ďalšie automaticky", + loadConfirm: "Koľko stránok chcete načítať? (0 znamená nekonečno)", + noNext: "Nenašiel sa žiadny ďalší odkaz, vytvorte nové pravidlo", + passSec: "Aktualizované pred #t# sekundami", + passMin: "Aktualizované pred #t# minútami", + passHour: "Aktualizované pred #t# hodinami", + passDay: "Aktualizované pred #t# dňami", + cantDel: "Nie je možné odstrániť vstavané pravidlá", + confirmDel: "Ste si istí, že chcete odstrániť toto pravidlo?", + updateSucc: "Aktualizácia úspešná", + beginUpdate: "Začína sa aktualizácia, chvíľu počkajte", + customUrls: "Importovať URL pravidla Pagetual alebo AutoPagerize, jedno URL na riadok.", + customRules: "Zadajte vlastné pravidlá. ✍️Prispieť pravidlami", + save: "Uložiť", + loadingText: "Načítava sa...", + opacity: "Nepriehľadnosť", + opacityPlaceholder: "0: skryť medzerník", + hideBar: "Skryť medzerník stránkovania", + hideBarButNoStop: "Skryť, ale nezastaviť", + dbClick2Stop: "Dvojitým kliknutím na prázdne miesto pozastavíte", + sortTitle: "Triedenie sa prejaví po ďalšej aktualizácii pravidiel", + autoRun: "Automatické povolenie (režim čiernej listiny)", + autoLoadNum: "Množstvo pre prednačítané stránky", + turnRate: "Otočte na ďalšiu stránku, keď je menej ako 【X】 násobok výšky stránky od pätičky", + inputPageNum: "Zadajte číslo stránky na preskočenie", + enableHistory: "Zapísať históriu prehliadania po otočení stránky", + enableHistoryAfterInsert: "Zapísať históriu prehliadania ihneď po spojení, inak zapísať po prehliadaní", + contentVisibility: "Automaticky prepínať viditeľnosť obsahu na zlepšenie výkonu vykresľovania", + initRun: "Otočiť stránky ihneď po otvorení", + preload: "Prednačítať ďalšiu stránku na zrýchlenie", + click2ImportRule: "Kliknite pre import odkazu na základné pravidlá a potom počkajte, kým sa aktualizácia nedokončí: ", + forceAllBody: "Pripojiť celé telo stránky?", + openInNewTab: "Otvoriť URL adries prídavkov v novej karte", + importSucc: "Import dokončený", + import: "Importovať", + editCurrent: "Upraviť pravidlo pre aktuálnu webovú stránku", + editBlacklist: "Upraviť čiernu listinu URL, jeden záznam na riadok, podporuje zástupné znaky [?,*].", + upBtnImg: "Ikona späť na začiatok", + downBtnImg: "Ikona ísť na pätičku", + sideControllerIcon: "Ikona bočného panela", + loadingTextTitle: "Načítavanie", + dbClick2StopCtrl: "Kláves Ctrl", + dbClick2StopAlt: "Kláves Alt", + dbClick2StopShift: "Kláves Shift", + dbClick2StopMeta: "Kláves Meta", + dbClick2StopKey: "Klávesová skratka", + pageElementCss: "Vlastný štýl pre hlavné prvky stránky", + customCss: "Vlastné kompletné CSS", + firstAlert: "Neimportovali ste základné pravidlo, vyberte prosím vhodné pravidlo na import", + picker: "Výber prvkov Pagetual", + closePicker: "Zavrieť výber Pagetual", + pickerPlaceholder: "Výber prvkov, (Iba pre pokročilých používateľov, inak nechajte prázdne)", + pickerCheck: "Skontrolovať výber a kopírovať", + switchSelector: "Kliknutím prepnete prvok", + gotoEdit: "Prejsť na úpravu pravidla s aktuálnym výberom", + manualMode: "Zakázať spájanie, manuálne prejsť na ďalšiu stránku pomocou klávesu so šípkou doprava (alebo odoslať udalosť 'pagetual.next')", + clickMode: "Zakázať spájanie, automaticky kliknúť na ďalšiu stránku pri posunutí na koniec stránky", + pageBarMenu: "Kliknutím na stred lišty stránky otvoríte menu výberu", + nextSwitch: "Prepnúť ďalší odkaz", + arrowToScroll: "Stlačením ľavej šípky sa posuniete späť a pravou šípkou prejdete na stránku", + sideController: "Zobraziť ovládací panel stránkovania v bočnom paneli", + sideControllerScroll: "Prepnúť posúvanie", + sideControllerAlways: "Vždy zobraziť", + hideLoadingIcon: "Skryť animáciu načítavania", + hideBarArrow: "Skryť šípku pre lištu stránky", + duplicate: "Duplicitný Pagetual bol nainštalovaný, skontrolujte svoj správcu skriptov!", + forceStateIframe: "Vložiť celú stránku ako iframe", + forceStateDynamic: "Načítať dynamický obsah cez iframe", + forceStateDisable: "Zakázať otáčanie stránok na tejto stránke", + autoScrollRate: "Rýchlosť posúvania (1~1000)", + disableAutoScroll: "Zastaviť automatické posúvanie", + enableAutoScroll: "Povoliť automatické posúvanie", + toggleAutoScroll: "Prepnúť automatické posúvanie", + ruleRequest: "Žiadosť o pravidlo", + page: "Stránka ", + prevPage: "Predchádzajúca stránka", + nextPage: "Ďalšia stránka", + errorRulesMustBeArray: "Pravidlá musia byť pole!", + errorJson: "Chyba JSON, skontrolujte znova!", + editSuccess: "Úspešne upravené", + errorWrongUrl: "Nesprávne URL, skontrolujte znova!", + errorAlreadyExists: "Pravidlo už existuje!", + settingsSaved: "Nastavenia sú uložené, obnovte pre zobrazenie", + iframe: "Vynútené rozdelenie pomocou iframe", + dynamic: "Dynamické načítavanie", + reloadPage: "Úprava dokončená, načítať znova?", + copied: "Skopírované", + noValidContent: "Nebol zistený žiadny platný obsah, môže byť prítomná Captcha", + outOfDate: "Skript je zastaraný, aktualizujte prosím na najnovšiu verziu.", + hideBarTips: "Skryť lištu stránkovania, prepnúť pohlcujúci zážitok", + setConfigPage: "Nastaviť aktuálnu stránku ako predvolenú konfiguračnú stránku", + wedata2github: "Zmeniť adresu wedata na zrkadlovú adresu v repozitári github", + addOtherProp: "Pridať vlastnosti pravidla", + addNextSelector: "Pridať obsah výberu ako nextLink", + addPageSelector: "Pridať obsah výberu ako pageElement", + propName: "Zadajte názov vlastnosti pravidla", + propValue: "Zadajte hodnotu vlastnosti pravidla", + customFirst: "Ignorovať vyrovnávaciu pamäť pre lokálne vlastné pravidlá", + rulesExample: "Príklad pravidiel", + lastPage: "Dosiahli ste poslednú stránku", + lastPageTips: "Zobraziť tipy pri dosiahnutí poslednej stránky" + } + }, + { + name: "Magyar", + match: ["hu"], + lang: { + enableDebug: "Hibakeresési kimenet engedélyezése a konzolon", + updateNotification: "Értesítés a szabályok frissítése után", + disable: "Ideiglenes letiltás", + disableSite: "Letiltott állapot váltása", + disableSiteTips: "Letiltva ezen az oldalon.", + enableSiteTips: "Engedélyezve ezen az oldalon.", + enable: "✅Automatikus lapozás engedélyezése", + tempActive: "Ideiglenesen aktív", + toTop: "Vissza a tetejére.", + toBottom: "Ugrás az aljára.", + current: "Jelenlegi oldal.", + forceIframe: "Következő oldal csatlakozásának kényszerítése", + cancelForceIframe: "Kényszerített csatlakozás megszakítása", + configure: "Pagetual konfigurálása", + firstUpdate: "Kattintson ide az alapértelmezett szabálylista inicializálásához", + update: "Online szabályok frissítése", + click2update: "Kattintson a szabályok URL-ről történő frissítéséhez", + loadNow: "Következő automatikus betöltése", + loadConfirm: "Hány oldalt szeretne betölteni? (0 a végtelent jelenti)", + noNext: "Nincs következő link, hozzon létre új szabályt", + passSec: "#t# másodperce frissítve", + passMin: "#t# perce frissítve", + passHour: "#t# órája frissítve", + passDay: "#t# napja frissítve", + cantDel: "Beépített szabályok nem törölhetők", + confirmDel: "Biztosan törli ezt a szabályt?", + updateSucc: "Sikeres frissítés", + beginUpdate: "Frissítés megkezdése, kérem várjon egy pillanatot", + customUrls: "Pagetual vagy AutoPagerize szabály URL importálása, soronként egy URL.", + customRules: "Adjon meg egyéni szabályokat. ✍️Szabályok beküldése", + save: "Mentés", + loadingText: "Betöltés...", + opacity: "Átlátszóság", + opacityPlaceholder: "0: elválasztó elrejtése", + hideBar: "Lapozó elválasztó elrejtése", + hideBarButNoStop: "Elrejtés, de nem leállítás", + dbClick2Stop: "Dupla kattintás az üres területre a szüneteltetéshez", + sortTitle: "A rendezés a következő szabályfrissítés után lép érvénybe", + autoRun: "Automatikus engedélyezés (feketelista mód)", + autoLoadNum: "Előtöltendő oldalak száma", + turnRate: "Lapozzon a következő oldalra, ha a lábléctől mért távolság kevesebb, mint az oldal magasságának 【X】-szerese", + inputPageNum: "Adja meg az ugrani kívánt oldalszámot", + enableHistory: "Böngészési előzmények írása lapozás után", + enableHistoryAfterInsert: "Böngészési előzmények írása azonnal az illesztés után, egyébként a böngészés után", + contentVisibility: "A content-visibility automatikus váltása a renderelési teljesítmény javítása érdekében", + initRun: "Oldalak lapozása azonnal a megnyitás után", + preload: "Következő oldal előtöltése a gyorsítás érdekében", + click2ImportRule: "Kattintson az alapszabályok linkjének importálásához, majd várja meg a frissítés befejezését: ", + forceAllBody: "Csatlakoztatja az oldal teljes törzsét?", + openInNewTab: "A kiegészítések URL-jeinek megnyitása új lapon", + importSucc: "Importálás befejezve", + import: "Importálás", + editCurrent: "Szabály szerkesztése az aktuális webhelyhez", + editBlacklist: "URL feketelista szerkesztése, soronként egy bejegyzés, támogatja a [?,*] helyettesítő karaktereket.", + upBtnImg: "Vissza a tetejére ikon", + downBtnImg: "Ugrás a lábléchez ikon", + sideControllerIcon: "Oldalsáv ikonja", + loadingTextTitle: "Betöltés", + dbClick2StopCtrl: "Ctrl billentyű", + dbClick2StopAlt: "Alt billentyű", + dbClick2StopShift: "Shift billentyű", + dbClick2StopMeta: "Meta billentyű", + dbClick2StopKey: "Gyorsbillentyű", + pageElementCss: "Egyéni stílus a fő oldalelemekhez", + customCss: "Egyéni teljes CSS", + firstAlert: "Nem importálta az alapszabályt, kérjük, válassza ki a megfelelő szabályt az importáláshoz", + picker: "Pagetual elemkiválasztó", + closePicker: "Pagetual kiválasztó bezárása", + pickerPlaceholder: "Elemválasztó (Csak haladó felhasználóknak, egyébként hagyja üresen)", + pickerCheck: "Választó ellenőrzése és másolása", + switchSelector: "Kattintson az elem váltásához", + gotoEdit: "Ugrás a szabály szerkesztéséhez az aktuális választóval", + manualMode: "Illesztés letiltása, manuális lapozás a jobb nyílbillentyűvel (vagy a 'pagetual.next' esemény küldésével)", + clickMode: "Illesztés letiltása, automatikus kattintás a következő oldalra az oldal végére görgetve", + pageBarMenu: "Kattintson az oldalsáv közepére a kiválasztó menü megnyitásához", + nextSwitch: "Következő link váltása", + arrowToScroll: "Nyomja meg a bal nyilat a visszagörgetéshez és a jobb nyilat az oldallapozáshoz", + sideController: "A lapozásvezérlő sáv megjelenítése az oldalsávon", + sideControllerScroll: "Görgetés váltása", + sideControllerAlways: "Mindig mutassa", + hideLoadingIcon: "Betöltési animáció elrejtése", + hideBarArrow: "Oldalsáv nyilának elrejtése", + duplicate: "Duplikált Pagetual telepítve van, ellenőrizze a szkriptkezelőjét!", + forceStateIframe: "Teljes oldal beágyazása iframe-ként", + forceStateDynamic: "Dinamikus tartalom betöltése iframe-en keresztül", + forceStateDisable: "Lapozás letiltása ezen az oldalon", + autoScrollRate: "Görgetési sebesség (1-1000)", + disableAutoScroll: "Automatikus görgetés leállítása", + enableAutoScroll: "Automatikus görgetés engedélyezése", + toggleAutoScroll: "Automatikus görgetés váltása", + ruleRequest: "Szabálykérés", + page: "Oldal ", + prevPage: "Előző oldal", + nextPage: "Következő oldal", + errorRulesMustBeArray: "A szabályoknak tömbnek kell lenniük!", + errorJson: "JSON hiba, ellenőrizze újra!", + editSuccess: "Sikeres szerkesztés", + errorWrongUrl: "Hibás URL, ellenőrizze újra!", + errorAlreadyExists: "Már létezik egy szabály!", + settingsSaved: "A beállítások mentve, frissítsen a megtekintéshez", + iframe: "Iframe által kényszerített felosztás", + dynamic: "Dinamikus betöltés", + reloadPage: "Szerkesztés befejezve, újratölti most?", + copied: "Másolva", + noValidContent: "Nincs érvényes tartalom, lehet, hogy Captcha van jelen", + outOfDate: "A szkript elavult, kérjük, frissítsen a legújabb verzióra.", + hideBarTips: "A lapozósáv elrejtése, magával ragadó élmény váltása", + setConfigPage: "Az aktuális oldal beállítása alapértelmezett konfigurációs oldalként", + wedata2github: "A wedata cím megváltoztatása a tükör címre a github tárolóban", + addOtherProp: "Szabálytulajdonságok hozzáadása", + addNextSelector: "Választó tartalmának hozzáadása nextLink-ként", + addPageSelector: "Választó tartalmának hozzáadása pageElement-ként", + propName: "Adja meg a szabálytulajdonság nevét", + propValue: "Adja meg a szabálytulajdonság értékét", + customFirst: "Gyorsítótár figyelmen kívül hagyása a helyi egyéni szabályoknál", + rulesExample: "Szabályok példa", + lastPage: "Elérte az utolsó oldalt", + lastPageTips: "Tippek megjelenítése az utolsó oldal elérésekor" + } + }, + { + name: "Română", + match: ["ro"], + lang: { + enableDebug: "Activați ieșirea de depanare în consolă", + updateNotification: "Notificare după actualizarea regulilor", + disable: "Dezactivați temporar", + disableSite: "Comutați starea de dezactivare", + disableSiteTips: "Dezactivat pe acest site.", + enableSiteTips: "Activat pe acest site.", + enable: "✅Activați întoarcerea automată a paginii", + tempActive: "Activ temporar", + toTop: "Înapoi sus.", + toBottom: "Mergi jos.", + current: "Pagina curentă.", + forceIframe: "Forțați alăturarea la pagina următoare", + cancelForceIframe: "Anulați alăturarea forțată", + configure: "Configurați Pagetual", + firstUpdate: "Faceți clic aici pentru a inițializa lista de reguli implicită", + update: "Actualizați regulile online", + click2update: "Faceți clic pentru a actualiza regulile de la URL acum", + loadNow: "Încărcați următoarea automat", + loadConfirm: "Câte pagini doriți să încărcați? (0 înseamnă infinit)", + noNext: "Nu s-a găsit niciun link următor, vă rugăm să creați o nouă regulă", + passSec: "Actualizat acum #t# secunde", + passMin: "Actualizat acum #t# minute", + passHour: "Actualizat acum #t# ore", + passDay: "Actualizat acum #t# zile", + cantDel: "Nu se pot șterge regulile încorporate", + confirmDel: "Sunteți sigur că doriți să ștergeți această regulă?", + updateSucc: "Actualizare reușită", + beginUpdate: "Începe actualizarea, vă rugăm așteptați un moment", + customUrls: "Importați URL-ul regulii Pagetual sau AutoPagerize, un URL pe linie.", + customRules: "Introduceți reguli personalizate. ✍️Contribuiți cu reguli", + save: "Salvați", + loadingText: "Se încarcă...", + opacity: "Opacitate", + opacityPlaceholder: "0: ascundeți distanțierul", + hideBar: "Ascundeți distanțierul de paginare", + hideBarButNoStop: "Ascundeți, dar nu opriți", + dbClick2Stop: "Faceți dublu clic pe spațiul gol pentru a întrerupe", + sortTitle: "Sortarea intră în vigoare după următoarea actualizare a regulilor", + autoRun: "Activare automată (mod listă neagră)", + autoLoadNum: "Cantitatea de pagini de preîncărcat", + turnRate: "Întoarceți la pagina următoare când este mai puțin de 【X】 ori înălțimea paginii de la subsol", + inputPageNum: "Introduceți numărul paginii pentru a sări", + enableHistory: "Scrieți istoricul de navigare după întoarcerea paginii", + enableHistoryAfterInsert: "Scrieți istoricul de navigare imediat după îmbinare, altfel scrieți după navigare", + contentVisibility: "Comutați automat vizibilitatea conținutului pentru a îmbunătăți performanța de randare", + initRun: "Întoarceți paginile imediat după deschidere", + preload: "Preîncărcați pagina următoare pentru a accelera", + click2ImportRule: "Faceți clic pentru a importa linkul regulilor de bază, apoi așteptați până la finalizarea actualizării: ", + forceAllBody: "Alăturați corpul complet al paginii?", + openInNewTab: "Deschideți URL-urile adăugirilor într-o filă nouă", + importSucc: "Import finalizat", + import: "Importați", + editCurrent: "Editați regula pentru site-ul web curent", + editBlacklist: "Editați lista neagră de URL-uri, o intrare pe linie, suportă caracterele [?,*].", + upBtnImg: "Pictogramă înapoi sus", + downBtnImg: "Pictogramă mergi la subsol", + sideControllerIcon: "Pictogramă bară laterală", + loadingTextTitle: "Se încarcă", + dbClick2StopCtrl: "Tasta Ctrl", + dbClick2StopAlt: "Tasta Alt", + dbClick2StopShift: "Tasta Shift", + dbClick2StopMeta: "Tasta Meta", + dbClick2StopKey: "Tastă de comandă rapidă", + pageElementCss: "Stil personalizat pentru elementele principale ale paginii", + customCss: "CSS complet personalizat", + firstAlert: "Nu ați importat regula de bază, vă rugăm să selectați regula corespunzătoare pentru a o importa", + picker: "Selector de elemente Pagetual", + closePicker: "Închideți selectorul Pagetual", + pickerPlaceholder: "Selector de elemente (Doar utilizatori avansați, altfel lăsați necompletat)", + pickerCheck: "Verificați selectorul și copiați", + switchSelector: "Faceți clic pentru a comuta elementul", + gotoEdit: "Mergeți la editarea regulii cu selectorul curent", + manualMode: "Dezactivați îmbinarea, avansați manual la pagina următoare folosind tasta săgeată dreapta (sau trimiteți evenimentul 'pagetual.next')", + clickMode: "Dezactivați îmbinarea, faceți clic automat pe pagina următoare la derularea până la sfârșitul paginii", + pageBarMenu: "Faceți clic în centrul barei de pagină pentru a deschide meniul selectorului", + nextSwitch: "Comutați linkul următor", + arrowToScroll: "Apăsați săgeata stânga pentru a derula înapoi și săgeata dreapta pentru a avansa pagina", + sideController: "Afișați bara de control a paginării în bara laterală", + sideControllerScroll: "Comutare derulare", + sideControllerAlways: "Afișați întotdeauna", + hideLoadingIcon: "Ascundeți animația de încărcare", + hideBarArrow: "Ascundeți săgeata pentru bara de pagină", + duplicate: "Pagetual duplicat a fost instalat, verificați managerul de scripturi!", + forceStateIframe: "Încorporați pagina completă ca iframe", + forceStateDynamic: "Încărcați conținut dinamic prin iframe", + forceStateDisable: "Dezactivați întoarcerea paginii pe acest site", + autoScrollRate: "Viteza de derulare (1~1000)", + disableAutoScroll: "Opriți derularea automată", + enableAutoScroll: "Activați derularea automată", + toggleAutoScroll: "Comutați derularea automată", + ruleRequest: "Cerere de regulă", + page: "Pagina ", + prevPage: "Pagina anterioară", + nextPage: "Pagina următoare", + errorRulesMustBeArray: "Regulile trebuie să fie un tablou!", + errorJson: "Eroare JSON, verificați din nou!", + editSuccess: "Editat cu succes", + errorWrongUrl: "URL greșit, verificați din nou!", + errorAlreadyExists: "O regulă există deja!", + settingsSaved: "Setările sunt salvate, reîmprospătați pentru a vizualiza", + iframe: "Divizare forțată de iframe", + dynamic: "Încărcare dinamică", + reloadPage: "Editare finalizată, reîncărcați acum?", + copied: "Copiat", + noValidContent: "Nu s-a detectat niciun conținut valid, este posibil să existe un Captcha", + outOfDate: "Scriptul este învechit, vă rugăm să actualizați la cea mai recentă versiune.", + hideBarTips: "Ascundeți bara de paginare, comutați experiența imersivă", + setConfigPage: "Setați pagina curentă ca pagină de configurare implicită", + wedata2github: "Schimbați adresa wedata cu adresa oglindă din depozitul github", + addOtherProp: "Adăugați proprietăți de regulă", + addNextSelector: "Adăugați conținutul selectorului ca nextLink", + addPageSelector: "Adăugați conținutul selectorului ca pageElement", + propName: "Introduceți numele proprietății regulii", + propValue: "Introduceți valoarea proprietății regulii", + customFirst: "Ignorați memoria cache pentru regulile personalizate locale", + rulesExample: "Exemplu de reguli", + lastPage: "Ați ajuns la ultima pagină", + lastPageTips: "Afișați sfaturi la atingerea ultimei pagini" + } + }, + { + name: "Suomi", + match: ["fi"], + lang: { + enableDebug: "Ota virheenkorjaustuloste käyttöön konsolissa", + updateNotification: "Ilmoitus sääntöjen päivityksen jälkeen", + disable: "Poista väliaikaisesti käytöstä", + disableSite: "Vaihda käytöstä poistettu tila", + disableSiteTips: "Poistettu käytöstä tällä sivustolla.", + enableSiteTips: "Otettu käyttöön tällä sivustolla.", + enable: "✅Ota automaattinen sivunvaihto käyttöön", + tempActive: "Väliaikaisesti aktiivinen", + toTop: "Takaisin ylös.", + toBottom: "Mene alas.", + current: "Nykyinen sivu.", + forceIframe: "Pakota liittymään seuraavalle sivulle", + cancelForceIframe: "Peruuta pakotettu liittyminen", + configure: "Määritä Pagetual", + firstUpdate: "Napsauta tästä alustaaksesi oletussääntöluettelon", + update: "Päivitä verkkosäännöt", + click2update: "Napsauta päivittääksesi säännöt URL-osoitteesta nyt", + loadNow: "Lataa seuraava automaattisesti", + loadConfirm: "Kuinka monta sivua haluat ladata? (0 tarkoittaa ääretöntä)", + noNext: "Seuraavaa linkkiä ei löytynyt, luo uusi sääntö", + passSec: "Päivitetty #t# sekuntia sitten", + passMin: "Päivitetty #t# minuuttia sitten", + passHour: "Päivitetty #t# tuntia sitten", + passDay: "Päivitetty #t# päivää sitten", + cantDel: "Sisäänrakennettuja sääntöjä ei voi poistaa", + confirmDel: "Haluatko varmasti poistaa tämän säännön?", + updateSucc: "Päivitys onnistui", + beginUpdate: "Aloitetaan päivitys, odota hetki", + customUrls: "Tuo Pagetual- tai AutoPagerize-säännön URL-osoite, yksi URL-osoite riviä kohti.", + customRules: "Syötä mukautettuja sääntöjä. ✍️Osallistu sääntöihin", + save: "Tallenna", + loadingText: "Ladataan...", + opacity: "Läpinäkyvyys", + opacityPlaceholder: "0: piilota välilevy", + hideBar: "Piilota sivutuksen välilevy", + hideBarButNoStop: "Piilota, mutta älä pysäytä", + dbClick2Stop: "Kaksoisnapsauta tyhjää tilaa keskeyttääksesi", + sortTitle: "Lajittelu tulee voimaan seuraavan sääntöpäivityksen jälkeen", + autoRun: "Ota automaattisesti käyttöön (mustan listan tila)", + autoLoadNum: "Esiladattavien sivujen määrä", + turnRate: "Vaihda seuraavalle sivulle, kun se on alle 【X】 kertaa sivun korkeuden päässä alatunnisteesta", + inputPageNum: "Syötä sivunumero siirtyäksesi", + enableHistory: "Kirjoita selaushistoria sivunvaihdon jälkeen", + enableHistoryAfterInsert: "Kirjoita selaushistoria heti liittämisen jälkeen, muuten kirjoita selauksen jälkeen", + contentVisibility: "Vaihda automaattisesti sisällön näkyvyyttä parantaaksesi renderöintisuorituskykyä", + initRun: "Vaihda sivuja heti avaamisen jälkeen", + preload: "Esilataa seuraava sivu nopeuttaaksesi", + click2ImportRule: "Napsauta tuodaksesi perussääntöjen linkin ja odota sitten, kunnes päivitys on valmis: ", + forceAllBody: "Liitetäänkö sivun koko runko?", + openInNewTab: "Avaa lisäysten URL-osoitteet uudessa välilehdessä", + importSucc: "Tuonti onnistui", + import: "Tuo", + editCurrent: "Muokkaa nykyisen verkkosivuston sääntöä", + editBlacklist: "Muokkaa URL-mustaa listaa, yksi merkintä riviä kohti, tukee [?,*] -jokerimerkkejä.", + upBtnImg: "Takaisin ylös -kuvake", + downBtnImg: "Mene alatunnisteeseen -kuvake", + sideControllerIcon: "Sivupalkin kuvake", + loadingTextTitle: "Ladataan", + dbClick2StopCtrl: "Ctrl-näppäin", + dbClick2StopAlt: "Alt-näppäin", + dbClick2StopShift: "Shift-näppäin", + dbClick2StopMeta: "Meta-näppäin", + dbClick2StopKey: "Pikakuvake", + pageElementCss: "Mukautettu tyyli pääsivun elementeille", + customCss: "Mukautettu täydellinen CSS", + firstAlert: "Et ole tuonut perussääntöä, valitse sopiva sääntö tuotavaksi", + picker: "Pagetual-elementin valitsin", + closePicker: "Sulje Pagetual-valitsin", + pickerPlaceholder: "Elementin valitsin (Vain edistyneille käyttäjille, muuten jätä tyhjäksi)", + pickerCheck: "Tarkista valitsin ja kopioi", + switchSelector: "Napsauta vaihtaaksesi elementtiä", + gotoEdit: "Siirry muokkaamaan sääntöä nykyisellä valitsimella", + manualMode: "Poista liittäminen käytöstä, siirry manuaalisesti seuraavalle sivulle oikealla nuolinäppäimellä (tai lähetä tapahtuma 'pagetual.next')", + clickMode: "Poista liittäminen käytöstä, napsauta automaattisesti seuraavaa sivua, kun vierität sivun loppuun", + pageBarMenu: "Napsauta sivupalkin keskustaa avataksesi valitsinvalikon", + nextSwitch: "Vaihda seuraava linkki", + arrowToScroll: "Paina vasenta nuolta selataksesi taaksepäin ja oikeaa nuolta siirtyäksesi sivulle", + sideController: "Näytä sivutuksen ohjauspalkki sivupalkissa", + sideControllerScroll: "Vierityksen vaihto", + sideControllerAlways: "Näytä aina", + hideLoadingIcon: "Piilota latausanimaatio", + hideBarArrow: "Piilota nuoli sivupalkille", + duplicate: "Pagetualin kaksoiskappale on asennettu, tarkista komentosarjojen hallinta!", + forceStateIframe: "Upota koko sivu iframeksi", + forceStateDynamic: "Lataa dynaamista sisältöä iframen kautta", + forceStateDisable: "Poista sivunvaihto käytöstä tällä sivustolla", + autoScrollRate: "Vieritysnopeus (1-1000)", + disableAutoScroll: "Pysäytä automaattinen vieritys", + enableAutoScroll: "Ota automaattinen vieritys käyttöön", + toggleAutoScroll: "Vaihda automaattista vieritystä", + ruleRequest: "Sääntöpyyntö", + page: "Sivu ", + prevPage: "Edellinen sivu", + nextPage: "Seuraava sivu", + errorRulesMustBeArray: "Sääntöjen on oltava taulukko!", + errorJson: "JSON-virhe, tarkista uudelleen!", + editSuccess: "Muokkaus onnistui", + errorWrongUrl: "Väärä URL-osoite, tarkista uudelleen!", + errorAlreadyExists: "Sääntö on jo olemassa!", + settingsSaved: "Asetukset on tallennettu, päivitä nähdäksesi", + iframe: "Pakotettu jako iframella", + dynamic: "Dynaaminen lataus", + reloadPage: "Muokkaus valmis, ladataanko uudelleen nyt?", + copied: "Kopioitu", + noValidContent: "Kelvollista sisältöä ei havaittu, Captcha saattaa olla läsnä", + outOfDate: "Komentosarja on vanhentunut, päivitä uusimpaan versioon.", + hideBarTips: "Piilota sivutuspalkki, vaihda immersiiviseen kokemukseen", + setConfigPage: "Aseta nykyinen sivu oletusmäärityssivuksi", + wedata2github: "Vaihda wedata-osoite github-arkiston peiliosoitteeseen", + addOtherProp: "Lisää säännön ominaisuuksia", + addNextSelector: "Lisää valitsimen sisältö nimellä nextLink", + addPageSelector: "Lisää valitsimen sisältö nimellä pageElement", + propName: "Syötä säännön ominaisuuden nimi", + propValue: "Syötä säännön ominaisuuden arvo", + customFirst: "Ohita välimuisti paikallisille mukautetuille säännöille", + rulesExample: "Sääntöesimerkki", + lastPage: "Viimeinen sivu saavutettu", + lastPageTips: "Näytä vinkkejä, kun saavutaan viimeiselle sivulle" + } + }, + { + name: "Ελληνικά", + match: ["el"], + lang: { + enableDebug: "Ενεργοποίηση εξόδου εντοπισμού σφαλμάτων στην κονσόλα", + updateNotification: "Ειδοποίηση μετά την ενημέρωση των κανόνων", + disable: "Προσωρινή απενεργοποίηση", + disableSite: "Εναλλαγή κατάστασης απενεργοποίησης", + disableSiteTips: "Απενεργοποιημένο σε αυτόν τον ιστότοπο.", + enableSiteTips: "Ενεργοποιημένο σε αυτόν τον ιστότοπο.", + enable: "✅Ενεργοποίηση αυτόματης αλλαγής σελίδας", + tempActive: "Προσωρινά ενεργό", + toTop: "Επιστροφή στην κορυφή.", + toBottom: "Μετάβαση στο κάτω μέρος.", + current: "Τρέχουσα σελίδα.", + forceIframe: "Εξαναγκασμός συμμετοχής στην επόμενη σελίδα", + cancelForceIframe: "Ακύρωση εξαναγκασμένης συμμετοχής", + configure: "Διαμόρφωση Pagetual", + firstUpdate: "Κάντε κλικ εδώ για να αρχικοποιήσετε την προεπιλεγμένη λίστα κανόνων", + update: "Ενημέρωση διαδικτυακών κανόνων", + click2update: "Κάντε κλικ για να ενημερώσετε τους κανόνες από το URL τώρα", + loadNow: "Φόρτωση του επόμενου αυτόματα", + loadConfirm: "Πόσες σελίδες θέλετε να φορτώσετε; (0 σημαίνει άπειρο)", + noNext: "Δεν βρέθηκε επόμενος σύνδεσμος, δημιουργήστε έναν νέο κανόνα", + passSec: "Ενημερώθηκε πριν από #t# δευτερόλεπτα", + passMin: "Ενημερώθηκε πριν από #t# λεπτά", + passHour: "Ενημερώθηκε πριν από #t# ώρες", + passDay: "Ενημερώθηκε πριν από #t# ημέρες", + cantDel: "Δεν είναι δυνατή η διαγραφή ενσωματωμένων κανόνων", + confirmDel: "Είστε βέβαιοι ότι θέλετε να διαγράψετε αυτόν τον κανόνα;", + updateSucc: "Η ενημέρωση ολοκληρώθηκε με επιτυχία", + beginUpdate: "Έναρξη ενημέρωσης, περιμένετε μια στιγμή", + customUrls: "Εισαγωγή URL κανόνα Pagetual ή AutoPagerize, ένα URL ανά γραμμή.", + customRules: "Εισαγωγή προσαρμοσμένων κανόνων. ✍️Συνεισφέρετε κανόνες", + save: "Αποθήκευση", + loadingText: "Φόρτωση...", + opacity: "Αδιαφάνεια", + opacityPlaceholder: "0: απόκρυψη διαχωριστικού", + hideBar: "Απόκρυψη του διαχωριστικού σελιδοποίησης", + hideBarButNoStop: "Απόκρυψη αλλά όχι διακοπή", + dbClick2Stop: "Κάντε διπλό κλικ στον κενό χώρο για παύση", + sortTitle: "Η ταξινόμηση τίθεται σε ισχύ μετά την επόμενη ενημέρωση κανόνων", + autoRun: "Αυτόματη ενεργοποίηση (λειτουργία μαύρης λίστας)", + autoLoadNum: "Ποσότητα για προφόρτωση σελίδων", + turnRate: "Μετάβαση στην επόμενη σελίδα όταν απέχει λιγότερο από 【X】 φορές το ύψος της σελίδας από το υποσέλιδο", + inputPageNum: "Εισαγάγετε τον αριθμό σελίδας για μετάβαση", + enableHistory: "Εγγραφή ιστορικού περιήγησης μετά την αλλαγή σελίδας", + enableHistoryAfterInsert: "Εγγραφή ιστορικού περιήγησης αμέσως μετά τη συγκόλληση, διαφορετικά εγγραφή μετά την περιήγηση", + contentVisibility: "Αυτόματη εναλλαγή της ορατότητας περιεχομένου για βελτίωση της απόδοσης απόδοσης", + initRun: "Αλλαγή σελίδων αμέσως μετά το άνοιγμα", + preload: "Προφόρτωση της επόμενης σελίδας για επιτάχυνση", + click2ImportRule: "Κάντε κλικ για να εισαγάγετε τον σύνδεσμο των βασικών κανόνων και, στη συνέχεια, περιμένετε μέχρι να ολοκληρωθεί η ενημέρωση: ", + forceAllBody: "Συμμετοχή ολόκληρου του σώματος της σελίδας;", + openInNewTab: "Άνοιγμα των URL των προσθηκών σε νέα καρτέλα", + importSucc: "Η εισαγωγή ολοκληρώθηκε", + import: "Εισαγωγή", + editCurrent: "Επεξεργασία κανόνα για τον τρέχοντα ιστότοπο", + editBlacklist: "Επεξεργαστείτε τη μαύρη λίστα URL, μία καταχώριση ανά γραμμή, υποστηρίζει μπαλαντέρ [?,*].", + upBtnImg: "Εικονίδιο επιστροφής στην κορυφή", + downBtnImg: "Εικονίδιο μετάβασης στο υποσέλιδο", + sideControllerIcon: "Εικονίδιο πλευρικής γραμμής", + loadingTextTitle: "Φόρτωση", + dbClick2StopCtrl: "Πλήκτρο Ctrl", + dbClick2StopAlt: "Πλήκτρο Alt", + dbClick2StopShift: "Πλήκτρο Shift", + dbClick2StopMeta: "Πλήκτρο Meta", + dbClick2StopKey: "Πλήκτρο συντόμευσης", + pageElementCss: "Προσαρμοσμένο στυλ για τα κύρια στοιχεία της σελίδας", + customCss: "Προσαρμοσμένο πλήρες CSS", + firstAlert: "Δεν έχετε εισαγάγει τον βασικό κανόνα, επιλέξτε τον κατάλληλο κανόνα για εισαγωγή", + picker: "Επιλογέας στοιχείων Pagetual", + closePicker: "Κλείσιμο του επιλογέα Pagetual", + pickerPlaceholder: "Επιλογέας στοιχείων (Μόνο για προχωρημένους χρήστες, αλλιώς αφήστε κενό)", + pickerCheck: "Έλεγχος επιλογέα και αντιγραφή", + switchSelector: "Κάντε κλικ για εναλλαγή στοιχείου", + gotoEdit: "Μετάβαση στην επεξεργασία κανόνα με τον τρέχοντα επιλογέα", + manualMode: "Απενεργοποίηση συγκόλλησης, μη αυτόματη μετάβαση στην επόμενη σελίδα χρησιμοποιώντας το δεξί βέλος (ή αποστολή συμβάντος 'pagetual.next')", + clickMode: "Απενεργοποίηση συγκόλλησης, αυτόματο κλικ στην επόμενη σελίδα κατά την κύλιση στο τέλος της σελίδας", + pageBarMenu: "Κάντε κλικ στο κέντρο της γραμμής σελίδας για να ανοίξετε το μενού επιλογέα", + nextSwitch: "Εναλλαγή επόμενου συνδέσμου", + arrowToScroll: "Πατήστε το αριστερό βέλος για κύλιση προς τα πίσω και το δεξί βέλος για μετάβαση στη σελίδα", + sideController: "Εμφάνιση της γραμμής ελέγχου σελιδοποίησης στην πλευρική γραμμή", + sideControllerScroll: "Εναλλαγή κύλισης", + sideControllerAlways: "Πάντα εμφάνιση", + hideLoadingIcon: "Απόκρυψη κινούμενης εικόνας φόρτωσης", + hideBarArrow: "Απόκρυψη βέλους για τη γραμμή σελίδας", + duplicate: "Έχει εγκατασταθεί διπλότυπο Pagetual, ελέγξτε τον διαχειριστή σεναρίων σας!", + forceStateIframe: "Ενσωμάτωση ολόκληρης της σελίδας ως iframe", + forceStateDynamic: "Φόρτωση δυναμικού περιεχομένου μέσω iframe", + forceStateDisable: "Απενεργοποίηση αλλαγής σελίδας σε αυτόν τον ιστότοπο", + autoScrollRate: "Ταχύτητα κύλισης (1~1000)", + disableAutoScroll: "Διακοπή αυτόματης κύλισης", + enableAutoScroll: "Ενεργοποίηση αυτόματης κύλισης", + toggleAutoScroll: "Εναλλαγή αυτόματης κύλισης", + ruleRequest: "Αίτημα κανόνα", + page: "Σελίδα ", + prevPage: "Προηγούμενη σελίδα", + nextPage: "Επόμενη σελίδα", + errorRulesMustBeArray: "Οι κανόνες πρέπει να είναι πίνακας!", + errorJson: "Σφάλμα JSON, ελέγξτε ξανά!", + editSuccess: "Η επεξεργασία ολοκληρώθηκε με επιτυχία", + errorWrongUrl: "Λάθος URL, ελέγξτε ξανά!", + errorAlreadyExists: "Ένας κανόνας υπάρχει ήδη!", + settingsSaved: "Οι ρυθμίσεις αποθηκεύτηκαν, ανανεώστε για προβολή", + iframe: "Εξαναγκασμένος διαχωρισμός από iframe", + dynamic: "Δυναμική φόρτωση", + reloadPage: "Η επεξεργασία ολοκληρώθηκε, επαναφόρτωση τώρα;", + copied: "Αντιγράφηκε", + noValidContent: "Δεν εντοπίστηκε έγκυρο περιεχόμενο, ενδέχεται να υπάρχει Captcha", + outOfDate: "Το σενάριο είναι ξεπερασμένο, ενημερώστε στην πιο πρόσφατη έκδοση.", + hideBarTips: "Απόκρυψη της γραμμής σελιδοποίησης, εναλλαγή καθηλωτικής εμπειρίας", + setConfigPage: "Ορισμός της τρέχουσας σελίδας ως προεπιλεγμένης σελίδας διαμόρφωσης", + wedata2github: "Αλλάξτε τη διεύθυνση wedata στη διεύθυνση καθρέφτη στο αποθετήριο github", + addOtherProp: "Προσθήκη ιδιοτήτων κανόνα", + addNextSelector: "Προσθήκη περιεχομένου επιλογέα ως nextLink", + addPageSelector: "Προσθήκη περιεχομένου επιλογέα ως pageElement", + propName: "Εισαγάγετε το όνομα ιδιότητας κανόνα", + propValue: "Εισαγάγετε την τιμή ιδιότητας κανόνα", + customFirst: "Παράβλεψη κρυφής μνήμης για τοπικούς προσαρμοσμένους κανόνες", + rulesExample: "Παράδειγμα κανόνων", + lastPage: "Φτάσατε στην τελευταία σελίδα", + lastPageTips: "Εμφάνιση συμβουλών κατά την άφιξη στην τελευταία σελίδα" + } + }, + { + name: "Esperanto", + match: ["eo"], + lang: { + enableDebug: "Aktivigi sencimigan eligon al la konzolo", + updateNotification: "Sciigo post ĝisdatigo de reguloj", + disable: "Provizore malŝalti", + disableSite: "Baskuligi malŝaltitan staton", + disableSiteTips: "Malŝaltita en ĉi tiu retejo.", + enableSiteTips: "Ŝaltita en ĉi tiu retejo.", + enable: "✅Aktivigi aŭtomatan paĝo-turnadon", + tempActive: "Provizore aktiva", + toTop: "Reen al supro.", + toBottom: "Iri al malsupro.", + current: "Nuna paĝo.", + forceIframe: "Devigi kunigon de la sekva paĝo", + cancelForceIframe: "Nuligi devigitan kunigon", + configure: "Agordi Pagetual", + firstUpdate: "Klaku ĉi tie por pravalorizi la defaŭltan regul-liston", + update: "Ĝisdatigi retajn regulojn", + click2update: "Klaku por ĝisdatigi regulojn el URL nun", + loadNow: "Ŝargi la sekvan aŭtomate", + loadConfirm: "Kiom da paĝoj vi volas ŝargi? (0 signifas senfine)", + noNext: "Neniu sekva ligilo trovita, bonvolu krei novan regulon", + passSec: "Ĝisdatigita antaŭ #t# sekundoj", + passMin: "Ĝisdatigita antaŭ #t# minutoj", + passHour: "Ĝisdatigita antaŭ #t# horoj", + passDay: "Ĝisdatigita antaŭ #t# tagoj", + cantDel: "Ne eblas forigi enkonstruitajn regulojn", + confirmDel: "Ĉu vi certas, ke vi volas forigi ĉi tiun regulon?", + updateSucc: "Ĝisdatigo sukcesis", + beginUpdate: "Komencante ĝisdatigon, bonvolu atendi momenton", + customUrls: "Importi regulan URL de Pagetual aŭ AutoPagerize, unu URL po linio.", + customRules: "Enigu proprajn regulojn. ✍️Kontribui regulojn", + save: "Konservi", + loadingText: "Ŝargante...", + opacity: "Opakeco", + opacityPlaceholder: "0: kaŝi apartigilon", + hideBar: "Kaŝi la paĝrangan apartigilon", + hideBarButNoStop: "Kaŝi sed ne haltigi", + dbClick2Stop: "Duoble-klaku sur la malplena spaco por paŭzi", + sortTitle: "Ordigo efektiviĝas post la sekva ĝisdatigo de reguloj", + autoRun: "Aŭtomata aktivigo (nigra listo reĝimo)", + autoLoadNum: "Kvanto por antaŭŝargitaj paĝoj", + turnRate: "Turnu la sekvan paĝon kiam ĝi estas malpli ol 【X】 fojojn la paĝa alteco de la piedlinio", + inputPageNum: "Enigu paĝan numeron por salti", + enableHistory: "Skribi foliumhistorion post paĝo-turnado", + enableHistoryAfterInsert: "Skribi foliumhistorion tuj post kunigo, alie skribi post foliumado", + contentVisibility: "Aŭtomate baskuligi enhavan videblecon por plibonigi bildigan rendimenton", + initRun: "Turni paĝojn tuj post malfermo", + preload: "Antaŭŝargi la sekvan paĝon por rapidigi", + click2ImportRule: "Klaku por importi bazan regulan ligilon, kaj poste atendu ĝis la ĝisdatigo finiĝos: ", + forceAllBody: "Kunigi la plenan korpon de la paĝo?", + openInNewTab: "Malfermi URL-ojn de aldonoj en nova langeto", + importSucc: "Importado finiĝis", + import: "Importi", + editCurrent: "Redakti regulon por la nuna retejo", + editBlacklist: "Redakti la nigran liston de URL-oj, unu enigo po linio, subtenas [?,*] ĵokerojn.", + upBtnImg: "Ikono por reen al supro", + downBtnImg: "Ikono por iri al piedlinio", + sideControllerIcon: "Ikono de flanka stango", + loadingTextTitle: "Ŝargante", + dbClick2StopCtrl: "Klavo Ctrl", + dbClick2StopAlt: "Klavo Alt", + dbClick2StopShift: "Klavo Shift", + dbClick2StopMeta: "Klavo Meta", + dbClick2StopKey: "Fulmoklavo", + pageElementCss: "Propra stilo por ĉefaj paĝaj elementoj", + customCss: "Propra kompleta CSS", + firstAlert: "Vi ne importis la bazan regulon, bonvolu elekti la taŭgan regulon por importi", + picker: "Pagetual elementa elektilo", + closePicker: "Fermi la elektilon de Pagetual", + pickerPlaceholder: "Elementa elektilo (Nur por spertaj uzantoj, alie lasu malplena)", + pickerCheck: "Kontroli elektilon kaj kopii", + switchSelector: "Klaku por ŝanĝi elementon", + gotoEdit: "Iri al redakto de regulo kun la nuna elektilo", + manualMode: "Malŝalti kunigon, permane antaŭeniri al la sekva paĝo per la dekstra sagoklavo (aŭ sendi eventon 'pagetual.next')", + clickMode: "Malŝalti kunigon, aŭtomate alklaki la sekvan paĝon rulumante ĝis la fino de la paĝo", + pageBarMenu: "Klaku la centron de la paĝa stango por malfermi la elektilan menuon", + nextSwitch: "Ŝanĝi la sekvan ligilon", + arrowToScroll: "Premu la maldekstran sagon por rulumigi reen kaj la dekstran sagon por antaŭeniri paĝon", + sideController: "Montri la paĝrangan kontrolstangon en la flanka stango", + sideControllerScroll: "Rulumiga baskulo", + sideControllerAlways: "Ĉiam montri", + hideLoadingIcon: "Kaŝi ŝargan animacion", + hideBarArrow: "Kaŝi sagon por la paĝa stango", + duplicate: "Duplikata Pagetual estis instalita, kontrolu vian skript-administrilon!", + forceStateIframe: "Enigi plenan paĝon kiel iframe", + forceStateDynamic: "Ŝargi dinamikan enhavon per iframe", + forceStateDisable: "Malŝalti paĝo-turnadon en ĉi tiu retejo", + autoScrollRate: "Rulumrapido (1~1000)", + disableAutoScroll: "Haltigi Aŭtomatan Rulumadon", + enableAutoScroll: "Aktivigi Aŭtomatan Rulumadon", + toggleAutoScroll: "Baskuligi Aŭtomatan Rulumadon", + ruleRequest: "Regula Peto", + page: "Paĝo ", + prevPage: "Antaŭa paĝo", + nextPage: "Sekva paĝo", + errorRulesMustBeArray: "Reguloj devas esti tabelo!", + errorJson: "JSON-eraro, Rekontrolu!", + editSuccess: "Sukcese redaktita", + errorWrongUrl: "Malĝusta URL, Rekontrolu!", + errorAlreadyExists: "Regulo jam ekzistas!", + settingsSaved: "La agordoj estas konservitaj, refreŝigu por vidi", + iframe: "Devigita disigo per iframe", + dynamic: "Dinamika ŝargado", + reloadPage: "Redakto finiĝis, ĉu reŝargi nun?", + copied: "Kopiita", + noValidContent: "Neniu valida enhavo detektita, Captcha eble ĉeestas", + outOfDate: "La skripto estas malmoderna, bonvolu ĝisdatigi al la plej nova versio.", + hideBarTips: "Kaŝi la paĝrangan stangon, baskuligi imersivan sperton", + setConfigPage: "Agordi la nunan paĝon kiel la defaŭltan agordan paĝon", + wedata2github: "Ŝanĝi la wedata-adreson al la spegula adreso en la github-deponejo", + addOtherProp: "Aldoni regulajn ecojn", + addNextSelector: "Aldoni elektilan enhavon kiel nextLink", + addPageSelector: "Aldoni elektilan enhavon kiel pageElement", + propName: "Enigu regulan econan nomon", + propValue: "Enigu regulan econan valoron", + customFirst: "Ignori kaŝmemoron por lokaj propraj reguloj", + rulesExample: "Regula Ekzemplo", + lastPage: "Atingis la lastan paĝon", + lastPageTips: "Montri konsilojn atinginte la lastan paĝon" + } + }, + { + name: "Български", + match: ["bg"], + lang: { + enableDebug: "Активиране на изход за отстраняване на грешки в конзолата", + updateNotification: "Известие след актуализиране на правилата", + disable: "Временно деактивиране", + disableSite: "Превключване на деактивирано състояние", + disableSiteTips: "Деактивирано на този сайт.", + enableSiteTips: "Активирано на този сайт.", + enable: "✅Активиране на автоматично прелистване на страници", + tempActive: "Временно активно", + toTop: "Обратно горе.", + toBottom: "Към дъното.", + current: "Текуща страница.", + forceIframe: "Принудително присъединяване към следващата страница", + cancelForceIframe: "Отказ от принудително присъединяване", + configure: "Конфигуриране на Pagetual", + firstUpdate: "Щракнете тук, за да инициализирате списъка с правила по подразбиране", + update: "Актуализиране на онлайн правилата", + click2update: "Щракнете, за да актуализирате правилата от URL сега", + loadNow: "Зареждане на следващото автоматично", + loadConfirm: "Колко страници искате да заредите? (0 означава безкрайност)", + noNext: "Няма намерена следваща връзка, моля, създайте ново правило", + passSec: "Актуализирано преди #t# секунди", + passMin: "Актуализирано преди #t# минути", + passHour: "Актуализирано преди #t# часа", + passDay: "Актуализирано преди #t# дни", + cantDel: "Не могат да се изтриват вградени правила", + confirmDel: "Сигурни ли сте, че искате да изтриете това правило?", + updateSucc: "Актуализацията е успешна", + beginUpdate: "Започва актуализация, моля, изчакайте малко", + customUrls: "Импортиране на URL на правило Pagetual или AutoPagerize, един URL на ред.", + customRules: "Въведете персонализирани правила. ✍️Допринесете с правила", + save: "Запазване", + loadingText: "Зареждане...", + opacity: "Непрозрачност", + opacityPlaceholder: "0: скриване на разделителя", + hideBar: "Скриване на разделителя за пагинация", + hideBarButNoStop: "Скриване, но не спиране", + dbClick2Stop: "Двоен клик върху празното пространство за пауза", + sortTitle: "Сортирането влиза в сила след следващата актуализация на правилата", + autoRun: "Автоматично активиране (режим на черен списък)", + autoLoadNum: "Количество за предварително заредени страници", + turnRate: "Превъртете на следващата страница, когато е на по-малко от 【X】 пъти височината на страницата от долния колонтитул", + inputPageNum: "Въведете номер на страница за прескачане", + enableHistory: "Записване на историята на сърфиране след прелистване на страница", + enableHistoryAfterInsert: "Записване на историята на сърфиране веднага след снаждане, в противен случай записване след сърфиране", + contentVisibility: "Автоматично превключване на видимостта на съдържанието за подобряване на производителността на изобразяване", + initRun: "Превъртане на страници веднага след отваряне", + preload: "Предварително зареждане на следващата страница за ускоряване", + click2ImportRule: "Щракнете, за да импортирате връзката към основните правила, и след това изчакайте, докато актуализацията приключи: ", + forceAllBody: "Присъединяване на цялото тяло на страницата?", + openInNewTab: "Отваряне на URL адресите на допълненията в нов раздел", + importSucc: "Импортирането е завършено", + import: "Импортиране", + editCurrent: "Редактиране на правило за текущия уебсайт", + editBlacklist: "Редактирайте черния списък с URL адреси, един запис на ред, поддържа заместващи символи [?,*].", + upBtnImg: "Икона за връщане горе", + downBtnImg: "Икона за преминаване към долния колонтитул", + sideControllerIcon: "Икона на страничната лента", + loadingTextTitle: "Зареждане", + dbClick2StopCtrl: "Клавиш Ctrl", + dbClick2StopAlt: "Клавиш Alt", + dbClick2StopShift: "Клавиш Shift", + dbClick2StopMeta: "Клавиш Meta", + dbClick2StopKey: "Клавишна комбинация", + pageElementCss: "Персонализиран стил за основните елементи на страницата", + customCss: "Персонализиран пълен CSS", + firstAlert: "Не сте импортирали основното правило, моля, изберете подходящото правило за импортиране", + picker: "Избор на елементи на Pagetual", + closePicker: "Затваряне на избора на Pagetual", + pickerPlaceholder: "Избор на елементи (Само за напреднали потребители, в противен случай оставете празно)", + pickerCheck: "Проверка на селектора и копиране", + switchSelector: "Щракнете, за да превключите елемент", + gotoEdit: "Отидете на редактиране на правило с текущия селектор", + manualMode: "Деактивиране на снаждането, ръчно преминаване към следващата страница с помощта на десния клавиш със стрелка (или изпращане на събитие 'pagetual.next')", + clickMode: "Деактивиране на снаждането, автоматично щракване върху следващата страница при превъртане до края на страницата", + pageBarMenu: "Щракнете в центъра на лентата на страницата, за да отворите менюто за избор", + nextSwitch: "Превключване на следваща връзка", + arrowToScroll: "Натиснете лявата стрелка, за да превъртите назад, и дясната стрелка, за да преминете напред", + sideController: "Показване на контролната лента за пагинация в страничната лента", + sideControllerScroll: "Превключване на превъртането", + sideControllerAlways: "Винаги показване", + hideLoadingIcon: "Скриване на анимацията за зареждане", + hideBarArrow: "Скриване на стрелката за лентата на страницата", + duplicate: "Инсталиран е дубликат на Pagetual, проверете вашия мениджър на скриптове!", + forceStateIframe: "Вграждане на цялата страница като iframe", + forceStateDynamic: "Зареждане на динамично съдържание чрез iframe", + forceStateDisable: "Деактивиране на прелистването на страници на този сайт", + autoScrollRate: "Скорост на превъртане (1-1000)", + disableAutoScroll: "Спиране на автоматичното превъртане", + enableAutoScroll: "Активиране на автоматичното превъртане", + toggleAutoScroll: "Превключване на автоматичното превъртане", + ruleRequest: "Искане за правило", + page: "Страница ", + prevPage: "Предишна страница", + nextPage: "Следваща страница", + errorRulesMustBeArray: "Правилата трябва да са масив!", + errorJson: "Грешка в JSON, проверете отново!", + editSuccess: "Редактирането е успешно", + errorWrongUrl: "Грешен URL, проверете отново!", + errorAlreadyExists: "Правило вече съществува!", + settingsSaved: "Настройките са запазени, опреснете, за да видите", + iframe: "Принудително разделяне от iframe", + dynamic: "Динамично зареждане", + reloadPage: "Редактирането е завършено, презареждане сега?", + copied: "Копирано", + noValidContent: "Не е открито валидно съдържание, може да има Captcha", + outOfDate: "Скриптът е остарял, моля, актуализирайте до най-новата версия.", + hideBarTips: "Скрийте лентата за пагинация, превключете поглъщащото изживяване", + setConfigPage: "Задайте текущата страница като страница за конфигурация по подразбиране", + wedata2github: "Променете адреса на wedata на огледалния адрес в хранилището на github", + addOtherProp: "Добавяне на свойства на правилото", + addNextSelector: "Добавяне на съдържание на селектора като nextLink", + addPageSelector: "Добавяне на съдържание на селектора като pageElement", + propName: "Въведете име на свойството на правилото", + propValue: "Въведете стойност на свойството на правилото", + customFirst: "Игнориране на кеша за локални персонализирани правила", + rulesExample: "Пример за правила", + lastPage: "Достигната е последната страница", + lastPageTips: "Показване на съвети при достигане на последната страница" + } + }, + { + name: "Čeština", + match: ["cs"], + lang: { + enableDebug: "Povolit výstup ladění do konzole", + updateNotification: "Oznámení po aktualizaci pravidel", + disable: "Dočasně zakázat", + disableSite: "Přepnout stav zakázání", + disableSiteTips: "Na této stránce zakázáno.", + enableSiteTips: "Na této stránce povoleno.", + enable: "✅Povolit automatické otáčení stránek", + tempActive: "Dočasně aktivní", + toTop: "Zpět nahoru.", + toBottom: "Jít dolů.", + current: "Aktuální stránka.", + forceIframe: "Vynutit připojení k další stránce", + cancelForceIframe: "Zrušit vynucené připojení", + configure: "Konfigurovat Pagetual", + firstUpdate: "Klikněte sem pro inicializaci výchozího seznamu pravidel", + update: "Aktualizovat online pravidla", + click2update: "Klikněte pro aktualizaci pravidel z URL nyní", + loadNow: "Načíst další automaticky", + loadConfirm: "Kolik stránek chcete načíst? (0 znamená nekonečno)", + noNext: "Nenalezen žádný další odkaz, vytvořte nové pravidlo", + passSec: "Aktualizováno před #t# sekundami", + passMin: "Aktualizováno před #t# minutami", + passHour: "Aktualizováno před #t# hodinami", + passDay: "Aktualizováno před #t# dny", + cantDel: "Nelze odstranit vestavěná pravidla", + confirmDel: "Jste si jisti, že chcete toto pravidlo odstranit?", + updateSucc: "Aktualizace úspěšná", + beginUpdate: "Zahajuje se aktualizace, chvíli prosím počkejte", + customUrls: "Importovat URL pravidla Pagetual nebo AutoPagerize, jedno URL na řádek.", + customRules: "Zadejte vlastní pravidla. ✍️Přispějte pravidly", + save: "Uložit", + loadingText: "Načítání...", + opacity: "Neprůhlednost", + opacityPlaceholder: "0: skrýt oddělovač", + hideBar: "Skrýt oddělovač stránkování", + hideBarButNoStop: "Skrýt, ale nezastavit", + dbClick2Stop: "Dvojitým kliknutím na prázdné místo pozastavíte", + sortTitle: "Třídění se projeví po další aktualizaci pravidel", + autoRun: "Automatické povolení (režim černé listiny)", + autoLoadNum: "Množství pro přednačtené stránky", + turnRate: "Otočte na další stránku, když je méně než 【X】 násobek výšky stránky od zápatí", + inputPageNum: "Zadejte číslo stránky pro skok", + enableHistory: "Zapsat historii procházení po otočení stránky", + enableHistoryAfterInsert: "Zapsat historii procházení ihned po spojení, jinak zapsat po procházení", + contentVisibility: "Automaticky přepínat viditelnost obsahu pro zlepšení výkonu vykreslování", + initRun: "Otočit stránky ihned po otevření", + preload: "Přednačíst další stránku pro zrychlení", + click2ImportRule: "Klikněte pro import odkazu na základní pravidla a poté počkejte, dokud se aktualizace nedokončí: ", + forceAllBody: "Připojit celé tělo stránky?", + openInNewTab: "Otevřít URL adres přídavků v nové kartě", + importSucc: "Import dokončen", + import: "Importovat", + editCurrent: "Upravit pravidlo pro aktuální webovou stránku", + editBlacklist: "Upravit černou listinu URL, jeden záznam na řádek, podporuje zástupné znaky [?,*].", + upBtnImg: "Ikona zpět nahoru", + downBtnImg: "Ikona jít do zápatí", + sideControllerIcon: "Ikona bočního panelu", + loadingTextTitle: "Načítání", + dbClick2StopCtrl: "Klávesa Ctrl", + dbClick2StopAlt: "Klávesa Alt", + dbClick2StopShift: "Klávesa Shift", + dbClick2StopMeta: "Klávesa Meta", + dbClick2StopKey: "Klávesová zkratka", + pageElementCss: "Vlastní styl pro hlavní prvky stránky", + customCss: "Vlastní kompletní CSS", + firstAlert: "Neimportovali jste základní pravidlo, vyberte prosím vhodné pravidlo k importu", + picker: "Výběr prvků Pagetual", + closePicker: "Zavřít výběr Pagetual", + pickerPlaceholder: "Výběr prvků (Pouze pro pokročilé uživatele, jinak nechte prázdné)", + pickerCheck: "Zkontrolovat výběr a kopírovat", + switchSelector: "Kliknutím přepnete prvek", + gotoEdit: "Přejít na úpravu pravidla s aktuálním výběrem", + manualMode: "Zakázat spojování, ručně přejít na další stránku pomocí klávesy se šipkou doprava (nebo odeslat událost 'pagetual.next')", + clickMode: "Zakázat spojování, automaticky kliknout na další stránku při posunutí na konec stránky", + pageBarMenu: "Kliknutím na střed lišty stránky otevřete menu výběru", + nextSwitch: "Přepnout další odkaz", + arrowToScroll: "Stisknutím levé šipky se posunete zpět a pravou šipkou přejdete na stránku", + sideController: "Zobrazit ovládací panel stránkování v bočním panelu", + sideControllerScroll: "Přepnout posouvání", + sideControllerAlways: "Vždy zobrazit", + hideLoadingIcon: "Skrýt animaci načítání", + hideBarArrow: "Skrýt šipku pro lištu stránky", + duplicate: "Duplicitní Pagetual byl nainstalován, zkontrolujte svůj správce skriptů!", + forceStateIframe: "Vložit celou stránku jako iframe", + forceStateDynamic: "Načíst dynamický obsah přes iframe", + forceStateDisable: "Zakázat otáčení stránek на této stránce", + autoScrollRate: "Rychlost posouvání (1-1000)", + disableAutoScroll: "Zastavit automatické posouvání", + enableAutoScroll: "Povolit automatické posouvání", + toggleAutoScroll: "Přepnout automatické posouvání", + ruleRequest: "Žádost o pravidlo", + page: "Stránka ", + prevPage: "Předchozí stránka", + nextPage: "Další stránka", + errorRulesMustBeArray: "Pravidla musí být pole!", + errorJson: "Chyba JSON, zkontrolujte znovu!", + editSuccess: "Úspěšně upraveno", + errorWrongUrl: "Nesprávné URL, zkontrolujte znovu!", + errorAlreadyExists: "Pravidlo již existuje!", + settingsSaved: "Nastavení jsou uložena, obnovte pro zobrazení", + iframe: "Vynucené rozdělení pomocí iframe", + dynamic: "Dynamické načítání", + reloadPage: "Úprava dokončena, načíst znovu?", + copied: "Zkopírováno", + noValidContent: "Nebyl zjištěn žádný platný obsah, může být přítomna Captcha", + outOfDate: "Skript je zastaralý, aktualizujte prosím na nejnovější verzi.", + hideBarTips: "Skrýt lištu stránkování, přepnout pohlcující zážitek", + setConfigPage: "Nastavit aktuální stránku jako výchozí konfigurační stránku", + wedata2github: "Změnit adresu wedata na zrcadlovou adresu v repozitáři github", + addOtherProp: "Přidat vlastnosti pravidla", + addNextSelector: "Přidat obsah výběru jako nextLink", + addPageSelector: "Přidat obsah výběru jako pageElement", + propName: "Zadejte název vlastnosti pravidla", + propValue: "Zadejte hodnotu vlastnosti pravidla", + customFirst: "Ignorovat mezipaměť pro místní vlastní pravidla", + rulesExample: "Příklad pravidel", + lastPage: "Dosáhli jste poslední stránky", + lastPageTips: "Zobrazit tipy při dosažení poslední stránky" + } + }, + { + name: "Tiếng Việt", + match: ["vi"], + lang: { + enableDebug: "Bật đầu ra gỡ lỗi vào bảng điều khiển", + updateNotification: "Thông báo sau khi cập nhật quy tắc", + disable: "Tạm thời vô hiệu hóa", + disableSite: "Chuyển đổi trạng thái vô hiệu hóa", + disableSiteTips: "Đã vô hiệu hóa trên trang này.", + enableSiteTips: "Đã bật trên trang này.", + enable: "✅Bật tự động chuyển trang", + tempActive: "Tạm thời hoạt động", + toTop: "Quay lại đầu trang.", + toBottom: "Đi đến cuối trang.", + current: "Trang hiện tại.", + forceIframe: "Buộc tham gia trang tiếp theo", + cancelForceIframe: "Hủy bỏ buộc tham gia", + configure: "Cấu hình Pagetual", + firstUpdate: "Nhấp vào đây để khởi tạo danh sách quy tắc mặc định", + update: "Cập nhật quy tắc trực tuyến", + click2update: "Nhấp để cập nhật quy tắc từ url ngay bây giờ", + loadNow: "Tải trang tiếp theo tự động", + loadConfirm: "Bạn muốn tải bao nhiêu trang? (0 có nghĩa là vô hạn)", + noNext: "Không tìm thấy liên kết tiếp theo, vui lòng tạo quy tắc mới", + passSec: "Đã cập nhật #t# giây trước", + passMin: "Đã cập nhật #t# phút trước", + passHour: "Đã cập nhật #t# giờ trước", + passDay: "Đã cập nhật #t# ngày trước", + cantDel: "Không thể xóa các quy tắc cài sẵn", + confirmDel: "Bạn có chắc chắn muốn xóa quy tắc này không?", + updateSucc: "Cập nhật thành công", + beginUpdate: "Bắt đầu cập nhật, vui lòng đợi một lát", + customUrls: "Nhập URL quy tắc Pagetual hoặc AutoPagerize, mỗi URL một dòng.", + customRules: "Nhập các quy tắc tùy chỉnh. ✍️Đóng góp quy tắc", + save: "Lưu", + loadingText: "Đang tải...", + opacity: "Độ mờ", + opacityPlaceholder: "0: ẩn dấu phân cách", + hideBar: "Ẩn dấu phân cách phân trang", + hideBarButNoStop: "Ẩn nhưng không dừng", + dbClick2Stop: "Nhấp đúp vào khoảng trống để tạm dừng", + sortTitle: "Việc sắp xếp có hiệu lực sau khi cập nhật quy tắc tiếp theo", + autoRun: "Tự động bật (chế độ danh sách đen)", + autoLoadNum: "Số lượng trang tải trước", + turnRate: "Chuyển sang trang tiếp theo khi còn cách chân trang chưa đến 【X】 lần chiều cao trang", + inputPageNum: "Nhập số trang để chuyển đến", + enableHistory: "Ghi lại lịch sử duyệt web sau khi chuyển trang", + enableHistoryAfterInsert: "Ghi lại lịch sử duyệt web ngay sau khi ghép nối, nếu không thì ghi lại sau khi duyệt", + contentVisibility: "Tự động chuyển đổi khả năng hiển thị nội dung để cải thiện hiệu suất hiển thị", + initRun: "Chuyển trang ngay sau khi mở", + preload: "Tải trước trang tiếp theo để tăng tốc", + click2ImportRule: "Nhấp để nhập liên kết quy tắc cơ sở, sau đó đợi cho đến khi cập nhật hoàn tất: ", + forceAllBody: "Tham gia toàn bộ nội dung của trang?", + openInNewTab: "Mở các url bổ sung trong tab mới", + importSucc: "Nhập hoàn tất", + import: "Nhập", + editCurrent: "Chỉnh sửa quy tắc cho trang web hiện tại", + editBlacklist: "Chỉnh sửa danh sách đen url, mỗi mục một dòng, hỗ trợ ký tự đại diện [?,*].", + upBtnImg: "Biểu tượng quay lại đầu trang", + downBtnImg: "Biểu tượng đi đến chân trang", + sideControllerIcon: "Biểu tượng của thanh bên", + loadingTextTitle: "Đang tải", + dbClick2StopCtrl: "Phím Ctrl", + dbClick2StopAlt: "Phím Alt", + dbClick2StopShift: "Phím Shift", + dbClick2StopMeta: "Phím Meta", + dbClick2StopKey: "Phím tắt", + pageElementCss: "Kiểu tùy chỉnh cho các phần tử trang chính", + customCss: "CSS hoàn chỉnh tùy chỉnh", + firstAlert: "Bạn chưa nhập quy tắc cơ sở, vui lòng chọn quy tắc thích hợp để nhập", + picker: "Bộ chọn phần tử Pagetual", + closePicker: "Đóng bộ chọn Pagetual", + pickerPlaceholder: "Bộ chọn phần tử (Chỉ dành cho người dùng nâng cao, nếu không thì để trống)", + pickerCheck: "Kiểm tra bộ chọn và sao chép", + switchSelector: "Nhấp để chuyển đổi phần tử", + gotoEdit: "Chuyển đến chỉnh sửa quy tắc với bộ chọn hiện tại", + manualMode: "Vô hiệu hóa việc ghép nối, chuyển đến trang tiếp theo theo cách thủ công bằng phím mũi tên phải (hoặc gửi sự kiện 'pagetual.next')", + clickMode: "Vô hiệu hóa việc ghép nối, tự động nhấp vào trang tiếp theo khi cuộn đến cuối trang", + pageBarMenu: "Nhấp vào giữa thanh trang để mở menu bộ chọn", + nextSwitch: "Chuyển đổi liên kết tiếp theo", + arrowToScroll: "Nhấn mũi tên trái để cuộn lại và mũi tên phải để chuyển trang", + sideController: "Hiển thị thanh điều khiển phân trang trong thanh bên", + sideControllerScroll: "Chuyển đổi cuộn", + sideControllerAlways: "Luôn hiển thị", + hideLoadingIcon: "Ẩn hoạt ảnh tải", + hideBarArrow: "Ẩn mũi tên cho thanh trang", + duplicate: "Pagetual trùng lặp đã được cài đặt, hãy kiểm tra trình quản lý tập lệnh của bạn!", + forceStateIframe: "Nhúng toàn bộ trang dưới dạng iframe", + forceStateDynamic: "Tải nội dung động qua iframe", + forceStateDisable: "Vô hiệu hóa việc chuyển trang trên trang này", + autoScrollRate: "Tốc độ cuộn (1~1000)", + disableAutoScroll: "Dừng cuộn tự động", + enableAutoScroll: "Bật cuộn tự động", + toggleAutoScroll: "Chuyển đổi cuộn tự động", + ruleRequest: "Yêu cầu quy tắc", + page: "Trang ", + prevPage: "Trang trước", + nextPage: "Trang tiếp theo", + errorRulesMustBeArray: "Quy tắc phải là một mảng!", + errorJson: "Lỗi JSON, hãy kiểm tra lại!", + editSuccess: "Chỉnh sửa thành công", + errorWrongUrl: "URL sai, hãy kiểm tra lại!", + errorAlreadyExists: "Một quy tắc đã tồn tại!", + settingsSaved: "Cài đặt đã được lưu, hãy làm mới để xem", + iframe: "Tách bắt buộc bằng iframe", + dynamic: "Tải động", + reloadPage: "Chỉnh sửa hoàn tất, tải lại ngay bây giờ?", + copied: "Đã sao chép", + noValidContent: "Không phát hiện thấy nội dung hợp lệ, có thể có Captcha", + outOfDate: "Tập lệnh đã lỗi thời, vui lòng cập nhật lên phiên bản mới nhất.", + hideBarTips: "Ẩn thanh phân trang, chuyển đổi trải nghiệm đắm chìm", + setConfigPage: "Đặt trang hiện tại làm trang cấu hình mặc định", + wedata2github: "Thay đổi địa chỉ wedata thành địa chỉ nhân bản trong kho lưu trữ github", + addOtherProp: "Thêm thuộc tính quy tắc", + addNextSelector: "Thêm nội dung bộ chọn làm nextLink", + addPageSelector: "Thêm nội dung bộ chọn làm pageElement", + propName: "Nhập tên thuộc tính quy tắc", + propValue: "Nhập giá trị thuộc tính quy tắc", + customFirst: "Bỏ qua bộ nhớ cache cho các quy tắc tùy chỉnh cục bộ", + rulesExample: "Ví dụ về quy tắc", + lastPage: "Đã đến trang cuối cùng", + lastPageTips: "Hiển thị mẹo khi đến trang cuối cùng" + } + }, + { + name: "Polski", + match: ["pl"], + lang: { + enableDebug: "Włącz wyjście debugowania do konsoli", + updateNotification: "Powiadomienie po aktualizacji reguł", + disable: "Tymczasowo wyłącz", + disableSite: "Przełącz stan wyłączenia", + disableSiteTips: "Wyłączone na tej stronie.", + enableSiteTips: "Włączone na tej stronie.", + enable: "✅Włącz automatyczne przewracanie stron", + tempActive: "Tymczasowo aktywne", + toTop: "Powrót na górę.", + toBottom: "Przejdź na dół.", + current: "Bieżąca strona.", + forceIframe: "Wymuś dołączenie do następnej strony", + cancelForceIframe: "Anuluj wymuszone dołączenie", + configure: "Skonfiguruj Pagetual", + firstUpdate: "Kliknij tutaj, aby zainicjować domyślną listę reguł", + update: "Aktualizuj reguły online", + click2update: "Kliknij, aby zaktualizować reguły z adresu URL teraz", + loadNow: "Załaduj następną automatycznie", + loadConfirm: "Ile stron chcesz załadować? (0 oznacza nieskończoność)", + noNext: "Nie znaleziono następnego linku, utwórz nową regułę", + passSec: "Zaktualizowano #t# sekund temu", + passMin: "Zaktualizowano #t# minut temu", + passHour: "Zaktualizowano #t# godzin temu", + passDay: "Zaktualizowano #t# dni temu", + cantDel: "Nie można usunąć wbudowanych reguł", + confirmDel: "Czy na pewno chcesz usunąć tę regułę?", + updateSucc: "Aktualizacja zakończona powodzeniem", + beginUpdate: "Rozpoczynam aktualizację, proszę czekać", + customUrls: "Importuj adres URL reguły Pagetual lub AutoPagerize, jeden adres URL na linię.", + customRules: "Wprowadź niestandardowe reguły. ✍️Współtwórz reguły", + save: "Zapisz", + loadingText: "Ładowanie...", + opacity: "Przezroczystość", + opacityPlaceholder: "0: ukryj separator", + hideBar: "Ukryj separator paginacji", + hideBarButNoStop: "Ukryj, ale nie zatrzymuj", + dbClick2Stop: "Kliknij dwukrotnie w puste miejsce, aby wstrzymać", + sortTitle: "Sortowanie zacznie obowiązywać po następnej aktualizacji reguł", + autoRun: "Automatyczne włączanie (tryb czarnej listy)", + autoLoadNum: "Ilość stron do wstępnego załadowania", + turnRate: "Przewróć na następną stronę, gdy odległość od stopki jest mniejsza niż 【X】-krotność wysokości strony", + inputPageNum: "Wprowadź numer strony, aby przejść", + enableHistory: "Zapisuj historię przeglądania po przewróceniu strony", + enableHistoryAfterInsert: "Zapisuj historię przeglądania natychmiast po połączeniu, w przeciwnym razie zapisuj po przeglądaniu", + contentVisibility: "Automatycznie przełączaj widoczność zawartości, aby poprawić wydajność renderowania", + initRun: "Przewracaj strony natychmiast po otwarciu", + preload: "Wstępnie załaduj następną stronę, aby przyspieszyć", + click2ImportRule: "Kliknij, aby zaimportować link do podstawowych reguł, a następnie poczekaj na zakończenie aktualizacji: ", + forceAllBody: "Dołączyć całą treść strony?", + openInNewTab: "Otwórz adresy URL dodatków w nowej karcie", + importSucc: "Import zakończony", + import: "Importuj", + editCurrent: "Edytuj regułę dla bieżącej witryny", + editBlacklist: "Edytuj czarną listę adresów URL, jeden wpis na linię, obsługuje symbole wieloznaczne [?,*].", + upBtnImg: "Ikona powrotu na górę", + downBtnImg: "Ikona przejścia do stopki", + sideControllerIcon: "Ikona paska bocznego", + loadingTextTitle: "Ładowanie", + dbClick2StopCtrl: "Klawisz Ctrl", + dbClick2StopAlt: "Klawisz Alt", + dbClick2StopShift: "Klawisz Shift", + dbClick2StopMeta: "Klawisz Meta", + dbClick2StopKey: "Klawisz skrótu", + pageElementCss: "Niestandardowy styl dla głównych elementów strony", + customCss: "Niestandardowy kompletny CSS", + firstAlert: "Nie zaimportowałeś podstawowej reguły, wybierz odpowiednią regułę do zaimportowania", + picker: "Selektor elementów Pagetual", + closePicker: "Zamknij selektor Pagetual", + pickerPlaceholder: "Selektor elementów (Tylko dla zaawansowanych użytkowników, w przeciwnym razie pozostaw puste)", + pickerCheck: "Sprawdź selektor i skopiuj", + switchSelector: "Kliknij, aby przełączyć element", + gotoEdit: "Przejdź do edycji reguły z bieżącym selektorem", + manualMode: "Wyłącz łączenie, ręcznie przejdź do następnej strony za pomocą klawisza strzałki w prawo (lub wyślij zdarzenie 'pagetual.next')", + clickMode: "Wyłącz łączenie, automatycznie kliknij następną stronę po przewinięciu do końca strony", + pageBarMenu: "Kliknij środek paska strony, aby otworzyć menu selektora", + nextSwitch: "Przełącz następny link", + arrowToScroll: "Naciśnij lewą strzałkę, aby przewinąć do tyłu, a prawą strzałkę, aby przejść do przodu", + sideController: "Wyświetl pasek sterowania paginacją na pasku bocznym", + sideControllerScroll: "Przełączanie przewijania", + sideControllerAlways: "Zawsze pokazuj", + hideLoadingIcon: "Ukryj animację ładowania", + hideBarArrow: "Ukryj strzałkę paska strony", + duplicate: "Zainstalowano zduplikowany Pagetual, sprawdź menedżera skryptów!", + forceStateIframe: "Osadź całą stronę jako iframe", + forceStateDynamic: "Załaduj dynamiczną zawartość przez iframe", + forceStateDisable: "Wyłącz przewracanie stron na tej stronie", + autoScrollRate: "Prędkość przewijania (1-1000)", + disableAutoScroll: "Zatrzymaj automatyczne przewijanie", + enableAutoScroll: "Włącz automatyczne przewijanie", + toggleAutoScroll: "Przełącz automatyczne przewijanie", + ruleRequest: "Żądanie reguły", + page: "Strona ", + prevPage: "Poprzednia strona", + nextPage: "Następna strona", + errorRulesMustBeArray: "Reguły muszą być tablicą!", + errorJson: "Błąd JSON, sprawdź ponownie!", + editSuccess: "Edycja zakończona pomyślnie", + errorWrongUrl: "Błędny adres URL, sprawdź ponownie!", + errorAlreadyExists: "Reguła już istnieje!", + settingsSaved: "Ustawienia zostały zapisane, odśwież, aby zobaczyć", + iframe: "Wymuszony podział przez iframe", + dynamic: "Dynamiczne ładowanie", + reloadPage: "Edycja zakończona, przeładować teraz?", + copied: "Skopiowano", + noValidContent: "Nie wykryto prawidłowej zawartości, może być obecna Captcha", + outOfDate: "Skrypt jest przestarzały, zaktualizuj do najnowszej wersji.", + hideBarTips: "Ukryj pasek paginacji, przełącz na tryb immersyjny", + setConfigPage: "Ustaw bieżącą stronę jako domyślną stronę konfiguracji", + wedata2github: "Zmień adres wedata na adres lustrzany w repozytorium github", + addOtherProp: "Dodaj właściwości reguły", + addNextSelector: "Dodaj zawartość selektora jako nextLink", + addPageSelector: "Dodaj zawartość selektora jako pageElement", + propName: "Wprowadź nazwę właściwości reguły", + propValue: "Wprowadź wartość właściwości reguły", + customFirst: "Ignoruj pamięć podręczną dla lokalnych niestandardowych reguł", + rulesExample: "Przykład reguł", + lastPage: "Osiągnięto ostatnią stronę", + lastPageTips: "Pokaż wskazówki po osiągnięciu ostatniej strony" + } + }, + { + name: "Українська", + match: ["uk"], + lang: { + enableDebug: "Увімкнути вивід налагодження в консоль", + updateNotification: "Сповіщення після оновлення правил", + disable: "Тимчасово вимкнути", + disableSite: "Перемкнути стан вимкнення", + disableSiteTips: "Вимкнено на цьому сайті.", + enableSiteTips: "Увімкнено на цьому сайті.", + enable: "✅Увімкнути автоматичне перегортання сторінок", + tempActive: "Тимчасово активний", + toTop: "Повернутися нагору.", + toBottom: "Перейти вниз.", + current: "Поточна сторінка.", + forceIframe: "Примусово приєднати наступну сторінку", + cancelForceIframe: "Скасувати примусове приєднання", + configure: "Налаштувати Pagetual", + firstUpdate: "Натисніть тут, щоб ініціалізувати стандартний список правил", + update: "Оновити онлайн-правила", + click2update: "Натисніть, щоб оновити правила з URL зараз", + loadNow: "Завантажити наступну автоматично", + loadConfirm: "Скільки сторінок ви хочете завантажити? (0 означає нескінченно)", + noNext: "Не знайдено наступного посилання, створіть нове правило", + passSec: "Оновлено #t# секунд тому", + passMin: "Оновлено #t# хвилин тому", + passHour: "Оновлено #t# годин тому", + passDay: "Оновлено #t# днів тому", + cantDel: "Неможливо видалити вбудовані правила", + confirmDel: "Ви впевнені, що хочете видалити це правило?", + updateSucc: "Оновлення успішне", + beginUpdate: "Починається оновлення, зачекайте хвилинку", + customUrls: "Імпортувати URL правила Pagetual або AutoPagerize, один URL на рядок.", + customRules: "Введіть власні правила. ✍️Додайте правила", + save: "Зберегти", + loadingText: "Завантаження...", + opacity: "Непрозорість", + opacityPlaceholder: "0: приховати роздільник", + hideBar: "Приховати роздільник пагінації", + hideBarButNoStop: "Приховати, але не зупиняти", + dbClick2Stop: "Двічі клацніть на порожньому місці, щоб призупинити", + sortTitle: "Сортування набуде чинності після наступного оновлення правил", + autoRun: "Автоматичне ввімкнення (режим чорного списку)", + autoLoadNum: "Кількість для попередньо завантажених сторінок", + turnRate: "Перегорніть на наступну сторінку, коли до нижнього колонтитула залишиться менше 【X】 висот сторінки", + inputPageNum: "Введіть номер сторінки для переходу", + enableHistory: "Записувати історію переглядів після перегортання сторінки", + enableHistoryAfterInsert: "Записувати історію переглядів одразу після з'єднання, інакше записувати після перегляду", + contentVisibility: "Автоматично перемикати видимість вмісту для покращення продуктивності рендерингу", + initRun: "Перегортати сторінки одразу після відкриття", + preload: "Попередньо завантажити наступну сторінку для прискорення", + click2ImportRule: "Натисніть, щоб імпортувати посилання на базові правила, а потім зачекайте, доки оновлення не завершиться: ", + forceAllBody: "Приєднати все тіло сторінки?", + openInNewTab: "Відкрити URL-адреси доповнень у новій вкладці", + importSucc: "Імпорт завершено", + import: "Імпортувати", + editCurrent: "Редагувати правило для поточного веб-сайту", + editBlacklist: "Редагувати чорний список URL-адрес, один запис на рядок, підтримує символи підстановки [?,*].", + upBtnImg: "Іконка повернення нагору", + downBtnImg: "Іконка переходу до нижнього колонтитула", + sideControllerIcon: "Іконка бічної панелі", + loadingTextTitle: "Завантаження", + dbClick2StopCtrl: "Клавіша Ctrl", + dbClick2StopAlt: "Клавіша Alt", + dbClick2StopShift: "Клавіша Shift", + dbClick2StopMeta: "Клавіша Meta", + dbClick2StopKey: "Клавіша швидкого доступу", + pageElementCss: "Власний стиль для основних елементів сторінки", + customCss: "Власний повний CSS", + firstAlert: "Ви не імпортували базове правило, будь ласка, виберіть відповідне правило для імпорту", + picker: "Вибір елементів Pagetual", + closePicker: "Закрити вибір Pagetual", + pickerPlaceholder: "Вибір елементів (Лише для досвідчених користувачів, інакше залиште порожнім)", + pickerCheck: "Перевірити селектор і скопіювати", + switchSelector: "Натисніть, щоб перемкнути елемент", + gotoEdit: "Перейти до редагування правила з поточним селектором", + manualMode: "Вимкнути з'єднання, вручну переходити на наступну сторінку за допомогою клавіші зі стрілкою вправо (або надіслати подію 'pagetual.next')", + clickMode: "Вимкнути з'єднання, автоматично клацати на наступну сторінку при прокручуванні до кінця сторінки", + pageBarMenu: "Натисніть на центр панелі сторінки, щоб відкрити меню вибору", + nextSwitch: "Перемкнути наступне посилання", + arrowToScroll: "Натисніть ліву стрілку, щоб прокрутити назад, і праву стрілку, щоб перейти на сторінку вперед", + sideController: "Відображати панель керування пагінацією в бічній панелі", + sideControllerScroll: "Перемикання прокрутки", + sideControllerAlways: "Завжди показувати", + hideLoadingIcon: "Приховати анімацію завантаження", + hideBarArrow: "Приховати стрілку для панелі сторінки", + duplicate: "Встановлено дублікат Pagetual, перевірте свій менеджер скриптів!", + forceStateIframe: "Вбудувати повну сторінку як iframe", + forceStateDynamic: "Завантажувати динамічний вміст через iframe", + forceStateDisable: "Вимкнути перегортання сторінок на цьому сайті", + autoScrollRate: "Швидкість прокрутки (1-1000)", + disableAutoScroll: "Зупинити автоматичну прокрутку", + enableAutoScroll: "Увімкнути автоматичну прокрутку", + toggleAutoScroll: "Перемкнути автоматичну прокрутку", + ruleRequest: "Запит на правило", + page: "Сторінка ", + prevPage: "Попередня сторінка", + nextPage: "Наступна сторінка", + errorRulesMustBeArray: "Правила повинні бути масивом!", + errorJson: "Помилка JSON, перевірте ще раз!", + editSuccess: "Відредаговано успішно", + errorWrongUrl: "Неправильна URL-адреса, перевірте ще раз!", + errorAlreadyExists: "Правило вже існує!", + settingsSaved: "Налаштування збережено, оновіть, щоб переглянути", + iframe: "Примусове розділення за допомогою iframe", + dynamic: "Динамічне завантаження", + reloadPage: "Редагування завершено, перезавантажити зараз?", + copied: "Скопійовано", + noValidContent: "Не виявлено дійсного вмісту, можливо, є Captcha", + outOfDate: "Скрипт застарів, оновіть до останньої версії.", + hideBarTips: "Приховати панель пагінації, перемкнути на захоплюючий досвід", + setConfigPage: "Встановити поточну сторінку як сторінку конфігурації за замовчуванням", + wedata2github: "Змінити адресу wedata на дзеркальну адресу в репозиторії github", + addOtherProp: "Додати властивості правила", + addNextSelector: "Додати вміст селектора як nextLink", + addPageSelector: "Додати вміст селектора як pageElement", + propName: "Введіть назву властивості правила", + propValue: "Введіть значення властивості правила", + customFirst: "Ігнорувати кеш для локальних власних правил", + rulesExample: "Приклад правил", + lastPage: "Досягнуто останньої сторінки", + lastPageTips: "Показувати поради при досягненні останньої сторінки" + } + }, + { + name: "Türkçe", + match: ["tr"], + lang: { + enableDebug: "Konsola hata ayıklama çıktısını etkinleştir", + updateNotification: "Kurallar güncellendikten sonra bildirim", + disable: "Geçici olarak devre dışı bırak", + disableSite: "Devre dışı bırakma durumunu değiştir", + disableSiteTips: "Bu sitede devre dışı bırakıldı.", + enableSiteTips: "Bu sitede etkinleştirildi.", + enable: "✅Otomatik sayfa çevirmeyi etkinleştir", + tempActive: "Geçici olarak aktif", + toTop: "Başa dön.", + toBottom: "Sona git.", + current: "Mevcut sayfa.", + forceIframe: "Sonraki sayfaya katılmaya zorla", + cancelForceIframe: "Zorla katılmayı iptal et", + configure: "Pagetual'ı yapılandır", + firstUpdate: "Varsayılan kural listesini başlatmak için buraya tıklayın", + update: "Çevrimiçi kuralları güncelle", + click2update: "Kuralları şimdi URL'den güncellemek için tıkla", + loadNow: "Sonrakini otomatik olarak yükle", + loadConfirm: "Kaç sayfa yüklemek istiyorsunuz? (0 sonsuz demektir)", + noNext: "Sonraki bağlantı bulunamadı, lütfen yeni bir kural oluşturun", + passSec: "#t# saniye önce güncellendi", + passMin: "#t# dakika önce güncellendi", + passHour: "#t# saat önce güncellendi", + passDay: "#t# gün önce güncellendi", + cantDel: "Yerleşik kurallar silinemez", + confirmDel: "Bu kuralı silmek istediğinizden emin misiniz?", + updateSucc: "Güncelleme başarılı", + beginUpdate: "Güncelleme başlıyor, lütfen bir dakika bekleyin", + customUrls: "Pagetual veya AutoPagerize kural URL'sini içe aktarın, her satıra bir URL.", + customRules: "Özel kuralları girin. ✍️Kurallara katkıda bulunun", + save: "Kaydet", + loadingText: "Yükleniyor...", + opacity: "Opaklık", + opacityPlaceholder: "0: ayırıcıyı gizle", + hideBar: "Sayfalandırma ayırıcısını gizle", + hideBarButNoStop: "Gizle ama durdurma", + dbClick2Stop: "Duraklatmak için boş alana çift tıklayın", + sortTitle: "Sıralama bir sonraki kural güncellemesinden sonra etkili olur", + autoRun: "Otomatik etkinleştir (kara liste modu)", + autoLoadNum: "Önceden yüklenecek sayfa miktarı", + turnRate: "Altbilgiden sayfa yüksekliğinin 【X】 katından daha az olduğunda sonraki sayfaya geçin", + inputPageNum: "Atlamak için sayfa numarasını girin", + enableHistory: "Sayfa çevirdikten sonra tarama geçmişini yaz", + enableHistoryAfterInsert: "Birleştirmeden hemen sonra tarama geçmişini yaz, aksi takdirde taramadan sonra yaz", + contentVisibility: "Oluşturma performansını iyileştirmek için içerik görünürlüğünü otomatik olarak değiştir", + initRun: "Açtıktan hemen sonra sayfaları çevir", + preload: "Hızlandırmak için sonraki sayfayı önceden yükle", + click2ImportRule: "Temel kurallar bağlantısını içe aktarmak için tıklayın ve ardından güncelleme tamamlanana kadar bekleyin: ", + forceAllBody: "Sayfanın tam gövdesine katılsın mı?", + openInNewTab: "Eklerin URL'lerini yeni sekmede aç", + importSucc: "İçe aktarma tamamlandı", + import: "İçe aktar", + editCurrent: "Mevcut web sitesi için kuralı düzenle", + editBlacklist: "URL kara listesini düzenleyin, her satıra bir giriş, [?,*] joker karakterlerini destekler.", + upBtnImg: "Başa dön simgesi", + downBtnImg: "Altbilgiye git simgesi", + sideControllerIcon: "Kenar çubuğu simgesi", + loadingTextTitle: "Yükleniyor", + dbClick2StopCtrl: "Ctrl tuşu", + dbClick2StopAlt: "Alt tuşu", + dbClick2StopShift: "Shift tuşu", + dbClick2StopMeta: "Meta tuşu", + dbClick2StopKey: "Kısayol tuşu", + pageElementCss: "Ana sayfa öğeleri için özel stil", + customCss: "Özel tam CSS", + firstAlert: "Temel kuralı içe aktarmadınız, lütfen içe aktarmak için uygun kuralı seçin", + picker: "Pagetual öğe seçici", + closePicker: "Pagetual seçiciyi kapat", + pickerPlaceholder: "Öğe seçici (Yalnızca ileri düzey kullanıcılar, aksi takdirde boş bırakın)", + pickerCheck: "Seçiciyi kontrol et ve kopyala", + switchSelector: "Öğeyi değiştirmek için tıkla", + gotoEdit: "Mevcut seçiciyle kuralı düzenlemeye git", + manualMode: "Birleştirmeyi devre dışı bırak, sağ ok tuşunu kullanarak sonraki sayfaya manuel olarak ilerle (veya 'pagetual.next' olayını gönder)", + clickMode: "Birleştirmeyi devre dışı bırak, sayfanın sonuna kaydırıldığında sonraki sayfayı otomatik olarak tıkla", + pageBarMenu: "Seçici menüsünü açmak için sayfa çubuğunun ortasına tıklayın", + nextSwitch: "Sonraki bağlantıyı değiştir", + arrowToScroll: "Geri kaydırmak için sol oka, sayfayı ilerletmek için sağ oka basın", + sideController: "Sayfalandırma kontrol çubuğunu kenar çubuğunda göster", + sideControllerScroll: "Kaydırmayı değiştir", + sideControllerAlways: "Her zaman göster", + hideLoadingIcon: "Yükleme animasyonunu gizle", + hideBarArrow: "Sayfa çubuğu için oku gizle", + duplicate: "Yinelenen Pagetual yüklendi, komut dosyası yöneticinizi kontrol edin!", + forceStateIframe: "Tam sayfayı iframe olarak göm", + forceStateDynamic: "Dinamik içeriği iframe aracılığıyla yükle", + forceStateDisable: "Bu sitede sayfa çevirmeyi devre dışı bırak", + autoScrollRate: "Kaydırma hızı (1-1000)", + disableAutoScroll: "Otomatik Kaydırmayı Durdur", + enableAutoScroll: "Otomatik Kaydırmayı Etkinleştir", + toggleAutoScroll: "Otomatik Kaydırmayı Değiştir", + ruleRequest: "Kural İsteği", + page: "Sayfa ", + prevPage: "Önceki sayfa", + nextPage: "Sonraki sayfa", + errorRulesMustBeArray: "Kurallar bir Dizi olmalıdır!", + errorJson: "JSON hatası, Tekrar kontrol edin!", + editSuccess: "Başarıyla düzenlendi", + errorWrongUrl: "Yanlış URL, Tekrar kontrol edin!", + errorAlreadyExists: "Bir kural zaten var!", + settingsSaved: "Ayarlar kaydedildi, görüntülemek için yenileyin", + iframe: "Iframe tarafından zorla bölündü", + dynamic: "Dinamik yükleme", + reloadPage: "Düzenleme tamamlandı, şimdi yeniden yüklensin mi?", + copied: "Kopyalandı", + noValidContent: "Geçerli içerik algılanmadı, bir Captcha olabilir", + outOfDate: "Komut dosyası güncel değil, lütfen en son sürüme güncelleyin.", + hideBarTips: "Sayfalandırma çubuğunu gizle, sürükleyici deneyime geç", + setConfigPage: "Mevcut sayfayı varsayılan yapılandırma sayfası olarak ayarla", + wedata2github: "Wedata adresini github deposundaki ayna adresine değiştirin", + addOtherProp: "Kural özellikleri ekle", + addNextSelector: "Seçici içeriğini nextLink olarak ekle", + addPageSelector: "Seçici içeriğini pageElement olarak ekle", + propName: "Kural özelliği adını girin", + propValue: "Kural özelliği değerini girin", + customFirst: "Yerel özel kurallar için önbelleği yoksay", + rulesExample: "Kurallar Örneği", + lastPage: "Son sayfaya ulaşıldı", + lastPageTips: "Son sayfaya ulaşıldığında ipuçları göster" + } + }, + { + name: "Nederlands", + match: ["nl"], + lang: { + enableDebug: "Foutopsporingsuitvoer naar console inschakelen", + updateNotification: "Melding nadat regels zijn bijgewerkt", + disable: "Tijdelijk uitschakelen", + disableSite: "Uitgeschakelde status omschakelen", + disableSiteTips: "Uitgeschakeld op deze site.", + enableSiteTips: "Ingeschakeld op deze site.", + enable: "✅Automatisch pagina's omslaan inschakelen", + tempActive: "Tijdelijk actief", + toTop: "Terug naar boven.", + toBottom: "Ga naar beneden.", + current: "Huidige pagina.", + forceIframe: "Dwingen om volgende pagina te koppelen", + cancelForceIframe: "Gedwongen koppeling annuleren", + configure: "Pagetual configureren", + firstUpdate: "Klik hier om de standaardregellijst te initialiseren", + update: "Online regels bijwerken", + click2update: "Klik om regels nu vanaf URL bij te werken", + loadNow: "Laad volgende automatisch", + loadConfirm: "Hoeveel pagina's wilt u laden? (0 betekent oneindig)", + noNext: "Geen volgende link gevonden, maak een nieuwe regel", + passSec: "#t# seconden geleden bijgewerkt", + passMin: "#t# minuten geleden bijgewerkt", + passHour: "#t# uur geleden bijgewerkt", + passDay: "#t# dagen geleden bijgewerkt", + cantDel: "Ingebouwde regels kunnen niet worden verwijderd", + confirmDel: "Weet u zeker dat u deze regel wilt verwijderen?", + updateSucc: "Update geslaagd", + beginUpdate: "Start update, een ogenblik geduld", + customUrls: "Importeer Pagetual of AutoPagerize regel-URL, één URL per regel.", + customRules: "Voer aangepaste regels in. ✍️Draag regels bij", + save: "Opslaan", + loadingText: "Laden...", + opacity: "Dekking", + opacityPlaceholder: "0: verberg scheidingsteken", + hideBar: "Verberg het pagineringsscheidingsteken", + hideBarButNoStop: "Verbergen maar niet stoppen", + dbClick2Stop: "Dubbelklik op de lege ruimte om te pauzeren", + sortTitle: "Sorteren wordt van kracht na de volgende regelupdate", + autoRun: "Automatisch inschakelen (zwarte lijst-modus)", + autoLoadNum: "Aantal voor vooraf geladen pagina's", + turnRate: "Sla de volgende pagina om wanneer deze minder dan 【X】 keer de paginahoogte van de voettekst is", + inputPageNum: "Voer paginanummer in om te springen", + enableHistory: "Schrijf browsegeschiedenis na het omslaan van de pagina", + enableHistoryAfterInsert: "Schrijf browsegeschiedenis onmiddellijk na het splitsen, anders schrijven na het browsen", + contentVisibility: "Schakel automatisch de zichtbaarheid van inhoud om de renderprestaties te verbeteren", + initRun: "Sla pagina's onmiddellijk na het openen om", + preload: "Laad de volgende pagina vooraf om te versnellen", + click2ImportRule: "Klik om de link met basisregels te importeren en wacht vervolgens tot de update is voltooid: ", + forceAllBody: "Volledige body van de pagina koppelen?", + openInNewTab: "Open URL's van toevoegingen in een nieuw tabblad", + importSucc: "Importeren voltooid", + import: "Importeren", + editCurrent: "Regel voor huidige website bewerken", + editBlacklist: "Bewerk de URL-zwarte lijst, één item per regel, ondersteunt [?,*] jokertekens.", + upBtnImg: "Pictogram terug naar boven", + downBtnImg: "Pictogram ga naar voettekst", + sideControllerIcon: "Pictogram zijbalk", + loadingTextTitle: "Laden", + dbClick2StopCtrl: "Ctrl-toets", + dbClick2StopAlt: "Alt-toets", + dbClick2StopShift: "Shift-toets", + dbClick2StopMeta: "Meta-toets", + dbClick2StopKey: "Sneltoets", + pageElementCss: "Aangepaste stijl voor hoofdpagina-elementen", + customCss: "Aangepaste volledige CSS", + firstAlert: "U heeft de basisregel niet geïmporteerd, selecteer de juiste regel om te importeren", + picker: "Pagetual-elementenkiezer", + closePicker: "Pagetual-kiezer sluiten", + pickerPlaceholder: "Elementenkiezer (Alleen voor gevorderde gebruikers, laat anders leeg)", + pickerCheck: "Controleer kiezer en kopieer", + switchSelector: "Klik om van element te wisselen", + gotoEdit: "Ga naar regel bewerken met huidige kiezer", + manualMode: "Schakel splitsen uit, ga handmatig naar de volgende pagina met de rechterpijltoets (of verstuur gebeurtenis 'pagetual.next')", + clickMode: "Schakel splitsen uit, klik automatisch op de volgende pagina bij het scrollen naar het einde van de pagina", + pageBarMenu: "Klik op het midden van de paginabalk om het kiezermenu te openen", + nextSwitch: "Wissel volgende link", + arrowToScroll: "Druk op de linkerpijl om terug te scrollen en op de rechterpijl om naar de volgende pagina te gaan", + sideController: "Toon de pagineringsbalk in de zijbalk", + sideControllerScroll: "Scroll-schakelaar", + sideControllerAlways: "Altijd tonen", + hideLoadingIcon: "Verberg laadanimatie", + hideBarArrow: "Verberg pijl voor paginabalk", + duplicate: "Dubbele Pagetual is geïnstalleerd, controleer uw scriptmanager!", + forceStateIframe: "Volledige pagina insluiten als iframe", + forceStateDynamic: "Laad dynamische inhoud via iframe", + forceStateDisable: "Schakel het omslaan van pagina's op deze site uit", + autoScrollRate: "Scrollsnelheid (1-1000)", + disableAutoScroll: "Stop automatisch scrollen", + enableAutoScroll: "Schakel automatisch scrollen in", + toggleAutoScroll: "Schakel automatisch scrollen om", + ruleRequest: "Regelverzoek", + page: "Pagina ", + prevPage: "Vorige pagina", + nextPage: "Volgende pagina", + errorRulesMustBeArray: "Regels moeten een array zijn!", + errorJson: "JSON-fout, controleer opnieuw!", + editSuccess: "Succesvol bewerkt", + errorWrongUrl: "Verkeerde URL, controleer opnieuw!", + errorAlreadyExists: "Er bestaat al een regel!", + settingsSaved: "De instellingen zijn opgeslagen, ververs om te bekijken", + iframe: "Gedwongen gesplitst door iframe", + dynamic: "Dynamisch laden", + reloadPage: "Bewerking voltooid, nu opnieuw laden?", + copied: "Gekopieerd", + noValidContent: "Geen geldige inhoud gedetecteerd, er is mogelijk een Captcha aanwezig", + outOfDate: "Het script is verouderd, update naar de nieuwste versie.", + hideBarTips: "Verberg de pagineringsbalk, schakel de meeslepende ervaring om", + setConfigPage: "Stel de huidige pagina in als de standaardconfiguratiepagina", + wedata2github: "Wijzig het wedata-adres in het spiegeladres in de github-repository", + addOtherProp: "Voeg regeleigenschappen toe", + addNextSelector: "Voeg kiezerinhoud toe als nextLink", + addPageSelector: "Voeg kiezerinhoud toe als pageElement", + propName: "Voer de naam van de regeleigenschap in", + propValue: "Voer de waarde van de regeleigenschap in", + customFirst: "Cache negeren voor lokale aangepaste regels", + rulesExample: "Voorbeeld van regels", + lastPage: "Laatste pagina bereikt", + lastPageTips: "Toon tips bij het bereiken van de laatste pagina" + } + }, + { + name: "Dansk", + match: ["da"], + lang: { + enableDebug: "Aktivér fejlfindingsoutput til konsollen", + updateNotification: "Meddelelse efter opdatering af regler", + disable: "Deaktiver midlertidigt", + disableSite: "Skift deaktiveret tilstand", + disableSiteTips: "Deaktiveret på dette websted.", + enableSiteTips: "Aktiveret på dette websted.", + enable: "✅Aktivér automatisk sidevending", + tempActive: "Midlertidigt aktiv", + toTop: "Tilbage til toppen.", + toBottom: "Gå til bunden.", + current: "Nuværende side.", + forceIframe: "Tving tilslutning til næste side", + cancelForceIframe: "Annuller tvungen tilslutning", + configure: "Konfigurer Pagetual", + firstUpdate: "Klik her for at initialisere standardregellisten", + update: "Opdater onlineregler", + click2update: "Klik for at opdatere regler fra URL nu", + loadNow: "Indlæs næste automatisk", + loadConfirm: "Hvor mange sider vil du indlæse? (0 betyder uendelig)", + noNext: "Intet næste link fundet, opret en ny regel", + passSec: "Opdateret for #t# sekunder siden", + passMin: "Opdateret for #t# minutter siden", + passHour: "Opdateret for #t# timer siden", + passDay: "Opdateret for #t# dage siden", + cantDel: "Kan ikke slette indbyggede regler", + confirmDel: "Er du sikker på, at du vil slette denne regel?", + updateSucc: "Opdatering lykkedes", + beginUpdate: "Starter opdatering, vent venligst et øjeblik", + customUrls: "Importer Pagetual- eller AutoPagerize-regel-URL, én URL pr. linje.", + customRules: "Indtast brugerdefinerede regler. ✍️Bidrag med regler", + save: "Gem", + loadingText: "Indlæser...", + opacity: "Opacitet", + opacityPlaceholder: "0: skjul afstandsstykke", + hideBar: "Skjul pagineringsafstandsstykket", + hideBarButNoStop: "Skjul, men stop ikke", + dbClick2Stop: "Dobbeltklik på det tomme rum for at sætte på pause", + sortTitle: "Sortering træder i kraft efter næste regelopdatering", + autoRun: "Automatisk aktivering (sortlistetilstand)", + autoLoadNum: "Antal for forudindlæste sider", + turnRate: "Vend til næste side, når den er mindre end 【X】 gange sidehøjden fra sidefoden", + inputPageNum: "Indtast sidetal for at hoppe", + enableHistory: "Skriv browserhistorik efter sidevending", + enableHistoryAfterInsert: "Skriv browserhistorik umiddelbart efter splejsning, ellers skriv efter browsing", + contentVisibility: "Skift automatisk indholdssynlighed for at forbedre gengivelsesydelsen", + initRun: "Vend sider umiddelbart efter åbning", + preload: "Forudindlæs næste side for at fremskynde", + click2ImportRule: "Klik for at importere link til grundregler, og vent derefter, indtil opdateringen er fuldført: ", + forceAllBody: "Tilslut hele sidens krop?", + openInNewTab: "Åbn URL'er for tilføjelser i ny fane", + importSucc: "Import fuldført", + import: "Importer", + editCurrent: "Rediger regel for nuværende websted", + editBlacklist: "Rediger URL-sortlisten, én post pr. linje, understøtter [?,*] jokertegn.", + upBtnImg: "Ikon for tilbage til toppen", + downBtnImg: "Ikon for at gå til sidefod", + sideControllerIcon: "Sidebjælkeikon", + loadingTextTitle: "Indlæser", + dbClick2StopCtrl: "Ctrl-tast", + dbClick2StopAlt: "Alt-tast", + dbClick2StopShift: "Shift-tast", + dbClick2StopMeta: "Meta-tast", + dbClick2StopKey: "Genvejstast", + pageElementCss: "Brugerdefineret stil for hovedsideelementer", + customCss: "Brugerdefineret komplet CSS", + firstAlert: "Du har ikke importeret grundreglen, vælg den relevante regel at importere", + picker: "Pagetual-elementvælger", + closePicker: "Luk Pagetual-vælger", + pickerPlaceholder: "Elementvælger (Kun avancerede brugere, ellers lad være tomt)", + pickerCheck: "Kontroller vælger og kopier", + switchSelector: "Klik for at skifte element", + gotoEdit: "Gå til redigeringsregel med nuværende vælger", + manualMode: "Deaktiver splejsning, gå manuelt frem til næste side ved hjælp af højre piletast (eller send hændelsen 'pagetual.next')", + clickMode: "Deaktiver splejsning, klik automatisk på næste side, når du ruller til slutningen af siden", + pageBarMenu: "Klik på midten af sidebjælken for at åbne vælgermenuen", + nextSwitch: "Skift næste link", + arrowToScroll: "Tryk på venstre pil for at rulle tilbage og højre pil for at gå frem en side", + sideController: "Vis pagineringskontrolbjælken i sidebjælken", + sideControllerScroll: "Rul-skift", + sideControllerAlways: "Vis altid", + hideLoadingIcon: "Skjul indlæsningsanimation", + hideBarArrow: "Skjul pil for sidebjælke", + duplicate: "Duplikat Pagetual er blevet installeret, tjek din scriptmanager!", + forceStateIframe: "Integrer hele siden som en iframe", + forceStateDynamic: "Indlæs dynamisk indhold via iframe", + forceStateDisable: "Deaktiver sidevending på dette websted", + autoScrollRate: "Rullehastighed (1-1000)", + disableAutoScroll: "Stop automatisk rulning", + enableAutoScroll: "Aktivér automatisk rulning", + toggleAutoScroll: "Skift automatisk rulning", + ruleRequest: "Regelanmodning", + page: "Side ", + prevPage: "Forrige side", + nextPage: "Næste side", + errorRulesMustBeArray: "Regler skal være en matrix!", + errorJson: "JSON-fejl, tjek igen!", + editSuccess: "Redigering lykkedes", + errorWrongUrl: "Forkert URL, tjek igen!", + errorAlreadyExists: "En regel eksisterer allerede!", + settingsSaved: "Indstillingerne er gemt, opdater for at se", + iframe: "Tvunget opdelt af iframe", + dynamic: "Dynamisk indlæsning", + reloadPage: "Redigering fuldført, genindlæs nu?", + copied: "Kopieret", + noValidContent: "Intet gyldigt indhold fundet, en Captcha kan være til stede", + outOfDate: "Scriptet er forældet, opdater venligst til den nyeste version.", + hideBarTips: "Skjul pagineringsbjælken, skift til en fordybende oplevelse", + setConfigPage: "Indstil den aktuelle side som standardkonfigurationsside", + wedata2github: "Skift wedata-adressen til spejladressen i github-depotet", + addOtherProp: "Tilføj regelegenskaber", + addNextSelector: "Tilføj vælgerindhold som nextLink", + addPageSelector: "Tilføj vælgerindhold som pageElement", + propName: "Indtast regelegenskabsnavn", + propValue: "Indtast regelegenskabsværdi", + customFirst: "Ignorer cache for lokale brugerdefinerede regler", + rulesExample: "Regeleksempel", + lastPage: "Nåede den sidste side", + lastPageTips: "Vis tips, når du når den sidste side" + } + }, + { + name: "Français (Canada)", + match: ["fr-CA"], + lang: { + enableDebug: "Activer la sortie de débogage dans la console", + updateNotification: "Notification après la mise à jour des règles", + disable: "Désactiver temporairement", + disableSite: "Basculer l'état de désactivation", + disableSiteTips: "Désactivé sur ce site.", + enableSiteTips: "Activé sur ce site.", + enable: "✅Activer le changement de page automatique", + tempActive: "Temporairement actif", + toTop: "Retour en haut.", + toBottom: "Aller en bas.", + current: "Page actuelle.", + forceIframe: "Forcer la jonction de la page suivante", + cancelForceIframe: "Annuler la jonction forcée", + configure: "Configurer Pagetual", + firstUpdate: "Cliquez ici pour initialiser la liste de règles par défaut", + update: "Mettre à jour les règles en ligne", + click2update: "Cliquez pour mettre à jour les règles depuis l'URL maintenant", + loadNow: "Charger la suite automatiquement", + loadConfirm: "Combien de pages voulez-vous charger ? (0 pour infini)", + noNext: "Aucun lien suivant trouvé, veuillez créer une nouvelle règle", + passSec: "Mis à jour il y a #t# secondes", + passMin: "Mis à jour il y a #t# minutes", + passHour: "Mis à jour il y a #t# heures", + passDay: "Mis à jour il y a #t# jours", + cantDel: "Impossible de supprimer les règles intégrées", + confirmDel: "Êtes-vous sûr de vouloir supprimer cette règle ?", + updateSucc: "Mise à jour réussie", + beginUpdate: "Début de la mise à jour, veuillez patienter", + customUrls: "Importer l'URL des règles Pagetual ou AutoPagerize, une URL par ligne.", + customRules: "Saisir des règles personnalisées. ✍️Contribuer aux règles", + save: "Enregistrer", + loadingText: "Chargement en cours...", + opacity: "Opacité", + opacityPlaceholder: "0 : masquer le séparateur", + hideBar: "Masquer le séparateur de pagination", + hideBarButNoStop: "Masquer mais ne pas arrêter", + dbClick2Stop: "Double-cliquez sur l'espace vide pour mettre en pause", + sortTitle: "Le tri prendra effet après la prochaine mise à jour des règles", + autoRun: "Activation automatique (mode liste noire)", + autoLoadNum: "Nombre de pages à précharger", + turnRate: "Passer à la page suivante lorsqu'elle est à moins de 【X】 fois la hauteur de la page du pied de page", + inputPageNum: "Entrez le numéro de page pour y accéder", + enableHistory: "Inscrire l'historique de navigation après le changement de page", + enableHistoryAfterInsert: "Inscrire l'historique de navigation immédiatement après la jonction, sinon après la navigation", + contentVisibility: "Basculer automatiquement content-visibility pour améliorer les performances de rendu", + initRun: "Changer de page immédiatement après l'ouverture", + preload: "Précharger la page suivante pour accélérer", + click2ImportRule: "Cliquez pour importer le lien des règles de base, puis attendez la fin de la mise à jour : ", + forceAllBody: "Joindre le corps complet de la page ?", + openInNewTab: "Ouvrir les URL ajoutées dans un nouvel onglet", + importSucc: "Importation terminée", + import: "Importer", + editCurrent: "Modifier la règle pour le site actuel", + editBlacklist: "Modifier la liste noire d'URL, une entrée par ligne, supporte les jokers [?,*].", + upBtnImg: "Icône de retour en haut", + downBtnImg: "Icône d'aller en bas de page", + sideControllerIcon: "Icône de la barre latérale", + loadingTextTitle: "Chargement", + dbClick2StopCtrl: "Touche Ctrl", + dbClick2StopAlt: "Touche Alt", + dbClick2StopShift: "Touche Maj", + dbClick2StopMeta: "Touche Méta", + dbClick2StopKey: "Touche de raccourci", + pageElementCss: "Style personnalisé pour les éléments principaux de la page", + customCss: "CSS complet personnalisé", + firstAlert: "Vous n'avez pas importé la règle de base, veuillez sélectionner la règle appropriée à importer", + picker: "Sélecteur d'éléments Pagetual", + closePicker: "Fermer le sélecteur Pagetual", + pickerPlaceholder: "Sélecteur d'élément (Utilisateurs avancés seulement, laissez vide sinon)", + pickerCheck: "Vérifier le sélecteur et copier", + switchSelector: "Cliquez pour changer d'élément", + gotoEdit: "Aller à l'édition de la règle avec le sélecteur actuel", + manualMode: "Désactiver la jonction, avancer manuellement à la page suivante avec la flèche droite (ou envoyer l'événement 'pagetual.next')", + clickMode: "Désactiver la jonction, cliquer automatiquement sur la page suivante en faisant défiler jusqu'à la fin de la page", + pageBarMenu: "Cliquez au centre de la barre de page pour ouvrir le menu du sélecteur", + nextSwitch: "Changer de lien suivant", + arrowToScroll: "Appuyez sur la flèche gauche pour revenir en arrière et la flèche droite pour avancer", + sideController: "Afficher la barre de contrôle de pagination dans la barre latérale", + sideControllerScroll: "Afficher au défilement", + sideControllerAlways: "Toujours afficher", + hideLoadingIcon: "Masquer l'animation de chargement", + hideBarArrow: "Masquer les flèches de la barre de page", + duplicate: "Un doublon de Pagetual a été installé, vérifiez votre gestionnaire de scripts !", + forceStateIframe: "Intégrer la page complète en tant qu'iframe", + forceStateDynamic: "Charger le contenu dynamique via iframe", + forceStateDisable: "Désactiver le changement de page sur ce site", + autoScrollRate: "Vitesse de défilement (1~1000)", + disableAutoScroll: "Arrêter le défilement auto", + enableAutoScroll: "Activer le défilement auto", + toggleAutoScroll: "Basculer le défilement auto", + ruleRequest: "Demande de règle", + page: "Page ", + prevPage: "Page préc.", + nextPage: "Page suiv.", + errorRulesMustBeArray: "Les règles doivent être un tableau (Array) !", + errorJson: "Erreur JSON, veuillez vérifier !", + editSuccess: "Modification réussie", + errorWrongUrl: "URL incorrecte, veuillez vérifier !", + errorAlreadyExists: "Une règle existe déjà !", + settingsSaved: "Les paramètres sont enregistrés, actualisez pour voir les changements", + iframe: "Division forcée par iframe", + dynamic: "Chargement dynamique", + reloadPage: "Modification terminée, recharger maintenant ?", + copied: "Copié", + noValidContent: "Aucun contenu valide détecté, un Captcha peut être présent", + outOfDate: "Le script est obsolète, veuillez mettre à jour vers la dernière version.", + hideBarTips: "Masquer la barre de pagination, basculer l'expérience immersive", + setConfigPage: "Définir la page actuelle comme page de configuration par défaut", + wedata2github: "Changer l'adresse wedata pour l'adresse miroir dans le dépôt github", + addOtherProp: "Ajouter des propriétés à la règle", + addNextSelector: "Ajouter le contenu du sélecteur comme nextLink", + addPageSelector: "Ajouter le contenu du sélecteur comme pageElement", + propName: "Entrez le nom de la propriété de la règle", + propValue: "Entrez la valeur de la propriété de la règle", + customFirst: "Ignorer le cache pour les règles personnalisées locales", + rulesExample: "Exemple de règles", + lastPage: "Dernière page atteinte", + lastPageTips: "Afficher une notification en atteignant la dernière page" + } + }, + { + name: "Bahasa Indonesia", + match: ["id"], + lang: { + enableDebug: "Aktifkan output debug ke konsol", + updateNotification: "Notifikasi setelah aturan diperbarui", + disable: "Nonaktifkan sementara", + disableSite: "Ubah status nonaktif", + disableSiteTips: "Dinonaktifkan di situs ini.", + enableSiteTips: "Diaktifkan di situs ini.", + enable: "✅Aktifkan pembalik halaman otomatis", + tempActive: "Aktif sementara", + toTop: "Kembali ke Atas.", + toBottom: "Pergi ke Bawah.", + current: "Halaman Saat Ini.", + forceIframe: "Paksa untuk menggabungkan halaman berikutnya", + cancelForceIframe: "Batalkan penggabungan paksa", + configure: "Konfigurasi Pagetual", + firstUpdate: "Klik di sini untuk menginisialisasi daftar aturan default", + update: "Perbarui aturan online", + click2update: "Klik untuk memperbarui aturan dari URL sekarang", + loadNow: "Muat berikutnya secara otomatis", + loadConfirm: "Berapa halaman yang ingin Anda muat? (0 berarti tak terbatas)", + noNext: "Tautan berikutnya tidak ditemukan, harap buat aturan baru", + passSec: "Diperbarui #t# detik yang lalu", + passMin: "Diperbarui #t# menit yang lalu", + passHour: "Diperbarui #t# jam yang lalu", + passDay: "Diperbarui #t# hari yang lalu", + cantDel: "Tidak dapat menghapus aturan bawaan", + confirmDel: "Apakah Anda yakin ingin menghapus aturan ini?", + updateSucc: "Pembaruan berhasil", + beginUpdate: "Memulai pembaruan, harap tunggu sebentar", + customUrls: "Impor URL aturan Pagetual atau AutoPagerize, satu URL per baris.", + customRules: "Masukkan aturan khusus. ✍️Kontribusi aturan", + save: "Simpan", + loadingText: "Sedang Memuat...", + opacity: "Opasitas", + opacityPlaceholder: "0: sembunyikan pemisah", + hideBar: "Sembunyikan pemisah paginasi", + hideBarButNoStop: "Sembunyikan tapi jangan hentikan", + dbClick2Stop: "Klik dua kali pada ruang kosong untuk menjeda", + sortTitle: "Pengurutan berlaku setelah pembaruan aturan berikutnya", + autoRun: "Aktifkan otomatis (mode daftar hitam)", + autoLoadNum: "Jumlah halaman pramuat", + turnRate: "Buka halaman berikutnya saat jarak dari footer kurang dari 【X】 kali tinggi halaman", + inputPageNum: "Masukkan nomor halaman untuk melompat", + enableHistory: "Tulis riwayat penjelajahan setelah membalik halaman", + enableHistoryAfterInsert: "Tulis riwayat penjelajahan segera setelah penyambungan, jika tidak, tulis setelah menjelajah", + contentVisibility: "Secara otomatis mengganti content-visibility untuk meningkatkan kinerja rendering", + initRun: "Balik halaman segera setelah dibuka", + preload: "Pramuat halaman berikutnya untuk mempercepat", + click2ImportRule: "Klik untuk mengimpor tautan aturan dasar, lalu tunggu hingga pembaruan selesai: ", + forceAllBody: "Gabungkan seluruh badan halaman?", + openInNewTab: "Buka URL tambahan di tab baru", + importSucc: "Impor selesai", + import: "Impor", + editCurrent: "Edit aturan untuk situs web saat ini", + editBlacklist: "Edit daftar hitam URL, satu entri per baris, Mendukung wildcard [?,*].", + upBtnImg: "Ikon kembali ke atas", + downBtnImg: "Ikon pergi ke footer", + sideControllerIcon: "Ikon bilah sisi", + loadingTextTitle: "Memuat", + dbClick2StopCtrl: "Tombol Ctrl", + dbClick2StopAlt: "Tombol Alt", + dbClick2StopShift: "Tombol Shift", + dbClick2StopMeta: "Tombol Meta", + dbClick2StopKey: "Tombol pintas", + pageElementCss: "Gaya kustom untuk elemen halaman utama", + customCss: "CSS kustom lengkap", + firstAlert: "Anda belum mengimpor aturan dasar, silakan pilih aturan yang sesuai untuk diimpor", + picker: "Pemilih elemen Pagetual", + closePicker: "Tutup pemilih Pagetual", + pickerPlaceholder: "Selektor elemen, (Hanya pengguna tingkat lanjut, biarkan kosong jika tidak)", + pickerCheck: "Periksa selektor dan salin", + switchSelector: "Klik untuk mengganti elemen", + gotoEdit: "Pergi ke edit aturan dengan selektor saat ini", + manualMode: "Nonaktifkan penyambungan, maju ke halaman berikutnya secara manual menggunakan tombol panah kanan (atau kirim acara 'pagetual.next')", + clickMode: "Nonaktifkan penyambungan, klik halaman berikutnya secara otomatis saat menggulir ke akhir halaman", + pageBarMenu: "Klik tengah bilah halaman untuk membuka menu pemilih", + nextSwitch: "Ganti tautan berikutnya", + arrowToScroll: "Tekan panah kiri untuk menggulir ke belakang dan panah kanan untuk maju halaman", + sideController: "Tampilkan bilah kontrol paging di bilah sisi", + sideControllerScroll: "Tampilkan saat bergulir", + sideControllerAlways: "Selalu tampilkan", + hideLoadingIcon: "Sembunyikan animasi memuat", + hideBarArrow: "Sembunyikan panah untuk bilah halaman", + duplicate: "Pagetual duplikat telah diinstal, periksa manajer skrip Anda!", + forceStateIframe: "Sematkan halaman penuh sebagai iframe", + forceStateDynamic: "Muat konten dinamis melalui iframe", + forceStateDisable: "Nonaktifkan pembalik halaman di situs ini", + autoScrollRate: "Kecepatan gulir (1~1000)", + disableAutoScroll: "Hentikan Gulir Otomatis", + enableAutoScroll: "Aktifkan Gulir Otomatis", + toggleAutoScroll: "Ubah Gulir Otomatis", + ruleRequest: "Permintaan Aturan", + page: "Halaman ", + prevPage: "Halaman seb.", + nextPage: "Halaman ber.", + errorRulesMustBeArray: "Aturan harus berupa Array!", + errorJson: "Kesalahan JSON, Periksa lagi!", + editSuccess: "Berhasil diedit", + errorWrongUrl: "URL salah, Periksa lagi!", + errorAlreadyExists: "Aturan sudah ada!", + settingsSaved: "Pengaturan disimpan, segarkan untuk melihat", + iframe: "Pemisahan paksa oleh iframe", + dynamic: "Pemuatan dinamis", + reloadPage: "Pengeditan selesai, muat ulang sekarang?", + copied: "Disalin", + noValidContent: "Tidak ada konten valid yang terdeteksi, mungkin ada Captcha", + outOfDate: "Skrip sudah usang, harap perbarui ke versi terbaru.", + hideBarTips: "Sembunyikan bilah paginasi, alihkan pengalaman imersif", + setConfigPage: "Atur halaman saat ini sebagai halaman konfigurasi default", + wedata2github: "Ubah alamat wedata ke alamat cermin di repositori github", + addOtherProp: "Tambahkan properti aturan", + addNextSelector: "Tambahkan konten selektor sebagai nextLink", + addPageSelector: "Tambahkan konten selektor sebagai pageElement", + propName: "Masukkan nama properti aturan", + propValue: "Masukkan nilai properti aturan", + customFirst: "Abaikan cache untuk aturan kustom lokal", + rulesExample: "Contoh Aturan", + lastPage: "Telah mencapai halaman terakhir", + lastPageTips: "Tampilkan tip saat mencapai halaman terakhir" + } + }, { // Traduzido por Thiago Ramos (thiagojramos@outlook.com). name: "Português (Brasil)", - match: ["pt", "pt-BR"], + match: ["pt", "pt-BR", "pt-PT"], lang: { enableDebug: "Ativar log de depuração no console.", updateNotification: "Notificar após a atualização das regras", @@ -250,7 +3022,8 @@ disableSite: "Rolagem infinita: Ativar / Desativar.", disableSiteTips: "Desabilitado neste site.", enableSiteTips: "Ativado neste site.", - enable: "Ativar rolagem automática de página.", + enable: "✅Ativar rolagem automática de página.", + tempActive: "Temporariamente ativo", toTop: "Voltar ao Topo.", toBottom: "Ir para o Rodapé.", current: "Página Atual.", @@ -363,10 +3136,258 @@ lastPageTips: "Mostrar dicas ao atingir a última página" } }, + { + name: "Français", + match: ["fr"], + lang: { + enableDebug: "Activer la sortie de débogage dans la console", + updateNotification: "Notification après la mise à jour des règles", + disable: "Désactiver temporairement", + disableSite: "Basculer l'état de désactivation", + disableSiteTips: "Désactivé sur ce site.", + enableSiteTips: "Activé sur ce site.", + enable: "✅Activer le changement de page automatique", + tempActive: "Temporairement actif", + toTop: "Retour en haut.", + toBottom: "Aller en bas.", + current: "Page actuelle.", + forceIframe: "Forcer la jonction de la page suivante", + cancelForceIframe: "Annuler la jonction forcée", + configure: "Configurer Pagetual", + firstUpdate: "Cliquez ici pour initialiser la liste de règles par défaut", + update: "Mettre à jour les règles en ligne", + click2update: "Cliquez pour mettre à jour les règles depuis l'URL maintenant", + loadNow: "Charger la suite automatiquement", + loadConfirm: "Combien de pages voulez-vous charger ? (0 pour infini)", + noNext: "Aucun lien suivant trouvé, veuillez créer une nouvelle règle", + passSec: "Mis à jour il y a #t# secondes", + passMin: "Mis à jour il y a #t# minutes", + passHour: "Mis à jour il y a #t# heures", + passDay: "Mis à jour il y a #t# jours", + cantDel: "Impossible de supprimer les règles intégrées", + confirmDel: "Êtes-vous sûr de vouloir supprimer cette règle ?", + updateSucc: "Mise à jour réussie", + beginUpdate: "Début de la mise à jour, veuillez patienter", + customUrls: "Importer l'URL des règles Pagetual ou AutoPagerize, une URL par ligne.", + customRules: "Saisir des règles personnalisées. ✍️Contribuer aux règles", + save: "Enregistrer", + loadingText: "Chargement en cours...", + opacity: "Opacité", + opacityPlaceholder: "0 : masquer le séparateur", + hideBar: "Masquer le séparateur de pagination", + hideBarButNoStop: "Masquer mais ne pas arrêter", + dbClick2Stop: "Double-cliquez sur l'espace vide pour mettre en pause", + sortTitle: "Le tri prendra effet après la prochaine mise à jour des règles", + autoRun: "Activation automatique (mode liste noire)", + autoLoadNum: "Nombre de pages à précharger", + turnRate: "Passer à la page suivante lorsqu'elle est à moins de 【X】 fois la hauteur de la page du pied de page", + inputPageNum: "Entrez le numéro de page pour y accéder", + enableHistory: "Inscrire l'historique de navigation après le changement de page", + enableHistoryAfterInsert: "Inscrire l'historique de navigation immédiatement après la jonction, sinon après la navigation", + contentVisibility: "Basculer automatiquement content-visibility pour améliorer les performances de rendu", + initRun: "Changer de page immédiatement après l'ouverture", + preload: "Précharger la page suivante pour accélérer", + click2ImportRule: "Cliquez pour importer le lien des règles de base, puis attendez la fin de la mise à jour : ", + forceAllBody: "Joindre le corps complet de la page ?", + openInNewTab: "Ouvrir les URL ajoutées dans un nouvel onglet", + importSucc: "Importation terminée", + import: "Importer", + editCurrent: "Modifier la règle pour le site actuel", + editBlacklist: "Modifier la liste noire d'URL, une entrée par ligne, supporte les jokers [?,*].", + upBtnImg: "Icône de retour en haut", + downBtnImg: "Icône d'aller en bas de page", + sideControllerIcon: "Icône de la barre latérale", + loadingTextTitle: "Chargement", + dbClick2StopCtrl: "Touche Ctrl", + dbClick2StopAlt: "Touche Alt", + dbClick2StopShift: "Touche Maj", + dbClick2StopMeta: "Touche Méta", + dbClick2StopKey: "Touche de raccourci", + pageElementCss: "Style personnalisé pour les éléments principaux de la page", + customCss: "CSS complet personnalisé", + firstAlert: "Vous n'avez pas importé la règle de base, veuillez sélectionner la règle appropriée à importer", + picker: "Sélecteur d'éléments Pagetual", + closePicker: "Fermer le sélecteur Pagetual", + pickerPlaceholder: "Sélecteur d'élément (Utilisateurs avancés seulement, laissez vide sinon)", + pickerCheck: "Vérifier le sélecteur et copier", + switchSelector: "Cliquez pour changer d'élément", + gotoEdit: "Aller à l'édition de la règle avec le sélecteur actuel", + manualMode: "Désactiver la jonction, avancer manuellement à la page suivante avec la flèche droite (ou envoyer l'événement 'pagetual.next')", + clickMode: "Désactiver la jonction, cliquer automatiquement sur la page suivante en faisant défiler jusqu'à la fin de la page", + pageBarMenu: "Cliquez au centre de la barre de page pour ouvrir le menu du sélecteur", + nextSwitch: "Changer de lien suivant", + arrowToScroll: "Appuyez sur la flèche gauche pour revenir en arrière et la flèche droite pour avancer", + sideController: "Afficher la barre de contrôle de pagination dans la barre latérale", + sideControllerScroll: "Afficher au défilement", + sideControllerAlways: "Toujours afficher", + hideLoadingIcon: "Masquer l'animation de chargement", + hideBarArrow: "Masquer les flèches de la barre de page", + duplicate: "Un doublon de Pagetual a été installé, vérifiez votre gestionnaire de scripts !", + forceStateIframe: "Intégrer la page complète en tant qu'iframe", + forceStateDynamic: "Charger le contenu dynamique via iframe", + forceStateDisable: "Désactiver le changement de page sur ce site", + autoScrollRate: "Vitesse de défilement (1~1000)", + disableAutoScroll: "Arrêter le défilement auto", + enableAutoScroll: "Activer le défilement auto", + toggleAutoScroll: "Basculer le défilement auto", + ruleRequest: "Demande de règle", + page: "Page ", + prevPage: "Page préc.", + nextPage: "Page suiv.", + errorRulesMustBeArray: "Les règles doivent être un tableau (Array) !", + errorJson: "Erreur JSON, veuillez vérifier !", + editSuccess: "Modification réussie", + errorWrongUrl: "URL incorrecte, veuillez vérifier !", + errorAlreadyExists: "Une règle existe déjà !", + settingsSaved: "Les paramètres sont enregistrés, actualisez pour voir les changements", + iframe: "Division forcée par iframe", + dynamic: "Chargement dynamique", + reloadPage: "Modification terminée, recharger maintenant ?", + copied: "Copié", + noValidContent: "Aucun contenu valide détecté, un Captcha peut être présent", + outOfDate: "Le script est obsolète, veuillez mettre à jour vers la dernière version.", + hideBarTips: "Masquer la barre de pagination, basculer l'expérience immersive", + setConfigPage: "Définir la page actuelle comme page de configuration par défaut", + wedata2github: "Changer l'adresse wedata pour l'adresse miroir dans le dépôt github", + addOtherProp: "Ajouter des propriétés à la règle", + addNextSelector: "Ajouter le contenu du sélecteur comme nextLink", + addPageSelector: "Ajouter le contenu du sélecteur comme pageElement", + propName: "Entrez le nom de la propriété de la règle", + propValue: "Entrez la valeur de la propriété de la règle", + customFirst: "Ignorer le cache pour les règles personnalisées locales", + rulesExample: "Exemple de règles", + lastPage: "Dernière page atteinte", + lastPageTips: "Afficher une notification en atteignant la dernière page" + } + }, + { + name: "Italiano", + match: ["it"], + lang: { + enableDebug: "Abilita output di debug nella console", + updateNotification: "Notifica dopo l'aggiornamento delle regole", + disable: "Disabilita temporaneamente", + disableSite: "Attiva/disattiva lo stato di disabilitazione", + disableSiteTips: "Disabilitato su questo sito.", + enableSiteTips: "Abilitato su questo sito.", + enable: "✅Abilita il cambio pagina automatico", + tempActive: "Temporaneamente attivo", + toTop: "Torna in cima.", + toBottom: "Vai in fondo.", + current: "Pagina corrente.", + forceIframe: "Forza l'unione della pagina successiva", + cancelForceIframe: "Annulla unione forzata", + configure: "Configura Pagetual", + firstUpdate: "Clicca qui per inizializzare l'elenco delle regole predefinite", + update: "Aggiorna regole online", + click2update: "Clicca per aggiornare le regole dall'URL ora", + loadNow: "Carica la prossima automaticamente", + loadConfirm: "Quante pagine vuoi caricare? (0 significa infinite)", + noNext: "Nessun link 'successivo' trovato, crea una nuova regola", + passSec: "Aggiornato #t# secondi fa", + passMin: "Aggiornato #t# minuti fa", + passHour: "Aggiornato #t# ore fa", + passDay: "Aggiornato #t# giorni fa", + cantDel: "Impossibile eliminare le regole predefinite", + confirmDel: "Sei sicuro di voler eliminare questa regola?", + updateSucc: "Aggiornamento riuscito", + beginUpdate: "Inizio aggiornamento, attendere un momento prego", + customUrls: "Importa URL di regole Pagetual o AutoPagerize, un URL per riga.", + customRules: "Inserisci regole personalizzate. ✍️Contribuisci alle regole", + save: "Salva", + loadingText: "Caricamento in corso...", + opacity: "Opacità", + opacityPlaceholder: "0: nascondi separatore", + hideBar: "Nascondi il separatore di pagina", + hideBarButNoStop: "Nascondi ma non fermare", + dbClick2Stop: "Fai doppio clic sullo spazio vuoto per mettere in pausa", + sortTitle: "L'ordinamento avrà effetto dopo il prossimo aggiornamento delle regole", + autoRun: "Abilitazione automatica (modalità lista nera)", + autoLoadNum: "Numero di pagine da precaricare", + turnRate: "Gira alla pagina successiva quando la distanza dal fondo è inferiore a 【X】 volte l'altezza della pagina", + inputPageNum: "Inserisci il numero di pagina a cui saltare", + enableHistory: "Scrivi la cronologia di navigazione dopo aver girato pagina", + enableHistoryAfterInsert: "Scrivi la cronologia subito dopo l'unione, altrimenti dopo la navigazione", + contentVisibility: "Cambia automaticamente content-visibility per migliorare le prestazioni di rendering", + initRun: "Inizia a girare le pagine subito dopo l'apertura", + preload: "Precarica la pagina successiva per velocizzare", + click2ImportRule: "Clicca per importare il link delle regole di base, poi attendi il completamento dell'aggiornamento: ", + forceAllBody: "Unire l'intero corpo della pagina?", + openInNewTab: "Apri gli URL aggiunti in una nuova scheda", + importSucc: "Importazione completata", + import: "Importa", + editCurrent: "Modifica regola per il sito corrente", + editBlacklist: "Modifica la lista nera di URL, una voce per riga, supporta i caratteri jolly [?,*].", + upBtnImg: "Icona per tornare in cima", + downBtnImg: "Icona per andare in fondo", + sideControllerIcon: "Icona della barra laterale", + loadingTextTitle: "Caricamento", + dbClick2StopCtrl: "Tasto Ctrl", + dbClick2StopAlt: "Tasto Alt", + dbClick2StopShift: "Tasto Maiusc", + dbClick2StopMeta: "Tasto Meta", + dbClick2StopKey: "Tasto di scelta rapida", + pageElementCss: "Stile personalizzato per gli elementi principali della pagina", + customCss: "CSS completo personalizzato", + firstAlert: "Non hai importato la regola di base, seleziona la regola appropriata da importare", + picker: "Selettore di elementi Pagetual", + closePicker: "Chiudi selettore Pagetual", + pickerPlaceholder: "Selettore di elementi (Solo utenti esperti, altrimenti lasciare vuoto)", + pickerCheck: "Controlla selettore e copia", + switchSelector: "Clicca per cambiare elemento", + gotoEdit: "Vai alla modifica della regola con il selettore corrente", + manualMode: "Disabilita unione, avanza manualmente alla pagina successiva con la freccia destra (o invia l'evento 'pagetual.next')", + clickMode: "Disabilita unione, clicca automaticamente la pagina successiva scorrendo fino alla fine", + pageBarMenu: "Clicca al centro della barra di pagina per aprire il menu del selettore", + nextSwitch: "Cambia link successivo", + arrowToScroll: "Premi freccia sinistra per scorrere indietro e freccia destra per avanzare di pagina", + sideController: "Mostra la barra di controllo della paginazione nella barra laterale", + sideControllerScroll: "Mostra durante lo scorrimento", + sideControllerAlways: "Mostra sempre", + hideLoadingIcon: "Nascondi animazione di caricamento", + hideBarArrow: "Nascondi frecce della barra di pagina", + duplicate: "È stato installato un duplicato di Pagetual, controlla il tuo gestore di script!", + forceStateIframe: "Incorpora la pagina intera come iframe", + forceStateDynamic: "Carica contenuto dinamico tramite iframe", + forceStateDisable: "Disabilita il cambio pagina su questo sito", + autoScrollRate: "Velocità di scorrimento (1~1000)", + disableAutoScroll: "Ferma scorrimento automatico", + enableAutoScroll: "Abilita scorrimento automatico", + toggleAutoScroll: "Attiva/disattiva scorrimento automatico", + ruleRequest: "Richiesta regola", + page: "Pagina ", + prevPage: "Pagina prec.", + nextPage: "Pagina succ.", + errorRulesMustBeArray: "Le regole devono essere un Array!", + errorJson: "Errore JSON, controlla di nuovo!", + editSuccess: "Modificato con successo", + errorWrongUrl: "URL errato, controlla di nuovo!", + errorAlreadyExists: "Una regola esiste già!", + settingsSaved: "Le impostazioni sono state salvate, aggiorna per visualizzare", + iframe: "Divisione forzata tramite iframe", + dynamic: "Caricamento dinamico", + reloadPage: "Modifica completata, ricaricare ora?", + copied: "Copiato", + noValidContent: "Nessun contenuto valido rilevato, potrebbe esserci un Captcha", + outOfDate: "Lo script non è aggiornato, si prega di aggiornare all'ultima versione.", + hideBarTips: "Nascondi la barra di paginazione, attiva/disattiva l'esperienza immersiva", + setConfigPage: "Imposta la pagina corrente come pagina di configurazione predefinita", + wedata2github: "Cambia l'indirizzo wedata con l'indirizzo mirror nel repository github", + addOtherProp: "Aggiungi proprietà alla regola", + addNextSelector: "Aggiungi contenuto del selettore come nextLink", + addPageSelector: "Aggiungi contenuto del selettore come pageElement", + propName: "Inserisci il nome della proprietà della regola", + propValue: "Inserisci il valore della proprietà della regola", + customFirst: "Ignora la cache per le regole personalizzate locali", + rulesExample: "Esempio di regole", + lastPage: "Raggiunta l'ultima pagina", + lastPageTips: "Mostra un avviso quando si raggiunge l'ultima pagina" + } + }, { // Translated by SrKalopsia (srkalopsia@gmail.com). name: "Español", - match: ["es", "es-ES"], + match: ["es", "es-AR", "es-BO", "es-CL", "es-CO", "es-CR", "es-DO", "es-EC", "es-ES", "es-GT", "es-HN", "es-MX", "es-NI", "es-PA", "es-PE", "es-PR", "es-PY", "es-SV", "es-UY", "es-VE"], lang: { enableDebug: "Habilitar salida de depuración", updateNotification: "Notificación después de actualizar las reglas", @@ -374,7 +3395,8 @@ disableSite: "Alternar estado desactivado", disableSiteTips: "Desactivado en este sitio", enableSiteTips: "Activado en este sitio", - enable: "Habilitar", + enable: "✅Habilitar", + tempActive: "Temporalmente activo", toTop: "Ir al inicio", toBottom: "Ir al final", current: "Página actual", @@ -500,6 +3522,7 @@ disableSiteTips: "%D9%85%D8%B9%D8%B7%D9%84%20%D8%B9%D9%84%D9%89%20%D9%87%D8%B0%D8%A7%20%D8%A7%D9%84%D9%85%D9%88%D9%82%D8%B9", enableSiteTips: "%D9%85%D9%81%D8%B9%D9%84%20%D8%B9%D9%84%D9%89%20%D9%87%D8%B0%D8%A7%20%D8%A7%D9%84%D9%85%D9%88%D9%82%D8%B9", enable: "%D9%85%D9%81%D8%B9%D9%84", + tempActive: "%D9%86%D8%B4%D8%B7%20%D9%85%D8%A4%D9%82%D8%AA%D8%A7", toTop: "%D8%A5%D9%84%D9%89%20%D8%A7%D9%84%D8%A3%D8%B9%D9%84%D9%89", toBottom: "%D8%A5%D9%84%D9%89%20%D8%A7%D9%84%D8%A3%D8%B3%D9%81%D9%84", current: "%D8%A7%D9%84%D8%B5%D9%81%D8%AD%D8%A9%20%D8%A7%D9%84%D8%AD%D8%A7%D9%84%D9%8A%D8%A9", @@ -622,7 +3645,8 @@ disableSite: "站点禁用开关", disableSiteTips: "已在此站禁用", enableSiteTips: "已在此站启用", - enable: "启用自动翻页", + enable: "✅启用自动翻页", + tempActive: "临时启用翻页", toTop: "回到顶部", toBottom: "前往页尾", current: "当前页", @@ -745,7 +3769,8 @@ disableSite: "站點禁用開關", disableSiteTips: "已在此站禁用", enableSiteTips: "已在此站啟用", - enable: "啟用自動翻頁", + enable: "✅啟用自動翻頁", + tempActive: "臨時啟用翻頁", toTop: "回到頂部", toBottom: "前往頁尾", current: "當前頁", @@ -860,7 +3885,7 @@ }, { name: "日本語", - match: ["ja"], + match: ["ja", "ja-JP"], lang: { enableDebug: "デバッグモード", updateNotification: "ルール更新後の通知", @@ -868,7 +3893,8 @@ disableSite: "無効状態の切り替え", disableSiteTips: "このサイトで既に無効になっています", enableSiteTips: "このサイトで既に有効になっています", - enable: "ページめくりを有効にする", + enable: "✅ページめくりを有効にする", + tempActive: "一時的にアクティブ", toTop: "トップに戻る", toBottom: "ページの下部に移動", current: "現在のページ", @@ -877,7 +3903,7 @@ configure: "設定ページを開く", firstUpdate: "ここをクリックしてルールを初期化します", update: "更新ルール", - click2update: "今すぐルールを更新してください", + click2update: "今すぐルールを更新", loadNow: "今すぐページをめくる", loadConfirm: "数ページめくりたいですか?(0は途切れない)", noNext: "次のページが見つかりません、新しいルールを作成してください", @@ -890,7 +3916,7 @@ updateSucc: "更新に成功しました", beginUpdate: "更新中、お待ちください", customUrls: "インポートルールのURL、1行に1つ", - customRules: "【東方永頁機】の形式でカスタムルールを入力してください ✍️寄稿ルール", + customRules: "【東方永頁機】の形式でルールを入力してください ✍️寄稿", save: "設定を保存", loadingText: "少女祈祷中...", opacity: "不透明値", @@ -899,7 +3925,7 @@ hideBarButNoStop: "非表示にするが停止しない", dbClick2Stop: "空白部分をダブルクリックしてページめくりを一時停止します", sortTitle: "並べ替えは、次のルールの更新後に有効になります", - autoRun: "自動的に有効", + autoRun: "自動的に有効 (blacklist mode)", autoLoadNum: "指定したページ数を自動的に読み込みます", turnRate: "ページの端からページの高さの【X】倍になったらページをめくる", inputPageNum: "ジャンプするページ番号を入力", @@ -915,9 +3941,9 @@ import: "インポート", editCurrent: "現在のルールの編集", editBlacklist: "ブラックリストのURLを編集し、1行ずつ、サポート? *ワイルドカード", - upBtnImg: "トップアイコンに戻る", - downBtnImg: "フッターアイコンに移動", - sideControllerIcon: "サイドバー アイコン", + upBtnImg: "Icon of back to top", + downBtnImg: "Icon of go to footer", + sideControllerIcon: "Icon of sidebar", loadingTextTitle: "テキストをロード", dbClick2StopCtrl: "Ctrlキー", dbClick2StopAlt: "Altキー", @@ -991,7 +4017,8 @@ disableSite: "Включить/выключить на сайте", disableSiteTips: "Выключено для этого сайта", enableSiteTips: "Включено для этого сайта", - enable: "Включить", + enable: "✅Включить", + tempActive: "Временно активен", toTop: "Наверх", toBottom: "Вниз", current: "Текущая страница", @@ -1111,6 +4138,7 @@ }); var i18nData = langData[0].lang; function setLang(la) { + langName = la; for (let i = 0; i < langData.length; i++) { let lang = langData[i]; if (lang && lang.match.indexOf(la) !== -1) { @@ -1124,7 +4152,7 @@ } } } - setLang(lang); + setLang(langName); var enableDebug = true; var _GM_xmlhttpRequest, _GM_registerMenuCommand, _GM_notification, _GM_addStyle, _GM_openInTab, _GM_info, _GM_setClipboard; function i18n(name, param) { @@ -1135,18 +4163,205 @@ if (enableDebug) { console.log( `%c【Pagetual v.${_GM_info.script.version}】 ${title ? title : 'debug'}:`, - 'color: yellow;font-size: large;font-weight: bold;background-color: darkblue;', + 'color: yellow;font-size: large;font-weight: bold;background-color: darkblue;border-radius: 10px;text-shadow: 1px 1px 3px black;padding: 5px;', str ); } } + function requestWithFetch(f, onFetchError) { + function getHeaderValue(headers, name) { + if (!headers || !name) return ""; + let lowerName = String(name).toLowerCase(); + if (typeof Headers !== "undefined" && headers instanceof Headers) { + return headers.get(lowerName) || ""; + } + if (typeof headers === "object") { + for (let key in headers) { + if (Object.prototype.hasOwnProperty.call(headers, key) && String(key).toLowerCase() === lowerName) { + return headers[key] || ""; + } + } + } + return ""; + } + function extractCharsetFromContentType(contentType) { + if (!contentType || typeof contentType !== "string") return ""; + let match = contentType.match(/charset\s*=\s*["']?([^;"'\s]+)/i); + return match && match[1] ? match[1].trim() : ""; + } + function decodeArrayBufferByCharset(buffer, preferredCharset) { + let bytes = new Uint8Array(buffer); + let decoderList = []; + let normalize = label => String(label || "").trim().toLowerCase(); + let addAlias = (name, aliases) => { + if (aliases.indexOf(normalizedPreferred) !== -1) { + pushDecoder(name); + for (let i = 0; i < aliases.length; i++) { + pushDecoder(aliases[i]); + } + } + }; + let pushDecoder = label => { + let raw = String(label || "").trim(); + if (raw && decoderList.indexOf(raw) === -1) { + decoderList.push(raw); + } + }; + let normalizedPreferred = normalize(preferredCharset).replace(/["']/g, ""); + pushDecoder(preferredCharset); + pushDecoder(normalizedPreferred); + pushDecoder(normalizedPreferred.replace(/_/g, "-")); + pushDecoder(normalizedPreferred.replace(/-/g, "_")); + addAlias("shift_jis", ["shiftjis", "shift-jis", "sjis", "ms_kanji", "windows-31j", "cp932", "ms932"]); + addAlias("euc-jp", ["eucjp"]); + addAlias("iso-2022-jp", ["iso2022jp", "jis"]); + addAlias("gb18030", ["gbk", "gb2312", "x-gbk", "cp936", "ms936", "windows-936"]); + addAlias("big5", ["big-5", "cn-big5", "x-x-big5"]); + addAlias("euc-kr", ["euckr", "ks_c_5601-1987", "ksc5601", "windows-949", "cp949"]); + addAlias("windows-1251", ["cp1251"]); + addAlias("windows-1252", ["cp1252", "iso-8859-1", "latin1", "latin-1"]); + pushDecoder("utf-8"); + for (let i = 0; i < decoderList.length; i++) { + try { + return new TextDecoder(decoderList[i]).decode(bytes); + } catch (e) {} + } + try { + return new TextDecoder().decode(bytes); + } catch (e) { + return ""; + } + } + function detectCharsetFromHtmlHead(buffer) { + if (!buffer || !buffer.byteLength) return ""; + let scanLen = Math.min(buffer.byteLength, 16384); + let bytes = new Uint8Array(buffer, 0, scanLen); + let ascii = ""; + for (let i = 0; i < bytes.length; i++) { + let code = bytes[i]; + ascii += code < 128 ? String.fromCharCode(code) : " "; + } + let charsetMatch = ascii.match(/]*charset\s*=\s*["']?\s*([a-zA-Z0-9._-]+)/i); + if (!charsetMatch) { + charsetMatch = ascii.match(/]*content\s*=\s*["'][^"']*charset\s*=\s*([a-zA-Z0-9._-]+)/i); + } + return charsetMatch && charsetMatch[1] ? charsetMatch[1].trim() : ""; + } + function isUtf8Charset(label) { + let normalized = String(label || "").trim().toLowerCase().replace(/_/g, "-"); + return !normalized || normalized === "utf-8" || normalized === "utf8"; + } + if (!f || !f.url || typeof fetch === "undefined") { + if (onFetchError) { + onFetchError({error: "Fetch not available"}); + } else if (f && f.onerror) { + f.onerror({error: "Fetch not available"}); + } + return; + } + let method = (f.method || "GET").toUpperCase(); + let timeoutId = null; + let controller = typeof AbortController !== "undefined" ? new AbortController() : null; + if (f.timeout > 0 && controller) { + timeoutId = setTimeout(() => { + controller.abort(); + }, f.timeout); + } + let options = { + method: method, + headers: f.headers || {} + }; + if (controller) options.signal = controller.signal; + if (method !== "GET" && method !== "HEAD" && typeof f.data !== "undefined") { + options.body = f.data; + } + fetch(f.url, options).then(async response => { + if (timeoutId) clearTimeout(timeoutId); + let responseCharset = extractCharsetFromContentType(response.headers.get("content-type") || ""); + let overrideCharset = extractCharsetFromContentType(f.overrideMimeType || ""); + let requestCharset = extractCharsetFromContentType(getHeaderValue(options.headers, "content-type")); + let text; + let charsetFromHeaders = responseCharset || overrideCharset || requestCharset; + if (charsetFromHeaders) { + if (isUtf8Charset(charsetFromHeaders)) { + text = await response.text(); + } else { + text = decodeArrayBufferByCharset(await response.arrayBuffer(), charsetFromHeaders); + } + } else { + let rawBuffer = await response.arrayBuffer(); + let metaCharset = detectCharsetFromHtmlHead(rawBuffer); + let targetCharset = metaCharset || charset || "utf-8"; + if (isUtf8Charset(targetCharset)) { + text = new TextDecoder("utf-8").decode(new Uint8Array(rawBuffer)); + } else { + text = decodeArrayBufferByCharset(rawBuffer, targetCharset); + } + } + let headers = ""; + response.headers.forEach((value, key) => { + headers += key + ": " + value + "\r\n"; + }); + if (f.onload) { + f.onload({ + response: text, + responseText: text, + status: response.status, + statusText: response.statusText, + finalUrl: response.url, + responseHeaders: headers + }); + } + }).catch(error => { + if (timeoutId) clearTimeout(timeoutId); + if (error && error.name === "AbortError" && f.ontimeout) { + f.ontimeout(error); + return; + } + if (onFetchError) { + onFetchError(error); + } else if (f.onerror) { + f.onerror(error); + } + }); + } + function isSameOriginRequest(f) { + if (!f || !f.url || typeof location === "undefined") return false; + try { + return new URL(f.url, location.href).origin === location.origin; + } catch (e) { + return false; + } + } + let nativeGMRequest = null; if (typeof GM_xmlhttpRequest !== 'undefined') { - _GM_xmlhttpRequest = GM_xmlhttpRequest; + nativeGMRequest = GM_xmlhttpRequest; } else if (typeof GM !== 'undefined' && typeof GM.xmlHttpRequest !== 'undefined') { - _GM_xmlhttpRequest = GM.xmlHttpRequest; + nativeGMRequest = GM.xmlHttpRequest; + } + if (nativeGMRequest) { + _GM_xmlhttpRequest = function(f) { + if (!f) return nativeGMRequest(f); + if (isSameOriginRequest(f)) { + requestWithFetch(f); + return; + } + let originalOnerror = f.onerror; + let request = Object.assign({}, f); + request.onerror = function(gmError) { + requestWithFetch(f, function(fetchError) { + if (originalOnerror) { + originalOnerror(fetchError || gmError || {error: "Request failed"}); + } + }); + }; + return nativeGMRequest(request); + }; } else { - _GM_xmlhttpRequest = (f) => {fetch(f.url, {method: f.method || 'GET', body: f.data, headers: f.headers}).then(response => response.text()).then(data => {f.onload && f.onload({response: data})}).catch(f.onerror && f.onerror())}; + _GM_xmlhttpRequest = function(f) { + requestWithFetch(f); + }; } if (typeof GM_registerMenuCommand !== 'undefined') { _GM_registerMenuCommand = GM_registerMenuCommand; @@ -1183,7 +4398,7 @@ } else { _GM_addStyle = cssStr => { let styleEle = document.createElement("style"); - styleEle.innerHTML = cssStr; + setHTML(styleEle, cssStr); document.head.appendChild(styleEle); return styleEle; }; @@ -1289,21 +4504,25 @@ storage.setItem(list, listData); }); } - const isMobile = ('ontouchstart' in document.documentElement); - const configPage = [`https://pagetual.hoothin.com/${lang === 'zh-CN' ? 'cn/' : ''}rule.html`, + const isMobile = ('ontouchstart' in document.documentElement && /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)); + const cnConfigPage = "https://pagetual.hoothin.com/cn/rule.html"; + const configPage = ["https://pagetual.hoothin.com/rule.html", "https://github.com/hoothin/UserScripts/tree/master/Pagetual", "https://hoothin.github.io/UserScripts/Pagetual/"]; const firstRunPage = "https://pagetual.hoothin.com/firstRun"; + const wedataRulesUrl = "http://wedata.net/databases/AutoPagerize/items_all.json"; + const wedataMirrorRulesUrl = "https://hoothin.github.io/UserScripts/Pagetual/items_all.json"; const guidePage = /^https?:\/\/.*pagetual.*rule\.html/i; - const ruleImportUrlReg = /greasyfork\.org\/.*scripts\/438684(\-[^\/]*)?(\/discussions|\/?$|\/feedback)|github\.com\/hoothin\/UserScripts\/(tree\/master\/Pagetual|issues)|^https:\/\/pagetual\.hoothin\.com\/.*firstRun\.html/i; + const ruleImportUrlReg = /greasyfork\.org\/.*scripts\/438684(\-[^\/]*)?(\/discussions|\/?$|\/feedback)|github\.com\/hoothin\/UserScripts\/(tree\/master\/Pagetual|issues)|^https:\/\/pagetual\.hoothin\.com\/.*first(Run|-run)\.html/i; const allOfBody = "body>*"; const mainSel = ["article,.article","[role=main],main,.main,#main","#results"]; - const nextTextReg1 = new RegExp("\u005e\u7ffb\u003f\u005b\u4e0b\u540e\u5f8c\u6b21\u005d\u005b\u4e00\u30fc\u0031\u005d\u003f\u005b\u9875\u9801\u5f20\u5f35\u005d\u007c\u005e\u006e\u0065\u0078\u0074\u005b\u005c\u0073\u005f\u002d\u005d\u003f\u0070\u0061\u0067\u0065\u005c\u0073\u002a\u005b\u203a\u003e\u2192\u00bb\u005d\u003f\u0024\u007c\u6b21\u306e\u30da\u30fc\u30b8\u007c\u005e\u6b21\u3078\u003f\u0024\u007c\u0412\u043f\u0435\u0440\u0435\u0434", "i"); - const nextTextReg2 = new RegExp("\u005e\u0028\u005b\u4e0b\u540e\u5f8c\u6b21\u005d\u005b\u4e00\u30fc\u0031\u005d\u003f\u005b\u7ae0\u8bdd\u8a71\u8282\u7bc0\u5e45\u005d\u007c\u006e\u0065\u0078\u0074\u002e\u003f\u0063\u0068\u0061\u0070\u0074\u0065\u0072\u0029\u0028\u005b\u003a\uff1a\u005c\u002d\u005f\u2014\u005c\u0073\u005c\u002e\u3002\u003e\u0023\u00b7\u005c\u005b\u3010\u3001\uff08\u005c\u0028\u002f\u002c\uff0c\uff1b\u003b\u2192\u005d\u007c\u0024\u0029", "i"); - const prevReg = new RegExp("\u005e\u005c\u0073\u002a\u0028\u005b\u4e0a\u524d\u9996\u5c3e\u005d\u007c\u0070\u0072\u0065\u0076\u0069\u006f\u0075\u0073\u007c\u0065\u006e\u0064\u0029", "i"); + const nextTextReg1 = new RegExp("\u005e\u7ffb\u003f\u005b\u4e0b\u540e\u5f8c\u6b21\u005d\u005b\u4e00\u30fc\u2500\u0031\u005d\u003f\u005b\u9875\u9801\u5f20\u5f35\u005d\u007c\u005e\u006e\u0065\u0078\u0074\u005b\u005c\u0073\u005f\u002d\u005d\u003f\u0070\u0061\u0067\u0065\u005c\u0073\u002a\u005b\u203a\u003e\u2192\u00bb\u005d\u003f\u0024\u007c\u6b21\u306e\u30da\u30fc\u30b8\u007c\u005e\u6b21\u3078\u0024\u007c\u0412\u043f\u0435\u0440\u0435\u0434\u007c\u005e\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435", "i"); + const nextTextReg2 = new RegExp("\u005e\u0028\u005b\u4e0b\u540e\u5f8c\u6b21\u005d\u005b\u4e00\u30fc\u2500\u0031\u005d\u003f\u005b\u7ae0\u8bdd\u8a71\u8282\u7bc0\u5e45\u005d\u007c\u006e\u0065\u0078\u0074\u002e\u003f\u0063\u0068\u0061\u0070\u0074\u0065\u0072\u0029\u0028\u005b\u003a\uff1a\u005c\u002d\u005f\u2014\u005c\u0073\u005c\u002e\u3002\u003e\u0023\u00b7\u005c\u005b\u3010\u3001\uff08\u005c\u0028\u002f\u002c\uff0c\uff1b\u003b\u2192\u005d\u007c\u0024\u0029", "i"); + const nextTextReg3 = /^(next\s*(»|>>|>|›|→|❯|\d+)?|>|▶|>|›|→|❯)\s*$/i; + const prevReg = new RegExp("\u005e\u005c\u0073\u002a\u0028\u005b\u4e0a\u524d\u9996\u5c3e\u005d\u007c\u0070\u0072\u0065\u0076\u007c\u0065\u006e\u0064\u0029", "i"); const lazyImgAttr = ["data-lazy-src", "data-s", "data-lazy", "data-isrc", "data-url", "data-orig-file", "zoomfile", "file", "original", "load-src", "imgsrc", "real_src", "src2", "origin-src", "data-lazyload", "data-lazyload-src", "data-lazy-load-src", "data-ks-lazyload", "data-ks-lazyload-custom", "data-src", "data-defer-src", "data-actualsrc", "data-cover", "data-original", "data-thumb", "data-imageurl", "data-placeholder", "lazysrc"]; var rulesData = {uninited: true, firstRun: true, sideController: !isMobile}, ruleUrls, updateDate, loadNowNum = 5, autoScrollRate = 50; - var isPause = false, manualPause = false, isHideBar = false, isLoading = false, curPage = 1, forceState = 0, autoScroll = 0, autoScrollInterval, bottomGap = 1000, autoLoadNum = -1, nextIndex = 0, stopScroll = false, clickMode = false, openInNewTab = 0, charset = "UTF-8", charsetValid = true, urlWillChange = false, hidePageBar = false; + var isPause = false, manualPause = false, isHideBar = false, isLoading = false, curPage = 1, forceState = 0, autoScroll = 0, autoScrollInterval, bottomGap = 1000, autoLoadNum = -1, initAutoLoadNum = 0, nextIndex = 0, stopScroll = false, clickMode = false, openInNewTab = 0, charset = "UTF-8", charsetValid = true, urlWillChange = false, hidePageBar = false; var tryTimes = 0, showedLastPageTips = false, rate = 1, author = ''; function getBody(doc) { @@ -1535,12 +4754,211 @@ return segs.length ? '/' + segs.join('/') : null; } - const escapeHTMLPolicy = (_unsafeWindow.trustedTypes && _unsafeWindow.trustedTypes.createPolicy) ? _unsafeWindow.trustedTypes.createPolicy('pagetual_default', { - createHTML: (string, sink) => string - }) : null; + function createHTML(html, doc) { + const targetDoc = doc || document; + const fragment = targetDoc.createDocumentFragment(); + if (html === null || html === undefined || html === '') return fragment; + parseHTMLToFragment(String(html), fragment, targetDoc); + return fragment; + } + let canDirectSetHTML = true; + let canPolicySetHTML = true; + let escapeHTMLPolicy; + let escapeHTMLCreator; + const MY_POLICY_NAME = 'pagetual_default'; + const SVG_NS = 'http://www.w3.org/2000/svg'; + const VOID_TAGS = { + area: true, + base: true, + br: true, + col: true, + embed: true, + hr: true, + img: true, + input: true, + link: true, + meta: true, + param: true, + source: true, + track: true, + wbr: true + }; + const RAW_TEXT_TAGS = { + script: true, + style: true, + textarea: true, + title: true, + xmp: true, + plaintext: true, + noscript: true + }; + const HTML_ENTITIES = { + amp: '&', + lt: '<', + gt: '>', + quot: '"', + apos: "'", + nbsp: '\u00A0' + }; + function decodeEntities(text) { + return text.replace(/&(#x?[0-9a-fA-F]+|[a-zA-Z]+);/g, function(_, code) { + if (code[0] === '#') { + const isHex = code[1] === 'x' || code[1] === 'X'; + const num = parseInt(code.slice(isHex ? 2 : 1), isHex ? 16 : 10); + if (!isNaN(num)) { + try { return String.fromCodePoint(num); } catch(e) {} + } + return '&' + code + ';'; + } + const key = code.toLowerCase(); + return (key in HTML_ENTITIES) ? HTML_ENTITIES[key] : '&' + code + ';'; + }); + } + function parseHTMLToFragment(html, fragment, doc) { + const stack = [fragment]; + const tokenRe = /|]*>|<\/?[a-zA-Z][^>]*>|[^<]+/gi; + let match; + while ((match = tokenRe.exec(html))) { + const token = match[0]; + if (token[0] !== '<') { + const text = decodeEntities(token); + if (text) stack[stack.length - 1].appendChild(doc.createTextNode(text)); + continue; + } + if (token.indexOf('|]*>|<\/?[a-zA-Z][^>]*>|[^<]+/gi; + let match; + while ((match = tokenRe.exec(html))) { + const token = match[0]; + if (token[0] !== '<') { + const text = decodeEntities(token); + if (text) stack[stack.length - 1].appendChild(doc.createTextNode(text)); + continue; + } + if (token.indexOf('|]*>|<\/?[a-zA-Z][^>]*>|[^<]+/gi; + let match; + while ((match = tokenRe.exec(html))) { + const token = match[0]; + if (token[0] !== '<') { + const text = decodeEntities(token); + if (text) stack[stack.length - 1].appendChild(doc.createTextNode(text)); + continue; + } + if (token.indexOf('0){ - if(char_f[x])processChar=char_f[x]+processChar; + if (!char_f[x]) break; + processChar=char_f[x]+processChar; + x++; } x=0; while(badd-->0){ - if(char_b[x])processChar+=char_b[x]; + if (!char_b[x]) break; + processChar+=char_b[x]; + x++; } if(processChar.indexOf(curOther) != -1){ newChar=otherChar; @@ -944,11 +944,15 @@ var curOther=others[k],fadd=curOther.indexOf(char),badd=curOther.length-1-fadd,x=0; var processChar=char; while(fadd-->0){ - if(char_f[x])processChar=char_f[x]+processChar; + if (!char_f[x]) break; + processChar=char_f[x]+processChar; + x++; } x=0; while(badd-->0){ - if(char_b[x])processChar+=char_b[x]; + if (!char_b[x]) break; + processChar+=char_b[x]; + x++; } if(processChar.indexOf(curOther) != -1){ newChar=otherChar; @@ -1122,6 +1126,17 @@ _unsafeWindow.tc2sc = simplized; _unsafeWindow.sc2tc = traditionalized; + window.addEventListener("message", function(event) { + if (event.data && event.data.type === "switchChineseRequest") { + const receivedData = event.data.payload; + const result = receivedData.target === 'sc' ? simplized(receivedData.str) : traditionalized(receivedData.str); + window.postMessage({ + type: "switchChineseResult", + payload: result + }, "*"); + } + }); + var storage = { supportGM: typeof GM_getValue == 'function' && typeof GM_getValue('a', 'b') != 'undefined', supportGMPromise: typeof GM != 'undefined' && typeof GM.getValue == 'function' && typeof GM.getValue('a','b') != 'undefined', @@ -1217,14 +1232,14 @@ curLang = isSimple; } curLang=!curLang; - activeEle.innerHTML=curLang?traditionalized(activeEle.innerHTML):simplized(activeEle.innerHTML); - activeEle.value=curLang?traditionalized(activeEle.value):simplized(activeEle.value); + activeEle.innerHTML=curLang?simplized(activeEle.innerHTML):traditionalized(activeEle.innerHTML); + activeEle.value=curLang?simplized(activeEle.value):traditionalized(activeEle.value); }else if("INPUT"==activeEle.nodeName.toUpperCase()){ if (curInput != activeEle) { curLang = isSimple; } curLang=!curLang; - activeEle.value=curLang?traditionalized(activeEle.value):simplized(activeEle.value); + activeEle.value=curLang?simplized(activeEle.value):traditionalized(activeEle.value); }else{ var selecter; if(window.getSelection()){ @@ -1275,19 +1290,23 @@ var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver; var observer = new MutationObserver(function(records) { records.map(function(record) { + let target = record.target; + let parentNode = target && target.parentNode; + while (target) { + if (/TEXTAREA/i.test(target.nodeName)) return; + if (/INPUT/i.test(target.nodeName) && (target.value === "" || target.type === "text" || target.type === "search" || target.type === "hidden")) { + return; + } + if (target.contentEditable == 'true') return; + if (target.nodeName.toUpperCase() == 'BODY') { + break; + } + target = target.parentNode; + } if (record.type === "characterData") { - let target = record.target; - let parentNode = target && target.parentNode; if (!parentNode) { return; } - while (target) { - if (target.contentEditable == 'true') return; - if (target.nodeName.toUpperCase() == 'BODY') { - break; - } - target = target.parentNode; - } transTask(parentNode); } if(record.addedNodes){ @@ -1709,12 +1728,16 @@ storage.setItem('sc2tcCombConfig', sc2tcCombConfig); } catch (e) { console.log(e); + alert("自訂簡繁用語轉換格式錯誤:" + e); + return; } try { illiteracyConfig = customIlliteracyInput.value ? JSON.parse(customIlliteracyInput.value) : ""; storage.setItem('illiteracyConfig', illiteracyConfig); } catch (e) { console.log(e); + alert("通用字詞轉換格式錯誤:" + e); + return; } storage.setItem('sc2tcCombTree', ""); storage.setItem('tc2scCombTree', ""); @@ -1884,32 +1907,38 @@ function makeCombTree(key, value) { let curTree=sc2tcCombTree; for(let i=0;i=12.0.0" + } } + diff --git a/Switch Traditional Chinese and Simplified Chinese/lib/readme.md b/Switch Traditional Chinese and Simplified Chinese/lib/readme.md index 1f9ed4f33d0..670521a96db 100644 --- a/Switch Traditional Chinese and Simplified Chinese/lib/readme.md +++ b/Switch Traditional Chinese and Simplified Chinese/lib/readme.md @@ -1,56 +1,1082 @@ -簡繁自由切換 -=== -> 切換簡體中文與正體中文 +# switch-chinese + +[Online Demo](https://tool.hoothin.com/chinese-converter) + +[简体中文](#简体中文) | [繁體中文](#繁體中文) | [English](#english) + +--- + +## 简体中文 + +简繁体中文转换库 - 支持简体中文与繁体中文双向转换,基于词组的智能分词处理「一简多繁」问题 [![NPM](https://img.shields.io/npm/v/switch-chinese.svg)](https://www.npmjs.com/package/switch-chinese) [![License](https://img.shields.io/badge/license-MIT-brightgreen.svg)](https://www.npmjs.com/package/switch-chinese) +### 特性 + +- **轻量级**:零依赖,体积小,性能优异 +- **智能转换**:支持基于词组的智能分词和「一简多繁」精准转换 +- **多种数据类型**:支持字符串、数组、对象的转换,自动递归处理嵌套结构 +- **自定义词库**:允许用户自定义简繁转换词汇 +- **缓存机制**:支持字典缓存,避免重复初始化 +- **简繁检测**:自动检测文本是简体中文、繁体中文还是未知类型 +- **术语转换**:内置大陆简体与台湾正体的常用术语转换 +- **无依赖**:纯 JavaScript 实现,无需任何第三方依赖 + +### 安装 + +使用 npm 安装: + +```bash +npm install switch-chinese +``` + +使用 yarn 安装: + +```bash +yarn add switch-chinese +``` + +### 快速开始 + +#### 基础用法 + +```javascript +import stcasc from 'switch-chinese'; + +const { traditionalized, simplized, detect } = stcasc(); + +// 简体转繁体 +const tc = traditionalized('简繁转换 繁简切换 香烟 香烟袅袅'); +console.log(tc); +// 输出: 簡繁轉換 繁簡切換 香菸 香煙裊裊 + +// 繁体转简体 +const sc = simplized('繁體中文'); +console.log(sc); +// 输出: 繁体中文 +``` + +#### 检测中文类型 + +```javascript +import stcasc, { ChineseType } from 'switch-chinese'; + +const { detect } = stcasc(); + +const type1 = detect('简体中文'); +if (type1 === ChineseType.SIMPLIFIED) { + console.log('检测到简体中文'); +} + +const type2 = detect('繁體中文'); +if (type2 === ChineseType.TRADITIONAL) { + console.log('检测到繁体中文'); +} + +const type3 = detect('English'); +if (type3 === ChineseType.UNKNOWN) { + console.log('未检测到中文'); +} +``` + +ChineseType 枚举值: +- `ChineseType.SIMPLIFIED` (0): 简体中文 +- `ChineseType.TRADITIONAL` (1): 繁体中文 +- `ChineseType.UNKNOWN` (2): 未知类型 + +#### 转换数组和对象 + +库支持转换数组和对象中的所有字符串,非字符串值保持原样: + +```javascript +import stcasc from 'switch-chinese'; + +const { traditionalized, simplized } = stcasc(); + +// 转换数组 +const arr = ['简体中文', '软件', '网络', 123, true, null]; +const arrTc = traditionalized(arr); +console.log(arrTc); +// 输出: ['簡體中文', '軟體', '網路', 123, true, null] + +// 转换对象 +const obj = { + title: '简体中文标题', + description: '这是一个简体中文描述', + count: 100, + active: true, + tags: ['软件', '网络', '服务器'] +}; +const objTc = traditionalized(obj); +console.log(objTc); +// 输出: { +// title: '簡體中文標題', +// description: '這是一個簡體中文描述', +// count: 100, +// active: true, +// tags: ['軟體', '網路', '伺服器'] +// } + +// 转换嵌套结构 +const nested = { + user: { + name: '简体名称', + profile: { + bio: '这是简体中文简介', + skills: ['软件开发', '网络管理'] + } + }, + count: 42 +}; +const nestedTc = traditionalized(nested); +// 所有字符串属性值都会被转换,数字等其他类型保持不变 +``` + +### 高级用法 + +#### 使用缓存优化性能 + +在多次调用时,建议使用缓存机制避免重复生成字典,提升性能: + +```javascript +import stcasc from 'switch-chinese'; + +// 第一次调用,生成字典 +let converter = stcasc(); +const cache = converter.cache; + +// 保存缓存到持久化存储(如 localStorage、文件等) +localStorage.setItem('stcasc-cache', JSON.stringify(cache)); + +// 后续调用,直接使用缓存 +const cachedData = JSON.parse(localStorage.getItem('stcasc-cache')); +converter = stcasc(cachedData); + +// 现在可以直接使用,无需重新生成字典 +const result = converter.traditionalized('简体中文'); +``` + +#### 自定义简繁转换词库 + +可以根据业务需求自定义简繁转换规则: + +```javascript +import stcasc from 'switch-chinese'; + +const customDict = { + '身份': '身分', + '转义': '跳脫', + '转换': '轉檔', + '软件': '軟體', + '硬件': '硬體', + '网络': '網路', + '服务器': '伺服器' +}; + +const { traditionalized, simplized } = stcasc({}, customDict); + +console.log(traditionalized('软件转换')); +// 输出: 軟體轉檔(使用自定义词库) +``` + +#### 禁用术语转换 + +默认情况下,库会转换一些特定术语(如「知识产权」→「智慧財產權」)。如需禁用此功能: + +```javascript +import stcasc from 'switch-chinese'; + +// 第三个参数设置为 true 以禁用术语转换 +const { traditionalized } = stcasc({}, {}, true); + +console.log(traditionalized('知识产权')); +// 输出: 知識産權(仅做字符转换,不转换术语) +``` + +#### 输出格式选项 + +库支持多种输出格式: + +```javascript +import stcasc, { OutputFormat } from 'switch-chinese'; + +const { traditionalized } = stcasc(); + +// 普通格式(默认) +const normal = traditionalized('简体中文'); +// 输出: 簡體中文 + +// 括号格式:同时显示原文和转换后的文本 +const bracket = traditionalized('简体中文', { format: OutputFormat.BRACKET }); +// 输出: 簡(简)體(体)中文 + +// Ruby 注音格式:适用于 HTML 显示 +const ruby = traditionalized('简体中文', { format: OutputFormat.RUBY }); +// 输出: 中文 +``` + +OutputFormat 枚举值: +- `OutputFormat.NORMAL` (0): 只输出转换后的结果(默认) +- `OutputFormat.BRACKET` (1): 输出「转换(原文)」格式 +- `OutputFormat.RUBY` (2): 输出 `` HTML 标签格式 + +### API 文档 + +#### stcasc(cache?, custom?, disableTerms?) + +主函数,用于创建转换器实例。 + +**参数:** + +- `cache` (Object, 可选): 缓存对象,用于避免重复生成字典 +- `custom` (Object, 可选): 自定义简繁转换词库 +- `disableTerms` (Boolean, 可选): 是否禁用术语转换,默认 `false` + +**返回值:** + +返回包含以下方法的对象: + +- `traditionalized(input, options?)`: 将简体中文转换为繁体中文 + - `input`: 可以是字符串、数组或对象 + - 字符串:直接转换返回新字符串 + - 数组:转换所有字符串元素,其他类型保持不变 + - 对象:递归转换所有字符串属性值,其他类型保持不变 +- `simplized(input, options?)`: 将繁体中文转换为简体中文 + - `input`: 可以是字符串、数组或对象 + - 支持的数据类型同 `traditionalized` +- `detect(text)`: 检测文本的中文类型,返回 ChineseType 枚举值 +- `cache`: 字典缓存对象 + +**Options 参数:** + +- `format` (Number, 可选): 输出格式,使用 `OutputFormat` 常量 + +#### ChineseType + +导出的常量对象,用于表示中文类型检测结果: + +```javascript +export const ChineseType = { + SIMPLIFIED: 0, // 简体中文 + TRADITIONAL: 1, // 繁体中文 + UNKNOWN: 2 // 未知类型 +}; +``` + +#### OutputFormat + +导出的常量对象,用于表示输出格式选项: + +```javascript +export const OutputFormat = { + NORMAL: 0, // 只输出转换后的结果 + BRACKET: 1, // 输出「转换(原文)」格式 + RUBY: 2 // 输出 HTML 标签格式 +}; +``` + +### 转换示例 + +#### 智能词组转换 + +该库支持基于上下文的智能词组转换,能够正确处理「一简多繁」的情况: + +```javascript +const { traditionalized } = stcasc(); + +// 智能识别词组边界 +console.log(traditionalized('香烟袅袅')); +// 输出: 香煙裊裊 + +console.log(traditionalized('里长面子')); +// 输出: 里長面子(「里长」是职务名称) + +console.log(traditionalized('吃干面')); +// 输出: 吃乾麵(「干面」是食物) + +console.log(traditionalized('把考卷发回来')); +// 输出: 把考卷發回來(「发」是动词) + +console.log(traditionalized('卷发')); +// 输出: 捲髮(「卷发」是发型) +``` + +#### 术语转换 + +内置常用的大陆简体与台湾正体术语转换: + +```javascript +const { traditionalized } = stcasc(); + +console.log(traditionalized('知识产权')); +// 输出: 智慧財產權 + +console.log(traditionalized('计算机软件')); +// 输出: 計算機軟體 + +console.log(traditionalized('网络服务器')); +// 输出: 網路伺服器 +``` + +### 技术特点 + +#### 高性能 + +- 使用字典树(Trie)优化词组匹配 +- 支持缓存机制,避免重复初始化 +- 纯 JavaScript 实现,执行效率高 + +#### 准确转换 + +- 内置大量简繁对照字符 +- 支持「一简多繁」智能识别 +- 基于词组的上下文分析 + +#### 易于集成 + +- ES Module 标准导出 +- TypeScript 类型支持(通过常量枚举) +- 零依赖,兼容性好 + +### 浏览器支持 + +支持所有现代浏览器及 Node.js 环境: + +- Chrome +- Firefox +- Safari +- Edge +- Node.js 12+ + +### 开源协议 + +MIT License + +### 相关链接 + +- [GitHub 仓库](https://github.com/hoothin/UserScripts/tree/master/Switch%20Traditional%20Chinese%20and%20Simplified%20Chinese/lib) +- [NPM 包地址](https://www.npmjs.com/package/switch-chinese) +- [问题反馈](https://github.com/hoothin/UserScripts/issues) + +### 关键词 + +简繁转换, 繁简转换, 简体中文, 繁体中文, 正体中文, 中文转换, 一简多繁, 简繁切换, 繁简切换, 中文检测, 智能分词, 自定义词库, 零依赖, 轻量级 -演示 --- -+ 基礎用法 -``` js -import Stcasc from './stcasc.lib.js'; -let stcasc = Stcasc(); -console.log(stcasc.traditionalized("香烟 香烟袅袅 烟雾里 里长面子 吃干面 干 把考卷发回来 卷发")); -//香菸 香煙裊裊 煙霧裡 里長面子 吃乾麵 幹 把考卷發回來 捲髮 +## English + +Lightweight Chinese converter library for bidirectional conversion between Simplified and Traditional Chinese with intelligent word segmentation and one-to-many character mapping support. + +[![NPM](https://img.shields.io/npm/v/switch-chinese.svg)](https://www.npmjs.com/package/switch-chinese) [![License](https://img.shields.io/badge/license-MIT-brightgreen.svg)](https://www.npmjs.com/package/switch-chinese) + +### Features + +- **Lightweight**: Zero dependencies, small footprint, excellent performance +- **Intelligent Conversion**: Context-aware word segmentation and accurate one-to-many character mapping +- **Multiple Data Types**: Supports string, array, and object conversion with automatic recursive processing +- **Custom Dictionary**: User-defined conversion rules support +- **Caching Mechanism**: Dictionary caching to avoid repeated initialization +- **Text Detection**: Automatic detection of Simplified Chinese, Traditional Chinese, or unknown text +- **Term Conversion**: Built-in mainland China and Taiwan terminology mapping +- **Zero Dependencies**: Pure JavaScript implementation, no third-party dependencies required + +### Installation + +Install via npm: + +```bash +npm install switch-chinese +``` + +Install via yarn: + +```bash +yarn add switch-chinese +``` + +### Quick Start + +#### Basic Usage + +```javascript +import stcasc from 'switch-chinese'; + +const { traditionalized, simplized, detect } = stcasc(); + +// Simplified to Traditional +const tc = traditionalized('简繁转换 繁简切换 香烟 香烟袅袅'); +console.log(tc); +// Output: 簡繁轉換 繁簡切換 香菸 香煙裊裊 + +// Traditional to Simplified +const sc = simplized('繁體中文'); +console.log(sc); +// Output: 繁体中文 +``` + +#### Text Detection + +```javascript +import stcasc, { ChineseType } from 'switch-chinese'; + +const { detect } = stcasc(); + +const type1 = detect('简体中文'); +if (type1 === ChineseType.SIMPLIFIED) { + console.log('Detected Simplified Chinese'); +} + +const type2 = detect('繁體中文'); +if (type2 === ChineseType.TRADITIONAL) { + console.log('Detected Traditional Chinese'); +} + +const type3 = detect('English'); +if (type3 === ChineseType.UNKNOWN) { + console.log('No Chinese text detected'); +} +``` + +ChineseType enumeration values: +- `ChineseType.SIMPLIFIED` (0): Simplified Chinese +- `ChineseType.TRADITIONAL` (1): Traditional Chinese +- `ChineseType.UNKNOWN` (2): Unknown type + +#### Converting Arrays and Objects + +The library supports converting all strings in arrays and objects, while preserving non-string values: + +```javascript +import stcasc from 'switch-chinese'; + +const { traditionalized, simplized } = stcasc(); + +// Convert array +const arr = ['简体中文', '软件', '网络', 123, true, null]; +const arrTc = traditionalized(arr); +console.log(arrTc); +// Output: ['簡體中文', '軟體', '網路', 123, true, null] + +// Convert object +const obj = { + title: '简体中文标题', + description: '这是一个简体中文描述', + count: 100, + active: true, + tags: ['软件', '网络', '服务器'] +}; +const objTc = traditionalized(obj); +console.log(objTc); +// Output: { +// title: '簡體中文標題', +// description: '這是一個簡體中文描述', +// count: 100, +// active: true, +// tags: ['軟體', '網路', '伺服器'] +// } + +// Convert nested structures +const nested = { + user: { + name: '简体名称', + profile: { + bio: '这是简体中文简介', + skills: ['软件开发', '网络管理'] + } + }, + count: 42 +}; +const nestedTc = traditionalized(nested); +// All string property values will be converted, other types remain unchanged +``` + +### Advanced Usage + +#### Performance Optimization with Caching + +For multiple conversions, use caching mechanism to improve performance: + +```javascript +import stcasc from 'switch-chinese'; + +// First call, generate dictionary +let converter = stcasc(); +const cache = converter.cache; + +// Save cache to persistent storage (e.g., localStorage, file system) +localStorage.setItem('stcasc-cache', JSON.stringify(cache)); + +// Subsequent calls, use cached data +const cachedData = JSON.parse(localStorage.getItem('stcasc-cache')); +converter = stcasc(cachedData); + +// Now you can use it directly without regenerating dictionary +const result = converter.traditionalized('简体中文'); +``` + +#### Custom Conversion Dictionary + +Customize conversion rules according to your needs: + +```javascript +import stcasc from 'switch-chinese'; + +const customDict = { + '身份': '身分', + '转义': '跳脫', + '转换': '轉檔', + '软件': '軟體', + '硬件': '硬體', + '网络': '網路', + '服务器': '伺服器' +}; + +const { traditionalized, simplized } = stcasc({}, customDict); + +console.log(traditionalized('软件转换')); +// Output: 軟體轉檔 (using custom dictionary) +``` + +#### Disable Term Conversion + +By default, the library converts specific terms (e.g., "知识产权" → "智慧財產權"). To disable this feature: + +```javascript +import stcasc from 'switch-chinese'; + +// Set the third parameter to true to disable term conversion +const { traditionalized } = stcasc({}, {}, true); + +console.log(traditionalized('知识产权')); +// Output: 知識産權 (character conversion only, no term conversion) ``` -+ 透過 npm 安裝 +#### Output Formats + +The library supports multiple output formats: + +```javascript +import stcasc, { OutputFormat } from 'switch-chinese'; + +const { traditionalized } = stcasc(); + +// Normal format (default) +const normal = traditionalized('简体中文'); +// Output: 簡體中文 + +// Bracket format: shows both original and converted text +const bracket = traditionalized('简体中文', { format: OutputFormat.BRACKET }); +// Output: 簡(简)體(体)中文 + +// Ruby annotation format: for HTML display +const ruby = traditionalized('简体中文', { format: OutputFormat.RUBY }); +// Output: 中文 +``` + +OutputFormat enumeration values: +- `OutputFormat.NORMAL` (0): Output converted result only (default) +- `OutputFormat.BRACKET` (1): Output in "converted(original)" format +- `OutputFormat.RUBY` (2): Output in `` HTML tag format + +### API Reference + +#### stcasc(cache?, custom?, disableTerms?) + +Main function to create a converter instance. + +**Parameters:** + +- `cache` (Object, optional): Cache object to avoid regenerating dictionary +- `custom` (Object, optional): Custom Simplified-Traditional conversion dictionary +- `disableTerms` (Boolean, optional): Whether to disable term conversion, default `false` + +**Returns:** + +An object containing the following methods: + +- `traditionalized(input, options?)`: Convert Simplified Chinese to Traditional Chinese + - `input`: Can be a string, array, or object + - String: Directly converts and returns a new string + - Array: Converts all string elements, other types remain unchanged + - Object: Recursively converts all string property values, other types remain unchanged +- `simplized(input, options?)`: Convert Traditional Chinese to Simplified Chinese + - `input`: Can be a string, array, or object + - Supports the same data types as `traditionalized` +- `detect(text)`: Detect Chinese text type, returns ChineseType enumeration value +- `cache`: Dictionary cache object + +**Options parameter:** + +- `format` (Number, optional): Output format, use `OutputFormat` constants + +#### ChineseType + +Exported constant object representing text detection results: + +```javascript +export const ChineseType = { + SIMPLIFIED: 0, // Simplified Chinese + TRADITIONAL: 1, // Traditional Chinese + UNKNOWN: 2 // Unknown type +}; +``` + +#### OutputFormat + +Exported constant object representing output format options: + +```javascript +export const OutputFormat = { + NORMAL: 0, // Output converted result only + BRACKET: 1, // Output "converted(original)" format + RUBY: 2 // Output HTML tag format +}; +``` + +### Conversion Examples + +#### Intelligent Word Segmentation + +The library supports context-aware intelligent word segmentation, accurately handling one-to-many character mappings: + +```javascript +const { traditionalized } = stcasc(); + +// Intelligent phrase boundary recognition +console.log(traditionalized('香烟袅袅')); +// Output: 香煙裊裊 + +console.log(traditionalized('里长面子')); +// Output: 里長面子 ("里长" is a position title) + +console.log(traditionalized('吃干面')); +// Output: 吃乾麵 ("干面" is a food) + +console.log(traditionalized('把考卷发回来')); +// Output: 把考卷發回來 ("发" is a verb in this context) + +console.log(traditionalized('卷发')); +// Output: 捲髮 ("卷发" is a hairstyle) +``` -``` +#### Term Conversion + +Built-in conversion for common mainland China and Taiwan terminology: + +```javascript +const { traditionalized } = stcasc(); + +console.log(traditionalized('知识产权')); +// Output: 智慧財產權 + +console.log(traditionalized('计算机软件')); +// Output: 計算機軟體 + +console.log(traditionalized('网络服务器')); +// Output: 網路伺服器 +``` + +### Technical Highlights + +#### High Performance + +- Dictionary tree (Trie) optimization for phrase matching +- Caching mechanism support to avoid repeated initialization +- Pure JavaScript implementation for high execution efficiency + +#### Accurate Conversion + +- Extensive built-in Simplified-Traditional character mappings +- Intelligent recognition for one-to-many character conversions +- Context-based phrase analysis + +#### Easy Integration + +- ES Module standard export +- TypeScript support through constant enumerations +- Zero dependencies, excellent compatibility + +### Browser Support + +Supports all modern browsers and Node.js environments: + +- Chrome +- Firefox +- Safari +- Edge +- Node.js 12+ + +### License + +MIT License + +### Links + +- [GitHub Repository](https://github.com/hoothin/UserScripts/tree/master/Switch%20Traditional%20Chinese%20and%20Simplified%20Chinese/lib) +- [NPM Package](https://www.npmjs.com/package/switch-chinese) +- [Issue Tracker](https://github.com/hoothin/UserScripts/issues) + +### Keywords + +Chinese Converter, Simplified Chinese, Traditional Chinese, Chinese Translation, Character Detection, Text Converter, Language Converter, i18n, Localization, Ruby Annotation, One-to-Many Mapping, Intelligent Word Segmentation, Custom Dictionary, Zero Dependencies, Lightweight + +--- + +## 繁體中文 + +簡繁體中文智能轉換庫 - 支援簡體中文與正體中文雙向轉換,基於詞組的智能分詞處理「一簡多繁」問題 + +[![NPM](https://img.shields.io/npm/v/switch-chinese.svg)](https://www.npmjs.com/package/switch-chinese) [![License](https://img.shields.io/badge/license-MIT-brightgreen.svg)](https://www.npmjs.com/package/switch-chinese) + +### 特色 + +- **輕量級**:零依賴,體積小,效能優異 +- **智能轉換**:支援基於詞組的智能分詞和「一簡多繁」精準轉換 +- **多種資料類型**:支援字串、陣列、物件的轉換,自動遞迴處理巢狀結構 +- **自訂詞庫**:允許使用者自訂簡繁轉換詞彙 +- **快取機制**:支援字典快取,避免重複初始化 +- **簡繁檢測**:自動檢測文字是簡體中文、繁體中文還是未知類型 +- **術語轉換**:內建大陸簡體與台灣正體的常用術語轉換 +- **無依賴**:純 JavaScript 實現,無需任何第三方依賴 + +### 安裝 + +使用 npm 安裝: + +```bash npm install switch-chinese -import Stcasc from 'switch-chinese'; ``` -+ 轉正體中文 +使用 yarn 安裝: + +```bash +yarn add switch-chinese +``` + +### 快速開始 + +#### 基礎用法 + +```javascript +import stcasc from 'switch-chinese'; + +const { traditionalized, simplized, detect } = stcasc(); + +// 簡體轉繁體 +const tc = traditionalized('简繁转换 繁简切换 香烟 香烟袅袅'); +console.log(tc); +// 輸出: 簡繁轉換 繁簡切換 香菸 香煙裊裊 + +// 繁體轉簡體 +const sc = simplized('繁體中文'); +console.log(sc); +// 輸出: 繁体中文 +``` + +#### 檢測中文類型 + +```javascript +import stcasc, { ChineseType } from 'switch-chinese'; + +const { detect } = stcasc(); + +const type1 = detect('简体中文'); +if (type1 === ChineseType.SIMPLIFIED) { + console.log('檢測到簡體中文'); +} + +const type2 = detect('繁體中文'); +if (type2 === ChineseType.TRADITIONAL) { + console.log('檢測到繁體中文'); +} + +const type3 = detect('English'); +if (type3 === ChineseType.UNKNOWN) { + console.log('未檢測到中文'); +} +``` + +ChineseType 列舉值: +- `ChineseType.SIMPLIFIED` (0): 簡體中文 +- `ChineseType.TRADITIONAL` (1): 繁體中文 +- `ChineseType.UNKNOWN` (2): 未知類型 -``` js -stcasc.traditionalized("中文"); +#### 轉換陣列和物件 + +函式庫支援轉換陣列和物件中的所有字串,非字串值保持原樣: + +```javascript +import stcasc from 'switch-chinese'; + +const { traditionalized, simplized } = stcasc(); + +// 轉換陣列 +const arr = ['简体中文', '软件', '网络', 123, true, null]; +const arrTc = traditionalized(arr); +console.log(arrTc); +// 輸出: ['簡體中文', '軟體', '網路', 123, true, null] + +// 轉換物件 +const obj = { + title: '简体中文标题', + description: '这是一个简体中文描述', + count: 100, + active: true, + tags: ['软件', '网络', '服务器'] +}; +const objTc = traditionalized(obj); +console.log(objTc); +// 輸出: { +// title: '簡體中文標題', +// description: '這是一個簡體中文描述', +// count: 100, +// active: true, +// tags: ['軟體', '網路', '伺服器'] +// } + +// 轉換巢狀結構 +const nested = { + user: { + name: '简体名称', + profile: { + bio: '这是简体中文简介', + skills: ['软件开发', '网络管理'] + } + }, + count: 42 +}; +const nestedTc = traditionalized(nested); +// 所有字串屬性值都會被轉換,數字等其他類型保持不變 ``` -+ 轉簡體中文 +### 進階用法 + +#### 使用快取最佳化效能 + +在多次呼叫時,建議使用快取機制避免重複生成字典,提升效能: + +```javascript +import stcasc from 'switch-chinese'; + +// 第一次呼叫,生成字典 +let converter = stcasc(); +const cache = converter.cache; -``` js -stcasc.simplized("中文"); +// 將快取儲存至持久化儲存(如 localStorage、檔案等) +localStorage.setItem('stcasc-cache', JSON.stringify(cache)); + +// 後續呼叫,直接使用快取 +const cachedData = JSON.parse(localStorage.getItem('stcasc-cache')); +converter = stcasc(cachedData); + +// 現在可以直接使用,無需重新生成字典 +const result = converter.traditionalized('简体中文'); ``` -+ 添加快取 +#### 自訂簡繁轉換詞庫 + +可以根據業務需求自訂簡繁轉換規則: -``` js -let cache = loadCacheAtYourWay(); -let stcasc = Stcasc(cache); -saveCacheAtYourWay(stcasc.cache); +```javascript +import stcasc from 'switch-chinese'; + +const customDict = { + '身份': '身分', + '转义': '跳脫', + '转换': '轉檔', + '软件': '軟體', + '硬件': '硬體', + '网络': '網路', + '服务器': '伺服器' +}; + +const { traditionalized, simplized } = stcasc({}, customDict); + +console.log(traditionalized('软件转换')); +// 輸出: 軟體轉檔(使用自訂詞庫) +``` + +#### 停用術語轉換 + +預設情況下,函式庫會轉換一些特定術語(如「知识产权」→「智慧財產權」)。如需停用此功能: + +```javascript +import stcasc from 'switch-chinese'; + +// 第三個參數設定為 true 以停用術語轉換 +const { traditionalized } = stcasc({}, {}, true); + +console.log(traditionalized('知识产权')); +// 輸出: 知識産權(僅做字元轉換,不轉換術語) +``` + +#### 輸出格式選項 + +函式庫支援多種輸出格式: + +```javascript +import stcasc, { OutputFormat } from 'switch-chinese'; + +const { traditionalized } = stcasc(); + +// 普通格式(預設) +const normal = traditionalized('简体中文'); +// 輸出: 簡體中文 + +// 括號格式:同時顯示原文和轉換後的文字 +const bracket = traditionalized('简体中文', { format: OutputFormat.BRACKET }); +// 輸出: 簡(简)體(体)中文 + +// Ruby 注音格式:適用於 HTML 顯示 +const ruby = traditionalized('简体中文', { format: OutputFormat.RUBY }); +// 輸出: 中文 ``` -+ 自訂簡繁切換 +OutputFormat 列舉值: +- `OutputFormat.NORMAL` (0): 只輸出轉換後的結果(預設) +- `OutputFormat.BRACKET` (1): 輸出「轉換(原文)」格式 +- `OutputFormat.RUBY` (2): 輸出 `` HTML 標籤格式 + +### API 文件 + +#### stcasc(cache?, custom?, disableTerms?) + +主函式,用於建立轉換器實例。 + +**參數:** + +- `cache` (Object, 可選): 快取物件,用於避免重複生成字典 +- `custom` (Object, 可選): 自訂簡繁轉換詞庫 +- `disableTerms` (Boolean, 可選): 是否停用術語轉換,預設 `false` + +**回傳值:** -``` js -const custom = { - "身份": "身分", - "转义": "跳脫", - "转换": "轉檔", - "软件": "軟體" +回傳包含以下方法的物件: + +- `traditionalized(input, options?)`: 將簡體中文轉換為繁體中文 + - `input`: 可以是字串、陣列或物件 + - 字串:直接轉換並回傳新字串 + - 陣列:轉換所有字串元素,其他類型保持不變 + - 物件:遞迴轉換所有字串屬性值,其他類型保持不變 +- `simplized(input, options?)`: 將繁體中文轉換為簡體中文 + - `input`: 可以是字串、陣列或物件 + - 支援的資料類型同 `traditionalized` +- `detect(text)`: 檢測文字的中文類型,回傳 ChineseType 列舉值 +- `cache`: 字典快取物件 + +**Options 參數:** + +- `format` (Number, 可選): 輸出格式,使用 `OutputFormat` 常數 + +#### ChineseType + +匯出的常數物件,用於表示中文類型檢測結果: + +```javascript +export const ChineseType = { + SIMPLIFIED: 0, // 簡體中文 + TRADITIONAL: 1, // 繁體中文 + UNKNOWN: 2 // 未知類型 +}; +``` + +#### OutputFormat + +匯出的常數物件,用於表示輸出格式選項: + +```javascript +export const OutputFormat = { + NORMAL: 0, // 只輸出轉換後的結果 + BRACKET: 1, // 輸出「轉換(原文)」格式 + RUBY: 2 // 輸出 HTML 標籤格式 }; -let stcasc = Stcasc(cache, custom); ``` + +### 轉換範例 + +#### 智能詞組轉換 + +本函式庫支援基於上下文的智能詞組轉換,能夠正確處理「一簡多繁」的情況: + +```javascript +const { traditionalized } = stcasc(); + +// 智能識別詞組邊界 +console.log(traditionalized('香烟袅袅')); +// 輸出: 香煙裊裊 + +console.log(traditionalized('里长面子')); +// 輸出: 里長面子(「里長」是職務名稱) + +console.log(traditionalized('吃干面')); +// 輸出: 吃乾麵(「乾麵」是食物) + +console.log(traditionalized('把考卷发回来')); +// 輸出: 把考卷發回來(「發」是動詞) + +console.log(traditionalized('卷发')); +// 輸出: 捲髮(「捲髮」是髮型) +``` + +#### 術語轉換 + +內建常用的大陸簡體與台灣正體術語轉換: + +```javascript +const { traditionalized } = stcasc(); + +console.log(traditionalized('知识产权')); +// 輸出: 智慧財產權 + +console.log(traditionalized('计算机软件')); +// 輸出: 計算機軟體 + +console.log(traditionalized('网络服务器')); +// 輸出: 網路伺服器 +``` + +### 技術特點 + +#### 高效能 + +- 使用字典樹(Trie)最佳化詞組比對 +- 支援快取機制,避免重複初始化 +- 純 JavaScript 實現,執行效率高 + +#### 精準轉換 + +- 內建大量簡繁對照字元 +- 支援「一簡多繁」智能識別 +- 基於詞組的上下文分析 + +#### 易於整合 + +- ES Module 標準匯出 +- TypeScript 類型支援(透過常數列舉) +- 零依賴,相容性佳 + +### 瀏覽器支援 + +支援所有現代瀏覽器及 Node.js 環境: + +- Chrome +- Firefox +- Safari +- Edge +- Node.js 12+ + +### 開源授權 + +MIT License + +### 相關連結 + +- [GitHub 儲存庫](https://github.com/hoothin/UserScripts/tree/master/Switch%20Traditional%20Chinese%20and%20Simplified%20Chinese/lib) +- [NPM 套件位址](https://www.npmjs.com/package/switch-chinese) +- [問題回報](https://github.com/hoothin/UserScripts/issues) + +### 關鍵字 + +簡繁轉換, 繁簡轉換, 簡體中文, 繁體中文, 正體中文, 中文轉換, 一簡多繁, 簡繁切換, 繁簡切換, 中文檢測, 智能分詞, 自訂詞庫, 零依賴, 輕量級 diff --git a/Switch Traditional Chinese and Simplified Chinese/lib/stcasc.d.ts b/Switch Traditional Chinese and Simplified Chinese/lib/stcasc.d.ts new file mode 100644 index 00000000000..350324519b8 --- /dev/null +++ b/Switch Traditional Chinese and Simplified Chinese/lib/stcasc.d.ts @@ -0,0 +1,167 @@ +/** + * Chinese character type enumeration + */ +export declare const ChineseType: { + /** Simplified Chinese */ + readonly SIMPLIFIED: 0; + /** Traditional Chinese */ + readonly TRADITIONAL: 1; + /** Unknown type */ + readonly UNKNOWN: 2; +}; + +/** + * Output format enumeration + */ +export declare const OutputFormat: { + /** Normal output - only the converted result */ + readonly NORMAL: 0; + /** Bracket format - outputs「Simplified(Traditional)」or「Traditional(Simplified)」*/ + readonly BRACKET: 1; + /** Ruby annotation format - outputs SimplifiedTraditional */ + readonly RUBY: 2; +}; + +/** + * Conversion options + */ +export interface ConversionOptions { + /** + * Output format + * @default OutputFormat.NORMAL + */ + format?: 0 | 1 | 2; +} + +/** + * Tree node for combination dictionary + */ +interface CombTreeNode { + end?: string; + [key: string]: CombTreeNode | string | undefined; +} + +/** + * Cache object for storing conversion dictionaries + */ +export interface ConversionCache { + sc2tcCombTree?: Record; + tc2scCombTree?: Record; + stDict?: Record; + tsDict?: Record; +} + +/** + * Custom dictionary mapping + * Key: source text (simplified or traditional) + * Value: target text (can be string or array of strings for multiple mappings) + */ +export type CustomDictionary = Record; + +/** + * Result object returned by stcasc function + */ +export interface StcascConverter { + /** + * Convert traditional Chinese to simplified Chinese + * @param text - String to convert + * @param options - Conversion options + * @returns Converted simplified Chinese string + */ + simplized(text: string, options?: ConversionOptions): string; + + /** + * Convert traditional Chinese to simplified Chinese (array version) + * @param data - Array to convert (converts all strings in the array) + * @param options - Conversion options + * @returns Array with converted strings + */ + simplized(data: T, options?: ConversionOptions): T; + + /** + * Convert traditional Chinese to simplified Chinese (object version) + * @param data - Object to convert (converts all string property values) + * @param options - Conversion options + * @returns Object with converted string values + */ + simplized>(data: T, options?: ConversionOptions): T; + + /** + * Convert simplified Chinese to traditional Chinese + * @param text - String to convert + * @param options - Conversion options + * @returns Converted traditional Chinese string + */ + traditionalized(text: string, options?: ConversionOptions): string; + + /** + * Convert simplified Chinese to traditional Chinese (array version) + * @param data - Array to convert (converts all strings in the array) + * @param options - Conversion options + * @returns Array with converted strings + */ + traditionalized(data: T, options?: ConversionOptions): T; + + /** + * Convert simplified Chinese to traditional Chinese (object version) + * @param data - Object to convert (converts all string property values) + * @param options - Conversion options + * @returns Object with converted string values + */ + traditionalized>(data: T, options?: ConversionOptions): T; + + /** + * Detect Chinese text type + * @param text - Text to detect + * @returns ChineseType value (0=SIMPLIFIED, 1=TRADITIONAL, 2=UNKNOWN) + */ + detect(text: string): 0 | 1 | 2; + + /** + * Cached conversion dictionaries + */ + cache: ConversionCache; +} + +/** + * Initialize Chinese converter with optional cache and custom dictionary + * + * @param cache - Optional cache object to reuse conversion dictionaries + * @param custom - Optional custom dictionary for special term conversions + * @param disableTerms - If true, disables built-in term conversions + * @returns Converter object with conversion methods + * + * @example + * ```typescript + * import stcasc from 'switch-chinese'; + * + * const converter = stcasc(); + * const traditional = converter.traditionalized('简体中文'); + * const simplified = converter.simplized('繁體中文'); + * const type = converter.detect('繁體中文'); + * ``` + * + * @example + * ```typescript + * // With custom dictionary + * const converter = stcasc({}, { + * '自定义词': '自訂詞', + * '程序': ['程式', '程序'] + * }); + * ``` + * + * @example + * ```typescript + * // With output format + * const converter = stcasc(); + * const result = converter.traditionalized('简体', { format: 1 }); + * // Output: 簡體(简体) + * ``` + */ +declare function stcasc( + cache?: ConversionCache, + custom?: CustomDictionary, + disableTerms?: boolean +): StcascConverter; + +export default stcasc; diff --git a/Switch Traditional Chinese and Simplified Chinese/lib/stcasc.lib.js b/Switch Traditional Chinese and Simplified Chinese/lib/stcasc.lib.js index f1fdb131004..2256dc7222a 100644 --- a/Switch Traditional Chinese and Simplified Chinese/lib/stcasc.lib.js +++ b/Switch Traditional Chinese and Simplified Chinese/lib/stcasc.lib.js @@ -1,4 +1,16 @@ 'use strict'; +export const ChineseType = { + SIMPLIFIED: 0, + TRADITIONAL: 1, + UNKNOWN: 2 +}; + +export const OutputFormat = { + NORMAL: 0, // 只输出转换后的结果 + BRACKET: 1, // 输出「简(繁)」或「繁(简)」格式 + RUBY: 2 // 输出 格式 +}; + const scStr = '万与丑专业丛东丝丢两严丧个丰临为为丽举么么义乌乐乔习乡书买乱争于亏云亘亚产产亩亲亵亸亿仅仆从仑仓仪们价众众优伙会伛伞伟传伡伣伤伥伦伧伪伫体余佣佥侠侣侥侦侧侨侩侪侬侭俣俦俨俩俪俫俭借债倾偬偻偾偿傤傥傧储傩儿克兑兖党兰关兴兹养兽冁内冈册冗写军农冢冯冲冲决况冻净凄准凉凌减凑凛几凤处凫凭凯凶击凿刍划刘则刚创删别刬刭制刹刽刾刿剀剂剐剑剥剧劝办务劢动励劲劳势勋勖勚匀匦匮区医华协单卖卜卢卤卧卫却卷厂厅历历厉压厌厍厐厕厘厠厢厣厦厨厩厮县叁参叆叇双发发变叙叠只台叶号叹叽吁后吓吕吗吨听启吴呆呐呒呓呕呖呗员呙呛呜周咏咙咛咝咤咨咸响哑哒哓哔哕哗哙哜哝哟唇唉唛唝唠唡唢唤啧啬啭啮啯啰啴啸喂喷喽喾嗫嗳嘘嘤嘱噜嚣团园囱围囵国图圆圣圹场坏块坚坛坛坛坛坜坝坞坟坠垄垅垆垒垦垩垫垭垯垱垲垴埘埙埚堑堕塆墙墻壊壮声壳壶壸処备复复够头夸夹夺奁奂奋奖奥奬妆妇妈妩妪妫姗姜姹娄娅娆娇娈娱娲娴婳婴婵婶媪媭嫒嫔嫱嬀嬷孙学孪宁宁宝实宠审宪宫宽宽宾寝对寻导寿将尔尘尝尧尴尸尽尽层屃屉届属屡屦屿岁岂岖岗岘岚岛岩岭岳岽岿峃峄峡峣峤峥峦峰崂崃崄崭嵘嵚嵝巅巨巩巯币布帅师帏帐帘帜带帧帮帱帻帼幂干干并并广庄庆庐庑库应庙庞废庼廏廪开异弃弑张弥弪弯弹强归当录彝彟彦彨彻征径徕御忆忏志忧念忾怀态怂怃怄怅怆怜总怼怿恋恒恳恶恶恸恹恺恻恼恽悦悫悬悭悮悯惊惧惨惩惫惬惭惮惯愠愤愦愿慑慭懑懒懔戆戋戏戗战戬户扎扑托扦执扩扪扫扬扰抚抛抟抠抡抢护报抬抻担拟拢拣拥拦拧拨择挂挚挛挜挝挞挟挠挡挢挣挤挥挦捂捝捞损捡换捣据捻掳掴掷掸掺掼揽揾揿搀搁搂搄搅携摄摅摆摇摈摊撄撑撵撷撸撺擜擞攒敌敍敚敛敩数斋斓斗斩断无旧时旷旸昙昼昽显晋晒晓晔晕晖暂暧札术朴机杀杂权杠条来杨杩杰松板极构枞枢枣枥枧枨枪枫枭柜柠柽栀栅标栈栉栊栋栌栎栏树栖样栾桠桡桢档桤桥桦桧桨桩桪梁梦梼梾梿检棁棂棱椁椝椟椠椢椤椫椭椮楼榄榅榇榈榉榝槚槛槟槠横樯樱橥橱橹橼檐檩欢欤欧歼殁殇残殒殓殚殡殴殻毁毂毕毙毡毵氇气氢氩氲汇汇汉污汤汹沟没沣沤沥沦沧沨沩沪泄泞注泪泶泷泸泺泻泼泽泾洁洒洼浃浅浆浇浈浉浊测浍济浏浐浑浒浓浔浕涂涌涚涛涝涞涟涠涡涢涣涤润涧涨涩淀渊渌渍渎渐渑渔渖渗温游湾湿溁溃溅溆溇滗滚滞滟滠满滢滤滥滦滨滩滪潆潇潋潍潙潜潨潴澛澜濑濒灏灭灯灵灶灾灿炀炉炖炜炝点炼炽烁烂烃烛烟烟烦烧烨烩烫烬热焕焖焘煴爱爷牍牦牵牺犊状犷犸犹狈狝狞独狭狮狯狰狱狲猃猎猕猡猪猫猬献獭玑玙玚玛玮环现玱玺珐珑珰珲琎琏琐琼瑶瑷瑸璎瓒瓮瓯産电画畅畴疖疗疟疠疡疬疭疮疯疱疴痈痉痒痖痨痪痫痴痹瘅瘆瘉瘗瘘瘪瘫瘾瘿癞癣癫皋皑皱皲盏盐监盖盗盘眍眦眬着睁睐睑睾瞆瞒瞩矫矶矾矿砀码砖砗砚砜砺砻砾础硁硅硕硖硗硙硚确硵硷碍碛碜碱礼祃祎祢祯祷祸禀禄禅离秃秆种秘积称秸秽秾稆税稣稳穑穞穷窃窍窎窑窜窝窥窦窭竖竞竪笃笋笔笕笺笼笾筑筚筛筜筝筹筼签签筿简箓箦箧箨箩箪箫篑篓篮篯篱簖籁籴类籼粜粝粤粪粮糁糇糍系系紧绝絷纟纠纡红纣纤纥约级纨纩纪纫纬纭纮纯纰纱纲纳纴纵纶纷纸纹纺纻纼纽纾线绀绁绂练组绅细织终绉绊绋绌绍绎经绐绑绒结绔绕绖绗绘给绚绛络絶绞统绠绡绢绣绤绥绦继绨绩绪绫绬续绮绯绰绱绲绳维绵绶绷绸绹绺绻综绽绾绿缀缁缂缃缄缅缆缇缈缉缊缋缌缍缎缏缑缒缓缔缕编缗缘缙缚缛缜缝缞缟缠缡缢缣缤缥缦缧缨缩缪缫缬缭缮缯缰缱缲缳缴缵罂网罗罚罢罴羁羟羡群翘翙翚翱耢耧耸耻聂聋职聍联聩聪肃肠肤肮肴肾肿胀胁胆胜胧胨胪胫胶脉脍脏脐脑脓脔脚脱脶脸腊腌腘腭腻腼腽腾膑膻臜致舆舍舣舰舱舻艰艳艺节芈芗芜芦苁苇苈苋苌苍苎苏苧苹范茎茏茑茔茕茧荆荐荙荚荛荜荝荞荟荠荡荣荤荥荦荧荨荩荪荫荬荭荮药莅莱莲莳莴莶获莸莹莺莼萚萝萤营萦萧萨葱蒀蒇蒉蒋蒌蒏蓝蓟蓠蓣蓥蓦蔂蔷蔹蔺蔼蕰蕲蕴薮藓蘖虏虑虚虫虬虮虱虽虾虿蚀蚁蚂蚃蚕蚝蚬蛊蛎蛏蛮蛰蛱蛲蛳蛴蜕蜗蜡蝇蝈蝉蝎蝼蝾螀螨蟏衅衆衔补表衬衮袄袅袆袜袭袯装裆裈裢裣裤裥褛褴襕见观觃规觅视觇览觉觊觋觌觍觎觏觐觑觞触觯訚詟誉誊说说谣讠计订讣认讥讦讧讨让讪讫讬训议讯记讱讲讳讴讵讶讷许讹论讻讼讽设访诀证诂诃评诅识诇诈诉诊诋诌词诎诏诐译诒诓诔试诖诗诘诙诚诛诜话诞诟诠诡询诣诤该详诧诨诩诪诫诬语诮误诰诱诲诳诵诶请诸诹诺读诼诽课诿谀谁谂调谄谅谆谇谈谉谊谋谌谍谎谏谐谑谒谓谔谕谖谗谘谙谚谛谜谝谞谟谠谡谢谣谤谥谦谧谨谩谪谫谬谭谮谯谰谱谲谳谴谵谶谷豮贜贝贞负贠贡财责贤败账货质贩贪贫贬购贮贯贰贱贲贳贴贵贶贷贸费贺贻贼贽贾贿赀赁赂赃资赅赆赇赈赉赊赋赌赍赎赏赐赑赒赓赔赕赖赗赘赙赚赛赜赝赞赞赟赠赡赢赣赪赵赶趋趱趸跃跄跖跞跡践跶跷跸跹跻踊踌踪踬踯蹑蹒蹰蹿躏躜躯軆輼车轧轨轩轪轫转轭轮软轰轱轲轳轴轵轶轷轸轹轺轻轼载轾轿辀辁辂较辄辅辆辇辈辉辊辋辌辍辎辏辐辑辒输辔辕辖辗辘辙辚辞辟辩辫边辽达迁过迈运还这进远违连迟迩迳迹适选逊递逦逻遗遥邓邝邬邮邹邺邻郁郏郐郑郓郦郧郸酂酝酦酱酽酾酿采释里里鈎鉴鉴銮鋭録錾钅钆钇针钉钊钋钌钍钎钏钐钑钒钓钔钕钖钗钘钙钚钛钜钝钞钟钟钠钡钢钣钤钥钦钧钨钩钪钫钬钭钮钯钰钱钲钳钴钵钶钷钸钹钺钻钼钽钾钿铀铁铂铃铄铅铆铇铈铉铊铋铌铍铎铏铐铑铒铓铔铕铖铗铘铙铚铛铜铝铞铟铠铡铢铣铤铥铦铧铨铩铪铫铬铭铮铯铰铱铲铳铴铵银铷铸铹铺铻铼铽链链铿销锁锂锃锄锅锆锇锈锈锉锊锋锌锍锎锏锐锑锒锓锔锕锖锗锘错锚锛锜锝锞锟锠锡锢锣锤锥锦锧锨锩锪锫锬锭键锯锰锱锲锳锴锵锶锷锸锹锺锻锼锽锾锿镀镁镂镃镄镅镆镇镈镉镊镋镌镍镎镏镐镑镒镓镔镕镖镗镘镙镚镛镜镝镞镟镠镡镢镣镤镥镦镧镨镩镪镫镬镭镮镯镰镱镲镳镴镵镶长门闩闪闫闬闭问闯闰闱闲闲闳间闵闶闷闸闹闺闻闼闽闾闿阀阁阂阃阄阅阆阇阈阉阊阋阌阍阎阏阐阑阒阓阔阕阖阗阘阙阚阛队阳阴阵阶际陆陇陈陉陕陦陧陨险随隐隶隽难雇雏雠雳雾霁霉霡霭靓靔静面靥鞑鞒鞯鞲韦韧韨韩韪韫韬韵頽页顶顷顸项顺须顼顽顾顿颀颁颂颃预颅领颇颈颉颊颋颌颍颎颏颐频颒颓颔颕颖颗题颙颚颛颜颜额颞颟颠颡颢颣颤颥颦颧风飏飐飑飒飓飔飕飖飗飘飙飚飞飨餍饣饤饥饦饧饨饩饪饫饬饭饮饯饰饱饲饳饴饵饶饷饸饹饺饻饼饽饾饿馀馁馂馃馄馅馆馇馈馉馊馋馌馍馎馏馐馑馒馓馔馕駡马驭驮驯驰驱驲驳驴驵驶驷驸驹驺驻驼驽驾驿骀骁骂骃骄骅骆骇骈骉骊骋验骍骎骏骐骑骒骓骔骕骖骗骘骙骚骛骜骝骞骟骠骡骢骣骤骥骦骧髅髋髌鬓鬶魇魉鱼鱽鱾鱿鲀鲁鲂鲃鲄鲅鲆鲇鲈鲉鲊鲋鲌鲍鲎鲏鲐鲑鲒鲓鲔鲕鲖鲗鲘鲙鲚鲛鲜鲝鲞鲟鲠鲡鲢鲣鲤鲥鲦鲧鲨鲩鲪鲫鲬鲭鲮鲯鲰鲱鲲鲳鲴鲵鲶鲷鲸鲹鲺鲻鲼鲽鲾鲿鳀鳁鳂鳃鳄鳅鳆鳇鳈鳉鳊鳋鳌鳍鳎鳏鳐鳑鳒鳓鳔鳕鳖鳗鳘鳙鳛鳜鳝鳞鳟鳠鳡鳢鳣鳤鷀鷄鸟鸠鸡鸢鸣鸤鸥鸦鸧鸨鸩鸪鸫鸬鸭鸮鸯鸰鸱鸲鸳鸴鸵鸶鸷鸸鸹鸺鸻鸼鸽鸾鸿鹀鹁鹂鹃鹄鹅鹆鹇鹈鹉鹊鹋鹌鹍鹎鹏鹐鹑鹒鹓鹔鹕鹖鹗鹘鹙鹚鹛鹜鹝鹞鹟鹠鹡鹢鹣鹤鹥鹦鹧鹨鹩鹪鹫鹬鹭鹮鹯鹰鹱鹲鹳鹴鹾麦麸麹麽黄黉黡黩黪黾鼋鼌鼍鼹齐齑齿龀龁龂龃龄龅龆龇龈龉龊龋龌龙龚龛龟酸'; const tcStr = '萬與醜專業叢東絲丟兩嚴喪個豐臨為爲麗舉麽麼義烏樂喬習鄉書買亂爭於虧雲亙亞産產畝親褻嚲億僅僕從侖倉儀們價衆眾優夥會傴傘偉傳俥俔傷倀倫傖僞佇體餘傭僉俠侶僥偵側僑儈儕儂儘俁儔儼倆儷倈儉藉債傾傯僂僨償儎儻儐儲儺兒剋兌兗黨蘭關興茲養獸囅內岡冊宂寫軍農塚馮沖衝決況凍淨淒準涼淩減湊凜幾鳳處鳧憑凱兇擊鑿芻劃劉則剛創刪別剗剄製剎劊㓨劌剴劑剮劍剝劇勸辦務勱動勵勁勞勢勳勗勩勻匭匱區醫華協單賣蔔盧鹵臥衛卻捲廠廳曆歷厲壓厭厙龎廁釐廁廂厴廈廚廄廝縣叄參靉靆雙發髮變敘疊隻臺葉號嘆嘰籲後嚇呂嗎噸聽啟吳獃吶嘸囈嘔嚦唄員咼嗆嗚週詠嚨嚀噝吒諮鹹響啞噠嘵嗶噦嘩噲嚌噥喲脣欸嘜嗊嘮啢嗩喚嘖嗇囀齧嘓囉嘽嘯餵噴嘍嚳囁噯噓嚶囑嚕囂團園囪圍圇國圖圓聖壙場壞塊堅壇罎罈壜壢壩塢墳墜壟壠壚壘墾堊墊埡墶壋塏堖塒壎堝塹墮壪牆牆壞壯聲殼壺壼處備複復夠頭誇夾奪奩奐奮獎奧獎妝婦媽嫵嫗媯姍薑奼婁婭嬈嬌孌娛媧嫻嫿嬰嬋嬸媼嬃嬡嬪嬙媯嬤孫學孿寧甯寶實寵審憲宮寬寛賓寢對尋導壽將爾塵嘗堯尷屍盡儘層屭屜屆屬屢屨嶼歲豈嶇崗峴嵐島巖嶺嶽崬巋嶨嶧峽嶢嶠崢巒峯嶗崍嶮嶄嶸嶔嶁巔鉅鞏巰幣佈帥師幃帳簾幟帶幀幫幬幘幗冪幹乾並併廣莊慶廬廡庫應廟龐廢廎廄廩開異棄弒張彌弳彎彈強歸當錄彜彠彥彲徹徵徑徠禦憶懺誌憂唸愾懷態慫憮慪悵愴憐總懟懌戀恆懇惡噁慟懨愷惻惱惲悅愨懸慳悞憫驚懼慘懲憊愜慚憚慣慍憤憒願懾憖懣懶懍戇戔戲戧戰戩戶紮撲託扡執擴捫掃揚擾撫拋摶摳掄搶護報擡捵擔擬攏揀擁攔擰撥擇掛摯攣掗撾撻挾撓擋撟掙擠揮撏摀挩撈損撿換搗據撚擄摑擲撣摻摜攬搵撳攙擱摟揯攪攜攝攄擺搖擯攤攖撐攆擷擼攛㩵擻攢敵敘敓斂斆數齋斕鬥斬斷無舊時曠暘曇晝曨顯晉曬曉曄暈暉暫曖劄術樸機殺雜權槓條來楊榪傑鬆闆極構樅樞棗櫪梘棖槍楓梟櫃檸檉梔柵標棧櫛櫳棟櫨櫟欄樹棲樣欒椏橈楨檔榿橋樺檜槳樁樳樑夢檮棶槤檢梲櫺稜槨槼櫝槧槶欏樿橢槮樓欖榲櫬櫚櫸樧檟檻檳櫧橫檣櫻櫫櫥櫓櫞簷檁歡歟歐殲歿殤殘殞殮殫殯毆殼毀轂畢斃氈毿氌氣氫氬氳彙匯漢汙湯洶溝沒灃漚瀝淪滄渢溈滬洩濘註淚澩瀧瀘濼瀉潑澤涇潔灑窪浹淺漿澆湞溮濁測澮濟瀏滻渾滸濃潯濜塗湧涗濤澇淶漣潿渦溳渙滌潤澗漲澀澱淵淥漬瀆漸澠漁瀋滲溫遊灣濕濚潰濺漵漊潷滾滯灩灄滿瀅濾濫灤濱灘澦瀠瀟瀲濰溈潛潀瀦瀂瀾瀨瀕灝滅燈靈竈災燦煬爐燉煒熗點煉熾爍爛烴燭煙菸煩燒燁燴燙燼熱煥燜燾熅愛爺牘犛牽犧犢狀獷獁猶狽獮獰獨狹獅獪猙獄猻獫獵獼玀豬貓蝟獻獺璣璵瑒瑪瑋環現瑲璽琺瓏璫琿璡璉瑣瓊瑤璦璸瓔瓚甕甌產電畫暢疇癤療瘧癘瘍癧瘲瘡瘋皰痾癰痙癢瘂癆瘓癇癡痺癉瘮癒瘞瘻癟癱癮癭癩癬癲臯皚皺皸盞鹽監蓋盜盤瞘眥矓著睜睞瞼睪瞶瞞矚矯磯礬礦碭碼磚硨硯碸礪礱礫礎硜矽碩硤磽磑礄確磠鹼礙磧磣堿禮禡禕禰禎禱禍稟祿禪離禿稈種祕積稱稭穢穠穭稅穌穩穡穭窮竊竅窵窯竄窩窺竇窶豎競豎篤筍筆筧箋籠籩築篳篩簹箏籌篔簽籤篠簡籙簀篋籜籮簞簫簣簍籃籛籬籪籟糴類秈糶糲粵糞糧糝餱餈係繫緊絕縶糹糾紆紅紂纖紇約級紈纊紀紉緯紜紘純紕紗綱納紝縱綸紛紙紋紡紵紖紐紓線紺紲紱練組紳細織終縐絆紼絀紹繹經紿綁絨結絝繞絰絎繪給絢絳絡絕絞統綆綃絹繡綌綏縧繼綈績緒綾緓續綺緋綽鞝緄繩維綿綬繃綢綯綹綣綜綻綰綠綴緇緙緗緘緬纜緹緲緝縕繢緦綞緞緶緱縋緩締縷編緡緣縉縛縟縝縫縗縞纏縭縊縑繽縹縵縲纓縮繆繅纈繚繕繒韁繾繰繯繳纘罌網羅罰罷羆羈羥羨羣翹翽翬翺耮耬聳恥聶聾職聹聯聵聰肅腸膚骯餚腎腫脹脅膽勝朧腖臚脛膠脈膾髒臍腦膿臠腳脫腡臉臘醃膕齶膩靦膃騰臏羶臢緻輿捨艤艦艙艫艱豔藝節羋薌蕪蘆蓯葦藶莧萇蒼苧蘇薴蘋範莖蘢蔦塋煢繭荊薦薘莢蕘蓽萴蕎薈薺蕩榮葷滎犖熒蕁藎蓀蔭蕒葒葤藥蒞萊蓮蒔萵薟獲蕕瑩鶯蓴蘀蘿螢營縈蕭薩蔥蒕蕆蕢蔣蔞醟藍薊蘺蕷鎣驀虆薔蘞藺藹薀蘄蘊藪蘚櫱虜慮虛蟲虯蟣蝨雖蝦蠆蝕蟻螞蠁蠶蠔蜆蠱蠣蟶蠻蟄蛺蟯螄蠐蛻蝸蠟蠅蟈蟬蠍螻蠑螿蟎蠨釁眾銜補錶襯袞襖裊褘襪襲襏裝襠褌褳襝褲襉褸襤襴見觀覎規覓視覘覽覺覬覡覿覥覦覯覲覷觴觸觶誾讋譽謄說説謡訁計訂訃認譏訐訌討讓訕訖託訓議訊記訒講諱謳詎訝訥許訛論訩訟諷設訪訣證詁訶評詛識詗詐訴診詆謅詞詘詔詖譯詒誆誄試詿詩詰詼誠誅詵話誕詬詮詭詢詣諍該詳詫諢詡譸誡誣語誚誤誥誘誨誑誦誒請諸諏諾讀諑誹課諉諛誰諗調諂諒諄誶談讅誼謀諶諜謊諫諧謔謁謂諤諭諼讒諮諳諺諦謎諞諝謨讜謖謝謠謗謚謙謐謹謾謫譾謬譚譖譙讕譜譎讞譴譫讖穀豶贓貝貞負貟貢財責賢敗賬貨質販貪貧貶購貯貫貳賤賁貰貼貴貺貸貿費賀貽賊贄賈賄貲賃賂贓資賅贐賕賑賚賒賦賭齎贖賞賜贔賙賡賠賧賴賵贅賻賺賽賾贗贊讚贇贈贍贏贛赬趙趕趨趲躉躍蹌蹠躒蹟踐躂蹺蹕躚躋踴躊蹤躓躑躡蹣躕躥躪躦軀體轀車軋軌軒軑軔轉軛輪軟轟軲軻轤軸軹軼軤軫轢軺輕軾載輊轎輈輇輅較輒輔輛輦輩輝輥輞輬輟輜輳輻輯轀輸轡轅轄輾轆轍轔辭闢辯辮邊遼達遷過邁運還這進遠違連遲邇逕跡適選遜遞邐邏遺遙鄧鄺鄔郵鄒鄴鄰鬱郟鄶鄭鄆酈鄖鄲酇醞醱醬釅釃釀採釋裏裡鉤鑒鑑鑾銳錄鏨釒釓釔針釘釗釙釕釷釺釧釤鈒釩釣鍆釹鍚釵鈃鈣鈈鈦鉅鈍鈔鍾鐘鈉鋇鋼鈑鈐鑰欽鈞鎢鈎鈧鈁鈥鈄鈕鈀鈺錢鉦鉗鈷缽鈳鉕鈽鈸鉞鑽鉬鉭鉀鈿鈾鐵鉑鈴鑠鉛鉚鉋鈰鉉鉈鉍鈮鈹鐸鉶銬銠鉺鋩錏銪鋮鋏鋣鐃銍鐺銅鋁銱銦鎧鍘銖銑鋌銩銛鏵銓鎩鉿銚鉻銘錚銫鉸銥鏟銃鐋銨銀銣鑄鐒鋪鋙錸鋱鏈鍊鏗銷鎖鋰鋥鋤鍋鋯鋨鏽銹銼鋝鋒鋅鋶鐦鐧銳銻鋃鋟鋦錒錆鍺鍩錯錨錛錡鍀錁錕錩錫錮鑼錘錐錦鑕鍁錈鍃錇錟錠鍵鋸錳錙鍥鍈鍇鏘鍶鍔鍤鍬鍾鍛鎪鍠鍰鎄鍍鎂鏤鎡鐨鎇鏌鎮鎛鎘鑷钂鐫鎳鎿鎦鎬鎊鎰鎵鑌鎔鏢鏜鏝鏍鏰鏞鏡鏑鏃鏇鏐鐔钁鐐鏷鑥鐓鑭鐠鑹鏹鐙鑊鐳鐶鐲鐮鐿鑔钀鑞鑱鑲長門閂閃閆閈閉問闖閏闈閑閒閎間閔閌悶閘鬧閨聞闥閩閭闓閥閣閡閫鬮閱閬闍閾閹閶鬩閿閽閻閼闡闌闃闠闊闋闔闐闒闕闞闤隊陽陰陣階際陸隴陳陘陝隯隉隕險隨隱隸雋難僱雛讎靂霧霽黴霢靄靚靝靜麵靨韃鞽韉韝韋韌韍韓韙韞韜韻頹頁頂頃頇項順須頊頑顧頓頎頒頌頏預顱領頗頸頡頰頲頜潁熲頦頤頻頮頹頷頴穎顆題顒顎顓顔顏額顳顢顛顙顥纇顫顬顰顴風颺颭颮颯颶颸颼颻飀飄飆飈飛饗饜飠飣饑飥餳飩餼飪飫飭飯飲餞飾飽飼飿飴餌饒餉餄餎餃餏餅餑餖餓餘餒餕餜餛餡館餷饋餶餿饞饁饃餺餾饈饉饅饊饌饢罵馬馭馱馴馳驅馹駁驢駔駛駟駙駒騶駐駝駑駕驛駘驍罵駰驕驊駱駭駢驫驪騁驗騂駸駿騏騎騍騅騌驌驂騙騭騤騷騖驁騮騫騸驃騾驄驏驟驥驦驤髏髖髕鬢鬹魘魎魚魛魢魷魨魯魴䰾魺鮁鮃鯰鱸鮋鮓鮒鮊鮑鱟鮍鮐鮭鮚鮳鮪鮞鮦鰂鮜鱠鱭鮫鮮鮺鯗鱘鯁鱺鰱鰹鯉鰣鰷鯀鯊鯇鮶鯽鯒鯖鯪鯕鯫鯡鯤鯧鯝鯢鯰鯛鯨鰺鯴鯔鱝鰈鰏鱨鯷鰮鰃鰓鱷鰍鰒鰉鰁鱂鯿鰠鼇鰭鰨鰥鰩鰟鰜鰳鰾鱈鼈鰻鰵鱅鰼鱖鱔鱗鱒鱯鱤鱧鱣䲘鶿雞鳥鳩雞鳶鳴鳲鷗鴉鶬鴇鴆鴣鶇鸕鴨鴞鴦鴒鴟鴝鴛鷽鴕鷥鷙鴯鴰鵂鴴鵃鴿鸞鴻鵐鵓鸝鵑鵠鵝鵒鷳鵜鵡鵲鶓鵪鵾鵯鵬鵮鶉鶊鵷鷫鶘鶡鶚鶻鶖鶿鶥鶩鷊鷂鶲鶹鶺鷁鶼鶴鷖鸚鷓鷚鷯鷦鷲鷸鷺䴉鸇鷹鸌鸏鸛鸘鹺麥麩麴麼黃黌黶黷黲黽黿鼂鼉鼴齊齏齒齔齕齗齟齡齙齠齜齦齬齪齲齷龍龔龕龜痠'; const oc2tc = { @@ -84,10 +96,6 @@ const sc2tc = { '栗', ['慄','战栗','颤栗','不寒而栗'] ], - '凄':[ - '淒', - ['悽','凄厉','凄惨','悲凄','凄苦'] - ], '沈':[ '沈', ['瀋','沈阳'] @@ -321,7 +329,7 @@ const sc2tc = { '干':[ '幹', ['乾','口干','吃干','吐干','吮干','吸干','吹干','呷干','喉干','喝干','嘴干','太干','干井','干似','干冰','干冷','干化','干咳','干咽','干品','干哥','干嚎','干土','干坤','干妹','干姊','干姐','干姜','干娘','干爹','干爸','干妈','干季','干巴','干布','干干','干式','干弟','干性','干料','干旱','干杯','干果','干枝','干枯','干柴','干梅','干沙','干泥','干洗','干涸','干渴','干焦','干熬','干燥','干爽','干球','干疤','干瘦','干眼','干瞪','干硬','干窘','干笑','干等','干粉','干耗','干肉','干股','干脆','干花','干草','干菜','干薪','干衣','干裂','干透','干酪','干醋','干隆','干面','弄干','很干','抹干','抽干','揩干','擦干','晾干','朝干','未干','杯干','果干','桑干','榨干','水干','流干','海干','滴干','炒干','烘干','烤干','焙干','焦干','煨干','熨干','略干','碗干','粉干','耗干','肉干','舔干','菜干','蒸干','速干','干儿','干哑','干呕','干坛','干孙','干尸','干搁','干晒','干净','干涩','干涧','干湿','干热','干烧','干瘪','干瘾','干发','干粮','干结','干丝','干声','干叶','干号','干货','干阳','干饭','拧干','晒干','极干','泪干','沥干','烧干','烩干','发干','笋干','绞干','阴干','难干','风干','饮干','饼干','鱼干','唇干'], - ['干','干系','天干','干涉','干扰','干戈','相干'] + ['干','干系','天干','干涉','干扰','干戈','相干','干我什','干我事','干我的事','干你什','干你事','干你的事','干他什','干他事','干他的事','干她什','干她事','干她的事'] ], '了':[ '了', @@ -473,7 +481,7 @@ const tc2sc = { ['了','瞭望','瞭然','瞭解','瞭若指掌','瞭如指掌'] ] }; -const sc2tcComb = { +let sc2tcComb = { '香烟袅袅':'香煙裊裊', '袅袅香烟':'裊裊香煙', '补丁':'補靪', @@ -610,12 +618,12 @@ const sc2tcComb = { var stDict = {}, tsDict = {}; var sc2tcCombTree = {}, tc2scCombTree = {}; -function traditionalized(orgStr) { +function traditionalizedString(orgStr, format) { if (!orgStr) return ""; var str = '', char; for (var i = 0; i < orgStr.length; i++) { char = orgStr.charAt(i); - let search = sc2tcCombTree[char], searchIndex = i, hasMatch = false; + let search = sc2tcCombTree[char], searchIndex = i, hasMatch = false, startIndex = i; while (search && searchIndex < orgStr.length) { let downTree = null; if (searchIndex < orgStr.length - 1) { @@ -625,7 +633,19 @@ function traditionalized(orgStr) { if (search.end) { hasMatch = true; i = searchIndex; - str += search.end; + if (format === OutputFormat.NORMAL) { + str += search.end; + } else { + const originalText = orgStr.substring(startIndex, searchIndex + 1); + const convertedText = search.end; + if (format === OutputFormat.BRACKET && originalText !== convertedText) { + str += convertedText + '(' + originalText + ')'; + } else if (format === OutputFormat.RUBY && originalText !== convertedText) { + str += '' + convertedText + '' + originalText + ''; + } else { + str += convertedText; + } + } } break; } @@ -657,11 +677,15 @@ function traditionalized(orgStr) { var curOther = others[k], fadd = curOther.indexOf(char), badd = curOther.length - 1 - fadd, x = 0; var processChar = char; while (fadd-- > 0) { - if (char_f[x]) processChar = char_f[x] + processChar; + if (!char_f[x]) break; + processChar = char_f[x] + processChar; + x++; } x = 0; while (badd-- > 0) { - if (char_b[x]) processChar += char_b[x]; + if (!char_b[x]) break; + processChar += char_b[x]; + x++; } if (processChar.indexOf(curOther) != -1) { newChar = otherChar; @@ -675,7 +699,13 @@ function traditionalized(orgStr) { } else { newChar = tChar; } - str += newChar; + if (format === OutputFormat.BRACKET && char !== newChar) { + str += newChar + '(' + char + ')'; + } else if (format === OutputFormat.RUBY && char !== newChar) { + str += '' + newChar + '' + char + ''; + } else { + str += newChar; + } } else str += char; } else str += char; @@ -683,12 +713,44 @@ function traditionalized(orgStr) { return str; } -function simplized(orgStr) { +function traditionalized(input, options) { + options = options || {}; + const format = options.format !== undefined ? options.format : OutputFormat.NORMAL; + + // Handle null/undefined + if (input == null) return input; + + // Handle string + if (typeof input === 'string') { + return traditionalizedString(input, format); + } + + // Handle array + if (Array.isArray(input)) { + return input.map(item => traditionalized(item, options)); + } + + // Handle object + if (typeof input === 'object') { + const result = {}; + for (const key in input) { + if (input.hasOwnProperty(key)) { + result[key] = traditionalized(input[key], options); + } + } + return result; + } + + // Return other types as-is (number, boolean, etc.) + return input; +} + +function simplizedString(orgStr, format) { if (!orgStr) return ""; var str = '', char; for (var i = 0; i < orgStr.length; i++) { char = orgStr.charAt(i); - let search = tc2scCombTree[char], searchIndex = i, hasMatch = false; + let search = tc2scCombTree[char], searchIndex = i, hasMatch = false, startIndex = i; while (search && searchIndex < orgStr.length) { let downTree = null; if (searchIndex < orgStr.length - 1) { @@ -698,7 +760,19 @@ function simplized(orgStr) { if (search.end) { hasMatch = true; i = searchIndex; - str += search.end; + if (format === OutputFormat.NORMAL) { + str += search.end; + } else { + const originalText = orgStr.substring(startIndex, searchIndex + 1); + const convertedText = search.end; + if (format === OutputFormat.BRACKET && originalText !== convertedText) { + str += convertedText + '(' + originalText + ')'; + } else if (format === OutputFormat.RUBY && originalText !== convertedText) { + str += '' + convertedText + '' + originalText + ''; + } else { + str += convertedText; + } + } } break; } @@ -730,11 +804,15 @@ function simplized(orgStr) { var curOther = others[k], fadd = curOther.indexOf(char), badd = curOther.length - 1 - fadd, x = 0; var processChar = char; while (fadd-- > 0) { - if (char_f[x]) processChar = char_f[x] + processChar; + if (!char_f[x]) break; + processChar = char_f[x] + processChar; + x++; } x = 0; while (badd-- > 0) { - if (char_b[x]) processChar += char_b[x]; + if (!char_b[x]) break; + processChar += char_b[x]; + x++; } if (processChar.indexOf(curOther) != -1) { newChar = otherChar; @@ -748,7 +826,13 @@ function simplized(orgStr) { } else { newChar = sChar; } - str += newChar; + if (format === OutputFormat.BRACKET && char !== newChar) { + str += newChar + '(' + char + ')'; + } else if (format === OutputFormat.RUBY && char !== newChar) { + str += '' + newChar + '' + char + ''; + } else { + str += newChar; + } } else str += char; } else str += char; @@ -756,84 +840,149 @@ function simplized(orgStr) { return str; } -function Stcasc(cache, custom) { - if (!cache) cache = {}; - if (cache.sc2tcCombTree && cache.tc2scCombTree) { - sc2tcCombTree = cache.sc2tcCombTree; +function simplized(input, options) { + options = options || {}; + const format = options.format !== undefined ? options.format : OutputFormat.NORMAL; + + // Handle null/undefined + if (input == null) return input; + + // Handle string + if (typeof input === 'string') { + return simplizedString(input, format); + } + + // Handle array + if (Array.isArray(input)) { + return input.map(item => simplized(item, options)); + } + + // Handle object + if (typeof input === 'object') { + const result = {}; + for (const key in input) { + if (input.hasOwnProperty(key)) { + result[key] = simplized(input[key], options); + } + } + return result; + } + + // Return other types as-is (number, boolean, etc.) + return input; +} + +function detect(text) { + if (!text) return ChineseType.UNKNOWN; + + for (let i = 0; i < text.length; i++) { + const char = text.charAt(i); + if (char.charCodeAt(0) > 10000) { + const scChar = tsDict[char]; + if (scChar && scChar !== char) { + return ChineseType.TRADITIONAL; + } + } + } + + for (let i = 0; i < text.length; i++) { + const char = text.charAt(i); + if (char.charCodeAt(0) > 10000) { + const tcChar = stDict[char]; + if (tcChar && tcChar !== char) { + return ChineseType.SIMPLIFIED; + } + } + } + + return ChineseType.UNKNOWN; +} + +function stcasc(cache, custom, disableTerms) { + if (!cache) cache = {}; + if (cache.sc2tcCombTree && cache.tc2scCombTree) { + sc2tcCombTree = cache.sc2tcCombTree; tc2scCombTree = cache.tc2scCombTree; - } else { - if (custom && custom.length) { - for (let sc in custom) { - sc2tcComb[sc] = custom[sc]; - } - } - function makeCombTree(key, value) { - let curTree = sc2tcCombTree; - for (let i = 0; i < key.length; i++) { - let newTree = {}; - if (i == key.length - 1) { - newTree = {"end": value}; - } - let curKey = key.charAt(i); - let branch = curTree[curKey]; - if (!branch) { - curTree[curKey] = newTree; - curTree = newTree; - } else { - curTree = branch; - } - } - curTree = tc2scCombTree; - for (let i = 0; i < value.length; i++) { - let newTree = {}; - if (i == value.length - 1) { - newTree = {"end": key}; - } - let curKey = value.charAt(i); - let branch = curTree[curKey]; - if (!branch) { - curTree[curKey] = newTree; - curTree = newTree; - } else { - curTree = branch; - } - } - } - for (let key in sc2tcComb) { - let value = sc2tcComb[key]; - if (Array.isArray(value)) { - value.forEach(v => { - makeCombTree(key, v); - }); - } else { - makeCombTree(key, value); - } - } - cache.sc2tcCombTree = sc2tcCombTree; + } else { + if (disableTerms) sc2tcComb = {}; + if (custom && custom.length) { + for (let sc in custom) { + sc2tcComb[sc] = custom[sc]; + } + } + function makeCombTree(key, value) { + let curTree = sc2tcCombTree; + for (let i = 0; i < key.length; i++) { + let curKey = key.charAt(i); + let branch = curTree[curKey]; + let newTree = {}; + if (i == key.length - 1) { + newTree = {"end": value}; + if (branch) { + branch.end = value; + } + } + if (branch) { + curTree = branch; + } else { + curTree[curKey] = newTree; + curTree = newTree; + } + } + curTree = tc2scCombTree; + for (let i = 0; i < value.length; i++) { + let curKey = value.charAt(i); + let branch = curTree[curKey]; + let newTree = {}; + if (i == value.length - 1) { + newTree = {"end": key}; + if (branch) { + branch.end = key; + } + } + if (branch) { + curTree = branch; + } else { + curTree[curKey] = newTree; + curTree = newTree; + } + } + } + for (let key in sc2tcComb) { + let value = sc2tcComb[key]; + if (Array.isArray(value)) { + value.forEach(v => { + makeCombTree(key, v); + }); + } else { + makeCombTree(key, value); + } + } + cache.sc2tcCombTree = sc2tcCombTree; cache.tc2scCombTree = tc2scCombTree; - } - if (cache.stDict && cache.tsDict) { - stDict = cache.stDict; + } + if (cache.stDict && cache.tsDict) { + stDict = cache.stDict; tsDict = cache.tsDict; - } else { - for (let i = 0; i < scStr.length; i++) { - let _sc = scStr[i]; - let _tc = tcStr[i]; - if (!stDict[_sc]) stDict[_sc] = _tc; - if (!tsDict[_tc]) tsDict[_tc] = _sc; - } - Object.keys(oc2tc).forEach(key => { - let ocList = oc2tc[key]; - for (let i = 0; i < ocList.length; i++) { - let oc = ocList[i]; - stDict[oc] = key; - tsDict[oc] = tsDict[key] || key; - } - }) - cache.stDict = stDict; + } else { + for (let i = 0; i < scStr.length; i++) { + let _sc = scStr[i]; + let _tc = tcStr[i]; + if (!stDict[_sc]) stDict[_sc] = _tc; + if (!tsDict[_tc]) tsDict[_tc] = _sc; + } + Object.keys(oc2tc).forEach(key => { + let ocList = oc2tc[key]; + for (let i = 0; i < ocList.length; i++) { + let oc = ocList[i]; + stDict[oc] = key; + tsDict[oc] = tsDict[key] || key; + } + }) + cache.stDict = stDict; cache.tsDict = tsDict; - } - return {simplized, traditionalized, cache}; + } + return {simplized, traditionalized, detect, cache}; } -export default Stcasc; \ No newline at end of file +export default stcasc; diff --git a/Switch Traditional Chinese and Simplified Chinese/lib/test.js b/Switch Traditional Chinese and Simplified Chinese/lib/test.js new file mode 100644 index 00000000000..55337889052 --- /dev/null +++ b/Switch Traditional Chinese and Simplified Chinese/lib/test.js @@ -0,0 +1,215 @@ +import stcasc, { ChineseType, OutputFormat } from './stcasc.lib.js'; + +console.log('========== 简繁转换库测试 ==========\n'); + +// 初始化 +const { traditionalized, simplized, detect } = stcasc(); + +// 测试 1: 基础简体转繁体 +console.log('测试 1: 基础简体转繁体'); +const sc1 = '简繁转换 繁简切换 香烟 香烟袅袅 烟雾里 里长面子'; +const tc1 = traditionalized(sc1); +console.log('输入:', sc1); +console.log('输出:', tc1); +console.log(''); + +// 测试 2: 基础繁体转简体 +console.log('测试 2: 基础繁体转简体'); +const tc2 = '繁體中文 簡體中文'; +const sc2 = simplized(tc2); +console.log('输入:', tc2); +console.log('输出:', sc2); +console.log(''); + +// 测试 3: 检测简体中文 +console.log('测试 3: 检测简体中文'); +const text1 = '这是简体中文'; +const type1 = detect(text1); +console.log('文本:', text1); +console.log('类型:', type1 === ChineseType.SIMPLIFIED ? '简体中文' : '未知'); +console.log('枚举值:', type1); +console.log(''); + +// 测试 4: 检测繁体中文 +console.log('测试 4: 检测繁体中文'); +const text2 = '這是繁體中文'; +const type2 = detect(text2); +console.log('文本:', text2); +console.log('类型:', type2 === ChineseType.TRADITIONAL ? '繁体中文' : '未知'); +console.log('枚举值:', type2); +console.log(''); + +// 测试 5: 检测非中文 +console.log('测试 5: 检测非中文'); +const text3 = 'English Text'; +const type3 = detect(text3); +console.log('文本:', text3); +console.log('类型:', type3 === ChineseType.UNKNOWN ? '未知' : '中文'); +console.log('枚举值:', type3); +console.log(''); + +// 测试 6: 输出格式 - BRACKET(括号格式) +console.log('测试 6: 输出格式 - BRACKET(括号格式)'); +const sc3 = '简体中文转换'; +const tc3 = traditionalized(sc3, { format: OutputFormat.BRACKET }); +console.log('输入:', sc3); +console.log('输出:', tc3); +console.log(''); + +// 测试 7: 输出格式 - RUBY(HTML ruby标签格式) +console.log('测试 7: 输出格式 - RUBY(HTML ruby标签格式)'); +const sc4 = '简体中文'; +const tc4 = traditionalized(sc4, { format: OutputFormat.RUBY }); +console.log('输入:', sc4); +console.log('输出:', tc4); +console.log(''); + +// 测试 8: 繁体转简体 - BRACKET格式 +console.log('测试 8: 繁体转简体 - BRACKET格式'); +const tc5 = '繁體中文'; +const sc5 = simplized(tc5, { format: OutputFormat.BRACKET }); +console.log('输入:', tc5); +console.log('输出:', sc5); +console.log(''); + +// 测试 9: 繁体转简体 - RUBY格式 +console.log('测试 9: 繁体转简体 - RUBY格式'); +const tc6 = '繁體中文'; +const sc6 = simplized(tc6, { format: OutputFormat.RUBY }); +console.log('输入:', tc6); +console.log('输出:', sc6); +console.log(''); + +// 测试 10: 复杂文本转换 - 正常格式 +console.log('测试 10: 复杂文本转换 - 正常格式'); +const complex = '吃干面 把考卷发回来 卷发 知识产权'; +const complexTc = traditionalized(complex); +console.log('输入:', complex); +console.log('输出:', complexTc); +console.log(''); + +// 测试 11: 复杂文本转换 - BRACKET格式 +console.log('测试 11: 复杂文本转换 - BRACKET格式'); +const complexBracket = traditionalized(complex, { format: OutputFormat.BRACKET }); +console.log('输入:', complex); +console.log('输出:', complexBracket); +console.log(''); + +// 测试 12: 术语转换 +console.log('测试 12: 术语转换'); +const terms = '软件 硬盘 网络 服务器 鼠标'; +const termsTc = traditionalized(terms); +console.log('输入:', terms); +console.log('输出:', termsTc); +console.log(''); + +// 测试 13: 混合文本 +console.log('测试 13: 混合文本'); +const mixed = 'This is 简体中文 and English'; +const mixedTc = traditionalized(mixed); +console.log('输入:', mixed); +console.log('输出:', mixedTc); +console.log(''); + +// ========== 新增测试:Array/Object 支持 ========== +console.log('========== Array/Object 测试 ==========\n'); + +// 测试 14: 转换数组(简体->繁体) +console.log('测试 14: 转换数组(简体->繁体)'); +const arr1 = ['简体中文', '软件', '硬盘', 123, true, null]; +const arr1Tc = traditionalized(arr1); +console.log('输入:', arr1); +console.log('输出:', arr1Tc); +console.log(''); + +// 测试 15: 转换数组(繁体->简体) +console.log('测试 15: 转换数组(繁体->简体)'); +const arr2 = ['繁體中文', '軟體', '硬碟', 456, false]; +const arr2Sc = simplized(arr2); +console.log('输入:', arr2); +console.log('输出:', arr2Sc); +console.log(''); + +// 测试 16: 转换对象(简体->繁体) +console.log('测试 16: 转换对象(简体->繁体)'); +const obj1 = { + title: '简体中文标题', + description: '这是一个简体中文描述', + count: 100, + active: true, + tags: ['软件', '网络', '服务器'] +}; +const obj1Tc = traditionalized(obj1); +console.log('输入:', JSON.stringify(obj1, null, 2)); +console.log('输出:', JSON.stringify(obj1Tc, null, 2)); +console.log(''); + +// 测试 17: 转换对象(繁体->简体) +console.log('测试 17: 转换对象(繁体->简体)'); +const obj2 = { + title: '繁體中文標題', + description: '這是一個繁體中文描述', + price: 99.99, + items: ['軟體', '硬碟'] +}; +const obj2Sc = simplized(obj2); +console.log('输入:', JSON.stringify(obj2, null, 2)); +console.log('输出:', JSON.stringify(obj2Sc, null, 2)); +console.log(''); + +// 测试 18: 转换嵌套数组 +console.log('测试 18: 转换嵌套数组'); +const nestedArr = [ + '简体中文', + ['软件', '硬盘'], + [['网络', '服务器']] +]; +const nestedArrTc = traditionalized(nestedArr); +console.log('输入:', JSON.stringify(nestedArr)); +console.log('输出:', JSON.stringify(nestedArrTc)); +console.log(''); + +// 测试 19: 转换嵌套对象 +console.log('测试 19: 转换嵌套对象'); +const nestedObj = { + user: { + name: '简体名称', + profile: { + bio: '这是简体中文简介', + skills: ['软件开发', '网络管理'] + } + }, + count: 42 +}; +const nestedObjTc = traditionalized(nestedObj); +console.log('输入:', JSON.stringify(nestedObj, null, 2)); +console.log('输出:', JSON.stringify(nestedObjTc, null, 2)); +console.log(''); + +// 测试 20: 数组转换 - BRACKET 格式 +console.log('测试 20: 数组转换 - BRACKET 格式'); +const arr3 = ['简体', '中文']; +const arr3Bracket = traditionalized(arr3, { format: OutputFormat.BRACKET }); +console.log('输入:', arr3); +console.log('输出:', arr3Bracket); +console.log(''); + +// 测试 21: 对象转换 - RUBY 格式 +console.log('测试 21: 对象转换 - RUBY 格式'); +const obj3 = { + text1: '简体', + text2: '中文' +}; +const obj3Ruby = traditionalized(obj3, { format: OutputFormat.RUBY }); +console.log('输入:', JSON.stringify(obj3, null, 2)); +console.log('输出:', JSON.stringify(obj3Ruby, null, 2)); +console.log(''); + +// 测试 22: 处理 null 和 undefined +console.log('测试 22: 处理 null 和 undefined'); +console.log('null 输入:', traditionalized(null)); +console.log('undefined 输入:', traditionalized(undefined)); +console.log('包含 null 的数组:', traditionalized(['简体', null, '中文'])); +console.log(''); + +console.log('========== 测试完成 =========='); diff --git a/X-Downloader/X-Downloader.user.js b/X-Downloader/X-Downloader.user.js new file mode 100644 index 00000000000..72531dfbd90 --- /dev/null +++ b/X-Downloader/X-Downloader.user.js @@ -0,0 +1,167 @@ +// ==UserScript== +// @name X-Downloader-Script +// @name:zh-CN X-Downloader-Script +// @name:zh-TW X-Downloader-Script +// @name:ja X-Downloader-Script +// @namespace hoothin +// @version 2025-08-18 +// @license MIT +// @description Enhances your Twitter (X) experience by adding a convenient download button to images and videos (GIFs), enabling easy, one-click saving of media. +// @description:zh-CN 优化你的推特 (X) 浏览体验,直接在图片和视频(GIF)上添加一个便捷的下载按钮,一键轻松保存喜欢的媒体内容。 +// @description:zh-TW 優化您的 Twitter (X) 瀏覽體驗,直接在圖片及影片(GIF)上新增一個便捷的下載按鈕,一鍵輕鬆儲存喜愛的媒體內容。 +// @description:ja Twitter (X) の画像や動画(GIF)に便利なダウンロードボタンを追加し、ワンクリックでお気に入りのメディアを簡単に保存できるようにします。 +// @author hoothin +// @match https://x.com/* +// @match https://twitter.com/* +// @icon data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== +// @grant none +// @downloadURL https://update.greasyfork.org/scripts/545186/X-Downloader-Script.user.js +// @updateURL https://update.greasyfork.org/scripts/545186/X-Downloader-Script.meta.js +// ==/UserScript== + +(function() { + 'use strict'; + let downloadBtn = document.createElement("a"), touch = false, simpleClick = false; + downloadBtn.target = "_blank"; + downloadBtn.style.cssText = "background: #000000aa; border-radius: 50%; transition: opacity ease 0.3s; position: absolute; top: 0; right: 0px; cursor: pointer; opacity: 0; padding: 5px;"; + downloadBtn.innerHTML = ``; + downloadBtn.addEventListener("mousedown", e => { + let parent = downloadBtn.parentNode; + if (!parent) return; + simpleClick = false; + let img = parent.querySelector('[data-testid="tweetPhoto"]>img,[data-testid="card.layoutLarge.media"] img'); + if (img) { + let newsrc = img.src.replace("_normal.",".").replace("_200x200.",".").replace("_mini.",".").replace("_bigger.",".").replace(/_x\d+\./,"."), imgname; + if (/\.svg$/.test(newsrc)) return; + if (newsrc == img.src) { + newsrc=newsrc.replace(/\?format=/i, ".").replace(/\&name=/i, ":").replace(/\.(?=[^\.\/]*$)/, "?format=").replace( /(:large|:medium|:small|:orig|:thumb|:[\dx]+)/i, ""); + if (newsrc != img.src) { + newsrc = newsrc + "&name=orig"; + } + } + while(parent) { + if (parent.nodeName == "ARTICLE" && parent.dataset && parent.dataset.testid == "tweet") { + break; + } + parent = parent.parentNode; + } + if (parent) { + const time = parent.querySelector('time[datetime]'); + const user = parent.querySelector('[role="link"]>div>div>span>span'); + let formatMatch = img.src.match(/format=(\w+)/), ext = "jpg"; + if (formatMatch) { + ext = formatMatch[1]; + } else { + formatMatch = newsrc.match(/\.(\w+)/); + if (formatMatch) { + ext = formatMatch[1]; + } + } + imgname = `${user.innerText} ${time.innerText.replace(/(.*) · (.*)/, "$2 $1")}.${ext}`; + } + downloadBtn.href = newsrc; + if ((e.button === 0 && !e.ctrlKey) || touch) { + simpleClick = true; + downloadByFetch(newsrc, imgname); + } + } else { + while(parent) { + if (parent.nodeName == "ARTICLE" && parent.dataset && parent.dataset.testid == "tweet") { + break; + } + parent = parent.parentNode; + } + if (parent) { + downloadBtn.removeAttribute('download'); + let link = parent.querySelector('a[role="link"][aria-label][href^="/"]'); + downloadBtn.href = `https://twitter.luopo.org/?url=${encodeURIComponent(link ? link.href : document.location.href)}`; + if (e.altKey || touch) { + window.open(downloadBtn.href, "_blank"); + } + } + } + }); + downloadBtn.addEventListener("click", e => { + if (simpleClick || e.altKey || touch) { + e.preventDefault(); + e.stopPropagation(); + } + }); + downloadBtn.addEventListener("mouseenter", () => { + downloadBtn.style.opacity = 1; + }); + downloadBtn.addEventListener("mouseleave", () => { + setTimeout(() => { + downloadBtn.style.opacity = 0.1; + }, 100); + }); + async function downloadByFetch(imageUrl, filename) { + try { + const response = await fetch(imageUrl); + if (!response.ok) throw new Error('CORS request failed'); + const blob = await response.blob(); + const blobUrl = URL.createObjectURL(blob); + const tempLink = document.createElement('a'); + tempLink.href = blobUrl; + tempLink.setAttribute('download', filename); + document.body.appendChild(tempLink); + tempLink.click(); + document.body.removeChild(tempLink); + URL.revokeObjectURL(blobUrl); + } catch (error) { + console.error('error:', error); + window.open(imageUrl, '_blank'); + } + } + const show = (ele) => { + ele.appendChild(downloadBtn); + setTimeout(() => { + downloadBtn.style.opacity = touch ? 0.8 : 0.6; + }, 0); + }; + const addBtn = e => { + if (e.target.dataset && e.target.dataset.testid == "card.layoutLarge.media") { + show(e.target.parentNode); + } else if (e.target.dataset && e.target.dataset.testid == "tweetPhoto") { + show(e.target.parentNode); + } else if (e.target.dataset && /^video\-player/.test(e.target.dataset.testid)) { + show(e.target.parentNode); + } else if (e.target.parentNode && e.target.parentNode.dataset && e.target.parentNode.dataset.testid == "tweetPhoto") { + show(e.target.parentNode.parentNode); + } + }; + function isElementVisible(el) { + const rect = el.getBoundingClientRect(); + return rect.top < window.innerHeight && rect.top > 0 && rect.bottom >= 0; + } + function findFirstVisibleElement(selector) { + const elements = document.querySelectorAll(selector); + const firstVisibleElement = Array.from(elements).find(el => { + return isElementVisible(el); + }); + return firstVisibleElement; + } + let checkTimer; + const touchCheck = e => { + clearTimeout(checkTimer); + if (e.target == downloadBtn) return; + checkTimer = setTimeout(() => { + if (isElementVisible(downloadBtn)) return; + let target = findFirstVisibleElement("[data-testid='card.layoutLarge.media']"); + if (target) { + return show(target.parentNode); + } + target = findFirstVisibleElement("[data-testid='tweetPhoto']"); + if (target) { + return show(target.parentNode); + } + target = findFirstVisibleElement("[data-testid^='video-player']"); + if (target) { + return show(target.parentNode); + } + }, 100); + }; + document.addEventListener("mouseenter", addBtn, true); + document.addEventListener("touchstart", e => {touch = true; addBtn(e);}, true); + document.addEventListener("touchend", touchCheck, true); +})(); \ No newline at end of file