diff --git a/darkreader/darkreader.min.js b/darkreader/darkreader.min.js new file mode 100644 index 00000000..ef40168c --- /dev/null +++ b/darkreader/darkreader.min.js @@ -0,0 +1 @@ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).DarkReader={})}(this,function(e){"use strict";var u,d=function(){return(d=Object.assign||function(e){for(var t,n=1,r=arguments.length;nc[0]&&t[1]=e.length?void 0:e)&&e[r++],done:!e}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")}function j(e,t){var n="function"==typeof Symbol&&e[Symbol.iterator];if(!n)return e;var r,o,a=n.call(e),i=[];try{for(;(void 0===t||0 Promise))`.","See if using `DarkReader.setFetchMethod(window.fetch)`","before `DarkReader.enable()` works."].join(" ")))]})})}var z=$;window.chrome||(window.chrome={}),chrome.runtime||(chrome.runtime={});var Q,K,Y,X,Z=new Set;function J(){for(var c=[],e=0;e>16&255,g:e>>8&255,b:e>>0&255,a:1}}(t);if(Je.has(t))return function(e){e=Je.get(e);return{r:e>>16&255,g:e>>8&255,b:e>>0&255,a:1}}(t);return"transparent"!==e?null:{r:0,g:0,b:0,a:0}}(e=e.includes("calc(")?function(r){var e=0;for(;-1!==(e=r.indexOf("calc("));){var t=Ne(r,e);if(!t)break;var n=r.slice(t.start+1,t.end-1),o=n.includes("%"),n=(n=n.split("%").join(""),Math.round(function(e){for(var t,n=[],r=[],o=0,a=e.length;o=n.frameDuration){n.startQueue();break}}))};var At=new Vt;function Mt(i){return N(this,void 0,void 0,function(){var t=this;return F(this,function(e){return[2,new Promise(function(o,a){return N(t,void 0,void 0,function(){var t,n,r;return F(this,function(e){switch(e.label){case 0:return i.startsWith("data:")?(t=i,[3,4]):[3,1];case 1:return e.trys.push([1,3,,4]),[4,function(t){return N(this,void 0,void 0,function(){return F(this,function(e){switch(e.label){case 0:return new URL(t).origin!==location.origin?[3,2]:[4,G(t)];case 1:return[2,e.sent()];case 2:return[4,Rt({url:t,responseType:"data-url"})];case 3:return[2,e.sent()]}})})}(i)];case 2:return t=e.sent(),[3,4];case 3:return r=e.sent(),a(r),[2];case 4:return e.trys.push([4,6,,7]),[4,function(r){return N(this,void 0,void 0,function(){return F(this,function(e){return[2,new Promise(function(e,t){var n=new Image;n.onload=function(){return e(n)},n.onerror=function(){return t("Unable to load image ".concat(r))},n.src=r})]})})}(t)];case 5:return n=e.sent(),At.addToQueue(function(){o(d({src:i,dataURL:t,width:n.naturalWidth,height:n.naturalHeight},function(e){Lt||!function(){var e=Dt,t=Dt;(Lt=document.createElement("canvas")).width=e,Lt.height=t,(Ot=Lt.getContext("2d")).imageSmoothingEnabled=!1}();var t=e.naturalWidth,n=e.naturalHeight;if(0===n||0===t)return"logWarn(Image is empty ".concat(e.currentSrc,")"),null;if(Pt'),"",'',''),"","",''),""].join("");return"data:image/svg+xml;base64,".concat(btoa(t))}function Nt(){At&&At.stopQueue(),Ot=Lt=null}var Ft="gradient".length,jt="conic-",Bt=jt.length,qt="radial-",Ut="linear-";function Wt(r){for(var o,a=[],i=jt.length;-1!==(o=r.indexOf("gradient",i))&&"break"!==function(){var t;if([Ut,qt,jt].find(function(e){if(0<=o-e.length&&r.substring(o-e.length,o)===e)return t=("repeating"===r.slice(o-e.length-10,o-e.length-1)?"repeating-":"-webkit"===r.slice(o-e.length-8,o-e.length-1)?"-webkit-":"").concat(e,"gradient"),!0}),!t)return"break";var e=Ne(r,o+Ft),n=e.start,e=e.end,n=r.substring(n+1,e-1);i=e+1+Bt,a.push({typeGradient:t,match:n,offset:t.length+2,index:o-t.length+Ft,hasComma:!0})}(););return a.length&&(a[a.length-1].hasComma=!1),a}function Gt(e,t){return Boolean(e&&e.getPropertyPriority(t))}function Ht(e,t,n,r,o,a){var i,c;if(e.startsWith("--")){if(i=r.getModifierForVariable({varName:e,sourceValue:t,rule:n,ignoredImgSelectors:o,isCancelled:a}))return{property:e,value:i,important:Gt(n.style,e),sourceValue:t}}else if(t.includes("var(")){if(i=r.getModifierForVarDependant(e,t))return{property:e,value:i,important:Gt(n.style,e),sourceValue:t}}else{if("color-scheme"===e)return null;if(e.includes("color")&&"-webkit-print-color-adjust"!==e||"fill"===e||"stroke"===e||"stop-color"===e){if(i=function(e,t,n){if(Yt.has(t.toLowerCase()))return t;var r=E(t);if(!r)return null;if(e.includes("background"))return n.style.webkitMaskImage&&"none"!==n.style.webkitMaskImage||n.style.webkitMask&&!n.style.webkitMask.startsWith("none")||n.style.mask&&"none"!==n.style.mask||n.style.getPropertyValue("mask-image")&&"none"!==n.style.getPropertyValue("mask-image")?function(e){return v(r,e)}:function(e){return g(r,e)};if(e.includes("border")||e.includes("outline"))return function(e){return kt(r,e)};return function(e){return v(r,e)}}(e,t,n))return{property:e,value:i,important:Gt(n.style,e),sourceValue:t}}else if("background-image"===e||"list-style-image"===e){if(i=Jt(t,n,o,a))return{property:e,value:i,important:Gt(n.style,e),sourceValue:t}}else if(e.includes("shadow"))if(i=(c=en(t))?function(e){return c(e).result}:null)return{property:e,value:i,important:Gt(n.style,e),sourceValue:t}}return null}function $t(){for(var e=[],t=0;t :not(iframe)"," {")),n.push(" background-color: ".concat(g({r:255,g:255,b:255},e)," !important;")),n.push(" border-color: ".concat(kt({r:64,g:64,b:64},e)," !important;")),n.push(" color: ".concat(v({r:0,g:0,b:0},e)," !important;")),n.push("}"),n.join("\n")}var Yt=new Set(["inherit","transparent","initial","currentcolor","none","unset"]);var Xt=new Map,x=new Map;function Zt(e,n){if(e&&0!==n.length){if(n.some(function(e){return"*"===e}))return 1;for(var r=e.split(/,\s*/g),t=0;tt.index?1:-1}),S=function(e,t){var n=e.isDark,r=e.isLight,o=e.isTransparent,a=e.isLarge,i=e.isTooLarge,c=e.width;return i?'url("'.concat(e.src,'")'):n&&o&&1===t.mode&&!a&&2 + +You can then enable it in your front end js files like so: + +DarkReader.enable({ + brightness: 100, + contrast: 90, + sepia: 10 +}) + +You can also disable it like so: + +DarkReader.disable() + +The main use I have found for this, however, is not to src this file, but rather to utilize it to generate +dark mode versions of personal sites using its exportGeneratedCSS() function: + +const CSS = await DarkReader.exportGeneratedCSS() +console.log(CSS) + +copying this from the console into a ./styles/darkreader.css file and then href from a link tag in your main css file allows you to have a baseline dark mode from which to further work on: + +// grab the head element +const head = document.getElementByTagName('HEAD') + +// start off in light mode +let hasDarkCSS = false + +function toggleLight() { + if (!hasDarkCSS) return + head[0].removeChild(head[0].lastChild) + hasDarkCSS = !hasDarkCSS +} + +function toggleDark() { + if (hasDarkCSS) return + const link = document.createElement('link') + link.rel = 'stylesheet' + link.type = 'text/css' + link.href = 'styles/darkreader.css' + head[0].appendChild(link) + hasDarkCSS = !hasDarkCSS +} + +Please note that the generated CSS file should be used as a TEMPLATE, unless the site's color scheme is very simple, but it is very handy as it can generate dark versions of your project websites that are a great baseline to work off of.