BlueSky Correct Terminology

Ensures BlueSky is using the correct terminology by replacing all instances of "post" with "skeet".

  1. // ==UserScript==
  2. // @name BlueSky Correct Terminology
  3. // @description Ensures BlueSky is using the correct terminology by replacing all instances of "post" with "skeet".
  4. // @namespace vivelin.net
  5. // @match https://bsky.app/*
  6. // @grant none
  7. // @version 1.0.7
  8. // @author Vivelin
  9. // @license MIT
  10. // ==/UserScript==
  11. (function () {
  12. "use strict";
  13.  
  14. /**
  15. * An object containing an array of RegExp patterns and string replacements for each language.
  16. */
  17. const allReplacements = {
  18. en: [
  19. { pattern: /\bPost(s)?\b/g, replacement: "Skeet$1" },
  20. { pattern: /\b([Rr]e)?post(s|ed)?\b/g, replacement: "$1skeet$2" },
  21. ],
  22. };
  23.  
  24. /**
  25. * Controls whether user-generated content should be processed (true) or left alone (false, default).
  26. */
  27. const shouldReplaceSkeetContent = false;
  28.  
  29. /**
  30. * Replaces the string, if necessary.
  31. * @param {string} text The original text to replace.
  32. * @param replacements An array of objects with the RegExp pattern and string replacement.
  33. * @returns {string} The replaced text.
  34. */
  35. function replaceText(text, replacements) {
  36. if (!text) return text;
  37.  
  38. for (const replacement of replacements) {
  39. if (text.match(replacement.pattern)) {
  40. text = text.replaceAll(
  41. replacement.pattern,
  42. replacement.replacement,
  43. );
  44. }
  45. }
  46.  
  47. return text;
  48. }
  49.  
  50. /**
  51. * Recursively processes and replaces all instances of text.
  52. * @param {Node} node The node to process.
  53. * @returns {void}
  54. */
  55. function processNode(node, replacements) {
  56. node = node || document.body;
  57.  
  58. if (node instanceof Text) {
  59. node.data = replaceText(node.data, replacements);
  60. } else if (node instanceof HTMLElement) {
  61. if (
  62. node.isContentEditable ||
  63. (!shouldReplaceSkeetContent &&
  64. (node.dataset.wordWrap === "1" ||
  65. node.dataset.testid === "profileHeaderDisplayName" ||
  66. node.ariaLabel === "Expand alt text" ||
  67. (node instanceof HTMLAnchorElement &&
  68. node.href &&
  69. node.href.match(/\/profile\//))))
  70. ) {
  71. return;
  72. }
  73.  
  74. for (const child of node.childNodes) {
  75. processNode(child, replacements);
  76. }
  77. }
  78. }
  79.  
  80. function observeCallback(_mutationList, _observer) {
  81. const lang = document.getElementsByTagName("html")[0].lang || "en";
  82. const replacements = allReplacements[lang];
  83. if (replacements) {
  84. processNode(document.body, replacements);
  85. }
  86. }
  87.  
  88. const observer = new MutationObserver(observeCallback);
  89. observer.observe(document.body, { childList: true, subtree: true });
  90. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址