From 0d8f5008d96516e446e3e26871d46c6733f87711 Mon Sep 17 00:00:00 2001 From: Fredrik Bakke Date: Wed, 28 Feb 2024 15:05:31 +0100 Subject: [PATCH 1/7] self-host goatcounter script --- theme/index.hbs | 2 +- website/js/goat.js | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 website/js/goat.js diff --git a/theme/index.hbs b/theme/index.hbs index fb365846a4..dd078f1e22 100644 --- a/theme/index.hbs +++ b/theme/index.hbs @@ -333,7 +333,7 @@ - + diff --git a/website/js/goat.js b/website/js/goat.js new file mode 100644 index 0000000000..cabb3cdf10 --- /dev/null +++ b/website/js/goat.js @@ -0,0 +1 @@ +!function(){"use strict";window.goatcounter&&window.goatcounter.vars?window.goatcounter=window.goatcounter.vars:window.goatcounter=window.goatcounter||{};var t=document.querySelector("script[data-goatcounter]");if(t&&t.dataset.goatcounterSettings){try{var e=JSON.parse(t.dataset.goatcounterSettings)}catch(t){console.error("invalid JSON in data-goatcounter-settings: "+t)}for(var n in e)["no_onload","no_events","allow_local","allow_frame","path","title","referrer","event"].indexOf(n)>-1&&(window.goatcounter[n]=e[n])}var o=encodeURIComponent,r=function(t){return null==t||"function"==typeof t},a=function(){var t=window,e=document;return t.callPhantom||t._phantom||t.phantom?150:t.__nightmare?151:e.__selenium_unwrapped||e.__webdriver_evaluate||e.__driver_evaluate?152:navigator.webdriver?153:0},i=function(t){console&&"warn"in console&&console.warn("goatcounter: "+t)},c=function(){var t=document.querySelector("script[data-goatcounter]");return t&&t.dataset.goatcounter?t.dataset.goatcounter:goatcounter.endpoint||window.counter},u=function(){var t=location,e=document.querySelector('link[rel="canonical"][href]');if(e){var n=document.createElement("a");n.href=e.href,n.hostname.replace(/^www\./,"")===location.hostname.replace(/^www\./,"")&&(t=n)}return t.pathname+t.search||"/"},l=function(t){null===document.body?document.addEventListener("DOMContentLoaded",(function(){t()}),!1):t()};goatcounter.filter=function(){return"visibilityState"in document&&"prerender"===document.visibilityState?"visibilityState":goatcounter.allow_frame||location===parent.location?!goatcounter.allow_local&&location.hostname.match(/(localhost$|^127\.|^10\.|^172\.(1[6-9]|2[0-9]|3[0-1])\.|^192\.168\.|^0\.0\.0\.0$)/)?"localhost":goatcounter.allow_local||"file:"!==location.protocol?!(!localStorage||"t"!==localStorage.getItem("skipgc"))&&"disabled with #toggle-goatcounter":"localfile":"frame"},window.goatcounter.url=function(t){var e=function(t){var e,n,o,i={p:void 0===t.path?goatcounter.path:t.path,r:void 0===t.referrer?goatcounter.referrer:t.referrer,t:void 0===t.title?goatcounter.title:t.title,e:!(!t.event&&!goatcounter.event),s:[window.screen.width,window.screen.height,window.devicePixelRatio||1],b:a(),q:location.search};return"function"==typeof i.r&&(e=i.r),"function"==typeof i.t&&(o=i.t),"function"==typeof i.p&&(n=i.p),r(i.r)&&(i.r=document.referrer),r(i.t)&&(i.t=document.title),r(i.p)&&(i.p=u()),e&&(i.r=e(i.r)),o&&(i.t=o(i.t)),n&&(i.p=n(i.p)),i}(t||{});if(null!==e.p){e.rnd=Math.random().toString(36).substr(2,5);var n=c();return n?n+function(t){var e=[];for(var n in t)""!==t[n]&&null!==t[n]&&void 0!==t[n]&&!1!==t[n]&&e.push(o(n)+"="+o(t[n]));return"?"+e.join("&")}(e):i("no endpoint found")}},window.goatcounter.count=function(t){var e=goatcounter.filter();if(e)return i("not counting because of: "+e);var n=goatcounter.url(t);if(!n)return i("not counting because path callback returned null");navigator.sendBeacon(n)},window.goatcounter.get_query=function(t){for(var e=location.search.substr(1).split("&"),n=0;n Date: Wed, 28 Feb 2024 15:20:35 +0100 Subject: [PATCH 2/7] unminify --- website/js/goat.js | 237 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 236 insertions(+), 1 deletion(-) diff --git a/website/js/goat.js b/website/js/goat.js index cabb3cdf10..94c4760dee 100644 --- a/website/js/goat.js +++ b/website/js/goat.js @@ -1 +1,236 @@ -!function(){"use strict";window.goatcounter&&window.goatcounter.vars?window.goatcounter=window.goatcounter.vars:window.goatcounter=window.goatcounter||{};var t=document.querySelector("script[data-goatcounter]");if(t&&t.dataset.goatcounterSettings){try{var e=JSON.parse(t.dataset.goatcounterSettings)}catch(t){console.error("invalid JSON in data-goatcounter-settings: "+t)}for(var n in e)["no_onload","no_events","allow_local","allow_frame","path","title","referrer","event"].indexOf(n)>-1&&(window.goatcounter[n]=e[n])}var o=encodeURIComponent,r=function(t){return null==t||"function"==typeof t},a=function(){var t=window,e=document;return t.callPhantom||t._phantom||t.phantom?150:t.__nightmare?151:e.__selenium_unwrapped||e.__webdriver_evaluate||e.__driver_evaluate?152:navigator.webdriver?153:0},i=function(t){console&&"warn"in console&&console.warn("goatcounter: "+t)},c=function(){var t=document.querySelector("script[data-goatcounter]");return t&&t.dataset.goatcounter?t.dataset.goatcounter:goatcounter.endpoint||window.counter},u=function(){var t=location,e=document.querySelector('link[rel="canonical"][href]');if(e){var n=document.createElement("a");n.href=e.href,n.hostname.replace(/^www\./,"")===location.hostname.replace(/^www\./,"")&&(t=n)}return t.pathname+t.search||"/"},l=function(t){null===document.body?document.addEventListener("DOMContentLoaded",(function(){t()}),!1):t()};goatcounter.filter=function(){return"visibilityState"in document&&"prerender"===document.visibilityState?"visibilityState":goatcounter.allow_frame||location===parent.location?!goatcounter.allow_local&&location.hostname.match(/(localhost$|^127\.|^10\.|^172\.(1[6-9]|2[0-9]|3[0-1])\.|^192\.168\.|^0\.0\.0\.0$)/)?"localhost":goatcounter.allow_local||"file:"!==location.protocol?!(!localStorage||"t"!==localStorage.getItem("skipgc"))&&"disabled with #toggle-goatcounter":"localfile":"frame"},window.goatcounter.url=function(t){var e=function(t){var e,n,o,i={p:void 0===t.path?goatcounter.path:t.path,r:void 0===t.referrer?goatcounter.referrer:t.referrer,t:void 0===t.title?goatcounter.title:t.title,e:!(!t.event&&!goatcounter.event),s:[window.screen.width,window.screen.height,window.devicePixelRatio||1],b:a(),q:location.search};return"function"==typeof i.r&&(e=i.r),"function"==typeof i.t&&(o=i.t),"function"==typeof i.p&&(n=i.p),r(i.r)&&(i.r=document.referrer),r(i.t)&&(i.t=document.title),r(i.p)&&(i.p=u()),e&&(i.r=e(i.r)),o&&(i.t=o(i.t)),n&&(i.p=n(i.p)),i}(t||{});if(null!==e.p){e.rnd=Math.random().toString(36).substr(2,5);var n=c();return n?n+function(t){var e=[];for(var n in t)""!==t[n]&&null!==t[n]&&void 0!==t[n]&&!1!==t[n]&&e.push(o(n)+"="+o(t[n]));return"?"+e.join("&")}(e):i("no endpoint found")}},window.goatcounter.count=function(t){var e=goatcounter.filter();if(e)return i("not counting because of: "+e);var n=goatcounter.url(t);if(!n)return i("not counting because path callback returned null");navigator.sendBeacon(n)},window.goatcounter.get_query=function(t){for(var e=location.search.substr(1).split("&"),n=0;n -1 && (window.goatcounter[n] = e[n]); + } + var o = encodeURIComponent, + r = function (t) { + return null == t || 'function' == typeof t; + }, + a = function () { + var t = window, + e = document; + return t.callPhantom || t._phantom || t.phantom + ? 150 + : t.__nightmare + ? 151 + : e.__selenium_unwrapped || + e.__webdriver_evaluate || + e.__driver_evaluate + ? 152 + : navigator.webdriver + ? 153 + : 0; + }, + i = function (t) { + console && 'warn' in console && console.warn('goatcounter: ' + t); + }, + c = function () { + var t = document.querySelector('script[data-goatcounter]'); + return t && t.dataset.goatcounter + ? t.dataset.goatcounter + : goatcounter.endpoint || window.counter; + }, + u = function () { + var t = location, + e = document.querySelector('link[rel="canonical"][href]'); + if (e) { + var n = document.createElement('a'); + (n.href = e.href), + n.hostname.replace(/^www\./, '') === + location.hostname.replace(/^www\./, '') && (t = n); + } + return t.pathname + t.search || '/'; + }, + l = function (t) { + null === document.body + ? document.addEventListener( + 'DOMContentLoaded', + function () { + t(); + }, + !1 + ) + : t(); + }; + (goatcounter.filter = function () { + return 'visibilityState' in document && + 'prerender' === document.visibilityState + ? 'visibilityState' + : goatcounter.allow_frame || location === parent.location + ? !goatcounter.allow_local && + location.hostname.match( + /(localhost$|^127\.|^10\.|^172\.(1[6-9]|2[0-9]|3[0-1])\.|^192\.168\.|^0\.0\.0\.0$)/ + ) + ? 'localhost' + : goatcounter.allow_local || 'file:' !== location.protocol + ? !(!localStorage || 't' !== localStorage.getItem('skipgc')) && + 'disabled with #toggle-goatcounter' + : 'localfile' + : 'frame'; + }), + (window.goatcounter.url = function (t) { + var e = (function (t) { + var e, + n, + o, + i = { + p: void 0 === t.path ? goatcounter.path : t.path, + r: void 0 === t.referrer ? goatcounter.referrer : t.referrer, + t: void 0 === t.title ? goatcounter.title : t.title, + e: !(!t.event && !goatcounter.event), + s: [ + window.screen.width, + window.screen.height, + window.devicePixelRatio || 1, + ], + b: a(), + q: location.search, + }; + return ( + 'function' == typeof i.r && (e = i.r), + 'function' == typeof i.t && (o = i.t), + 'function' == typeof i.p && (n = i.p), + r(i.r) && (i.r = document.referrer), + r(i.t) && (i.t = document.title), + r(i.p) && (i.p = u()), + e && (i.r = e(i.r)), + o && (i.t = o(i.t)), + n && (i.p = n(i.p)), + i + ); + })(t || {}); + if (null !== e.p) { + e.rnd = Math.random().toString(36).substr(2, 5); + var n = c(); + return n + ? n + + (function (t) { + var e = []; + for (var n in t) + '' !== t[n] && + null !== t[n] && + void 0 !== t[n] && + !1 !== t[n] && + e.push(o(n) + '=' + o(t[n])); + return '?' + e.join('&'); + })(e) + : i('no endpoint found'); + } + }), + (window.goatcounter.count = function (t) { + var e = goatcounter.filter(); + if (e) return i('not counting because of: ' + e); + var n = goatcounter.url(t); + if (!n) return i('not counting because path callback returned null'); + navigator.sendBeacon(n); + }), + (window.goatcounter.get_query = function (t) { + for ( + var e = location.search.substr(1).split('&'), n = 0; + n < e.length; + n++ + ) + if (0 === e[n].toLowerCase().indexOf(t.toLowerCase() + '=')) + return e[n].substr(t.length + 1); + }), + (window.goatcounter.bind_events = function () { + if (document.querySelectorAll) { + Array.prototype.slice + .call(document.querySelectorAll('*[data-goatcounter-click]')) + .forEach(function (t) { + if (!t.dataset.goatcounterBound) { + var e = (function (t) { + return function () { + goatcounter.count({ + event: !0, + path: t.dataset.goatcounterClick || t.name || t.id || '', + title: + t.dataset.goatcounterTitle || + t.title || + (t.innerHTML || '').substr(0, 200) || + '', + referrer: + t.dataset.goatcounterReferrer || + t.dataset.goatcounterReferral || + '', + }); + }; + })(t); + t.addEventListener('click', e, !1), + t.addEventListener('auxclick', e, !1), + (t.dataset.goatcounterBound = 'true'); + } + }); + } + }), + (window.goatcounter.visit_count = function (t) { + l(function () { + ((t = t || {}).type = t.type || 'html'), + (t.append = t.append || 'body'), + (t.path = t.path || u()), + (t.attr = t.attr || { + width: '200', + height: t.no_branding ? '60' : '80', + }), + (t.attr.src = c() + 'er/' + o(t.path) + '.' + o(t.type) + '?'), + t.no_branding && (t.attr.src += '&no_branding=1'), + t.style && (t.attr.src += '&style=' + o(t.style)), + t.start && (t.attr.src += '&start=' + o(t.start)), + t.end && (t.attr.src += '&end=' + o(t.end)); + var e = { png: 'img', svg: 'img', html: 'iframe' }[t.type]; + if (!e) return i('visit_count: unknown type: ' + t.type); + 'html' === t.type && + ((t.attr.frameborder = '0'), (t.attr.scrolling = 'no')); + var n = document.createElement(e); + for (var r in t.attr) n.setAttribute(r, t.attr[r]); + var a = document.querySelector(t.append); + if (!a) return i('visit_count: append not found: ' + t.append); + a.appendChild(n); + }); + }), + '#toggle-goatcounter' === location.hash && + ('t' === localStorage.getItem('skipgc') + ? (localStorage.removeItem('skipgc', 't'), + alert('GoatCounter tracking is now ENABLED in this browser.')) + : (localStorage.setItem('skipgc', 't'), + alert( + 'GoatCounter tracking is now DISABLED in this browser until ' + + location + + ' is loaded again.' + ))), + goatcounter.no_onload || + l(function () { + if ( + 'visibilityState' in document && + 'visible' !== document.visibilityState + ) { + var t = function (e) { + 'visible' === document.visibilityState && + (document.removeEventListener('visibilitychange', t), + goatcounter.count()); + }; + document.addEventListener('visibilitychange', t); + } else goatcounter.count(); + goatcounter.no_events || goatcounter.bind_events(); + }); +})(); From cd3fd3d7d2303f6f469427a7f439b537e9b18ca6 Mon Sep 17 00:00:00 2001 From: Fredrik Bakke Date: Fri, 1 Mar 2024 16:06:27 +0100 Subject: [PATCH 3/7] use original goatcounter script --- website/js/goat.js | 476 +++++++++++++++++++++++---------------------- 1 file changed, 247 insertions(+), 229 deletions(-) diff --git a/website/js/goat.js b/website/js/goat.js index 94c4760dee..3c8868d293 100644 --- a/website/js/goat.js +++ b/website/js/goat.js @@ -1,236 +1,254 @@ -!(function () { +// GoatCounter: https://www.goatcounter.com +// This file is released under the ISC license: https://opensource.org/licenses/ISC +; (function () { 'use strict'; - window.goatcounter && window.goatcounter.vars - ? (window.goatcounter = window.goatcounter.vars) - : (window.goatcounter = window.goatcounter || {}); - var t = document.querySelector('script[data-goatcounter]'); - if (t && t.dataset.goatcounterSettings) { - try { - var e = JSON.parse(t.dataset.goatcounterSettings); - } catch (t) { - console.error('invalid JSON in data-goatcounter-settings: ' + t); + + if (window.goatcounter && window.goatcounter.vars) // Compatibility with very old version; do not use. + window.goatcounter = window.goatcounter.vars + else + window.goatcounter = window.goatcounter || {} + + // Load settings from data-goatcounter-settings. + var s = document.querySelector('script[data-goatcounter]') + if (s && s.dataset.goatcounterSettings) { + try { var set = JSON.parse(s.dataset.goatcounterSettings) } + catch (err) { console.error('invalid JSON in data-goatcounter-settings: ' + err) } + for (var k in set) + if (['no_onload', 'no_events', 'allow_local', 'allow_frame', 'path', 'title', 'referrer', 'event'].indexOf(k) > -1) + window.goatcounter[k] = set[k] + } + + var enc = encodeURIComponent + + // Get all data we're going to send off to the counter endpoint. + var get_data = function (vars) { + var data = { + p: (vars.path === undefined ? goatcounter.path : vars.path), + r: (vars.referrer === undefined ? goatcounter.referrer : vars.referrer), + t: (vars.title === undefined ? goatcounter.title : vars.title), + e: !!(vars.event || goatcounter.event), + s: [window.screen.width, window.screen.height, (window.devicePixelRatio || 1)], + b: is_bot(), + q: location.search, } - for (var n in e) - [ - 'no_onload', - 'no_events', - 'allow_local', - 'allow_frame', - 'path', - 'title', - 'referrer', - 'event', - ].indexOf(n) > -1 && (window.goatcounter[n] = e[n]); + + var rcb, pcb, tcb // Save callbacks to apply later. + if (typeof (data.r) === 'function') rcb = data.r + if (typeof (data.t) === 'function') tcb = data.t + if (typeof (data.p) === 'function') pcb = data.p + + if (is_empty(data.r)) data.r = document.referrer + if (is_empty(data.t)) data.t = document.title + if (is_empty(data.p)) data.p = get_path() + + if (rcb) data.r = rcb(data.r) + if (tcb) data.t = tcb(data.t) + if (pcb) data.p = pcb(data.p) + return data + } + + // Check if a value is "empty" for the purpose of get_data(). + var is_empty = function (v) { return v === null || v === undefined || typeof (v) === 'function' } + + // See if this looks like a bot; there is some additional filtering on the + // backend, but these properties can't be fetched from there. + var is_bot = function () { + // Headless browsers are probably a bot. + var w = window, d = document + if (w.callPhantom || w._phantom || w.phantom) + return 150 + if (w.__nightmare) + return 151 + if (d.__selenium_unwrapped || d.__webdriver_evaluate || d.__driver_evaluate) + return 152 + if (navigator.webdriver) + return 153 + return 0 + } + + // Object to urlencoded string, starting with a ?. + var urlencode = function (obj) { + var p = [] + for (var k in obj) + if (obj[k] !== '' && obj[k] !== null && obj[k] !== undefined && obj[k] !== false) + p.push(enc(k) + '=' + enc(obj[k])) + return '?' + p.join('&') + } + + // Show a warning in the console. + var warn = function (msg) { + if (console && 'warn' in console) + console.warn('goatcounter: ' + msg) + } + + // Get the endpoint to send requests to. + var get_endpoint = function () { + var s = document.querySelector('script[data-goatcounter]') + if (s && s.dataset.goatcounter) + return s.dataset.goatcounter + return (goatcounter.endpoint || window.counter) // counter is for compat; don't use. + } + + // Get current path. + var get_path = function () { + var loc = location, + c = document.querySelector('link[rel="canonical"][href]') + if (c) { // May be relative or point to different domain. + var a = document.createElement('a') + a.href = c.href + if (a.hostname.replace(/^www\./, '') === location.hostname.replace(/^www\./, '')) + loc = a + } + return (loc.pathname + loc.search) || '/' + } + + // Run function after DOM is loaded. + var on_load = function (f) { + if (document.body === null) + document.addEventListener('DOMContentLoaded', function () { f() }, false) + else + f() + } + + // Filter some requests that we (probably) don't want to count. + goatcounter.filter = function () { + if ('visibilityState' in document && document.visibilityState === 'prerender') + return 'visibilityState' + if (!goatcounter.allow_frame && location !== parent.location) + return 'frame' + if (!goatcounter.allow_local && location.hostname.match(/(localhost$|^127\.|^10\.|^172\.(1[6-9]|2[0-9]|3[0-1])\.|^192\.168\.|^0\.0\.0\.0$)/)) + return 'localhost' + if (!goatcounter.allow_local && location.protocol === 'file:') + return 'localfile' + if (localStorage && localStorage.getItem('skipgc') === 't') + return 'disabled with #toggle-goatcounter' + return false } - var o = encodeURIComponent, - r = function (t) { - return null == t || 'function' == typeof t; - }, - a = function () { - var t = window, - e = document; - return t.callPhantom || t._phantom || t.phantom - ? 150 - : t.__nightmare - ? 151 - : e.__selenium_unwrapped || - e.__webdriver_evaluate || - e.__driver_evaluate - ? 152 - : navigator.webdriver - ? 153 - : 0; - }, - i = function (t) { - console && 'warn' in console && console.warn('goatcounter: ' + t); - }, - c = function () { - var t = document.querySelector('script[data-goatcounter]'); - return t && t.dataset.goatcounter - ? t.dataset.goatcounter - : goatcounter.endpoint || window.counter; - }, - u = function () { - var t = location, - e = document.querySelector('link[rel="canonical"][href]'); - if (e) { - var n = document.createElement('a'); - (n.href = e.href), - n.hostname.replace(/^www\./, '') === - location.hostname.replace(/^www\./, '') && (t = n); + + // Get URL to send to GoatCounter. + window.goatcounter.url = function (vars) { + var data = get_data(vars || {}) + if (data.p === null) // null from user callback. + return + data.rnd = Math.random().toString(36).substr(2, 5) // Browsers don't always listen to Cache-Control. + + var endpoint = get_endpoint() + if (!endpoint) + return warn('no endpoint found') + + return endpoint + urlencode(data) + } + + // Count a hit. + window.goatcounter.count = function (vars) { + var f = goatcounter.filter() + if (f) + return warn('not counting because of: ' + f) + var url = goatcounter.url(vars) + if (!url) + return warn('not counting because path callback returned null') + navigator.sendBeacon(url) + } + + // Get a query parameter. + window.goatcounter.get_query = function (name) { + var s = location.search.substr(1).split('&') + for (var i = 0; i < s.length; i++) + if (s[i].toLowerCase().indexOf(name.toLowerCase() + '=') === 0) + return s[i].substr(name.length + 1) + } + + // Track click events. + window.goatcounter.bind_events = function () { + if (!document.querySelectorAll) // Just in case someone uses an ancient browser. + return + + var send = function (elem) { + return function () { + goatcounter.count({ + event: true, + path: (elem.dataset.goatcounterClick || elem.name || elem.id || ''), + title: (elem.dataset.goatcounterTitle || elem.title || (elem.innerHTML || '').substr(0, 200) || ''), + referrer: (elem.dataset.goatcounterReferrer || elem.dataset.goatcounterReferral || ''), + }) } - return t.pathname + t.search || '/'; - }, - l = function (t) { - null === document.body - ? document.addEventListener( - 'DOMContentLoaded', - function () { - t(); - }, - !1 - ) - : t(); - }; - (goatcounter.filter = function () { - return 'visibilityState' in document && - 'prerender' === document.visibilityState - ? 'visibilityState' - : goatcounter.allow_frame || location === parent.location - ? !goatcounter.allow_local && - location.hostname.match( - /(localhost$|^127\.|^10\.|^172\.(1[6-9]|2[0-9]|3[0-1])\.|^192\.168\.|^0\.0\.0\.0$)/ - ) - ? 'localhost' - : goatcounter.allow_local || 'file:' !== location.protocol - ? !(!localStorage || 't' !== localStorage.getItem('skipgc')) && - 'disabled with #toggle-goatcounter' - : 'localfile' - : 'frame'; - }), - (window.goatcounter.url = function (t) { - var e = (function (t) { - var e, - n, - o, - i = { - p: void 0 === t.path ? goatcounter.path : t.path, - r: void 0 === t.referrer ? goatcounter.referrer : t.referrer, - t: void 0 === t.title ? goatcounter.title : t.title, - e: !(!t.event && !goatcounter.event), - s: [ - window.screen.width, - window.screen.height, - window.devicePixelRatio || 1, - ], - b: a(), - q: location.search, - }; - return ( - 'function' == typeof i.r && (e = i.r), - 'function' == typeof i.t && (o = i.t), - 'function' == typeof i.p && (n = i.p), - r(i.r) && (i.r = document.referrer), - r(i.t) && (i.t = document.title), - r(i.p) && (i.p = u()), - e && (i.r = e(i.r)), - o && (i.t = o(i.t)), - n && (i.p = n(i.p)), - i - ); - })(t || {}); - if (null !== e.p) { - e.rnd = Math.random().toString(36).substr(2, 5); - var n = c(); - return n - ? n + - (function (t) { - var e = []; - for (var n in t) - '' !== t[n] && - null !== t[n] && - void 0 !== t[n] && - !1 !== t[n] && - e.push(o(n) + '=' + o(t[n])); - return '?' + e.join('&'); - })(e) - : i('no endpoint found'); + } + + Array.prototype.slice.call(document.querySelectorAll("*[data-goatcounter-click]")).forEach(function (elem) { + if (elem.dataset.goatcounterBound) + return + var f = send(elem) + elem.addEventListener('click', f, false) + elem.addEventListener('auxclick', f, false) // Middle click. + elem.dataset.goatcounterBound = 'true' + }) + } + + // Add a "visitor counter" frame or image. + window.goatcounter.visit_count = function (opt) { + on_load(function () { + opt = opt || {} + opt.type = opt.type || 'html' + opt.append = opt.append || 'body' + opt.path = opt.path || get_path() + opt.attr = opt.attr || { width: '200', height: (opt.no_branding ? '60' : '80') } + + opt.attr['src'] = get_endpoint() + 'er/' + enc(opt.path) + '.' + enc(opt.type) + '?' + if (opt.no_branding) opt.attr['src'] += '&no_branding=1' + if (opt.style) opt.attr['src'] += '&style=' + enc(opt.style) + if (opt.start) opt.attr['src'] += '&start=' + enc(opt.start) + if (opt.end) opt.attr['src'] += '&end=' + enc(opt.end) + + var tag = { png: 'img', svg: 'img', html: 'iframe' }[opt.type] + if (!tag) + return warn('visit_count: unknown type: ' + opt.type) + + if (opt.type === 'html') { + opt.attr['frameborder'] = '0' + opt.attr['scrolling'] = 'no' } - }), - (window.goatcounter.count = function (t) { - var e = goatcounter.filter(); - if (e) return i('not counting because of: ' + e); - var n = goatcounter.url(t); - if (!n) return i('not counting because path callback returned null'); - navigator.sendBeacon(n); - }), - (window.goatcounter.get_query = function (t) { - for ( - var e = location.search.substr(1).split('&'), n = 0; - n < e.length; - n++ - ) - if (0 === e[n].toLowerCase().indexOf(t.toLowerCase() + '=')) - return e[n].substr(t.length + 1); - }), - (window.goatcounter.bind_events = function () { - if (document.querySelectorAll) { - Array.prototype.slice - .call(document.querySelectorAll('*[data-goatcounter-click]')) - .forEach(function (t) { - if (!t.dataset.goatcounterBound) { - var e = (function (t) { - return function () { - goatcounter.count({ - event: !0, - path: t.dataset.goatcounterClick || t.name || t.id || '', - title: - t.dataset.goatcounterTitle || - t.title || - (t.innerHTML || '').substr(0, 200) || - '', - referrer: - t.dataset.goatcounterReferrer || - t.dataset.goatcounterReferral || - '', - }); - }; - })(t); - t.addEventListener('click', e, !1), - t.addEventListener('auxclick', e, !1), - (t.dataset.goatcounterBound = 'true'); - } - }); + + var d = document.createElement(tag) + for (var k in opt.attr) + d.setAttribute(k, opt.attr[k]) + + var p = document.querySelector(opt.append) + if (!p) + return warn('visit_count: append not found: ' + opt.append) + p.appendChild(d) + }) + } + + // Make it easy to skip your own views. + if (location.hash === '#toggle-goatcounter') { + if (localStorage.getItem('skipgc') === 't') { + localStorage.removeItem('skipgc', 't') + alert('GoatCounter tracking is now ENABLED in this browser.') + } + else { + localStorage.setItem('skipgc', 't') + alert('GoatCounter tracking is now DISABLED in this browser until ' + location + ' is loaded again.') + } + } + + if (!goatcounter.no_onload) + on_load(function () { + // 1. Page is visible, count request. + // 2. Page is not yet visible; wait until it switches to 'visible' and count. + // See #487 + if (!('visibilityState' in document) || document.visibilityState === 'visible') + goatcounter.count() + else { + var f = function (e) { + if (document.visibilityState !== 'visible') + return + document.removeEventListener('visibilitychange', f) + goatcounter.count() + } + document.addEventListener('visibilitychange', f) } - }), - (window.goatcounter.visit_count = function (t) { - l(function () { - ((t = t || {}).type = t.type || 'html'), - (t.append = t.append || 'body'), - (t.path = t.path || u()), - (t.attr = t.attr || { - width: '200', - height: t.no_branding ? '60' : '80', - }), - (t.attr.src = c() + 'er/' + o(t.path) + '.' + o(t.type) + '?'), - t.no_branding && (t.attr.src += '&no_branding=1'), - t.style && (t.attr.src += '&style=' + o(t.style)), - t.start && (t.attr.src += '&start=' + o(t.start)), - t.end && (t.attr.src += '&end=' + o(t.end)); - var e = { png: 'img', svg: 'img', html: 'iframe' }[t.type]; - if (!e) return i('visit_count: unknown type: ' + t.type); - 'html' === t.type && - ((t.attr.frameborder = '0'), (t.attr.scrolling = 'no')); - var n = document.createElement(e); - for (var r in t.attr) n.setAttribute(r, t.attr[r]); - var a = document.querySelector(t.append); - if (!a) return i('visit_count: append not found: ' + t.append); - a.appendChild(n); - }); - }), - '#toggle-goatcounter' === location.hash && - ('t' === localStorage.getItem('skipgc') - ? (localStorage.removeItem('skipgc', 't'), - alert('GoatCounter tracking is now ENABLED in this browser.')) - : (localStorage.setItem('skipgc', 't'), - alert( - 'GoatCounter tracking is now DISABLED in this browser until ' + - location + - ' is loaded again.' - ))), - goatcounter.no_onload || - l(function () { - if ( - 'visibilityState' in document && - 'visible' !== document.visibilityState - ) { - var t = function (e) { - 'visible' === document.visibilityState && - (document.removeEventListener('visibilitychange', t), - goatcounter.count()); - }; - document.addEventListener('visibilitychange', t); - } else goatcounter.count(); - goatcounter.no_events || goatcounter.bind_events(); - }); + + if (!goatcounter.no_events) + goatcounter.bind_events() + }) })(); From 15e03ba20f6570b3ad05f073acebd53ba891dc2b Mon Sep 17 00:00:00 2001 From: Fredrik Bakke Date: Fri, 1 Mar 2024 16:28:06 +0100 Subject: [PATCH 4/7] add redirection? --- book.toml | 2 ++ theme/index.hbs | 2 +- website/js/goat.js | 4 ++-- website/js/redirect.js | 5 +++++ 4 files changed, 10 insertions(+), 3 deletions(-) create mode 100644 website/js/redirect.js diff --git a/book.toml b/book.toml index 4ed9b191ee..7e592ce06c 100644 --- a/book.toml +++ b/book.toml @@ -68,6 +68,8 @@ additional-css = [ ] additional-js = [ "website/js/custom.js", + "website/js/goat.js", + "website/js/redirect.js", "theme/pagetoc.js" ] no-section-label = false diff --git a/theme/index.hbs b/theme/index.hbs index dd078f1e22..806003f3bd 100644 --- a/theme/index.hbs +++ b/theme/index.hbs @@ -333,7 +333,7 @@ - + diff --git a/website/js/goat.js b/website/js/goat.js index 3c8868d293..adf0849718 100644 --- a/website/js/goat.js +++ b/website/js/goat.js @@ -9,7 +9,7 @@ window.goatcounter = window.goatcounter || {} // Load settings from data-goatcounter-settings. - var s = document.querySelector('script[data-goatcounter]') + var s = document.querySelector('script[dgc]') if (s && s.dataset.goatcounterSettings) { try { var set = JSON.parse(s.dataset.goatcounterSettings) } catch (err) { console.error('invalid JSON in data-goatcounter-settings: ' + err) } @@ -83,7 +83,7 @@ // Get the endpoint to send requests to. var get_endpoint = function () { - var s = document.querySelector('script[data-goatcounter]') + var s = document.querySelector('script[dgc]') if (s && s.dataset.goatcounter) return s.dataset.goatcounter return (goatcounter.endpoint || window.counter) // counter is for compat; don't use. diff --git a/website/js/redirect.js b/website/js/redirect.js new file mode 100644 index 0000000000..bd7ee30144 --- /dev/null +++ b/website/js/redirect.js @@ -0,0 +1,5 @@ +document.addEventListener('DOMContentLoaded', (event) => { + if (window.location.href.includes("/redirect/goatcounter")) { + window.location.href = 'https://agda-unimath.goatcounter.com/count'; + } +}); From 03c8de076471510476559c42793eea84dffb2e61 Mon Sep 17 00:00:00 2001 From: Fredrik Bakke Date: Fri, 1 Mar 2024 17:05:01 +0100 Subject: [PATCH 5/7] remove redirection --- book.toml | 3 +- theme/index.hbs | 2 +- website/js/goat.js | 254 ------------------------------- website/js/goatcounter.js | 304 ++++++++++++++++++++++++++++++++++++++ website/js/redirect.js | 5 - 5 files changed, 306 insertions(+), 262 deletions(-) delete mode 100644 website/js/goat.js create mode 100644 website/js/goatcounter.js delete mode 100644 website/js/redirect.js diff --git a/book.toml b/book.toml index 7e592ce06c..c84cc630ff 100644 --- a/book.toml +++ b/book.toml @@ -68,8 +68,7 @@ additional-css = [ ] additional-js = [ "website/js/custom.js", - "website/js/goat.js", - "website/js/redirect.js", + "website/js/goatcounter.js", "theme/pagetoc.js" ] no-section-label = false diff --git a/theme/index.hbs b/theme/index.hbs index 806003f3bd..1b0f76ba20 100644 --- a/theme/index.hbs +++ b/theme/index.hbs @@ -333,7 +333,7 @@ - + diff --git a/website/js/goat.js b/website/js/goat.js deleted file mode 100644 index adf0849718..0000000000 --- a/website/js/goat.js +++ /dev/null @@ -1,254 +0,0 @@ -// GoatCounter: https://www.goatcounter.com -// This file is released under the ISC license: https://opensource.org/licenses/ISC -; (function () { - 'use strict'; - - if (window.goatcounter && window.goatcounter.vars) // Compatibility with very old version; do not use. - window.goatcounter = window.goatcounter.vars - else - window.goatcounter = window.goatcounter || {} - - // Load settings from data-goatcounter-settings. - var s = document.querySelector('script[dgc]') - if (s && s.dataset.goatcounterSettings) { - try { var set = JSON.parse(s.dataset.goatcounterSettings) } - catch (err) { console.error('invalid JSON in data-goatcounter-settings: ' + err) } - for (var k in set) - if (['no_onload', 'no_events', 'allow_local', 'allow_frame', 'path', 'title', 'referrer', 'event'].indexOf(k) > -1) - window.goatcounter[k] = set[k] - } - - var enc = encodeURIComponent - - // Get all data we're going to send off to the counter endpoint. - var get_data = function (vars) { - var data = { - p: (vars.path === undefined ? goatcounter.path : vars.path), - r: (vars.referrer === undefined ? goatcounter.referrer : vars.referrer), - t: (vars.title === undefined ? goatcounter.title : vars.title), - e: !!(vars.event || goatcounter.event), - s: [window.screen.width, window.screen.height, (window.devicePixelRatio || 1)], - b: is_bot(), - q: location.search, - } - - var rcb, pcb, tcb // Save callbacks to apply later. - if (typeof (data.r) === 'function') rcb = data.r - if (typeof (data.t) === 'function') tcb = data.t - if (typeof (data.p) === 'function') pcb = data.p - - if (is_empty(data.r)) data.r = document.referrer - if (is_empty(data.t)) data.t = document.title - if (is_empty(data.p)) data.p = get_path() - - if (rcb) data.r = rcb(data.r) - if (tcb) data.t = tcb(data.t) - if (pcb) data.p = pcb(data.p) - return data - } - - // Check if a value is "empty" for the purpose of get_data(). - var is_empty = function (v) { return v === null || v === undefined || typeof (v) === 'function' } - - // See if this looks like a bot; there is some additional filtering on the - // backend, but these properties can't be fetched from there. - var is_bot = function () { - // Headless browsers are probably a bot. - var w = window, d = document - if (w.callPhantom || w._phantom || w.phantom) - return 150 - if (w.__nightmare) - return 151 - if (d.__selenium_unwrapped || d.__webdriver_evaluate || d.__driver_evaluate) - return 152 - if (navigator.webdriver) - return 153 - return 0 - } - - // Object to urlencoded string, starting with a ?. - var urlencode = function (obj) { - var p = [] - for (var k in obj) - if (obj[k] !== '' && obj[k] !== null && obj[k] !== undefined && obj[k] !== false) - p.push(enc(k) + '=' + enc(obj[k])) - return '?' + p.join('&') - } - - // Show a warning in the console. - var warn = function (msg) { - if (console && 'warn' in console) - console.warn('goatcounter: ' + msg) - } - - // Get the endpoint to send requests to. - var get_endpoint = function () { - var s = document.querySelector('script[dgc]') - if (s && s.dataset.goatcounter) - return s.dataset.goatcounter - return (goatcounter.endpoint || window.counter) // counter is for compat; don't use. - } - - // Get current path. - var get_path = function () { - var loc = location, - c = document.querySelector('link[rel="canonical"][href]') - if (c) { // May be relative or point to different domain. - var a = document.createElement('a') - a.href = c.href - if (a.hostname.replace(/^www\./, '') === location.hostname.replace(/^www\./, '')) - loc = a - } - return (loc.pathname + loc.search) || '/' - } - - // Run function after DOM is loaded. - var on_load = function (f) { - if (document.body === null) - document.addEventListener('DOMContentLoaded', function () { f() }, false) - else - f() - } - - // Filter some requests that we (probably) don't want to count. - goatcounter.filter = function () { - if ('visibilityState' in document && document.visibilityState === 'prerender') - return 'visibilityState' - if (!goatcounter.allow_frame && location !== parent.location) - return 'frame' - if (!goatcounter.allow_local && location.hostname.match(/(localhost$|^127\.|^10\.|^172\.(1[6-9]|2[0-9]|3[0-1])\.|^192\.168\.|^0\.0\.0\.0$)/)) - return 'localhost' - if (!goatcounter.allow_local && location.protocol === 'file:') - return 'localfile' - if (localStorage && localStorage.getItem('skipgc') === 't') - return 'disabled with #toggle-goatcounter' - return false - } - - // Get URL to send to GoatCounter. - window.goatcounter.url = function (vars) { - var data = get_data(vars || {}) - if (data.p === null) // null from user callback. - return - data.rnd = Math.random().toString(36).substr(2, 5) // Browsers don't always listen to Cache-Control. - - var endpoint = get_endpoint() - if (!endpoint) - return warn('no endpoint found') - - return endpoint + urlencode(data) - } - - // Count a hit. - window.goatcounter.count = function (vars) { - var f = goatcounter.filter() - if (f) - return warn('not counting because of: ' + f) - var url = goatcounter.url(vars) - if (!url) - return warn('not counting because path callback returned null') - navigator.sendBeacon(url) - } - - // Get a query parameter. - window.goatcounter.get_query = function (name) { - var s = location.search.substr(1).split('&') - for (var i = 0; i < s.length; i++) - if (s[i].toLowerCase().indexOf(name.toLowerCase() + '=') === 0) - return s[i].substr(name.length + 1) - } - - // Track click events. - window.goatcounter.bind_events = function () { - if (!document.querySelectorAll) // Just in case someone uses an ancient browser. - return - - var send = function (elem) { - return function () { - goatcounter.count({ - event: true, - path: (elem.dataset.goatcounterClick || elem.name || elem.id || ''), - title: (elem.dataset.goatcounterTitle || elem.title || (elem.innerHTML || '').substr(0, 200) || ''), - referrer: (elem.dataset.goatcounterReferrer || elem.dataset.goatcounterReferral || ''), - }) - } - } - - Array.prototype.slice.call(document.querySelectorAll("*[data-goatcounter-click]")).forEach(function (elem) { - if (elem.dataset.goatcounterBound) - return - var f = send(elem) - elem.addEventListener('click', f, false) - elem.addEventListener('auxclick', f, false) // Middle click. - elem.dataset.goatcounterBound = 'true' - }) - } - - // Add a "visitor counter" frame or image. - window.goatcounter.visit_count = function (opt) { - on_load(function () { - opt = opt || {} - opt.type = opt.type || 'html' - opt.append = opt.append || 'body' - opt.path = opt.path || get_path() - opt.attr = opt.attr || { width: '200', height: (opt.no_branding ? '60' : '80') } - - opt.attr['src'] = get_endpoint() + 'er/' + enc(opt.path) + '.' + enc(opt.type) + '?' - if (opt.no_branding) opt.attr['src'] += '&no_branding=1' - if (opt.style) opt.attr['src'] += '&style=' + enc(opt.style) - if (opt.start) opt.attr['src'] += '&start=' + enc(opt.start) - if (opt.end) opt.attr['src'] += '&end=' + enc(opt.end) - - var tag = { png: 'img', svg: 'img', html: 'iframe' }[opt.type] - if (!tag) - return warn('visit_count: unknown type: ' + opt.type) - - if (opt.type === 'html') { - opt.attr['frameborder'] = '0' - opt.attr['scrolling'] = 'no' - } - - var d = document.createElement(tag) - for (var k in opt.attr) - d.setAttribute(k, opt.attr[k]) - - var p = document.querySelector(opt.append) - if (!p) - return warn('visit_count: append not found: ' + opt.append) - p.appendChild(d) - }) - } - - // Make it easy to skip your own views. - if (location.hash === '#toggle-goatcounter') { - if (localStorage.getItem('skipgc') === 't') { - localStorage.removeItem('skipgc', 't') - alert('GoatCounter tracking is now ENABLED in this browser.') - } - else { - localStorage.setItem('skipgc', 't') - alert('GoatCounter tracking is now DISABLED in this browser until ' + location + ' is loaded again.') - } - } - - if (!goatcounter.no_onload) - on_load(function () { - // 1. Page is visible, count request. - // 2. Page is not yet visible; wait until it switches to 'visible' and count. - // See #487 - if (!('visibilityState' in document) || document.visibilityState === 'visible') - goatcounter.count() - else { - var f = function (e) { - if (document.visibilityState !== 'visible') - return - document.removeEventListener('visibilitychange', f) - goatcounter.count() - } - document.addEventListener('visibilitychange', f) - } - - if (!goatcounter.no_events) - goatcounter.bind_events() - }) -})(); diff --git a/website/js/goatcounter.js b/website/js/goatcounter.js new file mode 100644 index 0000000000..3be239c492 --- /dev/null +++ b/website/js/goatcounter.js @@ -0,0 +1,304 @@ +// GoatCounter: https://www.goatcounter.com +// This file is released under the ISC license: https://opensource.org/licenses/ISC +(function () { + 'use strict'; + + if (window.goatcounter && window.goatcounter.vars) + // Compatibility with very old version; do not use. + window.goatcounter = window.goatcounter.vars; + else window.goatcounter = window.goatcounter || {}; + + // Load settings from data-goatcounter-settings. + var s = document.querySelector('script[dgc]'); + if (s && s.dataset.goatcounterSettings) { + try { + var set = JSON.parse(s.dataset.goatcounterSettings); + } catch (err) { + console.error('invalid JSON in data-goatcounter-settings: ' + err); + } + for (var k in set) + if ( + [ + 'no_onload', + 'no_events', + 'allow_local', + 'allow_frame', + 'path', + 'title', + 'referrer', + 'event', + ].indexOf(k) > -1 + ) + window.goatcounter[k] = set[k]; + } + + var enc = encodeURIComponent; + + // Get all data we're going to send off to the counter endpoint. + var get_data = function (vars) { + var data = { + p: vars.path === undefined ? goatcounter.path : vars.path, + r: vars.referrer === undefined ? goatcounter.referrer : vars.referrer, + t: vars.title === undefined ? goatcounter.title : vars.title, + e: !!(vars.event || goatcounter.event), + s: [ + window.screen.width, + window.screen.height, + window.devicePixelRatio || 1, + ], + b: is_bot(), + q: location.search, + }; + + var rcb, pcb, tcb; // Save callbacks to apply later. + if (typeof data.r === 'function') rcb = data.r; + if (typeof data.t === 'function') tcb = data.t; + if (typeof data.p === 'function') pcb = data.p; + + if (is_empty(data.r)) data.r = document.referrer; + if (is_empty(data.t)) data.t = document.title; + if (is_empty(data.p)) data.p = get_path(); + + if (rcb) data.r = rcb(data.r); + if (tcb) data.t = tcb(data.t); + if (pcb) data.p = pcb(data.p); + return data; + }; + + // Check if a value is "empty" for the purpose of get_data(). + var is_empty = function (v) { + return v === null || v === undefined || typeof v === 'function'; + }; + + // See if this looks like a bot; there is some additional filtering on the + // backend, but these properties can't be fetched from there. + var is_bot = function () { + // Headless browsers are probably a bot. + var w = window, + d = document; + if (w.callPhantom || w._phantom || w.phantom) return 150; + if (w.__nightmare) return 151; + if (d.__selenium_unwrapped || d.__webdriver_evaluate || d.__driver_evaluate) + return 152; + if (navigator.webdriver) return 153; + return 0; + }; + + // Object to urlencoded string, starting with a ?. + var urlencode = function (obj) { + var p = []; + for (var k in obj) + if ( + obj[k] !== '' && + obj[k] !== null && + obj[k] !== undefined && + obj[k] !== false + ) + p.push(enc(k) + '=' + enc(obj[k])); + return '?' + p.join('&'); + }; + + // Show a warning in the console. + var warn = function (msg) { + if (console && 'warn' in console) console.warn('goatcounter: ' + msg); + }; + + // Get the endpoint to send requests to. + var get_endpoint = function () { + var s = document.querySelector('script[dgc]'); + if (s && s.dataset.goatcounter) return s.dataset.goatcounter; + return goatcounter.endpoint || window.counter; // counter is for compat; don't use. + }; + + // Get current path. + var get_path = function () { + var loc = location, + c = document.querySelector('link[rel="canonical"][href]'); + if (c) { + // May be relative or point to different domain. + var a = document.createElement('a'); + a.href = c.href; + if ( + a.hostname.replace(/^www\./, '') === + location.hostname.replace(/^www\./, '') + ) + loc = a; + } + return loc.pathname + loc.search || '/'; + }; + + // Run function after DOM is loaded. + var on_load = function (f) { + if (document.body === null) + document.addEventListener( + 'DOMContentLoaded', + function () { + f(); + }, + false + ); + else f(); + }; + + // Filter some requests that we (probably) don't want to count. + goatcounter.filter = function () { + if ( + 'visibilityState' in document && + document.visibilityState === 'prerender' + ) + return 'visibilityState'; + if (!goatcounter.allow_frame && location !== parent.location) + return 'frame'; + if ( + !goatcounter.allow_local && + location.hostname.match( + /(localhost$|^127\.|^10\.|^172\.(1[6-9]|2[0-9]|3[0-1])\.|^192\.168\.|^0\.0\.0\.0$)/ + ) + ) + return 'localhost'; + if (!goatcounter.allow_local && location.protocol === 'file:') + return 'localfile'; + if (localStorage && localStorage.getItem('skipgc') === 't') + return 'disabled with #toggle-goatcounter'; + return false; + }; + + // Get URL to send to GoatCounter. + window.goatcounter.url = function (vars) { + var data = get_data(vars || {}); + if (data.p === null) + // null from user callback. + return; + data.rnd = Math.random().toString(36).substr(2, 5); // Browsers don't always listen to Cache-Control. + + var endpoint = get_endpoint(); + if (!endpoint) return warn('no endpoint found'); + + return endpoint + urlencode(data); + }; + + // Count a hit. + window.goatcounter.count = function (vars) { + var f = goatcounter.filter(); + if (f) return warn('not counting because of: ' + f); + var url = goatcounter.url(vars); + if (!url) return warn('not counting because path callback returned null'); + navigator.sendBeacon(url); + }; + + // Get a query parameter. + window.goatcounter.get_query = function (name) { + var s = location.search.substr(1).split('&'); + for (var i = 0; i < s.length; i++) + if (s[i].toLowerCase().indexOf(name.toLowerCase() + '=') === 0) + return s[i].substr(name.length + 1); + }; + + // Track click events. + window.goatcounter.bind_events = function () { + if (!document.querySelectorAll) + // Just in case someone uses an ancient browser. + return; + + var send = function (elem) { + return function () { + goatcounter.count({ + event: true, + path: elem.dataset.goatcounterClick || elem.name || elem.id || '', + title: + elem.dataset.goatcounterTitle || + elem.title || + (elem.innerHTML || '').substr(0, 200) || + '', + referrer: + elem.dataset.goatcounterReferrer || + elem.dataset.goatcounterReferral || + '', + }); + }; + }; + + Array.prototype.slice + .call(document.querySelectorAll('*[data-goatcounter-click]')) + .forEach(function (elem) { + if (elem.dataset.goatcounterBound) return; + var f = send(elem); + elem.addEventListener('click', f, false); + elem.addEventListener('auxclick', f, false); // Middle click. + elem.dataset.goatcounterBound = 'true'; + }); + }; + + // Add a "visitor counter" frame or image. + window.goatcounter.visit_count = function (opt) { + on_load(function () { + opt = opt || {}; + opt.type = opt.type || 'html'; + opt.append = opt.append || 'body'; + opt.path = opt.path || get_path(); + opt.attr = opt.attr || { + width: '200', + height: opt.no_branding ? '60' : '80', + }; + + opt.attr['src'] = + get_endpoint() + 'er/' + enc(opt.path) + '.' + enc(opt.type) + '?'; + if (opt.no_branding) opt.attr['src'] += '&no_branding=1'; + if (opt.style) opt.attr['src'] += '&style=' + enc(opt.style); + if (opt.start) opt.attr['src'] += '&start=' + enc(opt.start); + if (opt.end) opt.attr['src'] += '&end=' + enc(opt.end); + + var tag = { png: 'img', svg: 'img', html: 'iframe' }[opt.type]; + if (!tag) return warn('visit_count: unknown type: ' + opt.type); + + if (opt.type === 'html') { + opt.attr['frameborder'] = '0'; + opt.attr['scrolling'] = 'no'; + } + + var d = document.createElement(tag); + for (var k in opt.attr) d.setAttribute(k, opt.attr[k]); + + var p = document.querySelector(opt.append); + if (!p) return warn('visit_count: append not found: ' + opt.append); + p.appendChild(d); + }); + }; + + // Make it easy to skip your own views. + if (location.hash === '#toggle-goatcounter') { + if (localStorage.getItem('skipgc') === 't') { + localStorage.removeItem('skipgc', 't'); + alert('GoatCounter tracking is now ENABLED in this browser.'); + } else { + localStorage.setItem('skipgc', 't'); + alert( + 'GoatCounter tracking is now DISABLED in this browser until ' + + location + + ' is loaded again.' + ); + } + } + + if (!goatcounter.no_onload) + on_load(function () { + // 1. Page is visible, count request. + // 2. Page is not yet visible; wait until it switches to 'visible' and count. + // See #487 + if ( + !('visibilityState' in document) || + document.visibilityState === 'visible' + ) + goatcounter.count(); + else { + var f = function (e) { + if (document.visibilityState !== 'visible') return; + document.removeEventListener('visibilitychange', f); + goatcounter.count(); + }; + document.addEventListener('visibilitychange', f); + } + + if (!goatcounter.no_events) goatcounter.bind_events(); + }); +})(); diff --git a/website/js/redirect.js b/website/js/redirect.js deleted file mode 100644 index bd7ee30144..0000000000 --- a/website/js/redirect.js +++ /dev/null @@ -1,5 +0,0 @@ -document.addEventListener('DOMContentLoaded', (event) => { - if (window.location.href.includes("/redirect/goatcounter")) { - window.location.href = 'https://agda-unimath.goatcounter.com/count'; - } -}); From 450842e9181351216a6209a41d80b5d118c1f587 Mon Sep 17 00:00:00 2001 From: Fredrik Bakke Date: Fri, 1 Mar 2024 17:07:41 +0100 Subject: [PATCH 6/7] `dgc` -> `data-goatcounter` --- theme/index.hbs | 2 +- website/js/goatcounter.js | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/theme/index.hbs b/theme/index.hbs index 1b0f76ba20..a7aa02309c 100644 --- a/theme/index.hbs +++ b/theme/index.hbs @@ -333,7 +333,7 @@ - + diff --git a/website/js/goatcounter.js b/website/js/goatcounter.js index 3be239c492..e7203fbf39 100644 --- a/website/js/goatcounter.js +++ b/website/js/goatcounter.js @@ -9,7 +9,7 @@ else window.goatcounter = window.goatcounter || {}; // Load settings from data-goatcounter-settings. - var s = document.querySelector('script[dgc]'); + var s = document.querySelector('script[data-goatcounter]'); if (s && s.dataset.goatcounterSettings) { try { var set = JSON.parse(s.dataset.goatcounterSettings); @@ -105,7 +105,7 @@ // Get the endpoint to send requests to. var get_endpoint = function () { - var s = document.querySelector('script[dgc]'); + var s = document.querySelector('script[data-goatcounter]'); if (s && s.dataset.goatcounter) return s.dataset.goatcounter; return goatcounter.endpoint || window.counter; // counter is for compat; don't use. }; @@ -274,8 +274,8 @@ localStorage.setItem('skipgc', 't'); alert( 'GoatCounter tracking is now DISABLED in this browser until ' + - location + - ' is loaded again.' + location + + ' is loaded again.' ); } } From 4b315843d5d3ad92417260ea4589b2a9c7711dfc Mon Sep 17 00:00:00 2001 From: Fredrik Bakke Date: Fri, 1 Mar 2024 17:16:46 +0100 Subject: [PATCH 7/7] pre-commit --- website/js/goatcounter.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/website/js/goatcounter.js b/website/js/goatcounter.js index e7203fbf39..b532245ea3 100644 --- a/website/js/goatcounter.js +++ b/website/js/goatcounter.js @@ -274,8 +274,8 @@ localStorage.setItem('skipgc', 't'); alert( 'GoatCounter tracking is now DISABLED in this browser until ' + - location + - ' is loaded again.' + location + + ' is loaded again.' ); } }