From 4b73ec962e79cd8cb106d413364646577399bf82 Mon Sep 17 00:00:00 2001 From: hoothin Date: Sat, 17 Jan 2026 18:26:04 +0900 Subject: [PATCH 01/50] Update Picviewer CE+.user.js --- Picviewer CE+/Picviewer CE+.user.js | 47 ++++++++++++++++++++++------- 1 file changed, 36 insertions(+), 11 deletions(-) diff --git a/Picviewer CE+/Picviewer CE+.user.js b/Picviewer CE+/Picviewer CE+.user.js index 69b14bfd5a8..b11d15cc288 100644 --- a/Picviewer CE+/Picviewer CE+.user.js +++ b/Picviewer CE+/Picviewer CE+.user.js @@ -12,7 +12,7 @@ // @description:ja 画像を強力に閲覧できるツール。ポップアップ表示、拡大・縮小、回転、一括保存などの機能を自動で実行できます // @description:pt-BR Poderosa ferramenta de visualização de imagens on-line, que pode pop-up/dimensionar/girar/salvar em lote imagens automaticamente // @description:ru Мощный онлайн-инструмент для просмотра изображений, который может автоматически отображать/масштабировать/вращать/пакетно сохранять изображения -// @version 2026.1.13.1 +// @version 2026.1.17.1 // @icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAAV1BMVEUAAAD////29vbKysoqKioiIiKysrKhoaGTk5N9fX3z8/Pv7+/r6+vk5OTb29vOzs6Ojo5UVFQzMzMZGRkREREMDAy4uLisrKylpaV4eHhkZGRPT08/Pz/IfxjQAAAAgklEQVQoz53RRw7DIBBAUb5pxr2m3/+ckfDImwyJlL9DDzQgDIUMRu1vWOxTBdeM+onApENF0qHjpkOk2VTwLVEF40Kbfj1wK8AVu2pQA1aBBYDHJ1wy9Cf4cXD5chzNAvsAnc8TjoLAhIzsBao9w1rlVTIvkOYMd9nm6xPi168t9AYkbANdajpjcwAAAABJRU5ErkJggg== // @namespace https://github.com/hoothin/UserScripts // @homepage https://pv.hoothin.com/ @@ -24224,15 +24224,33 @@ ImgOps | https://imgops.com/#b#`; const loaded = await Promise.all(srcs.map(src => this.loadImageForStitch(src))); let totalW = 0; let totalH = 0; + let maxW = 0; + let maxH = 0; + loaded.forEach(({img}) => { + const w = img.naturalWidth || img.width; + const h = img.naturalHeight || img.height; + if (w > maxW) maxW = w; + if (h > maxH) maxH = h; + }); if (layout === 'column') { loaded.forEach(({img}) => { - totalW = Math.max(totalW, img.naturalWidth || img.width); - totalH += img.naturalHeight || img.height; + const w = img.naturalWidth || img.width; + const h = img.naturalHeight || img.height; + const ratio = w ? (maxW / w) : 1; + const drawW = maxW || w; + const drawH = h * ratio; + totalW = Math.max(totalW, drawW); + totalH += drawH; }); } else { loaded.forEach(({img}) => { - totalW += img.naturalWidth || img.width; - totalH = Math.max(totalH, img.naturalHeight || img.height); + const w = img.naturalWidth || img.width; + const h = img.naturalHeight || img.height; + const ratio = h ? (maxH / h) : 1; + const drawH = maxH || h; + const drawW = w * ratio; + totalW += drawW; + totalH = Math.max(totalH, drawH); }); } const canvas = document.createElement('canvas'); @@ -24244,11 +24262,17 @@ ImgOps | https://imgops.com/#b#`; const w = img.naturalWidth || img.width; const h = img.naturalHeight || img.height; if (layout === 'column') { - ctx.drawImage(img, 0, offset, w, h); - offset += h; + const ratio = w ? (maxW / w) : 1; + const drawW = maxW || w; + const drawH = h * ratio; + ctx.drawImage(img, 0, offset, drawW, drawH); + offset += drawH; } else { - ctx.drawImage(img, offset, 0, w, h); - offset += w; + const ratio = h ? (maxH / h) : 1; + const drawH = maxH || h; + const drawW = w * ratio; + ctx.drawImage(img, offset, 0, drawW, drawH); + offset += drawW; } }); const blob = await new Promise(resolve => canvas.toBlob(resolve, 'image/png')); @@ -28266,7 +28290,7 @@ ImgOps | https://imgops.com/#b#`; var configStyle = document.createElement("style"); configStyle.textContent = "#pv-prefs { display: initial; }"; configStyle.type = 'text/css'; - if (location.hostname == "hoothin.github.io" && location.pathname == "/UserScripts/Picviewer%20CE+/") { + if ((location.hostname == "hoothin.github.io" && location.pathname == "/UserScripts/Picviewer%20CE+/") || (location.hostname == "pv.hoothin.com" && location.pathname.indexOf("open-settings") !== -1)) { openPrefs(); } else if (location.hostname == "hoothin.github.io" && location.pathname == "/UserScripts/Picviewer%20CE+/gallery.html") { let gallery = new GalleryC(); @@ -28382,7 +28406,7 @@ ImgOps | https://imgops.com/#b#`; setTimeout(()=>{ if (GM_config.frame && GM_config.frame.contentDocument.body.innerHTML === "") { - _GM_openInTab("https://hoothin.github.io/UserScripts/Picviewer%20CE+/", {active:true}); + _GM_openInTab("https://pv.hoothin.com/open-settings", {active:true}); return; } if (GM_config.frame && GM_config.frame.style && GM_config.frame.style.display == "none") { @@ -28420,6 +28444,7 @@ ImgOps | https://imgops.com/#b#`; try { if (localStorage && localStorage.setItem) { if (!storage.getItem('inited')) { + _GM_openInTab("https://pv.hoothin.com/first-run"); localStorage.setItem('picviewerCE.config.curTab', 4); storage.setItem('inited', true); } From c02f019c2cad42361ace182d397c17806b111823 Mon Sep 17 00:00:00 2001 From: hoothin-update Date: Sat, 17 Jan 2026 09:26:18 +0000 Subject: [PATCH 02/50] chore(Picviewer CE+): Auto-generate dist.user.js --- Picviewer CE+/dist.user.js | 47 +++++++++++++++++++++++++++++--------- 1 file changed, 36 insertions(+), 11 deletions(-) diff --git a/Picviewer CE+/dist.user.js b/Picviewer CE+/dist.user.js index 427fe3c7eda..5ae597ad9f5 100644 --- a/Picviewer CE+/dist.user.js +++ b/Picviewer CE+/dist.user.js @@ -12,7 +12,7 @@ // @description:ja 画像を強力に閲覧できるツール。ポップアップ表示、拡大・縮小、回転、一括保存などの機能を自動で実行できます // @description:pt-BR Poderosa ferramenta de visualização de imagens on-line, que pode pop-up/dimensionar/girar/salvar em lote imagens automaticamente // @description:ru Мощный онлайн-инструмент для просмотра изображений, который может автоматически отображать/масштабировать/вращать/пакетно сохранять изображения -// @version 2026.1.13.1 +// @version 2026.1.17.1 // @icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAAV1BMVEUAAAD////29vbKysoqKioiIiKysrKhoaGTk5N9fX3z8/Pv7+/r6+vk5OTb29vOzs6Ojo5UVFQzMzMZGRkREREMDAy4uLisrKylpaV4eHhkZGRPT08/Pz/IfxjQAAAAgklEQVQoz53RRw7DIBBAUb5pxr2m3/+ckfDImwyJlL9DDzQgDIUMRu1vWOxTBdeM+onApENF0qHjpkOk2VTwLVEF40Kbfj1wK8AVu2pQA1aBBYDHJ1wy9Cf4cXD5chzNAvsAnc8TjoLAhIzsBao9w1rlVTIvkOYMd9nm6xPi168t9AYkbANdajpjcwAAAABJRU5ErkJggg== // @namespace https://github.com/hoothin/UserScripts // @homepage https://pv.hoothin.com/ @@ -24224,15 +24224,33 @@ ImgOps | https://imgops.com/#b#`; const loaded = await Promise.all(srcs.map(src => this.loadImageForStitch(src))); let totalW = 0; let totalH = 0; + let maxW = 0; + let maxH = 0; + loaded.forEach(({img}) => { + const w = img.naturalWidth || img.width; + const h = img.naturalHeight || img.height; + if (w > maxW) maxW = w; + if (h > maxH) maxH = h; + }); if (layout === 'column') { loaded.forEach(({img}) => { - totalW = Math.max(totalW, img.naturalWidth || img.width); - totalH += img.naturalHeight || img.height; + const w = img.naturalWidth || img.width; + const h = img.naturalHeight || img.height; + const ratio = w ? (maxW / w) : 1; + const drawW = maxW || w; + const drawH = h * ratio; + totalW = Math.max(totalW, drawW); + totalH += drawH; }); } else { loaded.forEach(({img}) => { - totalW += img.naturalWidth || img.width; - totalH = Math.max(totalH, img.naturalHeight || img.height); + const w = img.naturalWidth || img.width; + const h = img.naturalHeight || img.height; + const ratio = h ? (maxH / h) : 1; + const drawH = maxH || h; + const drawW = w * ratio; + totalW += drawW; + totalH = Math.max(totalH, drawH); }); } const canvas = document.createElement('canvas'); @@ -24244,11 +24262,17 @@ ImgOps | https://imgops.com/#b#`; const w = img.naturalWidth || img.width; const h = img.naturalHeight || img.height; if (layout === 'column') { - ctx.drawImage(img, 0, offset, w, h); - offset += h; + const ratio = w ? (maxW / w) : 1; + const drawW = maxW || w; + const drawH = h * ratio; + ctx.drawImage(img, 0, offset, drawW, drawH); + offset += drawH; } else { - ctx.drawImage(img, offset, 0, w, h); - offset += w; + const ratio = h ? (maxH / h) : 1; + const drawH = maxH || h; + const drawW = w * ratio; + ctx.drawImage(img, offset, 0, drawW, drawH); + offset += drawW; } }); const blob = await new Promise(resolve => canvas.toBlob(resolve, 'image/png')); @@ -28266,7 +28290,7 @@ ImgOps | https://imgops.com/#b#`; var configStyle = document.createElement("style"); configStyle.textContent = "#pv-prefs { display: initial; }"; configStyle.type = 'text/css'; - if (location.hostname == "hoothin.github.io" && location.pathname == "/UserScripts/Picviewer%20CE+/") { + if ((location.hostname == "hoothin.github.io" && location.pathname == "/UserScripts/Picviewer%20CE+/") || (location.hostname == "pv.hoothin.com" && location.pathname.indexOf("open-settings") !== -1)) { openPrefs(); } else if (location.hostname == "hoothin.github.io" && location.pathname == "/UserScripts/Picviewer%20CE+/gallery.html") { let gallery = new GalleryC(); @@ -28382,7 +28406,7 @@ ImgOps | https://imgops.com/#b#`; setTimeout(()=>{ if (GM_config.frame && GM_config.frame.contentDocument.body.innerHTML === "") { - _GM_openInTab("https://hoothin.github.io/UserScripts/Picviewer%20CE+/", {active:true}); + _GM_openInTab("https://pv.hoothin.com/open-settings", {active:true}); return; } if (GM_config.frame && GM_config.frame.style && GM_config.frame.style.display == "none") { @@ -28420,6 +28444,7 @@ ImgOps | https://imgops.com/#b#`; try { if (localStorage && localStorage.setItem) { if (!storage.getItem('inited')) { + _GM_openInTab("https://pv.hoothin.com/first-run"); localStorage.setItem('picviewerCE.config.curTab', 4); storage.setItem('inited', true); } From 3ef164265f2bff8373c9af59c1e30174bd12583a Mon Sep 17 00:00:00 2001 From: hoothin Date: Mon, 19 Jan 2026 09:43:22 +0900 Subject: [PATCH 03/50] Update README.md --- Pagetual/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Pagetual/README.md b/Pagetual/README.md index 6077f2266b0..b24092e63dc 100644 --- a/Pagetual/README.md +++ b/Pagetual/README.md @@ -2,7 +2,7 @@ == *Pagetual - Perpetual pages. Auto loading paginated web pages for 90% of all web sites !* -🔧CONFIGURATION PAGE +🔧CONFIGURATION PAGE

@@ -33,7 +33,7 @@ https://raw.githubusercontent.com/hoothin/UserScripts/master/Pagetual/pagetualRu
         Made with ❤️ by Hoothin
     
     
-        
+        
     
 
 

From cb0d902e7f7ad2c9355f98f895733799bc538700 Mon Sep 17 00:00:00 2001
From: hoothin 
Date: Mon, 19 Jan 2026 10:02:34 +0900
Subject: [PATCH 04/50] Update pagetual.user.js

---
 Pagetual/pagetual.user.js | 28 +++++++++++++++++++++++++---
 1 file changed, 25 insertions(+), 3 deletions(-)

diff --git a/Pagetual/pagetual.user.js b/Pagetual/pagetual.user.js
index c84d06d613c..56682e7251e 100644
--- a/Pagetual/pagetual.user.js
+++ b/Pagetual/pagetual.user.js
@@ -9328,7 +9328,7 @@
                 importBtn.style.fontSize = "20px";
                 importBtn.addEventListener("click", e => {
                     let parentNode = importBtn.parentNode;
-                    if (!parentNode) return;
+                    if (!parentNode || !e.isTrusted) return;
                     parentNode.removeChild(importBtn);
                     try {
                         let rules = parentNode.innerText.trim();
@@ -9522,11 +9522,11 @@
                   padding: 0!important;
                  }
                  #saveBtn {
-                  width: 60vw;
+                  width: var(--config-width, 60vw);
                   position: fixed;
                   z-index: 999;
                   bottom: 0;
-                  left: 20vw;
+                  left: var(--config-left, 20vw);
                   font-size: xx-large;
                   opacity: 0.6;
                   cursor: pointer;
@@ -10021,6 +10021,7 @@
         }
 
         updateP.onclick = e => {
+            if (!e.isTrusted) return;
             updateFail = false;
             //ruleParser.rules = [];
             showTips(i18n("beginUpdate"), "", 30000);
@@ -10105,8 +10106,29 @@
         saveBtn.innerHTML = i18n("save");
         saveBtn.id = "saveBtn";
         configCon.appendChild(saveBtn);
+        saveBtn.style.display = "none";
+        const syncSaveBtnLayout = () => {
+            if (!configCon || !saveBtn) return;
+            const rect = configCon.getBoundingClientRect();
+            if (rect.width > 0) {
+                document.documentElement.style.setProperty("--config-left", `${rect.left}px`);
+                document.documentElement.style.setProperty("--config-width", `${rect.width}px`);
+                saveBtn.style.display = "";
+            } else {
+                saveBtn.style.display = "none";
+            }
+        };
+        syncSaveBtnLayout();
+        window.addEventListener("resize", syncSaveBtnLayout);
+        if (window.ResizeObserver) {
+            const saveBtnResizeObserver = new ResizeObserver(() => {
+                syncSaveBtnLayout();
+            });
+            saveBtnResizeObserver.observe(configCon);
+        }
         saveBtn.onclick = e => {
             try {
+                if (!e.isTrusted) return;
                 let customRules;
                 if (editor) {
                     if (editorChanged) {

From 16cd85d93141722d41dc03e53da4262a31182343 Mon Sep 17 00:00:00 2001
From: hoothin 
Date: Tue, 20 Jan 2026 11:38:26 +0900
Subject: [PATCH 05/50] Update README.md

---
 Pagetual/README.md | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/Pagetual/README.md b/Pagetual/README.md
index b24092e63dc..a0d35bb29cf 100644
--- a/Pagetual/README.md
+++ b/Pagetual/README.md
@@ -30,10 +30,7 @@ https://raw.githubusercontent.com/hoothin/UserScripts/master/Pagetual/pagetualRu
         Send 📧email
     
     
-        Made with ❤️ by Hoothin
-    
-    
-        
+        
Made with ❤️ by Hoothin From aa81734ae9a05ee5fa5d91e798ccf12c3c74a36b Mon Sep 17 00:00:00 2001 From: hoothin Date: Tue, 20 Jan 2026 17:11:16 +0900 Subject: [PATCH 06/50] Update Picviewer CE+.user.js --- Picviewer CE+/Picviewer CE+.user.js | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/Picviewer CE+/Picviewer CE+.user.js b/Picviewer CE+/Picviewer CE+.user.js index b11d15cc288..a9f1ad098dd 100644 --- a/Picviewer CE+/Picviewer CE+.user.js +++ b/Picviewer CE+/Picviewer CE+.user.js @@ -27420,6 +27420,8 @@ ImgOps | https://imgops.com/#b#`; "#pv-prefs .section_header_holder { padding-right: 10px; }", "#pv-prefs textarea { width: 100%; }", "#pv-prefs .nav-tabs { white-space: nowrap; width: fit-content; max-width: 100%; margin: 20 auto; display: flex; overflow-x: auto; overflow-y: visible; }", + "#pv-prefs_buttons_holder { position: fixed; bottom: 0; width: 100%; right: 10px; background: #EEE; }", + "#pv-prefs_wrapper { padding-bottom: 70px; }" ].join('\n'), fields: { // 浮动工具栏 @@ -28055,6 +28057,9 @@ ImgOps | https://imgops.com/#b#`; }, events: { open: async function(doc, win, frame) { + if (localStorage && localStorage.getItem && localStorage.getItem('picviewerCE.config.curTab') === null) { + localStorage.setItem('picviewerCE.config.curTab', 4); + } isConfigOpen = true; let saveBtn = doc.querySelector("#"+this.id+"_saveBtn"); let closeBtn = doc.querySelector("#"+this.id+"_closeBtn"); @@ -28442,12 +28447,9 @@ ImgOps | https://imgops.com/#b#`; } }); try { - if (localStorage && localStorage.setItem) { - if (!storage.getItem('inited')) { - _GM_openInTab("https://pv.hoothin.com/first-run"); - localStorage.setItem('picviewerCE.config.curTab', 4); - storage.setItem('inited', true); - } + if (!storage.getItem('inited')) { + _GM_openInTab("https://pv.hoothin.com/first-run", {active:true}); + storage.setItem('inited', true); } } catch(e) {} if (typeof prefs.gallery.formatConversion == 'undefined') { From 6f1c5ddcdf2ecbcb8e2e87633d9ea7599de72a83 Mon Sep 17 00:00:00 2001 From: hoothin-update Date: Tue, 20 Jan 2026 08:11:35 +0000 Subject: [PATCH 07/50] chore(Picviewer CE+): Auto-generate dist.user.js --- Picviewer CE+/dist.user.js | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/Picviewer CE+/dist.user.js b/Picviewer CE+/dist.user.js index 5ae597ad9f5..a5658d84035 100644 --- a/Picviewer CE+/dist.user.js +++ b/Picviewer CE+/dist.user.js @@ -27420,6 +27420,8 @@ ImgOps | https://imgops.com/#b#`; "#pv-prefs .section_header_holder { padding-right: 10px; }", "#pv-prefs textarea { width: 100%; }", "#pv-prefs .nav-tabs { white-space: nowrap; width: fit-content; max-width: 100%; margin: 20 auto; display: flex; overflow-x: auto; overflow-y: visible; }", + "#pv-prefs_buttons_holder { position: fixed; bottom: 0; width: 100%; right: 10px; background: #EEE; }", + "#pv-prefs_wrapper { padding-bottom: 70px; }" ].join('\n'), fields: { // 浮动工具栏 @@ -28055,6 +28057,9 @@ ImgOps | https://imgops.com/#b#`; }, events: { open: async function(doc, win, frame) { + if (localStorage && localStorage.getItem && localStorage.getItem('picviewerCE.config.curTab') === null) { + localStorage.setItem('picviewerCE.config.curTab', 4); + } isConfigOpen = true; let saveBtn = doc.querySelector("#"+this.id+"_saveBtn"); let closeBtn = doc.querySelector("#"+this.id+"_closeBtn"); @@ -28442,12 +28447,9 @@ ImgOps | https://imgops.com/#b#`; } }); try { - if (localStorage && localStorage.setItem) { - if (!storage.getItem('inited')) { - _GM_openInTab("https://pv.hoothin.com/first-run"); - localStorage.setItem('picviewerCE.config.curTab', 4); - storage.setItem('inited', true); - } + if (!storage.getItem('inited')) { + _GM_openInTab("https://pv.hoothin.com/first-run", {active:true}); + storage.setItem('inited', true); } } catch(e) {} if (typeof prefs.gallery.formatConversion == 'undefined') { From 6d9dcf44298e4abc38d139d025794204594edecd Mon Sep 17 00:00:00 2001 From: hoothin Date: Tue, 20 Jan 2026 19:37:46 +0900 Subject: [PATCH 08/50] Update pvcep_rules.js --- Picviewer CE+/pvcep_rules.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Picviewer CE+/pvcep_rules.js b/Picviewer CE+/pvcep_rules.js index d1a878995eb..25a9bade564 100644 --- a/Picviewer CE+/pvcep_rules.js +++ b/Picviewer CE+/pvcep_rules.js @@ -302,8 +302,8 @@ var siteInfo = [ name: '花瓣网', url: /^https?:\/\/huaban\.com\//i, ext: 'previous-2', - r: [/(.*img.hb.aicdn.com\/.*)_fw(?:236|320)$/i, /_fw\d+\w+/i], - s: ['$1_fw658', ''], + r: [/(.*img.hb.aicdn.com\/.*)_fw(?:236|320)$/i, /(\/small)(\/.*)_fw\d+\w+/i, /_fw\d+\w+/i], + s: ['$1_fw658', '$2', ''], description: './../following-sibling::p[@class="description"]', exclude: /weixin_code\.png$/i }, From 649a918643b999f38796a074b4bb48aeecbc4083 Mon Sep 17 00:00:00 2001 From: hoothin Date: Tue, 20 Jan 2026 19:40:47 +0900 Subject: [PATCH 09/50] Update Picviewer CE+.user.js --- Picviewer CE+/Picviewer CE+.user.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Picviewer CE+/Picviewer CE+.user.js b/Picviewer CE+/Picviewer CE+.user.js index a9f1ad098dd..d78cf8b0efd 100644 --- a/Picviewer CE+/Picviewer CE+.user.js +++ b/Picviewer CE+/Picviewer CE+.user.js @@ -46,7 +46,7 @@ // @grant GM.notification // @grant unsafeWindow // @require https://update.greasyfork.org/scripts/6158/23710/GM_config%20CN.js -// @require https://update.greasyfork.org/scripts/438080/1714183/pvcep_rules.js +// @require https://update.greasyfork.org/scripts/438080/1738227/pvcep_rules.js // @require https://update.greasyfork.org/scripts/440698/1733533/pvcep_lang.js // @match *://*/* // @exclude http://www.toodledo.com/tasks/* From 7faf1e9246f26ba4369d26ab28454064dfa6713e Mon Sep 17 00:00:00 2001 From: hoothin-update Date: Tue, 20 Jan 2026 10:40:58 +0000 Subject: [PATCH 10/50] chore(Picviewer CE+): Auto-generate dist.user.js --- Picviewer CE+/dist.user.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Picviewer CE+/dist.user.js b/Picviewer CE+/dist.user.js index a5658d84035..e9ba3d4b72b 100644 --- a/Picviewer CE+/dist.user.js +++ b/Picviewer CE+/dist.user.js @@ -46,7 +46,7 @@ // @grant GM.notification // @grant unsafeWindow // @require https://hoothin.github.io/UserScripts/Picviewer%20CE%2B/GM_config%20CN.js?v=23710 -// @require https://hoothin.github.io/UserScripts/Picviewer%20CE%2B/pvcep_rules.js?v=1714183 +// @require https://hoothin.github.io/UserScripts/Picviewer%20CE%2B/pvcep_rules.js?v=1738227 // @require https://hoothin.github.io/UserScripts/Picviewer%20CE%2B/pvcep_lang.js?v=1733533 // @match *://*/* // @exclude http://www.toodledo.com/tasks/* From 3a228321e99057fd147d02084735701c4031aef5 Mon Sep 17 00:00:00 2001 From: hoothin Date: Fri, 23 Jan 2026 10:15:14 +0900 Subject: [PATCH 11/50] Update pvcep_lang.js --- Picviewer CE+/pvcep_lang.js | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/Picviewer CE+/pvcep_lang.js b/Picviewer CE+/pvcep_lang.js index 113b1cfa052..b65c8122ea3 100644 --- a/Picviewer CE+/pvcep_lang.js +++ b/Picviewer CE+/pvcep_lang.js @@ -117,6 +117,8 @@ const langData = [ config: "Settings", openConfig: "Open Settings", ruleRequest: "Rule Request", + disableKeyForHost: "Disable shortcuts", + restoreKeyForHost: "Restore shortcuts", closeGallery: "Close Gallery", returnToGallery: "Back to the Gallery", picInfo: "Click to change", @@ -390,6 +392,8 @@ const langData = [ config: "%D8%A7%D9%84%D8%A5%D8%B9%D8%AF%D8%A7%D8%AF%D8%A7%D8%AA", openConfig: "%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", ruleRequest: "%D8%B7%D9%84%D8%A8%20%D8%A7%D9%84%D9%82%D9%88%D8%A7%D8%B9%D8%AF", + disableKeyForHost: "Disable shortcuts", + restoreKeyForHost: "Restore shortcuts", closeGallery: "%D8%A5%D8%BA%D9%84%D8%A7%D9%82%20%D8%A7%D9%84%D9%85%D8%B9%D8%B1%D8%B6", returnToGallery: "%D8%A7%D9%84%D8%B9%D9%88%D8%AF%D8%A9%20%D8%A5%D9%84%D9%89%20%D8%A7%D9%84%D9%85%D8%B9%D8%B1%D8%B6", picInfo: "%D8%A7%D9%86%D9%82%D8%B1%20%D9%84%D8%AA%D8%BA%D9%8A%D9%8A%D8%B1", @@ -661,6 +665,8 @@ const langData = [ config: "设置", openConfig: "打开设置", ruleRequest: "适配请求", + disableKeyForHost: "Disable shortcuts", + restoreKeyForHost: "Restore shortcuts", closeGallery: "关闭库", returnToGallery: "回到库", picInfo: "点击修改", @@ -932,6 +938,8 @@ const langData = [ config: "設置", openConfig: "打開設置", ruleRequest: "適配請求", + disableKeyForHost: "Disable shortcuts", + restoreKeyForHost: "Restore shortcuts", closeGallery: "關閉庫", returnToGallery: "回到庫", picInfo: "點擊修改", @@ -1204,6 +1212,8 @@ const langData = [ config: "Configurações", openConfig: "Abrir configurações", ruleRequest: "Solicitar regra", + disableKeyForHost: "Disable shortcuts", + restoreKeyForHost: "Restore shortcuts", closeGallery: "Fechar galeria", returnToGallery: "Voltar para a Galeria", picInfo: "Clique para editar", @@ -1476,6 +1486,8 @@ const langData = [ config: "Configurações", openConfig: "Configurações", ruleRequest: "Pedido de regra", + disableKeyForHost: "Disable shortcuts", + restoreKeyForHost: "Restore shortcuts", closeGallery: "Sair da Galeria", returnToGallery: "Voltar para a Galeria", picInfo: "Clique para alterar", @@ -1748,6 +1760,8 @@ const langData = [ config: "Параметры", openConfig: "Открыть параметры", ruleRequest: "Запрос правил", + disableKeyForHost: "Disable shortcuts", + restoreKeyForHost: "Restore shortcuts", closeGallery: "Закрыть галерею", returnToGallery: "Вернуться в галерею", picInfo: "Нажмите, чтобы изменить", @@ -2020,6 +2034,8 @@ const langData = [ config: "Ayarlar", openConfig: "Ayarları Açın", ruleRequest: "Kural Talebi", + disableKeyForHost: "Disable shortcuts", + restoreKeyForHost: "Restore shortcuts", closeGallery: "Galeriyi kapatın", returnToGallery: "Galeriye geri dönün", picInfo: "Değiştirmek için tıklayın", @@ -2291,6 +2307,8 @@ const langData = [ config: "設定", openConfig: "設定を開く", ruleRequest: "ルール要求", + disableKeyForHost: "Disable shortcuts", + restoreKeyForHost: "Restore shortcuts", closeGallery: "ギャラリーを閉じる", returnToGallery: "ギャラリーに戻る", picInfo: "クリックして変更", @@ -2563,6 +2581,8 @@ const langData = [ config: "Налаштування", openConfig: "Відкрити налаштування", ruleRequest: "Правило Запит", + disableKeyForHost: "Disable shortcuts", + restoreKeyForHost: "Restore shortcuts", closeGallery: "Закрити галерею", returnToGallery: "Повернутись у галерею", picInfo: "Натисніть, щоб змінити", From 14c3308d019091a52aab926a61f9c9d26996d975 Mon Sep 17 00:00:00 2001 From: hoothin Date: Fri, 23 Jan 2026 10:28:18 +0900 Subject: [PATCH 12/50] Update pvcep_lang.js --- Picviewer CE+/pvcep_lang.js | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/Picviewer CE+/pvcep_lang.js b/Picviewer CE+/pvcep_lang.js index b65c8122ea3..2bda9d64459 100644 --- a/Picviewer CE+/pvcep_lang.js +++ b/Picviewer CE+/pvcep_lang.js @@ -392,8 +392,8 @@ const langData = [ config: "%D8%A7%D9%84%D8%A5%D8%B9%D8%AF%D8%A7%D8%AF%D8%A7%D8%AA", openConfig: "%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", ruleRequest: "%D8%B7%D9%84%D8%A8%20%D8%A7%D9%84%D9%82%D9%88%D8%A7%D8%B9%D8%AF", - disableKeyForHost: "Disable shortcuts", - restoreKeyForHost: "Restore shortcuts", + disableKeyForHost: "%D8%AA%D8%B9%D8%B7%D9%8A%D9%84%20%D8%A7%D9%84%D8%A7%D8%AE%D8%AA%D8%B5%D8%A7%D8%B1%D8%A7%D8%AA", + restoreKeyForHost: "%D8%A7%D8%B3%D8%AA%D8%B9%D8%A7%D8%AF%D8%A9%20%D8%A7%D9%84%D8%A7%D8%AE%D8%AA%D8%B5%D8%A7%D8%B1%D8%A7%D8%AA", closeGallery: "%D8%A5%D8%BA%D9%84%D8%A7%D9%82%20%D8%A7%D9%84%D9%85%D8%B9%D8%B1%D8%B6", returnToGallery: "%D8%A7%D9%84%D8%B9%D9%88%D8%AF%D8%A9%20%D8%A5%D9%84%D9%89%20%D8%A7%D9%84%D9%85%D8%B9%D8%B1%D8%B6", picInfo: "%D8%A7%D9%86%D9%82%D8%B1%20%D9%84%D8%AA%D8%BA%D9%8A%D9%8A%D8%B1", @@ -665,8 +665,8 @@ const langData = [ config: "设置", openConfig: "打开设置", ruleRequest: "适配请求", - disableKeyForHost: "Disable shortcuts", - restoreKeyForHost: "Restore shortcuts", + disableKeyForHost: "禁用快捷键", + restoreKeyForHost: "恢复快捷键", closeGallery: "关闭库", returnToGallery: "回到库", picInfo: "点击修改", @@ -938,8 +938,8 @@ const langData = [ config: "設置", openConfig: "打開設置", ruleRequest: "適配請求", - disableKeyForHost: "Disable shortcuts", - restoreKeyForHost: "Restore shortcuts", + disableKeyForHost: "停用快速鍵", + restoreKeyForHost: "恢復快速鍵", closeGallery: "關閉庫", returnToGallery: "回到庫", picInfo: "點擊修改", @@ -1212,8 +1212,8 @@ const langData = [ config: "Configurações", openConfig: "Abrir configurações", ruleRequest: "Solicitar regra", - disableKeyForHost: "Disable shortcuts", - restoreKeyForHost: "Restore shortcuts", + disableKeyForHost: "Desativar atalhos", + restoreKeyForHost: "Restaurar atalhos", closeGallery: "Fechar galeria", returnToGallery: "Voltar para a Galeria", picInfo: "Clique para editar", @@ -1486,8 +1486,8 @@ const langData = [ config: "Configurações", openConfig: "Configurações", ruleRequest: "Pedido de regra", - disableKeyForHost: "Disable shortcuts", - restoreKeyForHost: "Restore shortcuts", + disableKeyForHost: "Desativar atalhos", + restoreKeyForHost: "Restaurar atalhos", closeGallery: "Sair da Galeria", returnToGallery: "Voltar para a Galeria", picInfo: "Clique para alterar", @@ -1760,8 +1760,8 @@ const langData = [ config: "Параметры", openConfig: "Открыть параметры", ruleRequest: "Запрос правил", - disableKeyForHost: "Disable shortcuts", - restoreKeyForHost: "Restore shortcuts", + disableKeyForHost: "Отключить сочетания клавиш", + restoreKeyForHost: "Восстановить сочетания клавиш", closeGallery: "Закрыть галерею", returnToGallery: "Вернуться в галерею", picInfo: "Нажмите, чтобы изменить", @@ -2034,8 +2034,8 @@ const langData = [ config: "Ayarlar", openConfig: "Ayarları Açın", ruleRequest: "Kural Talebi", - disableKeyForHost: "Disable shortcuts", - restoreKeyForHost: "Restore shortcuts", + disableKeyForHost: "Kısayolları devre dışı bırak", + restoreKeyForHost: "Kısayolları geri yükle", closeGallery: "Galeriyi kapatın", returnToGallery: "Galeriye geri dönün", picInfo: "Değiştirmek için tıklayın", @@ -2307,8 +2307,8 @@ const langData = [ config: "設定", openConfig: "設定を開く", ruleRequest: "ルール要求", - disableKeyForHost: "Disable shortcuts", - restoreKeyForHost: "Restore shortcuts", + disableKeyForHost: "ショートカットを無効にする", + restoreKeyForHost: "ショートカットを元に戻す", closeGallery: "ギャラリーを閉じる", returnToGallery: "ギャラリーに戻る", picInfo: "クリックして変更", @@ -2581,8 +2581,8 @@ const langData = [ config: "Налаштування", openConfig: "Відкрити налаштування", ruleRequest: "Правило Запит", - disableKeyForHost: "Disable shortcuts", - restoreKeyForHost: "Restore shortcuts", + disableKeyForHost: "Вимкнути комбінації клавіш", + restoreKeyForHost: "Відновити комбінації клавіш", closeGallery: "Закрити галерею", returnToGallery: "Повернутись у галерею", picInfo: "Натисніть, щоб змінити", From be1e07b35b945c23cba0c7b4b2827a64c081d9e2 Mon Sep 17 00:00:00 2001 From: hoothin Date: Fri, 23 Jan 2026 10:29:59 +0900 Subject: [PATCH 13/50] Update Picviewer CE+.user.js --- Picviewer CE+/Picviewer CE+.user.js | 76 ++++++++++++++++++++++++----- 1 file changed, 64 insertions(+), 12 deletions(-) diff --git a/Picviewer CE+/Picviewer CE+.user.js b/Picviewer CE+/Picviewer CE+.user.js index d78cf8b0efd..dc08df12a53 100644 --- a/Picviewer CE+/Picviewer CE+.user.js +++ b/Picviewer CE+/Picviewer CE+.user.js @@ -12,7 +12,7 @@ // @description:ja 画像を強力に閲覧できるツール。ポップアップ表示、拡大・縮小、回転、一括保存などの機能を自動で実行できます // @description:pt-BR Poderosa ferramenta de visualização de imagens on-line, que pode pop-up/dimensionar/girar/salvar em lote imagens automaticamente // @description:ru Мощный онлайн-инструмент для просмотра изображений, который может автоматически отображать/масштабировать/вращать/пакетно сохранять изображения -// @version 2026.1.17.1 +// @version 2026.1.23.1 // @icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAAV1BMVEUAAAD////29vbKysoqKioiIiKysrKhoaGTk5N9fX3z8/Pv7+/r6+vk5OTb29vOzs6Ojo5UVFQzMzMZGRkREREMDAy4uLisrKylpaV4eHhkZGRPT08/Pz/IfxjQAAAAgklEQVQoz53RRw7DIBBAUb5pxr2m3/+ckfDImwyJlL9DDzQgDIUMRu1vWOxTBdeM+onApENF0qHjpkOk2VTwLVEF40Kbfj1wK8AVu2pQA1aBBYDHJ1wy9Cf4cXD5chzNAvsAnc8TjoLAhIzsBao9w1rlVTIvkOYMd9nm6xPi168t9AYkbANdajpjcwAAAABJRU5ErkJggg== // @namespace https://github.com/hoothin/UserScripts // @homepage https://pv.hoothin.com/ @@ -47,7 +47,7 @@ // @grant unsafeWindow // @require https://update.greasyfork.org/scripts/6158/23710/GM_config%20CN.js // @require https://update.greasyfork.org/scripts/438080/1738227/pvcep_rules.js -// @require https://update.greasyfork.org/scripts/440698/1733533/pvcep_lang.js +// @require https://update.greasyfork.org/scripts/440698/1740314/pvcep_lang.js // @match *://*/* // @exclude http://www.toodledo.com/tasks/* // @exclude http*://maps.google.com*/* @@ -28254,6 +28254,30 @@ ImgOps | https://imgops.com/#b#`; document.head.removeChild(hideIconStyle); } }); + function buildDisableKeyPattern() { + let originPattern = location.origin.replace(/^https?/, "https?").replace(/\./g, "\\."); + let pathBase = location.pathname.replace(/[^\/]*$/, ""); + return "^" + originPattern + pathBase; + } + function isDisableKeyPatternMatched() { + let pattern = buildDisableKeyPattern(); + let list = normalizeDisableKeySites(prefs.floatBar.disableKeySites); + return list.indexOf(pattern) !== -1; + } + _GM_registerMenuCommand( + isDisableKeyPatternMatched() ? i18n("restoreKeyForHost") : i18n("disableKeyForHost"), + () => { + let pattern = buildDisableKeyPattern(); + let list = normalizeDisableKeySites(prefs.floatBar.disableKeySites); + if (list.indexOf(pattern) === -1) { + list.unshift(pattern); + saveDisableKeySites(list); + } else { + let nextList = list.filter(item => item !== pattern); + saveDisableKeySites(nextList); + } + } + ); _GM_registerMenuCommand(i18n("ruleRequest"), () => { _GM_openInTab("https://github.com/hoothin/UserScripts/issues/new?labels=Picviewer%20CE%2B&template=custom-rule-request.md&title=Request%20Picviewer%20CE%2B%20support%20for%20" + location.hostname, {active:true}); }); @@ -28346,19 +28370,47 @@ ImgOps | https://imgops.com/#b#`; } // 注册按键 - let disableKey = false; - if (prefs.floatBar.disableKeySites) { - let sitesArr = prefs.floatBar.disableKeySites.split("\n"); - for(let s = 0; s < sitesArr.length; s++) { - let siteReg = sitesArr[s].trim(); - if (new RegExp(siteReg).test(_URL)) { - disableKey = true; - break; + function normalizeDisableKeySites(value) { + if (!value) return []; + return value.split("\n").map(s => s.trim()).filter(Boolean); + } + + function isKeyDisabledForUrl(url, host, list) { + for (let i = 0; i < list.length; i++) { + let siteReg = list[i]; + try { + let reg = new RegExp(siteReg); + if (reg.test(url) || reg.test(host)) return true; + } catch (e) { } } + return false; } - if (!disableKey) { - document.addEventListener('keydown', keydown, true); + + let keydownBound = false; + function updateKeydownListener() { + let list = normalizeDisableKeySites(prefs.floatBar.disableKeySites); + let disableKey = isKeyDisabledForUrl(_URL, location.hostname, list); + if (!disableKey && !keydownBound) { + document.addEventListener('keydown', keydown, true); + keydownBound = true; + } else if (disableKey && keydownBound) { + document.removeEventListener('keydown', keydown, true); + keydownBound = false; + } + } + updateKeydownListener(); + + function saveDisableKeySites(list) { + let value = list.join("\n"); + prefs.floatBar.disableKeySites = value; + if (GM_config && GM_config.set) { + GM_config.set('floatBar.disableKeySites', value); + let field = GM_config.fields && GM_config.fields['floatBar.disableKeySites']; + if (field && field.node) field.node.value = value; + GM_config.save(); + } + updateKeydownListener(); } let canImport = false; From 95c543b6ccd8659d25c9c92bfdd66f6714b74186 Mon Sep 17 00:00:00 2001 From: hoothin-update Date: Fri, 23 Jan 2026 01:30:08 +0000 Subject: [PATCH 14/50] chore(Picviewer CE+): Auto-generate dist.user.js --- Picviewer CE+/dist.user.js | 76 ++++++++++++++++++++++++++++++++------ 1 file changed, 64 insertions(+), 12 deletions(-) diff --git a/Picviewer CE+/dist.user.js b/Picviewer CE+/dist.user.js index e9ba3d4b72b..856071eb35f 100644 --- a/Picviewer CE+/dist.user.js +++ b/Picviewer CE+/dist.user.js @@ -12,7 +12,7 @@ // @description:ja 画像を強力に閲覧できるツール。ポップアップ表示、拡大・縮小、回転、一括保存などの機能を自動で実行できます // @description:pt-BR Poderosa ferramenta de visualização de imagens on-line, que pode pop-up/dimensionar/girar/salvar em lote imagens automaticamente // @description:ru Мощный онлайн-инструмент для просмотра изображений, который может автоматически отображать/масштабировать/вращать/пакетно сохранять изображения -// @version 2026.1.17.1 +// @version 2026.1.23.1 // @icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAAV1BMVEUAAAD////29vbKysoqKioiIiKysrKhoaGTk5N9fX3z8/Pv7+/r6+vk5OTb29vOzs6Ojo5UVFQzMzMZGRkREREMDAy4uLisrKylpaV4eHhkZGRPT08/Pz/IfxjQAAAAgklEQVQoz53RRw7DIBBAUb5pxr2m3/+ckfDImwyJlL9DDzQgDIUMRu1vWOxTBdeM+onApENF0qHjpkOk2VTwLVEF40Kbfj1wK8AVu2pQA1aBBYDHJ1wy9Cf4cXD5chzNAvsAnc8TjoLAhIzsBao9w1rlVTIvkOYMd9nm6xPi168t9AYkbANdajpjcwAAAABJRU5ErkJggg== // @namespace https://github.com/hoothin/UserScripts // @homepage https://pv.hoothin.com/ @@ -47,7 +47,7 @@ // @grant unsafeWindow // @require https://hoothin.github.io/UserScripts/Picviewer%20CE%2B/GM_config%20CN.js?v=23710 // @require https://hoothin.github.io/UserScripts/Picviewer%20CE%2B/pvcep_rules.js?v=1738227 -// @require https://hoothin.github.io/UserScripts/Picviewer%20CE%2B/pvcep_lang.js?v=1733533 +// @require https://hoothin.github.io/UserScripts/Picviewer%20CE%2B/pvcep_lang.js?v=1740314 // @match *://*/* // @exclude http://www.toodledo.com/tasks/* // @exclude http*://maps.google.com*/* @@ -28254,6 +28254,30 @@ ImgOps | https://imgops.com/#b#`; document.head.removeChild(hideIconStyle); } }); + function buildDisableKeyPattern() { + let originPattern = location.origin.replace(/^https?/, "https?").replace(/\./g, "\\."); + let pathBase = location.pathname.replace(/[^\/]*$/, ""); + return "^" + originPattern + pathBase; + } + function isDisableKeyPatternMatched() { + let pattern = buildDisableKeyPattern(); + let list = normalizeDisableKeySites(prefs.floatBar.disableKeySites); + return list.indexOf(pattern) !== -1; + } + _GM_registerMenuCommand( + isDisableKeyPatternMatched() ? i18n("restoreKeyForHost") : i18n("disableKeyForHost"), + () => { + let pattern = buildDisableKeyPattern(); + let list = normalizeDisableKeySites(prefs.floatBar.disableKeySites); + if (list.indexOf(pattern) === -1) { + list.unshift(pattern); + saveDisableKeySites(list); + } else { + let nextList = list.filter(item => item !== pattern); + saveDisableKeySites(nextList); + } + } + ); _GM_registerMenuCommand(i18n("ruleRequest"), () => { _GM_openInTab("https://github.com/hoothin/UserScripts/issues/new?labels=Picviewer%20CE%2B&template=custom-rule-request.md&title=Request%20Picviewer%20CE%2B%20support%20for%20" + location.hostname, {active:true}); }); @@ -28346,19 +28370,47 @@ ImgOps | https://imgops.com/#b#`; } // 注册按键 - let disableKey = false; - if (prefs.floatBar.disableKeySites) { - let sitesArr = prefs.floatBar.disableKeySites.split("\n"); - for(let s = 0; s < sitesArr.length; s++) { - let siteReg = sitesArr[s].trim(); - if (new RegExp(siteReg).test(_URL)) { - disableKey = true; - break; + function normalizeDisableKeySites(value) { + if (!value) return []; + return value.split("\n").map(s => s.trim()).filter(Boolean); + } + + function isKeyDisabledForUrl(url, host, list) { + for (let i = 0; i < list.length; i++) { + let siteReg = list[i]; + try { + let reg = new RegExp(siteReg); + if (reg.test(url) || reg.test(host)) return true; + } catch (e) { } } + return false; } - if (!disableKey) { - document.addEventListener('keydown', keydown, true); + + let keydownBound = false; + function updateKeydownListener() { + let list = normalizeDisableKeySites(prefs.floatBar.disableKeySites); + let disableKey = isKeyDisabledForUrl(_URL, location.hostname, list); + if (!disableKey && !keydownBound) { + document.addEventListener('keydown', keydown, true); + keydownBound = true; + } else if (disableKey && keydownBound) { + document.removeEventListener('keydown', keydown, true); + keydownBound = false; + } + } + updateKeydownListener(); + + function saveDisableKeySites(list) { + let value = list.join("\n"); + prefs.floatBar.disableKeySites = value; + if (GM_config && GM_config.set) { + GM_config.set('floatBar.disableKeySites', value); + let field = GM_config.fields && GM_config.fields['floatBar.disableKeySites']; + if (field && field.node) field.node.value = value; + GM_config.save(); + } + updateKeydownListener(); } let canImport = false; From 864431639548fd3f77a85a669e4eae0a5798a57c Mon Sep 17 00:00:00 2001 From: hoothin Date: Sat, 31 Jan 2026 18:24:23 +0900 Subject: [PATCH 15/50] Update Picviewer CE+.user.js --- Picviewer CE+/Picviewer CE+.user.js | 213 ++++++++++++++++++++-------- 1 file changed, 150 insertions(+), 63 deletions(-) diff --git a/Picviewer CE+/Picviewer CE+.user.js b/Picviewer CE+/Picviewer CE+.user.js index dc08df12a53..1cb566a73bd 100644 --- a/Picviewer CE+/Picviewer CE+.user.js +++ b/Picviewer CE+/Picviewer CE+.user.js @@ -11925,7 +11925,7 @@ var floatBar; 'use strict'; //var siteInfo = [{}]; - var debug; + var debug = console.log.bind(console); var lang; function initLang(){ let customLang=storage.getItem("customLang")||'auto'; @@ -12744,24 +12744,6 @@ ImgOps | https://imgops.com/#b#`; return; } catch (e) { } - - const existingPolicies = new Set(unsafeWindow.trustedTypes.getPolicyNames()); - for (const name of allowedNames) { - if (name === '*' || existingPolicies.has(name)) { - continue; - } - - try { - escapeHTMLPolicy = unsafeWindow.trustedTypes.createPolicy(name, { - createHTML: (string, sink) => string, - createScriptURL: string => string, - createScript: string => string - }); - return; - } catch (e) { - debug(`create '${name}' failed, trying next...`); - } - } debug("Could not create any trusted types policy."); } @@ -12771,7 +12753,107 @@ ImgOps | https://imgops.com/#b#`; return doc.body || doc.querySelector('body') || doc; } function createHTML(html){ - return escapeHTMLPolicy?escapeHTMLPolicy.createHTML(html):html; + const fragment = document.createDocumentFragment(); + if (html === null || html === undefined || html === '') return fragment; + parseHTMLToFragment(String(html), fragment, document); + return fragment; + } + 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 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][^>]*>|[^<]+/g; + 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][^>]*>|[^<]+/g; + 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][^>]*>|[^<]+/g; + 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 (metaResult.ttDirectiveFound) { - combinedTtDirectiveFound = true; + if (token.indexOf('|<\/?[a-zA-Z][^>]*>|[^<]+/g; + const tokenRe = /|]*>|<\/?[a-zA-Z][^>]*>|[^<]+/gi; let match; while ((match = tokenRe.exec(html))) { const token = match[0]; @@ -4626,6 +4639,9 @@ if (token.indexOf('|<\/?[a-zA-Z][^>]*>|[^<]+/g; + const tokenRe = /|]*>|<\/?[a-zA-Z][^>]*>|[^<]+/gi; let match; while ((match = tokenRe.exec(html))) { const token = match[0]; @@ -12828,6 +12841,9 @@ ImgOps | https://imgops.com/#b#`; if (token.indexOf('|<\/?[a-zA-Z][^>]*>|[^<]+/g; + const tokenRe = /|]*>|<\/?[a-zA-Z][^>]*>|[^<]+/gi; let match; while ((match = tokenRe.exec(html))) { const token = match[0]; @@ -12828,6 +12841,9 @@ ImgOps | https://imgops.com/#b#`; if (token.indexOf('