Remove User ID from Stack Overflow Share URLs

Removes the User ID from the URL displayed by the "Share" button for questions and answers on Stack Overflow and related sites. For a description of why the User ID was added, see https://meta.stackoverflow.com/q/277769

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

/* eslint-disable max-len */
// ==UserScript==
// @name        Remove User ID from Stack Overflow Share URLs
// @namespace   https://kevinlocke.name/userscripts
// @description Removes the User ID from the URL displayed by the "Share" button for questions and answers on Stack Overflow and related sites.  For a description of why the User ID was added, see https://meta.stackoverflow.com/q/277769
// @match       https://*.askubuntu.com/*
// @match       https://*.mathoverflow.net/*
// @match       https://*.serverfault.com/*
// @match       https://*.stackapps.com/*
// @match       https://*.stackexchange.com/*
// @match       https://*.stackoverflow.com/*
// @match       https://*.superuser.com/*
// @version     1.0.1
// @license     MIT
// @grant       none
// @supportURL https://github.com/kevinoid/stackoverflow-share-remove-user-id
// ==/UserScript==
/* eslint-enable max-len */

// Note: Domain list from https://stackexchange.com/sites?view=list

'use strict';

// Amount of information to log to the console.  Lower = more.
const logLevel = 3;

// Simple logging framework
function notLogged() {}
const log = {
  /* eslint-disable no-console */
  error: logLevel < 5 ? console.error : notLogged,
  warn: logLevel < 4 ? console.warn : notLogged,
  info: logLevel < 3 ? console.info : notLogged,
  log: logLevel < 2 ? console.log : notLogged,
  debug: logLevel < 1 ? (console.debug || console.log) : notLogged
  /* eslint-enable no-console */
};

function forEach(arrayLike, callback, thisArg) {
  Array.prototype.forEach.call(arrayLike, callback, thisArg);
}

/** Removes the User ID from the URL displayed in response to clicking a
 * "Share" link.
 */
function removeUserIDOnClick(evt) {
  const {classList} = evt.target;
  if (!classList.contains('js-share-link')
      && !classList.contains('short-link')) {
    // click was not on "Share" link
    log.debug('Ignoring click not on .js-share-link or .short-link.');
    return;
  }

  const inputs = evt.target.parentNode.getElementsByTagName('input');
  if (inputs.length === 0) {
    log.warn('Could not find "Share" URL input element.');
    return;
  }

  forEach(inputs, (input) => {
    // Only change URLs with known formats to avoid breaking other URL formats
    const oldUrl = input.value;
    const newUrl
      = oldUrl.replace(/^(https?:\/\/[^/]*\/[aq]\/[0-9]+)\/[0-9]+$/, '$1');
    if (newUrl === oldUrl) {
      if (/^https?:\/\/[^/]*\/[aq]\/[0-9]+$/.test(oldUrl)) {
        log.debug(`Ignoring "Share" URL without User ID: ${oldUrl}`);
      } else {
        log.warn(`Ignoring unrecognized "Share" URL: ${oldUrl}`);
      }

      return;
    }

    log.debug(`Changed "Share" URL from ${oldUrl} to ${newUrl}`);
    input.value = newUrl;

    // Changing the value clears the selection.  Select the URL text.
    input.setSelectionRange(0, newUrl.length);
  });
}

// Wait until load event to register click event listener so that it is
// registered (and therefore runs) after the Stack Overflow click listener.
window.addEventListener(
  'load',
  () => document.addEventListener('click', removeUserIDOnClick, false),
  false
);