├── 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 |
--------------------------------------------------------------------------------
/EhSyringe Extension/Resources/assets/logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/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 ? `
` : ''}
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 |
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 | 
20 | 
21 | 
22 |
--------------------------------------------------------------------------------