├── EhSyringe Extension ├── Info.plist ├── Resources │ ├── _locales │ │ └── en │ │ │ └── messages.json │ ├── assets │ │ ├── logo-padding.svg │ │ ├── logo.svg │ │ ├── logo128.png │ │ ├── logo16.png │ │ ├── logo32.png │ │ ├── logo48.png │ │ ├── logo64.png │ │ └── popup.html │ ├── manifest.json │ ├── script │ │ ├── background.js │ │ ├── page.js │ │ ├── popup.js │ │ ├── vendor.js │ │ └── vendor.js.LICENSE.txt │ └── userscript │ │ ├── EhDetailPageTagColor.user.js │ │ ├── EhReadStatus.user.js │ │ └── EhTagTranslatedJump.user.js └── SafariWebExtensionHandler.swift ├── EhSyringe.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist └── xcuserdata │ └── zhaoxin.xcuserdatad │ └── xcschemes │ └── xcschememanagement.plist ├── EhSyringe ├── AppDelegate.swift ├── Assets.xcassets │ ├── AccentColor.colorset │ │ └── Contents.json │ ├── AppIcon.appiconset │ │ └── Contents.json │ ├── Contents.json │ └── LargeIcon.imageset │ │ └── Contents.json ├── Base.lproj │ ├── LaunchScreen.storyboard │ ├── Main.html │ └── Main.storyboard ├── Info.plist ├── Resources │ ├── Icon.png │ └── Style.css ├── SceneDelegate.swift └── ViewController.swift └── README.md /EhSyringe Extension/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NSExtension 6 | 7 | NSExtensionPointIdentifier 8 | com.apple.Safari.web-extension 9 | NSExtensionPrincipalClass 10 | $(PRODUCT_MODULE_NAME).SafariWebExtensionHandler 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /EhSyringe Extension/Resources/_locales/en/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "extension_name": { 3 | "message": "EhSyringe Extension", 4 | "description": "The display name for the extension." 5 | }, 6 | "extension_description": { 7 | "message": "This is EhSyringe Extension. You should tell us what your extension does here.", 8 | "description": "Description of what the extension does." 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /EhSyringe Extension/Resources/assets/logo-padding.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | logo 5 | Created with Sketch. 6 | 22 | -------------------------------------------------------------------------------- /EhSyringe Extension/Resources/assets/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | logo 5 | Created with Sketch. 6 | 22 | -------------------------------------------------------------------------------- /EhSyringe Extension/Resources/assets/logo128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EhTagTranslation/EhSyringeSafariExtensionApp/d09f6e1875202fe80d94c8c1d7897da9e42f5b4f/EhSyringe Extension/Resources/assets/logo128.png -------------------------------------------------------------------------------- /EhSyringe Extension/Resources/assets/logo16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EhTagTranslation/EhSyringeSafariExtensionApp/d09f6e1875202fe80d94c8c1d7897da9e42f5b4f/EhSyringe Extension/Resources/assets/logo16.png -------------------------------------------------------------------------------- /EhSyringe Extension/Resources/assets/logo32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EhTagTranslation/EhSyringeSafariExtensionApp/d09f6e1875202fe80d94c8c1d7897da9e42f5b4f/EhSyringe Extension/Resources/assets/logo32.png -------------------------------------------------------------------------------- /EhSyringe Extension/Resources/assets/logo48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EhTagTranslation/EhSyringeSafariExtensionApp/d09f6e1875202fe80d94c8c1d7897da9e42f5b4f/EhSyringe Extension/Resources/assets/logo48.png -------------------------------------------------------------------------------- /EhSyringe Extension/Resources/assets/logo64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EhTagTranslation/EhSyringeSafariExtensionApp/d09f6e1875202fe80d94c8c1d7897da9e42f5b4f/EhSyringe Extension/Resources/assets/logo64.png -------------------------------------------------------------------------------- /EhSyringe Extension/Resources/assets/popup.html: -------------------------------------------------------------------------------- 1 | EhSyringe -------------------------------------------------------------------------------- /EhSyringe Extension/Resources/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "EhSyringe", 3 | "short_name": "EhSyringe", 4 | "description": "E 站注射器,将中文翻译注入到 E 站体内。包含全站 UI 翻译和超过 10000 条标签翻译,标签数据库持续更新中。", 5 | "author": "EhTagTranslation", 6 | "version": "2.4.0", 7 | "homepage_url": "https://github.com/EhTagTranslation/EhSyringe", 8 | "manifest_version": 2, 9 | "applications": { 10 | "gecko": { 11 | "id": "{759d5566-1dce-41ae-bae9-00dd5172c422}", 12 | "strict_min_version": "57.0" 13 | } 14 | }, 15 | "icons": { 16 | "16": "assets/logo16.png", 17 | "32": "assets/logo32.png", 18 | "48": "assets/logo48.png", 19 | "128": "assets/logo128.png" 20 | }, 21 | "omnibox": { 22 | "keyword": "ex" 23 | }, 24 | "background": { 25 | "scripts": [ 26 | "script/vendor.js", 27 | "script/background.js" 28 | ], 29 | "persistent": false 30 | }, 31 | "browser_action": { 32 | "default_icon": { 33 | "16": "assets/logo16.png", 34 | "32": "assets/logo32.png", 35 | "48": "assets/logo48.png", 36 | "128": "assets/logo128.png" 37 | }, 38 | "default_popup": "assets/popup.html" 39 | }, 40 | "content_scripts": [ 41 | { 42 | "matches": [ 43 | "*://exhentai.org/*", 44 | "*://e-hentai.org/*", 45 | "*://*.exhentai.org/*", 46 | "*://*.e-hentai.org/*" 47 | ], 48 | "exclude_matches": [ 49 | "*://forums.e-hentai.org/*" 50 | ], 51 | "js": [ 52 | "script/vendor.js", 53 | "script/page.js", 54 | "userscript/EhDetailPageTagColor.user.js", 55 | "userscript/EhTagTranslatedJump.user.js", 56 | "userscript/EhReadStatus.user.js" 57 | ], 58 | "run_at": "document_start" 59 | } 60 | ], 61 | "permissions": [ 62 | "*://exhentai.org/*", 63 | "*://e-hentai.org/*", 64 | "*://*.exhentai.org/*", 65 | "*://*.e-hentai.org/*", 66 | "activeTab", 67 | "notifications", 68 | "storage", 69 | "contextMenus" 70 | ] 71 | } 72 | -------------------------------------------------------------------------------- /EhSyringe Extension/Resources/script/background.js: -------------------------------------------------------------------------------- 1 | !function(){"use strict";var t,e={5397:function(t,e,n){n(3541);var r=n(9809),a=n(2137),i=n(6610),s=n(5991),o=n(7757),c=n.n(o),u=n(655),h=n(2471),g=n(7743),l=n(314),p=n(4801);function f(t){browser.tabs.create({url:t})}function d(t){if(t.background&&chrome.browserAction.setBadgeBackgroundColor&&chrome.browserAction.setBadgeBackgroundColor({color:t.background}),null!=t.text)if(chrome.browserAction.setBadgeText)chrome.browserAction.setBadgeText({text:t.text});else if(chrome.browserAction.setTitle){var e=p.B.displayName,n=t.text?"".concat(e," (").concat(t.text,")"):e;chrome.browserAction.setTitle({title:n})}}var v=n(511),m=function(){function t(){(0,i.Z)(this,t)}return(0,s.Z)(t,[{key:"send",value:function(t){return function(t){browser.notifications.create({type:"basic",title:t.title,message:t.message,iconUrl:browser.runtime.getURL("assets/logo-padding.svg")}).then((function(e){var n=t.action;n&&browser.notifications.onClicked.addListener((function t(r){r===e&&(n(),browser.notifications.onClicked.removeListener(t))}))})).catch(console.error)}(t)}}]),t}();m=(0,u.gn)([(0,h.t)()],m);var b=function(){function t(){(0,i.Z)(this,t)}var e;return(0,s.Z)(t,[{key:"json",value:(e=(0,a.Z)(c().mark((function t(e){var n,r,a=arguments;return c().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return n=a.length>1&&void 0!==a[1]?a[1]:"GET",t.next=3,fetch(e,{method:n});case 3:return r=t.sent,t.next=6,r.json();case 6:return t.abrupt("return",t.sent);case 7:case"end":return t.stop()}}),t)}))),function(t){return e.apply(this,arguments)})},{key:"download",value:function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"GET",n=arguments.length>2?arguments[2]:void 0,r=arguments.length>3&&void 0!==arguments[3]?arguments[3]:"arraybuffer";return new Promise((function(a,i){var s=new XMLHttpRequest;s.open(e,t),s.responseType=r,s.onload=function(){s.status>=300?i(new Error("".concat(e," ").concat(t," ").concat(s.statusText," (").concat(s.status,")"))):s.response instanceof ArrayBuffer&&"arraybuffer"===r||"json"===r?a(s.response):i(new Error("数据无法解析"))},s.onerror=function(){i("加载失败")},n&&(s.onprogress=n),s.send()}))}}]),t}();b=(0,u.gn)([(0,r.t6)()],b);var w=function(){function t(e,n,r,a,s){var o=this;(0,i.Z)(this,t),this.logger=e,this.storage=n,this.messaging=r,this.notification=a,this.http=s,this.check().catch(e.error),r.on("check-extension",(function(){return o.check()}))}var e;return(0,s.Z)(t,[{key:"check",value:(e=(0,a.Z)(c().mark((function t(){var e,n,r,a,i;return c().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return t.next=2,this.storage.get("extensionCheck");case 2:if(e=t.sent,!(Date.now()-e<=864e5)){t.next=7;break}return this.logger.info("上次检查于 ".concat(new Date(e).toLocaleString(),",跳过")),t.abrupt("return",!1);case 7:return t.prev=7,t.next=10,this.http.json("https://api.github.com/repos/EhTagTranslation/EhSyringe/releases/latest");case 10:if(n=t.sent,r="v".concat(p.B.version),"string"==typeof(a=n.tag_name)&&a.startsWith("v")){t.next=17;break}throw i=new Error("响应格式错误"),Object.defineProperty(i,"response",n),i;case 17:return t.next=19,this.storage.set("extensionCheck",Date.now());case 19:if(this.logger.log("检查插件更新",{current:r,latest:a}),a!==r){t.next=22;break}return t.abrupt("return",!1);case 22:return this.notification.send({title:p.B.displayName,message:"发现新的版本 ".concat(a,",点击跳转到下载页面。"),action:function(){return f(n.html_url)}}),t.abrupt("return",!0);case 26:return t.prev=26,t.t0=t.catch(7),this.logger.error("检查插件更新失败",t.t0),t.abrupt("return",!1);case 30:case"end":return t.stop()}}),t,this,[[7,26]])}))),function(){return e.apply(this,arguments)})}]),t}();w=(0,u.gn)([(0,h.t)(),(0,u.w6)("design:paramtypes",[g.Y,l.K,v.s,m,b])],w);var k=n(6156);function y(t,e){var n="undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(!n){if(Array.isArray(t)||(n=function(t,e){if(t){if("string"==typeof t)return x(t,e);var n=Object.prototype.toString.call(t).slice(8,-1);return"Object"===n&&t.constructor&&(n=t.constructor.name),"Map"===n||"Set"===n?Array.from(t):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?x(t,e):void 0}}(t))||e&&t&&"number"==typeof t.length){n&&(t=n);var r=0,a=function(){};return{s:a,n:function(){return r>=t.length?{done:!0}:{done:!1,value:t[r++]}},e:function(t){throw t},f:a}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var i,s=!0,o=!1;return{s:function(){n=n.call(t)},n:function(){var t=n.next();return s=t.done,t},e:function(t){o=!0,i=t},f:function(){try{s||null==n.return||n.return()}finally{if(o)throw i}}}}function x(t,e){(null==e||e>t.length)&&(e=t.length);for(var n=0,r=new Array(e);n/gi.exec(t.body);if(!e)throw new Error("GitHub 发布数据无法解析,可能需要更新插件版本");try{var n=JSON.parse(e[1]).mirror;if("string"!=typeof n)throw new Error;return["https://cdn.jsdelivr.net/gh/EhTagTranslation/DatabaseReleases@".concat(n,"/db.html.json"),"https://gitcdn.xyz/cdn/EhTagTranslation/DatabaseReleases/".concat(n,"/db.html.json"),"https://rawcdn.githack.com/EhTagTranslation/DatabaseReleases/".concat(n,"/db.html.json"),"https://cdn.statically.io/gh/EhTagTranslation/DatabaseReleases/".concat(n,"/db.html.json")]}catch(t){throw new Error("GitHub 发布数据无法解析,可能需要更新插件版本")}}},{key:"getData",value:(e=(0,a.Z)(c().mark((function t(e,n){var r,a,i,s,o,u,h,g;return c().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:a=this.dataUrls(e),i=[],s=y(a),t.prev=3,s.s();case 5:if((o=s.n()).done){t.next=22;break}return u=o.value,t.prev=7,t.next=10,this.http.download(u,"GET",n,"json");case 10:if(h=t.sent,(null===(r=null==h?void 0:h.head)||void 0===r?void 0:r.sha)!==e.target_commitish||!(null==h?void 0:h.data)){t.next=14;break}return this.logger.log("从 ".concat(u," 下载成功")),t.abrupt("return",h);case 14:t.next=20;break;case 16:t.prev=16,t.t0=t.catch(7),i.push(t.t0),this.logger.warn("尝试从 ".concat(u," 下载失败"),t.t0);case 20:t.next=5;break;case 22:t.next=27;break;case 24:t.prev=24,t.t1=t.catch(3),s.e(t.t1);case 27:return t.prev=27,s.f(),t.finish(27);case 30:if(0!==i.length){t.next=32;break}throw new Error("没有获取到有效的文件");case 32:throw g=i[i.length-1],Object.defineProperty(g,"errors",{value:i,enumerable:!0}),g;case 35:case"end":return t.stop()}}),t,this,[[3,24,27,30],[7,16]])}))),function(t,n){return e.apply(this,arguments)})}]),t}();O=(0,u.gn)([(0,r.t6)(),(0,u.w6)("design:paramtypes",[b,g.Y])],O);var j=function(){function t(e){(0,i.Z)(this,t),this.logger=e,this.loadingStrArr=[[""],["⢎⠀","⢆⡀","⢄⡠","⢀⡰","⠀⡱","⠈⠱","⠊⠑","⠎⠁"],[" ","· "," · "," · "," ·"]],this.frame=0,this.index=0,this.interval=void 0,this.text="",this.loadingString=[""],this.color="",this.extname="EhSyringe"}return(0,s.Z)(t,[{key:"setColor",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"#4A90E2";d({background:t})}},{key:"setText",value:function(t){d({text:t})}},{key:"set",value:function(t,e){var n=this,r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0;this.index!==r&&(this.index=r,this.loadingString=this.loadingStrArr[this.index]||[""],this.frame=0),this.text=t,this.setColor(e),r?this.interval||(this.interval=setInterval((function(){n.setText("".concat(n.text).concat(n.loadingString[n.frame]||"")),n.frame++,n.loadingString[n.frame]||(n.frame=0)}),100)):(this.frame=0,this.interval&&(clearInterval(this.interval),this.interval=void 0),this.setText(this.text))}}]),t}();j=(0,u.gn)([(0,h.t)(),(0,u.w6)("design:paramtypes",[g.Y])],j);var S=n(1912);function D(t,e){var n=Object.keys(t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(t);e&&(r=r.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),n.push.apply(n,r)}return n}function Z(t){for(var e=1;ethis._lastCheckData.check&&Object.assign(this._lastCheckData,e);case 4:case"end":return t.stop()}}),t,this)}))),function(){return o.apply(this,arguments)})},{key:"lastCheckData",get:function(){return this._lastCheckData},set:function(t){t&&t.check>this.lastCheckData.check&&(Object.assign(this._lastCheckData,t),this.storage.set("release",this._lastCheckData).catch(this.logger.error))}},{key:"update",value:(r=(0,a.Z)(c().mark((function t(){var e,n,r=this;return c().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return this.initDownloadStatus(),t.prev=1,t.next=4,this.download();case 4:return e=t.sent,t.next=7,this.messaging.emit("update-tag",e.data);case 7:return this.badge.set("OK","#00C801"),this.pushDownloadStatus({run:!0,info:"更新完成",progress:100,complete:!0}),(0,S._)(2500).then((function(){r.downloadStatus.complete&&(r.badge.set("","#4A90E2"),r.initDownloadStatus())})),t.abrupt("return",!0);case 13:return t.prev=13,t.t0=t.catch(1),n=t.t0,this.logger.error(n),this.badge.set("ERR","#C80000"),this.pushDownloadStatus({run:!1,error:!0,info:(null==n?void 0:n.message)?n.message:"更新失败"}),t.abrupt("return",!1);case 20:case"end":return t.stop()}}),t,this,[[1,13]])}))),function(){return r.apply(this,arguments)})},{key:"initDownloadStatus",value:function(){this.downloadStatus=Z({},E),this.messaging.emit("updating-database",this.downloadStatus,!0)}},{key:"pushDownloadStatus",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};this.downloadStatus=Z(Z({},this.downloadStatus),t),this.messaging.emit("updating-database",this.downloadStatus,!0)}},{key:"checkVersion",value:(n=(0,a.Z)(c().mark((function t(){var e,n,r,a=arguments;return c().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:if(a.length>0&&void 0!==a[0]&&a[0]){t.next=6;break}if(e=(new Date).getTime(),n=this.lastCheckData,!(e-n.check<=3e5&&n.githubRelease)){t.next=6;break}return t.abrupt("return",n);case 6:return t.next=8,this.database.getLatestVersion();case 8:if((r=t.sent).target_commitish){t.next=11;break}throw new Error("获取失败,响应有误");case 11:return this.lastCheckData={sha:r.target_commitish,githubRelease:r,check:Date.now()},this.checked=!0,t.abrupt("return",this.lastCheckData);case 14:case"end":return t.stop()}}),t,this)}))),function(){return n.apply(this,arguments)})},{key:"download",value:(e=(0,a.Z)(c().mark((function t(){var e,n,r,a,i,s=this;return c().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return this.badge.set("","#4A90E2",2),this.pushDownloadStatus({run:!0,info:"加载中"}),t.next=4,this.checkVersion();case 4:if(n=t.sent,null===(e=null==n?void 0:n.githubRelease)||void 0===e?void 0:e.target_commitish){t.next=8;break}throw this.logger.debug("checkData",n),new Error("无法获取版本信息");case 8:return r=n.githubRelease,a=this.logger.time("开始下载"),t.prev=10,this.pushDownloadStatus({info:"0%",progress:0}),this.badge.set("0","#4A90E2",1),t.next=15,this.database.getData(r,(function(t){if(t.lengthComputable){var e=Math.floor(t.loaded/t.total*100);s.pushDownloadStatus({info:"".concat(e,"%"),progress:e}),s.badge.set(e.toFixed(0),"#4A90E2",1)}}));case 15:return i=t.sent,this.pushDownloadStatus({info:"下载完成",progress:100}),this.badge.set("100","#4A90E2",1),t.abrupt("return",{release:r,data:i});case 19:return t.prev=19,a.end(),t.finish(19);case 22:case"end":return t.stop()}}),t,this,[[10,,19,22]])}))),function(){return e.apply(this,arguments)})}]),t}();P=(0,u.gn)([(0,h.t)(),(0,u.w6)("design:paramtypes",[g.Y,v.s,l.K,O,j])],P);var C=n(8469),T=function(){function t(e,n,r){var s=this;(0,i.Z)(this,t),this.logger=e,this.messaging=n,this.tagging=r,this.origin="https://e-hentai.org",this.onInputStarted=(0,a.Z)(c().mark((function t(){var e,n,r;return c().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return t.next=2,browser.tabs.query({url:["*://exhentai.org/*","*://e-hentai.org/*"]});case 2:n=t.sent,(null==(r=null!==(e=n.find((function(t){return t.active})))&&void 0!==e?e:n[0])?void 0:r.url)?s.origin=new URL(r.url).origin:s.origin="https://e-hentai.org";case 5:case"end":return t.stop()}}),t)}))),this.onInputChanged=function(t,e){s.messaging.emit("suggest-tag",{term:t.trim(),limit:5}).then((function(t){var n=t.map((function(t){var e=s.tagging.makeTagMatchHtml(t,"match");return{content:s.tagging.searchTerm(t.tag),description:"".concat(e.cn," - ").concat(e.en,"")}}));e(n)})).catch(s.logger.error)},this.onInputEntered=function(t){f("".concat(s.origin,"/?f_search=").concat(encodeURIComponent(t)))},chrome.omnibox?this.init():e.info("不支持 Omnibox")}return(0,s.Z)(t,[{key:"init",value:function(){var t=this;chrome.omnibox.onInputChanged.addListener(this.onInputChanged),chrome.omnibox.onInputEntered.addListener(this.onInputEntered),chrome.omnibox.onInputStarted.addListener((function(){t.onInputStarted().catch(t.logger.error)}))}}]),t}();T=(0,u.gn)([(0,h.t)(),(0,u.w6)("design:paramtypes",[g.Y,v.s,C.P])],T);var A=function(){function t(e,n,r){var a=this;(0,i.Z)(this,t),this.logger=e,this.messaging=n,this.tagging=r,this.nsScore={female:5,male:4.995,misc:4.5,language:1,artist:3,group:2.5,parody:4,character:3.5,reclass:1,rows:0},this.tagList=[],this.sha="",n.on("suggest-tag",(function(t){return a.getSuggests(t.term,t.limit)})),this.update().catch(e.error)}var e,n;return(0,s.Z)(t,[{key:"update",value:(n=(0,a.Z)(c().mark((function t(){var e;return c().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return t.next=2,this.messaging.emit("get-tag-map",{ifNotMatch:this.sha});case 2:(e=t.sent).map&&(this.tagList=Object.values(e.map)),this.sha=e.sha;case 5:case"end":return t.stop()}}),t,this)}))),function(){return n.apply(this,arguments)})},{key:"markTag",value:function(t,e,n){var r=t.key,a=t.cn.toLowerCase(),i=r.indexOf(e),s=a.indexOf(e),o=this.tagging.namespace(t.ns),c=0,u={};return i>=0&&(c+=this.nsScore[o]*(e.length+1)/r.length*(0===i?2:1),u.key={start:i,end:i+e.length}),s>=0&&(c+=this.nsScore[o]*(e.length+1)/a.length*(0===s?2:1),u.cn={start:s,end:s+e.length}),{tag:t,term:n,match:u,score:c}}},{key:"getSuggests",value:(e=(0,a.Z)(c().mark((function t(e){var n,r,a,i,s,o,u=this,h=arguments;return c().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return n=h.length>1&&void 0!==h[1]?h[1]:-1,t.next=3,this.update();case 3:if(this.tagList.length&&e){t.next=5;break}return t.abrupt("return",[]);case 5:return r=e.toLowerCase(),a=r.indexOf(":"),i=this.tagList,a>=1&&(s=this.tagging.ns(r.slice(0,a)))&&(r=r.slice(a+1),i=i.filter((function(t){return t.ns===s}))),o=i.map((function(t){return u.markTag(t,r,e)})).filter((function(t){return t.score>0})),e&&(o=o.sort((function(t,e){return e.score-t.score}))),n>0&&(o=o.slice(0,n)),t.abrupt("return",o);case 13:case"end":return t.stop()}}),t,this)}))),function(t){return e.apply(this,arguments)})}]),t}();A=(0,u.gn)([(0,h.t)(),(0,u.w6)("design:paramtypes",[g.Y,v.s,C.P])],A);var U=n(7386),I=n(1718),L=n(9127),_=n(4975);function M(t,e){var n=Object.keys(t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(t);e&&(r=r.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),n.push.apply(n,r)}return n}function R(t){for(var e=1;e=i)&&Object.keys(r.O).every((function(t){return r.O[t](n[c])}))?n.splice(c--,1):(o=!1,i0&&t[u-1][2]>i;u--)t[u]=t[u-1];t[u]=[n,a,i]},r.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return r.d(e,{a:e}),e},r.d=function(t,e){for(var n in e)r.o(e,n)&&!r.o(t,n)&&Object.defineProperty(t,n,{enumerable:!0,get:e[n]})},r.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(t){if("object"==typeof window)return window}}(),r.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},r.j=352,function(){var t={352:0};r.O.j=function(e){return 0===t[e]};var e=function(e,n){var a,i,s=n[0],o=n[1],c=n[2],u=0;for(a in o)r.o(o,a)&&(r.m[a]=o[a]);if(c)var h=c(r);for(e&&e(n);udiv')].map(e => { 29 | if(e.querySelector('.gt') == null) return 30 | return { 31 | tag: e.querySelector('.gt').title, 32 | background: e.querySelector('.gt').style.background, 33 | color: e.querySelector('.gt').style.color, 34 | borderColor: e.querySelector('.gt').style.borderColor, 35 | weight: e.querySelector('[id^=tagweight]').value, 36 | } 37 | }).filter(v => v)); 38 | } 39 | 40 | async function dyeing() { 41 | setTimeout(colorIcon, 0); 42 | const myTags = GM_getValue("myTags", []); 43 | let css = ''; 44 | myTags.forEach(v => { 45 | css += ` 46 | [id="td_${v.tag.replaceAll(' ', '_')}"]{ 47 | border-color: ${v.borderColor} !important; 48 | background: ${v.background} !important; 49 | } 50 | [id="td_${v.tag.replaceAll(' ', '_')}"] a { 51 | color: ${v.color}; 52 | } 53 | ` 54 | }); 55 | GM_addStyle(css); 56 | } 57 | 58 | function colorIcon() { 59 | const myTags = GM_getValue("myTags", []); 60 | const tagIds = [...document.querySelectorAll("#taglist td>div")].map(v => v.id.replace('td_', '').replaceAll('_', ' ')); 61 | const tags = tagIds.map(id => myTags.find(v => v.tag == id)).filter(v => v); 62 | tags.sort((a, b) => parseInt(a.weight) - parseInt(b.weight)); 63 | const weight = tags.reduce((accumulator, tag) => accumulator + parseInt(tag.weight), 0); 64 | const colors = tags.map(tag => (/(rgb\(.*?\))/ig.exec(tag.borderColor)||[])[0]).filter(v => v); 65 | if(!colors.length) return; 66 | const canvas = document.createElement('canvas'); 67 | canvas.width = canvas.height = 128; 68 | const edgeSize = 8; 69 | let ctx = canvas.getContext("2d"); 70 | colors.forEach((c, i) => { 71 | ctx.fillStyle = ctx.strokeStyle = c; 72 | ctx.fillRect((canvas.width - edgeSize*2) / colors.length * i + edgeSize, 0, (canvas.width - edgeSize*2) / colors.length, canvas.height); 73 | }); 74 | ctx.globalCompositeOperation="destination-in"; 75 | ctx.fillStyle = "rgb(0,0,0)"; 76 | ctx.roundRect(edgeSize/2,edgeSize/2,canvas.width - edgeSize,canvas.height - edgeSize, 20).fill(); 77 | ctx.globalCompositeOperation="source-over"; 78 | ctx.lineWidth = edgeSize; 79 | ctx.strokeStyle = "#5C0D11"; 80 | ctx.stroke(); 81 | ctx.font = '100px Consolas, Monaco, monospace'; 82 | const tw = ctx.measureText("w").width; 83 | const fs = Math.min((( 100 / (tw * 3))) * canvas.width, canvas.width ); 84 | ctx.font = `${fs.toFixed(2)}px Consolas, Monaco, monospace`; 85 | ctx.fillStyle = "#5C0D11"; 86 | ctx.strokeStyle = "#FFF"; 87 | const t = `${weight}`; 88 | const tl = t.length > 2 ? edgeSize : edgeSize * 2; 89 | ctx.strokeText(`${weight}`,tl, fs); 90 | ctx.fillText(`${weight}`, tl, fs); 91 | canvas.toBlob(function(blob) { 92 | const link = canvas.toDataURL('image/png'); 93 | const favicon = document.createElement("link"); 94 | favicon.rel = "icon"; 95 | favicon.href = URL.createObjectURL(blob); 96 | document.head.appendChild(favicon); 97 | }); 98 | } 99 | 100 | CanvasRenderingContext2D.prototype.roundRect = function (x, y, w, h, r) { 101 | if (w < 2 * r) r = w / 2; 102 | if (h < 2 * r) r = h / 2; 103 | this.beginPath(); 104 | this.moveTo(x+r, y); 105 | this.arcTo(x+w, y, x+w, y+h, r); 106 | this.arcTo(x+w, y+h, x, y+h, r); 107 | this.arcTo(x, y+h, x, y, r); 108 | this.arcTo(x, y, x+w, y, r); 109 | this.closePath(); 110 | return this; 111 | } 112 | 113 | document.addEventListener('DOMContentLoaded', async function(){ 114 | if(window.location.pathname == "/mytags")saveMyTagData(); 115 | if(window.location.pathname.slice(0, 3) == '/g/')dyeing(); 116 | }); 117 | -------------------------------------------------------------------------------- /EhSyringe Extension/Resources/userscript/EhReadStatus.user.js: -------------------------------------------------------------------------------- 1 | // ==UserScript== 2 | // @name eh阅读状态 3 | // @namespace com.xioxin.EhTagReadStatus 4 | // @version 0.1 5 | // @description 利用css ":visited" 特性在标题前增加阅读状态指示 6 | // @author xioxin 7 | // @include *://exhentai.org/* 8 | // @include *://e-hentai.org/* 9 | // @grant GM_addStyle 10 | // ==/UserScript== 11 | 12 | function GM_addStyle(script){ 13 | var style = document.createElement("style"); 14 | style.type = "text/css"; 15 | style.innerHTML = script 16 | document.getElementsByTagName("HEAD").item(0).appendChild(style); 17 | } 18 | 19 | function GM_setValue(key, val) {localStorage.setItem(key, JSON.stringify(val))} 20 | 21 | function GM_getValue(key, val) {return JSON.parse(localStorage.getItem(key)||'null') || val } 22 | 23 | 24 | document.addEventListener('DOMContentLoaded',async function(){ 25 | GM_addStyle(` 26 | .itg a .glink::before { 27 | content: "●"; 28 | color: #1a9317; 29 | padding-right: 4px; 30 | } 31 | .itg a:visited .glink::before { 32 | color: #aaa; 33 | }`); 34 | }); 35 | -------------------------------------------------------------------------------- /EhSyringe Extension/Resources/userscript/EhTagTranslatedJump.user.js: -------------------------------------------------------------------------------- 1 | // ==UserScript== 2 | // @name eh漫画语言快捷按钮 3 | // @namespace com.xioxin.translatedJump 4 | // @version 0.6 5 | // @description 快速跳转到其他漫画语言版本 6 | // @author xioxin 7 | // @include *://exhentai.org/g/* 8 | // @include *://e-hentai.org/g/* 9 | // @grant GM_addStyle 10 | // ==/UserScript== 11 | 12 | function GM_addStyle(script){ 13 | var style = document.createElement("style"); 14 | style.type = "text/css"; 15 | style.innerHTML=script 16 | document.getElementsByTagName("HEAD").item(0).appendChild(style); 17 | } 18 | 19 | function GM_setValue(key, val) {localStorage.setItem(key, JSON.stringify(val))} 20 | 21 | function GM_getValue(key, val) {return JSON.parse(localStorage.getItem(key)||'null') || val } 22 | 23 | 24 | const languagePriority = ['chinese', 'japanese', 'english']; 25 | const languages = ` 26 | albanian 阿尔巴尼亚语 data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgNzIgNzIiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZmlsbD0iI0ZGRiIgZD0iTTUgMTdoNjJ2MzhINXoiLz48cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSIyIiBkPSJNNSAxN2g2MnYzOEg1eiIvPjwvc3ZnPg== 27 | arabic 阿拉伯语 data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgNzIgNzIiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZmlsbD0iI0ZGRiIgZD0iTTUgMTdoNjJ2MzhINXoiLz48cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSIyIiBkPSJNNSAxN2g2MnYzOEg1eiIvPjwvc3ZnPg== 28 | bengali 孟加拉语 data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgNzIgNzIiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZmlsbD0iI0ZGRiIgZD0iTTUgMTdoNjJ2MzhINXoiLz48cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSIyIiBkPSJNNSAxN2g2MnYzOEg1eiIvPjwvc3ZnPg== 29 | catalan 加泰罗尼亚语 data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgNzIgNzIiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZmlsbD0iI0ZGRiIgZD0iTTUgMTdoNjJ2MzhINXoiLz48cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSIyIiBkPSJNNSAxN2g2MnYzOEg1eiIvPjwvc3ZnPg== 30 | cebuano 宿务语 data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgNzIgNzIiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZmlsbD0iI0ZGRiIgZD0iTTUgMTdoNjJ2MzhINXoiLz48cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSIyIiBkPSJNNSAxN2g2MnYzOEg1eiIvPjwvc3ZnPg== 31 | chinese 汉语 data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgNzIgNzIiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZmlsbD0iI2QyMmYyNyIgZD0iTTUgMTdoNjJ2MzhINXoiLz48Y2lyY2xlIGN4PSIyNCIgY3k9IjM0IiByPSIxLjc1IiBmaWxsPSIjZjFiMzFjIi8+PGNpcmNsZSBjeD0iMjQiIGN5PSIyNCIgcj0iMS43NSIgZmlsbD0iI2YxYjMxYyIvPjxjaXJjbGUgY3g9IjI4IiBjeT0iMzEiIHI9IjEuNzUiIGZpbGw9IiNmMWIzMWMiLz48Y2lyY2xlIGN4PSIyOCIgY3k9IjI2IiByPSIxLjc1IiBmaWxsPSIjZjFiMzFjIi8+PHBhdGggZmlsbD0iI2YxYjMxYyIgc3Ryb2tlPSIjZjFiMzFjIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGQ9Ik0xMy41MjggMzIuNDQ1bDIuNDcyLTggMi40NzMgOEwxMiAyNy41aDhsLTYuNDcyIDQuOTQ1eiIvPjxnPjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2Utd2lkdGg9IjIiIGQ9Ik01IDE3aDYydjM4SDV6Ii8+PC9nPjwvc3ZnPg== 32 | czech 捷克语 data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgNzIgNzIiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZmlsbD0iI0ZGRiIgZD0iTTUgMTdoNjJ2MzhINXoiLz48cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSIyIiBkPSJNNSAxN2g2MnYzOEg1eiIvPjwvc3ZnPg== 33 | danish 丹麦语 data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgNzIgNzIiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZmlsbD0iI0ZGRiIgZD0iTTUgMTdoNjJ2MzhINXoiLz48cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSIyIiBkPSJNNSAxN2g2MnYzOEg1eiIvPjwvc3ZnPg== 34 | dutch 荷兰语 data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgNzIgNzIiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZmlsbD0iI0ZGRiIgZD0iTTUgMTdoNjJ2MzhINXoiLz48cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSIyIiBkPSJNNSAxN2g2MnYzOEg1eiIvPjwvc3ZnPg== 35 | english 英语 data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgNzIgNzIiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZmlsbD0iIzFlNTBhMCIgZD0iTTUgMTdoNjJ2MzhINXoiLz48cGF0aCBmaWxsPSIjZmZmIiBkPSJNNDAgMjguODU2VjMyaDEwLjE4MUw2NyAyMS42OTFWMTdoLTcuNjU0TDQwIDI4Ljg1NnoiLz48cGF0aCBmaWxsPSIjZDIyZjI3IiBkPSJNNjcgMTdoLTMuODI3TDQwIDMxLjIwM1YzMmgzLjQ4Mkw2NyAxNy41ODZWMTd6Ii8+PHBhdGggZmlsbD0iI2ZmZiIgZD0iTTU5LjM0NyA1NUg2N3YtNC42OTJMNTAuMTgyIDQwSDQwdjMuMTQzTDU5LjM0NyA1NXoiLz48cGF0aCBmaWxsPSIjZDIyZjI3IiBkPSJNNjcgNTV2LTIuMzQ3TDQ2LjM1NSA0MGgtNC43ODdsMjQuNDc0IDE1SDY3eiIvPjxwYXRoIGZpbGw9IiNmZmYiIGQ9Ik0zMiA0My4xNDRWNDBIMjEuODE5TDUgNTAuMzA5VjU1aDcuNjU0TDMyIDQzLjE0NHoiLz48cGF0aCBmaWxsPSIjZDIyZjI3IiBkPSJNNSA1NWgzLjgyN0wzMiA0MC43OTdWNDBoLTMuNDgyTDUgNTQuNDE0VjU1eiIvPjxwYXRoIGZpbGw9IiNmZmYiIGQ9Ik0xMi42NTMgMTdINXY0LjY5MkwyMS44MTggMzJIMzJ2LTMuMTQzTDEyLjY1MyAxN3oiLz48cGF0aCBmaWxsPSIjZDIyZjI3IiBkPSJNNSAxN3YyLjM0N0wyNS42NDYgMzJoNC43ODZMNS45NTggMTdINXoiLz48cGF0aCBmaWxsPSIjZmZmIiBkPSJNNSAzMWg2MnYxMEg1eiIvPjxwYXRoIGZpbGw9IiNmZmYiIGQ9Ik0zMSAxN2gxMHYzOEgzMXoiLz48cGF0aCBmaWxsPSIjZDIyZjI3IiBkPSJNNSAzM2g2MnY2SDV6Ii8+PHBhdGggZmlsbD0iI2QyMmYyNyIgZD0iTTMzIDE3aDZ2MzhoLTZ6Ii8+PGc+PHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIHN0cm9rZS13aWR0aD0iMiIgZD0iTTUgMTdoNjJ2MzhINXoiLz48L2c+PC9zdmc+ 36 | esperanto 世界语 data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgNzIgNzIiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGNpcmNsZSBjeD0iMzYiIGN5PSIzNiIgcj0iMjgiIGZpbGw9IiM5MkQzRjUiLz48ZyBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLW1pdGVybGltaXQ9IjEwIiBzdHJva2Utd2lkdGg9IjIiPjxjaXJjbGUgY3g9IjM2IiBjeT0iMzYiIHI9IjI4Ii8+PHBhdGggZD0iTTM2IDh2NTZjLTguNTYgMC0xNS41LTEyLjUzNi0xNS41LTI4UzI3LjQ0IDggMzYgOGM4LjU2IDAgMTUuNSAxMi41MzYgMTUuNSAyOFM0NC41NiA2NCAzNiA2NE02NCAzNkg4TTYwIDIySDEyTTYwIDUwSDEyIi8+PC9nPjwvc3ZnPg== 37 | estonian 爱沙尼亚语 data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgNzIgNzIiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZmlsbD0iI2ZmZiIgZD0iTTUgMTdoNjJ2MzhINXoiLz48cGF0aCBkPSJNNSAzMGg2MnYxMkg1eiIvPjxwYXRoIGZpbGw9IiMxZTUwYTAiIGQ9Ik01IDE3aDYydjEzSDV6Ii8+PGc+PHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIHN0cm9rZS13aWR0aD0iMiIgZD0iTTUgMTdoNjJ2MzhINXoiLz48L2c+PC9zdmc+ 38 | finnish 芬兰语 data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgNzIgNzIiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZmlsbD0iI2ZmZiIgZD0iTTUgMTdoNjJ2MzhINXoiLz48cGF0aCBmaWxsPSIjMWU1MGEwIiBzdHJva2U9IiMxZTUwYTAiIHN0cm9rZS1taXRlcmxpbWl0PSIxMCIgc3Ryb2tlLXdpZHRoPSIyIiBkPSJNNjcgMzNIMzBWMTdoLTZ2MTZINXY2aDE5djE2aDZWMzloMzd2LTZ6Ii8+PGc+PHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIHN0cm9rZS13aWR0aD0iMiIgZD0iTTUgMTdoNjJ2MzhINXoiLz48L2c+PC9zdmc+ 39 | french 法语 data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgNzIgNzIiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZmlsbD0iI2ZmZiIgZD0iTTUgMTdoNjJ2MzhINXoiLz48cGF0aCBmaWxsPSIjMWU1MGEwIiBkPSJNNSAxN2gyMXYzOEg1eiIvPjxwYXRoIGZpbGw9IiNkMjJmMjciIGQ9Ik00NiAxN2gyMXYzOEg0NnoiLz48Zz48cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSIyIiBkPSJNNSAxN2g2MnYzOEg1eiIvPjwvZz48L3N2Zz4= 40 | german 德语 data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgNzIgNzIiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZmlsbD0iI2ZmZiIgZD0iTTUgMTdoNjJ2MzhINXoiLz48cGF0aCBmaWxsPSIjMWU1MGEwIiBkPSJNNSAxN2gyMXYzOEg1eiIvPjxwYXRoIGZpbGw9IiNkMjJmMjciIGQ9Ik00NiAxN2gyMXYzOEg0NnoiLz48Zz48cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSIyIiBkPSJNNSAxN2g2MnYzOEg1eiIvPjwvZz48L3N2Zz4= 41 | greek 希腊语 data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgNzIgNzIiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZmlsbD0iI2ZmZiIgZD0iTTUgMTdoNjJ2MzhINXoiLz48cGF0aCBmaWxsPSIjMWU1MGEwIiBkPSJNNSAzNGg2MnY0SDV6TTUgMjUuNzVoNjJ2NEg1ek01IDQyLjI1aDYydjRINXpNNSA1MGg2MnY1SDV6TTUgMTdoNjJ2NUg1eiIvPjxwYXRoIGZpbGw9IiMxZTUwYTAiIGQ9Ik01IDE3aDIydjIxSDV6Ii8+PHBhdGggZmlsbD0iI2ZmZiIgZD0iTTE0LjUgMTdoNHYyMmgtNHoiLz48cGF0aCBmaWxsPSIjZmZmIiBkPSJNNSAyNS43NWgyMnY0SDV6Ii8+PGc+PHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIHN0cm9rZS13aWR0aD0iMiIgZD0iTTUgMTdoNjJ2MzhINXoiLz48L2c+PC9zdmc+ 42 | hebrew 希伯来语 data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgNzIgNzIiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZmlsbD0iI0ZGRiIgZD0iTTUgMTdoNjJ2MzhINXoiLz48cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSIyIiBkPSJNNSAxN2g2MnYzOEg1eiIvPjwvc3ZnPg== 43 | hindi 印地语 data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgNzIgNzIiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZmlsbD0iI0ZGRiIgZD0iTTUgMTdoNjJ2MzhINXoiLz48cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSIyIiBkPSJNNSAxN2g2MnYzOEg1eiIvPjwvc3ZnPg== 44 | hungarian 匈牙利语 data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgNzIgNzIiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZmlsbD0iIzVjOWUzMSIgZD0iTTUgMTdoNjJ2MzhINXoiLz48cGF0aCBmaWxsPSIjZDIyZjI3IiBkPSJNNSAxN2g2MnYxM0g1eiIvPjxwYXRoIGZpbGw9IiNmZmYiIGQ9Ik01IDMwaDYydjEySDV6Ii8+PGc+PHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIHN0cm9rZS13aWR0aD0iMiIgZD0iTTUgMTdoNjJ2MzhINXoiLz48L2c+PC9zdmc+ 45 | indonesian 印尼语 data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgNzIgNzIiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZmlsbD0iI2QyMmYyNyIgZD0iTTUgMTdoNjJ2MzhINXoiLz48cGF0aCBmaWxsPSIjZmZmIiBkPSJNNSAzNmg2MnYxOUg1eiIvPjxnPjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2Utd2lkdGg9IjIiIGQ9Ik01IDE3aDYydjM4SDV6Ii8+PC9nPjwvc3ZnPg== 46 | italian 意大利语 data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgNzIgNzIiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZmlsbD0iI2ZmZiIgZD0iTTUgMTdoNjJ2MzhINXoiLz48cGF0aCBmaWxsPSIjNWM5ZTMxIiBkPSJNNSAxN2gyMXYzOEg1eiIvPjxwYXRoIGZpbGw9IiNkMjJmMjciIGQ9Ik00NiAxN2gyMXYzOEg0NnoiLz48Zz48cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSIyIiBkPSJNNSAxN2g2MnYzOEg1eiIvPjwvZz48L3N2Zz4= 47 | japanese 日语 data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgNzIgNzIiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZmlsbD0iI2ZmZiIgZD0iTTUgMTdoNjJ2MzhINXoiLz48Y2lyY2xlIGN4PSIzNiIgY3k9IjM2IiByPSI5IiBmaWxsPSIjZDIyZjI3Ii8+PGc+PHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIHN0cm9rZS13aWR0aD0iMiIgZD0iTTUgMTdoNjJ2MzhINXoiLz48L2c+PC9zdmc+ 48 | korean 韩语 data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgNzIgNzIiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZmlsbD0iI2ZmZiIgZD0iTTUgMTdoNjJ2MzhINXoiLz48Y2lyY2xlIGN4PSIzNiIgY3k9IjM2IiByPSI5IiBmaWxsPSIjZDIyZjI3Ii8+PGcgZmlsbD0iIzFlNTBhMCI+PHBhdGggZD0iTTI4LjEyNyAzMS42NzZBNC40OTIgNC40OTIgMCAwIDAgMzYgMzZjLjAyMy0uMDQuMDM0LS4wODMuMDU1LS4xMjNsLjAyNC4wMTRhNC40OTMgNC40OTMgMCAwIDEgNy43MjQgNC41OWwuMDAzLjAwMmE4Ljk5MiA4Ljk5MiAwIDAgMS0xNS42OC04LjgwN3pNMjguMzMxIDMxLjI4N2wuMDIuMDExYy0uMDMuMDQ2LS4wNjcuMDg1LS4wOTUuMTMzLjAyNy0uMDQ3LjA0Ny0uMDk4LjA3NS0uMTQ0eiIvPjwvZz48ZyBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCI+PHBhdGggZD0iTTI0LjIzMiA0MS45MDJsMyA1LjE5Nk0yMC43NjggNDMuOTAybDMgNS4xOTZNMjIuNSA0Mi45MDJsMSAxLjczMk0yNC41IDQ2LjM2NmwxIDEuNzMyIi8+PGc+PHBhdGggZD0iTTQ1LjUgNDguMDk4bDEtMS43MzJNNDcuNSA0NC42MzRsMS0xLjczMk00Ny4yMzIgNDkuMDk4bDEtMS43MzJNNDkuMjMyIDQ1LjYzNGwxLTEuNzMyTTQzLjc2OCA0Ny4wOThsMS0xLjczMk00NS43NjggNDMuNjM0bDEtMS43MzIiLz48L2c+PGc+PHBhdGggZD0iTTIwLjc2OCAyOC4wOThsMy01LjE5Nk0yMi41IDI5LjA5OGwzLTUuMTk2TTI0LjIzMiAzMC4wOThsMy01LjE5NiIvPjwvZz48Zz48cGF0aCBkPSJNNDQuNzY4IDI0LjkwMmwxIDEuNzMyTTQ2Ljc2OCAyOC4zNjZsMSAxLjczMk00OC4yMzIgMjIuOTAybDEgMS43MzJNNTAuMjMyIDI2LjM2NmwxIDEuNzMyTTQ2LjUgMjMuOTAybDMgNS4xOTYiLz48L2c+PC9nPjxnPjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2Utd2lkdGg9IjIiIGQ9Ik01IDE3aDYydjM4SDV6Ii8+PC9nPjwvc3ZnPg== 49 | mongolian 蒙古语 data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgNzIgNzIiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZmlsbD0iIzFlNTBhMCIgZD0iTTUuMjI3IDE3aDYydjM4aC02MnoiLz48cGF0aCBmaWxsPSIjZDIyZjI3IiBkPSJNNS4yMjcgMTdoMjF2MzhoLTIxek00Ni4yMjcgMTdoMjF2MzhoLTIxeiIvPjxjaXJjbGUgY3g9IjE2IiBjeT0iMjkiIHI9IjEiIGZpbGw9IiNmY2VhMmIiIHN0cm9rZT0iI2ZjZWEyYiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2Utd2lkdGg9IjIiLz48Y2lyY2xlIGN4PSIxNiIgY3k9IjQxIiByPSIxIiBmaWxsPSIjZmNlYTJiIiBzdHJva2U9IiNmY2VhMmIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSIyIi8+PHBhdGggZmlsbD0iI2ZjZWEyYiIgc3Ryb2tlPSIjZmNlYTJiIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIHN0cm9rZS13aWR0aD0iMiIgZD0iTTE3IDI0YTEgMSAwIDAgMS0yIDBsMS0xek0xNSAzM2gybC0xIDEtMS0xek0xNSA0OGgybC0xIDEtMS0xek0xNSAzN2gyTTE1IDQ1aDJNMTEgMzNoMXYxNmgtMXpNMjAgMzNoMXYxNmgtMXoiLz48Zz48cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSIyIiBkPSJNNSAxN2g2MnYzOEg1eiIvPjwvZz48L3N2Zz4= 50 | norwegian 挪威语 data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgNzIgNzIiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZmlsbD0iI2QyMmYyNyIgZD0iTTUgMTdoNjJ2MzhINXoiLz48cGF0aCBmaWxsPSIjMWU1MGEwIiBzdHJva2U9IiNmZmYiIHN0cm9rZS1taXRlcmxpbWl0PSIxMCIgc3Ryb2tlLXdpZHRoPSIyIiBkPSJNNjcgMzNIMzBWMTdoLTZ2MTZINXY2aDE5djE2aDZWMzloMzd2LTZ6Ii8+PGc+PHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIHN0cm9rZS13aWR0aD0iMiIgZD0iTTUgMTdoNjJ2MzhINXoiLz48L2c+PC9zdmc+ 51 | polish 波兰语 data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgNzIgNzIiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZmlsbD0iI2ZmZiIgZD0iTTUgMTdoNjJ2MzhINXoiLz48cGF0aCBmaWxsPSIjZDIyZjI3IiBkPSJNNSAzNmg2MnYxOUg1eiIvPjxnPjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2Utd2lkdGg9IjIiIGQ9Ik01IDE3aDYydjM4SDV6Ii8+PC9nPjwvc3ZnPg== 52 | portuguese 葡萄牙语 data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgNzIgNzIiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZmlsbD0iI2QyMmYyNyIgZD0iTTUgMTdoNjJ2MzhINXoiLz48cGF0aCBmaWxsPSIjNWM5ZTMxIiBkPSJNNSAxN2gyMXYzOEg1eiIvPjxjaXJjbGUgY3g9IjI2IiBjeT0iMzYiIHI9IjEyIiBmaWxsPSJub25lIiBzdHJva2U9IiNmY2VhMmIiIHN0cm9rZS1taXRlcmxpbWl0PSIxMCIgc3Ryb2tlLXdpZHRoPSIyIi8+PHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSIjZmNlYTJiIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGQ9Ik0yNiAyNHYyNE0yNiAzOS41TDE3IDQ0aDE4bC05LTQuNXpNMjYgMzMuNWw5LTUuNS04LjUgMS41TDE3IDI4bDkgNS41eiIvPjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iI2ZjZWEyYiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBkPSJNMzggMzZsLTEyIDUtMTItNSAxMi01IDEyIDV6Ii8+PHBhdGggZmlsbD0iI2ZmZiIgc3Ryb2tlPSIjZDIyZjI3IiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIHN0cm9rZS13aWR0aD0iMiIgZD0iTTIwLjIgMjloMTEuNnYxMC4xYzAgMi41LTIuNiA0LjYtNS44IDQuNi0zLjIgMC01LjgtMi4xLTUuOC00LjZWMjl6Ii8+PGNpcmNsZSBjeD0iMjYiIGN5PSIzMi44IiByPSIuNyIgZmlsbD0iIzFlNTBhMCIgc3Ryb2tlPSIjMWU1MGEwIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz48Y2lyY2xlIGN4PSIyNiIgY3k9IjM4LjciIHI9Ii43IiBmaWxsPSIjMWU1MGEwIiBzdHJva2U9IiMxZTUwYTAiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIvPjxjaXJjbGUgY3g9IjI2IiBjeT0iMzUuNyIgcj0iLjciIGZpbGw9IiMxZTUwYTAiIHN0cm9rZT0iIzFlNTBhMCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIi8+PGNpcmNsZSBjeD0iMjkiIGN5PSIzNS43IiByPSIuNyIgZmlsbD0iIzFlNTBhMCIgc3Ryb2tlPSIjMWU1MGEwIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz48Y2lyY2xlIGN4PSIyMyIgY3k9IjM1LjciIHI9Ii43IiBmaWxsPSIjMWU1MGEwIiBzdHJva2U9IiMxZTUwYTAiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIvPjxnPjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2Utd2lkdGg9IjIiIGQ9Ik01IDE3aDYydjM4SDV6Ii8+PC9nPjwvc3ZnPg== 53 | romanian 罗马尼亚语 data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgNzIgNzIiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZmlsbD0iI2YxYjMxYyIgZD0iTTUgMTdoNjJ2MzhINXoiLz48cGF0aCBmaWxsPSIjMWU1MGEwIiBkPSJNNSAxN2gyMXYzOEg1eiIvPjxwYXRoIGZpbGw9IiNkMjJmMjciIGQ9Ik00NiAxN2gyMXYzOEg0NnoiLz48Zz48cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSIyIiBkPSJNNSAxN2g2MnYzOEg1eiIvPjwvZz48L3N2Zz4= 54 | russian 俄语 data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgNzIgNzIiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZmlsbD0iI2QyMmYyNyIgZD0iTTUgMTdoNjJ2MzhINXoiLz48cGF0aCBmaWxsPSIjZmZmIiBkPSJNNSAxN2g2MnYxM0g1eiIvPjxwYXRoIGZpbGw9IiMxZTUwYTAiIGQ9Ik01IDMwaDYydjEySDV6Ii8+PGc+PHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIHN0cm9rZS13aWR0aD0iMiIgZD0iTTUgMTdoNjJ2MzhINXoiLz48L2c+PC9zdmc+ 55 | slovak 斯洛伐克语 data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgNzIgNzIiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZmlsbD0iI2QyMmYyNyIgZD0iTTUgMTdoNjJ2MzhINXoiLz48cGF0aCBmaWxsPSIjZDBjZmNlIiBkPSJNNSAxN2g2MnYxM0g1eiIvPjxwYXRoIGZpbGw9IiMxZTUwYTAiIGQ9Ik01IDMwaDYydjEySDV6Ii8+PHBhdGggZmlsbD0iI2QyMmYyNyIgc3Ryb2tlPSIjZmZmIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGQ9Ik0yMy44MzMgNDVzNi43NS0yLjI1IDYuNzUtOXYtOWgtMTMuNXY5YzAgNi43NSA2Ljc1IDkgNi43NSA5eiIvPjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iI2ZmZiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2Utd2lkdGg9IjIiIGQ9Ik0yMy44MzMgMjkuNXYxMk0yMS44MzMgMzEuNWg0TTIwLjMzMyAzNC41aDciLz48Y2lyY2xlIGN4PSIyMy44MzMiIGN5PSI0MS41IiByPSIzLjE2NyIgZmlsbD0iIzFlNTBhMCIvPjxwYXRoIGZpbGw9IiMxZTUwYTAiIGQ9Ik0xOS4yNSAzOS4zMzNhMi4xNDYgMi4xNDYgMCAwIDAtMS4zMjcuNDY1IDkuNTggOS41OCAwIDAgMCAyLjcwMyAzLjM2MyAyLjE1OCAyLjE1OCAwIDAgMC0xLjM3Ni0zLjgyOHpNMjguNDE3IDM5LjMzM2EyLjE1OCAyLjE1OCAwIDAgMC0xLjM3NiAzLjgyOCA5LjU4IDkuNTggMCAwIDAgMi43MDItMy4zNjMgMi4xNDYgMi4xNDYgMCAwIDAtMS4zMjYtLjQ2NXoiLz48cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiNmZmYiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgZD0iTTIzLjgzMyA0NXM2Ljc1LTIuMjUgNi43NS05di05aC0xMy41djljMCA2Ljc1IDYuNzUgOSA2Ljc1IDl6Ii8+PGc+PHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIHN0cm9rZS13aWR0aD0iMiIgZD0iTTUgMTdoNjJ2MzhINXoiLz48L2c+PC9zdmc+ 56 | slovenian 斯洛文尼亚语 data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgNzIgNzIiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZmlsbD0iI2QyMmYyNyIgZD0iTTUgMTdoNjJ2MzhINXoiLz48cGF0aCBmaWxsPSIjZmZmIiBkPSJNNSAxN2g2MnYxM0g1eiIvPjxwYXRoIGZpbGw9IiMxZTUwYTAiIGQ9Ik01IDMwaDYydjEySDV6Ii8+PHBhdGggZmlsbD0iIzFlNTBhMCIgc3Ryb2tlPSIjMDAwIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGQ9Ik0yMi41ODMgMjJ2OWMwIDYuNzUtNi43NSA5LTYuNzUgOXMtNi43NS0yLjI1LTYuNzUtOXYtOXM2Ljg5Ni0zLjQwNiAxMy41IDB6Ii8+PHBhdGggZmlsbD0iI2ZmZiIgc3Ryb2tlPSIjZmZmIiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIGQ9Ik0xMS45NjMgMzMuMzUybDcuOTc1LjMzOUE2LjgxNiA2LjgxNiAwIDAgMSAxNiAzOGMtMyAxLTQuMDM3LTQuNjQ5LTQuMDM3LTQuNjQ5Ii8+PHBhdGggZmlsbD0iI2ZmZiIgc3Ryb2tlPSIjZmZmIiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIGQ9Ik0xNC41IDMzLjVsMS0yIDIuMjY1IDIuNTg0TDE0LjUgMzMuNSIvPjxjaXJjbGUgY3g9IjEzIiBjeT0iMjQiIHI9IjEiIGZpbGw9IiNmY2VhMmIiLz48cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiNmZmYiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSIyIiBkPSJNMjEgMzVsLTEtMy0yIDMtMi01LTIgNS0yLTMtMSAzczQgOSAxMCAweiIvPjxjaXJjbGUgY3g9IjE2IiBjeT0iMjYiIHI9IjEiIGZpbGw9IiNmY2VhMmIiLz48Y2lyY2xlIGN4PSIxOSIgY3k9IjI0IiByPSIxIiBmaWxsPSIjZmNlYTJiIi8+PHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSIjZDIyZjI3IiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIGQ9Ik0yMi41ODMgMjJ2OWMwIDYuNzUtNi43NSA5LTYuNzUgOXMtNi43NS0yLjI1LTYuNzUtOXYtOXM2Ljg5Ni0zLjQwNiAxMy41IDB6Ii8+PGc+PHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIHN0cm9rZS13aWR0aD0iMiIgZD0iTTUgMTdoNjJ2MzhINXoiLz48L2c+PC9zdmc+ 57 | spanish 西班牙语 data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgNzIgNzIiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZmlsbD0iI2YxYjMxYyIgZD0iTTUgMTdoNjJ2MzhINXoiLz48cGF0aCBmaWxsPSIjZDIyZjI3IiBkPSJNMjMgMzN2N2EyLjAwNiAyLjAwNiAwIDAgMS0yIDJoLTRhMi4wMDYgMi4wMDYgMCAwIDEtMi0ydi03TTUgMTdoNjJ2OUg1ek01IDQ2aDYydjlINXoiLz48cGF0aCBmaWxsPSIjZjFiMzFjIiBkPSJNMTkgMzNoNHY0aC00eiIvPjxjaXJjbGUgY3g9IjE5IiBjeT0iMzciIHI9IjEuNSIgZmlsbD0iIzZhNDYyZiIvPjxnIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzZhNDYyZiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2Utd2lkdGg9IjIiPjxwYXRoIGQ9Ik0yNyAzM3Y5TTExIDMzdjlNMTUgMzBhOC41NjggOC41NjggMCAwIDEgNC0xTTIzIDMwYTguNTY4IDguNTY4IDAgMCAwLTQtMU0xNSAzM2g4TTIzIDMzdjdhMi4wMDYgMi4wMDYgMCAwIDEtMiAyaC00YTIuMDA2IDIuMDA2IDAgMCAxLTItMnYtN00xMCA0MmgyTTI2IDQyaDIiLz48L2c+PGc+PHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIHN0cm9rZS13aWR0aD0iMiIgZD0iTTUgMTdoNjJ2MzhINXoiLz48L2c+PC9zdmc+ 58 | swedish 瑞典语 data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgNzIgNzIiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZmlsbD0iIzFlNTBhMCIgZD0iTTUgMTdoNjJ2MzhINXoiLz48cGF0aCBmaWxsPSIjZmNlYTJiIiBzdHJva2U9IiNmY2VhMmIiIHN0cm9rZS1taXRlcmxpbWl0PSIxMCIgc3Ryb2tlLXdpZHRoPSIyIiBkPSJNNjcgMzNIMzBWMTdoLTZ2MTZINXY2aDE5djE2aDZWMzloMzd2LTZ6Ii8+PGc+PHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIHN0cm9rZS13aWR0aD0iMiIgZD0iTTUgMTdoNjJ2MzhINXoiLz48L2c+PC9zdmc+ 59 | tagalog 他加禄语 data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgNzIgNzIiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZmlsbD0iI0ZGRiIgZD0iTTUgMTdoNjJ2MzhINXoiLz48cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSIyIiBkPSJNNSAxN2g2MnYzOEg1eiIvPjwvc3ZnPg== 60 | thai 泰语 data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgNzIgNzIiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZmlsbD0iI2ZmZiIgZD0iTTUgMTdoNjJ2MzhINXoiLz48cGF0aCBmaWxsPSIjMWU1MGEwIiBkPSJNNSAzMGg2MnYxMkg1eiIvPjxwYXRoIGZpbGw9IiNkMjJmMjciIGQ9Ik01IDUwaDYydjVINXpNNSAxN2g2MnY1SDV6Ii8+PGc+PHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiIHN0cm9rZS13aWR0aD0iMiIgZD0iTTUgMTdoNjJ2MzhINXoiLz48L2c+PC9zdmc+ 61 | turkish 土耳其语 data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgNzIgNzIiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZmlsbD0iI2QyMmYyNyIgZD0iTTUgMTdoNjJ2MzhINXoiLz48cGF0aCBmaWxsPSIjZmZmIiBzdHJva2U9IiNmZmYiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgZD0iTTQwLjY0IDMzLjA1bDMuMDUyIDQuMDE5LTQuOTM0LTEuNTMyIDQuOTMyLTEuNTQxLTMuMDQ2IDQuMDI1LS4wMDQtNC45NzJNMzEuMjkgNDQuNjRhOC42NDMgOC42NDMgMCAxIDEgMy45NTgtMTYuMzQgMTEgMTEgMCAxIDAgMCAxNS4zOCA4LjcxNSA4LjcxNSAwIDAgMS0zLjk1OC45NXoiLz48Zz48cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSIyIiBkPSJNNSAxN2g2MnYzOEg1eiIvPjwvZz48L3N2Zz4= 62 | ukrainian 乌克兰语 data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgNzIgNzIiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZmlsbD0iIzYxYjJlNCIgZD0iTTUgMTdoNjJ2MzhINXoiLz48cGF0aCBmaWxsPSIjZmNlYTJiIiBkPSJNNSAzNmg2MnYxOUg1eiIvPjxnPjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2Utd2lkdGg9IjIiIGQ9Ik01IDE3aDYydjM4SDV6Ii8+PC9nPjwvc3ZnPg== 63 | vietnamese 越南语 data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgNzIgNzIiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZmlsbD0iI2QyMmYyNyIgZD0iTTUgMTdoNjJ2MzhINXoiLz48cGF0aCBmaWxsPSIjZjFiMzFjIiBzdHJva2U9IiNmMWIzMWMiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgZD0iTTI4Ljg5IDQ3bDcuMzAzLTIyIDYuMjk1IDIxLjY2M0wyNSAzMy42MWwyMi0uNTQzTDI4Ljg5IDQ3eiIvPjxnPjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2Utd2lkdGg9IjIiIGQ9Ik01IDE3aDYydjM4SDV6Ii8+PC9nPjwvc3ZnPg== 64 | speechless 无言 data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgNzIgNzIiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGNpcmNsZSBjeD0iMzYiIGN5PSIzNS44IiByPSIyMyIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjRkNFQTJCIiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIHN0cm9rZS13aWR0aD0iMS44Ii8+PHBhdGggZmlsbD0iI0ZDRUEyQiIgZD0iTTQ2LjggNTYuM2MxMS4zLTYgMTUuNy0yMC4yIDkuNy0zMS41cy0yMC0xNS41LTMxLjMtOS41LTE1LjUgMjAtOS41IDMxLjNjMi4zIDQuMiA1LjggNy43IDEwLjEgOS44IDAgMS42LjcgMy4yIDEuOCA0LjQgMS40IDEuNiA4LjUgMy4zIDEyLjItLjIgMS4xLTEgNy4zLTQuMiA3LTQuM3oiLz48Zz48cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSIyIiBkPSJNNTEuNSA1Mi44YzkuNC04LjYgMTAuMS0yMy4xIDEuNS0zMi41cy0yMy4xLTEwLjEtMzIuNS0xLjVTMTAuNCA0MS45IDE5IDUxLjNjLjkuOSAxLjggMS44IDIuOCAyLjYiLz48cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSIyIiBkPSJNMjEuNCAyMy42Yy43LTEuNCAxLjktMi40IDMuMy0yLjkgMS4zLS43IDIuOS0uOCA0LjMtLjRNNTAuNyAyMy42Yy0xLjUtMi43LTQuNi00LTcuNi0zLjNNMzQgNDEuNWMtMS40LS4yLTIuOC0uNy00LTEuNU00Mi4xIDQwYy0xLjMuNy0yLjcgMS4yLTQuMiAxLjVNMzcuOCAzOC42YzAtMS0uOS0xLjktMS45LTEuOXMtMS45LjktMS45IDEuOU0zNCA0Ny40di04LjhNMzcuOCAzOC42djguOSIvPjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLW1pdGVybGltaXQ9IjEwIiBzdHJva2Utd2lkdGg9IjIiIGQ9Ik0zNy4yIDQ3LjRjMS43IDAgMyAxLjMgMyAzdjEuOGg0LjFjMS4zLS4xIDIuNS43IDIuOCAycy0uMyAyLjYtMS40IDMuMmMtLjUuMy0xLjEuNi0xLjYuOS0yIDEuMS00LjEgMi4yLTYuMiAzLjMtMS45IDEtNCAxLjQtNi4xIDEtMy42LS42LTYtNC01LjQtNy43LjItMS41LjUtMyAxLTQuNC42LTEuOCAyLjMtMy4xIDQuMi0zLjFoNS42eiIvPjxwYXRoIGQ9Ik0zMCAyNy44YzAgMS43LTEuMyAzLTMgM3MtMy0xLjMtMy0zIDEuMy0zIDMtM2MxLjYgMCAzIDEuMyAzIDIuOXYuMU00OCAyNy44YzAgMS43LTEuMyAzLTMgM3MtMy0xLjMtMy0zIDEuMy0zIDMtM2MxLjYgMCAzIDEuMyAzIDIuOXYuMSIvPjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIHN0cm9rZS13aWR0aD0iMiIgZD0iTTM2LjIgNTEuOGMtMS4zIDAtMiAuNy0yLjUgMS41LS42LjkgMCAyLjIgMSAyLjJIMzljLjcgMCAxLjItLjYgMS4yLTEuNFY1Mi4yIi8+PC9nPjwvc3ZnPg== 65 | text_cleaned 文字清除 data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgNzIgNzIiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGcgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjMDAwIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2Utd2lkdGg9IjIiPjxwYXRoIGQ9Ik01OS4wMzUgNjBoLTQ2LjA3YS45NjguOTY4IDAgMCAxLS45NjUtLjk2NXYtNDYuMDdhLjk2OC45NjggMCAwIDEgLjk2NS0uOTY1aDQ2LjA3YS45NjguOTY4IDAgMCAxIC45NjUuOTY1djQ2LjA3YS45NjguOTY4IDAgMCAxLS45NjUuOTY1eiIvPjxwYXRoIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgZD0iTTMyLjA3IDQyLjU3OGE1LjMxNCA1LjMxNCAwIDAgMS0zLjUzOCAxLjM0MyA1LjMzNCA1LjMzNCAwIDAgMS01LjMzNC01LjMzNHYtNC4yNjhhNS4zMzQgNS4zMzQgMCAwIDEgNS4zMzQtNS4zMzQgNS4zMTMgNS4zMTMgMCAwIDEgMy41MzggMS4zNDNNNDIuNDAxIDI5LjA0OXYxNC45MzZoNi40MDEiLz48L2c+PHBhdGggZmlsbD0iI2QyMmYyNyIgZD0iTTU5LjAzNSA2MC40NTNoLTQ2LjA3YS45NjguOTY4IDAgMCAxLS45NjUtLjk2NXYtNDYuMDdhLjk2OC45NjggMCAwIDEgLjk2NS0uOTY1aDQ2LjA3YS45NjguOTY4IDAgMCAxIC45NjUuOTY1djQ2LjA3YS45NjguOTY4IDAgMCAxLS45NjUuOTY1eiIvPjxnIGZpbGw9Im5vbmUiIHN0cm9rZT0iI2ZmZiIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSIyIj48cGF0aCBkPSJNNTkuMDM1IDYwaC00Ni4wN2EuOTY4Ljk2OCAwIDAgMS0uOTY1LS45NjV2LTQ2LjA3YS45NjguOTY4IDAgMCAxIC45NjUtLjk2NWg0Ni4wN2EuOTY4Ljk2OCAwIDAgMSAuOTY1Ljk2NXY0Ni4wN2EuOTY4Ljk2OCAwIDAgMS0uOTY1Ljk2NXoiLz48cGF0aCBzdHJva2UtbGluZWNhcD0icm91bmQiIGQ9Ik0zMi4wNyA0Mi41NzhhNS4zMTQgNS4zMTQgMCAwIDEtMy41MzggMS4zNDMgNS4zMzQgNS4zMzQgMCAwIDEtNS4zMzQtNS4zMzR2LTQuMjY4YTUuMzM0IDUuMzM0IDAgMCAxIDUuMzM0LTUuMzM0IDUuMzEzIDUuMzEzIDAgMCAxIDMuNTM4IDEuMzQzTTQyLjQwMSAyOS4wNDl2MTQuOTM2aDYuNDAxIi8+PC9nPjwvc3ZnPg== 66 | rewrite 重写 data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgNzIgNzIiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZmlsbD0iI0ZGRiIgZD0iTTE2LjQwNSAxMS4zNzhINTUuOTd2NDkuMDY2SDE2LjQwNXoiLz48cGF0aCBmaWxsPSIjZjRhYTQxIiBkPSJNMzkuOTMxIDQwLjIyMmwxMS4yOTQtMTEuMjk0IDcuMzc2IDcuMzc2LTExLjE5OCAxMS4xOTgiLz48cGF0aCBmaWxsPSIjYTU3OTM5IiBkPSJNMzcuOTQxIDQ2LjgxOWwxLjk2MS01LjY0OSA2LjQ1NCA2LjQ1NC01LjY0OCAxLjk2Ii8+PHBhdGggZmlsbD0iI0VBNUE0NyIgZD0iTTU0LjYwOSAyNS4wNTJsMy45NzgtMy45NzkgNy44NTkgNy44NTktMy45NDUgMy45NDUiLz48cGF0aCBmaWxsPSIjZDBjZmNlIiBkPSJNNTAuNDk0IDI5LjY2bDQuNjA4LTQuNjA4IDcuMzc1IDcuMzc1LTQuNTY4IDQuNTY5Ii8+PGc+PHBhdGggZD0iTTM4LjA3IDQ3LjE5MWwyLjM4NiAyLjM4Ni0zLjQ2NCAxLjI4eiIvPjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIHN0cm9rZS13aWR0aD0iMiIgZD0iTTIyLjMyMiAxOS44NzVoMjdNMjIuMzIyIDI3Ljg3NWgyNS42TTIyLjMyMiAzNS44NzVoMTcuMTA5TTIyLjMyMiA0My44NzVoMTIuMjA2TTIyLjMyMiA1MS44NzVoMTAuMTQ2Ii8+PHBhdGggZD0iTTM4LjA3IDQ3LjE5MWwyLjM4NiAyLjM4Ni0zLjQ2NCAxLjI4eiIvPjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIHN0cm9rZS13aWR0aD0iMiIgZD0iTTQwLjY5MiA0OS41OTFsNS42NjQtMS45NjcgMTUuNTktMTUuNTktNi40NTQtNi40NTQtMTUuNTkgMTUuNTktMS45NzQgNS42NzF6TTU4LjA4NiAyMi45ODZsMS41NTUtMS41NTUgNi40NTQgNi40NTQtMS42MzIgMS42MzJNNDAuMjc5IDQwLjc5M2w2LjQ1NCA2LjQ1NCIvPjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIiBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIHN0cm9rZS13aWR0aD0iMiIgZD0iTTM3LjkzMiA0Ni44MjhsLTEuMzgzIDQuMTQ5IDQuMTU5LTEuMzkyTTUxLjMwMiAzMC4xNTdsNi4yMDIgNi4yMDIiLz48cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLW1pdGVybGltaXQ9IjEwIiBzdHJva2Utd2lkdGg9IjIuMDIxIiBkPSJNNTUuMzIyIDQ0LjIyOHYxNS42NDdoLTM5di00OGgzOXY4LjQ1NiIvPjwvZz48L3N2Zz4= 67 | unknown 未知 data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgNzIgNzIiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZmlsbD0iI0ZGRiIgZD0iTTUgMTdoNjJ2MzhINXoiLz48cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiMwMDAiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSIyIiBkPSJNNSAxN2g2MnYzOEg1eiIvPjwvc3ZnPg==`.trim().split('\n').map(v => { 68 | const [value, name, icon] = v.split(' '); 69 | return {value: value.replace('_', ' '), name, icon}; 70 | }); 71 | 72 | async function getDataList(name) { 73 | let searchUrl = `${window.location.origin}/?f_search=${encodeURIComponent(`"${name}"`)}`; 74 | const response = await fetch(searchUrl); 75 | const html = await response.text(); 76 | const safeHtml = html.replace(/^.*(.*)<\/body>.*$/igms,"$1").replace(/(.*?)<\/script>/igms, ''); 77 | const dom = document.createElement('div') 78 | dom.innerHTML = safeHtml; 79 | const list = [...dom.querySelectorAll('.itg>tbody>tr,.gl1t')]; 80 | let dataList = list.map(e => { 81 | if(e.querySelector('.glname') == null) return null; 82 | const pagesElement = e.querySelector('div.gl3e div:nth-child(5), div.gl5t > div:nth-child(2) > div:nth-child(2)'); 83 | const linkElement = e.querySelector('.gl1e a,.glname a,.gl2e a,.gl1t>a'); 84 | const torrentElement = e.querySelector('.gldown a'); 85 | const titleElement = e.querySelector('.glink'); 86 | return { 87 | distance: minDistance(cleanBookName(titleElement.textContent), name), 88 | href: linkElement.href, 89 | title: titleElement.textContent, 90 | pages: pagesElement ? pagesElement.textContent : null, 91 | torrentHref: torrentElement ? torrentElement.href : null, 92 | tags: [...e.querySelectorAll('.gt')].map(e2 => e2.title) 93 | } 94 | }).filter(v => v); 95 | return dataList; 96 | } 97 | 98 | 99 | function cleanBookName(name) { 100 | name = name.replace(/\[.*?\]/gi, ''); 101 | name = name.replace(/\(.*?\)/gi, ''); 102 | name = name.replace(/\sCh\.[0-9-]+/gi, ''); 103 | name = name.replace(/\s第[0-9-]+話/gi, ''); 104 | name = name.replace(/\s第[0-9-]+话/gi, ''); 105 | name = name.trim(); 106 | return name; 107 | } 108 | 109 | function minDistance(s1, s2) { 110 | const len1 = s1.length 111 | const len2 = s2.length 112 | let matrix = [] 113 | for (let i = 0; i <= len1; i++) { 114 | matrix[i] = new Array() 115 | for (let j = 0; j <= len2; j++) { 116 | if (i == 0) { 117 | matrix[i][j] = j 118 | } else if (j == 0) { 119 | matrix[i][j] = i 120 | } else { 121 | let cost = 0 122 | if (s1[i - 1] != s2[j - 1]) { 123 | cost = 1 124 | } 125 | const temp = matrix[i - 1][j - 1] + cost 126 | 127 | matrix[i][j] = Math.min(matrix[i - 1][j] + 1, matrix[i][j - 1] + 1, temp) 128 | } 129 | } 130 | } 131 | return matrix[len1][len2] 132 | } 133 | 134 | 135 | document.addEventListener('DOMContentLoaded',async function(){ 136 | 137 | GM_addStyle(` 138 | .tj-box { 139 | text-align: left; 140 | font-size: 12px; 141 | font-weight: 400; 142 | position: absolute; 143 | top: -1px; 144 | right: -1px; 145 | z-index: 99999999; 146 | background: inherit; 147 | border: inherit; 148 | padding: 0 8px; 149 | } 150 | .tj-box .tj-lang-icon{ 151 | background: inherit; 152 | display: inline-block; 153 | border: inherit; 154 | border-width: 0; 155 | } 156 | .tj-box .tj-lang-icon>a>img { 157 | width: 24px; 158 | } 159 | .tj-box .tj-lang-icon ul { 160 | display: none; 161 | white-space: nowrap; 162 | background: inherit; 163 | margin: 0; 164 | padding: 8px; 165 | border: inherit; 166 | border-width: 1px; 167 | position: absolute; 168 | top: 24px; 169 | right: -1px; 170 | list-style: none; 171 | } 172 | .tj-box .tj-lang-icon:hover ul { 173 | display: block; 174 | } 175 | .tj-box .tj-lang-icon ul li { 176 | padding: 2px 0; 177 | } 178 | .tj-box a { 179 | text-decoration: none; 180 | } 181 | .tj-box ul a.title::before { 182 | content: "●"; 183 | color: #1a9317; 184 | padding-right: 4px; 185 | } 186 | .tj-box ul a.title:visited::before { 187 | color: #aaa; 188 | } 189 | `); 190 | 191 | 192 | const title1 = document.querySelector("#gn").textContent; 193 | const title2 = document.querySelector("#gj").textContent; 194 | const cleanTitle1 = cleanBookName(title1); 195 | const cleanTitle2 = cleanBookName(title2); 196 | console.log("搜索相似:", cleanTitle1, '&', cleanTitle2); 197 | const dataList = []; 198 | const urlSet = new Set([window.location.origin + window.location.pathname]); 199 | if(cleanTitle1) { 200 | (await getDataList(cleanTitle1)).forEach(v => { 201 | if(!urlSet.has(v.href)) { 202 | dataList.push(v); 203 | urlSet.add(v.href); 204 | } 205 | }); 206 | } 207 | if(cleanTitle2) { 208 | (await getDataList(cleanTitle2)).forEach(v => { 209 | if(!urlSet.has(v.href)) { 210 | dataList.push(v); 211 | urlSet.add(v.href); 212 | } 213 | }); 214 | } 215 | 216 | dataList.sort((a,b) => a.distance - b.distance); 217 | 218 | dataList.forEach(v => { 219 | for(let lang of languages) { 220 | if(v.tags.length && v.tags.includes(`language:${lang.value}`)) { 221 | v.language = lang; 222 | break; 223 | } 224 | } 225 | if(v.language) return; 226 | 227 | // 两个循环是因为优先判断tag 228 | for(let lang of languages) { 229 | if(v.title.toLowerCase().includes(lang.value)) { 230 | v.language = lang; 231 | break; 232 | } 233 | } 234 | if(v.language) return; 235 | 236 | // 没有找到语言的 并且没翻译的默认为日语 237 | if(v.tags.length && !v.tags.includes(`language:translated`)) { 238 | v.language = languages.find(v => v.value == 'japanese'); 239 | } else { 240 | v.language = languages.find(v => v.value == 'unknown'); 241 | } 242 | }); 243 | 244 | const languageGroupMap = {}; 245 | const languageGroup = []; 246 | dataList.forEach(v => { 247 | if(!languageGroupMap[v.language.value]) { 248 | languageGroupMap[v.language.value] = {language: v.language, list: []}; 249 | languageGroup.push(languageGroupMap[v.language.value]); 250 | } 251 | languageGroupMap[v.language.value].list.push(v); 252 | }); 253 | 254 | languageGroup.sort((a,b) => { 255 | let pa = languagePriority.indexOf(a.language.value); 256 | let pb = languagePriority.indexOf(b.language.value); 257 | if(pa == -1) pa = 999; 258 | if(pb == -1) pb = 999; 259 | return pa - pb; 260 | }); 261 | 262 | const box = document.createElement('div'); 263 | box.className = `tj-box`; 264 | document.querySelector(".gm").appendChild(box); 265 | 266 | if(languageGroup.length) { 267 | box.innerHTML = languageGroup.map(group => ` 268 |
269 | 270 |
    271 | ${group.list.map(item => ` 272 |
  • 273 | ${item.title} 274 | ${item.pages} ${item.torrentHref ? `T` : ''} 275 |
  • 276 | `).join('')} 277 |
278 |
279 | `).join(''); 280 | }else { 281 | box.innerHTML = "未找到"; 282 | } 283 | console.log("dataList", dataList, languageGroup); 284 | }); 285 | -------------------------------------------------------------------------------- /EhSyringe Extension/SafariWebExtensionHandler.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SafariWebExtensionHandler.swift 3 | // EhSyringe Extension 4 | // 5 | // Created by zhaoxin on 2021/7/14. 6 | // 7 | 8 | import SafariServices 9 | import os.log 10 | 11 | class SafariWebExtensionHandler: NSObject, NSExtensionRequestHandling { 12 | 13 | func beginRequest(with context: NSExtensionContext) { 14 | let item = context.inputItems[0] as! NSExtensionItem 15 | let message = item.userInfo?[SFExtensionMessageKey] 16 | os_log(.default, "Received message from browser.runtime.sendNativeMessage: %@", message as! CVarArg) 17 | 18 | let response = NSExtensionItem() 19 | response.userInfo = [ SFExtensionMessageKey: [ "Response to": message ] ] 20 | 21 | context.completeRequest(returningItems: [response], completionHandler: nil) 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /EhSyringe.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 55; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | DC1E888B269EEFEB0008E674 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC1E888A269EEFEB0008E674 /* AppDelegate.swift */; }; 11 | DC1E888F269EEFEB0008E674 /* Main.html in Resources */ = {isa = PBXBuildFile; fileRef = DC1E888D269EEFEB0008E674 /* Main.html */; }; 12 | DC1E8891269EEFEB0008E674 /* Icon.png in Resources */ = {isa = PBXBuildFile; fileRef = DC1E8890269EEFEB0008E674 /* Icon.png */; }; 13 | DC1E8893269EEFEB0008E674 /* Style.css in Resources */ = {isa = PBXBuildFile; fileRef = DC1E8892269EEFEB0008E674 /* Style.css */; }; 14 | DC1E8895269EEFEB0008E674 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC1E8894269EEFEB0008E674 /* SceneDelegate.swift */; }; 15 | DC1E8897269EEFEB0008E674 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC1E8896269EEFEB0008E674 /* ViewController.swift */; }; 16 | DC1E889A269EEFEB0008E674 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DC1E8898269EEFEB0008E674 /* LaunchScreen.storyboard */; }; 17 | DC1E889D269EEFEB0008E674 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DC1E889B269EEFEB0008E674 /* Main.storyboard */; }; 18 | DC1E88A5269EEFEC0008E674 /* EhSyringe Extension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = DC1E88A4269EEFEC0008E674 /* EhSyringe Extension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 19 | DC1E88AA269EEFEC0008E674 /* SafariWebExtensionHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC1E88A9269EEFEC0008E674 /* SafariWebExtensionHandler.swift */; }; 20 | DC1E88AD269EEFEC0008E674 /* _locales in Resources */ = {isa = PBXBuildFile; fileRef = DC1E88AC269EEFEC0008E674 /* _locales */; }; 21 | DC1E88BD269EEFEC0008E674 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DC1E889E269EEFEC0008E674 /* Assets.xcassets */; }; 22 | DC1E88EE269EF2A20008E674 /* script in Resources */ = {isa = PBXBuildFile; fileRef = DC1E88EB269EF2A20008E674 /* script */; }; 23 | DC1E88EF269EF2A20008E674 /* manifest.json in Resources */ = {isa = PBXBuildFile; fileRef = DC1E88EC269EF2A20008E674 /* manifest.json */; }; 24 | DC1E88F0269EF2A20008E674 /* assets in Resources */ = {isa = PBXBuildFile; fileRef = DC1E88ED269EF2A20008E674 /* assets */; }; 25 | DC1E88F3269EF63A0008E674 /* userscript in Resources */ = {isa = PBXBuildFile; fileRef = DC1E88F2269EF63A0008E674 /* userscript */; }; 26 | /* End PBXBuildFile section */ 27 | 28 | /* Begin PBXContainerItemProxy section */ 29 | DC1E88A6269EEFEC0008E674 /* PBXContainerItemProxy */ = { 30 | isa = PBXContainerItemProxy; 31 | containerPortal = DC1E887F269EEFEB0008E674 /* Project object */; 32 | proxyType = 1; 33 | remoteGlobalIDString = DC1E88A3269EEFEC0008E674; 34 | remoteInfo = "EhSyringe Extension"; 35 | }; 36 | /* End PBXContainerItemProxy section */ 37 | 38 | /* Begin PBXCopyFilesBuildPhase section */ 39 | DC1E88C3269EEFEC0008E674 /* Embed App Extensions */ = { 40 | isa = PBXCopyFilesBuildPhase; 41 | buildActionMask = 2147483647; 42 | dstPath = ""; 43 | dstSubfolderSpec = 13; 44 | files = ( 45 | DC1E88A5269EEFEC0008E674 /* EhSyringe Extension.appex in Embed App Extensions */, 46 | ); 47 | name = "Embed App Extensions"; 48 | runOnlyForDeploymentPostprocessing = 0; 49 | }; 50 | /* End PBXCopyFilesBuildPhase section */ 51 | 52 | /* Begin PBXFileReference section */ 53 | DC1E8887269EEFEB0008E674 /* EhSyringe.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = EhSyringe.app; sourceTree = BUILT_PRODUCTS_DIR; }; 54 | DC1E888A269EEFEB0008E674 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 55 | DC1E888E269EEFEB0008E674 /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.html; name = Base; path = ../Base.lproj/Main.html; sourceTree = ""; }; 56 | DC1E8890269EEFEB0008E674 /* Icon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Icon.png; sourceTree = ""; }; 57 | DC1E8892269EEFEB0008E674 /* Style.css */ = {isa = PBXFileReference; lastKnownFileType = text.css; path = Style.css; sourceTree = ""; }; 58 | DC1E8894269EEFEB0008E674 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; 59 | DC1E8896269EEFEB0008E674 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 60 | DC1E8899269EEFEB0008E674 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 61 | DC1E889C269EEFEB0008E674 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 62 | DC1E889E269EEFEC0008E674 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 63 | DC1E889F269EEFEC0008E674 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 64 | DC1E88A4269EEFEC0008E674 /* EhSyringe Extension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "EhSyringe Extension.appex"; sourceTree = BUILT_PRODUCTS_DIR; }; 65 | DC1E88A9269EEFEC0008E674 /* SafariWebExtensionHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SafariWebExtensionHandler.swift; sourceTree = ""; }; 66 | DC1E88AC269EEFEC0008E674 /* _locales */ = {isa = PBXFileReference; lastKnownFileType = folder; path = _locales; sourceTree = ""; }; 67 | DC1E88BC269EEFEC0008E674 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 68 | DC1E88EB269EF2A20008E674 /* script */ = {isa = PBXFileReference; lastKnownFileType = folder; path = script; sourceTree = ""; }; 69 | DC1E88EC269EF2A20008E674 /* manifest.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = manifest.json; sourceTree = ""; }; 70 | DC1E88ED269EF2A20008E674 /* assets */ = {isa = PBXFileReference; lastKnownFileType = folder; path = assets; sourceTree = ""; }; 71 | DC1E88F2269EF63A0008E674 /* userscript */ = {isa = PBXFileReference; lastKnownFileType = folder; path = userscript; sourceTree = ""; }; 72 | /* End PBXFileReference section */ 73 | 74 | /* Begin PBXFrameworksBuildPhase section */ 75 | DC1E8884269EEFEB0008E674 /* Frameworks */ = { 76 | isa = PBXFrameworksBuildPhase; 77 | buildActionMask = 2147483647; 78 | files = ( 79 | ); 80 | runOnlyForDeploymentPostprocessing = 0; 81 | }; 82 | DC1E88A1269EEFEC0008E674 /* Frameworks */ = { 83 | isa = PBXFrameworksBuildPhase; 84 | buildActionMask = 2147483647; 85 | files = ( 86 | ); 87 | runOnlyForDeploymentPostprocessing = 0; 88 | }; 89 | /* End PBXFrameworksBuildPhase section */ 90 | 91 | /* Begin PBXGroup section */ 92 | DC1E887E269EEFEB0008E674 = { 93 | isa = PBXGroup; 94 | children = ( 95 | DC1E8889269EEFEB0008E674 /* EhSyringe */, 96 | DC1E88A8269EEFEC0008E674 /* EhSyringe Extension */, 97 | DC1E8888269EEFEB0008E674 /* Products */, 98 | ); 99 | sourceTree = ""; 100 | }; 101 | DC1E8888269EEFEB0008E674 /* Products */ = { 102 | isa = PBXGroup; 103 | children = ( 104 | DC1E8887269EEFEB0008E674 /* EhSyringe.app */, 105 | DC1E88A4269EEFEC0008E674 /* EhSyringe Extension.appex */, 106 | ); 107 | name = Products; 108 | sourceTree = ""; 109 | }; 110 | DC1E8889269EEFEB0008E674 /* EhSyringe */ = { 111 | isa = PBXGroup; 112 | children = ( 113 | DC1E888A269EEFEB0008E674 /* AppDelegate.swift */, 114 | DC1E8894269EEFEB0008E674 /* SceneDelegate.swift */, 115 | DC1E8896269EEFEB0008E674 /* ViewController.swift */, 116 | DC1E8898269EEFEB0008E674 /* LaunchScreen.storyboard */, 117 | DC1E889B269EEFEB0008E674 /* Main.storyboard */, 118 | DC1E889E269EEFEC0008E674 /* Assets.xcassets */, 119 | DC1E889F269EEFEC0008E674 /* Info.plist */, 120 | DC1E888C269EEFEB0008E674 /* Resources */, 121 | ); 122 | path = EhSyringe; 123 | sourceTree = ""; 124 | }; 125 | DC1E888C269EEFEB0008E674 /* Resources */ = { 126 | isa = PBXGroup; 127 | children = ( 128 | DC1E888D269EEFEB0008E674 /* Main.html */, 129 | DC1E8890269EEFEB0008E674 /* Icon.png */, 130 | DC1E8892269EEFEB0008E674 /* Style.css */, 131 | ); 132 | path = Resources; 133 | sourceTree = ""; 134 | }; 135 | DC1E88A8269EEFEC0008E674 /* EhSyringe Extension */ = { 136 | isa = PBXGroup; 137 | children = ( 138 | DC1E88A9269EEFEC0008E674 /* SafariWebExtensionHandler.swift */, 139 | DC1E88BC269EEFEC0008E674 /* Info.plist */, 140 | DC1E88AB269EEFEC0008E674 /* Resources */, 141 | ); 142 | path = "EhSyringe Extension"; 143 | sourceTree = ""; 144 | }; 145 | DC1E88AB269EEFEC0008E674 /* Resources */ = { 146 | isa = PBXGroup; 147 | children = ( 148 | DC1E88F2269EF63A0008E674 /* userscript */, 149 | DC1E88ED269EF2A20008E674 /* assets */, 150 | DC1E88EC269EF2A20008E674 /* manifest.json */, 151 | DC1E88EB269EF2A20008E674 /* script */, 152 | DC1E88AC269EEFEC0008E674 /* _locales */, 153 | ); 154 | path = Resources; 155 | sourceTree = ""; 156 | }; 157 | /* End PBXGroup section */ 158 | 159 | /* Begin PBXNativeTarget section */ 160 | DC1E8886269EEFEB0008E674 /* EhSyringe */ = { 161 | isa = PBXNativeTarget; 162 | buildConfigurationList = DC1E88C4269EEFEC0008E674 /* Build configuration list for PBXNativeTarget "EhSyringe" */; 163 | buildPhases = ( 164 | DC1E8883269EEFEB0008E674 /* Sources */, 165 | DC1E8884269EEFEB0008E674 /* Frameworks */, 166 | DC1E8885269EEFEB0008E674 /* Resources */, 167 | DC1E88C3269EEFEC0008E674 /* Embed App Extensions */, 168 | ); 169 | buildRules = ( 170 | ); 171 | dependencies = ( 172 | DC1E88A7269EEFEC0008E674 /* PBXTargetDependency */, 173 | ); 174 | name = EhSyringe; 175 | productName = EhSyringe; 176 | productReference = DC1E8887269EEFEB0008E674 /* EhSyringe.app */; 177 | productType = "com.apple.product-type.application"; 178 | }; 179 | DC1E88A3269EEFEC0008E674 /* EhSyringe Extension */ = { 180 | isa = PBXNativeTarget; 181 | buildConfigurationList = DC1E88C0269EEFEC0008E674 /* Build configuration list for PBXNativeTarget "EhSyringe Extension" */; 182 | buildPhases = ( 183 | DC1E88A0269EEFEC0008E674 /* Sources */, 184 | DC1E88A1269EEFEC0008E674 /* Frameworks */, 185 | DC1E88A2269EEFEC0008E674 /* Resources */, 186 | ); 187 | buildRules = ( 188 | ); 189 | dependencies = ( 190 | ); 191 | name = "EhSyringe Extension"; 192 | productName = "EhSyringe Extension"; 193 | productReference = DC1E88A4269EEFEC0008E674 /* EhSyringe Extension.appex */; 194 | productType = "com.apple.product-type.app-extension"; 195 | }; 196 | /* End PBXNativeTarget section */ 197 | 198 | /* Begin PBXProject section */ 199 | DC1E887F269EEFEB0008E674 /* Project object */ = { 200 | isa = PBXProject; 201 | attributes = { 202 | BuildIndependentTargetsInParallel = 1; 203 | LastSwiftUpdateCheck = 1300; 204 | LastUpgradeCheck = 1300; 205 | TargetAttributes = { 206 | DC1E8886269EEFEB0008E674 = { 207 | CreatedOnToolsVersion = 13.0; 208 | }; 209 | DC1E88A3269EEFEC0008E674 = { 210 | CreatedOnToolsVersion = 13.0; 211 | }; 212 | }; 213 | }; 214 | buildConfigurationList = DC1E8882269EEFEB0008E674 /* Build configuration list for PBXProject "EhSyringe" */; 215 | compatibilityVersion = "Xcode 13.0"; 216 | developmentRegion = en; 217 | hasScannedForEncodings = 0; 218 | knownRegions = ( 219 | en, 220 | Base, 221 | ); 222 | mainGroup = DC1E887E269EEFEB0008E674; 223 | productRefGroup = DC1E8888269EEFEB0008E674 /* Products */; 224 | projectDirPath = ""; 225 | projectRoot = ""; 226 | targets = ( 227 | DC1E8886269EEFEB0008E674 /* EhSyringe */, 228 | DC1E88A3269EEFEC0008E674 /* EhSyringe Extension */, 229 | ); 230 | }; 231 | /* End PBXProject section */ 232 | 233 | /* Begin PBXResourcesBuildPhase section */ 234 | DC1E8885269EEFEB0008E674 /* Resources */ = { 235 | isa = PBXResourcesBuildPhase; 236 | buildActionMask = 2147483647; 237 | files = ( 238 | DC1E8891269EEFEB0008E674 /* Icon.png in Resources */, 239 | DC1E889D269EEFEB0008E674 /* Main.storyboard in Resources */, 240 | DC1E889A269EEFEB0008E674 /* LaunchScreen.storyboard in Resources */, 241 | DC1E888F269EEFEB0008E674 /* Main.html in Resources */, 242 | DC1E88BD269EEFEC0008E674 /* Assets.xcassets in Resources */, 243 | DC1E8893269EEFEB0008E674 /* Style.css in Resources */, 244 | ); 245 | runOnlyForDeploymentPostprocessing = 0; 246 | }; 247 | DC1E88A2269EEFEC0008E674 /* Resources */ = { 248 | isa = PBXResourcesBuildPhase; 249 | buildActionMask = 2147483647; 250 | files = ( 251 | DC1E88F3269EF63A0008E674 /* userscript in Resources */, 252 | DC1E88AD269EEFEC0008E674 /* _locales in Resources */, 253 | DC1E88F0269EF2A20008E674 /* assets in Resources */, 254 | DC1E88EF269EF2A20008E674 /* manifest.json in Resources */, 255 | DC1E88EE269EF2A20008E674 /* script in Resources */, 256 | ); 257 | runOnlyForDeploymentPostprocessing = 0; 258 | }; 259 | /* End PBXResourcesBuildPhase section */ 260 | 261 | /* Begin PBXSourcesBuildPhase section */ 262 | DC1E8883269EEFEB0008E674 /* Sources */ = { 263 | isa = PBXSourcesBuildPhase; 264 | buildActionMask = 2147483647; 265 | files = ( 266 | DC1E8897269EEFEB0008E674 /* ViewController.swift in Sources */, 267 | DC1E888B269EEFEB0008E674 /* AppDelegate.swift in Sources */, 268 | DC1E8895269EEFEB0008E674 /* SceneDelegate.swift in Sources */, 269 | ); 270 | runOnlyForDeploymentPostprocessing = 0; 271 | }; 272 | DC1E88A0269EEFEC0008E674 /* Sources */ = { 273 | isa = PBXSourcesBuildPhase; 274 | buildActionMask = 2147483647; 275 | files = ( 276 | DC1E88AA269EEFEC0008E674 /* SafariWebExtensionHandler.swift in Sources */, 277 | ); 278 | runOnlyForDeploymentPostprocessing = 0; 279 | }; 280 | /* End PBXSourcesBuildPhase section */ 281 | 282 | /* Begin PBXTargetDependency section */ 283 | DC1E88A7269EEFEC0008E674 /* PBXTargetDependency */ = { 284 | isa = PBXTargetDependency; 285 | target = DC1E88A3269EEFEC0008E674 /* EhSyringe Extension */; 286 | targetProxy = DC1E88A6269EEFEC0008E674 /* PBXContainerItemProxy */; 287 | }; 288 | /* End PBXTargetDependency section */ 289 | 290 | /* Begin PBXVariantGroup section */ 291 | DC1E888D269EEFEB0008E674 /* Main.html */ = { 292 | isa = PBXVariantGroup; 293 | children = ( 294 | DC1E888E269EEFEB0008E674 /* Base */, 295 | ); 296 | name = Main.html; 297 | sourceTree = ""; 298 | }; 299 | DC1E8898269EEFEB0008E674 /* LaunchScreen.storyboard */ = { 300 | isa = PBXVariantGroup; 301 | children = ( 302 | DC1E8899269EEFEB0008E674 /* Base */, 303 | ); 304 | name = LaunchScreen.storyboard; 305 | sourceTree = ""; 306 | }; 307 | DC1E889B269EEFEB0008E674 /* Main.storyboard */ = { 308 | isa = PBXVariantGroup; 309 | children = ( 310 | DC1E889C269EEFEB0008E674 /* Base */, 311 | ); 312 | name = Main.storyboard; 313 | sourceTree = ""; 314 | }; 315 | /* End PBXVariantGroup section */ 316 | 317 | /* Begin XCBuildConfiguration section */ 318 | DC1E88BE269EEFEC0008E674 /* Debug */ = { 319 | isa = XCBuildConfiguration; 320 | buildSettings = { 321 | ALWAYS_SEARCH_USER_PATHS = NO; 322 | CLANG_ANALYZER_NONNULL = YES; 323 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 324 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 325 | CLANG_CXX_LIBRARY = "libc++"; 326 | CLANG_ENABLE_MODULES = YES; 327 | CLANG_ENABLE_OBJC_ARC = YES; 328 | CLANG_ENABLE_OBJC_WEAK = YES; 329 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 330 | CLANG_WARN_BOOL_CONVERSION = YES; 331 | CLANG_WARN_COMMA = YES; 332 | CLANG_WARN_CONSTANT_CONVERSION = YES; 333 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 334 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 335 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 336 | CLANG_WARN_EMPTY_BODY = YES; 337 | CLANG_WARN_ENUM_CONVERSION = YES; 338 | CLANG_WARN_INFINITE_RECURSION = YES; 339 | CLANG_WARN_INT_CONVERSION = YES; 340 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 341 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 342 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 343 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 344 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 345 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 346 | CLANG_WARN_STRICT_PROTOTYPES = YES; 347 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 348 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 349 | CLANG_WARN_UNREACHABLE_CODE = YES; 350 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 351 | COPY_PHASE_STRIP = NO; 352 | DEBUG_INFORMATION_FORMAT = dwarf; 353 | ENABLE_STRICT_OBJC_MSGSEND = YES; 354 | ENABLE_TESTABILITY = YES; 355 | GCC_C_LANGUAGE_STANDARD = gnu11; 356 | GCC_DYNAMIC_NO_PIC = NO; 357 | GCC_NO_COMMON_BLOCKS = YES; 358 | GCC_OPTIMIZATION_LEVEL = 0; 359 | GCC_PREPROCESSOR_DEFINITIONS = ( 360 | "DEBUG=1", 361 | "$(inherited)", 362 | ); 363 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 364 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 365 | GCC_WARN_UNDECLARED_SELECTOR = YES; 366 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 367 | GCC_WARN_UNUSED_FUNCTION = YES; 368 | GCC_WARN_UNUSED_VARIABLE = YES; 369 | IPHONEOS_DEPLOYMENT_TARGET = 15.0; 370 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 371 | MTL_FAST_MATH = YES; 372 | ONLY_ACTIVE_ARCH = YES; 373 | SDKROOT = iphoneos; 374 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 375 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 376 | }; 377 | name = Debug; 378 | }; 379 | DC1E88BF269EEFEC0008E674 /* Release */ = { 380 | isa = XCBuildConfiguration; 381 | buildSettings = { 382 | ALWAYS_SEARCH_USER_PATHS = NO; 383 | CLANG_ANALYZER_NONNULL = YES; 384 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 385 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 386 | CLANG_CXX_LIBRARY = "libc++"; 387 | CLANG_ENABLE_MODULES = YES; 388 | CLANG_ENABLE_OBJC_ARC = YES; 389 | CLANG_ENABLE_OBJC_WEAK = YES; 390 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 391 | CLANG_WARN_BOOL_CONVERSION = YES; 392 | CLANG_WARN_COMMA = YES; 393 | CLANG_WARN_CONSTANT_CONVERSION = YES; 394 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 395 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 396 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 397 | CLANG_WARN_EMPTY_BODY = YES; 398 | CLANG_WARN_ENUM_CONVERSION = YES; 399 | CLANG_WARN_INFINITE_RECURSION = YES; 400 | CLANG_WARN_INT_CONVERSION = YES; 401 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 402 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 403 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 404 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 405 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 406 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 407 | CLANG_WARN_STRICT_PROTOTYPES = YES; 408 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 409 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 410 | CLANG_WARN_UNREACHABLE_CODE = YES; 411 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 412 | COPY_PHASE_STRIP = NO; 413 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 414 | ENABLE_NS_ASSERTIONS = NO; 415 | ENABLE_STRICT_OBJC_MSGSEND = YES; 416 | GCC_C_LANGUAGE_STANDARD = gnu11; 417 | GCC_NO_COMMON_BLOCKS = YES; 418 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 419 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 420 | GCC_WARN_UNDECLARED_SELECTOR = YES; 421 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 422 | GCC_WARN_UNUSED_FUNCTION = YES; 423 | GCC_WARN_UNUSED_VARIABLE = YES; 424 | IPHONEOS_DEPLOYMENT_TARGET = 15.0; 425 | MTL_ENABLE_DEBUG_INFO = NO; 426 | MTL_FAST_MATH = YES; 427 | SDKROOT = iphoneos; 428 | SWIFT_COMPILATION_MODE = wholemodule; 429 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 430 | VALIDATE_PRODUCT = YES; 431 | }; 432 | name = Release; 433 | }; 434 | DC1E88C1269EEFEC0008E674 /* Debug */ = { 435 | isa = XCBuildConfiguration; 436 | buildSettings = { 437 | CODE_SIGN_STYLE = Automatic; 438 | CURRENT_PROJECT_VERSION = 1; 439 | DEVELOPMENT_TEAM = N8JMN6858M; 440 | GENERATE_INFOPLIST_FILE = YES; 441 | INFOPLIST_FILE = "EhSyringe Extension/Info.plist"; 442 | INFOPLIST_KEY_CFBundleDisplayName = "EhSyringe Extension"; 443 | INFOPLIST_KEY_NSHumanReadableCopyright = ""; 444 | IPHONEOS_DEPLOYMENT_TARGET = 15.0; 445 | LD_RUNPATH_SEARCH_PATHS = ( 446 | "$(inherited)", 447 | "@executable_path/Frameworks", 448 | "@executable_path/../../Frameworks", 449 | ); 450 | MARKETING_VERSION = 1.0; 451 | PRODUCT_BUNDLE_IDENTIFIER = com.EhTagTranslation.EhSyringe.Extension; 452 | PRODUCT_NAME = "$(TARGET_NAME)"; 453 | SKIP_INSTALL = YES; 454 | SWIFT_EMIT_LOC_STRINGS = YES; 455 | SWIFT_VERSION = 5.0; 456 | TARGETED_DEVICE_FAMILY = "1,2"; 457 | }; 458 | name = Debug; 459 | }; 460 | DC1E88C2269EEFEC0008E674 /* Release */ = { 461 | isa = XCBuildConfiguration; 462 | buildSettings = { 463 | CODE_SIGN_STYLE = Automatic; 464 | CURRENT_PROJECT_VERSION = 1; 465 | DEVELOPMENT_TEAM = N8JMN6858M; 466 | GENERATE_INFOPLIST_FILE = YES; 467 | INFOPLIST_FILE = "EhSyringe Extension/Info.plist"; 468 | INFOPLIST_KEY_CFBundleDisplayName = "EhSyringe Extension"; 469 | INFOPLIST_KEY_NSHumanReadableCopyright = ""; 470 | IPHONEOS_DEPLOYMENT_TARGET = 15.0; 471 | LD_RUNPATH_SEARCH_PATHS = ( 472 | "$(inherited)", 473 | "@executable_path/Frameworks", 474 | "@executable_path/../../Frameworks", 475 | ); 476 | MARKETING_VERSION = 1.0; 477 | PRODUCT_BUNDLE_IDENTIFIER = com.EhTagTranslation.EhSyringe.Extension; 478 | PRODUCT_NAME = "$(TARGET_NAME)"; 479 | SKIP_INSTALL = YES; 480 | SWIFT_EMIT_LOC_STRINGS = YES; 481 | SWIFT_VERSION = 5.0; 482 | TARGETED_DEVICE_FAMILY = "1,2"; 483 | }; 484 | name = Release; 485 | }; 486 | DC1E88C5269EEFEC0008E674 /* Debug */ = { 487 | isa = XCBuildConfiguration; 488 | buildSettings = { 489 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 490 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 491 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 492 | CODE_SIGN_STYLE = Automatic; 493 | CURRENT_PROJECT_VERSION = 1; 494 | DEVELOPMENT_TEAM = N8JMN6858M; 495 | GENERATE_INFOPLIST_FILE = YES; 496 | INFOPLIST_FILE = EhSyringe/Info.plist; 497 | INFOPLIST_KEY_CFBundleDisplayName = EhSyringe; 498 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; 499 | INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; 500 | INFOPLIST_KEY_UIMainStoryboardFile = Main; 501 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 502 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 503 | IPHONEOS_DEPLOYMENT_TARGET = 15.0; 504 | LD_RUNPATH_SEARCH_PATHS = ( 505 | "$(inherited)", 506 | "@executable_path/Frameworks", 507 | ); 508 | MARKETING_VERSION = 1.0; 509 | OTHER_LDFLAGS = ( 510 | "-framework", 511 | WebKit, 512 | ); 513 | PRODUCT_BUNDLE_IDENTIFIER = com.EhTagTranslation.EhSyringe; 514 | PRODUCT_NAME = "$(TARGET_NAME)"; 515 | SWIFT_EMIT_LOC_STRINGS = YES; 516 | SWIFT_VERSION = 5.0; 517 | TARGETED_DEVICE_FAMILY = "1,2"; 518 | }; 519 | name = Debug; 520 | }; 521 | DC1E88C6269EEFEC0008E674 /* Release */ = { 522 | isa = XCBuildConfiguration; 523 | buildSettings = { 524 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 525 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 526 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 527 | CODE_SIGN_STYLE = Automatic; 528 | CURRENT_PROJECT_VERSION = 1; 529 | DEVELOPMENT_TEAM = N8JMN6858M; 530 | GENERATE_INFOPLIST_FILE = YES; 531 | INFOPLIST_FILE = EhSyringe/Info.plist; 532 | INFOPLIST_KEY_CFBundleDisplayName = EhSyringe; 533 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; 534 | INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; 535 | INFOPLIST_KEY_UIMainStoryboardFile = Main; 536 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 537 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 538 | IPHONEOS_DEPLOYMENT_TARGET = 15.0; 539 | LD_RUNPATH_SEARCH_PATHS = ( 540 | "$(inherited)", 541 | "@executable_path/Frameworks", 542 | ); 543 | MARKETING_VERSION = 1.0; 544 | OTHER_LDFLAGS = ( 545 | "-framework", 546 | WebKit, 547 | ); 548 | PRODUCT_BUNDLE_IDENTIFIER = com.EhTagTranslation.EhSyringe; 549 | PRODUCT_NAME = "$(TARGET_NAME)"; 550 | SWIFT_EMIT_LOC_STRINGS = YES; 551 | SWIFT_VERSION = 5.0; 552 | TARGETED_DEVICE_FAMILY = "1,2"; 553 | }; 554 | name = Release; 555 | }; 556 | /* End XCBuildConfiguration section */ 557 | 558 | /* Begin XCConfigurationList section */ 559 | DC1E8882269EEFEB0008E674 /* Build configuration list for PBXProject "EhSyringe" */ = { 560 | isa = XCConfigurationList; 561 | buildConfigurations = ( 562 | DC1E88BE269EEFEC0008E674 /* Debug */, 563 | DC1E88BF269EEFEC0008E674 /* Release */, 564 | ); 565 | defaultConfigurationIsVisible = 0; 566 | defaultConfigurationName = Release; 567 | }; 568 | DC1E88C0269EEFEC0008E674 /* Build configuration list for PBXNativeTarget "EhSyringe Extension" */ = { 569 | isa = XCConfigurationList; 570 | buildConfigurations = ( 571 | DC1E88C1269EEFEC0008E674 /* Debug */, 572 | DC1E88C2269EEFEC0008E674 /* Release */, 573 | ); 574 | defaultConfigurationIsVisible = 0; 575 | defaultConfigurationName = Release; 576 | }; 577 | DC1E88C4269EEFEC0008E674 /* Build configuration list for PBXNativeTarget "EhSyringe" */ = { 578 | isa = XCConfigurationList; 579 | buildConfigurations = ( 580 | DC1E88C5269EEFEC0008E674 /* Debug */, 581 | DC1E88C6269EEFEC0008E674 /* Release */, 582 | ); 583 | defaultConfigurationIsVisible = 0; 584 | defaultConfigurationName = Release; 585 | }; 586 | /* End XCConfigurationList section */ 587 | }; 588 | rootObject = DC1E887F269EEFEB0008E674 /* Project object */; 589 | } 590 | -------------------------------------------------------------------------------- /EhSyringe.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /EhSyringe.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /EhSyringe.xcodeproj/xcuserdata/zhaoxin.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | EhSyringe.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /EhSyringe/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // EhSyringe 4 | // 5 | // Created by zhaoxin on 2021/7/14. 6 | // 7 | 8 | import UIKit 9 | 10 | @main 11 | class AppDelegate: UIResponder, UIApplicationDelegate { 12 | 13 | var window: UIWindow? 14 | 15 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 16 | // Override point for customization after application launch. 17 | return true 18 | } 19 | 20 | func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { 21 | return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /EhSyringe/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /EhSyringe/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "scale" : "2x", 6 | "size" : "20x20" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "scale" : "3x", 11 | "size" : "20x20" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "scale" : "2x", 16 | "size" : "29x29" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "scale" : "3x", 21 | "size" : "29x29" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "scale" : "2x", 26 | "size" : "40x40" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "scale" : "3x", 31 | "size" : "40x40" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "scale" : "2x", 36 | "size" : "60x60" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "scale" : "3x", 41 | "size" : "60x60" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "scale" : "1x", 46 | "size" : "20x20" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "scale" : "2x", 51 | "size" : "20x20" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "scale" : "1x", 56 | "size" : "29x29" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "scale" : "2x", 61 | "size" : "29x29" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "scale" : "1x", 66 | "size" : "40x40" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "scale" : "2x", 71 | "size" : "40x40" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "scale" : "1x", 76 | "size" : "76x76" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "scale" : "2x", 81 | "size" : "76x76" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "scale" : "2x", 86 | "size" : "83.5x83.5" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "scale" : "1x", 91 | "size" : "1024x1024" 92 | } 93 | ], 94 | "info" : { 95 | "author" : "xcode", 96 | "version" : 1 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /EhSyringe/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /EhSyringe/Assets.xcassets/LargeIcon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "universal", 13 | "scale" : "3x" 14 | } 15 | ], 16 | "info" : { 17 | "author" : "xcode", 18 | "version" : 1 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /EhSyringe/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /EhSyringe/Base.lproj/Main.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | EhSyringe Icon 13 |

You can turn on EhSyringe’s Safari extension in Settings.

14 | 15 | 16 | -------------------------------------------------------------------------------- /EhSyringe/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /EhSyringe/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | UIApplicationSceneManifest 6 | 7 | UIApplicationSupportsMultipleScenes 8 | 9 | UISceneConfigurations 10 | 11 | UIWindowSceneSessionRoleApplication 12 | 13 | 14 | UISceneConfigurationName 15 | Default Configuration 16 | UISceneDelegateClassName 17 | $(PRODUCT_MODULE_NAME).SceneDelegate 18 | UISceneStoryboardFile 19 | Main 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /EhSyringe/Resources/Icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EhTagTranslation/EhSyringeSafariExtensionApp/d09f6e1875202fe80d94c8c1d7897da9e42f5b4f/EhSyringe/Resources/Icon.png -------------------------------------------------------------------------------- /EhSyringe/Resources/Style.css: -------------------------------------------------------------------------------- 1 | * { 2 | -webkit-user-select: none; 3 | -webkit-user-drag: none; 4 | cursor: default; 5 | } 6 | 7 | :root { 8 | color-scheme: light dark; 9 | 10 | --spacing: 20px; 11 | } 12 | 13 | html { 14 | height: 100%; 15 | } 16 | 17 | body { 18 | display: flex; 19 | align-items: center; 20 | justify-content: center; 21 | flex-direction: column; 22 | 23 | gap: var(--spacing); 24 | margin: 0 calc(var(--spacing) * 2); 25 | height: 100%; 26 | 27 | font: -apple-system-short-body; 28 | text-align: center; 29 | } 30 | -------------------------------------------------------------------------------- /EhSyringe/SceneDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SceneDelegate.swift 3 | // EhSyringe 4 | // 5 | // Created by zhaoxin on 2021/7/14. 6 | // 7 | 8 | import UIKit 9 | 10 | class SceneDelegate: UIResponder, UIWindowSceneDelegate { 11 | 12 | var window: UIWindow? 13 | 14 | func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { 15 | guard let _ = (scene as? UIWindowScene) else { return } 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /EhSyringe/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // EhSyringe 4 | // 5 | // Created by zhaoxin on 2021/7/14. 6 | // 7 | 8 | import UIKit 9 | import WebKit 10 | 11 | class ViewController: UIViewController, WKNavigationDelegate, WKScriptMessageHandler { 12 | 13 | @IBOutlet var webView: WKWebView! 14 | 15 | override func viewDidLoad() { 16 | super.viewDidLoad() 17 | 18 | self.webView.navigationDelegate = self 19 | self.webView.scrollView.isScrollEnabled = false 20 | 21 | self.webView.configuration.userContentController.add(self, name: "controller") 22 | 23 | self.webView.loadFileURL(Bundle.main.url(forResource: "Main", withExtension: "html")!, allowingReadAccessTo: Bundle.main.resourceURL!) 24 | } 25 | 26 | func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { 27 | // Override point for customization. 28 | } 29 | 30 | func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) { 31 | // Override point for customization. 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # EhSyringeSafariExtensionApp 2 | 3 | 4 | ## 本项目不再更新 5 | > 目前iOS平台已经有可用的UserScript插件
6 | > 请直接安装类似插件,通过插件安装EhSyringe
7 | > 目前可用的UserScript插件: https://github.com/quoid/userscripts#installation 8 | 9 | 10 | 11 | iOS15开始支持浏览器扩展,未来可以使用altstore.io进行安装。 12 | 13 | ### TODO 14 | * [ ] 直接嵌入EhSyringe是临时的方案,改为引用EhSyringe原始代码而不需要维护两套。 15 | * [ ] 修改图标风格以匹配Safari风格,并增加更大的尺寸。 16 | * [ ] 增加 UserScript 相关支持。因为目前iOS版本的Safari暂不支持Tampermonkey。 17 | 18 | ### 预览 19 | ![IMG_0073](https://user-images.githubusercontent.com/5716100/125611943-1c7a4025-c817-486c-b651-724d219e6bda.PNG) 20 | ![IMG_0074](https://user-images.githubusercontent.com/5716100/125611951-46e5f781-3b78-4666-84f6-34f70e5ef32c.PNG) 21 | ![IMG_0075](https://user-images.githubusercontent.com/5716100/125611974-ccc5ecff-342b-45b8-8c3d-f91f9caf6af9.PNG) 22 | --------------------------------------------------------------------------------