1212// @description:ja 画像を強力に閲覧できるツール。ポップアップ表示、拡大・縮小、回転、一括保存などの機能を自動で実行できます
1313// @description:pt-BR Poderosa ferramenta de visualização de imagens on-line, que pode pop-up/dimensionar/girar/salvar em lote imagens automaticamente
1414// @description:ru Мощный онлайн-инструмент для просмотра изображений, который может автоматически отображать/масштабировать/вращать/пакетно сохранять изображения
15- // @version 2026.2.2 .1
15+ // @version 2026.2.6 .1
1616// @icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAAV1BMVEUAAAD////29vbKysoqKioiIiKysrKhoaGTk5N9fX3z8/Pv7+/r6+vk5OTb29vOzs6Ojo5UVFQzMzMZGRkREREMDAy4uLisrKylpaV4eHhkZGRPT08/Pz/IfxjQAAAAgklEQVQoz53RRw7DIBBAUb5pxr2m3/+ckfDImwyJlL9DDzQgDIUMRu1vWOxTBdeM+onApENF0qHjpkOk2VTwLVEF40Kbfj1wK8AVu2pQA1aBBYDHJ1wy9Cf4cXD5chzNAvsAnc8TjoLAhIzsBao9w1rlVTIvkOYMd9nm6xPi168t9AYkbANdajpjcwAAAABJRU5ErkJggg==
1717// @namespace https://github.com/hoothin/UserScripts
1818// @homepage https://pv.hoothin.com/
@@ -12758,13 +12758,17 @@ ImgOps | https://imgops.com/#b#`;
1275812758 createScriptURL: string => string,
1275912759 createScript: string => string
1276012760 });
12761+ escapeHTMLCreator = escapeHTMLPolicy.createHTML;
1276112762 return;
1276212763 } catch (e) {
1276312764 }
1276412765 debug("Could not create any trusted types policy.");
1276512766 }
1276612767
1276712768 let escapeHTMLPolicy = null;
12769+ let escapeHTMLCreator = null;
12770+ let canDirectSetHTML = true;
12771+ let canPolicySetHTML = true;
1276812772
1276912773 function getBody(doc){
1277012774 return doc.body || doc.querySelector('body') || doc;
@@ -12792,6 +12796,15 @@ ImgOps | https://imgops.com/#b#`;
1279212796 track: true,
1279312797 wbr: true
1279412798 };
12799+ const RAW_TEXT_TAGS = {
12800+ script: true,
12801+ style: true,
12802+ textarea: true,
12803+ title: true,
12804+ xmp: true,
12805+ plaintext: true,
12806+ noscript: true
12807+ };
1279512808 const HTML_ENTITIES = {
1279612809 amp: '&',
1279712810 lt: '<',
@@ -12816,7 +12829,7 @@ ImgOps | https://imgops.com/#b#`;
1281612829 }
1281712830 function parseHTMLToFragment(html, fragment, doc){
1281812831 const stack = [fragment];
12819- const tokenRe = /<!--[\s\S]*?-->|<\/?[a-zA-Z][^>]*>|[^<]+/g ;
12832+ const tokenRe = /<!--[\s\S]*?-->|<!doctype[^>]*>|< \/?[a-zA-Z][^>]*>|[^<]+/gi ;
1282012833 let match;
1282112834 while ((match = tokenRe.exec(html))) {
1282212835 const token = match[0];
@@ -12828,6 +12841,9 @@ ImgOps | https://imgops.com/#b#`;
1282812841 if (token.indexOf('<!--') === 0) {
1282912842 continue;
1283012843 }
12844+ if (/^<!doctype/i.test(token)) {
12845+ continue;
12846+ }
1283112847 if (token[1] === '/') {
1283212848 const tag = token.slice(2, -1).trim().toLowerCase();
1283312849 for (let i = stack.length - 1; i > 0; i--) {
@@ -12861,23 +12877,67 @@ ImgOps | https://imgops.com/#b#`;
1286112877 const selfClosing = token.endsWith('/>');
1286212878 if (!selfClosing && !VOID_TAGS[tagName]) {
1286312879 stack.push(el);
12880+ if (RAW_TEXT_TAGS[tagName]) {
12881+ const closeRe = new RegExp('<\\/\\s*' + tagName + '\\s*>', 'ig');
12882+ closeRe.lastIndex = tokenRe.lastIndex;
12883+ const closeMatch = closeRe.exec(html);
12884+ if (closeMatch) {
12885+ const rawText = html.slice(tokenRe.lastIndex, closeMatch.index);
12886+ if (rawText) el.appendChild(doc.createTextNode(rawText));
12887+ tokenRe.lastIndex = closeMatch.index + closeMatch[0].length;
12888+ stack.pop();
12889+ }
12890+ }
1286412891 }
1286512892 }
1286612893 }
12894+ function createScriptURL(html){
12895+ return escapeHTMLPolicy?escapeHTMLPolicy.createScriptURL(html):html;
12896+ }
12897+ function createScript(html){
12898+ return escapeHTMLPolicy?escapeHTMLPolicy.createScript(html):html;
12899+ }
12900+ function tryDirectSetHTML(target, htmlStr){
12901+ if (!canDirectSetHTML) return false;
12902+ try {
12903+ target.innerHTML = htmlStr;
12904+ return true;
12905+ } catch (e) {
12906+ canDirectSetHTML = false;
12907+ return false;
12908+ }
12909+ }
12910+ function ensureEscapeHTMLCreator(){
12911+ if (!canPolicySetHTML) return null;
12912+ if (escapeHTMLCreator) return escapeHTMLCreator;
12913+ if (escapeHTMLPolicy && typeof escapeHTMLPolicy.createHTML === "function") {
12914+ escapeHTMLCreator = escapeHTMLPolicy.createHTML;
12915+ return escapeHTMLCreator;
12916+ }
12917+ return null;
12918+ }
12919+ function tryPolicySetHTML(target, htmlStr){
12920+ if (!canPolicySetHTML) return false;
12921+ const creator = ensureEscapeHTMLCreator();
12922+ if (!creator) return false;
12923+ try {
12924+ target.innerHTML = creator(htmlStr);
12925+ return true;
12926+ } catch (e) {
12927+ canPolicySetHTML = false;
12928+ return false;
12929+ }
12930+ }
1286712931 function setHTML(target, html){
1286812932 if (!target) return;
12869- const fragment = createHTML(html);
12933+ const htmlStr = html === null || html === undefined ? '' : String(html);
12934+ if (tryDirectSetHTML(target, htmlStr) || tryPolicySetHTML(target, htmlStr)) return;
12935+ const fragment = createHTML(htmlStr);
1287012936 while (target.firstChild) {
1287112937 target.removeChild(target.firstChild);
1287212938 }
1287312939 target.appendChild(fragment);
1287412940 }
12875- function createScriptURL(html){
12876- return escapeHTMLPolicy?escapeHTMLPolicy.createScriptURL(html):html;
12877- }
12878- function createScript(html){
12879- return escapeHTMLPolicy?escapeHTMLPolicy.createScript(html):html;
12880- }
1288112941 async function init(topObject,window,document,arrayFn,envir,storage,unsafeWindow){
1288212942 await createPolicy();
1288312943 // 默认设置,请到设置界面修改
0 commit comments