From 3b69c565a3e34ef4aaefffb79cec8bfe4765d841 Mon Sep 17 00:00:00 2001 From: Jonah Aragon Date: Sat, 16 Mar 2024 15:24:18 +0000 Subject: [PATCH] Randomize DNS table order (#2438) Signed-off-by: Daniel Gray --- config/mkdocs-common.yml | 1 + docs/dns.md | 2 + theme/assets/javascripts/randomize-element.js | 65 +++++++++++++++++++ theme/main.html | 9 ++- 4 files changed, 74 insertions(+), 3 deletions(-) create mode 100644 theme/assets/javascripts/randomize-element.js diff --git a/config/mkdocs-common.yml b/config/mkdocs-common.yml index 00c60a46..84f68846 100644 --- a/config/mkdocs-common.yml +++ b/config/mkdocs-common.yml @@ -96,6 +96,7 @@ extra_css: - assets/stylesheets/extra.css?v=3.17.0 extra_javascript: - assets/javascripts/mathjax.js + - assets/javascripts/randomize-element.js watch: - ../theme diff --git a/docs/dns.md b/docs/dns.md index 3c4bcc2c..d93c8f07 100644 --- a/docs/dns.md +++ b/docs/dns.md @@ -3,6 +3,8 @@ title: "DNS Resolvers" icon: material/dns description: These are some encrypted DNS providers we recommend switching to, to replace your ISP's default configuration. cover: dns.webp +global: + - [randomize-element, "table tbody"] --- Encrypted DNS with third-party servers should only be used to get around basic [DNS blocking](https://en.wikipedia.org/wiki/DNS_blocking) when you can be sure there won't be any consequences. Encrypted DNS will not help you hide any of your browsing activity. diff --git a/theme/assets/javascripts/randomize-element.js b/theme/assets/javascripts/randomize-element.js new file mode 100644 index 00000000..44b25968 --- /dev/null +++ b/theme/assets/javascripts/randomize-element.js @@ -0,0 +1,65 @@ +/** + * @overview Randomizes the order of an HTML element's children. + * @author Jonah Aragon + * @license + * Copyright (c) 2024 Jonah Aragon + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +// Fetch global data from meta tag +let globalData = document.querySelector("#global-data"); + +if (globalData.dataset.randomizeElement) { + // Get elements to be randomized from meta tag in HTML + let randomizeElement = globalData.dataset.randomizeElement; + console.log("Randomizing child elements of " + randomizeElement); + + // Get all elements to be randomized + let randomizeChildren = document.querySelectorAll(randomizeElement); + let randomizeArray = Array.from(randomizeChildren); + + // Handle multiple elements to be randomized + for (const element of randomizeArray) { + let selector = " > *"; + if (globalData.dataset.randomizeElementSelector) { + selector = globalData.dataset.randomizeElementSelector + } + + // Select all direct children of element + let children = element.querySelectorAll(randomizeElement + selector); + + // Randomize rows (simple, probably not efficient) + let randomChildren = Array.from(children) + .map(value => ({ value, sort: Math.random() })) + .sort((a, b) => a.sort - b.sort) + .map(({ value }) => value); + + // Replace each element with randomly selected element + for (let i = 0; i < children.length; i++) { + let child = randomChildren[i].cloneNode(true); + child.classList.add("randomized"); + let parent = children[i].parentNode; + parent.insertBefore(child, children[i]); + children[i].remove(); + } + + } + +} diff --git a/theme/main.html b/theme/main.html index 1b111782..45d8d886 100644 --- a/theme/main.html +++ b/theme/main.html @@ -54,6 +54,9 @@ {% endif %} + {% if page %} + + {% endif %} {% endblock %} {% block htmltitle %} {% if page.meta and page.meta.meta_title and config.theme.language == "en" %} @@ -68,19 +71,19 @@ {% endblock %} {% block announce %}{% if config.extra.offline %} You're viewing an offline copy of Privacy Guides built on {{ build_date_utc }}. - + Visit privacyguides.org for the latest version. {% elif config.extra.context == "deploy-preview" %} You're viewing an unreviewed preview of Privacy Guides built on {{ build_date_utc }}. These previews are user-submitted and may not necessarily reflect the opinion of the site. - + Visit privacyguides.org for current advice. {% elif config.extra.context == "branch-deploy" %} You're viewing a staging branch of Privacy Guides built on {{ build_date_utc }}. The information on this page may be incomplete or otherwise not yet meet our editorial release standards. - + Visit privacyguides.org for current advice. {% else %}{% endif %}{% endblock %}